summaryrefslogtreecommitdiff
path: root/drivers/staging/rtl8188eu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/rtl8188eu')
-rw-r--r--drivers/staging/rtl8188eu/Kconfig27
-rw-r--r--drivers/staging/rtl8188eu/Makefile57
-rw-r--r--drivers/staging/rtl8188eu/TODO14
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_ap.c1762
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_cmd.c1275
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_debug.c181
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_efuse.c900
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_ieee80211.c1076
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_ioctl_set.c602
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_iol.c19
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_led.c484
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_mlme.c2063
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_mlme_ext.c5483
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_pwrctrl.c650
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_recv.c2054
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_rf.c58
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_security.c1537
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_sreset.c21
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_sta_mgt.c511
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_wlan_util.c1468
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_xmit.c2081
-rw-r--r--drivers/staging/rtl8188eu/hal/bb_cfg.c681
-rw-r--r--drivers/staging/rtl8188eu/hal/fw.c201
-rw-r--r--drivers/staging/rtl8188eu/hal/hal8188e_rate_adaptive.c761
-rw-r--r--drivers/staging/rtl8188eu/hal/hal_com.c285
-rw-r--r--drivers/staging/rtl8188eu/hal/hal_intf.c66
-rw-r--r--drivers/staging/rtl8188eu/hal/mac_cfg.c120
-rw-r--r--drivers/staging/rtl8188eu/hal/odm.c1101
-rw-r--r--drivers/staging/rtl8188eu/hal/odm_hwconfig.c400
-rw-r--r--drivers/staging/rtl8188eu/hal/odm_rtl8188e.c337
-rw-r--r--drivers/staging/rtl8188eu/hal/phy.c1334
-rw-r--r--drivers/staging/rtl8188eu/hal/pwrseq.c88
-rw-r--r--drivers/staging/rtl8188eu/hal/pwrseqcmd.c105
-rw-r--r--drivers/staging/rtl8188eu/hal/rf.c288
-rw-r--r--drivers/staging/rtl8188eu/hal/rf_cfg.c248
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c633
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_dm.c211
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c575
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c191
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188e_xmit.c57
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188eu_led.c55
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c95
-rw-r--r--drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c662
-rw-r--r--drivers/staging/rtl8188eu/hal/usb_halinit.c1992
-rw-r--r--drivers/staging/rtl8188eu/include/HalVerDef.h37
-rw-r--r--drivers/staging/rtl8188eu/include/basic_types.h134
-rw-r--r--drivers/staging/rtl8188eu/include/drv_types.h178
-rw-r--r--drivers/staging/rtl8188eu/include/fw.h44
-rw-r--r--drivers/staging/rtl8188eu/include/hal8188e_phy_cfg.h205
-rw-r--r--drivers/staging/rtl8188eu/include/hal8188e_phy_reg.h201
-rw-r--r--drivers/staging/rtl8188eu/include/hal8188e_rate_adaptive.h74
-rw-r--r--drivers/staging/rtl8188eu/include/hal_com.h151
-rw-r--r--drivers/staging/rtl8188eu/include/hal_intf.h224
-rw-r--r--drivers/staging/rtl8188eu/include/ieee80211.h777
-rw-r--r--drivers/staging/rtl8188eu/include/mlme_osdep.h21
-rw-r--r--drivers/staging/rtl8188eu/include/mon.h28
-rw-r--r--drivers/staging/rtl8188eu/include/odm.h1066
-rw-r--r--drivers/staging/rtl8188eu/include/odm_debug.h98
-rw-r--r--drivers/staging/rtl8188eu/include/odm_hwconfig.h101
-rw-r--r--drivers/staging/rtl8188eu/include/odm_precomp.h67
-rw-r--r--drivers/staging/rtl8188eu/include/odm_rtl8188e.h39
-rw-r--r--drivers/staging/rtl8188eu/include/odm_types.h24
-rw-r--r--drivers/staging/rtl8188eu/include/osdep_intf.h36
-rw-r--r--drivers/staging/rtl8188eu/include/osdep_service.h90
-rw-r--r--drivers/staging/rtl8188eu/include/phy.h26
-rw-r--r--drivers/staging/rtl8188eu/include/phydm_reg.h22
-rw-r--r--drivers/staging/rtl8188eu/include/phydm_regdefine11n.h53
-rw-r--r--drivers/staging/rtl8188eu/include/pwrseq.h245
-rw-r--r--drivers/staging/rtl8188eu/include/pwrseqcmd.h53
-rw-r--r--drivers/staging/rtl8188eu/include/recv_osdep.h28
-rw-r--r--drivers/staging/rtl8188eu/include/rf.h12
-rw-r--r--drivers/staging/rtl8188eu/include/rtl8188e_cmd.h70
-rw-r--r--drivers/staging/rtl8188eu/include/rtl8188e_dm.h45
-rw-r--r--drivers/staging/rtl8188eu/include/rtl8188e_hal.h374
-rw-r--r--drivers/staging/rtl8188eu/include/rtl8188e_recv.h53
-rw-r--r--drivers/staging/rtl8188eu/include/rtl8188e_spec.h1403
-rw-r--r--drivers/staging/rtl8188eu/include/rtl8188e_xmit.h160
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_android.h51
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_ap.h45
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_cmd.h384
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_debug.h132
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_eeprom.h114
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_efuse.h93
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_event.h81
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_ht.h26
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_ioctl.h87
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_ioctl_set.h29
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_iol.h14
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_led.h98
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_mlme.h359
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_mlme_ext.h717
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_pwrctrl.h245
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_recv.h264
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_rf.h134
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_security.h305
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_sreset.h30
-rw-r--r--drivers/staging/rtl8188eu/include/rtw_xmit.h358
-rw-r--r--drivers/staging/rtl8188eu/include/sta_info.h359
-rw-r--r--drivers/staging/rtl8188eu/include/usb_ops_linux.h58
-rw-r--r--drivers/staging/rtl8188eu/include/wifi.h689
-rw-r--r--drivers/staging/rtl8188eu/include/wlan_bssdef.h243
-rw-r--r--drivers/staging/rtl8188eu/include/xmit_osdep.h33
-rw-r--r--drivers/staging/rtl8188eu/os_dep/ioctl_linux.c3067
-rw-r--r--drivers/staging/rtl8188eu/os_dep/mlme_linux.c175
-rw-r--r--drivers/staging/rtl8188eu/os_dep/mon.c190
-rw-r--r--drivers/staging/rtl8188eu/os_dep/os_intfs.c747
-rw-r--r--drivers/staging/rtl8188eu/os_dep/osdep_service.c98
-rw-r--r--drivers/staging/rtl8188eu/os_dep/recv_linux.c145
-rw-r--r--drivers/staging/rtl8188eu/os_dep/rtw_android.c250
-rw-r--r--drivers/staging/rtl8188eu/os_dep/usb_intf.c516
-rw-r--r--drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c814
-rw-r--r--drivers/staging/rtl8188eu/os_dep/xmit_linux.c211
112 files changed, 50109 insertions, 0 deletions
diff --git a/drivers/staging/rtl8188eu/Kconfig b/drivers/staging/rtl8188eu/Kconfig
new file mode 100644
index 0000000..f2939fc
--- /dev/null
+++ b/drivers/staging/rtl8188eu/Kconfig
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0
+config R8188EU
+ depends on !KERNEL_3_14
+ tristate "Realtek RTL8188EU Wireless LAN NIC driver"
+ depends on m
+ depends on WLAN && USB && CFG80211
+ depends on m
+ depends on WIRELESS_EXT
+ depends on WEXT_PRIV
+ select LIB80211
+ select LIB80211_CRYPT_WEP
+ select LIB80211_CRYPT_CCMP
+ help
+ This option adds the Realtek RTL8188EU USB device such as TP-Link TL-WN725N.
+ If built as a module, it will be called r8188eu.
+
+if R8188EU
+
+config 88EU_AP_MODE
+ bool "Realtek RTL8188EU AP mode"
+ default y
+ help
+ This option enables Access Point mode. Unless you know that your system
+ will never be used as an AP, or the target system has limited memory,
+ "Y" should be selected.
+
+endif
diff --git a/drivers/staging/rtl8188eu/Makefile b/drivers/staging/rtl8188eu/Makefile
new file mode 100644
index 0000000..bdf654f
--- /dev/null
+++ b/drivers/staging/rtl8188eu/Makefile
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: GPL-2.0
+r8188eu-y := \
+ core/rtw_ap.o \
+ core/rtw_cmd.o \
+ core/rtw_debug.o \
+ core/rtw_efuse.o \
+ core/rtw_ieee80211.o \
+ core/rtw_ioctl_set.o \
+ core/rtw_iol.o \
+ core/rtw_led.o \
+ core/rtw_mlme.o \
+ core/rtw_mlme_ext.o \
+ core/rtw_pwrctrl.o \
+ core/rtw_recv.o \
+ core/rtw_rf.o \
+ core/rtw_security.o \
+ core/rtw_sreset.o \
+ core/rtw_sta_mgt.o \
+ core/rtw_wlan_util.o \
+ core/rtw_xmit.o \
+ hal/fw.o \
+ hal/mac_cfg.o \
+ hal/bb_cfg.o \
+ hal/rf_cfg.o \
+ hal/pwrseqcmd.o \
+ hal/pwrseq.o \
+ hal/hal8188e_rate_adaptive.o \
+ hal/hal_intf.o \
+ hal/hal_com.o \
+ hal/odm.o \
+ hal/odm_hwconfig.o \
+ hal/odm_rtl8188e.o \
+ hal/rtl8188e_cmd.o \
+ hal/rtl8188e_dm.o \
+ hal/rtl8188e_hal_init.o \
+ hal/phy.o \
+ hal/rf.o \
+ hal/rtl8188e_rxdesc.o \
+ hal/rtl8188e_xmit.o \
+ hal/rtl8188eu_led.o \
+ hal/rtl8188eu_recv.o \
+ hal/rtl8188eu_xmit.o \
+ hal/usb_halinit.o \
+ os_dep/ioctl_linux.o \
+ os_dep/mlme_linux.o \
+ os_dep/mon.o \
+ os_dep/os_intfs.o \
+ os_dep/osdep_service.o \
+ os_dep/recv_linux.o \
+ os_dep/rtw_android.o \
+ os_dep/usb_intf.o \
+ os_dep/usb_ops_linux.o \
+ os_dep/xmit_linux.o
+
+obj-$(CPTCFG_R8188EU) := r8188eu.o
+
+ccflags-y += -I$(src)/include
diff --git a/drivers/staging/rtl8188eu/TODO b/drivers/staging/rtl8188eu/TODO
new file mode 100644
index 0000000..5faa0a9
--- /dev/null
+++ b/drivers/staging/rtl8188eu/TODO
@@ -0,0 +1,14 @@
+TODO:
+- find and remove remaining code valid only for 5 GHz. Most of the obvious
+ ones have been removed, but things like channel > 14 still exist.
+- find and remove any code for other chips that is left over
+- convert any remaining unusual variable types
+- find codes that can use %pM and %Nph formatting
+- checkpatch.pl fixes - most of the remaining ones are lines too long. Many
+ of them will require refactoring
+- merge Realtek's bugfixes and new features into the driver
+- switch to use LIB80211
+- switch to use MAC80211
+
+Please send any patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
+and Larry Finger <Larry.Finger@lwfinger.net>.
diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c
new file mode 100644
index 0000000..1e35024
--- /dev/null
+++ b/drivers/staging/rtl8188eu/core/rtw_ap.c
@@ -0,0 +1,1762 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _RTW_AP_C_
+
+#include <linux/ieee80211.h>
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <wifi.h>
+#include <ieee80211.h>
+#include <asm/unaligned.h>
+
+#ifdef CPTCFG_88EU_AP_MODE
+
+void init_mlme_ap_info(struct adapter *padapter)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+
+ spin_lock_init(&pmlmepriv->bcn_update_lock);
+
+ /* for ACL */
+ _rtw_init_queue(&pacl_list->acl_node_q);
+
+ start_ap_mode(padapter);
+}
+
+void free_mlme_ap_info(struct adapter *padapter)
+{
+ struct sta_info *psta = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ pmlmepriv->update_bcn = false;
+ pmlmeext->bstart_bss = false;
+
+ rtw_sta_flush(padapter);
+
+ pmlmeinfo->state = _HW_STATE_NOLINK_;
+
+ /* free_assoc_sta_resources */
+ rtw_free_all_stainfo(padapter);
+
+ /* free bc/mc sta_info */
+ psta = rtw_get_bcmc_stainfo(padapter);
+ spin_lock_bh(&pstapriv->sta_hash_lock);
+ rtw_free_stainfo(padapter, psta);
+ spin_unlock_bh(&pstapriv->sta_hash_lock);
+}
+
+static void update_BCNTIM(struct adapter *padapter)
+{
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network;
+ unsigned char *pie = pnetwork_mlmeext->ies;
+ u8 *p, *dst_ie, *premainder_ie = NULL;
+ u8 *pbackup_remainder_ie = NULL;
+ uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen;
+
+ /* update TIM IE */
+ p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, _TIM_IE_, &tim_ielen,
+ pnetwork_mlmeext->ie_length - _FIXED_IE_LENGTH_);
+ if (p && tim_ielen > 0) {
+ tim_ielen += 2;
+ premainder_ie = p + tim_ielen;
+ tim_ie_offset = (int)(p - pie);
+ remainder_ielen = pnetwork_mlmeext->ie_length -
+ tim_ie_offset - tim_ielen;
+ /* append TIM IE from dst_ie offset */
+ dst_ie = p;
+ } else {
+ tim_ielen = 0;
+
+ /* calculate head_len */
+ offset = _FIXED_IE_LENGTH_;
+ offset += pnetwork_mlmeext->ssid.ssid_length + 2;
+
+ /* get supported rates len */
+ p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_,
+ &tmp_len, (pnetwork_mlmeext->ie_length -
+ _BEACON_IE_OFFSET_));
+ if (p)
+ offset += tmp_len + 2;
+
+ /* DS Parameter Set IE, len = 3 */
+ offset += 3;
+
+ premainder_ie = pie + offset;
+
+ remainder_ielen = pnetwork_mlmeext->ie_length -
+ offset - tim_ielen;
+
+ /* append TIM IE from offset */
+ dst_ie = pie + offset;
+ }
+
+ if (remainder_ielen > 0) {
+ pbackup_remainder_ie = rtw_malloc(remainder_ielen);
+ if (pbackup_remainder_ie && premainder_ie)
+ memcpy(pbackup_remainder_ie, premainder_ie,
+ remainder_ielen);
+ }
+ *dst_ie++ = _TIM_IE_;
+
+ if ((pstapriv->tim_bitmap & 0xff00) && (pstapriv->tim_bitmap & 0x00fc))
+ tim_ielen = 5;
+ else
+ tim_ielen = 4;
+
+ *dst_ie++ = tim_ielen;
+
+ *dst_ie++ = 0;/* DTIM count */
+ *dst_ie++ = 1;/* DTIM period */
+
+ if (pstapriv->tim_bitmap & BIT(0))/* for bc/mc frames */
+ *dst_ie++ = BIT(0);/* bitmap ctrl */
+ else
+ *dst_ie++ = 0;
+
+ if (tim_ielen == 4) {
+ *dst_ie++ = pstapriv->tim_bitmap & 0xff;
+ } else if (tim_ielen == 5) {
+ put_unaligned_le16(pstapriv->tim_bitmap, dst_ie);
+ dst_ie += 2;
+ }
+
+ /* copy remainder IE */
+ if (pbackup_remainder_ie) {
+ memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
+
+ kfree(pbackup_remainder_ie);
+ }
+ offset = (uint)(dst_ie - pie);
+ pnetwork_mlmeext->ie_length = offset + remainder_ielen;
+
+ set_tx_beacon_cmd(padapter);
+}
+
+static u8 chk_sta_is_alive(struct sta_info *psta)
+{
+ u8 ret = false;
+
+ if ((psta->sta_stats.last_rx_data_pkts +
+ psta->sta_stats.last_rx_ctrl_pkts) ==
+ (psta->sta_stats.rx_data_pkts +
+ psta->sta_stats.rx_ctrl_pkts))
+ ;
+ else
+ ret = true;
+
+ sta_update_last_rx_pkts(psta);
+
+ return ret;
+}
+
+void expire_timeout_chk(struct adapter *padapter)
+{
+ struct list_head *phead, *plist;
+ u8 updated = 0;
+ struct sta_info *psta = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ u8 chk_alive_num = 0;
+ char chk_alive_list[NUM_STA];
+ int i;
+
+ spin_lock_bh(&pstapriv->auth_list_lock);
+
+ phead = &pstapriv->auth_list;
+ plist = phead->next;
+
+ /* check auth_queue */
+ while (phead != plist) {
+ psta = container_of(plist, struct sta_info, auth_list);
+ plist = plist->next;
+
+ if (psta->expire_to > 0) {
+ psta->expire_to--;
+ if (psta->expire_to == 0) {
+ list_del_init(&psta->auth_list);
+ pstapriv->auth_list_cnt--;
+
+ DBG_88E("auth expire %6ph\n",
+ psta->hwaddr);
+
+ spin_unlock_bh(&pstapriv->auth_list_lock);
+
+ spin_lock_bh(&pstapriv->sta_hash_lock);
+ rtw_free_stainfo(padapter, psta);
+ spin_unlock_bh(&pstapriv->sta_hash_lock);
+
+ spin_lock_bh(&pstapriv->auth_list_lock);
+ }
+ }
+ }
+ spin_unlock_bh(&pstapriv->auth_list_lock);
+
+ psta = NULL;
+
+ spin_lock_bh(&pstapriv->asoc_list_lock);
+
+ phead = &pstapriv->asoc_list;
+ plist = phead->next;
+
+ /* check asoc_queue */
+ while (phead != plist) {
+ psta = container_of(plist, struct sta_info, asoc_list);
+ plist = plist->next;
+
+ if (chk_sta_is_alive(psta) || !psta->expire_to) {
+ psta->expire_to = pstapriv->expire_to;
+ psta->keep_alive_trycnt = 0;
+ psta->under_exist_checking = 0;
+ } else {
+ psta->expire_to--;
+ }
+
+ if (psta->expire_to <= 0) {
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ if (padapter->registrypriv.wifi_spec == 1) {
+ psta->expire_to = pstapriv->expire_to;
+ continue;
+ }
+
+ if (psta->state & WIFI_SLEEP_STATE) {
+ if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {
+ /* to check if alive by another methods
+ * if station is at ps mode.
+ */
+ psta->expire_to = pstapriv->expire_to;
+ psta->state |= WIFI_STA_ALIVE_CHK_STATE;
+
+ /* to update bcn with tim_bitmap
+ * for this station
+ */
+ pstapriv->tim_bitmap |= BIT(psta->aid);
+ update_beacon(padapter, _TIM_IE_, NULL,
+ false);
+
+ if (!pmlmeext->active_keep_alive_check)
+ continue;
+ }
+ }
+ if (pmlmeext->active_keep_alive_check) {
+ int stainfo_offset;
+
+ stainfo_offset =
+ rtw_stainfo_offset(pstapriv, psta);
+ if (stainfo_offset_valid(stainfo_offset))
+ chk_alive_list[chk_alive_num++] =
+ stainfo_offset;
+ continue;
+ }
+
+ list_del_init(&psta->asoc_list);
+ pstapriv->asoc_list_cnt--;
+
+ DBG_88E("asoc expire %pM, state = 0x%x\n", (psta->hwaddr), psta->state);
+ updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
+ } else {
+ /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */
+ if (psta->sleepq_len > (NR_XMITFRAME / pstapriv->asoc_list_cnt) &&
+ padapter->xmitpriv.free_xmitframe_cnt < (NR_XMITFRAME / pstapriv->asoc_list_cnt / 2)) {
+ DBG_88E("%s sta:%pM, sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", __func__,
+ (psta->hwaddr), psta->sleepq_len,
+ padapter->xmitpriv.free_xmitframe_cnt,
+ pstapriv->asoc_list_cnt);
+ wakeup_sta_to_xmit(padapter, psta);
+ }
+ }
+ }
+
+ spin_unlock_bh(&pstapriv->asoc_list_lock);
+
+ if (chk_alive_num) {
+ u8 backup_oper_channel = 0;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ /* switch to correct channel of current network before issue keep-alive frames */
+ if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
+ backup_oper_channel = rtw_get_oper_ch(padapter);
+ SelectChannel(padapter, pmlmeext->cur_channel);
+ }
+
+ /* issue null data to check sta alive*/
+ for (i = 0; i < chk_alive_num; i++) {
+ int ret = _FAIL;
+
+ psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);
+
+ if (psta->state & WIFI_SLEEP_STATE)
+ ret = issue_nulldata(padapter, psta->hwaddr, 0, 1, 50);
+ else
+ ret = issue_nulldata(padapter, psta->hwaddr, 0, 3, 50);
+
+ psta->keep_alive_trycnt++;
+ if (ret == _SUCCESS) {
+ DBG_88E("asoc check, sta(%pM) is alive\n", (psta->hwaddr));
+ psta->expire_to = pstapriv->expire_to;
+ psta->keep_alive_trycnt = 0;
+ continue;
+ } else if (psta->keep_alive_trycnt <= 3) {
+ DBG_88E("ack check for asoc expire, keep_alive_trycnt =%d\n", psta->keep_alive_trycnt);
+ psta->expire_to = 1;
+ continue;
+ }
+
+ psta->keep_alive_trycnt = 0;
+
+ DBG_88E("asoc expire %pM, state = 0x%x\n", (psta->hwaddr), psta->state);
+ spin_lock_bh(&pstapriv->asoc_list_lock);
+ list_del_init(&psta->asoc_list);
+ pstapriv->asoc_list_cnt--;
+ updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
+ spin_unlock_bh(&pstapriv->asoc_list_lock);
+ }
+
+ if (backup_oper_channel > 0) /* back to the original operation channel */
+ SelectChannel(padapter, backup_oper_channel);
+ }
+
+ associated_clients_update(padapter, updated);
+}
+
+void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level)
+{
+ int i;
+ u32 init_rate = 0;
+ unsigned char sta_band = 0, raid, shortGIrate = false;
+ unsigned int tx_ra_bitmap = 0;
+ struct ht_priv *psta_ht = NULL;
+
+ if (psta)
+ psta_ht = &psta->htpriv;
+ else
+ return;
+
+ if (!(psta->state & _FW_LINKED))
+ return;
+
+ /* b/g mode ra_bitmap */
+ for (i = 0; i < sizeof(psta->bssrateset); i++) {
+ if (psta->bssrateset[i])
+ tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i] & 0x7f);
+ }
+ /* n mode ra_bitmap */
+ if (psta_ht->ht_option) {
+ for (i = 0; i < 8; i++)
+ if (psta_ht->ht_cap.mcs.rx_mask[0] & BIT(i))
+ tx_ra_bitmap |= BIT(i + 12);
+
+ /* max short GI rate */
+ shortGIrate = psta_ht->sgi;
+ }
+
+ if (tx_ra_bitmap & 0xffff000)
+ sta_band |= WIRELESS_11_24N | WIRELESS_11G | WIRELESS_11B;
+ else if (tx_ra_bitmap & 0xff0)
+ sta_band |= WIRELESS_11G | WIRELESS_11B;
+ else
+ sta_band |= WIRELESS_11B;
+
+ psta->wireless_mode = sta_band;
+
+ raid = networktype_to_raid(sta_band);
+ init_rate = get_highest_rate_idx(tx_ra_bitmap & 0x0fffffff) & 0x3f;
+
+ if (psta->aid < NUM_STA) {
+ u8 arg = 0;
+
+ arg = psta->mac_id & 0x1f;
+
+ arg |= BIT(7);/* support entry 2~31 */
+
+ if (shortGIrate)
+ arg |= BIT(5);
+
+ tx_ra_bitmap |= ((raid << 28) & 0xf0000000);
+
+ DBG_88E("%s => mac_id:%d , raid:%d , bitmap = 0x%x, arg = 0x%x\n",
+ __func__, psta->mac_id, raid, tx_ra_bitmap, arg);
+
+ /* bitmap[0:27] = tx_rate_bitmap */
+ /* bitmap[28:31]= Rate Adaptive id */
+ /* arg[0:4] = macid */
+ /* arg[5] = Short GI */
+ rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, rssi_level);
+
+ if (shortGIrate)
+ init_rate |= BIT(6);
+
+ /* set ra_id, init_rate */
+ psta->raid = raid;
+ psta->init_rate = init_rate;
+
+ } else {
+ DBG_88E("station aid %d exceed the max number\n", psta->aid);
+ }
+}
+
+static void update_bmc_sta(struct adapter *padapter)
+{
+ u32 init_rate = 0;
+ unsigned char network_type, raid;
+ int i, supportRateNum = 0;
+ unsigned int tx_ra_bitmap = 0;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wlan_bssid_ex *pcur_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
+ struct sta_info *psta = rtw_get_bcmc_stainfo(padapter);
+
+ if (psta) {
+ psta->aid = 0;/* default set to 0 */
+ psta->mac_id = psta->aid + 1;
+
+ psta->qos_option = 0;
+ psta->htpriv.ht_option = false;
+
+ psta->ieee8021x_blocked = 0;
+
+ memset(&psta->sta_stats, 0, sizeof(struct stainfo_stats));
+
+ /* prepare for add_RATid */
+ supportRateNum = rtw_get_rateset_len((u8 *)&pcur_network->SupportedRates);
+ network_type = rtw_check_network_type((u8 *)&pcur_network->SupportedRates, supportRateNum, 1);
+
+ memcpy(psta->bssrateset, &pcur_network->SupportedRates, supportRateNum);
+ psta->bssratelen = supportRateNum;
+
+ /* b/g mode ra_bitmap */
+ for (i = 0; i < supportRateNum; i++) {
+ if (psta->bssrateset[i])
+ tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i] & 0x7f);
+ }
+
+ if (pcur_network->Configuration.DSConfig > 14) {
+ /* force to A mode. 5G doesn't support CCK rates */
+ network_type = WIRELESS_11A;
+ tx_ra_bitmap = 0x150; /* 6, 12, 24 Mbps */
+ } else {
+ /* force to b mode */
+ network_type = WIRELESS_11B;
+ tx_ra_bitmap = 0xf;
+ }
+
+ raid = networktype_to_raid(network_type);
+ init_rate = get_highest_rate_idx(tx_ra_bitmap & 0x0fffffff) & 0x3f;
+
+ /* ap mode */
+ rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true);
+
+ {
+ u8 arg = 0;
+
+ arg = psta->mac_id & 0x1f;
+ arg |= BIT(7);
+ tx_ra_bitmap |= ((raid << 28) & 0xf0000000);
+ DBG_88E("%s, mask = 0x%x, arg = 0x%x\n", __func__, tx_ra_bitmap, arg);
+
+ /* bitmap[0:27] = tx_rate_bitmap */
+ /* bitmap[28:31]= Rate Adaptive id */
+ /* arg[0:4] = macid */
+ /* arg[5] = Short GI */
+ rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, 0);
+ }
+ /* set ra_id, init_rate */
+ psta->raid = raid;
+ psta->init_rate = init_rate;
+
+ rtw_stassoc_hw_rpt(padapter, psta);
+
+ spin_lock_bh(&psta->lock);
+ psta->state = _FW_LINKED;
+ spin_unlock_bh(&psta->lock);
+
+ } else {
+ DBG_88E("add_RATid_bmc_sta error!\n");
+ }
+}
+
+/* notes: */
+/* AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode */
+/* MAC_ID = AID+1 for sta in ap/adhoc mode */
+/* MAC_ID = 1 for bc/mc for sta/ap/adhoc */
+/* MAC_ID = 0 for bssid for sta/ap/adhoc */
+/* CAM_ID = 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */
+
+void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
+ struct ht_priv *phtpriv_sta = &psta->htpriv;
+
+ psta->mac_id = psta->aid + 1;
+ DBG_88E("%s\n", __func__);
+
+ /* ap mode */
+ rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true);
+
+ if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
+ psta->ieee8021x_blocked = true;
+ else
+ psta->ieee8021x_blocked = false;
+
+ /* update sta's cap */
+
+ /* ERP */
+ VCS_update(padapter, psta);
+ /* HT related cap */
+ if (phtpriv_sta->ht_option) {
+ /* check if sta supports rx ampdu */
+ phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable;
+
+ /* check if sta support s Short GI */
+ if (le16_to_cpu(phtpriv_sta->ht_cap.cap_info &
+ phtpriv_ap->ht_cap.cap_info) &
+ (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40))
+ phtpriv_sta->sgi = true;
+
+ /* bwmode */
+ if (le16_to_cpu(phtpriv_sta->ht_cap.cap_info &
+ phtpriv_ap->ht_cap.cap_info) &
+ IEEE80211_HT_CAP_SUP_WIDTH) {
+ phtpriv_sta->bwmode = pmlmeext->cur_bwmode;
+ phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;
+ }
+ psta->qos_option = true;
+ } else {
+ phtpriv_sta->ampdu_enable = false;
+ phtpriv_sta->sgi = false;
+ phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20;
+ phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ }
+
+ /* Rx AMPDU */
+ send_delba(padapter, 0, psta->hwaddr);/* recipient */
+
+ /* TX AMPDU */
+ send_delba(padapter, 1, psta->hwaddr);/* originator */
+ phtpriv_sta->agg_enable_bitmap = 0x0;/* reset */
+ phtpriv_sta->candidate_tid_bitmap = 0x0;/* reset */
+
+ /* todo: init other variables */
+
+ memset(&psta->sta_stats, 0, sizeof(struct stainfo_stats));
+
+ spin_lock_bh(&psta->lock);
+ psta->state |= _FW_LINKED;
+ spin_unlock_bh(&psta->lock);
+}
+
+static void update_hw_ht_param(struct adapter *padapter)
+{
+ unsigned char max_AMPDU_len;
+ unsigned char min_MPDU_spacing;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ DBG_88E("%s\n", __func__);
+
+ /* handle A-MPDU parameter field */
+ /*
+ ampdu_params_info [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
+ ampdu_params_info [4:2]:Min MPDU Start Spacing
+ */
+ max_AMPDU_len = pmlmeinfo->HT_caps.ampdu_params_info & 0x03;
+
+ min_MPDU_spacing = (pmlmeinfo->HT_caps.ampdu_params_info & 0x1c) >> 2;
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
+
+ /* */
+ /* Config SM Power Save setting */
+ /* */
+ pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & 0x0C) >> 2;
+ if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
+ DBG_88E("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__);
+}
+
+static void start_bss_network(struct adapter *padapter, u8 *pbuf)
+{
+ u8 *p;
+ u8 val8, cur_channel, cur_bwmode, cur_ch_offset;
+ u16 bcn_interval;
+ u32 acparm;
+ uint ie_len;
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network;
+ struct HT_info_element *pht_info = NULL;
+
+ bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod;
+ cur_channel = pnetwork->Configuration.DSConfig;
+ cur_bwmode = HT_CHANNEL_WIDTH_20;
+ cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+
+ /* check if there is wps ie,
+ * if there is wpsie in beacon, the hostapd will update
+ * beacon twice when stating hostapd, and at first time the
+ * security ie (RSN/WPA IE) will not include in beacon.
+ */
+ if (!rtw_get_wps_ie(pnetwork->ies + _FIXED_IE_LENGTH_, pnetwork->ie_length - _FIXED_IE_LENGTH_, NULL, NULL))
+ pmlmeext->bstart_bss = true;
+
+ /* todo: update wmm, ht cap */
+ if (pmlmepriv->qospriv.qos_option)
+ pmlmeinfo->WMM_enable = true;
+ if (pmlmepriv->htpriv.ht_option) {
+ pmlmeinfo->WMM_enable = true;
+ pmlmeinfo->HT_enable = true;
+
+ update_hw_ht_param(padapter);
+ }
+
+ /* setting only at first time */
+ if (!pmlmepriv->cur_network.join_res) {
+ /* WEP Key will be set before this function, do not
+ * clear CAM.
+ */
+ if ((psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) &&
+ (psecuritypriv->dot11PrivacyAlgrthm != _WEP104_))
+ flush_all_cam_entry(padapter); /* clear CAM */
+ }
+
+ /* set MSR to AP_Mode */
+ Set_MSR(padapter, _HW_STATE_AP_);
+
+ /* Set BSSID REG */
+ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pnetwork->MacAddress);
+
+ /* Set EDCA param reg */
+ acparm = 0x002F3217; /* VO */
+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));
+ acparm = 0x005E4317; /* VI */
+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));
+ acparm = 0x005ea42b;
+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
+ acparm = 0x0000A444; /* BK */
+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));
+
+ /* Set Security */
+ val8 = (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf;
+ rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
+
+ /* Beacon Control related register */
+ rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&bcn_interval));
+
+ UpdateBrateTbl(padapter, pnetwork->SupportedRates);
+ rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);
+
+ if (!pmlmepriv->cur_network.join_res) { /* setting only at first time */
+ /* turn on all dynamic functions */
+ Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
+ }
+ /* set channel, bwmode */
+ p = rtw_get_ie((pnetwork->ies + sizeof(struct ndis_802_11_fixed_ie)), _HT_ADD_INFO_IE_, &ie_len, (pnetwork->ie_length - sizeof(struct ndis_802_11_fixed_ie)));
+ if (p && ie_len) {
+ pht_info = (struct HT_info_element *)(p + 2);
+
+ if ((pregpriv->cbw40_enable) && (pht_info->infos[0] & BIT(2))) {
+ /* switch to the 40M Hz mode */
+ cur_bwmode = HT_CHANNEL_WIDTH_40;
+ switch (pht_info->infos[0] & 0x3) {
+ case 1:
+ cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
+ break;
+ case 3:
+ cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
+ break;
+ default:
+ cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ break;
+ }
+ }
+ }
+ /* TODO: need to judge the phy parameters on concurrent
+ * mode for single phy
+ */
+ set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
+
+ DBG_88E("CH =%d, BW =%d, offset =%d\n", cur_channel, cur_bwmode, cur_ch_offset);
+
+ /* */
+ pmlmeext->cur_channel = cur_channel;
+ pmlmeext->cur_bwmode = cur_bwmode;
+ pmlmeext->cur_ch_offset = cur_ch_offset;
+ pmlmeext->cur_wireless_mode = pmlmepriv->cur_network.network_type;
+
+ /* update cur_wireless_mode */
+ update_wireless_mode(padapter);
+
+ /* update capability after cur_wireless_mode updated */
+ update_capinfo(padapter, rtw_get_capability((struct wlan_bssid_ex *)pnetwork));
+
+ /* let pnetwork_mlmeext == pnetwork_mlme. */
+ memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length);
+
+ if (pmlmeext->bstart_bss) {
+ update_beacon(padapter, _TIM_IE_, NULL, false);
+
+ /* issue beacon frame */
+ if (send_beacon(padapter) == _FAIL)
+ DBG_88E("send_beacon, fail!\n");
+ }
+
+ /* update bc/mc sta_info */
+ update_bmc_sta(padapter);
+}
+
+int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
+{
+ int ret = _SUCCESS;
+ u8 *p;
+ u8 *pHT_caps_ie = NULL;
+ u8 *pHT_info_ie = NULL;
+ struct sta_info *psta = NULL;
+ u16 cap, ht_cap = false;
+ uint ie_len = 0;
+ int group_cipher, pairwise_cipher;
+ u8 channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX];
+ int supportRateNum = 0;
+ u8 OUI1[] = {0x00, 0x50, 0xf2, 0x01};
+ u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wlan_bssid_ex *pbss_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
+ u8 *ie = pbss_network->ies;
+
+ /* SSID */
+ /* Supported rates */
+ /* DS Params */
+ /* WLAN_EID_COUNTRY */
+ /* ERP Information element */
+ /* Extended supported rates */
+ /* WPA/WPA2 */
+ /* Wi-Fi Wireless Multimedia Extensions */
+ /* ht_capab, ht_oper */
+ /* WPS IE */
+
+ DBG_88E("%s, len =%d\n", __func__, len);
+
+ if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ return _FAIL;
+
+ if (len < 0 || len > MAX_IE_SZ)
+ return _FAIL;
+
+ pbss_network->ie_length = len;
+
+ memset(ie, 0, MAX_IE_SZ);
+
+ memcpy(ie, pbuf, pbss_network->ie_length);
+
+ if (pbss_network->InfrastructureMode != Ndis802_11APMode)
+ return _FAIL;
+
+ pbss_network->Rssi = 0;
+
+ ether_addr_copy(pbss_network->MacAddress, myid(&padapter->eeprompriv));
+
+ /* beacon interval */
+ p = rtw_get_beacon_interval_from_ie(ie);/* 8: TimeStamp, 2: Beacon Interval 2:Capability */
+ pbss_network->Configuration.BeaconPeriod = get_unaligned_le16(p);
+
+ /* capability */
+ cap = get_unaligned_le16(ie);
+
+ /* SSID */
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_));
+ if (p && ie_len > 0) {
+ memset(&pbss_network->ssid, 0, sizeof(struct ndis_802_11_ssid));
+ memcpy(pbss_network->ssid.ssid, (p + 2), ie_len);
+ pbss_network->ssid.ssid_length = ie_len;
+ }
+
+ /* channel */
+ channel = 0;
+ pbss_network->Configuration.Length = 0;
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _DSSET_IE_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_));
+ if (p && ie_len > 0)
+ channel = *(p + 2);
+
+ pbss_network->Configuration.DSConfig = channel;
+
+ memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX);
+ /* get supported rates */
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_));
+ if (p) {
+ memcpy(supportRate, p + 2, ie_len);
+ supportRateNum = ie_len;
+ }
+
+ /* get ext_supported rates */
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ie_len, pbss_network->ie_length - _BEACON_IE_OFFSET_);
+ if (p) {
+ memcpy(supportRate + supportRateNum, p + 2, ie_len);
+ supportRateNum += ie_len;
+ }
+
+ network_type = rtw_check_network_type(supportRate, supportRateNum, channel);
+
+ rtw_set_supported_rate(pbss_network->SupportedRates, network_type);
+
+ /* parsing ERP_IE */
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_));
+ if (p && ie_len > 0)
+ ERP_IE_handler(padapter, (struct ndis_802_11_var_ie *)p);
+
+ /* update privacy/security */
+ if (cap & BIT(4))
+ pbss_network->Privacy = 1;
+ else
+ pbss_network->Privacy = 0;
+
+ psecuritypriv->wpa_psk = 0;
+
+ /* wpa2 */
+ group_cipher = 0;
+ pairwise_cipher = 0;
+ psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;
+ psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_));
+ if (p && ie_len > 0) {
+ if (rtw_parse_wpa2_ie(p, ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
+ psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
+
+ psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */
+ psecuritypriv->wpa_psk |= BIT(1);
+
+ psecuritypriv->wpa2_group_cipher = group_cipher;
+ psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher;
+ }
+ }
+ /* wpa */
+ ie_len = 0;
+ group_cipher = 0;
+ pairwise_cipher = 0;
+ psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;
+ psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;
+ for (p = ie + _BEACON_IE_OFFSET_;; p += (ie_len + 2)) {
+ p = rtw_get_ie(p, _SSN_IE_1_, &ie_len,
+ (pbss_network->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2)));
+ if ((p) && (!memcmp(p + 2, OUI1, 4))) {
+ if (rtw_parse_wpa_ie(p, ie_len + 2, &group_cipher,
+ &pairwise_cipher, NULL) == _SUCCESS) {
+ psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
+
+ psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */
+
+ psecuritypriv->wpa_psk |= BIT(0);
+
+ psecuritypriv->wpa_group_cipher = group_cipher;
+ psecuritypriv->wpa_pairwise_cipher = pairwise_cipher;
+ }
+ break;
+ }
+ if ((!p) || (ie_len == 0))
+ break;
+ }
+
+ /* wmm */
+ ie_len = 0;
+ pmlmepriv->qospriv.qos_option = 0;
+ if (pregistrypriv->wmm_enable) {
+ for (p = ie + _BEACON_IE_OFFSET_;; p += (ie_len + 2)) {
+ p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len,
+ (pbss_network->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2)));
+ if ((p) && !memcmp(p + 2, WMM_PARA_IE, 6)) {
+ pmlmepriv->qospriv.qos_option = 1;
+
+ /* QoS Info, support U-APSD */
+ *(p + 8) |= BIT(7);
+
+ /* disable all ACM bits since the WMM
+ * admission control is not supported
+ */
+ *(p + 10) &= ~BIT(4); /* BE */
+ *(p + 14) &= ~BIT(4); /* BK */
+ *(p + 18) &= ~BIT(4); /* VI */
+ *(p + 22) &= ~BIT(4); /* VO */
+ break;
+ }
+
+ if ((!p) || (ie_len == 0))
+ break;
+ }
+ }
+ /* parsing HT_CAP_IE */
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len,
+ (pbss_network->ie_length - _BEACON_IE_OFFSET_));
+ if (p && ie_len > 0) {
+ struct ieee80211_ht_cap *pht_cap = (struct ieee80211_ht_cap *)(p + 2);
+
+ pHT_caps_ie = p;
+ ht_cap = true;
+ network_type |= WIRELESS_11_24N;
+
+ if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) ||
+ (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP))
+ pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & (0x07 << 2));
+ else
+ pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & 0x00);
+
+ /* set Max Rx AMPDU size to 64K */
+ pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_FACTOR & 0x03);
+
+ pht_cap->mcs.rx_mask[0] = 0xff;
+ pht_cap->mcs.rx_mask[1] = 0x0;
+ memcpy(&pmlmepriv->htpriv.ht_cap, p + 2, ie_len);
+ }
+
+ /* parsing HT_INFO_IE */
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len,
+ (pbss_network->ie_length - _BEACON_IE_OFFSET_));
+ if (p && ie_len > 0)
+ pHT_info_ie = p;
+ switch (network_type) {
+ case WIRELESS_11B:
+ pbss_network->NetworkTypeInUse = Ndis802_11DS;
+ break;
+ case WIRELESS_11G:
+ case WIRELESS_11BG:
+ case WIRELESS_11G_24N:
+ case WIRELESS_11BG_24N:
+ pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
+ break;
+ case WIRELESS_11A:
+ pbss_network->NetworkTypeInUse = Ndis802_11OFDM5;
+ break;
+ default:
+ pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
+ break;
+ }
+
+ pmlmepriv->cur_network.network_type = network_type;
+
+ pmlmepriv->htpriv.ht_option = false;
+
+ if ((psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_TKIP) ||
+ (psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) {
+ /* todo: */
+ /* ht_cap = false; */
+ }
+
+ /* ht_cap */
+ if (pregistrypriv->ht_enable && ht_cap) {
+ pmlmepriv->htpriv.ht_option = true;
+ pmlmepriv->qospriv.qos_option = 1;
+
+ if (pregistrypriv->ampdu_enable == 1)
+ pmlmepriv->htpriv.ampdu_enable = true;
+ HT_caps_handler(padapter, (struct ndis_802_11_var_ie *)pHT_caps_ie);
+
+ HT_info_handler(padapter, (struct ndis_802_11_var_ie *)pHT_info_ie);
+ }
+
+ pbss_network->Length = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pbss_network);
+
+ /* issue beacon to start bss network */
+ start_bss_network(padapter, (u8 *)pbss_network);
+
+ /* alloc sta_info for ap itself */
+ psta = rtw_get_stainfo(&padapter->stapriv, pbss_network->MacAddress);
+ if (!psta) {
+ psta = rtw_alloc_stainfo(&padapter->stapriv, pbss_network->MacAddress);
+ if (!psta)
+ return _FAIL;
+ }
+
+ /* fix bug of flush_cam_entry at STOP AP mode */
+ psta->state |= WIFI_AP_STATE;
+ rtw_indicate_connect(padapter);
+ pmlmepriv->cur_network.join_res = true;/* for check if already set beacon */
+ return ret;
+}
+
+void rtw_set_macaddr_acl(struct adapter *padapter, int mode)
+{
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+
+ DBG_88E("%s, mode =%d\n", __func__, mode);
+
+ pacl_list->mode = mode;
+}
+
+int rtw_acl_add_sta(struct adapter *padapter, u8 *addr)
+{
+ struct list_head *plist, *phead;
+ u8 added = false;
+ int i, ret = 0;
+ struct rtw_wlan_acl_node *paclnode;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+ struct __queue *pacl_node_q = &pacl_list->acl_node_q;
+
+ DBG_88E("%s(acl_num =%d) =%pM\n", __func__, pacl_list->num, (addr));
+
+ if ((NUM_ACL - 1) < pacl_list->num)
+ return -1;
+
+ spin_lock_bh(&pacl_node_q->lock);
+
+ phead = get_list_head(pacl_node_q);
+ plist = phead->next;
+
+ while (phead != plist) {
+ paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
+ plist = plist->next;
+
+ if (!memcmp(paclnode->addr, addr, ETH_ALEN)) {
+ if (paclnode->valid) {
+ added = true;
+ DBG_88E("%s, sta has been added\n", __func__);
+ break;
+ }
+ }
+ }
+
+ spin_unlock_bh(&pacl_node_q->lock);
+
+ if (added)
+ return ret;
+
+ spin_lock_bh(&pacl_node_q->lock);
+
+ for (i = 0; i < NUM_ACL; i++) {
+ paclnode = &pacl_list->aclnode[i];
+
+ if (!paclnode->valid) {
+ INIT_LIST_HEAD(&paclnode->list);
+
+ ether_addr_copy(paclnode->addr, addr);
+
+ paclnode->valid = true;
+
+ list_add_tail(&paclnode->list, get_list_head(pacl_node_q));
+
+ pacl_list->num++;
+
+ break;
+ }
+ }
+
+ DBG_88E("%s, acl_num =%d\n", __func__, pacl_list->num);
+
+ spin_unlock_bh(&pacl_node_q->lock);
+
+ return ret;
+}
+
+int rtw_acl_remove_sta(struct adapter *padapter, u8 *addr)
+{
+ struct list_head *plist, *phead;
+ struct rtw_wlan_acl_node *paclnode;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+ struct __queue *pacl_node_q = &pacl_list->acl_node_q;
+
+ DBG_88E("%s(acl_num =%d) =%pM\n", __func__, pacl_list->num, (addr));
+
+ spin_lock_bh(&pacl_node_q->lock);
+
+ phead = get_list_head(pacl_node_q);
+ plist = phead->next;
+
+ while (phead != plist) {
+ paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
+ plist = plist->next;
+
+ if (!memcmp(paclnode->addr, addr, ETH_ALEN)) {
+ if (paclnode->valid) {
+ paclnode->valid = false;
+
+ list_del_init(&paclnode->list);
+
+ pacl_list->num--;
+ }
+ }
+ }
+
+ spin_unlock_bh(&pacl_node_q->lock);
+
+ DBG_88E("%s, acl_num =%d\n", __func__, pacl_list->num);
+ return 0;
+}
+
+static void update_bcn_erpinfo_ie(struct adapter *padapter)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
+ unsigned char *p, *ie = pnetwork->ies;
+ u32 len = 0;
+
+ DBG_88E("%s, ERP_enable =%d\n", __func__, pmlmeinfo->ERP_enable);
+
+ if (!pmlmeinfo->ERP_enable)
+ return;
+
+ /* parsing ERP_IE */
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &len,
+ (pnetwork->ie_length - _BEACON_IE_OFFSET_));
+ if (p && len > 0) {
+ struct ndis_802_11_var_ie *pIE = (struct ndis_802_11_var_ie *)p;
+
+ if (pmlmepriv->num_sta_non_erp == 1)
+ pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT |
+ RTW_ERP_INFO_USE_PROTECTION;
+ else
+ pIE->data[0] &= ~(RTW_ERP_INFO_NON_ERP_PRESENT |
+ RTW_ERP_INFO_USE_PROTECTION);
+
+ if (pmlmepriv->num_sta_no_short_preamble > 0)
+ pIE->data[0] |= RTW_ERP_INFO_BARKER_PREAMBLE_MODE;
+ else
+ pIE->data[0] &= ~(RTW_ERP_INFO_BARKER_PREAMBLE_MODE);
+
+ ERP_IE_handler(padapter, pIE);
+ }
+}
+
+static void update_bcn_wps_ie(struct adapter *padapter)
+{
+ u8 *pwps_ie = NULL, *pwps_ie_src;
+ u8 *premainder_ie, *pbackup_remainder_ie = NULL;
+ uint wps_ielen = 0, wps_offset, remainder_ielen;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
+ unsigned char *ie = pnetwork->ies;
+ u32 ielen = pnetwork->ie_length;
+
+ DBG_88E("%s\n", __func__);
+
+ pwps_ie_src = pmlmepriv->wps_beacon_ie;
+ if (!pwps_ie_src)
+ return;
+
+ pwps_ie = rtw_get_wps_ie(ie + _FIXED_IE_LENGTH_,
+ ielen - _FIXED_IE_LENGTH_, NULL, &wps_ielen);
+
+ if (!pwps_ie || wps_ielen == 0)
+ return;
+
+ wps_offset = (uint)(pwps_ie - ie);
+
+ premainder_ie = pwps_ie + wps_ielen;
+
+ remainder_ielen = ielen - wps_offset - wps_ielen;
+
+ if (remainder_ielen > 0) {
+ pbackup_remainder_ie = rtw_malloc(remainder_ielen);
+ if (pbackup_remainder_ie)
+ memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
+ }
+
+ wps_ielen = (uint)pwps_ie_src[1];/* to get ie data len */
+ if (wps_offset + wps_ielen + 2 + remainder_ielen <= MAX_IE_SZ) {
+ memcpy(pwps_ie, pwps_ie_src, wps_ielen + 2);
+ pwps_ie += wps_ielen + 2;
+
+ if (pbackup_remainder_ie)
+ memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen);
+
+ /* update ie_length */
+ pnetwork->ie_length = wps_offset + wps_ielen + 2 + remainder_ielen;
+ }
+
+ kfree(pbackup_remainder_ie);
+}
+
+static void update_bcn_vendor_spec_ie(struct adapter *padapter, u8 *oui)
+{
+ DBG_88E("%s\n", __func__);
+
+ if (!memcmp(WPS_OUI, oui, 4))
+ update_bcn_wps_ie(padapter);
+ else
+ DBG_88E("unknown OUI type!\n");
+}
+
+void update_beacon(struct adapter *padapter, u8 ie_id, u8 *oui, u8 tx)
+{
+ struct mlme_priv *pmlmepriv;
+ struct mlme_ext_priv *pmlmeext;
+
+ if (!padapter)
+ return;
+
+ pmlmepriv = &padapter->mlmepriv;
+ pmlmeext = &padapter->mlmeextpriv;
+
+ if (!pmlmeext->bstart_bss)
+ return;
+
+ spin_lock_bh(&pmlmepriv->bcn_update_lock);
+
+ switch (ie_id) {
+ case _TIM_IE_:
+ update_BCNTIM(padapter);
+ break;
+ case _ERPINFO_IE_:
+ update_bcn_erpinfo_ie(padapter);
+ break;
+ case _VENDOR_SPECIFIC_IE_:
+ update_bcn_vendor_spec_ie(padapter, oui);
+ break;
+ default:
+ break;
+ }
+
+ pmlmepriv->update_bcn = true;
+
+ spin_unlock_bh(&pmlmepriv->bcn_update_lock);
+
+ if (tx)
+ set_tx_beacon_cmd(padapter);
+}
+
+/*
+op_mode
+Set to 0 (HT pure) under the following conditions
+ - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
+ - all STAs in the BSS are 20 MHz HT in 20 MHz BSS
+Set to 1 (HT non-member protection) if there may be non-HT STAs
+ in both the primary and the secondary channel
+Set to 2 if only HT STAs are associated in BSS,
+ however and at least one 20 MHz HT STA is associated
+Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
+ (currently non-GF HT station is considered as non-HT STA also)
+*/
+static int rtw_ht_operation_update(struct adapter *padapter)
+{
+ u16 cur_op_mode, new_op_mode;
+ int op_mode_changes = 0;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
+
+ if (pmlmepriv->htpriv.ht_option)
+ return 0;
+
+ DBG_88E("%s current operation mode = 0x%X\n",
+ __func__, pmlmepriv->ht_op_mode);
+
+ if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
+ pmlmepriv->num_sta_ht_no_gf) {
+ pmlmepriv->ht_op_mode |=
+ HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
+ op_mode_changes++;
+ } else if ((pmlmepriv->ht_op_mode &
+ HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
+ pmlmepriv->num_sta_ht_no_gf == 0) {
+ pmlmepriv->ht_op_mode &=
+ ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
+ op_mode_changes++;
+ }
+
+ if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
+ (pmlmepriv->num_sta_no_ht || pmlmepriv->olbc_ht)) {
+ pmlmepriv->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
+ op_mode_changes++;
+ } else if ((pmlmepriv->ht_op_mode &
+ HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
+ (pmlmepriv->num_sta_no_ht == 0 && !pmlmepriv->olbc_ht)) {
+ pmlmepriv->ht_op_mode &=
+ ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
+ op_mode_changes++;
+ }
+
+ /* Note: currently we switch to the MIXED op mode if HT non-greenfield
+ * station is associated. Probably it's a theoretical case, since
+ * it looks like all known HT STAs support greenfield.
+ */
+ new_op_mode = 0;
+ if (pmlmepriv->num_sta_no_ht ||
+ (pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT))
+ new_op_mode = OP_MODE_MIXED;
+ else if ((le16_to_cpu(phtpriv_ap->ht_cap.cap_info) &
+ IEEE80211_HT_CAP_SUP_WIDTH) &&
+ pmlmepriv->num_sta_ht_20mhz)
+ new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;
+ else if (pmlmepriv->olbc_ht)
+ new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS;
+ else
+ new_op_mode = OP_MODE_PURE;
+
+ cur_op_mode = pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;
+ if (cur_op_mode != new_op_mode) {
+ pmlmepriv->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;
+ pmlmepriv->ht_op_mode |= new_op_mode;
+ op_mode_changes++;
+ }
+
+ DBG_88E("%s new operation mode = 0x%X changes =%d\n",
+ __func__, pmlmepriv->ht_op_mode, op_mode_changes);
+
+ return op_mode_changes;
+}
+
+void associated_clients_update(struct adapter *padapter, u8 updated)
+{
+ /* update associated stations cap. */
+ if (updated) {
+ struct list_head *phead, *plist;
+ struct sta_info *psta = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ spin_lock_bh(&pstapriv->asoc_list_lock);
+
+ phead = &pstapriv->asoc_list;
+ plist = phead->next;
+
+ /* check asoc_queue */
+ while (phead != plist) {
+ psta = container_of(plist, struct sta_info, asoc_list);
+
+ plist = plist->next;
+
+ VCS_update(padapter, psta);
+ }
+ spin_unlock_bh(&pstapriv->asoc_list_lock);
+ }
+}
+
+/* called > TSR LEVEL for USB or SDIO Interface*/
+void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta)
+{
+ u8 beacon_updated = false;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ if (!(psta->flags & WLAN_STA_SHORT_PREAMBLE)) {
+ if (!psta->no_short_preamble_set) {
+ psta->no_short_preamble_set = 1;
+
+ pmlmepriv->num_sta_no_short_preamble++;
+
+ if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
+ (pmlmepriv->num_sta_no_short_preamble == 1)) {
+ beacon_updated = true;
+ update_beacon(padapter, 0xFF, NULL, true);
+ }
+ }
+ } else {
+ if (psta->no_short_preamble_set) {
+ psta->no_short_preamble_set = 0;
+
+ pmlmepriv->num_sta_no_short_preamble--;
+
+ if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
+ (pmlmepriv->num_sta_no_short_preamble == 0)) {
+ beacon_updated = true;
+ update_beacon(padapter, 0xFF, NULL, true);
+ }
+ }
+ }
+
+ if (psta->flags & WLAN_STA_NONERP) {
+ if (!psta->nonerp_set) {
+ psta->nonerp_set = 1;
+
+ pmlmepriv->num_sta_non_erp++;
+
+ if (pmlmepriv->num_sta_non_erp == 1) {
+ beacon_updated = true;
+ update_beacon(padapter, _ERPINFO_IE_, NULL, true);
+ }
+ }
+ } else {
+ if (psta->nonerp_set) {
+ psta->nonerp_set = 0;
+
+ pmlmepriv->num_sta_non_erp--;
+
+ if (pmlmepriv->num_sta_non_erp == 0) {
+ beacon_updated = true;
+ update_beacon(padapter, _ERPINFO_IE_, NULL, true);
+ }
+ }
+ }
+
+ if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)) {
+ if (!psta->no_short_slot_time_set) {
+ psta->no_short_slot_time_set = 1;
+
+ pmlmepriv->num_sta_no_short_slot_time++;
+
+ if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
+ (pmlmepriv->num_sta_no_short_slot_time == 1)) {
+ beacon_updated = true;
+ update_beacon(padapter, 0xFF, NULL, true);
+ }
+ }
+ } else {
+ if (psta->no_short_slot_time_set) {
+ psta->no_short_slot_time_set = 0;
+
+ pmlmepriv->num_sta_no_short_slot_time--;
+
+ if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
+ (pmlmepriv->num_sta_no_short_slot_time == 0)) {
+ beacon_updated = true;
+ update_beacon(padapter, 0xFF, NULL, true);
+ }
+ }
+ }
+
+ if (psta->flags & WLAN_STA_HT) {
+ u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info);
+
+ DBG_88E("HT: STA %pM HT Capabilities Info: 0x%04x\n",
+ (psta->hwaddr), ht_capab);
+
+ if (psta->no_ht_set) {
+ psta->no_ht_set = 0;
+ pmlmepriv->num_sta_no_ht--;
+ }
+
+ if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) {
+ if (!psta->no_ht_gf_set) {
+ psta->no_ht_gf_set = 1;
+ pmlmepriv->num_sta_ht_no_gf++;
+ }
+ DBG_88E("%s STA %pM - no greenfield, num of non-gf stations %d\n",
+ __func__, (psta->hwaddr),
+ pmlmepriv->num_sta_ht_no_gf);
+ }
+
+ if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH) == 0) {
+ if (!psta->ht_20mhz_set) {
+ psta->ht_20mhz_set = 1;
+ pmlmepriv->num_sta_ht_20mhz++;
+ }
+ DBG_88E("%s STA %pM - 20 MHz HT, num of 20MHz HT STAs %d\n",
+ __func__, (psta->hwaddr),
+ pmlmepriv->num_sta_ht_20mhz);
+ }
+ } else {
+ if (!psta->no_ht_set) {
+ psta->no_ht_set = 1;
+ pmlmepriv->num_sta_no_ht++;
+ }
+ if (pmlmepriv->htpriv.ht_option) {
+ DBG_88E("%s STA %pM - no HT, num of non-HT stations %d\n",
+ __func__, (psta->hwaddr),
+ pmlmepriv->num_sta_no_ht);
+ }
+ }
+
+ if (rtw_ht_operation_update(padapter) > 0) {
+ update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, false);
+ update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, true);
+ }
+
+ /* update associated stations cap. */
+ associated_clients_update(padapter, beacon_updated);
+
+ DBG_88E("%s, updated =%d\n", __func__, beacon_updated);
+}
+
+u8 bss_cap_update_on_sta_leave(struct adapter *padapter, struct sta_info *psta)
+{
+ u8 beacon_updated = false;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ if (!psta)
+ return beacon_updated;
+
+ if (psta->no_short_preamble_set) {
+ psta->no_short_preamble_set = 0;
+ pmlmepriv->num_sta_no_short_preamble--;
+ if (pmlmeext->cur_wireless_mode > WIRELESS_11B &&
+ pmlmepriv->num_sta_no_short_preamble == 0) {
+ beacon_updated = true;
+ update_beacon(padapter, 0xFF, NULL, true);
+ }
+ }
+
+ if (psta->nonerp_set) {
+ psta->nonerp_set = 0;
+ pmlmepriv->num_sta_non_erp--;
+ if (pmlmepriv->num_sta_non_erp == 0) {
+ beacon_updated = true;
+ update_beacon(padapter, _ERPINFO_IE_, NULL, true);
+ }
+ }
+
+ if (psta->no_short_slot_time_set) {
+ psta->no_short_slot_time_set = 0;
+ pmlmepriv->num_sta_no_short_slot_time--;
+ if (pmlmeext->cur_wireless_mode > WIRELESS_11B &&
+ pmlmepriv->num_sta_no_short_slot_time == 0) {
+ beacon_updated = true;
+ update_beacon(padapter, 0xFF, NULL, true);
+ }
+ }
+
+ if (psta->no_ht_gf_set) {
+ psta->no_ht_gf_set = 0;
+ pmlmepriv->num_sta_ht_no_gf--;
+ }
+
+ if (psta->no_ht_set) {
+ psta->no_ht_set = 0;
+ pmlmepriv->num_sta_no_ht--;
+ }
+
+ if (psta->ht_20mhz_set) {
+ psta->ht_20mhz_set = 0;
+ pmlmepriv->num_sta_ht_20mhz--;
+ }
+
+ if (rtw_ht_operation_update(padapter) > 0) {
+ update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, false);
+ update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, true);
+ }
+
+ /* update associated stations cap. */
+
+ DBG_88E("%s, updated =%d\n", __func__, beacon_updated);
+
+ return beacon_updated;
+}
+
+u8 ap_free_sta(struct adapter *padapter, struct sta_info *psta,
+ bool active, u16 reason)
+{
+ u8 beacon_updated = false;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ if (!psta)
+ return beacon_updated;
+
+ /* tear down Rx AMPDU */
+ send_delba(padapter, 0, psta->hwaddr);/* recipient */
+
+ /* tear down TX AMPDU */
+ send_delba(padapter, 1, psta->hwaddr);/* originator */
+ psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
+ psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
+
+ if (active)
+ issue_deauth(padapter, psta->hwaddr, reason);
+
+ /* clear cam entry / key */
+ rtw_clearstakey_cmd(padapter, (u8 *)psta, (u8)(psta->mac_id + 3), true);
+
+ spin_lock_bh(&psta->lock);
+ psta->state &= ~_FW_LINKED;
+ spin_unlock_bh(&psta->lock);
+
+ rtw_indicate_sta_disassoc_event(padapter, psta);
+
+ report_del_sta_event(padapter, psta->hwaddr, reason);
+
+ beacon_updated = bss_cap_update_on_sta_leave(padapter, psta);
+
+ spin_lock_bh(&pstapriv->sta_hash_lock);
+ rtw_free_stainfo(padapter, psta);
+ spin_unlock_bh(&pstapriv->sta_hash_lock);
+
+ return beacon_updated;
+}
+
+int rtw_sta_flush(struct adapter *padapter)
+{
+ struct list_head *phead, *plist;
+ struct sta_info *psta = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ DBG_88E(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
+
+ if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
+ return 0;
+
+ spin_lock_bh(&pstapriv->asoc_list_lock);
+ phead = &pstapriv->asoc_list;
+ plist = phead->next;
+
+ /* free sta asoc_queue */
+ while (phead != plist) {
+ psta = container_of(plist, struct sta_info, asoc_list);
+
+ plist = plist->next;
+
+ list_del_init(&psta->asoc_list);
+ pstapriv->asoc_list_cnt--;
+
+ ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
+ }
+ spin_unlock_bh(&pstapriv->asoc_list_lock);
+
+ issue_deauth(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING);
+
+ associated_clients_update(padapter, true);
+
+ return 0;
+}
+
+/* called > TSR LEVEL for USB or SDIO Interface*/
+void sta_info_update(struct adapter *padapter, struct sta_info *psta)
+{
+ int flags = psta->flags;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ /* update wmm cap. */
+ if (WLAN_STA_WME & flags)
+ psta->qos_option = 1;
+ else
+ psta->qos_option = 0;
+
+ if (pmlmepriv->qospriv.qos_option == 0)
+ psta->qos_option = 0;
+
+ /* update 802.11n ht cap. */
+ if (WLAN_STA_HT & flags) {
+ psta->htpriv.ht_option = true;
+ psta->qos_option = 1;
+ } else {
+ psta->htpriv.ht_option = false;
+ }
+
+ if (!pmlmepriv->htpriv.ht_option)
+ psta->htpriv.ht_option = false;
+
+ update_sta_info_apmode(padapter, psta);
+}
+
+/* called >= TSR LEVEL for USB or SDIO Interface*/
+void ap_sta_info_defer_update(struct adapter *padapter, struct sta_info *psta)
+{
+ if (psta->state & _FW_LINKED) {
+ /* add ratid */
+ add_RATid(padapter, psta, 0);/* DM_RATR_STA_INIT */
+ }
+}
+
+void start_ap_mode(struct adapter *padapter)
+{
+ int i;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+
+ pmlmepriv->update_bcn = false;
+
+ pmlmeext->bstart_bss = false;
+
+ pmlmepriv->num_sta_non_erp = 0;
+
+ pmlmepriv->num_sta_no_short_slot_time = 0;
+
+ pmlmepriv->num_sta_no_short_preamble = 0;
+
+ pmlmepriv->num_sta_ht_no_gf = 0;
+ pmlmepriv->num_sta_no_ht = 0;
+ pmlmepriv->num_sta_ht_20mhz = 0;
+
+ pmlmepriv->olbc = false;
+
+ pmlmepriv->olbc_ht = false;
+
+ pmlmepriv->ht_op_mode = 0;
+
+ for (i = 0; i < NUM_STA; i++)
+ pstapriv->sta_aid[i] = NULL;
+
+ pmlmepriv->wps_beacon_ie = NULL;
+ pmlmepriv->wps_probe_resp_ie = NULL;
+ pmlmepriv->wps_assoc_resp_ie = NULL;
+
+ /* for ACL */
+ INIT_LIST_HEAD(&pacl_list->acl_node_q.queue);
+ pacl_list->num = 0;
+ pacl_list->mode = 0;
+ for (i = 0; i < NUM_ACL; i++) {
+ INIT_LIST_HEAD(&pacl_list->aclnode[i].list);
+ pacl_list->aclnode[i].valid = false;
+ }
+}
+
+void stop_ap_mode(struct adapter *padapter)
+{
+ struct list_head *phead, *plist;
+ struct rtw_wlan_acl_node *paclnode;
+ struct sta_info *psta = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+ struct __queue *pacl_node_q = &pacl_list->acl_node_q;
+
+ pmlmepriv->update_bcn = false;
+ pmlmeext->bstart_bss = false;
+
+ /* reset and init security priv , this can refine with
+ * rtw_reset_securitypriv
+ */
+ memset((unsigned char *)&padapter->securitypriv, 0, sizeof(struct security_priv));
+ padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
+
+ /* for ACL */
+ spin_lock_bh(&pacl_node_q->lock);
+ phead = get_list_head(pacl_node_q);
+ plist = phead->next;
+ while (phead != plist) {
+ paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
+ plist = plist->next;
+
+ if (paclnode->valid) {
+ paclnode->valid = false;
+
+ list_del_init(&paclnode->list);
+
+ pacl_list->num--;
+ }
+ }
+ spin_unlock_bh(&pacl_node_q->lock);
+
+ DBG_88E("%s, free acl_node_queue, num =%d\n", __func__, pacl_list->num);
+
+ rtw_sta_flush(padapter);
+
+ /* free_assoc_sta_resources */
+ rtw_free_all_stainfo(padapter);
+
+ psta = rtw_get_bcmc_stainfo(padapter);
+ spin_lock_bh(&pstapriv->sta_hash_lock);
+ rtw_free_stainfo(padapter, psta);
+ spin_unlock_bh(&pstapriv->sta_hash_lock);
+
+ rtw_init_bcmc_stainfo(padapter);
+
+ rtw_free_mlme_priv_ie_data(pmlmepriv);
+}
+
+#endif /* CPTCFG_88EU_AP_MODE */
diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c
new file mode 100644
index 0000000..e36a533
--- /dev/null
+++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c
@@ -0,0 +1,1275 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _RTW_CMD_C_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <recv_osdep.h>
+#include <mlme_osdep.h>
+#include <rtw_mlme_ext.h>
+
+/*
+ * Caller and the rtw_cmd_thread can protect cmd_q by spin_lock.
+ * No irqsave is necessary.
+ */
+
+int rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
+{
+ init_completion(&pcmdpriv->cmd_queue_comp);
+ init_completion(&pcmdpriv->terminate_cmdthread_comp);
+
+ _rtw_init_queue(&pcmdpriv->cmd_queue);
+ return _SUCCESS;
+}
+
+/*
+ * Calling Context:
+ *
+ * rtw_enqueue_cmd can only be called between kernel thread,
+ * since only spin_lock is used.
+ *
+ * ISR/Call-Back functions can't call this sub-function.
+ */
+
+static int _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj)
+{
+ unsigned long irqL;
+
+ if (!obj)
+ goto exit;
+
+ spin_lock_irqsave(&queue->lock, irqL);
+
+ list_add_tail(&obj->list, &queue->queue);
+
+ spin_unlock_irqrestore(&queue->lock, irqL);
+
+exit:
+
+ return _SUCCESS;
+}
+
+struct cmd_obj *rtw_dequeue_cmd(struct __queue *queue)
+{
+ unsigned long irqL;
+ struct cmd_obj *obj;
+
+ spin_lock_irqsave(&queue->lock, irqL);
+ obj = list_first_entry_or_null(&queue->queue, struct cmd_obj, list);
+ if (obj)
+ list_del_init(&obj->list);
+ spin_unlock_irqrestore(&queue->lock, irqL);
+
+ return obj;
+}
+
+static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
+{
+ u8 bAllow = false; /* set to true to allow enqueuing cmd when hw_init_completed is false */
+
+ /* To decide allow or not */
+ if ((pcmdpriv->padapter->pwrctrlpriv.bHWPwrPindetect) &&
+ (!pcmdpriv->padapter->registrypriv.usbss_enable)) {
+ if (cmd_obj->cmdcode == _Set_Drv_Extra_CMD_) {
+ struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)cmd_obj->parmbuf;
+
+ if (pdrvextra_cmd_parm->ec_id == POWER_SAVING_CTRL_WK_CID)
+ bAllow = true;
+ }
+ }
+
+ if (cmd_obj->cmdcode == _SetChannelPlan_CMD_)
+ bAllow = true;
+
+ if ((!pcmdpriv->padapter->hw_init_completed && !bAllow) ||
+ !pcmdpriv->cmdthd_running) /* com_thread not running */
+ return _FAIL;
+ return _SUCCESS;
+}
+
+u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
+{
+ int res = _FAIL;
+ struct adapter *padapter = pcmdpriv->padapter;
+
+ if (!cmd_obj)
+ goto exit;
+
+ cmd_obj->padapter = padapter;
+
+ res = rtw_cmd_filter(pcmdpriv, cmd_obj);
+ if (res == _FAIL) {
+ rtw_free_cmd_obj(cmd_obj);
+ goto exit;
+ }
+
+ res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj);
+
+ if (res == _SUCCESS)
+ complete(&pcmdpriv->cmd_queue_comp);
+
+exit:
+
+ return res;
+}
+
+void rtw_free_cmd_obj(struct cmd_obj *pcmd)
+{
+ if ((pcmd->cmdcode != _JoinBss_CMD_) && (pcmd->cmdcode != _CreateBss_CMD_)) {
+ /* free parmbuf in cmd_obj */
+ kfree(pcmd->parmbuf);
+ }
+
+ if (pcmd->rsp) {
+ if (pcmd->rspsz != 0) {
+ /* free rsp in cmd_obj */
+ kfree(pcmd->rsp);
+ }
+ }
+
+ /* free cmd_obj */
+ kfree(pcmd);
+}
+
+int rtw_cmd_thread(void *context)
+{
+ u8 ret;
+ struct cmd_obj *pcmd;
+ u8 (*cmd_hdl)(struct adapter *padapter, u8 *pbuf);
+ void (*pcmd_callback)(struct adapter *dev, struct cmd_obj *pcmd);
+ struct adapter *padapter = context;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ allow_signal(SIGTERM);
+
+ pcmdpriv->cmdthd_running = true;
+ complete(&pcmdpriv->terminate_cmdthread_comp);
+
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
+ ("start r871x %s !!!!\n", __func__));
+
+ while (1) {
+ if (wait_for_completion_interruptible(&pcmdpriv->cmd_queue_comp))
+ break;
+
+ if (padapter->bDriverStopped ||
+ padapter->bSurpriseRemoved) {
+ DBG_88E("%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n",
+ __func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__);
+ break;
+ }
+_next:
+ if (padapter->bDriverStopped ||
+ padapter->bSurpriseRemoved) {
+ DBG_88E("%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n",
+ __func__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__);
+ break;
+ }
+
+ pcmd = rtw_dequeue_cmd(&pcmdpriv->cmd_queue);
+ if (!pcmd)
+ continue;
+
+ if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) {
+ pcmd->res = H2C_DROPPED;
+ } else {
+ if (pcmd->cmdcode < ARRAY_SIZE(wlancmds)) {
+ cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
+
+ if (cmd_hdl) {
+ ret = cmd_hdl(pcmd->padapter, pcmd->parmbuf);
+ pcmd->res = ret;
+ }
+ } else {
+ pcmd->res = H2C_PARAMETERS_ERROR;
+ }
+
+ cmd_hdl = NULL;
+ }
+
+ /* call callback function for post-processed */
+ if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) {
+ pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback;
+ if (!pcmd_callback) {
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("mlme_cmd_hdl(): pcmd_callback = 0x%p, cmdcode = 0x%x\n", pcmd_callback, pcmd->cmdcode));
+ rtw_free_cmd_obj(pcmd);
+ } else {
+ /* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!= NULL) */
+ pcmd_callback(pcmd->padapter, pcmd);/* need conider that free cmd_obj in rtw_cmd_callback */
+ }
+ } else {
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("%s: cmdcode = 0x%x callback not defined!\n", __func__, pcmd->cmdcode));
+ rtw_free_cmd_obj(pcmd);
+ }
+
+ if (signal_pending(current))
+ flush_signals(current);
+
+ goto _next;
+ }
+ pcmdpriv->cmdthd_running = false;
+
+ /* free all cmd_obj resources */
+ while ((pcmd = rtw_dequeue_cmd(&pcmdpriv->cmd_queue)))
+ rtw_free_cmd_obj(pcmd);
+
+ complete(&pcmdpriv->terminate_cmdthread_comp);
+
+ complete_and_exit(NULL, 0);
+}
+
+/*
+ * rtw_sitesurvey_cmd(~)
+ * ### NOTE:#### (!!!!)
+ * MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE
+ * LOCKED pmlmepriv->lock
+ */
+u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid, int ssid_num,
+ struct rtw_ieee80211_channel *ch, int ch_num)
+{
+ u8 res = _FAIL;
+ struct cmd_obj *ph2c;
+ struct sitesurvey_parm *psurveyPara;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED))
+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1);
+
+ ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
+ if (!ph2c)
+ return _FAIL;
+
+ psurveyPara = kzalloc(sizeof(*psurveyPara), GFP_ATOMIC);
+ if (!psurveyPara) {
+ kfree(ph2c);
+ return _FAIL;
+ }
+
+ rtw_free_network_queue(padapter, false);
+
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("%s: flush network queue\n", __func__));
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, _SiteSurvey_CMD_);
+
+ psurveyPara->scan_mode = pmlmepriv->scan_mode;
+
+ /* prepare ssid list */
+ if (ssid) {
+ int i;
+
+ for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) {
+ if (ssid[i].ssid_length) {
+ memcpy(&psurveyPara->ssid[i], &ssid[i], sizeof(struct ndis_802_11_ssid));
+ psurveyPara->ssid_num++;
+ }
+ }
+ }
+
+ /* prepare channel list */
+ if (ch) {
+ int i;
+
+ for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
+ if (ch[i].hw_value && !(ch[i].flags & RTW_IEEE80211_CHAN_DISABLED)) {
+ memcpy(&psurveyPara->ch[i], &ch[i], sizeof(struct rtw_ieee80211_channel));
+ psurveyPara->ch_num++;
+ }
+ }
+ }
+
+ set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+
+ if (res == _SUCCESS) {
+ mod_timer(&pmlmepriv->scan_to_timer,
+ jiffies + msecs_to_jiffies(SCANNING_TIMEOUT));
+
+ led_control_8188eu(padapter, LED_CTL_SITE_SURVEY);
+
+ pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */
+ } else {
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
+ }
+
+ return res;
+}
+
+void rtw_readtssi_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd)
+{
+ kfree(pcmd->parmbuf);
+ kfree(pcmd);
+}
+
+u8 rtw_createbss_cmd(struct adapter *padapter)
+{
+ struct cmd_obj *pcmd;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network;
+ u8 res = _SUCCESS;
+
+ led_control_8188eu(padapter, LED_CTL_START_TO_LINK);
+
+ if (pmlmepriv->assoc_ssid.ssid_length == 0)
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for Any SSid:%s\n", pmlmepriv->assoc_ssid.ssid));
+ else
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, (" createbss for SSid:%s\n", pmlmepriv->assoc_ssid.ssid));
+
+ pcmd = kzalloc(sizeof(*pcmd), GFP_ATOMIC);
+ if (!pcmd) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ INIT_LIST_HEAD(&pcmd->list);
+ pcmd->cmdcode = _CreateBss_CMD_;
+ pcmd->parmbuf = (unsigned char *)pdev_network;
+ pcmd->cmdsz = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network);
+ pcmd->rsp = NULL;
+ pcmd->rspsz = 0;
+ pdev_network->Length = pcmd->cmdsz;
+ res = rtw_enqueue_cmd(pcmdpriv, pcmd);
+exit:
+
+ return res;
+}
+
+u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork)
+{
+ u8 res = _SUCCESS;
+ uint t_len = 0;
+ struct wlan_bssid_ex *psecnetwork;
+ struct cmd_obj *pcmd;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct qos_priv *pqospriv = &pmlmepriv->qospriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
+ enum ndis_802_11_network_infra ndis_network_mode = pnetwork->network.InfrastructureMode;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ led_control_8188eu(padapter, LED_CTL_START_TO_LINK);
+
+ if (pmlmepriv->assoc_ssid.ssid_length == 0)
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+Join cmd: Any SSid\n"));
+ else
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+Join cmd: SSid =[%s]\n", pmlmepriv->assoc_ssid.ssid));
+
+ pcmd = kzalloc(sizeof(*pcmd), GFP_ATOMIC);
+ if (!pcmd) {
+ res = _FAIL;
+ goto exit;
+ }
+ /* for ies is fix buf size */
+ t_len = sizeof(struct wlan_bssid_ex);
+
+ /* for hidden ap to set fw_state here */
+ if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE)) {
+ switch (ndis_network_mode) {
+ case Ndis802_11IBSS:
+ set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
+ break;
+ case Ndis802_11Infrastructure:
+ set_fwstate(pmlmepriv, WIFI_STATION_STATE);
+ break;
+ case Ndis802_11APMode:
+ case Ndis802_11AutoUnknown:
+ case Ndis802_11InfrastructureMax:
+ break;
+ }
+ }
+
+ psecnetwork = (struct wlan_bssid_ex *)&psecuritypriv->sec_bss;
+ if (!psecnetwork) {
+ kfree(pcmd);
+
+ res = _FAIL;
+
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
+ ("%s :psecnetwork == NULL!!!\n", __func__));
+
+ goto exit;
+ }
+
+ memset(psecnetwork, 0, t_len);
+
+ memcpy(psecnetwork, &pnetwork->network, get_wlan_bssid_ex_sz(&pnetwork->network));
+
+ psecuritypriv->authenticator_ie[0] = (unsigned char)psecnetwork->ie_length;
+
+ if (psecnetwork->ie_length - 12 < 255)
+ memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->ies[12], psecnetwork->ie_length - 12);
+ else
+ memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->ies[12], 255);
+
+ psecnetwork->ie_length = 0;
+ /* Added by Albert 2009/02/18 */
+ /* If the driver wants to use the bssid to create the connection. */
+ /* If not, we have to copy the connecting AP's MAC address to it so that */
+ /* the driver just has the bssid information for PMKIDList searching. */
+
+ if (!pmlmepriv->assoc_by_bssid)
+ memcpy(&pmlmepriv->assoc_bssid[0], &pnetwork->network.MacAddress[0], ETH_ALEN);
+
+ psecnetwork->ie_length = rtw_restruct_sec_ie(padapter, &pnetwork->network.ies[0], &psecnetwork->ies[0], pnetwork->network.ie_length);
+
+ pqospriv->qos_option = 0;
+
+ if (pregistrypriv->wmm_enable) {
+ u32 tmp_len;
+
+ tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.ies[0], &psecnetwork->ies[0], pnetwork->network.ie_length, psecnetwork->ie_length);
+
+ if (psecnetwork->ie_length != tmp_len) {
+ psecnetwork->ie_length = tmp_len;
+ pqospriv->qos_option = 1; /* There is WMM IE in this corresp. beacon */
+ } else {
+ pqospriv->qos_option = 0;/* There is no WMM IE in this corresp. beacon */
+ }
+ }
+
+ phtpriv->ht_option = false;
+ if (pregistrypriv->ht_enable) {
+ /*
+ * Added by Albert 2010/06/23
+ * For the WEP mode, we will use the bg mode to do
+ * the connection to avoid some IOT issue.
+ * Especially for Realtek 8192u SoftAP.
+ */
+ if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) &&
+ (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) &&
+ (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) {
+ /* rtw_restructure_ht_ie */
+ rtw_restructure_ht_ie(padapter, &pnetwork->network.ies[0], &psecnetwork->ies[0],
+ pnetwork->network.ie_length, &psecnetwork->ie_length);
+ }
+ }
+
+ pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.ies, pnetwork->network.ie_length);
+
+ if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_TENDA)
+ padapter->pwrctrlpriv.smart_ps = 0;
+ else
+ padapter->pwrctrlpriv.smart_ps = padapter->registrypriv.smart_ps;
+
+ DBG_88E("%s: smart_ps =%d\n", __func__, padapter->pwrctrlpriv.smart_ps);
+
+ pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);/* get cmdsz before endian conversion */
+
+ INIT_LIST_HEAD(&pcmd->list);
+ pcmd->cmdcode = _JoinBss_CMD_;
+ pcmd->parmbuf = (unsigned char *)psecnetwork;
+ pcmd->rsp = NULL;
+ pcmd->rspsz = 0;
+
+ res = rtw_enqueue_cmd(pcmdpriv, pcmd);
+
+exit:
+
+ return res;
+}
+
+u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueue) /* for sta_mode */
+{
+ struct cmd_obj *cmdobj = NULL;
+ struct disconnect_parm *param = NULL;
+ struct cmd_priv *cmdpriv = &padapter->cmdpriv;
+ u8 res = _SUCCESS;
+
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+%s\n", __func__));
+
+ /* prepare cmd parameter */
+ param = kzalloc(sizeof(*param), GFP_ATOMIC);
+ if (!param) {
+ res = _FAIL;
+ goto exit;
+ }
+ param->deauth_timeout_ms = deauth_timeout_ms;
+
+ if (enqueue) {
+ /* need enqueue, prepare cmd_obj and enqueue */
+ cmdobj = kzalloc(sizeof(*cmdobj), GFP_ATOMIC);
+ if (!cmdobj) {
+ res = _FAIL;
+ kfree(param);
+ goto exit;
+ }
+ init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_);
+ res = rtw_enqueue_cmd(cmdpriv, cmdobj);
+ } else {
+ /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
+ if (disconnect_hdl(padapter, (u8 *)param) != H2C_SUCCESS)
+ res = _FAIL;
+ kfree(param);
+ }
+
+exit:
+
+ return res;
+}
+
+u8 rtw_setopmode_cmd(struct adapter *padapter, enum ndis_802_11_network_infra networktype)
+{
+ struct cmd_obj *ph2c;
+ struct setopmode_parm *psetop;
+
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ ph2c = kzalloc(sizeof(*ph2c), GFP_KERNEL);
+ psetop = kzalloc(sizeof(*psetop), GFP_KERNEL);
+ if (!ph2c || !psetop) {
+ kfree(ph2c);
+ kfree(psetop);
+ return false;
+ }
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
+ psetop->mode = (u8)networktype;
+
+ return rtw_enqueue_cmd(pcmdpriv, ph2c);
+}
+
+u8 rtw_setstakey_cmd(struct adapter *padapter, u8 *psta, u8 unicast_key)
+{
+ struct cmd_obj *ph2c;
+ struct set_stakey_parm *psetstakey_para;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ struct set_stakey_rsp *psetstakey_rsp = NULL;
+
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct sta_info *sta = (struct sta_info *)psta;
+
+ ph2c = kzalloc(sizeof(*ph2c), GFP_KERNEL);
+ psetstakey_para = kzalloc(sizeof(*psetstakey_para), GFP_KERNEL);
+ psetstakey_rsp = kzalloc(sizeof(*psetstakey_rsp), GFP_KERNEL);
+
+ if (!ph2c || !psetstakey_para || !psetstakey_rsp) {
+ kfree(ph2c);
+ kfree(psetstakey_para);
+ kfree(psetstakey_rsp);
+ return _FAIL;
+ }
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
+ ph2c->rsp = (u8 *)psetstakey_rsp;
+ ph2c->rspsz = sizeof(struct set_stakey_rsp);
+
+ ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
+
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
+ psetstakey_para->algorithm = (unsigned char)psecuritypriv->dot11PrivacyAlgrthm;
+ else
+ GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, false);
+
+ if (unicast_key)
+ memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16);
+ else
+ memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16);
+
+ /* jeff: set this because at least sw key is ready */
+ padapter->securitypriv.busetkipkey = true;
+
+ return rtw_enqueue_cmd(pcmdpriv, ph2c);
+}
+
+u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry, u8 enqueue)
+{
+ struct cmd_obj *ph2c;
+ struct set_stakey_parm *psetstakey_para;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ struct set_stakey_rsp *psetstakey_rsp = NULL;
+ struct sta_info *sta = (struct sta_info *)psta;
+ u8 res = _SUCCESS;
+
+ if (!enqueue) {
+ clear_cam_entry(padapter, entry);
+ } else {
+ ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ psetstakey_para = kzalloc(sizeof(*psetstakey_para), GFP_ATOMIC);
+ if (!psetstakey_para) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ psetstakey_rsp = kzalloc(sizeof(*psetstakey_rsp), GFP_ATOMIC);
+ if (!psetstakey_rsp) {
+ kfree(ph2c);
+ kfree(psetstakey_para);
+ res = _FAIL;
+ goto exit;
+ }
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
+ ph2c->rsp = (u8 *)psetstakey_rsp;
+ ph2c->rspsz = sizeof(struct set_stakey_rsp);
+
+ ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
+
+ psetstakey_para->algorithm = _NO_PRIVACY_;
+
+ psetstakey_para->id = entry;
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+ }
+exit:
+
+ return res;
+}
+
+u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr)
+{
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ struct cmd_obj *ph2c;
+ struct addBaReq_parm *paddbareq_parm;
+ u8 res = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ paddbareq_parm = kzalloc(sizeof(*paddbareq_parm), GFP_ATOMIC);
+ if (!paddbareq_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ paddbareq_parm->tid = tid;
+ memcpy(paddbareq_parm->addr, addr, ETH_ALEN);
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, _AddBAReq_CMD_);
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+
+exit:
+
+ return res;
+}
+
+u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter)
+{
+ struct cmd_obj *ph2c;
+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ u8 res = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
+ if (!pdrvextra_cmd_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;
+ pdrvextra_cmd_parm->type_size = 0;
+ pdrvextra_cmd_parm->pbuf = (u8 *)padapter;
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+exit:
+ return res;
+}
+
+u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue)
+{
+ struct cmd_obj *pcmdobj;
+ struct SetChannelPlan_param *setChannelPlan_param;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ u8 res = _SUCCESS;
+
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+%s\n", __func__));
+
+ /* check input parameter */
+ if (!rtw_is_channel_plan_valid(chplan)) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ /* prepare cmd parameter */
+ setChannelPlan_param = kzalloc(sizeof(*setChannelPlan_param), GFP_KERNEL);
+ if (!setChannelPlan_param) {
+ res = _FAIL;
+ goto exit;
+ }
+ setChannelPlan_param->channel_plan = chplan;
+
+ if (enqueue) {
+ /* need enqueue, prepare cmd_obj and enqueue */
+ pcmdobj = kzalloc(sizeof(*pcmdobj), GFP_KERNEL);
+ if (!pcmdobj) {
+ kfree(setChannelPlan_param);
+ res = _FAIL;
+ goto exit;
+ }
+
+ init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelPlan_param, _SetChannelPlan_CMD_);
+ res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
+ } else {
+ /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
+ if (set_chplan_hdl(padapter, (unsigned char *)setChannelPlan_param) != H2C_SUCCESS)
+ res = _FAIL;
+
+ kfree(setChannelPlan_param);
+ }
+
+ if (res == _SUCCESS)
+ padapter->mlmepriv.ChannelPlan = chplan;
+
+exit:
+
+ return res;
+}
+
+static void traffic_status_watchdog(struct adapter *padapter)
+{
+ u8 bEnterPS;
+ u8 bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false;
+ u8 bHigherBusyTraffic = false, bHigherBusyRxTraffic = false, bHigherBusyTxTraffic = false;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ /* */
+ /* Determine if our traffic is busy now */
+ /* */
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 100 ||
+ pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 100) {
+ bBusyTraffic = true;
+
+ if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
+ bRxBusyTraffic = true;
+ else
+ bTxBusyTraffic = true;
+ }
+
+ /* Higher Tx/Rx data. */
+ if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
+ pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) {
+ bHigherBusyTraffic = true;
+
+ if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
+ bHigherBusyRxTraffic = true;
+ else
+ bHigherBusyTxTraffic = true;
+ }
+
+ /* check traffic for powersaving. */
+ if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
+ (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2))
+ bEnterPS = false;
+ else
+ bEnterPS = true;
+
+ /* LeisurePS only work in infra mode. */
+ if (bEnterPS)
+ LPS_Enter(padapter);
+ else
+ LPS_Leave(padapter);
+ } else {
+ LPS_Leave(padapter);
+ }
+
+ pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;
+ pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;
+ pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
+ pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
+ pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;
+ pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;
+ pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
+ pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
+ pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
+}
+
+static void dynamic_chk_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz)
+{
+ struct mlme_priv *pmlmepriv;
+
+ padapter = (struct adapter *)pbuf;
+ pmlmepriv = &padapter->mlmepriv;
+
+#ifdef CPTCFG_88EU_AP_MODE
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ expire_timeout_chk(padapter);
+#endif
+
+ linked_status_chk(padapter);
+ traffic_status_watchdog(padapter);
+
+ rtw_hal_dm_watchdog(padapter);
+}
+
+static void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type)
+{
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ u8 mstatus;
+
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
+ check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
+ return;
+
+ switch (lps_ctrl_type) {
+ case LPS_CTRL_SCAN:
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ /* connect */
+ LPS_Leave(padapter);
+ }
+ break;
+ case LPS_CTRL_JOINBSS:
+ LPS_Leave(padapter);
+ break;
+ case LPS_CTRL_CONNECT:
+ mstatus = 1;/* connect */
+ /* Reset LPS Setting */
+ padapter->pwrctrlpriv.LpsIdleCount = 0;
+ rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
+ break;
+ case LPS_CTRL_DISCONNECT:
+ mstatus = 0;/* disconnect */
+ LPS_Leave(padapter);
+ rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
+ break;
+ case LPS_CTRL_SPECIAL_PACKET:
+ pwrpriv->DelayLPSLastTimeStamp = jiffies;
+ LPS_Leave(padapter);
+ break;
+ case LPS_CTRL_LEAVE:
+ LPS_Leave(padapter);
+ break;
+ default:
+ break;
+ }
+}
+
+u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue)
+{
+ struct cmd_obj *ph2c;
+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ u8 res = _SUCCESS;
+
+ if (enqueue) {
+ ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
+ if (!pdrvextra_cmd_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID;
+ pdrvextra_cmd_parm->type_size = lps_ctrl_type;
+ pdrvextra_cmd_parm->pbuf = NULL;
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+ } else {
+ lps_ctrl_wk_hdl(padapter, lps_ctrl_type);
+ }
+
+exit:
+
+ return res;
+}
+
+static void rpt_timer_setting_wk_hdl(struct adapter *padapter, u16 min_time)
+{
+ rtw_hal_set_hwreg(padapter, HW_VAR_RPT_TIMER_SETTING, (u8 *)(&min_time));
+}
+
+u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 min_time)
+{
+ struct cmd_obj *ph2c;
+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ u8 res = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
+ if (!pdrvextra_cmd_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm->ec_id = RTP_TIMER_CFG_WK_CID;
+ pdrvextra_cmd_parm->type_size = min_time;
+ pdrvextra_cmd_parm->pbuf = NULL;
+ init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+exit:
+
+ return res;
+}
+
+static void antenna_select_wk_hdl(struct adapter *padapter, u8 antenna)
+{
+ rtw_hal_set_hwreg(padapter, HW_VAR_ANTENNA_DIVERSITY_SELECT, (u8 *)(&antenna));
+}
+
+u8 rtw_antenna_select_cmd(struct adapter *padapter, u8 antenna, u8 enqueue)
+{
+ struct cmd_obj *ph2c;
+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ u8 support_ant_div;
+ u8 res = _SUCCESS;
+
+ rtw_hal_get_def_var(padapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &support_ant_div);
+ if (!support_ant_div)
+ return res;
+
+ if (enqueue) {
+ ph2c = kzalloc(sizeof(*ph2c), GFP_KERNEL);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_KERNEL);
+ if (!pdrvextra_cmd_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm->ec_id = ANT_SELECT_WK_CID;
+ pdrvextra_cmd_parm->type_size = antenna;
+ pdrvextra_cmd_parm->pbuf = NULL;
+ init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+ } else {
+ antenna_select_wk_hdl(padapter, antenna);
+ }
+exit:
+
+ return res;
+}
+
+u8 rtw_ps_cmd(struct adapter *padapter)
+{
+ struct cmd_obj *ppscmd;
+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ ppscmd = kzalloc(sizeof(*ppscmd), GFP_ATOMIC);
+ pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
+ if (!ppscmd || !pdrvextra_cmd_parm) {
+ kfree(ppscmd);
+ kfree(pdrvextra_cmd_parm);
+ return _FAIL;
+ }
+
+ pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
+ pdrvextra_cmd_parm->pbuf = NULL;
+ init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
+
+ return rtw_enqueue_cmd(pcmdpriv, ppscmd);
+}
+
+#ifdef CPTCFG_88EU_AP_MODE
+
+static void rtw_chk_hi_queue_hdl(struct adapter *padapter)
+{
+ int cnt = 0;
+ struct sta_info *psta_bmc;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ psta_bmc = rtw_get_bcmc_stainfo(padapter);
+ if (!psta_bmc)
+ return;
+
+ if (psta_bmc->sleepq_len == 0) {
+ u8 val = 0;
+
+ rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
+
+ while (!val) {
+ msleep(100);
+
+ cnt++;
+
+ if (cnt > 10)
+ break;
+
+ rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
+ }
+
+ if (cnt <= 10) {
+ pstapriv->tim_bitmap &= ~BIT(0);
+ pstapriv->sta_dz_bitmap &= ~BIT(0);
+
+ update_beacon(padapter, _TIM_IE_, NULL, false);
+ } else { /* re check again */
+ rtw_chk_hi_queue_cmd(padapter);
+ }
+ }
+}
+
+u8 rtw_chk_hi_queue_cmd(struct adapter *padapter)
+{
+ struct cmd_obj *ph2c;
+ struct drvextra_cmd_parm *pdrvextra_cmd_parm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ u8 res = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(*ph2c), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
+ if (!pdrvextra_cmd_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
+ pdrvextra_cmd_parm->type_size = 0;
+ pdrvextra_cmd_parm->pbuf = NULL;
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, _Set_Drv_Extra_CMD_);
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+exit:
+ return res;
+}
+#endif
+
+u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf)
+{
+ struct drvextra_cmd_parm *pdrvextra_cmd;
+
+ if (!pbuf)
+ return H2C_PARAMETERS_ERROR;
+
+ pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
+
+ switch (pdrvextra_cmd->ec_id) {
+ case DYNAMIC_CHK_WK_CID:
+ dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type_size);
+ break;
+ case POWER_SAVING_CTRL_WK_CID:
+ rtw_ps_processor(padapter);
+ break;
+ case LPS_CTRL_WK_CID:
+ lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size);
+ break;
+ case RTP_TIMER_CFG_WK_CID:
+ rpt_timer_setting_wk_hdl(padapter, pdrvextra_cmd->type_size);
+ break;
+ case ANT_SELECT_WK_CID:
+ antenna_select_wk_hdl(padapter, pdrvextra_cmd->type_size);
+ break;
+#ifdef CPTCFG_88EU_AP_MODE
+ case CHECK_HIQ_WK_CID:
+ rtw_chk_hi_queue_hdl(padapter);
+ break;
+#endif /* CPTCFG_88EU_AP_MODE */
+ default:
+ break;
+ }
+
+ if (pdrvextra_cmd->pbuf && pdrvextra_cmd->type_size > 0)
+ kfree(pdrvextra_cmd->pbuf);
+
+ return H2C_SUCCESS;
+}
+
+void rtw_survey_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ if (pcmd->res == H2C_DROPPED) {
+ /* TODO: cancel timer and do timeout handler directly... */
+ /* need to make timeout handlerOS independent */
+ mod_timer(&pmlmepriv->scan_to_timer,
+ jiffies + msecs_to_jiffies(1));
+ } else if (pcmd->res != H2C_SUCCESS) {
+ mod_timer(&pmlmepriv->scan_to_timer,
+ jiffies + msecs_to_jiffies(1));
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ********Error: MgntActrtw_set_802_11_bssid_LIST_SCAN Fail ************\n\n."));
+ }
+
+ /* free cmd */
+ rtw_free_cmd_obj(pcmd);
+}
+
+void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ if (pcmd->res != H2C_SUCCESS) {
+ spin_lock_bh(&pmlmepriv->lock);
+ set_fwstate(pmlmepriv, _FW_LINKED);
+ spin_unlock_bh(&pmlmepriv->lock);
+
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n ***Error: disconnect_cmd_callback Fail ***\n."));
+ return;
+ }
+
+ /* free cmd */
+ rtw_free_cmd_obj(pcmd);
+}
+
+void rtw_joinbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ if (pcmd->res == H2C_DROPPED) {
+ /* TODO: cancel timer and do timeout handler directly... */
+ /* need to make timeout handlerOS independent */
+ mod_timer(&pmlmepriv->assoc_timer,
+ jiffies + msecs_to_jiffies(1));
+ } else if (pcmd->res != H2C_SUCCESS) {
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("********Error:rtw_select_and_join_from_scanned_queue Wait Sema Fail ************\n"));
+ mod_timer(&pmlmepriv->assoc_timer,
+ jiffies + msecs_to_jiffies(1));
+ }
+
+ rtw_free_cmd_obj(pcmd);
+}
+
+void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
+{
+ struct sta_info *psta = NULL;
+ struct wlan_network *pwlan = NULL;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
+ struct wlan_network *tgt_network = &pmlmepriv->cur_network;
+
+ if (pcmd->res != H2C_SUCCESS) {
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
+ ("\n **** Error: %s Fail ****\n\n.", __func__));
+ mod_timer(&pmlmepriv->assoc_timer,
+ jiffies + msecs_to_jiffies(1));
+ }
+
+ del_timer_sync(&pmlmepriv->assoc_timer);
+
+ spin_lock_bh(&pmlmepriv->lock);
+
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+ psta = rtw_get_stainfo(&padapter->stapriv, pnetwork->MacAddress);
+ if (!psta) {
+ psta = rtw_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress);
+ if (!psta) {
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nCan't alloc sta_info when createbss_cmd_callback\n"));
+ goto createbss_cmd_fail;
+ }
+ }
+
+ rtw_indicate_connect(padapter);
+ } else {
+ pwlan = rtw_alloc_network(pmlmepriv);
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+ if (!pwlan) {
+ pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
+ if (!pwlan) {
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\n Error: can't get pwlan in rtw_joinbss_event_callback\n"));
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+ goto createbss_cmd_fail;
+ }
+ pwlan->last_scanned = jiffies;
+ } else {
+ list_add_tail(&pwlan->list,
+ &pmlmepriv->scanned_queue.queue);
+ }
+
+ pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork);
+ memcpy(&pwlan->network, pnetwork, pnetwork->Length);
+
+ memcpy(&tgt_network->network, pnetwork, (get_wlan_bssid_ex_sz(pnetwork)));
+
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+ /* we will set _FW_LINKED when there is one more sat to
+ * join us (rtw_stassoc_event_callback)
+ */
+ }
+
+createbss_cmd_fail:
+
+ spin_unlock_bh(&pmlmepriv->lock);
+
+ rtw_free_cmd_obj(pcmd);
+}
+
+void rtw_setstaKey_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd)
+{
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)(pcmd->rsp);
+ struct sta_info *psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr);
+
+ if (!psta) {
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: %s => can't get sta_info\n\n", __func__));
+ goto exit;
+ }
+exit:
+ rtw_free_cmd_obj(pcmd);
+}
+
+void rtw_setassocsta_cmdrsp_callback(struct adapter *padapter, struct cmd_obj *pcmd)
+{
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf);
+ struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *)(pcmd->rsp);
+ struct sta_info *psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr);
+
+ if (!psta) {
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nERROR: %s => can't get sta_info\n\n", __func__));
+ goto exit;
+ }
+
+ psta->aid = passocsta_rsp->cam_id;
+ psta->mac_id = passocsta_rsp->cam_id;
+
+ spin_lock_bh(&pmlmepriv->lock);
+
+ set_fwstate(pmlmepriv, _FW_LINKED);
+ spin_unlock_bh(&pmlmepriv->lock);
+
+exit:
+ rtw_free_cmd_obj(pcmd);
+}
diff --git a/drivers/staging/rtl8188eu/core/rtw_debug.c b/drivers/staging/rtl8188eu/core/rtw_debug.c
new file mode 100644
index 0000000..6c2fe1a
--- /dev/null
+++ b/drivers/staging/rtl8188eu/core/rtw_debug.c
@@ -0,0 +1,181 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _RTW_DEBUG_C_
+
+#include <rtw_debug.h>
+#include <usb_ops_linux.h>
+
+int proc_get_drv_version(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ int len = 0;
+
+ len += snprintf(page + len, count - len, "%s\n", DRIVERVERSION);
+
+ *eof = 1;
+ return len;
+}
+
+int proc_get_write_reg(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ *eof = 1;
+ return 0;
+}
+
+int proc_set_write_reg(struct file *file, const char __user *buffer,
+ unsigned long count, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ char tmp[32];
+ u32 addr, val, len;
+
+ if (count < 3) {
+ DBG_88E("argument size is less than 3\n");
+ return -EFAULT;
+ }
+
+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
+ int num = sscanf(tmp, "%x %x %x", &addr, &val, &len);
+
+ if (num != 3) {
+ DBG_88E("invalid write_reg parameter!\n");
+ return count;
+ }
+ switch (len) {
+ case 1:
+ usb_write8(padapter, addr, (u8)val);
+ break;
+ case 2:
+ usb_write16(padapter, addr, (u16)val);
+ break;
+ case 4:
+ usb_write32(padapter, addr, val);
+ break;
+ default:
+ DBG_88E("error write length =%d", len);
+ break;
+ }
+ }
+ return count;
+}
+
+static u32 proc_get_read_addr = 0xeeeeeeee;
+static u32 proc_get_read_len = 0x4;
+
+int proc_get_read_reg(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+
+ int len = 0;
+
+ if (proc_get_read_addr == 0xeeeeeeee) {
+ *eof = 1;
+ return len;
+ }
+
+ switch (proc_get_read_len) {
+ case 1:
+ len += snprintf(page + len, count - len, "usb_read8(0x%x)=0x%x\n", proc_get_read_addr, usb_read8(padapter, proc_get_read_addr));
+ break;
+ case 2:
+ len += snprintf(page + len, count - len, "usb_read16(0x%x)=0x%x\n", proc_get_read_addr, usb_read16(padapter, proc_get_read_addr));
+ break;
+ case 4:
+ len += snprintf(page + len, count - len, "usb_read32(0x%x)=0x%x\n", proc_get_read_addr, usb_read32(padapter, proc_get_read_addr));
+ break;
+ default:
+ len += snprintf(page + len, count - len, "error read length=%d\n", proc_get_read_len);
+ break;
+ }
+
+ *eof = 1;
+ return len;
+}
+
+int proc_set_read_reg(struct file *file, const char __user *buffer,
+ unsigned long count, void *data)
+{
+ char tmp[16];
+ u32 addr, len;
+
+ if (count < 2) {
+ DBG_88E("argument size is less than 2\n");
+ return -EFAULT;
+ }
+
+ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
+ int num = sscanf(tmp, "%x %x", &addr, &len);
+
+ if (num != 2) {
+ DBG_88E("invalid read_reg parameter!\n");
+ return count;
+ }
+
+ proc_get_read_addr = addr;
+
+ proc_get_read_len = len;
+ }
+
+ return count;
+}
+
+int proc_get_adapter_state(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ int len = 0;
+
+ len += snprintf(page + len, count - len, "bSurpriseRemoved=%d, bDriverStopped=%d\n",
+ padapter->bSurpriseRemoved, padapter->bDriverStopped);
+
+ *eof = 1;
+ return len;
+}
+
+int proc_get_best_channel(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data)
+{
+ struct net_device *dev = data;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ int len = 0;
+ u32 i, best_channel_24G = 1, index_24G = 0;
+
+ for (i = 0; pmlmeext->channel_set[i].ChannelNum != 0; i++) {
+ if (pmlmeext->channel_set[i].ChannelNum == 1)
+ index_24G = i;
+ }
+
+ for (i = 0; pmlmeext->channel_set[i].ChannelNum != 0; i++) {
+ /* 2.4G */
+ if (pmlmeext->channel_set[i].ChannelNum == 6) {
+ if (pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_24G].rx_count) {
+ index_24G = i;
+ best_channel_24G = pmlmeext->channel_set[i].ChannelNum;
+ }
+ }
+
+ /* debug */
+ len += snprintf(page + len, count - len, "The rx cnt of channel %3d = %d\n",
+ pmlmeext->channel_set[i].ChannelNum, pmlmeext->channel_set[i].rx_count);
+ }
+
+ len += snprintf(page + len, count - len, "best_channel_24G = %d\n", best_channel_24G);
+
+ *eof = 1;
+ return len;
+}
diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c
new file mode 100644
index 0000000..02c476f
--- /dev/null
+++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c
@@ -0,0 +1,900 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _RTW_EFUSE_C_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <rtw_efuse.h>
+#include <usb_ops_linux.h>
+#include <rtl8188e_hal.h>
+#include <rtw_iol.h>
+
+#define REG_EFUSE_CTRL 0x0030
+#define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */
+
+enum{
+ VOLTAGE_V25 = 0x03,
+ LDOE25_SHIFT = 28,
+ };
+
+/*
+ * When we want to enable write operation, we should change to pwr on state.
+ * When we stop write, we should switch to 500k mode and disable LDO 2.5V.
+ */
+void efuse_power_switch(struct adapter *pAdapter, u8 write, u8 pwrstate)
+{
+ u8 tempval;
+ u16 tmpv16;
+
+ if (pwrstate) {
+ usb_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
+
+ /* 1.2V Power: From VDDON with Power Cut(0x0000h[15]), default valid */
+ tmpv16 = usb_read16(pAdapter, REG_SYS_ISO_CTRL);
+ if (!(tmpv16 & PWC_EV12V)) {
+ tmpv16 |= PWC_EV12V;
+ usb_write16(pAdapter, REG_SYS_ISO_CTRL, tmpv16);
+ }
+ /* Reset: 0x0000h[28], default valid */
+ tmpv16 = usb_read16(pAdapter, REG_SYS_FUNC_EN);
+ if (!(tmpv16 & FEN_ELDR)) {
+ tmpv16 |= FEN_ELDR;
+ usb_write16(pAdapter, REG_SYS_FUNC_EN, tmpv16);
+ }
+
+ /* Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */
+ tmpv16 = usb_read16(pAdapter, REG_SYS_CLKR);
+ if ((!(tmpv16 & LOADER_CLK_EN)) || (!(tmpv16 & ANA8M))) {
+ tmpv16 |= (LOADER_CLK_EN | ANA8M);
+ usb_write16(pAdapter, REG_SYS_CLKR, tmpv16);
+ }
+
+ if (write) {
+ /* Enable LDO 2.5V before read/write action */
+ tempval = usb_read8(pAdapter, EFUSE_TEST + 3);
+ tempval &= 0x0F;
+ tempval |= (VOLTAGE_V25 << 4);
+ usb_write8(pAdapter, EFUSE_TEST + 3, (tempval | 0x80));
+ }
+ } else {
+ usb_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
+
+ if (write) {
+ /* Disable LDO 2.5V after read/write action */
+ tempval = usb_read8(pAdapter, EFUSE_TEST + 3);
+ usb_write8(pAdapter, EFUSE_TEST + 3, (tempval & 0x7F));
+ }
+ }
+}
+
+static void
+efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8 *pbuf)
+{
+ u8 *efuseTbl = NULL;
+ u8 rtemp8;
+ u16 eFuse_Addr = 0;
+ u8 offset, wren;
+ u16 i, j;
+ u16 **eFuseWord = NULL;
+ u16 efuse_utilized = 0;
+ u8 u1temp = 0;
+ void **tmp = NULL;
+
+ efuseTbl = kzalloc(EFUSE_MAP_LEN_88E, GFP_KERNEL);
+ if (!efuseTbl)
+ return;
+
+ tmp = kcalloc(EFUSE_MAX_SECTION_88E,
+ sizeof(void *) + EFUSE_MAX_WORD_UNIT * sizeof(u16),
+ GFP_KERNEL);
+ if (!tmp) {
+ DBG_88E("%s: alloc eFuseWord fail!\n", __func__);
+ goto eFuseWord_failed;
+ }
+ for (i = 0; i < EFUSE_MAX_SECTION_88E; i++)
+ tmp[i] = ((char *)(tmp + EFUSE_MAX_SECTION_88E)) + i * EFUSE_MAX_WORD_UNIT * sizeof(u16);
+ eFuseWord = (u16 **)tmp;
+
+ /* 0. Refresh efuse init map as all oxFF. */
+ for (i = 0; i < EFUSE_MAX_SECTION_88E; i++)
+ for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++)
+ eFuseWord[i][j] = 0xFFFF;
+
+ /* */
+ /* 1. Read the first byte to check if efuse is empty!!! */
+ /* */
+ /* */
+ rtemp8 = *(phymap + eFuse_Addr);
+ if (rtemp8 != 0xFF) {
+ efuse_utilized++;
+ eFuse_Addr++;
+ } else {
+ DBG_88E("EFUSE is empty efuse_Addr-%d efuse_data =%x\n", eFuse_Addr, rtemp8);
+ goto exit;
+ }
+
+ /* */
+ /* 2. Read real efuse content. Filter PG header and every section data. */
+ /* */
+ while ((rtemp8 != 0xFF) && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
+ /* Check PG header for section num. */
+ if ((rtemp8 & 0x1F) == 0x0F) { /* extended header */
+ u1temp = (rtemp8 & 0xE0) >> 5;
+ rtemp8 = *(phymap + eFuse_Addr);
+ if ((rtemp8 & 0x0F) == 0x0F) {
+ eFuse_Addr++;
+ rtemp8 = *(phymap + eFuse_Addr);
+
+ if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E))
+ eFuse_Addr++;
+ continue;
+ } else {
+ offset = ((rtemp8 & 0xF0) >> 1) | u1temp;
+ wren = rtemp8 & 0x0F;
+ eFuse_Addr++;
+ }
+ } else {
+ offset = (rtemp8 >> 4) & 0x0f;
+ wren = rtemp8 & 0x0f;
+ }
+
+ if (offset < EFUSE_MAX_SECTION_88E) {
+ /* Get word enable value from PG header */
+ for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
+ /* Check word enable condition in the section */
+ if (!(wren & 0x01)) {
+ rtemp8 = *(phymap + eFuse_Addr);
+ eFuse_Addr++;
+ efuse_utilized++;
+ eFuseWord[offset][i] = (rtemp8 & 0xff);
+ if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
+ break;
+ rtemp8 = *(phymap + eFuse_Addr);
+ eFuse_Addr++;
+ efuse_utilized++;
+ eFuseWord[offset][i] |= (((u16)rtemp8 << 8) & 0xff00);
+
+ if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
+ break;
+ }
+ wren >>= 1;
+ }
+ }
+ /* Read next PG header */
+ rtemp8 = *(phymap + eFuse_Addr);
+
+ if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
+ efuse_utilized++;
+ eFuse_Addr++;
+ }
+ }
+
+ /* */
+ /* 3. Collect 16 sections and 4 word unit into Efuse map. */
+ /* */
+ for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) {
+ for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) {
+ efuseTbl[(i * 8) + (j * 2)] = (eFuseWord[i][j] & 0xff);
+ efuseTbl[(i * 8) + ((j * 2) + 1)] = ((eFuseWord[i][j] >> 8) & 0xff);
+ }
+ }
+
+ /* */
+ /* 4. Copy from Efuse map to output pointer memory!!! */
+ /* */
+ for (i = 0; i < _size_byte; i++)
+ pbuf[i] = efuseTbl[_offset + i];
+
+ /* */
+ /* 5. Calculate Efuse utilization. */
+ /* */
+
+exit:
+ kfree(eFuseWord);
+
+eFuseWord_failed:
+ kfree(efuseTbl);
+}
+
+static void efuse_read_phymap_from_txpktbuf(
+ struct adapter *adapter,
+ int bcnhead, /* beacon head, where FW store len(2-byte) and efuse physical map. */
+ u8 *content, /* buffer to store efuse physical map */
+ u16 *size /* for efuse content: the max byte to read. will update to byte read */
+ )
+{
+ u16 dbg_addr = 0;
+ unsigned long start = 0;
+ u8 reg_0x143 = 0;
+ u32 lo32 = 0, hi32 = 0;
+ u16 len = 0, count = 0;
+ int i = 0;
+ u16 limit = *size;
+
+ u8 *pos = content;
+
+ if (bcnhead < 0) /* if not valid */
+ bcnhead = usb_read8(adapter, REG_TDECTRL + 1);
+
+ DBG_88E("%s bcnhead:%d\n", __func__, bcnhead);
+
+ usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
+
+ dbg_addr = bcnhead * 128 / 8; /* 8-bytes addressing */
+
+ while (1) {
+ usb_write16(adapter, REG_PKTBUF_DBG_ADDR, dbg_addr + i);
+
+ usb_write8(adapter, REG_TXPKTBUF_DBG, 0);
+ start = jiffies;
+ while (!(reg_0x143 = usb_read8(adapter, REG_TXPKTBUF_DBG)) &&
+ jiffies_to_msecs(jiffies - start) < 1000) {
+ DBG_88E("%s polling reg_0x143:0x%02x, reg_0x106:0x%02x\n", __func__, reg_0x143, usb_read8(adapter, 0x106));
+ usleep_range(1000, 2000);
+ }
+
+ lo32 = usb_read32(adapter, REG_PKTBUF_DBG_DATA_L);
+ hi32 = usb_read32(adapter, REG_PKTBUF_DBG_DATA_H);
+
+ if (i == 0) {
+ u8 lenc[2];
+ u16 lenbak, aaabak;
+ u16 aaa;
+
+ lenc[0] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L);
+ lenc[1] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L + 1);
+
+ aaabak = le16_to_cpup((__le16 *)lenc);
+ lenbak = le16_to_cpu(*((__le16 *)lenc));
+ aaa = le16_to_cpup((__le16 *)&lo32);
+ len = le16_to_cpu(*((__le16 *)&lo32));
+
+ limit = min_t(u16, len - 2, limit);
+
+ DBG_88E("%s len:%u, lenbak:%u, aaa:%u, aaabak:%u\n", __func__, len, lenbak, aaa, aaabak);
+
+ memcpy(pos, ((u8 *)&lo32) + 2, (limit >= count + 2) ? 2 : limit - count);
+ count += (limit >= count + 2) ? 2 : limit - count;
+ pos = content + count;
+
+ } else {
+ memcpy(pos, ((u8 *)&lo32), (limit >= count + 4) ? 4 : limit - count);
+ count += (limit >= count + 4) ? 4 : limit - count;
+ pos = content + count;
+ }
+
+ if (limit > count && len - 2 > count) {
+ memcpy(pos, (u8 *)&hi32, (limit >= count + 4) ? 4 : limit - count);
+ count += (limit >= count + 4) ? 4 : limit - count;
+ pos = content + count;
+ }
+
+ if (limit <= count || len - 2 <= count)
+ break;
+ i++;
+ }
+ usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, DISABLE_TRXPKT_BUF_ACCESS);
+ DBG_88E("%s read count:%u\n", __func__, count);
+ *size = count;
+}
+
+static s32 iol_read_efuse(struct adapter *padapter, u8 txpktbuf_bndy, u16 offset, u16 size_byte, u8 *logical_map)
+{
+ s32 status = _FAIL;
+ u8 physical_map[512];
+ u16 size = 512;
+
+ usb_write8(padapter, REG_TDECTRL + 1, txpktbuf_bndy);
+ memset(physical_map, 0xFF, 512);
+ usb_write8(padapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
+ status = iol_execute(padapter, CMD_READ_EFUSE_MAP);
+ if (status == _SUCCESS)
+ efuse_read_phymap_from_txpktbuf(padapter, txpktbuf_bndy, physical_map, &size);
+ efuse_phymap_to_logical(physical_map, offset, size_byte, logical_map);
+ return status;
+}
+
+void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf)
+{
+ if (rtw_iol_applied(Adapter)) {
+ rtw_hal_power_on(Adapter);
+ iol_mode_enable(Adapter, 1);
+ iol_read_efuse(Adapter, 0, _offset, _size_byte, pbuf);
+ iol_mode_enable(Adapter, 0);
+ }
+}
+
+u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data)
+{
+ u16 tmpaddr = 0;
+ u16 start_addr = efuse_addr;
+ u8 badworden = 0x0F;
+ u8 tmpdata[8];
+
+ memset(tmpdata, 0xff, PGPKT_DATA_SIZE);
+
+ if (!(word_en & BIT(0))) {
+ tmpaddr = start_addr;
+ efuse_OneByteWrite(pAdapter, start_addr++, data[0]);
+ efuse_OneByteWrite(pAdapter, start_addr++, data[1]);
+
+ efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[0]);
+ efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[1]);
+ if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1]))
+ badworden &= (~BIT(0));
+ }
+ if (!(word_en & BIT(1))) {
+ tmpaddr = start_addr;
+ efuse_OneByteWrite(pAdapter, start_addr++, data[2]);
+ efuse_OneByteWrite(pAdapter, start_addr++, data[3]);
+
+ efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[2]);
+ efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[3]);
+ if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3]))
+ badworden &= (~BIT(1));
+ }
+ if (!(word_en & BIT(2))) {
+ tmpaddr = start_addr;
+ efuse_OneByteWrite(pAdapter, start_addr++, data[4]);
+ efuse_OneByteWrite(pAdapter, start_addr++, data[5]);
+
+ efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[4]);
+ efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[5]);
+ if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5]))
+ badworden &= (~BIT(2));
+ }
+ if (!(word_en & BIT(3))) {
+ tmpaddr = start_addr;
+ efuse_OneByteWrite(pAdapter, start_addr++, data[6]);
+ efuse_OneByteWrite(pAdapter, start_addr++, data[7]);
+
+ efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[6]);
+ efuse_OneByteRead(pAdapter, tmpaddr + 1, &tmpdata[7]);
+ if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7]))
+ badworden &= (~BIT(3));
+ }
+ return badworden;
+}
+
+static u16 Efuse_GetCurrentSize(struct adapter *pAdapter)
+{
+ u16 efuse_addr = 0;
+ u8 hoffset = 0, hworden = 0;
+ u8 efuse_data, word_cnts = 0;
+
+ rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
+
+ while (efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) &&
+ AVAILABLE_EFUSE_ADDR(efuse_addr)) {
+ if (efuse_data != 0xFF) {
+ if ((efuse_data & 0x1F) == 0x0F) { /* extended header */
+ hoffset = efuse_data;
+ efuse_addr++;
+ efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data);
+ if ((efuse_data & 0x0F) == 0x0F) {
+ efuse_addr++;
+ continue;
+ } else {
+ hoffset = ((hoffset & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
+ hworden = efuse_data & 0x0F;
+ }
+ } else {
+ hoffset = (efuse_data >> 4) & 0x0F;
+ hworden = efuse_data & 0x0F;
+ }
+ word_cnts = Efuse_CalculateWordCnts(hworden);
+ /* read next header */
+ efuse_addr = efuse_addr + (word_cnts * 2) + 1;
+ } else {
+ break;
+ }
+ }
+
+ rtw_hal_set_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
+
+ return efuse_addr;
+}
+
+int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data)
+{
+ u8 ReadState = PG_STATE_HEADER;
+ int bContinual = true;
+ int bDataEmpty = true;
+ u8 efuse_data, word_cnts = 0;
+ u16 efuse_addr = 0;
+ u8 hoffset = 0, hworden = 0;
+ u8 tmpidx = 0;
+ u8 tmpdata[8];
+ u8 tmp_header = 0;
+
+ if (!data)
+ return false;
+ if (offset > EFUSE_MAX_SECTION_88E)
+ return false;
+
+ memset(data, 0xff, sizeof(u8) * PGPKT_DATA_SIZE);
+ memset(tmpdata, 0xff, sizeof(u8) * PGPKT_DATA_SIZE);
+
+ /* <Roger_TODO> Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */
+ /* Skip dummy parts to prevent unexpected data read from Efuse. */
+ /* By pass right now. 2009.02.19. */
+ while (bContinual && AVAILABLE_EFUSE_ADDR(efuse_addr)) {
+ /* Header Read ------------- */
+ if (ReadState & PG_STATE_HEADER) {
+ if (efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) && (efuse_data != 0xFF)) {
+ if (EXT_HEADER(efuse_data)) {
+ tmp_header = efuse_data;
+ efuse_addr++;
+ efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data);
+ if (!ALL_WORDS_DISABLED(efuse_data)) {
+ hoffset = ((tmp_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
+ hworden = efuse_data & 0x0F;
+ } else {
+ DBG_88E("Error, All words disabled\n");
+ efuse_addr++;
+ continue;
+ }
+ } else {
+ hoffset = (efuse_data >> 4) & 0x0F;
+ hworden = efuse_data & 0x0F;
+ }
+ word_cnts = Efuse_CalculateWordCnts(hworden);
+ bDataEmpty = true;
+
+ if (hoffset == offset) {
+ for (tmpidx = 0; tmpidx < word_cnts * 2; tmpidx++) {
+ if (efuse_OneByteRead(pAdapter, efuse_addr + 1 + tmpidx, &efuse_data)) {
+ tmpdata[tmpidx] = efuse_data;
+ if (efuse_data != 0xff)
+ bDataEmpty = false;
+ }
+ }
+ if (!bDataEmpty) {
+ ReadState = PG_STATE_DATA;
+ } else {/* read next header */
+ efuse_addr = efuse_addr + (word_cnts * 2) + 1;
+ ReadState = PG_STATE_HEADER;
+ }
+ } else {/* read next header */
+ efuse_addr = efuse_addr + (word_cnts * 2) + 1;
+ ReadState = PG_STATE_HEADER;
+ }
+ } else {
+ bContinual = false;
+ }
+ } else if (ReadState & PG_STATE_DATA) {
+ /* Data section Read ------------- */
+ efuse_WordEnableDataRead(hworden, tmpdata, data);
+ efuse_addr = efuse_addr + (word_cnts * 2) + 1;
+ ReadState = PG_STATE_HEADER;
+ }
+ }
+
+ if ((data[0] == 0xff) && (data[1] == 0xff) && (data[2] == 0xff) && (data[3] == 0xff) &&
+ (data[4] == 0xff) && (data[5] == 0xff) && (data[6] == 0xff) && (data[7] == 0xff))
+ return false;
+ else
+ return true;
+}
+
+static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, struct pgpkt *pFixPkt, u16 *pAddr)
+{
+ u8 originaldata[8], badworden = 0;
+ u16 efuse_addr = *pAddr;
+ u32 PgWriteSuccess = 0;
+
+ memset(originaldata, 0xff, 8);
+
+ if (Efuse_PgPacketRead(pAdapter, pFixPkt->offset, originaldata)) {
+ /* check if data exist */
+ badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr + 1, pFixPkt->word_en, originaldata);
+
+ if (badworden != 0xf) { /* write fail */
+ PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pFixPkt->offset, badworden, originaldata);
+
+ if (!PgWriteSuccess)
+ return false;
+ else
+ efuse_addr = Efuse_GetCurrentSize(pAdapter);
+ } else {
+ efuse_addr = efuse_addr + (pFixPkt->word_cnts * 2) + 1;
+ }
+ } else {
+ efuse_addr = efuse_addr + (pFixPkt->word_cnts * 2) + 1;
+ }
+ *pAddr = efuse_addr;
+ return true;
+}
+
+static bool hal_EfusePgPacketWrite2ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
+{
+ bool ret = false;
+ u16 efuse_addr = *pAddr;
+ u16 efuse_max_available_len =
+ EFUSE_REAL_CONTENT_LEN_88E - EFUSE_OOB_PROTECT_BYTES_88E;
+ u8 pg_header = 0, tmp_header = 0, pg_header_temp = 0;
+ u8 repeatcnt = 0;
+
+ while (efuse_addr < efuse_max_available_len) {
+ pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F;
+ efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
+ efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
+
+ while (tmp_header == 0xFF) {
+ if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
+ return false;
+
+ efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
+ efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
+ }
+
+ /* to write ext_header */
+ if (tmp_header == pg_header) {
+ efuse_addr++;
+ pg_header_temp = pg_header;
+ pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en;
+
+ efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
+ efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
+
+ while (tmp_header == 0xFF) {
+ if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
+ return false;
+
+ efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
+ efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
+ }
+
+ if ((tmp_header & 0x0F) == 0x0F) { /* word_en PG fail */
+ if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
+ return false;
+
+ efuse_addr++;
+ continue;
+ } else if (pg_header != tmp_header) { /* offset PG fail */
+ struct pgpkt fixPkt;
+
+ fixPkt.offset = ((pg_header_temp & 0xE0) >> 5) | ((tmp_header & 0xF0) >> 1);
+ fixPkt.word_en = tmp_header & 0x0F;
+ fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en);
+ if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr))
+ return false;
+ } else {
+ ret = true;
+ break;
+ }
+ } else if ((tmp_header & 0x1F) == 0x0F) { /* wrong extended header */
+ efuse_addr += 2;
+ continue;
+ }
+ }
+
+ *pAddr = efuse_addr;
+ return ret;
+}
+
+static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
+{
+ bool ret = false;
+ u8 pg_header = 0, tmp_header = 0;
+ u16 efuse_addr = *pAddr;
+ u8 repeatcnt = 0;
+
+ pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en;
+
+ efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
+ efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
+
+ while (tmp_header == 0xFF) {
+ if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
+ return false;
+ efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
+ efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
+ }
+
+ if (pg_header == tmp_header) {
+ ret = true;
+ } else {
+ struct pgpkt fixPkt;
+
+ fixPkt.offset = (tmp_header >> 4) & 0x0F;
+ fixPkt.word_en = tmp_header & 0x0F;
+ fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en);
+ if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr))
+ return false;
+ }
+
+ *pAddr = efuse_addr;
+ return ret;
+}
+
+static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
+{
+ u16 efuse_addr = *pAddr;
+ u8 badworden = 0;
+ u32 PgWriteSuccess = 0;
+
+ badworden = 0x0f;
+ badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr + 1, pTargetPkt->word_en, pTargetPkt->data);
+ if (badworden == 0x0F) {
+ /* write ok */
+ return true;
+ }
+ /* reorganize other pg packet */
+ PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data);
+ if (!PgWriteSuccess)
+ return false;
+ else
+ return true;
+}
+
+static bool
+hal_EfusePgPacketWriteHeader(
+ struct adapter *pAdapter,
+ u8 efuseType,
+ u16 *pAddr,
+ struct pgpkt *pTargetPkt)
+{
+ bool ret = false;
+
+ if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE)
+ ret = hal_EfusePgPacketWrite2ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt);
+ else
+ ret = hal_EfusePgPacketWrite1ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt);
+
+ return ret;
+}
+
+static bool wordEnMatched(struct pgpkt *pTargetPkt, struct pgpkt *pCurPkt,
+ u8 *pWden)
+{
+ u8 match_word_en = 0x0F; /* default all words are disabled */
+
+ /* check if the same words are enabled both target and current PG packet */
+ if (((pTargetPkt->word_en & BIT(0)) == 0) &&
+ ((pCurPkt->word_en & BIT(0)) == 0))
+ match_word_en &= ~BIT(0); /* enable word 0 */
+ if (((pTargetPkt->word_en & BIT(1)) == 0) &&
+ ((pCurPkt->word_en & BIT(1)) == 0))
+ match_word_en &= ~BIT(1); /* enable word 1 */
+ if (((pTargetPkt->word_en & BIT(2)) == 0) &&
+ ((pCurPkt->word_en & BIT(2)) == 0))
+ match_word_en &= ~BIT(2); /* enable word 2 */
+ if (((pTargetPkt->word_en & BIT(3)) == 0) &&
+ ((pCurPkt->word_en & BIT(3)) == 0))
+ match_word_en &= ~BIT(3); /* enable word 3 */
+
+ *pWden = match_word_en;
+
+ if (match_word_en != 0xf)
+ return true;
+ else
+ return false;
+}
+
+static bool hal_EfuseCheckIfDatafollowed(struct adapter *pAdapter, u8 word_cnts, u16 startAddr)
+{
+ bool ret = false;
+ u8 i, efuse_data;
+
+ for (i = 0; i < (word_cnts * 2); i++) {
+ if (efuse_OneByteRead(pAdapter, (startAddr + i), &efuse_data) && (efuse_data != 0xFF))
+ ret = true;
+ }
+ return ret;
+}
+
+static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
+{
+ bool ret = false;
+ u8 i, efuse_data = 0, cur_header = 0;
+ u8 matched_wden = 0, badworden = 0;
+ u16 startAddr = 0;
+ u16 efuse_max_available_len =
+ EFUSE_REAL_CONTENT_LEN_88E - EFUSE_OOB_PROTECT_BYTES_88E;
+ struct pgpkt curPkt;
+
+ rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr);
+ startAddr %= EFUSE_REAL_CONTENT_LEN;
+
+ while (1) {
+ if (startAddr >= efuse_max_available_len) {
+ ret = false;
+ break;
+ }
+
+ if (efuse_OneByteRead(pAdapter, startAddr, &efuse_data) && (efuse_data != 0xFF)) {
+ if (EXT_HEADER(efuse_data)) {
+ cur_header = efuse_data;
+ startAddr++;
+ efuse_OneByteRead(pAdapter, startAddr, &efuse_data);
+ if (ALL_WORDS_DISABLED(efuse_data)) {
+ ret = false;
+ break;
+ } else {
+ curPkt.offset = ((cur_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
+ curPkt.word_en = efuse_data & 0x0F;
+ }
+ } else {
+ cur_header = efuse_data;
+ curPkt.offset = (cur_header >> 4) & 0x0F;
+ curPkt.word_en = cur_header & 0x0F;
+ }
+
+ curPkt.word_cnts = Efuse_CalculateWordCnts(curPkt.word_en);
+ /* if same header is found but no data followed */
+ /* write some part of data followed by the header. */
+ if ((curPkt.offset == pTargetPkt->offset) &&
+ (!hal_EfuseCheckIfDatafollowed(pAdapter, curPkt.word_cnts, startAddr + 1)) &&
+ wordEnMatched(pTargetPkt, &curPkt, &matched_wden)) {
+ /* Here to write partial data */
+ badworden = Efuse_WordEnableDataWrite(pAdapter, startAddr + 1, matched_wden, pTargetPkt->data);
+ if (badworden != 0x0F) {
+ u32 PgWriteSuccess = 0;
+ /* if write fail on some words, write these bad words again */
+
+ PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data);
+
+ if (!PgWriteSuccess) {
+ ret = false; /* write fail, return */
+ break;
+ }
+ }
+ /* partial write ok, update the target packet for later use */
+ for (i = 0; i < 4; i++) {
+ if ((matched_wden & (0x1 << i)) == 0) /* this word has been written */
+ pTargetPkt->word_en |= (0x1 << i); /* disable the word */
+ }
+ pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
+ }
+ /* read from next header */
+ startAddr = startAddr + (curPkt.word_cnts * 2) + 1;
+ } else {
+ /* not used header, 0xff */
+ *pAddr = startAddr;
+ ret = true;
+ break;
+ }
+ }
+ return ret;
+}
+
+static void hal_EfuseConstructPGPkt(u8 offset, u8 word_en, u8 *pData, struct pgpkt *pTargetPkt)
+{
+ memset((void *)pTargetPkt->data, 0xFF, sizeof(u8) * 8);
+ pTargetPkt->offset = offset;
+ pTargetPkt->word_en = word_en;
+ efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data);
+ pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
+}
+
+bool Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *pData)
+{
+ struct pgpkt targetPkt;
+ u16 startAddr = 0;
+ u8 efuseType = EFUSE_WIFI;
+
+ if (Efuse_GetCurrentSize(pAdapter) >= EFUSE_MAP_LEN_88E)
+ return false;
+
+ hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
+
+ if (!hal_EfusePartialWriteCheck(pAdapter, efuseType, &startAddr, &targetPkt))
+ return false;
+
+ if (!hal_EfusePgPacketWriteHeader(pAdapter, efuseType, &startAddr, &targetPkt))
+ return false;
+
+ if (!hal_EfusePgPacketWriteData(pAdapter, efuseType, &startAddr, &targetPkt))
+ return false;
+
+ return true;
+}
+
+u8 Efuse_CalculateWordCnts(u8 word_en)
+{
+ u8 word_cnts = 0;
+
+ if (!(word_en & BIT(0)))
+ word_cnts++; /* 0 : write enable */
+ if (!(word_en & BIT(1)))
+ word_cnts++;
+ if (!(word_en & BIT(2)))
+ word_cnts++;
+ if (!(word_en & BIT(3)))
+ word_cnts++;
+ return word_cnts;
+}
+
+u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data)
+{
+ u8 tmpidx = 0;
+ u8 result;
+
+ usb_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
+ usb_write8(pAdapter, EFUSE_CTRL + 2, ((u8)((addr >> 8) & 0x03)) |
+ (usb_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC));
+
+ usb_write8(pAdapter, EFUSE_CTRL + 3, 0x72);/* read cmd */
+
+ while (!(0x80 & usb_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100))
+ tmpidx++;
+ if (tmpidx < 100) {
+ *data = usb_read8(pAdapter, EFUSE_CTRL);
+ result = true;
+ } else {
+ *data = 0xff;
+ result = false;
+ }
+ return result;
+}
+
+u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data)
+{
+ u8 tmpidx = 0;
+ u8 result;
+
+ usb_write8(pAdapter, EFUSE_CTRL + 1, (u8)(addr & 0xff));
+ usb_write8(pAdapter, EFUSE_CTRL + 2,
+ (usb_read8(pAdapter, EFUSE_CTRL + 2) & 0xFC) |
+ (u8)((addr >> 8) & 0x03));
+ usb_write8(pAdapter, EFUSE_CTRL, data);/* data */
+
+ usb_write8(pAdapter, EFUSE_CTRL + 3, 0xF2);/* write cmd */
+
+ while ((0x80 & usb_read8(pAdapter, EFUSE_CTRL + 3)) && (tmpidx < 100))
+ tmpidx++;
+
+ if (tmpidx < 100)
+ result = true;
+ else
+ result = false;
+
+ return result;
+}
+
+/* Read allowed word in current efuse section data. */
+void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata)
+{
+ if (!(word_en & BIT(0))) {
+ targetdata[0] = sourdata[0];
+ targetdata[1] = sourdata[1];
+ }
+ if (!(word_en & BIT(1))) {
+ targetdata[2] = sourdata[2];
+ targetdata[3] = sourdata[3];
+ }
+ if (!(word_en & BIT(2))) {
+ targetdata[4] = sourdata[4];
+ targetdata[5] = sourdata[5];
+ }
+ if (!(word_en & BIT(3))) {
+ targetdata[6] = sourdata[6];
+ targetdata[7] = sourdata[7];
+ }
+}
+
+/* Read All Efuse content */
+static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse)
+{
+ efuse_power_switch(pAdapter, false, true);
+
+ efuse_ReadEFuse(pAdapter, efuseType, 0, EFUSE_MAP_LEN_88E, Efuse);
+
+ efuse_power_switch(pAdapter, false, false);
+}
+
+/* Transfer current EFUSE content to shadow init and modify map. */
+void EFUSE_ShadowMapUpdate(struct adapter *pAdapter, u8 efuseType)
+{
+ struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
+
+ if (pEEPROM->bautoload_fail_flag)
+ memset(pEEPROM->efuse_eeprom_data, 0xFF, EFUSE_MAP_LEN_88E);
+ else
+ Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data);
+}
diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
new file mode 100644
index 0000000..cc1b543
--- /dev/null
+++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
@@ -0,0 +1,1076 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _IEEE80211_C
+
+#include <linux/ieee80211.h>
+
+#include <drv_types.h>
+#include <osdep_intf.h>
+#include <ieee80211.h>
+#include <wifi.h>
+#include <osdep_service.h>
+#include <wlan_bssdef.h>
+
+u8 RTW_WPA_OUI_TYPE[] = { 0x00, 0x50, 0xf2, 1 };
+u8 WPA_AUTH_KEY_MGMT_NONE[] = { 0x00, 0x50, 0xf2, 0 };
+u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x50, 0xf2, 1 };
+u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x50, 0xf2, 2 };
+u8 WPA_CIPHER_SUITE_NONE[] = { 0x00, 0x50, 0xf2, 0 };
+u8 WPA_CIPHER_SUITE_WEP40[] = { 0x00, 0x50, 0xf2, 1 };
+u8 WPA_CIPHER_SUITE_TKIP[] = { 0x00, 0x50, 0xf2, 2 };
+u8 WPA_CIPHER_SUITE_WRAP[] = { 0x00, 0x50, 0xf2, 3 };
+u8 WPA_CIPHER_SUITE_CCMP[] = { 0x00, 0x50, 0xf2, 4 };
+u8 WPA_CIPHER_SUITE_WEP104[] = { 0x00, 0x50, 0xf2, 5 };
+
+u16 RSN_VERSION_BSD = 1;
+u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x0f, 0xac, 1 };
+u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x0f, 0xac, 2 };
+u8 RSN_CIPHER_SUITE_NONE[] = { 0x00, 0x0f, 0xac, 0 };
+u8 RSN_CIPHER_SUITE_WEP40[] = { 0x00, 0x0f, 0xac, 1 };
+u8 RSN_CIPHER_SUITE_TKIP[] = { 0x00, 0x0f, 0xac, 2 };
+u8 RSN_CIPHER_SUITE_WRAP[] = { 0x00, 0x0f, 0xac, 3 };
+u8 RSN_CIPHER_SUITE_CCMP[] = { 0x00, 0x0f, 0xac, 4 };
+u8 RSN_CIPHER_SUITE_WEP104[] = { 0x00, 0x0f, 0xac, 5 };
+/* */
+/* for adhoc-master to generate ie and provide supported-rate to fw */
+/* */
+
+static u8 WIFI_CCKRATES[] = {
+ IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK,
+ IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK,
+ IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK,
+ IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK
+};
+
+static u8 WIFI_OFDMRATES[] = {
+ IEEE80211_OFDM_RATE_6MB,
+ IEEE80211_OFDM_RATE_9MB,
+ IEEE80211_OFDM_RATE_12MB,
+ IEEE80211_OFDM_RATE_18MB,
+ IEEE80211_OFDM_RATE_24MB,
+ IEEE80211_OFDM_RATE_36MB,
+ IEEE80211_OFDM_RATE_48MB,
+ IEEE80211_OFDM_RATE_54MB
+};
+
+int rtw_get_bit_value_from_ieee_value(u8 val)
+{
+ static const unsigned char dot11_rate_table[] = {
+ 2, 4, 11, 22, 12, 18, 24, 36, 48,
+ 72, 96, 108, 0}; /* last element must be zero!! */
+ int i = 0;
+
+ while (dot11_rate_table[i] != 0) {
+ if (dot11_rate_table[i] == val)
+ return BIT(i);
+ i++;
+ }
+ return 0;
+}
+
+bool rtw_is_cckrates_included(u8 *rate)
+{
+ while (*rate) {
+ u8 r = *rate & 0x7f;
+
+ if (r == 2 || r == 4 || r == 11 || r == 22)
+ return true;
+ rate++;
+ }
+
+ return false;
+}
+
+bool rtw_is_cckratesonly_included(u8 *rate)
+{
+ while (*rate) {
+ u8 r = *rate & 0x7f;
+
+ if (r != 2 && r != 4 && r != 11 && r != 22)
+ return false;
+ rate++;
+ }
+
+ return true;
+}
+
+int rtw_check_network_type(unsigned char *rate, int ratelen, int channel)
+{
+ /* could be pure B, pure G, or B/G */
+ if (rtw_is_cckratesonly_included(rate))
+ return WIRELESS_11B;
+ else if (rtw_is_cckrates_included(rate))
+ return WIRELESS_11BG;
+ else
+ return WIRELESS_11G;
+}
+
+u8 *rtw_set_fixed_ie(void *pbuf, unsigned int len, void *source,
+ unsigned int *frlen)
+{
+ memcpy(pbuf, source, len);
+ *frlen = *frlen + len;
+ return ((u8 *)pbuf) + len;
+}
+
+/* rtw_set_ie will update frame length */
+u8 *rtw_set_ie
+(
+ u8 *pbuf,
+ int index,
+ uint len,
+ u8 *source,
+ uint *frlen /* frame length */
+)
+{
+ *pbuf = (u8)index;
+
+ *(pbuf + 1) = (u8)len;
+
+ if (len > 0)
+ memcpy((void *)(pbuf + 2), (void *)source, len);
+
+ *frlen = *frlen + (len + 2);
+
+ return pbuf + len + 2;
+}
+
+/*----------------------------------------------------------------------------
+index: the information element id index, limit is the limit for search
+-----------------------------------------------------------------------------*/
+u8 *rtw_get_ie(u8 *pbuf, int index, uint *len, int limit)
+{
+ int tmp, i;
+ u8 *p;
+
+ if (limit < 1)
+ return NULL;
+
+ p = pbuf;
+ i = 0;
+ *len = 0;
+ while (1) {
+ if (*p == index) {
+ *len = *(p + 1);
+ return p;
+ } else {
+ tmp = *(p + 1);
+ p += (tmp + 2);
+ i += (tmp + 2);
+ }
+ if (i >= limit)
+ break;
+ }
+ return NULL;
+}
+
+void rtw_set_supported_rate(u8 *SupportedRates, uint mode)
+{
+ memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
+
+ switch (mode) {
+ case WIRELESS_11B:
+ memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
+ break;
+ case WIRELESS_11G:
+ case WIRELESS_11A:
+ case WIRELESS_11_5N:
+ case WIRELESS_11A_5N:/* Todo: no basic rate for ofdm ? */
+ memcpy(SupportedRates, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
+ break;
+ case WIRELESS_11BG:
+ case WIRELESS_11G_24N:
+ case WIRELESS_11_24N:
+ case WIRELESS_11BG_24N:
+ memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
+ memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
+ break;
+ }
+}
+
+uint rtw_get_rateset_len(u8 *rateset)
+{
+ uint i;
+
+ for (i = 0; i < 13; i++)
+ if (rateset[i] == 0)
+ break;
+ return i;
+}
+
+int rtw_generate_ie(struct registry_priv *pregistrypriv)
+{
+ u8 wireless_mode;
+ int rateLen;
+ uint sz = 0;
+ struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
+ u8 *ie = pdev_network->ies;
+
+ /* timestamp will be inserted by hardware */
+ sz += 8;
+ ie += sz;
+
+ /* beacon interval : 2bytes */
+ *(__le16 *)ie = cpu_to_le16((u16)pdev_network->Configuration.BeaconPeriod);/* BCN_INTERVAL; */
+ sz += 2;
+ ie += 2;
+
+ /* capability info */
+ *(u16 *)ie = 0;
+
+ *(__le16 *)ie |= cpu_to_le16(cap_IBSS);
+
+ if (pregistrypriv->preamble == PREAMBLE_SHORT)
+ *(__le16 *)ie |= cpu_to_le16(cap_ShortPremble);
+
+ if (pdev_network->Privacy)
+ *(__le16 *)ie |= cpu_to_le16(cap_Privacy);
+
+ sz += 2;
+ ie += 2;
+
+ /* SSID */
+ ie = rtw_set_ie(ie, _SSID_IE_, pdev_network->ssid.ssid_length, pdev_network->ssid.ssid, &sz);
+
+ /* supported rates */
+ if (pregistrypriv->wireless_mode == WIRELESS_11ABGN) {
+ if (pdev_network->Configuration.DSConfig > 14)
+ wireless_mode = WIRELESS_11A_5N;
+ else
+ wireless_mode = WIRELESS_11BG_24N;
+ } else {
+ wireless_mode = pregistrypriv->wireless_mode;
+ }
+
+ rtw_set_supported_rate(pdev_network->SupportedRates, wireless_mode);
+
+ rateLen = rtw_get_rateset_len(pdev_network->SupportedRates);
+
+ if (rateLen > 8) {
+ ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, pdev_network->SupportedRates, &sz);
+ /* ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); */
+ } else {
+ ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, pdev_network->SupportedRates, &sz);
+ }
+
+ /* DS parameter set */
+ ie = rtw_set_ie(ie, _DSSET_IE_, 1, (u8 *)&(pdev_network->Configuration.DSConfig), &sz);
+
+ /* IBSS Parameter Set */
+
+ ie = rtw_set_ie(ie, _IBSS_PARA_IE_, 2, (u8 *)&(pdev_network->Configuration.ATIMWindow), &sz);
+
+ if (rateLen > 8)
+ ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz);
+
+ return sz;
+}
+
+unsigned char *rtw_get_wpa_ie(unsigned char *pie, uint *wpa_ie_len, int limit)
+{
+ uint len;
+ u16 val16;
+ __le16 le_tmp;
+ static const unsigned char wpa_oui_type[] = {0x00, 0x50, 0xf2, 0x01};
+ u8 *pbuf = pie;
+ int limit_new = limit;
+
+ while (1) {
+ pbuf = rtw_get_ie(pbuf, _WPA_IE_ID_, &len, limit_new);
+
+ if (pbuf) {
+ /* check if oui matches... */
+ if (memcmp((pbuf + 2), wpa_oui_type, sizeof(wpa_oui_type)))
+ goto check_next_ie;
+
+ /* check version... */
+ memcpy((u8 *)&le_tmp, (pbuf + 6), sizeof(val16));
+
+ val16 = le16_to_cpu(le_tmp);
+ if (val16 != 0x0001)
+ goto check_next_ie;
+ *wpa_ie_len = *(pbuf + 1);
+ return pbuf;
+ } else {
+ *wpa_ie_len = 0;
+ return NULL;
+ }
+
+check_next_ie:
+ limit_new = limit - (pbuf - pie) - 2 - len;
+ if (limit_new <= 0)
+ break;
+ pbuf += (2 + len);
+ }
+ *wpa_ie_len = 0;
+ return NULL;
+}
+
+unsigned char *rtw_get_wpa2_ie(unsigned char *pie, uint *rsn_ie_len, int limit)
+{
+ return rtw_get_ie(pie, _WPA2_IE_ID_, rsn_ie_len, limit);
+}
+
+int rtw_get_wpa_cipher_suite(u8 *s)
+{
+ if (!memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN))
+ return WPA_CIPHER_NONE;
+ if (!memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN))
+ return WPA_CIPHER_WEP40;
+ if (!memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN))
+ return WPA_CIPHER_TKIP;
+ if (!memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN))
+ return WPA_CIPHER_CCMP;
+ if (!memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN))
+ return WPA_CIPHER_WEP104;
+
+ return 0;
+}
+
+int rtw_get_wpa2_cipher_suite(u8 *s)
+{
+ if (!memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN))
+ return WPA_CIPHER_NONE;
+ if (!memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN))
+ return WPA_CIPHER_WEP40;
+ if (!memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN))
+ return WPA_CIPHER_TKIP;
+ if (!memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN))
+ return WPA_CIPHER_CCMP;
+ if (!memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN))
+ return WPA_CIPHER_WEP104;
+
+ return 0;
+}
+
+int rtw_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x)
+{
+ int i, ret = _SUCCESS;
+ int left, count;
+ u8 *pos;
+ u8 SUITE_1X[4] = {0x00, 0x50, 0xf2, 1};
+
+ if (wpa_ie_len <= 0) {
+ /* No WPA IE - fail silently */
+ return _FAIL;
+ }
+
+ if ((*wpa_ie != _WPA_IE_ID_) || (*(wpa_ie + 1) != (u8)(wpa_ie_len - 2)) ||
+ (memcmp(wpa_ie + 2, RTW_WPA_OUI_TYPE, WPA_SELECTOR_LEN)))
+ return _FAIL;
+
+ pos = wpa_ie;
+
+ pos += 8;
+ left = wpa_ie_len - 8;
+
+ /* group_cipher */
+ if (left >= WPA_SELECTOR_LEN) {
+ *group_cipher = rtw_get_wpa_cipher_suite(pos);
+ pos += WPA_SELECTOR_LEN;
+ left -= WPA_SELECTOR_LEN;
+ } else if (left > 0) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie length mismatch, %u too much", __func__, left));
+ return _FAIL;
+ }
+
+ /* pairwise_cipher */
+ if (left >= 2) {
+ count = get_unaligned_le16(pos);
+ pos += 2;
+ left -= 2;
+
+ if (count == 0 || left < count * WPA_SELECTOR_LEN) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie count botch (pairwise), "
+ "count %u left %u", __func__, count, left));
+ return _FAIL;
+ }
+
+ for (i = 0; i < count; i++) {
+ *pairwise_cipher |= rtw_get_wpa_cipher_suite(pos);
+
+ pos += WPA_SELECTOR_LEN;
+ left -= WPA_SELECTOR_LEN;
+ }
+ } else if (left == 1) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie too short (for key mgmt)", __func__));
+ return _FAIL;
+ }
+
+ if (is_8021x) {
+ if (left >= 6) {
+ pos += 2;
+ if (!memcmp(pos, SUITE_1X, 4)) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s : there has 802.1x auth\n", __func__));
+ *is_8021x = 1;
+ }
+ }
+ }
+
+ return ret;
+}
+
+int rtw_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x)
+{
+ int i, ret = _SUCCESS;
+ int left, count;
+ u8 *pos;
+ u8 SUITE_1X[4] = {0x00, 0x0f, 0xac, 0x01};
+
+ if (rsn_ie_len <= 0) {
+ /* No RSN IE - fail silently */
+ return _FAIL;
+ }
+
+ if ((*rsn_ie != _WPA2_IE_ID_) || (*(rsn_ie + 1) != (u8)(rsn_ie_len - 2)))
+ return _FAIL;
+
+ pos = rsn_ie;
+ pos += 4;
+ left = rsn_ie_len - 4;
+
+ /* group_cipher */
+ if (left >= RSN_SELECTOR_LEN) {
+ *group_cipher = rtw_get_wpa2_cipher_suite(pos);
+
+ pos += RSN_SELECTOR_LEN;
+ left -= RSN_SELECTOR_LEN;
+
+ } else if (left > 0) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie length mismatch, %u too much", __func__, left));
+ return _FAIL;
+ }
+
+ /* pairwise_cipher */
+ if (left >= 2) {
+ count = get_unaligned_le16(pos);
+ pos += 2;
+ left -= 2;
+
+ if (count == 0 || left < count * RSN_SELECTOR_LEN) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie count botch (pairwise), "
+ "count %u left %u", __func__, count, left));
+ return _FAIL;
+ }
+
+ for (i = 0; i < count; i++) {
+ *pairwise_cipher |= rtw_get_wpa2_cipher_suite(pos);
+
+ pos += RSN_SELECTOR_LEN;
+ left -= RSN_SELECTOR_LEN;
+ }
+
+ } else if (left == 1) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s: ie too short (for key mgmt)", __func__));
+
+ return _FAIL;
+ }
+
+ if (is_8021x) {
+ if (left >= 6) {
+ pos += 2;
+ if (!memcmp(pos, SUITE_1X, 4)) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s (): there has 802.1x auth\n", __func__));
+ *is_8021x = 1;
+ }
+ }
+ }
+ return ret;
+}
+
+void rtw_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, u8 *wpa_ie, u16 *wpa_len)
+{
+ u8 authmode, sec_idx, i;
+ u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
+ uint cnt;
+
+ /* Search required WPA or WPA2 IE and copy to sec_ie[] */
+
+ cnt = _TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_;
+
+ sec_idx = 0;
+
+ while (cnt < in_len) {
+ authmode = in_ie[cnt];
+
+ if ((authmode == _WPA_IE_ID_) && (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
+ ("\n rtw_get_wpa_ie: sec_idx =%d in_ie[cnt+1]+2 =%d\n",
+ sec_idx, in_ie[cnt + 1] + 2));
+
+ if (wpa_ie) {
+ memcpy(wpa_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
+
+ for (i = 0; i < (in_ie[cnt + 1] + 2); i += 8) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
+ ("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n",
+ wpa_ie[i], wpa_ie[i + 1], wpa_ie[i + 2], wpa_ie[i + 3], wpa_ie[i + 4],
+ wpa_ie[i + 5], wpa_ie[i + 6], wpa_ie[i + 7]));
+ }
+ }
+
+ *wpa_len = in_ie[cnt + 1] + 2;
+ cnt += in_ie[cnt + 1] + 2; /* get next */
+ } else {
+ if (authmode == _WPA2_IE_ID_) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
+ ("\n get_rsn_ie: sec_idx =%d in_ie[cnt+1]+2 =%d\n",
+ sec_idx, in_ie[cnt + 1] + 2));
+
+ if (rsn_ie) {
+ memcpy(rsn_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
+
+ for (i = 0; i < (in_ie[cnt + 1] + 2); i += 8) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
+ ("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n",
+ rsn_ie[i], rsn_ie[i + 1], rsn_ie[i + 2], rsn_ie[i + 3], rsn_ie[i + 4],
+ rsn_ie[i + 5], rsn_ie[i + 6], rsn_ie[i + 7]));
+ }
+ }
+
+ *rsn_len = in_ie[cnt + 1] + 2;
+ cnt += in_ie[cnt + 1] + 2; /* get next */
+ } else {
+ cnt += in_ie[cnt + 1] + 2; /* get next */
+ }
+ }
+ }
+}
+
+u8 rtw_is_wps_ie(u8 *ie_ptr, uint *wps_ielen)
+{
+ u8 match = false;
+ u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
+
+ if (!ie_ptr)
+ return match;
+
+ eid = ie_ptr[0];
+
+ if ((eid == _WPA_IE_ID_) && (!memcmp(&ie_ptr[2], wps_oui, 4))) {
+ *wps_ielen = ie_ptr[1] + 2;
+ match = true;
+ }
+ return match;
+}
+
+/**
+ * rtw_get_wps_ie - Search WPS IE from a series of ies
+ * @in_ie: Address of ies to search
+ * @in_len: Length limit from in_ie
+ * @wps_ie: If not NULL and WPS IE is found, WPS IE will be copied to the buf starting from wps_ie
+ * @wps_ielen: If not NULL and WPS IE is found, will set to the length of the entire WPS IE
+ *
+ * Returns: The address of the WPS IE found, or NULL
+ */
+u8 *rtw_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen)
+{
+ uint cnt;
+ u8 *wpsie_ptr = NULL;
+ u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
+
+ if (wps_ielen)
+ *wps_ielen = 0;
+
+ if (!in_ie || in_len <= 0)
+ return wpsie_ptr;
+
+ cnt = 0;
+
+ while (cnt < in_len) {
+ eid = in_ie[cnt];
+
+ if ((eid == _WPA_IE_ID_) && (!memcmp(&in_ie[cnt + 2], wps_oui, 4))) {
+ wpsie_ptr = &in_ie[cnt];
+
+ if (wps_ie)
+ memcpy(wps_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
+
+ if (wps_ielen)
+ *wps_ielen = in_ie[cnt + 1] + 2;
+
+ cnt += in_ie[cnt + 1] + 2;
+
+ break;
+ } else {
+ cnt += in_ie[cnt + 1] + 2; /* goto next */
+ }
+ }
+ return wpsie_ptr;
+}
+
+/**
+ * rtw_get_wps_attr - Search a specific WPS attribute from a given WPS IE
+ * @wps_ie: Address of WPS IE to search
+ * @wps_ielen: Length limit from wps_ie
+ * @target_attr_id: The attribute ID of WPS attribute to search
+ * @buf_attr: If not NULL and the WPS attribute is found, WPS attribute will be copied to the buf starting from buf_attr
+ * @len_attr: If not NULL and the WPS attribute is found, will set to the length of the entire WPS attribute
+ *
+ * Returns: the address of the specific WPS attribute found, or NULL
+ */
+u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_attr, u32 *len_attr)
+{
+ u8 *attr_ptr = NULL;
+ u8 *target_attr_ptr = NULL;
+ u8 wps_oui[4] = {0x00, 0x50, 0xF2, 0x04};
+
+ if (len_attr)
+ *len_attr = 0;
+
+ if ((wps_ie[0] != _VENDOR_SPECIFIC_IE_) ||
+ (memcmp(wps_ie + 2, wps_oui, 4)))
+ return attr_ptr;
+
+ /* 6 = 1(Element ID) + 1(Length) + 4(WPS OUI) */
+ attr_ptr = wps_ie + 6; /* goto first attr */
+
+ while (attr_ptr - wps_ie < wps_ielen) {
+ /* 4 = 2(Attribute ID) + 2(Length) */
+ u16 attr_id = get_unaligned_be16(attr_ptr);
+ u16 attr_data_len = get_unaligned_be16(attr_ptr + 2);
+ u16 attr_len = attr_data_len + 4;
+
+ if (attr_id == target_attr_id) {
+ target_attr_ptr = attr_ptr;
+ if (buf_attr)
+ memcpy(buf_attr, attr_ptr, attr_len);
+ if (len_attr)
+ *len_attr = attr_len;
+ break;
+ } else {
+ attr_ptr += attr_len; /* goto next */
+ }
+ }
+ return target_attr_ptr;
+}
+
+/**
+ * rtw_get_wps_attr_content - Search a specific WPS attribute content from a given WPS IE
+ * @wps_ie: Address of WPS IE to search
+ * @wps_ielen: Length limit from wps_ie
+ * @target_attr_id: The attribute ID of WPS attribute to search
+ * @buf_content: If not NULL and the WPS attribute is found, WPS attribute content will be copied to the buf starting from buf_content
+ * @len_content: If not NULL and the WPS attribute is found, will set to the length of the WPS attribute content
+ *
+ * Returns: the address of the specific WPS attribute content found, or NULL
+ */
+u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *buf_content, uint *len_content)
+{
+ u8 *attr_ptr;
+ u32 attr_len;
+
+ if (len_content)
+ *len_content = 0;
+
+ attr_ptr = rtw_get_wps_attr(wps_ie, wps_ielen, target_attr_id, NULL, &attr_len);
+
+ if (attr_ptr && attr_len) {
+ if (buf_content)
+ memcpy(buf_content, attr_ptr + 4, attr_len - 4);
+
+ if (len_content)
+ *len_content = attr_len - 4;
+
+ return attr_ptr + 4;
+ }
+
+ return NULL;
+}
+
+static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen,
+ struct rtw_ieee802_11_elems *elems,
+ int show_errors)
+{
+ unsigned int oui;
+
+ /* first 3 bytes in vendor specific information element are the IEEE
+ * OUI of the vendor. The following byte is used a vendor specific
+ * sub-type. */
+ if (elen < 4) {
+ if (show_errors) {
+ DBG_88E("short vendor specific information element ignored (len=%lu)\n",
+ (unsigned long)elen);
+ }
+ return -1;
+ }
+
+ oui = RTW_GET_BE24(pos);
+ switch (oui) {
+ case OUI_MICROSOFT:
+ /* Microsoft/Wi-Fi information elements are further typed and
+ * subtyped */
+ switch (pos[3]) {
+ case 1:
+ /* Microsoft OUI (00:50:F2) with OUI Type 1:
+ * real WPA information element */
+ elems->wpa_ie = pos;
+ elems->wpa_ie_len = elen;
+ break;
+ case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */
+ if (elen < 5) {
+ DBG_88E("short WME information element ignored (len=%lu)\n",
+ (unsigned long)elen);
+ return -1;
+ }
+ switch (pos[4]) {
+ case WME_OUI_SUBTYPE_INFORMATION_ELEMENT:
+ case WME_OUI_SUBTYPE_PARAMETER_ELEMENT:
+ elems->wme = pos;
+ elems->wme_len = elen;
+ break;
+ case WME_OUI_SUBTYPE_TSPEC_ELEMENT:
+ elems->wme_tspec = pos;
+ elems->wme_tspec_len = elen;
+ break;
+ default:
+ DBG_88E("unknown WME information element ignored (subtype=%d len=%lu)\n",
+ pos[4], (unsigned long)elen);
+ return -1;
+ }
+ break;
+ case 4:
+ /* Wi-Fi Protected Setup (WPS) IE */
+ elems->wps_ie = pos;
+ elems->wps_ie_len = elen;
+ break;
+ default:
+ DBG_88E("Unknown Microsoft information element ignored (type=%d len=%lu)\n",
+ pos[3], (unsigned long)elen);
+ return -1;
+ }
+ break;
+
+ case OUI_BROADCOM:
+ switch (pos[3]) {
+ case VENDOR_HT_CAPAB_OUI_TYPE:
+ elems->vendor_ht_cap = pos;
+ elems->vendor_ht_cap_len = elen;
+ break;
+ default:
+ DBG_88E("Unknown Broadcom information element ignored (type=%d len=%lu)\n",
+ pos[3], (unsigned long)elen);
+ return -1;
+ }
+ break;
+ default:
+ DBG_88E("unknown vendor specific information element ignored (vendor OUI %3phC len=%lu)\n",
+ pos, (unsigned long)elen);
+ return -1;
+ }
+ return 0;
+}
+
+/**
+ * ieee802_11_parse_elems - Parse information elements in management frames
+ * @start: Pointer to the start of ies
+ * @len: Length of IE buffer in octets
+ * @elems: Data structure for parsed elements
+ * @show_errors: Whether to show parsing errors in debug log
+ * Returns: Parsing result
+ */
+enum parse_res rtw_ieee802_11_parse_elems(u8 *start, uint len,
+ struct rtw_ieee802_11_elems *elems,
+ int show_errors)
+{
+ uint left = len;
+ u8 *pos = start;
+ int unknown = 0;
+
+ memset(elems, 0, sizeof(*elems));
+
+ while (left >= 2) {
+ u8 id, elen;
+
+ id = *pos++;
+ elen = *pos++;
+ left -= 2;
+
+ if (elen > left) {
+ if (show_errors) {
+ DBG_88E("IEEE 802.11 element parse failed (id=%d elen=%d left=%lu)\n",
+ id, elen, (unsigned long)left);
+ }
+ return ParseFailed;
+ }
+
+ switch (id) {
+ case WLAN_EID_SSID:
+ elems->ssid = pos;
+ elems->ssid_len = elen;
+ break;
+ case WLAN_EID_SUPP_RATES:
+ elems->supp_rates = pos;
+ elems->supp_rates_len = elen;
+ break;
+ case WLAN_EID_FH_PARAMS:
+ elems->fh_params = pos;
+ elems->fh_params_len = elen;
+ break;
+ case WLAN_EID_DS_PARAMS:
+ elems->ds_params = pos;
+ elems->ds_params_len = elen;
+ break;
+ case WLAN_EID_CF_PARAMS:
+ elems->cf_params = pos;
+ elems->cf_params_len = elen;
+ break;
+ case WLAN_EID_TIM:
+ elems->tim = pos;
+ elems->tim_len = elen;
+ break;
+ case WLAN_EID_IBSS_PARAMS:
+ elems->ibss_params = pos;
+ elems->ibss_params_len = elen;
+ break;
+ case WLAN_EID_CHALLENGE:
+ elems->challenge = pos;
+ elems->challenge_len = elen;
+ break;
+ case WLAN_EID_ERP_INFO:
+ elems->erp_info = pos;
+ elems->erp_info_len = elen;
+ break;
+ case WLAN_EID_EXT_SUPP_RATES:
+ elems->ext_supp_rates = pos;
+ elems->ext_supp_rates_len = elen;
+ break;
+ case WLAN_EID_VENDOR_SPECIFIC:
+ if (rtw_ieee802_11_parse_vendor_specific(pos, elen, elems, show_errors))
+ unknown++;
+ break;
+ case WLAN_EID_RSN:
+ elems->rsn_ie = pos;
+ elems->rsn_ie_len = elen;
+ break;
+ case WLAN_EID_PWR_CAPABILITY:
+ elems->power_cap = pos;
+ elems->power_cap_len = elen;
+ break;
+ case WLAN_EID_SUPPORTED_CHANNELS:
+ elems->supp_channels = pos;
+ elems->supp_channels_len = elen;
+ break;
+ case WLAN_EID_MOBILITY_DOMAIN:
+ elems->mdie = pos;
+ elems->mdie_len = elen;
+ break;
+ case WLAN_EID_FAST_BSS_TRANSITION:
+ elems->ftie = pos;
+ elems->ftie_len = elen;
+ break;
+ case WLAN_EID_TIMEOUT_INTERVAL:
+ elems->timeout_int = pos;
+ elems->timeout_int_len = elen;
+ break;
+ case WLAN_EID_HT_CAPABILITY:
+ elems->ht_capabilities = pos;
+ elems->ht_capabilities_len = elen;
+ break;
+ case WLAN_EID_HT_OPERATION:
+ elems->ht_operation = pos;
+ elems->ht_operation_len = elen;
+ break;
+ default:
+ unknown++;
+ if (!show_errors)
+ break;
+ DBG_88E("IEEE 802.11 element parse ignored unknown element (id=%d elen=%d)\n",
+ id, elen);
+ break;
+ }
+ left -= elen;
+ pos += elen;
+ }
+ if (left)
+ return ParseFailed;
+ return unknown ? ParseUnknown : ParseOK;
+}
+
+void rtw_macaddr_cfg(u8 *mac_addr)
+{
+ u8 mac[ETH_ALEN];
+
+ if (!mac_addr)
+ return;
+
+ if (rtw_initmac && mac_pton(rtw_initmac, mac)) {
+ /* Users specify the mac address */
+ ether_addr_copy(mac_addr, mac);
+ } else {
+ /* Use the mac address stored in the Efuse */
+ ether_addr_copy(mac, mac_addr);
+ }
+
+ if (is_broadcast_ether_addr(mac) || is_zero_ether_addr(mac)) {
+ eth_random_addr(mac_addr);
+ DBG_88E("MAC Address from efuse error, assign random one !!!\n");
+ }
+
+ DBG_88E("%s MAC Address = %pM\n", __func__, mac_addr);
+}
+
+static int rtw_get_cipher_info(struct wlan_network *pnetwork)
+{
+ uint wpa_ielen;
+ unsigned char *pbuf;
+ int group_cipher = 0, pairwise_cipher = 0, is8021x = 0;
+ int ret = _FAIL;
+
+ pbuf = rtw_get_wpa_ie(&pnetwork->network.ies[12], &wpa_ielen, pnetwork->network.ie_length - 12);
+
+ if (pbuf && (wpa_ielen > 0)) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: wpa_ielen: %d", __func__, wpa_ielen));
+ if (rtw_parse_wpa_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is8021x) == _SUCCESS) {
+ pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
+ pnetwork->BcnInfo.group_cipher = group_cipher;
+ pnetwork->BcnInfo.is_8021x = is8021x;
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: pnetwork->pairwise_cipher: %d, is_8021x is %d",
+ __func__, pnetwork->BcnInfo.pairwise_cipher, pnetwork->BcnInfo.is_8021x));
+ ret = _SUCCESS;
+ }
+ } else {
+ pbuf = rtw_get_wpa2_ie(&pnetwork->network.ies[12], &wpa_ielen, pnetwork->network.ie_length - 12);
+
+ if (pbuf && (wpa_ielen > 0)) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("get RSN IE\n"));
+ if (rtw_parse_wpa2_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is8021x) == _SUCCESS) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("get RSN IE OK!!!\n"));
+ pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
+ pnetwork->BcnInfo.group_cipher = group_cipher;
+ pnetwork->BcnInfo.is_8021x = is8021x;
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: pnetwork->pairwise_cipher: %d,"
+ "pnetwork->group_cipher is %d, is_8021x is %d", __func__, pnetwork->BcnInfo.pairwise_cipher,
+ pnetwork->BcnInfo.group_cipher, pnetwork->BcnInfo.is_8021x));
+ ret = _SUCCESS;
+ }
+ }
+ }
+
+ return ret;
+}
+
+void rtw_get_bcn_info(struct wlan_network *pnetwork)
+{
+ unsigned short cap = 0;
+ u8 bencrypt = 0;
+ __le16 le_tmp;
+ u16 wpa_len = 0, rsn_len = 0;
+ struct HT_info_element *pht_info = NULL;
+ uint len;
+ unsigned char *p;
+
+ memcpy(&le_tmp, rtw_get_capability_from_ie(pnetwork->network.ies), 2);
+ cap = le16_to_cpu(le_tmp);
+ if (cap & WLAN_CAPABILITY_PRIVACY) {
+ bencrypt = 1;
+ pnetwork->network.Privacy = 1;
+ } else {
+ pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS;
+ }
+ rtw_get_sec_ie(pnetwork->network.ies, pnetwork->network.ie_length, NULL, &rsn_len, NULL, &wpa_len);
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: ssid =%s\n", __func__, pnetwork->network.ssid.ssid));
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: wpa_len =%d rsn_len =%d\n", __func__, wpa_len, rsn_len));
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: ssid =%s\n", __func__, pnetwork->network.ssid.ssid));
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s: wpa_len =%d rsn_len =%d\n", __func__, wpa_len, rsn_len));
+
+ if (rsn_len > 0) {
+ pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA2;
+ } else if (wpa_len > 0) {
+ pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA;
+ } else {
+ if (bencrypt)
+ pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WEP;
+ }
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: pnetwork->encryp_protocol is %x\n",
+ pnetwork->BcnInfo.encryp_protocol));
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_get_bcn_info: pnetwork->encryp_protocol is %x\n",
+ pnetwork->BcnInfo.encryp_protocol));
+ rtw_get_cipher_info(pnetwork);
+
+ /* get bwmode and ch_offset */
+ /* parsing HT_CAP_IE */
+ p = rtw_get_ie(pnetwork->network.ies + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pnetwork->network.ie_length - _FIXED_IE_LENGTH_);
+ if (p && len > 0) {
+ struct ieee80211_ht_cap *ht_cap =
+ (struct ieee80211_ht_cap *)(p + 2);
+
+ pnetwork->BcnInfo.ht_cap_info = le16_to_cpu(ht_cap->cap_info);
+ } else {
+ pnetwork->BcnInfo.ht_cap_info = 0;
+ }
+ /* parsing HT_INFO_IE */
+ p = rtw_get_ie(pnetwork->network.ies + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, pnetwork->network.ie_length - _FIXED_IE_LENGTH_);
+ if (p && len > 0) {
+ pht_info = (struct HT_info_element *)(p + 2);
+ pnetwork->BcnInfo.ht_info_infos_0 = pht_info->infos[0];
+ } else {
+ pnetwork->BcnInfo.ht_info_infos_0 = 0;
+ }
+}
+
+/* show MCS rate, unit: 100Kbps */
+u16 rtw_mcs_rate(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, unsigned char *MCS_rate)
+{
+ u16 max_rate = 0;
+
+ if (rf_type == RF_1T1R) {
+ if (MCS_rate[0] & BIT(7))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 1500 : 1350) : ((short_GI_20) ? 722 : 650);
+ else if (MCS_rate[0] & BIT(6))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 1350 : 1215) : ((short_GI_20) ? 650 : 585);
+ else if (MCS_rate[0] & BIT(5))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : ((short_GI_20) ? 578 : 520);
+ else if (MCS_rate[0] & BIT(4))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : ((short_GI_20) ? 433 : 390);
+ else if (MCS_rate[0] & BIT(3))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : ((short_GI_20) ? 289 : 260);
+ else if (MCS_rate[0] & BIT(2))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 450 : 405) : ((short_GI_20) ? 217 : 195);
+ else if (MCS_rate[0] & BIT(1))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : ((short_GI_20) ? 144 : 130);
+ else if (MCS_rate[0] & BIT(0))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 150 : 135) : ((short_GI_20) ? 72 : 65);
+ } else {
+ if (MCS_rate[1]) {
+ if (MCS_rate[1] & BIT(7))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 3000 : 2700) : ((short_GI_20) ? 1444 : 1300);
+ else if (MCS_rate[1] & BIT(6))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 2700 : 2430) : ((short_GI_20) ? 1300 : 1170);
+ else if (MCS_rate[1] & BIT(5))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 2400 : 2160) : ((short_GI_20) ? 1156 : 1040);
+ else if (MCS_rate[1] & BIT(4))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 1800 : 1620) : ((short_GI_20) ? 867 : 780);
+ else if (MCS_rate[1] & BIT(3))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : ((short_GI_20) ? 578 : 520);
+ else if (MCS_rate[1] & BIT(2))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : ((short_GI_20) ? 433 : 390);
+ else if (MCS_rate[1] & BIT(1))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : ((short_GI_20) ? 289 : 260);
+ else if (MCS_rate[1] & BIT(0))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : ((short_GI_20) ? 144 : 130);
+ } else {
+ if (MCS_rate[0] & BIT(7))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 1500 : 1350) : ((short_GI_20) ? 722 : 650);
+ else if (MCS_rate[0] & BIT(6))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 1350 : 1215) : ((short_GI_20) ? 650 : 585);
+ else if (MCS_rate[0] & BIT(5))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 1200 : 1080) : ((short_GI_20) ? 578 : 520);
+ else if (MCS_rate[0] & BIT(4))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 900 : 810) : ((short_GI_20) ? 433 : 390);
+ else if (MCS_rate[0] & BIT(3))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 600 : 540) : ((short_GI_20) ? 289 : 260);
+ else if (MCS_rate[0] & BIT(2))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 450 : 405) : ((short_GI_20) ? 217 : 195);
+ else if (MCS_rate[0] & BIT(1))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 300 : 270) : ((short_GI_20) ? 144 : 130);
+ else if (MCS_rate[0] & BIT(0))
+ max_rate = (bw_40MHz) ? ((short_GI_40) ? 150 : 135) : ((short_GI_20) ? 72 : 65);
+ }
+ }
+ return max_rate;
+}
diff --git a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c
new file mode 100644
index 0000000..0c12b9b
--- /dev/null
+++ b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c
@@ -0,0 +1,602 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _RTW_IOCTL_SET_C_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <rtw_ioctl_set.h>
+#include <hal_intf.h>
+
+extern void indicate_wx_scan_complete_event(struct adapter *padapter);
+
+u8 rtw_do_join(struct adapter *padapter)
+{
+ struct list_head *plist, *phead;
+ u8 *pibss = NULL;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct __queue *queue = &pmlmepriv->scanned_queue;
+ u8 ret = _SUCCESS;
+
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+ phead = get_list_head(queue);
+ plist = phead->next;
+
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("\n rtw_do_join: phead = %p; plist = %p\n\n\n", phead, plist));
+
+ pmlmepriv->cur_network.join_res = -2;
+
+ set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
+
+ pmlmepriv->pscanned = plist;
+
+ pmlmepriv->to_join = true;
+
+ if (list_empty(&queue->queue)) {
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+
+ /* when set_ssid/set_bssid for rtw_do_join(), but scanning queue is empty */
+ /* we try to issue sitesurvey firstly */
+
+ if (!pmlmepriv->LinkDetectInfo.bBusyTraffic ||
+ pmlmepriv->to_roaming > 0) {
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("rtw_do_join(): site survey if scanned_queue is empty\n."));
+ /* submit site_survey_cmd */
+ ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
+ if (ret != _SUCCESS) {
+ pmlmepriv->to_join = false;
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("rtw_do_join(): site survey return error\n."));
+ }
+ } else {
+ pmlmepriv->to_join = false;
+ ret = _FAIL;
+ }
+
+ goto exit;
+ } else {
+ int select_ret;
+
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+ select_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
+ if (select_ret == _SUCCESS) {
+ pmlmepriv->to_join = false;
+ mod_timer(&pmlmepriv->assoc_timer,
+ jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
+ } else {
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
+ /* submit createbss_cmd to change to a ADHOC_MASTER */
+
+ /* pmlmepriv->lock has been acquired by caller... */
+ struct wlan_bssid_ex *pdev_network = &padapter->registrypriv.dev_network;
+
+ pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
+
+ pibss = padapter->registrypriv.dev_network.MacAddress;
+
+ memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
+
+ rtw_update_registrypriv_dev_network(padapter);
+
+ rtw_generate_random_ibss(pibss);
+
+ if (rtw_createbss_cmd(padapter) != _SUCCESS) {
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("***Error =>do_goin: rtw_createbss_cmd status FAIL***\n "));
+ ret = false;
+ goto exit;
+ }
+ pmlmepriv->to_join = false;
+
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
+ ("***Error => rtw_select_and_join_from_scanned_queue FAIL under STA_Mode***\n "));
+ } else {
+ /* can't associate ; reset under-linking */
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+
+ /* when set_ssid/set_bssid for rtw_do_join(), but there are no desired bss in scanning queue */
+ /* we try to issue sitesurvey firstly */
+ if (!pmlmepriv->LinkDetectInfo.bBusyTraffic ||
+ pmlmepriv->to_roaming > 0) {
+ ret = rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
+ if (ret != _SUCCESS) {
+ pmlmepriv->to_join = false;
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("do_join(): site survey return error\n."));
+ }
+ } else {
+ ret = _FAIL;
+ pmlmepriv->to_join = false;
+ }
+ }
+ }
+ }
+
+exit:
+ return ret;
+}
+
+u8 rtw_set_802_11_bssid(struct adapter *padapter, u8 *bssid)
+{
+ u8 status = _SUCCESS;
+ u32 cur_time = 0;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ DBG_88E_LEVEL(_drv_info_, "set bssid:%pM\n", bssid);
+
+ if ((bssid[0] == 0x00 && bssid[1] == 0x00 && bssid[2] == 0x00 &&
+ bssid[3] == 0x00 && bssid[4] == 0x00 && bssid[5] == 0x00) ||
+ (bssid[0] == 0xFF && bssid[1] == 0xFF && bssid[2] == 0xFF &&
+ bssid[3] == 0xFF && bssid[4] == 0xFF && bssid[5] == 0xFF)) {
+ status = _FAIL;
+ goto exit;
+ }
+
+ spin_lock_bh(&pmlmepriv->lock);
+
+ DBG_88E("Set BSSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv));
+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
+ goto handle_tkip_countermeasure;
+ else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
+ goto release_mlme_lock;
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_bssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"));
+
+ if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid, ETH_ALEN)) {
+ if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE))
+ goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
+ } else {
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("Set BSSID not the same bssid\n"));
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_bssid =%pM\n", (bssid)));
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("cur_bssid =%pM\n", (pmlmepriv->cur_network.network.MacAddress)));
+
+ rtw_disassoc_cmd(padapter, 0, true);
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED))
+ rtw_indicate_disconnect(padapter);
+
+ rtw_free_assoc_resources(padapter);
+
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
+ _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
+ set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
+ }
+ }
+ }
+
+handle_tkip_countermeasure:
+ /* should we add something here...? */
+
+ if (padapter->securitypriv.btkip_countermeasure) {
+ cur_time = jiffies;
+
+ if (cur_time - padapter->securitypriv.btkip_countermeasure_time > 60 * HZ) {
+ padapter->securitypriv.btkip_countermeasure = false;
+ padapter->securitypriv.btkip_countermeasure_time = 0;
+ } else {
+ status = _FAIL;
+ goto release_mlme_lock;
+ }
+ }
+
+ memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN);
+ pmlmepriv->assoc_by_bssid = true;
+
+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
+ pmlmepriv->to_join = true;
+ else
+ status = rtw_do_join(padapter);
+
+release_mlme_lock:
+ spin_unlock_bh(&pmlmepriv->lock);
+
+exit:
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
+ ("%s: status=%d\n", __func__, status));
+
+ return status;
+}
+
+u8 rtw_set_802_11_ssid(struct adapter *padapter, struct ndis_802_11_ssid *ssid)
+{
+ u8 status = _SUCCESS;
+ u32 cur_time = 0;
+
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wlan_network *pnetwork = &pmlmepriv->cur_network;
+
+ DBG_88E_LEVEL(_drv_info_, "set ssid [%s] fw_state=0x%08x\n",
+ ssid->ssid, get_fwstate(pmlmepriv));
+
+ if (!padapter->hw_init_completed) {
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
+ ("set_ssid: hw_init_completed == false =>exit!!!\n"));
+ status = _FAIL;
+ goto exit;
+ }
+
+ spin_lock_bh(&pmlmepriv->lock);
+
+ DBG_88E("Set SSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv));
+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
+ goto handle_tkip_countermeasure;
+ else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
+ goto release_mlme_lock;
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
+ ("set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"));
+
+ if (pmlmepriv->assoc_ssid.ssid_length == ssid->ssid_length &&
+ !memcmp(&pmlmepriv->assoc_ssid.ssid, ssid->ssid, ssid->ssid_length)) {
+ if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
+ ("Set SSID is the same ssid, fw_state = 0x%08x\n",
+ get_fwstate(pmlmepriv)));
+
+ if (!rtw_is_same_ibss(padapter, pnetwork)) {
+ /* if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again */
+ rtw_disassoc_cmd(padapter, 0, true);
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED))
+ rtw_indicate_disconnect(padapter);
+
+ rtw_free_assoc_resources(padapter);
+
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
+ _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
+ set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
+ }
+ } else {
+ goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
+ }
+ } else {
+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_JOINBSS, 1);
+ }
+ } else {
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("Set SSID not the same ssid\n"));
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_ssid =[%s] len = 0x%x\n", ssid->ssid, (unsigned int)ssid->ssid_length));
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("assoc_ssid =[%s] len = 0x%x\n", pmlmepriv->assoc_ssid.ssid, (unsigned int)pmlmepriv->assoc_ssid.ssid_length));
+
+ rtw_disassoc_cmd(padapter, 0, true);
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED))
+ rtw_indicate_disconnect(padapter);
+
+ rtw_free_assoc_resources(padapter);
+
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
+ _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
+ set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
+ }
+ }
+ }
+
+handle_tkip_countermeasure:
+
+ if (padapter->securitypriv.btkip_countermeasure) {
+ cur_time = jiffies;
+
+ if (cur_time - padapter->securitypriv.btkip_countermeasure_time > 60 * HZ) {
+ padapter->securitypriv.btkip_countermeasure = false;
+ padapter->securitypriv.btkip_countermeasure_time = 0;
+ } else {
+ status = _FAIL;
+ goto release_mlme_lock;
+ }
+ }
+
+ memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid));
+ pmlmepriv->assoc_by_bssid = false;
+
+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
+ pmlmepriv->to_join = true;
+ else
+ status = rtw_do_join(padapter);
+
+release_mlme_lock:
+ spin_unlock_bh(&pmlmepriv->lock);
+
+exit:
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
+ ("-%s: status =%d\n", __func__, status));
+ return status;
+}
+
+u8 rtw_set_802_11_infrastructure_mode(struct adapter *padapter,
+ enum ndis_802_11_network_infra networktype)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wlan_network *cur_network = &pmlmepriv->cur_network;
+ enum ndis_802_11_network_infra *pold_state = &cur_network->network.InfrastructureMode;
+
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_notice_,
+ ("+rtw_set_802_11_infrastructure_mode: old =%d new =%d fw_state = 0x%08x\n",
+ *pold_state, networktype, get_fwstate(pmlmepriv)));
+
+ if (*pold_state != networktype) {
+ spin_lock_bh(&pmlmepriv->lock);
+
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, (" change mode!"));
+ /* DBG_88E("change mode, old_mode =%d, new_mode =%d, fw_state = 0x%x\n", *pold_state, networktype, get_fwstate(pmlmepriv)); */
+
+ if (*pold_state == Ndis802_11APMode) {
+ /* change to other mode from Ndis802_11APMode */
+ cur_network->join_res = -1;
+
+#ifdef CPTCFG_88EU_AP_MODE
+ stop_ap_mode(padapter);
+#endif
+ }
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED) ||
+ *pold_state == Ndis802_11IBSS)
+ rtw_disassoc_cmd(padapter, 0, true);
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED) ||
+ check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
+ rtw_free_assoc_resources(padapter);
+
+ if (*pold_state == Ndis802_11Infrastructure ||
+ *pold_state == Ndis802_11IBSS) {
+ if (check_fwstate(pmlmepriv, _FW_LINKED))
+ rtw_indicate_disconnect(padapter); /* will clr Linked_state; before this function, we must have checked whether issue dis-assoc_cmd or not */
+ }
+
+ *pold_state = networktype;
+
+ _clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
+
+ switch (networktype) {
+ case Ndis802_11IBSS:
+ set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
+ break;
+ case Ndis802_11Infrastructure:
+ set_fwstate(pmlmepriv, WIFI_STATION_STATE);
+ break;
+ case Ndis802_11APMode:
+ set_fwstate(pmlmepriv, WIFI_AP_STATE);
+#ifdef CPTCFG_88EU_AP_MODE
+ start_ap_mode(padapter);
+#endif
+ break;
+ case Ndis802_11AutoUnknown:
+ case Ndis802_11InfrastructureMax:
+ break;
+ }
+ spin_unlock_bh(&pmlmepriv->lock);
+ }
+
+ return true;
+}
+
+u8 rtw_set_802_11_disassociate(struct adapter *padapter)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ spin_lock_bh(&pmlmepriv->lock);
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
+ ("MgntActrtw_set_802_11_disassociate: rtw_indicate_disconnect\n"));
+
+ rtw_disassoc_cmd(padapter, 0, true);
+ rtw_indicate_disconnect(padapter);
+ rtw_free_assoc_resources(padapter);
+ rtw_pwr_wakeup(padapter);
+ }
+
+ spin_unlock_bh(&pmlmepriv->lock);
+
+ return true;
+}
+
+u8 rtw_set_802_11_bssid_list_scan(struct adapter *padapter, struct ndis_802_11_ssid *pssid, int ssid_max_num)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ u8 res = true;
+
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("+%s(), fw_state =%x\n", __func__, get_fwstate(pmlmepriv)));
+
+ if (!padapter) {
+ res = false;
+ goto exit;
+ }
+ if (!padapter->hw_init_completed) {
+ res = false;
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n === %s:hw_init_completed == false ===\n", __func__));
+ goto exit;
+ }
+
+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) ||
+ pmlmepriv->LinkDetectInfo.bBusyTraffic) {
+ /* Scan or linking is in progress, do nothing. */
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("%s fail since fw_state = %x\n", __func__, get_fwstate(pmlmepriv)));
+ res = true;
+
+ if (check_fwstate(pmlmepriv,
+ _FW_UNDER_SURVEY | _FW_UNDER_LINKING))
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n###_FW_UNDER_SURVEY|_FW_UNDER_LINKING\n\n"));
+ else
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n###pmlmepriv->sitesurveyctrl.traffic_busy == true\n\n"));
+
+ } else {
+ if (rtw_is_scan_deny(padapter)) {
+ DBG_88E(FUNC_ADPT_FMT": scan deny\n", FUNC_ADPT_ARG(padapter));
+ indicate_wx_scan_complete_event(padapter);
+ return _SUCCESS;
+ }
+
+ spin_lock_bh(&pmlmepriv->lock);
+
+ res = rtw_sitesurvey_cmd(padapter, pssid, ssid_max_num, NULL, 0);
+
+ spin_unlock_bh(&pmlmepriv->lock);
+ }
+exit:
+ return res;
+}
+
+u8 rtw_set_802_11_authentication_mode(struct adapter *padapter, enum ndis_802_11_auth_mode authmode)
+{
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ int res;
+ u8 ret;
+
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
+ ("set_802_11_auth.mode(): mode =%x\n", authmode));
+
+ psecuritypriv->ndisauthtype = authmode;
+
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
+ ("%s:psecuritypriv->ndisauthtype=%d", __func__,
+ psecuritypriv->ndisauthtype));
+
+ if (psecuritypriv->ndisauthtype > 3)
+ psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
+
+ res = rtw_set_auth(padapter, psecuritypriv);
+
+ if (res == _SUCCESS)
+ ret = true;
+ else
+ ret = false;
+
+ return ret;
+}
+
+u8 rtw_set_802_11_add_wep(struct adapter *padapter, struct ndis_802_11_wep *wep)
+{
+ int keyid, res;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ u8 ret = _SUCCESS;
+
+ keyid = wep->KeyIndex & 0x3fffffff;
+
+ if (keyid >= 4) {
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("MgntActrtw_set_802_11_add_wep:keyid>4 =>fail\n"));
+ ret = false;
+ goto exit;
+ }
+
+ switch (wep->KeyLength) {
+ case 5:
+ psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("MgntActrtw_set_802_11_add_wep:wep->KeyLength = 5\n"));
+ break;
+ case 13:
+ psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("MgntActrtw_set_802_11_add_wep:wep->KeyLength = 13\n"));
+ break;
+ default:
+ psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("MgntActrtw_set_802_11_add_wep:wep->KeyLength!= 5 or 13\n"));
+ break;
+ }
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
+ ("rtw_set_802_11_add_wep:before memcpy, wep->KeyLength = 0x%x wep->KeyIndex = 0x%x keyid =%x\n",
+ wep->KeyLength, wep->KeyIndex, keyid));
+
+ memcpy(&psecuritypriv->dot11DefKey[keyid].skey[0],
+ &wep->KeyMaterial, wep->KeyLength);
+
+ psecuritypriv->dot11DefKeylen[keyid] = wep->KeyLength;
+
+ psecuritypriv->dot11PrivacyKeyIndex = keyid;
+
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
+ ("rtw_set_802_11_add_wep:security key material : %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
+ psecuritypriv->dot11DefKey[keyid].skey[0],
+ psecuritypriv->dot11DefKey[keyid].skey[1],
+ psecuritypriv->dot11DefKey[keyid].skey[2],
+ psecuritypriv->dot11DefKey[keyid].skey[3],
+ psecuritypriv->dot11DefKey[keyid].skey[4],
+ psecuritypriv->dot11DefKey[keyid].skey[5],
+ psecuritypriv->dot11DefKey[keyid].skey[6],
+ psecuritypriv->dot11DefKey[keyid].skey[7],
+ psecuritypriv->dot11DefKey[keyid].skey[8],
+ psecuritypriv->dot11DefKey[keyid].skey[9],
+ psecuritypriv->dot11DefKey[keyid].skey[10],
+ psecuritypriv->dot11DefKey[keyid].skey[11],
+ psecuritypriv->dot11DefKey[keyid].skey[12]));
+
+ res = rtw_set_key(padapter, psecuritypriv, keyid, 1);
+
+ if (res == _FAIL)
+ ret = false;
+exit:
+ return ret;
+}
+
+/* Return 0 or 100Kbps */
+u16 rtw_get_cur_max_rate(struct adapter *adapter)
+{
+ int i = 0;
+ u8 *p;
+ u16 rate = 0, max_rate = 0;
+ struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct registry_priv *pregistrypriv = &adapter->registrypriv;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
+ u8 bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0;
+ u32 ht_ielen = 0;
+
+ if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
+ !check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
+ return 0;
+
+ if (pmlmeext->cur_wireless_mode & (WIRELESS_11_24N | WIRELESS_11_5N)) {
+ p = rtw_get_ie(&pcur_bss->ies[12], _HT_CAPABILITY_IE_,
+ &ht_ielen, pcur_bss->ie_length - 12);
+ if (p && ht_ielen > 0) {
+ /* cur_bwmod is updated by beacon, pmlmeinfo is updated by association response */
+ bw_40MHz = (pmlmeext->cur_bwmode && (HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH & pmlmeinfo->HT_info.infos[0])) ? 1 : 0;
+
+ short_GI_20 = (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & IEEE80211_HT_CAP_SGI_20) ? 1 : 0;
+ short_GI_40 = (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & IEEE80211_HT_CAP_SGI_40) ? 1 : 0;
+
+ max_rate = rtw_mcs_rate(
+ RF_1T1R,
+ bw_40MHz & pregistrypriv->cbw40_enable,
+ short_GI_20,
+ short_GI_40,
+ pmlmeinfo->HT_caps.mcs.rx_mask
+ );
+ }
+ } else {
+ while (pcur_bss->SupportedRates[i] != 0 &&
+ pcur_bss->SupportedRates[i] != 0xFF) {
+ rate = pcur_bss->SupportedRates[i] & 0x7F;
+ if (rate > max_rate)
+ max_rate = rate;
+ i++;
+ }
+
+ max_rate *= 5;
+ }
+
+ return max_rate;
+}
+
+/* Return _SUCCESS or _FAIL */
+int rtw_set_country(struct adapter *adapter, const char *country_code)
+{
+ int i;
+ int channel_plan = RT_CHANNEL_DOMAIN_WORLD_WIDE_5G;
+
+ DBG_88E("%s country_code:%s\n", __func__, country_code);
+ for (i = 0; i < ARRAY_SIZE(channel_table); i++) {
+ if (strcmp(channel_table[i].name, country_code) == 0) {
+ channel_plan = channel_table[i].channel_plan;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(channel_table))
+ DBG_88E("%s unknown country_code:%s\n", __func__, country_code);
+
+ return rtw_set_chplan_cmd(adapter, channel_plan, 1);
+}
diff --git a/drivers/staging/rtl8188eu/core/rtw_iol.c b/drivers/staging/rtl8188eu/core/rtw_iol.c
new file mode 100644
index 0000000..fc3c662
--- /dev/null
+++ b/drivers/staging/rtl8188eu/core/rtw_iol.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include <rtw_iol.h>
+
+bool rtw_iol_applied(struct adapter *adapter)
+{
+ if (adapter->registrypriv.fw_iol == 1)
+ return true;
+
+ if (adapter->registrypriv.fw_iol == 2 &&
+ !adapter_to_dvobj(adapter)->ishighspeed)
+ return true;
+ return false;
+}
diff --git a/drivers/staging/rtl8188eu/core/rtw_led.c b/drivers/staging/rtl8188eu/core/rtw_led.c
new file mode 100644
index 0000000..d1406cc
--- /dev/null
+++ b/drivers/staging/rtl8188eu/core/rtw_led.c
@@ -0,0 +1,484 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include <drv_types.h>
+#include "rtw_led.h"
+
+/* */
+/* Description: */
+/* Callback function of LED BlinkTimer, */
+/* it just schedules to corresponding BlinkWorkItem/led_blink_hdl */
+/* */
+static void BlinkTimerCallback(struct timer_list *t)
+{
+ struct LED_871x *pLed = from_timer(pLed, t, BlinkTimer);
+ struct adapter *padapter = pLed->padapter;
+
+ if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
+ return;
+
+ schedule_work(&pLed->BlinkWorkItem);
+}
+
+/* */
+/* Description: */
+/* Callback function of LED BlinkWorkItem. */
+/* */
+void BlinkWorkItemCallback(struct work_struct *work)
+{
+ struct LED_871x *pLed = container_of(work, struct LED_871x,
+ BlinkWorkItem);
+
+ blink_handler(pLed);
+}
+
+/* */
+/* Description: */
+/* Reset status of LED_871x object. */
+/* */
+void ResetLedStatus(struct LED_871x *pLed)
+{
+ pLed->CurrLedState = RTW_LED_OFF; /* Current LED state. */
+ pLed->bLedOn = false; /* true if LED is ON, false if LED is OFF. */
+
+ pLed->bLedBlinkInProgress = false; /* true if it is blinking, false o.w.. */
+ pLed->bLedWPSBlinkInProgress = false;
+
+ pLed->BlinkTimes = 0; /* Number of times to toggle led state for blinking. */
+ pLed->BlinkingLedState = LED_UNKNOWN; /* Next state for blinking, either RTW_LED_ON or RTW_LED_OFF are. */
+
+ pLed->bLedNoLinkBlinkInProgress = false;
+ pLed->bLedLinkBlinkInProgress = false;
+ pLed->bLedScanBlinkInProgress = false;
+}
+
+/*Description: */
+/* Initialize an LED_871x object. */
+void InitLed871x(struct adapter *padapter, struct LED_871x *pLed)
+{
+ pLed->padapter = padapter;
+
+ ResetLedStatus(pLed);
+
+ timer_setup(&pLed->BlinkTimer, BlinkTimerCallback, 0);
+
+ INIT_WORK(&pLed->BlinkWorkItem, BlinkWorkItemCallback);
+}
+
+/* */
+/* Description: */
+/* DeInitialize an LED_871x object. */
+/* */
+void DeInitLed871x(struct LED_871x *pLed)
+{
+ cancel_work_sync(&pLed->BlinkWorkItem);
+ del_timer_sync(&pLed->BlinkTimer);
+ ResetLedStatus(pLed);
+}
+
+/* */
+/* Description: */
+/* Implementation of LED blinking behavior. */
+/* It toggle off LED and schedule corresponding timer if necessary. */
+/* */
+
+static void SwLedBlink1(struct LED_871x *pLed)
+{
+ struct adapter *padapter = pLed->padapter;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ u8 bStopBlinking = false;
+
+ /* Change LED according to BlinkingLedState specified. */
+ if (pLed->BlinkingLedState == RTW_LED_ON) {
+ sw_led_on(padapter, pLed);
+ RT_TRACE(_module_rtl8712_led_c_, _drv_info_,
+ ("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
+ } else {
+ sw_led_off(padapter, pLed);
+ RT_TRACE(_module_rtl8712_led_c_, _drv_info_,
+ ("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
+ }
+
+ if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
+ sw_led_off(padapter, pLed);
+ ResetLedStatus(pLed);
+ return;
+ }
+
+ switch (pLed->CurrLedState) {
+ case LED_BLINK_SLOWLY:
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ mod_timer(&pLed->BlinkTimer, jiffies +
+ msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
+ break;
+ case LED_BLINK_NORMAL:
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ mod_timer(&pLed->BlinkTimer, jiffies +
+ msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
+ break;
+ case LED_BLINK_SCAN:
+ pLed->BlinkTimes--;
+ if (pLed->BlinkTimes == 0)
+ bStopBlinking = true;
+ if (bStopBlinking) {
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ pLed->bLedLinkBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_NORMAL;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ mod_timer(&pLed->BlinkTimer, jiffies +
+ msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
+ RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
+ } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
+ pLed->bLedNoLinkBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ mod_timer(&pLed->BlinkTimer, jiffies +
+ msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
+ RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
+ }
+ pLed->bLedScanBlinkInProgress = false;
+ } else {
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ mod_timer(&pLed->BlinkTimer, jiffies +
+ msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
+ }
+ break;
+ case LED_BLINK_TXRX:
+ pLed->BlinkTimes--;
+ if (pLed->BlinkTimes == 0)
+ bStopBlinking = true;
+ if (bStopBlinking) {
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ pLed->bLedLinkBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_NORMAL;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ mod_timer(&pLed->BlinkTimer, jiffies +
+ msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
+ RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
+ } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
+ pLed->bLedNoLinkBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ mod_timer(&pLed->BlinkTimer, jiffies +
+ msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
+ RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
+ }
+ pLed->BlinkTimes = 0;
+ pLed->bLedBlinkInProgress = false;
+ } else {
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ mod_timer(&pLed->BlinkTimer, jiffies +
+ msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
+ }
+ break;
+ case LED_BLINK_WPS:
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ mod_timer(&pLed->BlinkTimer, jiffies +
+ msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
+ break;
+ case LED_BLINK_WPS_STOP: /* WPS success */
+ if (pLed->BlinkingLedState == RTW_LED_ON)
+ bStopBlinking = false;
+ else
+ bStopBlinking = true;
+
+ if (bStopBlinking) {
+ pLed->bLedLinkBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_NORMAL;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ mod_timer(&pLed->BlinkTimer, jiffies +
+ msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
+ RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
+
+ pLed->bLedWPSBlinkInProgress = false;
+ } else {
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ mod_timer(&pLed->BlinkTimer, jiffies +
+ msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+ /* ALPHA, added by chiyoko, 20090106 */
+static void SwLedControlMode1(struct adapter *padapter, enum LED_CTL_MODE LedAction)
+{
+ struct led_priv *ledpriv = &padapter->ledpriv;
+ struct LED_871x *pLed = &ledpriv->sw_led;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ switch (LedAction) {
+ case LED_CTL_POWER_ON:
+ case LED_CTL_START_TO_LINK:
+ case LED_CTL_NO_LINK:
+ if (pLed->bLedNoLinkBlinkInProgress)
+ break;
+ if (pLed->CurrLedState == LED_BLINK_SCAN ||
+ IS_LED_WPS_BLINKING(pLed))
+ return;
+ if (pLed->bLedLinkBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ pLed->bLedNoLinkBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ mod_timer(&pLed->BlinkTimer, jiffies +
+ msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
+ break;
+ case LED_CTL_LINK:
+ if (pLed->bLedLinkBlinkInProgress)
+ break;
+ if (pLed->CurrLedState == LED_BLINK_SCAN ||
+ IS_LED_WPS_BLINKING(pLed))
+ return;
+ if (pLed->bLedNoLinkBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedNoLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ pLed->bLedLinkBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_NORMAL;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ mod_timer(&pLed->BlinkTimer, jiffies +
+ msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
+ break;
+ case LED_CTL_SITE_SURVEY:
+ if (pmlmepriv->LinkDetectInfo.bBusyTraffic &&
+ check_fwstate(pmlmepriv, _FW_LINKED))
+ break;
+ if (pLed->bLedScanBlinkInProgress)
+ break;
+ if (IS_LED_WPS_BLINKING(pLed))
+ return;
+ if (pLed->bLedNoLinkBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedNoLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedLinkBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ pLed->bLedScanBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_SCAN;
+ pLed->BlinkTimes = 24;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ mod_timer(&pLed->BlinkTimer, jiffies +
+ msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
+ break;
+ case LED_CTL_TX:
+ case LED_CTL_RX:
+ if (pLed->bLedBlinkInProgress)
+ break;
+ if (pLed->CurrLedState == LED_BLINK_SCAN ||
+ IS_LED_WPS_BLINKING(pLed))
+ return;
+ if (pLed->bLedNoLinkBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedNoLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedLinkBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedLinkBlinkInProgress = false;
+ }
+ pLed->bLedBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_TXRX;
+ pLed->BlinkTimes = 2;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ mod_timer(&pLed->BlinkTimer, jiffies +
+ msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
+ break;
+ case LED_CTL_START_WPS: /* wait until xinpin finish */
+ case LED_CTL_START_WPS_BOTTON:
+ if (pLed->bLedWPSBlinkInProgress)
+ break;
+ if (pLed->bLedNoLinkBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedNoLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedLinkBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ if (pLed->bLedScanBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedScanBlinkInProgress = false;
+ }
+ pLed->bLedWPSBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_WPS;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ mod_timer(&pLed->BlinkTimer, jiffies +
+ msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
+ break;
+ case LED_CTL_STOP_WPS:
+ if (pLed->bLedNoLinkBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedNoLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedLinkBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ if (pLed->bLedScanBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedScanBlinkInProgress = false;
+ }
+ if (pLed->bLedWPSBlinkInProgress)
+ del_timer_sync(&pLed->BlinkTimer);
+ else
+ pLed->bLedWPSBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_WPS_STOP;
+ if (pLed->bLedOn) {
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ mod_timer(&pLed->BlinkTimer, jiffies +
+ msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
+ } else {
+ pLed->BlinkingLedState = RTW_LED_ON;
+ mod_timer(&pLed->BlinkTimer,
+ jiffies + msecs_to_jiffies(0));
+ }
+ break;
+ case LED_CTL_STOP_WPS_FAIL:
+ if (pLed->bLedWPSBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedWPSBlinkInProgress = false;
+ }
+ pLed->bLedNoLinkBlinkInProgress = true;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if (pLed->bLedOn)
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ mod_timer(&pLed->BlinkTimer, jiffies +
+ msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
+ break;
+ case LED_CTL_POWER_OFF:
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ if (pLed->bLedNoLinkBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedNoLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedLinkBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedLinkBlinkInProgress = false;
+ }
+ if (pLed->bLedBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedBlinkInProgress = false;
+ }
+ if (pLed->bLedWPSBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedWPSBlinkInProgress = false;
+ }
+ if (pLed->bLedScanBlinkInProgress) {
+ del_timer_sync(&pLed->BlinkTimer);
+ pLed->bLedScanBlinkInProgress = false;
+ }
+ sw_led_off(padapter, pLed);
+ break;
+ default:
+ break;
+ }
+
+ RT_TRACE(_module_rtl8712_led_c_, _drv_info_,
+ ("Led %d\n", pLed->CurrLedState));
+}
+
+void blink_handler(struct LED_871x *pLed)
+{
+ struct adapter *padapter = pLed->padapter;
+
+ if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
+ return;
+
+ SwLedBlink1(pLed);
+}
+
+void led_control_8188eu(struct adapter *padapter, enum LED_CTL_MODE LedAction)
+{
+ if (padapter->bSurpriseRemoved || padapter->bDriverStopped ||
+ !padapter->hw_init_completed)
+ return;
+
+ if ((padapter->pwrctrlpriv.rf_pwrstate != rf_on &&
+ padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) &&
+ (LedAction == LED_CTL_TX || LedAction == LED_CTL_RX ||
+ LedAction == LED_CTL_SITE_SURVEY ||
+ LedAction == LED_CTL_LINK ||
+ LedAction == LED_CTL_NO_LINK ||
+ LedAction == LED_CTL_POWER_ON))
+ return;
+
+ SwLedControlMode1(padapter, LedAction);
+}
diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c
new file mode 100644
index 0000000..5738a9d
--- /dev/null
+++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c
@@ -0,0 +1,2063 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _RTW_MLME_C_
+
+#include <linux/ieee80211.h>
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <recv_osdep.h>
+#include <xmit_osdep.h>
+#include <hal_intf.h>
+#include <mlme_osdep.h>
+#include <sta_info.h>
+#include <wifi.h>
+#include <wlan_bssdef.h>
+#include <rtw_ioctl_set.h>
+#include <linux/vmalloc.h>
+
+extern const u8 MCS_rate_1R[16];
+
+int rtw_init_mlme_priv(struct adapter *padapter)
+{
+ int i;
+ u8 *pbuf;
+ struct wlan_network *pnetwork;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ int res = _SUCCESS;
+
+ /* We don't need to memset padapter->XXX to zero, because adapter is allocated by vzalloc(). */
+
+ pmlmepriv->nic_hdl = (u8 *)padapter;
+
+ pmlmepriv->pscanned = NULL;
+ pmlmepriv->fw_state = 0;
+ pmlmepriv->cur_network.network.InfrastructureMode = Ndis802_11AutoUnknown;
+ pmlmepriv->scan_mode = SCAN_ACTIVE;/* 1: active, 0: pasive. Maybe someday we should rename this varable to "active_mode" (Jeff) */
+
+ spin_lock_init(&pmlmepriv->lock);
+ _rtw_init_queue(&pmlmepriv->free_bss_pool);
+ _rtw_init_queue(&pmlmepriv->scanned_queue);
+
+ memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
+
+ pbuf = vzalloc(array_size(MAX_BSS_CNT, sizeof(struct wlan_network)));
+
+ if (!pbuf) {
+ res = _FAIL;
+ goto exit;
+ }
+ pmlmepriv->free_bss_buf = pbuf;
+
+ pnetwork = (struct wlan_network *)pbuf;
+
+ for (i = 0; i < MAX_BSS_CNT; i++) {
+ INIT_LIST_HEAD(&pnetwork->list);
+
+ list_add_tail(&pnetwork->list, &pmlmepriv->free_bss_pool.queue);
+
+ pnetwork++;
+ }
+
+ /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
+
+ rtw_clear_scan_deny(padapter);
+
+ rtw_init_mlme_timer(padapter);
+
+exit:
+ return res;
+}
+
+#if defined(CPTCFG_88EU_AP_MODE)
+static void rtw_free_mlme_ie_data(u8 **ppie, u32 *plen)
+{
+ kfree(*ppie);
+ *plen = 0;
+ *ppie = NULL;
+}
+
+void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
+{
+ rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
+ rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
+ rtw_free_mlme_ie_data(&pmlmepriv->wps_beacon_ie, &pmlmepriv->wps_beacon_ie_len);
+ rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_req_ie, &pmlmepriv->wps_probe_req_ie_len);
+ rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_resp_ie, &pmlmepriv->wps_probe_resp_ie_len);
+ rtw_free_mlme_ie_data(&pmlmepriv->wps_assoc_resp_ie, &pmlmepriv->wps_assoc_resp_ie_len);
+}
+#else
+void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
+{
+}
+#endif
+
+void rtw_free_mlme_priv(struct mlme_priv *pmlmepriv)
+{
+ if (pmlmepriv) {
+ rtw_free_mlme_priv_ie_data(pmlmepriv);
+ vfree(pmlmepriv->free_bss_buf);
+ }
+}
+
+struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv)
+ /* _queue *free_queue) */
+{
+ struct wlan_network *pnetwork;
+ struct __queue *free_queue = &pmlmepriv->free_bss_pool;
+
+ spin_lock_bh(&free_queue->lock);
+ pnetwork = list_first_entry_or_null(&free_queue->queue,
+ struct wlan_network, list);
+ if (!pnetwork)
+ goto exit;
+
+ list_del_init(&pnetwork->list);
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
+ ("rtw_alloc_network: ptr=%p\n", &pnetwork->list));
+ pnetwork->network_type = 0;
+ pnetwork->fixed = false;
+ pnetwork->last_scanned = jiffies;
+ pnetwork->aid = 0;
+ pnetwork->join_res = 0;
+
+exit:
+ spin_unlock_bh(&free_queue->lock);
+
+ return pnetwork;
+}
+
+static void _rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork, u8 isfreeall)
+{
+ unsigned long curr_time;
+ u32 delta_time;
+ u32 lifetime = SCANQUEUE_LIFETIME;
+ struct __queue *free_queue = &pmlmepriv->free_bss_pool;
+
+ if (!pnetwork)
+ return;
+
+ if (pnetwork->fixed)
+ return;
+ curr_time = jiffies;
+ if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
+ (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)))
+ lifetime = 1;
+ if (!isfreeall) {
+ delta_time = (curr_time - pnetwork->last_scanned)/HZ;
+ if (delta_time < lifetime)/* unit:sec */
+ return;
+ }
+ spin_lock_bh(&free_queue->lock);
+ list_del_init(&pnetwork->list);
+ list_add_tail(&pnetwork->list, &free_queue->queue);
+ spin_unlock_bh(&free_queue->lock);
+}
+
+static void rtw_free_network_nolock(struct mlme_priv *pmlmepriv,
+ struct wlan_network *pnetwork)
+{
+ struct __queue *free_queue = &pmlmepriv->free_bss_pool;
+
+ if (!pnetwork)
+ return;
+ if (pnetwork->fixed)
+ return;
+ list_del_init(&pnetwork->list);
+ list_add_tail(&pnetwork->list, get_list_head(free_queue));
+}
+
+/*
+ * return the wlan_network with the matching addr
+ *
+ * Shall be called under atomic context... to avoid possible racing condition...
+ */
+struct wlan_network *rtw_find_network(struct __queue *scanned_queue, u8 *addr)
+{
+ struct list_head *phead, *plist;
+ struct wlan_network *pnetwork = NULL;
+ u8 zero_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
+
+ if (!memcmp(zero_addr, addr, ETH_ALEN)) {
+ pnetwork = NULL;
+ goto exit;
+ }
+ phead = get_list_head(scanned_queue);
+ plist = phead->next;
+
+ while (plist != phead) {
+ pnetwork = container_of(plist, struct wlan_network, list);
+ if (!memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN))
+ break;
+ plist = plist->next;
+ }
+ if (plist == phead)
+ pnetwork = NULL;
+exit:
+ return pnetwork;
+}
+
+void rtw_free_network_queue(struct adapter *padapter, u8 isfreeall)
+{
+ struct list_head *phead, *plist;
+ struct wlan_network *pnetwork;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct __queue *scanned_queue = &pmlmepriv->scanned_queue;
+
+ spin_lock_bh(&scanned_queue->lock);
+
+ phead = get_list_head(scanned_queue);
+ plist = phead->next;
+
+ while (phead != plist) {
+ pnetwork = container_of(plist, struct wlan_network, list);
+
+ plist = plist->next;
+
+ _rtw_free_network(pmlmepriv, pnetwork, isfreeall);
+ }
+ spin_unlock_bh(&scanned_queue->lock);
+}
+
+int rtw_if_up(struct adapter *padapter)
+{
+ int res;
+
+ if (padapter->bDriverStopped || padapter->bSurpriseRemoved ||
+ !check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
+ ("%s:bDriverStopped(%d) OR bSurpriseRemoved(%d)",
+ __func__, padapter->bDriverStopped,
+ padapter->bSurpriseRemoved));
+ res = false;
+ } else {
+ res = true;
+ }
+ return res;
+}
+
+void rtw_generate_random_ibss(u8 *pibss)
+{
+ unsigned long curtime = jiffies;
+
+ pibss[0] = 0x02; /* in ad-hoc mode bit1 must set to 1 */
+ pibss[1] = 0x11;
+ pibss[2] = 0x87;
+ pibss[3] = (u8)(curtime & 0xff);/* p[0]; */
+ pibss[4] = (u8)((curtime>>8) & 0xff);/* p[1]; */
+ pibss[5] = (u8)((curtime>>16) & 0xff);/* p[2]; */
+}
+
+u8 *rtw_get_capability_from_ie(u8 *ie)
+{
+ return ie + 8 + 2;
+}
+
+u16 rtw_get_capability(struct wlan_bssid_ex *bss)
+{
+ __le16 val;
+
+ memcpy((u8 *)&val, rtw_get_capability_from_ie(bss->ies), 2);
+
+ return le16_to_cpu(val);
+}
+
+u8 *rtw_get_beacon_interval_from_ie(u8 *ie)
+{
+ return ie + 8;
+}
+
+int rtw_is_same_ibss(struct adapter *adapter, struct wlan_network *pnetwork)
+{
+ int ret = true;
+ struct security_priv *psecuritypriv = &adapter->securitypriv;
+
+ if ((psecuritypriv->dot11PrivacyAlgrthm != _NO_PRIVACY_) &&
+ (pnetwork->network.Privacy == 0))
+ ret = false;
+ else if ((psecuritypriv->dot11PrivacyAlgrthm == _NO_PRIVACY_) &&
+ (pnetwork->network.Privacy == 1))
+ ret = false;
+ else
+ ret = true;
+ return ret;
+}
+
+static int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b)
+{
+ return (a->ssid.ssid_length == b->ssid.ssid_length) &&
+ !memcmp(a->ssid.ssid, b->ssid.ssid, a->ssid.ssid_length);
+}
+
+int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst)
+{
+ u16 s_cap, d_cap;
+ __le16 le_scap, le_dcap;
+
+ memcpy((u8 *)&le_scap, rtw_get_capability_from_ie(src->ies), 2);
+ memcpy((u8 *)&le_dcap, rtw_get_capability_from_ie(dst->ies), 2);
+
+ s_cap = le16_to_cpu(le_scap);
+ d_cap = le16_to_cpu(le_dcap);
+
+ return ((src->ssid.ssid_length == dst->ssid.ssid_length) &&
+ (!memcmp(src->MacAddress, dst->MacAddress, ETH_ALEN)) &&
+ (!memcmp(src->ssid.ssid, dst->ssid.ssid, src->ssid.ssid_length)) &&
+ ((s_cap & WLAN_CAPABILITY_IBSS) ==
+ (d_cap & WLAN_CAPABILITY_IBSS)) &&
+ ((s_cap & WLAN_CAPABILITY_ESS) ==
+ (d_cap & WLAN_CAPABILITY_ESS)));
+}
+
+struct wlan_network *rtw_get_oldest_wlan_network(struct __queue *scanned_queue)
+{
+ struct list_head *plist, *phead;
+ struct wlan_network *pwlan = NULL;
+ struct wlan_network *oldest = NULL;
+
+ phead = get_list_head(scanned_queue);
+
+ for (plist = phead->next; plist != phead; plist = plist->next) {
+ pwlan = container_of(plist, struct wlan_network, list);
+
+ if (!pwlan->fixed) {
+ if (!oldest || time_after(oldest->last_scanned, pwlan->last_scanned))
+ oldest = pwlan;
+ }
+ }
+ return oldest;
+}
+
+void update_network(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
+ struct adapter *padapter, bool update_ie)
+{
+ long rssi_ori = dst->Rssi;
+ u8 sq_smp = src->PhyInfo.SignalQuality;
+ u8 ss_final;
+ u8 sq_final;
+ long rssi_final;
+
+ rtw_hal_antdiv_rssi_compared(padapter, dst, src); /* this will update src.Rssi, need consider again */
+
+ /* The rule below is 1/5 for sample value, 4/5 for history value */
+ if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) &&
+ is_same_network(&padapter->mlmepriv.cur_network.network, src)) {
+ /* Take the recvpriv's value for the connected AP*/
+ ss_final = padapter->recvpriv.signal_strength;
+ sq_final = padapter->recvpriv.signal_qual;
+ /* the rssi value here is undecorated, and will be used for antenna diversity */
+ if (sq_smp != 101) /* from the right channel */
+ rssi_final = (src->Rssi + dst->Rssi * 4) / 5;
+ else
+ rssi_final = rssi_ori;
+ } else {
+ if (sq_smp != 101) { /* from the right channel */
+ ss_final = ((u32)(src->PhyInfo.SignalStrength)+(u32)(dst->PhyInfo.SignalStrength)*4)/5;
+ sq_final = ((u32)(src->PhyInfo.SignalQuality)+(u32)(dst->PhyInfo.SignalQuality)*4)/5;
+ rssi_final = (src->Rssi+dst->Rssi*4)/5;
+ } else {
+ /* bss info not receiving from the right channel, use the original RX signal infos */
+ ss_final = dst->PhyInfo.SignalStrength;
+ sq_final = dst->PhyInfo.SignalQuality;
+ rssi_final = dst->Rssi;
+ }
+ }
+ if (update_ie)
+ memcpy((u8 *)dst, (u8 *)src, get_wlan_bssid_ex_sz(src));
+ dst->PhyInfo.SignalStrength = ss_final;
+ dst->PhyInfo.SignalQuality = sq_final;
+ dst->Rssi = rssi_final;
+}
+
+static void update_current_network(struct adapter *adapter, struct wlan_bssid_ex *pnetwork)
+{
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED) &&
+ is_same_network(&pmlmepriv->cur_network.network, pnetwork)) {
+ update_network(&pmlmepriv->cur_network.network, pnetwork, adapter, true);
+ rtw_update_protection(adapter, (pmlmepriv->cur_network.network.ies) + sizeof(struct ndis_802_11_fixed_ie),
+ pmlmepriv->cur_network.network.ie_length);
+ }
+}
+
+/*
+ * Caller must hold pmlmepriv->lock first.
+ */
+void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *target)
+{
+ struct list_head *plist, *phead;
+ u32 bssid_ex_sz;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ struct __queue *queue = &pmlmepriv->scanned_queue;
+ struct wlan_network *pnetwork = NULL;
+ struct wlan_network *oldest = NULL;
+
+ spin_lock_bh(&queue->lock);
+ phead = get_list_head(queue);
+ plist = phead->next;
+
+ while (phead != plist) {
+ pnetwork = container_of(plist, struct wlan_network, list);
+
+ if (is_same_network(&pnetwork->network, target))
+ break;
+ if ((oldest == ((struct wlan_network *)0)) ||
+ time_after(oldest->last_scanned, pnetwork->last_scanned))
+ oldest = pnetwork;
+ plist = plist->next;
+ }
+ /* If we didn't find a match, then get a new network slot to initialize
+ * with this beacon's information
+ */
+ if (phead == plist) {
+ if (list_empty(&pmlmepriv->free_bss_pool.queue)) {
+ /* If there are no more slots, expire the oldest */
+ pnetwork = oldest;
+
+ rtw_hal_get_def_var(adapter, HAL_DEF_CURRENT_ANTENNA,
+ &target->PhyInfo.Optimum_antenna);
+ memcpy(&pnetwork->network, target,
+ get_wlan_bssid_ex_sz(target));
+ /* variable initialize */
+ pnetwork->fixed = false;
+ pnetwork->last_scanned = jiffies;
+
+ pnetwork->network_type = 0;
+ pnetwork->aid = 0;
+ pnetwork->join_res = 0;
+
+ /* bss info not receiving from the right channel */
+ if (pnetwork->network.PhyInfo.SignalQuality == 101)
+ pnetwork->network.PhyInfo.SignalQuality = 0;
+ } else {
+ /* Otherwise just pull from the free list */
+
+ pnetwork = rtw_alloc_network(pmlmepriv); /* will update scan_time */
+
+ if (!pnetwork) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
+ ("\n\n\nsomething wrong here\n\n\n"));
+ goto exit;
+ }
+
+ bssid_ex_sz = get_wlan_bssid_ex_sz(target);
+ target->Length = bssid_ex_sz;
+ rtw_hal_get_def_var(adapter, HAL_DEF_CURRENT_ANTENNA,
+ &target->PhyInfo.Optimum_antenna);
+ memcpy(&pnetwork->network, target, bssid_ex_sz);
+
+ pnetwork->last_scanned = jiffies;
+
+ /* bss info not receiving from the right channel */
+ if (pnetwork->network.PhyInfo.SignalQuality == 101)
+ pnetwork->network.PhyInfo.SignalQuality = 0;
+ list_add_tail(&pnetwork->list, &queue->queue);
+ }
+ } else {
+ /* we have an entry and we are going to update it. But this
+ * entry may be already expired. In this case we do the same
+ * as we found a new net and call the new_net handler
+ */
+ bool update_ie = true;
+
+ pnetwork->last_scanned = jiffies;
+
+ /* target.Reserved[0]== 1, means that scanned network is a bcn frame. */
+ if ((pnetwork->network.ie_length > target->ie_length) && (target->Reserved[0] == 1))
+ update_ie = false;
+
+ update_network(&pnetwork->network, target, adapter, update_ie);
+ }
+
+exit:
+ spin_unlock_bh(&queue->lock);
+}
+
+static void rtw_add_network(struct adapter *adapter,
+ struct wlan_bssid_ex *pnetwork)
+{
+ update_current_network(adapter, pnetwork);
+ rtw_update_scanned_network(adapter, pnetwork);
+}
+
+/*
+ * select the desired network based on the capability of the (i)bss.
+ * check items: (1) security
+ * (2) network_type
+ * (3) WMM
+ * (4) HT
+ * (5) others
+ */
+static int rtw_is_desired_network(struct adapter *adapter, struct wlan_network *pnetwork)
+{
+ struct security_priv *psecuritypriv = &adapter->securitypriv;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ u32 desired_encmode;
+ u32 privacy;
+
+ /* u8 wps_ie[512]; */
+ uint wps_ielen;
+
+ int bselected = true;
+
+ desired_encmode = psecuritypriv->ndisencryptstatus;
+ privacy = pnetwork->network.Privacy;
+
+ if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
+ if (rtw_get_wps_ie(pnetwork->network.ies+_FIXED_IE_LENGTH_, pnetwork->network.ie_length-_FIXED_IE_LENGTH_, NULL, &wps_ielen))
+ return true;
+ else
+ return false;
+ }
+ if (adapter->registrypriv.wifi_spec == 1) { /* for correct flow of 8021X to do.... */
+ if ((desired_encmode == Ndis802_11EncryptionDisabled) && (privacy != 0))
+ bselected = false;
+ }
+
+ if ((desired_encmode != Ndis802_11EncryptionDisabled) && (privacy == 0)) {
+ DBG_88E("desired_encmode: %d, privacy: %d\n", desired_encmode, privacy);
+ bselected = false;
+ }
+
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
+ if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
+ bselected = false;
+ }
+
+ return bselected;
+}
+
+/* TODO: Perry: For Power Management */
+void rtw_atimdone_event_callback(struct adapter *adapter, u8 *pbuf)
+{
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("receive atimdone_event\n"));
+}
+
+void rtw_survey_event_callback(struct adapter *adapter, u8 *pbuf)
+{
+ u32 len;
+ struct wlan_bssid_ex *pnetwork;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+
+ pnetwork = (struct wlan_bssid_ex *)pbuf;
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
+ ("%s, ssid=%s\n", __func__, pnetwork->ssid.ssid));
+
+ len = get_wlan_bssid_ex_sz(pnetwork);
+ if (len > (sizeof(struct wlan_bssid_ex))) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
+ ("\n****%s: return a wrong bss ***\n", __func__));
+ return;
+ }
+ spin_lock_bh(&pmlmepriv->lock);
+
+ /* update IBSS_network 's timestamp */
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
+ if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, pnetwork->MacAddress, ETH_ALEN)) {
+ struct wlan_network *ibss_wlan = NULL;
+
+ memcpy(pmlmepriv->cur_network.network.ies, pnetwork->ies, 8);
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+ ibss_wlan = rtw_find_network(&pmlmepriv->scanned_queue, pnetwork->MacAddress);
+ if (ibss_wlan) {
+ memcpy(ibss_wlan->network.ies, pnetwork->ies, 8);
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+ goto exit;
+ }
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+ }
+ }
+
+ /* lock pmlmepriv->lock when you accessing network_q */
+ if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
+ if (pnetwork->ssid.ssid[0] == 0)
+ pnetwork->ssid.ssid_length = 0;
+ rtw_add_network(adapter, pnetwork);
+ }
+
+exit:
+ spin_unlock_bh(&pmlmepriv->lock);
+}
+
+void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf)
+{
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+
+ spin_lock_bh(&pmlmepriv->lock);
+
+ if (pmlmepriv->wps_probe_req_ie) {
+ pmlmepriv->wps_probe_req_ie_len = 0;
+ kfree(pmlmepriv->wps_probe_req_ie);
+ pmlmepriv->wps_probe_req_ie = NULL;
+ }
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
+ ("%s: fw_state:%x\n\n", __func__, get_fwstate(pmlmepriv)));
+
+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
+ del_timer_sync(&pmlmepriv->scan_to_timer);
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
+ } else {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("nic status=%x, survey done event comes too late!\n", get_fwstate(pmlmepriv)));
+ }
+
+ rtw_set_signal_stat_timer(&adapter->recvpriv);
+
+ if (pmlmepriv->to_join) {
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
+ if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
+ set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
+
+ if (rtw_select_and_join_from_scanned_queue(pmlmepriv) == _SUCCESS) {
+ mod_timer(&pmlmepriv->assoc_timer,
+ jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
+ } else {
+ struct wlan_bssid_ex *pdev_network = &adapter->registrypriv.dev_network;
+ u8 *pibss = adapter->registrypriv.dev_network.MacAddress;
+
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("switching to adhoc master\n"));
+
+ memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
+
+ rtw_update_registrypriv_dev_network(adapter);
+ rtw_generate_random_ibss(pibss);
+
+ pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
+
+ if (rtw_createbss_cmd(adapter) != _SUCCESS)
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Error=>rtw_createbss_cmd status FAIL\n"));
+ pmlmepriv->to_join = false;
+ }
+ }
+ } else {
+ int s_ret;
+
+ set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
+ pmlmepriv->to_join = false;
+ s_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
+ if (s_ret == _SUCCESS) {
+ mod_timer(&pmlmepriv->assoc_timer,
+ jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
+ } else if (s_ret == 2) { /* there is no need to wait for join */
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+ rtw_indicate_connect(adapter);
+ } else {
+ DBG_88E("try_to_join, but select scanning queue fail, to_roaming:%d\n", pmlmepriv->to_roaming);
+ if (pmlmepriv->to_roaming != 0) {
+ if (--pmlmepriv->to_roaming == 0 ||
+ rtw_sitesurvey_cmd(adapter, &pmlmepriv->assoc_ssid, 1, NULL, 0) != _SUCCESS) {
+ pmlmepriv->to_roaming = 0;
+ rtw_free_assoc_resources(adapter);
+ rtw_indicate_disconnect(adapter);
+ } else {
+ pmlmepriv->to_join = true;
+ }
+ }
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+ }
+ }
+ }
+
+ indicate_wx_scan_complete_event(adapter);
+
+ spin_unlock_bh(&pmlmepriv->lock);
+
+ rtw_os_xmit_schedule(adapter);
+}
+
+void rtw_dummy_event_callback(struct adapter *adapter, u8 *pbuf)
+{
+}
+
+void rtw_fwdbg_event_callback(struct adapter *adapter, u8 *pbuf)
+{
+}
+
+static void free_scanqueue(struct mlme_priv *pmlmepriv)
+{
+ struct __queue *free_queue = &pmlmepriv->free_bss_pool;
+ struct __queue *scan_queue = &pmlmepriv->scanned_queue;
+ struct list_head *plist, *phead, *ptemp;
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+%s\n", __func__));
+ spin_lock_bh(&scan_queue->lock);
+ spin_lock_bh(&free_queue->lock);
+
+ phead = get_list_head(scan_queue);
+ plist = phead->next;
+
+ while (plist != phead) {
+ ptemp = plist->next;
+ list_del_init(plist);
+ list_add_tail(plist, &free_queue->queue);
+ plist = ptemp;
+ }
+
+ spin_unlock_bh(&free_queue->lock);
+ spin_unlock_bh(&scan_queue->lock);
+}
+
+/*
+ * rtw_free_assoc_resources: the caller has to lock pmlmepriv->lock
+ */
+void rtw_free_assoc_resources(struct adapter *adapter)
+{
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+ rtw_free_assoc_resources_locked(adapter);
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+}
+
+/*
+ * rtw_free_assoc_resources_locked: the caller has to lock pmlmepriv->lock
+ */
+void rtw_free_assoc_resources_locked(struct adapter *adapter)
+{
+ struct wlan_network *pwlan = NULL;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ struct sta_priv *pstapriv = &adapter->stapriv;
+ struct wlan_network *tgt_network = &pmlmepriv->cur_network;
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_free_assoc_resources\n"));
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
+ ("tgt_network->network.MacAddress=%pM ssid=%s\n",
+ tgt_network->network.MacAddress, tgt_network->network.ssid.ssid));
+
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE)) {
+ struct sta_info *psta;
+
+ psta = rtw_get_stainfo(&adapter->stapriv, tgt_network->network.MacAddress);
+
+ spin_lock_bh(&pstapriv->sta_hash_lock);
+ rtw_free_stainfo(adapter, psta);
+ spin_unlock_bh(&pstapriv->sta_hash_lock);
+ }
+
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE)) {
+ struct sta_info *psta;
+
+ rtw_free_all_stainfo(adapter);
+
+ psta = rtw_get_bcmc_stainfo(adapter);
+ spin_lock_bh(&pstapriv->sta_hash_lock);
+ rtw_free_stainfo(adapter, psta);
+ spin_unlock_bh(&pstapriv->sta_hash_lock);
+
+ rtw_init_bcmc_stainfo(adapter);
+ }
+
+ pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
+ if (pwlan)
+ pwlan->fixed = false;
+ else
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_free_assoc_resources:pwlan==NULL\n\n"));
+
+ if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) && (adapter->stapriv.asoc_sta_count == 1)))
+ rtw_free_network_nolock(pmlmepriv, pwlan);
+
+ pmlmepriv->key_mask = 0;
+}
+
+/*
+ * rtw_indicate_connect: the caller has to lock pmlmepriv->lock
+ */
+void rtw_indicate_connect(struct adapter *padapter)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+%s\n", __func__));
+
+ pmlmepriv->to_join = false;
+
+ if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
+ set_fwstate(pmlmepriv, _FW_LINKED);
+
+ led_control_8188eu(padapter, LED_CTL_LINK);
+
+ rtw_os_indicate_connect(padapter);
+ }
+
+ pmlmepriv->to_roaming = 0;
+
+ rtw_set_scan_deny(padapter, 3000);
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("-%s: fw_state=0x%08x\n", __func__, get_fwstate(pmlmepriv)));
+}
+
+/*
+ * rtw_indicate_disconnect: the caller has to lock pmlmepriv->lock
+ */
+void rtw_indicate_disconnect(struct adapter *padapter)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+%s\n", __func__));
+
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING | WIFI_UNDER_WPS);
+
+ if (pmlmepriv->to_roaming > 0)
+ _clr_fwstate_(pmlmepriv, _FW_LINKED);
+
+ if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) ||
+ (pmlmepriv->to_roaming <= 0)) {
+ rtw_os_indicate_disconnect(padapter);
+
+ _clr_fwstate_(pmlmepriv, _FW_LINKED);
+ led_control_8188eu(padapter, LED_CTL_NO_LINK);
+ rtw_clear_scan_deny(padapter);
+ }
+
+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_DISCONNECT, 1);
+}
+
+inline void rtw_indicate_scan_done(struct adapter *padapter, bool aborted)
+{
+ indicate_wx_scan_complete_event(padapter);
+}
+
+static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, struct wlan_network *pnetwork)
+{
+ int i;
+ struct sta_info *bmc_sta, *psta = NULL;
+ struct recv_reorder_ctrl *preorder_ctrl;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ psta = rtw_get_stainfo(pstapriv, pnetwork->network.MacAddress);
+ if (!psta)
+ psta = rtw_alloc_stainfo(pstapriv, pnetwork->network.MacAddress);
+
+ if (psta) { /* update ptarget_sta */
+ DBG_88E("%s\n", __func__);
+ psta->aid = pnetwork->join_res;
+ psta->mac_id = 0;
+ /* sta mode */
+ rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true);
+ /* security related */
+ if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
+ padapter->securitypriv.binstallGrpkey = false;
+ padapter->securitypriv.busetkipkey = false;
+ padapter->securitypriv.bgrpkey_handshake = false;
+ psta->ieee8021x_blocked = true;
+ psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
+ memset((u8 *)&psta->dot118021x_UncstKey, 0, sizeof(union Keytype));
+ memset((u8 *)&psta->dot11tkiprxmickey, 0, sizeof(union Keytype));
+ memset((u8 *)&psta->dot11tkiptxmickey, 0, sizeof(union Keytype));
+ memset((u8 *)&psta->dot11txpn, 0, sizeof(union pn48));
+ memset((u8 *)&psta->dot11rxpn, 0, sizeof(union pn48));
+ }
+ /*
+ * Commented by Albert 2012/07/21
+ * When doing the WPS, the wps_ie_len won't equal to 0
+ * And the Wi-Fi driver shouldn't allow the data
+ * packet to be transmitted.
+ */
+ if (padapter->securitypriv.wps_ie_len != 0) {
+ psta->ieee8021x_blocked = true;
+ padapter->securitypriv.wps_ie_len = 0;
+ }
+ /* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info */
+ /* if A-MPDU Rx is enabled, resetting rx_ordering_ctrl wstart_b(indicate_seq) to default value = 0xffff */
+ /* todo: check if AP can send A-MPDU packets */
+ for (i = 0; i < 16; i++) {
+ /* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
+ preorder_ctrl = &psta->recvreorder_ctrl[i];
+ preorder_ctrl->enable = false;
+ preorder_ctrl->indicate_seq = 0xffff;
+ preorder_ctrl->wend_b = 0xffff;
+ preorder_ctrl->wsize_b = 64;/* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */
+ }
+ bmc_sta = rtw_get_bcmc_stainfo(padapter);
+ if (bmc_sta) {
+ for (i = 0; i < 16; i++) {
+ /* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
+ preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
+ preorder_ctrl->enable = false;
+ preorder_ctrl->indicate_seq = 0xffff;
+ preorder_ctrl->wend_b = 0xffff;
+ preorder_ctrl->wsize_b = 64;/* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */
+ }
+ }
+ /* misc. */
+ update_sta_info(padapter, psta);
+ }
+ return psta;
+}
+
+/* pnetwork: returns from rtw_joinbss_event_callback */
+/* ptarget_wlan: found from scanned_queue */
+static void rtw_joinbss_update_network(struct adapter *padapter, struct wlan_network *ptarget_wlan, struct wlan_network *pnetwork)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wlan_network *cur_network = &pmlmepriv->cur_network;
+
+ DBG_88E("%s\n", __func__);
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
+ ("\nfw_state:%x, BSSID:%pM\n",
+ get_fwstate(pmlmepriv), pnetwork->network.MacAddress));
+
+ /* why not use ptarget_wlan?? */
+ memcpy(&cur_network->network, &pnetwork->network, pnetwork->network.Length);
+ /* some ies in pnetwork is wrong, so we should use ptarget_wlan ies */
+ cur_network->network.ie_length = ptarget_wlan->network.ie_length;
+ memcpy(&cur_network->network.ies[0], &ptarget_wlan->network.ies[0], MAX_IE_SZ);
+
+ cur_network->aid = pnetwork->join_res;
+
+ rtw_set_signal_stat_timer(&padapter->recvpriv);
+ padapter->recvpriv.signal_strength = ptarget_wlan->network.PhyInfo.SignalStrength;
+ padapter->recvpriv.signal_qual = ptarget_wlan->network.PhyInfo.SignalQuality;
+ /* the ptarget_wlan->network.Rssi is raw data, we use ptarget_wlan->network.PhyInfo.SignalStrength instead (has scaled) */
+ padapter->recvpriv.rssi = translate_percentage_to_dbm(ptarget_wlan->network.PhyInfo.SignalStrength);
+ rtw_set_signal_stat_timer(&padapter->recvpriv);
+
+ /* update fw_state will clr _FW_UNDER_LINKING here indirectly */
+ switch (pnetwork->network.InfrastructureMode) {
+ case Ndis802_11Infrastructure:
+ if (pmlmepriv->fw_state&WIFI_UNDER_WPS)
+ pmlmepriv->fw_state = WIFI_STATION_STATE|WIFI_UNDER_WPS;
+ else
+ pmlmepriv->fw_state = WIFI_STATION_STATE;
+ break;
+ case Ndis802_11IBSS:
+ pmlmepriv->fw_state = WIFI_ADHOC_STATE;
+ break;
+ default:
+ pmlmepriv->fw_state = WIFI_NULL_STATE;
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Invalid network_mode\n"));
+ break;
+ }
+
+ rtw_update_protection(padapter, (cur_network->network.ies) +
+ sizeof(struct ndis_802_11_fixed_ie),
+ (cur_network->network.ie_length));
+ rtw_update_ht_cap(padapter, cur_network->network.ies, cur_network->network.ie_length);
+}
+
+/* Notes: the function could be > passive_level (the same context as Rx tasklet) */
+/* pnetwork: returns from rtw_joinbss_event_callback */
+/* ptarget_wlan: found from scanned_queue */
+/* if join_res > 0, for (fw_state == WIFI_STATION_STATE), we check if "ptarget_sta" & "ptarget_wlan" exist. */
+/* if join_res > 0, for (fw_state == WIFI_ADHOC_STATE), we only check if "ptarget_wlan" exist. */
+/* if join_res > 0, update "cur_network->network" from "pnetwork->network" if (ptarget_wlan != NULL). */
+
+void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
+{
+ struct sta_info *ptarget_sta = NULL, *pcur_sta = NULL;
+ struct sta_priv *pstapriv = &adapter->stapriv;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
+ struct wlan_network *cur_network = &pmlmepriv->cur_network;
+ struct wlan_network *pcur_wlan = NULL, *ptarget_wlan = NULL;
+ unsigned int the_same_macaddr = false;
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("joinbss event call back received with res=%d\n", pnetwork->join_res));
+
+ rtw_get_encrypt_decrypt_from_registrypriv(adapter);
+
+ if (pmlmepriv->assoc_ssid.ssid_length == 0)
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("@@@@@ joinbss event call back for Any SSid\n"));
+ else
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("@@@@@ rtw_joinbss_event_callback for SSid:%s\n", pmlmepriv->assoc_ssid.ssid));
+
+ the_same_macaddr = !memcmp(pnetwork->network.MacAddress, cur_network->network.MacAddress, ETH_ALEN);
+
+ pnetwork->network.Length = get_wlan_bssid_ex_sz(&pnetwork->network);
+ if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex)) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n\n ***joinbss_evt_callback return a wrong bss ***\n\n"));
+ return;
+ }
+
+ spin_lock_bh(&pmlmepriv->lock);
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("\nrtw_joinbss_event_callback!! _enter_critical\n"));
+
+ if (pnetwork->join_res > 0) {
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+ if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
+ /* s1. find ptarget_wlan */
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ if (the_same_macaddr) {
+ ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
+ } else {
+ pcur_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
+ if (pcur_wlan)
+ pcur_wlan->fixed = false;
+
+ pcur_sta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
+ if (pcur_sta) {
+ spin_lock_bh(&pstapriv->sta_hash_lock);
+ rtw_free_stainfo(adapter, pcur_sta);
+ spin_unlock_bh(&pstapriv->sta_hash_lock);
+ }
+
+ ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
+ if (ptarget_wlan)
+ ptarget_wlan->fixed = true;
+ }
+ }
+ } else {
+ ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
+ if (ptarget_wlan)
+ ptarget_wlan->fixed = true;
+ }
+ }
+
+ /* s2. update cur_network */
+ if (ptarget_wlan) {
+ rtw_joinbss_update_network(adapter, ptarget_wlan, pnetwork);
+ } else {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Can't find ptarget_wlan when joinbss_event callback\n"));
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+ goto ignore_joinbss_callback;
+ }
+
+ /* s3. find ptarget_sta & update ptarget_sta after update cur_network only for station mode */
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
+ ptarget_sta = rtw_joinbss_update_stainfo(adapter, pnetwork);
+ if (!ptarget_sta) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Can't update stainfo when joinbss_event callback\n"));
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+ goto ignore_joinbss_callback;
+ }
+ }
+
+ /* s4. indicate connect */
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
+ rtw_indicate_connect(adapter);
+ } else {
+ /* adhoc mode will rtw_indicate_connect when rtw_stassoc_event_callback */
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("adhoc mode, fw_state:%x", get_fwstate(pmlmepriv)));
+ }
+
+ /* s5. Cancel assoc_timer */
+ del_timer_sync(&pmlmepriv->assoc_timer);
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("Cancel assoc_timer\n"));
+
+ } else {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_joinbss_event_callback err: fw_state:%x", get_fwstate(pmlmepriv)));
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+ goto ignore_joinbss_callback;
+ }
+
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+
+ } else if (pnetwork->join_res == -4) {
+ rtw_reset_securitypriv(adapter);
+ mod_timer(&pmlmepriv->assoc_timer,
+ jiffies + msecs_to_jiffies(1));
+
+ if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("fail! clear _FW_UNDER_LINKING ^^^fw_state=%x\n", get_fwstate(pmlmepriv)));
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+ }
+ } else { /* if join_res < 0 (join fails), then try again */
+ mod_timer(&pmlmepriv->assoc_timer,
+ jiffies + msecs_to_jiffies(1));
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+ }
+
+ignore_joinbss_callback:
+ spin_unlock_bh(&pmlmepriv->lock);
+}
+
+void rtw_joinbss_event_callback(struct adapter *adapter, u8 *pbuf)
+{
+ struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
+
+ mlmeext_joinbss_event_callback(adapter, pnetwork->join_res);
+
+ rtw_os_xmit_schedule(adapter);
+}
+
+static u8 search_max_mac_id(struct adapter *padapter)
+{
+ u8 mac_id;
+#if defined(CPTCFG_88EU_AP_MODE)
+ u8 aid;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+#endif
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+#if defined(CPTCFG_88EU_AP_MODE)
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+ for (aid = pstapriv->max_num_sta; aid > 0; aid--) {
+ if (pstapriv->sta_aid[aid-1])
+ break;
+ }
+ mac_id = aid + 1;
+ } else
+#endif
+ {/* adhoc id = 31~2 */
+ for (mac_id = NUM_STA-1; mac_id >= IBSS_START_MAC_ID; mac_id--) {
+ if (pmlmeinfo->FW_sta_info[mac_id].status == 1)
+ break;
+ }
+ }
+ return mac_id;
+}
+
+/* FOR AP , AD-HOC mode */
+void rtw_stassoc_hw_rpt(struct adapter *adapter, struct sta_info *psta)
+{
+ u16 media_status;
+ u8 macid;
+
+ if (!psta)
+ return;
+
+ macid = search_max_mac_id(adapter);
+ rtw_hal_set_hwreg(adapter, HW_VAR_TX_RPT_MAX_MACID, (u8 *)&macid);
+ media_status = (psta->mac_id<<8)|1; /* MACID|OPMODE:1 connect */
+ rtw_hal_set_hwreg(adapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
+}
+
+void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf)
+{
+ struct sta_info *psta;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ struct stassoc_event *pstassoc = (struct stassoc_event *)pbuf;
+ struct wlan_network *cur_network = &pmlmepriv->cur_network;
+ struct wlan_network *ptarget_wlan = NULL;
+
+ if (!rtw_access_ctrl(adapter, pstassoc->macaddr))
+ return;
+
+#if defined(CPTCFG_88EU_AP_MODE)
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+ psta = rtw_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
+ if (psta) {
+ ap_sta_info_defer_update(adapter, psta);
+ rtw_stassoc_hw_rpt(adapter, psta);
+ }
+ return;
+ }
+#endif
+ /* for AD-HOC mode */
+ psta = rtw_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
+ if (psta) {
+ /* the sta have been in sta_info_queue => do nothing */
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
+ ("Error: %s: sta has been in sta_hash_queue\n",
+ __func__));
+ return; /* between drv has received this event before and fw have not yet to set key to CAM_ENTRY) */
+ }
+ psta = rtw_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr);
+ if (!psta) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
+ ("Can't alloc sta_info when %s\n", __func__));
+ return;
+ }
+ /* to do: init sta_info variable */
+ psta->qos_option = 0;
+ psta->mac_id = (uint)pstassoc->cam_id;
+ DBG_88E("%s\n", __func__);
+ /* for ad-hoc mode */
+ rtw_hal_set_odm_var(adapter, HAL_ODM_STA_INFO, psta, true);
+ rtw_stassoc_hw_rpt(adapter, psta);
+ if (adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
+ psta->dot118021XPrivacy = adapter->securitypriv.dot11PrivacyAlgrthm;
+ psta->ieee8021x_blocked = false;
+ spin_lock_bh(&pmlmepriv->lock);
+ if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
+ (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))) {
+ if (adapter->stapriv.asoc_sta_count == 2) {
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+ ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
+ if (ptarget_wlan)
+ ptarget_wlan->fixed = true;
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+ /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
+ rtw_indicate_connect(adapter);
+ }
+ }
+ spin_unlock_bh(&pmlmepriv->lock);
+ mlmeext_sta_add_event_callback(adapter, psta);
+}
+
+void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf)
+{
+ int mac_id = -1;
+ struct sta_info *psta;
+ struct wlan_network *pwlan = NULL;
+ struct wlan_bssid_ex *pdev_network = NULL;
+ u8 *pibss = NULL;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ struct stadel_event *pstadel = (struct stadel_event *)pbuf;
+ struct sta_priv *pstapriv = &adapter->stapriv;
+ struct wlan_network *tgt_network = &pmlmepriv->cur_network;
+
+ psta = rtw_get_stainfo(&adapter->stapriv, pstadel->macaddr);
+ if (psta)
+ mac_id = psta->mac_id;
+ else
+ mac_id = pstadel->mac_id;
+
+ DBG_88E("%s(mac_id=%d)=%pM\n", __func__, mac_id, pstadel->macaddr);
+
+ if (mac_id >= 0) {
+ u16 media_status;
+
+ media_status = (mac_id<<8)|0; /* MACID|OPMODE:0 means disconnect */
+ /* for STA, AP, ADHOC mode, report disconnect stauts to FW */
+ rtw_hal_set_hwreg(adapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
+ }
+
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ return;
+
+ mlmeext_sta_del_event_callback(adapter);
+
+ spin_lock_bh(&pmlmepriv->lock);
+
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
+ if (pmlmepriv->to_roaming > 0)
+ pmlmepriv->to_roaming--; /* this stadel_event is caused by roaming, decrease to_roaming */
+ else if (pmlmepriv->to_roaming == 0)
+ pmlmepriv->to_roaming = adapter->registrypriv.max_roaming_times;
+
+ if (*((unsigned short *)(pstadel->rsvd)) != WLAN_REASON_EXPIRATION_CHK)
+ pmlmepriv->to_roaming = 0; /* don't roam */
+
+ rtw_free_uc_swdec_pending_queue(adapter);
+
+ rtw_free_assoc_resources(adapter);
+ rtw_indicate_disconnect(adapter);
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+ /* remove the network entry in scanned_queue */
+ pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
+ if (pwlan) {
+ pwlan->fixed = false;
+ rtw_free_network_nolock(pmlmepriv, pwlan);
+ }
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+ _rtw_roaming(adapter, tgt_network);
+ }
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
+ check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
+ spin_lock_bh(&pstapriv->sta_hash_lock);
+ rtw_free_stainfo(adapter, psta);
+ spin_unlock_bh(&pstapriv->sta_hash_lock);
+
+ if (adapter->stapriv.asoc_sta_count == 1) { /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+ /* free old ibss network */
+ pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
+ if (pwlan) {
+ pwlan->fixed = false;
+ rtw_free_network_nolock(pmlmepriv, pwlan);
+ }
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+ /* re-create ibss */
+ pdev_network = &adapter->registrypriv.dev_network;
+ pibss = adapter->registrypriv.dev_network.MacAddress;
+
+ memcpy(pdev_network, &tgt_network->network, get_wlan_bssid_ex_sz(&tgt_network->network));
+
+ memcpy(&pdev_network->ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
+
+ rtw_update_registrypriv_dev_network(adapter);
+
+ rtw_generate_random_ibss(pibss);
+
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
+ set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
+ _clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
+ }
+
+ if (rtw_createbss_cmd(adapter) != _SUCCESS)
+ RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("***Error=>stadel_event_callback: rtw_createbss_cmd status FAIL***\n "));
+ }
+ }
+ spin_unlock_bh(&pmlmepriv->lock);
+}
+
+void rtw_cpwm_event_callback(struct adapter *padapter, u8 *pbuf)
+{
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+%s !!!\n", __func__));
+}
+
+/*
+ * _rtw_join_timeout_handler - Timeout/failure handler for CMD JoinBss
+ * @adapter: pointer to struct adapter structure
+ */
+void _rtw_join_timeout_handler (struct timer_list *t)
+{
+ struct adapter *adapter = from_timer(adapter, t, mlmepriv.assoc_timer);
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ int do_join_r;
+
+ DBG_88E("%s, fw_state=%x\n", __func__, get_fwstate(pmlmepriv));
+
+ if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
+ return;
+
+ spin_lock_bh(&pmlmepriv->lock);
+
+ if (pmlmepriv->to_roaming > 0) { /* join timeout caused by roaming */
+ while (1) {
+ pmlmepriv->to_roaming--;
+ if (pmlmepriv->to_roaming != 0) { /* try another , */
+ DBG_88E("%s try another roaming\n", __func__);
+ do_join_r = rtw_do_join(adapter);
+ if (do_join_r != _SUCCESS) {
+ DBG_88E("%s roaming do_join return %d\n", __func__, do_join_r);
+ continue;
+ }
+ break;
+ }
+ DBG_88E("%s We've try roaming but fail\n", __func__);
+ rtw_indicate_disconnect(adapter);
+ break;
+ }
+ } else {
+ rtw_indicate_disconnect(adapter);
+ free_scanqueue(pmlmepriv);/* */
+ }
+ spin_unlock_bh(&pmlmepriv->lock);
+}
+
+/*
+ * rtw_scan_timeout_handler - Timeout/Failure handler for CMD SiteSurvey
+ * @adapter: pointer to struct adapter structure
+ */
+void rtw_scan_timeout_handler (struct timer_list *t)
+{
+ struct adapter *adapter = from_timer(adapter, t,
+ mlmepriv.scan_to_timer);
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+
+ DBG_88E(FUNC_ADPT_FMT" fw_state=%x\n", FUNC_ADPT_ARG(adapter), get_fwstate(pmlmepriv));
+ spin_lock_bh(&pmlmepriv->lock);
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
+ spin_unlock_bh(&pmlmepriv->lock);
+ rtw_indicate_scan_done(adapter, true);
+}
+
+static void rtw_auto_scan_handler(struct adapter *padapter)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ /* auto site survey per 60sec */
+ if (pmlmepriv->scan_interval > 0) {
+ pmlmepriv->scan_interval--;
+ if (pmlmepriv->scan_interval == 0) {
+ DBG_88E("%s\n", __func__);
+ rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
+ pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */
+ }
+ }
+}
+
+void rtw_dynamic_check_timer_handlder(struct timer_list *t)
+{
+ struct adapter *adapter = from_timer(adapter, t,
+ mlmepriv.dynamic_chk_timer);
+ struct registry_priv *pregistrypriv = &adapter->registrypriv;
+
+ if (!adapter)
+ return;
+ if (!adapter->hw_init_completed)
+ goto exit;
+ if ((adapter->bDriverStopped) || (adapter->bSurpriseRemoved))
+ goto exit;
+ if (adapter->net_closed)
+ goto exit;
+ rtw_dynamic_chk_wk_cmd(adapter);
+
+ if (pregistrypriv->wifi_spec == 1) {
+ /* auto site survey */
+ rtw_auto_scan_handler(adapter);
+ }
+exit:
+ mod_timer(&adapter->mlmepriv.dynamic_chk_timer,
+ jiffies + msecs_to_jiffies(2000));
+}
+
+#define RTW_SCAN_RESULT_EXPIRE 2000
+
+/*
+ * Select a new join candidate from the original @param candidate and @param competitor
+ * @return true: candidate is updated
+ * @return false: candidate is not updated
+ */
+static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv
+ , struct wlan_network **candidate, struct wlan_network *competitor)
+{
+ int updated = false;
+ unsigned long since_scan;
+ struct adapter *adapter = container_of(pmlmepriv, struct adapter,
+ mlmepriv);
+
+ /* check bssid, if needed */
+ if (pmlmepriv->assoc_by_bssid) {
+ if (memcmp(competitor->network.MacAddress, pmlmepriv->assoc_bssid, ETH_ALEN))
+ goto exit;
+ }
+
+ /* check ssid, if needed */
+ if (pmlmepriv->assoc_ssid.ssid_length) {
+ if (competitor->network.ssid.ssid_length != pmlmepriv->assoc_ssid.ssid_length ||
+ memcmp(competitor->network.ssid.ssid, pmlmepriv->assoc_ssid.ssid, pmlmepriv->assoc_ssid.ssid_length))
+ goto exit;
+ }
+
+ if (!rtw_is_desired_network(adapter, competitor))
+ goto exit;
+
+ if (pmlmepriv->to_roaming) {
+ since_scan = jiffies - competitor->last_scanned;
+ if (jiffies_to_msecs(since_scan) >= RTW_SCAN_RESULT_EXPIRE ||
+ !is_same_ess(&competitor->network, &pmlmepriv->cur_network.network))
+ goto exit;
+ }
+
+ if (!*candidate || (*candidate)->network.Rssi < competitor->network.Rssi) {
+ *candidate = competitor;
+ updated = true;
+ }
+ if (updated) {
+ DBG_88E("[by_bssid:%u][assoc_ssid:%s]new candidate: %s(%pM rssi:%d\n",
+ pmlmepriv->assoc_by_bssid,
+ pmlmepriv->assoc_ssid.ssid,
+ (*candidate)->network.ssid.ssid,
+ (*candidate)->network.MacAddress,
+ (int)(*candidate)->network.Rssi);
+ DBG_88E("[to_roaming:%u]\n", pmlmepriv->to_roaming);
+ }
+
+exit:
+ return updated;
+}
+
+/*
+ * Calling context:
+ * The caller of the sub-routine will be in critical section...
+ * The caller must hold the following spinlock
+ * pmlmepriv->lock
+ */
+
+int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv)
+{
+ int ret;
+ struct list_head *phead;
+ struct adapter *adapter;
+ struct __queue *queue = &pmlmepriv->scanned_queue;
+ struct wlan_network *pnetwork = NULL;
+ struct wlan_network *candidate = NULL;
+ u8 supp_ant_div = false;
+
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+ phead = get_list_head(queue);
+ adapter = (struct adapter *)pmlmepriv->nic_hdl;
+ pmlmepriv->pscanned = phead->next;
+ while (phead != pmlmepriv->pscanned) {
+ pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
+ if (!pnetwork) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s return _FAIL:(pnetwork==NULL)\n", __func__));
+ ret = _FAIL;
+ goto exit;
+ }
+ pmlmepriv->pscanned = pmlmepriv->pscanned->next;
+ rtw_check_join_candidate(pmlmepriv, &candidate, pnetwork);
+ }
+ if (!candidate) {
+ DBG_88E("%s: return _FAIL(candidate==NULL)\n", __func__);
+ ret = _FAIL;
+ goto exit;
+ } else {
+ DBG_88E("%s: candidate: %s(%pM ch:%u)\n", __func__,
+ candidate->network.ssid.ssid, candidate->network.MacAddress,
+ candidate->network.Configuration.DSConfig);
+ }
+
+ /* check for situation of _FW_LINKED */
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ DBG_88E("%s: _FW_LINKED while ask_for_joinbss!!!\n", __func__);
+
+ rtw_disassoc_cmd(adapter, 0, true);
+ rtw_indicate_disconnect(adapter);
+ rtw_free_assoc_resources_locked(adapter);
+ }
+
+ rtw_hal_get_def_var(adapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &(supp_ant_div));
+ if (supp_ant_div) {
+ u8 cur_ant;
+
+ rtw_hal_get_def_var(adapter, HAL_DEF_CURRENT_ANTENNA, &(cur_ant));
+ DBG_88E("#### Opt_Ant_(%s), cur_Ant(%s)\n",
+ (candidate->network.PhyInfo.Optimum_antenna == 2) ? "A" : "B",
+ (cur_ant == 2) ? "A" : "B"
+ );
+ }
+
+ ret = rtw_joinbss_cmd(adapter, candidate);
+
+exit:
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+ return ret;
+}
+
+int rtw_set_auth(struct adapter *adapter, struct security_priv *psecuritypriv)
+{
+ struct cmd_obj *pcmd;
+ struct setauth_parm *psetauthparm;
+ struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
+ int res = _SUCCESS;
+
+ pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+ if (!pcmd) {
+ res = _FAIL; /* try again */
+ goto exit;
+ }
+
+ psetauthparm = kzalloc(sizeof(struct setauth_parm), GFP_KERNEL);
+ if (!psetauthparm) {
+ kfree(pcmd);
+ res = _FAIL;
+ goto exit;
+ }
+ psetauthparm->mode = (unsigned char)psecuritypriv->dot11AuthAlgrthm;
+ pcmd->cmdcode = _SetAuth_CMD_;
+ pcmd->parmbuf = (unsigned char *)psetauthparm;
+ pcmd->cmdsz = sizeof(struct setauth_parm);
+ pcmd->rsp = NULL;
+ pcmd->rspsz = 0;
+ INIT_LIST_HEAD(&pcmd->list);
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
+ ("after enqueue set_auth_cmd, auth_mode=%x\n",
+ psecuritypriv->dot11AuthAlgrthm));
+ res = rtw_enqueue_cmd(pcmdpriv, pcmd);
+exit:
+ return res;
+}
+
+int rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv, int keyid, u8 set_tx)
+{
+ u8 keylen;
+ struct cmd_obj *pcmd;
+ struct setkey_parm *psetkeyparm;
+ struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ int res = _SUCCESS;
+
+ pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+ if (!pcmd)
+ return _FAIL; /* try again */
+
+ psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
+ if (!psetkeyparm) {
+ res = _FAIL;
+ goto err_free_cmd;
+ }
+
+ if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
+ psetkeyparm->algorithm = (unsigned char)psecuritypriv->dot118021XGrpPrivacy;
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
+ ("\n %s: psetkeyparm->algorithm=(unsigned char)psecuritypriv->dot118021XGrpPrivacy=%d\n",
+ __func__, psetkeyparm->algorithm));
+ } else {
+ psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm;
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
+ ("\n %s: psetkeyparm->algorithm=(u8)psecuritypriv->dot11PrivacyAlgrthm=%d\n",
+ __func__, psetkeyparm->algorithm));
+ }
+ psetkeyparm->keyid = (u8)keyid;/* 0~3 */
+ psetkeyparm->set_tx = set_tx;
+ pmlmepriv->key_mask |= BIT(psetkeyparm->keyid);
+ DBG_88E("==> %s algorithm(%x), keyid(%x), key_mask(%x)\n",
+ __func__, psetkeyparm->algorithm, psetkeyparm->keyid,
+ pmlmepriv->key_mask);
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
+ ("\n %s: psetkeyparm->algorithm=%d psetkeyparm->keyid=(u8)keyid=%d\n",
+ __func__, psetkeyparm->algorithm, keyid));
+
+ switch (psetkeyparm->algorithm) {
+ case _WEP40_:
+ keylen = 5;
+ memcpy(&psetkeyparm->key[0],
+ &psecuritypriv->dot11DefKey[keyid].skey[0], keylen);
+ break;
+ case _WEP104_:
+ keylen = 13;
+ memcpy(&psetkeyparm->key[0],
+ &psecuritypriv->dot11DefKey[keyid].skey[0], keylen);
+ break;
+ case _TKIP_:
+ keylen = 16;
+ memcpy(&psetkeyparm->key, &psecuritypriv->dot118021XGrpKey[keyid], keylen);
+ psetkeyparm->grpkey = 1;
+ break;
+ case _AES_:
+ keylen = 16;
+ memcpy(&psetkeyparm->key, &psecuritypriv->dot118021XGrpKey[keyid], keylen);
+ psetkeyparm->grpkey = 1;
+ break;
+ default:
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
+ ("\n %s:psecuritypriv->dot11PrivacyAlgrthm=%x (must be 1 or 2 or 4 or 5)\n",
+ __func__, psecuritypriv->dot11PrivacyAlgrthm));
+ res = _FAIL;
+ goto err_free_parm;
+ }
+ pcmd->cmdcode = _SetKey_CMD_;
+ pcmd->parmbuf = (u8 *)psetkeyparm;
+ pcmd->cmdsz = sizeof(struct setkey_parm);
+ pcmd->rsp = NULL;
+ pcmd->rspsz = 0;
+ INIT_LIST_HEAD(&pcmd->list);
+ return rtw_enqueue_cmd(pcmdpriv, pcmd);
+
+err_free_parm:
+ kfree(psetkeyparm);
+err_free_cmd:
+ kfree(pcmd);
+ return res;
+}
+
+/* adjust ies for rtw_joinbss_cmd in WMM */
+int rtw_restruct_wmm_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_len, uint initial_out_len)
+{
+ unsigned int ielength = 0;
+ unsigned int i, j;
+
+ /* i = 12; after the fixed IE */
+ for (i = 12; i < in_len; i += (in_ie[i + 1] + 2) /* to the next IE element */) {
+ ielength = initial_out_len;
+
+ if (in_ie[i] == 0xDD && in_ie[i+2] == 0x00 && in_ie[i+3] == 0x50 && in_ie[i+4] == 0xF2 && in_ie[i+5] == 0x02 && i+5 < in_len) {
+ /* WMM element ID and OUI */
+ /* Append WMM IE to the last index of out_ie */
+
+ for (j = i; j < i + 9; j++) {
+ out_ie[ielength] = in_ie[j];
+ ielength++;
+ }
+ out_ie[initial_out_len + 1] = 0x07;
+ out_ie[initial_out_len + 6] = 0x00;
+ out_ie[initial_out_len + 8] = 0x00;
+ break;
+ }
+ }
+ return ielength;
+}
+
+/*
+ * Ported from 8185: IsInPreAuthKeyList().
+ * (Renamed from SecIsInPreAuthKeyList(), 2006-10-13.)
+ * Added by Annie, 2006-05-07.
+ * Search by BSSID,
+ * Return Value:
+ * -1 :if there is no pre-auth key in the table
+ * >= 0 :if there is pre-auth key, and return the entry id
+ */
+static int SecIsInPMKIDList(struct adapter *Adapter, u8 *bssid)
+{
+ struct security_priv *psecuritypriv = &Adapter->securitypriv;
+ int i = 0;
+
+ do {
+ if ((psecuritypriv->PMKIDList[i].bUsed) &&
+ (!memcmp(psecuritypriv->PMKIDList[i].Bssid, bssid, ETH_ALEN)))
+ break;
+ } while (++i < NUM_PMKID_CACHE);
+
+ if (i == NUM_PMKID_CACHE)
+ i = -1;/* Could not find. */
+
+ return i;
+}
+
+/* */
+/* Check the RSN IE length */
+/* If the RSN IE length <= 20, the RSN IE didn't include the PMKID information */
+/* 0-11th element in the array are the fixed IE */
+/* 12th element in the array is the IE */
+/* 13th element in the array is the IE length */
+/* */
+
+static int rtw_append_pmkid(struct adapter *Adapter, int iEntry, u8 *ie, uint ie_len)
+{
+ struct security_priv *psecuritypriv = &Adapter->securitypriv;
+
+ if (ie[13] <= 20) {
+ /* The RSN IE didn't include the PMK ID, append the PMK information */
+ ie[ie_len] = 1;
+ ie_len++;
+ ie[ie_len] = 0; /* PMKID count = 0x0100 */
+ ie_len++;
+ memcpy(&ie[ie_len], &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
+
+ ie_len += 16;
+ ie[13] += 18;/* PMKID length = 2+16 */
+ }
+ return ie_len;
+}
+
+int rtw_restruct_sec_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_len)
+{
+ u8 authmode;
+ uint ielength;
+ int iEntry;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ struct security_priv *psecuritypriv = &adapter->securitypriv;
+ uint ndisauthmode = psecuritypriv->ndisauthtype;
+ uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
+ ("+%s: ndisauthmode=%d ndissecuritytype=%d\n", __func__,
+ ndisauthmode, ndissecuritytype));
+
+ /* copy fixed ie only */
+ memcpy(out_ie, in_ie, 12);
+ ielength = 12;
+ if ((ndisauthmode == Ndis802_11AuthModeWPA) ||
+ (ndisauthmode == Ndis802_11AuthModeWPAPSK))
+ authmode = _WPA_IE_ID_;
+ if ((ndisauthmode == Ndis802_11AuthModeWPA2) ||
+ (ndisauthmode == Ndis802_11AuthModeWPA2PSK))
+ authmode = _WPA2_IE_ID_;
+
+ if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
+ memcpy(out_ie+ielength, psecuritypriv->wps_ie, psecuritypriv->wps_ie_len);
+
+ ielength += psecuritypriv->wps_ie_len;
+ } else if ((authmode == _WPA_IE_ID_) || (authmode == _WPA2_IE_ID_)) {
+ /* copy RSN or SSN */
+ memcpy(&out_ie[ielength], &psecuritypriv->supplicant_ie[0], psecuritypriv->supplicant_ie[1]+2);
+ ielength += psecuritypriv->supplicant_ie[1]+2;
+ rtw_report_sec_ie(adapter, authmode, psecuritypriv->supplicant_ie);
+ }
+
+ iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
+ if (iEntry >= 0 && authmode == _WPA2_IE_ID_)
+ ielength = rtw_append_pmkid(adapter, iEntry, out_ie, ielength);
+
+ return ielength;
+}
+
+void rtw_init_registrypriv_dev_network(struct adapter *adapter)
+{
+ struct registry_priv *pregistrypriv = &adapter->registrypriv;
+ struct eeprom_priv *peepriv = &adapter->eeprompriv;
+ struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
+ u8 *myhwaddr = myid(peepriv);
+
+ memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN);
+
+ memcpy(&pdev_network->ssid, &pregistrypriv->ssid, sizeof(struct ndis_802_11_ssid));
+
+ pdev_network->Configuration.Length = sizeof(struct ndis_802_11_config);
+ pdev_network->Configuration.BeaconPeriod = 100;
+ pdev_network->Configuration.FHConfig.Length = 0;
+ pdev_network->Configuration.FHConfig.HopPattern = 0;
+ pdev_network->Configuration.FHConfig.HopSet = 0;
+ pdev_network->Configuration.FHConfig.DwellTime = 0;
+}
+
+void rtw_update_registrypriv_dev_network(struct adapter *adapter)
+{
+ int sz = 0;
+ struct registry_priv *pregistrypriv = &adapter->registrypriv;
+ struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
+ struct security_priv *psecuritypriv = &adapter->securitypriv;
+ struct wlan_network *cur_network = &adapter->mlmepriv.cur_network;
+
+ pdev_network->Privacy = psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0; /* adhoc no 802.1x */
+
+ pdev_network->Rssi = 0;
+
+ switch (pregistrypriv->wireless_mode) {
+ case WIRELESS_11B:
+ pdev_network->NetworkTypeInUse = Ndis802_11DS;
+ break;
+ case WIRELESS_11G:
+ case WIRELESS_11BG:
+ case WIRELESS_11_24N:
+ case WIRELESS_11G_24N:
+ case WIRELESS_11BG_24N:
+ pdev_network->NetworkTypeInUse = Ndis802_11OFDM24;
+ break;
+ default:
+ pdev_network->NetworkTypeInUse = Ndis802_11OFDM24;
+ break;
+ }
+
+ pdev_network->Configuration.DSConfig = pregistrypriv->channel;
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
+ ("pregistrypriv->channel=%d, pdev_network->Configuration.DSConfig=0x%x\n",
+ pregistrypriv->channel, pdev_network->Configuration.DSConfig));
+
+ if (cur_network->network.InfrastructureMode == Ndis802_11IBSS)
+ pdev_network->Configuration.ATIMWindow = 0;
+
+ pdev_network->InfrastructureMode = cur_network->network.InfrastructureMode;
+
+ /* 1. Supported rates */
+ /* 2. IE */
+
+ sz = rtw_generate_ie(pregistrypriv);
+ pdev_network->ie_length = sz;
+ pdev_network->Length = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network);
+
+ /* notes: translate ie_length & Length after assign the Length to cmdsz in createbss_cmd(); */
+ /* pdev_network->ie_length = cpu_to_le32(sz); */
+}
+
+void rtw_get_encrypt_decrypt_from_registrypriv(struct adapter *adapter)
+{
+}
+
+/* the function is at passive_level */
+void rtw_joinbss_reset(struct adapter *padapter)
+{
+ u8 threshold;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
+
+ /* todo: if you want to do something io/reg/hw setting before join_bss, please add code here */
+ pmlmepriv->num_FortyMHzIntolerant = 0;
+
+ pmlmepriv->num_sta_no_ht = 0;
+
+ phtpriv->ampdu_enable = false;/* reset to disabled */
+
+ /* TH = 1 => means that invalidate usb rx aggregation */
+ /* TH = 0 => means that validate usb rx aggregation, use init value. */
+ if (phtpriv->ht_option) {
+ if (padapter->registrypriv.wifi_spec == 1)
+ threshold = 1;
+ else
+ threshold = 0;
+ rtw_hal_set_hwreg(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
+ } else {
+ threshold = 1;
+ rtw_hal_set_hwreg(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
+ }
+}
+
+/* the function is >= passive_level */
+unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ie, uint in_len, uint *pout_len)
+{
+ u32 ielen, out_len;
+ enum ht_cap_ampdu_factor max_rx_ampdu_factor;
+ unsigned char *p;
+ unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct qos_priv *pqospriv = &pmlmepriv->qospriv;
+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
+ u32 rx_packet_offset, max_recvbuf_sz;
+
+ phtpriv->ht_option = false;
+
+ p = rtw_get_ie(in_ie+12, _HT_CAPABILITY_IE_, &ielen, in_len-12);
+
+ if (p && ielen > 0) {
+ struct ieee80211_ht_cap ht_cap;
+
+ if (pqospriv->qos_option == 0) {
+ out_len = *pout_len;
+ rtw_set_ie(out_ie + out_len, _VENDOR_SPECIFIC_IE_,
+ _WMM_IE_Length_, WMM_IE, pout_len);
+
+ pqospriv->qos_option = 1;
+ }
+
+ out_len = *pout_len;
+
+ memset(&ht_cap, 0, sizeof(struct ieee80211_ht_cap));
+
+ ht_cap.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH |
+ IEEE80211_HT_CAP_SGI_20 |
+ IEEE80211_HT_CAP_SGI_40 |
+ IEEE80211_HT_CAP_TX_STBC |
+ IEEE80211_HT_CAP_DSSSCCK40);
+
+ rtw_hal_get_def_var(padapter, HAL_DEF_RX_PACKET_OFFSET, &rx_packet_offset);
+ rtw_hal_get_def_var(padapter, HAL_DEF_MAX_RECVBUF_SZ, &max_recvbuf_sz);
+
+ /*
+ ampdu_params_info [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
+ ampdu_params_info [4:2]:Min MPDU Start Spacing
+ */
+
+ rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
+ ht_cap.ampdu_params_info = max_rx_ampdu_factor & 0x03;
+
+ if (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
+ ht_cap.ampdu_params_info |= IEEE80211_HT_CAP_AMPDU_DENSITY & (0x07 << 2);
+ else
+ ht_cap.ampdu_params_info |= IEEE80211_HT_CAP_AMPDU_DENSITY & 0x00;
+
+ rtw_set_ie(out_ie+out_len, _HT_CAPABILITY_IE_,
+ sizeof(struct ieee80211_ht_cap),
+ (unsigned char *)&ht_cap, pout_len);
+
+ phtpriv->ht_option = true;
+
+ p = rtw_get_ie(in_ie+12, _HT_ADD_INFO_IE_, &ielen, in_len-12);
+ if (p && (ielen == sizeof(struct ieee80211_ht_addt_info))) {
+ out_len = *pout_len;
+ rtw_set_ie(out_ie+out_len, _HT_ADD_INFO_IE_, ielen, p+2, pout_len);
+ }
+ }
+ return phtpriv->ht_option;
+}
+
+/* the function is > passive_level (in critical_section) */
+void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ if (!phtpriv->ht_option)
+ return;
+
+ if ((!pmlmeinfo->HT_info_enable) || (!pmlmeinfo->HT_caps_enable))
+ return;
+
+ DBG_88E("+%s()\n", __func__);
+
+ /* maybe needs check if ap supports rx ampdu. */
+ if ((!phtpriv->ampdu_enable) && (pregistrypriv->ampdu_enable == 1)) {
+ if (pregistrypriv->wifi_spec == 1)
+ phtpriv->ampdu_enable = false;
+ else
+ phtpriv->ampdu_enable = true;
+ } else if (pregistrypriv->ampdu_enable == 2) {
+ phtpriv->ampdu_enable = true;
+ }
+
+ /* update cur_bwmode & cur_ch_offset */
+ if ((pregistrypriv->cbw40_enable) &&
+ (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & BIT(1)) &&
+ (pmlmeinfo->HT_info.infos[0] & BIT(2))) {
+ int i;
+
+ /* update the MCS rates */
+ for (i = 0; i < 16; i++)
+ ((u8 *)&pmlmeinfo->HT_caps.mcs)[i] &= MCS_rate_1R[i];
+ /* switch to the 40M Hz mode according to the AP */
+ pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
+ switch ((pmlmeinfo->HT_info.infos[0] & 0x3)) {
+ case HT_EXTCHNL_OFFSET_UPPER:
+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
+ break;
+ case HT_EXTCHNL_OFFSET_LOWER:
+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
+ break;
+ default:
+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ break;
+ }
+ }
+
+ /* Config SM Power Save setting */
+ pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->HT_caps.cap_info) & 0x0C) >> 2;
+ if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
+ DBG_88E("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__);
+
+ /* Config current HT Protection mode. */
+ pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3;
+}
+
+void rtw_issue_addbareq_cmd(struct adapter *padapter, struct xmit_frame *pxmitframe)
+{
+ u8 issued;
+ int priority;
+ struct sta_info *psta = NULL;
+ struct ht_priv *phtpriv;
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+
+ if (is_multicast_ether_addr(pattrib->ra) ||
+ padapter->mlmepriv.LinkDetectInfo.NumTxOkInPeriod < 100)
+ return;
+
+ priority = pattrib->priority;
+
+ if (pattrib->psta)
+ psta = pattrib->psta;
+ else
+ psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
+
+ if (!psta)
+ return;
+
+ phtpriv = &psta->htpriv;
+
+ if ((phtpriv->ht_option) && (phtpriv->ampdu_enable)) {
+ issued = (phtpriv->agg_enable_bitmap >> priority) & 0x1;
+ issued |= (phtpriv->candidate_tid_bitmap >> priority) & 0x1;
+
+ if (issued == 0) {
+ DBG_88E("%s, p=%d\n", __func__, priority);
+ psta->htpriv.candidate_tid_bitmap |= BIT((u8)priority);
+ rtw_addbareq_cmd(padapter, (u8)priority, pattrib->ra);
+ }
+ }
+}
+
+void rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ spin_lock_bh(&pmlmepriv->lock);
+ _rtw_roaming(padapter, tgt_network);
+ spin_unlock_bh(&pmlmepriv->lock);
+}
+
+void _rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ int do_join_r;
+ struct wlan_network *pnetwork;
+
+ if (tgt_network)
+ pnetwork = tgt_network;
+ else
+ pnetwork = &pmlmepriv->cur_network;
+
+ if (pmlmepriv->to_roaming > 0) {
+ DBG_88E("roaming from %s(%pM length:%d\n",
+ pnetwork->network.ssid.ssid, pnetwork->network.MacAddress,
+ pnetwork->network.ssid.ssid_length);
+ memcpy(&pmlmepriv->assoc_ssid, &pnetwork->network.ssid, sizeof(struct ndis_802_11_ssid));
+
+ pmlmepriv->assoc_by_bssid = false;
+
+ while (1) {
+ do_join_r = rtw_do_join(padapter);
+ if (do_join_r == _SUCCESS) {
+ break;
+ }
+ DBG_88E("roaming do_join return %d\n", do_join_r);
+ pmlmepriv->to_roaming--;
+
+ if (pmlmepriv->to_roaming > 0) {
+ continue;
+ } else {
+ DBG_88E("%s(%d) -to roaming fail, indicate_disconnect\n", __func__, __LINE__);
+ rtw_indicate_disconnect(padapter);
+ break;
+ }
+ }
+ }
+}
diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
new file mode 100644
index 0000000..7c516ec
--- /dev/null
+++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
@@ -0,0 +1,5483 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _RTW_MLME_EXT_C_
+
+#include <linux/ieee80211.h>
+#include <asm/unaligned.h>
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <wifi.h>
+#include <rtw_mlme_ext.h>
+#include <wlan_bssdef.h>
+#include <mlme_osdep.h>
+#include <recv_osdep.h>
+
+static u8 null_addr[ETH_ALEN] = {};
+
+/**************************************************
+OUI definitions for the vendor specific IE
+***************************************************/
+const u8 RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
+const u8 WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
+static const u8 WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02};
+static const u8 P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09};
+
+static const u8 WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
+
+const u8 WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02};
+const u8 RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02};
+
+/********************************************************
+MCS rate definitions
+*********************************************************/
+const u8 MCS_rate_1R[16] = {
+ 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/********************************************************
+ChannelPlan definitions
+*********************************************************/
+static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */
+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, /* 0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, /* 0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
+ {{10, 11, 12, 13}, 4}, /* 0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
+ {{}, 0}, /* 0x05, RT_CHANNEL_DOMAIN_2G_NULL */
+};
+
+static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
+ /* 0x00 ~ 0x1F , Old Define ===== */
+ {0x02}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */
+ {0x02}, /* 0x01, RT_CHANNEL_DOMAIN_IC */
+ {0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */
+ {0x01}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
+ {0x01}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
+ {0x03}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */
+ {0x03}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
+ {0x01}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
+ {0x03}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */
+ {0x03}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
+ {0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
+ {0x02}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
+ {0x01}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
+ {0x02}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
+ {0x02}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
+ {0x02}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
+ {0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
+ {0x02}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
+ {0x01}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
+ {0x00}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */
+ {0x02}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
+ {0x00}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
+ {0x00}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
+ {0x03}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
+ {0x05}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
+ {0x02}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
+ {0x00}, /* 0x1A, */
+ {0x00}, /* 0x1B, */
+ {0x00}, /* 0x1C, */
+ {0x00}, /* 0x1D, */
+ {0x00}, /* 0x1E, */
+ {0x05}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */
+ /* 0x20 ~ 0x7F , New Define ===== */
+ {0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
+ {0x01}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
+ {0x02}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
+ {0x03}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
+ {0x04}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
+ {0x02}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
+ {0x00}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
+ {0x03}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
+ {0x00}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
+ {0x00}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
+ {0x00}, /* 0x2A, */
+ {0x00}, /* 0x2B, */
+ {0x00}, /* 0x2C, */
+ {0x00}, /* 0x2D, */
+ {0x00}, /* 0x2E, */
+ {0x00}, /* 0x2F, */
+ {0x00}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
+ {0x00}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
+ {0x00}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
+ {0x00}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
+ {0x02}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
+ {0x00}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
+ {0x00}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
+ {0x03}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
+ {0x03}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
+ {0x02}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
+ {0x00}, /* 0x3A, */
+ {0x00}, /* 0x3B, */
+ {0x00}, /* 0x3C, */
+ {0x00}, /* 0x3D, */
+ {0x00}, /* 0x3E, */
+ {0x00}, /* 0x3F, */
+ {0x02}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
+ {0x03}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */
+};
+
+static const struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {
+ 0x03
+}; /* use the combination for max channel numbers */
+
+/*
+ * Search the @param channel_num in given @param channel_set
+ * @ch_set: the given channel set
+ * @ch: the given channel number
+ *
+ * return the index of channel_num in channel_set, -1 if not found
+ */
+int rtw_ch_set_search_ch(struct rt_channel_info *ch_set, const u32 ch)
+{
+ int i;
+
+ for (i = 0; ch_set[i].ChannelNum != 0; i++) {
+ if (ch == ch_set[i].ChannelNum)
+ break;
+ }
+
+ if (i >= ch_set[i].ChannelNum)
+ return -1;
+ return i;
+}
+
+struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
+{
+ struct xmit_frame *pmgntframe;
+ struct xmit_buf *pxmitbuf;
+
+ pmgntframe = rtw_alloc_xmitframe(pxmitpriv);
+ if (!pmgntframe) {
+ DBG_88E("%s, alloc xmitframe fail\n", __func__);
+ return NULL;
+ }
+
+ pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv);
+ if (!pxmitbuf) {
+ DBG_88E("%s, alloc xmitbuf fail\n", __func__);
+ rtw_free_xmitframe(pxmitpriv, pmgntframe);
+ return NULL;
+ }
+ pmgntframe->frame_tag = MGNT_FRAMETAG;
+ pmgntframe->pxmitbuf = pxmitbuf;
+ pmgntframe->buf_addr = pxmitbuf->pbuf;
+ pxmitbuf->priv_data = pmgntframe;
+ return pmgntframe;
+}
+
+/****************************************************************************
+
+Following are some TX functions for WiFi MLME
+
+*****************************************************************************/
+
+void update_mgnt_tx_rate(struct adapter *padapter, u8 rate)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ pmlmeext->tx_rate = rate;
+ DBG_88E("%s(): rate = %x\n", __func__, rate);
+}
+
+void update_mgntframe_attrib(struct adapter *padapter, struct pkt_attrib *pattrib)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib));
+
+ pattrib->hdrlen = 24;
+ pattrib->nr_frags = 1;
+ pattrib->priority = 7;
+ pattrib->mac_id = 0;
+ pattrib->qsel = 0x12;
+
+ pattrib->pktlen = 0;
+
+ if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
+ pattrib->raid = 6;/* b mode */
+ else
+ pattrib->raid = 5;/* a/g mode */
+
+ pattrib->encrypt = _NO_PRIVACY_;
+ pattrib->bswenc = false;
+
+ pattrib->qos_en = false;
+ pattrib->ht_en = false;
+ pattrib->bwmode = HT_CHANNEL_WIDTH_20;
+ pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ pattrib->sgi = false;
+
+ pattrib->seqnum = pmlmeext->mgnt_seq;
+
+ pattrib->retry_ctrl = true;
+}
+
+static void dump_mgntframe(struct adapter *padapter,
+ struct xmit_frame *pmgntframe)
+{
+ if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
+ return;
+
+ rtw_hal_mgnt_xmit(padapter, pmgntframe);
+}
+
+static s32 dump_mgntframe_and_wait(struct adapter *padapter,
+ struct xmit_frame *pmgntframe,
+ int timeout_ms)
+{
+ s32 ret = _FAIL;
+ struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
+ struct submit_ctx sctx;
+
+ if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
+ return ret;
+
+ rtw_sctx_init(&sctx, timeout_ms);
+ pxmitbuf->sctx = &sctx;
+
+ ret = rtw_hal_mgnt_xmit(padapter, pmgntframe);
+
+ if (ret == _SUCCESS)
+ ret = rtw_sctx_wait(&sctx);
+
+ return ret;
+}
+
+static s32 dump_mgntframe_and_wait_ack(struct adapter *padapter,
+ struct xmit_frame *pmgntframe)
+{
+ s32 ret = _FAIL;
+ u32 timeout_ms = 500;/* 500ms */
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+ if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
+ return -1;
+
+ if (mutex_lock_interruptible(&pxmitpriv->ack_tx_mutex))
+ return _FAIL;
+ pxmitpriv->ack_tx = true;
+
+ pmgntframe->ack_report = 1;
+ if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS)
+ ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms);
+
+ pxmitpriv->ack_tx = false;
+ mutex_unlock(&pxmitpriv->ack_tx_mutex);
+
+ return ret;
+}
+
+static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
+{
+ u8 *ssid_ie;
+ uint ssid_len_ori;
+ int len_diff = 0;
+
+ ssid_ie = rtw_get_ie(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len);
+
+ if (ssid_ie && ssid_len_ori > 0) {
+ switch (hidden_ssid_mode) {
+ case 1: {
+ u8 *next_ie = ssid_ie + 2 + ssid_len_ori;
+ u32 remain_len = 0;
+
+ remain_len = ies_len - (next_ie - ies);
+
+ ssid_ie[1] = 0;
+ memcpy(ssid_ie+2, next_ie, remain_len);
+ len_diff -= ssid_len_ori;
+
+ break;
+ }
+ case 2:
+ memset(&ssid_ie[2], 0, ssid_len_ori);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return len_diff;
+}
+
+static void issue_beacon(struct adapter *padapter, int timeout_ms)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ unsigned int rate_len;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
+ u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe) {
+ DBG_88E("%s, alloc mgnt frame fail\n", __func__);
+ return;
+ }
+#if defined(CPTCFG_88EU_AP_MODE)
+ spin_lock_bh(&pmlmepriv->bcn_update_lock);
+#endif
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+ pattrib->qsel = 0x10;
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_control;
+ *(fctrl) = 0;
+
+ ether_addr_copy(pwlanhdr->addr1, bc_addr);
+ ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
+ ether_addr_copy(pwlanhdr->addr3, cur_network->MacAddress);
+
+ SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
+ /* pmlmeext->mgnt_seq++; */
+ SetFrameSubType(pframe, WIFI_BEACON);
+
+ pframe += sizeof(struct ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
+
+ if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
+ int len_diff;
+ u8 *wps_ie;
+ uint wps_ielen;
+ u8 sr = 0;
+
+ memcpy(pframe, cur_network->ies, cur_network->ie_length);
+ len_diff = update_hidden_ssid(
+ pframe+_BEACON_IE_OFFSET_
+ , cur_network->ie_length-_BEACON_IE_OFFSET_
+ , pmlmeinfo->hidden_ssid_mode
+ );
+ pframe += (cur_network->ie_length+len_diff);
+ pattrib->pktlen += (cur_network->ie_length+len_diff);
+ wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_,
+ pattrib->pktlen-sizeof(struct ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen);
+ if (wps_ie && wps_ielen > 0)
+ rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
+ if (sr != 0)
+ set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
+ else
+ _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
+
+ goto _issue_bcn;
+ }
+
+ /* below for ad-hoc mode */
+
+ /* timestamp will be inserted by hardware */
+ pframe += 8;
+ pattrib->pktlen += 8;
+
+ /* beacon interval: 2 bytes */
+
+ memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->ies)), 2);
+
+ pframe += 2;
+ pattrib->pktlen += 2;
+
+ /* capability info: 2 bytes */
+
+ memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->ies)), 2);
+
+ pframe += 2;
+ pattrib->pktlen += 2;
+
+ /* SSID */
+ pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pattrib->pktlen);
+
+ /* supported rates... */
+ rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, min_t(unsigned int, rate_len, 8), cur_network->SupportedRates, &pattrib->pktlen);
+
+ /* DS parameter set */
+ pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&cur_network->Configuration.DSConfig, &pattrib->pktlen);
+
+ {
+ u8 erpinfo = 0;
+ u32 ATIMWindow;
+ /* IBSS Parameter Set... */
+ ATIMWindow = 0;
+ pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
+
+ /* ERP IE */
+ pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
+ }
+
+ /* EXTERNDED SUPPORTED RATE */
+ if (rate_len > 8)
+ pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
+ /* todo:HT for adhoc */
+_issue_bcn:
+
+#if defined(CPTCFG_88EU_AP_MODE)
+ pmlmepriv->update_bcn = false;
+
+ spin_unlock_bh(&pmlmepriv->bcn_update_lock);
+#endif
+
+ if ((pattrib->pktlen + TXDESC_SIZE) > 512) {
+ DBG_88E("beacon frame too large\n");
+ return;
+ }
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ /* DBG_88E("issue bcn_sz=%d\n", pattrib->last_txcmdsz); */
+ if (timeout_ms > 0)
+ dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms);
+ else
+ dump_mgntframe(padapter, pmgntframe);
+}
+
+static void issue_probersp(struct adapter *padapter, unsigned char *da)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ unsigned char *mac, *bssid;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+#if defined(CPTCFG_88EU_AP_MODE)
+ u8 *pwps_ie;
+ uint wps_ielen;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+#endif
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
+ unsigned int rate_len;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe) {
+ DBG_88E("%s, alloc mgnt frame fail\n", __func__);
+ return;
+ }
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct ieee80211_hdr *)pframe;
+
+ mac = myid(&padapter->eeprompriv);
+ bssid = cur_network->MacAddress;
+
+ fctrl = &pwlanhdr->frame_control;
+ *(fctrl) = 0;
+ ether_addr_copy(pwlanhdr->addr1, da);
+ ether_addr_copy(pwlanhdr->addr2, mac);
+ ether_addr_copy(pwlanhdr->addr3, bssid);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(fctrl, WIFI_PROBERSP);
+
+ pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
+ pattrib->pktlen = pattrib->hdrlen;
+ pframe += pattrib->hdrlen;
+
+ if (cur_network->ie_length > MAX_IE_SZ)
+ return;
+
+#if defined(CPTCFG_88EU_AP_MODE)
+ if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
+ pwps_ie = rtw_get_wps_ie(cur_network->ies+_FIXED_IE_LENGTH_, cur_network->ie_length-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
+
+ /* inerset & update wps_probe_resp_ie */
+ if ((pmlmepriv->wps_probe_resp_ie != NULL) && pwps_ie && (wps_ielen > 0)) {
+ uint wps_offset, remainder_ielen;
+ u8 *premainder_ie;
+
+ wps_offset = (uint)(pwps_ie - cur_network->ies);
+
+ premainder_ie = pwps_ie + wps_ielen;
+
+ remainder_ielen = cur_network->ie_length - wps_offset - wps_ielen;
+
+ memcpy(pframe, cur_network->ies, wps_offset);
+ pframe += wps_offset;
+ pattrib->pktlen += wps_offset;
+
+ wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */
+ if ((wps_offset+wps_ielen+2) <= MAX_IE_SZ) {
+ memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen+2);
+ pframe += wps_ielen+2;
+ pattrib->pktlen += wps_ielen+2;
+ }
+
+ if ((wps_offset+wps_ielen+2+remainder_ielen) <= MAX_IE_SZ) {
+ memcpy(pframe, premainder_ie, remainder_ielen);
+ pframe += remainder_ielen;
+ pattrib->pktlen += remainder_ielen;
+ }
+ } else {
+ memcpy(pframe, cur_network->ies, cur_network->ie_length);
+ pframe += cur_network->ie_length;
+ pattrib->pktlen += cur_network->ie_length;
+ }
+ } else
+#endif
+ {
+ /* timestamp will be inserted by hardware */
+ pframe += 8;
+ pattrib->pktlen += 8;
+
+ /* beacon interval: 2 bytes */
+
+ memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->ies)), 2);
+
+ pframe += 2;
+ pattrib->pktlen += 2;
+
+ /* capability info: 2 bytes */
+
+ memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->ies)), 2);
+
+ pframe += 2;
+ pattrib->pktlen += 2;
+
+ /* below for ad-hoc mode */
+
+ /* SSID */
+ pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pattrib->pktlen);
+
+ /* supported rates... */
+ rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, min_t(unsigned int, rate_len, 8), cur_network->SupportedRates, &pattrib->pktlen);
+
+ /* DS parameter set */
+ pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&cur_network->Configuration.DSConfig, &pattrib->pktlen);
+
+ if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
+ u8 erpinfo = 0;
+ u32 ATIMWindow;
+ /* IBSS Parameter Set... */
+ /* ATIMWindow = cur->Configuration.ATIMWindow; */
+ ATIMWindow = 0;
+ pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
+
+ /* ERP IE */
+ pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
+ }
+
+ /* EXTERNDED SUPPORTED RATE */
+ if (rate_len > 8)
+ pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
+ /* todo:HT for adhoc */
+ }
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ dump_mgntframe(padapter, pmgntframe);
+}
+
+static int issue_probereq(struct adapter *padapter,
+ struct ndis_802_11_ssid *pssid, u8 *da,
+ bool wait_ack)
+{
+ int ret = _FAIL;
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ unsigned char *mac;
+ unsigned char bssrate[NumRates];
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ int bssrate_len = 0;
+ u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+%s\n", __func__));
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ goto exit;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct ieee80211_hdr *)pframe;
+
+ mac = myid(&padapter->eeprompriv);
+
+ fctrl = &pwlanhdr->frame_control;
+ *(fctrl) = 0;
+
+ if (da) {
+ /* unicast probe request frame */
+ ether_addr_copy(pwlanhdr->addr1, da);
+ ether_addr_copy(pwlanhdr->addr3, da);
+ } else {
+ /* broadcast probe request frame */
+ ether_addr_copy(pwlanhdr->addr1, bc_addr);
+ ether_addr_copy(pwlanhdr->addr3, bc_addr);
+ }
+
+ ether_addr_copy(pwlanhdr->addr2, mac);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_PROBEREQ);
+
+ pframe += sizeof(struct ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
+
+ if (pssid)
+ pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->ssid_length, pssid->ssid, &pattrib->pktlen);
+ else
+ pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &pattrib->pktlen);
+
+ get_rate_set(padapter, bssrate, &bssrate_len);
+
+ if (bssrate_len > 8) {
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &pattrib->pktlen);
+ pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, bssrate_len - 8, bssrate + 8, &pattrib->pktlen);
+ } else {
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &pattrib->pktlen);
+ }
+
+ /* add wps_ie for wps2.0 */
+ if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) {
+ memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
+ pframe += pmlmepriv->wps_probe_req_ie_len;
+ pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
+ }
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
+ ("issuing probe_req, tx_len=%d\n", pattrib->last_txcmdsz));
+
+ if (wait_ack) {
+ ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
+ } else {
+ dump_mgntframe(padapter, pmgntframe);
+ ret = _SUCCESS;
+ }
+
+exit:
+ return ret;
+}
+
+static int issue_probereq_ex(struct adapter *padapter,
+ struct ndis_802_11_ssid *pssid, u8 *da,
+ int try_cnt, int wait_ms)
+{
+ int ret;
+ int i = 0;
+ unsigned long start = jiffies;
+
+ do {
+ ret = issue_probereq(padapter, pssid, da, wait_ms > 0);
+
+ i++;
+
+ if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
+ break;
+
+ if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
+ msleep(wait_ms);
+
+ } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
+
+ if (ret != _FAIL) {
+ ret = _SUCCESS;
+ goto exit;
+ }
+
+ if (try_cnt && wait_ms) {
+ if (da)
+ DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
+ FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt,
+ jiffies_to_msecs(jiffies - start));
+ else
+ DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
+ FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt,
+ jiffies_to_msecs(jiffies - start));
+ }
+exit:
+ return ret;
+}
+
+/* if psta == NULL, indicate we are station(client) now... */
+static void issue_auth(struct adapter *padapter, struct sta_info *psta,
+ unsigned short status)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ unsigned int val32;
+ u16 val16;
+#ifdef CPTCFG_88EU_AP_MODE
+ __le16 le_val16;
+#endif
+ int use_shared_key = 0;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (pmgntframe == NULL)
+ return;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_control;
+ *(fctrl) = 0;
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_AUTH);
+
+ pframe += sizeof(struct ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
+
+ if (psta) {/* for AP mode */
+#ifdef CPTCFG_88EU_AP_MODE
+
+ ether_addr_copy(pwlanhdr->addr1, psta->hwaddr);
+ ether_addr_copy(pwlanhdr->addr2,
+ myid(&padapter->eeprompriv));
+ ether_addr_copy(pwlanhdr->addr3,
+ myid(&padapter->eeprompriv));
+
+ /* setting auth algo number */
+ val16 = (u16)psta->authalg;
+
+ if (status != _STATS_SUCCESSFUL_)
+ val16 = 0;
+
+ if (val16) {
+ le_val16 = cpu_to_le16(val16);
+ use_shared_key = 1;
+ } else {
+ le_val16 = 0;
+ }
+
+ pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, &le_val16,
+ &pattrib->pktlen);
+
+ /* setting auth seq number */
+ val16 = (u16)psta->auth_seq;
+ le_val16 = cpu_to_le16(val16);
+ pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, &le_val16,
+ &pattrib->pktlen);
+
+ /* setting status code... */
+ val16 = status;
+ le_val16 = cpu_to_le16(val16);
+ pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_,
+ &le_val16, &pattrib->pktlen);
+
+ /* added challenging text... */
+ if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
+ pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &pattrib->pktlen);
+#endif
+ } else {
+ __le32 le_tmp32;
+ __le16 le_tmp16;
+
+ ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress);
+ ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
+ ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
+
+ /* setting auth algo number */
+ val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/* 0:OPEN System, 1:Shared key */
+ if (val16)
+ use_shared_key = 1;
+
+ /* setting IV for auth seq #3 */
+ if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
+ val32 = (pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30);
+ le_tmp32 = cpu_to_le32(val32);
+ pframe = rtw_set_fixed_ie(pframe, 4, &le_tmp32,
+ &pattrib->pktlen);
+
+ pattrib->iv_len = 4;
+ }
+
+ le_tmp16 = cpu_to_le16(val16);
+ pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, &le_tmp16,
+ &pattrib->pktlen);
+
+ /* setting auth seq number */
+ val16 = pmlmeinfo->auth_seq;
+ le_tmp16 = cpu_to_le16(val16);
+ pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, &le_tmp16,
+ &pattrib->pktlen);
+
+ /* setting status code... */
+ le_tmp16 = cpu_to_le16(status);
+ pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, &le_tmp16,
+ &pattrib->pktlen);
+
+ /* then checking to see if sending challenging text... */
+ if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
+ pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, pmlmeinfo->chg_txt, &pattrib->pktlen);
+
+ SetPrivacy(fctrl);
+
+ pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
+
+ pattrib->encrypt = _WEP40_;
+
+ pattrib->icv_len = 4;
+
+ pattrib->pktlen += pattrib->icv_len;
+ }
+ }
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ rtw_wep_encrypt(padapter, (u8 *)pmgntframe);
+ DBG_88E("%s\n", __func__);
+ dump_mgntframe(padapter, pmgntframe);
+}
+
+#ifdef CPTCFG_88EU_AP_MODE
+static void issue_asocrsp(struct adapter *padapter, unsigned short status,
+ struct sta_info *pstat, int pkt_type)
+{
+ struct xmit_frame *pmgntframe;
+ struct ieee80211_hdr *pwlanhdr;
+ struct pkt_attrib *pattrib;
+ unsigned char *pbuf, *pframe;
+ unsigned short val;
+ __le16 *fctrl;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
+ u8 *ie = pnetwork->ies;
+ __le16 lestatus, leval;
+
+ DBG_88E("%s\n", __func__);
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ return;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_control;
+ *(fctrl) = 0;
+
+ ether_addr_copy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr);
+ ether_addr_copy((void *)GetAddr2Ptr(pwlanhdr),
+ myid(&padapter->eeprompriv));
+ ether_addr_copy((void *)GetAddr3Ptr(pwlanhdr), pnetwork->MacAddress);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
+ SetFrameSubType(pwlanhdr, pkt_type);
+ else
+ return;
+
+ pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
+ pattrib->pktlen += pattrib->hdrlen;
+ pframe += pattrib->hdrlen;
+
+ /* capability */
+ val = *(unsigned short *)rtw_get_capability_from_ie(ie);
+
+ pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_, &val, &pattrib->pktlen);
+
+ lestatus = cpu_to_le16(status);
+ pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, &lestatus,
+ &pattrib->pktlen);
+
+ leval = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
+ pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_, &leval, &pattrib->pktlen);
+
+ if (pstat->bssratelen <= 8) {
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, pstat->bssratelen, pstat->bssrateset, &pattrib->pktlen);
+ } else {
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pstat->bssrateset, &pattrib->pktlen);
+ pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, pstat->bssratelen-8, pstat->bssrateset+8, &pattrib->pktlen);
+ }
+
+ if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) {
+ uint ie_len = 0;
+
+ /* FILL HT CAP INFO IE */
+ pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_));
+ if (pbuf && ie_len > 0) {
+ memcpy(pframe, pbuf, ie_len+2);
+ pframe += (ie_len+2);
+ pattrib->pktlen += (ie_len+2);
+ }
+
+ /* FILL HT ADD INFO IE */
+ pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_));
+ if (pbuf && ie_len > 0) {
+ memcpy(pframe, pbuf, ie_len+2);
+ pframe += (ie_len+2);
+ pattrib->pktlen += (ie_len+2);
+ }
+ }
+
+ /* FILL WMM IE */
+ if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) {
+ uint ie_len = 0;
+ unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
+
+ for (pbuf = ie + _BEACON_IE_OFFSET_;; pbuf += (ie_len + 2)) {
+ pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2)));
+ if (pbuf && !memcmp(pbuf+2, WMM_PARA_IE, 6)) {
+ memcpy(pframe, pbuf, ie_len+2);
+ pframe += (ie_len+2);
+ pattrib->pktlen += (ie_len+2);
+ break;
+ }
+
+ if ((pbuf == NULL) || (ie_len == 0))
+ break;
+ }
+ }
+
+ if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &pattrib->pktlen);
+
+ /* add WPS IE ie for wps 2.0 */
+ if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) {
+ memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
+
+ pframe += pmlmepriv->wps_assoc_resp_ie_len;
+ pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
+ }
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+ dump_mgntframe(padapter, pmgntframe);
+}
+#endif /* CPTCFG_88EU_AP_MODE */
+
+static void issue_assocreq(struct adapter *padapter)
+{
+ int ret = _FAIL;
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe, *p;
+ struct ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ unsigned int i, j, ie_len, index = 0;
+ unsigned char bssrate[NumRates], sta_bssrate[NumRates];
+ struct ndis_802_11_var_ie *pIE;
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ int bssrate_len = 0, sta_bssrate_len = 0;
+ struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ goto exit;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_control;
+ *(fctrl) = 0;
+ ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress);
+ ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
+ ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_ASSOCREQ);
+
+ pframe += sizeof(struct ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
+
+ /* caps */
+
+ memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.ies), 2);
+
+ pframe += 2;
+ pattrib->pktlen += 2;
+
+ /* listen interval */
+ /* todo: listen interval for power saving */
+ put_unaligned_le16(3, pframe);
+ pframe += 2;
+ pattrib->pktlen += 2;
+
+ /* SSID */
+ pframe = rtw_set_ie(pframe, _SSID_IE_, pmlmeinfo->network.ssid.ssid_length, pmlmeinfo->network.ssid.ssid, &pattrib->pktlen);
+
+ /* supported rate & extended supported rate */
+
+ /* Check if the AP's supported rates are also supported by STA. */
+ get_rate_set(padapter, sta_bssrate, &sta_bssrate_len);
+
+ if (pmlmeext->cur_channel == 14)/* for JAPAN, channel 14 can only uses B Mode(CCK) */
+ sta_bssrate_len = 4;
+
+ for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
+ if (pmlmeinfo->network.SupportedRates[i] == 0)
+ break;
+ DBG_88E("network.SupportedRates[%d]=%02X\n", i, pmlmeinfo->network.SupportedRates[i]);
+ }
+
+ for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
+ if (pmlmeinfo->network.SupportedRates[i] == 0)
+ break;
+
+ /* Check if the AP's supported rates are also supported by STA. */
+ for (j = 0; j < sta_bssrate_len; j++) {
+ /* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
+ if ((pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK)
+ == (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK))
+ break;
+ }
+
+ if (j == sta_bssrate_len) {
+ /* the rate is not supported by STA */
+ DBG_88E("%s(): the rate[%d]=%02X is not supported by STA!\n", __func__, i, pmlmeinfo->network.SupportedRates[i]);
+ } else {
+ /* the rate is supported by STA */
+ bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
+ }
+ }
+
+ bssrate_len = index;
+ DBG_88E("bssrate_len=%d\n", bssrate_len);
+
+ if (bssrate_len == 0) {
+ rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
+ rtw_free_xmitframe(pxmitpriv, pmgntframe);
+ goto exit; /* don't connect to AP if no joint supported rate */
+ }
+
+ if (bssrate_len > 8) {
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &pattrib->pktlen);
+ pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, bssrate_len - 8, bssrate + 8, &pattrib->pktlen);
+ } else {
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &pattrib->pktlen);
+ }
+
+ /* RSN */
+ p = rtw_get_ie((pmlmeinfo->network.ies + sizeof(struct ndis_802_11_fixed_ie)), _RSN_IE_2_, &ie_len, (pmlmeinfo->network.ie_length - sizeof(struct ndis_802_11_fixed_ie)));
+ if (p)
+ pframe = rtw_set_ie(pframe, _RSN_IE_2_, ie_len, p + 2, &pattrib->pktlen);
+
+ /* HT caps */
+ if (padapter->mlmepriv.htpriv.ht_option) {
+ p = rtw_get_ie((pmlmeinfo->network.ies + sizeof(struct ndis_802_11_fixed_ie)), _HT_CAPABILITY_IE_, &ie_len, (pmlmeinfo->network.ie_length - sizeof(struct ndis_802_11_fixed_ie)));
+ if ((p != NULL) && (!(is_ap_in_tkip(padapter)))) {
+ memcpy(&pmlmeinfo->HT_caps, p + 2, sizeof(struct ieee80211_ht_cap));
+
+ /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
+ if (pregpriv->cbw40_enable == 0)
+ pmlmeinfo->HT_caps.cap_info &= cpu_to_le16(~(BIT(6) | BIT(1)));
+ else
+ pmlmeinfo->HT_caps.cap_info |= cpu_to_le16(BIT(1));
+
+ /* todo: disable SM power save mode */
+ pmlmeinfo->HT_caps.cap_info |= cpu_to_le16(0x000c);
+
+ if (pregpriv->rx_stbc)
+ pmlmeinfo->HT_caps.cap_info |= cpu_to_le16(0x0100);/* RX STBC One spatial stream */
+ memcpy((u8 *)&pmlmeinfo->HT_caps.mcs, MCS_rate_1R, 16);
+ pframe = rtw_set_ie(pframe, _HT_CAPABILITY_IE_, ie_len, (u8 *)(&pmlmeinfo->HT_caps), &pattrib->pktlen);
+ }
+ }
+
+ /* vendor specific IE, such as WPA, WMM, WPS */
+ for (i = sizeof(struct ndis_802_11_fixed_ie); i < pmlmeinfo->network.ie_length; i += (pIE->Length + 2)) {
+ pIE = (struct ndis_802_11_var_ie *)(pmlmeinfo->network.ies + i);
+
+ switch (pIE->ElementID) {
+ case _VENDOR_SPECIFIC_IE_:
+ if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
+ (!memcmp(pIE->data, WMM_OUI, 4)) ||
+ (!memcmp(pIE->data, WPS_OUI, 4))) {
+ if (!padapter->registrypriv.wifi_spec) {
+ /* Commented by Kurt 20110629 */
+ /* In some older APs, WPS handshake */
+ /* would be fail if we append vender extensions informations to AP */
+ if (!memcmp(pIE->data, WPS_OUI, 4))
+ pIE->Length = 14;
+ }
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, pIE->Length, pIE->data, &pattrib->pktlen);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &pattrib->pktlen);
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+ dump_mgntframe(padapter, pmgntframe);
+
+ ret = _SUCCESS;
+
+exit:
+ if (ret == _SUCCESS)
+ rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);
+ else
+ rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
+}
+
+/* when wait_ack is true, this function should be called at process context */
+static int _issue_nulldata(struct adapter *padapter, unsigned char *da,
+ unsigned int power_mode, bool wait_ack)
+{
+ int ret = _FAIL;
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ struct xmit_priv *pxmitpriv;
+ struct mlme_ext_priv *pmlmeext;
+ struct mlme_ext_info *pmlmeinfo;
+ struct wlan_bssid_ex *pnetwork;
+
+ if (!padapter)
+ goto exit;
+
+ pxmitpriv = &padapter->xmitpriv;
+ pmlmeext = &padapter->mlmeextpriv;
+ pmlmeinfo = &pmlmeext->mlmext_info;
+ pnetwork = &pmlmeinfo->network;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ goto exit;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+ pattrib->retry_ctrl = false;
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_control;
+ *(fctrl) = 0;
+
+ if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)
+ SetFrDs(fctrl);
+ else if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)
+ SetToDs(fctrl);
+
+ if (power_mode)
+ SetPwrMgt(fctrl);
+
+ ether_addr_copy(pwlanhdr->addr1, da);
+ ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
+ ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_DATA_NULL);
+
+ pframe += sizeof(struct ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ if (wait_ack) {
+ ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
+ } else {
+ dump_mgntframe(padapter, pmgntframe);
+ ret = _SUCCESS;
+ }
+
+exit:
+ return ret;
+}
+
+/* when wait_ms > 0 , this function should be called at process context */
+/* da == NULL for station mode */
+int issue_nulldata(struct adapter *padapter, unsigned char *da,
+ unsigned int power_mode, int try_cnt, int wait_ms)
+{
+ int ret;
+ int i = 0;
+ unsigned long start = jiffies;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
+
+ /* da == NULL, assume it's null data for sta to ap*/
+ if (da == NULL)
+ da = pnetwork->MacAddress;
+
+ do {
+ ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0);
+
+ i++;
+
+ if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
+ break;
+
+ if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
+ msleep(wait_ms);
+ } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
+
+ if (ret != _FAIL) {
+ ret = _SUCCESS;
+ goto exit;
+ }
+
+ if (try_cnt && wait_ms) {
+ if (da)
+ DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
+ FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt,
+ jiffies_to_msecs(jiffies - start));
+ else
+ DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
+ FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt,
+ jiffies_to_msecs(jiffies - start));
+ }
+exit:
+ return ret;
+}
+
+/* when wait_ack is true, this function should be called at process context */
+static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da,
+ u16 tid, bool wait_ack)
+{
+ int ret = _FAIL;
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ unsigned short *qc;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
+
+ DBG_88E("%s\n", __func__);
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ goto exit;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ pattrib->hdrlen += 2;
+ pattrib->qos_en = true;
+ pattrib->eosp = 1;
+ pattrib->ack_policy = 0;
+ pattrib->mdata = 0;
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_control;
+ *(fctrl) = 0;
+
+ if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)
+ SetFrDs(fctrl);
+ else if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)
+ SetToDs(fctrl);
+
+ if (pattrib->mdata)
+ SetMData(fctrl);
+
+ qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
+
+ SetPriority(qc, tid);
+
+ SetEOSP(qc, pattrib->eosp);
+
+ SetAckpolicy(qc, pattrib->ack_policy);
+
+ ether_addr_copy(pwlanhdr->addr1, da);
+ ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
+ ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
+
+ pframe += sizeof(struct ieee80211_qos_hdr);
+ pattrib->pktlen = sizeof(struct ieee80211_qos_hdr);
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ if (wait_ack) {
+ ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
+ } else {
+ dump_mgntframe(padapter, pmgntframe);
+ ret = _SUCCESS;
+ }
+
+exit:
+ return ret;
+}
+
+/* when wait_ms > 0 , this function should be called at process context */
+/* da == NULL for station mode */
+int issue_qos_nulldata(struct adapter *padapter, unsigned char *da,
+ u16 tid, int try_cnt, int wait_ms)
+{
+ int ret;
+ int i = 0;
+ unsigned long start = jiffies;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
+
+ /* da == NULL, assume it's null data for sta to ap*/
+ if (da == NULL)
+ da = pnetwork->MacAddress;
+
+ do {
+ ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0);
+
+ i++;
+
+ if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
+ break;
+
+ if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
+ msleep(wait_ms);
+ } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
+
+ if (ret != _FAIL) {
+ ret = _SUCCESS;
+ goto exit;
+ }
+
+ if (try_cnt && wait_ms) {
+ if (da)
+ DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
+ FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt,
+ jiffies_to_msecs(jiffies - start));
+ else
+ DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
+ FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt,
+ jiffies_to_msecs(jiffies - start));
+ }
+exit:
+ return ret;
+}
+
+static int _issue_deauth(struct adapter *padapter, unsigned char *da,
+ unsigned short reason, bool wait_ack)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
+ int ret = _FAIL;
+ __le16 le_tmp;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (pmgntframe == NULL)
+ goto exit;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+ pattrib->retry_ctrl = false;
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_control;
+ *(fctrl) = 0;
+
+ ether_addr_copy(pwlanhdr->addr1, da);
+ ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
+ ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_DEAUTH);
+
+ pframe += sizeof(struct ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
+
+ le_tmp = cpu_to_le16(reason);
+ pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_, &le_tmp,
+ &pattrib->pktlen);
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ if (wait_ack) {
+ ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
+ } else {
+ dump_mgntframe(padapter, pmgntframe);
+ ret = _SUCCESS;
+ }
+
+exit:
+ return ret;
+}
+
+int issue_deauth(struct adapter *padapter, unsigned char *da,
+ unsigned short reason)
+{
+ DBG_88E("%s to %pM\n", __func__, da);
+ return _issue_deauth(padapter, da, reason, false);
+}
+
+static int issue_deauth_ex(struct adapter *padapter, u8 *da,
+ unsigned short reason, int try_cnt,
+ int wait_ms)
+{
+ int ret;
+ int i = 0;
+ unsigned long start = jiffies;
+
+ do {
+ ret = _issue_deauth(padapter, da, reason, wait_ms > 0);
+
+ i++;
+
+ if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
+ break;
+
+ if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
+ mdelay(wait_ms);
+ } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
+
+ if (ret != _FAIL) {
+ ret = _SUCCESS;
+ goto exit;
+ }
+
+ if (try_cnt && wait_ms) {
+ if (da)
+ DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
+ FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt,
+ jiffies_to_msecs(jiffies - start));
+ else
+ DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
+ FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
+ ret == _SUCCESS ? ", acked" : "", i, try_cnt,
+ jiffies_to_msecs(jiffies - start));
+ }
+exit:
+ return ret;
+}
+
+static void issue_action_BA(struct adapter *padapter, unsigned char *raddr,
+ unsigned char action, unsigned short status)
+{
+ u8 category = RTW_WLAN_CATEGORY_BACK;
+ u16 start_seq;
+ u16 BA_para_set;
+ u16 reason_code;
+ u16 BA_timeout_value;
+ __le16 le_tmp;
+ u16 BA_starting_seqctrl = 0;
+ enum ht_cap_ampdu_factor max_rx_ampdu_factor;
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ u8 *pframe;
+ struct ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct sta_info *psta;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+ struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
+
+ DBG_88E("%s, category=%d, action=%d, status=%d\n", __func__, category, action, status);
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ return;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_control;
+ *(fctrl) = 0;
+
+ ether_addr_copy(pwlanhdr->addr1, raddr);
+ ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
+ ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_ACTION);
+
+ pframe += sizeof(struct ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
+
+ pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
+
+ if (category == 3) {
+ switch (action) {
+ case 0: /* ADDBA req */
+ do {
+ pmlmeinfo->dialogToken++;
+ } while (pmlmeinfo->dialogToken == 0);
+ pframe = rtw_set_fixed_ie(pframe, 1, &pmlmeinfo->dialogToken, &pattrib->pktlen);
+
+ BA_para_set = 0x1002 | ((status & 0xf) << 2); /* immediate ack & 64 buffer size */
+ le_tmp = cpu_to_le16(BA_para_set);
+ pframe = rtw_set_fixed_ie(pframe, 2, &(le_tmp),
+ &pattrib->pktlen);
+
+ BA_timeout_value = 5000;/* 5ms */
+ le_tmp = cpu_to_le16(BA_timeout_value);
+ pframe = rtw_set_fixed_ie(pframe, 2, &(le_tmp),
+ &pattrib->pktlen);
+
+ psta = rtw_get_stainfo(pstapriv, raddr);
+ if (psta) {
+ start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07] & 0xfff) + 1;
+
+ DBG_88E("BA_starting_seqctrl=%d for TID=%d\n", start_seq, status & 0x07);
+
+ psta->BA_starting_seqctrl[status & 0x07] = start_seq;
+
+ BA_starting_seqctrl = start_seq << 4;
+ }
+ le_tmp = cpu_to_le16(BA_starting_seqctrl);
+ pframe = rtw_set_fixed_ie(pframe, 2, &(le_tmp),
+ &pattrib->pktlen);
+ break;
+ case 1: /* ADDBA rsp */
+ {
+ struct ADDBA_request *ADDBA_req = &pmlmeinfo->ADDBA_req;
+
+ pframe = rtw_set_fixed_ie(pframe, 1,
+ &ADDBA_req->dialog_token,
+ &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 2, &status,
+ &pattrib->pktlen);
+
+ BA_para_set = le16_to_cpu(ADDBA_req->BA_para_set) &
+ 0x3f;
+ rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
+ switch (max_rx_ampdu_factor) {
+ case MAX_AMPDU_FACTOR_64K:
+ BA_para_set |= 0x1000; /* 64 buffer size */
+ break;
+ case MAX_AMPDU_FACTOR_32K:
+ BA_para_set |= 0x0800; /* 32 buffer size */
+ break;
+ case MAX_AMPDU_FACTOR_16K:
+ BA_para_set |= 0x0400; /* 16 buffer size */
+ break;
+ case MAX_AMPDU_FACTOR_8K:
+ BA_para_set |= 0x0200; /* 8 buffer size */
+ break;
+ default:
+ BA_para_set |= 0x1000; /* 64 buffer size */
+ break;
+ }
+
+ if (pregpriv->ampdu_amsdu == 0)/* disabled */
+ BA_para_set = BA_para_set & ~BIT(0);
+ else if (pregpriv->ampdu_amsdu == 1)/* enabled */
+ BA_para_set = BA_para_set | BIT(0);
+ le_tmp = cpu_to_le16(BA_para_set);
+
+ pframe = rtw_set_fixed_ie(pframe, 2, &(le_tmp),
+ &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 2,
+ &ADDBA_req->BA_timeout_value,
+ &pattrib->pktlen);
+ break;
+ }
+ case 2:/* DELBA */
+ BA_para_set = (status & 0x1F) << 3;
+ le_tmp = cpu_to_le16(BA_para_set);
+ pframe = rtw_set_fixed_ie(pframe, 2, &(le_tmp),
+ &pattrib->pktlen);
+
+ reason_code = 37;/* Requested from peer STA as it does not want to use the mechanism */
+ le_tmp = cpu_to_le16(reason_code);
+ pframe = rtw_set_fixed_ie(pframe, 2, &(le_tmp),
+ &pattrib->pktlen);
+ break;
+ default:
+ break;
+ }
+ }
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ dump_mgntframe(padapter, pmgntframe);
+}
+
+static void issue_action_BSSCoexistPacket(struct adapter *padapter)
+{
+ struct list_head *plist, *phead;
+ unsigned char category, action;
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ struct wlan_network *pnetwork = NULL;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct __queue *queue = &pmlmepriv->scanned_queue;
+ u8 InfoContent[16] = {0};
+ u8 ICS[8][15];
+ struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
+
+ if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0))
+ return;
+
+ if (pmlmeinfo->bwmode_updated)
+ return;
+
+ DBG_88E("%s\n", __func__);
+
+ category = RTW_WLAN_CATEGORY_PUBLIC;
+ action = ACT_PUBLIC_BSSCOEXIST;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ return;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_control;
+ *(fctrl) = 0;
+
+ ether_addr_copy(pwlanhdr->addr1, cur_network->MacAddress);
+ ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
+ ether_addr_copy(pwlanhdr->addr3, cur_network->MacAddress);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_ACTION);
+
+ pframe += sizeof(struct ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
+
+ pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
+ pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
+
+ /* */
+ if (pmlmepriv->num_FortyMHzIntolerant > 0) {
+ u8 iedata = 0;
+
+ iedata |= BIT(2);/* 20 MHz BSS Width Request */
+
+ pframe = rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &pattrib->pktlen);
+ }
+
+ /* */
+ memset(ICS, 0, sizeof(ICS));
+ if (pmlmepriv->num_sta_no_ht > 0) {
+ int i;
+
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+
+ phead = get_list_head(queue);
+ plist = phead->next;
+
+ while (phead != plist) {
+ uint len;
+ u8 *p;
+ struct wlan_bssid_ex *pbss_network;
+
+ pnetwork = container_of(plist, struct wlan_network, list);
+
+ plist = plist->next;
+
+ pbss_network = (struct wlan_bssid_ex *)&pnetwork->network;
+
+ p = rtw_get_ie(pbss_network->ies + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->ie_length - _FIXED_IE_LENGTH_);
+ if ((p == NULL) || (len == 0)) { /* non-HT */
+ if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14))
+ continue;
+
+ ICS[0][pbss_network->Configuration.DSConfig] = 1;
+
+ if (ICS[0][0] == 0)
+ ICS[0][0] = 1;
+ }
+ }
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+
+ for (i = 0; i < 8; i++) {
+ if (ICS[i][0] == 1) {
+ int j, k = 0;
+
+ InfoContent[k] = i;
+ /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */
+ k++;
+
+ for (j = 1; j <= 14; j++) {
+ if (ICS[i][j] == 1) {
+ if (k < 16) {
+ InfoContent[k] = j; /* channel number */
+ /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */
+ k++;
+ }
+ }
+ }
+
+ pframe = rtw_set_ie(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &pattrib->pktlen);
+ }
+ }
+ }
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ dump_mgntframe(padapter, pmgntframe);
+}
+
+unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr)
+{
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct sta_info *psta = NULL;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u16 tid;
+
+ if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
+ if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
+ return _SUCCESS;
+
+ psta = rtw_get_stainfo(pstapriv, addr);
+ if (psta == NULL)
+ return _SUCCESS;
+
+ if (initiator == 0) { /* recipient */
+ for (tid = 0; tid < MAXTID; tid++) {
+ if (psta->recvreorder_ctrl[tid].enable) {
+ DBG_88E("rx agg disable tid(%d)\n", tid);
+ issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid << 1) | initiator) & 0x1F));
+ psta->recvreorder_ctrl[tid].enable = false;
+ psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
+ }
+ }
+ } else if (initiator == 1) { /* originator */
+ for (tid = 0; tid < MAXTID; tid++) {
+ if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
+ DBG_88E("tx agg disable tid(%d)\n", tid);
+ issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid << 1) | initiator) & 0x1F));
+ psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
+ psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
+ }
+ }
+ }
+
+ return _SUCCESS;
+}
+
+unsigned int send_beacon(struct adapter *padapter)
+{
+ u8 bxmitok = false;
+ int issue = 0;
+ int poll = 0;
+ unsigned long start = jiffies;
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
+ do {
+ issue_beacon(padapter, 100);
+ issue++;
+ do {
+ yield();
+ rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok));
+ poll++;
+ } while ((poll%10) != 0 && !bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
+ } while (!bxmitok && issue < 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
+
+ if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
+ return _FAIL;
+ if (!bxmitok) {
+ DBG_88E("%s fail! %u ms\n", __func__,
+ jiffies_to_msecs(jiffies - start));
+ return _FAIL;
+ } else {
+ u32 passing_time = jiffies_to_msecs(jiffies - start);
+
+ if (passing_time > 100 || issue > 3)
+ DBG_88E("%s success, issue:%d, poll:%d, %u ms\n",
+ __func__, issue, poll,
+ jiffies_to_msecs(jiffies - start));
+ return _SUCCESS;
+ }
+}
+
+/****************************************************************************
+
+Following are some utility functions for WiFi MLME
+
+*****************************************************************************/
+
+static void site_survey(struct adapter *padapter)
+{
+ unsigned char survey_channel = 0, val8;
+ enum rt_scan_type ScanType = SCAN_PASSIVE;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u32 initialgain = 0;
+ struct rtw_ieee80211_channel *ch;
+
+ if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
+ ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
+ survey_channel = ch->hw_value;
+ ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;
+ }
+
+ if (survey_channel != 0) {
+ /* PAUSE 4-AC Queue when site_survey */
+ /* rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
+ /* val8 |= 0x0f; */
+ /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
+ if (pmlmeext->sitesurvey_res.channel_idx == 0)
+ set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+ else
+ SelectChannel(padapter, survey_channel);
+
+ if (ScanType == SCAN_ACTIVE) { /* obey the channel plan setting... */
+ int i;
+
+ for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
+ if (pmlmeext->sitesurvey_res.ssid[i].ssid_length) {
+ /* todo: to issue two probe req??? */
+ issue_probereq(padapter,
+ &(pmlmeext->sitesurvey_res.ssid[i]),
+ NULL, false);
+ /* msleep(SURVEY_TO>>1); */
+ issue_probereq(padapter,
+ &(pmlmeext->sitesurvey_res.ssid[i]),
+ NULL, false);
+ }
+ }
+
+ if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
+ /* todo: to issue two probe req??? */
+ issue_probereq(padapter, NULL, NULL, false);
+ /* msleep(SURVEY_TO>>1); */
+ issue_probereq(padapter, NULL, NULL, false);
+ }
+
+ if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
+ /* todo: to issue two probe req??? */
+ issue_probereq(padapter, NULL, NULL, false);
+ /* msleep(SURVEY_TO>>1); */
+ issue_probereq(padapter, NULL, NULL, false);
+ }
+ }
+
+ set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
+ } else {
+ /* 20100721:Interrupt scan operation here. */
+ /* For SW antenna diversity before link, it needs to switch to another antenna and scan again. */
+ /* It compares the scan result and select better one to do connection. */
+ if (rtw_hal_antdiv_before_linked(padapter)) {
+ pmlmeext->sitesurvey_res.bss_cnt = 0;
+ pmlmeext->sitesurvey_res.channel_idx = -1;
+ pmlmeext->chan_scan_time = SURVEY_TO / 2;
+ set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
+ return;
+ }
+
+ pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
+
+ /* switch back to the original channel */
+
+ set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+
+ /* flush 4-AC Queue after site_survey */
+ /* val8 = 0; */
+ /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
+
+ /* config MSR */
+ Set_MSR(padapter, (pmlmeinfo->state & 0x3));
+
+ initialgain = 0xff; /* restore RX GAIN */
+ rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
+ /* turn on dynamic functions */
+ Restore_DM_Func_Flag(padapter);
+ /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */
+
+ if (is_client_associated_to_ap(padapter))
+ issue_nulldata(padapter, NULL, 0, 3, 500);
+
+ val8 = 0; /* survey done */
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
+
+ report_surveydone_event(padapter);
+
+ pmlmeext->chan_scan_time = SURVEY_TO;
+ pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
+
+ issue_action_BSSCoexistPacket(padapter);
+ issue_action_BSSCoexistPacket(padapter);
+ issue_action_BSSCoexistPacket(padapter);
+ }
+}
+
+/* collect bss info from Beacon and Probe request/response frames. */
+static u8 collect_bss_info(struct adapter *padapter,
+ struct recv_frame *precv_frame,
+ struct wlan_bssid_ex *bssid)
+{
+ int i;
+ u32 len;
+ u8 *p;
+ u16 val16, subtype;
+ u8 *pframe = precv_frame->pkt->data;
+ u32 packet_len = precv_frame->pkt->len;
+ u8 ie_offset;
+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ len = packet_len - sizeof(struct ieee80211_hdr_3addr);
+
+ if (len > MAX_IE_SZ)
+ return _FAIL;
+
+ memset(bssid, 0, sizeof(struct wlan_bssid_ex));
+
+ subtype = GetFrameSubType(pframe);
+
+ if (subtype == WIFI_BEACON) {
+ bssid->Reserved[0] = 1;
+ ie_offset = _BEACON_IE_OFFSET_;
+ } else {
+ /* FIXME : more type */
+ if (subtype == WIFI_PROBEREQ) {
+ ie_offset = _PROBEREQ_IE_OFFSET_;
+ bssid->Reserved[0] = 2;
+ } else if (subtype == WIFI_PROBERSP) {
+ ie_offset = _PROBERSP_IE_OFFSET_;
+ bssid->Reserved[0] = 3;
+ } else {
+ bssid->Reserved[0] = 0;
+ ie_offset = _FIXED_IE_LENGTH_;
+ }
+ }
+
+ bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
+
+ /* below is to copy the information element */
+ bssid->ie_length = len;
+ memcpy(bssid->ies, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->ie_length);
+
+ /* get the signal strength in dBM.raw data */
+ bssid->Rssi = precv_frame->attrib.phy_info.recvpower;
+ bssid->PhyInfo.SignalQuality = precv_frame->attrib.phy_info.SignalQuality;/* in percentage */
+ bssid->PhyInfo.SignalStrength = precv_frame->attrib.phy_info.SignalStrength;/* in percentage */
+ rtw_hal_get_def_var(padapter, HAL_DEF_CURRENT_ANTENNA, &bssid->PhyInfo.Optimum_antenna);
+
+ /* checking SSID */
+ p = rtw_get_ie(bssid->ies + ie_offset, _SSID_IE_, &len, bssid->ie_length - ie_offset);
+ if (!p) {
+ DBG_88E("marc: cannot find SSID for survey event\n");
+ return _FAIL;
+ }
+
+ if (len) {
+ if (len > NDIS_802_11_LENGTH_SSID) {
+ DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
+ return _FAIL;
+ }
+ memcpy(bssid->ssid.ssid, (p + 2), len);
+ bssid->ssid.ssid_length = len;
+ } else {
+ bssid->ssid.ssid_length = 0;
+ }
+
+ memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
+
+ /* checking rate info... */
+ i = 0;
+ p = rtw_get_ie(bssid->ies + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->ie_length - ie_offset);
+ if (p != NULL) {
+ if (len > NDIS_802_11_LENGTH_RATES_EX) {
+ DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
+ return _FAIL;
+ }
+ memcpy(bssid->SupportedRates, (p + 2), len);
+ i = len;
+ }
+
+ p = rtw_get_ie(bssid->ies + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->ie_length - ie_offset);
+ if (p) {
+ if (len > (NDIS_802_11_LENGTH_RATES_EX-i)) {
+ DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
+ return _FAIL;
+ }
+ memcpy(bssid->SupportedRates + i, (p + 2), len);
+ }
+
+ /* todo: */
+ bssid->NetworkTypeInUse = Ndis802_11OFDM24;
+
+ if (bssid->ie_length < 12)
+ return _FAIL;
+
+ /* Checking for DSConfig */
+ p = rtw_get_ie(bssid->ies + ie_offset, _DSSET_IE_, &len, bssid->ie_length - ie_offset);
+
+ bssid->Configuration.DSConfig = 0;
+ bssid->Configuration.Length = 0;
+
+ if (p) {
+ bssid->Configuration.DSConfig = *(p + 2);
+ } else {/* In 5G, some ap do not have DSSET IE */
+ /* checking HT info for channel */
+ p = rtw_get_ie(bssid->ies + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->ie_length - ie_offset);
+ if (p) {
+ struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
+
+ bssid->Configuration.DSConfig = HT_info->primary_channel;
+ } else { /* use current channel */
+ bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter);
+ }
+ }
+
+ if (subtype == WIFI_PROBEREQ) {
+ /* FIXME */
+ bssid->InfrastructureMode = Ndis802_11Infrastructure;
+ ether_addr_copy(bssid->MacAddress, GetAddr2Ptr(pframe));
+ bssid->Privacy = 1;
+ return _SUCCESS;
+ }
+
+ bssid->Configuration.BeaconPeriod =
+ get_unaligned_le16(rtw_get_beacon_interval_from_ie(bssid->ies));
+
+ val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid);
+
+ if (val16 & BIT(0)) {
+ bssid->InfrastructureMode = Ndis802_11Infrastructure;
+ ether_addr_copy(bssid->MacAddress, GetAddr2Ptr(pframe));
+ } else {
+ bssid->InfrastructureMode = Ndis802_11IBSS;
+ ether_addr_copy(bssid->MacAddress, GetAddr3Ptr(pframe));
+ }
+
+ if (val16 & BIT(4))
+ bssid->Privacy = 1;
+ else
+ bssid->Privacy = 0;
+
+ bssid->Configuration.ATIMWindow = 0;
+
+ /* 20/40 BSS Coexistence check */
+ if ((pregistrypriv->wifi_spec == 1) && (!pmlmeinfo->bwmode_updated)) {
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ p = rtw_get_ie(bssid->ies + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->ie_length - ie_offset);
+ if (p && len > 0) {
+ struct ieee80211_ht_cap *pHT_caps =
+ (struct ieee80211_ht_cap *)(p + 2);
+
+ if (le16_to_cpu(pHT_caps->cap_info) & BIT(14))
+ pmlmepriv->num_FortyMHzIntolerant++;
+ } else {
+ pmlmepriv->num_sta_no_ht++;
+ }
+ }
+
+ /* mark bss info receiving from nearby channel as SignalQuality 101 */
+ if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter))
+ bssid->PhyInfo.SignalQuality = 101;
+ return _SUCCESS;
+}
+
+static void start_create_ibss(struct adapter *padapter)
+{
+ unsigned short caps;
+ u8 val8;
+ u8 join_type;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network);
+
+ pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
+ pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
+
+ /* update wireless mode */
+ update_wireless_mode(padapter);
+
+ /* update capability */
+ caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
+ update_capinfo(padapter, caps);
+ if (caps & cap_IBSS) {/* adhoc master */
+ val8 = 0xcf;
+ rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
+
+ /* switch channel */
+ /* SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
+ set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+
+ beacon_timing_control(padapter);
+
+ /* set msr to WIFI_FW_ADHOC_STATE */
+ pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
+ Set_MSR(padapter, (pmlmeinfo->state & 0x3));
+
+ /* issue beacon */
+ if (send_beacon(padapter) == _FAIL) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("issuing beacon frame fail....\n"));
+
+ report_join_res(padapter, -1);
+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
+ } else {
+ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress);
+ join_type = 0;
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
+
+ report_join_res(padapter, 1);
+ pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
+ }
+ } else {
+ DBG_88E("%s, invalid cap:%x\n", __func__, caps);
+ return;
+ }
+}
+
+static void start_clnt_join(struct adapter *padapter)
+{
+ unsigned short caps;
+ u8 val8;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network);
+ int beacon_timeout;
+
+ pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
+ pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
+
+ /* update wireless mode */
+ update_wireless_mode(padapter);
+
+ /* update capability */
+ caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
+ update_capinfo(padapter, caps);
+ if (caps & cap_ESS) {
+ Set_MSR(padapter, WIFI_FW_STATION_STATE);
+
+ val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf;
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
+
+ /* switch channel */
+ set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+
+ /* here wait for receiving the beacon to start auth */
+ /* and enable a timer */
+ beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval);
+ set_link_timer(pmlmeext, beacon_timeout);
+ mod_timer(&padapter->mlmepriv.assoc_timer, jiffies +
+ msecs_to_jiffies((REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO * REASSOC_LIMIT) + beacon_timeout));
+
+ pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
+ } else if (caps & cap_IBSS) { /* adhoc client */
+ Set_MSR(padapter, WIFI_FW_ADHOC_STATE);
+
+ val8 = 0xcf;
+ rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
+
+ /* switch channel */
+ set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+
+ beacon_timing_control(padapter);
+
+ pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
+
+ report_join_res(padapter, 1);
+ } else {
+ return;
+ }
+}
+
+static void start_clnt_auth(struct adapter *padapter)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ del_timer_sync(&pmlmeext->link_timer);
+
+ pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
+ pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
+
+ pmlmeinfo->auth_seq = 1;
+ pmlmeinfo->reauth_count = 0;
+ pmlmeinfo->reassoc_count = 0;
+ pmlmeinfo->link_count = 0;
+ pmlmeext->retry = 0;
+
+ /* Because of AP's not receiving deauth before */
+ /* AP may: 1)not response auth or 2)deauth us after link is complete */
+ /* issue deauth before issuing auth to deal with the situation */
+ /* Commented by Albert 2012/07/21 */
+ /* For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */
+ issue_deauth(padapter, (&pmlmeinfo->network)->MacAddress, WLAN_REASON_DEAUTH_LEAVING);
+
+ DBG_88E_LEVEL(_drv_info_, "start auth\n");
+ issue_auth(padapter, NULL, 0);
+
+ set_link_timer(pmlmeext, REAUTH_TO);
+}
+
+static void start_clnt_assoc(struct adapter *padapter)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ del_timer_sync(&pmlmeext->link_timer);
+
+ pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
+ pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
+
+ issue_assocreq(padapter);
+
+ set_link_timer(pmlmeext, REASSOC_TO);
+}
+
+static unsigned int receive_disconnect(struct adapter *padapter,
+ unsigned char *MacAddr,
+ unsigned short reason)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
+
+ /* check A3 */
+ if (memcmp(MacAddr, pnetwork->MacAddress, ETH_ALEN))
+ return _SUCCESS;
+
+ DBG_88E("%s\n", __func__);
+
+ if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) {
+ if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
+ report_del_sta_event(padapter, MacAddr, reason);
+ } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
+ report_join_res(padapter, -2);
+ }
+ }
+ return _SUCCESS;
+}
+
+static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid)
+{
+ struct registry_priv *pregistrypriv;
+ struct mlme_ext_priv *pmlmeext;
+ struct rt_channel_info *chplan_new;
+ u8 channel;
+ u8 i;
+
+ pregistrypriv = &padapter->registrypriv;
+ pmlmeext = &padapter->mlmeextpriv;
+
+ /* Adjust channel plan by AP Country IE */
+ if (pregistrypriv->enable80211d &&
+ (!pmlmeext->update_channel_plan_by_ap_done)) {
+ u8 *ie, *p;
+ u32 len;
+ struct rt_channel_plan chplan_ap;
+ struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
+ u8 country[4];
+ u8 fcn; /* first channel number */
+ u8 noc; /* number of channel */
+ u8 j, k;
+
+ ie = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
+ if (!ie)
+ return;
+ if (len < 6)
+ return;
+ ie += 2;
+ p = ie;
+ ie += len;
+
+ memset(country, 0, 4);
+ memcpy(country, p, 3);
+ p += 3;
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
+ ("%s: 802.11d country =%s\n", __func__, country));
+
+ i = 0;
+ while ((ie - p) >= 3) {
+ fcn = *(p++);
+ noc = *(p++);
+ p++;
+
+ for (j = 0; j < noc; j++) {
+ channel = fcn + j;
+
+ chplan_ap.Channel[i++] = channel;
+ }
+ }
+ chplan_ap.Len = i;
+
+ memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
+
+ memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
+ chplan_new = pmlmeext->channel_set;
+
+ i = 0;
+ j = 0;
+ k = 0;
+ if (pregistrypriv->wireless_mode & WIRELESS_11G) {
+ do {
+ if ((i == MAX_CHANNEL_NUM) ||
+ (chplan_sta[i].ChannelNum == 0) ||
+ (chplan_sta[i].ChannelNum > 14))
+ break;
+
+ if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14))
+ break;
+
+ if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
+ chplan_new[k].ChannelNum = chplan_ap.Channel[j];
+ chplan_new[k].ScanType = SCAN_ACTIVE;
+ i++;
+ j++;
+ k++;
+ } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
+ chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
+ chplan_new[k].ScanType = SCAN_PASSIVE;
+ i++;
+ k++;
+ } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
+ chplan_new[k].ChannelNum = chplan_ap.Channel[j];
+ chplan_new[k].ScanType = SCAN_ACTIVE;
+ j++;
+ k++;
+ }
+ } while (1);
+
+ /* change AP not support channel to Passive scan */
+ while ((i < MAX_CHANNEL_NUM) &&
+ (chplan_sta[i].ChannelNum != 0) &&
+ (chplan_sta[i].ChannelNum <= 14)) {
+ chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
+ chplan_new[k].ScanType = SCAN_PASSIVE;
+ i++;
+ k++;
+ }
+
+ /* add channel AP supported */
+ while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
+ chplan_new[k].ChannelNum = chplan_ap.Channel[j];
+ chplan_new[k].ScanType = SCAN_ACTIVE;
+ j++;
+ k++;
+ }
+ } else {
+ /* keep original STA 2.4G channel plan */
+ while ((i < MAX_CHANNEL_NUM) &&
+ (chplan_sta[i].ChannelNum != 0) &&
+ (chplan_sta[i].ChannelNum <= 14)) {
+ chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
+ chplan_new[k].ScanType = chplan_sta[i].ScanType;
+ i++;
+ k++;
+ }
+
+ /* skip AP 2.4G channel plan */
+ while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14))
+ j++;
+ }
+
+ pmlmeext->update_channel_plan_by_ap_done = 1;
+ }
+
+ /* If channel is used by AP, set channel scan type to active */
+ channel = bssid->Configuration.DSConfig;
+ chplan_new = pmlmeext->channel_set;
+ i = 0;
+ while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) {
+ if (chplan_new[i].ChannelNum == channel) {
+ if (chplan_new[i].ScanType == SCAN_PASSIVE) {
+ chplan_new[i].ScanType = SCAN_ACTIVE;
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
+ ("%s: change channel %d scan type from passive to active\n",
+ __func__, channel));
+ }
+ break;
+ }
+ i++;
+ }
+}
+
+/****************************************************************************
+
+Following are the callback functions for each subtype of the management frames
+
+*****************************************************************************/
+
+static unsigned int OnProbeReq(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ unsigned int ielen;
+ unsigned char *p;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur = &pmlmeinfo->network;
+ u8 *pframe = precv_frame->pkt->data;
+ uint len = precv_frame->pkt->len;
+
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
+ return _SUCCESS;
+
+ if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
+ !check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE))
+ return _SUCCESS;
+
+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, &ielen,
+ len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
+
+ /* check (wildcard) SSID */
+ if (p) {
+ if ((ielen != 0 && memcmp((void *)(p+2), (void *)cur->ssid.ssid, cur->ssid.ssid_length)) ||
+ (ielen == 0 && pmlmeinfo->hidden_ssid_mode))
+ return _SUCCESS;
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED) &&
+ pmlmepriv->cur_network.join_res)
+ issue_probersp(padapter, get_sa(pframe));
+ }
+ return _SUCCESS;
+}
+
+static unsigned int OnProbeRsp(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
+ report_survey_event(padapter, precv_frame);
+ return _SUCCESS;
+ }
+
+ return _SUCCESS;
+}
+
+static unsigned int OnBeacon(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ int cam_idx;
+ struct sta_info *psta;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ u8 *pframe = precv_frame->pkt->data;
+ uint len = precv_frame->pkt->len;
+ struct wlan_bssid_ex *pbss;
+ int ret = _SUCCESS;
+ struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
+
+ if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
+ report_survey_event(padapter, precv_frame);
+ return _SUCCESS;
+ }
+
+ if (!memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN)) {
+ if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
+ /* we should update current network before auth, or some IE is wrong */
+ pbss = (struct wlan_bssid_ex *)rtw_malloc(sizeof(struct wlan_bssid_ex));
+ if (pbss) {
+ if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {
+ update_network(&pmlmepriv->cur_network.network, pbss, padapter, true);
+ rtw_get_bcn_info(&pmlmepriv->cur_network);
+ }
+ kfree(pbss);
+ }
+
+ /* check the vendor of the assoc AP */
+ pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct ieee80211_hdr_3addr), len-sizeof(struct ieee80211_hdr_3addr));
+
+ /* update TSF Value */
+ update_TSF(pmlmeext, pframe, len);
+
+ /* start auth */
+ start_clnt_auth(padapter);
+
+ return _SUCCESS;
+ }
+
+ if (((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
+ psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
+ if (psta != NULL) {
+ ret = rtw_check_bcn_info(padapter, pframe, len);
+ if (!ret) {
+ DBG_88E_LEVEL(_drv_info_, "ap has changed, disconnect now\n ");
+ receive_disconnect(padapter, pmlmeinfo->network.MacAddress, 65535);
+ return _SUCCESS;
+ }
+ /* update WMM, ERP in the beacon */
+ /* todo: the timer is used instead of the number of the beacon received */
+ if ((sta_rx_pkts(psta) & 0xf) == 0)
+ update_beacon_info(padapter, pframe, len, psta);
+ }
+ } else if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
+ psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
+ if (psta != NULL) {
+ /* update WMM, ERP in the beacon */
+ /* todo: the timer is used instead of the number of the beacon received */
+ if ((sta_rx_pkts(psta) & 0xf) == 0)
+ update_beacon_info(padapter, pframe, len, psta);
+ } else {
+ /* allocate a new CAM entry for IBSS station */
+ cam_idx = allocate_fw_sta_entry(padapter);
+ if (cam_idx == NUM_STA)
+ goto _END_ONBEACON_;
+
+ /* get supported rate */
+ if (update_sta_support_rate(padapter, (pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_), (len - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_), cam_idx) == _FAIL) {
+ pmlmeinfo->FW_sta_info[cam_idx].status = 0;
+ goto _END_ONBEACON_;
+ }
+
+ /* update TSF Value */
+ update_TSF(pmlmeext, pframe, len);
+
+ /* report sta add event */
+ report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx);
+ }
+ }
+ }
+
+_END_ONBEACON_:
+
+ return _SUCCESS;
+}
+
+#ifdef CPTCFG_88EU_AP_MODE
+static unsigned int OnAuth(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ unsigned int auth_mode, ie_len;
+ u16 seq;
+ unsigned char *sa, *p;
+ u16 algorithm;
+ int status;
+ static struct sta_info stat;
+ struct sta_info *pstat = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u8 *pframe = precv_frame->pkt->data;
+ uint len = precv_frame->pkt->len;
+
+ if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
+ return _FAIL;
+
+ DBG_88E("+%s\n", __func__);
+
+ sa = GetAddr2Ptr(pframe);
+
+ auth_mode = psecuritypriv->dot11AuthAlgrthm;
+ seq = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + 2));
+ algorithm = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN));
+
+ DBG_88E("auth alg=%x, seq=%X\n", algorithm, seq);
+
+ if (auth_mode == 2 && psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ &&
+ psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
+ auth_mode = 0;
+
+ if ((algorithm > 0 && auth_mode == 0) || /* rx a shared-key auth but shared not enabled */
+ (algorithm == 0 && auth_mode == 1)) { /* rx a open-system auth but shared-key is enabled */
+ DBG_88E("auth rejected due to bad alg [alg=%d, auth_mib=%d] %02X%02X%02X%02X%02X%02X\n",
+ algorithm, auth_mode, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);
+
+ status = _STATS_NO_SUPP_ALG_;
+
+ goto auth_fail;
+ }
+
+ if (!rtw_access_ctrl(padapter, sa)) {
+ status = _STATS_UNABLE_HANDLE_STA_;
+ goto auth_fail;
+ }
+
+ pstat = rtw_get_stainfo(pstapriv, sa);
+ if (!pstat) {
+ /* allocate a new one */
+ DBG_88E("going to alloc stainfo for sa=%pM\n", sa);
+ pstat = rtw_alloc_stainfo(pstapriv, sa);
+ if (!pstat) {
+ DBG_88E(" Exceed the upper limit of supported clients...\n");
+ status = _STATS_UNABLE_HANDLE_STA_;
+ goto auth_fail;
+ }
+
+ pstat->state = WIFI_FW_AUTH_NULL;
+ pstat->auth_seq = 0;
+ } else {
+ spin_lock_bh(&pstapriv->asoc_list_lock);
+ if (!list_empty(&pstat->asoc_list)) {
+ list_del_init(&pstat->asoc_list);
+ pstapriv->asoc_list_cnt--;
+ }
+ spin_unlock_bh(&pstapriv->asoc_list_lock);
+
+ if (seq == 1) {
+ /* TODO: STA re_auth and auth timeout */
+ }
+ }
+
+ spin_lock_bh(&pstapriv->auth_list_lock);
+ if (list_empty(&pstat->auth_list)) {
+ list_add_tail(&pstat->auth_list, &pstapriv->auth_list);
+ pstapriv->auth_list_cnt++;
+ }
+ spin_unlock_bh(&pstapriv->auth_list_lock);
+
+ if (pstat->auth_seq == 0)
+ pstat->expire_to = pstapriv->auth_to;
+
+ if ((pstat->auth_seq + 1) != seq) {
+ DBG_88E("(1)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
+ seq, pstat->auth_seq+1);
+ status = _STATS_OUT_OF_AUTH_SEQ_;
+ goto auth_fail;
+ }
+
+ if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2)) {
+ if (seq == 1) {
+ pstat->state &= ~WIFI_FW_AUTH_NULL;
+ pstat->state |= WIFI_FW_AUTH_SUCCESS;
+ pstat->expire_to = pstapriv->assoc_to;
+ pstat->authalg = algorithm;
+ } else {
+ DBG_88E("(2)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
+ seq, pstat->auth_seq+1);
+ status = _STATS_OUT_OF_AUTH_SEQ_;
+ goto auth_fail;
+ }
+ } else { /* shared system or auto authentication */
+ if (seq == 1) {
+ /* prepare for the challenging txt... */
+
+ pstat->state &= ~WIFI_FW_AUTH_NULL;
+ pstat->state |= WIFI_FW_AUTH_STATE;
+ pstat->authalg = algorithm;
+ pstat->auth_seq = 2;
+ } else if (seq == 3) {
+ /* checking for challenging txt... */
+ DBG_88E("checking for challenging txt...\n");
+
+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, &ie_len,
+ len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4);
+
+ if ((p == NULL) || (ie_len <= 0)) {
+ DBG_88E("auth rejected because challenge failure!(1)\n");
+ status = _STATS_CHALLENGE_FAIL_;
+ goto auth_fail;
+ }
+
+ if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) {
+ pstat->state &= (~WIFI_FW_AUTH_STATE);
+ pstat->state |= WIFI_FW_AUTH_SUCCESS;
+ /* challenging txt is correct... */
+ pstat->expire_to = pstapriv->assoc_to;
+ } else {
+ DBG_88E("auth rejected because challenge failure!\n");
+ status = _STATS_CHALLENGE_FAIL_;
+ goto auth_fail;
+ }
+ } else {
+ DBG_88E("(3)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
+ seq, pstat->auth_seq+1);
+ status = _STATS_OUT_OF_AUTH_SEQ_;
+ goto auth_fail;
+ }
+ }
+
+ /* Now, we are going to issue_auth... */
+ pstat->auth_seq = seq + 1;
+
+ issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_));
+
+ if (pstat->state & WIFI_FW_AUTH_SUCCESS)
+ pstat->auth_seq = 0;
+
+ return _SUCCESS;
+
+auth_fail:
+
+ if (pstat)
+ rtw_free_stainfo(padapter, pstat);
+
+ pstat = &stat;
+ memset((char *)pstat, '\0', sizeof(stat));
+ pstat->auth_seq = 2;
+ memcpy(pstat->hwaddr, sa, 6);
+
+ issue_auth(padapter, pstat, (unsigned short)status);
+
+ return _FAIL;
+}
+#endif /* CPTCFG_88EU_AP_MODE */
+
+static unsigned int OnAuthClient(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ unsigned int seq, len, status, offset;
+ unsigned char *p;
+ unsigned int go2asoc = 0;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u8 *pframe = precv_frame->pkt->data;
+ uint pkt_len = precv_frame->pkt->len;
+
+ DBG_88E("%s\n", __func__);
+
+ /* check A1 matches or not */
+ if (memcmp(myid(&padapter->eeprompriv), get_da(pframe), ETH_ALEN))
+ return _SUCCESS;
+
+ if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
+ return _SUCCESS;
+
+ offset = (GetPrivacy(pframe)) ? 4 : 0;
+
+ seq = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 2));
+ status = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 4));
+
+ if (status != 0) {
+ DBG_88E("clnt auth fail, status: %d\n", status);
+ if (status == 13) { /* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
+ if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
+ pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
+ else
+ pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
+ }
+
+ set_link_timer(pmlmeext, 1);
+ goto authclnt_fail;
+ }
+
+ if (seq == 2) {
+ if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
+ /* legendary shared system */
+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, &len,
+ pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_);
+
+ if (p == NULL)
+ goto authclnt_fail;
+
+ memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);
+ pmlmeinfo->auth_seq = 3;
+ issue_auth(padapter, NULL, 0);
+ set_link_timer(pmlmeext, REAUTH_TO);
+
+ return _SUCCESS;
+ } else {
+ /* open system */
+ go2asoc = 1;
+ }
+ } else if (seq == 4) {
+ if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
+ go2asoc = 1;
+ else
+ goto authclnt_fail;
+ } else {
+ /* this is also illegal */
+ goto authclnt_fail;
+ }
+
+ if (go2asoc) {
+ DBG_88E_LEVEL(_drv_info_, "auth success, start assoc\n");
+ start_clnt_assoc(padapter);
+ return _SUCCESS;
+ }
+authclnt_fail:
+ return _FAIL;
+}
+
+static unsigned int OnAssocReq(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+#ifdef CPTCFG_88EU_AP_MODE
+ u16 capab_info;
+ struct rtw_ieee802_11_elems elems;
+ struct sta_info *pstat;
+ unsigned char reassoc, *p, *pos, *wpa_ie;
+ unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
+ int i, wpa_ie_len, left;
+ unsigned char supportRate[16];
+ int supportRateNum;
+ unsigned short status = _STATS_SUCCESSFUL_;
+ unsigned short frame_type, ie_offset = 0;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur = &pmlmeinfo->network;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ u8 *pframe = precv_frame->pkt->data;
+ uint ie_len, pkt_len = precv_frame->pkt->len;
+
+ if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
+ return _FAIL;
+
+ frame_type = GetFrameSubType(pframe);
+ if (frame_type == WIFI_ASSOCREQ) {
+ reassoc = 0;
+ ie_offset = _ASOCREQ_IE_OFFSET_;
+ } else { /* WIFI_REASSOCREQ */
+ reassoc = 1;
+ ie_offset = _REASOCREQ_IE_OFFSET_;
+ }
+
+ if (pkt_len < IEEE80211_3ADDR_LEN + ie_offset) {
+ DBG_88E("handle_assoc(reassoc=%d) - too short payload (len=%lu)"
+ "\n", reassoc, (unsigned long)pkt_len);
+ return _FAIL;
+ }
+
+ pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
+ if (!pstat) {
+ status = _RSON_CLS2_;
+ goto asoc_class2_error;
+ }
+
+ capab_info = get_unaligned_le16(pframe + WLAN_HDR_A3_LEN);
+
+ left = pkt_len - (IEEE80211_3ADDR_LEN + ie_offset);
+ pos = pframe + (IEEE80211_3ADDR_LEN + ie_offset);
+
+ DBG_88E("%s\n", __func__);
+
+ /* check if this stat has been successfully authenticated/assocated */
+ if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) {
+ if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) {
+ status = _RSON_CLS2_;
+ goto asoc_class2_error;
+ } else {
+ pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
+ pstat->state |= WIFI_FW_ASSOC_STATE;
+ }
+ } else {
+ pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
+ pstat->state |= WIFI_FW_ASSOC_STATE;
+ }
+ pstat->capability = capab_info;
+ /* now parse all ieee802_11 ie to point to elems */
+ if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed ||
+ !elems.ssid) {
+ DBG_88E("STA %pM sent invalid association request\n",
+ pstat->hwaddr);
+ status = _STATS_FAILURE_;
+ goto OnAssocReqFail;
+ }
+
+ /* now we should check all the fields... */
+ /* checking SSID */
+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SSID_IE_, &ie_len,
+ pkt_len - WLAN_HDR_A3_LEN - ie_offset);
+
+ if (!p || ie_len == 0) {
+ /* broadcast ssid, however it is not allowed in assocreq */
+ status = _STATS_FAILURE_;
+ goto OnAssocReqFail;
+ } else {
+ /* check if ssid match */
+ if (memcmp((void *)(p+2), cur->ssid.ssid, cur->ssid.ssid_length))
+ status = _STATS_FAILURE_;
+
+ if (ie_len != cur->ssid.ssid_length)
+ status = _STATS_FAILURE_;
+ }
+
+ if (_STATS_SUCCESSFUL_ != status)
+ goto OnAssocReqFail;
+
+ /* check if the supported rate is ok */
+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
+ if (p == NULL) {
+ DBG_88E("Rx a sta assoc-req which supported rate is empty!\n");
+ /* use our own rate set as statoin used */
+ /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
+ /* supportRateNum = AP_BSSRATE_LEN; */
+
+ status = _STATS_FAILURE_;
+ goto OnAssocReqFail;
+ } else {
+ memcpy(supportRate, p+2, ie_len);
+ supportRateNum = ie_len;
+
+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_, &ie_len,
+ pkt_len - WLAN_HDR_A3_LEN - ie_offset);
+ if (p != NULL) {
+ if (supportRateNum <= sizeof(supportRate)) {
+ memcpy(supportRate+supportRateNum, p+2, ie_len);
+ supportRateNum += ie_len;
+ }
+ }
+ }
+
+ /* todo: mask supportRate between AP & STA -> move to update raid */
+ /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */
+
+ /* update station supportRate */
+ pstat->bssratelen = supportRateNum;
+ memcpy(pstat->bssrateset, supportRate, supportRateNum);
+ UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
+
+ /* check RSN/WPA/WPS */
+ pstat->dot8021xalg = 0;
+ pstat->wpa_psk = 0;
+ pstat->wpa_group_cipher = 0;
+ pstat->wpa2_group_cipher = 0;
+ pstat->wpa_pairwise_cipher = 0;
+ pstat->wpa2_pairwise_cipher = 0;
+ memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
+ if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
+ int group_cipher = 0, pairwise_cipher = 0;
+
+ wpa_ie = elems.rsn_ie;
+ wpa_ie_len = elems.rsn_ie_len;
+
+ if (rtw_parse_wpa2_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
+ pstat->dot8021xalg = 1;/* psk, todo:802.1x */
+ pstat->wpa_psk |= BIT(1);
+
+ pstat->wpa2_group_cipher = group_cipher & psecuritypriv->wpa2_group_cipher;
+ pstat->wpa2_pairwise_cipher = pairwise_cipher & psecuritypriv->wpa2_pairwise_cipher;
+
+ if (!pstat->wpa2_group_cipher)
+ status = WLAN_STATUS_INVALID_GROUP_CIPHER;
+
+ if (!pstat->wpa2_pairwise_cipher)
+ status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
+ } else {
+ status = WLAN_STATUS_INVALID_IE;
+ }
+ } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) {
+ int group_cipher = 0, pairwise_cipher = 0;
+
+ wpa_ie = elems.wpa_ie;
+ wpa_ie_len = elems.wpa_ie_len;
+
+ if (rtw_parse_wpa_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
+ pstat->dot8021xalg = 1;/* psk, todo:802.1x */
+ pstat->wpa_psk |= BIT(0);
+
+ pstat->wpa_group_cipher = group_cipher & psecuritypriv->wpa_group_cipher;
+ pstat->wpa_pairwise_cipher = pairwise_cipher & psecuritypriv->wpa_pairwise_cipher;
+
+ if (!pstat->wpa_group_cipher)
+ status = WLAN_STATUS_INVALID_GROUP_CIPHER;
+
+ if (!pstat->wpa_pairwise_cipher)
+ status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
+ } else {
+ status = WLAN_STATUS_INVALID_IE;
+ }
+ } else {
+ wpa_ie = NULL;
+ wpa_ie_len = 0;
+ }
+
+ if (_STATS_SUCCESSFUL_ != status)
+ goto OnAssocReqFail;
+
+ pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
+ if (!wpa_ie) {
+ if (elems.wps_ie) {
+ DBG_88E("STA included WPS IE in "
+ "(Re)Association Request - assume WPS is "
+ "used\n");
+ pstat->flags |= WLAN_STA_WPS;
+ /* wpabuf_free(sta->wps_ie); */
+ /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */
+ /* elems.wps_ie_len - 4); */
+ } else {
+ DBG_88E("STA did not include WPA/RSN IE "
+ "in (Re)Association Request - possible WPS "
+ "use\n");
+ pstat->flags |= WLAN_STA_MAYBE_WPS;
+ }
+
+ /* AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */
+ /* that the selected registrar of AP is _FLASE */
+ if ((psecuritypriv->wpa_psk > 0) && (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS))) {
+ if (pmlmepriv->wps_beacon_ie) {
+ u8 selected_registrar = 0;
+
+ rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL);
+
+ if (!selected_registrar) {
+ DBG_88E("selected_registrar is false , or AP is not ready to do WPS\n");
+
+ status = _STATS_UNABLE_HANDLE_STA_;
+
+ goto OnAssocReqFail;
+ }
+ }
+ }
+ } else {
+ int copy_len;
+
+ if (psecuritypriv->wpa_psk == 0) {
+ DBG_88E("STA %pM: WPA/RSN IE in association "
+ "request, but AP don't support WPA/RSN\n", pstat->hwaddr);
+
+ status = WLAN_STATUS_INVALID_IE;
+
+ goto OnAssocReqFail;
+ }
+
+ if (elems.wps_ie) {
+ DBG_88E("STA included WPS IE in "
+ "(Re)Association Request - WPS is "
+ "used\n");
+ pstat->flags |= WLAN_STA_WPS;
+ copy_len = 0;
+ } else {
+ copy_len = min_t(int, wpa_ie_len + 2, sizeof(pstat->wpa_ie));
+ }
+ if (copy_len > 0)
+ memcpy(pstat->wpa_ie, wpa_ie-2, copy_len);
+ }
+ /* check if there is WMM IE & support WWM-PS */
+ pstat->flags &= ~WLAN_STA_WME;
+ pstat->qos_option = 0;
+ pstat->qos_info = 0;
+ pstat->has_legacy_ac = true;
+ pstat->uapsd_vo = 0;
+ pstat->uapsd_vi = 0;
+ pstat->uapsd_be = 0;
+ pstat->uapsd_bk = 0;
+ if (pmlmepriv->qospriv.qos_option) {
+ p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0;
+ for (;;) {
+ p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
+ if (p != NULL) {
+ if (!memcmp(p+2, WMM_IE, 6)) {
+ pstat->flags |= WLAN_STA_WME;
+
+ pstat->qos_option = 1;
+ pstat->qos_info = *(p+8);
+
+ pstat->max_sp_len = (pstat->qos_info>>5) & 0x3;
+
+ if ((pstat->qos_info & 0xf) != 0xf)
+ pstat->has_legacy_ac = true;
+ else
+ pstat->has_legacy_ac = false;
+
+ if (pstat->qos_info & 0xf) {
+ if (pstat->qos_info & BIT(0))
+ pstat->uapsd_vo = BIT(0)|BIT(1);
+ else
+ pstat->uapsd_vo = 0;
+
+ if (pstat->qos_info & BIT(1))
+ pstat->uapsd_vi = BIT(0)|BIT(1);
+ else
+ pstat->uapsd_vi = 0;
+
+ if (pstat->qos_info & BIT(2))
+ pstat->uapsd_bk = BIT(0)|BIT(1);
+ else
+ pstat->uapsd_bk = 0;
+
+ if (pstat->qos_info & BIT(3))
+ pstat->uapsd_be = BIT(0)|BIT(1);
+ else
+ pstat->uapsd_be = 0;
+ }
+ break;
+ }
+ } else {
+ break;
+ }
+ p = p + ie_len + 2;
+ }
+ }
+
+ /* save HT capabilities in the sta object */
+ memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap));
+ if (elems.ht_capabilities &&
+ elems.ht_capabilities_len >= sizeof(struct ieee80211_ht_cap)) {
+ pstat->flags |= WLAN_STA_HT;
+
+ pstat->flags |= WLAN_STA_WME;
+
+ memcpy(&pstat->htpriv.ht_cap,
+ elems.ht_capabilities, sizeof(struct ieee80211_ht_cap));
+ } else {
+ pstat->flags &= ~WLAN_STA_HT;
+ }
+ if ((!pmlmepriv->htpriv.ht_option) && (pstat->flags & WLAN_STA_HT)) {
+ status = _STATS_FAILURE_;
+ goto OnAssocReqFail;
+ }
+
+ if ((pstat->flags & WLAN_STA_HT) &&
+ ((pstat->wpa2_pairwise_cipher & WPA_CIPHER_TKIP) ||
+ (pstat->wpa_pairwise_cipher & WPA_CIPHER_TKIP))) {
+ DBG_88E("HT: %pM tried to "
+ "use TKIP with HT association\n", pstat->hwaddr);
+
+ /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */
+ /* goto OnAssocReqFail; */
+ }
+
+ pstat->flags |= WLAN_STA_NONERP;
+ for (i = 0; i < pstat->bssratelen; i++) {
+ if ((pstat->bssrateset[i] & 0x7f) > 22) {
+ pstat->flags &= ~WLAN_STA_NONERP;
+ break;
+ }
+ }
+
+ if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+ pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
+ else
+ pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
+
+ if (status != _STATS_SUCCESSFUL_)
+ goto OnAssocReqFail;
+
+ /* TODO: identify_proprietary_vendor_ie(); */
+ /* Realtek proprietary IE */
+ /* identify if this is Broadcom sta */
+ /* identify if this is ralink sta */
+ /* Customer proprietary IE */
+
+ /* get a unique AID */
+ if (pstat->aid > 0) {
+ DBG_88E(" old AID %d\n", pstat->aid);
+ } else {
+ for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
+ if (pstapriv->sta_aid[pstat->aid - 1] == NULL)
+ break;
+
+ /* if (pstat->aid > NUM_STA) { */
+ if (pstat->aid > pstapriv->max_num_sta) {
+ pstat->aid = 0;
+
+ DBG_88E(" no room for more AIDs\n");
+
+ status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
+
+ goto OnAssocReqFail;
+ } else {
+ pstapriv->sta_aid[pstat->aid - 1] = pstat;
+ DBG_88E("allocate new AID=(%d)\n", pstat->aid);
+ }
+ }
+
+ pstat->state &= (~WIFI_FW_ASSOC_STATE);
+ pstat->state |= WIFI_FW_ASSOC_SUCCESS;
+
+ spin_lock_bh(&pstapriv->auth_list_lock);
+ if (!list_empty(&pstat->auth_list)) {
+ list_del_init(&pstat->auth_list);
+ pstapriv->auth_list_cnt--;
+ }
+ spin_unlock_bh(&pstapriv->auth_list_lock);
+
+ spin_lock_bh(&pstapriv->asoc_list_lock);
+ if (list_empty(&pstat->asoc_list)) {
+ pstat->expire_to = pstapriv->expire_to;
+ list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list);
+ pstapriv->asoc_list_cnt++;
+ }
+ spin_unlock_bh(&pstapriv->asoc_list_lock);
+
+ /* now the station is qualified to join our BSS... */
+ if ((pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_ == status)) {
+ /* 1 bss_cap_update & sta_info_update */
+ bss_cap_update_on_sta_join(padapter, pstat);
+ sta_info_update(padapter, pstat);
+
+ /* issue assoc rsp before notify station join event. */
+ if (frame_type == WIFI_ASSOCREQ)
+ issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
+ else
+ issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
+
+ /* 2 - report to upper layer */
+ DBG_88E("indicate_sta_join_event to upper layer - hostapd\n");
+ rtw_indicate_sta_assoc_event(padapter, pstat);
+
+ /* 3-(1) report sta add event */
+ report_add_sta_event(padapter, pstat->hwaddr, pstat->aid);
+ }
+
+ return _SUCCESS;
+
+asoc_class2_error:
+
+ issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status);
+
+ return _FAIL;
+
+OnAssocReqFail:
+
+ pstat->aid = 0;
+ if (frame_type == WIFI_ASSOCREQ)
+ issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
+ else
+ issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
+
+#endif /* CPTCFG_88EU_AP_MODE */
+
+ return _FAIL;
+}
+
+static unsigned int OnAssocRsp(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ uint i;
+ int res;
+ unsigned short status;
+ struct ndis_802_11_var_ie *pIE;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u8 *pframe = precv_frame->pkt->data;
+ uint pkt_len = precv_frame->pkt->len;
+
+ DBG_88E("%s\n", __func__);
+
+ /* check A1 matches or not */
+ if (memcmp(myid(&padapter->eeprompriv), get_da(pframe), ETH_ALEN))
+ return _SUCCESS;
+
+ if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
+ return _SUCCESS;
+
+ if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
+ return _SUCCESS;
+
+ del_timer_sync(&pmlmeext->link_timer);
+
+ /* status */
+ status = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 2));
+ if (status > 0) {
+ DBG_88E("assoc reject, status code: %d\n", status);
+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
+ res = -4;
+ goto report_assoc_result;
+ }
+
+ /* get capabilities */
+ pmlmeinfo->capability = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
+
+ /* set slot time */
+ pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20;
+
+ /* AID */
+ pmlmeinfo->aid = (int)(le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 4)) & 0x3fff);
+ res = pmlmeinfo->aid;
+
+ /* following are moved to join event callback function */
+ /* to handle HT, WMM, rate adaptive, update MAC reg */
+ /* for not to handle the synchronous IO in the tasklet */
+ for (i = 6 + WLAN_HDR_A3_LEN; i < pkt_len;) {
+ pIE = (struct ndis_802_11_var_ie *)(pframe + i);
+
+ switch (pIE->ElementID) {
+ case _VENDOR_SPECIFIC_IE_:
+ if (!memcmp(pIE->data, WMM_PARA_OUI, 6)) /* WMM */
+ WMM_param_handler(padapter, pIE);
+ break;
+ case _HT_CAPABILITY_IE_: /* HT caps */
+ HT_caps_handler(padapter, pIE);
+ break;
+ case _HT_EXTRA_INFO_IE_: /* HT info */
+ HT_info_handler(padapter, pIE);
+ break;
+ case _ERPINFO_IE_:
+ ERP_IE_handler(padapter, pIE);
+ default:
+ break;
+ }
+
+ i += (pIE->Length + 2);
+ }
+
+ pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
+ pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
+
+ UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates);
+
+report_assoc_result:
+ if (res > 0)
+ rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len);
+ else
+ rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
+
+ report_join_res(padapter, res);
+
+ return _SUCCESS;
+}
+
+static unsigned int OnDeAuth(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ unsigned short reason;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u8 *pframe = precv_frame->pkt->data;
+ struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
+
+ /* check A3 */
+ if (memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN))
+ return _SUCCESS;
+
+ reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
+
+ DBG_88E("%s Reason code(%d)\n", __func__, reason);
+
+#ifdef CPTCFG_88EU_AP_MODE
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+ struct sta_info *psta;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ DBG_88E_LEVEL(_drv_always_, "ap recv deauth reason code(%d) sta:%pM\n",
+ reason, GetAddr2Ptr(pframe));
+
+ psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
+ if (psta) {
+ u8 updated = 0;
+
+ spin_lock_bh(&pstapriv->asoc_list_lock);
+ if (!list_empty(&psta->asoc_list)) {
+ list_del_init(&psta->asoc_list);
+ pstapriv->asoc_list_cnt--;
+ updated = ap_free_sta(padapter, psta, false, reason);
+ }
+ spin_unlock_bh(&pstapriv->asoc_list_lock);
+
+ associated_clients_update(padapter, updated);
+ }
+
+ return _SUCCESS;
+ } else
+#endif
+ {
+ DBG_88E_LEVEL(_drv_always_, "sta recv deauth reason code(%d) sta:%pM\n",
+ reason, GetAddr3Ptr(pframe));
+
+ receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
+ }
+ pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
+ return _SUCCESS;
+}
+
+static unsigned int OnDisassoc(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ u16 reason;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u8 *pframe = precv_frame->pkt->data;
+ struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
+
+ /* check A3 */
+ if (memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN))
+ return _SUCCESS;
+
+ reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
+
+ DBG_88E("%s Reason code(%d)\n", __func__, reason);
+
+#ifdef CPTCFG_88EU_AP_MODE
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+ struct sta_info *psta;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ DBG_88E_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n",
+ reason, GetAddr2Ptr(pframe));
+
+ psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
+ if (psta) {
+ u8 updated = 0;
+
+ spin_lock_bh(&pstapriv->asoc_list_lock);
+ if (!list_empty(&psta->asoc_list)) {
+ list_del_init(&psta->asoc_list);
+ pstapriv->asoc_list_cnt--;
+ updated = ap_free_sta(padapter, psta, false, reason);
+ }
+ spin_unlock_bh(&pstapriv->asoc_list_lock);
+
+ associated_clients_update(padapter, updated);
+ }
+
+ return _SUCCESS;
+ } else
+#endif
+ {
+ DBG_88E_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n",
+ reason, GetAddr3Ptr(pframe));
+
+ receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
+ }
+ pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
+ return _SUCCESS;
+}
+
+static unsigned int OnAtim(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ DBG_88E("%s\n", __func__);
+ return _SUCCESS;
+}
+
+static unsigned int on_action_spct(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ struct sta_info *psta = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ u8 *pframe = precv_frame->pkt->data;
+ u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
+ u8 category;
+ u8 action;
+
+ DBG_88E(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
+
+ psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
+
+ if (!psta)
+ goto exit;
+
+ category = frame_body[0];
+ if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT)
+ goto exit;
+
+ action = frame_body[1];
+ switch (action) {
+ case RTW_WLAN_ACTION_SPCT_MSR_REQ:
+ case RTW_WLAN_ACTION_SPCT_MSR_RPRT:
+ case RTW_WLAN_ACTION_SPCT_TPC_REQ:
+ case RTW_WLAN_ACTION_SPCT_TPC_RPRT:
+ break;
+ case RTW_WLAN_ACTION_SPCT_CHL_SWITCH:
+ break;
+ default:
+ break;
+ }
+
+exit:
+ return _FAIL;
+}
+
+static unsigned int OnAction_qos(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ return _SUCCESS;
+}
+
+static unsigned int OnAction_dls(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ return _SUCCESS;
+}
+
+static unsigned int OnAction_back(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ u8 *addr;
+ struct sta_info *psta = NULL;
+ struct recv_reorder_ctrl *preorder_ctrl;
+ unsigned char *frame_body;
+ unsigned char category, action;
+ unsigned short tid, status, reason_code = 0;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u8 *pframe = precv_frame->pkt->data;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ /* check RA matches or not */
+ if (memcmp(myid(&padapter->eeprompriv), GetAddr1Ptr(pframe),
+ ETH_ALEN))/* for if1, sta/ap mode */
+ return _SUCCESS;
+
+ DBG_88E("%s\n", __func__);
+
+ if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
+ if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
+ return _SUCCESS;
+
+ addr = GetAddr2Ptr(pframe);
+ psta = rtw_get_stainfo(pstapriv, addr);
+
+ if (!psta)
+ return _SUCCESS;
+
+ frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
+
+ category = frame_body[0];
+ if (category == RTW_WLAN_CATEGORY_BACK) { /* representing Block Ack */
+ if (!pmlmeinfo->HT_enable)
+ return _SUCCESS;
+ action = frame_body[1];
+ DBG_88E("%s, action=%d\n", __func__, action);
+ switch (action) {
+ case RTW_WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
+ memcpy(&pmlmeinfo->ADDBA_req, &frame_body[2], sizeof(struct ADDBA_request));
+ process_addba_req(padapter, (u8 *)&pmlmeinfo->ADDBA_req, addr);
+
+ /* 37 = reject ADDBA Req */
+ issue_action_BA(padapter, addr,
+ RTW_WLAN_ACTION_ADDBA_RESP,
+ pmlmeinfo->accept_addba_req ? 0 : 37);
+ break;
+ case RTW_WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
+ status = get_unaligned_le16(&frame_body[3]);
+ tid = (frame_body[5] >> 2) & 0x7;
+ if (status == 0) { /* successful */
+ DBG_88E("agg_enable for TID=%d\n", tid);
+ psta->htpriv.agg_enable_bitmap |= 1 << tid;
+ psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
+ } else {
+ psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
+ }
+ break;
+ case RTW_WLAN_ACTION_DELBA: /* DELBA */
+ if ((frame_body[3] & BIT(3)) == 0) {
+ psta->htpriv.agg_enable_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
+ psta->htpriv.candidate_tid_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
+ reason_code = get_unaligned_le16(&frame_body[4]);
+ } else if ((frame_body[3] & BIT(3)) == BIT(3)) {
+ tid = (frame_body[3] >> 4) & 0x0F;
+ preorder_ctrl = &psta->recvreorder_ctrl[tid];
+ preorder_ctrl->enable = false;
+ preorder_ctrl->indicate_seq = 0xffff;
+ }
+ DBG_88E("%s(): DELBA: %x(%x)\n", __func__, pmlmeinfo->agg_enable_bitmap, reason_code);
+ /* todo: how to notify the host while receiving DELETE BA */
+ break;
+ default:
+ break;
+ }
+ }
+ return _SUCCESS;
+}
+
+static s32 rtw_action_public_decache(struct recv_frame *recv_frame, s32 token)
+{
+ struct adapter *adapter = recv_frame->adapter;
+ struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
+ u8 *frame = recv_frame->pkt->data;
+ u16 seq_ctrl = ((recv_frame->attrib.seq_num & 0xffff) << 4) |
+ (recv_frame->attrib.frag_num & 0xf);
+
+ if (GetRetry(frame)) {
+ if (token >= 0) {
+ if ((seq_ctrl == mlmeext->action_public_rxseq) && (token == mlmeext->action_public_dialog_token)) {
+ DBG_88E(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x, token:%d\n",
+ FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq, token);
+ return _FAIL;
+ }
+ } else {
+ if (seq_ctrl == mlmeext->action_public_rxseq) {
+ DBG_88E(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x\n",
+ FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq);
+ return _FAIL;
+ }
+ }
+ }
+
+ mlmeext->action_public_rxseq = seq_ctrl;
+
+ if (token >= 0)
+ mlmeext->action_public_dialog_token = token;
+
+ return _SUCCESS;
+}
+
+static unsigned int on_action_public_p2p(struct recv_frame *precv_frame)
+{
+ u8 *pframe = precv_frame->pkt->data;
+ u8 *frame_body;
+ u8 dialogToken = 0;
+
+ frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
+ dialogToken = frame_body[7];
+
+ if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
+ return _FAIL;
+
+ return _SUCCESS;
+}
+
+static unsigned int on_action_public_vendor(struct recv_frame *precv_frame)
+{
+ unsigned int ret = _FAIL;
+ u8 *pframe = precv_frame->pkt->data;
+ u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
+
+ if (!memcmp(frame_body + 2, P2P_OUI, 4))
+ ret = on_action_public_p2p(precv_frame);
+
+ return ret;
+}
+
+static unsigned int on_action_public_default(struct recv_frame *precv_frame,
+ u8 action)
+{
+ unsigned int ret = _FAIL;
+ u8 *pframe = precv_frame->pkt->data;
+ u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
+ u8 token;
+
+ token = frame_body[2];
+
+ if (rtw_action_public_decache(precv_frame, token) == _FAIL)
+ goto exit;
+
+ ret = _SUCCESS;
+
+exit:
+ return ret;
+}
+
+static unsigned int on_action_public(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ unsigned int ret = _FAIL;
+ u8 *pframe = precv_frame->pkt->data;
+ u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
+ u8 category, action;
+
+ /* check RA matches or not */
+ if (memcmp(myid(&padapter->eeprompriv), GetAddr1Ptr(pframe), ETH_ALEN))
+ goto exit;
+
+ category = frame_body[0];
+ if (category != RTW_WLAN_CATEGORY_PUBLIC)
+ goto exit;
+
+ action = frame_body[1];
+ switch (action) {
+ case ACT_PUBLIC_VENDOR:
+ ret = on_action_public_vendor(precv_frame);
+ break;
+ default:
+ ret = on_action_public_default(precv_frame, action);
+ break;
+ }
+
+exit:
+ return ret;
+}
+
+static unsigned int OnAction_ht(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ return _SUCCESS;
+}
+
+static unsigned int OnAction_wmm(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ return _SUCCESS;
+}
+
+static unsigned int OnAction_p2p(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ return _SUCCESS;
+}
+
+static unsigned int DoReserved(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ return _SUCCESS;
+}
+
+static struct action_handler OnAction_tbl[] = {
+ {RTW_WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct},
+ {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction_qos},
+ {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction_dls},
+ {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back},
+ {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public},
+ {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved},
+ {RTW_WLAN_CATEGORY_FT, "ACTION_FT", &DoReserved},
+ {RTW_WLAN_CATEGORY_HT, "ACTION_HT", &OnAction_ht},
+ {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved},
+ {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction_wmm},
+ {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &OnAction_p2p},
+};
+
+static unsigned int OnAction(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ int i;
+ unsigned char category;
+ struct action_handler *ptable;
+ unsigned char *frame_body;
+ u8 *pframe = precv_frame->pkt->data;
+
+ frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
+
+ category = frame_body[0];
+
+ for (i = 0; i < ARRAY_SIZE(OnAction_tbl); i++) {
+ ptable = &OnAction_tbl[i];
+ if (category == ptable->num)
+ ptable->func(padapter, precv_frame);
+ }
+ return _SUCCESS;
+}
+
+/****************************************************************************
+
+Following are the initialization functions for WiFi MLME
+
+*****************************************************************************/
+
+static struct mlme_handler mlme_sta_tbl[] = {
+ {WIFI_ASSOCREQ, "OnAssocReq", &OnAssocReq},
+ {WIFI_ASSOCRSP, "OnAssocRsp", &OnAssocRsp},
+ {WIFI_REASSOCREQ, "OnReAssocReq", &OnAssocReq},
+ {WIFI_REASSOCRSP, "OnReAssocRsp", &OnAssocRsp},
+ {WIFI_PROBEREQ, "OnProbeReq", &OnProbeReq},
+ {WIFI_PROBERSP, "OnProbeRsp", &OnProbeRsp},
+ {0, "DoReserved", &DoReserved},
+ {0, "DoReserved", &DoReserved},
+ {WIFI_BEACON, "OnBeacon", &OnBeacon},
+ {WIFI_ATIM, "OnATIM", &OnAtim},
+ {WIFI_DISASSOC, "OnDisassoc", &OnDisassoc},
+ {WIFI_AUTH, "OnAuth", &OnAuthClient},
+ {WIFI_DEAUTH, "OnDeAuth", &OnDeAuth},
+ {WIFI_ACTION, "OnAction", &OnAction},
+};
+
+int init_hw_mlme_ext(struct adapter *padapter)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+ return _SUCCESS;
+}
+
+static void init_mlme_ext_priv_value(struct adapter *padapter)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ unsigned char mixed_datarate[NumRates] = {
+ _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
+ _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_,
+ _48M_RATE_, _54M_RATE_, 0xff
+ };
+ unsigned char mixed_basicrate[NumRates] = {
+ _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
+ _12M_RATE_, _24M_RATE_, 0xff,
+ };
+
+ atomic_set(&pmlmeext->event_seq, 0);
+ pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */
+
+ pmlmeext->cur_channel = padapter->registrypriv.channel;
+ pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ pmlmeext->oper_channel = pmlmeext->cur_channel;
+ pmlmeext->oper_bwmode = pmlmeext->cur_bwmode;
+ pmlmeext->oper_ch_offset = pmlmeext->cur_ch_offset;
+ pmlmeext->retry = 0;
+
+ pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
+
+ memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
+ memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
+
+ pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
+
+ pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
+ pmlmeext->sitesurvey_res.channel_idx = 0;
+ pmlmeext->sitesurvey_res.bss_cnt = 0;
+ pmlmeext->scan_abort = false;
+
+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
+ pmlmeinfo->reauth_count = 0;
+ pmlmeinfo->reassoc_count = 0;
+ pmlmeinfo->link_count = 0;
+ pmlmeinfo->auth_seq = 0;
+ pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
+ pmlmeinfo->key_index = 0;
+ pmlmeinfo->iv = 0;
+
+ pmlmeinfo->enc_algo = _NO_PRIVACY_;
+ pmlmeinfo->authModeToggle = 0;
+
+ memset(pmlmeinfo->chg_txt, 0, 128);
+
+ pmlmeinfo->slotTime = SHORT_SLOT_TIME;
+ pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
+
+ pmlmeinfo->dialogToken = 0;
+
+ pmlmeext->action_public_rxseq = 0xffff;
+ pmlmeext->action_public_dialog_token = 0xff;
+}
+
+static int has_channel(struct rt_channel_info *channel_set,
+ u8 chanset_size,
+ u8 chan)
+{
+ int i;
+
+ for (i = 0; i < chanset_size; i++) {
+ if (channel_set[i].ChannelNum == chan)
+ return 1;
+ }
+ return 0;
+}
+
+static void init_channel_list(struct adapter *padapter,
+ struct rt_channel_info *channel_set,
+ u8 chanset_size,
+ struct p2p_channels *channel_list)
+{
+ struct p2p_oper_class_map op_class[] = {
+ { IEEE80211G, 81, 1, 13, 1, BW20 },
+ { IEEE80211G, 82, 14, 14, 1, BW20 },
+ { -1, 0, 0, 0, 0, BW20 }
+ };
+
+ int cla, op;
+
+ cla = 0;
+
+ for (op = 0; op_class[op].op_class; op++) {
+ u8 ch;
+ struct p2p_oper_class_map *o = &op_class[op];
+ struct p2p_reg_class *reg = NULL;
+
+ for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
+ if (!has_channel(channel_set, chanset_size, ch))
+ continue;
+
+ if (!padapter->registrypriv.ht_enable && o->inc == 8)
+ continue;
+
+ if ((0 == (padapter->registrypriv.cbw40_enable & BIT(1))) &&
+ ((o->bw == BW40MINUS) || (o->bw == BW40PLUS)))
+ continue;
+
+ if (reg == NULL) {
+ reg = &channel_list->reg_class[cla];
+ cla++;
+ reg->reg_class = o->op_class;
+ reg->channels = 0;
+ }
+ reg->channel[reg->channels] = ch;
+ reg->channels++;
+ }
+ }
+ channel_list->reg_classes = cla;
+}
+
+static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan,
+ struct rt_channel_info *channel_set)
+{
+ u8 index, chanset_size = 0;
+ u8 b2_4GBand = false;
+ u8 Index2G = 0;
+
+ memset(channel_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM);
+
+ if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) {
+ DBG_88E("ChannelPlan ID %x error !!!!!\n", ChannelPlan);
+ return chanset_size;
+ }
+
+ if (padapter->registrypriv.wireless_mode & WIRELESS_11G) {
+ b2_4GBand = true;
+ if (ChannelPlan == RT_CHANNEL_DOMAIN_REALTEK_DEFINE)
+ Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
+ else
+ Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G;
+ }
+
+ if (b2_4GBand) {
+ for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) {
+ channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index];
+
+ if ((ChannelPlan == RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN) ||/* Channel 1~11 is active, and 12~14 is passive */
+ (ChannelPlan == RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G)) {
+ if (channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11)
+ channel_set[chanset_size].ScanType = SCAN_ACTIVE;
+ else if ((channel_set[chanset_size].ChannelNum >= 12 && channel_set[chanset_size].ChannelNum <= 14))
+ channel_set[chanset_size].ScanType = SCAN_PASSIVE;
+ } else if (ChannelPlan == RT_CHANNEL_DOMAIN_WORLD_WIDE_13 ||
+ Index2G == RT_CHANNEL_DOMAIN_2G_WORLD) {/* channel 12~13, passive scan */
+ if (channel_set[chanset_size].ChannelNum <= 11)
+ channel_set[chanset_size].ScanType = SCAN_ACTIVE;
+ else
+ channel_set[chanset_size].ScanType = SCAN_PASSIVE;
+ } else {
+ channel_set[chanset_size].ScanType = SCAN_ACTIVE;
+ }
+
+ chanset_size++;
+ }
+ }
+ return chanset_size;
+}
+
+int init_mlme_ext_priv(struct adapter *padapter)
+{
+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ pmlmeext->padapter = padapter;
+
+ init_mlme_ext_priv_value(padapter);
+ pmlmeinfo->accept_addba_req = pregistrypriv->accept_addba_req;
+
+ init_mlme_ext_timer(padapter);
+
+#ifdef CPTCFG_88EU_AP_MODE
+ init_mlme_ap_info(padapter);
+#endif
+
+ pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan, pmlmeext->channel_set);
+ init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
+
+ pmlmeext->chan_scan_time = SURVEY_TO;
+ pmlmeext->mlmeext_init = true;
+
+ pmlmeext->active_keep_alive_check = true;
+
+ return _SUCCESS;
+}
+
+void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext)
+{
+ struct adapter *padapter = pmlmeext->padapter;
+
+ if (!padapter)
+ return;
+
+ if (padapter->bDriverStopped) {
+ del_timer_sync(&pmlmeext->survey_timer);
+ del_timer_sync(&pmlmeext->link_timer);
+ }
+}
+
+static void _mgt_dispatcher(struct adapter *padapter,
+ struct mlme_handler *ptable,
+ struct recv_frame *precv_frame)
+{
+ u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ u8 *pframe = precv_frame->pkt->data;
+
+ if (ptable->func) {
+ /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
+ if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
+ memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
+ return;
+ ptable->func(padapter, precv_frame);
+ }
+}
+
+void mgt_dispatcher(struct adapter *padapter, struct recv_frame *precv_frame)
+{
+ int index;
+ struct mlme_handler *ptable;
+#ifdef CPTCFG_88EU_AP_MODE
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+#endif
+ u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ u8 *pframe = precv_frame->pkt->data;
+ struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe));
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
+ ("+%s: type(0x%x) subtype(0x%x)\n", __func__,
+ (unsigned int)GetFrameType(pframe),
+ (unsigned int)GetFrameSubType(pframe)));
+
+ if (GetFrameType(pframe) != WIFI_MGT_TYPE) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
+ ("%s: type(0x%x) error!\n", __func__,
+ (unsigned int)GetFrameType(pframe)));
+ return;
+ }
+
+ /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
+ if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
+ memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
+ return;
+
+ ptable = mlme_sta_tbl;
+
+ index = GetFrameSubType(pframe) >> 4;
+
+ if (index > 13) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Currently we do not support reserved sub-fr-type=%d\n", index));
+ return;
+ }
+ ptable += index;
+
+ if (psta) {
+ if (GetRetry(pframe)) {
+ if (precv_frame->attrib.seq_num ==
+ psta->RxMgmtFrameSeqNum) {
+ /* drop the duplicate management frame */
+ DBG_88E("Drop duplicate management frame with seq_num=%d.\n",
+ precv_frame->attrib.seq_num);
+ return;
+ }
+ }
+ psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num;
+ }
+
+#ifdef CPTCFG_88EU_AP_MODE
+ switch (GetFrameSubType(pframe)) {
+ case WIFI_AUTH:
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ ptable->func = &OnAuth;
+ else
+ ptable->func = &OnAuthClient;
+ /* fall through */
+ case WIFI_ASSOCREQ:
+ case WIFI_REASSOCREQ:
+ case WIFI_PROBEREQ:
+ case WIFI_BEACON:
+ case WIFI_ACTION:
+ _mgt_dispatcher(padapter, ptable, precv_frame);
+ break;
+ default:
+ _mgt_dispatcher(padapter, ptable, precv_frame);
+ break;
+ }
+#else
+ _mgt_dispatcher(padapter, ptable, precv_frame);
+#endif
+}
+
+/****************************************************************************
+
+Following are the functions to report events
+
+*****************************************************************************/
+
+void report_survey_event(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ struct cmd_obj *pcmd_obj;
+ u8 *pevtcmd;
+ u32 cmdsz;
+ struct survey_event *psurvey_evt;
+ struct C2HEvent_Header *pc2h_evt_hdr;
+ struct mlme_ext_priv *pmlmeext;
+ struct cmd_priv *pcmdpriv;
+
+ if (!padapter)
+ return;
+
+ pmlmeext = &padapter->mlmeextpriv;
+ pcmdpriv = &padapter->cmdpriv;
+
+ pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!pcmd_obj)
+ return;
+
+ cmdsz = sizeof(struct survey_event) + sizeof(struct C2HEvent_Header);
+ pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
+ if (!pevtcmd) {
+ kfree(pcmd_obj);
+ return;
+ }
+
+ INIT_LIST_HEAD(&pcmd_obj->list);
+
+ pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_;
+ pcmd_obj->cmdsz = cmdsz;
+ pcmd_obj->parmbuf = pevtcmd;
+
+ pcmd_obj->rsp = NULL;
+ pcmd_obj->rspsz = 0;
+
+ pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
+ pc2h_evt_hdr->len = sizeof(struct survey_event);
+ pc2h_evt_hdr->ID = _Survey_EVT_;
+ pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
+
+ psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
+
+ if (collect_bss_info(padapter, precv_frame, (struct wlan_bssid_ex *)&psurvey_evt->bss) == _FAIL) {
+ kfree(pcmd_obj);
+ kfree(pevtcmd);
+ return;
+ }
+
+ process_80211d(padapter, &psurvey_evt->bss);
+
+ rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
+
+ pmlmeext->sitesurvey_res.bss_cnt++;
+}
+
+void report_surveydone_event(struct adapter *padapter)
+{
+ struct cmd_obj *pcmd_obj;
+ u8 *pevtcmd;
+ u32 cmdsz;
+ struct surveydone_event *psurveydone_evt;
+ struct C2HEvent_Header *pc2h_evt_hdr;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+ if (!pcmd_obj)
+ return;
+
+ cmdsz = sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header);
+ pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
+ if (!pevtcmd) {
+ kfree(pcmd_obj);
+ return;
+ }
+
+ INIT_LIST_HEAD(&pcmd_obj->list);
+
+ pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_;
+ pcmd_obj->cmdsz = cmdsz;
+ pcmd_obj->parmbuf = pevtcmd;
+
+ pcmd_obj->rsp = NULL;
+ pcmd_obj->rspsz = 0;
+
+ pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
+ pc2h_evt_hdr->len = sizeof(struct surveydone_event);
+ pc2h_evt_hdr->ID = _SurveyDone_EVT_;
+ pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
+
+ psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
+ psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
+
+ DBG_88E("survey done event(%x)\n", psurveydone_evt->bss_cnt);
+
+ rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
+}
+
+void report_join_res(struct adapter *padapter, int res)
+{
+ struct cmd_obj *pcmd_obj;
+ u8 *pevtcmd;
+ u32 cmdsz;
+ struct joinbss_event *pjoinbss_evt;
+ struct C2HEvent_Header *pc2h_evt_hdr;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!pcmd_obj)
+ return;
+
+ cmdsz = sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header);
+ pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
+ if (!pevtcmd) {
+ kfree(pcmd_obj);
+ return;
+ }
+
+ INIT_LIST_HEAD(&pcmd_obj->list);
+
+ pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_;
+ pcmd_obj->cmdsz = cmdsz;
+ pcmd_obj->parmbuf = pevtcmd;
+
+ pcmd_obj->rsp = NULL;
+ pcmd_obj->rspsz = 0;
+
+ pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
+ pc2h_evt_hdr->len = sizeof(struct joinbss_event);
+ pc2h_evt_hdr->ID = _JoinBss_EVT_;
+ pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
+
+ pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
+ memcpy((unsigned char *)(&pjoinbss_evt->network.network), &pmlmeinfo->network, sizeof(struct wlan_bssid_ex));
+ pjoinbss_evt->network.join_res = res;
+ pjoinbss_evt->network.aid = res;
+
+ DBG_88E("%s(%d)\n", __func__, res);
+
+ rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network);
+
+ rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
+}
+
+void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr,
+ unsigned short reason)
+{
+ struct cmd_obj *pcmd_obj;
+ u8 *pevtcmd;
+ u32 cmdsz;
+ struct sta_info *psta;
+ int mac_id;
+ struct stadel_event *pdel_sta_evt;
+ struct C2HEvent_Header *pc2h_evt_hdr;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+ if (!pcmd_obj)
+ return;
+
+ cmdsz = sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header);
+ pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
+ if (!pevtcmd) {
+ kfree(pcmd_obj);
+ return;
+ }
+
+ INIT_LIST_HEAD(&pcmd_obj->list);
+
+ pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_;
+ pcmd_obj->cmdsz = cmdsz;
+ pcmd_obj->parmbuf = pevtcmd;
+
+ pcmd_obj->rsp = NULL;
+ pcmd_obj->rspsz = 0;
+
+ pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
+ pc2h_evt_hdr->len = sizeof(struct stadel_event);
+ pc2h_evt_hdr->ID = _DelSTA_EVT_;
+ pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
+
+ pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
+ ether_addr_copy((unsigned char *)(&pdel_sta_evt->macaddr), MacAddr);
+ memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2);
+
+ psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);
+ if (psta)
+ mac_id = (int)psta->mac_id;
+ else
+ mac_id = -1;
+
+ pdel_sta_evt->mac_id = mac_id;
+
+ DBG_88E("%s: delete STA, mac_id =%d\n", __func__, mac_id);
+
+ rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
+}
+
+void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr,
+ int cam_idx)
+{
+ struct cmd_obj *pcmd_obj;
+ u8 *pevtcmd;
+ u32 cmdsz;
+ struct stassoc_event *padd_sta_evt;
+ struct C2HEvent_Header *pc2h_evt_hdr;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ pcmd_obj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+ if (!pcmd_obj)
+ return;
+
+ cmdsz = sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header);
+ pevtcmd = kzalloc(cmdsz, GFP_KERNEL);
+ if (!pevtcmd) {
+ kfree(pcmd_obj);
+ return;
+ }
+
+ INIT_LIST_HEAD(&pcmd_obj->list);
+
+ pcmd_obj->cmdcode = _Set_MLME_EVT_CMD_;
+ pcmd_obj->cmdsz = cmdsz;
+ pcmd_obj->parmbuf = pevtcmd;
+
+ pcmd_obj->rsp = NULL;
+ pcmd_obj->rspsz = 0;
+
+ pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
+ pc2h_evt_hdr->len = sizeof(struct stassoc_event);
+ pc2h_evt_hdr->ID = _AddSTA_EVT_;
+ pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
+
+ padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
+ ether_addr_copy((unsigned char *)(&padd_sta_evt->macaddr), MacAddr);
+ padd_sta_evt->cam_id = cam_idx;
+
+ DBG_88E("%s: add STA\n", __func__);
+
+ rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
+}
+
+/****************************************************************************
+
+Following are the event callback functions
+
+*****************************************************************************/
+
+/* for sta/adhoc mode */
+void update_sta_info(struct adapter *padapter, struct sta_info *psta)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ /* ERP */
+ VCS_update(padapter, psta);
+
+ /* HT */
+ if (pmlmepriv->htpriv.ht_option) {
+ psta->htpriv.ht_option = true;
+
+ psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
+
+ if (support_short_GI(padapter, &pmlmeinfo->HT_caps))
+ psta->htpriv.sgi = true;
+
+ psta->qos_option = true;
+ } else {
+ psta->htpriv.ht_option = false;
+
+ psta->htpriv.ampdu_enable = false;
+
+ psta->htpriv.sgi = false;
+ psta->qos_option = false;
+ }
+ psta->htpriv.bwmode = pmlmeext->cur_bwmode;
+ psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
+
+ psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
+ psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
+
+ /* QoS */
+ if (pmlmepriv->qospriv.qos_option)
+ psta->qos_option = true;
+
+ psta->state = _FW_LINKED;
+}
+
+void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
+{
+ struct sta_info *psta, *psta_bmc;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ u8 join_type;
+ u16 media_status;
+
+ if (join_res < 0) {
+ join_type = 1;
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
+ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
+
+ /* restore to initial setting. */
+ update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
+
+ goto exit_mlmeext_joinbss_event_callback;
+ }
+
+ if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
+ /* for bc/mc */
+ psta_bmc = rtw_get_bcmc_stainfo(padapter);
+ if (psta_bmc) {
+ pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc;
+ update_bmc_sta_support_rate(padapter, psta_bmc->mac_id);
+ Update_RA_Entry(padapter, psta_bmc->mac_id);
+ }
+ }
+
+ /* turn on dynamic functions */
+ Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
+
+ /* update IOT-related issue */
+ update_IOT_info(padapter);
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);
+
+ /* BCN interval */
+ rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
+
+ /* update capability */
+ update_capinfo(padapter, pmlmeinfo->capability);
+
+ /* WMM, Update EDCA param */
+ WMMOnAssocRsp(padapter);
+
+ /* HT */
+ HTOnAssocRsp(padapter);
+
+ set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+
+ psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
+ if (psta) { /* only for infra. mode */
+ pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
+
+ psta->wireless_mode = pmlmeext->cur_wireless_mode;
+
+ /* set per sta rate after updating HT cap. */
+ set_sta_rate(padapter, psta);
+ rtw_hal_set_hwreg(padapter, HW_VAR_TX_RPT_MAX_MACID, (u8 *)&psta->mac_id);
+ media_status = (psta->mac_id<<8)|1; /* MACID|OPMODE: 1 means connect */
+ rtw_hal_set_hwreg(padapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
+ }
+
+ join_type = 2;
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
+
+ if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) {
+ /* correcting TSF */
+ correct_TSF(padapter, pmlmeext);
+ }
+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
+
+exit_mlmeext_joinbss_event_callback:
+
+ DBG_88E("=>%s\n", __func__);
+}
+
+void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *psta)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u8 join_type;
+
+ DBG_88E("%s\n", __func__);
+
+ if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
+ if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {/* adhoc master or sta_count>1 */
+ /* nothing to do */
+ } else { /* adhoc client */
+ /* correcting TSF */
+ correct_TSF(padapter, pmlmeext);
+
+ /* start beacon */
+ if (send_beacon(padapter) == _FAIL) {
+ pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
+ pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
+ return;
+ }
+ pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
+ }
+
+ join_type = 2;
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
+ }
+
+ pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
+
+ /* rate radaptive */
+ Update_RA_Entry(padapter, psta->mac_id);
+
+ /* update adhoc sta_info */
+ update_sta_info(padapter, psta);
+}
+
+void mlmeext_sta_del_event_callback(struct adapter *padapter)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter)) {
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
+ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
+
+ /* restore to initial setting. */
+ update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
+
+ /* switch to the 20M Hz mode after disconnect */
+ pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+
+ /* SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */
+ set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+
+ flush_all_cam_entry(padapter);
+
+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
+
+ /* set MSR to no link state -> infra. mode */
+ Set_MSR(padapter, _HW_STATE_STATION_);
+
+ del_timer_sync(&pmlmeext->link_timer);
+ }
+}
+
+/****************************************************************************
+
+Following are the functions for the timer handlers
+
+*****************************************************************************/
+
+static u8 chk_ap_is_alive(struct adapter *padapter, struct sta_info *psta)
+{
+ u8 ret = false;
+
+ if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta)) &&
+ sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) &&
+ sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta))
+ ret = false;
+ else
+ ret = true;
+
+ sta_update_last_rx_pkts(psta);
+
+ return ret;
+}
+
+void linked_status_chk(struct adapter *padapter)
+{
+ u32 i;
+ struct sta_info *psta;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ if (is_client_associated_to_ap(padapter)) {
+ /* linked infrastructure client mode */
+
+ int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
+ int rx_chk_limit;
+
+ rx_chk_limit = 4;
+ psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);
+ if (psta) {
+ bool is_p2p_enable = false;
+
+ if (!chk_ap_is_alive(padapter, psta))
+ rx_chk = _FAIL;
+
+ if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
+ tx_chk = _FAIL;
+
+ if (pmlmeext->active_keep_alive_check && (rx_chk == _FAIL || tx_chk == _FAIL)) {
+ u8 backup_oper_channel = 0;
+
+ /* switch to correct channel of current network before issue keep-alive frames */
+ if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
+ backup_oper_channel = rtw_get_oper_ch(padapter);
+ SelectChannel(padapter, pmlmeext->cur_channel);
+ }
+
+ if (rx_chk != _SUCCESS)
+ issue_probereq_ex(padapter, &pmlmeinfo->network.ssid, psta->hwaddr, 3, 1);
+
+ if ((tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) || rx_chk != _SUCCESS) {
+ tx_chk = issue_nulldata(padapter, psta->hwaddr, 0, 3, 1);
+ /* if tx acked and p2p disabled, set rx_chk _SUCCESS to reset retry count */
+ if (tx_chk == _SUCCESS && !is_p2p_enable)
+ rx_chk = _SUCCESS;
+ }
+
+ /* back to the original operation channel */
+ if (backup_oper_channel > 0)
+ SelectChannel(padapter, backup_oper_channel);
+ } else {
+ if (rx_chk != _SUCCESS) {
+ if (pmlmeext->retry == 0) {
+ issue_probereq(padapter,
+ &pmlmeinfo->network.ssid,
+ pmlmeinfo->network.MacAddress,
+ false);
+ issue_probereq(padapter,
+ &pmlmeinfo->network.ssid,
+ pmlmeinfo->network.MacAddress,
+ false);
+ issue_probereq(padapter,
+ &pmlmeinfo->network.ssid,
+ pmlmeinfo->network.MacAddress,
+ false);
+ }
+ }
+
+ if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf)
+ tx_chk = issue_nulldata(padapter, NULL, 0, 1, 0);
+ }
+
+ if (rx_chk == _FAIL) {
+ pmlmeext->retry++;
+ if (pmlmeext->retry > rx_chk_limit) {
+ DBG_88E_LEVEL(_drv_always_, FUNC_ADPT_FMT" disconnect or roaming\n",
+ FUNC_ADPT_ARG(padapter));
+ receive_disconnect(padapter, pmlmeinfo->network.MacAddress,
+ WLAN_REASON_EXPIRATION_CHK);
+ return;
+ }
+ } else {
+ pmlmeext->retry = 0;
+ }
+
+ if (tx_chk == _FAIL) {
+ pmlmeinfo->link_count &= 0xf;
+ } else {
+ pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
+ pmlmeinfo->link_count = 0;
+ }
+ } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL) */
+ } else if (is_client_associated_to_ibss(padapter)) {
+ /* linked IBSS mode */
+ /* for each assoc list entry to check the rx pkt counter */
+ for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
+ if (pmlmeinfo->FW_sta_info[i].status == 1) {
+ psta = pmlmeinfo->FW_sta_info[i].psta;
+
+ if (!psta)
+ continue;
+ if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta)) {
+ if (pmlmeinfo->FW_sta_info[i].retry < 3) {
+ pmlmeinfo->FW_sta_info[i].retry++;
+ } else {
+ pmlmeinfo->FW_sta_info[i].retry = 0;
+ pmlmeinfo->FW_sta_info[i].status = 0;
+ report_del_sta_event(padapter, psta->hwaddr
+ , 65535/* indicate disconnect caused by no rx */
+ );
+ }
+ } else {
+ pmlmeinfo->FW_sta_info[i].retry = 0;
+ pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
+ }
+ }
+ }
+ }
+}
+
+void survey_timer_hdl(struct timer_list *t)
+{
+ struct adapter *padapter = from_timer(padapter, t,
+ mlmeextpriv.survey_timer);
+ struct cmd_obj *ph2c;
+ struct sitesurvey_parm *psurveyPara;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ /* issue rtw_sitesurvey_cmd */
+ if (pmlmeext->sitesurvey_res.state > SCAN_START) {
+ if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS)
+ pmlmeext->sitesurvey_res.channel_idx++;
+
+ if (pmlmeext->scan_abort) {
+ pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
+ DBG_88E("%s idx:%d\n", __func__
+ , pmlmeext->sitesurvey_res.channel_idx);
+
+ pmlmeext->scan_abort = false;/* reset */
+ }
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c)
+ goto exit_survey_timer_hdl;
+
+ psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC);
+ if (!psurveyPara) {
+ kfree(ph2c);
+ goto exit_survey_timer_hdl;
+ }
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, _SiteSurvey_CMD_);
+ rtw_enqueue_cmd(pcmdpriv, ph2c);
+ }
+
+exit_survey_timer_hdl:
+ return;
+}
+
+void link_timer_hdl(struct timer_list *t)
+{
+ struct adapter *padapter = from_timer(padapter, t,
+ mlmeextpriv.link_timer);
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
+ DBG_88E("%s:no beacon while connecting\n", __func__);
+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
+ report_join_res(padapter, -3);
+ } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
+ /* re-auth timer */
+ if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
+ pmlmeinfo->state = 0;
+ report_join_res(padapter, -1);
+ return;
+ }
+
+ DBG_88E("%s: auth timeout and try again\n", __func__);
+ pmlmeinfo->auth_seq = 1;
+ issue_auth(padapter, NULL, 0);
+ set_link_timer(pmlmeext, REAUTH_TO);
+ } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
+ /* re-assoc timer */
+ if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
+ report_join_res(padapter, -2);
+ return;
+ }
+
+ DBG_88E("%s: assoc timeout and try again\n", __func__);
+ issue_assocreq(padapter);
+ set_link_timer(pmlmeext, REASSOC_TO);
+ }
+}
+
+void addba_timer_hdl(struct timer_list *t)
+{
+ struct sta_info *psta = from_timer(psta, t, addba_retry_timer);
+ struct ht_priv *phtpriv;
+
+ if (!psta)
+ return;
+
+ phtpriv = &psta->htpriv;
+
+ if ((phtpriv->ht_option) && (phtpriv->ampdu_enable)) {
+ if (phtpriv->candidate_tid_bitmap)
+ phtpriv->candidate_tid_bitmap = 0x0;
+ }
+}
+
+u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf)
+{
+ u8 type;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
+
+ if (psetop->mode == Ndis802_11APMode) {
+ pmlmeinfo->state = WIFI_FW_AP_STATE;
+ type = _HW_STATE_AP_;
+ } else if (psetop->mode == Ndis802_11Infrastructure) {
+ pmlmeinfo->state &= ~(BIT(0)|BIT(1));/* clear state */
+ pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to STATION_STATE */
+ type = _HW_STATE_STATION_;
+ } else if (psetop->mode == Ndis802_11IBSS) {
+ type = _HW_STATE_ADHOC_;
+ } else {
+ type = _HW_STATE_NOLINK_;
+ }
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type));
+ /* Set_MSR(padapter, type); */
+
+ return H2C_SUCCESS;
+}
+
+u8 createbss_hdl(struct adapter *padapter, u8 *pbuf)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network);
+ struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
+
+ if (pparm->InfrastructureMode == Ndis802_11APMode) {
+#ifdef CPTCFG_88EU_AP_MODE
+
+ if (pmlmeinfo->state == WIFI_FW_AP_STATE) {
+ /* todo: */
+ return H2C_SUCCESS;
+ }
+#endif
+ }
+
+ /* below is for ad-hoc master */
+ if (pparm->InfrastructureMode == Ndis802_11IBSS) {
+ rtw_joinbss_reset(padapter);
+
+ pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ pmlmeinfo->ERP_enable = 0;
+ pmlmeinfo->WMM_enable = 0;
+ pmlmeinfo->HT_enable = 0;
+ pmlmeinfo->HT_caps_enable = 0;
+ pmlmeinfo->HT_info_enable = 0;
+ pmlmeinfo->agg_enable_bitmap = 0;
+ pmlmeinfo->candidate_tid_bitmap = 0;
+
+ /* disable dynamic functions, such as high power, DIG */
+ Save_DM_Func_Flag(padapter);
+ Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
+
+ /* config the initial gain under linking, need to write the BB registers */
+ /* initialgain = 0x1E; */
+ /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
+
+ /* cancel link timer */
+ del_timer_sync(&pmlmeext->link_timer);
+
+ /* clear CAM */
+ flush_all_cam_entry(padapter);
+
+ memcpy(pnetwork, pbuf, offsetof(struct wlan_bssid_ex, ie_length));
+ pnetwork->ie_length = ((struct wlan_bssid_ex *)pbuf)->ie_length;
+
+ if (pnetwork->ie_length > MAX_IE_SZ)/* Check pbuf->ie_length */
+ return H2C_PARAMETERS_ERROR;
+
+ memcpy(pnetwork->ies, ((struct wlan_bssid_ex *)pbuf)->ies, pnetwork->ie_length);
+
+ start_create_ibss(padapter);
+ }
+
+ return H2C_SUCCESS;
+}
+
+u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf)
+{
+ u8 join_type;
+ struct ndis_802_11_var_ie *pIE;
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network);
+ struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
+ u32 i;
+
+ /* check already connecting to AP or not */
+ if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
+ if (pmlmeinfo->state & WIFI_FW_STATION_STATE)
+ issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 5, 100);
+
+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
+
+ /* clear CAM */
+ flush_all_cam_entry(padapter);
+
+ del_timer_sync(&pmlmeext->link_timer);
+
+ /* set MSR to nolink -> infra. mode */
+ Set_MSR(padapter, _HW_STATE_STATION_);
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
+ }
+
+ rtw_antenna_select_cmd(padapter, pparm->PhyInfo.Optimum_antenna, false);
+
+ rtw_joinbss_reset(padapter);
+
+ pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ pmlmeinfo->ERP_enable = 0;
+ pmlmeinfo->WMM_enable = 0;
+ pmlmeinfo->HT_enable = 0;
+ pmlmeinfo->HT_caps_enable = 0;
+ pmlmeinfo->HT_info_enable = 0;
+ pmlmeinfo->agg_enable_bitmap = 0;
+ pmlmeinfo->candidate_tid_bitmap = 0;
+ pmlmeinfo->bwmode_updated = false;
+
+ memcpy(pnetwork, pbuf, offsetof(struct wlan_bssid_ex, ie_length));
+ pnetwork->ie_length = ((struct wlan_bssid_ex *)pbuf)->ie_length;
+
+ if (pnetwork->ie_length > MAX_IE_SZ)/* Check pbuf->ie_length */
+ return H2C_PARAMETERS_ERROR;
+
+ memcpy(pnetwork->ies, ((struct wlan_bssid_ex *)pbuf)->ies, pnetwork->ie_length);
+
+ /* Check AP vendor to move rtw_joinbss_cmd() */
+
+ for (i = sizeof(struct ndis_802_11_fixed_ie); i < pnetwork->ie_length;) {
+ pIE = (struct ndis_802_11_var_ie *)(pnetwork->ies + i);
+
+ switch (pIE->ElementID) {
+ case _VENDOR_SPECIFIC_IE_:/* Get WMM IE. */
+ if (!memcmp(pIE->data, WMM_OUI, 4))
+ pmlmeinfo->WMM_enable = 1;
+ break;
+ case _HT_CAPABILITY_IE_: /* Get HT Cap IE. */
+ pmlmeinfo->HT_caps_enable = 1;
+ break;
+ case _HT_EXTRA_INFO_IE_: /* Get HT Info IE. */
+ pmlmeinfo->HT_info_enable = 1;
+
+ /* spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz */
+ {
+ struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data);
+
+ if ((pregpriv->cbw40_enable) && (pht_info->infos[0] & BIT(2))) {
+ /* switch to the 40M Hz mode according to the AP */
+ pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
+ switch (pht_info->infos[0] & 0x3) {
+ case 1:
+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
+ break;
+ case 3:
+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
+ break;
+ default:
+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ break;
+ }
+
+ DBG_88E("set ch/bw before connected\n");
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ i += (pIE->Length + 2);
+ }
+ /* disable dynamic functions, such as high power, DIG */
+
+ /* config the initial gain under linking, need to write the BB registers */
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
+ join_type = 0;
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
+
+ /* cancel link timer */
+ del_timer_sync(&pmlmeext->link_timer);
+
+ start_clnt_join(padapter);
+
+ return H2C_SUCCESS;
+}
+
+u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf)
+{
+ struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&pmlmeinfo->network);
+ u8 val8;
+
+ if (is_client_associated_to_ap(padapter))
+ issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100);
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
+ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
+
+ /* restore to initial setting. */
+ update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
+
+ if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
+ /* Stop BCN */
+ val8 = 0;
+ rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8));
+ }
+
+ /* set MSR to no link state -> infra. mode */
+ Set_MSR(padapter, _HW_STATE_STATION_);
+
+ pmlmeinfo->state = WIFI_FW_NULL_STATE;
+
+ /* switch to the 20M Hz mode after disconnect */
+ pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
+ pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+
+ set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+
+ flush_all_cam_entry(padapter);
+
+ del_timer_sync(&pmlmeext->link_timer);
+
+ rtw_free_uc_swdec_pending_queue(padapter);
+
+ return H2C_SUCCESS;
+}
+
+static int rtw_scan_ch_decision(struct adapter *padapter,
+ struct rtw_ieee80211_channel *out,
+ u32 out_num,
+ struct rtw_ieee80211_channel *in, u32 in_num)
+{
+ int i, j;
+ int set_idx;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ /* clear out first */
+ memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
+
+ /* acquire channels from in */
+ j = 0;
+ for (i = 0; i < in_num; i++) {
+ set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value);
+ if (in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED) &&
+ set_idx >= 0) {
+ out[j] = in[i];
+
+ if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE)
+ out[j].flags &= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
+
+ j++;
+ }
+ if (j >= out_num)
+ break;
+ }
+
+ /* if out is empty, use channel_set as default */
+ if (j == 0) {
+ for (i = 0; i < pmlmeext->max_chan_nums; i++) {
+ out[i].hw_value = pmlmeext->channel_set[i].ChannelNum;
+
+ if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
+ out[i].flags &= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
+
+ j++;
+ }
+ }
+
+ return j;
+}
+
+u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf;
+ u8 bdelayscan = false;
+ u8 val8;
+ u32 initialgain;
+ u32 i;
+
+ if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
+ /* for first time sitesurvey_cmd */
+ rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, NULL);
+
+ pmlmeext->sitesurvey_res.state = SCAN_START;
+ pmlmeext->sitesurvey_res.bss_cnt = 0;
+ pmlmeext->sitesurvey_res.channel_idx = 0;
+
+ for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
+ if (pparm->ssid[i].ssid_length) {
+ memcpy(pmlmeext->sitesurvey_res.ssid[i].ssid, pparm->ssid[i].ssid, IW_ESSID_MAX_SIZE);
+ pmlmeext->sitesurvey_res.ssid[i].ssid_length = pparm->ssid[i].ssid_length;
+ } else {
+ pmlmeext->sitesurvey_res.ssid[i].ssid_length = 0;
+ }
+ }
+
+ pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter
+ , pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT
+ , pparm->ch, pparm->ch_num
+ );
+
+ pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
+
+ /* issue null data if associating to the AP */
+ if (is_client_associated_to_ap(padapter)) {
+ pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
+
+ issue_nulldata(padapter, NULL, 1, 3, 500);
+
+ bdelayscan = true;
+ }
+ if (bdelayscan) {
+ /* delay 50ms to protect nulldata(1). */
+ set_survey_timer(pmlmeext, 50);
+ return H2C_SUCCESS;
+ }
+ }
+
+ if ((pmlmeext->sitesurvey_res.state == SCAN_START) || (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) {
+ /* disable dynamic functions, such as high power, DIG */
+ Save_DM_Func_Flag(padapter);
+ Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
+
+ /* config the initial gain under scanning, need to write the BB registers */
+ initialgain = 0x1E;
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
+
+ /* set MSR to no link state */
+ Set_MSR(padapter, _HW_STATE_NOLINK_);
+
+ val8 = 1; /* under site survey */
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
+
+ pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
+ }
+
+ site_survey(padapter);
+
+ return H2C_SUCCESS;
+}
+
+u8 setauth_hdl(struct adapter *padapter, unsigned char *pbuf)
+{
+ struct setauth_parm *pparm = (struct setauth_parm *)pbuf;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ if (pparm->mode < 4)
+ pmlmeinfo->auth_algo = pparm->mode;
+ return H2C_SUCCESS;
+}
+
+u8 setkey_hdl(struct adapter *padapter, u8 *pbuf)
+{
+ unsigned short ctrl;
+ struct setkey_parm *pparm = (struct setkey_parm *)pbuf;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u8 null_sta[ETH_ALEN] = {};
+
+ /* main tx key for wep. */
+ if (pparm->set_tx)
+ pmlmeinfo->key_index = pparm->keyid;
+
+ /* write cam */
+ ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
+
+ DBG_88E_LEVEL(_drv_info_, "set group key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) "
+ "keyid:%d\n", pparm->algorithm, pparm->keyid);
+ write_cam(padapter, pparm->keyid, ctrl, null_sta, pparm->key);
+
+ return H2C_SUCCESS;
+}
+
+u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf)
+{
+ u16 ctrl = 0;
+ u8 cam_id;/* cam_entry */
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf;
+
+ /* cam_entry: */
+ /* 0~3 for default key */
+
+ /* for concurrent mode (ap+sta): */
+ /* default key is disable, using sw encrypt/decrypt */
+ /* cam_entry = 4 for sta mode (macid = 0) */
+ /* cam_entry(macid+3) = 5 ~ N for ap mode (aid = 1~N, macid = 2 ~N) */
+
+ /* for concurrent mode (sta+sta): */
+ /* default key is disable, using sw encrypt/decrypt */
+ /* cam_entry = 4 mapping to macid = 0 */
+ /* cam_entry = 5 mapping to macid = 2 */
+
+ cam_id = 4;
+
+ DBG_88E_LEVEL(_drv_info_, "set pairwise key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) camid:%d\n",
+ pparm->algorithm, cam_id);
+ if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
+ struct sta_info *psta;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ if (pparm->algorithm == _NO_PRIVACY_) /* clear cam entry */ {
+ clear_cam_entry(padapter, pparm->id);
+ return H2C_SUCCESS_RSP;
+ }
+
+ psta = rtw_get_stainfo(pstapriv, pparm->addr);
+ if (psta) {
+ ctrl = BIT(15) | ((pparm->algorithm) << 2);
+
+ DBG_88E("r871x_set_stakey_hdl(): enc_algorithm=%d\n", pparm->algorithm);
+
+ if ((psta->mac_id < 1) || (psta->mac_id > (NUM_STA-4))) {
+ DBG_88E("r871x_set_stakey_hdl():set_stakey failed, mac_id(aid)=%d\n", psta->mac_id);
+ return H2C_REJECTED;
+ }
+
+ cam_id = psta->mac_id + 3;/* 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */
+
+ DBG_88E("Write CAM, mac_addr =%pM, cam_entry=%d\n",
+ pparm->addr, cam_id);
+
+ write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
+
+ return H2C_SUCCESS_RSP;
+ } else {
+ DBG_88E("r871x_set_stakey_hdl(): sta has been free\n");
+ return H2C_REJECTED;
+ }
+ }
+
+ /* below for sta mode */
+
+ if (pparm->algorithm == _NO_PRIVACY_) { /* clear cam entry */
+ clear_cam_entry(padapter, pparm->id);
+ return H2C_SUCCESS;
+ }
+ ctrl = BIT(15) | ((pparm->algorithm) << 2);
+ write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
+ pmlmeinfo->enc_algo = pparm->algorithm;
+ return H2C_SUCCESS;
+}
+
+u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf)
+{
+ struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr);
+
+ if (!psta)
+ return H2C_SUCCESS;
+
+ if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) ||
+ ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
+ issue_action_BA(padapter, pparm->addr, RTW_WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
+ mod_timer(&psta->addba_retry_timer,
+ jiffies + msecs_to_jiffies(ADDBA_TO));
+ } else {
+ psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
+ }
+ return H2C_SUCCESS;
+}
+
+u8 set_tx_beacon_cmd(struct adapter *padapter)
+{
+ struct cmd_obj *ph2c;
+ struct wlan_bssid_ex *ptxBeacon_parm;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u8 res;
+ int len_diff = 0;
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ ptxBeacon_parm = kmemdup(&pmlmeinfo->network,
+ sizeof(struct wlan_bssid_ex), GFP_ATOMIC);
+ if (ptxBeacon_parm == NULL) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ len_diff = update_hidden_ssid(ptxBeacon_parm->ies+_BEACON_IE_OFFSET_,
+ ptxBeacon_parm->ie_length-_BEACON_IE_OFFSET_,
+ pmlmeinfo->hidden_ssid_mode);
+ ptxBeacon_parm->ie_length += len_diff;
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, _TX_Beacon_CMD_);
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+
+exit:
+ return res;
+}
+
+u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf)
+{
+ u8 evt_code;
+ u16 evt_sz;
+ uint *peventbuf;
+ void (*event_callback)(struct adapter *dev, u8 *pbuf);
+
+ peventbuf = (uint *)pbuf;
+ evt_sz = (u16)(*peventbuf & 0xffff);
+ evt_code = (u8)((*peventbuf>>16) & 0xff);
+
+ /* checking if event code is valid */
+ if (evt_code >= MAX_C2HEVT) {
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nEvent Code(%d) mismatch!\n", evt_code));
+ goto _abort_event_;
+ }
+
+ /* checking if event size match the event parm size */
+ if ((wlanevents[evt_code].parmsize != 0) &&
+ (wlanevents[evt_code].parmsize != evt_sz)) {
+ RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
+ ("\nEvent(%d) Parm Size mismatch (%d vs %d)!\n",
+ evt_code, wlanevents[evt_code].parmsize, evt_sz));
+ goto _abort_event_;
+ }
+
+ peventbuf += 2;
+
+ if (peventbuf) {
+ event_callback = wlanevents[evt_code].event_callback;
+ event_callback(padapter, (u8 *)peventbuf);
+ }
+
+_abort_event_:
+ return H2C_SUCCESS;
+}
+
+u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf)
+{
+ if (send_beacon(padapter) == _FAIL) {
+ DBG_88E("issue_beacon, fail!\n");
+ return H2C_PARAMETERS_ERROR;
+ }
+#ifdef CPTCFG_88EU_AP_MODE
+ else { /* tx bc/mc frames after update TIM */
+ struct sta_info *psta_bmc;
+ struct list_head *xmitframe_plist, *xmitframe_phead;
+ struct xmit_frame *pxmitframe = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ /* for BC/MC Frames */
+ psta_bmc = rtw_get_bcmc_stainfo(padapter);
+ if (!psta_bmc)
+ return H2C_SUCCESS;
+
+ if ((pstapriv->tim_bitmap & BIT(0)) && (psta_bmc->sleepq_len > 0)) {
+ msleep(10);/* 10ms, ATIM(HIQ) Windows */
+ spin_lock_bh(&psta_bmc->sleep_q.lock);
+
+ xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
+ xmitframe_plist = xmitframe_phead->next;
+
+ while (xmitframe_phead != xmitframe_plist) {
+ pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
+
+ xmitframe_plist = xmitframe_plist->next;
+
+ list_del_init(&pxmitframe->list);
+
+ psta_bmc->sleepq_len--;
+ if (psta_bmc->sleepq_len > 0)
+ pxmitframe->attrib.mdata = 1;
+ else
+ pxmitframe->attrib.mdata = 0;
+
+ pxmitframe->attrib.triggered = 1;
+
+ pxmitframe->attrib.qsel = 0x11;/* HIQ */
+
+ spin_unlock_bh(&psta_bmc->sleep_q.lock);
+ if (rtw_hal_xmit(padapter, pxmitframe))
+ rtw_os_xmit_complete(padapter, pxmitframe);
+ spin_lock_bh(&psta_bmc->sleep_q.lock);
+ }
+ spin_unlock_bh(&psta_bmc->sleep_q.lock);
+ }
+ }
+#endif
+ return H2C_SUCCESS;
+}
+
+u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf)
+{
+ struct set_ch_parm *set_ch_parm;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ if (!pbuf)
+ return H2C_PARAMETERS_ERROR;
+
+ set_ch_parm = (struct set_ch_parm *)pbuf;
+
+ DBG_88E(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
+ FUNC_NDEV_ARG(padapter->pnetdev),
+ set_ch_parm->ch, set_ch_parm->bw, set_ch_parm->ch_offset);
+
+ pmlmeext->cur_channel = set_ch_parm->ch;
+ pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
+ pmlmeext->cur_bwmode = set_ch_parm->bw;
+
+ set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
+
+ return H2C_SUCCESS;
+}
+
+u8 set_chplan_hdl(struct adapter *padapter, unsigned char *pbuf)
+{
+ struct SetChannelPlan_param *setChannelPlan_param;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ if (!pbuf)
+ return H2C_PARAMETERS_ERROR;
+
+ setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
+
+ pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set);
+ init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
+
+ return H2C_SUCCESS;
+}
diff --git a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
new file mode 100644
index 0000000..7b16632
--- /dev/null
+++ b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
@@ -0,0 +1,650 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _RTW_PWRCTRL_C_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <osdep_intf.h>
+#include <usb_ops_linux.h>
+#include <linux/usb.h>
+
+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("==> %s\n", __func__);
+ mutex_lock(&pwrpriv->mutex_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);
+
+ led_control_8188eu(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;
+
+ mutex_unlock(&pwrpriv->mutex_lock);
+
+ return 0;
+
+error_exit:
+ DBG_88E("%s, failed\n", __func__);
+ return -1;
+}
+
+static int rtw_hw_resume(struct adapter *padapter)
+{
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct net_device *pnetdev = padapter->pnetdev;
+
+ /* system resume */
+ DBG_88E("==> %s\n", __func__);
+ mutex_lock(&pwrpriv->mutex_lock);
+ pwrpriv->bips_processing = true;
+ rtw_reset_drv_sw(padapter);
+
+ if (ips_netdrv_open((struct adapter *)rtw_netdev_priv(pnetdev)) != _SUCCESS) {
+ mutex_unlock(&pwrpriv->mutex_lock);
+ goto error_exit;
+ }
+
+ netif_device_attach(pnetdev);
+ netif_carrier_on(pnetdev);
+
+ if (!netif_queue_stopped(pnetdev))
+ netif_start_queue(pnetdev);
+ else
+ netif_wake_queue(pnetdev);
+
+ pwrpriv->bkeepfwalive = false;
+ pwrpriv->brfoffbyhw = false;
+
+ pwrpriv->rf_pwrstate = rf_on;
+ pwrpriv->bips_processing = false;
+
+ mutex_unlock(&pwrpriv->mutex_lock);
+
+ return 0;
+error_exit:
+ DBG_88E("%s, Open net dev failed\n", __func__);
+ return -1;
+}
+
+void ips_enter(struct adapter *padapter)
+{
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct xmit_priv *pxmit_priv = &padapter->xmitpriv;
+
+ if (padapter->registrypriv.mp_mode == 1)
+ return;
+
+ if (pxmit_priv->free_xmitbuf_cnt != NR_XMITBUFF ||
+ pxmit_priv->free_xmit_extbuf_cnt != NR_XMIT_EXTBUFF) {
+ DBG_88E_LEVEL(_drv_info_, "There are some pkts to transmit\n");
+ DBG_88E_LEVEL(_drv_info_, "free_xmitbuf_cnt: %d, free_xmit_extbuf_cnt: %d\n",
+ pxmit_priv->free_xmitbuf_cnt, pxmit_priv->free_xmit_extbuf_cnt);
+ return;
+ }
+
+ mutex_lock(&pwrpriv->mutex_lock);
+
+ pwrpriv->bips_processing = true;
+
+ /* syn ips_mode with request */
+ pwrpriv->ips_mode = pwrpriv->ips_mode_req;
+
+ pwrpriv->ips_enter_cnts++;
+ DBG_88E("==>%s:%d\n", __func__, pwrpriv->ips_enter_cnts);
+ if (rf_off == pwrpriv->change_rfpwrstate) {
+ pwrpriv->bpower_saving = true;
+ DBG_88E_LEVEL(_drv_info_, "nolinked power save enter\n");
+
+ if (pwrpriv->ips_mode == IPS_LEVEL_2)
+ pwrpriv->bkeepfwalive = true;
+
+ rtw_ips_pwr_down(padapter);
+ pwrpriv->rf_pwrstate = rf_off;
+ }
+ pwrpriv->bips_processing = false;
+
+ mutex_unlock(&pwrpriv->mutex_lock);
+}
+
+int ips_leave(struct adapter *padapter)
+{
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct security_priv *psecuritypriv = &(padapter->securitypriv);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ int result = _SUCCESS;
+ int keyid;
+
+ mutex_lock(&pwrpriv->mutex_lock);
+
+ if ((pwrpriv->rf_pwrstate == rf_off) && (!pwrpriv->bips_processing)) {
+ pwrpriv->bips_processing = true;
+ pwrpriv->change_rfpwrstate = rf_on;
+ pwrpriv->ips_leave_cnts++;
+ DBG_88E("==>%s:%d\n", __func__, pwrpriv->ips_leave_cnts);
+
+ result = rtw_ips_pwr_up(padapter);
+ if (result == _SUCCESS)
+ pwrpriv->rf_pwrstate = rf_on;
+
+ DBG_88E_LEVEL(_drv_info_, "nolinked power save leave\n");
+
+ if ((_WEP40_ == psecuritypriv->dot11PrivacyAlgrthm) || (_WEP104_ == psecuritypriv->dot11PrivacyAlgrthm)) {
+ DBG_88E("==>%s, channel(%d), processing(%x)\n", __func__, padapter->mlmeextpriv.cur_channel, pwrpriv->bips_processing);
+ set_channel_bwmode(padapter, padapter->mlmeextpriv.cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
+ for (keyid = 0; keyid < 4; keyid++) {
+ if (pmlmepriv->key_mask & BIT(keyid)) {
+ if (keyid == psecuritypriv->dot11PrivacyKeyIndex)
+ result = rtw_set_key(padapter, psecuritypriv, keyid, 1);
+ else
+ result = rtw_set_key(padapter, psecuritypriv, keyid, 0);
+ }
+ }
+ }
+
+ DBG_88E("==> %s.....LED(0x%08x)...\n", __func__, usb_read32(padapter, 0x4c));
+ pwrpriv->bips_processing = false;
+
+ pwrpriv->bkeepfwalive = false;
+ pwrpriv->bpower_saving = false;
+ }
+
+ mutex_unlock(&pwrpriv->mutex_lock);
+
+ return result;
+}
+
+static bool rtw_pwr_unassociated_idle(struct adapter *adapter)
+{
+ struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
+ bool ret = false;
+
+ if (time_after_eq(adapter->pwrctrlpriv.ips_deny_time, jiffies))
+ goto exit;
+
+ if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR) ||
+ check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS) ||
+ check_fwstate(pmlmepriv, WIFI_AP_STATE) ||
+ check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE))
+ goto exit;
+
+ ret = true;
+
+exit:
+ return ret;
+}
+
+void rtw_ps_processor(struct adapter *padapter)
+{
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ enum rt_rf_power_state rfpwrstate;
+
+ pwrpriv->ps_processing = true;
+
+ if (pwrpriv->bips_processing)
+ goto exit;
+
+ if (padapter->pwrctrlpriv.bHWPwrPindetect) {
+ rfpwrstate = RfOnOffDetect(padapter);
+ DBG_88E("@@@@- #2 %s==> rfstate:%s\n", __func__, (rfpwrstate == rf_on) ? "rf_on" : "rf_off");
+
+ if (rfpwrstate != pwrpriv->rf_pwrstate) {
+ if (rfpwrstate == rf_off) {
+ pwrpriv->change_rfpwrstate = rf_off;
+ pwrpriv->brfoffbyhw = true;
+ rtw_hw_suspend(padapter);
+ } else {
+ pwrpriv->change_rfpwrstate = rf_on;
+ rtw_hw_resume(padapter);
+ }
+ DBG_88E("current rf_pwrstate(%s)\n", (pwrpriv->rf_pwrstate == rf_off) ? "rf_off" : "rf_on");
+ }
+ pwrpriv->pwr_state_check_cnts++;
+ }
+
+ if (pwrpriv->ips_mode_req == IPS_NONE)
+ goto exit;
+
+ if (!rtw_pwr_unassociated_idle(padapter))
+ goto exit;
+
+ if ((pwrpriv->rf_pwrstate == rf_on) && ((pwrpriv->pwr_state_check_cnts%4) == 0)) {
+ DBG_88E("==>%s .fw_state(%x)\n", __func__, get_fwstate(pmlmepriv));
+ pwrpriv->change_rfpwrstate = rf_off;
+
+ ips_enter(padapter);
+ }
+exit:
+ rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);
+ pwrpriv->ps_processing = false;
+}
+
+static void pwr_state_check_handler(struct timer_list *t)
+{
+ struct adapter *padapter =
+ from_timer(padapter, t,
+ pwrctrlpriv.pwr_state_check_timer);
+
+ rtw_ps_cmd(padapter);
+}
+
+/*
+ *
+ * Parameters
+ * padapter
+ * pslv power state level, only could be PS_STATE_S0 ~ PS_STATE_S4
+ *
+ */
+void rtw_set_rpwm(struct adapter *padapter, u8 pslv)
+{
+ u8 rpwm;
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+
+ pslv = PS_STATE(pslv);
+
+ if (pwrpriv->btcoex_rfon) {
+ if (pslv < PS_STATE_S4)
+ pslv = PS_STATE_S3;
+ }
+
+ if (pwrpriv->rpwm == pslv) {
+ RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
+ ("%s: Already set rpwm[0x%02X], new=0x%02X!\n", __func__, pwrpriv->rpwm, pslv));
+ return;
+ }
+
+ if ((padapter->bSurpriseRemoved) ||
+ (!padapter->hw_init_completed)) {
+ RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
+ ("%s: SurpriseRemoved(%d) hw_init_completed(%d)\n",
+ __func__, padapter->bSurpriseRemoved, padapter->hw_init_completed));
+
+ pwrpriv->cpwm = PS_STATE_S4;
+
+ return;
+ }
+
+ if (padapter->bDriverStopped) {
+ RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
+ ("%s: change power state(0x%02X) when DriverStopped\n", __func__, pslv));
+
+ if (pslv < PS_STATE_S2) {
+ RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
+ ("%s: Reject to enter PS_STATE(0x%02X) lower than S2 when DriverStopped!!\n", __func__, pslv));
+ return;
+ }
+ }
+
+ rpwm = pslv | pwrpriv->tog;
+ RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
+ ("%s: rpwm=0x%02x cpwm=0x%02x\n", __func__, rpwm, pwrpriv->cpwm));
+
+ pwrpriv->rpwm = pslv;
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&rpwm));
+
+ pwrpriv->tog += 0x80;
+ pwrpriv->cpwm = pslv;
+}
+
+static u8 PS_RDY_CHECK(struct adapter *padapter)
+{
+ unsigned long curr_time, delta_time;
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+ curr_time = jiffies;
+ delta_time = curr_time - pwrpriv->DelayLPSLastTimeStamp;
+
+ if (delta_time < LPS_DELAY_TIME)
+ return false;
+
+ if ((!check_fwstate(pmlmepriv, _FW_LINKED)) ||
+ (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) ||
+ (check_fwstate(pmlmepriv, WIFI_AP_STATE)) ||
+ (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
+ (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)))
+ return false;
+ if (pwrpriv->bInSuspend)
+ return false;
+ if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X &&
+ !padapter->securitypriv.binstallGrpkey) {
+ DBG_88E("Group handshake still in progress !!!\n");
+ return false;
+ }
+ return true;
+}
+
+void rtw_set_ps_mode(struct adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode)
+{
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+
+ RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
+ ("%s: PowerMode=%d Smart_PS=%d\n",
+ __func__, ps_mode, smart_ps));
+
+ if (ps_mode > PM_Card_Disable) {
+ RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("ps_mode:%d error\n", ps_mode));
+ return;
+ }
+
+ if (pwrpriv->pwr_mode == ps_mode) {
+ if (ps_mode == PS_MODE_ACTIVE)
+ return;
+
+ if ((pwrpriv->smart_ps == smart_ps) &&
+ (pwrpriv->bcn_ant_mode == bcn_ant_mode))
+ return;
+ }
+
+ /* if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) */
+ if (ps_mode == PS_MODE_ACTIVE) {
+ if (PS_RDY_CHECK(padapter)) {
+ DBG_88E("%s: Enter 802.11 power save\n", __func__);
+ pwrpriv->bFwCurrentInPSMode = true;
+ pwrpriv->pwr_mode = ps_mode;
+ pwrpriv->smart_ps = smart_ps;
+ pwrpriv->bcn_ant_mode = bcn_ant_mode;
+ rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
+ rtw_set_rpwm(padapter, PS_STATE_S2);
+ }
+ }
+}
+
+/*
+ * Return:
+ * 0: Leave OK
+ * -1: Timeout
+ * -2: Other error
+ */
+s32 LPS_RF_ON_check(struct adapter *padapter, u32 delay_ms)
+{
+ unsigned long start_time;
+ u8 bAwake = false;
+ s32 err = 0;
+
+ start_time = jiffies;
+ while (1) {
+ rtw_hal_get_hwreg(padapter, HW_VAR_FWLPS_RF_ON, &bAwake);
+ if (bAwake)
+ break;
+
+ if (padapter->bSurpriseRemoved) {
+ err = -2;
+ DBG_88E("%s: device surprise removed!!\n", __func__);
+ break;
+ }
+
+ if (jiffies_to_msecs(jiffies - start_time) > delay_ms) {
+ err = -1;
+ DBG_88E("%s: Wait for FW LPS leave more than %u ms!!!\n", __func__, delay_ms);
+ break;
+ }
+ msleep(1);
+ }
+
+ return err;
+}
+
+/* */
+/* Description: */
+/* Enter the leisure power save mode. */
+/* */
+void LPS_Enter(struct adapter *padapter)
+{
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+
+ if (!PS_RDY_CHECK(padapter))
+ return;
+
+ if (pwrpriv->bLeisurePs) {
+ /* Idle for a while if we connect to AP a while ago. */
+ if (pwrpriv->LpsIdleCount >= 2) { /* 4 Sec */
+ if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) {
+ pwrpriv->bpower_saving = true;
+ DBG_88E("%s smart_ps:%d\n", __func__, pwrpriv->smart_ps);
+ /* For Tenda W311R IOT issue */
+ rtw_set_ps_mode(padapter, pwrpriv->power_mgnt, pwrpriv->smart_ps, 0);
+ }
+ } else {
+ pwrpriv->LpsIdleCount++;
+ }
+ }
+}
+
+#define LPS_LEAVE_TIMEOUT_MS 100
+
+/* Description: */
+/* Leave the leisure power save mode. */
+void LPS_Leave(struct adapter *padapter)
+{
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+
+ if (pwrpriv->bLeisurePs) {
+ if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
+ rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0);
+
+ if (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
+ LPS_RF_ON_check(padapter, LPS_LEAVE_TIMEOUT_MS);
+ }
+ }
+
+ pwrpriv->bpower_saving = false;
+}
+
+/* */
+/* Description: Leave all power save mode: LPS, FwLPS, IPS if needed. */
+/* Move code to function by tynli. 2010.03.26. */
+/* */
+void LeaveAllPowerSaveMode(struct adapter *Adapter)
+{
+ struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv);
+ u8 enqueue = 0;
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED))
+ rtw_lps_ctrl_wk_cmd(Adapter, LPS_CTRL_LEAVE, enqueue);
+}
+
+void rtw_init_pwrctrl_priv(struct adapter *padapter)
+{
+ struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
+
+ mutex_init(&pwrctrlpriv->mutex_lock);
+ pwrctrlpriv->rf_pwrstate = rf_on;
+ pwrctrlpriv->ips_enter_cnts = 0;
+ pwrctrlpriv->ips_leave_cnts = 0;
+ pwrctrlpriv->bips_processing = false;
+
+ pwrctrlpriv->ips_mode = padapter->registrypriv.ips_mode;
+ pwrctrlpriv->ips_mode_req = padapter->registrypriv.ips_mode;
+
+ pwrctrlpriv->pwr_state_check_interval = RTW_PWR_STATE_CHK_INTERVAL;
+ pwrctrlpriv->pwr_state_check_cnts = 0;
+ pwrctrlpriv->bInternalAutoSuspend = false;
+ pwrctrlpriv->bInSuspend = false;
+ pwrctrlpriv->bkeepfwalive = false;
+
+ pwrctrlpriv->LpsIdleCount = 0;
+ if (padapter->registrypriv.mp_mode == 1)
+ pwrctrlpriv->power_mgnt = PS_MODE_ACTIVE;
+ else
+ pwrctrlpriv->power_mgnt = padapter->registrypriv.power_mgnt;/* PS_MODE_MIN; */
+ pwrctrlpriv->bLeisurePs = (pwrctrlpriv->power_mgnt != PS_MODE_ACTIVE) ? true : false;
+
+ pwrctrlpriv->bFwCurrentInPSMode = false;
+
+ pwrctrlpriv->rpwm = 0;
+ pwrctrlpriv->cpwm = PS_STATE_S4;
+
+ pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE;
+ pwrctrlpriv->smart_ps = padapter->registrypriv.smart_ps;
+ pwrctrlpriv->bcn_ant_mode = 0;
+
+ pwrctrlpriv->tog = 0x80;
+
+ pwrctrlpriv->btcoex_rfon = false;
+
+ timer_setup(&pwrctrlpriv->pwr_state_check_timer,
+ pwr_state_check_handler, 0);
+}
+
+/*
+* rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
+* @adapter: pointer to struct adapter structure
+* @ips_deffer_ms: the ms will prevent from falling into IPS after wakeup
+* Return _SUCCESS or _FAIL
+*/
+
+int _rtw_pwr_wakeup(struct adapter *padapter, u32 ips_deffer_ms, const char *caller)
+{
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ unsigned long expires;
+ unsigned long start;
+ int ret = _SUCCESS;
+
+ expires = jiffies + msecs_to_jiffies(ips_deffer_ms);
+ if (time_before(pwrpriv->ips_deny_time, expires))
+ pwrpriv->ips_deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms);
+
+ start = jiffies;
+ if (pwrpriv->ps_processing) {
+ DBG_88E("%s wait ps_processing...\n", __func__);
+ while (pwrpriv->ps_processing &&
+ jiffies_to_msecs(jiffies - start) <= 3000)
+ udelay(1500);
+ if (pwrpriv->ps_processing)
+ DBG_88E("%s wait ps_processing timeout\n", __func__);
+ else
+ DBG_88E("%s wait ps_processing done\n", __func__);
+ }
+
+ /* System suspend is not allowed to wakeup */
+ if ((!pwrpriv->bInternalAutoSuspend) && (pwrpriv->bInSuspend)) {
+ ret = _FAIL;
+ goto exit;
+ }
+
+ /* block??? */
+ if ((pwrpriv->bInternalAutoSuspend) && (padapter->net_closed)) {
+ ret = _FAIL;
+ goto exit;
+ }
+
+ /* I think this should be check in IPS, LPS, autosuspend functions... */
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ ret = _SUCCESS;
+ goto exit;
+ }
+ if (rf_off == pwrpriv->rf_pwrstate) {
+ DBG_88E("%s call ips_leave....\n", __func__);
+ if (ips_leave(padapter) == _FAIL) {
+ DBG_88E("======> 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_88E("%s: bDriverStopped=%d, bup=%d, hw_init_completed =%u\n"
+ , caller
+ , padapter->bDriverStopped
+ , padapter->bup
+ , padapter->hw_init_completed);
+ ret = false;
+ goto exit;
+ }
+
+exit:
+ expires = jiffies + msecs_to_jiffies(ips_deffer_ms);
+ if (time_before(pwrpriv->ips_deny_time, expires))
+ pwrpriv->ips_deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms);
+ return ret;
+}
+
+int rtw_pm_set_lps(struct adapter *padapter, u8 mode)
+{
+ int ret = 0;
+ struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
+
+ if (mode < PS_MODE_NUM) {
+ if (pwrctrlpriv->power_mgnt != mode) {
+ if (mode == PS_MODE_ACTIVE)
+ LeaveAllPowerSaveMode(padapter);
+ else
+ pwrctrlpriv->LpsIdleCount = 2;
+ pwrctrlpriv->power_mgnt = mode;
+ pwrctrlpriv->bLeisurePs = (pwrctrlpriv->power_mgnt != PS_MODE_ACTIVE) ? true : false;
+ }
+ } else {
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+int rtw_pm_set_ips(struct adapter *padapter, u8 mode)
+{
+ struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
+
+ if (mode == IPS_NORMAL || mode == IPS_LEVEL_2) {
+ rtw_ips_mode_req(pwrctrlpriv, mode);
+ DBG_88E("%s %s\n", __func__, mode == IPS_NORMAL ? "IPS_NORMAL" : "IPS_LEVEL_2");
+ return 0;
+ } else if (mode == IPS_NONE) {
+ rtw_ips_mode_req(pwrctrlpriv, mode);
+ DBG_88E("%s %s\n", __func__, "IPS_NONE");
+ if ((padapter->bSurpriseRemoved == 0) && (rtw_pwr_wakeup(padapter) == _FAIL))
+ return -EFAULT;
+ } else {
+ return -EINVAL;
+ }
+ return 0;
+}
diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c
new file mode 100644
index 0000000..186b574
--- /dev/null
+++ b/drivers/staging/rtl8188eu/core/rtw_recv.c
@@ -0,0 +1,2054 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _RTW_RECV_C_
+
+#include <linux/ieee80211.h>
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <recv_osdep.h>
+#include <mlme_osdep.h>
+#include <mon.h>
+#include <wifi.h>
+#include <linux/vmalloc.h>
+
+#define ETHERNET_HEADER_SIZE 14 /* Ethernet Header Length */
+#define LLC_HEADER_SIZE 6 /* LLC Header Length */
+
+static u8 SNAP_ETH_TYPE_IPX[2] = {0x81, 0x37};
+static u8 SNAP_ETH_TYPE_APPLETALK_AARP[2] = {0x80, 0xf3};
+
+/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
+static u8 rtw_bridge_tunnel_header[] = {
+ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8
+};
+
+static u8 rtw_rfc1042_header[] = {
+ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00
+};
+
+static void rtw_signal_stat_timer_hdl(struct timer_list *t);
+
+void _rtw_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv)
+{
+ memset((u8 *)psta_recvpriv, 0, sizeof(struct sta_recv_priv));
+
+ spin_lock_init(&psta_recvpriv->lock);
+
+ _rtw_init_queue(&psta_recvpriv->defrag_q);
+}
+
+int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter)
+{
+ int i;
+
+ struct recv_frame *precvframe;
+
+ int res = _SUCCESS;
+
+ _rtw_init_queue(&precvpriv->free_recv_queue);
+ _rtw_init_queue(&precvpriv->recv_pending_queue);
+ _rtw_init_queue(&precvpriv->uc_swdec_pending_queue);
+
+ precvpriv->adapter = padapter;
+
+ precvpriv->pallocated_frame_buf = vzalloc(NR_RECVFRAME * sizeof(struct recv_frame) + RXFRAME_ALIGN_SZ);
+
+ if (!precvpriv->pallocated_frame_buf)
+ return _FAIL;
+
+ precvframe = PTR_ALIGN(precvpriv->pallocated_frame_buf, RXFRAME_ALIGN_SZ);
+
+ for (i = 0; i < NR_RECVFRAME; i++) {
+ INIT_LIST_HEAD(&precvframe->list);
+
+ list_add_tail(&precvframe->list,
+ &precvpriv->free_recv_queue.queue);
+
+ precvframe->pkt = NULL;
+
+ precvframe->adapter = padapter;
+ precvframe++;
+ }
+ res = rtw_hal_init_recv_priv(padapter);
+
+ timer_setup(&precvpriv->signal_stat_timer, rtw_signal_stat_timer_hdl,
+ 0);
+
+ precvpriv->signal_stat_sampling_interval = 1000; /* ms */
+
+ rtw_set_signal_stat_timer(precvpriv);
+
+ return res;
+}
+
+void _rtw_free_recv_priv(struct recv_priv *precvpriv)
+{
+ struct adapter *padapter = precvpriv->adapter;
+
+ rtw_free_uc_swdec_pending_queue(padapter);
+
+ vfree(precvpriv->pallocated_frame_buf);
+
+ rtw_hal_free_recv_priv(padapter);
+}
+
+struct recv_frame *_rtw_alloc_recvframe(struct __queue *pfree_recv_queue)
+{
+ struct recv_frame *hdr;
+
+ hdr = list_first_entry_or_null(&pfree_recv_queue->queue,
+ struct recv_frame, list);
+ if (hdr)
+ list_del_init(&hdr->list);
+
+ return hdr;
+}
+
+struct recv_frame *rtw_alloc_recvframe(struct __queue *pfree_recv_queue)
+{
+ struct recv_frame *precvframe;
+
+ spin_lock_bh(&pfree_recv_queue->lock);
+
+ precvframe = _rtw_alloc_recvframe(pfree_recv_queue);
+
+ spin_unlock_bh(&pfree_recv_queue->lock);
+
+ return precvframe;
+}
+
+int rtw_free_recvframe(struct recv_frame *precvframe,
+ struct __queue *pfree_recv_queue)
+{
+ if (!precvframe)
+ return _FAIL;
+ if (precvframe->pkt) {
+ dev_kfree_skb_any(precvframe->pkt);/* free skb by driver */
+ precvframe->pkt = NULL;
+ }
+
+ spin_lock_bh(&pfree_recv_queue->lock);
+
+ list_del_init(&precvframe->list);
+
+ list_add_tail(&precvframe->list, get_list_head(pfree_recv_queue));
+
+ spin_unlock_bh(&pfree_recv_queue->lock);
+
+ return _SUCCESS;
+}
+
+int _rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue)
+{
+ list_del_init(&precvframe->list);
+ list_add_tail(&precvframe->list, get_list_head(queue));
+
+ return _SUCCESS;
+}
+
+int rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue)
+{
+ int ret;
+
+ spin_lock_bh(&queue->lock);
+ ret = _rtw_enqueue_recvframe(precvframe, queue);
+ spin_unlock_bh(&queue->lock);
+
+ return ret;
+}
+
+/*
+caller : defrag ; recvframe_chk_defrag in recv_thread (passive)
+pframequeue: defrag_queue : will be accessed in recv_thread (passive)
+
+using spinlock to protect
+
+*/
+
+void rtw_free_recvframe_queue(struct __queue *pframequeue, struct __queue *pfree_recv_queue)
+{
+ struct recv_frame *hdr;
+ struct list_head *plist, *phead;
+
+ spin_lock(&pframequeue->lock);
+
+ phead = get_list_head(pframequeue);
+ plist = phead->next;
+
+ while (phead != plist) {
+ hdr = list_entry(plist, struct recv_frame, list);
+
+ plist = plist->next;
+
+ rtw_free_recvframe(hdr, pfree_recv_queue);
+ }
+
+ spin_unlock(&pframequeue->lock);
+}
+
+u32 rtw_free_uc_swdec_pending_queue(struct adapter *adapter)
+{
+ u32 cnt = 0;
+ struct recv_frame *pending_frame;
+
+ while ((pending_frame = rtw_alloc_recvframe(&adapter->recvpriv.uc_swdec_pending_queue))) {
+ rtw_free_recvframe(pending_frame, &adapter->recvpriv.free_recv_queue);
+ DBG_88E("%s: dequeue uc_swdec_pending_queue\n", __func__);
+ cnt++;
+ }
+
+ return cnt;
+}
+
+static int recvframe_chkmic(struct adapter *adapter,
+ struct recv_frame *precvframe)
+{
+ int i, res = _SUCCESS;
+ u32 datalen;
+ u8 miccode[8];
+ u8 bmic_err = false, brpt_micerror = true;
+ u8 *pframe, *payload, *pframemic;
+ u8 *mickey;
+ struct sta_info *stainfo;
+ struct rx_pkt_attrib *prxattrib = &precvframe->attrib;
+ struct security_priv *psecuritypriv = &adapter->securitypriv;
+
+ struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ stainfo = rtw_get_stainfo(&adapter->stapriv, &prxattrib->ta[0]);
+
+ if (prxattrib->encrypt == _TKIP_) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
+ ("\n %s: prxattrib->encrypt==_TKIP_\n", __func__));
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
+ ("\n %s: da=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
+ __func__, prxattrib->ra[0], prxattrib->ra[1], prxattrib->ra[2],
+ prxattrib->ra[3], prxattrib->ra[4], prxattrib->ra[5]));
+
+ /* calculate mic code */
+ if (stainfo) {
+ if (is_multicast_ether_addr(prxattrib->ra)) {
+ if (!psecuritypriv) {
+ res = _FAIL;
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
+ ("\n %s: didn't install group key!!!!!!!!!!\n", __func__));
+ DBG_88E("\n %s: didn't install group key!!!!!!!!!!\n", __func__);
+ goto exit;
+ }
+ mickey = &psecuritypriv->dot118021XGrprxmickey[prxattrib->key_index].skey[0];
+
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
+ ("\n %s: bcmc key\n", __func__));
+ } else {
+ mickey = &stainfo->dot11tkiprxmickey.skey[0];
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
+ ("\n %s: unicast key\n", __func__));
+ }
+
+ /* icv_len included the mic code */
+ datalen = precvframe->pkt->len-prxattrib->hdrlen -
+ prxattrib->iv_len-prxattrib->icv_len-8;
+ pframe = precvframe->pkt->data;
+ payload = pframe+prxattrib->hdrlen+prxattrib->iv_len;
+
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n prxattrib->iv_len=%d prxattrib->icv_len=%d\n", prxattrib->iv_len, prxattrib->icv_len));
+ rtw_seccalctkipmic(mickey, pframe, payload, datalen, &miccode[0],
+ (unsigned char)prxattrib->priority); /* care the length of the data */
+
+ pframemic = payload + datalen;
+
+ bmic_err = false;
+
+ for (i = 0; i < 8; i++) {
+ if (miccode[i] != *(pframemic+i)) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
+ ("%s: miccode[%d](%02x)!=*(pframemic+%d)(%02x) ",
+ __func__, i, miccode[i], i, *(pframemic + i)));
+ bmic_err = true;
+ }
+ }
+
+ if (bmic_err) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
+ ("\n *(pframemic-8)-*(pframemic-1)=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
+ *(pframemic-8), *(pframemic-7), *(pframemic-6),
+ *(pframemic-5), *(pframemic-4), *(pframemic-3),
+ *(pframemic-2), *(pframemic-1)));
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
+ ("\n *(pframemic-16)-*(pframemic-9)=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
+ *(pframemic-16), *(pframemic-15), *(pframemic-14),
+ *(pframemic-13), *(pframemic-12), *(pframemic-11),
+ *(pframemic-10), *(pframemic-9)));
+ {
+ uint i;
+
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
+ ("\n ======demp packet (len=%d)======\n",
+ precvframe->pkt->len));
+ for (i = 0; i < precvframe->pkt->len; i += 8) {
+ RT_TRACE(_module_rtl871x_recv_c_,
+ _drv_err_,
+ ("0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x",
+ *(precvframe->pkt->data+i),
+ *(precvframe->pkt->data+i+1),
+ *(precvframe->pkt->data+i+2),
+ *(precvframe->pkt->data+i+3),
+ *(precvframe->pkt->data+i+4),
+ *(precvframe->pkt->data+i+5),
+ *(precvframe->pkt->data+i+6),
+ *(precvframe->pkt->data+i+7)));
+ }
+ RT_TRACE(_module_rtl871x_recv_c_,
+ _drv_err_,
+ ("\n ====== demp packet end [len=%d]======\n",
+ precvframe->pkt->len));
+ RT_TRACE(_module_rtl871x_recv_c_,
+ _drv_err_,
+ ("\n hrdlen=%d,\n",
+ prxattrib->hdrlen));
+ }
+
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
+ ("ra=0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x psecuritypriv->binstallGrpkey=%d ",
+ prxattrib->ra[0], prxattrib->ra[1], prxattrib->ra[2],
+ prxattrib->ra[3], prxattrib->ra[4], prxattrib->ra[5], psecuritypriv->binstallGrpkey));
+
+ /* double check key_index for some timing issue , */
+ /* cannot compare with psecuritypriv->dot118021XGrpKeyid also cause timing issue */
+ if (is_multicast_ether_addr(prxattrib->ra) && prxattrib->key_index != pmlmeinfo->key_index)
+ brpt_micerror = false;
+
+ if ((prxattrib->bdecrypted) && (brpt_micerror)) {
+ rtw_handle_tkip_mic_err(adapter, (u8)is_multicast_ether_addr(prxattrib->ra));
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" mic error :prxattrib->bdecrypted=%d ", prxattrib->bdecrypted));
+ DBG_88E(" mic error :prxattrib->bdecrypted=%d\n", prxattrib->bdecrypted);
+ } else {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" mic error :prxattrib->bdecrypted=%d ", prxattrib->bdecrypted));
+ DBG_88E(" mic error :prxattrib->bdecrypted=%d\n", prxattrib->bdecrypted);
+ }
+ res = _FAIL;
+ } else {
+ /* mic checked ok */
+ if (!psecuritypriv->bcheck_grpkey && is_multicast_ether_addr(prxattrib->ra)) {
+ psecuritypriv->bcheck_grpkey = true;
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("psecuritypriv->bcheck_grpkey = true"));
+ }
+ }
+ } else {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
+ ("%s: rtw_get_stainfo==NULL!!!\n", __func__));
+ }
+
+ skb_trim(precvframe->pkt, precvframe->pkt->len - 8);
+ }
+
+exit:
+
+ return res;
+}
+
+/* decrypt and set the ivlen, icvlen of the recv_frame */
+static struct recv_frame *decryptor(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ struct rx_pkt_attrib *prxattrib = &precv_frame->attrib;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct recv_frame *return_packet = precv_frame;
+ u32 res = _SUCCESS;
+
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("prxstat->decrypted=%x prxattrib->encrypt=0x%03x\n", prxattrib->bdecrypted, prxattrib->encrypt));
+
+ if (prxattrib->encrypt > 0) {
+ u8 *iv = precv_frame->pkt->data + prxattrib->hdrlen;
+
+ prxattrib->key_index = (((iv[3]) >> 6) & 0x3);
+
+ if (prxattrib->key_index > WEP_KEYS) {
+ DBG_88E("prxattrib->key_index(%d)>WEP_KEYS\n", prxattrib->key_index);
+
+ switch (prxattrib->encrypt) {
+ case _WEP40_:
+ case _WEP104_:
+ prxattrib->key_index = psecuritypriv->dot11PrivacyKeyIndex;
+ break;
+ case _TKIP_:
+ case _AES_:
+ default:
+ prxattrib->key_index = psecuritypriv->dot118021XGrpKeyid;
+ break;
+ }
+ }
+ }
+
+ if ((prxattrib->encrypt > 0) && (prxattrib->bdecrypted == 0)) {
+ psecuritypriv->hw_decrypted = false;
+
+ switch (prxattrib->encrypt) {
+ case _WEP40_:
+ case _WEP104_:
+ res = rtw_wep_decrypt(padapter, (u8 *)precv_frame);
+ break;
+ case _TKIP_:
+ res = rtw_tkip_decrypt(padapter, (u8 *)precv_frame);
+ break;
+ case _AES_:
+ res = rtw_aes_decrypt(padapter, (u8 *)precv_frame);
+ break;
+ default:
+ break;
+ }
+ } else if (prxattrib->bdecrypted == 1 && prxattrib->encrypt > 0 &&
+ (psecuritypriv->busetkipkey == 1 || prxattrib->encrypt != _TKIP_))
+ psecuritypriv->hw_decrypted = true;
+
+ if (res == _FAIL) {
+ rtw_free_recvframe(return_packet, &padapter->recvpriv.free_recv_queue);
+ return_packet = NULL;
+ }
+
+ return return_packet;
+}
+
+/* set the security information in the recv_frame */
+static struct recv_frame *portctrl(struct adapter *adapter,
+ struct recv_frame *precv_frame)
+{
+ u8 *psta_addr, *ptr;
+ uint auth_alg;
+ struct recv_frame *pfhdr;
+ struct sta_info *psta;
+ struct sta_priv *pstapriv;
+ struct recv_frame *prtnframe;
+ u16 ether_type;
+ u16 eapol_type = 0x888e;/* for Funia BD's WPA issue */
+ struct rx_pkt_attrib *pattrib;
+ __be16 be_tmp;
+
+ pstapriv = &adapter->stapriv;
+
+ auth_alg = adapter->securitypriv.dot11AuthAlgrthm;
+
+ ptr = precv_frame->pkt->data;
+ pfhdr = precv_frame;
+ pattrib = &pfhdr->attrib;
+ psta_addr = pattrib->ta;
+ psta = rtw_get_stainfo(pstapriv, psta_addr);
+
+ prtnframe = NULL;
+
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########%s:adapter->securitypriv.dot11AuthAlgrthm=%d\n", __func__, adapter->securitypriv.dot11AuthAlgrthm));
+
+ if (auth_alg == 2) {
+ /* get ether_type */
+ ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE + pfhdr->attrib.iv_len;
+ memcpy(&be_tmp, ptr, 2);
+ ether_type = ntohs(be_tmp);
+
+ if (psta && (psta->ieee8021x_blocked)) {
+ /* blocked */
+ /* only accept EAPOL frame */
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########%s:psta->ieee8021x_blocked==1\n", __func__));
+
+ if (ether_type == eapol_type) {
+ prtnframe = precv_frame;
+ } else {
+ /* free this frame */
+ rtw_free_recvframe(precv_frame, &adapter->recvpriv.free_recv_queue);
+ prtnframe = NULL;
+ }
+ } else {
+ /* allowed */
+ /* check decryption status, and decrypt the frame if needed */
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########%s:psta->ieee8021x_blocked==0\n", __func__));
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
+ ("%s:precv_frame->hdr.attrib.privacy=%x\n",
+ __func__, precv_frame->attrib.privacy));
+
+ if (pattrib->bdecrypted == 0)
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("%s:prxstat->decrypted=%x\n", __func__, pattrib->bdecrypted));
+
+ prtnframe = precv_frame;
+ /* check is the EAPOL frame or not (Rekey) */
+ if (ether_type == eapol_type) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("########%s:ether_type==0x888e\n", __func__));
+ /* check Rekey */
+
+ prtnframe = precv_frame;
+ } else {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########%s:ether_type=0x%04x\n", __func__, ether_type));
+ }
+ }
+ } else {
+ prtnframe = precv_frame;
+ }
+
+ return prtnframe;
+}
+
+static int recv_decache(struct recv_frame *precv_frame, u8 bretry,
+ struct stainfo_rxcache *prxcache)
+{
+ int tid = precv_frame->attrib.priority;
+
+ u16 seq_ctrl = ((precv_frame->attrib.seq_num&0xffff) << 4) |
+ (precv_frame->attrib.frag_num & 0xf);
+
+ if (tid > 15) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("%s, (tid>15)! seq_ctrl=0x%x, tid=0x%x\n", __func__, seq_ctrl, tid));
+
+ return _FAIL;
+ }
+
+ if (1) {/* if (bretry) */
+ if (seq_ctrl == prxcache->tid_rxseq[tid]) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("%s, seq_ctrl=0x%x, tid=0x%x, tid_rxseq=0x%x\n", __func__, seq_ctrl, tid, prxcache->tid_rxseq[tid]));
+
+ return _FAIL;
+ }
+ }
+
+ prxcache->tid_rxseq[tid] = seq_ctrl;
+
+ return _SUCCESS;
+}
+
+static void process_pwrbit_data(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+#ifdef CPTCFG_88EU_AP_MODE
+ unsigned char pwrbit;
+ u8 *ptr = precv_frame->pkt->data;
+ struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct sta_info *psta = NULL;
+
+ psta = rtw_get_stainfo(pstapriv, pattrib->src);
+
+ pwrbit = GetPwrMgt(ptr);
+
+ if (psta) {
+ if (pwrbit) {
+ if (!(psta->state & WIFI_SLEEP_STATE))
+ stop_sta_xmit(padapter, psta);
+ } else {
+ if (psta->state & WIFI_SLEEP_STATE)
+ wakeup_sta_to_xmit(padapter, psta);
+ }
+ }
+
+#endif
+}
+
+static void process_wmmps_data(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+#ifdef CPTCFG_88EU_AP_MODE
+ struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct sta_info *psta = NULL;
+
+ psta = rtw_get_stainfo(pstapriv, pattrib->src);
+
+ if (!psta)
+ return;
+
+ if (!psta->qos_option)
+ return;
+
+ if (!(psta->qos_info&0xf))
+ return;
+
+ if (psta->state&WIFI_SLEEP_STATE) {
+ u8 wmmps_ac = 0;
+
+ switch (pattrib->priority) {
+ case 1:
+ case 2:
+ wmmps_ac = psta->uapsd_bk&BIT(1);
+ break;
+ case 4:
+ case 5:
+ wmmps_ac = psta->uapsd_vi&BIT(1);
+ break;
+ case 6:
+ case 7:
+ wmmps_ac = psta->uapsd_vo&BIT(1);
+ break;
+ case 0:
+ case 3:
+ default:
+ wmmps_ac = psta->uapsd_be&BIT(1);
+ break;
+ }
+
+ if (wmmps_ac) {
+ if (psta->sleepq_ac_len > 0) {
+ /* process received triggered frame */
+ xmit_delivery_enabled_frames(padapter, psta);
+ } else {
+ /* issue one qos null frame with More data bit = 0 and the EOSP bit set (= 1) */
+ issue_qos_nulldata(padapter, psta->hwaddr, (u16)pattrib->priority, 0, 0);
+ }
+ }
+ }
+
+#endif
+}
+
+static void count_rx_stats(struct adapter *padapter,
+ struct recv_frame *prframe,
+ struct sta_info *sta)
+{
+ int sz;
+ struct sta_info *psta = NULL;
+ struct stainfo_stats *pstats = NULL;
+ struct rx_pkt_attrib *pattrib = &prframe->attrib;
+ struct recv_priv *precvpriv = &padapter->recvpriv;
+
+ sz = prframe->pkt->len;
+ precvpriv->rx_bytes += sz;
+
+ padapter->mlmepriv.LinkDetectInfo.NumRxOkInPeriod++;
+
+ if (!is_multicast_ether_addr(pattrib->dst))
+ padapter->mlmepriv.LinkDetectInfo.NumRxUnicastOkInPeriod++;
+
+ if (sta)
+ psta = sta;
+ else
+ psta = prframe->psta;
+
+ if (psta) {
+ pstats = &psta->sta_stats;
+
+ pstats->rx_data_pkts++;
+ pstats->rx_bytes += sz;
+ }
+}
+
+static int sta2sta_data_frame(struct adapter *adapter,
+ struct recv_frame *precv_frame,
+ struct sta_info **psta)
+{
+ int ret = _SUCCESS;
+ struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
+ struct sta_priv *pstapriv = &adapter->stapriv;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ u8 *mybssid = get_bssid(pmlmepriv);
+ u8 *myhwaddr = myid(&adapter->eeprompriv);
+ u8 *sta_addr = NULL;
+ bool mcast = is_multicast_ether_addr(pattrib->dst);
+
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
+ check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
+ /* filter packets that SA is myself or multicast or broadcast */
+ if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN)) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" SA==myself\n"));
+ ret = _FAIL;
+ goto exit;
+ }
+
+ if (memcmp(myhwaddr, pattrib->dst, ETH_ALEN) && !mcast) {
+ ret = _FAIL;
+ goto exit;
+ }
+
+ if (!memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
+ !memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
+ memcmp(pattrib->bssid, mybssid, ETH_ALEN)) {
+ ret = _FAIL;
+ goto exit;
+ }
+
+ sta_addr = pattrib->src;
+ } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
+ /* For Station mode, sa and bssid should always be BSSID, and DA is my mac-address */
+ if (memcmp(pattrib->bssid, pattrib->src, ETH_ALEN)) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("bssid!=TA under STATION_MODE; drop pkt\n"));
+ ret = _FAIL;
+ goto exit;
+ }
+ sta_addr = pattrib->bssid;
+ } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+ if (mcast) {
+ /* For AP mode, if DA == MCAST, then BSSID should be also MCAST */
+ if (!is_multicast_ether_addr(pattrib->bssid)) {
+ ret = _FAIL;
+ goto exit;
+ }
+ } else { /* not mc-frame */
+ /* For AP mode, if DA is non-MCAST, then it must be BSSID, and bssid == BSSID */
+ if (memcmp(pattrib->bssid, pattrib->dst, ETH_ALEN)) {
+ ret = _FAIL;
+ goto exit;
+ }
+
+ sta_addr = pattrib->src;
+ }
+ } else {
+ ret = _FAIL;
+ }
+
+ if (mcast)
+ *psta = rtw_get_bcmc_stainfo(adapter);
+ else
+ *psta = rtw_get_stainfo(pstapriv, sta_addr); /* get ap_info */
+
+ if (!*psta) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("can't get psta under %s ; drop pkt\n", __func__));
+ ret = _FAIL;
+ goto exit;
+ }
+
+exit:
+ return ret;
+}
+
+static int ap2sta_data_frame(
+ struct adapter *adapter,
+ struct recv_frame *precv_frame,
+ struct sta_info **psta)
+{
+ u8 *ptr = precv_frame->pkt->data;
+ struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
+ int ret = _SUCCESS;
+ struct sta_priv *pstapriv = &adapter->stapriv;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ u8 *mybssid = get_bssid(pmlmepriv);
+ u8 *myhwaddr = myid(&adapter->eeprompriv);
+ bool mcast = is_multicast_ether_addr(pattrib->dst);
+
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
+ (check_fwstate(pmlmepriv, _FW_LINKED) ||
+ check_fwstate(pmlmepriv, _FW_UNDER_LINKING))) {
+ /* filter packets that SA is myself or multicast or broadcast */
+ if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN)) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" SA==myself\n"));
+ ret = _FAIL;
+ goto exit;
+ }
+
+ /* da should be for me */
+ if (memcmp(myhwaddr, pattrib->dst, ETH_ALEN) && !mcast) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
+ (" %s: compare DA fail; DA=%pM\n", __func__, (pattrib->dst)));
+ ret = _FAIL;
+ goto exit;
+ }
+
+ /* check BSSID */
+ if (!memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
+ !memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
+ (memcmp(pattrib->bssid, mybssid, ETH_ALEN))) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
+ (" %s: compare BSSID fail ; BSSID=%pM\n", __func__, (pattrib->bssid)));
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("mybssid=%pM\n", (mybssid)));
+
+ if (!mcast) {
+ DBG_88E("issue_deauth to the nonassociated ap=%pM for the reason(7)\n", (pattrib->bssid));
+ issue_deauth(adapter, pattrib->bssid, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
+ }
+
+ ret = _FAIL;
+ goto exit;
+ }
+
+ if (mcast)
+ *psta = rtw_get_bcmc_stainfo(adapter);
+ else
+ *psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /* get ap_info */
+
+ if (!*psta) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("ap2sta: can't get psta under STATION_MODE ; drop pkt\n"));
+ ret = _FAIL;
+ goto exit;
+ }
+
+ /* if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) == WIFI_QOS_DATA_TYPE) { */
+ /* */
+
+ if (GetFrameSubType(ptr) & BIT(6)) {
+ /* No data, will not indicate to upper layer, temporily count it here */
+ count_rx_stats(adapter, precv_frame, *psta);
+ ret = RTW_RX_HANDLED;
+ goto exit;
+ }
+ } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+ /* Special case */
+ ret = RTW_RX_HANDLED;
+ goto exit;
+ } else {
+ if (!memcmp(myhwaddr, pattrib->dst, ETH_ALEN) && !mcast) {
+ *psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /* get sta_info */
+ if (!*psta) {
+ DBG_88E("issue_deauth to the ap =%pM for the reason(7)\n", (pattrib->bssid));
+
+ issue_deauth(adapter, pattrib->bssid, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
+ }
+ }
+
+ ret = _FAIL;
+ }
+
+exit:
+
+ return ret;
+}
+
+static int sta2ap_data_frame(struct adapter *adapter,
+ struct recv_frame *precv_frame,
+ struct sta_info **psta)
+{
+ struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
+ struct sta_priv *pstapriv = &adapter->stapriv;
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+ u8 *ptr = precv_frame->pkt->data;
+ unsigned char *mybssid = get_bssid(pmlmepriv);
+ int ret = _SUCCESS;
+
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+ /* For AP mode, RA = BSSID, TX = STA(SRC_ADDR), A3 = DST_ADDR */
+ if (memcmp(pattrib->bssid, mybssid, ETH_ALEN)) {
+ ret = _FAIL;
+ goto exit;
+ }
+
+ *psta = rtw_get_stainfo(pstapriv, pattrib->src);
+ if (!*psta) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("can't get psta under AP_MODE; drop pkt\n"));
+ DBG_88E("issue_deauth to sta=%pM for the reason(7)\n", (pattrib->src));
+
+ issue_deauth(adapter, pattrib->src, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
+
+ ret = RTW_RX_HANDLED;
+ goto exit;
+ }
+
+ process_pwrbit_data(adapter, precv_frame);
+
+ if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) == WIFI_QOS_DATA_TYPE)
+ process_wmmps_data(adapter, precv_frame);
+
+ if (GetFrameSubType(ptr) & BIT(6)) {
+ /* No data, will not indicate to upper layer, temporily count it here */
+ count_rx_stats(adapter, precv_frame, *psta);
+ ret = RTW_RX_HANDLED;
+ goto exit;
+ }
+ } else {
+ u8 *myhwaddr = myid(&adapter->eeprompriv);
+
+ if (memcmp(pattrib->ra, myhwaddr, ETH_ALEN)) {
+ ret = RTW_RX_HANDLED;
+ goto exit;
+ }
+ DBG_88E("issue_deauth to sta=%pM for the reason(7)\n", (pattrib->src));
+ issue_deauth(adapter, pattrib->src, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
+ ret = RTW_RX_HANDLED;
+ goto exit;
+ }
+
+exit:
+
+ return ret;
+}
+
+static int validate_recv_ctrl_frame(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+#ifdef CPTCFG_88EU_AP_MODE
+ struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ u8 *pframe = precv_frame->pkt->data;
+
+ if (GetFrameType(pframe) != WIFI_CTRL_TYPE)
+ return _FAIL;
+
+ /* receive the frames that ra(a1) is my address */
+ if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN))
+ return _FAIL;
+
+ /* only handle ps-poll */
+ if (GetFrameSubType(pframe) == WIFI_PSPOLL) {
+ u16 aid;
+ u8 wmmps_ac = 0;
+ struct sta_info *psta = NULL;
+
+ aid = GetAid(pframe);
+ psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
+
+ if ((!psta) || (psta->aid != aid))
+ return _FAIL;
+
+ /* for rx pkt statistics */
+ psta->sta_stats.rx_ctrl_pkts++;
+
+ switch (pattrib->priority) {
+ case 1:
+ case 2:
+ wmmps_ac = psta->uapsd_bk&BIT(0);
+ break;
+ case 4:
+ case 5:
+ wmmps_ac = psta->uapsd_vi&BIT(0);
+ break;
+ case 6:
+ case 7:
+ wmmps_ac = psta->uapsd_vo&BIT(0);
+ break;
+ case 0:
+ case 3:
+ default:
+ wmmps_ac = psta->uapsd_be&BIT(0);
+ break;
+ }
+
+ if (wmmps_ac)
+ return _FAIL;
+
+ if (psta->state & WIFI_STA_ALIVE_CHK_STATE) {
+ DBG_88E("%s alive check-rx ps-poll\n", __func__);
+ psta->expire_to = pstapriv->expire_to;
+ psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
+ }
+
+ if ((psta->state&WIFI_SLEEP_STATE) && (pstapriv->sta_dz_bitmap&BIT(psta->aid))) {
+ struct list_head *xmitframe_plist, *xmitframe_phead;
+ struct xmit_frame *pxmitframe = NULL;
+
+ spin_lock_bh(&psta->sleep_q.lock);
+
+ xmitframe_phead = get_list_head(&psta->sleep_q);
+ xmitframe_plist = xmitframe_phead->next;
+
+ if (xmitframe_phead != xmitframe_plist) {
+ pxmitframe = list_entry(xmitframe_plist, struct xmit_frame, list);
+
+ xmitframe_plist = xmitframe_plist->next;
+
+ list_del_init(&pxmitframe->list);
+
+ psta->sleepq_len--;
+
+ if (psta->sleepq_len > 0)
+ pxmitframe->attrib.mdata = 1;
+ else
+ pxmitframe->attrib.mdata = 0;
+
+ pxmitframe->attrib.triggered = 1;
+
+ spin_unlock_bh(&psta->sleep_q.lock);
+ if (rtw_hal_xmit(padapter, pxmitframe))
+ rtw_os_xmit_complete(padapter, pxmitframe);
+ spin_lock_bh(&psta->sleep_q.lock);
+
+ if (psta->sleepq_len == 0) {
+ pstapriv->tim_bitmap &= ~BIT(psta->aid);
+
+ /* update BCN for TIM IE */
+ /* update_BCNTIM(padapter); */
+ update_beacon(padapter, _TIM_IE_, NULL, false);
+ }
+ } else {
+ if (pstapriv->tim_bitmap&BIT(psta->aid)) {
+ if (psta->sleepq_len == 0) {
+ DBG_88E("no buffered packets to xmit\n");
+
+ /* issue nulldata with More data bit = 0 to indicate we have no buffered packets */
+ issue_nulldata(padapter, psta->hwaddr, 0, 0, 0);
+ } else {
+ DBG_88E("error!psta->sleepq_len=%d\n", psta->sleepq_len);
+ psta->sleepq_len = 0;
+ }
+
+ pstapriv->tim_bitmap &= ~BIT(psta->aid);
+
+ /* update BCN for TIM IE */
+ /* update_BCNTIM(padapter); */
+ update_beacon(padapter, _TIM_IE_, NULL, false);
+ }
+ }
+
+ spin_unlock_bh(&psta->sleep_q.lock);
+ }
+ }
+
+#endif
+
+ return _FAIL;
+}
+
+struct recv_frame *recvframe_chk_defrag(struct adapter *padapter,
+ struct recv_frame *precv_frame);
+
+static int validate_recv_mgnt_frame(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ struct sta_info *psta;
+
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("+%s\n", __func__));
+
+ precv_frame = recvframe_chk_defrag(padapter, precv_frame);
+ if (!precv_frame) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
+ ("%s: fragment packet\n", __func__));
+ return _SUCCESS;
+ }
+
+ /* for rx pkt statistics */
+ psta = rtw_get_stainfo(&padapter->stapriv,
+ GetAddr2Ptr(precv_frame->pkt->data));
+ if (psta) {
+ psta->sta_stats.rx_mgnt_pkts++;
+ if (GetFrameSubType(precv_frame->pkt->data) == WIFI_BEACON) {
+ psta->sta_stats.rx_beacon_pkts++;
+ } else if (GetFrameSubType(precv_frame->pkt->data) == WIFI_PROBEREQ) {
+ psta->sta_stats.rx_probereq_pkts++;
+ } else if (GetFrameSubType(precv_frame->pkt->data) == WIFI_PROBERSP) {
+ if (!memcmp(padapter->eeprompriv.mac_addr,
+ GetAddr1Ptr(precv_frame->pkt->data), ETH_ALEN))
+ psta->sta_stats.rx_probersp_pkts++;
+ else if (is_multicast_ether_addr(GetAddr1Ptr(precv_frame->pkt->data)))
+ psta->sta_stats.rx_probersp_bm_pkts++;
+ else
+ psta->sta_stats.rx_probersp_uo_pkts++;
+ }
+ }
+
+ mgt_dispatcher(padapter, precv_frame);
+
+ return _SUCCESS;
+}
+
+static int validate_recv_data_frame(struct adapter *adapter,
+ struct recv_frame *precv_frame)
+{
+ u8 bretry;
+ u8 *psa, *pda, *pbssid;
+ struct sta_info *psta = NULL;
+ u8 *ptr = precv_frame->pkt->data;
+ struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
+ struct security_priv *psecuritypriv = &adapter->securitypriv;
+ int ret = _SUCCESS;
+
+ bretry = GetRetry(ptr);
+ pda = get_da(ptr);
+ psa = get_sa(ptr);
+ pbssid = get_hdr_bssid(ptr);
+
+ if (!pbssid) {
+ ret = _FAIL;
+ goto exit;
+ }
+
+ memcpy(pattrib->dst, pda, ETH_ALEN);
+ memcpy(pattrib->src, psa, ETH_ALEN);
+
+ memcpy(pattrib->bssid, pbssid, ETH_ALEN);
+
+ switch (pattrib->to_fr_ds) {
+ case 0:
+ memcpy(pattrib->ra, pda, ETH_ALEN);
+ memcpy(pattrib->ta, psa, ETH_ALEN);
+ ret = sta2sta_data_frame(adapter, precv_frame, &psta);
+ break;
+ case 1:
+ memcpy(pattrib->ra, pda, ETH_ALEN);
+ memcpy(pattrib->ta, pbssid, ETH_ALEN);
+ ret = ap2sta_data_frame(adapter, precv_frame, &psta);
+ break;
+ case 2:
+ memcpy(pattrib->ra, pbssid, ETH_ALEN);
+ memcpy(pattrib->ta, psa, ETH_ALEN);
+ ret = sta2ap_data_frame(adapter, precv_frame, &psta);
+ break;
+ case 3:
+ memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN);
+ memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN);
+ ret = _FAIL;
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" case 3\n"));
+ break;
+ default:
+ ret = _FAIL;
+ break;
+ }
+
+ if (ret == _FAIL)
+ goto exit;
+ else if (ret == RTW_RX_HANDLED)
+ goto exit;
+
+ if (!psta) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" after to_fr_ds_chk; psta==NULL\n"));
+ ret = _FAIL;
+ goto exit;
+ }
+
+ /* psta->rssi = prxcmd->rssi; */
+ /* psta->signal_quality = prxcmd->sq; */
+ precv_frame->psta = psta;
+
+ pattrib->amsdu = 0;
+ pattrib->ack_policy = 0;
+ /* parsing QC field */
+ if (pattrib->qos == 1) {
+ pattrib->priority = GetPriority((ptr + 24));
+ pattrib->ack_policy = GetAckpolicy((ptr + 24));
+ pattrib->amsdu = GetAMsdu((ptr + 24));
+ pattrib->hdrlen = pattrib->to_fr_ds == 3 ? 32 : 26;
+
+ if (pattrib->priority != 0 && pattrib->priority != 3)
+ adapter->recvpriv.bIsAnyNonBEPkts = true;
+ } else {
+ pattrib->priority = 0;
+ pattrib->hdrlen = pattrib->to_fr_ds == 3 ? 30 : 24;
+ }
+
+ if (pattrib->order)/* HT-CTRL 11n */
+ pattrib->hdrlen += 4;
+
+ precv_frame->preorder_ctrl = &psta->recvreorder_ctrl[pattrib->priority];
+
+ /* decache, drop duplicate recv packets */
+ if (recv_decache(precv_frame, bretry, &psta->sta_recvpriv.rxcache) == _FAIL) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("decache : drop pkt\n"));
+ ret = _FAIL;
+ goto exit;
+ }
+
+ if (pattrib->privacy) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("%s:pattrib->privacy=%x\n", __func__, pattrib->privacy));
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n ^^^^^^^^^^^is_multicast_ether_addr(pattrib->ra(0x%02x))=%d^^^^^^^^^^^^^^^6\n", pattrib->ra[0], is_multicast_ether_addr(pattrib->ra)));
+
+ GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, is_multicast_ether_addr(pattrib->ra));
+
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n pattrib->encrypt=%d\n", pattrib->encrypt));
+
+ SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt);
+ } else {
+ pattrib->encrypt = 0;
+ pattrib->iv_len = 0;
+ pattrib->icv_len = 0;
+ }
+
+exit:
+
+ return ret;
+}
+
+static int validate_recv_frame(struct adapter *adapter,
+ struct recv_frame *precv_frame)
+{
+ /* shall check frame subtype, to / from ds, da, bssid */
+
+ /* then call check if rx seq/frag. duplicated. */
+
+ u8 type;
+ u8 subtype;
+ int retval = _SUCCESS;
+ u8 bDumpRxPkt;
+ struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
+ u8 *ptr = precv_frame->pkt->data;
+ u8 ver = (unsigned char)(*ptr) & 0x3;
+ struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
+
+ if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
+ int ch_set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, rtw_get_oper_ch(adapter));
+
+ if (ch_set_idx >= 0)
+ pmlmeext->channel_set[ch_set_idx].rx_count++;
+ }
+
+ /* add version chk */
+ if (ver != 0) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("validate_recv_data_frame fail! (ver!=0)\n"));
+ retval = _FAIL;
+ goto exit;
+ }
+
+ type = GetFrameType(ptr);
+ subtype = GetFrameSubType(ptr); /* bit(7)~bit(2) */
+
+ pattrib->to_fr_ds = get_tofr_ds(ptr);
+
+ pattrib->frag_num = GetFragNum(ptr);
+ pattrib->seq_num = GetSequence(ptr);
+
+ pattrib->pw_save = GetPwrMgt(ptr);
+ pattrib->mfrag = GetMFrag(ptr);
+ pattrib->mdata = GetMData(ptr);
+ pattrib->privacy = GetPrivacy(ptr);
+ pattrib->order = GetOrder(ptr);
+
+ /* Dump rx packets */
+ rtw_hal_get_def_var(adapter, HAL_DEF_DBG_DUMP_RXPKT, &(bDumpRxPkt));
+ if (bDumpRxPkt == 1) {/* dump all rx packets */
+ if (_drv_err_ <= GlobalDebugLevel) {
+ pr_info(DRIVER_PREFIX "#############################\n");
+ print_hex_dump(KERN_INFO, DRIVER_PREFIX, DUMP_PREFIX_NONE,
+ 16, 1, ptr, 64, false);
+ pr_info(DRIVER_PREFIX "#############################\n");
+ }
+ } else if (bDumpRxPkt == 2) {
+ if ((_drv_err_ <= GlobalDebugLevel) && (type == WIFI_MGT_TYPE)) {
+ pr_info(DRIVER_PREFIX "#############################\n");
+ print_hex_dump(KERN_INFO, DRIVER_PREFIX, DUMP_PREFIX_NONE,
+ 16, 1, ptr, 64, false);
+ pr_info(DRIVER_PREFIX "#############################\n");
+ }
+ } else if (bDumpRxPkt == 3) {
+ if ((_drv_err_ <= GlobalDebugLevel) && (type == WIFI_DATA_TYPE)) {
+ pr_info(DRIVER_PREFIX "#############################\n");
+ print_hex_dump(KERN_INFO, DRIVER_PREFIX, DUMP_PREFIX_NONE,
+ 16, 1, ptr, 64, false);
+ pr_info(DRIVER_PREFIX "#############################\n");
+ }
+ }
+ switch (type) {
+ case WIFI_MGT_TYPE: /* mgnt */
+ retval = validate_recv_mgnt_frame(adapter, precv_frame);
+ if (retval == _FAIL)
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("validate_recv_mgnt_frame fail\n"));
+ retval = _FAIL; /* only data frame return _SUCCESS */
+ break;
+ case WIFI_CTRL_TYPE: /* ctrl */
+ retval = validate_recv_ctrl_frame(adapter, precv_frame);
+ if (retval == _FAIL)
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("validate_recv_ctrl_frame fail\n"));
+ retval = _FAIL; /* only data frame return _SUCCESS */
+ break;
+ case WIFI_DATA_TYPE: /* data */
+ led_control_8188eu(adapter, LED_CTL_RX);
+ pattrib->qos = (subtype & BIT(7)) ? 1 : 0;
+ retval = validate_recv_data_frame(adapter, precv_frame);
+ if (retval == _FAIL) {
+ struct recv_priv *precvpriv = &adapter->recvpriv;
+
+ precvpriv->rx_drop++;
+ }
+ break;
+ default:
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("validate_recv_data_frame fail! type= 0x%x\n", type));
+ retval = _FAIL;
+ break;
+ }
+
+ /*
+ * This is the last moment before management and control frames get
+ * discarded. So we need to forward them to the monitor now or never.
+ *
+ * At the same time data frames can still be encrypted if software
+ * decryption is in use. However, decryption can occur not until later
+ * (see recv_func()).
+ *
+ * Hence forward the frame to the monitor anyway to preserve the order
+ * in which frames were received.
+ */
+ rtl88eu_mon_recv_hook(adapter->pmondev, precv_frame);
+
+exit:
+
+ return retval;
+}
+
+/* remove the wlanhdr and add the eth_hdr */
+
+static int wlanhdr_to_ethhdr(struct recv_frame *precvframe)
+{
+ int rmv_len;
+ u16 eth_type, len;
+ __be16 be_tmp;
+ u8 bsnaphdr;
+ u8 *psnap_type;
+ struct ieee80211_snap_hdr *psnap;
+
+ u8 *ptr = precvframe->pkt->data;
+ struct rx_pkt_attrib *pattrib = &precvframe->attrib;
+
+ if (pattrib->encrypt)
+ skb_trim(precvframe->pkt, precvframe->pkt->len - pattrib->icv_len);
+
+ psnap = (struct ieee80211_snap_hdr *)(ptr+pattrib->hdrlen + pattrib->iv_len);
+ psnap_type = ptr+pattrib->hdrlen + pattrib->iv_len+SNAP_SIZE;
+ /* convert hdr + possible LLC headers into Ethernet header */
+ if ((!memcmp(psnap, rtw_rfc1042_header, SNAP_SIZE) &&
+ memcmp(psnap_type, SNAP_ETH_TYPE_IPX, 2) &&
+ memcmp(psnap_type, SNAP_ETH_TYPE_APPLETALK_AARP, 2)) ||
+ !memcmp(psnap, rtw_bridge_tunnel_header, SNAP_SIZE)) {
+ /* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */
+ bsnaphdr = true;
+ } else {
+ /* Leave Ethernet header part of hdr and full payload */
+ bsnaphdr = false;
+ }
+
+ rmv_len = pattrib->hdrlen + pattrib->iv_len + (bsnaphdr ? SNAP_SIZE : 0);
+ len = precvframe->pkt->len - rmv_len;
+
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
+ ("\n===pattrib->hdrlen: %x, pattrib->iv_len:%x===\n\n", pattrib->hdrlen, pattrib->iv_len));
+
+ memcpy(&be_tmp, ptr+rmv_len, 2);
+ eth_type = ntohs(be_tmp); /* pattrib->ether_type */
+ pattrib->eth_type = eth_type;
+
+ ptr = skb_pull(precvframe->pkt, rmv_len - sizeof(struct ethhdr) + (bsnaphdr ? 2 : 0));
+ if (!ptr)
+ return _FAIL;
+
+ memcpy(ptr, pattrib->dst, ETH_ALEN);
+ memcpy(ptr + ETH_ALEN, pattrib->src, ETH_ALEN);
+
+ if (!bsnaphdr) {
+ be_tmp = htons(len);
+ memcpy(ptr + 12, &be_tmp, 2);
+ }
+
+ return _SUCCESS;
+}
+
+/* perform defrag */
+static struct recv_frame *recvframe_defrag(struct adapter *adapter,
+ struct __queue *defrag_q)
+{
+ struct list_head *plist, *phead;
+ u8 wlanhdr_offset;
+ u8 curfragnum;
+ struct recv_frame *pnfhdr;
+ struct recv_frame *prframe, *pnextrframe;
+ struct __queue *pfree_recv_queue;
+
+ curfragnum = 0;
+ pfree_recv_queue = &adapter->recvpriv.free_recv_queue;
+
+ phead = get_list_head(defrag_q);
+ plist = phead->next;
+ prframe = list_entry(plist, struct recv_frame, list);
+ list_del_init(&prframe->list);
+
+ if (curfragnum != prframe->attrib.frag_num) {
+ /* the first fragment number must be 0 */
+ /* free the whole queue */
+ rtw_free_recvframe(prframe, pfree_recv_queue);
+ rtw_free_recvframe_queue(defrag_q, pfree_recv_queue);
+
+ return NULL;
+ }
+
+ curfragnum++;
+
+ plist = get_list_head(defrag_q);
+
+ plist = plist->next;
+
+ while (phead != plist) {
+ pnfhdr = list_entry(plist, struct recv_frame, list);
+ pnextrframe = pnfhdr;
+
+ /* check the fragment sequence (2nd ~n fragment frame) */
+
+ if (curfragnum != pnfhdr->attrib.frag_num) {
+ /* the fragment number must be increasing (after decache) */
+ /* release the defrag_q & prframe */
+ rtw_free_recvframe(prframe, pfree_recv_queue);
+ rtw_free_recvframe_queue(defrag_q, pfree_recv_queue);
+ return NULL;
+ }
+
+ curfragnum++;
+
+ /* copy the 2nd~n fragment frame's payload to the first fragment */
+ /* get the 2nd~last fragment frame's payload */
+
+ wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len;
+
+ skb_pull(pnextrframe->pkt, wlanhdr_offset);
+
+ /* append to first fragment frame's tail (if privacy frame, pull the ICV) */
+ skb_trim(prframe->pkt, prframe->pkt->len - prframe->attrib.icv_len);
+
+ skb_put_data(prframe->pkt, pnfhdr->pkt->data, pnfhdr->pkt->len);
+
+ prframe->attrib.icv_len = pnfhdr->attrib.icv_len;
+ plist = plist->next;
+ }
+
+ /* free the defrag_q queue and return the prframe */
+ rtw_free_recvframe_queue(defrag_q, pfree_recv_queue);
+
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("Performance defrag!!!!!\n"));
+
+ return prframe;
+}
+
+/* check if need to defrag, if needed queue the frame to defrag_q */
+struct recv_frame *recvframe_chk_defrag(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ u8 ismfrag;
+ u8 fragnum;
+ u8 *psta_addr;
+ struct recv_frame *pfhdr;
+ struct sta_info *psta;
+ struct sta_priv *pstapriv;
+ struct list_head *phead;
+ struct recv_frame *prtnframe = NULL;
+ struct __queue *pfree_recv_queue, *pdefrag_q;
+
+ pstapriv = &padapter->stapriv;
+
+ pfhdr = precv_frame;
+
+ pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
+
+ /* need to define struct of wlan header frame ctrl */
+ ismfrag = pfhdr->attrib.mfrag;
+ fragnum = pfhdr->attrib.frag_num;
+
+ psta_addr = pfhdr->attrib.ta;
+ psta = rtw_get_stainfo(pstapriv, psta_addr);
+ if (!psta) {
+ u8 type = GetFrameType(pfhdr->pkt->data);
+
+ if (type != WIFI_DATA_TYPE) {
+ psta = rtw_get_bcmc_stainfo(padapter);
+ pdefrag_q = &psta->sta_recvpriv.defrag_q;
+ } else {
+ pdefrag_q = NULL;
+ }
+ } else {
+ pdefrag_q = &psta->sta_recvpriv.defrag_q;
+ }
+
+ if ((ismfrag == 0) && (fragnum == 0))
+ prtnframe = precv_frame;/* isn't a fragment frame */
+
+ if (ismfrag == 1) {
+ /* 0~(n-1) fragment frame */
+ /* enqueue to defraf_g */
+ if (pdefrag_q) {
+ if (fragnum == 0) {
+ /* the first fragment */
+ if (!list_empty(&pdefrag_q->queue))
+ /* free current defrag_q */
+ rtw_free_recvframe_queue(pdefrag_q, pfree_recv_queue);
+ }
+
+ /* Then enqueue the 0~(n-1) fragment into the defrag_q */
+
+ phead = get_list_head(pdefrag_q);
+ list_add_tail(&pfhdr->list, phead);
+
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("Enqueuq: ismfrag=%d, fragnum=%d\n", ismfrag, fragnum));
+
+ prtnframe = NULL;
+ } else {
+ /* can't find this ta's defrag_queue, so free this recv_frame */
+ rtw_free_recvframe(precv_frame, pfree_recv_queue);
+ prtnframe = NULL;
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("Free because pdefrag_q==NULL: ismfrag=%d, fragnum=%d\n", ismfrag, fragnum));
+ }
+ }
+
+ if ((ismfrag == 0) && (fragnum != 0)) {
+ /* the last fragment frame */
+ /* enqueue the last fragment */
+ if (pdefrag_q) {
+ phead = get_list_head(pdefrag_q);
+ list_add_tail(&pfhdr->list, phead);
+
+ /* call recvframe_defrag to defrag */
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("defrag: ismfrag=%d, fragnum=%d\n", ismfrag, fragnum));
+ precv_frame = recvframe_defrag(padapter, pdefrag_q);
+ prtnframe = precv_frame;
+ } else {
+ /* can't find this ta's defrag_queue, so free this recv_frame */
+ rtw_free_recvframe(precv_frame, pfree_recv_queue);
+ prtnframe = NULL;
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("Free because pdefrag_q==NULL: ismfrag=%d, fragnum=%d\n", ismfrag, fragnum));
+ }
+ }
+
+ if (prtnframe && (prtnframe->attrib.privacy)) {
+ /* after defrag we must check tkip mic code */
+ if (recvframe_chkmic(padapter, prtnframe) == _FAIL) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recvframe_chkmic(padapter, prtnframe)==_FAIL\n"));
+ rtw_free_recvframe(prtnframe, pfree_recv_queue);
+ prtnframe = NULL;
+ }
+ }
+
+ return prtnframe;
+}
+
+static int amsdu_to_msdu(struct adapter *padapter, struct recv_frame *prframe)
+{
+ int a_len, padding_len;
+ u16 eth_type, nSubframe_Length;
+ u8 nr_subframes, i;
+ unsigned char *pdata;
+ struct rx_pkt_attrib *pattrib;
+ struct sk_buff *sub_skb, *subframes[MAX_SUBFRAME_COUNT];
+ struct recv_priv *precvpriv = &padapter->recvpriv;
+ struct __queue *pfree_recv_queue = &precvpriv->free_recv_queue;
+
+ nr_subframes = 0;
+ pattrib = &prframe->attrib;
+
+ skb_pull(prframe->pkt, prframe->attrib.hdrlen);
+
+ if (prframe->attrib.iv_len > 0)
+ skb_pull(prframe->pkt, prframe->attrib.iv_len);
+
+ a_len = prframe->pkt->len;
+
+ pdata = prframe->pkt->data;
+
+ while (a_len > ETH_HLEN) {
+ /* Offset 12 denote 2 mac address */
+ nSubframe_Length = get_unaligned_be16(pdata + 12);
+
+ if (a_len < (ETHERNET_HEADER_SIZE + nSubframe_Length)) {
+ DBG_88E("nRemain_Length is %d and nSubframe_Length is : %d\n", a_len, nSubframe_Length);
+ goto exit;
+ }
+
+ /* move the data point to data content */
+ pdata += ETH_HLEN;
+ a_len -= ETH_HLEN;
+
+ /* Allocate new skb for releasing to upper layer */
+ sub_skb = dev_alloc_skb(nSubframe_Length + 12);
+ if (sub_skb) {
+ skb_reserve(sub_skb, 12);
+ skb_put_data(sub_skb, pdata, nSubframe_Length);
+ } else {
+ sub_skb = skb_clone(prframe->pkt, GFP_ATOMIC);
+ if (sub_skb) {
+ sub_skb->data = pdata;
+ sub_skb->len = nSubframe_Length;
+ skb_set_tail_pointer(sub_skb, nSubframe_Length);
+ } else {
+ DBG_88E("skb_clone() Fail!!! , nr_subframes=%d\n", nr_subframes);
+ break;
+ }
+ }
+
+ subframes[nr_subframes++] = sub_skb;
+
+ if (nr_subframes >= MAX_SUBFRAME_COUNT) {
+ DBG_88E("ParseSubframe(): Too many Subframes! Packets dropped!\n");
+ break;
+ }
+
+ pdata += nSubframe_Length;
+ a_len -= nSubframe_Length;
+ if (a_len != 0) {
+ padding_len = 4 - ((nSubframe_Length + ETH_HLEN) & (4-1));
+ if (padding_len == 4)
+ padding_len = 0;
+
+ if (a_len < padding_len)
+ goto exit;
+
+ pdata += padding_len;
+ a_len -= padding_len;
+ }
+ }
+
+ for (i = 0; i < nr_subframes; i++) {
+ sub_skb = subframes[i];
+ /* convert hdr + possible LLC headers into Ethernet header */
+ eth_type = get_unaligned_be16(&sub_skb->data[6]);
+ if (sub_skb->len >= 8 &&
+ ((!memcmp(sub_skb->data, rtw_rfc1042_header, SNAP_SIZE) &&
+ eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) ||
+ !memcmp(sub_skb->data, rtw_bridge_tunnel_header, SNAP_SIZE))) {
+ /* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */
+ skb_pull(sub_skb, SNAP_SIZE);
+ memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src, ETH_ALEN);
+ memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst, ETH_ALEN);
+ } else {
+ __be16 len;
+ /* Leave Ethernet header part of hdr and full payload */
+ len = htons(sub_skb->len);
+ memcpy(skb_push(sub_skb, 2), &len, 2);
+ memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src, ETH_ALEN);
+ memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst, ETH_ALEN);
+ }
+
+ /* Indicate the packets to upper layer */
+ /* Insert NAT2.5 RX here! */
+ sub_skb->protocol = eth_type_trans(sub_skb, padapter->pnetdev);
+ sub_skb->dev = padapter->pnetdev;
+
+ sub_skb->ip_summed = CHECKSUM_NONE;
+
+ netif_rx(sub_skb);
+ }
+
+exit:
+ rtw_free_recvframe(prframe, pfree_recv_queue);/* free this recv_frame */
+
+ return _SUCCESS;
+}
+
+static int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num)
+{
+ u8 wsize = preorder_ctrl->wsize_b;
+ u16 wend = (preorder_ctrl->indicate_seq + wsize - 1) & 0xFFF;/* 4096; */
+
+ /* Rx Reorder initialize condition. */
+ if (preorder_ctrl->indicate_seq == 0xFFFF)
+ preorder_ctrl->indicate_seq = seq_num;
+
+ /* Drop out the packet which SeqNum is smaller than WinStart */
+ if (SN_LESS(seq_num, preorder_ctrl->indicate_seq))
+ return false;
+
+ /* */
+ /* Sliding window manipulation. Conditions includes: */
+ /* 1. Incoming SeqNum is equal to WinStart =>Window shift 1 */
+ /* 2. Incoming SeqNum is larger than the WinEnd => Window shift N */
+ /* */
+ if (SN_EQUAL(seq_num, preorder_ctrl->indicate_seq)) {
+ preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) & 0xFFF;
+ } else if (SN_LESS(wend, seq_num)) {
+ if (seq_num >= (wsize - 1))
+ preorder_ctrl->indicate_seq = seq_num + 1 - wsize;
+ else
+ preorder_ctrl->indicate_seq = 0xFFF - (wsize - (seq_num + 1)) + 1;
+ }
+
+ return true;
+}
+
+static int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl,
+ struct recv_frame *prframe)
+{
+ struct rx_pkt_attrib *pattrib = &prframe->attrib;
+ struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
+ struct list_head *phead, *plist;
+ struct recv_frame *hdr;
+ struct rx_pkt_attrib *pnextattrib;
+
+ phead = get_list_head(ppending_recvframe_queue);
+ plist = phead->next;
+
+ while (phead != plist) {
+ hdr = list_entry(plist, struct recv_frame, list);
+ pnextattrib = &hdr->attrib;
+
+ if (SN_LESS(pnextattrib->seq_num, pattrib->seq_num))
+ plist = plist->next;
+ else if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num))
+ return false;
+ else
+ break;
+ }
+
+ list_del_init(&prframe->list);
+
+ list_add_tail(&prframe->list, plist);
+ return true;
+}
+
+static int recv_indicatepkts_in_order(struct adapter *padapter, struct recv_reorder_ctrl *preorder_ctrl, int bforced)
+{
+ struct list_head *phead, *plist;
+ struct recv_frame *prframe;
+ struct recv_frame *prhdr;
+ struct rx_pkt_attrib *pattrib;
+ int bPktInBuf = false;
+ struct recv_priv *precvpriv = &padapter->recvpriv;
+ struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
+
+ phead = get_list_head(ppending_recvframe_queue);
+ plist = phead->next;
+
+ /* Handling some condition for forced indicate case. */
+ if (bforced) {
+ if (list_empty(phead))
+ return true;
+
+ prhdr = list_entry(plist, struct recv_frame, list);
+ pattrib = &prhdr->attrib;
+ preorder_ctrl->indicate_seq = pattrib->seq_num;
+ }
+
+ /* Prepare indication list and indication. */
+ /* Check if there is any packet need indicate. */
+ while (!list_empty(phead)) {
+ prhdr = list_entry(plist, struct recv_frame, list);
+ prframe = prhdr;
+ pattrib = &prframe->attrib;
+
+ if (!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
+ ("%s: indicate=%d seq=%d amsdu=%d\n",
+ __func__, preorder_ctrl->indicate_seq, pattrib->seq_num, pattrib->amsdu));
+ plist = plist->next;
+ list_del_init(&prframe->list);
+
+ if (SN_EQUAL(preorder_ctrl->indicate_seq, pattrib->seq_num))
+ preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) & 0xFFF;
+
+ /* Set this as a lock to make sure that only one thread is indicating packet. */
+
+ /* indicate this recv_frame */
+ if (!pattrib->amsdu) {
+ if ((!padapter->bDriverStopped) &&
+ (!padapter->bSurpriseRemoved))
+ rtw_recv_indicatepkt(padapter, prframe);/* indicate this recv_frame */
+ } else if (pattrib->amsdu == 1) {
+ if (amsdu_to_msdu(padapter, prframe) != _SUCCESS)
+ rtw_free_recvframe(prframe, &precvpriv->free_recv_queue);
+ } else {
+ /* error condition; */
+ }
+
+ /* Update local variables. */
+ bPktInBuf = false;
+ } else {
+ bPktInBuf = true;
+ break;
+ }
+ }
+ return bPktInBuf;
+}
+
+static int recv_indicatepkt_reorder(struct adapter *padapter,
+ struct recv_frame *prframe)
+{
+ int retval = _SUCCESS;
+ struct rx_pkt_attrib *pattrib = &prframe->attrib;
+ struct recv_reorder_ctrl *preorder_ctrl = prframe->preorder_ctrl;
+ struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
+
+ if (!pattrib->amsdu) {
+ /* s1. */
+ wlanhdr_to_ethhdr(prframe);
+
+ if ((pattrib->qos != 1) || (pattrib->eth_type == 0x0806) ||
+ (pattrib->ack_policy != 0)) {
+ if ((!padapter->bDriverStopped) &&
+ (!padapter->bSurpriseRemoved)) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("@@@@ %s -recv_func recv_indicatepkt\n", __func__));
+
+ rtw_recv_indicatepkt(padapter, prframe);
+ return _SUCCESS;
+ }
+
+ return _FAIL;
+ }
+
+ if (!preorder_ctrl->enable) {
+ /* indicate this recv_frame */
+ preorder_ctrl->indicate_seq = pattrib->seq_num;
+ rtw_recv_indicatepkt(padapter, prframe);
+
+ preorder_ctrl->indicate_seq =
+ (preorder_ctrl->indicate_seq + 1) % 4096;
+ return _SUCCESS;
+ }
+ } else if (pattrib->amsdu == 1) { /* temp filter -> means didn't support A-MSDUs in a A-MPDU */
+ if (!preorder_ctrl->enable) {
+ preorder_ctrl->indicate_seq = pattrib->seq_num;
+ retval = amsdu_to_msdu(padapter, prframe);
+
+ preorder_ctrl->indicate_seq =
+ (preorder_ctrl->indicate_seq + 1) % 4096;
+ return retval;
+ }
+ }
+
+ spin_lock_bh(&ppending_recvframe_queue->lock);
+
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
+ ("%s: indicate=%d seq=%d\n", __func__,
+ preorder_ctrl->indicate_seq, pattrib->seq_num));
+
+ /* s2. check if winstart_b(indicate_seq) needs to been updated */
+ if (!check_indicate_seq(preorder_ctrl, pattrib->seq_num)) {
+ rtw_recv_indicatepkt(padapter, prframe);
+
+ spin_unlock_bh(&ppending_recvframe_queue->lock);
+
+ goto _success_exit;
+ }
+
+ /* s3. Insert all packet into Reorder Queue to maintain its ordering. */
+ if (!enqueue_reorder_recvframe(preorder_ctrl, prframe))
+ goto _err_exit;
+
+ /* s4. */
+ /* Indication process. */
+ /* After Packet dropping and Sliding Window shifting as above, we can now just indicate the packets */
+ /* with the SeqNum smaller than latest WinStart and buffer other packets. */
+ /* */
+ /* For Rx Reorder condition: */
+ /* 1. All packets with SeqNum smaller than WinStart => Indicate */
+ /* 2. All packets with SeqNum larger than or equal to WinStart => Buffer it. */
+ /* */
+
+ /* recv_indicatepkts_in_order(padapter, preorder_ctrl, true); */
+ if (recv_indicatepkts_in_order(padapter, preorder_ctrl, false)) {
+ mod_timer(&preorder_ctrl->reordering_ctrl_timer,
+ jiffies + msecs_to_jiffies(REORDER_WAIT_TIME));
+ spin_unlock_bh(&ppending_recvframe_queue->lock);
+ } else {
+ spin_unlock_bh(&ppending_recvframe_queue->lock);
+ del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
+ }
+
+_success_exit:
+
+ return _SUCCESS;
+
+_err_exit:
+
+ spin_unlock_bh(&ppending_recvframe_queue->lock);
+
+ return _FAIL;
+}
+
+void rtw_reordering_ctrl_timeout_handler(struct timer_list *t)
+{
+ struct recv_reorder_ctrl *preorder_ctrl = from_timer(preorder_ctrl, t,
+ reordering_ctrl_timer);
+ struct adapter *padapter = preorder_ctrl->padapter;
+ struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
+
+ if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
+ return;
+
+ spin_lock_bh(&ppending_recvframe_queue->lock);
+
+ if (recv_indicatepkts_in_order(padapter, preorder_ctrl, true))
+ mod_timer(&preorder_ctrl->reordering_ctrl_timer,
+ jiffies + msecs_to_jiffies(REORDER_WAIT_TIME));
+
+ spin_unlock_bh(&ppending_recvframe_queue->lock);
+}
+
+static int process_recv_indicatepkts(struct adapter *padapter,
+ struct recv_frame *prframe)
+{
+ int retval = _SUCCESS;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
+
+ if (phtpriv->ht_option) { /* B/G/N Mode */
+ if (recv_indicatepkt_reorder(padapter, prframe) != _SUCCESS) {
+ /* including perform A-MPDU Rx Ordering Buffer Control */
+ if ((!padapter->bDriverStopped) &&
+ (!padapter->bSurpriseRemoved)) {
+ return _FAIL;
+ }
+ }
+ } else { /* B/G mode */
+ retval = wlanhdr_to_ethhdr(prframe);
+ if (retval != _SUCCESS) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("wlanhdr_to_ethhdr: drop pkt\n"));
+ return retval;
+ }
+
+ if ((!padapter->bDriverStopped) &&
+ (!padapter->bSurpriseRemoved)) {
+ /* indicate this recv_frame */
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("@@@@ %s- recv_func recv_indicatepkt\n", __func__));
+ rtw_recv_indicatepkt(padapter, prframe);
+ } else {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("@@@@ %s- recv_func free_indicatepkt\n", __func__));
+
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("recv_func:bDriverStopped(%d) OR bSurpriseRemoved(%d)", padapter->bDriverStopped, padapter->bSurpriseRemoved));
+ return _FAIL;
+ }
+ }
+
+ return retval;
+}
+
+static int recv_func_prehandle(struct adapter *padapter,
+ struct recv_frame *rframe)
+{
+ int ret = _SUCCESS;
+ struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
+
+ /* check the frame crtl field and decache */
+ ret = validate_recv_frame(padapter, rframe);
+ if (ret != _SUCCESS) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("recv_func: validate_recv_frame fail! drop pkt\n"));
+ rtw_free_recvframe(rframe, pfree_recv_queue);/* free this recv_frame */
+ goto exit;
+ }
+
+exit:
+ return ret;
+}
+
+static int recv_func_posthandle(struct adapter *padapter,
+ struct recv_frame *prframe)
+{
+ int ret = _SUCCESS;
+ struct recv_frame *orig_prframe = prframe;
+ struct recv_priv *precvpriv = &padapter->recvpriv;
+ struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
+
+ /* DATA FRAME */
+ led_control_8188eu(padapter, LED_CTL_RX);
+
+ prframe = decryptor(padapter, prframe);
+ if (!prframe) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("decryptor: drop pkt\n"));
+ ret = _FAIL;
+ goto _recv_data_drop;
+ }
+
+ prframe = recvframe_chk_defrag(padapter, prframe);
+ if (!prframe) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recvframe_chk_defrag: drop pkt\n"));
+ goto _recv_data_drop;
+ }
+
+ prframe = portctrl(padapter, prframe);
+ if (!prframe) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("portctrl: drop pkt\n"));
+ ret = _FAIL;
+ goto _recv_data_drop;
+ }
+
+ count_rx_stats(padapter, prframe, NULL);
+
+ ret = process_recv_indicatepkts(padapter, prframe);
+ if (ret != _SUCCESS) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recv_func: process_recv_indicatepkts fail!\n"));
+ rtw_free_recvframe(orig_prframe, pfree_recv_queue);/* free this recv_frame */
+ goto _recv_data_drop;
+ }
+ return ret;
+
+_recv_data_drop:
+ precvpriv->rx_drop++;
+ return ret;
+}
+
+static int recv_func(struct adapter *padapter, struct recv_frame *rframe)
+{
+ int ret;
+ struct rx_pkt_attrib *prxattrib = &rframe->attrib;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct mlme_priv *mlmepriv = &padapter->mlmepriv;
+
+ /* check if need to handle uc_swdec_pending_queue*/
+ if (check_fwstate(mlmepriv, WIFI_STATION_STATE) && psecuritypriv->busetkipkey) {
+ struct recv_frame *pending_frame;
+
+ while ((pending_frame = rtw_alloc_recvframe(&padapter->recvpriv.uc_swdec_pending_queue))) {
+ if (recv_func_posthandle(padapter, pending_frame) == _SUCCESS)
+ DBG_88E("%s: dequeue uc_swdec_pending_queue\n", __func__);
+ }
+ }
+
+ ret = recv_func_prehandle(padapter, rframe);
+
+ if (ret == _SUCCESS) {
+ /* check if need to enqueue into uc_swdec_pending_queue*/
+ if (check_fwstate(mlmepriv, WIFI_STATION_STATE) &&
+ !is_multicast_ether_addr(prxattrib->ra) &&
+ prxattrib->encrypt > 0 &&
+ prxattrib->bdecrypted == 0 &&
+ !is_wep_enc(psecuritypriv->dot11PrivacyAlgrthm) &&
+ !psecuritypriv->busetkipkey) {
+ rtw_enqueue_recvframe(rframe, &padapter->recvpriv.uc_swdec_pending_queue);
+ DBG_88E("%s: no key, enqueue uc_swdec_pending_queue\n", __func__);
+ goto exit;
+ }
+
+ ret = recv_func_posthandle(padapter, rframe);
+ }
+
+exit:
+ return ret;
+}
+
+s32 rtw_recv_entry(struct recv_frame *precvframe)
+{
+ struct adapter *padapter;
+ struct recv_priv *precvpriv;
+ s32 ret = _SUCCESS;
+
+ padapter = precvframe->adapter;
+
+ precvpriv = &padapter->recvpriv;
+
+ ret = recv_func(padapter, precvframe);
+ if (ret == _FAIL) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("%s: recv_func return fail!!!\n", __func__));
+ goto _recv_entry_drop;
+ }
+
+ precvpriv->rx_pkts++;
+
+ return ret;
+
+_recv_entry_drop:
+ return ret;
+}
+
+static void rtw_signal_stat_timer_hdl(struct timer_list *t)
+{
+ struct adapter *adapter =
+ from_timer(adapter, t, recvpriv.signal_stat_timer);
+ struct recv_priv *recvpriv = &adapter->recvpriv;
+
+ u32 tmp_s, tmp_q;
+ u8 avg_signal_strength = 0;
+ u8 avg_signal_qual = 0;
+ u8 _alpha = 3; /* this value is based on converging_constant = 5000 and sampling_interval = 1000 */
+
+ if (recvpriv->signal_strength_data.update_req == 0) {
+ /* update_req is clear, means we got rx */
+ avg_signal_strength = recvpriv->signal_strength_data.avg_val;
+ /* after avg_vals are acquired, we can re-stat the signal
+ * values
+ */
+ recvpriv->signal_strength_data.update_req = 1;
+ }
+
+ if (recvpriv->signal_qual_data.update_req == 0) {
+ /* update_req is clear, means we got rx */
+ avg_signal_qual = recvpriv->signal_qual_data.avg_val;
+ /* after avg_vals are acquired, we can re-stat the signal
+ * values
+ */
+ recvpriv->signal_qual_data.update_req = 1;
+ }
+
+ /* update value of signal_strength, rssi, signal_qual */
+ if (!check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY)) {
+ tmp_s = avg_signal_strength +
+ (_alpha - 1) * recvpriv->signal_strength;
+ tmp_s = DIV_ROUND_UP(tmp_s, _alpha);
+ if (tmp_s > 100)
+ tmp_s = 100;
+
+ tmp_q = avg_signal_qual +
+ (_alpha - 1) * recvpriv->signal_qual;
+ tmp_q = DIV_ROUND_UP(tmp_q, _alpha);
+ if (tmp_q > 100)
+ tmp_q = 100;
+
+ recvpriv->signal_strength = tmp_s;
+ recvpriv->rssi = (s8)translate_percentage_to_dbm(tmp_s);
+ recvpriv->signal_qual = tmp_q;
+ }
+
+ rtw_set_signal_stat_timer(recvpriv);
+}
diff --git a/drivers/staging/rtl8188eu/core/rtw_rf.c b/drivers/staging/rtl8188eu/core/rtw_rf.c
new file mode 100644
index 0000000..094aa15
--- /dev/null
+++ b/drivers/staging/rtl8188eu/core/rtw_rf.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _RTW_RF_C_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <recv_osdep.h>
+#include <xmit_osdep.h>
+
+struct ch_freq {
+ u32 channel;
+ u32 frequency;
+};
+
+static struct ch_freq ch_freq_map[] = {
+ {1, 2412}, {2, 2417}, {3, 2422}, {4, 2427}, {5, 2432},
+ {6, 2437}, {7, 2442}, {8, 2447}, {9, 2452}, {10, 2457},
+ {11, 2462}, {12, 2467}, {13, 2472}, {14, 2484},
+ /* UNII */
+ {36, 5180}, {40, 5200}, {44, 5220}, {48, 5240}, {52, 5260},
+ {56, 5280}, {60, 5300}, {64, 5320}, {149, 5745}, {153, 5765},
+ {157, 5785}, {161, 5805}, {165, 5825}, {167, 5835}, {169, 5845},
+ {171, 5855}, {173, 5865},
+ /* HiperLAN2 */
+ {100, 5500}, {104, 5520}, {108, 5540}, {112, 5560}, {116, 5580},
+ {120, 5600}, {124, 5620}, {128, 5640}, {132, 5660}, {136, 5680},
+ {140, 5700},
+ /* Japan MMAC */
+ {34, 5170}, {38, 5190}, {42, 5210}, {46, 5230},
+ /* Japan */
+ {184, 4920}, {188, 4940}, {192, 4960}, {196, 4980},
+ {208, 5040},/* Japan, means J08 */
+ {212, 5060},/* Japan, means J12 */
+ {216, 5080},/* Japan, means J16 */
+};
+
+static int ch_freq_map_num = ARRAY_SIZE(ch_freq_map);
+
+u32 rtw_ch2freq(u32 channel)
+{
+ u8 i;
+ u32 freq = 0;
+
+ for (i = 0; i < ch_freq_map_num; i++) {
+ if (channel == ch_freq_map[i].channel) {
+ freq = ch_freq_map[i].frequency;
+ break;
+ }
+ }
+ if (i == ch_freq_map_num)
+ freq = 2412;
+
+ return freq;
+}
diff --git a/drivers/staging/rtl8188eu/core/rtw_security.c b/drivers/staging/rtl8188eu/core/rtw_security.c
new file mode 100644
index 0000000..435c0fb
--- /dev/null
+++ b/drivers/staging/rtl8188eu/core/rtw_security.c
@@ -0,0 +1,1537 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _RTW_SECURITY_C_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <wifi.h>
+#include <osdep_intf.h>
+#include <net/lib80211.h>
+
+/* WEP related ===== */
+
+#define CRC32_POLY 0x04c11db7
+
+struct arc4context {
+ u32 x;
+ u32 y;
+ u8 state[256];
+};
+
+static void arcfour_init(struct arc4context *parc4ctx, u8 *key, u32 key_len)
+{
+ u32 t, u;
+ u32 keyindex;
+ u32 stateindex;
+ u8 *state;
+ u32 counter;
+
+ state = parc4ctx->state;
+ parc4ctx->x = 0;
+ parc4ctx->y = 0;
+ for (counter = 0; counter < 256; counter++)
+ state[counter] = (u8)counter;
+ keyindex = 0;
+ stateindex = 0;
+ for (counter = 0; counter < 256; counter++) {
+ t = state[counter];
+ stateindex = (stateindex + key[keyindex] + t) & 0xff;
+ u = state[stateindex];
+ state[stateindex] = (u8)t;
+ state[counter] = (u8)u;
+ if (++keyindex >= key_len)
+ keyindex = 0;
+ }
+}
+
+static u32 arcfour_byte(struct arc4context *parc4ctx)
+{
+ u32 x;
+ u32 y;
+ u32 sx, sy;
+ u8 *state;
+
+ state = parc4ctx->state;
+ x = (parc4ctx->x + 1) & 0xff;
+ sx = state[x];
+ y = (sx + parc4ctx->y) & 0xff;
+ sy = state[y];
+ parc4ctx->x = x;
+ parc4ctx->y = y;
+ state[y] = (u8)sx;
+ state[x] = (u8)sy;
+ return state[(sx + sy) & 0xff];
+}
+
+static void arcfour_encrypt(struct arc4context *parc4ctx, u8 *dest, u8 *src, u32 len)
+{
+ u32 i;
+
+ for (i = 0; i < len; i++)
+ dest[i] = src[i] ^ (unsigned char)arcfour_byte(parc4ctx);
+}
+
+static int bcrc32initialized;
+static u32 crc32_table[256];
+
+static u8 crc32_reverseBit(u8 data)
+{
+ return (u8)((data<<7)&0x80) | ((data<<5)&0x40) | ((data<<3)&0x20) |
+ ((data<<1)&0x10) | ((data>>1)&0x08) | ((data>>3)&0x04) |
+ ((data>>5)&0x02) | ((data>>7)&0x01);
+}
+
+static void crc32_init(void)
+{
+ int i, j;
+ u32 c;
+ u8 *p = (u8 *)&c, *p1;
+ u8 k;
+
+ if (bcrc32initialized == 1)
+ return;
+
+ c = 0x12340000;
+
+ for (i = 0; i < 256; ++i) {
+ k = crc32_reverseBit((u8)i);
+ for (c = ((u32)k) << 24, j = 8; j > 0; --j)
+ c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY : (c << 1);
+ p1 = (u8 *)&crc32_table[i];
+
+ p1[0] = crc32_reverseBit(p[3]);
+ p1[1] = crc32_reverseBit(p[2]);
+ p1[2] = crc32_reverseBit(p[1]);
+ p1[3] = crc32_reverseBit(p[0]);
+ }
+ bcrc32initialized = 1;
+}
+
+static __le32 getcrc32(u8 *buf, int len)
+{
+ u8 *p;
+ u32 crc;
+
+ if (bcrc32initialized == 0)
+ crc32_init();
+
+ crc = 0xffffffff; /* preload shift register, per CRC-32 spec */
+
+ for (p = buf; len > 0; ++p, --len)
+ crc = crc32_table[(crc ^ *p) & 0xff] ^ (crc >> 8);
+ return cpu_to_le32(~crc); /* transmit complement, per CRC-32 spec */
+}
+
+/*
+ Need to consider the fragment situation
+*/
+void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe)
+{
+ int curfragnum, length;
+ u8 *pframe;
+ u8 hw_hdr_offset = 0;
+ struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ const int keyindex = psecuritypriv->dot11PrivacyKeyIndex;
+ void *crypto_private;
+ struct sk_buff *skb;
+ struct lib80211_crypto_ops *crypto_ops;
+
+ if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
+ return;
+
+ if ((pattrib->encrypt != _WEP40_) && (pattrib->encrypt != _WEP104_))
+ return;
+
+ hw_hdr_offset = TXDESC_SIZE +
+ (((struct xmit_frame *)pxmitframe)->pkt_offset * PACKET_OFFSET_SZ);
+
+ pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset;
+
+ crypto_ops = lib80211_get_crypto_ops("WEP");
+
+ if (!crypto_ops)
+ return;
+
+ crypto_private = crypto_ops->init(keyindex);
+ if (!crypto_private)
+ return;
+
+ if (crypto_ops->set_key(psecuritypriv->dot11DefKey[keyindex].skey,
+ psecuritypriv->dot11DefKeylen[keyindex], NULL, crypto_private) < 0)
+ goto free_crypto_private;
+
+ for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
+ if (curfragnum + 1 == pattrib->nr_frags)
+ length = pattrib->last_txcmdsz;
+ else
+ length = pxmitpriv->frag_len;
+ skb = dev_alloc_skb(length);
+ if (!skb)
+ goto free_crypto_private;
+
+ skb_put_data(skb, pframe, length);
+
+ memmove(skb->data + 4, skb->data, pattrib->hdrlen);
+ skb_pull(skb, 4);
+ skb_trim(skb, skb->len - 4);
+
+ if (crypto_ops->encrypt_mpdu(skb, pattrib->hdrlen, crypto_private)) {
+ kfree_skb(skb);
+ goto free_crypto_private;
+ }
+
+ memcpy(pframe, skb->data, skb->len);
+
+ pframe += skb->len;
+ pframe = (u8 *)round_up((size_t)(pframe), 4);
+
+ kfree_skb(skb);
+ }
+
+free_crypto_private:
+ crypto_ops->deinit(crypto_private);
+}
+
+int rtw_wep_decrypt(struct adapter *padapter, u8 *precvframe)
+{
+ struct rx_pkt_attrib *prxattrib = &(((struct recv_frame *)precvframe)->attrib);
+
+ if ((prxattrib->encrypt == _WEP40_) || (prxattrib->encrypt == _WEP104_)) {
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct sk_buff *skb = ((struct recv_frame *)precvframe)->pkt;
+ u8 *pframe = skb->data;
+ void *crypto_private = NULL;
+ int status = _SUCCESS;
+ const int keyindex = prxattrib->key_index;
+ struct lib80211_crypto_ops *crypto_ops = lib80211_get_crypto_ops("WEP");
+ char iv[4], icv[4];
+
+ if (!crypto_ops) {
+ status = _FAIL;
+ goto exit;
+ }
+
+ memcpy(iv, pframe + prxattrib->hdrlen, 4);
+ memcpy(icv, pframe + skb->len - 4, 4);
+
+ crypto_private = crypto_ops->init(keyindex);
+ if (!crypto_private) {
+ status = _FAIL;
+ goto exit;
+ }
+ if (crypto_ops->set_key(psecuritypriv->dot11DefKey[keyindex].skey,
+ psecuritypriv->dot11DefKeylen[keyindex], NULL, crypto_private) < 0) {
+ status = _FAIL;
+ goto exit;
+ }
+ if (crypto_ops->decrypt_mpdu(skb, prxattrib->hdrlen, crypto_private)) {
+ status = _FAIL;
+ goto exit;
+ }
+
+ memmove(pframe, pframe + 4, prxattrib->hdrlen);
+ skb_push(skb, 4);
+ skb_put(skb, 4);
+
+ memcpy(pframe + prxattrib->hdrlen, iv, 4);
+ memcpy(pframe + skb->len - 4, icv, 4);
+
+exit:
+ if (crypto_ops && crypto_private)
+ crypto_ops->deinit(crypto_private);
+ return status;
+ }
+
+ return _FAIL;
+}
+
+/* 3 ===== TKIP related ===== */
+
+static u32 secmicgetuint32(u8 *p)
+/* Convert from Byte[] to Us3232 in a portable way */
+{
+ s32 i;
+ u32 res = 0;
+
+ for (i = 0; i < 4; i++)
+ res |= ((u32)(*p++)) << (8*i);
+ return res;
+}
+
+static void secmicputuint32(u8 *p, u32 val)
+/* Convert from Us3232 to Byte[] in a portable way */
+{
+ long i;
+
+ for (i = 0; i < 4; i++) {
+ *p++ = (u8)(val & 0xff);
+ val >>= 8;
+ }
+}
+
+static void secmicclear(struct mic_data *pmicdata)
+{
+/* Reset the state to the empty message. */
+ pmicdata->L = pmicdata->K0;
+ pmicdata->R = pmicdata->K1;
+ pmicdata->nBytesInM = 0;
+ pmicdata->M = 0;
+}
+
+void rtw_secmicsetkey(struct mic_data *pmicdata, u8 *key)
+{
+ /* Set the key */
+ pmicdata->K0 = secmicgetuint32(key);
+ pmicdata->K1 = secmicgetuint32(key + 4);
+ /* and reset the message */
+ secmicclear(pmicdata);
+}
+
+void rtw_secmicappendbyte(struct mic_data *pmicdata, u8 b)
+{
+ /* Append the byte to our word-sized buffer */
+ pmicdata->M |= ((unsigned long)b) << (8*pmicdata->nBytesInM);
+ pmicdata->nBytesInM++;
+ /* Process the word if it is full. */
+ if (pmicdata->nBytesInM >= 4) {
+ pmicdata->L ^= pmicdata->M;
+ pmicdata->R ^= ROL32(pmicdata->L, 17);
+ pmicdata->L += pmicdata->R;
+ pmicdata->R ^= ((pmicdata->L & 0xff00ff00) >> 8) | ((pmicdata->L & 0x00ff00ff) << 8);
+ pmicdata->L += pmicdata->R;
+ pmicdata->R ^= ROL32(pmicdata->L, 3);
+ pmicdata->L += pmicdata->R;
+ pmicdata->R ^= ROR32(pmicdata->L, 2);
+ pmicdata->L += pmicdata->R;
+ /* Clear the buffer */
+ pmicdata->M = 0;
+ pmicdata->nBytesInM = 0;
+ }
+}
+
+void rtw_secmicappend(struct mic_data *pmicdata, u8 *src, u32 nbytes)
+{
+ /* This is simple */
+ while (nbytes > 0) {
+ rtw_secmicappendbyte(pmicdata, *src++);
+ nbytes--;
+ }
+}
+
+void rtw_secgetmic(struct mic_data *pmicdata, u8 *dst)
+{
+ /* Append the minimum padding */
+ rtw_secmicappendbyte(pmicdata, 0x5a);
+ rtw_secmicappendbyte(pmicdata, 0);
+ rtw_secmicappendbyte(pmicdata, 0);
+ rtw_secmicappendbyte(pmicdata, 0);
+ rtw_secmicappendbyte(pmicdata, 0);
+ /* and then zeroes until the length is a multiple of 4 */
+ while (pmicdata->nBytesInM != 0)
+ rtw_secmicappendbyte(pmicdata, 0);
+ /* The appendByte function has already computed the result. */
+ secmicputuint32(dst, pmicdata->L);
+ secmicputuint32(dst+4, pmicdata->R);
+ /* Reset to the empty message. */
+ secmicclear(pmicdata);
+}
+
+void rtw_seccalctkipmic(u8 *key, u8 *header, u8 *data, u32 data_len, u8 *mic_code, u8 pri)
+{
+ struct mic_data micdata;
+ u8 priority[4] = {0x0, 0x0, 0x0, 0x0};
+
+ rtw_secmicsetkey(&micdata, key);
+ priority[0] = pri;
+
+ /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */
+ if (header[1]&1) { /* ToDS == 1 */
+ rtw_secmicappend(&micdata, &header[16], 6); /* DA */
+ if (header[1]&2) /* From Ds == 1 */
+ rtw_secmicappend(&micdata, &header[24], 6);
+ else
+ rtw_secmicappend(&micdata, &header[10], 6);
+ } else { /* ToDS == 0 */
+ rtw_secmicappend(&micdata, &header[4], 6); /* DA */
+ if (header[1]&2) /* From Ds == 1 */
+ rtw_secmicappend(&micdata, &header[16], 6);
+ else
+ rtw_secmicappend(&micdata, &header[10], 6);
+ }
+ rtw_secmicappend(&micdata, &priority[0], 4);
+
+ rtw_secmicappend(&micdata, data, data_len);
+
+ rtw_secgetmic(&micdata, mic_code);
+}
+
+
+
+/* macros for extraction/creation of unsigned char/unsigned short values */
+#define RotR1(v16) ((((v16) >> 1) & 0x7FFF) ^ (((v16) & 1) << 15))
+#define Lo8(v16) ((u8)((v16) & 0x00FF))
+#define Hi8(v16) ((u8)(((v16) >> 8) & 0x00FF))
+#define Lo16(v32) ((u16)((v32) & 0xFFFF))
+#define Hi16(v32) ((u16)(((v32) >> 16) & 0xFFFF))
+#define Mk16(hi, lo) ((lo) ^ (((u16)(hi)) << 8))
+
+/* select the Nth 16-bit word of the temporal key unsigned char array TK[] */
+#define TK16(N) Mk16(tk[2*(N)+1], tk[2*(N)])
+
+/* S-box lookup: 16 bits --> 16 bits */
+#define _S_(v16) (Sbox1[0][Lo8(v16)] ^ Sbox1[1][Hi8(v16)])
+
+/* fixed algorithm "parameters" */
+#define PHASE1_LOOP_CNT 8 /* this needs to be "big enough" */
+#define TA_SIZE 6 /* 48-bit transmitter address */
+#define TK_SIZE 16 /* 128-bit temporal key */
+#define P1K_SIZE 10 /* 80-bit Phase1 key */
+#define RC4_KEY_SIZE 16 /* 128-bit RC4KEY (104 bits unknown) */
+
+/* 2-unsigned char by 2-unsigned char subset of the full AES S-box table */
+static const unsigned short Sbox1[2][256] = { /* Sbox for hash (can be in ROM) */
+{
+ 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
+ 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
+ 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
+ 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
+ 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
+ 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
+ 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
+ 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
+ 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
+ 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
+ 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
+ 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
+ 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
+ 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
+ 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
+ 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
+ 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
+ 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
+ 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
+ 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
+ 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
+ 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
+ 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
+ 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
+ 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
+ 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
+ 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
+ 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
+ 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
+ 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
+ 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
+ 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
+ },
+
+ { /* second half of table is unsigned char-reversed version of first! */
+ 0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491,
+ 0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC,
+ 0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB,
+ 0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B,
+ 0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83,
+ 0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A,
+ 0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F,
+ 0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA,
+ 0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B,
+ 0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713,
+ 0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6,
+ 0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85,
+ 0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411,
+ 0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B,
+ 0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1,
+ 0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF,
+ 0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E,
+ 0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6,
+ 0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B,
+ 0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD,
+ 0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8,
+ 0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2,
+ 0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049,
+ 0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810,
+ 0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197,
+ 0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F,
+ 0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C,
+ 0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927,
+ 0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733,
+ 0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5,
+ 0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0,
+ 0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C,
+ }
+};
+
+ /*
+**********************************************************************
+* Routine: Phase 1 -- generate P1K, given TA, TK, IV32
+*
+* Inputs:
+* tk[] = temporal key [128 bits]
+* ta[] = transmitter's MAC address [ 48 bits]
+* iv32 = upper 32 bits of IV [ 32 bits]
+* Output:
+* p1k[] = Phase 1 key [ 80 bits]
+*
+* Note:
+* This function only needs to be called every 2**16 packets,
+* although in theory it could be called every packet.
+*
+**********************************************************************
+*/
+static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32)
+{
+ int i;
+ /* Initialize the 80 bits of P1K[] from IV32 and TA[0..5] */
+ p1k[0] = Lo16(iv32);
+ p1k[1] = Hi16(iv32);
+ p1k[2] = Mk16(ta[1], ta[0]); /* use TA[] as little-endian */
+ p1k[3] = Mk16(ta[3], ta[2]);
+ p1k[4] = Mk16(ta[5], ta[4]);
+
+ /* Now compute an unbalanced Feistel cipher with 80-bit block */
+ /* size on the 80-bit block P1K[], using the 128-bit key TK[] */
+ for (i = 0; i < PHASE1_LOOP_CNT; i++) { /* Each add operation here is mod 2**16 */
+ p1k[0] += _S_(p1k[4] ^ TK16((i&1)+0));
+ p1k[1] += _S_(p1k[0] ^ TK16((i&1)+2));
+ p1k[2] += _S_(p1k[1] ^ TK16((i&1)+4));
+ p1k[3] += _S_(p1k[2] ^ TK16((i&1)+6));
+ p1k[4] += _S_(p1k[3] ^ TK16((i&1)+0));
+ p1k[4] += (unsigned short)i; /* avoid "slide attacks" */
+ }
+}
+
+/*
+**********************************************************************
+* Routine: Phase 2 -- generate RC4KEY, given TK, P1K, IV16
+*
+* Inputs:
+* tk[] = Temporal key [128 bits]
+* p1k[] = Phase 1 output key [ 80 bits]
+* iv16 = low 16 bits of IV counter [ 16 bits]
+* Output:
+* rc4key[] = the key used to encrypt the packet [128 bits]
+*
+* Note:
+* The value {TA, IV32, IV16} for Phase1/Phase2 must be unique
+* across all packets using the same key TK value. Then, for a
+* given value of TK[], this TKIP48 construction guarantees that
+* the final RC4KEY value is unique across all packets.
+*
+* Suggested implementation optimization: if PPK[] is "overlaid"
+* appropriately on RC4KEY[], there is no need for the final
+* for loop below that copies the PPK[] result into RC4KEY[].
+*
+**********************************************************************
+*/
+static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16)
+{
+ int i;
+ u16 PPK[6]; /* temporary key for mixing */
+ /* Note: all adds in the PPK[] equations below are mod 2**16 */
+ for (i = 0; i < 5; i++)
+ PPK[i] = p1k[i]; /* first, copy P1K to PPK */
+ PPK[5] = p1k[4] + iv16; /* next, add in IV16 */
+
+ /* Bijective non-linear mixing of the 96 bits of PPK[0..5] */
+ PPK[0] += _S_(PPK[5] ^ TK16(0)); /* Mix key in each "round" */
+ PPK[1] += _S_(PPK[0] ^ TK16(1));
+ PPK[2] += _S_(PPK[1] ^ TK16(2));
+ PPK[3] += _S_(PPK[2] ^ TK16(3));
+ PPK[4] += _S_(PPK[3] ^ TK16(4));
+ PPK[5] += _S_(PPK[4] ^ TK16(5)); /* Total # S-box lookups == 6 */
+
+ /* Final sweep: bijective, "linear". Rotates kill LSB correlations */
+ PPK[0] += RotR1(PPK[5] ^ TK16(6));
+ PPK[1] += RotR1(PPK[0] ^ TK16(7)); /* Use all of TK[] in Phase2 */
+ PPK[2] += RotR1(PPK[1]);
+ PPK[3] += RotR1(PPK[2]);
+ PPK[4] += RotR1(PPK[3]);
+ PPK[5] += RotR1(PPK[4]);
+ /* Note: At this point, for a given key TK[0..15], the 96-bit output */
+ /* value PPK[0..5] is guaranteed to be unique, as a function */
+ /* of the 96-bit "input" value {TA, IV32, IV16}. That is, P1K */
+ /* is now a keyed permutation of {TA, IV32, IV16}. */
+
+ /* Set RC4KEY[0..3], which includes "cleartext" portion of RC4 key */
+ rc4key[0] = Hi8(iv16); /* RC4KEY[0..2] is the WEP IV */
+ rc4key[1] = (Hi8(iv16) | 0x20) & 0x7F; /* Help avoid weak (FMS) keys */
+ rc4key[2] = Lo8(iv16);
+ rc4key[3] = Lo8((PPK[5] ^ TK16(0)) >> 1);
+
+ /* Copy 96 bits of PPK[0..5] to RC4KEY[4..15] (little-endian) */
+ for (i = 0; i < 6; i++) {
+ rc4key[4+2*i] = Lo8(PPK[i]);
+ rc4key[5+2*i] = Hi8(PPK[i]);
+ }
+}
+
+/* The hlen isn't include the IV */
+u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe)
+{ /* exclude ICV */
+ u16 pnl;
+ u32 pnh;
+ u8 rc4key[16];
+ u8 ttkey[16];
+ u8 crc[4];
+ u8 hw_hdr_offset = 0;
+ struct arc4context mycontext;
+ int curfragnum, length;
+
+ u8 *pframe, *payload, *iv, *prwskey;
+ union pn48 dot11txpn;
+ struct sta_info *stainfo;
+ struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ u32 res = _SUCCESS;
+
+ if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
+ return _FAIL;
+
+ hw_hdr_offset = TXDESC_SIZE +
+ (((struct xmit_frame *)pxmitframe)->pkt_offset * PACKET_OFFSET_SZ);
+ pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset;
+ /* 4 start to encrypt each fragment */
+ if (pattrib->encrypt == _TKIP_) {
+ if (pattrib->psta)
+ stainfo = pattrib->psta;
+ else
+ stainfo = rtw_get_stainfo(&padapter->stapriv, &pattrib->ra[0]);
+
+ if (stainfo != NULL) {
+ RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("%s: stainfo!= NULL!!!\n", __func__));
+
+ if (is_multicast_ether_addr(pattrib->ra))
+ prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
+ else
+ prwskey = &stainfo->dot118021x_UncstKey.skey[0];
+
+ for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
+ iv = pframe+pattrib->hdrlen;
+ payload = pframe+pattrib->iv_len+pattrib->hdrlen;
+
+ GET_TKIP_PN(iv, dot11txpn);
+
+ pnl = (u16)(dot11txpn.val);
+ pnh = (u32)(dot11txpn.val>>16);
+ phase1((u16 *)&ttkey[0], prwskey, &pattrib->ta[0], pnh);
+ phase2(&rc4key[0], prwskey, (u16 *)&ttkey[0], pnl);
+
+ if ((curfragnum+1) == pattrib->nr_frags) { /* 4 the last fragment */
+ length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
+ RT_TRACE(_module_rtl871x_security_c_, _drv_info_,
+ ("pattrib->iv_len=%x, pattrib->icv_len=%x\n",
+ pattrib->iv_len, pattrib->icv_len));
+ *((__le32 *)crc) = getcrc32(payload, length);/* modified by Amy*/
+
+ arcfour_init(&mycontext, rc4key, 16);
+ arcfour_encrypt(&mycontext, payload, payload, length);
+ arcfour_encrypt(&mycontext, payload+length, crc, 4);
+ } else {
+ length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
+ *((__le32 *)crc) = getcrc32(payload, length);/* modified by Amy*/
+ arcfour_init(&mycontext, rc4key, 16);
+ arcfour_encrypt(&mycontext, payload, payload, length);
+ arcfour_encrypt(&mycontext, payload+length, crc, 4);
+
+ pframe += pxmitpriv->frag_len;
+ pframe = (u8 *)round_up((size_t)(pframe), 4);
+ }
+ }
+ } else {
+ RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("%s: stainfo==NULL!!!\n", __func__));
+ res = _FAIL;
+ }
+ }
+ return res;
+}
+
+/* The hlen isn't include the IV */
+u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe)
+{ /* exclude ICV */
+ u16 pnl;
+ u32 pnh;
+ u8 rc4key[16];
+ u8 ttkey[16];
+ u8 crc[4];
+ struct arc4context mycontext;
+ int length;
+
+ u8 *pframe, *payload, *iv, *prwskey;
+ union pn48 dot11txpn;
+ struct sta_info *stainfo;
+ struct rx_pkt_attrib *prxattrib = &((struct recv_frame *)precvframe)->attrib;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ u32 res = _SUCCESS;
+
+
+ pframe = (unsigned char *)((struct recv_frame *)precvframe)->pkt->data;
+
+ /* 4 start to decrypt recvframe */
+ if (prxattrib->encrypt == _TKIP_) {
+ stainfo = rtw_get_stainfo(&padapter->stapriv, &prxattrib->ta[0]);
+ if (stainfo) {
+ if (is_multicast_ether_addr(prxattrib->ra)) {
+ if (!psecuritypriv->binstallGrpkey) {
+ res = _FAIL;
+ DBG_88E("%s:rx bc/mc packets, but didn't install group key!!!!!!!!!!\n", __func__);
+ goto exit;
+ }
+ prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey;
+ } else {
+ RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("%s: stainfo!= NULL!!!\n", __func__));
+ prwskey = &stainfo->dot118021x_UncstKey.skey[0];
+ }
+
+ iv = pframe+prxattrib->hdrlen;
+ payload = pframe+prxattrib->iv_len+prxattrib->hdrlen;
+ length = ((struct recv_frame *)precvframe)->pkt->len-prxattrib->hdrlen-prxattrib->iv_len;
+
+ GET_TKIP_PN(iv, dot11txpn);
+
+ pnl = (u16)(dot11txpn.val);
+ pnh = (u32)(dot11txpn.val>>16);
+
+ phase1((u16 *)&ttkey[0], prwskey, &prxattrib->ta[0], pnh);
+ phase2(&rc4key[0], prwskey, (unsigned short *)&ttkey[0], pnl);
+
+ /* 4 decrypt payload include icv */
+
+ arcfour_init(&mycontext, rc4key, 16);
+ arcfour_encrypt(&mycontext, payload, payload, length);
+
+ *((__le32 *)crc) = getcrc32(payload, length-4);
+
+ if (crc[3] != payload[length-1] ||
+ crc[2] != payload[length-2] ||
+ crc[1] != payload[length-3] ||
+ crc[0] != payload[length-4]) {
+ RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
+ ("rtw_wep_decrypt:icv error crc (%4ph)!=payload (%4ph)\n",
+ &crc, &payload[length-4]));
+ res = _FAIL;
+ }
+ } else {
+ RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_decrypt: stainfo==NULL!!!\n"));
+ res = _FAIL;
+ }
+ }
+exit:
+ return res;
+}
+
+/* 3 ===== AES related ===== */
+
+
+#define MAX_MSG_SIZE 2048
+/*****************************/
+/******** SBOX Table *********/
+/*****************************/
+
+static u8 sbox_table[256] = {
+ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
+ 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
+ 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
+ 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
+ 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
+ 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
+ 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
+ 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
+ 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
+ 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
+ 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
+ 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
+ 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
+ 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
+ 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
+ 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
+ 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
+};
+
+/*****************************/
+/**** Function Prototypes ****/
+/*****************************/
+
+static void bitwise_xor(u8 *ina, u8 *inb, u8 *out);
+static void construct_mic_iv(u8 *mic_header1, int qc_exists, int a4_exists, u8 *mpdu, uint payload_length, u8 *pn_vector);
+static void construct_mic_header1(u8 *mic_header1, int header_length, u8 *mpdu);
+static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, int a4_exists, int qc_exists);
+static void construct_ctr_preload(u8 *ctr_preload, int a4_exists, int qc_exists, u8 *mpdu, u8 *pn_vector, int c);
+static void xor_128(u8 *a, u8 *b, u8 *out);
+static void xor_32(u8 *a, u8 *b, u8 *out);
+static u8 sbox(u8 a);
+static void next_key(u8 *key, int round);
+static void byte_sub(u8 *in, u8 *out);
+static void shift_row(u8 *in, u8 *out);
+static void mix_column(u8 *in, u8 *out);
+static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext);
+
+/****************************************/
+/* aes128k128d() */
+/* Performs a 128 bit AES encrypt with */
+/* 128 bit data. */
+/****************************************/
+static void xor_128(u8 *a, u8 *b, u8 *out)
+{
+ int i;
+
+ for (i = 0; i < 16; i++)
+ out[i] = a[i] ^ b[i];
+}
+
+static void xor_32(u8 *a, u8 *b, u8 *out)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ out[i] = a[i] ^ b[i];
+}
+
+static u8 sbox(u8 a)
+{
+ return sbox_table[(int)a];
+}
+
+static void next_key(u8 *key, int round)
+{
+ u8 rcon;
+ u8 sbox_key[4];
+ u8 rcon_table[12] = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
+ 0x1b, 0x36, 0x36, 0x36
+ };
+
+ sbox_key[0] = sbox(key[13]);
+ sbox_key[1] = sbox(key[14]);
+ sbox_key[2] = sbox(key[15]);
+ sbox_key[3] = sbox(key[12]);
+
+ rcon = rcon_table[round];
+
+ xor_32(&key[0], sbox_key, &key[0]);
+ key[0] = key[0] ^ rcon;
+
+ xor_32(&key[4], &key[0], &key[4]);
+ xor_32(&key[8], &key[4], &key[8]);
+ xor_32(&key[12], &key[8], &key[12]);
+}
+
+static void byte_sub(u8 *in, u8 *out)
+{
+ int i;
+ for (i = 0; i < 16; i++)
+ out[i] = sbox(in[i]);
+}
+
+static void shift_row(u8 *in, u8 *out)
+{
+ out[0] = in[0];
+ out[1] = in[5];
+ out[2] = in[10];
+ out[3] = in[15];
+ out[4] = in[4];
+ out[5] = in[9];
+ out[6] = in[14];
+ out[7] = in[3];
+ out[8] = in[8];
+ out[9] = in[13];
+ out[10] = in[2];
+ out[11] = in[7];
+ out[12] = in[12];
+ out[13] = in[1];
+ out[14] = in[6];
+ out[15] = in[11];
+}
+
+static void mix_column(u8 *in, u8 *out)
+{
+ int i;
+ u8 add1b[4];
+ u8 add1bf7[4];
+ u8 rotl[4];
+ u8 swap_halves[4];
+ u8 andf7[4];
+ u8 rotr[4];
+ u8 temp[4];
+ u8 tempb[4];
+
+ for (i = 0 ; i < 4; i++) {
+ if ((in[i] & 0x80) == 0x80)
+ add1b[i] = 0x1b;
+ else
+ add1b[i] = 0x00;
+ }
+
+ swap_halves[0] = in[2]; /* Swap halves */
+ swap_halves[1] = in[3];
+ swap_halves[2] = in[0];
+ swap_halves[3] = in[1];
+
+ rotl[0] = in[3]; /* Rotate left 8 bits */
+ rotl[1] = in[0];
+ rotl[2] = in[1];
+ rotl[3] = in[2];
+
+ andf7[0] = in[0] & 0x7f;
+ andf7[1] = in[1] & 0x7f;
+ andf7[2] = in[2] & 0x7f;
+ andf7[3] = in[3] & 0x7f;
+
+ for (i = 3; i > 0; i--) { /* logical shift left 1 bit */
+ andf7[i] = andf7[i] << 1;
+ if ((andf7[i-1] & 0x80) == 0x80)
+ andf7[i] = (andf7[i] | 0x01);
+ }
+ andf7[0] = andf7[0] << 1;
+ andf7[0] = andf7[0] & 0xfe;
+
+ xor_32(add1b, andf7, add1bf7);
+
+ xor_32(in, add1bf7, rotr);
+
+ temp[0] = rotr[0]; /* Rotate right 8 bits */
+ rotr[0] = rotr[1];
+ rotr[1] = rotr[2];
+ rotr[2] = rotr[3];
+ rotr[3] = temp[0];
+
+ xor_32(add1bf7, rotr, temp);
+ xor_32(swap_halves, rotl, tempb);
+ xor_32(temp, tempb, out);
+}
+
+static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext)
+{
+ int round;
+ int i;
+ u8 intermediatea[16];
+ u8 intermediateb[16];
+ u8 round_key[16];
+
+ for (i = 0; i < 16; i++)
+ round_key[i] = key[i];
+ for (round = 0; round < 11; round++) {
+ if (round == 0) {
+ xor_128(round_key, data, ciphertext);
+ next_key(round_key, round);
+ } else if (round == 10) {
+ byte_sub(ciphertext, intermediatea);
+ shift_row(intermediatea, intermediateb);
+ xor_128(intermediateb, round_key, ciphertext);
+ } else { /* 1 - 9 */
+ byte_sub(ciphertext, intermediatea);
+ shift_row(intermediatea, intermediateb);
+ mix_column(&intermediateb[0], &intermediatea[0]);
+ mix_column(&intermediateb[4], &intermediatea[4]);
+ mix_column(&intermediateb[8], &intermediatea[8]);
+ mix_column(&intermediateb[12], &intermediatea[12]);
+ xor_128(intermediatea, round_key, ciphertext);
+ next_key(round_key, round);
+ }
+ }
+}
+
+/************************************************/
+/* construct_mic_iv() */
+/* Builds the MIC IV from header fields and PN */
+/************************************************/
+static void construct_mic_iv(u8 *mic_iv, int qc_exists, int a4_exists, u8 *mpdu,
+ uint payload_length, u8 *pn_vector)
+{
+ int i;
+
+ mic_iv[0] = 0x59;
+ if (qc_exists && a4_exists)
+ mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */
+ if (qc_exists && !a4_exists)
+ mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */
+ if (!qc_exists)
+ mic_iv[1] = 0x00;
+ for (i = 2; i < 8; i++)
+ mic_iv[i] = mpdu[i + 8]; /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */
+ for (i = 8; i < 14; i++)
+ mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */
+ mic_iv[14] = (unsigned char)(payload_length / 256);
+ mic_iv[15] = (unsigned char)(payload_length % 256);
+}
+
+/************************************************/
+/* construct_mic_header1() */
+/* Builds the first MIC header block from */
+/* header fields. */
+/************************************************/
+static void construct_mic_header1(u8 *mic_header1, int header_length, u8 *mpdu)
+{
+ mic_header1[0] = (u8)((header_length - 2) / 256);
+ mic_header1[1] = (u8)((header_length - 2) % 256);
+ mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */
+ mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */
+ mic_header1[4] = mpdu[4]; /* A1 */
+ mic_header1[5] = mpdu[5];
+ mic_header1[6] = mpdu[6];
+ mic_header1[7] = mpdu[7];
+ mic_header1[8] = mpdu[8];
+ mic_header1[9] = mpdu[9];
+ mic_header1[10] = mpdu[10]; /* A2 */
+ mic_header1[11] = mpdu[11];
+ mic_header1[12] = mpdu[12];
+ mic_header1[13] = mpdu[13];
+ mic_header1[14] = mpdu[14];
+ mic_header1[15] = mpdu[15];
+}
+
+/************************************************/
+/* construct_mic_header2() */
+/* Builds the last MIC header block from */
+/* header fields. */
+/************************************************/
+static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, int a4_exists, int qc_exists)
+{
+ int i;
+
+ for (i = 0; i < 16; i++)
+ mic_header2[i] = 0x00;
+
+ mic_header2[0] = mpdu[16]; /* A3 */
+ mic_header2[1] = mpdu[17];
+ mic_header2[2] = mpdu[18];
+ mic_header2[3] = mpdu[19];
+ mic_header2[4] = mpdu[20];
+ mic_header2[5] = mpdu[21];
+
+ mic_header2[6] = 0x00;
+ mic_header2[7] = 0x00; /* mpdu[23]; */
+
+ if (!qc_exists && a4_exists) {
+ for (i = 0; i < 6; i++)
+ mic_header2[8+i] = mpdu[24+i]; /* A4 */
+ }
+
+ if (qc_exists && !a4_exists) {
+ mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */
+ mic_header2[9] = mpdu[25] & 0x00;
+ }
+
+ if (qc_exists && a4_exists) {
+ for (i = 0; i < 6; i++)
+ mic_header2[8+i] = mpdu[24+i]; /* A4 */
+
+ mic_header2[14] = mpdu[30] & 0x0f;
+ mic_header2[15] = mpdu[31] & 0x00;
+ }
+}
+
+/************************************************/
+/* construct_mic_header2() */
+/* Builds the last MIC header block from */
+/* header fields. */
+/************************************************/
+static void construct_ctr_preload(u8 *ctr_preload, int a4_exists, int qc_exists, u8 *mpdu, u8 *pn_vector, int c)
+{
+ int i;
+
+ for (i = 0; i < 16; i++)
+ ctr_preload[i] = 0x00;
+ i = 0;
+
+ ctr_preload[0] = 0x01; /* flag */
+ if (qc_exists && a4_exists)
+ ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */
+ if (qc_exists && !a4_exists)
+ ctr_preload[1] = mpdu[24] & 0x0f;
+
+ for (i = 2; i < 8; i++)
+ ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */
+ for (i = 8; i < 14; i++)
+ ctr_preload[i] = pn_vector[13 - i]; /* ctr_preload[8:13] = PN[5:0] */
+ ctr_preload[14] = (unsigned char)(c / 256); /* Ctr */
+ ctr_preload[15] = (unsigned char)(c % 256);
+}
+
+/************************************/
+/* bitwise_xor() */
+/* A 128 bit, bitwise exclusive or */
+/************************************/
+static void bitwise_xor(u8 *ina, u8 *inb, u8 *out)
+{
+ int i;
+
+ for (i = 0; i < 16; i++)
+ out[i] = ina[i] ^ inb[i];
+}
+
+static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen)
+{
+ uint qc_exists, a4_exists, i, j, payload_remainder,
+ num_blocks, payload_index;
+
+ u8 pn_vector[6];
+ u8 mic_iv[16];
+ u8 mic_header1[16];
+ u8 mic_header2[16];
+ u8 ctr_preload[16];
+
+ /* Intermediate Buffers */
+ u8 chain_buffer[16];
+ u8 aes_out[16];
+ u8 padded_buffer[16];
+ u8 mic[8];
+ uint frtype = GetFrameType(pframe);
+ uint frsubtype = GetFrameSubType(pframe);
+
+ frsubtype >>= 4;
+
+ memset(mic_iv, 0, 16);
+ memset(mic_header1, 0, 16);
+ memset(mic_header2, 0, 16);
+ memset(ctr_preload, 0, 16);
+ memset(chain_buffer, 0, 16);
+ memset(aes_out, 0, 16);
+ memset(padded_buffer, 0, 16);
+
+ if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen == WLAN_HDR_A3_QOS_LEN))
+ a4_exists = 0;
+ else
+ a4_exists = 1;
+
+ if ((frtype == WIFI_DATA_CFACK) || (frtype == WIFI_DATA_CFPOLL) || (frtype == WIFI_DATA_CFACKPOLL)) {
+ qc_exists = 1;
+ if (hdrlen != WLAN_HDR_A3_QOS_LEN)
+ hdrlen += 2;
+ } else if ((frsubtype == 0x08) || (frsubtype == 0x09) || (frsubtype == 0x0a) || (frsubtype == 0x0b)) {
+ if (hdrlen != WLAN_HDR_A3_QOS_LEN)
+ hdrlen += 2;
+ qc_exists = 1;
+ } else {
+ qc_exists = 0;
+ }
+
+ pn_vector[0] = pframe[hdrlen];
+ pn_vector[1] = pframe[hdrlen+1];
+ pn_vector[2] = pframe[hdrlen+4];
+ pn_vector[3] = pframe[hdrlen+5];
+ pn_vector[4] = pframe[hdrlen+6];
+ pn_vector[5] = pframe[hdrlen+7];
+
+ construct_mic_iv(mic_iv, qc_exists, a4_exists, pframe, plen, pn_vector);
+
+ construct_mic_header1(mic_header1, hdrlen, pframe);
+ construct_mic_header2(mic_header2, pframe, a4_exists, qc_exists);
+
+ payload_remainder = plen % 16;
+ num_blocks = plen / 16;
+
+ /* Find start of payload */
+ payload_index = hdrlen + 8;
+
+ /* Calculate MIC */
+ aes128k128d(key, mic_iv, aes_out);
+ bitwise_xor(aes_out, mic_header1, chain_buffer);
+ aes128k128d(key, chain_buffer, aes_out);
+ bitwise_xor(aes_out, mic_header2, chain_buffer);
+ aes128k128d(key, chain_buffer, aes_out);
+
+ for (i = 0; i < num_blocks; i++) {
+ bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);/* bitwise_xor(aes_out, &message[payload_index], chain_buffer); */
+
+ payload_index += 16;
+ aes128k128d(key, chain_buffer, aes_out);
+ }
+
+ /* Add on the final payload block if it needs padding */
+ if (payload_remainder > 0) {
+ for (j = 0; j < 16; j++)
+ padded_buffer[j] = 0x00;
+ for (j = 0; j < payload_remainder; j++)
+ padded_buffer[j] = pframe[payload_index++];/* padded_buffer[j] = message[payload_index++]; */
+ bitwise_xor(aes_out, padded_buffer, chain_buffer);
+ aes128k128d(key, chain_buffer, aes_out);
+ }
+
+ for (j = 0; j < 8; j++)
+ mic[j] = aes_out[j];
+
+ /* Insert MIC into payload */
+ for (j = 0; j < 8; j++)
+ pframe[payload_index+j] = mic[j];
+
+ payload_index = hdrlen + 8;
+ for (i = 0; i < num_blocks; i++) {
+ construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, pn_vector, i+1);
+ aes128k128d(key, ctr_preload, aes_out);
+ bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
+ for (j = 0; j < 16; j++)
+ pframe[payload_index++] = chain_buffer[j];
+ }
+
+ if (payload_remainder > 0) { /* If there is a short final block, then pad it,*/
+ /* encrypt it and copy the unpadded part back */
+ construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, pn_vector, num_blocks+1);
+
+ for (j = 0; j < 16; j++)
+ padded_buffer[j] = 0x00;
+ for (j = 0; j < payload_remainder; j++)
+ padded_buffer[j] = pframe[payload_index+j];
+ aes128k128d(key, ctr_preload, aes_out);
+ bitwise_xor(aes_out, padded_buffer, chain_buffer);
+ for (j = 0; j < payload_remainder; j++)
+ pframe[payload_index++] = chain_buffer[j];
+ }
+ /* Encrypt the MIC */
+ construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, pn_vector, 0);
+
+ for (j = 0; j < 16; j++)
+ padded_buffer[j] = 0x00;
+ for (j = 0; j < 8; j++)
+ padded_buffer[j] = pframe[j+hdrlen+8+plen];
+
+ aes128k128d(key, ctr_preload, aes_out);
+ bitwise_xor(aes_out, padded_buffer, chain_buffer);
+ for (j = 0; j < 8; j++)
+ pframe[payload_index++] = chain_buffer[j];
+ return _SUCCESS;
+}
+
+u32 rtw_aes_encrypt(struct adapter *padapter, u8 *pxmitframe)
+{ /* exclude ICV */
+
+ /*static*/
+/* unsigned char message[MAX_MSG_SIZE]; */
+
+ /* Intermediate Buffers */
+ int curfragnum, length;
+ u8 *pframe, *prwskey; /* *payload,*iv */
+ u8 hw_hdr_offset = 0;
+ struct sta_info *stainfo;
+ struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+/* uint offset = 0; */
+ u32 res = _SUCCESS;
+
+ if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
+ return _FAIL;
+
+ hw_hdr_offset = TXDESC_SIZE +
+ (((struct xmit_frame *)pxmitframe)->pkt_offset * PACKET_OFFSET_SZ);
+
+ pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset;
+
+ /* 4 start to encrypt each fragment */
+ if (pattrib->encrypt == _AES_) {
+ if (pattrib->psta)
+ stainfo = pattrib->psta;
+ else
+ stainfo = rtw_get_stainfo(&padapter->stapriv, &pattrib->ra[0]);
+
+ if (stainfo) {
+ RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("%s: stainfo!= NULL!!!\n", __func__));
+
+ if (is_multicast_ether_addr(pattrib->ra))
+ prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
+ else
+ prwskey = &stainfo->dot118021x_UncstKey.skey[0];
+ for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
+ if ((curfragnum+1) == pattrib->nr_frags) { /* 4 the last fragment */
+ length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
+
+ aes_cipher(prwskey, pattrib->hdrlen, pframe, length);
+ } else {
+ length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
+
+ aes_cipher(prwskey, pattrib->hdrlen, pframe, length);
+ pframe += pxmitpriv->frag_len;
+ pframe = (u8 *)round_up((size_t)(pframe), 8);
+ }
+ }
+ } else {
+ RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("%s: stainfo==NULL!!!\n", __func__));
+ res = _FAIL;
+ }
+ }
+
+ return res;
+}
+
+u32 rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe)
+{
+ struct rx_pkt_attrib *prxattrib = &((struct recv_frame *)precvframe)->attrib;
+ u32 res = _SUCCESS;
+
+ /* 4 start to encrypt each fragment */
+ if (prxattrib->encrypt == _AES_) {
+ struct sta_info *stainfo = rtw_get_stainfo(&padapter->stapriv, &prxattrib->ta[0]);
+
+ if (stainfo != NULL) {
+ int key_idx;
+ const int key_length = 16, iv_len = 8, icv_len = 8;
+ struct sk_buff *skb = ((struct recv_frame *)precvframe)->pkt;
+ void *crypto_private = NULL;
+ u8 *key, *pframe = skb->data;
+ struct lib80211_crypto_ops *crypto_ops = lib80211_get_crypto_ops("CCMP");
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ char iv[8], icv[8];
+
+ if (is_multicast_ether_addr(prxattrib->ra)) {
+ /* in concurrent we should use sw descrypt in group key, so we remove this message */
+ if (!psecuritypriv->binstallGrpkey) {
+ res = _FAIL;
+ DBG_88E("%s:rx bc/mc packets, but didn't install group key!!!!!!!!!!\n", __func__);
+ goto exit;
+ }
+ key_idx = psecuritypriv->dot118021XGrpKeyid;
+ key = psecuritypriv->dot118021XGrpKey[key_idx].skey;
+ } else {
+ key_idx = 0;
+ key = stainfo->dot118021x_UncstKey.skey;
+ }
+
+ if (!crypto_ops) {
+ res = _FAIL;
+ goto exit_lib80211_ccmp;
+ }
+
+ memcpy(iv, pframe + prxattrib->hdrlen, iv_len);
+ memcpy(icv, pframe + skb->len - icv_len, icv_len);
+
+ crypto_private = crypto_ops->init(key_idx);
+ if (!crypto_private) {
+ res = _FAIL;
+ goto exit_lib80211_ccmp;
+ }
+ if (crypto_ops->set_key(key, key_length, NULL, crypto_private) < 0) {
+ res = _FAIL;
+ goto exit_lib80211_ccmp;
+ }
+ if (crypto_ops->decrypt_mpdu(skb, prxattrib->hdrlen, crypto_private)) {
+ res = _FAIL;
+ goto exit_lib80211_ccmp;
+ }
+
+ memmove(pframe, pframe + iv_len, prxattrib->hdrlen);
+ skb_push(skb, iv_len);
+ skb_put(skb, icv_len);
+
+ memcpy(pframe + prxattrib->hdrlen, iv, iv_len);
+ memcpy(pframe + skb->len - icv_len, icv, icv_len);
+
+exit_lib80211_ccmp:
+ if (crypto_ops && crypto_private)
+ crypto_ops->deinit(crypto_private);
+ } else {
+ RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_aes_encrypt: stainfo==NULL!!!\n"));
+ res = _FAIL;
+ }
+ }
+exit:
+ return res;
+}
+
+/* AES tables*/
+const u32 Te0[256] = {
+ 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
+ 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
+ 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
+ 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
+ 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
+ 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
+ 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
+ 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
+ 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
+ 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
+ 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
+ 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
+ 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
+ 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
+ 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
+ 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
+ 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
+ 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
+ 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
+ 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
+ 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
+ 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
+ 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
+ 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
+ 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
+ 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
+ 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
+ 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
+ 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
+ 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
+ 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
+ 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
+ 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
+ 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
+ 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
+ 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
+ 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
+ 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
+ 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
+ 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
+ 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
+ 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
+ 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
+ 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
+ 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
+ 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
+ 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
+ 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
+ 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
+ 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
+ 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
+ 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
+ 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
+ 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
+ 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
+ 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
+ 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
+ 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
+ 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
+ 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
+ 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
+ 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
+ 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
+ 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
+};
+
+const u32 Td0[256] = {
+ 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
+ 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
+ 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
+ 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
+ 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
+ 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
+ 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
+ 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
+ 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
+ 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
+ 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
+ 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
+ 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
+ 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
+ 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
+ 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
+ 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
+ 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
+ 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
+ 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
+ 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
+ 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
+ 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
+ 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
+ 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
+ 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
+ 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
+ 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
+ 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
+ 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
+ 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
+ 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
+ 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
+ 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
+ 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
+ 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
+ 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
+ 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
+ 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
+ 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
+ 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
+ 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
+ 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
+ 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
+ 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
+ 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
+ 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
+ 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
+ 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
+ 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
+ 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
+ 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
+ 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
+ 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
+ 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
+ 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
+ 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
+ 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
+ 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
+ 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
+ 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
+ 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
+ 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
+ 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
+};
+
+const u8 Td4s[256] = {
+ 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U,
+ 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU,
+ 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U,
+ 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU,
+ 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU,
+ 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU,
+ 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U,
+ 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U,
+ 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U,
+ 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U,
+ 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU,
+ 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U,
+ 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU,
+ 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U,
+ 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U,
+ 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU,
+ 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU,
+ 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U,
+ 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U,
+ 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU,
+ 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U,
+ 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU,
+ 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U,
+ 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U,
+ 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U,
+ 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU,
+ 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU,
+ 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU,
+ 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U,
+ 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U,
+ 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U,
+ 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU,
+};
+const u8 rcons[] = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36
+ /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+
+/**
+ * Expand the cipher key into the encryption key schedule.
+ *
+ * @return the number of rounds for the given cipher key size.
+ */
+#define ROUND(i, d, s) \
+do { \
+ d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \
+ d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \
+ d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \
+ d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3]; \
+} while (0)
diff --git a/drivers/staging/rtl8188eu/core/rtw_sreset.c b/drivers/staging/rtl8188eu/core/rtw_sreset.c
new file mode 100644
index 0000000..a8397b1
--- /dev/null
+++ b/drivers/staging/rtl8188eu/core/rtw_sreset.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include <rtw_sreset.h>
+#include <usb_ops_linux.h>
+
+void rtw_hal_sreset_init(struct adapter *padapter)
+{
+ struct sreset_priv *psrtpriv = &padapter->HalData->srestpriv;
+
+ psrtpriv->wifi_error_status = WIFI_STATUS_SUCCESS;
+}
+
+void sreset_set_wifi_error_status(struct adapter *padapter, u32 status)
+{
+ padapter->HalData->srestpriv.wifi_error_status = status;
+}
diff --git a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c
new file mode 100644
index 0000000..34d4912
--- /dev/null
+++ b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c
@@ -0,0 +1,511 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _RTW_STA_MGT_C_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <recv_osdep.h>
+#include <xmit_osdep.h>
+#include <mlme_osdep.h>
+#include <sta_info.h>
+#include <linux/vmalloc.h>
+
+static void _rtw_init_stainfo(struct sta_info *psta)
+{
+ memset((u8 *)psta, 0, sizeof(struct sta_info));
+
+ spin_lock_init(&psta->lock);
+ INIT_LIST_HEAD(&psta->list);
+ INIT_LIST_HEAD(&psta->hash_list);
+ _rtw_init_queue(&psta->sleep_q);
+ psta->sleepq_len = 0;
+
+ _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv);
+ _rtw_init_sta_recv_priv(&psta->sta_recvpriv);
+
+#ifdef CPTCFG_88EU_AP_MODE
+
+ INIT_LIST_HEAD(&psta->asoc_list);
+
+ INIT_LIST_HEAD(&psta->auth_list);
+
+ psta->expire_to = 0;
+
+ psta->flags = 0;
+
+ psta->capability = 0;
+
+ psta->bpairwise_key_installed = false;
+
+ psta->nonerp_set = 0;
+ psta->no_short_slot_time_set = 0;
+ psta->no_short_preamble_set = 0;
+ psta->no_ht_gf_set = 0;
+ psta->no_ht_set = 0;
+ psta->ht_20mhz_set = 0;
+
+ psta->under_exist_checking = 0;
+
+ psta->keep_alive_trycnt = 0;
+
+#endif /* CPTCFG_88EU_AP_MODE */
+}
+
+u32 _rtw_init_sta_priv(struct sta_priv *pstapriv)
+{
+ struct sta_info *psta;
+ s32 i;
+
+ pstapriv->pallocated_stainfo_buf = vzalloc(sizeof(struct sta_info) * NUM_STA + 4);
+
+ if (!pstapriv->pallocated_stainfo_buf)
+ return _FAIL;
+
+ pstapriv->pstainfo_buf = pstapriv->pallocated_stainfo_buf + 4 -
+ ((size_t)(pstapriv->pallocated_stainfo_buf) & 3);
+
+ _rtw_init_queue(&pstapriv->free_sta_queue);
+
+ spin_lock_init(&pstapriv->sta_hash_lock);
+
+ pstapriv->asoc_sta_count = 0;
+ _rtw_init_queue(&pstapriv->sleep_q);
+ _rtw_init_queue(&pstapriv->wakeup_q);
+
+ psta = (struct sta_info *)(pstapriv->pstainfo_buf);
+
+ for (i = 0; i < NUM_STA; i++) {
+ _rtw_init_stainfo(psta);
+
+ INIT_LIST_HEAD(&pstapriv->sta_hash[i]);
+
+ list_add_tail(&psta->list, get_list_head(&pstapriv->free_sta_queue));
+
+ psta++;
+ }
+
+#ifdef CPTCFG_88EU_AP_MODE
+
+ pstapriv->sta_dz_bitmap = 0;
+ pstapriv->tim_bitmap = 0;
+
+ INIT_LIST_HEAD(&pstapriv->asoc_list);
+ INIT_LIST_HEAD(&pstapriv->auth_list);
+ spin_lock_init(&pstapriv->asoc_list_lock);
+ spin_lock_init(&pstapriv->auth_list_lock);
+ pstapriv->asoc_list_cnt = 0;
+ pstapriv->auth_list_cnt = 0;
+
+ pstapriv->auth_to = 3; /* 3*2 = 6 sec */
+ pstapriv->assoc_to = 3;
+ pstapriv->expire_to = 3; /* 3*2 = 6 sec */
+ pstapriv->max_num_sta = NUM_STA;
+#endif
+
+ return _SUCCESS;
+}
+
+inline int rtw_stainfo_offset(struct sta_priv *stapriv, struct sta_info *sta)
+{
+ int offset = (((u8 *)sta) - stapriv->pstainfo_buf)/sizeof(struct sta_info);
+
+ if (!stainfo_offset_valid(offset))
+ DBG_88E("%s invalid offset(%d), out of range!!!", __func__, offset);
+
+ return offset;
+}
+
+inline struct sta_info *rtw_get_stainfo_by_offset(struct sta_priv *stapriv, int offset)
+{
+ if (!stainfo_offset_valid(offset))
+ DBG_88E("%s invalid offset(%d), out of range!!!", __func__, offset);
+
+ return (struct sta_info *)(stapriv->pstainfo_buf + offset * sizeof(struct sta_info));
+}
+
+u32 _rtw_free_sta_priv(struct sta_priv *pstapriv)
+{
+ struct list_head *phead, *plist;
+ struct sta_info *psta = NULL;
+ struct recv_reorder_ctrl *preorder_ctrl;
+ int index;
+
+ if (pstapriv) {
+ /* delete all reordering_ctrl_timer */
+ spin_lock_bh(&pstapriv->sta_hash_lock);
+ for (index = 0; index < NUM_STA; index++) {
+ phead = &pstapriv->sta_hash[index];
+ plist = phead->next;
+
+ while (phead != plist) {
+ int i;
+
+ psta = container_of(plist, struct sta_info,
+ hash_list);
+ plist = plist->next;
+
+ for (i = 0; i < 16; i++) {
+ preorder_ctrl = &psta->recvreorder_ctrl[i];
+ del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
+ }
+ }
+ }
+ spin_unlock_bh(&pstapriv->sta_hash_lock);
+ /*===============================*/
+
+ vfree(pstapriv->pallocated_stainfo_buf);
+ }
+
+ return _SUCCESS;
+}
+
+struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
+{
+ s32 index;
+ struct list_head *phash_list;
+ struct sta_info *psta;
+ struct __queue *pfree_sta_queue;
+ struct recv_reorder_ctrl *preorder_ctrl;
+ int i = 0;
+ u16 wRxSeqInitialValue = 0xffff;
+
+ pfree_sta_queue = &pstapriv->free_sta_queue;
+
+ spin_lock_bh(&pfree_sta_queue->lock);
+ psta = list_first_entry_or_null(&pfree_sta_queue->queue,
+ struct sta_info, list);
+ if (!psta) {
+ spin_unlock_bh(&pfree_sta_queue->lock);
+ } else {
+ list_del_init(&psta->list);
+ spin_unlock_bh(&pfree_sta_queue->lock);
+ _rtw_init_stainfo(psta);
+ memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
+ index = wifi_mac_hash(hwaddr);
+ RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_, ("%s: index=%x", __func__, index));
+ if (index >= NUM_STA) {
+ RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("ERROR => %s: index >= NUM_STA", __func__));
+ psta = NULL;
+ goto exit;
+ }
+ phash_list = &pstapriv->sta_hash[index];
+
+ spin_lock_bh(&pstapriv->sta_hash_lock);
+ list_add_tail(&psta->hash_list, phash_list);
+ pstapriv->asoc_sta_count++;
+ spin_unlock_bh(&pstapriv->sta_hash_lock);
+
+/* Commented by Albert 2009/08/13 */
+/* For the SMC router, the sequence number of first packet of WPS handshake will be 0. */
+/* In this case, this packet will be dropped by recv_decache function if we use the 0x00 as the default value for tid_rxseq variable. */
+/* So, we initialize the tid_rxseq variable as the 0xffff. */
+
+ for (i = 0; i < 16; i++)
+ memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i], &wRxSeqInitialValue, 2);
+
+ RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_,
+ ("alloc number_%d stainfo with hwaddr = %pM\n",
+ pstapriv->asoc_sta_count, hwaddr));
+
+ init_addba_retry_timer(pstapriv->padapter, psta);
+
+ /* for A-MPDU Rx reordering buffer control */
+ for (i = 0; i < 16; i++) {
+ preorder_ctrl = &psta->recvreorder_ctrl[i];
+
+ preorder_ctrl->padapter = pstapriv->padapter;
+
+ preorder_ctrl->enable = false;
+
+ preorder_ctrl->indicate_seq = 0xffff;
+ preorder_ctrl->wend_b = 0xffff;
+ preorder_ctrl->wsize_b = 64;/* 64; */
+
+ _rtw_init_queue(&preorder_ctrl->pending_recvframe_queue);
+
+ rtw_init_recv_timer(preorder_ctrl);
+ }
+
+ /* init for DM */
+ psta->rssi_stat.UndecoratedSmoothedPWDB = -1;
+ psta->rssi_stat.UndecoratedSmoothedCCK = -1;
+
+ /* init for the sequence number of received management frame */
+ psta->RxMgmtFrameSeqNum = 0xffff;
+ }
+
+exit:
+ return psta;
+}
+
+/* using pstapriv->sta_hash_lock to protect */
+u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta)
+{
+ int i;
+ struct __queue *pfree_sta_queue;
+ struct recv_reorder_ctrl *preorder_ctrl;
+ struct sta_xmit_priv *pstaxmitpriv;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ if (!psta)
+ goto exit;
+
+ pfree_sta_queue = &pstapriv->free_sta_queue;
+
+ pstaxmitpriv = &psta->sta_xmitpriv;
+
+ spin_lock_bh(&pxmitpriv->lock);
+
+ rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q);
+ psta->sleepq_len = 0;
+
+ rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
+
+ list_del_init(&pstaxmitpriv->vo_q.tx_pending);
+
+ rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
+
+ list_del_init(&pstaxmitpriv->vi_q.tx_pending);
+
+ rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
+
+ list_del_init(&pstaxmitpriv->bk_q.tx_pending);
+
+ rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
+
+ list_del_init(&pstaxmitpriv->be_q.tx_pending);
+
+ spin_unlock_bh(&pxmitpriv->lock);
+
+ list_del_init(&psta->hash_list);
+ RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_,
+ ("\n free number_%d stainfo with hwaddr=0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",
+ pstapriv->asoc_sta_count, psta->hwaddr[0], psta->hwaddr[1],
+ psta->hwaddr[2], psta->hwaddr[3], psta->hwaddr[4],
+ psta->hwaddr[5]));
+ pstapriv->asoc_sta_count--;
+
+ /* re-init sta_info; 20061114 */
+ _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv);
+ _rtw_init_sta_recv_priv(&psta->sta_recvpriv);
+
+ del_timer_sync(&psta->addba_retry_timer);
+
+ /* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */
+ for (i = 0; i < 16; i++) {
+ struct list_head *phead, *plist;
+ struct recv_frame *prframe;
+ struct __queue *ppending_recvframe_queue;
+ struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
+
+ preorder_ctrl = &psta->recvreorder_ctrl[i];
+
+ del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
+
+ ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
+
+ spin_lock_bh(&ppending_recvframe_queue->lock);
+
+ phead = get_list_head(ppending_recvframe_queue);
+ plist = phead->next;
+
+ while (!list_empty(phead)) {
+ prframe = container_of(plist, struct recv_frame, list);
+
+ plist = plist->next;
+
+ list_del_init(&prframe->list);
+
+ rtw_free_recvframe(prframe, pfree_recv_queue);
+ }
+
+ spin_unlock_bh(&ppending_recvframe_queue->lock);
+ }
+
+ if (!(psta->state & WIFI_AP_STATE))
+ rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, false);
+
+#ifdef CPTCFG_88EU_AP_MODE
+
+ spin_lock_bh(&pstapriv->auth_list_lock);
+ if (!list_empty(&psta->auth_list)) {
+ list_del_init(&psta->auth_list);
+ pstapriv->auth_list_cnt--;
+ }
+ spin_unlock_bh(&pstapriv->auth_list_lock);
+
+ psta->expire_to = 0;
+
+ psta->sleepq_ac_len = 0;
+ psta->qos_info = 0;
+
+ psta->max_sp_len = 0;
+ psta->uapsd_bk = 0;
+ psta->uapsd_be = 0;
+ psta->uapsd_vi = 0;
+ psta->uapsd_vo = 0;
+ psta->has_legacy_ac = 0;
+
+ pstapriv->sta_dz_bitmap &= ~BIT(psta->aid);
+ pstapriv->tim_bitmap &= ~BIT(psta->aid);
+
+ if ((psta->aid > 0) && (pstapriv->sta_aid[psta->aid - 1] == psta)) {
+ pstapriv->sta_aid[psta->aid - 1] = NULL;
+ psta->aid = 0;
+ }
+
+ psta->under_exist_checking = 0;
+
+#endif /* CPTCFG_88EU_AP_MODE */
+
+ spin_lock_bh(&pfree_sta_queue->lock);
+ list_add_tail(&psta->list, get_list_head(pfree_sta_queue));
+ spin_unlock_bh(&pfree_sta_queue->lock);
+
+exit:
+
+ return _SUCCESS;
+}
+
+/* free all stainfo which in sta_hash[all] */
+void rtw_free_all_stainfo(struct adapter *padapter)
+{
+ struct list_head *plist, *phead;
+ s32 index;
+ struct sta_info *psta = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo(padapter);
+
+ if (pstapriv->asoc_sta_count == 1)
+ return;
+
+ spin_lock_bh(&pstapriv->sta_hash_lock);
+
+ for (index = 0; index < NUM_STA; index++) {
+ phead = &pstapriv->sta_hash[index];
+ plist = phead->next;
+
+ while (phead != plist) {
+ psta = container_of(plist, struct sta_info, hash_list);
+
+ plist = plist->next;
+
+ if (pbcmc_stainfo != psta)
+ rtw_free_stainfo(padapter, psta);
+ }
+ }
+ spin_unlock_bh(&pstapriv->sta_hash_lock);
+}
+
+/* any station allocated can be searched by hash list */
+struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
+{
+ struct list_head *plist, *phead;
+ struct sta_info *psta = NULL;
+ u32 index;
+ u8 *addr;
+ u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ if (!hwaddr)
+ return NULL;
+
+ if (is_multicast_ether_addr(hwaddr))
+ addr = bc_addr;
+ else
+ addr = hwaddr;
+
+ index = wifi_mac_hash(addr);
+
+ spin_lock_bh(&pstapriv->sta_hash_lock);
+
+ phead = &pstapriv->sta_hash[index];
+ plist = phead->next;
+
+ while (phead != plist) {
+ psta = container_of(plist, struct sta_info, hash_list);
+
+ if (!memcmp(psta->hwaddr, addr, ETH_ALEN)) {
+ /* if found the matched address */
+ break;
+ }
+ psta = NULL;
+ plist = plist->next;
+ }
+
+ spin_unlock_bh(&pstapriv->sta_hash_lock);
+ return psta;
+}
+
+u32 rtw_init_bcmc_stainfo(struct adapter *padapter)
+{
+ struct sta_info *psta;
+ u32 res = _SUCCESS;
+ unsigned char bcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ psta = rtw_alloc_stainfo(pstapriv, bcast_addr);
+
+ if (!psta) {
+ res = _FAIL;
+ RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("rtw_alloc_stainfo fail"));
+ goto exit;
+ }
+
+ /* default broadcast & multicast use macid 1 */
+ psta->mac_id = 1;
+
+exit:
+ return res;
+}
+
+struct sta_info *rtw_get_bcmc_stainfo(struct adapter *padapter)
+{
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ return rtw_get_stainfo(pstapriv, bc_addr);
+}
+
+u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr)
+{
+ u8 res = true;
+#ifdef CPTCFG_88EU_AP_MODE
+ struct list_head *plist, *phead;
+ struct rtw_wlan_acl_node *paclnode;
+ u8 match = false;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+ struct __queue *pacl_node_q = &pacl_list->acl_node_q;
+
+ spin_lock_bh(&pacl_node_q->lock);
+ phead = get_list_head(pacl_node_q);
+ plist = phead->next;
+ while (phead != plist) {
+ paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
+ plist = plist->next;
+
+ if (!memcmp(paclnode->addr, mac_addr, ETH_ALEN)) {
+ if (paclnode->valid) {
+ match = true;
+ break;
+ }
+ }
+ }
+ spin_unlock_bh(&pacl_node_q->lock);
+
+ if (pacl_list->mode == 1)/* accept unless in deny list */
+ res = (match) ? false : true;
+ else if (pacl_list->mode == 2)/* deny unless in accept list */
+ res = (match) ? true : false;
+ else
+ res = true;
+
+#endif
+
+ return res;
+}
diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
new file mode 100644
index 0000000..c985b14
--- /dev/null
+++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
@@ -0,0 +1,1468 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _RTW_WLAN_UTIL_C_
+
+#include <linux/ieee80211.h>
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <wifi.h>
+
+static const u8 ARTHEROS_OUI1[] = {0x00, 0x03, 0x7f};
+static const u8 ARTHEROS_OUI2[] = {0x00, 0x13, 0x74};
+
+static const u8 BROADCOM_OUI1[] = {0x00, 0x10, 0x18};
+static const u8 BROADCOM_OUI2[] = {0x00, 0x0a, 0xf7};
+
+static const u8 CISCO_OUI[] = {0x00, 0x40, 0x96};
+static const u8 MARVELL_OUI[] = {0x00, 0x50, 0x43};
+static const u8 RALINK_OUI[] = {0x00, 0x0c, 0x43};
+static const u8 REALTEK_OUI[] = {0x00, 0xe0, 0x4c};
+static const u8 AIRGOCAP_OUI[] = {0x00, 0x0a, 0xf5};
+static const u8 EPIGRAM_OUI[] = {0x00, 0x90, 0x4c};
+
+u8 REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20};
+
+#define WAIT_FOR_BCN_TO_MIN (6000)
+#define WAIT_FOR_BCN_TO_MAX (20000)
+
+static const u8 rtw_basic_rate_cck[4] = {
+ IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK,
+ IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK,
+ IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK,
+ IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK
+};
+
+static const u8 rtw_basic_rate_ofdm[3] = {
+ IEEE80211_OFDM_RATE_6MB | IEEE80211_BASIC_RATE_MASK,
+ IEEE80211_OFDM_RATE_12MB | IEEE80211_BASIC_RATE_MASK,
+ IEEE80211_OFDM_RATE_24MB | IEEE80211_BASIC_RATE_MASK
+};
+
+static const u8 rtw_basic_rate_mix[7] = {
+ IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK,
+ IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK,
+ IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK,
+ IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK,
+ IEEE80211_OFDM_RATE_6MB | IEEE80211_BASIC_RATE_MASK,
+ IEEE80211_OFDM_RATE_12MB | IEEE80211_BASIC_RATE_MASK,
+ IEEE80211_OFDM_RATE_24MB | IEEE80211_BASIC_RATE_MASK
+};
+
+bool cckrates_included(unsigned char *rate, int ratelen)
+{
+ int i;
+
+ for (i = 0; i < ratelen; i++) {
+ u8 r = rate[i] & 0x7f;
+
+ if (r == 2 || r == 4 || r == 11 || r == 22)
+ return true;
+ }
+ return false;
+}
+
+bool cckratesonly_included(unsigned char *rate, int ratelen)
+{
+ int i;
+
+ for (i = 0; i < ratelen; i++) {
+ u8 r = rate[i] & 0x7f;
+
+ if (r != 2 && r != 4 && r != 11 && r != 22)
+ return false;
+ }
+ return true;
+}
+
+unsigned char networktype_to_raid(unsigned char network_type)
+{
+ switch (network_type) {
+ case WIRELESS_11B:
+ return RATR_INX_WIRELESS_B;
+ case WIRELESS_11A:
+ case WIRELESS_11G:
+ return RATR_INX_WIRELESS_G;
+ case WIRELESS_11BG:
+ return RATR_INX_WIRELESS_GB;
+ case WIRELESS_11_24N:
+ case WIRELESS_11_5N:
+ return RATR_INX_WIRELESS_N;
+ case WIRELESS_11A_5N:
+ case WIRELESS_11G_24N:
+ return RATR_INX_WIRELESS_NG;
+ case WIRELESS_11BG_24N:
+ return RATR_INX_WIRELESS_NGB;
+ default:
+ return RATR_INX_WIRELESS_GB;
+ }
+}
+
+u8 judge_network_type(struct adapter *padapter, unsigned char *rate, int ratelen)
+{
+ u8 network_type = 0;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ if (pmlmeinfo->HT_enable)
+ network_type = WIRELESS_11_24N;
+
+ if (cckratesonly_included(rate, ratelen))
+ network_type |= WIRELESS_11B;
+ else if (cckrates_included(rate, ratelen))
+ network_type |= WIRELESS_11BG;
+ else
+ network_type |= WIRELESS_11G;
+
+ return network_type;
+}
+
+static unsigned char ratetbl_val_2wifirate(unsigned char rate)
+{
+ switch (rate & 0x7f) {
+ case 0:
+ return IEEE80211_CCK_RATE_1MB;
+ case 1:
+ return IEEE80211_CCK_RATE_2MB;
+ case 2:
+ return IEEE80211_CCK_RATE_5MB;
+ case 3:
+ return IEEE80211_CCK_RATE_11MB;
+ case 4:
+ return IEEE80211_OFDM_RATE_6MB;
+ case 5:
+ return IEEE80211_OFDM_RATE_9MB;
+ case 6:
+ return IEEE80211_OFDM_RATE_12MB;
+ case 7:
+ return IEEE80211_OFDM_RATE_18MB;
+ case 8:
+ return IEEE80211_OFDM_RATE_24MB;
+ case 9:
+ return IEEE80211_OFDM_RATE_36MB;
+ case 10:
+ return IEEE80211_OFDM_RATE_48MB;
+ case 11:
+ return IEEE80211_OFDM_RATE_54MB;
+ default:
+ return 0;
+ }
+}
+
+static bool is_basicrate(struct adapter *padapter, unsigned char rate)
+{
+ int i;
+ unsigned char val;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ for (i = 0; i < NumRates; i++) {
+ val = pmlmeext->basicrate[i];
+
+ if ((val != 0xff) && (val != 0xfe)) {
+ if (rate == ratetbl_val_2wifirate(val))
+ return true;
+ }
+ }
+ return false;
+}
+
+static unsigned int ratetbl2rateset(struct adapter *padapter, unsigned char *rateset)
+{
+ int i;
+ unsigned char rate;
+ unsigned int len = 0;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ for (i = 0; i < NumRates; i++) {
+ rate = pmlmeext->datarate[i];
+
+ switch (rate) {
+ case 0xff:
+ return len;
+ case 0xfe:
+ continue;
+ default:
+ rate = ratetbl_val_2wifirate(rate);
+
+ if (is_basicrate(padapter, rate))
+ rate |= IEEE80211_BASIC_RATE_MASK;
+
+ rateset[len] = rate;
+ len++;
+ break;
+ }
+ }
+ return len;
+}
+
+void get_rate_set(struct adapter *padapter, unsigned char *pbssrate, int *bssrate_len)
+{
+ unsigned char supportedrates[NumRates];
+
+ memset(supportedrates, 0, NumRates);
+ *bssrate_len = ratetbl2rateset(padapter, supportedrates);
+ memcpy(pbssrate, supportedrates, *bssrate_len);
+}
+
+void UpdateBrateTbl(struct adapter *Adapter, u8 *mbrate)
+{
+ u8 i;
+ u8 rate;
+
+ /* 1M, 2M, 5.5M, 11M, 6M, 12M, 24M are mandatory. */
+ for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
+ rate = mbrate[i] & 0x7f;
+ switch (rate) {
+ case IEEE80211_CCK_RATE_1MB:
+ case IEEE80211_CCK_RATE_2MB:
+ case IEEE80211_CCK_RATE_5MB:
+ case IEEE80211_CCK_RATE_11MB:
+ case IEEE80211_OFDM_RATE_6MB:
+ case IEEE80211_OFDM_RATE_12MB:
+ case IEEE80211_OFDM_RATE_24MB:
+ mbrate[i] |= IEEE80211_BASIC_RATE_MASK;
+ break;
+ }
+ }
+}
+
+void UpdateBrateTblForSoftAP(u8 *bssrateset, u32 bssratelen)
+{
+ u8 i;
+ u8 rate;
+
+ for (i = 0; i < bssratelen; i++) {
+ rate = bssrateset[i] & 0x7f;
+ switch (rate) {
+ case IEEE80211_CCK_RATE_1MB:
+ case IEEE80211_CCK_RATE_2MB:
+ case IEEE80211_CCK_RATE_5MB:
+ case IEEE80211_CCK_RATE_11MB:
+ bssrateset[i] |= IEEE80211_BASIC_RATE_MASK;
+ break;
+ }
+ }
+}
+
+void Save_DM_Func_Flag(struct adapter *padapter)
+{
+ u8 saveflag = true;
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_OP, (u8 *)(&saveflag));
+}
+
+void Restore_DM_Func_Flag(struct adapter *padapter)
+{
+ u8 saveflag = false;
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_OP, (u8 *)(&saveflag));
+}
+
+void Switch_DM_Func(struct adapter *padapter, u32 mode, u8 enable)
+{
+ if (enable)
+ rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_SET, (u8 *)(&mode));
+ else
+ rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_CLR, (u8 *)(&mode));
+}
+
+void Set_MSR(struct adapter *padapter, u8 type)
+{
+ rtw_hal_set_hwreg(padapter, HW_VAR_MEDIA_STATUS, (u8 *)(&type));
+}
+
+inline u8 rtw_get_oper_ch(struct adapter *adapter)
+{
+ return adapter->mlmeextpriv.oper_channel;
+}
+
+inline void rtw_set_oper_ch(struct adapter *adapter, u8 ch)
+{
+ adapter->mlmeextpriv.oper_channel = ch;
+}
+
+inline void rtw_set_oper_bw(struct adapter *adapter, u8 bw)
+{
+ adapter->mlmeextpriv.oper_bwmode = bw;
+}
+
+inline void rtw_set_oper_choffset(struct adapter *adapter, u8 offset)
+{
+ adapter->mlmeextpriv.oper_ch_offset = offset;
+}
+
+void SelectChannel(struct adapter *padapter, unsigned char channel)
+{
+ /* saved channel info */
+ rtw_set_oper_ch(padapter, channel);
+ rtw_hal_set_chan(padapter, channel);
+}
+
+void SetBWMode(struct adapter *padapter, unsigned short bwmode,
+ unsigned char channel_offset)
+{
+ /* saved bw info */
+ rtw_set_oper_bw(padapter, bwmode);
+ rtw_set_oper_choffset(padapter, channel_offset);
+
+ rtw_hal_set_bwmode(padapter, (enum ht_channel_width)bwmode, channel_offset);
+}
+
+void set_channel_bwmode(struct adapter *padapter, unsigned char channel, unsigned char channel_offset, unsigned short bwmode)
+{
+ u8 center_ch;
+
+ if ((bwmode == HT_CHANNEL_WIDTH_20) ||
+ (channel_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)) {
+ /* SelectChannel(padapter, channel); */
+ center_ch = channel;
+ } else {
+ /* switch to the proper channel */
+ if (channel_offset == HAL_PRIME_CHNL_OFFSET_LOWER) {
+ /* SelectChannel(padapter, channel + 2); */
+ center_ch = channel + 2;
+ } else {
+ /* SelectChannel(padapter, channel - 2); */
+ center_ch = channel - 2;
+ }
+ }
+
+ /* set Channel */
+ /* saved channel/bw info */
+ rtw_set_oper_ch(padapter, channel);
+ rtw_set_oper_bw(padapter, bwmode);
+ rtw_set_oper_choffset(padapter, channel_offset);
+
+ rtw_hal_set_chan(padapter, center_ch); /* set center channel */
+ SetBWMode(padapter, bwmode, channel_offset);
+}
+
+u16 get_beacon_interval(struct wlan_bssid_ex *bss)
+{
+ __le16 val;
+
+ memcpy((unsigned char *)&val, rtw_get_beacon_interval_from_ie(bss->ies), 2);
+
+ return le16_to_cpu(val);
+}
+
+int is_client_associated_to_ap(struct adapter *padapter)
+{
+ struct mlme_ext_priv *pmlmeext;
+ struct mlme_ext_info *pmlmeinfo;
+
+ if (!padapter)
+ return _FAIL;
+
+ pmlmeext = &padapter->mlmeextpriv;
+ pmlmeinfo = &pmlmeext->mlmext_info;
+
+ if ((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) &&
+ (pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)
+ return true;
+ else
+ return _FAIL;
+}
+
+int is_client_associated_to_ibss(struct adapter *padapter)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ if ((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) &&
+ (pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE)
+ return true;
+ else
+ return _FAIL;
+}
+
+int is_IBSS_empty(struct adapter *padapter)
+{
+ unsigned int i;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
+ if (pmlmeinfo->FW_sta_info[i].status == 1)
+ return _FAIL;
+ }
+ return true;
+}
+
+unsigned int decide_wait_for_beacon_timeout(unsigned int bcn_interval)
+{
+ if ((bcn_interval << 2) < WAIT_FOR_BCN_TO_MIN)
+ return WAIT_FOR_BCN_TO_MIN;
+ else if ((bcn_interval << 2) > WAIT_FOR_BCN_TO_MAX)
+ return WAIT_FOR_BCN_TO_MAX;
+ else
+ return bcn_interval << 2;
+}
+
+void invalidate_cam_all(struct adapter *padapter)
+{
+ rtw_hal_set_hwreg(padapter, HW_VAR_CAM_INVALID_ALL, NULL);
+}
+
+void write_cam(struct adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key)
+{
+ unsigned int i, val, addr;
+ int j;
+ u32 cam_val[2];
+
+ addr = entry << 3;
+
+ for (j = 5; j >= 0; j--) {
+ switch (j) {
+ case 0:
+ val = ctrl | (mac[0] << 16) | (mac[1] << 24);
+ break;
+ case 1:
+ val = mac[2] | (mac[3] << 8) | (mac[4] << 16) | (mac[5] << 24);
+ break;
+ default:
+ i = (j - 2) << 2;
+ val = key[i] | (key[i + 1] << 8) | (key[i + 2] << 16) |
+ (key[i + 3] << 24);
+ break;
+ }
+
+ cam_val[0] = val;
+ cam_val[1] = addr + (unsigned int)j;
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_CAM_WRITE, (u8 *)cam_val);
+ }
+}
+
+void clear_cam_entry(struct adapter *padapter, u8 entry)
+{
+ u8 null_sta[ETH_ALEN] = {};
+ u8 null_key[16] = {};
+
+ write_cam(padapter, entry, 0, null_sta, null_key);
+}
+
+int allocate_fw_sta_entry(struct adapter *padapter)
+{
+ unsigned int mac_id;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ for (mac_id = IBSS_START_MAC_ID; mac_id < NUM_STA; mac_id++) {
+ if (pmlmeinfo->FW_sta_info[mac_id].status == 0) {
+ pmlmeinfo->FW_sta_info[mac_id].status = 1;
+ pmlmeinfo->FW_sta_info[mac_id].retry = 0;
+ break;
+ }
+ }
+
+ return mac_id;
+}
+
+void flush_all_cam_entry(struct adapter *padapter)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_CAM_INVALID_ALL, NULL);
+
+ memset((u8 *)(pmlmeinfo->FW_sta_info), 0, sizeof(pmlmeinfo->FW_sta_info));
+}
+
+int WMM_param_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ if (pmlmepriv->qospriv.qos_option == 0) {
+ pmlmeinfo->WMM_enable = 0;
+ return _FAIL;
+ }
+
+ pmlmeinfo->WMM_enable = 1;
+ memcpy(&pmlmeinfo->WMM_param, pIE->data + 6, sizeof(struct WMM_para_element));
+ return true;
+}
+
+void WMMOnAssocRsp(struct adapter *padapter)
+{
+ u8 ACI, ACM, AIFS, ECWMin, ECWMax, aSifsTime;
+ u8 acm_mask;
+ u16 TXOP;
+ u32 acParm, i;
+ u32 edca[4], inx[4];
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+
+ if (pmlmeinfo->WMM_enable == 0) {
+ padapter->mlmepriv.acm_mask = 0;
+ return;
+ }
+
+ acm_mask = 0;
+
+ if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
+ aSifsTime = 10;
+ else
+ aSifsTime = 16;
+
+ for (i = 0; i < 4; i++) {
+ ACI = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 5) & 0x03;
+ ACM = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 4) & 0x01;
+
+ /* AIFS = AIFSN * slot time + SIFS - r2t phy delay */
+ AIFS = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN & 0x0f) * pmlmeinfo->slotTime + aSifsTime;
+
+ ECWMin = pmlmeinfo->WMM_param.ac_param[i].CW & 0x0f;
+ ECWMax = (pmlmeinfo->WMM_param.ac_param[i].CW & 0xf0) >> 4;
+ TXOP = le16_to_cpu(pmlmeinfo->WMM_param.ac_param[i].TXOP_limit);
+
+ acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
+
+ switch (ACI) {
+ case 0x0:
+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acParm));
+ acm_mask |= (ACM ? BIT(1) : 0);
+ edca[XMIT_BE_QUEUE] = acParm;
+ break;
+ case 0x1:
+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acParm));
+ edca[XMIT_BK_QUEUE] = acParm;
+ break;
+ case 0x2:
+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acParm));
+ acm_mask |= (ACM ? BIT(2) : 0);
+ edca[XMIT_VI_QUEUE] = acParm;
+ break;
+ case 0x3:
+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acParm));
+ acm_mask |= (ACM ? BIT(3) : 0);
+ edca[XMIT_VO_QUEUE] = acParm;
+ break;
+ }
+
+ DBG_88E("WMM(%x): %x, %x\n", ACI, ACM, acParm);
+ }
+
+ if (padapter->registrypriv.acm_method == 1)
+ rtw_hal_set_hwreg(padapter, HW_VAR_ACM_CTRL, (u8 *)(&acm_mask));
+ else
+ padapter->mlmepriv.acm_mask = acm_mask;
+
+ inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3;
+
+ if (pregpriv->wifi_spec == 1) {
+ u32 j, change_inx = false;
+
+ /* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */
+ for (i = 0; i < 4; i++) {
+ for (j = i + 1; j < 4; j++) {
+ /* compare CW and AIFS */
+ if ((edca[j] & 0xFFFF) < (edca[i] & 0xFFFF)) {
+ change_inx = true;
+ } else if ((edca[j] & 0xFFFF) == (edca[i] & 0xFFFF)) {
+ /* compare TXOP */
+ if ((edca[j] >> 16) > (edca[i] >> 16))
+ change_inx = true;
+ }
+
+ if (change_inx) {
+ swap(edca[i], edca[j]);
+ swap(inx[i], inx[j]);
+ change_inx = false;
+ }
+ }
+ }
+ }
+
+ for (i = 0; i < 4; i++) {
+ pxmitpriv->wmm_para_seq[i] = inx[i];
+ DBG_88E("wmm_para_seq(%d): %d\n", i, pxmitpriv->wmm_para_seq[i]);
+ }
+}
+
+static void bwmode_update_check(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
+{
+ unsigned char new_bwmode;
+ unsigned char new_ch_offset;
+ struct HT_info_element *pHT_info;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
+
+ if (!pIE)
+ return;
+
+ if (!phtpriv)
+ return;
+
+ if (pIE->Length > sizeof(struct HT_info_element))
+ return;
+
+ pHT_info = (struct HT_info_element *)pIE->data;
+
+ if ((pHT_info->infos[0] & BIT(2)) && pregistrypriv->cbw40_enable) {
+ new_bwmode = HT_CHANNEL_WIDTH_40;
+
+ switch (pHT_info->infos[0] & 0x3) {
+ case 1:
+ new_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
+ break;
+ case 3:
+ new_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
+ break;
+ default:
+ new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ break;
+ }
+ } else {
+ new_bwmode = HT_CHANNEL_WIDTH_20;
+ new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ }
+
+ if ((new_bwmode != pmlmeext->cur_bwmode) ||
+ (new_ch_offset != pmlmeext->cur_ch_offset)) {
+ pmlmeinfo->bwmode_updated = true;
+
+ pmlmeext->cur_bwmode = new_bwmode;
+ pmlmeext->cur_ch_offset = new_ch_offset;
+
+ /* update HT info also */
+ HT_info_handler(padapter, pIE);
+ } else {
+ pmlmeinfo->bwmode_updated = false;
+ }
+
+ if (pmlmeinfo->bwmode_updated) {
+ struct sta_info *psta;
+ struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ /* update ap's stainfo */
+ psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
+ if (psta) {
+ struct ht_priv *phtpriv_sta = &psta->htpriv;
+
+ if (phtpriv_sta->ht_option) {
+ /* bwmode */
+ phtpriv_sta->bwmode = pmlmeext->cur_bwmode;
+ phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;
+ } else {
+ phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20;
+ phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ }
+ }
+ }
+}
+
+void HT_caps_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
+{
+ unsigned int i;
+ u8 max_AMPDU_len, min_MPDU_spacing;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
+ u8 *HT_cap = (u8 *)(&pmlmeinfo->HT_caps);
+
+ if (!pIE)
+ return;
+
+ if (!phtpriv->ht_option)
+ return;
+
+ pmlmeinfo->HT_caps_enable = 1;
+
+ for (i = 0; i < (pIE->Length); i++) {
+ if (i != 2) {
+ /* Got the endian issue here. */
+ HT_cap[i] &= (pIE->data[i]);
+ } else {
+ /* modify from fw by Thomas 2010/11/17 */
+ if ((pmlmeinfo->HT_caps.ampdu_params_info & 0x3) > (pIE->data[i] & 0x3))
+ max_AMPDU_len = pIE->data[i] & 0x3;
+ else
+ max_AMPDU_len = pmlmeinfo->HT_caps.ampdu_params_info & 0x3;
+
+ if ((pmlmeinfo->HT_caps.ampdu_params_info & 0x1c) > (pIE->data[i] & 0x1c))
+ min_MPDU_spacing = pmlmeinfo->HT_caps.ampdu_params_info & 0x1c;
+ else
+ min_MPDU_spacing = pIE->data[i] & 0x1c;
+
+ pmlmeinfo->HT_caps.ampdu_params_info = max_AMPDU_len | min_MPDU_spacing;
+ }
+ }
+
+ /* update the MCS rates */
+ for (i = 0; i < 16; i++)
+ ((u8 *)&pmlmeinfo->HT_caps.mcs)[i] &= MCS_rate_1R[i];
+}
+
+void HT_info_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct ht_priv *phtpriv = &pmlmepriv->htpriv;
+
+ if (!pIE)
+ return;
+
+ if (!phtpriv->ht_option)
+ return;
+
+ if (pIE->Length > sizeof(struct HT_info_element))
+ return;
+
+ pmlmeinfo->HT_info_enable = 1;
+ memcpy(&pmlmeinfo->HT_info, pIE->data, pIE->Length);
+}
+
+void HTOnAssocRsp(struct adapter *padapter)
+{
+ unsigned char max_AMPDU_len;
+ unsigned char min_MPDU_spacing;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ DBG_88E("%s\n", __func__);
+
+ if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable)) {
+ pmlmeinfo->HT_enable = 1;
+ } else {
+ pmlmeinfo->HT_enable = 0;
+ return;
+ }
+
+ /* handle A-MPDU parameter field
+ *
+ * AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
+ * AMPDU_para [4:2]:Min MPDU Start Spacing
+ */
+ max_AMPDU_len = pmlmeinfo->HT_caps.ampdu_params_info & 0x03;
+
+ min_MPDU_spacing = (pmlmeinfo->HT_caps.ampdu_params_info & 0x1c) >> 2;
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
+}
+
+void ERP_IE_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ if (pIE->Length > 1)
+ return;
+
+ pmlmeinfo->ERP_enable = 1;
+ memcpy(&pmlmeinfo->ERP_IE, pIE->data, pIE->Length);
+}
+
+void VCS_update(struct adapter *padapter, struct sta_info *psta)
+{
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ switch (pregpriv->vrtl_carrier_sense) { /* 0:off 1:on 2:auto */
+ case 0: /* off */
+ psta->rtsen = 0;
+ psta->cts2self = 0;
+ break;
+ case 1: /* on */
+ if (pregpriv->vcs_type == 1) { /* 1:RTS/CTS 2:CTS to self */
+ psta->rtsen = 1;
+ psta->cts2self = 0;
+ } else {
+ psta->rtsen = 0;
+ psta->cts2self = 1;
+ }
+ break;
+ case 2: /* auto */
+ default:
+ if ((pmlmeinfo->ERP_enable) && (pmlmeinfo->ERP_IE & BIT(1))) {
+ if (pregpriv->vcs_type == 1) {
+ psta->rtsen = 1;
+ psta->cts2self = 0;
+ } else {
+ psta->rtsen = 0;
+ psta->cts2self = 1;
+ }
+ } else {
+ psta->rtsen = 0;
+ psta->cts2self = 0;
+ }
+ break;
+ }
+}
+
+int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len)
+{
+ unsigned int len;
+ unsigned char *p;
+ unsigned short val16, subtype;
+ struct wlan_network *cur_network = &Adapter->mlmepriv.cur_network;
+ u16 wpa_len = 0, rsn_len = 0;
+ u8 encryp_protocol = 0;
+ struct wlan_bssid_ex *bssid;
+ int group_cipher = 0, pairwise_cipher = 0, is_8021x = 0;
+ unsigned char *pbuf;
+ u32 wpa_ielen = 0;
+ u8 *pbssid = GetAddr3Ptr(pframe);
+ struct HT_info_element *pht_info = NULL;
+ u32 bcn_channel;
+ unsigned short ht_cap_info;
+ unsigned char ht_info_infos_0;
+ int ssid_len;
+
+ if (!is_client_associated_to_ap(Adapter))
+ return true;
+
+ len = packet_len - sizeof(struct ieee80211_hdr_3addr);
+
+ if (len > MAX_IE_SZ) {
+ DBG_88E("%s IE too long for survey event\n", __func__);
+ return _FAIL;
+ }
+
+ if (memcmp(cur_network->network.MacAddress, pbssid, 6)) {
+ DBG_88E("Oops: rtw_check_network_encrypt linked but recv other bssid bcn\n%pM %pM\n",
+ (pbssid), (cur_network->network.MacAddress));
+ return true;
+ }
+
+ bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC);
+ if (!bssid)
+ return _FAIL;
+
+ subtype = GetFrameSubType(pframe) >> 4;
+
+ if (subtype == WIFI_BEACON)
+ bssid->Reserved[0] = 1;
+
+ bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
+
+ /* below is to copy the information element */
+ bssid->ie_length = len;
+ memcpy(bssid->ies, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->ie_length);
+
+ /* check bw and channel offset */
+ /* parsing HT_CAP_IE */
+ p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
+ if (p && len > 0) {
+ struct ieee80211_ht_cap *ht_cap =
+ (struct ieee80211_ht_cap *)(p + 2);
+
+ ht_cap_info = le16_to_cpu(ht_cap->cap_info);
+ } else {
+ ht_cap_info = 0;
+ }
+ /* parsing HT_INFO_IE */
+ p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
+ if (p && len > 0) {
+ pht_info = (struct HT_info_element *)(p + 2);
+ ht_info_infos_0 = pht_info->infos[0];
+ } else {
+ ht_info_infos_0 = 0;
+ }
+ if (ht_cap_info != cur_network->BcnInfo.ht_cap_info ||
+ ((ht_info_infos_0 & 0x03) != (cur_network->BcnInfo.ht_info_infos_0 & 0x03))) {
+ DBG_88E("%s bcn now: ht_cap_info:%x ht_info_infos_0:%x\n", __func__,
+ ht_cap_info, ht_info_infos_0);
+ DBG_88E("%s bcn link: ht_cap_info:%x ht_info_infos_0:%x\n", __func__,
+ cur_network->BcnInfo.ht_cap_info, cur_network->BcnInfo.ht_info_infos_0);
+ DBG_88E("%s bw mode change, disconnect\n", __func__);
+ /* bcn_info_update */
+ cur_network->BcnInfo.ht_cap_info = ht_cap_info;
+ cur_network->BcnInfo.ht_info_infos_0 = ht_info_infos_0;
+ /* to do : need to check that whether modify related register of BB or not */
+ /* goto _mismatch; */
+ }
+
+ /* Checking for channel */
+ p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, _DSSET_IE_, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
+ if (p) {
+ bcn_channel = *(p + 2);
+ } else {/* In 5G, some ap do not have DSSET IE checking HT info for channel */
+ p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
+ if (pht_info) {
+ bcn_channel = pht_info->primary_channel;
+ } else { /* we don't find channel IE, so don't check it */
+ DBG_88E("Oops: %s we don't find channel IE, so don't check it\n", __func__);
+ bcn_channel = Adapter->mlmeextpriv.cur_channel;
+ }
+ }
+ if (bcn_channel != Adapter->mlmeextpriv.cur_channel) {
+ DBG_88E("%s beacon channel:%d cur channel:%d disconnect\n", __func__,
+ bcn_channel, Adapter->mlmeextpriv.cur_channel);
+ goto _mismatch;
+ }
+
+ /* checking SSID */
+ ssid_len = 0;
+ p = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, _SSID_IE_, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
+ if (p) {
+ ssid_len = *(p + 1);
+ if (ssid_len > NDIS_802_11_LENGTH_SSID)
+ ssid_len = 0;
+ }
+ memcpy(bssid->ssid.ssid, (p + 2), ssid_len);
+ bssid->ssid.ssid_length = ssid_len;
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("%s bssid.ssid.ssid:%s bssid.ssid.ssid_length:%d "
+ "cur_network->network.ssid.ssid:%s len:%d\n", __func__, bssid->ssid.ssid,
+ bssid->ssid.ssid_length, cur_network->network.ssid.ssid,
+ cur_network->network.ssid.ssid_length));
+
+ if (memcmp(bssid->ssid.ssid, cur_network->network.ssid.ssid, 32) ||
+ bssid->ssid.ssid_length != cur_network->network.ssid.ssid_length) {
+ if (bssid->ssid.ssid[0] != '\0' && bssid->ssid.ssid_length != 0) { /* not hidden ssid */
+ DBG_88E("%s(), SSID is not match return FAIL\n", __func__);
+ goto _mismatch;
+ }
+ }
+
+ /* check encryption info */
+ val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid);
+
+ if (val16 & BIT(4))
+ bssid->Privacy = 1;
+ else
+ bssid->Privacy = 0;
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
+ ("%s(): cur_network->network.Privacy is %d, bssid.Privacy is %d\n",
+ __func__, cur_network->network.Privacy, bssid->Privacy));
+ if (cur_network->network.Privacy != bssid->Privacy) {
+ DBG_88E("%s(), privacy is not match return FAIL\n", __func__);
+ goto _mismatch;
+ }
+
+ rtw_get_sec_ie(bssid->ies, bssid->ie_length, NULL, &rsn_len, NULL, &wpa_len);
+
+ if (rsn_len > 0) {
+ encryp_protocol = ENCRYP_PROTOCOL_WPA2;
+ } else if (wpa_len > 0) {
+ encryp_protocol = ENCRYP_PROTOCOL_WPA;
+ } else {
+ if (bssid->Privacy)
+ encryp_protocol = ENCRYP_PROTOCOL_WEP;
+ }
+
+ if (cur_network->BcnInfo.encryp_protocol != encryp_protocol) {
+ DBG_88E("%s(): encryption protocol is not match , return FAIL\n", __func__);
+ goto _mismatch;
+ }
+
+ if (encryp_protocol == ENCRYP_PROTOCOL_WPA || encryp_protocol == ENCRYP_PROTOCOL_WPA2) {
+ pbuf = rtw_get_wpa_ie(&bssid->ies[12], &wpa_ielen,
+ bssid->ie_length - 12);
+ if (pbuf && (wpa_ielen > 0)) {
+ if (_SUCCESS == rtw_parse_wpa_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is_8021x)) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
+ ("%s pnetwork->pairwise_cipher: %d, group_cipher is %d, is_8021x is %d\n", __func__,
+ pairwise_cipher, group_cipher, is_8021x));
+ }
+ } else {
+ pbuf = rtw_get_wpa2_ie(&bssid->ies[12], &wpa_ielen,
+ bssid->ie_length - 12);
+
+ if (pbuf && (wpa_ielen > 0)) {
+ if (_SUCCESS == rtw_parse_wpa2_ie(pbuf, wpa_ielen + 2, &group_cipher, &pairwise_cipher, &is_8021x)) {
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
+ ("%s pnetwork->pairwise_cipher: %d, pnetwork->group_cipher is %d, is_802x is %d\n",
+ __func__, pairwise_cipher, group_cipher, is_8021x));
+ }
+ }
+ }
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
+ ("%s cur_network->group_cipher is %d: %d\n", __func__, cur_network->BcnInfo.group_cipher, group_cipher));
+ if (pairwise_cipher != cur_network->BcnInfo.pairwise_cipher || group_cipher != cur_network->BcnInfo.group_cipher) {
+ DBG_88E("%s pairwise_cipher(%x:%x) or group_cipher(%x:%x) is not match , return FAIL\n", __func__,
+ pairwise_cipher, cur_network->BcnInfo.pairwise_cipher,
+ group_cipher, cur_network->BcnInfo.group_cipher);
+ goto _mismatch;
+ }
+
+ if (is_8021x != cur_network->BcnInfo.is_8021x) {
+ DBG_88E("%s authentication is not match , return FAIL\n", __func__);
+ goto _mismatch;
+ }
+ }
+
+ kfree(bssid);
+ return _SUCCESS;
+
+_mismatch:
+ kfree(bssid);
+ return _FAIL;
+}
+
+void update_beacon_info(struct adapter *padapter, u8 *pframe, uint pkt_len, struct sta_info *psta)
+{
+ unsigned int i;
+ unsigned int len;
+ struct ndis_802_11_var_ie *pIE;
+
+ len = pkt_len - (_BEACON_IE_OFFSET_ + WLAN_HDR_A3_LEN);
+
+ for (i = 0; i < len;) {
+ pIE = (struct ndis_802_11_var_ie *)(pframe + (_BEACON_IE_OFFSET_ + WLAN_HDR_A3_LEN) + i);
+
+ switch (pIE->ElementID) {
+ case _HT_EXTRA_INFO_IE_: /* HT info */
+ bwmode_update_check(padapter, pIE);
+ break;
+ case _ERPINFO_IE_:
+ ERP_IE_handler(padapter, pIE);
+ VCS_update(padapter, psta);
+ break;
+ default:
+ break;
+ }
+
+ i += (pIE->Length + 2);
+ }
+}
+
+unsigned int is_ap_in_tkip(struct adapter *padapter)
+{
+ u32 i;
+ struct ndis_802_11_var_ie *pIE;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
+
+ if (rtw_get_capability((struct wlan_bssid_ex *)cur_network) & WLAN_CAPABILITY_PRIVACY) {
+ for (i = sizeof(struct ndis_802_11_fixed_ie); i < pmlmeinfo->network.ie_length;) {
+ pIE = (struct ndis_802_11_var_ie *)(pmlmeinfo->network.ies + i);
+
+ switch (pIE->ElementID) {
+ case _VENDOR_SPECIFIC_IE_:
+ if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) && (!memcmp((pIE->data + 12), WPA_TKIP_CIPHER, 4)))
+ return true;
+ break;
+ case _RSN_IE_2_:
+ if (!memcmp((pIE->data + 8), RSN_TKIP_CIPHER, 4))
+ return true;
+ default:
+ break;
+ }
+
+ i += (pIE->Length + 2);
+ }
+ return false;
+ } else {
+ return false;
+ }
+}
+
+static int wifirate2_ratetbl_inx(unsigned char rate)
+{
+ rate = rate & 0x7f;
+
+ switch (rate) {
+ case 108:
+ return 11;
+ case 96:
+ return 10;
+ case 72:
+ return 9;
+ case 48:
+ return 8;
+ case 36:
+ return 7;
+ case 24:
+ return 6;
+ case 18:
+ return 5;
+ case 12:
+ return 4;
+ case 22:
+ return 3;
+ case 11:
+ return 2;
+ case 4:
+ return 1;
+ case 2:
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+unsigned int update_basic_rate(unsigned char *ptn, unsigned int ptn_sz)
+{
+ unsigned int i, num_of_rate;
+ unsigned int mask = 0;
+
+ num_of_rate = min_t(unsigned int, ptn_sz, NumRates);
+
+ for (i = 0; i < num_of_rate; i++) {
+ if ((*(ptn + i)) & 0x80)
+ mask |= 0x1 << wifirate2_ratetbl_inx(*(ptn + i));
+ }
+ return mask;
+}
+
+unsigned int update_supported_rate(unsigned char *ptn, unsigned int ptn_sz)
+{
+ unsigned int i, num_of_rate;
+ unsigned int mask = 0;
+
+ num_of_rate = min_t(unsigned int, ptn_sz, NumRates);
+
+ for (i = 0; i < num_of_rate; i++)
+ mask |= 0x1 << wifirate2_ratetbl_inx(*(ptn + i));
+ return mask;
+}
+
+unsigned int update_MSC_rate(struct ieee80211_ht_cap *pHT_caps)
+{
+ return (pHT_caps->mcs.rx_mask[0] << 12) |
+ (pHT_caps->mcs.rx_mask[1] << 20);
+}
+
+int support_short_GI(struct adapter *padapter, struct ieee80211_ht_cap *pHT_caps)
+{
+ unsigned char bit_offset;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ if (!(pmlmeinfo->HT_enable))
+ return _FAIL;
+
+ if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_RALINK)
+ return _FAIL;
+
+ bit_offset = (pmlmeext->cur_bwmode & HT_CHANNEL_WIDTH_40) ? 6 : 5;
+
+ if (__le16_to_cpu(pHT_caps->cap_info) & (0x1 << bit_offset))
+ return _SUCCESS;
+ else
+ return _FAIL;
+}
+
+unsigned char get_highest_rate_idx(u32 mask)
+{
+ int i;
+ unsigned char rate_idx = 0;
+
+ for (i = 27; i >= 0; i--) {
+ if (mask & BIT(i)) {
+ rate_idx = i;
+ break;
+ }
+ }
+ return rate_idx;
+}
+
+void Update_RA_Entry(struct adapter *padapter, u32 mac_id)
+{
+ rtw_hal_update_ra_mask(padapter, mac_id, 0);
+}
+
+void set_sta_rate(struct adapter *padapter, struct sta_info *psta)
+{
+ /* rate adaptive */
+ Update_RA_Entry(padapter, psta->mac_id);
+}
+
+/* Update RRSR and Rate for USERATE */
+void update_tx_basic_rate(struct adapter *padapter, u8 wirelessmode)
+{
+ unsigned char supported_rates[NDIS_802_11_LENGTH_RATES_EX];
+
+ memset(supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX);
+
+ if ((wirelessmode & WIRELESS_11B) && (wirelessmode == WIRELESS_11B))
+ memcpy(supported_rates, rtw_basic_rate_cck, 4);
+ else if (wirelessmode & WIRELESS_11B)
+ memcpy(supported_rates, rtw_basic_rate_mix, 7);
+ else
+ memcpy(supported_rates, rtw_basic_rate_ofdm, 3);
+
+ if (wirelessmode & WIRELESS_11B)
+ update_mgnt_tx_rate(padapter, IEEE80211_CCK_RATE_1MB);
+ else
+ update_mgnt_tx_rate(padapter, IEEE80211_OFDM_RATE_6MB);
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, supported_rates);
+}
+
+unsigned char check_assoc_AP(u8 *pframe, uint len)
+{
+ unsigned int i;
+ struct ndis_802_11_var_ie *pIE;
+ u8 epigram_vendor_flag;
+ u8 ralink_vendor_flag;
+
+ epigram_vendor_flag = 0;
+ ralink_vendor_flag = 0;
+
+ for (i = sizeof(struct ndis_802_11_fixed_ie); i < len;) {
+ pIE = (struct ndis_802_11_var_ie *)(pframe + i);
+
+ switch (pIE->ElementID) {
+ case _VENDOR_SPECIFIC_IE_:
+ if ((!memcmp(pIE->data, ARTHEROS_OUI1, 3)) ||
+ (!memcmp(pIE->data, ARTHEROS_OUI2, 3))) {
+ DBG_88E("link to Artheros AP\n");
+ return HT_IOT_PEER_ATHEROS;
+ } else if ((!memcmp(pIE->data, BROADCOM_OUI1, 3)) ||
+ (!memcmp(pIE->data, BROADCOM_OUI2, 3))) {
+ DBG_88E("link to Broadcom AP\n");
+ return HT_IOT_PEER_BROADCOM;
+ } else if (!memcmp(pIE->data, MARVELL_OUI, 3)) {
+ DBG_88E("link to Marvell AP\n");
+ return HT_IOT_PEER_MARVELL;
+ } else if (!memcmp(pIE->data, RALINK_OUI, 3)) {
+ if (!ralink_vendor_flag) {
+ ralink_vendor_flag = 1;
+ } else {
+ DBG_88E("link to Ralink AP\n");
+ return HT_IOT_PEER_RALINK;
+ }
+ } else if (!memcmp(pIE->data, CISCO_OUI, 3)) {
+ DBG_88E("link to Cisco AP\n");
+ return HT_IOT_PEER_CISCO;
+ } else if (!memcmp(pIE->data, REALTEK_OUI, 3)) {
+ DBG_88E("link to Realtek 96B\n");
+ return HT_IOT_PEER_REALTEK;
+ } else if (!memcmp(pIE->data, AIRGOCAP_OUI, 3)) {
+ DBG_88E("link to Airgo Cap\n");
+ return HT_IOT_PEER_AIRGO;
+ } else if (!memcmp(pIE->data, EPIGRAM_OUI, 3)) {
+ epigram_vendor_flag = 1;
+ if (ralink_vendor_flag) {
+ DBG_88E("link to Tenda W311R AP\n");
+ return HT_IOT_PEER_TENDA;
+ } else {
+ DBG_88E("Capture EPIGRAM_OUI\n");
+ }
+ } else {
+ break;
+ }
+
+ default:
+ break;
+ }
+ i += (pIE->Length + 2);
+ }
+
+ if (ralink_vendor_flag && !epigram_vendor_flag) {
+ DBG_88E("link to Ralink AP\n");
+ return HT_IOT_PEER_RALINK;
+ } else if (ralink_vendor_flag && epigram_vendor_flag) {
+ DBG_88E("link to Tenda W311R AP\n");
+ return HT_IOT_PEER_TENDA;
+ } else {
+ DBG_88E("link to new AP\n");
+ return HT_IOT_PEER_UNKNOWN;
+ }
+}
+
+void update_IOT_info(struct adapter *padapter)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ switch (pmlmeinfo->assoc_AP_vendor) {
+ case HT_IOT_PEER_MARVELL:
+ pmlmeinfo->turboMode_cts2self = 1;
+ pmlmeinfo->turboMode_rtsen = 0;
+ break;
+ case HT_IOT_PEER_RALINK:
+ pmlmeinfo->turboMode_cts2self = 0;
+ pmlmeinfo->turboMode_rtsen = 1;
+ /* disable high power */
+ Switch_DM_Func(padapter, (u32)(~DYNAMIC_BB_DYNAMIC_TXPWR),
+ false);
+ break;
+ case HT_IOT_PEER_REALTEK:
+ /* disable high power */
+ Switch_DM_Func(padapter, (u32)(~DYNAMIC_BB_DYNAMIC_TXPWR),
+ false);
+ break;
+ default:
+ pmlmeinfo->turboMode_cts2self = 0;
+ pmlmeinfo->turboMode_rtsen = 1;
+ break;
+ }
+}
+
+void update_capinfo(struct adapter *Adapter, u16 updateCap)
+{
+ struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ bool ShortPreamble;
+
+ /* Check preamble mode, 2005.01.06, by rcnjko. */
+ /* Mark to update preamble value forever, 2008.03.18 by lanhsin */
+
+ if (updateCap & cShortPreamble) { /* Short Preamble */
+ if (pmlmeinfo->preamble_mode != PREAMBLE_SHORT) { /* PREAMBLE_LONG or PREAMBLE_AUTO */
+ ShortPreamble = true;
+ pmlmeinfo->preamble_mode = PREAMBLE_SHORT;
+ rtw_hal_set_hwreg(Adapter, HW_VAR_ACK_PREAMBLE, (u8 *)&ShortPreamble);
+ }
+ } else { /* Long Preamble */
+ if (pmlmeinfo->preamble_mode != PREAMBLE_LONG) { /* PREAMBLE_SHORT or PREAMBLE_AUTO */
+ ShortPreamble = false;
+ pmlmeinfo->preamble_mode = PREAMBLE_LONG;
+ rtw_hal_set_hwreg(Adapter, HW_VAR_ACK_PREAMBLE, (u8 *)&ShortPreamble);
+ }
+ }
+
+ if (updateCap & cIBSS) {
+ /* Filen: See 802.11-2007 p.91 */
+ pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
+ } else { /* Filen: See 802.11-2007 p.90 */
+ if (pmlmeext->cur_wireless_mode & (WIRELESS_11G | WIRELESS_11_24N)) {
+ if (updateCap & cShortSlotTime) { /* Short Slot Time */
+ if (pmlmeinfo->slotTime != SHORT_SLOT_TIME)
+ pmlmeinfo->slotTime = SHORT_SLOT_TIME;
+ } else { /* Long Slot Time */
+ if (pmlmeinfo->slotTime != NON_SHORT_SLOT_TIME)
+ pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
+ }
+ } else if (pmlmeext->cur_wireless_mode & (WIRELESS_11A | WIRELESS_11_5N)) {
+ pmlmeinfo->slotTime = SHORT_SLOT_TIME;
+ } else {
+ /* B Mode */
+ pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
+ }
+ }
+
+ rtw_hal_set_hwreg(Adapter, HW_VAR_SLOT_TIME, &pmlmeinfo->slotTime);
+}
+
+void update_wireless_mode(struct adapter *padapter)
+{
+ int ratelen, network_type = 0;
+ u32 SIFS_Timer;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
+ unsigned char *rate = cur_network->SupportedRates;
+
+ ratelen = rtw_get_rateset_len(cur_network->SupportedRates);
+
+ if (pmlmeinfo->HT_info_enable && pmlmeinfo->HT_caps_enable)
+ pmlmeinfo->HT_enable = 1;
+
+ if (pmlmeinfo->HT_enable)
+ network_type = WIRELESS_11_24N;
+
+ if (cckratesonly_included(rate, ratelen))
+ network_type |= WIRELESS_11B;
+ else if (cckrates_included(rate, ratelen))
+ network_type |= WIRELESS_11BG;
+ else
+ network_type |= WIRELESS_11G;
+
+ pmlmeext->cur_wireless_mode = network_type & padapter->registrypriv.wireless_mode;
+
+ SIFS_Timer = 0x0a0a0808;/* 0x0808 -> for CCK, 0x0a0a -> for OFDM */
+ /* change this value if having IOT issues. */
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_RESP_SIFS, (u8 *)&SIFS_Timer);
+
+ update_mgnt_tx_rate(padapter,
+ pmlmeext->cur_wireless_mode & WIRELESS_11B ?
+ IEEE80211_CCK_RATE_1MB : IEEE80211_OFDM_RATE_6MB);
+}
+
+void update_bmc_sta_support_rate(struct adapter *padapter, u32 mac_id)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ if (pmlmeext->cur_wireless_mode & WIRELESS_11B) {
+ /* Only B, B/G, and B/G/N AP could use CCK rate */
+ memcpy((pmlmeinfo->FW_sta_info[mac_id].SupportedRates), rtw_basic_rate_cck, 4);
+ } else {
+ memcpy((pmlmeinfo->FW_sta_info[mac_id].SupportedRates), rtw_basic_rate_ofdm, 3);
+ }
+}
+
+int update_sta_support_rate(struct adapter *padapter, u8 *pvar_ie, uint var_ie_len, int cam_idx)
+{
+ unsigned int ie_len;
+ struct ndis_802_11_var_ie *pIE;
+ int supportRateNum = 0;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ pIE = (struct ndis_802_11_var_ie *)rtw_get_ie(pvar_ie, _SUPPORTEDRATES_IE_, &ie_len, var_ie_len);
+ if (!pIE)
+ return _FAIL;
+ if (ie_len > NDIS_802_11_LENGTH_RATES_EX)
+ return _FAIL;
+
+ memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates, pIE->data, ie_len);
+ supportRateNum = ie_len;
+
+ pIE = (struct ndis_802_11_var_ie *)rtw_get_ie(pvar_ie, _EXT_SUPPORTEDRATES_IE_, &ie_len, var_ie_len);
+ if (pIE) {
+ if (supportRateNum + ie_len > NDIS_802_11_LENGTH_RATES_EX)
+ return _FAIL;
+ memcpy((pmlmeinfo->FW_sta_info[cam_idx].SupportedRates + supportRateNum), pIE->data, ie_len);
+ }
+
+ return _SUCCESS;
+}
+
+void process_addba_req(struct adapter *padapter, u8 *paddba_req, u8 *addr)
+{
+ struct sta_info *psta;
+ u16 tid;
+ u16 param;
+ struct recv_reorder_ctrl *preorder_ctrl;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct ADDBA_request *preq = (struct ADDBA_request *)paddba_req;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ psta = rtw_get_stainfo(pstapriv, addr);
+
+ if (psta) {
+ param = le16_to_cpu(preq->BA_para_set);
+ tid = (param >> 2) & 0x0f;
+ preorder_ctrl = &psta->recvreorder_ctrl[tid];
+ preorder_ctrl->indicate_seq = 0xffff;
+ preorder_ctrl->enable = pmlmeinfo->accept_addba_req;
+ }
+}
+
+void update_TSF(struct mlme_ext_priv *pmlmeext, u8 *pframe, uint len)
+{
+ u8 *pIE;
+ __le32 *pbuf;
+
+ pIE = pframe + sizeof(struct ieee80211_hdr_3addr);
+ pbuf = (__le32 *)pIE;
+
+ pmlmeext->TSFValue = le32_to_cpu(*(pbuf + 1));
+
+ pmlmeext->TSFValue = pmlmeext->TSFValue << 32;
+
+ pmlmeext->TSFValue |= le32_to_cpu(*pbuf);
+}
+
+void correct_TSF(struct adapter *padapter, struct mlme_ext_priv *pmlmeext)
+{
+ rtw_hal_set_hwreg(padapter, HW_VAR_CORRECT_TSF, NULL);
+}
diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c
new file mode 100644
index 0000000..4eb2f33
--- /dev/null
+++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c
@@ -0,0 +1,2081 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _RTW_XMIT_C_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <mon.h>
+#include <wifi.h>
+#include <osdep_intf.h>
+#include <linux/vmalloc.h>
+
+static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
+static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
+
+static void _init_txservq(struct tx_servq *ptxservq)
+{
+ INIT_LIST_HEAD(&ptxservq->tx_pending);
+ _rtw_init_queue(&ptxservq->sta_pending);
+ ptxservq->qcnt = 0;
+}
+
+void _rtw_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv)
+{
+ memset((unsigned char *)psta_xmitpriv, 0, sizeof(struct sta_xmit_priv));
+ spin_lock_init(&psta_xmitpriv->lock);
+ _init_txservq(&psta_xmitpriv->be_q);
+ _init_txservq(&psta_xmitpriv->bk_q);
+ _init_txservq(&psta_xmitpriv->vi_q);
+ _init_txservq(&psta_xmitpriv->vo_q);
+ INIT_LIST_HEAD(&psta_xmitpriv->legacy_dz);
+ INIT_LIST_HEAD(&psta_xmitpriv->apsd);
+}
+
+s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
+{
+ int i;
+ struct xmit_buf *pxmitbuf;
+ struct xmit_frame *pxframe;
+ int res = _SUCCESS;
+ u32 max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ;
+ u32 num_xmit_extbuf = NR_XMIT_EXTBUFF;
+
+ /* We don't need to memset padapter->XXX to zero, because adapter is allocated by vzalloc(). */
+
+ spin_lock_init(&pxmitpriv->lock);
+
+ /*
+ Please insert all the queue initializaiton using _rtw_init_queue below
+ */
+
+ pxmitpriv->adapter = padapter;
+
+ _rtw_init_queue(&pxmitpriv->be_pending);
+ _rtw_init_queue(&pxmitpriv->bk_pending);
+ _rtw_init_queue(&pxmitpriv->vi_pending);
+ _rtw_init_queue(&pxmitpriv->vo_pending);
+ _rtw_init_queue(&pxmitpriv->bm_pending);
+
+ _rtw_init_queue(&pxmitpriv->free_xmit_queue);
+
+ /*
+ Please allocate memory with the sz = (struct xmit_frame) * NR_XMITFRAME,
+ and initialize free_xmit_frame below.
+ Please also apply free_txobj to link_up all the xmit_frames...
+ */
+
+ pxmitpriv->pallocated_frame_buf = vzalloc(NR_XMITFRAME * sizeof(struct xmit_frame) + 4);
+
+ if (!pxmitpriv->pallocated_frame_buf) {
+ pxmitpriv->pxmit_frame_buf = NULL;
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xmit_frame fail!\n"));
+ res = _FAIL;
+ goto exit;
+ }
+ pxmitpriv->pxmit_frame_buf = PTR_ALIGN(pxmitpriv->pallocated_frame_buf, 4);
+
+ pxframe = (struct xmit_frame *)pxmitpriv->pxmit_frame_buf;
+
+ for (i = 0; i < NR_XMITFRAME; i++) {
+ INIT_LIST_HEAD(&pxframe->list);
+
+ pxframe->padapter = padapter;
+ pxframe->frame_tag = NULL_FRAMETAG;
+
+ pxframe->pkt = NULL;
+
+ pxframe->buf_addr = NULL;
+ pxframe->pxmitbuf = NULL;
+
+ list_add_tail(&pxframe->list, &pxmitpriv->free_xmit_queue.queue);
+
+ pxframe++;
+ }
+
+ pxmitpriv->free_xmitframe_cnt = NR_XMITFRAME;
+
+ pxmitpriv->frag_len = MAX_FRAG_THRESHOLD;
+
+ /* init xmit_buf */
+ _rtw_init_queue(&pxmitpriv->free_xmitbuf_queue);
+ _rtw_init_queue(&pxmitpriv->pending_xmitbuf_queue);
+
+ pxmitpriv->pallocated_xmitbuf = vzalloc(NR_XMITBUFF * sizeof(struct xmit_buf) + 4);
+
+ if (!pxmitpriv->pallocated_xmitbuf) {
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xmit_buf fail!\n"));
+ res = _FAIL;
+ goto exit;
+ }
+
+ pxmitpriv->pxmitbuf = PTR_ALIGN(pxmitpriv->pallocated_xmitbuf, 4);
+
+ pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
+
+ for (i = 0; i < NR_XMITBUFF; i++) {
+ INIT_LIST_HEAD(&pxmitbuf->list);
+
+ pxmitbuf->priv_data = NULL;
+ pxmitbuf->padapter = padapter;
+ pxmitbuf->ext_tag = false;
+
+ /* Tx buf allocation may fail sometimes, so sleep and retry. */
+ res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ));
+ if (res == _FAIL) {
+ msleep(10);
+ res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ));
+ if (res == _FAIL)
+ goto exit;
+ }
+
+ pxmitbuf->flags = XMIT_VO_QUEUE;
+
+ list_add_tail(&pxmitbuf->list, &pxmitpriv->free_xmitbuf_queue.queue);
+ pxmitbuf++;
+ }
+
+ pxmitpriv->free_xmitbuf_cnt = NR_XMITBUFF;
+
+ /* Init xmit extension buff */
+ _rtw_init_queue(&pxmitpriv->free_xmit_extbuf_queue);
+
+ pxmitpriv->pallocated_xmit_extbuf = vzalloc(num_xmit_extbuf * sizeof(struct xmit_buf) + 4);
+
+ if (!pxmitpriv->pallocated_xmit_extbuf) {
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xmit_extbuf fail!\n"));
+ res = _FAIL;
+ goto exit;
+ }
+
+ pxmitpriv->pxmit_extbuf = PTR_ALIGN(pxmitpriv->pallocated_xmit_extbuf, 4);
+
+ pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf;
+
+ for (i = 0; i < num_xmit_extbuf; i++) {
+ INIT_LIST_HEAD(&pxmitbuf->list);
+
+ pxmitbuf->priv_data = NULL;
+ pxmitbuf->padapter = padapter;
+ pxmitbuf->ext_tag = true;
+
+ res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, max_xmit_extbuf_size + XMITBUF_ALIGN_SZ);
+ if (res == _FAIL) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ list_add_tail(&pxmitbuf->list, &pxmitpriv->free_xmit_extbuf_queue.queue);
+ pxmitbuf++;
+ }
+
+ pxmitpriv->free_xmit_extbuf_cnt = num_xmit_extbuf;
+
+ res = rtw_alloc_hwxmits(padapter);
+ if (res == _FAIL)
+ goto exit;
+ rtw_init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
+
+ for (i = 0; i < 4; i++)
+ pxmitpriv->wmm_para_seq[i] = i;
+
+ pxmitpriv->txirp_cnt = 1;
+
+ /* per AC pending irp */
+ pxmitpriv->beq_cnt = 0;
+ pxmitpriv->bkq_cnt = 0;
+ pxmitpriv->viq_cnt = 0;
+ pxmitpriv->voq_cnt = 0;
+
+ pxmitpriv->ack_tx = false;
+ mutex_init(&pxmitpriv->ack_tx_mutex);
+ rtw_sctx_init(&pxmitpriv->ack_tx_ops, 0);
+
+ rtw_hal_init_xmit_priv(padapter);
+
+exit:
+ return res;
+}
+
+void _rtw_free_xmit_priv(struct xmit_priv *pxmitpriv)
+{
+ int i;
+ struct adapter *padapter = pxmitpriv->adapter;
+ struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitpriv->pxmit_frame_buf;
+ struct xmit_buf *pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
+ u32 num_xmit_extbuf = NR_XMIT_EXTBUFF;
+
+ if (!pxmitpriv->pxmit_frame_buf)
+ return;
+
+ for (i = 0; i < NR_XMITFRAME; i++) {
+ rtw_os_xmit_complete(padapter, pxmitframe);
+
+ pxmitframe++;
+ }
+
+ for (i = 0; i < NR_XMITBUFF; i++) {
+ rtw_os_xmit_resource_free(pxmitbuf);
+ pxmitbuf++;
+ }
+
+ vfree(pxmitpriv->pallocated_frame_buf);
+ vfree(pxmitpriv->pallocated_xmitbuf);
+
+ /* free xmit extension buff */
+ pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf;
+ for (i = 0; i < num_xmit_extbuf; i++) {
+ rtw_os_xmit_resource_free(pxmitbuf);
+ pxmitbuf++;
+ }
+
+ vfree(pxmitpriv->pallocated_xmit_extbuf);
+
+ rtw_free_hwxmits(padapter);
+
+ mutex_destroy(&pxmitpriv->ack_tx_mutex);
+}
+
+static void update_attrib_vcs_info(struct adapter *padapter, struct xmit_frame *pxmitframe)
+{
+ u32 sz;
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+ struct sta_info *psta = pattrib->psta;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ if (pattrib->nr_frags != 1)
+ sz = padapter->xmitpriv.frag_len;
+ else /* no frag */
+ sz = pattrib->last_txcmdsz;
+
+ /* (1) RTS_Threshold is compared to the MPDU, not MSDU.
+ * (2) If there are more than one frag in this MSDU,
+ * only the first frag uses protection frame.
+ * Other fragments are protected by previous fragment.
+ * So we only need to check the length of first fragment.
+ */
+ if (pmlmeext->cur_wireless_mode < WIRELESS_11_24N || padapter->registrypriv.wifi_spec) {
+ if (sz > padapter->registrypriv.rts_thresh) {
+ pattrib->vcs_mode = RTS_CTS;
+ } else {
+ if (psta->rtsen)
+ pattrib->vcs_mode = RTS_CTS;
+ else if (psta->cts2self)
+ pattrib->vcs_mode = CTS_TO_SELF;
+ else
+ pattrib->vcs_mode = NONE_VCS;
+ }
+ } else {
+ while (true) {
+ /* IOT action */
+ if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_ATHEROS) && pattrib->ampdu_en &&
+ (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) {
+ pattrib->vcs_mode = CTS_TO_SELF;
+ break;
+ }
+
+ /* check ERP protection */
+ if (psta->rtsen || psta->cts2self) {
+ if (psta->rtsen)
+ pattrib->vcs_mode = RTS_CTS;
+ else if (psta->cts2self)
+ pattrib->vcs_mode = CTS_TO_SELF;
+
+ break;
+ }
+
+ /* check HT op mode */
+ if (pattrib->ht_en) {
+ u8 htopmode = pmlmeinfo->HT_protection;
+
+ if ((pmlmeext->cur_bwmode && (htopmode == 2 || htopmode == 3)) ||
+ (!pmlmeext->cur_bwmode && htopmode == 3)) {
+ pattrib->vcs_mode = RTS_CTS;
+ break;
+ }
+ }
+
+ /* check rts */
+ if (sz > padapter->registrypriv.rts_thresh) {
+ pattrib->vcs_mode = RTS_CTS;
+ break;
+ }
+
+ /* to do list: check MIMO power save condition. */
+
+ /* check AMPDU aggregation for TXOP */
+ if (pattrib->ampdu_en) {
+ pattrib->vcs_mode = RTS_CTS;
+ break;
+ }
+
+ pattrib->vcs_mode = NONE_VCS;
+ break;
+ }
+ }
+}
+
+static void update_attrib_phy_info(struct pkt_attrib *pattrib, struct sta_info *psta)
+{
+ pattrib->mdata = 0;
+ pattrib->eosp = 0;
+ pattrib->triggered = 0;
+
+ /* qos_en, ht_en, init rate, , bw, ch_offset, sgi */
+ pattrib->qos_en = psta->qos_option;
+
+ pattrib->raid = psta->raid;
+ pattrib->ht_en = psta->htpriv.ht_option;
+ pattrib->bwmode = psta->htpriv.bwmode;
+ pattrib->ch_offset = psta->htpriv.ch_offset;
+ pattrib->sgi = psta->htpriv.sgi;
+ pattrib->ampdu_en = false;
+ pattrib->retry_ctrl = false;
+}
+
+u8 qos_acm(u8 acm_mask, u8 priority)
+{
+ u8 change_priority = priority;
+
+ switch (priority) {
+ case 0:
+ case 3:
+ if (acm_mask & BIT(1))
+ change_priority = 1;
+ break;
+ case 1:
+ case 2:
+ break;
+ case 4:
+ case 5:
+ if (acm_mask & BIT(2))
+ change_priority = 0;
+ break;
+ case 6:
+ case 7:
+ if (acm_mask & BIT(3))
+ change_priority = 5;
+ break;
+ default:
+ DBG_88E("%s(): invalid pattrib->priority: %d!!!\n",
+ __func__, priority);
+ break;
+ }
+
+ return change_priority;
+}
+
+static void set_qos(struct sk_buff *skb, struct pkt_attrib *pattrib)
+{
+ if (pattrib->ether_type == 0x0800) {
+ struct iphdr ip_hdr;
+
+ skb_copy_bits(skb, ETH_HLEN, &ip_hdr, sizeof(ip_hdr));
+ pattrib->priority = ip_hdr.tos >> 5;
+ } else if (pattrib->ether_type == ETH_P_PAE) {
+ /* When priority processing of data frames is supported,
+ * a STA's SME should send EAPOL-Key frames at the highest
+ * priority.
+ */
+ pattrib->priority = 7;
+ } else {
+ pattrib->priority = 0;
+ }
+
+ pattrib->hdrlen = WLAN_HDR_A3_QOS_LEN;
+ pattrib->subtype = WIFI_QOS_DATA_TYPE;
+}
+
+static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct pkt_attrib *pattrib)
+{
+ struct sta_info *psta = NULL;
+ struct ethhdr etherhdr;
+
+ bool mcast;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct qos_priv *pqospriv = &pmlmepriv->qospriv;
+ int res = _SUCCESS;
+
+ skb_copy_bits(pkt, 0, &etherhdr, ETH_HLEN);
+
+ pattrib->ether_type = ntohs(etherhdr.h_proto);
+
+ memcpy(pattrib->dst, &etherhdr.h_dest, ETH_ALEN);
+ memcpy(pattrib->src, &etherhdr.h_source, ETH_ALEN);
+
+ pattrib->pctrl = 0;
+
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
+ check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
+ memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
+ memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+ } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
+ memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
+ memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+ } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+ memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
+ memcpy(pattrib->ta, get_bssid(pmlmepriv), ETH_ALEN);
+ }
+
+ pattrib->pktlen = pkt->len - ETH_HLEN;
+
+ if (pattrib->ether_type == ETH_P_IP) {
+ /* The following is for DHCP and ARP packet, we use
+ * cck1M to tx these packets and let LPS awake some
+ * time to prevent DHCP protocol fail.
+ */
+ u8 tmp[24];
+
+ skb_copy_bits(pkt, ETH_HLEN, tmp, 24);
+
+ pattrib->dhcp_pkt = 0;
+ if (pkt->len > ETH_HLEN + 24 + 282) {/* MINIMUM_DHCP_PACKET_SIZE) { */
+ if (pattrib->ether_type == ETH_P_IP) {/* IP header */
+ if (((tmp[21] == 68) && (tmp[23] == 67)) ||
+ ((tmp[21] == 67) && (tmp[23] == 68))) {
+ /* 68 : UDP BOOTP client */
+ /* 67 : UDP BOOTP server */
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("====================== %s: get DHCP Packet\n", __func__));
+ /* Use low rate to send DHCP packet. */
+ pattrib->dhcp_pkt = 1;
+ }
+ }
+ }
+ } else if (pattrib->ether_type == ETH_P_PAE) {
+ DBG_88E_LEVEL(_drv_info_, "send eapol packet\n");
+ }
+
+ if ((pattrib->ether_type == ETH_P_PAE) || (pattrib->dhcp_pkt == 1))
+ rtw_set_scan_deny(padapter, 3000);
+
+ /* If EAPOL , ARP , OR DHCP packet, driver must be in active mode. */
+ if ((pattrib->ether_type == ETH_P_ARP) || (pattrib->ether_type == ETH_P_PAE) || (pattrib->dhcp_pkt == 1))
+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SPECIAL_PACKET, 1);
+
+ mcast = is_multicast_ether_addr(pattrib->ra);
+
+ /* get sta_info */
+ if (mcast) {
+ psta = rtw_get_bcmc_stainfo(padapter);
+ } else {
+ psta = rtw_get_stainfo(pstapriv, pattrib->ra);
+ if (!psta) { /* if we cannot get psta => drrp the pkt */
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, ("\nupdate_attrib => get sta_info fail, ra: %pM\n", (pattrib->ra)));
+ res = _FAIL;
+ goto exit;
+ } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) &&
+ !(psta->state & _FW_LINKED)) {
+ res = _FAIL;
+ goto exit;
+ }
+ }
+
+ if (psta) {
+ pattrib->mac_id = psta->mac_id;
+ /* DBG_88E("%s ==> mac_id(%d)\n", __func__, pattrib->mac_id); */
+ pattrib->psta = psta;
+ } else {
+ /* if we cannot get psta => drop the pkt */
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, ("\nupdate_attrib => get sta_info fail, ra:%pM\n", (pattrib->ra)));
+ res = _FAIL;
+ goto exit;
+ }
+
+ pattrib->ack_policy = 0;
+
+ pattrib->hdrlen = WLAN_HDR_A3_LEN;
+ pattrib->subtype = WIFI_DATA_TYPE;
+ pattrib->priority = 0;
+
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE |
+ WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) {
+ if (psta->qos_option)
+ set_qos(pkt, pattrib);
+ } else {
+ if (pqospriv->qos_option) {
+ set_qos(pkt, pattrib);
+
+ if (pmlmepriv->acm_mask != 0)
+ pattrib->priority = qos_acm(pmlmepriv->acm_mask, pattrib->priority);
+ }
+ }
+
+ if (psta->ieee8021x_blocked) {
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("\n psta->ieee8021x_blocked == true\n"));
+
+ pattrib->encrypt = 0;
+
+ if (pattrib->ether_type != ETH_P_PAE) {
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("\npsta->ieee8021x_blocked == true, pattrib->ether_type(%.4x) != ETH_P_PAE\n", pattrib->ether_type));
+ res = _FAIL;
+ goto exit;
+ }
+ } else {
+ GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, mcast);
+
+ switch (psecuritypriv->dot11AuthAlgrthm) {
+ case dot11AuthAlgrthm_Open:
+ case dot11AuthAlgrthm_Shared:
+ case dot11AuthAlgrthm_Auto:
+ pattrib->key_idx = (u8)psecuritypriv->dot11PrivacyKeyIndex;
+ break;
+ case dot11AuthAlgrthm_8021X:
+ if (mcast)
+ pattrib->key_idx = (u8)psecuritypriv->dot118021XGrpKeyid;
+ else
+ pattrib->key_idx = 0;
+ break;
+ default:
+ pattrib->key_idx = 0;
+ break;
+ }
+ }
+
+ switch (pattrib->encrypt) {
+ case _WEP40_:
+ case _WEP104_:
+ pattrib->iv_len = 4;
+ pattrib->icv_len = 4;
+ break;
+ case _TKIP_:
+ pattrib->iv_len = 8;
+ pattrib->icv_len = 4;
+
+ if (padapter->securitypriv.busetkipkey == _FAIL) {
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
+ ("\npadapter->securitypriv.busetkipkey(%d) == _FAIL drop packet\n",
+ padapter->securitypriv.busetkipkey));
+ res = _FAIL;
+ goto exit;
+ }
+ break;
+ case _AES_:
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("pattrib->encrypt=%d (_AES_)\n", pattrib->encrypt));
+ pattrib->iv_len = 8;
+ pattrib->icv_len = 8;
+ break;
+ default:
+ pattrib->iv_len = 0;
+ pattrib->icv_len = 0;
+ break;
+ }
+
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
+ ("%s: encrypt=%d\n", __func__, pattrib->encrypt));
+
+ if (pattrib->encrypt && !psecuritypriv->hw_decrypted) {
+ pattrib->bswenc = true;
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
+ ("%s: encrypt=%d bswenc = true\n", __func__,
+ pattrib->encrypt));
+ } else {
+ pattrib->bswenc = false;
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("%s: bswenc = false\n", __func__));
+ }
+
+ update_attrib_phy_info(pattrib, psta);
+
+exit:
+ return res;
+}
+
+static s32 xmitframe_addmic(struct adapter *padapter, struct xmit_frame *pxmitframe)
+{
+ int curfragnum, length;
+ u8 *pframe, *payload, mic[8];
+ struct mic_data micdata;
+ struct sta_info *stainfo;
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ u8 priority[4] = {};
+ u8 hw_hdr_offset = 0;
+
+ if (pattrib->psta)
+ stainfo = pattrib->psta;
+ else
+ stainfo = rtw_get_stainfo(&padapter->stapriv, &pattrib->ra[0]);
+
+ hw_hdr_offset = TXDESC_SIZE + (pxmitframe->pkt_offset * PACKET_OFFSET_SZ);
+
+ if (pattrib->encrypt == _TKIP_) {
+ /* encode mic code */
+ if (stainfo) {
+ u8 null_key[16] = {};
+
+ pframe = pxmitframe->buf_addr + hw_hdr_offset;
+
+ if (is_multicast_ether_addr(pattrib->ra)) {
+ if (!memcmp(psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey, null_key, 16))
+ return _FAIL;
+ /* start to calculate the mic code */
+ rtw_secmicsetkey(&micdata, psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey);
+ } else {
+ if (!memcmp(&stainfo->dot11tkiptxmickey.skey[0], null_key, 16))
+ return _FAIL;
+ /* start to calculate the mic code */
+ rtw_secmicsetkey(&micdata, &stainfo->dot11tkiptxmickey.skey[0]);
+ }
+
+ if (pframe[1] & 1) { /* ToDS == 1 */
+ rtw_secmicappend(&micdata, &pframe[16], 6); /* DA */
+ if (pframe[1] & 2) /* From Ds == 1 */
+ rtw_secmicappend(&micdata, &pframe[24], 6);
+ else
+ rtw_secmicappend(&micdata, &pframe[10], 6);
+ } else { /* ToDS == 0 */
+ rtw_secmicappend(&micdata, &pframe[4], 6); /* DA */
+ if (pframe[1] & 2) /* From Ds == 1 */
+ rtw_secmicappend(&micdata, &pframe[16], 6);
+ else
+ rtw_secmicappend(&micdata, &pframe[10], 6);
+ }
+
+ if (pattrib->qos_en)
+ priority[0] = (u8)pxmitframe->attrib.priority;
+
+ rtw_secmicappend(&micdata, &priority[0], 4);
+
+ payload = pframe;
+
+ for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
+ payload = (u8 *)round_up((size_t)(payload), 4);
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
+ ("=== curfragnum=%d, pframe = 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x,!!!\n",
+ curfragnum, *payload, *(payload + 1),
+ *(payload + 2), *(payload + 3),
+ *(payload + 4), *(payload + 5),
+ *(payload + 6), *(payload + 7)));
+
+ payload += pattrib->hdrlen + pattrib->iv_len;
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
+ ("curfragnum=%d pattrib->hdrlen=%d pattrib->iv_len=%d",
+ curfragnum, pattrib->hdrlen, pattrib->iv_len));
+ if (curfragnum + 1 == pattrib->nr_frags) {
+ length = pattrib->last_txcmdsz -
+ pattrib->hdrlen -
+ pattrib->iv_len -
+ ((pattrib->bswenc) ?
+ pattrib->icv_len : 0);
+ rtw_secmicappend(&micdata, payload, length);
+ payload += length;
+ } else {
+ length = pxmitpriv->frag_len -
+ pattrib->hdrlen -
+ pattrib->iv_len -
+ ((pattrib->bswenc) ?
+ pattrib->icv_len : 0);
+ rtw_secmicappend(&micdata, payload, length);
+ payload += length + pattrib->icv_len;
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("curfragnum=%d length=%d pattrib->icv_len=%d", curfragnum, length, pattrib->icv_len));
+ }
+ }
+ rtw_secgetmic(&micdata, &mic[0]);
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("%s: before add mic code!!!\n", __func__));
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("%s: pattrib->last_txcmdsz=%d!!!\n", __func__, pattrib->last_txcmdsz));
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("%s: mic[0]=0x%.2x , mic[1]=0x%.2x , mic[2]= 0x%.2x, mic[3]=0x%.2x\n\
+ mic[4]= 0x%.2x , mic[5]= 0x%.2x , mic[6]= 0x%.2x , mic[7]= 0x%.2x !!!!\n",
+ __func__, mic[0], mic[1], mic[2], mic[3], mic[4], mic[5], mic[6], mic[7]));
+ /* add mic code and add the mic code length in last_txcmdsz */
+
+ memcpy(payload, &mic[0], 8);
+ pattrib->last_txcmdsz += 8;
+
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("\n ======== last pkt ========\n"));
+ payload -= pattrib->last_txcmdsz + 8;
+ for (curfragnum = 0; curfragnum < pattrib->last_txcmdsz; curfragnum += 8)
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
+ (" %.2x, %.2x, %.2x, %.2x, %.2x, %.2x, %.2x, %.2x ",
+ *(payload + curfragnum), *(payload + curfragnum + 1),
+ *(payload + curfragnum + 2), *(payload + curfragnum + 3),
+ *(payload + curfragnum + 4), *(payload + curfragnum + 5),
+ *(payload + curfragnum + 6), *(payload + curfragnum + 7)));
+ } else {
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("%s: rtw_get_stainfo==NULL!!!\n", __func__));
+ }
+ }
+
+ return _SUCCESS;
+}
+
+static s32 xmitframe_swencrypt(struct adapter *padapter, struct xmit_frame *pxmitframe)
+{
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+
+ if (pattrib->bswenc) {
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, ("### %s\n", __func__));
+ switch (pattrib->encrypt) {
+ case _WEP40_:
+ case _WEP104_:
+ rtw_wep_encrypt(padapter, (u8 *)pxmitframe);
+ break;
+ case _TKIP_:
+ rtw_tkip_encrypt(padapter, (u8 *)pxmitframe);
+ break;
+ case _AES_:
+ rtw_aes_encrypt(padapter, (u8 *)pxmitframe);
+ break;
+ default:
+ break;
+ }
+ } else {
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_, ("### xmitframe_hwencrypt\n"));
+ }
+
+ return _SUCCESS;
+}
+
+s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr, struct pkt_attrib *pattrib)
+{
+ u16 *qc;
+
+ struct ieee80211_hdr *pwlanhdr = (struct ieee80211_hdr *)hdr;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct qos_priv *pqospriv = &pmlmepriv->qospriv;
+ u8 qos_option = false;
+
+ int res = _SUCCESS;
+ __le16 *fctrl = &pwlanhdr->frame_control;
+
+ struct sta_info *psta;
+
+ if (pattrib->psta) {
+ psta = pattrib->psta;
+ } else {
+ if (is_multicast_ether_addr(pattrib->ra))
+ psta = rtw_get_bcmc_stainfo(padapter);
+ else
+ psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
+ }
+
+ memset(hdr, 0, WLANHDR_OFFSET);
+
+ SetFrameSubType(fctrl, pattrib->subtype);
+
+ if (pattrib->subtype & WIFI_DATA_TYPE) {
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
+ /* to_ds = 1, fr_ds = 0; */
+ /* Data transfer to AP */
+ SetToDs(fctrl);
+ memcpy(pwlanhdr->addr1, get_bssid(pmlmepriv), ETH_ALEN);
+ memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
+ memcpy(pwlanhdr->addr3, pattrib->dst, ETH_ALEN);
+
+ if (pqospriv->qos_option)
+ qos_option = true;
+ } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+ /* to_ds = 0, fr_ds = 1; */
+ SetFrDs(fctrl);
+ memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, get_bssid(pmlmepriv), ETH_ALEN);
+ memcpy(pwlanhdr->addr3, pattrib->src, ETH_ALEN);
+
+ if (psta && psta->qos_option)
+ qos_option = true;
+ } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
+ check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
+ memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
+ memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
+ memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv), ETH_ALEN);
+
+ if (psta && psta->qos_option)
+ qos_option = true;
+ } else {
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("fw_state:%x is not allowed to xmit frame\n", get_fwstate(pmlmepriv)));
+ res = _FAIL;
+ goto exit;
+ }
+
+ if (pattrib->mdata)
+ SetMData(fctrl);
+
+ if (pattrib->encrypt)
+ SetPrivacy(fctrl);
+
+ if (qos_option) {
+ qc = (unsigned short *)(hdr + pattrib->hdrlen - 2);
+
+ if (pattrib->priority)
+ SetPriority(qc, pattrib->priority);
+
+ SetEOSP(qc, pattrib->eosp);
+
+ SetAckpolicy(qc, pattrib->ack_policy);
+ }
+
+ /* TODO: fill HT Control Field */
+
+ /* Update Seq Num will be handled by f/w */
+ if (psta) {
+ psta->sta_xmitpriv.txseq_tid[pattrib->priority]++;
+ psta->sta_xmitpriv.txseq_tid[pattrib->priority] &= 0xFFF;
+
+ pattrib->seqnum = psta->sta_xmitpriv.txseq_tid[pattrib->priority];
+
+ SetSeqNum(hdr, pattrib->seqnum);
+
+ /* check if enable ampdu */
+ if (pattrib->ht_en && psta->htpriv.ampdu_enable) {
+ if (psta->htpriv.agg_enable_bitmap & BIT(pattrib->priority))
+ pattrib->ampdu_en = true;
+ }
+
+ /* re-check if enable ampdu by BA_starting_seqctrl */
+ if (pattrib->ampdu_en) {
+ u16 tx_seq;
+
+ tx_seq = psta->BA_starting_seqctrl[pattrib->priority & 0x0f];
+
+ /* check BA_starting_seqctrl */
+ if (SN_LESS(pattrib->seqnum, tx_seq)) {
+ pattrib->ampdu_en = false;/* AGG BK */
+ } else if (SN_EQUAL(pattrib->seqnum, tx_seq)) {
+ psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (tx_seq + 1) & 0xfff;
+
+ pattrib->ampdu_en = true;/* AGG EN */
+ } else {
+ psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (pattrib->seqnum + 1) & 0xfff;
+ pattrib->ampdu_en = true;/* AGG EN */
+ }
+ }
+ }
+ }
+exit:
+
+ return res;
+}
+
+s32 rtw_txframes_pending(struct adapter *padapter)
+{
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+ return (!list_empty(&pxmitpriv->be_pending.queue) ||
+ !list_empty(&pxmitpriv->bk_pending.queue) ||
+ !list_empty(&pxmitpriv->vi_pending.queue) ||
+ !list_empty(&pxmitpriv->vo_pending.queue));
+}
+
+s32 rtw_txframes_sta_ac_pending(struct adapter *padapter, struct pkt_attrib *pattrib)
+{
+ struct sta_info *psta;
+ struct tx_servq *ptxservq;
+ int priority = pattrib->priority;
+
+ psta = pattrib->psta;
+
+ switch (priority) {
+ case 1:
+ case 2:
+ ptxservq = &psta->sta_xmitpriv.bk_q;
+ break;
+ case 4:
+ case 5:
+ ptxservq = &psta->sta_xmitpriv.vi_q;
+ break;
+ case 6:
+ case 7:
+ ptxservq = &psta->sta_xmitpriv.vo_q;
+ break;
+ case 0:
+ case 3:
+ default:
+ ptxservq = &psta->sta_xmitpriv.be_q;
+ break;
+ }
+
+ return ptxservq->qcnt;
+}
+
+/*
+
+This sub-routine will perform all the following:
+
+1. remove 802.3 header.
+2. create wlan_header, based on the info in pxmitframe
+3. append sta's iv/ext-iv
+4. append LLC
+5. move frag chunk from pframe to pxmitframe->mem
+6. apply sw-encrypt, if necessary.
+
+*/
+s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct xmit_frame *pxmitframe)
+{
+ s32 frg_inx, frg_len, mpdu_len, llc_sz, mem_sz;
+ size_t addr;
+ u8 *pframe, *mem_start;
+ u8 hw_hdr_offset;
+ struct sta_info *psta;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+ u8 *pbuf_start;
+ bool mcast = is_multicast_ether_addr(pattrib->ra);
+ s32 res = _SUCCESS;
+ size_t remainder = pkt->len - ETH_HLEN;
+
+ psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
+
+ if (!psta)
+ return _FAIL;
+
+ if (!pxmitframe->buf_addr) {
+ DBG_88E("==> %s buf_addr == NULL\n", __func__);
+ return _FAIL;
+ }
+
+ pbuf_start = pxmitframe->buf_addr;
+
+ hw_hdr_offset = TXDESC_SIZE + (pxmitframe->pkt_offset * PACKET_OFFSET_SZ);
+
+ mem_start = pbuf_start + hw_hdr_offset;
+
+ if (rtw_make_wlanhdr(padapter, mem_start, pattrib) == _FAIL) {
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("%s: rtw_make_wlanhdr fail; drop pkt\n", __func__));
+ DBG_88E("%s: rtw_make_wlanhdr fail; drop pkt\n", __func__);
+ res = _FAIL;
+ goto exit;
+ }
+
+ frg_inx = 0;
+ frg_len = pxmitpriv->frag_len - 4;/* 2346-4 = 2342 */
+
+ while (1) {
+ llc_sz = 0;
+
+ mpdu_len = frg_len;
+
+ pframe = mem_start;
+
+ SetMFrag(mem_start);
+
+ pframe += pattrib->hdrlen;
+ mpdu_len -= pattrib->hdrlen;
+
+ /* adding icv, if necessary... */
+ if (pattrib->iv_len) {
+ switch (pattrib->encrypt) {
+ case _WEP40_:
+ case _WEP104_:
+ WEP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
+ break;
+ case _TKIP_:
+ if (mcast)
+ TKIP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
+ else
+ TKIP_IV(pattrib->iv, psta->dot11txpn, 0);
+ break;
+ case _AES_:
+ if (mcast)
+ AES_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
+ else
+ AES_IV(pattrib->iv, psta->dot11txpn, 0);
+ break;
+ }
+
+ memcpy(pframe, pattrib->iv, pattrib->iv_len);
+
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_,
+ ("%s: keyid=%d pattrib->iv[3]=%.2x pframe=%.2x %.2x %.2x %.2x\n",
+ __func__,
+ padapter->securitypriv.dot11PrivacyKeyIndex,
+ pattrib->iv[3], *pframe, *(pframe + 1),
+ *(pframe + 2), *(pframe + 3)));
+
+ pframe += pattrib->iv_len;
+
+ mpdu_len -= pattrib->iv_len;
+ }
+
+ if (frg_inx == 0) {
+ llc_sz = rtw_put_snap(pframe, pattrib->ether_type);
+ pframe += llc_sz;
+ mpdu_len -= llc_sz;
+ }
+
+ if ((pattrib->icv_len > 0) && (pattrib->bswenc))
+ mpdu_len -= pattrib->icv_len;
+
+ mem_sz = min_t(size_t, mcast ? pattrib->pktlen : mpdu_len, remainder);
+ skb_copy_bits(pkt, pkt->len - remainder, pframe, mem_sz);
+ remainder -= mem_sz;
+
+ pframe += mem_sz;
+
+ if ((pattrib->icv_len > 0) && (pattrib->bswenc)) {
+ memcpy(pframe, pattrib->icv, pattrib->icv_len);
+ pframe += pattrib->icv_len;
+ }
+
+ frg_inx++;
+
+ if (mcast || remainder == 0) {
+ pattrib->nr_frags = frg_inx;
+
+ pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->iv_len + ((pattrib->nr_frags == 1) ? llc_sz : 0) +
+ ((pattrib->bswenc) ? pattrib->icv_len : 0) + mem_sz;
+
+ ClearMFrag(mem_start);
+
+ break;
+ } else {
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("%s: There're still something in packet!\n", __func__));
+ }
+
+ addr = (size_t)(pframe);
+
+ mem_start = (unsigned char *)round_up(addr, 4) + hw_hdr_offset;
+ memcpy(mem_start, pbuf_start + hw_hdr_offset, pattrib->hdrlen);
+ }
+
+ /* Frame is about to be encrypted. Forward it to the monitor first. */
+ rtl88eu_mon_xmit_hook(padapter->pmondev, pxmitframe, frg_len);
+
+ if (xmitframe_addmic(padapter, pxmitframe) == _FAIL) {
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n"));
+ DBG_88E("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n");
+ res = _FAIL;
+ goto exit;
+ }
+
+ xmitframe_swencrypt(padapter, pxmitframe);
+
+ if (!mcast)
+ update_attrib_vcs_info(padapter, pxmitframe);
+ else
+ pattrib->vcs_mode = NONE_VCS;
+
+exit:
+ return res;
+}
+
+/* Logical Link Control(LLC) SubNetwork Attachment Point(SNAP) header
+ * IEEE LLC/SNAP header contains 8 octets
+ * First 3 octets comprise the LLC portion
+ * SNAP portion, 5 octets, is divided into two fields:
+ * Organizationally Unique Identifier(OUI), 3 octets,
+ * type, defined by that organization, 2 octets.
+ */
+s32 rtw_put_snap(u8 *data, u16 h_proto)
+{
+ struct ieee80211_snap_hdr *snap;
+ u8 *oui;
+
+ snap = (struct ieee80211_snap_hdr *)data;
+ snap->dsap = 0xaa;
+ snap->ssap = 0xaa;
+ snap->ctrl = 0x03;
+
+ if (h_proto == 0x8137 || h_proto == 0x80f3)
+ oui = P802_1H_OUI;
+ else
+ oui = RFC1042_OUI;
+
+ snap->oui[0] = oui[0];
+ snap->oui[1] = oui[1];
+ snap->oui[2] = oui[2];
+
+ *(__be16 *)(data + SNAP_SIZE) = htons(h_proto);
+
+ return SNAP_SIZE + sizeof(u16);
+}
+
+void rtw_update_protection(struct adapter *padapter, u8 *ie, uint ie_len)
+{
+ uint protection, erp_len;
+ u8 *perp;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
+
+ switch (pxmitpriv->vcs_setting) {
+ case DISABLE_VCS:
+ pxmitpriv->vcs = NONE_VCS;
+ break;
+ case ENABLE_VCS:
+ break;
+ case AUTO_VCS:
+ default:
+ perp = rtw_get_ie(ie, _ERPINFO_IE_, &erp_len, ie_len);
+ if (!perp) {
+ pxmitpriv->vcs = NONE_VCS;
+ } else {
+ protection = (*(perp + 2)) & BIT(1);
+ if (protection) {
+ if (pregistrypriv->vcs_type == RTS_CTS)
+ pxmitpriv->vcs = RTS_CTS;
+ else
+ pxmitpriv->vcs = CTS_TO_SELF;
+ } else {
+ pxmitpriv->vcs = NONE_VCS;
+ }
+ }
+ break;
+ }
+}
+
+void rtw_count_tx_stats(struct adapter *padapter, struct xmit_frame *pxmitframe, int sz)
+{
+ struct sta_info *psta = NULL;
+ struct stainfo_stats *pstats = NULL;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ if ((pxmitframe->frame_tag & 0x0f) == DATA_FRAMETAG) {
+ pxmitpriv->tx_bytes += sz;
+ pmlmepriv->LinkDetectInfo.NumTxOkInPeriod += pxmitframe->agg_num;
+
+ psta = pxmitframe->attrib.psta;
+ if (psta) {
+ pstats = &psta->sta_stats;
+ pstats->tx_pkts += pxmitframe->agg_num;
+ pstats->tx_bytes += sz;
+ }
+ }
+}
+
+struct xmit_buf *rtw_alloc_xmitbuf_ext(struct xmit_priv *pxmitpriv)
+{
+ unsigned long irql;
+ struct xmit_buf *pxmitbuf;
+ struct __queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue;
+
+ spin_lock_irqsave(&pfree_queue->lock, irql);
+ pxmitbuf = list_first_entry_or_null(&pfree_queue->queue,
+ struct xmit_buf, list);
+ if (pxmitbuf) {
+ list_del_init(&pxmitbuf->list);
+ pxmitpriv->free_xmit_extbuf_cnt--;
+ pxmitbuf->priv_data = NULL;
+ if (pxmitbuf->sctx) {
+ DBG_88E("%s pxmitbuf->sctx is not NULL\n", __func__);
+ rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC);
+ }
+ }
+ spin_unlock_irqrestore(&pfree_queue->lock, irql);
+
+ return pxmitbuf;
+}
+
+s32 rtw_free_xmitbuf_ext(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
+{
+ unsigned long irql;
+ struct __queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue;
+
+ if (!pxmitbuf)
+ return _FAIL;
+
+ spin_lock_irqsave(&pfree_queue->lock, irql);
+
+ list_del_init(&pxmitbuf->list);
+
+ list_add_tail(&pxmitbuf->list, get_list_head(pfree_queue));
+ pxmitpriv->free_xmit_extbuf_cnt++;
+
+ spin_unlock_irqrestore(&pfree_queue->lock, irql);
+
+ return _SUCCESS;
+}
+
+struct xmit_buf *rtw_alloc_xmitbuf(struct xmit_priv *pxmitpriv)
+{
+ unsigned long irql;
+ struct xmit_buf *pxmitbuf;
+ struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
+
+ spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irql);
+ pxmitbuf = list_first_entry_or_null(&pfree_xmitbuf_queue->queue,
+ struct xmit_buf, list);
+ if (pxmitbuf) {
+ list_del_init(&pxmitbuf->list);
+ pxmitpriv->free_xmitbuf_cnt--;
+ pxmitbuf->priv_data = NULL;
+ if (pxmitbuf->sctx) {
+ DBG_88E("%s pxmitbuf->sctx is not NULL\n", __func__);
+ rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC);
+ }
+ }
+ spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irql);
+
+ return pxmitbuf;
+}
+
+s32 rtw_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
+{
+ unsigned long irql;
+ struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
+
+ if (!pxmitbuf)
+ return _FAIL;
+
+ if (pxmitbuf->sctx) {
+ DBG_88E("%s pxmitbuf->sctx is not NULL\n", __func__);
+ rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_FREE);
+ }
+
+ if (pxmitbuf->ext_tag) {
+ rtw_free_xmitbuf_ext(pxmitpriv, pxmitbuf);
+ } else {
+ spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irql);
+
+ list_del_init(&pxmitbuf->list);
+
+ list_add_tail(&pxmitbuf->list, get_list_head(pfree_xmitbuf_queue));
+
+ pxmitpriv->free_xmitbuf_cnt++;
+ spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irql);
+ }
+
+ return _SUCCESS;
+}
+
+/*
+Calling context:
+1. OS_TXENTRY
+2. RXENTRY (rx_thread or RX_ISR/RX_CallBack)
+
+If we turn on USE_RXTHREAD, then, no need for critical section.
+Otherwise, we must use _enter/_exit critical to protect free_xmit_queue...
+
+Must be very very cautious...
+
+*/
+
+struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv)
+ /* _queue *pfree_xmit_queue) */
+{
+ /*
+ Please remember to use all the osdep_service api,
+ and lock/unlock or _enter/_exit critical to protect
+ pfree_xmit_queue
+ */
+ struct xmit_frame *pxframe;
+ struct __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;
+
+ spin_lock_bh(&pfree_xmit_queue->lock);
+ pxframe = list_first_entry_or_null(&pfree_xmit_queue->queue,
+ struct xmit_frame, list);
+ if (!pxframe) {
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
+ ("rtw_alloc_xmitframe:%d\n",
+ pxmitpriv->free_xmitframe_cnt));
+ } else {
+ list_del_init(&pxframe->list);
+
+ /* default value setting */
+ pxmitpriv->free_xmitframe_cnt--;
+
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
+ ("rtw_alloc_xmitframe():free_xmitframe_cnt=%d\n",
+ pxmitpriv->free_xmitframe_cnt));
+
+ pxframe->buf_addr = NULL;
+ pxframe->pxmitbuf = NULL;
+
+ memset(&pxframe->attrib, 0, sizeof(struct pkt_attrib));
+
+ pxframe->frame_tag = DATA_FRAMETAG;
+
+ pxframe->pkt = NULL;
+ pxframe->pkt_offset = 1;/* default use pkt_offset to fill tx desc */
+
+ pxframe->agg_num = 1;
+ pxframe->ack_report = 0;
+ }
+ spin_unlock_bh(&pfree_xmit_queue->lock);
+
+ return pxframe;
+}
+
+s32 rtw_free_xmitframe(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitframe)
+{
+ struct __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;
+ struct adapter *padapter = pxmitpriv->adapter;
+ struct sk_buff *pndis_pkt = NULL;
+
+ if (!pxmitframe) {
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("====== %s:pxmitframe == NULL!!!!!!!!!!\n", __func__));
+ goto exit;
+ }
+
+ spin_lock_bh(&pfree_xmit_queue->lock);
+
+ list_del_init(&pxmitframe->list);
+
+ if (pxmitframe->pkt) {
+ pndis_pkt = pxmitframe->pkt;
+ pxmitframe->pkt = NULL;
+ }
+
+ list_add_tail(&pxmitframe->list, get_list_head(pfree_xmit_queue));
+
+ pxmitpriv->free_xmitframe_cnt++;
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, ("%s:free_xmitframe_cnt=%d\n", __func__, pxmitpriv->free_xmitframe_cnt));
+
+ spin_unlock_bh(&pfree_xmit_queue->lock);
+
+ if (pndis_pkt)
+ rtw_os_pkt_complete(padapter, pndis_pkt);
+
+exit:
+ return _SUCCESS;
+}
+
+void rtw_free_xmitframe_queue(struct xmit_priv *pxmitpriv, struct __queue *pframequeue)
+{
+ struct list_head *plist, *phead;
+ struct xmit_frame *pxmitframe;
+
+ spin_lock_bh(&pframequeue->lock);
+
+ phead = get_list_head(pframequeue);
+ plist = phead->next;
+
+ while (phead != plist) {
+ pxmitframe = container_of(plist, struct xmit_frame, list);
+
+ plist = plist->next;
+
+ rtw_free_xmitframe(pxmitpriv, pxmitframe);
+ }
+ spin_unlock_bh(&pframequeue->lock);
+}
+
+s32 rtw_xmitframe_enqueue(struct adapter *padapter, struct xmit_frame *pxmitframe)
+{
+ if (rtw_xmit_classifier(padapter, pxmitframe) == _FAIL) {
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
+ ("%s: drop xmit pkt for classifier fail\n", __func__));
+ return _FAIL;
+ }
+
+ return _SUCCESS;
+}
+
+static struct xmit_frame *dequeue_one_xmitframe(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit, struct tx_servq *ptxservq, struct __queue *pframe_queue)
+{
+ struct list_head *xmitframe_plist, *xmitframe_phead;
+ struct xmit_frame *pxmitframe = NULL;
+
+ xmitframe_phead = get_list_head(pframe_queue);
+ xmitframe_plist = xmitframe_phead->next;
+
+ if (xmitframe_phead != xmitframe_plist) {
+ pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
+
+ xmitframe_plist = xmitframe_plist->next;
+
+ list_del_init(&pxmitframe->list);
+
+ ptxservq->qcnt--;
+ }
+ return pxmitframe;
+}
+
+struct xmit_frame *rtw_dequeue_xframe(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit_i, int entry)
+{
+ struct list_head *sta_plist, *sta_phead;
+ struct hw_xmit *phwxmit;
+ struct tx_servq *ptxservq = NULL;
+ struct __queue *pframe_queue = NULL;
+ struct xmit_frame *pxmitframe = NULL;
+ struct adapter *padapter = pxmitpriv->adapter;
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+ int i, inx[4];
+
+ inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3;
+
+ if (pregpriv->wifi_spec == 1) {
+ int j;
+
+ for (j = 0; j < 4; j++)
+ inx[j] = pxmitpriv->wmm_para_seq[j];
+ }
+
+ spin_lock_bh(&pxmitpriv->lock);
+
+ for (i = 0; i < entry; i++) {
+ phwxmit = phwxmit_i + inx[i];
+
+ sta_phead = get_list_head(phwxmit->sta_queue);
+ sta_plist = sta_phead->next;
+
+ while (sta_phead != sta_plist) {
+ ptxservq = container_of(sta_plist, struct tx_servq, tx_pending);
+
+ pframe_queue = &ptxservq->sta_pending;
+
+ pxmitframe = dequeue_one_xmitframe(pxmitpriv, phwxmit, ptxservq, pframe_queue);
+
+ if (pxmitframe) {
+ phwxmit->accnt--;
+
+ /* Remove sta node when there are no pending packets. */
+ if (list_empty(&pframe_queue->queue)) /* must be done after get_next and before break */
+ list_del_init(&ptxservq->tx_pending);
+ goto exit;
+ }
+
+ sta_plist = sta_plist->next;
+ }
+ }
+exit:
+ spin_unlock_bh(&pxmitpriv->lock);
+ return pxmitframe;
+}
+
+struct tx_servq *rtw_get_sta_pending(struct adapter *padapter,
+ struct sta_info *psta, int up, u8 *ac)
+{
+ struct tx_servq *ptxservq;
+
+ switch (up) {
+ case 1:
+ case 2:
+ ptxservq = &psta->sta_xmitpriv.bk_q;
+ *(ac) = 3;
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
+ ("%s : BK\n", __func__));
+ break;
+ case 4:
+ case 5:
+ ptxservq = &psta->sta_xmitpriv.vi_q;
+ *(ac) = 1;
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
+ ("%s : VI\n", __func__));
+ break;
+ case 6:
+ case 7:
+ ptxservq = &psta->sta_xmitpriv.vo_q;
+ *(ac) = 0;
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
+ ("%s : VO\n", __func__));
+ break;
+ case 0:
+ case 3:
+ default:
+ ptxservq = &psta->sta_xmitpriv.be_q;
+ *(ac) = 2;
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
+ ("%s : BE\n", __func__));
+ break;
+ }
+
+ return ptxservq;
+}
+
+/*
+ * Will enqueue pxmitframe to the proper queue,
+ * and indicate it to xx_pending list.....
+ */
+s32 rtw_xmit_classifier(struct adapter *padapter, struct xmit_frame *pxmitframe)
+{
+ u8 ac_index;
+ struct sta_info *psta;
+ struct tx_servq *ptxservq;
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits;
+ int res = _SUCCESS;
+
+ if (pattrib->psta)
+ psta = pattrib->psta;
+ else
+ psta = rtw_get_stainfo(pstapriv, pattrib->ra);
+
+ if (!psta) {
+ res = _FAIL;
+ DBG_88E("%s: psta == NULL\n", __func__);
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("%s: psta == NULL\n", __func__));
+ goto exit;
+ }
+
+ ptxservq = rtw_get_sta_pending(padapter, psta, pattrib->priority, (u8 *)(&ac_index));
+
+ if (list_empty(&ptxservq->tx_pending))
+ list_add_tail(&ptxservq->tx_pending, get_list_head(phwxmits[ac_index].sta_queue));
+
+ list_add_tail(&pxmitframe->list, get_list_head(&ptxservq->sta_pending));
+ ptxservq->qcnt++;
+ phwxmits[ac_index].accnt++;
+exit:
+ return res;
+}
+
+s32 rtw_alloc_hwxmits(struct adapter *padapter)
+{
+ struct hw_xmit *hwxmits;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+ pxmitpriv->hwxmit_entry = HWXMIT_ENTRY;
+
+ pxmitpriv->hwxmits = kcalloc(pxmitpriv->hwxmit_entry,
+ sizeof(struct hw_xmit), GFP_KERNEL);
+ if (!pxmitpriv->hwxmits)
+ return _FAIL;
+
+ hwxmits = pxmitpriv->hwxmits;
+
+ hwxmits[0] .sta_queue = &pxmitpriv->vo_pending;
+ hwxmits[1] .sta_queue = &pxmitpriv->vi_pending;
+ hwxmits[2] .sta_queue = &pxmitpriv->be_pending;
+ hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
+ return _SUCCESS;
+}
+
+void rtw_free_hwxmits(struct adapter *padapter)
+{
+ struct hw_xmit *hwxmits;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+ hwxmits = pxmitpriv->hwxmits;
+ kfree(hwxmits);
+}
+
+void rtw_init_hwxmits(struct hw_xmit *phwxmit, int entry)
+{
+ int i;
+
+ for (i = 0; i < entry; i++, phwxmit++)
+ phwxmit->accnt = 0;
+}
+
+u32 rtw_get_ff_hwaddr(struct xmit_frame *pxmitframe)
+{
+ u32 addr;
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+
+ switch (pattrib->qsel) {
+ case 0:
+ case 3:
+ addr = BE_QUEUE_INX;
+ break;
+ case 1:
+ case 2:
+ addr = BK_QUEUE_INX;
+ break;
+ case 4:
+ case 5:
+ addr = VI_QUEUE_INX;
+ break;
+ case 6:
+ case 7:
+ addr = VO_QUEUE_INX;
+ break;
+ case 0x10:
+ addr = BCN_QUEUE_INX;
+ break;
+ case 0x11:/* BC/MC in PS (HIQ) */
+ addr = HIGH_QUEUE_INX;
+ break;
+ case 0x12:
+ default:
+ addr = MGT_QUEUE_INX;
+ break;
+ }
+
+ return addr;
+}
+
+/*
+ * The main transmit(tx) entry
+ *
+ * Return
+ * 1 enqueue
+ * 0 success, hardware will handle this xmit frame(packet)
+ * <0 fail
+ */
+s32 rtw_xmit(struct adapter *padapter, struct sk_buff **ppkt)
+{
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct xmit_frame *pxmitframe = NULL;
+ s32 res;
+
+ pxmitframe = rtw_alloc_xmitframe(pxmitpriv);
+ if (!pxmitframe) {
+ RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("%s: no more pxmitframe\n", __func__));
+ DBG_88E("DBG_TX_DROP_FRAME %s no more pxmitframe\n", __func__);
+ return -1;
+ }
+
+ res = update_attrib(padapter, *ppkt, &pxmitframe->attrib);
+
+ if (res == _FAIL) {
+ RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("%s: update attrib fail\n", __func__));
+ rtw_free_xmitframe(pxmitpriv, pxmitframe);
+ return -1;
+ }
+ pxmitframe->pkt = *ppkt;
+
+ led_control_8188eu(padapter, LED_CTL_TX);
+
+ pxmitframe->attrib.qsel = pxmitframe->attrib.priority;
+
+#ifdef CPTCFG_88EU_AP_MODE
+ spin_lock_bh(&pxmitpriv->lock);
+ if (xmitframe_enqueue_for_sleeping_sta(padapter, pxmitframe)) {
+ spin_unlock_bh(&pxmitpriv->lock);
+ return 1;
+ }
+ spin_unlock_bh(&pxmitpriv->lock);
+#endif
+
+ if (!rtw_hal_xmit(padapter, pxmitframe))
+ return 1;
+
+ return 0;
+}
+
+#if defined(CPTCFG_88EU_AP_MODE)
+
+int xmitframe_enqueue_for_sleeping_sta(struct adapter *padapter, struct xmit_frame *pxmitframe)
+{
+ int ret = false;
+ struct sta_info *psta = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ bool mcast = is_multicast_ether_addr(pattrib->ra);
+
+ if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ return ret;
+
+ if (pattrib->psta)
+ psta = pattrib->psta;
+ else
+ psta = rtw_get_stainfo(pstapriv, pattrib->ra);
+
+ if (!psta)
+ return ret;
+
+ if (pattrib->triggered == 1) {
+ if (mcast)
+ pattrib->qsel = 0x11;/* HIQ */
+ return ret;
+ }
+
+ if (mcast) {
+ spin_lock_bh(&psta->sleep_q.lock);
+
+ if (pstapriv->sta_dz_bitmap) {/* if any one sta is in ps mode */
+ list_del_init(&pxmitframe->list);
+
+ list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q));
+
+ psta->sleepq_len++;
+
+ pstapriv->tim_bitmap |= BIT(0);/* */
+ pstapriv->sta_dz_bitmap |= BIT(0);
+
+ update_beacon(padapter, _TIM_IE_, NULL, false);/* tx bc/mc packets after update bcn */
+
+ ret = true;
+ }
+
+ spin_unlock_bh(&psta->sleep_q.lock);
+
+ return ret;
+ }
+
+ spin_lock_bh(&psta->sleep_q.lock);
+
+ if (psta->state & WIFI_SLEEP_STATE) {
+ u8 wmmps_ac = 0;
+
+ if (pstapriv->sta_dz_bitmap & BIT(psta->aid)) {
+ list_del_init(&pxmitframe->list);
+
+ list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q));
+
+ psta->sleepq_len++;
+
+ switch (pattrib->priority) {
+ case 1:
+ case 2:
+ wmmps_ac = psta->uapsd_bk & BIT(0);
+ break;
+ case 4:
+ case 5:
+ wmmps_ac = psta->uapsd_vi & BIT(0);
+ break;
+ case 6:
+ case 7:
+ wmmps_ac = psta->uapsd_vo & BIT(0);
+ break;
+ case 0:
+ case 3:
+ default:
+ wmmps_ac = psta->uapsd_be & BIT(0);
+ break;
+ }
+
+ if (wmmps_ac)
+ psta->sleepq_ac_len++;
+
+ if (((psta->has_legacy_ac) && (!wmmps_ac)) ||
+ ((!psta->has_legacy_ac) && (wmmps_ac))) {
+ pstapriv->tim_bitmap |= BIT(psta->aid);
+
+ if (psta->sleepq_len == 1) {
+ /* update BCN for TIM IE */
+ update_beacon(padapter, _TIM_IE_, NULL, false);
+ }
+ }
+ ret = true;
+ }
+ }
+
+ spin_unlock_bh(&psta->sleep_q.lock);
+
+ return ret;
+}
+
+static void dequeue_xmitframes_to_sleeping_queue(struct adapter *padapter, struct sta_info *psta, struct __queue *pframequeue)
+{
+ struct list_head *plist, *phead;
+ u8 ac_index;
+ struct tx_servq *ptxservq;
+ struct pkt_attrib *pattrib;
+ struct xmit_frame *pxmitframe;
+ struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits;
+
+ phead = get_list_head(pframequeue);
+ plist = phead->next;
+
+ while (phead != plist) {
+ pxmitframe = container_of(plist, struct xmit_frame, list);
+
+ plist = plist->next;
+
+ xmitframe_enqueue_for_sleeping_sta(padapter, pxmitframe);
+
+ pattrib = &pxmitframe->attrib;
+
+ ptxservq = rtw_get_sta_pending(padapter, psta, pattrib->priority, (u8 *)(&ac_index));
+
+ ptxservq->qcnt--;
+ phwxmits[ac_index].accnt--;
+ }
+}
+
+void stop_sta_xmit(struct adapter *padapter, struct sta_info *psta)
+{
+ struct sta_info *psta_bmc;
+ struct sta_xmit_priv *pstaxmitpriv;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+ pstaxmitpriv = &psta->sta_xmitpriv;
+
+ /* for BC/MC Frames */
+ psta_bmc = rtw_get_bcmc_stainfo(padapter);
+
+ spin_lock_bh(&pxmitpriv->lock);
+
+ psta->state |= WIFI_SLEEP_STATE;
+
+ pstapriv->sta_dz_bitmap |= BIT(psta->aid);
+
+ dequeue_xmitframes_to_sleeping_queue(padapter, psta,
+ &pstaxmitpriv->vo_q.sta_pending);
+ list_del_init(&pstaxmitpriv->vo_q.tx_pending);
+
+ dequeue_xmitframes_to_sleeping_queue(padapter, psta,
+ &pstaxmitpriv->vi_q.sta_pending);
+ list_del_init(&pstaxmitpriv->vi_q.tx_pending);
+
+ dequeue_xmitframes_to_sleeping_queue(padapter, psta,
+ &pstaxmitpriv->be_q.sta_pending);
+ list_del_init(&pstaxmitpriv->be_q.tx_pending);
+
+ dequeue_xmitframes_to_sleeping_queue(padapter, psta,
+ &pstaxmitpriv->bk_q.sta_pending);
+ list_del_init(&pstaxmitpriv->bk_q.tx_pending);
+
+ /* for BC/MC Frames */
+ pstaxmitpriv = &psta_bmc->sta_xmitpriv;
+ dequeue_xmitframes_to_sleeping_queue(padapter, psta_bmc,
+ &pstaxmitpriv->be_q.sta_pending);
+ list_del_init(&pstaxmitpriv->be_q.tx_pending);
+
+ spin_unlock_bh(&pxmitpriv->lock);
+}
+
+void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta)
+{
+ u8 update_mask = 0, wmmps_ac = 0;
+ struct sta_info *psta_bmc;
+ struct list_head *xmitframe_plist, *xmitframe_phead;
+ struct xmit_frame *pxmitframe = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ spin_lock_bh(&psta->sleep_q.lock);
+
+ xmitframe_phead = get_list_head(&psta->sleep_q);
+ xmitframe_plist = xmitframe_phead->next;
+
+ while (xmitframe_phead != xmitframe_plist) {
+ pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
+
+ xmitframe_plist = xmitframe_plist->next;
+
+ list_del_init(&pxmitframe->list);
+
+ switch (pxmitframe->attrib.priority) {
+ case 1:
+ case 2:
+ wmmps_ac = psta->uapsd_bk & BIT(1);
+ break;
+ case 4:
+ case 5:
+ wmmps_ac = psta->uapsd_vi & BIT(1);
+ break;
+ case 6:
+ case 7:
+ wmmps_ac = psta->uapsd_vo & BIT(1);
+ break;
+ case 0:
+ case 3:
+ default:
+ wmmps_ac = psta->uapsd_be & BIT(1);
+ break;
+ }
+
+ psta->sleepq_len--;
+ if (psta->sleepq_len > 0)
+ pxmitframe->attrib.mdata = 1;
+ else
+ pxmitframe->attrib.mdata = 0;
+
+ if (wmmps_ac) {
+ psta->sleepq_ac_len--;
+ if (psta->sleepq_ac_len > 0) {
+ pxmitframe->attrib.mdata = 1;
+ pxmitframe->attrib.eosp = 0;
+ } else {
+ pxmitframe->attrib.mdata = 0;
+ pxmitframe->attrib.eosp = 1;
+ }
+ }
+
+ pxmitframe->attrib.triggered = 1;
+
+ spin_unlock_bh(&psta->sleep_q.lock);
+ if (rtw_hal_xmit(padapter, pxmitframe))
+ rtw_os_xmit_complete(padapter, pxmitframe);
+ spin_lock_bh(&psta->sleep_q.lock);
+ }
+
+ if (psta->sleepq_len == 0) {
+ pstapriv->tim_bitmap &= ~BIT(psta->aid);
+
+ update_mask = BIT(0);
+
+ if (psta->state & WIFI_SLEEP_STATE)
+ psta->state ^= WIFI_SLEEP_STATE;
+
+ if (psta->state & WIFI_STA_ALIVE_CHK_STATE) {
+ psta->expire_to = pstapriv->expire_to;
+ psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
+ }
+
+ pstapriv->sta_dz_bitmap &= ~BIT(psta->aid);
+ }
+
+ spin_unlock_bh(&psta->sleep_q.lock);
+
+ /* for BC/MC Frames */
+ psta_bmc = rtw_get_bcmc_stainfo(padapter);
+ if (!psta_bmc)
+ return;
+
+ if ((pstapriv->sta_dz_bitmap & 0xfffe) == 0x0) { /* no any sta in ps mode */
+ spin_lock_bh(&psta_bmc->sleep_q.lock);
+
+ xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
+ xmitframe_plist = xmitframe_phead->next;
+
+ while (xmitframe_phead != xmitframe_plist) {
+ pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
+
+ xmitframe_plist = xmitframe_plist->next;
+
+ list_del_init(&pxmitframe->list);
+
+ psta_bmc->sleepq_len--;
+ if (psta_bmc->sleepq_len > 0)
+ pxmitframe->attrib.mdata = 1;
+ else
+ pxmitframe->attrib.mdata = 0;
+
+ pxmitframe->attrib.triggered = 1;
+
+ spin_unlock_bh(&psta_bmc->sleep_q.lock);
+ if (rtw_hal_xmit(padapter, pxmitframe))
+ rtw_os_xmit_complete(padapter, pxmitframe);
+ spin_lock_bh(&psta_bmc->sleep_q.lock);
+ }
+
+ if (psta_bmc->sleepq_len == 0) {
+ pstapriv->tim_bitmap &= ~BIT(0);
+ pstapriv->sta_dz_bitmap &= ~BIT(0);
+
+ update_mask |= BIT(1);
+ }
+
+ spin_unlock_bh(&psta_bmc->sleep_q.lock);
+ }
+
+ if (update_mask)
+ update_beacon(padapter, _TIM_IE_, NULL, false);
+}
+
+void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *psta)
+{
+ u8 wmmps_ac = 0;
+ struct list_head *xmitframe_plist, *xmitframe_phead;
+ struct xmit_frame *pxmitframe = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ spin_lock_bh(&psta->sleep_q.lock);
+
+ xmitframe_phead = get_list_head(&psta->sleep_q);
+ xmitframe_plist = xmitframe_phead->next;
+
+ while (xmitframe_phead != xmitframe_plist) {
+ pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
+
+ xmitframe_plist = xmitframe_plist->next;
+
+ switch (pxmitframe->attrib.priority) {
+ case 1:
+ case 2:
+ wmmps_ac = psta->uapsd_bk & BIT(1);
+ break;
+ case 4:
+ case 5:
+ wmmps_ac = psta->uapsd_vi & BIT(1);
+ break;
+ case 6:
+ case 7:
+ wmmps_ac = psta->uapsd_vo & BIT(1);
+ break;
+ case 0:
+ case 3:
+ default:
+ wmmps_ac = psta->uapsd_be & BIT(1);
+ break;
+ }
+
+ if (!wmmps_ac)
+ continue;
+
+ list_del_init(&pxmitframe->list);
+
+ psta->sleepq_len--;
+ psta->sleepq_ac_len--;
+
+ if (psta->sleepq_ac_len > 0) {
+ pxmitframe->attrib.mdata = 1;
+ pxmitframe->attrib.eosp = 0;
+ } else {
+ pxmitframe->attrib.mdata = 0;
+ pxmitframe->attrib.eosp = 1;
+ }
+
+ pxmitframe->attrib.triggered = 1;
+
+ if (rtw_hal_xmit(padapter, pxmitframe))
+ rtw_os_xmit_complete(padapter, pxmitframe);
+
+ if ((psta->sleepq_ac_len == 0) && (!psta->has_legacy_ac) && (wmmps_ac)) {
+ pstapriv->tim_bitmap &= ~BIT(psta->aid);
+
+ /* update BCN for TIM IE */
+ update_beacon(padapter, _TIM_IE_, NULL, false);
+ }
+ }
+
+ spin_unlock_bh(&psta->sleep_q.lock);
+}
+
+#endif
+
+void rtw_sctx_init(struct submit_ctx *sctx, int timeout_ms)
+{
+ sctx->timeout_ms = timeout_ms;
+ sctx->submit_time = jiffies;
+ init_completion(&sctx->done);
+ sctx->status = RTW_SCTX_SUBMITTED;
+}
+
+int rtw_sctx_wait(struct submit_ctx *sctx)
+{
+ int ret = _FAIL;
+ unsigned long expire;
+ int status = 0;
+
+ expire = sctx->timeout_ms ? msecs_to_jiffies(sctx->timeout_ms) : MAX_SCHEDULE_TIMEOUT;
+ if (!wait_for_completion_timeout(&sctx->done, expire)) {
+ /* timeout, do something?? */
+ status = RTW_SCTX_DONE_TIMEOUT;
+ DBG_88E("%s timeout\n", __func__);
+ } else {
+ status = sctx->status;
+ }
+
+ if (status == RTW_SCTX_DONE_SUCCESS)
+ ret = _SUCCESS;
+
+ return ret;
+}
+
+static bool rtw_sctx_chk_warning_status(int status)
+{
+ switch (status) {
+ case RTW_SCTX_DONE_UNKNOWN:
+ case RTW_SCTX_DONE_BUF_ALLOC:
+ case RTW_SCTX_DONE_BUF_FREE:
+
+ case RTW_SCTX_DONE_DRV_STOP:
+ case RTW_SCTX_DONE_DEV_REMOVE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void rtw_sctx_done_err(struct submit_ctx **sctx, int status)
+{
+ if (*sctx) {
+ if (rtw_sctx_chk_warning_status(status))
+ DBG_88E("%s status:%d\n", __func__, status);
+ (*sctx)->status = status;
+ complete(&((*sctx)->done));
+ *sctx = NULL;
+ }
+}
+
+int rtw_ack_tx_wait(struct xmit_priv *pxmitpriv, u32 timeout_ms)
+{
+ struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops;
+
+ pack_tx_ops->submit_time = jiffies;
+ pack_tx_ops->timeout_ms = timeout_ms;
+ pack_tx_ops->status = RTW_SCTX_SUBMITTED;
+
+ return rtw_sctx_wait(pack_tx_ops);
+}
+
+void rtw_ack_tx_done(struct xmit_priv *pxmitpriv, int status)
+{
+ struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops;
+
+ if (pxmitpriv->ack_tx)
+ rtw_sctx_done_err(&pack_tx_ops, status);
+ else
+ DBG_88E("%s ack_tx not set\n", __func__);
+}
diff --git a/drivers/staging/rtl8188eu/hal/bb_cfg.c b/drivers/staging/rtl8188eu/hal/bb_cfg.c
new file mode 100644
index 0000000..5188285
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/bb_cfg.c
@@ -0,0 +1,681 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include "odm_precomp.h"
+
+#include <phy.h>
+
+/* AGC_TAB_1T.TXT */
+
+static u32 array_agc_tab_1t_8188e[] = {
+ 0xC78, 0xFB000001,
+ 0xC78, 0xFB010001,
+ 0xC78, 0xFB020001,
+ 0xC78, 0xFB030001,
+ 0xC78, 0xFB040001,
+ 0xC78, 0xFB050001,
+ 0xC78, 0xFA060001,
+ 0xC78, 0xF9070001,
+ 0xC78, 0xF8080001,
+ 0xC78, 0xF7090001,
+ 0xC78, 0xF60A0001,
+ 0xC78, 0xF50B0001,
+ 0xC78, 0xF40C0001,
+ 0xC78, 0xF30D0001,
+ 0xC78, 0xF20E0001,
+ 0xC78, 0xF10F0001,
+ 0xC78, 0xF0100001,
+ 0xC78, 0xEF110001,
+ 0xC78, 0xEE120001,
+ 0xC78, 0xED130001,
+ 0xC78, 0xEC140001,
+ 0xC78, 0xEB150001,
+ 0xC78, 0xEA160001,
+ 0xC78, 0xE9170001,
+ 0xC78, 0xE8180001,
+ 0xC78, 0xE7190001,
+ 0xC78, 0xE61A0001,
+ 0xC78, 0xE51B0001,
+ 0xC78, 0xE41C0001,
+ 0xC78, 0xE31D0001,
+ 0xC78, 0xE21E0001,
+ 0xC78, 0xE11F0001,
+ 0xC78, 0x8A200001,
+ 0xC78, 0x89210001,
+ 0xC78, 0x88220001,
+ 0xC78, 0x87230001,
+ 0xC78, 0x86240001,
+ 0xC78, 0x85250001,
+ 0xC78, 0x84260001,
+ 0xC78, 0x83270001,
+ 0xC78, 0x82280001,
+ 0xC78, 0x6B290001,
+ 0xC78, 0x6A2A0001,
+ 0xC78, 0x692B0001,
+ 0xC78, 0x682C0001,
+ 0xC78, 0x672D0001,
+ 0xC78, 0x662E0001,
+ 0xC78, 0x652F0001,
+ 0xC78, 0x64300001,
+ 0xC78, 0x63310001,
+ 0xC78, 0x62320001,
+ 0xC78, 0x61330001,
+ 0xC78, 0x46340001,
+ 0xC78, 0x45350001,
+ 0xC78, 0x44360001,
+ 0xC78, 0x43370001,
+ 0xC78, 0x42380001,
+ 0xC78, 0x41390001,
+ 0xC78, 0x403A0001,
+ 0xC78, 0x403B0001,
+ 0xC78, 0x403C0001,
+ 0xC78, 0x403D0001,
+ 0xC78, 0x403E0001,
+ 0xC78, 0x403F0001,
+ 0xC78, 0xFB400001,
+ 0xC78, 0xFB410001,
+ 0xC78, 0xFB420001,
+ 0xC78, 0xFB430001,
+ 0xC78, 0xFB440001,
+ 0xC78, 0xFB450001,
+ 0xC78, 0xFB460001,
+ 0xC78, 0xFB470001,
+ 0xC78, 0xFB480001,
+ 0xC78, 0xFA490001,
+ 0xC78, 0xF94A0001,
+ 0xC78, 0xF84B0001,
+ 0xC78, 0xF74C0001,
+ 0xC78, 0xF64D0001,
+ 0xC78, 0xF54E0001,
+ 0xC78, 0xF44F0001,
+ 0xC78, 0xF3500001,
+ 0xC78, 0xF2510001,
+ 0xC78, 0xF1520001,
+ 0xC78, 0xF0530001,
+ 0xC78, 0xEF540001,
+ 0xC78, 0xEE550001,
+ 0xC78, 0xED560001,
+ 0xC78, 0xEC570001,
+ 0xC78, 0xEB580001,
+ 0xC78, 0xEA590001,
+ 0xC78, 0xE95A0001,
+ 0xC78, 0xE85B0001,
+ 0xC78, 0xE75C0001,
+ 0xC78, 0xE65D0001,
+ 0xC78, 0xE55E0001,
+ 0xC78, 0xE45F0001,
+ 0xC78, 0xE3600001,
+ 0xC78, 0xE2610001,
+ 0xC78, 0xC3620001,
+ 0xC78, 0xC2630001,
+ 0xC78, 0xC1640001,
+ 0xC78, 0x8B650001,
+ 0xC78, 0x8A660001,
+ 0xC78, 0x89670001,
+ 0xC78, 0x88680001,
+ 0xC78, 0x87690001,
+ 0xC78, 0x866A0001,
+ 0xC78, 0x856B0001,
+ 0xC78, 0x846C0001,
+ 0xC78, 0x676D0001,
+ 0xC78, 0x666E0001,
+ 0xC78, 0x656F0001,
+ 0xC78, 0x64700001,
+ 0xC78, 0x63710001,
+ 0xC78, 0x62720001,
+ 0xC78, 0x61730001,
+ 0xC78, 0x60740001,
+ 0xC78, 0x46750001,
+ 0xC78, 0x45760001,
+ 0xC78, 0x44770001,
+ 0xC78, 0x43780001,
+ 0xC78, 0x42790001,
+ 0xC78, 0x417A0001,
+ 0xC78, 0x407B0001,
+ 0xC78, 0x407C0001,
+ 0xC78, 0x407D0001,
+ 0xC78, 0x407E0001,
+ 0xC78, 0x407F0001,
+};
+
+static bool set_baseband_agc_config(struct adapter *adapt)
+{
+ u32 i;
+ const u32 arraylen = ARRAY_SIZE(array_agc_tab_1t_8188e);
+ u32 *array = array_agc_tab_1t_8188e;
+
+ for (i = 0; i < arraylen; i += 2) {
+ u32 v1 = array[i];
+ u32 v2 = array[i + 1];
+
+ if (v1 < 0xCDCDCDCD) {
+ phy_set_bb_reg(adapt, v1, bMaskDWord, v2);
+ udelay(1);
+ }
+ }
+ return true;
+}
+
+/* PHY_REG_1T.TXT */
+
+static u32 array_phy_reg_1t_8188e[] = {
+ 0x800, 0x80040000,
+ 0x804, 0x00000003,
+ 0x808, 0x0000FC00,
+ 0x80C, 0x0000000A,
+ 0x810, 0x10001331,
+ 0x814, 0x020C3D10,
+ 0x818, 0x02200385,
+ 0x81C, 0x00000000,
+ 0x820, 0x01000100,
+ 0x824, 0x00390204,
+ 0x828, 0x00000000,
+ 0x82C, 0x00000000,
+ 0x830, 0x00000000,
+ 0x834, 0x00000000,
+ 0x838, 0x00000000,
+ 0x83C, 0x00000000,
+ 0x840, 0x00010000,
+ 0x844, 0x00000000,
+ 0x848, 0x00000000,
+ 0x84C, 0x00000000,
+ 0x850, 0x00000000,
+ 0x854, 0x00000000,
+ 0x858, 0x569A11A9,
+ 0x85C, 0x01000014,
+ 0x860, 0x66F60110,
+ 0x864, 0x061F0649,
+ 0x868, 0x00000000,
+ 0x86C, 0x27272700,
+ 0x870, 0x07000760,
+ 0x874, 0x25004000,
+ 0x878, 0x00000808,
+ 0x87C, 0x00000000,
+ 0x880, 0xB0000C1C,
+ 0x884, 0x00000001,
+ 0x888, 0x00000000,
+ 0x88C, 0xCCC000C0,
+ 0x890, 0x00000800,
+ 0x894, 0xFFFFFFFE,
+ 0x898, 0x40302010,
+ 0x89C, 0x00706050,
+ 0x900, 0x00000000,
+ 0x904, 0x00000023,
+ 0x908, 0x00000000,
+ 0x90C, 0x81121111,
+ 0x910, 0x00000002,
+ 0x914, 0x00000201,
+ 0xA00, 0x00D047C8,
+ 0xA04, 0x80FF000C,
+ 0xA08, 0x8C838300,
+ 0xA0C, 0x2E7F120F,
+ 0xA10, 0x9500BB78,
+ 0xA14, 0x1114D028,
+ 0xA18, 0x00881117,
+ 0xA1C, 0x89140F00,
+ 0xA20, 0x1A1B0000,
+ 0xA24, 0x090E1317,
+ 0xA28, 0x00000204,
+ 0xA2C, 0x00D30000,
+ 0xA70, 0x101FBF00,
+ 0xA74, 0x00000007,
+ 0xA78, 0x00000900,
+ 0xA7C, 0x225B0606,
+ 0xA80, 0x218075B1,
+ 0xB2C, 0x80000000,
+ 0xC00, 0x48071D40,
+ 0xC04, 0x03A05611,
+ 0xC08, 0x000000E4,
+ 0xC0C, 0x6C6C6C6C,
+ 0xC10, 0x08800000,
+ 0xC14, 0x40000100,
+ 0xC18, 0x08800000,
+ 0xC1C, 0x40000100,
+ 0xC20, 0x00000000,
+ 0xC24, 0x00000000,
+ 0xC28, 0x00000000,
+ 0xC2C, 0x00000000,
+ 0xC30, 0x69E9AC47,
+ 0xC34, 0x469652AF,
+ 0xC38, 0x49795994,
+ 0xC3C, 0x0A97971C,
+ 0xC40, 0x1F7C403F,
+ 0xC44, 0x000100B7,
+ 0xC48, 0xEC020107,
+ 0xC4C, 0x007F037F,
+ 0xC50, 0x69553420,
+ 0xC54, 0x43BC0094,
+ 0xC58, 0x00013169,
+ 0xC5C, 0x00250492,
+ 0xC60, 0x00000000,
+ 0xC64, 0x7112848B,
+ 0xC68, 0x47C00BFF,
+ 0xC6C, 0x00000036,
+ 0xC70, 0x2C7F000D,
+ 0xC74, 0x020610DB,
+ 0xC78, 0x0000001F,
+ 0xC7C, 0x00B91612,
+ 0xC80, 0x390000E4,
+ 0xC84, 0x20F60000,
+ 0xC88, 0x40000100,
+ 0xC8C, 0x20200000,
+ 0xC90, 0x00091521,
+ 0xC94, 0x00000000,
+ 0xC98, 0x00121820,
+ 0xC9C, 0x00007F7F,
+ 0xCA0, 0x00000000,
+ 0xCA4, 0x000300A0,
+ 0xCA8, 0x00000000,
+ 0xCAC, 0x00000000,
+ 0xCB0, 0x00000000,
+ 0xCB4, 0x00000000,
+ 0xCB8, 0x00000000,
+ 0xCBC, 0x28000000,
+ 0xCC0, 0x00000000,
+ 0xCC4, 0x00000000,
+ 0xCC8, 0x00000000,
+ 0xCCC, 0x00000000,
+ 0xCD0, 0x00000000,
+ 0xCD4, 0x00000000,
+ 0xCD8, 0x64B22427,
+ 0xCDC, 0x00766932,
+ 0xCE0, 0x00222222,
+ 0xCE4, 0x00000000,
+ 0xCE8, 0x37644302,
+ 0xCEC, 0x2F97D40C,
+ 0xD00, 0x00000740,
+ 0xD04, 0x00020401,
+ 0xD08, 0x0000907F,
+ 0xD0C, 0x20010201,
+ 0xD10, 0xA0633333,
+ 0xD14, 0x3333BC43,
+ 0xD18, 0x7A8F5B6F,
+ 0xD2C, 0xCC979975,
+ 0xD30, 0x00000000,
+ 0xD34, 0x80608000,
+ 0xD38, 0x00000000,
+ 0xD3C, 0x00127353,
+ 0xD40, 0x00000000,
+ 0xD44, 0x00000000,
+ 0xD48, 0x00000000,
+ 0xD4C, 0x00000000,
+ 0xD50, 0x6437140A,
+ 0xD54, 0x00000000,
+ 0xD58, 0x00000282,
+ 0xD5C, 0x30032064,
+ 0xD60, 0x4653DE68,
+ 0xD64, 0x04518A3C,
+ 0xD68, 0x00002101,
+ 0xD6C, 0x2A201C16,
+ 0xD70, 0x1812362E,
+ 0xD74, 0x322C2220,
+ 0xD78, 0x000E3C24,
+ 0xE00, 0x2D2D2D2D,
+ 0xE04, 0x2D2D2D2D,
+ 0xE08, 0x0390272D,
+ 0xE10, 0x2D2D2D2D,
+ 0xE14, 0x2D2D2D2D,
+ 0xE18, 0x2D2D2D2D,
+ 0xE1C, 0x2D2D2D2D,
+ 0xE28, 0x00000000,
+ 0xE30, 0x1000DC1F,
+ 0xE34, 0x10008C1F,
+ 0xE38, 0x02140102,
+ 0xE3C, 0x681604C2,
+ 0xE40, 0x01007C00,
+ 0xE44, 0x01004800,
+ 0xE48, 0xFB000000,
+ 0xE4C, 0x000028D1,
+ 0xE50, 0x1000DC1F,
+ 0xE54, 0x10008C1F,
+ 0xE58, 0x02140102,
+ 0xE5C, 0x28160D05,
+ 0xE60, 0x00000008,
+ 0xE68, 0x001B25A4,
+ 0xE6C, 0x00C00014,
+ 0xE70, 0x00C00014,
+ 0xE74, 0x01000014,
+ 0xE78, 0x01000014,
+ 0xE7C, 0x01000014,
+ 0xE80, 0x01000014,
+ 0xE84, 0x00C00014,
+ 0xE88, 0x01000014,
+ 0xE8C, 0x00C00014,
+ 0xED0, 0x00C00014,
+ 0xED4, 0x00C00014,
+ 0xED8, 0x00C00014,
+ 0xEDC, 0x00000014,
+ 0xEE0, 0x00000014,
+ 0xEEC, 0x01C00014,
+ 0xF14, 0x00000003,
+ 0xF4C, 0x00000000,
+ 0xF00, 0x00000300,
+};
+
+static void rtl_bb_delay(struct adapter *adapt, u32 addr, u32 data)
+{
+ if (addr == 0xfe) {
+ msleep(50);
+ } else if (addr == 0xfd) {
+ mdelay(5);
+ } else if (addr == 0xfc) {
+ mdelay(1);
+ } else if (addr == 0xfb) {
+ udelay(50);
+ } else if (addr == 0xfa) {
+ udelay(5);
+ } else if (addr == 0xf9) {
+ udelay(1);
+ } else {
+ phy_set_bb_reg(adapt, addr, bMaskDWord, data);
+ /* Add 1us delay between BB/RF register setting. */
+ udelay(1);
+ }
+}
+
+static bool set_baseband_phy_config(struct adapter *adapt)
+{
+ u32 i;
+ const u32 arraylen = ARRAY_SIZE(array_phy_reg_1t_8188e);
+ u32 *array = array_phy_reg_1t_8188e;
+
+ for (i = 0; i < arraylen; i += 2) {
+ u32 v1 = array[i];
+ u32 v2 = array[i + 1];
+
+ if (v1 < 0xCDCDCDCD)
+ rtl_bb_delay(adapt, v1, v2);
+ }
+ return true;
+}
+
+/* PHY_REG_PG.TXT */
+
+static u32 array_phy_reg_pg_8188e[] = {
+ 0xE00, 0xFFFFFFFF, 0x06070809,
+ 0xE04, 0xFFFFFFFF, 0x02020405,
+ 0xE08, 0x0000FF00, 0x00000006,
+ 0x86C, 0xFFFFFF00, 0x00020400,
+ 0xE10, 0xFFFFFFFF, 0x08090A0B,
+ 0xE14, 0xFFFFFFFF, 0x01030607,
+ 0xE18, 0xFFFFFFFF, 0x08090A0B,
+ 0xE1C, 0xFFFFFFFF, 0x01030607,
+ 0xE00, 0xFFFFFFFF, 0x00000000,
+ 0xE04, 0xFFFFFFFF, 0x00000000,
+ 0xE08, 0x0000FF00, 0x00000000,
+ 0x86C, 0xFFFFFF00, 0x00000000,
+ 0xE10, 0xFFFFFFFF, 0x00000000,
+ 0xE14, 0xFFFFFFFF, 0x00000000,
+ 0xE18, 0xFFFFFFFF, 0x00000000,
+ 0xE1C, 0xFFFFFFFF, 0x00000000,
+ 0xE00, 0xFFFFFFFF, 0x02020202,
+ 0xE04, 0xFFFFFFFF, 0x00020202,
+ 0xE08, 0x0000FF00, 0x00000000,
+ 0x86C, 0xFFFFFF00, 0x00000000,
+ 0xE10, 0xFFFFFFFF, 0x04040404,
+ 0xE14, 0xFFFFFFFF, 0x00020404,
+ 0xE18, 0xFFFFFFFF, 0x00000000,
+ 0xE1C, 0xFFFFFFFF, 0x00000000,
+ 0xE00, 0xFFFFFFFF, 0x02020202,
+ 0xE04, 0xFFFFFFFF, 0x00020202,
+ 0xE08, 0x0000FF00, 0x00000000,
+ 0x86C, 0xFFFFFF00, 0x00000000,
+ 0xE10, 0xFFFFFFFF, 0x04040404,
+ 0xE14, 0xFFFFFFFF, 0x00020404,
+ 0xE18, 0xFFFFFFFF, 0x00000000,
+ 0xE1C, 0xFFFFFFFF, 0x00000000,
+ 0xE00, 0xFFFFFFFF, 0x00000000,
+ 0xE04, 0xFFFFFFFF, 0x00000000,
+ 0xE08, 0x0000FF00, 0x00000000,
+ 0x86C, 0xFFFFFF00, 0x00000000,
+ 0xE10, 0xFFFFFFFF, 0x00000000,
+ 0xE14, 0xFFFFFFFF, 0x00000000,
+ 0xE18, 0xFFFFFFFF, 0x00000000,
+ 0xE1C, 0xFFFFFFFF, 0x00000000,
+ 0xE00, 0xFFFFFFFF, 0x02020202,
+ 0xE04, 0xFFFFFFFF, 0x00020202,
+ 0xE08, 0x0000FF00, 0x00000000,
+ 0x86C, 0xFFFFFF00, 0x00000000,
+ 0xE10, 0xFFFFFFFF, 0x04040404,
+ 0xE14, 0xFFFFFFFF, 0x00020404,
+ 0xE18, 0xFFFFFFFF, 0x00000000,
+ 0xE1C, 0xFFFFFFFF, 0x00000000,
+ 0xE00, 0xFFFFFFFF, 0x00000000,
+ 0xE04, 0xFFFFFFFF, 0x00000000,
+ 0xE08, 0x0000FF00, 0x00000000,
+ 0x86C, 0xFFFFFF00, 0x00000000,
+ 0xE10, 0xFFFFFFFF, 0x00000000,
+ 0xE14, 0xFFFFFFFF, 0x00000000,
+ 0xE18, 0xFFFFFFFF, 0x00000000,
+ 0xE1C, 0xFFFFFFFF, 0x00000000,
+ 0xE00, 0xFFFFFFFF, 0x00000000,
+ 0xE04, 0xFFFFFFFF, 0x00000000,
+ 0xE08, 0x0000FF00, 0x00000000,
+ 0x86C, 0xFFFFFF00, 0x00000000,
+ 0xE10, 0xFFFFFFFF, 0x00000000,
+ 0xE14, 0xFFFFFFFF, 0x00000000,
+ 0xE18, 0xFFFFFFFF, 0x00000000,
+ 0xE1C, 0xFFFFFFFF, 0x00000000,
+ 0xE00, 0xFFFFFFFF, 0x00000000,
+ 0xE04, 0xFFFFFFFF, 0x00000000,
+ 0xE08, 0x0000FF00, 0x00000000,
+ 0x86C, 0xFFFFFF00, 0x00000000,
+ 0xE10, 0xFFFFFFFF, 0x00000000,
+ 0xE14, 0xFFFFFFFF, 0x00000000,
+ 0xE18, 0xFFFFFFFF, 0x00000000,
+ 0xE1C, 0xFFFFFFFF, 0x00000000,
+ 0xE00, 0xFFFFFFFF, 0x00000000,
+ 0xE04, 0xFFFFFFFF, 0x00000000,
+ 0xE08, 0x0000FF00, 0x00000000,
+ 0x86C, 0xFFFFFF00, 0x00000000,
+ 0xE10, 0xFFFFFFFF, 0x00000000,
+ 0xE14, 0xFFFFFFFF, 0x00000000,
+ 0xE18, 0xFFFFFFFF, 0x00000000,
+ 0xE1C, 0xFFFFFFFF, 0x00000000,
+ 0xE00, 0xFFFFFFFF, 0x00000000,
+ 0xE04, 0xFFFFFFFF, 0x00000000,
+ 0xE08, 0x0000FF00, 0x00000000,
+ 0x86C, 0xFFFFFF00, 0x00000000,
+ 0xE10, 0xFFFFFFFF, 0x00000000,
+ 0xE14, 0xFFFFFFFF, 0x00000000,
+ 0xE18, 0xFFFFFFFF, 0x00000000,
+ 0xE1C, 0xFFFFFFFF, 0x00000000,
+
+};
+
+static void store_pwrindex_offset(struct adapter *adapter,
+ u32 regaddr, u32 bitmask, u32 data)
+{
+ struct hal_data_8188e *hal_data = adapter->HalData;
+ u32 * const power_level_offset =
+ hal_data->MCSTxPowerLevelOriginalOffset[hal_data->pwrGroupCnt];
+
+ if (regaddr == rTxAGC_A_Rate18_06)
+ power_level_offset[0] = data;
+ if (regaddr == rTxAGC_A_Rate54_24)
+ power_level_offset[1] = data;
+ if (regaddr == rTxAGC_A_CCK1_Mcs32)
+ power_level_offset[6] = data;
+ if (regaddr == rTxAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00)
+ power_level_offset[7] = data;
+ if (regaddr == rTxAGC_A_Mcs03_Mcs00)
+ power_level_offset[2] = data;
+ if (regaddr == rTxAGC_A_Mcs07_Mcs04)
+ power_level_offset[3] = data;
+ if (regaddr == rTxAGC_A_Mcs11_Mcs08)
+ power_level_offset[4] = data;
+ if (regaddr == rTxAGC_A_Mcs15_Mcs12) {
+ power_level_offset[5] = data;
+ hal_data->pwrGroupCnt++;
+ }
+ if (regaddr == rTxAGC_B_Rate18_06)
+ power_level_offset[8] = data;
+ if (regaddr == rTxAGC_B_Rate54_24)
+ power_level_offset[9] = data;
+ if (regaddr == rTxAGC_B_CCK1_55_Mcs32)
+ power_level_offset[14] = data;
+ if (regaddr == rTxAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff)
+ power_level_offset[15] = data;
+ if (regaddr == rTxAGC_B_Mcs03_Mcs00)
+ power_level_offset[10] = data;
+ if (regaddr == rTxAGC_B_Mcs07_Mcs04)
+ power_level_offset[11] = data;
+ if (regaddr == rTxAGC_B_Mcs11_Mcs08)
+ power_level_offset[12] = data;
+ if (regaddr == rTxAGC_B_Mcs15_Mcs12)
+ power_level_offset[13] = data;
+}
+
+static void rtl_addr_delay(struct adapter *adapt,
+ u32 addr, u32 bit_mask, u32 data)
+{
+ switch (addr) {
+ case 0xfe:
+ msleep(50);
+ break;
+ case 0xfd:
+ mdelay(5);
+ break;
+ case 0xfc:
+ mdelay(1);
+ break;
+ case 0xfb:
+ udelay(50);
+ break;
+ case 0xfa:
+ udelay(5);
+ break;
+ case 0xf9:
+ udelay(1);
+ break;
+ default:
+ store_pwrindex_offset(adapt, addr, bit_mask, data);
+ }
+}
+
+static bool config_bb_with_pgheader(struct adapter *adapt)
+{
+ u32 i;
+ const u32 arraylen = ARRAY_SIZE(array_phy_reg_pg_8188e);
+ u32 *array = array_phy_reg_pg_8188e;
+
+ for (i = 0; i < arraylen; i += 3) {
+ u32 v1 = array[i];
+ u32 v2 = array[i + 1];
+ u32 v3 = array[i + 2];
+
+ if (v1 < 0xCDCDCDCD)
+ rtl_addr_delay(adapt, v1, v2, v3);
+ }
+ return true;
+}
+
+static void rtl88e_phy_init_bb_rf_register_definition(struct adapter *adapter)
+{
+ struct bb_reg_def *reg[4];
+
+ reg[RF_PATH_A] = &adapter->HalData->PHYRegDef[RF_PATH_A];
+ reg[RF_PATH_B] = &adapter->HalData->PHYRegDef[RF_PATH_B];
+
+ reg[RF_PATH_A]->rfintfs = rFPGA0_XAB_RFInterfaceSW;
+ reg[RF_PATH_B]->rfintfs = rFPGA0_XAB_RFInterfaceSW;
+
+ reg[RF_PATH_A]->rfintfi = rFPGA0_XAB_RFInterfaceRB;
+ reg[RF_PATH_B]->rfintfi = rFPGA0_XAB_RFInterfaceRB;
+
+ reg[RF_PATH_A]->rfintfo = rFPGA0_XA_RFInterfaceOE;
+ reg[RF_PATH_B]->rfintfo = rFPGA0_XB_RFInterfaceOE;
+
+ reg[RF_PATH_A]->rfintfe = rFPGA0_XA_RFInterfaceOE;
+ reg[RF_PATH_B]->rfintfe = rFPGA0_XB_RFInterfaceOE;
+
+ reg[RF_PATH_A]->rf3wireOffset = rFPGA0_XA_LSSIParameter;
+ reg[RF_PATH_B]->rf3wireOffset = rFPGA0_XB_LSSIParameter;
+
+ reg[RF_PATH_A]->rfLSSI_Select = rFPGA0_XAB_RFParameter;
+ reg[RF_PATH_B]->rfLSSI_Select = rFPGA0_XAB_RFParameter;
+
+ reg[RF_PATH_A]->rfTxGainStage = rFPGA0_TxGainStage;
+ reg[RF_PATH_B]->rfTxGainStage = rFPGA0_TxGainStage;
+
+ reg[RF_PATH_A]->rfHSSIPara1 = rFPGA0_XA_HSSIParameter1;
+ reg[RF_PATH_B]->rfHSSIPara1 = rFPGA0_XB_HSSIParameter1;
+
+ reg[RF_PATH_A]->rfHSSIPara2 = rFPGA0_XA_HSSIParameter2;
+ reg[RF_PATH_B]->rfHSSIPara2 = rFPGA0_XB_HSSIParameter2;
+
+ reg[RF_PATH_A]->rfSwitchControl = rFPGA0_XAB_SwitchControl;
+ reg[RF_PATH_B]->rfSwitchControl = rFPGA0_XAB_SwitchControl;
+
+ reg[RF_PATH_A]->rfAGCControl1 = rOFDM0_XAAGCCore1;
+ reg[RF_PATH_B]->rfAGCControl1 = rOFDM0_XBAGCCore1;
+
+ reg[RF_PATH_A]->rfAGCControl2 = rOFDM0_XAAGCCore2;
+ reg[RF_PATH_B]->rfAGCControl2 = rOFDM0_XBAGCCore2;
+
+ reg[RF_PATH_A]->rfRxIQImbalance = rOFDM0_XARxIQImbalance;
+ reg[RF_PATH_B]->rfRxIQImbalance = rOFDM0_XBRxIQImbalance;
+
+ reg[RF_PATH_A]->rfRxAFE = rOFDM0_XARxAFE;
+ reg[RF_PATH_B]->rfRxAFE = rOFDM0_XBRxAFE;
+
+ reg[RF_PATH_A]->rfTxIQImbalance = rOFDM0_XATxIQImbalance;
+ reg[RF_PATH_B]->rfTxIQImbalance = rOFDM0_XBTxIQImbalance;
+
+ reg[RF_PATH_A]->rfTxAFE = rOFDM0_XATxAFE;
+ reg[RF_PATH_B]->rfTxAFE = rOFDM0_XBTxAFE;
+
+ reg[RF_PATH_A]->rfLSSIReadBack = rFPGA0_XA_LSSIReadBack;
+ reg[RF_PATH_B]->rfLSSIReadBack = rFPGA0_XB_LSSIReadBack;
+
+ reg[RF_PATH_A]->rfLSSIReadBackPi = TransceiverA_HSPI_Readback;
+ reg[RF_PATH_B]->rfLSSIReadBackPi = TransceiverB_HSPI_Readback;
+}
+
+static bool config_parafile(struct adapter *adapt)
+{
+ struct eeprom_priv *eeprom = GET_EEPROM_EFUSE_PRIV(adapt);
+
+ set_baseband_phy_config(adapt);
+
+ /* If EEPROM or EFUSE autoload OK, We must config by PHY_REG_PG.txt */
+ if (!eeprom->bautoload_fail_flag) {
+ adapt->HalData->pwrGroupCnt = 0;
+ config_bb_with_pgheader(adapt);
+ }
+ set_baseband_agc_config(adapt);
+ return true;
+}
+
+bool rtl88eu_phy_bb_config(struct adapter *adapt)
+{
+ bool rtstatus;
+ u32 regval;
+ u8 crystal_cap;
+
+ rtl88e_phy_init_bb_rf_register_definition(adapt);
+
+ /* Enable BB and RF */
+ regval = usb_read16(adapt, REG_SYS_FUNC_EN);
+ usb_write16(adapt, REG_SYS_FUNC_EN,
+ (u16)(regval | BIT(13) | BIT(0) | BIT(1)));
+
+ usb_write8(adapt, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB);
+
+ usb_write8(adapt, REG_SYS_FUNC_EN, FEN_USBA |
+ FEN_USBD | FEN_BB_GLB_RSTn | FEN_BBRSTB);
+
+ /* Config BB and AGC */
+ rtstatus = config_parafile(adapt);
+
+ /* write 0x24[16:11] = 0x24[22:17] = crystal_cap */
+ crystal_cap = adapt->HalData->CrystalCap & 0x3F;
+ phy_set_bb_reg(adapt, REG_AFE_XTAL_CTRL, 0x7ff800,
+ (crystal_cap | (crystal_cap << 6)));
+
+ return rtstatus;
+}
diff --git a/drivers/staging/rtl8188eu/hal/fw.c b/drivers/staging/rtl8188eu/hal/fw.c
new file mode 100644
index 0000000..486ee4b
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/fw.c
@@ -0,0 +1,201 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013 Realtek Corporation.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "fw.h"
+#include "drv_types.h"
+#include "usb_ops_linux.h"
+#include "rtl8188e_spec.h"
+#include "rtl8188e_hal.h"
+
+#include <linux/firmware.h>
+#include <linux/slab.h>
+
+static void _rtl88e_enable_fw_download(struct adapter *adapt, bool enable)
+{
+ u8 tmp;
+
+ if (enable) {
+ tmp = usb_read8(adapt, REG_MCUFWDL);
+ usb_write8(adapt, REG_MCUFWDL, tmp | 0x01);
+
+ tmp = usb_read8(adapt, REG_MCUFWDL + 2);
+ usb_write8(adapt, REG_MCUFWDL + 2, tmp & 0xf7);
+ } else {
+ tmp = usb_read8(adapt, REG_MCUFWDL);
+ usb_write8(adapt, REG_MCUFWDL, tmp & 0xfe);
+
+ usb_write8(adapt, REG_MCUFWDL + 1, 0x00);
+ }
+}
+
+static void _rtl88e_fw_block_write(struct adapter *adapt,
+ const u8 *buffer, u32 size)
+{
+ u32 blk_sz = sizeof(u32);
+ const u8 *byte_buffer;
+ const u32 *dword_buffer = (u32 *)buffer;
+ u32 i, write_address, blk_cnt, remain;
+
+ blk_cnt = size / blk_sz;
+ remain = size % blk_sz;
+
+ write_address = FW_8192C_START_ADDRESS;
+
+ for (i = 0; i < blk_cnt; i++, write_address += blk_sz)
+ usb_write32(adapt, write_address, dword_buffer[i]);
+
+ byte_buffer = buffer + blk_cnt * blk_sz;
+ for (i = 0; i < remain; i++, write_address++)
+ usb_write8(adapt, write_address, byte_buffer[i]);
+}
+
+static void _rtl88e_fw_page_write(struct adapter *adapt,
+ u32 page, const u8 *buffer, u32 size)
+{
+ u8 value8;
+ u8 u8page = (u8)(page & 0x07);
+
+ value8 = (usb_read8(adapt, REG_MCUFWDL + 2) & 0xF8) | u8page;
+
+ usb_write8(adapt, (REG_MCUFWDL + 2), value8);
+ _rtl88e_fw_block_write(adapt, buffer, size);
+}
+
+static void _rtl88e_write_fw(struct adapter *adapt, u8 *buffer, u32 size)
+{
+ u8 *buf_ptr = buffer;
+ u32 page_no, remain;
+ u32 page, offset;
+
+ page_no = size / FW_8192C_PAGE_SIZE;
+ remain = size % FW_8192C_PAGE_SIZE;
+
+ for (page = 0; page < page_no; page++) {
+ offset = page * FW_8192C_PAGE_SIZE;
+ _rtl88e_fw_page_write(adapt, page, (buf_ptr + offset),
+ FW_8192C_PAGE_SIZE);
+ }
+
+ if (remain) {
+ offset = page_no * FW_8192C_PAGE_SIZE;
+ page = page_no;
+ _rtl88e_fw_page_write(adapt, page, (buf_ptr + offset), remain);
+ }
+}
+
+static void rtl88e_firmware_selfreset(struct adapter *adapt)
+{
+ u8 u1b_tmp;
+
+ u1b_tmp = usb_read8(adapt, REG_SYS_FUNC_EN + 1);
+ usb_write8(adapt, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));
+ usb_write8(adapt, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2)));
+}
+
+static int _rtl88e_fw_free_to_go(struct adapter *adapt)
+{
+ int err = -EIO;
+ u32 counter = 0;
+ u32 value32;
+
+ do {
+ value32 = usb_read32(adapt, REG_MCUFWDL);
+ if (value32 & FWDL_ChkSum_rpt)
+ break;
+ } while (counter++ < POLLING_READY_TIMEOUT_COUNT);
+
+ if (counter >= POLLING_READY_TIMEOUT_COUNT)
+ goto exit;
+
+ value32 = usb_read32(adapt, REG_MCUFWDL);
+ value32 |= MCUFWDL_RDY;
+ value32 &= ~WINTINI_RDY;
+ usb_write32(adapt, REG_MCUFWDL, value32);
+
+ rtl88e_firmware_selfreset(adapt);
+ counter = 0;
+
+ do {
+ value32 = usb_read32(adapt, REG_MCUFWDL);
+ if (value32 & WINTINI_RDY) {
+ err = 0;
+ goto exit;
+ }
+
+ udelay(FW_8192C_POLLING_DELAY);
+
+ } while (counter++ < POLLING_READY_TIMEOUT_COUNT);
+
+exit:
+ return err;
+}
+
+int rtl88eu_download_fw(struct adapter *adapt)
+{
+ struct dvobj_priv *dvobj = adapter_to_dvobj(adapt);
+ struct device *device = dvobj_to_dev(dvobj);
+ const struct firmware *fw;
+ const char fw_name[] = "rtlwifi/rtl8188eufw.bin";
+ struct rtl92c_firmware_header *pfwheader = NULL;
+ u8 *download_data, *fw_data;
+ size_t download_size;
+ unsigned int trailing_zeros_length;
+
+ if (request_firmware(&fw, fw_name, device)) {
+ dev_err(device, "Firmware %s not available\n", fw_name);
+ return -ENOENT;
+ }
+
+ if (fw->size > FW_8188E_SIZE) {
+ dev_err(device, "Firmware size exceed 0x%X. Check it.\n",
+ FW_8188E_SIZE);
+ release_firmware(fw);
+ return -1;
+ }
+
+ trailing_zeros_length = (4 - fw->size % 4) % 4;
+
+ fw_data = kmalloc(fw->size + trailing_zeros_length, GFP_KERNEL);
+ if (!fw_data) {
+ release_firmware(fw);
+ return -ENOMEM;
+ }
+
+ memcpy(fw_data, fw->data, fw->size);
+ memset(fw_data + fw->size, 0, trailing_zeros_length);
+
+ pfwheader = (struct rtl92c_firmware_header *)fw_data;
+
+ if (IS_FW_HEADER_EXIST(pfwheader)) {
+ download_data = fw_data + 32;
+ download_size = fw->size + trailing_zeros_length - 32;
+ } else {
+ download_data = fw_data;
+ download_size = fw->size + trailing_zeros_length;
+ }
+
+ release_firmware(fw);
+
+ if (usb_read8(adapt, REG_MCUFWDL) & RAM_DL_SEL) {
+ usb_write8(adapt, REG_MCUFWDL, 0);
+ rtl88e_firmware_selfreset(adapt);
+ }
+ _rtl88e_enable_fw_download(adapt, true);
+ usb_write8(adapt, REG_MCUFWDL, usb_read8(adapt, REG_MCUFWDL) | FWDL_ChkSum_rpt);
+ _rtl88e_write_fw(adapt, download_data, download_size);
+ _rtl88e_enable_fw_download(adapt, false);
+
+ kfree(fw_data);
+ return _rtl88e_fw_free_to_go(adapt);
+}
diff --git a/drivers/staging/rtl8188eu/hal/hal8188e_rate_adaptive.c b/drivers/staging/rtl8188eu/hal/hal8188e_rate_adaptive.c
new file mode 100644
index 0000000..5792f49
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/hal8188e_rate_adaptive.c
@@ -0,0 +1,761 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) Realtek Semiconductor Corp. All rights reserved.
+ */
+
+#include "odm_precomp.h"
+
+/* Rate adaptive parameters */
+
+static u8 RETRY_PENALTY[PERENTRY][RETRYSIZE + 1] = {
+ {5, 4, 3, 2, 0, 3}, /* 92 , idx = 0 */
+ {6, 5, 4, 3, 0, 4}, /* 86 , idx = 1 */
+ {6, 5, 4, 2, 0, 4}, /* 81 , idx = 2 */
+ {8, 7, 6, 4, 0, 6}, /* 75 , idx = 3 */
+ {10, 9, 8, 6, 0, 8}, /* 71 , idx = 4 */
+ {10, 9, 8, 4, 0, 8}, /* 66 , idx = 5 */
+ {10, 9, 8, 2, 0, 8}, /* 62 , idx = 6 */
+ {10, 9, 8, 0, 0, 8}, /* 59 , idx = 7 */
+ {18, 17, 16, 8, 0, 16}, /* 53 , idx = 8 */
+ {26, 25, 24, 16, 0, 24}, /* 50 , idx = 9 */
+ {34, 33, 32, 24, 0, 32}, /* 47 , idx = 0x0a */
+ {34, 31, 28, 20, 0, 32}, /* 43 , idx = 0x0b */
+ {34, 31, 27, 18, 0, 32}, /* 40 , idx = 0x0c */
+ {34, 31, 26, 16, 0, 32}, /* 37 , idx = 0x0d */
+ {34, 30, 22, 16, 0, 32}, /* 32 , idx = 0x0e */
+ {34, 30, 24, 16, 0, 32}, /* 26 , idx = 0x0f */
+ {49, 46, 40, 16, 0, 48}, /* 20 , idx = 0x10 */
+ {49, 45, 32, 0, 0, 48}, /* 17 , idx = 0x11 */
+ {49, 45, 22, 18, 0, 48}, /* 15 , idx = 0x12 */
+ {49, 40, 24, 16, 0, 48}, /* 12 , idx = 0x13 */
+ {49, 32, 18, 12, 0, 48}, /* 9 , idx = 0x14 */
+ {49, 22, 18, 14, 0, 48}, /* 6 , idx = 0x15 */
+ {49, 16, 16, 0, 0, 48}
+ }; /* 3, idx = 0x16 */
+
+static u8 PT_PENALTY[RETRYSIZE + 1] = {34, 31, 30, 24, 0, 32};
+
+/* wilson modify */
+static u8 RETRY_PENALTY_IDX[2][RATESIZE] = {
+ {4, 4, 4, 5, 4, 4, 5, 7, 7, 7, 8, 0x0a, /* SS>TH */
+ 4, 4, 4, 4, 6, 0x0a, 0x0b, 0x0d,
+ 5, 5, 7, 7, 8, 0x0b, 0x0d, 0x0f}, /* 0329 R01 */
+ {0x0a, 0x0a, 0x0b, 0x0c, 0x0a,
+ 0x0a, 0x0b, 0x0c, 0x0d, 0x10, 0x13, 0x14, /* SS<TH */
+ 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x11, 0x13, 0x15,
+ 9, 9, 9, 9, 0x0c, 0x0e, 0x11, 0x13}
+ };
+
+static u8 RETRY_PENALTY_UP_IDX[RATESIZE] = {
+ 0x0c, 0x0d, 0x0d, 0x0f, 0x0d, 0x0e,
+ 0x0f, 0x0f, 0x10, 0x12, 0x13, 0x14, /* SS>TH */
+ 0x0f, 0x10, 0x10, 0x12, 0x12, 0x13, 0x14, 0x15,
+ 0x11, 0x11, 0x12, 0x13, 0x13, 0x13, 0x14, 0x15};
+
+static u8 RSSI_THRESHOLD[RATESIZE] = {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0x24, 0x26, 0x2a,
+ 0x18, 0x1a, 0x1d, 0x1f, 0x21, 0x27, 0x29, 0x2a,
+ 0, 0, 0, 0x1f, 0x23, 0x28, 0x2a, 0x2c};
+
+static u16 N_THRESHOLD_HIGH[RATESIZE] = {
+ 4, 4, 8, 16,
+ 24, 36, 48, 72, 96, 144, 192, 216,
+ 60, 80, 100, 160, 240, 400, 560, 640,
+ 300, 320, 480, 720, 1000, 1200, 1600, 2000};
+static u16 N_THRESHOLD_LOW[RATESIZE] = {
+ 2, 2, 4, 8,
+ 12, 18, 24, 36, 48, 72, 96, 108,
+ 30, 40, 50, 80, 120, 200, 280, 320,
+ 150, 160, 240, 360, 500, 600, 800, 1000};
+
+static u8 DROPING_NECESSARY[RATESIZE] = {
+ 1, 1, 1, 1,
+ 1, 2, 3, 4, 5, 6, 7, 8,
+ 1, 2, 3, 4, 5, 6, 7, 8,
+ 5, 6, 7, 8, 9, 10, 11, 12};
+
+static u8 PendingForRateUpFail[5] = {2, 10, 24, 40, 60};
+static u16 DynamicTxRPTTiming[6] = {
+ 0x186a, 0x30d4, 0x493e, 0x61a8, 0x7a12, 0x927c}; /* 200ms-1200ms */
+
+/* End Rate adaptive parameters */
+
+static void odm_SetTxRPTTiming_8188E(struct odm_dm_struct *dm_odm,
+ struct odm_ra_info *pRaInfo, u8 extend)
+{
+ u8 idx = 0;
+
+ for (idx = 0; idx < 5; idx++)
+ if (DynamicTxRPTTiming[idx] == pRaInfo->RptTime)
+ break;
+
+ if (extend == 0) { /* back to default timing */
+ idx = 0; /* 200ms */
+ } else if (extend == 1) {/* increase the timing */
+ idx += 1;
+ if (idx > 5)
+ idx = 5;
+ } else if (extend == 2) {/* decrease the timing */
+ if (idx != 0)
+ idx -= 1;
+ }
+ pRaInfo->RptTime = DynamicTxRPTTiming[idx];
+
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
+ ("pRaInfo->RptTime = 0x%x\n", pRaInfo->RptTime));
+}
+
+static int odm_RateDown_8188E(struct odm_dm_struct *dm_odm,
+ struct odm_ra_info *pRaInfo)
+{
+ u8 RateID, LowestRate, HighestRate;
+ u8 i;
+
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE,
+ ODM_DBG_TRACE, ("=====>%s()\n", __func__));
+ if (!pRaInfo) {
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
+ ("%s(): pRaInfo is NULL\n", __func__));
+ return -1;
+ }
+ RateID = pRaInfo->PreRate;
+ LowestRate = pRaInfo->LowestRate;
+ HighestRate = pRaInfo->HighestRate;
+
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+ (" RateID =%d LowestRate =%d HighestRate =%d RateSGI =%d\n",
+ RateID, LowestRate, HighestRate, pRaInfo->RateSGI));
+ if (RateID > HighestRate) {
+ RateID = HighestRate;
+ } else if (pRaInfo->RateSGI) {
+ pRaInfo->RateSGI = 0;
+ } else if (RateID > LowestRate) {
+ if (RateID > 0) {
+ for (i = RateID - 1; i > LowestRate; i--) {
+ if (pRaInfo->RAUseRate & BIT(i)) {
+ RateID = i;
+ goto RateDownFinish;
+ }
+ }
+ }
+ } else if (RateID <= LowestRate) {
+ RateID = LowestRate;
+ }
+RateDownFinish:
+ if (pRaInfo->RAWaitingCounter == 1) {
+ pRaInfo->RAWaitingCounter += 1;
+ pRaInfo->RAPendingCounter += 1;
+ } else if (pRaInfo->RAWaitingCounter == 0) {
+ ;
+ } else {
+ pRaInfo->RAWaitingCounter = 0;
+ pRaInfo->RAPendingCounter = 0;
+ }
+
+ if (pRaInfo->RAPendingCounter >= 4)
+ pRaInfo->RAPendingCounter = 4;
+
+ pRaInfo->DecisionRate = RateID;
+ odm_SetTxRPTTiming_8188E(dm_odm, pRaInfo, 2);
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE,
+ ODM_DBG_LOUD, ("Rate down, RPT Timing default\n"));
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+ ("RAWaitingCounter %d, RAPendingCounter %d",
+ pRaInfo->RAWaitingCounter, pRaInfo->RAPendingCounter));
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
+ ("Rate down to RateID %d RateSGI %d\n", RateID, pRaInfo->RateSGI));
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+ ("<===== %s()\n", __func__));
+ return 0;
+}
+
+static int odm_RateUp_8188E(struct odm_dm_struct *dm_odm,
+ struct odm_ra_info *pRaInfo)
+{
+ u8 RateID, HighestRate;
+ u8 i;
+
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE,
+ ODM_DBG_TRACE, ("=====>%s()\n", __func__));
+ if (!pRaInfo) {
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
+ ("%s(): pRaInfo is NULL\n", __func__));
+ return -1;
+ }
+ RateID = pRaInfo->PreRate;
+ HighestRate = pRaInfo->HighestRate;
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+ (" RateID =%d HighestRate =%d\n",
+ RateID, HighestRate));
+ if (pRaInfo->RAWaitingCounter == 1) {
+ pRaInfo->RAWaitingCounter = 0;
+ pRaInfo->RAPendingCounter = 0;
+ } else if (pRaInfo->RAWaitingCounter > 1) {
+ pRaInfo->PreRssiStaRA = pRaInfo->RssiStaRA;
+ goto RateUpfinish;
+ }
+ odm_SetTxRPTTiming_8188E(dm_odm, pRaInfo, 0);
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
+ ("%s():Decrease RPT Timing\n", __func__));
+
+ if (RateID < HighestRate) {
+ for (i = RateID + 1; i <= HighestRate; i++) {
+ if (pRaInfo->RAUseRate & BIT(i)) {
+ RateID = i;
+ goto RateUpfinish;
+ }
+ }
+ } else if (RateID == HighestRate) {
+ if (pRaInfo->SGIEnable && (pRaInfo->RateSGI != 1))
+ pRaInfo->RateSGI = 1;
+ else if ((pRaInfo->SGIEnable) != 1)
+ pRaInfo->RateSGI = 0;
+ } else {
+ RateID = HighestRate;
+ }
+RateUpfinish:
+ if (pRaInfo->RAWaitingCounter ==
+ (4 + PendingForRateUpFail[pRaInfo->RAPendingCounter]))
+ pRaInfo->RAWaitingCounter = 0;
+ else
+ pRaInfo->RAWaitingCounter++;
+
+ pRaInfo->DecisionRate = RateID;
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
+ ("Rate up to RateID %d\n", RateID));
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+ ("RAWaitingCounter %d, RAPendingCounter %d",
+ pRaInfo->RAWaitingCounter, pRaInfo->RAPendingCounter));
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE,
+ ODM_DBG_TRACE, ("<===== %s()\n", __func__));
+ return 0;
+}
+
+static void odm_ResetRaCounter_8188E(struct odm_ra_info *pRaInfo)
+{
+ u8 RateID;
+
+ RateID = pRaInfo->DecisionRate;
+ pRaInfo->NscUp = (N_THRESHOLD_HIGH[RateID] +
+ N_THRESHOLD_LOW[RateID]) >> 1;
+ pRaInfo->NscDown = (N_THRESHOLD_HIGH[RateID] +
+ N_THRESHOLD_LOW[RateID]) >> 1;
+}
+
+static void odm_RateDecision_8188E(struct odm_dm_struct *dm_odm,
+ struct odm_ra_info *pRaInfo)
+{
+ u8 RateID = 0, RtyPtID = 0, PenaltyID1 = 0, PenaltyID2 = 0, i = 0;
+ /* u32 pool_retry; */
+ static u8 DynamicTxRPTTimingCounter;
+
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+ ("=====>%s()\n", __func__));
+
+ if (pRaInfo->Active && (pRaInfo->TOTAL > 0)) { /* STA used and data packet exits */
+ if ((pRaInfo->RssiStaRA < (pRaInfo->PreRssiStaRA - 3)) ||
+ (pRaInfo->RssiStaRA > (pRaInfo->PreRssiStaRA + 3))) {
+ pRaInfo->RAWaitingCounter = 0;
+ pRaInfo->RAPendingCounter = 0;
+ }
+ /* Start RA decision */
+ if (pRaInfo->PreRate > pRaInfo->HighestRate)
+ RateID = pRaInfo->HighestRate;
+ else
+ RateID = pRaInfo->PreRate;
+ if (pRaInfo->RssiStaRA > RSSI_THRESHOLD[RateID])
+ RtyPtID = 0;
+ else
+ RtyPtID = 1;
+ PenaltyID1 = RETRY_PENALTY_IDX[RtyPtID][RateID]; /* TODO by page */
+
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+ (" NscDown init is %d\n", pRaInfo->NscDown));
+
+ for (i = 0 ; i <= 4 ; i++)
+ pRaInfo->NscDown += pRaInfo->RTY[i] * RETRY_PENALTY[PenaltyID1][i];
+
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+ (" NscDown is %d, total*penalty[5] is %d\n", pRaInfo->NscDown,
+ (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID1][5])));
+
+ if (pRaInfo->NscDown > (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID1][5]))
+ pRaInfo->NscDown -= pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID1][5];
+ else
+ pRaInfo->NscDown = 0;
+
+ /* rate up */
+ PenaltyID2 = RETRY_PENALTY_UP_IDX[RateID];
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+ (" NscUp init is %d\n", pRaInfo->NscUp));
+
+ for (i = 0 ; i <= 4 ; i++)
+ pRaInfo->NscUp += pRaInfo->RTY[i] * RETRY_PENALTY[PenaltyID2][i];
+
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+ ("NscUp is %d, total*up[5] is %d\n",
+ pRaInfo->NscUp, (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID2][5])));
+
+ if (pRaInfo->NscUp > (pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID2][5]))
+ pRaInfo->NscUp -= pRaInfo->TOTAL * RETRY_PENALTY[PenaltyID2][5];
+ else
+ pRaInfo->NscUp = 0;
+
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE | ODM_COMP_INIT, ODM_DBG_LOUD,
+ (" RssiStaRa = %d RtyPtID =%d PenaltyID1 = 0x%x PenaltyID2 = 0x%x RateID =%d NscDown =%d NscUp =%d SGI =%d\n",
+ pRaInfo->RssiStaRA, RtyPtID, PenaltyID1, PenaltyID2, RateID, pRaInfo->NscDown, pRaInfo->NscUp, pRaInfo->RateSGI));
+ if ((pRaInfo->NscDown < N_THRESHOLD_LOW[RateID]) ||
+ (pRaInfo->DROP > DROPING_NECESSARY[RateID]))
+ odm_RateDown_8188E(dm_odm, pRaInfo);
+ else if (pRaInfo->NscUp > N_THRESHOLD_HIGH[RateID])
+ odm_RateUp_8188E(dm_odm, pRaInfo);
+
+ if (pRaInfo->DecisionRate > pRaInfo->HighestRate)
+ pRaInfo->DecisionRate = pRaInfo->HighestRate;
+
+ if ((pRaInfo->DecisionRate) == (pRaInfo->PreRate))
+ DynamicTxRPTTimingCounter += 1;
+ else
+ DynamicTxRPTTimingCounter = 0;
+
+ if (DynamicTxRPTTimingCounter >= 4) {
+ odm_SetTxRPTTiming_8188E(dm_odm, pRaInfo, 1);
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE,
+ ODM_DBG_LOUD, ("<===== Rate don't change 4 times, Extend RPT Timing\n"));
+ DynamicTxRPTTimingCounter = 0;
+ }
+
+ pRaInfo->PreRate = pRaInfo->DecisionRate; /* YJ, add, 120120 */
+
+ odm_ResetRaCounter_8188E(pRaInfo);
+ }
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+ ("<===== %s()\n", __func__));
+}
+
+static int odm_ARFBRefresh_8188E(struct odm_dm_struct *dm_odm, struct odm_ra_info *pRaInfo)
+{ /* Wilson 2011/10/26 */
+ struct adapter *adapt = dm_odm->Adapter;
+ u32 MaskFromReg;
+ s8 i;
+
+ switch (pRaInfo->RateID) {
+ case RATR_INX_WIRELESS_NGB:
+ pRaInfo->RAUseRate = pRaInfo->RateMask & 0x0f8ff015;
+ break;
+ case RATR_INX_WIRELESS_NG:
+ pRaInfo->RAUseRate = pRaInfo->RateMask & 0x0f8ff010;
+ break;
+ case RATR_INX_WIRELESS_NB:
+ pRaInfo->RAUseRate = pRaInfo->RateMask & 0x0f8ff005;
+ break;
+ case RATR_INX_WIRELESS_N:
+ pRaInfo->RAUseRate = pRaInfo->RateMask & 0x0f8ff000;
+ break;
+ case RATR_INX_WIRELESS_GB:
+ pRaInfo->RAUseRate = pRaInfo->RateMask & 0x00000ff5;
+ break;
+ case RATR_INX_WIRELESS_G:
+ pRaInfo->RAUseRate = pRaInfo->RateMask & 0x00000ff0;
+ break;
+ case RATR_INX_WIRELESS_B:
+ pRaInfo->RAUseRate = pRaInfo->RateMask & 0x0000000d;
+ break;
+ case 12:
+ MaskFromReg = usb_read32(adapt, REG_ARFR0);
+ pRaInfo->RAUseRate = pRaInfo->RateMask & MaskFromReg;
+ break;
+ case 13:
+ MaskFromReg = usb_read32(adapt, REG_ARFR1);
+ pRaInfo->RAUseRate = pRaInfo->RateMask & MaskFromReg;
+ break;
+ case 14:
+ MaskFromReg = usb_read32(adapt, REG_ARFR2);
+ pRaInfo->RAUseRate = pRaInfo->RateMask & MaskFromReg;
+ break;
+ case 15:
+ MaskFromReg = usb_read32(adapt, REG_ARFR3);
+ pRaInfo->RAUseRate = pRaInfo->RateMask & MaskFromReg;
+ break;
+ default:
+ pRaInfo->RAUseRate = (pRaInfo->RateMask);
+ break;
+ }
+ /* Highest rate */
+ if (pRaInfo->RAUseRate) {
+ for (i = RATESIZE; i >= 0; i--) {
+ if (pRaInfo->RAUseRate & BIT(i)) {
+ pRaInfo->HighestRate = i;
+ break;
+ }
+ }
+ } else {
+ pRaInfo->HighestRate = 0;
+ }
+ /* Lowest rate */
+ if (pRaInfo->RAUseRate) {
+ for (i = 0; i < RATESIZE; i++) {
+ if ((pRaInfo->RAUseRate) & BIT(i)) {
+ pRaInfo->LowestRate = i;
+ break;
+ }
+ }
+ } else {
+ pRaInfo->LowestRate = 0;
+ }
+
+ if (pRaInfo->HighestRate > 0x13)
+ pRaInfo->PTModeSS = 3;
+ else if (pRaInfo->HighestRate > 0x0b)
+ pRaInfo->PTModeSS = 2;
+ else if (pRaInfo->HighestRate > 0x03)
+ pRaInfo->PTModeSS = 1;
+ else
+ pRaInfo->PTModeSS = 0;
+
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
+ ("ODM_ARFBRefresh_8188E(): PTModeSS =%d\n", pRaInfo->PTModeSS));
+
+ if (pRaInfo->DecisionRate > pRaInfo->HighestRate)
+ pRaInfo->DecisionRate = pRaInfo->HighestRate;
+
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
+ ("ODM_ARFBRefresh_8188E(): RateID =%d RateMask =%8.8x RAUseRate =%8.8x HighestRate =%d, DecisionRate =%d\n",
+ pRaInfo->RateID, pRaInfo->RateMask, pRaInfo->RAUseRate, pRaInfo->HighestRate, pRaInfo->DecisionRate));
+ return 0;
+}
+
+static void odm_PTTryState_8188E(struct odm_ra_info *pRaInfo)
+{
+ pRaInfo->PTTryState = 0;
+ switch (pRaInfo->PTModeSS) {
+ case 3:
+ if (pRaInfo->DecisionRate >= 0x19)
+ pRaInfo->PTTryState = 1;
+ break;
+ case 2:
+ if (pRaInfo->DecisionRate >= 0x11)
+ pRaInfo->PTTryState = 1;
+ break;
+ case 1:
+ if (pRaInfo->DecisionRate >= 0x0a)
+ pRaInfo->PTTryState = 1;
+ break;
+ case 0:
+ if (pRaInfo->DecisionRate >= 0x03)
+ pRaInfo->PTTryState = 1;
+ break;
+ default:
+ pRaInfo->PTTryState = 0;
+ break;
+ }
+
+ if (pRaInfo->RssiStaRA < 48) {
+ pRaInfo->PTStage = 0;
+ } else if (pRaInfo->PTTryState == 1) {
+ if ((pRaInfo->PTStopCount >= 10) ||
+ (pRaInfo->PTPreRssi > pRaInfo->RssiStaRA + 5) ||
+ (pRaInfo->PTPreRssi < pRaInfo->RssiStaRA - 5) ||
+ (pRaInfo->DecisionRate != pRaInfo->PTPreRate)) {
+ if (pRaInfo->PTStage == 0)
+ pRaInfo->PTStage = 1;
+ else if (pRaInfo->PTStage == 1)
+ pRaInfo->PTStage = 3;
+ else
+ pRaInfo->PTStage = 5;
+
+ pRaInfo->PTPreRssi = pRaInfo->RssiStaRA;
+ pRaInfo->PTStopCount = 0;
+ } else {
+ pRaInfo->RAstage = 0;
+ pRaInfo->PTStopCount++;
+ }
+ } else {
+ pRaInfo->PTStage = 0;
+ pRaInfo->RAstage = 0;
+ }
+ pRaInfo->PTPreRate = pRaInfo->DecisionRate;
+}
+
+static void odm_PTDecision_8188E(struct odm_ra_info *pRaInfo)
+{
+ u8 j;
+ u8 temp_stage;
+ u32 numsc;
+ u32 num_total;
+ u8 stage_id;
+
+ numsc = 0;
+ num_total = pRaInfo->TOTAL * PT_PENALTY[5];
+ for (j = 0; j <= 4; j++) {
+ numsc += pRaInfo->RTY[j] * PT_PENALTY[j];
+ if (numsc > num_total)
+ break;
+ }
+
+ j >>= 1;
+ temp_stage = (pRaInfo->PTStage + 1) >> 1;
+ if (temp_stage > j)
+ stage_id = temp_stage - j;
+ else
+ stage_id = 0;
+
+ pRaInfo->PTSmoothFactor = (pRaInfo->PTSmoothFactor >> 1) +
+ (pRaInfo->PTSmoothFactor >> 2) +
+ stage_id * 16 + 2;
+ if (pRaInfo->PTSmoothFactor > 192)
+ pRaInfo->PTSmoothFactor = 192;
+ stage_id = pRaInfo->PTSmoothFactor >> 6;
+ temp_stage = stage_id * 2;
+ if (temp_stage != 0)
+ temp_stage -= 1;
+ if (pRaInfo->DROP > 3)
+ temp_stage = 0;
+ pRaInfo->PTStage = temp_stage;
+}
+
+static void odm_RATxRPTTimerSetting(struct odm_dm_struct *dm_odm,
+ u16 minRptTime)
+{
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+ (" =====>%s()\n", __func__));
+
+ if (dm_odm->CurrminRptTime != minRptTime) {
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
+ (" CurrminRptTime = 0x%04x minRptTime = 0x%04x\n", dm_odm->CurrminRptTime, minRptTime));
+ rtw_rpt_timer_cfg_cmd(dm_odm->Adapter, minRptTime);
+ dm_odm->CurrminRptTime = minRptTime;
+ }
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+ (" <===== %s()\n", __func__));
+}
+
+int ODM_RAInfo_Init(struct odm_dm_struct *dm_odm, u8 macid)
+{
+ struct odm_ra_info *pRaInfo = &dm_odm->RAInfo[macid];
+ u8 WirelessMode = 0xFF; /* invalid value */
+ u8 max_rate_idx = 0x13; /* MCS7 */
+
+ if (dm_odm->pWirelessMode)
+ WirelessMode = *dm_odm->pWirelessMode;
+
+ if (WirelessMode != 0xFF) {
+ if (WirelessMode & ODM_WM_N24G)
+ max_rate_idx = 0x13;
+ else if (WirelessMode & ODM_WM_G)
+ max_rate_idx = 0x0b;
+ else if (WirelessMode & ODM_WM_B)
+ max_rate_idx = 0x03;
+ }
+
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
+ ("%s(): WirelessMode:0x%08x , max_raid_idx:0x%02x\n",
+ __func__, WirelessMode, max_rate_idx));
+
+ pRaInfo->DecisionRate = max_rate_idx;
+ pRaInfo->PreRate = max_rate_idx;
+ pRaInfo->HighestRate = max_rate_idx;
+ pRaInfo->LowestRate = 0;
+ pRaInfo->RateID = 0;
+ pRaInfo->RateMask = 0xffffffff;
+ pRaInfo->RssiStaRA = 0;
+ pRaInfo->PreRssiStaRA = 0;
+ pRaInfo->SGIEnable = 0;
+ pRaInfo->RAUseRate = 0xffffffff;
+ pRaInfo->NscDown = (N_THRESHOLD_HIGH[0x13] + N_THRESHOLD_LOW[0x13]) / 2;
+ pRaInfo->NscUp = (N_THRESHOLD_HIGH[0x13] + N_THRESHOLD_LOW[0x13]) / 2;
+ pRaInfo->RateSGI = 0;
+ pRaInfo->Active = 1; /* Active is not used at present. by page, 110819 */
+ pRaInfo->RptTime = 0x927c;
+ pRaInfo->DROP = 0;
+ pRaInfo->RTY[0] = 0;
+ pRaInfo->RTY[1] = 0;
+ pRaInfo->RTY[2] = 0;
+ pRaInfo->RTY[3] = 0;
+ pRaInfo->RTY[4] = 0;
+ pRaInfo->TOTAL = 0;
+ pRaInfo->RAWaitingCounter = 0;
+ pRaInfo->RAPendingCounter = 0;
+ pRaInfo->PTActive = 1; /* Active when this STA is use */
+ pRaInfo->PTTryState = 0;
+ pRaInfo->PTStage = 5; /* Need to fill into HW_PWR_STATUS */
+ pRaInfo->PTSmoothFactor = 192;
+ pRaInfo->PTStopCount = 0;
+ pRaInfo->PTPreRate = 0;
+ pRaInfo->PTPreRssi = 0;
+ pRaInfo->PTModeSS = 0;
+ pRaInfo->RAstage = 0;
+ return 0;
+}
+
+int ODM_RAInfo_Init_all(struct odm_dm_struct *dm_odm)
+{
+ u8 macid = 0;
+
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, ("=====>\n"));
+ dm_odm->CurrminRptTime = 0;
+
+ for (macid = 0; macid < ODM_ASSOCIATE_ENTRY_NUM; macid++)
+ ODM_RAInfo_Init(dm_odm, macid);
+
+ return 0;
+}
+
+u8 ODM_RA_GetShortGI_8188E(struct odm_dm_struct *dm_odm, u8 macid)
+{
+ if ((!dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
+ return 0;
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+ ("macid =%d SGI =%d\n", macid, dm_odm->RAInfo[macid].RateSGI));
+ return dm_odm->RAInfo[macid].RateSGI;
+}
+
+u8 ODM_RA_GetDecisionRate_8188E(struct odm_dm_struct *dm_odm, u8 macid)
+{
+ u8 DecisionRate = 0;
+
+ if ((!dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
+ return 0;
+ DecisionRate = dm_odm->RAInfo[macid].DecisionRate;
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+ (" macid =%d DecisionRate = 0x%x\n", macid, DecisionRate));
+ return DecisionRate;
+}
+
+u8 ODM_RA_GetHwPwrStatus_8188E(struct odm_dm_struct *dm_odm, u8 macid)
+{
+ u8 PTStage = 5;
+
+ if ((!dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
+ return 0;
+ PTStage = dm_odm->RAInfo[macid].PTStage;
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+ ("macid =%d PTStage = 0x%x\n", macid, PTStage));
+ return PTStage;
+}
+
+void ODM_RA_UpdateRateInfo_8188E(struct odm_dm_struct *dm_odm, u8 macid, u8 RateID, u32 RateMask, u8 SGIEnable)
+{
+ struct odm_ra_info *pRaInfo = NULL;
+
+ if ((!dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
+ return;
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
+ ("macid =%d RateID = 0x%x RateMask = 0x%x SGIEnable =%d\n",
+ macid, RateID, RateMask, SGIEnable));
+
+ pRaInfo = &dm_odm->RAInfo[macid];
+ pRaInfo->RateID = RateID;
+ pRaInfo->RateMask = RateMask;
+ pRaInfo->SGIEnable = SGIEnable;
+ odm_ARFBRefresh_8188E(dm_odm, pRaInfo);
+}
+
+void ODM_RA_SetRSSI_8188E(struct odm_dm_struct *dm_odm, u8 macid, u8 Rssi)
+{
+ struct odm_ra_info *pRaInfo = NULL;
+
+ if ((!dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
+ return;
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+ (" macid =%d Rssi =%d\n", macid, Rssi));
+
+ pRaInfo = &dm_odm->RAInfo[macid];
+ pRaInfo->RssiStaRA = Rssi;
+}
+
+void ODM_RA_Set_TxRPT_Time(struct odm_dm_struct *dm_odm, u16 minRptTime)
+{
+ struct adapter *adapt = dm_odm->Adapter;
+
+ usb_write16(adapt, REG_TX_RPT_TIME, minRptTime);
+}
+
+void ODM_RA_TxRPT2Handle_8188E(struct odm_dm_struct *dm_odm, u8 *TxRPT_Buf, u16 TxRPT_Len, u32 macid_entry0, u32 macid_entry1)
+{
+ struct odm_ra_info *pRAInfo = NULL;
+ u8 MacId = 0;
+ u8 *pBuffer = NULL;
+ u32 valid = 0, ItemNum = 0;
+ u16 minRptTime = 0x927c;
+
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
+ ("=====>%s(): valid0 =%d valid1 =%d BufferLength =%d\n",
+ __func__, macid_entry0, macid_entry1, TxRPT_Len));
+
+ ItemNum = TxRPT_Len >> 3;
+ pBuffer = TxRPT_Buf;
+
+ do {
+ if (MacId >= ASSOCIATE_ENTRY_NUM)
+ valid = 0;
+ else if (MacId >= 32)
+ valid = (1 << (MacId - 32)) & macid_entry1;
+ else
+ valid = (1 << MacId) & macid_entry0;
+
+ pRAInfo = &dm_odm->RAInfo[MacId];
+ if (valid) {
+ pRAInfo->RTY[0] = (u16)GET_TX_REPORT_TYPE1_RERTY_0(pBuffer);
+ pRAInfo->RTY[1] = (u16)GET_TX_REPORT_TYPE1_RERTY_1(pBuffer);
+ pRAInfo->RTY[2] = (u16)GET_TX_REPORT_TYPE1_RERTY_2(pBuffer);
+ pRAInfo->RTY[3] = (u16)GET_TX_REPORT_TYPE1_RERTY_3(pBuffer);
+ pRAInfo->RTY[4] = (u16)GET_TX_REPORT_TYPE1_RERTY_4(pBuffer);
+ pRAInfo->DROP = (u16)GET_TX_REPORT_TYPE1_DROP_0(pBuffer);
+ pRAInfo->TOTAL = pRAInfo->RTY[0] + pRAInfo->RTY[1] +
+ pRAInfo->RTY[2] + pRAInfo->RTY[3] +
+ pRAInfo->RTY[4] + pRAInfo->DROP;
+ if (pRAInfo->TOTAL != 0) {
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
+ ("macid =%d Total =%d R0 =%d R1 =%d R2 =%d R3 =%d R4 =%d D0 =%d valid0 =%x valid1 =%x\n",
+ MacId, pRAInfo->TOTAL,
+ pRAInfo->RTY[0], pRAInfo->RTY[1],
+ pRAInfo->RTY[2], pRAInfo->RTY[3],
+ pRAInfo->RTY[4], pRAInfo->DROP,
+ macid_entry0, macid_entry1));
+ if (pRAInfo->PTActive) {
+ if (pRAInfo->RAstage < 5)
+ odm_RateDecision_8188E(dm_odm, pRAInfo);
+ else if (pRAInfo->RAstage == 5) /* Power training try state */
+ odm_PTTryState_8188E(pRAInfo);
+ else /* RAstage == 6 */
+ odm_PTDecision_8188E(pRAInfo);
+
+ /* Stage_RA counter */
+ if (pRAInfo->RAstage <= 5)
+ pRAInfo->RAstage++;
+ else
+ pRAInfo->RAstage = 0;
+ } else {
+ odm_RateDecision_8188E(dm_odm, pRAInfo);
+ }
+ ODM_RT_TRACE(dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD,
+ ("macid =%d R0 =%d R1 =%d R2 =%d R3 =%d R4 =%d drop =%d valid0 =%x RateID =%d SGI =%d\n",
+ MacId,
+ pRAInfo->RTY[0],
+ pRAInfo->RTY[1],
+ pRAInfo->RTY[2],
+ pRAInfo->RTY[3],
+ pRAInfo->RTY[4],
+ pRAInfo->DROP,
+ macid_entry0,
+ pRAInfo->DecisionRate,
+ pRAInfo->RateSGI));
+ } else {
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD, (" TOTAL = 0!!!!\n"));
+ }
+ }
+
+ if (minRptTime > pRAInfo->RptTime)
+ minRptTime = pRAInfo->RptTime;
+
+ pBuffer += TX_RPT2_ITEM_SIZE;
+ MacId++;
+ } while (MacId < ItemNum);
+
+ odm_RATxRPTTimerSetting(dm_odm, minRptTime);
+
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
+ ("<===== %s()\n", __func__));
+}
diff --git a/drivers/staging/rtl8188eu/hal/hal_com.c b/drivers/staging/rtl8188eu/hal/hal_com.c
new file mode 100644
index 0000000..95f1b14
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/hal_com.c
@@ -0,0 +1,285 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#include <osdep_service.h>
+#include <drv_types.h>
+
+#include <hal_intf.h>
+#include <hal_com.h>
+#include <rtl8188e_hal.h>
+
+#define _HAL_INIT_C_
+
+void dump_chip_info(struct HAL_VERSION chip_vers)
+{
+ uint cnt = 0;
+ char buf[128];
+
+ cnt += sprintf((buf+cnt), "Chip Version Info: CHIP_8188E_");
+ cnt += sprintf((buf+cnt), "%s_", chip_vers.ChipType == NORMAL_CHIP ?
+ "Normal_Chip" : "Test_Chip");
+ cnt += sprintf((buf+cnt), "%s_", chip_vers.VendorType == CHIP_VENDOR_TSMC ?
+ "TSMC" : "UMC");
+ if (chip_vers.CUTVersion == A_CUT_VERSION)
+ cnt += sprintf((buf+cnt), "A_CUT_");
+ else if (chip_vers.CUTVersion == B_CUT_VERSION)
+ cnt += sprintf((buf+cnt), "B_CUT_");
+ else if (chip_vers.CUTVersion == C_CUT_VERSION)
+ cnt += sprintf((buf+cnt), "C_CUT_");
+ else if (chip_vers.CUTVersion == D_CUT_VERSION)
+ cnt += sprintf((buf+cnt), "D_CUT_");
+ else if (chip_vers.CUTVersion == E_CUT_VERSION)
+ cnt += sprintf((buf+cnt), "E_CUT_");
+ else
+ cnt += sprintf((buf+cnt), "UNKNOWN_CUT(%d)_",
+ chip_vers.CUTVersion);
+ cnt += sprintf((buf+cnt), "1T1R_");
+ cnt += sprintf((buf+cnt), "RomVer(0)\n");
+
+ pr_info("%s", buf);
+}
+
+#define CHAN_PLAN_HW 0x80
+
+/* return the final channel plan decision */
+u8 hal_com_get_channel_plan(u8 hw_channel_plan, u8 sw_channel_plan,
+ u8 def_channel_plan, bool load_fail)
+{
+ u8 sw_cfg;
+ u8 chnlplan;
+
+ sw_cfg = true;
+ if (!load_fail) {
+ if (!rtw_is_channel_plan_valid(sw_channel_plan))
+ sw_cfg = false;
+ if (hw_channel_plan & CHAN_PLAN_HW)
+ sw_cfg = false;
+ }
+
+ if (sw_cfg)
+ chnlplan = sw_channel_plan;
+ else
+ chnlplan = hw_channel_plan & (~CHAN_PLAN_HW);
+
+ if (!rtw_is_channel_plan_valid(chnlplan))
+ chnlplan = def_channel_plan;
+
+ return chnlplan;
+}
+
+u8 MRateToHwRate(u8 rate)
+{
+ u8 ret = DESC_RATE1M;
+
+ switch (rate) {
+ /* CCK and OFDM non-HT rates */
+ case IEEE80211_CCK_RATE_1MB:
+ ret = DESC_RATE1M;
+ break;
+ case IEEE80211_CCK_RATE_2MB:
+ ret = DESC_RATE2M;
+ break;
+ case IEEE80211_CCK_RATE_5MB:
+ ret = DESC_RATE5_5M;
+ break;
+ case IEEE80211_CCK_RATE_11MB:
+ ret = DESC_RATE11M;
+ break;
+ case IEEE80211_OFDM_RATE_6MB:
+ ret = DESC_RATE6M;
+ break;
+ case IEEE80211_OFDM_RATE_9MB:
+ ret = DESC_RATE9M;
+ break;
+ case IEEE80211_OFDM_RATE_12MB:
+ ret = DESC_RATE12M;
+ break;
+ case IEEE80211_OFDM_RATE_18MB:
+ ret = DESC_RATE18M;
+ break;
+ case IEEE80211_OFDM_RATE_24MB:
+ ret = DESC_RATE24M;
+ break;
+ case IEEE80211_OFDM_RATE_36MB:
+ ret = DESC_RATE36M;
+ break;
+ case IEEE80211_OFDM_RATE_48MB:
+ ret = DESC_RATE48M;
+ break;
+ case IEEE80211_OFDM_RATE_54MB:
+ ret = DESC_RATE54M;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+void hal_set_brate_cfg(u8 *brates, u16 *rate_cfg)
+{
+ u8 i, is_brate, brate;
+
+ for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
+ is_brate = brates[i] & IEEE80211_BASIC_RATE_MASK;
+ brate = brates[i] & 0x7f;
+
+ if (is_brate) {
+ switch (brate) {
+ case IEEE80211_CCK_RATE_1MB:
+ *rate_cfg |= RATE_1M;
+ break;
+ case IEEE80211_CCK_RATE_2MB:
+ *rate_cfg |= RATE_2M;
+ break;
+ case IEEE80211_CCK_RATE_5MB:
+ *rate_cfg |= RATE_5_5M;
+ break;
+ case IEEE80211_CCK_RATE_11MB:
+ *rate_cfg |= RATE_11M;
+ break;
+ case IEEE80211_OFDM_RATE_6MB:
+ *rate_cfg |= RATE_6M;
+ break;
+ case IEEE80211_OFDM_RATE_9MB:
+ *rate_cfg |= RATE_9M;
+ break;
+ case IEEE80211_OFDM_RATE_12MB:
+ *rate_cfg |= RATE_12M;
+ break;
+ case IEEE80211_OFDM_RATE_18MB:
+ *rate_cfg |= RATE_18M;
+ break;
+ case IEEE80211_OFDM_RATE_24MB:
+ *rate_cfg |= RATE_24M;
+ break;
+ case IEEE80211_OFDM_RATE_36MB:
+ *rate_cfg |= RATE_36M;
+ break;
+ case IEEE80211_OFDM_RATE_48MB:
+ *rate_cfg |= RATE_48M;
+ break;
+ case IEEE80211_OFDM_RATE_54MB:
+ *rate_cfg |= RATE_54M;
+ break;
+ }
+ }
+ }
+}
+
+static void one_out_pipe(struct adapter *adapter)
+{
+ struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapter);
+
+ pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
+ pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];/* VI */
+ pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[0];/* BE */
+ pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0];/* BK */
+
+ pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
+ pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
+ pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
+ pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
+}
+
+static void two_out_pipe(struct adapter *adapter, bool wifi_cfg)
+{
+ struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapter);
+
+ if (wifi_cfg) {
+ /*
+ * WMM
+ * BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA
+ * 0, 1, 0, 1, 0, 0, 0, 0, 0
+ * 0:H, 1:L
+ */
+ pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[1];/* VO */
+ pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];/* VI */
+ pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1];/* BE */
+ pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0];/* BK */
+
+ pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
+ pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
+ pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
+ pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
+ } else {
+ /*
+ * typical setting
+ * BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA
+ * 1, 1, 0, 0, 0, 0, 0, 0, 0
+ * 0:H, 1:L
+ */
+ pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
+ pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];/* VI */
+ pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1];/* BE */
+ pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1];/* BK */
+
+ pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
+ pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
+ pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
+ pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
+ }
+}
+
+static void three_out_pipe(struct adapter *adapter, bool wifi_cfg)
+{
+ struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapter);
+
+ if (wifi_cfg) {
+ /*
+ * for WMM
+ * BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA
+ * 1, 2, 1, 0, 0, 0, 0, 0, 0
+ * 0:H, 1:N, 2:L
+ */
+ pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
+ pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1];/* VI */
+ pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2];/* BE */
+ pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1];/* BK */
+
+ pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
+ pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
+ pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
+ pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
+ } else {
+ /*
+ * typical setting
+ * BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA
+ * 2, 2, 1, 0, 0, 0, 0, 0, 0
+ * 0:H, 1:N, 2:L
+ */
+ pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
+ pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1];/* VI */
+ pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2];/* BE */
+ pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[2];/* BK */
+
+ pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
+ pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
+ pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
+ pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
+ }
+}
+
+bool hal_mapping_out_pipe(struct adapter *adapter, u8 numoutpipe)
+{
+ struct registry_priv *pregistrypriv = &adapter->registrypriv;
+ bool wifi_cfg = (pregistrypriv->wifi_spec) ? true : false;
+ bool result = true;
+
+ switch (numoutpipe) {
+ case 1:
+ one_out_pipe(adapter);
+ break;
+ case 2:
+ two_out_pipe(adapter, wifi_cfg);
+ break;
+ case 3:
+ three_out_pipe(adapter, wifi_cfg);
+ break;
+ default:
+ result = false;
+ }
+ return result;
+}
diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c
new file mode 100644
index 0000000..417b3bf
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/hal_intf.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#define _HAL_INTF_C_
+#include <hal_intf.h>
+
+uint rtw_hal_init(struct adapter *adapt)
+{
+ uint status = _SUCCESS;
+
+ adapt->hw_init_completed = false;
+
+ status = rtl8188eu_hal_init(adapt);
+
+ if (status == _SUCCESS) {
+ adapt->hw_init_completed = true;
+
+ if (adapt->registrypriv.notch_filter == 1)
+ rtw_hal_notch_filter(adapt, 1);
+ } else {
+ adapt->hw_init_completed = false;
+ DBG_88E("rtw_hal_init: hal__init fail\n");
+ }
+
+ RT_TRACE(_module_hal_init_c_, _drv_err_,
+ ("-rtl871x_hal_init:status=0x%x\n", status));
+
+ return status;
+}
+
+uint rtw_hal_deinit(struct adapter *adapt)
+{
+ uint status = _SUCCESS;
+
+ status = rtl8188eu_hal_deinit(adapt);
+
+ if (status == _SUCCESS)
+ adapt->hw_init_completed = false;
+ else
+ DBG_88E("\n rtw_hal_deinit: hal_init fail\n");
+
+ return status;
+}
+
+void rtw_hal_update_ra_mask(struct adapter *adapt, u32 mac_id, u8 rssi_level)
+{
+ struct mlme_priv *pmlmepriv = &adapt->mlmepriv;
+
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+#ifdef CPTCFG_88EU_AP_MODE
+ struct sta_info *psta = NULL;
+ struct sta_priv *pstapriv = &adapt->stapriv;
+
+ if (mac_id - 1 > 0)
+ psta = pstapriv->sta_aid[mac_id - 2];
+ if (psta)
+ add_RATid(adapt, psta, 0);/* todo: based on rssi_level*/
+#endif
+ } else {
+ UpdateHalRAMask8188EUsb(adapt, mac_id, rssi_level);
+ }
+}
diff --git a/drivers/staging/rtl8188eu/hal/mac_cfg.c b/drivers/staging/rtl8188eu/hal/mac_cfg.c
new file mode 100644
index 0000000..370aa5c
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/mac_cfg.c
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include "odm_precomp.h"
+#include "phy.h"
+
+/* MAC_REG.TXT */
+
+static u32 array_MAC_REG_8188E[] = {
+ 0x026, 0x00000041,
+ 0x027, 0x00000035,
+ 0x428, 0x0000000A,
+ 0x429, 0x00000010,
+ 0x430, 0x00000000,
+ 0x431, 0x00000001,
+ 0x432, 0x00000002,
+ 0x433, 0x00000004,
+ 0x434, 0x00000005,
+ 0x435, 0x00000006,
+ 0x436, 0x00000007,
+ 0x437, 0x00000008,
+ 0x438, 0x00000000,
+ 0x439, 0x00000000,
+ 0x43A, 0x00000001,
+ 0x43B, 0x00000002,
+ 0x43C, 0x00000004,
+ 0x43D, 0x00000005,
+ 0x43E, 0x00000006,
+ 0x43F, 0x00000007,
+ 0x440, 0x0000005D,
+ 0x441, 0x00000001,
+ 0x442, 0x00000000,
+ 0x444, 0x00000015,
+ 0x445, 0x000000F0,
+ 0x446, 0x0000000F,
+ 0x447, 0x00000000,
+ 0x458, 0x00000041,
+ 0x459, 0x000000A8,
+ 0x45A, 0x00000072,
+ 0x45B, 0x000000B9,
+ 0x460, 0x00000066,
+ 0x461, 0x00000066,
+ 0x480, 0x00000008,
+ 0x4C8, 0x000000FF,
+ 0x4C9, 0x00000008,
+ 0x4CC, 0x000000FF,
+ 0x4CD, 0x000000FF,
+ 0x4CE, 0x00000001,
+ 0x4D3, 0x00000001,
+ 0x500, 0x00000026,
+ 0x501, 0x000000A2,
+ 0x502, 0x0000002F,
+ 0x503, 0x00000000,
+ 0x504, 0x00000028,
+ 0x505, 0x000000A3,
+ 0x506, 0x0000005E,
+ 0x507, 0x00000000,
+ 0x508, 0x0000002B,
+ 0x509, 0x000000A4,
+ 0x50A, 0x0000005E,
+ 0x50B, 0x00000000,
+ 0x50C, 0x0000004F,
+ 0x50D, 0x000000A4,
+ 0x50E, 0x00000000,
+ 0x50F, 0x00000000,
+ 0x512, 0x0000001C,
+ 0x514, 0x0000000A,
+ 0x516, 0x0000000A,
+ 0x525, 0x0000004F,
+ 0x550, 0x00000010,
+ 0x551, 0x00000010,
+ 0x559, 0x00000002,
+ 0x55D, 0x000000FF,
+ 0x605, 0x00000030,
+ 0x608, 0x0000000E,
+ 0x609, 0x0000002A,
+ 0x620, 0x000000FF,
+ 0x621, 0x000000FF,
+ 0x622, 0x000000FF,
+ 0x623, 0x000000FF,
+ 0x624, 0x000000FF,
+ 0x625, 0x000000FF,
+ 0x626, 0x000000FF,
+ 0x627, 0x000000FF,
+ 0x652, 0x00000020,
+ 0x63C, 0x0000000A,
+ 0x63D, 0x0000000A,
+ 0x63E, 0x0000000E,
+ 0x63F, 0x0000000E,
+ 0x640, 0x00000040,
+ 0x66E, 0x00000005,
+ 0x700, 0x00000021,
+ 0x701, 0x00000043,
+ 0x702, 0x00000065,
+ 0x703, 0x00000087,
+ 0x708, 0x00000021,
+ 0x709, 0x00000043,
+ 0x70A, 0x00000065,
+ 0x70B, 0x00000087,
+};
+
+bool rtl88eu_phy_mac_config(struct adapter *adapt)
+{
+ u32 i;
+ u32 arraylength;
+ u32 *ptrarray;
+
+ arraylength = ARRAY_SIZE(array_MAC_REG_8188E);
+ ptrarray = array_MAC_REG_8188E;
+
+ for (i = 0; i < arraylength; i += 2)
+ usb_write8(adapt, ptrarray[i], (u8)ptrarray[i + 1]);
+
+ usb_write8(adapt, REG_MAX_AGGR_NUM, MAX_AGGR_NUM);
+ return true;
+}
diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c
new file mode 100644
index 0000000..4e2f6cb
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/odm.c
@@ -0,0 +1,1101 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+/* include files */
+
+#include "odm_precomp.h"
+#include "phy.h"
+
+u32 GlobalDebugLevel;
+
+/* avoid to warn in FreeBSD ==> To DO modify */
+static u32 EDCAParam[HT_IOT_PEER_MAX][3] = {
+ /* UL DL */
+ {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 0:unknown AP */
+ {0xa44f, 0x5ea44f, 0x5e431c}, /* 1:realtek AP */
+ {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 2:unknown AP => realtek_92SE */
+ {0x5ea32b, 0x5ea42b, 0x5e4322}, /* 3:broadcom AP */
+ {0x5ea422, 0x00a44f, 0x00a44f}, /* 4:ralink AP */
+ {0x5ea322, 0x00a630, 0x00a44f}, /* 5:atheros AP */
+ {0x5e4322, 0x5e4322, 0x5e4322},/* 6:cisco AP */
+ {0x5ea44f, 0x00a44f, 0x5ea42b}, /* 8:marvell AP */
+ {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 10:unknown AP=> 92U AP */
+ {0x5ea42b, 0xa630, 0x5e431c}, /* 11:airgocap AP */
+};
+
+/* Global var */
+u32 OFDMSwingTable[OFDM_TABLE_SIZE_92D] = {
+ 0x7f8001fe, /* 0, +6.0dB */
+ 0x788001e2, /* 1, +5.5dB */
+ 0x71c001c7, /* 2, +5.0dB */
+ 0x6b8001ae, /* 3, +4.5dB */
+ 0x65400195, /* 4, +4.0dB */
+ 0x5fc0017f, /* 5, +3.5dB */
+ 0x5a400169, /* 6, +3.0dB */
+ 0x55400155, /* 7, +2.5dB */
+ 0x50800142, /* 8, +2.0dB */
+ 0x4c000130, /* 9, +1.5dB */
+ 0x47c0011f, /* 10, +1.0dB */
+ 0x43c0010f, /* 11, +0.5dB */
+ 0x40000100, /* 12, +0dB */
+ 0x3c8000f2, /* 13, -0.5dB */
+ 0x390000e4, /* 14, -1.0dB */
+ 0x35c000d7, /* 15, -1.5dB */
+ 0x32c000cb, /* 16, -2.0dB */
+ 0x300000c0, /* 17, -2.5dB */
+ 0x2d4000b5, /* 18, -3.0dB */
+ 0x2ac000ab, /* 19, -3.5dB */
+ 0x288000a2, /* 20, -4.0dB */
+ 0x26000098, /* 21, -4.5dB */
+ 0x24000090, /* 22, -5.0dB */
+ 0x22000088, /* 23, -5.5dB */
+ 0x20000080, /* 24, -6.0dB */
+ 0x1e400079, /* 25, -6.5dB */
+ 0x1c800072, /* 26, -7.0dB */
+ 0x1b00006c, /* 27. -7.5dB */
+ 0x19800066, /* 28, -8.0dB */
+ 0x18000060, /* 29, -8.5dB */
+ 0x16c0005b, /* 30, -9.0dB */
+ 0x15800056, /* 31, -9.5dB */
+ 0x14400051, /* 32, -10.0dB */
+ 0x1300004c, /* 33, -10.5dB */
+ 0x12000048, /* 34, -11.0dB */
+ 0x11000044, /* 35, -11.5dB */
+ 0x10000040, /* 36, -12.0dB */
+ 0x0f00003c,/* 37, -12.5dB */
+ 0x0e400039,/* 38, -13.0dB */
+ 0x0d800036,/* 39, -13.5dB */
+ 0x0cc00033,/* 40, -14.0dB */
+ 0x0c000030,/* 41, -14.5dB */
+ 0x0b40002d,/* 42, -15.0dB */
+};
+
+u8 CCKSwingTable_Ch1_Ch13[CCK_TABLE_SIZE][8] = {
+ {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */
+ {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */
+ {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB */
+ {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB */
+ {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */
+ {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB */
+ {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB */
+ {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB */
+ {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */
+ {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB */
+ {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */
+ {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB */
+ {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB */
+ {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB */
+ {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */
+ {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB */
+ {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */
+ {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB */
+ {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */
+ {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB */
+ {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB */
+ {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB */
+ {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB */
+ {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB */
+ {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB */
+ {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB */
+ {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB */
+ {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB */
+ {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB */
+ {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB */
+ {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB */
+ {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB */
+ {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} /* 32, -16.0dB */
+};
+
+u8 CCKSwingTable_Ch14[CCK_TABLE_SIZE][8] = {
+ {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0dB */
+ {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 1, -0.5dB */
+ {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 2, -1.0dB */
+ {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 3, -1.5dB */
+ {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 4, -2.0dB */
+ {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 5, -2.5dB */
+ {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 6, -3.0dB */
+ {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 7, -3.5dB */
+ {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 8, -4.0dB */
+ {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 9, -4.5dB */
+ {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 10, -5.0dB */
+ {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 11, -5.5dB */
+ {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 12, -6.0dB */
+ {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 13, -6.5dB */
+ {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 14, -7.0dB */
+ {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 15, -7.5dB */
+ {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */
+ {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 17, -8.5dB */
+ {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 18, -9.0dB */
+ {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 19, -9.5dB */
+ {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 20, -10.0dB */
+ {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 21, -10.5dB */
+ {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 22, -11.0dB */
+ {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 23, -11.5dB */
+ {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 24, -12.0dB */
+ {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 25, -12.5dB */
+ {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 26, -13.0dB */
+ {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 27, -13.5dB */
+ {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 28, -14.0dB */
+ {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 29, -14.5dB */
+ {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 30, -15.0dB */
+ {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 31, -15.5dB */
+ {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} /* 32, -16.0dB */
+};
+
+#define RxDefaultAnt1 0x65a9
+#define RxDefaultAnt2 0x569a
+
+void ODM_InitDebugSetting(struct odm_dm_struct *pDM_Odm)
+{
+ pDM_Odm->DebugLevel = ODM_DBG_TRACE;
+
+ pDM_Odm->DebugComponents = 0;
+}
+
+/* 3 Export Interface */
+
+/* 2011/09/21 MH Add to describe different team necessary resource allocate?? */
+void ODM_DMInit(struct odm_dm_struct *pDM_Odm)
+{
+ /* 2012.05.03 Luke: For all IC series */
+ odm_CommonInfoSelfInit(pDM_Odm);
+ odm_CmnInfoInit_Debug(pDM_Odm);
+ odm_DIGInit(pDM_Odm);
+ odm_RateAdaptiveMaskInit(pDM_Odm);
+
+ odm_DynamicTxPowerInit(pDM_Odm);
+ odm_TXPowerTrackingInit(pDM_Odm);
+ ODM_EdcaTurboInit(pDM_Odm);
+ ODM_RAInfo_Init_all(pDM_Odm);
+ if ((pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV) ||
+ (pDM_Odm->AntDivType == CGCS_RX_HW_ANTDIV) ||
+ (pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV))
+ odm_InitHybridAntDiv(pDM_Odm);
+}
+
+/* 2011/09/20 MH This is the entry pointer for all team to execute HW out source DM. */
+/* You can not add any dummy function here, be care, you can only use DM structure */
+/* to perform any new ODM_DM. */
+void ODM_DMWatchdog(struct odm_dm_struct *pDM_Odm)
+{
+ /* 2012.05.03 Luke: For all IC series */
+ odm_CmnInfoHook_Debug(pDM_Odm);
+ odm_CmnInfoUpdate_Debug(pDM_Odm);
+ odm_CommonInfoSelfUpdate(pDM_Odm);
+ odm_FalseAlarmCounterStatistics(pDM_Odm);
+ odm_RSSIMonitorCheck(pDM_Odm);
+
+ /* Fix Leave LPS issue */
+ odm_DIG(pDM_Odm);
+ odm_CCKPacketDetectionThresh(pDM_Odm);
+
+ if (*(pDM_Odm->pbPowerSaving))
+ return;
+
+ odm_RefreshRateAdaptiveMask(pDM_Odm);
+
+ if ((pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV) ||
+ (pDM_Odm->AntDivType == CGCS_RX_HW_ANTDIV) ||
+ (pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV))
+ odm_HwAntDiv(pDM_Odm);
+
+ ODM_TXPowerTrackingCheck(pDM_Odm);
+ odm_EdcaTurboCheck(pDM_Odm);
+}
+
+void ODM_CmnInfoPtrArrayHook(struct odm_dm_struct *pDM_Odm, enum odm_common_info_def CmnInfo, u16 Index, void *pValue)
+{
+ if (CmnInfo == ODM_CMNINFO_STA_STATUS)
+ pDM_Odm->pODM_StaInfo[Index] = (struct sta_info *)pValue;
+}
+
+void odm_CommonInfoSelfInit(struct odm_dm_struct *pDM_Odm)
+{
+ struct adapter *adapter = pDM_Odm->Adapter;
+
+ pDM_Odm->bCckHighPower = (bool)phy_query_bb_reg(adapter, 0x824, BIT(9));
+ pDM_Odm->RFPathRxEnable = (u8)phy_query_bb_reg(adapter, 0xc04, 0x0F);
+
+ ODM_InitDebugSetting(pDM_Odm);
+}
+
+void odm_CommonInfoSelfUpdate(struct odm_dm_struct *pDM_Odm)
+{
+ u8 EntryCnt = 0;
+ u8 i;
+ struct sta_info *pEntry;
+
+ if (*(pDM_Odm->pBandWidth) == ODM_BW40M) {
+ if (*(pDM_Odm->pSecChOffset) == 1)
+ pDM_Odm->ControlChannel = *(pDM_Odm->pChannel) - 2;
+ else if (*(pDM_Odm->pSecChOffset) == 2)
+ pDM_Odm->ControlChannel = *(pDM_Odm->pChannel) + 2;
+ } else {
+ pDM_Odm->ControlChannel = *(pDM_Odm->pChannel);
+ }
+
+ for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
+ pEntry = pDM_Odm->pODM_StaInfo[i];
+ if (IS_STA_VALID(pEntry))
+ EntryCnt++;
+ }
+ if (EntryCnt == 1)
+ pDM_Odm->bOneEntryOnly = true;
+ else
+ pDM_Odm->bOneEntryOnly = false;
+}
+
+void odm_CmnInfoInit_Debug(struct odm_dm_struct *pDM_Odm)
+{
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_CmnInfoInit_Debug==>\n"));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportPlatform=%d\n", pDM_Odm->SupportPlatform));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportAbility=0x%x\n", pDM_Odm->SupportAbility));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportInterface=%d\n", pDM_Odm->SupportInterface));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportICType=0x%x\n", pDM_Odm->SupportICType));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("CutVersion=%d\n", pDM_Odm->CutVersion));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("BoardType=%d\n", pDM_Odm->BoardType));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtLNA=%d\n", pDM_Odm->ExtLNA));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtPA=%d\n", pDM_Odm->ExtPA));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtTRSW=%d\n", pDM_Odm->ExtTRSW));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("PatchID=%d\n", pDM_Odm->PatchID));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bInHctTest=%d\n", pDM_Odm->bInHctTest));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bWIFITest=%d\n", pDM_Odm->bWIFITest));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bDualMacSmartConcurrent=%d\n", pDM_Odm->bDualMacSmartConcurrent));
+}
+
+void odm_CmnInfoHook_Debug(struct odm_dm_struct *pDM_Odm)
+{
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_CmnInfoHook_Debug==>\n"));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pNumTxBytesUnicast=%llu\n", *(pDM_Odm->pNumTxBytesUnicast)));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pNumRxBytesUnicast=%llu\n", *(pDM_Odm->pNumRxBytesUnicast)));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pWirelessMode=0x%x\n", *(pDM_Odm->pWirelessMode)));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pSecChOffset=%d\n", *(pDM_Odm->pSecChOffset)));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pSecurity=%d\n", *(pDM_Odm->pSecurity)));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pBandWidth=%d\n", *(pDM_Odm->pBandWidth)));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pChannel=%d\n", *(pDM_Odm->pChannel)));
+
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pbScanInProcess=%d\n", *(pDM_Odm->pbScanInProcess)));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pbPowerSaving=%d\n", *(pDM_Odm->pbPowerSaving)));
+}
+
+void odm_CmnInfoUpdate_Debug(struct odm_dm_struct *pDM_Odm)
+{
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_CmnInfoUpdate_Debug==>\n"));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bWIFI_Direct=%d\n", pDM_Odm->bWIFI_Direct));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bWIFI_Display=%d\n", pDM_Odm->bWIFI_Display));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bLinked=%d\n", pDM_Odm->bLinked));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("RSSI_Min=%d\n", pDM_Odm->RSSI_Min));
+}
+
+void ODM_Write_DIG(struct odm_dm_struct *pDM_Odm, u8 CurrentIGI)
+{
+ struct rtw_dig *pDM_DigTable = &pDM_Odm->DM_DigTable;
+ struct adapter *adapter = pDM_Odm->Adapter;
+
+ if (pDM_DigTable->CurIGValue != CurrentIGI) {
+ phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, ODM_BIT_IGI_11N, CurrentIGI);
+ pDM_DigTable->CurIGValue = CurrentIGI;
+ }
+}
+
+void odm_DIGInit(struct odm_dm_struct *pDM_Odm)
+{
+ struct adapter *adapter = pDM_Odm->Adapter;
+ struct rtw_dig *pDM_DigTable = &pDM_Odm->DM_DigTable;
+
+ pDM_DigTable->CurIGValue = (u8)phy_query_bb_reg(adapter, ODM_REG_IGI_A_11N, ODM_BIT_IGI_11N);
+ pDM_DigTable->RssiLowThresh = DM_DIG_THRESH_LOW;
+ pDM_DigTable->RssiHighThresh = DM_DIG_THRESH_HIGH;
+ pDM_DigTable->FALowThresh = DM_false_ALARM_THRESH_LOW;
+ pDM_DigTable->FAHighThresh = DM_false_ALARM_THRESH_HIGH;
+ pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC;
+ pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC;
+ pDM_DigTable->BackoffVal = DM_DIG_BACKOFF_DEFAULT;
+ pDM_DigTable->BackoffVal_range_max = DM_DIG_BACKOFF_MAX;
+ pDM_DigTable->BackoffVal_range_min = DM_DIG_BACKOFF_MIN;
+ pDM_DigTable->PreCCK_CCAThres = 0xFF;
+ pDM_DigTable->CurCCK_CCAThres = 0x83;
+ pDM_DigTable->ForbiddenIGI = DM_DIG_MIN_NIC;
+ pDM_DigTable->LargeFAHit = 0;
+ pDM_DigTable->Recover_cnt = 0;
+ pDM_DigTable->DIG_Dynamic_MIN_0 = DM_DIG_MIN_NIC;
+ pDM_DigTable->DIG_Dynamic_MIN_1 = DM_DIG_MIN_NIC;
+ pDM_DigTable->bMediaConnect_0 = false;
+ pDM_DigTable->bMediaConnect_1 = false;
+
+ /* To Initialize pDM_Odm->bDMInitialGainEnable == false to avoid DIG error */
+ pDM_Odm->bDMInitialGainEnable = true;
+}
+
+void odm_DIG(struct odm_dm_struct *pDM_Odm)
+{
+ struct rtw_dig *pDM_DigTable = &pDM_Odm->DM_DigTable;
+ struct false_alarm_stats *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
+ u8 DIG_Dynamic_MIN;
+ u8 DIG_MaxOfMin;
+ bool FirstConnect, FirstDisConnect;
+ u8 dm_dig_max, dm_dig_min;
+ u8 CurrentIGI = pDM_DigTable->CurIGValue;
+
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG()==>\n"));
+ if ((!(pDM_Odm->SupportAbility&ODM_BB_DIG)) || (!(pDM_Odm->SupportAbility&ODM_BB_FA_CNT))) {
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
+ ("odm_DIG() Return: SupportAbility ODM_BB_DIG or ODM_BB_FA_CNT is disabled\n"));
+ return;
+ }
+
+ if (*(pDM_Odm->pbScanInProcess)) {
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG() Return: In Scan Progress\n"));
+ return;
+ }
+
+ /* add by Neil Chen to avoid PSD is processing */
+ if (!pDM_Odm->bDMInitialGainEnable) {
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG() Return: PSD is Processing\n"));
+ return;
+ }
+
+ DIG_Dynamic_MIN = pDM_DigTable->DIG_Dynamic_MIN_0;
+ FirstConnect = (pDM_Odm->bLinked) && (!pDM_DigTable->bMediaConnect_0);
+ FirstDisConnect = (!pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0);
+
+ /* 1 Boundary Decision */
+ dm_dig_max = DM_DIG_MAX_NIC;
+ dm_dig_min = DM_DIG_MIN_NIC;
+ DIG_MaxOfMin = DM_DIG_MAX_AP;
+
+ if (pDM_Odm->bLinked) {
+ /* 2 Modify DIG upper bound */
+ if ((pDM_Odm->RSSI_Min + 20) > dm_dig_max)
+ pDM_DigTable->rx_gain_range_max = dm_dig_max;
+ else if ((pDM_Odm->RSSI_Min + 20) < dm_dig_min)
+ pDM_DigTable->rx_gain_range_max = dm_dig_min;
+ else
+ pDM_DigTable->rx_gain_range_max = pDM_Odm->RSSI_Min + 20;
+ /* 2 Modify DIG lower bound */
+ if (pDM_Odm->bOneEntryOnly) {
+ if (pDM_Odm->RSSI_Min < dm_dig_min)
+ DIG_Dynamic_MIN = dm_dig_min;
+ else if (pDM_Odm->RSSI_Min > DIG_MaxOfMin)
+ DIG_Dynamic_MIN = DIG_MaxOfMin;
+ else
+ DIG_Dynamic_MIN = pDM_Odm->RSSI_Min;
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
+ ("odm_DIG() : bOneEntryOnly=true, DIG_Dynamic_MIN=0x%x\n",
+ DIG_Dynamic_MIN));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
+ ("odm_DIG() : pDM_Odm->RSSI_Min=%d\n",
+ pDM_Odm->RSSI_Min));
+ } else if (pDM_Odm->SupportAbility & ODM_BB_ANT_DIV) {
+ /* 1 Lower Bound for 88E AntDiv */
+ if (pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV) {
+ DIG_Dynamic_MIN = (u8)pDM_DigTable->AntDiv_RSSI_max;
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
+ ("odm_DIG(): pDM_DigTable->AntDiv_RSSI_max=%d\n",
+ pDM_DigTable->AntDiv_RSSI_max));
+ }
+ } else {
+ DIG_Dynamic_MIN = dm_dig_min;
+ }
+ } else {
+ pDM_DigTable->rx_gain_range_max = dm_dig_max;
+ DIG_Dynamic_MIN = dm_dig_min;
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG() : No Link\n"));
+ }
+
+ /* 1 Modify DIG lower bound, deal with abnormally large false alarm */
+ if (pFalseAlmCnt->Cnt_all > 10000) {
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("dm_DIG(): Abnormally false alarm case.\n"));
+
+ if (pDM_DigTable->LargeFAHit != 3)
+ pDM_DigTable->LargeFAHit++;
+ if (pDM_DigTable->ForbiddenIGI < CurrentIGI) {
+ pDM_DigTable->ForbiddenIGI = CurrentIGI;
+ pDM_DigTable->LargeFAHit = 1;
+ }
+
+ if (pDM_DigTable->LargeFAHit >= 3) {
+ if ((pDM_DigTable->ForbiddenIGI+1) > pDM_DigTable->rx_gain_range_max)
+ pDM_DigTable->rx_gain_range_min = pDM_DigTable->rx_gain_range_max;
+ else
+ pDM_DigTable->rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 1);
+ pDM_DigTable->Recover_cnt = 3600; /* 3600=2hr */
+ }
+
+ } else {
+ /* Recovery mechanism for IGI lower bound */
+ if (pDM_DigTable->Recover_cnt != 0) {
+ pDM_DigTable->Recover_cnt--;
+ } else {
+ if (pDM_DigTable->LargeFAHit < 3) {
+ if ((pDM_DigTable->ForbiddenIGI-1) < DIG_Dynamic_MIN) { /* DM_DIG_MIN) */
+ pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN; /* DM_DIG_MIN; */
+ pDM_DigTable->rx_gain_range_min = DIG_Dynamic_MIN; /* DM_DIG_MIN; */
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Normal Case: At Lower Bound\n"));
+ } else {
+ pDM_DigTable->ForbiddenIGI--;
+ pDM_DigTable->rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 1);
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): Normal Case: Approach Lower Bound\n"));
+ }
+ } else {
+ pDM_DigTable->LargeFAHit = 0;
+ }
+ }
+ }
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
+ ("odm_DIG(): pDM_DigTable->LargeFAHit=%d\n",
+ pDM_DigTable->LargeFAHit));
+
+ /* 1 Adjust initial gain by false alarm */
+ if (pDM_Odm->bLinked) {
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): DIG AfterLink\n"));
+ if (FirstConnect) {
+ CurrentIGI = pDM_Odm->RSSI_Min;
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("DIG: First Connect\n"));
+ } else {
+ if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2)
+ CurrentIGI = CurrentIGI + 4;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+2; */
+ else if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH1)
+ CurrentIGI = CurrentIGI + 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+1; */
+ else if (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH0)
+ CurrentIGI = CurrentIGI - 2;/* pDM_DigTable->CurIGValue =pDM_DigTable->PreIGValue-1; */
+ }
+ } else {
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): DIG BeforeLink\n"));
+ if (FirstDisConnect) {
+ CurrentIGI = pDM_DigTable->rx_gain_range_min;
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): First DisConnect\n"));
+ } else {
+ /* 2012.03.30 LukeLee: enable DIG before link but with very high thresholds */
+ if (pFalseAlmCnt->Cnt_all > 10000)
+ CurrentIGI = CurrentIGI + 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+2; */
+ else if (pFalseAlmCnt->Cnt_all > 8000)
+ CurrentIGI = CurrentIGI + 1;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+1; */
+ else if (pFalseAlmCnt->Cnt_all < 500)
+ CurrentIGI = CurrentIGI - 1;/* pDM_DigTable->CurIGValue =pDM_DigTable->PreIGValue-1; */
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): England DIG\n"));
+ }
+ }
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): DIG End Adjust IGI\n"));
+ /* 1 Check initial gain by upper/lower bound */
+ if (CurrentIGI > pDM_DigTable->rx_gain_range_max)
+ CurrentIGI = pDM_DigTable->rx_gain_range_max;
+ if (CurrentIGI < pDM_DigTable->rx_gain_range_min)
+ CurrentIGI = pDM_DigTable->rx_gain_range_min;
+
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
+ ("odm_DIG(): rx_gain_range_max=0x%x, rx_gain_range_min=0x%x\n",
+ pDM_DigTable->rx_gain_range_max, pDM_DigTable->rx_gain_range_min));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): TotalFA=%d\n", pFalseAlmCnt->Cnt_all));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG(): CurIGValue=0x%x\n", CurrentIGI));
+
+ /* 2 High power RSSI threshold */
+
+ ODM_Write_DIG(pDM_Odm, CurrentIGI);/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */
+ pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked;
+ pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN;
+}
+
+/* 3============================================================ */
+/* 3 FASLE ALARM CHECK */
+/* 3============================================================ */
+
+void odm_FalseAlarmCounterStatistics(struct odm_dm_struct *pDM_Odm)
+{
+ struct adapter *adapter = pDM_Odm->Adapter;
+ u32 ret_value;
+ struct false_alarm_stats *FalseAlmCnt = &(pDM_Odm->FalseAlmCnt);
+
+ if (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT))
+ return;
+
+ /* hold ofdm counter */
+ phy_set_bb_reg(adapter, ODM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1); /* hold page C counter */
+ phy_set_bb_reg(adapter, ODM_REG_OFDM_FA_RSTD_11N, BIT(31), 1); /* hold page D counter */
+
+ ret_value = phy_query_bb_reg(adapter, ODM_REG_OFDM_FA_TYPE1_11N, bMaskDWord);
+ FalseAlmCnt->Cnt_Fast_Fsync = (ret_value&0xffff);
+ FalseAlmCnt->Cnt_SB_Search_fail = (ret_value & 0xffff0000)>>16;
+ ret_value = phy_query_bb_reg(adapter, ODM_REG_OFDM_FA_TYPE2_11N, bMaskDWord);
+ FalseAlmCnt->Cnt_OFDM_CCA = (ret_value&0xffff);
+ FalseAlmCnt->Cnt_Parity_Fail = (ret_value & 0xffff0000)>>16;
+ ret_value = phy_query_bb_reg(adapter, ODM_REG_OFDM_FA_TYPE3_11N, bMaskDWord);
+ FalseAlmCnt->Cnt_Rate_Illegal = (ret_value&0xffff);
+ FalseAlmCnt->Cnt_Crc8_fail = (ret_value & 0xffff0000)>>16;
+ ret_value = phy_query_bb_reg(adapter, ODM_REG_OFDM_FA_TYPE4_11N, bMaskDWord);
+ FalseAlmCnt->Cnt_Mcs_fail = (ret_value&0xffff);
+
+ FalseAlmCnt->Cnt_Ofdm_fail = FalseAlmCnt->Cnt_Parity_Fail + FalseAlmCnt->Cnt_Rate_Illegal +
+ FalseAlmCnt->Cnt_Crc8_fail + FalseAlmCnt->Cnt_Mcs_fail +
+ FalseAlmCnt->Cnt_Fast_Fsync + FalseAlmCnt->Cnt_SB_Search_fail;
+
+ ret_value = phy_query_bb_reg(adapter, ODM_REG_SC_CNT_11N, bMaskDWord);
+ FalseAlmCnt->Cnt_BW_LSC = (ret_value&0xffff);
+ FalseAlmCnt->Cnt_BW_USC = (ret_value & 0xffff0000)>>16;
+
+ /* hold cck counter */
+ phy_set_bb_reg(adapter, ODM_REG_CCK_FA_RST_11N, BIT(12), 1);
+ phy_set_bb_reg(adapter, ODM_REG_CCK_FA_RST_11N, BIT(14), 1);
+
+ ret_value = phy_query_bb_reg(adapter, ODM_REG_CCK_FA_LSB_11N, bMaskByte0);
+ FalseAlmCnt->Cnt_Cck_fail = ret_value;
+ ret_value = phy_query_bb_reg(adapter, ODM_REG_CCK_FA_MSB_11N, bMaskByte3);
+ FalseAlmCnt->Cnt_Cck_fail += (ret_value & 0xff)<<8;
+
+ ret_value = phy_query_bb_reg(adapter, ODM_REG_CCK_CCA_CNT_11N, bMaskDWord);
+ FalseAlmCnt->Cnt_CCK_CCA = ((ret_value&0xFF)<<8) | ((ret_value&0xFF00)>>8);
+
+ FalseAlmCnt->Cnt_all = (FalseAlmCnt->Cnt_Fast_Fsync +
+ FalseAlmCnt->Cnt_SB_Search_fail +
+ FalseAlmCnt->Cnt_Parity_Fail +
+ FalseAlmCnt->Cnt_Rate_Illegal +
+ FalseAlmCnt->Cnt_Crc8_fail +
+ FalseAlmCnt->Cnt_Mcs_fail +
+ FalseAlmCnt->Cnt_Cck_fail);
+
+ FalseAlmCnt->Cnt_CCA_all = FalseAlmCnt->Cnt_OFDM_CCA + FalseAlmCnt->Cnt_CCK_CCA;
+
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Enter odm_FalseAlarmCounterStatistics\n"));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD,
+ ("Cnt_Fast_Fsync=%d, Cnt_SB_Search_fail=%d\n",
+ FalseAlmCnt->Cnt_Fast_Fsync, FalseAlmCnt->Cnt_SB_Search_fail));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD,
+ ("Cnt_Parity_Fail=%d, Cnt_Rate_Illegal=%d\n",
+ FalseAlmCnt->Cnt_Parity_Fail, FalseAlmCnt->Cnt_Rate_Illegal));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD,
+ ("Cnt_Crc8_fail=%d, Cnt_Mcs_fail=%d\n",
+ FalseAlmCnt->Cnt_Crc8_fail, FalseAlmCnt->Cnt_Mcs_fail));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Cnt_Cck_fail=%d\n", FalseAlmCnt->Cnt_Cck_fail));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Cnt_Ofdm_fail=%d\n", FalseAlmCnt->Cnt_Ofdm_fail));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Total False Alarm=%d\n", FalseAlmCnt->Cnt_all));
+}
+
+/* 3============================================================ */
+/* 3 CCK Packet Detect Threshold */
+/* 3============================================================ */
+
+void odm_CCKPacketDetectionThresh(struct odm_dm_struct *pDM_Odm)
+{
+ u8 CurCCK_CCAThres;
+ struct false_alarm_stats *FalseAlmCnt = &(pDM_Odm->FalseAlmCnt);
+
+ if (!(pDM_Odm->SupportAbility & (ODM_BB_CCK_PD|ODM_BB_FA_CNT)))
+ return;
+ if (pDM_Odm->ExtLNA)
+ return;
+ if (pDM_Odm->bLinked) {
+ if (pDM_Odm->RSSI_Min > 25) {
+ CurCCK_CCAThres = 0xcd;
+ } else if ((pDM_Odm->RSSI_Min <= 25) && (pDM_Odm->RSSI_Min > 10)) {
+ CurCCK_CCAThres = 0x83;
+ } else {
+ if (FalseAlmCnt->Cnt_Cck_fail > 1000)
+ CurCCK_CCAThres = 0x83;
+ else
+ CurCCK_CCAThres = 0x40;
+ }
+ } else {
+ if (FalseAlmCnt->Cnt_Cck_fail > 1000)
+ CurCCK_CCAThres = 0x83;
+ else
+ CurCCK_CCAThres = 0x40;
+ }
+ ODM_Write_CCK_CCA_Thres(pDM_Odm, CurCCK_CCAThres);
+}
+
+void ODM_Write_CCK_CCA_Thres(struct odm_dm_struct *pDM_Odm, u8 CurCCK_CCAThres)
+{
+ struct rtw_dig *pDM_DigTable = &pDM_Odm->DM_DigTable;
+ struct adapter *adapt = pDM_Odm->Adapter;
+
+ if (pDM_DigTable->CurCCK_CCAThres != CurCCK_CCAThres) /* modify by Guo.Mingzhi 2012-01-03 */
+ usb_write8(adapt, ODM_REG_CCK_CCA_11N, CurCCK_CCAThres);
+ pDM_DigTable->PreCCK_CCAThres = pDM_DigTable->CurCCK_CCAThres;
+ pDM_DigTable->CurCCK_CCAThres = CurCCK_CCAThres;
+}
+
+void ODM_RF_Saving(struct odm_dm_struct *pDM_Odm, u8 bForceInNormal)
+{
+ struct adapter *adapter = pDM_Odm->Adapter;
+ struct rtl_ps *pDM_PSTable = &pDM_Odm->DM_PSTable;
+ u8 Rssi_Up_bound = 30;
+ u8 Rssi_Low_bound = 25;
+
+ if (pDM_Odm->PatchID == 40) { /* RT_CID_819x_FUNAI_TV */
+ Rssi_Up_bound = 50;
+ Rssi_Low_bound = 45;
+ }
+ if (pDM_PSTable->initialize == 0) {
+ pDM_PSTable->Reg874 = (phy_query_bb_reg(adapter, 0x874, bMaskDWord)&0x1CC000)>>14;
+ pDM_PSTable->RegC70 = (phy_query_bb_reg(adapter, 0xc70, bMaskDWord) & BIT(3))>>3;
+ pDM_PSTable->Reg85C = (phy_query_bb_reg(adapter, 0x85c, bMaskDWord)&0xFF000000)>>24;
+ pDM_PSTable->RegA74 = (phy_query_bb_reg(adapter, 0xa74, bMaskDWord)&0xF000)>>12;
+ pDM_PSTable->initialize = 1;
+ }
+
+ if (!bForceInNormal) {
+ if (pDM_Odm->RSSI_Min != 0xFF) {
+ if (pDM_PSTable->PreRFState == RF_Normal) {
+ if (pDM_Odm->RSSI_Min >= Rssi_Up_bound)
+ pDM_PSTable->CurRFState = RF_Save;
+ else
+ pDM_PSTable->CurRFState = RF_Normal;
+ } else {
+ if (pDM_Odm->RSSI_Min <= Rssi_Low_bound)
+ pDM_PSTable->CurRFState = RF_Normal;
+ else
+ pDM_PSTable->CurRFState = RF_Save;
+ }
+ } else {
+ pDM_PSTable->CurRFState = RF_MAX;
+ }
+ } else {
+ pDM_PSTable->CurRFState = RF_Normal;
+ }
+
+ if (pDM_PSTable->PreRFState != pDM_PSTable->CurRFState) {
+ if (pDM_PSTable->CurRFState == RF_Save) {
+ phy_set_bb_reg(adapter, 0x874, 0x1C0000, 0x2); /* Reg874[20:18]=3'b010 */
+ phy_set_bb_reg(adapter, 0xc70, BIT(3), 0); /* RegC70[3]=1'b0 */
+ phy_set_bb_reg(adapter, 0x85c, 0xFF000000, 0x63); /* Reg85C[31:24]=0x63 */
+ phy_set_bb_reg(adapter, 0x874, 0xC000, 0x2); /* Reg874[15:14]=2'b10 */
+ phy_set_bb_reg(adapter, 0xa74, 0xF000, 0x3); /* RegA75[7:4]=0x3 */
+ phy_set_bb_reg(adapter, 0x818, BIT(28), 0x0); /* Reg818[28]=1'b0 */
+ phy_set_bb_reg(adapter, 0x818, BIT(28), 0x1); /* Reg818[28]=1'b1 */
+ } else {
+ phy_set_bb_reg(adapter, 0x874, 0x1CC000, pDM_PSTable->Reg874);
+ phy_set_bb_reg(adapter, 0xc70, BIT(3), pDM_PSTable->RegC70);
+ phy_set_bb_reg(adapter, 0x85c, 0xFF000000, pDM_PSTable->Reg85C);
+ phy_set_bb_reg(adapter, 0xa74, 0xF000, pDM_PSTable->RegA74);
+ phy_set_bb_reg(adapter, 0x818, BIT(28), 0x0);
+ }
+ pDM_PSTable->PreRFState = pDM_PSTable->CurRFState;
+ }
+}
+
+/* 3============================================================ */
+/* 3 RATR MASK */
+/* 3============================================================ */
+/* 3============================================================ */
+/* 3 Rate Adaptive */
+/* 3============================================================ */
+
+void odm_RateAdaptiveMaskInit(struct odm_dm_struct *pDM_Odm)
+{
+ struct odm_rate_adapt *pOdmRA = &pDM_Odm->RateAdaptive;
+
+ pOdmRA->Type = DM_Type_ByDriver;
+ if (pOdmRA->Type == DM_Type_ByDriver)
+ pDM_Odm->bUseRAMask = true;
+ else
+ pDM_Odm->bUseRAMask = false;
+
+ pOdmRA->RATRState = DM_RATR_STA_INIT;
+ pOdmRA->HighRSSIThresh = 50;
+ pOdmRA->LowRSSIThresh = 20;
+}
+
+u32 ODM_Get_Rate_Bitmap(struct odm_dm_struct *pDM_Odm, u32 macid, u32 ra_mask, u8 rssi_level)
+{
+ struct sta_info *pEntry;
+ u32 rate_bitmap = 0x0fffffff;
+ u8 WirelessMode;
+
+ pEntry = pDM_Odm->pODM_StaInfo[macid];
+ if (!IS_STA_VALID(pEntry))
+ return ra_mask;
+
+ WirelessMode = pEntry->wireless_mode;
+
+ switch (WirelessMode) {
+ case ODM_WM_B:
+ if (ra_mask & 0x0000000c) /* 11M or 5.5M enable */
+ rate_bitmap = 0x0000000d;
+ else
+ rate_bitmap = 0x0000000f;
+ break;
+ case (ODM_WM_A|ODM_WM_G):
+ if (rssi_level == DM_RATR_STA_HIGH)
+ rate_bitmap = 0x00000f00;
+ else
+ rate_bitmap = 0x00000ff0;
+ break;
+ case (ODM_WM_B|ODM_WM_G):
+ if (rssi_level == DM_RATR_STA_HIGH)
+ rate_bitmap = 0x00000f00;
+ else if (rssi_level == DM_RATR_STA_MIDDLE)
+ rate_bitmap = 0x00000ff0;
+ else
+ rate_bitmap = 0x00000ff5;
+ break;
+ case (ODM_WM_B|ODM_WM_G|ODM_WM_N24G):
+ case (ODM_WM_A|ODM_WM_B|ODM_WM_G|ODM_WM_N24G):
+ if (rssi_level == DM_RATR_STA_HIGH) {
+ rate_bitmap = 0x000f0000;
+ } else if (rssi_level == DM_RATR_STA_MIDDLE) {
+ rate_bitmap = 0x000ff000;
+ } else {
+ if (*(pDM_Odm->pBandWidth) == ODM_BW40M)
+ rate_bitmap = 0x000ff015;
+ else
+ rate_bitmap = 0x000ff005;
+ }
+ break;
+ default:
+ /* case WIRELESS_11_24N: */
+ /* case WIRELESS_11_5N: */
+ rate_bitmap = 0x0fffffff;
+ break;
+ }
+
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD,
+ (" ==> rssi_level:0x%02x, WirelessMode:0x%02x, rate_bitmap:0x%08x\n",
+ rssi_level, WirelessMode, rate_bitmap));
+
+ return rate_bitmap;
+}
+
+/* Update rate table mask according to rssi */
+void odm_RefreshRateAdaptiveMask(struct odm_dm_struct *pDM_Odm)
+{
+ if (!(pDM_Odm->SupportAbility & ODM_BB_RA_MASK))
+ return;
+ /* */
+ /* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
+ /* at the same time. In the stage2/3, we need to prive universal interface and merge all */
+ /* HW dynamic mechanism. */
+ /* */
+ odm_RefreshRateAdaptiveMaskCE(pDM_Odm);
+}
+
+void odm_RefreshRateAdaptiveMaskCE(struct odm_dm_struct *pDM_Odm)
+{
+ u8 i;
+ struct adapter *pAdapter = pDM_Odm->Adapter;
+
+ if (pAdapter->bDriverStopped) {
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_TRACE, ("<---- odm_RefreshRateAdaptiveMask(): driver is going to unload\n"));
+ return;
+ }
+
+ if (!pDM_Odm->bUseRAMask) {
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("<---- odm_RefreshRateAdaptiveMask(): driver does not control rate adaptive mask\n"));
+ return;
+ }
+
+ for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
+ struct sta_info *pstat = pDM_Odm->pODM_StaInfo[i];
+
+ if (IS_STA_VALID(pstat)) {
+ if (ODM_RAStateCheck(pDM_Odm, pstat->rssi_stat.UndecoratedSmoothedPWDB, false, &pstat->rssi_level)) {
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD,
+ ("RSSI:%d, RSSI_LEVEL:%d\n",
+ pstat->rssi_stat.UndecoratedSmoothedPWDB, pstat->rssi_level));
+ rtw_hal_update_ra_mask(pAdapter, i, pstat->rssi_level);
+ }
+ }
+ }
+}
+
+/* Return Value: bool */
+/* - true: RATRState is changed. */
+bool ODM_RAStateCheck(struct odm_dm_struct *pDM_Odm, s32 RSSI, bool bForceUpdate, u8 *pRATRState)
+{
+ struct odm_rate_adapt *pRA = &pDM_Odm->RateAdaptive;
+ const u8 GoUpGap = 5;
+ u8 HighRSSIThreshForRA = pRA->HighRSSIThresh;
+ u8 LowRSSIThreshForRA = pRA->LowRSSIThresh;
+ u8 RATRState;
+
+ /* Threshold Adjustment: */
+ /* when RSSI state trends to go up one or two levels, make sure RSSI is high enough. */
+ /* Here GoUpGap is added to solve the boundary's level alternation issue. */
+ switch (*pRATRState) {
+ case DM_RATR_STA_INIT:
+ case DM_RATR_STA_HIGH:
+ break;
+ case DM_RATR_STA_MIDDLE:
+ HighRSSIThreshForRA += GoUpGap;
+ break;
+ case DM_RATR_STA_LOW:
+ HighRSSIThreshForRA += GoUpGap;
+ LowRSSIThreshForRA += GoUpGap;
+ break;
+ default:
+ ODM_RT_ASSERT(pDM_Odm, false, ("wrong rssi level setting %d !", *pRATRState));
+ break;
+ }
+
+ /* Decide RATRState by RSSI. */
+ if (RSSI > HighRSSIThreshForRA)
+ RATRState = DM_RATR_STA_HIGH;
+ else if (RSSI > LowRSSIThreshForRA)
+ RATRState = DM_RATR_STA_MIDDLE;
+ else
+ RATRState = DM_RATR_STA_LOW;
+
+ if (*pRATRState != RATRState || bForceUpdate) {
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, ("RSSI Level %d -> %d\n", *pRATRState, RATRState));
+ *pRATRState = RATRState;
+ return true;
+ }
+ return false;
+}
+
+/* 3============================================================ */
+/* 3 Dynamic Tx Power */
+/* 3============================================================ */
+
+void odm_DynamicTxPowerInit(struct odm_dm_struct *pDM_Odm)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ struct dm_priv *pdmpriv = &Adapter->HalData->dmpriv;
+
+ pdmpriv->bDynamicTxPowerEnable = false;
+ pdmpriv->LastDTPLvl = TxHighPwrLevel_Normal;
+ pdmpriv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal;
+}
+
+/* 3============================================================ */
+/* 3 RSSI Monitor */
+/* 3============================================================ */
+
+void odm_RSSIMonitorCheck(struct odm_dm_struct *pDM_Odm)
+{
+ if (!(pDM_Odm->SupportAbility & ODM_BB_RSSI_MONITOR))
+ return;
+
+ /* */
+ /* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
+ /* at the same time. In the stage2/3, we need to prive universal interface and merge all */
+ /* HW dynamic mechanism. */
+ /* */
+ odm_RSSIMonitorCheckCE(pDM_Odm);
+} /* odm_RSSIMonitorCheck */
+
+static void FindMinimumRSSI(struct adapter *pAdapter)
+{
+ struct dm_priv *pdmpriv = &pAdapter->HalData->dmpriv;
+
+ /* 1 1.Unconditionally set RSSI */
+ pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB;
+}
+
+void odm_RSSIMonitorCheckCE(struct odm_dm_struct *pDM_Odm)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ struct dm_priv *pdmpriv = &Adapter->HalData->dmpriv;
+ int i;
+ int tmpEntryMaxPWDB = 0, tmpEntryMinPWDB = 0xff;
+ u8 sta_cnt = 0;
+ u32 PWDB_rssi[NUM_STA] = {0};/* 0~15]:MACID, [16~31]:PWDB_rssi */
+ struct sta_info *psta;
+ u8 bcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ if (!check_fwstate(&Adapter->mlmepriv, _FW_LINKED))
+ return;
+
+ for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
+ psta = pDM_Odm->pODM_StaInfo[i];
+ if (IS_STA_VALID(psta) &&
+ (psta->state & WIFI_ASOC_STATE) &&
+ memcmp(psta->hwaddr, bcast_addr, ETH_ALEN) &&
+ memcmp(psta->hwaddr, myid(&Adapter->eeprompriv), ETH_ALEN)) {
+ if (psta->rssi_stat.UndecoratedSmoothedPWDB < tmpEntryMinPWDB)
+ tmpEntryMinPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB;
+
+ if (psta->rssi_stat.UndecoratedSmoothedPWDB > tmpEntryMaxPWDB)
+ tmpEntryMaxPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB;
+ if (psta->rssi_stat.UndecoratedSmoothedPWDB != (-1))
+ PWDB_rssi[sta_cnt++] = (psta->mac_id | (psta->rssi_stat.UndecoratedSmoothedPWDB<<16));
+ }
+ }
+
+ for (i = 0; i < sta_cnt; i++) {
+ if (PWDB_rssi[i] != 0) {
+ ODM_RA_SetRSSI_8188E(&Adapter->HalData->odmpriv,
+ PWDB_rssi[i] & 0xFF,
+ (PWDB_rssi[i] >> 16) & 0xFF);
+ }
+ }
+
+ if (tmpEntryMaxPWDB != 0) /* If associated entry is found */
+ pdmpriv->EntryMaxUndecoratedSmoothedPWDB = tmpEntryMaxPWDB;
+ else
+ pdmpriv->EntryMaxUndecoratedSmoothedPWDB = 0;
+
+ if (tmpEntryMinPWDB != 0xff) /* If associated entry is found */
+ pdmpriv->EntryMinUndecoratedSmoothedPWDB = tmpEntryMinPWDB;
+ else
+ pdmpriv->EntryMinUndecoratedSmoothedPWDB = 0;
+
+ FindMinimumRSSI(Adapter);
+ Adapter->HalData->odmpriv.RSSI_Min = pdmpriv->MinUndecoratedPWDBForDM;
+}
+
+/* 3============================================================ */
+/* 3 Tx Power Tracking */
+/* 3============================================================ */
+
+void odm_TXPowerTrackingInit(struct odm_dm_struct *pDM_Odm)
+{
+ pDM_Odm->RFCalibrateInfo.bTXPowerTracking = true;
+ pDM_Odm->RFCalibrateInfo.TXPowercount = 0;
+ if (*(pDM_Odm->mp_mode) != 1)
+ pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = true;
+ MSG_88E("pDM_Odm TxPowerTrackControl = %d\n", pDM_Odm->RFCalibrateInfo.TxPowerTrackControl);
+
+ pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = true;
+}
+
+void ODM_TXPowerTrackingCheck(struct odm_dm_struct *pDM_Odm)
+{
+ /* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
+ /* at the same time. In the stage2/3, we need to prive universal interface and merge all */
+ /* HW dynamic mechanism. */
+ struct adapter *Adapter = pDM_Odm->Adapter;
+
+ if (!(pDM_Odm->SupportAbility & ODM_RF_TX_PWR_TRACK))
+ return;
+
+ if (!pDM_Odm->RFCalibrateInfo.TM_Trigger) { /* at least delay 1 sec */
+ phy_set_rf_reg(Adapter, RF_PATH_A, RF_T_METER_88E, BIT(17) | BIT(16), 0x03);
+
+ pDM_Odm->RFCalibrateInfo.TM_Trigger = 1;
+ return;
+ } else {
+ rtl88eu_dm_txpower_tracking_callback_thermalmeter(Adapter);
+ pDM_Odm->RFCalibrateInfo.TM_Trigger = 0;
+ }
+}
+
+/* 3============================================================ */
+/* 3 SW Antenna Diversity */
+/* 3============================================================ */
+
+void odm_InitHybridAntDiv(struct odm_dm_struct *pDM_Odm)
+{
+ if (!(pDM_Odm->SupportAbility & ODM_BB_ANT_DIV)) {
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Return: Not Support HW AntDiv\n"));
+ return;
+ }
+
+ rtl88eu_dm_antenna_div_init(pDM_Odm);
+}
+
+void odm_HwAntDiv(struct odm_dm_struct *pDM_Odm)
+{
+ if (!(pDM_Odm->SupportAbility & ODM_BB_ANT_DIV)) {
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Return: Not Support HW AntDiv\n"));
+ return;
+ }
+
+ rtl88eu_dm_antenna_diversity(pDM_Odm);
+}
+
+/* EDCA Turbo */
+void ODM_EdcaTurboInit(struct odm_dm_struct *pDM_Odm)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+
+ pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false;
+ pDM_Odm->DM_EDCA_Table.bIsCurRDLState = false;
+ Adapter->recvpriv.bIsAnyNonBEPkts = false;
+
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Original VO PARAM: 0x%x\n", usb_read32(Adapter, ODM_EDCA_VO_PARAM)));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Original VI PARAM: 0x%x\n", usb_read32(Adapter, ODM_EDCA_VI_PARAM)));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Original BE PARAM: 0x%x\n", usb_read32(Adapter, ODM_EDCA_BE_PARAM)));
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Original BK PARAM: 0x%x\n", usb_read32(Adapter, ODM_EDCA_BK_PARAM)));
+} /* ODM_InitEdcaTurbo */
+
+void odm_EdcaTurboCheck(struct odm_dm_struct *pDM_Odm)
+{
+ /* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
+ /* at the same time. In the stage2/3, we need to prive universal interface and merge all */
+ /* HW dynamic mechanism. */
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("odm_EdcaTurboCheck========================>\n"));
+
+ if (!(pDM_Odm->SupportAbility & ODM_MAC_EDCA_TURBO))
+ return;
+
+ odm_EdcaTurboCheckCE(pDM_Odm);
+ ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("<========================odm_EdcaTurboCheck\n"));
+} /* odm_CheckEdcaTurbo */
+
+void odm_EdcaTurboCheckCE(struct odm_dm_struct *pDM_Odm)
+{
+ struct adapter *Adapter = pDM_Odm->Adapter;
+ u32 trafficIndex;
+ u32 edca_param;
+ u64 cur_tx_bytes = 0;
+ u64 cur_rx_bytes = 0;
+ u8 bbtchange = false;
+ struct xmit_priv *pxmitpriv = &(Adapter->xmitpriv);
+ struct recv_priv *precvpriv = &(Adapter->recvpriv);
+ struct registry_priv *pregpriv = &Adapter->registrypriv;
+ struct mlme_ext_priv *pmlmeext = &(Adapter->mlmeextpriv);
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+
+ if (pregpriv->wifi_spec == 1) /* (pmlmeinfo->HT_enable == 0)) */
+ goto dm_CheckEdcaTurbo_EXIT;
+
+ if (pmlmeinfo->assoc_AP_vendor >= HT_IOT_PEER_MAX)
+ goto dm_CheckEdcaTurbo_EXIT;
+
+ /* Check if the status needs to be changed. */
+ if ((bbtchange) || (!precvpriv->bIsAnyNonBEPkts)) {
+ cur_tx_bytes = pxmitpriv->tx_bytes - pxmitpriv->last_tx_bytes;
+ cur_rx_bytes = precvpriv->rx_bytes - precvpriv->last_rx_bytes;
+
+ /* traffic, TX or RX */
+ if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_RALINK) ||
+ (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_ATHEROS)) {
+ if (cur_tx_bytes > (cur_rx_bytes << 2)) {
+ /* Uplink TP is present. */
+ trafficIndex = UP_LINK;
+ } else {
+ /* Balance TP is present. */
+ trafficIndex = DOWN_LINK;
+ }
+ } else {
+ if (cur_rx_bytes > (cur_tx_bytes << 2)) {
+ /* Downlink TP is present. */
+ trafficIndex = DOWN_LINK;
+ } else {
+ /* Balance TP is present. */
+ trafficIndex = UP_LINK;
+ }
+ }
+
+ if ((pDM_Odm->DM_EDCA_Table.prv_traffic_idx != trafficIndex) || (!pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA)) {
+ if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_CISCO) && (pmlmeext->cur_wireless_mode & WIRELESS_11_24N))
+ edca_param = EDCAParam[pmlmeinfo->assoc_AP_vendor][trafficIndex];
+ else
+ edca_param = EDCAParam[HT_IOT_PEER_UNKNOWN][trafficIndex];
+
+ usb_write32(Adapter, REG_EDCA_BE_PARAM, edca_param);
+
+ pDM_Odm->DM_EDCA_Table.prv_traffic_idx = trafficIndex;
+ }
+
+ pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = true;
+ } else {
+ /* Turn Off EDCA turbo here. */
+ /* Restore original EDCA according to the declaration of AP. */
+ if (pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA) {
+ usb_write32(Adapter, REG_EDCA_BE_PARAM,
+ Adapter->HalData->AcParam_BE);
+ pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false;
+ }
+ }
+
+dm_CheckEdcaTurbo_EXIT:
+ /* Set variables for next time. */
+ precvpriv->bIsAnyNonBEPkts = false;
+ pxmitpriv->last_tx_bytes = pxmitpriv->tx_bytes;
+ precvpriv->last_rx_bytes = precvpriv->rx_bytes;
+}
diff --git a/drivers/staging/rtl8188eu/hal/odm_hwconfig.c b/drivers/staging/rtl8188eu/hal/odm_hwconfig.c
new file mode 100644
index 0000000..d5a9ac5
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/odm_hwconfig.c
@@ -0,0 +1,400 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+/* include files */
+
+#include "odm_precomp.h"
+
+#define READ_AND_CONFIG READ_AND_CONFIG_MP
+
+#define READ_AND_CONFIG_MP(ic, txt) (ODM_ReadAndConfig##txt##ic(dm_odm))
+#define READ_AND_CONFIG_TC(ic, txt) (ODM_ReadAndConfig_TC##txt##ic(dm_odm))
+
+static u8 odm_query_rxpwrpercentage(s8 antpower)
+{
+ if ((antpower <= -100) || (antpower >= 20))
+ return 0;
+ else if (antpower >= 0)
+ return 100;
+ else
+ return 100 + antpower;
+}
+
+/* 2012/01/12 MH MOve some signal strength smooth method to MP HAL layer. */
+/* IF other SW team do not support the feature, remove this section.?? */
+static s32 odm_signal_scale_mapping(struct odm_dm_struct *dm_odm, s32 currsig)
+{
+ s32 retsig = 0;
+
+ if (currsig >= 51 && currsig <= 100)
+ retsig = 100;
+ else if (currsig >= 41 && currsig <= 50)
+ retsig = 80 + ((currsig - 40) * 2);
+ else if (currsig >= 31 && currsig <= 40)
+ retsig = 66 + (currsig - 30);
+ else if (currsig >= 21 && currsig <= 30)
+ retsig = 54 + (currsig - 20);
+ else if (currsig >= 10 && currsig <= 20)
+ retsig = 42 + (((currsig - 10) * 2) / 3);
+ else if (currsig >= 5 && currsig <= 9)
+ retsig = 22 + (((currsig - 5) * 3) / 2);
+ else if (currsig >= 1 && currsig <= 4)
+ retsig = 6 + (((currsig - 1) * 3) / 2);
+ else
+ retsig = currsig;
+
+ return retsig;
+}
+
+static u8 odm_evm_db_to_percentage(s8 value)
+{
+ /* -33dB~0dB to 0%~99% */
+ s8 ret_val = clamp(-value, 0, 33) * 3;
+
+ if (ret_val == 99)
+ ret_val = 100;
+
+ return ret_val;
+}
+
+static void odm_RxPhyStatus92CSeries_Parsing(struct odm_dm_struct *dm_odm,
+ struct odm_phy_status_info *pPhyInfo,
+ u8 *pPhyStatus,
+ struct odm_per_pkt_info *pPktinfo)
+{
+ struct sw_ant_switch *pDM_SWAT_Table = &dm_odm->DM_SWAT_Table;
+ u8 i, max_spatial_stream;
+ s8 rx_pwr[4], rx_pwr_all = 0;
+ u8 EVM, PWDB_ALL = 0, PWDB_ALL_BT;
+ u8 RSSI, total_rssi = 0;
+ bool is_cck_rate;
+ u8 rf_rx_num = 0;
+ u8 cck_highpwr = 0;
+ u8 LNA_idx, VGA_idx;
+
+ struct phy_status_rpt *pPhyStaRpt = (struct phy_status_rpt *)pPhyStatus;
+
+ is_cck_rate = pPktinfo->Rate >= DESC92C_RATE1M &&
+ pPktinfo->Rate <= DESC92C_RATE11M;
+
+ pPhyInfo->RxMIMOSignalQuality[RF_PATH_A] = -1;
+ pPhyInfo->RxMIMOSignalQuality[RF_PATH_B] = -1;
+
+ if (is_cck_rate) {
+ u8 cck_agc_rpt;
+
+ dm_odm->PhyDbgInfo.NumQryPhyStatusCCK++;
+ /* (1)Hardware does not provide RSSI for CCK */
+ /* (2)PWDB, Average PWDB calculated by hardware (for rate adaptive) */
+
+ cck_highpwr = dm_odm->bCckHighPower;
+
+ cck_agc_rpt = pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a;
+
+ /* 2011.11.28 LukeLee: 88E use different LNA & VGA gain table */
+ /* The RSSI formula should be modified according to the gain table */
+ /* In 88E, cck_highpwr is always set to 1 */
+ LNA_idx = (cck_agc_rpt & 0xE0) >> 5;
+ VGA_idx = cck_agc_rpt & 0x1F;
+ switch (LNA_idx) {
+ case 7:
+ if (VGA_idx <= 27)
+ rx_pwr_all = -100 + 2 * (27-VGA_idx); /* VGA_idx = 27~2 */
+ else
+ rx_pwr_all = -100;
+ break;
+ case 6:
+ rx_pwr_all = -48 + 2 * (2-VGA_idx); /* VGA_idx = 2~0 */
+ break;
+ case 5:
+ rx_pwr_all = -42 + 2 * (7-VGA_idx); /* VGA_idx = 7~5 */
+ break;
+ case 4:
+ rx_pwr_all = -36 + 2 * (7-VGA_idx); /* VGA_idx = 7~4 */
+ break;
+ case 3:
+ rx_pwr_all = -24 + 2 * (7-VGA_idx); /* VGA_idx = 7~0 */
+ break;
+ case 2:
+ if (cck_highpwr)
+ rx_pwr_all = -12 + 2 * (5-VGA_idx); /* VGA_idx = 5~0 */
+ else
+ rx_pwr_all = -6 + 2 * (5-VGA_idx);
+ break;
+ case 1:
+ rx_pwr_all = 8-2 * VGA_idx;
+ break;
+ case 0:
+ rx_pwr_all = 14-2 * VGA_idx;
+ break;
+ default:
+ break;
+ }
+ rx_pwr_all += 6;
+ PWDB_ALL = odm_query_rxpwrpercentage(rx_pwr_all);
+ if (!cck_highpwr) {
+ if (PWDB_ALL >= 80)
+ PWDB_ALL = ((PWDB_ALL-80)<<1) + ((PWDB_ALL-80)>>1) + 80;
+ else if ((PWDB_ALL <= 78) && (PWDB_ALL >= 20))
+ PWDB_ALL += 3;
+ if (PWDB_ALL > 100)
+ PWDB_ALL = 100;
+ }
+
+ pPhyInfo->RxPWDBAll = PWDB_ALL;
+ pPhyInfo->BTRxRSSIPercentage = PWDB_ALL;
+ pPhyInfo->RecvSignalPower = rx_pwr_all;
+ /* (3) Get Signal Quality (EVM) */
+ if (pPktinfo->bPacketMatchBSSID) {
+ u8 SQ, SQ_rpt;
+
+ if (pPhyInfo->RxPWDBAll > 40 && !dm_odm->bInHctTest) {
+ SQ = 100;
+ } else {
+ SQ_rpt = pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all;
+
+ if (SQ_rpt > 64)
+ SQ = 0;
+ else if (SQ_rpt < 20)
+ SQ = 100;
+ else
+ SQ = ((64-SQ_rpt) * 100) / 44;
+ }
+ pPhyInfo->SignalQuality = SQ;
+ pPhyInfo->RxMIMOSignalQuality[RF_PATH_A] = SQ;
+ pPhyInfo->RxMIMOSignalQuality[RF_PATH_B] = -1;
+ }
+ } else { /* is OFDM rate */
+ dm_odm->PhyDbgInfo.NumQryPhyStatusOFDM++;
+
+ /* (1)Get RSSI for HT rate */
+
+ for (i = RF_PATH_A; i < RF_PATH_MAX; i++) {
+ /* 2008/01/30 MH we will judge RF RX path now. */
+ if (dm_odm->RFPathRxEnable & BIT(i))
+ rf_rx_num++;
+
+ rx_pwr[i] = ((pPhyStaRpt->path_agc[i].gain & 0x3F) * 2) - 110;
+
+ pPhyInfo->RxPwr[i] = rx_pwr[i];
+
+ /* Translate DBM to percentage. */
+ RSSI = odm_query_rxpwrpercentage(rx_pwr[i]);
+ total_rssi += RSSI;
+
+ /* Modification for ext-LNA board */
+ if (dm_odm->BoardType == ODM_BOARD_HIGHPWR) {
+ if ((pPhyStaRpt->path_agc[i].trsw) == 1)
+ RSSI = (RSSI > 94) ? 100 : (RSSI + 6);
+ else
+ RSSI = (RSSI <= 16) ? (RSSI >> 3) : (RSSI - 16);
+
+ if ((RSSI <= 34) && (RSSI >= 4))
+ RSSI -= 4;
+ }
+
+ pPhyInfo->RxMIMOSignalStrength[i] = (u8)RSSI;
+
+ /* Get Rx snr value in DB */
+ pPhyInfo->RxSNR[i] = (s32)(pPhyStaRpt->path_rxsnr[i]/2);
+ dm_odm->PhyDbgInfo.RxSNRdB[i] = (s32)(pPhyStaRpt->path_rxsnr[i]/2);
+ }
+ /* (2)PWDB, Average PWDB calculated by hardware (for rate adaptive) */
+ rx_pwr_all = (((pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all) >> 1) & 0x7f) - 110;
+
+ PWDB_ALL = odm_query_rxpwrpercentage(rx_pwr_all);
+ PWDB_ALL_BT = PWDB_ALL;
+
+ pPhyInfo->RxPWDBAll = PWDB_ALL;
+ pPhyInfo->BTRxRSSIPercentage = PWDB_ALL_BT;
+ pPhyInfo->RxPower = rx_pwr_all;
+ pPhyInfo->RecvSignalPower = rx_pwr_all;
+
+ /* (3)EVM of HT rate */
+ if (pPktinfo->Rate >= DESC92C_RATEMCS8 && pPktinfo->Rate <= DESC92C_RATEMCS15)
+ max_spatial_stream = 2; /* both spatial stream make sense */
+ else
+ max_spatial_stream = 1; /* only spatial stream 1 makes sense */
+
+ for (i = 0; i < max_spatial_stream; i++) {
+ /* Do not use shift operation like "rx_evmX >>= 1" because the compilor of free build environment */
+ /* fill most significant bit to "zero" when doing shifting operation which may change a negative */
+ /* value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore. */
+ EVM = odm_evm_db_to_percentage((pPhyStaRpt->stream_rxevm[i])); /* dbm */
+
+ if (pPktinfo->bPacketMatchBSSID) {
+ if (i == RF_PATH_A) /* Fill value in RFD, Get the first spatial stream only */
+ pPhyInfo->SignalQuality = (u8)(EVM & 0xff);
+ pPhyInfo->RxMIMOSignalQuality[i] = (u8)(EVM & 0xff);
+ }
+ }
+ }
+ /* UI BSS List signal strength(in percentage), make it good looking, from 0~100. */
+ /* It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp(). */
+ if (is_cck_rate) {
+ pPhyInfo->SignalStrength = (u8)(odm_signal_scale_mapping(dm_odm, PWDB_ALL));/* PWDB_ALL; */
+ } else {
+ if (rf_rx_num != 0)
+ pPhyInfo->SignalStrength = (u8)(odm_signal_scale_mapping(dm_odm, total_rssi /= rf_rx_num));
+ }
+
+ /* For 92C/92D HW (Hybrid) Antenna Diversity */
+ pDM_SWAT_Table->antsel = pPhyStaRpt->ant_sel;
+ /* For 88E HW Antenna Diversity */
+ dm_odm->DM_FatTable.antsel_rx_keep_0 = pPhyStaRpt->ant_sel;
+ dm_odm->DM_FatTable.antsel_rx_keep_1 = pPhyStaRpt->ant_sel_b;
+ dm_odm->DM_FatTable.antsel_rx_keep_2 = pPhyStaRpt->antsel_rx_keep_2;
+}
+
+static void odm_Process_RSSIForDM(struct odm_dm_struct *dm_odm,
+ struct odm_phy_status_info *pPhyInfo,
+ struct odm_per_pkt_info *pPktinfo)
+{
+ s32 UndecoratedSmoothedPWDB, UndecoratedSmoothedCCK;
+ s32 UndecoratedSmoothedOFDM, RSSI_Ave;
+ bool is_cck_rate;
+ u8 RSSI_max, RSSI_min, i;
+ u32 OFDM_pkt = 0;
+ u32 Weighting = 0;
+ struct sta_info *pEntry;
+ u8 antsel_tr_mux;
+ struct fast_ant_train *pDM_FatTable = &dm_odm->DM_FatTable;
+
+ if (pPktinfo->StationID == 0xFF)
+ return;
+ pEntry = dm_odm->pODM_StaInfo[pPktinfo->StationID];
+ if (!IS_STA_VALID(pEntry))
+ return;
+ if ((!pPktinfo->bPacketMatchBSSID))
+ return;
+
+ is_cck_rate = pPktinfo->Rate >= DESC92C_RATE1M &&
+ pPktinfo->Rate <= DESC92C_RATE11M;
+
+ /* Smart Antenna Debug Message------------------ */
+
+ if (dm_odm->AntDivType == CG_TRX_SMART_ANTDIV) {
+ if (pDM_FatTable->FAT_State == FAT_TRAINING_STATE) {
+ if (pPktinfo->bPacketToSelf) {
+ antsel_tr_mux = (pDM_FatTable->antsel_rx_keep_2<<2) |
+ (pDM_FatTable->antsel_rx_keep_1<<1) |
+ pDM_FatTable->antsel_rx_keep_0;
+ pDM_FatTable->antSumRSSI[antsel_tr_mux] += pPhyInfo->RxPWDBAll;
+ pDM_FatTable->antRSSIcnt[antsel_tr_mux]++;
+ }
+ }
+ } else if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) || (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV)) {
+ if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon) {
+ antsel_tr_mux = (pDM_FatTable->antsel_rx_keep_2<<2) |
+ (pDM_FatTable->antsel_rx_keep_1<<1) | pDM_FatTable->antsel_rx_keep_0;
+ rtl88eu_dm_ant_sel_statistics(dm_odm, antsel_tr_mux, pPktinfo->StationID, pPhyInfo->RxPWDBAll);
+ }
+ }
+ /* Smart Antenna Debug Message------------------ */
+
+ UndecoratedSmoothedCCK = pEntry->rssi_stat.UndecoratedSmoothedCCK;
+ UndecoratedSmoothedOFDM = pEntry->rssi_stat.UndecoratedSmoothedOFDM;
+ UndecoratedSmoothedPWDB = pEntry->rssi_stat.UndecoratedSmoothedPWDB;
+
+ if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon) {
+ if (!is_cck_rate) { /* ofdm rate */
+ if (pPhyInfo->RxMIMOSignalStrength[RF_PATH_B] == 0) {
+ RSSI_Ave = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A];
+ } else {
+ if (pPhyInfo->RxMIMOSignalStrength[RF_PATH_A] > pPhyInfo->RxMIMOSignalStrength[RF_PATH_B]) {
+ RSSI_max = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A];
+ RSSI_min = pPhyInfo->RxMIMOSignalStrength[RF_PATH_B];
+ } else {
+ RSSI_max = pPhyInfo->RxMIMOSignalStrength[RF_PATH_B];
+ RSSI_min = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A];
+ }
+ if ((RSSI_max - RSSI_min) < 3)
+ RSSI_Ave = RSSI_max;
+ else if ((RSSI_max - RSSI_min) < 6)
+ RSSI_Ave = RSSI_max - 1;
+ else if ((RSSI_max - RSSI_min) < 10)
+ RSSI_Ave = RSSI_max - 2;
+ else
+ RSSI_Ave = RSSI_max - 3;
+ }
+
+ /* 1 Process OFDM RSSI */
+ if (UndecoratedSmoothedOFDM <= 0) { /* initialize */
+ UndecoratedSmoothedOFDM = pPhyInfo->RxPWDBAll;
+ } else {
+ if (pPhyInfo->RxPWDBAll > (u32)UndecoratedSmoothedOFDM) {
+ UndecoratedSmoothedOFDM =
+ (((UndecoratedSmoothedOFDM) * (Rx_Smooth_Factor-1)) +
+ (RSSI_Ave)) / (Rx_Smooth_Factor);
+ UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM + 1;
+ } else {
+ UndecoratedSmoothedOFDM =
+ (((UndecoratedSmoothedOFDM) * (Rx_Smooth_Factor-1)) +
+ (RSSI_Ave)) / (Rx_Smooth_Factor);
+ }
+ }
+
+ pEntry->rssi_stat.PacketMap = (pEntry->rssi_stat.PacketMap<<1) | BIT(0);
+
+ } else {
+ RSSI_Ave = pPhyInfo->RxPWDBAll;
+
+ /* 1 Process CCK RSSI */
+ if (UndecoratedSmoothedCCK <= 0) { /* initialize */
+ UndecoratedSmoothedCCK = pPhyInfo->RxPWDBAll;
+ } else {
+ if (pPhyInfo->RxPWDBAll > (u32)UndecoratedSmoothedCCK) {
+ UndecoratedSmoothedCCK =
+ ((UndecoratedSmoothedCCK * (Rx_Smooth_Factor-1)) +
+ pPhyInfo->RxPWDBAll) / Rx_Smooth_Factor;
+ UndecoratedSmoothedCCK = UndecoratedSmoothedCCK + 1;
+ } else {
+ UndecoratedSmoothedCCK =
+ ((UndecoratedSmoothedCCK * (Rx_Smooth_Factor-1)) +
+ pPhyInfo->RxPWDBAll) / Rx_Smooth_Factor;
+ }
+ }
+ pEntry->rssi_stat.PacketMap = pEntry->rssi_stat.PacketMap<<1;
+ }
+ /* 2011.07.28 LukeLee: modified to prevent unstable CCK RSSI */
+ if (pEntry->rssi_stat.ValidBit >= 64)
+ pEntry->rssi_stat.ValidBit = 64;
+ else
+ pEntry->rssi_stat.ValidBit++;
+
+ for (i = 0; i < pEntry->rssi_stat.ValidBit; i++)
+ OFDM_pkt += (u8)(pEntry->rssi_stat.PacketMap>>i) & BIT(0);
+
+ if (pEntry->rssi_stat.ValidBit == 64) {
+ Weighting = min_t(u32, OFDM_pkt << 4, 64);
+ UndecoratedSmoothedPWDB = (Weighting * UndecoratedSmoothedOFDM + (64-Weighting) * UndecoratedSmoothedCCK)>>6;
+ } else {
+ if (pEntry->rssi_stat.ValidBit != 0)
+ UndecoratedSmoothedPWDB = (OFDM_pkt * UndecoratedSmoothedOFDM +
+ (pEntry->rssi_stat.ValidBit-OFDM_pkt) *
+ UndecoratedSmoothedCCK)/pEntry->rssi_stat.ValidBit;
+ else
+ UndecoratedSmoothedPWDB = 0;
+ }
+ pEntry->rssi_stat.UndecoratedSmoothedCCK = UndecoratedSmoothedCCK;
+ pEntry->rssi_stat.UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM;
+ pEntry->rssi_stat.UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB;
+ }
+}
+
+/* Endianness before calling this API */
+void ODM_PhyStatusQuery(struct odm_dm_struct *dm_odm,
+ struct odm_phy_status_info *pPhyInfo,
+ u8 *pPhyStatus, struct odm_per_pkt_info *pPktinfo)
+{
+ odm_RxPhyStatus92CSeries_Parsing(dm_odm, pPhyInfo, pPhyStatus,
+ pPktinfo);
+ if (dm_odm->RSSI_test)
+ ;/* Select the packets to do RSSI checking for antenna switching. */
+ else
+ odm_Process_RSSIForDM(dm_odm, pPhyInfo, pPktinfo);
+}
diff --git a/drivers/staging/rtl8188eu/hal/odm_rtl8188e.c b/drivers/staging/rtl8188eu/hal/odm_rtl8188e.c
new file mode 100644
index 0000000..251bd8a
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/odm_rtl8188e.c
@@ -0,0 +1,337 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include "odm_precomp.h"
+#include "phy.h"
+
+static void dm_rx_hw_antena_div_init(struct odm_dm_struct *dm_odm)
+{
+ struct adapter *adapter = dm_odm->Adapter;
+ u32 value32;
+
+ if (*dm_odm->mp_mode == 1) {
+ dm_odm->AntDivType = CGCS_RX_SW_ANTDIV;
+ phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0);
+ phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1);
+ return;
+ }
+
+ /* MAC Setting */
+ value32 = phy_query_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord);
+ phy_set_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord,
+ value32 | (BIT(23) | BIT(25)));
+ /* Pin Settings */
+ phy_set_bb_reg(adapter, ODM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
+ phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
+ phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(22), 1);
+ phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1);
+ /* OFDM Settings */
+ phy_set_bb_reg(adapter, ODM_REG_ANTDIV_PARA1_11N, bMaskDWord,
+ 0x000000a0);
+ /* CCK Settings */
+ phy_set_bb_reg(adapter, ODM_REG_BB_PWR_SAV4_11N, BIT(7), 1);
+ phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1);
+ rtl88eu_dm_update_rx_idle_ant(dm_odm, MAIN_ANT);
+ phy_set_bb_reg(adapter, ODM_REG_ANT_MAPPING1_11N, 0xFFFF, 0x0201);
+}
+
+static void dm_trx_hw_antenna_div_init(struct odm_dm_struct *dm_odm)
+{
+ struct adapter *adapter = dm_odm->Adapter;
+ u32 value32;
+
+ if (*dm_odm->mp_mode == 1) {
+ dm_odm->AntDivType = CGCS_RX_SW_ANTDIV;
+ phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0);
+ phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
+ BIT(5) | BIT(4) | BIT(3), 0);
+ return;
+ }
+
+ /* MAC Setting */
+ value32 = phy_query_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord);
+ phy_set_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord,
+ value32 | (BIT(23) | BIT(25)));
+ /* Pin Settings */
+ phy_set_bb_reg(adapter, ODM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
+ phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
+ phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(22), 0);
+ phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1);
+ /* OFDM Settings */
+ phy_set_bb_reg(adapter, ODM_REG_ANTDIV_PARA1_11N, bMaskDWord,
+ 0x000000a0);
+ /* CCK Settings */
+ phy_set_bb_reg(adapter, ODM_REG_BB_PWR_SAV4_11N, BIT(7), 1);
+ phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1);
+ /* Tx Settings */
+ phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N, BIT(21), 0);
+ rtl88eu_dm_update_rx_idle_ant(dm_odm, MAIN_ANT);
+
+ /* antenna mapping table */
+ if (!dm_odm->bIsMPChip) { /* testchip */
+ phy_set_bb_reg(adapter, ODM_REG_RX_DEFAULT_A_11N,
+ BIT(10) | BIT(9) | BIT(8), 1);
+ phy_set_bb_reg(adapter, ODM_REG_RX_DEFAULT_A_11N,
+ BIT(13) | BIT(12) | BIT(11), 2);
+ } else { /* MPchip */
+ phy_set_bb_reg(adapter, ODM_REG_ANT_MAPPING1_11N, bMaskDWord,
+ 0x0201);
+ }
+}
+
+static void dm_fast_training_init(struct odm_dm_struct *dm_odm)
+{
+ struct adapter *adapter = dm_odm->Adapter;
+ u32 value32, i;
+ struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
+
+ if (*dm_odm->mp_mode == 1)
+ return;
+
+ for (i = 0; i < 6; i++) {
+ dm_fat_tbl->Bssid[i] = 0;
+ dm_fat_tbl->antSumRSSI[i] = 0;
+ dm_fat_tbl->antRSSIcnt[i] = 0;
+ dm_fat_tbl->antAveRSSI[i] = 0;
+ }
+ dm_fat_tbl->TrainIdx = 0;
+ dm_fat_tbl->FAT_State = FAT_NORMAL_STATE;
+
+ /* MAC Setting */
+ value32 = phy_query_bb_reg(adapter, 0x4c, bMaskDWord);
+ phy_set_bb_reg(adapter, 0x4c, bMaskDWord,
+ value32 | (BIT(23) | BIT(25)));
+ value32 = phy_query_bb_reg(adapter, 0x7B4, bMaskDWord);
+ phy_set_bb_reg(adapter, 0x7b4, bMaskDWord,
+ value32 | (BIT(16) | BIT(17)));
+
+ /* Match MAC ADDR */
+ phy_set_bb_reg(adapter, 0x7b4, 0xFFFF, 0);
+ phy_set_bb_reg(adapter, 0x7b0, bMaskDWord, 0);
+
+ phy_set_bb_reg(adapter, 0x870, BIT(9) | BIT(8), 0);
+ phy_set_bb_reg(adapter, 0x864, BIT(10), 0);
+ phy_set_bb_reg(adapter, 0xb2c, BIT(22), 0);
+ phy_set_bb_reg(adapter, 0xb2c, BIT(31), 1);
+ phy_set_bb_reg(adapter, 0xca4, bMaskDWord, 0x000000a0);
+
+ /* antenna mapping table */
+ if (!dm_odm->bIsMPChip) { /* testchip */
+ phy_set_bb_reg(adapter, 0x858, BIT(10) | BIT(9) | BIT(8), 1);
+ phy_set_bb_reg(adapter, 0x858, BIT(13) | BIT(12) | BIT(11), 2);
+ } else { /* MPchip */
+ phy_set_bb_reg(adapter, 0x914, bMaskByte0, 1);
+ phy_set_bb_reg(adapter, 0x914, bMaskByte1, 2);
+ }
+
+ /* Default Ant Setting when no fast training */
+ phy_set_bb_reg(adapter, 0x80c, BIT(21), 1);
+ phy_set_bb_reg(adapter, 0x864, BIT(5) | BIT(4) | BIT(3), 0);
+ phy_set_bb_reg(adapter, 0x864, BIT(8) | BIT(7) | BIT(6), 1);
+
+ /* Enter Traing state */
+ phy_set_bb_reg(adapter, 0x864, BIT(2) | BIT(1) | BIT(0), 1);
+ phy_set_bb_reg(adapter, 0xc50, BIT(7), 1);
+}
+
+void rtl88eu_dm_antenna_div_init(struct odm_dm_struct *dm_odm)
+{
+ if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV)
+ dm_rx_hw_antena_div_init(dm_odm);
+ else if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
+ dm_trx_hw_antenna_div_init(dm_odm);
+ else if (dm_odm->AntDivType == CG_TRX_SMART_ANTDIV)
+ dm_fast_training_init(dm_odm);
+}
+
+void rtl88eu_dm_update_rx_idle_ant(struct odm_dm_struct *dm_odm, u8 ant)
+{
+ struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
+ struct adapter *adapter = dm_odm->Adapter;
+ u32 default_ant, optional_ant;
+
+ if (dm_fat_tbl->RxIdleAnt != ant) {
+ if (ant == MAIN_ANT) {
+ default_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ?
+ MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX;
+ optional_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ?
+ AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX;
+ } else {
+ default_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ?
+ AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX;
+ optional_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ?
+ MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX;
+ }
+
+ if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) {
+ phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
+ BIT(5) | BIT(4) | BIT(3), default_ant);
+ phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
+ BIT(8) | BIT(7) | BIT(6), optional_ant);
+ phy_set_bb_reg(adapter, ODM_REG_ANTSEL_CTRL_11N,
+ BIT(14) | BIT(13) | BIT(12), default_ant);
+ phy_set_bb_reg(adapter, ODM_REG_RESP_TX_11N,
+ BIT(6) | BIT(7), default_ant);
+ } else if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV) {
+ phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
+ BIT(5) | BIT(4) | BIT(3), default_ant);
+ phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
+ BIT(8) | BIT(7) | BIT(6), optional_ant);
+ }
+ }
+ dm_fat_tbl->RxIdleAnt = ant;
+}
+
+static void update_tx_ant_88eu(struct odm_dm_struct *dm_odm, u8 ant, u32 mac_id)
+{
+ struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
+ u8 target_ant;
+
+ if (ant == MAIN_ANT)
+ target_ant = MAIN_ANT_CG_TRX;
+ else
+ target_ant = AUX_ANT_CG_TRX;
+ dm_fat_tbl->antsel_a[mac_id] = target_ant & BIT(0);
+ dm_fat_tbl->antsel_b[mac_id] = (target_ant & BIT(1)) >> 1;
+ dm_fat_tbl->antsel_c[mac_id] = (target_ant & BIT(2)) >> 2;
+}
+
+void rtl88eu_dm_set_tx_ant_by_tx_info(struct odm_dm_struct *dm_odm,
+ u8 *desc, u8 mac_id)
+{
+ struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
+
+ if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ||
+ (dm_odm->AntDivType == CG_TRX_SMART_ANTDIV)) {
+ SET_TX_DESC_ANTSEL_A_88E(desc, dm_fat_tbl->antsel_a[mac_id]);
+ SET_TX_DESC_ANTSEL_B_88E(desc, dm_fat_tbl->antsel_b[mac_id]);
+ SET_TX_DESC_ANTSEL_C_88E(desc, dm_fat_tbl->antsel_c[mac_id]);
+ }
+}
+
+void rtl88eu_dm_ant_sel_statistics(struct odm_dm_struct *dm_odm,
+ u8 antsel_tr_mux, u32 mac_id, u8 rx_pwdb_all)
+{
+ struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
+
+ if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) {
+ if (antsel_tr_mux == MAIN_ANT_CG_TRX) {
+ dm_fat_tbl->MainAnt_Sum[mac_id] += rx_pwdb_all;
+ dm_fat_tbl->MainAnt_Cnt[mac_id]++;
+ } else {
+ dm_fat_tbl->AuxAnt_Sum[mac_id] += rx_pwdb_all;
+ dm_fat_tbl->AuxAnt_Cnt[mac_id]++;
+ }
+ } else if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV) {
+ if (antsel_tr_mux == MAIN_ANT_CGCS_RX) {
+ dm_fat_tbl->MainAnt_Sum[mac_id] += rx_pwdb_all;
+ dm_fat_tbl->MainAnt_Cnt[mac_id]++;
+ } else {
+ dm_fat_tbl->AuxAnt_Sum[mac_id] += rx_pwdb_all;
+ dm_fat_tbl->AuxAnt_Cnt[mac_id]++;
+ }
+ }
+}
+
+static void rtl88eu_dm_hw_ant_div(struct odm_dm_struct *dm_odm)
+{
+ struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
+ struct rtw_dig *dig_table = &dm_odm->DM_DigTable;
+ struct sta_info *entry;
+ u32 i, min_rssi = 0xFF, ant_div_max_rssi = 0, max_rssi = 0;
+ u32 local_min_rssi, local_max_rssi;
+ u32 main_rssi, aux_rssi;
+ u8 RxIdleAnt = 0, target_ant = 7;
+
+ for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
+ entry = dm_odm->pODM_StaInfo[i];
+ if (IS_STA_VALID(entry)) {
+ /* 2 Calculate RSSI per Antenna */
+ main_rssi = (dm_fat_tbl->MainAnt_Cnt[i] != 0) ?
+ (dm_fat_tbl->MainAnt_Sum[i] /
+ dm_fat_tbl->MainAnt_Cnt[i]) : 0;
+ aux_rssi = (dm_fat_tbl->AuxAnt_Cnt[i] != 0) ?
+ (dm_fat_tbl->AuxAnt_Sum[i] /
+ dm_fat_tbl->AuxAnt_Cnt[i]) : 0;
+ target_ant = (main_rssi >= aux_rssi) ? MAIN_ANT : AUX_ANT;
+ /* 2 Select max_rssi for DIG */
+ local_max_rssi = max(main_rssi, aux_rssi);
+ if ((local_max_rssi > ant_div_max_rssi) &&
+ (local_max_rssi < 40))
+ ant_div_max_rssi = local_max_rssi;
+ if (local_max_rssi > max_rssi)
+ max_rssi = local_max_rssi;
+
+ /* 2 Select RX Idle Antenna */
+ if ((dm_fat_tbl->RxIdleAnt == MAIN_ANT) &&
+ (main_rssi == 0))
+ main_rssi = aux_rssi;
+ else if ((dm_fat_tbl->RxIdleAnt == AUX_ANT) &&
+ (aux_rssi == 0))
+ aux_rssi = main_rssi;
+
+ local_min_rssi = min(main_rssi, aux_rssi);
+ if (local_min_rssi < min_rssi) {
+ min_rssi = local_min_rssi;
+ RxIdleAnt = target_ant;
+ }
+ /* 2 Select TRX Antenna */
+ if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
+ update_tx_ant_88eu(dm_odm, target_ant, i);
+ }
+ dm_fat_tbl->MainAnt_Sum[i] = 0;
+ dm_fat_tbl->AuxAnt_Sum[i] = 0;
+ dm_fat_tbl->MainAnt_Cnt[i] = 0;
+ dm_fat_tbl->AuxAnt_Cnt[i] = 0;
+ }
+
+ /* 2 Set RX Idle Antenna */
+ rtl88eu_dm_update_rx_idle_ant(dm_odm, RxIdleAnt);
+
+ dig_table->AntDiv_RSSI_max = ant_div_max_rssi;
+ dig_table->RSSI_max = max_rssi;
+}
+
+void rtl88eu_dm_antenna_diversity(struct odm_dm_struct *dm_odm)
+{
+ struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
+ struct adapter *adapter = dm_odm->Adapter;
+
+ if (!(dm_odm->SupportAbility & ODM_BB_ANT_DIV))
+ return;
+ if (!dm_odm->bLinked) {
+ ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
+ ("ODM_AntennaDiversity_88E(): No Link.\n"));
+ if (dm_fat_tbl->bBecomeLinked) {
+ ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
+ ("Need to Turn off HW AntDiv\n"));
+ phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0);
+ phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA1_11N,
+ BIT(15), 0);
+ if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
+ phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N,
+ BIT(21), 0);
+ dm_fat_tbl->bBecomeLinked = dm_odm->bLinked;
+ }
+ return;
+ } else {
+ if (!dm_fat_tbl->bBecomeLinked) {
+ ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
+ ("Need to Turn on HW AntDiv\n"));
+ phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 1);
+ phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA1_11N,
+ BIT(15), 1);
+ if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
+ phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N,
+ BIT(21), 1);
+ dm_fat_tbl->bBecomeLinked = dm_odm->bLinked;
+ }
+ }
+ if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ||
+ (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV))
+ rtl88eu_dm_hw_ant_div(dm_odm);
+}
diff --git a/drivers/staging/rtl8188eu/hal/phy.c b/drivers/staging/rtl8188eu/hal/phy.c
new file mode 100644
index 0000000..51c40ab
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/phy.c
@@ -0,0 +1,1334 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _RTL8188E_PHYCFG_C_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <rtl8188e_hal.h>
+#include <rf.h>
+#include <phy.h>
+
+#define MAX_PRECMD_CNT 16
+#define MAX_RFDEPENDCMD_CNT 16
+#define MAX_POSTCMD_CNT 16
+
+#define MAX_DOZE_WAITING_TIMES_9x 64
+
+static u32 cal_bit_shift(u32 bitmask)
+{
+ u32 i;
+
+ for (i = 0; i <= 31; i++) {
+ if (((bitmask >> i) & 0x1) == 1)
+ break;
+ }
+ return i;
+}
+
+u32 phy_query_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask)
+{
+ u32 original_value, bit_shift;
+
+ original_value = usb_read32(adapt, regaddr);
+ bit_shift = cal_bit_shift(bitmask);
+ return (original_value & bitmask) >> bit_shift;
+}
+
+void phy_set_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask, u32 data)
+{
+ u32 original_value, bit_shift;
+
+ if (bitmask != bMaskDWord) { /* if not "double word" write */
+ original_value = usb_read32(adapt, regaddr);
+ bit_shift = cal_bit_shift(bitmask);
+ data = (original_value & (~bitmask)) | (data << bit_shift);
+ }
+
+ usb_write32(adapt, regaddr, data);
+}
+
+static u32 rf_serial_read(struct adapter *adapt,
+ enum rf_radio_path rfpath, u32 offset)
+{
+ u32 ret = 0;
+ struct bb_reg_def *phyreg = &adapt->HalData->PHYRegDef[rfpath];
+ u32 tmplong, tmplong2;
+ u8 rfpi_enable = 0;
+
+ offset &= 0xff;
+
+ tmplong = phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter2, bMaskDWord);
+ if (rfpath == RF_PATH_A)
+ tmplong2 = tmplong;
+ else
+ tmplong2 = phy_query_bb_reg(adapt, phyreg->rfHSSIPara2,
+ bMaskDWord);
+
+ tmplong2 = (tmplong2 & (~bLSSIReadAddress)) |
+ (offset<<23) | bLSSIReadEdge;
+
+ phy_set_bb_reg(adapt, rFPGA0_XA_HSSIParameter2, bMaskDWord,
+ tmplong&(~bLSSIReadEdge));
+ udelay(10);
+
+ phy_set_bb_reg(adapt, phyreg->rfHSSIPara2, bMaskDWord, tmplong2);
+ udelay(100);
+
+ udelay(10);
+
+ if (rfpath == RF_PATH_A)
+ rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, BIT(8));
+ else if (rfpath == RF_PATH_B)
+ rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XB_HSSIParameter1, BIT(8));
+
+ if (rfpi_enable)
+ ret = phy_query_bb_reg(adapt, phyreg->rfLSSIReadBackPi,
+ bLSSIReadBackData);
+ else
+ ret = phy_query_bb_reg(adapt, phyreg->rfLSSIReadBack,
+ bLSSIReadBackData);
+ return ret;
+}
+
+static void rf_serial_write(struct adapter *adapt,
+ enum rf_radio_path rfpath, u32 offset,
+ u32 data)
+{
+ u32 data_and_addr = 0;
+ struct bb_reg_def *phyreg = &adapt->HalData->PHYRegDef[rfpath];
+
+ offset &= 0xff;
+ data_and_addr = ((offset<<20) | (data&0x000fffff)) & 0x0fffffff;
+ phy_set_bb_reg(adapt, phyreg->rf3wireOffset, bMaskDWord, data_and_addr);
+}
+
+u32 rtw_hal_read_rfreg(struct adapter *adapt, enum rf_radio_path rf_path,
+ u32 reg_addr, u32 bit_mask)
+{
+ u32 original_value, bit_shift;
+
+ original_value = rf_serial_read(adapt, rf_path, reg_addr);
+ bit_shift = cal_bit_shift(bit_mask);
+ return (original_value & bit_mask) >> bit_shift;
+}
+
+void phy_set_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path,
+ u32 reg_addr, u32 bit_mask, u32 data)
+{
+ u32 original_value, bit_shift;
+
+ /* RF data is 12 bits only */
+ if (bit_mask != bRFRegOffsetMask) {
+ original_value = rf_serial_read(adapt, rf_path, reg_addr);
+ bit_shift = cal_bit_shift(bit_mask);
+ data = (original_value & (~bit_mask)) | (data << bit_shift);
+ }
+
+ rf_serial_write(adapt, rf_path, reg_addr, data);
+}
+
+static void get_tx_power_index(struct adapter *adapt, u8 channel, u8 *cck_pwr,
+ u8 *ofdm_pwr, u8 *bw20_pwr, u8 *bw40_pwr)
+{
+ struct hal_data_8188e *hal_data = adapt->HalData;
+ u8 index = (channel - 1);
+ u8 TxCount = 0, path_nums;
+
+ path_nums = 1;
+
+ for (TxCount = 0; TxCount < path_nums; TxCount++) {
+ if (TxCount == RF_PATH_A) {
+ cck_pwr[TxCount] = hal_data->Index24G_CCK_Base[TxCount][index];
+ ofdm_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
+ hal_data->OFDM_24G_Diff[TxCount][RF_PATH_A];
+
+ bw20_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
+ hal_data->BW20_24G_Diff[TxCount][RF_PATH_A];
+ bw40_pwr[TxCount] = hal_data->Index24G_BW40_Base[TxCount][index];
+ } else if (TxCount == RF_PATH_B) {
+ cck_pwr[TxCount] = hal_data->Index24G_CCK_Base[TxCount][index];
+ ofdm_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
+ hal_data->BW20_24G_Diff[RF_PATH_A][index]+
+ hal_data->BW20_24G_Diff[TxCount][index];
+
+ bw20_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
+ hal_data->BW20_24G_Diff[TxCount][RF_PATH_A]+
+ hal_data->BW20_24G_Diff[TxCount][index];
+ bw40_pwr[TxCount] = hal_data->Index24G_BW40_Base[TxCount][index];
+ }
+ }
+}
+
+static void phy_power_index_check(struct adapter *adapt, u8 channel,
+ u8 *cck_pwr, u8 *ofdm_pwr, u8 *bw20_pwr,
+ u8 *bw40_pwr)
+{
+ struct hal_data_8188e *hal_data = adapt->HalData;
+
+ hal_data->CurrentCckTxPwrIdx = cck_pwr[0];
+ hal_data->CurrentOfdm24GTxPwrIdx = ofdm_pwr[0];
+ hal_data->CurrentBW2024GTxPwrIdx = bw20_pwr[0];
+ hal_data->CurrentBW4024GTxPwrIdx = bw40_pwr[0];
+}
+
+void phy_set_tx_power_level(struct adapter *adapt, u8 channel)
+{
+ u8 cck_pwr[MAX_TX_COUNT] = {0};
+ u8 ofdm_pwr[MAX_TX_COUNT] = {0};/* [0]:RF-A, [1]:RF-B */
+ u8 bw20_pwr[MAX_TX_COUNT] = {0};
+ u8 bw40_pwr[MAX_TX_COUNT] = {0};
+
+ get_tx_power_index(adapt, channel, &cck_pwr[0], &ofdm_pwr[0],
+ &bw20_pwr[0], &bw40_pwr[0]);
+
+ phy_power_index_check(adapt, channel, &cck_pwr[0], &ofdm_pwr[0],
+ &bw20_pwr[0], &bw40_pwr[0]);
+
+ rtl88eu_phy_rf6052_set_cck_txpower(adapt, &cck_pwr[0]);
+ rtl88eu_phy_rf6052_set_ofdm_txpower(adapt, &ofdm_pwr[0], &bw20_pwr[0],
+ &bw40_pwr[0], channel);
+}
+
+static void phy_set_bw_mode_callback(struct adapter *adapt)
+{
+ struct hal_data_8188e *hal_data = adapt->HalData;
+ u8 reg_bw_opmode;
+ u8 reg_prsr_rsc;
+
+ if (adapt->bDriverStopped)
+ return;
+
+ /* Set MAC register */
+
+ reg_bw_opmode = usb_read8(adapt, REG_BWOPMODE);
+ reg_prsr_rsc = usb_read8(adapt, REG_RRSR+2);
+
+ switch (hal_data->CurrentChannelBW) {
+ case HT_CHANNEL_WIDTH_20:
+ reg_bw_opmode |= BW_OPMODE_20MHZ;
+ usb_write8(adapt, REG_BWOPMODE, reg_bw_opmode);
+ break;
+ case HT_CHANNEL_WIDTH_40:
+ reg_bw_opmode &= ~BW_OPMODE_20MHZ;
+ usb_write8(adapt, REG_BWOPMODE, reg_bw_opmode);
+ reg_prsr_rsc = (reg_prsr_rsc&0x90) |
+ (hal_data->nCur40MhzPrimeSC<<5);
+ usb_write8(adapt, REG_RRSR+2, reg_prsr_rsc);
+ break;
+ default:
+ break;
+ }
+
+ /* Set PHY related register */
+ switch (hal_data->CurrentChannelBW) {
+ case HT_CHANNEL_WIDTH_20:
+ phy_set_bb_reg(adapt, rFPGA0_RFMOD, bRFMOD, 0x0);
+ phy_set_bb_reg(adapt, rFPGA1_RFMOD, bRFMOD, 0x0);
+ break;
+ case HT_CHANNEL_WIDTH_40:
+ phy_set_bb_reg(adapt, rFPGA0_RFMOD, bRFMOD, 0x1);
+ phy_set_bb_reg(adapt, rFPGA1_RFMOD, bRFMOD, 0x1);
+ /* Set Control channel to upper or lower.
+ * These settings are required only for 40MHz
+ */
+ phy_set_bb_reg(adapt, rCCK0_System, bCCKSideBand,
+ (hal_data->nCur40MhzPrimeSC>>1));
+ phy_set_bb_reg(adapt, rOFDM1_LSTF, 0xC00,
+ hal_data->nCur40MhzPrimeSC);
+ phy_set_bb_reg(adapt, 0x818, (BIT(26) | BIT(27)),
+ (hal_data->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
+ break;
+ default:
+ break;
+ }
+
+ /* Set RF related register */
+ rtl88eu_phy_rf6052_set_bandwidth(adapt, hal_data->CurrentChannelBW);
+}
+
+void rtw_hal_set_bwmode(struct adapter *adapt, enum ht_channel_width bandwidth,
+ unsigned char offset)
+{
+ struct hal_data_8188e *hal_data = adapt->HalData;
+ enum ht_channel_width tmp_bw = hal_data->CurrentChannelBW;
+
+ hal_data->CurrentChannelBW = bandwidth;
+ hal_data->nCur40MhzPrimeSC = offset;
+
+ if ((!adapt->bDriverStopped) && (!adapt->bSurpriseRemoved))
+ phy_set_bw_mode_callback(adapt);
+ else
+ hal_data->CurrentChannelBW = tmp_bw;
+}
+
+static void phy_sw_chnl_callback(struct adapter *adapt, u8 channel)
+{
+ u32 param1, param2;
+ struct hal_data_8188e *hal_data = adapt->HalData;
+
+ phy_set_tx_power_level(adapt, channel);
+
+ param1 = RF_CHNLBW;
+ param2 = channel;
+ hal_data->RfRegChnlVal[0] = (hal_data->RfRegChnlVal[0] &
+ 0xfffffc00) | param2;
+ phy_set_rf_reg(adapt, 0, param1,
+ bRFRegOffsetMask, hal_data->RfRegChnlVal[0]);
+}
+
+void rtw_hal_set_chan(struct adapter *adapt, u8 channel)
+{
+ struct hal_data_8188e *hal_data = adapt->HalData;
+ u8 tmpchannel = hal_data->CurrentChannel;
+
+ if (channel == 0)
+ channel = 1;
+
+ hal_data->CurrentChannel = channel;
+
+ if ((!adapt->bDriverStopped) && (!adapt->bSurpriseRemoved))
+ phy_sw_chnl_callback(adapt, channel);
+ else
+ hal_data->CurrentChannel = tmpchannel;
+}
+
+#define ODM_TXPWRTRACK_MAX_IDX_88E 6
+
+void rtl88eu_dm_txpower_track_adjust(struct odm_dm_struct *dm_odm, u8 type,
+ u8 *direction, u32 *out_write_val)
+{
+ u8 pwr_value = 0;
+ /* Tx power tracking BB swing table. */
+ if (type == 0) { /* For OFDM adjust */
+ ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
+ ("BbSwingIdxOfdm = %d BbSwingFlagOfdm=%d\n",
+ dm_odm->BbSwingIdxOfdm, dm_odm->BbSwingFlagOfdm));
+
+ if (dm_odm->BbSwingIdxOfdm <= dm_odm->BbSwingIdxOfdmBase) {
+ *direction = 1;
+ pwr_value = dm_odm->BbSwingIdxOfdmBase -
+ dm_odm->BbSwingIdxOfdm;
+ } else {
+ *direction = 2;
+ pwr_value = dm_odm->BbSwingIdxOfdm -
+ dm_odm->BbSwingIdxOfdmBase;
+ }
+
+ } else if (type == 1) { /* For CCK adjust. */
+ ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
+ ("dm_odm->BbSwingIdxCck = %d dm_odm->BbSwingIdxCckBase = %d\n",
+ dm_odm->BbSwingIdxCck, dm_odm->BbSwingIdxCckBase));
+
+ if (dm_odm->BbSwingIdxCck <= dm_odm->BbSwingIdxCckBase) {
+ *direction = 1;
+ pwr_value = dm_odm->BbSwingIdxCckBase -
+ dm_odm->BbSwingIdxCck;
+ } else {
+ *direction = 2;
+ pwr_value = dm_odm->BbSwingIdxCck -
+ dm_odm->BbSwingIdxCckBase;
+ }
+ }
+
+ if (pwr_value >= ODM_TXPWRTRACK_MAX_IDX_88E && *direction == 1)
+ pwr_value = ODM_TXPWRTRACK_MAX_IDX_88E;
+
+ *out_write_val = pwr_value | (pwr_value<<8) | (pwr_value<<16) |
+ (pwr_value<<24);
+}
+
+static void dm_txpwr_track_setpwr(struct odm_dm_struct *dm_odm)
+{
+ if (dm_odm->BbSwingFlagOfdm || dm_odm->BbSwingFlagCck) {
+ ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
+ ("dm_txpwr_track_setpwr CH=%d\n", *(dm_odm->pChannel)));
+ phy_set_tx_power_level(dm_odm->Adapter, *(dm_odm->pChannel));
+ dm_odm->BbSwingFlagOfdm = false;
+ dm_odm->BbSwingFlagCck = false;
+ }
+}
+
+void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt)
+{
+ struct hal_data_8188e *hal_data = adapt->HalData;
+ u8 thermal_val = 0, delta, delta_lck, delta_iqk, offset;
+ u8 thermal_avg_count = 0;
+ u32 thermal_avg = 0;
+ s32 ele_d, temp_cck;
+ s8 ofdm_index[2], cck_index = 0;
+ s8 ofdm_index_old[2] = {0, 0}, cck_index_old = 0;
+ u32 i = 0, j = 0;
+
+ u8 ofdm_min_index = 6; /* OFDM BB Swing should be less than +3.0dB */
+ s8 ofdm_index_mapping[2][index_mapping_NUM_88E] = {
+ /* 2.4G, decrease power */
+ {0, 0, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11},
+ /* 2.4G, increase power */
+ {0, 0, -1, -2, -3, -4, -4, -4, -4, -5, -7, -8, -9, -9, -10},
+ };
+ u8 thermal_mapping[2][index_mapping_NUM_88E] = {
+ /* 2.4G, decrease power */
+ {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 27},
+ /* 2.4G, increase power */
+ {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 25, 25},
+ };
+ struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
+
+ dm_txpwr_track_setpwr(dm_odm);
+
+ dm_odm->RFCalibrateInfo.TXPowerTrackingCallbackCnt++;
+
+ dm_odm->RFCalibrateInfo.RegA24 = 0x090e1317;
+
+ thermal_val = (u8)rtw_hal_read_rfreg(adapt, RF_PATH_A,
+ RF_T_METER_88E, 0xfc00);
+
+ if (thermal_val) {
+ /* Query OFDM path A default setting */
+ ele_d = phy_query_bb_reg(adapt, rOFDM0_XATxIQImbalance, bMaskDWord)&bMaskOFDM_D;
+ for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {
+ if (ele_d == (OFDMSwingTable[i]&bMaskOFDM_D)) {
+ ofdm_index_old[0] = (u8)i;
+ dm_odm->BbSwingIdxOfdmBase = (u8)i;
+ break;
+ }
+ }
+
+ /* Query CCK default setting From 0xa24 */
+ temp_cck = dm_odm->RFCalibrateInfo.RegA24;
+
+ for (i = 0; i < CCK_TABLE_SIZE; i++) {
+ if ((dm_odm->RFCalibrateInfo.bCCKinCH14 &&
+ memcmp(&temp_cck, &CCKSwingTable_Ch14[i][2], 4)) ||
+ memcmp(&temp_cck, &CCKSwingTable_Ch1_Ch13[i][2], 4)) {
+ cck_index_old = (u8)i;
+ dm_odm->BbSwingIdxCckBase = (u8)i;
+ break;
+ }
+ }
+
+ if (!dm_odm->RFCalibrateInfo.ThermalValue) {
+ dm_odm->RFCalibrateInfo.ThermalValue = hal_data->EEPROMThermalMeter;
+ dm_odm->RFCalibrateInfo.ThermalValue_LCK = thermal_val;
+ dm_odm->RFCalibrateInfo.ThermalValue_IQK = thermal_val;
+
+ dm_odm->RFCalibrateInfo.OFDM_index[0] = ofdm_index_old[0];
+ dm_odm->RFCalibrateInfo.CCK_index = cck_index_old;
+ }
+
+ /* calculate average thermal meter */
+ dm_odm->RFCalibrateInfo.ThermalValue_AVG[dm_odm->RFCalibrateInfo.ThermalValue_AVG_index] = thermal_val;
+ dm_odm->RFCalibrateInfo.ThermalValue_AVG_index++;
+ if (dm_odm->RFCalibrateInfo.ThermalValue_AVG_index == AVG_THERMAL_NUM_88E)
+ dm_odm->RFCalibrateInfo.ThermalValue_AVG_index = 0;
+
+ for (i = 0; i < AVG_THERMAL_NUM_88E; i++) {
+ if (dm_odm->RFCalibrateInfo.ThermalValue_AVG[i]) {
+ thermal_avg += dm_odm->RFCalibrateInfo.ThermalValue_AVG[i];
+ thermal_avg_count++;
+ }
+ }
+
+ if (thermal_avg_count)
+ thermal_val = (u8)(thermal_avg / thermal_avg_count);
+
+ if (dm_odm->RFCalibrateInfo.bDoneTxpower &&
+ !dm_odm->RFCalibrateInfo.bReloadtxpowerindex) {
+ delta = abs(thermal_val - dm_odm->RFCalibrateInfo.ThermalValue);
+ } else {
+ delta = abs(thermal_val - hal_data->EEPROMThermalMeter);
+ if (dm_odm->RFCalibrateInfo.bReloadtxpowerindex) {
+ dm_odm->RFCalibrateInfo.bReloadtxpowerindex = false;
+ dm_odm->RFCalibrateInfo.bDoneTxpower = false;
+ }
+ }
+
+ delta_lck = abs(dm_odm->RFCalibrateInfo.ThermalValue_LCK - thermal_val);
+ delta_iqk = abs(dm_odm->RFCalibrateInfo.ThermalValue_IQK - thermal_val);
+
+ /* Delta temperature is equal to or larger than 20 centigrade.*/
+ if ((delta_lck >= 8)) {
+ dm_odm->RFCalibrateInfo.ThermalValue_LCK = thermal_val;
+ rtl88eu_phy_lc_calibrate(adapt);
+ }
+
+ if (delta > 0 && dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
+ delta = abs(hal_data->EEPROMThermalMeter - thermal_val);
+
+ /* calculate new OFDM / CCK offset */
+ if (thermal_val > hal_data->EEPROMThermalMeter)
+ j = 1;
+ else
+ j = 0;
+ for (offset = 0; offset < index_mapping_NUM_88E; offset++) {
+ if (delta < thermal_mapping[j][offset]) {
+ if (offset != 0)
+ offset--;
+ break;
+ }
+ }
+ if (offset >= index_mapping_NUM_88E)
+ offset = index_mapping_NUM_88E-1;
+
+ /* Updating ofdm_index values with new OFDM / CCK offset */
+ ofdm_index[0] = dm_odm->RFCalibrateInfo.OFDM_index[0] + ofdm_index_mapping[j][offset];
+ if (ofdm_index[0] > OFDM_TABLE_SIZE_92D-1)
+ ofdm_index[0] = OFDM_TABLE_SIZE_92D-1;
+ else if (ofdm_index[0] < ofdm_min_index)
+ ofdm_index[0] = ofdm_min_index;
+
+ cck_index = dm_odm->RFCalibrateInfo.CCK_index + ofdm_index_mapping[j][offset];
+ if (cck_index > CCK_TABLE_SIZE-1)
+ cck_index = CCK_TABLE_SIZE-1;
+ else if (cck_index < 0)
+ cck_index = 0;
+
+ /* 2 temporarily remove bNOPG */
+ /* Config by SwingTable */
+ if (dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
+ dm_odm->RFCalibrateInfo.bDoneTxpower = true;
+
+ /* Revse TX power table. */
+ dm_odm->BbSwingIdxOfdm = (u8)ofdm_index[0];
+ dm_odm->BbSwingIdxCck = (u8)cck_index;
+
+ if (dm_odm->BbSwingIdxOfdmCurrent != dm_odm->BbSwingIdxOfdm) {
+ dm_odm->BbSwingIdxOfdmCurrent = dm_odm->BbSwingIdxOfdm;
+ dm_odm->BbSwingFlagOfdm = true;
+ }
+
+ if (dm_odm->BbSwingIdxCckCurrent != dm_odm->BbSwingIdxCck) {
+ dm_odm->BbSwingIdxCckCurrent = dm_odm->BbSwingIdxCck;
+ dm_odm->BbSwingFlagCck = true;
+ }
+ }
+ }
+
+ /* Delta temperature is equal to or larger than 20 centigrade.*/
+ if (delta_iqk >= 8) {
+ dm_odm->RFCalibrateInfo.ThermalValue_IQK = thermal_val;
+ rtl88eu_phy_iq_calibrate(adapt, false);
+ }
+ /* update thermal meter value */
+ if (dm_odm->RFCalibrateInfo.TxPowerTrackControl)
+ dm_odm->RFCalibrateInfo.ThermalValue = thermal_val;
+ }
+ dm_odm->RFCalibrateInfo.TXPowercount = 0;
+}
+
+#define MAX_TOLERANCE 5
+
+static u8 phy_path_a_iqk(struct adapter *adapt, bool config_pathb)
+{
+ u32 reg_eac, reg_e94, reg_e9c;
+ u8 result = 0x00;
+
+ /* 1 Tx IQK */
+ /* path-A IQK setting */
+ phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
+ phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
+ phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x8214032a);
+ phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
+
+ /* LO calibration setting */
+ phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x00462911);
+
+ /* One shot, path A LOK & IQK */
+ phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
+ phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
+
+ mdelay(IQK_DELAY_TIME_88E);
+
+ reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
+ reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
+ reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
+
+ if (!(reg_eac & BIT(28)) &&
+ (((reg_e94 & 0x03FF0000)>>16) != 0x142) &&
+ (((reg_e9c & 0x03FF0000)>>16) != 0x42))
+ result |= 0x01;
+ return result;
+}
+
+static u8 phy_path_a_rx_iqk(struct adapter *adapt, bool configPathB)
+{
+ u32 reg_eac, reg_e94, reg_e9c, reg_ea4, u4tmp;
+ u8 result = 0x00;
+ struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
+
+ /* 1 Get TXIMR setting */
+ /* modify RXIQK mode table */
+ phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
+ phy_set_rf_reg(adapt, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0);
+ phy_set_rf_reg(adapt, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
+ phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f);
+ phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf117B);
+
+ /* PA,PAD off */
+ phy_set_rf_reg(adapt, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x980);
+ phy_set_rf_reg(adapt, RF_PATH_A, 0x56, bRFRegOffsetMask, 0x51000);
+
+ phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
+
+ /* IQK setting */
+ phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, 0x01007c00);
+ phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x81004800);
+
+ /* path-A IQK setting */
+ phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
+ phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
+ phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c1f);
+ phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
+
+ /* LO calibration setting */
+ phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
+
+ /* One shot, path A LOK & IQK */
+ phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
+ phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
+
+ /* delay x ms */
+ mdelay(IQK_DELAY_TIME_88E);
+
+ /* Check failed */
+ reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
+ reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
+ reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
+
+ if (!(reg_eac & BIT(28)) &&
+ (((reg_e94 & 0x03FF0000)>>16) != 0x142) &&
+ (((reg_e9c & 0x03FF0000)>>16) != 0x42))
+ result |= 0x01;
+ else /* if Tx not OK, ignore Rx */
+ return result;
+
+ u4tmp = 0x80007C00 | (reg_e94&0x3FF0000) | ((reg_e9c&0x3FF0000) >> 16);
+ phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, u4tmp);
+
+ /* 1 RX IQK */
+ /* modify RXIQK mode table */
+ ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
+ ("Path-A Rx IQK modify RXIQK mode table 2!\n"));
+ phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
+ phy_set_rf_reg(adapt, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0);
+ phy_set_rf_reg(adapt, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
+ phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f);
+ phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7ffa);
+ phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
+
+ /* IQK setting */
+ phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x01004800);
+
+ /* path-A IQK setting */
+ phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
+ phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
+ phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c05);
+ phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160c1f);
+
+ /* LO calibration setting */
+ phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
+
+ phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
+ phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
+
+ mdelay(IQK_DELAY_TIME_88E);
+
+ /* Check failed */
+ reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
+ reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
+ reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
+ reg_ea4 = phy_query_bb_reg(adapt, rRx_Power_Before_IQK_A_2, bMaskDWord);
+
+ /* reload RF 0xdf */
+ phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
+ phy_set_rf_reg(adapt, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x180);
+
+ if (!(reg_eac & BIT(27)) && /* if Tx is OK, check whether Rx is OK */
+ (((reg_ea4 & 0x03FF0000)>>16) != 0x132) &&
+ (((reg_eac & 0x03FF0000)>>16) != 0x36))
+ result |= 0x02;
+ else
+ ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
+ ("Path A Rx IQK fail!!\n"));
+
+ return result;
+}
+
+static u8 phy_path_b_iqk(struct adapter *adapt)
+{
+ u32 regeac, regeb4, regebc, regec4, regecc;
+ u8 result = 0x00;
+ struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
+
+ /* One shot, path B LOK & IQK */
+ phy_set_bb_reg(adapt, rIQK_AGC_Cont, bMaskDWord, 0x00000002);
+ phy_set_bb_reg(adapt, rIQK_AGC_Cont, bMaskDWord, 0x00000000);
+
+ mdelay(IQK_DELAY_TIME_88E);
+
+ regeac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
+ regeb4 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B, bMaskDWord);
+ regebc = phy_query_bb_reg(adapt, rTx_Power_After_IQK_B, bMaskDWord);
+ regec4 = phy_query_bb_reg(adapt, rRx_Power_Before_IQK_B_2, bMaskDWord);
+ regecc = phy_query_bb_reg(adapt, rRx_Power_After_IQK_B_2, bMaskDWord);
+
+ if (!(regeac & BIT(31)) &&
+ (((regeb4 & 0x03FF0000)>>16) != 0x142) &&
+ (((regebc & 0x03FF0000)>>16) != 0x42))
+ result |= 0x01;
+ else
+ return result;
+
+ if (!(regeac & BIT(30)) &&
+ (((regec4 & 0x03FF0000)>>16) != 0x132) &&
+ (((regecc & 0x03FF0000)>>16) != 0x36))
+ result |= 0x02;
+ else
+ ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION,
+ ODM_DBG_LOUD, ("Path B Rx IQK fail!!\n"));
+ return result;
+}
+
+static void patha_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8],
+ u8 final_candidate, bool txonly)
+{
+ u32 oldval_0, x, tx0_a, reg;
+ s32 y, tx0_c;
+
+ if (final_candidate == 0xFF) {
+ return;
+ } else if (iqkok) {
+ oldval_0 = (phy_query_bb_reg(adapt, rOFDM0_XATxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
+
+ x = result[final_candidate][0];
+ if ((x & 0x00000200) != 0)
+ x = x | 0xFFFFFC00;
+
+ tx0_a = (x * oldval_0) >> 8;
+ phy_set_bb_reg(adapt, rOFDM0_XATxIQImbalance, 0x3FF, tx0_a);
+ phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(31),
+ ((x * oldval_0>>7) & 0x1));
+
+ y = result[final_candidate][1];
+ if ((y & 0x00000200) != 0)
+ y = y | 0xFFFFFC00;
+
+ tx0_c = (y * oldval_0) >> 8;
+ phy_set_bb_reg(adapt, rOFDM0_XCTxAFE, 0xF0000000,
+ ((tx0_c&0x3C0)>>6));
+ phy_set_bb_reg(adapt, rOFDM0_XATxIQImbalance, 0x003F0000,
+ (tx0_c&0x3F));
+ phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(29),
+ ((y * oldval_0>>7) & 0x1));
+
+ if (txonly)
+ return;
+
+ reg = result[final_candidate][2];
+ phy_set_bb_reg(adapt, rOFDM0_XARxIQImbalance, 0x3FF, reg);
+
+ reg = result[final_candidate][3] & 0x3F;
+ phy_set_bb_reg(adapt, rOFDM0_XARxIQImbalance, 0xFC00, reg);
+
+ reg = (result[final_candidate][3] >> 6) & 0xF;
+ phy_set_bb_reg(adapt, rOFDM0_RxIQExtAnta, 0xF0000000, reg);
+ }
+}
+
+static void pathb_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8],
+ u8 final_candidate, bool txonly)
+{
+ u32 oldval_1, x, tx1_a, reg;
+ s32 y, tx1_c;
+
+ if (final_candidate == 0xFF) {
+ return;
+ } else if (iqkok) {
+ oldval_1 = (phy_query_bb_reg(adapt, rOFDM0_XBTxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
+
+ x = result[final_candidate][4];
+ if ((x & 0x00000200) != 0)
+ x = x | 0xFFFFFC00;
+ tx1_a = (x * oldval_1) >> 8;
+ phy_set_bb_reg(adapt, rOFDM0_XBTxIQImbalance, 0x3FF, tx1_a);
+
+ phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(27),
+ ((x * oldval_1>>7) & 0x1));
+
+ y = result[final_candidate][5];
+ if ((y & 0x00000200) != 0)
+ y = y | 0xFFFFFC00;
+
+ tx1_c = (y * oldval_1) >> 8;
+
+ phy_set_bb_reg(adapt, rOFDM0_XDTxAFE, 0xF0000000,
+ ((tx1_c&0x3C0)>>6));
+ phy_set_bb_reg(adapt, rOFDM0_XBTxIQImbalance, 0x003F0000,
+ (tx1_c&0x3F));
+ phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(25),
+ ((y * oldval_1>>7) & 0x1));
+
+ if (txonly)
+ return;
+
+ reg = result[final_candidate][6];
+ phy_set_bb_reg(adapt, rOFDM0_XBRxIQImbalance, 0x3FF, reg);
+
+ reg = result[final_candidate][7] & 0x3F;
+ phy_set_bb_reg(adapt, rOFDM0_XBRxIQImbalance, 0xFC00, reg);
+
+ reg = (result[final_candidate][7] >> 6) & 0xF;
+ phy_set_bb_reg(adapt, rOFDM0_AGCRSSITable, 0x0000F000, reg);
+ }
+}
+
+static void save_adda_registers(struct adapter *adapt, u32 *addareg,
+ u32 *backup, u32 register_num)
+{
+ u32 i;
+
+ for (i = 0; i < register_num; i++)
+ backup[i] = phy_query_bb_reg(adapt, addareg[i], bMaskDWord);
+}
+
+static void save_mac_registers(struct adapter *adapt, u32 *mac_reg,
+ u32 *backup)
+{
+ u32 i;
+
+ for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
+ backup[i] = usb_read8(adapt, mac_reg[i]);
+
+ backup[i] = usb_read32(adapt, mac_reg[i]);
+}
+
+static void reload_adda_reg(struct adapter *adapt, u32 *adda_reg,
+ u32 *backup, u32 regiester_num)
+{
+ u32 i;
+
+ for (i = 0; i < regiester_num; i++)
+ phy_set_bb_reg(adapt, adda_reg[i], bMaskDWord, backup[i]);
+}
+
+static void reload_mac_registers(struct adapter *adapt,
+ u32 *mac_reg, u32 *backup)
+{
+ u32 i;
+
+ for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
+ usb_write8(adapt, mac_reg[i], (u8)backup[i]);
+
+ usb_write32(adapt, mac_reg[i], backup[i]);
+}
+
+static void path_adda_on(struct adapter *adapt, u32 *adda_reg,
+ bool is_path_a_on, bool is2t)
+{
+ u32 path_on;
+ u32 i;
+
+ if (!is2t) {
+ path_on = 0x0bdb25a0;
+ phy_set_bb_reg(adapt, adda_reg[0], bMaskDWord, 0x0b1b25a0);
+ } else {
+ path_on = is_path_a_on ? 0x04db25a4 : 0x0b1b25a4;
+ phy_set_bb_reg(adapt, adda_reg[0], bMaskDWord, path_on);
+ }
+
+ for (i = 1; i < IQK_ADDA_REG_NUM; i++)
+ phy_set_bb_reg(adapt, adda_reg[i], bMaskDWord, path_on);
+}
+
+static void mac_setting_calibration(struct adapter *adapt, u32 *mac_reg, u32 *backup)
+{
+ u32 i = 0;
+
+ usb_write8(adapt, mac_reg[i], 0x3F);
+
+ for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++)
+ usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT(3))));
+
+ usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT(5))));
+}
+
+static void path_a_standby(struct adapter *adapt)
+{
+ phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x0);
+ phy_set_bb_reg(adapt, 0x840, bMaskDWord, 0x00010000);
+ phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
+}
+
+static void pi_mode_switch(struct adapter *adapt, bool pi_mode)
+{
+ u32 mode;
+
+ mode = pi_mode ? 0x01000100 : 0x01000000;
+ phy_set_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, bMaskDWord, mode);
+ phy_set_bb_reg(adapt, rFPGA0_XB_HSSIParameter1, bMaskDWord, mode);
+}
+
+static bool simularity_compare(struct adapter *adapt, s32 resulta[][8],
+ u8 c1, u8 c2)
+{
+ u32 i, j, diff, sim_bitmap = 0, bound;
+ u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */
+ bool result = true;
+ s32 tmp1 = 0, tmp2 = 0;
+
+ bound = 4;
+
+ for (i = 0; i < bound; i++) {
+ if ((i == 1) || (i == 3) || (i == 5) || (i == 7)) {
+ if ((resulta[c1][i] & 0x00000200) != 0)
+ tmp1 = resulta[c1][i] | 0xFFFFFC00;
+ else
+ tmp1 = resulta[c1][i];
+
+ if ((resulta[c2][i] & 0x00000200) != 0)
+ tmp2 = resulta[c2][i] | 0xFFFFFC00;
+ else
+ tmp2 = resulta[c2][i];
+ } else {
+ tmp1 = resulta[c1][i];
+ tmp2 = resulta[c2][i];
+ }
+
+ diff = abs(tmp1 - tmp2);
+
+ if (diff > MAX_TOLERANCE) {
+ if ((i == 2 || i == 6) && !sim_bitmap) {
+ if (resulta[c1][i] + resulta[c1][i+1] == 0)
+ final_candidate[(i/4)] = c2;
+ else if (resulta[c2][i] + resulta[c2][i+1] == 0)
+ final_candidate[(i/4)] = c1;
+ else
+ sim_bitmap = sim_bitmap | (1<<i);
+ } else {
+ sim_bitmap = sim_bitmap | (1<<i);
+ }
+ }
+ }
+
+ if (sim_bitmap == 0) {
+ for (i = 0; i < (bound/4); i++) {
+ if (final_candidate[i] != 0xFF) {
+ for (j = i*4; j < (i+1)*4-2; j++)
+ resulta[3][j] = resulta[final_candidate[i]][j];
+ result = false;
+ }
+ }
+ return result;
+ } else {
+ if (!(sim_bitmap & 0x03)) { /* path A TX OK */
+ for (i = 0; i < 2; i++)
+ resulta[3][i] = resulta[c1][i];
+ }
+ if (!(sim_bitmap & 0x0c)) { /* path A RX OK */
+ for (i = 2; i < 4; i++)
+ resulta[3][i] = resulta[c1][i];
+ }
+
+ if (!(sim_bitmap & 0x30)) { /* path B TX OK */
+ for (i = 4; i < 6; i++)
+ resulta[3][i] = resulta[c1][i];
+ }
+
+ if (!(sim_bitmap & 0xc0)) { /* path B RX OK */
+ for (i = 6; i < 8; i++)
+ resulta[3][i] = resulta[c1][i];
+ }
+ return false;
+ }
+}
+
+static void phy_iq_calibrate(struct adapter *adapt, s32 result[][8],
+ u8 t, bool is2t)
+{
+ struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
+ u32 i;
+ u8 path_a_ok, path_b_ok;
+ u32 adda_reg[IQK_ADDA_REG_NUM] = {
+ rFPGA0_XCD_SwitchControl, rBlue_Tooth,
+ rRx_Wait_CCA, rTx_CCK_RFON,
+ rTx_CCK_BBON, rTx_OFDM_RFON,
+ rTx_OFDM_BBON, rTx_To_Rx,
+ rTx_To_Tx, rRx_CCK,
+ rRx_OFDM, rRx_Wait_RIFS,
+ rRx_TO_Rx, rStandby,
+ rSleep, rPMPD_ANAEN};
+
+ u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
+ REG_TXPAUSE, REG_BCN_CTRL,
+ REG_BCN_CTRL_1, REG_GPIO_MUXCFG};
+
+ /* since 92C & 92D have the different define in IQK_BB_REG */
+ u32 iqk_bb_reg_92c[IQK_BB_REG_NUM] = {
+ rOFDM0_TRxPathEnable, rOFDM0_TRMuxPar,
+ rFPGA0_XCD_RFInterfaceSW, rConfig_AntA, rConfig_AntB,
+ rFPGA0_XAB_RFInterfaceSW, rFPGA0_XA_RFInterfaceOE,
+ rFPGA0_XB_RFInterfaceOE, rFPGA0_RFMOD};
+
+ u32 retry_count = 9;
+
+ if (*(dm_odm->mp_mode) == 1)
+ retry_count = 9;
+ else
+ retry_count = 2;
+
+ if (t == 0) {
+ /* Save ADDA parameters, turn Path A ADDA on */
+ save_adda_registers(adapt, adda_reg, dm_odm->RFCalibrateInfo.ADDA_backup,
+ IQK_ADDA_REG_NUM);
+ save_mac_registers(adapt, iqk_mac_reg,
+ dm_odm->RFCalibrateInfo.IQK_MAC_backup);
+ save_adda_registers(adapt, iqk_bb_reg_92c,
+ dm_odm->RFCalibrateInfo.IQK_BB_backup, IQK_BB_REG_NUM);
+ }
+
+ path_adda_on(adapt, adda_reg, true, is2t);
+ if (t == 0)
+ dm_odm->RFCalibrateInfo.bRfPiEnable = (u8)phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter1,
+ BIT(8));
+
+ if (!dm_odm->RFCalibrateInfo.bRfPiEnable) {
+ /* Switch BB to PI mode to do IQ Calibration. */
+ pi_mode_switch(adapt, true);
+ }
+
+ /* BB setting */
+ phy_set_bb_reg(adapt, rFPGA0_RFMOD, BIT(24), 0x00);
+ phy_set_bb_reg(adapt, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600);
+ phy_set_bb_reg(adapt, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4);
+ phy_set_bb_reg(adapt, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000);
+
+ phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(10), 0x01);
+ phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(26), 0x01);
+ phy_set_bb_reg(adapt, rFPGA0_XA_RFInterfaceOE, BIT(10), 0x00);
+ phy_set_bb_reg(adapt, rFPGA0_XB_RFInterfaceOE, BIT(10), 0x00);
+
+ if (is2t) {
+ phy_set_bb_reg(adapt, rFPGA0_XA_LSSIParameter, bMaskDWord,
+ 0x00010000);
+ phy_set_bb_reg(adapt, rFPGA0_XB_LSSIParameter, bMaskDWord,
+ 0x00010000);
+ }
+
+ /* MAC settings */
+ mac_setting_calibration(adapt, iqk_mac_reg,
+ dm_odm->RFCalibrateInfo.IQK_MAC_backup);
+
+ /* Page B init */
+ /* AP or IQK */
+ phy_set_bb_reg(adapt, rConfig_AntA, bMaskDWord, 0x0f600000);
+
+ if (is2t)
+ phy_set_bb_reg(adapt, rConfig_AntB, bMaskDWord, 0x0f600000);
+
+ /* IQ calibration setting */
+ phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
+ phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, 0x01007c00);
+ phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x81004800);
+
+ for (i = 0; i < retry_count; i++) {
+ path_a_ok = phy_path_a_iqk(adapt, is2t);
+ if (path_a_ok == 0x01) {
+ result[t][0] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A,
+ bMaskDWord)&0x3FF0000)>>16;
+ result[t][1] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_A,
+ bMaskDWord)&0x3FF0000)>>16;
+ break;
+ }
+ }
+
+ for (i = 0; i < retry_count; i++) {
+ path_a_ok = phy_path_a_rx_iqk(adapt, is2t);
+ if (path_a_ok == 0x03) {
+ result[t][2] = (phy_query_bb_reg(adapt, rRx_Power_Before_IQK_A_2,
+ bMaskDWord)&0x3FF0000)>>16;
+ result[t][3] = (phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2,
+ bMaskDWord)&0x3FF0000)>>16;
+ break;
+ } else {
+ ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
+ ("Path A Rx IQK Fail!!\n"));
+ }
+ }
+
+ if (path_a_ok == 0x00) {
+ ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
+ ("Path A IQK failed!!\n"));
+ }
+
+ if (is2t) {
+ path_a_standby(adapt);
+
+ /* Turn Path B ADDA on */
+ path_adda_on(adapt, adda_reg, false, is2t);
+
+ for (i = 0; i < retry_count; i++) {
+ path_b_ok = phy_path_b_iqk(adapt);
+ if (path_b_ok == 0x03) {
+ result[t][4] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B,
+ bMaskDWord)&0x3FF0000)>>16;
+ result[t][5] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_B,
+ bMaskDWord)&0x3FF0000)>>16;
+ result[t][6] = (phy_query_bb_reg(adapt, rRx_Power_Before_IQK_B_2,
+ bMaskDWord)&0x3FF0000)>>16;
+ result[t][7] = (phy_query_bb_reg(adapt, rRx_Power_After_IQK_B_2,
+ bMaskDWord)&0x3FF0000)>>16;
+ break;
+ } else if (i == (retry_count - 1) && path_b_ok == 0x01) { /* Tx IQK OK */
+ result[t][4] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B,
+ bMaskDWord)&0x3FF0000)>>16;
+ result[t][5] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_B,
+ bMaskDWord)&0x3FF0000)>>16;
+ }
+ }
+
+ if (path_b_ok == 0x00) {
+ ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
+ ("Path B IQK failed!!\n"));
+ }
+ }
+
+ /* Back to BB mode, load original value */
+ phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0);
+
+ if (t != 0) {
+ if (!dm_odm->RFCalibrateInfo.bRfPiEnable) {
+ /* Switch back BB to SI mode after
+ * finish IQ Calibration.
+ */
+ pi_mode_switch(adapt, false);
+ }
+
+ /* Reload ADDA power saving parameters */
+ reload_adda_reg(adapt, adda_reg, dm_odm->RFCalibrateInfo.ADDA_backup,
+ IQK_ADDA_REG_NUM);
+
+ /* Reload MAC parameters */
+ reload_mac_registers(adapt, iqk_mac_reg,
+ dm_odm->RFCalibrateInfo.IQK_MAC_backup);
+
+ reload_adda_reg(adapt, iqk_bb_reg_92c, dm_odm->RFCalibrateInfo.IQK_BB_backup,
+ IQK_BB_REG_NUM);
+
+ /* Restore RX initial gain */
+ phy_set_bb_reg(adapt, rFPGA0_XA_LSSIParameter,
+ bMaskDWord, 0x00032ed3);
+ if (is2t)
+ phy_set_bb_reg(adapt, rFPGA0_XB_LSSIParameter,
+ bMaskDWord, 0x00032ed3);
+
+ /* load 0xe30 IQC default value */
+ phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00);
+ phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00);
+ }
+}
+
+static void phy_lc_calibrate(struct adapter *adapt, bool is2t)
+{
+ u8 tmpreg;
+ u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal;
+
+ /* Check continuous TX and Packet TX */
+ tmpreg = usb_read8(adapt, 0xd03);
+
+ if ((tmpreg&0x70) != 0)
+ usb_write8(adapt, 0xd03, tmpreg&0x8F);
+ else
+ usb_write8(adapt, REG_TXPAUSE, 0xFF);
+
+ if ((tmpreg&0x70) != 0) {
+ /* 1. Read original RF mode */
+ /* Path-A */
+ rf_a_mode = rtw_hal_read_rfreg(adapt, RF_PATH_A, RF_AC,
+ bMask12Bits);
+
+ /* Path-B */
+ if (is2t)
+ rf_b_mode = rtw_hal_read_rfreg(adapt, RF_PATH_B, RF_AC,
+ bMask12Bits);
+
+ /* 2. Set RF mode = standby mode */
+ /* Path-A */
+ phy_set_rf_reg(adapt, RF_PATH_A, RF_AC, bMask12Bits,
+ (rf_a_mode&0x8FFFF)|0x10000);
+
+ /* Path-B */
+ if (is2t)
+ phy_set_rf_reg(adapt, RF_PATH_B, RF_AC, bMask12Bits,
+ (rf_b_mode&0x8FFFF)|0x10000);
+ }
+
+ /* 3. Read RF reg18 */
+ lc_cal = rtw_hal_read_rfreg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits);
+
+ /* 4. Set LC calibration begin bit15 */
+ phy_set_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits,
+ lc_cal|0x08000);
+
+ msleep(100);
+
+ /* Restore original situation */
+ if ((tmpreg&0x70) != 0) {
+ /* Deal with continuous TX case */
+ /* Path-A */
+ usb_write8(adapt, 0xd03, tmpreg);
+ phy_set_rf_reg(adapt, RF_PATH_A, RF_AC, bMask12Bits, rf_a_mode);
+
+ /* Path-B */
+ if (is2t)
+ phy_set_rf_reg(adapt, RF_PATH_B, RF_AC, bMask12Bits,
+ rf_b_mode);
+ } else {
+ /* Deal with Packet TX case */
+ usb_write8(adapt, REG_TXPAUSE, 0x00);
+ }
+}
+
+void rtl88eu_phy_iq_calibrate(struct adapter *adapt, bool recovery)
+{
+ struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
+ s32 result[4][8];
+ u8 i, final;
+ bool pathaok, pathbok;
+ s32 reg_e94, reg_e9c, reg_ea4, reg_eb4, reg_ebc, reg_ec4;
+ bool is12simular, is13simular, is23simular;
+ bool singletone = false, carrier_sup = false;
+ u32 iqk_bb_reg_92c[IQK_BB_REG_NUM] = {
+ rOFDM0_XARxIQImbalance, rOFDM0_XBRxIQImbalance,
+ rOFDM0_ECCAThreshold, rOFDM0_AGCRSSITable,
+ rOFDM0_XATxIQImbalance, rOFDM0_XBTxIQImbalance,
+ rOFDM0_XCTxAFE, rOFDM0_XDTxAFE,
+ rOFDM0_RxIQExtAnta};
+ bool is2t;
+
+ is2t = false;
+
+ if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
+ return;
+
+ if (singletone || carrier_sup)
+ return;
+
+ if (recovery) {
+ ODM_RT_TRACE(dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD,
+ ("phy_iq_calibrate: Return due to recovery!\n"));
+ reload_adda_reg(adapt, iqk_bb_reg_92c,
+ dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
+ return;
+ }
+
+ memset(result, 0, sizeof(result));
+ for (i = 0; i < 8; i += 2)
+ result[3][i] = 0x100;
+
+ final = 0xff;
+ pathaok = false;
+ pathbok = false;
+ is12simular = false;
+ is23simular = false;
+ is13simular = false;
+
+ for (i = 0; i < 3; i++) {
+ phy_iq_calibrate(adapt, result, i, is2t);
+
+ if (i == 1) {
+ is12simular = simularity_compare(adapt, result, 0, 1);
+ if (is12simular) {
+ final = 0;
+ break;
+ }
+ }
+
+ if (i == 2) {
+ is13simular = simularity_compare(adapt, result, 0, 2);
+ if (is13simular) {
+ final = 0;
+ break;
+ }
+ is23simular = simularity_compare(adapt, result, 1, 2);
+ if (is23simular)
+ final = 1;
+ else
+ final = 3;
+ }
+ }
+
+ for (i = 0; i < 4; i++) {
+ reg_e94 = result[i][0];
+ reg_e9c = result[i][1];
+ reg_ea4 = result[i][2];
+ reg_eb4 = result[i][4];
+ reg_ebc = result[i][5];
+ reg_ec4 = result[i][6];
+ }
+
+ if (final != 0xff) {
+ reg_e94 = result[final][0];
+ reg_e9c = result[final][1];
+ reg_ea4 = result[final][2];
+ reg_eb4 = result[final][4];
+ reg_ebc = result[final][5];
+ dm_odm->RFCalibrateInfo.RegE94 = reg_e94;
+ dm_odm->RFCalibrateInfo.RegE9C = reg_e9c;
+ dm_odm->RFCalibrateInfo.RegEB4 = reg_eb4;
+ dm_odm->RFCalibrateInfo.RegEBC = reg_ebc;
+ reg_ec4 = result[final][6];
+ pathaok = true;
+ pathbok = true;
+ } else {
+ ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
+ ("IQK: FAIL use default value\n"));
+ dm_odm->RFCalibrateInfo.RegE94 = 0x100;
+ dm_odm->RFCalibrateInfo.RegEB4 = 0x100;
+ dm_odm->RFCalibrateInfo.RegE9C = 0x0;
+ dm_odm->RFCalibrateInfo.RegEBC = 0x0;
+ }
+ if (reg_e94 != 0)
+ patha_fill_iqk(adapt, pathaok, result, final,
+ (reg_ea4 == 0));
+ if (is2t) {
+ if (reg_eb4 != 0)
+ pathb_fill_iqk(adapt, pathbok, result, final,
+ (reg_ec4 == 0));
+ }
+
+ if (final < 4) {
+ for (i = 0; i < IQK_Matrix_REG_NUM; i++)
+ dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[0].Value[0][i] = result[final][i];
+ dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[0].bIQKDone = true;
+ }
+
+ save_adda_registers(adapt, iqk_bb_reg_92c,
+ dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
+}
+
+void rtl88eu_phy_lc_calibrate(struct adapter *adapt)
+{
+ bool singletone = false, carrier_sup = false;
+ u32 timeout = 2000, timecount = 0;
+ struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
+
+ if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
+ return;
+ if (singletone || carrier_sup)
+ return;
+
+ while (*(dm_odm->pbScanInProcess) && timecount < timeout) {
+ mdelay(50);
+ timecount += 50;
+ }
+
+ dm_odm->RFCalibrateInfo.bLCKInProgress = true;
+
+ phy_lc_calibrate(adapt, false);
+
+ dm_odm->RFCalibrateInfo.bLCKInProgress = false;
+}
diff --git a/drivers/staging/rtl8188eu/hal/pwrseq.c b/drivers/staging/rtl8188eu/hal/pwrseq.c
new file mode 100644
index 0000000..f7890a8
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/pwrseq.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include "pwrseq.h"
+#include <rtl8188e_hal.h>
+
+/* drivers should parse below arrays and do the corresponding actions */
+
+/* 3 Power on Array */
+struct wl_pwr_cfg rtl8188E_power_on_flow[RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS +
+ RTL8188E_TRANS_END_STEPS] = {
+ RTL8188E_TRANS_CARDEMU_TO_ACT
+ RTL8188E_TRANS_END
+};
+
+/* 3Radio off Array */
+struct wl_pwr_cfg rtl8188E_radio_off_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
+ RTL8188E_TRANS_END_STEPS] = {
+ RTL8188E_TRANS_ACT_TO_CARDEMU
+ RTL8188E_TRANS_END
+};
+
+/* 3Card Disable Array */
+struct wl_pwr_cfg rtl8188E_card_disable_flow
+ [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
+ RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS +
+ RTL8188E_TRANS_END_STEPS] = {
+ RTL8188E_TRANS_ACT_TO_CARDEMU
+ RTL8188E_TRANS_CARDEMU_TO_CARDDIS
+ RTL8188E_TRANS_END
+};
+
+/* 3 Card Enable Array */
+struct wl_pwr_cfg rtl8188E_card_enable_flow
+ [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
+ RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS +
+ RTL8188E_TRANS_END_STEPS] = {
+ RTL8188E_TRANS_CARDDIS_TO_CARDEMU
+ RTL8188E_TRANS_CARDEMU_TO_ACT
+ RTL8188E_TRANS_END
+};
+
+/* 3Suspend Array */
+struct wl_pwr_cfg rtl8188E_suspend_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
+ RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS +
+ RTL8188E_TRANS_END_STEPS] = {
+ RTL8188E_TRANS_ACT_TO_CARDEMU
+ RTL8188E_TRANS_CARDEMU_TO_SUS
+ RTL8188E_TRANS_END
+};
+
+/* 3 Resume Array */
+struct wl_pwr_cfg rtl8188E_resume_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
+ RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS +
+ RTL8188E_TRANS_END_STEPS] = {
+ RTL8188E_TRANS_SUS_TO_CARDEMU
+ RTL8188E_TRANS_CARDEMU_TO_ACT
+ RTL8188E_TRANS_END
+};
+
+/* 3HWPDN Array */
+struct wl_pwr_cfg rtl8188E_hwpdn_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
+ RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS +
+ RTL8188E_TRANS_END_STEPS] = {
+ RTL8188E_TRANS_ACT_TO_CARDEMU
+ RTL8188E_TRANS_CARDEMU_TO_PDN
+ RTL8188E_TRANS_END
+};
+
+/* 3 Enter LPS */
+struct wl_pwr_cfg rtl8188E_enter_lps_flow[RTL8188E_TRANS_ACT_TO_LPS_STEPS +
+ RTL8188E_TRANS_END_STEPS] = {
+ /* FW behavior */
+ RTL8188E_TRANS_ACT_TO_LPS
+ RTL8188E_TRANS_END
+};
+
+/* 3 Leave LPS */
+struct wl_pwr_cfg rtl8188E_leave_lps_flow[RTL8188E_TRANS_LPS_TO_ACT_STEPS +
+ RTL8188E_TRANS_END_STEPS] = {
+ /* FW behavior */
+ RTL8188E_TRANS_LPS_TO_ACT
+ RTL8188E_TRANS_END
+};
diff --git a/drivers/staging/rtl8188eu/hal/pwrseqcmd.c b/drivers/staging/rtl8188eu/hal/pwrseqcmd.c
new file mode 100644
index 0000000..249cbc3
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/pwrseqcmd.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include <pwrseqcmd.h>
+#include <usb_ops_linux.h>
+
+/* This routine deals with the Power Configuration CMDs parsing
+ * for RTL8723/RTL8188E Series IC.
+ */
+u8 rtl88eu_pwrseqcmdparsing(struct adapter *padapter, u8 cut_vers,
+ struct wl_pwr_cfg pwrseqcmd[])
+{
+ struct wl_pwr_cfg pwrcfgcmd;
+ u8 poll_bit = false;
+ u32 aryidx = 0;
+ u8 value = 0;
+ u32 offset = 0;
+ u32 poll_count = 0; /* polling autoload done. */
+ u32 max_poll_count = 5000;
+
+ do {
+ pwrcfgcmd = pwrseqcmd[aryidx];
+
+ RT_TRACE(_module_hal_init_c_, _drv_info_,
+ ("rtl88eu_pwrseqcmdparsing: offset(%#x) cut_msk(%#x)"
+ " cmd(%#x)"
+ "msk(%#x) value(%#x)\n",
+ GET_PWR_CFG_OFFSET(pwrcfgcmd),
+ GET_PWR_CFG_CUT_MASK(pwrcfgcmd),
+ GET_PWR_CFG_CMD(pwrcfgcmd),
+ GET_PWR_CFG_MASK(pwrcfgcmd),
+ GET_PWR_CFG_VALUE(pwrcfgcmd)));
+
+ /* Only Handle the command whose CUT is matched */
+ if (GET_PWR_CFG_CUT_MASK(pwrcfgcmd) & cut_vers) {
+ switch (GET_PWR_CFG_CMD(pwrcfgcmd)) {
+ case PWR_CMD_READ:
+ RT_TRACE(_module_hal_init_c_, _drv_info_,
+ ("rtl88eu_pwrseqcmdparsing: PWR_CMD_READ\n"));
+ break;
+ case PWR_CMD_WRITE:
+ RT_TRACE(_module_hal_init_c_, _drv_info_,
+ ("rtl88eu_pwrseqcmdparsing: PWR_CMD_WRITE\n"));
+ offset = GET_PWR_CFG_OFFSET(pwrcfgcmd);
+
+ /* Read the value from system register */
+ value = usb_read8(padapter, offset);
+
+ value &= ~(GET_PWR_CFG_MASK(pwrcfgcmd));
+ value |= (GET_PWR_CFG_VALUE(pwrcfgcmd) &
+ GET_PWR_CFG_MASK(pwrcfgcmd));
+
+ /* Write the value back to system register */
+ usb_write8(padapter, offset, value);
+ break;
+ case PWR_CMD_POLLING:
+ RT_TRACE(_module_hal_init_c_, _drv_info_,
+ ("rtl88eu_pwrseqcmdparsing: PWR_CMD_POLLING\n"));
+
+ poll_bit = false;
+ offset = GET_PWR_CFG_OFFSET(pwrcfgcmd);
+ do {
+ value = usb_read8(padapter, offset);
+ value &= GET_PWR_CFG_MASK(pwrcfgcmd);
+
+ if (value == (GET_PWR_CFG_VALUE(pwrcfgcmd) &
+ GET_PWR_CFG_MASK(pwrcfgcmd)))
+ poll_bit = true;
+ else
+ udelay(10);
+
+ if (poll_count++ > max_poll_count) {
+ DBG_88E("Fail to polling Offset[%#x]\n", offset);
+ return false;
+ }
+ } while (!poll_bit);
+ break;
+ case PWR_CMD_DELAY:
+ RT_TRACE(_module_hal_init_c_, _drv_info_,
+ ("rtl88eu_pwrseqcmdparsing: PWR_CMD_DELAY\n"));
+ if (GET_PWR_CFG_VALUE(pwrcfgcmd) == PWRSEQ_DELAY_US)
+ udelay(GET_PWR_CFG_OFFSET(pwrcfgcmd));
+ else
+ udelay(GET_PWR_CFG_OFFSET(pwrcfgcmd)*1000);
+ break;
+ case PWR_CMD_END:
+ /* When this command is parsed, end the process */
+ RT_TRACE(_module_hal_init_c_, _drv_info_,
+ ("rtl88eu_pwrseqcmdparsing: PWR_CMD_END\n"));
+ return true;
+ default:
+ RT_TRACE(_module_hal_init_c_, _drv_err_,
+ ("rtl88eu_pwrseqcmdparsing: Unknown CMD!!\n"));
+ break;
+ }
+ }
+
+ aryidx++;/* Add Array Index */
+ } while (1);
+ return true;
+}
diff --git a/drivers/staging/rtl8188eu/hal/rf.c b/drivers/staging/rtl8188eu/hal/rf.c
new file mode 100644
index 0000000..6fe4dae
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/rf.c
@@ -0,0 +1,288 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <phy.h>
+#include <rf.h>
+#include <rtl8188e_hal.h>
+
+void rtl88eu_phy_rf6052_set_bandwidth(struct adapter *adapt,
+ enum ht_channel_width bandwidth)
+{
+ struct hal_data_8188e *hal_data = adapt->HalData;
+
+ switch (bandwidth) {
+ case HT_CHANNEL_WIDTH_20:
+ hal_data->RfRegChnlVal[0] = ((hal_data->RfRegChnlVal[0] &
+ 0xfffff3ff) | BIT(10) | BIT(11));
+ phy_set_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask,
+ hal_data->RfRegChnlVal[0]);
+ break;
+ case HT_CHANNEL_WIDTH_40:
+ hal_data->RfRegChnlVal[0] = ((hal_data->RfRegChnlVal[0] &
+ 0xfffff3ff) | BIT(10));
+ phy_set_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask,
+ hal_data->RfRegChnlVal[0]);
+ break;
+ default:
+ break;
+ }
+}
+
+void rtl88eu_phy_rf6052_set_cck_txpower(struct adapter *adapt, u8 *powerlevel)
+{
+ struct hal_data_8188e *hal_data = adapt->HalData;
+ struct dm_priv *pdmpriv = &hal_data->dmpriv;
+ struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
+ u32 tx_agc[2] = {0, 0}, tmpval = 0, pwrtrac_value;
+ u8 idx1, idx2;
+ u8 *ptr;
+ u8 direction;
+
+ if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
+ tx_agc[RF_PATH_A] = 0x3f3f3f3f;
+ tx_agc[RF_PATH_B] = 0x3f3f3f3f;
+ for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
+ tx_agc[idx1] = powerlevel[idx1] |
+ (powerlevel[idx1]<<8) |
+ (powerlevel[idx1]<<16) |
+ (powerlevel[idx1]<<24);
+ }
+ } else {
+ if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1) {
+ tx_agc[RF_PATH_A] = 0x10101010;
+ tx_agc[RF_PATH_B] = 0x10101010;
+ } else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level2) {
+ tx_agc[RF_PATH_A] = 0x00000000;
+ tx_agc[RF_PATH_B] = 0x00000000;
+ } else {
+ for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
+ tx_agc[idx1] = powerlevel[idx1] |
+ (powerlevel[idx1]<<8) |
+ (powerlevel[idx1]<<16) |
+ (powerlevel[idx1]<<24);
+ }
+ if (hal_data->EEPROMRegulatory == 0) {
+ tmpval = hal_data->MCSTxPowerLevelOriginalOffset[0][6] +
+ (hal_data->MCSTxPowerLevelOriginalOffset[0][7]<<8);
+ tx_agc[RF_PATH_A] += tmpval;
+
+ tmpval = hal_data->MCSTxPowerLevelOriginalOffset[0][14] +
+ (hal_data->MCSTxPowerLevelOriginalOffset[0][15]<<24);
+ tx_agc[RF_PATH_B] += tmpval;
+ }
+ }
+ }
+ for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
+ ptr = (u8 *)(&(tx_agc[idx1]));
+ for (idx2 = 0; idx2 < 4; idx2++) {
+ if (*ptr > RF6052_MAX_TX_PWR)
+ *ptr = RF6052_MAX_TX_PWR;
+ ptr++;
+ }
+ }
+ rtl88eu_dm_txpower_track_adjust(&hal_data->odmpriv, 1, &direction,
+ &pwrtrac_value);
+
+ if (direction == 1) {
+ /* Increase TX power */
+ tx_agc[0] += pwrtrac_value;
+ tx_agc[1] += pwrtrac_value;
+ } else if (direction == 2) {
+ /* Decrease TX power */
+ tx_agc[0] -= pwrtrac_value;
+ tx_agc[1] -= pwrtrac_value;
+ }
+
+ /* rf-A cck tx power */
+ tmpval = tx_agc[RF_PATH_A]&0xff;
+ phy_set_bb_reg(adapt, rTxAGC_A_CCK1_Mcs32, bMaskByte1, tmpval);
+ tmpval = tx_agc[RF_PATH_A]>>8;
+ phy_set_bb_reg(adapt, rTxAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
+
+ /* rf-B cck tx power */
+ tmpval = tx_agc[RF_PATH_B]>>24;
+ phy_set_bb_reg(adapt, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte0, tmpval);
+ tmpval = tx_agc[RF_PATH_B]&0x00ffffff;
+ phy_set_bb_reg(adapt, rTxAGC_B_CCK1_55_Mcs32, 0xffffff00, tmpval);
+}
+
+/* powerbase0 for OFDM rates */
+/* powerbase1 for HT MCS rates */
+static void getpowerbase88e(struct adapter *adapt, u8 *pwr_level_ofdm,
+ u8 *pwr_level_bw20, u8 *pwr_level_bw40,
+ u8 channel, u32 *ofdmbase, u32 *mcs_base)
+{
+ u32 powerbase0, powerbase1;
+ u8 i, powerlevel[2];
+
+ for (i = 0; i < 2; i++) {
+ powerbase0 = pwr_level_ofdm[i];
+
+ powerbase0 = (powerbase0<<24) | (powerbase0<<16) |
+ (powerbase0<<8) | powerbase0;
+ *(ofdmbase+i) = powerbase0;
+ }
+ /* Check HT20 to HT40 diff */
+ if (adapt->HalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
+ powerlevel[0] = pwr_level_bw20[0];
+ else
+ powerlevel[0] = pwr_level_bw40[0];
+ powerbase1 = powerlevel[0];
+ powerbase1 = (powerbase1<<24) | (powerbase1<<16) |
+ (powerbase1<<8) | powerbase1;
+ *mcs_base = powerbase1;
+}
+static void get_rx_power_val_by_reg(struct adapter *adapt, u8 channel,
+ u8 index, u32 *powerbase0, u32 *powerbase1,
+ u32 *out_val)
+{
+ struct hal_data_8188e *hal_data = adapt->HalData;
+ struct dm_priv *pdmpriv = &hal_data->dmpriv;
+ u8 i, chnlGroup = 0, pwr_diff_limit[4], customer_pwr_limit;
+ s8 pwr_diff = 0;
+ u32 write_val, customer_limit, rf;
+ u8 regulatory = hal_data->EEPROMRegulatory;
+
+ /* Index 0 & 1= legacy OFDM, 2-5=HT_MCS rate */
+
+ for (rf = 0; rf < 2; rf++) {
+ u8 j = index + (rf ? 8 : 0);
+
+ switch (regulatory) {
+ case 0:
+ chnlGroup = 0;
+ write_val = hal_data->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf ? 8 : 0)] +
+ ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
+ break;
+ case 1: /* Realtek regulatory */
+ /* increase power diff defined by Realtek for regulatory */
+ if (hal_data->pwrGroupCnt == 1)
+ chnlGroup = 0;
+ if (hal_data->pwrGroupCnt >= hal_data->PGMaxGroup)
+ Hal_GetChnlGroup88E(channel, &chnlGroup);
+
+ write_val = hal_data->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf ? 8 : 0)] +
+ ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
+ break;
+ case 2: /* Better regulatory */
+ /* don't increase any power diff */
+ write_val = (index < 2) ? powerbase0[rf] : powerbase1[rf];
+ break;
+ case 3: /* Customer defined power diff. */
+ /* increase power diff defined by customer. */
+ chnlGroup = 0;
+
+ if (index < 2)
+ pwr_diff = hal_data->TxPwrLegacyHtDiff[rf][channel-1];
+ else if (hal_data->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
+ pwr_diff = hal_data->TxPwrHt20Diff[rf][channel-1];
+
+ if (hal_data->CurrentChannelBW == HT_CHANNEL_WIDTH_40)
+ customer_pwr_limit = hal_data->PwrGroupHT40[rf][channel-1];
+ else
+ customer_pwr_limit = hal_data->PwrGroupHT20[rf][channel-1];
+
+ if (pwr_diff >= customer_pwr_limit)
+ pwr_diff = 0;
+ else
+ pwr_diff = customer_pwr_limit - pwr_diff;
+
+ for (i = 0; i < 4; i++) {
+ pwr_diff_limit[i] = (u8)((hal_data->MCSTxPowerLevelOriginalOffset[chnlGroup][j] &
+ (0x7f << (i * 8))) >> (i * 8));
+
+ if (pwr_diff_limit[i] > pwr_diff)
+ pwr_diff_limit[i] = pwr_diff;
+ }
+ customer_limit = (pwr_diff_limit[3]<<24) |
+ (pwr_diff_limit[2]<<16) |
+ (pwr_diff_limit[1]<<8) |
+ (pwr_diff_limit[0]);
+ write_val = customer_limit + ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
+ break;
+ default:
+ chnlGroup = 0;
+ write_val = hal_data->MCSTxPowerLevelOriginalOffset[chnlGroup][j] +
+ ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
+ break;
+ }
+/* 20100427 Joseph: Driver dynamic Tx power shall not affect Tx power. It shall be determined by power training mechanism. */
+/* Currently, we cannot fully disable driver dynamic tx power mechanism because it is referenced by BT coexist mechanism. */
+/* In the future, two mechanism shall be separated from each other and maintained independently. Thanks for Lanhsin's reminder. */
+ /* 92d do not need this */
+ if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1)
+ write_val = 0x14141414;
+ else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level2)
+ write_val = 0x00000000;
+
+ *(out_val+rf) = write_val;
+ }
+}
+
+static void write_ofdm_pwr_reg(struct adapter *adapt, u8 index, u32 *pvalue)
+{
+ u16 regoffset_a[6] = { rTxAGC_A_Rate18_06, rTxAGC_A_Rate54_24,
+ rTxAGC_A_Mcs03_Mcs00, rTxAGC_A_Mcs07_Mcs04,
+ rTxAGC_A_Mcs11_Mcs08, rTxAGC_A_Mcs15_Mcs12 };
+ u16 regoffset_b[6] = { rTxAGC_B_Rate18_06, rTxAGC_B_Rate54_24,
+ rTxAGC_B_Mcs03_Mcs00, rTxAGC_B_Mcs07_Mcs04,
+ rTxAGC_B_Mcs11_Mcs08, rTxAGC_B_Mcs15_Mcs12 };
+ u8 i, rf, pwr_val[4];
+ u32 write_val;
+ u16 regoffset;
+
+ for (rf = 0; rf < 2; rf++) {
+ write_val = pvalue[rf];
+ for (i = 0; i < 4; i++) {
+ pwr_val[i] = (u8)((write_val & (0x7f<<(i*8)))>>(i*8));
+ if (pwr_val[i] > RF6052_MAX_TX_PWR)
+ pwr_val[i] = RF6052_MAX_TX_PWR;
+ }
+ write_val = (pwr_val[3]<<24) | (pwr_val[2]<<16) |
+ (pwr_val[1]<<8) | pwr_val[0];
+
+ if (rf == 0)
+ regoffset = regoffset_a[index];
+ else
+ regoffset = regoffset_b[index];
+
+ phy_set_bb_reg(adapt, regoffset, bMaskDWord, write_val);
+ }
+}
+
+void rtl88eu_phy_rf6052_set_ofdm_txpower(struct adapter *adapt,
+ u8 *pwr_level_ofdm,
+ u8 *pwr_level_bw20,
+ u8 *pwr_level_bw40, u8 channel)
+{
+ u32 write_val[2], powerbase0[2], powerbase1[2], pwrtrac_value;
+ u8 direction;
+ u8 index = 0;
+
+ getpowerbase88e(adapt, pwr_level_ofdm, pwr_level_bw20, pwr_level_bw40,
+ channel, &powerbase0[0], &powerbase1[0]);
+
+ rtl88eu_dm_txpower_track_adjust(&adapt->HalData->odmpriv, 0,
+ &direction, &pwrtrac_value);
+
+ for (index = 0; index < 6; index++) {
+ get_rx_power_val_by_reg(adapt, channel, index,
+ &powerbase0[0], &powerbase1[0],
+ &write_val[0]);
+
+ if (direction == 1) {
+ write_val[0] += pwrtrac_value;
+ write_val[1] += pwrtrac_value;
+ } else if (direction == 2) {
+ write_val[0] -= pwrtrac_value;
+ write_val[1] -= pwrtrac_value;
+ }
+ write_ofdm_pwr_reg(adapt, index, &write_val[0]);
+ }
+}
diff --git a/drivers/staging/rtl8188eu/hal/rf_cfg.c b/drivers/staging/rtl8188eu/hal/rf_cfg.c
new file mode 100644
index 0000000..47b1bf5
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/rf_cfg.c
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include "odm_precomp.h"
+
+#include <phy.h>
+
+static bool check_condition(struct adapter *adapt, const u32 condition)
+{
+ struct odm_dm_struct *odm = &adapt->HalData->odmpriv;
+ u32 _board = odm->BoardType;
+ u32 _platform = odm->SupportPlatform;
+ u32 _interface = odm->SupportInterface;
+ u32 cond = condition;
+
+ if (condition == 0xCDCDCDCD)
+ return true;
+
+ cond = condition & 0x000000FF;
+ if ((_board == cond) && cond != 0x00)
+ return false;
+
+ cond = condition & 0x0000FF00;
+ cond >>= 8;
+ if ((_interface & cond) == 0 && cond != 0x07)
+ return false;
+
+ cond = condition & 0x00FF0000;
+ cond >>= 16;
+ if ((_platform & cond) == 0 && cond != 0x0F)
+ return false;
+ return true;
+}
+
+/* RadioA_1T.TXT */
+
+static u32 Array_RadioA_1T_8188E[] = {
+ 0x000, 0x00030000,
+ 0x008, 0x00084000,
+ 0x018, 0x00000407,
+ 0x019, 0x00000012,
+ 0x01E, 0x00080009,
+ 0x01F, 0x00000880,
+ 0x02F, 0x0001A060,
+ 0x03F, 0x00000000,
+ 0x042, 0x000060C0,
+ 0x057, 0x000D0000,
+ 0x058, 0x000BE180,
+ 0x067, 0x00001552,
+ 0x083, 0x00000000,
+ 0x0B0, 0x000FF8FC,
+ 0x0B1, 0x00054400,
+ 0x0B2, 0x000CCC19,
+ 0x0B4, 0x00043003,
+ 0x0B6, 0x0004953E,
+ 0x0B7, 0x0001C718,
+ 0x0B8, 0x000060FF,
+ 0x0B9, 0x00080001,
+ 0x0BA, 0x00040000,
+ 0x0BB, 0x00000400,
+ 0x0BF, 0x000C0000,
+ 0x0C2, 0x00002400,
+ 0x0C3, 0x00000009,
+ 0x0C4, 0x00040C91,
+ 0x0C5, 0x00099999,
+ 0x0C6, 0x000000A3,
+ 0x0C7, 0x00088820,
+ 0x0C8, 0x00076C06,
+ 0x0C9, 0x00000000,
+ 0x0CA, 0x00080000,
+ 0x0DF, 0x00000180,
+ 0x0EF, 0x000001A0,
+ 0x051, 0x0006B27D,
+ 0xFF0F041F, 0xABCD,
+ 0x052, 0x0007E4DD,
+ 0xCDCDCDCD, 0xCDCD,
+ 0x052, 0x0007E49D,
+ 0xFF0F041F, 0xDEAD,
+ 0x053, 0x00000073,
+ 0x056, 0x00051FF3,
+ 0x035, 0x00000086,
+ 0x035, 0x00000186,
+ 0x035, 0x00000286,
+ 0x036, 0x00001C25,
+ 0x036, 0x00009C25,
+ 0x036, 0x00011C25,
+ 0x036, 0x00019C25,
+ 0x0B6, 0x00048538,
+ 0x018, 0x00000C07,
+ 0x05A, 0x0004BD00,
+ 0x019, 0x000739D0,
+ 0x034, 0x0000ADF3,
+ 0x034, 0x00009DF0,
+ 0x034, 0x00008DED,
+ 0x034, 0x00007DEA,
+ 0x034, 0x00006DE7,
+ 0x034, 0x000054EE,
+ 0x034, 0x000044EB,
+ 0x034, 0x000034E8,
+ 0x034, 0x0000246B,
+ 0x034, 0x00001468,
+ 0x034, 0x0000006D,
+ 0x000, 0x00030159,
+ 0x084, 0x00068200,
+ 0x086, 0x000000CE,
+ 0x087, 0x00048A00,
+ 0x08E, 0x00065540,
+ 0x08F, 0x00088000,
+ 0x0EF, 0x000020A0,
+ 0x03B, 0x000F02B0,
+ 0x03B, 0x000EF7B0,
+ 0x03B, 0x000D4FB0,
+ 0x03B, 0x000CF060,
+ 0x03B, 0x000B0090,
+ 0x03B, 0x000A0080,
+ 0x03B, 0x00090080,
+ 0x03B, 0x0008F780,
+ 0x03B, 0x000722B0,
+ 0x03B, 0x0006F7B0,
+ 0x03B, 0x00054FB0,
+ 0x03B, 0x0004F060,
+ 0x03B, 0x00030090,
+ 0x03B, 0x00020080,
+ 0x03B, 0x00010080,
+ 0x03B, 0x0000F780,
+ 0x0EF, 0x000000A0,
+ 0x000, 0x00010159,
+ 0x018, 0x0000F407,
+ 0xFFE, 0x00000000,
+ 0xFFE, 0x00000000,
+ 0x01F, 0x00080003,
+ 0xFFE, 0x00000000,
+ 0xFFE, 0x00000000,
+ 0x01E, 0x00000001,
+ 0x01F, 0x00080000,
+ 0x000, 0x00033E60,
+};
+
+#define READ_NEXT_PAIR(v1, v2, i) \
+do { \
+ i += 2; v1 = array[i]; \
+ v2 = array[i+1]; \
+} while (0)
+
+#define RFREG_OFFSET_MASK 0xfffff
+#define B3WIREADDREAALENGTH 0x400
+#define B3WIREDATALENGTH 0x800
+#define BRFSI_RFENV 0x10
+
+static void rtl_rfreg_delay(struct adapter *adapt, enum rf_radio_path rfpath, u32 addr, u32 mask, u32 data)
+{
+ if (addr == 0xfe) {
+ mdelay(50);
+ } else if (addr == 0xfd) {
+ mdelay(5);
+ } else if (addr == 0xfc) {
+ mdelay(1);
+ } else if (addr == 0xfb) {
+ udelay(50);
+ } else if (addr == 0xfa) {
+ udelay(5);
+ } else if (addr == 0xf9) {
+ udelay(1);
+ } else {
+ phy_set_rf_reg(adapt, rfpath, addr, mask, data);
+ udelay(1);
+ }
+}
+
+static void rtl8188e_config_rf_reg(struct adapter *adapt,
+ u32 addr, u32 data)
+{
+ u32 content = 0x1000; /*RF Content: radio_a_txt*/
+ u32 maskforphyset = content & 0xE000;
+
+ rtl_rfreg_delay(adapt, RF_PATH_A, addr | maskforphyset,
+ RFREG_OFFSET_MASK,
+ data);
+}
+
+static bool rtl88e_phy_config_rf_with_headerfile(struct adapter *adapt)
+{
+ u32 i;
+ u32 array_len = ARRAY_SIZE(Array_RadioA_1T_8188E);
+ u32 *array = Array_RadioA_1T_8188E;
+
+ for (i = 0; i < array_len; i += 2) {
+ u32 v1 = array[i];
+ u32 v2 = array[i+1];
+
+ if (v1 < 0xCDCDCDCD) {
+ rtl8188e_config_rf_reg(adapt, v1, v2);
+ continue;
+ } else {
+ if (!check_condition(adapt, array[i])) {
+ READ_NEXT_PAIR(v1, v2, i);
+ while (v2 != 0xDEAD && v2 != 0xCDEF &&
+ v2 != 0xCDCD && i < array_len - 2)
+ READ_NEXT_PAIR(v1, v2, i);
+ i -= 2;
+ } else {
+ READ_NEXT_PAIR(v1, v2, i);
+ while (v2 != 0xDEAD && v2 != 0xCDEF &&
+ v2 != 0xCDCD && i < array_len - 2) {
+ rtl8188e_config_rf_reg(adapt, v1, v2);
+ READ_NEXT_PAIR(v1, v2, i);
+ }
+
+ while (v2 != 0xDEAD && i < array_len - 2)
+ READ_NEXT_PAIR(v1, v2, i);
+ }
+ }
+ }
+ return true;
+}
+
+bool rtl88eu_phy_rf_config(struct adapter *adapt)
+{
+ struct hal_data_8188e *hal_data = adapt->HalData;
+ u32 u4val = 0;
+ bool rtstatus;
+ struct bb_reg_def *pphyreg;
+
+ pphyreg = &hal_data->PHYRegDef[RF90_PATH_A];
+ u4val = phy_query_bb_reg(adapt, pphyreg->rfintfs, BRFSI_RFENV);
+
+ phy_set_bb_reg(adapt, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
+ udelay(1);
+
+ phy_set_bb_reg(adapt, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
+ udelay(1);
+
+ phy_set_bb_reg(adapt, pphyreg->rfHSSIPara2, B3WIREADDREAALENGTH, 0x0);
+ udelay(1);
+
+ phy_set_bb_reg(adapt, pphyreg->rfHSSIPara2, B3WIREDATALENGTH, 0x0);
+ udelay(1);
+
+ rtstatus = rtl88e_phy_config_rf_with_headerfile(adapt);
+
+ phy_set_bb_reg(adapt, pphyreg->rfintfs, BRFSI_RFENV, u4val);
+
+ return rtstatus;
+}
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
new file mode 100644
index 0000000..47352f2
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
@@ -0,0 +1,633 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _RTL8188E_CMD_C_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <recv_osdep.h>
+#include <mlme_osdep.h>
+#include <rtw_ioctl_set.h>
+
+#include <rtl8188e_hal.h>
+
+#define RTL88E_MAX_H2C_BOX_NUMS 4
+#define RTL88E_MAX_CMD_LEN 7
+#define RTL88E_MESSAGE_BOX_SIZE 4
+#define RTL88E_EX_MESSAGE_BOX_SIZE 4
+
+static u8 _is_fw_read_cmd_down(struct adapter *adapt, u8 msgbox_num)
+{
+ u8 read_down = false;
+ int retry_cnts = 100;
+
+ u8 valid;
+
+ do {
+ valid = usb_read8(adapt, REG_HMETFR) & BIT(msgbox_num);
+ if (valid == 0)
+ read_down = true;
+ } while ((!read_down) && (retry_cnts--));
+
+ return read_down;
+}
+
+/*****************************************
+* H2C Msg format :
+* 0x1DF - 0x1D0
+*| 31 - 8 | 7-5 4 - 0 |
+*| h2c_msg |Class_ID CMD_ID |
+*
+* Extend 0x1FF - 0x1F0
+*|31 - 0 |
+*|ext_msg|
+******************************************/
+static s32 FillH2CCmd_88E(struct adapter *adapt, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer)
+{
+ u8 bcmd_down = false;
+ s32 retry_cnts = 100;
+ u8 h2c_box_num;
+ u32 msgbox_addr;
+ u32 msgbox_ex_addr;
+ u8 cmd_idx, ext_cmd_len;
+ u32 h2c_cmd = 0;
+ u32 h2c_cmd_ex = 0;
+ s32 ret = _FAIL;
+
+ if (!adapt->bFWReady) {
+ DBG_88E("%s(): return H2C cmd because fw is not ready\n",
+ __func__);
+ return ret;
+ }
+
+ if (!pCmdBuffer)
+ goto exit;
+ if (CmdLen > RTL88E_MAX_CMD_LEN)
+ goto exit;
+ if (adapt->bSurpriseRemoved)
+ goto exit;
+
+ /* pay attention to if race condition happened in H2C cmd setting. */
+ do {
+ h2c_box_num = adapt->HalData->LastHMEBoxNum;
+
+ if (!_is_fw_read_cmd_down(adapt, h2c_box_num)) {
+ DBG_88E(" fw read cmd failed...\n");
+ goto exit;
+ }
+
+ *(u8 *)(&h2c_cmd) = ElementID;
+
+ if (CmdLen <= 3) {
+ memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, CmdLen);
+ } else {
+ memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, 3);
+ ext_cmd_len = CmdLen-3;
+ memcpy((u8 *)(&h2c_cmd_ex), pCmdBuffer+3, ext_cmd_len);
+
+ /* Write Ext command */
+ msgbox_ex_addr = REG_HMEBOX_EXT_0 + (h2c_box_num * RTL88E_EX_MESSAGE_BOX_SIZE);
+ for (cmd_idx = 0; cmd_idx < ext_cmd_len; cmd_idx++)
+ usb_write8(adapt, msgbox_ex_addr+cmd_idx, *((u8 *)(&h2c_cmd_ex)+cmd_idx));
+ }
+ /* Write command */
+ msgbox_addr = REG_HMEBOX_0 + (h2c_box_num * RTL88E_MESSAGE_BOX_SIZE);
+ for (cmd_idx = 0; cmd_idx < RTL88E_MESSAGE_BOX_SIZE; cmd_idx++)
+ usb_write8(adapt, msgbox_addr+cmd_idx, *((u8 *)(&h2c_cmd)+cmd_idx));
+
+ bcmd_down = true;
+
+ adapt->HalData->LastHMEBoxNum =
+ (h2c_box_num+1) % RTL88E_MAX_H2C_BOX_NUMS;
+
+ } while ((!bcmd_down) && (retry_cnts--));
+
+ ret = _SUCCESS;
+
+exit:
+ return ret;
+}
+
+/* bitmap[0:27] = tx_rate_bitmap */
+/* bitmap[28:31]= Rate Adaptive id */
+/* arg[0:4] = macid */
+/* arg[5] = Short GI */
+void rtw_hal_add_ra_tid(struct adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_level)
+{
+ struct odm_dm_struct *odmpriv = &pAdapter->HalData->odmpriv;
+ u8 macid, init_rate, raid, shortGIrate = false;
+
+ macid = arg&0x1f;
+
+ raid = (bitmap>>28) & 0x0f;
+ bitmap &= 0x0fffffff;
+
+ if (rssi_level != DM_RATR_STA_INIT)
+ bitmap = ODM_Get_Rate_Bitmap(odmpriv, macid, bitmap, rssi_level);
+
+ bitmap |= ((raid<<28)&0xf0000000);
+
+ init_rate = get_highest_rate_idx(bitmap&0x0fffffff)&0x3f;
+
+ shortGIrate = (arg & BIT(5)) ? true : false;
+
+ if (shortGIrate)
+ init_rate |= BIT(6);
+
+ raid = (bitmap>>28) & 0x0f;
+
+ bitmap &= 0x0fffffff;
+
+ DBG_88E("%s=> mac_id:%d, raid:%d, ra_bitmap=0x%x, shortGIrate=0x%02x\n",
+ __func__, macid, raid, bitmap, shortGIrate);
+
+ ODM_RA_UpdateRateInfo_8188E(odmpriv, macid, raid, bitmap, shortGIrate);
+}
+
+void rtl8188e_set_FwPwrMode_cmd(struct adapter *adapt, u8 Mode)
+{
+ struct setpwrmode_parm H2CSetPwrMode;
+ struct pwrctrl_priv *pwrpriv = &adapt->pwrctrlpriv;
+ u8 RLBM = 0; /* 0:Min, 1:Max, 2:User define */
+
+ DBG_88E("%s: Mode=%d SmartPS=%d UAPSD=%d\n", __func__,
+ Mode, pwrpriv->smart_ps, adapt->registrypriv.uapsd_enable);
+
+ switch (Mode) {
+ case PS_MODE_ACTIVE:
+ H2CSetPwrMode.Mode = 0;
+ break;
+ case PS_MODE_MIN:
+ H2CSetPwrMode.Mode = 1;
+ break;
+ case PS_MODE_MAX:
+ RLBM = 1;
+ H2CSetPwrMode.Mode = 1;
+ break;
+ case PS_MODE_DTIM:
+ RLBM = 2;
+ H2CSetPwrMode.Mode = 1;
+ break;
+ case PS_MODE_UAPSD_WMM:
+ H2CSetPwrMode.Mode = 2;
+ break;
+ default:
+ H2CSetPwrMode.Mode = 0;
+ break;
+ }
+
+ H2CSetPwrMode.SmartPS_RLBM = (((pwrpriv->smart_ps<<4)&0xf0) | (RLBM & 0x0f));
+
+ H2CSetPwrMode.AwakeInterval = 1;
+
+ H2CSetPwrMode.bAllQueueUAPSD = adapt->registrypriv.uapsd_enable;
+
+ if (Mode > 0)
+ H2CSetPwrMode.PwrState = 0x00;/* AllON(0x0C), RFON(0x04), RFOFF(0x00) */
+ else
+ H2CSetPwrMode.PwrState = 0x0C;/* AllON(0x0C), RFON(0x04), RFOFF(0x00) */
+
+ FillH2CCmd_88E(adapt, H2C_PS_PWR_MODE, sizeof(H2CSetPwrMode), (u8 *)&H2CSetPwrMode);
+}
+
+void rtl8188e_set_FwMediaStatus_cmd(struct adapter *adapt, __le16 mstatus_rpt)
+{
+ u8 opmode, macid;
+ u16 mst_rpt = le16_to_cpu(mstatus_rpt);
+
+ opmode = (u8)mst_rpt;
+ macid = (u8)(mst_rpt >> 8);
+
+ DBG_88E("### %s: MStatus=%x MACID=%d\n", __func__, opmode, macid);
+ FillH2CCmd_88E(adapt, H2C_COM_MEDIA_STATUS_RPT, sizeof(mst_rpt), (u8 *)&mst_rpt);
+}
+
+static void ConstructBeacon(struct adapter *adapt, u8 *pframe, u32 *pLength)
+{
+ struct ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ u32 rate_len, pktlen;
+ struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
+ u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ pwlanhdr = (struct ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_control;
+ *(fctrl) = 0;
+
+ ether_addr_copy(pwlanhdr->addr1, bc_addr);
+ ether_addr_copy(pwlanhdr->addr2, myid(&adapt->eeprompriv));
+ ether_addr_copy(pwlanhdr->addr3, cur_network->MacAddress);
+
+ SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
+ SetFrameSubType(pframe, WIFI_BEACON);
+
+ pframe += sizeof(struct ieee80211_hdr_3addr);
+ pktlen = sizeof(struct ieee80211_hdr_3addr);
+
+ /* timestamp will be inserted by hardware */
+ pframe += 8;
+ pktlen += 8;
+
+ /* beacon interval: 2 bytes */
+ memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->ies)), 2);
+
+ pframe += 2;
+ pktlen += 2;
+
+ /* capability info: 2 bytes */
+ memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->ies)), 2);
+
+ pframe += 2;
+ pktlen += 2;
+
+ if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
+ pktlen += cur_network->ie_length - sizeof(struct ndis_802_11_fixed_ie);
+ memcpy(pframe, cur_network->ies+sizeof(struct ndis_802_11_fixed_ie), pktlen);
+
+ goto _ConstructBeacon;
+ }
+
+ /* below for ad-hoc mode */
+
+ /* SSID */
+ pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->ssid.ssid_length, cur_network->ssid.ssid, &pktlen);
+
+ /* supported rates... */
+ rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, min_t(u32, rate_len, 8), cur_network->SupportedRates, &pktlen);
+
+ /* DS parameter set */
+ pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pktlen);
+
+ if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
+ u32 ATIMWindow;
+ /* IBSS Parameter Set... */
+ ATIMWindow = 0;
+ pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen);
+ }
+
+ /* todo: ERP IE */
+
+ /* EXTERNDED SUPPORTED RATE */
+ if (rate_len > 8)
+ pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen);
+
+ /* todo:HT for adhoc */
+
+_ConstructBeacon:
+
+ if ((pktlen + TXDESC_SIZE) > 512) {
+ DBG_88E("beacon frame too large\n");
+ return;
+ }
+
+ *pLength = pktlen;
+}
+
+static void ConstructPSPoll(struct adapter *adapt, u8 *pframe, u32 *pLength)
+{
+ struct ieee80211_hdr *pwlanhdr;
+ struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ __le16 *fctrl;
+ struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
+
+ pwlanhdr = (struct ieee80211_hdr *)pframe;
+
+ /* Frame control. */
+ fctrl = &pwlanhdr->frame_control;
+ *(fctrl) = 0;
+ SetPwrMgt(fctrl);
+ SetFrameSubType(pframe, WIFI_PSPOLL);
+
+ /* AID. */
+ SetDuration(pframe, (pmlmeinfo->aid | 0xc000));
+
+ /* BSSID. */
+ ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress);
+
+ /* TA. */
+ ether_addr_copy(pwlanhdr->addr2, myid(&adapt->eeprompriv));
+
+ *pLength = 16;
+}
+
+static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe,
+ u32 *pLength,
+ u8 *StaAddr,
+ u8 bQoS,
+ u8 AC,
+ u8 bEosp,
+ u8 bForcePowerSave)
+{
+ struct ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ u32 pktlen;
+ struct mlme_priv *pmlmepriv = &adapt->mlmepriv;
+ struct wlan_network *cur_network = &pmlmepriv->cur_network;
+ struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
+
+ pwlanhdr = (struct ieee80211_hdr *)pframe;
+
+ fctrl = &pwlanhdr->frame_control;
+ *(fctrl) = 0;
+ if (bForcePowerSave)
+ SetPwrMgt(fctrl);
+
+ switch (cur_network->network.InfrastructureMode) {
+ case Ndis802_11Infrastructure:
+ SetToDs(fctrl);
+ ether_addr_copy(pwlanhdr->addr1, pnetwork->MacAddress);
+ ether_addr_copy(pwlanhdr->addr2, myid(&adapt->eeprompriv));
+ ether_addr_copy(pwlanhdr->addr3, StaAddr);
+ break;
+ case Ndis802_11APMode:
+ SetFrDs(fctrl);
+ ether_addr_copy(pwlanhdr->addr1, StaAddr);
+ ether_addr_copy(pwlanhdr->addr2, pnetwork->MacAddress);
+ ether_addr_copy(pwlanhdr->addr3, myid(&adapt->eeprompriv));
+ break;
+ case Ndis802_11IBSS:
+ default:
+ ether_addr_copy(pwlanhdr->addr1, StaAddr);
+ ether_addr_copy(pwlanhdr->addr2, myid(&adapt->eeprompriv));
+ ether_addr_copy(pwlanhdr->addr3, pnetwork->MacAddress);
+ break;
+ }
+
+ SetSeqNum(pwlanhdr, 0);
+
+ if (bQoS) {
+ struct ieee80211_qos_hdr *pwlanqoshdr;
+
+ SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
+
+ pwlanqoshdr = (struct ieee80211_qos_hdr *)pframe;
+ SetPriority(&pwlanqoshdr->qos_ctrl, AC);
+ SetEOSP(&pwlanqoshdr->qos_ctrl, bEosp);
+
+ pktlen = sizeof(struct ieee80211_qos_hdr);
+ } else {
+ SetFrameSubType(pframe, WIFI_DATA_NULL);
+
+ pktlen = sizeof(struct ieee80211_hdr_3addr);
+ }
+
+ *pLength = pktlen;
+}
+
+static void ConstructProbeRsp(struct adapter *adapt, u8 *pframe, u32 *pLength, u8 *StaAddr, bool bHideSSID)
+{
+ struct ieee80211_hdr *pwlanhdr;
+ __le16 *fctrl;
+ u8 *mac, *bssid;
+ u32 pktlen;
+ struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
+
+ pwlanhdr = (struct ieee80211_hdr *)pframe;
+
+ mac = myid(&adapt->eeprompriv);
+ bssid = cur_network->MacAddress;
+
+ fctrl = &pwlanhdr->frame_control;
+ *(fctrl) = 0;
+ ether_addr_copy(pwlanhdr->addr1, StaAddr);
+ ether_addr_copy(pwlanhdr->addr2, mac);
+ ether_addr_copy(pwlanhdr->addr3, bssid);
+
+ SetSeqNum(pwlanhdr, 0);
+ SetFrameSubType(fctrl, WIFI_PROBERSP);
+
+ pktlen = sizeof(struct ieee80211_hdr_3addr);
+ pframe += pktlen;
+
+ if (cur_network->ie_length > MAX_IE_SZ)
+ return;
+
+ memcpy(pframe, cur_network->ies, cur_network->ie_length);
+ pframe += cur_network->ie_length;
+ pktlen += cur_network->ie_length;
+
+ *pLength = pktlen;
+}
+
+/* */
+/* Description: Fill the reserved packets that FW will use to RSVD page. */
+/* Now we just send 4 types packet to rsvd page. */
+/* (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp. */
+/* Input: */
+/* bDLFinished - false: At the first time we will send all the packets as a large packet to Hw, */
+/* so we need to set the packet length to total length. */
+/* true: At the second time, we should send the first packet (default:beacon) */
+/* to Hw again and set the length in descriptor to the real beacon length. */
+/* 2009.10.15 by tynli. */
+static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ struct xmit_priv *pxmitpriv;
+ struct mlme_ext_priv *pmlmeext;
+ struct mlme_ext_info *pmlmeinfo;
+ u32 BeaconLength = 0, ProbeRspLength = 0, PSPollLength;
+ u32 NullDataLength, QosNullLength;
+ u8 *ReservedPagePacket;
+ u8 PageNum, PageNeed, TxDescLen;
+ u16 BufIndex;
+ u32 TotalPacketLen;
+ struct rsvdpage_loc RsvdPageLoc;
+ struct wlan_bssid_ex *pnetwork;
+
+ DBG_88E("%s\n", __func__);
+ ReservedPagePacket = kzalloc(1000, GFP_KERNEL);
+ if (!ReservedPagePacket) {
+ DBG_88E("%s: alloc ReservedPagePacket fail!\n", __func__);
+ return;
+ }
+
+ pxmitpriv = &adapt->xmitpriv;
+ pmlmeext = &adapt->mlmeextpriv;
+ pmlmeinfo = &pmlmeext->mlmext_info;
+ pnetwork = &pmlmeinfo->network;
+
+ TxDescLen = TXDESC_SIZE;
+ PageNum = 0;
+
+ /* 3 (1) beacon * 2 pages */
+ BufIndex = TXDESC_OFFSET;
+ ConstructBeacon(adapt, &ReservedPagePacket[BufIndex], &BeaconLength);
+
+ /* When we count the first page size, we need to reserve description size for the RSVD */
+ /* packet, it will be filled in front of the packet in TXPKTBUF. */
+ PageNeed = (u8)PageNum_128(TxDescLen + BeaconLength);
+ /* To reserved 2 pages for beacon buffer. 2010.06.24. */
+ if (PageNeed == 1)
+ PageNeed += 1;
+ PageNum += PageNeed;
+ adapt->HalData->FwRsvdPageStartOffset = PageNum;
+
+ BufIndex += PageNeed * 128;
+
+ /* 3 (2) ps-poll *1 page */
+ RsvdPageLoc.LocPsPoll = PageNum;
+ ConstructPSPoll(adapt, &ReservedPagePacket[BufIndex], &PSPollLength);
+ rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, true, false);
+
+ PageNeed = (u8)PageNum_128(TxDescLen + PSPollLength);
+ PageNum += PageNeed;
+
+ BufIndex += PageNeed * 128;
+
+ /* 3 (3) null data * 1 page */
+ RsvdPageLoc.LocNullData = PageNum;
+ ConstructNullFunctionData(adapt, &ReservedPagePacket[BufIndex], &NullDataLength, pnetwork->MacAddress, false, 0, 0, false);
+ rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false);
+
+ PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
+ PageNum += PageNeed;
+
+ BufIndex += PageNeed * 128;
+
+ /* 3 (4) probe response * 1page */
+ RsvdPageLoc.LocProbeRsp = PageNum;
+ ConstructProbeRsp(adapt, &ReservedPagePacket[BufIndex], &ProbeRspLength, pnetwork->MacAddress, false);
+ rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex-TxDescLen], ProbeRspLength, false, false);
+
+ PageNeed = (u8)PageNum_128(TxDescLen + ProbeRspLength);
+ PageNum += PageNeed;
+
+ BufIndex += PageNeed * 128;
+
+ /* 3 (5) Qos null data */
+ RsvdPageLoc.LocQosNull = PageNum;
+ ConstructNullFunctionData(adapt, &ReservedPagePacket[BufIndex],
+ &QosNullLength, pnetwork->MacAddress, true, 0, 0, false);
+ rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, false, false);
+
+ PageNeed = (u8)PageNum_128(TxDescLen + QosNullLength);
+ PageNum += PageNeed;
+
+ TotalPacketLen = BufIndex + QosNullLength;
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+ if (!pmgntframe)
+ goto exit;
+
+ /* update attribute */
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(adapt, pattrib);
+ pattrib->qsel = 0x10;
+ pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET;
+ pattrib->pktlen = pattrib->last_txcmdsz;
+ memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen);
+
+ rtw_hal_mgnt_xmit(adapt, pmgntframe);
+
+ DBG_88E("%s: Set RSVD page location to Fw\n", __func__);
+ FillH2CCmd_88E(adapt, H2C_COM_RSVD_PAGE, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc);
+
+exit:
+ kfree(ReservedPagePacket);
+}
+
+void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *adapt, u8 mstatus)
+{
+ struct hal_data_8188e *haldata = adapt->HalData;
+ struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ bool bSendBeacon = false;
+ bool bcn_valid = false;
+ u8 DLBcnCount = 0;
+ u32 poll = 0;
+
+ DBG_88E("%s mstatus(%x)\n", __func__, mstatus);
+
+ if (mstatus == 1) {
+ /* We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */
+ /* Suggested by filen. Added by tynli. */
+ usb_write16(adapt, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid));
+ /* Do not set TSF again here or vWiFi beacon DMA INT will not work. */
+
+ /* Set REG_CR bit 8. DMA beacon by SW. */
+ haldata->RegCR_1 |= BIT(0);
+ usb_write8(adapt, REG_CR+1, haldata->RegCR_1);
+
+ /* Disable Hw protection for a time which revserd for Hw sending beacon. */
+ /* Fix download reserved page packet fail that access collision with the protection time. */
+ /* 2010.05.11. Added by tynli. */
+ usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL)&(~BIT(3)));
+ usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL) | BIT(4));
+
+ if (haldata->RegFwHwTxQCtrl & BIT(6)) {
+ DBG_88E("HalDownloadRSVDPage(): There is an Adapter is sending beacon.\n");
+ bSendBeacon = true;
+ }
+
+ /* Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame. */
+ usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl&(~BIT(6))));
+ haldata->RegFwHwTxQCtrl &= (~BIT(6));
+
+ /* Clear beacon valid check bit. */
+ rtw_hal_set_hwreg(adapt, HW_VAR_BCN_VALID, NULL);
+ DLBcnCount = 0;
+ poll = 0;
+ do {
+ /* download rsvd page. */
+ SetFwRsvdPagePkt(adapt, false);
+ DLBcnCount++;
+ do {
+ yield();
+ /* mdelay(10); */
+ /* check rsvd page download OK. */
+ rtw_hal_get_hwreg(adapt, HW_VAR_BCN_VALID, (u8 *)(&bcn_valid));
+ poll++;
+ } while (!bcn_valid && (poll%10) != 0 && !adapt->bSurpriseRemoved && !adapt->bDriverStopped);
+ } while (!bcn_valid && DLBcnCount <= 100 && !adapt->bSurpriseRemoved && !adapt->bDriverStopped);
+
+ if (adapt->bSurpriseRemoved || adapt->bDriverStopped)
+ ;
+ else if (!bcn_valid)
+ DBG_88E("%s: 1 Download RSVD page failed! DLBcnCount:%u, poll:%u\n", __func__, DLBcnCount, poll);
+ else
+ DBG_88E("%s: 1 Download RSVD success! DLBcnCount:%u, poll:%u\n", __func__, DLBcnCount, poll);
+ /* */
+ /* We just can send the reserved page twice during the time that Tx thread is stopped (e.g. pnpsetpower) */
+ /* because we need to free the Tx BCN Desc which is used by the first reserved page packet. */
+ /* At run time, we cannot get the Tx Desc until it is released in TxHandleInterrupt() so we will return */
+ /* the beacon TCB in the following code. 2011.11.23. by tynli. */
+ /* */
+
+ /* Enable Bcn */
+ usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL) | BIT(3));
+ usb_write8(adapt, REG_BCN_CTRL, usb_read8(adapt, REG_BCN_CTRL)&(~BIT(4)));
+
+ /* To make sure that if there exists an adapter which would like to send beacon. */
+ /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */
+ /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
+ /* the beacon cannot be sent by HW. */
+ /* 2010.06.23. Added by tynli. */
+ if (bSendBeacon) {
+ usb_write8(adapt, REG_FWHW_TXQ_CTRL+2, (haldata->RegFwHwTxQCtrl | BIT(6)));
+ haldata->RegFwHwTxQCtrl |= BIT(6);
+ }
+
+ /* Update RSVD page location H2C to Fw. */
+ if (bcn_valid) {
+ rtw_hal_set_hwreg(adapt, HW_VAR_BCN_VALID, NULL);
+ DBG_88E("Set RSVD page location to Fw.\n");
+ }
+
+ /* Do not enable HW DMA BCN or it will cause Pcie interface hang by timing issue. 2011.11.24. by tynli. */
+ /* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */
+ haldata->RegCR_1 &= (~BIT(0));
+ usb_write8(adapt, REG_CR+1, haldata->RegCR_1);
+ }
+}
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c
new file mode 100644
index 0000000..545d6a6
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_dm.c
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+/* */
+/* Description: */
+/* */
+/* This file is for 92CE/92CU dynamic mechanism only */
+/* */
+/* */
+/* */
+#define _RTL8188E_DM_C_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+
+#include <rtl8188e_hal.h>
+
+/* Initialize GPIO setting registers */
+static void dm_InitGPIOSetting(struct adapter *Adapter)
+{
+ u8 tmp1byte;
+
+ tmp1byte = usb_read8(Adapter, REG_GPIO_MUXCFG);
+ tmp1byte &= (GPIOSEL_GPIO | ~GPIOSEL_ENBT);
+
+ usb_write8(Adapter, REG_GPIO_MUXCFG, tmp1byte);
+}
+
+/* */
+/* functions */
+/* */
+static void Init_ODM_ComInfo_88E(struct adapter *Adapter)
+{
+ struct hal_data_8188e *hal_data = Adapter->HalData;
+ struct dm_priv *pdmpriv = &hal_data->dmpriv;
+ struct odm_dm_struct *dm_odm = &(hal_data->odmpriv);
+
+ /* Init Value */
+ memset(dm_odm, 0, sizeof(*dm_odm));
+
+ dm_odm->Adapter = Adapter;
+ dm_odm->SupportPlatform = ODM_CE;
+ dm_odm->SupportICType = ODM_RTL8188E;
+ dm_odm->CutVersion = ODM_CUT_A;
+ dm_odm->bIsMPChip = hal_data->VersionID.ChipType == NORMAL_CHIP;
+ dm_odm->PatchID = hal_data->CustomerID;
+ dm_odm->bWIFITest = Adapter->registrypriv.wifi_spec;
+
+ dm_odm->AntDivType = hal_data->TRxAntDivType;
+
+ /* Tx power tracking BB swing table. */
+ /* The base index = 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB */
+ dm_odm->BbSwingIdxOfdm = 12; /* Set defalut value as index 12. */
+ dm_odm->BbSwingIdxOfdmCurrent = 12;
+ dm_odm->BbSwingFlagOfdm = false;
+
+ pdmpriv->InitODMFlag = ODM_RF_CALIBRATION |
+ ODM_RF_TX_PWR_TRACK;
+
+ dm_odm->SupportAbility = pdmpriv->InitODMFlag;
+}
+
+static void Update_ODM_ComInfo_88E(struct adapter *Adapter)
+{
+ struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
+ struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
+ struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv;
+ struct hal_data_8188e *hal_data = Adapter->HalData;
+ struct odm_dm_struct *dm_odm = &(hal_data->odmpriv);
+ struct dm_priv *pdmpriv = &hal_data->dmpriv;
+ int i;
+
+ pdmpriv->InitODMFlag = ODM_BB_DIG |
+ ODM_BB_RA_MASK |
+ ODM_BB_DYNAMIC_TXPWR |
+ ODM_BB_FA_CNT |
+ ODM_BB_RSSI_MONITOR |
+ ODM_BB_CCK_PD |
+ ODM_BB_PWR_SAVE |
+ ODM_MAC_EDCA_TURBO |
+ ODM_RF_CALIBRATION |
+ ODM_RF_TX_PWR_TRACK;
+ if (hal_data->AntDivCfg)
+ pdmpriv->InitODMFlag |= ODM_BB_ANT_DIV;
+
+ if (Adapter->registrypriv.mp_mode == 1) {
+ pdmpriv->InitODMFlag = ODM_RF_CALIBRATION |
+ ODM_RF_TX_PWR_TRACK;
+ }
+
+ dm_odm->SupportAbility = pdmpriv->InitODMFlag;
+
+ dm_odm->pNumTxBytesUnicast = &Adapter->xmitpriv.tx_bytes;
+ dm_odm->pNumRxBytesUnicast = &Adapter->recvpriv.rx_bytes;
+ dm_odm->pWirelessMode = &pmlmeext->cur_wireless_mode;
+ dm_odm->pSecChOffset = &hal_data->nCur40MhzPrimeSC;
+ dm_odm->pSecurity = (u8 *)&Adapter->securitypriv.dot11PrivacyAlgrthm;
+ dm_odm->pBandWidth = (u8 *)&hal_data->CurrentChannelBW;
+ dm_odm->pChannel = &hal_data->CurrentChannel;
+ dm_odm->pbNet_closed = (bool *)&Adapter->net_closed;
+ dm_odm->mp_mode = &Adapter->registrypriv.mp_mode;
+ dm_odm->pbScanInProcess = (bool *)&pmlmepriv->bScanInProcess;
+ dm_odm->pbPowerSaving = (bool *)&pwrctrlpriv->bpower_saving;
+ dm_odm->AntDivType = hal_data->TRxAntDivType;
+
+ /* Tx power tracking BB swing table. */
+ /* The base index = 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB */
+ dm_odm->BbSwingIdxOfdm = 12; /* Set defalut value as index 12. */
+ dm_odm->BbSwingIdxOfdmCurrent = 12;
+ dm_odm->BbSwingFlagOfdm = false;
+
+ for (i = 0; i < NUM_STA; i++)
+ ODM_CmnInfoPtrArrayHook(dm_odm, ODM_CMNINFO_STA_STATUS, i, NULL);
+}
+
+void rtl8188e_InitHalDm(struct adapter *Adapter)
+{
+ struct dm_priv *pdmpriv = &Adapter->HalData->dmpriv;
+ struct odm_dm_struct *dm_odm = &(Adapter->HalData->odmpriv);
+
+ dm_InitGPIOSetting(Adapter);
+ pdmpriv->DM_Type = DM_Type_ByDriver;
+ pdmpriv->DMFlag = DYNAMIC_FUNC_DISABLE;
+ Update_ODM_ComInfo_88E(Adapter);
+ ODM_DMInit(dm_odm);
+}
+
+void rtw_hal_dm_watchdog(struct adapter *Adapter)
+{
+ u8 hw_init_completed = false;
+ struct mlme_priv *pmlmepriv = NULL;
+ u8 bLinked = false;
+
+ hw_init_completed = Adapter->hw_init_completed;
+
+ if (!hw_init_completed)
+ goto skip_dm;
+
+ /* ODM */
+ pmlmepriv = &Adapter->mlmepriv;
+
+ if ((check_fwstate(pmlmepriv, WIFI_AP_STATE)) ||
+ (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE |
+ WIFI_ADHOC_MASTER_STATE))) {
+ if (Adapter->stapriv.asoc_sta_count > 2)
+ bLinked = true;
+ } else {/* Station mode */
+ if (check_fwstate(pmlmepriv, _FW_LINKED))
+ bLinked = true;
+ }
+
+ Adapter->HalData->odmpriv.bLinked = bLinked;
+ ODM_DMWatchdog(&Adapter->HalData->odmpriv);
+skip_dm:
+ /* Check GPIO to determine current RF on/off and Pbc status. */
+ /* Check Hardware Radio ON/OFF or not */
+ return;
+}
+
+void rtw_hal_dm_init(struct adapter *Adapter)
+{
+ struct dm_priv *pdmpriv = &Adapter->HalData->dmpriv;
+ struct odm_dm_struct *podmpriv = &Adapter->HalData->odmpriv;
+
+ memset(pdmpriv, 0, sizeof(struct dm_priv));
+ Init_ODM_ComInfo_88E(Adapter);
+ ODM_InitDebugSetting(podmpriv);
+}
+
+/* Add new function to reset the state of antenna diversity before link. */
+/* Compare RSSI for deciding antenna */
+void rtw_hal_antdiv_rssi_compared(struct adapter *Adapter, struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src)
+{
+ if (Adapter->HalData->AntDivCfg != 0) {
+ /* select optimum_antenna for before linked =>For antenna diversity */
+ if (dst->Rssi >= src->Rssi) {/* keep org parameter */
+ src->Rssi = dst->Rssi;
+ src->PhyInfo.Optimum_antenna = dst->PhyInfo.Optimum_antenna;
+ }
+ }
+}
+
+/* Add new function to reset the state of antenna diversity before link. */
+u8 rtw_hal_antdiv_before_linked(struct adapter *Adapter)
+{
+ struct odm_dm_struct *dm_odm = &Adapter->HalData->odmpriv;
+ struct sw_ant_switch *dm_swat_tbl = &dm_odm->DM_SWAT_Table;
+ struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv);
+
+ /* Condition that does not need to use antenna diversity. */
+ if (Adapter->HalData->AntDivCfg == 0)
+ return false;
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED))
+ return false;
+
+ if (dm_swat_tbl->SWAS_NoLink_State == 0) {
+ /* switch channel */
+ dm_swat_tbl->SWAS_NoLink_State = 1;
+ dm_swat_tbl->CurAntenna = (dm_swat_tbl->CurAntenna == Antenna_A) ? Antenna_B : Antenna_A;
+
+ rtw_antenna_select_cmd(Adapter, dm_swat_tbl->CurAntenna, false);
+ return true;
+ } else {
+ dm_swat_tbl->SWAS_NoLink_State = 0;
+ return false;
+ }
+}
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
new file mode 100644
index 0000000..086f98d
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
@@ -0,0 +1,575 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _HAL_INIT_C_
+
+#include <linux/firmware.h>
+#include <linux/vmalloc.h>
+#include <drv_types.h>
+#include <rtw_efuse.h>
+#include <phy.h>
+#include <rtl8188e_hal.h>
+
+#include <rtw_iol.h>
+
+void iol_mode_enable(struct adapter *padapter, u8 enable)
+{
+ u8 reg_0xf0 = 0;
+
+ if (enable) {
+ /* Enable initial offload */
+ reg_0xf0 = usb_read8(padapter, REG_SYS_CFG);
+ usb_write8(padapter, REG_SYS_CFG, reg_0xf0|SW_OFFLOAD_EN);
+
+ if (!padapter->bFWReady) {
+ DBG_88E("bFWReady == false call reset 8051...\n");
+ _8051Reset88E(padapter);
+ }
+
+ } else {
+ /* disable initial offload */
+ reg_0xf0 = usb_read8(padapter, REG_SYS_CFG);
+ usb_write8(padapter, REG_SYS_CFG, reg_0xf0 & ~SW_OFFLOAD_EN);
+ }
+}
+
+s32 iol_execute(struct adapter *padapter, u8 control)
+{
+ s32 status = _FAIL;
+ u8 reg_0x88 = 0;
+ unsigned long start = 0;
+
+ control = control&0x0f;
+ reg_0x88 = usb_read8(padapter, REG_HMEBOX_E0);
+ usb_write8(padapter, REG_HMEBOX_E0, reg_0x88|control);
+
+ start = jiffies;
+ while ((reg_0x88 = usb_read8(padapter, REG_HMEBOX_E0)) & control &&
+ jiffies_to_msecs(jiffies - start) < 1000) {
+ udelay(5);
+ }
+
+ reg_0x88 = usb_read8(padapter, REG_HMEBOX_E0);
+ status = (reg_0x88 & control) ? _FAIL : _SUCCESS;
+ if (reg_0x88 & control<<4)
+ status = _FAIL;
+ return status;
+}
+
+static s32 iol_InitLLTTable(struct adapter *padapter, u8 txpktbuf_bndy)
+{
+ s32 rst = _SUCCESS;
+
+ iol_mode_enable(padapter, 1);
+ usb_write8(padapter, REG_TDECTRL+1, txpktbuf_bndy);
+ rst = iol_execute(padapter, CMD_INIT_LLT);
+ iol_mode_enable(padapter, 0);
+ return rst;
+}
+
+s32 rtl8188e_iol_efuse_patch(struct adapter *padapter)
+{
+ s32 result = _SUCCESS;
+
+ DBG_88E("==> %s\n", __func__);
+ if (rtw_iol_applied(padapter)) {
+ iol_mode_enable(padapter, 1);
+ result = iol_execute(padapter, CMD_READ_EFUSE_MAP);
+ if (result == _SUCCESS)
+ result = iol_execute(padapter, CMD_EFUSE_PATCH);
+
+ iol_mode_enable(padapter, 0);
+ }
+ return result;
+}
+
+#define MAX_REG_BOLCK_SIZE 196
+
+void _8051Reset88E(struct adapter *padapter)
+{
+ u8 u1bTmp;
+
+ u1bTmp = usb_read8(padapter, REG_SYS_FUNC_EN+1);
+ usb_write8(padapter, REG_SYS_FUNC_EN+1, u1bTmp&(~BIT(2)));
+ usb_write8(padapter, REG_SYS_FUNC_EN+1, u1bTmp|(BIT(2)));
+ DBG_88E("=====> _8051Reset88E(): 8051 reset success .\n");
+}
+
+void rtl8188e_InitializeFirmwareVars(struct adapter *padapter)
+{
+ /* Init Fw LPS related. */
+ padapter->pwrctrlpriv.bFwCurrentInPSMode = false;
+
+ /* Init H2C counter. by tynli. 2009.12.09. */
+ padapter->HalData->LastHMEBoxNum = 0;
+}
+
+void rtw_hal_free_data(struct adapter *padapter)
+{
+ kfree(padapter->HalData);
+ padapter->HalData = NULL;
+}
+
+void rtw_hal_read_chip_version(struct adapter *padapter)
+{
+ u32 value32;
+ struct HAL_VERSION ChipVersion;
+ struct hal_data_8188e *pHalData = padapter->HalData;
+
+ value32 = usb_read32(padapter, REG_SYS_CFG);
+ ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP);
+ ChipVersion.VendorType = ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : CHIP_VENDOR_TSMC);
+ ChipVersion.CUTVersion = (value32 & CHIP_VER_RTL_MASK)>>CHIP_VER_RTL_SHIFT; /* IC version (CUT) */
+
+ dump_chip_info(ChipVersion);
+
+ pHalData->VersionID = ChipVersion;
+}
+
+void rtw_hal_set_odm_var(struct adapter *Adapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet)
+{
+ struct odm_dm_struct *podmpriv = &Adapter->HalData->odmpriv;
+
+ switch (eVariable) {
+ case HAL_ODM_STA_INFO:
+ {
+ struct sta_info *psta = pValue1;
+
+ if (bSet) {
+ DBG_88E("### Set STA_(%d) info\n", psta->mac_id);
+ ODM_CmnInfoPtrArrayHook(podmpriv, ODM_CMNINFO_STA_STATUS, psta->mac_id, psta);
+ ODM_RAInfo_Init(podmpriv, psta->mac_id);
+ } else {
+ DBG_88E("### Clean STA_(%d) info\n", psta->mac_id);
+ ODM_CmnInfoPtrArrayHook(podmpriv, ODM_CMNINFO_STA_STATUS, psta->mac_id, NULL);
+ }
+ }
+ break;
+ case HAL_ODM_P2P_STATE:
+ podmpriv->bWIFI_Direct = bSet;
+ break;
+ case HAL_ODM_WIFI_DISPLAY_STATE:
+ podmpriv->bWIFI_Display = bSet;
+ break;
+ default:
+ break;
+ }
+}
+
+void rtw_hal_notch_filter(struct adapter *adapter, bool enable)
+{
+ if (enable) {
+ DBG_88E("Enable notch filter\n");
+ usb_write8(adapter, rOFDM0_RxDSP+1, usb_read8(adapter, rOFDM0_RxDSP+1) | BIT(1));
+ } else {
+ DBG_88E("Disable notch filter\n");
+ usb_write8(adapter, rOFDM0_RxDSP+1, usb_read8(adapter, rOFDM0_RxDSP+1) & ~BIT(1));
+ }
+}
+
+/* */
+/* */
+/* LLT R/W/Init function */
+/* */
+/* */
+static s32 _LLTWrite(struct adapter *padapter, u32 address, u32 data)
+{
+ s32 status = _SUCCESS;
+ s32 count = 0;
+ u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS);
+ u16 LLTReg = REG_LLT_INIT;
+
+ usb_write32(padapter, LLTReg, value);
+
+ /* polling */
+ do {
+ value = usb_read32(padapter, LLTReg);
+ if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value))
+ break;
+
+ if (count > POLLING_LLT_THRESHOLD) {
+ RT_TRACE(_module_hal_init_c_, _drv_err_, ("Failed to polling write LLT done at address %d!\n", address));
+ status = _FAIL;
+ break;
+ }
+ udelay(5);
+ } while (count++);
+
+ return status;
+}
+
+s32 InitLLTTable(struct adapter *padapter, u8 txpktbuf_bndy)
+{
+ s32 status = _FAIL;
+ u32 i;
+ u32 Last_Entry_Of_TxPktBuf = LAST_ENTRY_OF_TX_PKT_BUFFER;/* 176, 22k */
+
+ if (rtw_iol_applied(padapter)) {
+ status = iol_InitLLTTable(padapter, txpktbuf_bndy);
+ } else {
+ for (i = 0; i < (txpktbuf_bndy - 1); i++) {
+ status = _LLTWrite(padapter, i, i + 1);
+ if (status != _SUCCESS)
+ return status;
+ }
+
+ /* end of list */
+ status = _LLTWrite(padapter, (txpktbuf_bndy - 1), 0xFF);
+ if (status != _SUCCESS)
+ return status;
+
+ /* Make the other pages as ring buffer */
+ /* This ring buffer is used as beacon buffer if we config this MAC as two MAC transfer. */
+ /* Otherwise used as local loopback buffer. */
+ for (i = txpktbuf_bndy; i < Last_Entry_Of_TxPktBuf; i++) {
+ status = _LLTWrite(padapter, i, (i + 1));
+ if (status != _SUCCESS)
+ return status;
+ }
+
+ /* Let last entry point to the start entry of ring buffer */
+ status = _LLTWrite(padapter, Last_Entry_Of_TxPktBuf, txpktbuf_bndy);
+ if (status != _SUCCESS)
+ return status;
+ }
+
+ return status;
+}
+
+void Hal_InitPGData88E(struct adapter *padapter)
+{
+ struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
+
+ if (!pEEPROM->bautoload_fail_flag) { /* autoload OK. */
+ if (!is_boot_from_eeprom(padapter)) {
+ /* Read EFUSE real map to shadow. */
+ EFUSE_ShadowMapUpdate(padapter, EFUSE_WIFI);
+ }
+ } else {/* autoload fail */
+ RT_TRACE(_module_hci_hal_init_c_, _drv_notice_, ("AutoLoad Fail reported from CR9346!!\n"));
+ /* update to default value 0xFF */
+ if (!is_boot_from_eeprom(padapter))
+ EFUSE_ShadowMapUpdate(padapter, EFUSE_WIFI);
+ }
+}
+
+void Hal_EfuseParseIDCode88E(struct adapter *padapter, u8 *hwinfo)
+{
+ struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
+ u16 EEPROMId;
+
+ /* Checl 0x8129 again for making sure autoload status!! */
+ EEPROMId = le16_to_cpu(*((__le16 *)hwinfo));
+ if (EEPROMId != RTL_EEPROM_ID) {
+ DBG_88E("EEPROM ID(%#x) is invalid!!\n", EEPROMId);
+ pEEPROM->bautoload_fail_flag = true;
+ } else {
+ pEEPROM->bautoload_fail_flag = false;
+ }
+
+ DBG_88E("EEPROM ID = 0x%04x\n", EEPROMId);
+}
+
+static void Hal_ReadPowerValueFromPROM_8188E(struct txpowerinfo24g *pwrInfo24G, u8 *PROMContent, bool AutoLoadFail)
+{
+ u32 rfPath, eeAddr = EEPROM_TX_PWR_INX_88E, group, TxCount = 0;
+
+ memset(pwrInfo24G, 0, sizeof(struct txpowerinfo24g));
+
+ if (AutoLoadFail) {
+ for (rfPath = 0; rfPath < MAX_RF_PATH; rfPath++) {
+ /* 2.4G default value */
+ for (group = 0; group < MAX_CHNL_GROUP_24G; group++) {
+ pwrInfo24G->IndexCCK_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
+ pwrInfo24G->IndexBW40_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
+ }
+ for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
+ if (TxCount == 0) {
+ pwrInfo24G->BW20_Diff[rfPath][0] = EEPROM_DEFAULT_24G_HT20_DIFF;
+ pwrInfo24G->OFDM_Diff[rfPath][0] = EEPROM_DEFAULT_24G_OFDM_DIFF;
+ } else {
+ pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ pwrInfo24G->BW40_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ pwrInfo24G->CCK_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ }
+ }
+ }
+ return;
+ }
+
+ for (rfPath = 0; rfPath < MAX_RF_PATH; rfPath++) {
+ /* 2.4G default value */
+ for (group = 0; group < MAX_CHNL_GROUP_24G; group++) {
+ pwrInfo24G->IndexCCK_Base[rfPath][group] = PROMContent[eeAddr++];
+ if (pwrInfo24G->IndexCCK_Base[rfPath][group] == 0xFF)
+ pwrInfo24G->IndexCCK_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
+ }
+ for (group = 0; group < MAX_CHNL_GROUP_24G-1; group++) {
+ pwrInfo24G->IndexBW40_Base[rfPath][group] = PROMContent[eeAddr++];
+ if (pwrInfo24G->IndexBW40_Base[rfPath][group] == 0xFF)
+ pwrInfo24G->IndexBW40_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
+ }
+ for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
+ if (TxCount == 0) {
+ pwrInfo24G->BW40_Diff[rfPath][TxCount] = 0;
+ if (PROMContent[eeAddr] == 0xFF) {
+ pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_24G_HT20_DIFF;
+ } else {
+ pwrInfo24G->BW20_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0xf0)>>4;
+ if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
+ pwrInfo24G->BW20_Diff[rfPath][TxCount] |= 0xF0;
+ }
+
+ if (PROMContent[eeAddr] == 0xFF) {
+ pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_24G_OFDM_DIFF;
+ } else {
+ pwrInfo24G->OFDM_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0x0f);
+ if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
+ pwrInfo24G->OFDM_Diff[rfPath][TxCount] |= 0xF0;
+ }
+ pwrInfo24G->CCK_Diff[rfPath][TxCount] = 0;
+ eeAddr++;
+ } else {
+ if (PROMContent[eeAddr] == 0xFF) {
+ pwrInfo24G->BW40_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ } else {
+ pwrInfo24G->BW40_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0xf0)>>4;
+ if (pwrInfo24G->BW40_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
+ pwrInfo24G->BW40_Diff[rfPath][TxCount] |= 0xF0;
+ }
+
+ if (PROMContent[eeAddr] == 0xFF) {
+ pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ } else {
+ pwrInfo24G->BW20_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0x0f);
+ if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
+ pwrInfo24G->BW20_Diff[rfPath][TxCount] |= 0xF0;
+ }
+ eeAddr++;
+
+ if (PROMContent[eeAddr] == 0xFF) {
+ pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ } else {
+ pwrInfo24G->OFDM_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0xf0)>>4;
+ if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
+ pwrInfo24G->OFDM_Diff[rfPath][TxCount] |= 0xF0;
+ }
+
+ if (PROMContent[eeAddr] == 0xFF) {
+ pwrInfo24G->CCK_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
+ } else {
+ pwrInfo24G->CCK_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0x0f);
+ if (pwrInfo24G->CCK_Diff[rfPath][TxCount] & BIT(3)) /* 4bit sign number to 8 bit sign number */
+ pwrInfo24G->CCK_Diff[rfPath][TxCount] |= 0xF0;
+ }
+ eeAddr++;
+ }
+ }
+ }
+}
+
+void Hal_GetChnlGroup88E(u8 chnl, u8 *group)
+{
+ if (chnl < 3) /* Channel 1-2 */
+ *group = 0;
+ else if (chnl < 6) /* Channel 3-5 */
+ *group = 1;
+ else if (chnl < 9) /* Channel 6-8 */
+ *group = 2;
+ else if (chnl < 12) /* Channel 9-11 */
+ *group = 3;
+ else if (chnl < 14) /* Channel 12-13 */
+ *group = 4;
+ else if (chnl == 14) /* Channel 14 */
+ *group = 5;
+}
+
+void Hal_ReadPowerSavingMode88E(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail)
+{
+ if (AutoLoadFail) {
+ padapter->pwrctrlpriv.bHWPowerdown = false;
+ padapter->pwrctrlpriv.bSupportRemoteWakeup = false;
+ } else {
+ /* hw power down mode selection , 0:rf-off / 1:power down */
+
+ if (padapter->registrypriv.hwpdn_mode == 2)
+ padapter->pwrctrlpriv.bHWPowerdown = (hwinfo[EEPROM_RF_FEATURE_OPTION_88E] & BIT(4));
+ else
+ padapter->pwrctrlpriv.bHWPowerdown = padapter->registrypriv.hwpdn_mode;
+
+ /* decide hw if support remote wakeup function */
+ /* if hw supported, 8051 (SIE) will generate WeakUP signal(D+/D- toggle) when autoresume */
+ padapter->pwrctrlpriv.bSupportRemoteWakeup = (hwinfo[EEPROM_USB_OPTIONAL_FUNCTION0] & BIT(1)) ? true : false;
+
+ DBG_88E("%s...bHWPwrPindetect(%x)-bHWPowerdown(%x) , bSupportRemoteWakeup(%x)\n", __func__,
+ padapter->pwrctrlpriv.bHWPwrPindetect, padapter->pwrctrlpriv.bHWPowerdown, padapter->pwrctrlpriv.bSupportRemoteWakeup);
+
+ DBG_88E("### PS params => power_mgnt(%x), usbss_enable(%x) ###\n", padapter->registrypriv.power_mgnt, padapter->registrypriv.usbss_enable);
+ }
+}
+
+void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *PROMContent, bool AutoLoadFail)
+{
+ struct hal_data_8188e *pHalData = padapter->HalData;
+ struct txpowerinfo24g pwrInfo24G;
+ u8 ch, group;
+ u8 TxCount;
+
+ Hal_ReadPowerValueFromPROM_8188E(&pwrInfo24G, PROMContent, AutoLoadFail);
+
+ if (!AutoLoadFail)
+ pHalData->bTXPowerDataReadFromEEPORM = true;
+
+ for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
+ Hal_GetChnlGroup88E(ch, &group);
+ pHalData->Index24G_CCK_Base[0][ch] = pwrInfo24G.IndexCCK_Base[0][group];
+ if (ch == 14)
+ pHalData->Index24G_BW40_Base[0][ch] = pwrInfo24G.IndexBW40_Base[0][4];
+ else
+ pHalData->Index24G_BW40_Base[0][ch] = pwrInfo24G.IndexBW40_Base[0][group];
+
+ DBG_88E("======= Path %d, Channel %d =======\n", 0, ch);
+ DBG_88E("Index24G_CCK_Base[%d][%d] = 0x%x\n", 0, ch, pHalData->Index24G_CCK_Base[0][ch]);
+ DBG_88E("Index24G_BW40_Base[%d][%d] = 0x%x\n", 0, ch, pHalData->Index24G_BW40_Base[0][ch]);
+ }
+ for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
+ pHalData->CCK_24G_Diff[0][TxCount] = pwrInfo24G.CCK_Diff[0][TxCount];
+ pHalData->OFDM_24G_Diff[0][TxCount] = pwrInfo24G.OFDM_Diff[0][TxCount];
+ pHalData->BW20_24G_Diff[0][TxCount] = pwrInfo24G.BW20_Diff[0][TxCount];
+ pHalData->BW40_24G_Diff[0][TxCount] = pwrInfo24G.BW40_Diff[0][TxCount];
+ DBG_88E("======= TxCount %d =======\n", TxCount);
+ DBG_88E("CCK_24G_Diff[%d][%d] = %d\n", 0, TxCount, pHalData->CCK_24G_Diff[0][TxCount]);
+ DBG_88E("OFDM_24G_Diff[%d][%d] = %d\n", 0, TxCount, pHalData->OFDM_24G_Diff[0][TxCount]);
+ DBG_88E("BW20_24G_Diff[%d][%d] = %d\n", 0, TxCount, pHalData->BW20_24G_Diff[0][TxCount]);
+ DBG_88E("BW40_24G_Diff[%d][%d] = %d\n", 0, TxCount, pHalData->BW40_24G_Diff[0][TxCount]);
+ }
+
+ /* 2010/10/19 MH Add Regulator recognize for CU. */
+ if (!AutoLoadFail) {
+ pHalData->EEPROMRegulatory = (PROMContent[EEPROM_RF_BOARD_OPTION_88E]&0x7); /* bit0~2 */
+ if (PROMContent[EEPROM_RF_BOARD_OPTION_88E] == 0xFF)
+ pHalData->EEPROMRegulatory = (EEPROM_DEFAULT_BOARD_OPTION&0x7); /* bit0~2 */
+ } else {
+ pHalData->EEPROMRegulatory = 0;
+ }
+ DBG_88E("EEPROMRegulatory = 0x%x\n", pHalData->EEPROMRegulatory);
+}
+
+void Hal_EfuseParseXtal_8188E(struct adapter *pAdapter, u8 *hwinfo, bool AutoLoadFail)
+{
+ struct hal_data_8188e *pHalData = pAdapter->HalData;
+
+ if (!AutoLoadFail) {
+ pHalData->CrystalCap = hwinfo[EEPROM_XTAL_88E];
+ if (pHalData->CrystalCap == 0xFF)
+ pHalData->CrystalCap = EEPROM_Default_CrystalCap_88E;
+ } else {
+ pHalData->CrystalCap = EEPROM_Default_CrystalCap_88E;
+ }
+ DBG_88E("CrystalCap: 0x%2x\n", pHalData->CrystalCap);
+}
+
+void Hal_EfuseParseBoardType88E(struct adapter *pAdapter, u8 *hwinfo, bool AutoLoadFail)
+{
+ struct hal_data_8188e *pHalData = pAdapter->HalData;
+
+ if (!AutoLoadFail)
+ pHalData->BoardType = (hwinfo[EEPROM_RF_BOARD_OPTION_88E]
+ & 0xE0) >> 5;
+ else
+ pHalData->BoardType = 0;
+ DBG_88E("Board Type: 0x%2x\n", pHalData->BoardType);
+}
+
+void Hal_EfuseParseEEPROMVer88E(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail)
+{
+ struct hal_data_8188e *pHalData = padapter->HalData;
+
+ if (!AutoLoadFail) {
+ pHalData->EEPROMVersion = hwinfo[EEPROM_VERSION_88E];
+ if (pHalData->EEPROMVersion == 0xFF)
+ pHalData->EEPROMVersion = EEPROM_Default_Version;
+ } else {
+ pHalData->EEPROMVersion = 1;
+ }
+ RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
+ ("Hal_EfuseParseEEPROMVer(), EEVer = %d\n",
+ pHalData->EEPROMVersion));
+}
+
+void rtl8188e_EfuseParseChnlPlan(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail)
+{
+ padapter->mlmepriv.ChannelPlan =
+ hal_com_get_channel_plan(hwinfo ? hwinfo[EEPROM_ChannelPlan_88E] : 0xFF,
+ padapter->registrypriv.channel_plan,
+ RT_CHANNEL_DOMAIN_WORLD_WIDE_13, AutoLoadFail);
+
+ DBG_88E("mlmepriv.ChannelPlan = 0x%02x\n", padapter->mlmepriv.ChannelPlan);
+}
+
+void Hal_EfuseParseCustomerID88E(struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail)
+{
+ struct hal_data_8188e *pHalData = padapter->HalData;
+
+ if (!AutoLoadFail) {
+ pHalData->EEPROMCustomerID = hwinfo[EEPROM_CUSTOMERID_88E];
+ } else {
+ pHalData->EEPROMCustomerID = 0;
+ pHalData->EEPROMSubCustomerID = 0;
+ }
+ DBG_88E("EEPROM Customer ID: 0x%2x\n", pHalData->EEPROMCustomerID);
+}
+
+void Hal_ReadAntennaDiversity88E(struct adapter *pAdapter, u8 *PROMContent, bool AutoLoadFail)
+{
+ struct hal_data_8188e *pHalData = pAdapter->HalData;
+ struct registry_priv *registry_par = &pAdapter->registrypriv;
+
+ if (!AutoLoadFail) {
+ /* Antenna Diversity setting. */
+ if (registry_par->antdiv_cfg == 2) { /* 2:By EFUSE */
+ pHalData->AntDivCfg = (PROMContent[EEPROM_RF_BOARD_OPTION_88E]&0x18)>>3;
+ if (PROMContent[EEPROM_RF_BOARD_OPTION_88E] == 0xFF)
+ pHalData->AntDivCfg = (EEPROM_DEFAULT_BOARD_OPTION&0x18)>>3;
+ } else {
+ pHalData->AntDivCfg = registry_par->antdiv_cfg; /* 0:OFF , 1:ON, 2:By EFUSE */
+ }
+
+ if (registry_par->antdiv_type == 0) {
+ /* If TRxAntDivType is AUTO in advanced setting, use EFUSE value instead. */
+ pHalData->TRxAntDivType = PROMContent[EEPROM_RF_ANTENNA_OPT_88E];
+ if (pHalData->TRxAntDivType == 0xFF)
+ pHalData->TRxAntDivType = CG_TRX_HW_ANTDIV; /* For 88EE, 1Tx and 1RxCG are fixed.(1Ant, Tx and RxCG are both on aux port) */
+ } else {
+ pHalData->TRxAntDivType = registry_par->antdiv_type;
+ }
+
+ if (pHalData->TRxAntDivType == CG_TRX_HW_ANTDIV || pHalData->TRxAntDivType == CGCS_RX_HW_ANTDIV)
+ pHalData->AntDivCfg = 1; /* 0xC1[3] is ignored. */
+ } else {
+ pHalData->AntDivCfg = 0;
+ pHalData->TRxAntDivType = pHalData->TRxAntDivType; /* The value in the driver setting of device manager. */
+ }
+ DBG_88E("EEPROM : AntDivCfg = %x, TRxAntDivType = %x\n", pHalData->AntDivCfg, pHalData->TRxAntDivType);
+}
+
+void Hal_ReadThermalMeter_88E(struct adapter *Adapter, u8 *PROMContent, bool AutoloadFail)
+{
+ struct hal_data_8188e *pHalData = Adapter->HalData;
+
+ /* ThermalMeter from EEPROM */
+ if (!AutoloadFail)
+ pHalData->EEPROMThermalMeter = PROMContent[EEPROM_THERMAL_METER_88E];
+ else
+ pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter_88E;
+
+ if (pHalData->EEPROMThermalMeter == 0xff || AutoloadFail) {
+ pHalData->bAPKThermalMeterIgnore = true;
+ pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter_88E;
+ }
+ DBG_88E("ThermalMeter = 0x%x\n", pHalData->EEPROMThermalMeter);
+}
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c
new file mode 100644
index 0000000..0a90082
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c
@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _RTL8188E_REDESC_C_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <rtl8188e_hal.h>
+
+static void process_rssi(struct adapter *padapter, struct recv_frame *prframe)
+{
+ struct rx_pkt_attrib *pattrib = &prframe->attrib;
+ struct signal_stat *signal_stat = &padapter->recvpriv.signal_strength_data;
+
+ if (signal_stat->update_req) {
+ signal_stat->total_num = 0;
+ signal_stat->total_val = 0;
+ signal_stat->update_req = 0;
+ }
+
+ signal_stat->total_num++;
+ signal_stat->total_val += pattrib->phy_info.SignalStrength;
+ signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num;
+} /* Process_UI_RSSI_8192C */
+
+static void process_link_qual(struct adapter *padapter,
+ struct recv_frame *prframe)
+{
+ struct rx_pkt_attrib *pattrib;
+ struct signal_stat *signal_stat;
+
+ if (!prframe || !padapter)
+ return;
+
+ pattrib = &prframe->attrib;
+ signal_stat = &padapter->recvpriv.signal_qual_data;
+
+ if (signal_stat->update_req) {
+ signal_stat->total_num = 0;
+ signal_stat->total_val = 0;
+ signal_stat->update_req = 0;
+ }
+
+ signal_stat->total_num++;
+ signal_stat->total_val += pattrib->phy_info.SignalQuality;
+ signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num;
+}
+
+void rtl8188e_process_phy_info(struct adapter *padapter,
+ struct recv_frame *precvframe)
+{
+ /* Check RSSI */
+ process_rssi(padapter, precvframe);
+ /* Check EVM */
+ process_link_qual(padapter, precvframe);
+}
+
+void update_recvframe_attrib_88e(struct recv_frame *precvframe,
+ struct recv_stat *prxstat)
+{
+ struct rx_pkt_attrib *pattrib;
+ struct recv_stat report;
+
+ report.rxdw0 = prxstat->rxdw0;
+ report.rxdw1 = prxstat->rxdw1;
+ report.rxdw2 = prxstat->rxdw2;
+ report.rxdw3 = prxstat->rxdw3;
+ report.rxdw4 = prxstat->rxdw4;
+ report.rxdw5 = prxstat->rxdw5;
+
+ pattrib = &precvframe->attrib;
+ memset(pattrib, 0, sizeof(struct rx_pkt_attrib));
+
+ pattrib->crc_err = (u8)((le32_to_cpu(report.rxdw0) >> 14) & 0x1);/* u8)prxreport->crc32; */
+
+ /* update rx report to recv_frame attribute */
+ pattrib->pkt_rpt_type = (u8)((le32_to_cpu(report.rxdw3) >> 14) & 0x3);/* prxreport->rpt_sel; */
+
+ if (pattrib->pkt_rpt_type == NORMAL_RX) { /* Normal rx packet */
+ pattrib->pkt_len = (u16)(le32_to_cpu(report.rxdw0) & 0x00003fff);/* u16)prxreport->pktlen; */
+ pattrib->drvinfo_sz = (u8)((le32_to_cpu(report.rxdw0) >> 16) & 0xf) * 8;/* u8)(prxreport->drvinfosize << 3); */
+
+ pattrib->physt = (u8)((le32_to_cpu(report.rxdw0) >> 26) & 0x1);/* u8)prxreport->physt; */
+
+ pattrib->bdecrypted = (le32_to_cpu(report.rxdw0) & BIT(27)) ? 0 : 1;/* u8)(prxreport->swdec ? 0 : 1); */
+ pattrib->encrypt = (u8)((le32_to_cpu(report.rxdw0) >> 20) & 0x7);/* u8)prxreport->security; */
+
+ pattrib->qos = (u8)((le32_to_cpu(report.rxdw0) >> 23) & 0x1);/* u8)prxreport->qos; */
+ pattrib->priority = (u8)((le32_to_cpu(report.rxdw1) >> 8) & 0xf);/* u8)prxreport->tid; */
+
+ pattrib->amsdu = (u8)((le32_to_cpu(report.rxdw1) >> 13) & 0x1);/* u8)prxreport->amsdu; */
+
+ pattrib->seq_num = (u16)(le32_to_cpu(report.rxdw2) & 0x00000fff);/* u16)prxreport->seq; */
+ pattrib->frag_num = (u8)((le32_to_cpu(report.rxdw2) >> 12) & 0xf);/* u8)prxreport->frag; */
+ pattrib->mfrag = (u8)((le32_to_cpu(report.rxdw1) >> 27) & 0x1);/* u8)prxreport->mf; */
+ pattrib->mdata = (u8)((le32_to_cpu(report.rxdw1) >> 26) & 0x1);/* u8)prxreport->md; */
+
+ pattrib->mcs_rate = (u8)(le32_to_cpu(report.rxdw3) & 0x3f);/* u8)prxreport->rxmcs; */
+ pattrib->rxht = (u8)((le32_to_cpu(report.rxdw3) >> 6) & 0x1);/* u8)prxreport->rxht; */
+
+ pattrib->icv_err = (u8)((le32_to_cpu(report.rxdw0) >> 15) & 0x1);/* u8)prxreport->icverr; */
+ pattrib->shift_sz = (u8)((le32_to_cpu(report.rxdw0) >> 24) & 0x3);
+ } else if (pattrib->pkt_rpt_type == TX_REPORT1) { /* CCX */
+ pattrib->pkt_len = TX_RPT1_PKT_LEN;
+ pattrib->drvinfo_sz = 0;
+ } else if (pattrib->pkt_rpt_type == TX_REPORT2) { /* TX RPT */
+ pattrib->pkt_len = (u16)(le32_to_cpu(report.rxdw0) & 0x3FF);/* Rx length[9:0] */
+ pattrib->drvinfo_sz = 0;
+
+ /* */
+ /* Get TX report MAC ID valid. */
+ /* */
+ pattrib->MacIDValidEntry[0] = le32_to_cpu(report.rxdw4);
+ pattrib->MacIDValidEntry[1] = le32_to_cpu(report.rxdw5);
+
+ } else if (pattrib->pkt_rpt_type == HIS_REPORT) { /* USB HISR RPT */
+ pattrib->pkt_len = (u16)(le32_to_cpu(report.rxdw0) & 0x00003fff);/* u16)prxreport->pktlen; */
+ }
+}
+
+/*
+ * Notice:
+ * Before calling this function,
+ * precvframe->rx_data should be ready!
+ */
+void update_recvframe_phyinfo_88e(struct recv_frame *precvframe,
+ struct phy_stat *pphy_status)
+{
+ struct adapter *padapter = precvframe->adapter;
+ struct rx_pkt_attrib *pattrib = &precvframe->attrib;
+ struct odm_phy_status_info *pPHYInfo = (struct odm_phy_status_info *)(&pattrib->phy_info);
+ u8 *wlanhdr;
+ struct odm_per_pkt_info pkt_info;
+ u8 *sa = NULL;
+ struct sta_priv *pstapriv;
+ struct sta_info *psta;
+
+ pkt_info.bPacketMatchBSSID = false;
+ pkt_info.bPacketToSelf = false;
+ pkt_info.bPacketBeacon = false;
+
+ wlanhdr = precvframe->pkt->data;
+
+ pkt_info.bPacketMatchBSSID = ((!IsFrameTypeCtrl(wlanhdr)) &&
+ !pattrib->icv_err && !pattrib->crc_err &&
+ !memcmp(get_hdr_bssid(wlanhdr),
+ get_bssid(&padapter->mlmepriv), ETH_ALEN));
+
+ pkt_info.bPacketToSelf = pkt_info.bPacketMatchBSSID &&
+ (!memcmp(get_da(wlanhdr),
+ myid(&padapter->eeprompriv), ETH_ALEN));
+
+ pkt_info.bPacketBeacon = pkt_info.bPacketMatchBSSID &&
+ (GetFrameSubType(wlanhdr) == WIFI_BEACON);
+
+ if (pkt_info.bPacketBeacon) {
+ if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE))
+ sa = padapter->mlmepriv.cur_network.network.MacAddress;
+ /* to do Ad-hoc */
+ } else {
+ sa = get_sa(wlanhdr);
+ }
+
+ pstapriv = &padapter->stapriv;
+ pkt_info.StationID = 0xFF;
+ psta = rtw_get_stainfo(pstapriv, sa);
+ if (psta)
+ pkt_info.StationID = psta->mac_id;
+ pkt_info.Rate = pattrib->mcs_rate;
+
+ ODM_PhyStatusQuery(&padapter->HalData->odmpriv, pPHYInfo,
+ (u8 *)pphy_status, &(pkt_info));
+
+ precvframe->psta = NULL;
+ if (pkt_info.bPacketMatchBSSID &&
+ (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE))) {
+ if (psta) {
+ precvframe->psta = psta;
+ rtl8188e_process_phy_info(padapter, precvframe);
+ }
+ } else if (pkt_info.bPacketToSelf || pkt_info.bPacketBeacon) {
+ if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE)) {
+ if (psta)
+ precvframe->psta = psta;
+ }
+ rtl8188e_process_phy_info(padapter, precvframe);
+ }
+}
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_xmit.c b/drivers/staging/rtl8188eu/hal/rtl8188e_xmit.c
new file mode 100644
index 0000000..9b8a284
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_xmit.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _RTL8188E_XMIT_C_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <rtl8188e_hal.h>
+
+void handle_txrpt_ccx_88e(struct adapter *adapter, u8 *buf)
+{
+ struct txrpt_ccx_88e *txrpt_ccx = (struct txrpt_ccx_88e *)buf;
+
+ if (txrpt_ccx->int_ccx) {
+ if (txrpt_ccx->pkt_ok)
+ rtw_ack_tx_done(&adapter->xmitpriv,
+ RTW_SCTX_DONE_SUCCESS);
+ else
+ rtw_ack_tx_done(&adapter->xmitpriv,
+ RTW_SCTX_DONE_CCX_PKT_FAIL);
+ }
+}
+
+void _dbg_dump_tx_info(struct adapter *padapter, int frame_tag,
+ struct tx_desc *ptxdesc)
+{
+ u8 dmp_txpkt;
+ bool dump_txdesc = false;
+
+ rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(dmp_txpkt));
+
+ if (dmp_txpkt == 1) {/* dump txdesc for data frame */
+ DBG_88E("dump tx_desc for data frame\n");
+ if ((frame_tag & 0x0f) == DATA_FRAMETAG)
+ dump_txdesc = true;
+ } else if (dmp_txpkt == 2) {/* dump txdesc for mgnt frame */
+ DBG_88E("dump tx_desc for mgnt frame\n");
+ if ((frame_tag & 0x0f) == MGNT_FRAMETAG)
+ dump_txdesc = true;
+ }
+
+ if (dump_txdesc) {
+ DBG_88E("=====================================\n");
+ DBG_88E("txdw0(0x%08x)\n", ptxdesc->txdw0);
+ DBG_88E("txdw1(0x%08x)\n", ptxdesc->txdw1);
+ DBG_88E("txdw2(0x%08x)\n", ptxdesc->txdw2);
+ DBG_88E("txdw3(0x%08x)\n", ptxdesc->txdw3);
+ DBG_88E("txdw4(0x%08x)\n", ptxdesc->txdw4);
+ DBG_88E("txdw5(0x%08x)\n", ptxdesc->txdw5);
+ DBG_88E("txdw6(0x%08x)\n", ptxdesc->txdw6);
+ DBG_88E("txdw7(0x%08x)\n", ptxdesc->txdw7);
+ DBG_88E("=====================================\n");
+ }
+}
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c
new file mode 100644
index 0000000..35806b2
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_led.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <rtl8188e_hal.h>
+#include <usb_ops_linux.h>
+
+void sw_led_on(struct adapter *padapter, struct LED_871x *pLed)
+{
+ u8 led_cfg;
+
+ if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
+ return;
+ led_cfg = usb_read8(padapter, REG_LEDCFG2);
+ usb_write8(padapter, REG_LEDCFG2, (led_cfg & 0xf0) | BIT(5) | BIT(6));
+ pLed->bLedOn = true;
+}
+
+void sw_led_off(struct adapter *padapter, struct LED_871x *pLed)
+{
+ u8 led_cfg;
+
+ if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
+ goto exit;
+
+ led_cfg = usb_read8(padapter, REG_LEDCFG2);/* 0x4E */
+
+ /* Open-drain arrangement for controlling the LED) */
+ led_cfg &= 0x90; /* Set to software control. */
+ usb_write8(padapter, REG_LEDCFG2, (led_cfg | BIT(3)));
+ led_cfg = usb_read8(padapter, REG_MAC_PINMUX_CFG);
+ led_cfg &= 0xFE;
+ usb_write8(padapter, REG_MAC_PINMUX_CFG, led_cfg);
+exit:
+ pLed->bLedOn = false;
+}
+
+void rtw_hal_sw_led_init(struct adapter *padapter)
+{
+ struct led_priv *pledpriv = &padapter->ledpriv;
+
+ InitLed871x(padapter, &pledpriv->sw_led);
+}
+
+void rtw_hal_sw_led_deinit(struct adapter *padapter)
+{
+ struct led_priv *ledpriv = &padapter->ledpriv;
+
+ DeInitLed871x(&ledpriv->sw_led);
+}
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c
new file mode 100644
index 0000000..c0d51ba
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_recv.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _RTL8188EU_RECV_C_
+#include <linux/kmemleak.h>
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <recv_osdep.h>
+#include <mlme_osdep.h>
+
+#include <usb_ops_linux.h>
+#include <wifi.h>
+
+#include <rtl8188e_hal.h>
+
+int rtw_hal_init_recv_priv(struct adapter *padapter)
+{
+ struct recv_priv *precvpriv = &padapter->recvpriv;
+ int i, res = _SUCCESS;
+ struct recv_buf *precvbuf;
+
+ tasklet_init(&precvpriv->recv_tasklet,
+ (void(*)(unsigned long))rtl8188eu_recv_tasklet,
+ (unsigned long)padapter);
+
+ /* init recv_buf */
+ _rtw_init_queue(&precvpriv->free_recv_buf_queue);
+
+ precvpriv->precv_buf =
+ kcalloc(NR_RECVBUFF, sizeof(struct recv_buf), GFP_KERNEL);
+ if (!precvpriv->precv_buf) {
+ res = _FAIL;
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
+ ("alloc recv_buf fail!\n"));
+ goto exit;
+ }
+ precvbuf = precvpriv->precv_buf;
+
+ for (i = 0; i < NR_RECVBUFF; i++) {
+ res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf);
+ if (res == _FAIL)
+ break;
+ precvbuf->adapter = padapter;
+ precvbuf++;
+ }
+ skb_queue_head_init(&precvpriv->rx_skb_queue);
+ {
+ int i;
+ struct sk_buff *pskb = NULL;
+
+ skb_queue_head_init(&precvpriv->free_recv_skb_queue);
+
+ for (i = 0; i < NR_PREALLOC_RECV_SKB; i++) {
+ pskb = __netdev_alloc_skb(padapter->pnetdev,
+ MAX_RECVBUF_SZ, GFP_KERNEL);
+ if (pskb) {
+ kmemleak_not_leak(pskb);
+ skb_queue_tail(&precvpriv->free_recv_skb_queue,
+ pskb);
+ }
+ pskb = NULL;
+ }
+ }
+exit:
+ return res;
+}
+
+void rtw_hal_free_recv_priv(struct adapter *padapter)
+{
+ int i;
+ struct recv_buf *precvbuf;
+ struct recv_priv *precvpriv = &padapter->recvpriv;
+
+ precvbuf = precvpriv->precv_buf;
+
+ for (i = 0; i < NR_RECVBUFF; i++) {
+ usb_free_urb(precvbuf->purb);
+ precvbuf++;
+ }
+
+ kfree(precvpriv->precv_buf);
+
+ if (skb_queue_len(&precvpriv->rx_skb_queue))
+ DBG_88E(KERN_WARNING "rx_skb_queue not empty\n");
+ skb_queue_purge(&precvpriv->rx_skb_queue);
+
+ if (skb_queue_len(&precvpriv->free_recv_skb_queue))
+ DBG_88E(KERN_WARNING "free_recv_skb_queue not empty, %d\n",
+ skb_queue_len(&precvpriv->free_recv_skb_queue));
+
+ skb_queue_purge(&precvpriv->free_recv_skb_queue);
+}
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c
new file mode 100644
index 0000000..ab94ad9
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/rtl8188eu_xmit.c
@@ -0,0 +1,662 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _RTL8188E_XMIT_C_
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <mon.h>
+#include <wifi.h>
+#include <osdep_intf.h>
+#include <usb_ops_linux.h>
+#include <rtl8188e_hal.h>
+
+s32 rtw_hal_init_xmit_priv(struct adapter *adapt)
+{
+ struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
+
+ tasklet_init(&pxmitpriv->xmit_tasklet,
+ (void(*)(unsigned long))rtl8188eu_xmit_tasklet,
+ (unsigned long)adapt);
+ return _SUCCESS;
+}
+
+static u8 urb_zero_packet_chk(struct adapter *adapt, int sz)
+{
+ return !((sz + TXDESC_SIZE) % adapt->HalData->UsbBulkOutSize);
+}
+
+static void rtl8188eu_cal_txdesc_chksum(struct tx_desc *ptxdesc)
+{
+ u16 *usptr = (u16 *)ptxdesc;
+ u32 count = 16; /* (32 bytes / 2 bytes per XOR) => 16 times */
+ u32 index;
+ u16 checksum = 0;
+
+ /* Clear first */
+ ptxdesc->txdw7 &= cpu_to_le32(0xffff0000);
+
+ for (index = 0; index < count; index++)
+ checksum = checksum ^ le16_to_cpu(*(__le16 *)(usptr + index));
+ ptxdesc->txdw7 |= cpu_to_le32(0x0000ffff & checksum);
+}
+
+/*
+ * In normal chip, we should send some packet to Hw which will be used by Fw
+ * in FW LPS mode. The function is to fill the Tx descriptor of this packets,
+ * then Fw can tell Hw to send these packet derectly.
+ */
+void rtl8188e_fill_fake_txdesc(struct adapter *adapt, u8 *desc, u32 BufferLen, u8 ispspoll, u8 is_btqosnull)
+{
+ struct tx_desc *ptxdesc;
+
+ /* Clear all status */
+ ptxdesc = (struct tx_desc *)desc;
+ memset(desc, 0, TXDESC_SIZE);
+
+ /* offset 0 */
+ ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); /* own, bFirstSeg, bLastSeg; */
+
+ ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000); /* 32 bytes for TX Desc */
+
+ ptxdesc->txdw0 |= cpu_to_le32(BufferLen&0x0000ffff); /* Buffer size + command header */
+
+ /* offset 4 */
+ ptxdesc->txdw1 |= cpu_to_le32((QSLT_MGNT<<QSEL_SHT)&0x00001f00); /* Fixed queue of Mgnt queue */
+
+ /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error vlaue by Hw. */
+ if (ispspoll) {
+ ptxdesc->txdw1 |= cpu_to_le32(NAVUSEHDR);
+ } else {
+ ptxdesc->txdw4 |= cpu_to_le32(BIT(7)); /* Hw set sequence number */
+ ptxdesc->txdw3 |= cpu_to_le32((8 << 28)); /* set bit3 to 1. Suugested by TimChen. 2009.12.29. */
+ }
+
+ if (is_btqosnull)
+ ptxdesc->txdw2 |= cpu_to_le32(BIT(23)); /* BT NULL */
+
+ /* offset 16 */
+ ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */
+
+ /* USB interface drop packet if the checksum of descriptor isn't correct. */
+ /* Using this checksum can let hardware recovery from packet bulk out error (e.g. Cancel URC, Bulk out error.). */
+ rtl8188eu_cal_txdesc_chksum(ptxdesc);
+}
+
+static void fill_txdesc_sectype(struct pkt_attrib *pattrib, struct tx_desc *ptxdesc)
+{
+ if ((pattrib->encrypt > 0) && !pattrib->bswenc) {
+ switch (pattrib->encrypt) {
+ /* SEC_TYPE : 0:NO_ENC,1:WEP40/TKIP,2:WAPI,3:AES */
+ case _WEP40_:
+ case _WEP104_:
+ ptxdesc->txdw1 |= cpu_to_le32((0x01<<SEC_TYPE_SHT)&0x00c00000);
+ ptxdesc->txdw2 |= cpu_to_le32(0x7 << AMPDU_DENSITY_SHT);
+ break;
+ case _TKIP_:
+ case _TKIP_WTMIC_:
+ ptxdesc->txdw1 |= cpu_to_le32((0x01<<SEC_TYPE_SHT)&0x00c00000);
+ ptxdesc->txdw2 |= cpu_to_le32(0x7 << AMPDU_DENSITY_SHT);
+ break;
+ case _AES_:
+ ptxdesc->txdw1 |= cpu_to_le32((0x03<<SEC_TYPE_SHT)&0x00c00000);
+ ptxdesc->txdw2 |= cpu_to_le32(0x7 << AMPDU_DENSITY_SHT);
+ break;
+ case _NO_PRIVACY_:
+ default:
+ break;
+ }
+ }
+}
+
+static void fill_txdesc_vcs(struct pkt_attrib *pattrib, __le32 *pdw)
+{
+ switch (pattrib->vcs_mode) {
+ case RTS_CTS:
+ *pdw |= cpu_to_le32(RTS_EN);
+ break;
+ case CTS_TO_SELF:
+ *pdw |= cpu_to_le32(CTS_2_SELF);
+ break;
+ case NONE_VCS:
+ default:
+ break;
+ }
+ if (pattrib->vcs_mode) {
+ *pdw |= cpu_to_le32(HW_RTS_EN);
+ /* Set RTS BW */
+ if (pattrib->ht_en) {
+ *pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(27)) : 0;
+
+ if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
+ *pdw |= cpu_to_le32((0x01 << 28) & 0x30000000);
+ else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
+ *pdw |= cpu_to_le32((0x02 << 28) & 0x30000000);
+ else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
+ *pdw |= 0;
+ else
+ *pdw |= cpu_to_le32((0x03 << 28) & 0x30000000);
+ }
+ }
+}
+
+static void fill_txdesc_phy(struct pkt_attrib *pattrib, __le32 *pdw)
+{
+ if (pattrib->ht_en) {
+ *pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(25)) : 0;
+
+ if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
+ *pdw |= cpu_to_le32((0x01 << DATA_SC_SHT) & 0x003f0000);
+ else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
+ *pdw |= cpu_to_le32((0x02 << DATA_SC_SHT) & 0x003f0000);
+ else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
+ *pdw |= 0;
+ else
+ *pdw |= cpu_to_le32((0x03 << DATA_SC_SHT) & 0x003f0000);
+ }
+}
+
+static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bagg_pkt)
+{
+ int pull = 0;
+ uint qsel;
+ u8 data_rate, pwr_status, offset;
+ struct adapter *adapt = pxmitframe->padapter;
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+ struct odm_dm_struct *odmpriv = &adapt->HalData->odmpriv;
+ struct tx_desc *ptxdesc = (struct tx_desc *)pmem;
+ struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ if (adapt->registrypriv.mp_mode == 0) {
+ if ((!bagg_pkt) && (urb_zero_packet_chk(adapt, sz) == 0)) {
+ ptxdesc = (struct tx_desc *)(pmem+PACKET_OFFSET_SZ);
+ pull = 1;
+ }
+ }
+
+ memset(ptxdesc, 0, sizeof(struct tx_desc));
+
+ /* 4 offset 0 */
+ ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
+ ptxdesc->txdw0 |= cpu_to_le32(sz & 0x0000ffff);/* update TXPKTSIZE */
+
+ offset = TXDESC_SIZE + OFFSET_SZ;
+
+ ptxdesc->txdw0 |= cpu_to_le32(((offset) << OFFSET_SHT) & 0x00ff0000);/* 32 bytes for TX Desc */
+
+ if (is_multicast_ether_addr(pattrib->ra))
+ ptxdesc->txdw0 |= cpu_to_le32(BMC);
+
+ if (adapt->registrypriv.mp_mode == 0) {
+ if (!bagg_pkt) {
+ if ((pull) && (pxmitframe->pkt_offset > 0))
+ pxmitframe->pkt_offset = pxmitframe->pkt_offset - 1;
+ }
+ }
+
+ /* pkt_offset, unit:8 bytes padding */
+ if (pxmitframe->pkt_offset > 0)
+ ptxdesc->txdw1 |= cpu_to_le32((pxmitframe->pkt_offset << 26) & 0x7c000000);
+
+ /* driver uses rate */
+ ptxdesc->txdw4 |= cpu_to_le32(USERATE);/* rate control always by driver */
+
+ if ((pxmitframe->frame_tag & 0x0f) == DATA_FRAMETAG) {
+ /* offset 4 */
+ ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id & 0x3F);
+
+ qsel = (uint)(pattrib->qsel & 0x0000001f);
+ ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
+
+ ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid << RATE_ID_SHT) & 0x000F0000);
+
+ fill_txdesc_sectype(pattrib, ptxdesc);
+
+ if (pattrib->ampdu_en) {
+ ptxdesc->txdw2 |= cpu_to_le32(AGG_EN);/* AGG EN */
+ ptxdesc->txdw6 = cpu_to_le32(0x6666f800);
+ } else {
+ ptxdesc->txdw2 |= cpu_to_le32(AGG_BK);/* AGG BK */
+ }
+
+ /* offset 8 */
+
+ /* offset 12 */
+ ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum << SEQ_SHT) & 0x0FFF0000);
+
+ /* offset 16 , offset 20 */
+ if (pattrib->qos_en)
+ ptxdesc->txdw4 |= cpu_to_le32(QOS);/* QoS */
+
+ /* offset 20 */
+ if (pxmitframe->agg_num > 1)
+ ptxdesc->txdw5 |= cpu_to_le32((pxmitframe->agg_num << USB_TXAGG_NUM_SHT) & 0xFF000000);
+
+ if ((pattrib->ether_type != 0x888e) &&
+ (pattrib->ether_type != 0x0806) &&
+ (pattrib->ether_type != 0x88b4) &&
+ (pattrib->dhcp_pkt != 1)) {
+ /* Non EAP & ARP & DHCP type data packet */
+
+ fill_txdesc_vcs(pattrib, &ptxdesc->txdw4);
+ fill_txdesc_phy(pattrib, &ptxdesc->txdw4);
+
+ ptxdesc->txdw4 |= cpu_to_le32(0x00000008);/* RTS Rate=24M */
+ ptxdesc->txdw5 |= cpu_to_le32(0x0001ff00);/* DATA/RTS Rate FB LMT */
+
+ if (pattrib->ht_en) {
+ if (ODM_RA_GetShortGI_8188E(odmpriv, pattrib->mac_id))
+ ptxdesc->txdw5 |= cpu_to_le32(SGI);/* SGI */
+ }
+ data_rate = ODM_RA_GetDecisionRate_8188E(odmpriv, pattrib->mac_id);
+ ptxdesc->txdw5 |= cpu_to_le32(data_rate & 0x3F);
+ pwr_status = ODM_RA_GetHwPwrStatus_8188E(odmpriv, pattrib->mac_id);
+ ptxdesc->txdw4 |= cpu_to_le32((pwr_status & 0x7) << PWR_STATUS_SHT);
+ } else {
+ /* EAP data packet and ARP packet and DHCP. */
+ /* Use the 1M data rate to send the EAP/ARP packet. */
+ /* This will maybe make the handshake smooth. */
+ ptxdesc->txdw2 |= cpu_to_le32(AGG_BK);/* AGG BK */
+ if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT)
+ ptxdesc->txdw4 |= cpu_to_le32(BIT(24));/* DATA_SHORT */
+ ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate));
+ }
+ } else if ((pxmitframe->frame_tag&0x0f) == MGNT_FRAMETAG) {
+ /* offset 4 */
+ ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id & 0x3f);
+
+ qsel = (uint)(pattrib->qsel&0x0000001f);
+ ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
+
+ ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid << RATE_ID_SHT) & 0x000f0000);
+
+ /* offset 8 */
+ /* CCX-TXRPT ack for xmit mgmt frames. */
+ if (pxmitframe->ack_report)
+ ptxdesc->txdw2 |= cpu_to_le32(BIT(19));
+
+ /* offset 12 */
+ ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<SEQ_SHT)&0x0FFF0000);
+
+ /* offset 20 */
+ ptxdesc->txdw5 |= cpu_to_le32(RTY_LMT_EN);/* retry limit enable */
+ if (pattrib->retry_ctrl)
+ ptxdesc->txdw5 |= cpu_to_le32(0x00180000);/* retry limit = 6 */
+ else
+ ptxdesc->txdw5 |= cpu_to_le32(0x00300000);/* retry limit = 12 */
+
+ ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate));
+ } else if ((pxmitframe->frame_tag&0x0f) == TXAGG_FRAMETAG) {
+ DBG_88E("pxmitframe->frame_tag == TXAGG_FRAMETAG\n");
+ } else {
+ DBG_88E("pxmitframe->frame_tag = %d\n", pxmitframe->frame_tag);
+
+ /* offset 4 */
+ ptxdesc->txdw1 |= cpu_to_le32((4) & 0x3f);/* CAM_ID(MAC_ID) */
+
+ ptxdesc->txdw1 |= cpu_to_le32((6 << RATE_ID_SHT) & 0x000f0000);/* raid */
+
+ /* offset 8 */
+
+ /* offset 12 */
+ ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<SEQ_SHT)&0x0fff0000);
+
+ /* offset 20 */
+ ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate));
+ }
+
+ /* 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS. */
+ /* (1) The sequence number of each non-Qos frame / broadcast / multicast / */
+ /* mgnt frame should be controlled by Hw because Fw will also send null data */
+ /* which we cannot control when Fw LPS enable. */
+ /* --> default enable non-Qos data sequense number. 2010.06.23. by tynli. */
+ /* (2) Enable HW SEQ control for beacon packet, because we use Hw beacon. */
+ /* (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos packets. */
+ /* 2010.06.23. Added by tynli. */
+ if (!pattrib->qos_en) {
+ ptxdesc->txdw3 |= cpu_to_le32(EN_HWSEQ); /* Hw set sequence number */
+ ptxdesc->txdw4 |= cpu_to_le32(HW_SSN); /* Hw set sequence number */
+ }
+
+ rtl88eu_dm_set_tx_ant_by_tx_info(odmpriv, pmem, pattrib->mac_id);
+
+ rtl8188eu_cal_txdesc_chksum(ptxdesc);
+ _dbg_dump_tx_info(adapt, pxmitframe->frame_tag, ptxdesc);
+ return pull;
+}
+
+/* for non-agg data frame or management frame */
+static s32 rtw_dump_xframe(struct adapter *adapt, struct xmit_frame *pxmitframe)
+{
+ s32 ret = _SUCCESS;
+ s32 inner_ret = _SUCCESS;
+ int t, sz, w_sz, pull = 0;
+ u8 *mem_addr;
+ u32 ff_hwaddr;
+ struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf;
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+ struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
+
+ if ((pxmitframe->frame_tag == DATA_FRAMETAG) &&
+ (pxmitframe->attrib.ether_type != 0x0806) &&
+ (pxmitframe->attrib.ether_type != 0x888e) &&
+ (pxmitframe->attrib.ether_type != 0x88b4) &&
+ (pxmitframe->attrib.dhcp_pkt != 1))
+ rtw_issue_addbareq_cmd(adapt, pxmitframe);
+ mem_addr = pxmitframe->buf_addr;
+
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_dump_xframe()\n"));
+
+ for (t = 0; t < pattrib->nr_frags; t++) {
+ if (inner_ret != _SUCCESS && ret == _SUCCESS)
+ ret = _FAIL;
+
+ if (t != (pattrib->nr_frags - 1)) {
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("pattrib->nr_frags=%d\n", pattrib->nr_frags));
+
+ sz = pxmitpriv->frag_len;
+ sz = sz - 4 - pattrib->icv_len;
+ } else {
+ /* no frag */
+ sz = pattrib->last_txcmdsz;
+ }
+
+ pull = update_txdesc(pxmitframe, mem_addr, sz, false);
+
+ if (pull) {
+ mem_addr += PACKET_OFFSET_SZ; /* pull txdesc head */
+ pxmitframe->buf_addr = mem_addr;
+ w_sz = sz + TXDESC_SIZE;
+ } else {
+ w_sz = sz + TXDESC_SIZE + PACKET_OFFSET_SZ;
+ }
+ ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
+
+ inner_ret = usb_write_port(adapt, ff_hwaddr, w_sz, pxmitbuf);
+
+ rtw_count_tx_stats(adapt, pxmitframe, sz);
+
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_write_port, w_sz=%d\n", w_sz));
+
+ mem_addr += w_sz;
+
+ mem_addr = (u8 *)round_up((size_t)mem_addr, 4);
+ }
+
+ rtw_free_xmitframe(pxmitpriv, pxmitframe);
+
+ if (ret != _SUCCESS)
+ rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN);
+
+ return ret;
+}
+
+static u32 xmitframe_need_length(struct xmit_frame *pxmitframe)
+{
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+
+ u32 len;
+
+ /* no consider fragement */
+ len = pattrib->hdrlen + pattrib->iv_len +
+ SNAP_SIZE + sizeof(u16) +
+ pattrib->pktlen +
+ ((pattrib->bswenc) ? pattrib->icv_len : 0);
+
+ if (pattrib->encrypt == _TKIP_)
+ len += 8;
+
+ return len;
+}
+
+bool rtl8188eu_xmitframe_complete(struct adapter *adapt,
+ struct xmit_priv *pxmitpriv)
+{
+ struct xmit_frame *pxmitframe = NULL;
+ struct xmit_frame *pfirstframe = NULL;
+ struct xmit_buf *pxmitbuf;
+
+ /* aggregate variable */
+ struct hw_xmit *phwxmit;
+ struct sta_info *psta = NULL;
+ struct tx_servq *ptxservq = NULL;
+
+ struct list_head *xmitframe_plist = NULL, *xmitframe_phead = NULL;
+
+ u32 pbuf; /* next pkt address */
+ u32 pbuf_tail; /* last pkt tail */
+ u32 len; /* packet length, except TXDESC_SIZE and PKT_OFFSET */
+
+ u32 bulksize = adapt->HalData->UsbBulkOutSize;
+ u8 desc_cnt;
+ u32 bulkptr;
+
+ /* dump frame variable */
+ u32 ff_hwaddr;
+
+ RT_TRACE(_module_rtl8192c_xmit_c_, _drv_info_, ("+xmitframe_complete\n"));
+
+ pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
+ if (!pxmitbuf)
+ return false;
+
+ /* 3 1. pick up first frame */
+ rtw_free_xmitframe(pxmitpriv, pxmitframe);
+
+ pxmitframe = rtw_dequeue_xframe(pxmitpriv, pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
+ if (!pxmitframe) {
+ /* no more xmit frame, release xmit buffer */
+ rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
+ return false;
+ }
+
+ pxmitframe->pxmitbuf = pxmitbuf;
+ pxmitframe->buf_addr = pxmitbuf->pbuf;
+ pxmitbuf->priv_data = pxmitframe;
+
+ pxmitframe->agg_num = 1; /* alloc xmitframe should assign to 1. */
+ pxmitframe->pkt_offset = 1; /* first frame of aggregation, reserve offset */
+
+ rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe);
+
+ /* always return ndis_packet after rtw_xmitframe_coalesce */
+ rtw_os_xmit_complete(adapt, pxmitframe);
+
+ /* 3 2. aggregate same priority and same DA(AP or STA) frames */
+ pfirstframe = pxmitframe;
+ len = xmitframe_need_length(pfirstframe) + TXDESC_SIZE + (pfirstframe->pkt_offset*PACKET_OFFSET_SZ);
+ pbuf_tail = len;
+ pbuf = round_up(pbuf_tail, 8);
+
+ /* check pkt amount in one bulk */
+ desc_cnt = 0;
+ bulkptr = bulksize;
+ if (pbuf < bulkptr) {
+ desc_cnt++;
+ } else {
+ desc_cnt = 0;
+ bulkptr = ((pbuf / bulksize) + 1) * bulksize; /* round to next bulksize */
+ }
+
+ /* dequeue same priority packet from station tx queue */
+ psta = pfirstframe->attrib.psta;
+ switch (pfirstframe->attrib.priority) {
+ case 1:
+ case 2:
+ ptxservq = &psta->sta_xmitpriv.bk_q;
+ phwxmit = pxmitpriv->hwxmits + 3;
+ break;
+ case 4:
+ case 5:
+ ptxservq = &psta->sta_xmitpriv.vi_q;
+ phwxmit = pxmitpriv->hwxmits + 1;
+ break;
+ case 6:
+ case 7:
+ ptxservq = &psta->sta_xmitpriv.vo_q;
+ phwxmit = pxmitpriv->hwxmits;
+ break;
+ case 0:
+ case 3:
+ default:
+ ptxservq = &psta->sta_xmitpriv.be_q;
+ phwxmit = pxmitpriv->hwxmits + 2;
+ break;
+ }
+ spin_lock_bh(&pxmitpriv->lock);
+
+ xmitframe_phead = get_list_head(&ptxservq->sta_pending);
+ xmitframe_plist = xmitframe_phead->next;
+
+ while (xmitframe_phead != xmitframe_plist) {
+ pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list);
+ xmitframe_plist = xmitframe_plist->next;
+
+ pxmitframe->agg_num = 0; /* not first frame of aggregation */
+ pxmitframe->pkt_offset = 0; /* not first frame of aggregation, no need to reserve offset */
+
+ len = xmitframe_need_length(pxmitframe) + TXDESC_SIZE + (pxmitframe->pkt_offset*PACKET_OFFSET_SZ);
+
+ if (round_up(pbuf + len, 8) > MAX_XMITBUF_SZ) {
+ pxmitframe->agg_num = 1;
+ pxmitframe->pkt_offset = 1;
+ break;
+ }
+ list_del_init(&pxmitframe->list);
+ ptxservq->qcnt--;
+ phwxmit->accnt--;
+
+ pxmitframe->buf_addr = pxmitbuf->pbuf + pbuf;
+
+ rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe);
+ /* always return ndis_packet after rtw_xmitframe_coalesce */
+ rtw_os_xmit_complete(adapt, pxmitframe);
+
+ /* (len - TXDESC_SIZE) == pxmitframe->attrib.last_txcmdsz */
+ update_txdesc(pxmitframe, pxmitframe->buf_addr, pxmitframe->attrib.last_txcmdsz, true);
+
+ /* don't need xmitframe any more */
+ rtw_free_xmitframe(pxmitpriv, pxmitframe);
+
+ /* handle pointer and stop condition */
+ pbuf_tail = pbuf + len;
+ pbuf = round_up(pbuf_tail, 8);
+
+ pfirstframe->agg_num++;
+ if (pfirstframe->agg_num == MAX_TX_AGG_PACKET_NUMBER)
+ break;
+
+ if (pbuf < bulkptr) {
+ desc_cnt++;
+ if (desc_cnt == adapt->HalData->UsbTxAggDescNum)
+ break;
+ } else {
+ desc_cnt = 0;
+ bulkptr = ((pbuf / bulksize) + 1) * bulksize;
+ }
+ } /* end while (aggregate same priority and same DA(AP or STA) frames) */
+
+ if (list_empty(&ptxservq->sta_pending.queue))
+ list_del_init(&ptxservq->tx_pending);
+
+ spin_unlock_bh(&pxmitpriv->lock);
+ if ((pfirstframe->attrib.ether_type != 0x0806) &&
+ (pfirstframe->attrib.ether_type != 0x888e) &&
+ (pfirstframe->attrib.ether_type != 0x88b4) &&
+ (pfirstframe->attrib.dhcp_pkt != 1))
+ rtw_issue_addbareq_cmd(adapt, pfirstframe);
+ /* 3 3. update first frame txdesc */
+ if ((pbuf_tail % bulksize) == 0) {
+ /* remove pkt_offset */
+ pbuf_tail -= PACKET_OFFSET_SZ;
+ pfirstframe->buf_addr += PACKET_OFFSET_SZ;
+ pfirstframe->pkt_offset--;
+ }
+
+ update_txdesc(pfirstframe, pfirstframe->buf_addr, pfirstframe->attrib.last_txcmdsz, true);
+
+ /* 3 4. write xmit buffer to USB FIFO */
+ ff_hwaddr = rtw_get_ff_hwaddr(pfirstframe);
+ usb_write_port(adapt, ff_hwaddr, pbuf_tail, pxmitbuf);
+
+ /* 3 5. update statisitc */
+ pbuf_tail -= (pfirstframe->agg_num * TXDESC_SIZE);
+ pbuf_tail -= (pfirstframe->pkt_offset * PACKET_OFFSET_SZ);
+
+ rtw_count_tx_stats(adapt, pfirstframe, pbuf_tail);
+
+ rtw_free_xmitframe(pxmitpriv, pfirstframe);
+
+ return true;
+}
+
+/*
+ * Return
+ * true dump packet directly
+ * false enqueue packet
+ */
+bool rtw_hal_xmit(struct adapter *adapt, struct xmit_frame *pxmitframe)
+{
+ s32 res;
+ struct xmit_buf *pxmitbuf = NULL;
+ struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+ struct mlme_priv *pmlmepriv = &adapt->mlmepriv;
+
+ spin_lock_bh(&pxmitpriv->lock);
+
+ if (rtw_txframes_sta_ac_pending(adapt, pattrib) > 0)
+ goto enqueue;
+
+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING))
+ goto enqueue;
+
+ pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
+ if (!pxmitbuf)
+ goto enqueue;
+
+ spin_unlock_bh(&pxmitpriv->lock);
+
+ pxmitframe->pxmitbuf = pxmitbuf;
+ pxmitframe->buf_addr = pxmitbuf->pbuf;
+ pxmitbuf->priv_data = pxmitframe;
+
+ res = rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe);
+
+ if (res == _SUCCESS) {
+ rtw_dump_xframe(adapt, pxmitframe);
+ } else {
+ DBG_88E("==> %s xmitframe_coalesce failed\n", __func__);
+ rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
+ rtw_free_xmitframe(pxmitpriv, pxmitframe);
+ }
+
+ return true;
+
+enqueue:
+ res = rtw_xmitframe_enqueue(adapt, pxmitframe);
+ spin_unlock_bh(&pxmitpriv->lock);
+
+ if (res != _SUCCESS) {
+ RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("pre_xmitframe: enqueue xmitframe fail\n"));
+ rtw_free_xmitframe(pxmitpriv, pxmitframe);
+
+ /* Trick, make the statistics correct */
+ pxmitpriv->tx_pkts--;
+ pxmitpriv->tx_drop++;
+ return true;
+ }
+
+ return false;
+}
+
+s32 rtw_hal_mgnt_xmit(struct adapter *adapt, struct xmit_frame *pmgntframe)
+{
+ struct xmit_priv *xmitpriv = &adapt->xmitpriv;
+
+ rtl88eu_mon_xmit_hook(adapt->pmondev, pmgntframe, xmitpriv->frag_len);
+ return rtw_dump_xframe(adapt, pmgntframe);
+}
diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c
new file mode 100644
index 0000000..16a57b3
--- /dev/null
+++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c
@@ -0,0 +1,1992 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _HCI_HAL_INIT_C_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <rtw_efuse.h>
+#include <fw.h>
+#include <rtl8188e_hal.h>
+#include <phy.h>
+
+#define HAL_BB_ENABLE 1
+
+static void _ConfigNormalChipOutEP_8188E(struct adapter *adapt, u8 NumOutPipe)
+{
+ struct hal_data_8188e *haldata = adapt->HalData;
+
+ switch (NumOutPipe) {
+ case 3:
+ haldata->OutEpQueueSel = TX_SELE_HQ | TX_SELE_LQ | TX_SELE_NQ;
+ haldata->OutEpNumber = 3;
+ break;
+ case 2:
+ haldata->OutEpQueueSel = TX_SELE_HQ | TX_SELE_NQ;
+ haldata->OutEpNumber = 2;
+ break;
+ case 1:
+ haldata->OutEpQueueSel = TX_SELE_HQ;
+ haldata->OutEpNumber = 1;
+ break;
+ default:
+ break;
+ }
+ DBG_88E("%s OutEpQueueSel(0x%02x), OutEpNumber(%d)\n", __func__, haldata->OutEpQueueSel, haldata->OutEpNumber);
+}
+
+static bool HalUsbSetQueuePipeMapping8188EUsb(struct adapter *adapt, u8 NumInPipe, u8 NumOutPipe)
+{
+ bool result = false;
+
+ _ConfigNormalChipOutEP_8188E(adapt, NumOutPipe);
+
+ /* Normal chip with one IN and one OUT doesn't have interrupt IN EP. */
+ if (adapt->HalData->OutEpNumber == 1) {
+ if (NumInPipe != 1)
+ return result;
+ }
+
+ /* All config other than above support one Bulk IN and one Interrupt IN. */
+
+ result = hal_mapping_out_pipe(adapt, NumOutPipe);
+
+ return result;
+}
+
+void rtw_hal_chip_configure(struct adapter *adapt)
+{
+ struct hal_data_8188e *haldata = adapt->HalData;
+ struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapt);
+
+ if (pdvobjpriv->ishighspeed)
+ haldata->UsbBulkOutSize = USB_HIGH_SPEED_BULK_SIZE;/* 512 bytes */
+ else
+ haldata->UsbBulkOutSize = USB_FULL_SPEED_BULK_SIZE;/* 64 bytes */
+
+ haldata->interfaceIndex = pdvobjpriv->InterfaceNumber;
+
+ haldata->UsbTxAggMode = 1;
+ haldata->UsbTxAggDescNum = 0x6; /* only 4 bits */
+
+ haldata->UsbRxAggMode = USB_RX_AGG_DMA;/* USB_RX_AGG_DMA; */
+ haldata->UsbRxAggBlockCount = 8; /* unit : 512b */
+ haldata->UsbRxAggBlockTimeout = 0x6;
+ haldata->UsbRxAggPageCount = 48; /* uint :128 b 0x0A; 10 = MAX_RX_DMA_BUFFER_SIZE/2/haldata->UsbBulkOutSize */
+ haldata->UsbRxAggPageTimeout = 0x4; /* 6, absolute time = 34ms/(2^6) */
+
+ HalUsbSetQueuePipeMapping8188EUsb(adapt,
+ pdvobjpriv->RtNumInPipes, pdvobjpriv->RtNumOutPipes);
+}
+
+u32 rtw_hal_power_on(struct adapter *adapt)
+{
+ u16 value16;
+ /* HW Power on sequence */
+ if (adapt->HalData->bMacPwrCtrlOn)
+ return _SUCCESS;
+
+ if (!rtl88eu_pwrseqcmdparsing(adapt, PWR_CUT_ALL_MSK,
+ Rtl8188E_NIC_PWR_ON_FLOW)) {
+ DBG_88E(KERN_ERR "%s: run power on flow fail\n", __func__);
+ return _FAIL;
+ }
+
+ /* Enable MAC DMA/WMAC/SCHEDULE/SEC block */
+ /* Set CR bit10 to enable 32k calibration. Suggested by SD1 Gimmy. Added by tynli. 2011.08.31. */
+ usb_write16(adapt, REG_CR, 0x00); /* suggseted by zhouzhou, by page, 20111230 */
+
+ /* Enable MAC DMA/WMAC/SCHEDULE/SEC block */
+ value16 = usb_read16(adapt, REG_CR);
+ value16 |= (HCI_TXDMA_EN | HCI_RXDMA_EN | TXDMA_EN | RXDMA_EN
+ | PROTOCOL_EN | SCHEDULE_EN | ENSEC | CALTMR_EN);
+ /* for SDIO - Set CR bit10 to enable 32k calibration. Suggested by SD1 Gimmy. Added by tynli. 2011.08.31. */
+
+ usb_write16(adapt, REG_CR, value16);
+ adapt->HalData->bMacPwrCtrlOn = true;
+
+ return _SUCCESS;
+}
+
+/* Shall USB interface init this? */
+static void _InitInterrupt(struct adapter *Adapter)
+{
+ u32 imr, imr_ex;
+ u8 usb_opt;
+
+ /* HISR write one to clear */
+ usb_write32(Adapter, REG_HISR_88E, 0xFFFFFFFF);
+ /* HIMR - */
+ imr = IMR_PSTIMEOUT_88E | IMR_TBDER_88E | IMR_CPWM_88E | IMR_CPWM2_88E;
+ usb_write32(Adapter, REG_HIMR_88E, imr);
+ Adapter->HalData->IntrMask[0] = imr;
+
+ imr_ex = IMR_TXERR_88E | IMR_RXERR_88E | IMR_TXFOVW_88E | IMR_RXFOVW_88E;
+ usb_write32(Adapter, REG_HIMRE_88E, imr_ex);
+ Adapter->HalData->IntrMask[1] = imr_ex;
+
+ /* REG_USB_SPECIAL_OPTION - BIT(4) */
+ /* 0; Use interrupt endpoint to upload interrupt pkt */
+ /* 1; Use bulk endpoint to upload interrupt pkt, */
+ usb_opt = usb_read8(Adapter, REG_USB_SPECIAL_OPTION);
+
+ if (!adapter_to_dvobj(Adapter)->ishighspeed)
+ usb_opt = usb_opt & (~INT_BULK_SEL);
+ else
+ usb_opt = usb_opt | (INT_BULK_SEL);
+
+ usb_write8(Adapter, REG_USB_SPECIAL_OPTION, usb_opt);
+}
+
+static void _InitQueueReservedPage(struct adapter *Adapter)
+{
+ struct registry_priv *pregistrypriv = &Adapter->registrypriv;
+ u32 numHQ = 0;
+ u32 numLQ = 0;
+ u32 numNQ = 0;
+ u32 numPubQ;
+ u32 value32;
+ u8 value8;
+ bool bWiFiConfig = pregistrypriv->wifi_spec;
+
+ if (bWiFiConfig) {
+ if (Adapter->HalData->OutEpQueueSel & TX_SELE_HQ)
+ numHQ = 0x29;
+
+ if (Adapter->HalData->OutEpQueueSel & TX_SELE_LQ)
+ numLQ = 0x1C;
+
+ /* NOTE: This step shall be proceed before writing REG_RQPN. */
+ if (Adapter->HalData->OutEpQueueSel & TX_SELE_NQ)
+ numNQ = 0x1C;
+ value8 = (u8)_NPQ(numNQ);
+ usb_write8(Adapter, REG_RQPN_NPQ, value8);
+
+ numPubQ = 0xA8 - numHQ - numLQ - numNQ;
+
+ /* TX DMA */
+ value32 = _HPQ(numHQ) | _LPQ(numLQ) | _PUBQ(numPubQ) | LD_RQPN;
+ usb_write32(Adapter, REG_RQPN, value32);
+ } else {
+ usb_write16(Adapter, REG_RQPN_NPQ, 0x0000);/* Just follow MP Team,??? Georgia 03/28 */
+ usb_write16(Adapter, REG_RQPN_NPQ, 0x0d);
+ usb_write32(Adapter, REG_RQPN, 0x808E000d);/* reserve 7 page for LPS */
+ }
+}
+
+static void _InitTxBufferBoundary(struct adapter *Adapter, u8 txpktbuf_bndy)
+{
+ usb_write8(Adapter, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy);
+ usb_write8(Adapter, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy);
+ usb_write8(Adapter, REG_TXPKTBUF_WMAC_LBK_BF_HD, txpktbuf_bndy);
+ usb_write8(Adapter, REG_TRXFF_BNDY, txpktbuf_bndy);
+ usb_write8(Adapter, REG_TDECTRL + 1, txpktbuf_bndy);
+}
+
+static void _InitPageBoundary(struct adapter *Adapter)
+{
+ /* RX Page Boundary */
+ /* */
+ u16 rxff_bndy = MAX_RX_DMA_BUFFER_SIZE_88E - 1;
+
+ usb_write16(Adapter, (REG_TRXFF_BNDY + 2), rxff_bndy);
+}
+
+static void _InitNormalChipRegPriority(struct adapter *Adapter, u16 beQ,
+ u16 bkQ, u16 viQ, u16 voQ, u16 mgtQ,
+ u16 hiQ)
+{
+ u16 value16 = (usb_read16(Adapter, REG_TRXDMA_CTRL) & 0x7);
+
+ value16 |= _TXDMA_BEQ_MAP(beQ) | _TXDMA_BKQ_MAP(bkQ) |
+ _TXDMA_VIQ_MAP(viQ) | _TXDMA_VOQ_MAP(voQ) |
+ _TXDMA_MGQ_MAP(mgtQ) | _TXDMA_HIQ_MAP(hiQ);
+
+ usb_write16(Adapter, REG_TRXDMA_CTRL, value16);
+}
+
+static void _InitNormalChipOneOutEpPriority(struct adapter *Adapter)
+{
+ u16 value = 0;
+
+ switch (Adapter->HalData->OutEpQueueSel) {
+ case TX_SELE_HQ:
+ value = QUEUE_HIGH;
+ break;
+ case TX_SELE_LQ:
+ value = QUEUE_LOW;
+ break;
+ case TX_SELE_NQ:
+ value = QUEUE_NORMAL;
+ break;
+ default:
+ break;
+ }
+ _InitNormalChipRegPriority(Adapter, value, value, value, value,
+ value, value);
+}
+
+static void _InitNormalChipTwoOutEpPriority(struct adapter *Adapter)
+{
+ struct registry_priv *pregistrypriv = &Adapter->registrypriv;
+ u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ;
+ u16 valueHi = 0;
+ u16 valueLow = 0;
+
+ switch (Adapter->HalData->OutEpQueueSel) {
+ case (TX_SELE_HQ | TX_SELE_LQ):
+ valueHi = QUEUE_HIGH;
+ valueLow = QUEUE_LOW;
+ break;
+ case (TX_SELE_NQ | TX_SELE_LQ):
+ valueHi = QUEUE_NORMAL;
+ valueLow = QUEUE_LOW;
+ break;
+ case (TX_SELE_HQ | TX_SELE_NQ):
+ valueHi = QUEUE_HIGH;
+ valueLow = QUEUE_NORMAL;
+ break;
+ default:
+ break;
+ }
+
+ if (!pregistrypriv->wifi_spec) {
+ beQ = valueLow;
+ bkQ = valueLow;
+ viQ = valueHi;
+ voQ = valueHi;
+ mgtQ = valueHi;
+ hiQ = valueHi;
+ } else {/* for WMM ,CONFIG_OUT_EP_WIFI_MODE */
+ beQ = valueLow;
+ bkQ = valueHi;
+ viQ = valueHi;
+ voQ = valueLow;
+ mgtQ = valueHi;
+ hiQ = valueHi;
+ }
+ _InitNormalChipRegPriority(Adapter, beQ, bkQ, viQ, voQ, mgtQ, hiQ);
+}
+
+static void _InitNormalChipThreeOutEpPriority(struct adapter *Adapter)
+{
+ struct registry_priv *pregistrypriv = &Adapter->registrypriv;
+ u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ;
+
+ if (!pregistrypriv->wifi_spec) {/* typical setting */
+ beQ = QUEUE_LOW;
+ bkQ = QUEUE_LOW;
+ viQ = QUEUE_NORMAL;
+ voQ = QUEUE_HIGH;
+ mgtQ = QUEUE_HIGH;
+ hiQ = QUEUE_HIGH;
+ } else {/* for WMM */
+ beQ = QUEUE_LOW;
+ bkQ = QUEUE_NORMAL;
+ viQ = QUEUE_NORMAL;
+ voQ = QUEUE_HIGH;
+ mgtQ = QUEUE_HIGH;
+ hiQ = QUEUE_HIGH;
+ }
+ _InitNormalChipRegPriority(Adapter, beQ, bkQ, viQ, voQ, mgtQ, hiQ);
+}
+
+static void _InitQueuePriority(struct adapter *Adapter)
+{
+ switch (Adapter->HalData->OutEpNumber) {
+ case 1:
+ _InitNormalChipOneOutEpPriority(Adapter);
+ break;
+ case 2:
+ _InitNormalChipTwoOutEpPriority(Adapter);
+ break;
+ case 3:
+ _InitNormalChipThreeOutEpPriority(Adapter);
+ break;
+ default:
+ break;
+ }
+}
+
+static void _InitNetworkType(struct adapter *Adapter)
+{
+ u32 value32;
+
+ value32 = usb_read32(Adapter, REG_CR);
+ /* TODO: use the other function to set network type */
+ value32 = (value32 & ~MASK_NETTYPE) | _NETTYPE(NT_LINK_AP);
+
+ usb_write32(Adapter, REG_CR, value32);
+}
+
+static void _InitTransferPageSize(struct adapter *Adapter)
+{
+ /* Tx page size is always 128. */
+
+ u8 value8;
+
+ value8 = _PSRX(PBP_128) | _PSTX(PBP_128);
+ usb_write8(Adapter, REG_PBP, value8);
+}
+
+static void _InitDriverInfoSize(struct adapter *Adapter, u8 drvInfoSize)
+{
+ usb_write8(Adapter, REG_RX_DRVINFO_SZ, drvInfoSize);
+}
+
+static void _InitWMACSetting(struct adapter *Adapter)
+{
+ struct hal_data_8188e *haldata = Adapter->HalData;
+
+ haldata->ReceiveConfig = RCR_AAP | RCR_APM | RCR_AM | RCR_AB |
+ RCR_CBSSID_DATA | RCR_CBSSID_BCN |
+ RCR_APP_ICV | RCR_AMF | RCR_HTC_LOC_CTRL |
+ RCR_APP_MIC | RCR_APP_PHYSTS;
+
+ /* some REG_RCR will be modified later by phy_ConfigMACWithHeaderFile() */
+ usb_write32(Adapter, REG_RCR, haldata->ReceiveConfig);
+
+ /* Accept all multicast address */
+ usb_write32(Adapter, REG_MAR, 0xFFFFFFFF);
+ usb_write32(Adapter, REG_MAR + 4, 0xFFFFFFFF);
+}
+
+static void _InitAdaptiveCtrl(struct adapter *Adapter)
+{
+ u16 value16;
+ u32 value32;
+
+ /* Response Rate Set */
+ value32 = usb_read32(Adapter, REG_RRSR);
+ value32 &= ~RATE_BITMAP_ALL;
+ value32 |= RATE_RRSR_CCK_ONLY_1M;
+ usb_write32(Adapter, REG_RRSR, value32);
+
+ /* CF-END Threshold */
+
+ /* SIFS (used in NAV) */
+ value16 = _SPEC_SIFS_CCK(0x10) | _SPEC_SIFS_OFDM(0x10);
+ usb_write16(Adapter, REG_SPEC_SIFS, value16);
+
+ /* Retry Limit */
+ value16 = _LRL(0x30) | _SRL(0x30);
+ usb_write16(Adapter, REG_RL, value16);
+}
+
+static void _InitEDCA(struct adapter *Adapter)
+{
+ /* Set Spec SIFS (used in NAV) */
+ usb_write16(Adapter, REG_SPEC_SIFS, 0x100a);
+ usb_write16(Adapter, REG_MAC_SPEC_SIFS, 0x100a);
+
+ /* Set SIFS for CCK */
+ usb_write16(Adapter, REG_SIFS_CTX, 0x100a);
+
+ /* Set SIFS for OFDM */
+ usb_write16(Adapter, REG_SIFS_TRX, 0x100a);
+
+ /* TXOP */
+ usb_write32(Adapter, REG_EDCA_BE_PARAM, 0x005EA42B);
+ usb_write32(Adapter, REG_EDCA_BK_PARAM, 0x0000A44F);
+ usb_write32(Adapter, REG_EDCA_VI_PARAM, 0x005EA324);
+ usb_write32(Adapter, REG_EDCA_VO_PARAM, 0x002FA226);
+}
+
+static void _InitRDGSetting(struct adapter *Adapter)
+{
+ usb_write8(Adapter, REG_RD_CTRL, 0xFF);
+ usb_write16(Adapter, REG_RD_NAV_NXT, 0x200);
+ usb_write8(Adapter, REG_RD_RESP_PKT_TH, 0x05);
+}
+
+static void _InitRxSetting(struct adapter *Adapter)
+{
+ usb_write32(Adapter, REG_MACID, 0x87654321);
+ usb_write32(Adapter, 0x0700, 0x87654321);
+}
+
+static void _InitRetryFunction(struct adapter *Adapter)
+{
+ u8 value8;
+
+ value8 = usb_read8(Adapter, REG_FWHW_TXQ_CTRL);
+ value8 |= EN_AMPDU_RTY_NEW;
+ usb_write8(Adapter, REG_FWHW_TXQ_CTRL, value8);
+
+ /* Set ACK timeout */
+ usb_write8(Adapter, REG_ACKTO, 0x40);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: usb_AggSettingTxUpdate()
+ *
+ * Overview: Separate TX/RX parameters update independent for TP detection and
+ * dynamic TX/RX aggreagtion parameters update.
+ *
+ * Input: struct adapter *
+ *
+ * Output/Return: NONE
+ *
+ * Revised History:
+ * When Who Remark
+ * 12/10/2010 MHC Separate to smaller function.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void usb_AggSettingTxUpdate(struct adapter *Adapter)
+{
+ struct hal_data_8188e *haldata = Adapter->HalData;
+ u32 value32;
+
+ if (Adapter->registrypriv.wifi_spec)
+ haldata->UsbTxAggMode = false;
+
+ if (haldata->UsbTxAggMode) {
+ value32 = usb_read32(Adapter, REG_TDECTRL);
+ value32 = value32 & ~(BLK_DESC_NUM_MASK << BLK_DESC_NUM_SHIFT);
+ value32 |= ((haldata->UsbTxAggDescNum & BLK_DESC_NUM_MASK) << BLK_DESC_NUM_SHIFT);
+
+ usb_write32(Adapter, REG_TDECTRL, value32);
+ }
+} /* usb_AggSettingTxUpdate */
+
+/*-----------------------------------------------------------------------------
+ * Function: usb_AggSettingRxUpdate()
+ *
+ * Overview: Separate TX/RX parameters update independent for TP detection and
+ * dynamic TX/RX aggreagtion parameters update.
+ *
+ * Input: struct adapter *
+ *
+ * Output/Return: NONE
+ *
+ * Revised History:
+ * When Who Remark
+ * 12/10/2010 MHC Separate to smaller function.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void usb_AggSettingRxUpdate(struct adapter *Adapter)
+{
+ struct hal_data_8188e *haldata = Adapter->HalData;
+ u8 valueDMA;
+ u8 valueUSB;
+
+ valueDMA = usb_read8(Adapter, REG_TRXDMA_CTRL);
+ valueUSB = usb_read8(Adapter, REG_USB_SPECIAL_OPTION);
+
+ switch (haldata->UsbRxAggMode) {
+ case USB_RX_AGG_DMA:
+ valueDMA |= RXDMA_AGG_EN;
+ valueUSB &= ~USB_AGG_EN;
+ break;
+ case USB_RX_AGG_USB:
+ valueDMA &= ~RXDMA_AGG_EN;
+ valueUSB |= USB_AGG_EN;
+ break;
+ case USB_RX_AGG_MIX:
+ valueDMA |= RXDMA_AGG_EN;
+ valueUSB |= USB_AGG_EN;
+ break;
+ case USB_RX_AGG_DISABLE:
+ default:
+ valueDMA &= ~RXDMA_AGG_EN;
+ valueUSB &= ~USB_AGG_EN;
+ break;
+ }
+
+ usb_write8(Adapter, REG_TRXDMA_CTRL, valueDMA);
+ usb_write8(Adapter, REG_USB_SPECIAL_OPTION, valueUSB);
+
+ switch (haldata->UsbRxAggMode) {
+ case USB_RX_AGG_DMA:
+ usb_write8(Adapter, REG_RXDMA_AGG_PG_TH, haldata->UsbRxAggPageCount);
+ usb_write8(Adapter, REG_RXDMA_AGG_PG_TH + 1, haldata->UsbRxAggPageTimeout);
+ break;
+ case USB_RX_AGG_USB:
+ usb_write8(Adapter, REG_USB_AGG_TH, haldata->UsbRxAggBlockCount);
+ usb_write8(Adapter, REG_USB_AGG_TO, haldata->UsbRxAggBlockTimeout);
+ break;
+ case USB_RX_AGG_MIX:
+ usb_write8(Adapter, REG_RXDMA_AGG_PG_TH, haldata->UsbRxAggPageCount);
+ usb_write8(Adapter, REG_RXDMA_AGG_PG_TH + 1, (haldata->UsbRxAggPageTimeout & 0x1F));/* 0x280[12:8] */
+ usb_write8(Adapter, REG_USB_AGG_TH, haldata->UsbRxAggBlockCount);
+ usb_write8(Adapter, REG_USB_AGG_TO, haldata->UsbRxAggBlockTimeout);
+ break;
+ case USB_RX_AGG_DISABLE:
+ default:
+ /* TODO: */
+ break;
+ }
+
+ switch (PBP_128) {
+ case PBP_128:
+ haldata->HwRxPageSize = 128;
+ break;
+ case PBP_64:
+ haldata->HwRxPageSize = 64;
+ break;
+ case PBP_256:
+ haldata->HwRxPageSize = 256;
+ break;
+ case PBP_512:
+ haldata->HwRxPageSize = 512;
+ break;
+ case PBP_1024:
+ haldata->HwRxPageSize = 1024;
+ break;
+ default:
+ break;
+ }
+} /* usb_AggSettingRxUpdate */
+
+static void InitUsbAggregationSetting(struct adapter *Adapter)
+{
+ /* Tx aggregation setting */
+ usb_AggSettingTxUpdate(Adapter);
+
+ /* Rx aggregation setting */
+ usb_AggSettingRxUpdate(Adapter);
+}
+
+static void _InitBeaconParameters(struct adapter *Adapter)
+{
+ struct hal_data_8188e *haldata = Adapter->HalData;
+
+ usb_write16(Adapter, REG_BCN_CTRL, 0x1010);
+
+ /* TODO: Remove these magic number */
+ usb_write16(Adapter, REG_TBTT_PROHIBIT, 0x6404);/* ms */
+ usb_write8(Adapter, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);/* 5ms */
+ usb_write8(Adapter, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME); /* 2ms */
+
+ /* Suggested by designer timchen. Change beacon AIFS to the largest number */
+ /* beacause test chip does not contension before sending beacon. by tynli. 2009.11.03 */
+ usb_write16(Adapter, REG_BCNTCFG, 0x660F);
+
+ haldata->RegBcnCtrlVal = usb_read8(Adapter, REG_BCN_CTRL);
+ haldata->RegTxPause = usb_read8(Adapter, REG_TXPAUSE);
+ haldata->RegFwHwTxQCtrl = usb_read8(Adapter, REG_FWHW_TXQ_CTRL + 2);
+ haldata->RegReg542 = usb_read8(Adapter, REG_TBTT_PROHIBIT + 2);
+ haldata->RegCR_1 = usb_read8(Adapter, REG_CR + 1);
+}
+
+static void _BeaconFunctionEnable(struct adapter *Adapter,
+ bool Enable, bool Linked)
+{
+ usb_write8(Adapter, REG_BCN_CTRL, (BIT(4) | BIT(3) | BIT(1)));
+
+ usb_write8(Adapter, REG_RD_CTRL + 1, 0x6F);
+}
+
+/* Set CCK and OFDM Block "ON" */
+static void _BBTurnOnBlock(struct adapter *Adapter)
+{
+ phy_set_bb_reg(Adapter, rFPGA0_RFMOD, bCCKEn, 0x1);
+ phy_set_bb_reg(Adapter, rFPGA0_RFMOD, bOFDMEn, 0x1);
+}
+
+static void _InitAntenna_Selection(struct adapter *Adapter)
+{
+ struct hal_data_8188e *haldata = Adapter->HalData;
+
+ if (haldata->AntDivCfg == 0)
+ return;
+ DBG_88E("==> %s ....\n", __func__);
+
+ usb_write32(Adapter, REG_LEDCFG0, usb_read32(Adapter, REG_LEDCFG0) | BIT(23));
+ phy_set_bb_reg(Adapter, rFPGA0_XAB_RFParameter, BIT(13), 0x01);
+
+ if (phy_query_bb_reg(Adapter, rFPGA0_XA_RFInterfaceOE, 0x300) == Antenna_A)
+ haldata->CurAntenna = Antenna_A;
+ else
+ haldata->CurAntenna = Antenna_B;
+ DBG_88E("%s,Cur_ant:(%x)%s\n", __func__, haldata->CurAntenna, (haldata->CurAntenna == Antenna_A) ? "Antenna_A" : "Antenna_B");
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: HwSuspendModeEnable92Cu()
+ *
+ * Overview: HW suspend mode switch.
+ *
+ * Input: NONE
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Revised History:
+ * When Who Remark
+ * 08/23/2010 MHC HW suspend mode switch test..
+ *---------------------------------------------------------------------------
+ */
+enum rt_rf_power_state RfOnOffDetect(struct adapter *adapt)
+{
+ u8 val8;
+ enum rt_rf_power_state rfpowerstate = rf_off;
+
+ if (adapt->pwrctrlpriv.bHWPowerdown) {
+ val8 = usb_read8(adapt, REG_HSISR);
+ DBG_88E("pwrdown, 0x5c(BIT(7))=%02x\n", val8);
+ rfpowerstate = (val8 & BIT(7)) ? rf_off : rf_on;
+ } else { /* rf on/off */
+ usb_write8(adapt, REG_MAC_PINMUX_CFG, usb_read8(adapt, REG_MAC_PINMUX_CFG) & ~(BIT(3)));
+ val8 = usb_read8(adapt, REG_GPIO_IO_SEL);
+ DBG_88E("GPIO_IN=%02x\n", val8);
+ rfpowerstate = (val8 & BIT(3)) ? rf_on : rf_off;
+ }
+ return rfpowerstate;
+} /* HalDetectPwrDownMode */
+
+u32 rtl8188eu_hal_init(struct adapter *Adapter)
+{
+ u8 value8 = 0;
+ u16 value16;
+ u8 txpktbuf_bndy;
+ u32 status = _SUCCESS;
+ struct hal_data_8188e *haldata = Adapter->HalData;
+ struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv;
+ struct registry_priv *pregistrypriv = &Adapter->registrypriv;
+ unsigned long init_start_time = jiffies;
+
+ #define HAL_INIT_PROFILE_TAG(stage) do {} while (0)
+
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_BEGIN);
+
+ if (Adapter->pwrctrlpriv.bkeepfwalive) {
+ if (haldata->odmpriv.RFCalibrateInfo.bIQKInitialized) {
+ rtl88eu_phy_iq_calibrate(Adapter, true);
+ } else {
+ rtl88eu_phy_iq_calibrate(Adapter, false);
+ haldata->odmpriv.RFCalibrateInfo.bIQKInitialized = true;
+ }
+
+ ODM_TXPowerTrackingCheck(&haldata->odmpriv);
+ rtl88eu_phy_lc_calibrate(Adapter);
+
+ goto exit;
+ }
+
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_PW_ON);
+ status = rtw_hal_power_on(Adapter);
+ if (status == _FAIL) {
+ RT_TRACE(_module_hci_hal_init_c_, _drv_err_, ("Failed to init power on!\n"));
+ goto exit;
+ }
+
+ /* Save target channel */
+ haldata->CurrentChannel = 6;/* default set to 6 */
+
+ if (pwrctrlpriv->reg_rfoff)
+ pwrctrlpriv->rf_pwrstate = rf_off;
+
+ /* 2010/08/09 MH We need to check if we need to turnon or off RF after detecting */
+ /* HW GPIO pin. Before PHY_RFConfig8192C. */
+ /* 2010/08/26 MH If Efuse does not support sective suspend then disable the function. */
+
+ if (!pregistrypriv->wifi_spec) {
+ txpktbuf_bndy = TX_PAGE_BOUNDARY_88E;
+ } else {
+ /* for WMM */
+ txpktbuf_bndy = WMM_NORMAL_TX_PAGE_BOUNDARY_88E;
+ }
+
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC01);
+ _InitQueueReservedPage(Adapter);
+ _InitQueuePriority(Adapter);
+ _InitPageBoundary(Adapter);
+ _InitTransferPageSize(Adapter);
+
+ _InitTxBufferBoundary(Adapter, 0);
+
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_DOWNLOAD_FW);
+ if (Adapter->registrypriv.mp_mode == 1) {
+ _InitRxSetting(Adapter);
+ Adapter->bFWReady = false;
+ } else {
+ status = rtl88eu_download_fw(Adapter);
+
+ if (status) {
+ DBG_88E("%s: Download Firmware failed!!\n", __func__);
+ Adapter->bFWReady = false;
+ return status;
+ }
+ RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("Initializeadapt8192CSdio(): Download Firmware Success!!\n"));
+ Adapter->bFWReady = true;
+ }
+ rtl8188e_InitializeFirmwareVars(Adapter);
+
+ rtl88eu_phy_mac_config(Adapter);
+
+ rtl88eu_phy_bb_config(Adapter);
+
+ rtl88eu_phy_rf_config(Adapter);
+
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_EFUSE_PATCH);
+ status = rtl8188e_iol_efuse_patch(Adapter);
+ if (status == _FAIL) {
+ DBG_88E("%s rtl8188e_iol_efuse_patch failed\n", __func__);
+ goto exit;
+ }
+
+ _InitTxBufferBoundary(Adapter, txpktbuf_bndy);
+
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_LLTT);
+ status = InitLLTTable(Adapter, txpktbuf_bndy);
+ if (status == _FAIL) {
+ RT_TRACE(_module_hci_hal_init_c_, _drv_err_, ("Failed to init LLT table\n"));
+ goto exit;
+ }
+
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC02);
+ /* Get Rx PHY status in order to report RSSI and others. */
+ _InitDriverInfoSize(Adapter, DRVINFO_SZ);
+
+ _InitInterrupt(Adapter);
+ rtw_hal_set_hwreg(Adapter, HW_VAR_MAC_ADDR,
+ Adapter->eeprompriv.mac_addr);
+ _InitNetworkType(Adapter);/* set msr */
+ _InitWMACSetting(Adapter);
+ _InitAdaptiveCtrl(Adapter);
+ _InitEDCA(Adapter);
+ _InitRetryFunction(Adapter);
+ InitUsbAggregationSetting(Adapter);
+ _InitBeaconParameters(Adapter);
+ /* Init CR MACTXEN, MACRXEN after setting RxFF boundary REG_TRXFF_BNDY to patch */
+ /* Hw bug which Hw initials RxFF boundary size to a value which is larger than the real Rx buffer size in 88E. */
+ /* Enable MACTXEN/MACRXEN block */
+ value16 = usb_read16(Adapter, REG_CR);
+ value16 |= (MACTXEN | MACRXEN);
+ usb_write8(Adapter, REG_CR, value16);
+
+ if (haldata->bRDGEnable)
+ _InitRDGSetting(Adapter);
+
+ /* Enable TX Report */
+ /* Enable Tx Report Timer */
+ value8 = usb_read8(Adapter, REG_TX_RPT_CTRL);
+ usb_write8(Adapter, REG_TX_RPT_CTRL, (value8 | BIT(1) | BIT(0)));
+ /* Set MAX RPT MACID */
+ usb_write8(Adapter, REG_TX_RPT_CTRL + 1, 2);/* FOR sta mode ,0: bc/mc ,1:AP */
+ /* Tx RPT Timer. Unit: 32us */
+ usb_write16(Adapter, REG_TX_RPT_TIME, 0xCdf0);
+
+ usb_write8(Adapter, REG_EARLY_MODE_CONTROL, 0);
+
+ usb_write16(Adapter, REG_PKT_VO_VI_LIFE_TIME, 0x0400); /* unit: 256us. 256ms */
+ usb_write16(Adapter, REG_PKT_BE_BK_LIFE_TIME, 0x0400); /* unit: 256us. 256ms */
+
+ /* Keep RfRegChnlVal for later use. */
+ haldata->RfRegChnlVal[0] = rtw_hal_read_rfreg(Adapter, (enum rf_radio_path)0, RF_CHNLBW, bRFRegOffsetMask);
+ haldata->RfRegChnlVal[1] = rtw_hal_read_rfreg(Adapter, (enum rf_radio_path)1, RF_CHNLBW, bRFRegOffsetMask);
+
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_TURN_ON_BLOCK);
+ _BBTurnOnBlock(Adapter);
+
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_SECURITY);
+ invalidate_cam_all(Adapter);
+
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC11);
+ /* 2010/12/17 MH We need to set TX power according to EFUSE content at first. */
+ phy_set_tx_power_level(Adapter, haldata->CurrentChannel);
+
+/* Move by Neo for USB SS to below setp */
+/* _RfPowerSave(Adapter); */
+
+ _InitAntenna_Selection(Adapter);
+
+ /* */
+ /* Disable BAR, suggested by Scott */
+ /* 2010.04.09 add by hpfan */
+ /* */
+ usb_write32(Adapter, REG_BAR_MODE_CTRL, 0x0201ffff);
+
+ /* HW SEQ CTRL */
+ /* set 0x0 to 0xFF by tynli. Default enable HW SEQ NUM. */
+ usb_write8(Adapter, REG_HWSEQ_CTRL, 0xFF);
+
+ if (pregistrypriv->wifi_spec)
+ usb_write16(Adapter, REG_FAST_EDCA_CTRL, 0);
+
+ /* Nav limit , suggest by scott */
+ usb_write8(Adapter, 0x652, 0x0);
+
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_HAL_DM);
+ rtl8188e_InitHalDm(Adapter);
+
+ /* 2010/08/11 MH Merge from 8192SE for Minicard init. We need to confirm current radio status */
+ /* and then decide to enable RF or not.!!!??? For Selective suspend mode. We may not */
+ /* call initstruct adapter. May cause some problem?? */
+ /* Fix the bug that Hw/Sw radio off before S3/S4, the RF off action will not be executed */
+ /* in MgntActSet_RF_State() after wake up, because the value of haldata->eRFPowerState */
+ /* is the same as eRfOff, we should change it to eRfOn after we config RF parameters. */
+ /* Added by tynli. 2010.03.30. */
+ pwrctrlpriv->rf_pwrstate = rf_on;
+
+ /* enable Tx report. */
+ usb_write8(Adapter, REG_FWHW_TXQ_CTRL + 1, 0x0F);
+
+ /* Suggested by SD1 pisa. Added by tynli. 2011.10.21. */
+ usb_write8(Adapter, REG_EARLY_MODE_CONTROL + 3, 0x01);/* Pretx_en, for WEP/TKIP SEC */
+
+ /* tynli_test_tx_report. */
+ usb_write16(Adapter, REG_TX_RPT_TIME, 0x3DF0);
+
+ /* enable tx DMA to drop the redundate data of packet */
+ usb_write16(Adapter, REG_TXDMA_OFFSET_CHK, (usb_read16(Adapter, REG_TXDMA_OFFSET_CHK) | DROP_DATA_EN));
+
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_IQK);
+ /* 2010/08/26 MH Merge from 8192CE. */
+ if (pwrctrlpriv->rf_pwrstate == rf_on) {
+ if (haldata->odmpriv.RFCalibrateInfo.bIQKInitialized) {
+ rtl88eu_phy_iq_calibrate(Adapter, true);
+ } else {
+ rtl88eu_phy_iq_calibrate(Adapter, false);
+ haldata->odmpriv.RFCalibrateInfo.bIQKInitialized = true;
+ }
+
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_PW_TRACK);
+
+ ODM_TXPowerTrackingCheck(&haldata->odmpriv);
+
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_LCK);
+ rtl88eu_phy_lc_calibrate(Adapter);
+ }
+
+/* HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_PABIAS); */
+/* _InitPABias(Adapter); */
+ usb_write8(Adapter, REG_USB_HRPWM, 0);
+
+ /* ack for xmit mgmt frames. */
+ usb_write32(Adapter, REG_FWHW_TXQ_CTRL, usb_read32(Adapter, REG_FWHW_TXQ_CTRL) | BIT(12));
+
+exit:
+ HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_END);
+
+ DBG_88E("%s in %dms\n", __func__,
+ jiffies_to_msecs(jiffies - init_start_time));
+
+ return status;
+}
+
+static void CardDisableRTL8188EU(struct adapter *Adapter)
+{
+ u8 val8;
+
+ RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("CardDisableRTL8188EU\n"));
+
+ /* Stop Tx Report Timer. 0x4EC[Bit1]=b'0 */
+ val8 = usb_read8(Adapter, REG_TX_RPT_CTRL);
+ usb_write8(Adapter, REG_TX_RPT_CTRL, val8 & (~BIT(1)));
+
+ /* stop rx */
+ usb_write8(Adapter, REG_CR, 0x0);
+
+ /* Run LPS WL RFOFF flow */
+ rtl88eu_pwrseqcmdparsing(Adapter, PWR_CUT_ALL_MSK,
+ Rtl8188E_NIC_LPS_ENTER_FLOW);
+
+ /* 2. 0x1F[7:0] = 0 turn off RF */
+
+ val8 = usb_read8(Adapter, REG_MCUFWDL);
+ if ((val8 & RAM_DL_SEL) && Adapter->bFWReady) { /* 8051 RAM code */
+ /* Reset MCU 0x2[10]=0. */
+ val8 = usb_read8(Adapter, REG_SYS_FUNC_EN + 1);
+ val8 &= ~BIT(2); /* 0x2[10], FEN_CPUEN */
+ usb_write8(Adapter, REG_SYS_FUNC_EN + 1, val8);
+ }
+
+ /* reset MCU ready status */
+ usb_write8(Adapter, REG_MCUFWDL, 0);
+
+ /* YJ,add,111212 */
+ /* Disable 32k */
+ val8 = usb_read8(Adapter, REG_32K_CTRL);
+ usb_write8(Adapter, REG_32K_CTRL, val8 & (~BIT(0)));
+
+ /* Card disable power action flow */
+ rtl88eu_pwrseqcmdparsing(Adapter, PWR_CUT_ALL_MSK,
+ Rtl8188E_NIC_DISABLE_FLOW);
+
+ /* Reset MCU IO Wrapper */
+ val8 = usb_read8(Adapter, REG_RSV_CTRL + 1);
+ usb_write8(Adapter, REG_RSV_CTRL + 1, (val8 & (~BIT(3))));
+ val8 = usb_read8(Adapter, REG_RSV_CTRL + 1);
+ usb_write8(Adapter, REG_RSV_CTRL + 1, val8 | BIT(3));
+
+ /* YJ,test add, 111207. For Power Consumption. */
+ val8 = usb_read8(Adapter, GPIO_IN);
+ usb_write8(Adapter, GPIO_OUT, val8);
+ usb_write8(Adapter, GPIO_IO_SEL, 0xFF);/* Reg0x46 */
+
+ val8 = usb_read8(Adapter, REG_GPIO_IO_SEL);
+ usb_write8(Adapter, REG_GPIO_IO_SEL, (val8 << 4));
+ val8 = usb_read8(Adapter, REG_GPIO_IO_SEL + 1);
+ usb_write8(Adapter, REG_GPIO_IO_SEL + 1, val8 | 0x0F);/* Reg0x43 */
+ usb_write32(Adapter, REG_BB_PAD_CTRL, 0x00080808);/* set LNA ,TRSW,EX_PA Pin to output mode */
+ Adapter->HalData->bMacPwrCtrlOn = false;
+ Adapter->bFWReady = false;
+}
+
+static void rtl8192cu_hw_power_down(struct adapter *adapt)
+{
+ /* 2010/-8/09 MH For power down module, we need to enable register block contrl reg at 0x1c. */
+ /* Then enable power down control bit of register 0x04 BIT4 and BIT15 as 1. */
+
+ /* Enable register area 0x0-0xc. */
+ usb_write8(adapt, REG_RSV_CTRL, 0x0);
+ usb_write16(adapt, REG_APS_FSMCO, 0x8812);
+}
+
+u32 rtl8188eu_hal_deinit(struct adapter *Adapter)
+{
+ DBG_88E("==> %s\n", __func__);
+
+ usb_write32(Adapter, REG_HIMR_88E, IMR_DISABLED_88E);
+ usb_write32(Adapter, REG_HIMRE_88E, IMR_DISABLED_88E);
+
+ DBG_88E("bkeepfwalive(%x)\n", Adapter->pwrctrlpriv.bkeepfwalive);
+ if (Adapter->pwrctrlpriv.bkeepfwalive) {
+ if ((Adapter->pwrctrlpriv.bHWPwrPindetect) && (Adapter->pwrctrlpriv.bHWPowerdown))
+ rtl8192cu_hw_power_down(Adapter);
+ } else {
+ if (Adapter->hw_init_completed) {
+ CardDisableRTL8188EU(Adapter);
+
+ if ((Adapter->pwrctrlpriv.bHWPwrPindetect) && (Adapter->pwrctrlpriv.bHWPowerdown))
+ rtl8192cu_hw_power_down(Adapter);
+ }
+ }
+ return _SUCCESS;
+}
+
+u32 rtw_hal_inirp_init(struct adapter *Adapter)
+{
+ u8 i;
+ struct recv_buf *precvbuf;
+ uint status;
+ struct recv_priv *precvpriv = &Adapter->recvpriv;
+
+ status = _SUCCESS;
+
+ RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
+ ("===> usb_inirp_init\n"));
+
+ /* issue Rx irp to receive data */
+ precvbuf = precvpriv->precv_buf;
+ for (i = 0; i < NR_RECVBUFF; i++) {
+ if (!usb_read_port(Adapter, RECV_BULK_IN_ADDR, precvbuf)) {
+ RT_TRACE(_module_hci_hal_init_c_, _drv_err_, ("usb_rx_init: usb_read_port error\n"));
+ status = _FAIL;
+ goto exit;
+ }
+
+ precvbuf++;
+ }
+
+exit:
+
+ RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("<=== usb_inirp_init\n"));
+
+ return status;
+}
+
+/* */
+/* */
+/* EEPROM/EFUSE Content Parsing */
+/* */
+/* */
+static void Hal_EfuseParsePIDVID_8188EU(struct adapter *adapt, u8 *hwinfo, bool AutoLoadFail)
+{
+ struct hal_data_8188e *haldata = adapt->HalData;
+
+ if (!AutoLoadFail) {
+ /* VID, PID */
+ haldata->EEPROMVID = EF2BYTE(*(__le16 *)&hwinfo[EEPROM_VID_88EU]);
+ haldata->EEPROMPID = EF2BYTE(*(__le16 *)&hwinfo[EEPROM_PID_88EU]);
+
+ /* Customer ID, 0x00 and 0xff are reserved for Realtek. */
+ haldata->EEPROMCustomerID = *(u8 *)&hwinfo[EEPROM_CUSTOMERID_88E];
+ haldata->EEPROMSubCustomerID = EEPROM_Default_SubCustomerID;
+ } else {
+ haldata->EEPROMVID = EEPROM_Default_VID;
+ haldata->EEPROMPID = EEPROM_Default_PID;
+
+ /* Customer ID, 0x00 and 0xff are reserved for Realtek. */
+ haldata->EEPROMCustomerID = EEPROM_Default_CustomerID;
+ haldata->EEPROMSubCustomerID = EEPROM_Default_SubCustomerID;
+ }
+
+ DBG_88E("VID = 0x%04X, PID = 0x%04X\n", haldata->EEPROMVID, haldata->EEPROMPID);
+ DBG_88E("Customer ID: 0x%02X, SubCustomer ID: 0x%02X\n", haldata->EEPROMCustomerID, haldata->EEPROMSubCustomerID);
+}
+
+static void Hal_EfuseParseMACAddr_8188EU(struct adapter *adapt, u8 *hwinfo, bool AutoLoadFail)
+{
+ u16 i;
+ u8 sMacAddr[6] = {0x00, 0xE0, 0x4C, 0x81, 0x88, 0x02};
+ struct eeprom_priv *eeprom = GET_EEPROM_EFUSE_PRIV(adapt);
+
+ if (AutoLoadFail) {
+ for (i = 0; i < 6; i++)
+ eeprom->mac_addr[i] = sMacAddr[i];
+ } else {
+ /* Read Permanent MAC address */
+ memcpy(eeprom->mac_addr, &hwinfo[EEPROM_MAC_ADDR_88EU], ETH_ALEN);
+ }
+ RT_TRACE(_module_hci_hal_init_c_, _drv_notice_,
+ ("Hal_EfuseParseMACAddr_8188EU: Permanent Address = %pM\n",
+ eeprom->mac_addr));
+}
+
+static void readAdapterInfo_8188EU(struct adapter *adapt)
+{
+ struct eeprom_priv *eeprom = GET_EEPROM_EFUSE_PRIV(adapt);
+
+ /* parse the eeprom/efuse content */
+ Hal_EfuseParseIDCode88E(adapt, eeprom->efuse_eeprom_data);
+ Hal_EfuseParsePIDVID_8188EU(adapt, eeprom->efuse_eeprom_data, eeprom->bautoload_fail_flag);
+ Hal_EfuseParseMACAddr_8188EU(adapt, eeprom->efuse_eeprom_data, eeprom->bautoload_fail_flag);
+
+ Hal_ReadPowerSavingMode88E(adapt, eeprom->efuse_eeprom_data, eeprom->bautoload_fail_flag);
+ Hal_ReadTxPowerInfo88E(adapt, eeprom->efuse_eeprom_data, eeprom->bautoload_fail_flag);
+ Hal_EfuseParseEEPROMVer88E(adapt, eeprom->efuse_eeprom_data, eeprom->bautoload_fail_flag);
+ rtl8188e_EfuseParseChnlPlan(adapt, eeprom->efuse_eeprom_data, eeprom->bautoload_fail_flag);
+ Hal_EfuseParseXtal_8188E(adapt, eeprom->efuse_eeprom_data, eeprom->bautoload_fail_flag);
+ Hal_EfuseParseCustomerID88E(adapt, eeprom->efuse_eeprom_data, eeprom->bautoload_fail_flag);
+ Hal_ReadAntennaDiversity88E(adapt, eeprom->efuse_eeprom_data, eeprom->bautoload_fail_flag);
+ Hal_EfuseParseBoardType88E(adapt, eeprom->efuse_eeprom_data, eeprom->bautoload_fail_flag);
+ Hal_ReadThermalMeter_88E(adapt, eeprom->efuse_eeprom_data, eeprom->bautoload_fail_flag);
+}
+
+static void _ReadPROMContent(struct adapter *Adapter)
+{
+ struct eeprom_priv *eeprom = GET_EEPROM_EFUSE_PRIV(Adapter);
+ u8 eeValue;
+
+ /* check system boot selection */
+ eeValue = usb_read8(Adapter, REG_9346CR);
+ eeprom->EepromOrEfuse = (eeValue & BOOT_FROM_EEPROM) ? true : false;
+ eeprom->bautoload_fail_flag = (eeValue & EEPROM_EN) ? false : true;
+
+ DBG_88E("Boot from %s, Autoload %s !\n", (eeprom->EepromOrEfuse ? "EEPROM" : "EFUSE"),
+ (eeprom->bautoload_fail_flag ? "Fail" : "OK"));
+
+ Hal_InitPGData88E(Adapter);
+ readAdapterInfo_8188EU(Adapter);
+}
+
+void rtw_hal_read_chip_info(struct adapter *Adapter)
+{
+ unsigned long start = jiffies;
+
+ MSG_88E("====> %s\n", __func__);
+
+ _ReadPROMContent(Adapter);
+
+ MSG_88E("<==== %s in %d ms\n", __func__,
+ jiffies_to_msecs(jiffies - start));
+}
+
+#define GPIO_DEBUG_PORT_NUM 0
+static void rtl8192cu_trigger_gpio_0(struct adapter *adapt)
+{
+}
+
+static void ResumeTxBeacon(struct adapter *adapt)
+{
+ struct hal_data_8188e *haldata = adapt->HalData;
+
+ /* 2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */
+ /* which should be read from register to a global variable. */
+
+ usb_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl) | BIT(6));
+ haldata->RegFwHwTxQCtrl |= BIT(6);
+ usb_write8(adapt, REG_TBTT_PROHIBIT + 1, 0xff);
+ haldata->RegReg542 |= BIT(0);
+ usb_write8(adapt, REG_TBTT_PROHIBIT + 2, haldata->RegReg542);
+}
+
+static void StopTxBeacon(struct adapter *adapt)
+{
+ struct hal_data_8188e *haldata = adapt->HalData;
+
+ /* 2010.03.01. Marked by tynli. No need to call workitem beacause we record the value */
+ /* which should be read from register to a global variable. */
+
+ usb_write8(adapt, REG_FWHW_TXQ_CTRL + 2, (haldata->RegFwHwTxQCtrl) & (~BIT(6)));
+ haldata->RegFwHwTxQCtrl &= (~BIT(6));
+ usb_write8(adapt, REG_TBTT_PROHIBIT + 1, 0x64);
+ haldata->RegReg542 &= ~(BIT(0));
+ usb_write8(adapt, REG_TBTT_PROHIBIT + 2, haldata->RegReg542);
+
+ /* todo: CheckFwRsvdPageContent(Adapter); 2010.06.23. Added by tynli. */
+}
+
+static void hw_var_set_opmode(struct adapter *Adapter, u8 variable, u8 *val)
+{
+ u8 val8;
+ u8 mode = *((u8 *)val);
+
+ /* disable Port0 TSF update */
+ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(4));
+
+ /* set net_type */
+ val8 = usb_read8(Adapter, MSR) & 0x0c;
+ val8 |= mode;
+ usb_write8(Adapter, MSR, val8);
+
+ DBG_88E("%s()-%d mode = %d\n", __func__, __LINE__, mode);
+
+ if ((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) {
+ StopTxBeacon(Adapter);
+
+ usb_write8(Adapter, REG_BCN_CTRL, 0x19);/* disable atim wnd */
+ } else if (mode == _HW_STATE_ADHOC_) {
+ ResumeTxBeacon(Adapter);
+ usb_write8(Adapter, REG_BCN_CTRL, 0x1a);
+ } else if (mode == _HW_STATE_AP_) {
+ ResumeTxBeacon(Adapter);
+
+ usb_write8(Adapter, REG_BCN_CTRL, 0x12);
+
+ /* Set RCR */
+ usb_write32(Adapter, REG_RCR, 0x7000208e);/* CBSSID_DATA must set to 0,reject ICV_ERR packet */
+ /* enable to rx data frame */
+ usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
+ /* enable to rx ps-poll */
+ usb_write16(Adapter, REG_RXFLTMAP1, 0x0400);
+
+ /* Beacon Control related register for first time */
+ usb_write8(Adapter, REG_BCNDMATIM, 0x02); /* 2ms */
+
+ usb_write8(Adapter, REG_ATIMWND, 0x0a); /* 10ms */
+ usb_write16(Adapter, REG_BCNTCFG, 0x00);
+ usb_write16(Adapter, REG_TBTT_PROHIBIT, 0xff04);
+ usb_write16(Adapter, REG_TSFTR_SYN_OFFSET, 0x7fff);/* +32767 (~32ms) */
+
+ /* reset TSF */
+ usb_write8(Adapter, REG_DUAL_TSF_RST, BIT(0));
+
+ /* BIT3 - If set 0, hw will clr bcnq when tx becon ok/fail or port 0 */
+ usb_write8(Adapter, REG_MBID_NUM, usb_read8(Adapter, REG_MBID_NUM) | BIT(3) | BIT(4));
+
+ /* enable BCN0 Function for if1 */
+ /* don't enable update TSF0 for if1 (due to TSF update when beacon/probe rsp are received) */
+ usb_write8(Adapter, REG_BCN_CTRL, (DIS_TSF_UDT0_NORMAL_CHIP | EN_BCN_FUNCTION | BIT(1)));
+
+ /* dis BCN1 ATIM WND if if2 is station */
+ usb_write8(Adapter, REG_BCN_CTRL_1, usb_read8(Adapter, REG_BCN_CTRL_1) | BIT(0));
+ }
+}
+
+static void hw_var_set_macaddr(struct adapter *Adapter, u8 variable, u8 *val)
+{
+ u8 idx = 0;
+ u32 reg_macid;
+
+ reg_macid = REG_MACID;
+
+ for (idx = 0; idx < 6; idx++)
+ usb_write8(Adapter, (reg_macid + idx), val[idx]);
+}
+
+static void hw_var_set_bssid(struct adapter *Adapter, u8 variable, u8 *val)
+{
+ u8 idx = 0;
+ u32 reg_bssid;
+
+ reg_bssid = REG_BSSID;
+
+ for (idx = 0; idx < 6; idx++)
+ usb_write8(Adapter, (reg_bssid + idx), val[idx]);
+}
+
+static void hw_var_set_bcn_func(struct adapter *Adapter, u8 variable, u8 *val)
+{
+ u32 bcn_ctrl_reg;
+
+ bcn_ctrl_reg = REG_BCN_CTRL;
+
+ if (*((u8 *)val))
+ usb_write8(Adapter, bcn_ctrl_reg, (EN_BCN_FUNCTION | EN_TXBCN_RPT));
+ else
+ usb_write8(Adapter, bcn_ctrl_reg, usb_read8(Adapter, bcn_ctrl_reg) & (~(EN_BCN_FUNCTION | EN_TXBCN_RPT)));
+}
+
+void rtw_hal_set_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
+{
+ struct hal_data_8188e *haldata = Adapter->HalData;
+ struct dm_priv *pdmpriv = &haldata->dmpriv;
+ struct odm_dm_struct *podmpriv = &haldata->odmpriv;
+
+ switch (variable) {
+ case HW_VAR_MEDIA_STATUS:
+ {
+ u8 val8;
+
+ val8 = usb_read8(Adapter, MSR) & 0x0c;
+ val8 |= *((u8 *)val);
+ usb_write8(Adapter, MSR, val8);
+ }
+ break;
+ case HW_VAR_MEDIA_STATUS1:
+ {
+ u8 val8;
+
+ val8 = usb_read8(Adapter, MSR) & 0x03;
+ val8 |= *((u8 *)val) << 2;
+ usb_write8(Adapter, MSR, val8);
+ }
+ break;
+ case HW_VAR_SET_OPMODE:
+ hw_var_set_opmode(Adapter, variable, val);
+ break;
+ case HW_VAR_MAC_ADDR:
+ hw_var_set_macaddr(Adapter, variable, val);
+ break;
+ case HW_VAR_BSSID:
+ hw_var_set_bssid(Adapter, variable, val);
+ break;
+ case HW_VAR_BASIC_RATE:
+ {
+ u16 BrateCfg = 0;
+ u8 RateIndex = 0;
+
+ /* 2007.01.16, by Emily */
+ /* Select RRSR (in Legacy-OFDM and CCK) */
+ /* For 8190, we select only 24M, 12M, 6M, 11M, 5.5M, 2M, and 1M from the Basic rate. */
+ /* We do not use other rates. */
+ hal_set_brate_cfg(val, &BrateCfg);
+ DBG_88E("HW_VAR_BASIC_RATE: BrateCfg(%#x)\n", BrateCfg);
+
+ /* 2011.03.30 add by Luke Lee */
+ /* CCK 2M ACK should be disabled for some BCM and Atheros AP IOT */
+ /* because CCK 2M has poor TXEVM */
+ /* CCK 5.5M & 11M ACK should be enabled for better performance */
+
+ BrateCfg = (BrateCfg | 0xd) & 0x15d;
+ haldata->BasicRateSet = BrateCfg;
+
+ BrateCfg |= 0x01; /* default enable 1M ACK rate */
+ /* Set RRSR rate table. */
+ usb_write8(Adapter, REG_RRSR, BrateCfg & 0xff);
+ usb_write8(Adapter, REG_RRSR + 1, (BrateCfg >> 8) & 0xff);
+ usb_write8(Adapter, REG_RRSR + 2, usb_read8(Adapter, REG_RRSR + 2) & 0xf0);
+
+ /* Set RTS initial rate */
+ while (BrateCfg > 0x1) {
+ BrateCfg >>= 1;
+ RateIndex++;
+ }
+ /* Ziv - Check */
+ usb_write8(Adapter, REG_INIRTS_RATE_SEL, RateIndex);
+ }
+ break;
+ case HW_VAR_TXPAUSE:
+ usb_write8(Adapter, REG_TXPAUSE, *((u8 *)val));
+ break;
+ case HW_VAR_BCN_FUNC:
+ hw_var_set_bcn_func(Adapter, variable, val);
+ break;
+ case HW_VAR_CORRECT_TSF:
+ {
+ u64 tsf;
+ struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ tsf = pmlmeext->TSFValue - do_div(pmlmeext->TSFValue, (pmlmeinfo->bcn_interval * 1024)) - 1024; /* us */
+
+ if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
+ StopTxBeacon(Adapter);
+
+ /* disable related TSF function */
+ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(3)));
+
+ usb_write32(Adapter, REG_TSFTR, tsf);
+ usb_write32(Adapter, REG_TSFTR + 4, tsf >> 32);
+
+ /* enable related TSF function */
+ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(3));
+
+ if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
+ ResumeTxBeacon(Adapter);
+ }
+ break;
+ case HW_VAR_CHECK_BSSID:
+ if (*((u8 *)val)) {
+ usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR) | RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+ } else {
+ u32 val32;
+
+ val32 = usb_read32(Adapter, REG_RCR);
+
+ val32 &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+
+ usb_write32(Adapter, REG_RCR, val32);
+ }
+ break;
+ case HW_VAR_MLME_DISCONNECT:
+ /* Set RCR to not to receive data frame when NO LINK state */
+ /* reject all data frames */
+ usb_write16(Adapter, REG_RXFLTMAP2, 0x00);
+
+ /* reset TSF */
+ usb_write8(Adapter, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));
+
+ /* disable update TSF */
+ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(4));
+ break;
+ case HW_VAR_MLME_SITESURVEY:
+ if (*((u8 *)val)) { /* under sitesurvey */
+ /* config RCR to receive different BSSID & not to receive data frame */
+ u32 v = usb_read32(Adapter, REG_RCR);
+
+ v &= ~(RCR_CBSSID_BCN);
+ usb_write32(Adapter, REG_RCR, v);
+ /* reject all data frame */
+ usb_write16(Adapter, REG_RXFLTMAP2, 0x00);
+
+ /* disable update TSF */
+ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) | BIT(4));
+ } else { /* sitesurvey done */
+ struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ if ((is_client_associated_to_ap(Adapter)) ||
+ ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE)) {
+ /* enable to rx data frame */
+ usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
+
+ /* enable update TSF */
+ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(4)));
+ } else if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
+ usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
+ /* enable update TSF */
+ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(4)));
+ }
+
+ usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR) | RCR_CBSSID_BCN);
+ }
+ break;
+ case HW_VAR_MLME_JOIN:
+ {
+ u8 RetryLimit = 0x30;
+ u8 type = *((u8 *)val);
+ struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
+
+ if (type == 0) { /* prepare to join */
+ /* enable to rx data frame.Accept all data frame */
+ usb_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
+
+ usb_write32(Adapter, REG_RCR, usb_read32(Adapter, REG_RCR) | RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
+ RetryLimit = (haldata->CustomerID == RT_CID_CCX) ? 7 : 48;
+ else /* Ad-hoc Mode */
+ RetryLimit = 0x7;
+ } else if (type == 1) {
+ /* joinbss_event call back when join res < 0 */
+ usb_write16(Adapter, REG_RXFLTMAP2, 0x00);
+ } else if (type == 2) {
+ /* sta add event call back */
+ /* enable update TSF */
+ usb_write8(Adapter, REG_BCN_CTRL, usb_read8(Adapter, REG_BCN_CTRL) & (~BIT(4)));
+
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE))
+ RetryLimit = 0x7;
+ }
+ usb_write16(Adapter, REG_RL, RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit << RETRY_LIMIT_LONG_SHIFT);
+ }
+ break;
+ case HW_VAR_BEACON_INTERVAL:
+ usb_write16(Adapter, REG_BCN_INTERVAL, *((u16 *)val));
+ break;
+ case HW_VAR_SLOT_TIME:
+ {
+ u8 u1bAIFS, aSifsTime;
+ struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+
+ usb_write8(Adapter, REG_SLOT, val[0]);
+
+ if (pmlmeinfo->WMM_enable == 0) {
+ if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
+ aSifsTime = 10;
+ else
+ aSifsTime = 16;
+
+ u1bAIFS = aSifsTime + (2 * pmlmeinfo->slotTime);
+
+ /* <Roger_EXP> Temporary removed, 2008.06.20. */
+ usb_write8(Adapter, REG_EDCA_VO_PARAM, u1bAIFS);
+ usb_write8(Adapter, REG_EDCA_VI_PARAM, u1bAIFS);
+ usb_write8(Adapter, REG_EDCA_BE_PARAM, u1bAIFS);
+ usb_write8(Adapter, REG_EDCA_BK_PARAM, u1bAIFS);
+ }
+ }
+ break;
+ case HW_VAR_RESP_SIFS:
+ /* RESP_SIFS for CCK */
+ usb_write8(Adapter, REG_R2T_SIFS, val[0]); /* SIFS_T2T_CCK (0x08) */
+ usb_write8(Adapter, REG_R2T_SIFS + 1, val[1]); /* SIFS_R2T_CCK(0x08) */
+ /* RESP_SIFS for OFDM */
+ usb_write8(Adapter, REG_T2T_SIFS, val[2]); /* SIFS_T2T_OFDM (0x0a) */
+ usb_write8(Adapter, REG_T2T_SIFS + 1, val[3]); /* SIFS_R2T_OFDM(0x0a) */
+ break;
+ case HW_VAR_ACK_PREAMBLE:
+ {
+ u8 regTmp;
+ u8 bShortPreamble = *((bool *)val);
+ /* Joseph marked out for Netgear 3500 TKIP channel 7 issue.(Temporarily) */
+ regTmp = (haldata->nCur40MhzPrimeSC) << 5;
+ if (bShortPreamble)
+ regTmp |= 0x80;
+
+ usb_write8(Adapter, REG_RRSR + 2, regTmp);
+ }
+ break;
+ case HW_VAR_SEC_CFG:
+ usb_write8(Adapter, REG_SECCFG, *((u8 *)val));
+ break;
+ case HW_VAR_DM_FUNC_OP:
+ if (val[0])
+ podmpriv->BK_SupportAbility = podmpriv->SupportAbility;
+ else
+ podmpriv->SupportAbility = podmpriv->BK_SupportAbility;
+ break;
+ case HW_VAR_DM_FUNC_SET:
+ if (*((u32 *)val) == DYNAMIC_ALL_FUNC_ENABLE) {
+ pdmpriv->DMFlag = pdmpriv->InitDMFlag;
+ podmpriv->SupportAbility = pdmpriv->InitODMFlag;
+ } else {
+ podmpriv->SupportAbility |= *((u32 *)val);
+ }
+ break;
+ case HW_VAR_DM_FUNC_CLR:
+ podmpriv->SupportAbility &= *((u32 *)val);
+ break;
+ case HW_VAR_CAM_EMPTY_ENTRY:
+ {
+ u8 ucIndex = *((u8 *)val);
+ u8 i;
+ u32 ulCommand = 0;
+ u32 ulContent = 0;
+ u32 ulEncAlgo = CAM_AES;
+
+ for (i = 0; i < CAM_CONTENT_COUNT; i++) {
+ /* filled id in CAM config 2 byte */
+ if (i == 0)
+ ulContent |= (ucIndex & 0x03) | ((u16)(ulEncAlgo) << 2);
+ else
+ ulContent = 0;
+ /* polling bit, and No Write enable, and address */
+ ulCommand = CAM_CONTENT_COUNT * ucIndex + i;
+ ulCommand = ulCommand | CAM_POLLINIG |
+ CAM_WRITE;
+ /* write content 0 is equall to mark invalid */
+ usb_write32(Adapter, WCAMI, ulContent); /* delay_ms(40); */
+ usb_write32(Adapter, RWCAM, ulCommand); /* delay_ms(40); */
+ }
+ }
+ break;
+ case HW_VAR_CAM_INVALID_ALL:
+ usb_write32(Adapter, RWCAM, BIT(31) | BIT(30));
+ break;
+ case HW_VAR_CAM_WRITE:
+ {
+ u32 cmd;
+ u32 *cam_val = (u32 *)val;
+
+ usb_write32(Adapter, WCAMI, cam_val[0]);
+
+ cmd = CAM_POLLINIG | CAM_WRITE | cam_val[1];
+ usb_write32(Adapter, RWCAM, cmd);
+ }
+ break;
+ case HW_VAR_AC_PARAM_VO:
+ usb_write32(Adapter, REG_EDCA_VO_PARAM, ((u32 *)(val))[0]);
+ break;
+ case HW_VAR_AC_PARAM_VI:
+ usb_write32(Adapter, REG_EDCA_VI_PARAM, ((u32 *)(val))[0]);
+ break;
+ case HW_VAR_AC_PARAM_BE:
+ haldata->AcParam_BE = ((u32 *)(val))[0];
+ usb_write32(Adapter, REG_EDCA_BE_PARAM, ((u32 *)(val))[0]);
+ break;
+ case HW_VAR_AC_PARAM_BK:
+ usb_write32(Adapter, REG_EDCA_BK_PARAM, ((u32 *)(val))[0]);
+ break;
+ case HW_VAR_ACM_CTRL:
+ {
+ u8 acm_ctrl = *((u8 *)val);
+ u8 AcmCtrl = usb_read8(Adapter, REG_ACMHWCTRL);
+
+ if (acm_ctrl > 1)
+ AcmCtrl = AcmCtrl | 0x1;
+
+ if (acm_ctrl & BIT(3))
+ AcmCtrl |= AcmHw_VoqEn;
+ else
+ AcmCtrl &= (~AcmHw_VoqEn);
+
+ if (acm_ctrl & BIT(2))
+ AcmCtrl |= AcmHw_ViqEn;
+ else
+ AcmCtrl &= (~AcmHw_ViqEn);
+
+ if (acm_ctrl & BIT(1))
+ AcmCtrl |= AcmHw_BeqEn;
+ else
+ AcmCtrl &= (~AcmHw_BeqEn);
+
+ DBG_88E("[HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl);
+ usb_write8(Adapter, REG_ACMHWCTRL, AcmCtrl);
+ }
+ break;
+ case HW_VAR_AMPDU_MIN_SPACE:
+ {
+ u8 MinSpacingToSet;
+ u8 SecMinSpace;
+
+ MinSpacingToSet = *((u8 *)val);
+ if (MinSpacingToSet <= 7) {
+ switch (Adapter->securitypriv.dot11PrivacyAlgrthm) {
+ case _NO_PRIVACY_:
+ case _AES_:
+ SecMinSpace = 0;
+ break;
+ case _WEP40_:
+ case _WEP104_:
+ case _TKIP_:
+ case _TKIP_WTMIC_:
+ SecMinSpace = 6;
+ break;
+ default:
+ SecMinSpace = 7;
+ break;
+ }
+ if (MinSpacingToSet < SecMinSpace)
+ MinSpacingToSet = SecMinSpace;
+ usb_write8(Adapter, REG_AMPDU_MIN_SPACE, (usb_read8(Adapter, REG_AMPDU_MIN_SPACE) & 0xf8) | MinSpacingToSet);
+ }
+ }
+ break;
+ case HW_VAR_AMPDU_FACTOR:
+ {
+ u8 RegToSet_Normal[4] = {0x41, 0xa8, 0x72, 0xb9};
+ u8 FactorToSet;
+ u8 *pRegToSet;
+ u8 index = 0;
+
+ pRegToSet = RegToSet_Normal; /* 0xb972a841; */
+ FactorToSet = *((u8 *)val);
+ if (FactorToSet <= 3) {
+ FactorToSet = 1 << (FactorToSet + 2);
+ if (FactorToSet > 0xf)
+ FactorToSet = 0xf;
+
+ for (index = 0; index < 4; index++) {
+ if ((pRegToSet[index] & 0xf0) > (FactorToSet << 4))
+ pRegToSet[index] = (pRegToSet[index] & 0x0f) | (FactorToSet << 4);
+
+ if ((pRegToSet[index] & 0x0f) > FactorToSet)
+ pRegToSet[index] = (pRegToSet[index] & 0xf0) | (FactorToSet);
+
+ usb_write8(Adapter, (REG_AGGLEN_LMT + index), pRegToSet[index]);
+ }
+ }
+ }
+ break;
+ case HW_VAR_RXDMA_AGG_PG_TH:
+ {
+ u8 threshold = *((u8 *)val);
+
+ if (threshold == 0)
+ threshold = haldata->UsbRxAggPageCount;
+ usb_write8(Adapter, REG_RXDMA_AGG_PG_TH, threshold);
+ }
+ break;
+ case HW_VAR_SET_RPWM:
+ break;
+ case HW_VAR_H2C_FW_PWRMODE:
+ {
+ u8 psmode = (*(u8 *)val);
+
+ /* Forece leave RF low power mode for 1T1R to prevent conficting setting in Fw power */
+ /* saving sequence. 2010.06.07. Added by tynli. Suggested by SD3 yschang. */
+ if (psmode != PS_MODE_ACTIVE)
+ ODM_RF_Saving(podmpriv, true);
+ rtl8188e_set_FwPwrMode_cmd(Adapter, psmode);
+ }
+ break;
+ case HW_VAR_H2C_FW_JOINBSSRPT:
+ {
+ u8 mstatus = (*(u8 *)val);
+
+ rtl8188e_set_FwJoinBssReport_cmd(Adapter, mstatus);
+ }
+ break;
+ case HW_VAR_INITIAL_GAIN:
+ {
+ struct rtw_dig *pDigTable = &podmpriv->DM_DigTable;
+ u32 rx_gain = ((u32 *)(val))[0];
+
+ if (rx_gain == 0xff) {/* restore rx gain */
+ ODM_Write_DIG(podmpriv, pDigTable->BackupIGValue);
+ } else {
+ pDigTable->BackupIGValue = pDigTable->CurIGValue;
+ ODM_Write_DIG(podmpriv, rx_gain);
+ }
+ }
+ break;
+ case HW_VAR_TRIGGER_GPIO_0:
+ rtl8192cu_trigger_gpio_0(Adapter);
+ break;
+ case HW_VAR_RPT_TIMER_SETTING:
+ {
+ u16 min_rpt_time = (*(u16 *)val);
+
+ ODM_RA_Set_TxRPT_Time(podmpriv, min_rpt_time);
+ }
+ break;
+ case HW_VAR_ANTENNA_DIVERSITY_SELECT:
+ {
+ u8 Optimum_antenna = (*(u8 *)val);
+ u8 Ant;
+ /* switch antenna to Optimum_antenna */
+ if (haldata->CurAntenna != Optimum_antenna) {
+ Ant = (Optimum_antenna == 2) ? MAIN_ANT : AUX_ANT;
+ rtl88eu_dm_update_rx_idle_ant(&haldata->odmpriv, Ant);
+
+ haldata->CurAntenna = Optimum_antenna;
+ }
+ }
+ break;
+ case HW_VAR_EFUSE_BYTES: /* To set EFUE total used bytes, added by Roger, 2008.12.22. */
+ haldata->EfuseUsedBytes = *((u16 *)val);
+ break;
+ case HW_VAR_FIFO_CLEARN_UP:
+ {
+ struct pwrctrl_priv *pwrpriv = &Adapter->pwrctrlpriv;
+ u8 trycnt = 100;
+
+ /* pause tx */
+ usb_write8(Adapter, REG_TXPAUSE, 0xff);
+
+ /* keep sn */
+ Adapter->xmitpriv.nqos_ssn = usb_read16(Adapter, REG_NQOS_SEQ);
+
+ if (!pwrpriv->bkeepfwalive) {
+ /* RX DMA stop */
+ usb_write32(Adapter, REG_RXPKT_NUM, (usb_read32(Adapter, REG_RXPKT_NUM) | RW_RELEASE_EN));
+ do {
+ if (!(usb_read32(Adapter, REG_RXPKT_NUM) & RXDMA_IDLE))
+ break;
+ } while (trycnt--);
+ if (trycnt == 0)
+ DBG_88E("Stop RX DMA failed......\n");
+
+ /* RQPN Load 0 */
+ usb_write16(Adapter, REG_RQPN_NPQ, 0x0);
+ usb_write32(Adapter, REG_RQPN, 0x80000000);
+ mdelay(10);
+ }
+ }
+ break;
+ case HW_VAR_CHECK_TXBUF:
+ break;
+ case HW_VAR_APFM_ON_MAC:
+ haldata->bMacPwrCtrlOn = *val;
+ DBG_88E("%s: bMacPwrCtrlOn=%d\n", __func__, haldata->bMacPwrCtrlOn);
+ break;
+ case HW_VAR_TX_RPT_MAX_MACID:
+ {
+ u8 maxMacid = *val;
+
+ DBG_88E("### MacID(%d),Set Max Tx RPT MID(%d)\n", maxMacid, maxMacid + 1);
+ usb_write8(Adapter, REG_TX_RPT_CTRL + 1, maxMacid + 1);
+ }
+ break;
+ case HW_VAR_H2C_MEDIA_STATUS_RPT:
+ rtl8188e_set_FwMediaStatus_cmd(Adapter, (*(__le16 *)val));
+ break;
+ case HW_VAR_BCN_VALID:
+ /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2, write 1 to clear, Clear by sw */
+ usb_write8(Adapter, REG_TDECTRL + 2, usb_read8(Adapter, REG_TDECTRL + 2) | BIT(0));
+ break;
+ default:
+ break;
+ }
+}
+
+void rtw_hal_get_hwreg(struct adapter *Adapter, u8 variable, u8 *val)
+{
+ switch (variable) {
+ case HW_VAR_BASIC_RATE:
+ *((u16 *)(val)) = Adapter->HalData->BasicRateSet;
+ /* fall through */
+ case HW_VAR_TXPAUSE:
+ val[0] = usb_read8(Adapter, REG_TXPAUSE);
+ break;
+ case HW_VAR_BCN_VALID:
+ /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2 */
+ val[0] = (BIT(0) & usb_read8(Adapter, REG_TDECTRL + 2)) ? true : false;
+ break;
+ case HW_VAR_FWLPS_RF_ON:
+ {
+ /* When we halt NIC, we should check if FW LPS is leave. */
+ if (Adapter->pwrctrlpriv.rf_pwrstate == rf_off) {
+ /* If it is in HW/SW Radio OFF or IPS state, we do not check Fw LPS Leave, */
+ /* because Fw is unload. */
+ val[0] = true;
+ } else {
+ u32 valRCR;
+
+ valRCR = usb_read32(Adapter, REG_RCR);
+ valRCR &= 0x00070000;
+ if (valRCR)
+ val[0] = false;
+ else
+ val[0] = true;
+ }
+ }
+ break;
+ case HW_VAR_CURRENT_ANTENNA:
+ val[0] = Adapter->HalData->CurAntenna;
+ break;
+ case HW_VAR_EFUSE_BYTES: /* To get EFUE total used bytes, added by Roger, 2008.12.22. */
+ *((u16 *)(val)) = Adapter->HalData->EfuseUsedBytes;
+ break;
+ case HW_VAR_APFM_ON_MAC:
+ *val = Adapter->HalData->bMacPwrCtrlOn;
+ break;
+ case HW_VAR_CHK_HI_QUEUE_EMPTY:
+ *val = ((usb_read32(Adapter, REG_HGQ_INFORMATION) & 0x0000ff00) == 0) ? true : false;
+ break;
+ default:
+ break;
+ }
+}
+
+/* */
+/* Description: */
+/* Query setting of specified variable. */
+/* */
+u8 rtw_hal_get_def_var(struct adapter *Adapter, enum hal_def_variable eVariable,
+ void *pValue)
+{
+ struct hal_data_8188e *haldata = Adapter->HalData;
+ u8 bResult = _SUCCESS;
+
+ switch (eVariable) {
+ case HAL_DEF_UNDERCORATEDSMOOTHEDPWDB:
+ {
+ struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
+ struct sta_priv *pstapriv = &Adapter->stapriv;
+ struct sta_info *psta;
+
+ psta = rtw_get_stainfo(pstapriv, pmlmepriv->cur_network.network.MacAddress);
+ if (psta)
+ *((int *)pValue) = psta->rssi_stat.UndecoratedSmoothedPWDB;
+ }
+ break;
+ case HAL_DEF_IS_SUPPORT_ANT_DIV:
+ *((u8 *)pValue) = (haldata->AntDivCfg == 0) ? false : true;
+ break;
+ case HAL_DEF_CURRENT_ANTENNA:
+ *((u8 *)pValue) = haldata->CurAntenna;
+ break;
+ case HAL_DEF_DRVINFO_SZ:
+ *((u32 *)pValue) = DRVINFO_SZ;
+ break;
+ case HAL_DEF_MAX_RECVBUF_SZ:
+ *((u32 *)pValue) = MAX_RECVBUF_SZ;
+ break;
+ case HAL_DEF_RX_PACKET_OFFSET:
+ *((u32 *)pValue) = RXDESC_SIZE + DRVINFO_SZ;
+ break;
+ case HAL_DEF_DBG_DM_FUNC:
+ *((u32 *)pValue) = haldata->odmpriv.SupportAbility;
+ break;
+ case HAL_DEF_RA_DECISION_RATE:
+ {
+ u8 MacID = *((u8 *)pValue);
+
+ *((u8 *)pValue) = ODM_RA_GetDecisionRate_8188E(&haldata->odmpriv, MacID);
+ }
+ break;
+ case HAL_DEF_RA_SGI:
+ {
+ u8 MacID = *((u8 *)pValue);
+
+ *((u8 *)pValue) = ODM_RA_GetShortGI_8188E(&haldata->odmpriv, MacID);
+ }
+ break;
+ case HAL_DEF_PT_PWR_STATUS:
+ {
+ u8 MacID = *((u8 *)pValue);
+
+ *((u8 *)pValue) = ODM_RA_GetHwPwrStatus_8188E(&haldata->odmpriv, MacID);
+ }
+ break;
+ case HW_VAR_MAX_RX_AMPDU_FACTOR:
+ *((u32 *)pValue) = MAX_AMPDU_FACTOR_64K;
+ break;
+ case HW_DEF_RA_INFO_DUMP:
+ {
+ u8 entry_id = *((u8 *)pValue);
+
+ if (check_fwstate(&Adapter->mlmepriv, _FW_LINKED)) {
+ DBG_88E("============ RA status check ===================\n");
+ DBG_88E("Mac_id:%d , RateID = %d, RAUseRate = 0x%08x, RateSGI = %d, DecisionRate = 0x%02x ,PTStage = %d\n",
+ entry_id,
+ haldata->odmpriv.RAInfo[entry_id].RateID,
+ haldata->odmpriv.RAInfo[entry_id].RAUseRate,
+ haldata->odmpriv.RAInfo[entry_id].RateSGI,
+ haldata->odmpriv.RAInfo[entry_id].DecisionRate,
+ haldata->odmpriv.RAInfo[entry_id].PTStage);
+ }
+ }
+ break;
+ case HW_DEF_ODM_DBG_FLAG:
+ {
+ struct odm_dm_struct *dm_ocm = &haldata->odmpriv;
+
+ pr_info("dm_ocm->DebugComponents = 0x%llx\n", dm_ocm->DebugComponents);
+ }
+ break;
+ case HAL_DEF_DBG_DUMP_RXPKT:
+ *((u8 *)pValue) = haldata->bDumpRxPkt;
+ break;
+ case HAL_DEF_DBG_DUMP_TXPKT:
+ *((u8 *)pValue) = haldata->bDumpTxPkt;
+ break;
+ default:
+ bResult = _FAIL;
+ break;
+ }
+
+ return bResult;
+}
+
+void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level)
+{
+ u8 init_rate = 0;
+ u8 networkType, raid;
+ u32 mask, rate_bitmap;
+ u8 shortGIrate = false;
+ int supportRateNum = 0;
+ struct sta_info *psta;
+ struct odm_dm_struct *odmpriv = &adapt->HalData->odmpriv;
+ struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
+
+ if (mac_id >= NUM_STA) /* CAM_SIZE */
+ return;
+ psta = pmlmeinfo->FW_sta_info[mac_id].psta;
+ if (!psta)
+ return;
+ switch (mac_id) {
+ case 0:/* for infra mode */
+ supportRateNum = rtw_get_rateset_len(cur_network->SupportedRates);
+ networkType = judge_network_type(adapt, cur_network->SupportedRates, supportRateNum) & 0xf;
+ raid = networktype_to_raid(networkType);
+ mask = update_supported_rate(cur_network->SupportedRates, supportRateNum);
+ mask |= (pmlmeinfo->HT_enable) ? update_MSC_rate(&pmlmeinfo->HT_caps) : 0;
+ if (support_short_GI(adapt, &pmlmeinfo->HT_caps))
+ shortGIrate = true;
+ break;
+ case 1:/* for broadcast/multicast */
+ supportRateNum = rtw_get_rateset_len(pmlmeinfo->FW_sta_info[mac_id].SupportedRates);
+ if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
+ networkType = WIRELESS_11B;
+ else
+ networkType = WIRELESS_11G;
+ raid = networktype_to_raid(networkType);
+ mask = update_basic_rate(cur_network->SupportedRates, supportRateNum);
+ break;
+ default: /* for each sta in IBSS */
+ supportRateNum = rtw_get_rateset_len(pmlmeinfo->FW_sta_info[mac_id].SupportedRates);
+ networkType = judge_network_type(adapt, pmlmeinfo->FW_sta_info[mac_id].SupportedRates, supportRateNum) & 0xf;
+ raid = networktype_to_raid(networkType);
+ mask = update_supported_rate(cur_network->SupportedRates, supportRateNum);
+
+ /* todo: support HT in IBSS */
+ break;
+ }
+
+ rate_bitmap = ODM_Get_Rate_Bitmap(odmpriv, mac_id, mask, rssi_level);
+ DBG_88E("%s => mac_id:%d, networkType:0x%02x, mask:0x%08x\n\t ==> rssi_level:%d, rate_bitmap:0x%08x\n",
+ __func__, mac_id, networkType, mask, rssi_level, rate_bitmap);
+
+ mask &= rate_bitmap;
+
+ init_rate = get_highest_rate_idx(mask) & 0x3f;
+
+ ODM_RA_UpdateRateInfo_8188E(odmpriv, mac_id, raid, mask, shortGIrate);
+
+ /* set ra_id */
+ psta->raid = raid;
+ psta->init_rate = init_rate;
+}
+
+void beacon_timing_control(struct adapter *adapt)
+{
+ u32 value32;
+ struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u32 bcn_ctrl_reg = REG_BCN_CTRL;
+ /* reset TSF, enable update TSF, correcting TSF On Beacon */
+
+ /* BCN interval */
+ usb_write16(adapt, REG_BCN_INTERVAL, pmlmeinfo->bcn_interval);
+ usb_write8(adapt, REG_ATIMWND, 0x02);/* 2ms */
+
+ _InitBeaconParameters(adapt);
+
+ usb_write8(adapt, REG_SLOT, 0x09);
+
+ value32 = usb_read32(adapt, REG_TCR);
+ value32 &= ~TSFRST;
+ usb_write32(adapt, REG_TCR, value32);
+
+ value32 |= TSFRST;
+ usb_write32(adapt, REG_TCR, value32);
+
+ /* NOTE: Fix test chip's bug (about contention windows's randomness) */
+ usb_write8(adapt, REG_RXTSF_OFFSET_CCK, 0x50);
+ usb_write8(adapt, REG_RXTSF_OFFSET_OFDM, 0x50);
+
+ _BeaconFunctionEnable(adapt, true, true);
+
+ ResumeTxBeacon(adapt);
+
+ usb_write8(adapt, bcn_ctrl_reg, usb_read8(adapt, bcn_ctrl_reg) | BIT(1));
+}
+
+void rtw_hal_def_value_init(struct adapter *adapt)
+{
+ struct hal_data_8188e *haldata = adapt->HalData;
+ struct pwrctrl_priv *pwrctrlpriv;
+ u8 i;
+
+ pwrctrlpriv = &adapt->pwrctrlpriv;
+
+ /* init default value */
+ if (!pwrctrlpriv->bkeepfwalive)
+ haldata->LastHMEBoxNum = 0;
+
+ /* init dm default value */
+ haldata->odmpriv.RFCalibrateInfo.bIQKInitialized = false;
+ haldata->odmpriv.RFCalibrateInfo.TM_Trigger = 0;/* for IQK */
+ haldata->pwrGroupCnt = 0;
+ haldata->PGMaxGroup = 13;
+ haldata->odmpriv.RFCalibrateInfo.ThermalValue_HP_index = 0;
+ for (i = 0; i < HP_THERMAL_NUM; i++)
+ haldata->odmpriv.RFCalibrateInfo.ThermalValue_HP[i] = 0;
+}
diff --git a/drivers/staging/rtl8188eu/include/HalVerDef.h b/drivers/staging/rtl8188eu/include/HalVerDef.h
new file mode 100644
index 0000000..63a144e
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/HalVerDef.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __HAL_VERSION_DEF_H__
+#define __HAL_VERSION_DEF_H__
+
+enum HAL_CHIP_TYPE {
+ TEST_CHIP = 0,
+ NORMAL_CHIP = 1,
+ FPGA = 2,
+};
+
+enum HAL_CUT_VERSION {
+ A_CUT_VERSION = 0,
+ B_CUT_VERSION = 1,
+ C_CUT_VERSION = 2,
+ D_CUT_VERSION = 3,
+ E_CUT_VERSION = 4,
+ F_CUT_VERSION = 5,
+ G_CUT_VERSION = 6,
+};
+
+enum HAL_VENDOR {
+ CHIP_VENDOR_TSMC = 0,
+ CHIP_VENDOR_UMC = 1,
+};
+
+struct HAL_VERSION {
+ enum HAL_CHIP_TYPE ChipType;
+ enum HAL_CUT_VERSION CUTVersion;
+ enum HAL_VENDOR VendorType;
+};
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/basic_types.h b/drivers/staging/rtl8188eu/include/basic_types.h
new file mode 100644
index 0000000..b69b45d
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/basic_types.h
@@ -0,0 +1,134 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __BASIC_TYPES_H__
+#define __BASIC_TYPES_H__
+
+#include <linux/types.h>
+#define NDIS_OID uint
+
+/* port from fw */
+/* TODO: Macros Below are Sync from SD7-Driver. It is necessary
+ * to check correctness
+ */
+
+/*
+ * Call endian free function when
+ * 1. Read/write packet content.
+ * 2. Before write integer to IO.
+ * 3. After read integer from IO.
+ */
+
+/* Convert little data endian to host ordering */
+#define EF1BYTE(_val) \
+ ((u8)(_val))
+#define EF2BYTE(_val) \
+ (le16_to_cpu(_val))
+#define EF4BYTE(_val) \
+ (le32_to_cpu(_val))
+
+/* Create a bit mask
+ * Examples:
+ * BIT_LEN_MASK_32(0) => 0x00000000
+ * BIT_LEN_MASK_32(1) => 0x00000001
+ * BIT_LEN_MASK_32(2) => 0x00000003
+ * BIT_LEN_MASK_32(32) => 0xFFFFFFFF
+ */
+#define BIT_LEN_MASK_32(__bitlen) \
+ (0xFFFFFFFF >> (32 - (__bitlen)))
+#define BIT_LEN_MASK_16(__bitlen) \
+ (0xFFFF >> (16 - (__bitlen)))
+#define BIT_LEN_MASK_8(__bitlen) \
+ (0xFF >> (8 - (__bitlen)))
+
+/* Create an offset bit mask
+ * Examples:
+ * BIT_OFFSET_LEN_MASK_32(0, 2) => 0x00000003
+ * BIT_OFFSET_LEN_MASK_32(16, 2) => 0x00030000
+ */
+#define BIT_OFFSET_LEN_MASK_32(__bitoffset, __bitlen) \
+ (BIT_LEN_MASK_32(__bitlen) << (__bitoffset))
+#define BIT_OFFSET_LEN_MASK_16(__bitoffset, __bitlen) \
+ (BIT_LEN_MASK_16(__bitlen) << (__bitoffset))
+#define BIT_OFFSET_LEN_MASK_8(__bitoffset, __bitlen) \
+ (BIT_LEN_MASK_8(__bitlen) << (__bitoffset))
+
+/*Description:
+ * Return 4-byte value in host byte ordering from
+ * 4-byte pointer in little-endian system.
+ */
+#define LE_P4BYTE_TO_HOST_4BYTE(__pstart) \
+ (EF4BYTE(*((__le32 *)(__pstart))))
+#define LE_P2BYTE_TO_HOST_2BYTE(__pstart) \
+ (EF2BYTE(*((__le16 *)(__pstart))))
+#define LE_P1BYTE_TO_HOST_1BYTE(__pstart) \
+ (EF1BYTE(*((u8 *)(__pstart))))
+
+/* Description:
+ * Translate subfield (continuous bits in little-endian) of 4-byte
+ * value to host byte ordering.
+ */
+#define LE_BITS_TO_4BYTE(__pstart, __bitoffset, __bitlen) \
+ ( \
+ (LE_P4BYTE_TO_HOST_4BYTE(__pstart) >> (__bitoffset)) & \
+ BIT_LEN_MASK_32(__bitlen) \
+ )
+#define LE_BITS_TO_2BYTE(__pstart, __bitoffset, __bitlen) \
+ ( \
+ (LE_P2BYTE_TO_HOST_2BYTE(__pstart) >> (__bitoffset)) & \
+ BIT_LEN_MASK_16(__bitlen) \
+ )
+#define LE_BITS_TO_1BYTE(__pstart, __bitoffset, __bitlen) \
+ ( \
+ (LE_P1BYTE_TO_HOST_1BYTE(__pstart) >> (__bitoffset)) & \
+ BIT_LEN_MASK_8(__bitlen) \
+ )
+
+/* Description:
+ * Mask subfield (continuous bits in little-endian) of 4-byte value
+ * and return the result in 4-byte value in host byte ordering.
+ */
+#define LE_BITS_CLEARED_TO_4BYTE(__pstart, __bitoffset, __bitlen) \
+ ( \
+ LE_P4BYTE_TO_HOST_4BYTE(__pstart) & \
+ (~BIT_OFFSET_LEN_MASK_32(__bitoffset, __bitlen)) \
+ )
+#define LE_BITS_CLEARED_TO_2BYTE(__pstart, __bitoffset, __bitlen) \
+ ( \
+ LE_P2BYTE_TO_HOST_2BYTE(__pstart) & \
+ (~BIT_OFFSET_LEN_MASK_16(__bitoffset, __bitlen)) \
+ )
+#define LE_BITS_CLEARED_TO_1BYTE(__pstart, __bitoffset, __bitlen) \
+ ( \
+ LE_P1BYTE_TO_HOST_1BYTE(__pstart) & \
+ (~BIT_OFFSET_LEN_MASK_8(__bitoffset, __bitlen)) \
+ )
+
+/* Description:
+ * Set subfield of little-endian 4-byte value to specified value.
+ */
+#define SET_BITS_TO_LE_4BYTE(__pstart, __bitoffset, __bitlen, __val) \
+ *((u32 *)(__pstart)) = \
+ ( \
+ LE_BITS_CLEARED_TO_4BYTE(__pstart, __bitoffset, __bitlen) | \
+ ((((u32)__val) & BIT_LEN_MASK_32(__bitlen)) << (__bitoffset)) \
+ )
+
+#define SET_BITS_TO_LE_2BYTE(__pstart, __bitoffset, __bitlen, __val) \
+ *((u16 *)(__pstart)) = \
+ ( \
+ LE_BITS_CLEARED_TO_2BYTE(__pstart, __bitoffset, __bitlen) | \
+ ((((u16)__val) & BIT_LEN_MASK_16(__bitlen)) << (__bitoffset)) \
+ );
+
+#define SET_BITS_TO_LE_1BYTE(__pstart, __bitoffset, __bitlen, __val) \
+ *((u8 *)(__pstart)) = EF1BYTE \
+ ( \
+ LE_BITS_CLEARED_TO_1BYTE(__pstart, __bitoffset, __bitlen) | \
+ ((((u8)__val) & BIT_LEN_MASK_8(__bitlen)) << (__bitoffset)) \
+ )
+
+#endif /* __BASIC_TYPES_H__ */
diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h
new file mode 100644
index 0000000..35c0946
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/drv_types.h
@@ -0,0 +1,178 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+/*-----------------------------------------------------------------------------
+
+ For type defines and data structure defines
+
+------------------------------------------------------------------------------*/
+
+
+#ifndef __DRV_TYPES_H__
+#define __DRV_TYPES_H__
+
+#define DRV_NAME "r8188eu"
+
+#include <osdep_service.h>
+#include <wlan_bssdef.h>
+#include <rtw_ht.h>
+#include <rtw_cmd.h>
+#include <rtw_xmit.h>
+#include <rtw_recv.h>
+#include <hal_intf.h>
+#include <hal_com.h>
+#include <rtw_security.h>
+#include <rtw_pwrctrl.h>
+#include <rtw_eeprom.h>
+#include <sta_info.h>
+
+struct qos_priv {
+ /* bit mask option: u-apsd, s-apsd, ts, block ack... */
+ unsigned int qos_option;
+};
+
+#include <rtw_mlme.h>
+#include <rtw_debug.h>
+#include <rtw_rf.h>
+#include <rtw_event.h>
+#include <rtw_led.h>
+#include <rtw_mlme_ext.h>
+#include <rtw_ap.h>
+
+#define SPEC_DEV_ID_NONE BIT(0)
+#define SPEC_DEV_ID_DISABLE_HT BIT(1)
+#define SPEC_DEV_ID_ENABLE_PS BIT(2)
+#define SPEC_DEV_ID_RF_CONFIG_1T1R BIT(3)
+#define SPEC_DEV_ID_RF_CONFIG_2T2R BIT(4)
+#define SPEC_DEV_ID_ASSIGN_IFNAME BIT(5)
+
+struct registry_priv {
+ struct ndis_802_11_ssid ssid;
+ u8 channel;/* ad-hoc support requirement */
+ u8 wireless_mode;/* A, B, G, auto */
+ u8 preamble;/* long, short, auto */
+ u8 vrtl_carrier_sense;/* Enable, Disable, Auto */
+ u8 vcs_type;/* RTS/CTS, CTS-to-self */
+ u16 rts_thresh;
+ u16 frag_thresh;
+ u8 power_mgnt;
+ u8 ips_mode;
+ u8 smart_ps;
+ u8 mp_mode;
+ u8 acm_method;
+ /* UAPSD */
+ u8 wmm_enable;
+ u8 uapsd_enable;
+
+ struct wlan_bssid_ex dev_network;
+
+ u8 ht_enable;
+ u8 cbw40_enable;
+ u8 ampdu_enable;/* for tx */
+ u8 rx_stbc;
+ u8 ampdu_amsdu;/* A-MPDU Supports A-MSDU is permitted */
+
+ u8 wifi_spec;/* !turbo_mode */
+
+ u8 channel_plan;
+ bool accept_addba_req; /* true = accept AP's Add BA req */
+
+ u8 antdiv_cfg;
+ u8 antdiv_type;
+
+ u8 usbss_enable;/* 0:disable,1:enable */
+ u8 hwpdn_mode;/* 0:disable,1:enable,2:decide by EFUSE config */
+
+ u8 max_roaming_times; /* the max number driver will try */
+
+ u8 fw_iol; /* enable iol without other concern */
+
+ u8 enable80211d;
+
+ u8 ifname[16];
+ u8 if2name[16];
+
+ u8 notch_filter;
+ bool monitor_enable;
+};
+
+#define MAX_CONTINUAL_URB_ERR 4
+
+struct dvobj_priv {
+ struct adapter *if1;
+ /* For 92D, DMDP have 2 interface. */
+ u8 InterfaceNumber;
+ u8 NumInterfaces;
+
+ /* In /Out Pipe information */
+ int RtInPipe[2];
+ int RtOutPipe[3];
+ u8 Queue2Pipe[HW_QUEUE_ENTRY];/* for out pipe mapping */
+
+/*-------- below is for USB INTERFACE --------*/
+ u8 ishighspeed;
+ u8 RtNumInPipes;
+ u8 RtNumOutPipes;
+ struct mutex usb_vendor_req_mutex;
+
+ struct usb_interface *pusbintf;
+ struct usb_device *pusbdev;
+};
+
+static inline struct device *dvobj_to_dev(struct dvobj_priv *dvobj)
+{
+ /* todo: get interface type from dvobj and the return
+ * the dev accordingly
+ */
+ return &dvobj->pusbintf->dev;
+};
+
+struct adapter {
+ struct dvobj_priv *dvobj;
+ struct mlme_priv mlmepriv;
+ struct mlme_ext_priv mlmeextpriv;
+ struct cmd_priv cmdpriv;
+ struct xmit_priv xmitpriv;
+ struct recv_priv recvpriv;
+ struct sta_priv stapriv;
+ struct security_priv securitypriv;
+ struct registry_priv registrypriv;
+ struct pwrctrl_priv pwrctrlpriv;
+ struct eeprom_priv eeprompriv;
+ struct led_priv ledpriv;
+
+ struct hal_data_8188e *HalData;
+
+ s32 bDriverStopped;
+ s32 bSurpriseRemoved;
+
+ u8 hw_init_completed;
+
+ void *cmdThread;
+ struct net_device *pnetdev;
+ struct net_device *pmondev;
+
+ int bup;
+ struct net_device_stats stats;
+ struct iw_statistics iwstats;
+ struct proc_dir_entry *dir_dev;/* for proc directory */
+
+ int net_closed;
+ u8 bFWReady;
+ u8 bReadPortCancel;
+ u8 bWritePortCancel;
+
+ struct mutex hw_init_mutex;
+};
+
+#define adapter_to_dvobj(adapter) (adapter->dvobj)
+
+static inline u8 *myid(struct eeprom_priv *peepriv)
+{
+ return peepriv->mac_addr;
+}
+
+#endif /* __DRV_TYPES_H__ */
diff --git a/drivers/staging/rtl8188eu/include/fw.h b/drivers/staging/rtl8188eu/include/fw.h
new file mode 100644
index 0000000..9f010c4
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/fw.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2013 Realtek Corporation.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+#include "drv_types.h"
+#include <linux/types.h>
+
+#ifndef __RTL92C__FW__H__
+#define __RTL92C__FW__H__
+
+#define FW_8192C_START_ADDRESS 0x1000
+#define FW_8192C_PAGE_SIZE 4096
+#define FW_8192C_POLLING_DELAY 5
+
+struct rtl92c_firmware_header {
+ __le16 signature;
+ u8 category;
+ u8 function;
+ u16 version;
+ u8 subversion;
+ u8 rsvd1;
+ u8 month;
+ u8 date;
+ u8 hour;
+ u8 minute;
+ u16 ramcodesize;
+ u16 rsvd2;
+ u32 svnindex;
+ u32 rsvd3;
+ u32 rsvd4;
+ u32 rsvd5;
+};
+
+int rtl88eu_download_fw(struct adapter *adapt);
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/hal8188e_phy_cfg.h b/drivers/staging/rtl8188eu/include/hal8188e_phy_cfg.h
new file mode 100644
index 0000000..da66695
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/hal8188e_phy_cfg.h
@@ -0,0 +1,205 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __INC_HAL8188EPHYCFG_H__
+#define __INC_HAL8188EPHYCFG_H__
+
+
+/*--------------------------Define Parameters-------------------------------*/
+#define LOOP_LIMIT 5
+#define MAX_STALL_TIME 50 /* us */
+#define AntennaDiversityValue 0x80
+#define MAX_TXPWR_IDX_NMODE_92S 63
+#define Reset_Cnt_Limit 3
+
+#define IQK_MAC_REG_NUM 4
+#define IQK_ADDA_REG_NUM 16
+#define IQK_BB_REG_NUM 9
+#define HP_THERMAL_NUM 8
+
+#define MAX_AGGR_NUM 0x07
+
+
+/*--------------------------Define Parameters-------------------------------*/
+
+
+/*------------------------------Define structure----------------------------*/
+enum sw_chnl_cmd_id {
+ CmdID_End,
+ CmdID_SetTxPowerLevel,
+ CmdID_BBRegWrite10,
+ CmdID_WritePortUlong,
+ CmdID_WritePortUshort,
+ CmdID_WritePortUchar,
+ CmdID_RF_WriteReg,
+};
+
+/* 1. Switch channel related */
+struct sw_chnl_cmd {
+ enum sw_chnl_cmd_id CmdID;
+ u32 Para1;
+ u32 Para2;
+ u32 msDelay;
+};
+
+enum hw90_block {
+ HW90_BLOCK_MAC = 0,
+ HW90_BLOCK_PHY0 = 1,
+ HW90_BLOCK_PHY1 = 2,
+ HW90_BLOCK_RF = 3,
+ HW90_BLOCK_MAXIMUM = 4, /* Never use this */
+};
+
+enum rf_radio_path {
+ RF_PATH_A = 0, /* Radio Path A */
+ RF_PATH_B = 1, /* Radio Path B */
+};
+
+#define MAX_PG_GROUP 13
+
+#define RF_PATH_MAX 2
+#define MAX_RF_PATH RF_PATH_MAX
+#define MAX_TX_COUNT 4 /* path numbers */
+
+#define CHANNEL_MAX_NUMBER 14 /* 14 is the max chnl number */
+#define MAX_CHNL_GROUP_24G 6 /* ch1~2, ch3~5, ch6~8,
+ *ch9~11, ch12~13, CH 14
+ * total three groups
+ */
+#define CHANNEL_GROUP_MAX_88E 6
+
+enum wireless_mode {
+ WIRELESS_MODE_UNKNOWN = 0x00,
+ WIRELESS_MODE_A = BIT(2),
+ WIRELESS_MODE_B = BIT(0),
+ WIRELESS_MODE_G = BIT(1),
+ WIRELESS_MODE_AUTO = BIT(5),
+ WIRELESS_MODE_N_24G = BIT(3),
+ WIRELESS_MODE_N_5G = BIT(4),
+ WIRELESS_MODE_AC = BIT(6)
+};
+
+enum phy_rate_tx_offset_area {
+ RA_OFFSET_LEGACY_OFDM1,
+ RA_OFFSET_LEGACY_OFDM2,
+ RA_OFFSET_HT_OFDM1,
+ RA_OFFSET_HT_OFDM2,
+ RA_OFFSET_HT_OFDM3,
+ RA_OFFSET_HT_OFDM4,
+ RA_OFFSET_HT_CCK,
+};
+
+struct bb_reg_def {
+ u32 rfintfs; /* set software control: */
+ /* 0x870~0x877[8 bytes] */
+ u32 rfintfi; /* readback data: */
+ /* 0x8e0~0x8e7[8 bytes] */
+ u32 rfintfo; /* output data: */
+ /* 0x860~0x86f [16 bytes] */
+ u32 rfintfe; /* output enable: */
+ /* 0x860~0x86f [16 bytes] */
+ u32 rf3wireOffset; /* LSSI data: */
+ /* 0x840~0x84f [16 bytes] */
+ u32 rfLSSI_Select; /* BB Band Select: */
+ /* 0x878~0x87f [8 bytes] */
+ u32 rfTxGainStage; /* Tx gain stage: */
+ /* 0x80c~0x80f [4 bytes] */
+ u32 rfHSSIPara1; /* wire parameter control1 : */
+ /* 0x820~0x823,0x828~0x82b,
+ * 0x830~0x833, 0x838~0x83b [16 bytes]
+ */
+ u32 rfHSSIPara2; /* wire parameter control2 : */
+ /* 0x824~0x827,0x82c~0x82f, 0x834~0x837,
+ * 0x83c~0x83f [16 bytes]
+ */
+ u32 rfSwitchControl; /* Tx Rx antenna control : */
+ /* 0x858~0x85f [16 bytes] */
+ u32 rfAGCControl1; /* AGC parameter control1 : */
+ /* 0xc50~0xc53,0xc58~0xc5b, 0xc60~0xc63,
+ * 0xc68~0xc6b [16 bytes]
+ */
+ u32 rfAGCControl2; /* AGC parameter control2 : */
+ /* 0xc54~0xc57,0xc5c~0xc5f, 0xc64~0xc67,
+ * 0xc6c~0xc6f [16 bytes]
+ */
+ u32 rfRxIQImbalance; /* OFDM Rx IQ imbalance matrix : */
+ /* 0xc14~0xc17,0xc1c~0xc1f, 0xc24~0xc27,
+ * 0xc2c~0xc2f [16 bytes]
+ */
+ u32 rfRxAFE; /* Rx IQ DC ofset and Rx digital filter,
+ * Rx DC notch filter :
+ */
+ /* 0xc10~0xc13,0xc18~0xc1b, 0xc20~0xc23,
+ * 0xc28~0xc2b [16 bytes]
+ */
+ u32 rfTxIQImbalance; /* OFDM Tx IQ imbalance matrix */
+ /* 0xc80~0xc83,0xc88~0xc8b, 0xc90~0xc93,
+ * 0xc98~0xc9b [16 bytes]
+ */
+ u32 rfTxAFE; /* Tx IQ DC Offset and Tx DFIR type */
+ /* 0xc84~0xc87,0xc8c~0xc8f, 0xc94~0xc97,
+ * 0xc9c~0xc9f [16 bytes]
+ */
+ u32 rfLSSIReadBack; /* LSSI RF readback data SI mode */
+ /* 0x8a0~0x8af [16 bytes] */
+ u32 rfLSSIReadBackPi; /* LSSI RF readback data PI mode 0x8b8-8bc for
+ * Path A and B
+ */
+};
+
+/*------------------------------Define structure----------------------------*/
+
+
+/*------------------------Export global variable----------------------------*/
+/*------------------------Export global variable----------------------------*/
+
+
+/*------------------------Export Marco Definition---------------------------*/
+/*------------------------Export Marco Definition---------------------------*/
+
+
+/*--------------------------Exported Function prototype---------------------*/
+/* */
+/* BB and RF register read/write */
+/* */
+
+/* Read initi reg value for tx power setting. */
+void rtl8192c_PHY_GetHWRegOriginalValue(struct adapter *adapter);
+
+/* BB TX Power R/W */
+void PHY_GetTxPowerLevel8188E(struct adapter *adapter, u32 *powerlevel);
+
+void PHY_ScanOperationBackup8188E(struct adapter *Adapter, u8 Operation);
+
+/* Call after initialization */
+void ChkFwCmdIoDone(struct adapter *adapter);
+
+/* BB/MAC/RF other monitor API */
+void PHY_SetRFPathSwitch_8188E(struct adapter *adapter, bool main);
+
+void PHY_SwitchEphyParameter(struct adapter *adapter);
+
+void PHY_EnableHostClkReq(struct adapter *adapter);
+
+bool SetAntennaConfig92C(struct adapter *adapter, u8 defaultant);
+
+/*--------------------------Exported Function prototype---------------------*/
+
+#define PHY_SetMacReg PHY_SetBBReg
+
+#define SIC_HW_SUPPORT 0
+
+#define SIC_MAX_POLL_CNT 5
+
+#define SIC_CMD_READY 0
+#define SIC_CMD_WRITE 1
+#define SIC_CMD_READ 2
+
+#define SIC_CMD_REG 0x1EB /* 1byte */
+#define SIC_ADDR_REG 0x1E8 /* 1b9~1ba, 2 bytes */
+#define SIC_DATA_REG 0x1EC /* 1bc~1bf */
+
+#endif /* __INC_HAL8192CPHYCFG_H */
diff --git a/drivers/staging/rtl8188eu/include/hal8188e_phy_reg.h b/drivers/staging/rtl8188eu/include/hal8188e_phy_reg.h
new file mode 100644
index 0000000..bd915a1
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/hal8188e_phy_reg.h
@@ -0,0 +1,201 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __INC_HAL8188EPHYREG_H__
+#define __INC_HAL8188EPHYREG_H__
+/*--------------------------Define Parameters-------------------------------*/
+/* */
+/* BB-PHY register PMAC 0x100 PHY 0x800 - 0xEFF */
+/* 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF */
+/* 2. 0x800/0x900/0xA00/0xC00/0xD00/0xE00 */
+/* 3. RF register 0x00-2E */
+/* 4. Bit Mask for BB/RF register */
+/* 5. Other definition for BB/RF R/W */
+/* */
+
+/* 3. Page8(0x800) */
+#define rFPGA0_RFMOD 0x800 /* RF mode & CCK TxSC RF BW Setting */
+#define rFPGA0_TxGainStage 0x80c /* Set TX PWR init gain? */
+
+#define rFPGA0_XA_HSSIParameter1 0x820 /* RF 3 wire register */
+#define rFPGA0_XA_HSSIParameter2 0x824
+#define rFPGA0_XB_HSSIParameter1 0x828
+#define rFPGA0_XB_HSSIParameter2 0x82c
+
+#define rFPGA0_XA_LSSIParameter 0x840
+#define rFPGA0_XB_LSSIParameter 0x844
+
+#define rFPGA0_XAB_SwitchControl 0x858 /* RF Channel switch */
+#define rFPGA0_XCD_SwitchControl 0x85c
+
+#define rFPGA0_XA_RFInterfaceOE 0x860 /* RF Channel switch */
+#define rFPGA0_XB_RFInterfaceOE 0x864
+
+#define rFPGA0_XAB_RFInterfaceSW 0x870 /* RF Iface Software Control */
+#define rFPGA0_XCD_RFInterfaceSW 0x874
+
+#define rFPGA0_XAB_RFParameter 0x878 /* RF Parameter */
+
+#define rFPGA0_XA_LSSIReadBack 0x8a0 /* Tranceiver LSSI Readback */
+#define rFPGA0_XB_LSSIReadBack 0x8a4
+
+#define TransceiverA_HSPI_Readback 0x8b8
+#define TransceiverB_HSPI_Readback 0x8bc
+#define rFPGA0_XAB_RFInterfaceRB 0x8e0
+
+/* 4. Page9(0x900) */
+/* RF mode & OFDM TxSC RF BW Setting?? */
+#define rFPGA1_RFMOD 0x900
+
+/* 5. PageA(0xA00) */
+/* Set Control channel to upper or lower - required only for 40MHz */
+#define rCCK0_System 0xa00
+
+/* */
+/* PageB(0xB00) */
+/* */
+#define rConfig_AntA 0xb68
+#define rConfig_AntB 0xb6c
+
+/* */
+/* 6. PageC(0xC00) */
+/* */
+#define rOFDM0_TRxPathEnable 0xc04
+#define rOFDM0_TRMuxPar 0xc08
+
+/* RxIQ DC offset, Rx digital filter, DC notch filter */
+#define rOFDM0_XARxAFE 0xc10
+#define rOFDM0_XARxIQImbalance 0xc14 /* RxIQ imbalance matrix */
+#define rOFDM0_XBRxAFE 0xc18
+#define rOFDM0_XBRxIQImbalance 0xc1c
+
+#define rOFDM0_RxDSP 0xc40 /* Rx Sync Path */
+#define rOFDM0_ECCAThreshold 0xc4c /* energy CCA */
+
+#define rOFDM0_XAAGCCore1 0xc50 /* DIG */
+#define rOFDM0_XAAGCCore2 0xc54
+#define rOFDM0_XBAGCCore1 0xc58
+#define rOFDM0_XBAGCCore2 0xc5c
+
+#define rOFDM0_AGCRSSITable 0xc78
+
+#define rOFDM0_XATxIQImbalance 0xc80 /* TX PWR TRACK and DIG */
+#define rOFDM0_XATxAFE 0xc84
+#define rOFDM0_XBTxIQImbalance 0xc88
+#define rOFDM0_XBTxAFE 0xc8c
+#define rOFDM0_XCTxAFE 0xc94
+#define rOFDM0_XDTxAFE 0xc9c
+
+#define rOFDM0_RxIQExtAnta 0xca0
+
+/* */
+/* 7. PageD(0xD00) */
+/* */
+#define rOFDM1_LSTF 0xd00
+
+/* */
+/* 8. PageE(0xE00) */
+/* */
+#define rTxAGC_A_Rate18_06 0xe00
+#define rTxAGC_A_Rate54_24 0xe04
+#define rTxAGC_A_CCK1_Mcs32 0xe08
+#define rTxAGC_A_Mcs03_Mcs00 0xe10
+#define rTxAGC_A_Mcs07_Mcs04 0xe14
+#define rTxAGC_A_Mcs11_Mcs08 0xe18
+#define rTxAGC_A_Mcs15_Mcs12 0xe1c
+
+#define rTxAGC_B_Rate18_06 0x830
+#define rTxAGC_B_Rate54_24 0x834
+#define rTxAGC_B_CCK1_55_Mcs32 0x838
+#define rTxAGC_B_Mcs03_Mcs00 0x83c
+#define rTxAGC_B_Mcs07_Mcs04 0x848
+#define rTxAGC_B_Mcs11_Mcs08 0x84c
+#define rTxAGC_B_Mcs15_Mcs12 0x868
+#define rTxAGC_B_CCK11_A_CCK2_11 0x86c
+
+#define rFPGA0_IQK 0xe28
+#define rTx_IQK_Tone_A 0xe30
+#define rRx_IQK_Tone_A 0xe34
+#define rTx_IQK_PI_A 0xe38
+#define rRx_IQK_PI_A 0xe3c
+
+#define rTx_IQK 0xe40
+#define rRx_IQK 0xe44
+#define rIQK_AGC_Pts 0xe48
+#define rIQK_AGC_Rsp 0xe4c
+#define rIQK_AGC_Cont 0xe60
+
+#define rBlue_Tooth 0xe6c
+#define rRx_Wait_CCA 0xe70
+#define rTx_CCK_RFON 0xe74
+#define rTx_CCK_BBON 0xe78
+#define rTx_OFDM_RFON 0xe7c
+#define rTx_OFDM_BBON 0xe80
+#define rTx_To_Rx 0xe84
+#define rTx_To_Tx 0xe88
+#define rRx_CCK 0xe8c
+
+#define rTx_Power_Before_IQK_A 0xe94
+#define rTx_Power_After_IQK_A 0xe9c
+
+#define rRx_Power_Before_IQK_A_2 0xea4
+#define rRx_Power_After_IQK_A_2 0xeac
+
+#define rTx_Power_Before_IQK_B 0xeb4
+#define rTx_Power_After_IQK_B 0xebc
+
+#define rRx_Power_Before_IQK_B_2 0xec4
+#define rRx_Power_After_IQK_B_2 0xecc
+
+#define rRx_OFDM 0xed0
+#define rRx_Wait_RIFS 0xed4
+#define rRx_TO_Rx 0xed8
+#define rStandby 0xedc
+#define rSleep 0xee0
+#define rPMPD_ANAEN 0xeec
+
+/* */
+/* RL6052 Register definition */
+/* */
+#define RF_AC 0x00 /* */
+#define RF_CHNLBW 0x18 /* RF channel and BW switch */
+#define RF_T_METER_88E 0x42 /* */
+#define RF_RCK_OS 0x30 /* RF TX PA control */
+#define RF_TXPA_G1 0x31 /* RF TX PA control */
+#define RF_TXPA_G2 0x32 /* RF TX PA control */
+#define RF_WE_LUT 0xEF
+
+/* */
+/* Bit Mask */
+/* */
+
+/* 2. Page8(0x800) */
+#define bRFMOD 0x1 /* Reg 0x800 rFPGA0_RFMOD */
+#define bCCKEn 0x1000000
+#define bOFDMEn 0x2000000
+
+#define bLSSIReadAddress 0x7f800000 /* T65 RF */
+#define bLSSIReadEdge 0x80000000 /* LSSI "Read" edge signal */
+#define bLSSIReadBackData 0xfffff /* T65 RF */
+
+#define bCCKSideBand 0x10 /* Reg 0xa00 rCCK0_System 20/40 */
+
+/* */
+/* Other Definition */
+/* */
+
+/* for PutRegsetting & GetRegSetting BitMask */
+#define bMaskByte0 0xff /* Reg 0xc50 rOFDM0_XAAGCCore~0xC6f */
+#define bMaskByte1 0xff00
+#define bMaskByte3 0xff000000
+#define bMaskDWord 0xffffffff
+#define bMask12Bits 0xfff
+#define bMaskOFDM_D 0xffc00000
+
+/* for PutRFRegsetting & GetRFRegSetting BitMask */
+#define bRFRegOffsetMask 0xfffff
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/hal8188e_rate_adaptive.h b/drivers/staging/rtl8188eu/include/hal8188e_rate_adaptive.h
new file mode 100644
index 0000000..5b59c25
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/hal8188e_rate_adaptive.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __INC_RA_H
+#define __INC_RA_H
+/*
+ * Copyright (c) Realtek Semiconductor Corp. All rights reserved.
+ *
+ * Module Name:
+ * RateAdaptive.h
+ *
+ * Abstract:
+ * Prototype of RA and related data structure.
+ *
+ * Major Change History:
+ * When Who What
+ * ---------- --------------- -------------------------------
+ * 2011-08-12 Page Create.
+ */
+
+/* Rate adaptive define */
+#define PERENTRY 23
+#define RETRYSIZE 5
+#define RATESIZE 28
+#define TX_RPT2_ITEM_SIZE 8
+
+/* */
+/* TX report 2 format in Rx desc */
+/* */
+#define GET_TX_RPT2_DESC_PKT_LEN_88E(__pRxStatusDesc) \
+ LE_BITS_TO_4BYTE(__pRxStatusDesc, 0, 9)
+#define GET_TX_RPT2_DESC_MACID_VALID_1_88E(__pRxStatusDesc) \
+ LE_BITS_TO_4BYTE(__pRxStatusDesc+16, 0, 32)
+#define GET_TX_RPT2_DESC_MACID_VALID_2_88E(__pRxStatusDesc) \
+ LE_BITS_TO_4BYTE(__pRxStatusDesc+20, 0, 32)
+
+#define GET_TX_REPORT_TYPE1_RERTY_0(__pAddr) \
+ LE_BITS_TO_4BYTE(__pAddr, 0, 16)
+#define GET_TX_REPORT_TYPE1_RERTY_1(__pAddr) \
+ LE_BITS_TO_1BYTE(__pAddr+2, 0, 8)
+#define GET_TX_REPORT_TYPE1_RERTY_2(__pAddr) \
+ LE_BITS_TO_1BYTE(__pAddr+3, 0, 8)
+#define GET_TX_REPORT_TYPE1_RERTY_3(__pAddr) \
+ LE_BITS_TO_1BYTE(__pAddr+4, 0, 8)
+#define GET_TX_REPORT_TYPE1_RERTY_4(__pAddr) \
+ LE_BITS_TO_1BYTE(__pAddr+4+1, 0, 8)
+#define GET_TX_REPORT_TYPE1_DROP_0(__pAddr) \
+ LE_BITS_TO_1BYTE(__pAddr+4+2, 0, 8)
+#define GET_TX_REPORT_TYPE1_DROP_1(__pAddr) \
+ LE_BITS_TO_1BYTE(__pAddr+4+3, 0, 8)
+
+/* End rate adaptive define */
+
+int ODM_RAInfo_Init_all(struct odm_dm_struct *dm_odm);
+
+int ODM_RAInfo_Init(struct odm_dm_struct *dm_odm, u8 MacID);
+
+u8 ODM_RA_GetShortGI_8188E(struct odm_dm_struct *dm_odm, u8 MacID);
+
+u8 ODM_RA_GetDecisionRate_8188E(struct odm_dm_struct *dm_odm, u8 MacID);
+
+u8 ODM_RA_GetHwPwrStatus_8188E(struct odm_dm_struct *dm_odm, u8 MacID);
+void ODM_RA_UpdateRateInfo_8188E(struct odm_dm_struct *dm_odm, u8 MacID,
+ u8 RateID, u32 RateMask,
+ u8 SGIEnable);
+
+void ODM_RA_SetRSSI_8188E(struct odm_dm_struct *dm_odm, u8 macid,
+ u8 rssi);
+
+void ODM_RA_TxRPT2Handle_8188E(struct odm_dm_struct *dm_odm,
+ u8 *txrpt_buf, u16 txrpt_len,
+ u32 validentry0, u32 validentry1);
+
+void ODM_RA_Set_TxRPT_Time(struct odm_dm_struct *dm_odm, u16 minRptTime);
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/hal_com.h b/drivers/staging/rtl8188eu/include/hal_com.h
new file mode 100644
index 0000000..93cbbe7
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/hal_com.h
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __HAL_COMMON_H__
+#define __HAL_COMMON_H__
+
+/* */
+/* Rate Definition */
+/* */
+/* CCK */
+#define RATR_1M 0x00000001
+#define RATR_2M 0x00000002
+#define RATR_55M 0x00000004
+#define RATR_11M 0x00000008
+/* OFDM */
+#define RATR_6M 0x00000010
+#define RATR_9M 0x00000020
+#define RATR_12M 0x00000040
+#define RATR_18M 0x00000080
+#define RATR_24M 0x00000100
+#define RATR_36M 0x00000200
+#define RATR_48M 0x00000400
+#define RATR_54M 0x00000800
+/* MCS 1 Spatial Stream */
+#define RATR_MCS0 0x00001000
+#define RATR_MCS1 0x00002000
+#define RATR_MCS2 0x00004000
+#define RATR_MCS3 0x00008000
+#define RATR_MCS4 0x00010000
+#define RATR_MCS5 0x00020000
+#define RATR_MCS6 0x00040000
+#define RATR_MCS7 0x00080000
+/* MCS 2 Spatial Stream */
+#define RATR_MCS8 0x00100000
+#define RATR_MCS9 0x00200000
+#define RATR_MCS10 0x00400000
+#define RATR_MCS11 0x00800000
+#define RATR_MCS12 0x01000000
+#define RATR_MCS13 0x02000000
+#define RATR_MCS14 0x04000000
+#define RATR_MCS15 0x08000000
+
+/* CCK */
+#define RATE_1M BIT(0)
+#define RATE_2M BIT(1)
+#define RATE_5_5M BIT(2)
+#define RATE_11M BIT(3)
+/* OFDM */
+#define RATE_6M BIT(4)
+#define RATE_9M BIT(5)
+#define RATE_12M BIT(6)
+#define RATE_18M BIT(7)
+#define RATE_24M BIT(8)
+#define RATE_36M BIT(9)
+#define RATE_48M BIT(10)
+#define RATE_54M BIT(11)
+/* MCS 1 Spatial Stream */
+#define RATE_MCS0 BIT(12)
+#define RATE_MCS1 BIT(13)
+#define RATE_MCS2 BIT(14)
+#define RATE_MCS3 BIT(15)
+#define RATE_MCS4 BIT(16)
+#define RATE_MCS5 BIT(17)
+#define RATE_MCS6 BIT(18)
+#define RATE_MCS7 BIT(19)
+/* MCS 2 Spatial Stream */
+#define RATE_MCS8 BIT(20)
+#define RATE_MCS9 BIT(21)
+#define RATE_MCS10 BIT(22)
+#define RATE_MCS11 BIT(23)
+#define RATE_MCS12 BIT(24)
+#define RATE_MCS13 BIT(25)
+#define RATE_MCS14 BIT(26)
+#define RATE_MCS15 BIT(27)
+
+/* ALL CCK Rate */
+#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M)
+#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M | \
+ RATR_24M | RATR_36M | RATR_48M | RATR_54M)
+#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 | \
+ RATR_MCS3 | RATR_MCS4 | RATR_MCS5|RATR_MCS6 | \
+ RATR_MCS7)
+#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 | \
+ RATR_MCS11 | RATR_MCS12 | RATR_MCS13 | \
+ RATR_MCS14 | RATR_MCS15)
+
+/*------------------------------ Tx Desc definition Macro --------------------*/
+/* pragma mark -- Tx Desc related definition. -- */
+/* Rate */
+/* CCK Rates, TxHT = 0 */
+#define DESC_RATE1M 0x00
+#define DESC_RATE2M 0x01
+#define DESC_RATE5_5M 0x02
+#define DESC_RATE11M 0x03
+
+/* OFDM Rates, TxHT = 0 */
+#define DESC_RATE6M 0x04
+#define DESC_RATE9M 0x05
+#define DESC_RATE12M 0x06
+#define DESC_RATE18M 0x07
+#define DESC_RATE24M 0x08
+#define DESC_RATE36M 0x09
+#define DESC_RATE48M 0x0a
+#define DESC_RATE54M 0x0b
+
+/* MCS Rates, TxHT = 1 */
+#define DESC_RATEMCS0 0x0c
+#define DESC_RATEMCS1 0x0d
+#define DESC_RATEMCS2 0x0e
+#define DESC_RATEMCS3 0x0f
+#define DESC_RATEMCS4 0x10
+#define DESC_RATEMCS5 0x11
+#define DESC_RATEMCS6 0x12
+#define DESC_RATEMCS7 0x13
+#define DESC_RATEMCS8 0x14
+#define DESC_RATEMCS9 0x15
+#define DESC_RATEMCS10 0x16
+#define DESC_RATEMCS11 0x17
+#define DESC_RATEMCS12 0x18
+#define DESC_RATEMCS13 0x19
+#define DESC_RATEMCS14 0x1a
+#define DESC_RATEMCS15 0x1b
+#define DESC_RATEMCS15_SG 0x1c
+#define DESC_RATEMCS32 0x20
+
+/* 1 Byte long (in unit of TU) */
+#define REG_P2P_CTWIN 0x0572
+#define REG_NOA_DESC_SEL 0x05CF
+#define REG_NOA_DESC_DURATION 0x05E0
+#define REG_NOA_DESC_INTERVAL 0x05E4
+#define REG_NOA_DESC_START 0x05E8
+#define REG_NOA_DESC_COUNT 0x05EC
+
+#include "HalVerDef.h"
+void dump_chip_info(struct HAL_VERSION ChipVersion);
+
+
+/* return the final channel plan decision */
+u8 hal_com_get_channel_plan(u8 hw_channel_plan, u8 sw_channel_plan,
+ u8 def_channel_plan, bool load_fail);
+
+u8 MRateToHwRate(u8 rate);
+
+void hal_set_brate_cfg(u8 *brates, u16 *rate_cfg);
+
+bool hal_mapping_out_pipe(struct adapter *adapter, u8 numoutpipe);
+
+#endif /* __HAL_COMMON_H__ */
diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h
new file mode 100644
index 0000000..516a896
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/hal_intf.h
@@ -0,0 +1,224 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __HAL_INTF_H__
+#define __HAL_INTF_H__
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <hal8188e_phy_cfg.h>
+
+enum RTL871X_HCI_TYPE {
+ RTW_PCIE = BIT(0),
+ RTW_USB = BIT(1),
+ RTW_SDIO = BIT(2),
+ RTW_GSPI = BIT(3),
+};
+
+enum _CHIP_TYPE {
+ NULL_CHIP_TYPE,
+ RTL8712_8188S_8191S_8192S,
+ RTL8188C_8192C,
+ RTL8192D,
+ RTL8723A,
+ RTL8188E,
+ MAX_CHIP_TYPE
+};
+
+enum hw_variables {
+ HW_VAR_MEDIA_STATUS,
+ HW_VAR_MEDIA_STATUS1,
+ HW_VAR_SET_OPMODE,
+ HW_VAR_MAC_ADDR,
+ HW_VAR_BSSID,
+ HW_VAR_INIT_RTS_RATE,
+ HW_VAR_BASIC_RATE,
+ HW_VAR_TXPAUSE,
+ HW_VAR_BCN_FUNC,
+ HW_VAR_CORRECT_TSF,
+ HW_VAR_CHECK_BSSID,
+ HW_VAR_MLME_DISCONNECT,
+ HW_VAR_MLME_SITESURVEY,
+ HW_VAR_MLME_JOIN,
+ HW_VAR_BEACON_INTERVAL,
+ HW_VAR_SLOT_TIME,
+ HW_VAR_RESP_SIFS,
+ HW_VAR_ACK_PREAMBLE,
+ HW_VAR_SEC_CFG,
+ HW_VAR_BCN_VALID,
+ HW_VAR_DM_FUNC_OP,
+ HW_VAR_DM_FUNC_SET,
+ HW_VAR_DM_FUNC_CLR,
+ HW_VAR_CAM_EMPTY_ENTRY,
+ HW_VAR_CAM_INVALID_ALL,
+ HW_VAR_CAM_WRITE,
+ HW_VAR_CAM_READ,
+ HW_VAR_AC_PARAM_VO,
+ HW_VAR_AC_PARAM_VI,
+ HW_VAR_AC_PARAM_BE,
+ HW_VAR_AC_PARAM_BK,
+ HW_VAR_ACM_CTRL,
+ HW_VAR_AMPDU_MIN_SPACE,
+ HW_VAR_AMPDU_FACTOR,
+ HW_VAR_RXDMA_AGG_PG_TH,
+ HW_VAR_SET_RPWM,
+ HW_VAR_H2C_FW_PWRMODE,
+ HW_VAR_H2C_FW_JOINBSSRPT,
+ HW_VAR_FWLPS_RF_ON,
+ HW_VAR_H2C_FW_P2P_PS_OFFLOAD,
+ HW_VAR_TDLS_WRCR,
+ HW_VAR_TDLS_INIT_CH_SEN,
+ HW_VAR_TDLS_RS_RCR,
+ HW_VAR_TDLS_DONE_CH_SEN,
+ HW_VAR_INITIAL_GAIN,
+ HW_VAR_TRIGGER_GPIO_0,
+ HW_VAR_BT_SET_COEXIST,
+ HW_VAR_BT_ISSUE_DELBA,
+ HW_VAR_CURRENT_ANTENNA,
+ HW_VAR_ANTENNA_DIVERSITY_LINK,
+ HW_VAR_ANTENNA_DIVERSITY_SELECT,
+ HW_VAR_SWITCH_EPHY_WoWLAN,
+ HW_VAR_EFUSE_USAGE,
+ HW_VAR_EFUSE_BYTES,
+ HW_VAR_EFUSE_BT_USAGE,
+ HW_VAR_EFUSE_BT_BYTES,
+ HW_VAR_FIFO_CLEARN_UP,
+ HW_VAR_CHECK_TXBUF,
+ HW_VAR_APFM_ON_MAC, /* Auto FSM to Turn On, include clock, isolation,
+ * power control for MAC only
+ */
+ /* The valid upper nav range for the HW updating, if the true value is
+ * larger than the upper range, the HW won't update it.
+ */
+ /* Unit in microsecond. 0 means disable this function. */
+ HW_VAR_NAV_UPPER,
+ HW_VAR_RPT_TIMER_SETTING,
+ HW_VAR_TX_RPT_MAX_MACID,
+ HW_VAR_H2C_MEDIA_STATUS_RPT,
+ HW_VAR_CHK_HI_QUEUE_EMPTY,
+};
+
+enum hal_def_variable {
+ HAL_DEF_UNDERCORATEDSMOOTHEDPWDB,
+ HAL_DEF_IS_SUPPORT_ANT_DIV,
+ HAL_DEF_CURRENT_ANTENNA,
+ HAL_DEF_DRVINFO_SZ,
+ HAL_DEF_MAX_RECVBUF_SZ,
+ HAL_DEF_RX_PACKET_OFFSET,
+ HAL_DEF_DBG_DUMP_RXPKT,/* for dbg */
+ HAL_DEF_DBG_DM_FUNC,/* for dbg */
+ HAL_DEF_RA_DECISION_RATE,
+ HAL_DEF_RA_SGI,
+ HAL_DEF_PT_PWR_STATUS,
+ HW_VAR_MAX_RX_AMPDU_FACTOR,
+ HW_DEF_RA_INFO_DUMP,
+ HAL_DEF_DBG_DUMP_TXPKT,
+ HW_DEF_FA_CNT_DUMP,
+ HW_DEF_ODM_DBG_FLAG,
+};
+
+enum hal_odm_variable {
+ HAL_ODM_STA_INFO,
+ HAL_ODM_P2P_STATE,
+ HAL_ODM_WIFI_DISPLAY_STATE,
+};
+
+enum hal_intf_ps_func {
+ HAL_USB_SELECT_SUSPEND,
+ HAL_MAX_ID,
+};
+
+enum rt_eeprom_type {
+ EEPROM_93C46,
+ EEPROM_93C56,
+ EEPROM_BOOT_EFUSE,
+};
+
+#define RF_CHANGE_BY_INIT 0
+#define RF_CHANGE_BY_IPS BIT(28)
+#define RF_CHANGE_BY_PS BIT(29)
+#define RF_CHANGE_BY_HW BIT(30)
+#define RF_CHANGE_BY_SW BIT(31)
+
+enum hardware_type {
+ HARDWARE_TYPE_RTL8188EU,
+ HARDWARE_TYPE_MAX,
+};
+
+#define GET_EEPROM_EFUSE_PRIV(adapter) (&adapter->eeprompriv)
+
+#define is_boot_from_eeprom(adapter) (adapter->eeprompriv.EepromOrEfuse)
+
+void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level);
+u32 rtl8188eu_hal_deinit(struct adapter *Adapter);
+u32 rtl8188eu_hal_init(struct adapter *Adapter);
+void rtw_hal_def_value_init(struct adapter *padapter);
+
+void rtw_hal_free_data(struct adapter *padapter);
+
+void rtw_hal_dm_init(struct adapter *padapter);
+void rtw_hal_sw_led_init(struct adapter *padapter);
+void rtw_hal_sw_led_deinit(struct adapter *padapter);
+
+u32 rtw_hal_power_on(struct adapter *padapter);
+uint rtw_hal_init(struct adapter *padapter);
+uint rtw_hal_deinit(struct adapter *padapter);
+void rtw_hal_stop(struct adapter *padapter);
+void rtw_hal_set_hwreg(struct adapter *padapter, u8 variable, u8 *val);
+void rtw_hal_get_hwreg(struct adapter *padapter, u8 variable, u8 *val);
+
+void rtw_hal_chip_configure(struct adapter *padapter);
+void rtw_hal_read_chip_info(struct adapter *padapter);
+void rtw_hal_read_chip_version(struct adapter *padapter);
+
+u8 rtw_hal_get_def_var(struct adapter *padapter,
+ enum hal_def_variable eVariable, void *pValue);
+
+void rtw_hal_set_odm_var(struct adapter *padapter,
+ enum hal_odm_variable eVariable, void *pValue1,
+ bool bSet);
+
+u32 rtw_hal_inirp_init(struct adapter *padapter);
+void rtw_hal_inirp_deinit(struct adapter *padapter);
+void usb_intf_stop(struct adapter *padapter);
+
+bool rtw_hal_xmit(struct adapter *padapter, struct xmit_frame *pxmitframe);
+s32 rtw_hal_mgnt_xmit(struct adapter *padapter,
+ struct xmit_frame *pmgntframe);
+
+s32 rtw_hal_init_xmit_priv(struct adapter *padapter);
+
+int rtw_hal_init_recv_priv(struct adapter *padapter);
+void rtw_hal_free_recv_priv(struct adapter *padapter);
+
+void rtw_hal_update_ra_mask(struct adapter *padapter, u32 mac_id, u8 level);
+void rtw_hal_add_ra_tid(struct adapter *adapt, u32 bitmap, u8 arg, u8 level);
+void rtw_hal_clone_data(struct adapter *dst_adapt,
+ struct adapter *src_adapt);
+
+void beacon_timing_control(struct adapter *padapter);
+
+u32 rtw_hal_read_rfreg(struct adapter *padapter, enum rf_radio_path eRFPath,
+ u32 RegAddr, u32 BitMask);
+
+void rtw_hal_set_bwmode(struct adapter *padapter,
+ enum ht_channel_width Bandwidth, u8 Offset);
+void rtw_hal_set_chan(struct adapter *padapter, u8 channel);
+void rtw_hal_dm_watchdog(struct adapter *padapter);
+
+u8 rtw_hal_antdiv_before_linked(struct adapter *padapter);
+void rtw_hal_antdiv_rssi_compared(struct adapter *padapter,
+ struct wlan_bssid_ex *dst,
+ struct wlan_bssid_ex *src);
+
+void rtw_hal_sreset_init(struct adapter *padapter);
+
+void rtw_hal_notch_filter(struct adapter *adapter, bool enable);
+
+void indicate_wx_scan_complete_event(struct adapter *padapter);
+u8 rtw_do_join(struct adapter *padapter);
+
+#endif /* __HAL_INTF_H__ */
diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h
new file mode 100644
index 0000000..a75dce3
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/ieee80211.h
@@ -0,0 +1,777 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __IEEE80211_H
+#define __IEEE80211_H
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include "wifi.h"
+#include <linux/wireless.h>
+
+#ifdef CPTCFG_88EU_AP_MODE
+
+#define RTL_IOCTL_HOSTAPD (SIOCIWFIRSTPRIV + 28)
+
+/* RTL871X_IOCTL_HOSTAPD ioctl() cmd: */
+enum {
+ RTL871X_HOSTAPD_FLUSH = 1,
+ RTL871X_HOSTAPD_ADD_STA = 2,
+ RTL871X_HOSTAPD_REMOVE_STA = 3,
+ RTL871X_HOSTAPD_GET_INFO_STA = 4,
+ /* REMOVED: PRISM2_HOSTAPD_RESET_TXEXC_STA = 5, */
+ RTL871X_HOSTAPD_GET_WPAIE_STA = 5,
+ RTL871X_SET_ENCRYPTION = 6,
+ RTL871X_GET_ENCRYPTION = 7,
+ RTL871X_HOSTAPD_SET_FLAGS_STA = 8,
+ RTL871X_HOSTAPD_GET_RID = 9,
+ RTL871X_HOSTAPD_SET_RID = 10,
+ RTL871X_HOSTAPD_SET_ASSOC_AP_ADDR = 11,
+ RTL871X_HOSTAPD_SET_GENERIC_ELEMENT = 12,
+ RTL871X_HOSTAPD_MLME = 13,
+ RTL871X_HOSTAPD_SCAN_REQ = 14,
+ RTL871X_HOSTAPD_STA_CLEAR_STATS = 15,
+ RTL871X_HOSTAPD_SET_BEACON = 16,
+ RTL871X_HOSTAPD_SET_WPS_BEACON = 17,
+ RTL871X_HOSTAPD_SET_WPS_PROBE_RESP = 18,
+ RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP = 19,
+ RTL871X_HOSTAPD_SET_HIDDEN_SSID = 20,
+ RTL871X_HOSTAPD_SET_MACADDR_ACL = 21,
+ RTL871X_HOSTAPD_ACL_ADD_STA = 22,
+ RTL871X_HOSTAPD_ACL_REMOVE_STA = 23,
+};
+
+/* STA flags */
+#define WLAN_STA_AUTH BIT(0)
+#define WLAN_STA_ASSOC BIT(1)
+#define WLAN_STA_PS BIT(2)
+#define WLAN_STA_TIM BIT(3)
+#define WLAN_STA_PERM BIT(4)
+#define WLAN_STA_AUTHORIZED BIT(5)
+#define WLAN_STA_PENDING_POLL BIT(6) /* pending activity poll not ACKed */
+#define WLAN_STA_SHORT_PREAMBLE BIT(7)
+#define WLAN_STA_PREAUTH BIT(8)
+#define WLAN_STA_WME BIT(9)
+#define WLAN_STA_MFP BIT(10)
+#define WLAN_STA_HT BIT(11)
+#define WLAN_STA_WPS BIT(12)
+#define WLAN_STA_MAYBE_WPS BIT(13)
+#define WLAN_STA_NONERP BIT(31)
+
+#endif
+
+#define IEEE_CMD_SET_WPA_PARAM 1
+#define IEEE_CMD_SET_WPA_IE 2
+#define IEEE_CMD_SET_ENCRYPTION 3
+#define IEEE_CMD_MLME 4
+
+#define IEEE_PARAM_WPA_ENABLED 1
+#define IEEE_PARAM_TKIP_COUNTERMEASURES 2
+#define IEEE_PARAM_DROP_UNENCRYPTED 3
+#define IEEE_PARAM_PRIVACY_INVOKED 4
+#define IEEE_PARAM_AUTH_ALGS 5
+#define IEEE_PARAM_IEEE_802_1X 6
+#define IEEE_PARAM_WPAX_SELECT 7
+
+#define AUTH_ALG_OPEN_SYSTEM 0x1
+#define AUTH_ALG_SHARED_KEY 0x2
+#define AUTH_ALG_LEAP 0x00000004
+
+#define IEEE_MLME_STA_DEAUTH 1
+#define IEEE_MLME_STA_DISASSOC 2
+
+#define IEEE_CRYPT_ERR_UNKNOWN_ALG 2
+#define IEEE_CRYPT_ERR_UNKNOWN_ADDR 3
+#define IEEE_CRYPT_ERR_CRYPT_INIT_FAILED 4
+#define IEEE_CRYPT_ERR_KEY_SET_FAILED 5
+#define IEEE_CRYPT_ERR_TX_KEY_SET_FAILED 6
+#define IEEE_CRYPT_ERR_CARD_CONF_FAILED 7
+
+
+#define IEEE_CRYPT_ALG_NAME_LEN 16
+
+#define WPA_CIPHER_NONE BIT(0)
+#define WPA_CIPHER_WEP40 BIT(1)
+#define WPA_CIPHER_WEP104 BIT(2)
+#define WPA_CIPHER_TKIP BIT(3)
+#define WPA_CIPHER_CCMP BIT(4)
+
+
+
+#define WPA_SELECTOR_LEN 4
+extern u8 RTW_WPA_OUI_TYPE[];
+extern u8 WPA_AUTH_KEY_MGMT_NONE[];
+extern u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X[];
+extern u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X[];
+extern u8 WPA_CIPHER_SUITE_NONE[];
+extern u8 WPA_CIPHER_SUITE_WEP40[];
+extern u8 WPA_CIPHER_SUITE_TKIP[];
+extern u8 WPA_CIPHER_SUITE_WRAP[];
+extern u8 WPA_CIPHER_SUITE_CCMP[];
+extern u8 WPA_CIPHER_SUITE_WEP104[];
+
+
+#define RSN_HEADER_LEN 4
+#define RSN_SELECTOR_LEN 4
+
+extern u16 RSN_VERSION_BSD;
+extern u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X[];
+extern u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X[];
+extern u8 RSN_CIPHER_SUITE_NONE[];
+extern u8 RSN_CIPHER_SUITE_WEP40[];
+extern u8 RSN_CIPHER_SUITE_TKIP[];
+extern u8 RSN_CIPHER_SUITE_WRAP[];
+extern u8 RSN_CIPHER_SUITE_CCMP[];
+extern u8 RSN_CIPHER_SUITE_WEP104[];
+
+enum ratr_table_mode {
+ RATR_INX_WIRELESS_NGB = 0, /* BGN 40 Mhz 2SS 1SS */
+ RATR_INX_WIRELESS_NG = 1, /* GN or N */
+ RATR_INX_WIRELESS_NB = 2, /* BGN 20 Mhz 2SS 1SS or BN */
+ RATR_INX_WIRELESS_N = 3,
+ RATR_INX_WIRELESS_GB = 4,
+ RATR_INX_WIRELESS_G = 5,
+ RATR_INX_WIRELESS_B = 6,
+ RATR_INX_WIRELESS_MC = 7,
+ RATR_INX_WIRELESS_AC_N = 8,
+};
+
+enum NETWORK_TYPE {
+ WIRELESS_INVALID = 0,
+ /* Sub-Element */
+ WIRELESS_11B = BIT(0), /* tx:cck only, rx:cck only, hw: cck */
+ WIRELESS_11G = BIT(1), /* tx:ofdm only, rx:ofdm & cck, hw:cck & ofdm*/
+ WIRELESS_11A = BIT(2), /* tx:ofdm only, rx: ofdm only, hw:ofdm only */
+ WIRELESS_11_24N = BIT(3), /* tx:MCS only, rx:MCS & cck, hw:MCS & cck */
+ WIRELESS_11_5N = BIT(4), /* tx:MCS only, rx:MCS & ofdm, hw:ofdm only */
+ WIRELESS_AC = BIT(6),
+
+ /* Combination */
+ /* tx: cck & ofdm, rx: cck & ofdm & MCS, hw: cck & ofdm */
+ WIRELESS_11BG = (WIRELESS_11B | WIRELESS_11G),
+ /* tx: ofdm & MCS, rx: ofdm & cck & MCS, hw: cck & ofdm */
+ WIRELESS_11G_24N = (WIRELESS_11G | WIRELESS_11_24N),
+ /* tx: ofdm & MCS, rx: ofdm & MCS, hw: ofdm only */
+ WIRELESS_11A_5N = (WIRELESS_11A | WIRELESS_11_5N),
+ /* tx: ofdm & cck & MCS, rx: ofdm & cck & MCS, hw: ofdm & cck */
+ WIRELESS_11BG_24N = (WIRELESS_11B | WIRELESS_11G | WIRELESS_11_24N),
+ /* tx: ofdm & MCS, rx: ofdm & MCS, hw: ofdm only */
+ WIRELESS_11AGN = (WIRELESS_11A | WIRELESS_11G | WIRELESS_11_24N |
+ WIRELESS_11_5N),
+ WIRELESS_11ABGN = (WIRELESS_11A | WIRELESS_11B | WIRELESS_11G |
+ WIRELESS_11_24N | WIRELESS_11_5N),
+};
+
+#define SUPPORTED_24G_NETTYPE_MSK \
+ (WIRELESS_11B | WIRELESS_11G | WIRELESS_11_24N)
+#define SUPPORTED_5G_NETTYPE_MSK \
+ (WIRELESS_11A | WIRELESS_11_5N)
+
+#define IsSupported24G(NetType) \
+ ((NetType) & SUPPORTED_24G_NETTYPE_MSK ? true : false)
+#define IsSupported5G(NetType) \
+ ((NetType) & SUPPORTED_5G_NETTYPE_MSK ? true : false)
+
+#define IsEnableHWCCK(NetType) \
+ IsSupported24G(NetType)
+#define IsEnableHWOFDM(NetType) \
+ ((NetType) & (WIRELESS_11G | WIRELESS_11_24N | \
+ SUPPORTED_5G_NETTYPE_MSK) ? true : false)
+
+#define IsSupportedRxCCK(NetType) IsEnableHWCCK(NetType)
+#define IsSupportedRxOFDM(NetType) IsEnableHWOFDM(NetType)
+#define IsSupportedRxMCS(NetType) IsEnableHWOFDM(NetType)
+
+#define IsSupportedTxCCK(NetType) \
+ ((NetType) & (WIRELESS_11B) ? true : false)
+#define IsSupportedTxOFDM(NetType) \
+ ((NetType) & (WIRELESS_11G | WIRELESS_11A) ? true : false)
+#define IsSupportedTxMCS(NetType) \
+ ((NetType) & (WIRELESS_11_24N | WIRELESS_11_5N) ? true : false)
+
+
+struct ieee_param {
+ u32 cmd;
+ u8 sta_addr[ETH_ALEN];
+ union {
+ struct {
+ u8 name;
+ u32 value;
+ } wpa_param;
+ struct {
+ u32 len;
+ u8 reserved[32];
+ u8 data[0];
+ } wpa_ie;
+ struct {
+ int command;
+ int reason_code;
+ } mlme;
+ struct {
+ u8 alg[IEEE_CRYPT_ALG_NAME_LEN];
+ u8 set_tx;
+ u32 err;
+ u8 idx;
+ u8 seq[8]; /* sequence counter (set: RX, get: TX) */
+ u16 key_len;
+ u8 key[0];
+ } crypt;
+#ifdef CPTCFG_88EU_AP_MODE
+ struct {
+ u16 aid;
+ u16 capability;
+ int flags;
+ u8 tx_supp_rates[16];
+ struct ieee80211_ht_cap ht_cap;
+ } add_sta;
+ struct {
+ u8 reserved[2];/* for set max_num_sta */
+ u8 buf[0];
+ } bcn_ie;
+#endif
+
+ } u;
+};
+
+#ifdef CPTCFG_88EU_AP_MODE
+struct ieee_param_ex {
+ u32 cmd;
+ u8 sta_addr[ETH_ALEN];
+ u8 data[0];
+};
+
+struct sta_data {
+ u16 aid;
+ u16 capability;
+ int flags;
+ u32 sta_set;
+ u8 tx_supp_rates[16];
+ u32 tx_supp_rates_len;
+ struct ieee80211_ht_cap ht_cap;
+ u64 rx_pkts;
+ u64 rx_bytes;
+ u64 rx_drops;
+ u64 tx_pkts;
+ u64 tx_bytes;
+ u64 tx_drops;
+};
+#endif
+
+#define IEEE80211_DATA_LEN 2304
+/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
+ * 6.2.1.1.2.
+
+ * The figure in section 7.1.2 suggests a body size of up to 2312
+ * bytes is allowed, which is a bit confusing, I suspect this
+ * represents the 2304 bytes of real data, plus a possible 8 bytes of
+ * WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro)
+ */
+
+
+#define IEEE80211_HLEN 30
+#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN)
+
+
+/* this is stolen from ipw2200 driver */
+#define IEEE_IBSS_MAC_HASH_SIZE 31
+
+enum eap_type {
+ EAP_PACKET = 0,
+ EAPOL_START,
+ EAPOL_LOGOFF,
+ EAPOL_KEY,
+ EAPOL_ENCAP_ASF_ALERT
+};
+
+#define IEEE80211_3ADDR_LEN 24
+#define IEEE80211_4ADDR_LEN 30
+#define IEEE80211_FCS_LEN 4
+
+#define MIN_FRAG_THRESHOLD 256U
+#define MAX_FRAG_THRESHOLD 2346U
+
+/* sequence control field */
+#define RTW_IEEE80211_SCTL_FRAG 0x000F
+#define RTW_IEEE80211_SCTL_SEQ 0xFFF0
+
+
+#define RTW_ERP_INFO_NON_ERP_PRESENT BIT(0)
+#define RTW_ERP_INFO_USE_PROTECTION BIT(1)
+#define RTW_ERP_INFO_BARKER_PREAMBLE_MODE BIT(2)
+
+/* QoS, QOS */
+#define NORMAL_ACK 0
+#define NO_ACK 1
+#define NON_EXPLICIT_ACK 2
+#define BLOCK_ACK 3
+
+#ifndef ETH_P_PAE
+#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
+#endif /* ETH_P_PAE */
+
+#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
+
+#define ETH_P_ECONET 0x0018
+
+#ifndef ETH_P_80211_RAW
+#define ETH_P_80211_RAW (ETH_P_ECONET + 1)
+#endif
+
+/* IEEE 802.11 defines */
+
+#define P80211_OUI_LEN 3
+
+struct ieee80211_snap_hdr {
+ u8 dsap; /* always 0xAA */
+ u8 ssap; /* always 0xAA */
+ u8 ctrl; /* always 0x03 */
+ u8 oui[P80211_OUI_LEN]; /* organizational universal id */
+} __packed;
+
+#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
+
+#define WLAN_QC_GET_TID(qc) ((qc) & 0x0f)
+
+#define WLAN_GET_SEQ_FRAG(seq) ((seq) & RTW_IEEE80211_SCTL_FRAG)
+#define WLAN_GET_SEQ_SEQ(seq) ((seq) & RTW_IEEE80211_SCTL_SEQ)
+
+/* Non standard? Not in <linux/ieee80211.h> */
+#define WLAN_REASON_EXPIRATION_CHK 65535
+
+#define IEEE80211_MGMT_HDR_LEN 24
+#define IEEE80211_DATA_HDR3_LEN 24
+#define IEEE80211_DATA_HDR4_LEN 30
+
+#define IEEE80211_CCK_MODULATION BIT(0)
+#define IEEE80211_OFDM_MODULATION BIT(1)
+
+#define IEEE80211_24GHZ_BAND BIT(0)
+#define IEEE80211_52GHZ_BAND BIT(1)
+
+#define IEEE80211_CCK_RATE_LEN 4
+#define IEEE80211_NUM_OFDM_RATESLEN 8
+
+
+#define IEEE80211_CCK_RATE_1MB 0x02
+#define IEEE80211_CCK_RATE_2MB 0x04
+#define IEEE80211_CCK_RATE_5MB 0x0B
+#define IEEE80211_CCK_RATE_11MB 0x16
+#define IEEE80211_OFDM_RATE_LEN 8
+#define IEEE80211_OFDM_RATE_6MB 0x0C
+#define IEEE80211_OFDM_RATE_9MB 0x12
+#define IEEE80211_OFDM_RATE_12MB 0x18
+#define IEEE80211_OFDM_RATE_18MB 0x24
+#define IEEE80211_OFDM_RATE_24MB 0x30
+#define IEEE80211_OFDM_RATE_36MB 0x48
+#define IEEE80211_OFDM_RATE_48MB 0x60
+#define IEEE80211_OFDM_RATE_54MB 0x6C
+#define IEEE80211_BASIC_RATE_MASK 0x80
+
+#define IEEE80211_CCK_RATE_1MB_MASK BIT(0)
+#define IEEE80211_CCK_RATE_2MB_MASK BIT(1)
+#define IEEE80211_CCK_RATE_5MB_MASK BIT(2)
+#define IEEE80211_CCK_RATE_11MB_MASK BIT(3)
+#define IEEE80211_OFDM_RATE_6MB_MASK BIT(4)
+#define IEEE80211_OFDM_RATE_9MB_MASK BIT(5)
+#define IEEE80211_OFDM_RATE_12MB_MASK BIT(6)
+#define IEEE80211_OFDM_RATE_18MB_MASK BIT(7)
+#define IEEE80211_OFDM_RATE_24MB_MASK BIT(8)
+#define IEEE80211_OFDM_RATE_36MB_MASK BIT(9)
+#define IEEE80211_OFDM_RATE_48MB_MASK BIT(10)
+#define IEEE80211_OFDM_RATE_54MB_MASK BIT(11)
+
+#define IEEE80211_CCK_RATES_MASK 0x0000000F
+#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \
+ IEEE80211_CCK_RATE_2MB_MASK)
+#define IEEE80211_CCK_DEFAULT_RATES_MASK \
+ (IEEE80211_CCK_BASIC_RATES_MASK | \
+ IEEE80211_CCK_RATE_5MB_MASK | \
+ IEEE80211_CCK_RATE_11MB_MASK)
+
+#define IEEE80211_OFDM_RATES_MASK 0x00000FF0
+#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \
+ IEEE80211_OFDM_RATE_12MB_MASK | \
+ IEEE80211_OFDM_RATE_24MB_MASK)
+#define IEEE80211_OFDM_DEFAULT_RATES_MASK \
+ (IEEE80211_OFDM_BASIC_RATES_MASK | \
+ IEEE80211_OFDM_RATE_9MB_MASK | \
+ IEEE80211_OFDM_RATE_18MB_MASK | \
+ IEEE80211_OFDM_RATE_36MB_MASK | \
+ IEEE80211_OFDM_RATE_48MB_MASK | \
+ IEEE80211_OFDM_RATE_54MB_MASK)
+
+#define IEEE80211_NUM_OFDM_RATES 8
+#define IEEE80211_NUM_CCK_RATES 4
+#define IEEE80211_OFDM_SHIFT_MASK_A 4
+
+/* IEEE 802.11 requires that STA supports concurrent reception of at least
+ * three fragmented frames. This define can be increased to support more
+ * concurrent frames, but it should be noted that each entry can consume about
+ * 2 kB of RAM and increasing cache size will slow down frame reassembly.
+ */
+#define IEEE80211_FRAG_CACHE_LEN 4
+
+#define SEC_KEY_1 BIT(0)
+#define SEC_KEY_2 BIT(1)
+#define SEC_KEY_3 BIT(2)
+#define SEC_KEY_4 BIT(3)
+#define SEC_ACTIVE_KEY BIT(4)
+#define SEC_AUTH_MODE BIT(5)
+#define SEC_UNICAST_GROUP BIT(6)
+#define SEC_LEVEL BIT(7)
+#define SEC_ENABLED BIT(8)
+
+#define SEC_LEVEL_0 0 /* None */
+#define SEC_LEVEL_1 1 /* WEP 40 and 104 bit */
+#define SEC_LEVEL_2 2 /* Level 1 + TKIP */
+#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */
+#define SEC_LEVEL_3 4 /* Level 2 + CCMP */
+
+#define WEP_KEYS 4
+#define WEP_KEY_LEN 13
+
+/* SWEEP TABLE ENTRIES NUMBER*/
+#define MAX_SWEEP_TAB_ENTRIES 42
+#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET 7
+/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs
+ * only use 8, and then use extended rates for the remaining supported
+ * rates. Other APs, however, stick all of their supported rates on the
+ * main rates information element...
+ */
+#define MAX_RATES_LENGTH ((u8)12)
+#define MAX_RATES_EX_LENGTH ((u8)16)
+#define MAX_NETWORK_COUNT 128
+#define MAX_CHANNEL_NUMBER 161
+#define IEEE80211_SOFTMAC_SCAN_TIME 400
+/* HZ / 2) */
+#define IEEE80211_SOFTMAC_ASSOC_RETRY_TIME (HZ * 2)
+
+#define CRC_LENGTH 4U
+
+#define MAX_WPA_IE_LEN (256)
+#define MAX_WPS_IE_LEN (512)
+#define MAX_P2P_IE_LEN (256)
+#define MAX_WFD_IE_LEN (128)
+
+#define NETWORK_EMPTY_ESSID BIT(0)
+#define NETWORK_HAS_OFDM BIT(1)
+#define NETWORK_HAS_CCK BIT(2)
+
+#define IW_ESSID_MAX_SIZE 32
+/*
+ * join_res:
+ * -1: authentication fail
+ * -2: association fail
+ * > 0: TID
+ */
+
+enum ieee80211_state {
+ /* the card is not linked at all */
+ IEEE80211_NOLINK = 0,
+
+ /* IEEE80211_ASSOCIATING* are for BSS client mode
+ * the driver shall not perform RX filtering unless
+ * the state is LINKED.
+ * The driver shall just check for the state LINKED and
+ * defaults to NOLINK for ALL the other states (including
+ * LINKED_SCANNING)
+ */
+
+ /* the association procedure will start (wq scheduling)*/
+ IEEE80211_ASSOCIATING,
+ IEEE80211_ASSOCIATING_RETRY,
+
+ /* the association procedure is sending AUTH request*/
+ IEEE80211_ASSOCIATING_AUTHENTICATING,
+
+ /* the association procedure has successfully authentcated
+ * and is sending association request
+ */
+ IEEE80211_ASSOCIATING_AUTHENTICATED,
+
+ /* the link is ok. the card associated to a BSS or linked
+ * to a ibss cell or acting as an AP and creating the bss
+ */
+ IEEE80211_LINKED,
+
+ /* same as LINKED, but the driver shall apply RX filter
+ * rules as we are in NO_LINK mode. As the card is still
+ * logically linked, but it is doing a syncro site survey
+ * then it will be back to LINKED state.
+ */
+ IEEE80211_LINKED_SCANNING,
+
+};
+
+#define DEFAULT_MAX_SCAN_AGE (15 * HZ)
+#define DEFAULT_FTS 2346
+
+#define CFG_IEEE80211_RESERVE_FCS BIT(0)
+#define CFG_IEEE80211_COMPUTE_FCS BIT(1)
+
+#define MAXTID 16
+
+#define IEEE_A BIT(0)
+#define IEEE_B BIT(1)
+#define IEEE_G BIT(2)
+#define IEEE_MODE_MASK (IEEE_A | IEEE_B | IEEE_G)
+
+/* Action category code */
+enum rtw_ieee80211_category {
+ RTW_WLAN_CATEGORY_SPECTRUM_MGMT = 0,
+ RTW_WLAN_CATEGORY_QOS = 1,
+ RTW_WLAN_CATEGORY_DLS = 2,
+ RTW_WLAN_CATEGORY_BACK = 3,
+ RTW_WLAN_CATEGORY_PUBLIC = 4, /* IEEE 802.11 public action frames */
+ RTW_WLAN_CATEGORY_RADIO_MEASUREMENT = 5,
+ RTW_WLAN_CATEGORY_FT = 6,
+ RTW_WLAN_CATEGORY_HT = 7,
+ RTW_WLAN_CATEGORY_SA_QUERY = 8,
+ RTW_WLAN_CATEGORY_TDLS = 12,
+ RTW_WLAN_CATEGORY_WMM = 17,
+ RTW_WLAN_CATEGORY_P2P = 0x7f,/* P2P action frames */
+};
+
+/* SPECTRUM_MGMT action code */
+enum rtw_ieee80211_spectrum_mgmt_actioncode {
+ RTW_WLAN_ACTION_SPCT_MSR_REQ = 0,
+ RTW_WLAN_ACTION_SPCT_MSR_RPRT = 1,
+ RTW_WLAN_ACTION_SPCT_TPC_REQ = 2,
+ RTW_WLAN_ACTION_SPCT_TPC_RPRT = 3,
+ RTW_WLAN_ACTION_SPCT_CHL_SWITCH = 4,
+ RTW_WLAN_ACTION_SPCT_EXT_CHL_SWITCH = 5,
+};
+
+enum _PUBLIC_ACTION {
+ ACT_PUBLIC_BSSCOEXIST = 0, /* 20/40 BSS Coexistence */
+ ACT_PUBLIC_DSE_ENABLE = 1,
+ ACT_PUBLIC_DSE_DEENABLE = 2,
+ ACT_PUBLIC_DSE_REG_LOCATION = 3,
+ ACT_PUBLIC_EXT_CHL_SWITCH = 4,
+ ACT_PUBLIC_DSE_MSR_REQ = 5,
+ ACT_PUBLIC_DSE_MSR_RPRT = 6,
+ ACT_PUBLIC_MP = 7, /* Measurement Pilot */
+ ACT_PUBLIC_DSE_PWR_CONSTRAINT = 8,
+ ACT_PUBLIC_VENDOR = 9, /* for WIFI_DIRECT */
+ ACT_PUBLIC_GAS_INITIAL_REQ = 10,
+ ACT_PUBLIC_GAS_INITIAL_RSP = 11,
+ ACT_PUBLIC_GAS_COMEBACK_REQ = 12,
+ ACT_PUBLIC_GAS_COMEBACK_RSP = 13,
+ ACT_PUBLIC_TDLS_DISCOVERY_RSP = 14,
+ ACT_PUBLIC_LOCATION_TRACK = 15,
+ ACT_PUBLIC_MAX
+};
+
+/* BACK action code */
+enum rtw_ieee80211_back_actioncode {
+ RTW_WLAN_ACTION_ADDBA_REQ = 0,
+ RTW_WLAN_ACTION_ADDBA_RESP = 1,
+ RTW_WLAN_ACTION_DELBA = 2,
+};
+
+/* HT features action code */
+enum rtw_ieee80211_ht_actioncode {
+ RTW_WLAN_ACTION_NOTIFY_CH_WIDTH = 0,
+ RTW_WLAN_ACTION_SM_PS = 1,
+ RTW_WLAN_ACTION_PSPM = 2,
+ RTW_WLAN_ACTION_PCO_PHASE = 3,
+ RTW_WLAN_ACTION_MIMO_CSI_MX = 4,
+ RTW_WLAN_ACTION_MIMO_NONCP_BF = 5,
+ RTW_WLAN_ACTION_MIMP_CP_BF = 6,
+ RTW_WLAN_ACTION_ASEL_INDICATES_FB = 7,
+ RTW_WLAN_ACTION_HI_INFO_EXCHG = 8,
+};
+
+/* BACK (block-ack) parties */
+enum rtw_ieee80211_back_parties {
+ RTW_WLAN_BACK_RECIPIENT = 0,
+ RTW_WLAN_BACK_INITIATOR = 1,
+ RTW_WLAN_BACK_TIMER = 2,
+};
+
+#define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs)
+ * 00:50:F2
+ */
+#define WME_OUI_TYPE 2
+#define WME_OUI_SUBTYPE_INFORMATION_ELEMENT 0
+#define WME_OUI_SUBTYPE_PARAMETER_ELEMENT 1
+#define WME_OUI_SUBTYPE_TSPEC_ELEMENT 2
+#define WME_VERSION 1
+
+#define WME_ACTION_CODE_SETUP_REQUEST 0
+#define WME_ACTION_CODE_SETUP_RESPONSE 1
+#define WME_ACTION_CODE_TEARDOWN 2
+
+#define WME_SETUP_RESPONSE_STATUS_ADMISSION_ACCEPTED 0
+#define WME_SETUP_RESPONSE_STATUS_INVALID_PARAMETERS 1
+#define WME_SETUP_RESPONSE_STATUS_REFUSED 3
+
+#define WME_TSPEC_DIRECTION_UPLINK 0
+#define WME_TSPEC_DIRECTION_DOWNLINK 1
+#define WME_TSPEC_DIRECTION_BI_DIRECTIONAL 3
+
+
+#define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */
+
+#define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */
+
+/**
+ * enum rtw_ieee80211_channel_flags - channel flags
+ *
+ * Channel flags set by the regulatory control code.
+ *
+ * @RTW_IEEE80211_CHAN_DISABLED: This channel is disabled.
+ * @RTW_IEEE80211_CHAN_PASSIVE_SCAN: Only passive scanning is permitted
+ * on this channel.
+ * @RTW_IEEE80211_CHAN_NO_IBSS: IBSS is not allowed on this channel.
+ * @RTW_IEEE80211_CHAN_RADAR: Radar detection is required on this channel.
+ * @RTW_IEEE80211_CHAN_NO_HT40PLUS: extension channel above this channel
+ * is not permitted.
+ * @RTW_IEEE80211_CHAN_NO_HT40MINUS: extension channel below this channel
+ * is not permitted.
+ */
+enum rtw_ieee80211_channel_flags {
+ RTW_IEEE80211_CHAN_DISABLED = BIT(0),
+ RTW_IEEE80211_CHAN_PASSIVE_SCAN = BIT(1),
+ RTW_IEEE80211_CHAN_NO_IBSS = BIT(2),
+ RTW_IEEE80211_CHAN_RADAR = BIT(3),
+ RTW_IEEE80211_CHAN_NO_HT40PLUS = BIT(4),
+ RTW_IEEE80211_CHAN_NO_HT40MINUS = BIT(5),
+};
+
+#define RTW_IEEE80211_CHAN_NO_HT40 \
+ (RTW_IEEE80211_CHAN_NO_HT40PLUS | RTW_IEEE80211_CHAN_NO_HT40MINUS)
+
+/* Represent channel details, subset of ieee80211_channel */
+struct rtw_ieee80211_channel {
+ u16 hw_value;
+ u32 flags;
+};
+
+#define CHAN_FMT \
+ "hw_value:%u, " \
+ "flags:0x%08x" \
+
+#define CHAN_ARG(channel) \
+ (channel)->hw_value \
+ , (channel)->flags \
+
+/* Parsed Information Elements */
+struct rtw_ieee802_11_elems {
+ u8 *ssid;
+ u8 ssid_len;
+ u8 *supp_rates;
+ u8 supp_rates_len;
+ u8 *fh_params;
+ u8 fh_params_len;
+ u8 *ds_params;
+ u8 ds_params_len;
+ u8 *cf_params;
+ u8 cf_params_len;
+ u8 *tim;
+ u8 tim_len;
+ u8 *ibss_params;
+ u8 ibss_params_len;
+ u8 *challenge;
+ u8 challenge_len;
+ u8 *erp_info;
+ u8 erp_info_len;
+ u8 *ext_supp_rates;
+ u8 ext_supp_rates_len;
+ u8 *wpa_ie;
+ u8 wpa_ie_len;
+ u8 *rsn_ie;
+ u8 rsn_ie_len;
+ u8 *wme;
+ u8 wme_len;
+ u8 *wme_tspec;
+ u8 wme_tspec_len;
+ u8 *wps_ie;
+ u8 wps_ie_len;
+ u8 *power_cap;
+ u8 power_cap_len;
+ u8 *supp_channels;
+ u8 supp_channels_len;
+ u8 *mdie;
+ u8 mdie_len;
+ u8 *ftie;
+ u8 ftie_len;
+ u8 *timeout_int;
+ u8 timeout_int_len;
+ u8 *ht_capabilities;
+ u8 ht_capabilities_len;
+ u8 *ht_operation;
+ u8 ht_operation_len;
+ u8 *vendor_ht_cap;
+ u8 vendor_ht_cap_len;
+};
+
+enum parse_res {
+ ParseOK = 0,
+ ParseUnknown = 1,
+ ParseFailed = -1
+};
+
+enum parse_res rtw_ieee802_11_parse_elems(u8 *start, uint len,
+ struct rtw_ieee802_11_elems *elems,
+ int show_errors);
+
+u8 *rtw_set_fixed_ie(void *pbuf, unsigned int len,
+ void *source, unsigned int *frlen);
+u8 *rtw_set_ie(u8 *pbuf, int index, uint len, u8 *source, uint *frlen);
+
+enum secondary_ch_offset {
+ SCN = 0, /* no secondary channel */
+ SCA = 1, /* secondary channel above */
+ SCB = 3, /* secondary channel below */
+};
+
+u8 *rtw_get_ie(u8 *pbuf, int index, uint *len, int limit);
+
+void rtw_set_supported_rate(u8 *SupportedRates, uint mode);
+
+unsigned char *rtw_get_wpa_ie(unsigned char *pie, uint *wpa_ie_len, int limit);
+unsigned char *rtw_get_wpa2_ie(unsigned char *pie, uint *rsn_ie_len, int limit);
+int rtw_get_wpa_cipher_suite(u8 *s);
+int rtw_get_wpa2_cipher_suite(u8 *s);
+int rtw_get_wapi_ie(u8 *in_ie, uint in_len, u8 *wapi_ie, u16 *wapi_len);
+int rtw_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher,
+ int *pairwise_cipher, int *is_8021x);
+int rtw_parse_wpa2_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher,
+ int *pairwise_cipher, int *is_8021x);
+
+void rtw_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len,
+ u8 *wpa_ie, u16 *wpa_len);
+
+u8 rtw_is_wps_ie(u8 *ie_ptr, uint *wps_ielen);
+u8 *rtw_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen);
+u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id,
+ u8 *buf_attr, u32 *len_attr);
+u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id,
+ u8 *buf_content, uint *len_content);
+
+uint rtw_get_rateset_len(u8 *rateset);
+
+struct registry_priv;
+int rtw_generate_ie(struct registry_priv *pregistrypriv);
+
+
+int rtw_get_bit_value_from_ieee_value(u8 val);
+
+bool rtw_is_cckrates_included(u8 *rate);
+
+bool rtw_is_cckratesonly_included(u8 *rate);
+
+int rtw_check_network_type(unsigned char *rate, int ratelen, int channel);
+
+void rtw_get_bcn_info(struct wlan_network *pnetwork);
+
+void rtw_macaddr_cfg(u8 *mac_addr);
+
+u16 rtw_mcs_rate(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40,
+ unsigned char *MCS_rate);
+
+#endif /* IEEE80211_H */
diff --git a/drivers/staging/rtl8188eu/include/mlme_osdep.h b/drivers/staging/rtl8188eu/include/mlme_osdep.h
new file mode 100644
index 0000000..8e91944
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/mlme_osdep.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __MLME_OSDEP_H_
+#define __MLME_OSDEP_H_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+
+void rtw_init_mlme_timer(struct adapter *padapter);
+void rtw_os_indicate_disconnect(struct adapter *adapter);
+void rtw_os_indicate_connect(struct adapter *adapter);
+void rtw_report_sec_ie(struct adapter *adapter, u8 authmode, u8 *sec_ie);
+
+void rtw_reset_securitypriv(struct adapter *adapter);
+void indicate_wx_scan_complete_event(struct adapter *padapter);
+
+#endif /* _MLME_OSDEP_H_ */
diff --git a/drivers/staging/rtl8188eu/include/mon.h b/drivers/staging/rtl8188eu/include/mon.h
new file mode 100644
index 0000000..2977106
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/mon.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * RTL8188EU monitor interface
+ *
+ * Copyright (C) 2015 Jakub Sitnicki
+ */
+
+/*
+ * Monitor interface receives all transmitted and received IEEE 802.11
+ * frames, both Data and Management, and passes them up to userspace
+ * preserving the WLAN headers.
+ */
+
+#ifndef _MON_H_
+#define _MON_H_
+
+struct net_device;
+struct recv_frame;
+struct xmit_frame;
+
+struct net_device *rtl88eu_mon_init(void);
+void rtl88eu_mon_deinit(struct net_device *dev);
+
+void rtl88eu_mon_recv_hook(struct net_device *dev, struct recv_frame *frame);
+void rtl88eu_mon_xmit_hook(struct net_device *dev, struct xmit_frame *frame,
+ uint frag_len);
+
+#endif /* _MON_H_ */
diff --git a/drivers/staging/rtl8188eu/include/odm.h b/drivers/staging/rtl8188eu/include/odm.h
new file mode 100644
index 0000000..8245cea
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/odm.h
@@ -0,0 +1,1066 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+
+#ifndef __HALDMOUTSRC_H__
+#define __HALDMOUTSRC_H__
+
+/* Definition */
+/* Define all team support ability. */
+
+/* Define for all teams. Please Define the constant in your precomp header. */
+
+/* define DM_ODM_SUPPORT_AP 0 */
+/* define DM_ODM_SUPPORT_ADSL 0 */
+/* define DM_ODM_SUPPORT_CE 0 */
+/* define DM_ODM_SUPPORT_MP 1 */
+
+/* Define ODM SW team support flag. */
+
+/* Antenna Switch Relative Definition. */
+
+/* Add new function SwAntDivCheck8192C(). */
+/* This is the main function of Antenna diversity function before link. */
+/* Mainly, it just retains last scan result and scan again. */
+/* After that, it compares the scan result to see which one gets better
+ * RSSI. It selects antenna with better receiving power and returns better
+ * scan result.
+ */
+
+#define TP_MODE 0
+#define RSSI_MODE 1
+#define TRAFFIC_LOW 0
+#define TRAFFIC_HIGH 1
+
+/* 3 Tx Power Tracking */
+/* 3============================================================ */
+#define DPK_DELTA_MAPPING_NUM 13
+#define index_mapping_HP_NUM 15
+
+
+/* */
+/* 3 PSD Handler */
+/* 3============================================================ */
+
+#define AFH_PSD 1 /* 0:normal PSD scan, 1: only do 20 pts PSD */
+#define MODE_40M 0 /* 0:20M, 1:40M */
+#define PSD_TH2 3
+#define PSD_CHM 20 /* Minimum channel number for BT AFH */
+#define SIR_STEP_SIZE 3
+#define Smooth_Size_1 5
+#define Smooth_TH_1 3
+#define Smooth_Size_2 10
+#define Smooth_TH_2 4
+#define Smooth_Size_3 20
+#define Smooth_TH_3 4
+#define Smooth_Step_Size 5
+#define Adaptive_SIR 1
+#define PSD_RESCAN 4
+#define PSD_SCAN_INTERVAL 700 /* ms */
+
+/* 8723A High Power IGI Setting */
+#define DM_DIG_HIGH_PWR_IGI_LOWER_BOUND 0x22
+#define DM_DIG_Gmode_HIGH_PWR_IGI_LOWER_BOUND 0x28
+#define DM_DIG_HIGH_PWR_THRESHOLD 0x3a
+
+/* LPS define */
+#define DM_DIG_FA_TH0_LPS 4 /* 4 in lps */
+#define DM_DIG_FA_TH1_LPS 15 /* 15 lps */
+#define DM_DIG_FA_TH2_LPS 30 /* 30 lps */
+#define RSSI_OFFSET_DIG 0x05;
+
+struct rtw_dig {
+ u8 Dig_Enable_Flag;
+ u8 Dig_Ext_Port_Stage;
+
+ int RssiLowThresh;
+ int RssiHighThresh;
+
+ u32 FALowThresh;
+ u32 FAHighThresh;
+
+ u8 CurSTAConnectState;
+ u8 PreSTAConnectState;
+ u8 CurMultiSTAConnectState;
+
+ u8 PreIGValue;
+ u8 CurIGValue;
+ u8 BackupIGValue;
+
+ s8 BackoffVal;
+ s8 BackoffVal_range_max;
+ s8 BackoffVal_range_min;
+ u8 rx_gain_range_max;
+ u8 rx_gain_range_min;
+ u8 Rssi_val_min;
+
+ u8 PreCCK_CCAThres;
+ u8 CurCCK_CCAThres;
+ u8 PreCCKPDState;
+ u8 CurCCKPDState;
+
+ u8 LargeFAHit;
+ u8 ForbiddenIGI;
+ u32 Recover_cnt;
+
+ u8 DIG_Dynamic_MIN_0;
+ u8 DIG_Dynamic_MIN_1;
+ bool bMediaConnect_0;
+ bool bMediaConnect_1;
+
+ u32 AntDiv_RSSI_max;
+ u32 RSSI_max;
+};
+
+struct rtl_ps {
+ u8 PreCCAState;
+ u8 CurCCAState;
+
+ u8 PreRFState;
+ u8 CurRFState;
+
+ int Rssi_val_min;
+
+ u8 initialize;
+ u32 Reg874, RegC70, Reg85C, RegA74;
+
+};
+
+struct false_alarm_stats {
+ u32 Cnt_Parity_Fail;
+ u32 Cnt_Rate_Illegal;
+ u32 Cnt_Crc8_fail;
+ u32 Cnt_Mcs_fail;
+ u32 Cnt_Ofdm_fail;
+ u32 Cnt_Cck_fail;
+ u32 Cnt_all;
+ u32 Cnt_Fast_Fsync;
+ u32 Cnt_SB_Search_fail;
+ u32 Cnt_OFDM_CCA;
+ u32 Cnt_CCK_CCA;
+ u32 Cnt_CCA_all;
+ u32 Cnt_BW_USC; /* Gary */
+ u32 Cnt_BW_LSC; /* Gary */
+};
+
+struct rx_hpc {
+ u8 RXHP_flag;
+ u8 PSD_func_trigger;
+ u8 PSD_bitmap_RXHP[80];
+ u8 Pre_IGI;
+ u8 Cur_IGI;
+ u8 Pre_pw_th;
+ u8 Cur_pw_th;
+ bool First_time_enter;
+ bool RXHP_enable;
+ u8 TP_Mode;
+ struct timer_list PSDTimer;
+};
+
+#define ASSOCIATE_ENTRY_NUM 32 /* Max size of AsocEntry[]. */
+#define ODM_ASSOCIATE_ENTRY_NUM ASSOCIATE_ENTRY_NUM
+
+/* This indicates two different steps. */
+/* In SWAW_STEP_PEAK, driver needs to switch antenna and listen to
+ * the signal on the air.
+ */
+/* In SWAW_STEP_DETERMINE, driver just compares the signal captured in
+ * SWAW_STEP_PEAK with original RSSI to determine if it is necessary to
+ * switch antenna.
+ */
+
+#define SWAW_STEP_PEAK 0
+#define SWAW_STEP_DETERMINE 1
+
+#define TP_MODE 0
+#define RSSI_MODE 1
+#define TRAFFIC_LOW 0
+#define TRAFFIC_HIGH 1
+
+struct sw_ant_switch {
+ u8 try_flag;
+ s32 PreRSSI;
+ u8 CurAntenna;
+ u8 PreAntenna;
+ u8 RSSI_Trying;
+ u8 TestMode;
+ u8 bTriggerAntennaSwitch;
+ u8 SelectAntennaMap;
+ u8 RSSI_target;
+
+ /* Before link Antenna Switch check */
+ u8 SWAS_NoLink_State;
+ u32 SWAS_NoLink_BK_Reg860;
+ bool ANTA_ON; /* To indicate Ant A is or not */
+ bool ANTB_ON; /* To indicate Ant B is on or not */
+
+ s32 RSSI_sum_A;
+ s32 RSSI_sum_B;
+ s32 RSSI_cnt_A;
+ s32 RSSI_cnt_B;
+ u64 lastTxOkCnt;
+ u64 lastRxOkCnt;
+ u64 TXByteCnt_A;
+ u64 TXByteCnt_B;
+ u64 RXByteCnt_A;
+ u64 RXByteCnt_B;
+ u8 TrafficLoad;
+ struct timer_list SwAntennaSwitchTimer;
+ /* Hybrid Antenna Diversity */
+ u32 CCK_Ant1_Cnt[ASSOCIATE_ENTRY_NUM];
+ u32 CCK_Ant2_Cnt[ASSOCIATE_ENTRY_NUM];
+ u32 OFDM_Ant1_Cnt[ASSOCIATE_ENTRY_NUM];
+ u32 OFDM_Ant2_Cnt[ASSOCIATE_ENTRY_NUM];
+ u32 RSSI_Ant1_Sum[ASSOCIATE_ENTRY_NUM];
+ u32 RSSI_Ant2_Sum[ASSOCIATE_ENTRY_NUM];
+ u8 TxAnt[ASSOCIATE_ENTRY_NUM];
+ u8 TargetSTA;
+ u8 antsel;
+ u8 RxIdleAnt;
+};
+
+struct edca_turbo {
+ bool bCurrentTurboEDCA;
+ bool bIsCurRDLState;
+ u32 prv_traffic_idx; /* edca turbo */
+};
+
+struct odm_rate_adapt {
+ u8 Type; /* DM_Type_ByFW/DM_Type_ByDriver */
+ u8 HighRSSIThresh; /* if RSSI > HighRSSIThresh => RATRState is DM_RATR_STA_HIGH */
+ u8 LowRSSIThresh; /* if RSSI <= LowRSSIThresh => RATRState is DM_RATR_STA_LOW */
+ u8 RATRState; /* Current RSSI level, DM_RATR_STA_HIGH/DM_RATR_STA_MIDDLE/DM_RATR_STA_LOW */
+ u32 LastRATR; /* RATR Register Content */
+};
+
+#define IQK_MAC_REG_NUM 4
+#define IQK_ADDA_REG_NUM 16
+#define IQK_BB_REG_NUM_MAX 10
+#define IQK_BB_REG_NUM 9
+#define HP_THERMAL_NUM 8
+
+#define AVG_THERMAL_NUM 8
+#define IQK_Matrix_REG_NUM 8
+#define IQK_Matrix_Settings_NUM 1+24+21
+
+#define DM_Type_ByFWi 0
+#define DM_Type_ByDriver 1
+
+/* Declare for common info */
+
+struct odm_phy_status_info {
+ u8 RxPWDBAll;
+ u8 SignalQuality; /* in 0-100 index. */
+ u8 RxMIMOSignalQuality[MAX_PATH_NUM_92CS]; /* EVM */
+ u8 RxMIMOSignalStrength[MAX_PATH_NUM_92CS];/* in 0~100 index */
+ s8 RxPower; /* in dBm Translate from PWdB */
+ s8 RecvSignalPower;/* Real power in dBm for this packet, no
+ * beautification and aggregation. Keep this raw
+ * info to be used for the other procedures.
+ */
+ u8 BTRxRSSIPercentage;
+ u8 SignalStrength; /* in 0-100 index. */
+ u8 RxPwr[MAX_PATH_NUM_92CS];/* per-path's pwdb */
+ u8 RxSNR[MAX_PATH_NUM_92CS];/* per-path's SNR */
+};
+
+struct odm_phy_dbg_info {
+ /* ODM Write,debug info */
+ s8 RxSNRdB[MAX_PATH_NUM_92CS];
+ u64 NumQryPhyStatus;
+ u64 NumQryPhyStatusCCK;
+ u64 NumQryPhyStatusOFDM;
+ /* Others */
+ s32 RxEVM[MAX_PATH_NUM_92CS];
+};
+
+struct odm_per_pkt_info {
+ s8 Rate;
+ u8 StationID;
+ bool bPacketMatchBSSID;
+ bool bPacketToSelf;
+ bool bPacketBeacon;
+};
+
+struct odm_mac_status_info {
+ u8 test;
+};
+
+enum odm_ability {
+ /* BB Team */
+ ODM_DIG = 0x00000001,
+ ODM_HIGH_POWER = 0x00000002,
+ ODM_CCK_CCA_TH = 0x00000004,
+ ODM_FA_STATISTICS = 0x00000008,
+ ODM_RAMASK = 0x00000010,
+ ODM_RSSI_MONITOR = 0x00000020,
+ ODM_SW_ANTDIV = 0x00000040,
+ ODM_HW_ANTDIV = 0x00000080,
+ ODM_BB_PWRSV = 0x00000100,
+ ODM_2TPATHDIV = 0x00000200,
+ ODM_1TPATHDIV = 0x00000400,
+ ODM_PSD2AFH = 0x00000800
+};
+
+/* 2011/10/20 MH Define Common info enum for all team. */
+
+enum odm_common_info_def {
+ /* Fixed value: */
+
+ /* HOOK BEFORE REG INIT----------- */
+ ODM_CMNINFO_PLATFORM = 0,
+ ODM_CMNINFO_ABILITY, /* ODM_ABILITY_E */
+ ODM_CMNINFO_INTERFACE, /* ODM_INTERFACE_E */
+ ODM_CMNINFO_MP_TEST_CHIP,
+ ODM_CMNINFO_IC_TYPE, /* ODM_IC_TYPE_E */
+ ODM_CMNINFO_CUT_VER, /* ODM_CUT_VERSION_E */
+ ODM_CMNINFO_RF_TYPE, /* ODM_RF_PATH_E or ODM_RF_TYPE_E? */
+ ODM_CMNINFO_BOARD_TYPE, /* ODM_BOARD_TYPE_E */
+ ODM_CMNINFO_EXT_LNA, /* true */
+ ODM_CMNINFO_EXT_PA,
+ ODM_CMNINFO_EXT_TRSW,
+ ODM_CMNINFO_PATCH_ID, /* CUSTOMER ID */
+ ODM_CMNINFO_BINHCT_TEST,
+ ODM_CMNINFO_BWIFI_TEST,
+ ODM_CMNINFO_SMART_CONCURRENT,
+ /* HOOK BEFORE REG INIT----------- */
+
+ /* Dynamic value: */
+/* POINTER REFERENCE----------- */
+ ODM_CMNINFO_MAC_PHY_MODE, /* ODM_MAC_PHY_MODE_E */
+ ODM_CMNINFO_TX_UNI,
+ ODM_CMNINFO_RX_UNI,
+ ODM_CMNINFO_WM_MODE, /* ODM_WIRELESS_MODE_E */
+ ODM_CMNINFO_BAND, /* ODM_BAND_TYPE_E */
+ ODM_CMNINFO_SEC_CHNL_OFFSET, /* ODM_SEC_CHNL_OFFSET_E */
+ ODM_CMNINFO_SEC_MODE, /* ODM_SECURITY_E */
+ ODM_CMNINFO_BW, /* ODM_BW_E */
+ ODM_CMNINFO_CHNL,
+
+ ODM_CMNINFO_DMSP_GET_VALUE,
+ ODM_CMNINFO_BUDDY_ADAPTOR,
+ ODM_CMNINFO_DMSP_IS_MASTER,
+ ODM_CMNINFO_SCAN,
+ ODM_CMNINFO_POWER_SAVING,
+ ODM_CMNINFO_ONE_PATH_CCA, /* ODM_CCA_PATH_E */
+ ODM_CMNINFO_DRV_STOP,
+ ODM_CMNINFO_PNP_IN,
+ ODM_CMNINFO_INIT_ON,
+ ODM_CMNINFO_ANT_TEST,
+ ODM_CMNINFO_NET_CLOSED,
+ ODM_CMNINFO_MP_MODE,
+/* POINTER REFERENCE----------- */
+
+/* CALL BY VALUE------------- */
+ ODM_CMNINFO_WIFI_DIRECT,
+ ODM_CMNINFO_WIFI_DISPLAY,
+ ODM_CMNINFO_LINK,
+ ODM_CMNINFO_RSSI_MIN,
+ ODM_CMNINFO_DBG_COMP, /* u64 */
+ ODM_CMNINFO_DBG_LEVEL, /* u32 */
+ ODM_CMNINFO_RA_THRESHOLD_HIGH, /* u8 */
+ ODM_CMNINFO_RA_THRESHOLD_LOW, /* u8 */
+ ODM_CMNINFO_RF_ANTENNA_TYPE, /* u8 */
+ ODM_CMNINFO_BT_DISABLED,
+ ODM_CMNINFO_BT_OPERATION,
+ ODM_CMNINFO_BT_DIG,
+ ODM_CMNINFO_BT_BUSY, /* Check Bt is using or not */
+ ODM_CMNINFO_BT_DISABLE_EDCA,
+/* CALL BY VALUE-------------*/
+
+ /* Dynamic ptr array hook itms. */
+ ODM_CMNINFO_STA_STATUS,
+ ODM_CMNINFO_PHY_STATUS,
+ ODM_CMNINFO_MAC_STATUS,
+ ODM_CMNINFO_MAX,
+};
+
+/* 2011/10/20 MH Define ODM support ability. ODM_CMNINFO_ABILITY */
+
+enum odm_ability_def {
+ /* BB ODM section BIT 0-15 */
+ ODM_BB_DIG = BIT(0),
+ ODM_BB_RA_MASK = BIT(1),
+ ODM_BB_DYNAMIC_TXPWR = BIT(2),
+ ODM_BB_FA_CNT = BIT(3),
+ ODM_BB_RSSI_MONITOR = BIT(4),
+ ODM_BB_CCK_PD = BIT(5),
+ ODM_BB_ANT_DIV = BIT(6),
+ ODM_BB_PWR_SAVE = BIT(7),
+ ODM_BB_PWR_TRA = BIT(8),
+ ODM_BB_RATE_ADAPTIVE = BIT(9),
+ ODM_BB_PATH_DIV = BIT(10),
+ ODM_BB_PSD = BIT(11),
+ ODM_BB_RXHP = BIT(12),
+
+ /* MAC DM section BIT 16-23 */
+ ODM_MAC_EDCA_TURBO = BIT(16),
+ ODM_MAC_EARLY_MODE = BIT(17),
+
+ /* RF ODM section BIT 24-31 */
+ ODM_RF_TX_PWR_TRACK = BIT(24),
+ ODM_RF_RX_GAIN_TRACK = BIT(25),
+ ODM_RF_CALIBRATION = BIT(26),
+};
+
+#define ODM_RTL8188E BIT(4)
+
+/* ODM_CMNINFO_CUT_VER */
+enum odm_cut_version {
+ ODM_CUT_A = 1,
+ ODM_CUT_B = 2,
+ ODM_CUT_C = 3,
+ ODM_CUT_D = 4,
+ ODM_CUT_E = 5,
+ ODM_CUT_F = 6,
+ ODM_CUT_TEST = 7,
+};
+
+/* ODM_CMNINFO_RF_TYPE */
+/* For example 1T2R (A+AB = BIT0|BIT4|BIT5) */
+enum odm_rf_path {
+ ODM_RF_TX_A = BIT(0),
+ ODM_RF_TX_B = BIT(1),
+ ODM_RF_TX_C = BIT(2),
+ ODM_RF_TX_D = BIT(3),
+ ODM_RF_RX_A = BIT(4),
+ ODM_RF_RX_B = BIT(5),
+ ODM_RF_RX_C = BIT(6),
+ ODM_RF_RX_D = BIT(7),
+};
+
+enum odm_rf_type {
+ ODM_1T1R = 0,
+ ODM_1T2R = 1,
+ ODM_2T2R = 2,
+ ODM_2T3R = 3,
+ ODM_2T4R = 4,
+ ODM_3T3R = 5,
+ ODM_3T4R = 6,
+ ODM_4T4R = 7,
+};
+
+/* ODM Dynamic common info value definition */
+
+enum odm_mac_phy_mode {
+ ODM_SMSP = 0,
+ ODM_DMSP = 1,
+ ODM_DMDP = 2,
+};
+
+enum odm_bt_coexist {
+ ODM_BT_BUSY = 1,
+ ODM_BT_ON = 2,
+ ODM_BT_OFF = 3,
+ ODM_BT_NONE = 4,
+};
+
+/* ODM_CMNINFO_OP_MODE */
+enum odm_operation_mode {
+ ODM_NO_LINK = BIT(0),
+ ODM_LINK = BIT(1),
+ ODM_SCAN = BIT(2),
+ ODM_POWERSAVE = BIT(3),
+ ODM_AP_MODE = BIT(4),
+ ODM_CLIENT_MODE = BIT(5),
+ ODM_AD_HOC = BIT(6),
+ ODM_WIFI_DIRECT = BIT(7),
+ ODM_WIFI_DISPLAY = BIT(8),
+};
+
+/* ODM_CMNINFO_WM_MODE */
+enum odm_wireless_mode {
+ ODM_WM_UNKNOWN = 0x0,
+ ODM_WM_B = BIT(0),
+ ODM_WM_G = BIT(1),
+ ODM_WM_A = BIT(2),
+ ODM_WM_N24G = BIT(3),
+ ODM_WM_N5G = BIT(4),
+ ODM_WM_AUTO = BIT(5),
+ ODM_WM_AC = BIT(6),
+};
+
+/* ODM_CMNINFO_BAND */
+enum odm_band_type {
+ ODM_BAND_2_4G = BIT(0),
+ ODM_BAND_5G = BIT(1),
+};
+
+/* ODM_CMNINFO_SEC_CHNL_OFFSET */
+enum odm_sec_chnl_offset {
+ ODM_DONT_CARE = 0,
+ ODM_BELOW = 1,
+ ODM_ABOVE = 2
+};
+
+/* ODM_CMNINFO_SEC_MODE */
+enum odm_security {
+ ODM_SEC_OPEN = 0,
+ ODM_SEC_WEP40 = 1,
+ ODM_SEC_TKIP = 2,
+ ODM_SEC_RESERVE = 3,
+ ODM_SEC_AESCCMP = 4,
+ ODM_SEC_WEP104 = 5,
+ ODM_WEP_WPA_MIXED = 6, /* WEP + WPA */
+ ODM_SEC_SMS4 = 7,
+};
+
+/* ODM_CMNINFO_BW */
+enum odm_bw {
+ ODM_BW20M = 0,
+ ODM_BW40M = 1,
+ ODM_BW80M = 2,
+ ODM_BW160M = 3,
+ ODM_BW10M = 4,
+};
+
+/* ODM_CMNINFO_BOARD_TYPE */
+enum odm_board_type {
+ ODM_BOARD_NORMAL = 0,
+ ODM_BOARD_HIGHPWR = 1,
+ ODM_BOARD_MINICARD = 2,
+ ODM_BOARD_SLIM = 3,
+ ODM_BOARD_COMBO = 4,
+};
+
+/* ODM_CMNINFO_ONE_PATH_CCA */
+enum odm_cca_path {
+ ODM_CCA_2R = 0,
+ ODM_CCA_1R_A = 1,
+ ODM_CCA_1R_B = 2,
+};
+
+struct odm_ra_info {
+ u8 RateID;
+ u32 RateMask;
+ u32 RAUseRate;
+ u8 RateSGI;
+ u8 RssiStaRA;
+ u8 PreRssiStaRA;
+ u8 SGIEnable;
+ u8 DecisionRate;
+ u8 PreRate;
+ u8 HighestRate;
+ u8 LowestRate;
+ u32 NscUp;
+ u32 NscDown;
+ u16 RTY[5];
+ u32 TOTAL;
+ u16 DROP;
+ u8 Active;
+ u16 RptTime;
+ u8 RAWaitingCounter;
+ u8 RAPendingCounter;
+ u8 PTActive; /* on or off */
+ u8 PTTryState; /* 0 trying state, 1 for decision state */
+ u8 PTStage; /* 0~6 */
+ u8 PTStopCount; /* Stop PT counter */
+ u8 PTPreRate; /* if rate change do PT */
+ u8 PTPreRssi; /* if RSSI change 5% do PT */
+ u8 PTModeSS; /* decide whitch rate should do PT */
+ u8 RAstage; /* StageRA, decide how many times RA will be done
+ * between PT
+ */
+ u8 PTSmoothFactor;
+};
+
+struct ijk_matrix_regs_set {
+ bool bIQKDone;
+ s32 Value[1][IQK_Matrix_REG_NUM];
+};
+
+struct odm_rf_cal {
+ /* for tx power tracking */
+ u32 RegA24; /* for TempCCK */
+ s32 RegE94;
+ s32 RegE9C;
+ s32 RegEB4;
+ s32 RegEBC;
+
+ u8 TXPowercount;
+ bool bTXPowerTracking;
+ u8 TxPowerTrackControl; /* for mp mode, turn off txpwrtracking
+ * as default
+ */
+ u8 TM_Trigger;
+ u8 InternalPA5G[2]; /* pathA / pathB */
+
+ u8 ThermalMeter[2]; /* ThermalMeter, index 0 for RFIC0,
+ * and 1 for RFIC1
+ */
+ u8 ThermalValue;
+ u8 ThermalValue_LCK;
+ u8 ThermalValue_IQK;
+ u8 ThermalValue_DPK;
+ u8 ThermalValue_AVG[AVG_THERMAL_NUM];
+ u8 ThermalValue_AVG_index;
+ u8 ThermalValue_RxGain;
+ u8 ThermalValue_Crystal;
+ u8 ThermalValue_DPKstore;
+ u8 ThermalValue_DPKtrack;
+ bool TxPowerTrackingInProgress;
+ bool bDPKenable;
+
+ bool bReloadtxpowerindex;
+ u8 bRfPiEnable;
+ u32 TXPowerTrackingCallbackCnt; /* cosa add for debug */
+
+ u8 bCCKinCH14;
+ u8 CCK_index;
+ u8 OFDM_index[2];
+ bool bDoneTxpower;
+
+ u8 ThermalValue_HP[HP_THERMAL_NUM];
+ u8 ThermalValue_HP_index;
+ struct ijk_matrix_regs_set IQKMatrixRegSetting[IQK_Matrix_Settings_NUM];
+
+ u8 Delta_IQK;
+ u8 Delta_LCK;
+
+ /* for IQK */
+ u32 RegC04;
+ u32 Reg874;
+ u32 RegC08;
+ u32 RegB68;
+ u32 RegB6C;
+ u32 Reg870;
+ u32 Reg860;
+ u32 Reg864;
+
+ bool bIQKInitialized;
+ bool bLCKInProgress;
+ bool bAntennaDetected;
+ u32 ADDA_backup[IQK_ADDA_REG_NUM];
+ u32 IQK_MAC_backup[IQK_MAC_REG_NUM];
+ u32 IQK_BB_backup_recover[9];
+ u32 IQK_BB_backup[IQK_BB_REG_NUM];
+
+ /* for APK */
+ u32 APKoutput[2][2]; /* path A/B; output1_1a/output1_2a */
+ u8 bAPKdone;
+ u8 bAPKThermalMeterIgnore;
+ u8 bDPdone;
+ u8 bDPPathAOK;
+ u8 bDPPathBOK;
+};
+
+/* ODM Dynamic common info value definition */
+
+struct fast_ant_train {
+ u8 Bssid[6];
+ u8 antsel_rx_keep_0;
+ u8 antsel_rx_keep_1;
+ u8 antsel_rx_keep_2;
+ u32 antSumRSSI[7];
+ u32 antRSSIcnt[7];
+ u32 antAveRSSI[7];
+ u8 FAT_State;
+ u32 TrainIdx;
+ u8 antsel_a[ODM_ASSOCIATE_ENTRY_NUM];
+ u8 antsel_b[ODM_ASSOCIATE_ENTRY_NUM];
+ u8 antsel_c[ODM_ASSOCIATE_ENTRY_NUM];
+ u32 MainAnt_Sum[ODM_ASSOCIATE_ENTRY_NUM];
+ u32 AuxAnt_Sum[ODM_ASSOCIATE_ENTRY_NUM];
+ u32 MainAnt_Cnt[ODM_ASSOCIATE_ENTRY_NUM];
+ u32 AuxAnt_Cnt[ODM_ASSOCIATE_ENTRY_NUM];
+ u8 RxIdleAnt;
+ bool bBecomeLinked;
+};
+
+enum fat_state {
+ FAT_NORMAL_STATE = 0,
+ FAT_TRAINING_STATE = 1,
+};
+
+enum ant_div_type {
+ NO_ANTDIV = 0xFF,
+ CG_TRX_HW_ANTDIV = 0x01,
+ CGCS_RX_HW_ANTDIV = 0x02,
+ FIXED_HW_ANTDIV = 0x03,
+ CG_TRX_SMART_ANTDIV = 0x04,
+ CGCS_RX_SW_ANTDIV = 0x05,
+};
+
+/* Copy from SD4 defined structure. We use to support PHY DM integration. */
+struct odm_dm_struct {
+ /* Add for different team use temporarily */
+ struct adapter *Adapter; /* For CE/NIC team */
+ struct rtl8192cd_priv *priv; /* For AP/ADSL team */
+ /* WHen you use above pointers, they must be initialized. */
+ bool odm_ready;
+
+ struct rtl8192cd_priv *fake_priv;
+ u64 DebugComponents;
+ u32 DebugLevel;
+
+/* ODM HANDLE, DRIVER NEEDS NOT TO HOOK------ */
+ bool bCckHighPower;
+ u8 RFPathRxEnable; /* ODM_CMNINFO_RFPATH_ENABLE */
+ u8 ControlChannel;
+/* ODM HANDLE, DRIVER NEEDS NOT TO HOOK------ */
+
+/* 1 COMMON INFORMATION */
+ /* Init Value */
+/* HOOK BEFORE REG INIT----------- */
+ /* ODM Platform info AP/ADSL/CE/MP = 1/2/3/4 */
+ u8 SupportPlatform;
+ /* ODM Support Ability DIG/RATR/TX_PWR_TRACK/... = 1/2/3/... */
+ u32 SupportAbility;
+ /* ODM PCIE/USB/SDIO/GSPI = 0/1/2/3 */
+ u8 SupportInterface;
+ /* ODM composite or independent. Bit oriented/ 92C+92D+ .... or any
+ * other type = 1/2/3/...
+ */
+ u32 SupportICType;
+ /* Cut Version TestChip/A-cut/B-cut... = 0/1/2/3/... */
+ u8 CutVersion;
+ /* Board Type Normal/HighPower/MiniCard/SLIM/Combo/. = 0/1/2/3/4/. */
+ u8 BoardType;
+ /* with external LNA NO/Yes = 0/1 */
+ u8 ExtLNA;
+ /* with external PA NO/Yes = 0/1 */
+ u8 ExtPA;
+ /* with external TRSW NO/Yes = 0/1 */
+ u8 ExtTRSW;
+ u8 PatchID; /* Customer ID */
+ bool bInHctTest;
+ bool bWIFITest;
+
+ bool bDualMacSmartConcurrent;
+ u32 BK_SupportAbility;
+ u8 AntDivType;
+/* HOOK BEFORE REG INIT----------- */
+
+ /* Dynamic Value */
+/* POINTER REFERENCE----------- */
+
+ u8 u8_temp;
+ bool bool_temp;
+ struct adapter *adapter_temp;
+
+ /* MAC PHY Mode SMSP/DMSP/DMDP = 0/1/2 */
+ u8 *pMacPhyMode;
+ /* TX Unicast byte count */
+ u64 *pNumTxBytesUnicast;
+ /* RX Unicast byte count */
+ u64 *pNumRxBytesUnicast;
+ /* Wireless mode B/G/A/N = BIT0/BIT1/BIT2/BIT3 */
+ u8 *pWirelessMode; /* ODM_WIRELESS_MODE_E */
+ /* Frequence band 2.4G/5G = 0/1 */
+ u8 *pBandType;
+ /* Secondary channel offset don't_care/below/above = 0/1/2 */
+ u8 *pSecChOffset;
+ /* Security mode Open/WEP/AES/TKIP = 0/1/2/3 */
+ u8 *pSecurity;
+ /* BW info 20M/40M/80M = 0/1/2 */
+ u8 *pBandWidth;
+ /* Central channel location Ch1/Ch2/.... */
+ u8 *pChannel; /* central channel number */
+ /* Common info for 92D DMSP */
+
+ bool *pbGetValueFromOtherMac;
+ struct adapter **pBuddyAdapter;
+ bool *pbMasterOfDMSP; /* MAC0: master, MAC1: slave */
+ /* Common info for Status */
+ bool *pbScanInProcess;
+ bool *pbPowerSaving;
+ /* CCA Path 2-path/path-A/path-B = 0/1/2; using ODM_CCA_PATH_E. */
+ u8 *pOnePathCCA;
+ /* pMgntInfo->AntennaTest */
+ u8 *pAntennaTest;
+ bool *pbNet_closed;
+/* POINTER REFERENCE----------- */
+ /* */
+/* CALL BY VALUE------------- */
+ bool bWIFI_Direct;
+ bool bWIFI_Display;
+ bool bLinked;
+ u8 RSSI_Min;
+ u8 InterfaceIndex; /* Add for 92D dual MAC: 0--Mac0 1--Mac1 */
+ bool bIsMPChip;
+ bool bOneEntryOnly;
+ /* Common info for BTDM */
+ bool bBtDisabled; /* BT is disabled */
+ bool bBtHsOperation; /* BT HS mode is under progress */
+ u8 btHsDigVal; /* use BT rssi to decide the DIG value */
+ bool bBtDisableEdcaTurbo;/* Under some condition, don't enable the
+ * EDCA Turbo
+ */
+ bool bBtBusy; /* BT is busy. */
+/* CALL BY VALUE------------- */
+
+ /* 2 Define STA info. */
+ /* _ODM_STA_INFO */
+ /* For MP, we need to reduce one array pointer for default port.??*/
+ struct sta_info *pODM_StaInfo[ODM_ASSOCIATE_ENTRY_NUM];
+
+ u16 CurrminRptTime;
+ struct odm_ra_info RAInfo[ODM_ASSOCIATE_ENTRY_NUM]; /* Use MacID as
+ * array index. STA MacID=0,
+ * VWiFi Client MacID={1, ODM_ASSOCIATE_ENTRY_NUM-1}
+ */
+ /* */
+ /* 2012/02/14 MH Add to share 88E ra with other SW team. */
+ /* We need to colelct all support abilit to a proper area. */
+ /* */
+ bool RaSupport88E;
+
+ /* Define ........... */
+
+ /* Latest packet phy info (ODM write) */
+ struct odm_phy_dbg_info PhyDbgInfo;
+
+ /* Latest packet phy info (ODM write) */
+ struct odm_mac_status_info *pMacInfo;
+
+ /* Different Team independt structure?? */
+
+ /* ODM Structure */
+ struct fast_ant_train DM_FatTable;
+ struct rtw_dig DM_DigTable;
+ struct rtl_ps DM_PSTable;
+ struct rx_hpc DM_RXHP_Table;
+ struct false_alarm_stats FalseAlmCnt;
+ struct false_alarm_stats FlaseAlmCntBuddyAdapter;
+ struct sw_ant_switch DM_SWAT_Table;
+ bool RSSI_test;
+
+ struct edca_turbo DM_EDCA_Table;
+ u32 WMMEDCA_BE;
+ /* Copy from SD4 structure */
+ /* */
+ /* ================================================== */
+ /* */
+
+ bool *pbDriverStopped;
+ bool *pbDriverIsGoingToPnpSetPowerSleep;
+ bool *pinit_adpt_in_progress;
+
+ /* PSD */
+ bool bUserAssignLevel;
+ struct timer_list PSDTimer;
+ u8 RSSI_BT; /* come from BT */
+ bool bPSDinProcess;
+ bool bDMInitialGainEnable;
+
+ /* for rate adaptive, in fact, 88c/92c fw will handle this */
+ u8 bUseRAMask;
+
+ struct odm_rate_adapt RateAdaptive;
+
+ struct odm_rf_cal RFCalibrateInfo;
+
+ /* TX power tracking */
+ u8 BbSwingIdxOfdm;
+ u8 BbSwingIdxOfdmCurrent;
+ u8 BbSwingIdxOfdmBase;
+ bool BbSwingFlagOfdm;
+ u8 BbSwingIdxCck;
+ u8 BbSwingIdxCckCurrent;
+ u8 BbSwingIdxCckBase;
+ bool BbSwingFlagCck;
+ u8 *mp_mode;
+ /* ODM system resource. */
+
+ /* ODM relative time. */
+ struct timer_list PathDivSwitchTimer;
+ /* 2011.09.27 add for Path Diversity */
+ struct timer_list CCKPathDiversityTimer;
+ struct timer_list FastAntTrainingTimer;
+}; /* DM_Dynamic_Mechanism_Structure */
+
+#define ODM_RF_PATH_MAX 3
+
+enum ODM_RF_CONTENT {
+ odm_radioa_txt = 0x1000,
+ odm_radiob_txt = 0x1001,
+ odm_radioc_txt = 0x1002,
+ odm_radiod_txt = 0x1003
+};
+
+/* Status code */
+enum rt_status {
+ RT_STATUS_SUCCESS,
+ RT_STATUS_FAILURE,
+ RT_STATUS_PENDING,
+ RT_STATUS_RESOURCE,
+ RT_STATUS_INVALID_CONTEXT,
+ RT_STATUS_INVALID_PARAMETER,
+ RT_STATUS_NOT_SUPPORT,
+ RT_STATUS_OS_API_FAILED,
+};
+
+/* 3=========================================================== */
+/* 3 DIG */
+/* 3=========================================================== */
+
+enum dm_dig_op {
+ RT_TYPE_THRESH_HIGH = 0,
+ RT_TYPE_THRESH_LOW = 1,
+ RT_TYPE_BACKOFF = 2,
+ RT_TYPE_RX_GAIN_MIN = 3,
+ RT_TYPE_RX_GAIN_MAX = 4,
+ RT_TYPE_ENABLE = 5,
+ RT_TYPE_DISABLE = 6,
+ DIG_OP_TYPE_MAX
+};
+
+#define DM_DIG_THRESH_HIGH 40
+#define DM_DIG_THRESH_LOW 35
+
+#define DM_SCAN_RSSI_TH 0x14 /* scan return issue for LC */
+
+
+#define DM_false_ALARM_THRESH_LOW 400
+#define DM_false_ALARM_THRESH_HIGH 1000
+
+#define DM_DIG_MAX_NIC 0x4e
+#define DM_DIG_MIN_NIC 0x1e /* 0x22/0x1c */
+
+#define DM_DIG_MAX_AP 0x32
+#define DM_DIG_MIN_AP 0x20
+
+#define DM_DIG_MAX_NIC_HP 0x46
+#define DM_DIG_MIN_NIC_HP 0x2e
+
+#define DM_DIG_MAX_AP_HP 0x42
+#define DM_DIG_MIN_AP_HP 0x30
+
+/* vivi 92c&92d has different definition, 20110504 */
+/* this is for 92c */
+#define DM_DIG_FA_TH0 0x200/* 0x20 */
+#define DM_DIG_FA_TH1 0x300/* 0x100 */
+#define DM_DIG_FA_TH2 0x400/* 0x200 */
+/* this is for 92d */
+#define DM_DIG_FA_TH0_92D 0x100
+#define DM_DIG_FA_TH1_92D 0x400
+#define DM_DIG_FA_TH2_92D 0x600
+
+#define DM_DIG_BACKOFF_MAX 12
+#define DM_DIG_BACKOFF_MIN -4
+#define DM_DIG_BACKOFF_DEFAULT 10
+
+/* 3=========================================================== */
+/* 3 AGC RX High Power Mode */
+/* 3=========================================================== */
+#define LNA_Low_Gain_1 0x64
+#define LNA_Low_Gain_2 0x5A
+#define LNA_Low_Gain_3 0x58
+
+#define FA_RXHP_TH1 5000
+#define FA_RXHP_TH2 1500
+#define FA_RXHP_TH3 800
+#define FA_RXHP_TH4 600
+#define FA_RXHP_TH5 500
+
+/* 3=========================================================== */
+/* 3 EDCA */
+/* 3=========================================================== */
+
+/* 3=========================================================== */
+/* 3 Dynamic Tx Power */
+/* 3=========================================================== */
+/* Dynamic Tx Power Control Threshold */
+#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74
+#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67
+#define TX_POWER_NEAR_FIELD_THRESH_AP 0x3F
+
+#define TxHighPwrLevel_Normal 0
+#define TxHighPwrLevel_Level1 1
+#define TxHighPwrLevel_Level2 2
+#define TxHighPwrLevel_BT1 3
+#define TxHighPwrLevel_BT2 4
+#define TxHighPwrLevel_15 5
+#define TxHighPwrLevel_35 6
+#define TxHighPwrLevel_50 7
+#define TxHighPwrLevel_70 8
+#define TxHighPwrLevel_100 9
+
+/* 3=========================================================== */
+/* 3 Rate Adaptive */
+/* 3=========================================================== */
+#define DM_RATR_STA_INIT 0
+#define DM_RATR_STA_HIGH 1
+#define DM_RATR_STA_MIDDLE 2
+#define DM_RATR_STA_LOW 3
+
+/* 3=========================================================== */
+/* 3 BB Power Save */
+/* 3=========================================================== */
+
+
+enum dm_1r_cca {
+ CCA_1R = 0,
+ CCA_2R = 1,
+ CCA_MAX = 2,
+};
+
+enum dm_rf {
+ RF_Save = 0,
+ RF_Normal = 1,
+ RF_MAX = 2,
+};
+
+/* 3=========================================================== */
+/* 3 Antenna Diversity */
+/* 3=========================================================== */
+enum dm_swas {
+ Antenna_A = 1,
+ Antenna_B = 2,
+ Antenna_MAX = 3,
+};
+
+/* Maximal number of antenna detection mechanism needs to perform. */
+#define MAX_ANTENNA_DETECTION_CNT 10
+
+/* Extern Global Variables. */
+#define OFDM_TABLE_SIZE_92C 37
+#define OFDM_TABLE_SIZE_92D 43
+#define CCK_TABLE_SIZE 33
+
+extern u32 OFDMSwingTable[OFDM_TABLE_SIZE_92D];
+extern u8 CCKSwingTable_Ch1_Ch13[CCK_TABLE_SIZE][8];
+extern u8 CCKSwingTable_Ch14[CCK_TABLE_SIZE][8];
+
+/* check Sta pointer valid or not */
+#define IS_STA_VALID(pSta) (pSta)
+/* 20100514 Joseph: Add definition for antenna switching test after link. */
+/* This indicates two different the steps. */
+/* In SWAW_STEP_PEAK, driver needs to switch antenna and listen to the
+ * signal on the air.
+ */
+/* In SWAW_STEP_DETERMINE, driver just compares the signal captured in
+ * SWAW_STEP_PEAK
+ */
+/* with original RSSI to determine if it is necessary to switch antenna. */
+#define SWAW_STEP_PEAK 0
+#define SWAW_STEP_DETERMINE 1
+
+#define dm_CheckTXPowerTracking ODM_TXPowerTrackingCheck
+#define dm_RF_Saving ODM_RF_Saving
+
+void ODM_RF_Saving(struct odm_dm_struct *pDM_Odm, u8 bForceInNormal);
+void ODM_TXPowerTrackingCheck(struct odm_dm_struct *pDM_Odm);
+void ODM_Write_CCK_CCA_Thres(struct odm_dm_struct *pDM_Odm, u8 CurCCK_CCAThres);
+bool ODM_RAStateCheck(struct odm_dm_struct *pDM_Odm, s32 RSSI,
+ bool bForceUpdate, u8 *pRATRState);
+u32 ConvertTo_dB(u32 Value);
+u32 ODM_Get_Rate_Bitmap(struct odm_dm_struct *pDM_Odm, u32 macid,
+ u32 ra_mask, u8 rssi_level);
+void ODM_CmnInfoInit(struct odm_dm_struct *pDM_Odm,
+ enum odm_common_info_def CmnInfo, u32 Value);
+void ODM_CmnInfoUpdate(struct odm_dm_struct *pDM_Odm, u32 CmnInfo, u64 Value);
+void ODM_CmnInfoHook(struct odm_dm_struct *pDM_Odm,
+ enum odm_common_info_def CmnInfo, void *pValue);
+void ODM_CmnInfoPtrArrayHook(struct odm_dm_struct *pDM_Odm,
+ enum odm_common_info_def CmnInfo,
+ u16 Index, void *pValue);
+void ODM_DMInit(struct odm_dm_struct *pDM_Odm);
+void ODM_DMWatchdog(struct odm_dm_struct *pDM_Odm);
+void ODM_Write_DIG(struct odm_dm_struct *pDM_Odm, u8 CurrentIGI);
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/odm_debug.h b/drivers/staging/rtl8188eu/include/odm_debug.h
new file mode 100644
index 0000000..7ab2483
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/odm_debug.h
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+
+#ifndef __ODM_DBG_H__
+#define __ODM_DBG_H__
+
+
+/* */
+/* Define the debug levels */
+/* */
+/* 1. DBG_TRACE and DBG_LOUD are used for normal cases. */
+/* They can help SW engineer to develop or trace states changed */
+/* and also help HW enginner to trace every operation to and from HW, */
+/* e.g IO, Tx, Rx. */
+/* */
+/* 2. DBG_WARNNING and DBG_SERIOUS are used for unusual or error cases, */
+/* which help us to debug SW or HW. */
+
+/* Never used in a call to ODM_RT_TRACE()! */
+#define ODM_DBG_OFF 1
+
+/* Fatal bug. */
+/* For example, Tx/Rx/IO locked up, OS hangs, memory access violation, */
+/* resource allocation failed, unexpected HW behavior, HW BUG and so on. */
+#define ODM_DBG_SERIOUS 2
+
+/* Abnormal, rare, or unexpected cases. */
+/* For example, IRP/Packet/OID canceled, device suprisely unremoved and so on. */
+#define ODM_DBG_WARNING 3
+
+/* Normal case with useful information about current SW or HW state. */
+/* For example, Tx/Rx descriptor to fill, Tx/Rx descr. completed status, */
+/* SW protocol state change, dynamic mechanism state change and so on. */
+/* */
+#define ODM_DBG_LOUD 4
+
+/* Normal case with detail execution flow or information. */
+#define ODM_DBG_TRACE 5
+
+/* Define the tracing components */
+/* BB Functions */
+#define ODM_COMP_DIG BIT(0)
+#define ODM_COMP_RA_MASK BIT(1)
+#define ODM_COMP_DYNAMIC_TXPWR BIT(2)
+#define ODM_COMP_FA_CNT BIT(3)
+#define ODM_COMP_RSSI_MONITOR BIT(4)
+#define ODM_COMP_CCK_PD BIT(5)
+#define ODM_COMP_ANT_DIV BIT(6)
+#define ODM_COMP_PWR_SAVE BIT(7)
+#define ODM_COMP_PWR_TRA BIT(8)
+#define ODM_COMP_RATE_ADAPTIVE BIT(9)
+#define ODM_COMP_PATH_DIV BIT(10)
+#define ODM_COMP_PSD BIT(11)
+#define ODM_COMP_DYNAMIC_PRICCA BIT(12)
+#define ODM_COMP_RXHP BIT(13)
+/* MAC Functions */
+#define ODM_COMP_EDCA_TURBO BIT(16)
+#define ODM_COMP_EARLY_MODE BIT(17)
+/* RF Functions */
+#define ODM_COMP_TX_PWR_TRACK BIT(24)
+#define ODM_COMP_RX_GAIN_TRACK BIT(25)
+#define ODM_COMP_CALIBRATION BIT(26)
+/* Common Functions */
+#define ODM_COMP_COMMON BIT(30)
+#define ODM_COMP_INIT BIT(31)
+
+/*------------------------Export Marco Definition---------------------------*/
+#define RT_PRINTK(fmt, args...) \
+ pr_info("%s(): " fmt, __func__, ## args);
+
+#ifndef ASSERT
+ #define ASSERT(expr)
+#endif
+
+#define ODM_RT_TRACE(pDM_Odm, comp, level, fmt) \
+ if (((comp) & pDM_Odm->DebugComponents) && \
+ (level <= pDM_Odm->DebugLevel)) { \
+ pr_info("[ODM-8188E] "); \
+ RT_PRINTK fmt; \
+ }
+
+#define ODM_RT_ASSERT(pDM_Odm, expr, fmt) \
+ if (!(expr)) { \
+ pr_info("Assertion failed! %s at ......\n", #expr); \
+ pr_info(" ......%s,%s,line=%d\n", __FILE__, \
+ __func__, __LINE__); \
+ RT_PRINTK fmt; \
+ ASSERT(false); \
+ }
+
+void ODM_InitDebugSetting(struct odm_dm_struct *pDM_Odm);
+
+#endif /* __ODM_DBG_H__ */
diff --git a/drivers/staging/rtl8188eu/include/odm_hwconfig.h b/drivers/staging/rtl8188eu/include/odm_hwconfig.h
new file mode 100644
index 0000000..2cd8a47
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/odm_hwconfig.h
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#ifndef __HALHWOUTSRC_H__
+#define __HALHWOUTSRC_H__
+
+/* Definition */
+/* CCK Rates, TxHT = 0 */
+#define DESC92C_RATE1M 0x00
+#define DESC92C_RATE2M 0x01
+#define DESC92C_RATE5_5M 0x02
+#define DESC92C_RATE11M 0x03
+
+/* OFDM Rates, TxHT = 0 */
+#define DESC92C_RATE6M 0x04
+#define DESC92C_RATE9M 0x05
+#define DESC92C_RATE12M 0x06
+#define DESC92C_RATE18M 0x07
+#define DESC92C_RATE24M 0x08
+#define DESC92C_RATE36M 0x09
+#define DESC92C_RATE48M 0x0a
+#define DESC92C_RATE54M 0x0b
+
+/* MCS Rates, TxHT = 1 */
+#define DESC92C_RATEMCS0 0x0c
+#define DESC92C_RATEMCS1 0x0d
+#define DESC92C_RATEMCS2 0x0e
+#define DESC92C_RATEMCS3 0x0f
+#define DESC92C_RATEMCS4 0x10
+#define DESC92C_RATEMCS5 0x11
+#define DESC92C_RATEMCS6 0x12
+#define DESC92C_RATEMCS7 0x13
+#define DESC92C_RATEMCS8 0x14
+#define DESC92C_RATEMCS9 0x15
+#define DESC92C_RATEMCS10 0x16
+#define DESC92C_RATEMCS11 0x17
+#define DESC92C_RATEMCS12 0x18
+#define DESC92C_RATEMCS13 0x19
+#define DESC92C_RATEMCS14 0x1a
+#define DESC92C_RATEMCS15 0x1b
+#define DESC92C_RATEMCS15_SG 0x1c
+#define DESC92C_RATEMCS32 0x20
+
+/* structure and define */
+
+struct phy_rx_agc_info {
+ #ifdef __LITTLE_ENDIAN
+ u8 gain:7, trsw:1;
+ #else
+ u8 trsw:1, gain:7;
+ #endif
+};
+
+struct phy_status_rpt {
+ struct phy_rx_agc_info path_agc[RF_PATH_MAX];
+ u8 ch_corr[2];
+ u8 cck_sig_qual_ofdm_pwdb_all;
+ u8 cck_agc_rpt_ofdm_cfosho_a;
+ u8 cck_rpt_b_ofdm_cfosho_b;
+ u8 rsvd_1;/* ch_corr_msb; */
+ u8 noise_power_db_msb;
+ u8 path_cfotail[2];
+ u8 pcts_mask[2];
+ s8 stream_rxevm[2];
+ u8 path_rxsnr[3];
+ u8 noise_power_db_lsb;
+ u8 rsvd_2[3];
+ u8 stream_csi[2];
+ u8 stream_target_csi[2];
+ s8 sig_evm;
+ u8 rsvd_3;
+
+#ifdef __LITTLE_ENDIAN
+ u8 antsel_rx_keep_2:1; /* ex_intf_flg:1; */
+ u8 sgi_en:1;
+ u8 rxsc:2;
+ u8 idle_long:1;
+ u8 r_ant_train_en:1;
+ u8 ant_sel_b:1;
+ u8 ant_sel:1;
+#else /* _BIG_ENDIAN_ */
+ u8 ant_sel:1;
+ u8 ant_sel_b:1;
+ u8 r_ant_train_en:1;
+ u8 idle_long:1;
+ u8 rxsc:2;
+ u8 sgi_en:1;
+ u8 antsel_rx_keep_2:1; /* ex_intf_flg:1; */
+#endif
+};
+
+void ODM_PhyStatusQuery(struct odm_dm_struct *pDM_Odm,
+ struct odm_phy_status_info *pPhyInfo,
+ u8 *pPhyStatus,
+ struct odm_per_pkt_info *pPktinfo);
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/odm_precomp.h b/drivers/staging/rtl8188eu/include/odm_precomp.h
new file mode 100644
index 0000000..5254d87
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/odm_precomp.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#ifndef __ODM_PRECOMP_H__
+#define __ODM_PRECOMP_H__
+
+#include "odm_types.h"
+
+#define TEST_FALG___ 1
+
+/* 2 Config Flags and Structs - defined by each ODM Type */
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <hal_intf.h>
+#include <usb_ops_linux.h>
+
+/* 2 OutSrc Header Files */
+
+#include "odm.h"
+#include "odm_hwconfig.h"
+#include "odm_debug.h"
+#include "phydm_regdefine11n.h"
+
+#include "hal8188e_rate_adaptive.h" /* for RA,Power training */
+#include "rtl8188e_hal.h"
+
+#include "phydm_reg.h"
+
+#include "odm_rtl8188e.h"
+
+void odm_CmnInfoHook_Debug(struct odm_dm_struct *pDM_Odm);
+void odm_CmnInfoInit_Debug(struct odm_dm_struct *pDM_Odm);
+void odm_DIGInit(struct odm_dm_struct *pDM_Odm);
+void odm_RateAdaptiveMaskInit(struct odm_dm_struct *pDM_Odm);
+void odm_DynamicBBPowerSavingInit(struct odm_dm_struct *pDM_Odm);
+void odm_DynamicTxPowerInit(struct odm_dm_struct *pDM_Odm);
+void odm_TXPowerTrackingInit(struct odm_dm_struct *pDM_Odm);
+void ODM_EdcaTurboInit(struct odm_dm_struct *pDM_Odm);
+void odm_SwAntDivInit_NIC(struct odm_dm_struct *pDM_Odm);
+void odm_CmnInfoUpdate_Debug(struct odm_dm_struct *pDM_Odm);
+void odm_CommonInfoSelfUpdate(struct odm_dm_struct *pDM_Odm);
+void odm_FalseAlarmCounterStatistics(struct odm_dm_struct *pDM_Odm);
+void odm_DIG(struct odm_dm_struct *pDM_Odm);
+void odm_CCKPacketDetectionThresh(struct odm_dm_struct *pDM_Odm);
+void odm_RefreshRateAdaptiveMaskMP(struct odm_dm_struct *pDM_Odm);
+void odm_DynamicBBPowerSaving(struct odm_dm_struct *pDM_Odm);
+void odm_SwAntDivChkAntSwitch(struct odm_dm_struct *pDM_Odm, u8 Step);
+void odm_EdcaTurboCheck(struct odm_dm_struct *pDM_Odm);
+void odm_CommonInfoSelfInit(struct odm_dm_struct *pDM_Odm);
+void odm_RSSIMonitorCheck(struct odm_dm_struct *pDM_Odm);
+void odm_RefreshRateAdaptiveMask(struct odm_dm_struct *pDM_Odm);
+void odm_1R_CCA(struct odm_dm_struct *pDM_Odm);
+void odm_RefreshRateAdaptiveMaskCE(struct odm_dm_struct *pDM_Odm);
+void odm_RefreshRateAdaptiveMaskAPADSL(struct odm_dm_struct *pDM_Odm);
+void odm_DynamicTxPowerNIC(struct odm_dm_struct *pDM_Odm);
+void odm_RSSIMonitorCheckCE(struct odm_dm_struct *pDM_Odm);
+void odm_EdcaTurboCheckCE(struct odm_dm_struct *pDM_Odm);
+void odm_SwAntDivChkAntSwitchCallback(void *FunctionContext);
+void odm_InitHybridAntDiv(struct odm_dm_struct *pDM_Odm);
+void odm_HwAntDiv(struct odm_dm_struct *pDM_Odm);
+
+#endif /* __ODM_PRECOMP_H__ */
diff --git a/drivers/staging/rtl8188eu/include/odm_rtl8188e.h b/drivers/staging/rtl8188eu/include/odm_rtl8188e.h
new file mode 100644
index 0000000..dbf13c4
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/odm_rtl8188e.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __ODM_RTL8188E_H__
+#define __ODM_RTL8188E_H__
+
+#define MAIN_ANT 0
+#define AUX_ANT 1
+#define MAIN_ANT_CG_TRX 1
+#define AUX_ANT_CG_TRX 0
+#define MAIN_ANT_CGCS_RX 0
+#define AUX_ANT_CGCS_RX 1
+
+void ODM_DIG_LowerBound_88E(struct odm_dm_struct *pDM_Odm);
+
+void rtl88eu_dm_antenna_div_init(struct odm_dm_struct *dm_odm);
+
+void rtl88eu_dm_antenna_diversity(struct odm_dm_struct *dm_odm);
+
+void rtl88eu_dm_set_tx_ant_by_tx_info(struct odm_dm_struct *dm_odm, u8 *desc,
+ u8 mac_id);
+
+void rtl88eu_dm_update_rx_idle_ant(struct odm_dm_struct *dm_odm, u8 ant);
+
+void rtl88eu_dm_ant_sel_statistics(struct odm_dm_struct *dm_odm, u8 antsel_tr_mux,
+ u32 mac_id, u8 rx_pwdb_all);
+
+void odm_FastAntTraining(struct odm_dm_struct *pDM_Odm);
+
+void odm_FastAntTrainingCallback(struct odm_dm_struct *pDM_Odm);
+
+void odm_FastAntTrainingWorkItemCallback(struct odm_dm_struct *pDM_Odm);
+
+bool ODM_DynamicPrimaryCCA_DupRTS(struct odm_dm_struct *pDM_Odm);
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/odm_types.h b/drivers/staging/rtl8188eu/include/odm_types.h
new file mode 100644
index 0000000..7255f7a
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/odm_types.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __ODM_TYPES_H__
+#define __ODM_TYPES_H__
+
+#define ODM_CE 0x04 /* BIT2 */
+
+enum HAL_STATUS {
+ HAL_STATUS_SUCCESS,
+ HAL_STATUS_FAILURE,
+};
+
+#define SET_TX_DESC_ANTSEL_A_88E(__pTxDesc, __Value) \
+ SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 24, 1, __Value)
+#define SET_TX_DESC_ANTSEL_B_88E(__pTxDesc, __Value) \
+ SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 25, 1, __Value)
+#define SET_TX_DESC_ANTSEL_C_88E(__pTxDesc, __Value) \
+ SET_BITS_TO_LE_4BYTE(__pTxDesc+28, 29, 1, __Value)
+
+#endif /* __ODM_TYPES_H__ */
diff --git a/drivers/staging/rtl8188eu/include/osdep_intf.h b/drivers/staging/rtl8188eu/include/osdep_intf.h
new file mode 100644
index 0000000..07c3276
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/osdep_intf.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#ifndef __OSDEP_INTF_H_
+#define __OSDEP_INTF_H_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+
+extern char *rtw_initmac;
+extern int rtw_mc2u_disable;
+
+u8 rtw_init_drv_sw(struct adapter *padapter);
+u8 rtw_free_drv_sw(struct adapter *padapter);
+u8 rtw_reset_drv_sw(struct adapter *padapter);
+
+void rtw_stop_drv_threads(struct adapter *padapter);
+void rtw_cancel_all_timer(struct adapter *padapter);
+
+int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+
+int rtw_init_netdev_name(struct net_device *pnetdev, const char *ifname);
+struct net_device *rtw_init_netdev(struct adapter *padapter);
+u16 rtw_recv_select_queue(struct sk_buff *skb);
+
+int netdev_open(struct net_device *pnetdev);
+int ips_netdrv_open(struct adapter *padapter);
+void rtw_ips_dev_unload(struct adapter *padapter);
+int rtw_ips_pwr_up(struct adapter *padapter);
+void rtw_ips_pwr_down(struct adapter *padapter);
+
+#endif /* _OSDEP_INTF_H_ */
diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h
new file mode 100644
index 0000000..c0114ad
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/osdep_service.h
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __OSDEP_SERVICE_H_
+#define __OSDEP_SERVICE_H_
+
+#include <basic_types.h>
+
+#define _FAIL 0
+#define _SUCCESS 1
+#define RTW_RX_HANDLED 2
+
+#include <linux/spinlock.h>
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/circ_buf.h>
+#include <linux/uaccess.h>
+#include <asm/byteorder.h>
+#include <linux/atomic.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/sem.h>
+#include <linux/sched/signal.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+#include <linux/if_arp.h>
+#include <linux/rtnetlink.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h> /* for struct tasklet_struct */
+#include <linux/ip.h>
+#include <linux/kthread.h>
+
+#include <linux/usb.h>
+#include <linux/usb/ch9.h>
+
+struct __queue {
+ struct list_head queue;
+ spinlock_t lock;
+};
+
+static inline struct list_head *get_list_head(struct __queue *queue)
+{
+ return &(queue->queue);
+}
+
+static inline int rtw_netif_queue_stopped(struct net_device *pnetdev)
+{
+ return netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 0)) &&
+ netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 1)) &&
+ netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 2)) &&
+ netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 3));
+}
+
+u8 *_rtw_malloc(u32 sz);
+#define rtw_malloc(sz) _rtw_malloc((sz))
+
+void _rtw_init_queue(struct __queue *pqueue);
+
+struct rtw_netdev_priv_indicator {
+ void *priv;
+};
+struct net_device *rtw_alloc_etherdev_with_old_priv(void *old_priv);
+
+#define rtw_netdev_priv(netdev) \
+ (((struct rtw_netdev_priv_indicator *)netdev_priv(netdev))->priv)
+void rtw_free_netdev(struct net_device *netdev);
+
+#define FUNC_NDEV_FMT "%s(%s)"
+#define FUNC_NDEV_ARG(ndev) __func__, ndev->name
+#define FUNC_ADPT_FMT "%s(%s)"
+#define FUNC_ADPT_ARG(adapter) __func__, adapter->pnetdev->name
+
+/* Macros for handling unaligned memory accesses */
+
+#define RTW_GET_BE24(a) ((((u32)(a)[0]) << 16) | (((u32) (a)[1]) << 8) | \
+ ((u32)(a)[2]))
+
+void rtw_buf_free(u8 **buf, u32 *buf_len);
+void rtw_buf_update(u8 **buf, u32 *buf_len, u8 *src, u32 src_len);
+#endif
diff --git a/drivers/staging/rtl8188eu/include/phy.h b/drivers/staging/rtl8188eu/include/phy.h
new file mode 100644
index 0000000..40901d6
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/phy.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <odm.h>
+
+#define IQK_DELAY_TIME_88E 10
+#define index_mapping_NUM_88E 15
+#define AVG_THERMAL_NUM_88E 4
+
+bool rtl88eu_phy_mac_config(struct adapter *adapt);
+bool rtl88eu_phy_rf_config(struct adapter *adapt);
+bool rtl88eu_phy_bb_config(struct adapter *adapt);
+
+u32 phy_query_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask);
+void phy_set_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask, u32 data);
+u32 rtw_hal_read_rfreg(struct adapter *adapt, enum rf_radio_path rf_path,
+ u32 reg_addr, u32 bit_mask);
+void phy_set_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path,
+ u32 reg_addr, u32 bit_mask, u32 data);
+
+void phy_set_tx_power_level(struct adapter *adapt, u8 channel);
+
+void rtl88eu_dm_txpower_track_adjust(struct odm_dm_struct *dm_odm,
+ u8 type, u8 *dir, u32 *out_write);
+
+void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt);
+void rtl88eu_phy_iq_calibrate(struct adapter *adapter, bool recovery);
+void rtl88eu_phy_lc_calibrate(struct adapter *adapter);
diff --git a/drivers/staging/rtl8188eu/include/phydm_reg.h b/drivers/staging/rtl8188eu/include/phydm_reg.h
new file mode 100644
index 0000000..e3ae006
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/phydm_reg.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2016 Realtek Corporation.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+#ifndef __HAL_ODM_REG_H__
+#define __HAL_ODM_REG_H__
+
+#define ODM_EDCA_VO_PARAM 0x500
+#define ODM_EDCA_VI_PARAM 0x504
+#define ODM_EDCA_BE_PARAM 0x508
+#define ODM_EDCA_BK_PARAM 0x50C
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/phydm_regdefine11n.h b/drivers/staging/rtl8188eu/include/phydm_regdefine11n.h
new file mode 100644
index 0000000..5659968
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/phydm_regdefine11n.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2016 Realtek Corporation.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __ODM_REGDEFINE11N_H__
+#define __ODM_REGDEFINE11N_H__
+
+#define ODM_REG_TX_ANT_CTRL_11N 0x80C
+#define ODM_REG_RX_DEFAULT_A_11N 0x858
+#define ODM_REG_ANTSEL_CTRL_11N 0x860
+#define ODM_REG_RX_ANT_CTRL_11N 0x864
+#define ODM_REG_PIN_CTRL_11N 0x870
+#define ODM_REG_SC_CNT_11N 0x8C4
+
+#define ODM_REG_ANT_MAPPING1_11N 0x914
+
+#define ODM_REG_CCK_ANTDIV_PARA1_11N 0xA00
+#define ODM_REG_CCK_CCA_11N 0xA0A
+#define ODM_REG_CCK_ANTDIV_PARA2_11N 0xA0C
+#define ODM_REG_CCK_FA_RST_11N 0xA2C
+#define ODM_REG_CCK_FA_MSB_11N 0xA58
+#define ODM_REG_CCK_FA_LSB_11N 0xA5C
+#define ODM_REG_CCK_CCA_CNT_11N 0xA60
+#define ODM_REG_BB_PWR_SAV4_11N 0xA74
+
+#define ODM_REG_LNA_SWITCH_11N 0xB2C
+
+#define ODM_REG_OFDM_FA_HOLDC_11N 0xC00
+#define ODM_REG_IGI_A_11N 0xC50
+#define ODM_REG_ANTDIV_PARA1_11N 0xCA4
+#define ODM_REG_OFDM_FA_TYPE1_11N 0xCF0
+
+#define ODM_REG_OFDM_FA_RSTD_11N 0xD00
+#define ODM_REG_OFDM_FA_TYPE2_11N 0xDA0
+#define ODM_REG_OFDM_FA_TYPE3_11N 0xDA4
+#define ODM_REG_OFDM_FA_TYPE4_11N 0xDA8
+
+#define ODM_REG_ANTSEL_PIN_11N 0x4C
+#define ODM_REG_RESP_TX_11N 0x6D8
+
+#define ODM_BIT_IGI_11N 0x0000007F
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/pwrseq.h b/drivers/staging/rtl8188eu/include/pwrseq.h
new file mode 100644
index 0000000..aa58db5
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/pwrseq.h
@@ -0,0 +1,245 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#ifndef __HAL8188EPWRSEQ_H__
+#define __HAL8188EPWRSEQ_H__
+
+#include "pwrseqcmd.h"
+
+/*
+ * Check document WM-20110607-Paul-RTL8188E_Power_Architecture-R02.vsd
+ * There are 6 HW Power States:
+ * 0: POFF--Power Off
+ * 1: PDN--Power Down
+ * 2: CARDEMU--Card Emulation
+ * 3: ACT--Active Mode
+ * 4: LPS--Low Power State
+ * 5: SUS--Suspend
+ *
+ * The transition from different states are defined below
+ * TRANS_CARDEMU_TO_ACT
+ * TRANS_ACT_TO_CARDEMU
+ * TRANS_CARDEMU_TO_SUS
+ * TRANS_SUS_TO_CARDEMU
+ * TRANS_CARDEMU_TO_PDN
+ * TRANS_ACT_TO_LPS
+ * TRANS_LPS_TO_ACT
+ *
+ * TRANS_END
+ *
+ * PWR SEQ Version: rtl8188E_PwrSeq_V09.h
+ */
+#define RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS 10
+#define RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS 10
+#define RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS 10
+#define RTL8188E_TRANS_SUS_TO_CARDEMU_STEPS 10
+#define RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS 10
+#define RTL8188E_TRANS_PDN_TO_CARDEMU_STEPS 10
+#define RTL8188E_TRANS_ACT_TO_LPS_STEPS 15
+#define RTL8188E_TRANS_LPS_TO_ACT_STEPS 15
+#define RTL8188E_TRANS_END_STEPS 1
+
+
+#define RTL8188E_TRANS_CARDEMU_TO_ACT \
+ /* format
+ * { offset, cut_msk, cmd, msk, value
+ * },
+ * comment here
+ */ \
+ {0x0006, PWR_CUT_ALL_MSK, PWR_CMD_POLLING, BIT(1), BIT(1)}, \
+ /* wait till 0x04[17] = 1 power ready*/ \
+ {0x0002, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(0) | BIT(1), 0}, \
+ /* 0x02[1:0] = 0 reset BB*/ \
+ {0x0026, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(7), BIT(7)}, \
+ /*0x24[23] = 2b'01 schmit trigger */ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(7), 0}, \
+ /* 0x04[15] = 0 disable HWPDN (control by DRV)*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(4) | BIT(3), 0}, \
+ /*0x04[12:11] = 2b'00 disable WL suspend*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(0), BIT(0)}, \
+ /*0x04[8] = 1 polling until return 0*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_POLLING, BIT(0), 0}, \
+ /*wait till 0x04[8] = 0*/ \
+ {0x0023, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(4), 0}, \
+ /*LDO normal mode*/
+
+#define RTL8188E_TRANS_ACT_TO_CARDEMU \
+ /* format
+ * { offset, cut_msk, cmd, msk, value
+ * },
+ * comments here
+ */ \
+ {0x001F, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, 0xFF, 0}, \
+ /*0x1F[7:0] = 0 turn off RF*/ \
+ {0x0023, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(4), BIT(4)}, \
+ /*LDO Sleep mode*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(1), BIT(1)}, \
+ /*0x04[9] = 1 turn off MAC by HW state machine*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_POLLING, BIT(1), 0}, \
+ /*wait till 0x04[9] = 0 polling until return 0 to disable*/
+
+#define RTL8188E_TRANS_CARDEMU_TO_SUS \
+ /* format
+ * { offset, cut_msk, cmd, msk,
+ * value },
+ * comments here
+ */ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3)}, \
+ /* 0x04[12:11] = 2b'01enable WL suspend */ \
+ {0x0007, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, 0xFF, BIT(7)}, \
+ /* 0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */\
+ {0x0041, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(4), 0}, \
+ /*Clear SIC_EN register 0x40[12] = 1'b0 */ \
+ {0xfe10, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(4), BIT(4)}, \
+ /*Set USB suspend enable local register 0xfe10[4]=1 */
+
+#define RTL8188E_TRANS_SUS_TO_CARDEMU \
+ /* format
+ * { offset, cut_msk, cmd, msk,
+ * value },
+ * comments here
+ */ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(3) | BIT(4), 0}, \
+ /*0x04[12:11] = 2b'01enable WL suspend*/
+
+#define RTL8188E_TRANS_CARDEMU_TO_CARDDIS \
+ /* format
+ * { offset, cut_msk, cmd, msk,
+ * value },
+ * comments here
+ */ \
+ {0x0026, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(7), BIT(7)}, \
+ /*0x24[23] = 2b'01 schmit trigger */ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3)}, \
+ /*0x04[12:11] = 2b'01 enable WL suspend*/ \
+ {0x0007, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, 0xFF, 0}, \
+ /* 0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */\
+ {0x0041, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(4), 0}, \
+ /*Clear SIC_EN register 0x40[12] = 1'b0 */ \
+ {0xfe10, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(4), BIT(4)}, \
+ /*Set USB suspend enable local register 0xfe10[4]=1 */
+
+#define RTL8188E_TRANS_CARDDIS_TO_CARDEMU \
+ /* format
+ * { offset, cut_msk, cmd, msk,
+ * value },
+ * comments here
+ */ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(3) | BIT(4), 0}, \
+ /*0x04[12:11] = 2b'01enable WL suspend*/
+
+#define RTL8188E_TRANS_CARDEMU_TO_PDN \
+ /* format
+ * { offset, cut_msk, cmd, msk,
+ * value },
+ * comments here
+ */ \
+ {0x0006, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(0), 0}, \
+ /* 0x04[16] = 0*/ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(7), BIT(7)}, \
+ /* 0x04[15] = 1*/
+
+#define RTL8188E_TRANS_PDN_TO_CARDEMU \
+ /* format
+ * { offset, cut_msk, cmd, msk,
+ * value },
+ * comments here
+ */ \
+ {0x0005, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(7), 0}, \
+ /* 0x04[15] = 0*/
+
+/* This is used by driver for LPSRadioOff Procedure, not for FW LPS Step */
+#define RTL8188E_TRANS_ACT_TO_LPS \
+ /* format
+ * { offset, cut_msk, cmd, msk,
+ * value },
+ * comments here
+ */ \
+ {0x0522, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, 0xFF, 0x7F},/*Tx Pause*/ \
+ {0x05F8, PWR_CUT_ALL_MSK, PWR_CMD_POLLING, 0xFF, 0}, \
+ /*Should be zero if no packet is transmitting*/ \
+ {0x05F9, PWR_CUT_ALL_MSK, PWR_CMD_POLLING, 0xFF, 0}, \
+ /*Should be zero if no packet is transmitting*/ \
+ {0x05FA, PWR_CUT_ALL_MSK, PWR_CMD_POLLING, 0xFF, 0}, \
+ /*Should be zero if no packet is transmitting*/ \
+ {0x05FB, PWR_CUT_ALL_MSK, PWR_CMD_POLLING, 0xFF, 0}, \
+ /*Should be zero if no packet is transmitting*/ \
+ {0x0002, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(0), 0}, \
+ /*CCK and OFDM are disabled,and clock are gated*/ \
+ {0x0002, PWR_CUT_ALL_MSK, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US}, \
+ /*Delay 1us*/ \
+ {0x0100, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, 0xFF, 0x3F}, \
+ /*Reset MAC TRX*/ \
+ {0x0101, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(1), 0}, \
+ /*check if removed later*/\
+ {0x0553, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(5), BIT(5)}, \
+ /*Respond TxOK to scheduler*/
+
+
+#define RTL8188E_TRANS_LPS_TO_ACT \
+ /* format
+ * { offset, cut_msk, cmd, msk,
+ * value },
+ * comments here
+ */ \
+ {0xFE58, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, 0xFF, 0x84}, \
+ /*USB RPWM*/ \
+ {0x0002, PWR_CUT_ALL_MSK, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, \
+ /*Delay*/ \
+ {0x0008, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(4), 0}, \
+ /* 0x08[4] = 0 switch TSF to 40M */ \
+ {0x0109, PWR_CUT_ALL_MSK, PWR_CMD_POLLING, BIT(7), 0}, \
+ /* Polling 0x109[7]=0 TSF in 40M */ \
+ {0x0029, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(6) | BIT(7), 0}, \
+ /* 0x29[7:6] = 2b'00 enable BB clock */ \
+ {0x0101, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, BIT(1), BIT(1)}, \
+ /* 0x101[1] = 1 */ \
+ {0x0100, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, 0xFF, 0xFF}, \
+ /* 0x100[7:0] = 0xFF enable WMAC TRX */ \
+ {0x0002, PWR_CUT_ALL_MSK, \
+ PWR_CMD_WRITE, BIT(1) | BIT(0), BIT(1) | BIT(0)}, \
+ /* 0x02[1:0] = 2b'11 enable BB macro */ \
+ {0x0522, PWR_CUT_ALL_MSK, PWR_CMD_WRITE, 0xFF, 0}, /*. 0x522 = 0*/
+
+#define RTL8188E_TRANS_END \
+ /* format
+ * { offset, cut_msk, cmd, msk,
+ * value },
+ * comments here
+ */ \
+ {0xFFFF, PWR_CUT_ALL_MSK, PWR_CMD_END, 0, 0},
+
+
+extern struct wl_pwr_cfg rtl8188E_power_on_flow
+ [RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS + RTL8188E_TRANS_END_STEPS];
+extern struct wl_pwr_cfg rtl8188E_radio_off_flow
+ [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS + RTL8188E_TRANS_END_STEPS];
+extern struct wl_pwr_cfg rtl8188E_card_disable_flow
+ [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
+ RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS +
+ RTL8188E_TRANS_END_STEPS];
+extern struct wl_pwr_cfg rtl8188E_card_enable_flow
+ [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
+ RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS +
+ RTL8188E_TRANS_END_STEPS];
+extern struct wl_pwr_cfg rtl8188E_suspend_flow[
+ RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
+ RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS +
+ RTL8188E_TRANS_END_STEPS];
+extern struct wl_pwr_cfg rtl8188E_resume_flow
+ [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
+ RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS +
+ RTL8188E_TRANS_END_STEPS];
+extern struct wl_pwr_cfg rtl8188E_hwpdn_flow
+ [RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS +
+ RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS + RTL8188E_TRANS_END_STEPS];
+extern struct wl_pwr_cfg rtl8188E_enter_lps_flow
+ [RTL8188E_TRANS_ACT_TO_LPS_STEPS + RTL8188E_TRANS_END_STEPS];
+extern struct wl_pwr_cfg rtl8188E_leave_lps_flow
+ [RTL8188E_TRANS_LPS_TO_ACT_STEPS + RTL8188E_TRANS_END_STEPS];
+
+#endif /* __HAL8188EPWRSEQ_H__ */
diff --git a/drivers/staging/rtl8188eu/include/pwrseqcmd.h b/drivers/staging/rtl8188eu/include/pwrseqcmd.h
new file mode 100644
index 0000000..8c73322
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/pwrseqcmd.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __HALPWRSEQCMD_H__
+#define __HALPWRSEQCMD_H__
+
+#include <drv_types.h>
+
+/* The value of cmd: 4 bits */
+#define PWR_CMD_READ 0x00
+#define PWR_CMD_WRITE 0x01
+#define PWR_CMD_POLLING 0x02
+#define PWR_CMD_DELAY 0x03
+#define PWR_CMD_END 0x04
+
+/* The value of cut_msk: 8 bits */
+#define PWR_CUT_TESTCHIP_MSK BIT(0)
+#define PWR_CUT_A_MSK BIT(1)
+#define PWR_CUT_B_MSK BIT(2)
+#define PWR_CUT_C_MSK BIT(3)
+#define PWR_CUT_D_MSK BIT(4)
+#define PWR_CUT_E_MSK BIT(5)
+#define PWR_CUT_F_MSK BIT(6)
+#define PWR_CUT_G_MSK BIT(7)
+#define PWR_CUT_ALL_MSK 0xFF
+
+
+enum pwrseq_cmd_delat_unit {
+ PWRSEQ_DELAY_US,
+ PWRSEQ_DELAY_MS,
+};
+
+struct wl_pwr_cfg {
+ u16 offset;
+ u8 cut_msk;
+ u8 cmd:4;
+ u8 msk;
+ u8 value;
+};
+
+#define GET_PWR_CFG_OFFSET(__PWR_CMD) __PWR_CMD.offset
+#define GET_PWR_CFG_CUT_MASK(__PWR_CMD) __PWR_CMD.cut_msk
+#define GET_PWR_CFG_CMD(__PWR_CMD) __PWR_CMD.cmd
+#define GET_PWR_CFG_MASK(__PWR_CMD) __PWR_CMD.msk
+#define GET_PWR_CFG_VALUE(__PWR_CMD) __PWR_CMD.value
+
+u8 rtl88eu_pwrseqcmdparsing(struct adapter *padapter, u8 cut_vers,
+ struct wl_pwr_cfg pwrcfgCmd[]);
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/recv_osdep.h b/drivers/staging/rtl8188eu/include/recv_osdep.h
new file mode 100644
index 0000000..d234152
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/recv_osdep.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __RECV_OSDEP_H_
+#define __RECV_OSDEP_H_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+
+
+int _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter);
+void _rtw_free_recv_priv(struct recv_priv *precvpriv);
+
+
+s32 rtw_recv_entry(struct recv_frame *precv_frame);
+int rtw_recv_indicatepkt(struct adapter *adapter,
+ struct recv_frame *recv_frame);
+
+void rtw_handle_tkip_mic_err(struct adapter *padapter, u8 bgroup);
+
+int rtw_os_recvbuf_resource_alloc(struct adapter *adapt, struct recv_buf *buf);
+
+void rtw_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl);
+
+#endif /* */
diff --git a/drivers/staging/rtl8188eu/include/rf.h b/drivers/staging/rtl8188eu/include/rf.h
new file mode 100644
index 0000000..ed3241c
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rf.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#define RF6052_MAX_TX_PWR 0x3F
+#define RF6052_MAX_REG 0x3F
+
+void rtl88eu_phy_rf6052_set_bandwidth(struct adapter *adapt,
+ enum ht_channel_width bandwidth);
+void rtl88eu_phy_rf6052_set_cck_txpower(struct adapter *adapt,
+ u8 *powerlevel);
+void rtl88eu_phy_rf6052_set_ofdm_txpower(struct adapter *adapt,
+ u8 *powerlevel_ofdm,
+ u8 *powerlevel_bw20,
+ u8 *powerlevel_bw40, u8 channel);
diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h b/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h
new file mode 100644
index 0000000..e588656
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __RTL8188E_CMD_H__
+#define __RTL8188E_CMD_H__
+
+enum RTL8188E_H2C_CMD_ID {
+ /* Class Common */
+ H2C_COM_RSVD_PAGE = 0x00,
+ H2C_COM_MEDIA_STATUS_RPT = 0x01,
+ H2C_COM_SCAN = 0x02,
+ H2C_COM_KEEP_ALIVE = 0x03,
+ H2C_COM_DISCNT_DECISION = 0x04,
+ H2C_COM_INIT_OFFLOAD = 0x06,
+ H2C_COM_REMOTE_WAKE_CTL = 0x07,
+ H2C_COM_AP_OFFLOAD = 0x08,
+ H2C_COM_BCN_RSVD_PAGE = 0x09,
+ H2C_COM_PROB_RSP_RSVD_PAGE = 0x0A,
+
+ /* Class PS */
+ H2C_PS_PWR_MODE = 0x20,
+ H2C_PS_TUNE_PARA = 0x21,
+ H2C_PS_TUNE_PARA_2 = 0x22,
+ H2C_PS_LPS_PARA = 0x23,
+ H2C_PS_P2P_OFFLOAD = 0x24,
+
+ /* Class DM */
+ H2C_DM_MACID_CFG = 0x40,
+ H2C_DM_TXBF = 0x41,
+
+ /* Class BT */
+ H2C_BT_COEX_MASK = 0x60,
+ H2C_BT_COEX_GPIO_MODE = 0x61,
+ H2C_BT_DAC_SWING_VAL = 0x62,
+ H2C_BT_PSD_RST = 0x63,
+
+ /* Class */
+ H2C_RESET_TSF = 0xc0,
+};
+
+enum {
+ PWRS
+};
+
+struct setpwrmode_parm {
+ u8 Mode;/* 0:Active,1:LPS,2:WMMPS */
+ u8 SmartPS_RLBM;/* LPS= 0:PS_Poll,1:PS_Poll,2:NullData,WMM= 0:PS_Poll,1:NullData */
+ u8 AwakeInterval; /* unit: beacon interval */
+ u8 bAllQueueUAPSD;
+ u8 PwrState;/* AllON(0x0c),RFON(0x04),RFOFF(0x00) */
+};
+
+struct rsvdpage_loc {
+ u8 LocProbeRsp;
+ u8 LocPsPoll;
+ u8 LocNullData;
+ u8 LocQosNull;
+ u8 LocBTQosNull;
+};
+
+/* host message to firmware cmd */
+void rtl8188e_set_FwPwrMode_cmd(struct adapter *padapter, u8 Mode);
+void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *padapter, u8 mstatus);
+
+void rtl8188e_set_FwMediaStatus_cmd(struct adapter *adapt, __le16 mstatus_rpt);
+
+#endif/* __RTL8188E_CMD_H__ */
diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_dm.h b/drivers/staging/rtl8188eu/include/rtl8188e_dm.h
new file mode 100644
index 0000000..1920433
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtl8188e_dm.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __RTL8188E_DM_H__
+#define __RTL8188E_DM_H__
+enum{
+ UP_LINK,
+ DOWN_LINK,
+};
+/* duplicate code,will move to ODM ######### */
+#define IQK_MAC_REG_NUM 4
+#define IQK_ADDA_REG_NUM 16
+#define IQK_BB_REG_NUM 9
+#define HP_THERMAL_NUM 8
+/* duplicate code,will move to ODM ######### */
+struct dm_priv {
+ u8 DM_Type;
+ u8 DMFlag;
+ u8 InitDMFlag;
+ u32 InitODMFlag;
+
+ /* Upper and Lower Signal threshold for Rate Adaptive*/
+ int UndecoratedSmoothedPWDB;
+ int UndecoratedSmoothedCCK;
+ int EntryMinUndecoratedSmoothedPWDB;
+ int EntryMaxUndecoratedSmoothedPWDB;
+ int MinUndecoratedPWDBForDM;
+ int LastMinUndecoratedPWDBForDM;
+
+ /* for High Power */
+ u8 bDynamicTxPowerEnable;
+ u8 LastDTPLvl;
+ u8 DynamicTxHighPowerLvl;/* Tx Power Control for Near/Far Range */
+ u8 PowerIndex_backup[6];
+};
+
+void rtl8188e_InitHalDm(struct adapter *adapt);
+
+void AntDivCompare8188E(struct adapter *adapt, struct wlan_bssid_ex *dst,
+ struct wlan_bssid_ex *src);
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h
new file mode 100644
index 0000000..eb4655e
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h
@@ -0,0 +1,374 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __RTL8188E_HAL_H__
+#define __RTL8188E_HAL_H__
+
+
+/* include HAL Related header after HAL Related compiling flags */
+#include "rtl8188e_spec.h"
+#include "hal8188e_phy_reg.h"
+#include "hal8188e_phy_cfg.h"
+#include "rtl8188e_dm.h"
+#include "rtl8188e_recv.h"
+#include "rtl8188e_xmit.h"
+#include "rtl8188e_cmd.h"
+#include "pwrseq.h"
+#include "rtw_efuse.h"
+#include "rtw_sreset.h"
+#include "odm_precomp.h"
+
+/* Fw Array */
+#define Rtl8188E_FwImageArray Rtl8188EFwImgArray
+#define Rtl8188E_FWImgArrayLength Rtl8188EFWImgArrayLength
+
+#define RTL8188E_FW_UMC_IMG "rtl8188E\\rtl8188efw.bin"
+#define RTL8188E_PHY_REG "rtl8188E\\PHY_REG_1T.txt"
+#define RTL8188E_PHY_RADIO_A "rtl8188E\\radio_a_1T.txt"
+#define RTL8188E_PHY_RADIO_B "rtl8188E\\radio_b_1T.txt"
+#define RTL8188E_AGC_TAB "rtl8188E\\AGC_TAB_1T.txt"
+#define RTL8188E_PHY_MACREG "rtl8188E\\MAC_REG.txt"
+#define RTL8188E_PHY_REG_PG "rtl8188E\\PHY_REG_PG.txt"
+#define RTL8188E_PHY_REG_MP "rtl8188E\\PHY_REG_MP.txt"
+
+/* RTL8188E Power Configuration CMDs for USB/SDIO interfaces */
+#define Rtl8188E_NIC_PWR_ON_FLOW rtl8188E_power_on_flow
+#define Rtl8188E_NIC_RF_OFF_FLOW rtl8188E_radio_off_flow
+#define Rtl8188E_NIC_DISABLE_FLOW rtl8188E_card_disable_flow
+#define Rtl8188E_NIC_ENABLE_FLOW rtl8188E_card_enable_flow
+#define Rtl8188E_NIC_SUSPEND_FLOW rtl8188E_suspend_flow
+#define Rtl8188E_NIC_RESUME_FLOW rtl8188E_resume_flow
+#define Rtl8188E_NIC_PDN_FLOW rtl8188E_hwpdn_flow
+#define Rtl8188E_NIC_LPS_ENTER_FLOW rtl8188E_enter_lps_flow
+#define Rtl8188E_NIC_LPS_LEAVE_FLOW rtl8188E_leave_lps_flow
+
+#define DRVINFO_SZ 4 /* unit is 8bytes */
+#define PageNum_128(_Len) (u32)(((_Len)>>7) + ((_Len) & 0x7F ? 1 : 0))
+
+/* download firmware related data structure */
+#define FW_8188E_SIZE 0x4000 /* 16384,16k */
+#define FW_8188E_START_ADDRESS 0x1000
+#define FW_8188E_END_ADDRESS 0x1FFF /* 0x5FFF */
+
+#define MAX_PAGE_SIZE 4096 /* @ page : 4k bytes */
+
+#define IS_FW_HEADER_EXIST(_pFwHdr) \
+ ((le16_to_cpu(_pFwHdr->signature)&0xFFF0) == 0x92C0 || \
+ (le16_to_cpu(_pFwHdr->signature)&0xFFF0) == 0x88C0 || \
+ (le16_to_cpu(_pFwHdr->signature)&0xFFF0) == 0x2300 || \
+ (le16_to_cpu(_pFwHdr->signature)&0xFFF0) == 0x88E0)
+
+#define DRIVER_EARLY_INT_TIME 0x05
+#define BCN_DMA_ATIME_INT_TIME 0x02
+
+enum usb_rx_agg_mode {
+ USB_RX_AGG_DISABLE,
+ USB_RX_AGG_DMA,
+ USB_RX_AGG_USB,
+ USB_RX_AGG_MIX
+};
+
+#define MAX_RX_DMA_BUFFER_SIZE_88E \
+ 0x2400 /* 9k for 88E nornal chip , MaxRxBuff=10k-max(TxReportSize(64*8),
+ * WOLPattern(16*24))
+ */
+
+#define MAX_TX_REPORT_BUFFER_SIZE 0x0400 /* 1k */
+
+
+/* BK, BE, VI, VO, HCCA, MANAGEMENT, COMMAND, HIGH, BEACON. */
+#define MAX_TX_QUEUE 9
+
+#define TX_SELE_HQ BIT(0) /* High Queue */
+#define TX_SELE_LQ BIT(1) /* Low Queue */
+#define TX_SELE_NQ BIT(2) /* Normal Queue */
+
+/* Note: We will divide number of page equally for each queue other
+ * than public queue!
+ */
+/* 22k = 22528 bytes = 176 pages (@page = 128 bytes) */
+/* must reserved about 7 pages for LPS => 176-7 = 169 (0xA9) */
+/* 2*BCN / 1*ps-poll / 1*null-data /1*prob_rsp /1*QOS null-data /1*BT QOS
+ * null-data
+ */
+
+#define TX_TOTAL_PAGE_NUMBER_88E 0xA9/* 169 (21632=> 21k) */
+
+#define TX_PAGE_BOUNDARY_88E (TX_TOTAL_PAGE_NUMBER_88E + 1)
+
+/* Note: For Normal Chip Setting ,modify later */
+#define WMM_NORMAL_TX_TOTAL_PAGE_NUMBER \
+ TX_TOTAL_PAGE_NUMBER_88E /* 0xA9 , 0xb0=>176=>22k */
+#define WMM_NORMAL_TX_PAGE_BOUNDARY_88E \
+ (WMM_NORMAL_TX_TOTAL_PAGE_NUMBER + 1) /* 0xA9 */
+
+/* Chip specific */
+#define CHIP_BONDING_IDENTIFIER(_value) (((_value)>>22)&0x3)
+#define CHIP_BONDING_92C_1T2R 0x1
+#define CHIP_BONDING_88C_USB_MCARD 0x2
+#define CHIP_BONDING_88C_USB_HP 0x1
+#include "HalVerDef.h"
+#include "hal_com.h"
+
+/* Channel Plan */
+enum ChannelPlan {
+ CHPL_FCC = 0,
+ CHPL_IC = 1,
+ CHPL_ETSI = 2,
+ CHPL_SPA = 3,
+ CHPL_FRANCE = 4,
+ CHPL_MKK = 5,
+ CHPL_MKK1 = 6,
+ CHPL_ISRAEL = 7,
+ CHPL_TELEC = 8,
+ CHPL_GLOBAL = 9,
+ CHPL_WORLD = 10,
+};
+
+struct txpowerinfo24g {
+ u8 IndexCCK_Base[MAX_RF_PATH][MAX_CHNL_GROUP_24G];
+ u8 IndexBW40_Base[MAX_RF_PATH][MAX_CHNL_GROUP_24G];
+ /* If only one tx, only BW20 and OFDM are used. */
+ s8 CCK_Diff[MAX_RF_PATH][MAX_TX_COUNT];
+ s8 OFDM_Diff[MAX_RF_PATH][MAX_TX_COUNT];
+ s8 BW20_Diff[MAX_RF_PATH][MAX_TX_COUNT];
+ s8 BW40_Diff[MAX_RF_PATH][MAX_TX_COUNT];
+};
+
+#define EFUSE_REAL_CONTENT_LEN 512
+#define EFUSE_MAX_SECTION 16
+#define EFUSE_IC_ID_OFFSET 506 /* For some inferior IC purpose*/
+#define AVAILABLE_EFUSE_ADDR(addr) (addr < EFUSE_REAL_CONTENT_LEN)
+/* To prevent out of boundary programming case, */
+/* leave 1byte and program full section */
+/* 9bytes + 1byt + 5bytes and pre 1byte. */
+/* For worst case: */
+/* | 1byte|----8bytes----|1byte|--5bytes--| */
+/* | | Reserved(14bytes) | */
+
+/* PG data exclude header, dummy 6 bytes from CP test and reserved 1byte. */
+#define EFUSE_OOB_PROTECT_BYTES 15
+
+#define HWSET_MAX_SIZE_88E 512
+
+#define EFUSE_REAL_CONTENT_LEN_88E 256
+#define EFUSE_MAP_LEN_88E 512
+#define EFUSE_MAP_LEN EFUSE_MAP_LEN_88E
+#define EFUSE_MAX_SECTION_88E 64
+#define EFUSE_MAX_WORD_UNIT_88E 4
+#define EFUSE_IC_ID_OFFSET_88E 506
+#define AVAILABLE_EFUSE_ADDR_88E(addr) \
+ (addr < EFUSE_REAL_CONTENT_LEN_88E)
+/* To prevent out of boundary programming case, leave 1byte and program
+ * full section
+ */
+/* 9bytes + 1byt + 5bytes and pre 1byte. */
+/* For worst case: */
+/* | 2byte|----8bytes----|1byte|--7bytes--| 92D */
+/* PG data exclude header, dummy 7 bytes from CP test and reserved 1byte. */
+#define EFUSE_OOB_PROTECT_BYTES_88E 18
+#define EFUSE_PROTECT_BYTES_BANK_88E 16
+
+/* EFUSE for BT definition */
+#define EFUSE_BT_REAL_CONTENT_LEN 1536 /* 512*3 */
+#define EFUSE_BT_MAP_LEN 1024 /* 1k bytes */
+#define EFUSE_BT_MAX_SECTION 128 /* 1024/8 */
+
+#define EFUSE_PROTECT_BYTES_BANK 16
+
+struct hal_data_8188e {
+ struct HAL_VERSION VersionID;
+ u16 CustomerID;
+ u16 FirmwareVersion;
+ u16 FirmwareVersionRev;
+ u16 FirmwareSubVersion;
+ u16 FirmwareSignature;
+ u8 PGMaxGroup;
+ /* current WIFI_PHY values */
+ u32 ReceiveConfig;
+ enum wireless_mode CurrentWirelessMode;
+ enum ht_channel_width CurrentChannelBW;
+ u8 CurrentChannel;
+ u8 nCur40MhzPrimeSC;/* Control channel sub-carrier */
+
+ u16 BasicRateSet;
+
+ u8 BoardType;
+
+ /* EEPROM setting. */
+ u16 EEPROMVID;
+ u16 EEPROMPID;
+ u16 EEPROMSVID;
+ u16 EEPROMSDID;
+ u8 EEPROMCustomerID;
+ u8 EEPROMSubCustomerID;
+ u8 EEPROMVersion;
+ u8 EEPROMRegulatory;
+
+ u8 bTXPowerDataReadFromEEPORM;
+ u8 EEPROMThermalMeter;
+ u8 bAPKThermalMeterIgnore;
+
+ bool EepromOrEfuse;
+ /* 92C:256bytes, 88E:512bytes, we use union set (512bytes) */
+ u8 EfuseMap[2][HWSET_MAX_SIZE_512];
+ u8 EfuseUsedPercentage;
+ struct efuse_hal EfuseHal;
+
+ u8 Index24G_CCK_Base[MAX_RF_PATH][CHANNEL_MAX_NUMBER];
+ u8 Index24G_BW40_Base[MAX_RF_PATH][CHANNEL_MAX_NUMBER];
+ /* If only one tx, only BW20 and OFDM are used. */
+ s8 CCK_24G_Diff[MAX_RF_PATH][MAX_TX_COUNT];
+ s8 OFDM_24G_Diff[MAX_RF_PATH][MAX_TX_COUNT];
+ s8 BW20_24G_Diff[MAX_RF_PATH][MAX_TX_COUNT];
+ s8 BW40_24G_Diff[MAX_RF_PATH][MAX_TX_COUNT];
+
+ u8 TxPwrLevelCck[RF_PATH_MAX][CHANNEL_MAX_NUMBER];
+ /* For HT 40MHZ pwr */
+ u8 TxPwrLevelHT40_1S[RF_PATH_MAX][CHANNEL_MAX_NUMBER];
+ /* For HT 40MHZ pwr */
+ u8 TxPwrLevelHT40_2S[RF_PATH_MAX][CHANNEL_MAX_NUMBER];
+ /* HT 20<->40 Pwr diff */
+ u8 TxPwrHt20Diff[RF_PATH_MAX][CHANNEL_MAX_NUMBER];
+ /* For HT<->legacy pwr diff */
+ u8 TxPwrLegacyHtDiff[RF_PATH_MAX][CHANNEL_MAX_NUMBER];
+ /* For power group */
+ u8 PwrGroupHT20[RF_PATH_MAX][CHANNEL_MAX_NUMBER];
+ u8 PwrGroupHT40[RF_PATH_MAX][CHANNEL_MAX_NUMBER];
+
+ u8 LegacyHTTxPowerDiff;/* Legacy to HT rate power diff */
+ /* The current Tx Power Level */
+ u8 CurrentCckTxPwrIdx;
+ u8 CurrentOfdm24GTxPwrIdx;
+ u8 CurrentBW2024GTxPwrIdx;
+ u8 CurrentBW4024GTxPwrIdx;
+
+
+ /* Read/write are allow for following hardware information variables */
+ u8 framesync;
+ u32 framesyncC34;
+ u8 framesyncMonitor;
+ u8 DefaultInitialGain[4];
+ u8 pwrGroupCnt;
+ u32 MCSTxPowerLevelOriginalOffset[MAX_PG_GROUP][16];
+ u32 CCKTxPowerLevelOriginalOffset;
+
+ u8 CrystalCap;
+
+ u32 AcParam_BE; /* Original parameter for BE, use for EDCA turbo. */
+
+ struct bb_reg_def PHYRegDef[4]; /* Radio A/B/C/D */
+
+ u32 RfRegChnlVal[2];
+
+ /* RDG enable */
+ bool bRDGEnable;
+
+ /* for host message to fw */
+ u8 LastHMEBoxNum;
+
+ u8 RegTxPause;
+ /* Beacon function related global variable. */
+ u32 RegBcnCtrlVal;
+ u8 RegFwHwTxQCtrl;
+ u8 RegReg542;
+ u8 RegCR_1;
+
+ struct dm_priv dmpriv;
+ struct odm_dm_struct odmpriv;
+ struct sreset_priv srestpriv;
+
+ u8 CurAntenna;
+ u8 AntDivCfg;
+ u8 TRxAntDivType;
+
+
+ u8 bDumpRxPkt;/* for debug */
+ u8 bDumpTxPkt;/* for debug */
+ u8 FwRsvdPageStartOffset; /* Reserve page start offset except
+ * beacon in TxQ.
+ */
+
+ /* 2010/08/09 MH Add CU power down mode. */
+ bool pwrdown;
+
+ /* Add for dual MAC 0--Mac0 1--Mac1 */
+ u32 interfaceIndex;
+
+ u8 OutEpQueueSel;
+ u8 OutEpNumber;
+
+ u16 EfuseUsedBytes;
+
+ /* Auto FSM to Turn On, include clock, isolation, power control
+ * for MAC only
+ */
+ u8 bMacPwrCtrlOn;
+
+ u32 UsbBulkOutSize;
+
+ /* Interrupt relatd register information. */
+ u32 IntArray[3];/* HISR0,HISR1,HSISR */
+ u32 IntrMask[3];
+ u8 C2hArray[16];
+ u8 UsbTxAggMode;
+ u8 UsbTxAggDescNum;
+ u16 HwRxPageSize; /* Hardware setting */
+ u32 MaxUsbRxAggBlock;
+
+ enum usb_rx_agg_mode UsbRxAggMode;
+ u8 UsbRxAggBlockCount; /* USB Block count. Block size is
+ * 512-byte in high speed and 64-byte
+ * in full speed
+ */
+ u8 UsbRxAggBlockTimeout;
+ u8 UsbRxAggPageCount; /* 8192C DMA page count */
+ u8 UsbRxAggPageTimeout;
+};
+
+void Hal_GetChnlGroup88E(u8 chnl, u8 *group);
+
+/* rtl8188e_hal_init.c */
+void _8051Reset88E(struct adapter *padapter);
+void rtl8188e_InitializeFirmwareVars(struct adapter *padapter);
+
+
+s32 InitLLTTable(struct adapter *padapter, u8 txpktbuf_bndy);
+
+/* EFuse */
+void Hal_InitPGData88E(struct adapter *padapter);
+void Hal_EfuseParseIDCode88E(struct adapter *padapter, u8 *hwinfo);
+void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *hwinfo,
+ bool AutoLoadFail);
+
+void Hal_EfuseParseEEPROMVer88E(struct adapter *padapter, u8 *hwinfo,
+ bool AutoLoadFail);
+void rtl8188e_EfuseParseChnlPlan(struct adapter *padapter, u8 *hwinfo,
+ bool AutoLoadFail);
+void Hal_EfuseParseCustomerID88E(struct adapter *padapter, u8 *hwinfo,
+ bool AutoLoadFail);
+void Hal_ReadAntennaDiversity88E(struct adapter *pAdapter, u8 *PROMContent,
+ bool AutoLoadFail);
+void Hal_ReadThermalMeter_88E(struct adapter *dapter, u8 *PROMContent,
+ bool AutoloadFail);
+void Hal_EfuseParseXtal_8188E(struct adapter *pAdapter, u8 *hwinfo,
+ bool AutoLoadFail);
+void Hal_EfuseParseBoardType88E(struct adapter *pAdapter, u8 *hwinfo,
+ bool AutoLoadFail);
+void Hal_ReadPowerSavingMode88E(struct adapter *pAdapter, u8 *hwinfo,
+ bool AutoLoadFail);
+
+/* register */
+
+void rtl8188e_start_thread(struct adapter *padapter);
+void rtl8188e_stop_thread(struct adapter *padapter);
+
+s32 iol_execute(struct adapter *padapter, u8 control);
+void iol_mode_enable(struct adapter *padapter, u8 enable);
+s32 rtl8188e_iol_efuse_patch(struct adapter *padapter);
+void rtw_cancel_all_timer(struct adapter *padapter);
+
+#endif /* __RTL8188E_HAL_H__ */
diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_recv.h b/drivers/staging/rtl8188eu/include/rtl8188e_recv.h
new file mode 100644
index 0000000..c2c7ef9
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtl8188e_recv.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __RTL8188E_RECV_H__
+#define __RTL8188E_RECV_H__
+
+#define TX_RPT1_PKT_LEN 8
+
+#define RECV_BLK_SZ 512
+#define RECV_BLK_CNT 16
+#define RECV_BLK_TH RECV_BLK_CNT
+#define RECV_BULK_IN_ADDR 0x80
+#define RECV_INT_IN_ADDR 0x81
+
+#define NR_PREALLOC_RECV_SKB (8)
+
+#define NR_RECVBUFF (4)
+
+#define MAX_RECVBUF_SZ (15360) /* 15k < 16k */
+
+struct phy_stat {
+ unsigned int phydw0;
+ unsigned int phydw1;
+ unsigned int phydw2;
+ unsigned int phydw3;
+ unsigned int phydw4;
+ unsigned int phydw5;
+ unsigned int phydw6;
+ unsigned int phydw7;
+};
+
+/* Rx smooth factor */
+#define Rx_Smooth_Factor (20)
+
+enum rx_packet_type {
+ NORMAL_RX,/* Normal rx packet */
+ TX_REPORT1,/* CCX */
+ TX_REPORT2,/* TX RPT */
+ HIS_REPORT,/* USB HISR RPT */
+};
+
+#define INTERRUPT_MSG_FORMAT_LEN 60
+void rtl8188eu_recv_tasklet(void *priv);
+void rtl8188e_process_phy_info(struct adapter *padapter,
+ struct recv_frame *prframe);
+void update_recvframe_phyinfo_88e(struct recv_frame *fra, struct phy_stat *phy);
+void update_recvframe_attrib_88e(struct recv_frame *fra,
+ struct recv_stat *stat);
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_spec.h b/drivers/staging/rtl8188eu/include/rtl8188e_spec.h
new file mode 100644
index 0000000..dd943c8
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtl8188e_spec.h
@@ -0,0 +1,1403 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ *******************************************************************************/
+#ifndef __RTL8188E_SPEC_H__
+#define __RTL8188E_SPEC_H__
+
+/* 8192C Register offset definition */
+
+#define HAL_PS_TIMER_INT_DELAY 50 /* 50 microseconds */
+#define HAL_92C_NAV_UPPER_UNIT 128 /* micro-second */
+
+#define MAC_ADDR_LEN 6
+/* 8188E PKT_BUFF_ACCESS_CTRL value */
+#define TXPKT_BUF_SELECT 0x69
+#define RXPKT_BUF_SELECT 0xA5
+#define DISABLE_TRXPKT_BUF_ACCESS 0x0
+
+
+/* 0x0000h ~ 0x00FFh System Configuration */
+#define REG_SYS_ISO_CTRL 0x0000
+#define REG_SYS_FUNC_EN 0x0002
+#define REG_APS_FSMCO 0x0004
+#define REG_SYS_CLKR 0x0008
+#define REG_9346CR 0x000A
+#define REG_EE_VPD 0x000C
+#define REG_AFE_MISC 0x0010
+#define REG_SPS0_CTRL 0x0011
+#define REG_SPS_OCP_CFG 0x0018
+#define REG_RSV_CTRL 0x001C
+#define REG_RF_CTRL 0x001F
+#define REG_LDOA15_CTRL 0x0020
+#define REG_LDOV12D_CTRL 0x0021
+#define REG_LDOHCI12_CTRL 0x0022
+#define REG_LPLDO_CTRL 0x0023
+#define REG_AFE_XTAL_CTRL 0x0024
+#define REG_AFE_PLL_CTRL 0x0028
+#define REG_APE_PLL_CTRL_EXT 0x002c
+#define REG_EFUSE_CTRL 0x0030
+#define REG_EFUSE_TEST 0x0034
+#define REG_GPIO_MUXCFG 0x0040
+#define REG_GPIO_IO_SEL 0x0042
+#define REG_MAC_PINMUX_CFG 0x0043
+#define REG_GPIO_PIN_CTRL 0x0044
+#define REG_GPIO_INTM 0x0048
+#define REG_LEDCFG0 0x004C
+#define REG_LEDCFG1 0x004D
+#define REG_LEDCFG2 0x004E
+#define REG_LEDCFG3 0x004F
+#define REG_FSIMR 0x0050
+#define REG_FSISR 0x0054
+#define REG_HSIMR 0x0058
+#define REG_HSISR 0x005c
+#define REG_GPIO_PIN_CTRL_2 0x0060 /* RTL8723 WIFI/BT/GPS
+ * Multi-Function GPIO Pin Control.
+ */
+#define REG_GPIO_IO_SEL_2 0x0062 /* RTL8723 WIFI/BT/GPS
+ * Multi-Function GPIO Select.
+ */
+#define REG_BB_PAD_CTRL 0x0064
+#define REG_MULTI_FUNC_CTRL 0x0068 /* RTL8723 WIFI/BT/GPS
+ * Multi-Function control source.
+ */
+#define REG_GPIO_OUTPUT 0x006c
+#define REG_AFE_XTAL_CTRL_EXT 0x0078 /* RTL8188E */
+#define REG_XCK_OUT_CTRL 0x007c /* RTL8188E */
+#define REG_MCUFWDL 0x0080
+#define REG_WOL_EVENT 0x0081 /* RTL8188E */
+#define REG_MCUTSTCFG 0x0084
+#define REG_HMEBOX_E0 0x0088
+#define REG_HMEBOX_E1 0x008A
+#define REG_HMEBOX_E2 0x008C
+#define REG_HMEBOX_E3 0x008E
+#define REG_HMEBOX_EXT_0 0x01F0
+#define REG_HMEBOX_EXT_1 0x01F4
+#define REG_HMEBOX_EXT_2 0x01F8
+#define REG_HMEBOX_EXT_3 0x01FC
+#define REG_HIMR_88E 0x00B0
+#define REG_HISR_88E 0x00B4
+#define REG_HIMRE_88E 0x00B8
+#define REG_HISRE_88E 0x00BC
+#define REG_EFUSE_ACCESS 0x00CF /* Efuse access protection
+ * for RTL8723
+ */
+#define REG_BIST_SCAN 0x00D0
+#define REG_BIST_RPT 0x00D4
+#define REG_BIST_ROM_RPT 0x00D8
+#define REG_USB_SIE_INTF 0x00E0
+#define REG_PCIE_MIO_INTF 0x00E4
+#define REG_PCIE_MIO_INTD 0x00E8
+#define REG_HPON_FSM 0x00EC
+#define REG_SYS_CFG 0x00F0
+#define REG_GPIO_OUTSTS 0x00F4 /* For RTL8723 only. */
+#define REG_TYPE_ID 0x00FC
+
+#define REG_MAC_PHY_CTRL_NORMAL 0x00f8
+
+/* 0x0100h ~ 0x01FFh MACTOP General Configuration */
+#define REG_CR 0x0100
+#define REG_PBP 0x0104
+#define REG_PKT_BUFF_ACCESS_CTRL 0x0106
+#define REG_TRXDMA_CTRL 0x010C
+#define REG_TRXFF_BNDY 0x0114
+#define REG_TRXFF_STATUS 0x0118
+#define REG_RXFF_PTR 0x011C
+/* define REG_HIMR 0x0120 */
+/* define REG_HISR 0x0124 */
+#define REG_HIMRE 0x0128
+#define REG_HISRE 0x012C
+#define REG_CPWM 0x012F
+#define REG_FWIMR 0x0130
+#define REG_FTIMR 0x0138
+#define REG_FWISR 0x0134
+#define REG_PKTBUF_DBG_CTRL 0x0140
+#define REG_PKTBUF_DBG_ADDR (REG_PKTBUF_DBG_CTRL)
+#define REG_RXPKTBUF_DBG (REG_PKTBUF_DBG_CTRL + 2)
+#define REG_TXPKTBUF_DBG (REG_PKTBUF_DBG_CTRL + 3)
+#define REG_RXPKTBUF_CTRL (REG_PKTBUF_DBG_CTRL + 2)
+#define REG_PKTBUF_DBG_DATA_L 0x0144
+#define REG_PKTBUF_DBG_DATA_H 0x0148
+
+#define REG_TC0_CTRL 0x0150
+#define REG_TC1_CTRL 0x0154
+#define REG_TC2_CTRL 0x0158
+#define REG_TC3_CTRL 0x015C
+#define REG_TC4_CTRL 0x0160
+#define REG_TCUNIT_BASE 0x0164
+#define REG_MBIST_START 0x0174
+#define REG_MBIST_DONE 0x0178
+#define REG_MBIST_FAIL 0x017C
+#define REG_32K_CTRL 0x0194 /* RTL8188E */
+#define REG_C2HEVT_MSG_NORMAL 0x01A0
+#define REG_C2HEVT_CLEAR 0x01AF
+#define REG_MCUTST_1 0x01c0
+#define REG_FMETHR 0x01C8
+#define REG_HMETFR 0x01CC
+#define REG_HMEBOX_0 0x01D0
+#define REG_HMEBOX_1 0x01D4
+#define REG_HMEBOX_2 0x01D8
+#define REG_HMEBOX_3 0x01DC
+
+#define REG_LLT_INIT 0x01E0
+
+/* 0x0200h ~ 0x027Fh TXDMA Configuration */
+#define REG_RQPN 0x0200
+#define REG_FIFOPAGE 0x0204
+#define REG_TDECTRL 0x0208
+#define REG_TXDMA_OFFSET_CHK 0x020C
+#define REG_TXDMA_STATUS 0x0210
+#define REG_RQPN_NPQ 0x0214
+
+/* 0x0280h ~ 0x02FFh RXDMA Configuration */
+#define REG_RXDMA_AGG_PG_TH 0x0280
+#define REG_RXPKT_NUM 0x0284
+#define REG_RXDMA_STATUS 0x0288
+
+/* 0x0300h ~ 0x03FFh PCIe */
+#define REG_PCIE_CTRL_REG 0x0300
+#define REG_INT_MIG 0x0304 /* Interrupt Migration */
+#define REG_BCNQ_DESA 0x0308 /* TX Beacon Descr Address */
+#define REG_HQ_DESA 0x0310 /* TX High Queue Descr Addr */
+#define REG_MGQ_DESA 0x0318 /* TX Manage Queue Descr Addr*/
+#define REG_VOQ_DESA 0x0320 /* TX VO Queue Descr Addr */
+#define REG_VIQ_DESA 0x0328 /* TX VI Queue Descr Addr */
+#define REG_BEQ_DESA 0x0330 /* TX BE Queue Descr Addr */
+#define REG_BKQ_DESA 0x0338 /* TX BK Queue Descr Addr */
+#define REG_RX_DESA 0x0340 /* RX Queue Descr Addr */
+#define REG_MDIO 0x0354 /* MDIO for Access PCIE PHY */
+#define REG_DBG_SEL 0x0360 /* Debug Selection Register */
+#define REG_PCIE_HRPWM 0x0361 /* PCIe RPWM */
+#define REG_PCIE_HCPWM 0x0363 /* PCIe CPWM */
+#define REG_WATCH_DOG 0x0368
+
+/* RTL8723 series ------------------------------ */
+#define REG_PCIE_HISR 0x03A0
+
+/* spec version 11 */
+/* 0x0400h ~ 0x047Fh Protocol Configuration */
+#define REG_VOQ_INFORMATION 0x0400
+#define REG_VIQ_INFORMATION 0x0404
+#define REG_BEQ_INFORMATION 0x0408
+#define REG_BKQ_INFORMATION 0x040C
+#define REG_MGQ_INFORMATION 0x0410
+#define REG_HGQ_INFORMATION 0x0414
+#define REG_BCNQ_INFORMATION 0x0418
+#define REG_TXPKT_EMPTY 0x041A
+
+#define REG_CPU_MGQ_INFORMATION 0x041C
+#define REG_FWHW_TXQ_CTRL 0x0420
+#define REG_HWSEQ_CTRL 0x0423
+#define REG_TXPKTBUF_BCNQ_BDNY 0x0424
+#define REG_TXPKTBUF_MGQ_BDNY 0x0425
+#define REG_LIFETIME_EN 0x0426
+#define REG_MULTI_BCNQ_OFFSET 0x0427
+#define REG_SPEC_SIFS 0x0428
+#define REG_RL 0x042A
+#define REG_DARFRC 0x0430
+#define REG_RARFRC 0x0438
+#define REG_RRSR 0x0440
+#define REG_ARFR0 0x0444
+#define REG_ARFR1 0x0448
+#define REG_ARFR2 0x044C
+#define REG_ARFR3 0x0450
+#define REG_AGGLEN_LMT 0x0458
+#define REG_AMPDU_MIN_SPACE 0x045C
+#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D
+#define REG_FAST_EDCA_CTRL 0x0460
+#define REG_RD_RESP_PKT_TH 0x0463
+#define REG_INIRTS_RATE_SEL 0x0480
+/* define REG_INIDATA_RATE_SEL 0x0484 */
+#define REG_POWER_STATUS 0x04A4
+#define REG_POWER_STAGE1 0x04B4
+#define REG_POWER_STAGE2 0x04B8
+#define REG_PKT_VO_VI_LIFE_TIME 0x04C0
+#define REG_PKT_BE_BK_LIFE_TIME 0x04C2
+#define REG_STBC_SETTING 0x04C4
+#define REG_PROT_MODE_CTRL 0x04C8
+#define REG_MAX_AGGR_NUM 0x04CA
+#define REG_RTS_MAX_AGGR_NUM 0x04CB
+#define REG_BAR_MODE_CTRL 0x04CC
+#define REG_RA_TRY_RATE_AGG_LMT 0x04CF
+#define REG_EARLY_MODE_CONTROL 0x4D0
+#define REG_NQOS_SEQ 0x04DC
+#define REG_QOS_SEQ 0x04DE
+#define REG_NEED_CPU_HANDLE 0x04E0
+#define REG_PKT_LOSE_RPT 0x04E1
+#define REG_PTCL_ERR_STATUS 0x04E2
+#define REG_TX_RPT_CTRL 0x04EC
+#define REG_TX_RPT_TIME 0x04F0 /* 2 byte */
+#define REG_DUMMY 0x04FC
+
+/* 0x0500h ~ 0x05FFh EDCA Configuration */
+#define REG_EDCA_VO_PARAM 0x0500
+#define REG_EDCA_VI_PARAM 0x0504
+#define REG_EDCA_BE_PARAM 0x0508
+#define REG_EDCA_BK_PARAM 0x050C
+#define REG_BCNTCFG 0x0510
+#define REG_PIFS 0x0512
+#define REG_RDG_PIFS 0x0513
+#define REG_SIFS_CTX 0x0514
+#define REG_SIFS_TRX 0x0516
+#define REG_TSFTR_SYN_OFFSET 0x0518
+#define REG_AGGR_BREAK_TIME 0x051A
+#define REG_SLOT 0x051B
+#define REG_TX_PTCL_CTRL 0x0520
+#define REG_TXPAUSE 0x0522
+#define REG_DIS_TXREQ_CLR 0x0523
+#define REG_RD_CTRL 0x0524
+/* Format for offset 540h-542h:
+ * [3:0]: TBTT prohibit setup in unit of 32us. The time for HW getting
+ * beacon content before TBTT.
+ *
+ * [7:4]: Reserved.
+ * [19:8]: TBTT prohibit hold in unit of 32us. The time for HW holding
+ * to send the beacon packet.
+ *
+ * [23:20]: Reserved
+ * Description:
+ * |
+ * |<--Setup--|--Hold------------>|
+ * --------------|----------------------
+ * |
+ * TBTT
+ * Note: We cannot update beacon content to HW or send any AC packets during
+ * the time between Setup and Hold.
+ */
+#define REG_TBTT_PROHIBIT 0x0540
+#define REG_RD_NAV_NXT 0x0544
+#define REG_NAV_PROT_LEN 0x0546
+#define REG_BCN_CTRL 0x0550
+#define REG_BCN_CTRL_1 0x0551
+#define REG_MBID_NUM 0x0552
+#define REG_DUAL_TSF_RST 0x0553
+#define REG_BCN_INTERVAL 0x0554
+#define REG_DRVERLYINT 0x0558
+#define REG_BCNDMATIM 0x0559
+#define REG_ATIMWND 0x055A
+#define REG_BCN_MAX_ERR 0x055D
+#define REG_RXTSF_OFFSET_CCK 0x055E
+#define REG_RXTSF_OFFSET_OFDM 0x055F
+#define REG_TSFTR 0x0560
+#define REG_TSFTR1 0x0568
+#define REG_ATIMWND_1 0x0570
+#define REG_PSTIMER 0x0580
+#define REG_TIMER0 0x0584
+#define REG_TIMER1 0x0588
+#define REG_ACMHWCTRL 0x05C0
+
+/* define REG_FW_TSF_SYNC_CNT 0x04A0 */
+#define REG_FW_RESET_TSF_CNT_1 0x05FC
+#define REG_FW_RESET_TSF_CNT_0 0x05FD
+#define REG_FW_BCN_DIS_CNT 0x05FE
+
+/* 0x0600h ~ 0x07FFh WMAC Configuration */
+#define REG_APSD_CTRL 0x0600
+#define REG_BWOPMODE 0x0603
+#define REG_TCR 0x0604
+#define REG_RCR 0x0608
+#define REG_RX_PKT_LIMIT 0x060C
+#define REG_RX_DLK_TIME 0x060D
+#define REG_RX_DRVINFO_SZ 0x060F
+
+#define REG_MACID 0x0610
+#define REG_BSSID 0x0618
+#define REG_MAR 0x0620
+#define REG_MBIDCAMCFG 0x0628
+
+#define REG_USTIME_EDCA 0x0638
+#define REG_MAC_SPEC_SIFS 0x063A
+
+/* 20100719 Joseph: Hardware register definition change. (HW datasheet v54) */
+/* [15:8]SIFS_R2T_OFDM, [7:0]SIFS_R2T_CCK */
+#define REG_R2T_SIFS 0x063C
+/* [15:8]SIFS_T2T_OFDM, [7:0]SIFS_T2T_CCK */
+#define REG_T2T_SIFS 0x063E
+#define REG_ACKTO 0x0640
+#define REG_CTS2TO 0x0641
+#define REG_EIFS 0x0642
+
+/* RXERR_RPT */
+#define RXERR_TYPE_OFDM_PPDU 0
+#define RXERR_TYPE_OFDM_false_ALARM 1
+#define RXERR_TYPE_OFDM_MPDU_OK 2
+#define RXERR_TYPE_OFDM_MPDU_FAIL 3
+#define RXERR_TYPE_CCK_PPDU 4
+#define RXERR_TYPE_CCK_false_ALARM 5
+#define RXERR_TYPE_CCK_MPDU_OK 6
+#define RXERR_TYPE_CCK_MPDU_FAIL 7
+#define RXERR_TYPE_HT_PPDU 8
+#define RXERR_TYPE_HT_false_ALARM 9
+#define RXERR_TYPE_HT_MPDU_TOTAL 10
+#define RXERR_TYPE_HT_MPDU_OK 11
+#define RXERR_TYPE_HT_MPDU_FAIL 12
+#define RXERR_TYPE_RX_FULL_DROP 15
+
+#define RXERR_COUNTER_MASK 0xFFFFF
+#define RXERR_RPT_RST BIT(27)
+#define _RXERR_RPT_SEL(type) ((type) << 28)
+
+/* Note:
+ * The NAV upper value is very important to WiFi 11n 5.2.3 NAV test.
+ * The default value is always too small, but the WiFi TestPlan test
+ * by 25,000 microseconds of NAV through sending CTS in the air.
+ * We must update this value greater than 25,000 microseconds to pass
+ * the item. The offset of NAV_UPPER in 8192C Spec is incorrect, and
+ * the offset should be 0x0652.
+ */
+#define REG_NAV_UPPER 0x0652 /* unit of 128 */
+
+/* WMA, BA, CCX */
+/* define REG_NAV_CTRL 0x0650 */
+#define REG_BACAMCMD 0x0654
+#define REG_BACAMCONTENT 0x0658
+#define REG_LBDLY 0x0660
+#define REG_FWDLY 0x0661
+#define REG_RXERR_RPT 0x0664
+#define REG_WMAC_TRXPTCL_CTL 0x0668
+
+/* Security */
+#define REG_CAMCMD 0x0670
+#define REG_CAMWRITE 0x0674
+#define REG_CAMREAD 0x0678
+#define REG_CAMDBG 0x067C
+#define REG_SECCFG 0x0680
+
+/* Power */
+#define REG_WOW_CTRL 0x0690
+#define REG_PS_RX_INFO 0x0692
+#define REG_UAPSD_TID 0x0693
+#define REG_WKFMCAM_CMD 0x0698
+#define REG_WKFMCAM_NUM_88E 0x698
+#define REG_RXFLTMAP0 0x06A0
+#define REG_RXFLTMAP1 0x06A2
+#define REG_RXFLTMAP2 0x06A4
+#define REG_BCN_PSR_RPT 0x06A8
+#define REG_BT_COEX_TABLE 0x06C0
+
+/* Hardware Port 2 */
+#define REG_MACID1 0x0700
+#define REG_BSSID1 0x0708
+
+/* 0xFE00h ~ 0xFE55h USB Configuration */
+#define REG_USB_INFO 0xFE17
+#define REG_USB_SPECIAL_OPTION 0xFE55
+#define REG_USB_DMA_AGG_TO 0xFE5B
+#define REG_USB_AGG_TO 0xFE5C
+#define REG_USB_AGG_TH 0xFE5D
+
+/* For normal chip */
+#define REG_NORMAL_SIE_VID 0xFE60 /* 0xFE60~0xFE61 */
+#define REG_NORMAL_SIE_PID 0xFE62 /* 0xFE62~0xFE63 */
+#define REG_NORMAL_SIE_OPTIONAL 0xFE64
+#define REG_NORMAL_SIE_EP 0xFE65 /* 0xFE65~0xFE67 */
+#define REG_NORMAL_SIE_PHY 0xFE68 /* 0xFE68~0xFE6B */
+#define REG_NORMAL_SIE_OPTIONAL2 0xFE6C
+#define REG_NORMAL_SIE_GPS_EP 0xFE6D /* 0xFE6D, for RTL8723 only. */
+#define REG_NORMAL_SIE_MAC_ADDR 0xFE70 /* 0xFE70~0xFE75 */
+#define REG_NORMAL_SIE_STRING 0xFE80 /* 0xFE80~0xFEDF */
+
+/* TODO: use these definition when using REG_xxx naming rule. */
+/* NOTE: DO NOT Remove these definition. Use later. */
+
+#define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */
+#define EFUSE_TEST REG_EFUSE_TEST /* E-Fuse Test. */
+#define MSR (REG_CR + 2) /* Media Status reg */
+#define ISR REG_HISR_88E
+/* Timing Sync Function Timer Register. */
+#define TSFR REG_TSFTR
+
+#define PBP REG_PBP
+
+/* Redifine MACID register, to compatible prior ICs. */
+/* MAC ID Register, Offset 0x0050-0x0053 */
+#define IDR0 REG_MACID
+/* MAC ID Register, Offset 0x0054-0x0055 */
+#define IDR4 (REG_MACID + 4)
+
+/* 9. Security Control Registers (Offset: ) */
+/* IN 8190 Data Sheet is called CAMcmd */
+#define RWCAM REG_CAMCMD
+/* Software write CAM input content */
+#define WCAMI REG_CAMWRITE
+/* Software read/write CAM config */
+#define RCAMO REG_CAMREAD
+#define CAMDBG REG_CAMDBG
+/* Security Configuration Register */
+#define SECR REG_SECCFG
+
+/* Unused register */
+#define UnusedRegister 0x1BF
+#define DCAM UnusedRegister
+#define PSR UnusedRegister
+#define BBAddr UnusedRegister
+#define PhyDataR UnusedRegister
+
+/* Min Spacing related settings. */
+#define MAX_MSS_DENSITY_2T 0x13
+#define MAX_MSS_DENSITY_1T 0x0A
+
+/* EEPROM enable when set 1 */
+#define CmdEEPROM_En BIT(5)
+/* System EEPROM select, 0: boot from E-FUSE, 1: The EEPROM used is 9346 */
+#define CmdEERPOMSEL BIT(4)
+#define Cmd9346CR_9356SEL BIT(4)
+
+/* 8192C GPIO MUX Configuration Register (offset 0x40, 4 byte) */
+#define GPIOSEL_GPIO 0
+#define GPIOSEL_ENBT BIT(5)
+
+/* 8192C GPIO PIN Control Register (offset 0x44, 4 byte) */
+/* GPIO pins input value */
+#define GPIO_IN REG_GPIO_PIN_CTRL
+/* GPIO pins output value */
+#define GPIO_OUT (REG_GPIO_PIN_CTRL + 1)
+/* GPIO pins output enable when a bit is set to "1"; otherwise,
+ * input is configured.
+ */
+#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL + 2)
+#define GPIO_MOD (REG_GPIO_PIN_CTRL + 3)
+
+/* 8723/8188E Host System Interrupt Mask Register (offset 0x58, 32 byte) */
+#define HSIMR_GPIO12_0_INT_EN BIT(0)
+#define HSIMR_SPS_OCP_INT_EN BIT(5)
+#define HSIMR_RON_INT_EN BIT(6)
+#define HSIMR_PDN_INT_EN BIT(7)
+#define HSIMR_GPIO9_INT_EN BIT(25)
+
+/* 8723/8188E Host System Interrupt Status Register (offset 0x5C, 32 byte) */
+#define HSISR_GPIO12_0_INT BIT(0)
+#define HSISR_SPS_OCP_INT BIT(5)
+#define HSISR_RON_INT_EN BIT(6)
+#define HSISR_PDNINT BIT(7)
+#define HSISR_GPIO9_INT BIT(25)
+
+/* 8192C (MSR) Media Status Register (Offset 0x4C, 8 bits) */
+/*
+ * Network Type
+ * 00: No link
+ * 01: Link in ad hoc network
+ * 10: Link in infrastructure network
+ * 11: AP mode
+ * Default: 00b.
+ */
+#define MSR_NOLINK 0x00
+#define MSR_ADHOC 0x01
+#define MSR_INFRA 0x02
+#define MSR_AP 0x03
+
+/* 88EU (MSR) Media Status Register (Offset 0x4C, 8 bits) */
+#define USB_INTR_CONTENT_C2H_OFFSET 0
+#define USB_INTR_CONTENT_CPWM1_OFFSET 16
+#define USB_INTR_CONTENT_CPWM2_OFFSET 20
+#define USB_INTR_CONTENT_HISR_OFFSET 48
+#define USB_INTR_CONTENT_HISRE_OFFSET 52
+
+/* 88E Driver Initialization Offload REG_FDHM0(Offset 0x88, 8 bits) */
+/* IOL config for REG_FDHM0(Reg0x88) */
+#define CMD_INIT_LLT BIT(0)
+#define CMD_READ_EFUSE_MAP BIT(1)
+#define CMD_EFUSE_PATCH BIT(2)
+#define CMD_IOCONFIG BIT(3)
+#define CMD_INIT_LLT_ERR BIT(4)
+#define CMD_READ_EFUSE_MAP_ERR BIT(5)
+#define CMD_EFUSE_PATCH_ERR BIT(6)
+#define CMD_IOCONFIG_ERR BIT(7)
+
+/* 6. Adaptive Control Registers (Offset: 0x0160 - 0x01CF) */
+/* 8192C Response Rate Set Register (offset 0x181, 24bits) */
+#define RRSR_1M BIT(0)
+#define RRSR_2M BIT(1)
+#define RRSR_5_5M BIT(2)
+#define RRSR_11M BIT(3)
+#define RRSR_6M BIT(4)
+#define RRSR_9M BIT(5)
+#define RRSR_12M BIT(6)
+#define RRSR_18M BIT(7)
+#define RRSR_24M BIT(8)
+#define RRSR_36M BIT(9)
+#define RRSR_48M BIT(10)
+#define RRSR_54M BIT(11)
+#define RRSR_MCS0 BIT(12)
+#define RRSR_MCS1 BIT(13)
+#define RRSR_MCS2 BIT(14)
+#define RRSR_MCS3 BIT(15)
+#define RRSR_MCS4 BIT(16)
+#define RRSR_MCS5 BIT(17)
+#define RRSR_MCS6 BIT(18)
+#define RRSR_MCS7 BIT(19)
+
+/* 8192C Response Rate Set Register (offset 0x1BF, 8bits) */
+/* WOL bit information */
+#define HAL92C_WOL_PTK_UPDATE_EVENT BIT(0)
+#define HAL92C_WOL_GTK_UPDATE_EVENT BIT(1)
+
+/* 8192C BW_OPMODE bits (Offset 0x203, 8bit) */
+#define BW_OPMODE_20MHZ BIT(2)
+#define BW_OPMODE_5G BIT(1)
+
+/* 8192C CAM Config Setting (offset 0x250, 1 byte) */
+#define CAM_VALID BIT(15)
+#define CAM_NOTVALID 0x0000
+#define CAM_USEDK BIT(5)
+
+#define CAM_CONTENT_COUNT 8
+
+#define CAM_NONE 0x0
+#define CAM_WEP40 0x01
+#define CAM_TKIP 0x02
+#define CAM_AES 0x04
+#define CAM_WEP104 0x05
+#define CAM_SMS4 0x6
+
+#define TOTAL_CAM_ENTRY 32
+#define HALF_CAM_ENTRY 16
+
+#define CAM_CONFIG_USEDK true
+#define CAM_CONFIG_NO_USEDK false
+
+#define CAM_WRITE BIT(16)
+#define CAM_READ 0x00000000
+#define CAM_POLLINIG BIT(31)
+
+#define SCR_UseDK 0x01
+#define SCR_TxSecEnable 0x02
+#define SCR_RxSecEnable 0x04
+
+/* 10. Power Save Control Registers (Offset: 0x0260 - 0x02DF) */
+#define WOW_PMEN BIT(0) /* Power management Enable. */
+#define WOW_WOMEN BIT(1) /* WoW function on or off. */
+#define WOW_MAGIC BIT(2) /* Magic packet */
+#define WOW_UWF BIT(3) /* Unicast Wakeup frame. */
+
+/* 12. Host Interrupt Status Registers (Offset: 0x0300 - 0x030F) */
+/* 8188 IMR/ISR bits */
+#define IMR_DISABLED_88E 0x0
+/* IMR DW0(0x0060-0063) Bit 0-31 */
+#define IMR_TXCCK_88E BIT(30) /* TXRPT interrupt when CCX bit of the packet is set */
+#define IMR_PSTIMEOUT_88E BIT(29) /* Power Save Time Out Interrupt */
+#define IMR_GTINT4_88E BIT(28) /* When GTIMER4 expires, this bit is set to 1 */
+#define IMR_GTINT3_88E BIT(27) /* When GTIMER3 expires, this bit is set to 1 */
+#define IMR_TBDER_88E BIT(26) /* Transmit Beacon0 Error */
+#define IMR_TBDOK_88E BIT(25) /* Transmit Beacon0 OK */
+#define IMR_TSF_BIT32_TOGGLE_88E BIT(24) /* TSF Timer BIT32 toggle indication interrupt */
+#define IMR_BCNDMAINT0_88E BIT(20) /* Beacon DMA Interrupt 0 */
+#define IMR_BCNDERR0_88E BIT(16) /* Beacon Queue DMA Error 0 */
+#define IMR_HSISR_IND_ON_INT_88E BIT(15) /* HSISR Indicator (HSIMR & HSISR is true, this bit is set to 1) */
+#define IMR_BCNDMAINT_E_88E BIT(14) /* Beacon DMA Interrupt Extension for Win7 */
+#define IMR_ATIMEND_88E BIT(12) /* CTWidnow End or ATIM Window End */
+#define IMR_HISR1_IND_INT_88E BIT(11) /* HISR1 Indicator (HISR1 & HIMR1 is true, this bit is set to 1) */
+#define IMR_C2HCMD_88E BIT(10) /* CPU to Host Command INT Status, Write 1 clear */
+#define IMR_CPWM2_88E BIT(9) /* CPU power Mode exchange INT Status, Write 1 clear */
+#define IMR_CPWM_88E BIT(8) /* CPU power Mode exchange INT Status, Write 1 clear */
+#define IMR_HIGHDOK_88E BIT(7) /* High Queue DMA OK */
+#define IMR_MGNTDOK_88E BIT(6) /* Management Queue DMA OK */
+#define IMR_BKDOK_88E BIT(5) /* AC_BK DMA OK */
+#define IMR_BEDOK_88E BIT(4) /* AC_BE DMA OK */
+#define IMR_VIDOK_88E BIT(3) /* AC_VI DMA OK */
+#define IMR_VODOK_88E BIT(2) /* AC_VO DMA OK */
+#define IMR_RDU_88E BIT(1) /* Rx Descriptor Unavailable */
+#define IMR_ROK_88E BIT(0) /* Receive DMA OK */
+
+/* IMR DW1(0x00B4-00B7) Bit 0-31 */
+#define IMR_BCNDMAINT7_88E BIT(27) /* Beacon DMA Interrupt 7 */
+#define IMR_BCNDMAINT6_88E BIT(26) /* Beacon DMA Interrupt 6 */
+#define IMR_BCNDMAINT5_88E BIT(25) /* Beacon DMA Interrupt 5 */
+#define IMR_BCNDMAINT4_88E BIT(24) /* Beacon DMA Interrupt 4 */
+#define IMR_BCNDMAINT3_88E BIT(23) /* Beacon DMA Interrupt 3 */
+#define IMR_BCNDMAINT2_88E BIT(22) /* Beacon DMA Interrupt 2 */
+#define IMR_BCNDMAINT1_88E BIT(21) /* Beacon DMA Interrupt 1 */
+#define IMR_BCNDERR7_88E BIT(20) /* Beacon DMA Error Int 7 */
+#define IMR_BCNDERR6_88E BIT(19) /* Beacon DMA Error Int 6 */
+#define IMR_BCNDERR5_88E BIT(18) /* Beacon DMA Error Int 5 */
+#define IMR_BCNDERR4_88E BIT(17) /* Beacon DMA Error Int 4 */
+#define IMR_BCNDERR3_88E BIT(16) /* Beacon DMA Error Int 3 */
+#define IMR_BCNDERR2_88E BIT(15) /* Beacon DMA Error Int 2 */
+#define IMR_BCNDERR1_88E BIT(14) /* Beacon DMA Error Int 1 */
+#define IMR_ATIMEND_E_88E BIT(13) /* ATIM Window End Ext for Win7 */
+#define IMR_TXERR_88E BIT(11) /* Tx Err Flag Int Status, write 1 clear. */
+#define IMR_RXERR_88E BIT(10) /* Rx Err Flag INT Status, Write 1 clear */
+#define IMR_TXFOVW_88E BIT(9) /* Transmit FIFO Overflow */
+#define IMR_RXFOVW_88E BIT(8) /* Receive FIFO Overflow */
+
+#define HAL_NIC_UNPLUG_ISR 0xFFFFFFFF /* The value when the NIC is unplugged for PCI. */
+
+/* 8192C EFUSE */
+#define HWSET_MAX_SIZE 256
+#define HWSET_MAX_SIZE_88E 512
+
+/*===================================================================
+=====================================================================
+Here the register defines are for 92C. When the define is as same with 92C,
+we will use the 92C's define for the consistency
+So the following defines for 92C is not entire!!!!!!
+=====================================================================
+=====================================================================*/
+/*
+ * Based on Datasheet V33---090401
+ * Register Summary
+ * Current IOREG MAP
+ * 0x0000h ~ 0x00FFh System Configuration (256 Bytes)
+ * 0x0100h ~ 0x01FFh MACTOP General Configuration (256 Bytes)
+ * 0x0200h ~ 0x027Fh TXDMA Configuration (128 Bytes)
+ * 0x0280h ~ 0x02FFh RXDMA Configuration (128 Bytes)
+ * 0x0300h ~ 0x03FFh PCIE EMAC Reserved Region (256 Bytes)
+ * 0x0400h ~ 0x04FFh Protocol Configuration (256 Bytes)
+ * 0x0500h ~ 0x05FFh EDCA Configuration (256 Bytes)
+ * 0x0600h ~ 0x07FFh WMAC Configuration (512 Bytes)
+ * 0x2000h ~ 0x3FFFh 8051 FW Download Region (8196 Bytes)
+ */
+/* 8192C (TXPAUSE) transmission pause (Offset 0x522, 8 bits) */
+/* Note:
+ * The bits of stopping AC(VO/VI/BE/BK) queue in datasheet
+ * RTL8192S/RTL8192C are wrong,
+ * the correct arragement is VO - Bit0, VI - Bit1, BE - Bit2,
+ * and BK - Bit3.
+ * 8723 and 88E may be not correct either in the earlier version.
+ */
+#define StopBecon BIT(6)
+#define StopHigh BIT(5)
+#define StopMgt BIT(4)
+#define StopBK BIT(3)
+#define StopBE BIT(2)
+#define StopVI BIT(1)
+#define StopVO BIT(0)
+
+/* 8192C (RCR) Receive Configuration Register(Offset 0x608, 32 bits) */
+#define RCR_APPFCS BIT(31) /* WMAC append FCS after payload */
+#define RCR_APP_MIC BIT(30)
+#define RCR_APP_PHYSTS BIT(28)
+#define RCR_APP_ICV BIT(29)
+#define RCR_APP_PHYST_RXFF BIT(28)
+#define RCR_APP_BA_SSN BIT(27) /* Accept BA SSN */
+#define RCR_ENMBID BIT(24) /* Enable Multiple BssId. */
+#define RCR_LSIGEN BIT(23)
+#define RCR_MFBEN BIT(22)
+#define RCR_HTC_LOC_CTRL BIT(14) /* MFC<--HTC=1 MFC-->HTC=0 */
+#define RCR_AMF BIT(13) /* Accept management type frame */
+#define RCR_ACF BIT(12) /* Accept control type frame */
+#define RCR_ADF BIT(11) /* Accept data type frame */
+#define RCR_AICV BIT(9) /* Accept ICV error packet */
+#define RCR_ACRC32 BIT(8) /* Accept CRC32 error packet */
+#define RCR_CBSSID_BCN BIT(7) /* Accept BSSID match packet
+ * (Rx beacon, probe rsp)
+ */
+#define RCR_CBSSID_DATA BIT(6) /* Accept BSSID match (Data)*/
+#define RCR_CBSSID RCR_CBSSID_DATA /* Accept BSSID match */
+#define RCR_APWRMGT BIT(5) /* Accept power management pkt*/
+#define RCR_ADD3 BIT(4) /* Accept address 3 match pkt */
+#define RCR_AB BIT(3) /* Accept broadcast packet */
+#define RCR_AM BIT(2) /* Accept multicast packet */
+#define RCR_APM BIT(1) /* Accept physical match pkt */
+#define RCR_AAP BIT(0) /* Accept all unicast packet */
+#define RCR_MXDMA_OFFSET 8
+#define RCR_FIFO_OFFSET 13
+
+/* 0xFE00h ~ 0xFE55h USB Configuration */
+#define REG_USB_INFO 0xFE17
+#define REG_USB_SPECIAL_OPTION 0xFE55
+#define REG_USB_DMA_AGG_TO 0xFE5B
+#define REG_USB_AGG_TO 0xFE5C
+#define REG_USB_AGG_TH 0xFE5D
+
+#define REG_USB_HRPWM 0xFE58
+#define REG_USB_HCPWM 0xFE57
+/* 8192C Register Bit and Content definition */
+/* 0x0000h ~ 0x00FFh System Configuration */
+
+/* 2 SYS_ISO_CTRL */
+#define ISO_MD2PP BIT(0)
+#define ISO_UA2USB BIT(1)
+#define ISO_UD2CORE BIT(2)
+#define ISO_PA2PCIE BIT(3)
+#define ISO_PD2CORE BIT(4)
+#define ISO_IP2MAC BIT(5)
+#define ISO_DIOP BIT(6)
+#define ISO_DIOE BIT(7)
+#define ISO_EB2CORE BIT(8)
+#define ISO_DIOR BIT(9)
+#define PWC_EV12V BIT(15)
+
+/* 2 SYS_FUNC_EN */
+#define FEN_BBRSTB BIT(0)
+#define FEN_BB_GLB_RSTn BIT(1)
+#define FEN_USBA BIT(2)
+#define FEN_UPLL BIT(3)
+#define FEN_USBD BIT(4)
+#define FEN_DIO_PCIE BIT(5)
+#define FEN_PCIEA BIT(6)
+#define FEN_PPLL BIT(7)
+#define FEN_PCIED BIT(8)
+#define FEN_DIOE BIT(9)
+#define FEN_CPUEN BIT(10)
+#define FEN_DCORE BIT(11)
+#define FEN_ELDR BIT(12)
+#define FEN_DIO_RF BIT(13)
+#define FEN_HWPDN BIT(14)
+#define FEN_MREGEN BIT(15)
+
+/* 2 APS_FSMCO */
+#define PFM_LDALL BIT(0)
+#define PFM_ALDN BIT(1)
+#define PFM_LDKP BIT(2)
+#define PFM_WOWL BIT(3)
+#define EnPDN BIT(4)
+#define PDN_PL BIT(5)
+#define APFM_ONMAC BIT(8)
+#define APFM_OFF BIT(9)
+#define APFM_RSM BIT(10)
+#define AFSM_HSUS BIT(11)
+#define AFSM_PCIE BIT(12)
+#define APDM_MAC BIT(13)
+#define APDM_HOST BIT(14)
+#define APDM_HPDN BIT(15)
+#define RDY_MACON BIT(16)
+#define SUS_HOST BIT(17)
+#define ROP_ALD BIT(20)
+#define ROP_PWR BIT(21)
+#define ROP_SPS BIT(22)
+#define SOP_MRST BIT(25)
+#define SOP_FUSE BIT(26)
+#define SOP_ABG BIT(27)
+#define SOP_AMB BIT(28)
+#define SOP_RCK BIT(29)
+#define SOP_A8M BIT(30)
+#define XOP_BTCK BIT(31)
+
+/* 2 SYS_CLKR */
+#define ANAD16V_EN BIT(0)
+#define ANA8M BIT(1)
+#define MACSLP BIT(4)
+#define LOADER_CLK_EN BIT(5)
+
+/* 2 9346CR */
+
+#define BOOT_FROM_EEPROM BIT(4)
+#define EEPROM_EN BIT(5)
+
+/* 2 SPS0_CTRL */
+
+/* 2 SPS_OCP_CFG */
+
+/* 2 RF_CTRL */
+#define RF_EN BIT(0)
+#define RF_RSTB BIT(1)
+#define RF_SDMRSTB BIT(2)
+
+/* 2 LDOV12D_CTRL */
+#define LDV12_EN BIT(0)
+#define LDV12_SDBY BIT(1)
+#define LPLDO_HSM BIT(2)
+#define LPLDO_LSM_DIS BIT(3)
+#define _LDV12_VADJ(x) (((x) & 0xF) << 4)
+
+/* 2EFUSE_CTRL */
+#define ALD_EN BIT(18)
+#define EF_PD BIT(19)
+#define EF_FLAG BIT(31)
+
+/* 2 EFUSE_TEST (For RTL8723 partially) */
+#define EF_TRPT BIT(7)
+/* 00: Wifi Efuse, 01: BT Efuse0, 10: BT Efuse1, 11: BT Efuse2 */
+#define EF_CELL_SEL (BIT(8) | BIT(9))
+#define LDOE25_EN BIT(31)
+#define EFUSE_SEL(x) (((x) & 0x3) << 8)
+#define EFUSE_SEL_MASK 0x300
+#define EFUSE_WIFI_SEL_0 0x0
+#define EFUSE_BT_SEL_0 0x1
+#define EFUSE_BT_SEL_1 0x2
+#define EFUSE_BT_SEL_2 0x3
+
+#define EFUSE_ACCESS_ON 0x69 /* For RTL8723 only. */
+#define EFUSE_ACCESS_OFF 0x00 /* For RTL8723 only. */
+
+/* 2 8051FWDL */
+/* 2 MCUFWDL */
+#define MCUFWDL_EN BIT(0)
+#define MCUFWDL_RDY BIT(1)
+#define FWDL_ChkSum_rpt BIT(2)
+#define MACINI_RDY BIT(3)
+#define BBINI_RDY BIT(4)
+#define RFINI_RDY BIT(5)
+#define WINTINI_RDY BIT(6)
+#define RAM_DL_SEL BIT(7) /* 1:RAM, 0:ROM */
+#define ROM_DLEN BIT(19)
+#define CPRST BIT(23)
+
+/* 2 REG_SYS_CFG */
+#define XCLK_VLD BIT(0)
+#define ACLK_VLD BIT(1)
+#define UCLK_VLD BIT(2)
+#define PCLK_VLD BIT(3)
+#define PCIRSTB BIT(4)
+#define V15_VLD BIT(5)
+#define SW_OFFLOAD_EN BIT(7)
+#define SIC_IDLE BIT(8)
+#define BD_MAC2 BIT(9)
+#define BD_MAC1 BIT(10)
+#define IC_MACPHY_MODE BIT(11)
+#define CHIP_VER (BIT(12) | BIT(13) | BIT(14) | BIT(15))
+#define BT_FUNC BIT(16)
+#define VENDOR_ID BIT(19)
+#define PAD_HWPD_IDN BIT(22)
+#define TRP_VAUX_EN BIT(23) /* RTL ID */
+#define TRP_BT_EN BIT(24)
+#define BD_PKG_SEL BIT(25)
+#define BD_HCI_SEL BIT(26)
+#define TYPE_ID BIT(27)
+
+#define CHIP_VER_RTL_MASK 0xF000 /* Bit 12 ~ 15 */
+#define CHIP_VER_RTL_SHIFT 12
+
+/* 2REG_GPIO_OUTSTS (For RTL8723 only) */
+#define EFS_HCI_SEL (BIT(0) | BIT(1))
+#define PAD_HCI_SEL (BIT(2) | BIT(3))
+#define HCI_SEL (BIT(4) | BIT(5))
+#define PKG_SEL_HCI BIT(6)
+#define FEN_GPS BIT(7)
+#define FEN_BT BIT(8)
+#define FEN_WL BIT(9)
+#define FEN_PCI BIT(10)
+#define FEN_USB BIT(11)
+#define BTRF_HWPDN_N BIT(12)
+#define WLRF_HWPDN_N BIT(13)
+#define PDN_BT_N BIT(14)
+#define PDN_GPS_N BIT(15)
+#define BT_CTL_HWPDN BIT(16)
+#define GPS_CTL_HWPDN BIT(17)
+#define PPHY_SUSB BIT(20)
+#define UPHY_SUSB BIT(21)
+#define PCI_SUSEN BIT(22)
+#define USB_SUSEN BIT(23)
+#define RF_RL_ID (BIT(31) | BIT(30) | BIT(29) | BIT(28))
+
+/* 2SYS_CFG */
+#define RTL_ID BIT(23) /* TestChip ID, 1:Test(RLE); 0:MP(RL) */
+
+/* 0x0100h ~ 0x01FFh MACTOP General Configuration */
+
+/* 2 Function Enable Registers */
+/* 2 CR */
+
+#define HCI_TXDMA_EN BIT(0)
+#define HCI_RXDMA_EN BIT(1)
+#define TXDMA_EN BIT(2)
+#define RXDMA_EN BIT(3)
+#define PROTOCOL_EN BIT(4)
+#define SCHEDULE_EN BIT(5)
+#define MACTXEN BIT(6)
+#define MACRXEN BIT(7)
+#define ENSWBCN BIT(8)
+#define ENSEC BIT(9)
+#define CALTMR_EN BIT(10) /* 32k CAL TMR enable */
+
+/* Network type */
+#define _NETTYPE(x) (((x) & 0x3) << 16)
+#define MASK_NETTYPE 0x30000
+#define NT_NO_LINK 0x0
+#define NT_LINK_AD_HOC 0x1
+#define NT_LINK_AP 0x2
+#define NT_AS_AP 0x3
+
+/* 2 PBP - Page Size Register */
+#define GET_RX_PAGE_SIZE(value) ((value) & 0xF)
+#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4)
+#define _PSRX_MASK 0xF
+#define _PSTX_MASK 0xF0
+#define _PSRX(x) (x)
+#define _PSTX(x) ((x) << 4)
+
+#define PBP_64 0x0
+#define PBP_128 0x1
+#define PBP_256 0x2
+#define PBP_512 0x3
+#define PBP_1024 0x4
+
+/* 2 TX/RXDMA */
+#define RXDMA_ARBBW_EN BIT(0)
+#define RXSHFT_EN BIT(1)
+#define RXDMA_AGG_EN BIT(2)
+#define QS_VO_QUEUE BIT(8)
+#define QS_VI_QUEUE BIT(9)
+#define QS_BE_QUEUE BIT(10)
+#define QS_BK_QUEUE BIT(11)
+#define QS_MANAGER_QUEUE BIT(12)
+#define QS_HIGH_QUEUE BIT(13)
+
+#define HQSEL_VOQ BIT(0)
+#define HQSEL_VIQ BIT(1)
+#define HQSEL_BEQ BIT(2)
+#define HQSEL_BKQ BIT(3)
+#define HQSEL_MGTQ BIT(4)
+#define HQSEL_HIQ BIT(5)
+
+/* For normal driver, 0x10C */
+#define _TXDMA_HIQ_MAP(x) (((x) & 0x3) << 14)
+#define _TXDMA_MGQ_MAP(x) (((x) & 0x3) << 12)
+#define _TXDMA_BKQ_MAP(x) (((x) & 0x3) << 10)
+#define _TXDMA_BEQ_MAP(x) (((x) & 0x3) << 8)
+#define _TXDMA_VIQ_MAP(x) (((x) & 0x3) << 6)
+#define _TXDMA_VOQ_MAP(x) (((x) & 0x3) << 4)
+
+#define QUEUE_LOW 1
+#define QUEUE_NORMAL 2
+#define QUEUE_HIGH 3
+
+/* 2 TRXFF_BNDY */
+
+/* 2 LLT_INIT */
+#define _LLT_NO_ACTIVE 0x0
+#define _LLT_WRITE_ACCESS 0x1
+#define _LLT_READ_ACCESS 0x2
+
+#define _LLT_INIT_DATA(x) ((x) & 0xFF)
+#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8)
+#define _LLT_OP(x) (((x) & 0x3) << 30)
+#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3)
+
+/* 0x0200h ~ 0x027Fh TXDMA Configuration */
+/* 2RQPN */
+#define _HPQ(x) ((x) & 0xFF)
+#define _LPQ(x) (((x) & 0xFF) << 8)
+#define _PUBQ(x) (((x) & 0xFF) << 16)
+/* NOTE: in RQPN_NPQ register */
+#define _NPQ(x) ((x) & 0xFF)
+
+#define HPQ_PUBLIC_DIS BIT(24)
+#define LPQ_PUBLIC_DIS BIT(25)
+#define LD_RQPN BIT(31)
+
+/* 2TDECTRL */
+#define BCN_VALID BIT(16)
+#define BCN_HEAD(x) (((x) & 0xFF) << 8)
+#define BCN_HEAD_MASK 0xFF00
+
+/* 2 TDECTL */
+#define BLK_DESC_NUM_SHIFT 4
+#define BLK_DESC_NUM_MASK 0xF
+
+/* 2 TXDMA_OFFSET_CHK */
+#define DROP_DATA_EN BIT(9)
+
+/* 0x0280h ~ 0x028Bh RX DMA Configuration */
+
+/* REG_RXDMA_CONTROL, 0x0286h */
+
+/* 2 REG_RXPKT_NUM, 0x0284 */
+#define RXPKT_RELEASE_POLL BIT(16)
+#define RXDMA_IDLE BIT(17)
+#define RW_RELEASE_EN BIT(18)
+
+/* 0x0400h ~ 0x047Fh Protocol Configuration */
+/* 2 FWHW_TXQ_CTRL */
+#define EN_AMPDU_RTY_NEW BIT(7)
+
+/* 2 SPEC SIFS */
+#define _SPEC_SIFS_CCK(x) ((x) & 0xFF)
+#define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8)
+
+/* 2 RL */
+#define RETRY_LIMIT_SHORT_SHIFT 8
+#define RETRY_LIMIT_LONG_SHIFT 0
+
+/* 0x0500h ~ 0x05FFh EDCA Configuration */
+
+/* 2 EDCA setting */
+#define AC_PARAM_TXOP_LIMIT_OFFSET 16
+#define AC_PARAM_ECW_MAX_OFFSET 12
+#define AC_PARAM_ECW_MIN_OFFSET 8
+#define AC_PARAM_AIFS_OFFSET 0
+
+#define _LRL(x) ((x) & 0x3F)
+#define _SRL(x) (((x) & 0x3F) << 8)
+
+/* 2 BCN_CTRL */
+#define EN_MBSSID BIT(1)
+#define EN_TXBCN_RPT BIT(2)
+#define EN_BCN_FUNCTION BIT(3)
+#define DIS_TSF_UPDATE BIT(3)
+
+/* The same function but different bit field. */
+#define DIS_TSF_UDT0_NORMAL_CHIP BIT(4)
+#define DIS_TSF_UDT0_TEST_CHIP BIT(5)
+#define STOP_BCNQ BIT(6)
+
+/* 2 ACMHWCTRL */
+#define AcmHw_HwEn BIT(0)
+#define AcmHw_BeqEn BIT(1)
+#define AcmHw_ViqEn BIT(2)
+#define AcmHw_VoqEn BIT(3)
+#define AcmHw_BeqStatus BIT(4)
+#define AcmHw_ViqStatus BIT(5)
+#define AcmHw_VoqStatus BIT(6)
+
+/* 0x0600h ~ 0x07FFh WMAC Configuration */
+/* 2APSD_CTRL */
+#define APSDOFF BIT(6)
+#define APSDOFF_STATUS BIT(7)
+
+#define RATE_BITMAP_ALL 0xFFFFF
+
+/* Only use CCK 1M rate for ACK */
+#define RATE_RRSR_CCK_ONLY_1M 0xFFFF1
+
+/* 2 TCR */
+#define TSFRST BIT(0)
+#define DIS_GCLK BIT(1)
+#define PAD_SEL BIT(2)
+#define PWR_ST BIT(6)
+#define PWRBIT_OW_EN BIT(7)
+#define ACRC BIT(8)
+#define CFENDFORM BIT(9)
+#define ICV BIT(10)
+
+/* 2 RCR */
+#define AAP BIT(0)
+#define APM BIT(1)
+#define AM BIT(2)
+#define AB BIT(3)
+#define ADD3 BIT(4)
+#define APWRMGT BIT(5)
+#define CBSSID BIT(6)
+#define CBSSID_DATA BIT(6)
+#define CBSSID_BCN BIT(7)
+#define ACRC32 BIT(8)
+#define AICV BIT(9)
+#define ADF BIT(11)
+#define ACF BIT(12)
+#define AMF BIT(13)
+#define HTC_LOC_CTRL BIT(14)
+#define UC_DATA_EN BIT(16)
+#define BM_DATA_EN BIT(17)
+#define MFBEN BIT(22)
+#define LSIGEN BIT(23)
+#define EnMBID BIT(24)
+#define APP_BASSN BIT(27)
+#define APP_PHYSTS BIT(28)
+#define APP_ICV BIT(29)
+#define APP_MIC BIT(30)
+#define APP_FCS BIT(31)
+
+/* 2 SECCFG */
+#define SCR_TxUseDK BIT(0) /* Force Tx Use Default Key */
+#define SCR_RxUseDK BIT(1) /* Force Rx Use Default Key */
+#define SCR_TxEncEnable BIT(2) /* Enable Tx Encryption */
+#define SCR_RxDecEnable BIT(3) /* Enable Rx Decryption */
+#define SCR_SKByA2 BIT(4) /* Search kEY BY A2 */
+#define SCR_NoSKMC BIT(5) /* No Key Search Multicast */
+#define SCR_TXBCUSEDK BIT(6) /* Force Tx Bcast pkt Use Default Key */
+#define SCR_RXBCUSEDK BIT(7) /* Force Rx Bcast pkt Use Default Key */
+
+/* RTL8188E SDIO Configuration */
+
+/* I/O bus domain address mapping */
+#define SDIO_LOCAL_BASE 0x10250000
+#define WLAN_IOREG_BASE 0x10260000
+#define FIRMWARE_FIFO_BASE 0x10270000
+#define TX_HIQ_BASE 0x10310000
+#define TX_MIQ_BASE 0x10320000
+#define TX_LOQ_BASE 0x10330000
+#define RX_RX0FF_BASE 0x10340000
+
+/* SDIO host local register space mapping. */
+#define SDIO_LOCAL_MSK 0x0FFF
+#define WLAN_IOREG_MSK 0x7FFF
+#define WLAN_FIFO_MSK 0x1FFF /* Aggregation Length[12:0] */
+#define WLAN_RX0FF_MSK 0x0003
+
+/* Without ref to the SDIO Device ID */
+#define SDIO_WITHOUT_REF_DEVICE_ID 0
+#define SDIO_LOCAL_DEVICE_ID 0 /* 0b[16], 000b[15:13] */
+#define WLAN_TX_HIQ_DEVICE_ID 4 /* 0b[16], 100b[15:13] */
+#define WLAN_TX_MIQ_DEVICE_ID 5 /* 0b[16], 101b[15:13] */
+#define WLAN_TX_LOQ_DEVICE_ID 6 /* 0b[16], 110b[15:13] */
+#define WLAN_RX0FF_DEVICE_ID 7 /* 0b[16], 111b[15:13] */
+#define WLAN_IOREG_DEVICE_ID 8 /* 1b[16] */
+
+/* SDIO Tx Free Page Index */
+#define HI_QUEUE_IDX 0
+#define MID_QUEUE_IDX 1
+#define LOW_QUEUE_IDX 2
+#define PUBLIC_QUEUE_IDX 3
+
+#define SDIO_MAX_TX_QUEUE 3 /* HIQ, MIQ and LOQ */
+#define SDIO_MAX_RX_QUEUE 1
+
+/* SDIO Tx Control */
+#define SDIO_REG_TX_CTRL 0x0000
+/* SDIO Host Interrupt Mask */
+#define SDIO_REG_HIMR 0x0014
+/* SDIO Host Interrupt Service Routine */
+#define SDIO_REG_HISR 0x0018
+/* HCI Current Power Mode */
+#define SDIO_REG_HCPWM 0x0019
+/* RXDMA Request Length */
+#define SDIO_REG_RX0_REQ_LEN 0x001C
+/* Free Tx Buffer Page */
+#define SDIO_REG_FREE_TXPG 0x0020
+/* HCI Current Power Mode 1 */
+#define SDIO_REG_HCPWM1 0x0024
+/* HCI Current Power Mode 2 */
+#define SDIO_REG_HCPWM2 0x0026
+/* HTSF Informaion */
+#define SDIO_REG_HTSFR_INFO 0x0030
+/* HCI Request Power Mode 1 */
+#define SDIO_REG_HRPWM1 0x0080
+/* HCI Request Power Mode 2 */
+#define SDIO_REG_HRPWM2 0x0082
+/* HCI Power Save Clock */
+#define SDIO_REG_HPS_CLKR 0x0084
+/* SDIO HCI Suspend Control */
+#define SDIO_REG_HSUS_CTRL 0x0086
+/* SDIO Host Extension Interrupt Mask Always */
+#define SDIO_REG_HIMR_ON 0x0090
+/* SDIO Host Extension Interrupt Status Always */
+#define SDIO_REG_HISR_ON 0x0091
+
+#define SDIO_HIMR_DISABLED 0
+
+/* RTL8188E SDIO Host Interrupt Mask Register */
+#define SDIO_HIMR_RX_REQUEST_MSK BIT(0)
+#define SDIO_HIMR_AVAL_MSK BIT(1)
+#define SDIO_HIMR_TXERR_MSK BIT(2)
+#define SDIO_HIMR_RXERR_MSK BIT(3)
+#define SDIO_HIMR_TXFOVW_MSK BIT(4)
+#define SDIO_HIMR_RXFOVW_MSK BIT(5)
+#define SDIO_HIMR_TXBCNOK_MSK BIT(6)
+#define SDIO_HIMR_TXBCNERR_MSK BIT(7)
+#define SDIO_HIMR_BCNERLY_INT_MSK BIT(16)
+#define SDIO_HIMR_C2HCMD_MSK BIT(17)
+#define SDIO_HIMR_CPWM1_MSK BIT(18)
+#define SDIO_HIMR_CPWM2_MSK BIT(19)
+#define SDIO_HIMR_HSISR_IND_MSK BIT(20)
+#define SDIO_HIMR_GTINT3_IND_MSK BIT(21)
+#define SDIO_HIMR_GTINT4_IND_MSK BIT(22)
+#define SDIO_HIMR_PSTIMEOUT_MSK BIT(23)
+#define SDIO_HIMR_OCPINT_MSK BIT(24)
+#define SDIO_HIMR_ATIMEND_MSK BIT(25)
+#define SDIO_HIMR_ATIMEND_E_MSK BIT(26)
+#define SDIO_HIMR_CTWEND_MSK BIT(27)
+
+/* RTL8188E SDIO Specific */
+#define SDIO_HIMR_MCU_ERR_MSK BIT(28)
+#define SDIO_HIMR_TSF_BIT32_TOGGLE_MSK BIT(29)
+
+/* SDIO Host Interrupt Service Routine */
+#define SDIO_HISR_RX_REQUEST BIT(0)
+#define SDIO_HISR_AVAL BIT(1)
+#define SDIO_HISR_TXERR BIT(2)
+#define SDIO_HISR_RXERR BIT(3)
+#define SDIO_HISR_TXFOVW BIT(4)
+#define SDIO_HISR_RXFOVW BIT(5)
+#define SDIO_HISR_TXBCNOK BIT(6)
+#define SDIO_HISR_TXBCNERR BIT(7)
+#define SDIO_HISR_BCNERLY_INT BIT(16)
+#define SDIO_HISR_C2HCMD BIT(17)
+#define SDIO_HISR_CPWM1 BIT(18)
+#define SDIO_HISR_CPWM2 BIT(19)
+#define SDIO_HISR_HSISR_IND BIT(20)
+#define SDIO_HISR_GTINT3_IND BIT(21)
+#define SDIO_HISR_GTINT4_IND BIT(22)
+#define SDIO_HISR_PSTIME BIT(23)
+#define SDIO_HISR_OCPINT BIT(24)
+#define SDIO_HISR_ATIMEND BIT(25)
+#define SDIO_HISR_ATIMEND_E BIT(26)
+#define SDIO_HISR_CTWEND BIT(27)
+
+/* RTL8188E SDIO Specific */
+#define SDIO_HISR_MCU_ERR BIT(28)
+#define SDIO_HISR_TSF_BIT32_TOGGLE BIT(29)
+
+#define MASK_SDIO_HISR_CLEAR \
+ (SDIO_HISR_TXERR | SDIO_HISR_RXERR | SDIO_HISR_TXFOVW |\
+ SDIO_HISR_RXFOVW | SDIO_HISR_TXBCNOK | SDIO_HISR_TXBCNERR |\
+ SDIO_HISR_C2HCMD | SDIO_HISR_CPWM1 | SDIO_HISR_CPWM2 |\
+ SDIO_HISR_HSISR_IND | SDIO_HISR_GTINT3_IND | SDIO_HISR_GTINT4_IND |\
+ SDIO_HISR_PSTIMEOUT | SDIO_HISR_OCPINT)
+
+/* SDIO HCI Suspend Control Register */
+#define HCI_RESUME_PWR_RDY BIT(1)
+#define HCI_SUS_CTRL BIT(0)
+
+/* SDIO Tx FIFO related */
+/* The number of Tx FIFO free page */
+#define SDIO_TX_FREE_PG_QUEUE 4
+#define SDIO_TX_FIFO_PAGE_SZ 128
+
+/* 0xFE00h ~ 0xFE55h USB Configuration */
+
+/* 2 USB Information (0xFE17) */
+#define USB_IS_HIGH_SPEED 0
+#define USB_IS_FULL_SPEED 1
+#define USB_SPEED_MASK BIT(5)
+
+#define USB_NORMAL_SIE_EP_MASK 0xF
+#define USB_NORMAL_SIE_EP_SHIFT 4
+
+/* 2 Special Option */
+#define USB_AGG_EN BIT(3)
+
+/* 0; Use interrupt endpoint to upload interrupt pkt */
+/* 1; Use bulk endpoint to upload interrupt pkt, */
+#define INT_BULK_SEL BIT(4)
+
+/* 2REG_C2HEVT_CLEAR */
+/* Set by driver and notify FW that the driver has read
+ * the C2H command message
+ */
+#define C2H_EVT_HOST_CLOSE 0x00
+/* Set by FW indicating that FW had set the C2H command
+ * message and it's not yet read by driver.
+ */
+#define C2H_EVT_FW_CLOSE 0xFF
+
+/* 2REG_MULTI_FUNC_CTRL(For RTL8723 Only) */
+/* Enable GPIO[9] as WiFi HW PDn source */
+#define WL_HWPDN_EN BIT(0)
+/* WiFi HW PDn polarity control */
+#define WL_HWPDN_SL BIT(1)
+/* WiFi function enable */
+#define WL_FUNC_EN BIT(2)
+/* Enable GPIO[9] as WiFi RF HW PDn source */
+#define WL_HWROF_EN BIT(3)
+/* Enable GPIO[11] as BT HW PDn source */
+#define BT_HWPDN_EN BIT(16)
+/* BT HW PDn polarity control */
+#define BT_HWPDN_SL BIT(17)
+/* BT function enable */
+#define BT_FUNC_EN BIT(18)
+/* Enable GPIO[11] as BT/GPS RF HW PDn source */
+#define BT_HWROF_EN BIT(19)
+/* Enable GPIO[10] as GPS HW PDn source */
+#define GPS_HWPDN_EN BIT(20)
+/* GPS HW PDn polarity control */
+#define GPS_HWPDN_SL BIT(21)
+/* GPS function enable */
+#define GPS_FUNC_EN BIT(22)
+
+/* 3 REG_LIFECTRL_CTRL */
+#define HAL92C_EN_PKT_LIFE_TIME_BK BIT(3)
+#define HAL92C_EN_PKT_LIFE_TIME_BE BIT(2)
+#define HAL92C_EN_PKT_LIFE_TIME_VI BIT(1)
+#define HAL92C_EN_PKT_LIFE_TIME_VO BIT(0)
+
+#define HAL92C_MSDU_LIFE_TIME_UNIT 128 /* in us */
+
+/* General definitions */
+#define LAST_ENTRY_OF_TX_PKT_BUFFER 176 /* 22k 22528 bytes */
+
+#define POLLING_LLT_THRESHOLD 20
+#define POLLING_READY_TIMEOUT_COUNT 1000
+/* GPIO BIT */
+#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2)
+
+/* 8192C EEPROM/EFUSE share register definition. */
+
+/* EEPROM/Efuse PG Offset for 88EE/88EU/88ES */
+#define EEPROM_TX_PWR_INX_88E 0x10
+
+#define EEPROM_ChannelPlan_88E 0xB8
+#define EEPROM_XTAL_88E 0xB9
+#define EEPROM_THERMAL_METER_88E 0xBA
+#define EEPROM_IQK_LCK_88E 0xBB
+
+#define EEPROM_RF_BOARD_OPTION_88E 0xC1
+#define EEPROM_RF_FEATURE_OPTION_88E 0xC2
+#define EEPROM_RF_BT_SETTING_88E 0xC3
+#define EEPROM_VERSION_88E 0xC4
+#define EEPROM_CUSTOMERID_88E 0xC5
+#define EEPROM_RF_ANTENNA_OPT_88E 0xC9
+
+/* RTL88EE */
+#define EEPROM_MAC_ADDR_88EE 0xD0
+#define EEPROM_VID_88EE 0xD6
+#define EEPROM_DID_88EE 0xD8
+#define EEPROM_SVID_88EE 0xDA
+#define EEPROM_SMID_88EE 0xDC
+
+/* RTL88EU */
+#define EEPROM_MAC_ADDR_88EU 0xD7
+#define EEPROM_VID_88EU 0xD0
+#define EEPROM_PID_88EU 0xD2
+#define EEPROM_USB_OPTIONAL_FUNCTION0 0xD4
+
+/* RTL88ES */
+#define EEPROM_MAC_ADDR_88ES 0x11A
+
+/* EEPROM/Efuse Value Type */
+#define EETYPE_TX_PWR 0x0
+
+/* Default Value for EEPROM or EFUSE!!! */
+#define EEPROM_Default_TSSI 0x0
+#define EEPROM_Default_TxPowerDiff 0x0
+#define EEPROM_Default_CrystalCap 0x5
+/* Default: 2X2, RTL8192CE(QFPN68) */
+#define EEPROM_Default_BoardType 0x02
+#define EEPROM_Default_TxPower 0x1010
+#define EEPROM_Default_HT2T_TxPwr 0x10
+
+#define EEPROM_Default_LegacyHTTxPowerDiff 0x3
+#define EEPROM_Default_ThermalMeter 0x12
+
+#define EEPROM_Default_AntTxPowerDiff 0x0
+#define EEPROM_Default_TxPwDiff_CrystalCap 0x5
+#define EEPROM_Default_TxPowerLevel 0x2A
+
+#define EEPROM_Default_HT40_2SDiff 0x0
+/* HT20<->40 default Tx Power Index Difference */
+#define EEPROM_Default_HT20_Diff 2
+#define EEPROM_Default_LegacyHTTxPowerDiff 0x3
+#define EEPROM_Default_HT40_PwrMaxOffset 0
+#define EEPROM_Default_HT20_PwrMaxOffset 0
+
+#define EEPROM_Default_CrystalCap_88E 0x20
+#define EEPROM_Default_ThermalMeter_88E 0x18
+
+/* New EFUSE default value */
+#define EEPROM_DEFAULT_24G_INDEX 0x2D
+#define EEPROM_DEFAULT_24G_HT20_DIFF 0X02
+#define EEPROM_DEFAULT_24G_OFDM_DIFF 0X04
+
+#define EEPROM_DEFAULT_5G_INDEX 0X2A
+#define EEPROM_DEFAULT_5G_HT20_DIFF 0X00
+#define EEPROM_DEFAULT_5G_OFDM_DIFF 0X04
+
+#define EEPROM_DEFAULT_DIFF 0XFE
+#define EEPROM_DEFAULT_CHANNEL_PLAN 0x7F
+#define EEPROM_DEFAULT_BOARD_OPTION 0x00
+#define EEPROM_DEFAULT_FEATURE_OPTION 0x00
+#define EEPROM_DEFAULT_BT_OPTION 0x10
+
+/* For debug */
+#define EEPROM_Default_PID 0x1234
+#define EEPROM_Default_VID 0x5678
+#define EEPROM_Default_CustomerID 0xAB
+#define EEPROM_Default_CustomerID_8188E 0x00
+#define EEPROM_Default_SubCustomerID 0xCD
+#define EEPROM_Default_Version 0
+
+#define EEPROM_CHANNEL_PLAN_FCC 0x0
+#define EEPROM_CHANNEL_PLAN_IC 0x1
+#define EEPROM_CHANNEL_PLAN_ETSI 0x2
+#define EEPROM_CHANNEL_PLAN_SPA 0x3
+#define EEPROM_CHANNEL_PLAN_FRANCE 0x4
+#define EEPROM_CHANNEL_PLAN_MKK 0x5
+#define EEPROM_CHANNEL_PLAN_MKK1 0x6
+#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7
+#define EEPROM_CHANNEL_PLAN_TELEC 0x8
+#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMA 0x9
+#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA
+#define EEPROM_CHANNEL_PLAN_NCC 0xB
+#define EEPROM_USB_OPTIONAL1 0xE
+#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80
+
+#define EEPROM_CID_DEFAULT 0x0
+#define EEPROM_CID_TOSHIBA 0x4
+#define EEPROM_CID_CCX 0x10 /* CCX test. */
+#define EEPROM_CID_QMI 0x0D
+#define EEPROM_CID_WHQL 0xFE
+#define RTL_EEPROM_ID 0x8129
+
+#endif /* __RTL8188E_SPEC_H__ */
diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h b/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h
new file mode 100644
index 0000000..421e9f4
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtl8188e_xmit.h
@@ -0,0 +1,160 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __RTL8188E_XMIT_H__
+#define __RTL8188E_XMIT_H__
+
+#define MAX_TX_AGG_PACKET_NUMBER 0xFF
+/* */
+/* Queue Select Value in TxDesc */
+/* */
+#define QSLT_BK 0x2/* 0x01 */
+#define QSLT_BE 0x0
+#define QSLT_VI 0x5/* 0x4 */
+#define QSLT_VO 0x7/* 0x6 */
+#define QSLT_BEACON 0x10
+#define QSLT_HIGH 0x11
+#define QSLT_MGNT 0x12
+#define QSLT_CMD 0x13
+
+/* For 88e early mode */
+#define SET_EARLYMODE_PKTNUM(__pAddr, __Value) \
+ SET_BITS_TO_LE_4BYTE(__pAddr, 0, 3, __Value)
+#define SET_EARLYMODE_LEN0(__pAddr, __Value) \
+ SET_BITS_TO_LE_4BYTE(__pAddr, 4, 12, __Value)
+#define SET_EARLYMODE_LEN1(__pAddr, __Value) \
+ SET_BITS_TO_LE_4BYTE(__pAddr, 16, 12, __Value)
+#define SET_EARLYMODE_LEN2_1(__pAddr, __Value) \
+ SET_BITS_TO_LE_4BYTE(__pAddr, 28, 4, __Value)
+#define SET_EARLYMODE_LEN2_2(__pAddr, __Value) \
+ SET_BITS_TO_LE_4BYTE(__pAddr+4, 0, 8, __Value)
+#define SET_EARLYMODE_LEN3(__pAddr, __Value) \
+ SET_BITS_TO_LE_4BYTE(__pAddr+4, 8, 12, __Value)
+#define SET_EARLYMODE_LEN4(__pAddr, __Value) \
+ SET_BITS_TO_LE_4BYTE(__pAddr+4, 20, 12, __Value)
+
+/* */
+/* defined for TX DESC Operation */
+/* */
+
+#define MAX_TID (15)
+
+/* OFFSET 0 */
+#define OFFSET_SZ 0
+#define OFFSET_SHT 16
+#define BMC BIT(24)
+#define LSG BIT(26)
+#define FSG BIT(27)
+#define OWN BIT(31)
+
+
+/* OFFSET 4 */
+#define PKT_OFFSET_SZ 0
+#define QSEL_SHT 8
+#define RATE_ID_SHT 16
+#define NAVUSEHDR BIT(20)
+#define SEC_TYPE_SHT 22
+#define PKT_OFFSET_SHT 26
+
+/* OFFSET 8 */
+#define AGG_EN BIT(12)
+#define AGG_BK BIT(16)
+#define AMPDU_DENSITY_SHT 20
+#define ANTSEL_A BIT(24)
+#define ANTSEL_B BIT(25)
+#define TX_ANT_CCK_SHT 26
+#define TX_ANTL_SHT 28
+#define TX_ANT_HT_SHT 30
+
+/* OFFSET 12 */
+#define SEQ_SHT 16
+#define EN_HWSEQ BIT(31)
+
+/* OFFSET 16 */
+#define QOS BIT(6)
+#define HW_SSN BIT(7)
+#define USERATE BIT(8)
+#define DISDATAFB BIT(10)
+#define CTS_2_SELF BIT(11)
+#define RTS_EN BIT(12)
+#define HW_RTS_EN BIT(13)
+#define DATA_SHORT BIT(24)
+#define PWR_STATUS_SHT 15
+#define DATA_SC_SHT 20
+#define DATA_BW BIT(25)
+
+/* OFFSET 20 */
+#define RTY_LMT_EN BIT(17)
+
+enum TXDESC_SC {
+ SC_DONT_CARE = 0x00,
+ SC_UPPER = 0x01,
+ SC_LOWER = 0x02,
+ SC_DUPLICATE = 0x03
+};
+/* OFFSET 20 */
+#define SGI BIT(6)
+#define USB_TXAGG_NUM_SHT 24
+
+#define txdesc_set_ccx_sw_88e(txdesc, value) \
+ do { \
+ ((struct txdesc_88e *)(txdesc))->sw1 = (((value)>>8) & 0x0f); \
+ ((struct txdesc_88e *)(txdesc))->sw0 = ((value) & 0xff); \
+ } while (0)
+
+struct txrpt_ccx_88e {
+ /* offset 0 */
+ u8 tag1:1;
+ u8 pkt_num:3;
+ u8 txdma_underflow:1;
+ u8 int_bt:1;
+ u8 int_tri:1;
+ u8 int_ccx:1;
+
+ /* offset 1 */
+ u8 mac_id:6;
+ u8 pkt_ok:1;
+ u8 bmc:1;
+
+ /* offset 2 */
+ u8 retry_cnt:6;
+ u8 lifetime_over:1;
+ u8 retry_over:1;
+
+ /* offset 3 */
+ u8 ccx_qtime0;
+ u8 ccx_qtime1;
+
+ /* offset 5 */
+ u8 final_data_rate;
+
+ /* offset 6 */
+ u8 sw1:4;
+ u8 qsel:4;
+
+ /* offset 7 */
+ u8 sw0;
+};
+
+#define txrpt_ccx_sw_88e(txrpt_ccx) ((txrpt_ccx)->sw0 + ((txrpt_ccx)->sw1<<8))
+#define txrpt_ccx_qtime_88e(txrpt_ccx) \
+ ((txrpt_ccx)->ccx_qtime0+((txrpt_ccx)->ccx_qtime1<<8))
+
+void rtl8188e_fill_fake_txdesc(struct adapter *padapter, u8 *pDesc,
+ u32 BufferLen, u8 IsPsPoll, u8 IsBTQosNull);
+s32 rtl8188eu_init_xmit_priv(struct adapter *padapter);
+s32 rtl8188eu_xmit_buf_handler(struct adapter *padapter);
+#define hal_xmit_handler rtl8188eu_xmit_buf_handler
+void rtl8188eu_xmit_tasklet(void *priv);
+bool rtl8188eu_xmitframe_complete(struct adapter *padapter,
+ struct xmit_priv *pxmitpriv);
+
+void handle_txrpt_ccx_88e(struct adapter *adapter, u8 *buf);
+
+void _dbg_dump_tx_info(struct adapter *padapter, int frame_tag,
+ struct tx_desc *ptxdesc);
+
+#endif /* __RTL8188E_XMIT_H__ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_android.h b/drivers/staging/rtl8188eu/include/rtw_android.h
new file mode 100644
index 0000000..d7ca7c2
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtw_android.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#ifndef __RTW_ANDROID_H__
+#define __RTW_ANDROID_H__
+
+#include <linux/module.h>
+#include <linux/netdevice.h>
+
+enum ANDROID_WIFI_CMD {
+ ANDROID_WIFI_CMD_START,
+ ANDROID_WIFI_CMD_STOP,
+ ANDROID_WIFI_CMD_SCAN_ACTIVE,
+ ANDROID_WIFI_CMD_SCAN_PASSIVE,
+ ANDROID_WIFI_CMD_RSSI,
+ ANDROID_WIFI_CMD_LINKSPEED,
+ ANDROID_WIFI_CMD_RXFILTER_START,
+ ANDROID_WIFI_CMD_RXFILTER_STOP,
+ ANDROID_WIFI_CMD_RXFILTER_ADD,
+ ANDROID_WIFI_CMD_RXFILTER_REMOVE,
+ ANDROID_WIFI_CMD_BTCOEXSCAN_START,
+ ANDROID_WIFI_CMD_BTCOEXSCAN_STOP,
+ ANDROID_WIFI_CMD_BTCOEXMODE,
+ ANDROID_WIFI_CMD_SETSUSPENDOPT,
+ ANDROID_WIFI_CMD_P2P_DEV_ADDR,
+ ANDROID_WIFI_CMD_SETFWPATH,
+ ANDROID_WIFI_CMD_SETBAND,
+ ANDROID_WIFI_CMD_GETBAND,
+ ANDROID_WIFI_CMD_COUNTRY,
+ ANDROID_WIFI_CMD_P2P_SET_NOA,
+ ANDROID_WIFI_CMD_P2P_GET_NOA,
+ ANDROID_WIFI_CMD_P2P_SET_PS,
+ ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE,
+ ANDROID_WIFI_CMD_MACADDR,
+ ANDROID_WIFI_CMD_BLOCK,
+ ANDROID_WIFI_CMD_WFD_ENABLE,
+ ANDROID_WIFI_CMD_WFD_DISABLE,
+ ANDROID_WIFI_CMD_WFD_SET_TCPPORT,
+ ANDROID_WIFI_CMD_WFD_SET_MAX_TPUT,
+ ANDROID_WIFI_CMD_WFD_SET_DEVTYPE,
+ ANDROID_WIFI_CMD_MAX
+};
+
+int rtw_android_cmdstr_to_num(char *cmdstr);
+int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd);
+
+#endif /* __RTW_ANDROID_H__ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_ap.h b/drivers/staging/rtl8188eu/include/rtw_ap.h
new file mode 100644
index 0000000..bc0bf20
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtw_ap.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __RTW_AP_H_
+#define __RTW_AP_H_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+
+#ifdef CPTCFG_88EU_AP_MODE
+
+/* external function */
+void rtw_indicate_sta_assoc_event(struct adapter *padapter,
+ struct sta_info *psta);
+void rtw_indicate_sta_disassoc_event(struct adapter *padapter,
+ struct sta_info *psta);
+void init_mlme_ap_info(struct adapter *padapter);
+void free_mlme_ap_info(struct adapter *padapter);
+void update_beacon(struct adapter *padapter, u8 ie_id,
+ u8 *oui, u8 tx);
+void add_RATid(struct adapter *padapter, struct sta_info *psta,
+ u8 rssi_level);
+void expire_timeout_chk(struct adapter *padapter);
+void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta);
+int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len);
+void rtw_set_macaddr_acl(struct adapter *padapter, int mode);
+int rtw_acl_add_sta(struct adapter *padapter, u8 *addr);
+int rtw_acl_remove_sta(struct adapter *padapter, u8 *addr);
+
+void associated_clients_update(struct adapter *padapter, u8 updated);
+void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta);
+u8 bss_cap_update_on_sta_leave(struct adapter *padapter, struct sta_info *psta);
+void sta_info_update(struct adapter *padapter, struct sta_info *psta);
+void ap_sta_info_defer_update(struct adapter *padapter, struct sta_info *psta);
+u8 ap_free_sta(struct adapter *padapter, struct sta_info *psta,
+ bool active, u16 reason);
+int rtw_sta_flush(struct adapter *padapter);
+void start_ap_mode(struct adapter *padapter);
+void stop_ap_mode(struct adapter *padapter);
+#endif /* end of CPTCFG_88EU_AP_MODE */
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/rtw_cmd.h b/drivers/staging/rtl8188eu/include/rtw_cmd.h
new file mode 100644
index 0000000..216d711
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtw_cmd.h
@@ -0,0 +1,384 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __RTW_CMD_H_
+#define __RTW_CMD_H_
+
+#include <wlan_bssdef.h>
+#include <rtw_rf.h>
+#include <rtw_led.h>
+
+#include <osdep_service.h>
+#include <ieee80211.h> /* <ieee80211/ieee80211.h> */
+
+#define MAX_CMDSZ 1024
+#define MAX_RSPSZ 512
+
+#define CMDBUFF_ALIGN_SZ 512
+
+struct cmd_obj {
+ struct adapter *padapter;
+ u16 cmdcode;
+ u8 res;
+ u8 *parmbuf;
+ u32 cmdsz;
+ u8 *rsp;
+ u32 rspsz;
+ struct list_head list;
+};
+
+struct cmd_priv {
+ struct completion cmd_queue_comp;
+ struct completion terminate_cmdthread_comp;
+ struct __queue cmd_queue;
+ u8 cmdthd_running;
+ struct adapter *padapter;
+};
+
+#define init_h2fwcmd_w_parm_no_rsp(pcmd, pparm, code) \
+do {\
+ INIT_LIST_HEAD(&pcmd->list);\
+ pcmd->cmdcode = code;\
+ pcmd->parmbuf = (u8 *)(pparm);\
+ pcmd->cmdsz = sizeof(*pparm);\
+ pcmd->rsp = NULL;\
+ pcmd->rspsz = 0;\
+} while (0)
+
+u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *obj);
+struct cmd_obj *rtw_dequeue_cmd(struct __queue *queue);
+void rtw_free_cmd_obj(struct cmd_obj *pcmd);
+
+int rtw_cmd_thread(void *context);
+
+int rtw_init_cmd_priv(struct cmd_priv *pcmdpriv);
+
+enum rtw_drvextra_cmd_id {
+ NONE_WK_CID,
+ DYNAMIC_CHK_WK_CID,
+ DM_CTRL_WK_CID,
+ PBC_POLLING_WK_CID,
+ POWER_SAVING_CTRL_WK_CID,/* IPS,AUTOSuspend */
+ LPS_CTRL_WK_CID,
+ ANT_SELECT_WK_CID,
+ P2P_PS_WK_CID,
+ P2P_PROTO_WK_CID,
+ CHECK_HIQ_WK_CID,/* for softap mode, check hi queue if empty */
+ INTEl_WIDI_WK_CID,
+ C2H_WK_CID,
+ RTP_TIMER_CFG_WK_CID,
+ MAX_WK_CID
+};
+
+enum LPS_CTRL_TYPE {
+ LPS_CTRL_SCAN = 0,
+ LPS_CTRL_JOINBSS = 1,
+ LPS_CTRL_CONNECT = 2,
+ LPS_CTRL_DISCONNECT = 3,
+ LPS_CTRL_SPECIAL_PACKET = 4,
+ LPS_CTRL_LEAVE = 5,
+};
+
+enum RFINTFS {
+ SWSI,
+ HWSI,
+ HWPI,
+};
+
+/*
+ * Caller Mode: Infra, Ad-HoC(C)
+ *
+ * Notes: To disconnect the current associated BSS
+ *
+ * Command Mode
+ *
+ */
+struct disconnect_parm {
+ u32 deauth_timeout_ms;
+};
+
+struct setopmode_parm {
+ u8 mode;
+ u8 rsvd[3];
+};
+
+/*
+ * Caller Mode: AP, Ad-HoC, Infra
+ *
+ * Notes: To ask RTL8711 performing site-survey
+ *
+ * Command-Event Mode
+ *
+ */
+
+#define RTW_SSID_SCAN_AMOUNT 9 /* for WEXT_CSCAN_AMOUNT 9 */
+#define RTW_CHANNEL_SCAN_AMOUNT (14+37)
+struct sitesurvey_parm {
+ int scan_mode; /* active: 1, passive: 0 */
+ u8 ssid_num;
+ u8 ch_num;
+ struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT];
+ struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT];
+};
+
+/*
+ * Caller Mode: Any
+ *
+ * Notes: To set the auth type of RTL8711. open/shared/802.1x
+ *
+ * Command Mode
+ *
+ */
+struct setauth_parm {
+ u8 mode; /* 0: legacy open, 1: legacy shared 2: 802.1x */
+ u8 _1x; /* 0: PSK, 1: TLS */
+ u8 rsvd[2];
+};
+
+/*
+ * Caller Mode: Infra
+ *
+ * a. algorithm: wep40, wep104, tkip & aes
+ * b. keytype: grp key/unicast key
+ * c. key contents
+ *
+ * when shared key ==> keyid is the camid
+ * when 802.1x ==> keyid [0:1] ==> grp key
+ * when 802.1x ==> keyid > 2 ==> unicast key
+ *
+ */
+struct setkey_parm {
+ u8 algorithm; /* could be none, wep40, TKIP, CCMP, wep104 */
+ u8 keyid;
+ u8 grpkey; /* 1: this is the grpkey for 802.1x.
+ * 0: this is the unicast key for 802.1x
+ */
+ u8 set_tx; /* 1: main tx key for wep. 0: other key. */
+ u8 key[16]; /* this could be 40 or 104 */
+};
+
+/*
+ * When in AP or Ad-Hoc mode, this is used to
+ * allocate an sw/hw entry for a newly associated sta.
+ *
+ * Command
+ *
+ * when shared key ==> algorithm/keyid
+ *
+ */
+struct set_stakey_parm {
+ u8 addr[ETH_ALEN];
+ u8 algorithm;
+ u8 id;/* currently for erasing cam entry if
+ * algorithm == _NO_PRIVACY_
+ */
+ u8 key[16];
+};
+
+struct set_stakey_rsp {
+ u8 addr[ETH_ALEN];
+ u8 keyid;
+ u8 rsvd;
+};
+
+/*
+ * Caller Ad-Hoc/AP
+ *
+ * Command -Rsp(AID == CAMID) mode
+ *
+ * This is to force fw to add an sta_data entry per driver's request.
+ *
+ * FW will write an cam entry associated with it.
+ *
+ */
+struct set_assocsta_parm {
+ u8 addr[ETH_ALEN];
+};
+
+struct set_assocsta_rsp {
+ u8 cam_id;
+ u8 rsvd[3];
+};
+
+/*
+ * Notes: This command is used for H2C/C2H loopback testing
+ *
+ * mac[0] == 0
+ * ==> CMD mode, return H2C_SUCCESS.
+ * The following condition must be true under CMD mode
+ * mac[1] == mac[4], mac[2] == mac[3], mac[0]=mac[5]= 0;
+ * s0 == 0x1234, s1 == 0xabcd, w0 == 0x78563412, w1 == 0x5aa5def7;
+ * s2 == (b1 << 8 | b0);
+ *
+ * mac[0] == 1
+ * ==> CMD_RSP mode, return H2C_SUCCESS_RSP
+ *
+ * The rsp layout shall be:
+ * rsp: parm:
+ * mac[0] = mac[5];
+ * mac[1] = mac[4];
+ * mac[2] = mac[3];
+ * mac[3] = mac[2];
+ * mac[4] = mac[1];
+ * mac[5] = mac[0];
+ * s0 = s1;
+ * s1 = swap16(s0);
+ * w0 = swap32(w1);
+ * b0 = b1
+ * s2 = s0 + s1
+ * b1 = b0
+ * w1 = w0
+ *
+ * mac[0] == 2
+ * ==> CMD_EVENT mode, return H2C_SUCCESS
+ * The event layout shall be:
+ * event: parm:
+ * mac[0] = mac[5];
+ * mac[1] = mac[4];
+ * mac[2] = event's seq no, starting from 1 to parm's marc[3]
+ * mac[2] = event's seq no, starting from 1 to parm's marc[3]
+ * mac[2] = event's seq no, starting from 1 to parm's marc[3]
+ * mac[3] = mac[2];
+ * mac[4] = mac[1];
+ * mac[5] = mac[0];
+ * s0 = swap16(s0) - event.mac[2];
+ * s1 = s1 + event.mac[2];
+ * w0 = swap32(w0);
+ * b0 = b1
+ * s2 = s0 + event.mac[2]
+ * b1 = b0
+ * w1 = swap32(w1) - event.mac[2];
+ *
+ * parm->mac[3] is the total event counts that host requested.
+ * event will be the same with the cmd's param.
+ */
+
+/* CMD param Format for driver extra cmd handler */
+struct drvextra_cmd_parm {
+ int ec_id; /* extra cmd id */
+ int type_size; /* Can use this field as the type id or command size */
+ unsigned char *pbuf;
+};
+
+struct addBaReq_parm {
+ unsigned int tid;
+ u8 addr[ETH_ALEN];
+};
+
+/*H2C Handler index: 46 */
+struct set_ch_parm {
+ u8 ch;
+ u8 bw;
+ u8 ch_offset;
+};
+
+/*H2C Handler index: 59 */
+struct SetChannelPlan_param {
+ u8 channel_plan;
+};
+
+/*
+ *
+ * Result:
+ * 0x00: success
+ * 0x01: success, and check Response.
+ * 0x02: cmd ignored due to duplicated sequcne number
+ * 0x03: cmd dropped due to invalid cmd code
+ * 0x04: reserved.
+ *
+ */
+
+#define H2C_SUCCESS 0x00
+#define H2C_SUCCESS_RSP 0x01
+#define H2C_DROPPED 0x03
+#define H2C_PARAMETERS_ERROR 0x04
+#define H2C_REJECTED 0x05
+
+u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid,
+ int ssid_num, struct rtw_ieee80211_channel *ch,
+ int ch_num);
+u8 rtw_createbss_cmd(struct adapter *padapter);
+u8 rtw_setstakey_cmd(struct adapter *padapter, u8 *psta, u8 unicast_key);
+u8 rtw_clearstakey_cmd(struct adapter *padapter, u8 *psta, u8 entry,
+ u8 enqueue);
+u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork);
+u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms,
+ bool enqueue);
+u8 rtw_setopmode_cmd(struct adapter *padapter,
+ enum ndis_802_11_network_infra networktype);
+u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr);
+
+u8 rtw_dynamic_chk_wk_cmd(struct adapter *adapter);
+
+u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue);
+u8 rtw_rpt_timer_cfg_cmd(struct adapter *padapter, u16 minRptTime);
+
+u8 rtw_antenna_select_cmd(struct adapter *padapter, u8 antenna, u8 enqueue);
+u8 rtw_ps_cmd(struct adapter *padapter);
+
+#ifdef CPTCFG_88EU_AP_MODE
+u8 rtw_chk_hi_queue_cmd(struct adapter *padapter);
+#endif
+
+u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue);
+u8 rtw_drvextra_cmd_hdl(struct adapter *padapter, unsigned char *pbuf);
+
+void rtw_survey_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd);
+void rtw_disassoc_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd);
+void rtw_joinbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd);
+void rtw_createbss_cmd_callback(struct adapter *adapt, struct cmd_obj *pcmd);
+void rtw_readtssi_cmdrsp_callback(struct adapter *adapt, struct cmd_obj *cmd);
+
+void rtw_setstaKey_cmdrsp_callback(struct adapter *adapt, struct cmd_obj *cmd);
+void rtw_setassocsta_cmdrsp_callback(struct adapter *adapt, struct cmd_obj *cm);
+void rtw_getrttbl_cmdrsp_callback(struct adapter *adapt, struct cmd_obj *cmd);
+
+struct _cmd_callback {
+ u32 cmd_code;
+ void (*callback)(struct adapter *padapter, struct cmd_obj *cmd);
+};
+
+enum rtw_h2c_cmd {
+ _JoinBss_CMD_,
+ _DisConnect_CMD_,
+ _CreateBss_CMD_,
+ _SetOpMode_CMD_,
+ _SiteSurvey_CMD_,
+ _SetAuth_CMD_,
+ _SetKey_CMD_,
+ _SetStaKey_CMD_,
+ _SetAssocSta_CMD_,
+ _AddBAReq_CMD_,
+ _SetChannel_CMD_,
+ _TX_Beacon_CMD_,
+ _Set_MLME_EVT_CMD_,
+ _Set_Drv_Extra_CMD_,
+ _SetChannelPlan_CMD_,
+
+ MAX_H2CCMD
+};
+
+#ifdef _RTW_CMD_C_
+static struct _cmd_callback rtw_cmd_callback[] = {
+ {_JoinBss_CMD_, &rtw_joinbss_cmd_callback},
+ {_DisConnect_CMD_, &rtw_disassoc_cmd_callback},
+ {_CreateBss_CMD_, &rtw_createbss_cmd_callback},
+ {_SetOpMode_CMD_, NULL},
+ {_SiteSurvey_CMD_, &rtw_survey_cmd_callback},
+ {_SetAuth_CMD_, NULL},
+ {_SetKey_CMD_, NULL},
+ {_SetStaKey_CMD_, &rtw_setstaKey_cmdrsp_callback},
+ {_SetAssocSta_CMD_, &rtw_setassocsta_cmdrsp_callback},
+ {_AddBAReq_CMD_, NULL},
+ {_SetChannel_CMD_, NULL},
+ {_TX_Beacon_CMD_, NULL},
+ {_Set_MLME_EVT_CMD_, NULL},
+ {_Set_Drv_Extra_CMD_, NULL},
+ {_SetChannelPlan_CMD_, NULL},
+};
+#endif
+
+#endif /* _CMD_H_ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_debug.h b/drivers/staging/rtl8188eu/include/rtw_debug.h
new file mode 100644
index 0000000..9840e59
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtw_debug.h
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __RTW_DEBUG_H__
+#define __RTW_DEBUG_H__
+
+#include <osdep_service.h>
+#include <drv_types.h>
+
+#define DRIVERVERSION "v4.1.4_6773.20130222"
+#define _drv_always_ 1
+#define _drv_emerg_ 2
+#define _drv_alert_ 3
+#define _drv_crit_ 4
+#define _drv_err_ 5
+#define _drv_warning_ 6
+#define _drv_notice_ 7
+#define _drv_info_ 8
+#define _drv_debug_ 9
+
+
+#define _module_rtl871x_xmit_c_ BIT(0)
+#define _module_xmit_osdep_c_ BIT(1)
+#define _module_rtl871x_recv_c_ BIT(2)
+#define _module_recv_osdep_c_ BIT(3)
+#define _module_rtl871x_mlme_c_ BIT(4)
+#define _module_mlme_osdep_c_ BIT(5)
+#define _module_rtl871x_sta_mgt_c_ BIT(6)
+#define _module_rtl871x_cmd_c_ BIT(7)
+#define _module_cmd_osdep_c_ BIT(8)
+#define _module_rtl871x_io_c_ BIT(9)
+#define _module_io_osdep_c_ BIT(10)
+#define _module_os_intfs_c_ BIT(11)
+#define _module_rtl871x_security_c_ BIT(12)
+#define _module_rtl871x_eeprom_c_ BIT(13)
+#define _module_hal_init_c_ BIT(14)
+#define _module_hci_hal_init_c_ BIT(15)
+#define _module_rtl871x_ioctl_c_ BIT(16)
+#define _module_rtl871x_ioctl_set_c_ BIT(17)
+#define _module_rtl871x_ioctl_query_c_ BIT(18)
+#define _module_rtl871x_pwrctrl_c_ BIT(19)
+#define _module_hci_intfs_c_ BIT(20)
+#define _module_hci_ops_c_ BIT(21)
+#define _module_osdep_service_c_ BIT(22)
+#define _module_mp_ BIT(23)
+#define _module_hci_ops_os_c_ BIT(24)
+#define _module_rtl871x_ioctl_os_c BIT(25)
+#define _module_rtl8712_cmd_c_ BIT(26)
+#define _module_rtl8192c_xmit_c_ BIT(27)
+#define _module_hal_xmit_c_ BIT(28)
+#define _module_efuse_ BIT(29)
+#define _module_rtl8712_recv_c_ BIT(30)
+#define _module_rtl8712_led_c_ BIT(31)
+
+#define DRIVER_PREFIX "R8188EU: "
+
+extern u32 GlobalDebugLevel;
+
+#define DBG_88E_LEVEL(_level, fmt, arg...) \
+ do { \
+ if (_level <= GlobalDebugLevel) \
+ pr_info(DRIVER_PREFIX fmt, ##arg); \
+ } while (0)
+
+#define DBG_88E(...) \
+ do { \
+ if (_drv_err_ <= GlobalDebugLevel) \
+ pr_info(DRIVER_PREFIX __VA_ARGS__); \
+ } while (0)
+
+#define MSG_88E(...) \
+ do { \
+ if (_drv_err_ <= GlobalDebugLevel) \
+ pr_info(DRIVER_PREFIX __VA_ARGS__); \
+ } while (0)
+
+#define RT_TRACE(_comp, _level, fmt) \
+ do { \
+ if (_level <= GlobalDebugLevel) { \
+ pr_info("%s [0x%08x,%d]", DRIVER_PREFIX, \
+ (unsigned int)_comp, _level); \
+ pr_info fmt; \
+ } \
+ } while (0)
+
+#define RT_PRINT_DATA(_comp, _level, _titlestring, _hexdata, _hexdatalen)\
+ do { \
+ if (_level <= GlobalDebugLevel) { \
+ int __i; \
+ u8 *ptr = (u8 *)_hexdata; \
+ pr_info("%s", DRIVER_PREFIX); \
+ pr_info(_titlestring); \
+ for (__i = 0; __i < (int)_hexdatalen; __i++) { \
+ pr_info("%02X%s", ptr[__i], \
+ (((__i + 1) % 4) == 0) ? \
+ " " : " "); \
+ if (((__i + 1) % 16) == 0) \
+ pr_cont("\n"); \
+ } \
+ pr_cont("\n"); \
+ } \
+ } while (0)
+
+int proc_get_drv_version(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_get_write_reg(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_set_write_reg(struct file *file, const char __user *buffer,
+ unsigned long count, void *data);
+int proc_get_read_reg(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_set_read_reg(struct file *file, const char __user *buffer,
+ unsigned long count, void *data);
+
+int proc_get_adapter_state(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+int proc_get_best_channel(char *page, char **start,
+ off_t offset, int count,
+ int *eof, void *data);
+
+#endif /* __RTW_DEBUG_H__ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_eeprom.h b/drivers/staging/rtl8188eu/include/rtw_eeprom.h
new file mode 100644
index 0000000..1052549
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtw_eeprom.h
@@ -0,0 +1,114 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __RTW_EEPROM_H__
+#define __RTW_EEPROM_H__
+
+#include <osdep_service.h>
+#include <drv_types.h>
+
+#define RTL8712_EEPROM_ID 0x8712
+
+#define HWSET_MAX_SIZE_512 512
+#define EEPROM_MAX_SIZE HWSET_MAX_SIZE_512
+
+#define CLOCK_RATE 50 /* 100us */
+
+/* EEPROM opcodes */
+#define EEPROM_READ_OPCODE 06
+#define EEPROM_WRITE_OPCODE 05
+#define EEPROM_ERASE_OPCODE 07
+#define EEPROM_EWEN_OPCODE 19 /* Erase/write enable */
+#define EEPROM_EWDS_OPCODE 16 /* Erase/write disable */
+
+/* Country codes */
+#define USA 0x555320
+#define EUROPE 0x1 /* temp, should be provided later */
+#define JAPAN 0x2 /* temp, should be provided later */
+
+#define EEPROM_CID_DEFAULT 0x0
+#define EEPROM_CID_ALPHA 0x1
+#define EEPROM_CID_Senao 0x3
+#define EEPROM_CID_NetCore 0x5
+#define EEPROM_CID_CAMEO 0X8
+#define EEPROM_CID_SITECOM 0x9
+#define EEPROM_CID_COREGA 0xB
+#define EEPROM_CID_EDIMAX_BELK 0xC
+#define EEPROM_CID_SERCOMM_BELK 0xE
+#define EEPROM_CID_CAMEO1 0xF
+#define EEPROM_CID_WNC_COREGA 0x12
+#define EEPROM_CID_CLEVO 0x13
+#define EEPROM_CID_WHQL 0xFE
+
+/* Customer ID, note that: */
+/* This variable is initiailzed through EEPROM or registry, */
+/* however, its definition may be different with that in EEPROM for */
+/* EEPROM size consideration. So, we have to perform proper translation
+ * between them.
+ */
+/* Besides, CustomerID of registry has precedence of that of EEPROM. */
+/* defined below. 060703, by rcnjko. */
+enum RT_CUSTOMER_ID {
+ RT_CID_DEFAULT = 0,
+ RT_CID_8187_ALPHA0 = 1,
+ RT_CID_8187_SERCOMM_PS = 2,
+ RT_CID_8187_HW_LED = 3,
+ RT_CID_8187_NETGEAR = 4,
+ RT_CID_WHQL = 5,
+ RT_CID_819x_CAMEO = 6,
+ RT_CID_819x_RUNTOP = 7,
+ RT_CID_819x_Senao = 8,
+ RT_CID_TOSHIBA = 9, /* Merge by Jacken, 2008/01/31. */
+ RT_CID_819x_Netcore = 10,
+ RT_CID_Nettronix = 11,
+ RT_CID_DLINK = 12,
+ RT_CID_PRONET = 13,
+ RT_CID_COREGA = 14,
+ RT_CID_CHINA_MOBILE = 15,
+ RT_CID_819x_ALPHA = 16,
+ RT_CID_819x_Sitecom = 17,
+ RT_CID_CCX = 18, /* It's set under CCX logo test and isn't demanded
+ * for CCX functions, but for test behavior like retry
+ * limit and tx report. By Bruce, 2009-02-17.
+ */
+ RT_CID_819x_Lenovo = 19,
+ RT_CID_819x_QMI = 20,
+ RT_CID_819x_Edimax_Belkin = 21,
+ RT_CID_819x_Sercomm_Belkin = 22,
+ RT_CID_819x_CAMEO1 = 23,
+ RT_CID_819x_MSI = 24,
+ RT_CID_819x_Acer = 25,
+ RT_CID_819x_AzWave_ASUS = 26,
+ RT_CID_819x_AzWave = 27, /* For AzWave in PCIe,i
+ * The ID is AzWave use and not only Asus
+ */
+ RT_CID_819x_HP = 28,
+ RT_CID_819x_WNC_COREGA = 29,
+ RT_CID_819x_Arcadyan_Belkin = 30,
+ RT_CID_819x_SAMSUNG = 31,
+ RT_CID_819x_CLEVO = 32,
+ RT_CID_819x_DELL = 33,
+ RT_CID_819x_PRONETS = 34,
+ RT_CID_819x_Edimax_ASUS = 35,
+ RT_CID_819x_CAMEO_NETGEAR = 36,
+ RT_CID_PLANEX = 37,
+ RT_CID_CC_C = 38,
+ RT_CID_819x_Xavi = 39,
+ RT_CID_819x_FUNAI_TV = 40,
+ RT_CID_819x_ALPHA_WD = 41,
+};
+
+struct eeprom_priv {
+ u8 bautoload_fail_flag;
+ u8 bloadfile_fail_flag;
+ u8 bloadmac_fail_flag;
+ u8 mac_addr[6]; /* PermanentAddress */
+ u16 channel_plan;
+ u8 EepromOrEfuse;
+ u8 efuse_eeprom_data[HWSET_MAX_SIZE_512];
+};
+
+#endif /* __RTL871X_EEPROM_H__ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_efuse.h b/drivers/staging/rtl8188eu/include/rtw_efuse.h
new file mode 100644
index 0000000..3ec5376
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtw_efuse.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __RTW_EFUSE_H__
+#define __RTW_EFUSE_H__
+
+#include <osdep_service.h>
+
+#define EFUSE_ERROE_HANDLE 1
+
+#define PG_STATE_HEADER 0x01
+#define PG_STATE_WORD_0 0x02
+#define PG_STATE_WORD_1 0x04
+#define PG_STATE_WORD_2 0x08
+#define PG_STATE_WORD_3 0x10
+#define PG_STATE_DATA 0x20
+
+#define PG_SWBYTE_H 0x01
+#define PG_SWBYTE_L 0x02
+
+#define PGPKT_DATA_SIZE 8
+
+#define EFUSE_WIFI 0
+#define EFUSE_BT 1
+
+/* E-Fuse */
+#define EFUSE_MAP_SIZE 512
+#define EFUSE_MAX_SIZE 256
+/* end of E-Fuse */
+
+#define EFUSE_MAX_MAP_LEN 512
+#define EFUSE_MAX_HW_SIZE 512
+#define EFUSE_MAX_SECTION_BASE 16
+
+#define EXT_HEADER(header) ((header & 0x1F) == 0x0F)
+#define ALL_WORDS_DISABLED(wde) ((wde & 0x0F) == 0x0F)
+#define GET_HDR_OFFSET_2_0(header) ((header & 0xE0) >> 5)
+
+#define EFUSE_REPEAT_THRESHOLD_ 3
+
+/* The following is for BT Efuse definition */
+#define EFUSE_BT_MAX_MAP_LEN 1024
+#define EFUSE_MAX_BANK 4
+#define EFUSE_MAX_BT_BANK (EFUSE_MAX_BANK-1)
+/*--------------------------Define Parameters-------------------------------*/
+#define EFUSE_MAX_WORD_UNIT 4
+
+/*------------------------------Define structure----------------------------*/
+struct pgpkt {
+ u8 offset;
+ u8 word_en;
+ u8 data[8];
+ u8 word_cnts;
+};
+
+/*------------------------------Define structure----------------------------*/
+struct efuse_hal {
+ u8 fakeEfuseBank;
+ u32 fakeEfuseUsedBytes;
+ u8 fakeEfuseContent[EFUSE_MAX_HW_SIZE];
+ u8 fakeEfuseInitMap[EFUSE_MAX_MAP_LEN];
+ u8 fakeEfuseModifiedMap[EFUSE_MAX_MAP_LEN];
+
+ u16 BTEfuseUsedBytes;
+ u8 BTEfuseUsedPercentage;
+ u8 BTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
+ u8 BTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN];
+ u8 BTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN];
+
+ u16 fakeBTEfuseUsedBytes;
+ u8 fakeBTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
+ u8 fakeBTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN];
+ u8 fakeBTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN];
+};
+
+u8 Efuse_CalculateWordCnts(u8 word_en);
+u8 efuse_OneByteRead(struct adapter *adapter, u16 addr, u8 *data);
+u8 efuse_OneByteWrite(struct adapter *adapter, u16 addr, u8 data);
+
+void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset,
+ u16 _size_byte, u8 *pbuf);
+void efuse_power_switch(struct adapter *adapt, u8 write, u8 pwrstate);
+int Efuse_PgPacketRead(struct adapter *adapt, u8 offset, u8 *data);
+bool Efuse_PgPacketWrite(struct adapter *adapter, u8 offset, u8 word, u8 *data);
+void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata);
+u8 Efuse_WordEnableDataWrite(struct adapter *adapter, u16 efuse_addr,
+ u8 word_en, u8 *data);
+
+void EFUSE_ShadowMapUpdate(struct adapter *adapter, u8 efusetype);
+#endif
diff --git a/drivers/staging/rtl8188eu/include/rtw_event.h b/drivers/staging/rtl8188eu/include/rtw_event.h
new file mode 100644
index 0000000..bfe774e
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtw_event.h
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef _RTW_EVENT_H_
+#define _RTW_EVENT_H_
+
+#include <osdep_service.h>
+
+#include <wlan_bssdef.h>
+#include <linux/mutex.h>
+#include <linux/sem.h>
+
+/*
+ * Used to report a bss has been scanned
+ */
+struct survey_event {
+ struct wlan_bssid_ex bss;
+};
+
+/*
+ * Used to report that the requested site survey has been done.
+ *
+ * bss_cnt indicates the number of bss that has been reported.
+ *
+ *
+ */
+struct surveydone_event {
+ unsigned int bss_cnt;
+
+};
+
+/*
+ * Used to report the link result of joinning the given bss
+ *
+ *
+ * join_res:
+ * -1: authentication fail
+ * -2: association fail
+ * > 0: TID
+ *
+ */
+struct joinbss_event {
+ struct wlan_network network;
+};
+
+/*
+ * Used to report a given STA has joinned the created BSS.
+ * It is used in AP/Ad-HoC(M) mode.
+ */
+
+struct stassoc_event {
+ unsigned char macaddr[6];
+ unsigned char rsvd[2];
+ int cam_id;
+};
+
+struct stadel_event {
+ unsigned char macaddr[6];
+ unsigned char rsvd[2]; /* for reason */
+ int mac_id;
+};
+
+struct fwevent {
+ u32 parmsize;
+ void (*event_callback)(struct adapter *dev, u8 *pbuf);
+};
+
+#define C2HEVENT_SZ 32
+
+#define NETWORK_QUEUE_SZ 4
+
+struct network_queue {
+ int head;
+ int tail;
+ struct wlan_bssid_ex networks[NETWORK_QUEUE_SZ];
+};
+
+#endif /* _WLANEVENT_H_ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_ht.h b/drivers/staging/rtl8188eu/include/rtw_ht.h
new file mode 100644
index 0000000..192fa50
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtw_ht.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef _RTW_HT_H_
+#define _RTW_HT_H_
+
+#include <linux/ieee80211.h>
+
+struct ht_priv {
+ u32 ht_option;
+ u32 ampdu_enable;/* for enable Tx A-MPDU */
+ u8 bwmode;/* */
+ u8 ch_offset;/* PRIME_CHNL_OFFSET */
+ u8 sgi;/* short GI */
+
+ /* for processing Tx A-MPDU */
+ u8 agg_enable_bitmap;
+ u8 candidate_tid_bitmap;
+
+ struct ieee80211_ht_cap ht_cap;
+};
+
+#endif /* _RTL871X_HT_H_ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_ioctl.h b/drivers/staging/rtl8188eu/include/rtw_ioctl.h
new file mode 100644
index 0000000..5d773c8
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtw_ioctl.h
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef _RTW_IOCTL_H_
+#define _RTW_IOCTL_H_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+
+
+#ifndef OID_802_11_CAPABILITY
+ #define OID_802_11_CAPABILITY 0x0d010122
+#endif
+
+#ifndef OID_802_11_PMKID
+ #define OID_802_11_PMKID 0x0d010123
+#endif
+
+
+/* For DDK-defined OIDs */
+#define OID_NDIS_SEG1 0x00010100
+#define OID_NDIS_SEG2 0x00010200
+#define OID_NDIS_SEG3 0x00020100
+#define OID_NDIS_SEG4 0x01010100
+#define OID_NDIS_SEG5 0x01020100
+#define OID_NDIS_SEG6 0x01020200
+#define OID_NDIS_SEG7 0xFD010100
+#define OID_NDIS_SEG8 0x0D010100
+#define OID_NDIS_SEG9 0x0D010200
+#define OID_NDIS_SEG10 0x0D020200
+
+#define SZ_OID_NDIS_SEG1 23
+#define SZ_OID_NDIS_SEG2 3
+#define SZ_OID_NDIS_SEG3 6
+#define SZ_OID_NDIS_SEG4 6
+#define SZ_OID_NDIS_SEG5 4
+#define SZ_OID_NDIS_SEG6 8
+#define SZ_OID_NDIS_SEG7 7
+#define SZ_OID_NDIS_SEG8 36
+#define SZ_OID_NDIS_SEG9 24
+#define SZ_OID_NDIS_SEG10 19
+
+/* For Realtek-defined OIDs */
+#define OID_MP_SEG1 0xFF871100
+#define OID_MP_SEG2 0xFF818000
+
+#define OID_MP_SEG3 0xFF818700
+#define OID_MP_SEG4 0xFF011100
+
+enum oid_type {
+ QUERY_OID,
+ SET_OID
+};
+
+struct oid_par_priv {
+ void *adapter_context;
+ NDIS_OID oid;
+ void *information_buf;
+ u32 information_buf_len;
+ u32 *bytes_rw;
+ u32 *bytes_needed;
+ enum oid_type type_of_oid;
+ u32 dbg;
+};
+
+#if defined(_RTW_MP_IOCTL_C_)
+static int oid_null_function(struct oid_par_priv *poid_par_priv)
+{
+ return NDIS_STATUS_SUCCESS;
+}
+#endif
+
+extern struct iw_handler_def rtw_handlers_def;
+
+int drv_query_info(struct net_device *miniportadaptercontext, NDIS_OID oid,
+ void *informationbuffer, u32 informationbufferlength,
+ u32 *byteswritten, u32 *bytesneeded);
+
+int drv_set_info(struct net_device *MiniportAdapterContext,
+ NDIS_OID oid, void *informationbuffer,
+ u32 informationbufferlength, u32 *bytesread,
+ u32 *bytesneeded);
+
+#endif /* #ifndef __INC_CEINFO_ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_ioctl_set.h b/drivers/staging/rtl8188eu/include/rtw_ioctl_set.h
new file mode 100644
index 0000000..0be99f6
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtw_ioctl_set.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __RTW_IOCTL_SET_H_
+#define __RTW_IOCTL_SET_H_
+
+#include <drv_types.h>
+
+
+typedef u8 NDIS_802_11_PMKID_VALUE[16];
+
+u8 rtw_set_802_11_authentication_mode(struct adapter *adapt,
+ enum ndis_802_11_auth_mode authmode);
+u8 rtw_set_802_11_bssid(struct adapter *adapter, u8 *bssid);
+u8 rtw_set_802_11_add_wep(struct adapter *adapter, struct ndis_802_11_wep *wep);
+u8 rtw_set_802_11_disassociate(struct adapter *adapter);
+u8 rtw_set_802_11_bssid_list_scan(struct adapter *adapter,
+ struct ndis_802_11_ssid *pssid,
+ int ssid_max_num);
+u8 rtw_set_802_11_infrastructure_mode(struct adapter *adapter,
+ enum ndis_802_11_network_infra type);
+u8 rtw_set_802_11_ssid(struct adapter *adapt, struct ndis_802_11_ssid *ssid);
+u16 rtw_get_cur_max_rate(struct adapter *adapter);
+int rtw_set_country(struct adapter *adapter, const char *country_code);
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/rtw_iol.h b/drivers/staging/rtl8188eu/include/rtw_iol.h
new file mode 100644
index 0000000..d713782
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtw_iol.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __RTW_IOL_H_
+#define __RTW_IOL_H_
+
+#include <drv_types.h>
+
+bool rtw_iol_applied(struct adapter *adapter);
+
+#endif /* __RTW_IOL_H_ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_led.h b/drivers/staging/rtl8188eu/include/rtw_led.h
new file mode 100644
index 0000000..ee62ed7
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtw_led.h
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __RTW_LED_H_
+#define __RTW_LED_H_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+
+#define LED_BLINK_NO_LINK_INTERVAL_ALPHA 1000
+#define LED_BLINK_LINK_INTERVAL_ALPHA 500 /* 500 */
+#define LED_BLINK_SCAN_INTERVAL_ALPHA 180 /* 150 */
+#define LED_BLINK_FASTER_INTERVAL_ALPHA 50
+#define LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA 5000
+
+enum LED_CTL_MODE {
+ LED_CTL_POWER_ON,
+ LED_CTL_LINK,
+ LED_CTL_NO_LINK,
+ LED_CTL_TX,
+ LED_CTL_RX,
+ LED_CTL_SITE_SURVEY,
+ LED_CTL_POWER_OFF,
+ LED_CTL_START_TO_LINK,
+ LED_CTL_START_WPS,
+ LED_CTL_STOP_WPS,
+ LED_CTL_START_WPS_BOTTON,
+ LED_CTL_STOP_WPS_FAIL
+};
+
+enum LED_STATE_871x {
+ LED_UNKNOWN,
+ RTW_LED_ON,
+ RTW_LED_OFF,
+ LED_BLINK_NORMAL,
+ LED_BLINK_SLOWLY,
+ LED_BLINK_POWER_ON,
+ LED_BLINK_SCAN,
+ LED_BLINK_TXRX,
+ LED_BLINK_WPS,
+ LED_BLINK_WPS_STOP
+};
+
+struct LED_871x {
+ struct adapter *padapter;
+
+ enum LED_STATE_871x CurrLedState; /* Current LED state. */
+ enum LED_STATE_871x BlinkingLedState; /* Next state for blinking,
+ * either RTW_LED_ON or RTW_LED_OFF are.
+ */
+
+ u8 bLedOn; /* true if LED is ON, false if LED is OFF. */
+
+ u8 bLedBlinkInProgress; /* true if it is blinking, false o.w.. */
+
+ u8 bLedWPSBlinkInProgress;
+
+ u32 BlinkTimes; /* Number of times to toggle led state for blinking. */
+
+ struct timer_list BlinkTimer; /* Timer object for led blinking. */
+
+ /* ALPHA, added by chiyoko, 20090106 */
+ u8 bLedNoLinkBlinkInProgress;
+ u8 bLedLinkBlinkInProgress;
+ u8 bLedScanBlinkInProgress;
+ struct work_struct BlinkWorkItem; /* Workitem used by BlinkTimer to
+ * manipulate H/W to blink LED.
+ */
+};
+
+#define IS_LED_WPS_BLINKING(_LED_871x) \
+ (((struct LED_871x *)_LED_871x)->CurrLedState == LED_BLINK_WPS || \
+ ((struct LED_871x *)_LED_871x)->CurrLedState == LED_BLINK_WPS_STOP || \
+ ((struct LED_871x *)_LED_871x)->bLedWPSBlinkInProgress)
+
+void led_control_8188eu(struct adapter *padapter, enum LED_CTL_MODE LedAction);
+
+struct led_priv {
+ struct LED_871x sw_led;
+};
+
+void BlinkWorkItemCallback(struct work_struct *work);
+
+void ResetLedStatus(struct LED_871x *pLed);
+
+void InitLed871x(struct adapter *padapter, struct LED_871x *pLed);
+
+void DeInitLed871x(struct LED_871x *pLed);
+
+/* hal... */
+void blink_handler(struct LED_871x *pLed);
+void sw_led_on(struct adapter *padapter, struct LED_871x *pLed);
+void sw_led_off(struct adapter *padapter, struct LED_871x *pLed);
+
+#endif /* __RTW_LED_H_ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme.h b/drivers/staging/rtl8188eu/include/rtw_mlme.h
new file mode 100644
index 0000000..4275229
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtw_mlme.h
@@ -0,0 +1,359 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __RTW_MLME_H_
+#define __RTW_MLME_H_
+
+#include <osdep_service.h>
+#include <mlme_osdep.h>
+#include <drv_types.h>
+#include <wlan_bssdef.h>
+
+#define MAX_BSS_CNT 128
+#define MAX_JOIN_TIMEOUT 6500
+
+/* Increase the scanning timeout because of increasing the SURVEY_TO value. */
+
+#define SCANNING_TIMEOUT 8000
+
+#define SCAN_INTERVAL (30) /* unit:2sec, 30*2=60sec */
+
+#define SCANQUEUE_LIFETIME 20 /* unit:sec */
+
+#define WIFI_NULL_STATE 0x00000000
+
+#define WIFI_ASOC_STATE 0x00000001 /* Under Linked state */
+#define WIFI_REASOC_STATE 0x00000002
+#define WIFI_SLEEP_STATE 0x00000004
+#define WIFI_STATION_STATE 0x00000008
+
+#define WIFI_AP_STATE 0x00000010
+#define WIFI_ADHOC_STATE 0x00000020
+#define WIFI_ADHOC_MASTER_STATE 0x00000040
+#define WIFI_UNDER_LINKING 0x00000080
+
+#define WIFI_UNDER_WPS 0x00000100
+#define WIFI_STA_ALIVE_CHK_STATE 0x00000400
+#define WIFI_SITE_MONITOR 0x00000800 /* to indicate the station is under site surveying */
+
+#define _FW_UNDER_LINKING WIFI_UNDER_LINKING
+#define _FW_LINKED WIFI_ASOC_STATE
+#define _FW_UNDER_SURVEY WIFI_SITE_MONITOR
+
+enum dot11AuthAlgrthmNum {
+ dot11AuthAlgrthm_Open = 0, /* open system */
+ dot11AuthAlgrthm_Shared,
+ dot11AuthAlgrthm_8021X,
+ dot11AuthAlgrthm_Auto,
+ dot11AuthAlgrthm_WAPI,
+ dot11AuthAlgrthm_MaxNum
+};
+
+/* Scan type including active and passive scan. */
+enum rt_scan_type {
+ SCAN_PASSIVE,
+ SCAN_ACTIVE,
+ SCAN_MIX,
+};
+
+enum SCAN_RESULT_TYPE {
+ SCAN_RESULT_P2P_ONLY = 0, /* Will return all the P2P devices. */
+ SCAN_RESULT_ALL = 1, /* Will return all the scanned device,
+ * include AP.
+ */
+ SCAN_RESULT_WFD_TYPE = 2 /* Will just return the correct WFD
+ * device.
+ */
+ /* If this device is Miracast sink
+ * device, it will just return all the
+ * Miracast source devices.
+ */
+};
+
+/*
+ * there are several "locks" in mlme_priv,
+ * since mlme_priv is a shared resource between many threads,
+ * like ISR/Call-Back functions, the OID handlers, and even timer functions.
+ *
+ * Each _queue has its own locks, already.
+ * Other items are protected by mlme_priv.lock.
+ *
+ * To avoid possible dead lock, any thread trying to modifiying mlme_priv
+ * SHALL not lock up more than one lock at a time!
+ */
+
+#define traffic_threshold 10
+#define traffic_scan_period 500
+
+struct rt_link_detect {
+ u32 NumTxOkInPeriod;
+ u32 NumRxOkInPeriod;
+ u32 NumRxUnicastOkInPeriod;
+ bool bBusyTraffic;
+ bool bTxBusyTraffic;
+ bool bRxBusyTraffic;
+ bool bHigherBusyTraffic; /* For interrupt migration purpose. */
+ bool bHigherBusyRxTraffic; /* We may disable Tx interrupt according
+ * to Rx traffic.
+ */
+ bool bHigherBusyTxTraffic; /* We may disable Tx interrupt according
+ * to Tx traffic.
+ */
+};
+
+struct mlme_priv {
+ spinlock_t lock;
+ int fw_state; /* shall we protect this variable? maybe not necessarily... */
+ u8 bScanInProcess;
+ u8 to_join; /* flag */
+ u8 to_roaming; /* roaming trying times */
+
+ u8 *nic_hdl;
+
+ struct list_head *pscanned;
+ struct __queue free_bss_pool;
+ struct __queue scanned_queue;
+ u8 *free_bss_buf;
+
+ struct ndis_802_11_ssid assoc_ssid;
+ u8 assoc_bssid[6];
+
+ struct wlan_network cur_network;
+
+ u32 scan_interval;
+
+ struct timer_list assoc_timer;
+
+ uint assoc_by_bssid;
+
+ struct timer_list scan_to_timer; /* driver itself handles scan_timeout status. */
+
+ struct qos_priv qospriv;
+
+ /* Number of non-HT AP/stations */
+ int num_sta_no_ht;
+
+ /* Number of HT AP/stations 20 MHz */
+ /* int num_sta_ht_20mhz; */
+
+ int num_FortyMHzIntolerant;
+ struct ht_priv htpriv;
+ struct rt_link_detect LinkDetectInfo;
+ struct timer_list dynamic_chk_timer; /* dynamic/periodic check timer */
+
+ u8 key_mask; /* use for ips to set wep key after ips_leave */
+ u8 acm_mask; /* for wmm acm mask */
+ u8 ChannelPlan;
+ enum rt_scan_type scan_mode; /* active: 1, passive: 0 */
+
+ /* u8 probereq_wpsie[MAX_WPS_IE_LEN];added in probe req */
+ /* int probereq_wpsie_len; */
+ u8 *wps_probe_req_ie;
+ u32 wps_probe_req_ie_len;
+
+ u8 *assoc_req;
+ u32 assoc_req_len;
+ u8 *assoc_rsp;
+ u32 assoc_rsp_len;
+
+#if defined(CPTCFG_88EU_AP_MODE)
+ /* Number of associated Non-ERP stations (i.e., stations using 802.11b
+ * in 802.11g BSS)
+ */
+ int num_sta_non_erp;
+
+ /* Number of associated stations that do not support Short Slot Time */
+ int num_sta_no_short_slot_time;
+
+ /* Number of associated stations that do not support Short Preamble */
+ int num_sta_no_short_preamble;
+
+ int olbc; /* Overlapping Legacy BSS Condition */
+
+ /* Number of HT assoc sta that do not support greenfield */
+ int num_sta_ht_no_gf;
+
+ /* Number of associated non-HT stations */
+ /* int num_sta_no_ht; */
+
+ /* Number of HT associated stations 20 MHz */
+ int num_sta_ht_20mhz;
+
+ /* Overlapping BSS information */
+ int olbc_ht;
+
+ u16 ht_op_mode;
+
+ u8 *wps_beacon_ie;
+ /* u8 *wps_probe_req_ie; */
+ u8 *wps_probe_resp_ie;
+ u8 *wps_assoc_resp_ie;
+
+ u32 wps_beacon_ie_len;
+ u32 wps_probe_resp_ie_len;
+ u32 wps_assoc_resp_ie_len;
+
+ spinlock_t bcn_update_lock;
+ u8 update_bcn;
+#endif /* if defined (CPTCFG_88EU_AP_MODE) */
+};
+
+#ifdef CPTCFG_88EU_AP_MODE
+
+struct hostapd_priv {
+ struct adapter *padapter;
+};
+
+int hostapd_mode_init(struct adapter *padapter);
+void hostapd_mode_unload(struct adapter *padapter);
+#endif
+
+extern const u8 WPA_TKIP_CIPHER[4];
+extern const u8 RSN_TKIP_CIPHER[4];
+extern u8 REALTEK_96B_IE[];
+extern const u8 MCS_rate_1R[16];
+
+void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf);
+void rtw_survey_event_callback(struct adapter *adapter, u8 *pbuf);
+void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf);
+void rtw_joinbss_event_callback(struct adapter *adapter, u8 *pbuf);
+void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf);
+void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf);
+void rtw_atimdone_event_callback(struct adapter *adapter, u8 *pbuf);
+void rtw_cpwm_event_callback(struct adapter *adapter, u8 *pbuf);
+void indicate_wx_scan_complete_event(struct adapter *padapter);
+void rtw_indicate_wx_assoc_event(struct adapter *padapter);
+void rtw_indicate_wx_disassoc_event(struct adapter *padapter);
+int event_thread(void *context);
+void rtw_free_network_queue(struct adapter *adapter, u8 isfreeall);
+int rtw_init_mlme_priv(struct adapter *adapter);
+void rtw_free_mlme_priv(struct mlme_priv *pmlmepriv);
+int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv);
+int rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv,
+ int keyid, u8 set_tx);
+int rtw_set_auth(struct adapter *adapter, struct security_priv *psecuritypriv);
+
+static inline u8 *get_bssid(struct mlme_priv *pmlmepriv)
+{ /* if sta_mode:pmlmepriv->cur_network.network.MacAddress=> bssid */
+ /* if adhoc_mode:pmlmepriv->cur_network.network.MacAddress=> ibss mac address */
+ return pmlmepriv->cur_network.network.MacAddress;
+}
+
+static inline int check_fwstate(struct mlme_priv *pmlmepriv, int state)
+{
+ if (pmlmepriv->fw_state & state)
+ return true;
+
+ return false;
+}
+
+static inline int get_fwstate(struct mlme_priv *pmlmepriv)
+{
+ return pmlmepriv->fw_state;
+}
+
+/*
+ * No Limit on the calling context,
+ * therefore set it to be the critical section...
+ *
+ * ### NOTE:#### (!!!!)
+ * MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock
+ */
+static inline void set_fwstate(struct mlme_priv *pmlmepriv, int state)
+{
+ pmlmepriv->fw_state |= state;
+ /* FOR HW integration */
+ if (_FW_UNDER_SURVEY == state)
+ pmlmepriv->bScanInProcess = true;
+}
+
+static inline void _clr_fwstate_(struct mlme_priv *pmlmepriv, int state)
+{
+ pmlmepriv->fw_state &= ~state;
+ /* FOR HW integration */
+ if (_FW_UNDER_SURVEY == state)
+ pmlmepriv->bScanInProcess = false;
+}
+
+/*
+ * No Limit on the calling context,
+ * therefore set it to be the critical section...
+ */
+static inline void clr_fwstate(struct mlme_priv *pmlmepriv, int state)
+{
+ spin_lock_bh(&pmlmepriv->lock);
+ if (check_fwstate(pmlmepriv, state))
+ pmlmepriv->fw_state ^= state;
+ spin_unlock_bh(&pmlmepriv->lock);
+}
+
+static inline void clr_fwstate_ex(struct mlme_priv *pmlmepriv, int state)
+{
+ spin_lock_bh(&pmlmepriv->lock);
+ _clr_fwstate_(pmlmepriv, state);
+ spin_unlock_bh(&pmlmepriv->lock);
+}
+
+u16 rtw_get_capability(struct wlan_bssid_ex *bss);
+void rtw_update_scanned_network(struct adapter *adapter,
+ struct wlan_bssid_ex *target);
+void rtw_disconnect_hdl_under_linked(struct adapter *adapter,
+ struct sta_info *psta, u8 free_assoc);
+void rtw_generate_random_ibss(u8 *pibss);
+struct wlan_network *rtw_find_network(struct __queue *scanned_queue, u8 *addr);
+struct wlan_network *rtw_get_oldest_wlan_network(struct __queue *scanned_queue);
+
+void rtw_free_assoc_resources(struct adapter *adapter);
+void rtw_free_assoc_resources_locked(struct adapter *adapter);
+void rtw_indicate_disconnect(struct adapter *adapter);
+void rtw_indicate_connect(struct adapter *adapter);
+void rtw_indicate_scan_done(struct adapter *padapter, bool aborted);
+
+int rtw_restruct_sec_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie,
+ uint in_len);
+int rtw_restruct_wmm_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie,
+ uint in_len, uint initial_out_len);
+void rtw_init_registrypriv_dev_network(struct adapter *adapter);
+
+void rtw_update_registrypriv_dev_network(struct adapter *adapter);
+
+void rtw_get_encrypt_decrypt_from_registrypriv(struct adapter *adapter);
+
+void _rtw_join_timeout_handler(struct timer_list *t);
+void rtw_scan_timeout_handler(struct timer_list *t);
+
+void rtw_dynamic_check_timer_handlder(struct timer_list *t);
+#define rtw_is_scan_deny(adapter) false
+#define rtw_clear_scan_deny(adapter) do {} while (0)
+#define rtw_set_scan_deny_timer_hdl(adapter) do {} while (0)
+#define rtw_set_scan_deny(adapter, ms) do {} while (0)
+
+void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv);
+
+struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv);
+
+int rtw_if_up(struct adapter *padapter);
+
+u8 *rtw_get_capability_from_ie(u8 *ie);
+u8 *rtw_get_beacon_interval_from_ie(u8 *ie);
+
+void rtw_joinbss_reset(struct adapter *padapter);
+
+unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie,
+ u8 *out_ie, uint in_len, uint *pout_len);
+void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len);
+void rtw_issue_addbareq_cmd(struct adapter *padapter,
+ struct xmit_frame *pxmitframe);
+
+int rtw_is_same_ibss(struct adapter *adapter, struct wlan_network *pnetwork);
+int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst);
+
+void rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network);
+void _rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network);
+
+void rtw_stassoc_hw_rpt(struct adapter *adapter, struct sta_info *psta);
+
+#endif /* __RTL871X_MLME_H_ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h
new file mode 100644
index 0000000..8590e8d
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h
@@ -0,0 +1,717 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __RTW_MLME_EXT_H_
+#define __RTW_MLME_EXT_H_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <wlan_bssdef.h>
+
+
+/* Commented by Albert 20101105 */
+/* Increase the SURVEY_TO value from 100 to 150 ( 100ms to 150ms ) */
+/* The Realtek 8188CE SoftAP will spend around 100ms to send the probe response after receiving the probe request. */
+/* So, this driver tried to extend the dwell time for each scanning channel. */
+/* This will increase the chance to receive the probe response from SoftAP. */
+
+#define SURVEY_TO (100)
+#define REAUTH_TO (300) /* 50) */
+#define REASSOC_TO (300) /* 50) */
+/* define DISCONNECT_TO (3000) */
+#define ADDBA_TO (2000)
+
+#define LINKED_TO (1) /* unit:2 sec, 1x2=2 sec */
+
+#define REAUTH_LIMIT (4)
+#define REASSOC_LIMIT (4)
+#define READDBA_LIMIT (2)
+
+#define ROAMING_LIMIT 8
+
+#define DYNAMIC_FUNC_DISABLE (0x0)
+
+/* ====== ODM_ABILITY_E ======== */
+/* BB ODM section BIT 0-15 */
+#define DYNAMIC_BB_DIG BIT(0)
+#define DYNAMIC_BB_RA_MASK BIT(1)
+#define DYNAMIC_BB_DYNAMIC_TXPWR BIT(2)
+#define DYNAMIC_BB_BB_FA_CNT BIT(3)
+
+#define DYNAMIC_BB_RSSI_MONITOR BIT(4)
+#define DYNAMIC_BB_CCK_PD BIT(5)
+#define DYNAMIC_BB_ANT_DIV BIT(6)
+#define DYNAMIC_BB_PWR_SAVE BIT(7)
+#define DYNAMIC_BB_PWR_TRA BIT(8)
+#define DYNAMIC_BB_RATE_ADAPTIVE BIT(9)
+#define DYNAMIC_BB_PATH_DIV BIT(10)
+#define DYNAMIC_BB_PSD BIT(11)
+
+/* MAC DM section BIT 16-23 */
+#define DYNAMIC_MAC_EDCA_TURBO BIT(16)
+#define DYNAMIC_MAC_EARLY_MODE BIT(17)
+
+/* RF ODM section BIT 24-31 */
+#define DYNAMIC_RF_TX_PWR_TRACK BIT(24)
+#define DYNAMIC_RF_RX_GAIN_TRACK BIT(25)
+#define DYNAMIC_RF_CALIBRATION BIT(26)
+
+#define DYNAMIC_ALL_FUNC_ENABLE 0xFFFFFFF
+
+#define _HW_STATE_NOLINK_ 0x00
+#define _HW_STATE_ADHOC_ 0x01
+#define _HW_STATE_STATION_ 0x02
+#define _HW_STATE_AP_ 0x03
+
+
+#define _1M_RATE_ 0
+#define _2M_RATE_ 1
+#define _5M_RATE_ 2
+#define _11M_RATE_ 3
+#define _6M_RATE_ 4
+#define _9M_RATE_ 5
+#define _12M_RATE_ 6
+#define _18M_RATE_ 7
+#define _24M_RATE_ 8
+#define _36M_RATE_ 9
+#define _48M_RATE_ 10
+#define _54M_RATE_ 11
+
+extern const u8 RTW_WPA_OUI[];
+extern const u8 WPS_OUI[];
+
+/* Channel Plan Type. */
+/* Note: */
+/* We just add new channel plan when the new channel plan is different
+ * from any of the following channel plan.
+ */
+/* If you just want to customize the actions(scan period or join actions)
+ * about one of the channel plan,
+ */
+/* customize them in struct rt_channel_info in the RT_CHANNEL_LIST. */
+enum RT_CHANNEL_DOMAIN {
+ /* old channel plan mapping ===== */
+ RT_CHANNEL_DOMAIN_FCC = 0x00,
+ RT_CHANNEL_DOMAIN_IC = 0x01,
+ RT_CHANNEL_DOMAIN_ETSI = 0x02,
+ RT_CHANNEL_DOMAIN_SPAIN = 0x03,
+ RT_CHANNEL_DOMAIN_FRANCE = 0x04,
+ RT_CHANNEL_DOMAIN_MKK = 0x05,
+ RT_CHANNEL_DOMAIN_MKK1 = 0x06,
+ RT_CHANNEL_DOMAIN_ISRAEL = 0x07,
+ RT_CHANNEL_DOMAIN_TELEC = 0x08,
+ RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN = 0x09,
+ RT_CHANNEL_DOMAIN_WORLD_WIDE_13 = 0x0A,
+ RT_CHANNEL_DOMAIN_TAIWAN = 0x0B,
+ RT_CHANNEL_DOMAIN_CHINA = 0x0C,
+ RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO = 0x0D,
+ RT_CHANNEL_DOMAIN_KOREA = 0x0E,
+ RT_CHANNEL_DOMAIN_TURKEY = 0x0F,
+ RT_CHANNEL_DOMAIN_JAPAN = 0x10,
+ RT_CHANNEL_DOMAIN_FCC_NO_DFS = 0x11,
+ RT_CHANNEL_DOMAIN_JAPAN_NO_DFS = 0x12,
+ RT_CHANNEL_DOMAIN_WORLD_WIDE_5G = 0x13,
+ RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS = 0x14,
+
+ /* new channel plan mapping, (2GDOMAIN_5GDOMAIN) ===== */
+ RT_CHANNEL_DOMAIN_WORLD_NULL = 0x20,
+ RT_CHANNEL_DOMAIN_ETSI1_NULL = 0x21,
+ RT_CHANNEL_DOMAIN_FCC1_NULL = 0x22,
+ RT_CHANNEL_DOMAIN_MKK1_NULL = 0x23,
+ RT_CHANNEL_DOMAIN_ETSI2_NULL = 0x24,
+ RT_CHANNEL_DOMAIN_FCC1_FCC1 = 0x25,
+ RT_CHANNEL_DOMAIN_WORLD_ETSI1 = 0x26,
+ RT_CHANNEL_DOMAIN_MKK1_MKK1 = 0x27,
+ RT_CHANNEL_DOMAIN_WORLD_KCC1 = 0x28,
+ RT_CHANNEL_DOMAIN_WORLD_FCC2 = 0x29,
+ RT_CHANNEL_DOMAIN_WORLD_FCC3 = 0x30,
+ RT_CHANNEL_DOMAIN_WORLD_FCC4 = 0x31,
+ RT_CHANNEL_DOMAIN_WORLD_FCC5 = 0x32,
+ RT_CHANNEL_DOMAIN_WORLD_FCC6 = 0x33,
+ RT_CHANNEL_DOMAIN_FCC1_FCC7 = 0x34,
+ RT_CHANNEL_DOMAIN_WORLD_ETSI2 = 0x35,
+ RT_CHANNEL_DOMAIN_WORLD_ETSI3 = 0x36,
+ RT_CHANNEL_DOMAIN_MKK1_MKK2 = 0x37,
+ RT_CHANNEL_DOMAIN_MKK1_MKK3 = 0x38,
+ RT_CHANNEL_DOMAIN_FCC1_NCC1 = 0x39,
+ RT_CHANNEL_DOMAIN_FCC1_NCC2 = 0x40,
+ RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G = 0x41,
+ /* Add new channel plan above this line=============== */
+ RT_CHANNEL_DOMAIN_MAX,
+ RT_CHANNEL_DOMAIN_REALTEK_DEFINE = 0x7F,
+};
+
+enum RT_CHANNEL_DOMAIN_2G {
+ RT_CHANNEL_DOMAIN_2G_WORLD = 0x00, /* Worldwide 13 */
+ RT_CHANNEL_DOMAIN_2G_ETSI1 = 0x01, /* Europe */
+ RT_CHANNEL_DOMAIN_2G_FCC1 = 0x02, /* US */
+ RT_CHANNEL_DOMAIN_2G_MKK1 = 0x03, /* Japan */
+ RT_CHANNEL_DOMAIN_2G_ETSI2 = 0x04, /* France */
+ RT_CHANNEL_DOMAIN_2G_NULL = 0x05,
+ /* Add new channel plan above this line=============== */
+ RT_CHANNEL_DOMAIN_2G_MAX,
+};
+
+#define rtw_is_channel_plan_valid(chplan) \
+ (chplan < RT_CHANNEL_DOMAIN_MAX || \
+ chplan == RT_CHANNEL_DOMAIN_REALTEK_DEFINE)
+
+struct rt_channel_plan {
+ unsigned char Channel[MAX_CHANNEL_NUM];
+ unsigned char Len;
+};
+
+struct rt_channel_plan_2g {
+ unsigned char Channel[MAX_CHANNEL_NUM_2G];
+ unsigned char Len;
+};
+
+struct rt_channel_plan_map {
+ unsigned char Index2G;
+};
+
+static const struct {
+ int channel_plan;
+ char *name;
+} channel_table[] = { { RT_CHANNEL_DOMAIN_FCC, "US" },
+ { RT_CHANNEL_DOMAIN_ETSI, "EU" },
+ { RT_CHANNEL_DOMAIN_MKK, "JP" },
+ { RT_CHANNEL_DOMAIN_CHINA, "CN"} };
+
+enum Associated_AP {
+ atherosAP = 0,
+ broadcomAP = 1,
+ ciscoAP = 2,
+ marvellAP = 3,
+ ralinkAP = 4,
+ realtekAP = 5,
+ airgocapAP = 6,
+ unknownAP = 7,
+ maxAP,
+};
+
+enum HT_IOT_PEER {
+ HT_IOT_PEER_UNKNOWN = 0,
+ HT_IOT_PEER_REALTEK = 1,
+ HT_IOT_PEER_REALTEK_92SE = 2,
+ HT_IOT_PEER_BROADCOM = 3,
+ HT_IOT_PEER_RALINK = 4,
+ HT_IOT_PEER_ATHEROS = 5,
+ HT_IOT_PEER_CISCO = 6,
+ HT_IOT_PEER_MERU = 7,
+ HT_IOT_PEER_MARVELL = 8,
+ HT_IOT_PEER_REALTEK_SOFTAP = 9,/* peer is RealTek SOFT_AP */
+ HT_IOT_PEER_SELF_SOFTAP = 10, /* Self is SoftAP */
+ HT_IOT_PEER_AIRGO = 11,
+ HT_IOT_PEER_INTEL = 12,
+ HT_IOT_PEER_RTK_APCLIENT = 13,
+ HT_IOT_PEER_REALTEK_81XX = 14,
+ HT_IOT_PEER_REALTEK_WOW = 15,
+ HT_IOT_PEER_TENDA = 16,
+ HT_IOT_PEER_MAX = 17
+};
+
+enum SCAN_STATE {
+ SCAN_DISABLE = 0,
+ SCAN_START = 1,
+ SCAN_TXNULL = 2,
+ SCAN_PROCESS = 3,
+ SCAN_COMPLETE = 4,
+ SCAN_STATE_MAX,
+};
+
+struct mlme_handler {
+ unsigned int num;
+ const char *str;
+ unsigned int (*func)(struct adapter *adapt, struct recv_frame *frame);
+};
+
+struct action_handler {
+ unsigned int num;
+ const char *str;
+ unsigned int (*func)(struct adapter *adapt, struct recv_frame *frame);
+};
+
+struct ss_res {
+ int state;
+ int bss_cnt;
+ int channel_idx;
+ int scan_mode;
+ u8 ssid_num;
+ u8 ch_num;
+ struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT];
+ struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT];
+};
+
+/* define AP_MODE 0x0C */
+/* define STATION_MODE 0x08 */
+/* define AD_HOC_MODE 0x04 */
+/* define NO_LINK_MODE 0x00 */
+
+#define WIFI_FW_NULL_STATE _HW_STATE_NOLINK_
+#define WIFI_FW_STATION_STATE _HW_STATE_STATION_
+#define WIFI_FW_AP_STATE _HW_STATE_AP_
+#define WIFI_FW_ADHOC_STATE _HW_STATE_ADHOC_
+
+#define WIFI_FW_AUTH_NULL 0x00000100
+#define WIFI_FW_AUTH_STATE 0x00000200
+#define WIFI_FW_AUTH_SUCCESS 0x00000400
+
+#define WIFI_FW_ASSOC_STATE 0x00002000
+#define WIFI_FW_ASSOC_SUCCESS 0x00004000
+
+#define WIFI_FW_LINKING_STATE (WIFI_FW_AUTH_NULL | \
+ WIFI_FW_AUTH_STATE | \
+ WIFI_FW_AUTH_SUCCESS | \
+ WIFI_FW_ASSOC_STATE)
+
+struct FW_Sta_Info {
+ struct sta_info *psta;
+ u32 status;
+ u32 rx_pkt;
+ u32 retry;
+ unsigned char SupportedRates[NDIS_802_11_LENGTH_RATES_EX];
+};
+
+/*
+ * Usage:
+ * When one iface acted as AP mode and the other iface is STA mode and scanning,
+ * it should switch back to AP's operating channel periodically.
+ * Parameters info:
+ * When the driver scanned RTW_SCAN_NUM_OF_CH channels, it would switch back to
+ * AP's operating channel for
+ * RTW_STAY_AP_CH_MILLISECOND * SURVEY_TO milliseconds.
+ * Example:
+ * For chip supports 2.4G + 5GHz and AP mode is operating in channel 1,
+ * RTW_SCAN_NUM_OF_CH is 8, RTW_STAY_AP_CH_MS is 3 and SURVEY_TO is 100.
+ * When it's STA mode gets set_scan command,
+ * it would
+ * 1. Doing the scan on channel 1.2.3.4.5.6.7.8
+ * 2. Back to channel 1 for 300 milliseconds
+ * 3. Go through doing site survey on channel 9.10.11.36.40.44.48.52
+ * 4. Back to channel 1 for 300 milliseconds
+ * 5. ... and so on, till survey done.
+ */
+
+struct mlme_ext_info {
+ u32 state;
+ u32 reauth_count;
+ u32 reassoc_count;
+ u32 link_count;
+ u32 auth_seq;
+ u32 auth_algo; /* 802.11 auth, could be open, shared, auto */
+ u32 authModeToggle;
+ u32 enc_algo;/* encrypt algorithm; */
+ u32 key_index; /* this is only valid for legacy wep,
+ * 0~3 for key id.
+ */
+ u32 iv;
+ u8 chg_txt[128];
+ u16 aid;
+ u16 bcn_interval;
+ u16 capability;
+ u8 assoc_AP_vendor;
+ u8 slotTime;
+ u8 preamble_mode;
+ u8 WMM_enable;
+ u8 ERP_enable;
+ u8 ERP_IE;
+ u8 HT_enable;
+ u8 HT_caps_enable;
+ u8 HT_info_enable;
+ u8 HT_protection;
+ u8 turboMode_cts2self;
+ u8 turboMode_rtsen;
+ u8 SM_PS;
+ u8 agg_enable_bitmap;
+ u8 ADDBA_retry_count;
+ u8 candidate_tid_bitmap;
+ u8 dialogToken;
+ /* Accept ADDBA Request */
+ bool accept_addba_req;
+ u8 bwmode_updated;
+ u8 hidden_ssid_mode;
+
+ struct ADDBA_request ADDBA_req;
+ struct WMM_para_element WMM_param;
+ struct ieee80211_ht_cap HT_caps;
+ struct HT_info_element HT_info;
+ struct wlan_bssid_ex network;/* join network or bss_network,
+ * if in ap mode, it is the same
+ * as cur_network.network
+ */
+ struct FW_Sta_Info FW_sta_info[NUM_STA];
+};
+
+/* The channel information about this channel including joining,
+ * scanning, and power constraints.
+ */
+struct rt_channel_info {
+ u8 ChannelNum; /* The channel number. */
+ enum rt_scan_type ScanType; /* Scan type such as passive
+ * or active scan.
+ */
+ u32 rx_count;
+};
+
+int rtw_ch_set_search_ch(struct rt_channel_info *ch_set, const u32 ch);
+
+/* P2P_MAX_REG_CLASSES - Maximum number of regulatory classes */
+#define P2P_MAX_REG_CLASSES 10
+
+/* P2P_MAX_REG_CLASS_CHANNELS - Maximum number of chan per regulatory class */
+#define P2P_MAX_REG_CLASS_CHANNELS 20
+
+/* struct p2p_channels - List of supported channels */
+struct p2p_channels {
+ /* struct p2p_reg_class - Supported regulatory class */
+ struct p2p_reg_class {
+ /* reg_class - Regulatory class (IEEE 802.11-2007, Annex J) */
+ u8 reg_class;
+
+ /* channel - Supported channels */
+ u8 channel[P2P_MAX_REG_CLASS_CHANNELS];
+
+ /* channels - Number of channel entries in use */
+ size_t channels;
+ } reg_class[P2P_MAX_REG_CLASSES];
+
+ /* reg_classes - Number of reg_class entries in use */
+ size_t reg_classes;
+};
+
+struct p2p_oper_class_map {
+ enum hw_mode {IEEE80211G} mode;
+ u8 op_class;
+ u8 min_chan;
+ u8 max_chan;
+ u8 inc;
+ enum {BW20, BW40PLUS, BW40MINUS} bw;
+};
+
+struct mlme_ext_priv {
+ struct adapter *padapter;
+ u8 mlmeext_init;
+ atomic_t event_seq;
+ u16 mgnt_seq;
+
+ unsigned char cur_channel;
+ unsigned char cur_bwmode;
+ unsigned char cur_ch_offset;/* PRIME_CHNL_OFFSET */
+ unsigned char cur_wireless_mode; /* NETWORK_TYPE */
+
+ unsigned char oper_channel; /* saved chan info when call
+ * set_channel_bw
+ */
+ unsigned char oper_bwmode;
+ unsigned char oper_ch_offset;/* PRIME_CHNL_OFFSET */
+
+ unsigned char max_chan_nums;
+ struct rt_channel_info channel_set[MAX_CHANNEL_NUM];
+ struct p2p_channels channel_list;
+ unsigned char basicrate[NumRates];
+ unsigned char datarate[NumRates];
+
+ struct ss_res sitesurvey_res;
+ struct mlme_ext_info mlmext_info;/* for sta/adhoc mode, including
+ * current scan/connecting/connected
+ * related info. For ap mode,
+ * network includes ap's cap_info
+ */
+ struct timer_list survey_timer;
+ struct timer_list link_timer;
+ u16 chan_scan_time;
+
+ u8 scan_abort;
+ u8 tx_rate; /* TXRATE when USERATE is set. */
+
+ u32 retry; /* retry for issue probereq */
+
+ u64 TSFValue;
+
+#ifdef CPTCFG_88EU_AP_MODE
+ unsigned char bstart_bss;
+#endif
+ u8 update_channel_plan_by_ap_done;
+ /* recv_decache check for Action_public frame */
+ u8 action_public_dialog_token;
+ u16 action_public_rxseq;
+ u8 active_keep_alive_check;
+};
+
+int init_mlme_ext_priv(struct adapter *adapter);
+int init_hw_mlme_ext(struct adapter *padapter);
+void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext);
+void init_mlme_ext_timer(struct adapter *padapter);
+void init_addba_retry_timer(struct adapter *adapt, struct sta_info *sta);
+struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv);
+
+unsigned char networktype_to_raid(unsigned char network_type);
+u8 judge_network_type(struct adapter *padapter, unsigned char *rate, int len);
+void get_rate_set(struct adapter *padapter, unsigned char *pbssrate, int *len);
+void UpdateBrateTbl(struct adapter *padapter, u8 *mBratesOS);
+void UpdateBrateTblForSoftAP(u8 *bssrateset, u32 bssratelen);
+
+void Save_DM_Func_Flag(struct adapter *padapter);
+void Restore_DM_Func_Flag(struct adapter *padapter);
+void Switch_DM_Func(struct adapter *padapter, u32 mode, u8 enable);
+
+void Set_MSR(struct adapter *padapter, u8 type);
+
+u8 rtw_get_oper_ch(struct adapter *adapter);
+void rtw_set_oper_ch(struct adapter *adapter, u8 ch);
+void rtw_set_oper_bw(struct adapter *adapter, u8 bw);
+void rtw_set_oper_choffset(struct adapter *adapter, u8 offset);
+
+void set_channel_bwmode(struct adapter *padapter, unsigned char channel,
+ unsigned char channel_offset, unsigned short bwmode);
+void SelectChannel(struct adapter *padapter, unsigned char channel);
+void SetBWMode(struct adapter *padapter, unsigned short bwmode,
+ unsigned char channel_offset);
+
+unsigned int decide_wait_for_beacon_timeout(unsigned int bcn_interval);
+
+void write_cam(struct adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key);
+void clear_cam_entry(struct adapter *padapter, u8 entry);
+
+void invalidate_cam_all(struct adapter *padapter);
+
+int allocate_fw_sta_entry(struct adapter *padapter);
+void flush_all_cam_entry(struct adapter *padapter);
+
+void update_network(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
+ struct adapter *adapter, bool update_ie);
+
+u16 get_beacon_interval(struct wlan_bssid_ex *bss);
+
+int is_client_associated_to_ap(struct adapter *padapter);
+int is_client_associated_to_ibss(struct adapter *padapter);
+int is_IBSS_empty(struct adapter *padapter);
+
+unsigned char check_assoc_AP(u8 *pframe, uint len);
+
+int WMM_param_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE);
+void WMMOnAssocRsp(struct adapter *padapter);
+
+void HT_caps_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE);
+void HT_info_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE);
+void HTOnAssocRsp(struct adapter *padapter);
+
+void ERP_IE_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE);
+void VCS_update(struct adapter *padapter, struct sta_info *psta);
+
+void update_beacon_info(struct adapter *padapter, u8 *pframe, uint len,
+ struct sta_info *psta);
+int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len);
+void update_IOT_info(struct adapter *padapter);
+void update_capinfo(struct adapter *adapter, u16 updatecap);
+void update_wireless_mode(struct adapter *padapter);
+void update_tx_basic_rate(struct adapter *padapter, u8 modulation);
+void update_bmc_sta_support_rate(struct adapter *padapter, u32 mac_id);
+int update_sta_support_rate(struct adapter *padapter, u8 *pvar_ie,
+ uint var_ie_len, int cam_idx);
+
+/* for sta/adhoc mode */
+void update_sta_info(struct adapter *padapter, struct sta_info *psta);
+unsigned int update_basic_rate(unsigned char *ptn, unsigned int ptn_sz);
+unsigned int update_supported_rate(unsigned char *ptn, unsigned int ptn_sz);
+unsigned int update_MSC_rate(struct ieee80211_ht_cap *pHT_caps);
+void Update_RA_Entry(struct adapter *padapter, u32 mac_id);
+void set_sta_rate(struct adapter *padapter, struct sta_info *psta);
+
+unsigned char get_highest_rate_idx(u32 mask);
+int support_short_GI(struct adapter *padapter, struct ieee80211_ht_cap *caps);
+unsigned int is_ap_in_tkip(struct adapter *padapter);
+
+void report_join_res(struct adapter *padapter, int res);
+void report_survey_event(struct adapter *padapter,
+ struct recv_frame *precv_frame);
+void report_surveydone_event(struct adapter *padapter);
+void report_del_sta_event(struct adapter *padapter,
+ unsigned char *addr, unsigned short reason);
+void report_add_sta_event(struct adapter *padapter, unsigned char *addr,
+ int cam_idx);
+
+u8 set_tx_beacon_cmd(struct adapter *padapter);
+unsigned int setup_beacon_frame(struct adapter *padapter,
+ unsigned char *beacon_frame);
+void update_mgnt_tx_rate(struct adapter *padapter, u8 rate);
+void update_mgntframe_attrib(struct adapter *padapter,
+ struct pkt_attrib *pattrib);
+
+int issue_nulldata(struct adapter *padapter, unsigned char *da,
+ unsigned int power_mode, int try_cnt, int wait_ms);
+int issue_qos_nulldata(struct adapter *padapter, unsigned char *da,
+ u16 tid, int try_cnt, int wait_ms);
+int issue_deauth(struct adapter *padapter, unsigned char *da,
+ unsigned short reason);
+unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr);
+unsigned int send_beacon(struct adapter *padapter);
+
+void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res);
+void mlmeext_sta_del_event_callback(struct adapter *padapter);
+void mlmeext_sta_add_event_callback(struct adapter *padapter,
+ struct sta_info *psta);
+
+void linked_status_chk(struct adapter *padapter);
+
+void survey_timer_hdl(struct timer_list *t);
+void link_timer_hdl(struct timer_list *t);
+void addba_timer_hdl(struct timer_list *t);
+
+#define set_survey_timer(mlmeext, ms) \
+ mod_timer(&mlmeext->survey_timer, jiffies + \
+ msecs_to_jiffies(ms))
+
+#define set_link_timer(mlmeext, ms) \
+ mod_timer(&mlmeext->link_timer, jiffies + \
+ msecs_to_jiffies(ms))
+
+bool cckrates_included(unsigned char *rate, int ratelen);
+bool cckratesonly_included(unsigned char *rate, int ratelen);
+
+void process_addba_req(struct adapter *padapter, u8 *paddba_req, u8 *addr);
+
+void update_TSF(struct mlme_ext_priv *pmlmeext, u8 *pframe, uint len);
+void correct_TSF(struct adapter *padapter, struct mlme_ext_priv *pmlmeext);
+
+struct cmd_hdl {
+ uint parmsize;
+ u8 (*h2cfuns)(struct adapter *padapter, u8 *pbuf);
+};
+
+u8 read_macreg_hdl(struct adapter *padapter, u8 *pbuf);
+u8 write_macreg_hdl(struct adapter *padapter, u8 *pbuf);
+u8 read_bbreg_hdl(struct adapter *padapter, u8 *pbuf);
+u8 write_bbreg_hdl(struct adapter *padapter, u8 *pbuf);
+u8 read_rfreg_hdl(struct adapter *padapter, u8 *pbuf);
+u8 write_rfreg_hdl(struct adapter *padapter, u8 *pbuf);
+u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf);
+u8 disconnect_hdl(struct adapter *padapter, u8 *pbuf);
+u8 createbss_hdl(struct adapter *padapter, u8 *pbuf);
+u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf);
+u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf);
+u8 setauth_hdl(struct adapter *padapter, u8 *pbuf);
+u8 setkey_hdl(struct adapter *padapter, u8 *pbuf);
+u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf);
+u8 set_assocsta_hdl(struct adapter *padapter, u8 *pbuf);
+u8 del_assocsta_hdl(struct adapter *padapter, u8 *pbuf);
+u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf);
+
+u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf);
+u8 h2c_msg_hdl(struct adapter *padapter, unsigned char *pbuf);
+u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf);
+u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf);
+u8 set_chplan_hdl(struct adapter *padapter, unsigned char *pbuf);
+u8 led_blink_hdl(struct adapter *padapter, unsigned char *pbuf);
+/* Handling DFS channel switch announcement ie. */
+u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf);
+u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf);
+
+#ifdef _RTW_CMD_C_
+
+static struct cmd_hdl wlancmds[] = {
+ {sizeof(struct wlan_bssid_ex), join_cmd_hdl},
+ {sizeof(struct disconnect_parm), disconnect_hdl},
+ {sizeof(struct wlan_bssid_ex), createbss_hdl},
+ {sizeof(struct setopmode_parm), setopmode_hdl},
+ {sizeof(struct sitesurvey_parm), sitesurvey_cmd_hdl},
+ {sizeof(struct setauth_parm), setauth_hdl},
+ {sizeof(struct setkey_parm), setkey_hdl},
+ {sizeof(struct set_stakey_parm), set_stakey_hdl},
+ {sizeof(struct set_assocsta_parm), NULL},
+ {sizeof(struct addBaReq_parm), add_ba_hdl},
+ {sizeof(struct set_ch_parm), set_ch_hdl},
+ {sizeof(struct wlan_bssid_ex), tx_beacon_hdl},
+ {0, mlme_evt_hdl},
+ {0, rtw_drvextra_cmd_hdl},
+ {sizeof(struct SetChannelPlan_param), set_chplan_hdl}
+};
+
+#endif
+
+struct C2HEvent_Header {
+#ifdef __LITTLE_ENDIAN
+ unsigned int len:16;
+ unsigned int ID:8;
+ unsigned int seq:8;
+#elif defined(__BIG_ENDIAN)
+ unsigned int seq:8;
+ unsigned int ID:8;
+ unsigned int len:16;
+#endif
+ unsigned int rsvd;
+};
+
+void rtw_dummy_event_callback(struct adapter *adapter, u8 *pbuf);
+void rtw_fwdbg_event_callback(struct adapter *adapter, u8 *pbuf);
+
+enum rtw_c2h_event {
+ _Read_MACREG_EVT_ = 0, /*0*/
+ _Read_BBREG_EVT_,
+ _Read_RFREG_EVT_,
+ _Read_EEPROM_EVT_,
+ _Read_EFUSE_EVT_,
+ _Read_CAM_EVT_, /*5*/
+ _Get_BasicRate_EVT_,
+ _Get_DataRate_EVT_,
+ _Survey_EVT_, /*8*/
+ _SurveyDone_EVT_, /*9*/
+
+ _JoinBss_EVT_, /*10*/
+ _AddSTA_EVT_,
+ _DelSTA_EVT_,
+ _AtimDone_EVT_,
+ _TX_Report_EVT_,
+ _CCX_Report_EVT_, /*15*/
+ _DTM_Report_EVT_,
+ _TX_Rate_Statistics_EVT_,
+ _C2HLBK_EVT_,
+ _FWDBG_EVT_,
+ _C2HFEEDBACK_EVT_, /*20*/
+ _ADDBA_EVT_,
+ _C2HBCN_EVT_,
+ _ReportPwrState_EVT_, /* filen: only for PCIE, USB */
+ _CloseRF_EVT_, /* filen: only for PCIE,
+ * work around ASPM
+ */
+ MAX_C2HEVT
+};
+
+
+#ifdef _RTW_MLME_EXT_C_
+
+static struct fwevent wlanevents[] = {
+ {0, rtw_dummy_event_callback}, /*0*/
+ {0, NULL},
+ {0, NULL},
+ {0, NULL},
+ {0, NULL},
+ {0, NULL},
+ {0, NULL},
+ {0, NULL},
+ {0, &rtw_survey_event_callback}, /*8*/
+ {sizeof(struct surveydone_event), &rtw_surveydone_event_callback},/*9*/
+ {0, &rtw_joinbss_event_callback}, /*10*/
+ {sizeof(struct stassoc_event), &rtw_stassoc_event_callback},
+ {sizeof(struct stadel_event), &rtw_stadel_event_callback},
+ {0, &rtw_atimdone_event_callback},
+ {0, rtw_dummy_event_callback},
+ {0, NULL}, /*15*/
+ {0, NULL},
+ {0, NULL},
+ {0, NULL},
+ {0, rtw_fwdbg_event_callback},
+ {0, NULL}, /*20*/
+ {0, NULL},
+ {0, NULL},
+ {0, &rtw_cpwm_event_callback},
+ {0, NULL},
+};
+
+#endif/* _RTL_MLME_EXT_C_ */
+
+#endif /* __RTW_MLME_EXT_H_ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h b/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h
new file mode 100644
index 0000000..4046349
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h
@@ -0,0 +1,245 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __RTW_PWRCTRL_H_
+#define __RTW_PWRCTRL_H_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+
+#define FW_PWR0 0
+#define FW_PWR1 1
+#define FW_PWR2 2
+#define FW_PWR3 3
+#define HW_PWR0 7
+#define HW_PWR1 6
+#define HW_PWR2 2
+#define HW_PWR3 0
+#define HW_PWR4 8
+
+#define FW_PWRMSK 0x7
+
+#define XMIT_ALIVE BIT(0)
+#define RECV_ALIVE BIT(1)
+#define CMD_ALIVE BIT(2)
+#define EVT_ALIVE BIT(3)
+
+enum power_mgnt {
+ PS_MODE_ACTIVE = 0,
+ PS_MODE_MIN,
+ PS_MODE_MAX,
+ PS_MODE_DTIM,
+ PS_MODE_VOIP,
+ PS_MODE_UAPSD_WMM,
+ PS_MODE_UAPSD,
+ PS_MODE_IBSS,
+ PS_MODE_WWLAN,
+ PM_Radio_Off,
+ PM_Card_Disable,
+ PS_MODE_NUM
+};
+
+/*
+ * BIT[2:0] = HW state
+ * BIT[3] = Protocol PS state, 0: register active state,
+ * 1: register sleep state
+ * BIT[4] = sub-state
+ */
+
+#define PS_DPS BIT(0)
+#define PS_LCLK (PS_DPS)
+#define PS_RF_OFF BIT(1)
+#define PS_ALL_ON BIT(2)
+#define PS_ST_ACTIVE BIT(3)
+
+#define PS_ISR_ENABLE BIT(4)
+#define PS_IMR_ENABLE BIT(5)
+#define PS_ACK BIT(6)
+#define PS_TOGGLE BIT(7)
+
+#define PS_STATE_MASK (0x0F)
+#define PS_STATE_HW_MASK (0x07)
+#define PS_SEQ_MASK (0xc0)
+
+#define PS_STATE(x) (PS_STATE_MASK & (x))
+#define PS_STATE_HW(x) (PS_STATE_HW_MASK & (x))
+#define PS_SEQ(x) (PS_SEQ_MASK & (x))
+
+#define PS_STATE_S0 (PS_DPS)
+#define PS_STATE_S1 (PS_LCLK)
+#define PS_STATE_S2 (PS_RF_OFF)
+#define PS_STATE_S3 (PS_ALL_ON)
+#define PS_STATE_S4 ((PS_ST_ACTIVE) | (PS_ALL_ON))
+
+#define PS_IS_RF_ON(x) ((x) & (PS_ALL_ON))
+#define PS_IS_ACTIVE(x) ((x) & (PS_ST_ACTIVE))
+#define CLR_PS_STATE(x) ((x) = ((x) & (0xF0)))
+
+struct reportpwrstate_parm {
+ unsigned char mode;
+ unsigned char state; /* the CPWM value */
+ unsigned short rsvd;
+};
+
+#define LPS_DELAY_TIME 1*HZ /* 1 sec */
+
+#define EXE_PWR_NONE 0x01
+#define EXE_PWR_IPS 0x02
+#define EXE_PWR_LPS 0x04
+
+/* RF state. */
+enum rt_rf_power_state {
+ rf_on, /* RF is on after RFSleep or RFOff */
+ rf_sleep, /* 802.11 Power Save mode */
+ rf_off, /* HW/SW Radio OFF or Inactive Power Save */
+ /* Add the new RF state above this line===== */
+ rf_max
+};
+
+/* RF Off Level for IPS or HW/SW radio off */
+#define RT_RF_OFF_LEVL_ASPM BIT(0) /* PCI ASPM */
+#define RT_RF_OFF_LEVL_CLK_REQ BIT(1) /* PCI clock request */
+#define RT_RF_OFF_LEVL_PCI_D3 BIT(2) /* PCI D3 mode */
+#define RT_RF_OFF_LEVL_HALT_NIC BIT(3) /* NIC halt, re-init hw param*/
+#define RT_RF_OFF_LEVL_FREE_FW BIT(4) /* FW free, re-download the FW*/
+#define RT_RF_OFF_LEVL_FW_32K BIT(5) /* FW in 32k */
+#define RT_RF_PS_LEVEL_ALWAYS_ASPM BIT(6) /* Always enable ASPM and Clock
+ * Req in initialization.
+ */
+#define RT_RF_LPS_DISALBE_2R BIT(30) /* When LPS is on, disable 2R
+ * if no packet is RX or TX.
+ */
+#define RT_RF_LPS_LEVEL_ASPM BIT(31) /* LPS with ASPM */
+
+#define RT_IN_PS_LEVEL(ppsc, _PS_FLAG) \
+ ((ppsc->cur_ps_level & _PS_FLAG) ? true : false)
+#define RT_CLEAR_PS_LEVEL(ppsc, _PS_FLAG) \
+ (ppsc->cur_ps_level &= (~(_PS_FLAG)))
+#define RT_SET_PS_LEVEL(ppsc, _PS_FLAG) \
+ (ppsc->cur_ps_level |= _PS_FLAG)
+
+enum _PS_BBRegBackup_ {
+ PSBBREG_RF0 = 0,
+ PSBBREG_RF1,
+ PSBBREG_RF2,
+ PSBBREG_AFE0,
+ PSBBREG_TOTALCNT
+};
+
+enum { /* for ips_mode */
+ IPS_NONE = 0,
+ IPS_NORMAL,
+ IPS_LEVEL_2,
+};
+
+struct pwrctrl_priv {
+ struct mutex mutex_lock;
+ volatile u8 rpwm; /* requested power state for fw */
+ volatile u8 cpwm; /* fw current power state. updated when
+ * 1. read from HCPWM 2. driver lowers power level
+ */
+ volatile u8 tog; /* toggling */
+ volatile u8 cpwm_tog; /* toggling */
+
+ u8 pwr_mode;
+ u8 smart_ps;
+ u8 bcn_ant_mode;
+
+ u32 alives;
+ struct work_struct cpwm_event;
+ u8 bpower_saving;
+
+ u8 b_hw_radio_off;
+ u8 reg_rfoff;
+ u8 reg_pdnmode; /* powerdown mode */
+ u32 rfoff_reason;
+
+ /* RF OFF Level */
+ u32 cur_ps_level;
+ u32 reg_rfps_level;
+ uint ips_enter_cnts;
+ uint ips_leave_cnts;
+
+ u8 ips_mode;
+ u8 ips_mode_req; /* used to accept the mode setting request,
+ * will update to ipsmode later
+ */
+ uint bips_processing;
+ unsigned long ips_deny_time; /* will deny IPS when system time less than this */
+ u8 ps_processing; /* temp used to mark whether in rtw_ps_processor */
+
+ u8 bLeisurePs;
+ u8 LpsIdleCount;
+ u8 power_mgnt;
+ u8 bFwCurrentInPSMode;
+ u32 DelayLPSLastTimeStamp;
+ u8 btcoex_rfon;
+ s32 pnp_current_pwr_state;
+ u8 pnp_bstop_trx;
+
+ u8 bInternalAutoSuspend;
+ u8 bInSuspend;
+ u8 bSupportRemoteWakeup;
+ struct timer_list pwr_state_check_timer;
+ int pwr_state_check_interval;
+ u8 pwr_state_check_cnts;
+
+ int ps_flag;
+
+ enum rt_rf_power_state rf_pwrstate;/* cur power state */
+ enum rt_rf_power_state change_rfpwrstate;
+
+ u8 wepkeymask;
+ u8 bHWPowerdown;/* if support hw power down */
+ u8 bHWPwrPindetect;
+ u8 bkeepfwalive;
+ u8 brfoffbyhw;
+ unsigned long PS_BBRegBackup[PSBBREG_TOTALCNT];
+};
+
+#define rtw_get_ips_mode_req(pwrctrlpriv) \
+ (pwrctrlpriv)->ips_mode_req
+
+#define rtw_ips_mode_req(pwrctrlpriv, ips_mode) \
+ ((pwrctrlpriv)->ips_mode_req = (ips_mode))
+
+#define RTW_PWR_STATE_CHK_INTERVAL 2000
+
+#define _rtw_set_pwr_state_check_timer(pwrctrlpriv, ms) \
+ mod_timer(&pwrctrlpriv->pwr_state_check_timer, \
+ jiffies + msecs_to_jiffies(ms))
+
+#define rtw_set_pwr_state_check_timer(pwrctrl) \
+ _rtw_set_pwr_state_check_timer((pwrctrl), \
+ (pwrctrl)->pwr_state_check_interval)
+
+void rtw_init_pwrctrl_priv(struct adapter *adapter);
+
+void rtw_set_ps_mode(struct adapter *adapter, u8 ps_mode, u8 smart_ps,
+ u8 bcn_ant_mode);
+void rtw_set_rpwm(struct adapter *adapter, u8 val8);
+void LeaveAllPowerSaveMode(struct adapter *adapter);
+void ips_enter(struct adapter *padapter);
+int ips_leave(struct adapter *padapter);
+
+void rtw_ps_processor(struct adapter *padapter);
+
+enum rt_rf_power_state RfOnOffDetect(struct adapter *iadapter);
+
+s32 LPS_RF_ON_check(struct adapter *adapter, u32 delay_ms);
+void LPS_Enter(struct adapter *adapter);
+void LPS_Leave(struct adapter *adapter);
+
+int _rtw_pwr_wakeup(struct adapter *adapter, u32 ips_defer_ms,
+ const char *caller);
+#define rtw_pwr_wakeup(adapter) \
+ _rtw_pwr_wakeup(adapter, RTW_PWR_STATE_CHK_INTERVAL, __func__)
+#define rtw_pwr_wakeup_ex(adapter, ips_deffer_ms) \
+ _rtw_pwr_wakeup(adapter, ips_deffer_ms, __func__)
+int rtw_pm_set_ips(struct adapter *adapter, u8 mode);
+int rtw_pm_set_lps(struct adapter *adapter, u8 mode);
+
+#endif /* __RTL871X_PWRCTRL_H_ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_recv.h b/drivers/staging/rtl8188eu/include/rtw_recv.h
new file mode 100644
index 0000000..8fc5004
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtw_recv.h
@@ -0,0 +1,264 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef _RTW_RECV_H_
+#define _RTW_RECV_H_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+
+
+#define NR_RECVFRAME 256
+
+#define RXFRAME_ALIGN 8
+#define RXFRAME_ALIGN_SZ (1<<RXFRAME_ALIGN)
+
+#define MAX_RXFRAME_CNT 512
+#define MAX_RX_NUMBLKS (32)
+#define RECVFRAME_HDR_ALIGN 128
+
+#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
+
+#define MAX_SUBFRAME_COUNT 64
+
+/* for Rx reordering buffer control */
+struct recv_reorder_ctrl {
+ struct adapter *padapter;
+ bool enable;
+ u16 indicate_seq;/* wstart_b, init_value=0xffff */
+ u16 wend_b;
+ u8 wsize_b;
+ struct __queue pending_recvframe_queue;
+ struct timer_list reordering_ctrl_timer;
+};
+
+struct stainfo_rxcache {
+ u16 tid_rxseq[16];
+/*
+ * unsigned short tid0_rxseq;
+ * unsigned short tid1_rxseq;
+ * unsigned short tid2_rxseq;
+ * unsigned short tid3_rxseq;
+ * unsigned short tid4_rxseq;
+ * unsigned short tid5_rxseq;
+ * unsigned short tid6_rxseq;
+ * unsigned short tid7_rxseq;
+ * unsigned short tid8_rxseq;
+ * unsigned short tid9_rxseq;
+ * unsigned short tid10_rxseq;
+ * unsigned short tid11_rxseq;
+ * unsigned short tid12_rxseq;
+ * unsigned short tid13_rxseq;
+ * unsigned short tid14_rxseq;
+ * unsigned short tid15_rxseq;
+ */
+};
+
+struct signal_stat {
+ u8 update_req; /* used to indicate */
+ u8 avg_val; /* avg of valid elements */
+ u32 total_num; /* num of valid elements */
+ u32 total_val; /* sum of valid elements */
+};
+#define MAX_PATH_NUM_92CS 3
+struct phy_info {
+ u8 RxPWDBAll;
+ u8 SignalQuality; /* in 0-100 index. */
+ u8 RxMIMOSignalQuality[MAX_PATH_NUM_92CS]; /* EVM */
+ u8 RxMIMOSignalStrength[MAX_PATH_NUM_92CS];/* in 0~100 index */
+ s8 RxPower; /* in dBm Translate from PWdB */
+/* Real power in dBm for this packet, no beautification and aggregation.
+ * Keep this raw info to be used for the other procedures.
+ */
+ s8 recvpower;
+ u8 BTRxRSSIPercentage;
+ u8 SignalStrength; /* in 0-100 index. */
+ u8 RxPwr[MAX_PATH_NUM_92CS];/* per-path's pwdb */
+ u8 RxSNR[MAX_PATH_NUM_92CS];/* per-path's SNR */
+};
+
+struct rx_pkt_attrib {
+ u16 pkt_len;
+ u8 physt;
+ u8 drvinfo_sz;
+ u8 shift_sz;
+ u8 hdrlen; /* the WLAN Header Len */
+ u8 to_fr_ds;
+ u8 amsdu;
+ u8 qos;
+ u8 priority;
+ u8 pw_save;
+ u8 mdata;
+ u16 seq_num;
+ u8 frag_num;
+ u8 mfrag;
+ u8 order;
+ u8 privacy; /* in frame_ctrl field */
+ u8 bdecrypted;
+ u8 encrypt; /* when 0 indicate no encrypt. when non-zero,
+ * indicate the encrypt algorithm
+ */
+ u8 iv_len;
+ u8 icv_len;
+ u8 crc_err;
+ u8 icv_err;
+
+ u16 eth_type;
+
+ u8 dst[ETH_ALEN];
+ u8 src[ETH_ALEN];
+ u8 ta[ETH_ALEN];
+ u8 ra[ETH_ALEN];
+ u8 bssid[ETH_ALEN];
+
+ u8 ack_policy;
+
+ u8 key_index;
+
+ u8 mcs_rate;
+ u8 rxht;
+ u8 sgi;
+ u8 pkt_rpt_type;
+ u32 MacIDValidEntry[2]; /* 64 bits present 64 entry. */
+
+ struct phy_info phy_info;
+};
+
+
+/* These definition is used for Rx packet reordering. */
+#define SN_LESS(a, b) (((a - b) & 0x800) != 0)
+#define SN_EQUAL(a, b) (a == b)
+#define REORDER_WAIT_TIME (50) /* (ms) */
+
+#define RXDESC_SIZE 24
+#define RXDESC_OFFSET RXDESC_SIZE
+
+struct recv_stat {
+ __le32 rxdw0;
+ __le32 rxdw1;
+ __le32 rxdw2;
+ __le32 rxdw3;
+ __le32 rxdw4;
+ __le32 rxdw5;
+};
+
+/*
+ * accesser of recv_priv: rtw_recv_entry(dispatch / passive level);
+ * recv_thread(passive) ; returnpkt(dispatch)
+ * ; halt(passive) ;
+ *
+ * using enter_critical section to protect
+ */
+struct recv_priv {
+ struct __queue free_recv_queue;
+ struct __queue recv_pending_queue;
+ struct __queue uc_swdec_pending_queue;
+ void *pallocated_frame_buf;
+ struct adapter *adapter;
+ u32 bIsAnyNonBEPkts;
+ u64 rx_bytes;
+ u64 rx_pkts;
+ u64 rx_drop;
+ u64 last_rx_bytes;
+
+ struct tasklet_struct irq_prepare_beacon_tasklet;
+ struct tasklet_struct recv_tasklet;
+ struct sk_buff_head free_recv_skb_queue;
+ struct sk_buff_head rx_skb_queue;
+ struct recv_buf *precv_buf; /* 4 alignment */
+ struct __queue free_recv_buf_queue;
+ /* For display the phy information */
+ s8 rssi;
+ s8 rxpwdb;
+ u8 signal_strength;
+ u8 signal_qual;
+ u8 noise;
+ s8 RxRssi[2];
+
+ struct timer_list signal_stat_timer;
+ u32 signal_stat_sampling_interval;
+ struct signal_stat signal_qual_data;
+ struct signal_stat signal_strength_data;
+};
+
+#define rtw_set_signal_stat_timer(recvpriv) \
+ mod_timer(&(recvpriv)->signal_stat_timer, jiffies + \
+ msecs_to_jiffies((recvpriv)->signal_stat_sampling_interval))
+
+struct sta_recv_priv {
+ spinlock_t lock;
+ int option;
+ struct __queue defrag_q; /* keeping the fragment frame until defrag */
+ struct stainfo_rxcache rxcache;
+};
+
+struct recv_buf {
+ struct adapter *adapter;
+ struct urb *purb;
+ struct sk_buff *pskb;
+ u8 reuse;
+};
+
+/*
+ * head ----->
+ *
+ * data ----->
+ *
+ * payload
+ *
+ * tail ----->
+ *
+ *
+ * end ----->
+ *
+ * len = (unsigned int )(tail - data);
+ *
+ */
+struct recv_frame {
+ struct list_head list;
+ struct sk_buff *pkt;
+ struct adapter *adapter;
+ struct rx_pkt_attrib attrib;
+ struct sta_info *psta;
+ /* for A-MPDU Rx reordering buffer control */
+ struct recv_reorder_ctrl *preorder_ctrl;
+};
+
+struct recv_frame *_rtw_alloc_recvframe(struct __queue *pfree_recv_queue);
+struct recv_frame *rtw_alloc_recvframe(struct __queue *pfree_recv_queue);
+void rtw_init_recvframe(struct recv_frame *precvframe,
+ struct recv_priv *precvpriv);
+int rtw_free_recvframe(struct recv_frame *precvframe,
+ struct __queue *pfree_recv_queue);
+#define rtw_dequeue_recvframe(queue) rtw_alloc_recvframe(queue)
+int _rtw_enqueue_recvframe(struct recv_frame *precvframe,
+ struct __queue *queue);
+int rtw_enqueue_recvframe(struct recv_frame *precvframe, struct __queue *queue);
+void rtw_free_recvframe_queue(struct __queue *pframequeue,
+ struct __queue *pfree_recv_queue);
+u32 rtw_free_uc_swdec_pending_queue(struct adapter *adapter);
+
+void rtw_reordering_ctrl_timeout_handler(struct timer_list *t);
+
+static inline s32 translate_percentage_to_dbm(u32 sig_stren_index)
+{
+ s32 power; /* in dBm. */
+
+ /* Translate to dBm (x=0.5y-95). */
+ power = (s32)((sig_stren_index + 1) >> 1);
+ power -= 95;
+
+ return power;
+}
+
+
+struct sta_info;
+
+void _rtw_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv);
+
+void mgt_dispatcher(struct adapter *padapter, struct recv_frame *precv_frame);
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/rtw_rf.h b/drivers/staging/rtl8188eu/include/rtw_rf.h
new file mode 100644
index 0000000..b5dfb22
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtw_rf.h
@@ -0,0 +1,134 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __RTW_RF_H_
+#define __RTW_RF_H_
+
+#include <rtw_cmd.h>
+
+#define OFDM_PHY 1
+#define MIXED_PHY 2
+#define CCK_PHY 3
+
+#define NumRates (13)
+
+/* slot time for 11g */
+#define SHORT_SLOT_TIME 9
+#define NON_SHORT_SLOT_TIME 20
+
+#define RTL8711_RF_MAX_SENS 6
+#define RTL8711_RF_DEF_SENS 4
+
+/* We now define the following channels as the max channels in each
+ * channel plan.
+ */
+/* 2G, total 14 chnls */
+/* {1,2,3,4,5,6,7,8,9,10,11,12,13,14} */
+#define MAX_CHANNEL_NUM_2G 14
+#define MAX_CHANNEL_NUM 14 /* 2.4 GHz only */
+
+#define NUM_REGULATORYS 1
+
+/* Country codes */
+#define USA 0x555320
+#define EUROPE 0x1 /* temp, should be provided later */
+#define JAPAN 0x2 /* temp, should be provided later */
+
+struct regulatory_class {
+ u32 starting_freq; /* MHz, */
+ u8 channel_set[MAX_CHANNEL_NUM];
+ u8 channel_cck_power[MAX_CHANNEL_NUM]; /* dbm */
+ u8 channel_ofdm_power[MAX_CHANNEL_NUM]; /* dbm */
+ u8 txpower_limit; /* dbm */
+ u8 channel_spacing; /* MHz */
+ u8 modem;
+};
+
+enum capability {
+ cESS = 0x0001,
+ cIBSS = 0x0002,
+ cPollable = 0x0004,
+ cPollReq = 0x0008,
+ cPrivacy = 0x0010,
+ cShortPreamble = 0x0020,
+ cPBCC = 0x0040,
+ cChannelAgility = 0x0080,
+ cSpectrumMgnt = 0x0100,
+ cQos = 0x0200, /* For HCCA, use with CF-Pollable
+ * and CF-PollReq
+ */
+ cShortSlotTime = 0x0400,
+ cAPSD = 0x0800,
+ cRM = 0x1000, /* RRM (Radio Request Measurement) */
+ cDSSS_OFDM = 0x2000,
+ cDelayedBA = 0x4000,
+ cImmediateBA = 0x8000,
+};
+
+enum _REG_PREAMBLE_MODE {
+ PREAMBLE_LONG = 1,
+ PREAMBLE_AUTO = 2,
+ PREAMBLE_SHORT = 3,
+};
+
+enum _RTL8712_RF_MIMO_CONFIG_ {
+ RTL8712_RFCONFIG_1T = 0x10,
+ RTL8712_RFCONFIG_2T = 0x20,
+ RTL8712_RFCONFIG_1R = 0x01,
+ RTL8712_RFCONFIG_2R = 0x02,
+ RTL8712_RFCONFIG_1T1R = 0x11,
+ RTL8712_RFCONFIG_1T2R = 0x12,
+ RTL8712_RFCONFIG_TURBO = 0x92,
+ RTL8712_RFCONFIG_2T2R = 0x22
+};
+
+enum rf90_radio_path {
+ RF90_PATH_A = 0, /* Radio Path A */
+ RF90_PATH_B = 1, /* Radio Path B */
+ RF90_PATH_C = 2, /* Radio Path C */
+ RF90_PATH_D = 3 /* Radio Path D */
+};
+
+/* Bandwidth Offset */
+#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0
+#define HAL_PRIME_CHNL_OFFSET_LOWER 1
+#define HAL_PRIME_CHNL_OFFSET_UPPER 2
+
+/* Represent Channel Width in HT Capabilities */
+/* */
+enum ht_channel_width {
+ HT_CHANNEL_WIDTH_20 = 0,
+ HT_CHANNEL_WIDTH_40 = 1,
+ HT_CHANNEL_WIDTH_80 = 2,
+ HT_CHANNEL_WIDTH_160 = 3,
+ HT_CHANNEL_WIDTH_10 = 4,
+};
+
+/* */
+/* Represent Extension Channel Offset in HT Capabilities */
+/* This is available only in 40Mhz mode. */
+/* */
+enum ht_extchnl_offset {
+ HT_EXTCHNL_OFFSET_NO_EXT = 0,
+ HT_EXTCHNL_OFFSET_UPPER = 1,
+ HT_EXTCHNL_OFFSET_NO_DEF = 2,
+ HT_EXTCHNL_OFFSET_LOWER = 3,
+};
+
+/* 2007/11/15 MH Define different RF type. */
+enum rt_rf_type_def {
+ RF_1T2R = 0,
+ RF_2T4R = 1,
+ RF_2T2R = 2,
+ RF_1T1R = 3,
+ RF_2T2R_GREEN = 4,
+ RF_819X_MAX_TYPE = 5,
+};
+
+u32 rtw_ch2freq(u32 ch);
+
+
+#endif /* _RTL8711_RF_H_ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_security.h b/drivers/staging/rtl8188eu/include/rtw_security.h
new file mode 100644
index 0000000..9e4ef7a
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtw_security.h
@@ -0,0 +1,305 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __RTW_SECURITY_H_
+#define __RTW_SECURITY_H_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+
+#define _NO_PRIVACY_ 0x0
+#define _WEP40_ 0x1
+#define _TKIP_ 0x2
+#define _TKIP_WTMIC_ 0x3
+#define _AES_ 0x4
+#define _WEP104_ 0x5
+#define _WEP_WPA_MIXED_ 0x07 /* WEP + WPA */
+#define _SMS4_ 0x06
+
+#define is_wep_enc(alg) (((alg) == _WEP40_) || ((alg) == _WEP104_))
+
+#define _WPA_IE_ID_ 0xdd
+#define _WPA2_IE_ID_ 0x30
+
+#define SHA256_MAC_LEN 32
+#define AES_BLOCK_SIZE 16
+#define AES_PRIV_SIZE (4 * 44)
+
+enum {
+ ENCRYP_PROTOCOL_OPENSYS, /* open system */
+ ENCRYP_PROTOCOL_WEP, /* WEP */
+ ENCRYP_PROTOCOL_WPA, /* WPA */
+ ENCRYP_PROTOCOL_WPA2, /* WPA2 */
+ ENCRYP_PROTOCOL_WAPI, /* WAPI: Not support in this version */
+ ENCRYP_PROTOCOL_MAX
+};
+
+
+#ifndef Ndis802_11AuthModeWPA2
+#define Ndis802_11AuthModeWPA2 (Ndis802_11AuthModeWPANone + 1)
+#endif
+
+#ifndef Ndis802_11AuthModeWPA2PSK
+#define Ndis802_11AuthModeWPA2PSK (Ndis802_11AuthModeWPANone + 2)
+#endif
+
+union pn48 {
+ u64 val;
+
+#ifdef __LITTLE_ENDIAN
+ struct {
+ u8 TSC0;
+ u8 TSC1;
+ u8 TSC2;
+ u8 TSC3;
+ u8 TSC4;
+ u8 TSC5;
+ u8 TSC6;
+ u8 TSC7;
+ } _byte_;
+
+#elif defined(__BIG_ENDIAN)
+
+ struct {
+ u8 TSC7;
+ u8 TSC6;
+ u8 TSC5;
+ u8 TSC4;
+ u8 TSC3;
+ u8 TSC2;
+ u8 TSC1;
+ u8 TSC0;
+ } _byte_;
+#endif
+};
+
+union Keytype {
+ u8 skey[16];
+ u32 lkey[4];
+};
+
+struct rt_pmkid_list {
+ u8 bUsed;
+ u8 Bssid[6];
+ u8 PMKID[16];
+ u8 SsidBuf[33];
+ u8 *ssid_octet;
+ u16 ssid_length;
+};
+
+struct security_priv {
+ u32 dot11AuthAlgrthm; /* 802.11 auth, could be open,
+ * shared, 8021x and authswitch
+ */
+ u32 dot11PrivacyAlgrthm; /* This specify the privacy for
+ * shared auth. algorithm.
+ */
+ /* WEP */
+ u32 dot11PrivacyKeyIndex; /* this is only valid for legendary
+ * wep, 0~3 for key id.(tx key index)
+ */
+ union Keytype dot11DefKey[4]; /* this is only valid for def. key */
+ u32 dot11DefKeylen[4];
+ u32 dot118021XGrpPrivacy; /* This specify the privacy algthm.
+ * used for Grp key
+ */
+ u32 dot118021XGrpKeyid; /* key id used for Grp Key
+ * ( tx key index)
+ */
+ union Keytype dot118021XGrpKey[4]; /* 802.1x Group Key,
+ * for inx0 and inx1
+ */
+ union Keytype dot118021XGrptxmickey[4];
+ union Keytype dot118021XGrprxmickey[4];
+ union pn48 dot11Grptxpn; /* PN48 used for Grp Key xmit.*/
+ union pn48 dot11Grprxpn; /* PN48 used for Grp Key recv.*/
+#ifdef CPTCFG_88EU_AP_MODE
+ /* extend security capabilities for AP_MODE */
+ unsigned int dot8021xalg;/* 0:disable, 1:psk, 2:802.1x */
+ unsigned int wpa_psk;/* 0:disable, bit(0): WPA, bit(1):WPA2 */
+ unsigned int wpa_group_cipher;
+ unsigned int wpa2_group_cipher;
+ unsigned int wpa_pairwise_cipher;
+ unsigned int wpa2_pairwise_cipher;
+#endif
+ u8 wps_ie[MAX_WPS_IE_LEN];/* added in assoc req */
+ int wps_ie_len;
+ u8 binstallGrpkey;
+ u8 busetkipkey;
+ u8 bcheck_grpkey;
+ u8 bgrpkey_handshake;
+ s32 hw_decrypted;/* if the rx packets is hw_decrypted==false,i
+ * it means the hw has not been ready.
+ */
+
+ /* keeps the auth_type & enc_status from upper layer
+ * ioctl(wpa_supplicant or wzc)
+ */
+ u32 ndisauthtype; /* NDIS_802_11_AUTHENTICATION_MODE */
+ u32 ndisencryptstatus; /* NDIS_802_11_ENCRYPTION_STATUS */
+ struct wlan_bssid_ex sec_bss; /* for joinbss (h2c buffer) usage */
+ struct ndis_802_11_wep ndiswep;
+ u8 assoc_info[600];
+ u8 szofcapability[256]; /* for wpa2 usage */
+ u8 oidassociation[512]; /* for wpa/wpa2 usage */
+ u8 authenticator_ie[256]; /* store ap security information element */
+ u8 supplicant_ie[256]; /* store sta security information element */
+
+ /* for tkip countermeasure */
+ u32 last_mic_err_time;
+ u8 btkip_countermeasure;
+ u8 btkip_wait_report;
+ u32 btkip_countermeasure_time;
+
+ /* */
+ /* For WPA2 Pre-Authentication. */
+ /* */
+ struct rt_pmkid_list PMKIDList[NUM_PMKID_CACHE];
+ u8 PMKIDIndex;
+ u8 bWepDefaultKeyIdxSet;
+};
+
+#define GET_ENCRY_ALGO(psecuritypriv, psta, encry_algo, bmcst) \
+do { \
+ switch (psecuritypriv->dot11AuthAlgrthm) { \
+ case dot11AuthAlgrthm_Open: \
+ case dot11AuthAlgrthm_Shared: \
+ case dot11AuthAlgrthm_Auto: \
+ encry_algo = (u8)psecuritypriv->dot11PrivacyAlgrthm; \
+ break; \
+ case dot11AuthAlgrthm_8021X: \
+ if (bmcst) \
+ encry_algo = (u8)psecuritypriv->dot118021XGrpPrivacy;\
+ else \
+ encry_algo = (u8)psta->dot118021XPrivacy; \
+ break; \
+ case dot11AuthAlgrthm_WAPI: \
+ encry_algo = (u8)psecuritypriv->dot11PrivacyAlgrthm; \
+ break; \
+ } \
+} while (0)
+
+#define SET_ICE_IV_LEN(iv_len, icv_len, encrypt) \
+do { \
+ switch (encrypt) { \
+ case _WEP40_: \
+ case _WEP104_: \
+ iv_len = 4; \
+ icv_len = 4; \
+ break; \
+ case _TKIP_: \
+ iv_len = 8; \
+ icv_len = 4; \
+ break; \
+ case _AES_: \
+ iv_len = 8; \
+ icv_len = 8; \
+ break; \
+ case _SMS4_: \
+ iv_len = 18; \
+ icv_len = 16; \
+ break; \
+ default: \
+ iv_len = 0; \
+ icv_len = 0; \
+ break; \
+ } \
+} while (0)
+
+
+#define GET_TKIP_PN(iv, dot11txpn) \
+do { \
+ dot11txpn._byte_.TSC0 = iv[2]; \
+ dot11txpn._byte_.TSC1 = iv[0]; \
+ dot11txpn._byte_.TSC2 = iv[4]; \
+ dot11txpn._byte_.TSC3 = iv[5]; \
+ dot11txpn._byte_.TSC4 = iv[6]; \
+ dot11txpn._byte_.TSC5 = iv[7]; \
+} while (0)
+
+
+#define ROL32(A, n) (((A) << (n)) | (((A)>>(32-(n))) & ((1UL << (n)) - 1)))
+#define ROR32(A, n) ROL32((A), 32-(n))
+
+struct mic_data {
+ u32 K0, K1; /* Key */
+ u32 L, R; /* Current state */
+ u32 M; /* Message accumulator (single word) */
+ u32 nBytesInM; /* # bytes in M */
+};
+
+extern const u32 Te0[256];
+extern const u32 Td0[256];
+extern const u32 Td1[256];
+extern const u32 Td2[256];
+extern const u32 Td3[256];
+extern const u32 Td4[256];
+extern const u32 rcon[10];
+extern const u8 Td4s[256];
+extern const u8 rcons[10];
+
+#define RCON(i) (rcons[(i)] << 24)
+
+static inline u32 rotr(u32 val, int bits)
+{
+ return (val >> bits) | (val << (32 - bits));
+}
+
+#define TE0(i) Te0[((i) >> 24) & 0xff]
+#define TE1(i) rotr(Te0[((i) >> 16) & 0xff], 8)
+#define TE2(i) rotr(Te0[((i) >> 8) & 0xff], 16)
+#define TE3(i) rotr(Te0[(i) & 0xff], 24)
+
+/* ===== start - public domain SHA256 implementation ===== */
+
+/* This is based on SHA256 implementation in LibTomCrypt that was released into
+ * public domain by Tom St Denis.
+ */
+
+/* the K array */
+static const unsigned long K[64] = {
+ 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
+ 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
+ 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
+ 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+ 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
+ 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
+ 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
+ 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+ 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
+ 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
+ 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
+ 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+ 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+
+/* Various logical functions */
+#define RORc(x, y) \
+ (((((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long)((y)&31)) | \
+ ((unsigned long)(x) << (unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
+#define Ch(x, y, z) (z ^ (x & (y ^ z)))
+#define Maj(x, y, z) (((x | y) & z) | (x & y))
+#define S(x, n) RORc((x), (n))
+#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n))
+#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
+#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
+#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
+#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
+
+void rtw_secmicsetkey(struct mic_data *pmicdata, u8 *key);
+void rtw_secmicappendbyte(struct mic_data *pmicdata, u8 b);
+void rtw_secmicappend(struct mic_data *pmicdata, u8 *src, u32 nBytes);
+void rtw_secgetmic(struct mic_data *pmicdata, u8 *dst);
+void rtw_seccalctkipmic(u8 *key, u8 *header, u8 *data, u32 data_len,
+ u8 *Miccode, u8 priority);
+u32 rtw_aes_encrypt(struct adapter *padapter, u8 *pxmitframe);
+u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe);
+void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe);
+u32 rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe);
+u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe);
+int rtw_wep_decrypt(struct adapter *padapter, u8 *precvframe);
+
+#endif /* __RTL871X_SECURITY_H_ */
diff --git a/drivers/staging/rtl8188eu/include/rtw_sreset.h b/drivers/staging/rtl8188eu/include/rtw_sreset.h
new file mode 100644
index 0000000..ea3c0d9
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtw_sreset.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef _RTW_SRESET_C_
+#define _RTW_SRESET_C_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+
+struct sreset_priv {
+ u8 wifi_error_status;
+};
+
+#include <rtl8188e_hal.h>
+
+#define WIFI_STATUS_SUCCESS 0
+#define USB_VEN_REQ_CMD_FAIL BIT(0)
+#define USB_READ_PORT_FAIL BIT(1)
+#define USB_WRITE_PORT_FAIL BIT(2)
+#define WIFI_MAC_TXDMA_ERROR BIT(3)
+#define WIFI_TX_HANG BIT(4)
+#define WIFI_RX_HANG BIT(5)
+#define WIFI_IF_NOT_EXIST BIT(6)
+
+void sreset_set_wifi_error_status(struct adapter *padapter, u32 status);
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/rtw_xmit.h b/drivers/staging/rtl8188eu/include/rtw_xmit.h
new file mode 100644
index 0000000..cd6f4b2
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/rtw_xmit.h
@@ -0,0 +1,358 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef _RTW_XMIT_H_
+#define _RTW_XMIT_H_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+
+#define MAX_XMITBUF_SZ (20480) /* 20k */
+#define NR_XMITBUFF (4)
+
+#define XMITBUF_ALIGN_SZ 4
+
+/* xmit extension buff defination */
+#define MAX_XMIT_EXTBUF_SZ (1536)
+#define NR_XMIT_EXTBUFF (32)
+
+#define MAX_NUMBLKS (1)
+
+#define XMIT_VO_QUEUE (0)
+#define XMIT_VI_QUEUE (1)
+#define XMIT_BE_QUEUE (2)
+#define XMIT_BK_QUEUE (3)
+
+#define VO_QUEUE_INX 0
+#define VI_QUEUE_INX 1
+#define BE_QUEUE_INX 2
+#define BK_QUEUE_INX 3
+#define BCN_QUEUE_INX 4
+#define MGT_QUEUE_INX 5
+#define HIGH_QUEUE_INX 6
+#define TXCMD_QUEUE_INX 7
+
+#define HW_QUEUE_ENTRY 8
+
+#define WEP_IV(pattrib_iv, dot11txpn, keyidx)\
+do {\
+ pattrib_iv[0] = dot11txpn._byte_.TSC0;\
+ pattrib_iv[1] = dot11txpn._byte_.TSC1;\
+ pattrib_iv[2] = dot11txpn._byte_.TSC2;\
+ pattrib_iv[3] = ((keyidx & 0x3)<<6);\
+ dot11txpn.val = (dot11txpn.val == 0xffffff) ? 0 : (dot11txpn.val+1);\
+} while (0)
+
+
+#define TKIP_IV(pattrib_iv, dot11txpn, keyidx)\
+do {\
+ pattrib_iv[0] = dot11txpn._byte_.TSC1;\
+ pattrib_iv[1] = (dot11txpn._byte_.TSC1 | 0x20) & 0x7f;\
+ pattrib_iv[2] = dot11txpn._byte_.TSC0;\
+ pattrib_iv[3] = BIT(5) | ((keyidx & 0x3)<<6);\
+ pattrib_iv[4] = dot11txpn._byte_.TSC2;\
+ pattrib_iv[5] = dot11txpn._byte_.TSC3;\
+ pattrib_iv[6] = dot11txpn._byte_.TSC4;\
+ pattrib_iv[7] = dot11txpn._byte_.TSC5;\
+ dot11txpn.val = dot11txpn.val == 0xffffffffffffULL ? 0 : (dot11txpn.val+1);\
+} while (0)
+
+#define AES_IV(pattrib_iv, dot11txpn, keyidx)\
+do { \
+ pattrib_iv[0] = dot11txpn._byte_.TSC0; \
+ pattrib_iv[1] = dot11txpn._byte_.TSC1; \
+ pattrib_iv[2] = 0; \
+ pattrib_iv[3] = BIT(5) | ((keyidx & 0x3)<<6); \
+ pattrib_iv[4] = dot11txpn._byte_.TSC2; \
+ pattrib_iv[5] = dot11txpn._byte_.TSC3; \
+ pattrib_iv[6] = dot11txpn._byte_.TSC4; \
+ pattrib_iv[7] = dot11txpn._byte_.TSC5; \
+ dot11txpn.val = dot11txpn.val == 0xffffffffffffULL ? 0 : (dot11txpn.val+1);\
+} while (0)
+
+#define HWXMIT_ENTRY 4
+
+#define TXDESC_SIZE 32
+
+#define PACKET_OFFSET_SZ (8)
+#define TXDESC_OFFSET (TXDESC_SIZE + PACKET_OFFSET_SZ)
+
+struct tx_desc {
+ /* DWORD 0 */
+ __le32 txdw0;
+ __le32 txdw1;
+ __le32 txdw2;
+ __le32 txdw3;
+ __le32 txdw4;
+ __le32 txdw5;
+ __le32 txdw6;
+ __le32 txdw7;
+};
+
+struct hw_xmit {
+ struct __queue *sta_queue;
+ int accnt;
+};
+
+/* reduce size */
+struct pkt_attrib {
+ u8 type;
+ u8 subtype;
+ u8 bswenc;
+ u8 dhcp_pkt;
+ u16 ether_type;
+ u16 seqnum;
+ u16 hdrlen; /* the WLAN Header Len */
+ u32 pktlen; /* the original 802.3 pkt raw_data len (not include
+ * ether_hdr data)
+ */
+ u32 last_txcmdsz;
+ u8 nr_frags;
+ u8 encrypt; /* when 0 indicate no encrypt. when non-zero,
+ * indicate the encrypt algorith
+ */
+ u8 iv_len;
+ u8 icv_len;
+ u8 iv[18];
+ u8 icv[16];
+ u8 priority;
+ u8 ack_policy;
+ u8 mac_id;
+ u8 vcs_mode; /* virtual carrier sense method */
+ u8 dst[ETH_ALEN];
+ u8 src[ETH_ALEN];
+ u8 ta[ETH_ALEN];
+ u8 ra[ETH_ALEN];
+ u8 key_idx;
+ u8 qos_en;
+ u8 ht_en;
+ u8 raid;/* rate adpative id */
+ u8 bwmode;
+ u8 ch_offset;/* PRIME_CHNL_OFFSET */
+ u8 sgi;/* short GI */
+ u8 ampdu_en;/* tx ampdu enable */
+ u8 mdata;/* more data bit */
+ u8 pctrl;/* per packet txdesc control enable */
+ u8 triggered;/* for ap mode handling Power Saving sta */
+ u8 qsel;
+ u8 eosp;
+ u8 rate;
+ u8 intel_proxim;
+ u8 retry_ctrl;
+ struct sta_info *psta;
+};
+
+#define WLANHDR_OFFSET 64
+
+#define NULL_FRAMETAG (0x0)
+#define DATA_FRAMETAG 0x01
+#define L2_FRAMETAG 0x02
+#define MGNT_FRAMETAG 0x03
+#define AMSDU_FRAMETAG 0x04
+
+#define EII_FRAMETAG 0x05
+#define IEEE8023_FRAMETAG 0x06
+
+#define MP_FRAMETAG 0x07
+
+#define TXAGG_FRAMETAG 0x08
+
+struct submit_ctx {
+ u32 submit_time; /* */
+ u32 timeout_ms; /* <0: not synchronous, 0: wait forever, >0: up to ms waiting */
+ int status; /* status for operation */
+ struct completion done;
+};
+
+enum {
+ RTW_SCTX_SUBMITTED = -1,
+ RTW_SCTX_DONE_SUCCESS = 0,
+ RTW_SCTX_DONE_UNKNOWN,
+ RTW_SCTX_DONE_TIMEOUT,
+ RTW_SCTX_DONE_BUF_ALLOC,
+ RTW_SCTX_DONE_BUF_FREE,
+ RTW_SCTX_DONE_WRITE_PORT_ERR,
+ RTW_SCTX_DONE_TX_DESC_NA,
+ RTW_SCTX_DONE_TX_DENY,
+ RTW_SCTX_DONE_CCX_PKT_FAIL,
+ RTW_SCTX_DONE_DRV_STOP,
+ RTW_SCTX_DONE_DEV_REMOVE,
+};
+
+void rtw_sctx_init(struct submit_ctx *sctx, int timeout_ms);
+int rtw_sctx_wait(struct submit_ctx *sctx);
+void rtw_sctx_done_err(struct submit_ctx **sctx, int status);
+
+struct xmit_buf {
+ struct list_head list;
+ struct adapter *padapter;
+ u8 *pallocated_buf;
+ u8 *pbuf;
+ void *priv_data;
+ u16 ext_tag; /* 0: Normal xmitbuf, 1: extension xmitbuf. */
+ u16 flags;
+ u32 alloc_sz;
+ u32 len;
+ struct submit_ctx *sctx;
+ u32 ff_hwaddr;
+ struct urb *pxmit_urb[8];
+ dma_addr_t dma_transfer_addr; /* (in) dma addr for transfer_buffer */
+ u8 bpending[8];
+ int last[8];
+};
+
+struct xmit_frame {
+ struct list_head list;
+ struct pkt_attrib attrib;
+ struct sk_buff *pkt;
+ int frame_tag;
+ struct adapter *padapter;
+ u8 *buf_addr;
+ struct xmit_buf *pxmitbuf;
+
+ u8 agg_num;
+ s8 pkt_offset;
+ u8 ack_report;
+};
+
+struct tx_servq {
+ struct list_head tx_pending;
+ struct __queue sta_pending;
+ int qcnt;
+};
+
+struct sta_xmit_priv {
+ spinlock_t lock;
+ int option;
+ int apsd_setting; /* When bit mask is on, the associated edca
+ * queue supports APSD.
+ */
+ struct tx_servq be_q; /* priority == 0,3 */
+ struct tx_servq bk_q; /* priority == 1,2 */
+ struct tx_servq vi_q; /* priority == 4,5 */
+ struct tx_servq vo_q; /* priority == 6,7 */
+ struct list_head legacy_dz;
+ struct list_head apsd;
+ u16 txseq_tid[16];
+};
+
+struct hw_txqueue {
+ volatile int head;
+ volatile int tail;
+ volatile int free_sz; /* in units of 64 bytes */
+ volatile int free_cmdsz;
+ volatile int txsz[8];
+ uint ff_hwaddr;
+ uint cmd_hwaddr;
+ int ac_tag;
+};
+
+struct xmit_priv {
+ spinlock_t lock;
+ struct __queue be_pending;
+ struct __queue bk_pending;
+ struct __queue vi_pending;
+ struct __queue vo_pending;
+ struct __queue bm_pending;
+ u8 *pallocated_frame_buf;
+ u8 *pxmit_frame_buf;
+ uint free_xmitframe_cnt;
+ struct __queue free_xmit_queue;
+ uint frag_len;
+ struct adapter *adapter;
+ u8 vcs_setting;
+ u8 vcs;
+ u8 vcs_type;
+ u64 tx_bytes;
+ u64 tx_pkts;
+ u64 tx_drop;
+ u64 last_tx_bytes;
+ u64 last_tx_pkts;
+ struct hw_xmit *hwxmits;
+ u8 hwxmit_entry;
+ u8 wmm_para_seq[4];/* sequence for wmm ac parameter strength
+ * from large to small. it's value is 0->vo,
+ * 1->vi, 2->be, 3->bk.
+ */
+ u8 txirp_cnt;/* */
+ struct tasklet_struct xmit_tasklet;
+ /* per AC pending irp */
+ int beq_cnt;
+ int bkq_cnt;
+ int viq_cnt;
+ int voq_cnt;
+ struct __queue free_xmitbuf_queue;
+ struct __queue pending_xmitbuf_queue;
+ u8 *pallocated_xmitbuf;
+ u8 *pxmitbuf;
+ uint free_xmitbuf_cnt;
+ struct __queue free_xmit_extbuf_queue;
+ u8 *pallocated_xmit_extbuf;
+ u8 *pxmit_extbuf;
+ uint free_xmit_extbuf_cnt;
+ u16 nqos_ssn;
+ int ack_tx;
+ struct mutex ack_tx_mutex;
+ struct submit_ctx ack_tx_ops;
+};
+
+struct xmit_buf *rtw_alloc_xmitbuf_ext(struct xmit_priv *pxmitpriv);
+s32 rtw_free_xmitbuf_ext(struct xmit_priv *pxmitpriv,
+ struct xmit_buf *pxmitbuf);
+struct xmit_buf *rtw_alloc_xmitbuf(struct xmit_priv *pxmitpriv);
+s32 rtw_free_xmitbuf(struct xmit_priv *pxmitpriv,
+ struct xmit_buf *pxmitbuf);
+void rtw_count_tx_stats(struct adapter *padapter,
+ struct xmit_frame *pxmitframe, int sz);
+void rtw_update_protection(struct adapter *padapter, u8 *ie, uint ie_len);
+s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr,
+ struct pkt_attrib *pattrib);
+s32 rtw_put_snap(u8 *data, u16 h_proto);
+
+struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv);
+s32 rtw_free_xmitframe(struct xmit_priv *pxmitpriv,
+ struct xmit_frame *pxmitframe);
+void rtw_free_xmitframe_queue(struct xmit_priv *pxmitpriv,
+ struct __queue *pframequeue);
+struct tx_servq *rtw_get_sta_pending(struct adapter *padapter,
+ struct sta_info *psta, int up, u8 *ac);
+s32 rtw_xmitframe_enqueue(struct adapter *padapter,
+ struct xmit_frame *pxmitframe);
+struct xmit_frame *rtw_dequeue_xframe(struct xmit_priv *pxmitpriv,
+ struct hw_xmit *phwxmit_i, int entry);
+
+s32 rtw_xmit_classifier(struct adapter *padapter,
+ struct xmit_frame *pxmitframe);
+s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt,
+ struct xmit_frame *pxmitframe);
+s32 _rtw_init_hw_txqueue(struct hw_txqueue *phw_txqueue, u8 ac_tag);
+void _rtw_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv);
+s32 rtw_txframes_pending(struct adapter *padapter);
+s32 rtw_txframes_sta_ac_pending(struct adapter *padapter,
+ struct pkt_attrib *pattrib);
+void rtw_init_hwxmits(struct hw_xmit *phwxmit, int entry);
+s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter);
+void _rtw_free_xmit_priv(struct xmit_priv *pxmitpriv);
+s32 rtw_alloc_hwxmits(struct adapter *padapter);
+void rtw_free_hwxmits(struct adapter *padapter);
+s32 rtw_xmit(struct adapter *padapter, struct sk_buff **pkt);
+
+#if defined(CPTCFG_88EU_AP_MODE)
+int xmitframe_enqueue_for_sleeping_sta(struct adapter *padapter, struct xmit_frame *pxmitframe);
+void stop_sta_xmit(struct adapter *padapter, struct sta_info *psta);
+void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta);
+void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *psta);
+#endif
+
+u8 qos_acm(u8 acm_mask, u8 priority);
+u32 rtw_get_ff_hwaddr(struct xmit_frame *pxmitframe);
+int rtw_ack_tx_wait(struct xmit_priv *pxmitpriv, u32 timeout_ms);
+void rtw_ack_tx_done(struct xmit_priv *pxmitpriv, int status);
+
+/* include after declaring struct xmit_buf, in order to avoid warning */
+#include <xmit_osdep.h>
+
+#endif /* _RTL871X_XMIT_H_ */
diff --git a/drivers/staging/rtl8188eu/include/sta_info.h b/drivers/staging/rtl8188eu/include/sta_info.h
new file mode 100644
index 0000000..8da0d3e
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/sta_info.h
@@ -0,0 +1,359 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __STA_INFO_H_
+#define __STA_INFO_H_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <wifi.h>
+
+#define IBSS_START_MAC_ID 2
+#define NUM_STA 32
+#define NUM_ACL 16
+
+/* if mode ==0, then the sta is allowed once the addr is hit. */
+/* if mode ==1, then the sta is rejected once the addr is non-hit. */
+struct rtw_wlan_acl_node {
+ struct list_head list;
+ u8 addr[ETH_ALEN];
+ u8 valid;
+};
+
+/* mode=0, disable */
+/* mode=1, accept unless in deny list */
+/* mode=2, deny unless in accept list */
+struct wlan_acl_pool {
+ int mode;
+ int num;
+ struct rtw_wlan_acl_node aclnode[NUM_ACL];
+ struct __queue acl_node_q;
+};
+
+struct rssi_sta {
+ s32 UndecoratedSmoothedPWDB;
+ s32 UndecoratedSmoothedCCK;
+ s32 UndecoratedSmoothedOFDM;
+ u64 PacketMap;
+ u8 ValidBit;
+};
+
+struct stainfo_stats {
+ u64 rx_mgnt_pkts;
+ u64 rx_beacon_pkts;
+ u64 rx_probereq_pkts;
+ u64 rx_probersp_pkts;
+ u64 rx_probersp_bm_pkts;
+ u64 rx_probersp_uo_pkts;
+ u64 rx_ctrl_pkts;
+ u64 rx_data_pkts;
+
+ u64 last_rx_mgnt_pkts;
+ u64 last_rx_beacon_pkts;
+ u64 last_rx_probereq_pkts;
+ u64 last_rx_probersp_pkts;
+ u64 last_rx_probersp_bm_pkts;
+ u64 last_rx_probersp_uo_pkts;
+ u64 last_rx_ctrl_pkts;
+ u64 last_rx_data_pkts;
+ u64 rx_bytes;
+ u64 rx_drops;
+ u64 tx_pkts;
+ u64 tx_bytes;
+ u64 tx_drops;
+};
+
+struct sta_info {
+ spinlock_t lock;
+ struct list_head list; /* free_sta_queue */
+ struct list_head hash_list; /* sta_hash */
+
+ struct sta_xmit_priv sta_xmitpriv;
+ struct sta_recv_priv sta_recvpriv;
+
+ struct __queue sleep_q;
+ unsigned int sleepq_len;
+
+ uint state;
+ uint aid;
+ uint mac_id;
+ uint qos_option;
+ u8 hwaddr[ETH_ALEN];
+
+ uint ieee8021x_blocked; /* 0: allowed, 1:blocked */
+ uint dot118021XPrivacy; /* aes, tkip... */
+ union Keytype dot11tkiptxmickey;
+ union Keytype dot11tkiprxmickey;
+ union Keytype dot118021x_UncstKey;
+ union pn48 dot11txpn; /* PN48 used for Unicast xmit. */
+ union pn48 dot11rxpn; /* PN48 used for Unicast recv. */
+ u8 bssrateset[16];
+ u32 bssratelen;
+ s32 rssi;
+ s32 signal_quality;
+
+ u8 cts2self;
+ u8 rtsen;
+
+ u8 raid;
+ u8 init_rate;
+ u8 wireless_mode; /* NETWORK_TYPE */
+ struct stainfo_stats sta_stats;
+
+ /* for A-MPDU TX, ADDBA timeout check */
+ struct timer_list addba_retry_timer;
+
+ /* for A-MPDU Rx reordering buffer control */
+ struct recv_reorder_ctrl recvreorder_ctrl[16];
+
+ /* for A-MPDU Tx */
+ /* unsigned char ampdu_txen_bitmap; */
+ u16 BA_starting_seqctrl[16];
+
+ struct ht_priv htpriv;
+
+ /* Notes: */
+ /* STA_Mode: */
+ /* curr_network(mlme_priv/security_priv/qos/ht) +
+ * sta_info: (STA & AP) CAP/INFO
+ */
+ /* scan_q: AP CAP/INFO */
+
+ /* AP_Mode: */
+ /* curr_network(mlme_priv/security_priv/qos/ht) : AP CAP/INFO */
+ /* sta_info: (AP & STA) CAP/INFO */
+
+ struct list_head asoc_list;
+#ifdef CPTCFG_88EU_AP_MODE
+ struct list_head auth_list;
+
+ unsigned int expire_to;
+ unsigned int auth_seq;
+ unsigned int authalg;
+ unsigned char chg_txt[128];
+
+ u16 capability;
+ int flags;
+
+ int dot8021xalg;/* 0:disable, 1:psk, 2:802.1x */
+ int wpa_psk;/* 0:disable, bit(0): WPA, bit(1):WPA2 */
+ int wpa_group_cipher;
+ int wpa2_group_cipher;
+ int wpa_pairwise_cipher;
+ int wpa2_pairwise_cipher;
+
+ u8 bpairwise_key_installed;
+
+ u8 wpa_ie[32];
+
+ u8 nonerp_set;
+ u8 no_short_slot_time_set;
+ u8 no_short_preamble_set;
+ u8 no_ht_gf_set;
+ u8 no_ht_set;
+ u8 ht_20mhz_set;
+
+ unsigned int tx_ra_bitmap;
+ u8 qos_info;
+
+ u8 max_sp_len;
+ u8 uapsd_bk;/* BIT(0): Delivery enabled, BIT(1): Trigger enabled */
+ u8 uapsd_be;
+ u8 uapsd_vi;
+ u8 uapsd_vo;
+
+ u8 has_legacy_ac;
+ unsigned int sleepq_ac_len;
+#endif /* CPTCFG_88EU_AP_MODE */
+
+ u8 under_exist_checking;
+ u8 keep_alive_trycnt;
+
+ /* for DM */
+ struct rssi_sta rssi_stat;
+
+ /* ================ODM Relative Info======================= */
+ /* Please be careful, don't declare too much structure here.
+ * It will cost memory * STA support num.
+ */
+ /* 2011/10/20 MH Add for ODM STA info. */
+ /* Driver Write */
+ u8 bValid; /* record the sta status link or not? */
+ u8 IOTPeer; /* Enum value. HT_IOT_PEER_E */
+ u8 rssi_level; /* for Refresh RA mask */
+ /* ODM Write */
+ /* 1 PHY_STATUS_INFO */
+ u8 RSSI_Path[4]; /* */
+ u8 RSSI_Ave;
+ u8 RXEVM[4];
+ u8 RXSNR[4];
+
+ /* ================ODM Relative Info======================= */
+ /* */
+
+ /* To store the sequence number of received management frame */
+ u16 RxMgmtFrameSeqNum;
+};
+
+#define sta_rx_pkts(sta) \
+ (sta->sta_stats.rx_mgnt_pkts \
+ + sta->sta_stats.rx_ctrl_pkts \
+ + sta->sta_stats.rx_data_pkts)
+
+#define sta_last_rx_pkts(sta) \
+ (sta->sta_stats.last_rx_mgnt_pkts \
+ + sta->sta_stats.last_rx_ctrl_pkts \
+ + sta->sta_stats.last_rx_data_pkts)
+
+#define sta_rx_data_pkts(sta) \
+ (sta->sta_stats.rx_data_pkts)
+
+#define sta_last_rx_data_pkts(sta) \
+ (sta->sta_stats.last_rx_data_pkts)
+
+#define sta_rx_mgnt_pkts(sta) \
+ (sta->sta_stats.rx_mgnt_pkts)
+
+#define sta_last_rx_mgnt_pkts(sta) \
+ (sta->sta_stats.last_rx_mgnt_pkts)
+
+#define sta_rx_beacon_pkts(sta) \
+ (sta->sta_stats.rx_beacon_pkts)
+
+#define sta_last_rx_beacon_pkts(sta) \
+ (sta->sta_stats.last_rx_beacon_pkts)
+
+#define sta_rx_probereq_pkts(sta) \
+ (sta->sta_stats.rx_probereq_pkts)
+
+#define sta_last_rx_probereq_pkts(sta) \
+ (sta->sta_stats.last_rx_probereq_pkts)
+
+#define sta_rx_probersp_pkts(sta) \
+ (sta->sta_stats.rx_probersp_pkts)
+
+#define sta_last_rx_probersp_pkts(sta) \
+ (sta->sta_stats.last_rx_probersp_pkts)
+
+#define sta_rx_probersp_bm_pkts(sta) \
+ (sta->sta_stats.rx_probersp_bm_pkts)
+
+#define sta_last_rx_probersp_bm_pkts(sta) \
+ (sta->sta_stats.last_rx_probersp_bm_pkts)
+
+#define sta_rx_probersp_uo_pkts(sta) \
+ (sta->sta_stats.rx_probersp_uo_pkts)
+
+#define sta_last_rx_probersp_uo_pkts(sta) \
+ (sta->sta_stats.last_rx_probersp_uo_pkts)
+
+#define sta_update_last_rx_pkts(sta) \
+do { \
+ sta->sta_stats.last_rx_mgnt_pkts = sta->sta_stats.rx_mgnt_pkts; \
+ sta->sta_stats.last_rx_beacon_pkts = sta->sta_stats.rx_beacon_pkts; \
+ sta->sta_stats.last_rx_probereq_pkts = sta->sta_stats.rx_probereq_pkts; \
+ sta->sta_stats.last_rx_probersp_pkts = sta->sta_stats.rx_probersp_pkts; \
+ sta->sta_stats.last_rx_probersp_bm_pkts = sta->sta_stats.rx_probersp_bm_pkts; \
+ sta->sta_stats.last_rx_probersp_uo_pkts = sta->sta_stats.rx_probersp_uo_pkts; \
+ sta->sta_stats.last_rx_ctrl_pkts = sta->sta_stats.rx_ctrl_pkts; \
+ sta->sta_stats.last_rx_data_pkts = sta->sta_stats.rx_data_pkts; \
+} while (0)
+
+#define STA_RX_PKTS_ARG(sta) \
+ sta->sta_stats.rx_mgnt_pkts \
+ , sta->sta_stats.rx_ctrl_pkts \
+ , sta->sta_stats.rx_data_pkts
+
+#define STA_LAST_RX_PKTS_ARG(sta) \
+ sta->sta_stats.last_rx_mgnt_pkts \
+ , sta->sta_stats.last_rx_ctrl_pkts \
+ , sta->sta_stats.last_rx_data_pkts
+
+#define STA_RX_PKTS_DIFF_ARG(sta) \
+ sta->sta_stats.rx_mgnt_pkts - sta->sta_stats.last_rx_mgnt_pkts \
+ , sta->sta_stats.rx_ctrl_pkts - sta->sta_stats.last_rx_ctrl_pkts \
+ , sta->sta_stats.rx_data_pkts - sta->sta_stats.last_rx_data_pkts
+
+#define STA_PKTS_FMT "(m:%llu, c:%llu, d:%llu)"
+
+struct sta_priv {
+ u8 *pallocated_stainfo_buf;
+ u8 *pstainfo_buf;
+ struct __queue free_sta_queue;
+
+ spinlock_t sta_hash_lock;
+ struct list_head sta_hash[NUM_STA];
+ int asoc_sta_count;
+ struct __queue sleep_q;
+ struct __queue wakeup_q;
+
+ struct adapter *padapter;
+
+ spinlock_t asoc_list_lock;
+ struct list_head asoc_list;
+
+#ifdef CPTCFG_88EU_AP_MODE
+ struct list_head auth_list;
+ spinlock_t auth_list_lock;
+ u8 asoc_list_cnt;
+ u8 auth_list_cnt;
+
+ unsigned int auth_to; /* sec, time to expire in authenticating. */
+ unsigned int assoc_to; /* sec, time to expire before associating. */
+ unsigned int expire_to; /* sec , time to expire after associated. */
+
+ /* pointers to STA info; based on allocated AID or NULL if AID free
+ * AID is in the range 1-2007, so sta_aid[0] corresponders to AID 1
+ * and so on
+ */
+ struct sta_info *sta_aid[NUM_STA];
+
+ u16 sta_dz_bitmap;/* only support 15 stations, station aid bitmap
+ * for sleeping sta.
+ */
+ u16 tim_bitmap; /* only support 15 stations, aid=0~15 mapping
+ * bit0~bit15
+ */
+
+ u16 max_num_sta;
+
+ struct wlan_acl_pool acl_list;
+#endif
+
+};
+
+static inline u32 wifi_mac_hash(u8 *mac)
+{
+ u32 x;
+
+ x = mac[0];
+ x = (x << 2) ^ mac[1];
+ x = (x << 2) ^ mac[2];
+ x = (x << 2) ^ mac[3];
+ x = (x << 2) ^ mac[4];
+ x = (x << 2) ^ mac[5];
+
+ x ^= x >> 8;
+ x = x & (NUM_STA - 1);
+ return x;
+}
+
+u32 _rtw_init_sta_priv(struct sta_priv *pstapriv);
+u32 _rtw_free_sta_priv(struct sta_priv *pstapriv);
+
+#define stainfo_offset_valid(offset) (offset < NUM_STA && offset >= 0)
+int rtw_stainfo_offset(struct sta_priv *stapriv, struct sta_info *sta);
+struct sta_info *rtw_get_stainfo_by_offset(struct sta_priv *stapriv, int off);
+
+struct sta_info *rtw_alloc_stainfo(struct sta_priv *stapriv, u8 *hwaddr);
+u32 rtw_free_stainfo(struct adapter *adapt, struct sta_info *psta);
+void rtw_free_all_stainfo(struct adapter *adapt);
+struct sta_info *rtw_get_stainfo(struct sta_priv *stapriv, u8 *hwaddr);
+u32 rtw_init_bcmc_stainfo(struct adapter *adapt);
+struct sta_info *rtw_get_bcmc_stainfo(struct adapter *padapter);
+u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr);
+
+#endif /* _STA_INFO_H_ */
diff --git a/drivers/staging/rtl8188eu/include/usb_ops_linux.h b/drivers/staging/rtl8188eu/include/usb_ops_linux.h
new file mode 100644
index 0000000..70d7297
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/usb_ops_linux.h
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __USB_OPS_LINUX_H__
+#define __USB_OPS_LINUX_H__
+
+#define VENDOR_CMD_MAX_DATA_LEN 254
+
+#define RTW_USB_CONTROL_MSG_TIMEOUT_TEST 10/* ms */
+#define RTW_USB_CONTROL_MSG_TIMEOUT 500/* ms */
+
+#define MAX_USBCTRL_VENDORREQ_TIMES 10
+
+#define RTW_USB_BULKOUT_TIME 5000/* ms */
+
+#define REALTEK_USB_VENQT_READ 0xC0
+#define REALTEK_USB_VENQT_WRITE 0x40
+
+#define ALIGNMENT_UNIT 16
+#define MAX_VENDOR_REQ_CMD_SIZE 254 /* 8188cu SIE Support */
+#define MAX_USB_IO_CTL_SIZE (MAX_VENDOR_REQ_CMD_SIZE + ALIGNMENT_UNIT)
+
+#define USB_HIGH_SPEED_BULK_SIZE 512
+#define USB_FULL_SPEED_BULK_SIZE 64
+
+#define _usbctrl_vendorreq_async_callback(urb, regs) \
+ _usbctrl_vendorreq_async_callback(urb)
+#define usb_bulkout_zero_complete(purb, regs) \
+ usb_bulkout_zero_complete(purb)
+#define usb_write_mem_complete(purb, regs) \
+ usb_write_mem_complete(purb)
+#define usb_write_port_complete(purb, regs) \
+ usb_write_port_complete(purb)
+#define usb_read_port_complete(purb, regs) \
+ usb_read_port_complete(purb)
+#define usb_read_interrupt_complete(purb, regs) \
+ usb_read_interrupt_complete(purb)
+
+unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr);
+
+u8 usb_read8(struct adapter *adapter, u32 addr);
+u16 usb_read16(struct adapter *adapter, u32 addr);
+u32 usb_read32(struct adapter *adapter, u32 addr);
+
+u32 usb_read_port(struct adapter *adapter, u32 addr, struct recv_buf *precvbuf);
+void usb_read_port_cancel(struct adapter *adapter);
+
+int usb_write8(struct adapter *adapter, u32 addr, u8 val);
+int usb_write16(struct adapter *adapter, u32 addr, u16 val);
+int usb_write32(struct adapter *adapter, u32 addr, u32 val);
+
+u32 usb_write_port(struct adapter *adapter, u32 addr, u32 cnt, struct xmit_buf *pmem);
+void usb_write_port_cancel(struct adapter *adapter);
+
+#endif
diff --git a/drivers/staging/rtl8188eu/include/wifi.h b/drivers/staging/rtl8188eu/include/wifi.h
new file mode 100644
index 0000000..d059240
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/wifi.h
@@ -0,0 +1,689 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef _WIFI_H_
+#define _WIFI_H_
+
+#define WLAN_IEEE_OUI_LEN 3
+#define WLAN_CRC_LEN 4
+#define WLAN_BSSID_LEN 6
+#define WLAN_BSS_TS_LEN 8
+#define WLAN_HDR_A3_LEN 24
+#define WLAN_HDR_A4_LEN 30
+#define WLAN_HDR_A3_QOS_LEN 26
+#define WLAN_HDR_A4_QOS_LEN 32
+#define WLAN_DATA_MAXLEN 2312
+
+#define WLAN_A3_PN_OFFSET 24
+#define WLAN_A4_PN_OFFSET 30
+
+#define WLAN_MIN_ETHFRM_LEN 60
+#define WLAN_MAX_ETHFRM_LEN 1514
+
+#define P80211CAPTURE_VERSION 0x80211001
+
+/* This value is tested by WiFi 11n Test Plan 5.2.3. */
+/* This test verifies the WLAN NIC can update the NAV through sending
+ * the CTS with large duration.
+ */
+#define WiFiNavUpperUs 30000 /* 30 ms */
+
+enum WIFI_FRAME_TYPE {
+ WIFI_MGT_TYPE = (0),
+ WIFI_CTRL_TYPE = (BIT(2)),
+ WIFI_DATA_TYPE = (BIT(3)),
+ WIFI_QOS_DATA_TYPE = (BIT(7)|BIT(3)), /* QoS Data */
+};
+
+enum WIFI_FRAME_SUBTYPE {
+ /* below is for mgt frame */
+ WIFI_ASSOCREQ = (0 | WIFI_MGT_TYPE),
+ WIFI_ASSOCRSP = (BIT(4) | WIFI_MGT_TYPE),
+ WIFI_REASSOCREQ = (BIT(5) | WIFI_MGT_TYPE),
+ WIFI_REASSOCRSP = (BIT(5) | BIT(4) | WIFI_MGT_TYPE),
+ WIFI_PROBEREQ = (BIT(6) | WIFI_MGT_TYPE),
+ WIFI_PROBERSP = (BIT(6) | BIT(4) | WIFI_MGT_TYPE),
+ WIFI_BEACON = (BIT(7) | WIFI_MGT_TYPE),
+ WIFI_ATIM = (BIT(7) | BIT(4) | WIFI_MGT_TYPE),
+ WIFI_DISASSOC = (BIT(7) | BIT(5) | WIFI_MGT_TYPE),
+ WIFI_AUTH = (BIT(7) | BIT(5) | BIT(4) | WIFI_MGT_TYPE),
+ WIFI_DEAUTH = (BIT(7) | BIT(6) | WIFI_MGT_TYPE),
+ WIFI_ACTION = (BIT(7) | BIT(6) | BIT(4) | WIFI_MGT_TYPE),
+
+ /* below is for control frame */
+ WIFI_PSPOLL = (BIT(7) | BIT(5) | WIFI_CTRL_TYPE),
+ WIFI_RTS = (BIT(7) | BIT(5) | BIT(4) | WIFI_CTRL_TYPE),
+ WIFI_CTS = (BIT(7) | BIT(6) | WIFI_CTRL_TYPE),
+ WIFI_ACK = (BIT(7) | BIT(6) | BIT(4) | WIFI_CTRL_TYPE),
+ WIFI_CFEND = (BIT(7) | BIT(6) | BIT(5) | WIFI_CTRL_TYPE),
+ WIFI_CFEND_CFACK = (BIT(7) | BIT(6) | BIT(5) | BIT(4) |
+ WIFI_CTRL_TYPE),
+
+ /* below is for data frame */
+ WIFI_DATA = (0 | WIFI_DATA_TYPE),
+ WIFI_DATA_CFACK = (BIT(4) | WIFI_DATA_TYPE),
+ WIFI_DATA_CFPOLL = (BIT(5) | WIFI_DATA_TYPE),
+ WIFI_DATA_CFACKPOLL = (BIT(5) | BIT(4) | WIFI_DATA_TYPE),
+ WIFI_DATA_NULL = (BIT(6) | WIFI_DATA_TYPE),
+ WIFI_CF_ACK = (BIT(6) | BIT(4) | WIFI_DATA_TYPE),
+ WIFI_CF_POLL = (BIT(6) | BIT(5) | WIFI_DATA_TYPE),
+ WIFI_CF_ACKPOLL = (BIT(6) | BIT(5) | BIT(4) | WIFI_DATA_TYPE),
+ WIFI_QOS_DATA_NULL = (BIT(6) | WIFI_QOS_DATA_TYPE),
+};
+
+enum WIFI_REASON_CODE {
+ _RSON_RESERVED_ = 0,
+ _RSON_UNSPECIFIED_ = 1,
+ _RSON_AUTH_NO_LONGER_VALID_ = 2,
+ _RSON_DEAUTH_STA_LEAVING_ = 3,
+ _RSON_INACTIVITY_ = 4,
+ _RSON_UNABLE_HANDLE_ = 5,
+ _RSON_CLS2_ = 6,
+ _RSON_CLS3_ = 7,
+ _RSON_DISAOC_STA_LEAVING_ = 8,
+ _RSON_ASOC_NOT_AUTH_ = 9,
+
+ /* WPA reason */
+ _RSON_INVALID_IE_ = 13,
+ _RSON_MIC_FAILURE_ = 14,
+ _RSON_4WAY_HNDSHK_TIMEOUT_ = 15,
+ _RSON_GROUP_KEY_UPDATE_TIMEOUT_ = 16,
+ _RSON_DIFF_IE_ = 17,
+ _RSON_MLTCST_CIPHER_NOT_VALID_ = 18,
+ _RSON_UNICST_CIPHER_NOT_VALID_ = 19,
+ _RSON_AKMP_NOT_VALID_ = 20,
+ _RSON_UNSUPPORT_RSNE_VER_ = 21,
+ _RSON_INVALID_RSNE_CAP_ = 22,
+ _RSON_IEEE_802DOT1X_AUTH_FAIL_ = 23,
+
+ /* belowing are Realtek definition */
+ _RSON_PMK_NOT_AVAILABLE_ = 24,
+ _RSON_TDLS_TEAR_TOOFAR_ = 25,
+ _RSON_TDLS_TEAR_UN_RSN_ = 26,
+};
+
+enum WIFI_STATUS_CODE {
+ _STATS_SUCCESSFUL_ = 0,
+ _STATS_FAILURE_ = 1,
+ _STATS_CAP_FAIL_ = 10,
+ _STATS_NO_ASOC_ = 11,
+ _STATS_OTHER_ = 12,
+ _STATS_NO_SUPP_ALG_ = 13,
+ _STATS_OUT_OF_AUTH_SEQ_ = 14,
+ _STATS_CHALLENGE_FAIL_ = 15,
+ _STATS_AUTH_TIMEOUT_ = 16,
+ _STATS_UNABLE_HANDLE_STA_ = 17,
+ _STATS_RATE_FAIL_ = 18,
+};
+
+enum WIFI_REG_DOMAIN {
+ DOMAIN_FCC = 1,
+ DOMAIN_IC = 2,
+ DOMAIN_ETSI = 3,
+ DOMAIN_SPA = 4,
+ DOMAIN_FRANCE = 5,
+ DOMAIN_MKK = 6,
+ DOMAIN_ISRAEL = 7,
+ DOMAIN_MKK1 = 8,
+ DOMAIN_MKK2 = 9,
+ DOMAIN_MKK3 = 10,
+ DOMAIN_MAX
+};
+
+#define _TO_DS_ BIT(8)
+#define _FROM_DS_ BIT(9)
+#define _MORE_FRAG_ BIT(10)
+#define _RETRY_ BIT(11)
+#define _PWRMGT_ BIT(12)
+#define _MORE_DATA_ BIT(13)
+#define _PRIVACY_ BIT(14)
+#define _ORDER_ BIT(15)
+
+#define SetToDs(pbuf) \
+ *(__le16 *)(pbuf) |= cpu_to_le16(_TO_DS_)
+
+#define GetToDs(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_TO_DS_)) != 0)
+
+#define ClearToDs(pbuf) \
+ *(__le16 *)(pbuf) &= (~cpu_to_le16(_TO_DS_))
+
+#define SetFrDs(pbuf) \
+ *(__le16 *)(pbuf) |= cpu_to_le16(_FROM_DS_)
+
+#define GetFrDs(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_FROM_DS_)) != 0)
+
+#define ClearFrDs(pbuf) \
+ *(__le16 *)(pbuf) &= (~cpu_to_le16(_FROM_DS_))
+
+#define get_tofr_ds(pframe) ((GetToDs(pframe) << 1) | GetFrDs(pframe))
+
+
+#define SetMFrag(pbuf) \
+ *(__le16 *)(pbuf) |= cpu_to_le16(_MORE_FRAG_)
+
+#define GetMFrag(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_MORE_FRAG_)) != 0)
+
+#define ClearMFrag(pbuf) \
+ *(__le16 *)(pbuf) &= (~cpu_to_le16(_MORE_FRAG_))
+
+#define SetRetry(pbuf) \
+ *(__le16 *)(pbuf) |= cpu_to_le16(_RETRY_)
+
+#define GetRetry(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_RETRY_)) != 0)
+
+#define ClearRetry(pbuf) \
+ *(__le16 *)(pbuf) &= (~cpu_to_le16(_RETRY_))
+
+#define SetPwrMgt(pbuf) \
+ *(__le16 *)(pbuf) |= cpu_to_le16(_PWRMGT_)
+
+#define GetPwrMgt(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_PWRMGT_)) != 0)
+
+#define ClearPwrMgt(pbuf) \
+ *(__le16 *)(pbuf) &= (~cpu_to_le16(_PWRMGT_))
+
+#define SetMData(pbuf) \
+ *(__le16 *)(pbuf) |= cpu_to_le16(_MORE_DATA_)
+
+#define GetMData(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_MORE_DATA_)) != 0)
+
+#define ClearMData(pbuf) \
+ *(__le16 *)(pbuf) &= (~cpu_to_le16(_MORE_DATA_))
+
+#define SetPrivacy(pbuf) \
+ *(__le16 *)(pbuf) |= cpu_to_le16(_PRIVACY_)
+
+#define GetPrivacy(pbuf) \
+ (((*(__le16 *)(pbuf)) & cpu_to_le16(_PRIVACY_)) != 0)
+
+#define GetOrder(pbuf) \
+ (((*(__le16 *)(pbuf)) & cpu_to_le16(_ORDER_)) != 0)
+
+#define GetFrameType(pbuf) \
+ (le16_to_cpu(*(__le16 *)(pbuf)) & (BIT(3) | BIT(2)))
+
+#define GetFrameSubType(pbuf) (le16_to_cpu(*(__le16 *)(pbuf)) & (BIT(7) |\
+ BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2)))
+
+#define SetFrameSubType(pbuf, type) \
+ do { \
+ *(__le16 *)(pbuf) &= cpu_to_le16(~(BIT(7) | BIT(6) | \
+ BIT(5) | BIT(4) | BIT(3) | BIT(2))); \
+ *(__le16 *)(pbuf) |= cpu_to_le16(type); \
+ } while (0)
+
+#define GetSequence(pbuf) \
+ (le16_to_cpu(*(__le16 *)((size_t)(pbuf) + 22)) >> 4)
+
+#define GetFragNum(pbuf) \
+ (le16_to_cpu(*(__le16 *)((size_t)(pbuf) + 22)) & 0x0f)
+
+#define SetSeqNum(pbuf, num) \
+ do { \
+ *(__le16 *)((size_t)(pbuf) + 22) = \
+ ((*(__le16 *)((size_t)(pbuf) + 22)) & cpu_to_le16((unsigned short)0x000f)) | \
+ cpu_to_le16((unsigned short)(0xfff0 & (num << 4))); \
+ } while (0)
+
+#define SetDuration(pbuf, dur) \
+ *(__le16 *)((size_t)(pbuf) + 2) = cpu_to_le16(0xffff & (dur))
+
+
+#define SetPriority(pbuf, tid) \
+ *(__le16 *)(pbuf) |= cpu_to_le16(tid & 0xf)
+
+#define GetPriority(pbuf) ((le16_to_cpu(*(__le16 *)(pbuf))) & 0xf)
+
+#define SetEOSP(pbuf, eosp) \
+ *(__le16 *)(pbuf) |= cpu_to_le16((eosp & 1) << 4)
+
+#define SetAckpolicy(pbuf, ack) \
+ *(__le16 *)(pbuf) |= cpu_to_le16((ack & 3) << 5)
+
+#define GetAckpolicy(pbuf) (((le16_to_cpu(*(__le16 *)pbuf)) >> 5) & 0x3)
+
+#define GetAMsdu(pbuf) (((le16_to_cpu(*(__le16 *)pbuf)) >> 7) & 0x1)
+
+#define GetAid(pbuf) (le16_to_cpu(*(__le16 *)((size_t)(pbuf) + 2)) & 0x3fff)
+
+#define GetAddr1Ptr(pbuf) ((unsigned char *)((size_t)(pbuf) + 4))
+
+#define GetAddr2Ptr(pbuf) ((unsigned char *)((size_t)(pbuf) + 10))
+
+#define GetAddr3Ptr(pbuf) ((unsigned char *)((size_t)(pbuf) + 16))
+
+#define GetAddr4Ptr(pbuf) ((unsigned char *)((size_t)(pbuf) + 24))
+
+static inline unsigned char *get_da(unsigned char *pframe)
+{
+ unsigned char *da;
+ unsigned int to_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe);
+
+ switch (to_fr_ds) {
+ case 0x00: /* ToDs=0, FromDs=0 */
+ da = GetAddr1Ptr(pframe);
+ break;
+ case 0x01: /* ToDs=0, FromDs=1 */
+ da = GetAddr1Ptr(pframe);
+ break;
+ case 0x02: /* ToDs=1, FromDs=0 */
+ da = GetAddr3Ptr(pframe);
+ break;
+ default: /* ToDs=1, FromDs=1 */
+ da = GetAddr3Ptr(pframe);
+ break;
+ }
+ return da;
+}
+
+static inline unsigned char *get_sa(unsigned char *pframe)
+{
+ unsigned char *sa;
+ unsigned int to_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe);
+
+ switch (to_fr_ds) {
+ case 0x00: /* ToDs=0, FromDs=0 */
+ sa = GetAddr2Ptr(pframe);
+ break;
+ case 0x01: /* ToDs=0, FromDs=1 */
+ sa = GetAddr3Ptr(pframe);
+ break;
+ case 0x02: /* ToDs=1, FromDs=0 */
+ sa = GetAddr2Ptr(pframe);
+ break;
+ default: /* ToDs=1, FromDs=1 */
+ sa = GetAddr4Ptr(pframe);
+ break;
+ }
+ return sa;
+}
+
+static inline unsigned char *get_hdr_bssid(unsigned char *pframe)
+{
+ unsigned char *sa;
+ unsigned int to_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe);
+
+ switch (to_fr_ds) {
+ case 0x00: /* ToDs=0, FromDs=0 */
+ sa = GetAddr3Ptr(pframe);
+ break;
+ case 0x01: /* ToDs=0, FromDs=1 */
+ sa = GetAddr2Ptr(pframe);
+ break;
+ case 0x02: /* ToDs=1, FromDs=0 */
+ sa = GetAddr1Ptr(pframe);
+ break;
+ case 0x03: /* ToDs=1, FromDs=1 */
+ sa = GetAddr1Ptr(pframe);
+ break;
+ default:
+ sa = NULL; /* */
+ break;
+ }
+ return sa;
+}
+
+static inline int IsFrameTypeCtrl(unsigned char *pframe)
+{
+ if (WIFI_CTRL_TYPE == GetFrameType(pframe))
+ return true;
+ else
+ return false;
+}
+/*-----------------------------------------------------------------------------
+ Below is for the security related definition
+------------------------------------------------------------------------------*/
+#define _RESERVED_FRAME_TYPE_ 0
+#define _SKB_FRAME_TYPE_ 2
+#define _PRE_ALLOCMEM_ 1
+#define _PRE_ALLOCHDR_ 3
+#define _PRE_ALLOCLLCHDR_ 4
+#define _PRE_ALLOCICVHDR_ 5
+#define _PRE_ALLOCMICHDR_ 6
+
+#define _SIFSTIME_ \
+ ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) ? 16 : 10)
+#define _ACKCTSLNG_ 14 /* 14 bytes long, including crclng */
+#define _CRCLNG_ 4
+
+#define _ASOCREQ_IE_OFFSET_ 4 /* excluding wlan_hdr */
+#define _ASOCRSP_IE_OFFSET_ 6
+#define _REASOCREQ_IE_OFFSET_ 10
+#define _REASOCRSP_IE_OFFSET_ 6
+#define _PROBEREQ_IE_OFFSET_ 0
+#define _PROBERSP_IE_OFFSET_ 12
+#define _AUTH_IE_OFFSET_ 6
+#define _DEAUTH_IE_OFFSET_ 0
+#define _BEACON_IE_OFFSET_ 12
+#define _PUBLIC_ACTION_IE_OFFSET_ 8
+
+#define _FIXED_IE_LENGTH_ _BEACON_IE_OFFSET_
+
+#define _SSID_IE_ 0
+#define _SUPPORTEDRATES_IE_ 1
+#define _DSSET_IE_ 3
+#define _TIM_IE_ 5
+#define _IBSS_PARA_IE_ 6
+#define _COUNTRY_IE_ 7
+#define _CHLGETXT_IE_ 16
+#define _SUPPORTED_CH_IE_ 36
+#define _CH_SWTICH_ANNOUNCE_ 37 /* Secondary Channel Offset */
+#define _RSN_IE_2_ 48
+#define _SSN_IE_1_ 221
+#define _ERPINFO_IE_ 42
+#define _EXT_SUPPORTEDRATES_IE_ 50
+
+#define _HT_CAPABILITY_IE_ 45
+#define _FTIE_ 55
+#define _TIMEOUT_ITVL_IE_ 56
+#define _SRC_IE_ 59
+#define _HT_EXTRA_INFO_IE_ 61
+#define _HT_ADD_INFO_IE_ 61 /* _HT_EXTRA_INFO_IE_ */
+#define _WAPI_IE_ 68
+
+
+#define EID_BSSCoexistence 72 /* 20/40 BSS Coexistence */
+#define EID_BSSIntolerantChlReport 73
+#define _RIC_Descriptor_IE_ 75
+
+#define _LINK_ID_IE_ 101
+#define _CH_SWITCH_TIMING_ 104
+#define _PTI_BUFFER_STATUS_ 106
+#define _EXT_CAP_IE_ 127
+#define _VENDOR_SPECIFIC_IE_ 221
+
+#define _RESERVED47_ 47
+
+/* ---------------------------------------------------------------------------
+ Below is the fixed elements...
+-----------------------------------------------------------------------------*/
+#define _AUTH_ALGM_NUM_ 2
+#define _AUTH_SEQ_NUM_ 2
+#define _BEACON_ITERVAL_ 2
+#define _CAPABILITY_ 2
+#define _CURRENT_APADDR_ 6
+#define _LISTEN_INTERVAL_ 2
+#define _RSON_CODE_ 2
+#define _ASOC_ID_ 2
+#define _STATUS_CODE_ 2
+#define _TIMESTAMP_ 8
+
+#define AUTH_ODD_TO 0
+#define AUTH_EVEN_TO 1
+
+#define WLAN_ETHCONV_ENCAP 1
+#define WLAN_ETHCONV_RFC1042 2
+#define WLAN_ETHCONV_8021h 3
+
+#define cap_ESS BIT(0)
+#define cap_IBSS BIT(1)
+#define cap_CFPollable BIT(2)
+#define cap_CFRequest BIT(3)
+#define cap_Privacy BIT(4)
+#define cap_ShortPremble BIT(5)
+#define cap_PBCC BIT(6)
+#define cap_ChAgility BIT(7)
+#define cap_SpecMgmt BIT(8)
+#define cap_QoSi BIT(9)
+#define cap_ShortSlot BIT(10)
+
+/*-----------------------------------------------------------------------------
+ Below is the definition for 802.11i / 802.1x
+------------------------------------------------------------------------------*/
+#define _IEEE8021X_MGT_ 1 /* WPA */
+#define _IEEE8021X_PSK_ 2 /* WPA with pre-shared key */
+
+/*
+ * #define _NO_PRIVACY_ 0
+ * #define _WEP_40_PRIVACY_ 1
+ * #define _TKIP_PRIVACY_ 2
+ * #define _WRAP_PRIVACY_ 3
+ * #define _CCMP_PRIVACY_ 4
+ * #define _WEP_104_PRIVACY_ 5
+ * #define _WEP_WPA_MIXED_PRIVACY_ 6 WEP + WPA
+ */
+
+/*-----------------------------------------------------------------------------
+ Below is the definition for WMM
+------------------------------------------------------------------------------*/
+#define _WMM_IE_Length_ 7 /* for WMM STA */
+#define _WMM_Para_Element_Length_ 24
+
+
+/*-----------------------------------------------------------------------------
+ Below is the definition for 802.11n
+------------------------------------------------------------------------------*/
+
+/* 802.11 BAR control masks */
+#define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000
+#define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004
+
+/**
+ * struct rtw_ieee80211_ht_cap - HT additional information
+ *
+ * This structure refers to "HT information element" as
+ * described in 802.11n draft section 7.3.2.53
+ */
+struct ieee80211_ht_addt_info {
+ unsigned char control_chan;
+ unsigned char ht_param;
+ unsigned short operation_mode;
+ unsigned short stbc_param;
+ unsigned char basic_set[16];
+} __packed;
+
+struct HT_info_element {
+ unsigned char primary_channel;
+ unsigned char infos[5];
+ unsigned char MCS_rate[16];
+} __packed;
+
+struct AC_param {
+ unsigned char ACI_AIFSN;
+ unsigned char CW;
+ __le16 TXOP_limit;
+} __packed;
+
+struct WMM_para_element {
+ unsigned char QoS_info;
+ unsigned char reserved;
+ struct AC_param ac_param[4];
+} __packed;
+
+struct ADDBA_request {
+ unsigned char dialog_token;
+ __le16 BA_para_set;
+ unsigned short BA_timeout_value;
+ unsigned short BA_starting_seqctrl;
+} __packed;
+
+enum ht_cap_ampdu_factor {
+ MAX_AMPDU_FACTOR_8K = 0,
+ MAX_AMPDU_FACTOR_16K = 1,
+ MAX_AMPDU_FACTOR_32K = 2,
+ MAX_AMPDU_FACTOR_64K = 3,
+};
+
+/* 802.11n HT capabilities masks */
+#define IEEE80211_HT_CAP_SUP_WIDTH 0x0002
+#define IEEE80211_HT_CAP_SM_PS 0x000C
+#define IEEE80211_HT_CAP_GRN_FLD 0x0010
+#define IEEE80211_HT_CAP_SGI_20 0x0020
+#define IEEE80211_HT_CAP_SGI_40 0x0040
+#define IEEE80211_HT_CAP_TX_STBC 0x0080
+#define IEEE80211_HT_CAP_RX_STBC 0x0300
+#define IEEE80211_HT_CAP_DELAY_BA 0x0400
+#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800
+#define IEEE80211_HT_CAP_DSSSCCK40 0x1000
+/* 802.11n HT capability AMPDU settings */
+#define IEEE80211_HT_CAP_AMPDU_FACTOR 0x03
+#define IEEE80211_HT_CAP_AMPDU_DENSITY 0x1C
+/* 802.11n HT capability MSC set */
+#define IEEE80211_SUPP_MCS_SET_UEQM 4
+#define IEEE80211_HT_CAP_MAX_STREAMS 4
+#define IEEE80211_SUPP_MCS_SET_LEN 10
+/* maximum streams the spec allows */
+#define IEEE80211_HT_CAP_MCS_TX_DEFINED 0x01
+#define IEEE80211_HT_CAP_MCS_TX_RX_DIFF 0x02
+#define IEEE80211_HT_CAP_MCS_TX_STREAMS 0x0C
+#define IEEE80211_HT_CAP_MCS_TX_UEQM 0x10
+/* 802.11n HT IE masks */
+#define IEEE80211_HT_IE_CHA_SEC_OFFSET 0x03
+#define IEEE80211_HT_IE_CHA_SEC_NONE 0x00
+#define IEEE80211_HT_IE_CHA_SEC_ABOVE 0x01
+#define IEEE80211_HT_IE_CHA_SEC_BELOW 0x03
+#define IEEE80211_HT_IE_CHA_WIDTH 0x04
+#define IEEE80211_HT_IE_HT_PROTECTION 0x0003
+#define IEEE80211_HT_IE_NON_GF_STA_PRSNT 0x0004
+#define IEEE80211_HT_IE_NON_HT_STA_PRSNT 0x0010
+
+/* block-ack parameters */
+#define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002
+#define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C
+#define RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFC0
+#define IEEE80211_DELBA_PARAM_TID_MASK 0xF000
+#define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800
+
+/*
+ * A-PMDU buffer sizes
+ * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2)
+ */
+#define IEEE80211_MIN_AMPDU_BUF 0x8
+
+
+#define OP_MODE_PURE 0
+#define OP_MODE_MAY_BE_LEGACY_STAS 1
+#define OP_MODE_20MHZ_HT_STA_ASSOCED 2
+#define OP_MODE_MIXED 3
+
+#define HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK ((u8)BIT(0) | BIT(1))
+#define HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE ((u8)BIT(0))
+#define HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW ((u8)BIT(0) | BIT(1))
+#define HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH ((u8)BIT(2))
+#define HT_INFO_HT_PARAM_RIFS_MODE ((u8)BIT(3))
+#define HT_INFO_HT_PARAM_CTRL_ACCESS_ONLY ((u8)BIT(4))
+#define HT_INFO_HT_PARAM_SRV_INTERVAL_GRANULARITY ((u8)BIT(5))
+
+#define HT_INFO_OPERATION_MODE_OP_MODE_MASK \
+ ((u16)(0x0001 | 0x0002))
+#define HT_INFO_OPERATION_MODE_OP_MODE_OFFSET 0
+#define HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT ((u8)BIT(2))
+#define HT_INFO_OPERATION_MODE_TRANSMIT_BURST_LIMIT ((u8)BIT(3))
+#define HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT ((u8)BIT(4))
+
+#define HT_INFO_STBC_PARAM_DUAL_BEACON ((u16)BIT(6))
+#define HT_INFO_STBC_PARAM_DUAL_STBC_PROTECT ((u16)BIT(7))
+#define HT_INFO_STBC_PARAM_SECONDARY_BC ((u16)BIT(8))
+#define HT_INFO_STBC_PARAM_LSIG_TXOP_PROTECT_ALLOWED ((u16)BIT(9))
+#define HT_INFO_STBC_PARAM_PCO_ACTIVE ((u16)BIT(10))
+#define HT_INFO_STBC_PARAM_PCO_PHASE ((u16)BIT(11))
+
+/* ===============WPS Section=============== */
+/* For WPSv1.0 */
+#define WPSOUI 0x0050f204
+/* WPS attribute ID */
+#define WPS_ATTR_VER1 0x104A
+#define WPS_ATTR_SIMPLE_CONF_STATE 0x1044
+#define WPS_ATTR_RESP_TYPE 0x103B
+#define WPS_ATTR_UUID_E 0x1047
+#define WPS_ATTR_MANUFACTURER 0x1021
+#define WPS_ATTR_MODEL_NAME 0x1023
+#define WPS_ATTR_MODEL_NUMBER 0x1024
+#define WPS_ATTR_SERIAL_NUMBER 0x1042
+#define WPS_ATTR_PRIMARY_DEV_TYPE 0x1054
+#define WPS_ATTR_SEC_DEV_TYPE_LIST 0x1055
+#define WPS_ATTR_DEVICE_NAME 0x1011
+#define WPS_ATTR_CONF_METHOD 0x1008
+#define WPS_ATTR_RF_BANDS 0x103C
+#define WPS_ATTR_DEVICE_PWID 0x1012
+#define WPS_ATTR_REQUEST_TYPE 0x103A
+#define WPS_ATTR_ASSOCIATION_STATE 0x1002
+#define WPS_ATTR_CONFIG_ERROR 0x1009
+#define WPS_ATTR_VENDOR_EXT 0x1049
+#define WPS_ATTR_SELECTED_REGISTRAR 0x1041
+
+/* Value of WPS Request Type Attribute */
+#define WPS_REQ_TYPE_ENROLLEE_INFO_ONLY 0x00
+#define WPS_REQ_TYPE_ENROLLEE_OPEN_8021X 0x01
+#define WPS_REQ_TYPE_REGISTRAR 0x02
+#define WPS_REQ_TYPE_WLAN_MANAGER_REGISTRAR 0x03
+
+/* Value of WPS Response Type Attribute */
+#define WPS_RESPONSE_TYPE_INFO_ONLY 0x00
+#define WPS_RESPONSE_TYPE_8021X 0x01
+#define WPS_RESPONSE_TYPE_REGISTRAR 0x02
+#define WPS_RESPONSE_TYPE_AP 0x03
+
+/* Value of WPS WiFi Simple Configuration State Attribute */
+#define WPS_WSC_STATE_NOT_CONFIG 0x01
+#define WPS_WSC_STATE_CONFIG 0x02
+
+/* Value of WPS Version Attribute */
+#define WPS_VERSION_1 0x10
+
+/* Value of WPS Configuration Method Attribute */
+#define WPS_CONFIG_METHOD_FLASH 0x0001
+#define WPS_CONFIG_METHOD_ETHERNET 0x0002
+#define WPS_CONFIG_METHOD_LABEL 0x0004
+#define WPS_CONFIG_METHOD_DISPLAY 0x0008
+#define WPS_CONFIG_METHOD_E_NFC 0x0010
+#define WPS_CONFIG_METHOD_I_NFC 0x0020
+#define WPS_CONFIG_METHOD_NFC 0x0040
+#define WPS_CONFIG_METHOD_PBC 0x0080
+#define WPS_CONFIG_METHOD_KEYPAD 0x0100
+#define WPS_CONFIG_METHOD_VPBC 0x0280
+#define WPS_CONFIG_METHOD_PPBC 0x0480
+#define WPS_CONFIG_METHOD_VDISPLAY 0x2008
+#define WPS_CONFIG_METHOD_PDISPLAY 0x4008
+
+/* Value of Category ID of WPS Primary Device Type Attribute */
+#define WPS_PDT_CID_DISPLAYS 0x0007
+#define WPS_PDT_CID_MULIT_MEDIA 0x0008
+#define WPS_PDT_CID_RTK_WIDI WPS_PDT_CID_MULIT_MEDIA
+
+/* Value of Sub Category ID of WPS Primary Device Type Attribute */
+#define WPS_PDT_SCID_MEDIA_SERVER 0x0005
+#define WPS_PDT_SCID_RTK_DMP WPS_PDT_SCID_MEDIA_SERVER
+
+/* Value of Device Password ID */
+#define WPS_DPID_P 0x0000
+#define WPS_DPID_USER_SPEC 0x0001
+#define WPS_DPID_MACHINE_SPEC 0x0002
+#define WPS_DPID_REKEY 0x0003
+#define WPS_DPID_PBC 0x0004
+#define WPS_DPID_REGISTRAR_SPEC 0x0005
+
+/* Value of WPS RF Bands Attribute */
+#define WPS_RF_BANDS_2_4_GHZ 0x01
+#define WPS_RF_BANDS_5_GHZ 0x02
+
+/* Value of WPS Association State Attribute */
+#define WPS_ASSOC_STATE_NOT_ASSOCIATED 0x00
+#define WPS_ASSOC_STATE_CONNECTION_SUCCESS 0x01
+#define WPS_ASSOC_STATE_CONFIGURATION_FAILURE 0x02
+#define WPS_ASSOC_STATE_ASSOCIATION_FAILURE 0x03
+#define WPS_ASSOC_STATE_IP_FAILURE 0x04
+
+/* WPS Configuration Method */
+#define WPS_CM_NONE 0x0000
+#define WPS_CM_LABEL 0x0004
+#define WPS_CM_DISPLYA 0x0008
+#define WPS_CM_EXTERNAL_NFC_TOKEN 0x0010
+#define WPS_CM_INTEGRATED_NFC_TOKEN 0x0020
+#define WPS_CM_NFC_INTERFACE 0x0040
+#define WPS_CM_PUSH_BUTTON 0x0080
+#define WPS_CM_KEYPAD 0x0100
+#define WPS_CM_SW_PUHS_BUTTON 0x0280
+#define WPS_CM_HW_PUHS_BUTTON 0x0480
+#define WPS_CM_SW_DISPLAY_P 0x2008
+#define WPS_CM_LCD_DISPLAY_P 0x4008
+
+#define IP_MCAST_MAC(mac) \
+ ((mac[0] == 0x01) && (mac[1] == 0x00) && (mac[2] == 0x5e))
+#define ICMPV6_MCAST_MAC(mac) \
+ ((mac[0] == 0x33) && (mac[1] == 0x33) && (mac[2] != 0xff))
+
+#endif /* _WIFI_H_ */
diff --git a/drivers/staging/rtl8188eu/include/wlan_bssdef.h b/drivers/staging/rtl8188eu/include/wlan_bssdef.h
new file mode 100644
index 0000000..8462c9c
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/wlan_bssdef.h
@@ -0,0 +1,243 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __WLAN_BSSDEF_H__
+#define __WLAN_BSSDEF_H__
+
+
+#define MAX_IE_SZ 768
+
+#define NDIS_802_11_LENGTH_SSID 32
+#define NDIS_802_11_LENGTH_RATES 8
+#define NDIS_802_11_LENGTH_RATES_EX 16
+
+#define NDIS_802_11_RSSI long /* in dBm */
+
+struct ndis_802_11_ssid {
+ u32 ssid_length;
+ u8 ssid[32];
+};
+
+enum NDIS_802_11_NETWORK_TYPE {
+ Ndis802_11FH,
+ Ndis802_11DS,
+ Ndis802_11OFDM5,
+ Ndis802_11OFDM24,
+ Ndis802_11NetworkTypeMax /* dummy upper bound */
+};
+
+struct ndis_802_11_config_fh {
+ u32 Length; /* Length of structure */
+ u32 HopPattern; /* As defined by 802.11, MSB set */
+ u32 HopSet; /* to one if non-802.11 */
+ u32 DwellTime; /* units are Kusec */
+};
+
+/*
+ * FW will only save the channel number in DSConfig.
+ * ODI Handler will convert the channel number to freq. number.
+ */
+struct ndis_802_11_config {
+ u32 Length; /* Length of structure */
+ u32 BeaconPeriod; /* units are Kusec */
+ u32 ATIMWindow; /* units are Kusec */
+ u32 DSConfig; /* Frequency, units are kHz */
+ struct ndis_802_11_config_fh FHConfig;
+};
+
+enum ndis_802_11_network_infra {
+ Ndis802_11IBSS,
+ Ndis802_11Infrastructure,
+ Ndis802_11AutoUnknown,
+ Ndis802_11InfrastructureMax, /* dummy upper bound */
+ Ndis802_11APMode
+};
+
+struct ndis_802_11_fixed_ie {
+ u8 Timestamp[8];
+ u16 BeaconInterval;
+ u16 Capabilities;
+};
+
+
+
+struct ndis_802_11_var_ie {
+ u8 ElementID;
+ u8 Length;
+ u8 data[1];
+};
+
+/*
+ * Length is the 4 bytes multiples of the sume of
+ * [ETH_ALEN] + 2 + sizeof (struct ndis_802_11_ssid) + sizeof (u32)
+ * + sizeof (NDIS_802_11_RSSI) + sizeof (enum NDIS_802_11_NETWORK_TYPE)
+ * + sizeof (struct ndis_802_11_config)
+ * + NDIS_802_11_LENGTH_RATES_EX + ie_length
+ *
+ * Except the ie_length, all other fields are fixed length.
+ * Therefore, we can define a macro to represent the partial sum.
+ */
+
+enum ndis_802_11_auth_mode {
+ Ndis802_11AuthModeOpen,
+ Ndis802_11AuthModeShared,
+ Ndis802_11AuthModeAutoSwitch,
+ Ndis802_11AuthModeWPA,
+ Ndis802_11AuthModeWPAPSK,
+ Ndis802_11AuthModeWPANone,
+ Ndis802_11AuthModeWAPI,
+ Ndis802_11AuthModeMax /* Not a real mode, upper bound */
+};
+
+enum ndis_802_11_wep_status {
+ Ndis802_11WEPEnabled,
+ Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled,
+ Ndis802_11WEPDisabled,
+ Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled,
+ Ndis802_11WEPKeyAbsent,
+ Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent,
+ Ndis802_11WEPNotSupported,
+ Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported,
+ Ndis802_11Encryption2Enabled,
+ Ndis802_11Encryption2KeyAbsent,
+ Ndis802_11Encryption3Enabled,
+ Ndis802_11Encryption3KeyAbsent,
+ Ndis802_11_EncryptionWAPI
+};
+
+#define NDIS_802_11_AI_REQFI_CAPABILITIES 1
+#define NDIS_802_11_AI_REQFI_LISTENINTERVAL 2
+#define NDIS_802_11_AI_REQFI_CURRENTAPADDRESS 4
+
+#define NDIS_802_11_AI_RESFI_CAPABILITIES 1
+#define NDIS_802_11_AI_RESFI_STATUSCODE 2
+#define NDIS_802_11_AI_RESFI_ASSOCIATIONID 4
+
+enum ndis_802_11_reload_def {
+ Ndis802_11ReloadWEPKeys
+};
+
+struct ndis_802_11_wep {
+ u32 Length; /* Length of this structure */
+ u32 KeyIndex; /* 0 is the per-client key,
+ * 1-N are the global keys
+ */
+ u32 KeyLength; /* length of key in bytes */
+ u8 KeyMaterial[16];/* variable len depending on above field */
+};
+
+enum ndis_802_11_status_type {
+ Ndis802_11StatusType_Authentication,
+ Ndis802_11StatusType_MediaStreamMode,
+ Ndis802_11StatusType_PMKID_CandidateList,
+ Ndis802_11StatusTypeMax /* not a real type, defined as
+ * an upper bound
+ */
+};
+
+/* mask for authentication/integrity fields */
+#define NDIS_802_11_AUTH_REQUEST_AUTH_FIELDS 0x0f
+#define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01
+#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02
+#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06
+#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E
+
+/* MIC check time, 60 seconds. */
+#define MIC_CHECK_TIME 60000000
+
+#ifndef Ndis802_11APMode
+#define Ndis802_11APMode (Ndis802_11InfrastructureMax+1)
+#endif
+
+struct wlan_phy_info {
+ u8 SignalStrength;/* in percentage) */
+ u8 SignalQuality;/* in percentage) */
+ u8 Optimum_antenna; /* for Antenna diversity */
+ u8 Reserved_0;
+};
+
+struct wlan_bcn_info {
+ /* these infor get from rtw_get_encrypt_info when
+ * * translate scan to UI
+ */
+ u8 encryp_protocol;/* ENCRYP_PROTOCOL_E: OPEN/WEP/WPA/WPA2/WAPI */
+ int group_cipher; /* WPA/WPA2 group cipher */
+ int pairwise_cipher;/* WPA/WPA2/WEP pairwise cipher */
+ int is_8021x;
+
+ /* bwmode 20/40 and ch_offset UP/LOW */
+ unsigned short ht_cap_info;
+ unsigned char ht_info_infos_0;
+};
+
+/* temporally add #pragma pack for structure alignment issue of
+ * struct wlan_bssid_ex and get_struct wlan_bssid_ex_sz()
+ */
+struct wlan_bssid_ex {
+ u32 Length;
+ unsigned char MacAddress[ETH_ALEN];
+ u8 Reserved[2];/* 0]: IS beacon frame */
+ struct ndis_802_11_ssid ssid;
+ u32 Privacy;
+ NDIS_802_11_RSSI Rssi;/* in dBM,raw data ,get from PHY) */
+ enum NDIS_802_11_NETWORK_TYPE NetworkTypeInUse;
+ struct ndis_802_11_config Configuration;
+ enum ndis_802_11_network_infra InfrastructureMode;
+ unsigned char SupportedRates[NDIS_802_11_LENGTH_RATES_EX];
+ struct wlan_phy_info PhyInfo;
+ u32 ie_length;
+ u8 ies[MAX_IE_SZ]; /* timestamp, beacon interval, and
+ * capability information)
+ */
+} __packed;
+
+static inline uint get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss)
+{
+ return sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + bss->ie_length;
+}
+
+struct wlan_network {
+ struct list_head list;
+ int network_type; /* refer to ieee80211.h for WIRELESS_11A/B/G */
+ int fixed; /* set fixed when not to be removed
+ * in site-surveying
+ */
+ unsigned long last_scanned; /* timestamp for the network */
+ int aid; /* will only be valid when a BSS is joinned. */
+ int join_res;
+ struct wlan_bssid_ex network; /* must be the last item */
+ struct wlan_bcn_info BcnInfo;
+};
+
+enum VRTL_CARRIER_SENSE {
+ DISABLE_VCS,
+ ENABLE_VCS,
+ AUTO_VCS
+};
+
+enum VCS_TYPE {
+ NONE_VCS,
+ RTS_CTS,
+ CTS_TO_SELF
+};
+
+#define PWR_CAM 0
+#define PWR_MINPS 1
+#define PWR_MAXPS 2
+#define PWR_UAPSD 3
+#define PWR_VOIP 4
+
+enum UAPSD_MAX_SP {
+ NO_LIMIT,
+ TWO_MSDU,
+ FOUR_MSDU,
+ SIX_MSDU
+};
+
+#define NUM_PRE_AUTH_KEY 16
+#define NUM_PMKID_CACHE NUM_PRE_AUTH_KEY
+
+#endif /* ifndef WLAN_BSSDEF_H_ */
diff --git a/drivers/staging/rtl8188eu/include/xmit_osdep.h b/drivers/staging/rtl8188eu/include/xmit_osdep.h
new file mode 100644
index 0000000..5283a6d
--- /dev/null
+++ b/drivers/staging/rtl8188eu/include/xmit_osdep.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#ifndef __XMIT_OSDEP_H_
+#define __XMIT_OSDEP_H_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+
+#define NR_XMITFRAME 256
+
+struct xmit_priv;
+struct pkt_attrib;
+struct sta_xmit_priv;
+struct xmit_frame;
+struct xmit_buf;
+
+int rtw_xmit_entry(struct sk_buff *pkt, struct net_device *pnetdev);
+
+void rtw_os_xmit_schedule(struct adapter *padapter);
+
+int rtw_os_xmit_resource_alloc(struct adapter *padapter,
+ struct xmit_buf *pxmitbuf, u32 alloc_sz);
+void rtw_os_xmit_resource_free(struct xmit_buf *pxmitbuf);
+
+void rtw_os_pkt_complete(struct adapter *padapter, struct sk_buff *pkt);
+void rtw_os_xmit_complete(struct adapter *padapter,
+ struct xmit_frame *pxframe);
+
+#endif /* __XMIT_OSDEP_H_ */
diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
new file mode 100644
index 0000000..f266615
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
@@ -0,0 +1,3067 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _IOCTL_LINUX_C_
+
+#include <linux/ieee80211.h>
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <wlan_bssdef.h>
+#include <rtw_debug.h>
+#include <wifi.h>
+#include <rtw_mlme.h>
+#include <rtw_mlme_ext.h>
+#include <rtw_ioctl.h>
+#include <rtw_ioctl_set.h>
+#include <rtl8188e_hal.h>
+
+#include <linux/vmalloc.h>
+#include <linux/etherdevice.h>
+
+#include "osdep_intf.h"
+
+#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 30)
+
+#define SCAN_ITEM_SIZE 768
+#define MAX_CUSTOM_LEN 64
+#define RATE_COUNT 4
+
+/* combo scan */
+#define WEXT_CSCAN_AMOUNT 9
+#define WEXT_CSCAN_BUF_LEN 360
+#define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00"
+#define WEXT_CSCAN_HEADER_SIZE 12
+#define WEXT_CSCAN_SSID_SECTION 'S'
+#define WEXT_CSCAN_CHANNEL_SECTION 'C'
+#define WEXT_CSCAN_NPROBE_SECTION 'N'
+#define WEXT_CSCAN_ACTV_DWELL_SECTION 'A'
+#define WEXT_CSCAN_PASV_DWELL_SECTION 'P'
+#define WEXT_CSCAN_HOME_DWELL_SECTION 'H'
+#define WEXT_CSCAN_TYPE_SECTION 'T'
+
+static u32 rtw_rates[] = {1000000, 2000000, 5500000, 11000000,
+ 6000000, 9000000, 12000000, 18000000, 24000000, 36000000,
+ 48000000, 54000000};
+
+static const char * const iw_operation_mode[] = {
+ "Auto", "Ad-Hoc", "Managed", "Master", "Repeater",
+ "Secondary", "Monitor"
+};
+
+void indicate_wx_scan_complete_event(struct adapter *padapter)
+{
+ union iwreq_data wrqu;
+
+ memset(&wrqu, 0, sizeof(union iwreq_data));
+ wireless_send_event(padapter->pnetdev, SIOCGIWSCAN, &wrqu, NULL);
+}
+
+void rtw_indicate_wx_assoc_event(struct adapter *padapter)
+{
+ union iwreq_data wrqu;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ memset(&wrqu, 0, sizeof(union iwreq_data));
+
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+
+ memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN);
+
+ DBG_88E_LEVEL(_drv_always_, "assoc success\n");
+ wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
+}
+
+void rtw_indicate_wx_disassoc_event(struct adapter *padapter)
+{
+ union iwreq_data wrqu;
+
+ memset(&wrqu, 0, sizeof(union iwreq_data));
+
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ eth_zero_addr(wrqu.ap_addr.sa_data);
+
+ DBG_88E_LEVEL(_drv_always_, "indicate disassoc\n");
+ wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
+}
+
+static char *translate_scan(struct adapter *padapter,
+ struct iw_request_info *info,
+ struct wlan_network *pnetwork,
+ char *start, char *stop)
+{
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct iw_event iwe;
+ u16 cap;
+ __le16 le_tmp;
+ u32 ht_ielen = 0;
+ char custom[MAX_CUSTOM_LEN];
+ char *p;
+ u16 max_rate = 0, rate, ht_cap = false;
+ u32 i = 0;
+ u8 bw_40MHz = 0, short_GI = 0;
+ u16 mcs_rate = 0;
+ u8 ss, sq;
+
+ /* AP MAC address */
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+
+ memcpy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress, ETH_ALEN);
+ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
+
+ /* Add the ESSID */
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.flags = 1;
+ iwe.u.data.length = min_t(u16, pnetwork->network.ssid.ssid_length, 32);
+ start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.ssid.ssid);
+
+ /* parsing HT_CAP_IE */
+ p = rtw_get_ie(&pnetwork->network.ies[12], _HT_CAPABILITY_IE_, &ht_ielen, pnetwork->network.ie_length-12);
+
+ if (p && ht_ielen > 0) {
+ struct ieee80211_ht_cap *pht_capie;
+ ht_cap = true;
+
+ pht_capie = (struct ieee80211_ht_cap *)(p + 2);
+ memcpy(&mcs_rate, pht_capie->mcs.rx_mask, 2);
+ bw_40MHz = !!(le16_to_cpu(pht_capie->cap_info) &
+ IEEE80211_HT_CAP_SUP_WIDTH);
+ short_GI = !!(le16_to_cpu(pht_capie->cap_info) &
+ (IEEE80211_HT_CAP_SGI_20 |
+ IEEE80211_HT_CAP_SGI_40));
+ }
+
+ /* Add the protocol name */
+ iwe.cmd = SIOCGIWNAME;
+ if ((rtw_is_cckratesonly_included((u8 *)&pnetwork->network.SupportedRates))) {
+ if (ht_cap)
+ snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
+ else
+ snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
+ } else if ((rtw_is_cckrates_included((u8 *)&pnetwork->network.SupportedRates))) {
+ if (ht_cap)
+ snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
+ else
+ snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
+ } else {
+ if (pnetwork->network.Configuration.DSConfig > 14) {
+ if (ht_cap)
+ snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11an");
+ else
+ snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11a");
+ } else {
+ if (ht_cap)
+ snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
+ else
+ snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
+ }
+ }
+
+ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
+
+ /* Add mode */
+ iwe.cmd = SIOCGIWMODE;
+ memcpy(&le_tmp, rtw_get_capability_from_ie(pnetwork->network.ies), 2);
+
+ cap = le16_to_cpu(le_tmp);
+
+ if (!WLAN_CAPABILITY_IS_STA_BSS(cap)) {
+ if (cap & WLAN_CAPABILITY_ESS)
+ iwe.u.mode = IW_MODE_MASTER;
+ else
+ iwe.u.mode = IW_MODE_ADHOC;
+
+ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
+ }
+
+ if (pnetwork->network.Configuration.DSConfig < 1)
+ pnetwork->network.Configuration.DSConfig = 1;
+
+ /* Add frequency/channel */
+ iwe.cmd = SIOCGIWFREQ;
+ iwe.u.freq.m = rtw_ch2freq(pnetwork->network.Configuration.DSConfig) * 100000;
+ iwe.u.freq.e = 1;
+ iwe.u.freq.i = pnetwork->network.Configuration.DSConfig;
+ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
+
+ /* Add encryption capability */
+ iwe.cmd = SIOCGIWENCODE;
+ if (cap & WLAN_CAPABILITY_PRIVACY)
+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ else
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+ iwe.u.data.length = 0;
+ start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.ssid.ssid);
+
+ /*Add basic and extended rates */
+ max_rate = 0;
+ p = custom;
+ p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
+ while (pnetwork->network.SupportedRates[i] != 0) {
+ rate = pnetwork->network.SupportedRates[i]&0x7F;
+ if (rate > max_rate)
+ max_rate = rate;
+ p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
+ "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
+ i++;
+ }
+
+ if (ht_cap) {
+ if (mcs_rate&0x8000)/* MCS15 */
+ max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) : ((short_GI) ? 144 : 130);
+ else if (mcs_rate&0x0080)/* MCS7 */
+ ;
+ else/* default MCS7 */
+ max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) : ((short_GI) ? 72 : 65);
+
+ max_rate = max_rate*2;/* Mbps/2; */
+ }
+
+ iwe.cmd = SIOCGIWRATE;
+ iwe.u.bitrate.fixed = 0;
+ iwe.u.bitrate.disabled = 0;
+ iwe.u.bitrate.value = max_rate * 500000;
+ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN);
+
+ /* parsing WPA/WPA2 IE */
+ {
+ u8 *buf;
+ u8 wpa_ie[255], rsn_ie[255];
+ u16 wpa_len = 0, rsn_len = 0;
+ u8 *p;
+
+ buf = kzalloc(MAX_WPA_IE_LEN, GFP_ATOMIC);
+ if (!buf)
+ return start;
+
+ rtw_get_sec_ie(pnetwork->network.ies, pnetwork->network.ie_length, rsn_ie, &rsn_len, wpa_ie, &wpa_len);
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: ssid =%s\n", pnetwork->network.ssid.ssid));
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan: wpa_len =%d rsn_len =%d\n", wpa_len, rsn_len));
+
+ if (wpa_len > 0) {
+ p = buf;
+ p += sprintf(p, "wpa_ie=");
+ for (i = 0; i < wpa_len; i++)
+ p += sprintf(p, "%02x", wpa_ie[i]);
+
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVCUSTOM;
+ iwe.u.data.length = strlen(buf);
+ start = iwe_stream_add_point(info, start, stop, &iwe, buf);
+
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = wpa_len;
+ start = iwe_stream_add_point(info, start, stop, &iwe, wpa_ie);
+ }
+ if (rsn_len > 0) {
+ p = buf;
+ p += sprintf(p, "rsn_ie=");
+ for (i = 0; i < rsn_len; i++)
+ p += sprintf(p, "%02x", rsn_ie[i]);
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVCUSTOM;
+ iwe.u.data.length = strlen(buf);
+ start = iwe_stream_add_point(info, start, stop, &iwe, buf);
+
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = rsn_len;
+ start = iwe_stream_add_point(info, start, stop, &iwe, rsn_ie);
+ }
+ kfree(buf);
+ }
+
+ {/* parsing WPS IE */
+ uint cnt = 0, total_ielen;
+ u8 *wpsie_ptr = NULL;
+ uint wps_ielen = 0;
+ u8 *ie_ptr = pnetwork->network.ies + _FIXED_IE_LENGTH_;
+
+ total_ielen = pnetwork->network.ie_length - _FIXED_IE_LENGTH_;
+
+ while (cnt < total_ielen) {
+ if (rtw_is_wps_ie(&ie_ptr[cnt], &wps_ielen) && (wps_ielen > 2)) {
+ wpsie_ptr = &ie_ptr[cnt];
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = (u16)wps_ielen;
+ start = iwe_stream_add_point(info, start, stop, &iwe, wpsie_ptr);
+ }
+ cnt += ie_ptr[cnt+1]+2; /* goto next */
+ }
+ }
+
+ /* Add quality statistics */
+ iwe.cmd = IWEVQUAL;
+ iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID;
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED) &&
+ is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network)) {
+ ss = padapter->recvpriv.signal_strength;
+ sq = padapter->recvpriv.signal_qual;
+ } else {
+ ss = pnetwork->network.PhyInfo.SignalStrength;
+ sq = pnetwork->network.PhyInfo.SignalQuality;
+ }
+
+ iwe.u.qual.level = (u8)ss;
+ iwe.u.qual.qual = (u8)sq; /* signal quality */
+ iwe.u.qual.noise = 0; /* noise level */
+ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
+ return start;
+}
+
+static int wpa_set_auth_algs(struct net_device *dev, u32 value)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ int ret = 0;
+
+ if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
+ DBG_88E("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY and AUTH_ALG_OPEN_SYSTEM [value:0x%x]\n", value);
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+ padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeAutoSwitch;
+ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
+ } else if (value & AUTH_ALG_SHARED_KEY) {
+ DBG_88E("wpa_set_auth_algs, AUTH_ALG_SHARED_KEY [value:0x%x]\n", value);
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+
+ padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
+ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
+ } else if (value & AUTH_ALG_OPEN_SYSTEM) {
+ DBG_88E("wpa_set_auth_algs, AUTH_ALG_OPEN_SYSTEM\n");
+ if (padapter->securitypriv.ndisauthtype < Ndis802_11AuthModeWPAPSK) {
+ padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
+ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
+ }
+ } else if (value & AUTH_ALG_LEAP) {
+ DBG_88E("wpa_set_auth_algs, AUTH_ALG_LEAP\n");
+ } else {
+ DBG_88E("wpa_set_auth_algs, error!\n");
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
+{
+ int ret = 0;
+ u32 wep_key_idx, wep_key_len, wep_total_len;
+ struct ndis_802_11_wep *pwep = NULL;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+
+ param->u.crypt.err = 0;
+ param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
+
+ if (param_len < (u32)((u8 *)param->u.crypt.key - (u8 *)param) + param->u.crypt.key_len) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ if (is_broadcast_ether_addr(param->sta_addr)) {
+ if (param->u.crypt.idx >= WEP_KEYS) {
+ ret = -EINVAL;
+ goto exit;
+ }
+ } else {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+ RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("wpa_set_encryption, crypt.alg = WEP\n"));
+ DBG_88E("wpa_set_encryption, crypt.alg = WEP\n");
+
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+ padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
+ padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
+
+ wep_key_idx = param->u.crypt.idx;
+ wep_key_len = param->u.crypt.key_len;
+
+ RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("(1)wep_key_idx =%d\n", wep_key_idx));
+ DBG_88E("(1)wep_key_idx =%d\n", wep_key_idx);
+
+ if (wep_key_idx > WEP_KEYS)
+ return -EINVAL;
+
+ RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("(2)wep_key_idx =%d\n", wep_key_idx));
+
+ if (wep_key_len > 0) {
+ wep_key_len = wep_key_len <= 5 ? 5 : 13;
+ wep_total_len = wep_key_len + offsetof(struct ndis_802_11_wep, KeyMaterial);
+ pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len);
+ if (!pwep) {
+ RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, (" wpa_set_encryption: pwep allocate fail !!!\n"));
+ goto exit;
+ }
+ memset(pwep, 0, wep_total_len);
+ pwep->KeyLength = wep_key_len;
+ pwep->Length = wep_total_len;
+ if (wep_key_len == 13) {
+ padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
+ padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
+ }
+ } else {
+ ret = -EINVAL;
+ goto exit;
+ }
+ pwep->KeyIndex = wep_key_idx;
+ pwep->KeyIndex |= 0x80000000;
+ memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
+ if (param->u.crypt.set_tx) {
+ DBG_88E("wep, set_tx = 1\n");
+ if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
+ ret = -EOPNOTSUPP;
+ } else {
+ DBG_88E("wep, set_tx = 0\n");
+ if (wep_key_idx >= WEP_KEYS) {
+ ret = -EOPNOTSUPP;
+ goto exit;
+ }
+ memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
+ psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
+ rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0);
+ }
+ goto exit;
+ }
+
+ if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /* 802_1x */
+ struct sta_info *psta, *pbcmc_sta;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { /* sta mode */
+ psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
+ if (!psta) {
+ ;
+ } else {
+ if (strcmp(param->u.crypt.alg, "none") != 0)
+ psta->ieee8021x_blocked = false;
+
+ if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
+ (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled))
+ psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
+
+ if (param->u.crypt.set_tx == 1) { /* pairwise key */
+ memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
+
+ if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
+ memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
+ memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
+ padapter->securitypriv.busetkipkey = false;
+ }
+
+ DBG_88E(" ~~~~set sta key:unicastkey\n");
+
+ rtw_setstakey_cmd(padapter, (unsigned char *)psta, true);
+ } else { /* group key */
+ memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16 ));
+ memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
+ memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
+ padapter->securitypriv.binstallGrpkey = true;
+ DBG_88E(" ~~~~set sta key:groupkey\n");
+
+ padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
+
+ rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1);
+ }
+ }
+ pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+ if (!pbcmc_sta) {
+ ;
+ } else {
+ /* Jeff: don't disable ieee8021x_blocked while clearing key */
+ if (strcmp(param->u.crypt.alg, "none") != 0)
+ pbcmc_sta->ieee8021x_blocked = false;
+
+ if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
+ (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled))
+ pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
+ }
+ }
+ }
+
+exit:
+
+ kfree(pwep);
+ return ret;
+}
+
+static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ielen)
+{
+ u8 *buf = NULL;
+ int group_cipher = 0, pairwise_cipher = 0;
+ int ret = 0;
+
+ if ((ielen > MAX_WPA_IE_LEN) || (!pie)) {
+ _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
+ if (!pie)
+ return ret;
+ else
+ return -EINVAL;
+ }
+
+ if (ielen) {
+ buf = kmemdup(pie, ielen, GFP_KERNEL);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ /* dump */
+ {
+ int i;
+
+ DBG_88E("\n wpa_ie(length:%d):\n", ielen);
+ for (i = 0; i < ielen; i += 8)
+ DBG_88E("0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", buf[i], buf[i+1], buf[i+2], buf[i+3], buf[i+4], buf[i+5], buf[i+6], buf[i+7]);
+ }
+
+ if (ielen < RSN_HEADER_LEN) {
+ RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("Ie len too short %d\n", ielen));
+ ret = -1;
+ goto exit;
+ }
+
+ if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
+ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
+ padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK;
+ memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
+ }
+
+ if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
+ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
+ padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK;
+ memcpy(padapter->securitypriv.supplicant_ie, &buf[0], ielen);
+ }
+
+ switch (group_cipher) {
+ case WPA_CIPHER_NONE:
+ padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
+ break;
+ case WPA_CIPHER_WEP40:
+ padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+ break;
+ case WPA_CIPHER_TKIP:
+ padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
+ break;
+ case WPA_CIPHER_CCMP:
+ padapter->securitypriv.dot118021XGrpPrivacy = _AES_;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
+ break;
+ case WPA_CIPHER_WEP104:
+ padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+ break;
+ }
+
+ switch (pairwise_cipher) {
+ case WPA_CIPHER_NONE:
+ padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
+ break;
+ case WPA_CIPHER_WEP40:
+ padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+ break;
+ case WPA_CIPHER_TKIP:
+ padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
+ break;
+ case WPA_CIPHER_CCMP:
+ padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
+ break;
+ case WPA_CIPHER_WEP104:
+ padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+ break;
+ }
+
+ _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
+ {/* set wps_ie */
+ u16 cnt = 0;
+ u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
+
+ while (cnt < ielen) {
+ eid = buf[cnt];
+ if ((eid == _VENDOR_SPECIFIC_IE_) && (!memcmp(&buf[cnt+2], wps_oui, 4))) {
+ DBG_88E("SET WPS_IE\n");
+
+ padapter->securitypriv.wps_ie_len = min(buf[cnt + 1] + 2, MAX_WPA_IE_LEN << 2);
+
+ memcpy(padapter->securitypriv.wps_ie, &buf[cnt], padapter->securitypriv.wps_ie_len);
+
+ set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
+ cnt += buf[cnt+1]+2;
+ break;
+ } else {
+ cnt += buf[cnt+1]+2; /* goto next */
+ }
+ }
+ }
+ }
+
+ RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
+ ("rtw_set_wpa_ie: pairwise_cipher = 0x%08x padapter->securitypriv.ndisencryptstatus =%d padapter->securitypriv.ndisauthtype =%d\n",
+ pairwise_cipher, padapter->securitypriv.ndisencryptstatus, padapter->securitypriv.ndisauthtype));
+exit:
+ kfree(buf);
+ return ret;
+}
+
+typedef unsigned char NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX];
+
+static int rtw_wx_get_name(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ u32 ht_ielen = 0;
+ char *p;
+ u8 ht_cap = false;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
+ NDIS_802_11_RATES_EX *prates = NULL;
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("cmd_code =%x\n", info->cmd));
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
+ /* parsing HT_CAP_IE */
+ p = rtw_get_ie(&pcur_bss->ies[12], _HT_CAPABILITY_IE_, &ht_ielen, pcur_bss->ie_length-12);
+ if (p && ht_ielen > 0)
+ ht_cap = true;
+
+ prates = &pcur_bss->SupportedRates;
+
+ if (rtw_is_cckratesonly_included((u8 *)prates)) {
+ if (ht_cap)
+ snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bn");
+ else
+ snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b");
+ } else if (rtw_is_cckrates_included((u8 *)prates)) {
+ if (ht_cap)
+ snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bgn");
+ else
+ snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11bg");
+ } else {
+ if (pcur_bss->Configuration.DSConfig > 14) {
+ if (ht_cap)
+ snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11an");
+ else
+ snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11a");
+ } else {
+ if (ht_cap)
+ snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11gn");
+ else
+ snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g");
+ }
+ }
+ } else {
+ snprintf(wrqu->name, IFNAMSIZ, "unassociated");
+ }
+ return 0;
+}
+
+static int rtw_wx_set_freq(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_wx_set_freq\n"));
+ return 0;
+}
+
+static int rtw_wx_get_freq(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ /* wrqu->freq.m = ieee80211_wlan_frequencies[pcur_bss->Configuration.DSConfig-1] * 100000; */
+ wrqu->freq.m = rtw_ch2freq(pcur_bss->Configuration.DSConfig) * 100000;
+ wrqu->freq.e = 1;
+ wrqu->freq.i = pcur_bss->Configuration.DSConfig;
+ } else {
+ wrqu->freq.m = rtw_ch2freq(padapter->mlmeextpriv.cur_channel) * 100000;
+ wrqu->freq.e = 1;
+ wrqu->freq.i = padapter->mlmeextpriv.cur_channel;
+ }
+
+ return 0;
+}
+
+static int rtw_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ enum ndis_802_11_network_infra networkType;
+ int ret = 0;
+
+ if (_FAIL == rtw_pwr_wakeup(padapter)) {
+ ret = -EPERM;
+ goto exit;
+ }
+
+ if (!padapter->hw_init_completed) {
+ ret = -EPERM;
+ goto exit;
+ }
+
+ switch (wrqu->mode) {
+ case IW_MODE_AUTO:
+ networkType = Ndis802_11AutoUnknown;
+ DBG_88E("set_mode = IW_MODE_AUTO\n");
+ break;
+ case IW_MODE_ADHOC:
+ networkType = Ndis802_11IBSS;
+ DBG_88E("set_mode = IW_MODE_ADHOC\n");
+ break;
+ case IW_MODE_MASTER:
+ networkType = Ndis802_11APMode;
+ DBG_88E("set_mode = IW_MODE_MASTER\n");
+ break;
+ case IW_MODE_INFRA:
+ networkType = Ndis802_11Infrastructure;
+ DBG_88E("set_mode = IW_MODE_INFRA\n");
+ break;
+ default:
+ ret = -EINVAL;
+ RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_, ("\n Mode: %s is not supported\n", iw_operation_mode[wrqu->mode]));
+ goto exit;
+ }
+ if (!rtw_set_802_11_infrastructure_mode(padapter, networkType)) {
+ ret = -EPERM;
+ goto exit;
+ }
+ rtw_setopmode_cmd(padapter, networkType);
+exit:
+ return ret;
+}
+
+static int rtw_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_get_mode\n"));
+
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
+ wrqu->mode = IW_MODE_INFRA;
+ else if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
+ (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)))
+ wrqu->mode = IW_MODE_ADHOC;
+ else if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ wrqu->mode = IW_MODE_MASTER;
+ else
+ wrqu->mode = IW_MODE_AUTO;
+
+ return 0;
+}
+
+static int rtw_wx_set_pmkid(struct net_device *dev,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ u8 j, blInserted = false;
+ int ret = false;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct iw_pmksa *pPMK = (struct iw_pmksa *)extra;
+ u8 strZeroMacAddress[ETH_ALEN] = {0x00};
+ u8 strIssueBssid[ETH_ALEN] = {0x00};
+
+ memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
+ if (pPMK->cmd == IW_PMKSA_ADD) {
+ DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_ADD!\n");
+ if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
+ return ret;
+ else
+ ret = true;
+ blInserted = false;
+
+ /* overwrite PMKID */
+ for (j = 0; j < NUM_PMKID_CACHE; j++) {
+ if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
+ /* BSSID is matched, the same AP => rewrite with new PMKID. */
+ DBG_88E("[rtw_wx_set_pmkid] BSSID exists in the PMKList.\n");
+ memcpy(psecuritypriv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
+ psecuritypriv->PMKIDList[j].bUsed = true;
+ psecuritypriv->PMKIDIndex = j+1;
+ blInserted = true;
+ break;
+ }
+ }
+
+ if (!blInserted) {
+ /* Find a new entry */
+ DBG_88E("[rtw_wx_set_pmkid] Use the new entry index = %d for this PMKID.\n",
+ psecuritypriv->PMKIDIndex);
+
+ memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN);
+ memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN);
+
+ psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed = true;
+ psecuritypriv->PMKIDIndex++;
+ if (psecuritypriv->PMKIDIndex == 16)
+ psecuritypriv->PMKIDIndex = 0;
+ }
+ } else if (pPMK->cmd == IW_PMKSA_REMOVE) {
+ DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_REMOVE!\n");
+ ret = true;
+ for (j = 0; j < NUM_PMKID_CACHE; j++) {
+ if (!memcmp(psecuritypriv->PMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) {
+ /* BSSID is matched, the same AP => Remove this PMKID information and reset it. */
+ eth_zero_addr(psecuritypriv->PMKIDList[j].Bssid);
+ psecuritypriv->PMKIDList[j].bUsed = false;
+ break;
+ }
+ }
+ } else if (pPMK->cmd == IW_PMKSA_FLUSH) {
+ DBG_88E("[rtw_wx_set_pmkid] IW_PMKSA_FLUSH!\n");
+ memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
+ psecuritypriv->PMKIDIndex = 0;
+ ret = true;
+ }
+ return ret;
+}
+
+static int rtw_wx_get_sens(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ wrqu->sens.value = 0;
+ wrqu->sens.fixed = 0; /* no auto select */
+ wrqu->sens.disabled = 1;
+ return 0;
+}
+
+static int rtw_wx_get_range(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct iw_range *range = (struct iw_range *)extra;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ u16 val;
+ int i;
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_range. cmd_code =%x\n", info->cmd));
+
+ wrqu->data.length = sizeof(*range);
+ memset(range, 0, sizeof(*range));
+
+ /* Let's try to keep this struct in the same order as in
+ * linux/include/wireless.h
+ */
+
+ /* TODO: See what values we can set, and remove the ones we can't
+ * set, or fill them with some default data.
+ */
+
+ /* ~5 Mb/s real (802.11b) */
+ range->throughput = 5 * 1000 * 1000;
+
+ /* signal level threshold range */
+
+ /* percent values between 0 and 100. */
+ range->max_qual.qual = 100;
+ range->max_qual.level = 100;
+ range->max_qual.noise = 100;
+ range->max_qual.updated = 7; /* Updated all three */
+
+ range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
+ /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
+ range->avg_qual.level = 178; /* -78 dBm */
+ range->avg_qual.noise = 0;
+ range->avg_qual.updated = 7; /* Updated all three */
+
+ range->num_bitrates = RATE_COUNT;
+
+ for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
+ range->bitrate[i] = rtw_rates[i];
+
+ range->min_frag = MIN_FRAG_THRESHOLD;
+ range->max_frag = MAX_FRAG_THRESHOLD;
+
+ range->pm_capa = 0;
+
+ range->we_version_compiled = WIRELESS_EXT;
+ range->we_version_source = 16;
+
+ for (i = 0, val = 0; i < MAX_CHANNEL_NUM; i++) {
+ /* Include only legal frequencies for some countries */
+ if (pmlmeext->channel_set[i].ChannelNum != 0) {
+ range->freq[val].i = pmlmeext->channel_set[i].ChannelNum;
+ range->freq[val].m = rtw_ch2freq(pmlmeext->channel_set[i].ChannelNum) * 100000;
+ range->freq[val].e = 1;
+ val++;
+ }
+
+ if (val == IW_MAX_FREQUENCIES)
+ break;
+ }
+
+ range->num_channels = val;
+ range->num_frequency = val;
+
+/* The following code will proivde the security capability to network manager. */
+/* If the driver doesn't provide this capability to network manager, */
+/* the WPA/WPA2 routers can't be chosen in the network manager. */
+
+/*
+#define IW_SCAN_CAPA_NONE 0x00
+#define IW_SCAN_CAPA_ESSID 0x01
+#define IW_SCAN_CAPA_BSSID 0x02
+#define IW_SCAN_CAPA_CHANNEL 0x04
+#define IW_SCAN_CAPA_MODE 0x08
+#define IW_SCAN_CAPA_RATE 0x10
+#define IW_SCAN_CAPA_TYPE 0x20
+#define IW_SCAN_CAPA_TIME 0x40
+*/
+
+ range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
+ IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+
+ range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE |
+ IW_SCAN_CAPA_BSSID | IW_SCAN_CAPA_CHANNEL |
+ IW_SCAN_CAPA_MODE | IW_SCAN_CAPA_RATE;
+ return 0;
+}
+
+/* set bssid flow */
+/* s1. rtw_set_802_11_infrastructure_mode() */
+/* s2. rtw_set_802_11_authentication_mode() */
+/* s3. set_802_11_encryption_mode() */
+/* s4. rtw_set_802_11_bssid() */
+static int rtw_wx_set_wap(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *awrq,
+ char *extra)
+{
+ uint ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct sockaddr *temp = (struct sockaddr *)awrq;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct list_head *phead;
+ u8 *dst_bssid, *src_bssid;
+ struct __queue *queue = &(pmlmepriv->scanned_queue);
+ struct wlan_network *pnetwork = NULL;
+ enum ndis_802_11_auth_mode authmode;
+
+ if (_FAIL == rtw_pwr_wakeup(padapter)) {
+ ret = -1;
+ goto exit;
+ }
+
+ if (!padapter->bup) {
+ ret = -1;
+ goto exit;
+ }
+
+ if (temp->sa_family != ARPHRD_ETHER) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ authmode = padapter->securitypriv.ndisauthtype;
+ spin_lock_bh(&queue->lock);
+ phead = get_list_head(queue);
+ pmlmepriv->pscanned = phead->next;
+
+ while (phead != pmlmepriv->pscanned) {
+ pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
+
+ pmlmepriv->pscanned = pmlmepriv->pscanned->next;
+
+ dst_bssid = pnetwork->network.MacAddress;
+
+ src_bssid = temp->sa_data;
+
+ if ((!memcmp(dst_bssid, src_bssid, ETH_ALEN))) {
+ if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
+ ret = -1;
+ spin_unlock_bh(&queue->lock);
+ goto exit;
+ }
+
+ break;
+ }
+ }
+ spin_unlock_bh(&queue->lock);
+
+ rtw_set_802_11_authentication_mode(padapter, authmode);
+ if (!rtw_set_802_11_bssid(padapter, temp->sa_data)) {
+ ret = -1;
+ goto exit;
+ }
+
+exit:
+
+ return ret;
+}
+
+static int rtw_wx_get_wap(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
+
+ wrqu->ap_addr.sa_family = ARPHRD_ETHER;
+
+ eth_zero_addr(wrqu->ap_addr.sa_data);
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_wap\n"));
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED) ||
+ check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
+ check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ memcpy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress, ETH_ALEN);
+ else
+ eth_zero_addr(wrqu->ap_addr.sa_data);
+ return 0;
+}
+
+static int rtw_wx_set_mlme(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ u16 reason;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct iw_mlme *mlme = (struct iw_mlme *)extra;
+
+ if (!mlme)
+ return -1;
+
+ DBG_88E("%s\n", __func__);
+
+ reason = mlme->reason_code;
+
+ DBG_88E("%s, cmd =%d, reason =%d\n", __func__, mlme->cmd, reason);
+
+ switch (mlme->cmd) {
+ case IW_MLME_DEAUTH:
+ if (!rtw_set_802_11_disassociate(padapter))
+ ret = -1;
+ break;
+ case IW_MLME_DISASSOC:
+ if (!rtw_set_802_11_disassociate(padapter))
+ ret = -1;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ return ret;
+}
+
+static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *extra)
+{
+ u8 _status = false;
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct ndis_802_11_ssid ssid[RTW_SSID_SCAN_AMOUNT];
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_set_scan\n"));
+
+ if (_FAIL == rtw_pwr_wakeup(padapter)) {
+ ret = -1;
+ goto exit;
+ }
+
+ if (padapter->bDriverStopped) {
+ DBG_88E("bDriverStopped =%d\n", padapter->bDriverStopped);
+ ret = -1;
+ goto exit;
+ }
+
+ if (!padapter->bup) {
+ ret = -1;
+ goto exit;
+ }
+
+ if (!padapter->hw_init_completed) {
+ ret = -1;
+ goto exit;
+ }
+
+ /* When Busy Traffic, driver do not site survey. So driver return success. */
+ /* wpa_supplicant will not issue SIOCSIWSCAN cmd again after scan timeout. */
+ /* modify by thomas 2011-02-22. */
+ if (pmlmepriv->LinkDetectInfo.bBusyTraffic) {
+ indicate_wx_scan_complete_event(padapter);
+ goto exit;
+ }
+
+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING)) {
+ indicate_wx_scan_complete_event(padapter);
+ goto exit;
+ }
+
+/* For the DMP WiFi Display project, the driver won't to scan because */
+/* the pmlmepriv->scan_interval is always equal to 3. */
+/* So, the wpa_supplicant won't find out the WPS SoftAP. */
+
+ memset(ssid, 0, sizeof(struct ndis_802_11_ssid)*RTW_SSID_SCAN_AMOUNT);
+
+ if (wrqu->data.length == sizeof(struct iw_scan_req)) {
+ struct iw_scan_req *req = (struct iw_scan_req *)extra;
+
+ if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
+ int len = min_t(int, req->essid_len,
+ IW_ESSID_MAX_SIZE);
+
+ memcpy(ssid[0].ssid, req->essid, len);
+ ssid[0].ssid_length = len;
+
+ DBG_88E("IW_SCAN_THIS_ESSID, ssid =%s, len =%d\n", req->essid, req->essid_len);
+
+ spin_lock_bh(&pmlmepriv->lock);
+
+ _status = rtw_sitesurvey_cmd(padapter, ssid, 1, NULL, 0);
+
+ spin_unlock_bh(&pmlmepriv->lock);
+ } else if (req->scan_type == IW_SCAN_TYPE_PASSIVE) {
+ DBG_88E("rtw_wx_set_scan, req->scan_type == IW_SCAN_TYPE_PASSIVE\n");
+ }
+ } else {
+ if (wrqu->data.length >= WEXT_CSCAN_HEADER_SIZE &&
+ !memcmp(extra, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
+ int len = wrqu->data.length - WEXT_CSCAN_HEADER_SIZE;
+ char *pos = extra+WEXT_CSCAN_HEADER_SIZE;
+ char section;
+ char sec_len;
+ int ssid_index = 0;
+
+ while (len >= 1) {
+ section = *(pos++);
+ len -= 1;
+
+ switch (section) {
+ case WEXT_CSCAN_SSID_SECTION:
+ if (len < 1) {
+ len = 0;
+ break;
+ }
+ sec_len = *(pos++); len -= 1;
+ if (sec_len > 0 && sec_len <= len) {
+ ssid[ssid_index].ssid_length = sec_len;
+ memcpy(ssid[ssid_index].ssid, pos, ssid[ssid_index].ssid_length);
+ ssid_index++;
+ }
+ pos += sec_len;
+ len -= sec_len;
+ break;
+ case WEXT_CSCAN_TYPE_SECTION:
+ case WEXT_CSCAN_CHANNEL_SECTION:
+ pos += 1;
+ len -= 1;
+ break;
+ case WEXT_CSCAN_PASV_DWELL_SECTION:
+ case WEXT_CSCAN_HOME_DWELL_SECTION:
+ case WEXT_CSCAN_ACTV_DWELL_SECTION:
+ pos += 2;
+ len -= 2;
+ break;
+ default:
+ len = 0; /* stop parsing */
+ }
+ }
+
+ /* it has still some scan parameter to parse, we only do this now... */
+ _status = rtw_set_802_11_bssid_list_scan(padapter, ssid, RTW_SSID_SCAN_AMOUNT);
+ } else {
+ _status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
+ }
+ }
+
+ if (!_status)
+ ret = -1;
+
+exit:
+
+ return ret;
+}
+
+static int rtw_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct list_head *plist, *phead;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct __queue *queue = &(pmlmepriv->scanned_queue);
+ struct wlan_network *pnetwork = NULL;
+ char *ev = extra;
+ char *stop = ev + wrqu->data.length;
+ u32 ret = 0;
+ u32 cnt = 0;
+ u32 wait_for_surveydone;
+ int wait_status;
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_scan\n"));
+ RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, (" Start of Query SIOCGIWSCAN .\n"));
+
+ if (padapter->pwrctrlpriv.brfoffbyhw && padapter->bDriverStopped) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ wait_for_surveydone = 100;
+
+ wait_status = _FW_UNDER_SURVEY | _FW_UNDER_LINKING;
+
+ while (check_fwstate(pmlmepriv, wait_status)) {
+ msleep(30);
+ cnt++;
+ if (cnt > wait_for_surveydone)
+ break;
+ }
+
+ spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
+
+ phead = get_list_head(queue);
+ plist = phead->next;
+
+ while (phead != plist) {
+ if ((stop - ev) < SCAN_ITEM_SIZE) {
+ ret = -E2BIG;
+ break;
+ }
+
+ pnetwork = container_of(plist, struct wlan_network, list);
+
+ /* report network only if the current channel set contains the channel to which this network belongs */
+ if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0)
+ ev = translate_scan(padapter, a, pnetwork, ev, stop);
+
+ plist = plist->next;
+ }
+
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+
+ wrqu->data.length = ev-extra;
+ wrqu->data.flags = 0;
+
+exit:
+ return ret;
+}
+
+/* set ssid flow */
+/* s1. rtw_set_802_11_infrastructure_mode() */
+/* s2. set_802_11_authenticaion_mode() */
+/* s3. set_802_11_encryption_mode() */
+/* s4. rtw_set_802_11_ssid() */
+static int rtw_wx_set_essid(struct net_device *dev,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct __queue *queue = &pmlmepriv->scanned_queue;
+ struct list_head *phead;
+ struct wlan_network *pnetwork = NULL;
+ enum ndis_802_11_auth_mode authmode;
+ struct ndis_802_11_ssid ndis_ssid;
+ u8 *dst_ssid, *src_ssid;
+
+ uint ret = 0, len;
+
+ RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
+ ("+rtw_wx_set_essid: fw_state = 0x%08x\n", get_fwstate(pmlmepriv)));
+ if (_FAIL == rtw_pwr_wakeup(padapter)) {
+ ret = -1;
+ goto exit;
+ }
+
+ if (!padapter->bup) {
+ ret = -1;
+ goto exit;
+ }
+
+ if (wrqu->essid.length > IW_ESSID_MAX_SIZE) {
+ ret = -E2BIG;
+ goto exit;
+ }
+
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+ ret = -1;
+ goto exit;
+ }
+
+ authmode = padapter->securitypriv.ndisauthtype;
+ DBG_88E("=>%s\n", __func__);
+ if (wrqu->essid.flags && wrqu->essid.length) {
+ len = min_t(uint, wrqu->essid.length, IW_ESSID_MAX_SIZE);
+
+ if (wrqu->essid.length != 33)
+ DBG_88E("ssid =%s, len =%d\n", extra, wrqu->essid.length);
+
+ memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
+ ndis_ssid.ssid_length = len;
+ memcpy(ndis_ssid.ssid, extra, len);
+ src_ssid = ndis_ssid.ssid;
+
+ RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("rtw_wx_set_essid: ssid =[%s]\n", src_ssid));
+ spin_lock_bh(&queue->lock);
+ phead = get_list_head(queue);
+ pmlmepriv->pscanned = phead->next;
+
+ while (phead != pmlmepriv->pscanned) {
+ pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
+
+ pmlmepriv->pscanned = pmlmepriv->pscanned->next;
+
+ dst_ssid = pnetwork->network.ssid.ssid;
+
+ RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
+ ("rtw_wx_set_essid: dst_ssid =%s\n",
+ pnetwork->network.ssid.ssid));
+
+ if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.ssid_length)) &&
+ (pnetwork->network.ssid.ssid_length == ndis_ssid.ssid_length)) {
+ RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
+ ("rtw_wx_set_essid: find match, set infra mode\n"));
+
+ if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
+ if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
+ continue;
+ }
+
+ if (!rtw_set_802_11_infrastructure_mode(padapter, pnetwork->network.InfrastructureMode)) {
+ ret = -1;
+ spin_unlock_bh(&queue->lock);
+ goto exit;
+ }
+
+ break;
+ }
+ }
+ spin_unlock_bh(&queue->lock);
+ RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
+ ("set ssid: set_802_11_auth. mode =%d\n", authmode));
+ rtw_set_802_11_authentication_mode(padapter, authmode);
+ if (!rtw_set_802_11_ssid(padapter, &ndis_ssid)) {
+ ret = -1;
+ goto exit;
+ }
+ }
+
+exit:
+ DBG_88E("<=%s, ret %d\n", __func__, ret);
+
+ return ret;
+}
+
+static int rtw_wx_get_essid(struct net_device *dev,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *extra)
+{
+ u32 len;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_wx_get_essid\n"));
+
+ if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
+ (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))) {
+ len = pcur_bss->ssid.ssid_length;
+ memcpy(extra, pcur_bss->ssid.ssid, len);
+ } else {
+ len = 0;
+ *extra = 0;
+ }
+ wrqu->essid.length = len;
+ wrqu->essid.flags = 1;
+
+ return 0;
+}
+
+static int rtw_wx_set_rate(struct net_device *dev,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *extra)
+{
+ int i;
+ u8 datarates[NumRates];
+ u32 target_rate = wrqu->bitrate.value;
+ u32 fixed = wrqu->bitrate.fixed;
+ u32 ratevalue = 0;
+ u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, (" rtw_wx_set_rate\n"));
+ RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("target_rate = %d, fixed = %d\n", target_rate, fixed));
+
+ if (target_rate == -1) {
+ ratevalue = 11;
+ goto set_rate;
+ }
+ target_rate = target_rate/100000;
+
+ switch (target_rate) {
+ case 10:
+ ratevalue = 0;
+ break;
+ case 20:
+ ratevalue = 1;
+ break;
+ case 55:
+ ratevalue = 2;
+ break;
+ case 60:
+ ratevalue = 3;
+ break;
+ case 90:
+ ratevalue = 4;
+ break;
+ case 110:
+ ratevalue = 5;
+ break;
+ case 120:
+ ratevalue = 6;
+ break;
+ case 180:
+ ratevalue = 7;
+ break;
+ case 240:
+ ratevalue = 8;
+ break;
+ case 360:
+ ratevalue = 9;
+ break;
+ case 480:
+ ratevalue = 10;
+ break;
+ case 540:
+ ratevalue = 11;
+ break;
+ default:
+ ratevalue = 11;
+ break;
+ }
+
+set_rate:
+
+ for (i = 0; i < NumRates; i++) {
+ if (ratevalue == mpdatarate[i]) {
+ datarates[i] = mpdatarate[i];
+ if (fixed == 0)
+ break;
+ } else {
+ datarates[i] = 0xff;
+ }
+
+ RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_, ("datarate_inx =%d\n", datarates[i]));
+ }
+
+ return 0;
+}
+
+static int rtw_wx_get_rate(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ u16 max_rate = 0;
+
+ max_rate = rtw_get_cur_max_rate((struct adapter *)rtw_netdev_priv(dev));
+
+ if (max_rate == 0)
+ return -EPERM;
+
+ wrqu->bitrate.fixed = 0; /* no auto select */
+ wrqu->bitrate.value = max_rate * 100000;
+
+ return 0;
+}
+
+static int rtw_wx_set_rts(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+
+ if (wrqu->rts.disabled) {
+ padapter->registrypriv.rts_thresh = 2347;
+ } else {
+ if (wrqu->rts.value < 0 ||
+ wrqu->rts.value > 2347)
+ return -EINVAL;
+
+ padapter->registrypriv.rts_thresh = wrqu->rts.value;
+ }
+
+ DBG_88E("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh);
+
+ return 0;
+}
+
+static int rtw_wx_get_rts(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+
+ DBG_88E("%s, rts_thresh =%d\n", __func__, padapter->registrypriv.rts_thresh);
+
+ wrqu->rts.value = padapter->registrypriv.rts_thresh;
+ wrqu->rts.fixed = 0; /* no auto select */
+ /* wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); */
+
+ return 0;
+}
+
+static int rtw_wx_set_frag(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+
+ if (wrqu->frag.disabled) {
+ padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
+ } else {
+ if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
+ wrqu->frag.value > MAX_FRAG_THRESHOLD)
+ return -EINVAL;
+
+ padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
+ }
+
+ DBG_88E("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len);
+
+ return 0;
+}
+
+static int rtw_wx_get_frag(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+
+ DBG_88E("%s, frag_len =%d\n", __func__, padapter->xmitpriv.frag_len);
+
+ wrqu->frag.value = padapter->xmitpriv.frag_len;
+ wrqu->frag.fixed = 0; /* no auto select */
+
+ return 0;
+}
+
+static int rtw_wx_get_retry(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ wrqu->retry.value = 7;
+ wrqu->retry.fixed = 0; /* no auto select */
+ wrqu->retry.disabled = 1;
+
+ return 0;
+}
+
+static int rtw_wx_set_enc(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *keybuf)
+{
+ u32 key, ret = 0;
+ u32 keyindex_provided;
+ struct ndis_802_11_wep wep;
+ enum ndis_802_11_auth_mode authmode;
+
+ struct iw_point *erq = &(wrqu->encoding);
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
+
+ DBG_88E("+rtw_wx_set_enc, flags = 0x%x\n", erq->flags);
+
+ memset(&wep, 0, sizeof(struct ndis_802_11_wep));
+
+ key = erq->flags & IW_ENCODE_INDEX;
+
+ if (erq->flags & IW_ENCODE_DISABLED) {
+ DBG_88E("EncryptionDisabled\n");
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
+ padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
+ padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
+ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
+ authmode = Ndis802_11AuthModeOpen;
+ padapter->securitypriv.ndisauthtype = authmode;
+
+ goto exit;
+ }
+
+ if (key) {
+ if (key > WEP_KEYS)
+ return -EINVAL;
+ key--;
+ keyindex_provided = 1;
+ } else {
+ keyindex_provided = 0;
+ key = padapter->securitypriv.dot11PrivacyKeyIndex;
+ DBG_88E("rtw_wx_set_enc, key =%d\n", key);
+ }
+
+ /* set authentication mode */
+ if (erq->flags & IW_ENCODE_OPEN) {
+ DBG_88E("rtw_wx_set_enc():IW_ENCODE_OPEN\n");
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
+ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
+ padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
+ padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
+ authmode = Ndis802_11AuthModeOpen;
+ padapter->securitypriv.ndisauthtype = authmode;
+ } else if (erq->flags & IW_ENCODE_RESTRICTED) {
+ DBG_88E("rtw_wx_set_enc():IW_ENCODE_RESTRICTED\n");
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
+ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
+ padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
+ padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
+ authmode = Ndis802_11AuthModeShared;
+ padapter->securitypriv.ndisauthtype = authmode;
+ } else {
+ DBG_88E("rtw_wx_set_enc():erq->flags = 0x%x\n", erq->flags);
+
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;/* Ndis802_11EncryptionDisabled; */
+ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
+ padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
+ padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
+ authmode = Ndis802_11AuthModeOpen;
+ padapter->securitypriv.ndisauthtype = authmode;
+ }
+
+ wep.KeyIndex = key;
+ if (erq->length > 0) {
+ wep.KeyLength = erq->length <= 5 ? 5 : 13;
+
+ wep.Length = wep.KeyLength + offsetof(struct ndis_802_11_wep, KeyMaterial);
+ } else {
+ wep.KeyLength = 0;
+
+ if (keyindex_provided == 1) {
+ /* set key_id only, no given KeyMaterial(erq->length == 0). */
+ padapter->securitypriv.dot11PrivacyKeyIndex = key;
+
+ DBG_88E("(keyindex_provided == 1), keyid =%d, key_len =%d\n", key, padapter->securitypriv.dot11DefKeylen[key]);
+
+ switch (padapter->securitypriv.dot11DefKeylen[key]) {
+ case 5:
+ padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
+ break;
+ case 13:
+ padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
+ break;
+ default:
+ padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
+ break;
+ }
+
+ goto exit;
+ }
+ }
+
+ wep.KeyIndex |= 0x80000000;
+
+ memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
+
+ if (!rtw_set_802_11_add_wep(padapter, &wep)) {
+ if (rf_on == pwrpriv->rf_pwrstate)
+ ret = -EOPNOTSUPP;
+ goto exit;
+ }
+
+exit:
+ return ret;
+}
+
+static int rtw_wx_get_enc(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *keybuf)
+{
+ uint key;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct iw_point *erq = &(wrqu->encoding);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+ if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
+ if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
+ erq->length = 0;
+ erq->flags |= IW_ENCODE_DISABLED;
+ return 0;
+ }
+ }
+
+ key = erq->flags & IW_ENCODE_INDEX;
+
+ if (key) {
+ if (key > WEP_KEYS)
+ return -EINVAL;
+ key--;
+ } else {
+ key = padapter->securitypriv.dot11PrivacyKeyIndex;
+ }
+
+ erq->flags = key + 1;
+
+ switch (padapter->securitypriv.ndisencryptstatus) {
+ case Ndis802_11EncryptionNotSupported:
+ case Ndis802_11EncryptionDisabled:
+ erq->length = 0;
+ erq->flags |= IW_ENCODE_DISABLED;
+ break;
+ case Ndis802_11Encryption1Enabled:
+ erq->length = padapter->securitypriv.dot11DefKeylen[key];
+ if (erq->length) {
+ memcpy(keybuf, padapter->securitypriv.dot11DefKey[key].skey, padapter->securitypriv.dot11DefKeylen[key]);
+
+ erq->flags |= IW_ENCODE_ENABLED;
+
+ if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeOpen)
+ erq->flags |= IW_ENCODE_OPEN;
+ else if (padapter->securitypriv.ndisauthtype == Ndis802_11AuthModeShared)
+ erq->flags |= IW_ENCODE_RESTRICTED;
+ } else {
+ erq->length = 0;
+ erq->flags |= IW_ENCODE_DISABLED;
+ }
+ break;
+ case Ndis802_11Encryption2Enabled:
+ case Ndis802_11Encryption3Enabled:
+ erq->length = 16;
+ erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN | IW_ENCODE_NOKEY);
+ break;
+ default:
+ erq->length = 0;
+ erq->flags |= IW_ENCODE_DISABLED;
+ break;
+ }
+
+ return 0;
+}
+
+static int rtw_wx_get_power(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ wrqu->power.value = 0;
+ wrqu->power.fixed = 0; /* no auto select */
+ wrqu->power.disabled = 1;
+
+ return 0;
+}
+
+static int rtw_wx_set_gen_ie(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+
+ return rtw_set_wpa_ie(padapter, extra, wrqu->data.length);
+}
+
+static int rtw_wx_set_auth(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct iw_param *param = (struct iw_param *)&(wrqu->param);
+ int ret = 0;
+
+ switch (param->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_WPA_VERSION:
+ break;
+ case IW_AUTH_CIPHER_PAIRWISE:
+
+ break;
+ case IW_AUTH_CIPHER_GROUP:
+
+ break;
+ case IW_AUTH_KEY_MGMT:
+ /*
+ * ??? does not use these parameters
+ */
+ break;
+ case IW_AUTH_TKIP_COUNTERMEASURES:
+ if (param->value) {
+ /* wpa_supplicant is enabling the tkip countermeasure. */
+ padapter->securitypriv.btkip_countermeasure = true;
+ } else {
+ /* wpa_supplicant is disabling the tkip countermeasure. */
+ padapter->securitypriv.btkip_countermeasure = false;
+ }
+ break;
+ case IW_AUTH_DROP_UNENCRYPTED:
+ /* HACK:
+ *
+ * wpa_supplicant calls set_wpa_enabled when the driver
+ * is loaded and unloaded, regardless of if WPA is being
+ * used. No other calls are made which can be used to
+ * determine if encryption will be used or not prior to
+ * association being expected. If encryption is not being
+ * used, drop_unencrypted is set to false, else true -- we
+ * can use this to determine if the CAP_PRIVACY_ON bit should
+ * be set.
+ */
+
+ if (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption1Enabled)
+ break;/* it means init value, or using wep, ndisencryptstatus = Ndis802_11Encryption1Enabled, */
+ /* then it needn't reset it; */
+
+ if (param->value) {
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
+ padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
+ padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
+ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
+ padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
+ }
+
+ break;
+ case IW_AUTH_80211_AUTH_ALG:
+ /*
+ * It's the starting point of a link layer connection using wpa_supplicant
+ */
+ if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
+ LeaveAllPowerSaveMode(padapter);
+ rtw_disassoc_cmd(padapter, 500, false);
+ DBG_88E("%s...call rtw_indicate_disconnect\n ", __func__);
+ rtw_indicate_disconnect(padapter);
+ rtw_free_assoc_resources(padapter);
+ }
+ ret = wpa_set_auth_algs(dev, (u32)param->value);
+ break;
+ case IW_AUTH_WPA_ENABLED:
+ break;
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ break;
+ case IW_AUTH_PRIVACY_INVOKED:
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return ret;
+}
+
+static int rtw_wx_set_enc_ext(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ char *alg_name;
+ u32 param_len;
+ struct ieee_param *param = NULL;
+ struct iw_point *pencoding = &wrqu->encoding;
+ struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
+ int ret = 0;
+
+ param_len = sizeof(struct ieee_param) + pext->key_len;
+ param = (struct ieee_param *)rtw_malloc(param_len);
+ if (!param)
+ return -1;
+
+ memset(param, 0, param_len);
+
+ param->cmd = IEEE_CMD_SET_ENCRYPTION;
+ eth_broadcast_addr(param->sta_addr);
+
+ switch (pext->alg) {
+ case IW_ENCODE_ALG_NONE:
+ /* todo: remove key */
+ /* remove = 1; */
+ alg_name = "none";
+ break;
+ case IW_ENCODE_ALG_WEP:
+ alg_name = "WEP";
+ break;
+ case IW_ENCODE_ALG_TKIP:
+ alg_name = "TKIP";
+ break;
+ case IW_ENCODE_ALG_CCMP:
+ alg_name = "CCMP";
+ break;
+ default:
+ ret = -1;
+ goto exit;
+ }
+
+ strlcpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
+
+ if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+ param->u.crypt.set_tx = 1;
+
+ /* cliW: WEP does not have group key
+ * just not checking GROUP key setting
+ */
+ if ((pext->alg != IW_ENCODE_ALG_WEP) &&
+ (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY))
+ param->u.crypt.set_tx = 0;
+
+ param->u.crypt.idx = (pencoding->flags&0x00FF) - 1;
+
+ if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
+ memcpy(param->u.crypt.seq, pext->rx_seq, 8);
+
+ if (pext->key_len) {
+ param->u.crypt.key_len = pext->key_len;
+ memcpy(param->u.crypt.key, pext + 1, pext->key_len);
+ }
+
+ ret = wpa_set_encryption(dev, param, param_len);
+
+exit:
+ kfree(param);
+ return ret;
+}
+
+static int rtw_wx_get_nick(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ if (extra) {
+ wrqu->data.length = 14;
+ wrqu->data.flags = 1;
+ memcpy(extra, "<WIFI@REALTEK>", 14);
+ }
+
+ /* dump debug info here */
+ return 0;
+}
+
+static int dummy(struct net_device *dev, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b)
+{
+ return -1;
+}
+
+static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
+{
+ uint ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+
+ switch (name) {
+ case IEEE_PARAM_WPA_ENABLED:
+ padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; /* 802.1x */
+ switch ((value)&0xff) {
+ case 1: /* WPA */
+ padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
+ break;
+ case 2: /* WPA2 */
+ padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
+ break;
+ }
+ RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
+ ("wpa_set_param:padapter->securitypriv.ndisauthtype =%d\n", padapter->securitypriv.ndisauthtype));
+ break;
+ case IEEE_PARAM_TKIP_COUNTERMEASURES:
+ break;
+ case IEEE_PARAM_DROP_UNENCRYPTED: {
+ /* HACK:
+ *
+ * wpa_supplicant calls set_wpa_enabled when the driver
+ * is loaded and unloaded, regardless of if WPA is being
+ * used. No other calls are made which can be used to
+ * determine if encryption will be used or not prior to
+ * association being expected. If encryption is not being
+ * used, drop_unencrypted is set to false, else true -- we
+ * can use this to determine if the CAP_PRIVACY_ON bit should
+ * be set.
+ */
+
+ break;
+ }
+ case IEEE_PARAM_PRIVACY_INVOKED:
+ break;
+
+ case IEEE_PARAM_AUTH_ALGS:
+ ret = wpa_set_auth_algs(dev, value);
+ break;
+ case IEEE_PARAM_IEEE_802_1X:
+ break;
+ case IEEE_PARAM_WPAX_SELECT:
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+ return ret;
+}
+
+static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+
+ switch (command) {
+ case IEEE_MLME_STA_DEAUTH:
+ if (!rtw_set_802_11_disassociate(padapter))
+ ret = -1;
+ break;
+ case IEEE_MLME_STA_DISASSOC:
+ if (!rtw_set_802_11_disassociate(padapter))
+ ret = -1;
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
+static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
+{
+ struct ieee_param *param;
+ uint ret = 0;
+
+ if (!p->pointer || p->length != sizeof(struct ieee_param)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ param = (struct ieee_param *)rtw_malloc(p->length);
+ if (!param) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (copy_from_user(param, p->pointer, p->length)) {
+ kfree(param);
+ ret = -EFAULT;
+ goto out;
+ }
+
+ switch (param->cmd) {
+ case IEEE_CMD_SET_WPA_PARAM:
+ ret = wpa_set_param(dev, param->u.wpa_param.name, param->u.wpa_param.value);
+ break;
+
+ case IEEE_CMD_SET_WPA_IE:
+ ret = rtw_set_wpa_ie((struct adapter *)rtw_netdev_priv(dev),
+ (char *)param->u.wpa_ie.data, (u16)param->u.wpa_ie.len);
+ break;
+
+ case IEEE_CMD_SET_ENCRYPTION:
+ ret = wpa_set_encryption(dev, param, p->length);
+ break;
+
+ case IEEE_CMD_MLME:
+ ret = wpa_mlme(dev, param->u.mlme.command, param->u.mlme.reason_code);
+ break;
+
+ default:
+ DBG_88E("Unknown WPA supplicant request: %d\n", param->cmd);
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ if (ret == 0 && copy_to_user(p->pointer, param, p->length))
+ ret = -EFAULT;
+
+ kfree(param);
+
+out:
+
+ return ret;
+}
+
+#ifdef CPTCFG_88EU_AP_MODE
+static u8 set_pairwise_key(struct adapter *padapter, struct sta_info *psta)
+{
+ struct cmd_obj *ph2c;
+ struct set_stakey_parm *psetstakey_para;
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+ u8 res = _SUCCESS;
+
+ ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
+ if (!psetstakey_para) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
+
+ psetstakey_para->algorithm = (u8)psta->dot118021XPrivacy;
+
+ memcpy(psetstakey_para->addr, psta->hwaddr, ETH_ALEN);
+
+ memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);
+
+ res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+
+exit:
+
+ return res;
+}
+
+static int set_group_key(struct adapter *padapter, u8 *key, u8 alg, int keyid)
+{
+ u8 keylen;
+ struct cmd_obj *pcmd;
+ struct setkey_parm *psetkeyparm;
+ struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
+ int res = _SUCCESS;
+
+ DBG_88E("%s\n", __func__);
+
+ pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
+ if (!pcmd) {
+ res = _FAIL;
+ goto exit;
+ }
+ psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
+ if (!psetkeyparm) {
+ kfree(pcmd);
+ res = _FAIL;
+ goto exit;
+ }
+
+ psetkeyparm->keyid = (u8)keyid;
+
+ psetkeyparm->algorithm = alg;
+
+ psetkeyparm->set_tx = 1;
+
+ switch (alg) {
+ case _WEP40_:
+ keylen = 5;
+ break;
+ case _WEP104_:
+ keylen = 13;
+ break;
+ case _TKIP_:
+ case _TKIP_WTMIC_:
+ case _AES_:
+ default:
+ keylen = 16;
+ }
+
+ memcpy(&(psetkeyparm->key[0]), key, keylen);
+
+ pcmd->cmdcode = _SetKey_CMD_;
+ pcmd->parmbuf = (u8 *)psetkeyparm;
+ pcmd->cmdsz = (sizeof(struct setkey_parm));
+ pcmd->rsp = NULL;
+ pcmd->rspsz = 0;
+
+ INIT_LIST_HEAD(&pcmd->list);
+
+ res = rtw_enqueue_cmd(pcmdpriv, pcmd);
+
+exit:
+
+ return res;
+}
+
+static int set_wep_key(struct adapter *padapter, u8 *key, u8 keylen, int keyid)
+{
+ u8 alg;
+
+ switch (keylen) {
+ case 5:
+ alg = _WEP40_;
+ break;
+ case 13:
+ alg = _WEP104_;
+ break;
+ default:
+ alg = _NO_PRIVACY_;
+ }
+
+ return set_group_key(padapter, key, alg, keyid);
+}
+
+static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
+{
+ int ret = 0;
+ u32 wep_key_idx, wep_key_len, wep_total_len;
+ struct ndis_802_11_wep *pwep = NULL;
+ struct sta_info *psta = NULL, *pbcmc_sta = NULL;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct security_priv *psecuritypriv = &(padapter->securitypriv);
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ DBG_88E("%s\n", __func__);
+ param->u.crypt.err = 0;
+ param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
+ if (param_len != sizeof(struct ieee_param) + param->u.crypt.key_len) {
+ ret = -EINVAL;
+ goto exit;
+ }
+ if (is_broadcast_ether_addr(param->sta_addr)) {
+ if (param->u.crypt.idx >= WEP_KEYS) {
+ ret = -EINVAL;
+ goto exit;
+ }
+ } else {
+ psta = rtw_get_stainfo(pstapriv, param->sta_addr);
+ if (!psta) {
+ DBG_88E("rtw_set_encryption(), sta has already been removed or never been added\n");
+ goto exit;
+ }
+ }
+
+ if (strcmp(param->u.crypt.alg, "none") == 0 && (!psta)) {
+ /* todo:clear default encryption keys */
+
+ DBG_88E("clear default encryption keys, keyid =%d\n", param->u.crypt.idx);
+ goto exit;
+ }
+ if (strcmp(param->u.crypt.alg, "WEP") == 0 && (!psta)) {
+ DBG_88E("r871x_set_encryption, crypt.alg = WEP\n");
+ wep_key_idx = param->u.crypt.idx;
+ wep_key_len = param->u.crypt.key_len;
+ DBG_88E("r871x_set_encryption, wep_key_idx=%d, len=%d\n", wep_key_idx, wep_key_len);
+ if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ if (wep_key_len > 0) {
+ wep_key_len = wep_key_len <= 5 ? 5 : 13;
+ wep_total_len = wep_key_len + offsetof(struct ndis_802_11_wep, KeyMaterial);
+ pwep = (struct ndis_802_11_wep *)rtw_malloc(wep_total_len);
+ if (!pwep) {
+ DBG_88E(" r871x_set_encryption: pwep allocate fail !!!\n");
+ goto exit;
+ }
+
+ memset(pwep, 0, wep_total_len);
+
+ pwep->KeyLength = wep_key_len;
+ pwep->Length = wep_total_len;
+ }
+
+ pwep->KeyIndex = wep_key_idx;
+
+ memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
+
+ if (param->u.crypt.set_tx) {
+ DBG_88E("wep, set_tx = 1\n");
+
+ psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
+ psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
+ psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+
+ if (pwep->KeyLength == 13) {
+ psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
+ psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+ }
+
+ psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
+
+ memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
+
+ psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
+
+ set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
+ } else {
+ DBG_88E("wep, set_tx = 0\n");
+
+ /* don't update "psecuritypriv->dot11PrivacyAlgrthm" and */
+ /* psecuritypriv->dot11PrivacyKeyIndex = keyid", but can rtw_set_key to cam */
+
+ memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), pwep->KeyMaterial, pwep->KeyLength);
+
+ psecuritypriv->dot11DefKeylen[wep_key_idx] = pwep->KeyLength;
+
+ set_wep_key(padapter, pwep->KeyMaterial, pwep->KeyLength, wep_key_idx);
+ }
+
+ goto exit;
+ }
+
+ if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /* group key */
+ if (param->u.crypt.set_tx == 1) {
+ if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+ DBG_88E("%s, set group_key, WEP\n", __func__);
+
+ memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+ param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
+
+ psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+ if (param->u.crypt.key_len == 13)
+ psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+ } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+ DBG_88E("%s, set group_key, TKIP\n", __func__);
+ psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
+ memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+ param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
+ /* set mic key */
+ memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
+ memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
+
+ psecuritypriv->busetkipkey = true;
+ } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+ DBG_88E("%s, set group_key, CCMP\n", __func__);
+ psecuritypriv->dot118021XGrpPrivacy = _AES_;
+ memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+ param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
+ } else {
+ DBG_88E("%s, set group_key, none\n", __func__);
+ psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+ }
+ psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
+ psecuritypriv->binstallGrpkey = true;
+ psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/* */
+ set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
+ pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+ if (pbcmc_sta) {
+ pbcmc_sta->ieee8021x_blocked = false;
+ pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
+ }
+ }
+ goto exit;
+ }
+
+ if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /* psk/802_1x */
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+ if (param->u.crypt.set_tx == 1) {
+ memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
+
+ if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+ DBG_88E("%s, set pairwise key, WEP\n", __func__);
+
+ psta->dot118021XPrivacy = _WEP40_;
+ if (param->u.crypt.key_len == 13)
+ psta->dot118021XPrivacy = _WEP104_;
+ } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+ DBG_88E("%s, set pairwise key, TKIP\n", __func__);
+
+ psta->dot118021XPrivacy = _TKIP_;
+
+ /* set mic key */
+ memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
+ memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
+
+ psecuritypriv->busetkipkey = true;
+ } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+ DBG_88E("%s, set pairwise key, CCMP\n", __func__);
+
+ psta->dot118021XPrivacy = _AES_;
+ } else {
+ DBG_88E("%s, set pairwise key, none\n", __func__);
+
+ psta->dot118021XPrivacy = _NO_PRIVACY_;
+ }
+
+ set_pairwise_key(padapter, psta);
+
+ psta->ieee8021x_blocked = false;
+ } else { /* group key??? */
+ if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+ memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+ param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
+ psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+ if (param->u.crypt.key_len == 13)
+ psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+ } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+ psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
+
+ memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+ param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
+
+ /* set mic key */
+ memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
+ memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
+
+ psecuritypriv->busetkipkey = true;
+ } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+ psecuritypriv->dot118021XGrpPrivacy = _AES_;
+
+ memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
+ param->u.crypt.key, min_t(u16, param->u.crypt.key_len, 16));
+ } else {
+ psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+ }
+
+ psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
+
+ psecuritypriv->binstallGrpkey = true;
+
+ psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/* */
+
+ set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
+
+ pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+ if (pbcmc_sta) {
+ pbcmc_sta->ieee8021x_blocked = false;
+ pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
+ }
+ }
+ }
+ }
+
+exit:
+
+ kfree(pwep);
+
+ return ret;
+}
+
+static int rtw_set_beacon(struct net_device *dev, struct ieee_param *param, int len)
+{
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ unsigned char *pbuf = param->u.bcn_ie.buf;
+
+ DBG_88E("%s, len =%d\n", __func__, len);
+
+ if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ return -EINVAL;
+
+ memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2);
+
+ if ((pstapriv->max_num_sta > NUM_STA) || (pstapriv->max_num_sta <= 0))
+ pstapriv->max_num_sta = NUM_STA;
+
+ if (rtw_check_beacon_data(padapter, pbuf, (len-12-2)) == _SUCCESS)/* 12 = param header, 2:no packed */
+ ret = 0;
+ else
+ ret = -EINVAL;
+
+ return ret;
+}
+
+static int rtw_hostapd_sta_flush(struct net_device *dev)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+
+ DBG_88E("%s\n", __func__);
+
+ flush_all_cam_entry(padapter); /* clear CAM */
+
+ return rtw_sta_flush(padapter);
+}
+
+static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
+{
+ int ret = 0;
+ struct sta_info *psta = NULL;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ DBG_88E("rtw_add_sta(aid =%d) =%pM\n", param->u.add_sta.aid, (param->sta_addr));
+
+ if (!check_fwstate(pmlmepriv, (_FW_LINKED|WIFI_AP_STATE)))
+ return -EINVAL;
+
+ if (is_broadcast_ether_addr(param->sta_addr))
+ return -EINVAL;
+
+ psta = rtw_get_stainfo(pstapriv, param->sta_addr);
+ if (psta) {
+ int flags = param->u.add_sta.flags;
+
+ psta->aid = param->u.add_sta.aid;/* aid = 1~2007 */
+
+ memcpy(psta->bssrateset, param->u.add_sta.tx_supp_rates, 16);
+
+ /* check wmm cap. */
+ if (WLAN_STA_WME&flags)
+ psta->qos_option = 1;
+ else
+ psta->qos_option = 0;
+
+ if (pmlmepriv->qospriv.qos_option == 0)
+ psta->qos_option = 0;
+
+ /* chec 802.11n ht cap. */
+ if (WLAN_STA_HT&flags) {
+ psta->htpriv.ht_option = true;
+ psta->qos_option = 1;
+ memcpy(&psta->htpriv.ht_cap, &param->u.add_sta.ht_cap,
+ sizeof(struct ieee80211_ht_cap));
+ } else {
+ psta->htpriv.ht_option = false;
+ }
+
+ if (!pmlmepriv->htpriv.ht_option)
+ psta->htpriv.ht_option = false;
+
+ update_sta_info_apmode(padapter, psta);
+ } else {
+ ret = -ENOMEM;
+ }
+
+ return ret;
+}
+
+static int rtw_del_sta(struct net_device *dev, struct ieee_param *param)
+{
+ struct sta_info *psta = NULL;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ int updated = 0;
+
+ DBG_88E("rtw_del_sta =%pM\n", (param->sta_addr));
+
+ if (!check_fwstate(pmlmepriv, _FW_LINKED | WIFI_AP_STATE))
+ return -EINVAL;
+
+ if (is_broadcast_ether_addr(param->sta_addr))
+ return -EINVAL;
+
+ psta = rtw_get_stainfo(pstapriv, param->sta_addr);
+ if (psta) {
+ spin_lock_bh(&pstapriv->asoc_list_lock);
+ if (!list_empty(&psta->asoc_list)) {
+ list_del_init(&psta->asoc_list);
+ pstapriv->asoc_list_cnt--;
+ updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
+ }
+ spin_unlock_bh(&pstapriv->asoc_list_lock);
+ associated_clients_update(padapter, updated);
+ psta = NULL;
+ } else {
+ DBG_88E("rtw_del_sta(), sta has already been removed or never been added\n");
+ }
+
+ return 0;
+}
+
+static int rtw_ioctl_get_sta_data(struct net_device *dev, struct ieee_param *param, int len)
+{
+ int ret = 0;
+ struct sta_info *psta = NULL;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct ieee_param_ex *param_ex = (struct ieee_param_ex *)param;
+ struct sta_data *psta_data = (struct sta_data *)param_ex->data;
+
+ DBG_88E("rtw_ioctl_get_sta_info, sta_addr: %pM\n", (param_ex->sta_addr));
+
+ if (!check_fwstate(pmlmepriv, _FW_LINKED | WIFI_AP_STATE))
+ return -EINVAL;
+
+ if (is_broadcast_ether_addr(param_ex->sta_addr))
+ return -EINVAL;
+
+ psta = rtw_get_stainfo(pstapriv, param_ex->sta_addr);
+ if (psta) {
+ psta_data->aid = (u16)psta->aid;
+ psta_data->capability = psta->capability;
+ psta_data->flags = psta->flags;
+
+/*
+ nonerp_set : BIT(0)
+ no_short_slot_time_set : BIT(1)
+ no_short_preamble_set : BIT(2)
+ no_ht_gf_set : BIT(3)
+ no_ht_set : BIT(4)
+ ht_20mhz_set : BIT(5)
+*/
+
+ psta_data->sta_set = ((psta->nonerp_set) |
+ (psta->no_short_slot_time_set << 1) |
+ (psta->no_short_preamble_set << 2) |
+ (psta->no_ht_gf_set << 3) |
+ (psta->no_ht_set << 4) |
+ (psta->ht_20mhz_set << 5));
+ psta_data->tx_supp_rates_len = psta->bssratelen;
+ memcpy(psta_data->tx_supp_rates, psta->bssrateset, psta->bssratelen);
+ memcpy(&psta_data->ht_cap,
+ &psta->htpriv.ht_cap, sizeof(struct ieee80211_ht_cap));
+ psta_data->rx_pkts = psta->sta_stats.rx_data_pkts;
+ psta_data->rx_bytes = psta->sta_stats.rx_bytes;
+ psta_data->rx_drops = psta->sta_stats.rx_drops;
+ psta_data->tx_pkts = psta->sta_stats.tx_pkts;
+ psta_data->tx_bytes = psta->sta_stats.tx_bytes;
+ psta_data->tx_drops = psta->sta_stats.tx_drops;
+ } else {
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static int rtw_get_sta_wpaie(struct net_device *dev, struct ieee_param *param)
+{
+ int ret = 0;
+ struct sta_info *psta = NULL;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ DBG_88E("rtw_get_sta_wpaie, sta_addr: %pM\n", (param->sta_addr));
+
+ if (!check_fwstate(pmlmepriv, _FW_LINKED | WIFI_AP_STATE))
+ return -EINVAL;
+
+ if (is_broadcast_ether_addr(param->sta_addr))
+ return -EINVAL;
+
+ psta = rtw_get_stainfo(pstapriv, param->sta_addr);
+ if (psta) {
+ if (psta->wpa_ie[0] == WLAN_EID_RSN ||
+ psta->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {
+ int wpa_ie_len;
+ int copy_len;
+
+ wpa_ie_len = psta->wpa_ie[1];
+ copy_len = min_t(int, wpa_ie_len + 2, sizeof(psta->wpa_ie));
+ param->u.wpa_ie.len = copy_len;
+ memcpy(param->u.wpa_ie.reserved, psta->wpa_ie, copy_len);
+ } else {
+ DBG_88E("sta's wpa_ie is NONE\n");
+ }
+ } else {
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static int rtw_set_wps_beacon(struct net_device *dev, struct ieee_param *param, int len)
+{
+ unsigned char wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ int ie_len;
+
+ DBG_88E("%s, len =%d\n", __func__, len);
+
+ if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ return -EINVAL;
+
+ ie_len = len-12-2;/* 12 = param header, 2:no packed */
+
+ kfree(pmlmepriv->wps_beacon_ie);
+ pmlmepriv->wps_beacon_ie = NULL;
+
+ if (ie_len > 0) {
+ pmlmepriv->wps_beacon_ie = rtw_malloc(ie_len);
+ pmlmepriv->wps_beacon_ie_len = ie_len;
+ if (!pmlmepriv->wps_beacon_ie) {
+ DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+
+ memcpy(pmlmepriv->wps_beacon_ie, param->u.bcn_ie.buf, ie_len);
+
+ update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, true);
+
+ pmlmeext->bstart_bss = true;
+ }
+
+ return 0;
+}
+
+static int rtw_set_wps_probe_resp(struct net_device *dev, struct ieee_param *param, int len)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ int ie_len;
+
+ DBG_88E("%s, len =%d\n", __func__, len);
+
+ if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ return -EINVAL;
+
+ ie_len = len-12-2;/* 12 = param header, 2:no packed */
+
+ kfree(pmlmepriv->wps_probe_resp_ie);
+ pmlmepriv->wps_probe_resp_ie = NULL;
+
+ if (ie_len > 0) {
+ pmlmepriv->wps_probe_resp_ie = rtw_malloc(ie_len);
+ pmlmepriv->wps_probe_resp_ie_len = ie_len;
+ if (!pmlmepriv->wps_probe_resp_ie) {
+ DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+ memcpy(pmlmepriv->wps_probe_resp_ie, param->u.bcn_ie.buf, ie_len);
+ }
+
+ return 0;
+}
+
+static int rtw_set_wps_assoc_resp(struct net_device *dev, struct ieee_param *param, int len)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ int ie_len;
+
+ DBG_88E("%s, len =%d\n", __func__, len);
+
+ if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ return -EINVAL;
+
+ ie_len = len-12-2;/* 12 = param header, 2:no packed */
+
+ kfree(pmlmepriv->wps_assoc_resp_ie);
+ pmlmepriv->wps_assoc_resp_ie = NULL;
+
+ if (ie_len > 0) {
+ pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
+ pmlmepriv->wps_assoc_resp_ie_len = ie_len;
+ if (!pmlmepriv->wps_assoc_resp_ie) {
+ DBG_88E("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+
+ memcpy(pmlmepriv->wps_assoc_resp_ie, param->u.bcn_ie.buf, ie_len);
+ }
+
+ return 0;
+}
+
+static int rtw_set_hidden_ssid(struct net_device *dev, struct ieee_param *param, int len)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+
+ u8 value;
+
+ if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ return -EINVAL;
+
+ if (param->u.wpa_param.name != 0) /* dummy test... */
+ DBG_88E("%s name(%u) != 0\n", __func__, param->u.wpa_param.name);
+ value = param->u.wpa_param.value;
+
+ /* use the same definition of hostapd's ignore_broadcast_ssid */
+ if (value != 1 && value != 2)
+ value = 0;
+ DBG_88E("%s value(%u)\n", __func__, value);
+ pmlmeinfo->hidden_ssid_mode = value;
+ return 0;
+}
+
+static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+ if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ return -EINVAL;
+
+ if (is_broadcast_ether_addr(param->sta_addr))
+ return -EINVAL;
+
+ return rtw_acl_remove_sta(padapter, param->sta_addr);
+}
+
+static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+ if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ return -EINVAL;
+
+ if (is_broadcast_ether_addr(param->sta_addr))
+ return -EINVAL;
+
+ return rtw_acl_add_sta(padapter, param->sta_addr);
+}
+
+static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+ if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
+ return -EINVAL;
+
+ rtw_set_macaddr_acl(padapter, param->u.mlme.command);
+
+ return 0;
+}
+
+static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
+{
+ struct ieee_param *param;
+ int ret = 0;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+
+ /*
+ * this function is expect to call in master mode, which allows no power saving
+ * so, we just check hw_init_completed
+ */
+
+ if (!padapter->hw_init_completed) {
+ ret = -EPERM;
+ goto out;
+ }
+
+ if (!p->pointer || p->length != sizeof(struct ieee_param)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ param = (struct ieee_param *)rtw_malloc(p->length);
+ if (!param) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (copy_from_user(param, p->pointer, p->length)) {
+ kfree(param);
+ ret = -EFAULT;
+ goto out;
+ }
+
+ switch (param->cmd) {
+ case RTL871X_HOSTAPD_FLUSH:
+ ret = rtw_hostapd_sta_flush(dev);
+ break;
+ case RTL871X_HOSTAPD_ADD_STA:
+ ret = rtw_add_sta(dev, param);
+ break;
+ case RTL871X_HOSTAPD_REMOVE_STA:
+ ret = rtw_del_sta(dev, param);
+ break;
+ case RTL871X_HOSTAPD_SET_BEACON:
+ ret = rtw_set_beacon(dev, param, p->length);
+ break;
+ case RTL871X_SET_ENCRYPTION:
+ ret = rtw_set_encryption(dev, param, p->length);
+ break;
+ case RTL871X_HOSTAPD_GET_WPAIE_STA:
+ ret = rtw_get_sta_wpaie(dev, param);
+ break;
+ case RTL871X_HOSTAPD_SET_WPS_BEACON:
+ ret = rtw_set_wps_beacon(dev, param, p->length);
+ break;
+ case RTL871X_HOSTAPD_SET_WPS_PROBE_RESP:
+ ret = rtw_set_wps_probe_resp(dev, param, p->length);
+ break;
+ case RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP:
+ ret = rtw_set_wps_assoc_resp(dev, param, p->length);
+ break;
+ case RTL871X_HOSTAPD_SET_HIDDEN_SSID:
+ ret = rtw_set_hidden_ssid(dev, param, p->length);
+ break;
+ case RTL871X_HOSTAPD_GET_INFO_STA:
+ ret = rtw_ioctl_get_sta_data(dev, param, p->length);
+ break;
+ case RTL871X_HOSTAPD_SET_MACADDR_ACL:
+ ret = rtw_ioctl_set_macaddr_acl(dev, param, p->length);
+ break;
+ case RTL871X_HOSTAPD_ACL_ADD_STA:
+ ret = rtw_ioctl_acl_add_sta(dev, param, p->length);
+ break;
+ case RTL871X_HOSTAPD_ACL_REMOVE_STA:
+ ret = rtw_ioctl_acl_remove_sta(dev, param, p->length);
+ break;
+ default:
+ DBG_88E("Unknown hostapd request: %d\n", param->cmd);
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ if (ret == 0 && copy_to_user(p->pointer, param, p->length))
+ ret = -EFAULT;
+ kfree(param);
+out:
+ return ret;
+}
+#endif
+
+#include <rtw_android.h>
+static int rtw_wx_set_priv(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *awrq,
+ char *extra)
+{
+ int ret = 0;
+ int len = 0;
+ char *ext;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct iw_point *dwrq = (struct iw_point *)awrq;
+
+ if (dwrq->length == 0)
+ return -EFAULT;
+
+ len = dwrq->length;
+ ext = vmalloc(len);
+ if (!ext)
+ return -ENOMEM;
+
+ if (copy_from_user(ext, dwrq->pointer, len)) {
+ vfree(ext);
+ return -EFAULT;
+ }
+
+ /* added for wps2.0 @20110524 */
+ if (dwrq->flags == 0x8766 && len > 8) {
+ u32 cp_sz;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ u8 *probereq_wpsie = ext;
+ int probereq_wpsie_len = len;
+ u8 wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
+
+ if ((_VENDOR_SPECIFIC_IE_ == probereq_wpsie[0]) &&
+ (!memcmp(&probereq_wpsie[2], wps_oui, 4))) {
+ cp_sz = min(probereq_wpsie_len, MAX_WPS_IE_LEN);
+
+ pmlmepriv->wps_probe_req_ie_len = 0;
+ kfree(pmlmepriv->wps_probe_req_ie);
+ pmlmepriv->wps_probe_req_ie = NULL;
+
+ pmlmepriv->wps_probe_req_ie = rtw_malloc(cp_sz);
+ if (!pmlmepriv->wps_probe_req_ie) {
+ pr_info("%s()-%d: rtw_malloc() ERROR!\n", __func__, __LINE__);
+ ret = -EINVAL;
+ goto FREE_EXT;
+ }
+ memcpy(pmlmepriv->wps_probe_req_ie, probereq_wpsie, cp_sz);
+ pmlmepriv->wps_probe_req_ie_len = cp_sz;
+ }
+ goto FREE_EXT;
+ }
+
+ if (len >= WEXT_CSCAN_HEADER_SIZE &&
+ !memcmp(ext, WEXT_CSCAN_HEADER, WEXT_CSCAN_HEADER_SIZE)) {
+ ret = rtw_wx_set_scan(dev, info, awrq, ext);
+ goto FREE_EXT;
+ }
+
+FREE_EXT:
+
+ vfree(ext);
+
+ return ret;
+}
+
+static iw_handler rtw_handlers[] = {
+ NULL, /* SIOCSIWCOMMIT */
+ rtw_wx_get_name, /* SIOCGIWNAME */
+ dummy, /* SIOCSIWNWID */
+ dummy, /* SIOCGIWNWID */
+ rtw_wx_set_freq, /* SIOCSIWFREQ */
+ rtw_wx_get_freq, /* SIOCGIWFREQ */
+ rtw_wx_set_mode, /* SIOCSIWMODE */
+ rtw_wx_get_mode, /* SIOCGIWMODE */
+ dummy, /* SIOCSIWSENS */
+ rtw_wx_get_sens, /* SIOCGIWSENS */
+ NULL, /* SIOCSIWRANGE */
+ rtw_wx_get_range, /* SIOCGIWRANGE */
+ rtw_wx_set_priv, /* SIOCSIWPRIV */
+ NULL, /* SIOCGIWPRIV */
+ NULL, /* SIOCSIWSTATS */
+ NULL, /* SIOCGIWSTATS */
+ dummy, /* SIOCSIWSPY */
+ dummy, /* SIOCGIWSPY */
+ NULL, /* SIOCGIWTHRSPY */
+ NULL, /* SIOCWIWTHRSPY */
+ rtw_wx_set_wap, /* SIOCSIWAP */
+ rtw_wx_get_wap, /* SIOCGIWAP */
+ rtw_wx_set_mlme, /* request MLME operation; uses struct iw_mlme */
+ dummy, /* SIOCGIWAPLIST -- depricated */
+ rtw_wx_set_scan, /* SIOCSIWSCAN */
+ rtw_wx_get_scan, /* SIOCGIWSCAN */
+ rtw_wx_set_essid, /* SIOCSIWESSID */
+ rtw_wx_get_essid, /* SIOCGIWESSID */
+ dummy, /* SIOCSIWNICKN */
+ rtw_wx_get_nick, /* SIOCGIWNICKN */
+ NULL, /* -- hole -- */
+ NULL, /* -- hole -- */
+ rtw_wx_set_rate, /* SIOCSIWRATE */
+ rtw_wx_get_rate, /* SIOCGIWRATE */
+ rtw_wx_set_rts, /* SIOCSIWRTS */
+ rtw_wx_get_rts, /* SIOCGIWRTS */
+ rtw_wx_set_frag, /* SIOCSIWFRAG */
+ rtw_wx_get_frag, /* SIOCGIWFRAG */
+ dummy, /* SIOCSIWTXPOW */
+ dummy, /* SIOCGIWTXPOW */
+ dummy, /* SIOCSIWRETRY */
+ rtw_wx_get_retry, /* SIOCGIWRETRY */
+ rtw_wx_set_enc, /* SIOCSIWENCODE */
+ rtw_wx_get_enc, /* SIOCGIWENCODE */
+ dummy, /* SIOCSIWPOWER */
+ rtw_wx_get_power, /* SIOCGIWPOWER */
+ NULL, /*---hole---*/
+ NULL, /*---hole---*/
+ rtw_wx_set_gen_ie, /* SIOCSIWGENIE */
+ NULL, /* SIOCGWGENIE */
+ rtw_wx_set_auth, /* SIOCSIWAUTH */
+ NULL, /* SIOCGIWAUTH */
+ rtw_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
+ NULL, /* SIOCGIWENCODEEXT */
+ rtw_wx_set_pmkid, /* SIOCSIWPMKSA */
+ NULL, /*---hole---*/
+};
+
+static struct iw_statistics *rtw_get_wireless_stats(struct net_device *dev)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
+ struct iw_statistics *piwstats = &padapter->iwstats;
+ int tmp_level = 0;
+ int tmp_qual = 0;
+ int tmp_noise = 0;
+
+ if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
+ piwstats->qual.qual = 0;
+ piwstats->qual.level = 0;
+ piwstats->qual.noise = 0;
+ } else {
+ tmp_level = padapter->recvpriv.signal_strength;
+ tmp_qual = padapter->recvpriv.signal_qual;
+ tmp_noise = padapter->recvpriv.noise;
+
+ piwstats->qual.level = tmp_level;
+ piwstats->qual.qual = tmp_qual;
+ piwstats->qual.noise = tmp_noise;
+ }
+ piwstats->qual.updated = IW_QUAL_ALL_UPDATED;/* IW_QUAL_DBM; */
+ return &padapter->iwstats;
+}
+
+struct iw_handler_def rtw_handlers_def = {
+ .standard = rtw_handlers,
+ .num_standard = ARRAY_SIZE(rtw_handlers),
+ .get_wireless_stats = rtw_get_wireless_stats,
+};
+
+int rtw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ struct iwreq *wrq = (struct iwreq *)rq;
+ int ret = 0;
+
+ switch (cmd) {
+ case RTL_IOCTL_WPA_SUPPLICANT:
+ ret = wpa_supplicant_ioctl(dev, &wrq->u.data);
+ break;
+#ifdef CPTCFG_88EU_AP_MODE
+ case RTL_IOCTL_HOSTAPD:
+ ret = rtw_hostapd_ioctl(dev, &wrq->u.data);
+ break;
+#endif /* CPTCFG_88EU_AP_MODE */
+ case (SIOCDEVPRIVATE+1):
+ ret = rtw_android_priv_cmd(dev, rq, cmd);
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+ return ret;
+}
diff --git a/drivers/staging/rtl8188eu/os_dep/mlme_linux.c b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c
new file mode 100644
index 0000000..cf47207
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/mlme_linux.c
@@ -0,0 +1,175 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#define _MLME_OSDEP_C_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <mlme_osdep.h>
+
+void rtw_init_mlme_timer(struct adapter *padapter)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ timer_setup(&pmlmepriv->assoc_timer, _rtw_join_timeout_handler, 0);
+ timer_setup(&pmlmepriv->scan_to_timer, rtw_scan_timeout_handler, 0);
+ timer_setup(&pmlmepriv->dynamic_chk_timer,
+ rtw_dynamic_check_timer_handlder, 0);
+}
+
+void rtw_os_indicate_connect(struct adapter *adapter)
+{
+ rtw_indicate_wx_assoc_event(adapter);
+ netif_carrier_on(adapter->pnetdev);
+}
+
+static struct rt_pmkid_list backup_pmkid[NUM_PMKID_CACHE];
+
+void rtw_reset_securitypriv(struct adapter *adapter)
+{
+ u8 backup_index;
+ u8 backup_counter;
+ u32 backup_time;
+ struct security_priv *psec_priv = &adapter->securitypriv;
+
+ if (psec_priv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
+ /* 802.1x
+ * We have to backup the PMK information for WiFi PMK Caching
+ * test item. Backup the btkip_countermeasure information. When
+ * the countermeasure is trigger, the driver have to disconnect
+ * with AP for 60 seconds.
+ */
+ memcpy(backup_pmkid, psec_priv->PMKIDList,
+ sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
+ backup_index = psec_priv->PMKIDIndex;
+ backup_counter = psec_priv->btkip_countermeasure;
+ backup_time = psec_priv->btkip_countermeasure_time;
+
+ memset(psec_priv, 0, sizeof(*psec_priv));
+
+ /* Restore the PMK information to securitypriv structure
+ * for the following connection.
+ */
+ memcpy(psec_priv->PMKIDList, backup_pmkid,
+ sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
+ psec_priv->PMKIDIndex = backup_index;
+ psec_priv->btkip_countermeasure = backup_counter;
+ psec_priv->btkip_countermeasure_time = backup_time;
+ psec_priv->ndisauthtype = Ndis802_11AuthModeOpen;
+ psec_priv->ndisencryptstatus = Ndis802_11WEPDisabled;
+ } else {
+ /* reset values in securitypriv */
+ psec_priv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
+ psec_priv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
+ psec_priv->dot11PrivacyKeyIndex = 0;
+ psec_priv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+ psec_priv->dot118021XGrpKeyid = 1;
+ psec_priv->ndisauthtype = Ndis802_11AuthModeOpen;
+ psec_priv->ndisencryptstatus = Ndis802_11WEPDisabled;
+ }
+}
+
+void rtw_os_indicate_disconnect(struct adapter *adapter)
+{
+ /* Do it first for tx broadcast pkt after disconnection issue! */
+ netif_carrier_off(adapter->pnetdev);
+ rtw_indicate_wx_disassoc_event(adapter);
+ rtw_reset_securitypriv(adapter);
+}
+
+void rtw_report_sec_ie(struct adapter *adapter, u8 authmode, u8 *sec_ie)
+{
+ uint len;
+ u8 *buff, *p, i;
+ union iwreq_data wrqu;
+
+ RT_TRACE(_module_mlme_osdep_c_, _drv_info_,
+ ("+%s, authmode=%d\n", __func__, authmode));
+ buff = NULL;
+ if (authmode == _WPA_IE_ID_) {
+ RT_TRACE(_module_mlme_osdep_c_, _drv_info_,
+ ("%s, authmode=%d\n", __func__, authmode));
+ buff = rtw_malloc(IW_CUSTOM_MAX);
+ if (!buff)
+ return;
+ memset(buff, 0, IW_CUSTOM_MAX);
+ p = buff;
+ p += sprintf(p, "ASSOCINFO(ReqIEs =");
+ len = sec_ie[1] + 2;
+ len = min_t(uint, len, IW_CUSTOM_MAX);
+ for (i = 0; i < len; i++)
+ p += sprintf(p, "%02x", sec_ie[i]);
+ p += sprintf(p, ")");
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = min_t(__u16, p - buff, IW_CUSTOM_MAX);
+ wireless_send_event(adapter->pnetdev, IWEVCUSTOM, &wrqu, buff);
+ kfree(buff);
+ }
+}
+
+void init_addba_retry_timer(struct adapter *padapter, struct sta_info *psta)
+{
+ timer_setup(&psta->addba_retry_timer, addba_timer_hdl, 0);
+}
+
+void init_mlme_ext_timer(struct adapter *padapter)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ timer_setup(&pmlmeext->survey_timer, survey_timer_hdl, 0);
+ timer_setup(&pmlmeext->link_timer, link_timer_hdl, 0);
+}
+
+#ifdef CPTCFG_88EU_AP_MODE
+
+void rtw_indicate_sta_assoc_event(struct adapter *padapter, struct sta_info *psta)
+{
+ union iwreq_data wrqu;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ if (!psta)
+ return;
+
+ if (psta->aid > NUM_STA)
+ return;
+
+ if (pstapriv->sta_aid[psta->aid - 1] != psta)
+ return;
+
+ wrqu.addr.sa_family = ARPHRD_ETHER;
+
+ memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN);
+
+ DBG_88E("+%s\n", __func__);
+
+ wireless_send_event(padapter->pnetdev, IWEVREGISTERED, &wrqu, NULL);
+}
+
+void rtw_indicate_sta_disassoc_event(struct adapter *padapter, struct sta_info *psta)
+{
+ union iwreq_data wrqu;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ if (!psta)
+ return;
+
+ if (psta->aid > NUM_STA)
+ return;
+
+ if (pstapriv->sta_aid[psta->aid - 1] != psta)
+ return;
+
+ wrqu.addr.sa_family = ARPHRD_ETHER;
+
+ memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN);
+
+ DBG_88E("+%s\n", __func__);
+
+ wireless_send_event(padapter->pnetdev, IWEVEXPIRED, &wrqu, NULL);
+}
+
+#endif
diff --git a/drivers/staging/rtl8188eu/os_dep/mon.c b/drivers/staging/rtl8188eu/os_dep/mon.c
new file mode 100644
index 0000000..d7a643d
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/mon.c
@@ -0,0 +1,190 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RTL8188EU monitor interface
+ *
+ * Copyright (C) 2015 Jakub Sitnicki
+ */
+
+#include <linux/ieee80211.h>
+#include <linux/netdevice.h>
+#include <net/cfg80211.h>
+
+#include <drv_types.h>
+#include <rtw_recv.h>
+#include <rtw_xmit.h>
+#include <mon.h>
+
+/**
+ * unprotect_frame() - unset Protected flag and strip off IV and ICV/MIC
+ */
+static void unprotect_frame(struct sk_buff *skb, int iv_len, int icv_len)
+{
+ struct ieee80211_hdr *hdr;
+ int hdr_len;
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+ hdr_len = ieee80211_hdrlen(hdr->frame_control);
+
+ if (skb->len < hdr_len + iv_len + icv_len)
+ return;
+ if (!ieee80211_has_protected(hdr->frame_control))
+ return;
+
+ hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+
+ memmove(skb->data + iv_len, skb->data, hdr_len);
+ skb_pull(skb, iv_len);
+ skb_trim(skb, skb->len - icv_len);
+}
+
+static void mon_recv_decrypted(struct net_device *dev, const u8 *data,
+ int data_len, int iv_len, int icv_len)
+{
+ struct sk_buff *skb;
+
+ skb = netdev_alloc_skb(dev, data_len);
+ if (!skb)
+ return;
+ skb_put_data(skb, data, data_len);
+
+ /*
+ * Frame data is not encrypted. Strip off protection so
+ * userspace doesn't think that it is.
+ */
+ unprotect_frame(skb, iv_len, icv_len);
+
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+}
+
+static void mon_recv_encrypted(struct net_device *dev, const u8 *data,
+ int data_len)
+{
+ if (net_ratelimit())
+ netdev_info(dev, "Encrypted packets are not supported");
+}
+
+/**
+ * rtl88eu_mon_recv_hook() - forward received frame to the monitor interface
+ *
+ * Assumes that the frame contains an IV and an ICV/MIC, and that
+ * encrypt field in frame->attrib have been set accordingly.
+ */
+void rtl88eu_mon_recv_hook(struct net_device *dev, struct recv_frame *frame)
+{
+ struct rx_pkt_attrib *attr;
+ int iv_len, icv_len;
+ int data_len;
+ u8 *data;
+
+ if (!dev || !frame)
+ return;
+ if (!netif_running(dev))
+ return;
+
+ attr = &frame->attrib;
+ data = frame->pkt->data;
+ data_len = frame->pkt->len;
+
+ /* Broadcast and multicast frames don't have attr->{iv,icv}_len set */
+ SET_ICE_IV_LEN(iv_len, icv_len, attr->encrypt);
+
+ if (attr->bdecrypted)
+ mon_recv_decrypted(dev, data, data_len, iv_len, icv_len);
+ else
+ mon_recv_encrypted(dev, data, data_len);
+}
+
+/**
+ * rtl88eu_mon_xmit_hook() - forward trasmitted frame to the monitor interface
+ *
+ * Assumes that:
+ * - frame header contains an IV and frame->attrib.iv_len is set accordingly,
+ * - data is not encrypted and ICV/MIC has not been appended yet.
+ */
+void rtl88eu_mon_xmit_hook(struct net_device *dev, struct xmit_frame *frame,
+ uint frag_len)
+{
+ struct pkt_attrib *attr;
+ u8 *data;
+ int i, offset;
+
+ if (!dev || !frame)
+ return;
+ if (!netif_running(dev))
+ return;
+
+ attr = &frame->attrib;
+
+ offset = TXDESC_SIZE + frame->pkt_offset * PACKET_OFFSET_SZ;
+ data = frame->buf_addr + offset;
+
+ for (i = 0; i < attr->nr_frags - 1; i++) {
+ mon_recv_decrypted(dev, data, frag_len, attr->iv_len, 0);
+ data += frag_len;
+ data = (u8 *)round_up((size_t)data, 4);
+ }
+ /* Last fragment has different length */
+ mon_recv_decrypted(dev, data, attr->last_txcmdsz, attr->iv_len, 0);
+}
+
+static netdev_tx_t mon_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+}
+
+static const struct net_device_ops mon_netdev_ops = {
+ .ndo_start_xmit = mon_xmit,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
+static void mon_setup(struct net_device *dev)
+{
+ dev->netdev_ops = &mon_netdev_ops;
+ netdev_set_def_destructor(dev);
+ ether_setup(dev);
+#if LINUX_VERSION_IS_GEQ(4,3,0)
+ dev->priv_flags |= IFF_NO_QUEUE;
+#else
+ dev->tx_queue_len = 0;
+#endif
+ dev->type = ARPHRD_IEEE80211;
+ /*
+ * Use a locally administered address (IEEE 802)
+ * XXX: Copied from mac80211_hwsim driver. Revisit.
+ */
+ eth_zero_addr(dev->dev_addr);
+ dev->dev_addr[0] = 0x12;
+}
+
+struct net_device *rtl88eu_mon_init(void)
+{
+ struct net_device *dev;
+ int err;
+
+ dev = alloc_netdev(0, "mon%d", NET_NAME_UNKNOWN, mon_setup);
+ if (!dev)
+ goto fail;
+
+ err = register_netdev(dev);
+ if (err < 0)
+ goto fail_free_dev;
+
+ return dev;
+
+fail_free_dev:
+ free_netdev(dev);
+fail:
+ return NULL;
+}
+
+void rtl88eu_mon_deinit(struct net_device *dev)
+{
+ if (!dev)
+ return;
+
+ unregister_netdev(dev);
+}
diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c
new file mode 100644
index 0000000..43d1f2e
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c
@@ -0,0 +1,747 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _OS_INTFS_C_
+
+#include <osdep_service.h>
+#include <osdep_intf.h>
+#include <drv_types.h>
+#include <xmit_osdep.h>
+#include <recv_osdep.h>
+#include <hal_intf.h>
+#include <rtw_ioctl.h>
+#include <rtl8188e_hal.h>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Realtek Wireless Lan Driver");
+MODULE_AUTHOR("Realtek Semiconductor Corp.");
+MODULE_VERSION(DRIVERVERSION);
+MODULE_FIRMWARE("rtlwifi/rtl8188eufw.bin");
+
+#define RTW_NOTCH_FILTER 0 /* 0:Disable, 1:Enable, */
+
+/* module param defaults */
+/* Ndis802_11Infrastructure; infra, ad-hoc, auto */
+static int rtw_channel = 1;/* ad-hoc support requirement */
+static int rtw_wireless_mode = WIRELESS_11BG_24N;
+static int rtw_vrtl_carrier_sense = AUTO_VCS;
+static int rtw_vcs_type = RTS_CTS;/* */
+static int rtw_rts_thresh = 2347;/* */
+static int rtw_frag_thresh = 2346;/* */
+static int rtw_preamble = PREAMBLE_LONG;/* long, short, auto */
+static int rtw_power_mgnt = 1;
+static int rtw_ips_mode = IPS_NORMAL;
+
+static int rtw_smart_ps = 2;
+
+module_param(rtw_ips_mode, int, 0644);
+MODULE_PARM_DESC(rtw_ips_mode, "The default IPS mode");
+
+static int rtw_debug = 1;
+
+static int rtw_acm_method;/* 0:By SW 1:By HW. */
+
+static int rtw_wmm_enable = 1;/* default is set to enable the wmm. */
+static int rtw_uapsd_enable;
+
+static int rtw_ht_enable = 1;
+/* 0 :disable, bit(0): enable 2.4g, bit(1): enable 5g */
+static int rtw_cbw40_enable = 3;
+static int rtw_ampdu_enable = 1;/* for enable tx_ampdu */
+
+/* 0: disable
+ * bit(0):enable 2.4g
+ * bit(1):enable 5g
+ * default is set to enable 2.4GHZ for IOT issue with bufflao's AP at 5GHZ
+ */
+static int rtw_rx_stbc = 1;
+static int rtw_ampdu_amsdu;/* 0: disabled, 1:enabled, 2:auto */
+
+static int rtw_wifi_spec;
+static int rtw_channel_plan = RT_CHANNEL_DOMAIN_MAX;
+
+static int rtw_antdiv_cfg = 2; /* 0:OFF , 1:ON, 2:decide by Efuse config */
+
+/* 0: decide by efuse
+ * 1: for 88EE, 1Tx and 1RxCG are diversity (2 Ant with SPDT)
+ * 2: for 88EE, 1Tx and 2Rx are diversity (2 Ant, Tx and RxCG are both on aux
+ * port, RxCS is on main port)
+ * 3: for 88EE, 1Tx and 1RxCG are fixed (1Ant, Tx and RxCG are both on aux port)
+ */
+static int rtw_antdiv_type;
+
+static int rtw_enusbss;/* 0:disable, 1:enable */
+
+static int rtw_hwpdn_mode = 2;/* 0:disable, 1:enable, 2: by EFUSE config */
+
+int rtw_mc2u_disable;
+
+static int rtw_80211d;
+
+static char *ifname = "wlan%d";
+module_param(ifname, charp, 0644);
+MODULE_PARM_DESC(ifname, "The default name to allocate for first interface");
+
+static char *if2name = "wlan%d";
+module_param(if2name, charp, 0644);
+MODULE_PARM_DESC(if2name, "The default name to allocate for second interface");
+
+/* temp mac address if users want to use instead of the mac address in Efuse */
+char *rtw_initmac;
+
+module_param(rtw_initmac, charp, 0644);
+module_param(rtw_channel_plan, int, 0644);
+module_param(rtw_channel, int, 0644);
+module_param(rtw_wmm_enable, int, 0644);
+module_param(rtw_vrtl_carrier_sense, int, 0644);
+module_param(rtw_vcs_type, int, 0644);
+module_param(rtw_ht_enable, int, 0644);
+module_param(rtw_cbw40_enable, int, 0644);
+module_param(rtw_ampdu_enable, int, 0644);
+module_param(rtw_rx_stbc, int, 0644);
+module_param(rtw_ampdu_amsdu, int, 0644);
+module_param(rtw_power_mgnt, int, 0644);
+module_param(rtw_smart_ps, int, 0644);
+module_param(rtw_wifi_spec, int, 0644);
+module_param(rtw_antdiv_cfg, int, 0644);
+module_param(rtw_antdiv_type, int, 0644);
+module_param(rtw_enusbss, int, 0644);
+module_param(rtw_hwpdn_mode, int, 0644);
+
+static uint rtw_max_roaming_times = 2;
+module_param(rtw_max_roaming_times, uint, 0644);
+MODULE_PARM_DESC(rtw_max_roaming_times, "The max roaming times to try");
+
+static int rtw_fw_iol = 1;/* 0:Disable, 1:enable, 2:by usb speed */
+module_param(rtw_fw_iol, int, 0644);
+MODULE_PARM_DESC(rtw_fw_iol, "FW IOL");
+
+module_param(rtw_mc2u_disable, int, 0644);
+
+module_param(rtw_80211d, int, 0644);
+MODULE_PARM_DESC(rtw_80211d, "Enable 802.11d mechanism");
+
+static uint rtw_notch_filter = RTW_NOTCH_FILTER;
+module_param(rtw_notch_filter, uint, 0644);
+MODULE_PARM_DESC(rtw_notch_filter, "0:Disable, 1:Enable, 2:Enable only for P2P");
+module_param_named(debug, rtw_debug, int, 0444);
+MODULE_PARM_DESC(debug, "Set debug level (1-9) (default 1)");
+
+static bool rtw_monitor_enable;
+module_param_named(monitor_enable, rtw_monitor_enable, bool, 0444);
+MODULE_PARM_DESC(monitor_enable, "Enable monitor interface (default: false)");
+
+static int netdev_close(struct net_device *pnetdev);
+
+static void loadparam(struct adapter *padapter, struct net_device *pnetdev)
+{
+ struct registry_priv *registry_par = &padapter->registrypriv;
+
+ GlobalDebugLevel = rtw_debug;
+
+ memcpy(registry_par->ssid.ssid, "ANY", 3);
+ registry_par->ssid.ssid_length = 3;
+
+ registry_par->channel = (u8)rtw_channel;
+ registry_par->wireless_mode = (u8)rtw_wireless_mode;
+ registry_par->vrtl_carrier_sense = (u8)rtw_vrtl_carrier_sense;
+ registry_par->vcs_type = (u8)rtw_vcs_type;
+ registry_par->rts_thresh = (u16)rtw_rts_thresh;
+ registry_par->frag_thresh = (u16)rtw_frag_thresh;
+ registry_par->preamble = (u8)rtw_preamble;
+ registry_par->smart_ps = (u8)rtw_smart_ps;
+ registry_par->power_mgnt = (u8)rtw_power_mgnt;
+ registry_par->ips_mode = (u8)rtw_ips_mode;
+ registry_par->mp_mode = 0;
+ registry_par->acm_method = (u8)rtw_acm_method;
+
+ /* UAPSD */
+ registry_par->wmm_enable = (u8)rtw_wmm_enable;
+ registry_par->uapsd_enable = (u8)rtw_uapsd_enable;
+
+ registry_par->ht_enable = (u8)rtw_ht_enable;
+ registry_par->cbw40_enable = (u8)rtw_cbw40_enable;
+ registry_par->ampdu_enable = (u8)rtw_ampdu_enable;
+ registry_par->rx_stbc = (u8)rtw_rx_stbc;
+ registry_par->ampdu_amsdu = (u8)rtw_ampdu_amsdu;
+ registry_par->wifi_spec = (u8)rtw_wifi_spec;
+ registry_par->channel_plan = (u8)rtw_channel_plan;
+ registry_par->accept_addba_req = true;
+ registry_par->antdiv_cfg = (u8)rtw_antdiv_cfg;
+ registry_par->antdiv_type = (u8)rtw_antdiv_type;
+ registry_par->hwpdn_mode = (u8)rtw_hwpdn_mode;
+
+ registry_par->max_roaming_times = (u8)rtw_max_roaming_times;
+
+ registry_par->fw_iol = rtw_fw_iol;
+
+ registry_par->enable80211d = (u8)rtw_80211d;
+ snprintf(registry_par->ifname, 16, "%s", ifname);
+ snprintf(registry_par->if2name, 16, "%s", if2name);
+ registry_par->notch_filter = (u8)rtw_notch_filter;
+ registry_par->monitor_enable = rtw_monitor_enable;
+}
+
+static int rtw_net_set_mac_address(struct net_device *pnetdev, void *p)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev);
+ struct sockaddr *addr = p;
+
+ if (!padapter->bup)
+ memcpy(padapter->eeprompriv.mac_addr, addr->sa_data, ETH_ALEN);
+
+ return 0;
+}
+
+static struct net_device_stats *rtw_net_get_stats(struct net_device *pnetdev)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev);
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct recv_priv *precvpriv = &padapter->recvpriv;
+
+ padapter->stats.tx_packets = pxmitpriv->tx_pkts;
+ padapter->stats.rx_packets = precvpriv->rx_pkts;
+ padapter->stats.tx_dropped = pxmitpriv->tx_drop;
+ padapter->stats.rx_dropped = precvpriv->rx_drop;
+ padapter->stats.tx_bytes = pxmitpriv->tx_bytes;
+ padapter->stats.rx_bytes = precvpriv->rx_bytes;
+ return &padapter->stats;
+}
+
+/*
+ * AC to queue mapping
+ *
+ * AC_VO -> queue 0
+ * AC_VI -> queue 1
+ * AC_BE -> queue 2
+ * AC_BK -> queue 3
+ */
+static const u16 rtw_1d_to_queue[8] = { 2, 3, 3, 2, 1, 1, 0, 0 };
+
+/* Given a data frame determine the 802.1p/1d tag to use. */
+static unsigned int rtw_classify8021d(struct sk_buff *skb)
+{
+ unsigned int dscp;
+
+ /* skb->priority values from 256->263 are magic values to
+ * directly indicate a specific 802.1d priority. This is used
+ * to allow 802.1d priority to be passed directly in from VLAN
+ * tags, etc.
+ */
+ if (skb->priority >= 256 && skb->priority <= 263)
+ return skb->priority - 256;
+
+ switch (skb->protocol) {
+ case htons(ETH_P_IP):
+ dscp = ip_hdr(skb)->tos & 0xfc;
+ break;
+ default:
+ return 0;
+ }
+
+ return dscp >> 5;
+}
+
+#if LINUX_VERSION_IS_GEQ(5,2,0)
+static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb,
+ struct net_device *sb_dev)
+#elif LINUX_VERSION_IS_GEQ(4,19,0)
+static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb,
+ struct net_device *sb_dev,
+ select_queue_fallback_t fallback)
+#else
+static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb,
+ void *accel_priv,
+ select_queue_fallback_t fallback)
+#endif
+{
+ struct adapter *padapter = rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ skb->priority = rtw_classify8021d(skb);
+
+ if (pmlmepriv->acm_mask != 0)
+ skb->priority = qos_acm(pmlmepriv->acm_mask, skb->priority);
+
+ return rtw_1d_to_queue[skb->priority];
+}
+
+u16 rtw_recv_select_queue(struct sk_buff *skb)
+{
+ struct iphdr *piphdr;
+ unsigned int dscp;
+ __be16 eth_type;
+ u32 priority;
+ u8 *pdata = skb->data;
+
+ memcpy(&eth_type, pdata + (ETH_ALEN << 1), 2);
+
+ switch (eth_type) {
+ case htons(ETH_P_IP):
+ piphdr = (struct iphdr *)(pdata + ETH_HLEN);
+ dscp = piphdr->tos & 0xfc;
+ priority = dscp >> 5;
+ break;
+ default:
+ priority = 0;
+ }
+
+ return rtw_1d_to_queue[priority];
+}
+
+static const struct net_device_ops rtw_netdev_ops = {
+ .ndo_open = netdev_open,
+ .ndo_stop = netdev_close,
+ .ndo_start_xmit = rtw_xmit_entry,
+ .ndo_select_queue = rtw_select_queue,
+ .ndo_set_mac_address = rtw_net_set_mac_address,
+ .ndo_get_stats = rtw_net_get_stats,
+ .ndo_do_ioctl = rtw_ioctl,
+};
+
+int rtw_init_netdev_name(struct net_device *pnetdev, const char *ifname)
+{
+ if (dev_alloc_name(pnetdev, ifname) < 0)
+ RT_TRACE(_module_os_intfs_c_, _drv_err_, ("dev_alloc_name, fail!\n"));
+
+ netif_carrier_off(pnetdev);
+ return 0;
+}
+
+static const struct device_type wlan_type = {
+ .name = "wlan",
+};
+
+struct net_device *rtw_init_netdev(struct adapter *old_padapter)
+{
+ struct adapter *padapter;
+ struct net_device *pnetdev = NULL;
+
+ RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+init_net_dev\n"));
+
+ if (old_padapter)
+ pnetdev = rtw_alloc_etherdev_with_old_priv((void *)old_padapter);
+
+ if (!pnetdev)
+ return NULL;
+
+ pnetdev->dev.type = &wlan_type;
+ padapter = rtw_netdev_priv(pnetdev);
+ padapter->pnetdev = pnetdev;
+ DBG_88E("register rtw_netdev_ops to netdev_ops\n");
+ pnetdev->netdev_ops = &rtw_netdev_ops;
+ pnetdev->watchdog_timeo = HZ * 3; /* 3 second timeout */
+ pnetdev->wireless_handlers = (struct iw_handler_def *)&rtw_handlers_def;
+
+ loadparam(padapter, pnetdev);
+
+ return pnetdev;
+}
+
+static int rtw_start_drv_threads(struct adapter *padapter)
+{
+ int err = 0;
+
+ RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+rtw_start_drv_threads\n"));
+
+ padapter->cmdThread = kthread_run(rtw_cmd_thread, padapter,
+ "RTW_CMD_THREAD");
+ if (IS_ERR(padapter->cmdThread))
+ err = PTR_ERR(padapter->cmdThread);
+ else
+ /* wait for cmd_thread to run */
+ wait_for_completion_interruptible(&padapter->cmdpriv.terminate_cmdthread_comp);
+
+ return err;
+}
+
+void rtw_stop_drv_threads(struct adapter *padapter)
+{
+ RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+rtw_stop_drv_threads\n"));
+
+ /* Below is to terminate rtw_cmd_thread & event_thread... */
+ complete(&padapter->cmdpriv.cmd_queue_comp);
+ if (padapter->cmdThread)
+ wait_for_completion_interruptible(&padapter->cmdpriv.terminate_cmdthread_comp);
+}
+
+static u8 rtw_init_default_value(struct adapter *padapter)
+{
+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+
+ /* xmit_priv */
+ pxmitpriv->vcs_setting = pregistrypriv->vrtl_carrier_sense;
+ pxmitpriv->vcs = pregistrypriv->vcs_type;
+ pxmitpriv->vcs_type = pregistrypriv->vcs_type;
+ pxmitpriv->frag_len = pregistrypriv->frag_thresh;
+
+ /* mlme_priv */
+ pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */
+ pmlmepriv->scan_mode = SCAN_ACTIVE;
+
+ /* ht_priv */
+ pmlmepriv->htpriv.ampdu_enable = false;/* set to disabled */
+
+ /* security_priv */
+ psecuritypriv->binstallGrpkey = _FAIL;
+ psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
+ psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
+ psecuritypriv->dot11PrivacyKeyIndex = 0;
+ psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+ psecuritypriv->dot118021XGrpKeyid = 1;
+ psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
+ psecuritypriv->ndisencryptstatus = Ndis802_11WEPDisabled;
+
+ /* registry_priv */
+ rtw_init_registrypriv_dev_network(padapter);
+ rtw_update_registrypriv_dev_network(padapter);
+
+ /* hal_priv */
+ rtw_hal_def_value_init(padapter);
+
+ /* misc. */
+ padapter->bReadPortCancel = false;
+ padapter->bWritePortCancel = false;
+ return _SUCCESS;
+}
+
+u8 rtw_reset_drv_sw(struct adapter *padapter)
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
+
+ /* hal_priv */
+ rtw_hal_def_value_init(padapter);
+ padapter->bReadPortCancel = false;
+ padapter->bWritePortCancel = false;
+ pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */
+
+ padapter->xmitpriv.tx_pkts = 0;
+ padapter->recvpriv.rx_pkts = 0;
+
+ pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
+
+ _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING);
+ rtw_hal_sreset_init(padapter);
+ pwrctrlpriv->pwr_state_check_cnts = 0;
+
+ /* mlmeextpriv */
+ padapter->mlmeextpriv.sitesurvey_res.state = SCAN_DISABLE;
+
+ rtw_set_signal_stat_timer(&padapter->recvpriv);
+
+ return _SUCCESS;
+}
+
+u8 rtw_init_drv_sw(struct adapter *padapter)
+{
+ u8 ret8 = _SUCCESS;
+
+ RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+rtw_init_drv_sw\n"));
+
+ if ((rtw_init_cmd_priv(&padapter->cmdpriv)) == _FAIL) {
+ RT_TRACE(_module_os_intfs_c_, _drv_err_, ("\n Can't init cmd_priv\n"));
+ ret8 = _FAIL;
+ goto exit;
+ }
+
+ padapter->cmdpriv.padapter = padapter;
+
+ if (rtw_init_mlme_priv(padapter) == _FAIL) {
+ RT_TRACE(_module_os_intfs_c_, _drv_err_, ("\n Can't init mlme_priv\n"));
+ ret8 = _FAIL;
+ goto exit;
+ }
+
+ if (init_mlme_ext_priv(padapter) == _FAIL) {
+ RT_TRACE(_module_os_intfs_c_, _drv_err_, ("\n Can't init mlme_ext_priv\n"));
+ ret8 = _FAIL;
+ goto exit;
+ }
+
+ if (_rtw_init_xmit_priv(&padapter->xmitpriv, padapter) == _FAIL) {
+ DBG_88E("Can't _rtw_init_xmit_priv\n");
+ ret8 = _FAIL;
+ goto exit;
+ }
+
+ if (_rtw_init_recv_priv(&padapter->recvpriv, padapter) == _FAIL) {
+ DBG_88E("Can't _rtw_init_recv_priv\n");
+ ret8 = _FAIL;
+ goto exit;
+ }
+
+ if (_rtw_init_sta_priv(&padapter->stapriv) == _FAIL) {
+ DBG_88E("Can't _rtw_init_sta_priv\n");
+ ret8 = _FAIL;
+ goto exit;
+ }
+
+ padapter->stapriv.padapter = padapter;
+
+ rtw_init_bcmc_stainfo(padapter);
+
+ rtw_init_pwrctrl_priv(padapter);
+
+ ret8 = rtw_init_default_value(padapter);
+
+ rtw_hal_dm_init(padapter);
+ rtw_hal_sw_led_init(padapter);
+
+ rtw_hal_sreset_init(padapter);
+
+exit:
+ RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-rtw_init_drv_sw\n"));
+
+ return ret8;
+}
+
+void rtw_cancel_all_timer(struct adapter *padapter)
+{
+ RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+rtw_cancel_all_timer\n"));
+
+ del_timer_sync(&padapter->mlmepriv.assoc_timer);
+ RT_TRACE(_module_os_intfs_c_, _drv_info_, ("rtw_cancel_all_timer:cancel association timer complete!\n"));
+
+ del_timer_sync(&padapter->mlmepriv.scan_to_timer);
+ RT_TRACE(_module_os_intfs_c_, _drv_info_, ("rtw_cancel_all_timer:cancel scan_to_timer!\n"));
+
+ del_timer_sync(&padapter->mlmepriv.dynamic_chk_timer);
+ RT_TRACE(_module_os_intfs_c_, _drv_info_, ("rtw_cancel_all_timer:cancel dynamic_chk_timer!\n"));
+
+ /* cancel sw led timer */
+ rtw_hal_sw_led_deinit(padapter);
+ RT_TRACE(_module_os_intfs_c_, _drv_info_, ("rtw_cancel_all_timer:cancel DeInitSwLeds!\n"));
+
+ del_timer_sync(&padapter->pwrctrlpriv.pwr_state_check_timer);
+
+ del_timer_sync(&padapter->recvpriv.signal_stat_timer);
+}
+
+u8 rtw_free_drv_sw(struct adapter *padapter)
+{
+ RT_TRACE(_module_os_intfs_c_, _drv_info_, ("==>rtw_free_drv_sw"));
+
+ free_mlme_ext_priv(&padapter->mlmeextpriv);
+
+ rtw_free_mlme_priv(&padapter->mlmepriv);
+ _rtw_free_xmit_priv(&padapter->xmitpriv);
+
+ /* will free bcmc_stainfo here */
+ _rtw_free_sta_priv(&padapter->stapriv);
+
+ _rtw_free_recv_priv(&padapter->recvpriv);
+
+ rtw_hal_free_data(padapter);
+
+ RT_TRACE(_module_os_intfs_c_, _drv_info_, ("<== rtw_free_drv_sw\n"));
+
+ mutex_destroy(&padapter->hw_init_mutex);
+
+ RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-rtw_free_drv_sw\n"));
+
+ return _SUCCESS;
+}
+
+static int _netdev_open(struct net_device *pnetdev)
+{
+ uint status;
+ int err;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev);
+ struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
+
+ RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+88eu_drv - dev_open\n"));
+ DBG_88E("+88eu_drv - drv_open, bup =%d\n", padapter->bup);
+
+ if (pwrctrlpriv->ps_flag) {
+ padapter->net_closed = false;
+ goto netdev_open_normal_process;
+ }
+
+ if (!padapter->bup) {
+ padapter->bDriverStopped = false;
+ padapter->bSurpriseRemoved = false;
+
+ status = rtw_hal_init(padapter);
+ if (status == _FAIL) {
+ RT_TRACE(_module_os_intfs_c_, _drv_err_, ("rtl88eu_hal_init(): Can't init h/w!\n"));
+ goto netdev_open_error;
+ }
+
+ pr_info("MAC Address = %pM\n", pnetdev->dev_addr);
+
+ err = rtw_start_drv_threads(padapter);
+ if (err) {
+ pr_info("Initialize driver software resource Failed!\n");
+ goto netdev_open_error;
+ }
+
+ if (init_hw_mlme_ext(padapter) == _FAIL) {
+ pr_info("can't init mlme_ext_priv\n");
+ goto netdev_open_error;
+ }
+ rtw_hal_inirp_init(padapter);
+
+ led_control_8188eu(padapter, LED_CTL_NO_LINK);
+
+ padapter->bup = true;
+ }
+ padapter->net_closed = false;
+
+ mod_timer(&padapter->mlmepriv.dynamic_chk_timer,
+ jiffies + msecs_to_jiffies(2000));
+
+ padapter->pwrctrlpriv.bips_processing = false;
+ rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);
+
+ if (!rtw_netif_queue_stopped(pnetdev))
+ netif_tx_start_all_queues(pnetdev);
+ else
+ netif_tx_wake_all_queues(pnetdev);
+
+netdev_open_normal_process:
+ RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-88eu_drv - dev_open\n"));
+ DBG_88E("-88eu_drv - drv_open, bup =%d\n", padapter->bup);
+ return 0;
+
+netdev_open_error:
+ padapter->bup = false;
+ netif_carrier_off(pnetdev);
+ netif_tx_stop_all_queues(pnetdev);
+ RT_TRACE(_module_os_intfs_c_, _drv_err_, ("-88eu_drv - dev_open, fail!\n"));
+ DBG_88E("-88eu_drv - drv_open fail, bup =%d\n", padapter->bup);
+ return -1;
+}
+
+int netdev_open(struct net_device *pnetdev)
+{
+ int ret;
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev);
+
+ if (mutex_lock_interruptible(&padapter->hw_init_mutex))
+ return -ERESTARTSYS;
+ ret = _netdev_open(pnetdev);
+ mutex_unlock(&padapter->hw_init_mutex);
+ return ret;
+}
+
+int ips_netdrv_open(struct adapter *padapter)
+{
+ int status = _SUCCESS;
+
+ padapter->net_closed = false;
+ DBG_88E("===> %s.........\n", __func__);
+
+ padapter->bDriverStopped = false;
+ padapter->bSurpriseRemoved = false;
+
+ status = rtw_hal_init(padapter);
+ if (status == _FAIL) {
+ RT_TRACE(_module_os_intfs_c_, _drv_err_, ("ips_netdrv_open(): Can't init h/w!\n"));
+ goto netdev_open_error;
+ }
+
+ rtw_hal_inirp_init(padapter);
+
+ rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);
+ mod_timer(&padapter->mlmepriv.dynamic_chk_timer,
+ jiffies + msecs_to_jiffies(5000));
+
+ return _SUCCESS;
+
+netdev_open_error:
+ DBG_88E("-ips_netdrv_open - drv_open failure, bup =%d\n", padapter->bup);
+
+ return _FAIL;
+}
+
+int rtw_ips_pwr_up(struct adapter *padapter)
+{
+ int result;
+ unsigned long start_time = jiffies;
+
+ DBG_88E("===> rtw_ips_pwr_up..............\n");
+ rtw_reset_drv_sw(padapter);
+
+ result = ips_netdrv_open(padapter);
+
+ led_control_8188eu(padapter, LED_CTL_NO_LINK);
+
+ DBG_88E("<=== rtw_ips_pwr_up.............. in %dms\n",
+ jiffies_to_msecs(jiffies - start_time));
+ return result;
+}
+
+void rtw_ips_pwr_down(struct adapter *padapter)
+{
+ unsigned long start_time = jiffies;
+
+ DBG_88E("===> rtw_ips_pwr_down...................\n");
+
+ padapter->net_closed = true;
+
+ led_control_8188eu(padapter, LED_CTL_POWER_OFF);
+
+ rtw_ips_dev_unload(padapter);
+ DBG_88E("<=== rtw_ips_pwr_down..................... in %dms\n",
+ jiffies_to_msecs(jiffies - start_time));
+}
+
+void rtw_ips_dev_unload(struct adapter *padapter)
+{
+ DBG_88E("====> %s...\n", __func__);
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_FIFO_CLEARN_UP, NULL);
+
+ usb_intf_stop(padapter);
+
+ /* s5. */
+ if (!padapter->bSurpriseRemoved)
+ rtw_hal_deinit(padapter);
+}
+
+static int netdev_close(struct net_device *pnetdev)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev);
+
+ RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+88eu_drv - drv_close\n"));
+
+ if (padapter->pwrctrlpriv.bInternalAutoSuspend) {
+ if (padapter->pwrctrlpriv.rf_pwrstate == rf_off)
+ padapter->pwrctrlpriv.ps_flag = true;
+ }
+ padapter->net_closed = true;
+
+ if (padapter->pwrctrlpriv.rf_pwrstate == rf_on) {
+ DBG_88E("(2)88eu_drv - drv_close, bup =%d, hw_init_completed =%d\n",
+ padapter->bup, padapter->hw_init_completed);
+
+ /* s1. */
+ if (pnetdev) {
+ if (!rtw_netif_queue_stopped(pnetdev))
+ netif_tx_stop_all_queues(pnetdev);
+ }
+
+ /* s2. */
+ LeaveAllPowerSaveMode(padapter);
+ rtw_disassoc_cmd(padapter, 500, false);
+ /* s2-2. indicate disconnect to os */
+ rtw_indicate_disconnect(padapter);
+ /* s2-3. */
+ rtw_free_assoc_resources(padapter);
+ /* s2-4. */
+ rtw_free_network_queue(padapter, true);
+ /* Close LED */
+ led_control_8188eu(padapter, LED_CTL_POWER_OFF);
+ }
+
+ RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-88eu_drv - drv_close\n"));
+ DBG_88E("-88eu_drv - drv_close, bup =%d\n", padapter->bup);
+ return 0;
+}
diff --git a/drivers/staging/rtl8188eu/os_dep/osdep_service.c b/drivers/staging/rtl8188eu/os_dep/osdep_service.c
new file mode 100644
index 0000000..69d4b1d
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/osdep_service.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _OSDEP_SERVICE_C_
+
+#include <osdep_service.h>
+#include <osdep_intf.h>
+#include <drv_types.h>
+#include <recv_osdep.h>
+#include <linux/vmalloc.h>
+#include <rtw_ioctl_set.h>
+
+u8 *_rtw_malloc(u32 sz)
+{
+ return kmalloc(sz, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+}
+
+void _rtw_init_queue(struct __queue *pqueue)
+{
+ INIT_LIST_HEAD(&pqueue->queue);
+ spin_lock_init(&pqueue->lock);
+}
+
+struct net_device *rtw_alloc_etherdev_with_old_priv(void *old_priv)
+{
+ struct net_device *pnetdev;
+ struct rtw_netdev_priv_indicator *pnpi;
+
+ pnetdev = alloc_etherdev_mq(sizeof(struct rtw_netdev_priv_indicator), 4);
+ if (!pnetdev)
+ goto RETURN;
+
+ pnpi = netdev_priv(pnetdev);
+ pnpi->priv = old_priv;
+
+RETURN:
+ return pnetdev;
+}
+
+void rtw_free_netdev(struct net_device *netdev)
+{
+ struct rtw_netdev_priv_indicator *pnpi;
+
+ if (!netdev)
+ goto RETURN;
+
+ pnpi = netdev_priv(netdev);
+
+ if (!pnpi->priv)
+ goto RETURN;
+
+ vfree(pnpi->priv);
+ free_netdev(netdev);
+
+RETURN:
+ return;
+}
+
+void rtw_buf_free(u8 **buf, u32 *buf_len)
+{
+ *buf_len = 0;
+ kfree(*buf);
+ *buf = NULL;
+}
+
+void rtw_buf_update(u8 **buf, u32 *buf_len, u8 *src, u32 src_len)
+{
+ u32 dup_len = 0;
+ u8 *ori = NULL;
+ u8 *dup = NULL;
+
+ if (!buf || !buf_len)
+ return;
+
+ if (!src || !src_len)
+ goto keep_ori;
+
+ /* duplicate src */
+ dup = rtw_malloc(src_len);
+ if (dup) {
+ dup_len = src_len;
+ memcpy(dup, src, dup_len);
+ }
+
+keep_ori:
+ ori = *buf;
+
+ /* replace buf with dup */
+ *buf_len = 0;
+ *buf = dup;
+ *buf_len = dup_len;
+
+ /* free ori */
+ kfree(ori);
+}
diff --git a/drivers/staging/rtl8188eu/os_dep/recv_linux.c b/drivers/staging/rtl8188eu/os_dep/recv_linux.c
new file mode 100644
index 0000000..9c93398
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/recv_linux.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#include <osdep_service.h>
+#include <drv_types.h>
+
+#include <wifi.h>
+#include <recv_osdep.h>
+
+#include <osdep_intf.h>
+#include <usb_ops_linux.h>
+
+/* alloc os related resource in struct recv_buf */
+int rtw_os_recvbuf_resource_alloc(struct adapter *padapter,
+ struct recv_buf *precvbuf)
+{
+ precvbuf->pskb = NULL;
+ precvbuf->reuse = false;
+ precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!precvbuf->purb)
+ return _FAIL;
+ return _SUCCESS;
+}
+
+void rtw_handle_tkip_mic_err(struct adapter *padapter, u8 bgroup)
+{
+ union iwreq_data wrqu;
+ struct iw_michaelmicfailure ev;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ u32 cur_time = 0;
+
+ if (psecuritypriv->last_mic_err_time == 0) {
+ psecuritypriv->last_mic_err_time = jiffies;
+ } else {
+ cur_time = jiffies;
+
+ if (cur_time - psecuritypriv->last_mic_err_time < 60 * HZ) {
+ psecuritypriv->btkip_countermeasure = true;
+ psecuritypriv->last_mic_err_time = 0;
+ psecuritypriv->btkip_countermeasure_time = cur_time;
+ } else {
+ psecuritypriv->last_mic_err_time = jiffies;
+ }
+ }
+
+ memset(&ev, 0x00, sizeof(ev));
+ if (bgroup)
+ ev.flags |= IW_MICFAILURE_GROUP;
+ else
+ ev.flags |= IW_MICFAILURE_PAIRWISE;
+
+ ev.src_addr.sa_family = ARPHRD_ETHER;
+ memcpy(ev.src_addr.sa_data, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
+ memset(&wrqu, 0x00, sizeof(wrqu));
+ wrqu.data.length = sizeof(ev);
+ wireless_send_event(padapter->pnetdev, IWEVMICHAELMICFAILURE,
+ &wrqu, (char *)&ev);
+}
+
+int rtw_recv_indicatepkt(struct adapter *padapter,
+ struct recv_frame *precv_frame)
+{
+ struct recv_priv *precvpriv;
+ struct __queue *pfree_recv_queue;
+ struct sk_buff *skb;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ precvpriv = &padapter->recvpriv;
+ pfree_recv_queue = &precvpriv->free_recv_queue;
+
+ skb = precv_frame->pkt;
+ if (!skb) {
+ RT_TRACE(_module_recv_osdep_c_, _drv_err_,
+ ("%s():skb == NULL something wrong!!!!\n", __func__));
+ goto _recv_indicatepkt_drop;
+ }
+
+ if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+ struct sk_buff *pskb2 = NULL;
+ struct sta_info *psta = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
+ bool mcast = is_multicast_ether_addr(pattrib->dst);
+
+ if (memcmp(pattrib->dst, myid(&padapter->eeprompriv),
+ ETH_ALEN)) {
+ if (mcast) {
+ psta = rtw_get_bcmc_stainfo(padapter);
+ pskb2 = skb_clone(skb, GFP_ATOMIC);
+ } else {
+ psta = rtw_get_stainfo(pstapriv, pattrib->dst);
+ }
+
+ if (psta) {
+ struct net_device *pnetdev;
+
+ pnetdev = (struct net_device *)padapter->pnetdev;
+ skb->dev = pnetdev;
+ skb_set_queue_mapping(skb, rtw_recv_select_queue(skb));
+
+ rtw_xmit_entry(skb, pnetdev);
+
+ if (mcast)
+ skb = pskb2;
+ else
+ goto _recv_indicatepkt_end;
+ }
+ }
+ }
+
+ skb->ip_summed = CHECKSUM_NONE;
+ skb->dev = padapter->pnetdev;
+ skb->protocol = eth_type_trans(skb, padapter->pnetdev);
+
+ netif_rx(skb);
+
+_recv_indicatepkt_end:
+
+ /* pointers to NULL before rtw_free_recvframe() */
+ precv_frame->pkt = NULL;
+
+ rtw_free_recvframe(precv_frame, pfree_recv_queue);
+
+ RT_TRACE(_module_recv_osdep_c_, _drv_info_,
+ ("\n %s :after netif_rx!!!!\n", __func__));
+
+ return _SUCCESS;
+
+_recv_indicatepkt_drop:
+
+ /* enqueue back to free_recv_queue */
+ rtw_free_recvframe(precv_frame, pfree_recv_queue);
+
+ return _FAIL;
+}
+
+void rtw_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl)
+{
+ timer_setup(&preorder_ctrl->reordering_ctrl_timer,
+ rtw_reordering_ctrl_timeout_handler, 0);
+}
diff --git a/drivers/staging/rtl8188eu/os_dep/rtw_android.c b/drivers/staging/rtl8188eu/os_dep/rtw_android.c
new file mode 100644
index 0000000..daf6db3
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/rtw_android.c
@@ -0,0 +1,250 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#include <linux/module.h>
+#include <linux/netdevice.h>
+
+#include <rtw_android.h>
+#include <osdep_service.h>
+#include <rtw_debug.h>
+#include <rtw_ioctl_set.h>
+
+static const char *android_wifi_cmd_str[ANDROID_WIFI_CMD_MAX] = {
+ "START",
+ "STOP",
+ "SCAN-ACTIVE",
+ "SCAN-PASSIVE",
+ "RSSI",
+ "LINKSPEED",
+ "RXFILTER-START",
+ "RXFILTER-STOP",
+ "RXFILTER-ADD",
+ "RXFILTER-REMOVE",
+ "BTCOEXSCAN-START",
+ "BTCOEXSCAN-STOP",
+ "BTCOEXMODE",
+ "SETSUSPENDOPT",
+ "P2P_DEV_ADDR",
+ "SETFWPATH",
+ "SETBAND",
+ "GETBAND",
+ "COUNTRY",
+ "P2P_SET_NOA",
+ "P2P_GET_NOA",
+ "P2P_SET_PS",
+ "SET_AP_WPS_P2P_IE",
+ "MACADDR",
+ "BLOCK",
+ "WFD-ENABLE",
+ "WFD-DISABLE",
+ "WFD-SET-TCPPORT",
+ "WFD-SET-MAXTPUT",
+ "WFD-SET-DEVTYPE",
+};
+
+struct android_wifi_priv_cmd {
+ const char __user *buf;
+ int used_len;
+ int total_len;
+};
+
+/**
+ * Local (static) functions and variables
+ */
+
+/* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first
+ * time (only) in dhd_open, subsequential wifi on will be handled by
+ * wl_android_wifi_on
+ */
+static int g_wifi_on = true;
+
+int rtw_android_cmdstr_to_num(char *cmdstr)
+{
+ int cmd_num;
+
+ for (cmd_num = 0; cmd_num < ANDROID_WIFI_CMD_MAX; cmd_num++)
+ if (!strncasecmp(cmdstr, android_wifi_cmd_str[cmd_num],
+ strlen(android_wifi_cmd_str[cmd_num])))
+ break;
+ return cmd_num;
+}
+
+static int rtw_android_get_rssi(struct net_device *net, char *command,
+ int total_len)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(net);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct wlan_network *pcur_network = &pmlmepriv->cur_network;
+ int bytes_written = 0;
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ bytes_written += snprintf(&command[bytes_written], total_len,
+ "%s rssi %d",
+ pcur_network->network.ssid.ssid,
+ padapter->recvpriv.rssi);
+ }
+ return bytes_written;
+}
+
+static int rtw_android_get_link_speed(struct net_device *net, char *command,
+ int total_len)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(net);
+ u16 link_speed;
+
+ link_speed = rtw_get_cur_max_rate(padapter) / 10;
+ return snprintf(command, total_len, "LinkSpeed %d",
+ link_speed);
+}
+
+static int rtw_android_get_macaddr(struct net_device *net, char *command,
+ int total_len)
+{
+ return snprintf(command, total_len, "Macaddr = %pM",
+ net->dev_addr);
+}
+
+static int android_set_cntry(struct net_device *net, char *command,
+ int total_len)
+{
+ struct adapter *adapter = (struct adapter *)rtw_netdev_priv(net);
+ char *country_code = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_COUNTRY]) + 1;
+ int ret;
+
+ ret = rtw_set_country(adapter, country_code);
+ return (ret == _SUCCESS) ? 0 : -1;
+}
+
+static int android_get_p2p_addr(struct net_device *net, char *command,
+ int total_len)
+{
+ /* We use the same address as our HW MAC address */
+ memcpy(command, net->dev_addr, ETH_ALEN);
+ return ETH_ALEN;
+}
+
+int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
+{
+ int ret = 0;
+ char *command;
+ int cmd_num;
+ int bytes_written = 0;
+ struct android_wifi_priv_cmd priv_cmd;
+
+ if (!ifr->ifr_data)
+ return -EINVAL;
+ if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(priv_cmd)))
+ return -EFAULT;
+ if (priv_cmd.total_len < 1)
+ return -EINVAL;
+ command = memdup_user(priv_cmd.buf, priv_cmd.total_len);
+ if (IS_ERR(command))
+ return PTR_ERR(command);
+ command[priv_cmd.total_len - 1] = 0;
+ DBG_88E("%s: Android private cmd \"%s\" on %s\n",
+ __func__, command, ifr->ifr_name);
+ cmd_num = rtw_android_cmdstr_to_num(command);
+ switch (cmd_num) {
+ case ANDROID_WIFI_CMD_START:
+ goto response;
+ case ANDROID_WIFI_CMD_SETFWPATH:
+ goto response;
+ }
+ if (!g_wifi_on) {
+ DBG_88E("%s: Ignore private cmd \"%s\" - iface %s is down\n",
+ __func__, command, ifr->ifr_name);
+ ret = 0;
+ goto free;
+ }
+ switch (cmd_num) {
+ case ANDROID_WIFI_CMD_STOP:
+ break;
+ case ANDROID_WIFI_CMD_SCAN_ACTIVE:
+ break;
+ case ANDROID_WIFI_CMD_SCAN_PASSIVE:
+ break;
+ case ANDROID_WIFI_CMD_RSSI:
+ bytes_written = rtw_android_get_rssi(net, command,
+ priv_cmd.total_len);
+ break;
+ case ANDROID_WIFI_CMD_LINKSPEED:
+ bytes_written = rtw_android_get_link_speed(net, command,
+ priv_cmd.total_len);
+ break;
+ case ANDROID_WIFI_CMD_MACADDR:
+ bytes_written = rtw_android_get_macaddr(net, command,
+ priv_cmd.total_len);
+ break;
+ case ANDROID_WIFI_CMD_BLOCK:
+ break;
+ case ANDROID_WIFI_CMD_RXFILTER_START:
+ break;
+ case ANDROID_WIFI_CMD_RXFILTER_STOP:
+ break;
+ case ANDROID_WIFI_CMD_RXFILTER_ADD:
+ break;
+ case ANDROID_WIFI_CMD_RXFILTER_REMOVE:
+ break;
+ case ANDROID_WIFI_CMD_BTCOEXSCAN_START:
+ /* TBD: BTCOEXSCAN-START */
+ break;
+ case ANDROID_WIFI_CMD_BTCOEXSCAN_STOP:
+ /* TBD: BTCOEXSCAN-STOP */
+ break;
+ case ANDROID_WIFI_CMD_BTCOEXMODE:
+ break;
+ case ANDROID_WIFI_CMD_SETSUSPENDOPT:
+ break;
+ case ANDROID_WIFI_CMD_SETBAND:
+ break;
+ case ANDROID_WIFI_CMD_GETBAND:
+ break;
+ case ANDROID_WIFI_CMD_COUNTRY:
+ bytes_written = android_set_cntry(net, command,
+ priv_cmd.total_len);
+ break;
+ case ANDROID_WIFI_CMD_P2P_DEV_ADDR:
+ bytes_written = android_get_p2p_addr(net, command,
+ priv_cmd.total_len);
+ break;
+ case ANDROID_WIFI_CMD_P2P_SET_NOA:
+ break;
+ case ANDROID_WIFI_CMD_P2P_GET_NOA:
+ break;
+ case ANDROID_WIFI_CMD_P2P_SET_PS:
+ break;
+ default:
+ DBG_88E("Unknown PRIVATE command %s - ignored\n", command);
+ snprintf(command, 3, "OK");
+ bytes_written = strlen("OK");
+ }
+
+response:
+ if (bytes_written >= 0) {
+ if ((bytes_written == 0) && (priv_cmd.total_len > 0))
+ command[0] = '\0';
+ if (bytes_written >= priv_cmd.total_len) {
+ DBG_88E("%s: bytes_written = %d\n", __func__,
+ bytes_written);
+ bytes_written = priv_cmd.total_len;
+ } else {
+ bytes_written++;
+ }
+ priv_cmd.used_len = bytes_written;
+ if (copy_to_user((char __user *)priv_cmd.buf, command,
+ bytes_written)) {
+ DBG_88E("%s: failed to copy data to user buffer\n",
+ __func__);
+ ret = -EFAULT;
+ }
+ } else {
+ ret = bytes_written;
+ }
+free:
+ kfree(command);
+ return ret;
+}
diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
new file mode 100644
index 0000000..f560d60
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
@@ -0,0 +1,516 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+
+#define pr_fmt(fmt) "R8188EU: " fmt
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <recv_osdep.h>
+#include <xmit_osdep.h>
+#include <hal_intf.h>
+#include <linux/usb.h>
+#include <linux/vmalloc.h>
+#include <mon.h>
+#include <osdep_intf.h>
+
+#include <usb_ops_linux.h>
+#include <rtw_ioctl.h>
+
+#include "rtl8188e_hal.h"
+
+#define USB_VENDER_ID_REALTEK 0x0bda
+
+/* DID_USB_v916_20130116 */
+static const struct usb_device_id rtw_usb_id_tbl[] = {
+ /*=== Realtek demoboard ===*/
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8179)}, /* 8188EUS */
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x0179)}, /* 8188ETV */
+ /*=== Customer ID ===*/
+ /****** 8188EUS ********/
+ {USB_DEVICE(0x056e, 0x4008)}, /* Elecom WDC-150SU2M */
+ {USB_DEVICE(0x07b8, 0x8179)}, /* Abocom - Abocom */
+ {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */
+ {USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */
+ {USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */
+ {USB_DEVICE(0x2001, 0x331B)}, /* D-Link DWA-121 rev B1 */
+ {USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */
+ {USB_DEVICE(0x2357, 0x0111)}, /* TP-Link TL-WN727N v5.21 */
+ {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */
+ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0xffef)}, /* Rosewill RNX-N150NUB */
+ {} /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, rtw_usb_id_tbl);
+
+static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf)
+{
+ int i;
+ struct dvobj_priv *pdvobjpriv;
+ struct usb_host_config *phost_conf;
+ struct usb_config_descriptor *pconf_desc;
+ struct usb_host_interface *phost_iface;
+ struct usb_interface_descriptor *piface_desc;
+ struct usb_endpoint_descriptor *pendp_desc;
+ struct usb_device *pusbd;
+
+ pdvobjpriv = kzalloc(sizeof(*pdvobjpriv), GFP_KERNEL);
+ if (!pdvobjpriv)
+ return NULL;
+
+ pdvobjpriv->pusbintf = usb_intf;
+ pusbd = interface_to_usbdev(usb_intf);
+ pdvobjpriv->pusbdev = pusbd;
+ usb_set_intfdata(usb_intf, pdvobjpriv);
+
+ pdvobjpriv->RtNumInPipes = 0;
+ pdvobjpriv->RtNumOutPipes = 0;
+
+ phost_conf = pusbd->actconfig;
+ pconf_desc = &phost_conf->desc;
+
+ phost_iface = usb_intf->cur_altsetting;
+ piface_desc = &phost_iface->desc;
+
+ pdvobjpriv->NumInterfaces = pconf_desc->bNumInterfaces;
+ pdvobjpriv->InterfaceNumber = piface_desc->bInterfaceNumber;
+
+ for (i = 0; i < piface_desc->bNumEndpoints; i++) {
+ int ep_num;
+
+ pendp_desc = &phost_iface->endpoint[i].desc;
+
+ ep_num = usb_endpoint_num(pendp_desc);
+
+ if (usb_endpoint_is_bulk_in(pendp_desc)) {
+ pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = ep_num;
+ pdvobjpriv->RtNumInPipes++;
+ } else if (usb_endpoint_is_int_in(pendp_desc)) {
+ pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = ep_num;
+ pdvobjpriv->RtNumInPipes++;
+ } else if (usb_endpoint_is_bulk_out(pendp_desc)) {
+ pdvobjpriv->RtOutPipe[pdvobjpriv->RtNumOutPipes] =
+ ep_num;
+ pdvobjpriv->RtNumOutPipes++;
+ }
+ }
+
+ if (pusbd->speed == USB_SPEED_HIGH)
+ pdvobjpriv->ishighspeed = true;
+ else
+ pdvobjpriv->ishighspeed = false;
+
+ mutex_init(&pdvobjpriv->usb_vendor_req_mutex);
+ usb_get_dev(pusbd);
+
+ return pdvobjpriv;
+}
+
+static void usb_dvobj_deinit(struct usb_interface *usb_intf)
+{
+ struct dvobj_priv *dvobj = usb_get_intfdata(usb_intf);
+
+ usb_set_intfdata(usb_intf, NULL);
+ if (dvobj) {
+ /* Modify condition for 92DU DMDP 2010.11.18, by Thomas */
+ if ((dvobj->NumInterfaces != 2 &&
+ dvobj->NumInterfaces != 3) ||
+ (dvobj->InterfaceNumber == 1)) {
+ if (interface_to_usbdev(usb_intf)->state !=
+ USB_STATE_NOTATTACHED) {
+ /* If we didn't unplug usb dongle and
+ * remove/insert module, driver fails
+ * on sitesurvey for the first time when
+ * device is up . Reset usb port for sitesurvey
+ * fail issue. */
+ pr_debug("usb attached..., try to reset usb device\n");
+ usb_reset_device(interface_to_usbdev(usb_intf));
+ }
+ }
+
+ mutex_destroy(&dvobj->usb_vendor_req_mutex);
+ kfree(dvobj);
+ }
+
+ usb_put_dev(interface_to_usbdev(usb_intf));
+}
+
+void usb_intf_stop(struct adapter *padapter)
+{
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+usb_intf_stop\n"));
+
+ /* disable_hw_interrupt */
+ if (!padapter->bSurpriseRemoved) {
+ /* device still exists, so driver can do i/o operation */
+ /* TODO: */
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_,
+ ("SurpriseRemoved == false\n"));
+ }
+
+ /* cancel in irp */
+ rtw_hal_inirp_deinit(padapter);
+
+ /* cancel out irp */
+ usb_write_port_cancel(padapter);
+
+ /* todo:cancel other irps */
+
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-usb_intf_stop\n"));
+}
+
+static void rtw_dev_unload(struct adapter *padapter)
+{
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_dev_unload\n"));
+
+ if (padapter->bup) {
+ pr_debug("===> rtw_dev_unload\n");
+ padapter->bDriverStopped = true;
+ if (padapter->xmitpriv.ack_tx)
+ rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_DRV_STOP);
+ /* s3. */
+ usb_intf_stop(padapter);
+ /* s4. */
+ if (!padapter->pwrctrlpriv.bInternalAutoSuspend)
+ rtw_stop_drv_threads(padapter);
+
+ /* s5. */
+ if (!padapter->bSurpriseRemoved) {
+ rtw_hal_deinit(padapter);
+ padapter->bSurpriseRemoved = true;
+ }
+
+ padapter->bup = false;
+ } else {
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_,
+ ("r871x_dev_unload():padapter->bup == false\n"));
+ }
+
+ pr_debug("<=== rtw_dev_unload\n");
+
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-rtw_dev_unload\n"));
+}
+
+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;
+ unsigned long start_time = jiffies;
+
+ pr_debug("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
+
+ if ((!padapter->bup) || (padapter->bDriverStopped) ||
+ (padapter->bSurpriseRemoved)) {
+ pr_debug("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);
+
+ mutex_lock(&pwrpriv->mutex_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)) {
+ pr_debug("%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.ssid_length,
+ pmlmepriv->assoc_ssid.ssid_length);
+
+ pmlmepriv->to_roaming = 1;
+ }
+ /* s2-2. indicate disconnect to os */
+ rtw_indicate_disconnect(padapter);
+ /* s2-3. */
+ rtw_free_assoc_resources(padapter);
+ /* s2-4. */
+ rtw_free_network_queue(padapter, true);
+
+ rtw_dev_unload(padapter);
+ mutex_unlock(&pwrpriv->mutex_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:
+ pr_debug("<=== %s .............. in %dms\n", __func__,
+ jiffies_to_msecs(jiffies - start_time));
+
+ return 0;
+}
+
+static int rtw_resume_process(struct adapter *padapter)
+{
+ struct net_device *pnetdev;
+ struct pwrctrl_priv *pwrpriv = NULL;
+ int ret = -1;
+ unsigned long start_time = jiffies;
+
+ pr_debug("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
+
+ if (padapter) {
+ pnetdev = padapter->pnetdev;
+ pwrpriv = &padapter->pwrctrlpriv;
+ } else {
+ goto exit;
+ }
+
+ mutex_lock(&pwrpriv->mutex_lock);
+ rtw_reset_drv_sw(padapter);
+ pwrpriv->bkeepfwalive = false;
+
+ pr_debug("bkeepfwalive(%x)\n", pwrpriv->bkeepfwalive);
+ if (netdev_open(pnetdev) != 0) {
+ mutex_unlock(&pwrpriv->mutex_lock);
+ goto exit;
+ }
+
+ netif_device_attach(pnetdev);
+ netif_carrier_on(pnetdev);
+
+ mutex_unlock(&pwrpriv->mutex_lock);
+
+ rtw_roaming(padapter, NULL);
+
+ ret = 0;
+exit:
+ if (pwrpriv)
+ pwrpriv->bInSuspend = false;
+ pr_debug("<=== %s return %d.............. in %dms\n", __func__,
+ ret, jiffies_to_msecs(jiffies - start_time));
+
+ return ret;
+}
+
+static int rtw_resume(struct usb_interface *pusb_intf)
+{
+ struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
+ struct adapter *padapter = dvobj->if1;
+
+ return rtw_resume_process(padapter);
+}
+
+/*
+ * drv_init() - a device potentially for us
+ *
+ * notes: drv_init() is called when the bus driver has located
+ * a card for us to support.
+ * We accept the new device by returning 0.
+ */
+
+static struct adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj,
+ struct usb_interface *pusb_intf, const struct usb_device_id *pdid)
+{
+ struct adapter *padapter = NULL;
+ struct net_device *pnetdev = NULL;
+ struct net_device *pmondev;
+ int status = _FAIL;
+
+ padapter = vzalloc(sizeof(*padapter));
+ if (!padapter)
+ goto exit;
+ padapter->dvobj = dvobj;
+ dvobj->if1 = padapter;
+
+ padapter->bDriverStopped = true;
+ mutex_init(&padapter->hw_init_mutex);
+
+ pnetdev = rtw_init_netdev(padapter);
+ if (!pnetdev)
+ goto free_adapter;
+ SET_NETDEV_DEV(pnetdev, dvobj_to_dev(dvobj));
+ padapter = rtw_netdev_priv(pnetdev);
+
+ if (padapter->registrypriv.monitor_enable) {
+ pmondev = rtl88eu_mon_init();
+ if (!pmondev)
+ netdev_warn(pnetdev, "Failed to initialize monitor interface");
+ padapter->pmondev = pmondev;
+ }
+
+ padapter->HalData = kzalloc(sizeof(struct hal_data_8188e), GFP_KERNEL);
+ if (!padapter->HalData) {
+ DBG_88E("Failed to allocate memory for HAL data\n");
+ goto free_adapter;
+ }
+
+ /* step read_chip_version */
+ rtw_hal_read_chip_version(padapter);
+
+ /* step usb endpoint mapping */
+ rtw_hal_chip_configure(padapter);
+
+ /* step read efuse/eeprom data and get mac_addr */
+ rtw_hal_read_chip_info(padapter);
+
+ /* step 5. */
+ if (rtw_init_drv_sw(padapter) == _FAIL) {
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_,
+ ("Initialize driver software resource Failed!\n"));
+ goto free_hal_data;
+ }
+
+#ifdef CONFIG_PM
+ if (padapter->pwrctrlpriv.bSupportRemoteWakeup) {
+ dvobj->pusbdev->do_remote_wakeup = 1;
+ pusb_intf->needs_remote_wakeup = 1;
+ device_init_wakeup(&pusb_intf->dev, 1);
+ pr_debug("\n padapter->pwrctrlpriv.bSupportRemoteWakeup~~~~~~\n");
+ pr_debug("\n padapter->pwrctrlpriv.bSupportRemoteWakeup~~~[%d]~~~\n",
+ device_may_wakeup(&pusb_intf->dev));
+ }
+#endif
+
+ /* 2012-07-11 Move here to prevent the 8723AS-VAU BT auto
+ * suspend influence */
+ if (usb_autopm_get_interface(pusb_intf) < 0)
+ pr_debug("can't get autopm:\n");
+
+ /* alloc dev name after read efuse. */
+ rtw_init_netdev_name(pnetdev, padapter->registrypriv.ifname);
+ rtw_macaddr_cfg(padapter->eeprompriv.mac_addr);
+ memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN);
+ pr_debug("MAC Address from pnetdev->dev_addr = %pM\n",
+ pnetdev->dev_addr);
+
+ /* step 6. Tell the network stack we exist */
+ if (register_netdev(pnetdev) != 0) {
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("register_netdev() failed\n"));
+ goto free_hal_data;
+ }
+
+ pr_debug("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n"
+ , padapter->bDriverStopped
+ , padapter->bSurpriseRemoved
+ , padapter->bup
+ , padapter->hw_init_completed
+ );
+
+ status = _SUCCESS;
+
+free_hal_data:
+ if (status != _SUCCESS)
+ kfree(padapter->HalData);
+free_adapter:
+ if (status != _SUCCESS) {
+ if (pnetdev)
+ rtw_free_netdev(pnetdev);
+ else
+ vfree(padapter);
+ padapter = NULL;
+ }
+exit:
+ return padapter;
+}
+
+static void rtw_usb_if1_deinit(struct adapter *if1)
+{
+ struct net_device *pnetdev = if1->pnetdev;
+ struct mlme_priv *pmlmepriv = &if1->mlmepriv;
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED))
+ rtw_disassoc_cmd(if1, 0, false);
+
+#ifdef CPTCFG_88EU_AP_MODE
+ free_mlme_ap_info(if1);
+#endif
+
+ if (pnetdev)
+ unregister_netdev(pnetdev); /* will call netdev_close() */
+
+ rtl88eu_mon_deinit(if1->pmondev);
+ rtw_cancel_all_timer(if1);
+
+ rtw_dev_unload(if1);
+ pr_debug("+r871xu_dev_remove, hw_init_completed=%d\n",
+ if1->hw_init_completed);
+ rtw_free_drv_sw(if1);
+ rtw_free_netdev(pnetdev);
+}
+
+static int rtw_drv_init(struct usb_interface *pusb_intf, const struct usb_device_id *pdid)
+{
+ struct adapter *if1 = NULL;
+ struct dvobj_priv *dvobj;
+
+ /* Initialize dvobj_priv */
+ dvobj = usb_dvobj_init(pusb_intf);
+ if (!dvobj) {
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_,
+ ("initialize device object priv Failed!\n"));
+ goto exit;
+ }
+
+ if1 = rtw_usb_if1_init(dvobj, pusb_intf, pdid);
+ if (!if1) {
+ pr_debug("rtw_init_primarystruct adapter Failed!\n");
+ goto free_dvobj;
+ }
+
+ return 0;
+
+free_dvobj:
+ usb_dvobj_deinit(pusb_intf);
+exit:
+ return -ENODEV;
+}
+
+/*
+ * dev_remove() - our device is being removed
+*/
+/* rmmod module & unplug(SurpriseRemoved) will call r871xu_dev_remove() => how to recognize both */
+static void rtw_dev_remove(struct usb_interface *pusb_intf)
+{
+ struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
+ struct adapter *padapter = dvobj->if1;
+
+ pr_debug("+rtw_dev_remove\n");
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+dev_remove()\n"));
+
+ if (!pusb_intf->unregistering)
+ padapter->bSurpriseRemoved = true;
+
+ rtw_pm_set_ips(padapter, IPS_NONE);
+ rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
+
+ LeaveAllPowerSaveMode(padapter);
+
+ rtw_usb_if1_deinit(padapter);
+
+ usb_dvobj_deinit(pusb_intf);
+
+ RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-dev_remove()\n"));
+ pr_debug("-r871xu_dev_remove, done\n");
+}
+
+static struct usb_driver rtl8188e_usb_drv = {
+ .name = "r8188eu",
+ .probe = rtw_drv_init,
+ .disconnect = rtw_dev_remove,
+ .id_table = rtw_usb_id_tbl,
+ .suspend = rtw_suspend,
+ .resume = rtw_resume,
+ .reset_resume = rtw_resume,
+};
+
+module_usb_driver(rtl8188e_usb_drv)
diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
new file mode 100644
index 0000000..36604a0
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c
@@ -0,0 +1,814 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _USB_OPS_LINUX_C_
+
+#include <drv_types.h>
+#include <recv_osdep.h>
+#include <rtw_sreset.h>
+
+static void interrupt_handler_8188eu(struct adapter *adapt, u16 pkt_len, u8 *pbuf)
+{
+ struct hal_data_8188e *haldata = adapt->HalData;
+
+ if (pkt_len != INTERRUPT_MSG_FORMAT_LEN) {
+ DBG_88E("%s Invalid interrupt content length (%d)!\n", __func__, pkt_len);
+ return;
+ }
+
+ /* HISR */
+ memcpy(&haldata->IntArray[0], &pbuf[USB_INTR_CONTENT_HISR_OFFSET], 4);
+ memcpy(&haldata->IntArray[1], &pbuf[USB_INTR_CONTENT_HISRE_OFFSET], 4);
+
+ /* C2H Event */
+ if (pbuf[0] != 0)
+ memcpy(&haldata->C2hArray[0],
+ &pbuf[USB_INTR_CONTENT_C2H_OFFSET], 16);
+}
+
+static int recvbuf2recvframe(struct adapter *adapt, struct sk_buff *pskb)
+{
+ u8 *pbuf;
+ u8 shift_sz = 0;
+ u16 pkt_cnt;
+ u32 pkt_offset, skb_len, alloc_sz;
+ s32 transfer_len;
+ struct recv_stat *prxstat;
+ struct phy_stat *pphy_status = NULL;
+ struct sk_buff *pkt_copy = NULL;
+ struct recv_frame *precvframe = NULL;
+ struct rx_pkt_attrib *pattrib = NULL;
+ struct hal_data_8188e *haldata = adapt->HalData;
+ struct recv_priv *precvpriv = &adapt->recvpriv;
+ struct __queue *pfree_recv_queue = &precvpriv->free_recv_queue;
+
+ transfer_len = (s32)pskb->len;
+ pbuf = pskb->data;
+
+ prxstat = (struct recv_stat *)pbuf;
+ pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff;
+
+ do {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
+ ("%s: rxdesc=offsset 0:0x%08x, 4:0x%08x, 8:0x%08x, C:0x%08x\n",
+ __func__, prxstat->rxdw0, prxstat->rxdw1,
+ prxstat->rxdw2, prxstat->rxdw4));
+
+ prxstat = (struct recv_stat *)pbuf;
+
+ precvframe = rtw_alloc_recvframe(pfree_recv_queue);
+ if (!precvframe) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
+ ("%s: precvframe==NULL\n", __func__));
+ DBG_88E("%s()-%d: rtw_alloc_recvframe() failed! RX Drop!\n", __func__, __LINE__);
+ goto _exit_recvbuf2recvframe;
+ }
+
+ INIT_LIST_HEAD(&precvframe->list);
+
+ update_recvframe_attrib_88e(precvframe, prxstat);
+
+ pattrib = &precvframe->attrib;
+
+ if ((pattrib->crc_err) || (pattrib->icv_err)) {
+ DBG_88E("%s: RX Warning! crc_err=%d icv_err=%d, skip!\n", __func__, pattrib->crc_err, pattrib->icv_err);
+
+ rtw_free_recvframe(precvframe, pfree_recv_queue);
+ goto _exit_recvbuf2recvframe;
+ }
+
+ if ((pattrib->physt) && (pattrib->pkt_rpt_type == NORMAL_RX))
+ pphy_status = (struct phy_stat *)(pbuf + RXDESC_OFFSET);
+
+ pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz + pattrib->shift_sz + pattrib->pkt_len;
+
+ if ((pattrib->pkt_len <= 0) || (pkt_offset > transfer_len)) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
+ ("%s: pkt_len<=0\n", __func__));
+ DBG_88E("%s()-%d: RX Warning!,pkt_len<=0 or pkt_offset> transfer_len\n", __func__, __LINE__);
+ rtw_free_recvframe(precvframe, pfree_recv_queue);
+ goto _exit_recvbuf2recvframe;
+ }
+
+ /* Modified by Albert 20101213 */
+ /* For 8 bytes IP header alignment. */
+ if (pattrib->qos) /* Qos data, wireless lan header length is 26 */
+ shift_sz = 6;
+ else
+ shift_sz = 0;
+
+ skb_len = pattrib->pkt_len;
+
+ /* for first fragment packet, driver need allocate 1536+drvinfo_sz+RXDESC_SIZE to defrag packet. */
+ /* modify alloc_sz for recvive crc error packet by thomas 2011-06-02 */
+ if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) {
+ if (skb_len <= 1650)
+ alloc_sz = 1664;
+ else
+ alloc_sz = skb_len + 14;
+ } else {
+ alloc_sz = skb_len;
+ /* 6 is for IP header 8 bytes alignment in QoS packet case. */
+ /* 8 is for skb->data 4 bytes alignment. */
+ alloc_sz += 14;
+ }
+
+ pkt_copy = netdev_alloc_skb(adapt->pnetdev, alloc_sz);
+ if (pkt_copy) {
+ pkt_copy->dev = adapt->pnetdev;
+ precvframe->pkt = pkt_copy;
+ skb_reserve(pkt_copy, 8 - ((size_t)(pkt_copy->data) & 7));/* force pkt_copy->data at 8-byte alignment address */
+ skb_reserve(pkt_copy, shift_sz);/* force ip_hdr at 8-byte alignment address according to shift_sz. */
+ skb_put_data(pkt_copy, (pbuf + pattrib->drvinfo_sz + RXDESC_SIZE), skb_len);
+ } else {
+ DBG_88E("%s: alloc_skb fail , drop frag frame\n",
+ __func__);
+ rtw_free_recvframe(precvframe, pfree_recv_queue);
+ goto _exit_recvbuf2recvframe;
+ }
+
+ switch (haldata->UsbRxAggMode) {
+ case USB_RX_AGG_DMA:
+ case USB_RX_AGG_MIX:
+ pkt_offset = (u16)round_up(pkt_offset, 128);
+ break;
+ case USB_RX_AGG_USB:
+ pkt_offset = (u16)round_up(pkt_offset, 4);
+ break;
+ case USB_RX_AGG_DISABLE:
+ default:
+ break;
+ }
+ if (pattrib->pkt_rpt_type == NORMAL_RX) { /* Normal rx packet */
+ if (pattrib->physt)
+ update_recvframe_phyinfo_88e(precvframe, pphy_status);
+ if (rtw_recv_entry(precvframe) != _SUCCESS) {
+ RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
+ ("%s: rtw_recv_entry(precvframe) != _SUCCESS\n",
+ __func__));
+ }
+ } else if (pattrib->pkt_rpt_type == TX_REPORT1) {
+ /* CCX-TXRPT ack for xmit mgmt frames. */
+ handle_txrpt_ccx_88e(adapt, precvframe->pkt->data);
+ rtw_free_recvframe(precvframe, pfree_recv_queue);
+ } else if (pattrib->pkt_rpt_type == TX_REPORT2) {
+ ODM_RA_TxRPT2Handle_8188E(&haldata->odmpriv,
+ precvframe->pkt->data,
+ pattrib->pkt_len,
+ pattrib->MacIDValidEntry[0],
+ pattrib->MacIDValidEntry[1]);
+ rtw_free_recvframe(precvframe, pfree_recv_queue);
+ } else if (pattrib->pkt_rpt_type == HIS_REPORT) {
+ interrupt_handler_8188eu(adapt, pattrib->pkt_len, precvframe->pkt->data);
+ rtw_free_recvframe(precvframe, pfree_recv_queue);
+ }
+ pkt_cnt--;
+ transfer_len -= pkt_offset;
+ pbuf += pkt_offset;
+ precvframe = NULL;
+ pkt_copy = NULL;
+
+ if (transfer_len > 0 && pkt_cnt == 0)
+ pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff;
+
+ } while ((transfer_len > 0) && (pkt_cnt > 0));
+
+_exit_recvbuf2recvframe:
+
+ return _SUCCESS;
+}
+
+unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr)
+{
+ unsigned int pipe = 0, ep_num = 0;
+ struct usb_device *pusbd = pdvobj->pusbdev;
+
+ if (addr == RECV_BULK_IN_ADDR) {
+ pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[0]);
+ } else if (addr == RECV_INT_IN_ADDR) {
+ pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[1]);
+ } else if (addr < HW_QUEUE_ENTRY) {
+ ep_num = pdvobj->Queue2Pipe[addr];
+ pipe = usb_sndbulkpipe(pusbd, ep_num);
+ }
+
+ return pipe;
+}
+
+static int usbctrl_vendorreq(struct adapter *adapt, u8 request, u16 value, u16 index, void *pdata, u16 len, u8 requesttype)
+{
+ struct dvobj_priv *dvobjpriv = adapter_to_dvobj(adapt);
+ struct usb_device *udev = dvobjpriv->pusbdev;
+ unsigned int pipe;
+ int status = 0;
+ u8 reqtype;
+ u8 *pIo_buf;
+ int vendorreq_times = 0;
+
+ if ((adapt->bSurpriseRemoved) || (adapt->pwrctrlpriv.pnp_bstop_trx)) {
+ RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+ ("%s:(adapt->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n",
+ __func__));
+ status = -EPERM;
+ goto exit;
+ }
+
+ if (len > MAX_VENDOR_REQ_CMD_SIZE) {
+ DBG_88E("[%s] Buffer len error ,vendor request failed\n", __func__);
+ status = -EINVAL;
+ goto exit;
+ }
+
+ if (mutex_lock_interruptible(&dvobjpriv->usb_vendor_req_mutex)) {
+ status = -ERESTARTSYS;
+ goto exit;
+ }
+
+ /* Acquire IO memory for vendorreq */
+ pIo_buf = kmalloc(MAX_USB_IO_CTL_SIZE, GFP_ATOMIC);
+
+ if (!pIo_buf) {
+ status = -ENOMEM;
+ goto release_mutex;
+ }
+
+ while (++vendorreq_times <= MAX_USBCTRL_VENDORREQ_TIMES) {
+ memset(pIo_buf, 0, len);
+
+ if (requesttype == 0x01) {
+ pipe = usb_rcvctrlpipe(udev, 0);/* read_in */
+ reqtype = REALTEK_USB_VENQT_READ;
+ } else {
+ pipe = usb_sndctrlpipe(udev, 0);/* write_out */
+ reqtype = REALTEK_USB_VENQT_WRITE;
+ memcpy(pIo_buf, pdata, len);
+ }
+
+ status = usb_control_msg(udev, pipe, request, reqtype, value, index, pIo_buf, len, RTW_USB_CONTROL_MSG_TIMEOUT);
+
+ if (status == len) { /* Success this control transfer. */
+ if (requesttype == 0x01)
+ memcpy(pdata, pIo_buf, len);
+ } else { /* error cases */
+ DBG_88E("reg 0x%x, usb %s %u fail, status:%d value=0x%x, vendorreq_times:%d\n",
+ value, (requesttype == 0x01) ? "read" : "write",
+ len, status, *(u32 *)pdata, vendorreq_times);
+
+ if (status < 0) {
+ if (status == (-ESHUTDOWN) || status == -ENODEV)
+ adapt->bSurpriseRemoved = true;
+ else
+ adapt->HalData->srestpriv.wifi_error_status = USB_VEN_REQ_CMD_FAIL;
+ } else { /* status != len && status >= 0 */
+ if (status > 0) {
+ if (requesttype == 0x01) {
+ /* For Control read transfer, we have to copy the read data from pIo_buf to pdata. */
+ memcpy(pdata, pIo_buf, len);
+ }
+ }
+ }
+ }
+
+ /* firmware download is checksummed, don't retry */
+ if ((value >= FW_8188E_START_ADDRESS && value <= FW_8188E_END_ADDRESS) || status == len)
+ break;
+ }
+ kfree(pIo_buf);
+
+release_mutex:
+ mutex_unlock(&dvobjpriv->usb_vendor_req_mutex);
+exit:
+ return status;
+}
+
+u8 usb_read8(struct adapter *adapter, u32 addr)
+{
+ u8 request;
+ u8 requesttype;
+ u16 wvalue;
+ u16 index;
+ u16 len;
+ u8 data = 0;
+
+ request = 0x05;
+ requesttype = 0x01;/* read_in */
+ index = 0;/* n/a */
+
+ wvalue = (u16)(addr & 0x0000ffff);
+ len = 1;
+
+ usbctrl_vendorreq(adapter, request, wvalue, index, &data, len, requesttype);
+
+ return data;
+}
+
+u16 usb_read16(struct adapter *adapter, u32 addr)
+{
+ u8 request;
+ u8 requesttype;
+ u16 wvalue;
+ u16 index;
+ u16 len;
+ __le32 data;
+
+ request = 0x05;
+ requesttype = 0x01;/* read_in */
+ index = 0;/* n/a */
+ wvalue = (u16)(addr & 0x0000ffff);
+ len = 2;
+ usbctrl_vendorreq(adapter, request, wvalue, index, &data, len, requesttype);
+
+ return (u16)(le32_to_cpu(data) & 0xffff);
+}
+
+u32 usb_read32(struct adapter *adapter, u32 addr)
+{
+ u8 request;
+ u8 requesttype;
+ u16 wvalue;
+ u16 index;
+ u16 len;
+ __le32 data;
+
+ request = 0x05;
+ requesttype = 0x01;/* read_in */
+ index = 0;/* n/a */
+
+ wvalue = (u16)(addr & 0x0000ffff);
+ len = 4;
+
+ usbctrl_vendorreq(adapter, request, wvalue, index, &data, len, requesttype);
+
+ return le32_to_cpu(data);
+}
+
+static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs)
+{
+ struct recv_buf *precvbuf = (struct recv_buf *)purb->context;
+ struct adapter *adapt = (struct adapter *)precvbuf->adapter;
+ struct recv_priv *precvpriv = &adapt->recvpriv;
+
+ RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("%s!!!\n", __func__));
+
+ if (adapt->bSurpriseRemoved || adapt->bDriverStopped || adapt->bReadPortCancel) {
+ RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+ ("%s:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n",
+ __func__, adapt->bDriverStopped,
+ adapt->bSurpriseRemoved));
+
+ precvbuf->reuse = true;
+ DBG_88E("%s() RX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bReadPortCancel(%d)\n",
+ __func__, adapt->bDriverStopped,
+ adapt->bSurpriseRemoved, adapt->bReadPortCancel);
+ return;
+ }
+
+ if (purb->status == 0) { /* SUCCESS */
+ if ((purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)) {
+ RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+ ("%s: (purb->actual_length > MAX_RECVBUF_SZ) || (purb->actual_length < RXDESC_SIZE)\n",
+ __func__));
+ precvbuf->reuse = true;
+ usb_read_port(adapt, RECV_BULK_IN_ADDR, precvbuf);
+ DBG_88E("%s()-%d: RX Warning!\n", __func__, __LINE__);
+ } else {
+ skb_put(precvbuf->pskb, purb->actual_length);
+ skb_queue_tail(&precvpriv->rx_skb_queue, precvbuf->pskb);
+
+ if (skb_queue_len(&precvpriv->rx_skb_queue) <= 1)
+ tasklet_schedule(&precvpriv->recv_tasklet);
+
+ precvbuf->pskb = NULL;
+ precvbuf->reuse = false;
+ usb_read_port(adapt, RECV_BULK_IN_ADDR, precvbuf);
+ }
+ } else {
+ RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+ ("%s : purb->status(%d) != 0\n",
+ __func__, purb->status));
+
+ DBG_88E("###=> %s => urb status(%d)\n", __func__, purb->status);
+ skb_put(precvbuf->pskb, purb->actual_length);
+ precvbuf->pskb = NULL;
+
+ switch (purb->status) {
+ case -EINVAL:
+ case -EPIPE:
+ case -ENODEV:
+ case -ESHUTDOWN:
+ adapt->bSurpriseRemoved = true;
+ /* fall through */
+ case -ENOENT:
+ adapt->bDriverStopped = true;
+ RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+ ("%s:bDriverStopped=true\n", __func__));
+ break;
+ case -EPROTO:
+ case -EOVERFLOW:
+ adapt->HalData->srestpriv.wifi_error_status = USB_READ_PORT_FAIL;
+ precvbuf->reuse = true;
+ usb_read_port(adapt, RECV_BULK_IN_ADDR, precvbuf);
+ break;
+ case -EINPROGRESS:
+ DBG_88E("ERROR: URB IS IN PROGRESS!\n");
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+u32 usb_read_port(struct adapter *adapter, u32 addr, struct recv_buf *precvbuf)
+{
+ struct urb *purb = NULL;
+ struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter);
+ struct recv_priv *precvpriv = &adapter->recvpriv;
+ struct usb_device *pusbd = pdvobj->pusbdev;
+ int err;
+ unsigned int pipe;
+ u32 ret = _SUCCESS;
+
+ if (adapter->bDriverStopped || adapter->bSurpriseRemoved ||
+ adapter->pwrctrlpriv.pnp_bstop_trx) {
+ RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+ ("%s:(adapt->bDriverStopped ||adapt->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n",
+ __func__));
+ return _FAIL;
+ }
+
+ if (!precvbuf) {
+ RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+ ("%s:precvbuf==NULL\n", __func__));
+ return _FAIL;
+ }
+
+ if (!precvbuf->reuse || !precvbuf->pskb) {
+ precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);
+ if (precvbuf->pskb)
+ precvbuf->reuse = true;
+ }
+
+ /* re-assign for linux based on skb */
+ if (!precvbuf->reuse || !precvbuf->pskb) {
+ precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ);
+ if (!precvbuf->pskb) {
+ RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("init_recvbuf(): alloc_skb fail!\n"));
+ DBG_88E("#### %s() alloc_skb fail!#####\n", __func__);
+ return _FAIL;
+ }
+ } else { /* reuse skb */
+ precvbuf->reuse = false;
+ }
+
+ purb = precvbuf->purb;
+
+ /* translate DMA FIFO addr to pipehandle */
+ pipe = ffaddr2pipehdl(pdvobj, addr);
+
+ usb_fill_bulk_urb(purb, pusbd, pipe,
+ precvbuf->pskb->data,
+ MAX_RECVBUF_SZ,
+ usb_read_port_complete,
+ precvbuf);/* context is precvbuf */
+
+ err = usb_submit_urb(purb, GFP_ATOMIC);
+ if ((err) && (err != (-EPERM))) {
+ RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+ ("cannot submit rx in-token(err=0x%.8x), URB_STATUS =0x%.8x",
+ err, purb->status));
+ DBG_88E("cannot submit rx in-token(err = 0x%08x),urb_status = %d\n",
+ err, purb->status);
+ ret = _FAIL;
+ }
+
+ return ret;
+}
+
+void rtw_hal_inirp_deinit(struct adapter *padapter)
+{
+ int i;
+ struct recv_buf *precvbuf;
+
+ precvbuf = padapter->recvpriv.precv_buf;
+
+ DBG_88E("%s\n", __func__);
+
+ padapter->bReadPortCancel = true;
+
+ for (i = 0; i < NR_RECVBUFF; i++) {
+ precvbuf->reuse = true;
+ if (precvbuf->purb)
+ usb_kill_urb(precvbuf->purb);
+ precvbuf++;
+ }
+}
+
+int usb_write8(struct adapter *adapter, u32 addr, u8 val)
+{
+ u8 request;
+ u8 requesttype;
+ u16 wvalue;
+ u16 index;
+ u16 len;
+ u8 data;
+
+ request = 0x05;
+ requesttype = 0x00;/* write_out */
+ index = 0;/* n/a */
+ wvalue = (u16)(addr & 0x0000ffff);
+ len = 1;
+ data = val;
+ return usbctrl_vendorreq(adapter, request, wvalue,
+ index, &data, len, requesttype);
+}
+
+int usb_write16(struct adapter *adapter, u32 addr, u16 val)
+{
+ u8 request;
+ u8 requesttype;
+ u16 wvalue;
+ u16 index;
+ u16 len;
+ __le32 data;
+
+ request = 0x05;
+ requesttype = 0x00;/* write_out */
+ index = 0;/* n/a */
+
+ wvalue = (u16)(addr & 0x0000ffff);
+ len = 2;
+
+ data = cpu_to_le32(val & 0x0000ffff);
+
+ return usbctrl_vendorreq(adapter, request, wvalue,
+ index, &data, len, requesttype);
+}
+
+int usb_write32(struct adapter *adapter, u32 addr, u32 val)
+{
+ u8 request;
+ u8 requesttype;
+ u16 wvalue;
+ u16 index;
+ u16 len;
+ __le32 data;
+
+ request = 0x05;
+ requesttype = 0x00;/* write_out */
+ index = 0;/* n/a */
+
+ wvalue = (u16)(addr & 0x0000ffff);
+ len = 4;
+ data = cpu_to_le32(val);
+
+ return usbctrl_vendorreq(adapter, request, wvalue,
+ index, &data, len, requesttype);
+}
+
+static void usb_write_port_complete(struct urb *purb, struct pt_regs *regs)
+{
+ struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context;
+ struct adapter *padapter = pxmitbuf->padapter;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+ switch (pxmitbuf->flags) {
+ case VO_QUEUE_INX:
+ pxmitpriv->voq_cnt--;
+ break;
+ case VI_QUEUE_INX:
+ pxmitpriv->viq_cnt--;
+ break;
+ case BE_QUEUE_INX:
+ pxmitpriv->beq_cnt--;
+ break;
+ case BK_QUEUE_INX:
+ pxmitpriv->bkq_cnt--;
+ break;
+ case HIGH_QUEUE_INX:
+#ifdef CPTCFG_88EU_AP_MODE
+ rtw_chk_hi_queue_cmd(padapter);
+#endif
+ break;
+ default:
+ break;
+ }
+
+ if (padapter->bSurpriseRemoved || padapter->bDriverStopped ||
+ padapter->bWritePortCancel) {
+ RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+ ("%s:bDriverStopped(%d) OR bSurpriseRemoved(%d)",
+ __func__, padapter->bDriverStopped,
+ padapter->bSurpriseRemoved));
+ DBG_88E("%s(): TX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bWritePortCancel(%d) pxmitbuf->ext_tag(%x)\n",
+ __func__, padapter->bDriverStopped,
+ padapter->bSurpriseRemoved, padapter->bReadPortCancel,
+ pxmitbuf->ext_tag);
+
+ goto check_completion;
+ }
+
+ if (purb->status) {
+ RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+ ("%s : purb->status(%d) != 0\n",
+ __func__, purb->status));
+ DBG_88E("###=> %s status(%d)\n", __func__, purb->status);
+ if ((purb->status == -EPIPE) || (purb->status == -EPROTO)) {
+ sreset_set_wifi_error_status(padapter, USB_WRITE_PORT_FAIL);
+ } else if (purb->status == -EINPROGRESS) {
+ RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+ ("%s: EINPROGRESS\n", __func__));
+ goto check_completion;
+ } else if (purb->status == -ENOENT) {
+ DBG_88E("%s: -ENOENT\n", __func__);
+ goto check_completion;
+ } else if (purb->status == -ECONNRESET) {
+ DBG_88E("%s: -ECONNRESET\n", __func__);
+ goto check_completion;
+ } else if (purb->status == -ESHUTDOWN) {
+ RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+ ("%s: ESHUTDOWN\n", __func__));
+ padapter->bDriverStopped = true;
+ RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+ ("%s:bDriverStopped = true\n", __func__));
+ goto check_completion;
+ } else {
+ padapter->bSurpriseRemoved = true;
+ DBG_88E("bSurpriseRemoved = true\n");
+ RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+ ("%s:bSurpriseRemoved = true\n", __func__));
+ goto check_completion;
+ }
+ }
+
+check_completion:
+ rtw_sctx_done_err(&pxmitbuf->sctx,
+ purb->status ? RTW_SCTX_DONE_WRITE_PORT_ERR :
+ RTW_SCTX_DONE_SUCCESS);
+
+ rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
+
+ tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
+}
+
+u32 usb_write_port(struct adapter *padapter, u32 addr, u32 cnt, struct xmit_buf *xmitbuf)
+{
+ unsigned long irqL;
+ unsigned int pipe;
+ int status;
+ u32 ret = _FAIL;
+ struct urb *purb = NULL;
+ struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct xmit_frame *pxmitframe = (struct xmit_frame *)xmitbuf->priv_data;
+ struct usb_device *pusbd = pdvobj->pusbdev;
+
+ RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("+%s\n", __func__));
+
+ if ((padapter->bDriverStopped) || (padapter->bSurpriseRemoved) ||
+ (padapter->pwrctrlpriv.pnp_bstop_trx)) {
+ RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+ ("%s:( padapter->bDriverStopped ||padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n",
+ __func__));
+ rtw_sctx_done_err(&xmitbuf->sctx, RTW_SCTX_DONE_TX_DENY);
+ goto exit;
+ }
+
+ spin_lock_irqsave(&pxmitpriv->lock, irqL);
+
+ switch (addr) {
+ case VO_QUEUE_INX:
+ pxmitpriv->voq_cnt++;
+ xmitbuf->flags = VO_QUEUE_INX;
+ break;
+ case VI_QUEUE_INX:
+ pxmitpriv->viq_cnt++;
+ xmitbuf->flags = VI_QUEUE_INX;
+ break;
+ case BE_QUEUE_INX:
+ pxmitpriv->beq_cnt++;
+ xmitbuf->flags = BE_QUEUE_INX;
+ break;
+ case BK_QUEUE_INX:
+ pxmitpriv->bkq_cnt++;
+ xmitbuf->flags = BK_QUEUE_INX;
+ break;
+ case HIGH_QUEUE_INX:
+ xmitbuf->flags = HIGH_QUEUE_INX;
+ break;
+ default:
+ xmitbuf->flags = MGT_QUEUE_INX;
+ break;
+ }
+
+ spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
+
+ purb = xmitbuf->pxmit_urb[0];
+
+ /* translate DMA FIFO addr to pipehandle */
+ pipe = ffaddr2pipehdl(pdvobj, addr);
+
+ usb_fill_bulk_urb(purb, pusbd, pipe,
+ pxmitframe->buf_addr, /* xmitbuf->pbuf */
+ cnt,
+ usb_write_port_complete,
+ xmitbuf);/* context is xmitbuf */
+
+ status = usb_submit_urb(purb, GFP_ATOMIC);
+ if (status) {
+ rtw_sctx_done_err(&xmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
+ DBG_88E("%s, status =%d\n", __func__, status);
+ RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
+ ("%s(): usb_submit_urb, status =%x\n",
+ __func__, status));
+
+ switch (status) {
+ case -ENODEV:
+ padapter->bDriverStopped = true;
+ break;
+ default:
+ break;
+ }
+ goto exit;
+ }
+
+ ret = _SUCCESS;
+
+/* We add the URB_ZERO_PACKET flag to urb so that the host will send the zero packet automatically. */
+
+ RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("-%s\n", __func__));
+
+exit:
+ if (ret != _SUCCESS)
+ rtw_free_xmitbuf(pxmitpriv, xmitbuf);
+ return ret;
+}
+
+void usb_write_port_cancel(struct adapter *padapter)
+{
+ int i, j;
+ struct xmit_buf *pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmitbuf;
+
+ DBG_88E("%s\n", __func__);
+
+ padapter->bWritePortCancel = true;
+
+ for (i = 0; i < NR_XMITBUFF; i++) {
+ for (j = 0; j < 8; j++) {
+ if (pxmitbuf->pxmit_urb[j])
+ usb_kill_urb(pxmitbuf->pxmit_urb[j]);
+ }
+ pxmitbuf++;
+ }
+
+ pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmit_extbuf;
+ for (i = 0; i < NR_XMIT_EXTBUFF; i++) {
+ for (j = 0; j < 8; j++) {
+ if (pxmitbuf->pxmit_urb[j])
+ usb_kill_urb(pxmitbuf->pxmit_urb[j]);
+ }
+ pxmitbuf++;
+ }
+}
+
+void rtl8188eu_recv_tasklet(void *priv)
+{
+ struct sk_buff *pskb;
+ struct adapter *adapt = priv;
+ struct recv_priv *precvpriv = &adapt->recvpriv;
+
+ while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue))) {
+ if ((adapt->bDriverStopped) || (adapt->bSurpriseRemoved)) {
+ DBG_88E("recv_tasklet => bDriverStopped or bSurpriseRemoved\n");
+ dev_kfree_skb_any(pskb);
+ break;
+ }
+ recvbuf2recvframe(adapt, pskb);
+ skb_reset_tail_pointer(pskb);
+ pskb->len = 0;
+ skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
+ }
+}
+
+void rtl8188eu_xmit_tasklet(void *priv)
+{
+ struct adapter *adapt = priv;
+ struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
+
+ if (check_fwstate(&adapt->mlmepriv, _FW_UNDER_SURVEY))
+ return;
+
+ while (1) {
+ if ((adapt->bDriverStopped) ||
+ (adapt->bSurpriseRemoved) ||
+ (adapt->bWritePortCancel)) {
+ DBG_88E("xmit_tasklet => bDriverStopped or bSurpriseRemoved or bWritePortCancel\n");
+ break;
+ }
+
+ if (!rtl8188eu_xmitframe_complete(adapt, pxmitpriv))
+ break;
+ }
+}
diff --git a/drivers/staging/rtl8188eu/os_dep/xmit_linux.c b/drivers/staging/rtl8188eu/os_dep/xmit_linux.c
new file mode 100644
index 0000000..017e1d6
--- /dev/null
+++ b/drivers/staging/rtl8188eu/os_dep/xmit_linux.c
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ ******************************************************************************/
+#define _XMIT_OSDEP_C_
+
+#include <osdep_service.h>
+#include <drv_types.h>
+
+#include <wifi.h>
+#include <mlme_osdep.h>
+#include <xmit_osdep.h>
+#include <osdep_intf.h>
+
+int rtw_os_xmit_resource_alloc(struct adapter *padapter,
+ struct xmit_buf *pxmitbuf, u32 alloc_sz)
+{
+ int i;
+
+ pxmitbuf->pallocated_buf = kzalloc(alloc_sz, GFP_KERNEL);
+ if (!pxmitbuf->pallocated_buf)
+ return _FAIL;
+
+ pxmitbuf->pbuf = PTR_ALIGN(pxmitbuf->pallocated_buf, XMITBUF_ALIGN_SZ);
+ pxmitbuf->dma_transfer_addr = 0;
+
+ for (i = 0; i < 8; i++) {
+ pxmitbuf->pxmit_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
+ if (!pxmitbuf->pxmit_urb[i]) {
+ DBG_88E("pxmitbuf->pxmit_urb[i]==NULL");
+ return _FAIL;
+ }
+ }
+ return _SUCCESS;
+}
+
+void rtw_os_xmit_resource_free(struct xmit_buf *pxmitbuf)
+{
+ int i;
+
+ for (i = 0; i < 8; i++)
+ usb_free_urb(pxmitbuf->pxmit_urb[i]);
+
+ kfree(pxmitbuf->pallocated_buf);
+}
+
+#define WMM_XMIT_THRESHOLD (NR_XMITFRAME * 2 / 5)
+
+void rtw_os_pkt_complete(struct adapter *padapter, struct sk_buff *pkt)
+{
+ u16 queue;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+ queue = skb_get_queue_mapping(pkt);
+ if (padapter->registrypriv.wifi_spec) {
+ if (__netif_subqueue_stopped(padapter->pnetdev, queue) &&
+ (pxmitpriv->hwxmits[queue].accnt < WMM_XMIT_THRESHOLD))
+ netif_wake_subqueue(padapter->pnetdev, queue);
+ } else {
+ if (__netif_subqueue_stopped(padapter->pnetdev, queue))
+ netif_wake_subqueue(padapter->pnetdev, queue);
+ }
+
+ dev_kfree_skb_any(pkt);
+}
+
+void rtw_os_xmit_complete(struct adapter *padapter, struct xmit_frame *pxframe)
+{
+ if (pxframe->pkt)
+ rtw_os_pkt_complete(padapter, pxframe->pkt);
+ pxframe->pkt = NULL;
+}
+
+void rtw_os_xmit_schedule(struct adapter *padapter)
+{
+ struct xmit_priv *pxmitpriv;
+
+ if (!padapter)
+ return;
+
+ pxmitpriv = &padapter->xmitpriv;
+
+ spin_lock_bh(&pxmitpriv->lock);
+
+ if (rtw_txframes_pending(padapter))
+ tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
+
+ spin_unlock_bh(&pxmitpriv->lock);
+}
+
+static void rtw_check_xmit_resource(struct adapter *padapter,
+ struct sk_buff *pkt)
+{
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ u16 queue;
+
+ queue = skb_get_queue_mapping(pkt);
+ if (padapter->registrypriv.wifi_spec) {
+ /* No free space for Tx, tx_worker is too slow */
+ if (pxmitpriv->hwxmits[queue].accnt > WMM_XMIT_THRESHOLD)
+ netif_stop_subqueue(padapter->pnetdev, queue);
+ } else {
+ if (pxmitpriv->free_xmitframe_cnt <= 4) {
+ if (!netif_tx_queue_stopped(netdev_get_tx_queue(padapter->pnetdev, queue)))
+ netif_stop_subqueue(padapter->pnetdev, queue);
+ }
+ }
+}
+
+static int rtw_mlcst2unicst(struct adapter *padapter, struct sk_buff *skb)
+{
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct list_head *phead, *plist;
+ struct sk_buff *newskb;
+ struct sta_info *psta = NULL;
+ s32 res;
+
+ spin_lock_bh(&pstapriv->asoc_list_lock);
+ phead = &pstapriv->asoc_list;
+ plist = phead->next;
+
+ /* free sta asoc_queue */
+ while (phead != plist) {
+ psta = container_of(plist, struct sta_info, asoc_list);
+
+ plist = plist->next;
+
+ /* avoid come from STA1 and send back STA1 */
+ if (!memcmp(psta->hwaddr, &skb->data[6], 6))
+ continue;
+
+ newskb = skb_copy(skb, GFP_ATOMIC);
+
+ if (newskb) {
+ memcpy(newskb->data, psta->hwaddr, 6);
+ res = rtw_xmit(padapter, &newskb);
+ if (res < 0) {
+ DBG_88E("%s()-%d: rtw_xmit() return error!\n",
+ __func__, __LINE__);
+ pxmitpriv->tx_drop++;
+ dev_kfree_skb_any(newskb);
+ } else {
+ pxmitpriv->tx_pkts++;
+ }
+ } else {
+ DBG_88E("%s-%d: skb_copy() failed!\n",
+ __func__, __LINE__);
+ pxmitpriv->tx_drop++;
+
+ spin_unlock_bh(&pstapriv->asoc_list_lock);
+
+ /* Caller shall tx this multicast frame
+ * via normal way.
+ */
+ return false;
+ }
+ }
+
+ spin_unlock_bh(&pstapriv->asoc_list_lock);
+ dev_kfree_skb_any(skb);
+ return true;
+}
+
+int rtw_xmit_entry(struct sk_buff *pkt, struct net_device *pnetdev)
+{
+ struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev);
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ s32 res = 0;
+
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("+xmit_enry\n"));
+
+ if (!rtw_if_up(padapter)) {
+ RT_TRACE(_module_xmit_osdep_c_, _drv_err_,
+ ("%s: rtw_if_up fail\n", __func__));
+ goto drop_packet;
+ }
+
+ rtw_check_xmit_resource(padapter, pkt);
+
+ if (!rtw_mc2u_disable && check_fwstate(pmlmepriv, WIFI_AP_STATE) &&
+ (IP_MCAST_MAC(pkt->data) || ICMPV6_MCAST_MAC(pkt->data)) &&
+ (padapter->registrypriv.wifi_spec == 0)) {
+ if (pxmitpriv->free_xmitframe_cnt > NR_XMITFRAME / 4) {
+ res = rtw_mlcst2unicst(padapter, pkt);
+ if (res)
+ goto exit;
+ }
+ }
+
+ res = rtw_xmit(padapter, &pkt);
+ if (res < 0)
+ goto drop_packet;
+
+ pxmitpriv->tx_pkts++;
+ RT_TRACE(_module_xmit_osdep_c_, _drv_info_,
+ ("%s: tx_pkts=%d\n", __func__, (u32)pxmitpriv->tx_pkts));
+ goto exit;
+
+drop_packet:
+ pxmitpriv->tx_drop++;
+ dev_kfree_skb_any(pkt);
+ RT_TRACE(_module_xmit_osdep_c_, _drv_notice_,
+ ("%s: drop, tx_drop=%d\n", __func__, (u32)pxmitpriv->tx_drop));
+
+exit:
+ return 0;
+}