Update to 5.13.1 from upstream

This commit is contained in:
Rin Cat (鈴猫) 2021-12-04 07:42:09 -05:00
parent aab1daf818
commit c0e109d401
No known key found for this signature in database
GPG Key ID: 40DCF18E97150795
352 changed files with 50307 additions and 18938 deletions

229
Makefile Executable file → Normal file
View File

@ -1,5 +1,5 @@
EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS)
EXTRA_CFLAGS += -O2
EXTRA_CFLAGS += -O1
#EXTRA_CFLAGS += -O3
#EXTRA_CFLAGS += -Wall
#EXTRA_CFLAGS += -Wextra
@ -44,12 +44,15 @@ CONFIG_RTL8710B = n
CONFIG_RTL8192F = n
CONFIG_RTL8822C = n
CONFIG_RTL8814B = n
CONFIG_RTL8723F = n
######################### Interface ###########################
CONFIG_USB_HCI = y
CONFIG_PCI_HCI = n
CONFIG_SDIO_HCI = n
CONFIG_GSPI_HCI = n
########################## Features ###########################
CONFIG_AP_MODE = y
CONFIG_P2P = y
CONFIG_MP_INCLUDED = y
CONFIG_POWER_SAVING = y
CONFIG_IPS_MODE = default
@ -74,7 +77,7 @@ CONFIG_80211W = y
CONFIG_REDUCE_TX_CPU_LOADING = n
CONFIG_BR_EXT = y
CONFIG_TDLS = n
CONFIG_WIFI_MONITOR = y
CONFIG_WIFI_MONITOR = n
CONFIG_MCC_MODE = n
CONFIG_APPEND_VENDOR_IE_ENABLE = n
CONFIG_RTW_NAPI = y
@ -82,33 +85,39 @@ CONFIG_RTW_GRO = y
CONFIG_RTW_NETIF_SG = y
CONFIG_RTW_IPCAM_APPLICATION = n
CONFIG_RTW_REPEATER_SON = n
CONFIG_RTW_WIFI_HAL = n
CONFIG_ICMP_VOQ = n
CONFIG_IP_R_MONITOR = n #arp VOQ and high rate
# user priority mapping rule : tos, dscp
CONFIG_RTW_UP_MAPPING_RULE = tos
# Enable VHT rate on 2.4G channel or not
CONFIG_RTW_VHT_2G4 = y
CONFIG_RTW_IOCTL_SET_COUNTRY = y
CONFIG_RTW_MBO = n
########################## Android ###########################
# CONFIG_RTW_ANDROID - 0: no Android, 4/5/6/7/8/9/10/11 : Android version
CONFIG_RTW_ANDROID = 0
ifeq ($(shell test $(CONFIG_RTW_ANDROID) -gt 0; echo $$?), 0)
EXTRA_CFLAGS += -DCONFIG_RTW_ANDROID=$(CONFIG_RTW_ANDROID)
endif
########################## Debug ###########################
CONFIG_RTW_DEBUG = y
# default log level is _DRV_INFO_ = 4,
# please refer to "How_to_set_driver_debug_log_level.doc" to set the available level.
CONFIG_RTW_LOG_LEVEL = 3
CONFIG_RTW_LOG_LEVEL = 4
# enable /proc/net/rtlxxxx/ debug interfaces
CONFIG_PROC_DEBUG = y
######################## Wake On Lan ##########################
CONFIG_WOWLAN = n
#bit2: deauth, bit1: unicast, bit0: magic pkt.
CONFIG_WAKEUP_TYPE = 0x7
#bit3: ARP enable, bit2: deauth, bit1: unicast, bit0: magic pkt.
CONFIG_WAKEUP_TYPE = 0xf
CONFIG_WOW_LPS_MODE = default
#bit0: disBBRF off, #bit1: Wireless remote controller (WRC)
CONFIG_SUSPEND_TYPE = 0
CONFIG_WOW_STA_MIX = n
CONFIG_GPIO_WAKEUP = n
# Please contact with RTK support team first. After getting the agreement from RTK support team,
# you are just able to modify the CONFIG_WAKEUP_GPIO_IDX with customized requirement.
CONFIG_WAKEUP_GPIO_IDX = default
CONFIG_HIGH_ACTIVE_DEV2HST = n
######### only for USB #########
@ -121,6 +130,10 @@ CONFIG_AP_WOWLAN = n
CONFIG_RTW_SDIO_PM_KEEP_POWER = y
###################### MP HW TX MODE FOR VHT #######################
CONFIG_MP_VHT_HW_TX_MODE = n
###################### ROAMING #####################################
CONFIG_LAYER2_ROAMING = y
#bit0: ROAM_ON_EXPIRED, #bit1: ROAM_ON_RESUME, #bit2: ROAM_ACTIVE
CONFIG_ROAMING_FLAG = 0x3
###################### Platform Related #######################
CONFIG_PLATFORM_I386_PC = y
CONFIG_PLATFORM_ANDROID_X86 = n
@ -148,7 +161,6 @@ CONFIG_PLATFORM_ARM_TCC8930_JB42 = n
CONFIG_PLATFORM_ARM_RK2818 = n
CONFIG_PLATFORM_ARM_RK3066 = n
CONFIG_PLATFORM_ARM_RK3188 = n
CONFIG_PLATFORM_ARM_RK3399 = n
CONFIG_PLATFORM_ARM_URBETTER = n
CONFIG_PLATFORM_ARM_TI_PANDA = n
CONFIG_PLATFORM_MIPS_JZ4760 = n
@ -175,6 +187,7 @@ CONFIG_PLATFORM_MOZART = n
CONFIG_PLATFORM_RTK119X = n
CONFIG_PLATFORM_RTK119X_AM = n
CONFIG_PLATFORM_RTK129X = n
CONFIG_PLATFORM_RTK1319 = n
CONFIG_PLATFORM_RTK390X = n
CONFIG_PLATFORM_NOVATEK_NT72668 = n
CONFIG_PLATFORM_HISILICON = n
@ -222,6 +235,7 @@ _OS_INTFS_FILES := os_dep/osdep_service.o \
os_dep/linux/wifi_regd.o \
os_dep/linux/rtw_android.o \
os_dep/linux/rtw_proc.o \
os_dep/linux/nlrtw.o \
os_dep/linux/rtw_rhashtable.o
ifeq ($(CONFIG_MP_INCLUDED), y)
@ -721,6 +735,18 @@ endif
endif
########### HAL_RTL8723F #################################
ifeq ($(CONFIG_RTL8723F), y)
RTL871X := rtl8723f
ifeq ($(CONFIG_USB_HCI), y)
MODULE_NAME = 8723fu
endif
ifeq ($(CONFIG_SDIO_HCI), y)
MODULE_NAME = 8723fs
endif
endif
########### HAL_RTL8188F #################################
ifeq ($(CONFIG_RTL8188F), y)
@ -1007,6 +1033,17 @@ endif
########### END OF PATH #################################
ifeq ($(CONFIG_AP_MODE), y)
EXTRA_CFLAGS += -DCONFIG_AP_MODE
endif
ifeq ($(CONFIG_P2P), y)
EXTRA_CFLAGS += -DCONFIG_P2P
ifneq ($(CONFIG_AP_MODE), y)
$(error "CONFIG_AP_MODE is required for CONFIG_P2P")
endif
endif
ifeq ($(CONFIG_USB_HCI), y)
ifeq ($(CONFIG_USB_AUTOSUSPEND), y)
EXTRA_CFLAGS += -DCONFIG_USB_AUTOSUSPEND
@ -1154,11 +1191,18 @@ endif
ifeq ($(CONFIG_AP_WOWLAN), y)
EXTRA_CFLAGS += -DCONFIG_AP_WOWLAN
ifeq ($(CONFIG_AP_MODE), n)
EXTRA_CFLAGS += -DCONFIG_AP_MODE
endif
ifeq ($(CONFIG_SDIO_HCI), y)
EXTRA_CFLAGS += -DCONFIG_RTW_SDIO_PM_KEEP_POWER
endif
endif
ifeq ($(CONFIG_LAYER2_ROAMING), y)
EXTRA_CFLAGS += -DCONFIG_LAYER2_ROAMING -DCONFIG_ROAMING_FLAG=$(CONFIG_ROAMING_FLAG)
endif
ifeq ($(CONFIG_PNO_SUPPORT), y)
EXTRA_CFLAGS += -DCONFIG_PNO_SUPPORT
ifeq ($(CONFIG_PNO_SET_DEBUG), y)
@ -1248,15 +1292,6 @@ ifeq ($(CONFIG_IP_R_MONITOR), y)
EXTRA_CFLAGS += -DCONFIG_IP_R_MONITOR
endif
ifeq ($(CONFIG_RTW_WIFI_HAL), y)
#EXTRA_CFLAGS += -DCONFIG_RTW_WIFI_HAL_DEBUG
EXTRA_CFLAGS += -DCONFIG_RTW_WIFI_HAL
EXTRA_CFLAGS += -DCONFIG_RTW_CFGVEDNOR_LLSTATS
EXTRA_CFLAGS += -DCONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI
EXTRA_CFLAGS += -DCONFIG_RTW_CFGVEDNOR_RSSIMONITOR
EXTRA_CFLAGS += -DCONFIG_RTW_CFGVENDOR_WIFI_LOGGER
endif
ifeq ($(CONFIG_MP_VHT_HW_TX_MODE), y)
EXTRA_CFLAGS += -DCONFIG_MP_VHT_HW_TX_MODE
ifeq ($(CONFIG_PLATFORM_I386_PC), y)
@ -1289,20 +1324,16 @@ endif
EXTRA_CFLAGS += -DDM_ODM_SUPPORT_TYPE=0x04
ifeq ($(CONFIG_RTW_VHT_2G4), y)
EXTRA_CFLAGS += -DRTW_VHT_2G4=1
else
EXTRA_CFLAGS += -DRTW_VHT_2G4=0
endif
ifeq ($(CONFIG_RTW_IOCTL_SET_COUNTRY), y)
EXTRA_CFLAGS += -DCONFIG_RTW_IOCTL_SET_COUNTRY
ifeq ($(CONFIG_RTW_MBO), y)
EXTRA_CFLAGS += -DCONFIG_RTW_MBO -DCONFIG_RTW_80211K -DCONFIG_RTW_WNM -DCONFIG_RTW_BTM_ROAM
EXTRA_CFLAGS += -DCONFIG_RTW_80211R
endif
ifeq ($(CONFIG_PLATFORM_I386_PC), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
SUBARCH := $(shell uname -m | sed -e 's/i.86/i386/;s/armv7l/arm/;s/aarch64/arm64/')
SUBARCH := $(shell uname -m | sed -e s/i.86/i386/)
ARCH ?= $(SUBARCH)
CROSS_COMPILE ?=
KVER := $(shell uname -r)
@ -1671,7 +1702,9 @@ EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
# default setting for Power control
EXTRA_CFLAGS += -DRTW_ENABLE_WIFI_CONTROL_FUNC
ifeq ($(CONFIG_SDIO_HCI), y)
EXTRA_CFLAGS += -DRTW_SUPPORT_PLATFORM_SHUTDOWN
endif
# default setting for Special function
ARCH := arm
CROSS_COMPILE := /home/android_sdk/Rockchip/Rk3188/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-
@ -1696,37 +1729,6 @@ KSRC := /home/android_sdk/Rockchip/Rk3066sdk/kernel
MODULE_NAME :=wlan
endif
ifeq ($(CONFIG_PLATFORM_ARM_RK3399), y)
EXTRA_CFLAGS += -DCONFIG_PLATFORM_ROCKCHIPS
EXTRA_CFLAGS += -DCONFIG_PLATFORM_ROCKCHIPS_RK3399
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -Wno-error=date-time
# default setting for Android
EXTRA_CFLAGS += -DCONFIG_PLATFORM_ANDROID
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
# default setting for Android 5.0 and later
EXTRA_CFLAGS += -DCONFIG_RADIO_WORK
# default setting for Special function
EXTRA_CFLAGS += -DCONFIG_P2P_IPS
EXTRA_CFLAGS += -DCONFIG_RESUME_IN_WORKQUEUE
ARCH ?= arm64
CROSS_COMPILE ?= /rk3328_box_android_8.0_pro/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-
KSRC ?= /rk3328_box_android_8.0_pro/kernel
ifeq ($(CONFIG_SDIO_HCI), y)
EXTRA_CFLAGS += -DCONFIG_PLATFORM_OPS
_PLATFORM_FILES += platform/platform_rockchips_sdio.o
ifeq ($(CONFIG_RTL8822B), y)
USER_MODULE_NAME := 8822bs
endif
endif
endif
ifeq ($(CONFIG_PLATFORM_ARM_URBETTER), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN #-DCONFIG_MINIMAL_MEMORY_USAGE
ARCH := arm
@ -1921,6 +1923,7 @@ EXTRA_CFLAGS += -DCONFIG_RADIO_WORK
endif
#ARCH, CROSS_COMPILE, KSRC,and MODDESTDIR are provided by external makefile
INSTALL_PREFIX :=
MODULE_NAME := wlan
endif
ifeq ($(CONFIG_PLATFORM_ARM_RTD299X_LG), y)
@ -1977,9 +1980,6 @@ EXTRA_CFLAGS += -DRTW_USE_CFG80211_STA_EVENT
# default setting for Android 5.x and later
#EXTRA_CFLAGS += -DCONFIG_RADIO_WORK
# Change active scan time in each channel, unit is ms
#EXTRA_CFLAGS += -DSURVEY_TO_ACTIVE=50
# If system could power on and recognize Wi-Fi SDIO automatically,
# platfrom operations are not necessary.
#ifeq ($(CONFIG_SDIO_HCI), y)
@ -2082,11 +2082,13 @@ MODULE_NAME := 8192eu
endif
# Actions-Micro use this flag for DHC 1195 and DHC 1395
ifeq ($(CONFIG_PLATFORM_RTK119X_AM), y)
EXTRA_CFLAGS += -DCONFIG_PLATFORM_RTK119X_AM
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DCONFIG_TRAFFIC_PROTECT
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE -DCONFIG_FULL_CH_IN_P2P_HANDSHAKE
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_FULL_CH_IN_P2P_HANDSHAKE
EXTRA_CFLAGS += -DCONFIG_SEL_P2P_IFACE=2
EXTRA_CFLAGS += -DCONFIG_IFACE_NUMBER=3
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
@ -2104,7 +2106,43 @@ endif
ifeq ($(CONFIG_PLATFORM_RTK129X), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DRTK_129X_PLATFORM
EXTRA_CFLAGS += -DCONFIG_PLATFORM_RTK129X
EXTRA_CFLAGS += -DCONFIG_TRAFFIC_PROTECT
# default setting for Android 4.1, 4.2
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
#EXTRA_CFLAGS += -DCONFIG_P2P_IPS -DCONFIG_QOS_OPTIMIZATION
EXTRA_CFLAGS += -DCONFIG_QOS_OPTIMIZATION
# Enable this for Android 5.0
EXTRA_CFLAGS += -DCONFIG_RADIO_WORK
ifeq ($(CONFIG_RTL8821C)$(CONFIG_SDIO_HCI),yy)
EXTRA_CFLAGS += -DCONFIG_WAKEUP_GPIO_INPUT_MODE
EXTRA_CFLAGS += -DCONFIG_BT_WAKE_HST_OPEN_DRAIN
endif
EXTRA_CFLAGS += -Wno-error=date-time
# default setting for Android 7.0
ifeq ($(RTK_ANDROID_VERSION), nougat)
EXTRA_CFLAGS += -DRTW_P2P_GROUP_INTERFACE=1
endif
#EXTRA_CFLAGS += -DCONFIG_#PLATFORM_OPS
ifeq ($(CONFIG_USB_HCI), y)
EXTRA_CFLAGS += -DCONFIG_USE_USB_BUFFER_ALLOC_TX
endif
ARCH := arm64
# ==== Cross compile setting for Android 4.4 SDK =====
#CROSS_COMPILE := arm-linux-gnueabihf-
#KVER := 4.1.10
#CROSS_COMPILE := $(CROSS)
#KSRC := $(LINUX_KERNEL_PATH)
CROSS_COMPILE := /home/android_sdk/DHC/trunk-6.0.0_r1-QA160627/phoenix/toolchain/asdk64-4.9.4-a53-EL-3.10-g2.19-a64nt-160307/bin/asdk64-linux-
KSRC := /home/android_sdk/DHC/trunk-6.0.0_r1-QA160627/linux-kernel
endif
ifeq ($(CONFIG_PLATFORM_RTK1319), y)
EXTRA_CFLAGS += -DCONFIG_PLATFORM_RTK1319
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DCONFIG_TRAFFIC_PROTECT
# default setting for Android 4.1, 4.2
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
@ -2197,9 +2235,6 @@ EXTRA_CFLAGS += -DRTW_USE_CFG80211_STA_EVENT
# default setting for Android 5.x and later
EXTRA_CFLAGS += -DCONFIG_RADIO_WORK
# Change active scan time in each channel, unit is ms
#EXTRA_CFLAGS += -DSURVEY_TO_ACTIVE=50
ifeq ($(CONFIG_SDIO_HCI), y)
EXTRA_CFLAGS += -DCONFIG_PLATFORM_OPS
_PLATFORM_FILES += platform/platform_aml_s905_sdio.o
@ -2261,6 +2296,14 @@ ifeq ($(CONFIG_CUSTOMER_HUAWEI), y)
EXTRA_CFLAGS += -DCONFIG_HUAWEI_PROC
endif
CONFIG_PLATFORM_CMAP_INTFS = n
ifeq ($(CONFIG_PLATFORM_CMAP_INTFS), y)
PLATFORM_CMAP_INTFS_TYPE = 00
EXTRA_CFLAGS += -DCONFIG_PLATFORM_CMAP_INTFS -DCMAP_UNASSOC_METRICS_STA_MAX=32
_OS_INTFS_FILES += os_dep/linux/custom_multiap_intfs/custom_multiap_intfs.o
_PLATFORM_FILES += platform/custom_multiap_intfs_$(PLATFORM_CMAP_INTFS_TYPE).o
endif
ifeq ($(CONFIG_MULTIDRV), y)
ifeq ($(CONFIG_SDIO_HCI), y)
@ -2308,6 +2351,11 @@ ifeq ($(CONFIG_RTL8814B), y)
include $(src)/rtl8814b.mk
endif
########### HAL_RTL8723F #################################
ifeq ($(CONFIG_RTL8723F), y)
include $(src)/rtl8723f.mk
endif
rtk_core := core/rtw_cmd.o \
core/rtw_security.o \
core/rtw_debug.o \
@ -2323,9 +2371,11 @@ rtk_core := core/rtw_cmd.o \
core/rtw_pwrctrl.o \
core/rtw_rf.o \
core/rtw_chplan.o \
core/monitor/rtw_radiotap.o \
core/rtw_recv.o \
core/rtw_sta_mgt.o \
core/rtw_ap.o \
core/wds/rtw_wds.o \
core/mesh/rtw_mesh.o \
core/mesh/rtw_mesh_pathtbl.o \
core/mesh/rtw_mesh_hwmp.o \
@ -2342,13 +2392,34 @@ rtk_core := core/rtw_cmd.o \
core/rtw_odm.o \
core/rtw_rm.o \
core/rtw_rm_fsm.o \
core/rtw_ft.o \
core/rtw_wnm.o \
core/rtw_mbo.o \
core/rtw_rm_util.o \
core/efuse/rtw_efuse.o
core/efuse/rtw_efuse.o \
core/rtw_roch.o
ifeq ($(CONFIG_SDIO_HCI), y)
rtk_core += core/rtw_sdio.o
endif
EXTRA_CFLAGS += -I$(src)/core/crypto
rtk_core += \
core/crypto/aes-internal.o \
core/crypto/aes-internal-enc.o \
core/crypto/aes-gcm.o \
core/crypto/aes-ccm.o \
core/crypto/aes-omac1.o \
core/crypto/ccmp.o \
core/crypto/gcmp.o \
core/crypto/aes-siv.o \
core/crypto/aes-ctr.o \
core/crypto/sha256-internal.o \
core/crypto/sha256.o \
core/crypto/sha256-prf.o \
core/crypto/rtw_crypto_wrap.o \
core/rtw_swcrypto.o
$(MODULE_NAME)-y += $(rtk_core)
$(MODULE_NAME)-$(CONFIG_WAPI_SUPPORT) += core/rtw_wapi.o \
@ -2431,17 +2502,17 @@ config_r:
clean:
#$(MAKE) -C $(KSRC) M=$(shell pwd) clean
cd hal ; rm -fr */*/*/*.mod.c */*/*/*.mod */*/*/*.o */*/*/.*.cmd */*/*/*.ko */*/*/*.ur-safe
cd hal ; rm -fr */*/*.mod.c */*/*.mod */*/*.o */*/.*.cmd */*/*.ko */*/*.ur-safe
cd hal ; rm -fr */*.mod.c */*.mod */*.o */.*.cmd */*.ko */*.ur-safe
cd hal ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko *.ur-safe
cd core ; rm -fr */*.mod.c */*.mod */*.o */.*.cmd */*.ko */*.ur-safe
cd core ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko *.ur-safe
cd os_dep/linux ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko *.ur-safe
cd os_dep ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko *.ur-safe
cd platform ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko *.ur-safe
cd hal ; rm -fr */*/*/*.mod.c */*/*/*.mod */*/*/*.o */*/*/.*.cmd */*/*/*.ko
cd hal ; rm -fr */*/*.mod.c */*/*.mod */*/*.o */*/.*.cmd */*/*.ko
cd hal ; rm -fr */*.mod.c */*.mod */*.o */.*.cmd */*.ko
cd hal ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko
cd core ; rm -fr */*.mod.c */*.mod */*.o */.*.cmd */*.ko
cd core ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko
cd os_dep/linux ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko
cd os_dep ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko
cd platform ; rm -fr *.mod.c *.mod *.o .*.cmd *.ko
rm -fr Module.symvers ; rm -fr Module.markers ; rm -fr modules.order
rm -fr *.mod.c *.mod *.o .*.cmd *.ko *~
rm -fr .tmp_versions *.ur-safe
rm -fr .tmp_versions
endif

View File

@ -1,5 +1,5 @@
# REALTEK RTL88x2B USB Linux Driver
**Current Driver Version**: 5.8.7.4
**Current Driver Version**: 5.13.1
**Support Kernel**: 2.6.24 ~ 5.15 (with unofficial patches)
Official release note please check ReleaseNotes.pdf

10
clean
View File

@ -1,7 +1,5 @@
#!/bin/bash
rmmod 8822be
rmmod 88x2be
rmmod 8822bs
rmmod 88x2bs
rmmod 8822bu
rmmod 88x2bu
rmmod 8192cu
rmmod 8192ce
rmmod 8192du
rmmod 8192de

211
core/crypto/aes-ccm.c Normal file
View File

@ -0,0 +1,211 @@
/*
* Counter with CBC-MAC (CCM) with AES
*
* Copyright (c) 2010-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "rtw_crypto_wrap.h"
#include "aes.h"
#include "aes_wrap.h"
static void xor_aes_block(u8 *dst, const u8 *src)
{
u32 *d = (u32 *) dst;
u32 *s = (u32 *) src;
*d++ ^= *s++;
*d++ ^= *s++;
*d++ ^= *s++;
*d++ ^= *s++;
}
static void aes_ccm_auth_start(void *aes, size_t M, size_t L, const u8 *nonce,
const u8 *aad, size_t aad_len, size_t plain_len,
u8 *x)
{
u8 aad_buf[2 * AES_BLOCK_SIZE];
u8 b[AES_BLOCK_SIZE];
/* Authentication */
/* B_0: Flags | Nonce N | l(m) */
b[0] = aad_len ? 0x40 : 0 /* Adata */;
b[0] |= (((M - 2) / 2) /* M' */ << 3);
b[0] |= (L - 1) /* L' */;
os_memcpy(&b[1], nonce, 15 - L);
WPA_PUT_BE16(&b[AES_BLOCK_SIZE - L], plain_len);
wpa_hexdump_key(_MSG_EXCESSIVE_, "CCM B_0", b, AES_BLOCK_SIZE);
aes_encrypt(aes, b, x); /* X_1 = E(K, B_0) */
if (!aad_len)
return;
WPA_PUT_BE16(aad_buf, aad_len);
os_memcpy(aad_buf + 2, aad, aad_len);
os_memset(aad_buf + 2 + aad_len, 0, sizeof(aad_buf) - 2 - aad_len);
xor_aes_block(aad_buf, x);
aes_encrypt(aes, aad_buf, x); /* X_2 = E(K, X_1 XOR B_1) */
if (aad_len > AES_BLOCK_SIZE - 2) {
xor_aes_block(&aad_buf[AES_BLOCK_SIZE], x);
/* X_3 = E(K, X_2 XOR B_2) */
aes_encrypt(aes, &aad_buf[AES_BLOCK_SIZE], x);
}
}
static void aes_ccm_auth(void *aes, const u8 *data, size_t len, u8 *x)
{
size_t last = len % AES_BLOCK_SIZE;
size_t i;
for (i = 0; i < len / AES_BLOCK_SIZE; i++) {
/* X_i+1 = E(K, X_i XOR B_i) */
xor_aes_block(x, data);
data += AES_BLOCK_SIZE;
aes_encrypt(aes, x, x);
}
if (last) {
/* XOR zero-padded last block */
for (i = 0; i < last; i++)
x[i] ^= *data++;
aes_encrypt(aes, x, x);
}
}
static void aes_ccm_encr_start(size_t L, const u8 *nonce, u8 *a)
{
/* A_i = Flags | Nonce N | Counter i */
a[0] = L - 1; /* Flags = L' */
os_memcpy(&a[1], nonce, 15 - L);
}
static void aes_ccm_encr(void *aes, size_t L, const u8 *in, size_t len, u8 *out,
u8 *a)
{
size_t last = len % AES_BLOCK_SIZE;
size_t i;
/* crypt = msg XOR (S_1 | S_2 | ... | S_n) */
for (i = 1; i <= len / AES_BLOCK_SIZE; i++) {
WPA_PUT_BE16(&a[AES_BLOCK_SIZE - 2], i);
/* S_i = E(K, A_i) */
aes_encrypt(aes, a, out);
xor_aes_block(out, in);
out += AES_BLOCK_SIZE;
in += AES_BLOCK_SIZE;
}
if (last) {
WPA_PUT_BE16(&a[AES_BLOCK_SIZE - 2], i);
aes_encrypt(aes, a, out);
/* XOR zero-padded last block */
for (i = 0; i < last; i++)
*out++ ^= *in++;
}
}
static void aes_ccm_encr_auth(void *aes, size_t M, u8 *x, u8 *a, u8 *auth)
{
size_t i;
u8 tmp[AES_BLOCK_SIZE];
wpa_hexdump_key(_MSG_EXCESSIVE_, "CCM T", x, M);
/* U = T XOR S_0; S_0 = E(K, A_0) */
WPA_PUT_BE16(&a[AES_BLOCK_SIZE - 2], 0);
aes_encrypt(aes, a, tmp);
for (i = 0; i < M; i++)
auth[i] = x[i] ^ tmp[i];
wpa_hexdump_key(_MSG_EXCESSIVE_, "CCM U", auth, M);
}
static void aes_ccm_decr_auth(void *aes, size_t M, u8 *a, const u8 *auth, u8 *t)
{
size_t i;
u8 tmp[AES_BLOCK_SIZE];
wpa_hexdump_key(_MSG_EXCESSIVE_, "CCM U", auth, M);
/* U = T XOR S_0; S_0 = E(K, A_0) */
WPA_PUT_BE16(&a[AES_BLOCK_SIZE - 2], 0);
aes_encrypt(aes, a, tmp);
for (i = 0; i < M; i++)
t[i] = auth[i] ^ tmp[i];
wpa_hexdump_key(_MSG_EXCESSIVE_, "CCM T", t, M);
}
/* AES-CCM with fixed L=2 and aad_len <= 30 assumption */
int aes_ccm_ae(const u8 *key, size_t key_len, const u8 *nonce,
size_t M, const u8 *plain, size_t plain_len,
const u8 *aad, size_t aad_len, u8 *crypt, u8 *auth)
{
const size_t L = 2;
void *aes;
u8 x[AES_BLOCK_SIZE], a[AES_BLOCK_SIZE];
if (aad_len > 30 || M > AES_BLOCK_SIZE)
return -1;
aes = aes_encrypt_init(key, key_len);
if (aes == NULL)
return -1;
aes_ccm_auth_start(aes, M, L, nonce, aad, aad_len, plain_len, x);
aes_ccm_auth(aes, plain, plain_len, x);
/* Encryption */
aes_ccm_encr_start(L, nonce, a);
aes_ccm_encr(aes, L, plain, plain_len, crypt, a);
aes_ccm_encr_auth(aes, M, x, a, auth);
aes_encrypt_deinit(aes);
return 0;
}
/* AES-CCM with fixed L=2 and aad_len <= 30 assumption */
int aes_ccm_ad(const u8 *key, size_t key_len, const u8 *nonce,
size_t M, const u8 *crypt, size_t crypt_len,
const u8 *aad, size_t aad_len, const u8 *auth, u8 *plain)
{
const size_t L = 2;
void *aes;
u8 x[AES_BLOCK_SIZE], a[AES_BLOCK_SIZE];
u8 t[AES_BLOCK_SIZE];
if (aad_len > 30 || M > AES_BLOCK_SIZE)
return -1;
aes = aes_encrypt_init(key, key_len);
if (aes == NULL)
return -1;
/* Decryption */
aes_ccm_encr_start(L, nonce, a);
aes_ccm_decr_auth(aes, M, a, auth, t);
/* plaintext = msg XOR (S_1 | S_2 | ... | S_n) */
aes_ccm_encr(aes, L, crypt, crypt_len, plain, a);
aes_ccm_auth_start(aes, M, L, nonce, aad, aad_len, crypt_len, x);
aes_ccm_auth(aes, plain, crypt_len, x);
aes_encrypt_deinit(aes);
if (os_memcmp_const(x, t, M) != 0) {
wpa_printf(_MSG_EXCESSIVE_, "CCM: Auth mismatch");
return -1;
}
return 0;
}

70
core/crypto/aes-ctr.c Normal file
View File

@ -0,0 +1,70 @@
/*
* AES-128/192/256 CTR
*
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "rtw_crypto_wrap.h"
#include "aes.h"
#include "aes_wrap.h"
/**
* aes_ctr_encrypt - AES-128/192/256 CTR mode encryption
* @key: Key for encryption (key_len bytes)
* @key_len: Length of the key (16, 24, or 32 bytes)
* @nonce: Nonce for counter mode (16 bytes)
* @data: Data to encrypt in-place
* @data_len: Length of data in bytes
* Returns: 0 on success, -1 on failure
*/
int aes_ctr_encrypt(const u8 *key, size_t key_len, const u8 *nonce,
u8 *data, size_t data_len)
{
void *ctx;
size_t j, len, left = data_len;
int i;
u8 *pos = data;
u8 counter[AES_BLOCK_SIZE], buf[AES_BLOCK_SIZE];
ctx = aes_encrypt_init(key, key_len);
if (ctx == NULL)
return -1;
os_memcpy(counter, nonce, AES_BLOCK_SIZE);
while (left > 0) {
aes_encrypt(ctx, counter, buf);
len = (left < AES_BLOCK_SIZE) ? left : AES_BLOCK_SIZE;
for (j = 0; j < len; j++)
pos[j] ^= buf[j];
pos += len;
left -= len;
for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) {
counter[i]++;
if (counter[i])
break;
}
}
aes_encrypt_deinit(ctx);
return 0;
}
/**
* aes_128_ctr_encrypt - AES-128 CTR mode encryption
* @key: Key for encryption (key_len bytes)
* @nonce: Nonce for counter mode (16 bytes)
* @data: Data to encrypt in-place
* @data_len: Length of data in bytes
* Returns: 0 on success, -1 on failure
*/
int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
u8 *data, size_t data_len)
{
return aes_ctr_encrypt(key, 16, nonce, data, data_len);
}

326
core/crypto/aes-gcm.c Normal file
View File

@ -0,0 +1,326 @@
/*
* Galois/Counter Mode (GCM) and GMAC with AES
*
* Copyright (c) 2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "rtw_crypto_wrap.h"
#include "aes.h"
#include "aes_wrap.h"
static void inc32(u8 *block)
{
u32 val;
val = WPA_GET_BE32(block + AES_BLOCK_SIZE - 4);
val++;
WPA_PUT_BE32(block + AES_BLOCK_SIZE - 4, val);
}
static void xor_block(u8 *dst, const u8 *src)
{
u32 *d = (u32 *) dst;
u32 *s = (u32 *) src;
*d++ ^= *s++;
*d++ ^= *s++;
*d++ ^= *s++;
*d++ ^= *s++;
}
static void shift_right_block(u8 *v)
{
u32 val;
val = WPA_GET_BE32(v + 12);
val >>= 1;
if (v[11] & 0x01)
val |= 0x80000000;
WPA_PUT_BE32(v + 12, val);
val = WPA_GET_BE32(v + 8);
val >>= 1;
if (v[7] & 0x01)
val |= 0x80000000;
WPA_PUT_BE32(v + 8, val);
val = WPA_GET_BE32(v + 4);
val >>= 1;
if (v[3] & 0x01)
val |= 0x80000000;
WPA_PUT_BE32(v + 4, val);
val = WPA_GET_BE32(v);
val >>= 1;
WPA_PUT_BE32(v, val);
}
/* Multiplication in GF(2^128) */
static void gf_mult(const u8 *x, const u8 *y, u8 *z)
{
u8 v[16];
int i, j;
os_memset(z, 0, 16); /* Z_0 = 0^128 */
os_memcpy(v, y, 16); /* V_0 = Y */
for (i = 0; i < 16; i++) {
for (j = 0; j < 8; j++) {
if (x[i] & BIT(7 - j)) {
/* Z_(i + 1) = Z_i XOR V_i */
xor_block(z, v);
} else {
/* Z_(i + 1) = Z_i */
}
if (v[15] & 0x01) {
/* V_(i + 1) = (V_i >> 1) XOR R */
shift_right_block(v);
/* R = 11100001 || 0^120 */
v[0] ^= 0xe1;
} else {
/* V_(i + 1) = V_i >> 1 */
shift_right_block(v);
}
}
}
}
static void ghash_start(u8 *y)
{
/* Y_0 = 0^128 */
os_memset(y, 0, 16);
}
static void ghash(const u8 *h, const u8 *x, size_t xlen, u8 *y)
{
size_t m, i;
const u8 *xpos = x;
u8 tmp[16];
m = xlen / 16;
for (i = 0; i < m; i++) {
/* Y_i = (Y^(i-1) XOR X_i) dot H */
xor_block(y, xpos);
xpos += 16;
/* dot operation:
* multiplication operation for binary Galois (finite) field of
* 2^128 elements */
gf_mult(y, h, tmp);
os_memcpy(y, tmp, 16);
}
if (x + xlen > xpos) {
/* Add zero padded last block */
size_t last = x + xlen - xpos;
os_memcpy(tmp, xpos, last);
os_memset(tmp + last, 0, sizeof(tmp) - last);
/* Y_i = (Y^(i-1) XOR X_i) dot H */
xor_block(y, tmp);
/* dot operation:
* multiplication operation for binary Galois (finite) field of
* 2^128 elements */
gf_mult(y, h, tmp);
os_memcpy(y, tmp, 16);
}
/* Return Y_m */
}
static void aes_gctr(void *aes, const u8 *icb, const u8 *x, size_t xlen, u8 *y)
{
size_t i, n, last;
u8 cb[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE];
const u8 *xpos = x;
u8 *ypos = y;
if (xlen == 0)
return;
n = xlen / 16;
os_memcpy(cb, icb, AES_BLOCK_SIZE);
/* Full blocks */
for (i = 0; i < n; i++) {
aes_encrypt(aes, cb, ypos);
xor_block(ypos, xpos);
xpos += AES_BLOCK_SIZE;
ypos += AES_BLOCK_SIZE;
inc32(cb);
}
last = x + xlen - xpos;
if (last) {
/* Last, partial block */
aes_encrypt(aes, cb, tmp);
for (i = 0; i < last; i++)
*ypos++ = *xpos++ ^ tmp[i];
}
}
static void * aes_gcm_init_hash_subkey(const u8 *key, size_t key_len, u8 *H)
{
void *aes;
aes = aes_encrypt_init(key, key_len);
if (aes == NULL)
return NULL;
/* Generate hash subkey H = AES_K(0^128) */
os_memset(H, 0, AES_BLOCK_SIZE);
aes_encrypt(aes, H, H);
wpa_hexdump_key(_MSG_EXCESSIVE_, "Hash subkey H for GHASH",
H, AES_BLOCK_SIZE);
return aes;
}
static void aes_gcm_prepare_j0(const u8 *iv, size_t iv_len, const u8 *H, u8 *J0)
{
u8 len_buf[16];
if (iv_len == 12) {
/* Prepare block J_0 = IV || 0^31 || 1 [len(IV) = 96] */
os_memcpy(J0, iv, iv_len);
os_memset(J0 + iv_len, 0, AES_BLOCK_SIZE - iv_len);
J0[AES_BLOCK_SIZE - 1] = 0x01;
} else {
/*
* s = 128 * ceil(len(IV)/128) - len(IV)
* J_0 = GHASH_H(IV || 0^(s+64) || [len(IV)]_64)
*/
ghash_start(J0);
ghash(H, iv, iv_len, J0);
WPA_PUT_BE64(len_buf, 0);
WPA_PUT_BE64(len_buf + 8, iv_len * 8);
ghash(H, len_buf, sizeof(len_buf), J0);
}
}
static void aes_gcm_gctr(void *aes, const u8 *J0, const u8 *in, size_t len,
u8 *out)
{
u8 J0inc[AES_BLOCK_SIZE];
if (len == 0)
return;
os_memcpy(J0inc, J0, AES_BLOCK_SIZE);
inc32(J0inc);
aes_gctr(aes, J0inc, in, len, out);
}
static void aes_gcm_ghash(const u8 *H, const u8 *aad, size_t aad_len,
const u8 *crypt, size_t crypt_len, u8 *S)
{
u8 len_buf[16];
/*
* u = 128 * ceil[len(C)/128] - len(C)
* v = 128 * ceil[len(A)/128] - len(A)
* S = GHASH_H(A || 0^v || C || 0^u || [len(A)]64 || [len(C)]64)
* (i.e., zero padded to block size A || C and lengths of each in bits)
*/
ghash_start(S);
ghash(H, aad, aad_len, S);
ghash(H, crypt, crypt_len, S);
WPA_PUT_BE64(len_buf, aad_len * 8);
WPA_PUT_BE64(len_buf + 8, crypt_len * 8);
ghash(H, len_buf, sizeof(len_buf), S);
wpa_hexdump_key(_MSG_EXCESSIVE_, "S = GHASH_H(...)", S, 16);
}
/**
* aes_gcm_ae - GCM-AE_K(IV, P, A)
*/
int aes_gcm_ae(const u8 *key, size_t key_len, const u8 *iv, size_t iv_len,
const u8 *plain, size_t plain_len,
const u8 *aad, size_t aad_len, u8 *crypt, u8 *tag)
{
u8 H[AES_BLOCK_SIZE];
u8 J0[AES_BLOCK_SIZE];
u8 S[16];
void *aes;
aes = aes_gcm_init_hash_subkey(key, key_len, H);
if (aes == NULL)
return -1;
aes_gcm_prepare_j0(iv, iv_len, H, J0);
/* C = GCTR_K(inc_32(J_0), P) */
aes_gcm_gctr(aes, J0, plain, plain_len, crypt);
aes_gcm_ghash(H, aad, aad_len, crypt, plain_len, S);
/* T = MSB_t(GCTR_K(J_0, S)) */
aes_gctr(aes, J0, S, sizeof(S), tag);
/* Return (C, T) */
aes_encrypt_deinit(aes);
return 0;
}
/**
* aes_gcm_ad - GCM-AD_K(IV, C, A, T)
*/
int aes_gcm_ad(const u8 *key, size_t key_len, const u8 *iv, size_t iv_len,
const u8 *crypt, size_t crypt_len,
const u8 *aad, size_t aad_len, const u8 *tag, u8 *plain)
{
u8 H[AES_BLOCK_SIZE];
u8 J0[AES_BLOCK_SIZE];
u8 S[16], T[16];
void *aes;
aes = aes_gcm_init_hash_subkey(key, key_len, H);
if (aes == NULL)
return -1;
aes_gcm_prepare_j0(iv, iv_len, H, J0);
/* P = GCTR_K(inc_32(J_0), C) */
aes_gcm_gctr(aes, J0, crypt, crypt_len, plain);
aes_gcm_ghash(H, aad, aad_len, crypt, crypt_len, S);
/* T' = MSB_t(GCTR_K(J_0, S)) */
aes_gctr(aes, J0, S, sizeof(S), T);
aes_encrypt_deinit(aes);
if (os_memcmp_const(tag, T, 16) != 0) {
wpa_printf(_MSG_EXCESSIVE_, "GCM: Tag mismatch");
return -1;
}
return 0;
}
int aes_gmac(const u8 *key, size_t key_len, const u8 *iv, size_t iv_len,
const u8 *aad, size_t aad_len, u8 *tag)
{
return aes_gcm_ae(key, key_len, iv, iv_len, NULL, 0, aad, aad_len, NULL,
tag);
}

View File

@ -0,0 +1,129 @@
/*
* AES (Rijndael) cipher - encrypt
*
* Modifications to public domain implementation:
* - cleanup
* - use C pre-processor to make it easier to change S table access
* - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at
* cost of reduced throughput (quite small difference on Pentium 4,
* 10-25% when using -O1 or -O2 optimization)
*
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "rtw_crypto_wrap.h"
#include "aes_i.h"
static void rijndaelEncrypt(const u32 rk[], int Nr, const u8 pt[16], u8 ct[16])
{
u32 s0, s1, s2, s3, t0, t1, t2, t3;
#ifndef FULL_UNROLL
int r;
#endif /* ?FULL_UNROLL */
/*
* map byte array block to cipher state
* and add initial round key:
*/
s0 = GETU32(pt ) ^ rk[0];
s1 = GETU32(pt + 4) ^ rk[1];
s2 = GETU32(pt + 8) ^ rk[2];
s3 = GETU32(pt + 12) ^ rk[3];
#define ROUND(i,d,s) \
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]
#ifdef FULL_UNROLL
ROUND(1,t,s);
ROUND(2,s,t);
ROUND(3,t,s);
ROUND(4,s,t);
ROUND(5,t,s);
ROUND(6,s,t);
ROUND(7,t,s);
ROUND(8,s,t);
ROUND(9,t,s);
if (Nr > 10) {
ROUND(10,s,t);
ROUND(11,t,s);
if (Nr > 12) {
ROUND(12,s,t);
ROUND(13,t,s);
}
}
rk += Nr << 2;
#else /* !FULL_UNROLL */
/* Nr - 1 full rounds: */
r = Nr >> 1;
for (;;) {
ROUND(1,t,s);
rk += 8;
if (--r == 0)
break;
ROUND(0,s,t);
}
#endif /* ?FULL_UNROLL */
#undef ROUND
/*
* apply last round and
* map cipher state to byte array block:
*/
s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0];
PUTU32(ct , s0);
s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1];
PUTU32(ct + 4, s1);
s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2];
PUTU32(ct + 8, s2);
s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3];
PUTU32(ct + 12, s3);
}
void * aes_encrypt_init(const u8 *key, size_t len)
{
u32 *rk;
int res;
if (TEST_FAIL())
return NULL;
rk = os_malloc(AES_PRIV_SIZE);
if (rk == NULL)
return NULL;
res = rijndaelKeySetupEnc(rk, key, len * 8);
if (res < 0) {
rtw_mfree(rk, AES_PRIV_SIZE);
return NULL;
}
rk[AES_PRIV_NR_POS] = res;
return rk;
}
int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
{
u32 *rk = ctx;
rijndaelEncrypt(ctx, rk[AES_PRIV_NR_POS], plain, crypt);
return 0;
}
void aes_encrypt_deinit(void *ctx)
{
os_memset(ctx, 0, AES_PRIV_SIZE);
rtw_mfree(ctx, AES_PRIV_SIZE);
}

843
core/crypto/aes-internal.c Normal file
View File

@ -0,0 +1,843 @@
/*
* AES (Rijndael) cipher
*
* Modifications to public domain implementation:
* - cleanup
* - use C pre-processor to make it easier to change S table access
* - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at
* cost of reduced throughput (quite small difference on Pentium 4,
* 10-25% when using -O1 or -O2 optimization)
*
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "rtw_crypto_wrap.h"
#include "aes_i.h"
/*
* rijndael-alg-fst.c
*
* @version 3.0 (December 2000)
*
* Optimised ANSI C code for the Rijndael cipher (now AES)
*
* @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
* @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
* @author Paulo Barreto <paulo.barreto@terra.com.br>
*
* This code is hereby placed in the public domain.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
Te0[x] = S [x].[02, 01, 01, 03];
Te1[x] = S [x].[03, 02, 01, 01];
Te2[x] = S [x].[01, 03, 02, 01];
Te3[x] = S [x].[01, 01, 03, 02];
Te4[x] = S [x].[01, 01, 01, 01];
Td0[x] = Si[x].[0e, 09, 0d, 0b];
Td1[x] = Si[x].[0b, 0e, 09, 0d];
Td2[x] = Si[x].[0d, 0b, 0e, 09];
Td3[x] = Si[x].[09, 0d, 0b, 0e];
Td4[x] = Si[x].[01, 01, 01, 01];
*/
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,
};
#ifndef AES_SMALL_TABLES
const u32 Te1[256] = {
0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
};
const u32 Te2[256] = {
0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
};
const u32 Te3[256] = {
0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
};
const u32 Te4[256] = {
0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,
0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,
0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,
0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,
0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,
0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,
0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,
0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,
0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,
0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,
0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,
0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,
0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,
0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,
0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,
0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,
0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,
0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,
0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,
0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,
0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,
0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,
0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,
0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,
0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,
0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,
0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,
0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,
0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,
0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,
0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,
0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,
0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
};
#endif /* AES_SMALL_TABLES */
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,
};
#ifndef AES_SMALL_TABLES
const u32 Td1[256] = {
0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
};
const u32 Td2[256] = {
0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
};
const u32 Td3[256] = {
0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
};
const u32 Td4[256] = {
0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,
0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,
0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,
0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,
0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,
0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,
0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,
0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,
0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,
0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,
0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,
0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,
0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,
0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,
0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,
0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,
0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,
0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,
0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,
0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,
0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,
0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,
0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,
0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,
0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,
0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,
0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,
0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,
0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,
0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,
0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,
0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,
0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,
0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,
0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,
0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,
0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,
0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,
0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,
0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,
0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,
0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,
0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,
0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,
0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,
0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,
0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,
0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,
0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,
0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,
0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,
0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,
0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,
0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,
0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,
0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,
0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,
0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,
0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,
0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
};
const u32 rcon[] = {
0x01000000, 0x02000000, 0x04000000, 0x08000000,
0x10000000, 0x20000000, 0x40000000, 0x80000000,
0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
};
#else /* AES_SMALL_TABLES */
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 */
};
#endif /* AES_SMALL_TABLES */
/**
* Expand the cipher key into the encryption key schedule.
*
* @return the number of rounds for the given cipher key size.
*/
int rijndaelKeySetupEnc(u32 rk[], const u8 cipherKey[], int keyBits)
{
int i;
u32 temp;
rk[0] = GETU32(cipherKey );
rk[1] = GETU32(cipherKey + 4);
rk[2] = GETU32(cipherKey + 8);
rk[3] = GETU32(cipherKey + 12);
if (keyBits == 128) {
for (i = 0; i < 10; i++) {
temp = rk[3];
rk[4] = rk[0] ^ TE421(temp) ^ TE432(temp) ^
TE443(temp) ^ TE414(temp) ^ RCON(i);
rk[5] = rk[1] ^ rk[4];
rk[6] = rk[2] ^ rk[5];
rk[7] = rk[3] ^ rk[6];
rk += 4;
}
return 10;
}
rk[4] = GETU32(cipherKey + 16);
rk[5] = GETU32(cipherKey + 20);
if (keyBits == 192) {
for (i = 0; i < 8; i++) {
temp = rk[5];
rk[6] = rk[0] ^ TE421(temp) ^ TE432(temp) ^
TE443(temp) ^ TE414(temp) ^ RCON(i);
rk[7] = rk[1] ^ rk[6];
rk[8] = rk[2] ^ rk[7];
rk[9] = rk[3] ^ rk[8];
if (i == 7)
return 12;
rk[10] = rk[4] ^ rk[9];
rk[11] = rk[5] ^ rk[10];
rk += 6;
}
}
rk[6] = GETU32(cipherKey + 24);
rk[7] = GETU32(cipherKey + 28);
if (keyBits == 256) {
for (i = 0; i < 7; i++) {
temp = rk[7];
rk[8] = rk[0] ^ TE421(temp) ^ TE432(temp) ^
TE443(temp) ^ TE414(temp) ^ RCON(i);
rk[9] = rk[1] ^ rk[8];
rk[10] = rk[2] ^ rk[9];
rk[11] = rk[3] ^ rk[10];
if (i == 6)
return 14;
temp = rk[11];
rk[12] = rk[4] ^ TE411(temp) ^ TE422(temp) ^
TE433(temp) ^ TE444(temp);
rk[13] = rk[5] ^ rk[12];
rk[14] = rk[6] ^ rk[13];
rk[15] = rk[7] ^ rk[14];
rk += 8;
}
}
return -1;
}

172
core/crypto/aes-omac1.c Normal file
View File

@ -0,0 +1,172 @@
/*
* One-key CBC MAC (OMAC1) hash with AES
*
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "rtw_crypto_wrap.h"
#include "aes.h"
#include "aes_wrap.h"
static void gf_mulx(u8 *pad)
{
int i, carry;
carry = pad[0] & 0x80;
for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
pad[AES_BLOCK_SIZE - 1] <<= 1;
if (carry)
pad[AES_BLOCK_SIZE - 1] ^= 0x87;
}
/**
* omac1_aes_vector - One-Key CBC MAC (OMAC1) hash with AES
* @key: Key for the hash operation
* @key_len: Key length in octets
* @num_elem: Number of elements in the data vector
* @addr: Pointers to the data areas
* @len: Lengths of the data blocks
* @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
* Returns: 0 on success, -1 on failure
*
* This is a mode for using block cipher (AES in this case) for authentication.
* OMAC1 was standardized with the name CMAC by NIST in a Special Publication
* (SP) 800-38B.
*/
int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac)
{
void *ctx;
u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE];
const u8 *pos, *end;
size_t i, e, left, total_len;
if (TEST_FAIL())
return -1;
ctx = aes_encrypt_init(key, key_len);
if (ctx == NULL)
return -1;
os_memset(cbc, 0, AES_BLOCK_SIZE);
total_len = 0;
for (e = 0; e < num_elem; e++)
total_len += len[e];
left = total_len;
e = 0;
pos = addr[0];
end = pos + len[0];
while (left >= AES_BLOCK_SIZE) {
for (i = 0; i < AES_BLOCK_SIZE; i++) {
cbc[i] ^= *pos++;
if (pos >= end) {
/*
* Stop if there are no more bytes to process
* since there are no more entries in the array.
*/
if (i + 1 == AES_BLOCK_SIZE &&
left == AES_BLOCK_SIZE)
break;
e++;
pos = addr[e];
end = pos + len[e];
}
}
if (left > AES_BLOCK_SIZE)
aes_encrypt(ctx, cbc, cbc);
left -= AES_BLOCK_SIZE;
}
os_memset(pad, 0, AES_BLOCK_SIZE);
aes_encrypt(ctx, pad, pad);
gf_mulx(pad);
if (left || total_len == 0) {
for (i = 0; i < left; i++) {
cbc[i] ^= *pos++;
if (pos >= end) {
/*
* Stop if there are no more bytes to process
* since there are no more entries in the array.
*/
if (i + 1 == left)
break;
e++;
pos = addr[e];
end = pos + len[e];
}
}
cbc[left] ^= 0x80;
gf_mulx(pad);
}
for (i = 0; i < AES_BLOCK_SIZE; i++)
pad[i] ^= cbc[i];
aes_encrypt(ctx, pad, mac);
aes_encrypt_deinit(ctx);
return 0;
}
/**
* omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128
* @key: 128-bit key for the hash operation
* @num_elem: Number of elements in the data vector
* @addr: Pointers to the data areas
* @len: Lengths of the data blocks
* @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
* Returns: 0 on success, -1 on failure
*
* This is a mode for using block cipher (AES in this case) for authentication.
* OMAC1 was standardized with the name CMAC by NIST in a Special Publication
* (SP) 800-38B.
*/
int omac1_aes_128_vector(const u8 *key, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac)
{
return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
}
/**
* omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC)
* @key: 128-bit key for the hash operation
* @data: Data buffer for which a MAC is determined
* @data_len: Length of data buffer in bytes
* @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
* Returns: 0 on success, -1 on failure
*
* This is a mode for using block cipher (AES in this case) for authentication.
* OMAC1 was standardized with the name CMAC by NIST in a Special Publication
* (SP) 800-38B.
*/
int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
{
return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
}
/**
* omac1_aes_256 - One-Key CBC MAC (OMAC1) hash with AES-256 (aka AES-CMAC)
* @key: 256-bit key for the hash operation
* @data: Data buffer for which a MAC is determined
* @data_len: Length of data buffer in bytes
* @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
* Returns: 0 on success, -1 on failure
*
* This is a mode for using block cipher (AES in this case) for authentication.
* OMAC1 was standardized with the name CMAC by NIST in a Special Publication
* (SP) 800-38B.
*/
int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
{
return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
}

207
core/crypto/aes-siv.c Normal file
View File

@ -0,0 +1,207 @@
/*
* AES SIV (RFC 5297)
* Copyright (c) 2013 Cozybit, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "rtw_crypto_wrap.h"
#include "aes.h"
#include "aes_wrap.h"
#include "aes_siv.h"
static const u8 zero[AES_BLOCK_SIZE];
static void dbl(u8 *pad)
{
int i, carry;
carry = pad[0] & 0x80;
for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
pad[AES_BLOCK_SIZE - 1] <<= 1;
if (carry)
pad[AES_BLOCK_SIZE - 1] ^= 0x87;
}
static void xor(u8 *a, const u8 *b)
{
int i;
for (i = 0; i < AES_BLOCK_SIZE; i++)
*a++ ^= *b++;
}
static void xorend(u8 *a, int alen, const u8 *b, int blen)
{
int i;
if (alen < blen)
return;
for (i = 0; i < blen; i++)
a[alen - blen + i] ^= b[i];
}
static void pad_block(u8 *pad, const u8 *addr, size_t len)
{
os_memset(pad, 0, AES_BLOCK_SIZE);
os_memcpy(pad, addr, len);
if (len < AES_BLOCK_SIZE)
pad[len] = 0x80;
}
static int aes_s2v(const u8 *key, size_t key_len,
size_t num_elem, const u8 *addr[], size_t *len, u8 *mac)
{
u8 tmp[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE];
u8 *buf = NULL;
int ret;
size_t i;
const u8 *data[1];
size_t data_len[1];
if (!num_elem) {
os_memcpy(tmp, zero, sizeof(zero));
tmp[AES_BLOCK_SIZE - 1] = 1;
data[0] = tmp;
data_len[0] = sizeof(tmp);
return omac1_aes_vector(key, key_len, 1, data, data_len, mac);
}
data[0] = zero;
data_len[0] = sizeof(zero);
ret = omac1_aes_vector(key, key_len, 1, data, data_len, tmp);
if (ret)
return ret;
for (i = 0; i < num_elem - 1; i++) {
ret = omac1_aes_vector(key, key_len, 1, &addr[i], &len[i],
tmp2);
if (ret)
return ret;
dbl(tmp);
xor(tmp, tmp2);
}
if (len[i] >= AES_BLOCK_SIZE) {
buf = os_memdup(addr[i], len[i]);
if (!buf)
return -ENOMEM;
xorend(buf, len[i], tmp, AES_BLOCK_SIZE);
data[0] = buf;
ret = omac1_aes_vector(key, key_len, 1, data, &len[i], mac);
bin_clear_free(buf, len[i]);
return ret;
}
dbl(tmp);
pad_block(tmp2, addr[i], len[i]);
xor(tmp, tmp2);
data[0] = tmp;
data_len[0] = sizeof(tmp);
return omac1_aes_vector(key, key_len, 1, data, data_len, mac);
}
int aes_siv_encrypt(const u8 *key, size_t key_len,
const u8 *pw, size_t pwlen,
size_t num_elem, const u8 *addr[], const size_t *len,
u8 *out)
{
const u8 *_addr[6];
size_t _len[6];
const u8 *k1, *k2;
u8 v[AES_BLOCK_SIZE];
size_t i;
u8 *iv, *crypt_pw;
if (num_elem > ARRAY_SIZE(_addr) - 1 ||
(key_len != 32 && key_len != 48 && key_len != 64))
return -1;
key_len /= 2;
k1 = key;
k2 = key + key_len;
for (i = 0; i < num_elem; i++) {
_addr[i] = addr[i];
_len[i] = len[i];
}
_addr[num_elem] = pw;
_len[num_elem] = pwlen;
if (aes_s2v(k1, key_len, num_elem + 1, _addr, _len, v))
return -1;
iv = out;
crypt_pw = out + AES_BLOCK_SIZE;
os_memcpy(iv, v, AES_BLOCK_SIZE);
os_memcpy(crypt_pw, pw, pwlen);
/* zero out 63rd and 31st bits of ctr (from right) */
v[8] &= 0x7f;
v[12] &= 0x7f;
return aes_ctr_encrypt(k2, key_len, v, crypt_pw, pwlen);
}
int aes_siv_decrypt(const u8 *key, size_t key_len,
const u8 *iv_crypt, size_t iv_c_len,
size_t num_elem, const u8 *addr[], const size_t *len,
u8 *out)
{
const u8 *_addr[6];
size_t _len[6];
const u8 *k1, *k2;
size_t crypt_len;
size_t i;
int ret;
u8 iv[AES_BLOCK_SIZE];
u8 check[AES_BLOCK_SIZE];
if (iv_c_len < AES_BLOCK_SIZE || num_elem > ARRAY_SIZE(_addr) - 1 ||
(key_len != 32 && key_len != 48 && key_len != 64))
return -1;
crypt_len = iv_c_len - AES_BLOCK_SIZE;
key_len /= 2;
k1 = key;
k2 = key + key_len;
for (i = 0; i < num_elem; i++) {
_addr[i] = addr[i];
_len[i] = len[i];
}
_addr[num_elem] = out;
_len[num_elem] = crypt_len;
os_memcpy(iv, iv_crypt, AES_BLOCK_SIZE);
os_memcpy(out, iv_crypt + AES_BLOCK_SIZE, crypt_len);
iv[8] &= 0x7f;
iv[12] &= 0x7f;
ret = aes_ctr_encrypt(k2, key_len, iv, out, crypt_len);
if (ret)
return ret;
ret = aes_s2v(k1, key_len, num_elem + 1, _addr, _len, check);
if (ret)
return ret;
if (os_memcmp(check, iv_crypt, AES_BLOCK_SIZE) == 0)
return 0;
return -1;
}

21
core/crypto/aes.h Normal file
View File

@ -0,0 +1,21 @@
/*
* AES functions
* Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef AES_H
#define AES_H
#define AES_BLOCK_SIZE 16
void * aes_encrypt_init(const u8 *key, size_t len);
int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt);
void aes_encrypt_deinit(void *ctx);
void * aes_decrypt_init(const u8 *key, size_t len);
int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain);
void aes_decrypt_deinit(void *ctx);
#endif /* AES_H */

125
core/crypto/aes_i.h Normal file
View File

@ -0,0 +1,125 @@
/*
* AES (Rijndael) cipher
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef AES_I_H
#define AES_I_H
#include "aes.h"
/* #define FULL_UNROLL */
#define AES_SMALL_TABLES
extern const u32 Te0[256];
extern const u32 Te1[256];
extern const u32 Te2[256];
extern const u32 Te3[256];
extern const u32 Te4[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];
#ifndef AES_SMALL_TABLES
#define RCON(i) rcon[(i)]
#define TE0(i) Te0[((i) >> 24) & 0xff]
#define TE1(i) Te1[((i) >> 16) & 0xff]
#define TE2(i) Te2[((i) >> 8) & 0xff]
#define TE3(i) Te3[(i) & 0xff]
#define TE41(i) (Te4[((i) >> 24) & 0xff] & 0xff000000)
#define TE42(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000)
#define TE43(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00)
#define TE44(i) (Te4[(i) & 0xff] & 0x000000ff)
#define TE421(i) (Te4[((i) >> 16) & 0xff] & 0xff000000)
#define TE432(i) (Te4[((i) >> 8) & 0xff] & 0x00ff0000)
#define TE443(i) (Te4[(i) & 0xff] & 0x0000ff00)
#define TE414(i) (Te4[((i) >> 24) & 0xff] & 0x000000ff)
#define TE411(i) (Te4[((i) >> 24) & 0xff] & 0xff000000)
#define TE422(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000)
#define TE433(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00)
#define TE444(i) (Te4[(i) & 0xff] & 0x000000ff)
#define TE4(i) (Te4[(i)] & 0x000000ff)
#define TD0(i) Td0[((i) >> 24) & 0xff]
#define TD1(i) Td1[((i) >> 16) & 0xff]
#define TD2(i) Td2[((i) >> 8) & 0xff]
#define TD3(i) Td3[(i) & 0xff]
#define TD41(i) (Td4[((i) >> 24) & 0xff] & 0xff000000)
#define TD42(i) (Td4[((i) >> 16) & 0xff] & 0x00ff0000)
#define TD43(i) (Td4[((i) >> 8) & 0xff] & 0x0000ff00)
#define TD44(i) (Td4[(i) & 0xff] & 0x000000ff)
#define TD0_(i) Td0[(i) & 0xff]
#define TD1_(i) Td1[(i) & 0xff]
#define TD2_(i) Td2[(i) & 0xff]
#define TD3_(i) Td3[(i) & 0xff]
#else /* AES_SMALL_TABLES */
#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)
#define TE41(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000)
#define TE42(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000)
#define TE43(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00)
#define TE44(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff)
#define TE421(i) ((Te0[((i) >> 16) & 0xff] << 8) & 0xff000000)
#define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000)
#define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00)
#define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff)
#define TE411(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000)
#define TE422(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000)
#define TE433(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00)
#define TE444(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff)
#define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff)
#define TD0(i) Td0[((i) >> 24) & 0xff]
#define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8)
#define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16)
#define TD3(i) rotr(Td0[(i) & 0xff], 24)
#define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24)
#define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16)
#define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8)
#define TD44(i) (Td4s[(i) & 0xff])
#define TD0_(i) Td0[(i) & 0xff]
#define TD1_(i) rotr(Td0[(i) & 0xff], 8)
#define TD2_(i) rotr(Td0[(i) & 0xff], 16)
#define TD3_(i) rotr(Td0[(i) & 0xff], 24)
#endif /* AES_SMALL_TABLES */
#ifdef _MSC_VER
#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
#define GETU32(p) SWAP(*((u32 *)(p)))
#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
#else
#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \
((u32)(pt)[2] << 8) ^ ((u32)(pt)[3]))
#define PUTU32(ct, st) { \
(ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); \
(ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); }
#endif
#define AES_PRIV_SIZE (4 * 4 * 15 + 4)
#define AES_PRIV_NR_POS (4 * 15)
int rijndaelKeySetupEnc(u32 rk[], const u8 cipherKey[], int keyBits);
#endif /* AES_I_H */

21
core/crypto/aes_siv.h Normal file
View File

@ -0,0 +1,21 @@
/*
* AES SIV (RFC 5297)
* Copyright (c) 2013 Cozybit, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef AES_SIV_H
#define AES_SIV_H
int aes_siv_encrypt(const u8 *key, size_t key_len,
const u8 *pw, size_t pwlen,
size_t num_elem, const u8 *addr[], const size_t *len,
u8 *out);
int aes_siv_decrypt(const u8 *key, size_t key_len,
const u8 *iv_crypt, size_t iv_c_len,
size_t num_elem, const u8 *addr[], const size_t *len,
u8 *out);
#endif /* AES_SIV_H */

73
core/crypto/aes_wrap.h Normal file
View File

@ -0,0 +1,73 @@
/*
* AES-based functions
*
* - AES Key Wrap Algorithm (RFC3394)
* - One-Key CBC MAC (OMAC1) hash with AES-128 and AES-256
* - AES-128/192/256 CTR mode encryption
* - AES-128 EAX mode encryption/decryption
* - AES-128 CBC
* - AES-GCM
* - AES-CCM
*
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef AES_WRAP_H
#define AES_WRAP_H
int __must_check aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain,
u8 *cipher);
int __must_check aes_unwrap(const u8 *kek, size_t kek_len, int n,
const u8 *cipher, u8 *plain);
int __must_check omac1_aes_vector(const u8 *key, size_t key_len,
size_t num_elem, const u8 *addr[],
const size_t *len, u8 *mac);
int __must_check omac1_aes_128_vector(const u8 *key, size_t num_elem,
const u8 *addr[], const size_t *len,
u8 *mac);
int __must_check omac1_aes_128(const u8 *key, const u8 *data, size_t data_len,
u8 *mac);
int __must_check omac1_aes_256(const u8 *key, const u8 *data, size_t data_len,
u8 *mac);
int __must_check aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out);
int __must_check aes_ctr_encrypt(const u8 *key, size_t key_len, const u8 *nonce,
u8 *data, size_t data_len);
int __must_check aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
u8 *data, size_t data_len);
int __must_check aes_128_eax_encrypt(const u8 *key,
const u8 *nonce, size_t nonce_len,
const u8 *hdr, size_t hdr_len,
u8 *data, size_t data_len, u8 *tag);
int __must_check aes_128_eax_decrypt(const u8 *key,
const u8 *nonce, size_t nonce_len,
const u8 *hdr, size_t hdr_len,
u8 *data, size_t data_len, const u8 *tag);
int __must_check aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data,
size_t data_len);
int __must_check aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data,
size_t data_len);
int __must_check aes_gcm_ae(const u8 *key, size_t key_len,
const u8 *iv, size_t iv_len,
const u8 *plain, size_t plain_len,
const u8 *aad, size_t aad_len,
u8 *crypt, u8 *tag);
int __must_check aes_gcm_ad(const u8 *key, size_t key_len,
const u8 *iv, size_t iv_len,
const u8 *crypt, size_t crypt_len,
const u8 *aad, size_t aad_len, const u8 *tag,
u8 *plain);
int __must_check aes_gmac(const u8 *key, size_t key_len,
const u8 *iv, size_t iv_len,
const u8 *aad, size_t aad_len, u8 *tag);
int __must_check aes_ccm_ae(const u8 *key, size_t key_len, const u8 *nonce,
size_t M, const u8 *plain, size_t plain_len,
const u8 *aad, size_t aad_len, u8 *crypt, u8 *auth);
int __must_check aes_ccm_ad(const u8 *key, size_t key_len, const u8 *nonce,
size_t M, const u8 *crypt, size_t crypt_len,
const u8 *aad, size_t aad_len, const u8 *auth,
u8 *plain);
#endif /* AES_WRAP_H */

385
core/crypto/ccmp.c Normal file
View File

@ -0,0 +1,385 @@
/*
* CTR with CBC-MAC Protocol (CCMP)
* Copyright (c) 2010-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "rtw_crypto_wrap.h"
#include "aes.h"
#include "aes_wrap.h"
#include "wlancrypto_wrap.h"
static void ccmp_aad_nonce(_adapter *padapter, const struct ieee80211_hdr *hdr, const u8 *data,
u8 *aad, size_t *aad_len, u8 *nonce)
{
u16 fc, stype, seq;
int qos = 0, addr4 = 0;
u8 *pos;
nonce[0] = 0;
fc = le_to_host16(hdr->frame_control);
stype = WLAN_FC_GET_STYPE(fc);
if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
(WLAN_FC_TODS | WLAN_FC_FROMDS))
addr4 = 1;
if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA) {
fc &= ~0x0070; /* Mask subtype bits */
if (stype & WLAN_FC_STYPE_QOS_DATA) {
const u8 *qc;
qos = 1;
fc &= ~WLAN_FC_ORDER;
qc = (const u8 *)hdr + 24;
if (addr4)
qc += ETH_ALEN;
nonce[0] = qc[0] & 0x0f;
}
} else if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT)
nonce[0] |= 0x10; /* Management */
fc &= ~(WLAN_FC_RETRY | WLAN_FC_PWRMGT | WLAN_FC_MOREDATA);
fc |= WLAN_FC_ISWEP;
WPA_PUT_LE16(aad, fc);
pos = aad + 2;
os_memcpy(pos, GetAddr1Ptr((u8 *)hdr), 3 * ETH_ALEN);
pos += 3 * ETH_ALEN;
seq = le_to_host16(hdr->seq_ctrl);
seq &= ~0xfff0; /* Mask Seq#; do not modify Frag# */
WPA_PUT_LE16(pos, seq);
pos += 2;
os_memcpy(pos, (u8 *)hdr + 24, addr4 * ETH_ALEN + qos * 2);
pos += addr4 * ETH_ALEN;
if (qos) {
pos[0] &= ~0x70;
/* only spp mode need to refer QoS bit7 */
if (padapter->registrypriv.amsdu_mode != RTW_AMSDU_MODE_SPP)
pos[0] &= ~0x80;
pos++;
*pos++ = 0x00;
}
*aad_len = pos - aad;
os_memcpy(nonce + 1, hdr->addr2, ETH_ALEN);
nonce[7] = data[7]; /* PN5 */
nonce[8] = data[6]; /* PN4 */
nonce[9] = data[5]; /* PN3 */
nonce[10] = data[4]; /* PN2 */
nonce[11] = data[1]; /* PN1 */
nonce[12] = data[0]; /* PN0 */
}
static void ccmp_aad_nonce_pv1(const u8 *hdr, const u8 *a1, const u8 *a2,
const u8 *a3, const u8 *pn,
u8 *aad, size_t *aad_len, u8 *nonce)
{
u16 fc, type;
u8 *pos;
nonce[0] = BIT(5); /* PV1 */
/* TODO: Priority for QMF; 0 is used for Data frames */
fc = WPA_GET_LE16(hdr);
type = (fc & (BIT(2) | BIT(3) | BIT(4))) >> 2;
if (type == 1)
nonce[0] |= 0x10; /* Management */
fc &= ~(BIT(10) | BIT(11) | BIT(13) | BIT(14) | BIT(15));
fc |= BIT(12);
WPA_PUT_LE16(aad, fc);
pos = aad + 2;
if (type == 0 || type == 3) {
const u8 *sc;
os_memcpy(pos, a1, ETH_ALEN);
pos += ETH_ALEN;
os_memcpy(pos, a2, ETH_ALEN);
pos += ETH_ALEN;
if (type == 0) {
/* Either A1 or A2 contains SID */
sc = hdr + 2 + 2 + ETH_ALEN;
} else {
/* Both A1 and A2 contain full addresses */
sc = hdr + 2 + 2 * ETH_ALEN;
}
/* SC with Sequence Number subfield (bits 4-15 of the Sequence
* Control field) masked to 0. */
*pos++ = *sc & 0x0f;
*pos++ = 0;
if (a3) {
os_memcpy(pos, a3, ETH_ALEN);
pos += ETH_ALEN;
}
}
*aad_len = pos - aad;
os_memcpy(nonce + 1, a2, ETH_ALEN);
nonce[7] = pn[5]; /* PN5 */
nonce[8] = pn[4]; /* PN4 */
nonce[9] = pn[3]; /* PN3 */
nonce[10] = pn[2]; /* PN2 */
nonce[11] = pn[1]; /* PN1 */
nonce[12] = pn[0]; /* PN0 */
}
u8 * ccmp_decrypt(_adapter *padapter, const u8 *tk, const struct ieee80211_hdr *hdr,
const u8 *data, size_t data_len, size_t *decrypted_len)
{
u8 aad[30], nonce[13];
size_t aad_len;
size_t mlen;
u8 *plain;
if (data_len < 8 + 8)
return NULL;
plain = os_malloc(data_len + AES_BLOCK_SIZE);
if (plain == NULL)
return NULL;
mlen = data_len - 8 - 8;
os_memset(aad, 0, sizeof(aad));
ccmp_aad_nonce(padapter, hdr, data, aad, &aad_len, nonce);
wpa_hexdump(_MSG_EXCESSIVE_, "CCMP AAD", aad, aad_len);
wpa_hexdump(_MSG_EXCESSIVE_, "CCMP nonce", nonce, 13);
if (aes_ccm_ad(tk, 16, nonce, 8, data + 8, mlen, aad, aad_len,
data + 8 + mlen, plain) < 0) {
u16 seq_ctrl = le_to_host16(hdr->seq_ctrl);
wpa_printf(_MSG_INFO_, "Invalid CCMP MIC in frame: A1=" MACSTR
" A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u",
MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
MAC2STR(hdr->addr3),
WLAN_GET_SEQ_SEQ(seq_ctrl),
WLAN_GET_SEQ_FRAG(seq_ctrl));
rtw_mfree(plain, data_len + AES_BLOCK_SIZE);
return NULL;
}
wpa_hexdump(_MSG_EXCESSIVE_, "CCMP decrypted", plain, mlen);
*decrypted_len = mlen;
return plain;
}
void ccmp_get_pn(u8 *pn, const u8 *data)
{
pn[0] = data[7]; /* PN5 */
pn[1] = data[6]; /* PN4 */
pn[2] = data[5]; /* PN3 */
pn[3] = data[4]; /* PN2 */
pn[4] = data[1]; /* PN1 */
pn[5] = data[0]; /* PN0 */
}
u8 * ccmp_encrypt(_adapter *padapter, const u8 *tk, u8 *frame, size_t len, size_t hdrlen, u8 *qos,
u8 *pn, int keyid, size_t *encrypted_len)
{
u8 aad[30], nonce[13];
size_t aad_len, plen;
u8 *crypt, *pos, *pdata;
struct ieee80211_hdr *hdr;
if (len < hdrlen || hdrlen < 24)
return NULL;
plen = len - hdrlen;
crypt = os_malloc(hdrlen + 8 + plen + 8 + AES_BLOCK_SIZE);
if (crypt == NULL)
return NULL;
if (pn == NULL) {
os_memcpy(crypt, frame, hdrlen + 8);
hdr = (struct ieee80211_hdr *) crypt;
hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
pos = crypt + hdrlen + 8;
pdata = frame + hdrlen + 8;
} else {
os_memcpy(crypt, frame, hdrlen);
hdr = (struct ieee80211_hdr *) crypt;
hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
pos = crypt + hdrlen;
*pos++ = pn[5]; /* PN0 */
*pos++ = pn[4]; /* PN1 */
*pos++ = 0x00; /* Rsvd */
*pos++ = 0x20 | (keyid << 6);
*pos++ = pn[3]; /* PN2 */
*pos++ = pn[2]; /* PN3 */
*pos++ = pn[1]; /* PN4 */
*pos++ = pn[0]; /* PN5 */
pdata = frame + hdrlen;
}
os_memset(aad, 0, sizeof(aad));
ccmp_aad_nonce(padapter, hdr, crypt + hdrlen, aad, &aad_len, nonce);
wpa_hexdump(_MSG_EXCESSIVE_, "CCMP AAD", aad, aad_len);
wpa_hexdump(_MSG_EXCESSIVE_, "CCMP nonce", nonce, 13);
if (aes_ccm_ae(tk, 16, nonce, 8, pdata, plen, aad, aad_len,
pos, pos + plen) < 0) {
rtw_mfree(crypt, hdrlen + 8 + plen + 8 + AES_BLOCK_SIZE);
return NULL;
}
wpa_hexdump(_MSG_EXCESSIVE_, "CCMP encrypted", crypt + hdrlen + 8, plen);
*encrypted_len = hdrlen + 8 + plen + 8;
return crypt;
}
u8 * ccmp_encrypt_pv1(const u8 *tk, const u8 *a1, const u8 *a2, const u8 *a3,
const u8 *frame, size_t len,
size_t hdrlen, const u8 *pn, int keyid,
size_t *encrypted_len)
{
u8 aad[24], nonce[13];
size_t aad_len, plen;
u8 *crypt, *pos;
struct ieee80211_hdr *hdr;
if (len < hdrlen || hdrlen < 12)
return NULL;
plen = len - hdrlen;
crypt = os_malloc(hdrlen + plen + 8 + AES_BLOCK_SIZE);
if (crypt == NULL)
return NULL;
os_memcpy(crypt, frame, hdrlen);
hdr = (struct ieee80211_hdr *) crypt;
hdr->frame_control |= host_to_le16(BIT(12)); /* Protected Frame */
pos = crypt + hdrlen;
os_memset(aad, 0, sizeof(aad));
ccmp_aad_nonce_pv1(crypt, a1, a2, a3, pn, aad, &aad_len, nonce);
wpa_hexdump(_MSG_EXCESSIVE_, "CCMP AAD", aad, aad_len);
wpa_hexdump(_MSG_EXCESSIVE_, "CCMP nonce", nonce, sizeof(nonce));
if (aes_ccm_ae(tk, 16, nonce, 8, frame + hdrlen, plen, aad, aad_len,
pos, pos + plen) < 0) {
rtw_mfree(crypt, hdrlen + plen + 8 + AES_BLOCK_SIZE);
return NULL;
}
wpa_hexdump(_MSG_EXCESSIVE_, "CCMP encrypted", crypt + hdrlen, plen);
*encrypted_len = hdrlen + plen + 8;
return crypt;
}
u8 * ccmp_256_decrypt(_adapter *padapter, const u8 *tk, const struct ieee80211_hdr *hdr,
const u8 *data, size_t data_len, size_t *decrypted_len)
{
u8 aad[30], nonce[13];
size_t aad_len;
size_t mlen;
u8 *plain;
if (data_len < 8 + 16)
return NULL;
plain = os_malloc(data_len + AES_BLOCK_SIZE);
if (plain == NULL)
return NULL;
mlen = data_len - 8 - 16;
os_memset(aad, 0, sizeof(aad));
ccmp_aad_nonce(padapter, hdr, data, aad, &aad_len, nonce);
wpa_hexdump(_MSG_EXCESSIVE_, "CCMP-256 AAD", aad, aad_len);
wpa_hexdump(_MSG_EXCESSIVE_, "CCMP-256 nonce", nonce, 13);
if (aes_ccm_ad(tk, 32, nonce, 16, data + 8, mlen, aad, aad_len,
data + 8 + mlen, plain) < 0) {
u16 seq_ctrl = le_to_host16(hdr->seq_ctrl);
wpa_printf(_MSG_INFO_, "Invalid CCMP-256 MIC in frame: A1=" MACSTR
" A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u",
MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
MAC2STR(hdr->addr3),
WLAN_GET_SEQ_SEQ(seq_ctrl),
WLAN_GET_SEQ_FRAG(seq_ctrl));
rtw_mfree(plain, data_len + AES_BLOCK_SIZE);
return NULL;
}
wpa_hexdump(_MSG_EXCESSIVE_, "CCMP-256 decrypted", plain, mlen);
*decrypted_len = mlen;
return plain;
}
u8 * ccmp_256_encrypt(_adapter *padapter, const u8 *tk, u8 *frame, size_t len, size_t hdrlen,
u8 *qos, u8 *pn, int keyid, size_t *encrypted_len)
{
u8 aad[30], nonce[13];
size_t aad_len, plen;
u8 *crypt, *pos, *pdata;
struct ieee80211_hdr *hdr;
if (len < hdrlen || hdrlen < 24)
return NULL;
plen = len - hdrlen;
crypt = os_malloc(hdrlen + 8 + plen + 16 + AES_BLOCK_SIZE);
if (crypt == NULL)
return NULL;
if (pn == NULL) {
os_memcpy(crypt, frame, hdrlen + 8);
hdr = (struct ieee80211_hdr *) crypt;
hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
pos = crypt + hdrlen + 8;
pdata = frame + hdrlen + 8;
} else {
os_memcpy(crypt, frame, hdrlen);
hdr = (struct ieee80211_hdr *) crypt;
hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
pos = crypt + hdrlen;
*pos++ = pn[5]; /* PN0 */
*pos++ = pn[4]; /* PN1 */
*pos++ = 0x00; /* Rsvd */
*pos++ = 0x20 | (keyid << 6);
*pos++ = pn[3]; /* PN2 */
*pos++ = pn[2]; /* PN3 */
*pos++ = pn[1]; /* PN4 */
*pos++ = pn[0]; /* PN5 */
pdata = frame + hdrlen;
}
os_memset(aad, 0, sizeof(aad));
ccmp_aad_nonce(padapter, hdr, crypt + hdrlen, aad, &aad_len, nonce);
wpa_hexdump(_MSG_EXCESSIVE_, "CCMP-256 AAD", aad, aad_len);
wpa_hexdump(_MSG_EXCESSIVE_, "CCMP-256 nonce", nonce, 13);
if (aes_ccm_ae(tk, 32, nonce, 16, pdata, plen, aad, aad_len,
pos, pos + plen) < 0) {
rtw_mfree(crypt, hdrlen + 8 + plen + 16 + AES_BLOCK_SIZE);
return NULL;
}
wpa_hexdump(_MSG_EXCESSIVE_, "CCMP-256 encrypted", crypt + hdrlen + 8,
plen);
*encrypted_len = hdrlen + 8 + plen + 16;
return crypt;
}

194
core/crypto/gcmp.c Normal file
View File

@ -0,0 +1,194 @@
/*
* GCM with GMAC Protocol (GCMP)
* Copyright (c) 2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "rtw_crypto_wrap.h"
#include "aes.h"
#include "aes_wrap.h"
#include "wlancrypto_wrap.h"
static void gcmp_aad_nonce(_adapter * padapter, const struct ieee80211_hdr *hdr, const u8 *data,
u8 *aad, size_t *aad_len, u8 *nonce)
{
u16 fc, stype, seq;
int qos = 0, addr4 = 0;
u8 *pos;
fc = le_to_host16(hdr->frame_control);
stype = WLAN_FC_GET_STYPE(fc);
if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
(WLAN_FC_TODS | WLAN_FC_FROMDS))
addr4 = 1;
if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA) {
fc &= ~0x0070; /* Mask subtype bits */
if (stype & WLAN_FC_STYPE_QOS_DATA) {
const u8 *qc;
qos = 1;
fc &= ~WLAN_FC_ORDER;
qc = (const u8 *)hdr + 24;
if (addr4)
qc += ETH_ALEN;
}
}
fc &= ~(WLAN_FC_RETRY | WLAN_FC_PWRMGT | WLAN_FC_MOREDATA);
WPA_PUT_LE16(aad, fc);
pos = aad + 2;
os_memcpy(pos, GetAddr1Ptr((u8 *)hdr), 3 * ETH_ALEN);
pos += 3 * ETH_ALEN;
seq = le_to_host16(hdr->seq_ctrl);
seq &= ~0xfff0; /* Mask Seq#; do not modify Frag# */
WPA_PUT_LE16(pos, seq);
pos += 2;
wpa_printf(_MSG_INFO_, "pos - aad = %u, qos(%d)\n", (pos - aad), qos);
os_memcpy(pos, (u8 *)hdr + 24, addr4 * ETH_ALEN + qos * 2);
pos += addr4 * ETH_ALEN;
if (qos) {
pos[0] &= ~0x70;
/* only spp mode need to refer QoS bit7 */
if (padapter->registrypriv.amsdu_mode != RTW_AMSDU_MODE_SPP)
pos[0] &= ~0x80;
pos++;
*pos++ = 0x00;
}
wpa_printf(_MSG_INFO_, "pos - aad = %u\n", (pos - aad));
*aad_len = pos - aad;
os_memcpy(nonce, hdr->addr2, ETH_ALEN);
nonce[6] = data[7]; /* PN5 */
nonce[7] = data[6]; /* PN4 */
nonce[8] = data[5]; /* PN3 */
nonce[9] = data[4]; /* PN2 */
nonce[10] = data[1]; /* PN1 */
nonce[11] = data[0]; /* PN0 */
}
/**
* gcmp_decrypt -
* @tk: the temporal key
* @tk_len: length of @tk
* @hdr: the mac header
* @data: payload after mac header (PN + enc_data + MIC)
* @data_len: length of @data (PN + enc_data + MIC)
* @decrypted_len: length of the data decrypted
*/
u8 * gcmp_decrypt(_adapter *padapter, const u8 *tk, size_t tk_len, const struct ieee80211_hdr *hdr,
const u8 *data, size_t data_len, size_t *decrypted_len)
{
u8 aad[30], nonce[12], *plain;
size_t aad_len, mlen;
const u8 *m;
if (data_len < 8 + 16)
return NULL;
plain = os_malloc(data_len + AES_BLOCK_SIZE);
if (plain == NULL)
return NULL;
m = data + 8;
mlen = data_len - 8 - 16;
os_memset(aad, 0, sizeof(aad));
gcmp_aad_nonce(padapter, hdr, data, aad, &aad_len, nonce);
wpa_hexdump(_MSG_EXCESSIVE_, "GCMP AAD", aad, aad_len);
wpa_hexdump(_MSG_EXCESSIVE_, "GCMP nonce", nonce, sizeof(nonce));
if (aes_gcm_ad(tk, tk_len, nonce, sizeof(nonce), m, mlen, aad, aad_len,
m + mlen, plain) < 0) {
u16 seq_ctrl = le_to_host16(hdr->seq_ctrl);
wpa_printf(_MSG_INFO_, "Invalid GCMP frame: A1=" MACSTR
" A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u",
MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
MAC2STR(hdr->addr3),
WLAN_GET_SEQ_SEQ(seq_ctrl),
WLAN_GET_SEQ_FRAG(seq_ctrl));
rtw_mfree(plain, data_len + AES_BLOCK_SIZE);
return NULL;
}
*decrypted_len = mlen;
return plain;
}
/**
* gcmp_encrypt -
* @tk: the temporal key
* @tk_len: length of @tk
* @frame: the point to mac header, the frame including mac header and payload,
* if @pn is NULL, then the frame including pn
* @len: length of @frame
* length = mac header + payload
* @hdrlen: length of the mac header
* @qos: pointer to the QOS field of the frame
* @pn: packet number
* @keyid: key id
* @encrypted_len: length of the encrypted frame
* including mac header, pn, payload and MIC
*/
u8 * gcmp_encrypt(_adapter *padapter, const u8 *tk, size_t tk_len, const u8 *frame, size_t len,
size_t hdrlen, const u8 *qos,
const u8 *pn, int keyid, size_t *encrypted_len)
{
u8 aad[30], nonce[12], *crypt, *pos;
const u8 *pdata;
size_t aad_len, plen;
struct ieee80211_hdr *hdr;
if (len < hdrlen || hdrlen < 24)
return NULL;
plen = len - hdrlen;
crypt = os_malloc(hdrlen + 8 + plen + 16 + AES_BLOCK_SIZE);
if (crypt == NULL)
return NULL;
if (pn == NULL) {
os_memcpy(crypt, frame, hdrlen + 8);
hdr = (struct ieee80211_hdr *)crypt;
pos = crypt + hdrlen + 8;
pdata = frame + hdrlen + 8;
} else {
os_memcpy(crypt, frame, hdrlen);
hdr = (struct ieee80211_hdr *)crypt;
pos = crypt + hdrlen;
*pos++ = pn[5]; /* PN0 */
*pos++ = pn[4]; /* PN1 */
*pos++ = 0x00; /* Rsvd */
*pos++ = 0x20 | (keyid << 6);
*pos++ = pn[3]; /* PN2 */
*pos++ = pn[2]; /* PN3 */
*pos++ = pn[1]; /* PN4 */
*pos++ = pn[0]; /* PN5 */
pdata = frame + hdrlen;
}
os_memset(aad, 0, sizeof(aad));
gcmp_aad_nonce(padapter, hdr, crypt + hdrlen, aad, &aad_len, nonce);
wpa_hexdump(_MSG_EXCESSIVE_, "GCMP AAD", aad, aad_len);
wpa_hexdump(_MSG_EXCESSIVE_, "GCMP nonce", nonce, sizeof(nonce));
if (aes_gcm_ae(tk, tk_len, nonce, sizeof(nonce), pdata, plen,
aad, aad_len, pos, pos + plen) < 0) {
rtw_mfree(crypt, hdrlen + 8 + plen + 16 + AES_BLOCK_SIZE);
return NULL;
}
wpa_hexdump(_MSG_EXCESSIVE_, "GCMP MIC", pos + plen, 16);
wpa_hexdump(_MSG_EXCESSIVE_, "GCMP encrypted", pos, plen);
*encrypted_len = hdrlen + 8 + plen + 16;
return crypt;
}

View File

@ -0,0 +1,85 @@
#include "rtw_crypto_wrap.h"
#ifndef DEBUG_CRYPTO
#define DEBUG_CRYPTO 0
#endif /* DEBUG_CRYTO */
int os_memcmp(const void *s1, const void *s2, size_t n)
{
return _rtw_memcmp2(s1, s2, n);
}
int os_memcmp_const(const void *a, const void *b, size_t len)
{
const u8 *aa = a;
const u8 *bb = b;
size_t i;
u8 res;
for (res = 0, i = 0; i < len; i++)
res |= aa[i] ^ bb[i];
return res;
}
void* os_memdup(const void *src, u32 sz)
{
void *r = rtw_malloc(sz);
if (r && src)
_rtw_memcpy(r, src, sz);
return r;
}
size_t os_strlen(const char *s)
{
const char *p = s;
while (*p)
p++;
return p - s;
}
void forced_memzero(void *ptr, size_t len)
{
_rtw_memset(ptr, 0, len);
}
void bin_clear_free(void *bin, size_t len)
{
if (bin) {
forced_memzero(bin, len);
rtw_mfree(bin, len);
}
}
void wpa_printf(int level, const char *fmt, ...)
{
#if DEBUG_CRYPTO
#define MSG_LEN 100
va_list args;
u8 buf[MSG_LEN] = { 0 };
int err;
va_start(args, fmt);
err = vsnprintf(buf, MSG_LEN, fmt, args);
va_end(args);
RTW_INFO("%s", buf);
#undef MSG_LEN
#endif /* DEBUG_CRYPTO */
}
void wpa_hexdump(int level, const char *title, const void *buf, size_t len)
{
#if DEBUG_CRYPTO
RTW_INFO_DUMP((u8 *)title, buf, len);
#endif /* DEBUG_CRYPTO */
}
void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len)
{
#if DEBUG_CRYPTO
RTW_INFO_DUMP((u8 *)title, buf, len);
#endif /* DEBUG_CRYPTO */
}

View File

@ -0,0 +1,64 @@
#ifndef RTW_CRYTO_WRAP_H
#define RTW_CRYTO_WRAP_H
#include <drv_types.h>
#define TEST_FAIL() 0
#define os_memset _rtw_memset
#define os_memcpy _rtw_memcpy
#define os_malloc rtw_malloc
#define le_to_host16 le16_to_cpu
#define host_to_le16 cpu_to_le16
#define WPA_PUT_LE16 RTW_PUT_LE16
#define WPA_GET_LE16 RTW_GET_LE16
#define WPA_PUT_LE32 RTW_PUT_LE32
#define WPA_GET_LE32 RTW_GET_LE32
#define WPA_PUT_LE64 RTW_PUT_LE64
#define WPA_GET_LE64 RTW_GET_LE64
#define WPA_PUT_BE16 RTW_PUT_BE16
#define WPA_GET_BE16 RTW_GET_BE16
#define WPA_PUT_BE32 RTW_PUT_BE32
#define WPA_GET_BE32 RTW_GET_BE32
#define WPA_PUT_BE64 RTW_PUT_BE64
#define WPA_GET_BE64 RTW_GET_BE64
#ifndef MAC2STR
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
#endif
#define WLAN_FC_PVER 0x0003
#define WLAN_FC_TODS 0x0100
#define WLAN_FC_FROMDS 0x0200
#define WLAN_FC_MOREFRAG 0x0400
#define WLAN_FC_RETRY 0x0800
#define WLAN_FC_PWRMGT 0x1000
#define WLAN_FC_MOREDATA 0x2000
#define WLAN_FC_ISWEP 0x4000
#define WLAN_FC_ORDER 0x8000
#define WLAN_FC_TYPE_DATA RTW_IEEE80211_FTYPE_DATA
#define WLAN_FC_TYPE_MGMT RTW_IEEE80211_FTYPE_MGMT
#define WLAN_FC_STYPE_QOS_DATA RTW_IEEE80211_STYPE_QOS_DATA
enum {
_MSG_EXCESSIVE_, _MSG_MSGDUMP_, _MSG_DEBUG_, _MSG_INFO_, _MSG_WARNING_, _MSG_ERROR_
};
int os_memcmp(const void *s1, const void *s2, size_t n);
int os_memcmp_const(const void *a, const void *b, size_t len);
void* os_memdup(const void *src, u32 sz);
size_t os_strlen(const char *s);
void forced_memzero(void *ptr, size_t len);
void bin_clear_free(void *bin, size_t len);
void wpa_printf(int level, const char *fmt, ...);
void wpa_hexdump(int level, const char *title, const void *buf, size_t len);
void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len);
#endif /* RTW_CRYTO_WRAP_H */

View File

@ -0,0 +1,230 @@
/*
* SHA-256 hash implementation and interface functions
* Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "rtw_crypto_wrap.h"
//#include "common.h"
#include "sha256.h"
#include "sha256_i.h"
//#include "crypto.h"
#include "wlancrypto_wrap.h"
/**
* sha256_vector - SHA256 hash for data vector
* @num_elem: Number of elements in the data vector
* @addr: Pointers to the data areas
* @len: Lengths of the data blocks
* @mac: Buffer for the hash
* Returns: 0 on success, -1 of failure
*/
int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
u8 *mac)
{
struct _sha256_state ctx;
size_t i;
if (TEST_FAIL())
return -1;
_sha256_init(&ctx);
for (i = 0; i < num_elem; i++)
if (sha256_process(&ctx, addr[i], len[i]))
return -1;
if (sha256_done(&ctx, mac))
return -1;
return 0;
}
/* ===== 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))
#ifndef MIN
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#endif
/* compress 512-bits */
static int sha256_compress(struct _sha256_state *md, unsigned char *buf)
{
u32 S[8], W[64], t0, t1;
u32 t;
int i;
/* copy state into S */
for (i = 0; i < 8; i++) {
S[i] = md->state[i];
}
/* copy the state into 512-bits into W[0..15] */
for (i = 0; i < 16; i++)
W[i] = WPA_GET_BE32(buf + (4 * i));
/* fill W[16..63] */
for (i = 16; i < 64; i++) {
W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) +
W[i - 16];
}
/* Compress */
#define RND(a,b,c,d,e,f,g,h,i) \
t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
t1 = Sigma0(a) + Maj(a, b, c); \
d += t0; \
h = t0 + t1;
for (i = 0; i < 64; ++i) {
RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
}
/* feedback */
for (i = 0; i < 8; i++) {
md->state[i] = md->state[i] + S[i];
}
return 0;
}
/* Initialize the hash state */
void _sha256_init(struct _sha256_state *md)
{
md->curlen = 0;
md->length = 0;
md->state[0] = 0x6A09E667UL;
md->state[1] = 0xBB67AE85UL;
md->state[2] = 0x3C6EF372UL;
md->state[3] = 0xA54FF53AUL;
md->state[4] = 0x510E527FUL;
md->state[5] = 0x9B05688CUL;
md->state[6] = 0x1F83D9ABUL;
md->state[7] = 0x5BE0CD19UL;
}
/**
Process a block of memory though the hash
@param md The hash state
@param in The data to hash
@param inlen The length of the data (octets)
@return CRYPT_OK if successful
*/
int sha256_process(struct _sha256_state *md, const unsigned char *in,
unsigned long inlen)
{
unsigned long n;
if (md->curlen >= sizeof(md->buf))
return -1;
while (inlen > 0) {
if (md->curlen == 0 && inlen >= SHA256_BLOCK_SIZE) {
if (sha256_compress(md, (unsigned char *) in) < 0)
return -1;
md->length += SHA256_BLOCK_SIZE * 8;
in += SHA256_BLOCK_SIZE;
inlen -= SHA256_BLOCK_SIZE;
} else {
n = MIN(inlen, (SHA256_BLOCK_SIZE - md->curlen));
os_memcpy(md->buf + md->curlen, in, n);
md->curlen += n;
in += n;
inlen -= n;
if (md->curlen == SHA256_BLOCK_SIZE) {
if (sha256_compress(md, md->buf) < 0)
return -1;
md->length += 8 * SHA256_BLOCK_SIZE;
md->curlen = 0;
}
}
}
return 0;
}
/**
Terminate the hash to get the digest
@param md The hash state
@param out [out] The destination of the hash (32 bytes)
@return CRYPT_OK if successful
*/
int sha256_done(struct _sha256_state *md, unsigned char *out)
{
int i;
if (md->curlen >= sizeof(md->buf))
return -1;
/* increase the length of the message */
md->length += md->curlen * 8;
/* append the '1' bit */
md->buf[md->curlen++] = (unsigned char) 0x80;
/* if the length is currently above 56 bytes we append zeros
* then compress. Then we can fall back to padding zeros and length
* encoding like normal.
*/
if (md->curlen > 56) {
while (md->curlen < SHA256_BLOCK_SIZE) {
md->buf[md->curlen++] = (unsigned char) 0;
}
sha256_compress(md, md->buf);
md->curlen = 0;
}
/* pad up to 56 bytes of zeroes */
while (md->curlen < 56) {
md->buf[md->curlen++] = (unsigned char) 0;
}
/* store length */
WPA_PUT_BE64(md->buf + 56, md->length);
sha256_compress(md, md->buf);
/* copy output */
for (i = 0; i < 8; i++)
WPA_PUT_BE32(out + (4 * i), md->state[i]);
return 0;
}
/* ===== end - public domain SHA256 implementation ===== */

109
core/crypto/sha256-prf.c Normal file
View File

@ -0,0 +1,109 @@
/*
* SHA256-based PRF (IEEE 802.11r)
* Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "rtw_crypto_wrap.h"
//#include "common.h"
#include "sha256.h"
//#include "crypto.h"
#include "wlancrypto_wrap.h"
/**
* sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5.1.5.2)
* @key: Key for PRF
* @key_len: Length of the key in bytes
* @label: A unique label for each purpose of the PRF
* @data: Extra data to bind into the key
* @data_len: Length of the data
* @buf: Buffer for the generated pseudo-random key
* @buf_len: Number of bytes of key to generate
* Returns: 0 on success, -1 on failure
*
* This function is used to derive new, cryptographically separate keys from a
* given key.
*/
int sha256_prf(const u8 *key, size_t key_len, const char *label,
const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
{
return sha256_prf_bits(key, key_len, label, data, data_len, buf,
buf_len * 8);
}
/**
* sha256_prf_bits - IEEE Std 802.11-2012, 11.6.1.7.2 Key derivation function
* @key: Key for KDF
* @key_len: Length of the key in bytes
* @label: A unique label for each purpose of the PRF
* @data: Extra data to bind into the key
* @data_len: Length of the data
* @buf: Buffer for the generated pseudo-random key
* @buf_len: Number of bits of key to generate
* Returns: 0 on success, -1 on failure
*
* This function is used to derive new, cryptographically separate keys from a
* given key. If the requested buf_len is not divisible by eight, the least
* significant 1-7 bits of the last octet in the output are not part of the
* requested output.
*/
int sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
const u8 *data, size_t data_len, u8 *buf,
size_t buf_len_bits)
{
u16 counter = 1;
size_t pos, plen;
u8 hash[SHA256_MAC_LEN];
const u8 *addr[4];
size_t len[4];
u8 counter_le[2], length_le[2];
size_t buf_len = (buf_len_bits + 7) / 8;
addr[0] = counter_le;
len[0] = 2;
addr[1] = (u8 *) label;
len[1] = os_strlen(label);
addr[2] = data;
len[2] = data_len;
addr[3] = length_le;
len[3] = sizeof(length_le);
WPA_PUT_LE16(length_le, buf_len_bits);
pos = 0;
while (pos < buf_len) {
plen = buf_len - pos;
WPA_PUT_LE16(counter_le, counter);
if (plen >= SHA256_MAC_LEN) {
if (hmac_sha256_vector(key, key_len, 4, addr, len,
&buf[pos]) < 0)
return -1;
pos += SHA256_MAC_LEN;
} else {
if (hmac_sha256_vector(key, key_len, 4, addr, len,
hash) < 0)
return -1;
os_memcpy(&buf[pos], hash, plen);
pos += plen;
break;
}
counter++;
}
/*
* Mask out unused bits in the last octet if it does not use all the
* bits.
*/
if (buf_len_bits % 8) {
u8 mask = 0xff << (8 - buf_len_bits % 8);
buf[pos - 1] &= mask;
}
forced_memzero(hash, sizeof(hash));
return 0;
}

104
core/crypto/sha256.c Normal file
View File

@ -0,0 +1,104 @@
/*
* SHA-256 hash implementation and interface functions
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "rtw_crypto_wrap.h"
#include "sha256.h"
//#include "crypto.h"
#include "wlancrypto_wrap.h"
/**
* hmac_sha256_vector - HMAC-SHA256 over data vector (RFC 2104)
* @key: Key for HMAC operations
* @key_len: Length of the key in bytes
* @num_elem: Number of elements in the data vector
* @addr: Pointers to the data areas
* @len: Lengths of the data blocks
* @mac: Buffer for the hash (32 bytes)
* Returns: 0 on success, -1 on failure
*/
int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac)
{
unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */
unsigned char tk[32];
const u8 *_addr[6];
size_t _len[6], i;
if (num_elem > 5) {
/*
* Fixed limit on the number of fragments to avoid having to
* allocate memory (which could fail).
*/
return -1;
}
/* if key is longer than 64 bytes reset it to key = SHA256(key) */
if (key_len > 64) {
if (sha256_vector(1, &key, &key_len, tk) < 0)
return -1;
key = tk;
key_len = 32;
}
/* the HMAC_SHA256 transform looks like:
*
* SHA256(K XOR opad, SHA256(K XOR ipad, text))
*
* where K is an n byte key
* ipad is the byte 0x36 repeated 64 times
* opad is the byte 0x5c repeated 64 times
* and text is the data being protected */
/* start out by storing key in ipad */
os_memset(k_pad, 0, sizeof(k_pad));
os_memcpy(k_pad, key, key_len);
/* XOR key with ipad values */
for (i = 0; i < 64; i++)
k_pad[i] ^= 0x36;
/* perform inner SHA256 */
_addr[0] = k_pad;
_len[0] = 64;
for (i = 0; i < num_elem; i++) {
_addr[i + 1] = addr[i];
_len[i + 1] = len[i];
}
if (sha256_vector(1 + num_elem, _addr, _len, mac) < 0)
return -1;
os_memset(k_pad, 0, sizeof(k_pad));
os_memcpy(k_pad, key, key_len);
/* XOR key with opad values */
for (i = 0; i < 64; i++)
k_pad[i] ^= 0x5c;
/* perform outer SHA256 */
_addr[0] = k_pad;
_len[0] = 64;
_addr[1] = mac;
_len[1] = SHA256_MAC_LEN;
return sha256_vector(2, _addr, _len, mac);
}
/**
* hmac_sha256 - HMAC-SHA256 over data buffer (RFC 2104)
* @key: Key for HMAC operations
* @key_len: Length of the key in bytes
* @data: Pointers to the data area
* @data_len: Length of the data area
* @mac: Buffer for the hash (32 bytes)
* Returns: 0 on success, -1 on failure
*/
int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
size_t data_len, u8 *mac)
{
return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
}

30
core/crypto/sha256.h Normal file
View File

@ -0,0 +1,30 @@
/*
* SHA256 hash implementation and interface functions
* Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef SHA256_H
#define SHA256_H
#define SHA256_MAC_LEN 32
int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac);
int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
size_t data_len, u8 *mac);
int sha256_prf(const u8 *key, size_t key_len, const char *label,
const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
int sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
const u8 *data, size_t data_len, u8 *buf,
size_t buf_len_bits);
void tls_prf_sha256(const u8 *secret, size_t secret_len,
const char *label, const u8 *seed, size_t seed_len,
u8 *out, size_t outlen);
int hmac_sha256_kdf(const u8 *secret, size_t secret_len,
const char *label, const u8 *seed, size_t seed_len,
u8 *out, size_t outlen);
#endif /* SHA256_H */

25
core/crypto/sha256_i.h Normal file
View File

@ -0,0 +1,25 @@
/*
* SHA-256 internal definitions
* Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef SHA256_I_H
#define SHA256_I_H
#define SHA256_BLOCK_SIZE 64
struct _sha256_state {
u64 length;
u32 state[8], curlen;
u8 buf[SHA256_BLOCK_SIZE];
};
void _sha256_init(struct _sha256_state *md);
int sha256_process(struct _sha256_state *md, const unsigned char *in,
unsigned long inlen);
int sha256_done(struct _sha256_state *md, unsigned char *out);
#endif /* SHA256_I_H */

View File

@ -0,0 +1,34 @@
/*
* wlantest - IEEE 802.11 protocol monitoring and testing tool
* Copyright (c) 2010-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef WLANCRYPTO_WRAP_H
#define WLANCRYPTO_WRAP_H
int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
u8 *mac);
u8* ccmp_decrypt(_adapter *padapter, const u8 *tk, const struct ieee80211_hdr *hdr,
const u8 *data, size_t data_len, size_t *decrypted_len);
u8* ccmp_encrypt(_adapter *padapter, const u8 *tk, u8 *frame, size_t len, size_t hdrlen, u8 *qos,
u8 *pn, int keyid, size_t *encrypted_len);
u8* ccmp_encrypt_pv1(const u8 *tk, const u8 *a1, const u8 *a2, const u8 *a3,
const u8 *frame, size_t len,
size_t hdrlen, const u8 *pn, int keyid,
size_t *encrypted_len);
u8* ccmp_256_decrypt(_adapter *padapter, const u8 *tk, const struct ieee80211_hdr *hdr,
const u8 *data, size_t data_len, size_t *decrypted_len);
u8* ccmp_256_encrypt(_adapter *padapter, const u8 *tk, u8 *frame, size_t len, size_t hdrlen,
u8 *qos, u8 *pn, int keyid, size_t *encrypted_len);
u8* gcmp_decrypt(_adapter *padapter, const u8 *tk, size_t tk_len, const struct ieee80211_hdr *hdr,
const u8 *data, size_t data_len, size_t *decrypted_len);
u8* gcmp_encrypt(_adapter *padapter, const u8 *tk, size_t tk_len, const u8 *frame, size_t len,
size_t hdrlen, const u8 *qos,
const u8 *pn, int keyid, size_t *encrypted_len);
#endif /* WLANCRYPTO_WRAP_H */

View File

@ -56,6 +56,7 @@ BOOLEAN rtw_file_efuse_IsMasked(PADAPTER pAdapter, u16 Offset, u8 *maskbuf)
return (result > 0) ? 0 : 1;
}
BOOLEAN efuse_IsBT_Masked(PADAPTER pAdapter, u16 Offset)
{
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter);
@ -64,6 +65,7 @@ BOOLEAN efuse_IsBT_Masked(PADAPTER pAdapter, u16 Offset)
return FALSE;
#ifdef CONFIG_BT_EFUSE_MASK
#ifdef CONFIG_RTL8822C
#ifdef CONFIG_USB_HCI
if (IS_HARDWARE_TYPE_8822C(pAdapter))
return (IS_BT_MASKED(8822C, _MUSB, Offset)) ? TRUE : FALSE;
@ -76,6 +78,17 @@ BOOLEAN efuse_IsBT_Masked(PADAPTER pAdapter, u16 Offset)
if (IS_HARDWARE_TYPE_8822C(pAdapter))
return (IS_BT_MASKED(8822C, _MSDIO, Offset)) ? TRUE : FALSE;
#endif
#endif /*#ifdef CONFIG_RTL8822C*/
#ifdef CONFIG_RTL8723F
#ifdef CONFIG_USB_HCI
if (IS_HARDWARE_TYPE_8723F(pAdapter))
return (IS_BT_MASKED(8723F, _MUSB, Offset)) ? TRUE : FALSE;
#endif
#ifdef CONFIG_SDIO_HCI
if (IS_HARDWARE_TYPE_8723F(pAdapter))
return (IS_BT_MASKED(8723F, _MSDIO, Offset)) ? TRUE : FALSE;
#endif
#endif /*#ifdef CONFIG_RTL8723F*/
#endif /* CONFIG_BT_EFUSE_MASK */
return FALSE;
}
@ -85,18 +98,30 @@ void rtw_bt_efuse_mask_array(PADAPTER pAdapter, u8 *pArray)
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter);
#ifdef CONFIG_BT_EFUSE_MASK
#ifdef CONFIG_RTL8822C
#ifdef CONFIG_USB_HCI
if (IS_HARDWARE_TYPE_8822CU(pAdapter))
GET_MASK_ARRAY(8822C, _MUSB, pArray);
GET_BT_MASK_ARRAY(8822C, _MUSB, pArray);
#endif
#ifdef CONFIG_PCI_HCI
if (IS_HARDWARE_TYPE_8822CE(pAdapter))
GET_MASK_ARRAY(8822C, _MPCIE, pArray);
GET_BT_MASK_ARRAY(8822C, _MPCIE, pArray);
#endif
#ifdef CONFIG_SDIO_HCI
if (IS_HARDWARE_TYPE_8822CS(pAdapter))
GET_MASK_ARRAY(8822C, _MSDIO, pArray);
GET_BT_MASK_ARRAY(8822C, _MSDIO, pArray);
#endif
#endif /*#ifdef CONFIG_RTL8822C*/
#ifdef CONFIG_RTL8723F
#ifdef CONFIG_USB_HCI
if (IS_HARDWARE_TYPE_8723FU(pAdapter))
GET_BT_MASK_ARRAY(8723F, _MUSB, pArray);
#endif
#ifdef CONFIG_SDIO_HCI
if (IS_HARDWARE_TYPE_8723FS(pAdapter))
GET_BT_MASK_ARRAY(8723F, _MSDIO, pArray);
#endif
#endif /*#ifdef CONFIG_RTL8723F*/
#endif /* CONFIG_BT_EFUSE_MASK */
}
@ -106,6 +131,7 @@ u16 rtw_get_bt_efuse_mask_arraylen(PADAPTER pAdapter)
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter);
#ifdef CONFIG_BT_EFUSE_MASK
#ifdef CONFIG_RTL8822C
#ifdef CONFIG_USB_HCI
if (IS_HARDWARE_TYPE_8822CU(pAdapter))
return GET_BT_MASK_ARRAY_LEN(8822C, _MUSB);
@ -118,6 +144,17 @@ u16 rtw_get_bt_efuse_mask_arraylen(PADAPTER pAdapter)
if (IS_HARDWARE_TYPE_8822CS(pAdapter))
return GET_BT_MASK_ARRAY_LEN(8822C, _MSDIO);
#endif
#endif /*#ifdef CONFIG_RTL8822C*/
#ifdef CONFIG_RTL8723F
#ifdef CONFIG_USB_HCI
if (IS_HARDWARE_TYPE_8723FU(pAdapter))
return GET_BT_MASK_ARRAY_LEN(8723F, _MUSB);
#endif
#ifdef CONFIG_SDIO_HCI
if (IS_HARDWARE_TYPE_8723FS(pAdapter))
return GET_BT_MASK_ARRAY_LEN(8723F, _MSDIO);
#endif
#endif /*CONFIG_RTL8723F*/
#endif /* CONFIG_BT_EFUSE_MASK */
return 0;
@ -199,6 +236,10 @@ BOOLEAN efuse_IsMasked(PADAPTER pAdapter, u16 Offset)
if (IS_HARDWARE_TYPE_8814B(pAdapter))
return (IS_MASKED(8814B, _MUSB, Offset)) ? TRUE : FALSE;
#endif
#if defined(CONFIG_RTL8723F)
if (IS_HARDWARE_TYPE_8723F(pAdapter))
return (IS_MASKED(8723F, _MUSB, Offset)) ? TRUE : FALSE;
#endif
#endif /*CONFIG_USB_HCI*/
#ifdef CONFIG_PCI_HCI
@ -290,6 +331,10 @@ BOOLEAN efuse_IsMasked(PADAPTER pAdapter, u16 Offset)
if (IS_HARDWARE_TYPE_8822C(pAdapter))
return (IS_MASKED(8822C, _MSDIO, Offset)) ? TRUE : FALSE;
#endif
#if defined(CONFIG_RTL8723F)
if (IS_HARDWARE_TYPE_8723F(pAdapter))
return (IS_MASKED(8723F, _MSDIO, Offset)) ? TRUE : FALSE;
#endif
#endif /*CONFIG_SDIO_HCI*/
return FALSE;
@ -355,6 +400,10 @@ void rtw_efuse_mask_array(PADAPTER pAdapter, u8 *pArray)
if (IS_HARDWARE_TYPE_8814B(pAdapter))
GET_MASK_ARRAY(8814B, _MUSB, pArray);
#endif
#if defined(CONFIG_RTL8723F)
if (IS_HARDWARE_TYPE_8723F(pAdapter))
GET_MASK_ARRAY(8723F, _MUSB, pArray);
#endif
#endif /*CONFIG_USB_HCI*/
#ifdef CONFIG_PCI_HCI
@ -445,6 +494,10 @@ void rtw_efuse_mask_array(PADAPTER pAdapter, u8 *pArray)
if (IS_HARDWARE_TYPE_8822C(pAdapter))
GET_MASK_ARRAY(8822C , _MSDIO, pArray);
#endif
#if defined(CONFIG_RTL8723F)
if (IS_HARDWARE_TYPE_8723F(pAdapter))
GET_MASK_ARRAY(8723F, _MSDIO, pArray);
#endif
#endif /*CONFIG_SDIO_HCI*/
}
@ -509,6 +562,10 @@ u16 rtw_get_efuse_mask_arraylen(PADAPTER pAdapter)
return GET_MASK_ARRAY_LEN(8814B, _MUSB);
}
#endif
#if defined(CONFIG_RTL8723F)
if (IS_HARDWARE_TYPE_8723F(pAdapter))
return GET_MASK_ARRAY_LEN(8723F, _MUSB);
#endif
#endif /*CONFIG_USB_HCI*/
#ifdef CONFIG_PCI_HCI
@ -599,6 +656,10 @@ u16 rtw_get_efuse_mask_arraylen(PADAPTER pAdapter)
if (IS_HARDWARE_TYPE_8822C(pAdapter))
return GET_MASK_ARRAY_LEN(8822C, _MSDIO);
#endif
#if defined(CONFIG_RTL8723F)
if (IS_HARDWARE_TYPE_8723F(pAdapter))
return GET_MASK_ARRAY_LEN(8723F, _MSDIO);
#endif
#endif/*CONFIG_SDIO_HCI*/
return 0;
}
@ -716,6 +777,11 @@ void rtw_efuse_analyze(PADAPTER padapter, u8 Type, u8 Fake)
eFuseWord = rtw_zmalloc(EFUSE_MAX_SECTION_NUM * (EFUSE_MAX_WORD_UNIT * 2));
if (eFuseWord == NULL) {
RTW_INFO("%s:rtw_zmalloc eFuseWord = NULL !!\n", __func__);
return;
}
RTW_INFO("\n");
if (Type == 0) {
if (Fake == 0) {
@ -1032,7 +1098,7 @@ u8 efuse_bt_GetCurrentSize(PADAPTER adapter, u16 *usesize)
u16 efuse_bt_GetMaxSize(PADAPTER adapter)
{
return EFUSE_BT_REAL_CONTENT_LEN;
return EFUSE_BT_REAL_CONTENT_LEN - EFUSE_PROTECT_BYTES_BANK;
}
void EFUSE_GetEfuseDefinition(PADAPTER adapter, u8 efusetype, u8 type, void *out, BOOLEAN test)
@ -1237,6 +1303,7 @@ exit:
return status;
}
u8 rtw_efuse_map_write(PADAPTER adapter, u16 addr, u16 cnts, u8 *data)
{
struct dvobj_priv *d;
@ -1323,22 +1390,23 @@ static void rtw_bt_mask_map_read(PADAPTER padapter, u16 addr, u16 cnts, u8 *data
{
u16 i = 0;
#ifdef CONFIG_BT_EFUSE_MASK
if (padapter->registrypriv.boffefusemask == 0) {
for (i = 0; i < cnts; i++) {
if (padapter->registrypriv.bBTFileMaskEfuse == _TRUE) {
if (rtw_file_efuse_IsMasked(padapter, addr + i, btmaskfileBuffer)) /*use BT file efuse mask.*/
data[i] = 0xff;
else
RTW_DBG("data[%x] = %x\n", i, data[i]);
RTW_INFO("data[%x] = %x\n", i, data[i]);
} else {
if (efuse_IsBT_Masked(padapter, addr + i)) /*use drv internal efuse mask.*/
data[i] = 0xff;
else
RTW_DBG("data[%x] = %x\n", i, data[i]);
RTW_INFO("data[%x] = %x\n", i, data[i]);
}
}
}
#endif /*CONFIG_BT_EFUSE_MASK*/
}
u8 rtw_BT_efuse_map_read(PADAPTER adapter, u16 addr, u16 cnts, u8 *data)
@ -1350,6 +1418,7 @@ u8 rtw_BT_efuse_map_read(PADAPTER adapter, u16 addr, u16 cnts, u8 *data)
return _SUCCESS;
}
static u16
hal_EfuseGetCurrentSize_BT(
PADAPTER padapter,
@ -1435,6 +1504,28 @@ hal_EfuseGetCurrentSize_BT(
return retU2;
}
#ifdef CONFIG_RTL8822C
void rtw_pre_bt_efuse(PADAPTER padapter)
{
char pgdata[4] = {0x72, 0x80, 0x14, 0x90}; /*BT 5M PLL*/
u8 status = 1;
u8 bkmask;
BOOLEAN bt_en;
bkmask = padapter->registrypriv.boffefusemask;
padapter->registrypriv.boffefusemask = 1;
bt_en = rtw_read8(padapter, 0x6A) & BIT2 ? _TRUE : _FALSE;
if (IS_HARDWARE_TYPE_8822C(padapter) && bt_en == _TRUE) {
status = rtw_BT_efuse_map_write(padapter, 0x1f8, 4, pgdata);
RTW_INFO("%s done!!!\n", __FUNCTION__);
}
if (status == _FAIL)
RTW_INFO("%s: fail\n", __FUNCTION__);
padapter->registrypriv.boffefusemask = bkmask;
}
#endif
u8 rtw_BT_efuse_map_write(PADAPTER adapter, u16 addr, u16 cnts, u8 *data)
{
#define RT_ASSERT_RET(expr) \
@ -1477,10 +1568,10 @@ u8 rtw_BT_efuse_map_write(PADAPTER adapter, u16 addr, u16 cnts, u8 *data)
_rtw_memcpy(efuse , map, mapLen);
_rtw_memcpy(efuse + addr, data, cnts);
#ifdef CONFIG_BT_EFUSE_MASK
if (adapter->registrypriv.boffefusemask == 0) {
for (i = 0; i < cnts; i++) {
if (adapter->registrypriv.bFileMaskEfuse == _TRUE) {
if (adapter->registrypriv.bBTFileMaskEfuse == _TRUE) {
if (rtw_file_efuse_IsMasked(adapter, addr + i, btmaskfileBuffer)) /*use file efuse mask. */
efuse[addr + i] = map[addr + i];
} else {
@ -1490,6 +1581,7 @@ u8 rtw_BT_efuse_map_write(PADAPTER adapter, u16 addr, u16 cnts, u8 *data)
RTW_INFO("%s , efuse[%x] = %x, map = %x\n", __func__, addr + i, efuse[ addr + i], map[addr + i]);
}
}
#endif /*CONFIG_BT_EFUSE_MASK*/
/* precheck pg efuse data byte*/
chk_total_byte = 0;
idx = 0;
@ -1533,9 +1625,9 @@ u8 rtw_BT_efuse_map_write(PADAPTER adapter, u16 addr, u16 cnts, u8 *data)
j = (addr + idx) & 0x7;
_rtw_memcpy(newdata, &map[offset << 3], PGPKT_DATA_SIZE);
for (i = j; i < PGPKT_DATA_SIZE && idx < cnts; i++, idx++) {
if (efuse[idx] != map[addr + idx]) {
if (efuse[addr + idx] != map[addr + idx]) {
word_en &= ~BIT(i >> 1);
newdata[i] = efuse[idx];
newdata[i] = efuse[addr + idx];
}
}
@ -1553,7 +1645,10 @@ u8 rtw_BT_efuse_map_write(PADAPTER adapter, u16 addr, u16 cnts, u8 *data)
offset++;
}
exit:
rtw_mfree(map, mapLen);
if (efuse)
rtw_mfree(efuse, mapLen);
if (map)
rtw_mfree(map, mapLen);
return ret;
}
@ -3267,7 +3362,7 @@ int retriveAdaptorInfoFile(char *path, u8 *efuse_data)
}
#endif /* CONFIG_ADAPTOR_INFO_CACHING_FILE */
u8 rtw_efuse_file_read(PADAPTER padapter, u8 *filepatch, u8 *buf, u32 len)
u8 rtw_efuse_file_read(PADAPTER padapter, u8 *filepath, u8 *buf, u32 len)
{
char *ptmpbuf = NULL, *ptr;
u8 val8;
@ -3279,27 +3374,24 @@ u8 rtw_efuse_file_read(PADAPTER padapter, u8 *filepatch, u8 *buf, u32 len)
if (ptmpbuf == NULL)
return _FALSE;
count = rtw_retrieve_from_file(filepatch, ptmpbuf, bufsize);
count = rtw_retrieve_from_file(filepath, ptmpbuf, bufsize);
if (count <= 90) {
rtw_mfree(ptmpbuf, bufsize);
RTW_ERR("%s, filepatch %s, size=%d, FAIL!!\n", __FUNCTION__, filepatch, count);
RTW_ERR("%s, filepatch %s, size=%d, FAIL!!\n", __FUNCTION__, filepath, count);
return _FALSE;
}
i = 0;
j = 0;
ptr = ptmpbuf;
while ((j < len) && (i < count)) {
if (ptmpbuf[i] == '\0')
break;
ptr = strpbrk(&ptmpbuf[i], " \t\n\r");
if (ptr) {
if (ptr == &ptmpbuf[i]) {
i++;
continue;
}
/* Add string terminating null */
*ptr = 0;
} else {
@ -3314,15 +3406,50 @@ u8 rtw_efuse_file_read(PADAPTER padapter, u8 *filepatch, u8 *buf, u32 len)
RTW_DBG("i=%d, j=%d, 0x%02x\n", i, j, buf[j]);
j++;
}
i = ptr - ptmpbuf + 1;
}
rtw_mfree(ptmpbuf, bufsize);
RTW_INFO("%s, filepatch %s, size=%d, done\n", __FUNCTION__, filepatch, count);
RTW_INFO("%s, filepatch %s, size=%d, done\n", __FUNCTION__, filepath, count);
return _TRUE;
}
u8 rtw_efuse_file_store(PADAPTER padapter, u8 *filepath, u8 *buf, u32 len)
{
int err = 0, i = 0, j = 0, mapLen = 0 ;
char *cbuf, *pchr;
cbuf = rtw_zmalloc(len * 3);
pchr = cbuf;
if (filepath && buf) {
if (cbuf == NULL) {
RTW_INFO("%s, malloc cbuf _FAIL\n", __FUNCTION__);
err = _FAIL;
} else {
for (i = 0; i <= len; i += 16) {
for (j = 0; j < 16; j++)
pchr += sprintf(pchr, "%02X ", buf[i + j]);
pchr += sprintf(pchr, "\n");
}
err = rtw_store_to_file(filepath, cbuf, strlen(cbuf));
RTW_INFO("%s, rtw_store_to_file len=%d,err =%d, len(cbuf)=%zd\n", __FUNCTION__, len, err, strlen(cbuf));
if (err == strlen(cbuf)) {
err = _SUCCESS;
RTW_INFO("%s, filepatch %s, len=%d, done\n", __FUNCTION__, filepath, len);
} else {
err = _FAIL;
RTW_INFO("%s, filepatch %s, len=%d,err =%d, _FAIL\n", __FUNCTION__, filepath, len, err);
}
}
}
if (cbuf)
rtw_mfree(cbuf, len * 3);
return err;
}
#ifdef CONFIG_EFUSE_CONFIG_FILE
u32 rtw_read_efuse_from_file(const char *path, u8 *buf, int map_size)
{

View File

@ -143,7 +143,7 @@ exit:
return ret;
}
int rtw_bss_is_same_mbss(WLAN_BSSID_EX *a, WLAN_BSSID_EX *b)
int _rtw_bss_is_same_mbss(WLAN_BSSID_EX *a, WLAN_BSSID_EX *b, u8 **a_mconf_ie_r, u8 **b_mconf_ie_r)
{
int ret = 0;
u8 *a_mconf_ie, *b_mconf_ie;
@ -154,11 +154,16 @@ int rtw_bss_is_same_mbss(WLAN_BSSID_EX *a, WLAN_BSSID_EX *b)
a_mconf_ie = rtw_get_ie(BSS_EX_TLV_IES(a), WLAN_EID_MESH_CONFIG, &a_mconf_ie_len, BSS_EX_TLV_IES_LEN(a));
if (!a_mconf_ie || a_mconf_ie_len != 7)
goto exit;
if (a_mconf_ie_r)
*a_mconf_ie_r = a_mconf_ie;
if (b->InfrastructureMode != Ndis802_11_mesh)
goto exit;
b_mconf_ie = rtw_get_ie(BSS_EX_TLV_IES(b), WLAN_EID_MESH_CONFIG, &b_mconf_ie_len, BSS_EX_TLV_IES_LEN(b));
if (!b_mconf_ie || b_mconf_ie_len != 7)
goto exit;
if (b_mconf_ie_r)
*b_mconf_ie_r = b_mconf_ie;
if (a->mesh_id.SsidLength != b->mesh_id.SsidLength
|| _rtw_memcmp(a->mesh_id.Ssid, b->mesh_id.Ssid, a->mesh_id.SsidLength) == _FALSE)
@ -173,25 +178,28 @@ exit:
return ret;
}
int rtw_bss_is_candidate_mesh_peer(WLAN_BSSID_EX *self, WLAN_BSSID_EX *target, u8 ch, u8 add_peer)
int rtw_bss_is_same_mbss(WLAN_BSSID_EX *a, WLAN_BSSID_EX *b)
{
return _rtw_bss_is_same_mbss(a, b, NULL, NULL);
}
int rtw_bss_is_candidate_mesh_peer(_adapter *adapter, WLAN_BSSID_EX *target, u8 ch, u8 add_peer)
{
int ret = 0;
u8 *mconf_ie;
sint mconf_ie_len;
WLAN_BSSID_EX *self = &adapter->mlmepriv.cur_network.network;
u8 *s_mconf_ie, *t_mconf_ie;
u8 auth_pid;
int i, j;
if (!rtw_bss_is_same_mbss(self, target))
goto exit;
if (ch && self->Configuration.DSConfig != target->Configuration.DSConfig)
goto exit;
if (!_rtw_bss_is_same_mbss(self, target, &s_mconf_ie, &t_mconf_ie))
goto exit;
if (add_peer) {
/* Accept additional mesh peerings */
mconf_ie = rtw_get_ie(BSS_EX_TLV_IES(target), WLAN_EID_MESH_CONFIG, &mconf_ie_len, BSS_EX_TLV_IES_LEN(target));
if (!mconf_ie || mconf_ie_len != 7)
goto exit;
if (GET_MESH_CONF_ELE_ACCEPT_PEERINGS(mconf_ie + 2) == 0)
if (GET_MESH_CONF_ELE_ACCEPT_PEERINGS(t_mconf_ie + 2) == 0)
goto exit;
}
@ -223,10 +231,38 @@ int rtw_bss_is_candidate_mesh_peer(WLAN_BSSID_EX *self, WLAN_BSSID_EX *target, u
}
}
/* BSSBasicMCSSet */
/* 802.1X connected to AS ? */
auth_pid = GET_MESH_CONF_ELE_AUTH_PROTO_ID(s_mconf_ie + 2);
if (auth_pid && auth_pid <= 2) {
struct security_priv *sec = &adapter->securitypriv;
u8 *rsn_ie;
int rsn_ie_len;
int group_cipher = 0, pairwise_cipher = 0, gmcs = 0;
u8 mfp_opt = MFP_NO;
/* 802.1X connected to AS ? */
/* RSN */
rsn_ie = rtw_get_wpa2_ie(BSS_EX_TLV_IES(target), &rsn_ie_len, BSS_EX_TLV_IES_LEN(target));
if (!rsn_ie || rsn_ie_len == 0)
goto exit;
if (rtw_parse_wpa2_ie(rsn_ie, rsn_ie_len + 2, &group_cipher, &pairwise_cipher, &gmcs, NULL, &mfp_opt, NULL) != _SUCCESS)
goto exit;
if ((sec->mfp_opt == MFP_REQUIRED && mfp_opt < MFP_OPTIONAL)
|| (mfp_opt == MFP_REQUIRED && sec->mfp_opt < MFP_OPTIONAL))
goto exit;
if (!(sec->wpa2_group_cipher & group_cipher))
goto exit;
if (!(sec->wpa2_pairwise_cipher & pairwise_cipher))
goto exit;
#ifdef CONFIG_IEEE80211W
if ((sec->mfp_opt >= MFP_OPTIONAL && mfp_opt >= MFP_OPTIONAL)
&& security_type_bip_to_gmcs(sec->dot11wCipher) != gmcs)
goto exit;
#endif
}
ret = 1;
@ -339,7 +375,7 @@ static bool rtw_mesh_acnode_candidate_exist(_adapter *adapter)
#if CONFIG_RTW_MACADDR_ACL
&& rtw_access_ctrl(adapter, scanned->network.MacAddress) == _TRUE
#endif
&& rtw_bss_is_candidate_mesh_peer(&mlme->cur_network.network, &scanned->network, 1, 1)
&& rtw_bss_is_candidate_mesh_peer(adapter, &scanned->network, 1, 1)
#if CONFIG_RTW_MESH_PEER_BLACKLIST
&& !rtw_mesh_peer_blacklist_search(adapter, scanned->network.MacAddress)
#endif
@ -679,7 +715,7 @@ void rtw_chk_candidate_peer_notify(_adapter *adapter, struct wlan_network *scann
if (rtw_get_passing_time_ms(scanned->last_scanned) >= mcfg->peer_sel_policy.scanr_exp_ms
|| (mcfg->rssi_threshold && mcfg->rssi_threshold > scanned->network.Rssi)
|| !rtw_bss_is_candidate_mesh_peer(&mlme->cur_network.network, &scanned->network, 1, 1)
|| !rtw_bss_is_candidate_mesh_peer(adapter, &scanned->network, 1, 1)
#if CONFIG_RTW_MACADDR_ACL
|| rtw_access_ctrl(adapter, scanned->network.MacAddress) == _FALSE
#endif
@ -760,7 +796,7 @@ void rtw_mesh_peer_status_chk(_adapter *adapter)
flush = 0;
/* remove unsuitable peer */
if (!rtw_bss_is_candidate_mesh_peer(&mlme->cur_network.network, &plink->scanned->network, 1, 0)
if (!rtw_bss_is_candidate_mesh_peer(adapter, &plink->scanned->network, 1, 0)
#if CONFIG_RTW_MACADDR_ACL
|| rtw_access_ctrl(adapter, plink->addr) == _FALSE
#endif
@ -809,6 +845,10 @@ flush_add:
if (flush) {
rtw_list_delete(&sta->asoc_list);
stapriv->asoc_list_cnt--;
#ifdef CONFIG_RTW_TOKEN_BASED_XMIT
if (sta->tbtx_enable)
stapriv->tbtx_asoc_list_cnt--;
#endif
STA_SET_MESH_PLINK(sta, NULL);
stainfo_offset = rtw_stainfo_offset(stapriv, sta);
@ -828,7 +868,7 @@ flush_add:
continue;
/* remove unsuitable peer */
if (!rtw_bss_is_candidate_mesh_peer(&mlme->cur_network.network, &plink->scanned->network, 1, 1)
if (!rtw_bss_is_candidate_mesh_peer(adapter, &plink->scanned->network, 1, 1)
#if CONFIG_RTW_MACADDR_ACL
|| rtw_access_ctrl(adapter, plink->addr) == _FALSE
#endif
@ -901,7 +941,7 @@ static u8 rtw_mesh_offch_cto_mgate_required(_adapter *adapter)
#if CONFIG_RTW_MACADDR_ACL
&& rtw_access_ctrl(adapter, scanned->network.MacAddress) == _TRUE
#endif
&& rtw_bss_is_candidate_mesh_peer(&mlme->cur_network.network, &scanned->network, 1, 1)
&& rtw_bss_is_candidate_mesh_peer(adapter, &scanned->network, 1, 1)
&& rtw_bss_is_cto_mgate(&scanned->network)
#if CONFIG_RTW_MESH_PEER_BLACKLIST
&& !rtw_mesh_peer_blacklist_search(adapter, scanned->network.MacAddress)
@ -988,7 +1028,7 @@ u8 rtw_mesh_select_operating_ch(_adapter *adapter)
#if CONFIG_RTW_MACADDR_ACL
&& rtw_access_ctrl(adapter, scanned->network.MacAddress) == _TRUE
#endif
&& rtw_bss_is_candidate_mesh_peer(&mlme->cur_network.network, &scanned->network, 0, 0)
&& rtw_bss_is_candidate_mesh_peer(adapter, &scanned->network, 0, 0)
#if CONFIG_RTW_MESH_PEER_BLACKLIST
&& !rtw_mesh_peer_blacklist_search(adapter, scanned->network.MacAddress)
#endif
@ -999,7 +1039,7 @@ u8 rtw_mesh_select_operating_ch(_adapter *adapter)
int ch_set_idx = rtw_chset_search_ch(rfctl->channel_set, scanned->network.Configuration.DSConfig);
if (ch_set_idx >= 0
&& rfctl->channel_set[ch_set_idx].ScanType != SCAN_PASSIVE
&& !(rfctl->channel_set[ch_set_idx].flags & RTW_CHF_NO_IR)
&& !CH_IS_NON_OCP(&rfctl->channel_set[ch_set_idx])
) {
u8 nop, accept;
@ -1074,6 +1114,11 @@ void dump_mesh_networks(void *sel, _adapter *adapter)
#endif
u8 *mesh_conf_ie;
sint mesh_conf_ie_len;
u8 auth_pid;
u8 *rsn_ie;
int rsn_ie_len;
int gcs, pcs, gmcs;
u8 mfp_opt;
struct wlan_network **mesh_networks;
u8 mesh_network_cnt = 0;
int i;
@ -1103,13 +1148,54 @@ void dump_mesh_networks(void *sel, _adapter *adapter)
exit_critical_bh(&queue->lock);
RTW_PRINT_SEL(sel, " %-17s %-3s %-4s %-5s %-32s %-3s %-3s %-3s"
RTW_PRINT_SEL(sel, " %-17s %-3s %-4s %-5s %-32s %-10s"
" %-3s %-3s %-4s"
" %-3s %-3s %-3s"
NSTATE_TITLE_FMT_ACN
"\n"
, "bssid", "ch", "rssi", "age", "mesh_id", "nop", "fwd", "cto"
, "bssid", "ch", "rssi", "age", "mesh_id", "P M C S A "
, "pcs", "gcs", "gmcs"
, "nop", "fwd", "cto"
NSTATE_TITLE_ARG_ACN
);
if (MLME_IS_MESH(adapter) && MLME_IS_ASOC(adapter)) {
network = &mlme->cur_network;
mesh_conf_ie = rtw_get_ie(BSS_EX_TLV_IES(&network->network), WLAN_EID_MESH_CONFIG
, &mesh_conf_ie_len, BSS_EX_TLV_IES_LEN(&network->network));
if (mesh_conf_ie && mesh_conf_ie_len == 7) {
gcs = pcs = gmcs = 0;
mfp_opt = MFP_NO;
auth_pid = GET_MESH_CONF_ELE_AUTH_PROTO_ID(mesh_conf_ie + 2);
if (auth_pid && auth_pid <= 2) {
rsn_ie = rtw_get_wpa2_ie(BSS_EX_TLV_IES(&network->network)
, &rsn_ie_len, BSS_EX_TLV_IES_LEN(&network->network));
if (rsn_ie && rsn_ie_len)
rtw_parse_wpa2_ie(rsn_ie, rsn_ie_len + 2, &gcs, &pcs, &gmcs, NULL, &mfp_opt, NULL);
}
RTW_PRINT_SEL(sel, "* "MAC_FMT" %3d %-32s %2x%2x%2x%2x%2x"
" %03x %03x %c%03x"
" %c%2u %3u %c%c "
"\n"
, MAC_ARG(network->network.MacAddress)
, network->network.Configuration.DSConfig
, network->network.mesh_id.Ssid
, GET_MESH_CONF_ELE_PATH_SEL_PROTO_ID(mesh_conf_ie + 2)
, GET_MESH_CONF_ELE_PATH_SEL_METRIC_ID(mesh_conf_ie + 2)
, GET_MESH_CONF_ELE_CONGEST_CTRL_MODE_ID(mesh_conf_ie + 2)
, GET_MESH_CONF_ELE_SYNC_METHOD_ID(mesh_conf_ie + 2)
, auth_pid
, pcs, gcs, mfp_opt == MFP_REQUIRED ? 'R' : (mfp_opt == MFP_OPTIONAL ? 'C' : ' ')
, mfp_opt >= MFP_OPTIONAL ? gmcs : 0
, GET_MESH_CONF_ELE_ACCEPT_PEERINGS(mesh_conf_ie + 2) ? '+' : ' '
, GET_MESH_CONF_ELE_NUM_OF_PEERINGS(mesh_conf_ie + 2)
, GET_MESH_CONF_ELE_FORWARDING(mesh_conf_ie + 2)
, GET_MESH_CONF_ELE_CTO_MGATE(mesh_conf_ie + 2) ? 'G' : ' '
, GET_MESH_CONF_ELE_CTO_AS(mesh_conf_ie + 2) ? 'A' : ' '
);
}
}
for (i = 0; i < mesh_network_cnt; i++) {
network = mesh_networks[i];
@ -1121,6 +1207,14 @@ void dump_mesh_networks(void *sel, _adapter *adapter)
if (!mesh_conf_ie || mesh_conf_ie_len != 7)
continue;
gcs = pcs = gmcs = 0;
mfp_opt = MFP_NO;
auth_pid = GET_MESH_CONF_ELE_AUTH_PROTO_ID(mesh_conf_ie + 2);
if (auth_pid && auth_pid <= 2) {
rsn_ie = rtw_get_wpa2_ie(BSS_EX_TLV_IES(&network->network), &rsn_ie_len, BSS_EX_TLV_IES_LEN(&network->network));
if (rsn_ie && rsn_ie_len)
rtw_parse_wpa2_ie(rsn_ie, rsn_ie_len + 2, &gcs, &pcs, &gmcs, NULL, &mfp_opt, NULL);
}
age_ms = rtw_get_passing_time_ms(network->last_scanned);
#if CONFIG_RTW_MESH_ACNODE_PREVENT
if (network->acnode_stime == 0)
@ -1142,13 +1236,15 @@ void dump_mesh_networks(void *sel, _adapter *adapter)
blocked = 1;
else if (plink)
;
else if (rtw_bss_is_candidate_mesh_peer(&mlme->cur_network.network, &network->network, 0, 1))
else if (rtw_bss_is_candidate_mesh_peer(adapter, &network->network, 0, 1))
candidate = 1;
else if (rtw_bss_is_same_mbss(&mlme->cur_network.network, &network->network))
same_mbss = 1;
}
RTW_PRINT_SEL(sel, "%c "MAC_FMT" %3d %4ld %5d %-32s %c%2u %3u %c%c "
RTW_PRINT_SEL(sel, "%c "MAC_FMT" %3d %4ld %5d %-32s %2x%2x%2x%2x%2x"
" %03x %03x %c%03x"
" %c%2u %3u %c%c "
NSTATE_VALUE_FMT_ACN
"\n"
, established ? 'E' : (blocked ? 'B' : (plink ? 'N' : (candidate ? 'C' : (same_mbss ? 'S' : ' '))))
@ -1157,6 +1253,13 @@ void dump_mesh_networks(void *sel, _adapter *adapter)
, network->network.Rssi
, age_ms < 99999 ? age_ms : 99999
, network->network.mesh_id.Ssid
, GET_MESH_CONF_ELE_PATH_SEL_PROTO_ID(mesh_conf_ie + 2)
, GET_MESH_CONF_ELE_PATH_SEL_METRIC_ID(mesh_conf_ie + 2)
, GET_MESH_CONF_ELE_CONGEST_CTRL_MODE_ID(mesh_conf_ie + 2)
, GET_MESH_CONF_ELE_SYNC_METHOD_ID(mesh_conf_ie + 2)
, auth_pid
, pcs, gcs, mfp_opt == MFP_REQUIRED ? 'R' : (mfp_opt == MFP_OPTIONAL ? 'C' : ' ')
, mfp_opt >= MFP_OPTIONAL ? gmcs : 0
, GET_MESH_CONF_ELE_ACCEPT_PEERINGS(mesh_conf_ie + 2) ? '+' : ' '
, GET_MESH_CONF_ELE_NUM_OF_PEERINGS(mesh_conf_ie + 2)
, GET_MESH_CONF_ELE_FORWARDING(mesh_conf_ie + 2)
@ -1205,7 +1308,7 @@ static int rtw_mpm_ampe_dec(_adapter *adapter, struct mesh_plink_ent *plink
_rtw_memcpy(iv_crypt, mic_ie + 2, iv_crypt_len);
verify_ret = aes_siv_decrypt(plink->aek, iv_crypt, iv_crypt_len
verify_ret = rtw_aes_siv_decrypt(plink->aek, 32, iv_crypt, iv_crypt_len
, 3, aad, aad_len, ampe_buf);
rtw_mfree(iv_crypt, iv_crypt_len);
@ -1216,7 +1319,7 @@ static int rtw_mpm_ampe_dec(_adapter *adapter, struct mesh_plink_ent *plink
} else if (*ampe_buf != WLAN_EID_AMPE) {
RTW_WARN("plaintext is not AMPE IE\n");
goto exit;
} else if (AES_BLOCK_SIZE + 2 + *(ampe_buf + 1) > iv_crypt_len) {
} else if ( 16 /* AES_BLOCK_SIZE*/ + 2 + *(ampe_buf + 1) > iv_crypt_len) {
RTW_WARN("plaintext AMPE IE length is not valid\n");
goto exit;
}
@ -1251,7 +1354,7 @@ static int rtw_mpm_ampe_enc(_adapter *adapter, struct mesh_plink_ent *plink
_rtw_memcpy(ampe_ie, ampe_buf, ampe_ie_len);
protect_ret = aes_siv_encrypt(plink->aek, ampe_ie, ampe_ie_len
protect_ret = rtw_aes_siv_encrypt(plink->aek, 32, ampe_ie, ampe_ie_len
, 3, aad, aad_len, mic_ie + 2);
rtw_mfree(ampe_ie, ampe_ie_len);
@ -1296,7 +1399,7 @@ static int rtw_mpm_tx_ies_sync_bss(_adapter *adapter, struct mesh_plink_ent *pli
/* decode */
if (mic_ie) {
ampe_buf_len = flen - (mic_ie + 2 + AES_BLOCK_SIZE - fhead);
ampe_buf_len = flen - (mic_ie + 2 + 16 /* AES_BLOCK_SIZE */ - fhead);
ampe_buf = rtw_malloc(ampe_buf_len);
if (!ampe_buf)
goto exit;
@ -1340,7 +1443,7 @@ static int rtw_mpm_tx_ies_sync_bss(_adapter *adapter, struct mesh_plink_ent *pli
}
new_len += mpm_ielen + 2;
if (mic_ie)
new_len += AES_BLOCK_SIZE + 2 + ampe_buf_len;
new_len += 16 /* AES_BLOCK_SIZE*/ + 2 + ampe_buf_len;
/* alloc new frame */
new_buf = rtw_malloc(new_len);
@ -1385,7 +1488,7 @@ static int rtw_mpm_tx_ies_sync_bss(_adapter *adapter, struct mesh_plink_ent *pli
if (mic_ie) {
new_mic_ie = fpos;
*fpos++ = WLAN_EID_MIC;
*fpos++ = AES_BLOCK_SIZE;
*fpos++ = 16 /* AES_BLOCK_SIZE */;
}
#ifdef CONFIG_RTW_MESH_AEK
@ -1585,7 +1688,7 @@ static int rtw_mpm_check_frames(_adapter *adapter, u8 action, const u8 **buf, si
mic_ie = rtw_get_ie(fhead + sizeof(struct rtw_ieee80211_hdr_3addr) + tlv_ies_offset
, WLAN_EID_MIC, &mic_ielen
, flen - sizeof(struct rtw_ieee80211_hdr_3addr) - tlv_ies_offset);
if (!mic_ie || mic_ielen != AES_BLOCK_SIZE)
if (!mic_ie || mic_ielen != 16 /* AES_BLOCK_SIZE */)
goto exit;
}
@ -1661,6 +1764,10 @@ bypass_sync_bss:
if (!rtw_is_list_empty(&sac->asoc_list)) {
rtw_list_delete(&sac->asoc_list);
stapriv->asoc_list_cnt--;
#ifdef CONFIG_RTW_TOKEN_BASED_XMIT
if (sac->tbtx_enable)
stapriv->tbtx_asoc_list_cnt--;
#endif
STA_SET_MESH_PLINK(sac, NULL);
}
_exit_critical_bh(&stapriv->asoc_list_lock, &irqL);
@ -2357,7 +2464,7 @@ void dump_mesh_plink_ctl(void *sel, _adapter *adapter)
}
/* this function is called with plink_ctl being locked */
int rtw_mesh_peer_establish(_adapter *adapter, struct mesh_plink_ent *plink, struct sta_info *sta)
static int rtw_mesh_peer_establish(_adapter *adapter, struct mesh_plink_ent *plink, struct sta_info *sta)
{
#ifndef DBG_RTW_MESH_PEER_ESTABLISH
#define DBG_RTW_MESH_PEER_ESTABLISH 0
@ -2372,7 +2479,11 @@ int rtw_mesh_peer_establish(_adapter *adapter, struct mesh_plink_ent *plink, str
struct rtw_ieee802_11_elems elems;
_irqL irqL;
int i;
u16 status = 0;
int ret = _FAIL;
#ifdef CONFIG_RTW_TOKEN_BASED_XMIT
u8 sta_tbtx_enable = _FALSE;
#endif
if (!plink->rx_conf_ies || !plink->rx_conf_ies_len) {
RTW_INFO(FUNC_ADPT_FMT" no rx confirm from sta "MAC_FMT"\n"
@ -2424,11 +2535,15 @@ int rtw_mesh_peer_establish(_adapter *adapter, struct mesh_plink_ent *plink, str
rtw_ap_parse_sta_capability(adapter, sta, plink->rx_conf_ies);
if (rtw_ap_parse_sta_supported_rates(adapter, sta, tlv_ies, tlv_ieslen) != _STATS_SUCCESSFUL_)
status = rtw_ap_parse_sta_supported_rates(adapter, sta, tlv_ies, tlv_ieslen);
if (status != _STATS_SUCCESSFUL_)
goto exit;
if (rtw_ap_parse_sta_security_ie(adapter, sta, &elems) != _STATS_SUCCESSFUL_)
status = rtw_ap_parse_sta_security_ie(adapter, sta, &elems);
if (status != _STATS_SUCCESSFUL_) {
RTW_INFO(FUNC_ADPT_FMT" security check fail, status=%u\n", FUNC_ADPT_ARG(adapter), status);
goto exit;
}
rtw_ap_parse_sta_wmm_ie(adapter, sta, tlv_ies, tlv_ieslen);
#ifdef CONFIG_RTS_FULL_BW
@ -2436,6 +2551,14 @@ int rtw_mesh_peer_establish(_adapter *adapter, struct mesh_plink_ent *plink, str
rtw_parse_sta_vendor_ie_8812(adapter, sta, tlv_ies, tlv_ieslen);
#endif/*CONFIG_RTS_FULL_BW*/
#ifdef CONFIG_RTW_TOKEN_BASED_XMIT
if (elems.tbtx_cap && elems.tbtx_cap_len != 0) {
if(rtw_is_tbtx_capabilty(elems.tbtx_cap, elems.tbtx_cap_len)) {
sta_tbtx_enable = _TRUE;
}
}
#endif
rtw_ap_parse_sta_ht_ie(adapter, sta, &elems);
rtw_ap_parse_sta_vht_ie(adapter, sta, &elems);
@ -2467,6 +2590,12 @@ int rtw_mesh_peer_establish(_adapter *adapter, struct mesh_plink_ent *plink, str
/* sta->expire_to = mcfg->plink_timeout / 2; */
rtw_list_insert_tail(&sta->asoc_list, &stapriv->asoc_list);
stapriv->asoc_list_cnt++;
#ifdef CONFIG_RTW_TOKEN_BASED_XMIT
if (sta_tbtx_enable) {
sta->tbtx_enable = _TRUE;
stapriv->tbtx_asoc_list_cnt++;
}
#endif
}
_exit_critical_bh(&stapriv->asoc_list_lock, &irqL);
@ -2480,6 +2609,167 @@ exit:
return ret;
}
int rtw_mesh_set_plink_state(_adapter *adapter, const u8 *mac, u8 plink_state)
{
struct rtw_mesh_info *minfo = &adapter->mesh_info;
struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
struct mesh_plink_ent *plink = NULL;
_irqL irqL2;
struct sta_priv *stapriv = &adapter->stapriv;
struct sta_info *sta = NULL;
_irqL irqL;
struct sta_info *del_sta = NULL;
int ret = _SUCCESS;
_enter_critical_bh(&(plink_ctl->lock), &irqL2);
plink = _rtw_mesh_plink_get(adapter, mac);
if (!plink) {
ret = _FAIL;
goto release_plink_ctl;
}
plink->plink_state = plink_state;
#if CONFIG_RTW_MESH_ACNODE_PREVENT
if (plink_state == RTW_MESH_PLINK_OPN_SNT) {
if (rtw_mesh_scanned_is_acnode_confirmed(adapter, plink->scanned)
&& rtw_mesh_acnode_prevent_allow_sacrifice(adapter)
) {
struct sta_info *sac = rtw_mesh_acnode_prevent_pick_sacrifice(adapter);
if (sac) {
del_sta = sac;
_enter_critical_bh(&stapriv->asoc_list_lock, &irqL);
if (!rtw_is_list_empty(&del_sta->asoc_list)) {
rtw_list_delete(&del_sta->asoc_list);
stapriv->asoc_list_cnt--;
#ifdef CONFIG_RTW_TOKEN_BASED_XMIT
if (del_sta->tbtx_enable)
stapriv->tbtx_asoc_list_cnt--;
#endif
STA_SET_MESH_PLINK(del_sta, NULL);
}
_exit_critical_bh(&stapriv->asoc_list_lock, &irqL);
RTW_INFO(FUNC_ADPT_FMT" sacrifice "MAC_FMT" for acnode\n"
, FUNC_ADPT_ARG(adapter), MAC_ARG(del_sta->cmn.mac_addr));
}
}
} else
#endif
if (plink_state == RTW_MESH_PLINK_OPN_RCVD
|| plink_state == RTW_MESH_PLINK_CNF_RCVD
|| plink_state == RTW_MESH_PLINK_ESTAB
) {
sta = rtw_get_stainfo(stapriv, mac);
if (!sta) {
sta = rtw_alloc_stainfo(stapriv, mac);
if (!sta)
goto release_plink_ctl;
}
if (plink_state == RTW_MESH_PLINK_ESTAB) {
if (rtw_mesh_peer_establish(adapter, plink, sta) != _SUCCESS) {
del_sta = sta;
ret = _FAIL;
goto release_plink_ctl;
}
}
}
else if (plink_state == RTW_MESH_PLINK_HOLDING) {
del_sta = rtw_get_stainfo(stapriv, mac);
if (!del_sta)
goto release_plink_ctl;
_enter_critical_bh(&stapriv->asoc_list_lock, &irqL);
if (!rtw_is_list_empty(&del_sta->asoc_list)) {
rtw_list_delete(&del_sta->asoc_list);
stapriv->asoc_list_cnt--;
#ifdef CONFIG_RTW_TOKEN_BASED_XMIT
if (del_sta->tbtx_enable)
stapriv->tbtx_asoc_list_cnt--;
#endif
STA_SET_MESH_PLINK(del_sta, NULL);
}
_exit_critical_bh(&stapriv->asoc_list_lock, &irqL);
}
release_plink_ctl:
_exit_critical_bh(&(plink_ctl->lock), &irqL2);
if (del_sta) {
u8 sta_addr[ETH_ALEN];
u8 updated = _FALSE;
_rtw_memcpy(sta_addr, del_sta->cmn.mac_addr, ETH_ALEN);
updated = ap_free_sta(adapter, del_sta, 0, 0, 1);
rtw_mesh_expire_peer(stapriv->padapter, sta_addr);
associated_clients_update(adapter, updated, STA_INFO_UPDATE_ALL);
}
return ret;
}
struct mesh_set_plink_cmd_parm {
const u8 *mac;
u8 plink_state;
};
u8 rtw_mesh_set_plink_state_cmd_hdl(_adapter *adapter, u8 *parmbuf)
{
struct mesh_set_plink_cmd_parm *parm = (struct mesh_set_plink_cmd_parm *)parmbuf;
if (rtw_mesh_set_plink_state(adapter, parm->mac, parm->plink_state) == _SUCCESS)
return H2C_SUCCESS;
return H2C_CMD_FAIL;
}
u8 rtw_mesh_set_plink_state_cmd(_adapter *adapter, const u8 *mac, u8 plink_state)
{
struct cmd_obj *cmdobj;
struct mesh_set_plink_cmd_parm *parm;
struct cmd_priv *cmdpriv = &adapter->cmdpriv;
struct submit_ctx sctx;
u8 res = _SUCCESS;
/* prepare cmd parameter */
parm = rtw_zmalloc(sizeof(*parm));
if (parm == NULL) {
res = _FAIL;
goto exit;
}
parm->mac = mac;
parm->plink_state = plink_state;
/* need enqueue, prepare cmd_obj and enqueue */
cmdobj = rtw_zmalloc(sizeof(*cmdobj));
if (cmdobj == NULL) {
res = _FAIL;
rtw_mfree(parm, sizeof(*parm));
goto exit;
}
init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, CMD_SET_MESH_PLINK_STATE);
cmdobj->sctx = &sctx;
rtw_sctx_init(&sctx, 2000);
res = rtw_enqueue_cmd(cmdpriv, cmdobj);
if (res == _SUCCESS) {
rtw_sctx_wait(&sctx, __func__);
_enter_critical_mutex(&cmdpriv->sctx_mutex, NULL);
if (sctx.status == RTW_SCTX_SUBMITTED)
cmdobj->sctx = NULL;
_exit_critical_mutex(&cmdpriv->sctx_mutex, NULL);
if (sctx.status != RTW_SCTX_DONE_SUCCESS)
res = _FAIL;
}
exit:
return res;
}
void rtw_mesh_expire_peer_notify(_adapter *adapter, const u8 *peer_addr)
{
u8 null_ssid[2] = {0, 0};
@ -2511,7 +2801,7 @@ static u8 *rtw_mesh_construct_peer_mesh_close(_adapter *adapter, struct mesh_pli
+ 2 /* category, action */
+ 2 + minfo->mesh_id_len /* mesh id */
+ 2 + 8 + (minfo->mesh_auth_id ? 16 : 0) /* mpm */
+ (minfo->mesh_auth_id ? 2 + AES_BLOCK_SIZE : 0) /* mic */
+ (minfo->mesh_auth_id ? 2 + 16 /* AES_BLOCK_SIZE */ : 0) /* mic */
+ (minfo->mesh_auth_id ? 70 : 0) /* ampe */
;
@ -2545,7 +2835,7 @@ static u8 *rtw_mesh_construct_peer_mesh_close(_adapter *adapter, struct mesh_pli
int enc_ret;
*pos = WLAN_EID_MIC;
*(pos + 1) = AES_BLOCK_SIZE;
*(pos + 1) = 16 /* AES_BLOCK_SIZE */;
ampe_buf[0] = WLAN_EID_AMPE;
ampe_buf[1] = 68;
@ -3017,6 +3307,7 @@ void rtw_mesh_cfg_init_peer_sel_policy(struct rtw_mesh_cfg *mcfg)
void rtw_mesh_cfg_init(_adapter *adapter)
{
struct registry_priv *regsty = adapter_to_regsty(adapter);
struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
mcfg->max_peer_links = RTW_MESH_MAX_PEER_LINKS;
@ -3047,8 +3338,8 @@ void rtw_mesh_cfg_init(_adapter *adapter)
#endif
#if CONFIG_RTW_MESH_DATA_BMC_TO_UC
mcfg->b2u_flags_msrc = 0;
mcfg->b2u_flags_mfwd = RTW_MESH_B2U_GA_UCAST;
mcfg->b2u_flags_msrc = regsty->msrc_b2u_flags;
mcfg->b2u_flags_mfwd = regsty->mfwd_b2u_flags;
#endif
}
@ -3256,7 +3547,7 @@ endlookup:
static bool rtw_mesh_data_bmc_to_uc(_adapter *adapter
, const u8 *da, const u8 *sa, const u8 *mda, const u8 *msa
, u8 ae_need, const u8 *ori_ta, u8 mfwd_ttl
, _list *b2u_list, u8 *b2u_num, u32 *b2u_mseq)
, u16 os_qid, _list *b2u_list, u8 *b2u_num, u32 *b2u_mseq)
{
struct sta_priv *stapriv = &adapter->stapriv;
struct xmit_priv *xmitpriv = &adapter->xmitpriv;
@ -3292,14 +3583,14 @@ static bool rtw_mesh_data_bmc_to_uc(_adapter *adapter
struct pkt_attrib *attrib;
sta = rtw_get_stainfo_by_offset(stapriv, b2u_sta_id[i]);
if (!(sta->state & _FW_LINKED)
if (!(sta->state & WIFI_ASOC_STATE)
|| _rtw_memcmp(sta->cmn.mac_addr, msa, ETH_ALEN) == _TRUE
|| (ori_ta && _rtw_memcmp(sta->cmn.mac_addr, ori_ta, ETH_ALEN) == _TRUE)
|| is_broadcast_mac_addr(sta->cmn.mac_addr)
|| is_zero_mac_addr(sta->cmn.mac_addr))
continue;
b2uframe = rtw_alloc_xmitframe(xmitpriv);
b2uframe = rtw_alloc_xmitframe(xmitpriv, os_qid);
if (!b2uframe) {
bmc_need = _TRUE;
break;
@ -3339,7 +3630,7 @@ void dump_mesh_b2u_flags(void *sel, _adapter *adapter)
}
#endif /* CONFIG_RTW_MESH_DATA_BMC_TO_UC */
int rtw_mesh_addr_resolve(_adapter *adapter, struct xmit_frame *xframe, _pkt *pkt, _list *b2u_list)
int rtw_mesh_addr_resolve(_adapter *adapter, u16 os_qid, struct xmit_frame *xframe, _pkt *pkt, _list *b2u_list)
{
struct pkt_file pktfile;
struct ethhdr etherhdr;
@ -3401,7 +3692,7 @@ int rtw_mesh_addr_resolve(_adapter *adapter, struct xmit_frame *xframe, _pkt *pk
bmc_need = rtw_mesh_data_bmc_to_uc(adapter
, etherhdr.h_dest, etherhdr.h_source
, etherhdr.h_dest, adapter_mac_addr(adapter), ae_need, NULL, 0
, b2u_list, &b2u_num, &b2u_mseq);
, os_qid, b2u_list, &b2u_num, &b2u_mseq);
if (bmc_need == _FALSE) {
res = RTW_BMC_NO_NEED;
goto exit;
@ -3578,7 +3869,7 @@ int rtw_mesh_rx_data_validate_hdr(_adapter *adapter, union recv_frame *rframe, s
goto exit;
switch (rattrib->to_fr_ds) {
case 1:
case 2:
if (!IS_MCAST(GetAddr1Ptr(whdr)))
goto exit;
*sta = rtw_get_stainfo(stapriv, get_addr2_ptr(whdr));
@ -3666,7 +3957,7 @@ int rtw_mesh_rx_data_validate_mctrl(_adapter *adapter, union recv_frame *rframe
ae = mctrl->flags & MESH_FLAGS_AE;
mlen = ae_to_mesh_ctrl_len[ae];
switch (rattrib->to_fr_ds) {
case 1:
case 2:
*da = mda;
if (ae == MESH_FLAGS_AE_A4)
*sa = mctrl->eaddr1;
@ -3776,6 +4067,7 @@ int rtw_mesh_rx_msdu_act_check(union recv_frame *rframe
, const u8 *mda, const u8 *msa
, const u8 *da, const u8 *sa
, struct rtw_ieee80211s_hdr *mctrl
, u8 *msdu, enum rtw_rx_llc_hdl llc_hdl
, struct xmit_frame **fwd_frame, _list *b2u_list)
{
_adapter *adapter = rframe->u.hdr.adapter;
@ -3785,6 +4077,7 @@ int rtw_mesh_rx_msdu_act_check(union recv_frame *rframe
struct rtw_mesh_path *mppath;
u8 is_mda_bmc = IS_MCAST(mda);
u8 is_mda_self = !is_mda_bmc && _rtw_memcmp(mda, adapter_mac_addr(adapter), ETH_ALEN);
u16 os_qid;
struct xmit_frame *xframe;
struct pkt_attrib *xattrib;
u8 fwd_ra[ETH_ALEN] = {0};
@ -4012,6 +4305,8 @@ fwd_chk:
goto exit;
}
os_qid = rtw_os_recv_select_queue(msdu, llc_hdl);
#if CONFIG_RTW_MESH_DATA_BMC_TO_UC
_rtw_init_listhead(b2u_list);
#endif
@ -4025,13 +4320,13 @@ fwd_chk:
) {
bmc_need = rtw_mesh_data_bmc_to_uc(adapter
, da, sa, mda, msa, ae_need, rframe->u.hdr.psta->cmn.mac_addr, mctrl->ttl - 1
, b2u_list, &b2u_num, &fwd_mseq);
, os_qid, b2u_list, &b2u_num, &fwd_mseq);
}
if (bmc_need == _TRUE)
#endif
{
xframe = rtw_alloc_xmitframe(&adapter->xmitpriv);
xframe = rtw_alloc_xmitframe(&adapter->xmitpriv, os_qid);
if (!xframe) {
#ifdef DBG_TX_DROP_FRAME
RTW_INFO("DBG_TX_DROP_FRAME "FUNC_ADPT_FMT" rtw_alloc_xmitframe fail\n"

View File

@ -412,7 +412,7 @@ u8 *rtw_set_ie_mesh_config(u8 *buf, u32 *buf_len
, bool mbca_en, bool tbtt_adj, bool ps_level);
int rtw_bss_is_same_mbss(WLAN_BSSID_EX *a, WLAN_BSSID_EX *b);
int rtw_bss_is_candidate_mesh_peer(WLAN_BSSID_EX *self, WLAN_BSSID_EX *target, u8 ch, u8 add_peer);
int rtw_bss_is_candidate_mesh_peer(_adapter *adapter, WLAN_BSSID_EX *target, u8 ch, u8 add_peer);
void rtw_chk_candidate_peer_notify(_adapter *adapter, struct wlan_network *scanned);
@ -484,7 +484,8 @@ void rtw_mesh_plink_ctl_init(_adapter *adapter);
void rtw_mesh_plink_ctl_deinit(_adapter *adapter);
void dump_mesh_plink_ctl(void *sel, _adapter *adapter);
int rtw_mesh_peer_establish(_adapter *adapter, struct mesh_plink_ent *plink, struct sta_info *sta);
u8 rtw_mesh_set_plink_state_cmd(_adapter *adapter, const u8 *mac, u8 plink_state);
void _rtw_mesh_expire_peer_ent(_adapter *adapter, struct mesh_plink_ent *plink);
void rtw_mesh_expire_peer(_adapter *adapter, const u8 *peer_addr);
u8 rtw_mesh_ps_annc(_adapter *adapter, u8 ps);
@ -501,7 +502,7 @@ void rtw_mesh_deinit_mesh_info(_adapter *adapter);
void dump_mesh_b2u_flags(void *sel, _adapter *adapter);
#endif
int rtw_mesh_addr_resolve(_adapter *adapter, struct xmit_frame *xframe, _pkt *pkt, _list *b2u_list);
int rtw_mesh_addr_resolve(_adapter *adapter, u16 os_qid, struct xmit_frame *xframe, _pkt *pkt, _list *b2u_list);
s8 rtw_mesh_tx_set_whdr_mctrl_len(u8 mesh_frame_mode, struct pkt_attrib *attrib);
void rtw_mesh_tx_build_mctrl(_adapter *adapter, struct pkt_attrib *attrib, u8 *buf);
@ -518,6 +519,7 @@ int rtw_mesh_rx_msdu_act_check(union recv_frame *rframe
, const u8 *mda, const u8 *msa
, const u8 *da, const u8 *sa
, struct rtw_ieee80211s_hdr *mctrl
, u8 *msdu, enum rtw_rx_llc_hdl llc_hdl
, struct xmit_frame **fwd_frame, _list *b2u_list);
void dump_mesh_stats(void *sel, _adapter *adapter);

View File

@ -394,162 +394,6 @@ int rtw_mesh_path_error_tx(_adapter *adapter,
return 0;
}
static u32 rtw_get_vht_bitrate(u8 mcs, u8 bw, u8 nss, u8 sgi)
{
static const u32 base[4][10] = {
{ 6500000,
13000000,
19500000,
26000000,
39000000,
52000000,
58500000,
65000000,
78000000,
/* not in the spec, but some devices use this: */
86500000,
},
{ 13500000,
27000000,
40500000,
54000000,
81000000,
108000000,
121500000,
135000000,
162000000,
180000000,
},
{ 29300000,
58500000,
87800000,
117000000,
175500000,
234000000,
263300000,
292500000,
351000000,
390000000,
},
{ 58500000,
117000000,
175500000,
234000000,
351000000,
468000000,
526500000,
585000000,
702000000,
780000000,
},
};
u32 bitrate;
int bw_idx;
if (mcs > 9) {
RTW_HWMP_INFO("Invalid mcs = %d\n", mcs);
return 0;
}
if (nss > 4 || nss < 1) {
RTW_HWMP_INFO("Now only support nss = 1, 2, 3, 4\n");
}
switch (bw) {
case CHANNEL_WIDTH_160:
bw_idx = 3;
break;
case CHANNEL_WIDTH_80:
bw_idx = 2;
break;
case CHANNEL_WIDTH_40:
bw_idx = 1;
break;
case CHANNEL_WIDTH_20:
bw_idx = 0;
break;
default:
RTW_HWMP_INFO("bw = %d currently not supported\n", bw);
return 0;
}
bitrate = base[bw_idx][mcs];
bitrate *= nss;
if (sgi)
bitrate = (bitrate / 9) * 10;
/* do NOT round down here */
return (bitrate + 50000) / 100000;
}
static u32 rtw_get_ht_bitrate(u8 mcs, u8 bw, u8 sgi)
{
int modulation, streams, bitrate;
/* the formula below does only work for MCS values smaller than 32 */
if (mcs >= 32) {
RTW_HWMP_INFO("Invalid mcs = %d\n", mcs);
return 0;
}
if (bw > 1) {
RTW_HWMP_INFO("Now HT only support bw = 0(20Mhz), 1(40Mhz)\n");
return 0;
}
modulation = mcs & 7;
streams = (mcs >> 3) + 1;
bitrate = (bw == 1) ? 13500000 : 6500000;
if (modulation < 4)
bitrate *= (modulation + 1);
else if (modulation == 4)
bitrate *= (modulation + 2);
else
bitrate *= (modulation + 3);
bitrate *= streams;
if (sgi)
bitrate = (bitrate / 9) * 10;
/* do NOT round down here */
return (bitrate + 50000) / 100000;
}
/**
* @bw: 0(20Mhz), 1(40Mhz), 2(80Mhz), 3(160Mhz)
* @rate_idx: DESC_RATEXXXX & 0x7f
* @sgi: DESC_RATEXXXX >> 7
* Returns: bitrate in 100kbps
*/
static u32 rtw_desc_rate_to_bitrate(u8 bw, u8 rate_idx, u8 sgi)
{
u32 bitrate;
if (rate_idx <= DESC_RATE54M){
u16 ofdm_rate[12] = {10, 20, 55, 110,
60, 90, 120, 180, 240, 360, 480, 540};
bitrate = ofdm_rate[rate_idx];
} else if ((DESC_RATEMCS0 <= rate_idx) &&
(rate_idx <= DESC_RATEMCS31)) {
u8 mcs = rate_idx - DESC_RATEMCS0;
bitrate = rtw_get_ht_bitrate(mcs, bw, sgi);
} else if ((DESC_RATEVHTSS1MCS0 <= rate_idx) &&
(rate_idx <= DESC_RATEVHTSS4MCS9)) {
u8 mcs = (rate_idx - DESC_RATEVHTSS1MCS0) % 10;
u8 nss = ((rate_idx - DESC_RATEVHTSS1MCS0) / 10) + 1;
bitrate = rtw_get_vht_bitrate(mcs, bw, nss, sgi);
} else {
/* 60Ghz ??? */
bitrate = 1;
}
return bitrate;
}
static u32 rtw_airtime_link_metric_get(_adapter *adapter, struct sta_info *sta)
{
struct dm_struct *dm = adapter_to_phydm(adapter);

615
core/monitor/rtw_radiotap.c Normal file
View File

@ -0,0 +1,615 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#define _RTW_RADIOTAP_C_
#ifdef CONFIG_WIFI_MONITOR
#include <drv_types.h>
#include <hal_data.h>
#define CHAN2FREQ(a) ((a < 14) ? (2407+5*a) : (5000+5*a))
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0))
#define IEEE80211_RADIOTAP_ZERO_LEN_PSDU 26
#define IEEE80211_RADIOTAP_LSIG 27
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0))
#define IEEE80211_RADIOTAP_TIMESTAMP 22
/* For IEEE80211_RADIOTAP_TIMESTAMP */
#define IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MASK 0x000F
#define IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MS 0x0000
#define IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US 0x0001
#define IEEE80211_RADIOTAP_TIMESTAMP_UNIT_NS 0x0003
#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_MASK 0x00F0
#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_BEGIN_MDPU 0x0000
#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_MPDU 0x0010
#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_PPDU 0x0020
#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_PLCP_SIG_ACQ 0x0030
#define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_UNKNOWN 0x00F0
#define IEEE80211_RADIOTAP_TIMESTAMP_FLAG_64BIT 0x00
#define IEEE80211_RADIOTAP_TIMESTAMP_FLAG_32BIT 0x01
#define IEEE80211_RADIOTAP_TIMESTAMP_FLAG_ACCURACY 0x02
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0))
/* for IEEE80211_RADIOTAP_CHANNEL */
#define IEEE80211_CHAN_GSM 0x1000 /* GSM (900 MHz) */
#define IEEE80211_CHAN_STURBO 0x2000 /* Static Turbo */
#define IEEE80211_CHAN_HALF 0x4000 /* Half channel (10 MHz wide) */
#define IEEE80211_CHAN_QUARTER 0x8000 /* Quarter channel (5 MHz wide) */
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
#define IEEE80211_RADIOTAP_VHT 21
/* For IEEE80211_RADIOTAP_VHT */
#define IEEE80211_RADIOTAP_VHT_KNOWN_STBC 0x0001
#define IEEE80211_RADIOTAP_VHT_KNOWN_TXOP_PS_NA 0x0002
#define IEEE80211_RADIOTAP_VHT_KNOWN_GI 0x0004
#define IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS 0x0008
#define IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM 0x0010
#define IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED 0x0020
#define IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH 0x0040
#define IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID 0x0080
#define IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID 0x0100
#define IEEE80211_RADIOTAP_VHT_FLAG_STBC 0x01
#define IEEE80211_RADIOTAP_VHT_FLAG_TXOP_PS_NA 0x02
#define IEEE80211_RADIOTAP_VHT_FLAG_SGI 0x04
#define IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9 0x08
#define IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM 0x10
#define IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED 0x20
#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0))
#define IEEE80211_RADIOTAP_CODING_LDPC_USER0 0x01
#define IEEE80211_RADIOTAP_CODING_LDPC_USER1 0x02
#define IEEE80211_RADIOTAP_CODING_LDPC_USER2 0x04
#define IEEE80211_RADIOTAP_CODING_LDPC_USER3 0x08
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
#define IEEE80211_RADIOTAP_AMPDU_STATUS 20
/* For IEEE80211_RADIOTAP_AMPDU_STATUS */
#define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001
#define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002
#define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004
#define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008
#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010
#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020
#elif (LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0))
#define IEEE80211_RADIOTAP_AMPDU_EOF 0x0040
#define IEEE80211_RADIOTAP_AMPDU_EOF_KNOWN 0x0080
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
#define IEEE80211_RADIOTAP_MCS 19
/* For IEEE80211_RADIOTAP_MCS */
#define IEEE80211_RADIOTAP_MCS_HAVE_BW 0x01
#define IEEE80211_RADIOTAP_MCS_HAVE_MCS 0x02
#define IEEE80211_RADIOTAP_MCS_HAVE_GI 0x04
#define IEEE80211_RADIOTAP_MCS_HAVE_FMT 0x08
#define IEEE80211_RADIOTAP_MCS_HAVE_FEC 0x10
#define IEEE80211_RADIOTAP_MCS_BW_MASK 0x03
#define IEEE80211_RADIOTAP_MCS_BW_20 0
#define IEEE80211_RADIOTAP_MCS_BW_40 1
#define IEEE80211_RADIOTAP_MCS_BW_20L 2
#define IEEE80211_RADIOTAP_MCS_BW_20U 3
#define IEEE80211_RADIOTAP_MCS_SGI 0x04
#define IEEE80211_RADIOTAP_MCS_FMT_GF 0x08
#define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10
#elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
#define IEEE80211_RADIOTAP_MCS_HAVE_STBC 0x20
#define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60
#define IEEE80211_RADIOTAP_MCS_STBC_1 1
#define IEEE80211_RADIOTAP_MCS_STBC_2 2
#define IEEE80211_RADIOTAP_MCS_STBC_3 3
#define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34))
#define IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE 29
#define IEEE80211_RADIOTAP_VENDOR_NAMESPACE 30
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30))
#define IEEE80211_RADIOTAP_F_BADFCS 0x40
#endif
static inline void _rtw_radiotap_fill_flags(struct rx_pkt_attrib *a, u8 *flags)
{
struct moinfo *moif = (struct moinfo *)&a->moif;
if (0)
*flags |= IEEE80211_RADIOTAP_F_CFP;
if (0)
*flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
if ((a->encrypt == 1) || (a->encrypt == 5))
*flags |= IEEE80211_RADIOTAP_F_WEP;
if (a->mfrag)
*flags |= IEEE80211_RADIOTAP_F_FRAG;
if (1)
*flags |= IEEE80211_RADIOTAP_F_FCS;
if (0)
*flags |= IEEE80211_RADIOTAP_F_DATAPAD;
if (a->crc_err)
*flags |= IEEE80211_RADIOTAP_F_BADFCS;
/* Currently unspecified but used
for short guard interval (HT) */
if (moif->u.snif_info.sgi || a->sgi)
*flags |= 0x80;
}
sint rtw_fill_radiotap_hdr(_adapter *padapter, struct rx_pkt_attrib *a, u8 *buf)
{
#define RTAP_HDR_MAX 64
sint ret = _SUCCESS;
struct moinfo *moif = (struct moinfo *)&a->moif;
u8 rx_cnt = 0;
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
int i = 0;
u8 tmp_8bit = 0;
u16 tmp_16bit = 0;
u32 tmp_32bit = 0;
u64 tmp_64bit = 0;
_pkt *pskb = NULL;
struct ieee80211_radiotap_header *rtap_hdr = NULL;
u8 *ptr = NULL;
/*
radiotap length (include header 8)
11G length: 36 (0x0040002f)
11N length:
11AC length: 60 (0x0070002b)
*/
u8 hdr_buf[RTAP_HDR_MAX] = { 0 };
u16 rt_len = 8;
/* create header */
rtap_hdr = (struct ieee80211_radiotap_header *)&hdr_buf[0];
rtap_hdr->it_version = PKTHDR_RADIOTAP_VERSION;
/* each antenna information */
rx_cnt = rf_type_to_rf_rx_cnt(pHalData->rf_type);
#if 0
if (rx_cnt > 1) {
rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE) |
BIT(IEEE80211_RADIOTAP_EXT);
for (i = 1; i < rx_cnt; i++) {
tmp_32bit = (BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
BIT(IEEE80211_RADIOTAP_LOCK_QUALITY) |
BIT(IEEE80211_RADIOTAP_ANTENNA) |
BIT(IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE) |
BIT(IEEE80211_RADIOTAP_EXT));
_rtw_memcpy(&hdr_buf[rt_len], &tmp_32bit, 4);
rt_len += 4;
}
tmp_32bit = (BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
BIT(IEEE80211_RADIOTAP_LOCK_QUALITY) |
BIT(IEEE80211_RADIOTAP_ANTENNA));
_rtw_memcpy(&hdr_buf[rt_len], &tmp_32bit, 4);
rt_len += 4;
}
#endif
/* tsft, Required Alignment: 8 bytes */
if (0) { //(a->free_cnt) {
/* TSFT + free_cnt */
rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_TSFT);
if (!IS_ALIGNED(rt_len, 8))
rt_len = ((rt_len + 7) & 0xFFF8); /* Alignment */
tmp_64bit = cpu_to_le64(a->free_cnt);
_rtw_memcpy(&hdr_buf[rt_len], &tmp_64bit, 8);
rt_len += 8;
}
/* flags */
rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_FLAGS);
_rtw_radiotap_fill_flags(a, &hdr_buf[rt_len]);
rt_len += 1;
/* rate */
if (a->data_rate <= DESC_RATE54M) {
rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_RATE);
hdr_buf[rt_len] = hw_rate_to_m_rate(a->data_rate);
rt_len += 1;
}
/* channel & flags, Required Alignment: 2 bytes */
if (1) {
rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_CHANNEL);
rt_len += (rt_len % 2); /* Alignment */
tmp_16bit = CHAN2FREQ(rtw_get_oper_ch(padapter));
_rtw_memcpy(&hdr_buf[rt_len], &tmp_16bit, 2);
rt_len += 2;
/* channel flags */
tmp_16bit = 0;
if (pHalData->current_band_type == 0)
tmp_16bit |= cpu_to_le16(IEEE80211_CHAN_2GHZ);
else
tmp_16bit |= cpu_to_le16(IEEE80211_CHAN_5GHZ);
if (a->data_rate <= DESC_RATE11M) {
/* CCK */
tmp_16bit |= cpu_to_le16(IEEE80211_CHAN_CCK);
} else {
/* OFDM */
tmp_16bit |= cpu_to_le16(IEEE80211_CHAN_OFDM);
}
if (rtw_get_oper_bw(padapter) == CHANNEL_WIDTH_10) {
/* 10Mhz Channel Width */
tmp_16bit |= cpu_to_le16(IEEE80211_CHAN_HALF);
}
if (rtw_get_oper_bw(padapter) == CHANNEL_WIDTH_5) {
/* 5Mhz Channel Width */
tmp_16bit |= cpu_to_le16(IEEE80211_CHAN_QUARTER);
}
_rtw_memcpy(&hdr_buf[rt_len], &tmp_16bit, 2);
rt_len += 2;
}
/* dBm Antenna Signal */
rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
hdr_buf[rt_len] = a->phy_info.recv_signal_power;
rt_len += 1;
#if 0
/* dBm Antenna Noise */
rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_DBM_ANTNOISE);
hdr_buf[rt_len] = 0;
rt_len += 1;
#endif
#if 0
/* Signal Quality, Required Alignment: 2 bytes */
rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_LOCK_QUALITY);
if (!IS_ALIGNED(rt_len, 2))
rt_len++;
hdr_buf[rt_len] = a->phy_info.signal_quality;
rt_len += 2;
#endif
#if 0
/* Antenna */
rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_ANTENNA);
hdr_buf[rt_len] = 0; /* pHalData->rf_type; */
rt_len += 1;
#endif
#if 0
/* RX flags, Required Alignment: 2 bytes */
rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_RX_FLAGS);
tmp_16bit = 0;
_rtw_memcpy(&hdr_buf[rt_len], &tmp_16bit, 2);
rt_len += 2;
#endif
/* MCS information, Required Alignment: 1 bytes */
if (a->data_rate >= DESC_RATEMCS0 && a->data_rate <= DESC_RATEMCS31) {
rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_MCS);
/* Structure u8 known, u8 flags, u8 mcs */
/* known.bandwidth */
hdr_buf[rt_len] |= IEEE80211_RADIOTAP_MCS_HAVE_BW;
if (moif->u.snif_info.ofdm_bw)
hdr_buf[rt_len + 1] |= IEEE80211_RADIOTAP_MCS_BW_40;
if (a->bw == CHANNEL_WIDTH_40)
hdr_buf[rt_len + 1] |= IEEE80211_RADIOTAP_MCS_BW_40;
else
hdr_buf[rt_len + 1] |= IEEE80211_RADIOTAP_MCS_BW_20;
/* known.guard interval */
hdr_buf[rt_len] |= IEEE80211_RADIOTAP_MCS_HAVE_GI;
if (moif->u.snif_info.sgi) {
hdr_buf[rt_len + 1] |= IEEE80211_RADIOTAP_MCS_SGI;
} else {
hdr_buf[rt_len + 1] |= ((a->sgi & 0x01) << 2);
}
/* FEC Type */
hdr_buf[rt_len] |= IEEE80211_RADIOTAP_MCS_HAVE_FEC;
if (moif->u.snif_info.ldpc) {
hdr_buf[rt_len + 1] |= ((moif->u.snif_info.ldpc & 0x01) << 4);
} else {
hdr_buf[rt_len + 1] |= ((a->ldpc & 0x01) << 4);
}
/* STBC */
hdr_buf[rt_len] |= IEEE80211_RADIOTAP_MCS_HAVE_STBC;
if (moif->u.snif_info.stbc) {
hdr_buf[rt_len + 1] |= ((moif->u.snif_info.stbc & 0x03) << 5);
} else {
hdr_buf[rt_len + 1] |= ((a->stbc & 0x03) << 5);
}
/* known.MCS index */
hdr_buf[rt_len] |= IEEE80211_RADIOTAP_MCS_HAVE_MCS;
/* u8 mcs */
hdr_buf[rt_len + 2] = a->data_rate - DESC_RATEMCS0;
rt_len += 3;
}
/* AMPDU, Required Alignment: 4 bytes */
if (a->ampdu) {
static u32 ref_num = 0x10000000;
static u8 ppdu_cnt = 0;
/* Structure u32 reference number, u16 flags, u8 delimiter CRC value, u8 reserved */
rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_AMPDU_STATUS);
if (!IS_ALIGNED(rt_len, 4))
rt_len = ((rt_len + 3) & 0xFFFC); /* Alignment */
/* u32 reference number */
if (a->ppdu_cnt != ppdu_cnt) {
ppdu_cnt = a->ppdu_cnt;
ref_num += 1;
}
tmp_32bit = cpu_to_le32(ref_num);
_rtw_memcpy(&hdr_buf[rt_len], &tmp_32bit, 4);
rt_len += 4;
/* u16 flags */
tmp_16bit = 0;
if (0) {
tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN);
tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN);
}
if (0) {
tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_AMPDU_IS_LAST);
tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN);
}
if (0) {
tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR);
tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN);
}
if (a->ampdu_eof) {
tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_AMPDU_EOF_KNOWN);
tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_AMPDU_EOF);
}
_rtw_memcpy(&hdr_buf[rt_len], &tmp_16bit, 2);
rt_len += 2;
/* u8 delimiter CRC value, u8 reserved */
rt_len += 2;
}
/* VHT, Required Alignment: 2 bytes */
if (a->data_rate >= DESC_RATEVHTSS1MCS0 && a->data_rate <= DESC_RATEVHTSS4MCS9) {
rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_VHT);
rt_len += (rt_len % 2); /* Alignment */
/* Structure
u16 known, u8 flags, u8 bandwidth, u8 mcs_nss[4],
u8 coding, u8 group_id, u16 partial_aid */
tmp_16bit = 0;
/* STBC */
tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_STBC);
if (moif->u.snif_info.stbc) {
hdr_buf[rt_len + 2] |= IEEE80211_RADIOTAP_VHT_FLAG_STBC;
} else {
hdr_buf[rt_len + 2] |= (a->stbc & 0x01);
}
/* TXOP_PS_NOT_ALLOWED */
tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_TXOP_PS_NA);
if (moif->u.snif_info.vht_txop_not_allow) {
hdr_buf[rt_len + 2] |= IEEE80211_RADIOTAP_VHT_FLAG_TXOP_PS_NA;
}
/* Guard interval */
tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_GI);
if (moif->u.snif_info.sgi) {
hdr_buf[rt_len + 2] |= IEEE80211_RADIOTAP_VHT_FLAG_SGI;
} else {
hdr_buf[rt_len + 2] |= ((a->sgi & 0x01) << 2);
}
/* Short GI NSYM */
tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS);
if (moif->u.snif_info.vht_nsym_dis) {
hdr_buf[rt_len + 2] |= IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9;
}
/* LDPC extra OFDM symbol */
tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM);
if (moif->u.snif_info.vht_ldpc_extra) {
hdr_buf[rt_len + 2] |= IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM;
} else {
hdr_buf[rt_len + 2] |= ((a->ldpc & 0x01) << 4);
}
/* Short GI NSYM */
tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED);
if (moif->u.snif_info.vht_beamformed) {
hdr_buf[rt_len + 2] |= IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED;
}
/* know.Bandwidth */
tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH);
/* Group ID */
tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID);
/* Partial AID */
tmp_16bit |= cpu_to_le16(IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID);
_rtw_memcpy(&hdr_buf[rt_len], &tmp_16bit, 2);
rt_len += 3;
/* u8 bandwidth */
if (moif->u.snif_info.ofdm_bw)
tmp_8bit = moif->u.snif_info.ofdm_bw;
else
tmp_8bit = a->bw;
switch (tmp_8bit) {
case CHANNEL_WIDTH_20:
hdr_buf[rt_len] |= 0;
break;
case CHANNEL_WIDTH_40:
hdr_buf[rt_len] |= 1;
break;
case CHANNEL_WIDTH_80:
hdr_buf[rt_len] |= 4;
break;
case CHANNEL_WIDTH_160:
hdr_buf[rt_len] |= 11;
break;
default:
hdr_buf[rt_len] |= 0;
}
rt_len += 1;
/* u8 mcs_nss[4] */
if ((DESC_RATEVHTSS1MCS0 <= a->data_rate) &&
(a->data_rate <= DESC_RATEVHTSS4MCS9)) {
/* User 0 */
/* MCS */
hdr_buf[rt_len] = ((a->data_rate - DESC_RATEVHTSS1MCS0) % 10) << 4;
/* NSS */
hdr_buf[rt_len] |= (((a->data_rate - DESC_RATEVHTSS1MCS0) / 10) + 1);
}
rt_len += 4;
/* u8 coding, phystat? */
hdr_buf[rt_len] = 0;
rt_len += 1;
/* u8 group_id */
hdr_buf[rt_len] = moif->u.snif_info.vht_group_id;
rt_len += 1;
/* u16 partial_aid */
tmp_16bit = cpu_to_le16(moif->u.snif_info.vht_nsts_aid);
_rtw_memcpy(&hdr_buf[rt_len], &tmp_16bit, 2);
rt_len += 2;
}
/* frame timestamp, Required Alignment: 8 bytes */
if (0) { //(a->free_cnt) {
rtap_hdr->it_present |= BIT(IEEE80211_RADIOTAP_TIMESTAMP);
if (!IS_ALIGNED(rt_len, 8))
rt_len = ((rt_len + 7) & 0xFFF8); /* Alignment */
/* u64 timestamp */
tmp_64bit = cpu_to_le64(a->free_cnt);
_rtw_memcpy(&hdr_buf[rt_len], &tmp_64bit, 8);
rt_len += 8;
/* u16 accuracy */
tmp_16bit = cpu_to_le16(22);
_rtw_memcpy(&hdr_buf[rt_len], &tmp_16bit, 2);
rt_len += 2;
/* u8 unit/position */
hdr_buf[rt_len] |= IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;
rt_len += 1;
/* u8 flags */
hdr_buf[rt_len] |= IEEE80211_RADIOTAP_TIMESTAMP_FLAG_32BIT;
hdr_buf[rt_len] |= IEEE80211_RADIOTAP_TIMESTAMP_FLAG_ACCURACY;
rt_len += 1;
}
/* each antenna information */
#if 0
if (rx_cnt > 1) {
for (i = 0; i <= rx_cnt; i++) {
/* dBm Antenna Signal */
hdr_buf[rt_len] = a->phy_info.rx_mimo_signal_strength[i];
rt_len += 1;
/* Signal Quality */
if (!IS_ALIGNED(rt_len, 2))
rt_len++;
hdr_buf[rt_len] = cpu_to_le16(a->phy_info.rx_mimo_signal_quality[i]);
rt_len += 2;
/* Antenna */
hdr_buf[rt_len] = i; /* pHalData->rf_type; */
rt_len += 1;
}
}
#endif
/* push to skb */
pskb = (_pkt *)buf;
if (skb_headroom(pskb) < rt_len) {
RTW_INFO("%s:%d %s headroom is too small.\n", __FILE__, __LINE__, __func__);
ret = _FAIL;
return ret;
}
ptr = skb_push(pskb, rt_len);
if (ptr) {
rtap_hdr->it_len = cpu_to_le16(rt_len);
rtap_hdr->it_present = cpu_to_le32(rtap_hdr->it_present);
memcpy(ptr, rtap_hdr, rt_len);
} else
ret = _FAIL;
return ret;
}
void rx_query_moinfo(struct rx_pkt_attrib *a, u8 *desc)
{
switch (a->drvinfo_sz) {
case 40:
_rtw_memcpy(a->moif, &desc[32], 8);
break;
case 48:
_rtw_memcpy(a->moif, &desc[32], 12);
break;
case 32:
/* passthrough */
default:
break;
}
}
#endif /* CONFIG_WIFI_MONITOR */

View File

@ -0,0 +1,63 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#ifndef __RTW_RADIOTAP_H_
#define __RTW_RADIOTAP_H_
struct mon_reg_backup {
/* flags */
u8 known_rcr:1;
u8 known_drvinfo:1;
u8 known_rxfilter:1;
u8 known_misc0:1;
/* data */
u8 drvinfo;
u16 rxfilter0;
u16 rxfilter1;
u16 rxfilter2;
u32 rcr;
u32 misc0;
};
struct moinfo {
union {
struct {
u32 sgi:1;
u32 ldpc:1;
u32 stbc:2;
u32 not_sounding:1;
u32 ofdm_bw:2;
u32 vht_group_id:2;
u32 vht_nsts_aid:12;
u32 vht_txop_not_allow:1;
u32 vht_nsym_dis:1;
u32 vht_ldpc_extra:1;
u32 vht_su_mcs:12;
u32 vht_beamformed:1;
}snif_info;
struct {
u32 A;
u32 B;
u32 C;
}plcp_info;
}u;
};
sint rtw_fill_radiotap_hdr(_adapter *padapter, struct rx_pkt_attrib *a, u8 *buf);
void rx_query_moinfo(struct rx_pkt_attrib *a, u8 *desc);
#endif /* __RTW_RADIOTAP_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -94,11 +94,13 @@ static void _get_sta_beamform_cap(PADAPTER adapter, struct sta_info *sta,
u8 *sta_bf_cap, u8 *sounding_dim, u8 *comp_steering)
{
struct beamforming_info *info;
struct mlme_priv *mlme;
struct ht_priv *ht;
u16 ht_bf_cap;
#ifdef CONFIG_80211AC_VHT
struct vht_priv *vht;
u16 vht_bf_cap;
#endif /* CONFIG_80211AC_VHT */
u16 bf_cap;
*sta_bf_cap = 0;
@ -110,56 +112,123 @@ static void _get_sta_beamform_cap(PADAPTER adapter, struct sta_info *sta,
#ifdef CONFIG_80211AC_VHT
vht = &adapter->mlmepriv.vhtpriv;
#endif /* CONFIG_80211AC_VHT */
mlme = &adapter->mlmepriv;
if (is_supported_ht(sta->wireless_mode) == _TRUE) {
/* HT */
bf_cap = ht->beamform_cap;
if (is_supported_ht(sta->wireless_mode) == _FALSE)
return;
if (TEST_FLAG(bf_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE)) {
info->beamforming_cap |= BEAMFORMEE_CAP_HT_EXPLICIT;
*sta_bf_cap |= BEAMFORMER_CAP_HT_EXPLICIT;
*sounding_dim = (bf_cap & BEAMFORMING_HT_BEAMFORMEE_CHNL_EST_CAP) >> 6;
}
if (TEST_FLAG(bf_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE)) {
/* HT */
if (check_fwstate(mlme, WIFI_AP_STATE)) {
/* Get peer clinet's BF cap: the cap. is intersected with associated AP.*/
ht_bf_cap = sta->htpriv.beamform_cap;
RTW_INFO("At AP state, peer sta's ht_bf_cap=0x%x\n", ht_bf_cap);
if (TEST_FLAG(ht_bf_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE)) {
info->beamforming_cap |= BEAMFORMER_CAP_HT_EXPLICIT;
*sta_bf_cap |= BEAMFORMEE_CAP_HT_EXPLICIT;
*comp_steering = (bf_cap & BEAMFORMING_HT_BEAMFORMER_STEER_NUM) >> 4;
*comp_steering = (ht_bf_cap & BEAMFORMING_HT_BEAMFORMER_STEER_NUM) >> 4;
RTW_INFO("%s: we support BEAMFORMER_CAP_HT_EXPLICIT\n", __func__);
}
if (TEST_FLAG(ht_bf_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE)) {
info->beamforming_cap |= BEAMFORMEE_CAP_HT_EXPLICIT;
*sta_bf_cap |= BEAMFORMER_CAP_HT_EXPLICIT;
*sounding_dim = (ht_bf_cap & BEAMFORMING_HT_BEAMFORMEE_CHNL_EST_CAP) >> 6;
RTW_INFO("%s: we support BEAMFORMEE_CAP_HT_EXPLICIT\n", __func__);
}
} else {
/* Get adapter's BF Cap: the cap. is intersected with associated AP.*/
ht_bf_cap = ht->beamform_cap;
RTW_INFO("At non-AP state, adapter's ht_bf_cap=0x%x\n", ht_bf_cap);
if (TEST_FLAG(ht_bf_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE)) {
info->beamforming_cap |= BEAMFORMEE_CAP_HT_EXPLICIT;
*sta_bf_cap |= BEAMFORMER_CAP_HT_EXPLICIT;
*sounding_dim = (ht_bf_cap & BEAMFORMING_HT_BEAMFORMEE_CHNL_EST_CAP) >> 6;
RTW_INFO("%s: we support BEAMFORMEE_CAP_HT_EXPLICIT\n", __func__);
}
if (TEST_FLAG(ht_bf_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE)) {
info->beamforming_cap |= BEAMFORMER_CAP_HT_EXPLICIT;
*sta_bf_cap |= BEAMFORMEE_CAP_HT_EXPLICIT;
*comp_steering = (ht_bf_cap & BEAMFORMING_HT_BEAMFORMER_STEER_NUM) >> 4;
RTW_INFO("%s: we support BEAMFORMER_CAP_HT_EXPLICIT\n", __func__);
}
}
#ifdef CONFIG_80211AC_VHT
if (is_supported_vht(sta->wireless_mode) == _TRUE) {
/* VHT */
bf_cap = vht->beamform_cap;
/* We are SU Beamformee because the STA is SU Beamformer */
if (TEST_FLAG(bf_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE)) {
info->beamforming_cap |= BEAMFORMEE_CAP_VHT_SU;
*sta_bf_cap |= BEAMFORMER_CAP_VHT_SU;
if (is_supported_vht(sta->wireless_mode) == _FALSE)
return;
/* We are MU Beamformee because the STA is MU Beamformer */
if (TEST_FLAG(bf_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE)) {
info->beamforming_cap |= BEAMFORMEE_CAP_VHT_MU;
*sta_bf_cap |= BEAMFORMER_CAP_VHT_MU;
}
/* VHT */
if (check_fwstate(mlme, WIFI_AP_STATE)) {
/* Get peer clinet's BF cap: the cap. is intersected with associated AP.*/
vht_bf_cap = sta->vhtpriv.beamform_cap;
RTW_INFO("At AP state, peer sta's vht_bf_cap=0x%x\n", vht_bf_cap);
*sounding_dim = (bf_cap & BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM) >> 12;
}
/* We are SU Beamformer because the STA is SU Beamformee */
if (TEST_FLAG(bf_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE)) {
if (TEST_FLAG(vht_bf_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE)) {
info->beamforming_cap |= BEAMFORMER_CAP_VHT_SU;
*sta_bf_cap |= BEAMFORMEE_CAP_VHT_SU;
RTW_INFO("%s: we support BEAMFORMER_CAP_VHT_SU\n", __func__);
/* We are MU Beamformer because the STA is MU Beamformee */
if (TEST_FLAG(bf_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE)) {
if (TEST_FLAG(vht_bf_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE)) {
info->beamforming_cap |= BEAMFORMER_CAP_VHT_MU;
*sta_bf_cap |= BEAMFORMEE_CAP_VHT_MU;
RTW_INFO("%s: we support BEAMFORMER_CAP_VHT_MU\n", __func__);
}
*comp_steering = (bf_cap & BEAMFORMING_VHT_BEAMFORMER_STS_CAP) >> 8;
*comp_steering = (vht_bf_cap & BEAMFORMING_VHT_BEAMFORMER_STS_CAP) >> 8;
}
/* We are SU Beamformee because the STA is SU Beamformer */
if (TEST_FLAG(vht_bf_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE)) {
info->beamforming_cap |= BEAMFORMEE_CAP_VHT_SU;
*sta_bf_cap |= BEAMFORMER_CAP_VHT_SU;
RTW_INFO("%s: we support BEAMFORMEE_CAP_VHT_SU\n", __func__);
/* The STA is MU Beamformer, but we(AP) should not be MU Beamformee */
if (TEST_FLAG(vht_bf_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE)) {
RTW_WARN("%s: Associated STA should not be a MU BFer.\n", __func__);
}
*sounding_dim = (vht_bf_cap & BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM) >> 12;
}
} else {
/* Get adapter's BF Cap: the cap. is intersected with associated AP.*/
vht_bf_cap = vht->beamform_cap;
RTW_INFO("At non-AP state, adapter's vht_bf_cap=0x%x\n", vht_bf_cap);
/* We are SU Beamformee */
if (TEST_FLAG(vht_bf_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE)) {
info->beamforming_cap |= BEAMFORMEE_CAP_VHT_SU;
*sta_bf_cap |= BEAMFORMER_CAP_VHT_SU;
RTW_INFO("%s: we support BEAMFORMEE_CAP_VHT_SU\n", __func__);
/* We are MU Beamformee */
if (TEST_FLAG(vht_bf_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE)) {
info->beamforming_cap |= BEAMFORMEE_CAP_VHT_MU;
*sta_bf_cap |= BEAMFORMER_CAP_VHT_MU;
RTW_INFO("%s: we support BEAMFORMEE_CAP_VHT_MU\n", __func__);
}
*sounding_dim = (vht_bf_cap & BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM) >> 12;
}
/* We are SU Beamformer */
if (TEST_FLAG(vht_bf_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE)) {
info->beamforming_cap |= BEAMFORMER_CAP_VHT_SU;
*sta_bf_cap |= BEAMFORMEE_CAP_VHT_SU;
RTW_INFO("%s: we support BEAMFORMER_CAP_VHT_SU\n", __func__);
/* We are MU Beamformer, but client should not be a MU Beamformer */
if (TEST_FLAG(vht_bf_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE)) {
RTW_WARN("%s: non-AP state should not support MU BFer.\n", __func__);
}
*comp_steering = (vht_bf_cap & BEAMFORMING_VHT_BEAMFORMER_STS_CAP) >> 8;
}
}
#endif /* CONFIG_80211AC_VHT */
}
static u8 _send_ht_ndpa_packet(PADAPTER adapter, u8 *ra, enum channel_width bw)
@ -770,7 +839,7 @@ static void _sounding_handler(PADAPTER adapter)
wait_cnt = 0;
if (check_fwstate(&adapter->mlmepriv, WIFI_SITE_MONITOR) == _TRUE) {
if (check_fwstate(&adapter->mlmepriv, WIFI_UNDER_SURVEY) == _TRUE) {
RTW_INFO("%s: Sounding abort! scanning APs...\n", __FUNCTION__);
info->sounding_running--;
return;
@ -1386,6 +1455,10 @@ static void _beamforming_enter(PADAPTER adapter, void *p)
__FUNCTION__, MAC_ARG(sta_copy->cmn.mac_addr));
return;
}
RTW_INFO("%s: find STA info for " MAC_FMT "\n",
__FUNCTION__, MAC_ARG(sta_copy->cmn.mac_addr));
if (sta != sta_copy) {
RTW_WARN("%s: Origin sta(fake)=%p realsta=%p for " MAC_FMT "\n",
__FUNCTION__, sta_copy, sta, MAC_ARG(sta_copy->cmn.mac_addr));
@ -1890,7 +1963,7 @@ u8 rtw_bf_cmd(PADAPTER adapter, s32 type, u8 *pbuf, s32 size, u8 enqueue)
pdrvextra_cmd_parm->size = size;
pdrvextra_cmd_parm->pbuf = wk_buf;
init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
res = rtw_enqueue_cmd(pcmdpriv, ph2c);
@ -2097,7 +2170,7 @@ u8 beamforming_wk_cmd(_adapter *padapter, s32 type, u8 *pbuf, s32 size, u8 enque
pdrvextra_cmd_parm->size = size;
pdrvextra_cmd_parm->pbuf = wk_buf;
init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
res = rtw_enqueue_cmd(pcmdpriv, ph2c);
} else

View File

@ -17,6 +17,8 @@
#ifdef __KERNEL__
#include <linux/if_arp.h>
#include <net/ip.h>
#include <net/ipx.h>
#include <linux/atalk.h>
#include <linux/udp.h>
#include <linux/if_pppox.h>
#endif
@ -167,6 +169,39 @@ static __inline__ void __nat25_generate_ipv4_network_addr(unsigned char *network
}
static __inline__ void __nat25_generate_ipx_network_addr_with_node(unsigned char *networkAddr,
unsigned int *ipxNetAddr, unsigned char *ipxNodeAddr)
{
memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
networkAddr[0] = NAT25_IPX;
memcpy(networkAddr + 1, (unsigned char *)ipxNetAddr, 4);
memcpy(networkAddr + 5, ipxNodeAddr, 6);
}
static __inline__ void __nat25_generate_ipx_network_addr_with_socket(unsigned char *networkAddr,
unsigned int *ipxNetAddr, unsigned short *ipxSocketAddr)
{
memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
networkAddr[0] = NAT25_IPX;
memcpy(networkAddr + 1, (unsigned char *)ipxNetAddr, 4);
memcpy(networkAddr + 5, (unsigned char *)ipxSocketAddr, 2);
}
static __inline__ void __nat25_generate_apple_network_addr(unsigned char *networkAddr,
unsigned short *network, unsigned char *node)
{
memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
networkAddr[0] = NAT25_APPLE;
memcpy(networkAddr + 1, (unsigned char *)network, 2);
networkAddr[3] = *node;
}
static __inline__ void __nat25_generate_pppoe_network_addr(unsigned char *networkAddr,
unsigned char *ac_mac, unsigned short *sid)
{
@ -294,6 +329,19 @@ static __inline__ int __nat25_network_hash(unsigned char *networkAddr)
x = networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10];
return x & (NAT25_HASH_SIZE - 1);
} else if (networkAddr[0] == NAT25_IPX) {
unsigned long x;
x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^
networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10];
return x & (NAT25_HASH_SIZE - 1);
} else if (networkAddr[0] == NAT25_APPLE) {
unsigned long x;
x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3];
return x & (NAT25_HASH_SIZE - 1);
} else if (networkAddr[0] == NAT25_PPPOE) {
unsigned long x;
@ -841,6 +889,227 @@ int nat25_db_handle(_adapter *priv, struct sk_buff *skb, int method)
}
}
/*---------------------------------------------------*/
/* Handle IPX and Apple Talk frame */
/*---------------------------------------------------*/
else if ((protocol == __constant_htons(ETH_P_IPX)) ||
(protocol == __constant_htons(ETH_P_ATALK)) ||
(protocol == __constant_htons(ETH_P_AARP))) {
unsigned char ipx_header[2] = {0xFF, 0xFF};
struct ipxhdr *ipx = NULL;
struct elapaarp *ea = NULL;
struct ddpehdr *ddp = NULL;
unsigned char *framePtr = skb->data + ETH_HLEN;
if (protocol == __constant_htons(ETH_P_IPX)) {
RTW_INFO("NAT25: Protocol=IPX (Ethernet II)\n");
ipx = (struct ipxhdr *)framePtr;
} else { /* if(protocol <= __constant_htons(ETH_FRAME_LEN)) */
if (!memcmp(ipx_header, framePtr, 2)) {
RTW_INFO("NAT25: Protocol=IPX (Ethernet 802.3)\n");
ipx = (struct ipxhdr *)framePtr;
} else {
unsigned char ipx_8022_type = 0xE0;
unsigned char snap_8022_type = 0xAA;
if (*framePtr == snap_8022_type) {
unsigned char ipx_snap_id[5] = {0x0, 0x0, 0x0, 0x81, 0x37}; /* IPX SNAP ID */
unsigned char aarp_snap_id[5] = {0x00, 0x00, 0x00, 0x80, 0xF3}; /* Apple Talk AARP SNAP ID */
unsigned char ddp_snap_id[5] = {0x08, 0x00, 0x07, 0x80, 0x9B}; /* Apple Talk DDP SNAP ID */
framePtr += 3; /* eliminate the 802.2 header */
if (!memcmp(ipx_snap_id, framePtr, 5)) {
framePtr += 5; /* eliminate the SNAP header */
RTW_INFO("NAT25: Protocol=IPX (Ethernet SNAP)\n");
ipx = (struct ipxhdr *)framePtr;
} else if (!memcmp(aarp_snap_id, framePtr, 5)) {
framePtr += 5; /* eliminate the SNAP header */
ea = (struct elapaarp *)framePtr;
} else if (!memcmp(ddp_snap_id, framePtr, 5)) {
framePtr += 5; /* eliminate the SNAP header */
ddp = (struct ddpehdr *)framePtr;
} else {
DEBUG_WARN("NAT25: Protocol=Ethernet SNAP %02x%02x%02x%02x%02x\n", framePtr[0],
framePtr[1], framePtr[2], framePtr[3], framePtr[4]);
return -1;
}
} else if (*framePtr == ipx_8022_type) {
framePtr += 3; /* eliminate the 802.2 header */
if (!memcmp(ipx_header, framePtr, 2)) {
RTW_INFO("NAT25: Protocol=IPX (Ethernet 802.2)\n");
ipx = (struct ipxhdr *)framePtr;
} else
return -1;
}
}
}
/* IPX */
if (ipx != NULL) {
switch (method) {
case NAT25_CHECK:
if (!memcmp(skb->data + ETH_ALEN, ipx->ipx_source.node, ETH_ALEN)) {
RTW_INFO("NAT25: Check IPX skb_copy\n");
return 0;
}
return -1;
case NAT25_INSERT: {
RTW_INFO("NAT25: Insert IPX, Dest=%08x,%02x%02x%02x%02x%02x%02x,%04x Source=%08x,%02x%02x%02x%02x%02x%02x,%04x\n",
ipx->ipx_dest.net,
ipx->ipx_dest.node[0],
ipx->ipx_dest.node[1],
ipx->ipx_dest.node[2],
ipx->ipx_dest.node[3],
ipx->ipx_dest.node[4],
ipx->ipx_dest.node[5],
ipx->ipx_dest.sock,
ipx->ipx_source.net,
ipx->ipx_source.node[0],
ipx->ipx_source.node[1],
ipx->ipx_source.node[2],
ipx->ipx_source.node[3],
ipx->ipx_source.node[4],
ipx->ipx_source.node[5],
ipx->ipx_source.sock);
if (!memcmp(skb->data + ETH_ALEN, ipx->ipx_source.node, ETH_ALEN)) {
RTW_INFO("NAT25: Use IPX Net, and Socket as network addr\n");
__nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_source.net, &ipx->ipx_source.sock);
/* change IPX source node addr to wlan STA address */
memcpy(ipx->ipx_source.node, GET_MY_HWADDR(priv), ETH_ALEN);
} else
__nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_source.net, ipx->ipx_source.node);
__nat25_db_network_insert(priv, skb->data + ETH_ALEN, networkAddr);
__nat25_db_print(priv);
}
return 0;
case NAT25_LOOKUP: {
if (!memcmp(GET_MY_HWADDR(priv), ipx->ipx_dest.node, ETH_ALEN)) {
RTW_INFO("NAT25: Lookup IPX, Modify Destination IPX Node addr\n");
__nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_dest.net, &ipx->ipx_dest.sock);
__nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
/* replace IPX destination node addr with Lookup destination MAC addr */
memcpy(ipx->ipx_dest.node, skb->data, ETH_ALEN);
} else {
__nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_dest.net, ipx->ipx_dest.node);
__nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
}
}
return 0;
default:
return -1;
}
}
/* AARP */
else if (ea != NULL) {
/* Sanity check fields. */
if (ea->hw_len != ETH_ALEN || ea->pa_len != AARP_PA_ALEN) {
DEBUG_WARN("NAT25: Appletalk AARP Sanity check fail!\n");
return -1;
}
switch (method) {
case NAT25_CHECK:
return 0;
case NAT25_INSERT: {
/* change to AARP source mac address to wlan STA address */
memcpy(ea->hw_src, GET_MY_HWADDR(priv), ETH_ALEN);
RTW_INFO("NAT25: Insert AARP, Source=%d,%d Destination=%d,%d\n",
ea->pa_src_net,
ea->pa_src_node,
ea->pa_dst_net,
ea->pa_dst_node);
__nat25_generate_apple_network_addr(networkAddr, &ea->pa_src_net, &ea->pa_src_node);
__nat25_db_network_insert(priv, skb->data + ETH_ALEN, networkAddr);
__nat25_db_print(priv);
}
return 0;
case NAT25_LOOKUP: {
RTW_INFO("NAT25: Lookup AARP, Source=%d,%d Destination=%d,%d\n",
ea->pa_src_net,
ea->pa_src_node,
ea->pa_dst_net,
ea->pa_dst_node);
__nat25_generate_apple_network_addr(networkAddr, &ea->pa_dst_net, &ea->pa_dst_node);
__nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
/* change to AARP destination mac address to Lookup result */
memcpy(ea->hw_dst, skb->data, ETH_ALEN);
}
return 0;
default:
return -1;
}
}
/* DDP */
else if (ddp != NULL) {
switch (method) {
case NAT25_CHECK:
return -1;
case NAT25_INSERT: {
RTW_INFO("NAT25: Insert DDP, Source=%d,%d Destination=%d,%d\n",
ddp->deh_snet,
ddp->deh_snode,
ddp->deh_dnet,
ddp->deh_dnode);
__nat25_generate_apple_network_addr(networkAddr, &ddp->deh_snet, &ddp->deh_snode);
__nat25_db_network_insert(priv, skb->data + ETH_ALEN, networkAddr);
__nat25_db_print(priv);
}
return 0;
case NAT25_LOOKUP: {
RTW_INFO("NAT25: Lookup DDP, Source=%d,%d Destination=%d,%d\n",
ddp->deh_snet,
ddp->deh_snode,
ddp->deh_dnet,
ddp->deh_dnode);
__nat25_generate_apple_network_addr(networkAddr, &ddp->deh_dnet, &ddp->deh_dnode);
__nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
}
return 0;
default:
return -1;
}
}
return -1;
}
/*---------------------------------------------------*/
/* Handle PPPoE frame */
/*---------------------------------------------------*/

View File

@ -83,7 +83,7 @@ void rtw_btcoex_ScanNotify(PADAPTER padapter, u8 type)
if (_FALSE == type) {
#ifdef CONFIG_CONCURRENT_MODE
if (rtw_mi_buddy_check_fwstate(padapter, WIFI_SITE_MONITOR))
if (rtw_mi_buddy_check_fwstate(padapter, WIFI_UNDER_SURVEY))
return;
#endif
@ -178,6 +178,17 @@ void rtw_btcoex_IQKNotify(PADAPTER padapter, u8 state)
hal_btcoex_IQKNotify(padapter, state);
}
void rtw_btcoex_WLRFKNotify(PADAPTER padapter, u8 path, u8 type, u8 state)
{
PHAL_DATA_TYPE pHalData;
pHalData = GET_HAL_DATA(padapter);
if (_FALSE == pHalData->EEPROMBluetoothCoexist)
return;
hal_btcoex_WLRFKNotify(padapter, path, type, state);
}
void rtw_btcoex_BtInfoNotify(PADAPTER padapter, u8 length, u8 *tmpBuf)
{
PHAL_DATA_TYPE pHalData;
@ -315,6 +326,11 @@ void rtw_btcoex_SetManualControl(PADAPTER padapter, u8 manual)
hal_btcoex_SetManualControl(padapter, _FALSE);
}
void rtw_btcoex_set_policy_control(PADAPTER padapter, u8 btc_policy)
{
hal_btcoex_set_policy_control(padapter, btc_policy);
}
u8 rtw_btcoex_1Ant(PADAPTER padapter)
{
return hal_btcoex_1Ant(padapter);
@ -577,7 +593,7 @@ u8 rtw_btcoex_btinfo_cmd(_adapter *adapter, u8 *buf, u16 len)
_rtw_memcpy(btinfo, buf, len);
init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
res = rtw_enqueue_cmd(pcmdpriv, ph2c);
@ -1468,9 +1484,7 @@ u8 rtw_btcoex_sendmsgbysocket(_adapter *padapter, u8 *msg, u8 msg_size, bool for
{
u8 error;
struct msghdr udpmsg;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
mm_segment_t oldfs;
#endif
struct iovec iov;
struct bt_coex_info *pcoex_info = &padapter->coex_info;
@ -1500,19 +1514,15 @@ u8 rtw_btcoex_sendmsgbysocket(_adapter *padapter, u8 *msg, u8 msg_size, bool for
udpmsg.msg_control = NULL;
udpmsg.msg_controllen = 0;
udpmsg.msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
oldfs = get_fs();
set_fs(KERNEL_DS);
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
error = sock_sendmsg(pcoex_info->udpsock, &udpmsg);
#else
error = sock_sendmsg(pcoex_info->udpsock, &udpmsg, msg_size);
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0))
set_fs(oldfs);
#endif
if (error < 0) {
RTW_INFO("Error when sendimg msg, error:%d\n", error);
return _FAIL;

File diff suppressed because it is too large Load Diff

View File

@ -20,15 +20,28 @@
u8 rtw_chplan_get_default_regd(u8 id);
bool rtw_chplan_is_empty(u8 id);
bool rtw_is_channel_plan_valid(u8 id);
bool rtw_regsty_is_excl_chs(struct registry_priv *regsty, u8 ch);
enum regd_src_t {
REGD_SRC_RTK_PRIV = 0, /* Regulatory settings from Realtek framework (Realtek defined or customized) */
REGD_SRC_OS = 1, /* Regulatory settings from OS */
REGD_SRC_NUM,
};
#define regd_src_is_valid(src) ((src) < REGD_SRC_NUM)
extern const char *_regd_src_str[];
#define regd_src_str(src) ((src) >= REGD_SRC_NUM ? _regd_src_str[REGD_SRC_NUM] : _regd_src_str[src])
struct _RT_CHANNEL_INFO;
u8 init_channel_set(_adapter *padapter, u8 ChannelPlan, struct _RT_CHANNEL_INFO *channel_set);
u8 init_channel_set(_adapter *adapter);
bool rtw_chset_is_dfs_range(struct _RT_CHANNEL_INFO *chset, u32 hi, u32 lo);
bool rtw_chset_is_dfs_ch(struct _RT_CHANNEL_INFO *chset, u8 ch);
bool rtw_chset_is_dfs_chbw(struct _RT_CHANNEL_INFO *chset, u8 ch, u8 bw, u8 offset);
void rtw_process_beacon_hint(_adapter *adapter, WLAN_BSSID_EX *bss);
u8 rtw_process_beacon_hint(_adapter *adapter, WLAN_BSSID_EX *bss);
#define IS_ALPHA2_NO_SPECIFIED(_alpha2) ((*((u16 *)(_alpha2))) == 0xFFFF)
#define IS_ALPHA2_WORLDWIDE(_alpha2) (strncmp(_alpha2, "00", 2) == 0)
#define RTW_MODULE_RTL8821AE_HMC_M2 BIT0 /* RTL8821AE(HMC + M.2) */
#define RTW_MODULE_RTL8821AU BIT1 /* RTL8821AU */
@ -43,15 +56,24 @@ void rtw_process_beacon_hint(_adapter *adapter, WLAN_BSSID_EX *bss);
#define RTW_MODULE_RTL8821CE BIT10 /* RTL8821CE */
#define RTW_MODULE_RTL8822CE BIT11 /* RTL8822CE */
enum rtw_dfs_regd {
RTW_DFS_REGD_NONE = 0,
RTW_DFS_REGD_FCC = 1,
RTW_DFS_REGD_MKK = 2,
RTW_DFS_REGD_ETSI = 3,
RTW_DFS_REGD_NUM,
RTW_DFS_REGD_AUTO = 0xFF, /* follow channel plan */
};
extern const char *_rtw_dfs_regd_str[];
#define rtw_dfs_regd_str(region) (((region) >= RTW_DFS_REGD_NUM) ? _rtw_dfs_regd_str[RTW_DFS_REGD_NONE] : _rtw_dfs_regd_str[(region)])
struct country_chplan {
char alpha2[2];
char alpha2[2]; /* "00" means worldwide */
u8 chplan;
#ifdef CONFIG_80211AC_VHT
u8 en_11ac;
#endif
#if RTW_DEF_MODULE_REGULATORY_CERT
u16 def_module_flags; /* RTW_MODULE_RTLXXX */
#endif
};
#ifdef CONFIG_80211AC_VHT
@ -60,18 +82,14 @@ struct country_chplan {
#define COUNTRY_CHPLAN_EN_11AC(_ent) 0
#endif
#if RTW_DEF_MODULE_REGULATORY_CERT
#define COUNTRY_CHPLAN_DEF_MODULE_FALGS(_ent) ((_ent)->def_module_flags)
#else
#define COUNTRY_CHPLAN_DEF_MODULE_FALGS(_ent) 0
#endif
const struct country_chplan *rtw_get_chplan_from_country(const char *country_code);
void dump_country_chplan(void *sel, const struct country_chplan *ent);
void dump_country_chplan_map(void *sel);
void dump_chplan_id_list(void *sel);
#ifdef CONFIG_RTW_DEBUG
void dump_chplan_test(void *sel);
#endif
void dump_chplan_ver(void *sel);
#endif /* __RTW_CHPLAN_H__ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

668
core/rtw_ft.c Normal file
View File

@ -0,0 +1,668 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#include <drv_types.h>
#include <hal_data.h>
#ifdef CONFIG_RTW_80211R
#ifndef RTW_FT_DBG
#define RTW_FT_DBG 0
#endif
#if RTW_FT_DBG
#define RTW_FT_INFO(fmt, arg...) \
RTW_INFO(fmt, arg)
#define RTW_FT_DUMP(str, data, len) \
RTW_INFO_DUMP(str, data, len)
#else
#define RTW_FT_INFO(fmt, arg...) do {} while (0)
#define RTW_FT_DUMP(str, data, len) do {} while (0)
#endif
void rtw_ft_info_init(struct ft_roam_info *pft)
{
_rtw_memset(pft, 0, sizeof(struct ft_roam_info));
pft->ft_flags = 0
| RTW_FT_EN
/* | RTW_FT_OTD_EN */
#ifdef CONFIG_RTW_BTM_ROAM
| RTW_FT_BTM_ROAM
#endif
;
pft->ft_updated_bcn = _FALSE;
RTW_FT_INFO("%s : ft_flags=0x%02x\n", __func__, pft->ft_flags);
}
ssize_t rtw_ft_proc_flags_set(struct file *file,
const char __user *buffer, size_t count, loff_t *pos, void *data)
{
struct net_device *dev = data;
_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
char tmp[32];
u8 flags;
if (count < 1)
return -EFAULT;
if (count > sizeof(tmp)) {
rtw_warn_on(1);
return -EFAULT;
}
if (buffer && !copy_from_user(tmp, buffer, count)) {
int num = sscanf(tmp, "%hhx", &flags);
if (num == 1)
adapter->mlmepriv.ft_roam.ft_flags = flags;
}
return count;
}
int rtw_ft_proc_flags_get(struct seq_file *m, void *v)
{
struct net_device *dev = m->private;
_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
RTW_PRINT_SEL(m, "0x%02x\n", adapter->mlmepriv.ft_roam.ft_flags);
return 0;
}
u8 rtw_ft_chk_roaming_candidate(
_adapter *padapter, struct wlan_network *competitor)
{
u8 *pmdie;
u32 mdie_len = 0;
struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);
if (!(pmdie = rtw_get_ie(&competitor->network.IEs[12],
_MDIE_, &mdie_len, competitor->network.IELength-12))) {
RTW_INFO("FT : MDIE not foud in competitor!\n");
return _FALSE;
}
if (!_rtw_memcmp(&pft_roam->mdid, (pmdie+2), 2)) {
RTW_INFO("FT : unmatched MDIE!\n");
return _FALSE;
}
/*The candidate don't support over-the-DS*/
if (rtw_ft_valid_otd_candidate(padapter, pmdie)) {
RTW_INFO("FT: ignore the candidate("
MAC_FMT ") for over-the-DS\n",
MAC_ARG(competitor->network.MacAddress));
/* rtw_ft_clr_flags(padapter, RTW_FT_PEER_OTD_EN); */
return _FALSE;
}
if (rtw_ft_chk_flags(padapter, RTW_FT_TEST_RSSI_ROAM)) {
if (!_rtw_memcmp(padapter->mlmepriv.cur_network.network.MacAddress,
competitor->network.MacAddress, ETH_ALEN) ) {
competitor->network.Rssi +=20;
RTW_FT_INFO("%s : update "MAC_FMT" RSSI to %d for RTW_FT_TEST_RSSI_ROAM\n",
__func__, MAC_ARG(competitor->network.MacAddress),
(int)competitor->network.Rssi);
rtw_ft_clr_flags(padapter, RTW_FT_TEST_RSSI_ROAM);
}
}
return _TRUE;
}
void rtw_ft_update_stainfo(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
{
struct sta_priv *pstapriv = &padapter->stapriv;
struct sta_info *psta = NULL;
psta = rtw_get_stainfo(pstapriv, pnetwork->MacAddress);
if (psta == NULL)
psta = rtw_alloc_stainfo(pstapriv, pnetwork->MacAddress);
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;
_rtw_memset((u8 *)&psta->dot118021x_UncstKey, 0, sizeof(union Keytype));
_rtw_memset((u8 *)&psta->dot11tkiprxmickey, 0, sizeof(union Keytype));
_rtw_memset((u8 *)&psta->dot11tkiptxmickey, 0, sizeof(union Keytype));
}
}
void rtw_ft_reassoc_event_callback(_adapter *padapter, u8 *pbuf)
{
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
struct stassoc_event *pstassoc = (struct stassoc_event *)pbuf;
struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&(pmlmeinfo->network);
struct cfg80211_ft_event_params ft_evt_parms;
_irqL irqL;
_rtw_memset(&ft_evt_parms, 0, sizeof(ft_evt_parms));
rtw_ft_update_stainfo(padapter, pnetwork);
ft_evt_parms.ies_len = pft_roam->ft_event.ies_len;
ft_evt_parms.ies = rtw_zmalloc(ft_evt_parms.ies_len);
if (ft_evt_parms.ies)
_rtw_memcpy((void *)ft_evt_parms.ies, pft_roam->ft_event.ies, ft_evt_parms.ies_len);
else
goto err_2;
ft_evt_parms.target_ap = rtw_zmalloc(ETH_ALEN);
if (ft_evt_parms.target_ap)
_rtw_memcpy((void *)ft_evt_parms.target_ap, pstassoc->macaddr, ETH_ALEN);
else
goto err_1;
ft_evt_parms.ric_ies = pft_roam->ft_event.ric_ies;
ft_evt_parms.ric_ies_len = pft_roam->ft_event.ric_ies_len;
/* It's a KERNEL issue between v4.11 ~ v4.16,
* <= v4.10, NLMSG_DEFAULT_SIZE is used for nlmsg_new().
* v4.11 ~ v4.16, only used "100 + >ric_ies_len" for nlmsg_new()
* even then DRIVER don't support RIC.
* >= v4.17, issue should correct as "100 + ies_len + ric_ies_len".
*/
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) && \
(LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)))
if (!ft_evt_parms.ric_ies_len)
ft_evt_parms.ric_ies_len = ft_evt_parms.ies_len;
else
ft_evt_parms.ric_ies_len += ft_evt_parms.ies_len;
#endif
rtw_ft_lock_set_status(padapter, RTW_FT_AUTHENTICATED_STA, &irqL);
rtw_cfg80211_ft_event(padapter, &ft_evt_parms);
RTW_INFO("%s: to "MAC_FMT"\n", __func__, MAC_ARG(ft_evt_parms.target_ap));
rtw_mfree((u8 *)pft_roam->ft_event.target_ap, ETH_ALEN);
err_1:
rtw_mfree((u8 *)ft_evt_parms.ies, ft_evt_parms.ies_len);
err_2:
return;
}
void rtw_ft_validate_akm_type(_adapter *padapter,
struct wlan_network *pnetwork)
{
struct security_priv *psecuritypriv = &(padapter->securitypriv);
struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);
u32 tmp_len;
u8 *ptmp;
/*IEEE802.11-2012 Std. Table 8-101-AKM suite selectors*/
if (rtw_ft_valid_akm(padapter, psecuritypriv->rsn_akm_suite_type)) {
ptmp = rtw_get_ie(&pnetwork->network.IEs[12],
_MDIE_, &tmp_len, (pnetwork->network.IELength-12));
if (ptmp) {
pft_roam->mdid = *(u16 *)(ptmp+2);
pft_roam->ft_cap = *(ptmp+4);
RTW_INFO("FT: target " MAC_FMT " mdid=(0x%2x), capacity=(0x%2x)\n",
MAC_ARG(pnetwork->network.MacAddress), pft_roam->mdid, pft_roam->ft_cap);
rtw_ft_set_flags(padapter, RTW_FT_PEER_EN);
RTW_FT_INFO("%s : peer support FTOTA(0x%02x)\n", __func__, pft_roam->ft_flags);
if (rtw_ft_otd_roam_en(padapter)) {
rtw_ft_set_flags(padapter, RTW_FT_PEER_OTD_EN);
RTW_FT_INFO("%s : peer support FTOTD(0x%02x)\n", __func__, pft_roam->ft_flags);
}
} else {
/* Don't use FT roaming if target AP cannot support FT */
rtw_ft_clr_flags(padapter, (RTW_FT_PEER_EN|RTW_FT_PEER_OTD_EN));
rtw_ft_reset_status(padapter);
}
} else {
/* It could be a non-FT connection */
rtw_ft_clr_flags(padapter, (RTW_FT_PEER_EN|RTW_FT_PEER_OTD_EN));
rtw_ft_reset_status(padapter);
}
RTW_FT_INFO("%s : ft_flags=0x%02x\n", __func__, pft_roam->ft_flags);
}
void rtw_ft_update_bcn(_adapter *padapter, union recv_frame *precv_frame)
{
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
u8 *pframe = precv_frame->u.hdr.rx_data;
uint len = precv_frame->u.hdr.len;
WLAN_BSSID_EX *pbss;
if (rtw_ft_chk_status(padapter,RTW_FT_ASSOCIATED_STA)
&& (pmlmepriv->ft_roam.ft_updated_bcn == _FALSE)) {
pbss = (WLAN_BSSID_EX*)rtw_malloc(sizeof(WLAN_BSSID_EX));
if (pbss) {
if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {
struct beacon_keys recv_beacon;
update_network(&(pmlmepriv->cur_network.network), pbss, padapter, _TRUE);
/* Move into rtw_get_bcn_keys */
/* rtw_get_bcn_info(&(pmlmepriv->cur_network)); */
/* update bcn keys */
if (rtw_get_bcn_keys(padapter, pframe, len, &recv_beacon) == _TRUE) {
RTW_FT_INFO("%s: beacon keys ready\n", __func__);
_rtw_memcpy(&pmlmepriv->cur_beacon_keys,
&recv_beacon, sizeof(recv_beacon));
if (is_hidden_ssid(recv_beacon.ssid, recv_beacon.ssid_len)) {
_rtw_memcpy(pmlmepriv->cur_beacon_keys.ssid, pmlmeinfo->network.Ssid.Ssid, IW_ESSID_MAX_SIZE);
pmlmepriv->cur_beacon_keys.ssid_len = pmlmeinfo->network.Ssid.SsidLength;
}
} else {
RTW_ERR("%s: get beacon keys failed\n", __func__);
_rtw_memset(&pmlmepriv->cur_beacon_keys, 0, sizeof(recv_beacon));
}
#ifdef CONFIG_BCN_CNT_CONFIRM_HDL
pmlmepriv->new_beacon_cnts = 0;
#endif
}
rtw_mfree((u8*)pbss, sizeof(WLAN_BSSID_EX));
}
/* check the vendor of the assoc AP */
pmlmeinfo->assoc_AP_vendor =
check_assoc_AP(pframe+sizeof(struct rtw_ieee80211_hdr_3addr),
(len - sizeof(struct rtw_ieee80211_hdr_3addr)));
/* update TSF Value */
update_TSF(pmlmeext, pframe, len);
pmlmeext->bcn_cnt = 0;
pmlmeext->last_bcn_cnt = 0;
pmlmepriv->ft_roam.ft_updated_bcn = _TRUE;
}
}
void rtw_ft_start_clnt_join(_adapter *padapter)
{
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);
if (rtw_ft_otd_roam(padapter)) {
pmlmeinfo->state = WIFI_FW_AUTH_SUCCESS | WIFI_FW_STATION_STATE;
pft_roam->ft_event.ies =
(pft_roam->ft_action + sizeof(struct rtw_ieee80211_hdr_3addr) + 16);
pft_roam->ft_event.ies_len =
(pft_roam->ft_action_len - sizeof(struct rtw_ieee80211_hdr_3addr));
/*Not support RIC*/
pft_roam->ft_event.ric_ies = NULL;
pft_roam->ft_event.ric_ies_len = 0;
rtw_ft_report_evt(padapter);
return;
}
pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
start_clnt_auth(padapter);
}
u8 rtw_ft_update_rsnie(
_adapter *padapter, u8 bwrite,
struct pkt_attrib *pattrib, u8 **pframe)
{
struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);
u8 *pie;
u32 len;
pie = rtw_get_ie(pft_roam->updated_ft_ies, EID_WPA2, &len,
pft_roam->updated_ft_ies_len);
if (!bwrite)
return (pie)?_SUCCESS:_FAIL;
if (pie) {
*pframe = rtw_set_ie(((u8 *)*pframe), EID_WPA2, len,
pie+2, &(pattrib->pktlen));
} else
return _FAIL;
return _SUCCESS;
}
static u8 rtw_ft_update_mdie(
_adapter *padapter, struct pkt_attrib *pattrib, u8 **pframe)
{
struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);
u8 *pie, mdie[3];
u32 len = 3;
if (rtw_ft_roam(padapter)) {
if ((pie = rtw_get_ie(pft_roam->updated_ft_ies, _MDIE_,
&len, pft_roam->updated_ft_ies_len))) {
pie = (pie + 2); /* ignore md-id & length */
} else
return _FAIL;
} else {
*((u16 *)&mdie[0]) = pft_roam->mdid;
mdie[2] = pft_roam->ft_cap;
pie = &mdie[0];
}
*pframe = rtw_set_ie(((u8 *)*pframe), _MDIE_, len , pie, &(pattrib->pktlen));
return _SUCCESS;
}
static u8 rtw_ft_update_ftie(
_adapter *padapter, struct pkt_attrib *pattrib, u8 **pframe)
{
struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);
u8 *pie;
u32 len;
if ((pie = rtw_get_ie(pft_roam->updated_ft_ies, _FTIE_, &len,
pft_roam->updated_ft_ies_len)) != NULL) {
*pframe = rtw_set_ie(*pframe, _FTIE_, len ,
(pie+2), &(pattrib->pktlen));
} else
return _FAIL;
return _SUCCESS;
}
void rtw_ft_build_auth_req_ies(_adapter *padapter,
struct pkt_attrib *pattrib, u8 **pframe)
{
u8 ftie_append = _TRUE;
if (!pattrib || !(*pframe))
return;
if (!rtw_ft_roam(padapter))
return;
ftie_append = rtw_ft_update_rsnie(padapter, _TRUE, pattrib, pframe);
rtw_ft_update_mdie(padapter, pattrib, pframe);
if (ftie_append)
rtw_ft_update_ftie(padapter, pattrib, pframe);
}
void rtw_ft_build_assoc_req_ies(_adapter *padapter,
u8 is_reassoc, struct pkt_attrib *pattrib, u8 **pframe)
{
if (!pattrib || !(*pframe))
return;
if (rtw_ft_chk_flags(padapter, RTW_FT_PEER_EN))
rtw_ft_update_mdie(padapter, pattrib, pframe);
if ((!is_reassoc) || (!rtw_ft_roam(padapter)))
return;
if (rtw_ft_update_rsnie(padapter, _FALSE, pattrib, pframe))
rtw_ft_update_ftie(padapter, pattrib, pframe);
}
u8 rtw_ft_update_auth_rsp_ies(_adapter *padapter, u8 *pframe, u32 len)
{
u8 ret = _SUCCESS;
u8 target_ap_addr[ETH_ALEN] = {0};
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);
if (!rtw_ft_roam(padapter))
return _FAIL;
/*rtw_ft_report_reassoc_evt already,
* and waiting for cfg80211_rtw_update_ft_ies */
if (rtw_ft_authed_sta(padapter))
return ret;
if (!pframe || !len)
return _FAIL;
rtw_buf_update(&pmlmepriv->auth_rsp,
&pmlmepriv->auth_rsp_len, pframe, len);
pft_roam->ft_event.ies =
(pmlmepriv->auth_rsp + sizeof(struct rtw_ieee80211_hdr_3addr) + 6);
pft_roam->ft_event.ies_len =
(pmlmepriv->auth_rsp_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 6);
/*Not support RIC*/
pft_roam->ft_event.ric_ies = NULL;
pft_roam->ft_event.ric_ies_len = 0;
_rtw_memcpy(target_ap_addr, pmlmepriv->assoc_bssid, ETH_ALEN);
rtw_ft_report_reassoc_evt(padapter, target_ap_addr);
return ret;
}
static void rtw_ft_start_clnt_action(_adapter *padapter, u8 *pTargetAddr)
{
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
rtw_ft_set_status(padapter, RTW_FT_REQUESTING_STA);
rtw_ft_issue_action_req(padapter, pTargetAddr);
_set_timer(&pmlmeext->ft_link_timer, REASSOC_TO);
}
void rtw_ft_start_roam(_adapter *padapter, u8 *pTargetAddr)
{
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
if (rtw_ft_otd_roam(padapter)) {
RTW_FT_INFO("%s : try OTD roaming\n", __func__);
rtw_ft_start_clnt_action(padapter, pTargetAddr);
} else {
/*wait a little time to retrieve packets buffered in the current ap while scan*/
RTW_FT_INFO("%s : start roaming timer\n", __func__);
_set_timer(&pmlmeext->ft_roam_timer, 30);
}
}
void rtw_ft_issue_action_req(_adapter *padapter, u8 *pTargetAddr)
{
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
struct xmit_frame *pmgntframe;
struct rtw_ieee80211_hdr *pwlanhdr;
struct pkt_attrib *pattrib;
u8 *pframe;
u8 category = RTW_WLAN_CATEGORY_FT;
u8 action = RTW_WLAN_ACTION_FT_REQ;
pmgntframe = alloc_mgtxmitframe(pxmitpriv);
if (pmgntframe == NULL)
return;
pattrib = &pmgntframe->attrib;
update_mgntframe_attrib(padapter, pattrib);
_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
pwlanhdr->frame_ctl = 0;
_rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
pmlmeext->mgnt_seq++;
set_frame_sub_type(pframe, WIFI_ACTION);
pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
_rtw_memcpy(pframe, adapter_mac_addr(padapter), ETH_ALEN);
pframe += ETH_ALEN;
pattrib->pktlen += ETH_ALEN;
_rtw_memcpy(pframe, pTargetAddr, ETH_ALEN);
pframe += ETH_ALEN;
pattrib->pktlen += ETH_ALEN;
rtw_ft_update_mdie(padapter, pattrib, &pframe);
if (rtw_ft_update_rsnie(padapter, _TRUE, pattrib, &pframe))
rtw_ft_update_ftie(padapter, pattrib, &pframe);
RTW_INFO("FT : issue RTW_WLAN_ACTION_FT_REQ\n");
pattrib->last_txcmdsz = pattrib->pktlen;
dump_mgntframe(padapter, pmgntframe);
}
void rtw_ft_report_evt(_adapter *padapter)
{
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&(pmlmeinfo->network);
struct cfg80211_ft_event_params ft_evt_parms;
_irqL irqL;
_rtw_memset(&ft_evt_parms, 0, sizeof(ft_evt_parms));
rtw_ft_update_stainfo(padapter, pnetwork);
if (!pnetwork)
goto err_2;
ft_evt_parms.ies_len = pft_roam->ft_event.ies_len;
ft_evt_parms.ies = rtw_zmalloc(ft_evt_parms.ies_len);
if (ft_evt_parms.ies)
_rtw_memcpy((void *)ft_evt_parms.ies, pft_roam->ft_event.ies, ft_evt_parms.ies_len);
else
goto err_2;
ft_evt_parms.target_ap = rtw_zmalloc(ETH_ALEN);
if (ft_evt_parms.target_ap)
_rtw_memcpy((void *)ft_evt_parms.target_ap, pnetwork->MacAddress, ETH_ALEN);
else
goto err_1;
ft_evt_parms.ric_ies = pft_roam->ft_event.ric_ies;
ft_evt_parms.ric_ies_len = pft_roam->ft_event.ric_ies_len;
/* It's a KERNEL issue between v4.11 ~ v4.16,
* <= v4.10, NLMSG_DEFAULT_SIZE is used for nlmsg_new().
* v4.11 ~ v4.16, only used "100 + >ric_ies_len" for nlmsg_new()
* even then DRIVER don't support RIC.
* >= v4.17, issue should correct as "100 + ies_len + ric_ies_len".
*/
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) && \
(LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)))
ft_evt_parms.ric_ies_len = (ft_evt_parms.ies_len <= 100 )?
(0):(ft_evt_parms.ies_len - 100);
#endif
rtw_ft_lock_set_status(padapter, RTW_FT_AUTHENTICATED_STA, &irqL);
rtw_cfg80211_ft_event(padapter, &ft_evt_parms);
RTW_INFO("FT: rtw_ft_report_evt\n");
rtw_mfree((u8 *)pft_roam->ft_event.target_ap, ETH_ALEN);
err_1:
rtw_mfree((u8 *)ft_evt_parms.ies, ft_evt_parms.ies_len);
err_2:
return;
}
void rtw_ft_report_reassoc_evt(_adapter *padapter, u8 *pMacAddr)
{
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
struct cmd_obj *pcmd_obj = NULL;
struct stassoc_event *passoc_sta_evt = NULL;
struct rtw_evt_header *evt_hdr = NULL;
u8 *pevtcmd = NULL;
u32 cmdsz = 0;
pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
if (pcmd_obj == NULL)
return;
cmdsz = (sizeof(struct stassoc_event) + sizeof(struct rtw_evt_header));
pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
if (pevtcmd == NULL) {
rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
return;
}
_rtw_init_listhead(&pcmd_obj->list);
pcmd_obj->cmdcode = CMD_SET_MLME_EVT;
pcmd_obj->cmdsz = cmdsz;
pcmd_obj->parmbuf = pevtcmd;
pcmd_obj->rsp = NULL;
pcmd_obj->rspsz = 0;
evt_hdr = (struct rtw_evt_header *)(pevtcmd);
evt_hdr->len = sizeof(struct stassoc_event);
evt_hdr->id = EVT_FT_REASSOC;
evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
passoc_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct rtw_evt_header));
_rtw_memcpy((unsigned char *)(&(passoc_sta_evt->macaddr)), pMacAddr, ETH_ALEN);
rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
}
void rtw_ft_link_timer_hdl(void *ctx)
{
_adapter *padapter = (_adapter *)ctx;
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);
if (rtw_ft_chk_status(padapter, RTW_FT_REQUESTING_STA)) {
if (pft_roam->ft_req_retry_cnt < RTW_FT_ACTION_REQ_LMT) {
pft_roam->ft_req_retry_cnt++;
rtw_ft_issue_action_req(padapter, (u8 *)pmlmepriv->roam_network->network.MacAddress);
_set_timer(&pmlmeext->ft_link_timer, REASSOC_TO);
} else {
pft_roam->ft_req_retry_cnt = 0;
if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
rtw_ft_set_status(padapter, RTW_FT_ASSOCIATED_STA);
else
rtw_ft_reset_status(padapter);
}
}
}
void rtw_ft_roam_timer_hdl(void *ctx)
{
_adapter *padapter = (_adapter *)ctx;
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
RTW_FT_INFO("%s : try roaming\n", __func__);
receive_disconnect(padapter, pmlmepriv->cur_network.network.MacAddress
, WLAN_REASON_ACTIVE_ROAM, _FALSE);
}
void rtw_ft_roam_status_reset(_adapter *padapter)
{
struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);
if ((rtw_to_roam(padapter) > 0) &&
(!rtw_ft_chk_status(padapter, RTW_FT_REQUESTED_STA))) {
rtw_ft_reset_status(padapter);
}
padapter->mlmepriv.ft_roam.ft_updated_bcn = _FALSE;
}
#endif /* CONFIG_RTW_80211R */

View File

@ -38,6 +38,13 @@ 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_AES_128_CMAC[] = { 0x00, 0x0f, 0xac, 6 };
u8 RSN_CIPHER_SUITE_GCMP[] = { 0x00, 0x0f, 0xac, 8 };
u8 RSN_CIPHER_SUITE_GCMP_256[] = { 0x00, 0x0f, 0xac, 9 };
u8 RSN_CIPHER_SUITE_CCMP_256[] = { 0x00, 0x0f, 0xac, 10 };
u8 RSN_CIPHER_SUITE_BIP_GMAC_128[] = { 0x00, 0x0f, 0xac, 11 };
u8 RSN_CIPHER_SUITE_BIP_GMAC_256[] = { 0x00, 0x0f, 0xac, 12 };
u8 RSN_CIPHER_SUITE_BIP_CMAC_256[] = { 0x00, 0x0f, 0xac, 13 };
u8 RSN_CIPHER_SUITE_WEP104[] = { 0x00, 0x0f, 0xac, 5 };
u8 WLAN_AKM_8021X[] = {0x00, 0x0f, 0xac, 1};
@ -77,6 +84,20 @@ u8 WIFI_OFDMRATES[] = {
IEEE80211_OFDM_RATE_54MB
};
const char *MGN_RATE_STR(enum MGN_RATE rate)
{
u8 hw_rate;
if (rate == MGN_MCS32)
return "MCS32";
hw_rate = MRateToHwRate(rate);
if (hw_rate == DESC_RATE1M && rate != MGN_1M)
hw_rate = DESC_RATE_NUM; /* invalid case */
return HDATA_RATE(hw_rate);
}
u8 mgn_rates_cck[4] = {MGN_1M, MGN_2M, MGN_5_5M, MGN_11M};
u8 mgn_rates_ofdm[8] = {MGN_6M, MGN_9M, MGN_12M, MGN_18M, MGN_24M, MGN_36M, MGN_48M, MGN_54M};
u8 mgn_rates_mcs0_7[8] = {MGN_MCS0, MGN_MCS1, MGN_MCS2, MGN_MCS3, MGN_MCS4, MGN_MCS5, MGN_MCS6, MGN_MCS7};
@ -516,17 +537,24 @@ u8 rtw_update_rate_bymode(WLAN_BSSID_EX *pbss_network, u32 mode)
pbss_network->IELength -= ie_len;
}
network_type = WIRELESS_11B;
} else if ((mode & WIRELESS_11B) == 0) {
/* Remove CCK in support_rate IE */
rtw_filter_suppport_rateie(pbss_network, OFDM);
if (pbss_network->Configuration.DSConfig > 14)
} else {
if (pbss_network->Configuration.DSConfig > 14) {
/* Remove CCK in support_rate IE */
rtw_filter_suppport_rateie(pbss_network, OFDM);
network_type = WIRELESS_11A;
else
network_type = WIRELESS_11G;
} else
network_type = WIRELESS_11BG; /* do nothing */
} else {
if ((mode & WIRELESS_11B) == 0) {
/* Remove CCK in support_rate IE */
rtw_filter_suppport_rateie(pbss_network, OFDM);
network_type = WIRELESS_11G;
} else {
network_type = WIRELESS_11BG;
}
}
}
rtw_set_supported_rate(pbss_network->SupportedRates, network_type);
return network_type;
}
@ -706,7 +734,7 @@ int rtw_get_wpa_cipher_suite(u8 *s)
return 0;
}
int rtw_get_wpa2_cipher_suite(u8 *s)
int rtw_get_rsn_cipher_suite(u8 *s)
{
if (_rtw_memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN) == _TRUE)
return WPA_CIPHER_NONE;
@ -716,9 +744,22 @@ int rtw_get_wpa2_cipher_suite(u8 *s)
return WPA_CIPHER_TKIP;
if (_rtw_memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN) == _TRUE)
return WPA_CIPHER_CCMP;
if (_rtw_memcmp(s, RSN_CIPHER_SUITE_GCMP, RSN_SELECTOR_LEN) == _TRUE)
return WPA_CIPHER_GCMP;
if (_rtw_memcmp(s, RSN_CIPHER_SUITE_GCMP_256, RSN_SELECTOR_LEN) == _TRUE)
return WPA_CIPHER_GCMP_256;
if (_rtw_memcmp(s, RSN_CIPHER_SUITE_CCMP_256, RSN_SELECTOR_LEN) == _TRUE)
return WPA_CIPHER_CCMP_256;
if (_rtw_memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN) == _TRUE)
return WPA_CIPHER_WEP104;
if (_rtw_memcmp(s, RSN_CIPHER_SUITE_AES_128_CMAC, RSN_SELECTOR_LEN) == _TRUE)
return WPA_CIPHER_BIP_CMAC_128;
if (_rtw_memcmp(s, RSN_CIPHER_SUITE_BIP_GMAC_128, RSN_SELECTOR_LEN) == _TRUE)
return WPA_CIPHER_BIP_GMAC_128;
if (_rtw_memcmp(s, RSN_CIPHER_SUITE_BIP_GMAC_256, RSN_SELECTOR_LEN) == _TRUE)
return WPA_CIPHER_BIP_GMAC_256;
if (_rtw_memcmp(s, RSN_CIPHER_SUITE_BIP_CMAC_256, RSN_SELECTOR_LEN) == _TRUE)
return WPA_CIPHER_BIP_CMAC_256;
return 0;
}
@ -834,6 +875,7 @@ int rtw_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher,
int rtw_rsne_info_parse(const u8 *ie, uint ie_len, struct rsne_info *info)
{
const u8 *pos = ie;
u16 ver;
u16 cnt;
_rtw_memset(info, 0, sizeof(struct rsne_info));
@ -843,7 +885,13 @@ int rtw_rsne_info_parse(const u8 *ie, uint ie_len, struct rsne_info *info)
if (*ie != WLAN_EID_RSN || *(ie + 1) != ie_len - 2)
goto err;
pos += 2 + 2;
pos += 2;
/* Version */
ver = RTW_GET_LE16(pos);
if(1 != ver)
goto err;
pos += 2;
/* Group CS */
if (ie + ie_len < pos + 4) {
@ -905,11 +953,8 @@ int rtw_rsne_info_parse(const u8 *ie, uint ie_len, struct rsne_info *info)
}
cnt = RTW_GET_LE16(pos);
pos += 2;
if (ie + ie_len < pos + 16 * cnt) {
if (ie + ie_len != pos)
goto err;
goto exit;
}
if (ie + ie_len < pos + 16 * cnt)
goto err;
info->pmkid_cnt = cnt;
info->pmkid_list = (u8 *)pos;
pos += 16 * cnt;
@ -931,7 +976,7 @@ err:
}
int rtw_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher,
int *pairwise_cipher, u32 *akm, u8 *mfp_opt)
int *pairwise_cipher, int *gmcs, u32 *akm, u8 *mfp_opt, u8 *spp_opt)
{
struct rsne_info info;
int i, ret = _SUCCESS;
@ -942,21 +987,32 @@ int rtw_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher,
if (group_cipher) {
if (info.gcs)
*group_cipher = rtw_get_wpa2_cipher_suite(info.gcs);
*group_cipher = rtw_get_rsn_cipher_suite(info.gcs);
else
*group_cipher = 0;
}
if (pairwise_cipher) {
*pairwise_cipher = 0;
for (i = 0; i < info.pcs_cnt; i++)
*pairwise_cipher |= rtw_get_wpa2_cipher_suite(info.pcs_list + 4 * i);
if (info.pcs_list) {
for (i = 0; i < info.pcs_cnt; i++)
*pairwise_cipher |= rtw_get_rsn_cipher_suite(info.pcs_list + 4 * i);
}
}
if (gmcs) {
if (info.gmcs)
*gmcs = rtw_get_rsn_cipher_suite(info.gmcs);
else
*gmcs = WPA_CIPHER_BIP_CMAC_128; /* default value when absent */
}
if (akm) {
*akm = 0;
for (i = 0; i < info.akm_cnt; i++)
*akm |= rtw_get_akm_suite_bitmap(info.akm_list + 4 * i);
if (info.akm_list) {
for (i = 0; i < info.akm_cnt; i++)
*akm |= rtw_get_akm_suite_bitmap(info.akm_list + 4 * i);
}
}
if (mfp_opt) {
@ -965,6 +1021,12 @@ int rtw_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher,
*mfp_opt = GET_RSN_CAP_MFP_OPTION(info.cap);
}
if (spp_opt) {
*spp_opt = 0;
if (info.cap)
*spp_opt = GET_RSN_CAP_SPP_OPT(info.cap);
}
exit:
return ret;
}
@ -1378,7 +1440,14 @@ static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen,
return -1;
}
break;
#ifdef CONFIG_RTW_TOKEN_BASED_XMIT
case OUI_REALTEK:
if (elen == 8) { // TBTX capable IE length is 8
elems->tbtx_cap = pos;
elems->tbtx_cap_len = elen;
}
break;
#endif
default:
RTW_DBG("unknown vendor specific information "
"element ignored (vendor OUI %02x:%02x:%02x "
@ -1735,6 +1804,7 @@ err_chk:
RTW_INFO("%s mac addr:"MAC_FMT"\n", __func__, MAC_ARG(out));
}
#ifdef CONFIG_RTW_DEBUG
#ifdef CONFIG_80211N_HT
void dump_ht_cap_ie_content(void *sel, const u8 *buf, u32 buf_len)
{
@ -1797,36 +1867,6 @@ void dump_ht_op_ie(void *sel, const u8 *ie, u32 ie_len)
}
#endif /* CONFIG_80211N_HT */
void dump_ies(void *sel, const u8 *buf, u32 buf_len)
{
const u8 *pos = buf;
u8 id, len;
while (pos - buf + 1 < buf_len) {
id = *pos;
len = *(pos + 1);
RTW_PRINT_SEL(sel, "%s ID:%u, LEN:%u\n", __FUNCTION__, id, len);
#ifdef CONFIG_80211N_HT
dump_ht_cap_ie(sel, pos, len + 2);
dump_ht_op_ie(sel, pos, len + 2);
#endif
#ifdef CONFIG_80211AC_VHT
dump_vht_cap_ie(sel, pos, len + 2);
dump_vht_op_ie(sel, pos, len + 2);
#endif
dump_wps_ie(sel, pos, len + 2);
#ifdef CONFIG_P2P
dump_p2p_ie(sel, pos, len + 2);
#ifdef CONFIG_WFD
dump_wfd_ie(sel, pos, len + 2);
#endif
#endif
pos += (2 + len);
}
}
void dump_wps_ie(void *sel, const u8 *ie, u32 ie_len)
{
const u8 *pos = ie;
@ -1851,6 +1891,41 @@ void dump_wps_ie(void *sel, const u8 *ie, u32 ie_len)
pos += (4 + len);
}
}
#endif /* CONFIG_RTW_DEBUG */
void dump_ies(void *sel, const u8 *buf, u32 buf_len)
{
#ifdef CONFIG_RTW_DEBUG
const u8 *pos = buf;
u8 id, len;
while (pos - buf + 1 < buf_len) {
id = *pos;
len = *(pos + 1);
RTW_PRINT_SEL(sel, "%s ID:%u, LEN:%u\n", __FUNCTION__, id, len);
#ifdef CONFIG_80211N_HT
dump_ht_cap_ie(sel, pos, len + 2);
dump_ht_op_ie(sel, pos, len + 2);
#endif
#ifdef CONFIG_80211AC_VHT
dump_vht_cap_ie(sel, pos, len + 2);
dump_vht_op_ie(sel, pos, len + 2);
#endif
dump_wps_ie(sel, pos, len + 2);
#ifdef CONFIG_P2P
dump_p2p_ie(sel, pos, len + 2);
#ifdef CONFIG_WFD
dump_wfd_ie(sel, pos, len + 2);
#endif
#endif
#ifdef CONFIG_RTW_MULTI_AP
dump_multi_ap_ie(sel, pos, len + 2);
#endif
pos += (2 + len);
}
#endif /* CONFIG_RTW_DEBUG */
}
/**
* rtw_ies_get_chbw - get operation ch, bw, offset from IEs of BSS.
@ -2032,6 +2107,7 @@ void rtw_sync_chbw(u8 *req_ch, u8 *req_bw, u8 *req_offset
}
}
#ifdef CONFIG_P2P
/**
* rtw_get_p2p_merged_len - Get merged ie length from muitiple p2p ies.
* @in_ie: Pointer of the first p2p ie
@ -2441,31 +2517,7 @@ void rtw_bss_ex_del_p2p_attr(WLAN_BSSID_EX *bss_ex, u8 attr_id)
break;
}
}
void dump_wfd_ie(void *sel, const u8 *ie, u32 ie_len)
{
const u8 *pos = ie;
u8 id;
u16 len;
const u8 *wfd_ie;
uint wfd_ielen;
wfd_ie = rtw_get_wfd_ie(ie, ie_len, NULL, &wfd_ielen);
if (wfd_ie != ie || wfd_ielen == 0)
return;
pos += 6;
while (pos - ie + 3 <= ie_len) {
id = *pos;
len = RTW_GET_BE16(pos + 1);
RTW_PRINT_SEL(sel, "%s ID:%u, LEN:%u%s\n", __func__, id, len
, ((pos - ie + 3 + len) <= ie_len) ? "" : "(exceed ie_len)");
pos += (3 + len);
}
}
#endif /* CONFIG_P2P */
/**
* rtw_get_wfd_ie - Search WFD IE from a series of IEs
@ -2521,6 +2573,84 @@ u8 *rtw_get_wfd_ie(const u8 *in_ie, int in_len, u8 *wfd_ie, uint *wfd_ielen)
return (u8 *)wfd_ie_ptr;
}
uint rtw_del_wfd_ie(u8 *ies, uint ies_len_ori, const char *msg)
{
#define DBG_DEL_WFD_IE 0
u8 *target_ie;
u32 target_ie_len;
uint ies_len = ies_len_ori;
int index = 0;
while (1) {
target_ie = rtw_get_wfd_ie(ies, ies_len, NULL, &target_ie_len);
if (target_ie && target_ie_len) {
u8 *next_ie = target_ie + target_ie_len;
uint remain_len = ies_len - (next_ie - ies);
if (DBG_DEL_WFD_IE && msg) {
RTW_INFO("%s %d before\n", __func__, index);
dump_ies(RTW_DBGDUMP, ies, ies_len);
RTW_INFO("ies:%p, ies_len:%u\n", ies, ies_len);
RTW_INFO("target_ie:%p, target_ie_len:%u\n", target_ie, target_ie_len);
RTW_INFO("next_ie:%p, remain_len:%u\n", next_ie, remain_len);
}
_rtw_memmove(target_ie, next_ie, remain_len);
_rtw_memset(target_ie + remain_len, 0, target_ie_len);
ies_len -= target_ie_len;
if (DBG_DEL_WFD_IE && msg) {
RTW_INFO("%s %d after\n", __func__, index);
dump_ies(RTW_DBGDUMP, ies, ies_len);
}
index++;
} else
break;
}
return ies_len;
}
void rtw_bss_ex_del_wfd_ie(WLAN_BSSID_EX *bss_ex)
{
#define DBG_BSS_EX_DEL_WFD_IE 0
u8 *ies = BSS_EX_TLV_IES(bss_ex);
uint ies_len_ori = BSS_EX_TLV_IES_LEN(bss_ex);
uint ies_len;
ies_len = rtw_del_wfd_ie(ies, ies_len_ori, DBG_BSS_EX_DEL_WFD_IE ? __func__ : NULL);
bss_ex->IELength -= ies_len_ori - ies_len;
}
#ifdef CONFIG_WFD
void dump_wfd_ie(void *sel, const u8 *ie, u32 ie_len)
{
const u8 *pos = ie;
u8 id;
u16 len;
const u8 *wfd_ie;
uint wfd_ielen;
wfd_ie = rtw_get_wfd_ie(ie, ie_len, NULL, &wfd_ielen);
if (wfd_ie != ie || wfd_ielen == 0)
return;
pos += 6;
while (pos - ie + 3 <= ie_len) {
id = *pos;
len = RTW_GET_BE16(pos + 1);
RTW_PRINT_SEL(sel, "%s ID:%u, LEN:%u%s\n", __func__, id, len
, ((pos - ie + 3 + len) <= ie_len) ? "" : "(exceed ie_len)");
pos += (3 + len);
}
}
/**
* rtw_get_wfd_attr - Search a specific WFD attribute from a given WFD IE
* @wfd_ie: Address of WFD IE to search
@ -2611,47 +2741,6 @@ u8 *rtw_get_wfd_attr_content(u8 *wfd_ie, uint wfd_ielen, u8 target_attr_id, u8 *
return NULL;
}
uint rtw_del_wfd_ie(u8 *ies, uint ies_len_ori, const char *msg)
{
#define DBG_DEL_WFD_IE 0
u8 *target_ie;
u32 target_ie_len;
uint ies_len = ies_len_ori;
int index = 0;
while (1) {
target_ie = rtw_get_wfd_ie(ies, ies_len, NULL, &target_ie_len);
if (target_ie && target_ie_len) {
u8 *next_ie = target_ie + target_ie_len;
uint remain_len = ies_len - (next_ie - ies);
if (DBG_DEL_WFD_IE && msg) {
RTW_INFO("%s %d before\n", __func__, index);
dump_ies(RTW_DBGDUMP, ies, ies_len);
RTW_INFO("ies:%p, ies_len:%u\n", ies, ies_len);
RTW_INFO("target_ie:%p, target_ie_len:%u\n", target_ie, target_ie_len);
RTW_INFO("next_ie:%p, remain_len:%u\n", next_ie, remain_len);
}
_rtw_memmove(target_ie, next_ie, remain_len);
_rtw_memset(target_ie + remain_len, 0, target_ie_len);
ies_len -= target_ie_len;
if (DBG_DEL_WFD_IE && msg) {
RTW_INFO("%s %d after\n", __func__, index);
dump_ies(RTW_DBGDUMP, ies, ies_len);
}
index++;
} else
break;
}
return ies_len;
}
uint rtw_del_wfd_attr(u8 *ie, uint ielen_ori, u8 attr_id)
{
#define DBG_DEL_WFD_ATTR 0
@ -2699,17 +2788,6 @@ inline u8 *rtw_bss_ex_get_wfd_ie(WLAN_BSSID_EX *bss_ex, u8 *wfd_ie, uint *wfd_ie
return rtw_get_wfd_ie(BSS_EX_TLV_IES(bss_ex), BSS_EX_TLV_IES_LEN(bss_ex), wfd_ie, wfd_ielen);
}
void rtw_bss_ex_del_wfd_ie(WLAN_BSSID_EX *bss_ex)
{
#define DBG_BSS_EX_DEL_WFD_IE 0
u8 *ies = BSS_EX_TLV_IES(bss_ex);
uint ies_len_ori = BSS_EX_TLV_IES_LEN(bss_ex);
uint ies_len;
ies_len = rtw_del_wfd_ie(ies, ies_len_ori, DBG_BSS_EX_DEL_WFD_IE ? __func__ : NULL);
bss_ex->IELength -= ies_len_ori - ies_len;
}
void rtw_bss_ex_del_wfd_attr(WLAN_BSSID_EX *bss_ex, u8 attr_id)
{
#define DBG_BSS_EX_DEL_WFD_ATTR 0
@ -2767,6 +2845,79 @@ void rtw_bss_ex_del_wfd_attr(WLAN_BSSID_EX *bss_ex, u8 attr_id)
break;
}
}
#endif /* CONFIG_WFD */
#ifdef CONFIG_RTW_MULTI_AP
void dump_multi_ap_ie(void *sel, const u8 *ie, u32 ie_len)
{
const u8 *pos = ie;
u8 id;
u8 len;
const u8 *multi_ap_ie;
uint multi_ap_ielen;
multi_ap_ie = rtw_get_ie_ex(ie, ie_len, WLAN_EID_VENDOR_SPECIFIC, MULTI_AP_OUI, 4, NULL, &multi_ap_ielen);
if (multi_ap_ie != ie || multi_ap_ielen == 0)
return;
pos += 6;
while (pos - ie + 2 <= ie_len) {
id = *pos;
len = *(pos + 1);
RTW_PRINT_SEL(sel, "%s ID:%u, LEN:%u%s\n", __func__, id, len
, ((pos - ie + 2 + len) <= ie_len) ? "" : "(exceed ie_len)");
RTW_DUMP_SEL(sel, pos + 2, len);
pos += (2 + len);
}
}
/**
* rtw_get_multi_ap_ext - Search Multi-AP IE from a series of IEs and return extension subelement value
* @ies: Address of IEs to search
* @ies_len: Length limit from in_ie
*
* Returns: The address of the target IE found, or NULL
*/
u8 rtw_get_multi_ap_ie_ext(const u8 *ies, int ies_len)
{
u8 *ie;
uint ielen;
u8 val = 0;
ie = rtw_get_ie_ex(ies, ies_len, WLAN_EID_VENDOR_SPECIFIC, MULTI_AP_OUI, 4, NULL, &ielen);
if (ielen < 9)
goto exit;
if (ie[6] != MULTI_AP_SUB_ELEM_TYPE)
goto exit;
val = ie[8];
exit:
return val;
}
u8 *rtw_set_multi_ap_ie_ext(u8 *pbuf, uint *frlen, u8 val)
{
u8 cont_len = 7;
*pbuf++ = WLAN_EID_VENDOR_SPECIFIC;
*pbuf++ = cont_len;
_rtw_memcpy(pbuf, MULTI_AP_OUI, 4);
pbuf += 4;
*pbuf++ = MULTI_AP_SUB_ELEM_TYPE;
*pbuf++ = 1; /* len */
*pbuf++ = val;
if (frlen)
*frlen = *frlen + (cont_len + 2);
return pbuf;
}
#endif /* CONFIG_RTW_MULTI_AP */
/* Baron adds to avoid FreeBSD warning */
int ieee80211_is_empty_essid(const char *essid, int essid_len)
@ -2922,6 +3073,23 @@ u16 rtw_ht_mcs_rate(u8 bw_40MHz, u8 short_GI, unsigned char *MCS_rate)
return max_rate;
}
u8 rtw_ht_cap_get_rx_nss(u8 *ht_cap)
{
u8 *ht_mcs_set = HT_CAP_ELE_SUP_MCS_SET(ht_cap);
return rtw_ht_mcsset_to_nss(ht_mcs_set);
}
u8 rtw_ht_cap_get_tx_nss(u8 *ht_cap)
{
u8 *ht_mcs_set = HT_CAP_ELE_SUP_MCS_SET(ht_cap);
if (GET_HT_CAP_ELE_TX_MCS_DEF(ht_cap) && GET_HT_CAP_ELE_TRX_MCS_NEQ(ht_cap))
return GET_HT_CAP_ELE_TX_MAX_SS(ht_cap) + 1;
return rtw_ht_cap_get_rx_nss(ht_cap);
}
int rtw_action_frame_parse(const u8 *frame, u32 frame_len, u8 *category, u8 *action)
{
const u8 *frame_body = frame + sizeof(struct rtw_ieee80211_hdr_3addr);
@ -2954,23 +3122,41 @@ int rtw_action_frame_parse(const u8 *frame, u32 frame_len, u8 *category, u8 *act
}
static const char *_action_public_str[] = {
"ACT_PUB_BSSCOEXIST",
"ACT_PUB_DSE_ENABLE",
"ACT_PUB_DSE_DEENABLE",
"ACT_PUB_DSE_REG_LOCATION",
"ACT_PUB_EXT_CHL_SWITCH",
"ACT_PUB_DSE_MSR_REQ",
"ACT_PUB_DSE_MSR_RPRT",
"ACT_PUB_MP",
"ACT_PUB_DSE_PWR_CONSTRAINT",
"ACT_PUB_VENDOR",
"ACT_PUB_GAS_INITIAL_REQ",
"ACT_PUB_GAS_INITIAL_RSP",
"ACT_PUB_GAS_COMEBACK_REQ",
"ACT_PUB_GAS_COMEBACK_RSP",
"ACT_PUB_TDLS_DISCOVERY_RSP",
"ACT_PUB_LOCATION_TRACK",
"ACT_PUB_RSVD",
[ACT_PUBLIC_BSSCOEXIST] = "ACT_PUB_BSSCOEXIST",
[ACT_PUBLIC_DSE_ENABLE] = "ACT_PUB_DSE_ENABLE",
[ACT_PUBLIC_DSE_DEENABLE] = "ACT_PUB_DSE_DEENABLE",
[ACT_PUBLIC_DSE_REG_LOCATION] = "ACT_PUB_DSE_REG_LOCATION",
[ACT_PUBLIC_EXT_CHL_SWITCH] = "ACT_PUB_EXT_CHL_SWITCH",
[ACT_PUBLIC_DSE_MSR_REQ] = "ACT_PUB_DSE_MSR_REQ",
[ACT_PUBLIC_DSE_MSR_RPRT] = "ACT_PUB_DSE_MSR_RPRT",
[ACT_PUBLIC_MP] = "ACT_PUB_MP",
[ACT_PUBLIC_DSE_PWR_CONSTRAINT] = "ACT_PUB_DSE_PWR_CONSTRAINT",
[ACT_PUBLIC_VENDOR] = "ACT_PUB_VENDOR",
[ACT_PUBLIC_GAS_INITIAL_REQ] = "ACT_PUB_GAS_INITIAL_REQ",
[ACT_PUBLIC_GAS_INITIAL_RSP] = "ACT_PUB_GAS_INITIAL_RSP",
[ACT_PUBLIC_GAS_COMEBACK_REQ] = "ACT_PUB_GAS_COMEBACK_REQ",
[ACT_PUBLIC_GAS_COMEBACK_RSP] = "ACT_PUB_GAS_COMEBACK_RSP",
[ACT_PUBLIC_TDLS_DISCOVERY_RSP] = "ACT_PUB_TDLS_DISCOVERY_RSP",
[ACT_PUBLIC_LOCATION_TRACK] = "ACT_PUB_LOCATION_TRACK",
[ACT_PUBLIC_QAB_REQ] = "ACT_PUB_QAB_REQ",
[ACT_PUBLIC_QAB_RSP] = "ACT_PUB_QAB_RSP",
[ACT_PUBLIC_QMF_POLICY] = "ACT_PUB_QMF_POLICY",
[ACT_PUBLIC_QMF_POLICY_CHANGE] = "ACT_PUB_QMF_POLICY_CHANGE",
[ACT_PUBLIC_QLOAD_REQ] = "ACT_PUB_QLOAD_REQ",
[ACT_PUBLIC_QLOAD_REPORT] = "ACT_PUB_QLOAD_REPORT",
[ACT_PUBLIC_HCCA_TXOP_ADV] = "ACT_PUB_HCCA_TXOP_ADV",
[ACT_PUBLIC_HCCA_TXOP_RSP] = "ACT_PUB_HCCA_TXOP_RSP",
[ACT_PUBLIC_PUBLIC_KEY] = "ACT_PUB_PUBLIC_KEY",
[ACT_PUBLIC_CH_AVAILABILITY_QUERY] = "ACT_PUB_CH_AVAILABILITY_QUERY",
[ACT_PUBLIC_CH_SCHEDULE_MGMT] = "ACT_PUB_CH_SCHEDULE_MGMT",
[ACT_PUBLIC_CONTACT_VERI_SIGNAL] = "ACT_PUB_CONTACT_VERI_SIGNAL",
[ACT_PUBLIC_GDD_ENABLE_REQ] = "ACT_PUB_GDD_ENABLE_REQ",
[ACT_PUBLIC_GDD_ENABLE_RSP] = "ACT_PUB_GDD_ENABLE_RSP",
[ACT_PUBLIC_NETWORK_CH_CONTROL] = "ACT_PUB_NETWORK_CH_CONTROL",
[ACT_PUBLIC_WHITE_SPACE_MAP_ANN] = "ACT_PUB_WHITE_SPACE_MAP_ANN",
[ACT_PUBLIC_FTM_REQ] = "ACT_PUB_FTM_REQ",
[ACT_PUBLIC_FTM] = "ACT_PUB_FTM",
[ACT_PUBLIC_MAX] = "ACT_PUB_RSVD",
};
const char *action_public_str(u8 action)
@ -2979,3 +3165,53 @@ const char *action_public_str(u8 action)
return _action_public_str[action];
}
#if 0
/*tmp for sta mode, root cause have to wait supplicant's update.*/
void rtw_set_spp_amsdu_mode(u8 mode, u8 *rsn_ie, int rsn_ie_len)
{
struct rsne_info info;
int i, ret = _SUCCESS;
u8 spp_req_cap = 0;
ret = rtw_rsne_info_parse(rsn_ie, rsn_ie_len, &info);
if (ret != _SUCCESS)
return;
if (mode == RTW_AMSDU_MODE_NON_SPP ) {
spp_req_cap = 0; /* SPP_CAP=0, SPP_REQ=0 */
} else if (mode == RTW_AMSDU_MODE_SPP) {
spp_req_cap = SPP_CAP | SPP_REQ;
} else if (mode == RTW_AMSDU_MODE_ALL_DROP) {
spp_req_cap = SPP_REQ; /* SPP_CAP=0, SPP_REQ=1 */
} else {
RTW_INFO("%s unexpected mode = %d, please check the config\n", __func__, mode);
return;
}
SET_RSN_CAP_SPP(info.cap, spp_req_cap);
RTW_INFO("%s set spp opt = %d\n", __func__, GET_RSN_CAP_SPP_OPT(info.cap));
}
#endif
/* Returns:
_TRUE -- Disable AMSDU
_FALSE -- Enable AMSDU
*/
u8 rtw_check_amsdu_disable(u8 mode, u8 spp_opt)
{
u8 ret = _FALSE;
/* pp amsdu: peer's required has to be 0, or disable */
if ((mode == RTW_AMSDU_MODE_NON_SPP) && (spp_opt & SPP_REQ))
ret = _TRUE;
/* spp amsdu: peer's cap has to be 1, or disable */
else if ((mode == RTW_AMSDU_MODE_SPP) && (!(spp_opt & SPP_CAP)))
ret = _TRUE;
/* mode = all drop */
else if (mode == RTW_AMSDU_MODE_ALL_DROP)
ret = _TRUE;
else
ret = _FALSE;
return ret;
}

View File

@ -88,7 +88,7 @@ u8 rtw_do_join(_adapter *padapter)
pmlmepriv->cur_network.join_res = -2;
set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
set_fwstate(pmlmepriv, WIFI_UNDER_LINKING);
pmlmepriv->pscanned = plist;
@ -106,7 +106,7 @@ u8 rtw_do_join(_adapter *padapter)
if (_rtw_queue_empty(queue) == _TRUE) {
_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
_clr_fwstate_(pmlmepriv, WIFI_UNDER_LINKING);
/* when set_ssid/set_bssid for rtw_do_join(), but scanning queue is empty */
/* we try to issue sitesurvey firstly */
@ -141,6 +141,7 @@ u8 rtw_do_join(_adapter *padapter)
_set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
} else {
if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE) {
#ifdef CONFIG_AP_MODE
/* submit createbss_cmd to change to a ADHOC_MASTER */
/* pmlmepriv->lock has been acquired by caller... */
@ -164,11 +165,10 @@ u8 rtw_do_join(_adapter *padapter)
}
pmlmepriv->to_join = _FALSE;
#endif /* CONFIG_AP_MODE */
} else {
/* can't associate ; reset under-linking */
_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
_clr_fwstate_(pmlmepriv, WIFI_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 */
@ -223,12 +223,12 @@ u8 rtw_set_802_11_bssid(_adapter *padapter, u8 *bssid)
RTW_INFO("Set BSSID under fw_state=0x%08x\n", get_fwstate(pmlmepriv));
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE)
if (check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY) == _TRUE)
goto handle_tkip_countermeasure;
else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE)
else if (check_fwstate(pmlmepriv, WIFI_UNDER_LINKING) == _TRUE)
goto release_mlme_lock;
if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE) == _TRUE) {
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE | WIFI_ADHOC_MASTER_STATE) == _TRUE) {
if (_rtw_memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid, ETH_ALEN) == _TRUE) {
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _FALSE)
@ -237,7 +237,7 @@ u8 rtw_set_802_11_bssid(_adapter *padapter, u8 *bssid)
rtw_disassoc_cmd(padapter, 0, 0);
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
rtw_indicate_disconnect(padapter, 0, _FALSE);
rtw_free_assoc_resources_cmd(padapter, _TRUE, 0);
@ -260,7 +260,7 @@ handle_tkip_countermeasure:
pmlmepriv->assoc_ch = 0;
pmlmepriv->assoc_by_bssid = _TRUE;
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE)
if (check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY) == _TRUE)
pmlmepriv->to_join = _TRUE;
else
status = rtw_do_join(padapter);
@ -294,12 +294,12 @@ u8 rtw_set_802_11_ssid(_adapter *padapter, NDIS_802_11_SSID *ssid)
_enter_critical_bh(&pmlmepriv->lock, &irqL);
RTW_INFO("Set SSID under fw_state=0x%08x\n", get_fwstate(pmlmepriv));
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE)
if (check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY) == _TRUE)
goto handle_tkip_countermeasure;
else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE)
else if (check_fwstate(pmlmepriv, WIFI_UNDER_LINKING) == _TRUE)
goto release_mlme_lock;
if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE) == _TRUE) {
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE | WIFI_ADHOC_MASTER_STATE) == _TRUE) {
if ((pmlmepriv->assoc_ssid.SsidLength == ssid->SsidLength) &&
(_rtw_memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid, ssid->SsidLength) == _TRUE)) {
@ -309,7 +309,7 @@ u8 rtw_set_802_11_ssid(_adapter *padapter, NDIS_802_11_SSID *ssid)
/* if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again */
rtw_disassoc_cmd(padapter, 0, 0);
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
rtw_indicate_disconnect(padapter, 0, _FALSE);
rtw_free_assoc_resources_cmd(padapter, _TRUE, 0);
@ -330,7 +330,7 @@ u8 rtw_set_802_11_ssid(_adapter *padapter, NDIS_802_11_SSID *ssid)
rtw_disassoc_cmd(padapter, 0, 0);
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
rtw_indicate_disconnect(padapter, 0, _FALSE);
rtw_free_assoc_resources_cmd(padapter, _TRUE, 0);
@ -357,7 +357,7 @@ handle_tkip_countermeasure:
pmlmepriv->assoc_ch = 0;
pmlmepriv->assoc_by_bssid = _FALSE;
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE)
if (check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY) == _TRUE)
pmlmepriv->to_join = _TRUE;
else
status = rtw_do_join(padapter);
@ -405,9 +405,9 @@ u8 rtw_set_802_11_connect(_adapter *padapter,
RTW_PRINT(FUNC_ADPT_FMT" fw_state=0x%08x\n",
FUNC_ADPT_ARG(padapter), get_fwstate(pmlmepriv));
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE)
if (check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY) == _TRUE)
goto handle_tkip_countermeasure;
else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE)
else if (check_fwstate(pmlmepriv, WIFI_UNDER_LINKING) == _TRUE)
goto release_mlme_lock;
handle_tkip_countermeasure:
@ -429,7 +429,7 @@ handle_tkip_countermeasure:
pmlmepriv->assoc_ch = ch;
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE)
if (check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY) == _TRUE)
pmlmepriv->to_join = _TRUE;
else
status = rtw_do_join(padapter);
@ -467,7 +467,7 @@ u8 rtw_set_802_11_infrastructure_mode(_adapter *padapter,
}
_enter_critical_bh(&pmlmepriv->lock, &irqL);
is_linked = check_fwstate(pmlmepriv, _FW_LINKED);
is_linked = check_fwstate(pmlmepriv, WIFI_ASOC_STATE);
is_adhoc_master = check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
/* flags = 0, means enqueue cmd and no wait */
@ -526,9 +526,11 @@ u8 rtw_set_802_11_infrastructure_mode(_adapter *padapter,
case Ndis802_11AutoUnknown:
case Ndis802_11InfrastructureMax:
break;
#ifdef CONFIG_WIFI_MONITOR
case Ndis802_11Monitor:
set_fwstate(pmlmepriv, WIFI_MONITOR_STATE);
break;
#endif /* CONFIG_WIFI_MONITOR */
default:
ret = _FALSE;
rtw_warn_on(1);
@ -552,7 +554,7 @@ u8 rtw_set_802_11_disassociate(_adapter *padapter)
_enter_critical_bh(&pmlmepriv->lock, &irqL);
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE) {
rtw_disassoc_cmd(padapter, 0, 0);
rtw_indicate_disconnect(padapter, 0, _FALSE);
@ -600,7 +602,7 @@ u8 rtw_set_802_11_bssid_list_scan(_adapter *padapter, struct sitesurvey_parm *pp
goto exit;
}
if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) == _TRUE) ||
if ((check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY | WIFI_UNDER_LINKING) == _TRUE) ||
(pmlmepriv->LinkDetectInfo.bBusyTraffic == _TRUE)) {
/* Scan or linking is in progress, do nothing. */
res = _TRUE;
@ -795,7 +797,7 @@ u16 rtw_get_cur_max_rate(_adapter *adapter)
}
#endif
if ((check_fwstate(pmlmepriv, _FW_LINKED) != _TRUE)
if ((check_fwstate(pmlmepriv, WIFI_ASOC_STATE) != _TRUE)
&& (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) != _TRUE))
return 0;
@ -880,8 +882,12 @@ int rtw_set_scan_mode(_adapter *adapter, RT_SCAN_TYPE scan_mode)
*/
int rtw_set_channel_plan(_adapter *adapter, u8 channel_plan)
{
/* handle by cmd_thread to sync with scan operation */
return rtw_set_chplan_cmd(adapter, RTW_CMDF_WAIT_ACK, channel_plan, 1);
struct registry_priv *regsty = adapter_to_regsty(adapter);
if (!REGSTY_REGD_SRC_FROM_OS(regsty))
return rtw_set_chplan_cmd(adapter, RTW_CMDF_WAIT_ACK, channel_plan, 1);
RTW_WARN("%s(): not applied\n", __func__);
return _SUCCESS;
}
/*
@ -894,11 +900,13 @@ int rtw_set_channel_plan(_adapter *adapter, u8 channel_plan)
int rtw_set_country(_adapter *adapter, const char *country_code)
{
#ifdef CONFIG_RTW_IOCTL_SET_COUNTRY
return rtw_set_country_cmd(adapter, RTW_CMDF_WAIT_ACK, country_code, 1);
#else
RTW_INFO("%s(): not applied\n", __func__);
return _SUCCESS;
struct registry_priv *regsty = adapter_to_regsty(adapter);
if (!REGSTY_REGD_SRC_FROM_OS(regsty))
return rtw_set_country_cmd(adapter, RTW_CMDF_WAIT_ACK, country_code, 1);
#endif
RTW_WARN("%s(): not applied\n", __func__);
return _SUCCESS;
}
/*

View File

@ -24,7 +24,7 @@ struct xmit_frame *rtw_IOL_accquire_xmit_frame(ADAPTER *adapter)
struct xmit_priv *pxmitpriv = &(adapter->xmitpriv);
#if 1
xmit_frame = rtw_alloc_xmitframe(pxmitpriv);
xmit_frame = rtw_alloc_xmitframe(pxmitpriv, 0);
if (xmit_frame == NULL) {
RTW_INFO("%s rtw_alloc_xmitframe return null\n", __FUNCTION__);
goto exit;

803
core/rtw_mbo.c Normal file
View File

@ -0,0 +1,803 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#include <drv_types.h>
#include <hal_data.h>
#ifdef CONFIG_RTW_MBO
#ifndef RTW_MBO_DBG
#define RTW_MBO_DBG 0
#endif
#if RTW_MBO_DBG
#define RTW_MBO_INFO(fmt, arg...) \
RTW_INFO(fmt, arg)
#define RTW_MBO_DUMP(str, data, len) \
RTW_INFO_DUMP(str, data, len)
#else
#define RTW_MBO_INFO(fmt, arg...) do {} while (0)
#define RTW_MBO_DUMP(str, data, len) do {} while (0)
#endif
/* Cellular Data Connectivity field
* 1 : Cellular data connection available
* 2 : Cellular data connection not available
* 3 : Not Cellular data capable
* otherwise : Reserved
*/
int rtw_mbo_cell_data_conn = 2;
module_param(rtw_mbo_cell_data_conn, int, 0644);
static u8 wfa_mbo_oui[] = {0x50, 0x6F, 0x9A, 0x16};
#define rtw_mbo_get_oui(p) ((u8 *)(p) + 2)
#define rtw_mbo_get_attr_id(p) ((u8 *)(p))
#define rtw_mbo_get_disallow_res(p) ((u8 *)(p) + 3)
#define rtw_mbo_set_1byte_ie(p, v, l) \
rtw_set_fixed_ie((p), 1, (v), (l))
#define rtw_mbo_set_4byte_ie(p, v, l) \
rtw_set_fixed_ie((p), 4, (v), (l))
#define rtw_mbo_set_nbyte_ie(p, sz, v, l) \
rtw_set_fixed_ie((p), (sz), (v), (l))
#define rtw_mbo_subfield_set(p, offset, val) (*(p + offset) = val)
#define rtw_mbo_subfields_set(p, offset, buf, len) \
do { \
u32 _offset = 0; \
u8 *_p = p + offset; \
while(_offset < len) { \
*(_p + _offset) = *(buf + _offset); \
_offset++; \
} \
} while(0)
static u8 *rtw_mbo_ie_get(u8 *pie, u32 *plen, u32 limit)
{
const u8 *p = pie;
u32 tmp, i;
if (limit <= 1)
return NULL;
i = 0;
*plen = 0;
while (1) {
if ((*p == _VENDOR_SPECIFIC_IE_) &&
(_rtw_memcmp(rtw_mbo_get_oui(p), wfa_mbo_oui, 4))) {
*plen = *(p + 1);
RTW_MBO_DUMP("VENDOR_SPECIFIC_IE MBO: ", p, *(p + 1));
return (u8 *)p;
} else {
tmp = *(p + 1);
p += (tmp + 2);
i += (tmp + 2);
}
if (i >= limit)
break;
}
return NULL;
}
static u8 *rtw_mbo_attrs_get(u8 *pie, u32 limit, u8 attr_id, u32 *attr_len)
{
u8 *p = NULL;
u32 offset, plen = 0;
if ((pie == NULL) || (limit <= 1))
goto exit;
if ((p = rtw_mbo_ie_get(pie, &plen, limit)) == NULL)
goto exit;
/* shift 2 + OUI size and move to attributes content */
p = p + 2 + sizeof(wfa_mbo_oui);
plen = plen - 4;
RTW_MBO_DUMP("Attributes contents: ", p, plen);
if ((p = rtw_get_ie(p, attr_id, attr_len, plen)) == NULL)
goto exit;
RTW_MBO_INFO("%s : id=%u(len=%u)\n", __func__, attr_id, *attr_len);
RTW_MBO_DUMP("contents : ", p, *attr_len);
exit:
return p;
}
static u32 rtw_mbo_attr_sz_get(
_adapter *padapter, u8 id)
{
u32 len = 0;
switch (id) {
case RTW_MBO_ATTR_NPREF_CH_RPT_ID:
{
struct rf_ctl_t *prfctl = adapter_to_rfctl(padapter);
struct npref_ch_rtp *prpt = &(prfctl->ch_rtp);
struct npref_ch* pch;
u32 i, attr_len, offset;
for (i=0; i < prpt->nm_of_rpt; i++) {
pch = &prpt->ch_rpt[i];
/*attr_len = ch list + op class + preference + reason */
attr_len = pch->nm_of_ch + 3;
/* offset = id + len field + attr_len */
offset = attr_len + 2;
len += offset;
}
}
break;
case RTW_MBO_ATTR_CELL_DATA_CAP_ID:
case RTW_MBO_ATTR_TRANS_REJ_ID:
len = 3;
break;
default:
break;
}
return len;
}
static void rtw_mbo_build_mbo_ie_hdr(
u8 **pframe, struct pkt_attrib *pattrib, u8 payload_len)
{
u8 eid = RTW_MBO_EID;
u8 len = payload_len + 4;
*pframe = rtw_mbo_set_1byte_ie(*pframe, &eid, &(pattrib->pktlen));
*pframe = rtw_mbo_set_1byte_ie(*pframe, &len, &(pattrib->pktlen));
*pframe = rtw_mbo_set_4byte_ie(*pframe, wfa_mbo_oui, &(pattrib->pktlen));
}
void rtw_mbo_build_cell_data_cap_attr(
_adapter *padapter, u8 **pframe, struct pkt_attrib *pattrib)
{
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
u8 attr_id = RTW_MBO_ATTR_CELL_DATA_CAP_ID;
u8 attr_len = 1;
u8 cell_data_con = rtw_mbo_cell_data_conn;
/* used Cellular Data Capabilities from supplicant */
if (!rtw_mbo_wifi_logo_test(padapter) &&
pmlmepriv->pcell_data_cap_ie && pmlmepriv->cell_data_cap_len == 1) {
cell_data_con = *pmlmepriv->pcell_data_cap_ie;
RTW_MBO_INFO("%s : used Cellular Data Capabilities(%u) from supplicant!\n",
__func__, *pmlmepriv->pcell_data_cap_ie);
}
*pframe = rtw_mbo_set_1byte_ie(*pframe, &attr_id, &(pattrib->pktlen));
*pframe = rtw_mbo_set_1byte_ie(*pframe, &attr_len, &(pattrib->pktlen));
*pframe = rtw_mbo_set_1byte_ie(*pframe, &cell_data_con, &(pattrib->pktlen));
}
static void rtw_mbo_update_cell_data_cap(
_adapter *padapter, u8 *pie, u32 ie_len)
{
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
u8 *mbo_attr;
u32 mbo_attrlen;
if ((pie == NULL) || (ie_len == 0))
return;
mbo_attr = rtw_mbo_attrs_get(pie, ie_len,
RTW_MBO_ATTR_CELL_DATA_CAP_ID, &mbo_attrlen);
if ((mbo_attr == NULL) || (mbo_attrlen == 0) ) {
RTW_INFO("MBO : Cellular Data Capabilities not found!\n");
return;
}
rtw_buf_update(&pmlmepriv->pcell_data_cap_ie,
&pmlmepriv->cell_data_cap_len, (mbo_attr + 2), mbo_attrlen);
RTW_MBO_DUMP("rtw_mbo_update_cell_data_cap : ",
pmlmepriv->pcell_data_cap_ie, pmlmepriv->cell_data_cap_len);
}
void rtw_mbo_update_ie_data(
_adapter *padapter, u8 *pie, u32 ie_len)
{
rtw_mbo_update_cell_data_cap(padapter, pie, ie_len);
}
static u8 rtw_mbo_current_op_class_get(_adapter *padapter)
{
struct rf_ctl_t *prfctl = adapter_to_rfctl(padapter);
struct p2p_channels *pch_list = &(prfctl->channel_list);
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
struct p2p_reg_class *preg_class;
int class_idx, ch_idx;
u8 cur_op_class = 0;
for(class_idx =0; class_idx < pch_list->reg_classes; class_idx++) {
preg_class = &pch_list->reg_class[class_idx];
for (ch_idx = 0; ch_idx <= preg_class->channels; ch_idx++) {
if (pmlmeext->cur_channel == preg_class->channel[ch_idx]) {
cur_op_class = preg_class->reg_class;
RTW_MBO_INFO("%s : current ch : %d, op class : %d\n",
__func__, pmlmeext->cur_channel, cur_op_class);
break;
}
}
}
return cur_op_class;
}
static void rtw_mbo_supp_op_classes_get(_adapter *padapter, u8 *pclasses)
{
struct rf_ctl_t *prfctl = adapter_to_rfctl(padapter);
struct p2p_channels *pch_list = &(prfctl->channel_list);
int class_idx;
if (pclasses == NULL)
return;
RTW_MBO_INFO("%s : support op class \n", __func__);
for(class_idx = 0; class_idx < pch_list->reg_classes; class_idx++) {
*(pclasses + class_idx) = pch_list->reg_class[class_idx].reg_class;
RTW_MBO_INFO("%u ,", *(pclasses + class_idx));
}
RTW_MBO_INFO("%s : \n", __func__);
}
void rtw_mbo_build_supp_op_class_elem(
_adapter *padapter, u8 **pframe, struct pkt_attrib *pattrib)
{
struct rf_ctl_t *prfctl = adapter_to_rfctl(padapter);
u8 payload[32] = {0};
u8 delimiter_130 = 130; /*0x82*/
u8 reg_class_nm, len;
if ((reg_class_nm = prfctl->channel_list.reg_classes) == 0)
return;
payload[0] = rtw_mbo_current_op_class_get(padapter);
rtw_mbo_supp_op_classes_get(padapter, &payload[1]);
/* IEEE 802.11 Std Current Operating Class Extension Sequence */
payload[reg_class_nm + 1] = delimiter_130;
payload[reg_class_nm + 2] = 0x00;
RTW_MBO_DUMP("op class :", payload, reg_class_nm);
/* Current Operating Class field + Operating Class field
+ OneHundredAndThirty Delimiter field */
len = reg_class_nm + 3;
*pframe = rtw_set_ie(*pframe, EID_SupRegulatory, len ,
payload, &(pattrib->pktlen));
}
static u8 rtw_mbo_construct_npref_ch_rpt_attr(
_adapter *padapter, u8 *pbuf, u32 buf_len, u32 *plen)
{
struct rf_ctl_t *prfctl = adapter_to_rfctl(padapter);
struct npref_ch_rtp *prpt = &(prfctl->ch_rtp);
struct npref_ch* pch;
u32 attr_len, offset;
int i;
u8 *p = pbuf;
if (prpt->nm_of_rpt == 0) {
*plen = 0;
return _FALSE;
}
for (i=0; i < prpt->nm_of_rpt; i++) {
pch = &prpt->ch_rpt[i];
/* attr_len = ch list + op class + preference + reason */
attr_len = pch->nm_of_ch + 3;
/* offset = id + len field + attr_len */
offset = attr_len + 2;
rtw_mbo_subfield_set(p, 0, RTW_MBO_ATTR_NPREF_CH_RPT_ID);
rtw_mbo_subfield_set(p, 1, attr_len);
rtw_mbo_subfield_set(p, 2, pch->op_class);
rtw_mbo_subfields_set(p, 3, pch->chs, pch->nm_of_ch);
rtw_mbo_subfield_set(p, (offset - 2), pch->preference);
rtw_mbo_subfield_set(p, (offset - 1), pch->reason);
p += offset;
*plen += offset;
if (*plen >= buf_len) {
RTW_ERR("MBO : construct non-preferred channel report fail!\n");
return _FALSE;
}
}
return _TRUE;
}
void rtw_mbo_build_npref_ch_rpt_attr(
_adapter *padapter, u8 **pframe, struct pkt_attrib *pattrib)
{
struct rf_ctl_t *prfctl = adapter_to_rfctl(padapter);
struct npref_ch_rtp *prpt = &(prfctl->ch_rtp);
u32 tmp_sz = 0, body_len = 0;
u8 *ptmp;
tmp_sz = prpt->nm_of_rpt * sizeof(struct npref_ch);
ptmp = rtw_zmalloc(tmp_sz);
if (ptmp == NULL)
return;
if (rtw_mbo_construct_npref_ch_rpt_attr(padapter, ptmp, tmp_sz, &body_len) == _FALSE) {
rtw_mfree(ptmp, tmp_sz);
return;
}
RTW_MBO_DUMP("Non-preferred Channel Report :", ptmp, body_len);
*pframe = rtw_mbo_set_nbyte_ie(*pframe, body_len, ptmp, &(pattrib->pktlen));
rtw_mfree(ptmp, tmp_sz);
}
void rtw_mbo_build_trans_reject_reason_attr(
_adapter *padapter, u8 **pframe, struct pkt_attrib *pattrib, u8 *pres)
{
u8 attr_id = RTW_MBO_ATTR_TRANS_REJ_ID;
u8 attr_len = 1;
u32 len = 0;
len = rtw_mbo_attr_sz_get(padapter, RTW_MBO_ATTR_TRANS_REJ_ID);
if ((len == 0) || (len > 3)) {
RTW_ERR("MBO : build Transition Rejection Reason attribute fail(len=%u)\n", len);
return;
}
rtw_mbo_build_mbo_ie_hdr(pframe, pattrib, len);
*pframe = rtw_mbo_set_1byte_ie(*pframe, &attr_id, &(pattrib->pktlen));
*pframe = rtw_mbo_set_1byte_ie(*pframe, &attr_len, &(pattrib->pktlen));
*pframe = rtw_mbo_set_1byte_ie(*pframe, pres, &(pattrib->pktlen));
}
u8 rtw_mbo_disallowed_network(struct wlan_network *pnetwork)
{
u8 *p, *attr_id, *res;
u32 attr_len = 0;
u8 disallow = _FALSE;
if (pnetwork == NULL)
goto exit;
p = rtw_mbo_attrs_get(pnetwork->network.IEs,
pnetwork->network.IELength,
RTW_MBO_ATTR_ASSOC_DISABLED_ID,
&attr_len);
if (p == NULL) {
RTW_MBO_INFO("%s :Assoc Disallowed attribute not found!\n",__func__);
goto exit;
}
RTW_MBO_DUMP("Association Disallowed attribute :",p , attr_len + 2);
RTW_INFO("MBO : block "MAC_FMT" assoc disallowed reason %d\n",
MAC_ARG(pnetwork->network.MacAddress), *(rtw_mbo_get_disallow_res(p)));
disallow = _TRUE;
exit:
return disallow;
}
void rtw_mbo_build_exented_cap(
_adapter *padapter, u8 **pframe, struct pkt_attrib *pattrib)
{
u8 content[8] = { 0 };
rtw_wnm_set_ext_cap_btm(content, 1);
rtw_mbo_set_ext_cap_internw(content, 1);
*pframe = rtw_set_ie(*pframe,
EID_EXTCapability,
8,
content,
&(pattrib->pktlen));
}
static void rtw_mbo_non_pref_chans_dump(struct npref_ch* pch)
{
int i;
u8 buf[128] = {0};
for (i=0; i < pch->nm_of_ch; i++)
rtw_sprintf(buf, 128, "%s,%d", buf, pch->chs[i]);
RTW_MBO_INFO("%s : op_class=%01x, ch=%s, preference=%d, reason=%d\n",
__func__, pch->op_class, buf, pch->preference, pch->reason);
}
static u8 rtw_mbo_non_pref_chan_exist(struct npref_ch* pch, u8 ch)
{
u32 i;
u8 found = _FALSE;
for (i=0; i < pch->nm_of_ch; i++) {
if (pch->chs[i] == ch) {
found = _TRUE;
break;
}
}
return found;
}
static struct npref_ch* rtw_mbo_non_pref_chan_get(
_adapter *padapter, u8 op_class, u8 prefe, u8 res)
{
struct rf_ctl_t *prfctl = adapter_to_rfctl(padapter);
struct npref_ch_rtp *prpt = &(prfctl->ch_rtp);
struct npref_ch* pch = NULL;
int i;
if (prpt->nm_of_rpt == 0)
return pch;
for (i=0; i < prpt->nm_of_rpt; i++) {
if ((prpt->ch_rpt[i].op_class == op_class) &&
(prpt->ch_rpt[i].preference == prefe) &&
(prpt->ch_rpt[i].reason == res)) {
pch = &prpt->ch_rpt[i];
break;
}
}
return pch;
}
static void rtw_mbo_non_pref_chan_set(
struct npref_ch* pch, u8 op_class, u8 ch, u8 prefe, u8 res, u8 update)
{
u32 offset = pch->nm_of_ch;
if (update) {
if (rtw_mbo_non_pref_chan_exist(pch, ch) == _FALSE) {
pch->chs[offset] = ch;
pch->nm_of_ch++;
}
} else {
pch->op_class = op_class;
pch->chs[0] = ch;
pch->preference = prefe;
pch->reason = res;
pch->nm_of_ch = 1;
}
}
static void rtw_mbo_non_pref_chans_update(
_adapter *padapter, u8 op_class, u8 ch, u8 prefe, u8 res)
{
struct rf_ctl_t *prfctl = adapter_to_rfctl(padapter);
struct npref_ch_rtp *pch_rpt = &(prfctl->ch_rtp);
struct npref_ch* pch;
if (pch_rpt->nm_of_rpt >= RTW_MBO_MAX_CH_RPT_NUM) {
RTW_ERR("MBO : %d non_pref_chan entries supported!",
RTW_MBO_MAX_CH_RPT_NUM);
return;
}
if (pch_rpt->nm_of_rpt == 0) {
pch = &pch_rpt->ch_rpt[0];
rtw_mbo_non_pref_chan_set(pch, op_class, ch, prefe, res, _FALSE);
pch_rpt->nm_of_rpt = 1;
return;
}
pch = rtw_mbo_non_pref_chan_get(padapter, op_class, prefe, res);
if (pch == NULL) {
pch = &pch_rpt->ch_rpt[pch_rpt->nm_of_rpt];
rtw_mbo_non_pref_chan_set(pch, op_class, ch, prefe, res, _FALSE);
pch_rpt->nm_of_rpt++;
} else
rtw_mbo_non_pref_chan_set(pch, op_class, ch, prefe, res, _TRUE);
rtw_mbo_non_pref_chans_dump(pch);
}
static void rtw_mbo_non_pref_chans_set(
_adapter *padapter, char *param, ssize_t sz)
{
char *pnext;
u32 op_class, ch, prefe, res;
int i = 0;
do {
pnext = strsep(&param, " ");
if (pnext == NULL)
break;
sscanf(pnext, "%d:%d:%d:%d", &op_class, &ch, &prefe, &res);
rtw_mbo_non_pref_chans_update(padapter, op_class, ch, prefe, res);
if ((i++) > 10) {
RTW_ERR("MBO : overflow %d \n", i);
break;
}
} while(param != '\0');
}
static void rtw_mbo_non_pref_chans_del(
_adapter *padapter, char *param, ssize_t sz)
{
struct rf_ctl_t *prfctl = adapter_to_rfctl(padapter);
struct npref_ch_rtp *prpt = &(prfctl->ch_rtp);
RTW_INFO("%s : delete non_pref_chan %s\n", __func__, param);
_rtw_memset(prpt, 0, sizeof(struct npref_ch_rtp));
}
ssize_t rtw_mbo_proc_non_pref_chans_set(
struct file *pfile, const char __user *buffer,
size_t count, loff_t *pos, void *pdata)
{
struct net_device *dev = pdata;
_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
u8 tmp[128] = {0};
if (count < 1)
return -EFAULT;
if (count > sizeof(tmp)) {
rtw_warn_on(1);
return -EFAULT;
}
if (buffer && !copy_from_user(tmp, buffer, count)) {
if (strncmp(tmp, "add", 3) == 0)
rtw_mbo_non_pref_chans_set(padapter, &tmp[4], (count - 4));
else if (strncmp(tmp, "delete", 6) == 0)
rtw_mbo_non_pref_chans_del(padapter, &tmp[7], (count - 7));
else {
RTW_ERR("MBO : Invalid format : echo [add|delete] <oper_class>:<chan>:<preference>:<reason>\n");
return -EFAULT;
}
}
#ifdef CONFIG_RTW_WNM
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) &&
check_fwstate(pmlmepriv, WIFI_STATION_STATE))
rtw_wnm_issue_action(padapter, RTW_WLAN_ACTION_WNM_NOTIF_REQ, 0, 0);
#endif
return count;
}
int rtw_mbo_proc_non_pref_chans_get(
struct seq_file *m, void *v)
{
struct net_device *dev = m->private;
_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
struct rf_ctl_t *prfctl = adapter_to_rfctl(padapter);
struct npref_ch_rtp *prpt = &(prfctl->ch_rtp);
struct npref_ch* pch;
int i,j;
u8 buf[32] = {0};
RTW_PRINT_SEL(m, "op_class ch preference reason \n");
RTW_PRINT_SEL(m, "=======================================================\n");
if (prpt->nm_of_rpt == 0) {
RTW_PRINT_SEL(m, " empty table \n");
return 0;
}
for (i=0; i < prpt->nm_of_rpt; i++) {
pch = &prpt->ch_rpt[i];
buf[0]='\0';
for (j=0; j < pch->nm_of_ch; j++) {
if (j == 0)
rtw_sprintf(buf, 32, "%02u", pch->chs[j]);
else
rtw_sprintf(buf, 32, "%s,%02u", buf, pch->chs[j]);
}
RTW_PRINT_SEL(m, " %04u %20s %02u %02u\n",
pch->op_class, buf, pch->preference, pch->reason);
}
return 0;
}
ssize_t rtw_mbo_proc_cell_data_set(
struct file *pfile, const char __user *buffer,
size_t count, loff_t *pos, void *pdata)
{
struct net_device *dev = pdata;
_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
int mbo_cell_data = 0;
u8 tmp[8] = {0};
if (count < 1)
return -EFAULT;
if (count > sizeof(tmp))
return -EFAULT;
if (buffer && !copy_from_user(tmp, buffer, count)) {
int num = sscanf(tmp, "%d", &mbo_cell_data);
if (num == 1) {
rtw_mbo_cell_data_conn = mbo_cell_data;
#ifdef CONFIG_RTW_WNM
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) &&
check_fwstate(pmlmepriv, WIFI_STATION_STATE))
rtw_wnm_issue_action(padapter, RTW_WLAN_ACTION_WNM_NOTIF_REQ, 0, 0);
#endif
}
}
return count;
}
int rtw_mbo_proc_cell_data_get(
struct seq_file *m, void *v)
{
#if 0
struct net_device *dev = m->private;
_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
#endif
RTW_PRINT_SEL(m, "Cellular Data Connectivity : %d\n", rtw_mbo_cell_data_conn);
return 0;
}
static void rtw_mbo_non_pref_chan_subelem_parsing(
_adapter *padapter, u8 *subelem, size_t subelem_len)
{
u8 *pnon_pref_chans;
u32 non_pref_chan_offset, op_subelem_len;
u32 oui_offset = 3;
/* wpa_supplicant don't apped OUI Type */
u32 oui_type_offset = 0;
RTW_MBO_DUMP("Non-preferred Channel subelem : ", subelem , subelem_len);
/* Subelem :
Vendor Specific | Length | WFA OUI | OUI Type | MBO Attributes */
non_pref_chan_offset = 2 + oui_offset + oui_type_offset;
pnon_pref_chans = subelem + non_pref_chan_offset;
op_subelem_len = subelem_len - non_pref_chan_offset;
/* wpa_supplicant don't indicate non_pref_chan length,
so we cannot get how many non_pref_chan in a wnm notification */
RTW_MBO_DUMP("Non-preferred Channel : ", pnon_pref_chans, op_subelem_len);
}
void rtw_mbo_wnm_notification_parsing(
_adapter *padapter, const u8 *pdata, size_t data_len)
{
u8 *paction;
u8 category, action, dialog, type;
u32 len;
if ((pdata == NULL) || (data_len == 0))
return;
RTW_MBO_DUMP("WNM notification data : ", pdata, data_len);
paction = (u8 *)pdata + sizeof(struct rtw_ieee80211_hdr_3addr);
category = paction[0];
action = paction[1];
dialog = paction[2];
type = paction[3];
if ((action == RTW_WLAN_ACTION_WNM_NOTIF_REQ) &&
(type == WLAN_EID_VENDOR_SPECIFIC)) {
rtw_mbo_non_pref_chan_subelem_parsing(padapter, &paction[4],
(data_len - sizeof(struct rtw_ieee80211_hdr_3addr)));
}
}
void rtw_mbo_build_wnm_notification(
_adapter *padapter, u8 **pframe, struct pkt_attrib *pattrib)
{
struct rf_ctl_t *prfctl = adapter_to_rfctl(padapter);
struct npref_ch_rtp *prpt = &(prfctl->ch_rtp);
struct npref_ch* pch;
u8 subelem_id = WLAN_EID_VENDOR_SPECIFIC;
u8 non_pref_ch_oui[] = {0x50, 0x6F, 0x9A, 0x2};
u8 cell_data_cap_oui[] = {0x50, 0x6F, 0x9A, 0x3};
u8 cell_data_con = rtw_mbo_cell_data_conn;
u8 len, cell_data_con_len = 0, *pcont = *pframe;
int i;
if (rtw_mbo_cell_data_conn > 0) {
len = 0x5;
*pframe = rtw_mbo_set_1byte_ie(*pframe, &subelem_id, &(pattrib->pktlen));
*pframe = rtw_mbo_set_1byte_ie(*pframe, &len, &(pattrib->pktlen));
*pframe = rtw_mbo_set_4byte_ie(*pframe, cell_data_cap_oui, &(pattrib->pktlen));
*pframe = rtw_mbo_set_1byte_ie(*pframe, &cell_data_con, &(pattrib->pktlen));
RTW_MBO_INFO("%s : Cellular Data Capabilities subelemen\n", __func__);
RTW_MBO_DUMP(":", pcont, len + 2);
pcont += len + 2 ;
}
if (prpt->nm_of_rpt == 0) {
len = 0x4;
*pframe = rtw_mbo_set_1byte_ie(*pframe, &subelem_id, &(pattrib->pktlen));
*pframe = rtw_mbo_set_1byte_ie(*pframe, &len, &(pattrib->pktlen));
*pframe = rtw_mbo_set_4byte_ie(*pframe, non_pref_ch_oui, &(pattrib->pktlen));
RTW_MBO_INFO("%s :Non-preferred Channel Report subelement without data\n", __func__);
return;
}
for (i=0; i < prpt->nm_of_rpt; i++) {
pch = &prpt->ch_rpt[i];
/* OUI(3B) + OUT-type(1B) + op-class(1B) + ch list(nB)
+ Preference(1B) + reason(1B) */
len = pch->nm_of_ch + 7;
*pframe = rtw_mbo_set_1byte_ie(*pframe, &subelem_id, &(pattrib->pktlen));
*pframe = rtw_mbo_set_1byte_ie(*pframe, &len, &(pattrib->pktlen));
*pframe = rtw_mbo_set_4byte_ie(*pframe, non_pref_ch_oui, &(pattrib->pktlen));
*pframe = rtw_mbo_set_1byte_ie(*pframe, &pch->op_class, &(pattrib->pktlen));
*pframe = rtw_mbo_set_nbyte_ie(*pframe, pch->nm_of_ch, pch->chs, &(pattrib->pktlen));
*pframe = rtw_mbo_set_1byte_ie(*pframe, &pch->preference, &(pattrib->pktlen));
*pframe = rtw_mbo_set_1byte_ie(*pframe, &pch->reason, &(pattrib->pktlen));
RTW_MBO_INFO("%s :Non-preferred Channel Report subelement\n", __func__);
RTW_MBO_DUMP(":", pcont, len);
pcont = *pframe;
}
}
void rtw_mbo_build_probe_req_ies(
_adapter *padapter, u8 **pframe, struct pkt_attrib *pattrib)
{
u32 len =0;
rtw_mbo_build_exented_cap(padapter, pframe, pattrib);
len = rtw_mbo_attr_sz_get(padapter, RTW_MBO_ATTR_CELL_DATA_CAP_ID);
if ((len == 0) || (len > 3)) {
RTW_ERR("MBO : build Cellular Data Capabilities attribute fail(len=%u)\n", len);
return;
}
rtw_mbo_build_mbo_ie_hdr(pframe, pattrib, len);
rtw_mbo_build_cell_data_cap_attr(padapter, pframe, pattrib);
}
void rtw_mbo_build_assoc_req_ies(
_adapter *padapter, u8 **pframe, struct pkt_attrib *pattrib)
{
u32 len = 0;
rtw_mbo_build_supp_op_class_elem(padapter, pframe, pattrib);
len += rtw_mbo_attr_sz_get(padapter, RTW_MBO_ATTR_CELL_DATA_CAP_ID);
len += rtw_mbo_attr_sz_get(padapter, RTW_MBO_ATTR_NPREF_CH_RPT_ID);
if ((len == 0)|| (len < 3)) {
RTW_ERR("MBO : build assoc MBO IE fail(len=%u)\n", len);
return;
}
rtw_mbo_build_mbo_ie_hdr(pframe, pattrib, len);
rtw_mbo_build_cell_data_cap_attr(padapter, pframe, pattrib);
rtw_mbo_build_npref_ch_rpt_attr(padapter, pframe, pattrib);
}
#endif /* CONFIG_RTW_MBO */

View File

@ -21,6 +21,49 @@ MODULE_DESCRIPTION("Realtek Wireless Lan Driver");
MODULE_AUTHOR("Realtek Semiconductor Corp.");
MODULE_VERSION("DRIVERVERSION");
/* for MAX_RECVBUF_SZ */
#if defined(CONFIG_RTL8188E)
#include <rtl8188e_hal.h>
#elif defined(CONFIG_RTL8188F)
#include <rtl8188f_hal.h>
#elif defined(CONFIG_RTL8188GTV)
#include <rtl8188gtv_hal.h>
#elif defined(CONFIG_RTL8710B)
#include <rtl8710b_hal.h>
#elif defined(CONFIG_RTL8192E)
#include <rtl8192e_hal.h>
#elif defined(CONFIG_RTL8192F)
#include <rtl8192f_hal.h>
#elif defined(CONFIG_RTL8723B)
#include <rtl8723b_hal.h>
#elif defined(CONFIG_RTL8703B)
#include <rtl8703b_hal.h>
#elif defined(CONFIG_RTL8723D)
#include <rtl8723d_hal.h>
#elif defined(CONFIG_RTL8812A) || defined(CONFIG_RTL8821A)
#include <rtl8812a_hal.h>
#elif defined(CONFIG_RTL8822B)
#include <rtl8822b_hal.h>
#elif defined(CONFIG_RTL8822C)
#include <rtl8822c_hal.h>
#elif defined(CONFIG_RTL8814A)
#include <rtl8814a_hal.h>
#elif defined(CONFIG_RTL8814B)
#include <rtl8814b_hal.h>
#endif
#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
#define MAX_RTKM_RECVBUF_SZ MAX_RECVBUF_SZ
#define MAX_RTKM_NR_PREALLOC_RECV_SKB NR_RECVBUFF
#else /* !CONFIG_SDIO_HCI */
#ifdef CONFIG_PLATFORM_MSTAR_HIGH
#define MAX_RTKM_RECVBUF_SZ (31744) /* 31k */
#else
#define MAX_RTKM_RECVBUF_SZ (15360) /* 15k */
#endif /* CONFIG_PLATFORM_MSTAR_HIGH */
#define MAX_RTKM_NR_PREALLOC_RECV_SKB 16
#endif /* !CONFIG_SDIO_HCI */
struct sk_buff_head rtk_skb_mem_q;
struct u8 *rtk_buf_mem[NR_RECVBUFF];

View File

@ -1,6 +1,6 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2017 Realtek Corporation.
* Copyright(c) 2007 - 2019 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@ -20,11 +20,15 @@
void rtw_mi_update_union_chan_inf(_adapter *adapter, u8 ch, u8 offset , u8 bw)
{
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
struct mi_state *iface_state = &dvobj->iface_state;
iface_state->union_ch = ch;
iface_state->union_bw = bw;
iface_state->union_offset = offset;
if (!ch) {
dvobj->union_ch_bak = dvobj->union_ch;
dvobj->union_bw_bak = dvobj->union_bw;
dvobj->union_offset_bak = dvobj->union_offset;
}
dvobj->union_ch = ch;
dvobj->union_bw = bw;
dvobj->union_offset = offset;
}
#ifdef DBG_IFACE_STATUS
@ -131,7 +135,7 @@ int rtw_mi_get_ch_setting_union_by_ifbmp(struct dvobj_priv *dvobj, u8 ifbmp, u8
mlmeext = &iface->mlmeextpriv;
if (!check_fwstate(&iface->mlmepriv, _FW_LINKED | _FW_UNDER_LINKING))
if (!check_fwstate(&iface->mlmepriv, WIFI_ASOC_STATE | WIFI_UNDER_LINKING))
continue;
if (check_fwstate(&iface->mlmepriv, WIFI_OP_CH_SWITCHING))
@ -183,7 +187,6 @@ inline int rtw_mi_get_ch_setting_union_no_self(_adapter *adapter, u8 *ch, u8 *bw
return rtw_mi_get_ch_setting_union_by_ifbmp(adapter_to_dvobj(adapter), 0xFF & ~BIT(adapter->iface_id), ch, bw, offset);
}
/* For now, not return union_ch/bw/offset */
void rtw_mi_status_by_ifbmp(struct dvobj_priv *dvobj, u8 ifbmp, struct mi_state *mstate)
{
_adapter *iface;
@ -198,7 +201,7 @@ void rtw_mi_status_by_ifbmp(struct dvobj_priv *dvobj, u8 ifbmp, struct mi_state
if (check_fwstate(&iface->mlmepriv, WIFI_STATION_STATE) == _TRUE) {
MSTATE_STA_NUM(mstate)++;
if (check_fwstate(&iface->mlmepriv, _FW_LINKED) == _TRUE) {
if (check_fwstate(&iface->mlmepriv, WIFI_ASOC_STATE) == _TRUE) {
MSTATE_STA_LD_NUM(mstate)++;
#ifdef CONFIG_TDLS
@ -210,12 +213,12 @@ void rtw_mi_status_by_ifbmp(struct dvobj_priv *dvobj, u8 ifbmp, struct mi_state
MSTATE_P2P_GC_NUM(mstate)++;
#endif
}
if (check_fwstate(&iface->mlmepriv, _FW_UNDER_LINKING) == _TRUE)
if (check_fwstate(&iface->mlmepriv, WIFI_UNDER_LINKING) == _TRUE)
MSTATE_STA_LG_NUM(mstate)++;
#ifdef CONFIG_AP_MODE
} else if (check_fwstate(&iface->mlmepriv, WIFI_AP_STATE) == _TRUE ) {
if (check_fwstate(&iface->mlmepriv, _FW_LINKED) == _TRUE) {
if (check_fwstate(&iface->mlmepriv, WIFI_ASOC_STATE) == _TRUE) {
MSTATE_AP_NUM(mstate)++;
if (iface->stapriv.asoc_sta_count > 2)
MSTATE_AP_LD_NUM(mstate)++;
@ -228,7 +231,7 @@ void rtw_mi_status_by_ifbmp(struct dvobj_priv *dvobj, u8 ifbmp, struct mi_state
#endif
} else if (check_fwstate(&iface->mlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE) == _TRUE
&& check_fwstate(&iface->mlmepriv, _FW_LINKED) == _TRUE
&& check_fwstate(&iface->mlmepriv, WIFI_ASOC_STATE) == _TRUE
) {
MSTATE_ADHOC_NUM(mstate)++;
if (iface->stapriv.asoc_sta_count > 2)
@ -236,7 +239,7 @@ void rtw_mi_status_by_ifbmp(struct dvobj_priv *dvobj, u8 ifbmp, struct mi_state
#ifdef CONFIG_RTW_MESH
} else if (check_fwstate(&iface->mlmepriv, WIFI_MESH_STATE) == _TRUE
&& check_fwstate(&iface->mlmepriv, _FW_LINKED) == _TRUE
&& check_fwstate(&iface->mlmepriv, WIFI_ASOC_STATE) == _TRUE
) {
MSTATE_MESH_NUM(mstate)++;
if (iface->stapriv.asoc_sta_count > 2)
@ -248,7 +251,7 @@ void rtw_mi_status_by_ifbmp(struct dvobj_priv *dvobj, u8 ifbmp, struct mi_state
if (check_fwstate(&iface->mlmepriv, WIFI_UNDER_WPS) == _TRUE)
MSTATE_WPS_NUM(mstate)++;
if (check_fwstate(&iface->mlmepriv, WIFI_SITE_MONITOR) == _TRUE) {
if (check_fwstate(&iface->mlmepriv, WIFI_UNDER_SURVEY) == _TRUE) {
MSTATE_SCAN_NUM(mstate)++;
if (mlmeext_scan_state(&iface->mlmeextpriv) != SCAN_DISABLE
@ -259,10 +262,10 @@ void rtw_mi_status_by_ifbmp(struct dvobj_priv *dvobj, u8 ifbmp, struct mi_state
#ifdef CONFIG_IOCTL_CFG80211
if (rtw_cfg80211_get_is_mgmt_tx(iface))
MSTATE_MGMT_TX_NUM(mstate)++;
#ifdef CONFIG_P2P
if (rtw_cfg80211_get_is_roch(iface) == _TRUE)
MSTATE_ROCH_NUM(mstate)++;
#endif
#endif /* CONFIG_IOCTL_CFG80211 */
#ifdef CONFIG_P2P
if (MLME_IS_PD(iface))
@ -286,7 +289,6 @@ inline void rtw_mi_status_no_others(_adapter *adapter, struct mi_state *mstate)
return rtw_mi_status_by_ifbmp(adapter_to_dvobj(adapter), BIT(adapter->iface_id), mstate);
}
/* For now, not handle union_ch/bw/offset */
inline void rtw_mi_status_merge(struct mi_state *d, struct mi_state *a)
{
d->sta_num += a->sta_num;
@ -367,7 +369,6 @@ inline void rtw_mi_update_iface_status(struct mlme_priv *pmlmepriv, sint state)
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
struct mi_state *iface_state = &dvobj->iface_state;
struct mi_state tmp_mstate;
u8 u_ch, u_offset, u_bw;
if (state == WIFI_MONITOR_STATE
|| state == 0xFFFFFFFF
@ -380,16 +381,6 @@ inline void rtw_mi_update_iface_status(struct mlme_priv *pmlmepriv, sint state)
rtw_mi_status(adapter, &tmp_mstate);
_rtw_memcpy(iface_state, &tmp_mstate, sizeof(struct mi_state));
if (rtw_mi_get_ch_setting_union(adapter, &u_ch, &u_bw, &u_offset))
rtw_mi_update_union_chan_inf(adapter , u_ch, u_offset , u_bw);
else {
if (0) {
dump_adapters_status(RTW_DBGDUMP , dvobj);
RTW_INFO("%s-[ERROR] cannot get union channel\n", __func__);
rtw_warn_on(1);
}
}
#ifdef DBG_IFACE_STATUS
DBG_IFACE_STATUS_DUMP(adapter);
#endif
@ -407,7 +398,7 @@ u8 rtw_mi_check_status(_adapter *adapter, u8 type)
switch (type) {
case MI_LINKED:
if (MSTATE_STA_LD_NUM(iface_state) || MSTATE_AP_NUM(iface_state) || MSTATE_ADHOC_NUM(iface_state) || MSTATE_MESH_NUM(iface_state)) /*check_fwstate(&iface->mlmepriv, _FW_LINKED)*/
if (MSTATE_STA_LD_NUM(iface_state) || MSTATE_AP_NUM(iface_state) || MSTATE_ADHOC_NUM(iface_state) || MSTATE_MESH_NUM(iface_state)) /*check_fwstate(&iface->mlmepriv, WIFI_ASOC_STATE)*/
ret = _TRUE;
break;
case MI_ASSOC:
@ -821,10 +812,11 @@ void rtw_mi_buddy_set_scan_deny(_adapter *adapter, u32 ms)
}
#endif /*CONFIG_SET_SCAN_DENY_TIMER*/
#ifdef CONFIG_AP_MODE
static u8 _rtw_mi_beacon_update(_adapter *padapter, void *data)
{
if (!MLME_IS_STA(padapter)
&& check_fwstate(&padapter->mlmepriv, _FW_LINKED) == _TRUE) {
&& check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE) == _TRUE) {
RTW_INFO(ADPT_FMT" - update_beacon\n", ADPT_ARG(padapter));
update_beacon(padapter, 0xFF, NULL, _TRUE, 0);
}
@ -840,23 +832,28 @@ void rtw_mi_buddy_beacon_update(_adapter *padapter)
{
_rtw_mi_process(padapter, _TRUE, NULL, _rtw_mi_beacon_update);
}
#endif /* CONFIG_AP_MODE */
static u8 _rtw_mi_hal_dump_macaddr(_adapter *padapter, void *data)
#ifndef CONFIG_MI_WITH_MBSSID_CAM
static u8 _rtw_mi_hal_dump_macaddr(_adapter *padapter, void *sel)
{
u8 mac_addr[ETH_ALEN] = {0};
rtw_hal_get_hwreg(padapter, HW_VAR_MAC_ADDR, mac_addr);
RTW_INFO(ADPT_FMT"MAC Address ="MAC_FMT"\n", ADPT_ARG(padapter), MAC_ARG(mac_addr));
RTW_PRINT_SEL(sel, ADPT_FMT"- hw port(%d) mac_addr ="MAC_FMT"\n",
ADPT_ARG(padapter), padapter->hw_port, MAC_ARG(mac_addr));
return _TRUE;
}
void rtw_mi_hal_dump_macaddr(_adapter *padapter)
void rtw_mi_hal_dump_macaddr(void *sel, _adapter *padapter)
{
_rtw_mi_process(padapter, _FALSE, NULL, _rtw_mi_hal_dump_macaddr);
_rtw_mi_process(padapter, _FALSE, sel, _rtw_mi_hal_dump_macaddr);
}
void rtw_mi_buddy_hal_dump_macaddr(_adapter *padapter)
void rtw_mi_buddy_hal_dump_macaddr(void *sel, _adapter *padapter)
{
_rtw_mi_process(padapter, _TRUE, NULL, _rtw_mi_hal_dump_macaddr);
_rtw_mi_process(padapter, _TRUE, sel, _rtw_mi_hal_dump_macaddr);
}
#endif
#ifdef CONFIG_PCI_HCI
static u8 _rtw_mi_xmit_tasklet_schedule(_adapter *padapter, void *data)
@ -879,36 +876,16 @@ void rtw_mi_buddy_xmit_tasklet_schedule(_adapter *padapter)
u8 _rtw_mi_busy_traffic_check(_adapter *padapter, void *data)
{
u32 passtime;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
bool check_sc_interval = *(bool *)data;
if (pmlmepriv->LinkDetectInfo.bBusyTraffic == _TRUE) {
if (check_sc_interval) {
/* Miracast can't do AP scan*/
passtime = rtw_get_passing_time_ms(pmlmepriv->lastscantime);
if (passtime > BUSY_TRAFFIC_SCAN_DENY_PERIOD) {
RTW_INFO(ADPT_FMT" bBusyTraffic == _TRUE\n", ADPT_ARG(padapter));
return _TRUE;
}
} else
return _TRUE;
}
return _FALSE;
return padapter->mlmepriv.LinkDetectInfo.bBusyTraffic;
}
u8 rtw_mi_busy_traffic_check(_adapter *padapter, bool check_sc_interval)
u8 rtw_mi_busy_traffic_check(_adapter *padapter)
{
bool in_data = check_sc_interval;
return _rtw_mi_process(padapter, _FALSE, &in_data, _rtw_mi_busy_traffic_check);
return _rtw_mi_process(padapter, _FALSE, NULL, _rtw_mi_busy_traffic_check);
}
u8 rtw_mi_buddy_busy_traffic_check(_adapter *padapter, bool check_sc_interval)
u8 rtw_mi_buddy_busy_traffic_check(_adapter *padapter)
{
bool in_data = check_sc_interval;
return _rtw_mi_process(padapter, _TRUE, &in_data, _rtw_mi_busy_traffic_check);
return _rtw_mi_process(padapter, _TRUE, NULL, _rtw_mi_busy_traffic_check);
}
static u8 _rtw_mi_check_mlmeinfo_state(_adapter *padapter, void *data)
{
@ -948,21 +925,21 @@ static void rtw_dbg_dump_fwstate(_adapter *padapter, sint state)
RTW_INFO(FUNC_ADPT_FMT"fwstate-%s\n", FUNC_ADPT_ARG(padapter), buf);
}
if (state & _FW_LINKED) {
if (state & WIFI_ASOC_STATE) {
_rtw_memset(buf, 0, 32);
sprintf(buf, "_FW_LINKED");
sprintf(buf, "WIFI_ASOC_STATE");
RTW_INFO(FUNC_ADPT_FMT"fwstate-%s\n", FUNC_ADPT_ARG(padapter), buf);
}
if (state & _FW_UNDER_LINKING) {
if (state & WIFI_UNDER_LINKING) {
_rtw_memset(buf, 0, 32);
sprintf(buf, "_FW_UNDER_LINKING");
sprintf(buf, "WIFI_UNDER_LINKING");
RTW_INFO(FUNC_ADPT_FMT"fwstate-%s\n", FUNC_ADPT_ARG(padapter), buf);
}
if (state & _FW_UNDER_SURVEY) {
if (state & WIFI_UNDER_SURVEY) {
_rtw_memset(buf, 0, 32);
sprintf(buf, "_FW_UNDER_SURVEY");
sprintf(buf, "WIFI_UNDER_SURVEY");
RTW_INFO(FUNC_ADPT_FMT"fwstate-%s\n", FUNC_ADPT_ARG(padapter), buf);
}
}
@ -1172,7 +1149,7 @@ u8 rtw_mi_sreset_adapter_hdl(_adapter *padapter, u8 bstart)
return _rtw_mi_process(padapter, _FALSE, &in_data, _rtw_mi_sreset_adapter_hdl);
}
#if defined(DBG_CONFIG_ERROR_RESET) && defined(CONFIG_CONCURRENT_MODE)
#if defined(CONFIG_AP_MODE) && defined(DBG_CONFIG_ERROR_RESET) && defined(CONFIG_CONCURRENT_MODE)
void rtw_mi_ap_info_restore(_adapter *adapter)
{
int i;
@ -1200,6 +1177,8 @@ u8 rtw_mi_buddy_sreset_adapter_hdl(_adapter *padapter, u8 bstart)
return _rtw_mi_process(padapter, _TRUE, &in_data, _rtw_mi_sreset_adapter_hdl);
}
#ifdef CONFIG_AP_MODE
static u8 _rtw_mi_tx_beacon_hdl(_adapter *adapter, void *data)
{
if ((MLME_IS_AP(adapter) || MLME_IS_MESH(adapter))
@ -1241,6 +1220,7 @@ u8 rtw_mi_buddy_set_tx_beacon_cmd(_adapter *padapter)
{
return _rtw_mi_process(padapter, _TRUE, NULL, _rtw_mi_set_tx_beacon_cmd);
}
#endif /* CONFIG_AP_MODE */
#ifdef CONFIG_P2P
static u8 _rtw_mi_p2p_chk_state(_adapter *adapter, void *data)

File diff suppressed because it is too large Load Diff

2772
core/rtw_mlme_ext.c Executable file → Normal file

File diff suppressed because it is too large Load Diff

View File

@ -237,6 +237,7 @@ s32 init_mp_priv(PADAPTER padapter)
pmppriv->pktInterval = 0;
pmppriv->pktLength = 1000;
pmppriv->bprocess_mp_mode = _FALSE;
pmppriv->efuse_update_file= _FALSE;
mp_init_xmit_attrib(&pmppriv->tx, padapter);
@ -392,7 +393,14 @@ void mpt_InitHWConfig(PADAPTER Adapter)
PlatformEFIOWrite2Byte(Adapter, REG_RXFLTMAP1_8814B, 0x2000);
}
#endif
#if defined(CONFIG_RTL8723F)
/* todo: 8723F not verify yet */
else if (IS_HARDWARE_TYPE_8723F(Adapter)) {
/* 8723F mac is similar with 8723D,
* but can't find 8723D here.
*/
}
#endif
}
static void PHY_IQCalibrate(PADAPTER padapter, u8 bReCovery)
@ -512,13 +520,15 @@ static void PHY_SetRFPathSwitch(PADAPTER padapter , BOOLEAN bMain) {
#endif
} else if (IS_HARDWARE_TYPE_8822C(padapter)) {
#ifdef CONFIG_RTL8822C
/* remove for MP EVM Fail, need to review by willis 20180809
phy_set_rf_path_switch_8822c(phydm, bMain);
*/
#endif
} else if (IS_HARDWARE_TYPE_8814B(padapter)) {
#ifdef CONFIG_RTL8814B
/* phy_set_rf_path_switch_8814b(phydm, bMain); */
#endif
} else if (IS_HARDWARE_TYPE_8723F(padapter)) {
#ifdef CONFIG_RTL8723F
phy_set_rf_path_switch_8723f(phydm, bMain);
#endif
}
}
@ -753,56 +763,60 @@ static void init_mp_data(PADAPTER padapter)
pDM_Odm->rf_calibrate_info.txpowertrack_control = _FALSE;
}
void MPT_PwrCtlDM(PADAPTER padapter, u32 bstart)
void MPT_PwrCtlDM(PADAPTER padapter, u32 trk_type)
{
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
struct dm_struct *pDM_Odm = &pHalData->odmpriv;
u32 rf_ability;
padapter->mppriv.tssitrk_on = bstart == 3;
padapter->mppriv.tssitrk_on = trk_type == 3;
if (bstart == 1) {
RTW_INFO("in MPT_PwrCtlDM start\n");
if (trk_type == 0) { /* thermal PwrTrk off*/
struct txpwrtrack_cfg c;
u8 chnl = 0 ;
rf_ability = ((u32)halrf_cmn_info_get(pDM_Odm, HALRF_CMNINFO_ABILITY)) | HAL_RF_TX_PWR_TRACK;
halrf_cmn_info_set(pDM_Odm, HALRF_CMNINFO_ABILITY, rf_ability);
halrf_set_pwr_track(pDM_Odm, bstart);
pDM_Odm->rf_calibrate_info.txpowertrack_control = _TRUE;
padapter->mppriv.mp_dm = 1;
} else {
RTW_INFO("in MPT_PwrCtlDM stop\n");
RTW_INFO("in Thermal tracking off\n");
rf_ability = ((u32)halrf_cmn_info_get(pDM_Odm, HALRF_CMNINFO_ABILITY)) & ~HAL_RF_TX_PWR_TRACK;
halrf_cmn_info_set(pDM_Odm, HALRF_CMNINFO_ABILITY, rf_ability);
halrf_set_pwr_track(pDM_Odm, bstart);
pDM_Odm->rf_calibrate_info.txpowertrack_control = _FALSE;
halrf_cmn_info_set(pDM_Odm, HALRF_CMNINFO_POWER_TRACK_CONTROL, trk_type);
halrf_set_pwr_track(pDM_Odm, FALSE);
pDM_Odm->rf_calibrate_info.txpowertrack_control = trk_type;
if (IS_HARDWARE_TYPE_8822C(padapter))
padapter->mppriv.mp_dm = 1; /* default enable dpk tracking */
else
padapter->mppriv.mp_dm = 0;
{
struct txpwrtrack_cfg c;
u8 chnl = 0 ;
_rtw_memset(&c, 0, sizeof(struct txpwrtrack_cfg));
configure_txpower_track(pDM_Odm, &c);
odm_clear_txpowertracking_state(pDM_Odm);
if (*c.odm_tx_pwr_track_set_pwr) {
if (pDM_Odm->support_ic_type == ODM_RTL8188F)
(*c.odm_tx_pwr_track_set_pwr)(pDM_Odm, MIX_MODE, RF_PATH_A, chnl);
else if (pDM_Odm->support_ic_type == ODM_RTL8723D) {
(*c.odm_tx_pwr_track_set_pwr)(pDM_Odm, BBSWING, RF_PATH_A, chnl);
SetTxPower(padapter);
} else if (pDM_Odm->support_ic_type == ODM_RTL8192F) {
(*c.odm_tx_pwr_track_set_pwr)(pDM_Odm, MIX_MODE, RF_PATH_A, chnl);
(*c.odm_tx_pwr_track_set_pwr)(pDM_Odm, MIX_MODE, RF_PATH_B, chnl);
} else {
(*c.odm_tx_pwr_track_set_pwr)(pDM_Odm, BBSWING, RF_PATH_A, chnl);
(*c.odm_tx_pwr_track_set_pwr)(pDM_Odm, BBSWING, RF_PATH_B, chnl);
}
_rtw_memset(&c, 0, sizeof(struct txpwrtrack_cfg));
configure_txpower_track(pDM_Odm, &c);
odm_clear_txpowertracking_state(pDM_Odm);
if (*c.odm_tx_pwr_track_set_pwr) {
if (pDM_Odm->support_ic_type == ODM_RTL8188F)
(*c.odm_tx_pwr_track_set_pwr)(pDM_Odm, MIX_MODE, RF_PATH_A, chnl);
else if (pDM_Odm->support_ic_type == ODM_RTL8723D) {
(*c.odm_tx_pwr_track_set_pwr)(pDM_Odm, BBSWING, RF_PATH_A, chnl);
SetTxPower(padapter);
} else if (pDM_Odm->support_ic_type == ODM_RTL8192F) {
(*c.odm_tx_pwr_track_set_pwr)(pDM_Odm, MIX_MODE, RF_PATH_A, chnl);
(*c.odm_tx_pwr_track_set_pwr)(pDM_Odm, MIX_MODE, RF_PATH_B, chnl);
} else {
(*c.odm_tx_pwr_track_set_pwr)(pDM_Odm, BBSWING, RF_PATH_A, chnl);
(*c.odm_tx_pwr_track_set_pwr)(pDM_Odm, BBSWING, RF_PATH_B, chnl);
}
}
return ;
}
rf_ability = ((u32)halrf_cmn_info_get(pDM_Odm, HALRF_CMNINFO_ABILITY)) | HAL_RF_TX_PWR_TRACK;
halrf_cmn_info_set(pDM_Odm, HALRF_CMNINFO_ABILITY, rf_ability);
halrf_cmn_info_set(pDM_Odm, HALRF_CMNINFO_POWER_TRACK_CONTROL, trk_type);
if (trk_type == 1 || trk_type == 3) /* Thermal PwrTrk ON , TSSI PwrTrk ON */
halrf_set_pwr_track(pDM_Odm, TRUE);
else
halrf_set_pwr_track(pDM_Odm, false);/* TSSI K */
pDM_Odm->rf_calibrate_info.txpowertrack_control = trk_type;
padapter->mppriv.mp_dm = 1;
}
@ -854,7 +868,7 @@ u32 mp_join(PADAPTER padapter, u8 mode)
goto end_of_mp_start_test;
/* init mp_start_test status */
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE) {
rtw_disassoc_cmd(padapter, 500, 0);
rtw_indicate_disconnect(padapter, 0, _FALSE);
rtw_free_assoc_resources_cmd(padapter, _TRUE, 0);
@ -863,7 +877,7 @@ u32 mp_join(PADAPTER padapter, u8 mode)
/*pmlmepriv->fw_state = WIFI_MP_STATE;*/
init_fwstate(pmlmepriv, WIFI_MP_STATE);
set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
set_fwstate(pmlmepriv, WIFI_UNDER_LINKING);
/* 3 2. create a new psta for mp driver */
/* clear psta in the cur_network, if any */
@ -892,8 +906,8 @@ u32 mp_join(PADAPTER padapter, u8 mode)
_rtw_memcpy(pnetwork, &padapter->registrypriv.dev_network, padapter->registrypriv.dev_network.Length);
rtw_indicate_connect(padapter);
_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
set_fwstate(pmlmepriv, _FW_LINKED);
_clr_fwstate_(pmlmepriv, WIFI_UNDER_LINKING);
set_fwstate(pmlmepriv, WIFI_ASOC_STATE);
end_of_mp_start_test:
@ -1074,7 +1088,7 @@ static void mpt_AdjustRFRegByRateByChan92CU(PADAPTER pAdapter, u8 RateIdx, u8 Ch
{
u8 eRFPath;
u32 rfReg0x26;
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter);
struct hal_spec_t *hal_spec = GET_HAL_SPEC(pAdapter);
if (RateIdx < MPT_RATE_6M) /* CCK rate,for 88cu */
@ -1106,7 +1120,7 @@ static void mpt_AdjustRFRegByRateByChan92CU(PADAPTER pAdapter, u8 RateIdx, u8 Ch
}
}
for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++)
for (eRFPath = 0; eRFPath < hal_spec->rf_reg_path_num; eRFPath++)
write_rfreg(pAdapter, eRFPath, RF_SYN_G2, rfReg0x26);
}
#endif
@ -1280,7 +1294,7 @@ static struct xmit_frame *alloc_mp_xmitframe(struct xmit_priv *pxmitpriv)
struct xmit_frame *pmpframe;
struct xmit_buf *pxmitbuf;
pmpframe = rtw_alloc_xmitframe(pxmitpriv);
pmpframe = rtw_alloc_xmitframe(pxmitpriv, 0);
if (pmpframe == NULL)
return NULL;
@ -2003,6 +2017,11 @@ void SetPacketTx(PADAPTER padapter)
rtl8814b_prepare_mp_txdesc(padapter, pmp_priv);
#endif /* CONFIG_RTL8814B */
#if defined(CONFIG_RTL8723F)
if (IS_HARDWARE_TYPE_8723F(padapter))
rtl8723f_prepare_mp_txdesc(padapter, pmp_priv);
#endif /* CONFIG_RTL8723F */
/* 3 4. make wlan header, make_wlanhdr() */
hdr = (struct rtw_ieee80211_hdr *)pkt_start;
set_frame_sub_type(&hdr->frame_ctl, pattrib->subtype);
@ -2122,6 +2141,7 @@ void SetPacketRx(PADAPTER pAdapter, u8 bStartRx, u8 bAB)
pHalData->ReceiveConfig |= RCR_APP_PHYST_RXFF;
#if defined(CONFIG_RTL8822B) || defined(CONFIG_RTL8821C) || defined(CONFIG_RTL8822C)
/* todo: 8723F */
write_bbreg(pAdapter, 0x550, BIT3, bEnable);
#endif
rtw_write16(pAdapter, REG_RXFLTMAP0, 0xFFEF); /* REG_RXFLTMAP0 (RX Filter Map Group 0) */
@ -2363,7 +2383,9 @@ static u32 rtw_GetPSDData(PADAPTER pAdapter, u32 point)
{
u32 psd_val = 0;
#if defined(CONFIG_RTL8812A) || defined(CONFIG_RTL8821A) || defined(CONFIG_RTL8814A) || defined(CONFIG_RTL8822B) || defined(CONFIG_RTL8821C) || defined(CONFIG_RTL8822C)
#if defined(CONFIG_RTL8812A) || defined(CONFIG_RTL8821A) || defined(CONFIG_RTL8814A) \
|| defined(CONFIG_RTL8822B) || defined(CONFIG_RTL8821C)
u16 psd_reg = 0x910;
u16 psd_regL = 0xF44;
#else
@ -2438,12 +2460,12 @@ u32 mp_query_psd(PADAPTER pAdapter, u8 *data)
data[0] = '\0';
pdata = data;
if (psd_stop > 1536 || psd_stop < 1) {
if (psd_stop > 1920 || psd_stop < 1) {
rtw_warn_on(1);
psd_stop = 1536;
psd_stop = 1920;
}
if (IS_HARDWARE_TYPE_8822C(pAdapter)) {
if (IS_HARDWARE_TYPE_8822C(pAdapter) || IS_HARDWARE_TYPE_8723F(pAdapter)) {
u32 *psdbuf = rtw_zmalloc(sizeof(u32)*256);
if (psdbuf == NULL) {

View File

@ -178,6 +178,11 @@ void rtw_odm_releasespinlock(_adapter *adapter, enum rt_spinlock_type type)
}
}
s16 rtw_odm_get_tx_power_mbm(struct dm_struct *dm, u8 rfpath, u8 rate, u8 bw, u8 cch)
{
return phy_get_txpwr_single_mbm(dm->adapter, rfpath, mgn_rate_to_rs(rate), rate, bw, cch, 0, 0, 0, NULL);
}
#ifdef CONFIG_DFS_MASTER
inline void rtw_odm_radar_detect_reset(_adapter *adapter)
{
@ -200,6 +205,20 @@ inline BOOLEAN rtw_odm_radar_detect(_adapter *adapter)
return phydm_radar_detect(adapter_to_phydm(adapter));
}
static enum phydm_dfs_region_domain _rtw_dfs_regd_to_phydm[] = {
[RTW_DFS_REGD_NONE] = PHYDM_DFS_DOMAIN_UNKNOWN,
[RTW_DFS_REGD_FCC] = PHYDM_DFS_DOMAIN_FCC,
[RTW_DFS_REGD_MKK] = PHYDM_DFS_DOMAIN_MKK,
[RTW_DFS_REGD_ETSI] = PHYDM_DFS_DOMAIN_ETSI,
};
#define rtw_dfs_regd_to_phydm(region) (((region) >= RTW_DFS_REGD_NUM) ? _rtw_dfs_regd_to_phydm[RTW_DFS_REGD_NONE] : _rtw_dfs_regd_to_phydm[(region)])
void rtw_odm_update_dfs_region(struct dvobj_priv *dvobj)
{
odm_cmn_info_init(dvobj_to_phydm(dvobj), ODM_CMNINFO_DFS_REGION_DOMAIN, rtw_dfs_regd_to_phydm(rtw_rfctl_get_dfs_domain(dvobj_to_rfctl(dvobj))));
}
inline u8 rtw_odm_radar_detect_polling_int_ms(struct dvobj_priv *dvobj)
{
return phydm_dfs_polling_time(dvobj_to_phydm(dvobj));

View File

@ -598,7 +598,7 @@ u32 build_beacon_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
/* Value: */
/* Associated BSSID */
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
else
_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
@ -710,7 +710,7 @@ u32 build_probe_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
/* Value: */
/* Associated BSSID */
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
else
_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
@ -853,7 +853,7 @@ u32 build_probe_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 tunnel
/* Value: */
/* Associated BSSID */
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
else
_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
@ -1007,7 +1007,7 @@ u32 build_assoc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
/* Value: */
/* Associated BSSID */
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
else
_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
@ -1106,7 +1106,7 @@ u32 build_assoc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
/* Value: */
/* Associated BSSID */
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
else
_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
@ -1205,7 +1205,7 @@ u32 build_nego_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
/* Value: */
/* Associated BSSID */
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
else
_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
@ -1304,7 +1304,7 @@ u32 build_nego_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
/* Value: */
/* Associated BSSID */
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
else
_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
@ -1404,7 +1404,7 @@ u32 build_nego_confirm_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
/* Value: */
/* Associated BSSID */
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
else
_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
@ -1504,7 +1504,7 @@ u32 build_invitation_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
/* Value: */
/* Associated BSSID */
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
else
_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
@ -1617,7 +1617,7 @@ u32 build_invitation_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
/* Value: */
/* Associated BSSID */
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
else
_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
@ -1730,7 +1730,7 @@ u32 build_provdisc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
/* Value: */
/* Associated BSSID */
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
else
_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
@ -1830,7 +1830,7 @@ u32 build_provdisc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
/* Value: */
/* Associated BSSID */
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
else
_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
@ -2911,6 +2911,7 @@ u8 process_p2p_group_negotation_confirm(struct wifidirect_info *pwdinfo, u8 *pfr
{
#ifdef CONFIG_CONCURRENT_MODE
_adapter *padapter = pwdinfo->padapter;
struct roch_info *prochinfo = &padapter->rochinfo;
#endif
u8 *ies;
u32 ies_len;
@ -2956,7 +2957,7 @@ u8 process_p2p_group_negotation_confirm(struct wifidirect_info *pwdinfo, u8 *pfr
if (rtw_mi_check_status(padapter, MI_LINKED)
&& padapter->registrypriv.full_ch_in_p2p_handshake == 0) {
/* Switch back to the AP channel soon. */
_set_timer(&pwdinfo->ap_p2p_switch_timer, 100);
_set_timer(&prochinfo->ap_roch_ch_switch_timer, 100);
}
#endif
} else {
@ -3029,8 +3030,6 @@ void find_phase_handler(_adapter *padapter)
}
void p2p_concurrent_handler(_adapter *padapter);
void restore_p2p_state_handler(_adapter *padapter)
{
struct wifidirect_info *pwdinfo = &padapter->wdinfo;
@ -3055,7 +3054,7 @@ void restore_p2p_state_handler(_adapter *padapter)
if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
#ifdef CONFIG_CONCURRENT_MODE
p2p_concurrent_handler(padapter);
rtw_concurrent_handler(padapter);
#else
/* In the P2P client mode, the driver should not switch back to its listen channel */
/* because this P2P client should stay at the operating channel of P2P GO. */
@ -3102,344 +3101,7 @@ void pre_tx_negoreq_handler(_adapter *padapter)
}
#ifdef CONFIG_CONCURRENT_MODE
void p2p_concurrent_handler(_adapter *padapter)
{
struct wifidirect_info *pwdinfo = &padapter->wdinfo;
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
u8 val8;
#ifdef CONFIG_IOCTL_CFG80211
if (pwdinfo->driver_interface == DRIVER_CFG80211
&& !rtw_cfg80211_get_is_roch(padapter))
return;
#endif
if (rtw_mi_check_status(padapter, MI_LINKED)) {
u8 union_ch = rtw_mi_get_union_chan(padapter);
u8 union_bw = rtw_mi_get_union_bw(padapter);
u8 union_offset = rtw_mi_get_union_offset(padapter);
pwdinfo->operating_channel = union_ch;
if (pwdinfo->driver_interface == DRIVER_CFG80211) {
RTW_INFO("%s, switch ch back to union=%u,%u, %u\n"
, __func__, union_ch, union_bw, union_offset);
set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
rtw_back_opch(padapter);
} else if (pwdinfo->driver_interface == DRIVER_WEXT) {
if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
/* Now, the driver stays on the AP's channel. */
/* If the pwdinfo->ext_listen_period = 0, that means the P2P listen state is not available on listen channel. */
if (pwdinfo->ext_listen_period > 0) {
RTW_INFO("[%s] P2P_STATE_IDLE, ext_listen_period = %d\n", __FUNCTION__, pwdinfo->ext_listen_period);
if (union_ch != pwdinfo->listen_channel) {
rtw_leave_opch(padapter);
set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
}
rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
if (!rtw_mi_check_mlmeinfo_state(padapter, WIFI_FW_AP_STATE)) {
val8 = 1;
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
}
/* Todo: To check the value of pwdinfo->ext_listen_period is equal to 0 or not. */
_set_timer(&pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_period);
}
} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN) ||
rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL) ||
(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _FALSE) ||
rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ)) {
/* Now, the driver is in the listen state of P2P mode. */
RTW_INFO("[%s] P2P_STATE_IDLE, ext_listen_interval = %d\n", __FUNCTION__, pwdinfo->ext_listen_interval);
/* Commented by Albert 2012/11/01 */
/* If the AP's channel is the same as the listen channel, we should still be in the listen state */
/* Other P2P device is still able to find this device out even this device is in the AP's channel. */
/* So, configure this device to be able to receive the probe request frame and set it to listen state. */
if (union_ch != pwdinfo->listen_channel) {
set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
if (!rtw_mi_check_status(padapter, MI_AP_MODE)) {
val8 = 0;
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
}
rtw_p2p_set_state(pwdinfo, P2P_STATE_IDLE);
rtw_back_opch(padapter);
}
/* Todo: To check the value of pwdinfo->ext_listen_interval is equal to 0 or not. */
_set_timer(&pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_interval);
} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK)) {
/* The driver had finished the P2P handshake successfully. */
val8 = 0;
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
rtw_back_opch(padapter);
} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
val8 = 1;
set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
issue_probereq_p2p(padapter, NULL);
_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _TRUE) {
val8 = 1;
set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
issue_probereq_p2p(padapter, NULL);
_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ) && pwdinfo->invitereq_info.benable == _TRUE) {
/*
val8 = 1;
set_channel_bwmode(padapter, , HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
issue_probereq_p2p(padapter, NULL);
_set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
*/
}
}
} else {
/* In p2p+softap. When in P2P_STATE_GONEGO_OK, not back to listen channel.*/
if (!rtw_p2p_chk_state(pwdinfo , P2P_STATE_GONEGO_OK) || padapter->registrypriv.full_ch_in_p2p_handshake == 0)
set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
else
RTW_INFO("%s, buddy not linked, go nego ok, not back to listen channel\n", __func__);
}
}
#endif
#ifdef CONFIG_IOCTL_CFG80211
u8 roch_stay_in_cur_chan(_adapter *padapter)
{
int i;
_adapter *iface;
struct mlme_priv *pmlmepriv;
struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
u8 rst = _FALSE;
for (i = 0; i < dvobj->iface_nums; i++) {
iface = dvobj->padapters[i];
if (iface) {
pmlmepriv = &iface->mlmepriv;
if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING | WIFI_UNDER_WPS | WIFI_UNDER_KEY_HANDSHAKE) == _TRUE) {
RTW_INFO(ADPT_FMT"- _FW_UNDER_LINKING |WIFI_UNDER_WPS | WIFI_UNDER_KEY_HANDSHAKE (mlme state:0x%x)\n",
ADPT_ARG(iface), get_fwstate(&iface->mlmepriv));
rst = _TRUE;
break;
}
#ifdef CONFIG_AP_MODE
if (MLME_IS_AP(iface) || MLME_IS_MESH(iface)) {
if (rtw_ap_sta_states_check(iface) == _TRUE) {
rst = _TRUE;
break;
}
}
#endif
}
}
return rst;
}
static int ro_ch_handler(_adapter *adapter, u8 *buf)
{
int ret = H2C_SUCCESS;
struct p2p_roch_parm *roch_parm = (struct p2p_roch_parm *)buf;
struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);
struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &adapter->cfg80211_wdinfo;
#ifdef CONFIG_CONCURRENT_MODE
struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
#ifdef RTW_ROCH_BACK_OP
struct wifidirect_info *pwdinfo = &adapter->wdinfo;
#endif
#endif
u8 ready_on_channel = _FALSE;
u8 remain_ch;
unsigned int duration;
_enter_critical_mutex(&pwdev_priv->roch_mutex, NULL);
if (rtw_cfg80211_get_is_roch(adapter) != _TRUE)
goto exit;
remain_ch = (u8)ieee80211_frequency_to_channel(roch_parm->ch.center_freq);
duration = roch_parm->duration;
RTW_INFO(FUNC_ADPT_FMT" ch:%u duration:%d, cookie:0x%llx\n"
, FUNC_ADPT_ARG(adapter), remain_ch, roch_parm->duration, roch_parm->cookie);
if (roch_parm->wdev && roch_parm->cookie) {
if (pcfg80211_wdinfo->ro_ch_wdev != roch_parm->wdev) {
RTW_WARN(FUNC_ADPT_FMT" ongoing wdev:%p, wdev:%p\n"
, FUNC_ADPT_ARG(adapter), pcfg80211_wdinfo->ro_ch_wdev, roch_parm->wdev);
rtw_warn_on(1);
}
if (pcfg80211_wdinfo->remain_on_ch_cookie != roch_parm->cookie) {
RTW_WARN(FUNC_ADPT_FMT" ongoing cookie:0x%llx, cookie:0x%llx\n"
, FUNC_ADPT_ARG(adapter), pcfg80211_wdinfo->remain_on_ch_cookie, roch_parm->cookie);
rtw_warn_on(1);
}
}
if (roch_stay_in_cur_chan(adapter) == _TRUE) {
remain_ch = rtw_mi_get_union_chan(adapter);
RTW_INFO(FUNC_ADPT_FMT" stay in union ch:%d\n", FUNC_ADPT_ARG(adapter), remain_ch);
}
#ifdef CONFIG_CONCURRENT_MODE
if (rtw_mi_check_status(adapter, MI_LINKED) && (0 != rtw_mi_get_union_chan(adapter))) {
if ((remain_ch != rtw_mi_get_union_chan(adapter)) && !check_fwstate(&adapter->mlmepriv, _FW_LINKED)) {
if (remain_ch != pmlmeext->cur_channel
#ifdef RTW_ROCH_BACK_OP
|| ATOMIC_READ(&pwdev_priv->switch_ch_to) == 1
#endif
) {
rtw_leave_opch(adapter);
#ifdef RTW_ROCH_BACK_OP
RTW_INFO("%s, set switch ch timer, duration=%d\n", __func__, duration - pwdinfo->ext_listen_interval);
ATOMIC_SET(&pwdev_priv->switch_ch_to, 0);
_set_timer(&pwdinfo->ap_p2p_switch_timer, duration - pwdinfo->ext_listen_interval);
#endif
}
}
ready_on_channel = _TRUE;
} else
#endif /* CONFIG_CONCURRENT_MODE */
{
if (remain_ch != rtw_get_oper_ch(adapter))
ready_on_channel = _TRUE;
}
if (ready_on_channel == _TRUE) {
#ifndef RTW_SINGLE_WIPHY
if (!check_fwstate(&adapter->mlmepriv, _FW_LINKED))
#endif
{
#ifdef CONFIG_CONCURRENT_MODE
if (rtw_get_oper_ch(adapter) != remain_ch)
#endif
{
/* if (!padapter->mlmepriv.LinkDetectInfo.bBusyTraffic) */
set_channel_bwmode(adapter, remain_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
}
}
}
#ifdef CONFIG_BT_COEXIST
rtw_btcoex_ScanNotify(adapter, _TRUE);
#endif
RTW_INFO("%s, set ro ch timer, duration=%d\n", __func__, duration);
_set_timer(&pcfg80211_wdinfo->remain_on_ch_timer, duration);
exit:
_exit_critical_mutex(&pwdev_priv->roch_mutex, NULL);
return ret;
}
static int cancel_ro_ch_handler(_adapter *padapter, u8 *buf)
{
int ret = H2C_SUCCESS;
struct p2p_roch_parm *roch_parm = (struct p2p_roch_parm *)buf;
struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
struct wireless_dev *wdev;
struct wifidirect_info *pwdinfo = &padapter->wdinfo;
u8 ch, bw, offset;
_enter_critical_mutex(&pwdev_priv->roch_mutex, NULL);
if (rtw_cfg80211_get_is_roch(padapter) != _TRUE)
goto exit;
if (roch_parm->wdev && roch_parm->cookie) {
if (pcfg80211_wdinfo->ro_ch_wdev != roch_parm->wdev) {
RTW_WARN(FUNC_ADPT_FMT" ongoing wdev:%p, wdev:%p\n"
, FUNC_ADPT_ARG(padapter), pcfg80211_wdinfo->ro_ch_wdev, roch_parm->wdev);
rtw_warn_on(1);
}
if (pcfg80211_wdinfo->remain_on_ch_cookie != roch_parm->cookie) {
RTW_WARN(FUNC_ADPT_FMT" ongoing cookie:0x%llx, cookie:0x%llx\n"
, FUNC_ADPT_ARG(padapter), pcfg80211_wdinfo->remain_on_ch_cookie, roch_parm->cookie);
rtw_warn_on(1);
}
}
#if defined(RTW_ROCH_BACK_OP) && defined(CONFIG_CONCURRENT_MODE)
_cancel_timer_ex(&pwdinfo->ap_p2p_switch_timer);
ATOMIC_SET(&pwdev_priv->switch_ch_to, 1);
#endif
if (rtw_mi_get_ch_setting_union(padapter, &ch, &bw, &offset) != 0) {
if (0)
RTW_INFO(FUNC_ADPT_FMT" back to linked/linking union - ch:%u, bw:%u, offset:%u\n",
FUNC_ADPT_ARG(padapter), ch, bw, offset);
} else if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->listen_channel) {
ch = pwdinfo->listen_channel;
bw = CHANNEL_WIDTH_20;
offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
if (0)
RTW_INFO(FUNC_ADPT_FMT" back to listen ch - ch:%u, bw:%u, offset:%u\n",
FUNC_ADPT_ARG(padapter), ch, bw, offset);
} else {
ch = pcfg80211_wdinfo->restore_channel;
bw = CHANNEL_WIDTH_20;
offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
if (0)
RTW_INFO(FUNC_ADPT_FMT" back to restore ch - ch:%u, bw:%u, offset:%u\n",
FUNC_ADPT_ARG(padapter), ch, bw, offset);
}
set_channel_bwmode(padapter, ch, offset, bw);
rtw_back_opch(padapter);
rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
#ifdef CONFIG_DEBUG_CFG80211
RTW_INFO("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));
#endif
wdev = pcfg80211_wdinfo->ro_ch_wdev;
rtw_cfg80211_set_is_roch(padapter, _FALSE);
pcfg80211_wdinfo->ro_ch_wdev = NULL;
rtw_cfg80211_set_last_ro_ch_time(padapter);
rtw_cfg80211_remain_on_channel_expired(wdev
, pcfg80211_wdinfo->remain_on_ch_cookie
, &pcfg80211_wdinfo->remain_on_ch_channel
, pcfg80211_wdinfo->remain_on_ch_type, GFP_KERNEL);
RTW_INFO("cfg80211_remain_on_channel_expired cookie:0x%llx\n"
, pcfg80211_wdinfo->remain_on_ch_cookie);
#ifdef CONFIG_BT_COEXIST
rtw_btcoex_ScanNotify(padapter, _FALSE);
#endif
exit:
_exit_critical_mutex(&pwdev_priv->roch_mutex, NULL);
return ret;
}
static void ro_ch_timer_process(void *FunctionContext)
{
_adapter *adapter = (_adapter *)FunctionContext;
p2p_cancel_roch_cmd(adapter, 0, NULL, 0);
}
#if 0
static void rtw_change_p2pie_op_ch(_adapter *padapter, const u8 *frame_body, u32 len, u8 ch)
@ -4275,15 +3937,6 @@ int rtw_p2p_check_frames(_adapter *padapter, const u8 *buf, u32 len, u8 tx)
return is_p2p_frame;
}
void rtw_init_cfg80211_wifidirect_info(_adapter *padapter)
{
struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
_rtw_memset(pcfg80211_wdinfo, 0x00, sizeof(struct cfg80211_wifidirect_info));
rtw_init_timer(&pcfg80211_wdinfo->remain_on_ch_timer, padapter, ro_ch_timer_process, padapter);
}
#endif /* CONFIG_IOCTL_CFG80211 */
s32 p2p_protocol_wk_hdl(_adapter *padapter, int intCmdType, u8 *buf)
@ -4302,7 +3955,7 @@ s32 p2p_protocol_wk_hdl(_adapter *padapter, int intCmdType, u8 *buf)
case P2P_PRE_TX_PROVDISC_PROCESS_WK:
#ifdef CONFIG_CONCURRENT_MODE
if (rtw_mi_check_status(padapter, MI_LINKED))
p2p_concurrent_handler(padapter);
rtw_concurrent_handler(padapter);
else
pre_tx_provdisc_handler(padapter);
#else
@ -4313,7 +3966,7 @@ s32 p2p_protocol_wk_hdl(_adapter *padapter, int intCmdType, u8 *buf)
case P2P_PRE_TX_INVITEREQ_PROCESS_WK:
#ifdef CONFIG_CONCURRENT_MODE
if (rtw_mi_check_status(padapter, MI_LINKED))
p2p_concurrent_handler(padapter);
rtw_concurrent_handler(padapter);
else
pre_tx_invitereq_handler(padapter);
#else
@ -4324,7 +3977,7 @@ s32 p2p_protocol_wk_hdl(_adapter *padapter, int intCmdType, u8 *buf)
case P2P_PRE_TX_NEGOREQ_PROCESS_WK:
#ifdef CONFIG_CONCURRENT_MODE
if (rtw_mi_check_status(padapter, MI_LINKED))
p2p_concurrent_handler(padapter);
rtw_concurrent_handler(padapter);
else
pre_tx_negoreq_handler(padapter);
#else
@ -4332,21 +3985,6 @@ s32 p2p_protocol_wk_hdl(_adapter *padapter, int intCmdType, u8 *buf)
#endif
break;
#ifdef CONFIG_CONCURRENT_MODE
case P2P_AP_P2P_CH_SWITCH_PROCESS_WK:
p2p_concurrent_handler(padapter);
break;
#endif
#ifdef CONFIG_IOCTL_CFG80211
case P2P_RO_CH_WK:
ret = ro_ch_handler(padapter, buf);
break;
case P2P_CANCEL_RO_CH_WK:
ret = cancel_ro_ch_handler(padapter, buf);
break;
#endif
default:
rtw_warn_on(1);
break;
@ -4499,13 +4137,16 @@ void p2p_ps_wk_hdl(_adapter *padapter, u8 p2p_ps_state)
rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
#ifdef CONFIG_LPS
if (pwdinfo->opp_ps == 1) {
if (pwrpriv->smart_ps == 0) {
pwrpriv->smart_ps = 2;
if (pwrpriv->pwr_mode != PS_MODE_ACTIVE)
rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&(pwrpriv->pwr_mode)));
rtw_exec_lps(padapter, pwrpriv->pwr_mode);
}
}
#endif /* CONFIG_LPS */
pwdinfo->noa_index = 0;
pwdinfo->ctwindow = 0;
pwdinfo->opp_ps = 0;
@ -4519,7 +4160,7 @@ void p2p_ps_wk_hdl(_adapter *padapter, u8 p2p_ps_state)
_exit_pwrlock(&adapter_to_pwrctl(padapter)->lock);
if ((ps_deny & (PS_DENY_SCAN | PS_DENY_JOIN))
|| rtw_mi_check_fwstate(padapter, (_FW_UNDER_SURVEY | _FW_UNDER_LINKING))) {
|| rtw_mi_check_fwstate(padapter, (WIFI_UNDER_SURVEY | WIFI_UNDER_LINKING))) {
pwdinfo->p2p_ps_mode = P2P_PS_NONE;
RTW_DBG(FUNC_ADPT_FMT" Block P2P PS under site survey or LINKING\n", FUNC_ADPT_ARG(padapter));
return;
@ -4536,14 +4177,17 @@ void p2p_ps_wk_hdl(_adapter *padapter, u8 p2p_ps_state)
#endif /* CONFIG_MCC_MODE */
pwdinfo->p2p_ps_state = p2p_ps_state;
#ifdef CONFIG_LPS
if (pwdinfo->ctwindow > 0) {
if (pwrpriv->smart_ps != 0) {
pwrpriv->smart_ps = 0;
RTW_INFO("%s(): Enter CTW, change SmartPS\n", __FUNCTION__);
if (pwrpriv->pwr_mode != PS_MODE_ACTIVE)
rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&(pwrpriv->pwr_mode)));
rtw_exec_lps(padapter, pwrpriv->pwr_mode);
}
}
#endif /* CONFIG_LPS */
rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
}
break;
@ -4601,7 +4245,7 @@ u8 p2p_ps_wk_cmd(_adapter *padapter, u8 p2p_ps_state, u8 enqueue)
pdrvextra_cmd_parm->size = 0;
pdrvextra_cmd_parm->pbuf = NULL;
init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
res = rtw_enqueue_cmd(pcmdpriv, ph2c);
} else
@ -4708,26 +4352,6 @@ static void find_phase_timer_process(void *FunctionContext)
p2p_protocol_wk_cmd(adapter, P2P_FIND_PHASE_WK);
}
#ifdef CONFIG_CONCURRENT_MODE
void ap_p2p_switch_timer_process(void *FunctionContext)
{
_adapter *adapter = (_adapter *)FunctionContext;
struct wifidirect_info *pwdinfo = &adapter->wdinfo;
#ifdef CONFIG_IOCTL_CFG80211
struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);
#endif
if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
return;
#ifdef CONFIG_IOCTL_CFG80211
ATOMIC_SET(&pwdev_priv->switch_ch_to, 1);
#endif
p2p_protocol_wk_cmd(adapter, P2P_AP_P2P_CH_SWITCH_PROCESS_WK);
}
#endif
void reset_global_wifidirect_info(_adapter *padapter)
{
struct wifidirect_info *pwdinfo;
@ -4959,9 +4583,6 @@ void rtw_init_wifidirect_timers(_adapter *padapter)
rtw_init_timer(&pwdinfo->pre_tx_scan_timer, padapter, pre_tx_scan_timer_process, padapter);
rtw_init_timer(&pwdinfo->reset_ch_sitesurvey, padapter, reset_ch_sitesurvey_timer_process, padapter);
rtw_init_timer(&pwdinfo->reset_ch_sitesurvey2, padapter, reset_ch_sitesurvey_timer_process2, padapter);
#ifdef CONFIG_CONCURRENT_MODE
rtw_init_timer(&pwdinfo->ap_p2p_switch_timer, padapter, ap_p2p_switch_timer_process, padapter);
#endif
}
void rtw_init_wifidirect_addrs(_adapter *padapter, u8 *dev_addr, u8 *iface_addr)
@ -5288,6 +4909,9 @@ int rtw_p2p_enable(_adapter *padapter, enum P2P_ROLE role)
{
int ret = _SUCCESS;
struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
#ifdef CONFIG_CONCURRENT_MODE
struct roch_info *prochinfo = &padapter->rochinfo;
#endif
if (role == P2P_ROLE_DEVICE || role == P2P_ROLE_CLIENT || role == P2P_ROLE_GO) {
#if defined(CONFIG_CONCURRENT_MODE) && (!defined(RTW_P2P_GROUP_INTERFACE) || !RTW_P2P_GROUP_INTERFACE)
@ -5351,7 +4975,7 @@ int rtw_p2p_enable(_adapter *padapter, enum P2P_ROLE role)
reset_ch_sitesurvey_timer_process(padapter);
reset_ch_sitesurvey_timer_process2(padapter);
#ifdef CONFIG_CONCURRENT_MODE
_cancel_timer_ex(&pwdinfo->ap_p2p_switch_timer);
_cancel_timer_ex(&prochinfo->ap_roch_ch_switch_timer);
#endif
rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_NONE);

View File

@ -94,9 +94,9 @@ void _ips_enter(_adapter *padapter)
if (pwrpriv->ips_mode == IPS_LEVEL_2)
pwrpriv->bkeepfwalive = _TRUE;
#ifdef CONFIG_RTW_CFGVEDNOR_LLSTATS
#ifdef CONFIG_RTW_CFGVENDOR_LLSTATS
pwrpriv->pwr_saving_start_time = rtw_get_current_time();
#endif /* CONFIG_RTW_CFGVEDNOR_LLSTATS */
#endif /* CONFIG_RTW_CFGVENDOR_LLSTATS */
rtw_ips_pwr_down(padapter);
pwrpriv->rf_pwrstate = rf_off;
@ -138,9 +138,9 @@ int _ips_leave(_adapter *padapter)
if (result == _SUCCESS)
pwrpriv->rf_pwrstate = rf_on;
#ifdef CONFIG_RTW_CFGVEDNOR_LLSTATS
#ifdef CONFIG_RTW_CFGVENDOR_LLSTATS
pwrpriv->pwr_saving_time += rtw_get_passing_time_ms(pwrpriv->pwr_saving_start_time);
#endif /* CONFIG_RTW_CFGVEDNOR_LLSTATS */
#endif /* CONFIG_RTW_CFGVENDOR_LLSTATS */
RTW_PRINT("nolinked power save leave\n");
@ -192,11 +192,6 @@ int ips_leave(_adapter *padapter)
}
#endif /* CONFIG_IPS */
#ifdef CONFIG_AUTOSUSPEND
extern void autosuspend_enter(_adapter *padapter);
extern int autoresume_enter(_adapter *padapter);
#endif
#ifdef SUPPORT_HW_RFOFF_DETECTED
int rtw_hw_suspend(_adapter *padapter);
int rtw_hw_resume(_adapter *padapter);
@ -232,12 +227,12 @@ bool rtw_pwr_unassociated_idle(_adapter *adapter)
#ifdef CONFIG_P2P
pwdinfo = &(iface->wdinfo);
#endif
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE | WIFI_SITE_MONITOR)
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE | WIFI_UNDER_SURVEY)
|| check_fwstate(pmlmepriv, WIFI_UNDER_LINKING | WIFI_UNDER_WPS)
|| MLME_IS_AP(iface)
|| MLME_IS_MESH(iface)
|| check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE)
#if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211)
#if defined(CONFIG_IOCTL_CFG80211)
|| rtw_cfg80211_get_is_roch(iface) == _TRUE
|| (rtw_cfg80211_is_ro_ch_once(adapter)
&& rtw_cfg80211_get_last_ro_ch_passing_ms(adapter) < 3000)
@ -290,8 +285,10 @@ void rtw_ps_processor(_adapter *padapter)
ps_deny = rtw_ps_deny_get(padapter);
_exit_pwrlock(&adapter_to_pwrctl(padapter)->lock);
if (ps_deny != 0) {
RTW_INFO(FUNC_ADPT_FMT ": ps_deny=0x%08X, skip power save!\n",
FUNC_ADPT_ARG(padapter), ps_deny);
if (!MLME_IS_MONITOR(padapter)) {
RTW_INFO(FUNC_ADPT_FMT ": ps_deny=0x%08X, skip power save!\n",
FUNC_ADPT_ARG(padapter), ps_deny);
}
goto exit;
}
@ -309,43 +306,22 @@ void rtw_ps_processor(_adapter *padapter)
/* RTW_INFO("==> fw report state(0x%x)\n",rtw_read8(padapter,0x1ca)); */
if (pwrpriv->bHWPwrPindetect) {
#ifdef CONFIG_AUTOSUSPEND
if (padapter->registrypriv.usbss_enable) {
if (pwrpriv->rf_pwrstate == rf_on) {
if (padapter->net_closed == _TRUE)
pwrpriv->ps_flag = _TRUE;
rfpwrstate = RfOnOffDetect(padapter);
RTW_INFO("@@@@- #2 %s==> rfstate:%s\n", __FUNCTION__, (rfpwrstate == rf_on) ? "rf_on" : "rf_off");
rfpwrstate = RfOnOffDetect(padapter);
RTW_INFO("@@@@- #1 %s==> rfstate:%s\n", __FUNCTION__, (rfpwrstate == rf_on) ? "rf_on" : "rf_off");
if (rfpwrstate != pwrpriv->rf_pwrstate) {
if (rfpwrstate == rf_off) {
pwrpriv->change_rfpwrstate = rf_off;
pwrpriv->bkeepfwalive = _TRUE;
pwrpriv->brfoffbyhw = _TRUE;
autosuspend_enter(padapter);
}
}
}
} else
#endif /* CONFIG_AUTOSUSPEND */
{
rfpwrstate = RfOnOffDetect(padapter);
RTW_INFO("@@@@- #2 %s==> rfstate:%s\n", __FUNCTION__, (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);
}
RTW_INFO("current rf_pwrstate(%s)\n", (pwrpriv->rf_pwrstate == rf_off) ? "rf_off" : "rf_on");
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);
}
RTW_INFO("current rf_pwrstate(%s)\n", (pwrpriv->rf_pwrstate == rf_off) ? "rf_off" : "rf_on");
}
pwrpriv->pwr_state_check_cnts++;
}
#endif /* SUPPORT_HW_RFOFF_DETECTED */
@ -358,41 +334,12 @@ void rtw_ps_processor(_adapter *padapter)
if ((pwrpriv->rf_pwrstate == rf_on) && ((pwrpriv->pwr_state_check_cnts % 4) == 0)) {
RTW_INFO("==>%s .fw_state(%x)\n", __FUNCTION__, get_fwstate(pmlmepriv));
#if defined(CONFIG_BT_COEXIST) && defined (CONFIG_AUTOSUSPEND)
#else
pwrpriv->change_rfpwrstate = rf_off;
#endif
#ifdef CONFIG_AUTOSUSPEND
if (padapter->registrypriv.usbss_enable) {
if (pwrpriv->bHWPwrPindetect)
pwrpriv->bkeepfwalive = _TRUE;
if (padapter->net_closed == _TRUE)
pwrpriv->ps_flag = _TRUE;
#if defined(CONFIG_BT_COEXIST) && defined (CONFIG_AUTOSUSPEND)
if (_TRUE == pwrpriv->bInternalAutoSuspend)
RTW_INFO("<==%s .pwrpriv->bInternalAutoSuspend)(%x)\n", __FUNCTION__, pwrpriv->bInternalAutoSuspend);
else {
pwrpriv->change_rfpwrstate = rf_off;
RTW_INFO("<==%s .pwrpriv->bInternalAutoSuspend)(%x) call autosuspend_enter\n", __FUNCTION__, pwrpriv->bInternalAutoSuspend);
autosuspend_enter(padapter);
}
#else
autosuspend_enter(padapter);
#endif /* if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND) */
} else if (pwrpriv->bHWPwrPindetect) {
} else
#endif /* CONFIG_AUTOSUSPEND */
{
#if defined(CONFIG_BT_COEXIST) && defined (CONFIG_AUTOSUSPEND)
pwrpriv->change_rfpwrstate = rf_off;
#endif /* defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND) */
pwrpriv->change_rfpwrstate = rf_off;
#ifdef CONFIG_IPS
ips_enter(padapter);
#endif
}
}
exit:
#ifndef CONFIG_IPS_CHECK_IN_WD
@ -712,13 +659,13 @@ u8 PS_RDY_CHECK(_adapter *padapter)
if (rtw_time_after(pwrpriv->lps_deny_time, rtw_get_current_time()))
return _FALSE;
if (check_fwstate(pmlmepriv, WIFI_SITE_MONITOR)
if (check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY)
|| check_fwstate(pmlmepriv, WIFI_UNDER_LINKING | WIFI_UNDER_WPS)
|| MLME_IS_AP(padapter)
|| MLME_IS_MESH(padapter)
|| MLME_IS_MONITOR(padapter)
|| check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE)
#if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211)
#if defined(CONFIG_IOCTL_CFG80211)
|| rtw_cfg80211_get_is_roch(padapter) == _TRUE
#endif
|| rtw_is_scan_deny(padapter)
@ -861,22 +808,126 @@ void rtw_set_fw_in_ips_mode(PADAPTER padapter, u8 enable)
}
#endif /* CONFIG_PNO_SUPPORT */
void rtw_leave_lps_and_chk(_adapter *padapter, u8 ps_mode)
void rtw_exec_lps(_adapter *padapter, u8 ps_mode)
{
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
if (ps_mode == PS_MODE_ACTIVE) {
#ifdef CONFIG_LPS_ACK
_enter_critical_mutex(&pwrpriv->lps_ack_mutex, NULL);
rtw_sctx_init(&pwrpriv->lps_ack_sctx, 100);
#endif /* CONFIG_LPS_ACK */
rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
rtw_hal_set_hwreg(padapter, HW_VAR_LPS_STATE_CHK, (u8 *)(&ps_mode));
#ifdef CONFIG_LPS_ACK
_exit_critical_mutex(&pwrpriv->lps_ack_mutex, NULL);
#endif /* CONFIG_LPS_ACK */
} else {
if (MLME_IS_ASOC(padapter))
rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
else
RTW_INFO(FUNC_ADPT_FMT": It can't execute LPS without Wi-Fi connection!\n",
FUNC_ADPT_ARG(padapter));
}
}
void rtw_lps_rfon_ctrl(_adapter *padapter, u8 rfon_ctrl)
{
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
u8 rpwm = 0;
if (pwrpriv->bFwCurrentInPSMode && pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
if (rfon_ctrl == rf_on) {
#ifdef CONFIG_LPS_LCLK
if (pwrpriv->lps_level >= LPS_LCLK) {
s32 ready = _FAIL;
systime stime;
s32 utime;
u32 timeout; /* unit: ms */
#ifdef LPS_RPWM_WAIT_MS
timeout = LPS_RPWM_WAIT_MS;
#else
timeout = 30;
#endif /* !LPS_RPWM_WAIT_MS */
stime = rtw_get_current_time();
do {
ready = rtw_register_task_alive(padapter, LPS_ALIVE);
if (ready == _SUCCESS)
break;
utime = rtw_get_passing_time_ms(stime);
if (utime > timeout)
break;
rtw_msleep_os(1);
} while (1);
if (ready == _FAIL)
RTW_INFO(FUNC_ADPT_FMT": It is not ready to leave 32K !!!\n",
FUNC_ADPT_ARG(padapter));
}
#endif /* CONFIG_LPS_LCLK */
#ifdef CONFIG_LPS_ACK
_enter_critical_mutex(&pwrpriv->lps_ack_mutex, NULL);
rtw_sctx_init(&pwrpriv->lps_ack_sctx, 100);
#endif /* CONFIG_LPS_ACK */
rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
rtw_hal_set_hwreg(padapter, HW_VAR_LPS_STATE_CHK, (u8 *)(&ps_mode));
rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE_RFON_CTRL, (u8 *)(&rfon_ctrl));
rtw_hal_set_hwreg(padapter, HW_VAR_LPS_RFON_CHK, (u8 *)(&rfon_ctrl));
#ifdef CONFIG_LPS_ACK
_exit_critical_mutex(&pwrpriv->lps_ack_mutex, NULL);
#endif /* CONFIG_LPS_ACK */
} else {
if (MLME_IS_ASOC(padapter)) {
#ifdef CONFIG_LPS_PG
if (pwrpriv->lps_level == LPS_PG) {
if (rtw_hal_set_lps_pg_info_cmd(padapter) == _FAIL)
RTW_INFO(FUNC_ADPT_FMT": Send PG H2C command Fail! \n",
FUNC_ADPT_ARG(padapter));
}
#endif /* CONFIG_LPS_PG */
rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE_RFON_CTRL, (u8 *)(&rfon_ctrl));
} else {
RTW_INFO(FUNC_ADPT_FMT": It can't execute RFON without Wi-Fi connection!\n",
FUNC_ADPT_ARG(padapter));
}
#ifdef CONFIG_LPS_LCLK
if (pwrpriv->lps_level >= LPS_LCLK) {
rtw_unregister_task_alive(padapter, LPS_ALIVE);
if (pwrpriv->alives == 0) {
u8 polling_cnt = 0;
u8 reg_val8 = 0;
u8 result = _FAIL;
do {
rtw_msleep_os(1);
reg_val8 = rtw_read8(padapter, REG_CR);
if (reg_val8 == 0xEA) {
result= _SUCCESS;
break;
}
polling_cnt++;
} while (polling_cnt < 100);
if (result == _FAIL )
RTW_INFO(FUNC_ADPT_FMT": It is not finished to enter 32K !!!\n",
FUNC_ADPT_ARG(padapter));
}
}
#endif /* CONFIG_LPS_LCLK */
}
} else {
RTW_INFO(FUNC_ADPT_FMT": RFON can't work due to ps state is not in LPS !\n",
FUNC_ADPT_ARG(padapter));
}
}
void rtw_set_ps_mode(PADAPTER padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode, const char *msg)
@ -1024,7 +1075,7 @@ void rtw_set_ps_mode(PADAPTER padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode
rtw_hal_set_hwreg(padapter, HW_VAR_H2C_INACTIVE_IPS, (u8 *)(&ps_mode));
#endif /* CONFIG_WOWLAN */
rtw_leave_lps_and_chk(padapter, ps_mode);
rtw_exec_lps(padapter, ps_mode);
#ifdef CONFIG_LPS_PG
if (pwrpriv->lps_level == LPS_PG) {
@ -1105,9 +1156,8 @@ void rtw_set_ps_mode(PADAPTER padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode
pwrpriv->wmm_smart_ps = pregistrypriv->wmm_smart_ps;
#endif /* CONFIG_WMMPS_STA */
rtw_exec_lps(padapter, ps_mode);
if (check_fwstate(pmlmepriv, _FW_LINKED))
rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
#ifdef CONFIG_WOWLAN
if (pwrpriv->wowlan_mode == _TRUE)
rtw_hal_set_hwreg(padapter, HW_VAR_H2C_INACTIVE_IPS, (u8 *)(&ps_mode));
@ -1220,9 +1270,9 @@ void LPS_Enter(PADAPTER padapter, const char *msg)
sprintf(buf, "WIFI-%s", msg);
pwrpriv->bpower_saving = _TRUE;
#ifdef CONFIG_RTW_CFGVEDNOR_LLSTATS
#ifdef CONFIG_RTW_CFGVENDOR_LLSTATS
pwrpriv->pwr_saving_start_time = rtw_get_current_time();
#endif /* CONFIG_RTW_CFGVEDNOR_LLSTATS */
#endif /* CONFIG_RTW_CFGVENDOR_LLSTATS */
rtw_set_ps_mode(padapter, pwrpriv->power_mgnt, padapter->registrypriv.smart_ps, 0, buf);
@ -1276,9 +1326,9 @@ void LPS_Leave(PADAPTER padapter, const char *msg)
sprintf(buf, "WIFI-%s", msg);
rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0, buf);
#ifdef CONFIG_RTW_CFGVEDNOR_LLSTATS
#ifdef CONFIG_RTW_CFGVENDOR_LLSTATS
pwrpriv->pwr_saving_time += rtw_get_passing_time_ms(pwrpriv->pwr_saving_start_time);
#endif /* CONFIG_RTW_CFGVEDNOR_LLSTATS */
#endif /* CONFIG_RTW_CFGVENDOR_LLSTATS */
}
}
@ -1375,23 +1425,14 @@ void LeaveAllPowerSaveModeDirect(PADAPTER Adapter)
#endif
} else {
if (pwrpriv->rf_pwrstate == rf_off) {
#ifdef CONFIG_AUTOSUSPEND
if (Adapter->registrypriv.usbss_enable) {
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
usb_disable_autosuspend(adapter_to_dvobj(Adapter)->pusbdev);
#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) && LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34))
adapter_to_dvobj(Adapter)->pusbdev->autosuspend_disabled = Adapter->bDisableAutosuspend;/* autosuspend disabled by the user */
#endif
} else
#endif
{
#if defined(CONFIG_FWLPS_IN_IPS) || defined(CONFIG_SWLPS_IN_IPS) || defined(CONFIG_RTL8188E)
#ifdef CONFIG_IPS
if (_FALSE == ips_leave(pri_padapter))
RTW_INFO("======> ips_leave fail.............\n");
if (_FALSE == ips_leave(pri_padapter))
RTW_INFO("======> ips_leave fail.............\n");
#endif
#endif /* CONFIG_SWLPS_IN_IPS || (CONFIG_PLATFORM_SPRD && CONFIG_RTL8188E) */
}
}
}
@ -1447,23 +1488,14 @@ void LeaveAllPowerSaveMode(PADAPTER Adapter)
#endif
} else {
if (adapter_to_pwrctl(Adapter)->rf_pwrstate == rf_off) {
#ifdef CONFIG_AUTOSUSPEND
if (Adapter->registrypriv.usbss_enable) {
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
usb_disable_autosuspend(adapter_to_dvobj(Adapter)->pusbdev);
#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) && LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34))
adapter_to_dvobj(Adapter)->pusbdev->autosuspend_disabled = Adapter->bDisableAutosuspend;/* autosuspend disabled by the user */
#endif
} else
#endif
{
#if defined(CONFIG_FWLPS_IN_IPS) || defined(CONFIG_SWLPS_IN_IPS) || (defined(CONFIG_PLATFORM_SPRD) && defined(CONFIG_RTL8188E))
#ifdef CONFIG_IPS
if (_FALSE == ips_leave(Adapter))
RTW_INFO("======> ips_leave fail.............\n");
if (_FALSE == ips_leave(Adapter))
RTW_INFO("======> ips_leave fail.............\n");
#endif
#endif /* CONFIG_SWLPS_IN_IPS || (CONFIG_PLATFORM_SPRD && CONFIG_RTL8188E) */
}
}
}
@ -1589,7 +1621,8 @@ static void dma_event_callback(struct work_struct *work)
#ifdef CONFIG_LPS_RPWM_TIMER
#define DBG_CPWM_CHK_FAIL
#if defined(DBG_CPWM_CHK_FAIL) && (defined(CONFIG_RTL8822B) || defined(CONFIG_RTL8821C) || defined(CONFIG_RTL8822C))
#if defined(DBG_CPWM_CHK_FAIL) && (defined(CONFIG_RTL8822B) || defined(CONFIG_RTL8821C) || defined(CONFIG_RTL8822C) \
|| defined(CONFIG_RTL8723F))
#define CPU_EXCEPTION_CODE 0xFAFAFAFA
static void rtw_cpwm_chk_fail_debug(_adapter *padapter)
{
@ -1658,7 +1691,8 @@ static void rpwmtimeout_workitem_callback(struct work_struct *work)
pwrpriv->rpwm_retry = 0;
_exit_pwrlock(&pwrpriv->lock);
#if defined(DBG_CPWM_CHK_FAIL) && (defined(CONFIG_RTL8822B) || defined(CONFIG_RTL8821C) || defined(CONFIG_RTL8822C))
#if defined(DBG_CPWM_CHK_FAIL) && (defined(CONFIG_RTL8822B) || defined(CONFIG_RTL8821C) || defined(CONFIG_RTL8822C) \
|| defined(CONFIG_RTL8723F))
RTW_INFO("+%s: rpwm=0x%02X cpwm=0x%02X\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
rtw_cpwm_chk_fail_debug(padapter);
#endif
@ -2155,7 +2189,7 @@ void rtw_init_pwrctrl_priv(PADAPTER padapter)
struct registry_priv *registry_par = &padapter->registrypriv;
#endif
#ifdef CONFIG_GPIO_WAKEUP
u8 val8 = 0;
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
#endif
#if defined(CONFIG_CONCURRENT_MODE)
@ -2191,18 +2225,8 @@ void rtw_init_pwrctrl_priv(PADAPTER padapter)
pwrctrlpriv->pwr_state_check_interval = RTW_PWR_STATE_CHK_INTERVAL;
pwrctrlpriv->pwr_state_check_cnts = 0;
#ifdef CONFIG_AUTOSUSPEND
pwrctrlpriv->bInternalAutoSuspend = _FALSE;
#endif
pwrctrlpriv->bInSuspend = _FALSE;
pwrctrlpriv->bkeepfwalive = _FALSE;
#ifdef CONFIG_AUTOSUSPEND
#ifdef SUPPORT_HW_RFOFF_DETECTED
pwrctrlpriv->pwr_state_check_interval = (pwrctrlpriv->bHWPwrPindetect) ? 1000 : 2000;
#endif
#endif
pwrctrlpriv->LpsIdleCount = 0;
/* pwrctrlpriv->FWCtrlPSMode =padapter->registrypriv.power_mgnt; */ /* PS_MODE_MIN; */
@ -2272,23 +2296,38 @@ void rtw_init_pwrctrl_priv(PADAPTER padapter)
#endif /* CONFIG_HAS_EARLYSUSPEND || CONFIG_ANDROID_POWER */
#ifdef CONFIG_GPIO_WAKEUP
pwrctrlpriv->wowlan_gpio_index = WAKEUP_GPIO_IDX;
/* set output low state in initial */
pwrctrlpriv->wowlan_gpio_output_state = GPIO_OUTPUT_LOW;
/*default low active*/
pwrctrlpriv->is_high_active = HIGH_ACTIVE_DEV2HST;
pwrctrlpriv->hst2dev_high_active = HIGH_ACTIVE_HST2DEV;
#if (defined(CONFIG_RTL8192F) && defined(CONFIG_USB_HCI) && defined(CONFIG_BT_COEXIST))
if (pHalData->EEPROMBluetoothCoexist == _TRUE) {
/* for 8725AU case */
pwrctrlpriv->wowlan_gpio_index = WAKEUP_GPIO_IDX_8725AU;
pwrctrlpriv->is_high_active = HIGH_ACTIVE_DEV2HST_8725AU;
}
#endif
#ifdef CONFIG_RTW_ONE_PIN_GPIO
rtw_hal_switch_gpio_wl_ctrl(padapter, WAKEUP_GPIO_IDX, _TRUE);
rtw_hal_set_input_gpio(padapter, WAKEUP_GPIO_IDX);
rtw_hal_switch_gpio_wl_ctrl(padapter, pwrctrlpriv->wowlan_gpio_index, _TRUE);
rtw_hal_set_input_gpio(padapter, pwrctrlpriv->wowlan_gpio_index);
#else
#ifdef CONFIG_WAKEUP_GPIO_INPUT_MODE
if (pwrctrlpriv->is_high_active == 0)
rtw_hal_set_input_gpio(padapter, WAKEUP_GPIO_IDX);
rtw_hal_set_input_gpio(padapter, pwrctrlpriv->wowlan_gpio_index);
else
rtw_hal_set_output_gpio(padapter, WAKEUP_GPIO_IDX, 0);
rtw_hal_set_output_gpio(padapter, pwrctrlpriv->wowlan_gpio_index,
GPIO_OUTPUT_LOW);
#else
val8 = (pwrctrlpriv->is_high_active == 0) ? 1 : 0;
rtw_hal_set_output_gpio(padapter, WAKEUP_GPIO_IDX, val8);
RTW_INFO("%s: set GPIO_%d %d as default.\n",
__func__, WAKEUP_GPIO_IDX, val8);
rtw_hal_set_output_gpio(padapter, pwrctrlpriv->wowlan_gpio_index
, pwrctrlpriv->wowlan_gpio_output_state);
rtw_hal_switch_gpio_wl_ctrl(padapter, pwrctrlpriv->wowlan_gpio_index, _TRUE);
RTW_INFO("%s: set GPIO_%d to OUTPUT %s state in initial and %s_ACTIVE.\n",
__func__, pwrctrlpriv->wowlan_gpio_index,
pwrctrlpriv->wowlan_gpio_output_state ? "HIGH" : "LOW",
pwrctrlpriv->is_high_active ? "HIGI" : "LOW");
#endif /*CONFIG_WAKEUP_GPIO_INPUT_MODE*/
#endif /* CONFIG_RTW_ONE_PIN_GPIO */
#endif /* CONFIG_GPIO_WAKEUP */
@ -2328,7 +2367,17 @@ void rtw_init_pwrctrl_priv(PADAPTER padapter)
#ifdef CONFIG_WOW_PATTERN_HW_CAM
_rtw_mutex_init(&pwrctrlpriv->wowlan_pattern_cam_mutex);
#endif
#ifdef CONFIG_WOW_KEEP_ALIVE_PATTERN
pwrctrlpriv->wowlan_keep_alive_ack_index = 0xFF;
pwrctrlpriv->wowlan_wake_pattern_index = 0xFF;
#endif/*CONFIG_WOW_KEEP_ALIVE_PATTERN*/
pwrctrlpriv->wowlan_aoac_rpt_loc = 0;
#ifdef CONFIG_WAR_OFFLOAD
#if defined(CONFIG_OFFLOAD_MDNS_V4) || defined(CONFIG_OFFLOAD_MDNS_V6)
rtw_wow_war_mdns_parms_reset(padapter, _TRUE);
#endif /* defined(CONFIG_OFFLOAD_MDNS_V4) || defined(CONFIG_OFFLOAD_MDNS_V6) */
#endif /* CONFIG_WAR_OFFLOAD */
#endif /* CONFIG_WOWLAN */
#ifdef CONFIG_LPS_POFF
@ -2626,11 +2675,7 @@ int _rtw_pwr_wakeup(_adapter *padapter, u32 ips_deffer_ms, const char *caller)
}
#endif
if (pwrpriv->bInSuspend
#ifdef CONFIG_AUTOSUSPEND
&& pwrpriv->bInternalAutoSuspend == _FALSE
#endif
) {
if (pwrpriv->bInSuspend) {
RTW_INFO("%s wait bInSuspend...\n", __func__);
while (pwrpriv->bInSuspend
&& ((rtw_get_passing_time_ms(start) <= 3000 && !rtw_is_do_late_resume(pwrpriv))
@ -2644,71 +2689,27 @@ int _rtw_pwr_wakeup(_adapter *padapter, u32 ips_deffer_ms, const char *caller)
}
/* System suspend is not allowed to wakeup */
if ((_TRUE == pwrpriv->bInSuspend)
#ifdef CONFIG_AUTOSUSPEND
&& (pwrpriv->bInternalAutoSuspend == _FALSE)
#endif
) {
if (_TRUE == pwrpriv->bInSuspend) {
ret = _FAIL;
goto exit;
}
#ifdef CONFIG_AUTOSUSPEND
/* usb autosuspend block??? */
if ((pwrpriv->bInternalAutoSuspend == _TRUE) && (padapter->net_closed == _TRUE)) {
ret = _FAIL;
goto exit;
}
#endif
/* I think this should be check in IPS, LPS, autosuspend functions... */
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
#if defined(CONFIG_BT_COEXIST) && defined (CONFIG_AUTOSUSPEND)
if (_TRUE == pwrpriv->bInternalAutoSuspend) {
if (0 == pwrpriv->autopm_cnt) {
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33))
if (usb_autopm_get_interface(adapter_to_dvobj(padapter)->pusbintf) < 0)
RTW_INFO("can't get autopm:\n");
#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20))
usb_autopm_disable(adapter_to_dvobj(padapter)->pusbintf);
#else
usb_autoresume_device(adapter_to_dvobj(padapter)->pusbdev, 1);
#endif
pwrpriv->autopm_cnt++;
}
#endif /* #if defined (CONFIG_BT_COEXIST) && defined (CONFIG_AUTOSUSPEND) */
ret = _SUCCESS;
goto exit;
#if defined(CONFIG_BT_COEXIST) && defined (CONFIG_AUTOSUSPEND)
}
#endif /* #if defined (CONFIG_BT_COEXIST) && defined (CONFIG_AUTOSUSPEND) */
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE) {
ret = _SUCCESS;
goto exit;
}
if (rf_off == pwrpriv->rf_pwrstate) {
#ifdef CONFIG_USB_HCI
#ifdef CONFIG_AUTOSUSPEND
if (pwrpriv->brfoffbyhw == _TRUE) {
RTW_INFO("hw still in rf_off state ...........\n");
#ifdef CONFIG_IPS
RTW_INFO("%s call ips_leave....\n", __FUNCTION__);
if (_FAIL == ips_leave(padapter)) {
RTW_INFO("======> ips_leave fail.............\n");
ret = _FAIL;
goto exit;
} else if (padapter->registrypriv.usbss_enable) {
RTW_INFO("%s call autoresume_enter....\n", __FUNCTION__);
if (_FAIL == autoresume_enter(padapter)) {
RTW_INFO("======> autoresume fail.............\n");
ret = _FAIL;
goto exit;
}
} else
#endif
#endif
{
#ifdef CONFIG_IPS
RTW_INFO("%s call ips_leave....\n", __FUNCTION__);
if (_FAIL == ips_leave(padapter)) {
RTW_INFO("======> ips_leave fail.............\n");
ret = _FAIL;
goto exit;
}
#endif
}
#endif
}
/* TODO: the following checking need to be merged... */

1486
core/rtw_recv.c Executable file → Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -21,6 +21,9 @@
#endif
#define pstr(s) s+strlen(s)
#ifndef MIN
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#endif
u8 rm_post_event_hdl(_adapter *padapter, u8 *pbuf)
{
@ -191,8 +194,6 @@ int rm_en_cap_chk_and_set(struct rm_obj *prm, enum rm_cap_en en)
/* for caller outside rm */
u8 rm_add_nb_req(_adapter *padapter, struct sta_info *psta)
{
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
struct rm_obj *prm;
@ -205,16 +206,9 @@ u8 rm_add_nb_req(_adapter *padapter, struct sta_info *psta)
prm->psta = psta;
prm->q.category = RTW_WLAN_CATEGORY_RADIO_MEAS;
do {
pmlmeinfo->dialogToken++;
} while (pmlmeinfo->dialogToken == 0);
prm->q.diag_token = pmlmeinfo->dialogToken;
prm->q.m_token = 1;
prm->rmid = psta->cmn.aid << 16
| prm->q.diag_token << 8
| RM_MASTER;
prm->q.diag_token = rm_gen_dialog_token(padapter);
prm->q.m_token = rm_gen_meas_token(padapter);
prm->rmid = rm_gen_rmid(padapter, prm, RM_MASTER);
prm->q.action_code = RM_ACT_NB_REP_REQ;
@ -370,8 +364,8 @@ int ready_for_scan(struct rm_obj *prm)
int rm_sitesurvey(struct rm_obj *prm)
{
int meas_ch_num=0;
u8 ch_num=0, op_class=0, val8;
int meas_ch_amount=0;
u8 op_class=0, val8;
struct rtw_ieee80211_channel *pch_set;
struct sitesurvey_parm parm;
@ -381,33 +375,40 @@ int rm_sitesurvey(struct rm_obj *prm)
pch_set = &prm->q.ch_set[0];
_rtw_memset(pch_set, 0,
sizeof(struct rtw_ieee80211_channel) * MAX_OP_CHANNEL_SET_NUM);
sizeof(struct rtw_ieee80211_channel) * RTW_CHANNEL_SCAN_AMOUNT);
op_class = prm->q.op_class;
if (prm->q.ch_num == 0) {
/* ch_num=0 : scan all ch in operating class */
op_class = prm->q.op_class;
meas_ch_amount = rm_get_ch_set(pch_set,
op_class, prm->q.ch_num);
} else if (prm->q.ch_num == 255) {
/* 802.11 p.499 */
/* ch_num=255 : scan all ch in current operating class */
op_class = rm_get_oper_class_via_ch(
(u8)prm->psta->padapter->mlmeextpriv.cur_channel);
/* 802.11 p.1066 */
/* ch_num=255 : If the Channel Number is 255 and includes
* AP Channel Report subelements
*/
meas_ch_amount = rm_get_ch_set_from_bcn_req_opt(pch_set, &prm->q.opt.bcn);
} else
ch_num = prm->q.ch_num;
meas_ch_amount = rm_get_ch_set(pch_set, op_class, prm->q.ch_num);
/* get means channel */
meas_ch_num = rm_get_ch_set(pch_set, op_class, ch_num);
prm->q.ch_set_ch_amount = meas_ch_num;
prm->q.ch_set_ch_amount = meas_ch_amount;
#if (RM_MORE_DBG_MSG)
RTW_INFO("survey (%d) chaannels\n", meas_ch_amount);
#endif
_rtw_memset(&parm, 0, sizeof(struct sitesurvey_parm));
_rtw_memcpy(parm.ch, pch_set,
sizeof(struct rtw_ieee80211_channel) * MAX_OP_CHANNEL_SET_NUM);
sizeof(struct rtw_ieee80211_channel) *
MIN(meas_ch_amount, RTW_CHANNEL_SCAN_AMOUNT));
_rtw_memcpy(&parm.ssid[0], &prm->q.opt.bcn.ssid, IW_ESSID_MAX_SIZE);
parm.ssid_num = 1;
parm.scan_mode = prm->q.m_mode;
parm.ch_num = meas_ch_num;
parm.ch_num = meas_ch_amount;
parm.igi = 0;
parm.token = prm->rmid;
parm.duration = prm->q.meas_dur;
@ -501,6 +502,8 @@ static int rm_parse_bcn_req_s_elem(struct rm_obj *prm, u8 *pbody, int req_len)
u8 *popt_id;
int i, p=0; /* position */
int len = req_len;
int ap_ch_rpt_idx = 0;
struct _RT_OPERATING_CLASS *op;
/* opt length,2:pbody[0]+ pbody[1] */
@ -534,7 +537,6 @@ static int rm_parse_bcn_req_s_elem(struct rm_obj *prm, u8 *pbody, int req_len)
&pbody[p+2], pbody[p+1]);
#endif
#endif
RTW_INFO("RM: bcn_req_ssid=%s\n",
prm->q.opt.bcn.ssid.Ssid);
@ -587,11 +589,32 @@ static int rm_parse_bcn_req_s_elem(struct rm_obj *prm, u8 *pbody, int req_len)
popt_id[prm->q.opt.bcn.opt_id_num++] = pbody[p];
break;
case bcn_req_ac_ch_rep:
case bcn_req_ap_ch_rep:
#if (RM_MORE_DBG_MSG)
RTW_INFO("RM: bcn_req_ac_ch_rep\n");
RTW_INFO("RM: bcn_req_ap_ch_rep\n");
#endif
if (ap_ch_rpt_idx > BCN_REQ_OPT_AP_CH_RPT_MAX_NUM) {
RTW_ERR("RM: bcn_req_ap_ch_rep over size\n");
break;
}
popt_id[prm->q.opt.bcn.opt_id_num++] = pbody[p];
/* get channel list
* EID:len:op-class:ch-list
*/
op = rtw_malloc(sizeof (*op));
op->global_op_class = pbody[p + 2];
i = pbody[p + 1] - 1; /* ch list len; (-1) is op class */
#if (RM_MORE_DBG_MSG)
RTW_INFO("%d op class %d has %d ch\n",
ap_ch_rpt_idx,op->global_op_class,i);
#endif
op->Len = i;
memcpy(op->Channel, &pbody[p + 3],
MIN(i, MAX_CH_NUM_IN_OP_CLASS));
prm->q.opt.bcn.ap_ch_rpt[ap_ch_rpt_idx++] = op;
prm->q.opt.bcn.ap_ch_rpt_num = ap_ch_rpt_idx;
break;
default:
@ -703,10 +726,7 @@ int rm_recv_radio_mens_req(_adapter *padapter,
prm->q.m_token = pmeas_body[2];
prm->q.m_mode = pmeas_body[3];
prm->q.m_type = pmeas_body[4];
prm->rmid = psta->cmn.aid << 16
| prm->q.diag_token << 8
| RM_SLAVE;
prm->rmid = rm_gen_rmid(padapter, prm, RM_SLAVE);
RTW_INFO("RM: rmid=%x, bssid " MAC_FMT "\n", prm->rmid,
MAC_ARG(prm->psta->cmn.mac_addr));
@ -766,7 +786,7 @@ done:
int rm_recv_radio_mens_rep(_adapter *padapter,
union recv_frame *precv_frame, struct sta_info *psta)
{
int ret = _FALSE;
int len, ret = _FALSE;
struct rm_obj *prm;
u32 rmid;
u8 *pdiag_body = (u8 *)(precv_frame->u.hdr.rx_data +
@ -779,8 +799,11 @@ int rm_recv_radio_mens_rep(_adapter *padapter,
| RM_MASTER;
prm = rm_get_rmobj(padapter, rmid);
if (prm == NULL)
return _FALSE;
if (prm == NULL) {
/* not belong to us, report to upper */
rtw_cfg80211_rx_rrm_action(psta->padapter, precv_frame);
return _TRUE;
}
prm->p.action_code = pdiag_body[1];
prm->p.diag_token = pdiag_body[2];
@ -807,6 +830,13 @@ int rm_recv_radio_mens_rep(_adapter *padapter,
RTW_INFO("RM: recv %s\n", rm_type_rep_name(prm->p.m_type));
rm_post_event(padapter, prm->rmid, RM_EV_recv_rep);
/* report to upper via ioctl */
if ((prm->from_ioctl == true) &&
prm->q.m_type == bcn_req) {
len = pmeas_body[1] + 2; /* 2 : EID(1B) length(1B) */
indicate_beacon_report(prm->psta->cmn.mac_addr,
1, len, pmeas_body);
}
return ret;
}
@ -840,10 +870,7 @@ int rm_recv_link_mens_req(_adapter *padapter,
prm->q.rx_rate = hw_rate_to_m_rate(precv_frame->u.hdr.attrib.data_rate);
prm->q.rx_bw = precv_frame->u.hdr.attrib.bw;
prm->q.rx_rsni = rm_get_frame_rsni(prm, precv_frame);
prm->rmid = psta->cmn.aid << 16
| prm->q.diag_token << 8
| RM_SLAVE;
prm->rmid = rm_gen_rmid(padapter, prm, RM_SLAVE);
RTW_INFO("RM: rmid=%x, bssid" MAC_FMT " rx_pwr=%ddBm, rate=%s\n",
prm->rmid, MAC_ARG(prm->psta->cmn.mac_addr), prm->q.rx_pwr,
@ -879,8 +906,9 @@ int rm_recv_link_mens_rep(_adapter *padapter,
prm = rm_get_rmobj(padapter, rmid);
if (prm == NULL) {
RTW_ERR("RM: rmid 0x%08x not found\n", rmid);
return ret;
/* not belong to us, report to upper */
rtw_cfg80211_rx_rrm_action(psta->padapter, precv_frame);
return _TRUE;
}
RTW_INFO("RM: rmid=%x, bssid " MAC_FMT "\n", prm->rmid,
@ -922,8 +950,12 @@ int rm_radio_mens_nb_rep(_adapter *padapter,
| RM_MASTER;
prm = rm_get_rmobj(padapter, rmid);
if (prm == NULL)
return _FALSE;
if (prm == NULL) {
/* not belong to us, report to upper */
rtw_cfg80211_rx_rrm_action(psta->padapter, precv_frame);
return _TRUE;
}
prm->p.action_code = pdiag_body[1];
prm->p.diag_token = pdiag_body[2];
@ -1108,6 +1140,9 @@ static u8 *rm_gen_bcn_detail_elem(_adapter *padapter, u8 *pframe,
continue;
#if (RM_MORE_DBG_MSG)
switch (eid) {
case EID_SsId:
RTW_INFO("RM: EID_SSID\n");
break;
case EID_QBSSLoad:
RTW_INFO("RM: EID_QBSSLoad\n");
break;
@ -1117,16 +1152,24 @@ static u8 *rm_gen_bcn_detail_elem(_adapter *padapter, u8 *pframe,
case _MDIE_:
RTW_INFO("RM: EID_MobilityDomain\n");
break;
case EID_Vendor:
RTW_INFO("RM: EID_Vendor\n");
break;
default:
RTW_INFO("RM: EID %d todo\n",eid);
break;
}
#endif
pframe = rtw_set_ie(pframe, eid,
len,ptr+2, &my_len);
len, ptr+2, &my_len);
} /* for() */
break;
case bcn_req_ac_ch_rep:
case bcn_req_rep_detail:
RTW_INFO("RM: bcn_req_rep_detail\n");
break;
case bcn_req_ap_ch_rep:
RTW_INFO("RM: bcn_req_ap_ch_rep\n");
break;
default:
RTW_INFO("RM: OPT %d TODO\n",prm->q.opt.bcn.opt_id[j]);
break;
@ -1236,7 +1279,10 @@ static u8 *rm_gen_bcn_rep_ie (struct rm_obj *prm,
pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
/* ParentTSF */
val32 = prm->meas_start_time + pnetwork->network.PhyInfo.free_cnt;
val32 = pnetwork->network.PhyInfo.free_cnt;
if (prm->free_run_counter_valid)
val32 += prm->meas_start_time;
pframe = rtw_set_fixed_ie(pframe, 4, (u8 *)&val32, &my_len);
/* Generate Beacon detail */
@ -1255,6 +1301,99 @@ static u8 *rm_gen_bcn_rep_ie (struct rm_obj *prm,
return pframe;
}
#if 0 /* check MBO logo */
static int rm_match_sub_elem(_adapter *padapter,
struct rm_obj *prm, struct wlan_network *pnetwork)
{
WLAN_BSSID_EX *pbss = &pnetwork->network;
unsigned int my_len;
int j, k, len;
u8 *plen;
u8 *ptr;
u8 val8, eid;
my_len = 0;
/* Reporting Detail values
* 0: No fixed length fields or elements
* 1: All fixed length fields and any requested elements
* in the Request info element if present
* 2: All fixed length fields and elements
* 3-255: Reserved
*/
/* report_detail != 1 */
if (prm->q.opt.bcn.rep_detail != 1)
return _TRUE;
/* report_detail = 1 */
for (j = 0; j < prm->q.opt.bcn.opt_id_num; j++) {
switch (prm->q.opt.bcn.opt_id[j]) {
case bcn_req_ssid:
/* SSID */
#if (RM_MORE_DBG_MSG)
RTW_INFO("RM: bcn_req_ssid\n");
#endif
if (pbss->Ssid.SsidLength == 0)
return _FALSE;
break;
case bcn_req_req:
if (prm->q.opt.bcn.req_start == NULL)
break;
#if (RM_MORE_DBG_MSG)
RTW_INFO("RM: bcn_req_req");
#endif
for (k=0; k<prm->q.opt.bcn.req_len; k++) {
eid = prm->q.opt.bcn.req_start[k];
val8 = pbss->IELength - _FIXED_IE_LENGTH_;
ptr = rtw_get_ie(pbss->IEs + _FIXED_IE_LENGTH_,
eid, &len, val8);
#if (RM_MORE_DBG_MSG)
switch (eid) {
case EID_SsId:
RTW_INFO("RM: EID_SSID\n");
break;
case EID_QBSSLoad:
RTW_INFO("RM: EID_QBSSLoad\n");
break;
case EID_HTCapability:
RTW_INFO("RM: EID_HTCapability\n");
break;
case _MDIE_:
RTW_INFO("RM: EID_MobilityDomain\n");
break;
case EID_Vendor:
RTW_INFO("RM: EID_Vendor\n");
break;
default:
RTW_INFO("RM: EID %d todo\n",eid);
break;
}
#endif
if (!ptr) {
RTW_INFO("RM: EID %d not found\n",eid);
return _FALSE;
}
} /* for() */
break;
case bcn_req_rep_detail:
RTW_INFO("RM: bcn_req_rep_detail\n");
break;
case bcn_req_ap_ch_rep:
RTW_INFO("RM: bcn_req_ap_ch_rep\n");
break;
default:
RTW_INFO("RM: OPT %d TODO\n",prm->q.opt.bcn.opt_id[j]);
break;
}
}
return _TRUE;
}
#endif
static int retrieve_scan_result(struct rm_obj *prm)
{
_irqL irqL;
@ -1264,7 +1403,7 @@ static int retrieve_scan_result(struct rm_obj *prm)
struct rtw_ieee80211_channel *pch_set;
struct wlan_network *pnetwork = NULL;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
int i, meas_ch_num=0;
int i;
PWLAN_BSSID_EX pbss;
unsigned int matched_network;
int len, my_len;
@ -1287,7 +1426,6 @@ static int retrieve_scan_result(struct rm_obj *prm)
/* get requested measurement channel set */
pch_set = prm->q.ch_set;
meas_ch_num = prm->q.ch_set_ch_amount;
/* search scan queue to find requested SSID */
while (1) {
@ -1298,88 +1436,98 @@ static int retrieve_scan_result(struct rm_obj *prm)
pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
pbss = &pnetwork->network;
#if 0
RTW_INFO("RM: ooo ch %u ssid %s bssid "MAC_FMT"\n",
pbss->Configuration.DSConfig, pbss->Ssid.Ssid,
MAC_ARG(pbss->MacAddress));
/*
* report network if requested channel set contains
* the channel matchs selected network
*/
if (rtw_chset_search_ch(adapter_to_chset(padapter),
pbss->Configuration.DSConfig) == 0)
pbss->Configuration.DSConfig) < 0) /* not match */
goto next;
if (rtw_mlme_band_check(padapter, pbss->Configuration.DSConfig)
== _FALSE)
goto next;
#endif
if (rtw_validate_ssid(&(pbss->Ssid)) == _FALSE)
goto next;
/* match bssid */
if (is_wildcard_bssid(prm->q.bssid) == FALSE)
if (_rtw_memcmp(prm->q.bssid,
pbss->MacAddress, 6) == _FALSE)
//continue;
goto next;
/*
* default wildcard SSID. wildcard SSID:
* A SSID value (null) used to represent all SSIDs
*/
/* match ssid */
if ((prm->q.opt.bcn.ssid.SsidLength > 0) &&
_rtw_memcmp(prm->q.opt.bcn.ssid.Ssid,
pbss->Ssid.Ssid,
prm->q.opt.bcn.ssid.SsidLength) == _FALSE)
goto next;
/* go through measurement requested channels */
for (i = 0; i < meas_ch_num; i++) {
for (i = 0; i < prm->q.ch_set_ch_amount; i++) {
if ((pch_set[i].hw_value) ==
(pbss->Configuration.DSConfig)) /* match ch */
break;
}
if (i >= prm->q.ch_set_ch_amount) /* channel mismatch */
goto next;
/* match channel */
if (pch_set[i].hw_value != pbss->Configuration.DSConfig)
continue;
/* match bssid */
if (is_wildcard_bssid(prm->q.bssid) == FALSE)
if (_rtw_memcmp(prm->q.bssid,
pbss->MacAddress, 6) == _FALSE) {
continue;
}
/*
* default wildcard SSID. wildcard SSID:
* A SSID value (null) used to represent all SSIDs
*/
/* match ssid */
if ((prm->q.opt.bcn.ssid.SsidLength > 0) &&
_rtw_memcmp(prm->q.opt.bcn.ssid.Ssid,
pbss->Ssid.Ssid,
prm->q.opt.bcn.ssid.SsidLength) == _FALSE)
continue;
/* match condition */
if (rm_bcn_req_cond_mach(prm, pnetwork) == _FALSE) {
RTW_INFO("RM: condition mismatch ch %u ssid %s bssid "MAC_FMT"\n",
pch_set[i].hw_value, pbss->Ssid.Ssid,
MAC_ARG(pbss->MacAddress));
RTW_INFO("RM: condition %u:%u\n",
prm->q.opt.bcn.rep_cond.cond,
prm->q.opt.bcn.rep_cond.threshold);
continue;
}
/* Found a matched SSID */
matched_network++;
RTW_INFO("RM: ch %u Found %s bssid "MAC_FMT"\n",
pch_set[i].hw_value, pbss->Ssid.Ssid,
/* match condition */
if (rm_bcn_req_cond_mach(prm, pnetwork) == _FALSE) {
RTW_INFO("RM: condition mismatch ch %u ssid %s bssid "MAC_FMT"\n",
pbss->Configuration.DSConfig, pbss->Ssid.Ssid,
MAC_ARG(pbss->MacAddress));
RTW_INFO("RM: condition %u:%u\n",
prm->q.opt.bcn.rep_cond.cond,
prm->q.opt.bcn.rep_cond.threshold);
goto next;
//continue;
}
#if 0 /* check MBO logo */
/* match subelement */
if (rm_match_sub_elem(padapter, prm, pnetwork) == _FALSE)
goto next;
#endif
/* Found a matched SSID */
matched_network++;
len = 0;
_rtw_memset(tmp_buf, 0, MAX_XMIT_EXTBUF_SZ);
rm_gen_bcn_rep_ie(prm, tmp_buf, pnetwork, &len);
RTW_INFO("RM: ch %u Found %s bssid "MAC_FMT"\n",
pbss->Configuration.DSConfig, pbss->Ssid.Ssid,
MAC_ARG(pbss->MacAddress));
len = 0;
_rtw_memset(tmp_buf, 0, MAX_XMIT_EXTBUF_SZ);
rm_gen_bcn_rep_ie(prm, tmp_buf, pnetwork, &len);
new_packet:
if (my_len == 0) {
pbuf = rtw_malloc(MAX_XMIT_EXTBUF_SZ);
if (pbuf == NULL)
goto fail;
prm->buf[buf_idx].pbuf = pbuf;
}
if (my_len == 0) {
pbuf = rtw_malloc(MAX_XMIT_EXTBUF_SZ);
if (pbuf == NULL)
goto fail;
prm->buf[buf_idx].pbuf = pbuf;
}
if ((MAX_XMIT_EXTBUF_SZ - (my_len+len+24+4)) > 0) {
pbuf = rtw_set_fixed_ie(pbuf,
len, tmp_buf, &my_len);
prm->buf[buf_idx].len = my_len;
} else {
if (my_len == 0) /* not enough space */
goto fail;
if ((MAX_XMIT_EXTBUF_SZ - (my_len+len+24+4)) > 0) {
pbuf = rtw_set_fixed_ie(pbuf,
len, tmp_buf, &my_len);
prm->buf[buf_idx].len = my_len;
} else {
if (my_len == 0) /* not enough space */
goto fail;
my_len = 0;
buf_idx++;
goto new_packet;
}
} /* for() */
my_len = 0;
buf_idx++;
goto new_packet;
}
next:
plist = get_next(plist);
} /* while() */
@ -1647,17 +1795,96 @@ int issue_link_meas_rep(struct rm_obj *prm)
}
static u8 *rm_gen_bcn_req_s_elem(_adapter *padapter,
u8 *pframe, unsigned int *fr_len)
struct rm_obj *prm, u8 *pframe, unsigned int *fr_len)
{
u8 val8;
u8 val8, l;
int i;
unsigned int my_len = 0;
u8 bssid[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
struct _RT_OPERATING_CLASS *op;
/* meas mode */
val8 = bcn_req_active; /* measurement mode T8-64 */
pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
pframe = rtw_set_fixed_ie(pframe, 6, bssid, &my_len);
/* bssid */
pframe = rtw_set_fixed_ie(pframe, 6, prm->q.bssid, &my_len);
/*
* opt ssid (0)
*/
l = MIN(32, (int)prm->q.opt.bcn.ssid.SsidLength);
l = (int)prm->q.opt.bcn.ssid.SsidLength;
if (l > 32)
RTW_ERR("RM: %s SSID len over size %d! skip it!\n",__func__, l);
if (l > 0 && l <= 32) {
/* Type */
val8 = bcn_req_ssid;
pframe = rtw_set_fixed_ie(pframe, 1,
&val8, &my_len);
/* Len */
pframe = rtw_set_fixed_ie(pframe, 1,
&l, &my_len);
/* Value */
pframe = rtw_set_fixed_ie(pframe, l,
prm->q.opt.bcn.ssid.Ssid, &my_len);
}
/*
* opt reporting detail (2)
*/
/* Type */
val8 = bcn_req_rep_detail;
pframe = rtw_set_fixed_ie(pframe, 1,
&val8, &my_len);
/* Len */
l = 1;
pframe = rtw_set_fixed_ie(pframe, 1,
&l, &my_len);
/* Value */
pframe = rtw_set_fixed_ie(pframe, l,
&prm->q.opt.bcn.rep_detail, &my_len);
/*
* opt request (10)
*/
if (prm->q.opt.bcn.req_id_num > 0) {
/* Type */
val8 = bcn_req_req;
pframe = rtw_set_fixed_ie(pframe, 1,
&val8, &my_len);
/* Len */
l = prm->q.opt.bcn.req_id_num;
pframe = rtw_set_fixed_ie(pframe, 1,
&l, &my_len);
/* Value */
pframe = rtw_set_fixed_ie(pframe, l,
prm->q.opt.bcn.req_id, &my_len);
}
/*
* opt ap channel report (51)
*/
for (i = 0; i < prm->q.opt.bcn.ap_ch_rpt_num; i++) {
op = prm->q.opt.bcn.ap_ch_rpt[i];
if (op == NULL)
break;
/* Type */
val8 = bcn_req_ap_ch_rep;
pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
l = (u8)op->Len + 1;
/* length */
pframe = rtw_set_fixed_ie(pframe, 1, &l, &my_len);
/* op class */
val8 = op->global_op_class;
pframe = rtw_set_fixed_ie(pframe, 1, &val8, &my_len);
/* channel */
pframe = rtw_set_fixed_ie(pframe, op->Len, op->Channel, &my_len);
}
/* update length to caller */
*fr_len += my_len;
@ -1738,6 +1965,8 @@ int issue_radio_meas_req(struct rm_obj *prm)
}
pattr = &pmgntframe->attrib;
pframe = build_wlan_hdr(padapter, pmgntframe, prm->psta, WIFI_ACTION);
/* Category, Action code, Dialog token */
pframe = rtw_set_fixed_ie(pframe, 3, &prm->q.category, &pattr->pktlen);
/* repeat */
@ -1747,22 +1976,21 @@ int issue_radio_meas_req(struct rm_obj *prm)
my_len = 0;
plen = pframe + 1;
/* Element ID, Length, Meas token, Meas Mode, Meas type, op class, ch */
pframe = rtw_set_fixed_ie(pframe, 7, &prm->q.e_id, &my_len);
/* random interval */
val16 = 100; /* 100 TU */
val16 = cpu_to_le16(val16);
val16 = cpu_to_le16(prm->q.rand_intvl); /* TU */
pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&val16, &my_len);
/* measurement duration */
val16 = 100;
val16 = cpu_to_le16(val16);
val16 = cpu_to_le16(prm->q.meas_dur);
pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&val16, &my_len);
/* optional subelement */
switch (prm->q.m_type) {
case bcn_req:
pframe = rm_gen_bcn_req_s_elem(padapter, pframe, &my_len);
pframe = rm_gen_bcn_req_s_elem(padapter, prm, pframe, &my_len);
break;
case ch_load_req:
pframe = rm_gen_ch_load_req_s_elem(padapter, pframe, &my_len);
@ -1804,9 +2032,11 @@ int rm_radio_meas_report_cond(struct rm_obj *prm)
case ch_load_cond_anpi_equal_greater:
if (val8 >= prm->q.opt.clm.rep_cond.threshold)
return _SUCCESS;
break;
case ch_load_cond_anpi_equal_less:
if (val8 <= prm->q.opt.clm.rep_cond.threshold)
return _SUCCESS;
break;
default:
break;
}
@ -2116,7 +2346,6 @@ done:
static int rm_dbg_modify_meas(_adapter *padapter, char *s)
{
struct rm_priv *prmpriv = &padapter->rmpriv;
struct mlme_ext_info *pmlmeinfo = &padapter->mlmeextpriv.mlmext_info;
struct rm_obj *prm;
struct sta_info *psta;
char *pmac, *ptr, *paid, *prpt, *pnbp, *pclm, *pnhm, *pbcn, *plnk;
@ -2147,7 +2376,7 @@ static int rm_dbg_modify_meas(_adapter *padapter, char *s)
}
}
prm = (struct rm_obj *)prmpriv->prm_sel;
prm->q.m_token = 1;
prm->q.m_token = rm_gen_meas_token(padapter);
psta = prm->psta;
if (paid) { /* find sta_info according to aid */
@ -2166,26 +2395,16 @@ static int rm_dbg_modify_meas(_adapter *padapter, char *s)
if (psta) {
prm->psta = psta;
#if 0
prm->q.diag_token = psta->rm_diag_token++;
#else
/* TODO dialog should base on sta_info */
do {
pmlmeinfo->dialogToken++;
} while (pmlmeinfo->dialogToken == 0);
prm->q.diag_token = pmlmeinfo->dialogToken;
#endif
prm->rmid = psta->cmn.aid << 16
| prm->q.diag_token << 8
| RM_MASTER;
prm->q.diag_token = rm_gen_dialog_token(padapter);
prm->rmid = rm_gen_rmid(padapter, prm, RM_MASTER);
} else
return _FAIL;
prm->q.action_code = RM_ACT_RADIO_MEAS_REQ;
if (pbcn) {
prm->q.m_type = bcn_req;
prm->q.rand_intvl = le16_to_cpu(100);
prm->q.meas_dur = le16_to_cpu(100);
} else if (pnhm) {
prm->q.m_type = noise_histo_req;
} else if (pclm) {
@ -2242,6 +2461,108 @@ static void rm_dbg_activate_meas(_adapter *padapter, char *s)
prmpriv->prm_sel = NULL;
}
/* for ioctl */
int rm_send_bcn_reqs(_adapter *padapter, u8 *sta_addr, u8 op_class, u8 ch,
u16 measure_duration, u8 measure_mode, u8 *bssid, u8 *ssid,
u8 reporting_detail,
u8 n_ap_ch_rpt, struct _RT_OPERATING_CLASS *rpt,
u8 n_elem_id, u8 *elem_id_list)
{
struct rm_obj *prm;
char *pact;
struct sta_info *psta;
struct _RT_OPERATING_CLASS *prpt;
void *ptr;
int i,j,sz;
u8 bcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
if (n_ap_ch_rpt > BCN_REQ_OPT_AP_CH_RPT_MAX_NUM) {
RTW_ERR("RM: chset num %d > %d\n",
n_ap_ch_rpt, BCN_REQ_OPT_AP_CH_RPT_MAX_NUM);
return -1;
}
/* dest sta */
psta = rtw_get_stainfo(&padapter->stapriv, sta_addr);
if (!psta) {
RTW_ERR("RM: psta not found\n");
return -2;
}
prm = rm_alloc_rmobj(padapter);
if (prm == NULL) {
RTW_ERR("RM: unable to alloc rm obj for requeset\n");
return -3;
}
prm->psta = psta;
prm->q.meas_dur = measure_duration;
/* Figure 8-104 Measurement Requested format */
prm->q.category = RTW_WLAN_CATEGORY_RADIO_MEAS;
prm->q.action_code = RM_ACT_RADIO_MEAS_REQ;
prm->q.m_mode = measure_mode;
prm->q.m_type = bcn_req;
prm->q.diag_token = rm_gen_dialog_token(padapter);
prm->q.m_token = rm_gen_meas_token(padapter);
prm->rmid = rm_gen_rmid(padapter, prm, RM_MASTER);
prm->q.e_id = _MEAS_REQ_IE_; /* 38 */
prm->q.ch_num = ch;
prm->q.op_class = op_class;
prm->from_ioctl = true;
if (bssid != NULL)
memcpy(prm->q.bssid, bssid, ETH_ALEN);
else
memcpy(prm->q.bssid, bcast, ETH_ALEN);
if (ssid != NULL) {
i = MIN(32, strlen(ssid));
prm->q.opt.bcn.ssid.SsidLength = i;
memcpy(prm->q.opt.bcn.ssid.Ssid, ssid, i);
}
if (n_ap_ch_rpt > 0) {
prm->q.opt.bcn.ap_ch_rpt_num = n_ap_ch_rpt;
j = 0;
for (i = 0; i < n_ap_ch_rpt; i++) {
prpt = rpt++;
if (prpt == NULL)
break;
sz = sizeof(struct _RT_OPERATING_CLASS) * prpt->Len;
ptr = rtw_malloc(sz);
_rtw_memcpy(ptr, prpt, sz);
prm->q.opt.bcn.ap_ch_rpt[i] = (struct _RT_OPERATING_CLASS *)ptr;
}
}
prm->q.opt.bcn.rep_detail = reporting_detail;
if ((n_elem_id > 0) && (n_elem_id < BCN_REQ_REQ_OPT_MAX_NUM)) {
prm->q.opt.bcn.req_id_num = n_elem_id;
_rtw_memcpy(prm->q.opt.bcn.req_id, elem_id_list, n_elem_id);
}
/* enquee rmobj */
rm_enqueue_rmobj(padapter, prm, _FALSE);
RTW_INFO("\nAdd rmid=%x, meas_type=%s ok\n",
prm->rmid, rm_type_req_name(prm->q.m_type));
if (prm->psta)
RTW_INFO("mac="MAC_FMT"\n", MAC_ARG(prm->psta->cmn.mac_addr));
return 0;
}
void indicate_beacon_report(u8 *sta_addr,
u8 n_measure_rpt, u32 elem_len, u8 *elem)
{
RTW_INFO("RM: recv bcn reprot from mac="MAC_FMT"\n", MAC_ARG(sta_addr));
#ifdef CONFIG_PLATFORM_CMAP_INTFS
cmap_intfs_nl_beacon_report_event(sta_addr, n_measure_rpt, elem_len, elem);
#endif
}
static void rm_dbg_add_meas(_adapter *padapter, char *s)
{
struct rm_priv *prmpriv = &(padapter->rmpriv);
@ -2411,6 +2732,37 @@ static void rm_dbg_list_meas(_adapter *padapter, char *s)
}
#endif /* RM_SUPPORT_IWPRIV_DBG */
int verify_bcn_req(_adapter *padapter, struct sta_info *psta)
{
char *bssid = NULL;
char ssid[] = "RealKungFu";
u8 op_class = 0;
u8 ch = 255;
u16 measure_duration = 100;
u8 reporting_detaial = 0;
u8 n_ap_ch_rpt = 6;
u8 measure_mode = bcn_req_active;
u8 req[] = {1,2,3};
u8 req_len = sizeof(req);
static RT_OPERATING_CLASS US[] = {
/* 0, OP_CLASS_NULL */ //{ 0, 0, {}},
/* 1, OP_CLASS_1 */ {115, 4, {36, 40, 44, 48}},
/* 2, OP_CLASS_2 */ {118, 4, {52, 56, 60, 64}},
/* 3, OP_CLASS_3 */ {124, 4, {149, 153, 157, 161}},
/* 4, OP_CLASS_4 */ {121, 11, {100, 104, 108, 112, 116, 120, 124,
128, 132, 136, 140}},
/* 5, OP_CLASS_5 */ {125, 5, {149, 153, 157, 161, 165}},
/* 6, OP_CLASS_12 */ { 81, 11, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}
};
rm_send_bcn_reqs(padapter, psta->cmn.mac_addr, op_class, ch,
measure_duration, measure_mode, bssid, ssid,
reporting_detaial, n_ap_ch_rpt, US, req_len, req);
return 0;
}
void rm_dbg_cmd(_adapter *padapter, char *s)
{
unsigned val;
@ -2421,6 +2773,19 @@ void rm_dbg_cmd(_adapter *padapter, char *s)
if (_rtw_memcmp(s, "help", 4)) {
rm_dbg_help(padapter, s);
} else if (_rtw_memcmp(s, "send_bcn_req", 12)) {
/* rtwpriv wls1 rrm send_bcn_req aid=1 */
paid = strstr(s, "aid=");
if (paid) { /* find sta_info according to aid */
paid += 4; /* skip aid= */
sscanf(paid, "%u", &val); /* aid=x */
psta = rm_get_sta(padapter, val, NULL);
if (psta)
verify_bcn_req(padapter, psta);
}
} else if (_rtw_memcmp(s, "list_sta", 8)) {
rm_dbg_list_sta(padapter, s);

View File

@ -122,6 +122,7 @@ int rtw_init_rm(_adapter *padapter)
padapter, rm_timer_callback, padapter);
_set_timer(&prmpriv->rm_timer, CLOCK_UNIT);
prmpriv->meas_token = 1;
return _SUCCESS;
}
@ -387,7 +388,7 @@ u8 rtw_rm_post_envent_cmd(_adapter *padapter, u32 rmid, u8 evid)
pev->rmid = rmid;
pev->evid = evid;
init_h2fwcmd_w_parm_no_rsp(pcmd, pev, GEN_CMD_CODE(_RM_POST_EVENT));
init_h2fwcmd_w_parm_no_rsp(pcmd, pev, CMD_RM_POST_EVENT);
res = rtw_enqueue_cmd(pcmdpriv, pcmd);
exit:
return res;
@ -668,8 +669,9 @@ static int rm_state_do_meas(struct rm_obj *prm, enum RM_EV_ID evid)
switch (prm->q.m_type) {
case bcn_req:
val8 = 1; /* Enable free run counter */
rtw_hal_set_hwreg(padapter,
HW_VAR_FREECNT, &val8);
prm->free_run_counter_valid = rtw_hal_set_hwreg(
padapter, HW_VAR_FREECNT, &val8);
rm_sitesurvey(prm);
break;
case ch_load_req:

View File

@ -65,6 +65,29 @@ done:
return ch_amount;
}
u8 rm_get_ch_set_from_bcn_req_opt(
struct rtw_ieee80211_channel *pch_set, struct bcn_req_opt *opt)
{
int i,j,k,sz;
struct _RT_OPERATING_CLASS *ap_ch_rpt;
u8 ch_amount = 0;
k = 0;
for (i = 0; i < opt->ap_ch_rpt_num; i++) {
if (opt->ap_ch_rpt[i] == NULL)
break;
ap_ch_rpt = opt->ap_ch_rpt[i];
for (j = 0; j < ap_ch_rpt->Len; j++) {
pch_set[k].hw_value =
ap_ch_rpt->Channel[j];
RTW_INFO("RM: meas_ch[%d].hw_value = %u\n",
j, pch_set[k].hw_value);
k++;
}
}
return k;
}
u8 rm_get_oper_class_via_ch(u8 ch)
{
int i,j,sz;
@ -124,16 +147,20 @@ u8 rm_get_bcn_rcpi(struct rm_obj *prm, struct wlan_network *pnetwork)
u8 rm_get_frame_rsni(struct rm_obj *prm, union recv_frame *pframe)
{
int i;
u8 val8, snr;
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(prm->psta->padapter);
u8 val8, snr, rx_num;
struct hal_spec_t *hal_spec = GET_HAL_SPEC(prm->psta->padapter);
if (IS_CCK_RATE((hw_rate_to_m_rate(pframe->u.hdr.attrib.data_rate))))
val8 = 255;
else {
snr = 0;
for (i = 0; i < pHalData->NumTotalRFPath; i++)
snr += pframe->u.hdr.attrib.phy_info.rx_snr[i];
snr = snr / pHalData->NumTotalRFPath;
snr = rx_num = 0;
for (i = 0; i < hal_spec->rf_reg_path_num; i++) {
if (GET_HAL_RX_PATH_BMP(prm->psta->padapter) & BIT(i)) {
snr += pframe->u.hdr.attrib.phy_info.rx_snr[i];
rx_num++;
}
}
snr = snr / rx_num;
val8 = (u8)(snr + 10)*2;
}
return val8;
@ -142,20 +169,22 @@ u8 rm_get_frame_rsni(struct rm_obj *prm, union recv_frame *pframe)
u8 rm_get_bcn_rsni(struct rm_obj *prm, struct wlan_network *pnetwork)
{
int i;
u8 val8, snr;
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(prm->psta->padapter);
u8 val8, snr, rx_num;
struct hal_spec_t *hal_spec = GET_HAL_SPEC(prm->psta->padapter);
if (pnetwork->network.PhyInfo.is_cck_rate) {
/* current HW doesn't have CCK RSNI */
/* 255 indicates RSNI is unavailable */
val8 = 255;
} else {
snr = 0;
for (i = 0; i < pHalData->NumTotalRFPath; i++) {
snr += pnetwork->network.PhyInfo.rx_snr[i];
snr = rx_num = 0;
for (i = 0; i < hal_spec->rf_reg_path_num; i++) {
if (GET_HAL_RX_PATH_BMP(prm->psta->padapter) & BIT(i)) {
snr += pnetwork->network.PhyInfo.rx_snr[i];
rx_num++;
}
}
snr = snr / pHalData->NumTotalRFPath;
snr = snr / rx_num;
val8 = (u8)(snr + 10)*2;
}
return val8;
@ -425,4 +454,48 @@ int rm_get_path_a_max_tx_power(_adapter *adapter, s8 *path_a)
return 0;
}
u8 rm_gen_dialog_token(_adapter *padapter)
{
struct rm_priv *prmpriv = &(padapter->rmpriv);
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
do {
pmlmeinfo->dialogToken++;
} while (pmlmeinfo->dialogToken == 0);
return pmlmeinfo->dialogToken;
}
u8 rm_gen_meas_token(_adapter *padapter)
{
struct rm_priv *prmpriv = &(padapter->rmpriv);
do {
prmpriv->meas_token++;
} while (prmpriv->meas_token == 0);
return prmpriv->meas_token;
}
u32 rm_gen_rmid(_adapter *padapter, struct rm_obj *prm, u8 role)
{
u32 rmid;
if (prm->psta == NULL)
goto err;
if (prm->q.diag_token == 0)
goto err;
rmid = prm->psta->cmn.aid << 16
| prm->q.diag_token << 8
| role;
return rmid;
err:
RTW_ERR("RM: unable to gen rmid\n");
return 0;
}
#endif /* CONFIG_RTW_80211K */

591
core/rtw_roch.c Normal file
View File

@ -0,0 +1,591 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2020 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#include <drv_types.h>
#ifdef CONFIG_IOCTL_CFG80211
u8 rtw_roch_stay_in_cur_chan(_adapter *padapter)
{
int i;
_adapter *iface;
struct mlme_priv *pmlmepriv;
struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
u8 rst = _FALSE;
for (i = 0; i < dvobj->iface_nums; i++) {
iface = dvobj->padapters[i];
if (iface) {
pmlmepriv = &iface->mlmepriv;
if (check_fwstate(pmlmepriv, WIFI_UNDER_LINKING | WIFI_UNDER_WPS | WIFI_UNDER_KEY_HANDSHAKE) == _TRUE) {
RTW_INFO(ADPT_FMT"- WIFI_UNDER_LINKING |WIFI_UNDER_WPS | WIFI_UNDER_KEY_HANDSHAKE (mlme state:0x%x)\n",
ADPT_ARG(iface), get_fwstate(&iface->mlmepriv));
rst = _TRUE;
break;
}
#ifdef CONFIG_AP_MODE
if (MLME_IS_AP(iface) || MLME_IS_MESH(iface)) {
if (rtw_ap_sta_states_check(iface) == _TRUE) {
rst = _TRUE;
break;
}
}
#endif
}
}
return rst;
}
static int rtw_ro_ch_handler(_adapter *adapter, u8 *buf)
{
int ret = H2C_SUCCESS;
struct rtw_roch_parm *roch_parm = (struct rtw_roch_parm *)buf;
struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);
struct roch_info *prochinfo = &adapter->rochinfo;
#ifdef CONFIG_CONCURRENT_MODE
struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
#endif
u8 ready_on_channel = _FALSE;
u8 remain_ch;
unsigned int duration;
_enter_critical_mutex(&pwdev_priv->roch_mutex, NULL);
if (rtw_cfg80211_get_is_roch(adapter) != _TRUE)
goto exit;
remain_ch = (u8)ieee80211_frequency_to_channel(roch_parm->ch.center_freq);
duration = roch_parm->duration;
RTW_INFO(FUNC_ADPT_FMT" ch:%u duration:%d, cookie:0x%llx\n"
, FUNC_ADPT_ARG(adapter), remain_ch, roch_parm->duration, roch_parm->cookie);
if (roch_parm->wdev && roch_parm->cookie) {
if (prochinfo->ro_ch_wdev != roch_parm->wdev) {
RTW_WARN(FUNC_ADPT_FMT" ongoing wdev:%p, wdev:%p\n"
, FUNC_ADPT_ARG(adapter), prochinfo->ro_ch_wdev, roch_parm->wdev);
rtw_warn_on(1);
}
if (prochinfo->remain_on_ch_cookie != roch_parm->cookie) {
RTW_WARN(FUNC_ADPT_FMT" ongoing cookie:0x%llx, cookie:0x%llx\n"
, FUNC_ADPT_ARG(adapter), prochinfo->remain_on_ch_cookie, roch_parm->cookie);
rtw_warn_on(1);
}
}
if (rtw_roch_stay_in_cur_chan(adapter) == _TRUE) {
remain_ch = rtw_mi_get_union_chan(adapter);
RTW_INFO(FUNC_ADPT_FMT" stay in union ch:%d\n", FUNC_ADPT_ARG(adapter), remain_ch);
}
#ifdef CONFIG_CONCURRENT_MODE
if (rtw_mi_check_status(adapter, MI_LINKED) && (0 != rtw_mi_get_union_chan(adapter))) {
if ((remain_ch != rtw_mi_get_union_chan(adapter)) && !check_fwstate(&adapter->mlmepriv, WIFI_ASOC_STATE)) {
if (remain_ch != pmlmeext->cur_channel
#ifdef RTW_ROCH_BACK_OP
|| ATOMIC_READ(&pwdev_priv->switch_ch_to) == 1
#endif
) {
rtw_leave_opch(adapter);
#ifdef RTW_ROCH_BACK_OP
RTW_INFO("%s, set switch ch timer, duration=%d\n", __func__, prochinfo->max_away_dur);
ATOMIC_SET(&pwdev_priv->switch_ch_to, 0);
/* remain_ch is not same as union channel. duration is max_away_dur to
* back to AP's channel.
*/
_set_timer(&prochinfo->ap_roch_ch_switch_timer, prochinfo->max_away_dur);
#endif
}
}
ready_on_channel = _TRUE;
} else
#endif /* CONFIG_CONCURRENT_MODE */
{
if (remain_ch != rtw_get_oper_ch(adapter))
ready_on_channel = _TRUE;
}
if (ready_on_channel == _TRUE) {
#ifndef RTW_SINGLE_WIPHY
if (!check_fwstate(&adapter->mlmepriv, WIFI_ASOC_STATE))
#endif
{
#ifdef CONFIG_CONCURRENT_MODE
if (rtw_get_oper_ch(adapter) != remain_ch)
#endif
{
/* if (!padapter->mlmepriv.LinkDetectInfo.bBusyTraffic) */
set_channel_bwmode(adapter, remain_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
}
}
}
#ifdef CONFIG_BT_COEXIST
rtw_btcoex_ScanNotify(adapter, _TRUE);
#endif
RTW_INFO("%s, set ro ch timer, duration=%d\n", __func__, duration);
_set_timer(&prochinfo->remain_on_ch_timer, duration);
exit:
_exit_critical_mutex(&pwdev_priv->roch_mutex, NULL);
return ret;
}
static int rtw_cancel_ro_ch_handler(_adapter *padapter, u8 *buf)
{
int ret = H2C_SUCCESS;
struct rtw_roch_parm *roch_parm = (struct rtw_roch_parm *)buf;
struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
struct roch_info *prochinfo = &padapter->rochinfo;
struct wireless_dev *wdev;
#ifdef CONFIG_P2P
struct wifidirect_info *pwdinfo = &padapter->wdinfo;
#endif
u8 ch, bw, offset;
_enter_critical_mutex(&pwdev_priv->roch_mutex, NULL);
if (rtw_cfg80211_get_is_roch(padapter) != _TRUE)
goto exit;
if (roch_parm->wdev && roch_parm->cookie) {
if (prochinfo->ro_ch_wdev != roch_parm->wdev) {
RTW_WARN(FUNC_ADPT_FMT" ongoing wdev:%p, wdev:%p\n"
, FUNC_ADPT_ARG(padapter), prochinfo->ro_ch_wdev, roch_parm->wdev);
rtw_warn_on(1);
}
if (prochinfo->remain_on_ch_cookie != roch_parm->cookie) {
RTW_WARN(FUNC_ADPT_FMT" ongoing cookie:0x%llx, cookie:0x%llx\n"
, FUNC_ADPT_ARG(padapter), prochinfo->remain_on_ch_cookie, roch_parm->cookie);
rtw_warn_on(1);
}
}
#if defined(RTW_ROCH_BACK_OP) && defined(CONFIG_CONCURRENT_MODE)
_cancel_timer_ex(&prochinfo->ap_roch_ch_switch_timer);
ATOMIC_SET(&pwdev_priv->switch_ch_to, 1);
#endif
if (rtw_mi_get_ch_setting_union(padapter, &ch, &bw, &offset) != 0) {
if (0)
RTW_INFO(FUNC_ADPT_FMT" back to linked/linking union - ch:%u, bw:%u, offset:%u\n",
FUNC_ADPT_ARG(padapter), ch, bw, offset);
#ifdef CONFIG_P2P
} else if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->listen_channel) {
ch = pwdinfo->listen_channel;
bw = CHANNEL_WIDTH_20;
offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
if (0)
RTW_INFO(FUNC_ADPT_FMT" back to listen ch - ch:%u, bw:%u, offset:%u\n",
FUNC_ADPT_ARG(padapter), ch, bw, offset);
#endif
} else {
ch = prochinfo->restore_channel;
bw = CHANNEL_WIDTH_20;
offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
if (0)
RTW_INFO(FUNC_ADPT_FMT" back to restore ch - ch:%u, bw:%u, offset:%u\n",
FUNC_ADPT_ARG(padapter), ch, bw, offset);
}
set_channel_bwmode(padapter, ch, offset, bw);
rtw_back_opch(padapter);
#ifdef CONFIG_P2P
rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
#ifdef CONFIG_DEBUG_CFG80211
RTW_INFO("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));
#endif
#endif
wdev = prochinfo->ro_ch_wdev;
rtw_cfg80211_set_is_roch(padapter, _FALSE);
prochinfo->ro_ch_wdev = NULL;
rtw_cfg80211_set_last_ro_ch_time(padapter);
rtw_cfg80211_remain_on_channel_expired(wdev
, prochinfo->remain_on_ch_cookie
, &prochinfo->remain_on_ch_channel
, prochinfo->remain_on_ch_type, GFP_KERNEL);
RTW_INFO("cfg80211_remain_on_channel_expired cookie:0x%llx\n"
, prochinfo->remain_on_ch_cookie);
#ifdef CONFIG_BT_COEXIST
rtw_btcoex_ScanNotify(padapter, _FALSE);
#endif
exit:
_exit_critical_mutex(&pwdev_priv->roch_mutex, NULL);
return ret;
}
static void rtw_ro_ch_timer_process(void *FunctionContext)
{
_adapter *adapter = (_adapter *)FunctionContext;
rtw_cancel_roch_cmd(adapter, 0, NULL, 0);
}
#endif /* CONFIG_IOCTL_CFG80211 */
#if (defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)) || defined(CONFIG_IOCTL_CFG80211)
s32 rtw_roch_wk_hdl(_adapter *padapter, int intCmdType, u8 *buf)
{
int ret = H2C_SUCCESS;
switch (intCmdType) {
#ifdef CONFIG_IOCTL_CFG80211
case ROCH_RO_CH_WK:
ret = rtw_ro_ch_handler(padapter, buf);
break;
case ROCH_CANCEL_RO_CH_WK:
ret = rtw_cancel_ro_ch_handler(padapter, buf);
break;
#endif
#ifdef CONFIG_CONCURRENT_MODE
case ROCH_AP_ROCH_CH_SWITCH_PROCESS_WK:
rtw_concurrent_handler(padapter);
break;
#endif
default:
rtw_warn_on(1);
break;
}
return ret;
}
static int get_roch_parm_size(struct rtw_roch_parm *roch_parm)
{
#ifdef CONFIG_IOCTL_CFG80211
return (roch_parm ? sizeof(*roch_parm) : 0);
#else
rtw_warn_on(roch_parm);
return 0;
#endif
}
u8 rtw_roch_wk_cmd(_adapter *padapter, int intCmdType, struct rtw_roch_parm *roch_parm, u8 flags)
{
struct cmd_obj *ph2c = NULL;
struct drvextra_cmd_parm *pdrvextra_cmd_parm = NULL;
struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
struct submit_ctx sctx;
u8 res = _SUCCESS;
if (flags & RTW_CMDF_DIRECTLY) {
/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
if (H2C_SUCCESS != rtw_roch_wk_hdl(padapter, intCmdType, (u8 *)roch_parm))
res = _FAIL;
goto free_parm;
} else {
ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
if (!ph2c) {
res = _FAIL;
goto free_parm;
}
pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
if (!pdrvextra_cmd_parm) {
res = _FAIL;
goto free_parm;
}
pdrvextra_cmd_parm->ec_id = ROCH_WK_CID;
pdrvextra_cmd_parm->type = intCmdType;
pdrvextra_cmd_parm->size = get_roch_parm_size(roch_parm);
pdrvextra_cmd_parm->pbuf = (u8 *)roch_parm;
init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
if (flags & RTW_CMDF_WAIT_ACK) {
ph2c->sctx = &sctx;
rtw_sctx_init(&sctx, 10 * 1000);
}
res = rtw_enqueue_cmd(pcmdpriv, ph2c);
if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
rtw_sctx_wait(&sctx, __func__);
_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
if (sctx.status == RTW_SCTX_SUBMITTED)
ph2c->sctx = NULL;
_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
if (sctx.status != RTW_SCTX_DONE_SUCCESS)
res = _FAIL;
}
}
return res;
free_parm:
if (roch_parm)
rtw_mfree((u8 *)roch_parm, get_roch_parm_size(roch_parm));
if (ph2c)
rtw_mfree((u8 *)ph2c, sizeof(*ph2c));
return res;
}
#ifdef CONFIG_CONCURRENT_MODE
void rtw_ap_roch_ch_switch_timer_process(void *ctx)
{
_adapter *adapter = (_adapter *)ctx;
#ifdef CONFIG_IOCTL_CFG80211
struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);
#endif
#ifdef CONFIG_IOCTL_CFG80211
ATOMIC_SET(&pwdev_priv->switch_ch_to, 1);
#endif
rtw_roch_wk_cmd(adapter, ROCH_AP_ROCH_CH_SWITCH_PROCESS_WK, NULL, 0);
}
static bool chk_need_stay_in_cur_chan(_adapter *padapter)
{
#ifdef CONFIG_P2P
struct wifidirect_info *pwdinfo = &padapter->wdinfo;
/* When CONFIG_FULL_CH_IN_P2P_HANDSHAKE is defined and the
* interface is in the P2P_STATE_GONEGO_OK state, do not let the
* interface switch to the listen channel, because the interface will
* switch to the OP channel after the GO negotiation is successful.
*/
if (padapter->registrypriv.full_ch_in_p2p_handshake == 1 && rtw_p2p_chk_state(pwdinfo , P2P_STATE_GONEGO_OK)) {
RTW_INFO("%s, No linked interface now, but go nego ok, do not back to listen channel\n", __func__);
return _TRUE;
}
#endif
return _FALSE;
}
static bool chk_driver_interface(_adapter *padapter, u8 driver_interface)
{
#ifdef CONFIG_P2P
struct wifidirect_info *pwdinfo = &padapter->wdinfo;
if (pwdinfo->driver_interface == driver_interface)
return _TRUE;
#elif defined(CONFIG_IOCTL_CFG80211)
if (driver_interface == DRIVER_CFG80211)
return _TRUE;
#endif
return _FALSE;
}
static u8 get_remain_ch(_adapter *padapter)
{
struct roch_info *prochinfo = &padapter->rochinfo;
#ifdef CONFIG_P2P
struct wifidirect_info *pwdinfo = &padapter->wdinfo;
#endif
u8 remain_ch;
#ifdef CONFIG_P2P
remain_ch = pwdinfo->listen_channel;
#elif defined(CONFIG_IOCTL_CFG80211)
if (chk_driver_interface(padapter, DRIVER_CFG80211))
remain_ch = ieee80211_frequency_to_channel(prochinfo->remain_on_ch_channel.center_freq);
else
rtw_warn_on(1);
#endif
return remain_ch;
}
void rtw_concurrent_handler(_adapter *padapter)
{
#ifdef CONFIG_IOCTL_CFG80211
struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
#endif
struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
struct roch_info *prochinfo = &padapter->rochinfo;
#ifdef CONFIG_P2P
struct wifidirect_info *pwdinfo = &padapter->wdinfo;
u8 val8;
#endif
u8 remain_ch = get_remain_ch(padapter);
#ifdef CONFIG_IOCTL_CFG80211
if (chk_driver_interface(padapter, DRIVER_CFG80211)
&& !rtw_cfg80211_get_is_roch(padapter))
return;
#endif
if (rtw_mi_check_status(padapter, MI_LINKED)) {
u8 union_ch = rtw_mi_get_union_chan(padapter);
u8 union_bw = rtw_mi_get_union_bw(padapter);
u8 union_offset = rtw_mi_get_union_offset(padapter);
unsigned int duration;
#ifdef CONFIG_P2P
pwdinfo->operating_channel = union_ch;
#endif
if (chk_driver_interface(padapter, DRIVER_CFG80211)) {
#ifdef CONFIG_IOCTL_CFG80211
_enter_critical_mutex(&pwdev_priv->roch_mutex, NULL);
if (rtw_get_oper_ch(padapter) != union_ch) {
/* Current channel is not AP's channel - switching to AP's channel */
RTW_INFO("%s, switch ch back to union=%u,%u, %u\n"
, __func__, union_ch, union_bw, union_offset);
set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
rtw_back_opch(padapter);
/* Now, the driver stays on AP's channel. We should stay on AP's
* channel for min_home_dur (duration) and next switch channel is
* listen channel.
*/
duration = prochinfo->min_home_dur;
} else {
/* Current channel is AP's channel - switching to listen channel */
RTW_INFO("%s, switch ch to roch=%u\n"
, __func__, remain_ch);
rtw_leave_opch(padapter);
set_channel_bwmode(padapter,
remain_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
/* Now, the driver stays on listen channel. We should stay on listen
* channel for max_away_dur (duration) and next switch channel is AP's
* channel.
*/
duration = prochinfo->max_away_dur;
}
/* set channel switch timer */
ATOMIC_SET(&pwdev_priv->switch_ch_to, 0);
_set_timer(&prochinfo->ap_roch_ch_switch_timer, duration);
RTW_INFO("%s, set switch ch timer, duration=%d\n", __func__, duration);
_exit_critical_mutex(&pwdev_priv->roch_mutex, NULL);
#endif
}
#ifdef CONFIG_P2P
else if (chk_driver_interface(padapter, DRIVER_WEXT)) {
if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
/* Now, the driver stays on the AP's channel. */
/* If the pwdinfo->ext_listen_period = 0, that means the P2P listen state is not available on listen channel. */
if (pwdinfo->ext_listen_period > 0) {
RTW_INFO("[%s] P2P_STATE_IDLE, ext_listen_period = %d\n", __FUNCTION__, pwdinfo->ext_listen_period);
if (union_ch != pwdinfo->listen_channel) {
rtw_leave_opch(padapter);
set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
}
rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
if (!rtw_mi_check_mlmeinfo_state(padapter, WIFI_FW_AP_STATE)) {
val8 = 1;
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
}
/* Todo: To check the value of pwdinfo->ext_listen_period is equal to 0 or not. */
_set_timer(&prochinfo->ap_roch_ch_switch_timer, pwdinfo->ext_listen_period);
}
} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN) ||
rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL) ||
(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _FALSE) ||
rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ)) {
/* Now, the driver is in the listen state of P2P mode. */
RTW_INFO("[%s] P2P_STATE_IDLE, ext_listen_interval = %d\n", __FUNCTION__, pwdinfo->ext_listen_interval);
/* Commented by Albert 2012/11/01 */
/* If the AP's channel is the same as the listen channel, we should still be in the listen state */
/* Other P2P device is still able to find this device out even this device is in the AP's channel. */
/* So, configure this device to be able to receive the probe request frame and set it to listen state. */
if (union_ch != pwdinfo->listen_channel) {
set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
if (!rtw_mi_check_status(padapter, MI_AP_MODE)) {
val8 = 0;
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
}
rtw_p2p_set_state(pwdinfo, P2P_STATE_IDLE);
rtw_back_opch(padapter);
}
/* Todo: To check the value of pwdinfo->ext_listen_interval is equal to 0 or not. */
_set_timer(&prochinfo->ap_roch_ch_switch_timer, pwdinfo->ext_listen_interval);
} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK)) {
/* The driver had finished the P2P handshake successfully. */
val8 = 0;
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
rtw_back_opch(padapter);
} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
val8 = 1;
set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
issue_probereq_p2p(padapter, NULL);
_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _TRUE) {
val8 = 1;
set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
issue_probereq_p2p(padapter, NULL);
_set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ) && pwdinfo->invitereq_info.benable == _TRUE) {
/*
val8 = 1;
set_channel_bwmode(padapter, , HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
issue_probereq_p2p(padapter, NULL);
_set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
*/
}
}
#endif /* CONFIG_P2P */
} else if (!chk_need_stay_in_cur_chan(padapter)) {
set_channel_bwmode(padapter, remain_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
}
}
#endif /* CONFIG_CONCURRENT_MODE */
void rtw_init_roch_info(_adapter *padapter)
{
struct roch_info *prochinfo = &padapter->rochinfo;
_rtw_memset(prochinfo, 0x00, sizeof(struct roch_info));
#ifdef CONFIG_CONCURRENT_MODE
rtw_init_timer(&prochinfo->ap_roch_ch_switch_timer, padapter, rtw_ap_roch_ch_switch_timer_process, padapter);
#ifdef CONFIG_IOCTL_CFG80211
prochinfo->min_home_dur = 1500; /* min duration for traffic, home_time */
prochinfo->max_away_dur = 250; /* max acceptable away duration, home_away_time */
#endif
#endif
#ifdef CONFIG_IOCTL_CFG80211
rtw_init_timer(&prochinfo->remain_on_ch_timer, padapter, rtw_ro_ch_timer_process, padapter);
#endif
}
#endif /* (defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)) || defined(CONFIG_IOCTL_CFG80211) */

View File

@ -285,7 +285,9 @@ void rtw_rson_do_disconnect(_adapter *padapter)
pdvobj->rson_data.hopcnt = RTW_RSON_HC_NOTREADY;
pdvobj->rson_data.connectible = RTW_RSON_DENYCONNECT;
pdvobj->rson_data.loading = 0;
#ifdef CONFIG_AP_MODE
rtw_mi_tx_beacon_hdl(padapter);
#endif
#endif
}
@ -311,7 +313,9 @@ void rtw_rson_join_done(_adapter *padapter)
pdvobj->rson_data.hopcnt = rson_data.hopcnt + 1;
pdvobj->rson_data.connectible = RTW_RSON_ALLOWCONNECT;
pdvobj->rson_data.loading = 0;
#ifdef CONFIG_AP_MODE
rtw_mi_tx_beacon_hdl(padapter);
#endif
#endif
}
@ -497,7 +501,7 @@ u8 rtw_rson_scan_wk_cmd(_adapter *padapter, int op)
pdrvextra_cmd_parm->size = 0;
pdrvextra_cmd_parm->pbuf = NULL;
init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
res = rtw_enqueue_cmd(pcmdpriv, ph2c);
@ -535,13 +539,13 @@ void rtw_rson_scan_cmd_hdl(_adapter *padapter, int op)
if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) != _TRUE) {
int s_ret;
set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
set_fwstate(pmlmepriv, WIFI_UNDER_LINKING);
pmlmepriv->to_join = _FALSE;
s_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
if (s_ret == _SUCCESS)
_set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
else if (s_ret == 2) {
_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
_clr_fwstate_(pmlmepriv, WIFI_UNDER_LINKING);
rtw_indicate_connect(padapter);
} else {
RTW_INFO("try_to_join, but select scanning queue fail, to_roam:%d\n", rtw_to_roam(padapter));
@ -554,13 +558,13 @@ void rtw_rson_scan_cmd_hdl(_adapter *padapter, int op)
pmlmepriv->to_join = _TRUE;
} else
rtw_indicate_disconnect(padapter, 0, _FALSE);
_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
_clr_fwstate_(pmlmepriv, WIFI_UNDER_LINKING);
}
}
} else {
if (rtw_chk_roam_flags(padapter, RTW_ROAM_ACTIVE)) {
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)
&& check_fwstate(pmlmepriv, _FW_LINKED)) {
&& check_fwstate(pmlmepriv, WIFI_ASOC_STATE)) {
if (rtw_select_roaming_candidate(pmlmepriv) == _SUCCESS) {
#ifdef CONFIG_RTW_80211R
if (rtw_chk_ft_flags(padapter, RTW_FT_OVER_DS_SUPPORTED)) {

File diff suppressed because it is too large Load Diff

View File

@ -204,10 +204,14 @@ void sreset_restore_network_status(_adapter *padapter)
if (check_fwstate(mlmepriv, WIFI_STATION_STATE)) {
RTW_INFO(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_STATION_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
sreset_restore_network_station(padapter);
} else if (MLME_IS_AP(padapter) || MLME_IS_MESH(padapter)) {
}
#ifdef CONFIG_AP_MODE
else if (MLME_IS_AP(padapter) || MLME_IS_MESH(padapter)) {
RTW_INFO(FUNC_ADPT_FMT" %s\n", FUNC_ADPT_ARG(padapter), MLME_IS_AP(padapter) ? "AP" : "MESH");
rtw_ap_restore_network(padapter);
} else if (check_fwstate(mlmepriv, WIFI_ADHOC_STATE))
}
#endif
else if (check_fwstate(mlmepriv, WIFI_ADHOC_STATE))
RTW_INFO(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_ADHOC_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
else
RTW_INFO(FUNC_ADPT_FMT" fwstate:0x%08x - ???\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
@ -232,10 +236,10 @@ void sreset_stop_adapter(_adapter *padapter)
tasklet_kill(&pxmitpriv->xmit_tasklet);
#endif
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
if (check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY))
rtw_scan_abort(padapter);
if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
if (check_fwstate(pmlmepriv, WIFI_UNDER_LINKING)) {
rtw_set_to_roam(padapter, 0);
rtw_join_timeout_handler(padapter);
}
@ -252,7 +256,7 @@ void sreset_start_adapter(_adapter *padapter)
RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
if (check_fwstate(pmlmepriv, _FW_LINKED))
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE))
sreset_restore_network_status(padapter);
/* TODO: OS and HCI independent */
@ -298,7 +302,7 @@ void sreset_reset(_adapter *padapter)
_ips_enter(padapter);
_ips_leave(padapter);
#endif
#ifdef CONFIG_CONCURRENT_MODE
#if defined(CONFIG_AP_MODE) && defined(CONFIG_CONCURRENT_MODE)
rtw_mi_ap_info_restore(padapter);
#endif
rtw_mi_sreset_adapter_hdl(padapter, _TRUE);/*sreset_start_adapter*/

View File

@ -203,7 +203,9 @@ void _rtw_init_stainfo(struct sta_info *psta)
/* _rtw_init_listhead(&psta->wakeup_list); */
_rtw_init_queue(&psta->sleep_q);
#ifdef CONFIG_RTW_MGMT_QUEUE
_rtw_init_queue(&psta->mgmt_sleep_q);
#endif
_rtw_init_sta_xmit_priv(&psta->sta_xmitpriv);
_rtw_init_sta_recv_priv(&psta->sta_recvpriv);
@ -285,6 +287,9 @@ u32 _rtw_init_sta_priv(struct sta_priv *pstapriv)
_rtw_spinlock_init(&pstapriv->auth_list_lock);
pstapriv->asoc_list_cnt = 0;
pstapriv->auth_list_cnt = 0;
#ifdef CONFIG_RTW_TOKEN_BASED_XMIT
pstapriv->tbtx_asoc_list_cnt = 0;
#endif
pstapriv->auth_to = 3; /* 3*2 = 6 sec */
pstapriv->assoc_to = 3;
@ -300,12 +305,11 @@ u32 _rtw_init_sta_priv(struct sta_priv *pstapriv)
#endif
pstapriv->max_num_sta = NUM_STA;
#endif
#if CONFIG_RTW_MACADDR_ACL
for (i = 0; i < RTW_ACL_PERIOD_NUM; i++)
rtw_macaddr_acl_init(adapter, i);
#endif
#endif /* CONFIG_AP_MODE */
#if CONFIG_RTW_PRE_LINK_STA
rtw_pre_link_sta_ctl_init(pstapriv);
@ -365,6 +369,9 @@ void _rtw_free_sta_xmit_priv_lock(struct sta_xmit_priv *psta_xmitpriv)
_rtw_spinlock_free(&(psta_xmitpriv->bk_q.sta_pending.lock));
_rtw_spinlock_free(&(psta_xmitpriv->vi_q.sta_pending.lock));
_rtw_spinlock_free(&(psta_xmitpriv->vo_q.sta_pending.lock));
#ifdef CONFIG_RTW_MGMT_QUEUE
_rtw_spinlock_free(&(psta_xmitpriv->mgmt_q.sta_pending.lock));
#endif
}
static void _rtw_free_sta_recv_priv_lock(struct sta_recv_priv *psta_recvpriv)
@ -381,7 +388,7 @@ void rtw_mfree_stainfo(struct sta_info *psta);
void rtw_mfree_stainfo(struct sta_info *psta)
{
if (&(psta->lock) != NULL)
if (&psta->lock != NULL)
_rtw_spinlock_free(&psta->lock);
_rtw_free_sta_xmit_priv_lock(&psta->sta_xmitpriv);
@ -520,7 +527,7 @@ struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, const u8 *hwaddr)
_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
if (_rtw_queue_empty(pfree_sta_queue) == _TRUE) {
/* _exit_critical_bh(&(pfree_sta_queue->lock), &irqL); */
_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
/* _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL2); */
psta = NULL;
} else {
psta = LIST_CONTAINOR(get_next(&pfree_sta_queue->queue), struct sta_info, list);
@ -561,6 +568,8 @@ struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, const u8 *hwaddr)
_rtw_memcpy(&psta->sta_recvpriv.bmc_tid_rxseq[i], &wRxSeqInitialValue, 2);
_rtw_memset(&psta->sta_recvpriv.rxcache.iv[i], 0, sizeof(psta->sta_recvpriv.rxcache.iv[i]));
}
_rtw_memcpy(&psta->sta_recvpriv.nonqos_bmc_rxseq,&wRxSeqInitialValue,2);
_rtw_memcpy(&psta->sta_recvpriv.nonqos_rxseq,&wRxSeqInitialValue,2);
rtw_init_timer(&psta->addba_retry_timer, psta->padapter, addba_timer_hdl, psta);
#ifdef CONFIG_IEEE80211W
@ -582,7 +591,6 @@ struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, const u8 *hwaddr)
, FUNC_ADPT_ARG(pstapriv->padapter), i, preorder_ctrl->indicate_seq);
#endif
preorder_ctrl->wend_b = 0xffff;
/* preorder_ctrl->wsize_b = (NR_RECVBUFF-2); */
preorder_ctrl->wsize_b = 64;/* 64; */
preorder_ctrl->ampdu_size = RX_AMPDU_SIZE_INVALID;
@ -592,7 +600,7 @@ struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, const u8 *hwaddr)
rtw_clear_bit(RTW_RECV_ACK_OR_TIMEOUT, &preorder_ctrl->rec_abba_rsp_ack);
}
ATOMIC_SET(&psta->keytrack, 0);
/* init for DM */
psta->cmn.rssi_stat.rssi = (-1);
@ -601,6 +609,10 @@ struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, const u8 *hwaddr)
#ifdef CONFIG_ATMEL_RC_PATCH
psta->flag_atmel_rc = 0;
#endif
#ifdef CONFIG_RTW_TOKEN_BASED_XMIT
psta->tbtx_enable = _FALSE;
#endif
/* init for the sequence number of received management frame */
psta->RxMgmtFrameSeqNum = 0xffff;
_rtw_memset(&psta->sta_stats, 0, sizeof(struct stainfo_stats));
@ -629,7 +641,7 @@ u32 rtw_free_stainfo(_adapter *padapter , struct sta_info *psta)
{
int i;
_irqL irqL0;
_queue *pfree_sta_queue;
_queue *pfree_sta_queue, *pdefrag_q = NULL;
struct recv_reorder_ctrl *preorder_ctrl;
struct sta_xmit_priv *pstaxmitpriv;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
@ -637,9 +649,11 @@ u32 rtw_free_stainfo(_adapter *padapter , struct sta_info *psta)
struct hw_xmit *phwxmit;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
int pending_qcnt[4];
u8 is_pre_link_sta = _FALSE;
_list *phead, *plist;
_queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
union recv_frame *prframe;
if (psta == NULL)
goto exit;
@ -663,7 +677,7 @@ u32 rtw_free_stainfo(_adapter *padapter , struct sta_info *psta)
}
_enter_critical_bh(&psta->lock, &irqL0);
psta->state &= ~_FW_LINKED;
psta->state &= ~WIFI_ASOC_STATE;
_exit_critical_bh(&psta->lock, &irqL0);
pfree_sta_queue = &pstapriv->free_sta_queue;
@ -683,6 +697,11 @@ u32 rtw_free_stainfo(_adapter *padapter , struct sta_info *psta)
rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q);
psta->sleepq_len = 0;
#ifdef CONFIG_RTW_MGMT_QUEUE
rtw_free_mgmt_xmitframe_queue(pxmitpriv, &psta->mgmt_sleep_q);
psta->mgmt_sleepq_len = 0;
#endif
/* vo */
/* _enter_critical_bh(&(pxmitpriv->vo_pending.lock), &irqL0); */
rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
@ -723,6 +742,15 @@ u32 rtw_free_stainfo(_adapter *padapter , struct sta_info *psta)
pstaxmitpriv->bk_q.qcnt = 0;
/* _exit_critical_bh(&(pxmitpriv->bk_pending.lock), &irqL0); */
#ifdef CONFIG_RTW_MGMT_QUEUE
/* mgmt */
rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->mgmt_q.sta_pending);
rtw_list_delete(&(pstaxmitpriv->mgmt_q.tx_pending));
phwxmit = pxmitpriv->hwxmits + 4;
phwxmit->accnt -= pstaxmitpriv->mgmt_q.qcnt;
pstaxmitpriv->mgmt_q.qcnt = 0;
#endif
rtw_os_wake_queue_at_free_stainfo(padapter, pending_qcnt);
_exit_critical_bh(&pxmitpriv->lock, &irqL0);
@ -743,14 +771,11 @@ u32 rtw_free_stainfo(_adapter *padapter , struct sta_info *psta)
/* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */
for (i = 0; i < 16 ; i++) {
_irqL irqL;
_list *phead, *plist;
union recv_frame *prframe;
_queue *ppending_recvframe_queue;
_queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
preorder_ctrl = &psta->recvreorder_ctrl[i];
rtw_clear_bit(RTW_RECV_ACK_OR_TIMEOUT, &preorder_ctrl->rec_abba_rsp_ack);
_cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer);
@ -775,6 +800,20 @@ u32 rtw_free_stainfo(_adapter *padapter , struct sta_info *psta)
}
/* CVE-2020-24586, clear defrag queue */
pdefrag_q = &psta->sta_recvpriv.defrag_q;
enter_critical_bh(&pdefrag_q->lock);
phead = get_list_head(pdefrag_q);
plist = get_next(phead);
while (!rtw_is_list_empty(phead)) {
prframe = LIST_CONTAINOR(plist, union recv_frame, u);
plist = get_next(plist);
rtw_list_delete(&(prframe->u.hdr.list));
rtw_free_recvframe(prframe, pfree_recv_queue);
}
exit_critical_bh(&pdefrag_q->lock);
if (!((psta->state & WIFI_AP_STATE) || MacAddr_isBcst(psta->cmn.mac_addr)) && is_pre_link_sta == _FALSE)
rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _FALSE);
@ -828,9 +867,9 @@ u32 rtw_free_stainfo(_adapter *padapter , struct sta_info *psta)
#endif /* CONFIG_NATIVEAP_MLME */
#ifdef CONFIG_TX_MCAST2UNI
#if !defined(CONFIG_ACTIVE_KEEP_ALIVE_CHECK) && defined(CONFIG_80211N_HT)
psta->under_exist_checking = 0;
#endif /* CONFIG_TX_MCAST2UNI */
#endif
#endif /* CONFIG_AP_MODE */
@ -961,7 +1000,6 @@ u32 rtw_init_bcmc_stainfo(_adapter *padapter)
NDIS_802_11_MAC_ADDRESS bcast_addr = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
struct sta_priv *pstapriv = &padapter->stapriv;
/* _queue *pstapending = &padapter->xmitpriv.bm_pending; */
psta = rtw_alloc_stainfo(pstapriv, bcast_addr);

296
core/rtw_swcrypto.c Normal file
View File

@ -0,0 +1,296 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#include <drv_types.h>
#include <hal_data.h>
#include <aes.h>
#include <aes_siv.h>
#include <aes_wrap.h>
#include <sha256.h>
#include <wlancrypto_wrap.h>
/**
* rtw_ccmp_encrypt -
* @key: the temporal key
* @hdrlen: mac header length
* @frame: the frame including the mac header, pn and payload
* @plen: payload length, i.e., length of the plain text, without PN and MIC
*/
int _rtw_ccmp_encrypt(_adapter *padapter, u8 *key, u32 key_len, uint hdrlen, u8 *frame, uint plen)
{
u8 *enc = NULL;
size_t enc_len = 0;
if (key_len == 16) { /* 128 bits */
enc = ccmp_encrypt(padapter, key,
frame,
hdrlen + plen,
hdrlen,
(hdrlen == 26) ? (frame + hdrlen - 2) : NULL,
NULL, 0, &enc_len);
} else if (key_len == 32) { /* 256 bits */
enc = ccmp_256_encrypt(padapter, key,
frame,
hdrlen + plen,
hdrlen,
(hdrlen == 26) ? (frame + hdrlen - 2) : NULL,
NULL, 0, &enc_len);
}
if (enc == NULL) {
RTW_INFO("Failed to encrypt CCMP(%u) frame", key_len);
return _FAIL;
}
/* Copy @enc back to @frame and free @enc */
_rtw_memcpy(frame, enc, enc_len);
rtw_mfree(enc, enc_len + AES_BLOCK_SIZE);
return _SUCCESS;
}
/**
* rtw_ccmp_decrypt -
* @key: the temporal key
* @hdrlen: length of the mac header
* @frame: the raw frame (@hdrlen + PN + enc_data + MIC)
* @plen: length of the frame (@hdrlen + PN + enc_data + MIC)
*/
int _rtw_ccmp_decrypt(_adapter * padapter, u8 *key, u32 key_len, uint hdrlen, u8 *frame,
uint plen)
{
u8 *plain = NULL;
size_t plain_len = 0;
const struct ieee80211_hdr *hdr;
hdr = (const struct ieee80211_hdr *)frame;
if (key_len == 16) { /* 128 bits */
plain = ccmp_decrypt(padapter, key,
hdr,
frame + hdrlen, /* PN + enc_data + MIC */
plen - hdrlen, /* PN + enc_data + MIC */
&plain_len);
} else if (key_len == 32) { /* 256 bits */
plain = ccmp_256_decrypt(padapter, key,
hdr,
frame + hdrlen, /* PN + enc_data + MIC */
plen - hdrlen, /* PN + enc_data + MIC */
&plain_len);
}
if (plain == NULL) {
RTW_INFO("Failed to decrypt CCMP(%u) frame", key_len);
return _FAIL;
}
/* Copy @plain back to @frame and free @plain */
_rtw_memcpy(frame + hdrlen + 8, plain, plain_len);
rtw_mfree(plain, plen - hdrlen + AES_BLOCK_SIZE);
RTW_DBG_DUMP("ccmp_decrypt(): decrypted frame\n",
frame, hdrlen + 8 + plen);
return _SUCCESS;
}
#ifdef CONFIG_RTW_MESH_AEK
/* wrapper to ase_siv_encrypt and aes_siv_decrypt */
int _aes_siv_encrypt(const u8 *key, size_t key_len,
const u8 *pw, size_t pwlen,
size_t num_elem, const u8 *addr[], const size_t *len, u8 *out)
{
return aes_siv_encrypt(key, key_len, pw, pwlen, num_elem, addr, len, out);
}
int _aes_siv_decrypt(const u8 *key, size_t key_len,
const u8 *iv_crypt, size_t iv_c_len,
size_t num_elem, const u8 *addr[], const size_t *len, u8 *out)
{
return aes_siv_decrypt(key, key_len, iv_crypt, iv_c_len, num_elem, addr, len, out);
}
#endif
/**
* _rtw_gcmp_encrypt -
* @key: the temporal key
* @hdrlen: mac header length
* @frame: the frame including the mac header, pn and payload
* @plen: payload length, i.e., length of the plain text, without PN and MIC
*/
int _rtw_gcmp_encrypt(_adapter * padapter, u8 *key, u32 key_len, uint hdrlen, u8 *frame, uint plen)
{
u8 *enc = NULL;
size_t enc_len = 0;
enc = gcmp_encrypt(padapter, key, key_len,
frame,
hdrlen + plen,
hdrlen,
(hdrlen == 26) ? (frame + hdrlen - 2) : NULL,
NULL, 0, &enc_len);
if (enc == NULL) {
RTW_INFO("Failed to encrypt GCMP frame");
return _FAIL;
}
/* Copy @enc back to @frame and free @enc */
_rtw_memcpy(frame, enc, enc_len);
rtw_mfree(enc, enc_len + AES_BLOCK_SIZE);
return _SUCCESS;
}
/**
* _rtw_gcmp_decrypt -
* @key: the temporal key
* @hdrlen: length of the mac header
* @frame: the raw frame (@hdrlen + PN + enc_data + MIC)
* @plen: length of the frame (@hdrlen + PN + enc_data + MIC)
*/
int _rtw_gcmp_decrypt(_adapter *padapter, u8 *key, u32 key_len, uint hdrlen, u8 *frame, uint plen)
{
u8 *plain = NULL;
size_t plain_len = 0;
const struct ieee80211_hdr *hdr;
hdr = (const struct ieee80211_hdr *)frame;
plain = gcmp_decrypt(padapter, key, key_len,
hdr,
frame + hdrlen, /* PN + enc_data + MIC */
plen - hdrlen, /* PN + enc_data + MIC */
&plain_len);
if (plain == NULL) {
RTW_INFO("Failed to decrypt GCMP(%u) frame", key_len);
return _FAIL;
}
/* Copy @plain back to @frame and free @plain */
_rtw_memcpy(frame + hdrlen + 8, plain, plain_len);
rtw_mfree(plain, plen - hdrlen + AES_BLOCK_SIZE);
RTW_DBG_DUMP("gcmp_decipher(): decrypted frame\n",
frame, hdrlen + 8 + plen);
return _SUCCESS;
}
#if defined(CONFIG_IEEE80211W) | defined(CONFIG_TDLS)
u8 _bip_ccmp_protect(const u8 *key, size_t key_len,
const u8 *data, size_t data_len, u8 *mic)
{
u8 res = _SUCCESS;
if (key_len == 16) {
if (omac1_aes_128(key, data, data_len, mic)) {
res = _FAIL;
RTW_ERR("%s : omac1_aes_128 fail!", __func__);
}
} else if (key_len == 32) {
if (omac1_aes_256(key, data, data_len, mic)) {
res = _FAIL;
RTW_ERR("%s : omac1_aes_256 fail!", __func__);
}
} else {
RTW_ERR("%s : key_len not match!", __func__);
res = _FAIL;
}
return res;
}
u8 _bip_gcmp_protect(u8 *whdr_pos, size_t len,
const u8 *key, size_t key_len,
const u8 *data, size_t data_len, u8 *mic)
{
u8 res = _SUCCESS;
u32 mic_len = 16;
u8 nonce[12], *npos;
const u8 *gcmp_ipn;
gcmp_ipn = whdr_pos + len - mic_len - 6;
/* Nonce: A2 | IPN */
_rtw_memcpy(nonce, get_addr2_ptr(whdr_pos), ETH_ALEN);
npos = nonce + ETH_ALEN;
*npos++ = gcmp_ipn[5];
*npos++ = gcmp_ipn[4];
*npos++ = gcmp_ipn[3];
*npos++ = gcmp_ipn[2];
*npos++ = gcmp_ipn[1];
*npos++ = gcmp_ipn[0];
if (aes_gmac(key, key_len, nonce, sizeof(nonce),
data, data_len, mic)) {
res = _FAIL;
RTW_ERR("%s : aes_gmac fail!", __func__);
}
return res;
}
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_TDLS
void _tdls_generate_tpk(void *sta, const u8 *own_addr, const u8 *bssid)
{
struct sta_info *psta = (struct sta_info *)sta;
u8 *SNonce = psta->SNonce;
u8 *ANonce = psta->ANonce;
u8 key_input[SHA256_MAC_LEN];
const u8 *nonce[2];
size_t len[2];
u8 data[3 * ETH_ALEN];
/* IEEE Std 802.11z-2010 8.5.9.1:
* TPK-Key-Input = SHA-256(min(SNonce, ANonce) || max(SNonce, ANonce))
*/
len[0] = 32;
len[1] = 32;
if (_rtw_memcmp2(SNonce, ANonce, 32) < 0) {
nonce[0] = SNonce;
nonce[1] = ANonce;
} else {
nonce[0] = ANonce;
nonce[1] = SNonce;
}
sha256_vector(2, nonce, len, key_input);
/*
* TPK = KDF-Hash-Length(TPK-Key-Input, "TDLS PMK",
* min(MAC_I, MAC_R) || max(MAC_I, MAC_R) || BSSID)
*/
if (_rtw_memcmp2(own_addr, psta->cmn.mac_addr, ETH_ALEN) < 0) {
_rtw_memcpy(data, own_addr, ETH_ALEN);
_rtw_memcpy(data + ETH_ALEN, psta->cmn.mac_addr, ETH_ALEN);
} else {
_rtw_memcpy(data, psta->cmn.mac_addr, ETH_ALEN);
_rtw_memcpy(data + ETH_ALEN, own_addr, ETH_ALEN);
}
_rtw_memcpy(data + 2 * ETH_ALEN, bssid, ETH_ALEN);
sha256_prf(key_input, SHA256_MAC_LEN, "TDLS PMK", data, sizeof(data), (u8 *)&psta->tpk, sizeof(psta->tpk));
}
#endif /* CONFIG_TDLS */

View File

@ -930,6 +930,7 @@ u8 *rtw_tdls_set_ch_sw(u8 *pframe, struct pkt_attrib *pattrib, struct sta_info *
void rtw_tdls_set_ch_sw_oper_control(_adapter *padapter, u8 enable)
{
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
u8 bcn_early_case;
if (enable == _TRUE) {
#ifdef CONFIG_TDLS_CH_SW_V2
@ -939,14 +940,18 @@ void rtw_tdls_set_ch_sw_oper_control(_adapter *padapter, u8 enable)
#ifdef CONFIG_TDLS_CH_SW_BY_DRV
pHalData->ch_switch_offload = _FALSE;
#endif
bcn_early_case = TDLS_BCN_ERLY_ON;
}
else
else {
pHalData->ch_switch_offload = _FALSE;
bcn_early_case = TDLS_BCN_ERLY_OFF;
}
if (ATOMIC_READ(&padapter->tdlsinfo.chsw_info.chsw_on) != enable)
ATOMIC_SET(&padapter->tdlsinfo.chsw_info.chsw_on, enable);
rtw_hal_set_hwreg(padapter, HW_VAR_TDLS_BCN_EARLY_C2H_RPT, &enable);
rtw_hal_set_hwreg(padapter, HW_VAR_BCN_EARLY_C2H_RPT, &enable);
rtw_hal_set_hwreg(padapter, HW_VAR_SET_DRV_ERLY_INT, &bcn_early_case);
RTW_INFO("[TDLS] %s Bcn Early C2H Report\n", (enable == _TRUE) ? "Start" : "Stop");
}
@ -962,6 +967,7 @@ void rtw_tdls_ch_sw_back_to_base_chnl(_adapter *padapter)
rtw_tdls_cmd(padapter, pchsw_info->addr, TDLS_CH_SW_TO_BASE_CHNL_UNSOLICITED);
}
#ifndef CONFIG_TDLS_CH_SW_V2
static void rtw_tdls_chsw_oper_init(_adapter *padapter, u32 timeout_ms)
{
struct submit_ctx *chsw_sctx = &padapter->tdlsinfo.chsw_info.chsw_sctx;
@ -982,6 +988,7 @@ void rtw_tdls_chsw_oper_done(_adapter *padapter)
rtw_sctx_done(&chsw_sctx);
}
#endif
s32 rtw_tdls_do_ch_sw(_adapter *padapter, struct sta_info *ptdls_sta, u8 chnl_type, u8 channel, u8 channel_offset, u16 bwmode, u16 ch_switch_time)
{
@ -1814,9 +1821,9 @@ int On_TDLS_Dis_Rsp(_adapter *padapter, union recv_frame *precv_frame)
issue_tdls_setup_req(padapter, &txmgmt, _FALSE);
}
}
exit:
#endif /* CONFIG_TDLS_AUTOSETUP */
exit:
return ret;
}
@ -2199,7 +2206,7 @@ int On_TDLS_Setup_Rsp(_adapter *padapter, union recv_frame *precv_frame, struct
if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE) {
ptdls_sta->tdls_sta_state |= TDLS_LINKED_STATE;
ptdls_sta->state |= _FW_LINKED;
ptdls_sta->state |= WIFI_ASOC_STATE;
_cancel_timer_ex(&ptdls_sta->handshake_timer);
}
@ -2316,7 +2323,7 @@ int On_TDLS_Setup_Cfm(_adapter *padapter, union recv_frame *precv_frame, struct
if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE) {
ptdls_sta->tdls_sta_state |= TDLS_LINKED_STATE;
ptdls_sta->state |= _FW_LINKED;
ptdls_sta->state |= WIFI_ASOC_STATE;
_cancel_timer_ex(&ptdls_sta->handshake_timer);
}
@ -2590,6 +2597,7 @@ sint On_TDLS_Ch_Switch_Req(_adapter *padapter, union recv_frame *precv_frame, st
j += (pIE->Length + 2);
}
#ifndef CONFIG_TDLS_CH_SW_V2
rtw_hal_get_hwreg(padapter, HW_VAR_CH_SW_NEED_TO_TAKE_CARE_IQK_INFO, &take_care_iqk);
if (take_care_iqk == _TRUE) {
u8 central_chnl;
@ -2604,6 +2612,7 @@ sint On_TDLS_Ch_Switch_Req(_adapter *padapter, union recv_frame *precv_frame, st
return _FAIL;
}
}
#endif
/* cancel ch sw monitor timer for responder */
if (!(pchsw_info->ch_sw_state & TDLS_CH_SW_INITIATOR_STATE))
@ -2768,7 +2777,7 @@ void wfd_ie_tdls(_adapter *padapter, u8 *pframe, u32 *pktlen)
/* Value: */
/* Associated BSSID */
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
else
_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);

View File

@ -32,6 +32,7 @@ const u8 _vht_sup_ch_width_set_to_bw_cap[] = {
0,
};
#ifdef CONFIG_RTW_DEBUG
const char *const _vht_sup_ch_width_set_str[] = {
"80MHz",
"160MHz",
@ -104,40 +105,47 @@ void dump_vht_op_ie(void *sel, const u8 *ie, u32 ie_len)
dump_vht_op_ie_content(sel, vht_op_ie + 2, vht_op_ielen);
}
#endif
/* 20/40/80, ShortGI, MCS Rate */
const u16 VHT_MCS_DATA_RATE[3][2][30] = {
const u16 VHT_MCS_DATA_RATE[3][2][40] = { /* unit: 0.5M */
{ {
13, 26, 39, 52, 78, 104, 117, 130, 156, 156,
26, 52, 78, 104, 156, 208, 234, 260, 312, 312,
39, 78, 117, 156, 234, 312, 351, 390, 468, 520
39, 78, 117, 156, 234, 312, 351, 390, 468, 520,
52, 104, 156, 208, 312, 416, 468, 520, 624, 624,
}, /* Long GI, 20MHz */
{
14, 29, 43, 58, 87, 116, 130, 144, 173, 173,
29, 58, 87, 116, 173, 231, 260, 289, 347, 347,
43, 87, 130, 173, 260, 347, 390, 433, 520, 578
43, 87, 130, 173, 260, 347, 390, 433, 520, 578,
58, 116, 173, 231, 347, 462, 520, 578, 693, 693,
}
}, /* Short GI, 20MHz */
{ {
27, 54, 81, 108, 162, 216, 243, 270, 324, 360,
54, 108, 162, 216, 324, 432, 486, 540, 648, 720,
81, 162, 243, 324, 486, 648, 729, 810, 972, 1080
81, 162, 243, 324, 486, 648, 729, 810, 972, 1080,
108, 216, 324, 432, 648, 864, 972, 1080, 1296, 1440,
}, /* Long GI, 40MHz */
{
30, 60, 90, 120, 180, 240, 270, 300, 360, 400,
60, 120, 180, 240, 360, 480, 540, 600, 720, 800,
90, 180, 270, 360, 540, 720, 810, 900, 1080, 1200
90, 180, 270, 360, 540, 720, 810, 900, 1080, 1200,
120, 240, 360, 480, 720, 960, 1080, 1200, 1440, 1600,
}
}, /* Short GI, 40MHz */
{ {
59, 117, 176, 234, 351, 468, 527, 585, 702, 780,
59, 117, 176, 234, 351, 468, 527, 585, 702, 780,
117, 234, 351, 468, 702, 936, 1053, 1170, 1404, 1560,
176, 351, 527, 702, 1053, 1404, 1580, 1755, 2106, 2340
176, 351, 527, 702, 1053, 1404, 1580, 1755, 2106, 2340,
234, 468, 702, 936, 1404, 1872, 2106, 2340, 2808, 3120,
}, /* Long GI, 80MHz */
{
65, 130, 195, 260, 390, 520, 585, 650, 780, 867,
130, 260, 390, 520, 780, 1040, 1170, 1300, 1560, 1734,
195, 390, 585, 780, 1170, 1560, 1755, 1950, 2340, 2600
195, 390, 585, 780, 1170, 1560, 1755, 1950, 2340, 2600,
260, 520, 780, 1040, 1560, 2080, 2340, 2600, 3120, 3467,
}
} /* Short GI, 80MHz */
};
@ -209,8 +217,8 @@ void rtw_vht_nss_to_mcsmap(u8 nss, u8 *target_mcs_map, u8 *cur_mcs_map)
u16 rtw_vht_mcs_to_data_rate(u8 bw, u8 short_GI, u8 vht_mcs_rate)
{
if (vht_mcs_rate > MGN_VHT3SS_MCS9)
vht_mcs_rate = MGN_VHT3SS_MCS9;
if (vht_mcs_rate > MGN_VHT4SS_MCS9)
vht_mcs_rate = MGN_VHT4SS_MCS9;
/* RTW_INFO("bw=%d, short_GI=%d, ((vht_mcs_rate - MGN_VHT1SS_MCS0)&0x3f)=%d\n", bw, short_GI, ((vht_mcs_rate - MGN_VHT1SS_MCS0)&0x3f)); */
return VHT_MCS_DATA_RATE[bw][short_GI][((vht_mcs_rate - MGN_VHT1SS_MCS0) & 0x3f)];
}
@ -264,10 +272,13 @@ void rtw_vht_use_default_setting(_adapter *padapter)
CLEAR_FLAGS(pvhtpriv->beamform_cap);
#ifdef CONFIG_BEAMFORMING
#ifdef RTW_BEAMFORMING_VERSION_2
#ifdef CONFIG_CONCURRENT_MODE
/* only enable beamforming in STA client mode */
if (MLME_IS_STA(padapter) && !MLME_IS_GC(padapter)
&& !MLME_IS_ADHOC(padapter)
&& !MLME_IS_MESH(padapter))
if (MLME_IS_STA(padapter) && !MLME_IS_GC(padapter))
#else
if ((MLME_IS_AP(padapter) && !MLME_IS_GO(padapter)) ||
(MLME_IS_STA(padapter) && !MLME_IS_GC(padapter)))
#endif
#endif
{
rtw_hal_get_def_var(padapter, HAL_DEF_EXPLICIT_BEAMFORMER,
@ -336,13 +347,13 @@ u64 rtw_vht_mcs_map_to_bitmap(u8 *mcs_map, u8 nss)
switch (tmp) {
case 2:
bitmap = bitmap | (0x03ff << j);
bitmap = bitmap | ((u64)0x03ff << j);
break;
case 1:
bitmap = bitmap | (0x01ff << j);
bitmap = bitmap | ((u64)0x01ff << j);
break;
case 0:
bitmap = bitmap | (0x00ff << j);
bitmap = bitmap | ((u64)0x00ff << j);
break;
default:
break;
@ -562,7 +573,7 @@ void VHT_caps_handler(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
u8 cur_ldpc_cap = 0, cur_stbc_cap = 0, tx_nss = 0;
u8 cur_ldpc_cap = 0, cur_stbc_cap = 0, rx_nss = 0;
u16 cur_beamform_cap = 0;
u8 *pcap_mcs;
@ -663,8 +674,8 @@ void VHT_caps_handler(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
pvhtpriv->ampdu_len = GET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pIE->data);
pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(pIE->data);
tx_nss = GET_HAL_TX_NSS(padapter);
rtw_vht_nss_to_mcsmap(tx_nss, pvhtpriv->vht_mcs_map, pcap_mcs);
rx_nss = GET_HAL_RX_NSS(padapter);
rtw_vht_nss_to_mcsmap(rx_nss, pvhtpriv->vht_mcs_map, pcap_mcs);
pvhtpriv->vht_highest_rate = rtw_get_vht_highest_rate(pvhtpriv->vht_mcs_map);
}
@ -1057,6 +1068,7 @@ void VHTOnAssocRsp(_adapter *padapter)
rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MAX_TIME, (u8 *)(&pvhtpriv->vht_highest_rate));
}
#ifdef CONFIG_AP_MODE
void rtw_vht_ies_attach(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
{
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
@ -1125,4 +1137,5 @@ void rtw_check_for_vht20(_adapter *adapter, u8 *ies, int ies_len)
}
}
}
#endif /* CONFIG_AP_MODE */
#endif /* CONFIG_80211AC_VHT */

File diff suppressed because it is too large Load Diff

1098
core/rtw_wnm.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

786
core/wds/rtw_wds.c Normal file
View File

@ -0,0 +1,786 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#define _RTW_WDS_C_
#include <drv_types.h>
#if defined(CONFIG_RTW_WDS)
#include <linux/jhash.h>
#if defined(CONFIG_AP_MODE)
#ifdef PLATFORM_LINUX
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
static void rtw_wpath_free_rcu(struct rtw_wds_path *wpath)
{
kfree_rcu(wpath, rcu);
rtw_mstat_update(MSTAT_TYPE_PHY, MSTAT_FREE, sizeof(struct rtw_wds_path));
}
#else
static void rtw_wpath_free_rcu_callback(rtw_rcu_head *head)
{
struct rtw_wds_path *wpath;
wpath = container_of(head, struct rtw_wds_path, rcu);
rtw_mfree(wpath, sizeof(struct rtw_wds_path));
}
static void rtw_wpath_free_rcu(struct rtw_wds_path *wpath)
{
call_rcu(&wpath->rcu, rtw_wpath_free_rcu_callback);
}
#endif
#endif /* PLATFORM_LINUX */
static void rtw_wds_path_free_rcu(struct rtw_wds_table *tbl, struct rtw_wds_path *wpath);
static u32 rtw_wds_table_hash(const void *addr, u32 len, u32 seed)
{
/* Use last four bytes of hw addr as hash index */
return jhash_1word(*(u32 *)(addr+2), seed);
}
static const rtw_rhashtable_params rtw_wds_rht_params = {
.nelem_hint = 2,
.automatic_shrinking = true,
.key_len = ETH_ALEN,
.key_offset = offsetof(struct rtw_wds_path, dst),
.head_offset = offsetof(struct rtw_wds_path, rhash),
.hashfn = rtw_wds_table_hash,
};
static void rtw_wds_path_rht_free(void *ptr, void *tblptr)
{
struct rtw_wds_path *wpath = ptr;
struct rtw_wds_table *tbl = tblptr;
rtw_wds_path_free_rcu(tbl, wpath);
}
static struct rtw_wds_table *rtw_wds_table_alloc(void)
{
struct rtw_wds_table *newtbl;
newtbl = rtw_malloc(sizeof(struct rtw_wds_table));
if (!newtbl)
return NULL;
return newtbl;
}
static void rtw_wds_table_free(struct rtw_wds_table *tbl)
{
rtw_rhashtable_free_and_destroy(&tbl->rhead,
rtw_wds_path_rht_free, tbl);
rtw_mfree(tbl, sizeof(struct rtw_wds_table));
}
void rtw_wds_path_assign_nexthop(struct rtw_wds_path *wpath, struct sta_info *sta)
{
rtw_rcu_assign_pointer(wpath->next_hop, sta);
}
static struct rtw_wds_path *rtw_wpath_lookup(struct rtw_wds_table *tbl, const u8 *dst)
{
struct rtw_wds_path *wpath;
if (!tbl)
return NULL;
wpath = rtw_rhashtable_lookup_fast(&tbl->rhead, dst, rtw_wds_rht_params);
return wpath;
}
struct rtw_wds_path *rtw_wds_path_lookup(_adapter *adapter, const u8 *dst)
{
return rtw_wpath_lookup(adapter->wds_paths, dst);
}
static struct rtw_wds_path *
__rtw_wds_path_lookup_by_idx(struct rtw_wds_table *tbl, int idx)
{
int i = 0, ret;
struct rtw_wds_path *wpath = NULL;
rtw_rhashtable_iter iter;
if (!tbl)
return NULL;
ret = rtw_rhashtable_walk_enter(&tbl->rhead, &iter);
if (ret)
return NULL;
ret = rtw_rhashtable_walk_start(&iter);
if (ret && ret != -EAGAIN)
goto err;
while ((wpath = rtw_rhashtable_walk_next(&iter))) {
if (IS_ERR(wpath) && PTR_ERR(wpath) == -EAGAIN)
continue;
if (IS_ERR(wpath))
break;
if (i++ == idx)
break;
}
err:
rtw_rhashtable_walk_stop(&iter);
rtw_rhashtable_walk_exit(&iter);
if (IS_ERR(wpath) || !wpath)
return NULL;
return wpath;
}
/**
* Locking: must be called within a read rcu section.
*/
struct rtw_wds_path *
rtw_wds_path_lookup_by_idx(_adapter *adapter, int idx)
{
return __rtw_wds_path_lookup_by_idx(adapter->wds_paths, idx);
}
void dump_wpath(void *sel, _adapter *adapter)
{
struct rtw_wds_path *wpath;
int idx = 0;
char dst[ETH_ALEN];
char next_hop[ETH_ALEN];
u32 age_ms;
RTW_PRINT_SEL(sel, "num:%d\n", ATOMIC_READ(&adapter->wds_path_num));
RTW_PRINT_SEL(sel, "%-17s %-17s %-6s\n"
, "dst", "next_hop", "age"
);
do {
rtw_rcu_read_lock();
wpath = rtw_wds_path_lookup_by_idx(adapter, idx);
if (wpath) {
_rtw_memcpy(dst, wpath->dst, ETH_ALEN);
_rtw_memcpy(next_hop, wpath->next_hop->cmn.mac_addr, ETH_ALEN);
age_ms = rtw_get_passing_time_ms(wpath->last_update);
}
rtw_rcu_read_unlock();
if (wpath) {
RTW_PRINT_SEL(sel, MAC_FMT" "MAC_FMT" %6u\n"
, MAC_ARG(dst), MAC_ARG(next_hop)
, age_ms < 999999 ? age_ms : 999999
);
}
idx++;
} while (wpath);
}
static
struct rtw_wds_path *rtw_wds_path_new(_adapter *adapter,
const u8 *dst)
{
struct rtw_wds_path *new_wpath;
new_wpath = rtw_zmalloc(sizeof(struct rtw_wds_path));
if (!new_wpath)
return NULL;
new_wpath->adapter = adapter;
_rtw_memcpy(new_wpath->dst, dst, ETH_ALEN);
new_wpath->last_update = rtw_get_current_time();
return new_wpath;
}
/**
* Returns: 0 on success
*
* State: the initial state of the new path is set to 0
*/
struct rtw_wds_path *rtw_wds_path_add(_adapter *adapter,
const u8 *dst, struct sta_info *next_hop)
{
struct rtw_wds_table *tbl = adapter->wds_paths;
struct rtw_wds_path *wpath, *new_wpath;
int ret;
if (!tbl)
return ERR_PTR(-ENOTSUPP);
if (_rtw_memcmp(dst, adapter_mac_addr(adapter), ETH_ALEN) == _TRUE)
/* never add ourselves as neighbours */
return ERR_PTR(-ENOTSUPP);
if (IS_MCAST(dst))
return ERR_PTR(-ENOTSUPP);
if (ATOMIC_INC_UNLESS(&adapter->wds_path_num, RTW_WDS_MAX_PATHS) == 0)
return ERR_PTR(-ENOSPC);
new_wpath = rtw_wds_path_new(adapter, dst);
if (!new_wpath)
return ERR_PTR(-ENOMEM);
do {
ret = rtw_rhashtable_lookup_insert_fast(&tbl->rhead,
&new_wpath->rhash,
rtw_wds_rht_params);
if (ret == -EEXIST)
wpath = rtw_rhashtable_lookup_fast(&tbl->rhead,
dst,
rtw_wds_rht_params);
} while (unlikely(ret == -EEXIST && !wpath));
if (ret && ret != -EEXIST)
return ERR_PTR(ret);
/* At this point either new_wpath was added, or we found a
* matching entry already in the table; in the latter case
* free the unnecessary new entry.
*/
if (ret == -EEXIST) {
rtw_mfree(new_wpath, sizeof(struct rtw_wds_path));
new_wpath = wpath;
}
rtw_wds_path_assign_nexthop(new_wpath, next_hop);
return new_wpath;
}
static void rtw_wds_path_free_rcu(struct rtw_wds_table *tbl,
struct rtw_wds_path *wpath)
{
_adapter *adapter = wpath->adapter;
ATOMIC_DEC(&adapter->wds_path_num);
rtw_wpath_free_rcu(wpath);
}
static void __rtw_wds_path_del(struct rtw_wds_table *tbl, struct rtw_wds_path *wpath)
{
rtw_rhashtable_remove_fast(&tbl->rhead, &wpath->rhash, rtw_wds_rht_params);
rtw_wds_path_free_rcu(tbl, wpath);
}
void rtw_wds_path_flush_by_nexthop(struct sta_info *sta)
{
_adapter *adapter = sta->padapter;
struct rtw_wds_table *tbl = adapter->wds_paths;
struct rtw_wds_path *wpath;
rtw_rhashtable_iter iter;
int ret;
if (!tbl)
return;
ret = rtw_rhashtable_walk_enter(&tbl->rhead, &iter);
if (ret)
return;
ret = rtw_rhashtable_walk_start(&iter);
if (ret && ret != -EAGAIN)
goto out;
while ((wpath = rtw_rhashtable_walk_next(&iter))) {
if (IS_ERR(wpath) && PTR_ERR(wpath) == -EAGAIN)
continue;
if (IS_ERR(wpath))
break;
if (rtw_rcu_access_pointer(wpath->next_hop) == sta)
__rtw_wds_path_del(tbl, wpath);
}
out:
rtw_rhashtable_walk_stop(&iter);
rtw_rhashtable_walk_exit(&iter);
}
static void rtw_wds_table_flush_by_iface(struct rtw_wds_table *tbl)
{
struct rtw_wds_path *wpath;
rtw_rhashtable_iter iter;
int ret;
if (!tbl)
return;
ret = rtw_rhashtable_walk_enter(&tbl->rhead, &iter);
if (ret)
return;
ret = rtw_rhashtable_walk_start(&iter);
if (ret && ret != -EAGAIN)
goto out;
while ((wpath = rtw_rhashtable_walk_next(&iter))) {
if (IS_ERR(wpath) && PTR_ERR(wpath) == -EAGAIN)
continue;
if (IS_ERR(wpath))
break;
__rtw_wds_path_del(tbl, wpath);
}
out:
rtw_rhashtable_walk_stop(&iter);
rtw_rhashtable_walk_exit(&iter);
}
void rtw_wds_path_flush_by_iface(_adapter *adapter)
{
rtw_wds_table_flush_by_iface(adapter->wds_paths);
}
static int rtw_wds_table_path_del(struct rtw_wds_table *tbl,
const u8 *addr)
{
struct rtw_wds_path *wpath;
if (!tbl)
return -ENXIO;
rtw_rcu_read_lock();
wpath = rtw_rhashtable_lookup_fast(&tbl->rhead, addr, rtw_wds_rht_params);
if (!wpath) {
rtw_rcu_read_unlock();
return -ENXIO;
}
__rtw_wds_path_del(tbl, wpath);
rtw_rcu_read_unlock();
return 0;
}
int rtw_wds_path_del(_adapter *adapter, const u8 *addr)
{
int err;
err = rtw_wds_table_path_del(adapter->wds_paths, addr);
return err;
}
int rtw_wds_pathtbl_init(_adapter *adapter)
{
struct rtw_wds_table *tbl_path;
int ret;
tbl_path = rtw_wds_table_alloc();
if (!tbl_path)
return -ENOMEM;
rtw_rhashtable_init(&tbl_path->rhead, &rtw_wds_rht_params);
ATOMIC_SET(&adapter->wds_path_num, 0);
adapter->wds_paths = tbl_path;
return 0;
}
static
void rtw_wds_path_tbl_expire(_adapter *adapter,
struct rtw_wds_table *tbl)
{
struct rtw_wds_path *wpath;
rtw_rhashtable_iter iter;
int ret;
if (!tbl)
return;
ret = rtw_rhashtable_walk_enter(&tbl->rhead, &iter);
if (ret)
return;
ret = rtw_rhashtable_walk_start(&iter);
if (ret && ret != -EAGAIN)
goto out;
while ((wpath = rtw_rhashtable_walk_next(&iter))) {
if (IS_ERR(wpath) && PTR_ERR(wpath) == -EAGAIN)
continue;
if (IS_ERR(wpath))
break;
if (rtw_time_after(rtw_get_current_time(), wpath->last_update + RTW_WDS_PATH_EXPIRE))
__rtw_wds_path_del(tbl, wpath);
}
out:
rtw_rhashtable_walk_stop(&iter);
rtw_rhashtable_walk_exit(&iter);
}
void rtw_wds_path_expire(_adapter *adapter)
{
rtw_wds_path_tbl_expire(adapter, adapter->wds_paths);
}
void rtw_wds_pathtbl_unregister(_adapter *adapter)
{
if (adapter->wds_paths) {
rtw_wds_table_free(adapter->wds_paths);
adapter->wds_paths = NULL;
}
}
int rtw_wds_nexthop_lookup(_adapter *adapter, const u8 *da, u8 *ra)
{
struct rtw_wds_path *wpath;
struct sta_info *next_hop;
int err = -ENOENT;
rtw_rcu_read_lock();
wpath = rtw_wds_path_lookup(adapter, da);
if (!wpath)
goto endlookup;
next_hop = rtw_rcu_dereference(wpath->next_hop);
if (next_hop) {
_rtw_memcpy(ra, next_hop->cmn.mac_addr, ETH_ALEN);
err = 0;
}
endlookup:
rtw_rcu_read_unlock();
return err;
}
#endif /* defined(CONFIG_AP_MODE) */
/* WDS group adddressed proxy TX record */
struct rtw_wds_gptr {
u8 src[ETH_ALEN];
systime last_update;
rtw_rhash_head rhash;
_adapter *adapter;
rtw_rcu_head rcu;
};
#define RTW_WDS_GPTR_EXPIRE (2 * HZ)
/* Maximum number of gptrs per interface */
#define RTW_WDS_MAX_GPTRS 1024
#ifdef PLATFORM_LINUX
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
static void rtw_wgptr_free_rcu(struct rtw_wds_gptr *wgptr)
{
kfree_rcu(wgptr, rcu);
rtw_mstat_update(MSTAT_TYPE_PHY, MSTAT_FREE, sizeof(struct rtw_wds_gptr));
}
#else
static void rtw_wgptr_free_rcu_callback(rtw_rcu_head *head)
{
struct rtw_wds_gptr *wgptr;
wgptr = container_of(head, struct rtw_wds_gptr, rcu);
rtw_mfree(wgptr, sizeof(struct rtw_wds_gptr));
}
static void rtw_wgptr_free_rcu(struct rtw_wds_gptr *wgptr)
{
call_rcu(&wgptr->rcu, rtw_wgptr_free_rcu_callback);
}
#endif
#endif /* PLATFORM_LINUX */
static void rtw_wds_gptr_free_rcu(struct rtw_wds_gptr_table *tbl, struct rtw_wds_gptr *wgptr)
{
_adapter *adapter = wgptr->adapter;
ATOMIC_DEC(&adapter->wds_gpt_record_num);
rtw_wgptr_free_rcu(wgptr);
}
static u32 rtw_wds_gptr_table_hash(const void *addr, u32 len, u32 seed)
{
/* Use last four bytes of hw addr as hash index */
return jhash_1word(*(u32 *)(addr+2), seed);
}
static const rtw_rhashtable_params rtw_wds_gptr_rht_params = {
.nelem_hint = 2,
.automatic_shrinking = true,
.key_len = ETH_ALEN,
.key_offset = offsetof(struct rtw_wds_gptr, src),
.head_offset = offsetof(struct rtw_wds_gptr, rhash),
.hashfn = rtw_wds_gptr_table_hash,
};
static void rtw_wds_gptr_rht_free(void *ptr, void *tblptr)
{
struct rtw_wds_gptr *wgptr = ptr;
struct rtw_wds_gptr_table *tbl = tblptr;
rtw_wds_gptr_free_rcu(tbl, wgptr);
}
static struct rtw_wds_gptr_table *rtw_wds_gptr_table_alloc(void)
{
struct rtw_wds_gptr_table *newtbl;
newtbl = rtw_malloc(sizeof(struct rtw_wds_gptr_table));
if (!newtbl)
return NULL;
return newtbl;
}
static void rtw_wds_gptr_table_free(struct rtw_wds_gptr_table *tbl)
{
rtw_rhashtable_free_and_destroy(&tbl->rhead,
rtw_wds_gptr_rht_free, tbl);
rtw_mfree(tbl, sizeof(struct rtw_wds_gptr_table));
}
static struct rtw_wds_gptr *rtw_wds_gptr_lookup(_adapter *adapter, const u8 *src)
{
struct rtw_wds_gptr_table *tbl = adapter->wds_gpt_records;
if (!tbl)
return NULL;
return rtw_rhashtable_lookup_fast(&tbl->rhead, src, rtw_wds_gptr_rht_params);
}
/**
* Locking: must be called within a read rcu section.
*/
static struct rtw_wds_gptr *rtw_wds_gptr_lookup_by_idx(_adapter *adapter, int idx)
{
int i = 0, ret;
struct rtw_wds_gptr_table *tbl = adapter->wds_gpt_records;
struct rtw_wds_gptr *wgptr = NULL;
rtw_rhashtable_iter iter;
if (!tbl)
return NULL;
ret = rtw_rhashtable_walk_enter(&tbl->rhead, &iter);
if (ret)
return NULL;
ret = rtw_rhashtable_walk_start(&iter);
if (ret && ret != -EAGAIN)
goto err;
while ((wgptr = rtw_rhashtable_walk_next(&iter))) {
if (IS_ERR(wgptr) && PTR_ERR(wgptr) == -EAGAIN)
continue;
if (IS_ERR(wgptr))
break;
if (i++ == idx)
break;
}
err:
rtw_rhashtable_walk_stop(&iter);
rtw_rhashtable_walk_exit(&iter);
if (IS_ERR(wgptr) || !wgptr)
return NULL;
return wgptr;
}
void dump_wgptr(void *sel, _adapter *adapter)
{
struct rtw_wds_gptr *wgptr;
int idx = 0;
char src[ETH_ALEN];
u32 age_ms;
RTW_PRINT_SEL(sel, "num:%d\n", ATOMIC_READ(&adapter->wds_gpt_record_num));
RTW_PRINT_SEL(sel, "%-17s %-6s\n"
, "src", "age"
);
do {
rtw_rcu_read_lock();
wgptr = rtw_wds_gptr_lookup_by_idx(adapter, idx);
if (wgptr) {
_rtw_memcpy(src, wgptr->src, ETH_ALEN);
age_ms = rtw_get_passing_time_ms(wgptr->last_update);
}
rtw_rcu_read_unlock();
if (wgptr) {
RTW_PRINT_SEL(sel, MAC_FMT" %6u\n"
, MAC_ARG(src)
, age_ms < 999999 ? age_ms : 999999
);
}
idx++;
} while (wgptr);
}
static struct rtw_wds_gptr *rtw_wds_gptr_new(_adapter *adapter, const u8 *src)
{
struct rtw_wds_gptr *new_wgptr;
new_wgptr = rtw_zmalloc(sizeof(struct rtw_wds_gptr));
if (!new_wgptr)
return NULL;
new_wgptr->adapter = adapter;
_rtw_memcpy(new_wgptr->src, src, ETH_ALEN);
new_wgptr->last_update = rtw_get_current_time();
return new_wgptr;
}
static struct rtw_wds_gptr *rtw_wds_gptr_add(_adapter *adapter, const u8 *src)
{
struct rtw_wds_gptr_table *tbl = adapter->wds_gpt_records;
struct rtw_wds_gptr *wgptr, *new_wgptr;
int ret;
if (!tbl)
return ERR_PTR(-ENOTSUPP);
if (ATOMIC_INC_UNLESS(&adapter->wds_gpt_record_num, RTW_WDS_MAX_PATHS) == 0)
return ERR_PTR(-ENOSPC);
new_wgptr = rtw_wds_gptr_new(adapter, src);
if (!new_wgptr)
return ERR_PTR(-ENOMEM);
do {
ret = rtw_rhashtable_lookup_insert_fast(&tbl->rhead,
&new_wgptr->rhash,
rtw_wds_gptr_rht_params);
if (ret == -EEXIST)
wgptr = rtw_rhashtable_lookup_fast(&tbl->rhead,
src,
rtw_wds_gptr_rht_params);
} while (unlikely(ret == -EEXIST && !wgptr));
if (ret && ret != -EEXIST)
return ERR_PTR(ret);
/* At this point either new_wgptr was added, or we found a
* matching entry already in the table; in the latter case
* free the unnecessary new entry.
*/
if (ret == -EEXIST) {
rtw_mfree(new_wgptr, sizeof(struct rtw_wds_gptr));
new_wgptr = wgptr;
}
return new_wgptr;
}
bool rtw_rx_wds_gptr_check(_adapter *adapter, const u8 *src)
{
struct rtw_wds_gptr *wgptr;
bool ret = 0;
rtw_rcu_read_lock();
wgptr = rtw_wds_gptr_lookup(adapter, src);
if (wgptr)
ret = rtw_time_after(wgptr->last_update + RTW_WDS_GPTR_EXPIRE, rtw_get_current_time());
rtw_rcu_read_unlock();
return ret;
}
void rtw_tx_wds_gptr_update(_adapter *adapter, const u8 *src)
{
struct rtw_wds_gptr *wgptr;
rtw_rcu_read_lock();
wgptr = rtw_wds_gptr_lookup(adapter, src);
if (!wgptr)
rtw_wds_gptr_add(adapter, src);
else
wgptr->last_update = rtw_get_current_time();
rtw_rcu_read_unlock();
}
static void __rtw_wds_gptr_del(struct rtw_wds_gptr_table *tbl, struct rtw_wds_gptr *wgptr)
{
rtw_rhashtable_remove_fast(&tbl->rhead, &wgptr->rhash, rtw_wds_gptr_rht_params);
rtw_wds_gptr_free_rcu(tbl, wgptr);
}
void rtw_wds_gptr_expire(_adapter *adapter)
{
struct rtw_wds_gptr_table *tbl = adapter->wds_gpt_records;
struct rtw_wds_gptr *wgptr;
rtw_rhashtable_iter iter;
int ret;
if (!tbl)
return;
ret = rtw_rhashtable_walk_enter(&tbl->rhead, &iter);
if (ret)
return;
ret = rtw_rhashtable_walk_start(&iter);
if (ret && ret != -EAGAIN)
goto out;
while ((wgptr = rtw_rhashtable_walk_next(&iter))) {
if (IS_ERR(wgptr) && PTR_ERR(wgptr) == -EAGAIN)
continue;
if (IS_ERR(wgptr))
break;
if (rtw_time_after(rtw_get_current_time(), wgptr->last_update + RTW_WDS_GPTR_EXPIRE))
__rtw_wds_gptr_del(tbl, wgptr);
}
out:
rtw_rhashtable_walk_stop(&iter);
rtw_rhashtable_walk_exit(&iter);
}
int rtw_wds_gptr_tbl_init(_adapter *adapter)
{
struct rtw_wds_gptr_table *tbl;
int ret;
tbl = rtw_wds_gptr_table_alloc();
if (!tbl)
return -ENOMEM;
rtw_rhashtable_init(&tbl->rhead, &rtw_wds_gptr_rht_params);
ATOMIC_SET(&adapter->wds_gpt_record_num, 0);
adapter->wds_gpt_records = tbl;
return 0;
}
void rtw_wds_gptr_tbl_unregister(_adapter *adapter)
{
if (adapter->wds_gpt_records) {
rtw_wds_gptr_table_free(adapter->wds_gpt_records);
adapter->wds_gpt_records = NULL;
}
}
#endif /* defined(CONFIG_RTW_WDS) */

65
core/wds/rtw_wds.h Normal file
View File

@ -0,0 +1,65 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2019 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#ifndef __RTW_WDS_H_
#define __RTW_WDS_H_
#ifdef CONFIG_AP_MODE
struct rtw_wds_path {
u8 dst[ETH_ALEN];
rtw_rhash_head rhash;
_adapter *adapter;
struct sta_info __rcu *next_hop;
rtw_rcu_head rcu;
systime last_update;
};
struct rtw_wds_table {
rtw_rhashtable rhead;
};
#define RTW_WDS_PATH_EXPIRE (600 * HZ)
/* Maximum number of paths per interface */
#define RTW_WDS_MAX_PATHS 1024
int rtw_wds_nexthop_lookup(_adapter *adapter, const u8 *da, u8 *ra);
struct rtw_wds_path *rtw_wds_path_lookup(_adapter *adapter, const u8 *dst);
void dump_wpath(void *sel, _adapter *adapter);
void rtw_wds_path_expire(_adapter *adapter);
struct rtw_wds_path *rtw_wds_path_add(_adapter *adapter, const u8 *dst, struct sta_info *next_hop);
void rtw_wds_path_assign_nexthop(struct rtw_wds_path *path, struct sta_info *sta);
int rtw_wds_pathtbl_init(_adapter *adapter);
void rtw_wds_pathtbl_unregister(_adapter *adapter);
void rtw_wds_path_flush_by_nexthop(struct sta_info *sta);
#endif /* CONFIG_AP_MODE */
struct rtw_wds_gptr_table {
rtw_rhashtable rhead;
};
void dump_wgptr(void *sel, _adapter *adapter);
bool rtw_rx_wds_gptr_check(_adapter *adapter, const u8 *src);
void rtw_tx_wds_gptr_update(_adapter *adapter, const u8 *src);
void rtw_wds_gptr_expire(_adapter *adapter);
int rtw_wds_gptr_tbl_init(_adapter *adapter);
void rtw_wds_gptr_tbl_unregister(_adapter *adapter);
#endif /* __RTW_WDSH_ */

View File

@ -28,9 +28,9 @@ static const char *const glbt_info_src_8822b_1ant[] = {
"BT Info[bt scbd]"
};
u32 glcoex_ver_date_8822b_1ant = 20191120;
u32 glcoex_ver_8822b_1ant = 0x77;
u32 glcoex_ver_btdesired_8822b_1ant = 0x75;
u32 glcoex_ver_date_8822b_1ant = 20210316;
u32 glcoex_ver_8822b_1ant = 0x18317b;
u32 glcoex_ver_btdesired_8822b_1ant = 0x79;
#if 0
static
@ -264,7 +264,8 @@ halbtc8822b1ant_ccklock_action(struct btc_coexist *btc)
struct coex_sta_8822b_1ant *coex_sta = &btc->coex_sta_8822b_1ant;
u8 h2c_parameter[2] = {0};
static u8 cnt;
boolean wifi_busy = FALSE;
#if 0
if (coex_sta->tdma_timer_base == 3) {
if (!coex_sta->is_no_wl_5ms_extend) {
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
@ -279,10 +280,22 @@ halbtc8822b1ant_ccklock_action(struct btc_coexist *btc)
}
return;
}
#endif
btc->btc_get(btc, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
if (!coex_sta->gl_wifi_busy ||
coex_sta->wl_iot_peer == BTC_IOT_PEER_CISCO) {
cnt = 0;
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], wifi is not busy or CISCO AP, return!!\n");
BTC_TRACE(trace_buf);
return;
}
if (!coex_sta->is_no_wl_5ms_extend && coex_sta->force_lps_ctrl &&
!coex_sta->cck_lock_ever) {
if (coex_sta->wl_fw_dbg_info[7] <= 5)
if (coex_sta->wl_fw_dbg_info[7] <= 5 && wifi_busy)
cnt++;
else
cnt = 0;
@ -319,14 +332,13 @@ halbtc8822b1ant_ccklock_detect(struct btc_coexist *btc)
{
struct coex_sta_8822b_1ant *coex_sta = &btc->coex_sta_8822b_1ant;
struct coex_dm_8822b_1ant *coex_dm = &btc->coex_dm_8822b_1ant;
struct btc_wifi_link_info_ext *link_info_ext = &btc->wifi_link_info_ext;
struct wifi_link_info_8822b_1ant *link_info_ext =
&btc->wifi_link_info_8822b_1ant;
boolean is_cck_lock_rate = FALSE;
if (coex_dm->bt_status == BTC_BTSTATUS_INQ_PAGE ||
coex_sta->is_setup_link) {
coex_sta->cck_lock = FALSE;
return;
}
coex_sta->is_setup_link)
return;
if (coex_sta->wl_rx_rate <= BTC_CCK_2 ||
coex_sta->wl_rts_rx_rate <= BTC_CCK_2)
@ -408,10 +420,6 @@ halbtc8822b1ant_set_tdma_timer_base(struct btc_coexist *btc, u8 type)
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], %s() h2c_0x69 = 0x%x\n", __func__, h2c_para[1]);
BTC_TRACE(trace_buf);
/* no 5ms_wl_slot_extend for 4-slot mode */
if (coex_sta->tdma_timer_base == 3)
halbtc8822b1ant_ccklock_action(btc);
}
static void halbtc8822b1ant_low_penalty_ra(struct btc_coexist *btc,
@ -531,13 +539,14 @@ static void halbtc8822b1ant_enable_gnt_to_gpio(struct btc_coexist *btc,
}
}
static void halbtc8822b1ant_monitor_bt_ctr(struct btc_coexist *btc)
static boolean halbtc8822b1ant_monitor_bt_ctr(struct btc_coexist *btc)
{
struct coex_sta_8822b_1ant *coex_sta = &btc->coex_sta_8822b_1ant;
u32 reg_hp_txrx, reg_lp_txrx, u32tmp;
struct coex_dm_8822b_1ant *coex_dm = &btc->coex_dm_8822b_1ant;
u32 reg_hp_txrx, reg_lp_txrx, u32tmp, cnt_bt_all;
u32 reg_hp_tx = 0, reg_hp_rx = 0, reg_lp_tx = 0, reg_lp_rx = 0;
static u8 num_of_bt_counter_chk, cnt_autoslot_hang;
struct btc_bt_link_info *bt_link_info = &btc->bt_link_info;
static u32 cnt_bt_pre = 0;
boolean is_run_coex = FALSE;
reg_hp_txrx = 0x770;
reg_lp_txrx = 0x774;
@ -563,9 +572,35 @@ static void halbtc8822b1ant_monitor_bt_ctr(struct btc_coexist *btc)
/* reset counter */
btc->btc_write_1byte(btc, 0x76e, 0xc);
if (coex_sta->under_lps || coex_sta->under_ips ||
(coex_sta->high_priority_tx == 65535 &&
coex_sta->high_priority_rx == 65535 &&
coex_sta->low_priority_tx == 65535 &&
coex_sta->low_priority_rx == 65535))
coex_sta->bt_ctr_ok = FALSE;
else
coex_sta->bt_ctr_ok = TRUE;
if (!coex_sta->bt_ctr_ok)
return FALSE;
if (coex_sta->low_priority_tx > 1150 &&
!coex_sta->c2h_bt_inquiry_page)
coex_sta->pop_event_cnt++;
cnt_bt_all = coex_sta->high_priority_tx +
coex_sta->high_priority_rx +
coex_sta->low_priority_tx +
coex_sta->low_priority_rx;
if ((cnt_bt_pre > (cnt_bt_all + 50) ||
cnt_bt_all > (cnt_bt_pre + 50)) &&
coex_dm->bt_status == BT_8822B_1ANT_BSTATUS_NCON_IDLE)
is_run_coex = TRUE;
cnt_bt_pre = cnt_bt_all;
return is_run_coex;
}
static void halbtc8822b1ant_monitor_wifi_ctr(struct btc_coexist *btc)
@ -577,7 +612,6 @@ static void halbtc8822b1ant_monitor_wifi_ctr(struct btc_coexist *btc)
u32 cnt_cck;
static u8 cnt_ccklocking;
u8 h2c_parameter[1] = {0};
struct btc_bt_link_info *bt_link_info = &btc->bt_link_info;
btc->btc_get(btc, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
btc->btc_get(btc, BTC_GET_BL_WIFI_SCAN, &wifi_scan);
@ -859,9 +893,17 @@ static void halbtc8822b1ant_update_wifi_link_info(struct btc_coexist *btc,
struct btc_wifi_link_info wifi_link_info;
struct coex_dm_8822b_1ant *coex_dm = &btc->coex_dm_8822b_1ant;
u8 wifi_central_chnl = 0, num_of_wifi_link = 0;
boolean isunder5G = FALSE, ismcc25g = FALSE, isp2pconnected = FALSE;
u32 wifi_link_status = 0;
boolean isunder5G = FALSE, ismcc25g = FALSE, isp2pconnected = FALSE;
boolean wifi_connected = FALSE;
boolean scan = FALSE, link = FALSE, roam = FALSE, under_4way = FALSE;
btc->btc_get(btc, BTC_GET_BL_WIFI_SCAN, &scan);
btc->btc_get(btc, BTC_GET_BL_WIFI_LINK, &link);
btc->btc_get(btc, BTC_GET_BL_WIFI_ROAM, &roam);
btc->btc_get(btc, BTC_GET_BL_WIFI_4_WAY_PROGRESS, &under_4way);
btc->btc_get(btc, BTC_GET_BL_WIFI_LW_PWR_STATE,
&wifi_link_info_ext->is_32k);
btc->btc_get(btc, BTC_GET_BL_WIFI_CONNECTED,
&wifi_link_info_ext->is_connected);
@ -959,6 +1001,20 @@ static void halbtc8822b1ant_update_wifi_link_info(struct btc_coexist *btc,
wifi_link_info_ext->num_of_active_port = num_of_wifi_link;
wifi_link_info_ext->is_p2p_connected = isp2pconnected;
if (scan || link || roam || under_4way ||
reason == BT_8822B_1ANT_RSN_2GSCANSTART ||
reason == BT_8822B_1ANT_RSN_2GSWITCHBAND ||
reason == BT_8822B_1ANT_RSN_2GCONSTART ||
reason == BT_8822B_1ANT_RSN_2GSPECIALPKT) {
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], scan = %d, link = %d, roam = %d 4way = %d!!!\n",
scan, link, roam, under_4way);
BTC_TRACE(trace_buf);
coex_sta->is_wifi_linkscan_process = TRUE;
} else {
coex_sta->is_wifi_linkscan_process = FALSE;
}
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], wifi_link_info: link_mode=%d, STA_Ch=%d, P2P_Ch=%d, AnyClient_Join_Go=%d !\n",
@ -1188,6 +1244,7 @@ static void halbtc8822b1ant_update_bt_link_info(struct btc_coexist *btc)
#if 1
if (coex_sta->hid_busy_num == 0 &&
coex_sta->hid_pair_cnt > 0 &&
coex_sta->bt_ctr_ok &&
coex_sta->low_priority_tx > 1500 &&
coex_sta->low_priority_rx > 1500 &&
!coex_sta->c2h_bt_inquiry_page)
@ -1390,11 +1447,16 @@ halbtc8822b1ant_update_wifi_ch_info(struct btc_coexist *btc, u8 type)
}
}
coex_dm->wifi_chnl_info[0] = h2c_parameter[0];
coex_dm->wifi_chnl_info[1] = h2c_parameter[1];
coex_dm->wifi_chnl_info[2] = h2c_parameter[2];
/* Only send mailbox if ch info change */
if (coex_dm->wifi_chnl_info[0] != h2c_parameter[0] &&
coex_dm->wifi_chnl_info[1] != h2c_parameter[1] &&
coex_dm->wifi_chnl_info[2] != h2c_parameter[2]) {
btc->btc_fill_h2c(btc, 0x66, 3, h2c_parameter);
coex_dm->wifi_chnl_info[0] = h2c_parameter[0];
coex_dm->wifi_chnl_info[1] = h2c_parameter[1];
coex_dm->wifi_chnl_info[2] = h2c_parameter[2];
btc->btc_fill_h2c(btc, 0x66, 3, h2c_parameter);
}
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], para[0:2] = 0x%x 0x%x 0x%x\n", h2c_parameter[0],
@ -1651,6 +1713,7 @@ halbtc8822b1ant_set_gnt_wl(struct btc_coexist *btc, u8 state)
static void halbtc8822b1ant_mimo_ps(struct btc_coexist *btc,
boolean force_exec, u8 state)
{
#if 0
static u8 pre_state;
if (!force_exec) {
@ -1665,6 +1728,7 @@ static void halbtc8822b1ant_mimo_ps(struct btc_coexist *btc,
BTC_TRACE(trace_buf);
btc->btc_set(btc, BTC_SET_MIMO_PS_MODE, &state);
#endif
}
static void halbtc8822b1ant_set_table(struct btc_coexist *btc,
@ -1862,6 +1926,16 @@ void halbtc8822b1ant_table(struct btc_coexist *btc, boolean force_exec, u8 type)
0x5a5a5aaa, break_table,
select_table);
break;
case 29:
halbtc8822b1ant_set_table(btc, force_exec, 0xdaffdaff,
0xdaffdaff, break_table,
select_table);
break;
case 30:
halbtc8822b1ant_set_table(btc, force_exec, 0x6a555a5a,
0x5a5a5a5a, break_table,
select_table);
break;
default:
break;
}
@ -2055,7 +2129,6 @@ void halbtc8822b1ant_set_tdma(struct btc_coexist *btc, u8 byte1,
u8 h2c_parameter[5] = {0};
u8 real_byte1 = byte1, real_byte5 = byte5;
boolean ap_enable = FALSE, result = FALSE;
struct btc_bt_link_info *bt_link_info = &btc->bt_link_info;
u8 ps_type = BTC_PS_WIFI_NATIVE;
if (byte5 & BIT(2))
@ -2146,7 +2219,6 @@ halbtc8822b1ant_tdma(struct btc_coexist *btc, boolean force_exec,
{
struct coex_sta_8822b_1ant *coex_sta = &btc->coex_sta_8822b_1ant;
struct coex_dm_8822b_1ant *coex_dm = &btc->coex_dm_8822b_1ant;
struct btc_bt_link_info *bt_link_info = &btc->bt_link_info;
u8 type;
btc->btc_set_atomic(btc, &coex_dm->setting_tdma, TRUE);
@ -2154,7 +2226,7 @@ halbtc8822b1ant_tdma(struct btc_coexist *btc, boolean force_exec,
/* tcase: bit0~7 --> tdma case index
* bit8 --> for 4-slot (50ms) mode
*/
if (tcase & TDMA_4SLOT)/* 4-slot (50ms) mode */
if (tcase & TDMA_4SLOT)/* 4-slot (50ms) mode */
halbtc8822b1ant_set_tdma_timer_base(btc, 3);
else
halbtc8822b1ant_set_tdma_timer_base(btc, 0);
@ -2182,7 +2254,12 @@ halbtc8822b1ant_tdma(struct btc_coexist *btc, boolean force_exec,
type);
BTC_TRACE(trace_buf);
halbtc8822b1ant_write_scbd(btc, BT_8822B_1ANT_SCBD_TDMA, TRUE);
if (coex_sta->a2dp_exist && coex_sta->bt_inq_page_remain)
halbtc8822b1ant_write_scbd(btc, BT_8822B_1ANT_SCBD_TDMA,
FALSE);
else
halbtc8822b1ant_write_scbd(btc, BT_8822B_1ANT_SCBD_TDMA,
TRUE);
/* enable TBTT nterrupt */
btc->btc_write_1byte_bitmask(btc, 0x550, 0x8, 0x1);
@ -2277,7 +2354,7 @@ halbtc8822b1ant_tdma(struct btc_coexist *btc, boolean force_exec,
0x10);
break;
case 25:
halbtc8822b1ant_set_tdma(btc, 0x51, 0x3a, 0x3, 0x11,
halbtc8822b1ant_set_tdma(btc, 0x51, 0x3a, 0x3, 0x10,
0x50);
break;
case 26:
@ -2897,6 +2974,9 @@ static void halbtc8822b1ant_action_bt_whql_test(struct btc_coexist *btc)
halbtc8822b1ant_set_wl_rx_gain(btc, NM_EXCU, FALSE);
halbtc8822b1ant_set_bt_rx_gain(btc, NM_EXCU, FALSE);
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G);
halbtc8822b1ant_table(btc, NM_EXCU, 0);
halbtc8822b1ant_tdma(btc, NM_EXCU, FALSE, 8);
}
@ -2911,6 +2991,9 @@ static void halbtc8822b1ant_action_bt_relink(struct btc_coexist *btc)
halbtc8822b1ant_set_wl_rx_gain(btc, NM_EXCU, FALSE);
halbtc8822b1ant_set_bt_rx_gain(btc, NM_EXCU, FALSE);
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G);
if (coex_sta->gl_wifi_busy) {
halbtc8822b1ant_table(btc, NM_EXCU, 3);
@ -2934,7 +3017,7 @@ static void halbtc8822b1ant_action_bt_idle(struct btc_coexist *btc)
wifi_rssi_state =
halbtc8822b1ant_wifi_rssi_state(btc, &prewifi_rssi_state, 2,
20, 0);
32, 0);
halbtc8822b1ant_set_wl_tx_power(btc, NM_EXCU, 0xd8);
halbtc8822b1ant_set_bt_tx_power(btc, NM_EXCU, 0);
@ -2984,6 +3067,9 @@ static void halbtc8822b1ant_action_bt_inquiry(struct btc_coexist *btc)
halbtc8822b1ant_set_wl_rx_gain(btc, NM_EXCU, FALSE);
halbtc8822b1ant_set_bt_rx_gain(btc, NM_EXCU, FALSE);
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G);
btc->btc_get(btc, BTC_GET_BL_WIFI_CONNECTED, &wifi_connected);
btc->btc_get(btc, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
@ -3032,17 +3118,35 @@ void halbtc8822b1ant_action_bt_sco_hid_busy(struct btc_coexist *btc)
{
struct coex_sta_8822b_1ant *coex_sta = &btc->coex_sta_8822b_1ant;
struct btc_bt_link_info *bt_link_info = &btc->bt_link_info;
boolean wifi_busy = FALSE;
boolean wifi_busy = FALSE, is_bt_ctr_hi = FALSE;
halbtc8822b1ant_set_wl_tx_power(btc, NM_EXCU, 0xd8);
halbtc8822b1ant_set_bt_tx_power(btc, NM_EXCU, 0);
halbtc8822b1ant_set_wl_rx_gain(btc, NM_EXCU, FALSE);
halbtc8822b1ant_set_bt_rx_gain(btc, NM_EXCU, FALSE);
if (coex_sta->bt_ctr_ok &&
(coex_sta->low_priority_rx + coex_sta->low_priority_tx > 360))
is_bt_ctr_hi = TRUE;
else
is_bt_ctr_hi = FALSE;
btc->btc_get(btc, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
if (!wifi_busy)
wifi_busy = coex_sta->gl_wifi_busy;
#if 0
if (coex_sta->cck_lock_ever) {
coex_sta->wl_coex_mode = BT_8822B_1ANT_WLINK_2GFREE;
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G_FREERUN);
halbtc8822b1ant_table(btc, NM_EXCU, 29);
halbtc8822b1ant_tdma(btc, NM_EXCU, FALSE, 8);
return;
}
#endif
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G);
if (bt_link_info->sco_exist) {
if (coex_sta->is_bt_multi_link) {
@ -3059,9 +3163,8 @@ void halbtc8822b1ant_action_bt_sco_hid_busy(struct btc_coexist *btc)
/* for HID exist */
if (bt_link_info->hid_only &&
(coex_sta->is_bt_multi_link ||
(coex_sta->low_priority_rx +
coex_sta->low_priority_tx > 360) ||
bt_link_info->slave_role)) {
is_bt_ctr_hi ||
bt_link_info->slave_role)) {
if (coex_sta->gl_wifi_busy &&
(coex_sta->wl_rx_rate <= 3 ||
coex_sta->wl_rts_rx_rate <= 3))
@ -3096,9 +3199,12 @@ static void halbtc8822b1ant_action_bt_acl_busy(struct btc_coexist *btc)
boolean wifi_busy = FALSE, wifi_turbo = FALSE, ap_enable = FALSE;
static u8 prewifi_rssi_state = BTC_RSSI_STATE_LOW;
static u8 prewifi_rssi_state2 = BTC_RSSI_STATE_LOW;
u32 wifi_bw = 1;
u32 wifi_bw = 1, slot_type = 0;
u8 wifi_rssi_state, wifi_rssi_state2, iot_peer = BTC_IOT_PEER_UNKNOWN;
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G);
btc->btc_get(btc, BTC_GET_U4_WIFI_BW, &wifi_bw);
btc->btc_get(btc, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
btc->btc_get(btc, BTC_GET_U1_AP_NUM, &coex_sta->scan_ap_num);
@ -3200,20 +3306,25 @@ static void halbtc8822b1ant_action_bt_acl_busy(struct btc_coexist *btc)
7 | TDMA_4SLOT);
} else if (bt_link_info->hid_exist &&
bt_link_info->a2dp_exist) { /* HID + A2DP */
/*4-slot will not be applied when AP is CISCO*/
if (coex_sta->wl_iot_peer != BTC_IOT_PEER_CISCO)
slot_type = TDMA_4SLOT;
halbtc8822b1ant_table(btc, FC_EXCU, 1);
if (coex_sta->connect_ap_period_cnt > 0 || !wifi_busy) {
halbtc8822b1ant_tdma(btc, NM_EXCU, TRUE,
26 | TDMA_4SLOT);
26 | slot_type);
} else if (coex_sta->bt_418_hid_exist ||
coex_sta->bt_ble_hid_exist) {
halbtc8822b1ant_wltoggle_table(btc, NM_EXCU, 3,
0xaa, 0x5a, 0x5a, 0x5a);
halbtc8822b1ant_tdma(btc, NM_EXCU, TRUE,
39 | TDMA_4SLOT);
39 | slot_type);
} else {
halbtc8822b1ant_tdma(btc, NM_EXCU, TRUE,
7 | TDMA_4SLOT);
7 | slot_type);
}
/* PAN, HID+PAN */
} else if ((bt_link_info->pan_only) ||
@ -3238,28 +3349,11 @@ static void halbtc8822b1ant_action_bt_acl_busy(struct btc_coexist *btc)
static void halbtc8822b1ant_action_bt_mr(struct btc_coexist *btc)
{
struct wifi_link_info_8822b_1ant *wifi_link_info_ext =
&btc->wifi_link_info_8822b_1ant;
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G_FREERUN);
if (!wifi_link_info_ext->is_all_under_5g) {
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G_FREERUN);
halbtc8822b1ant_table(btc, NM_EXCU, 8);
halbtc8822b1ant_tdma(btc, NM_EXCU, FALSE, 8);
/* Enter MIMO Power Save, 0:enable */
halbtc8822b1ant_mimo_ps(btc, NM_EXCU, 0);
} else {
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_5G);
halbtc8822b1ant_table(btc, NM_EXCU, 0);
halbtc8822b1ant_tdma(btc, NM_EXCU, FALSE, 8);
/* No MIMO Power Save, 3:disable */
halbtc8822b1ant_mimo_ps(btc, NM_EXCU, 3);
}
halbtc8822b1ant_table(btc, NM_EXCU, 8);
halbtc8822b1ant_tdma(btc, NM_EXCU, FALSE, 8);
}
static void halbtc8822b1ant_action_rf4ce(struct btc_coexist *btc)
@ -3269,6 +3363,9 @@ static void halbtc8822b1ant_action_rf4ce(struct btc_coexist *btc)
halbtc8822b1ant_set_wl_rx_gain(btc, NM_EXCU, FALSE);
halbtc8822b1ant_set_bt_rx_gain(btc, NM_EXCU, FALSE);
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G);
halbtc8822b1ant_table(btc, NM_EXCU, 1);
halbtc8822b1ant_tdma(btc, NM_EXCU, TRUE, 50);
}
@ -3296,6 +3393,9 @@ static void halbtc8822b1ant_action_wifi_only(struct btc_coexist *btc)
halbtc8822b1ant_set_wl_rx_gain(btc, NM_EXCU, FALSE);
halbtc8822b1ant_set_bt_rx_gain(btc, NM_EXCU, FALSE);
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G);
btc->btc_get(btc, BTC_GET_BL_RF4CE_CONNECTED, &rf4ce_enabled);
btc->btc_get(btc, BTC_GET_BL_WIFI_CONNECTED, &wifi_connected);
@ -3319,7 +3419,6 @@ halbtc8822b1ant_action_wifi_native_lps(struct btc_coexist *btc)
{
struct wifi_link_info_8822b_1ant *wifi_link_info_ext =
&btc->wifi_link_info_8822b_1ant;
struct btc_bt_link_info *bt_link_info = &btc->bt_link_info;
if (wifi_link_info_ext->is_all_under_5g)
return;
@ -3329,6 +3428,9 @@ halbtc8822b1ant_action_wifi_native_lps(struct btc_coexist *btc)
halbtc8822b1ant_set_wl_rx_gain(btc, NM_EXCU, FALSE);
halbtc8822b1ant_set_bt_rx_gain(btc, NM_EXCU, FALSE);
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G);
halbtc8822b1ant_table(btc, NM_EXCU, 21);
halbtc8822b1ant_tdma(btc, NM_EXCU, FALSE, 8);
}
@ -3342,8 +3444,11 @@ static void halbtc8822b1ant_action_wifi_linkscan(struct btc_coexist *btc)
halbtc8822b1ant_set_wl_rx_gain(btc, NM_EXCU, FALSE);
halbtc8822b1ant_set_bt_rx_gain(btc, NM_EXCU, FALSE);
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G);
if (bt_link_info->pan_exist) {
halbtc8822b1ant_table(btc, NM_EXCU, 1);
halbtc8822b1ant_table(btc, NM_EXCU, 30);
halbtc8822b1ant_tdma(btc, NM_EXCU, TRUE, 22);
} else if (bt_link_info->a2dp_exist) {
halbtc8822b1ant_table(btc, NM_EXCU, 1);
@ -3362,6 +3467,9 @@ halbtc8822b1ant_action_wifi_not_connected(struct btc_coexist *btc)
halbtc8822b1ant_set_wl_rx_gain(btc, NM_EXCU, FALSE);
halbtc8822b1ant_set_bt_rx_gain(btc, NM_EXCU, FALSE);
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G);
/* tdma and coex table */
halbtc8822b1ant_table(btc, NM_EXCU, 0);
halbtc8822b1ant_tdma(btc, FC_EXCU, FALSE, 8);
@ -3379,7 +3487,8 @@ static void halbtc8822b1ant_action_wifi_connected(struct btc_coexist *btc)
if (coex_dm->bt_status == BT_8822B_1ANT_BSTATUS_ACL_BUSY ||
coex_dm->bt_status == BT_8822B_1ANT_BSTATUS_ACL_SCO_BUSY) {
if (bt_link_info->hid_only) /* HID only */
if (bt_link_info->hid_only || bt_link_info->sco_exist)
/* HID only or SCO*/
halbtc8822b1ant_action_bt_sco_hid_busy(btc);
else
halbtc8822b1ant_action_bt_acl_busy(btc);
@ -3482,7 +3591,6 @@ static void
halbtc8822b1ant_action_wifi_multiport2g(struct btc_coexist *btc)
{
struct coex_sta_8822b_1ant *coex_sta = &btc->coex_sta_8822b_1ant;
struct btc_bt_link_info *bt_link_info = &btc->bt_link_info;
u32 traffic_dir;
u8 ant_pase;
@ -3499,8 +3607,7 @@ halbtc8822b1ant_action_wifi_multiport2g(struct btc_coexist *btc)
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], BT is disabled !!!\n");
BTC_TRACE(trace_buf);
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G);
halbtc8822b1ant_action_wifi_only(btc);
} else if (coex_sta->is_setup_link ||
coex_sta->bt_relink_downcount != 0) {
@ -3543,8 +3650,6 @@ halbtc8822b1ant_action_wifi_multiport2g(struct btc_coexist *btc)
"[BTCoex], wifi_multiport2g, WL scan!!\n");
BTC_TRACE(trace_buf);
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G);
halbtc8822b1ant_action_wifi_linkscan(btc);
} else {
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
@ -3590,29 +3695,6 @@ static void halbtc8822b1ant_run_coex(struct btc_coexist *btc, u8 reason)
struct coex_sta_8822b_1ant *coex_sta = &btc->coex_sta_8822b_1ant;
struct wifi_link_info_8822b_1ant *wifi_link_info_ext =
&btc->wifi_link_info_8822b_1ant;
boolean wifi_connected = FALSE, wifi_32k = false;
boolean scan = FALSE, link = FALSE, roam = FALSE, under_4way = FALSE;
btc->btc_get(btc, BTC_GET_BL_WIFI_SCAN, &scan);
btc->btc_get(btc, BTC_GET_BL_WIFI_LINK, &link);
btc->btc_get(btc, BTC_GET_BL_WIFI_ROAM, &roam);
btc->btc_get(btc, BTC_GET_BL_WIFI_4_WAY_PROGRESS, &under_4way);
btc->btc_get(btc, BTC_GET_BL_WIFI_CONNECTED, &wifi_connected);
btc->btc_get(btc, BTC_GET_BL_WIFI_LW_PWR_STATE, &wifi_32k);
if (scan || link || roam || under_4way ||
reason == BT_8822B_1ANT_RSN_2GSCANSTART ||
reason == BT_8822B_1ANT_RSN_2GSWITCHBAND ||
reason == BT_8822B_1ANT_RSN_2GCONSTART ||
reason == BT_8822B_1ANT_RSN_2GSPECIALPKT) {
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], scan = %d, link = %d, roam = %d 4way = %d!!!\n",
scan, link, roam, under_4way);
BTC_TRACE(trace_buf);
coex_sta->is_wifi_linkscan_process = TRUE;
} else {
coex_sta->is_wifi_linkscan_process = FALSE;
}
/* update wifi_link_info_ext variable */
halbtc8822b1ant_update_wifi_link_info(btc, reason);
@ -3645,7 +3727,7 @@ static void halbtc8822b1ant_run_coex(struct btc_coexist *btc, u8 reason)
return;
}
if (coex_sta->under_lps && wifi_32k) {
if (coex_sta->under_lps && wifi_link_info_ext->is_32k) {
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], RunCoexistMechanism(), return for wifi is under LPS-32K !!!\n");
BTC_TRACE(trace_buf);
@ -3666,21 +3748,8 @@ static void halbtc8822b1ant_run_coex(struct btc_coexist *btc, u8 reason)
return;
}
if (coex_sta->msft_mr_exist && wifi_connected) {
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], RunCoexistMechanism(), microsoft MR!!\n");
BTC_TRACE(trace_buf);
coex_sta->wl_coex_mode = BT_8822B_1ANT_WLINK_BTMR;
halbtc8822b1ant_action_bt_mr(btc);
return;
}
coex_sta->coex_run_cnt++;
/* No MIMO Power Save, 3:disable */
halbtc8822b1ant_mimo_ps(btc, NM_EXCU, 3);
/* Pure-5G Coex Process */
if (wifi_link_info_ext->is_all_under_5g) {
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
@ -3689,10 +3758,20 @@ static void halbtc8822b1ant_run_coex(struct btc_coexist *btc, u8 reason)
coex_sta->wl_coex_mode = BT_8822B_1ANT_WLINK_5G;
halbtc8822b1ant_action_wifi_under5g(btc);
return;
goto exit;
}
if (wifi_link_info_ext->is_mcc_25g) { /* not iclude scan action */
if (coex_sta->msft_mr_exist && wifi_link_info_ext->is_connected) {
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], RunCoexistMechanism(), microsoft MR!!\n");
BTC_TRACE(trace_buf);
coex_sta->wl_coex_mode = BT_8822B_1ANT_WLINK_BTMR;
halbtc8822b1ant_action_bt_mr(btc);
goto exit;
}
if (wifi_link_info_ext->is_mcc_25g) { /* not include scan action */
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], WiFi is under mcc dual-band!!!\n");
@ -3700,7 +3779,7 @@ static void halbtc8822b1ant_run_coex(struct btc_coexist *btc, u8 reason)
coex_sta->wl_coex_mode = BT_8822B_1ANT_WLINK_25GMPORT;
halbtc8822b1ant_action_wifi_multiport25g(btc);
return;
goto exit;
}
/* if multi-port or P2PGO+Client_Join */
@ -3721,7 +3800,7 @@ static void halbtc8822b1ant_run_coex(struct btc_coexist *btc, u8 reason)
coex_sta->wl_coex_mode = BT_8822B_1ANT_WLINK_2GMPORT;
halbtc8822b1ant_action_wifi_multiport2g(btc);
return;
goto exit;
}
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
@ -3742,50 +3821,45 @@ static void halbtc8822b1ant_run_coex(struct btc_coexist *btc, u8 reason)
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], BT is disabled !!!\n");
BTC_TRACE(trace_buf);
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G);
halbtc8822b1ant_action_wifi_only(btc);
return;
goto exit;
}
if (coex_sta->under_lps && !coex_sta->force_lps_ctrl) {
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], RunCoexistMechanism(), wifi is under LPS !!!\n");
BTC_TRACE(trace_buf);
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G);
halbtc8822b1ant_action_wifi_native_lps(btc);
return;
goto exit;
}
if (coex_sta->bt_whck_test) {
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], BT is under WHCK TEST!!!\n");
BTC_TRACE(trace_buf);
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G);
halbtc8822b1ant_action_bt_whql_test(btc);
return;
goto exit;
}
if (coex_sta->is_setup_link || coex_sta->bt_relink_downcount != 0) {
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], BT is re-link !!!\n");
BTC_TRACE(trace_buf);
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G);
halbtc8822b1ant_action_bt_relink(btc);
return;
goto exit;
}
if (coex_sta->c2h_bt_inquiry_page) {
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], BT is under inquiry/page !!\n");
BTC_TRACE(trace_buf);
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G);
halbtc8822b1ant_action_bt_inquiry(btc);
return;
goto exit;
}
if ((coex_dm->bt_status == BT_8822B_1ANT_BSTATUS_NCON_IDLE ||
@ -3795,34 +3869,41 @@ static void halbtc8822b1ant_run_coex(struct btc_coexist *btc, u8 reason)
"############# [BTCoex], BT Is idle\n");
BTC_TRACE(trace_buf);
halbtc8822b1ant_action_bt_idle(btc);
return;
goto exit;
}
if (coex_sta->is_wifi_linkscan_process) {
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], wifi is under linkscan process!!\n");
BTC_TRACE(trace_buf);
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G);
halbtc8822b1ant_action_wifi_linkscan(btc);
return;
goto exit;
}
if (wifi_connected) {
if (wifi_link_info_ext->is_connected) {
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], wifi is under connected!!\n");
BTC_TRACE(trace_buf);
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G);
halbtc8822b1ant_action_wifi_connected(btc);
goto exit;
} else {
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], wifi is under not-connected!!\n");
BTC_TRACE(trace_buf);
halbtc8822b1ant_set_ant_path(btc, BTC_ANT_PATH_AUTO, NM_EXCU,
BT_8822B_1ANT_PHASE_2G);
halbtc8822b1ant_action_wifi_not_connected(btc);
goto exit;
}
exit:
/*MIMO Power Save-> 0:enable 3:disable*/
if (coex_sta->wl_coex_mode == BT_8822B_1ANT_WLINK_BTMR ||
coex_sta->wl_coex_mode == BT_8822B_1ANT_WLINK_2GFREE)
halbtc8822b1ant_mimo_ps(btc, NM_EXCU, 1);
else
halbtc8822b1ant_mimo_ps(btc, NM_EXCU, 0);
}
static void halbtc8822b1ant_init_coex_var(struct btc_coexist *btc)
@ -4447,12 +4528,13 @@ void ex_halbtc8822b1ant_display_coex_info(struct btc_coexist *btc)
ps_tdma_case = coex_dm->cur_ps_tdma;
CL_SPRINTF(cli_buf, BT_TMP_BUF_SIZE,
"\r\n %-35s = %02x %02x %02x %02x %02x (case-%d, %s)",
"\r\n %-35s = %02x %02x %02x %02x %02x (case-%d, %s, Timer:%d)",
"TDMA",
coex_dm->ps_tdma_para[0], coex_dm->ps_tdma_para[1],
coex_dm->ps_tdma_para[2], coex_dm->ps_tdma_para[3],
coex_dm->ps_tdma_para[4], ps_tdma_case,
(coex_dm->cur_ps_tdma_on ? "TDMA-On" : "TDMA-Off"));
(coex_dm->cur_ps_tdma_on ? "On" : "Off"),
coex_sta->tdma_timer_base);
CL_PRINTF(cli_buf);
switch (coex_sta->wl_coex_mode) {
@ -5001,6 +5083,7 @@ void ex_halbtc8822b1ant_media_status_notify(struct btc_coexist *btc, u8 type)
struct coex_sta_8822b_1ant *coex_sta = &btc->coex_sta_8822b_1ant;
struct coex_dm_8822b_1ant *coex_dm = &btc->coex_dm_8822b_1ant;
boolean wifi_under_b_mode = FALSE;
u8 h2c_parameter[2] = {0};
if (btc->manual_control || btc->stop_coex_dm)
return;
@ -5039,6 +5122,12 @@ void ex_halbtc8822b1ant_media_status_notify(struct btc_coexist *btc, u8 type)
else
btc->btc_write_1byte_bitmask(btc, 0x6cf, BIT(4), 0x1);
/*Leak-AP protection will reopen when connecting AP*/
h2c_parameter[0] = 0xc;
h2c_parameter[1] = 0x0;
btc->btc_fill_h2c(btc, 0x69, 2, h2c_parameter);
coex_sta->is_no_wl_5ms_extend = FALSE;
halbtc8822b1ant_run_coex(btc, BT_8822B_1ANT_RSN_2GMEDIA);
} else {
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
@ -5054,7 +5143,7 @@ void ex_halbtc8822b1ant_media_status_notify(struct btc_coexist *btc, u8 type)
halbtc8822b1ant_run_coex(btc, BT_8822B_1ANT_RSN_MEDIADISCON);
}
btc->btc_get(btc, BTC_GET_U1_IOT_PEER, &coex_sta->wl_iot_peer);
halbtc8822b1ant_update_wifi_ch_info(btc, type);
}
@ -5218,6 +5307,14 @@ void ex_halbtc8822b1ant_bt_info_notify(struct btc_coexist *btc, u8 *tmp_buf,
coex_sta->c2h_bt_inquiry_page =
((coex_sta->bt_info_lb2 & BIT(2)) ? TRUE : FALSE);
if (coex_sta->bt_inq_page_pre != coex_sta->c2h_bt_inquiry_page) {
coex_sta->bt_inq_page_pre = coex_sta->c2h_bt_inquiry_page;
coex_sta->bt_inq_page_remain = TRUE;
if (!coex_sta->c2h_bt_inquiry_page)
coex_sta->bt_inq_page_downcount = 2;
}
if ((coex_sta->bt_info_lb2 & 0x49) == 0x49)
coex_sta->a2dp_bit_pool = (coex_sta->bt_info_hb3 & 0x7f);
else
@ -5241,6 +5338,7 @@ void ex_halbtc8822b1ant_bt_info_notify(struct btc_coexist *btc, u8 *tmp_buf,
if (coex_sta->hid_pair_cnt > 0 && coex_sta->hid_busy_num >= 2) {
coex_sta->bt_418_hid_exist = TRUE;
} else if (coex_sta->hid_busy_num == 1 &&
coex_sta->bt_ctr_ok &&
(coex_sta->high_priority_rx + 100 <
coex_sta->high_priority_tx) &&
coex_sta->high_priority_rx < 100) {
@ -5548,7 +5646,8 @@ void ex_halbtc8822b1ant_coex_dm_reset(struct btc_coexist *btc)
void ex_halbtc8822b1ant_periodical(struct btc_coexist *btc)
{
struct coex_sta_8822b_1ant *coex_sta = &btc->coex_sta_8822b_1ant;
boolean bt_relink_finish = FALSE, is_defreeze = FALSE;
boolean bt_relink_finish = FALSE, is_defreeze = FALSE,
bt_ctr_change = FALSE;
static u8 freeze_cnt;
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
@ -5558,7 +5657,7 @@ void ex_halbtc8822b1ant_periodical(struct btc_coexist *btc)
if (!btc->auto_report)
halbtc8822b1ant_query_bt_info(btc);
halbtc8822b1ant_monitor_bt_ctr(btc);
bt_ctr_change = halbtc8822b1ant_monitor_bt_ctr(btc);
halbtc8822b1ant_monitor_wifi_ctr(btc);
halbtc8822b1ant_update_wifi_link_info(btc,
BT_8822B_1ANT_RSN_PERIODICAL);
@ -5572,6 +5671,12 @@ void ex_halbtc8822b1ant_periodical(struct btc_coexist *btc)
}
}
if (coex_sta->bt_inq_page_downcount != 0) {
coex_sta->bt_inq_page_downcount--;
if (coex_sta->bt_relink_downcount == 0)
coex_sta->bt_inq_page_remain = FALSE;
}
if (coex_sta->freeze_coexrun_by_btinfo) {
freeze_cnt++;
@ -5621,7 +5726,7 @@ void ex_halbtc8822b1ant_periodical(struct btc_coexist *btc)
}
if (halbtc8822b1ant_moniter_wifibt_status(btc) || bt_relink_finish ||
coex_sta->is_set_ps_state_fail || is_defreeze)
coex_sta->is_set_ps_state_fail || is_defreeze || bt_ctr_change)
halbtc8822b1ant_run_coex(btc, BT_8822B_1ANT_RSN_PERIODICAL);
}

View File

@ -205,6 +205,7 @@ enum bt_8822b_1ant_WL_LINK_MODE {
BT_8822B_1ANT_WLINK_2GGO = 0x4,
BT_8822B_1ANT_WLINK_2GGC = 0x5,
BT_8822B_1ANT_WLINK_BTMR = 0x6,
BT_8822B_1ANT_WLINK_2GFREE = 0x7,
BT_8822B_1ANT_WLINK_MAX
};
@ -266,6 +267,7 @@ struct coex_sta_8822b_1ant {
u32 high_priority_rx;
u32 low_priority_tx;
u32 low_priority_rx;
boolean bt_ctr_ok;
boolean is_hi_pri_rx_overhead;
s8 bt_rssi;
u8 pre_bt_rssi_state;
@ -274,6 +276,8 @@ struct coex_sta_8822b_1ant {
u32 bt_info_c2h_cnt[BT_8822B_1ANT_INFO_SRC_MAX];
boolean bt_whck_test;
boolean c2h_bt_inquiry_page;
boolean bt_inq_page_pre;
boolean bt_inq_page_remain;
boolean c2h_bt_remote_name_req;
boolean c2h_bt_page; /* Add for win8.1 page out issue */
boolean wifi_high_pri_task1;
@ -351,6 +355,7 @@ struct coex_sta_8822b_1ant {
u32 gnt_error_cnt;
u8 bt_afh_map[10];
u8 bt_relink_downcount;
u8 bt_inq_page_downcount;
boolean is_tdma_btautoslot;
u8 switch_band_notify_to;
@ -406,6 +411,7 @@ struct coex_sta_8822b_1ant {
u8 tdma_timer_base;
boolean wl_slot_toggle;
boolean wl_slot_toggle_change; /* if toggle to no-toggle */
u8 wl_iot_peer;
};
struct rfe_type_8822b_1ant {
@ -423,6 +429,7 @@ struct wifi_link_info_8822b_1ant {
boolean is_mcc_25g;
boolean is_p2p_connected;
boolean is_connected;
boolean is_32k;
};
/* *******************************************

View File

@ -28,9 +28,9 @@ static const char *const glbt_info_src_8822b_2ant[] = {
"BT Info[bt scbd]"
};
u32 glcoex_ver_date_8822b_2ant = 20191120;
u32 glcoex_ver_8822b_2ant = 0x77;
u32 glcoex_ver_btdesired_8822b_2ant = 0x75;
u32 glcoex_ver_date_8822b_2ant = 20200302;
u32 glcoex_ver_8822b_2ant = 0x7b;
u32 glcoex_ver_btdesired_8822b_2ant = 0x79;
static u8 halbtc8822b2ant_bt_rssi_state(struct btc_coexist *btc,
u8 *ppre_bt_rssi_state, u8 level_num,
@ -264,25 +264,22 @@ halbtc8822b2ant_ccklock_action(struct btc_coexist *btc)
struct coex_sta_8822b_2ant *coex_sta = &btc->coex_sta_8822b_2ant;
u8 h2c_parameter[2] = {0};
static u8 cnt;
boolean wifi_busy = FALSE;
if (coex_sta->tdma_timer_base == 3) {
if (!coex_sta->is_no_wl_5ms_extend) {
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], set h2c 0x69 opcode 12 to turn off 5ms WL slot extend!!\n");
BTC_TRACE(trace_buf);
btc->btc_get(btc, BTC_GET_BL_WIFI_BUSY, &wifi_busy);
h2c_parameter[0] = 0xc;
h2c_parameter[1] = 0x1;
btc->btc_fill_h2c(btc, 0x69, 2, h2c_parameter);
coex_sta->is_no_wl_5ms_extend = TRUE;
cnt = 0;
}
if (!coex_sta->gl_wifi_busy ||
coex_sta->wl_iot_peer == BTC_IOT_PEER_CISCO) {
cnt = 0;
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], wifi is not busy or CISCO AP, return!!\n");
BTC_TRACE(trace_buf);
return;
}
if (!coex_sta->is_no_wl_5ms_extend && coex_sta->force_lps_ctrl &&
!coex_sta->cck_lock_ever) {
if (coex_sta->wl_fw_dbg_info[7] <= 5)
if (coex_sta->wl_fw_dbg_info[7] <= 5 && wifi_busy)
cnt++;
else
cnt = 0;
@ -319,14 +316,13 @@ halbtc8822b2ant_ccklock_detect(struct btc_coexist *btc)
{
struct coex_sta_8822b_2ant *coex_sta = &btc->coex_sta_8822b_2ant;
struct coex_dm_8822b_2ant *coex_dm = &btc->coex_dm_8822b_2ant;
struct btc_wifi_link_info_ext *link_info_ext = &btc->wifi_link_info_ext;
struct wifi_link_info_8822b_2ant *link_info_ext =
&btc->wifi_link_info_8822b_2ant;
boolean is_cck_lock_rate = FALSE;
if (coex_dm->bt_status == BTC_BTSTATUS_INQ_PAGE ||
coex_sta->is_setup_link) {
coex_sta->cck_lock = FALSE;
return;
}
coex_sta->is_setup_link)
return;
if (coex_sta->wl_rx_rate <= BTC_CCK_2 ||
coex_sta->wl_rts_rx_rate <= BTC_CCK_2)
@ -408,10 +404,6 @@ halbtc8822b2ant_set_tdma_timer_base(struct btc_coexist *btc, u8 type)
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], %s() h2c_0x69 = 0x%x\n", __func__, h2c_para[1]);
BTC_TRACE(trace_buf);
/* no 5ms_wl_slot_extend for 4-slot mode */
if (coex_sta->tdma_timer_base == 3)
halbtc8822b2ant_ccklock_action(btc);
}
static void halbtc8822b2ant_coex_switch_thres(struct btc_coexist *btc,
@ -615,14 +607,14 @@ static void halbtc8822b2ant_enable_gnt_to_gpio(struct btc_coexist *btc,
}
}
static void halbtc8822b2ant_monitor_bt_ctr(struct btc_coexist *btc)
static boolean halbtc8822b2ant_monitor_bt_ctr(struct btc_coexist *btc)
{
struct coex_sta_8822b_2ant *coex_sta = &btc->coex_sta_8822b_2ant;
u32 reg_hp_txrx, reg_lp_txrx, u32tmp;
struct coex_dm_8822b_2ant *coex_dm = &btc->coex_dm_8822b_2ant;
u32 reg_hp_txrx, reg_lp_txrx, u32tmp, cnt_bt_all;
u32 reg_hp_tx = 0, reg_hp_rx = 0, reg_lp_tx = 0, reg_lp_rx = 0;
static u8 num_of_bt_counter_chk, cnt_autoslot_hang;
struct btc_bt_link_info *bt_link_info = &btc->bt_link_info;
static u32 cnt_bt_pre = 0;
boolean is_run_coex = FALSE;
reg_hp_txrx = 0x770;
reg_lp_txrx = 0x774;
@ -640,9 +632,21 @@ static void halbtc8822b2ant_monitor_bt_ctr(struct btc_coexist *btc)
coex_sta->low_priority_tx = reg_lp_tx;
coex_sta->low_priority_rx = reg_lp_rx;
if (coex_sta->under_lps || coex_sta->under_ips ||
(coex_sta->high_priority_tx == 65535 &&
coex_sta->high_priority_rx == 65535 &&
coex_sta->low_priority_tx == 65535 &&
coex_sta->low_priority_rx == 65535))
coex_sta->bt_ctr_ok = FALSE;
else
coex_sta->bt_ctr_ok = TRUE;
/* reset counter */
btc->btc_write_1byte(btc, 0x76e, 0xc);
if (!coex_sta->bt_ctr_ok)
return FALSE;
if (coex_sta->low_priority_tx > 1050 &&
!coex_sta->c2h_bt_inquiry_page)
coex_sta->pop_event_cnt++;
@ -654,6 +658,20 @@ static void halbtc8822b2ant_monitor_bt_ctr(struct btc_coexist *btc)
else
coex_sta->is_esco_mode = TRUE;
}
cnt_bt_all = coex_sta->high_priority_tx +
coex_sta->high_priority_rx +
coex_sta->low_priority_tx +
coex_sta->low_priority_rx;
if ((cnt_bt_pre > (cnt_bt_all + 50) ||
cnt_bt_all > (cnt_bt_pre + 50)) &&
coex_dm->bt_status == BT_8822B_2ANT_BSTATUS_NCON_IDLE)
is_run_coex = TRUE;
cnt_bt_pre = cnt_bt_all;
return is_run_coex;
}
static void halbtc8822b2ant_monitor_wifi_ctr(struct btc_coexist *btc)
@ -666,7 +684,6 @@ static void halbtc8822b2ant_monitor_wifi_ctr(struct btc_coexist *btc)
u32 cnt_cck;
static u8 cnt_ccklocking;
u8 h2c_parameter[1] = {0};
struct btc_bt_link_info *bt_link_info = &btc->bt_link_info;
#if 0
/*send h2c to query WL FW dbg info */
@ -1464,11 +1481,16 @@ halbtc8822b2ant_update_wifi_ch_info(struct btc_coexist *btc, u8 type)
}
}
coex_dm->wifi_chnl_info[0] = h2c_parameter[0];
coex_dm->wifi_chnl_info[1] = h2c_parameter[1];
coex_dm->wifi_chnl_info[2] = h2c_parameter[2];
/* Only send mailbox if ch info change */
if (coex_dm->wifi_chnl_info[0] != h2c_parameter[0] &&
coex_dm->wifi_chnl_info[1] != h2c_parameter[1] &&
coex_dm->wifi_chnl_info[2] != h2c_parameter[2]) {
btc->btc_fill_h2c(btc, 0x66, 3, h2c_parameter);
coex_dm->wifi_chnl_info[0] = h2c_parameter[0];
coex_dm->wifi_chnl_info[1] = h2c_parameter[1];
coex_dm->wifi_chnl_info[2] = h2c_parameter[2];
btc->btc_fill_h2c(btc, 0x66, 3, h2c_parameter);
}
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], para[0:2] = 0x%x 0x%x 0x%x\n", h2c_parameter[0],
@ -1584,12 +1606,13 @@ static void halbtc8822b2ant_set_wl_rx_gain(struct btc_coexist *btc,
for (i = 0; i < ARRAY_SIZE(rx_gain_value_en); i++)
btc->btc_write_4byte(btc, 0x81c, rx_gain_value_en[i]);
#if 0
/* set Rx filter corner RCK offset */
btc->btc_set_rf_reg(btc, BTC_RF_A, 0xde, 0x2, 0x1);
btc->btc_set_rf_reg(btc, BTC_RF_A, 0x1d, 0x3f, 0x3f);
btc->btc_set_rf_reg(btc, BTC_RF_B, 0xde, 0x2, 0x1);
btc->btc_set_rf_reg(btc, BTC_RF_B, 0x1d, 0x3f, 0x3f);
#endif
} else {
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], BB Agc Table Off!\n");
@ -1597,12 +1620,13 @@ static void halbtc8822b2ant_set_wl_rx_gain(struct btc_coexist *btc,
for (i = 0; i < ARRAY_SIZE(rx_gain_value_dis); i++)
btc->btc_write_4byte(btc, 0x81c, rx_gain_value_dis[i]);
#if 0
/* set Rx filter corner RCK offset */
btc->btc_set_rf_reg(btc, BTC_RF_A, 0x1d, 0x3f, 0x4);
btc->btc_set_rf_reg(btc, BTC_RF_A, 0xde, 0x2, 0x0);
btc->btc_set_rf_reg(btc, BTC_RF_B, 0x1d, 0x3f, 0x4);
btc->btc_set_rf_reg(btc, BTC_RF_B, 0xde, 0x2, 0x0);
#endif
}
coex_dm->cur_agc_table_en = agc_table_en;
@ -1616,6 +1640,87 @@ static void halbtc8822b2ant_set_bt_rx_gain(struct btc_coexist *btc,
halbtc8822b2ant_write_scbd(btc, BT_8822B_2ANT_SCBD_RXGAIN, rx_gain_en);
}
static void
halbtc8822b2ant_set_rf_para(struct btc_coexist *btc, boolean force_exec,
u8 level)
{
struct btc_coex_sta *coex_sta = &btc->coex_sta;
u8 tmp = 0;
u32 traffic_dir;
struct btc_rf_para rf_para;
/* wl_tx_dec_power, bt_tx_dec_power, wl_rx_gain, bt_rx_lna_constrain */
struct btc_rf_para rf_para_tx_8822b[] = {
{0xc8, 0x00, FALSE, 1}, /* for normal */
{0xc8, 0x00, FALSE, 1}, /* for WL-CPT */
{0xc8, 0x00, TRUE, 1}, /* 2 for RCU SDR */
{0xcc, 0xfa, TRUE, 1},
{0xd0, 0xf7, TRUE, 1},
{0xd4, 0xf3, TRUE, 1},
{0xc8, 0x00, TRUE, 1}, /* 6 for RCU OFC */
{0xcc, 0xfa, TRUE, 1},
{0xd0, 0xf7, TRUE, 1},
{0xd4, 0xf3, TRUE, 1},
{0xc8, 0x00, TRUE, 1}, /* 10 for A2DP SDR */
{0xcc, 0xfa, TRUE, 1},
{0xd0, 0xf7, TRUE, 1},
{0xd4, 0xf3, TRUE, 1},
{0xc8, 0x00, TRUE, 1}, /* 14 for A2DP OFC */
{0xcc, 0xfa, TRUE, 1},
{0xd0, 0xf7, TRUE, 1},
{0xd4, 0xf3, TRUE, 1},
{0xc8, 0x00, TRUE, 1}, /* 18 for A2DP+RCU SDR */
{0xcc, 0xfa, TRUE, 1},
{0xd0, 0xf7, TRUE, 1},
{0xd4, 0xf3, TRUE, 1},
{0xc8, 0x00, TRUE, 1}, /* 22 for A2DP+RCU OFC */
{0xcc, 0xfa, TRUE, 1},
{0xd0, 0xf7, TRUE, 1},
{0xd4, 0xf3, TRUE, 1} };
struct btc_rf_para rf_para_rx_8822b[] = {
{0xc8, 0x00, FALSE, 1}, /* for normal */
{0xc8, 0x00, FALSE, 1}, /* for WL-CPT */
{0xc8, 0x00, TRUE, 1}, /* 2 for RCU SDR */
{0xcc, 0xfa, TRUE, 1},
{0xd0, 0xf7, TRUE, 1},
{0xd4, 0xf3, TRUE, 1},
{0xc8, 0x00, TRUE, 1}, /* 6 for RCU OFC */
{0xcc, 0xfa, TRUE, 1},
{0xd0, 0xf7, TRUE, 1},
{0xd4, 0xf3, TRUE, 1},
{0xc8, 0x00, TRUE, 1}, /* 10 for A2DP SDR */
{0xcc, 0xfa, TRUE, 1},
{0xd0, 0xf7, TRUE, 1},
{0xd4, 0xf3, TRUE, 1},
{0xc8, 0x00, TRUE, 1}, /* 14 for A2DP OFC */
{0xcc, 0xfa, TRUE, 1},
{0xd0, 0xf7, TRUE, 1},
{0xd4, 0xf3, TRUE, 1},
{0xc8, 0x00, TRUE, 1}, /* 18 for A2DP+RCU SDR */
{0xcc, 0xfa, TRUE, 1},
{0xd0, 0xf7, TRUE, 1},
{0xd4, 0xf3, TRUE, 1},
{0xc8, 0x00, TRUE, 1}, /* 22 for A2DP+RCU OFC */
{0xcc, 0xfa, TRUE, 1},
{0xd0, 0xf7, TRUE, 1},
{0xd4, 0xf3, TRUE, 1} };
btc->btc_get(btc, BTC_GET_U4_WIFI_TRAFFIC_DIR, &traffic_dir);
if (level > ARRAY_SIZE(rf_para_tx_8822b))
level = ARRAY_SIZE(rf_para_tx_8822b) - 1;
if (traffic_dir == BTC_WIFI_TRAFFIC_TX)
rf_para = rf_para_tx_8822b[level];
else
rf_para = rf_para_rx_8822b[level];
halbtc8822b2ant_set_wl_tx_power(btc, NM_EXCU, rf_para.wl_pwr_dec_lvl);
halbtc8822b2ant_set_bt_tx_power(btc, FC_EXCU, rf_para.bt_pwr_dec_lvl);
halbtc8822b2ant_set_wl_rx_gain(btc, NM_EXCU, rf_para.wl_low_gain_en);
halbtc8822b2ant_set_bt_rx_gain(btc, FC_EXCU, rf_para.bt_lna_lvl);
}
static u32
halbtc8822b2ant_wait_indirect_reg_ready(struct btc_coexist *btc)
{
@ -2077,7 +2182,6 @@ static void halbtc8822b2ant_set_tdma(struct btc_coexist *btc, u8 byte1,
u8 h2c_parameter[5] = {0};
u8 real_byte1 = byte1, real_byte5 = byte5;
boolean ap_enable = FALSE, result = FALSE;
struct btc_bt_link_info *bt_link_info = &btc->bt_link_info;
u8 ps_type = BTC_PS_WIFI_NATIVE;
if (byte5 & BIT(2))
@ -2168,7 +2272,6 @@ halbtc8822b2ant_tdma(struct btc_coexist *btc, boolean force_exec,
{
struct coex_sta_8822b_2ant *coex_sta = &btc->coex_sta_8822b_2ant;
struct coex_dm_8822b_2ant *coex_dm = &btc->coex_dm_8822b_2ant;
struct btc_bt_link_info *bt_link_info = &btc->bt_link_info;
u8 type;
btc->btc_set_atomic(btc, &coex_dm->setting_tdma, TRUE);
@ -2176,12 +2279,12 @@ halbtc8822b2ant_tdma(struct btc_coexist *btc, boolean force_exec,
/* tcase: bit0~7 --> tdma case index
* bit8 --> for 4-slot (50ms) mode
*/
if (tcase & TDMA_4SLOT)/* 4-slot (50ms) mode */
if (tcase & TDMA_4SLOT)/* 4-slot (50ms) mode */
halbtc8822b2ant_set_tdma_timer_base(btc, 3);
else
halbtc8822b2ant_set_tdma_timer_base(btc, 0);
type = tcase & 0xff;
type = (u8)(tcase & 0xff);
/* To avoid TDMA H2C fail before Last LPS enter */
if (!force_exec && coex_sta->coex_run_reason != BTC_RSN_LPS) {
@ -2204,7 +2307,12 @@ halbtc8822b2ant_tdma(struct btc_coexist *btc, boolean force_exec,
type);
BTC_TRACE(trace_buf);
halbtc8822b2ant_write_scbd(btc, BT_8822B_2ANT_SCBD_TDMA, TRUE);
if (coex_sta->a2dp_exist && coex_sta->bt_inq_page_remain)
halbtc8822b2ant_write_scbd(btc, BT_8822B_2ANT_SCBD_TDMA,
FALSE);
else
halbtc8822b2ant_write_scbd(btc, BT_8822B_2ANT_SCBD_TDMA,
TRUE);
/* enable TBTT nterrupt */
btc->btc_write_1byte_bitmask(btc, 0x550, 0x8, 0x1);
@ -2841,13 +2949,15 @@ static u8 halbtc8822b2ant_action_algorithm(struct btc_coexist *btc)
static void halbtc8822b2ant_action_freerun(struct btc_coexist *btc)
{
struct coex_sta_8822b_2ant *coex_sta = &btc->coex_sta_8822b_2ant;
struct btc_bt_link_info *bt_link_info = &btc->bt_link_info;
static u8 pre_wifi_rssi_state1 = BTC_RSSI_STATE_LOW,
pre_wifi_rssi_state2 = BTC_RSSI_STATE_LOW,
pre_wifi_rssi_state3 = BTC_RSSI_STATE_LOW;
u8 wifi_rssi_state1, wifi_rssi_state2, wifi_rssi_state3;
static u8 pre_bt_rssi_state = BTC_RSSI_STATE_LOW;
u8 bt_rssi_state, lna_lvl = 1;
u8 bt_tx_offset = 0;
u8 bt_tx_offset = 0, level, base = 0;
u32 ap_cnt;
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], ************* freerunXXXX*************\n");
@ -2882,34 +2992,35 @@ static void halbtc8822b2ant_action_freerun(struct btc_coexist *btc)
halbtc8822b2ant_write_scbd(btc, BT_8822B_2ANT_SCBD_CQDDR, TRUE);
if (coex_sta->wl_noisy_level == 0)
bt_tx_offset = 3;
/* keep WL/BT Tx/Rx for non 2G-1port case */
if (coex_sta->wl_coex_mode != BT_8822B_2ANT_WLINK_2G1PORT)
return;
/*avoid tdma off to write 0xc5b ,0xe5b */
halbtc8822b2ant_set_bt_rx_gain(btc, FC_EXCU, TRUE);
halbtc8822b2ant_set_wl_rx_gain(btc, NM_EXCU, TRUE);
ap_cnt = coex_sta->scan_ap_num;
if (bt_link_info->hid_only)
base = 2;
else if (bt_link_info->a2dp_only)
base = 10;
else if (bt_link_info->hid_exist && bt_link_info->a2dp_exist)
base = 18;
if (BTC_RSSI_HIGH(wifi_rssi_state1)) {
halbtc8822b2ant_set_wl_tx_power(btc, NM_EXCU, 0xc8);
halbtc8822b2ant_set_bt_tx_power(btc, FC_EXCU,
0x0 - bt_tx_offset);
} else if (BTC_RSSI_HIGH(wifi_rssi_state2)) {
halbtc8822b2ant_set_wl_tx_power(btc, NM_EXCU, 0xcc);
halbtc8822b2ant_set_bt_tx_power(btc, FC_EXCU,
0xfa - bt_tx_offset);
} else if (BTC_RSSI_HIGH(wifi_rssi_state3)) {
halbtc8822b2ant_set_wl_tx_power(btc, NM_EXCU, 0xd0);
halbtc8822b2ant_set_bt_tx_power(btc, FC_EXCU, 0xf7
- bt_tx_offset);
} else {
halbtc8822b2ant_set_wl_tx_power(btc, NM_EXCU, 0xd4);
halbtc8822b2ant_set_bt_tx_power(btc, FC_EXCU, 0xf3);
}
if (ap_cnt > 10) /* for office case */
base = base + 4;
/* decrease more BT Tx power for clear case */
if (BTC_RSSI_HIGH(wifi_rssi_state1))
level = 0;
else if (BTC_RSSI_HIGH(wifi_rssi_state2))
level = 1;
else if (BTC_RSSI_HIGH(wifi_rssi_state3))
level = 2;
else
level = 3;
level = level + base;
halbtc8822b2ant_set_rf_para(btc, NM_EXCU, level);
}
static void halbtc8822b2ant_action_coex_all_off(struct btc_coexist *btc)
@ -2943,7 +3054,6 @@ static void halbtc8822b2ant_action_bt_whql_test(struct btc_coexist *btc)
static void halbtc8822b2ant_action_bt_relink(struct btc_coexist *btc)
{
struct coex_sta_8822b_2ant *coex_sta = &btc->coex_sta_8822b_2ant;
struct btc_bt_link_info *bt_link_info = &btc->bt_link_info;
halbtc8822b2ant_set_wl_tx_power(btc, NM_EXCU, 0xd8);
halbtc8822b2ant_set_bt_tx_power(btc, NM_EXCU, 0);
@ -3354,7 +3464,6 @@ halbtc8822b2ant_action_wifi_native_lps(struct btc_coexist *btc)
{
struct wifi_link_info_8822b_2ant *wifi_link_info_ext =
&btc->wifi_link_info_8822b_2ant;
struct btc_bt_link_info *bt_link_info = &btc->bt_link_info;
if (wifi_link_info_ext->is_all_under_5g)
return;
@ -3430,7 +3539,14 @@ static void halbtc8822b2ant_action_wifi_connected(struct btc_coexist *btc)
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], Action 2-Ant, algorithm = HID.\n");
BTC_TRACE(trace_buf);
halbtc8822b2ant_action_hid(btc);
if (halbtc8822b2ant_freerun_check(btc)) {
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], Action 2-Ant, algorithm = HID -> Freerun\n");
BTC_TRACE(trace_buf);
halbtc8822b2ant_action_freerun(btc);
} else {
halbtc8822b2ant_action_hid(btc);
}
break;
case BT_8822B_2ANT_COEX_A2DP:
if (halbtc8822b2ant_freerun_check(btc)) {
@ -3484,7 +3600,14 @@ static void halbtc8822b2ant_action_wifi_connected(struct btc_coexist *btc)
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], Action 2-Ant, algorithm = HID+A2DP.\n");
BTC_TRACE(trace_buf);
halbtc8822b2ant_action_hid_a2dp(btc);
if (halbtc8822b2ant_freerun_check(btc)) {
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
"[BTCoex], Action 2-Ant, algorithm = HID -> Freerun\n");
BTC_TRACE(trace_buf);
halbtc8822b2ant_action_freerun(btc);
} else {
halbtc8822b2ant_action_hid_a2dp(btc);
}
break;
default:
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
@ -4470,12 +4593,13 @@ void ex_halbtc8822b2ant_display_coex_info(struct btc_coexist *btc)
ps_tdma_case = coex_dm->cur_ps_tdma;
CL_SPRINTF(cli_buf, BT_TMP_BUF_SIZE,
"\r\n %-35s = %02x %02x %02x %02x %02x (case-%d, %s)",
"\r\n %-35s = %02x %02x %02x %02x %02x (case-%d, %s, Timer:%d)",
"TDMA",
coex_dm->ps_tdma_para[0], coex_dm->ps_tdma_para[1],
coex_dm->ps_tdma_para[2], coex_dm->ps_tdma_para[3],
coex_dm->ps_tdma_para[4], ps_tdma_case,
(coex_dm->cur_ps_tdma_on ? "TDMA-On" : "TDMA-Off"));
(coex_dm->cur_ps_tdma_on ? "On" : "Off"),
coex_sta->tdma_timer_base);
CL_PRINTF(cli_buf);
switch (coex_sta->wl_coex_mode) {
@ -4981,6 +5105,7 @@ void ex_halbtc8822b2ant_media_status_notify(struct btc_coexist *btc, u8 type)
{
struct coex_sta_8822b_2ant *coex_sta = &btc->coex_sta_8822b_2ant;
boolean wifi_under_b_mode = FALSE;
u8 h2c_parameter[2] = {0};
if (btc->manual_control || btc->stop_coex_dm)
return;
@ -5016,6 +5141,12 @@ void ex_halbtc8822b2ant_media_status_notify(struct btc_coexist *btc, u8 type)
else
btc->btc_write_1byte_bitmask(btc, 0x6cf, BIT(4), 0x1);
/*Leak-AP protection will reopen when connecting AP*/
h2c_parameter[0] = 0xc;
h2c_parameter[1] = 0x0;
btc->btc_fill_h2c(btc, 0x69, 2, h2c_parameter);
coex_sta->is_no_wl_5ms_extend = FALSE;
halbtc8822b2ant_run_coex(btc, BT_8822B_2ANT_RSN_2GMEDIA);
} else {
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
@ -5030,7 +5161,7 @@ void ex_halbtc8822b2ant_media_status_notify(struct btc_coexist *btc, u8 type)
halbtc8822b2ant_run_coex(btc, BT_8822B_2ANT_RSN_MEDIADISCON);
}
btc->btc_get(btc, BTC_GET_U1_IOT_PEER, &coex_sta->wl_iot_peer);
halbtc8822b2ant_update_wifi_ch_info(btc, type);
}
@ -5193,6 +5324,14 @@ void ex_halbtc8822b2ant_bt_info_notify(struct btc_coexist *btc, u8 *tmp_buf,
coex_sta->c2h_bt_inquiry_page =
((coex_sta->bt_info_lb2 & BIT(2)) ? TRUE : FALSE);
if (coex_sta->bt_inq_page_pre != coex_sta->c2h_bt_inquiry_page) {
coex_sta->bt_inq_page_pre = coex_sta->c2h_bt_inquiry_page;
coex_sta->bt_inq_page_remain = TRUE;
if (!coex_sta->c2h_bt_inquiry_page)
coex_sta->bt_inq_page_downcount = 2;
}
if ((coex_sta->bt_info_lb2 & 0x49) == 0x49)
coex_sta->a2dp_bit_pool = (coex_sta->bt_info_hb3 & 0x7f);
else
@ -5216,6 +5355,7 @@ void ex_halbtc8822b2ant_bt_info_notify(struct btc_coexist *btc, u8 *tmp_buf,
if (coex_sta->hid_pair_cnt > 0 && coex_sta->hid_busy_num >= 2) {
coex_sta->bt_418_hid_exist = TRUE;
} else if (coex_sta->hid_busy_num == 1 &&
coex_sta->bt_ctr_ok &&
(coex_sta->high_priority_rx + 100 <
coex_sta->high_priority_tx) &&
coex_sta->high_priority_rx < 100) {
@ -5520,7 +5660,8 @@ void ex_halbtc8822b2ant_pnp_notify(struct btc_coexist *btc, u8 pnp_state)
void ex_halbtc8822b2ant_periodical(struct btc_coexist *btc)
{
struct coex_sta_8822b_2ant *coex_sta = &btc->coex_sta_8822b_2ant;
boolean bt_relink_finish = FALSE, is_defreeze = FALSE;
boolean bt_relink_finish = FALSE, is_defreeze = FALSE,
bt_ctr_change = FALSE;
static u8 freeze_cnt;
BTC_SPRINTF(trace_buf, BT_TMP_BUF_SIZE,
@ -5530,7 +5671,7 @@ void ex_halbtc8822b2ant_periodical(struct btc_coexist *btc)
if (!btc->auto_report)
halbtc8822b2ant_query_bt_info(btc);
halbtc8822b2ant_monitor_bt_ctr(btc);
bt_ctr_change = halbtc8822b2ant_monitor_bt_ctr(btc);
halbtc8822b2ant_monitor_wifi_ctr(btc);
halbtc8822b2ant_update_wifi_link_info(btc,
BT_8822B_2ANT_RSN_PERIODICAL);
@ -5544,6 +5685,12 @@ void ex_halbtc8822b2ant_periodical(struct btc_coexist *btc)
}
}
if (coex_sta->bt_inq_page_downcount != 0) {
coex_sta->bt_inq_page_downcount--;
if (coex_sta->bt_relink_downcount == 0)
coex_sta->bt_inq_page_remain = FALSE;
}
if (coex_sta->freeze_coexrun_by_btinfo) {
freeze_cnt++;
@ -5589,7 +5736,7 @@ void ex_halbtc8822b2ant_periodical(struct btc_coexist *btc)
}
if (halbtc8822b2ant_moniter_wifibt_status(btc) || bt_relink_finish ||
coex_sta->is_set_ps_state_fail || is_defreeze)
coex_sta->is_set_ps_state_fail || is_defreeze || bt_ctr_change)
halbtc8822b2ant_run_coex(btc, BT_8822B_2ANT_RSN_PERIODICAL);
}

View File

@ -273,6 +273,7 @@ struct coex_sta_8822b_2ant {
u32 high_priority_rx;
u32 low_priority_tx;
u32 low_priority_rx;
boolean bt_ctr_ok;
boolean is_hi_pri_rx_overhead;
u8 bt_rssi;
u8 pre_bt_rssi_state;
@ -281,6 +282,8 @@ struct coex_sta_8822b_2ant {
u32 bt_info_c2h_cnt[BT_8822B_2ANT_INFO_SRC_MAX];
boolean bt_whck_test;
boolean c2h_bt_inquiry_page;
boolean bt_inq_page_pre;
boolean bt_inq_page_remain;
boolean c2h_bt_remote_name_req;
u8 bt_info_lb2;
@ -365,6 +368,7 @@ struct coex_sta_8822b_2ant {
u8 bt_afh_map[10];
u8 bt_relink_downcount;
u8 bt_inq_page_downcount;
boolean is_tdma_btautoslot;
boolean is_esco_mode;
@ -421,6 +425,7 @@ struct coex_sta_8822b_2ant {
u8 tdma_timer_base;
boolean wl_slot_toggle;
boolean wl_slot_toggle_change; /* if toggle to no-toggle */
u8 wl_iot_peer;
};
#define BT_8822B_2ANT_EXT_BAND_SWITCH_USE_DPDT 0

View File

@ -174,6 +174,37 @@ do {\
#define BTC_ANT_WIFI_AT_CPL_MAIN 0
#define BTC_ANT_WIFI_AT_CPL_AUX 1
/* for common code request */
#define REG_LTE_IDR_COEX_CTRL 0x0038
#define REG_SYS_SDIO_CTRL 0x0070
#define REG_SYS_SDIO_CTRL3 0x0073
/* #define REG_RETRY_LIMIT 0x042a */
/* #define REG_DARFRC 0x0430 */
#define REG_DARFRCH 0x0434
#define REG_CCK_CHECK 0x0454
#define REG_AMPDU_MAX_TIME_V1 0x0455
#define REG_TX_HANG_CTRL 0x045E
#define REG_LIFETIME_EN 0x0426
#define REG_BT_COEX_TABLE0 0x06C0
#define REG_BT_COEX_TABLE1 0x06C4
#define REG_BT_COEX_BRK_TABLE 0x06C8
#define REG_BT_COEX_TABLE_H 0x06CC
#define REG_BT_ACT_STATISTICS 0x0770
#define REG_BT_ACT_STATISTICS_1 0x0774
#define REG_BT_STAT_CTRL 0x0778
#define BIT_EN_GNT_BT_AWAKE BIT(3)
#define BIT_EN_BCN_FUNCTION BIT(3)
#define BIT_EN_BCN_PKT_REL BIT(6)
#define BIT_FEN_BB_GLB_RST BIT(1)
#define BIT_FEN_BB_RSTB BIT(0)
#define TDMA_4SLOT BIT(8)
/* for 2T2R -> 2T1R coex MIMO-PS mechanism tranlation */
#define BTC_2GTDD_MAX_TRY 3 /* the max retry count for 1R->2R */
#define BTC_2GFDD_MAX_STAY 300 /* the max stay time at 1R if 2R try-able (unit: 2s) */
typedef enum _BTC_POWERSAVE_TYPE {
BTC_PS_WIFI_NATIVE = 0, /* wifi original power save behavior */
BTC_PS_LPS_ON = 1,
@ -212,6 +243,7 @@ typedef enum _BTC_CHIP_TYPE {
BTC_CHIP_RTL8723D = 10,
BTC_CHIP_RTL8703B = 11,
BTC_CHIP_RTL8725A = 12,
BTC_CHIP_RTL8723F = 13,
BTC_CHIP_MAX
} BTC_CHIP_TYPE, *PBTC_CHIP_TYPE;
@ -233,15 +265,14 @@ static const char *const glbt_info_src[] = {
"BT Info[bt auto report]",
};
#define TDMA_4SLOT BIT(8)
#define BTC_INFO_FTP BIT(7)
#define BTC_INFO_A2DP BIT(6)
#define BTC_INFO_HID BIT(5)
#define BTC_INFO_FTP BIT(7)
#define BTC_INFO_A2DP BIT(6)
#define BTC_INFO_HID BIT(5)
#define BTC_INFO_SCO_BUSY BIT(4)
#define BTC_INFO_ACL_BUSY BIT(3)
#define BTC_INFO_INQ_PAGE BIT(2)
#define BTC_INFO_SCO_ESCO BIT(1)
#define BTC_INFO_CONNECTION BIT(0)
#define BTC_INFO_CONNECTION BIT(0)
#define BTC_BTINFO_LENGTH_MAX 10
@ -253,9 +284,9 @@ enum btc_gnt_setup_state {
};
enum btc_gnt_setup_state_2 {
BTC_GNT_SW_LOW = 0x0,
BTC_GNT_SW_HIGH = 0x1,
BTC_GNT_HW_PTA = 0x2,
BTC_GNT_HW_PTA = 0x0,
BTC_GNT_SW_LOW = 0x1,
BTC_GNT_SW_HIGH = 0x3,
BTC_GNT_MAX
};
@ -379,6 +410,7 @@ enum btc_ext_ant_switch_type {
BTC_SWITCH_NONE = 0x0,
BTC_SWITCH_SPDT = 0x1,
BTC_SWITCH_SP3T = 0x2,
BTC_SWITCH_DPDT = 0x3,
BTC_SWITCH_ANTMAX
};
@ -428,13 +460,19 @@ enum btc_wl2bt_scoreboard {
BTC_SCBD_EXTFEM = BIT(8),
BTC_SCBD_TDMA = BIT(9),
BTC_SCBD_FIX2M = BIT(10),
BTC_SCBD_ALL = 0xffff
BTC_SCBD_MAILBOX_DBG = BIT(14),
BTC_SCBD_ALL = 0xffff,
BTC_SCBD_ALL_32BIT = 0xffffffff
};
enum btc_bt2wl_scoreboard {
BTC_SCBD_BT_ONOFF = BIT(1),
BTC_SCBD_BT_LPS = BIT(7)
};
enum btc_scoreboard_bit_num {
BTC_SCBD_16_BIT = BIT(0),
BTC_SCBD_32_BIT = BIT(1)
};
enum btc_runreason {
BTC_RSN_2GSCANSTART = 0x0,
@ -457,6 +495,8 @@ enum btc_runreason {
BTC_RSN_LPS = 0x11,
BTC_RSN_TIMERUP = 0x12,
BTC_RSN_WLSTATUS = 0x13,
BTC_RSN_BTCNT = 0x14,
BTC_RSN_RFK = 0x15,
BTC_RSN_MAX
};
@ -481,6 +521,9 @@ static const char *const run_reason_string[] = {
"LPSNotify",
"TimerUp",
"WL_STATUS_CHANGE",
"BT_CNT_CHANGE",
"WL_RFK",
"Reason Max"
};
enum btc_wl_link_mode {
@ -491,6 +534,7 @@ enum btc_wl_link_mode {
BTC_WLINK_2GGO = 0x4,
BTC_WLINK_2GGC = 0x5,
BTC_WLINK_BTMR = 0x6,
BTC_WLINK_2GFREE = 0x7,
BTC_WLINK_MAX
};
@ -501,7 +545,9 @@ static const char *const coex_mode_string[] = {
"5G",
"2G-P2P-GO",
"2G-P2P-GC",
"BT-MR"
"BT-MR",
"2G1RFREE",
"unknow"
};
enum btc_bt_state_cnt {
@ -518,6 +564,7 @@ enum btc_bt_state_cnt {
BTC_CNT_BT_INFOUPDATE = 0xa,
BTC_CNT_BT_IQK = 0xb,
BTC_CNT_BT_IQKFAIL = 0xc,
BTC_CNT_BT_TRX = 0xd,
BTC_CNT_BT_MAX
};
@ -534,8 +581,10 @@ enum btc_wl_state_cnt {
BTC_CNT_WL_NOISY1 = 0x9,
BTC_CNT_WL_NOISY2 = 0xa,
BTC_CNT_WL_ACTIVEPORT = 0xb,
BTC_CNT_WL_5MS_NOEXTEND = 0xc,
BTC_CNT_WL_LEAKAP_NORX = 0xc,
BTC_CNT_WL_FW_NOTIFY = 0xd,
BTC_CNT_WL_2G_TDDTRY = 0xe,
BTC_CNT_WL_2G_FDDSTAY = 0xf,
BTC_CNT_WL_MAX
};
@ -562,6 +611,8 @@ enum btc_timer_cnt {
BTC_TIMER_BT_RELINK = 0x7,
BTC_TIMER_BT_REENABLE = 0x8,
BTC_TIMER_BT_MULTILINK = 0x9,
BTC_TIMER_BT_INQPAGE = 0xa,
BTC_TIMER_BT_A2DP_ACT = 0xb,
BTC_TIMER_MAX
};
@ -572,6 +623,8 @@ enum btc_wl_status_change {
BTC_WLSTATUS_CHANGE_LINKINFO = 0x3,
BTC_WLSTATUS_CHANGE_DIR = 0x4,
BTC_WLSTATUS_CHANGE_NOISY = 0x5,
BTC_WLSTATUS_CHANGE_BTCNT = 0x6,
BTC_WLSTATUS_CHANGE_LOCKTRY = 0x7,
BTC_WLSTATUS_CHANGE_MAX
};
@ -585,6 +638,7 @@ enum btc_commom_chip_setup {
BTC_CSETUP_WL_TX_POWER = 0x6,
BTC_CSETUP_WL_RX_GAIN = 0x7,
BTC_CSETUP_WLAN_ACT_IPS = 0x8,
BTC_CSETUP_BT_CTRL_ACT = 0x9,
BTC_CSETUP_MAX
};
@ -618,6 +672,33 @@ enum btc_wl_priority_mask {
BTC_WLPRI_MAX
};
enum btc_ext_chip_id{
BTC_EXT_CHIP_NONE,
BTC_EXT_CHIP_RF4CE,
BTC_EXT_CHIP_MAX
};
enum btc_ext_chip_mode{
BTC_EXTMODE_NORMAL,
BTC_EXTMODE_VOICE,
BTC_EXTMODE_MAX
};
enum btc_wl_rfk_type {
BTC_PWR_TRK = 0,
BTC_IQK = 1,
BTC_LCK = 2,
BTC_DPK = 3,
BTC_TXGAPK = 4,
BTC_RFK_TYPE_MAX
};
enum btc_wl_rfk_state {
BTC_RFK_START = 0,
BTC_RFK_END = 1,
BTC_RFK_STATE_MAX
};
struct btc_board_info {
/* The following is some board information */
u8 bt_chip_type;
@ -639,6 +720,7 @@ struct btc_board_info {
u8 customerID;
u8 customer_id;
u8 ant_distance; /* WL-BT antenna space for non-shared antenna */
u8 ext_chip_id;
};
struct btc_coex_dm {
@ -661,10 +743,6 @@ struct btc_coex_dm {
u8 bt_status;
u8 wl_chnl_info[3];
u8 cur_toggle_para[6];
u8 cur_val0x6cc;
u32 cur_val0x6c0;
u32 cur_val0x6c4;
u32 cur_val0x6c8;
u32 cur_ant_pos_type;
u32 cur_switch_status;
u32 setting_tdma;
@ -673,15 +751,17 @@ struct btc_coex_dm {
struct btc_coex_sta {
boolean coex_freeze;
boolean coex_freerun;
boolean tdma_bt_autoslot;
boolean rf4ce_en;
boolean is_no_wl_5ms_extend;
boolean force_freerun;
boolean force_tdd;
boolean bt_disabled;
boolean bt_disabled_pre;
boolean bt_link_exist;
boolean bt_whck_test;
boolean bt_inq_page;
boolean bt_inq_page_pre;
boolean bt_inq_page_remain;
boolean bt_inq;
boolean bt_page;
boolean bt_ble_voice;
@ -703,11 +783,14 @@ struct btc_coex_sta {
boolean bt_ble_scan_en;
boolean bt_slave;
boolean bt_a2dp_active;
boolean bt_a2dp_active_pre;
boolean bt_a2dp_active_remain;
boolean bt_slave_latency;
boolean bt_init_scan;
boolean bt_418_hid_exist;
boolean bt_ble_hid_exist;
boolean bt_mesh;
boolean bt_ctr_ok;
boolean wl_under_lps;
boolean wl_under_ips;
@ -723,7 +806,6 @@ struct btc_coex_sta {
boolean wl_gl_busy_pre;
boolean wl_linkscan_proc;
boolean wl_mimo_ps;
boolean wl_ps_state_fail;
boolean wl_cck_dead_lock_ap;
boolean wl_tx_limit_en;
boolean wl_ampdu_limit_en;
@ -732,6 +814,9 @@ struct btc_coex_sta {
boolean wl_pnp_wakeup;
boolean wl_slot_toggle;
boolean wl_slot_toggle_change; /* if toggle to no-toggle */
boolean wl_leak_ap; /* !is_no_wl_5ms_extend */
boolean wl_blacklist_ap;
boolean wl_rfk;
u8 coex_table_type;
u8 coex_run_reason;
@ -759,6 +844,7 @@ struct btc_coex_sta {
u8 bt_sut_pwr_lvl[4];
u8 bt_golden_rx_shift[4];
u8 bt_ext_autoslot_thres;
u8 ext_chip_mode;
u8 wl_pnp_state_pre;
u8 wl_noisy_level;
@ -773,18 +859,23 @@ struct btc_coex_sta {
u8 wl_coex_mode;
u8 wl_iot_peer;
u8 wl_ra_thres;
u8 wl_ampdulen_backup;
u8 wl_ampdulen;
u8 wl_rxagg_size;
u8 wl_toggle_para[6];
u8 wl_toggle_interval;
u16 score_board_BW;
u16 score_board_WB;
u32 score_board_WB;
u16 bt_reg_vendor_ac;
u16 bt_reg_vendor_ae;
u32 bt_reg_vendor_dac;
u16 bt_reg_modem_a;
u16 bt_reg_rf_2;
u16 wl_txlimit_backup;
u16 bt_reg_rf_9;
u16 wl_txlimit;
u32 score_board_BW_32bit;
u32 score_board_WB_32bit;
u32 hi_pri_tx;
u32 hi_pri_rx;
u32 lo_pri_tx;
@ -793,8 +884,9 @@ struct btc_coex_sta {
u32 bt_supported_version;
u32 bt_ble_scan_para[3];
u32 bt_a2dp_device_name;
u32 wl_arfb1_backup;
u32 wl_arfb2_backup;
u32 bt_a2dp_flush_time;
u32 wl_arfb1;
u32 wl_arfb2;
u32 wl_traffic_dir;
u32 wl_bw;
u32 cnt_bt_info_c2h[BTC_BTINFO_SRC_MAX];
@ -1031,6 +1123,7 @@ typedef enum _BTC_GET_TYPE {
BTC_GET_U1_AP_NUM,
BTC_GET_U1_ANT_TYPE,
BTC_GET_U1_IOT_PEER,
BTC_GET_BL_WIFI_BSSID,
/* type u2Byte */
BTC_GET_U2_BEACON_PERIOD,
@ -1151,6 +1244,13 @@ typedef enum _BTC_NOTIFY_TYPE_STACK_OPERATION {
BTC_STACK_OP_MAX
} BTC_NOTIFY_TYPE_STACK_OPERATION, *PBTC_NOTIFY_TYPE_STACK_OPERATION;
typedef enum _BTC_LINK_CHANGE_TYPE{
BTC_LINK_CHANGE_TYPE_NONE = 0x0,
BTC_LINK_CHANGE_TYPE_ECSA_START = 0x1,
BTC_LINK_CHANGE_TYPE_ECSA_DONE = 0x2,
BTC_LINK_CHANGE_TYPE_MAX
}BTC_LINK_CHANGE_TYPE,*PBTC_LINK_CHANGE_TYPE;
/* Bryant Add */
typedef enum _BTC_ANTENNA_POS {
BTC_ANTENNA_AT_MAIN_PORT = 0x1,
@ -1385,11 +1485,16 @@ typedef u4Byte
IN PVOID pBtcContext,
IN u2Byte reg_addr
);
typedef VOID
typedef u2Byte
(*BFP_BTC_R_SCBD)(
IN PVOID pBtcContext,
IN pu2Byte score_board_val
);
typedef u4Byte
(*BFP_BTC_R_SCBD_32BIT)(
IN PVOID pBtcContext,
IN pu4Byte score_board_val
);
typedef VOID
(*BFP_BTC_W_SCBD)(
IN PVOID pBtcContext,
@ -1397,6 +1502,12 @@ typedef VOID
IN BOOLEAN state
);
typedef VOID
(*BFP_BTC_W_SCBD_32BIT)(
IN PVOID pBtcContext,
IN u4Byte bitpos,
IN BOOLEAN state
);
typedef VOID
(*BFP_BTC_W_LINDIRECT)(
IN PVOID pBtcContext,
IN u2Byte reg_addr,
@ -1675,6 +1786,8 @@ struct btc_coexist {
struct btc_coex_sta coex_sta;
struct btc_rfe_type rfe_type;
const struct btc_chip_para *chip_para;
u8 wifi_black_bssid[6];
u8 wifi_bssid[6];
#ifdef CONFIG_RF4CE_COEXIST
struct btc_rf4ce_info rf4ce_info;
@ -1707,7 +1820,10 @@ struct btc_coexist {
BFP_BTC_R_LINDIRECT btc_read_linderct;
BFP_BTC_W_LINDIRECT btc_write_linderct;
BFP_BTC_R_SCBD btc_read_scbd;
BFP_BTC_R_SCBD_32BIT btc_read_scbd_32bit;
BFP_BTC_W_SCBD btc_write_scbd;
BFP_BTC_W_SCBD_32BIT btc_write_scbd_32bit;
/* read/write bb related */
BFP_BTC_SET_BB_REG btc_set_bb_reg;
BFP_BTC_GET_BB_REG btc_get_bb_reg;
@ -1813,7 +1929,10 @@ struct btc_chip_para {
u32 para_ver_date;
u32 para_ver;
u32 bt_desired_ver;
u32 wl_desired_ver;
boolean scbd_support;
u32 scbd_reg;
u8 scbd_bit_num;
boolean mailbox_support;
boolean lte_indirect_access;
boolean new_scbd10_def; /* TRUE: 1:fix 2M(8822c) */
@ -1957,6 +2076,13 @@ EXhalbtcoutsrc_WLStatusChangeNotify(
IN u4Byte change_type
);
VOID
EXhalbtcoutsrc_WL_RFK_Notify(
IN PBTC_COEXIST pBtCoexist,
IN u1Byte path,
IN u1Byte type,
IN u1Byte state
);
VOID
EXhalbtcoutsrc_CoexDmSwitch(
IN PBTC_COEXIST pBtCoexist
);

View File

@ -124,6 +124,11 @@ struct btc_coexist;
#include "halbtc8822c.h"
#endif
#ifdef CONFIG_RTL8723F
#include "halbtc8723fwifionly.h"
#include "halbtc8723f.h"
#endif
#ifdef CONFIG_RTL8192F
#include "halbtc8192f.h"
#endif
@ -150,6 +155,10 @@ struct btc_coexist;
#include "halbtc8822cwifionly.h"
#endif
#ifdef CONFIG_RTL8723F
#include "halbtc8723fwifionly.h"
#endif
#ifdef CONFIG_RTL8814B
#include "halbtc8814bwifionly.h"
#endif

View File

@ -76,6 +76,10 @@
#if defined(CONFIG_RTL8814B)
#include "rtl8814b/HalEfuseMask8814B_USB.h"
#endif
#if defined(CONFIG_RTL8723F)
#include "rtl8723f/HalEfuseMask8723F_USB.h"
#endif
#endif /*CONFIG_USB_HCI*/
#ifdef CONFIG_PCI_HCI
@ -178,4 +182,7 @@
#include "rtl8822c/HalEfuseMask8822C_SDIO.h"
#endif
#if defined(CONFIG_RTL8723F)
#include "rtl8723f/HalEfuseMask8723F_SDIO.h"
#endif
#endif /*CONFIG_SDIO_HCI*/

View File

@ -1,6 +1,6 @@
/******************************************************************************
*
* Copyright(c) 2013 - 2017 Realtek Corporation.
* Copyright(c) 2013 - 2019 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@ -172,6 +172,7 @@ typedef enum _bt_op_code {
BT_LO_OP_GET_AFH_MAP_M = 0x1f,
BT_LO_OP_GET_AFH_MAP_H = 0x20,
BT_OP_SET_BT_TRX_MASK = 0x29,
BT_OP_GET_BT_COEX_SUPPORTED_FEATURE = 0x2a,
BT_OP_GET_BT_COEX_SUPPORTED_VERSION = 0x2b,
BT_OP_GET_BT_ANT_DET_VAL = 0x2c,
@ -533,7 +534,7 @@ u8 halbtcoutsrc_IsWifiBusy(PADAPTER padapter)
{
if (rtw_mi_check_status(padapter, MI_AP_ASSOC))
return _TRUE;
if (rtw_mi_busy_traffic_check(padapter, _FALSE))
if (rtw_mi_busy_traffic_check(padapter))
return _TRUE;
return _FALSE;
@ -721,6 +722,34 @@ struct btc_wifi_link_info halbtcoutsrc_getwifilinkinfo(PBTC_COEXIST pBtCoexist)
wifi_link_info.link_mode = BTC_LINK_25G_MCC_GC_STA;
}
}
if (sta_iface && ap_iface) {
u8 band_sta = sta_iface->mlmeextpriv.cur_channel > 14 ? BAND_ON_5G : BAND_ON_2_4G;
u8 band_ap = ap_iface->mlmeextpriv.cur_channel > 14 ? BAND_ON_5G : BAND_ON_2_4G;
if (band_sta == band_ap) {
switch (band_sta) {
case BAND_ON_2_4G:
#ifdef CONFIG_MCC_MODE
wifi_link_info.link_mode =
mcc_en == _TRUE ? BTC_LINK_2G_MCC_GO_STA : BTC_LINK_2G_SCC_GO_STA;
#else /* !CONFIG_MCC_MODE */
wifi_link_info.link_mode = BTC_LINK_2G_SCC_GO_STA;
#endif /* CONFIG_MCC_MODE */
break;
case BAND_ON_5G:
#ifdef CONFIG_MCC_MODE
wifi_link_info.link_mode =
mcc_en == _TRUE ? BTC_LINK_5G_MCC_GO_STA : BTC_LINK_5G_SCC_GO_STA;
#else /* !CONFIG_MCC_MODE */
wifi_link_info.link_mode = BTC_LINK_5G_SCC_GO_STA;
#endif /* CONFIG_MCC_MODE */
break;
}
} else {
wifi_link_info.link_mode = BTC_LINK_25G_MCC_GO_STA;
}
}
} else {
if (pBtCoexist->board_info.btdm_ant_num == 1)
RTW_ERR("%s do not support n_assoc_iface > 2 (ant_num == 1)", __func__);
@ -782,7 +811,7 @@ static u8 _btmpoper_cmd(PBTC_COEXIST pBtCoexist, u8 opcode, u8 opcodever, u8 *cm
/* GLBtcBtMpRptWait should be _FALSE here*/
if (GLBtcBtMpRptWiFiOK == _FALSE) {
RTW_ERR("%s: Didn't get H2C Rsp Event!\n", __FUNCTION__);
RTW_DBG("%s: Didn't get H2C Rsp Event!\n", __FUNCTION__);
ret = BT_STATUS_H2C_TIMTOUT;
goto exit;
}
@ -1059,6 +1088,11 @@ u32 halbtcoutsrc_GetPhydmVersion(void *pBtcContext)
#ifdef CONFIG_RTL8814B
return RELEASE_VERSION_8814B;
#endif
#ifdef CONFIG_RTL8723F
return RELEASE_VERSION_8723F;
#endif
}
u8 halbtcoutsrc_Get(void *pBtcContext, u8 getType, void *pOutBuf)
@ -1123,10 +1157,10 @@ u8 halbtcoutsrc_Get(void *pBtcContext, u8 getType, void *pOutBuf)
case BTC_GET_BL_WIFI_SCAN:
#if 0
*pu8 = (rtw_mi_check_fwstate(padapter, WIFI_SITE_MONITOR)) ? _TRUE : _FALSE;
*pu8 = (rtw_mi_check_fwstate(padapter, WIFI_UNDER_SURVEY)) ? _TRUE : _FALSE;
#else
/* Use the value of the new variable GLBtcWiFiInScanState to judge whether WiFi is in scan state or not, since the originally used flag
WIFI_SITE_MONITOR in fwstate may not be cleared in time */
WIFI_UNDER_SURVEY in fwstate may not be cleared in time */
*pu8 = GLBtcWiFiInScanState;
#endif
break;
@ -1143,6 +1177,10 @@ u8 halbtcoutsrc_Get(void *pBtcContext, u8 getType, void *pOutBuf)
*pu8 = _FALSE;
break;
case BTC_GET_BL_WIFI_BSSID:
_rtw_memcpy(pu8, get_bssid(&padapter->mlmepriv), ETH_ALEN);
break;
case BTC_GET_BL_WIFI_UNDER_5G:
*pu8 = (pHalData->current_band_type == BAND_ON_5G) ? _TRUE : _FALSE;
break;
@ -1996,7 +2034,7 @@ void halbtcoutsrc_DisplayWifiStatus(PBTC_COEXIST pBtCoexist)
pBtCoexist->btc_get(pBtCoexist, BTC_GET_BL_WIFI_ROAM, &bRoam);
CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d/ %d/ %d ", "Link/ Roam/ Scan",
bLink, bRoam, bScan);
CL_PRINTF(cliBuf);
CL_PRINTF(cliBuf);
pBtCoexist->btc_get(pBtCoexist, BTC_GET_U4_WIFI_IQK_TOTAL, &iqk_cnt_total);
pBtCoexist->btc_get(pBtCoexist, BTC_GET_U4_WIFI_IQK_OK, &iqk_cnt_ok);
@ -2005,9 +2043,9 @@ void halbtcoutsrc_DisplayWifiStatus(PBTC_COEXIST pBtCoexist)
"IQK All/ OK/ Fail/AutoLoad/FWDL", iqk_cnt_total, iqk_cnt_ok, iqk_cnt_fail,
((halbtcoutsrc_is_autoload_fail(pBtCoexist) == _TRUE) ? "fail":"ok"), ((halbtcoutsrc_is_fw_ready(pBtCoexist) == _TRUE) ? "ok":"fail"));
CL_PRINTF(cliBuf);
if (wifiLinkStatus & WIFI_STA_CONNECTED) {
CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s", "IOT Peer", GLBtcIotPeerString[padapter->mlmeextpriv.mlmext_info.assoc_AP_vendor]);
CL_SPRINTF(cliBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s/ "MAC_FMT"", "IOT Peer/BSSID", GLBtcIotPeerString[padapter->mlmeextpriv.mlmext_info.assoc_AP_vendor], MAC_ARG(get_bssid(&padapter->mlmepriv)));
CL_PRINTF(cliBuf);
}
@ -2291,17 +2329,36 @@ void halbtcoutsrc_WriteLIndirectReg(void *pBtcContext, u16 reg_addr, u32 bit_mas
}
}
void halbtcoutsrc_Read_scbd(void *pBtcContext, u16* score_board_val)
u16 halbtcoutsrc_Read_scbd(void *pBtcContext, u16* score_board_val)
{
PBTC_COEXIST btc = (PBTC_COEXIST)pBtcContext;
struct btc_coex_sta *coex_sta = &btc->coex_sta;
const struct btc_chip_para *chip_para = btc->chip_para;
if (!chip_para->scbd_support)
return;
return 0;
*score_board_val = (btc->btc_read_2byte(btc, 0xaa)) & 0x7fff;
*score_board_val = (btc->btc_read_2byte(btc, chip_para->scbd_reg))
& 0x7fff;
coex_sta->score_board_BW = *score_board_val;
return coex_sta->score_board_BW;
}
u32 halbtcoutsrc_Read_scbd_32bit(void *pBtcContext, u32* score_board_val)
{
PBTC_COEXIST btc = (PBTC_COEXIST)pBtcContext;
struct btc_coex_sta *coex_sta = &btc->coex_sta;
const struct btc_chip_para *chip_para = btc->chip_para;
if (!chip_para->scbd_support)
return 0;
*score_board_val = (btc->btc_read_4byte(btc, chip_para->scbd_reg))
& 0x7fffffff;
coex_sta->score_board_BW_32bit = *score_board_val;
return coex_sta->score_board_BW_32bit;
}
void halbtcoutsrc_Write_scbd(void *pBtcContext, u16 bitpos, u8 state)
@ -2310,7 +2367,6 @@ void halbtcoutsrc_Write_scbd(void *pBtcContext, u16 bitpos, u8 state)
struct btc_coex_sta *coex_sta = &btc->coex_sta;
const struct btc_chip_para *chip_para = btc->chip_para;
u16 val = 0x2;
u8* btc_dbg_buf = &gl_btc_trace_buf[0];
if (!chip_para->scbd_support)
return;
@ -2335,16 +2391,52 @@ void halbtcoutsrc_Write_scbd(void *pBtcContext, u16 bitpos, u8 state)
if (val != coex_sta->score_board_WB) {
coex_sta->score_board_WB = val;
val = val | 0x8000;
btc->btc_write_2byte(btc, 0xaa, val);
BTC_SPRINTF(btc_dbg_buf, BT_TMP_BUF_SIZE,
"[BTCoex], write scoreboard 0x%x\n", val);
btc->btc_write_2byte(btc, chip_para->scbd_reg, val);
RTW_DBG("[BTC], write scoreboard 0x%x\n", val);
} else {
BTC_SPRINTF(btc_dbg_buf, BT_TMP_BUF_SIZE,
"[BTCoex], %s: return for nochange\n", __func__);
RTW_DBG("[BTC], return for nochange\n");
}
}
void halbtcoutsrc_Write_scbd_32bit(void *pBtcContext, u32 bitpos, u8 state)
{
PBTC_COEXIST btc = (PBTC_COEXIST)pBtcContext;
struct btc_coex_sta *coex_sta = &btc->coex_sta;
const struct btc_chip_para *chip_para = btc->chip_para;
u32 val = 0x2;
if (!chip_para->scbd_support)
return;
val = val | coex_sta->score_board_WB_32bit;
/* for 8822b, Scoreboard[10]: 0: CQDDR off, 1: CQDDR on
* for 8822c, Scoreboard[10]: 0: CQDDR on, 1:CQDDR fix 2M
*/
if (!btc->chip_para->new_scbd10_def && (bitpos & BTC_SCBD_FIX2M)) {
if (state)
val = val & (~BTC_SCBD_FIX2M);
else
val = val | BTC_SCBD_FIX2M;
} else {
if (state)
val = val | bitpos;
else
val = val & (~bitpos);
}
BTC_TRACE(btc_dbg_buf);
if (val != coex_sta->score_board_WB_32bit) {
coex_sta->score_board_WB_32bit = val;
val = val | 0x80000000;
btc->btc_write_4byte(btc, chip_para->scbd_reg, val);
RTW_DBG("[BTC], write scoreboard 0x%x\n", val);
} else {
RTW_DBG("[BTC], return for nochange\n");
}
}
void halbtcoutsrc_SetBbReg(void *pBtcContext, u32 RegAddr, u32 BitMask, u32 Data)
@ -2451,36 +2543,50 @@ u8 halbtcoutsrc_SetBtAntDetection(void *pBtcContext, u8 txTime, u8 btChnl)
#endif
}
BOOLEAN
halbtcoutsrc_SetBtTRXMASK(
void *pBtcContext,
u8 bt_trx_mask
)
u8 halbtcoutsrc_SetBtTRXMASK(void *pBtcContext, u8 bt_trx_mask)
{
/* Always return _FALSE since we don't implement this yet */
#if 0
struct btc_coexist *pBtCoexist = (struct btc_coexist *)pBtcContext;
PADAPTER Adapter = pBtCoexist->Adapter;
BOOLEAN bStatus = FALSE;
u8 btCanTx = 0;
PBTC_COEXIST pBtCoexist;
u8 bStatus = _FALSE;
u8 btCanTx = 0;
u16 ret = BT_STATUS_BT_OP_SUCCESS;
pBtCoexist = (PBTC_COEXIST)pBtcContext;
if (IS_HARDWARE_TYPE_8723B(pBtCoexist->Adapter) || IS_HARDWARE_TYPE_8723D(pBtCoexist->Adapter)
|| IS_HARDWARE_TYPE_8821C(pBtCoexist->Adapter)) {
if (IS_HARDWARE_TYPE_8723B(pBtCoexist->Adapter))
bStatus = NDBG_SetBtTRXMASK(Adapter, 1, bt_trx_mask, &btCanTx);
else
bStatus = NDBG_SetBtTRXMASK(Adapter, 2, bt_trx_mask, &btCanTx);
if (halbtcoutsrc_IsHwMailboxExist(pBtCoexist) == _TRUE) {
u8 buf[3] = {0};
u8 len = 0;
_irqL irqL;
u8 op_code;
u8 status;
if (IS_HARDWARE_TYPE_8723B(pBtCoexist->Adapter)) {
buf[0] = bt_trx_mask;
len = 1;
} else {
buf[0] = (bt_trx_mask & 0x80) >> 7;
buf[1] = bt_trx_mask & 0x7f;
len = 2;
}
_enter_critical_mutex(&GLBtcBtMpOperLock, &irqL);
op_code = BT_OP_SET_BT_TRX_MASK;
status = _btmpoper_cmd(pBtCoexist, op_code, 0, buf, len);
if (status != BT_STATUS_BT_OP_SUCCESS)
ret = SET_BT_MP_OPER_RET(op_code, status);
_exit_critical_mutex(&GLBtcBtMpOperLock, &irqL);
} else
ret = BT_STATUS_NOT_IMPLEMENT;
}
if (bStatus)
return TRUE;
if (ret == BT_STATUS_BT_OP_SUCCESS)
return _TRUE;
else
return FALSE;
#else
return _FALSE;
#endif
return _FALSE;
}
u16 halbtcoutsrc_GetBtReg_with_status(void *pBtcContext, u8 RegType, u32 RegAddr, u32 *data)
@ -2887,7 +2993,7 @@ void halbtcoutsrc_reduce_wl_tx_power(void *pBtcContext, s8 tx_power)
HAL_DATA_TYPE *pHalData = GET_HAL_DATA((PADAPTER)pBtCoexist->Adapter);
/* The reduction of wl tx pwr should be processed inside the set tx pwr lvl function */
if (IS_HARDWARE_TYPE_8822C(pBtCoexist->Adapter))
if (IS_HARDWARE_TYPE_8822C(pBtCoexist->Adapter) || IS_HARDWARE_TYPE_8723F(pBtCoexist->Adapter))
rtw_hal_set_tx_power_level(pBtCoexist->Adapter, pHalData->current_channel);
}
@ -3006,6 +3112,114 @@ void BT_CoexOffloadC2hCheck(PADAPTER Adapter, u8 *Buffer, u8 Length)
}
#endif
#if (CONFIG_BTCOEX_SUPPORT_BTC_CMN == 1)
static void halbtcoutsrc_wl_noisy_detect(struct btc_coexist *btc)
{
struct btc_coex_sta *coex_sta = &btc->coex_sta;
u32 cnt_cck, ok_11b, err_11b;
ok_11b = btc->btc_phydm_query_PHY_counter(btc, PHYDM_INFO_CRC32_OK_CCK);
err_11b = btc->btc_phydm_query_PHY_counter(btc,
PHYDM_INFO_CRC32_ERROR_CCK);
/* WiFi environment noisy identification */
cnt_cck = ok_11b + err_11b;
if (!coex_sta->wl_gl_busy && !coex_sta->wl_cck_lock) {
if (cnt_cck > 250) {
if (coex_sta->cnt_wl[BTC_CNT_WL_NOISY2] < 5)
coex_sta->cnt_wl[BTC_CNT_WL_NOISY2]++;
if (coex_sta->cnt_wl[BTC_CNT_WL_NOISY2] == 5) {
coex_sta->cnt_wl[BTC_CNT_WL_NOISY0] = 0;
coex_sta->cnt_wl[BTC_CNT_WL_NOISY1] = 0;
}
} else if (cnt_cck < 100) {
if (coex_sta->cnt_wl[BTC_CNT_WL_NOISY0] < 5)
coex_sta->cnt_wl[BTC_CNT_WL_NOISY0]++;
if (coex_sta->cnt_wl[BTC_CNT_WL_NOISY0] == 5) {
coex_sta->cnt_wl[BTC_CNT_WL_NOISY1] = 0;
coex_sta->cnt_wl[BTC_CNT_WL_NOISY2] = 0;
}
} else {
if (coex_sta->cnt_wl[BTC_CNT_WL_NOISY1] < 5)
coex_sta->cnt_wl[BTC_CNT_WL_NOISY1]++;
if (coex_sta->cnt_wl[BTC_CNT_WL_NOISY1] == 5) {
coex_sta->cnt_wl[BTC_CNT_WL_NOISY0] = 0;
coex_sta->cnt_wl[BTC_CNT_WL_NOISY2] = 0;
}
}
if (coex_sta->cnt_wl[BTC_CNT_WL_NOISY2] == 5)
coex_sta->wl_noisy_level = 2;
else if (coex_sta->cnt_wl[BTC_CNT_WL_NOISY1] == 5)
coex_sta->wl_noisy_level = 1;
else
coex_sta->wl_noisy_level = 0;
RTW_DBG("[BTC], wl_noisy_level = %d\n",
coex_sta->wl_noisy_level);
}
}
static boolean halbtcoutsrc_btc_monitor_bt_ctr(struct btc_coexist *btc)
{
struct btc_coex_sta *coex_sta = &btc->coex_sta;
struct btc_coex_dm *coex_dm = &btc->coex_dm;
u32 cnt_bt_hi_pri, cnt_bt_lo_pri, cnt_bt_all;
boolean is_run_coex = _FALSE;
cnt_bt_hi_pri = btc->btc_read_4byte(btc, REG_BT_ACT_STATISTICS);
coex_sta->hi_pri_tx = cnt_bt_hi_pri & MASKLWORD;
coex_sta->hi_pri_rx = (cnt_bt_hi_pri & MASKHWORD) >> 16;
cnt_bt_lo_pri = btc->btc_read_4byte(btc, REG_BT_ACT_STATISTICS_1);
coex_sta->lo_pri_tx = cnt_bt_lo_pri & MASKLWORD;
coex_sta->lo_pri_rx = (cnt_bt_lo_pri & MASKHWORD) >> 16;
RTW_DBG("[BTC], Hi-Pri Rx/Tx: %d/%d, Lo-Pri Rx/Tx: %d/%d\n",
coex_sta->hi_pri_rx, coex_sta->hi_pri_tx,
coex_sta->lo_pri_rx, coex_sta->lo_pri_tx);
/* reset counter */
btc->btc_write_1byte(btc, 0x76e, 0xc);
if (coex_sta->wl_under_lps || coex_sta->wl_under_ips ||
(coex_sta->hi_pri_rx == 65535 && coex_sta->hi_pri_tx == 65535 &&
coex_sta->lo_pri_rx == 65535 && coex_sta->lo_pri_tx == 65535))
coex_sta->bt_ctr_ok = _FALSE;
else
coex_sta->bt_ctr_ok = _TRUE;
if (!coex_sta->bt_ctr_ok)
return _FALSE;
if (coex_sta->hi_pri_rx == 0 && coex_sta->hi_pri_tx == 0 &&
coex_sta->lo_pri_rx == 0 && coex_sta->lo_pri_tx == 0) {
coex_sta->cnt_bt[BTC_CNT_BT_DISABLE]++;
if (coex_sta->cnt_bt[BTC_CNT_BT_DISABLE] > 2)
coex_sta->cnt_bt[BTC_CNT_BT_DISABLE] = 2;
} else {
coex_sta->cnt_bt[BTC_CNT_BT_DISABLE] = 0;
}
cnt_bt_all = coex_sta->hi_pri_rx + coex_sta->hi_pri_tx +
coex_sta->lo_pri_rx + coex_sta->lo_pri_tx;
if ((coex_sta->cnt_bt[BTC_CNT_BT_TRX] > (cnt_bt_all + 50) ||
cnt_bt_all > (coex_sta->cnt_bt[BTC_CNT_BT_TRX] + 50)) &&
coex_dm->bt_status == BTC_BTSTATUS_NCON_IDLE)
is_run_coex = _TRUE;
coex_sta->cnt_bt[BTC_CNT_BT_TRX] = cnt_bt_all;
return is_run_coex;
}
#endif
/* ************************************
* Extern functions called by other module
* ************************************ */
@ -3044,6 +3258,14 @@ u8 EXhalbtcoutsrc_BindBtCoexWithAdapter(void *padapter)
pBtCoexist->chip_type = BTC_CHIP_RTL8725A;
pBtCoexist->chip_para = &btc_chip_para_8192f;
}
#endif
#ifdef PLATFORM_LINUX
#ifdef CONFIG_RTL8723F
else if (IS_HARDWARE_TYPE_8723F(padapter)) {
pBtCoexist->chip_type = BTC_CHIP_RTL8723F;
pBtCoexist->chip_para = &btc_chip_para_8723f;
}
#endif
#endif
else {
pBtCoexist->chip_type = BTC_CHIP_UNDEF;
@ -3119,7 +3341,9 @@ u8 EXhalbtcoutsrc_InitlizeVariables(void *padapter)
pBtCoexist->btc_write_linderct = halbtcoutsrc_WriteLIndirectReg;
pBtCoexist->btc_read_scbd = halbtcoutsrc_Read_scbd;
pBtCoexist->btc_read_scbd_32bit = halbtcoutsrc_Read_scbd_32bit;
pBtCoexist->btc_write_scbd = halbtcoutsrc_Write_scbd;
pBtCoexist->btc_write_scbd_32bit = halbtcoutsrc_Write_scbd_32bit;
pBtCoexist->btc_set_bb_reg = halbtcoutsrc_SetBbReg;
pBtCoexist->btc_get_bb_reg = halbtcoutsrc_GetBbReg;
@ -4689,15 +4913,19 @@ u32 EXhalbtcoutsrc_CoexTimerCheck(PBTC_COEXIST pBtCoexist)
u32 EXhalbtcoutsrc_WLStatusCheck(PBTC_COEXIST pBtCoexist)
{
struct btc_wifi_link_info link_info;
struct btc_coex_sta *coex_sta = &pBtCoexist->coex_sta;
const struct btc_chip_para *chip_para = pBtCoexist->chip_para;
u32 change_map = 0;
static bool wl_busy_pre;
bool wl_busy = _FALSE;
bool wl_busy = _FALSE, bt_ctr_change = _FALSE;
s32 wl_rssi;
u32 traffic_dir;
u8 i, tmp;
static u8 rssi_step_pre = 5, wl_noisy_level_pre = 4;
halbtcoutsrc_wl_noisy_detect(pBtCoexist);
bt_ctr_change = halbtcoutsrc_btc_monitor_bt_ctr(pBtCoexist);
/* WL busy to idle or idle to busy */
pBtCoexist->btc_get(pBtCoexist, BTC_GET_BL_WIFI_BUSY, &wl_busy);
if (wl_busy != wl_busy_pre) {
@ -4743,9 +4971,30 @@ u32 EXhalbtcoutsrc_WLStatusCheck(PBTC_COEXIST pBtCoexist)
}
/* Noisy Detect */
if (pBtCoexist->coex_sta.wl_noisy_level != wl_noisy_level_pre) {
if (coex_sta->wl_noisy_level != wl_noisy_level_pre) {
change_map |= BIT(BTC_WLSTATUS_CHANGE_NOISY);
wl_noisy_level_pre = pBtCoexist->coex_sta.wl_noisy_level;
wl_noisy_level_pre = coex_sta->wl_noisy_level;
}
/* BT Counter change > 50 */
if (bt_ctr_change)
change_map |= BIT(BTC_WLSTATUS_CHANGE_BTCNT);
/* CCK Lock Try */
if (coex_sta->wl_coex_mode == BTC_WLINK_2GFREE)
coex_sta->cnt_wl[BTC_CNT_WL_2G_FDDSTAY]++;
if (coex_sta->wl_coex_mode == BTC_WLINK_2GFREE &&
coex_sta->cnt_wl[BTC_CNT_WL_2G_FDDSTAY] > BTC_2GFDD_MAX_STAY &&
coex_sta->cnt_wl[BTC_CNT_WL_2G_TDDTRY] < BTC_2GTDD_MAX_TRY) {
coex_sta->cnt_wl[BTC_CNT_WL_2G_TDDTRY]++;
RTW_DBG("[BTC], Try 2.4G coex from FDD to TDD (FDD:%d, TRY:%d)\n",
coex_sta->cnt_wl[BTC_CNT_WL_2G_FDDSTAY],
coex_sta->cnt_wl[BTC_CNT_WL_2G_TDDTRY]);
coex_sta->cnt_wl[BTC_CNT_WL_2G_FDDSTAY] = 0;
change_map |= BIT(BTC_WLSTATUS_CHANGE_LOCKTRY);
}
RTW_DBG("[BTC], %s(): change_map = 0x%x\n", __func__, change_map);
@ -4769,6 +5018,14 @@ void EXhalbtcoutsrc_status_monitor(PBTC_COEXIST pBtCoexist)
}
#endif
void EXhalbtcoutsrc_WL_RFK_Notify(PBTC_COEXIST pBtCoexist, u8 path, u8 type, u8 state)
{
#if (CONFIG_BTCOEX_SUPPORT_BTC_CMN == 1)
rtw_btc_ex_wl_rfk_notify(pBtCoexist, path, type, state);
#endif
return;
}
void EXhalbtcoutsrc_periodical(PBTC_COEXIST pBtCoexist)
{
if (!halbtcoutsrc_IsBtCoexistAvailable(pBtCoexist))
@ -5714,6 +5971,11 @@ void hal_btcoex_IQKNotify(PADAPTER padapter, u8 state)
GLBtcWiFiInIQKState = state;
}
void hal_btcoex_WLRFKNotify(PADAPTER padapter, u8 path, u8 type, u8 state)
{
EXhalbtcoutsrc_WL_RFK_Notify(&GLBtCoexist, path, type, state);
}
void hal_btcoex_BtInfoNotify(PADAPTER padapter, u8 length, u8 *tmpBuf)
{
if (GLBtcWiFiInIQKState == _TRUE)
@ -5836,6 +6098,24 @@ void hal_btcoex_SetManualControl(PADAPTER padapter, u8 bmanual)
GLBtCoexist.manual_control = bmanual;
}
void hal_btcoex_set_policy_control(PADAPTER padapter, u8 btc_policy)
{
switch (btc_policy) {
case BTCOEX_POLICY_CONTROL_AUTO:
GLBtCoexist.coex_sta.force_freerun = _FALSE;
GLBtCoexist.coex_sta.force_tdd = _FALSE;
break;
case BTCOEX_POLICY_CONTROL_FORCE_FREERUN:
GLBtCoexist.coex_sta.force_freerun = _TRUE;
GLBtCoexist.coex_sta.force_tdd = _FALSE;
break;
case BTCOEX_POLICY_CONTROL_FORCE_TDMA:
GLBtCoexist.coex_sta.force_freerun = _FALSE;
GLBtCoexist.coex_sta.force_tdd = _TRUE;
break;
}
}
u8 hal_btcoex_1Ant(PADAPTER padapter)
{
if (hal_btcoex_IsBtExist(padapter) == _FALSE)

View File

@ -132,6 +132,11 @@ void hal_btcoex_wifionly_switchband_notify(PADAPTER padapter)
else if (IS_HARDWARE_TYPE_8814B(padapter))
ex_hal8814b_wifi_only_switchbandnotify(&GLBtCoexistWifiOnly, is_5g);
#endif
#ifdef CONFIG_RTL8723F
else if (IS_HARDWARE_TYPE_8723F(padapter))
ex_hal8723f_wifi_only_switchbandnotify(&GLBtCoexistWifiOnly, is_5g);
#endif
}
void hal_btcoex_wifionly_scan_notify(PADAPTER padapter)
@ -192,6 +197,11 @@ void hal_btcoex_wifionly_connect_notify(PADAPTER padapter)
else if (IS_HARDWARE_TYPE_8814B(padapter))
ex_hal8814b_wifi_only_connectnotify(&GLBtCoexistWifiOnly, is_5g);
#endif
#ifdef CONFIG_RTL8723F
else if (IS_HARDWARE_TYPE_8723F(padapter))
ex_hal8723f_wifi_only_connectnotify(&GLBtCoexistWifiOnly, is_5g);
#endif
}
void hal_btcoex_wifionly_hw_config(PADAPTER padapter)
@ -223,6 +233,11 @@ void hal_btcoex_wifionly_hw_config(PADAPTER padapter)
else if (IS_HARDWARE_TYPE_8814B(padapter))
ex_hal8814b_wifi_only_hw_config(pwifionlycfg);
#endif
#ifdef CONFIG_RTL8723F
else if (IS_HARDWARE_TYPE_8723F(padapter))
ex_hal8723f_wifi_only_hw_config(pwifionlycfg);
#endif
}
void hal_btcoex_wifionly_initlizevariables(PADAPTER padapter)

File diff suppressed because it is too large Load Diff

View File

@ -75,6 +75,7 @@ typedef enum _C2H_EVT {
C2H_PER_RATE_RPT = 0x2c,
#endif
C2H_LPS_STATUS_RPT = 0x32,
C2H_SET_TXPWR_FINISH = 0x70,
C2H_DEFEATURE_RSVD = 0xFD,
C2H_EXTEND = 0xff,
} C2H_EVT;
@ -128,4 +129,14 @@ int c2h_per_rate_rpt_hdl(_adapter *adapter, u8 *data, u8 len);
#define LPS_STATUS_RPT_LEN 2
int c2h_lps_status_rpt(PADAPTER adapter, u8 *data, u8 len);
#endif /* CONFIG_LPS_ACK */
#ifdef CONFIG_FW_OFFLOAD_SET_TXPWR_IDX
/* C2H_SET_TXPWR_FINISH, 0x70 */
#define SET_TXPWR_FINISH_LEN 1
void c2h_txpwr_idx_offload_done(_adapter *adapter, u8 *data, u8 len);
int c2h_txpwr_idx_offload_wait(_adapter *adapter);
#endif
void rtw_hal_bcn_early_rpt_c2h_handler(_adapter *adapter);
#endif /* __COMMON_C2H_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -86,7 +86,8 @@ void rtw_hal_update_iqk_fw_offload_cap(_adapter *adapter)
}
}
#if ((RTL8822B_SUPPORT == 1) || (RTL8821C_SUPPORT == 1) || (RTL8814B_SUPPORT == 1) || (RTL8822C_SUPPORT == 1))
#if ((RTL8822B_SUPPORT == 1) || (RTL8821C_SUPPORT == 1) || (RTL8814B_SUPPORT == 1) || (RTL8822C_SUPPORT == 1) \
|| (RTL8723F_SUPPORT == 1))
void rtw_phydm_iqk_trigger(_adapter *adapter)
{
struct dm_struct *p_dm_odm = adapter_to_phydm(adapter);
@ -95,7 +96,7 @@ void rtw_phydm_iqk_trigger(_adapter *adapter)
u8 rfk_forbidden = _FALSE;
halrf_cmn_info_set(p_dm_odm, HALRF_CMNINFO_RFK_FORBIDDEN, rfk_forbidden);
#if (RTL8822C_SUPPORT == 1) || (RTL8814B_SUPPORT == 1)
#if (RTL8822C_SUPPORT == 1) || (RTL8814B_SUPPORT == 1) || (RTL8723F_SUPPORT == 1)
/* halrf_cmn_info_set(p_dm_odm, HALRF_CMNINFO_IQK_SEGMENT, segment); to do */
halrf_rf_k_connect_trigger(p_dm_odm, _TRUE, SEGMENT_FREE);
#else
@ -106,6 +107,30 @@ void rtw_phydm_iqk_trigger(_adapter *adapter)
}
#endif
void rtw_phydm_iqk_trigger_all(_adapter *adapter)
{
struct dm_struct *p_dm_odm = adapter_to_phydm(adapter);
u8 clear = _TRUE;
u8 segment = _FALSE;
u8 rfk_forbidden = _FALSE;
#if ((RTL8822B_SUPPORT == 1) || (RTL8821C_SUPPORT == 1) || (RTL8814B_SUPPORT == 1) || (RTL8822C_SUPPORT == 1) \
|| (RTL8723F_SUPPORT == 1))
halrf_cmn_info_set(p_dm_odm, HALRF_CMNINFO_RFK_FORBIDDEN, rfk_forbidden);
#if (RTL8822C_SUPPORT == 1) || (RTL8814B_SUPPORT == 1) || (RTL8723F_SUPPORT == 1)
/* halrf_cmn_info_set(p_dm_odm, HALRF_CMNINFO_IQK_SEGMENT, segment); to do */
halrf_rf_k_connect_trigger(p_dm_odm, _TRUE, SEGMENT_FREE);
#else
/*segment = _rtw_phydm_iqk_segment_chk(adapter);*/
halrf_cmn_info_set(p_dm_odm, HALRF_CMNINFO_IQK_SEGMENT, segment);
halrf_segment_iqk_trigger(p_dm_odm, clear, segment);
#endif /* (RTL8822C_SUPPORT == 1) || (RTL8814B_SUPPORT == 1) (RTL8723F_SUPPORT == 1) */
#else
halrf_iqk_trigger(p_dm_odm, _FALSE);
#endif /* ((RTL8822B_SUPPORT == 1) || (RTL8821C_SUPPORT == 1) || (RTL8814B_SUPPORT == 1) || (RTL8822C_SUPPORT == 1))
(RTL8723F_SUPPORT == 1) */
}
void rtw_phydm_iqk_trigger_dbg(_adapter *adapter, bool recovery, bool clear, bool segment)
{
struct dm_struct *p_dm_odm = adapter_to_phydm(adapter);
@ -122,6 +147,19 @@ void rtw_phydm_lck_trigger(_adapter *adapter)
halrf_lck_trigger(p_dm_odm);
}
void rtw_hal_phydm_cal_trigger(_adapter *adapter)
{
struct dm_struct *p_dm_odm = adapter_to_phydm(adapter);
rtw_ps_deny(adapter, PS_DENY_IOCTL);
LeaveAllPowerSaveModeDirect(adapter);
rtw_phydm_iqk_trigger_all(adapter);
rtw_ps_deny_cancel(adapter, PS_DENY_IOCTL);
}
#ifdef CONFIG_DBG_RF_CAL
void rtw_hal_iqk_test(_adapter *adapter, bool recovery, bool clear, bool segment)
{
@ -370,7 +408,7 @@ void Init_ODM_ComInfo(_adapter *adapter)
rtw_hal_set_odm_var(adapter, HAL_ODM_REGULATION, NULL, _TRUE);
#ifdef CONFIG_DFS_MASTER
odm_cmn_info_init(pDM_Odm, ODM_CMNINFO_DFS_REGION_DOMAIN, adapter_to_rfctl(adapter)->dfs_region_domain);
rtw_odm_update_dfs_region(dvobj);
odm_cmn_info_hook(pDM_Odm, ODM_CMNINFO_DFS_MASTER_ENABLE, &(adapter_to_rfctl(adapter)->radar_detect_enabled));
#endif
@ -407,6 +445,7 @@ void Init_ODM_ComInfo(_adapter *adapter)
/*halrf info init*/
halrf_cmn_info_init(pDM_Odm, HALRF_CMNINFO_EEPROM_THERMAL_VALUE, pHalData->eeprom_thermal_meter);
halrf_cmn_info_init(pDM_Odm, HALRF_CMNINFO_PWT_TYPE, 0);
halrf_cmn_info_init(pDM_Odm, HALRF_CMNINFO_MP_POWER_TRACKING_TYPE, pHalData->txpwr_pg_mode);
if (rtw_odm_adaptivity_needed(adapter) == _TRUE)
rtw_odm_adaptivity_config_msg(RTW_DBGDUMP, adapter);
@ -600,7 +639,7 @@ void rtw_hal_turbo_edca(_adapter *adapter)
return;
}
if (pregpriv->wifi_spec == 1) { /* || (pmlmeinfo->HT_enable == 0)) */
if ((pregpriv->wifi_spec == 1)) { /* || (pmlmeinfo->HT_enable == 0)) */
precvpriv->is_any_non_be_pkts = _FALSE;
return;
}
@ -1035,6 +1074,18 @@ void GetHalODMVar(
#ifdef RTW_HALMAC
#include "../hal_halmac.h"
#endif
bool rtw_phydm_rfe_ctrl_gpio(
_adapter *adapter,
u8 gpio_num
)
{
#ifdef RTW_HALMAC
if(rtw_halmac_rfe_ctrl_cfg(adapter_to_dvobj(adapter), gpio_num))
return _TRUE;
else
#endif/*RTW_HALMAC*/
return _FALSE;
}
enum hal_status
rtw_phydm_fw_iqk(
@ -1160,6 +1211,7 @@ rtw_phydm_cfg_phy_para(
void rtw_phydm_wd_lps_lclk_hdl(_adapter *adapter)
{
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(adapter);
struct sta_priv *pstapriv = &adapter->stapriv;
struct sta_info *psta = NULL;
@ -1181,6 +1233,14 @@ void rtw_phydm_wd_lps_lclk_hdl(_adapter *adapter)
odm_cmn_info_update(&pHalData->odmpriv, ODM_CMNINFO_LINK, is_linked);
phydm_watchdog_lps_32k(&pHalData->odmpriv);
#ifdef CONFIG_LPS_PG
if (pwrpriv->lps_level == LPS_PG) {
if (rtw_hal_set_lps_pg_info_cmd(adapter) == _FAIL)
RTW_INFO(FUNC_ADPT_FMT": Send PG H2C command Fail! \n",
FUNC_ADPT_ARG(adapter));
}
#endif /* CONFIG_LPS_PG */
}
void rtw_phydm_watchdog_in_lps_lclk(_adapter *adapter)
@ -1338,6 +1398,8 @@ void dump_sta_info(void *sel, struct sta_info *psta)
void rtw_phydm_ra_registed(_adapter *adapter, struct sta_info *psta)
{
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj);
if (psta == NULL) {
RTW_ERR(FUNC_ADPT_FMT" sta is NULL\n", FUNC_ADPT_ARG(adapter));
@ -1345,6 +1407,9 @@ void rtw_phydm_ra_registed(_adapter *adapter, struct sta_info *psta)
return;
}
if (psta->cmn.mac_id >= macid_ctl->num)
return;
phydm_ra_registed(&hal_data->odmpriv, psta->cmn.mac_id, psta->cmn.rssi_stat.rssi);
dump_sta_info(RTW_DBGDUMP, psta);
}
@ -1375,14 +1440,7 @@ void rtw_phydm_trx_cfg(_adapter *adapter, bool tx_1ss)
}
#endif
/*
* trx_mode init - 8822B / 8822C / 8192F
* 1ssNTx - 8192E / 8812A / 8822B / 8822C / 8192F
* Path-diversity - 8822B / 8822C / 8192F
* PHYDM API - phydm_api_trx_mode
*/
static u8 rtw_phydm_config_trx_path(_adapter *adapter)
u8 rtw_hal_runtime_trx_path_decision(_adapter *adapter)
{
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
enum bb_path txpath;
@ -1441,13 +1499,6 @@ static u8 rtw_phydm_config_trx_path(_adapter *adapter)
} else
txpath_1ss = txpath;
if (phydm_api_trx_mode(adapter_to_phydm(adapter), txpath, rxpath, txpath_1ss) == FALSE) {
RTW_ERR("%s txpath=0x%x, rxpath=0x%x, txpath_1ss=0x%x fail\n", __func__
, txpath, rxpath, txpath_1ss);
rtw_warn_on(1);
goto exit;
}
if (hal_data->txpath_nss[0] != txpath_1ss) {
hal_data->txpath_nss[0] = txpath_1ss;
if (txpath_1ss == BB_PATH_AUTO)
@ -1463,23 +1514,14 @@ static u8 rtw_phydm_config_trx_path(_adapter *adapter)
}
#elif defined(CONFIG_RTL8814B)
{
if (config_phydm_trx_mode_8814b(adapter_to_phydm(adapter), txpath, rxpath) == FALSE) {
RTW_ERR("%s txpath=0x%x, rxpath=0x%x fail\n", __func__
, txpath, rxpath);
rtw_warn_on(1);
goto exit;
}
/* 8814B is always full-TX */
tx_path_nss_set_full_tx(hal_data->txpath_nss, hal_data->txpath_num_nss, txpath);
}
#elif defined(CONFIG_RTL8812A) || defined(CONFIG_RTL8192E)
{
#ifdef CONFIG_RTW_TX_NPATH_EN
if (adapter->registrypriv.tx_npath == 1) {
phydm_tx_2path(adapter_to_phydm(adapter));
if (adapter->registrypriv.tx_npath == 1)
tx_path_nss_set_full_tx(hal_data->txpath_nss, hal_data->txpath_num_nss, txpath);
}
#endif
}
#endif
@ -1493,6 +1535,61 @@ exit:
return rst;
}
/*
* trx_mode init - 8822B / 8822C / 8192F
* 1ssNTx - 8192E / 8812A / 8822B / 8822C / 8192F
* Path-diversity - 8822B / 8822C / 8192F
* PHYDM API - phydm_api_trx_mode
*/
static u8 rtw_phydm_config_trx_path(_adapter *adapter)
{
u8 rst = _SUCCESS;
#if defined(CONFIG_RTL8192F) || defined(CONFIG_RTL8822B) ||defined(CONFIG_RTL8822C)
{
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
enum bb_path txpath = hal_data->txpath;
enum bb_path rxpath = hal_data->rxpath;
enum bb_path txpath_1ss = hal_data->txpath_nss[0];
if (phydm_api_trx_mode(adapter_to_phydm(adapter), txpath, rxpath, txpath_1ss) == FALSE) {
RTW_ERR("%s txpath=0x%x, rxpath=0x%x, txpath_1ss=0x%x fail\n", __func__
, txpath, rxpath, txpath_1ss);
rtw_warn_on(1);
rst = _FAIL;
}
}
#elif defined(CONFIG_RTL8814B)
{
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
enum bb_path txpath = hal_data->txpath;
enum bb_path rxpath = hal_data->rxpath;
if (txpath == BB_PATH_ABCD && rxpath == BB_PATH_ABCD)
rst = config_phydm_trx_mode_8814b(adapter_to_phydm(adapter), txpath, rxpath);
else
rst = config_phydm_trx_mode_ext_8814b(adapter_to_phydm(adapter), txpath,
rxpath,
txpath, txpath, txpath);
if (rst == FALSE) {
RTW_ERR("%s txpath=0x%x, rxpath=0x%x fail\n", __func__
, txpath, rxpath);
rtw_warn_on(1);
rst = _FAIL;
}
}
#elif defined(CONFIG_RTL8812A) || defined(CONFIG_RTL8192E)
{
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
if (hal_data->txpath_num_nss[0] == 2)
phydm_tx_2path(adapter_to_phydm(adapter));
}
#endif
return rst;
}
void rtw_phydm_init(_adapter *adapter)
{
PHAL_DATA_TYPE hal_data = GET_HAL_DATA(adapter);
@ -1500,7 +1597,8 @@ void rtw_phydm_init(_adapter *adapter)
rtw_phydm_config_trx_path(adapter);
init_phydm_info(adapter);
odm_dm_init(phydm);
hal_data->phydm_init_result = odm_dm_init(phydm);
#ifdef CONFIG_CUSTOMER01_SMART_ANTENNA
phydm_pathb_q_matrix_rotate_en(phydm);
#endif
@ -1712,12 +1810,23 @@ void rtw_dyn_soml_config(_adapter *adapter)
void rtw_phydm_set_rrsr(_adapter *adapter, u32 rrsr_value, bool write_rrsr)
{
struct dm_struct *phydm = adapter_to_phydm(adapter);
u32 temp_rrsr =0xFFFFFFFF;
if (adapter->registrypriv.set_rrsr_value != 0xFFFFFFFF)
temp_rrsr = adapter->registrypriv.set_rrsr_value;
else
temp_rrsr = rrsr_value;
odm_cmn_info_update(phydm, ODM_CMNINFO_RRSR_VAL, temp_rrsr);
if(write_rrsr)
phydm_rrsr_set_register(phydm, temp_rrsr);
}
void rtw_phydm_dyn_rrsr_en(_adapter *adapter, bool en_rrsr)
{
struct dm_struct *phydm = adapter_to_phydm(adapter);
odm_cmn_info_update(phydm, ODM_CMNINFO_RRSR_VAL, rrsr_value);
if(write_rrsr)
phydm_rrsr_set_register(phydm, rrsr_value);
phydm_rrsr_en(phydm, en_rrsr);
}
void rtw_phydm_read_efuse(_adapter *adapter)
{
@ -1763,7 +1872,7 @@ void rtw_phydm_watchdog(_adapter *adapter, bool in_lps)
RTW_DBG("%s skip due to hw_init_completed == FALSE\n", __func__);
return;
}
if (rtw_mi_check_fwstate(adapter, _FW_UNDER_SURVEY))
if (rtw_mi_check_fwstate(adapter, WIFI_UNDER_SURVEY))
pHalData->bScanInProcess = _TRUE;
else
pHalData->bScanInProcess = _FALSE;

View File

@ -47,12 +47,14 @@ void rtw_dyn_soml_para_set(_adapter *adapter, u8 train_num, u8 intvl,
void rtw_dyn_soml_config(_adapter *adapter);
#endif
void rtw_phydm_set_rrsr(_adapter *adapter, u32 rrsr_value, bool write_rrsr);
void rtw_phydm_dyn_rrsr_en(_adapter *adapter, bool en_rrsr);
void rtw_phydm_watchdog(_adapter *adapter, bool in_lps);
void rtw_hal_update_iqk_fw_offload_cap(_adapter *adapter);
void dump_sta_info(void *sel, struct sta_info *psta);
void dump_sta_traffic(void *sel, _adapter *adapter, struct sta_info *psta);
void rtw_hal_phydm_cal_trigger(_adapter *adapter);
#ifdef CONFIG_DBG_RF_CAL
void rtw_hal_iqk_test(_adapter *adapter, bool recovery, bool clear, bool segment);
void rtw_hal_lck_test(_adapter *adapter);
@ -93,7 +95,8 @@ enum phy_cnt {
CRC32_ERROR_CCK,
};
u32 rtw_phydm_get_phy_cnt(_adapter *adapter, enum phy_cnt cnt);
#if ((RTL8822B_SUPPORT == 1) || (RTL8821C_SUPPORT == 1) || (RTL8814B_SUPPORT == 1) || (RTL8822C_SUPPORT == 1))
#if ((RTL8822B_SUPPORT == 1) || (RTL8821C_SUPPORT == 1) || (RTL8814B_SUPPORT == 1) || (RTL8822C_SUPPORT == 1) \
|| (RTL8723F_SUPPORT == 1))
void rtw_phydm_iqk_trigger(_adapter *adapter);
#endif
void rtw_phydm_read_efuse(_adapter *adapter);
@ -113,5 +116,6 @@ void rtw_phydm_pwr_tracking_directly(_adapter *adapter);
#ifdef CONFIG_CTRL_TXSS_BY_TP
void rtw_phydm_trx_cfg(_adapter *adapter, bool tx_1ss);
#endif
u8 rtw_hal_runtime_trx_path_decision(_adapter *adapter);
bool rtw_phydm_rfe_ctrl_gpio(_adapter *adapter, u8 gpio_num);
#endif /* __HAL_DM_H__ */

View File

@ -87,8 +87,16 @@ u8 rtw_phydm_nhm_ratio(_adapter *adapter)
{
struct dm_struct *phydm = adapter_to_phydm(adapter);
return phydm_cmn_info_query(phydm, (enum phydm_info_query) PHYDM_INFO_NHM_RATIO);
return phydm_cmn_info_query(phydm, (enum phydm_info_query) PHYDM_INFO_NHM_ENV_RATIO);
}
u8 rtw_phydm_nhm_noise_pwr(_adapter *adapter)
{
struct dm_struct *phydm = adapter_to_phydm(adapter);
return phydm_cmn_info_query(phydm, (enum phydm_info_query) PHYDM_INFO_NHM_PWR);
}
void rtw_acs_reset(_adapter *adapter)
{
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
@ -203,7 +211,8 @@ void rtw_acs_get_rst(_adapter *adapter)
(rpt.clm_rpt_stamp == hal_data->acs.trig_rpt.clm_rpt_stamp) &&
(rpt.nhm_rpt_stamp == hal_data->acs.trig_rpt.nhm_rpt_stamp)){
hal_data->acs.clm_ratio[chan_idx] = rpt.clm_ratio;
hal_data->acs.nhm_ratio[chan_idx] = rpt.nhm_ratio;
hal_data->acs.nhm_ratio[chan_idx] = rpt.nhm_env_ratio;
hal_data->acs.env_mntr_rpt[chan_idx] = (rpt.nhm_noise_pwr -100);
_rtw_memcpy(&hal_data->acs.nhm[chan_idx][0], rpt.nhm_result, NHM_RPT_NUM);
/*RTW_INFO("[ACS] get_rst success (rst = 0x%02x, clm_stamp:%d:%d, nhm_stamp:%d:%d)\n",
@ -228,6 +237,8 @@ void rtw_acs_get_rst(_adapter *adapter)
#ifdef CONFIG_RTW_ACS_DBG
RTW_INFO("[ACS] Result CH:%d, CLM:%d NHM:%d\n",
cur_chan, hal_data->acs.clm_ratio[chan_idx], hal_data->acs.nhm_ratio[chan_idx]);
RTW_INFO("[ACS] Result NHM(dBm):%d\n",
hal_data->acs.env_mntr_rpt[chan_idx] );
#endif
}
@ -246,9 +257,9 @@ void _rtw_phydm_acs_select_best_chan(_adapter *adapter)
for (ch_idx = 0; ch_idx < max_chan_nums; ch_idx++) {
if (pbss_nums[ch_idx])
pinterference_time[ch_idx] = (pclm_ratio[ch_idx] / 2) + pnhm_ratio[ch_idx];
pinterference_time[ch_idx] = (pclm_ratio[ch_idx] / 2) + (pnhm_ratio[ch_idx] / 2);
else
pinterference_time[ch_idx] = pclm_ratio[ch_idx] + pnhm_ratio[ch_idx];
pinterference_time[ch_idx] = (pclm_ratio[ch_idx] / 3) + ((pnhm_ratio[ch_idx] * 2) / 3);
if (rtw_get_ch_num_by_idx(adapter, ch_idx) < 14) {
if (pinterference_time[ch_idx] < min_itf_24g) {
@ -358,6 +369,18 @@ u8 rtw_acs_get_nhm_ratio_by_ch_num(_adapter *adapter, u8 chan)
return hal_data->acs.nhm_ratio[chan_idx];
}
u8 rtw_acs_get_nhm_noise_pwr_by_ch_idx(_adapter *adapter, u8 ch_idx)
{
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
if (ch_idx >= MAX_CHANNEL_NUM) {
RTW_ERR("%s [ACS] ch_idx(%d) is invalid\n", __func__, ch_idx);
return 0;
}
return hal_data->acs.env_mntr_rpt[ch_idx];
}
u8 rtw_acs_get_num_ratio_by_ch_idx(_adapter *adapter, u8 ch_idx)
{
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
@ -429,6 +452,36 @@ void rtw_acs_update_current_info(_adapter *adapter)
rtw_acs_current_info_dump(RTW_DBGDUMP, adapter);
#endif
}
/*
rsni
para1:rcpi=>RSSI in dbm
para2:anpi=>nhm in dbm
range:0~255
255: is not available (defined by 802.11k spec)
*/
u8 rtw_acs_get_rsni(_adapter *adapter, s8 rcpi, u8 ch)
{
struct dm_struct *phydm = adapter_to_phydm(adapter);
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
u8 rsni = 255;
s8 anpi = 0;
int chan_idx = -1;
if(ch == 0)
goto exit;
chan_idx = rtw_chset_search_ch(adapter_to_chset(adapter), ch);
if(chan_idx == -1)
goto exit;
anpi = rtw_acs_get_nhm_noise_pwr_by_ch_idx(adapter, chan_idx);
if((rcpi != 0) && (anpi != 0))
rsni = phydm_env_mntr_get_802_11_k_rsni(phydm, rcpi, anpi);
RTW_DBG("[ACS][RSNI]ch=%d chan_idx=%d RSNI=%u RSSI=%d NHM=%d\n", ch, chan_idx, rsni,rcpi, anpi);
exit:
return rsni;
}
#endif /*CONFIG_RTW_ACS*/
#ifdef CONFIG_BACKGROUND_NOISE_MONITOR

View File

@ -80,6 +80,7 @@ struct auto_chan_sel {
bool triggered;
u8 clm_ratio[MAX_CHANNEL_NUM];
u8 nhm_ratio[MAX_CHANNEL_NUM];
s8 env_mntr_rpt[MAX_CHANNEL_NUM]; /*unit:dbm*/
#if (RTK_ACS_VERSION == 3)
u8 nhm[MAX_CHANNEL_NUM][NHM_RPT_NUM];
#endif
@ -124,8 +125,13 @@ void rtw_acs_adv_reset(_adapter *adapter);
u8 rtw_acs_get_clm_ratio_by_ch_num(_adapter *adapter, u8 chan);
u8 rtw_acs_get_clm_ratio_by_ch_idx(_adapter *adapter, u8 ch_idx);
u8 rtw_acs_get_nhm_ratio_by_ch_num(_adapter *adapter, u8 chan);
u8 rtw_acs_get_nhm_noise_pwr_by_ch_idx(_adapter *adapter, u8 ch_idx);
u8 rtw_acs_get_num_ratio_by_ch_idx(_adapter *adapter, u8 ch_idx);
u8 rtw_phydm_clm_ratio(_adapter *adapter);
u8 rtw_phydm_nhm_ratio(_adapter *adapter);
u8 rtw_phydm_nhm_noise_pwr(_adapter *adapter);
void rtw_acs_reset(_adapter *adapter);
void rtw_acs_trigger(_adapter *adapter, u16 scan_time_ms, u8 scan_chan, enum NHM_PID pid);
void rtw_acs_get_rst(_adapter *adapter);
@ -137,7 +143,7 @@ void rtw_acs_current_info_dump(void *sel, _adapter *adapter);
void rtw_acs_start(_adapter *adapter);
void rtw_acs_stop(_adapter *adapter);
u8 rtw_acs_get_rsni(_adapter *adapter, s8 rcpi, u8 ch);
#endif /*CONFIG_RTW_ACS*/
#ifdef CONFIG_BACKGROUND_NOISE_MONITOR

View File

@ -29,6 +29,7 @@
#define MSG_PREFIX "[HALMAC]"
#define RTW_HALMAC_DLFW_MEM_NO_STOP_TX
#define RTW_HALMAC_FILTER_DRV_C2H /* Block C2H owner=driver */
/*
* Driver API for HALMAC operations
@ -569,6 +570,7 @@ const char *const RTW_HALMAC_FEATURE_NAME[] = {
"HALMAC_FEATURE_POWER_TRACKING",
"HALMAC_FEATURE_PSD",
"HALMAC_FEATURE_FW_SNDING",
"HALMAC_FEATURE_DPK",
"HALMAC_FEATURE_ALL"
};
@ -622,6 +624,15 @@ static inline u8 is_valid_id_status(enum halmac_feature_id id, enum halmac_cmd_p
case HALMAC_FEATURE_FW_SNDING:
RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
break;
case HALMAC_FEATURE_DPK:
if (status == HALMAC_CMD_PROCESS_RCVD)
return _FALSE;
if ((status != HALMAC_CMD_PROCESS_DONE)
|| (status != HALMAC_CMD_PROCESS_ERROR))
RTW_WARN("%s: %s unexpected status(0x%x)!\n",
__FUNCTION__, RTW_HALMAC_FEATURE_NAME[id],
status);
break;
case HALMAC_FEATURE_ALL:
RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
break;
@ -682,6 +693,7 @@ static int wait_halmac_event(struct dvobj_priv *d, enum halmac_feature_id id)
struct halmac_adapter *mac;
struct halmac_api *api;
struct submit_ctx *sctx;
int status;
int ret;
@ -690,13 +702,16 @@ static int wait_halmac_event(struct dvobj_priv *d, enum halmac_feature_id id)
return -1;
ret = rtw_sctx_wait(sctx, RTW_HALMAC_FEATURE_NAME[id]);
status = sctx->status;
free_halmac_event(d, id);
if (_SUCCESS == ret)
return 0;
/* timeout! We have to reset halmac state */
RTW_ERR("%s: Wait id(%d, %s) TIMEOUT! Reset HALMAC state!\n",
__FUNCTION__, id, RTW_HALMAC_FEATURE_NAME[id]);
/* If no one change sctx->status, it is timeout case */
if (status == 0)
status = RTW_SCTX_DONE_TIMEOUT;
RTW_ERR("%s: id(%d, %s) status=0x%x ! Reset HALMAC state!\n",
__FUNCTION__, id, RTW_HALMAC_FEATURE_NAME[id], status);
mac = dvobj_to_halmac(d);
api = HALMAC_GET_API(mac);
api->halmac_reset_feature(mac, id);
@ -708,7 +723,9 @@ static int wait_halmac_event(struct dvobj_priv *d, enum halmac_feature_id id)
* Return:
* Always return RTW_HALMAC_SUCCESS, HALMAC don't care the return value.
*/
static u8 _halmac_event_indication(void *p, enum halmac_feature_id feature_id, enum halmac_cmd_process_status process_status, u8 *buf, u32 size)
static u8 _halmac_event_indication(void *p, enum halmac_feature_id feature_id,
enum halmac_cmd_process_status process_status,
u8 *buf, u32 size)
{
struct dvobj_priv *d;
PADAPTER adapter;
@ -733,20 +750,27 @@ static u8 _halmac_event_indication(void *p, enum halmac_feature_id feature_id, e
indicator->status = process_status;
indicator->ret_size = size;
if (!indicator->sctx) {
RTW_WARN("%s: No feature id(%d, %s) waiting!!\n", __FUNCTION__, feature_id, RTW_HALMAC_FEATURE_NAME[feature_id]);
RTW_WARN("%s: id(%d, %s) is not waiting!!\n", __FUNCTION__,
feature_id, RTW_HALMAC_FEATURE_NAME[feature_id]);
goto exit;
}
sctx = indicator->sctx;
if (HALMAC_CMD_PROCESS_ERROR == process_status) {
RTW_ERR("%s: Something wrong id(%d, %s)!!\n", __FUNCTION__, feature_id, RTW_HALMAC_FEATURE_NAME[feature_id]);
RTW_ERR("%s: id(%d, %s) Something wrong!!\n", __FUNCTION__,
feature_id, RTW_HALMAC_FEATURE_NAME[feature_id]);
if ((size == 1) && buf)
RTW_ERR("%s: error code=0x%x\n", __FUNCTION__, *buf);
rtw_sctx_done_err(&sctx, RTW_SCTX_DONE_UNKNOWN);
goto exit;
}
if (size > indicator->buf_size) {
RTW_WARN("%s: id(%d, %s) buffer is not enough(%d<%d), data will be truncated!\n",
__FUNCTION__, feature_id, RTW_HALMAC_FEATURE_NAME[feature_id], indicator->buf_size, size);
RTW_WARN("%s: id(%d, %s) buffer is not enough(%d<%d), "
"and data will be truncated!\n",
__FUNCTION__,
feature_id, RTW_HALMAC_FEATURE_NAME[feature_id],
indicator->buf_size, size);
cpsz = indicator->buf_size;
} else {
cpsz = size;
@ -1194,6 +1218,7 @@ int rtw_halmac_init_adapter(struct dvobj_priv *d, struct halmac_platform_api *pf
struct halmac_adapter *halmac;
struct halmac_api *api;
enum halmac_interface intf;
enum halmac_intf_phy_platform pltfm = HALMAC_INTF_PHY_PLATFORM_ALL;
enum halmac_ret_status status;
int err = 0;
#ifdef CONFIG_SDIO_HCI
@ -1239,9 +1264,13 @@ int rtw_halmac_init_adapter(struct dvobj_priv *d, struct halmac_platform_api *pf
goto deinit;
}
status = api->halmac_phy_cfg(halmac, HALMAC_INTF_PHY_PLATFORM_ALL);
#ifdef CONFIG_PLATFORM_RTK1319
pltfm = HALMAC_INTF_PHY_PLATFORM_DHC;
#endif /* CONFIG_PLATFORM_RTK1319 */
status = api->halmac_phy_cfg(halmac, pltfm);
if (status != HALMAC_RET_SUCCESS) {
RTW_ERR("%s: halmac_phy_cfg fail!(status=%d)\n", __FUNCTION__, status);
RTW_ERR("%s: halmac_phy_cfg fail! (platform=%d, status=%d)\n",
__FUNCTION__, pltfm, status);
err = -1;
goto deinit;
}
@ -1254,9 +1283,13 @@ int rtw_halmac_init_adapter(struct dvobj_priv *d, struct halmac_platform_api *pf
/* Convert clock speed unit to MHz from Hz */
info.clock_speed = RTW_DIV_ROUND_UP(rtw_sdio_get_clock(d), 1000000);
info.block_size = rtw_sdio_get_block_size(d);
RTW_DBG("%s: SDIO ver=%u clock=%uMHz blk_size=%u bytes\n",
if (d->hmpriv.sdio_io_indir == 2)
info.io_indir_flag = 0;
else
info.io_indir_flag = 1; /* Default enable indirect I/O */
RTW_DBG("%s: SDIO ver=%u clock=%uMHz blk_size=%u bytes, io_indir=%u\n",
__FUNCTION__, info.spec_ver+2, info.clock_speed,
info.block_size);
info.block_size, info.io_indir_flag);
status = api->halmac_sdio_hw_info(halmac, &info);
if (status != HALMAC_RET_SUCCESS) {
RTW_ERR("%s: halmac_sdio_hw_info fail!(status=%d)\n",
@ -3473,6 +3506,16 @@ static int init_mac_flow(struct dvobj_priv *d)
/* Sync driver RCR cache with register setting */
rtw_hal_get_hwreg(dvobj_get_primary_adapter(d), HW_VAR_RCR, NULL);
#ifdef CONFIG_RTS_FULL_BW
err = rtw_halmac_set_rts_full_bw(d, _TRUE);
if (err)
RTW_WARN("%s: Fail to set RTS FULL BW mode\n", __FUNCTION__);
#else
err = rtw_halmac_set_rts_full_bw(d, _FALSE);
if (err)
RTW_WARN("%s: Fail to disable RTS FULL BW mode\n", __FUNCTION__);
#endif /* CONFIG_RTS_FULL_BW */
_init_trx_cfg_drv(d);
/* Driver inser flow end */
@ -4137,11 +4180,56 @@ int rtw_halmac_c2h_handle(struct dvobj_priv *d, u8 *c2h, u32 size)
struct halmac_adapter *mac;
struct halmac_api *api;
enum halmac_ret_status status;
#ifdef RTW_HALMAC_FILTER_DRV_C2H
u32 desc_size = 0;
u8 *c2h_data;
u8 sub;
#endif /* RTW_HALMAC_FILTER_DRV_C2H */
mac = dvobj_to_halmac(d);
api = HALMAC_GET_API(mac);
#ifdef RTW_HALMAC_FILTER_DRV_C2H
status = api->halmac_get_hw_value(mac, HALMAC_HW_RX_DESC_SIZE,
&desc_size);
if (status != HALMAC_RET_SUCCESS) {
RTW_ERR("%s: fail to get rx desc size!\n", __FUNCTION__);
goto skip_filter;
}
c2h_data = c2h + desc_size;
sub = C2H_HDR_GET_C2H_SUB_CMD_ID(c2h_data);
switch (sub) {
case C2H_SUB_CMD_ID_C2H_PKT_FTM_DBG:
case C2H_SUB_CMD_ID_C2H_PKT_FTM_2_DBG:
case C2H_SUB_CMD_ID_C2H_PKT_FTM_3_DBG:
case C2H_SUB_CMD_ID_C2H_PKT_FTM_4_DBG:
case C2H_SUB_CMD_ID_FTMACKRPT_HDL_DBG:
case C2H_SUB_CMD_ID_FTMC2H_RPT:
case C2H_SUB_CMD_ID_DRVFTMC2H_RPT:
case C2H_SUB_CMD_ID_C2H_PKT_FTM_5_DBG:
case C2H_SUB_CMD_ID_CCX_RPT:
case C2H_SUB_CMD_ID_C2H_PKT_NAN_RPT:
case C2H_SUB_CMD_ID_C2H_PKT_ATM_RPT:
case C2H_SUB_CMD_ID_C2H_PKT_SCC_CSA_RPT:
case C2H_SUB_CMD_ID_C2H_PKT_FW_STATUS_NOTIFY:
case C2H_SUB_CMD_ID_C2H_PKT_FTMSESSION_END:
case C2H_SUB_CMD_ID_C2H_PKT_DETECT_THERMAL:
case C2H_SUB_CMD_ID_FW_FWCTRL_RPT:
case C2H_SUB_CMD_ID_SCAN_CH_NOTIFY:
case C2H_SUB_CMD_ID_FW_TBTT_RPT:
case C2H_SUB_CMD_ID_BCN_OFFLOAD:
case C2H_SUB_CMD_ID_FW_DBG_MSG:
RTW_PRINT("%s: unhandled C2H, id=0xFF subid=0x%x len=%u\n",
__FUNCTION__, sub, C2H_HDR_GET_LEN(c2h_data));
RTW_PRINT_DUMP("C2H: ", c2h_data, size - desc_size);
return 0;
}
skip_filter:
#endif /* RTW_HALMAC_FILTER_DRV_C2H */
status = api->halmac_get_c2h_info(mac, c2h, size);
if (HALMAC_RET_SUCCESS != status)
return -1;
@ -4761,6 +4849,48 @@ int rtw_halmac_iqk(struct dvobj_priv *d, u8 clear, u8 segment)
return 0;
}
/**
* rtw_halmac_dpk() - Run DP Calibration
* @d: struct dvobj_priv*
* @buf: buffer for store return value
* @bufsz: size of buffer
*
* Process DP Calibration(DPK).
*
* Return 0 for OK, otherwise fail.
*/
int rtw_halmac_dpk(struct dvobj_priv *d, u8 *buf, u32 bufsz)
{
struct halmac_adapter *mac;
struct halmac_api *api;
enum halmac_ret_status status;
enum halmac_feature_id id;
int ret;
mac = dvobj_to_halmac(d);
api = HALMAC_GET_API(mac);
id = HALMAC_FEATURE_DPK;
ret = init_halmac_event(d, id, buf, bufsz);
if (ret)
return -1;
status = api->halmac_start_dpk(mac);
if (status != HALMAC_RET_SUCCESS) {
free_halmac_event(d, id);
RTW_ERR("%s: Fail to start DPK (0x%x)!\n",
__FUNCTION__, status);
return -1;
}
ret = wait_halmac_event(d, id);
if (ret)
return -1;
return 0;
}
static inline u32 _phy_parameter_val_drv2halmac(u32 val, u8 msk_en, u32 msk)
{
if (!msk_en)
@ -5034,6 +5164,35 @@ void rtw_halmac_led_switch(struct dvobj_priv *d, u8 on)
api->halmac_pinmux_wl_led_sw_ctrl(halmac, on);
}
static int _gpio_cfg(struct dvobj_priv *d, enum halmac_gpio_func gpio, u8 enable)
{
struct halmac_adapter *halmac;
struct halmac_api *api;
enum halmac_ret_status status;
halmac = dvobj_to_halmac(d);
api = HALMAC_GET_API(halmac);
if (enable) {
status = api->halmac_pinmux_set_func(halmac, gpio);
if (status != HALMAC_RET_SUCCESS) {
RTW_ERR("%s: pinmux set GPIO(%d) fail!(0x%x)\n",
__FUNCTION__, gpio, status);
return -1;
}
} else {
status = api->halmac_pinmux_free_func(halmac, gpio);
if (status != HALMAC_RET_SUCCESS) {
RTW_ERR("%s: pinmux free GPIO(%d) fail!(0x%x)\n",
__FUNCTION__, gpio, status);
return -1;
}
}
return 0;
}
/**
* rtw_halmac_bt_wake_cfg() - Configure BT wake host function
* @d: struct dvobj_priv*
@ -5047,33 +5206,58 @@ void rtw_halmac_led_switch(struct dvobj_priv *d, u8 on)
*/
int rtw_halmac_bt_wake_cfg(struct dvobj_priv *d, u8 enable)
{
struct halmac_adapter *halmac;
struct halmac_api *api;
enum halmac_ret_status status;
return _gpio_cfg(d, HALMAC_GPIO_FUNC_BT_HOST_WAKE1, enable);
}
static enum halmac_gpio_func _gpio_to_func_for_rfe_ctrl(u8 gpio)
{
enum halmac_gpio_func f = HALMAC_GPIO_FUNC_UNDEFINE;
halmac = dvobj_to_halmac(d);
api = HALMAC_GET_API(halmac);
if (enable) {
status = api->halmac_pinmux_set_func(halmac,
HALMAC_GPIO_FUNC_BT_HOST_WAKE1);
if (status != HALMAC_RET_SUCCESS) {
RTW_ERR("%s: pinmux set BT_HOST_WAKE1 fail!(0x%x)\n",
__FUNCTION__, status);
return -1;
}
} else {
status = api->halmac_pinmux_free_func(halmac,
HALMAC_GPIO_FUNC_BT_HOST_WAKE1);
if (status != HALMAC_RET_SUCCESS) {
RTW_ERR("%s: pinmux free BT_HOST_WAKE1 fail!(0x%x)\n",
__FUNCTION__, status);
return -1;
}
#ifdef CONFIG_RTL8822C
switch (gpio) {
case 1:
f = HALMAC_GPIO_FUNC_ANTSWB;
break;
case 2:
f = HALMAC_GPIO_FUNC_S1_TRSW;
break;
case 3:
f = HALMAC_GPIO_FUNC_S0_TRSW;
break;
case 6:
f = HALMAC_GPIO_FUNC_S0_PAPE;
break;
case 7:
f = HALMAC_GPIO_FUNC_S0_TRSWB;
break;
case 13:
f = HALMAC_GPIO_FUNC_ANTSW;
break;
}
#endif /* CONFIG_RTL8822C */
return 0;
return f;
}
/**
* rtw_halmac_rfe_ctrl_cfg() - Configure RFE control GPIO
* @d: struct dvobj_priv*
* @gpio: gpio number
*
* Configure pinmux to enable RFE control GPIO.
*
* Return 0 for OK, otherwise fail.
*/
int rtw_halmac_rfe_ctrl_cfg(struct dvobj_priv *d, u8 gpio)
{
enum halmac_gpio_func f;
f = _gpio_to_func_for_rfe_ctrl(gpio);
if (f == HALMAC_GPIO_FUNC_UNDEFINE)
return -1;
return _gpio_cfg(d, f, 1);
}
#ifdef CONFIG_PNO_SUPPORT
@ -5277,6 +5461,37 @@ int rtw_halmac_pno_scanoffload(struct dvobj_priv *d, u32 enable)
#ifdef CONFIG_SDIO_HCI
/**
* rtw_halmac_preinit_sdio_io_indirect() - Enable indirect I/O or not
* @d: struct dvobj_priv*
* @enable: true: enable, false: disable
*
* Enable register access using direct I/O or indirect. This function should be
* called before rtw_halmac_init_adapter(), and the life cycle is the same as
* driver until removing driver.
*
* Return 0 for OK, otherwise fail.
*/
int rtw_halmac_preinit_sdio_io_indirect(struct dvobj_priv *d, bool enable)
{
struct halmac_adapter *halmac;
struct halmacpriv *priv;
halmac = dvobj_to_halmac(d);
if (halmac) {
RTW_WARN("%s: illegal operation! "
"preinit function only could be called before init!\n",
__FUNCTION__);
return -1;
}
priv = &d->hmpriv;
priv->sdio_io_indir = (enable ? 1 : 2);
return 0;
}
/*
* Description:
* Update queue allocated page number to driver

View File

@ -1,6 +1,6 @@
/******************************************************************************
*
* Copyright(c) 2015 - 2018 Realtek Corporation.
* Copyright(c) 2015 - 2019 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@ -116,6 +116,9 @@ int rtw_halmac_write32(struct intf_hdl *, u32 addr, u32 value);
/* Software Information */
void rtw_halmac_get_version(char *str, u32 len);
/* Software setting before Initialization */
int rtw_halmac_preinit_sdio_io_indirect(struct dvobj_priv *d, bool enable);
/* Software Initialization */
int rtw_halmac_init_adapter(struct dvobj_priv *d, struct halmac_platform_api *pf_api);
int rtw_halmac_deinit_adapter(struct dvobj_priv *);
@ -195,10 +198,12 @@ int rtw_halmac_download_rsvd_page(struct dvobj_priv *dvobj, u8 pg_offset, u8 *pb
int rtw_halmac_fill_hal_spec(struct dvobj_priv *, struct hal_spec_t *);
int rtw_halmac_p2pps(struct dvobj_priv *dvobj, PHAL_P2P_PS_PARA pp2p_ps_para);
int rtw_halmac_iqk(struct dvobj_priv *d, u8 clear, u8 segment);
int rtw_halmac_dpk(struct dvobj_priv *d, u8 *buf, u32 bufsz);
int rtw_halmac_cfg_phy_para(struct dvobj_priv *d, struct rtw_phy_parameter *para);
int rtw_halmac_led_cfg(struct dvobj_priv *d, u8 enable, u8 mode);
void rtw_halmac_led_switch(struct dvobj_priv *d, u8 on);
int rtw_halmac_bt_wake_cfg(struct dvobj_priv *d, u8 enable);
int rtw_halmac_rfe_ctrl_cfg(struct dvobj_priv *d, u8 gpio);
#ifdef CONFIG_PNO_SUPPORT
int rtw_halmac_pno_scanoffload(struct dvobj_priv *d, u32 enable);
#endif

View File

@ -19,6 +19,7 @@
int usb_init_recv_priv(_adapter *padapter, u16 ini_in_buf_sz)
{
struct registry_priv *regsty = adapter_to_regsty(padapter);
struct recv_priv *precvpriv = &padapter->recvpriv;
int i, res = _SUCCESS;
struct recv_buf *precvbuf;
@ -60,9 +61,9 @@ int usb_init_recv_priv(_adapter *padapter, u16 ini_in_buf_sz)
skb_queue_head_init(&precvpriv->free_recv_skb_queue);
#endif
RTW_INFO("NR_RECVBUFF: %d\n", NR_RECVBUFF);
RTW_INFO("NR_RECVBUFF: %d, recvbuf_nr: %d\n", NR_RECVBUFF, regsty->recvbuf_nr);
RTW_INFO("MAX_RECVBUF_SZ: %d\n", MAX_RECVBUF_SZ);
precvpriv->pallocated_recv_buf = rtw_zmalloc(NR_RECVBUFF * sizeof(struct recv_buf) + 4);
precvpriv->pallocated_recv_buf = rtw_zmalloc(regsty->recvbuf_nr * sizeof(struct recv_buf) + 4);
if (precvpriv->pallocated_recv_buf == NULL) {
res = _FAIL;
goto exit;
@ -72,14 +73,16 @@ int usb_init_recv_priv(_adapter *padapter, u16 ini_in_buf_sz)
precvbuf = (struct recv_buf *)precvpriv->precv_buf;
for (i = 0; i < NR_RECVBUFF ; i++) {
for (i = 0; i < regsty->recvbuf_nr ; i++) {
_rtw_init_listhead(&precvbuf->list);
#ifdef PLATFORM_WINDOWS
_rtw_spinlock_init(&precvbuf->recvbuf_lock);
#endif
precvbuf->alloc_sz = MAX_RECVBUF_SZ;
res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf);
res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf, precvbuf->alloc_sz);
if (res == _FAIL)
break;
@ -91,7 +94,7 @@ int usb_init_recv_priv(_adapter *padapter, u16 ini_in_buf_sz)
precvbuf++;
}
precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF;
precvpriv->free_recv_buf_queue_cnt = regsty->recvbuf_nr;
#if defined(PLATFORM_LINUX) || defined(PLATFORM_FREEBSD)
@ -149,18 +152,19 @@ exit:
void usb_free_recv_priv(_adapter *padapter, u16 ini_in_buf_sz)
{
int i;
struct registry_priv *regsty = &padapter->registrypriv;
struct recv_buf *precvbuf;
struct recv_priv *precvpriv = &padapter->recvpriv;
precvbuf = (struct recv_buf *)precvpriv->precv_buf;
for (i = 0; i < NR_RECVBUFF ; i++) {
for (i = 0; i < regsty->recvbuf_nr ; i++) {
rtw_os_recvbuf_resource_free(padapter, precvbuf);
precvbuf++;
}
if (precvpriv->pallocated_recv_buf)
rtw_mfree(precvpriv->pallocated_recv_buf, NR_RECVBUFF * sizeof(struct recv_buf) + 4);
rtw_mfree(precvpriv->pallocated_recv_buf, regsty->recvbuf_nr * sizeof(struct recv_buf) + 4);
#ifdef CONFIG_USB_INTERRUPT_IN_PIPE
#ifdef PLATFORM_LINUX

View File

@ -36,6 +36,7 @@ const u32 _chip_type_to_odm_ic_type[] = {
ODM_RTL8192F,
ODM_RTL8822C,
ODM_RTL8814B,
ODM_RTL8723F,
0,
};
@ -86,13 +87,12 @@ static void rtw_init_wireless_mode(_adapter *padapter)
struct hal_spec_t *hal_spec = GET_HAL_SPEC(padapter);
if(hal_spec->proto_cap & PROTO_CAP_11B)
proto_wireless_mode |= WIRELESS_11B;
if(hal_spec->proto_cap & PROTO_CAP_11G)
proto_wireless_mode |= WIRELESS_11G;
#ifdef CONFIG_80211AC_VHT
if(hal_spec->band_cap & BAND_CAP_5G)
proto_wireless_mode |= WIRELESS_11A;
#endif
#ifdef CONFIG_80211N_HT
if(hal_spec->proto_cap & PROTO_CAP_11N) {
@ -252,6 +252,7 @@ void dump_hal_trx_mode(void *sel, _adapter *adapter)
{
struct registry_priv *regpriv = &adapter->registrypriv;
PHAL_DATA_TYPE hal_data = GET_HAL_DATA(adapter);
int i;
RTW_PRINT_SEL(sel, "trx_path_bmp:0x%02x(%s), NumTotalRFPath:%u, max_tx_cnt:%u\n"
, hal_data->trx_path_bmp
@ -261,6 +262,9 @@ void dump_hal_trx_mode(void *sel, _adapter *adapter)
);
RTW_PRINT_SEL(sel, "tx_nss:%u, rx_nss:%u\n"
, hal_data->tx_nss, hal_data->rx_nss);
for (i = 0; i < hal_data->tx_nss; i++)
RTW_PRINT_SEL(sel, "txpath_cap_num_%uss:%u\n"
, i + 1, hal_data->txpath_cap_num_nss[i]);
RTW_PRINT_SEL(sel, "\n");
dump_hal_runtime_trx_mode(sel, adapter);
@ -268,25 +272,22 @@ void dump_hal_trx_mode(void *sel, _adapter *adapter)
void _dump_rf_path(void *sel, _adapter *adapter)
{
struct registry_priv *regpriv = &adapter->registrypriv;
PHAL_DATA_TYPE hal_data = GET_HAL_DATA(adapter);
struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
struct registry_priv *regsty = adapter_to_regsty(adapter);
RTW_PRINT_SEL(sel, "[RF_PATH] ver_id.RF_TYPE:%s, rf_reg_path_num:%u, max_tx_cnt:%u\n"
, rf_type_to_rfpath_str(rtw_chip_rftype_to_hal_rftype(adapter, 0))
, GET_HAL_SPEC(adapter)->rf_reg_path_num
, GET_HAL_SPEC(adapter)->max_tx_cnt);
RTW_PRINT_SEL(sel, "[RF_PATH] ver_id.RF_TYPE:%s\n"
, rf_type_to_rfpath_str(rtw_chip_rftype_to_hal_rftype(adapter, 0)));
RTW_PRINT_SEL(sel, "[RF_PATH] HALSPEC's rf_reg_trx_path_bmp:0x%02x, rf_reg_path_avail_num:%u, max_tx_cnt:%u\n"
, hal_spec->rf_reg_trx_path_bmp, hal_spec->rf_reg_path_avail_num, hal_spec->max_tx_cnt);
RTW_PRINT_SEL(sel, "[RF_PATH] PG's trx_path_bmp:0x%02x, max_tx_cnt:%u\n"
, hal_data->eeprom_trx_path_bmp, hal_data->eeprom_max_tx_cnt);
RTW_PRINT_SEL(sel, "[RF_PATH] Registry's RF PATH:%s\n"
, rf_type_to_rfpath_str(regpriv->rf_path));
RTW_PRINT_SEL(sel, "[RF_PATH] Registry's trx_path_bmp:0x%02x, tx_path_lmt:%u, rx_path_lmt:%u\n"
, regsty->trx_path_bmp, regsty->tx_path_lmt, regsty->rx_path_lmt);
RTW_PRINT_SEL(sel, "[RF_PATH] HALDATA's trx_path_bmp:0x%02x, max_tx_cnt:%u\n"
, hal_data->trx_path_bmp, hal_data->max_tx_cnt);
RTW_PRINT_SEL(sel, "[RF_PATH] HALDATA's rf_type:%s\n"
, rf_type_to_rfpath_str(hal_data->rf_type));
RTW_PRINT_SEL(sel, "[RF_PATH] NumTotalRFPath:%d\n"
, hal_data->NumTotalRFPath);
RTW_PRINT_SEL(sel, "[RF_PATH] HALDATA's rf_type:%s, NumTotalRFPath:%d\n"
, rf_type_to_rfpath_str(hal_data->rf_type), hal_data->NumTotalRFPath);
}
#ifdef CONFIG_RTL8814A
@ -310,56 +311,43 @@ if (IS_HARDWARE_TYPE_8814A(adapter)) {
} else
#endif
{
struct registry_priv *regpriv = &adapter->registrypriv;
enum rf_type ic_cap;
enum rf_type type;
struct registry_priv *regsty = adapter_to_regsty(adapter);
u8 trx_path_bmp;
u8 tx_path_num;
u8 rx_path_num;
int i;
ic_cap = rtw_chip_rftype_to_hal_rftype(adapter, hal_spec->rf_reg_path_num);
if (!RF_TYPE_VALID(ic_cap)) {
RTW_ERR("%s rtw_chip_rftype_to_hal_rftype failed\n", __func__);
return _FAIL;
}
type = ic_cap;
if (RF_TYPE_VALID(regpriv->rf_path)) {
if (rf_type_is_a_in_b(regpriv->rf_path, ic_cap))
type = regpriv->rf_path;
else
RTW_WARN("%s invalid regpriv:%s > ic_cap:%s\n", __func__
, rf_type_to_rfpath_str(regpriv->rf_path)
, rf_type_to_rfpath_str(ic_cap));
}
if (hal_data->eeprom_trx_path_bmp != 0x00) {
/* specific trx path is defined, restrict it with rftype(TX and RX num) */
u8 trx_path_bmp = rtw_restrict_trx_path_bmp_by_rftype(
hal_data->eeprom_trx_path_bmp, type, &tx_path_num, &rx_path_num);
trx_path_bmp = hal_spec->rf_reg_trx_path_bmp;
if (regsty->trx_path_bmp != 0x00) {
/* restrict trx_path_bmp with regsty.trx_path_bmp */
trx_path_bmp &= regsty->trx_path_bmp;
if (!trx_path_bmp) {
RTW_ERR("%s rtw_restrict_trx_path_bmp_by_rftype(0x%x, %s) failed\n"
, __func__, hal_data->eeprom_trx_path_bmp
, rf_type_to_rfpath_str(type));
RTW_ERR("%s hal_spec.rf_reg_trx_path_bmp:0x%02x, regsty->trx_path_bmp:0x%02x no intersection\n"
, __func__, hal_spec->rf_reg_trx_path_bmp, regsty->trx_path_bmp);
return _FAIL;
}
} else if (hal_data->eeprom_trx_path_bmp != 0x00) {
/* restrict trx_path_bmp with eeprom_trx_path_bmp */
trx_path_bmp &= hal_data->eeprom_trx_path_bmp;
if (!trx_path_bmp) {
RTW_ERR("%s hal_spec.rf_reg_trx_path_bmp:0x%02x, hal_data->eeprom_trx_path_bmp:0x%02x no intersection\n"
, __func__, hal_spec->rf_reg_trx_path_bmp, hal_data->eeprom_trx_path_bmp);
return _FAIL;
}
hal_data->trx_path_bmp = trx_path_bmp;
hal_data->rf_type = trx_bmp_to_rf_type((trx_path_bmp & 0xF0) >> 4
, trx_path_bmp & 0x0F);
} else {
/* no specific trx path is defined, use default trx_bmp */
enum bb_path tx_bmp, rx_bmp;
rf_type_to_default_trx_bmp(type, &tx_bmp, &rx_bmp);
hal_data->trx_path_bmp = (tx_bmp << 4) | rx_bmp;
hal_data->rf_type = type;
tx_path_num = rf_type_to_rf_tx_cnt(hal_data->rf_type);
rx_path_num = rf_type_to_rf_rx_cnt(hal_data->rf_type);
}
hal_data->NumTotalRFPath = tx_path_num;
if (hal_data->NumTotalRFPath < rx_path_num)
hal_data->NumTotalRFPath = rx_path_num;
/* restrict trx_path_bmp with TX and RX num limit */
trx_path_bmp = rtw_restrict_trx_path_bmp_by_trx_num_lmt(trx_path_bmp
, regsty->tx_path_lmt, regsty->rx_path_lmt, &tx_path_num, &rx_path_num);
if (!trx_path_bmp) {
RTW_ERR("%s rtw_restrict_trx_path_bmp_by_trx_num_lmt(0x%02x, %u, %u) failed\n"
, __func__, trx_path_bmp, regsty->tx_path_lmt, regsty->rx_path_lmt);
return _FAIL;
}
hal_data->trx_path_bmp = trx_path_bmp;
hal_data->rf_type = trx_bmp_to_rf_type((trx_path_bmp & 0xF0) >> 4, trx_path_bmp & 0x0F);
hal_data->NumTotalRFPath = rtw_max(tx_path_num, rx_path_num);
hal_data->max_tx_cnt = hal_spec->max_tx_cnt;
hal_data->max_tx_cnt = rtw_min(hal_data->max_tx_cnt, tx_path_num);
@ -385,9 +373,9 @@ void _dump_trx_nss(void *sel, _adapter *adapter)
struct registry_priv *regpriv = &adapter->registrypriv;
struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
RTW_PRINT_SEL(sel, "[TRX_Nss] HALSPEC - tx_nss :%d, rx_nss:%d\n", hal_spec->tx_nss_num, hal_spec->rx_nss_num);
RTW_PRINT_SEL(sel, "[TRX_Nss] Registry - tx_nss :%d, rx_nss:%d\n", regpriv->tx_nss, regpriv->rx_nss);
RTW_PRINT_SEL(sel, "[TRX_Nss] HALDATA - tx_nss :%d, rx_nss:%d\n", GET_HAL_TX_NSS(adapter), GET_HAL_RX_NSS(adapter));
RTW_PRINT_SEL(sel, "[TRX_Nss] HALSPEC - tx_nss:%d, rx_nss:%d\n", hal_spec->tx_nss_num, hal_spec->rx_nss_num);
RTW_PRINT_SEL(sel, "[TRX_Nss] Registry - tx_nss:%d, rx_nss:%d\n", regpriv->tx_nss, regpriv->rx_nss);
RTW_PRINT_SEL(sel, "[TRX_Nss] HALDATA - tx_nss:%d, rx_nss:%d\n", GET_HAL_TX_NSS(adapter), GET_HAL_RX_NSS(adapter));
}
#define NSS_VALID(nss) (nss > 0)
@ -398,6 +386,7 @@ u8 rtw_hal_trxnss_init(_adapter *adapter)
struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
PHAL_DATA_TYPE hal_data = GET_HAL_DATA(adapter);
enum rf_type rf_path = GET_HAL_RFPATH(adapter);
int i;
hal_data->tx_nss = hal_spec->tx_nss_num;
hal_data->rx_nss = hal_spec->rx_nss_num;
@ -409,6 +398,23 @@ u8 rtw_hal_trxnss_init(_adapter *adapter)
hal_data->rx_nss = rtw_min(hal_data->rx_nss, regpriv->rx_nss);
hal_data->rx_nss = rtw_min(hal_data->rx_nss, rf_type_to_rf_rx_cnt(rf_path));
for (i = 0; i < 4; i++) {
if (hal_data->tx_nss < i + 1)
break;
if (IS_HARDWARE_TYPE_8814B(adapter) /* 8814B is always full-TX */
#ifdef CONFIG_RTW_TX_NPATH_EN
/* these IC is capable of full-TX when macro defined */
|| IS_HARDWARE_TYPE_8192E(adapter) || IS_HARDWARE_TYPE_8192F(adapter)
|| IS_HARDWARE_TYPE_8812(adapter) || IS_HARDWARE_TYPE_8822B(adapter)
|| IS_HARDWARE_TYPE_8822C(adapter)
#endif
)
hal_data->txpath_cap_num_nss[i] = hal_data->max_tx_cnt;
else
hal_data->txpath_cap_num_nss[i] = i + 1;
}
if (1)
_dump_trx_nss(RTW_DBGDUMP, adapter);
@ -527,11 +533,20 @@ uint rtw_hal_iface_init(_adapter *adapter)
uint rtw_hal_init(_adapter *padapter)
{
uint status = _SUCCESS;
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
halrf_set_rfsupportability(adapter_to_phydm(padapter));
status = padapter->hal_func.hal_init(padapter);
if(pHalData ->phydm_init_result) {
status = _FAIL;
RTW_ERR("%s phydm init fail reason=%u \n",
__func__,
pHalData ->phydm_init_result);
}
if (status == _SUCCESS) {
rtw_set_hw_init_completed(padapter, _TRUE);
if (padapter->registrypriv.notch_filter == 1)
@ -556,6 +571,12 @@ uint rtw_hal_init(_adapter *padapter)
#ifdef CONFIG_TDMADIG
rtw_phydm_tdmadig(padapter, TDMADIG_INIT);
#endif/*CONFIG_TDMADIG*/
rtw_phydm_dyn_rrsr_en(padapter,padapter->registrypriv.en_dyn_rrsr);
#ifdef RTW_HALMAC
RTW_INFO("%s: padapter->registrypriv.set_rrsr_value=0x%x\n", __func__,padapter->registrypriv.set_rrsr_value);
if(padapter->registrypriv.set_rrsr_value != 0xFFFFFFFF)
rtw_phydm_set_rrsr(padapter, padapter->registrypriv.set_rrsr_value, TRUE);
#endif
} else {
rtw_set_hw_init_completed(padapter, _FALSE);
RTW_ERR("%s: hal_init fail\n", __func__);
@ -567,12 +588,21 @@ uint rtw_hal_init(_adapter *padapter)
{
uint status = _SUCCESS;
struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
int i;
halrf_set_rfsupportability(adapter_to_phydm(padapter));
status = padapter->hal_func.hal_init(padapter);
if(pHalData ->phydm_init_result) {
status = _FAIL;
RTW_ERR("%s phydm init fail reason=%u \n",
__func__,
pHalData->phydm_init_result);
}
if (status == _SUCCESS) {
rtw_set_hw_init_completed(padapter, _TRUE);
rtw_mi_set_mac_addr(padapter);/*set mac addr of all ifaces*/
@ -608,6 +638,13 @@ uint rtw_hal_init(_adapter *padapter)
rtw_phydm_tdmadig(padapter, TDMADIG_INIT);
#endif/*CONFIG_TDMADIG*/
rtw_phydm_dyn_rrsr_en(padapter,padapter->registrypriv.en_dyn_rrsr);
#ifdef RTW_HALMAC
RTW_INFO("%s: padapter->registrypriv.set_rrsr_value=0x%x\n", __func__,padapter->registrypriv.set_rrsr_value);
if(padapter->registrypriv.set_rrsr_value != 0xFFFFFFFF)
rtw_phydm_set_rrsr(padapter, padapter->registrypriv.set_rrsr_value, TRUE);
#endif
} else {
rtw_set_hw_init_completed(padapter, _FALSE);
RTW_ERR("%s: fail\n", __func__);
@ -816,6 +853,13 @@ u8 rtw_hal_intf_ps_func(_adapter *padapter, HAL_INTF_PS_FUNC efunc_id, u8 *val)
return _FAIL;
}
#ifdef CONFIG_RTW_MGMT_QUEUE
s32 rtw_hal_mgmt_xmitframe_enqueue(_adapter *padapter, struct xmit_frame *pxmitframe)
{
return padapter->hal_func.hal_mgmt_xmitframe_enqueue(padapter, pxmitframe);
}
#endif
s32 rtw_hal_xmitframe_enqueue(_adapter *padapter, struct xmit_frame *pxmitframe)
{
return padapter->hal_func.hal_xmitframe_enqueue(padapter, pxmitframe);
@ -831,9 +875,16 @@ s32 rtw_hal_xmit(_adapter *padapter, struct xmit_frame *pxmitframe)
*/
s32 rtw_hal_mgnt_xmit(_adapter *padapter, struct xmit_frame *pmgntframe)
{
#ifdef CONFIG_RTW_MGMT_QUEUE
_irqL irqL;
struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
#endif
s32 ret = _FAIL;
update_mgntframe_attrib_addr(padapter, pmgntframe);
#ifdef CONFIG_RTW_MGMT_QUEUE
update_mgntframe_subtype(padapter, pmgntframe);
#endif
#if defined(CONFIG_IEEE80211W) || defined(CONFIG_RTW_MESH)
if ((!MLME_IS_MESH(padapter) && SEC_IS_BIP_KEY_INSTALLED(&padapter->securitypriv) == _TRUE)
@ -844,6 +895,23 @@ s32 rtw_hal_mgnt_xmit(_adapter *padapter, struct xmit_frame *pmgntframe)
rtw_mgmt_xmitframe_coalesce(padapter, pmgntframe->pkt, pmgntframe);
#endif
#ifdef CONFIG_RTW_MGMT_QUEUE
if (MLME_IS_AP(padapter) || MLME_IS_MESH(padapter)) {
_enter_critical_bh(&pxmitpriv->lock, &irqL);
ret = mgmt_xmitframe_enqueue_for_sleeping_sta(padapter, pmgntframe);
_exit_critical_bh(&pxmitpriv->lock, &irqL);
#ifdef DBG_MGMT_QUEUE
if (ret == _TRUE)
RTW_INFO("%s doesn't be queued, dattrib->ra:"MAC_FMT" seq_num = %u, subtype = 0x%x\n",
__func__, MAC_ARG(pmgntframe->attrib.ra), pmgntframe->attrib.seqnum, pmgntframe->attrib.subtype);
#endif
if (ret == RTW_QUEUE_MGMT)
return ret;
}
#endif
ret = padapter->hal_func.mgnt_xmit(padapter, pmgntframe);
return ret;
}
@ -1246,13 +1314,16 @@ s32 c2h_handler(_adapter *adapter, u8 id, u8 seq, u8 plen, u8 *payload)
#if defined(CONFIG_TDLS) && defined(CONFIG_TDLS_CH_SW)
case C2H_FW_CHNL_SWITCH_COMPLETE:
#ifndef CONFIG_TDLS_CH_SW_V2
rtw_tdls_chsw_oper_done(adapter);
break;
case C2H_BCN_EARLY_RPT:
rtw_tdls_ch_sw_back_to_base_chnl(adapter);
#endif
break;
#endif
case C2H_BCN_EARLY_RPT:
rtw_hal_bcn_early_rpt_c2h_handler(adapter);
break;
#ifdef CONFIG_MCC_MODE
case C2H_MCC:
rtw_hal_mcc_c2h_handler(adapter, plen, payload);
@ -1290,10 +1361,16 @@ s32 c2h_handler(_adapter *adapter, u8 id, u8 seq, u8 plen, u8 *payload)
c2h_lps_status_rpt(adapter, payload, plen);
break;
#endif
#ifdef CONFIG_FW_OFFLOAD_SET_TXPWR_IDX
case C2H_SET_TXPWR_FINISH:
c2h_txpwr_idx_offload_done(adapter, payload, plen);
break;
#endif
case C2H_EXTEND:
sub_id = payload[0];
/* no handle, goto default */
/* fall through */
default:
if (phydm_c2H_content_parsing(adapter_to_phydm(adapter), id, plen, payload) != TRUE)
ret = _FAIL;
@ -1333,6 +1410,7 @@ s32 rtw_hal_c2h_id_handle_directly(_adapter *adapter, u8 id, u8 seq, u8 plen, u8
case C2H_BCN_EARLY_RPT:
case C2H_AP_REQ_TXRPT:
case C2H_SPC_STAT:
case C2H_SET_TXPWR_FINISH:
return _TRUE;
default:
return _FALSE;
@ -1658,7 +1736,7 @@ static s32 _rtw_hal_macid_drop(_adapter *adapter, u8 macid, u8 drop)
, ADPT_ARG(adapter), drop ? "drop" : "undrop" , macid);
goto exit;
}
if(_rtw_macid_ctl_chk_cap(adapter, MACID_DROP)) {
if (macid < 32) {
#ifndef CONFIG_PROTSEL_MACSLEEP
@ -1738,12 +1816,13 @@ static s32 _rtw_hal_macid_drop(_adapter *adapter, u8 macid, u8 drop)
, ADPT_ARG(adapter), drop ? "drop" : "undrop"
, macid, reg_drop_info, val32);
#endif /* CONFIG_PROTSEL_MACSLEEP */
} else if(_rtw_macid_ctl_chk_cap(adapter, MACID_DROP_INDIRECT)) {
u16 start_addr = macid_ctl->macid_txrpt/8;
u32 txrpt_h4b = 0;
u8 i;
/* each address means 1 byte */
start_addr += macid*(macid_ctl->macid_txrpt_pgsz/8);
/* select tx report buffer */
@ -1798,7 +1877,6 @@ inline s32 rtw_hal_macid_undrop(_adapter *adapter, u8 macid)
return _rtw_hal_macid_drop(adapter, macid, 0);
}
s32 rtw_hal_fill_h2c_cmd(PADAPTER padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer)
{
_adapter *pri_adapter = GET_PRIMARY_ADAPTER(padapter);
@ -1868,11 +1946,17 @@ void rtw_hal_fw_correct_bcn(_adapter *padapter)
void rtw_hal_set_tx_power_level(_adapter *adapter, u8 channel)
{
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
if (phy_chk_ch_setting_consistency(adapter, channel) != _SUCCESS)
return;
hal_data->set_entire_txpwr = 1;
adapter->hal_func.set_tx_power_level_handler(adapter, channel);
rtw_hal_set_txpwr_done(adapter);
hal_data->set_entire_txpwr = 0;
}
void rtw_hal_update_txpwr_level(_adapter *adapter)
@ -1880,6 +1964,7 @@ void rtw_hal_update_txpwr_level(_adapter *adapter)
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
rtw_hal_set_tx_power_level(adapter, hal_data->current_channel);
rtw_rfctl_update_op_mode(adapter_to_rfctl(adapter), 0, 0);
}
void rtw_hal_set_txpwr_done(_adapter *adapter)

View File

@ -42,8 +42,9 @@ const int mcc_max_policy_num = sizeof(mcc_switch_channel_policy_table) /sizeof(u
static void dump_iqk_val_table(PADAPTER padapter)
{
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
struct hal_spec_t *hal_spec = GET_HAL_SPEC(padapter);
struct hal_iqk_reg_backup *iqk_reg_backup = pHalData->iqk_reg_backup;
u8 total_rf_path = pHalData->NumTotalRFPath;
u8 total_rf_path = hal_spec->rf_reg_path_num;
u8 rf_path_idx = 0;
u8 backup_chan_idx = 0;
u8 backup_reg_idx = 0;
@ -385,7 +386,7 @@ static void mcc_cfg_phdym_rf_ch (_adapter *adapter)
set_channel_bwmode(adapter, mlmeext->cur_channel, mlmeext->cur_ch_offset, mlmeext->cur_bwmode);
order = mccadapriv->order;
mcc_dm->mcc_rf_ch[order] = phy_query_rf_reg(adapter, RF_PATH_A, 0x18, 0xffffffff);
mcc_dm->mcc_rf_ch[order] = phy_query_rf_reg(adapter, RF_PATH_A, 0x18, 0x03ff);
}
static void mcc_cfg_phdym_update_macid (_adapter *adapter, u8 add, u8 mac_id)
@ -1270,7 +1271,14 @@ u8 rtw_hal_dl_mcc_fw_rsvd_page(_adapter *adapter, u8 *pframe, u16 *index,
struct mlme_ext_info *pmlmeinfo = NULL;
struct mlme_ext_priv *pmlmeext = NULL;
struct hal_com_data *hal = GET_HAL_DATA(adapter);
struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
struct mcc_adapter_priv *mccadapriv = NULL;
#if defined(CONFIG_RTL8822C)
struct dm_struct *phydm = adapter_to_phydm(adapter);
struct txagc_table_8822c tab;
u8 agc_buff[2][NUM_RATE_AC_2SS]; /* tatol 0x40 rate index for PATH A/B */
#endif
u8 ret = _SUCCESS, i = 0, j =0, order = 0, CurtPktPageNum = 0;
u8 *start = NULL;
u8 path = RF_PATH_A;
@ -1347,7 +1355,8 @@ u8 rtw_hal_dl_mcc_fw_rsvd_page(_adapter *adapter, u8 *pframe, u16 *index,
}
for (i = 0; i < MAX_MCC_NUM; i++) {
u8 center_ch = 0, band, ch = 0, bw = 0, bw_offset = 0;
u8 center_ch = 0, ch = 0, bw = 0, bw_offset = 0;
BAND_TYPE band = BAND_MAX;
u8 power_index = 0;
u8 rate_array_sz = 0;
u8 *rates = NULL;
@ -1374,8 +1383,8 @@ u8 rtw_hal_dl_mcc_fw_rsvd_page(_adapter *adapter, u8 *pframe, u16 *index,
i, pmccobjpriv->mcc_pwr_idx_rsvd_page[i]);
total_rate_offset = start;
for (path = RF_PATH_A; path < hal->NumTotalRFPath; ++path) {
#if !defined(CONFIG_RTL8822C)
for (path = RF_PATH_A; path < hal_spec->rf_reg_path_num; ++path) {
total_rate = 0;
/* PATH A for 0~63 byte, PATH B for 64~127 byte*/
if (path == RF_PATH_A)
@ -1393,7 +1402,7 @@ u8 rtw_hal_dl_mcc_fw_rsvd_page(_adapter *adapter, u8 *pframe, u16 *index,
rates = rates_by_sections[CCK].rates;
for (j = 0; j < rate_array_sz; ++j) {
power_index = phy_get_tx_power_index_ex(iface, path, CCK, rates[j], bw, band, center_ch, ch);
rate = PHY_GetRateIndexOfTxPowerByRate(rates[j]);
rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
shift = rate % 4;
if (shift == 0) {
@ -1435,7 +1444,7 @@ u8 rtw_hal_dl_mcc_fw_rsvd_page(_adapter *adapter, u8 *pframe, u16 *index,
rates = rates_by_sections[OFDM].rates;
for (j = 0; j < rate_array_sz; ++j) {
power_index = phy_get_tx_power_index_ex(iface, path, OFDM, rates[j], bw, band, center_ch, ch);
rate = PHY_GetRateIndexOfTxPowerByRate(rates[j]);
rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
shift = rate % 4;
if (shift == 0) {
@ -1475,7 +1484,7 @@ u8 rtw_hal_dl_mcc_fw_rsvd_page(_adapter *adapter, u8 *pframe, u16 *index,
rates = rates_by_sections[HT_MCS0_MCS7].rates;
for (j = 0; j < rate_array_sz; ++j) {
power_index = phy_get_tx_power_index_ex(iface, path, HT_1SS, rates[j], bw, band, center_ch, ch);
rate = PHY_GetRateIndexOfTxPowerByRate(rates[j]);
rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
shift = rate % 4;
if (shift == 0) {
@ -1515,7 +1524,7 @@ u8 rtw_hal_dl_mcc_fw_rsvd_page(_adapter *adapter, u8 *pframe, u16 *index,
rates = rates_by_sections[HT_MCS8_MCS15].rates;
for (j = 0; j < rate_array_sz; ++j) {
power_index = phy_get_tx_power_index_ex(iface, path, HT_2SS, rates[j], bw, band, center_ch, ch);
rate = PHY_GetRateIndexOfTxPowerByRate(rates[j]);
rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
shift = rate % 4;
if (shift == 0) {
@ -1554,7 +1563,7 @@ u8 rtw_hal_dl_mcc_fw_rsvd_page(_adapter *adapter, u8 *pframe, u16 *index,
rates = rates_by_sections[VHT_1SSMCS0_1SSMCS9].rates;
for (j = 0; j < rate_array_sz; ++j) {
power_index = phy_get_tx_power_index_ex(iface, path, VHT_1SS, rates[j], bw, band, center_ch, ch);
rate = PHY_GetRateIndexOfTxPowerByRate(rates[j]);
rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
shift = rate % 4;
if (shift == 0) {
@ -1590,7 +1599,7 @@ u8 rtw_hal_dl_mcc_fw_rsvd_page(_adapter *adapter, u8 *pframe, u16 *index,
rates = rates_by_sections[VHT_2SSMCS0_2SSMCS9].rates;
for (j = 0; j < rate_array_sz; ++j) {
power_index = phy_get_tx_power_index_ex(iface, path, VHT_2SS, rates[j], bw, band, center_ch, ch);
rate = PHY_GetRateIndexOfTxPowerByRate(rates[j]);
rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
shift = rate % 4;
if (shift == 0) {
@ -1636,6 +1645,91 @@ u8 rtw_hal_dl_mcc_fw_rsvd_page(_adapter *adapter, u8 *pframe, u16 *index,
*total_page_num += CurtPktPageNum;
*index += (CurtPktPageNum * page_size);
RSVD_PAGE_CFG("mcc_pwr_idx_rsvd_page", CurtPktPageNum, *total_page_num, *index);
#else /* 8822C */
for (path = RF_PATH_A; path < hal_spec->rf_reg_path_num; ++path) {
/* CCK */
if (ch <= 14) {
rate_array_sz = rates_by_sections[CCK].rate_num;
rates = rates_by_sections[CCK].rates;
for (j = 0; j < rate_array_sz; ++j) {
power_index = phy_get_tx_power_index_ex(iface, path, CCK, rates[j], bw, band, center_ch, ch);
rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
agc_buff[path][rate] = power_index;
}
}
/* OFDM */
rate_array_sz = rates_by_sections[OFDM].rate_num;
rates = rates_by_sections[OFDM].rates;
for (j = 0; j < rate_array_sz; ++j) {
power_index = phy_get_tx_power_index_ex(iface, path, OFDM, rates[j], bw, band, center_ch, ch);
rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
agc_buff[path][rate] = power_index;
}
/* HT */
rate_array_sz = rates_by_sections[HT_MCS0_MCS7].rate_num;
rates = rates_by_sections[HT_MCS0_MCS7].rates;
for (j = 0; j < rate_array_sz; ++j) {
power_index = phy_get_tx_power_index_ex(iface, path, HT_1SS, rates[j], bw, band, center_ch, ch);
rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
agc_buff[path][rate] = power_index;
}
rate_array_sz = rates_by_sections[HT_MCS8_MCS15].rate_num;
rates = rates_by_sections[HT_MCS8_MCS15].rates;
for (j = 0; j < rate_array_sz; ++j) {
power_index = phy_get_tx_power_index_ex(iface, path, HT_2SS, rates[j], bw, band, center_ch, ch);
rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
agc_buff[path][rate] = power_index;
}
/* VHT */
rate_array_sz = rates_by_sections[VHT_1SSMCS0_1SSMCS9].rate_num;
rates = rates_by_sections[VHT_1SSMCS0_1SSMCS9].rates;
for (j = 0; j < rate_array_sz; ++j) {
power_index = phy_get_tx_power_index_ex(iface, path, VHT_1SS, rates[j], bw, band, center_ch, ch);
rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
agc_buff[path][rate] = power_index;
}
rate_array_sz = rates_by_sections[VHT_2SSMCS0_2SSMCS9].rate_num;
rates = rates_by_sections[VHT_2SSMCS0_2SSMCS9].rates;
for (j = 0; j < rate_array_sz; ++j) {
power_index = phy_get_tx_power_index_ex(iface, path, VHT_2SS, rates[j], bw, band, center_ch, ch);
rate = phy_get_rate_idx_of_txpwr_by_rate(rates[j]);
agc_buff[path][rate] = power_index;
}
}
phydm_get_txagc_ref_and_diff_8822c(phydm, agc_buff, NUM_RATE_AC_2SS, &tab);
*start = tab.ref_pow_cck[0];
start++;
*start = tab.ref_pow_cck[1];
start++;
*start = tab.ref_pow_ofdm[0];
start++;
*start = tab.ref_pow_ofdm[1];
start++;
_rtw_memcpy(start, tab.diff_t, sizeof(tab.diff_t));
CurtPktPageNum = 1;
*total_page_num += CurtPktPageNum;
*index += (CurtPktPageNum * page_size);
RSVD_PAGE_CFG("mcc_pwr_idx_rsvd_page", CurtPktPageNum, *total_page_num, *index);
#ifdef DBG_PWR_IDX_RSVD_PAGE
if (1) {
u8 path_idx;
for (path_idx = 0; path_idx < 2; path_idx++) {
for (j = 0; j < NUM_RATE_AC_2SS; j++)
RTW_INFO("agc_buff[%d][%d]=%x\n", i, j, agc_buff[i][j]);
}
RTW_INFO("tab->ref_pow_cck[0]=%x\n", tab.ref_pow_cck[0]);
RTW_INFO("tab->ref_pow_cck[1]=%x\n", tab.ref_pow_cck[1]);
RTW_INFO("tab->ref_pow_ofdm[0]=%x\n", tab.ref_pow_ofdm[0]);
RTW_INFO("tab->ref_pow_ofdm[1]=%x\n", tab.ref_pow_ofdm[1]);
RTW_INFO_DUMP("diff_t ", tab.diff_t, NUM_RATE_AC_2SS);
RTW_INFO_DUMP("tab ", (u8 *)&tab, sizeof(tab));
}
#endif
#endif
}
exit:
@ -1660,6 +1754,7 @@ static void rtw_hal_set_fw_mcc_rsvd_page(PADAPTER padapter)
rtw_hal_set_hwreg(port0_iface, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
#ifdef CONFIG_AP_MODE
/* Re-Download beacon */
for (i = 0; i < MAX_MCC_NUM; i++) {
iface = pmccobjpriv->iface[i];
@ -1673,18 +1768,19 @@ static void rtw_hal_set_fw_mcc_rsvd_page(PADAPTER padapter)
tx_beacon_hdl(iface, NULL);
}
}
#endif
}
static void rtw_hal_set_mcc_rsvdpage_cmd(_adapter *padapter)
{
u8 cmd[H2C_MCC_LOCATION_LEN] = {0}, i = 0, order = 0;
_adapter *iface = NULL;
PHAL_DATA_TYPE hal = GET_HAL_DATA(padapter);
struct hal_spec_t *hal_spec = GET_HAL_SPEC(padapter);
struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv);
SET_H2CCMD_MCC_PWRIDX_OFFLOAD_EN(cmd, _TRUE);
SET_H2CCMD_MCC_PWRIDX_OFFLOAD_RFNUM(cmd, hal->NumTotalRFPath);
SET_H2CCMD_MCC_PWRIDX_OFFLOAD_RFNUM(cmd, hal_spec->rf_reg_path_num);
for (order = 0; order < MAX_MCC_NUM; order++) {
iface = pmccobjpriv->iface[i];
@ -1787,7 +1883,7 @@ static void rtw_hal_set_mcc_IQK_offload_cmd(PADAPTER padapter)
_adapter *iface = NULL;
u8 cmd[H2C_MCC_IQK_PARAM_LEN] = {0}, bready = 0, i = 0, order = 0;
u16 TX_X = 0, TX_Y = 0, RX_X = 0, RX_Y = 0;
u8 total_rf_path = GET_HAL_DATA(padapter)->NumTotalRFPath;
u8 total_rf_path = GET_HAL_SPEC(padapter)->rf_reg_path_num;
u8 rf_path_idx = 0, last_order = MAX_MCC_NUM - 1, last_rf_path_index = total_rf_path - 1;
/* by order, last order & last_rf_path_index must set ready bit = 1 */
@ -2214,6 +2310,15 @@ static void rtw_hal_mcc_start_prehdl(PADAPTER padapter)
mccadapriv = &iface->mcc_adapterpriv;
mccadapriv->role = MCC_ROLE_MAX;
}
#ifdef CONFIG_RTL8822C
if (IS_HARDWARE_TYPE_8822C(padapter)) {
HAL_DATA_TYPE *hal = GET_HAL_DATA(padapter);
struct dm_struct *dm = &hal->odmpriv;
odm_cmn_info_update(dm, ODM_CMNINFO_IS_DOWNLOAD_FW, hal->bFWReady);
}
#endif
}
static u8 rtw_hal_set_mcc_start_setting(PADAPTER padapter, u8 status)
@ -2379,6 +2484,15 @@ static void rtw_hal_mcc_stop_posthdl(PADAPTER padapter)
#ifdef CONFIG_MCC_PHYDM_OFFLOAD
rtw_hal_mcc_cfg_phydm(padapter, MCC_CFG_PHYDM_STOP, NULL);
#endif
#ifdef CONFIG_RTL8822C
if (IS_HARDWARE_TYPE_8822C(padapter)) {
HAL_DATA_TYPE *hal = GET_HAL_DATA(padapter);
struct dm_struct *dm = &hal->odmpriv;
odm_cmn_info_update(dm, ODM_CMNINFO_IS_DOWNLOAD_FW, _FALSE);
}
#endif
}
static void rtw_hal_mcc_start_posthdl(PADAPTER padapter)
@ -2430,7 +2544,7 @@ static u8 rtw_hal_set_mcc_setting(PADAPTER padapter, u8 status)
u8 ret = _FAIL;
struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
u8 stop = (status < MCC_SETCMD_STATUS_START_CONNECT) ? _TRUE : _FALSE;
u32 start_time = rtw_get_current_time();
systime start_time = rtw_get_current_time();
RTW_INFO("===> "FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
@ -2644,14 +2758,17 @@ static void rtw_hal_mcc_update_noa_start_time_hdl(PADAPTER padapter, u8 buflen,
static u8 mcc_get_reg_hdl(PADAPTER adapter, const u8 *val)
{
struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
struct mcc_obj_priv *mccobjpriv = &(dvobj->mcc_objpriv);
struct hal_com_data *hal = GET_HAL_DATA(adapter);
_adapter *cur_iface = NULL;
u8 ret = _SUCCESS;
u8 cur_order = 0;
#ifdef CONFIG_RTL8822C
u16 dbg_reg[DBG_MCC_REG_NUM] = {0x4d4,0x522,0x1d70};
#else
u16 dbg_reg[DBG_MCC_REG_NUM] = {0x4d4,0x522,0xc50,0xe50};
#endif
u16 dbg_rf_reg[DBG_MCC_RF_REG_NUM] = {0x18};
u8 i;
u32 reg_val;
@ -2673,7 +2790,7 @@ static u8 mcc_get_reg_hdl(PADAPTER adapter, const u8 *val)
goto exit;
}
path_nums = hal->NumTotalRFPath;
path_nums = hal_spec->rf_reg_path_num;
if (cur_order == 0xff)
cur_iface = adapter;
else
@ -2749,7 +2866,7 @@ static u8 mcc_get_reg_cmd(_adapter *adapter, u8 cur_order)
_rtw_memcpy(mcc_cur_order, &cur_order, 1);
init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
exit:
@ -3284,14 +3401,34 @@ u8 rtw_hal_set_mcc_setting_start_bss_network(PADAPTER padapter, u8 chbw_allow)
if (MCC_EN(padapter)) {
/* channel bw offset can not be allowed, start MCC */
if (chbw_allow == _FALSE) {
struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
rtw_hal_mcc_restore_iqk_val(padapter);
_enter_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
ret = rtw_hal_set_mcc_setting(padapter, MCC_SETCMD_STATUS_START_CONNECT);
_exit_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
//rtw_hal_mcc_restore_iqk_val(padapter);
_enter_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
ret = rtw_hal_set_mcc_setting(padapter, MCC_SETCMD_STATUS_START_CONNECT);
_exit_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
if (ret == _FAIL) { /* MCC Start fail, AP/GO switch to buddy's channel */
u8 ch_to_set = 0, bw_to_set, offset_to_set;
rtw_hal_set_mcc_status(padapter, MCC_STATUS_NEED_MCC | MCC_STATUS_DOING_MCC);
rtw_hal_set_mcc_setting_disconnect(padapter);
if (rtw_mi_get_ch_setting_union_no_self(
padapter, &ch_to_set, &bw_to_set,
&offset_to_set) != 0) {
PHAL_DATA_TYPE hal = GET_HAL_DATA(padapter);
u8 doiqk = _TRUE;
rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, &doiqk);
hal->current_channel = 0;
hal->current_channel_bw = CHANNEL_WIDTH_MAX;
set_channel_bwmode(padapter, ch_to_set, offset_to_set, bw_to_set);
doiqk = _FALSE;
rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, &doiqk);
}
}
}
}
return ret;
}
@ -3361,9 +3498,17 @@ u8 rtw_hal_set_mcc_setting_join_done_chk_ch(PADAPTER padapter)
_enter_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
ret = rtw_hal_set_mcc_setting(padapter, MCC_SETCMD_STATUS_START_CONNECT);
_exit_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
if (ret == _FAIL) { /* MCC Start Fail, then disconenct client join */
rtw_hal_set_mcc_status(padapter, MCC_STATUS_NEED_MCC | MCC_STATUS_DOING_MCC);
rtw_disassoc_cmd(padapter, 0, RTW_CMDF_DIRECTLY);
rtw_indicate_disconnect(padapter, 0, _FALSE);
rtw_free_assoc_resources(padapter, _TRUE);
rtw_free_network_queue(padapter, _TRUE);
}
}
}
}
}
return ret;
}
@ -3423,7 +3568,7 @@ static void rtw_hal_mcc_dump_noa_content(void *sel, PADAPTER padapter)
static void mcc_dump_dbg_reg(void *sel, _adapter *adapter)
{
struct mcc_obj_priv *mccobjpriv = adapter_to_mccobjpriv(adapter);
HAL_DATA_TYPE *hal = GET_HAL_DATA(adapter);
struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
u8 i,j;
_irqL irqL;
@ -3436,7 +3581,7 @@ static void mcc_dump_dbg_reg(void *sel, _adapter *adapter)
RTW_PRINT_SEL(sel, "REG_0x%X:0x%08x\n", mccobjpriv->dbg_reg[i], mccobjpriv->dbg_reg_val[i]);
for (i = 0; i < ARRAY_SIZE(mccobjpriv->dbg_rf_reg); i++) {
for (j = 0; j < hal->NumTotalRFPath; j++)
for (j = 0; j < hal_spec->rf_reg_path_num; j++)
RTW_PRINT_SEL(sel, "RF_PATH_%d_REG_0x%X:0x%08x\n",
j, mccobjpriv->dbg_rf_reg[i], mccobjpriv->dbg_rf_reg_val[i][j]);
}
@ -3826,7 +3971,7 @@ u8 rtw_set_mcc_duration_cmd(_adapter *adapter, u8 type, u8 val)
_rtw_memcpy(buf, &type, 1);
_rtw_memcpy(buf + 1, &val, 1);
init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
exit:
@ -3892,7 +4037,7 @@ u8 rtw_set_mcc_phydm_offload_enable_cmd(_adapter *adapter, u8 enable, u8 enqueue
pdrvextra_cmd_parm->pbuf = mcc_phydm_offload_enable;
_rtw_memcpy(mcc_phydm_offload_enable, &enable, 1);
init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
} else {
mcc_phydm_offload_enable_hdl(adapter, &enable);

View File

@ -180,7 +180,7 @@ void hal_mpt_CCKTxPowerAdjust(PADAPTER Adapter, BOOLEAN bInCH14)
} else if (IS_HARDWARE_TYPE_8723D(Adapter)) {
/* 2.4G CCK TX DFIR */
/* 2016.01.20 Suggest from RS BB mingzhi*/
if (u1Channel == 14) {
if ((u1Channel == 14)) {
phy_set_bb_reg(Adapter, rCCK0_TxFilter2, bMaskDWord, 0x0000B81C);
phy_set_bb_reg(Adapter, rCCK0_DebugPort, bMaskDWord, 0x00000000);
phy_set_bb_reg(Adapter, 0xAAC, bMaskDWord, 0x00003667);
@ -434,12 +434,16 @@ mpt_SetTxPower(
u8 path = 0 , i = 0, MaxRate = MGN_6M;
u8 StartPath = RF_PATH_A, EndPath = RF_PATH_B;
u8 tx_nss = 2;
if (IS_HARDWARE_TYPE_8814A(pAdapter) || IS_HARDWARE_TYPE_8814B(pAdapter))
if (IS_HARDWARE_TYPE_8814A(pAdapter) || IS_HARDWARE_TYPE_8814B(pAdapter)) {
EndPath = RF_PATH_D;
else if (IS_HARDWARE_TYPE_8188F(pAdapter) || IS_HARDWARE_TYPE_8188GTV(pAdapter)
|| IS_HARDWARE_TYPE_8723D(pAdapter) || IS_HARDWARE_TYPE_8821C(pAdapter))
tx_nss = 4;
} else if (IS_HARDWARE_TYPE_8188F(pAdapter) || IS_HARDWARE_TYPE_8188GTV(pAdapter)
|| IS_HARDWARE_TYPE_8723D(pAdapter) || IS_HARDWARE_TYPE_8821C(pAdapter) || IS_HARDWARE_TYPE_8723F(pAdapter)) {
EndPath = RF_PATH_A;
tx_nss = 1;
}
switch (Rate) {
case MPT_CCK: {
@ -471,12 +475,15 @@ mpt_SetTxPower(
MGN_MCS25, MGN_MCS26, MGN_MCS27, MGN_MCS28, MGN_MCS29,
MGN_MCS30, MGN_MCS31,
};
if (pHalData->rf_type == RF_3T3R)
if (tx_nss == 4)
MaxRate = MGN_MCS31;
else if (tx_nss == 3)
MaxRate = MGN_MCS23;
else if (pHalData->rf_type == RF_2T2R)
else if (tx_nss == 2)
MaxRate = MGN_MCS15;
else
MaxRate = MGN_MCS7;
for (path = StartPath; path <= EndPath; path++) {
for (i = 0; i < sizeof(rate); ++i) {
if (rate[i] > MaxRate)
@ -497,9 +504,11 @@ mpt_SetTxPower(
MGN_VHT4SS_MCS0, MGN_VHT4SS_MCS1, MGN_VHT4SS_MCS2, MGN_VHT4SS_MCS3, MGN_VHT4SS_MCS4,
MGN_VHT4SS_MCS5, MGN_VHT4SS_MCS6, MGN_VHT4SS_MCS7, MGN_VHT4SS_MCS8, MGN_VHT4SS_MCS9,
};
if (pHalData->rf_type == RF_3T3R)
if (tx_nss == 4)
MaxRate = MGN_VHT4SS_MCS9;
else if (tx_nss == 3)
MaxRate = MGN_VHT3SS_MCS9;
else if (pHalData->rf_type == RF_2T2R || pHalData->rf_type == RF_2T4R)
else if (tx_nss == 2)
MaxRate = MGN_VHT2SS_MCS9;
else
MaxRate = MGN_VHT1SS_MCS9;
@ -856,7 +865,8 @@ void mpt_SetRFPath_8814A(PADAPTER pAdapter)
}
#endif /* CONFIG_RTL8814A */
#if defined(CONFIG_RTL8814A) || defined(CONFIG_RTL8822B) || defined(CONFIG_RTL8821C) || defined(CONFIG_RTL8822C) || defined(CONFIG_RTL8814B)
#if defined(CONFIG_RTL8814A) || defined(CONFIG_RTL8822B) || defined(CONFIG_RTL8821C) \
|| defined(CONFIG_RTL8822C) || defined(CONFIG_RTL8814B) || defined(CONFIG_RTL8723F)
void
mpt_SetSingleTone_8814A(
PADAPTER pAdapter,
@ -952,7 +962,7 @@ mpt_SetSingleTone_8814A(
phy_set_bb_reg(pAdapter, rCCAonSec_Jaguar, BIT1, 0x0); /* Enable CCA*/
if (bEnPMacTx == FALSE) {
if(IS_HARDWARE_TYPE_JAGUAR3(pAdapter)) {
if (IS_HARDWARE_TYPE_JAGUAR3(pAdapter) || IS_HARDWARE_TYPE_JAGUAR3_11N(pAdapter)) {
#ifdef PHYDM_MP_SUPPORT
phydm_stop_ofdm_cont_tx(pAdapter);
pMptCtx->bCckContTx = FALSE;
@ -1506,9 +1516,68 @@ void mpt_set_rfpath_8192f(PADAPTER pAdapter)
#endif
void hal_mpt_SetAntenna(PADAPTER pAdapter)
{
RTW_INFO("Do %s\n", __func__);
PHAL_DATA_TYPE hal;
ANTENNA_PATH anttx;
enum bb_path bb_tx = 0;
hal = GET_HAL_DATA(pAdapter);
anttx = hal->antenna_tx_path;
switch (anttx) {
case ANTENNA_A:
bb_tx = BB_PATH_A;
break;
case ANTENNA_B:
bb_tx = BB_PATH_B;
break;
case ANTENNA_C:
bb_tx = BB_PATH_C;
break;
case ANTENNA_D:
bb_tx = BB_PATH_D;
break;
case ANTENNA_AB:
bb_tx = BB_PATH_AB;
break;
case ANTENNA_AC:
bb_tx = BB_PATH_AC;
break;
case ANTENNA_AD:
bb_tx = BB_PATH_AD;
break;
case ANTENNA_BC:
bb_tx = BB_PATH_BC;
break;
case ANTENNA_BD:
bb_tx = BB_PATH_BD;
break;
case ANTENNA_CD:
bb_tx = BB_PATH_CD;
break;
case ANTENNA_ABC:
bb_tx = BB_PATH_ABC;
break;
case ANTENNA_BCD:
bb_tx = BB_PATH_BCD;
break;
case ANTENNA_ABD:
bb_tx = BB_PATH_ABD;
break;
case ANTENNA_ACD:
bb_tx = BB_PATH_ACD;
break;
case ANTENNA_ABCD:
bb_tx = BB_PATH_ABCD;
break;
default:
bb_tx = BB_PATH_A;
break;
}
tx_path_nss_set_full_tx(hal->txpath_nss, hal->txpath_num_nss, bb_tx);
RTW_INFO("%s ,ant idx %d, tx path_num_nss = %d\n", __func__, anttx, hal->txpath_num_nss[0]);
#ifdef CONFIG_RTL8822C
if (IS_HARDWARE_TYPE_8822C(pAdapter)) {
rtl8822c_mp_config_rfpath(pAdapter);
@ -1607,7 +1676,7 @@ s32 hal_mpt_SetThermalMeter(PADAPTER pAdapter, u8 target_ther)
void hal_mpt_TriggerRFThermalMeter(PADAPTER pAdapter)
{
if (IS_HARDWARE_TYPE_JAGUAR3(pAdapter)) {
if (IS_HARDWARE_TYPE_JAGUAR3(pAdapter) || IS_HARDWARE_TYPE_JAGUAR3_11N(pAdapter)) {
phy_set_rf_reg(pAdapter, RF_PATH_A, 0x42, BIT19, 0x1);
phy_set_rf_reg(pAdapter, RF_PATH_A, 0x42, BIT19, 0x0);
phy_set_rf_reg(pAdapter, RF_PATH_A, 0x42, BIT19, 0x1);
@ -1684,8 +1753,9 @@ void hal_mpt_SetSingleCarrierTx(PADAPTER pAdapter, u8 bStart)
phy_set_bb_reg(pAdapter, rCCK0_System, bCCKScramble, 1);
/*/ 4. Turn On Continue Tx and turn off the other test modes.*/
#if defined(CONFIG_RTL8812A) || defined(CONFIG_RTL8821A) || defined(CONFIG_RTL8814A) || defined(CONFIG_RTL8822B) || defined(CONFIG_RTL8821C)
if (IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter))
#if defined(CONFIG_RTL8812A) || defined(CONFIG_RTL8821A) || defined(CONFIG_RTL8814A)\
|| defined(CONFIG_RTL8822B) || defined(CONFIG_RTL8821C) || defined(CONFIG_RTL8723F)
if (IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter) || IS_HARDWARE_TYPE_JAGUAR3_11N(pAdapter))
phy_set_bb_reg(pAdapter, rSingleTone_ContTx_Jaguar, BIT18 | BIT17 | BIT16, OFDM_SingleCarrier);
else
#endif /* CONFIG_RTL8812A || CONFIG_RTL8821A || CONFIG_RTL8814A || CONFIG_RTL8822B || CONFIG_RTL8821C */
@ -1695,8 +1765,9 @@ void hal_mpt_SetSingleCarrierTx(PADAPTER pAdapter, u8 bStart)
/*/ Stop Single Carrier.*/
/*/ Stop Single Carrier.*/
/*/ Turn off all test modes.*/
#if defined(CONFIG_RTL8812A) || defined(CONFIG_RTL8821A) || defined(CONFIG_RTL8814A) || defined(CONFIG_RTL8822B) || defined(CONFIG_RTL8821C)
if (IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter))
#if defined(CONFIG_RTL8812A) || defined(CONFIG_RTL8821A) || defined(CONFIG_RTL8814A) || defined(CONFIG_RTL8822B)\
|| defined(CONFIG_RTL8821C) || defined(CONFIG_RTL8723F)
if (IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter)|| IS_HARDWARE_TYPE_JAGUAR3_11N(pAdapter))
phy_set_bb_reg(pAdapter, rSingleTone_ContTx_Jaguar, BIT18 | BIT17 | BIT16, OFDM_ALL_OFF);
else
#endif /* CONFIG_RTL8812A || CONFIG_RTL8821A || CONFIG_RTL8814A || CONFIG_RTL8822B || CONFIG_RTL8821C */
@ -1719,7 +1790,7 @@ void hal_mpt_SetSingleToneTx(PADAPTER pAdapter, u8 bStart)
static u32 regRF = 0, regBB0 = 0, regBB1 = 0, regBB2 = 0, regBB3 = 0;
u8 rfPath;
if (IS_HARDWARE_TYPE_JAGUAR3(pAdapter)) {
if (IS_HARDWARE_TYPE_JAGUAR3(pAdapter) || IS_HARDWARE_TYPE_JAGUAR3_11N(pAdapter)) {
#ifdef PHYDM_MP_SUPPORT
#ifdef CONFIG_RTL8814B
if(pHalData->current_channel_bw == CHANNEL_WIDTH_80_80)
@ -1989,7 +2060,7 @@ void hal_mpt_SetCarrierSuppressionTx(PADAPTER pAdapter, u8 bStart)
pAdapter->mppriv.mpt_ctx.is_carrier_suppression = bStart;
if (IS_HARDWARE_TYPE_JAGUAR3(pAdapter)) {
if (IS_HARDWARE_TYPE_JAGUAR3(pAdapter) || IS_HARDWARE_TYPE_JAGUAR3_11N(pAdapter)) {
#ifdef PHYDM_MP_SUPPORT
phydm_mp_set_carrier_supp(pdm_odm, bStart, pAdapter->mppriv.rateidx);
#endif
@ -2004,7 +2075,7 @@ void hal_mpt_SetCarrierSuppressionTx(PADAPTER pAdapter, u8 bStart)
write_bbreg(pAdapter, rFPGA0_RFMOD, bCCKEn, bEnable);/*set CCK block on*/
/*/Turn Off All Test Mode*/
if (IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter))
if (IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter) || IS_HARDWARE_TYPE_JAGUAR3_11N(pAdapter))
phy_set_bb_reg(pAdapter, 0x914, BIT18 | BIT17 | BIT16, OFDM_ALL_OFF); /* rSingleTone_ContTx_Jaguar*/
else
phy_set_bb_reg(pAdapter, rOFDM1_LSTF, BIT30 | BIT29 | BIT28, OFDM_ALL_OFF);
@ -2048,7 +2119,7 @@ u32 hal_mpt_query_phytxok(PADAPTER pAdapter)
struct dm_struct *dm = (struct dm_struct *)&pHalData->odmpriv;
struct phydm_mp *mp = &dm->dm_mp_table;
if (IS_HARDWARE_TYPE_JAGUAR3(pAdapter)) {
if (IS_HARDWARE_TYPE_JAGUAR3(pAdapter) || IS_HARDWARE_TYPE_JAGUAR3_11N(pAdapter)) {
phydm_mp_get_tx_ok(&pHalData->odmpriv, pAdapter->mppriv.rateidx);
count = mp->tx_phy_ok_cnt;
@ -2086,7 +2157,7 @@ static void mpt_StopCckContTx(
phy_set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, 0x0); /*normal mode*/
phy_set_bb_reg(pAdapter, rCCK0_System, bCCKScramble, 0x1); /*turn on scramble setting*/
if (!IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter)) {
if (!IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter) && !IS_HARDWARE_TYPE_JAGUAR3_11N(pAdapter)) {
phy_set_bb_reg(pAdapter, 0xa14, 0x300, 0x0); /* 0xa15[1:0] = 2b00*/
phy_set_bb_reg(pAdapter, rOFDM0_TRMuxPar, 0x10000, 0x0); /* 0xc08[16] = 0*/
@ -2099,9 +2170,11 @@ static void mpt_StopCckContTx(
phy_set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x0);
phy_set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x1);
if (!IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter)) {
phy_set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100);
phy_set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100);
if (!IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter) && !IS_HARDWARE_TYPE_JAGUAR3_11N(pAdapter)
&& !IS_HARDWARE_TYPE_8723D(pAdapter) && !IS_HARDWARE_TYPE_8192F(pAdapter)
&& !IS_HARDWARE_TYPE_8188F(pAdapter)) {
phy_set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100);
phy_set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100);
}
if (IS_HARDWARE_TYPE_8188E(pAdapter) || IS_HARDWARE_TYPE_8723B(pAdapter) ||
@ -2126,14 +2199,14 @@ static void mpt_StopOfdmContTx(
pMptCtx->bCckContTx = FALSE;
pMptCtx->bOfdmContTx = FALSE;
if (IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter))
if (IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter) || IS_HARDWARE_TYPE_JAGUAR3_11N(pAdapter))
phy_set_bb_reg(pAdapter, 0x914, BIT18 | BIT17 | BIT16, OFDM_ALL_OFF);
else
phy_set_bb_reg(pAdapter, rOFDM1_LSTF, BIT30 | BIT29 | BIT28, OFDM_ALL_OFF);
rtw_mdelay_os(10);
if (!IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter)){
if (!IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter) && !IS_HARDWARE_TYPE_JAGUAR3_11N(pAdapter)){
phy_set_bb_reg(pAdapter, 0xa14, 0x300, 0x0); /* 0xa15[1:0] = 0*/
phy_set_bb_reg(pAdapter, rOFDM0_TRMuxPar, 0x10000, 0x0); /* 0xc08[16] = 0*/
}
@ -2142,9 +2215,11 @@ static void mpt_StopOfdmContTx(
phy_set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x0);
phy_set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x1);
if (!IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter)) {
phy_set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100);
phy_set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100);
if (!IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter) && !IS_HARDWARE_TYPE_JAGUAR3_11N(pAdapter)
&& !IS_HARDWARE_TYPE_8723D(pAdapter) && !IS_HARDWARE_TYPE_8192F(pAdapter)
&& !IS_HARDWARE_TYPE_8188F(pAdapter)) {
phy_set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000100);
phy_set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000100);
}
} /* mpt_StopOfdmContTx */
@ -2162,7 +2237,7 @@ static void mpt_StartCckContTx(
phy_set_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn, 1);/*set CCK block on*/
/*Turn Off All Test Mode*/
if (IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter))
if (IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter) || IS_HARDWARE_TYPE_JAGUAR3_11N(pAdapter))
phy_set_bb_reg(pAdapter, 0x914, BIT18 | BIT17 | BIT16, OFDM_ALL_OFF);
else
phy_set_bb_reg(pAdapter, rOFDM1_LSTF, BIT30 | BIT29 | BIT28, OFDM_ALL_OFF);
@ -2174,7 +2249,7 @@ static void mpt_StartCckContTx(
phy_set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, 0x2); /*transmit mode*/
phy_set_bb_reg(pAdapter, rCCK0_System, bCCKScramble, 0x1); /*turn on scramble setting*/
if (!IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter)) {
if (!IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter) && !IS_HARDWARE_TYPE_JAGUAR3_11N(pAdapter)) {
phy_set_bb_reg(pAdapter, 0xa14, 0x300, 0x3); /* 0xa15[1:0] = 11 force cck rxiq = 0*/
phy_set_bb_reg(pAdapter, rOFDM0_TRMuxPar, 0x10000, 0x1); /* 0xc08[16] = 1 force ofdm rxiq = ofdm txiq*/
phy_set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter2, BIT14, 1);
@ -2182,7 +2257,9 @@ static void mpt_StartCckContTx(
phy_set_bb_reg(pAdapter, 0x0B34, BIT14, 1);
}
if (!IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter)) {
if (!IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter) && !IS_HARDWARE_TYPE_JAGUAR3_11N(pAdapter)
&& !IS_HARDWARE_TYPE_8723D(pAdapter) && !IS_HARDWARE_TYPE_8192F(pAdapter)
&& !IS_HARDWARE_TYPE_8188F(pAdapter)) {
phy_set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000500);
phy_set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000500);
}
@ -2220,18 +2297,20 @@ static void mpt_StartOfdmContTx(
/* 3. turn on scramble setting*/
phy_set_bb_reg(pAdapter, rCCK0_System, bCCKScramble, 1);
if (!IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter)) {
if (!IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter) && !IS_HARDWARE_TYPE_JAGUAR3_11N(pAdapter)) {
phy_set_bb_reg(pAdapter, 0xa14, 0x300, 0x3); /* 0xa15[1:0] = 2b'11*/
phy_set_bb_reg(pAdapter, rOFDM0_TRMuxPar, 0x10000, 0x1); /* 0xc08[16] = 1*/
}
/* 4. Turn On Continue Tx and turn off the other test modes.*/
if (IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter))
if (IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter) || IS_HARDWARE_TYPE_JAGUAR3_11N(pAdapter))
phy_set_bb_reg(pAdapter, 0x914, BIT18 | BIT17 | BIT16, OFDM_ContinuousTx);
else
phy_set_bb_reg(pAdapter, rOFDM1_LSTF, BIT30 | BIT29 | BIT28, OFDM_ContinuousTx);
if (!IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter)) {
if (!IS_HARDWARE_TYPE_JAGUAR_ALL(pAdapter) && !IS_HARDWARE_TYPE_JAGUAR3_11N(pAdapter)
&& !IS_HARDWARE_TYPE_8723D(pAdapter) && !IS_HARDWARE_TYPE_8192F(pAdapter)
&& !IS_HARDWARE_TYPE_8188F(pAdapter)) {
phy_set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter1, bMaskDWord, 0x01000500);
phy_set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter1, bMaskDWord, 0x01000500);
}
@ -2240,45 +2319,49 @@ static void mpt_StartOfdmContTx(
pMptCtx->bOfdmContTx = TRUE;
} /* mpt_StartOfdmContTx */
#if defined(CONFIG_RTL8814A) || defined(CONFIG_RTL8821B) || defined(CONFIG_RTL8822B) || defined(CONFIG_RTL8821C) || defined(CONFIG_RTL8822C) || defined(CONFIG_RTL8814B)
#if defined(CONFIG_RTL8814A) || defined(CONFIG_RTL8821B) || defined(CONFIG_RTL8822B) \
|| defined(CONFIG_RTL8821C) || defined(CONFIG_RTL8822C) || defined(CONFIG_RTL8814B) \
|| defined(CONFIG_RTL8723F)
#ifdef PHYDM_PMAC_TX_SETTING_SUPPORT
static void mpt_convert_phydm_txinfo_for_jaguar3(
RT_PMAC_TX_INFO pMacTxInfo, struct phydm_pmac_info *phydmtxinfo)
RT_PMAC_TX_INFO *pMacTxInfo, struct phydm_pmac_info *phydmtxinfo)
{
phydmtxinfo->en_pmac_tx = pMacTxInfo.bEnPMacTx;
phydmtxinfo->mode = pMacTxInfo.Mode;
phydmtxinfo->tx_rate = MRateToHwRate(mpt_to_mgnt_rate(pMacTxInfo.TX_RATE));
phydmtxinfo->tx_sc = pMacTxInfo.TX_SC;
phydmtxinfo->is_short_preamble = pMacTxInfo.bSPreamble;
phydmtxinfo->ndp_sound = pMacTxInfo.NDP_sound;
phydmtxinfo->bw = pMacTxInfo.BandWidth;
phydmtxinfo->m_stbc = pMacTxInfo.m_STBC;
phydmtxinfo->packet_period = pMacTxInfo.PacketPeriod;
phydmtxinfo->packet_count = pMacTxInfo.PacketCount;
phydmtxinfo->packet_pattern = pMacTxInfo.PacketPattern;
phydmtxinfo->sfd = pMacTxInfo.SFD;
phydmtxinfo->signal_field = pMacTxInfo.SignalField;
phydmtxinfo->service_field = pMacTxInfo.ServiceField;
phydmtxinfo->length = pMacTxInfo.LENGTH;
_rtw_memcpy(&phydmtxinfo->crc16,pMacTxInfo.CRC16, 2);
_rtw_memcpy(&phydmtxinfo->lsig , pMacTxInfo.LSIG,3);
_rtw_memcpy(&phydmtxinfo->ht_sig , pMacTxInfo.HT_SIG,6);
_rtw_memcpy(&phydmtxinfo->vht_sig_a , pMacTxInfo.VHT_SIG_A,6);
_rtw_memcpy(&phydmtxinfo->vht_sig_b , pMacTxInfo.VHT_SIG_B,4);
phydmtxinfo->vht_sig_b_crc = pMacTxInfo.VHT_SIG_B_CRC;
_rtw_memcpy(&phydmtxinfo->vht_delimiter,pMacTxInfo.VHT_Delimiter,4);
phydmtxinfo->en_pmac_tx = pMacTxInfo->bEnPMacTx;
phydmtxinfo->mode = pMacTxInfo->Mode;
phydmtxinfo->tx_rate = MRateToHwRate(mpt_to_mgnt_rate(pMacTxInfo->TX_RATE));
phydmtxinfo->tx_sc = pMacTxInfo->TX_SC;
phydmtxinfo->is_short_preamble = pMacTxInfo->bSPreamble;
phydmtxinfo->ndp_sound = pMacTxInfo->NDP_sound;
phydmtxinfo->bw = pMacTxInfo->BandWidth;
phydmtxinfo->m_stbc = pMacTxInfo->m_STBC;
phydmtxinfo->packet_period = pMacTxInfo->PacketPeriod;
phydmtxinfo->packet_count = pMacTxInfo->PacketCount;
phydmtxinfo->packet_pattern = pMacTxInfo->PacketPattern;
phydmtxinfo->sfd = pMacTxInfo->SFD;
phydmtxinfo->signal_field = pMacTxInfo->SignalField;
phydmtxinfo->service_field = pMacTxInfo->ServiceField;
phydmtxinfo->length = pMacTxInfo->LENGTH;
_rtw_memcpy(&phydmtxinfo->crc16,pMacTxInfo->CRC16, 2);
_rtw_memcpy(&phydmtxinfo->lsig , pMacTxInfo->LSIG,3);
_rtw_memcpy(&phydmtxinfo->ht_sig , pMacTxInfo->HT_SIG,6);
_rtw_memcpy(&phydmtxinfo->vht_sig_a , pMacTxInfo->VHT_SIG_A,6);
_rtw_memcpy(&phydmtxinfo->vht_sig_b , pMacTxInfo->VHT_SIG_B,4);
phydmtxinfo->vht_sig_b_crc = pMacTxInfo->VHT_SIG_B_CRC;
_rtw_memcpy(&phydmtxinfo->vht_delimiter,pMacTxInfo->VHT_Delimiter,4);
}
#endif
/* for HW TX mode */
void mpt_ProSetPMacTx(PADAPTER Adapter)
u8 mpt_ProSetPMacTx(PADAPTER Adapter)
{
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
PMPT_CONTEXT pMptCtx = &(Adapter->mppriv.mpt_ctx);
struct mp_priv *pmppriv = &Adapter->mppriv;
struct hal_spec_t *hal_spec = GET_HAL_SPEC(Adapter);
RT_PMAC_TX_INFO PMacTxInfo = pMptCtx->PMacTxInfo;
u32 u4bTmp;
struct dm_struct *p_dm_odm;
u32 u4bTmp;
u8 status = _TRUE;
p_dm_odm = &pHalData->odmpriv;
@ -2303,14 +2386,42 @@ void mpt_ProSetPMacTx(PADAPTER Adapter)
RTW_INFO("TXSC %d BandWidth %d PacketPeriod %d PacketCount %d PacketLength %d PacketPattern %d\n", PMacTxInfo.TX_SC, PMacTxInfo.BandWidth, PMacTxInfo.PacketPeriod, PMacTxInfo.PacketCount,
PMacTxInfo.PacketLength, PMacTxInfo.PacketPattern);
if (IS_HARDWARE_TYPE_JAGUAR3(Adapter)) {
if (hal_spec->tx_nss_num < 2 && MPT_IS_2SS_RATE(PMacTxInfo.TX_RATE))
return _FALSE;
if (hal_spec->tx_nss_num < 3 && MPT_IS_3SS_RATE(PMacTxInfo.TX_RATE))
return _FALSE;
if (hal_spec->tx_nss_num < 4 && MPT_IS_4SS_RATE(PMacTxInfo.TX_RATE))
return _FALSE;
if (!is_supported_vht(Adapter->registrypriv.wireless_mode) && MPT_IS_VHT_RATE(PMacTxInfo.TX_RATE))
return _FALSE;
if (!is_supported_ht(Adapter->registrypriv.wireless_mode) && MPT_IS_HT_RATE(PMacTxInfo.TX_RATE))
return _FALSE;
if (PMacTxInfo.BandWidth == 1 && hal_chk_bw_cap(Adapter, BW_CAP_40M))
PMacTxInfo.BandWidth = CHANNEL_WIDTH_40;
else if (PMacTxInfo.BandWidth == 2 && hal_chk_bw_cap(Adapter, BW_CAP_80M))
PMacTxInfo.BandWidth = CHANNEL_WIDTH_80;
else
PMacTxInfo.BandWidth = CHANNEL_WIDTH_20;
if (IS_HARDWARE_TYPE_JAGUAR3(Adapter) || IS_HARDWARE_TYPE_JAGUAR3_11N(Adapter)) {
#ifdef PHYDM_PMAC_TX_SETTING_SUPPORT
struct phydm_pmac_info phydm_mactxinfo;
mpt_convert_phydm_txinfo_for_jaguar3(PMacTxInfo, &phydm_mactxinfo);
if (PMacTxInfo.bEnPMacTx == TRUE) {
pMptCtx->HWTxmode = PMacTxInfo.Mode;
pMptCtx->mpt_rate_index = PMacTxInfo.TX_RATE;
if (PMacTxInfo.Mode == CONTINUOUS_TX)
hal_mpt_SetTxPower(Adapter);
} else {
PMacTxInfo.Mode = pMptCtx->HWTxmode;
PMacTxInfo.TX_RATE = pMptCtx->mpt_rate_index;
pMptCtx->HWTxmode = TEST_NONE;
}
mpt_convert_phydm_txinfo_for_jaguar3(&PMacTxInfo, &phydm_mactxinfo);
phydm_set_pmac_tx(p_dm_odm, &phydm_mactxinfo, pMptCtx->mpt_rf_path);
#endif
return;
return status;
}
if (PMacTxInfo.bEnPMacTx == FALSE) {
@ -2337,7 +2448,7 @@ void mpt_ProSetPMacTx(PADAPTER Adapter)
mpt_SetSingleTone_8814A(Adapter, FALSE, TRUE);
}
pMptCtx->HWTxmode = TEST_NONE;
return;
return status;
}
pMptCtx->mpt_rate_index = PMacTxInfo.TX_RATE;
@ -2501,6 +2612,7 @@ void mpt_ProSetPMacTx(PADAPTER Adapter)
if (PMacTxInfo.Mode == OFDM_Single_Tone_TX)
mpt_SetSingleTone_8814A(Adapter, TRUE, TRUE);
return status;
}
#endif
@ -2527,4 +2639,14 @@ void hal_mpt_SetContinuousTx(PADAPTER pAdapter, u8 bStart)
}
}
void mpt_trigger_tssi_tracking(PADAPTER pAdapter, u8 rf_path)
{
#ifdef CONFIG_RTL8814B
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter);
struct dm_struct *pDM_Odm = &pHalData->odmpriv;
halrf_do_tssi_8814b(pDM_Odm, rf_path);
#endif
}
#endif /* CONFIG_MP_INCLUDE*/

View File

@ -751,6 +751,7 @@ enum halmac_ret_status
init_protocol_cfg_8822b(struct halmac_adapter *adapter)
{
u32 value32;
u8 value8;
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
@ -773,6 +774,9 @@ init_protocol_cfg_8822b(struct halmac_adapter *adapter)
HALMAC_REG_W8(REG_FAST_EDCA_BEBK_SETTING, WLAN_FAST_EDCA_BE_TH);
HALMAC_REG_W8(REG_FAST_EDCA_BEBK_SETTING + 2, WLAN_FAST_EDCA_BK_TH);
value8 = HALMAC_REG_R8(REG_INIRTS_RATE_SEL);
HALMAC_REG_W8(REG_INIRTS_RATE_SEL, value8 | BIT(5));
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
return HALMAC_RET_SUCCESS;

View File

@ -83,6 +83,10 @@ struct halmac_intf_phy_para pcie_gen1_phy_param_8822b[] = {
HALMAC_IP_INTF_PHY,
HALMAC_INTF_PHY_CUT_ALL,
HALMAC_INTF_PHY_PLATFORM_ASUS},
{0x001B, 0xF029,
HALMAC_IP_INTF_PHY,
HALMAC_INTF_PHY_CUT_ALL,
HALMAC_INTF_PHY_PLATFORM_LENOVO_V540},
{0x0020, 0x94FF,
HALMAC_IP_INTF_PHY,
HALMAC_INTF_PHY_CUT_C,

View File

@ -211,7 +211,7 @@ static struct halmac_wlan_pwr_cfg TRANS_ACT_TO_CARDEMU_8822B[] = {
HALMAC_PWR_CUT_ALL_MSK,
HALMAC_PWR_INTF_ALL_MSK,
HALMAC_PWR_ADDR_MAC,
HALMAC_PWR_CMD_WRITE, BIT(3), 0},
HALMAC_PWR_CMD_WRITE, 0xFF, 0xC4},
{0x001F,
HALMAC_PWR_CUT_ALL_MSK,
HALMAC_PWR_INTF_ALL_MSK,

View File

@ -21,7 +21,7 @@
#if HALMAC_8822B_SUPPORT
#define HALMAC_8822B_PWR_SEQ_VER "V31"
#define HALMAC_8822B_PWR_SEQ_VER "V35"
extern struct halmac_wlan_pwr_cfg *card_en_flow_8822b[];
extern struct halmac_wlan_pwr_cfg *card_dis_flow_8822b[];

View File

@ -19,6 +19,58 @@
#include "halmac_init_88xx.h"
#if HALMAC_88XX_SUPPORT
/**
* start_dpk_88xx() -trigger FW DPK
* @adapter : the adapter of halmac
* Author : Yong-Ching Lin/KaiYuan Chang/Ivan Lin
* Return : enum halmac_ret_status
* More details of status code can be found in prototype document
*/
enum halmac_ret_status
start_dpk_88xx(struct halmac_adapter *adapter)
{
u8 h2c_buf[H2C_PKT_SIZE_88XX] = { 0 };
u16 seq_num = 0;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
struct halmac_h2c_header_info hdr_info;
enum halmac_cmd_process_status *proc_status;
proc_status = &adapter->halmac_state.dpk_state.proc_status;
if (halmac_fw_validate(adapter) != HALMAC_RET_SUCCESS)
return HALMAC_RET_NO_DLFW;
if (adapter->fw_ver.h2c_version < 15)
return HALMAC_RET_FW_NO_SUPPORT;
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
if (*proc_status == HALMAC_CMD_PROCESS_SENDING) {
PLTFM_MSG_TRACE("[TRACE]Wait event(dpk)\n");
return HALMAC_RET_BUSY_STATE;
}
*proc_status = HALMAC_CMD_PROCESS_SENDING;
hdr_info.sub_cmd_id = SUB_CMD_ID_DPK;
hdr_info.content_size = 1;
hdr_info.ack = 1;
set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
adapter->halmac_state.dpk_state.seq_num = seq_num;
status = send_h2c_pkt_88xx(adapter, h2c_buf);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_MSG_ERR("[ERR]send h2c pkt fail!!\n");
reset_ofld_feature_88xx(adapter, HALMAC_FEATURE_DPK);
return status;
}
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
return HALMAC_RET_SUCCESS;
}
/**
* start_iqk_88xx() -trigger FW IQK
@ -163,6 +215,34 @@ get_iqk_status_88xx(struct halmac_adapter *adapter,
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
get_dpk_status_88xx(struct halmac_adapter *adapter,
enum halmac_cmd_process_status *proc_status, u8 *data,
u32 *size)
{
struct halmac_dpk_state *state = &adapter->halmac_state.dpk_state;
*proc_status = adapter->halmac_state.dpk_state.proc_status;
if (!data)
return HALMAC_RET_NULL_POINTER;
if (!size)
return HALMAC_RET_NULL_POINTER;
if (*proc_status == HALMAC_CMD_PROCESS_DONE) {
if (*size < state->data_size) {
*size = state->data_size;
return HALMAC_RET_BUFFER_TOO_SMALL;
}
*size = state->data_size;
PLTFM_MEMCPY(data, state->data, *size);
}
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
get_pwr_trk_status_88xx(struct halmac_adapter *adapter,
enum halmac_cmd_process_status *proc_status)
@ -300,6 +380,102 @@ get_h2c_ack_iqk_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
get_h2c_ack_dpk_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
{
u8 seq_num;
u8 fw_rc;
struct halmac_dpk_state *state = &adapter->halmac_state.dpk_state;
enum halmac_cmd_process_status proc_status;
seq_num = (u8)H2C_ACK_HDR_GET_H2C_SEQ(buf);
PLTFM_MSG_TRACE("[TRACE]Seq num : h2c->%d c2h->%d\n",
state->seq_num, seq_num);
if (seq_num != state->seq_num) {
PLTFM_MSG_ERR("[ERR]Seq num mismatch : h2c->%d c2h->%d\n",
state->seq_num, seq_num);
return HALMAC_RET_SUCCESS;
}
if (state->proc_status != HALMAC_CMD_PROCESS_SENDING) {
PLTFM_MSG_ERR("[ERR]not cmd sending\n");
return HALMAC_RET_SUCCESS;
}
fw_rc = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(buf);
state->fw_rc = fw_rc;
if ((enum halmac_h2c_return_code)fw_rc == HALMAC_H2C_RETURN_SUCCESS) {
proc_status = HALMAC_CMD_PROCESS_RCVD;
state->proc_status = proc_status;
PLTFM_EVENT_SIG(HALMAC_FEATURE_DPK, proc_status, NULL, 0);
} else {
proc_status = HALMAC_CMD_PROCESS_ERROR;
state->proc_status = proc_status;
PLTFM_EVENT_SIG(HALMAC_FEATURE_DPK, proc_status, &fw_rc, 1);
}
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
get_dpk_data_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
{
u8 seq_num;
u8 seg_id;
u8 seg_size;
u16 total_size;
enum halmac_cmd_process_status proc_status;
struct halmac_dpk_state *state = &adapter->halmac_state.dpk_state;
seq_num = (u8)DPK_DATA_GET_H2C_SEQ(buf);
PLTFM_MSG_TRACE("[TRACE]seq num : h2c->%d c2h->%d\n",
state->seq_num, seq_num);
if (seq_num != state->seq_num) {
PLTFM_MSG_ERR("[ERR]seq num mismatch : h2c->%d c2h->%d\n",
state->seq_num, seq_num);
return HALMAC_RET_SUCCESS;
}
if (state->proc_status != HALMAC_CMD_PROCESS_RCVD) {
PLTFM_MSG_ERR("[ERR]not receive dpk ack\n");
if (state->proc_status != HALMAC_CMD_PROCESS_SENDING) {
PLTFM_MSG_ERR("[ERR]not cmd sending\n");
return HALMAC_RET_SUCCESS;
}
}
total_size = (u16)DPK_DATA_GET_TOTAL_SIZE(buf);
seg_id = (u8)DPK_DATA_GET_SEGMENT_ID(buf);
seg_size = (u8)DPK_DATA_GET_SEGMENT_SIZE(buf);
state->data_size = total_size;
if (!state->data) {
state->data = (u8 *)PLTFM_MALLOC(state->data_size);
if (!state->data) {
PLTFM_MSG_ERR("[ERR]malloc fail!!\n");
return HALMAC_RET_NULL_POINTER;
}
}
if (seg_id == 0)
state->seg_size = seg_size;
PLTFM_MEMCPY(state->data + seg_id * state->seg_size,
buf + C2H_DATA_OFFSET_88XX, seg_size);
if (DPK_DATA_GET_END_SEGMENT(buf) == 0)
return HALMAC_RET_SUCCESS;
proc_status = HALMAC_CMD_PROCESS_DONE;
state->proc_status = proc_status;
PLTFM_EVENT_SIG(HALMAC_FEATURE_DPK, state->proc_status, state->data,
state->data_size);
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
get_h2c_ack_pwr_trk_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
{

View File

@ -52,6 +52,20 @@ get_h2c_ack_pwr_trk_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size);
enum halmac_ret_status
get_psd_data_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size);
enum halmac_ret_status
start_dpk_88xx(struct halmac_adapter *adapter);
enum halmac_ret_status
get_h2c_ack_dpk_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size);
enum halmac_ret_status
get_dpk_data_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size);
enum halmac_ret_status
get_dpk_status_88xx(struct halmac_adapter *adapter,
enum halmac_cmd_process_status *proc_status, u8 *data,
u32 *size);
#endif /* HALMAC_88XX_SUPPORT */
#endif/* _HALMAC_BB_RF_88XX_H_ */

View File

@ -500,7 +500,9 @@ set_hw_value_88xx(struct halmac_adapter *adapter, enum halmac_hw_id hw_id,
void *value)
{
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
struct halmac_tx_page_threshold_info *th_info = NULL;
#if HALMAC_SDIO_SUPPORT
struct halmac_tx_page_threshold_info *th_info;
#endif
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
@ -761,6 +763,9 @@ parse_c2h_pkt_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
case C2H_SUB_CMD_ID_SCAN_CH_NOTIFY:
status = get_scan_ch_notify_88xx(adapter, c2h_pkt, c2h_size);
break;
case C2H_SUB_CMD_ID_DPK_DATA:
status = get_dpk_data_88xx(adapter, c2h_pkt, c2h_size);
break;
default:
PLTFM_MSG_WARN("[WARN]Sub cmd id!!\n");
status = HALMAC_RET_C2H_NOT_HANDLED;
@ -893,6 +898,9 @@ get_h2c_ack_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
case H2C_SUB_CMD_ID_FW_SNDING_ACK:
status = get_h2c_ack_fw_snding_88xx(adapter, buf, size);
break;
case H2C_SUB_CMD_ID_DPK_ACK:
status = get_h2c_ack_dpk_88xx(adapter, buf, size);
break;
default:
status = HALMAC_RET_C2H_NOT_HANDLED;
break;
@ -2853,6 +2861,9 @@ query_status_88xx(struct halmac_adapter *adapter,
case HALMAC_FEATURE_FW_SNDING:
status = get_fw_snding_status_88xx(adapter, proc_status);
break;
case HALMAC_FEATURE_DPK:
status = get_dpk_status_88xx(adapter, proc_status, data, size);
break;
default:
return HALMAC_RET_INVALID_FEATURE_ID;
}
@ -2998,7 +3009,7 @@ pwr_seq_parser_88xx(struct halmac_adapter *adapter,
cut = HALMAC_PWR_CUT_TESTCHIP_MSK;
break;
default:
PLTFM_MSG_ERR("[ERR]cut version!!\n");
PLTFM_MSG_ERR("[ERR]chip info!!\n");
return HALMAC_RET_SWITCH_CASE_ERROR;
}
@ -3165,7 +3176,7 @@ parse_intf_phy_88xx(struct halmac_adapter *adapter,
u16 ip_sel;
struct halmac_intf_phy_para *cur_param;
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
u8 result = HALMAC_RET_SUCCESS;
enum halmac_ret_status result = HALMAC_RET_SUCCESS;
switch (adapter->chip_ver) {
case HALMAC_CHIP_VER_A_CUT:
@ -3210,6 +3221,15 @@ parse_intf_phy_88xx(struct halmac_adapter *adapter,
} else if (intf_phy == HAL_INTF_PHY_USB2 ||
intf_phy == HAL_INTF_PHY_USB3) {
#if HALMAC_USB_SUPPORT
if (offset > 0x100)
usb_page_switch_88xx(adapter,
intf_phy,
1);
else
usb_page_switch_88xx(adapter,
intf_phy,
0);
offset = offset & 0xFF;
result = usbphy_write_88xx(adapter, (u8)offset,
value, intf_phy);
if (result != HALMAC_RET_SUCCESS)
@ -3236,7 +3256,7 @@ parse_intf_phy_88xx(struct halmac_adapter *adapter,
cur_param++;
} while (1);
return HALMAC_RET_SUCCESS;
return result;
}
/**

View File

@ -26,6 +26,15 @@
#define FEATURE_DUMP_LOG_EFUSE HALMAC_FEATURE_DUMP_LOGICAL_EFUSE
#define FEATURE_DUMP_LOG_EFUSE_MASK HALMAC_FEATURE_DUMP_LOGICAL_EFUSE_MASK
#define SUPER_USB_ZONE0_START 0x150
#define SUPER_USB_ZONE0_END 0x199
#define SUPER_USB_ZONE1_START 0x200
#define SUPER_USB_ZONE1_END 0x217
#define SUPER_USB_RE_PG_CK_ZONE0_START 0x15D
#define SUPER_USB_RE_PG_CK_ZONE0_END 0x164
static u8 bt_switch = 0;
static enum halmac_cmd_construct_state
efuse_cmd_cnstr_state_88xx(struct halmac_adapter *adapter);
@ -54,6 +63,10 @@ dump_efuse_drv_88xx(struct halmac_adapter *adapter);
static enum halmac_ret_status
proc_write_log_efuse_88xx(struct halmac_adapter *adapter, u32 offset, u8 value);
static enum halmac_ret_status
proc_write_log_efuse_word_88xx(struct halmac_adapter *adapter, u32 offset,
u16 value);
static enum halmac_ret_status
update_eeprom_mask_88xx(struct halmac_adapter *adapter,
struct halmac_pg_efuse_info *info, u8 *updated_mask);
@ -72,6 +85,11 @@ proc_pg_efuse_88xx(struct halmac_adapter *adapter,
struct halmac_pg_efuse_info *info, u8 word_en,
u8 pre_word_en, u32 eeprom_offset);
static enum halmac_ret_status
pg_super_usb_efuse_88xx(struct halmac_adapter *adapter,
struct halmac_pg_efuse_info *info, u8 word_en,
u8 pre_word_en, u32 eeprom_offset);
static enum halmac_ret_status
program_efuse_88xx(struct halmac_adapter *adapter,
struct halmac_pg_efuse_info *info, u8 *updated_mask);
@ -80,6 +98,28 @@ static void
mask_eeprom_88xx(struct halmac_adapter *adapter,
struct halmac_pg_efuse_info *info);
static enum halmac_ret_status
proc_gen_super_usb_map_88xx(struct halmac_adapter *adapter, u8 *drv_map,
u8 *updated_map, u8 *updated_mask);
static enum halmac_ret_status
super_usb_efuse_parser_88xx(struct halmac_adapter *adapter, u8 *phy_map,
u8 *log_map, u8 *log_mask);
static enum halmac_ret_status
super_usb_chk_88xx(struct halmac_adapter *adapter, u8 *super_usb);
static enum halmac_ret_status
log_efuse_re_pg_chk_88xx(struct halmac_adapter *adapter, u8 *efuse_mask,
u32 addr, u8 *re_pg);
static enum halmac_ret_status
super_usb_fmt_chk_88xx(struct halmac_adapter *adapter, u8 *re_pg);
static enum halmac_ret_status
super_usb_re_pg_chk_88xx(struct halmac_adapter *adapter, u8 *phy_map,
u8 *re_pg);
/**
* dump_efuse_map_88xx() - dump "physical" efuse map
* @adapter : the adapter of halmac
@ -220,13 +260,23 @@ dump_efuse_map_bt_88xx(struct halmac_adapter *adapter,
PLTFM_MSG_ERR("[ERR]switch efuse bank!!\n");
return status;
}
bt_switch = 1;
status = read_hw_efuse_88xx(adapter, 0, size, map);
if (status != HALMAC_RET_SUCCESS) {
bt_switch = 0;
PLTFM_MSG_ERR("[ERR]read hw efuse\n");
return status;
}
status = switch_efuse_bank_88xx(adapter, HALMAC_EFUSE_BANK_WIFI);
if (status != HALMAC_RET_SUCCESS) {
bt_switch = 0;
PLTFM_MSG_ERR("[ERR]switch efuse bank!!\n");
return status;
}
bt_switch = 0;
if (cnv_efuse_state_88xx(adapter, HALMAC_CMD_CNSTR_IDLE) !=
HALMAC_RET_SUCCESS)
return HALMAC_RET_ERROR_STATE;
@ -282,13 +332,23 @@ write_efuse_bt_88xx(struct halmac_adapter *adapter, u32 offset, u8 value,
PLTFM_MSG_ERR("[ERR]switch efuse bank!!\n");
return status;
}
bt_switch = 1;
status = write_hw_efuse_88xx(adapter, offset, value);
if (status != HALMAC_RET_SUCCESS) {
bt_switch = 0;
PLTFM_MSG_ERR("[ERR]write efuse\n");
return status;
}
status = switch_efuse_bank_88xx(adapter, HALMAC_EFUSE_BANK_WIFI);
if (status != HALMAC_RET_SUCCESS) {
bt_switch = 0;
PLTFM_MSG_ERR("[ERR]switch efuse bank!!\n");
return status;
}
bt_switch = 0;
if (cnv_efuse_state_88xx(adapter, HALMAC_CMD_CNSTR_IDLE) !=
HALMAC_RET_SUCCESS)
return HALMAC_RET_ERROR_STATE;
@ -344,13 +404,23 @@ read_efuse_bt_88xx(struct halmac_adapter *adapter, u32 offset, u8 *value,
PLTFM_MSG_ERR("[ERR]switch efuse bank\n");
return status;
}
bt_switch = 1;
status = read_efuse_88xx(adapter, offset, 1, value);
if (status != HALMAC_RET_SUCCESS) {
bt_switch = 0;
PLTFM_MSG_ERR("[ERR]read efuse\n");
return status;
}
status = switch_efuse_bank_88xx(adapter, HALMAC_EFUSE_BANK_WIFI);
if (status != HALMAC_RET_SUCCESS) {
bt_switch = 0;
PLTFM_MSG_ERR("[ERR]switch efuse bank!!\n");
return status;
}
bt_switch = 0;
if (cnv_efuse_state_88xx(adapter, HALMAC_CMD_CNSTR_IDLE) !=
HALMAC_RET_SUCCESS)
return HALMAC_RET_ERROR_STATE;
@ -737,6 +807,61 @@ write_log_efuse_88xx(struct halmac_adapter *adapter, u32 offset, u8 value)
return HALMAC_RET_SUCCESS;
}
/**
* write_log_efuse_word_88xx() - write "logical" efuse offset word
* @adapter : the adapter of halmac
* @offset : offset
* @value : value
* Author : Soar
* Return : enum halmac_ret_status
* More details of status code can be found in prototype document
*/
enum halmac_ret_status
write_log_efuse_word_88xx(struct halmac_adapter *adapter, u32 offset, u16 value)
{
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
enum halmac_cmd_process_status *proc_status;
proc_status = &adapter->halmac_state.efuse_state.proc_status;
PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
if (offset >= adapter->hw_cfg_info.eeprom_size) {
PLTFM_MSG_ERR("[ERR]Offset is too large\n");
return HALMAC_RET_EFUSE_SIZE_INCORRECT;
}
if (*proc_status == HALMAC_CMD_PROCESS_SENDING) {
PLTFM_MSG_WARN("[WARN]Wait event(efuse)\n");
return HALMAC_RET_BUSY_STATE;
}
if (efuse_cmd_cnstr_state_88xx(adapter) != HALMAC_CMD_CNSTR_IDLE) {
PLTFM_MSG_WARN("[WARN]Not idle(efuse)\n");
return HALMAC_RET_ERROR_STATE;
}
status = switch_efuse_bank_88xx(adapter, HALMAC_EFUSE_BANK_WIFI);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_MSG_ERR("[ERR]switch efuse bank\n");
return status;
}
status = proc_write_log_efuse_word_88xx(adapter, offset, value);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_MSG_ERR("[ERR]write logical efuse\n");
return status;
}
if (cnv_efuse_state_88xx(adapter, HALMAC_CMD_CNSTR_IDLE) !=
HALMAC_RET_SUCCESS)
return HALMAC_RET_ERROR_STATE;
PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
return HALMAC_RET_SUCCESS;
}
/**
* pg_efuse_by_map_88xx() - pg logical efuse by map
* @adapter : the adapter of halmac
@ -873,9 +998,11 @@ switch_efuse_bank_88xx(struct halmac_adapter *adapter,
u8 reg_value;
struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
if (cnv_efuse_state_88xx(adapter, HALMAC_CMD_CNSTR_BUSY) !=
HALMAC_RET_SUCCESS)
return HALMAC_RET_ERROR_STATE;
if (!bt_switch) {
if (cnv_efuse_state_88xx(adapter, HALMAC_CMD_CNSTR_BUSY) !=
HALMAC_RET_SUCCESS)
return HALMAC_RET_ERROR_STATE;
}
reg_value = HALMAC_REG_R8(REG_LDO_EFUSE_CTRL + 1);
@ -1293,9 +1420,19 @@ proc_pg_efuse_by_map_88xx(struct halmac_adapter *adapter,
enum halmac_efuse_read_cfg cfg)
{
u8 *updated_mask = NULL;
u8 *updated_map = NULL;
u32 map_size = adapter->hw_cfg_info.eeprom_size;
u32 mask_size = adapter->hw_cfg_info.eeprom_size >> 4;
u8 super_usb;
struct halmac_pg_efuse_info local_info;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
status = super_usb_chk_88xx(adapter, &super_usb);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_MSG_ERR("[ERR]super_usb_chk\n");
return status;
}
updated_mask = (u8 *)PLTFM_MALLOC(mask_size);
if (!updated_mask) {
PLTFM_MSG_ERR("[ERR]malloc updated mask\n");
@ -1310,21 +1447,58 @@ proc_pg_efuse_by_map_88xx(struct halmac_adapter *adapter,
return status;
}
if (super_usb) {
updated_map = (u8 *)PLTFM_MALLOC(map_size);
if (!updated_map) {
PLTFM_MSG_ERR("[ERR]malloc updated map\n");
PLTFM_FREE(updated_mask, mask_size);
return HALMAC_RET_MALLOC_FAIL;
}
PLTFM_MEMSET(updated_map, 0xFF, map_size);
status = proc_gen_super_usb_map_88xx(adapter, info->efuse_map,
updated_map, updated_mask);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_MSG_ERR("[ERR]gen eeprom mask/map\n");
PLTFM_FREE(updated_mask, mask_size);
PLTFM_FREE(updated_map, map_size);
return status;
}
local_info.efuse_map = updated_map;
local_info.efuse_mask = updated_mask;
local_info.efuse_map_size = map_size;
local_info.efuse_mask_size = mask_size;
}
if (super_usb)
status = check_efuse_enough_88xx(adapter, &local_info,
updated_mask);
else
status = check_efuse_enough_88xx(adapter, info, updated_mask);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_MSG_ERR("[ERR]chk efuse enough\n");
PLTFM_FREE(updated_mask, mask_size);
if (super_usb)
PLTFM_FREE(updated_map, map_size);
return status;
}
if (super_usb)
status = program_efuse_88xx(adapter, &local_info, updated_mask);
else
status = program_efuse_88xx(adapter, info, updated_mask);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_MSG_ERR("[ERR]pg efuse\n");
PLTFM_FREE(updated_mask, mask_size);
if (super_usb)
PLTFM_FREE(updated_map, map_size);
return status;
}
PLTFM_FREE(updated_mask, mask_size);
if (super_usb)
PLTFM_FREE(updated_map, map_size);
return HALMAC_RET_SUCCESS;
}
@ -1520,6 +1694,117 @@ proc_write_log_efuse_88xx(struct halmac_adapter *adapter, u32 offset, u8 value)
return HALMAC_RET_SUCCESS;
}
static enum halmac_ret_status
proc_write_log_efuse_word_88xx(struct halmac_adapter *adapter, u32 offset,
u16 value)
{
u8 byte1;
u8 byte2;
u8 blk;
u8 blk_idx;
u8 hdr;
u8 hdr2;
u8 *map = NULL;
u32 eeprom_size = adapter->hw_cfg_info.eeprom_size;
u32 prtct_efuse_size = adapter->hw_cfg_info.prtct_efuse_size;
u32 end;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
map = (u8 *)PLTFM_MALLOC(eeprom_size);
if (!map) {
PLTFM_MSG_ERR("[ERR]malloc map\n");
return HALMAC_RET_MALLOC_FAIL;
}
PLTFM_MEMSET(map, 0xFF, eeprom_size);
status = read_log_efuse_map_88xx(adapter, map);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_MSG_ERR("[ERR]read logical efuse\n");
PLTFM_FREE(map, eeprom_size);
return status;
}
end = adapter->efuse_end;
blk = (u8)(offset >> 3);
blk_idx = (u8)((offset & (8 - 1)) >> 1);
if (offset > 0x7f) {
hdr = (((blk & 0x07) << 5) & 0xE0) | 0x0F;
hdr2 = (u8)(((blk & 0x78) << 1) +
((0x1 << blk_idx) ^ 0x0F));
} else {
hdr = (u8)((blk << 4) + ((0x01 << blk_idx) ^ 0x0F));
}
if ((offset & 1) == 0) {
byte1 = (u8)(value & 0xFF);
byte2 = (u8)((value >> 8) & 0xFF);
} else {
PLTFM_FREE(map, eeprom_size);
return HALMAC_RET_ADR_NOT_ALIGN;
}
if (offset > 0x7f) {
if (adapter->hw_cfg_info.efuse_size <=
4 + prtct_efuse_size + end) {
PLTFM_FREE(map, eeprom_size);
return HALMAC_RET_EFUSE_NOT_ENOUGH;
}
status = write_hw_efuse_88xx(adapter, end, hdr);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_FREE(map, eeprom_size);
return status;
}
status = write_hw_efuse_88xx(adapter, end + 1, hdr2);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_FREE(map, eeprom_size);
return status;
}
status = write_hw_efuse_88xx(adapter, end + 2, byte1);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_FREE(map, eeprom_size);
return status;
}
status = write_hw_efuse_88xx(adapter, end + 3, byte2);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_FREE(map, eeprom_size);
return status;
}
} else {
if (adapter->hw_cfg_info.efuse_size <=
3 + prtct_efuse_size + end) {
PLTFM_FREE(map, eeprom_size);
return HALMAC_RET_EFUSE_NOT_ENOUGH;
}
status = write_hw_efuse_88xx(adapter, end, hdr);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_FREE(map, eeprom_size);
return status;
}
status = write_hw_efuse_88xx(adapter, end + 1, byte1);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_FREE(map, eeprom_size);
return status;
}
status = write_hw_efuse_88xx(adapter, end + 2, byte2);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_FREE(map, eeprom_size);
return status;
}
}
PLTFM_FREE(map, eeprom_size);
return HALMAC_RET_SUCCESS;
}
enum halmac_ret_status
read_efuse_88xx(struct halmac_adapter *adapter, u32 offset, u32 size, u8 *map)
{
@ -1629,6 +1914,14 @@ check_efuse_enough_88xx(struct halmac_adapter *adapter,
u16 j;
u32 eeprom_offset;
u32 pg_num = 0;
u8 super_usb;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
status = super_usb_chk_88xx(adapter, &super_usb);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_MSG_ERR("[ERR]super_usb_chk\n");
return status;
}
for (i = 0; i < info->efuse_map_size; i = i + 8) {
eeprom_offset = i;
@ -1639,14 +1932,21 @@ check_efuse_enough_88xx(struct halmac_adapter *adapter,
pre_word_en = (*(updated_mask + (i >> 4)) >> 4);
if (pre_word_en > 0) {
if (eeprom_offset > 0x7f) {
pg_num += 2;
if (super_usb &&
((eeprom_offset >= SUPER_USB_ZONE0_START &&
eeprom_offset <= SUPER_USB_ZONE0_END) ||
(eeprom_offset >= SUPER_USB_ZONE1_START &&
eeprom_offset <= SUPER_USB_ZONE1_END))) {
for (j = 0; j < 4; j++) {
if (((pre_word_en >> j) & 0x1) > 0)
pg_num += 2;
pg_num += 4;
}
} else {
pg_num++;
if (eeprom_offset > 0x7f)
pg_num += 2;
else
pg_num++;
for (j = 0; j < 4; j++) {
if (((pre_word_en >> j) & 0x1) > 0)
pg_num += 2;
@ -1767,6 +2067,68 @@ proc_pg_efuse_88xx(struct halmac_adapter *adapter,
return status;
}
static enum halmac_ret_status
pg_super_usb_efuse_88xx(struct halmac_adapter *adapter,
struct halmac_pg_efuse_info *info, u8 word_en,
u8 pre_word_en, u32 eeprom_offset)
{
u8 blk;
u8 hdr;
u8 hdr2;
u16 i;
u32 efuse_end;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
efuse_end = adapter->efuse_end;
blk = (u8)(eeprom_offset >> 3);
hdr = (((blk & 0x07) << 5) & 0xE0) | 0x0F;
for (i = 0; i < 4; i++) {
hdr = (((blk & 0x07) << 5) & 0xE0) | 0x0F;
if (((pre_word_en >> i) & 0x1) > 0) {
hdr2 = (u8)(((blk & 0x78) << 1) +
((pre_word_en & BIT(i)) ^ 0x0F));
status = write_hw_efuse_88xx(adapter, efuse_end, hdr);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_MSG_ERR("[ERR]write efuse\n");
return status;
}
status = write_hw_efuse_88xx(adapter, efuse_end + 1,
hdr2);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_MSG_ERR("[ERR]write efuse(+1)\n");
return status;
}
efuse_end = efuse_end + 2;
status = write_hw_efuse_88xx(adapter, efuse_end,
*(info->efuse_map +
eeprom_offset +
(i << 1)));
if (status != HALMAC_RET_SUCCESS) {
PLTFM_MSG_ERR("[ERR]write efuse(<<1)\n");
return status;
}
status = write_hw_efuse_88xx(adapter, efuse_end + 1,
*(info->efuse_map +
eeprom_offset + (i << 1)
+ 1));
if (status != HALMAC_RET_SUCCESS) {
PLTFM_MSG_ERR("[ERR]write efuse(<<1)+1\n");
return status;
}
efuse_end = efuse_end + 2;
}
}
adapter->efuse_end = efuse_end;
return status;
}
static enum halmac_ret_status
program_efuse_88xx(struct halmac_adapter *adapter,
struct halmac_pg_efuse_info *info, u8 *updated_mask)
@ -1775,8 +2137,15 @@ program_efuse_88xx(struct halmac_adapter *adapter,
u8 word_en;
u16 i;
u32 eeprom_offset;
u8 super_usb;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
status = super_usb_chk_88xx(adapter, &super_usb);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_MSG_ERR("[ERR]super_usb_chk\n");
return status;
}
for (i = 0; i < info->efuse_map_size; i = i + 8) {
eeprom_offset = i;
@ -1789,7 +2158,20 @@ program_efuse_88xx(struct halmac_adapter *adapter,
}
if (pre_word_en > 0) {
if (eeprom_offset > 0x7f) {
if (super_usb &&
((eeprom_offset >= SUPER_USB_ZONE0_START &&
eeprom_offset <= SUPER_USB_ZONE0_END) ||
(eeprom_offset >= SUPER_USB_ZONE1_START &&
eeprom_offset <= SUPER_USB_ZONE1_END))) {
status = pg_super_usb_efuse_88xx(adapter, info,
word_en,
pre_word_en,
eeprom_offset);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_MSG_ERR("[ERR]super usb efuse\n");
return status;
}
} else if (eeprom_offset > 0x7f) {
status = pg_extend_efuse_88xx(adapter, info,
word_en,
pre_word_en,
@ -2255,4 +2637,437 @@ read_wifi_phy_efuse_88xx(struct halmac_adapter *adapter, u32 offset, u32 size,
return HALMAC_RET_SUCCESS;
}
static enum halmac_ret_status
proc_gen_super_usb_map_88xx(struct halmac_adapter *adapter, u8 *drv_map,
u8 *updated_map, u8 *updated_mask)
{
u8 *local_map = NULL;
u8 *super_usb_map = NULL;
u8 *super_usb_mask = NULL;
u8 mask_val_0;
u8 mask_val_1;
u32 efuse_size;
u32 i;
u32 j;
u32 val32;
u32 map_size = adapter->hw_cfg_info.eeprom_size;
u32 mask_size = adapter->hw_cfg_info.eeprom_size >> 4;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
if (adapter->efuse_map_valid == 0) {
efuse_size = adapter->hw_cfg_info.efuse_size;
local_map = (u8 *)PLTFM_MALLOC(efuse_size);
if (!local_map) {
PLTFM_MSG_ERR("[ERR]local map\n");
return HALMAC_RET_MALLOC_FAIL;
}
status = read_efuse_88xx(adapter, 0, efuse_size, local_map);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_MSG_ERR("[ERR]read efuse\n");
PLTFM_FREE(local_map, efuse_size);
return status;
}
if (!adapter->efuse_map) {
adapter->efuse_map = (u8 *)PLTFM_MALLOC(efuse_size);
if (!adapter->efuse_map) {
PLTFM_MSG_ERR("[ERR]malloc adapter map\n");
PLTFM_FREE(local_map, efuse_size);
return HALMAC_RET_MALLOC_FAIL;
}
}
PLTFM_MUTEX_LOCK(&adapter->efuse_mutex);
PLTFM_MEMCPY(adapter->efuse_map, local_map, efuse_size);
adapter->efuse_map_valid = 1;
PLTFM_MUTEX_UNLOCK(&adapter->efuse_mutex);
PLTFM_FREE(local_map, efuse_size);
}
super_usb_mask = (u8 *)PLTFM_MALLOC(mask_size);
if (!super_usb_mask) {
PLTFM_MSG_ERR("[ERR]malloc updated mask\n");
return HALMAC_RET_MALLOC_FAIL;
}
PLTFM_MEMSET(super_usb_mask, 0x00, mask_size);
super_usb_map = (u8 *)PLTFM_MALLOC(map_size);
if (!super_usb_map) {
PLTFM_MSG_ERR("[ERR]malloc updated map\n");
PLTFM_FREE(super_usb_mask, mask_size);
return HALMAC_RET_MALLOC_FAIL;
}
PLTFM_MEMSET(super_usb_map, 0xFF, map_size);
status = super_usb_efuse_parser_88xx(adapter, adapter->efuse_map,
super_usb_map, super_usb_mask);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_FREE(super_usb_mask, mask_size);
PLTFM_FREE(super_usb_map, map_size);
return HALMAC_RET_EEPROM_PARSING_FAIL;
}
for (i = 0; i < map_size; i = i + 16) {
mask_val_0 = *(updated_mask + (i >> 4));
mask_val_1 = *(super_usb_mask + (i >> 4));
if (mask_val_0 || mask_val_1) {
for (j = 0; j < 4; j++) {
val32 = i + (j << 1);
if (mask_val_0 & BIT(j + 4)) {
*(updated_map + val32) =
*(drv_map + val32);
*(updated_map + val32 + 1) =
*(drv_map + val32 + 1);
} else if (mask_val_1 & BIT(j + 4)) {
*(updated_map + val32) =
*(super_usb_map + val32);
*(updated_map + val32 + 1) =
*(super_usb_map + val32 + 1);
}
}
for (j = 0; j < 4; j++) {
val32 = i + (j << 1);
if (mask_val_0 & BIT(j)) {
*(updated_map + val32 + 8) =
*(drv_map + val32 + 8);
*(updated_map + val32 + 9) =
*(drv_map + val32 + 9);
} else if (mask_val_1 & BIT(j)) {
*(updated_map + val32 + 8) =
*(super_usb_map + val32 + 8);
*(updated_map + val32 + 9) =
*(super_usb_map + val32 + 9);
}
}
*(updated_mask + (i >> 4)) |= mask_val_1;
}
}
PLTFM_FREE(super_usb_mask, mask_size);
PLTFM_FREE(super_usb_map, map_size);
return status;
}
static enum halmac_ret_status
super_usb_efuse_parser_88xx(struct halmac_adapter *adapter, u8 *phy_map,
u8 *log_map, u8 *log_mask)
{
u8 i;
u8 value8;
u8 blk_idx;
u8 word_en;
u8 valid;
u8 hdr;
u8 hdr2 = 0;
u8 usb_addr;
u32 eeprom_idx;
u32 efuse_idx = 0;
u32 start_offset;
u32 prtct_efuse_size = adapter->hw_cfg_info.prtct_efuse_size;
struct halmac_hw_cfg_info *hw_info = &adapter->hw_cfg_info;
do {
value8 = *(phy_map + efuse_idx);
hdr = value8;
if ((hdr & 0x1f) == 0x0f) {
efuse_idx++;
value8 = *(phy_map + efuse_idx);
hdr2 = value8;
if (hdr2 == 0xff)
break;
blk_idx = ((hdr2 & 0xF0) >> 1) | ((hdr >> 5) & 0x07);
word_en = hdr2 & 0x0F;
} else {
blk_idx = (hdr & 0xF0) >> 4;
word_en = hdr & 0x0F;
}
if (hdr == 0xff)
break;
efuse_idx++;
if (efuse_idx >= hw_info->efuse_size - prtct_efuse_size - 1)
return HALMAC_RET_EEPROM_PARSING_FAIL;
for (i = 0; i < 4; i++) {
valid = (u8)((~(word_en >> i)) & BIT(0));
if (valid == 1) {
eeprom_idx = (blk_idx << 3) + (i << 1);
if ((eeprom_idx + 1) > hw_info->eeprom_size) {
PLTFM_MSG_ERR("[ERR]efuse idx:0x%X\n",
efuse_idx - 1);
PLTFM_MSG_ERR("[ERR]read hdr:0x%X\n",
hdr);
PLTFM_MSG_ERR("[ERR]rad hdr2:0x%X\n",
hdr2);
return HALMAC_RET_EEPROM_PARSING_FAIL;
}
value8 = *(phy_map + efuse_idx);
*(log_map + eeprom_idx) = value8;
eeprom_idx++;
efuse_idx++;
if (efuse_idx > hw_info->efuse_size -
prtct_efuse_size - 1)
return HALMAC_RET_EEPROM_PARSING_FAIL;
value8 = *(phy_map + efuse_idx);
*(log_map + eeprom_idx) = value8;
efuse_idx++;
if (efuse_idx > hw_info->efuse_size -
prtct_efuse_size)
return HALMAC_RET_EEPROM_PARSING_FAIL;
}
}
start_offset = blk_idx << 3;
if ((start_offset >= SUPER_USB_ZONE0_START &&
start_offset <= SUPER_USB_ZONE0_END) ||
(start_offset >= SUPER_USB_ZONE1_START &&
start_offset <= SUPER_USB_ZONE1_END))
usb_addr = 1;
else
usb_addr = 0;
if (usb_addr) {
if (word_en != 0xE && word_en != 0xD &&
word_en != 0xB && word_en != 0x7) {
if (blk_idx & 1)
*(log_mask + (blk_idx >> 1)) |=
~word_en & 0x0F;
else
*(log_mask + (blk_idx >> 1)) |=
~(word_en << 4) & 0xF0;
} else {
if (blk_idx & 1)
*(log_mask + (blk_idx >> 1)) &=
word_en | 0xF0;
else
*(log_mask + (blk_idx >> 1)) &=
(word_en << 4) | 0x0F;
}
}
} while (1);
adapter->efuse_end = efuse_idx;
return HALMAC_RET_SUCCESS;
}
static enum halmac_ret_status
super_usb_chk_88xx(struct halmac_adapter *adapter, u8 *super_usb)
{
u8 *local_map = NULL;
u32 efuse_size;
u8 re_pg;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
if (adapter->chip_id == HALMAC_CHIP_ID_8822C &&
(adapter->intf == HALMAC_INTERFACE_PCIE ||
adapter->intf == HALMAC_INTERFACE_USB)) {
*super_usb = 1;
} else {
*super_usb = 0;
return HALMAC_RET_SUCCESS;
}
if (adapter->efuse_map_valid == 0) {
efuse_size = adapter->hw_cfg_info.efuse_size;
local_map = (u8 *)PLTFM_MALLOC(efuse_size);
if (!local_map) {
PLTFM_MSG_ERR("[ERR]local map\n");
return HALMAC_RET_MALLOC_FAIL;
}
status = read_efuse_88xx(adapter, 0, efuse_size, local_map);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_MSG_ERR("[ERR]read efuse\n");
PLTFM_FREE(local_map, efuse_size);
return status;
}
if (!adapter->efuse_map) {
adapter->efuse_map = (u8 *)PLTFM_MALLOC(efuse_size);
if (!adapter->efuse_map) {
PLTFM_MSG_ERR("[ERR]malloc adapter map\n");
PLTFM_FREE(local_map, efuse_size);
return HALMAC_RET_MALLOC_FAIL;
}
}
PLTFM_MUTEX_LOCK(&adapter->efuse_mutex);
PLTFM_MEMCPY(adapter->efuse_map, local_map, efuse_size);
adapter->efuse_map_valid = 1;
PLTFM_MUTEX_UNLOCK(&adapter->efuse_mutex);
PLTFM_FREE(local_map, efuse_size);
}
status = super_usb_re_pg_chk_88xx(adapter, adapter->efuse_map, &re_pg);
if (status != HALMAC_RET_SUCCESS)
return status;
if (re_pg) {
status = super_usb_fmt_chk_88xx(adapter, &re_pg);
if (status != HALMAC_RET_SUCCESS)
return status;
if (re_pg == 1) {
*super_usb = 0;
return HALMAC_RET_SUCCESS;
}
}
return status;
}
static enum halmac_ret_status
log_efuse_re_pg_chk_88xx(struct halmac_adapter *adapter, u8 *efuse_mask,
u32 addr, u8 *re_pg)
{
u32 size = adapter->hw_cfg_info.eeprom_size;
u8 mask_val;
u8 mask_offset;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
if (addr >= size) {
PLTFM_MSG_ERR("[ERR]Offset is too large\n");
return HALMAC_RET_EFUSE_SIZE_INCORRECT;
}
mask_val = *(efuse_mask + (addr >> 4));
if (addr & 0x8)
mask_offset = BIT((addr & 0x7) >> 1);
else
mask_offset = BIT((addr & 0x7) >> 1) << 4;
if (mask_val & mask_offset)
*re_pg = 1;
else
*re_pg = 0;
return status;
}
static enum halmac_ret_status
super_usb_fmt_chk_88xx(struct halmac_adapter *adapter, u8 *re_pg)
{
u32 map_size = adapter->hw_cfg_info.eeprom_size;
u32 mask_size = adapter->hw_cfg_info.eeprom_size >> 4;
u32 addr;
u8 *super_usb_map = NULL;
u8 *super_usb_mask = NULL;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
super_usb_mask = (u8 *)PLTFM_MALLOC(mask_size);
if (!super_usb_mask) {
PLTFM_MSG_ERR("[ERR]malloc updated mask\n");
return HALMAC_RET_MALLOC_FAIL;
}
PLTFM_MEMSET(super_usb_mask, 0x00, mask_size);
super_usb_map = (u8 *)PLTFM_MALLOC(map_size);
if (!super_usb_map) {
PLTFM_MSG_ERR("[ERR]malloc updated map\n");
PLTFM_FREE(super_usb_mask, mask_size);
return HALMAC_RET_MALLOC_FAIL;
}
PLTFM_MEMSET(super_usb_map, 0xFF, map_size);
status = super_usb_efuse_parser_88xx(adapter, adapter->efuse_map,
super_usb_map, super_usb_mask);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_FREE(super_usb_mask, mask_size);
PLTFM_FREE(super_usb_map, map_size);
return HALMAC_RET_EEPROM_PARSING_FAIL;
}
for (addr = SUPER_USB_ZONE0_START;
addr <= SUPER_USB_ZONE0_END; addr++) {
status = log_efuse_re_pg_chk_88xx(adapter, super_usb_mask, addr,
re_pg);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_FREE(super_usb_mask, mask_size);
PLTFM_FREE(super_usb_map, map_size);
return status;
}
if (*re_pg == 1) {
PLTFM_FREE(super_usb_mask, mask_size);
PLTFM_FREE(super_usb_map, map_size);
return status;
}
}
for (addr = SUPER_USB_ZONE1_START;
addr <= SUPER_USB_ZONE1_END; addr++) {
status = log_efuse_re_pg_chk_88xx(adapter, super_usb_mask, addr,
re_pg);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_FREE(super_usb_mask, mask_size);
PLTFM_FREE(super_usb_map, map_size);
return status;
}
if (*re_pg == 1) {
PLTFM_FREE(super_usb_mask, mask_size);
PLTFM_FREE(super_usb_map, map_size);
return status;
}
}
*re_pg = 0;
PLTFM_FREE(super_usb_mask, mask_size);
PLTFM_FREE(super_usb_map, map_size);
return status;
}
static enum halmac_ret_status
super_usb_re_pg_chk_88xx(struct halmac_adapter *adapter, u8 *phy_map, u8 *re_pg)
{
u32 size = adapter->hw_cfg_info.eeprom_size;
u32 addr;
u8 *map = NULL;
enum halmac_ret_status status = HALMAC_RET_SUCCESS;
map = (u8 *)PLTFM_MALLOC(size);
if (!map) {
PLTFM_MSG_ERR("[ERR]malloc map\n");
return HALMAC_RET_MALLOC_FAIL;
}
PLTFM_MEMSET(map, 0xFF, size);
status = eeprom_mask_parser_88xx(adapter, phy_map, map);
if (status != HALMAC_RET_SUCCESS) {
PLTFM_FREE(map, size);
return status;
}
for (addr = SUPER_USB_RE_PG_CK_ZONE0_START;
addr <= SUPER_USB_RE_PG_CK_ZONE0_END; addr++) {
if (*(map + addr) != 0xFF) {
PLTFM_FREE(map, size);
*re_pg = 1;
return status;
}
}
*re_pg = 0;
PLTFM_FREE(map, size);
return status;
}
#endif /* HALMAC_88XX_SUPPORT */

View File

@ -68,6 +68,10 @@ read_logical_efuse_88xx(struct halmac_adapter *adapter, u32 offset, u8 *value);
enum halmac_ret_status
write_log_efuse_88xx(struct halmac_adapter *adapter, u32 offset, u8 value);
enum halmac_ret_status
write_log_efuse_word_88xx(struct halmac_adapter *adapter, u32 offset,
u16 value);
enum halmac_ret_status
pg_efuse_by_map_88xx(struct halmac_adapter *adapter,
struct halmac_pg_efuse_info *info,

Some files were not shown because too many files have changed in this diff Show More