feat: update new aic driver version

This commit is contained in:
Shen Mintao
2025-07-24 11:20:36 +08:00
parent 99210d657b
commit 3800c225ac
101 changed files with 12814 additions and 4038 deletions
+1
View File
@@ -1,2 +1,3 @@
KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="5721", SYMLINK+="aicudisk", RUN+="/usr/bin/eject /dev/%k"
KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="5723", SYMLINK+="tendaudisk", RUN+="/usr/bin/eject /dev/%k"
KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="5725", SYMLINK+="tendaudiskv2", RUN+="/usr/bin/eject /dev/%k"
+2 -2
View File
@@ -6,7 +6,7 @@ obj-$(CONFIG_AIC8800_WLAN_SUPPORT) += aic8800_fdrv/
########## config option ##########
export CONFIG_USE_FW_REQUEST = n
export CONFIG_PREALLOC_RX_SKB = n
export CONFIG_PREALLOC_RX_SKB = y
export CONFIG_PREALLOC_TXQ = y
###################################
@@ -50,7 +50,7 @@ KDIR = /lib/modules/$(shell uname -r)/build
PWD = $(shell pwd)
KVER = $(shell uname -r)
MODDESTDIR = /lib/modules/$(KVER)/kernel/drivers/net/wireless/aic8800
SUBARCH = $(shell uname -m | sed -e s/i.86/i386/ -e s/armv.l/arm/ -e s/aarch64/arm64/)
SUBARCH = $(shell uname -m | sed -e s/i.86/i386/ -e s/armv.l/arm/ -e s/aarch64/arm64/ -e s/loongarch64/loongarch/ -e s/loong64/loongarch/)
ARCH ?= $(SUBARCH)
CROSS_COMPILE ?=
endif
+10
View File
@@ -0,0 +1,10 @@
*.o
*.ko
*.order
*.symvers
*.o.d
*.o.cmd
*.ko.cmd
*.mod
*.mod.c
*.mod.cmd
+28 -2
View File
@@ -82,6 +82,7 @@ CONFIG_BR_SUPPORT = n
CONFIG_USB_MSG_OUT_EP = y
CONFIG_USB_MSG_IN_EP = y
CONFIG_USB_RX_REASSEMBLE = n
CONFIG_WOWLAN = n
#DCDW support tx aggr, D80 support both
CONFIG_USB_RX_AGGR = n
@@ -109,18 +110,32 @@ CONFIG_PREALLOC_TXQ ?= y
CONFIG_USE_WIRELESS_EXT = y
CONFIG_DPD = y
CONFIG_FORCE_DPD_CALIB = y
CONFIG_LOFT_CALIB = n
CONFIG_GKI = n
CONFIG_SCHED_SCAN = n
CONFIG_TEMP_COMP = n
CONFIG_POWER_LIMIT = n
CONFIG_EXT_FEM_8800DCDW = n
# CONFIG_MCC = n for sta and p2p concurrent in same channel.
CONFIG_MCC = y
CONFIG_LOAD_BT_PATCH_IN_FDRV = n
CONFIG_DYNAMIC_PWR = n
CONFIG_DYNAMIC_PERPWR = n
CONFIG_BAND_STEERING = n
#support D80X2 can write rf result to file
CONFIG_WRITE_FILE_D80X2 = n
ifneq ($(CONFIG_WIRELESS_EXT), y)
CONFIG_USE_WIRELESS_EXT = n
endif
ifeq ($(CONFIG_EXT_FEM_8800DCDW), y)
CONFIG_DPD = n
CONFIG_FORCE_DPD_CALIB = n
CONFIG_LOFT_CALIB = y
endif
# Support of MU-MIMO transmission (need FW support)
ifeq ($(CONFIG_RWNX_BFMER), y)
CONFIG_RWNX_MUMIMO_TX ?= n
@@ -148,6 +163,7 @@ BR_NAME = br0
obj-$(CONFIG_AIC8800_WLAN_SUPPORT) := $(MODULE_NAME).o
$(MODULE_NAME)-y := \
rwnx_wakelock.o \
rwnx_msg_tx.o \
rwnx_msg_rx.o \
rwnx_utils.o \
@@ -172,8 +188,11 @@ $(MODULE_NAME)-y := \
aic_vendor.o \
aic_priv_cmd.o \
aicwf_compat_8800dc.o \
aicwf_compat_8800d80.o
aicwf_compat_8800d80.o \
aicwf_compat_8800d80x2.o
$(MODULE_NAME)-$(CONFIG_BAND_STEERING) += aicwf_manager.o \
aicwf_steering.o
$(MODULE_NAME)-$(CONFIG_BR_SUPPORT) += aic_br_ext.o
$(MODULE_NAME)-$(CONFIG_RWNX_RADAR) += rwnx_radar.o
$(MODULE_NAME)-$(CONFIG_DEBUG_FS) += rwnx_debugfs.o
@@ -241,6 +260,10 @@ ccflags-$(CONFIG_RWNX_MUMIMO_TX) += -DCONFIG_RWNX_MUMIMO_TX
ccflags-$(CONFIG_RFTEST) += -DCONFIG_RFTEST
ccflags-$(CONFIG_MCC) += -DCONFIG_MCC
ccflags-$(CONFIG_LOAD_BT_PATCH_IN_FDRV) += -DCONFIG_LOAD_BT_PATCH_IN_FDRV
ccflags-$(CONFIG_DYNAMIC_PWR) += -DCONFIG_DYNAMIC_PWR
ccflags-$(CONFIG_DYNAMIC_PERPWR) += -DCONFIG_DYNAMIC_PERPWR
ccflags-$(CONFIG_BAND_STEERING) += -DCONFIG_BAND_STEERING
ccflags-$(CONFIG_WRITE_FILE_D80X2) += -DRF_WRITE_FILE
ifeq ($(CONFIG_SDIO_SUPPORT), y)
ccflags-y += -DAICWF_SDIO_SUPPORT
@@ -274,7 +297,7 @@ endif
ccflags-$(CONFIG_RX_REORDER) += -DAICWF_RX_REORDER
ccflags-$(CONFIG_ARP_OFFLOAD) += -DAICWF_ARP_OFFLOAD
ccflags-$(CONFIG_USE_5G) += -DUSE_5G
ccflags-$(CONFIG_RADAR_OR_IR_DETECT) += -DRADAR_OR_IR_DETECT
ccflags-$(CONFIG_RADAR_OR_IR_DETECT) += -DCONFIG_RADAR_OR_IR_DETECT
ccflags-$(CONFIG_DOWNLOAD_FW) += -DCONFIG_DOWNLOAD_FW
ccflags-$(CONFIG_USB_BT) += -DCONFIG_USB_BT
ccflags-$(CONFIG_ALIGN_8BYTES) += -DCONFIG_ALIGN_8BYTES
@@ -310,11 +333,14 @@ ccflags-$(CONFIG_PREALLOC_TXQ) += -DCONFIG_PREALLOC_TXQ
ccflags-$(CONFIG_USE_WIRELESS_EXT) += -DCONFIG_USE_WIRELESS_EXT
ccflags-$(CONFIG_DPD) += -DCONFIG_DPD
ccflags-$(CONFIG_FORCE_DPD_CALIB) += -DCONFIG_FORCE_DPD_CALIB -DCONFIG_DPD
ccflags-$(CONFIG_LOFT_CALIB) += -DCONFIG_LOFT_CALIB
ccflags-$(CONFIG_GKI) += -DCONFIG_GKI
ccflags-$(CONFIG_SCHED_SCAN) += -DCONFIG_SCHED_SCAN
ccflags-$(CONFIG_FILTER_TCP_ACK) += -DCONFIG_FILTER_TCP_ACK
ccflags-$(CONFIG_TEMP_COMP) += -DCONFIG_TEMP_COMP
ccflags-$(CONFIG_POWER_LIMIT) += -DCONFIG_POWER_LIMIT
ccflags-$(CONFIG_EXT_FEM_8800DCDW) += -DCONFIG_EXT_FEM_8800DCDW
ccflags-$(CONFIG_WOWLAN) += -DCONFIG_WOWLAN
MAKEFLAGS +=-j$(shell nproc)
# Platform support list
+542 -24
View File
@@ -11,16 +11,31 @@
*/
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/vmalloc.h>
#include <linux/ctype.h>
#include "rwnx_defs.h"
#include "rwnx_msg_tx.h"
#include "rwnx_debugfs.h"
#include "rwnx_main.h"
#include "aic_priv_cmd.h"
#include "aicwf_compat_8800dc.h"
#include "aicwf_compat_8800d80.h"
#include "aicwf_compat_8800d80x2.h"
#include "rwnx_mod_params.h"
#include "rwnx_platform.h"
#define FLASH_BIN_ADDR_8800M80 0x8000000
extern void set_testmode(int);
extern int get_flash_bin_size(void);
extern u32 get_flash_bin_crc(void);
extern int testmode;
extern int rwnx_fill_station_info(struct rwnx_sta *sta, struct rwnx_vif *vif,
struct station_info *sinfo, u8 *phymode, u32 *tx_phyrate, u32 *rx_phyrate);
static void print_help(const char *cmd);
struct dbg_rftest_cmd_cfm cfm = {{0,}};
@@ -69,7 +84,13 @@ enum {
RDWR_EFUSE_HE_OFF,
SET_USB_OFF,
SET_PLL_TEST,
SET_ANT_MODE,
GET_NOISE,
RDWR_BT_EFUSE_PWROFST,
EXEC_FLASH_OPER,
RDWR_PWRADD2X,
RDWR_EFUSE_PWRADD2X,
CHECK_FLASH=0x108,
};
typedef struct {
@@ -119,6 +140,14 @@ typedef struct
u32_l usrdata[3]; // 3 words totally
} cmd_ef_usrdata_t;
typedef struct
{
u32_l flash_read_addr;
u32_l flash_read_size;
} cmd_check_flash_t;
extern char country_code[];
#define CMD_MAXARGS 30
#if 0//#include <linux/ctype.h>
@@ -247,6 +276,22 @@ int str_starts(const char *str, const char *start)
static int aic_priv_cmd_set_tx (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command)
{
cmd_rf_settx_t settx_param;
u8_l set_p = 0;
u8_l lvl_band, lvl_mod, lvl_idx, lvl_pwr = 0;
u8_l buf[10];
#ifdef CONFIG_POWER_LIMIT
int8_t max_pwr;
uint8_t r_idx;
txpwr_loss_conf_t txpwr_loss_tmp;
txpwr_loss_conf_t *txpwr_loss;
txpwr_loss = &txpwr_loss_tmp;
#endif
#ifdef AICWF_SDIO_SUPPORT
struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev;
#endif
#ifdef AICWF_USB_SUPPORT
struct aic_usb_dev *dev = g_rwnx_plat->usbdev;
#endif
if (argc < 6)
return -EINVAL;
@@ -261,13 +306,69 @@ static int aic_priv_cmd_set_tx (struct rwnx_hw *rwnx_hw, int argc, char *argv[],
} else {
settx_param.tx_intv_us = 10000; // set default val 10ms
}
if (argc > 7) {
if (dev->chipid == PRODUCT_ID_AIC8801){
AICWFDBG(LOGERROR, "unsupported cmd\n");
return -EINVAL;
}
lvl_pwr = command_strtoul(argv[7], NULL, 10);
AICWFDBG(LOGINFO, "lvl_pwr: %d\n", lvl_pwr);
if (settx_param.chan >= 36)
lvl_band = 2;
else
lvl_band = 1;
if (settx_param.mode == 0)
lvl_mod = 0;
else if (settx_param.mode == 2 || settx_param.mode == 4)
lvl_mod = 1;
else if (settx_param.mode == 5)
lvl_mod = 2;
if (settx_param.mode >= 4)
lvl_idx = settx_param.rate & 0xF;
else if (settx_param.mode >= 2)
lvl_idx = settx_param.rate & 0x7;
else
lvl_idx = settx_param.rate;
buf[0] = lvl_band;
buf[1] = lvl_mod;
buf[2] = lvl_idx;
buf[3] = lvl_pwr;
set_p = 1;
}
settx_param.max_pwr = POWER_LEVEL_INVALID_VAL;
AICWFDBG(LOGINFO, "txparam:%d,%d,%d,%d,%d,%d\n", settx_param.chan, settx_param.bw,
settx_param.mode, settx_param.rate, settx_param.length, settx_param.tx_intv_us);
#ifdef CONFIG_POWER_LIMIT
settx_param.max_pwr = get_powerlimit_by_chnum(settx_param.chan);
r_idx = get_ccode_region(country_code);
txpwr_loss = &txpwr_loss_tmp;
get_userconfig_txpwr_loss(txpwr_loss);
if (txpwr_loss->loss_enable_2g4 == 1)
AICWFDBG(LOGINFO, "%s:loss_value_2g4: %d\r\n", __func__,
txpwr_loss->loss_value_2g4);
if (txpwr_loss->loss_enable_5g == 1)
AICWFDBG(LOGINFO, "%s:loss_value_5g: %d\r\n", __func__,
txpwr_loss->loss_value_5g);
max_pwr = get_powerlimit_by_chnum(settx_param.chan, r_idx, settx_param.bw);
if (settx_param.chan >= 36) {
if (txpwr_loss->loss_enable_5g == 1)
max_pwr -= txpwr_loss->loss_value_5g;
} else {
if (txpwr_loss->loss_enable_2g4 == 1)
max_pwr -= txpwr_loss->loss_value_2g4;
}
if (!set_p || (lvl_pwr == 255)) {
settx_param.max_pwr = max_pwr;
AICWFDBG(LOGINFO, "max_pwr:%d\n", settx_param.max_pwr);
} else
AICWFDBG(LOGINFO, "the specified power is input without power limit\n");
#endif
if (set_p && (lvl_pwr != 255))
rwnx_send_rftest_req(rwnx_hw, RDWR_PWRLVL, 4, buf, &cfm);
rwnx_send_rftest_req(rwnx_hw, SET_TX, sizeof(cmd_rf_settx_t), (u8_l *)&settx_param, NULL);
return 0;
}
@@ -389,8 +490,8 @@ static int aic_priv_cmd_set_xtal_cap_fine (struct rwnx_hw *rwnx_hw, int argc, ch
return -EINVAL;
xtal_cap_fine = command_strtoul(argv[1], NULL, 10);
AICWFDBG(LOGINFO, "xtal_cap =%x\r\n", xtal_cap_fine);
rwnx_send_rftest_req(rwnx_hw, SET_XTAL_CAP, sizeof(xtal_cap_fine), (u8_l *)&xtal_cap_fine, &cfm);
AICWFDBG(LOGINFO, "xtal_cap_fine =%x\r\n", xtal_cap_fine);
rwnx_send_rftest_req(rwnx_hw, SET_XTAL_CAP_FINE, sizeof(xtal_cap_fine), (u8_l *)&xtal_cap_fine, &cfm);
memcpy(command, &cfm.rftest_result[0], 4);
return 4;
}
@@ -439,7 +540,7 @@ static int aic_priv_cmd_set_freq_cal_fine (struct rwnx_hw *rwnx_hw, int argc, ch
static int aic_priv_cmd_get_freq_cal (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command)
{
u8_l val;
u32_l val;
#ifdef AICWF_SDIO_SUPPORT
struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev;
#endif
@@ -450,7 +551,7 @@ static int aic_priv_cmd_get_freq_cal (struct rwnx_hw *rwnx_hw, int argc, char *a
rwnx_send_rftest_req(rwnx_hw, GET_FREQ_CAL, 0, NULL, &cfm);
memcpy(command, &cfm.rftest_result[0], 4);
val = cfm.rftest_result[0];
if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) {
if (dev->chipid != PRODUCT_ID_AIC8801) {
AICWFDBG(LOGINFO, "cap=0x%x (remain:%x), cap_fine=%x (remain:%x)\n",
val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff, (val >> 24) & 0xff);
} else {
@@ -696,7 +797,7 @@ static int aic_priv_cmd_rdwr_pwrlvl (struct rwnx_hw *rwnx_hw, int argc, char *ar
AICWFDBG(LOGERROR, "wrong func: %x\n", func);
return -EINVAL;
}
if(dev->chipid == PRODUCT_ID_AIC8800D81){
if((dev->chipid == PRODUCT_ID_AIC8800D81) || (dev->chipid == PRODUCT_ID_AIC8800D81X2) || (dev->chipid == PRODUCT_ID_AIC8800D89X2)){
memcpy(command, &cfm.rftest_result[0], 6 * 12);
return (6 * 12);
} else {
@@ -721,15 +822,15 @@ static int aic_priv_cmd_rdwr_pwrofst (struct rwnx_hw *rwnx_hw, int argc, char *a
}
if (func == 0) { // read cur
rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFST, 0, NULL, &cfm);
} else if (func <= 2) { // write 2.4g/5g pwr ofst
if ((argc > 4) && (dev->chipid == PRODUCT_ID_AIC8800D81)) {
} else if (func <= 4) { // write 2.4g/5g pwr ofst and ant0/1
if ((argc > 4) && ((dev->chipid == PRODUCT_ID_AIC8800D81) || (dev->chipid == PRODUCT_ID_AIC8800D81X2) || (dev->chipid == PRODUCT_ID_AIC8800D89X2))) {
u8_l type = (u8_l)command_strtoul(argv[2], NULL, 16);
u8_l chgrp = (u8_l)command_strtoul(argv[3], NULL, 16);
s8_l pwrofst = (u8_l)command_strtoul(argv[4], NULL, 10);
u8_l buf[4] = {func, type, chgrp, (u8_l)pwrofst};
AICWFDBG(LOGINFO, "set pwrofst_%s:[%x][%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", type, chgrp, pwrofst);
rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFST, sizeof(buf), buf, &cfm);
} else if ((argc > 3) && (dev->chipid != PRODUCT_ID_AIC8800D81)) {
} else if ((argc > 3) && ((dev->chipid == PRODUCT_ID_AIC8801) || (dev->chipid == PRODUCT_ID_AIC8800DW) || (dev->chipid == PRODUCT_ID_AIC8800DC))) {
u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16);
s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10);
u8_l buf[3] = {func, chgrp, (u8_l)pwrofst};
@@ -746,6 +847,8 @@ static int aic_priv_cmd_rdwr_pwrofst (struct rwnx_hw *rwnx_hw, int argc, char *a
res_len = 3;
} else if (dev->chipid == PRODUCT_ID_AIC8800D81) { // 3 * 2 (2.4g) + 3 * 6 (5g)
res_len = 3 * 3 + 3 * 6;
} else if ((dev->chipid == PRODUCT_ID_AIC8800D81X2) || (dev->chipid == PRODUCT_ID_AIC8800D89X2)) { // ant0/1
res_len = ( 3 * 3 + 3 * 6 ) * 2;
} else {
res_len = 3 + 4;
}
@@ -826,15 +929,15 @@ static int aic_priv_cmd_rdwr_efuse_pwrofst (struct rwnx_hw *rwnx_hw, int argc, c
}
if (func == 0) { // read cur
rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFST, 0, NULL, &cfm);
} else if (func <= 2) { // write 2.4g/5g pwr ofst
if ((argc > 4) && (dev->chipid == PRODUCT_ID_AIC8800D81)) {
} else if (func <= 4) { // write 2.4g/5g pwr ofst and ant0/1
if ((argc > 4) && ((dev->chipid == PRODUCT_ID_AIC8800D81) || (dev->chipid == PRODUCT_ID_AIC8800D81X2) || (dev->chipid == PRODUCT_ID_AIC8800D89X2))) {
u8_l type = (u8_l)command_strtoul(argv[2], NULL, 16);
u8_l chgrp = (u8_l)command_strtoul(argv[3], NULL, 16);
s8_l pwrofst = (u8_l)command_strtoul(argv[4], NULL, 10);
u8_l buf[4] = {func, type, chgrp, (u8_l)pwrofst};
AICWFDBG(LOGINFO, "set efuse pwrofst_%s:[%x][%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", type, chgrp, pwrofst);
rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFST, sizeof(buf), buf, &cfm);
} else if ((argc > 3) && (dev->chipid != PRODUCT_ID_AIC8800D81)) {
} else if ((argc > 3) && ((dev->chipid == PRODUCT_ID_AIC8801) || (dev->chipid == PRODUCT_ID_AIC8800DW) || (dev->chipid == PRODUCT_ID_AIC8800DC))) {
u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16);
s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10);
u8_l buf[3] = {func, chgrp, (u8_l)pwrofst};
@@ -851,7 +954,9 @@ static int aic_priv_cmd_rdwr_efuse_pwrofst (struct rwnx_hw *rwnx_hw, int argc, c
if ((dev->chipid == PRODUCT_ID_AIC8800DC) || (dev->chipid == PRODUCT_ID_AIC8800DW)) { // 6 = 3 (2.4g) * 2
res_len = 3 * 2;
} else if (dev->chipid == PRODUCT_ID_AIC8800D81) { // 3 * 2 (2.4g) + 3 * 6 (5g)
res_len = 3 * 3 + 3 * 6;
res_len = (3 * 3 + 3 * 6) * 2;
} else if((dev->chipid == PRODUCT_ID_AIC8800D81X2) || (dev->chipid == PRODUCT_ID_AIC8800D89X2)) { // 3 * 2 (2.4g) *2 + 3 * 6 (5g) *2
res_len = (3 * 3 + 3 * 6) * 2 * 2;
} else { // 7 = 3(2.4g) + 4(5g)
res_len = 3 + 4;
}
@@ -867,14 +972,14 @@ static int aic_priv_cmd_rdwr_efuse_pwrofstfine (struct rwnx_hw *rwnx_hw, int arg
func = (u8_l)command_strtoul(argv[1], NULL, 16);
}
if (func == 0) { // read cur
rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFSTFINE, 0, NULL, &cfm);
rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFSTFINE, 0, NULL, &cfm);
} else if (func <= 2) { // write 2.4g/5g pwr ofst
if (argc > 3) {
u8_l chgrp = (u8_l)command_strtoul(argv[2], NULL, 16);
s8_l pwrofst = (u8_l)command_strtoul(argv[3], NULL, 10);
u8_l buf[3] = {func, chgrp, (u8_l)pwrofst};
AICWFDBG(LOGINFO, "set pwrofstfine:[%x][%x]=%d\r\n", func, chgrp, pwrofst);
rwnx_send_rftest_req(rwnx_hw, RDWR_PWROFSTFINE, sizeof(buf), buf, &cfm);
rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWROFSTFINE, sizeof(buf), buf, &cfm);
} else {
AICWFDBG(LOGERROR, "wrong args\n");
return -EINVAL;
@@ -999,7 +1104,7 @@ static int aic_priv_cmd_rdwr_efuse_he_off (struct rwnx_hw *rwnx_hw, int argc, ch
func = command_strtoul(argv[1], NULL, 10);
AICWFDBG(LOGINFO, "set he off: %d\n", func);
if(func == 1) {
if(func == 1 || func == 0) {
rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_HE_OFF, sizeof(func), (u8_l *)&func, &cfm);
AICWFDBG(LOGINFO, "he_off cfm: %d\n", cfm.rftest_result[0]);
memcpy(command, &cfm.rftest_result[0], 4);
@@ -1168,6 +1273,206 @@ static int aic_priv_cmd_set_pll_test (struct rwnx_hw *rwnx_hw, int argc, char *a
return 0;
}
static int aic_priv_cmd_set_ant_mode (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command)
{
u8_l func = 0;
if (argc > 1) {
func = command_strtoul(argv[1], NULL, 10);
AICWFDBG(LOGINFO, "ant %d\r\n", func);
rwnx_send_rftest_req(rwnx_hw, SET_ANT_MODE, sizeof(func), (u8_l *)&func, NULL);
} else {
return -EINVAL;
}
return 0;
}
static int aic_priv_cmd_rdwr_bt_efuse_pwrofst (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command)
{
u8_l func = 0;
if (argc == 1) {
func = 0;
} else if (argc == 2) {
func = 1;
}
if (func == 0) { // read cur
rwnx_send_rftest_req(rwnx_hw, RDWR_BT_EFUSE_PWROFST, 0, NULL, &cfm);
} else if (func == 1) { // write bt tx pwrofst
int8_t bt_txpwrofst = command_strtoul(argv[1], NULL, 10);
AICWFDBG(LOGINFO, "set bt efuse pwrofst %d\r\n",bt_txpwrofst);
if (bt_txpwrofst < -7 || bt_txpwrofst > 7) {
AICWFDBG(LOGERROR, "wrong params %d, pwrofst limit -7 ~ 7\n", bt_txpwrofst);
return -EINVAL;
} else {
rwnx_send_rftest_req(rwnx_hw, RDWR_BT_EFUSE_PWROFST, sizeof(bt_txpwrofst), &bt_txpwrofst, &cfm);
}
} else {
AICWFDBG(LOGERROR, "wrong func: %x\n", func);
return -EINVAL;
}
memcpy(command, &cfm.rftest_result[0], 2);
return 2;
}
static int aic_priv_cmd_exec_flash_oper(struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command)
{
u8_l func = 0;
if (argc > 1) {
func = (s8_l)command_strtoul(argv[1], NULL, 10);
AICWFDBG(LOGINFO, "exec_flash_oper: %d\n", func);
rwnx_send_rftest_req(rwnx_hw, EXEC_FLASH_OPER, sizeof(func), &func, &cfm);
AICWFDBG(LOGINFO, "flash oper %u %u \n",cfm.rftest_result[0],cfm.rftest_result[1]);
} else {
AICWFDBG(LOGERROR, "wrong args\n");
return -EINVAL;
}
return 0;
}
static int aic_priv_cmd_country_set(struct rwnx_hw *rwnx_hw, int argc,
char *argv[], char *command)
{
int ret = 0;
struct ieee80211_regdomain *regdomain;
if (argc < 2) {
AICWFDBG(LOGINFO, "%s param err\n", __func__);
return -1;
}
AICWFDBG(LOGINFO, "cmd country_set: %s\n", argv[1]);
regdomain = getRegdomainFromRwnxDB(rwnx_hw->wiphy, argv[1]);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
ret = regulatory_set_wiphy_regd(
rwnx_hw->wiphy, regdomain);
#else
ret = wiphy_apply_custom_regulatory(
rwnx_hw->wiphy, regdomain);
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) */
#ifdef CONFIG_RADAR_OR_IR_DETECT
rwnx_radar_set_domain(&rwnx_hw->radar, regdomain->dfs_region);
#endif
#ifdef CONFIG_POWER_LIMIT
if (!testmode){
rwnx_send_me_chan_config_req(rwnx_hw, argv[1]);
}
#endif
return ret;
}
static int aic_priv_cmd_get_noise(struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command)
{
rwnx_send_rftest_req(rwnx_hw, GET_NOISE, 0, NULL, &cfm);
AICWFDBG(LOGINFO, "noise: %d,%d\n", (char)cfm.rftest_result[0], (char)cfm.rftest_result[1]);
command[0] = (char)cfm.rftest_result[0];
command[1] = (char)cfm.rftest_result[1];
return 2;
}
static int aic_priv_cmd_rdwr_pwradd2x (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command)
{
u8_l func = 0;
int8_t pwradd2x_in = 0;
#ifdef AICWF_SDIO_SUPPORT
struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev;
#endif
#ifdef AICWF_USB_SUPPORT
struct aic_usb_dev *dev = g_rwnx_plat->usbdev;
#endif
if (dev->chipid != PRODUCT_ID_AIC8800D81) {
AICWFDBG(LOGERROR, "RDWR_PWRADD2X, only D40/80 support\n");
return -EINVAL;
}
if (argc > 1) {
func = (u8_l)command_strtoul(argv[1], NULL, 10);
}
if ((func > 0) && (argc > 2)) {
pwradd2x_in = (int8_t)command_strtoul(argv[2], NULL, 10);
}
if (func == 0) { // read cur
rwnx_send_rftest_req(rwnx_hw, RDWR_PWRADD2X, 0, NULL, &cfm);
} else if ((func == 1) || (func == 2)) { // write pwradd2x
AICWFDBG(LOGINFO, "set pwradd2x_%s %d\r\n", (func == 1) ? "2g4" : "5g", pwradd2x_in);
if (pwradd2x_in < -15 || pwradd2x_in > 15) {
AICWFDBG(LOGERROR, "wrong params %d, pwradd2x: -15 ~ 15\n", pwradd2x_in);
return -EINVAL;
} else {
u8_l buf[2] = {func, (u8_l)pwradd2x_in};
rwnx_send_rftest_req(rwnx_hw, RDWR_PWRADD2X, sizeof(buf), buf, &cfm);
}
} else {
AICWFDBG(LOGERROR, "wrong func: %x\n", func);
return -EINVAL;
}
memcpy(command, &cfm.rftest_result[0], 2);
return 2;
}
static int aic_priv_cmd_rdwr_efuse_pwradd2x (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command)
{
u8_l func = 0;
int8_t pwradd2x_in = 0;
#ifdef AICWF_SDIO_SUPPORT
struct aic_sdio_dev *dev = g_rwnx_plat->sdiodev;
#endif
#ifdef AICWF_USB_SUPPORT
struct aic_usb_dev *dev = g_rwnx_plat->usbdev;
#endif
if (dev->chipid != PRODUCT_ID_AIC8800D81) {
AICWFDBG(LOGERROR, "RDWR_EFUSE_PWRADD2X, only D40/80 support\n");
return -EINVAL;
}
if (argc > 1) {
func = (u8_l)command_strtoul(argv[1], NULL, 10);
}
if ((func > 0) && (argc > 2)) {
pwradd2x_in = (int8_t)command_strtoul(argv[2], NULL, 10);
}
if (func == 0) { // read cur
rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWRADD2X, 0, NULL, &cfm);
} else if ((func == 1) || (func == 2)) { // write pwradd2x
AICWFDBG(LOGINFO, "set efuse pwradd2x_%s %d\r\n", (func == 1) ? "2g4" : "5g", pwradd2x_in);
if (pwradd2x_in < -15 || pwradd2x_in > 15) {
AICWFDBG(LOGERROR, "wrong params %d, pwradd2x: -15 ~ 15\n", pwradd2x_in);
return -EINVAL;
} else {
u8_l buf[2] = {func, (u8_l)pwradd2x_in};
rwnx_send_rftest_req(rwnx_hw, RDWR_EFUSE_PWRADD2X, sizeof(buf), buf, &cfm);
}
} else {
AICWFDBG(LOGERROR, "wrong func: %x\n", func);
return -EINVAL;
}
memcpy(command, &cfm.rftest_result[0], 3);
return 3;
}
static int aic_priv_cmd_check_flash(struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command)
{
cmd_check_flash_t cmd_check_flash;
cmd_check_flash.flash_read_addr = FLASH_BIN_ADDR_8800M80;
cmd_check_flash.flash_read_size = get_flash_bin_size();
rwnx_send_rftest_req(rwnx_hw, CHECK_FLASH, sizeof(cmd_check_flash), (u8_l *)&cmd_check_flash, &cfm);
cfm.rftest_result[1] = get_flash_bin_crc();
AICWFDBG(LOGINFO, "flash_crc: %x %x\n", cfm.rftest_result[0], cfm.rftest_result[1]);
memcpy(command, &cfm.rftest_result[0], 8);
return 8;
}
static int aic_priv_cmd_help (struct rwnx_hw *rwnx_hw, int argc, char *argv[], char *command)
{
@@ -1192,7 +1497,7 @@ static const struct aic_priv_cmd aic_priv_commands[] = {
"= display rx fcsok/total pkt num" },
{ "set_rxstop", aic_priv_cmd_set_rxstop,
"= stop rx " },
{ "set_tx_tone", aic_priv_cmd_set_tx_tone,
{ "set_txtone", aic_priv_cmd_set_tx_tone,
"<val> val = 0/off" },
{ "set_rx_meter", aic_priv_cmd_set_rx_meter,
"= set rx meter " },
@@ -1270,6 +1575,20 @@ static const struct aic_priv_cmd aic_priv_commands[] = {
"= off usb configure before usb disconnect" },
{ "set_pll_test", aic_priv_cmd_set_pll_test,
"<func> <freq> <tx_pwr> = use pll test to measure saturation power" },
{ "set_ant", aic_priv_cmd_set_ant_mode,
"<val> = 0/ant0, 1/ant1, 2/both" },
{ "rdwr_bt_efuse_pwrofst", aic_priv_cmd_rdwr_bt_efuse_pwrofst,
"<pwrofst> = read/write bt tx power offset into efuse" },
{ "exec_flash_oper",aic_priv_cmd_exec_flash_oper,
"<val> = 0 check, 1 rec, 2 prot 3 rd_wcr0 4 er_wcr0 "},
{"country_set", aic_priv_cmd_country_set, "<ccode>"},
{"get_noise", aic_priv_cmd_get_noise, "get noise"},
{"rdwr_pwradd2x", aic_priv_cmd_rdwr_pwradd2x,
"a value is added for both 2.4G and 5G to achieve overall power adjustment of the band"},
{"rdwr_efuse_pwradd2x", aic_priv_cmd_rdwr_efuse_pwradd2x,
"a value is added for both 2.4G and 5G to achieve overall power adjustment of the band, write to efuse"},
{"check_flash", aic_priv_cmd_check_flash,
"check bin crc in flash" },
//Reserve for new aic_priv_cmd.
{ "help", aic_priv_cmd_help,
@@ -1304,6 +1623,13 @@ int handle_private_cmd(struct net_device *net, char *command, u32 cmd_len)
RWNX_DBG(RWNX_FN_ENTRY_STR);
#if 0
if(!testmode) {
AICWFDBG(LOGERROR, "not in testmode\n");
return -1;
}
#endif
argc = parse_line(command, argv);
if (argc == 0) {
return -1;
@@ -1312,7 +1638,8 @@ int handle_private_cmd(struct net_device *net, char *command, u32 cmd_len)
count = 0;
cmd = aic_priv_commands;
while (cmd->cmd) {
if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0)
if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0 &&
strncasecmp(cmd->cmd, argv[0], strlen(cmd->cmd)) == 0)
{
match = cmd;
if (strcasecmp(cmd->cmd, argv[0]) == 0) {
@@ -1355,6 +1682,8 @@ int handle_private_cmd(struct net_device *net, char *command, u32 cmd_len)
#define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE"
#define CMD_SET_TESTMODE "SET_TESTMODE"
#define CMD_SET_BLE_WAKE "SET_BLE_WAKE"
#define CMD_SET_MON_FREQ "SET_MON_FREQ"
#define CMD_GET_CS_INFO "GET_CS_INFO"
struct ieee80211_regdomain *getRegdomainFromRwnxDB(struct wiphy *wiphy, char *alpha2);
@@ -1387,6 +1716,143 @@ void set_vendor_extension_ie(char *command){
}
#endif//CONFIG_SET_VENDOR_EXTENSION_IE
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0))
int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_chan_def *chandef);
#else
int rwnx_cfg80211_set_monitor_channel_(struct wiphy *wiphy,
struct cfg80211_chan_def *chandef);
#endif
int rwnx_atoi2(char *value, int c_len);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0))
void set_mon_chan(struct rwnx_vif *vif, struct net_device *dev, char *parameter)
#else
void set_mon_chan(struct rwnx_vif *vif, char *parameter)
#endif
{
struct cfg80211_chan_def *chandef = NULL;
int freq = 0;
chandef = (struct cfg80211_chan_def *)vmalloc(sizeof(struct cfg80211_chan_def));
memset(chandef, 0, sizeof(struct cfg80211_chan_def));
chandef->chan = (struct ieee80211_channel *)vmalloc(sizeof(struct ieee80211_channel));
memset(chandef->chan, 0, sizeof(struct ieee80211_channel));
freq = rwnx_atoi2(parameter, 4);
if(freq <= 2484){
chandef->chan->band = NL80211_BAND_2GHZ;
}else{
chandef->chan->band = NL80211_BAND_5GHZ;
}
chandef->chan->center_freq = freq;
chandef->width = NL80211_CHAN_WIDTH_20;
chandef->center_freq1 = chandef->chan->center_freq;
chandef->center_freq2 = 0;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0))
rwnx_cfg80211_set_monitor_channel_(vif->rwnx_hw->wiphy, dev, chandef);
#else
rwnx_cfg80211_set_monitor_channel_(vif->rwnx_hw->wiphy, chandef);
#endif
vfree(chandef->chan);
vfree(chandef);
}
int get_cs_info(struct rwnx_vif *vif, u8 *mac_addr, u8 *val)
{
struct rwnx_sta *sta = NULL;
u8 phymode = 0;
u32 tx_phyrate = 0, rx_phyrate = 0;
struct aicwf_cs_info cs_info;
struct station_info sinfo;
struct rwnx_sta_stats *stats;
struct rx_vector_2 *rx_vect2;
struct rwnx_chanctx *ctxt;
if (RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_MONITOR)
return -EINVAL;
else if ((RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_STATION) ||
(RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_P2P_CLIENT)) {
AICWFDBG(LOGINFO, "%s: sta mode\n", __func__);
if (vif->sta.ap)
sta = vif->sta.ap;
} else {
struct rwnx_sta *sta_iter;
AICWFDBG(LOGINFO, "%s: ap mode, mac=%pM\n", __func__, mac_addr);
spin_lock_bh(&vif->rwnx_hw->cb_lock);
list_for_each_entry(sta_iter, &vif->ap.sta_list, list) {
if (sta_iter->valid && ether_addr_equal(sta_iter->mac_addr, mac_addr)) {
sta = sta_iter;
break;
}
}
spin_unlock_bh(&vif->rwnx_hw->cb_lock);
}
memset(&cs_info, 0, sizeof(struct aicwf_cs_info));
memcpy(cs_info.countrycode, country_code, 4);
if((sta == NULL) && (RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_AP)) {
sta = &vif->rwnx_hw->sta_table[vif->ap.bcmc_index];
ctxt = &vif->rwnx_hw->chanctx_table[vif->ch_index];
sta->center_freq = ctxt->chan_def.chan->center_freq;
sta->width = ctxt->chan_def.width;
}
if(sta) {
stats = &sta->stats;
rx_vect2 = &stats->last_rx.rx_vect2;
AICWFDBG(LOGINFO, "fill: staidx=%d\n", sta->sta_idx);
rwnx_fill_station_info(sta, vif, &sinfo, &phymode, &tx_phyrate, &rx_phyrate);
cs_info.rssi = sinfo.signal;
//cs_info.bandwidth = sta->width;
if(sta->width < NL80211_CHAN_WIDTH_40)
cs_info.bandwidth = 0;
else if(sta->width < NL80211_CHAN_WIDTH_80)
cs_info.bandwidth = 1;
else
cs_info.bandwidth = 2;
cs_info.freq = sta->center_freq;
cs_info.phymode = phymode; // 0:b 1:g 2:a 3:n 4:ac 5:ax
//snr (int8_t)rx_vect2->evm1, (int8_t)rx_vect2->evm2
cs_info.snr = (int8_t)(rx_vect2->evm1) + (int8_t)(rx_vect2->evm2) / 2;
cs_info.noise = cs_info.rssi - cs_info.snr; //rssi - snr
//chanutil TBD
cs_info.chan_time_ms = stats->last_chan_time;
cs_info.chan_time_busy_ms = stats->last_chan_busy_time;
cs_info.tx_ack_succ_stat = stats->tx_ack_succ_stat;
cs_info.tx_ack_fail_stat = stats->tx_ack_fail_stat;
cs_info.chan_tx_busy_time = stats->last_chan_tx_busy_time;
cs_info.txpwr = cs_info.freq >5000? userconfig_info.txpwr_lvl_v4.pwrlvl_11a_5g[0] : userconfig_info.txpwr_lvl_v4.pwrlvl_11ax_2g4[0];
if(sta->sta_idx < NX_REMOTE_STA_MAX) {
cs_info.rxnss = sinfo.rxrate.nss;
cs_info.rxmcs = sinfo.rxrate.mcs;
cs_info.txnss = sinfo.txrate.nss;
cs_info.txmcs = sinfo.txrate.mcs;
}
cs_info.tx_phyrate = tx_phyrate;
cs_info.rx_phyrate = rx_phyrate;
memcpy(val, &cs_info, sizeof(struct aicwf_cs_info));
AICWFDBG(LOGINFO, "phymode=%d. bw=%d, rssi=%d, tx_phyrate=%d, rx_phyrate=%d\n", cs_info.phymode, cs_info.bandwidth, cs_info.rssi,
tx_phyrate, rx_phyrate);
return sizeof(struct aicwf_cs_info);
}
return 0;
}
int android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
{
@@ -1470,7 +1936,8 @@ int android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
#if 1//Handle Android command
if(!strncasecmp(command, CMD_SET_COUNTRY, strlen(CMD_SET_COUNTRY))) {
if(!strncasecmp(command, CMD_SET_COUNTRY, strlen(CMD_SET_COUNTRY)) &&
strncasecmp(command, "country_set", strlen("country_set"))) {
skip = strlen(CMD_SET_COUNTRY) + 1;
country = command + skip;
if (!country || strlen(country) < RWNX_COUNTRY_CODE_LEN) {
@@ -1497,10 +1964,24 @@ int android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
#else
wiphy_apply_custom_regulatory(vif->rwnx_hw->wiphy, regdomain);
#endif
#ifdef CONFIG_RADAR_OR_IR_DETECT
rwnx_radar_set_domain(&vif->rwnx_hw->radar, regdomain->dfs_region);
#endif
#ifdef CONFIG_POWER_LIMIT
if (!testmode){
rwnx_send_me_chan_config_req(vif->rwnx_hw, country);
}
#endif
ret = 0;
goto exit;
}
#ifdef CONFIG_SET_VENDOR_EXTENSION_IE
else if(!strncasecmp(command, CMD_SET_VENDOR_EX_IE, strlen(CMD_SET_VENDOR_EX_IE))){
set_vendor_extension_ie(command);
ret = 0;
goto exit;
}
#endif//CONFIG_SET_VENDOR_EXTENSION_IE
else if(!strncasecmp(command, CMD_SET_AP_WPS_P2P_IE, strlen(CMD_SET_AP_WPS_P2P_IE))){
@@ -1510,7 +1991,9 @@ int android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
if(g_rwnx_plat && g_rwnx_plat->usbdev->rwnx_hw){
if (g_rwnx_plat->usbdev->chipid == PRODUCT_ID_AIC8800DW ||
(g_rwnx_plat->usbdev->chipid == PRODUCT_ID_AIC8800DC) ||
(g_rwnx_plat->usbdev->chipid == PRODUCT_ID_AIC8800D81)){
(g_rwnx_plat->usbdev->chipid == PRODUCT_ID_AIC8800D81) ||
(g_rwnx_plat->usbdev->chipid == PRODUCT_ID_AIC8800D81X2) ||
(g_rwnx_plat->usbdev->chipid == PRODUCT_ID_AIC8800D89X2)){
set_testmode(!testmode);
rwnx_send_reboot(g_rwnx_plat->usbdev->rwnx_hw);
}
@@ -1525,10 +2008,46 @@ int android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
ret = 0;
goto exit;
}
#ifdef CONFIG_RWNX_MON_DATA
else if(!strncasecmp(command, CMD_SET_MON_FREQ, strlen(CMD_SET_MON_FREQ))){
char *set_parameter;
skip = strlen(CMD_SET_MON_FREQ) + 1;
set_parameter = command + skip;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 13, 0))
set_mon_chan(vif, net, set_parameter);
#else
set_mon_chan(vif, set_parameter);
#endif
ret = 0;
goto exit;
}
#endif
else if(!strncasecmp(command, CMD_GET_CS_INFO, strlen(CMD_GET_CS_INFO))) {
u8 mac_addr[6];
u8 val[128];
int i;
u8 *offset;
AICWFDBG(LOGDEBUG, "CMD_GET_CS_INFO,len=%d\n", priv_cmd.total_len);
offset = command + (strlen(CMD_GET_CS_INFO) + 1);
for(i=0; i<6; i++) {
mac_addr[i] = command_strtoul(offset, NULL, 16);
offset += 3;
}
bytes_written = get_cs_info(vif, mac_addr, val);
AICWFDBG(LOGDEBUG, "bytewritten=%d, addr=%pM\n", bytes_written, mac_addr);
memcpy(command, val, bytes_written);
goto exit;
}
#endif//Handle Android command
bytes_written = handle_private_cmd(net, command, priv_cmd.total_len);
exit:
if (bytes_written >= 0) {
if ((bytes_written == 0) && (priv_cmd.total_len > 0)) {
command[0] = '\0';
@@ -1541,7 +2060,7 @@ int android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
bytes_written++;
priv_cmd.used_len = bytes_written;
if (copy_to_user(priv_cmd.buf, command, bytes_written)) {
AICWFDBG(LOGERROR, "%s: failed to copy data to user buffer\n", __FUNCTION__);
AICWFDBG(LOGINFO, "%s: failed to copy data to user buffer\n", __FUNCTION__);
ret = -EFAULT;
}
}
@@ -1550,7 +2069,6 @@ int android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
ret = bytes_written;
}
exit:
///todo: add our unlock
//net_os_wake_unlock(net);
kfree(command);
@@ -19,6 +19,35 @@ typedef struct _android_wifi_priv_cmd {
int total_len;
} android_wifi_priv_cmd;
struct aicwf_cs_info {
u8_l phymode;
u8_l bandwidth;
u16_l freq;
s8_l rssi;
s8_l snr;
s8_l noise;
u8_l txpwr;
//chanutil
u16_l chan_time_ms;
u16_l chan_time_busy_ms;
char countrycode[4];
u8_l rxnss;
u8_l rxmcs;
u8_l txnss;
u8_l txmcs;
u32_l tx_phyrate;
u32_l rx_phyrate;
u32_l tx_ack_succ_stat;
u32_l tx_ack_fail_stat;
u16_l chan_tx_busy_time;
};
#ifdef CONFIG_COMPAT
typedef struct _compat_android_wifi_priv_cmd {
compat_caddr_t buf;
@@ -28,6 +57,8 @@ typedef struct _compat_android_wifi_priv_cmd {
#endif /* CONFIG_COMPAT */
int android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd);
int get_cs_info(struct rwnx_vif *vif, u8 *mac_addr, u8 *val);
#endif /* _AIC_PRIV_CMD_H_ */
+11
View File
@@ -314,17 +314,28 @@ out_put_fail:
return -EMSGSIZE;
}
struct ieee80211_regdomain *getRegdomainFromRwnxDB(struct wiphy *wiphy, char *alpha2);
static int aicwf_vendor_subcmd_set_country_code(struct wiphy *wiphy, struct wireless_dev *wdev,
const void *data, int len)
{
int ret = 0, rem, type;
const struct nlattr *iter;
struct ieee80211_regdomain *regdomain;
nla_for_each_attr(iter, data, len, rem) {
type = nla_type(iter);
switch (type) {
case ANDR_WIFI_ATTRIBUTE_COUNTRY:
printk("%s(%d), ANDR_WIFI_ATTRIBUTE_COUNTRY: %s\n", __func__, __LINE__, (char *)nla_data(iter));
regdomain = getRegdomainFromRwnxDB(wiphy, (char *)nla_data(iter));
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
if((ret = regulatory_set_wiphy_regd(wiphy, regdomain))){
AICWFDBG(LOGERROR, "regulatory_set_wiphy_regd fail \r\n");
}
#else
wiphy_apply_custom_regulatory(wiphy, regdomain);
#endif
break;
default:
pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type);
@@ -3,6 +3,9 @@
#include "reg_access.h"
#define FW_USERCONFIG_NAME_8800D80 "aic_userconfig_8800d80.txt"
#define FW_USERCONFIG_NAME_8800D80_U11 "aic_userconfig_8800d80_u11.txt"
#define FW_USERCONFIG_NAME_8800D80_U11_PRO "aic_userconfig_8800d80_u11_pro.txt"
#define FW_USERCONFIG_NAME_8800D80_U11_CUS "aic_userconfig_8800d80_u11_cus.txt"
#define FW_POWERLIMIT_NAME_8800D80 "aic_powerlimit_8800d80.txt"
extern char aic_fw_path[200];
@@ -37,6 +40,18 @@ int rwnx_plat_userconfig_load_8800d80(struct rwnx_hw *rwnx_hw){
int size;
u32 *dst=NULL;
char *filename = FW_USERCONFIG_NAME_8800D80;
if (rwnx_hw->usbdev->pid == USB_PRODUCT_ID_TENDA_U11
|| rwnx_hw->usbdev->pid == USB_PRODUCT_ID_AIC8800M80_CUS1
|| rwnx_hw->usbdev->pid == USB_PRODUCT_ID_AIC8800M80_CUS4) {
filename = FW_USERCONFIG_NAME_8800D80_U11;
} else if (rwnx_hw->usbdev->pid == USB_PRODUCT_ID_TENDA_U11_PRO
|| rwnx_hw->usbdev->pid == USB_PRODUCT_ID_AIC8800M80_CUS3
|| rwnx_hw->usbdev->pid == USB_PRODUCT_ID_AIC8800M80_CUS5
|| rwnx_hw->usbdev->pid == USB_PRODUCT_ID_AIC8800M80_CUS6) {
filename = FW_USERCONFIG_NAME_8800D80_U11_PRO;
} else if (rwnx_hw->usbdev->pid == USB_PRODUCT_ID_AIC8800M80_CUS2) {
filename = FW_USERCONFIG_NAME_8800D80_U11_CUS;
}
#ifndef ANDROID_PLATFORM
sprintf(aic_fw_path, "%s/%s", aic_fw_path, "aic8800D80");
@@ -65,7 +80,7 @@ int rwnx_plat_userconfig_load_8800d80(struct rwnx_hw *rwnx_hw){
}
#ifdef CONFIG_POWER_LIMIT
extern char default_ccode[];
extern char country_code[];
int rwnx_plat_powerlimit_load_8800d80(struct rwnx_hw *rwnx_hw)
{
int size;
@@ -85,7 +100,7 @@ int rwnx_plat_powerlimit_load_8800d80(struct rwnx_hw *rwnx_hw)
AICWFDBG(LOGINFO, "### Load file done: %s, size=%d\n", filename, size);
/* parsing the file */
rwnx_plat_powerlimit_parsing((char *)dst, size, default_ccode);
rwnx_plat_powerlimit_parsing((char *)dst, size, country_code);
rwnx_release_firmware_common(&dst);
@@ -0,0 +1,97 @@
#include "rwnx_main.h"
#include "rwnx_msg_tx.h"
#include "reg_access.h"
#define FW_USERCONFIG_NAME_8800D80X2 "aic_userconfig_8800d80x2.txt"
#define FW_POWERLIMIT_NAME_8800D80X2 "aic_powerlimit_8800d80x2.txt"
extern char aic_fw_path[200];
int rwnx_request_firmware_common(struct rwnx_hw *rwnx_hw,
u32** buffer, const char *filename);
void rwnx_plat_userconfig_parsing_8800d80x2(char *buffer, int size);
void rwnx_plat_userconfig_parsing(char *buffer, int size);
void rwnx_release_firmware_common(u32** buffer);
int aicwf_set_rf_config_8800d80x2(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm)
{
int ret = 0;
if ((ret = rwnx_send_txpwr_lvl_v4_req(rwnx_hw))) {
return -1;
}
if ((ret = rwnx_send_txpwr_lvl_adj_req(rwnx_hw))) {
return -1;
}
if ((ret = rwnx_send_txpwr_ofst2x_v2_req(rwnx_hw))) {
return -1;
}
if ((ret = rwnx_send_rf_calib_req(rwnx_hw, cfm))) {
return -1;
}
return 0 ;
}
int rwnx_plat_userconfig_load_8800d80x2(struct rwnx_hw *rwnx_hw){
int size;
u32 *dst=NULL;
char *filename = FW_USERCONFIG_NAME_8800D80X2;
#ifndef ANDROID_PLATFORM
sprintf(aic_fw_path, "%s/%s", aic_fw_path, "aic8800D80X2");
#endif
AICWFDBG(LOGINFO, "userconfig file path:%s \r\n", filename);
/* load file */
size = rwnx_request_firmware_common(rwnx_hw, &dst, filename);
if (size <= 0) {
AICWFDBG(LOGERROR, "wrong size of firmware file\n");
dst = NULL;
return 0;
}
/* Copy the file on the Embedded side */
AICWFDBG(LOGINFO, "### Load file done: %s, size=%d\n", filename, size);
rwnx_plat_userconfig_parsing_8800d80x2((char *)dst, size);
rwnx_release_firmware_common(&dst);
AICWFDBG(LOGINFO, "userconfig download complete\n\n");
return 0;
}
#ifdef CONFIG_POWER_LIMIT
extern char country_code[];
int rwnx_plat_powerlimit_load_8800d80x2(struct rwnx_hw *rwnx_hw)
{
int size;
u32 *dst=NULL;
char *filename = FW_POWERLIMIT_NAME_8800D80X2;
AICWFDBG(LOGINFO, "powerlimit file path:%s \r\n", filename);
/* load file */
size = rwnx_request_firmware_common(rwnx_hw, &dst, filename);
if (size <= 0) {
AICWFDBG(LOGERROR, "wrong size of cfg file\n");
dst = NULL;
return 0;
}
AICWFDBG(LOGINFO, "### Load file done: %s, size=%d\n", filename, size);
/* parsing the file */
rwnx_plat_powerlimit_parsing((char *)dst, size, country_code);
rwnx_release_firmware_common(&dst);
AICWFDBG(LOGINFO, "powerlimit download complete\n\n");
return 0;
}
#endif
@@ -0,0 +1,9 @@
#include <linux/types.h>
int rwnx_plat_userconfig_load_8800d80x2(struct rwnx_hw *rwnx_hw);
#ifdef CONFIG_POWER_LIMIT
int rwnx_plat_powerlimit_load_8800d80x2(struct rwnx_hw *rwnx_hw);
#endif
int aicwf_set_rf_config_8800d80x2(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm);
@@ -45,6 +45,8 @@
#define FW_USERCONFIG_NAME_8800DW "aic_userconfig_8800dw.txt"
#define FW_POWERLIMIT_NAME_8800DC "aic_powerlimit_8800dc.txt"
#define FW_POWERLIMIT_NAME_8800DW "aic_powerlimit_8800dw.txt"
#define FW_USERCONFIG_NAME_8800DW_W311 "aic_userconfig_8800dw_w311.txt"
#define FW_USERCONFIG_NAME_8800DW_U2 "aic_userconfig_8800dw_u2.txt"
#ifdef CONFIG_LOAD_BT_PATCH_IN_FDRV
enum aicbt_patch_table_type {
@@ -240,6 +242,7 @@ u32 syscfg_tbl_8800dc[][2] = {
u32 patch_tbl_wifisetting[][2] =
{
{0x0004, 0x00020010}, //wdt_reboot_type, wdt_period_sec
#if !defined(CONFIG_FPGA_VERIFICATION)
{0x0090, 0x0013FC00}, //rx_ringbuf_start2
#endif
@@ -248,6 +251,10 @@ u32 patch_tbl_wifisetting[][2] =
{0x0120, 0x140A0100}, //usb agg tx params(total cnt, aggr cnt, out en, global out nak)
#endif //CONFIG_USB_TX_AGGR
{0x00b0, 0xAD180100},
#ifdef CONFIG_BAND_STEERING
{0x0138, 0x00010a00}, //apm probe resp offload en
#endif
{0x0084, 0x00000040},
};
u32 jump_tbl[][2] =
@@ -1453,6 +1460,7 @@ uint32_t agc_cfg_ram[] = {
0x00000000
};
#if !defined(CONFIG_EXT_FEM_8800DCDW)
uint32_t txgain_map[96] = {
#ifdef CONFIG_FPGA_VERIFICATION
0x20c0c971,
@@ -1632,9 +1640,9 @@ uint32_t txgain_map[96] = {
0x00ffcd70,
0x00ffcd80,
0x00ffcd90,
0x00ffce80,
0x00ffce93,
0x00ffcf90,
0x00ffcf68,
0x00ffcf75,
0x00ffcf83,
0x00ffc080,
0x00ffc090,
0x00ffc180,
@@ -1733,8 +1741,8 @@ const uint32_t txgain_map_h[96] =
0xffcc6b, //15
0xffcc79, //16
0xffcd72, //17
0xffce60, //18
0xffce72, //19
0xffcf5b, //18
0xffcf66, //19
0xffcf72, //20
0xffcf80, //21
0xffcf90, //22
@@ -1757,6 +1765,214 @@ const uint32_t txgain_map_h[96] =
0xffc86b, //7
};
#else /* #ifdef CONFIG_EXT_FEM_8800DCDW */
const uint32_t txgain_map_femkct[96] =
{
//11b
0x00ffd780,//15
0x00ffd872,//16
0x00ffd880,//17
0x00ffd972,//18
0x00ffd980,//19
0x00ffda72,//20
0x00ffda80,//21
0x00ffdb72,//22
0x00ffdb80,//23
0x00ffdc72,//24
0x00ffdc80,//25
0x00ffdd72,//26
0x00ffdd80,//27
0x00ffde72,//28
0x00ffde80,//29
0x00ffdf72,//30
0x00ffd072,//-1
0x00ffd072,//0
0x00ffd080,//1
0x00ffd172,//2
0x00ffd180,//3
0x00ffd272,//4
0x00ffd280,//5
0x00ffd36d,//6
0x00ffd379,//7
0x00ffd46d,//8
0x00ffd479,//9
0x00ffd572,//10
0x00ffd580,//11
0x00ffd672,//12
0x00ffd680,//13
0x00ffd772,//14
//high
0x00ffc872,//11
0x00ffc880,//12
0x00ffc972,//13
0x00ffc980,//14
0x00ffca72,//15
0x00ffca80,//16
0x00ffcb72,//17
0x00ffcb80,//18
0x00ffcc72,//19
0x00ffcc80,//20
0x00ffcd72,//21
0x00ffcd80,//22
0x00ffce72,//23
0x00ffce80,//24
0x00ffcf72,//25
0x00ffcf80,//26
0x00ffc072,//-5
0x00ffc080,//-4
0x00ffc172,//-3
0x00ffc180,//-2
0x00ffc272,//-1
0x00ffc280,//0
0x00ffc372,//1
0x00ffc380,//2
0x00ffc472,//3
0x00ffc480,//4
0x00ffc572,//5
0x00ffc580,//6
0x00ffc672,//7
0x00ffc680,//8
0x00ffc772,//9
0x00ffc780,//10
//low
0x00ffc872,//11
0x00ffc880,//12
0x00ffc972,//13
0x00ffc980,//14
0x00ffca72,//15
0x00ffca80,//16
0x00ffcb72,//17
0x00ffcb80,//18
0x00ffcc72,//19
0x00ffcc80,//20
0x00ffcd72,//21
0x00ffcd80,//22
0x00ffce72,//23
0x00ffce80,//24
0x00ffcf72,//26
0x00ffcf80,//27
0x00ffc072,//-5
0x00ffc080,//-4
0x00ffc172,//-3
0x00ffc180,//-2
0x00ffc272,//-1
0x00ffc280,//0
0x00ffc372,//1
0x00ffc380,//2
0x00ffc472,//3
0x00ffc480,//4
0x00ffc572,//5
0x00ffc580,//6
0x00ffc672,//7
0x00ffc680,//8
0x00ffc772,//9
0x00ffc780,//10
};
const uint32_t txgain_map_femkct_h[96] =
{
//11b
0x00ffd872,//15
0x00ffd880,//16
0x00ffd972,//17
0x00ffd980,//18
0x00ffd990,//19
0x00ffda72,//20
0x00ffda80,//21
0x00ffdb72,//22
0x00ffdb80,//23
0x00ffdc72,//24
0x00ffdc80,//25
0x00ffdd72,//26
0x00ffdd80,//27
0x00ffde72,//28
0x00ffde80,//29
0x00ffdf72,//30
0x00ffd072,//-1
0x00ffd072,//0
0x00ffd080,//1
0x00ffd172,//2
0x00ffd180,//3
0x00ffd272,//4
0x00ffd280,//5
0x00ffd379,//6
0x00ffd46d,//7
0x00ffd479,//8
0x00ffd572,//9
0x00ffd580,//10
0x00ffd672,//11
0x00ffd680,//12
0x00ffd772,//13
0x00ffd780,//14
//high
0x00ffc880,//11
0x00ffc972,//12
0x00ffc980,//13
0x00ffca72,//14
0x00ffca80,//15
0x00ffcb72,//16
0x00ffcb80,//17
0x00ffcc72,//18
0x00ffcc80,//19
0x00ffcc90,//20
0x00ffcd72,//21
0x00ffcd80,//22
0x00ffce72,//23
0x00ffce80,//24
0x00ffcf72,//25
0x00ffcf80,//26
0x00ffc080,//-5
0x00ffc172,//-4
0x00ffc180,//-3
0x00ffc272,//-2
0x00ffc280,//-1
0x00ffc372,//0
0x00ffc380,//1
0x00ffc472,//2
0x00ffc480,//3
0x00ffc572,//4
0x00ffc580,//5
0x00ffc672,//6
0x00ffc680,//7
0x00ffc772,//8
0x00ffc780,//9
0x00ffc872,//10
//low
0x00ffc880,//11
0x00ffc972,//12
0x00ffc980,//13
0x00ffca72,//14
0x00ffca80,//15
0x00ffcb72,//16
0x00ffcb80,//17
0x00ffcc72,//18
0x00ffcc80,//19
0x00ffcc90,//20
0x00ffcd72,//21
0x00ffcd80,//22
0x00ffce72,//23
0x00ffce80,//24
0x00ffcf72,//25
0x00ffcf80,//26
0x00ffc080,//-5
0x00ffc172,//-4
0x00ffc180,//-3
0x00ffc272,//-2
0x00ffc280,//-1
0x00ffc372,//0
0x00ffc380,//1
0x00ffc472,//2
0x00ffc480,//3
0x00ffc572,//4
0x00ffc580,//5
0x00ffc672,//6
0x00ffc680,//7
0x00ffc772,//8
0x00ffc780,//9
0x00ffc872,//10
};
#endif
u32 patch_tbl_func[][2] =
{
{0x00110054, 0x0018186D}, // same as jump_tbl idx 168
@@ -1770,6 +1986,7 @@ u32 patch_tbl_rf_func[][2] =
};
#if !defined(CONFIG_EXT_FEM_8800DCDW)
u32 wifi_txgain_table_24g_8800dcdw[32] =
{
0xA4B22189, //index 0
@@ -1914,6 +2131,80 @@ u32 wifi_txgain_table_24g_1_8800dcdw_h[32] =
0x00001825,
};
#else /* #ifdef CONFIG_EXT_FEM_8800DCDW */
// ofdm
uint32_t wifi_txgain_table_24g_8800dcdw_femkct[32] = {
0x919221C2, //index 0
0x00007825,
0x899221C3, //index 1
0x00007825,
0x8B9221C3, //index 2
0x00007825,
0x929221C3, //index 3
0x00007825,
0x949221C4, //index 4
0x00007825,
0x969221C4, //index 5
0x00007825,
0x949221C6, //index 6
0x00007825,
0x949221C8, //index 7
0x00007825,
0x9C9221C8, //index 8
0x00007825,
0x9C9221CA, //index 9
0x00007825,
0x9C9221CB, //index 10
0x00007825,
0x939221D5, //index 11
0x00007825,
0x9B9221D7, //index 12
0x00007825,
0xA49221D7, //index 13
0x00007825,
0xA79221D7, //index 14
0x00007825,
0xBD9221D7, //index 15
0x00007825,
};
// 11b
uint32_t wifi_txgain_table_24g_1_8800dcdw_femkct[32] = {
0x836E20C2, //index 0
0x00003024,
0x856E20C2, //index 1
0x00003024,
0x826E20C3, //index 2
0x00003024,
0x836E20C3, //index 3
0x00003024,
0x856E20C3, //index 4
0x00003024,
0x876E20C3, //index 5
0x00003024,
0x8B6E20C3, //index 6
0x00003024,
0x926E20C4, //index 7
0x00003024,
0x9A6E20C4, //index 8
0x00003024,
0x936E20C5, //index 9
0x00003024,
0x936E20C7, //index 10
0x00003024,
0xA16E20C8, //index 11
0x00003024,
0xA16E20CA, //index 12
0x00003024,
0xA26E20CB, //index 13
0x00003024,
0xAA6E20CD, //index 14
0x00003024,
0xAC7220CF, //index 15
0x00003024,
};
#endif
u32 wifi_rxgain_table_24g_20m_8800dcdw[64] = {
0x82f282d1,//index 0
0x9591a324,
@@ -2277,6 +2568,10 @@ err:
rf_misc_ram_lite_t dpd_res;
#endif
#ifdef CONFIG_LOFT_CALIB
rf_misc_ram_lite_t loft_res_local;
#endif
int aicwf_patch_table_load(struct rwnx_hw *rwnx_hw, char *filename)
{
int err = 0;
@@ -2513,11 +2808,21 @@ void aicwf_patch_config_8800dc(struct rwnx_hw *rwnx_hw)
#if !defined(CONFIG_FPGA_VERIFICATION)
if ((IS_CHIP_ID_H())) {
#if defined(CONFIG_EXT_FEM_8800DCDW)
txgain_cfg_size = sizeof(txgain_map_femkct_h);
txgain_cfg_array = (u32 *)txgain_map_femkct_h;
#else
txgain_cfg_size = sizeof(txgain_map_h);
txgain_cfg_array = (u32 *)txgain_map_h;
#endif
} else {
#if defined(CONFIG_EXT_FEM_8800DCDW)
txgain_cfg_size = sizeof(txgain_map_femkct);
txgain_cfg_array = (u32 *)txgain_map_femkct;
#else
txgain_cfg_size = sizeof(txgain_map);
txgain_cfg_array = (u32 *)txgain_map;
#endif
}
ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, txgain_cfg_addr, txgain_cfg_size, txgain_cfg_array);
if (ret) {
@@ -2588,6 +2893,7 @@ int aicwf_set_rf_config_8800dc(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_c
if (testmode == FW_NORMAL_MODE) {
#if !defined(CONFIG_EXT_FEM_8800DCDW)
if (IS_CHIP_ID_H()) {
if ((ret = rwnx_send_rf_config_req(rwnx_hw, 0, 1, (u8_l *)wifi_txgain_table_24g_8800dcdw_h, 128)))
return -1;
@@ -2599,6 +2905,18 @@ int aicwf_set_rf_config_8800dc(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_c
if ((ret = rwnx_send_rf_config_req(rwnx_hw, 16, 1, (u8_l *)wifi_txgain_table_24g_1_8800dcdw, 128)))
return -1;
}
#else /* #ifdef CONFIG_EXT_FEM_8800DCDW */
{
ret = rwnx_send_rf_config_req(rwnx_hw, 0, 1, (u8_l *)wifi_txgain_table_24g_8800dcdw_femkct, 128);
if (ret) {
return -1;
}
ret = rwnx_send_rf_config_req(rwnx_hw, 16, 1, (u8_l *)wifi_txgain_table_24g_1_8800dcdw_femkct, 128);
if (ret) {
return -1;
}
}
#endif
if ((ret = rwnx_send_rf_config_req(rwnx_hw, 0, 0, (u8_l *)wifi_rxgain_table_24g_20m_8800dcdw, 256)))
return -1;
@@ -2629,6 +2947,14 @@ int aicwf_set_rf_config_8800dc(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_c
return ret;
}
}
#elif defined(CONFIG_LOFT_CALIB)
if (loft_res_local.bit_mask[1]) {
ret = aicwf_loft_result_apply_8800dc(rwnx_hw, &loft_res_local);
if (ret) {
AICWFDBG(LOGINFO, "apply loft res fail: %d\n", ret);
return ret;
}
}
#else
{
ret = aicwf_misc_ram_init_8800dc(rwnx_hw);
@@ -2703,7 +3029,7 @@ int aicwf_plat_rftest_load_8800dc(struct rwnx_hw *rwnx_hw)
return ret;
}
#ifdef CONFIG_DPD
#if defined(CONFIG_DPD) || defined(CONFIG_LOFT_CALIB)
int aicwf_misc_ram_valid_check_8800dc(struct rwnx_hw *rwnx_hw, int *valid_out)
{
int ret = 0;
@@ -2712,35 +3038,54 @@ int aicwf_misc_ram_valid_check_8800dc(struct rwnx_hw *rwnx_hw, int *valid_out)
uint32_t misc_ram_addr;
uint32_t ram_base_addr, ram_word_cnt;
uint32_t bit_mask[4];
uint32_t dpd_info_read_addr = 0xfe004;
uint32_t boot_argc_read_addr = 0x1220f0;
uint32_t flash_size_mem_addr = 0x40038030;
uint8_t flash_size = 0;
int i;
if (valid_out) {
*valid_out = 0;
}
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, boot_argc_read_addr, &cfm);
if (ret) {
AICWFDBG(LOGERROR, "boot argc [0x%x] rd fail: %d\n", boot_argc_read_addr, ret);
return ret;
}
printk("boot argc %x\n", cfm.memdata);
if (cfm.memdata & 0x10) {
*valid_out = 1;
return ret;
}
if (chip_mcu_id) {
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, flash_size_mem_addr, &cfm);
if (ret) {
AICWFDBG(LOGERROR, "flash size[0x%x] rd fail: %d\n", flash_size_mem_addr, ret);
return ret;
}
flash_size = cfm.memdata & 0xff;
printk("flash size %x\n", flash_size);
if (flash_size == 0x16) {
dpd_info_read_addr += 0x4300000;
} else if (flash_size == 0x15) {
dpd_info_read_addr += 0x4100000;
} else if (flash_size == 0x18) {
dpd_info_read_addr += 0x4700000;
} else {
dpd_info_read_addr += 0x4100000;
}
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, dpd_info_read_addr, &cfm);
if (ret) {
AICWFDBG(LOGERROR, "dpd info [0x%x] rd fail: %d\n", dpd_info_read_addr, ret);
return ret;
}
if (cfm.memdata & (1<<7)) {
if (valid_out) {
*valid_out = 1;
}
}
} else {
if (testmode == FW_RFTEST_MODE) {
uint32_t vect1 = 0;
uint32_t vect2 = 0;
cfg_base = RAM_LMAC_FW_ADDR + 0x0004;
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base, &cfm);
if (ret) {
AICWFDBG(LOGERROR, "cfg_base:%x vcet1 rd fail: %d\n", cfg_base, ret);
return ret;
}
vect1 = cfm.memdata;
if ((vect1 & 0xFFFF0000) != (RAM_LMAC_FW_ADDR & 0xFFFF0000)) {
AICWFDBG(LOGERROR, "vect1 invalid: %x\n", vect1);
return ret;
}
cfg_base = RAM_LMAC_FW_ADDR + 0x0008;
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base, &cfm);
if (ret) {
AICWFDBG(LOGERROR, "cfg_base:%x vcet2 rd fail: %d\n", cfg_base, ret);
return ret;
}
vect2 = cfm.memdata;
if ((vect2 & 0xFFFF0000) != (RAM_LMAC_FW_ADDR & 0xFFFF0000)) {
AICWFDBG(LOGERROR, "vect2 invalid: %x\n", vect2);
return ret;
}
cfg_base = RAM_LMAC_FW_ADDR + 0x0164;
}
// init misc ram
@@ -2769,6 +3114,7 @@ int aicwf_misc_ram_valid_check_8800dc(struct rwnx_hw *rwnx_hw, int *valid_out)
*valid_out = 1;
}
}
}
return ret;
}
@@ -2879,7 +3225,7 @@ int aicwf_dpd_calib_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *dpd_res)
for (i = 0; i < ram_word_cnt; i++) {
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, ram_base_addr + i * 4, &cfm);
if (ret) {
AICWFDBG(LOGERROR, "bit_mask[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret);
AICWFDBG(LOGERROR, "dpd_high[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret);
return ret;
}
dpd_res->dpd_high[i] = cfm.memdata;
@@ -2890,7 +3236,7 @@ int aicwf_dpd_calib_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *dpd_res)
for (i = 0; i < ram_word_cnt; i++) {
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, ram_base_addr + i * 4, &cfm);
if (ret) {
AICWFDBG(LOGERROR, "bit_mask[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret);
AICWFDBG(LOGERROR, "loft_res[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret);
return ret;
}
dpd_res->loft_res[i] = cfm.memdata;
@@ -3023,6 +3369,117 @@ int aicwf_dpd_result_write_8800dc(void *buf, int buf_len)
#endif /* !CONFIG_FORCE_DPD_CALIB */
#endif
#ifdef CONFIG_LOFT_CALIB
int aicwf_loft_calib_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *loft_res)
{
int ret = 0;
uint32_t fw_addr, boot_type;
int valid_flag;
ret = aicwf_misc_ram_valid_check_8800dc(rwnx_hw, &valid_flag);
if (ret) {
AICWFDBG(LOGINFO, "misc ram check fail: %d\n", ret);
return ret;
}
if (valid_flag) {
AICWFDBG(LOGINFO, "misc ram valid, skip calib process\n");
return ret;
}
ret = aicwf_plat_calib_load_8800dc(rwnx_hw);
if (ret) {
AICWFDBG(LOGINFO, "load calib bin fail: %d\n", ret);
return ret;
}
/* fw start */
fw_addr = 0x00130009;
boot_type = HOST_START_APP_FNCALL;
AICWFDBG(LOGINFO, "Start app: %08x, %d\n", fw_addr, boot_type);
ret = rwnx_send_dbg_start_app_req(rwnx_hw, fw_addr, boot_type);
if (ret) {
AICWFDBG(LOGINFO, "start app fail: %d\n", ret);
return ret;
}
{ // read loft res
const uint32_t cfg_base = 0x10164;
struct dbg_mem_read_cfm cfm;
uint32_t misc_ram_addr;
uint32_t ram_base_addr, ram_word_cnt;
int i;
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0x14, &cfm);
if (ret) {
AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret);
return ret;
}
misc_ram_addr = cfm.memdata;
// bit_mask
ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask);
ram_word_cnt = (MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved)) / 4;
for (i = 0; i < ram_word_cnt; i++) {
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, ram_base_addr + i * 4, &cfm);
if (ret) {
AICWFDBG(LOGERROR, "bit_mask[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret);
return ret;
}
loft_res->bit_mask[i] = cfm.memdata;
}
// loft_res
ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, loft_res);
ram_word_cnt = MEMBER_SIZE(rf_misc_ram_t, loft_res) / 4;
for (i = 0; i < ram_word_cnt; i++) {
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, ram_base_addr + i * 4, &cfm);
if (ret) {
AICWFDBG(LOGERROR, "loft_res[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret);
return ret;
}
loft_res->loft_res[i] = cfm.memdata;
}
}
return ret;
}
int aicwf_loft_result_apply_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *loft_res)
{
int ret = 0;
uint32_t cfg_base = 0x10164;
struct dbg_mem_read_cfm cfm;
uint32_t misc_ram_addr;
uint32_t ram_base_addr, ram_byte_cnt;
AICWFDBG(LOGINFO, "bit_mask[1]=%x\n", loft_res->bit_mask[1]);
if (loft_res->bit_mask[1] == 0) {
AICWFDBG(LOGERROR, "void loft_res, bypass it.\n");
return 0;
}
if (testmode == FW_RFTEST_MODE) {
cfg_base = RAM_LMAC_FW_ADDR + 0x0164;
}
if ((ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0x14, &cfm))) {
AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, ret);
return ret;
}
misc_ram_addr = cfm.memdata;
AICWFDBG(LOGINFO, "misc_ram_addr: %x\n", misc_ram_addr);
/* Copy loft_res on the Embedded side */
// bit_mask
AICWFDBG(LOGINFO, "bit_mask[0]=%x\n", loft_res->bit_mask[0]);
ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, bit_mask);
ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, bit_mask) + MEMBER_SIZE(rf_misc_ram_t, reserved);
ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ram_base_addr, ram_byte_cnt, (u32 *)&loft_res->bit_mask[0]);
if (ret) {
AICWFDBG(LOGERROR, "bit_mask wr fail: %x, ret:%d\r\n", ram_base_addr, ret);
return ret;
}
// loft_res
AICWFDBG(LOGINFO, "loft_res[0]=%x\n", loft_res->loft_res[0]);
ram_base_addr = misc_ram_addr + offsetof(rf_misc_ram_t, loft_res);
ram_byte_cnt = MEMBER_SIZE(rf_misc_ram_t, loft_res);
ret = rwnx_send_dbg_mem_block_write_req(rwnx_hw, ram_base_addr, ram_byte_cnt, (u32 *)&loft_res->loft_res[0]);
if (ret) {
AICWFDBG(LOGERROR, "loft_res wr fail: %x, ret:%d\r\n", ram_base_addr, ret);
return ret;
}
return ret;
}
#endif
int rwnx_plat_userconfig_load_8800dc(struct rwnx_hw *rwnx_hw){
int size;
u32 *dst=NULL;
@@ -3054,6 +3511,14 @@ int rwnx_plat_userconfig_load_8800dw(struct rwnx_hw *rwnx_hw){
int size;
u32 *dst=NULL;
char *filename = FW_USERCONFIG_NAME_8800DW;
if (rwnx_hw->usbdev->pid == USB_PRODUCT_ID_TENDA) {
filename = FW_USERCONFIG_NAME_8800DW_W311;
} else if (rwnx_hw->usbdev->pid == USB_PRODUCT_ID_TENDA_U2
|| rwnx_hw->usbdev->pid == USB_PRODUCT_ID_AIC8800FC_CUS1
|| rwnx_hw->usbdev->pid == USB_PRODUCT_ID_AIC8800FC_CUS2
|| rwnx_hw->usbdev->pid == USB_PRODUCT_ID_AIC8800FC_CUS3) {
filename = FW_USERCONFIG_NAME_8800DW_U2;
}
AICWFDBG(LOGINFO, "userconfig file path:%s \r\n", filename);
@@ -3078,7 +3543,7 @@ int rwnx_plat_userconfig_load_8800dw(struct rwnx_hw *rwnx_hw){
}
#ifdef CONFIG_POWER_LIMIT
extern char default_ccode[];
extern char country_code[];
int rwnx_plat_powerlimit_load_8800dcdw(struct rwnx_hw *rwnx_hw, uint16_t chip_id)
{
@@ -3107,7 +3572,7 @@ int rwnx_plat_powerlimit_load_8800dcdw(struct rwnx_hw *rwnx_hw, uint16_t chip_id
/* Copy the file on the Embedded side */
AICWFDBG(LOGINFO, "### Load file done: %s, size=%d\n", filename, size);
rwnx_plat_powerlimit_parsing((char *)dst, size, default_ccode);
rwnx_plat_powerlimit_parsing((char *)dst, size, country_code);
rwnx_release_firmware_common(&dst);
@@ -3162,6 +3627,7 @@ void system_config_8800dc(struct rwnx_hw *rwnx_hw){
array3_tbl_t p_syscfg_msk_tbl;
int ret, cnt;
const u32 mem_addr = 0x40500000;
const u32 cache_mem_addr = 0x40100020;
struct dbg_mem_read_cfm rd_mem_addr_cfm;
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, mem_addr, &rd_mem_addr_cfm);
@@ -3175,6 +3641,21 @@ void system_config_8800dc(struct rwnx_hw *rwnx_hw){
chip_mcu_id = 1;
}
if (chip_mcu_id) {
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cache_mem_addr, &rd_mem_addr_cfm);
if (ret) {
AICWFDBG(LOGERROR, "%x rd fail: %d\n", mem_addr, ret);
return;
}
rd_mem_addr_cfm.memdata |= 0x01;
ret = rwnx_send_dbg_mem_write_req(rwnx_hw, cache_mem_addr, rd_mem_addr_cfm.memdata);
if (ret) {
AICWFDBG(LOGERROR, "%x write fail: %d\n", cache_mem_addr, ret);
return;
}
}
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, 0x00000020, &rd_mem_addr_cfm);
if (ret) {
AICWFDBG(LOGERROR, "[0x00000020] rd fail: %d\n", ret);
@@ -1,6 +1,6 @@
#include <linux/types.h>
#ifdef CONFIG_DPD
#if defined(CONFIG_DPD) || defined(CONFIG_LOFT_CALIB)
typedef struct {
uint32_t bit_mask[3];
uint32_t reserved;
@@ -22,17 +22,25 @@ typedef struct {
#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
#define DPD_RESULT_SIZE_8800DC sizeof(rf_misc_ram_lite_t)
#endif
#ifdef CONFIG_DPD
extern rf_misc_ram_lite_t dpd_res;
#endif
#ifdef CONFIG_LOFT_CALIB
extern rf_misc_ram_lite_t loft_res_local;
#endif
int aicwf_patch_table_load(struct rwnx_hw *rwnx_hw, char *filename);
void aicwf_patch_config_8800dc(struct rwnx_hw *rwnx_hw);
int aicwf_set_rf_config_8800dc(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm);
int aicwf_misc_ram_init_8800dc(struct rwnx_hw *rwnx_hw);
#ifdef CONFIG_DPD
#if defined(CONFIG_DPD) || defined(CONFIG_LOFT_CALIB)
int aicwf_misc_ram_valid_check_8800dc(struct rwnx_hw *rwnx_hw, int *valid_out);
int aicwf_plat_calib_load_8800dc(struct rwnx_hw *rwnx_hw);
#endif
#ifdef CONFIG_DPD
int aicwf_dpd_calib_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *dpd_res);
int aicwf_dpd_result_apply_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *dpd_res);
#ifndef CONFIG_FORCE_DPD_CALIB
@@ -40,6 +48,10 @@ int aicwf_dpd_result_load_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *dp
int aicwf_dpd_result_write_8800dc(void *buf, int buf_len);
#endif
#endif
#ifdef CONFIG_LOFT_CALIB
int aicwf_loft_calib_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *loft_res);
int aicwf_loft_result_apply_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *loft_res);
#endif
int aicwf_plat_patch_load_8800dc(struct rwnx_hw *rwnx_hw);
int aicwf_plat_rftest_load_8800dc(struct rwnx_hw *rwnx_hw);
int rwnx_plat_userconfig_load_8800dc(struct rwnx_hw *rwnx_hw);
@@ -10,6 +10,7 @@
#define LOGTRACE 0x0004
#define LOGDEBUG 0x0008
#define LOGDATA 0x0010
#define LOGSTEER 0x0020
extern int aicwf_dbg_level;
void rwnx_data_dump(char* tag, void* data, unsigned long len);
@@ -0,0 +1,601 @@
/**
******************************************************************************
*
* Copyright (C) 2020 AIC semiconductor.
*
* @file aicwf_manager.c
*
* @brief netlink msg definitions
*
******************************************************************************
*/
#include <linux/module.h>
#include <linux/netlink.h>
#include <net/sock.h>
#include "aicwf_manager.h"
#include "lmac_mac.h"
#include "aicwf_debug.h"
#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
#define MAC_ARG(x) ((u8_l *)(x))[0], ((u8_l *)(x))[1], ((u8_l *)(x))[2], ((u8_l *)(x))[3], ((u8_l *)(x))[4], ((u8_l *)(x))[5]
#define MANAGER_STR "[MANAGER] USB "
static struct sock *nl_sock = NULL;
static struct rwnx_vif *nl_rwnx_vif[PHY_BAND_MAX][CONFIG_IFACE_NUMBER] = {{NULL}};
static u8_l nl_hook[PHY_BAND_MAX][CONFIG_IFACE_NUMBER] = {{0}};
static u8_l nl_daemon_on = 0;
#define FREQ_2G_MIN 2412
#define FREQ_2G_MAX 2484
#define FREQ_5G_MIN 5170
#define FREQ_5G_MAX 5825
#define FREQ_6G_MIN 5925
#define FREQ_6G_MAX 7125
static int freq_to_channel(int freq)
{
if (freq >= FREQ_2G_MIN && freq <= FREQ_2G_MAX) {
if (freq == 2484) {
return 14;
} else {
return (freq - 2412) / 5 + 1;
}
} else if (freq >= FREQ_5G_MIN && freq <= FREQ_5G_MAX) {
return (freq - 5000) / 5;
} else if (freq >= FREQ_6G_MIN && freq <= FREQ_6G_MAX) {
return (freq - 5950) / 5;
} else {
AICWFDBG(LOGERROR, MANAGER_STR"aic Unsupported frequency: %d MHz\n", freq);
return -1;
}
}
void aicwf_nl_recv_msg(struct sk_buff *skb)
{
struct rwnx_vif *rwnx_vif;
struct rwnx_sta *sta = NULL;
u8_l rwnx_hook = 0;
u8_l band;
u8_l ssid;
struct nlmsghdr *nlh = NULL;
struct b_nl_message *msg = NULL;
struct b_elm_header *hdr = NULL;
struct b_elm_intf *intf = NULL;
struct b_elm_sta_info *sta_info = NULL;
struct b_elm_roam_info *roam_info = NULL;
u32 offset = 0;
if (skb == NULL) {
AICWFDBG(LOGERROR, MANAGER_STR"skb is null.\n");
return;
}
nlh = (struct nlmsghdr *)skb->data;
msg = (struct b_nl_message *)NLMSG_DATA(nlh);
AICWFDBG(LOGSTEER, MANAGER_STR"%s, %d\n", __func__, msg->type);
/* message type */
switch(msg->type) {
case AIC_NL_DAEMON_ON_TYPE:
nl_daemon_on = 1;
AICWFDBG(LOGSTEER, MANAGER_STR"AIC_NL_DAEMON_ON_TYPE\n");
for (band = 0; band < PHY_BAND_MAX; band++) {
for (ssid = 0; ssid < CONFIG_IFACE_NUMBER; ssid++) {
rwnx_vif = nl_rwnx_vif[band][ssid];
rwnx_hook = nl_hook[band][ssid];
if (!rwnx_hook) {
AICWFDBG(LOGSTEER, MANAGER_STR"%s, !rwnx_hook, %d,%d\n", __func__, band, ssid);
continue;
}
if (rwnx_vif == NULL || rwnx_vif->up == false) {
AICWFDBG(LOGSTEER, MANAGER_STR"%s, !rwnx_vif, %d,%d\n", __func__, band, ssid);
continue;
}
#ifdef CONFIG_BAND_STEERING
aicwf_band_steering_init(rwnx_vif);
#endif
spin_lock_bh(&rwnx_vif->rwnx_hw->cb_lock);
list_for_each_entry(sta, &rwnx_vif->ap.sta_list, list){
if (sta->valid)
aicwf_nl_send_new_sta_msg(rwnx_vif, sta->mac_addr);
}
spin_unlock_bh(&rwnx_vif->rwnx_hw->cb_lock);
}
}
break;
case AIC_NL_DAEMON_OFF_TYPE:
nl_daemon_on = 0;
break;
#ifdef CONFIG_BAND_STEERING
case AIC_NL_B_STEER_BLOCK_ADD_TYPE:
case AIC_NL_B_STEER_BLOCK_DEL_TYPE:
while (offset < msg->len) {
hdr = (struct b_elm_header *)(msg->content + offset);
offset += ELM_HEADER_LEN;
switch(hdr->id) {
case AIC_ELM_INTF_ID:
intf = (struct b_elm_intf *)(msg->content + offset);
break;
case AIC_ELM_STA_INFO_ID:
sta_info = (struct b_elm_sta_info *)(msg->content + offset);
break;
default:
AICWFDBG(LOGERROR, MANAGER_STR"unknown element id.\n");
break;
}
offset += hdr->len;
}
if (intf && sta_info) {
band = intf->band;
ssid = intf->ssid;
AICWFDBG(LOGSTEER, MANAGER_STR"STEER_BLOCK band: %d, ssid: %d\n", band, ssid);
rwnx_vif = nl_rwnx_vif[band][ssid];
rwnx_hook = nl_hook[band][ssid];
if (!rwnx_hook) {
AICWFDBG(LOGSTEER, MANAGER_STR"rwnx_hook is null p1.\n");
break;
}
if (rwnx_vif == NULL || rwnx_vif->up == false) {
AICWFDBG(LOGSTEER, MANAGER_STR"rwnx_vif is null/down p1.\n");
break;
}
if (msg->type == AIC_NL_B_STEER_BLOCK_ADD_TYPE)
aicwf_band_steering_block_entry_add(rwnx_vif, sta_info->mac);
else if (msg->type == AIC_NL_B_STEER_BLOCK_DEL_TYPE)
aicwf_band_steering_block_entry_del(rwnx_vif, sta_info->mac);
}
break;
case AIC_NL_B_STEER_ROAM_TYPE:
while (offset < msg->len) {
hdr = (struct b_elm_header *)(msg->content + offset);
offset += ELM_HEADER_LEN;
/* element type: should handle wrong length */
switch(hdr->id) {
case AIC_ELM_INTF_ID:
intf = (struct b_elm_intf *)(msg->content + offset);
break;
case AIC_ELM_ROAM_INFO_ID:
roam_info = (struct b_elm_roam_info *)(msg->content + offset);
break;
default:
AICWFDBG(LOGERROR, MANAGER_STR"unknown element id.\n");
break;
}
offset += hdr->len;
}
if (intf && roam_info) {
band = intf->band;
ssid = intf->ssid;
rwnx_vif = nl_rwnx_vif[band][ssid];
rwnx_hook = nl_hook[band][ssid];
if (!rwnx_hook) {
AICWFDBG(LOGERROR, MANAGER_STR"rwnx_hook is null p2.\n");
break;
}
if (rwnx_vif == NULL || rwnx_vif->up == false) {
AICWFDBG(LOGERROR, MANAGER_STR"rwnx_vif is null/down p2.\n");
break;
}
AICWFDBG(LOGSTEER, MANAGER_STR"AIC_NL_B_STEER_ROAM_TYPE (hostapd_cli)!\n");
AICWFDBG(LOGSTEER, MANAGER_STR"sta_mac="MAC_FMT"\n", MAC_ARG(roam_info->sta_mac));
AICWFDBG(LOGSTEER, MANAGER_STR"bss_mac="MAC_FMT" bss_ch=%u method=%s\n",
MAC_ARG(roam_info->bss_mac),
roam_info->bss_ch,
roam_info->method == 0 ? "11V" : "Deauth");
if (roam_info->method == 1)
aicwf_band_steering_roam_block_entry_add(rwnx_vif, roam_info->sta_mac);
}
break;
#endif
default:
AICWFDBG(LOGERROR, MANAGER_STR"unknown message type.\n");
break;
}
return;
}
void aicwf_nl_send_msg(void *msg, u32 msg_len)
{
struct nlmsghdr *nlh = NULL;
struct sk_buff *skb = NULL;
u32 skb_len;
s32 err;
skb_len = NLMSG_SPACE(NL_MAX_MSG_SIZE);
skb = __dev_alloc_skb(skb_len, GFP_ATOMIC);
if (!skb) {
AICWFDBG(LOGERROR, MANAGER_STR"allocate skb failed.\n");
goto func_return;
}
nlh = nlmsg_put(skb, 0, 0, 0, NL_MAX_MSG_SIZE, 0);
if (!nlh) {
AICWFDBG(LOGERROR, MANAGER_STR"put netlink header failed.\n");
kfree_skb(skb);
goto func_return;
}
NETLINK_CB(skb).portid = 0;
NETLINK_CB(skb).dst_group = 0;
memset(NLMSG_DATA(nlh), 0, msg_len);
memcpy(NLMSG_DATA(nlh), (u8_l *)msg, msg_len);
if (!nl_sock) {
AICWFDBG(LOGERROR, MANAGER_STR"[%s %u] nl_sock is NULL\n", __FUNCTION__, __LINE__);
goto msg_fail_skb;
}
err = netlink_unicast(nl_sock, skb, NL_AIC_MANAGER_PID, MSG_DONTWAIT);
if (err < 0) {
/* netlink_unicast() already kfree_skb */
AICWFDBG(LOGSTEER, MANAGER_STR"send netlink unicast failed.\n");
goto func_return;
}
func_return:
return;
msg_fail_skb:
kfree_skb(skb);
}
static void aicwf_netlink_set_msg(
struct b_nl_message *msg, u32 *msg_len, void *elm, u32 elm_len)
{
memcpy(msg->content + (*msg_len), elm, elm_len);
(*msg_len) += elm_len;
return;
}
void aicwf_nl_send_del_sta_msg(struct rwnx_vif *rwnx_vif, u8_l *mac)
{
u32 msg_len = 0;
struct b_nl_message msg = {0};
struct b_elm_header hdr = {0};
struct b_elm_intf intf = {{0}};
struct b_elm_sta_info sta_info = {{0}};
if (!nl_daemon_on)
return;
AICWFDBG(LOGSTEER, MANAGER_STR"%s, "MAC_FMT"\n", __func__, MAC_ARG(mac));
/* element header */
hdr.id = AIC_ELM_INTF_ID;
hdr.len = ELM_INTF_LEN;
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
/* element: AIC_ELM_INTF_ID */
intf.root = 0; /* TBD */
intf.band = rwnx_vif->ap.band;
intf.ssid = rwnx_vif->rwnx_hw->iface_idx;
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&intf, ELM_INTF_LEN);
/* element header */
hdr.id = AIC_ELM_STA_INFO_ID;
hdr.len = ELM_STA_INFO_LEN;
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
/* element: AIC_ELM_STA_INFO_ID */
memcpy(sta_info.mac, mac, 6);
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&sta_info, ELM_STA_INFO_LEN);
/* finish message */
msg.type = AIC_NL_DEL_STA_TYPE;
msg.len = msg_len;
/* length += (type + len) */
msg_len += 8;
aicwf_nl_send_msg((void *)&msg, msg_len);
return;
}
void aicwf_nl_send_new_sta_msg(struct rwnx_vif *rwnx_vif, u8_l *mac)
{
u32 msg_len = 0;
struct b_nl_message msg = {0};
struct b_elm_header hdr = {0};
struct b_elm_intf intf = {{0}};
struct b_elm_sta_info sta_info = {{0}};
if (!nl_daemon_on)
return;
AICWFDBG(LOGSTEER, MANAGER_STR"%s, "MAC_FMT"\n", __func__, MAC_ARG(mac));
/* element header */
hdr.id = AIC_ELM_INTF_ID;
hdr.len = ELM_INTF_LEN;
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
/* element: AIC_ELM_INTF_ID */
intf.root = 0; /* TBD */
intf.band = rwnx_vif->ap.band;
intf.ssid = rwnx_vif->rwnx_hw->iface_idx;
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&intf, ELM_INTF_LEN);
/* element header */
hdr.id = AIC_ELM_STA_INFO_ID;
hdr.len = ELM_STA_INFO_LEN;
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
/* element: AIC_ELM_STA_INFO_ID */
memcpy(sta_info.mac, mac, 6);
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&sta_info, ELM_STA_INFO_LEN);
/* finish message */
msg.type = AIC_NL_NEW_STA_TYPE;
msg.len = msg_len;
/* length += (type + len) */
msg_len += 8;
aicwf_nl_send_msg((void *)&msg, msg_len);
return;
}
void aicwf_nl_send_intf_rpt_msg(struct rwnx_vif *rwnx_vif)
{
u32 msg_len = 0;
struct b_nl_message msg = {0};
struct b_elm_header hdr = {0};
struct b_elm_intf intf = {{0}};
struct b_elm_intf_info intf_info = {0};
if (!nl_daemon_on)
return;
/* element header */
hdr.id = AIC_ELM_INTF_ID;
hdr.len = ELM_INTF_LEN;
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
/* element: AIC_ELM_INTF_ID */
memcpy(intf.mac, rwnx_vif->ndev->dev_addr, 6);
intf.root = 0; /* TBD */
intf.band = rwnx_vif->ap.band;
intf.ssid = rwnx_vif->rwnx_hw->iface_idx;
memcpy(intf.name, rwnx_vif->ndev->name, 16);
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&intf, ELM_INTF_LEN);
/* element header */
hdr.id = AIC_ELM_INTF_INFO_ID;
hdr.len = ELM_INTF_INFO_LEN;
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
/* element: AIC_ELM_INTF_INFO_ID */
intf_info.ch = freq_to_channel(rwnx_vif->ap.freq);
intf_info.tx_tp = 0; /* TBD */
intf_info.rx_tp = 0; /* TBD */
intf_info.bss_info = 0;
intf_info.reg_class = (rwnx_vif->ap.band == 0) ? 81 : 128;
intf_info.phy_type = 7;
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&intf_info, ELM_INTF_INFO_LEN);
/* finish message */
msg.type = AIC_NL_INTF_RPT_TYPE;
msg.len = msg_len;
/* length += (type + len) */
msg_len += 8;
aicwf_nl_send_msg((void *)&msg, msg_len);
return;
}
void aicwf_nl_send_sta_rpt_msg(struct rwnx_vif *rwnx_vif, struct rwnx_sta *sta)
{
u32 msg_len = 0;
struct b_nl_message msg = {0};
struct b_elm_header hdr = {0};
struct b_elm_intf intf = {{0}};
struct b_elm_sta_info sta_info = {{0}};
struct b_elm_sta_info_ext sta_info_ext = {{0}};
if (!nl_daemon_on)
return;
/* element header */
hdr.id = AIC_ELM_INTF_ID;
hdr.len = ELM_INTF_LEN;
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
/* element: AIC_ELM_INTF_ID */
memcpy(intf.mac, rwnx_vif->ndev->dev_addr, 6);
intf.root = 0; /* TBD */
intf.band = rwnx_vif->ap.band;
intf.ssid = rwnx_vif->rwnx_hw->iface_idx;
memcpy(intf.name, rwnx_vif->ndev->name, 16);
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&intf, ELM_INTF_LEN);
/* element header */
hdr.id = AIC_ELM_STA_INFO_ID;
hdr.len = ELM_STA_INFO_LEN;
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
/* element: AIC_ELM_STA_INFO_ID */
memcpy(sta_info.mac, sta->mac_addr, 6);
sta_info.rssi = sta->rssi;
sta_info.link_time = sta->link_time;
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&sta_info, ELM_STA_INFO_LEN);
/* element header */
hdr.id = AIC_ELM_STA_INFO_EXT_ID;
hdr.len = ELM_STA_INFO_EXT_LEN;
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
/* element: AIC_ELM_STA_INFO_EXT_ID */
memcpy(sta_info_ext.mac, sta->mac_addr, 6);
sta_info_ext.supported_band = sta->support_band;
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&sta_info_ext, ELM_STA_INFO_EXT_LEN);
/* finish message */
msg.type = AIC_NL_STA_RPT_TYPE;
msg.len = msg_len;
/* length += (type + len) */
msg_len += 8;
aicwf_nl_send_msg((void *)&msg, msg_len);
return;
}
void aicwf_nl_send_frame_rpt_msg(struct rwnx_vif *rwnx_vif, u16_l frame_type, u8_l *sa, s8_l rssi)
{
u32 msg_len = 0;
struct b_nl_message msg = {0};
struct b_elm_header hdr = {0};
struct b_elm_frame_info frame_info = {0};
struct b_elm_intf intf = {{0}};
if (!nl_daemon_on)
return;
//AICWFDBG(LOGSTEER, "[NETLINK] %s, sta: "MAC_FMT"\n", __func__, MAC_ARG(sa));
/* TBD */
if (frame_type == WIFI_PROBEREQ && rssi <= LOW_RSSI_IGNORE) {
AICWFDBG(LOGSTEER, MANAGER_STR"WIFI_PROBEREQ <= %d, ignore\n", LOW_RSSI_IGNORE);
return;
}
/* element header */
hdr.id = AIC_ELM_INTF_ID;
hdr.len = ELM_INTF_LEN;
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
/* element: AIC_ELM_INTF_ID */
intf.root = 0; /* TBD */
intf.band = rwnx_vif->ap.band;
intf.ssid = rwnx_vif->rwnx_hw->iface_idx;
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&intf, ELM_INTF_LEN);
/* element header */
hdr.id = AIC_ELM_FRAME_INFO_ID;
hdr.len = ELM_FRAME_INFO_LEN;
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
/* element: AIC_ELM_FRAME_INFO_ID */
frame_info.frame_type = frame_type;
memcpy(frame_info.sa, sa, 6);
frame_info.rssi = rssi;
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&frame_info, ELM_FRAME_INFO_LEN);
/* finish message */
msg.type = AIC_NL_FRAME_RPT_TYPE;
msg.len = msg_len;
/* length += (type + len) */
msg_len += 8;
aicwf_nl_send_msg((void *)&msg, msg_len);
return;
}
void aicwf_nl_send_time_tick_msg(struct rwnx_vif *rwnx_vif)
{
u32 msg_len = 0;
struct b_nl_message msg = {0};
struct b_elm_header hdr = {0};
struct b_elm_intf intf = {{0}};
if (!nl_daemon_on)
return;
/* element header */
hdr.id = AIC_ELM_INTF_ID;
hdr.len = ELM_INTF_LEN;
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
/* element: AIC_ELM_INTF_ID */
intf.root = 0; /* TBD */
intf.band = rwnx_vif->ap.band;
intf.ssid = rwnx_vif->rwnx_hw->iface_idx;
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&intf, ELM_INTF_LEN);
/* finish message */
msg.type = AIC_NL_TIME_TICK_TYPE;
msg.len = msg_len;
/* length += (type + len) */
msg_len += 8;
aicwf_nl_send_msg((void *)&msg, msg_len);
return;
}
void aicwf_nl_hook(struct rwnx_vif *rwnx_vif, u8_l band, u8_l ssid)
{
AICWFDBG(LOGSTEER, MANAGER_STR"%s band:%d, ssid:%d\n", __func__, band, ssid);
nl_hook[band][ssid] = 1;
nl_rwnx_vif[band][ssid] = rwnx_vif;
return;
}
void aicwf_nl_hook_deinit(u8_l band, u8_l ssid)
{
AICWFDBG(LOGSTEER, MANAGER_STR"%s band:%d, ssid:%d\n", __func__, band, ssid);
nl_hook[band][ssid] = 0;
nl_rwnx_vif[band][ssid] = NULL;
return;
}
void aicwf_nl_init(void)
{
if (nl_sock) {
AICWFDBG(LOGSTEER, MANAGER_STR"netlink already init.\n");
return;
}
struct netlink_kernel_cfg cfg = {
.input = aicwf_nl_recv_msg,
};
nl_sock = netlink_kernel_create(&init_net, NL_AIC_PROTOCOL, &cfg);
if (!nl_sock)
AICWFDBG(LOGERROR, MANAGER_STR"create netlink falied.\n");
return;
}
void aicwf_nl_deinit(void)
{
if(nl_sock)
{
netlink_kernel_release(nl_sock);
nl_sock = NULL;
}
AICWFDBG(LOGSTEER, MANAGER_STR"[aicwf_nl_deinit] delete nl_sock netlink succeed.\n");
return;
}
@@ -0,0 +1,146 @@
#ifndef _AICWF_MANAGER_H_
#define _AICWF_MANAGER_H_
#include "lmac_types.h"
#include "rwnx_defs.h"
#define DRV_WLAN_MANAGER_VER "v1.0"
/* TBD */
#define CONFIG_IFACE_NUMBER 1
#define NL_AIC_PROTOCOL_FRT_DRV 28
#define NL_AIC_PROTOCOL_SEC_DRV 29
#define NL_AIC_PROTOCOL NL_AIC_PROTOCOL_SEC_DRV
#define NL_AIC_MANAGER_PID 5185
#define NL_MAX_MSG_SIZE 768
/* Netlink Message Type List */
#define AIC_NL_DAEMON_ON_TYPE 1
#define AIC_NL_DAEMON_OFF_TYPE 2
#define AIC_NL_DAEMON_ALIVE_TYPE 3
#define AIC_NL_DEL_STA_TYPE 4
#define AIC_NL_NEW_STA_TYPE 5
#define AIC_NL_INTF_RPT_TYPE 6
#define AIC_NL_STA_RPT_TYPE 7
#define AIC_NL_FRAME_RPT_TYPE 8
#define AIC_NL_TIME_TICK_TYPE 9
#define AIC_NL_PRIV_INFO_CMD_TYPE 10
#ifdef CONFIG_BAND_STEERING
#define AIC_NL_B_STEER_CMD_TYPE 11
#define AIC_NL_B_STEER_BLOCK_ADD_TYPE 12
#define AIC_NL_B_STEER_BLOCK_DEL_TYPE 13
#define AIC_NL_B_STEER_ROAM_TYPE 14
#endif
#define AIC_NL_GENERAL_CMD_TYPE 100
#define AIC_NL_CUSTOMER_TYPE 101
#define AIC_NL_CONFIG_UPDATE_TYPE 102
/* Element ID */
#define AIC_ELM_INTF_ID 1
#define AIC_ELM_INTF_INFO_ID 2
#define AIC_ELM_FRAME_INFO_ID 3
#define AIC_ELM_STA_INFO_ID 4
#define AIC_ELM_ROAM_INFO_ID 5
#define AIC_ELM_BUFFER_ID 6
#define AIC_ELM_STA_INFO_EXT_ID 7
#define LOW_RSSI_IGNORE (-85)
struct b_nl_message {
u32_l type;
u32_l len;
u8_l content[NL_MAX_MSG_SIZE];
};
struct b_elm_header {
u8_l id;
u8_l len;
};
struct b_elm_intf {
u8_l mac[6];
u8_l root;
u8_l band;
u8_l ssid;
s8_l name[16];
};
struct b_elm_intf_info {
u16_l ch;
u8_l ch_clm;
u8_l ch_noise;
u32_l tx_tp;
u32_l rx_tp;
u32_l assoc_sta_num;
/* self neighbor report info */
u32_l bss_info;
u8_l reg_class;
u8_l phy_type;
};
struct b_elm_frame_info {
u16_l frame_type;
u8_l sa[6];
s8_l rssi;
};
struct b_elm_sta_info {
u8_l mac[6];
s8_l rssi;
u32_l link_time;
u32_l tx_tp; /* kbits */
u32_l rx_tp; /* kbits */
};
struct b_elm_roam_info {
u8_l sta_mac[6]; /* station mac */
u8_l bss_mac[6]; /* target bss mac */
u16_l bss_ch; /* target bss channel */
u8_l method; /* 0: 11V, 1: Deauth */
};
struct b_elm_buffer {
u8_l buf[255];
};
struct b_elm_sta_info_ext {
u8_l mac[6];
u8_l supported_band; /* bit0:2g bit1:5g */
u8_l empty[119]; /* for future use */
};
/* Element Size List */
#define ELM_HEADER_LEN (sizeof(struct b_elm_header))
#define ELM_INTF_LEN (sizeof(struct b_elm_intf))
#define ELM_INTF_INFO_LEN (sizeof(struct b_elm_intf_info))
#define ELM_FRAME_INFO_LEN (sizeof(struct b_elm_frame_info))
#define ELM_STA_INFO_LEN (sizeof(struct b_elm_sta_info))
#define ELM_ROAM_INFO_LEN (sizeof(struct b_elm_roam_info))
#define ELM_BUFFER_LEN (sizeof(struct b_elm_buffer))
#define ELM_STA_INFO_EXT_LEN (sizeof(struct b_elm_sta_info_ext))
void aicwf_nl_send_del_sta_msg(struct rwnx_vif *rwnx_vif, u8_l *mac);
void aicwf_nl_send_new_sta_msg(struct rwnx_vif *rwnx_vif, u8_l *mac);
void aicwf_nl_send_intf_rpt_msg(struct rwnx_vif *rwnx_vif);
void aicwf_nl_send_sta_rpt_msg(struct rwnx_vif *rwnx_vif, struct rwnx_sta *sta);
void aicwf_nl_send_frame_rpt_msg(struct rwnx_vif *rwnx_vif, u16_l frame_type, u8_l *sa, s8_l rssi);
void aicwf_nl_send_time_tick_msg(struct rwnx_vif *rwnx_vif);
void aicwf_nl_hook(struct rwnx_vif *rwnx_vif, u8_l band, u8_l iface_id);
void aicwf_nl_hook_deinit(u8_l band, u8_l ssid);
void aicwf_nl_init(void);
void aicwf_nl_deinit(void);
void aicwf_wlan_manager_recv_msg(struct b_nl_message *msg);
void aicwf_nl_recv_msg(struct sk_buff *skb);
void aicwf_nl_send_msg(void *msg, u32_l msg_len);
#endif
+1 -10
View File
@@ -527,12 +527,7 @@ static void aicwf_sdio_bus_stop(struct device *dev)
aicwf_sdio_pwrctl_timer(sdiodev, 0);
if(timer_pending(&sdiodev->rwnx_hw->p2p_alive_timer)){
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
ret = timer_delete(&sdiodev->rwnx_hw->p2p_alive_timer);
#else
ret = del_timer(&sdiodev->rwnx_hw->p2p_alive_timer);
#endif
}
ret = del_timer(&sdiodev->rwnx_hw->p2p_alive_timer);}
sdio_dbg("%s\n",__func__);
if (sdiodev->pwrctl_tsk) {
complete(&sdiodev->pwrctrl_trgg);
@@ -1085,11 +1080,7 @@ void aicwf_sdio_pwrctl_timer(struct aic_sdio_dev *sdiodev, uint duration)
spin_lock_bh(&sdiodev->pwrctl_lock);
if (!duration) {
if (timer_pending(&sdiodev->timer))
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
timer_delete_sync(&sdiodev->timer);
#else
del_timer_sync(&sdiodev->timer);
#endif
} else {
sdiodev->active_duration = duration;
timeout = msecs_to_jiffies(sdiodev->active_duration);
@@ -0,0 +1,217 @@
/**
******************************************************************************
*
* Copyright (C) 2020 AIC semiconductor.
*
* @file aicwf_steering.c
*
* @brief band steering definitions
*
******************************************************************************
*/
#include "aicwf_steering.h"
#include "rwnx_defs.h"
#define MAC_FMT_B "%02x:%02x:%02x:%02x:%02x:%02x"
#define MAC_ARG_B(x) ((u8_l *)(x))[0], ((u8_l *)(x))[1], ((u8_l *)(x))[2], ((u8_l *)(x))[3], ((u8_l *)(x))[4], ((u8_l *)(x))[5]
#define STEEER_STR "[STEERING] USB "
#ifdef CONFIG_BAND_STEERING
static struct b_steer_block_entry *block_entry_lookup(struct rwnx_vif *rwnx_vif, u8_l *mac)
{
u8_l i;
struct b_steer_block_entry *ent = NULL;
for (i = 0; i < B_STEER_ENTRY_NUM; i++) {
ent = &(rwnx_vif->bsteerpriv.block_list[i]);
if (ent->used && (memcmp(ent->mac, mac, 6) == 0)) {
AICWFDBG(LOGSTEER, STEEER_STR"%s "MAC_FMT_B"\n", __func__, MAC_ARG_B(mac));
return ent;
}
}
return NULL;
}
void aicwf_band_steering_expire(struct rwnx_vif *rwnx_vif)
{
u8_l i;
struct b_steer_block_entry *ent = NULL;
if (rwnx_vif->bsteerpriv.inited == false) {
AICWFDBG(LOGSTEER, STEEER_STR"%s bsteerpriv not inited\n", __func__);
return;
}
spin_lock_bh(&(rwnx_vif->bsteerpriv.lock));
/* block entry */
for (i = 0; i < B_STEER_ENTRY_NUM; i++) {
ent = &(rwnx_vif->bsteerpriv.block_list[i]);
if (!ent->used)
continue;
if (ent->entry_expire) {
ent->entry_expire--;
if (ent->entry_expire == 0)
ent->used = 0;
}
}
spin_unlock_bh(&(rwnx_vif->bsteerpriv.lock));
return;
}
s32_l aicwf_band_steering_block_chk(struct rwnx_vif *rwnx_vif, u8_l *mac)
{
s32 ret = 0;
struct b_steer_block_entry *ent = NULL;
if (rwnx_vif->bsteerpriv.inited == false) {
AICWFDBG(LOGSTEER, STEEER_STR"%s bsteerpriv not inited\n", __func__);
return 0;
}
spin_lock_bh(&(rwnx_vif->bsteerpriv.lock));
ent = block_entry_lookup(rwnx_vif, mac);
if (ent)
ret = 1;
spin_unlock_bh(&(rwnx_vif->bsteerpriv.lock));
return ret;
}
void aicwf_band_steering_block_entry_add(struct rwnx_vif *rwnx_vif, u8_l *mac)
{
u8_l i;
struct b_steer_block_entry *ent = NULL;
if (rwnx_vif->bsteerpriv.inited == false) {
AICWFDBG(LOGSTEER, STEEER_STR"%s bsteerpriv not inited\n", __func__);
return;
}
AICWFDBG(LOGSTEER, STEEER_STR"%s "MAC_FMT_B"\n", __func__, MAC_ARG_B(mac));
spin_lock_bh(&(rwnx_vif->bsteerpriv.lock));
ent = block_entry_lookup(rwnx_vif, mac);
/* already exist */
if (ent) {
AICWFDBG(LOGSTEER, STEEER_STR"%s already exist\n", __func__);
ent->entry_expire = B_STEER_BLOCK_ENTRY_EXPIRE;
goto func_return;
}
/* find an empty entry */
for (i = 0; i < B_STEER_ENTRY_NUM; i++) {
if (!rwnx_vif->bsteerpriv.block_list[i].used) {
ent = &(rwnx_vif->bsteerpriv.block_list[i]);
break;
}
}
/* add the entry */
if (ent) {
AICWFDBG(LOGSTEER, STEEER_STR"%s "MAC_FMT_B"\n", __func__, MAC_ARG_B(mac));
ent->used = 1;
memcpy(ent->mac, mac, 6);
ent->entry_expire = B_STEER_BLOCK_ENTRY_EXPIRE;
}
func_return:
spin_unlock_bh(&(rwnx_vif->bsteerpriv.lock));
return;
}
void aicwf_band_steering_block_entry_del(struct rwnx_vif *rwnx_vif, u8_l *mac)
{
struct b_steer_block_entry *ent = NULL;
if (rwnx_vif->bsteerpriv.inited == false) {
AICWFDBG(LOGSTEER, STEEER_STR"%s bsteerpriv not inited\n", __func__);
return;
}
AICWFDBG(LOGSTEER, STEEER_STR"%s "MAC_FMT_B"\n", __func__, MAC_ARG_B(mac));
spin_lock_bh(&(rwnx_vif->bsteerpriv.lock));
ent = block_entry_lookup(rwnx_vif, mac);
if (ent)
ent->used = 0;
spin_unlock_bh(&(rwnx_vif->bsteerpriv.lock));
return;
}
void aicwf_band_steering_roam_block_entry_add(struct rwnx_vif *rwnx_vif, u8_l *mac)
{
u8_l i;
struct b_steer_block_entry *ent = NULL;
if (rwnx_vif->bsteerpriv.inited == false) {
AICWFDBG(LOGSTEER, STEEER_STR"%s bsteerpriv not inited\n", __func__);
return;
}
AICWFDBG(LOGSTEER, STEEER_STR"%s "MAC_FMT_B"\n", __func__, MAC_ARG_B(mac));
spin_lock_bh(&rwnx_vif->bsteerpriv.lock);
ent = block_entry_lookup(rwnx_vif, mac);
/* already exist */
if (ent)
goto func_return;
/* find an empty entry */
for (i = 0; i < B_STEER_ENTRY_NUM; i++) {
if (!rwnx_vif->bsteerpriv.block_list[i].used) {
ent = &(rwnx_vif->bsteerpriv.block_list[i]);
break;
}
}
/* add the entry */
if (ent) {
ent->used = 1;
memcpy(ent->mac, mac, 6);
ent->entry_expire = B_STEER_ROAM_BLOCK_ENTRY_EXPIRE;
}
func_return:
spin_unlock_bh(&rwnx_vif->bsteerpriv.lock);
return;
}
void aicwf_band_steering_init(struct rwnx_vif *rwnx_vif)
{
u8_l i;
AICWFDBG(LOGSTEER, STEEER_STR"%s\n", __func__);
spin_lock_init(&rwnx_vif->bsteerpriv.lock);
rwnx_vif->bsteerpriv.inited = true;
spin_lock_bh(&rwnx_vif->bsteerpriv.lock);
/* block entry */
for (i = 0; i < B_STEER_ENTRY_NUM; i++)
memset(&(rwnx_vif->bsteerpriv.block_list[i]), 0, sizeof(struct b_steer_block_entry));
spin_unlock_bh(&rwnx_vif->bsteerpriv.lock);
return;
}
#endif
@@ -0,0 +1,40 @@
#ifndef _AICWF_STEERING_H_
#define _AICWF_STEERING_H_
#include <linux/spinlock.h>
#include "lmac_types.h"
#ifdef CONFIG_BAND_STEERING
#define B_STEER_ENTRY_NUM 64//32
#define B_STEER_BLOCK_ENTRY_EXPIRE 60
#define B_STEER_ROAM_BLOCK_ENTRY_EXPIRE 5
#define STEER_UPFATE_TIME 2000
struct rwnx_vif;
struct b_steer_block_entry {
u8_l used;
u8_l mac[6];
u32_l entry_expire;
};
struct b_steer_priv {
struct b_steer_block_entry block_list[B_STEER_ENTRY_NUM];
spinlock_t lock;
bool inited;
};
void aicwf_band_steering_expire(struct rwnx_vif *rwnx_vif);
s32_l aicwf_band_steering_block_chk(struct rwnx_vif *rwnx_vif, u8_l *mac);
void aicwf_band_steering_block_entry_add(struct rwnx_vif *rwnx_vif, u8_l *mac);
void aicwf_band_steering_block_entry_del(struct rwnx_vif *rwnx_vif, u8_l *mac);
void aicwf_band_steering_roam_block_entry_add(struct rwnx_vif *rwnx_vif, u8_l *mac);
void aicwf_band_steering_init(struct rwnx_vif *rwnx_vif);
#endif
#endif
+4 -23
View File
@@ -106,11 +106,7 @@ void tcp_ack_deinit(struct rwnx_hw *priv)
drop_msg = NULL;
write_seqlock_bh(&ack_m->ack_info[i].seqlock);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
timer_delete(&ack_m->ack_info[i].timer);
#else
del_timer(&ack_m->ack_info[i].timer);
#endif
drop_msg = ack_m->ack_info[i].msgbuf;
ack_m->ack_info[i].msgbuf = NULL;
write_sequnlock_bh(&ack_m->ack_info[i].seqlock);
@@ -192,7 +188,7 @@ int is_drop_tcp_ack(struct tcphdr *tcphdr, int tcp_tot_len,
case TCPOPT_WINDOW:
if (*ptr < 15)
*win_scale = (1 << (*ptr));
printk("%d\n",*win_scale);
//printk("%d\n",*win_scale);
break;
default:
drop = 2;
@@ -379,11 +375,7 @@ int tcp_ack_handle(struct msg_buf *new_msgbuf,
//printk("%lx \n",ack_info->msgbuf);
drop_msg = ack_info->msgbuf;
ack_info->msgbuf = NULL;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
timer_delete(&ack_info->timer);
#else
del_timer(&ack_info->timer);
#endif
}else{
//printk("msgbuf is NULL \n");
}
@@ -417,11 +409,7 @@ int tcp_ack_handle(struct msg_buf *new_msgbuf,
atomic_read(&ack_m->max_drop_cnt)))) {
ack_info->drop_cnt = 0;
ack_info->in_send_msg = new_msgbuf;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
timer_delete(&ack_info->timer);
#else
del_timer(&ack_info->timer);
#endif
} else {
ret = 1;
ack_info->msgbuf = new_msgbuf;
@@ -454,7 +442,7 @@ int tcp_ack_handle_new(struct msg_buf *new_msgbuf,
struct tcp_ack_msg *ack;
int ret = 0;
struct msg_buf *drop_msg = NULL;
struct msg_buf * send_msg = NULL;
//struct msg_buf * send_msg = NULL;
//printk("",);
write_seqlock_bh(&ack_info->seqlock);
@@ -482,13 +470,9 @@ int tcp_ack_handle_new(struct msg_buf *new_msgbuf,
(ack_info->drop_cnt >=
atomic_read(&ack_m->max_drop_cnt)))){
ack_info->drop_cnt = 0;
send_msg = new_msgbuf;
ack_info->in_send_msg = send_msg;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
timer_delete(&ack_info->timer);
#else
//send_msg = new_msgbuf;
ack_info->in_send_msg = new_msgbuf;
del_timer(&ack_info->timer);
#endif
}else{
ret = 1;
ack_info->msgbuf = new_msgbuf;
@@ -566,9 +550,6 @@ int filter_send_tcp_ack(struct rwnx_hw *priv,
struct tcp_ack_info *ack_info;
struct tcp_ack_manage *ack_m = &priv->ack_m;
if (plen > MAX_TCP_ACK)
return 0;
tcp_ack_update(ack_m);
drop = tcp_check_ack(buf, &ack_msg, &win_scale);
// printk("drop:%d win_scale:%d",drop,win_scale);
@@ -27,26 +27,7 @@ struct msg_buf {
//struct list_head list;
struct sk_buff *skb;
struct rwnx_vif *rwnx_vif;
/* data just tx cmd use,not include the head */
/*void *data;
void *tran_data;
unsigned long pcie_addr;
u8 type;
u8 mode;
u16 len;
unsigned long timeout;*/
/*unsigned int fifo_id;
struct sprdwl_msg_list *msglist;*/
/*unsigned char buffer_type;
struct sprdwl_xmit_msg_list *xmit_msg_list;
unsigned char msg_type;
unsigned long last_time;
u8 ctxt_id;*/
};
struct tcp_ack_msg {
+33 -14
View File
@@ -329,7 +329,11 @@ static bool aicwf_another_ptk_1(struct rx_buff *buffer)
u8 *read = buffer->read;
u16 aggr_len = 0;
if(read == NULL || read >= buffer->end) {
if(read == NULL || read >= (buffer->end - 2)) {
return false;
}
if(buffer->len < 2) {
return false;
}
@@ -346,7 +350,7 @@ static bool aicwf_another_ptk(struct sk_buff *skb)
u8 *data;
u16 aggr_len = 0;
if (skb->data == NULL || skb->len == 0) {
if (skb->data == NULL || skb->len < 2) {
return false;
}
data = skb->data;
@@ -367,7 +371,6 @@ void rwnx_frame_parser(char* tag, char* data, unsigned long len);
#ifdef CONFIG_RX_TASKLET
int aicwf_tasklet_rxframes(struct aicwf_rx_priv *rx_priv)
{
int ret = 0;
unsigned long flags = 0;
struct sk_buff *skb = NULL; /* Packet for event or data frames */
@@ -395,7 +398,8 @@ int aicwf_tasklet_rxframes(struct aicwf_rx_priv *rx_priv)
pkt_len = (*skb->data | (*(skb->data + 1) << 8));
//printk("p:%d, s:%d , %x\n", pkt_len, skb->len, data[2]);
#ifndef CONFIG_USB_RX_REASSEMBLE
if (pkt_len > 1600) {
if (pkt_len > skb->len) {
AICWFDBG(LOGERROR, "%s pkt_len:%d skb->len:%d\r\n", __func__, pkt_len, skb->len);
dev_kfree_skb(skb);
atomic_dec(&rx_priv->rx_cnt);
continue;
@@ -455,9 +459,10 @@ int aicwf_tasklet_rxframes(struct aicwf_rx_priv *rx_priv)
}
return ret;
}
}
#endif
extern bool rx_urb_sched;
int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv)
{
#ifdef AICWF_SDIO_SUPPORT
@@ -580,8 +585,8 @@ int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv)
pkt_len = (*data | (*(data + 1) << 8));
//printk("%s cnt:%d pkt_len:%d \r\n", __func__, cnt, pkt_len);
#ifndef CONFIG_USB_RX_REASSEMBLE
if (pkt_len > 1600) {
AICWFDBG(LOGERROR, "%s pkt_len > 1600 \r\n", __func__);
if (pkt_len > buffer->len) {
AICWFDBG(LOGERROR, "%s pkt_len:%d buffer->len:%d\r\n", __func__, pkt_len, buffer->len);
aicwf_prealloc_rxbuff_free(buffer, &rx_priv->rxbuff_lock);
atomic_dec(&rx_priv->rx_cnt);
return -EBADE;
@@ -603,6 +608,7 @@ int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv)
memcpy(skb_inblock->data, data, aggr_len);
rwnx_rxdataind_aicwf(rx_priv->usbdev->rwnx_hw, skb_inblock, (void *)rx_priv);
buffer->read = buffer->read + aggr_len;
buffer->len -= aggr_len;
}
else { // type : config
aggr_len = pkt_len;
@@ -629,10 +635,15 @@ int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv)
rwnx_rx_handle_print(rx_priv->usbdev->rwnx_hw, msg + 4, aggr_len);
buffer->read = buffer->read + (adjust_len + 4);
buffer->len -= (adjust_len + 4);
kfree(msg);
}
}
aicwf_prealloc_rxbuff_free(buffer, &rx_priv->rxbuff_lock);
if (rx_urb_sched) {
schedule_work(&rx_priv->usbdev->rx_urb_work);
rx_urb_sched = false;
}
atomic_dec(&rx_priv->rx_cnt);
}
}else{
@@ -655,7 +666,8 @@ int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv)
pkt_len = (*data | (*(data + 1) << 8));
//printk("p:%d, s:%d , %x\n", pkt_len, skb->len, data[2]);
#ifndef CONFIG_USB_RX_REASSEMBLE
if (pkt_len > 1600) {
if (pkt_len > buffer->len) {
AICWFDBG(LOGERROR, "%s pkt_len:%d buffer->len:%d\r\n", __func__, pkt_len, buffer->len);
aicwf_prealloc_rxbuff_free(buffer, &rx_priv->rxbuff_lock);
atomic_dec(&rx_priv->rx_cnt);
continue;
@@ -702,6 +714,10 @@ int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv)
}
aicwf_prealloc_rxbuff_free(buffer, &rx_priv->rxbuff_lock);
if (rx_urb_sched) {
schedule_work(&rx_priv->usbdev->rx_urb_work);
rx_urb_sched = false;
}
atomic_dec(&rx_priv->rx_cnt);
}
}
@@ -732,10 +748,12 @@ int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv)
pkt_len = (*skb->data | (*(skb->data + 1) << 8));
//printk("p:%d, s:%d , %x\n", pkt_len, skb->len, data[2]);
#ifndef CONFIG_USB_RX_REASSEMBLE
if (pkt_len > 1600) {
dev_kfree_skb(skb);
atomic_dec(&rx_priv->rx_cnt);
continue;
if (pkt_len > skb->len) {
AICWFDBG(LOGERROR, "%s pkt_len:%d skb->len:%d\r\n", __func__, pkt_len, skb->len);
//dev_kfree_skb(skb);
//atomic_dec(&rx_priv->rx_cnt);
//continue;
break;
}
#endif
if((skb->data[2] & USB_TYPE_CFG) != USB_TYPE_CFG) { // type : data
@@ -810,7 +828,8 @@ int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv)
pkt_len = (*skb->data | (*(skb->data + 1) << 8));
//printk("p:%d, s:%d , %x\n", pkt_len, skb->len, data[2]);
#ifndef CONFIG_USB_RX_REASSEMBLE
if (pkt_len > 1600) {
if (pkt_len > skb->len) {
AICWFDBG(LOGERROR, "%s pkt_len:%d skb->len:%d\r\n", __func__, pkt_len, skb->len);
dev_kfree_skb(skb);
atomic_dec(&rx_priv->rx_cnt);
continue;
@@ -970,7 +989,7 @@ static struct recv_msdu *aicwf_rxframe_queue_init(struct list_head *q, int qsize
for (i = 0; i < qsize; i++) {
INIT_LIST_HEAD(&req->rxframe_list);
list_add(&req->rxframe_list, q);
req->len = 0;
//req->len = 0;
req++;
}
+11 -2
View File
@@ -23,7 +23,7 @@
#define DATA_BUF_MAX 2048
#define TXPKT_BLOCKSIZE 512
#define MAX_AGGR_TXPKT_LEN (1536*64)
#define CMD_TX_TIMEOUT 5000
#define CMD_TX_TIMEOUT 2000
#define TX_ALIGNMENT 4
#ifdef CONFIG_USB_TX_AGGR
@@ -152,6 +152,7 @@ struct aicwf_tx_priv {
};
#define DEFRAG_MAX_WAIT 40 //100
#ifdef AICWF_RX_REORDER
#define MAX_REORD_RXFRAME 250
#define REORDER_UPDATE_TIME 500//50
@@ -182,8 +183,16 @@ struct recv_msdu {
u8 tid;
u8 forward;
u16 seq_num;
uint len;
//uint len;
u8 is_amsdu;
u8 is_ap_reord;
u8 ap_fwd_cnt;
u8 ap_resend_cnt;
u8 *rx_data;
struct sk_buff *first_fwd_skb;
struct sk_buff *last_fwd_skb;
struct sk_buff *first_resend_skb;
struct sk_buff *last_resend_skb;
//for pending rx reorder list
struct list_head reord_pending_list;
//for total frame list, when rxframe from busif, dequeue, when submit frame to net, enqueue
+146 -63
View File
@@ -15,6 +15,7 @@
#include "rwnx_defs.h"
#include "usb_host.h"
#include "rwnx_platform.h"
#include "rwnx_msg_tx.h"
#ifdef CONFIG_GPIO_WAKEUP
#ifdef CONFIG_PLATFORM_ROCKCHIP
@@ -54,6 +55,8 @@ bool aicwf_usb_rx_aggr = true;
bool aicwf_usb_rx_aggr = false;
#endif
atomic_t rx_urb_cnt;
bool rx_urb_sched = false;
u32 aicwf_usb_max_pkt_size = AICWF_USB_MAX_PKT_SIZE;
void aicwf_usb_tx_flowctrl(struct rwnx_hw *rwnx_hw, bool state)
{
@@ -160,7 +163,7 @@ void rwnx_stop_sta_all_queues(struct rwnx_sta *sta, struct rwnx_hw *rwnx_hw)
txq = rwnx_txq_sta_get(sta, tid, rwnx_hw);
netif_stop_subqueue(txq->ndev, txq->ndev_idx);
}
}
}
void rwnx_wake_sta_all_queues(struct rwnx_sta *sta, struct rwnx_hw *rwnx_hw)
{
@@ -170,7 +173,7 @@ void rwnx_wake_sta_all_queues(struct rwnx_sta *sta, struct rwnx_hw *rwnx_hw)
txq = rwnx_txq_sta_get(sta, tid, rwnx_hw);
netif_wake_subqueue(txq->ndev, txq->ndev_idx);
}
}
}
static void usb_txc_sta_flowctrl(struct aicwf_usb_buf *usb_buf, struct aic_usb_dev *usb_dev)
{
@@ -220,6 +223,7 @@ static void aicwf_usb_tx_complete(struct urb *urb)
#ifdef CONFIG_USB_ALIGN_DATA
if(usb_buf->usb_align_data) {
kfree(usb_buf->usb_align_data);
usb_buf->usb_align_data = NULL;
}
#endif
#ifndef CONFIG_USB_TX_AGGR
@@ -256,7 +260,7 @@ void aicwf_usb_rx_submit_all_urb_(struct aic_usb_dev *usb_dev);
#ifdef CONFIG_PREALLOC_RX_SKB
static void aicwf_usb_rx_complete(struct urb *urb)
{
{
struct aicwf_usb_buf *usb_buf = (struct aicwf_usb_buf *) urb->context;
struct aic_usb_dev *usb_dev = usb_buf->usbdev;
struct aicwf_rx_priv* rx_priv = usb_dev->rx_priv;
@@ -313,10 +317,10 @@ static void aicwf_usb_rx_complete(struct urb *urb)
if (usb_dev->state == USB_UP_ST) {
spin_lock_irqsave(&rx_priv->rxqlock, flags);
if (aicwf_usb_rx_aggr) {
//if (aicwf_usb_rx_aggr) {
rx_buff->len = urb->actual_length;
//printk("%s rx_buff->len:%d \r\n", __func__, rx_buff->len);
}
//}
if(!aicwf_rxbuff_enqueue(usb_dev->dev, &rx_priv->rxq, rx_buff)){
spin_unlock_irqrestore(&rx_priv->rxqlock, flags);
@@ -425,7 +429,7 @@ static void aicwf_usb_rx_complete(struct urb *urb)
reassemble_done = true;
}
} else {
if (frag_len == AICWF_USB_MAX_PKT_SIZE) {
if (frag_len == aicwf_usb_max_pkt_size) {
reassemble_valid = true;
}
}
@@ -470,7 +474,7 @@ static void aicwf_usb_rx_complete(struct urb *urb)
u32 pkt_len = skb->data[0] | (skb->data[1] << 8);
if ((type & USB_TYPE_CFG) != USB_TYPE_CFG) {
u32 pkt_total_len = pkt_len + RX_HWHRD_LEN;
if ((pkt_total_len > AICWF_USB_MAX_PKT_SIZE) && (skb->len == AICWF_USB_MAX_PKT_SIZE)) {
if ((pkt_total_len > aicwf_usb_max_pkt_size) && (skb->len == aicwf_usb_max_pkt_size)) {
AICWFDBG(LOGINFO, "reassemble pkt, len=%u\n", pkt_total_len);
struct sk_buff *reassemble_skb = __dev_alloc_skb(pkt_total_len, GFP_ATOMIC/*GFP_KERNEL*/);
if (reassemble_skb) {
@@ -479,7 +483,7 @@ static void aicwf_usb_rx_complete(struct urb *urb)
rx_priv->rx_reassemble_skb = reassemble_skb;
rx_priv->rx_reassemble_total_len = pkt_total_len;
rx_priv->rx_reassemble_cur_len = skb->len;
rx_priv->rx_reassemble_total_frags = ALIGN(pkt_total_len, AICWF_USB_MAX_PKT_SIZE) / AICWF_USB_MAX_PKT_SIZE;
rx_priv->rx_reassemble_total_frags = ALIGN(pkt_total_len, aicwf_usb_max_pkt_size) / aicwf_usb_max_pkt_size;
rx_priv->rx_reassemble_cur_frags = 1;
} else {
usb_err("reassemble pkt alloc fail, len=%u\n", pkt_total_len);
@@ -495,7 +499,7 @@ static void aicwf_usb_rx_complete(struct urb *urb)
} else {
if (type == USB_TYPE_CFG_CMD_RSP) {
u32 pkt_total_len = ALIGN((pkt_len + 4), 4);
if ((pkt_total_len > AICWF_USB_MAX_PKT_SIZE) && (skb->len == AICWF_USB_MAX_PKT_SIZE)) {
if ((pkt_total_len > aicwf_usb_max_pkt_size) && (skb->len == aicwf_usb_max_pkt_size)) {
AICWFDBG(LOGINFO, "reassemble pkt, len=%u\n", pkt_total_len);
struct sk_buff *reassemble_skb = __dev_alloc_skb(pkt_total_len, GFP_ATOMIC/*GFP_KERNEL*/);
if (reassemble_skb) {
@@ -504,7 +508,7 @@ static void aicwf_usb_rx_complete(struct urb *urb)
rx_priv->rx_reassemble_skb = reassemble_skb;
rx_priv->rx_reassemble_total_len = pkt_total_len;
rx_priv->rx_reassemble_cur_len = skb->len;
rx_priv->rx_reassemble_total_frags = ALIGN(pkt_total_len, AICWF_USB_MAX_PKT_SIZE) / AICWF_USB_MAX_PKT_SIZE;
rx_priv->rx_reassemble_total_frags = ALIGN(pkt_total_len, aicwf_usb_max_pkt_size) / aicwf_usb_max_pkt_size;
rx_priv->rx_reassemble_cur_frags = 1;
} else {
usb_err("reassemble pkt alloc fail, len=%u\n", pkt_total_len);
@@ -752,6 +756,7 @@ static int aicwf_usb_submit_rx_urb(struct aic_usb_dev *usb_dev,
if (rx_buff == NULL) {
AICWFDBG(LOGERROR, "failed to alloc rxbuff\r\n");
aicwf_usb_rx_buf_put(usb_dev, usb_buf);
rx_urb_sched = true;
return -1;
}
rx_buff->len = 0;
@@ -803,7 +808,7 @@ static int aicwf_usb_submit_rx_urb(struct aic_usb_dev *usb_dev,
if(aicwf_usb_rx_aggr){
skb = __dev_alloc_skb(AICWF_USB_AGGR_MAX_PKT_SIZE, GFP_ATOMIC/*GFP_KERNEL*/);
} else {
skb = __dev_alloc_skb(AICWF_USB_MAX_PKT_SIZE, GFP_ATOMIC/*GFP_KERNEL*/);
skb = __dev_alloc_skb(aicwf_usb_max_pkt_size, GFP_ATOMIC/*GFP_KERNEL*/);
}
if (!skb) {
aicwf_usb_rx_buf_put(usb_dev, usb_buf);
@@ -821,7 +826,7 @@ static int aicwf_usb_submit_rx_urb(struct aic_usb_dev *usb_dev,
usb_fill_bulk_urb(usb_buf->urb,
usb_dev->udev,
usb_dev->bulk_in_pipe,
skb->data, AICWF_USB_MAX_PKT_SIZE, aicwf_usb_rx_complete, usb_buf);
skb->data, aicwf_usb_max_pkt_size, aicwf_usb_rx_complete, usb_buf);
}
usb_buf->usbdev = usb_dev;
@@ -1728,6 +1733,7 @@ static int aicwf_usb_bus_txdata(struct device *dev, struct sk_buff *skb)
u16 index = 0;
bool need_cfm = false;
#ifdef CONFIG_USB_ALIGN_DATA//AIDEN
u8 *buf_align;
int align;
#endif
@@ -1823,6 +1829,7 @@ static int aicwf_usb_bus_txdata(struct device *dev, struct sk_buff *skb)
#if defined CONFIG_USB_NO_TRANS_DMA_MAP
#error "CONFIG_USB_NO_TRANS_DMA_MAP not supported"
#endif
#if 0
usb_buf->usb_align_data = (u8*)kmalloc(sizeof(u8) * buf_len + align_param, GFP_ATOMIC);
align = ((unsigned long)(usb_buf->usb_align_data)) & (align_param - 1);
@@ -1830,6 +1837,21 @@ static int aicwf_usb_bus_txdata(struct device *dev, struct sk_buff *skb)
usb_fill_bulk_urb(usb_buf->urb, usb_dev->udev, usb_dev->bulk_out_pipe,
usb_buf->usb_align_data + (align_param - align), buf_len, aicwf_usb_tx_complete, usb_buf);
#else
if (!IS_ALIGNED((unsigned long)buf, align_param)) {
usb_buf->usb_align_data = (u8*)kmalloc(sizeof(u8) * buf_len + align_param, GFP_ATOMIC);
if (usb_buf->usb_align_data) {
align = ((unsigned long)(usb_buf->usb_align_data)) & (align_param - 1);
buf_align = usb_buf->usb_align_data + (align_param - align);
memcpy(buf_align, buf, buf_len);
}
} else {
buf_align = buf;
}
usb_fill_bulk_urb(usb_buf->urb, usb_dev->udev, usb_dev->bulk_out_pipe,
buf_align, buf_len, aicwf_usb_tx_complete, usb_buf);
#endif
#else
usb_fill_bulk_urb(usb_buf->urb, usb_dev->udev, usb_dev->bulk_out_pipe,
buf, buf_len, aicwf_usb_tx_complete, usb_buf);
@@ -1878,14 +1900,15 @@ static int aicwf_usb_bus_start(struct device *dev)
aicwf_usb_state_change(usb_dev, USB_UP_ST);
usb_dev->rx_prepare_ready = false;
aicwf_usb_rx_prepare(usb_dev);
aicwf_usb_tx_prepare(usb_dev);
#ifdef CONFIG_USB_MSG_IN_EP
if(usb_dev->msg_in_pipe){
aicwf_usb_msg_rx_prepare(usb_dev);
} else {
aicwf_usb_rx_prepare(usb_dev);
}
#endif
if(!usb_dev->rx_prepare_ready){
if(!usb_dev->msg_in_pipe && !usb_dev->rx_prepare_ready){
AICWFDBG(LOGERROR, "%s rx prepare fail\r\n", __func__);
return -1;
}else{
@@ -2117,18 +2140,23 @@ static int aicwf_parse_usb(struct aic_usb_dev *usb_dev, struct usb_interface *in
/* Check interface number */
#ifdef CONFIG_USB_BT
if (usb->actconfig->desc.bNumInterfaces != 3) {
if (usb->actconfig->desc.bNumInterfaces != 3)
#else
if (usb->actconfig->desc.bNumInterfaces != 1) {
if (usb->actconfig->desc.bNumInterfaces != 1)
#endif
{
AICWFDBG(LOGERROR, "Number of interfaces: %d not supported\n",
usb->actconfig->desc.bNumInterfaces);
if(usb_dev->chipid == PRODUCT_ID_AIC8800DC){
AICWFDBG(LOGERROR, "AIC8800DC change to AIC8800DW\n");
usb_dev->chipid = PRODUCT_ID_AIC8800DW;
}else if (usb_dev->chipid == PRODUCT_ID_AIC8800D81) {
AICWFDBG(LOGERROR, "AIC8800D80\n");
} else {
} else if (usb_dev->chipid == PRODUCT_ID_AIC8800D81) {
AICWFDBG(LOGINFO, "AIC8800D80\n");
} else if(usb_dev->chipid == PRODUCT_ID_AIC8800D81X2 ||
usb_dev->chipid == PRODUCT_ID_AIC8800D89X2 ||
usb_dev->chipid == PRODUCT_ID_AIC8800D81){
//TODO
}else{
ret = -ENODEV;
goto exit;
}
@@ -2200,10 +2228,26 @@ static int aicwf_parse_usb(struct aic_usb_dev *usb_dev, struct usb_interface *in
}
#endif
if (usb->speed == USB_SPEED_HIGH){
switch (usb->speed) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
case USB_SPEED_SUPER_PLUS:
AICWFDBG(LOGINFO, "Aic super plus speed USB device detected\n");
break;
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
case USB_SPEED_SUPER:
AICWFDBG(LOGINFO, "Aic super speed USB device detected\n");
break;
#endif
case USB_SPEED_HIGH:
AICWFDBG(LOGINFO, "Aic high speed USB device detected\n");
}else{
break;
case USB_SPEED_FULL:
AICWFDBG(LOGINFO, "Aic full speed USB device detected\n");
break;
default:
AICWFDBG(LOGINFO, "Aic unknown speed(%d) USB device detected\n", usb->speed);
break;
}
exit:
@@ -2293,7 +2337,9 @@ static int aicwf_usb_chipmatch(struct aic_usb_dev *usb_dev, u16_l vid, u16_l pid
usb_dev->chipid = PRODUCT_ID_AIC8801;
AICWFDBG(LOGINFO, "%s USE AIC8801\r\n", __func__);
return 0;
}else if(pid == USB_PRODUCT_ID_AIC8800DC){
}else if(pid == USB_PRODUCT_ID_AIC8800DC || pid == USB_PRODUCT_ID_TENDA
|| pid == USB_PRODUCT_ID_TENDA_U2 || pid == USB_PRODUCT_ID_AIC8800FC_CUS1
|| pid == USB_PRODUCT_ID_AIC8800FC_CUS2 || pid == USB_PRODUCT_ID_AIC8800FC_CUS3){
usb_dev->chipid = PRODUCT_ID_AIC8800DC;
AICWFDBG(LOGINFO, "%s USE AIC8800DC\r\n", __func__);
return 0;
@@ -2301,12 +2347,43 @@ static int aicwf_usb_chipmatch(struct aic_usb_dev *usb_dev, u16_l vid, u16_l pid
usb_dev->chipid = PRODUCT_ID_AIC8800DW;
AICWFDBG(LOGINFO, "%s USE AIC8800DW\r\n", __func__);
return 0;
}else if(pid == USB_PRODUCT_ID_AIC8800D81 || vid == USB_VENDOR_ID_TP || pid == USB_PRODUCT_ID_AIC8800D83
|| vid == USB_VENDOR_ID_TENDA || pid == USB_PRODUCT_ID_AIC8800D84 || pid == USB_PRODUCT_ID_AIC8800D85){
}else if(pid == USB_PRODUCT_ID_AIC8800D81 || pid == USB_PRODUCT_ID_AIC8800D41
|| pid == USB_PRODUCT_ID_TENDA_U11 || pid == USB_PRODUCT_ID_TENDA_U11_PRO
|| pid == USB_PRODUCT_ID_AIC8800M80_CUS1 || pid == USB_PRODUCT_ID_AIC8800M80_CUS2
|| pid == USB_PRODUCT_ID_AIC8800M80_CUS3 || pid == USB_PRODUCT_ID_AIC8800M80_CUS4
|| pid == USB_PRODUCT_ID_AIC8800M80_CUS5 || pid == USB_PRODUCT_ID_AIC8800M80_CUS6){
usb_dev->chipid = PRODUCT_ID_AIC8800D81;
aicwf_usb_rx_aggr = true;
AICWFDBG(LOGINFO, "%s USE AIC8800D81\r\n", __func__);
return 0;
}else if(pid == USB_PRODUCT_ID_AIC8800D81X2){
usb_dev->chipid = PRODUCT_ID_AIC8800D81X2;
aicwf_usb_max_pkt_size = AICWF_USB_MAX_AMSDU_PKT_SIZE;
if (usb_dev->udev->speed <= USB_SPEED_HIGH) {
aicwf_usb_rx_aggr = true;
} else {
#ifdef CONFIG_PLATFORM_HI
aicwf_usb_rx_aggr = true;
#else
aicwf_usb_rx_aggr = false;
#endif
}
AICWFDBG(LOGINFO, "%s USE AIC8800D81X2\r\n", __func__);
return 0;
}else if(pid == USB_PRODUCT_ID_AIC8800D89X2){
usb_dev->chipid = PRODUCT_ID_AIC8800D89X2;
aicwf_usb_max_pkt_size = AICWF_USB_MAX_AMSDU_PKT_SIZE;
if (usb_dev->udev->speed <= USB_SPEED_HIGH) {
aicwf_usb_rx_aggr = true;
} else {
#ifdef CONFIG_PLATFORM_HI
aicwf_usb_rx_aggr = true;
#else
aicwf_usb_rx_aggr = false;
#endif
}
AICWFDBG(LOGINFO, "%s USE AIC8800D89X2\r\n", __func__);
return 0;
}else{
return -1;
}
@@ -2371,6 +2448,9 @@ static int aicwf_usb_probe(struct usb_interface *intf, const struct usb_device_i
usb_dev->dev = &usb->dev;
usb_set_intfdata(intf, usb_dev);
usb_dev->vid = id->idVendor;
usb_dev->pid = id->idProduct;
ret = aicwf_usb_chipmatch(usb_dev, id->idVendor, id->idProduct);
if (ret < 0) {
@@ -2442,6 +2522,9 @@ static int aicwf_usb_probe(struct usb_interface *intf, const struct usb_device_i
AICWFDBG(LOGERROR, "aicwf_rwnx_usb_platform_init err %d\n", ret);
goto out_free_bus;
}
if(usb_dev->msg_in_pipe){
aicwf_usb_rx_prepare(usb_dev);
}
aicwf_hostif_ready();
#ifdef CONFIG_GPIO_WAKEUP
@@ -2506,58 +2589,52 @@ static int aicwf_usb_suspend(struct usb_interface *intf, pm_message_t state)
{
struct aic_usb_dev *usb_dev =
(struct aic_usb_dev *) usb_get_intfdata(intf);
#ifdef CONFIG_GPIO_WAKEUP
struct rwnx_vif *rwnx_vif, *tmp;
//unsigned long irqflags;
AICWFDBG(LOGINFO, "%s enter\r\n", __func__);
#ifdef CONFIG_WOWLAN
rwnx_send_dummy_reboot(usb_dev->rwnx_hw);
#endif
printk("%s enter\r\n", __func__);
#ifdef CONFIG_GPIO_WAKEUP
// spin_lock_irqsave(&irq_lock, irqflags);
// rwnx_enable_hostwake_irq();
// spin_unlock_irqrestore(&irq_lock, irqflags);
atomic_inc(&irq_count);
list_for_each_entry_safe(rwnx_vif, tmp, &usb_dev->rwnx_hw->vifs, list) {
if (rwnx_vif->ndev){
netif_tx_stop_all_queues(rwnx_vif->ndev);
mdelay(1000);
}
}
aicwf_usb_state_change(usb_dev, USB_SLEEP_ST);
aicwf_bus_stop(usb_dev->bus_if);
list_for_each_entry_safe(rwnx_vif, tmp, &usb_dev->rwnx_hw->vifs, list) {
if (rwnx_vif->ndev)
netif_device_detach(rwnx_vif->ndev);
}
#endif
aicwf_usb_state_change(usb_dev, USB_SLEEP_ST);
aicwf_bus_stop(usb_dev->bus_if);
return 0;
return 0;
}
static int aicwf_usb_resume(struct usb_interface *intf)
{
struct aic_usb_dev *usb_dev =
(struct aic_usb_dev *) usb_get_intfdata(intf);
#ifdef CONFIG_GPIO_WAKEUP
struct rwnx_vif *rwnx_vif, *tmp;
// unsigned long irqflags;
#endif
printk("%s enter\r\n", __func__);
#ifdef CONFIG_GPIO_WAKEUP
// spin_lock_irqsave(&irq_lock, irqflags);
// rwnx_disable_hostwake_irq();
// spin_unlock_irqrestore(&irq_lock, irqflags);
atomic_dec(&irq_count);
AICWFDBG(LOGINFO, "%s enter\r\n", __func__);
list_for_each_entry_safe(rwnx_vif, tmp, &usb_dev->rwnx_hw->vifs, list) {
if (rwnx_vif->ndev)
netif_device_attach(rwnx_vif->ndev);
}
#endif
if (usb_dev->state == USB_UP_ST)
return 0;
if (usb_dev->state != USB_UP_ST){
aicwf_bus_start(usb_dev->bus_if);
}
list_for_each_entry_safe(rwnx_vif, tmp, &usb_dev->rwnx_hw->vifs, list) {
if (rwnx_vif->ndev){
netif_tx_wake_all_queues(rwnx_vif->ndev);
}
}
if(usb_dev->msg_in_pipe){
aicwf_usb_rx_prepare(usb_dev);
}
return 0;
}
@@ -2575,15 +2652,21 @@ static struct usb_device_id aicwf_usb_id_table[] = {
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_AIC, USB_PRODUCT_ID_AIC8800D41, 0xff, 0xff, 0xff)},
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_AIC, USB_PRODUCT_ID_AIC8800DC, 0xff, 0xff, 0xff)},
{USB_DEVICE(USB_VENDOR_ID_AIC, USB_PRODUCT_ID_AIC8800DW)},
{USB_DEVICE(USB_VENDOR_ID_AIC, USB_PRODUCT_ID_AIC8800D83)},
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_PRODUCT_ID_AIC8800D81)},
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_PRODUCT_ID_AIC8800D83)},
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_PRODUCT_ID_AIC8800D84)},
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_PRODUCT_ID_AIC8800D85)},
{USB_DEVICE(USB_VENDOR_ID_TP, USB_PRODUCT_ID_TP)},
{USB_DEVICE(USB_VENDOR_ID_TP, USB_PRODUCT_ID_MERCURY)},
{USB_DEVICE(USB_VENDOR_ID_TP, USB_PRODUCT_ID_FAST)},
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_AIC_V2, USB_PRODUCT_ID_AIC8800D81X2, 0xff, 0xff, 0xff)},
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_PRODUCT_ID_AIC8800D89X2)},
{USB_DEVICE(USB_VENDOR_ID_TENDA, USB_PRODUCT_ID_TENDA)},
{USB_DEVICE(USB_VENDOR_ID_TENDA, USB_PRODUCT_ID_TENDA_U2)},
{USB_DEVICE(USB_VENDOR_ID_TENDA, USB_PRODUCT_ID_TENDA_U11)},
{USB_DEVICE(USB_VENDOR_ID_TENDA, USB_PRODUCT_ID_TENDA_U11_PRO)},
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_PRODUCT_ID_AIC8800FC_CUS1)},
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_PRODUCT_ID_AIC8800FC_CUS2)},
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_PRODUCT_ID_AIC8800FC_CUS3)},
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_PRODUCT_ID_AIC8800M80_CUS1)},
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_PRODUCT_ID_AIC8800M80_CUS2)},
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_PRODUCT_ID_AIC8800M80_CUS3)},
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_PRODUCT_ID_AIC8800M80_CUS4)},
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_PRODUCT_ID_AIC8800M80_CUS5)},
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_PRODUCT_ID_AIC8800M80_CUS6)},
#endif
{}
};
+23 -12
View File
@@ -17,38 +17,46 @@
/* USB Device ID */
#define USB_VENDOR_ID_AIC 0xA69C
#define USB_VENDOR_ID_AIC_V2 0x368B
#define USB_VENDOR_ID_TP 0x2357
#define USB_VENDOR_ID_TENDA 0x2604
#define USB_PRODUCT_ID_TP 0x014e
#define USB_PRODUCT_ID_MERCURY 0x014b
#define USB_PRODUCT_ID_FAST 0x014f
#define USB_PRODUCT_ID_TENDA 0x001f
#ifndef CONFIG_USB_BT
#define USB_PRODUCT_ID_AIC8800 0x8800
#define USB_PRODUCT_ID_AIC8801 0x8801
#define USB_PRODUCT_ID_AIC8800DC 0x88dc
#define USB_PRODUCT_ID_AIC8800DW 0x88dd
#define USB_PRODUCT_ID_AIC8800D81 0x8d81
#define USB_PRODUCT_ID_AIC8800D81X2 0x8d91
#define USB_PRODUCT_ID_AIC8800D89X2 0x8d99
#else
#define USB_PRODUCT_ID_AIC8801 0x8801
#define USB_PRODUCT_ID_AIC8800DC 0x88dc
#define USB_PRODUCT_ID_AIC8800DW 0x88dd
#define USB_PRODUCT_ID_AIC8800D81 0x8d81
#define USB_PRODUCT_ID_AIC8800D41 0x8d41
#define USB_PRODUCT_ID_AIC8800D83 0x8d83
#define USB_PRODUCT_ID_AIC8800D84 0x8d84
#define USB_PRODUCT_ID_AIC8800D85 0x8d85
#define USB_PRODUCT_ID_AIC8800D81X2 0x8d91
#define USB_PRODUCT_ID_AIC8800D89X2 0x8d99
#define USB_PRODUCT_ID_TENDA 0x0013
#define USB_PRODUCT_ID_TENDA_U2 0x0014
#define USB_PRODUCT_ID_TENDA_U11 0x001f
#define USB_PRODUCT_ID_TENDA_U11_PRO 0x0020
#define USB_PRODUCT_ID_AIC8800FC_CUS1 0x88df
#define USB_PRODUCT_ID_AIC8800FC_CUS2 0x88E0
#define USB_PRODUCT_ID_AIC8800FC_CUS3 0x88E1
#define USB_PRODUCT_ID_AIC8800M80_CUS1 0x8D83
#define USB_PRODUCT_ID_AIC8800M80_CUS2 0x8D85
#define USB_PRODUCT_ID_AIC8800M80_CUS3 0x8D86
#define USB_PRODUCT_ID_AIC8800M80_CUS4 0x8D89
#define USB_PRODUCT_ID_AIC8800M80_CUS5 0x8D8A
#define USB_PRODUCT_ID_AIC8800M80_CUS6 0x8D8C
#endif
enum AICWF_IC{
PRODUCT_ID_AIC8801 = 0,
PRODUCT_ID_AIC8800DC,
PRODUCT_ID_AIC8800DW,
PRODUCT_ID_AIC8800D81
PRODUCT_ID_AIC8800D81,
PRODUCT_ID_AIC8800D81X2,
PRODUCT_ID_AIC8800D89X2
};
@@ -71,6 +79,7 @@ enum AICWF_IC{
#endif
#define AICWF_USB_MSG_MAX_PKT_SIZE (2048)
#define AICWF_USB_MAX_PKT_SIZE (2048)
#define AICWF_USB_MAX_AMSDU_PKT_SIZE (2048*6)
#define AICWF_USB_FC_PERSTA_HIGH_WATER 64
#define AICWF_USB_FC_PERSTA_LOW_WATER 16
@@ -183,6 +192,8 @@ struct aic_usb_dev {
#endif
u16 chipid;
bool tbusy;
u16_l vid;
u16_l pid;
};
extern void aicwf_usb_exit(void);
@@ -970,6 +970,26 @@ static int aicwf_set_scan(struct net_device *dev, struct iw_request_info *a,
}
}
#if WIRELESS_EXT >= 17
if (wrqu->data.length == sizeof(struct iw_scan_req)) {
struct iw_scan_req *req = (struct iw_scan_req *)extra;
if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
int len = min((int)req->essid_len, 32);
request->ssids = kmalloc(sizeof(struct cfg80211_ssid), GFP_KERNEL);
if(!request->ssids){
AICWFDBG(LOGERROR, "%s Failied to alloc memory for ssids", __func__);
return -ENOMEM;
}
memset(request->ssids, 0, sizeof(struct cfg80211_ssid));
memcpy(request->ssids[0].ssid, req->essid, len);
request->ssids[0].ssid_len = len;
request->n_ssids = 1;
AICWFDBG(LOGDEBUG,"IW_SCAN_THIS_ESSID, ssid=%s, len=%d\n", req->essid, req->essid_len);
} else if (req->scan_type == IW_SCAN_TYPE_PASSIVE)
AICWFDBG(LOGDEBUG,"aic_set_scan, req->scan_type == IW_SCAN_TYPE_PASSIVE\n");
}
#endif
if ((ret = rwnx_send_scanu_req(rwnx_hw, rwnx_vif, request))){
return ret;
}
@@ -980,7 +1000,6 @@ static int aicwf_set_scan(struct net_device *dev, struct iw_request_info *a,
if (!wait_for_completion_killable_timeout(&rwnx_hw->wext_scan_com, wext_scan_timeout)) {
AICWFDBG(LOGERROR, "%s WEXT scan timeout", __func__);
}
return 0;
}
+1
View File
@@ -472,6 +472,7 @@ enum mac_connection_flags
#define IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS 0x01
#define IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US 0x02
#define IEEE80211_HE_PHY_CAP2_DOPPLER_RX 0x20
#define IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ 0x04
#define IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ 0x08
#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM 0x18
#define IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 0x00
+272 -10
View File
@@ -402,6 +402,17 @@ enum mm_msg_tag
MM_SET_TXPWR_LVL_ADJ_REQ,
MM_SET_TXPWR_LVL_ADJ_CFM,
MM_RADAR_DETECT_IND,
MM_SET_APF_PROG_REQ,
MM_SET_APF_PROG_CFM,
MM_GET_APF_PROG_REQ,
MM_GET_APF_PROG_CFM,
MM_SET_TXPWR_PER_STA_REQ,
MM_SET_TXPWR_PER_STA_CFM,
/// MAX number of messages
MM_MAX,
};
@@ -1264,6 +1275,17 @@ struct mm_set_rf_config_req
u32_l data[64];
};
typedef struct
{
u32_l magic_num; /*“GWCR” or ’SWCR”*/
u32_l info_flag;
u32_l calib_flag;
u32_l reserved0;
u32_l res_data[536/sizeof(u32_l)];
}wf_rf_calib_res_drv_t;
#define DRIVER_GET_WIFI_CALRES_MAGIC_NUM 0x52435747
#define DRIVER_SET_WIFI_CALRES_MAGIC_NUM 0x52435753
struct mm_set_rf_calib_req
{
@@ -1277,6 +1299,20 @@ struct mm_set_rf_calib_req
};
struct mm_set_rf_calib_req_v2
{
u32_l cal_cfg_24g;
u32_l cal_cfg_5g;
u32_l param_alpha;
u32_l bt_calib_en;
u32_l bt_calib_param;
u8_l xtal_cap;
u8_l xtal_cap_fine;
u8_l reserved0[2];
wf_rf_calib_res_drv_t cal_res;
};
struct mm_set_rf_calib_cfm
{
u32_l rxgain_24g_addr;
@@ -1285,6 +1321,15 @@ struct mm_set_rf_calib_cfm
u32_l txgain_5g_addr;
};
struct mm_set_rf_calib_cfm_v2
{
u32_l rxgain_24g_addr;
u32_l rxgain_5g_addr;
u32_l txgain_24g_addr;
u32_l txgain_5g_addr;
wf_rf_calib_res_drv_t cal_res;
};
struct mm_get_mac_addr_req
{
u32_l get;
@@ -1305,6 +1350,12 @@ struct mm_get_sta_info_cfm
u32_l rate_info;
u32_l txfailed;
u8 rssi;
u8 reserved[3];
u32_l chan_time;
u32_l chan_busy_time;
u32_l ack_fail_stat;
u32_l ack_succ_stat;
u32_l chan_tx_busy_time;
};
typedef struct
@@ -1340,6 +1391,20 @@ typedef struct
s8_l pwrlvl_11ax_5g[12];
} txpwr_lvl_conf_v3_t;
typedef struct
{
u8_l enable;
s8_l pwrlvl_11b_11ag_2g4[12];
s8_l pwrlvl_11n_11ac_2g4[10];
s8_l pwrlvl_11ax_2g4[12];
s8_l pwrlvl_11a_5g[8];
s8_l pwrlvl_11n_11ac_5g[10];
s8_l pwrlvl_11ax_5g[12];
s8_l pwrlvl_11a_6g[8];
s8_l pwrlvl_11n_11ac_6g[10];
s8_l pwrlvl_11ax_6g[12];
} txpwr_lvl_conf_v4_t;
typedef struct
{
u8_l enable;
@@ -1353,6 +1418,7 @@ struct mm_set_txpwr_lvl_req
txpwr_lvl_conf_t txpwr_lvl;
txpwr_lvl_conf_v2_t txpwr_lvl_v2;
txpwr_lvl_conf_v3_t txpwr_lvl_v3;
txpwr_lvl_conf_v4_t txpwr_lvl_v4;
};
};
@@ -1363,8 +1429,10 @@ struct mm_set_txpwr_lvl_adj_req
typedef struct
{
u8_l loss_enable;
u8_l loss_value;
u8_l loss_enable_2g4;
s8_l loss_value_2g4;
u8_l loss_enable_5g;
s8_l loss_value_5g;
} txpwr_loss_conf_t;
typedef struct
@@ -1424,16 +1492,58 @@ typedef struct
typedef struct
{
int8_t enable;
int8_t pwrofst2x_tbl_2g4[3][3];
int8_t pwrofst2x_tbl_5g[3][6];
u8_l enable;
s8_l pwrofst2x_tbl_2g4[3][3];
s8_l pwrofst2x_tbl_5g[3][6];
} txpwr_ofst2x_conf_t;
/*
* pwrofst2x_v2_tbl_2g4_ant0/1[3][3]:
* +---------------+----------+---------------+--------------+
* | ChGrp\RateTyp | DSSS | OFDM_HIGHRATE | OFDM_LOWRATE |
* +---------------+----------+---------------+--------------+
* | CH_1_4 | [0][0] | [0][1] | Reserved |
* +---------------+----------+---------------+--------------+
* | CH_5_9 | [1][0] | [1][1] | Reserved |
* +---------------+----------+---------------+--------------+
* | CH_10_13 | [2][0] | [2][1] | Reserved |
* +---------------+----------+---------------+--------------+
* pwrofst2x_v2_tbl_5g_ant0/1[6][3]:
* +-----------------+---------------+--------------+--------------+
* | ChGrp\RateTyp | OFDM_HIGHRATE | OFDM_LOWRATE | OFDM_MIDRATE |
* +-----------------+---------------+--------------+--------------+
* | CH_42(36~50) | [0][0] | Reserved | Reserved |
* +-----------------+---------------+--------------+--------------+
* | CH_58(51~64) | [1][0] | Reserved | Reserved |
* +-----------------+---------------+--------------+--------------+
* | CH_106(98~114) | [2][0] | Reserved | Reserved |
* +-----------------+---------------+--------------+--------------+
* | CH_122(115~130) | [3][0] | Reserved | Reserved |
* +-----------------+---------------+--------------+--------------+
* | CH_138(131~146) | [4][0] | Reserved | Reserved |
* +-----------------+---------------+--------------+--------------+
* | CH_155(147~166) | [5][0] | Reserved | Reserved |
* +-----------------+---------------+--------------+--------------+
*/
typedef struct
{
u8_l enable;
u8_l pwrofst_flags;
s8_l pwrofst2x_tbl_2g4_ant0[3][3];
s8_l pwrofst2x_tbl_2g4_ant1[3][3];
s8_l pwrofst2x_tbl_5g_ant0[6][3];
s8_l pwrofst2x_tbl_5g_ant1[6][3];
s8_l pwrofst2x_tbl_6g_ant0[15];
s8_l pwrofst2x_tbl_6g_ant1[15];
} txpwr_ofst2x_conf_v2_t;
struct mm_set_txpwr_ofst_req
{
union {
txpwr_ofst_conf_t txpwr_ofst;
txpwr_ofst2x_conf_t txpwr_ofst2x;
txpwr_ofst2x_conf_v2_t txpwr_ofst2x_v2;
};
};
@@ -1978,8 +2088,26 @@ enum vendor_hwconfig_tag{
AP_PS_LEVEL_SET_REQ,
CUSTOMIZED_FREQ_REQ,
WAKEUP_INFO_REQ,
KEEPALIVE_PKT_REQ,
};
enum vendor_hwconfig_tag_x2{
ACS_TXOP_REQ_X2 = 0,
CHANNEL_ACCESS_REQ_X2,
MAC_TIMESCALE_REQ_X2,
CCA_THRESHOLD_REQ_X2,
BWMODE_REQ_X2,
CHIP_TEMP_GET_REQ_X2,
STBC_MCS_SET_REQ_X2,
MAX_AGG_TX_CNT_REQ_X2,
MAX_BW_MCS_THRESH_SET_REQ_X2,
DCM_FORCE_EN_REQ_X2,
AUTO_CCA_EN_REQ_X2,
NSS_1T2R_REQ_X2,
ON_AIR_DUTY_CYCLE_REQ_X2,
};
enum {
BWMODE20M = 0,
BWMODE10M,
@@ -2006,6 +2134,7 @@ struct mm_set_channel_access_req
u8_l cfe_en;
u8_l rc_retry_cnt[3];
s8_l ccademod_th;
u8_l remove_1m2m;
};
struct mm_set_mac_timescale_req
@@ -2047,6 +2176,58 @@ struct mm_get_chip_temp_cfm
s8_l degree;
};
struct mm_get_stbc_msc_req
{
u32_l hwconfig_id;
u8_l enable;
u8_l mcs_thresh;
};
struct mm_set_max_tx_agg_cnt_req
{
u32_l hwconfig_id;
u8_l enale;
u8_l mcs_thresh;
u8_l max_agg_cnt[AC_MAX];
};
struct mm_set_max_bw_mcs_thresh_req
{
u32_l hwconfig_id;
u8_l enale;
u8_l max_bw_mcs_thresh;
};
struct mm_set_dcm_force_en_req
{
u32_l hwconfig_id;
u8_l enable;
};
struct mm_set_auto_cca_en_req
{
u32_l hwconfig_id;
u8_l enable;
int8_t max_cca_thresh;
u8_l default_cca_set;
int8_t default_cca_thresh;
};
struct mm_set_nss_1t2r_req
{
u32_l hwconfig_id;
u8_l enable;
};
struct mm_set_on_air_duty_cycle_req
{
u32_l hwconfig_id;
u8_l enable;
u8_l percent;//10 means 10%, 1-99
};
struct mm_set_vendor_hwconfig_cfm
{
u32_l hwconfig_id;
@@ -2062,6 +2243,15 @@ struct mm_set_customized_freq_req
u16_l map_freq[4];
};
struct mm_set_keepalive_req
{
u32_l hwconfig_id;
u16_l code;
u16_l length;
u32_l intv;
u8_l payload[];
};
struct mm_set_txop_req
{
u16_l txop_bk;
@@ -2100,6 +2290,18 @@ enum vendor_swconfig_tag
EXT_FLAGS_MASK_SET_REQ,
};
enum vendor_swconfig_tag_x2
{
BCN_CFG_REQ_X2 = 0,
TEMP_COMP_SET_REQ_X2,
TEMP_COMP_GET_REQ_X2,
EXT_FLAGS_SET_REQ_X2,
EXT_FLAGS_GET_REQ_X2,
EXT_FLAGS_MASK_SET_REQ_X2,
TWO_ANT_RSSI_GET_REQ_X2,
};
struct mm_set_bcn_cfg_req
{
/// Ignore or not bcn tim bcmc bit
@@ -2184,6 +2386,12 @@ struct mm_set_vendor_swconfig_cfm
};
};
struct mm_set_txpwr_lvl_per_sta_req
{
u8_l sta_idx;
s8_l tx_pwr_offset;
};
/// Structure containing the parameters of the @ref ME_RC_STATS_REQ message.
struct me_rc_stats_req
{
@@ -2551,13 +2759,13 @@ struct apm_stop_req
struct apm_start_cac_req
{
/// Control channel on which we have to start the CAC
struct mac_chan_def chan;
struct mac_chan_op chan;
/// Center frequency of the first segment
u32_l center_freq1;
//u32_l center_freq1;
/// Center frequency of the second segment (only in 80+80 configuration)
u32_l center_freq2;
//u32_l center_freq2;
/// Width of channel
u8_l ch_width;
//u8_l ch_width;
/// Index of the VIF for which the CAC is started
u8_l vif_idx;
};
@@ -3007,7 +3215,7 @@ struct dbg_rftest_cmd_req
struct dbg_rftest_cmd_cfm
{
u32_l rftest_result[18];
u32_l rftest_result[32];
};
struct dbg_gpio_write_req {
@@ -3069,6 +3277,21 @@ struct dbg_mem_block_write_cfm
u32_l wstatus;
};
/// Structure containing the parameters of the @ref DBG_MEM_BLOCK_READ_REQ message.
struct dbg_mem_block_read_req
{
u32_l memaddr;
u32_l memsize;
};
/// Structure containing the parameters of the @ref DBG_MEM_BLOCK_READ_CFM message.
struct dbg_mem_block_read_cfm
{
u32_l memaddr;
u32_l memsize;
u32_l memdata[1024 / sizeof(u32_l)];
};
/// Structure containing the parameters of the @ref DBG_START_APP_REQ message.
struct dbg_start_app_req
{
@@ -3233,5 +3456,44 @@ struct tdls_peer_traffic_ind_cfm
u8_l status;
};
struct mm_set_wakeup_info_req {
u32_l hwconfig_id;
u16_l code;
u16_l offset;
u16_l length;
u8_l mask_and_pattern[];
};
struct dbg_pwm_init_req
{
/// PWM_CHANNEL_GPIO
u8 pwm_gpidx;
/// 0 normal 1 breath
u8 mode;
/// 0 config only 1 run after config
u8 run;
u32 tmr_cnt;
u32 dty_cnt;
u32 step_val;
/// 0 disable 1 enable
u8 gpio_en;
/// 0 input 1 output
u8 gpio_dir;
/// 0 low 1 high
u8 gpio_val;
};
struct dbg_pwm_deinit_req
{
/// PWM_CHANNEL_GPIO
u8 pwm_gpidx;
/// 0 disable 1 enable
u8 gpio_en;
/// 0 input 1 output
u8 gpio_dir;
/// 0 low 1 high
u8 gpio_val;
};
#endif // LMAC_MSG_H_
+1 -1
View File
@@ -21,7 +21,7 @@
#define ROM_FMAC_FW_ADDR 0x00010000
#define RAM_FMAC_FW_ADDR 0x00120000
#define ROM_FMAC_PATCH_ADDR 0x00180000
#ifdef CONFIG_DPD
#if defined(CONFIG_DPD) || defined(CONFIG_LOFT_CALIB)
#define ROM_FMAC_CALIB_ADDR 0x00130000
#endif
File diff suppressed because it is too large Load Diff
+62 -5
View File
@@ -19,6 +19,7 @@
#include "rwnx_strs.h"
#include "rwnx_events.h"
#include "aicwf_txrxif.h"
#include "rwnx_wakelock.h"
#ifdef AICWF_SDIO_SUPPORT
#include "aicwf_sdio.h"
#else
@@ -46,8 +47,8 @@ static void cmd_complete(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd)
//RWNX_DBG(RWNX_FN_ENTRY_STR);
lockdep_assert_held(&cmd_mgr->lock);
list_del(&cmd->list);
cmd_mgr->queue_sz--;
//list_del(&cmd->list);
//cmd_mgr->queue_sz--;
cmd->flags |= RWNX_CMD_FLAG_DONE;
if (cmd->flags & RWNX_CMD_FLAG_NONBLOCK) {
@@ -58,6 +59,10 @@ static void cmd_complete(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd)
complete(&cmd->complete);
}
}
if(cmd_mgr->queue_sz == 0){
rwnx_wakeup_unlock(g_rwnx_plat->usbdev->rwnx_hw->ws_tx);
}
}
int cmd_mgr_queue_force_defer(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd)
@@ -102,6 +107,9 @@ int cmd_mgr_queue_force_defer(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd
init_completion(&cmd->complete);
list_add_tail(&cmd->list, &cmd_mgr->cmds);
if(cmd_mgr->queue_sz == 0){
rwnx_wakeup_lock(g_rwnx_plat->usbdev->rwnx_hw->ws_tx);
}
cmd_mgr->queue_sz++;
spin_unlock_bh(&cmd_mgr->lock);
@@ -123,12 +131,33 @@ static int cmd_mgr_queue(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd)
struct aic_usb_dev *usbdev = container_of(cmd_mgr, struct aic_usb_dev, cmd_mgr);
#endif
bool defer_push = false;
u8_l empty = 0;
//RWNX_DBG(RWNX_FN_ENTRY_STR);
#ifdef CREATE_TRACE_POINTS
trace_msg_send(cmd->id);
#endif
if(cmd->e2a_msg != NULL) {
do {
if(cmd_mgr->state == RWNX_CMD_MGR_STATE_CRASHED)
break;
spin_lock_bh(&cmd_mgr->lock);
empty = list_empty(&cmd_mgr->cmds);
if(!empty) {
spin_unlock_bh(&cmd_mgr->lock);
if(in_softirq()) {
printk("in_softirq:check cmdqueue empty\n");
mdelay(10);
} else {
printk("check cmdqueue empty\n");
msleep(50);
}
}
} while(!empty);//wait for cmd queue empty
} else {
spin_lock_bh(&cmd_mgr->lock);
}
if (cmd_mgr->state == RWNX_CMD_MGR_STATE_CRASHED) {
printk(KERN_CRIT"cmd queue crashed\n");
@@ -177,6 +206,9 @@ static int cmd_mgr_queue(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd)
init_completion(&cmd->complete);
list_add_tail(&cmd->list, &cmd_mgr->cmds);
if(cmd_mgr->queue_sz == 0){
rwnx_wakeup_lock(g_rwnx_plat->usbdev->rwnx_hw->ws_tx);
}
cmd_mgr->queue_sz++;
if(cmd->a2e_msg->id == ME_TRAFFIC_IND_REQ
@@ -240,6 +272,13 @@ static int cmd_mgr_queue(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd)
spin_unlock_bh(&cmd_mgr->lock);
}
else{
spin_lock_bh(&cmd_mgr->lock);
list_del(&cmd->list);
cmd_mgr->queue_sz--;
if(cmd_mgr->queue_sz == 0){
rwnx_wakeup_unlock(usbdev->rwnx_hw->ws_tx);
}
spin_unlock_bh(&cmd_mgr->lock);
rwnx_cmd_free(cmd);//kfree(cmd);AIDEN
if(!list_empty(&cmd_mgr->cmds) && usbdev->state == USB_UP_ST)
WAKE_CMD_WORK(cmd_mgr);
@@ -350,10 +389,18 @@ void cmd_mgr_task_process(struct work_struct *work)
cmd_complete(cmd_mgr, next);
}
spin_unlock_bh(&cmd_mgr->lock);
} else
} else {
spin_lock_bh(&cmd_mgr->lock);
list_del(&next->list);
cmd_mgr->queue_sz--;
if(cmd_mgr->queue_sz == 0){
rwnx_wakeup_unlock(usbdev->rwnx_hw->ws_tx);
}
spin_unlock_bh(&cmd_mgr->lock);
rwnx_cmd_free(next);//kfree(next);AIDEN
}
}
}
}
@@ -460,11 +507,17 @@ static void cmd_mgr_drain(struct rwnx_cmd_mgr *cmd_mgr)
spin_lock_bh(&cmd_mgr->lock);
list_for_each_entry_safe(cur, nxt, &cmd_mgr->cmds, list) {
list_del(&cur->list);
cmd_mgr->queue_sz--;
//cmd_mgr->queue_sz--;
if (!(cur->flags & RWNX_CMD_FLAG_NONBLOCK))
complete(&cur->complete);
}
spin_unlock_bh(&cmd_mgr->lock);
#if 0
if(cmd_mgr->queue_sz == 0){
rwnx_wakeup_unlock(g_rwnx_plat->usbdev->rwnx_hw->ws_tx);
}
#endif
}
void rwnx_cmd_mgr_init(struct rwnx_cmd_mgr *cmd_mgr)
@@ -506,6 +559,7 @@ void aicwf_set_cmd_tx(void *dev, struct lmac_msg *msg, uint len)
{
u8 *buffer = NULL;
u16 index = 0;
int ret = 0;
#ifdef AICWF_SDIO_SUPPORT
struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *)dev;
struct aicwf_bus *bus = sdiodev->bus_if;
@@ -540,6 +594,9 @@ void aicwf_set_cmd_tx(void *dev, struct lmac_msg *msg, uint len)
index += 2;
memcpy(&buffer[index], (u8 *)msg->param, msg->param_len);
aicwf_bus_txmsg(bus, buffer, len + 8);
ret = aicwf_bus_txmsg(bus, buffer, len + 8);
if (ret == -EIO) {
ret = aicwf_bus_txmsg(bus, buffer, len + 8);
}
}
@@ -244,9 +244,11 @@ enum ieee80211_radiotap_he_mu_bits {
#define REGULATORY_IGNORE_STALE_KICKOFF 0
#else
#define STA_TDLS_INITIATOR(sta) sta->tdls_initiator
#ifndef REGULATORY_IGNORE_STALE_KICKOFF
#define REGULATORY_IGNORE_STALE_KICKOFF 0
#endif
#endif
+230 -12
View File
@@ -200,11 +200,11 @@ DEBUGFS_READ_WRITE_FILE_OPS(stats);
#endif /* CONFIG_RWNX_FULLMAC */
#define STA_HDR "** STA %d (%pM)\n"
#define STA_HDR_MAX_LEN sizeof("- STA xx (xx:xx:xx:xx:xx:xx)\n") + PS_HDR_MAX_LEN
#define STA_HDR_MAX_LEN (sizeof("- STA xx (xx:xx:xx:xx:xx:xx)\n") + PS_HDR_MAX_LEN)
#ifdef CONFIG_RWNX_FULLMAC
#define VIF_HDR "* VIF [%d] %s\n"
#define VIF_HDR_MAX_LEN sizeof(VIF_HDR) + IFNAMSIZ
#define VIF_HDR_MAX_LEN (sizeof(VIF_HDR) + IFNAMSIZ)
#else
#define VIF_HDR "* VIF [%d]\n"
#define VIF_HDR_MAX_LEN sizeof(VIF_HDR)
@@ -1261,6 +1261,12 @@ static ssize_t rwnx_dbgfs_regdbg_write(struct file *file,
if(oper== 0) {
ret = rwnx_send_dbg_mem_read_req(priv, addr, &mem_read_cfm);
printk("[0x%x] = [0x%x]\n", mem_read_cfm.memaddr, mem_read_cfm.memdata);
} else if (oper == 1) {
ret = rwnx_send_dbg_mem_read_req(priv, addr, &mem_read_cfm);
printk("before write : [0x%x] = [0x%x]\n", mem_read_cfm.memaddr, mem_read_cfm.memdata);
ret = rwnx_send_dbg_mem_block_write_req(priv, addr, 4, &val);
ret = rwnx_send_dbg_mem_read_req(priv, addr, &mem_read_cfm);
printk("after write : [0x%x] = [0x%x]\n", mem_read_cfm.memaddr, mem_read_cfm.memdata);
}
return count;
@@ -1274,7 +1280,7 @@ static ssize_t rwnx_dbgfs_vendor_hwconfig_write(struct file *file,
{
struct rwnx_hw *priv = file->private_data;
char buf[64];
int32_t addr[13];
int32_t addr[14];
int32_t addr_out[12];
u32_l hwconfig_id;
size_t len = min_t(size_t,count,sizeof(buf)-1);
@@ -1288,10 +1294,10 @@ static ssize_t rwnx_dbgfs_vendor_hwconfig_write(struct file *file,
}
buf[len] = '\0';
ret = sscanf(buf, "%x %x %x %x %x %x %x %x %x %x %x %x %x %x",
&hwconfig_id, &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5], &addr[6], &addr[7], &addr[8], &addr[9], &addr[10], &addr[11]);
if(ret > 14) {
printk("param error > 14\n");
ret = sscanf(buf, "%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
&hwconfig_id, &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5], &addr[6], &addr[7], &addr[8], &addr[9], &addr[10], &addr[11], &addr[12], &addr[13]);
if(ret > 15) {
printk("param error > 15\n");
} else {
switch(hwconfig_id)
{
@@ -1303,12 +1309,12 @@ static ssize_t rwnx_dbgfs_vendor_hwconfig_write(struct file *file,
printk("ACS_TXOP_REQ bk:0x%x be:0x%x vi:0x%x vo:0x%x\n",addr[0], addr[1], addr[2], addr[3]);
break;
case 1:
if(ret != 14) {
printk("param error != 14\n");
if(ret != 15) {
printk("param error != 15\n");
break;}
ret = rwnx_send_vendor_hwconfig_req(priv, hwconfig_id, addr, NULL);
printk("CHANNEL_ACCESS_REQ edca:%x,%x,%x,%x, vif:%x, retry_cnt:%x, rts:%x, long_nav:%x, cfe:%x, rc_retry_cnt:%x:%x:%x ccademod_th %x\n",
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12]);
printk("CHANNEL_ACCESS_REQ edca:%x,%x,%x,%x, vif:%x, retry_cnt:%x, rts:%x, long_nav:%x, cfe:%x, rc_retry_cnt:%x:%x:%x ccademod_th %x, remove_1m2m %x\n",
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13]);
break;
case 2:
if(ret != 7) {
@@ -1456,6 +1462,216 @@ static ssize_t rwnx_dbgfs_vendor_swconfig_write(struct file *file,
DEBUGFS_WRITE_FILE_OPS(vendor_swconfig);
static ssize_t rwnx_dbgfs_vendor_hwconfig_x2_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct rwnx_hw *priv = file->private_data;
char buf[64];
int32_t addr[14];
int32_t addr_out[12];
u32_l hwconfig_id;
size_t len = min_t(size_t,count,sizeof(buf)-1);
int ret;
printk("%s\n",__func__);
//choose the type of write info by struct
//struct mm_set_vendor_trx_param_req trx_param;
if(copy_from_user(buf,user_buf,len)) {
return -EFAULT;
}
buf[len] = '\0';
ret = sscanf(buf, "%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
&hwconfig_id, &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5], &addr[6], &addr[7], &addr[8], &addr[9], &addr[10], &addr[11], &addr[12], &addr[13]);
if(ret > 15) {
printk("param error > 15\n");
} else {
switch(hwconfig_id)
{
case 0:
if(ret != 5) {
printk("param error != 5\n");
break;}
ret = rwnx_send_vendor_hwconfig_req_x2(priv, hwconfig_id, addr, NULL);
printk("ACS_TXOP_REQ bk:0x%x be:0x%x vi:0x%x vo:0x%x\n",addr[0], addr[1], addr[2], addr[3]);
break;
case 1:
if(ret != 15) {
printk("param error != 15\n");
break;}
ret = rwnx_send_vendor_hwconfig_req_x2(priv, hwconfig_id, addr, NULL);
printk("CHANNEL_ACCESS_REQ edca:%x,%x,%x,%x, vif:%x, retry_cnt:%x, rts:%x, long_nav:%x, cfe:%x, rc_retry_cnt:%x:%x:%x ccademod_th %x remove_1m2m %x\n",
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13]);
break;
case 2:
if(ret != 7) {
printk("param error != 7\n");
break;}
ret = rwnx_send_vendor_hwconfig_req_x2(priv, hwconfig_id, addr, NULL);
printk("MAC_TIMESCALE_REQ sifsA:%x,sifsB:%x,slot:%x,ofdm_delay:%x,long_delay:%x,short_delay:%x\n",
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
break;
case 3:
if(ret != 6) {
printk("param error != 6\n");
break;}
addr[1] = ~addr[1] + 1;
addr[2] = ~addr[2] + 1;
addr[3] = ~addr[3] + 1;
addr[4] = ~addr[4] + 1;
ret = rwnx_send_vendor_hwconfig_req_x2(priv, hwconfig_id, addr, NULL);
printk("CCA_THRESHOLD_REQ auto_cca:%d, cca20p_rise:%d cca20s_rise:%d cca20p_fail:%d cca20s_fail:%d\n",
addr[0], addr[1], addr[2], addr[3], addr[4]);
break;
case 4: // BWMODE_REQ
if (ret != 2) {
printk("param error != 2\n");
} else {
ret = rwnx_send_vendor_hwconfig_req_x2(priv, hwconfig_id, addr, NULL);
printk("BWMODE_REQ md=%d\n", addr[0]);
}
break;
case 5: // CHIP_TEMP_GET_REQ
if (ret != 1) {
printk("param error != 1\n");
} else {
ret = rwnx_send_vendor_hwconfig_req_x2(priv, hwconfig_id, addr, addr_out);
printk("CHIP_TEMP_GET_REQ degree=%d\n", addr_out[0]);
}
break;
case 6: // STBC_MCS_SET_REQ
if (ret != 3) {
printk("param error != 3\n");
} else {
printk("ret=%d, id=%d, param=%x, %x\n", ret, hwconfig_id, addr[0], addr[1]);
ret = rwnx_send_vendor_hwconfig_req_x2(priv, hwconfig_id, addr, addr_out);
}
break;
case 7:
printk("ret=%d, id=%d, param=%x, %x\n", ret, hwconfig_id, addr[0], addr[1]);
ret = rwnx_send_vendor_hwconfig_req_x2(priv, hwconfig_id, addr, addr_out);
break;
case 8:
case 9:
case 10:
case 11:
case 12:
ret = rwnx_send_vendor_hwconfig_req_x2(priv, hwconfig_id, addr, addr_out);
break;
default:
printk("param error:%d\n", hwconfig_id);
break;
}
if(ret) {
printk("rwnx_send_vendor_hwconfig_req fail: %x\n", ret);
}
}
return count;
}
DEBUGFS_WRITE_FILE_OPS(vendor_hwconfig_x2);
static ssize_t rwnx_dbgfs_vendor_swconfig_x2_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct rwnx_hw *priv = file->private_data;
char buf[64];
int32_t addr[12];
int32_t addr_out[12];
u32_l swconfig_id;
size_t len = min_t(size_t, count, sizeof(buf) - 1);
int ret;
printk("%s\n", __func__);
if (copy_from_user(buf, user_buf, len)) {
return -EFAULT;
}
buf[len] = '\0';
ret = sscanf(buf, "%x %x %x", &swconfig_id, &addr[0], &addr[1]);
if (ret > 3) {
printk("param error > 3\n");
} else {
switch (swconfig_id)
{
case 0: // BCN_CFG_REQ
if (ret != 2) {
printk("param error != 2\n");
} else {
ret = rwnx_send_vendor_swconfig_req_x2(priv, swconfig_id, addr, addr_out);
printk("BCN_CFG_REQ set_en=%d, get_en=%d\n", addr[0], addr_out[0]);
}
break;
case 1: // TEMP_COMP_SET_REQ
if (ret != 3) {
printk("param error != 3\n");
} else {
ret = rwnx_send_vendor_swconfig_req_x2(priv, swconfig_id, addr, addr_out);
printk("TEMP_COMP_SET_REQ set_en=%d, tmr=%dms, get_st=%d\n",
addr[0], addr[1], addr_out[0]);
}
break;
case 2: // TEMP_COMP_GET_REQ
if (ret != 1) {
printk("param error != 1\n");
} else {
ret = rwnx_send_vendor_swconfig_req_x2(priv, swconfig_id, addr, addr_out);
printk("TEMP_COMP_GET_REQ get_st=%d, degree=%d\n", addr_out[0], addr_out[1]);
}
break;
case 3: // EXT_FLAGS_SET_REQ
if (ret != 2) {
printk("param error != 2\n");
} else {
ret = rwnx_send_vendor_swconfig_req_x2(priv, swconfig_id, addr, addr_out);
printk("EXT_FLAGS_SET_REQ set ext_flags=0x%x, get ext_flags=0x%x\n",
addr[0], addr_out[0]);
}
break;
case 4: // EXT_FLAGS_GET_REQ
if (ret != 1) {
printk("param error != 1\n");
} else {
ret = rwnx_send_vendor_swconfig_req_x2(priv, swconfig_id, addr, addr_out);
printk("EXT_FLAGS_GET_REQ get ext_flags=0x%x\n", addr_out[0]);
}
break;
case 5: // EXT_FLAGS_MASK_SET_REQ
if (ret != 3) {
printk("param error != 3\n");
} else {
ret = rwnx_send_vendor_swconfig_req_x2(priv, swconfig_id, addr, addr_out);
printk("EXT_FLAGS_MASK_SET_REQ set ext_flags mask=0x%x, val=0x%x, get ext_flags=0x%x\n",
addr[0], addr[1], addr_out[0]);
}
break;
case 6: // TWO_ANT_RSSI_GET_REQ
ret = rwnx_send_vendor_swconfig_req_x2(priv, swconfig_id, addr, addr_out);
printk("2 ant rssi=%x\n", addr_out[0]);
break;
default:
printk("param error\n");
break;
}
if (ret) {
printk("rwnx_send_vendor_swconfig_req fail: %x\n", ret);
}
}
return count;
}
DEBUGFS_WRITE_FILE_OPS(vendor_swconfig_x2);
static ssize_t rwnx_dbgfs_agg_disable_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
@@ -2157,7 +2373,7 @@ static ssize_t rwnx_dbgfs_last_rx_read(struct file *file,
nss = last_rx->ht.mcs / 8;;
gi = last_rx->ht.short_gi;
} else {
BUG_ON((mcs = legrates_lut[last_rx->leg_rate]) == -1);
BUG_ON((mcs = legrates_lut[last_rx->leg_rate].idx) == -1);
nss = 0;
gi = 0;
}
@@ -2436,6 +2652,8 @@ int rwnx_dbgfs_register(struct rwnx_hw *rwnx_hw, const char *name)
DEBUGFS_ADD_FILE(regdbg, dir_drv, S_IWUSR);
DEBUGFS_ADD_FILE(vendor_hwconfig, dir_drv,S_IWUSR);
DEBUGFS_ADD_FILE(vendor_swconfig, dir_drv,S_IWUSR);
DEBUGFS_ADD_FILE(vendor_hwconfig_x2, dir_drv,S_IWUSR);
DEBUGFS_ADD_FILE(vendor_swconfig_x2, dir_drv,S_IWUSR);
DEBUGFS_ADD_FILE(agg_disable, dir_drv,S_IWUSR);
DEBUGFS_ADD_FILE(set_roc, dir_drv,S_IWUSR);
DEBUGFS_ADD_FILE(dbg_level, dir_drv, S_IWUSR | S_IRUSR);
+145 -12
View File
@@ -33,6 +33,9 @@
#ifdef CONFIG_FILTER_TCP_ACK
#include "aicwf_tcp_ack.h"
#endif
#ifdef CONFIG_BAND_STEERING
#include "aicwf_steering.h"
#endif
#ifdef AICWF_SDIO_SUPPORT
#include "aicwf_sdio.h"
@@ -73,6 +76,24 @@
#define HIGH_KERNEL_VERSION4 KERNEL_VERSION(6, 3, 0)
#endif
#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION
#ifndef IEEE80211_MAX_AMPDU_BUF
#define IEEE80211_MAX_AMPDU_BUF IEEE80211_MAX_AMPDU_BUF_HE
#endif
#ifndef IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB
#define IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB
#endif
#ifndef IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB
#define IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB
#endif
#ifndef IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA
#define IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU
#endif
#endif
#ifndef IEEE80211_MAX_AMPDU_BUF
#define IEEE80211_MAX_AMPDU_BUF 0x100
#endif
@@ -86,14 +107,6 @@
#define IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA 0x40
#endif
#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION
#define IEEE80211_MAX_AMPDU_BUF IEEE80211_MAX_AMPDU_BUF_HE
#define IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB
#define IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB
#define IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL)
enum nl80211_ac {
NL80211_AC_VO,
@@ -200,6 +213,38 @@ enum nl80211_mesh_power_mode {
};
#endif
#ifdef CONFIG_BAND_STEERING
enum band_type {
BAND_ON_24G = 0,
BAND_ON_5G = 1,
BAND_ON_60G = 2,
BAND_ON_6G = 3,
BAND_MAX,
};
enum WIFI_FRAME_TYPE {
WIFI_MGT_TYPE = (0),
};
enum WIFI_FRAME_SUBTYPE {
WIFI_ASSOCREQ = (0 | WIFI_MGT_TYPE),
WIFI_PROBEREQ = (BIT(6) | WIFI_MGT_TYPE),
WIFI_AUTH = (BIT(7) | BIT(5) | BIT(4) | WIFI_MGT_TYPE),
};
struct tmp_feature_sta {
u8_l sta_idx;
u8_l supported_band;
};
#define MAX_PENDING_PROBES 3
struct ap_probe_rsp {
u8_l da[6];
struct work_struct rsp_work;
bool in_use;
};
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)
#define NL80211_MESHCONF_POWER_MODE 26
@@ -217,6 +262,7 @@ enum nl80211_mesh_power_mode {
#endif
/**
* struct rwnx_bcn - Information of the beacon in used (AP mode)
*
@@ -356,7 +402,6 @@ struct rwnx_vif {
struct rwnx_key key[6];
unsigned long drv_flags;
atomic_t drv_conn_state;
u8 is_conn;
u8 drv_vif_index; /* Identifier of the VIF in driver */
u8 vif_index; /* Identifier of the station in FW */
u8 ch_index; /* Channel context identifier */
@@ -407,6 +452,12 @@ struct rwnx_vif {
bool create_path; /* Indicate if we are waiting for a MESH_CREATE_PATH_CFM
message */
int generation; /* Increased each time the list of Mesh Paths is updated */
#ifdef CONFIG_BAND_STEERING
u8_l tmp_sta_idx;
enum band_type band;
u32_l freq;
bool start;
#endif
enum nl80211_mesh_power_mode mesh_pm; /* mesh power save mode currently set in firmware */
enum nl80211_mesh_power_mode next_mesh_pm; /* mesh power save mode for next peer */
} ap;
@@ -435,6 +486,13 @@ struct rwnx_vif {
struct br_ext_info ethBrExtInfo;
#endif /* CONFIG_BR_SUPPORT */
#ifdef CONFIG_BAND_STEERING
struct workqueue_struct *rsp_wq;
struct timer_list steer_timer;
struct work_struct steer_work;
struct b_steer_priv bsteerpriv;
struct ap_probe_rsp pb_pool[MAX_PENDING_PROBES];
#endif
};
@@ -479,10 +537,18 @@ struct rwnx_rx_rate_stats {
* @rx_rate: Statistics of the received rates
*/
struct rwnx_sta_stats {
//#ifdef CONFIG_RWNX_DEBUGFS
u32 rx_pkts;
u32 tx_pkts;
u64 rx_bytes;
u64 tx_bytes;
unsigned long last_act;
struct hw_vect last_rx;
struct rwnx_rx_rate_stats rx_rate;
//#endif
u32 last_chan_time;
u32 last_chan_busy_time;
u32 tx_ack_succ_stat;
u32 tx_ack_fail_stat;
u32 last_chan_tx_busy_time;
};
#if (defined CONFIG_HE_FOR_OLD_KERNEL) || (defined CONFIG_VHT_FOR_OLD_KERNEL)
@@ -490,6 +556,14 @@ struct aic_sta {
u8 sta_idx; /* Identifier of the station */
bool he; /* Flag indicating if the station supports HE */
bool vht; /* Flag indicating if the station supports VHT */
struct ieee80211_he_cap_elem he_cap_elem;
struct ieee80211_he_mcs_nss_supp he_mcs_nss_supp;
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL)
__le32 vht_cap_info;
struct ieee80211_vht_mcs_info supp_mcs;
#endif
};
#endif
@@ -537,6 +611,17 @@ struct rwnx_sta {
struct rwnx_tdls tdls; /* TDLS station information */
struct rwnx_sta_stats stats;
enum nl80211_mesh_power_mode mesh_pm; /* link-specific mesh power save mode */
#ifdef CONFIG_DYNAMIC_PERPWR
s8_l rssi_save;
s8_l per_pwrloss;
struct work_struct per_pwr_work;
unsigned long last_jiffies;
#endif
#ifdef CONFIG_BAND_STEERING
u32_l link_time;
s8_l rssi;
u8_l support_band;
#endif
};
static inline const u8 *rwnx_sta_addr(struct rwnx_sta *rwnx_sta) {
@@ -620,13 +705,41 @@ struct rwnx_phy_info {
bool limit_bw;
};
struct defrag_ctrl_info {
struct list_head list;
u8 sta_idx;
u8 tid;
u16 sn;
u8 next_fn;
u16 frm_len;
struct sk_buff *skb;
struct timer_list defrag_timer;
struct rwnx_hw *rwnx_hw;
};
struct amsdu_subframe_hdr {
u8 da[6];
u8 sa[6];
u16 sublen;
};
/* rwnx driver status */
void rwnx_set_conn_state(atomic_t *drv_conn_state, int state);
enum rwnx_drv_connect_status {
RWNX_DRV_STATUS_DISCONNECTED = 0,
RWNX_DRV_STATUS_DISCONNECTING,
RWNX_DRV_STATUS_CONNECTING,
RWNX_DRV_STATUS_CONNECTED,
RWNX_DRV_STATUS_ROAMING,
};
static const char *const s_conn_state[] = {
"RWNX_DRV_STATUS_DISCONNECTED",
"RWNX_DRV_STATUS_DISCONNECTING",
"RWNX_DRV_STATUS_CONNECTING",
"RWNX_DRV_STATUS_CONNECTED",
"RWNX_DRV_STATUS_ROAMING",
};
@@ -735,10 +848,19 @@ struct rwnx_hw {
bool scanning;
bool p2p_working;
struct list_head defrag_list;
spinlock_t defrag_lock;
struct work_struct apmStalossWork;
struct workqueue_struct *apmStaloss_wq;
u8 apm_vif_idx;
u8 sta_mac_addr[6];
struct wakeup_source *ws_rx;
struct wakeup_source *ws_irqrx;
struct wakeup_source *ws_tx;
struct wakeup_source *ws_pwrctrl;
#ifdef CONFIG_SCHED_SCAN
bool is_sched_scan;
#endif//CONFIG_SCHED_SCAN
@@ -760,9 +882,20 @@ struct rwnx_hw {
bool wext_scan;
struct completion wext_scan_com;
struct list_head wext_scanre_list;
char wext_essid[32];
char wext_essid[33];
int support_freqs[SCAN_CHANNEL_MAX];
int support_freqs_number;
#ifdef CONFIG_DYNAMIC_PWR
struct timer_list pwrloss_timer;
struct work_struct pwrloss_work;
struct rwnx_vif *read_rssi_vif;
s8 pwrloss_lvl;
u8 sta_rssi_idx;
#endif
#endif
#ifdef CONFIG_BAND_STEERING
u8_l iface_idx;
struct tmp_feature_sta feature_table[NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX];
#endif
};
File diff suppressed because it is too large Load Diff
+39
View File
@@ -15,6 +15,9 @@
int rwnx_cfg80211_init(struct rwnx_plat *rwnx_plat, void **platform_data);
void rwnx_cfg80211_deinit(struct rwnx_hw *rwnx_hw);
int rwnx_fill_station_info(struct rwnx_sta *sta, struct rwnx_vif *vif,
struct station_info *sinfo, u8 *phymode, u32 *tx_phyrate, u32 *rx_phyrate);
extern int testmode;
extern u8 chip_id;
extern u8 chip_sub_id;
@@ -23,4 +26,40 @@ extern u8 chip_mcu_id;
#define CHIP_ID_H_MASK 0xC0
#define IS_CHIP_ID_H() ((chip_id & CHIP_ID_H_MASK) == CHIP_ID_H_MASK)
#define RSSI_GET_INTERVAL (10 * 1000) //time interval
#define RSSI_THD_0 (-20) //rssi 0 (dBm)
#define RSSI_THD_1 (-30) //rssi 1 (dBm)
#define RSSI_THD_2 (-75) //rssi 2 (dBm)
#define PWR_LOSS_LVL0 (-10) //RSSI > RSSI_THD_0
#define PWR_LOSS_LVL1 (-5 ) //RSSI_THD_1 < RSSI <RSSI_THD_0
#define PWR_LOSS_LVL2 (0) //RSSI_THD_2 < RSSI <RSSI_THD_1
#define PWR_LOSS_LVL3 (0)//(2) //RSSI <RSSI_THD_2
#define PWR_DELAY_TIME (10 * 1000) //pwr reduced latency time (ms)
struct rwnx_sta *rwnx_retrieve_sta(struct rwnx_hw *rwnx_hw,
struct rwnx_vif *rwnx_vif, u8 *addr,
__le16 fc, bool ap);
#ifdef CONFIG_BAND_STEERING
void aicwf_steering_work(struct work_struct *work);
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
void aicwf_steering_timeout(ulong data);
#else
void aicwf_steering_timeout(struct timer_list *t);
#endif
#endif
#ifdef CONFIG_DYNAMIC_PERPWR
void rssi_update_txpwrloss(struct rwnx_sta *sta, s8_l rssi);
void aicwf_txpwer_per_sta_worker(struct work_struct *work);
#endif
#ifdef CONFIG_DYNAMIC_PWR
void set_txpwrloss_ctrl(struct rwnx_hw *rwnx_hw, s8 value);
void aicwf_pwrloss_worker(struct work_struct *work);
#endif
#endif /* _RWNX_MAIN_H_ */
+124 -37
View File
@@ -27,6 +27,8 @@
#define FULLMAC_PARAM(name, default) .name = default,
#endif /* CONFIG_RWNX_FULLMAC */
extern int reg_regdb_size;
struct rwnx_mod_params rwnx_mod_params = {
/* common parameters */
COMMON_PARAM(ht_on, true, true)
@@ -44,8 +46,8 @@ struct rwnx_mod_params rwnx_mod_params = {
COMMON_PARAM(sgi, true, true)
COMMON_PARAM(sgi80, true, true)
COMMON_PARAM(use_2040, 1, 1)
COMMON_PARAM(nss, 1, 1)
COMMON_PARAM(amsdu_rx_max, 2, 2)
COMMON_PARAM(nss, 2, 2)
COMMON_PARAM(amsdu_rx_max, 1, 1)
COMMON_PARAM(bfmee, true, true)
COMMON_PARAM(bfmer, false, false)
COMMON_PARAM(mesh, true, true)
@@ -355,7 +357,7 @@ struct ieee80211_regdomain *getRegdomainFromRwnxDB(struct wiphy *wiphy,
idx = 0;
while (reg_regdb[idx]){
while (reg_regdb[idx] && idx < reg_regdb_size){
if((reg_regdb[idx]->alpha2[0] == alpha2[0]) &&
(reg_regdb[idx]->alpha2[1] == alpha2[1])){
memcpy(country_code, alpha2, 2);
@@ -718,6 +720,9 @@ static void rwnx_set_vht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
return;
}
if(rwnx_hw->usbdev->chipid <= PRODUCT_ID_AIC8800D81)
nss = 1;
rwnx_hw->vht_cap_2G.vht_supported = true;
if (rwnx_hw->mod_params->sgi80)
rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
@@ -733,9 +738,11 @@ static void rwnx_set_vht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
rwnx_hw->vht_cap_2G.cap |= 3 << 13;
#endif
}
if (nss > 1)
if((rwnx_hw->usbdev->chipid == PRODUCT_ID_AIC8800D81X2 ||
rwnx_hw->usbdev->chipid == PRODUCT_ID_AIC8800D89X2) &&
rwnx_hw->mod_params->stbc_on == true){ //if (nss > 1)
rwnx_hw->vht_cap_2G.cap |= IEEE80211_VHT_CAP_TXSTBC;
}
// Update the AMSDU max RX size (not shifted as located at offset 0 of the VHT cap)
rwnx_hw->vht_cap_2G.cap |= rwnx_hw->mod_params->amsdu_rx_max;
@@ -782,7 +789,7 @@ static void rwnx_set_vht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
for (i = 0; i < nss; i++) {
rwnx_hw->vht_cap_2G.vht_mcs.rx_mcs_map |= cpu_to_le16(mcs_map << (i*2));
rwnx_hw->vht_cap_2G.vht_mcs.rx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max);
mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_7;
//mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9;
}
for (; i < 8; i++) {
rwnx_hw->vht_cap_2G.vht_mcs.rx_mcs_map |= cpu_to_le16(
@@ -794,8 +801,8 @@ static void rwnx_set_vht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
for (i = 0; i < nss; i++) {
rwnx_hw->vht_cap_2G.vht_mcs.tx_mcs_map |= cpu_to_le16(mcs_map << (i*2));
rwnx_hw->vht_cap_2G.vht_mcs.tx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max);
mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map,
IEEE80211_VHT_MCS_SUPPORT_0_8);
//mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map,
// IEEE80211_VHT_MCS_SUPPORT_0_9);
}
for (; i < 8; i++) {
rwnx_hw->vht_cap_2G.vht_mcs.tx_mcs_map |= cpu_to_le16(
@@ -828,8 +835,11 @@ static void rwnx_set_vht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
rwnx_hw->vht_cap_5G.cap |= 3 << 13;
#endif
}
if (nss > 1)
if((rwnx_hw->usbdev->chipid == PRODUCT_ID_AIC8800D81X2 ||
rwnx_hw->usbdev->chipid == PRODUCT_ID_AIC8800D89X2) &&
rwnx_hw->mod_params->stbc_on == true){ //if (nss > 1)
rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_TXSTBC;
}
// Update the AMSDU max RX size (not shifted as located at offset 0 of the VHT cap)
rwnx_hw->vht_cap_5G.cap |= rwnx_hw->mod_params->amsdu_rx_max;
@@ -877,7 +887,7 @@ static void rwnx_set_vht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
for (i = 0; i < nss; i++) {
rwnx_hw->vht_cap_5G.vht_mcs.rx_mcs_map |= cpu_to_le16(mcs_map << (i*2));
rwnx_hw->vht_cap_5G.vht_mcs.rx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max);
mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_7;
//mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9;
}
for (; i < 8; i++) {
rwnx_hw->vht_cap_5G.vht_mcs.rx_mcs_map |= cpu_to_le16(
@@ -889,8 +899,8 @@ static void rwnx_set_vht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
for (i = 0; i < nss; i++) {
rwnx_hw->vht_cap_5G.vht_mcs.tx_mcs_map |= cpu_to_le16(mcs_map << (i*2));
rwnx_hw->vht_cap_5G.vht_mcs.tx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max);
mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map,
IEEE80211_VHT_MCS_SUPPORT_0_8);
//mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map,
// IEEE80211_VHT_MCS_SUPPORT_0_9);
}
for (; i < 8; i++) {
rwnx_hw->vht_cap_5G.vht_mcs.tx_mcs_map |= cpu_to_le16(
@@ -903,6 +913,8 @@ static void rwnx_set_vht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
#endif
rwnx_hw->vht_cap_5G.cap &= ~IEEE80211_VHT_CAP_SHORT_GI_80;
}
rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
}
#endif
return;
@@ -923,6 +935,10 @@ static void rwnx_set_vht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
return;
}
if(rwnx_hw->usbdev->chipid <= PRODUCT_ID_AIC8800D81){
nss = 1;
}
band_2GHz->vht_cap.vht_supported = true;
if (rwnx_hw->mod_params->sgi80)
band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
@@ -938,9 +954,11 @@ static void rwnx_set_vht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
band_2GHz->vht_cap.cap |= 3 << 13;
#endif
}
if (nss > 1)
if((rwnx_hw->usbdev->chipid == PRODUCT_ID_AIC8800D81X2 ||
rwnx_hw->usbdev->chipid == PRODUCT_ID_AIC8800D89X2) &&
rwnx_hw->mod_params->stbc_on == true){ //if (nss > 1)
band_2GHz->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
}
// Update the AMSDU max RX size (not shifted as located at offset 0 of the VHT cap)
band_2GHz->vht_cap.cap |= rwnx_hw->mod_params->amsdu_rx_max;
@@ -987,7 +1005,7 @@ static void rwnx_set_vht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
for (i = 0; i < nss; i++) {
band_2GHz->vht_cap.vht_mcs.rx_mcs_map |= cpu_to_le16(mcs_map << (i*2));
band_2GHz->vht_cap.vht_mcs.rx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max);
mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_7;
//mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9;
}
for (; i < 8; i++) {
band_2GHz->vht_cap.vht_mcs.rx_mcs_map |= cpu_to_le16(
@@ -999,8 +1017,8 @@ static void rwnx_set_vht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
for (i = 0; i < nss; i++) {
band_2GHz->vht_cap.vht_mcs.tx_mcs_map |= cpu_to_le16(mcs_map << (i*2));
band_2GHz->vht_cap.vht_mcs.tx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max);
mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map,
IEEE80211_VHT_MCS_SUPPORT_0_8);
//mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map,
// IEEE80211_VHT_MCS_SUPPORT_0_9);
}
for (; i < 8; i++) {
band_2GHz->vht_cap.vht_mcs.tx_mcs_map |= cpu_to_le16(
@@ -1032,8 +1050,12 @@ static void rwnx_set_vht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
band_5GHz->vht_cap.cap |= 3 << 13;
#endif
}
if (nss > 1)
if((rwnx_hw->usbdev->chipid == PRODUCT_ID_AIC8800D81X2 ||
rwnx_hw->usbdev->chipid == PRODUCT_ID_AIC8800D89X2) &&
rwnx_hw->mod_params->stbc_on == true){ //if (nss > 1)
band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
}
// Update the AMSDU max RX size (not shifted as located at offset 0 of the VHT cap)
band_5GHz->vht_cap.cap |= rwnx_hw->mod_params->amsdu_rx_max;
@@ -1081,7 +1103,7 @@ static void rwnx_set_vht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
for (i = 0; i < nss; i++) {
band_5GHz->vht_cap.vht_mcs.rx_mcs_map |= cpu_to_le16(mcs_map << (i*2));
band_5GHz->vht_cap.vht_mcs.rx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max);
mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_7;
//mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9;
}
for (; i < 8; i++) {
band_5GHz->vht_cap.vht_mcs.rx_mcs_map |= cpu_to_le16(
@@ -1093,8 +1115,8 @@ static void rwnx_set_vht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
for (i = 0; i < nss; i++) {
band_5GHz->vht_cap.vht_mcs.tx_mcs_map |= cpu_to_le16(mcs_map << (i*2));
band_5GHz->vht_cap.vht_mcs.tx_highest = MAX_VHT_RATE(mcs_map, nss, bw_max);
mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map,
IEEE80211_VHT_MCS_SUPPORT_0_8);
//mcs_map = min_t(int, rwnx_hw->mod_params->mcs_map,
// IEEE80211_VHT_MCS_SUPPORT_0_9);
}
for (; i < 8; i++) {
band_5GHz->vht_cap.vht_mcs.tx_mcs_map |= cpu_to_le16(
@@ -1131,6 +1153,9 @@ static void rwnx_set_ht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
return;
}
if(rwnx_hw->usbdev->chipid <= PRODUCT_ID_AIC8800D81)
nss = 1;
if (rwnx_hw->mod_params->stbc_on)
band_2GHz->ht_cap.cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT;
if (rwnx_hw->mod_params->ldpc_on)
@@ -1142,8 +1167,12 @@ static void rwnx_set_ht_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
} else {
band_2GHz->ht_cap.mcs.rx_highest = cpu_to_le16(65 * nss);
}
if (nss > 1)
if((rwnx_hw->usbdev->chipid == PRODUCT_ID_AIC8800D81X2 ||
rwnx_hw->usbdev->chipid == PRODUCT_ID_AIC8800D89X2) &&
rwnx_hw->mod_params->stbc_on == true){ //if (nss > 1)
band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
}
// Update the AMSDU max RX size
if (rwnx_hw->mod_params->amsdu_rx_max)
@@ -1182,6 +1211,9 @@ static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
int nss = rwnx_hw->mod_params->nss;
int mcs_map;
if(rwnx_hw->usbdev->chipid <= PRODUCT_ID_AIC8800D81)
nss = 1;
he_cap = (struct ieee80211_sta_he_cap *) &rwnx_he_capa.he_cap;
he_cap->has_he = true;
he_cap->he_cap_elem.mac_cap_info[2] |= IEEE80211_HE_MAC_CAP2_ALL_ACK;
@@ -1193,7 +1225,13 @@ static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
if (rwnx_hw->mod_params->use_80) {
he_cap->ppe_thres[0] |= 0x20;
he_cap->ppe_thres[2] |= 0xc0;
he_cap->ppe_thres[3] |= 0x07;
he_cap->ppe_thres[3] |= 0x01;
}
if (nss == 2) {
he_cap->ppe_thres[0] |= 0x01;
he_cap->ppe_thres[3] |= 0x70;
he_cap->ppe_thres[4] |= 0x1c;
he_cap->ppe_thres[5] |= 0x07;
}
//if (rwnx_hw->mod_params->use_80)
{
@@ -1222,6 +1260,13 @@ static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
#endif
if (rwnx_hw->mod_params->stbc_on)
he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ;
if((rwnx_hw->usbdev->chipid == PRODUCT_ID_AIC8800D81X2 ||
rwnx_hw->usbdev->chipid == PRODUCT_ID_AIC8800D89X2) &&
rwnx_hw->mod_params->stbc_on == true){ //if (nss > 1)
he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0)
he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM |
IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 |
@@ -1253,7 +1298,7 @@ static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT |
IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO;
#endif
he_cap->he_cap_elem.phy_cap_info[7] |= IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI;
//he_cap->he_cap_elem.phy_cap_info[7] |= IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI;
he_cap->he_cap_elem.phy_cap_info[8] |= IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G;
he_cap->he_cap_elem.phy_cap_info[9] |= IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB;
@@ -1265,7 +1310,7 @@ static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
he_cap->he_mcs_nss_supp.rx_mcs_80 |= cpu_to_le16(mcs_map << (i*2));
he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss;
he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss;
mcs_map = IEEE80211_HE_MCS_SUPPORT_0_7;
//mcs_map = IEEE80211_HE_MCS_SUPPORT_0_7;
}
for (; i < 8; i++) {
__le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2));
@@ -1279,8 +1324,8 @@ static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
he_cap->he_mcs_nss_supp.tx_mcs_80 |= cpu_to_le16(mcs_map << (i*2));
he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss;
he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss;
mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map,
IEEE80211_HE_MCS_SUPPORT_0_7);
//mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map,
// IEEE80211_HE_MCS_SUPPORT_0_7);
}
for (; i < 8; i++) {
__le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2));
@@ -1312,6 +1357,10 @@ static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
//#endif
return;
}
if(rwnx_hw->usbdev->chipid <= PRODUCT_ID_AIC8800D81)
nss = 1;
he_cap = (struct ieee80211_sta_he_cap *) &band_2GHz->iftype_data->he_cap;
he_cap->has_he = true;
he_cap->he_cap_elem.mac_cap_info[2] |= IEEE80211_HE_MAC_CAP2_ALL_ACK;
@@ -1323,7 +1372,13 @@ static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
if (rwnx_hw->mod_params->use_80) {
he_cap->ppe_thres[0] |= 0x20;
he_cap->ppe_thres[2] |= 0xc0;
he_cap->ppe_thres[3] |= 0x07;
he_cap->ppe_thres[3] |= 0x01;
}
if (nss == 2) {
he_cap->ppe_thres[0] |= 0x01;
he_cap->ppe_thres[3] |= 0x70;
he_cap->ppe_thres[4] |= 0x1c;
he_cap->ppe_thres[5] |= 0x07;
}
//if (rwnx_hw->mod_params->use_80)
{
@@ -1352,6 +1407,13 @@ static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
#endif
if (rwnx_hw->mod_params->stbc_on)
he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ;
if((rwnx_hw->usbdev->chipid == PRODUCT_ID_AIC8800D81X2 ||
rwnx_hw->usbdev->chipid == PRODUCT_ID_AIC8800D89X2) &&
rwnx_hw->mod_params->stbc_on == true){ //if (nss > 1)
he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0)
he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM |
IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 |
@@ -1383,7 +1445,7 @@ static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT |
IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO;
#endif
he_cap->he_cap_elem.phy_cap_info[7] |= IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI;
//he_cap->he_cap_elem.phy_cap_info[7] |= IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI;
he_cap->he_cap_elem.phy_cap_info[8] |= IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
he_cap->he_cap_elem.phy_cap_info[9] |= IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
@@ -1401,7 +1463,7 @@ static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
he_cap->he_mcs_nss_supp.rx_mcs_80 |= cpu_to_le16(mcs_map << (i*2));
he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss;
he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss;
mcs_map = IEEE80211_HE_MCS_SUPPORT_0_7;
//mcs_map = IEEE80211_HE_MCS_SUPPORT_0_7;
}
for (; i < 8; i++) {
__le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2));
@@ -1415,8 +1477,8 @@ static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
he_cap->he_mcs_nss_supp.tx_mcs_80 |= cpu_to_le16(mcs_map << (i*2));
he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss;
he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss;
mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map,
IEEE80211_HE_MCS_SUPPORT_0_7);
//mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map,
// IEEE80211_HE_MCS_SUPPORT_0_7);
}
for (; i < 8; i++) {
__le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2));
@@ -1438,7 +1500,13 @@ static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
if (rwnx_hw->mod_params->use_80) {
he_cap->ppe_thres[0] |= 0x20;
he_cap->ppe_thres[2] |= 0xc0;
he_cap->ppe_thres[3] |= 0x07;
he_cap->ppe_thres[3] |= 0x01;
}
if (nss == 2) {
he_cap->ppe_thres[0] |= 0x01;
he_cap->ppe_thres[3] |= 0x70;
he_cap->ppe_thres[4] |= 0x1c;
he_cap->ppe_thres[5] |= 0x07;
}
//if (rwnx_hw->mod_params->use_80)
{
@@ -1466,6 +1534,13 @@ static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
#endif
if (rwnx_hw->mod_params->stbc_on)
he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ;
if((rwnx_hw->usbdev->chipid == PRODUCT_ID_AIC8800D81X2 ||
rwnx_hw->usbdev->chipid == PRODUCT_ID_AIC8800D89X2) &&
rwnx_hw->mod_params->stbc_on == true){ //if (nss > 1)
he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0)
he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM |
IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 |
@@ -1497,7 +1572,7 @@ static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT |
IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO;
#endif
he_cap->he_cap_elem.phy_cap_info[7] |= IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI;
//he_cap->he_cap_elem.phy_cap_info[7] |= IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI;
he_cap->he_cap_elem.phy_cap_info[8] |= IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
he_cap->he_cap_elem.phy_cap_info[9] |= IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB |
@@ -1515,7 +1590,7 @@ static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
he_cap->he_mcs_nss_supp.rx_mcs_80 |= cpu_to_le16(mcs_map << (i*2));
he_cap->he_mcs_nss_supp.rx_mcs_160 |= unsup_for_ss;
he_cap->he_mcs_nss_supp.rx_mcs_80p80 |= unsup_for_ss;
mcs_map = IEEE80211_HE_MCS_SUPPORT_0_7;
//mcs_map = IEEE80211_HE_MCS_SUPPORT_0_7;
}
for (; i < 8; i++) {
__le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2));
@@ -1529,8 +1604,8 @@ static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
he_cap->he_mcs_nss_supp.tx_mcs_80 |= cpu_to_le16(mcs_map << (i*2));
he_cap->he_mcs_nss_supp.tx_mcs_160 |= unsup_for_ss;
he_cap->he_mcs_nss_supp.tx_mcs_80p80 |= unsup_for_ss;
mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map,
IEEE80211_HE_MCS_SUPPORT_0_7);
//mcs_map = min_t(int, rwnx_hw->mod_params->he_mcs_map,
// IEEE80211_HE_MCS_SUPPORT_0_7);
}
for (; i < 8; i++) {
__le16 unsup_for_ss = cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << (i*2));
@@ -1704,20 +1779,32 @@ int rwnx_handle_dynparams(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
//check he_mcs max
if(rwnx_hw->usbdev->chipid != PRODUCT_ID_AIC8800D81 &&
rwnx_hw->usbdev->chipid != PRODUCT_ID_AIC8800D81X2 &&
rwnx_hw->usbdev->chipid != PRODUCT_ID_AIC8800D89X2 &&
rwnx_hw->mod_params->he_mcs_map > IEEE80211_HE_MCS_SUPPORT_0_9){
rwnx_hw->mod_params->he_mcs_map = IEEE80211_HE_MCS_SUPPORT_0_9;
} else {
rwnx_hw->mod_params->he_mcs_map = IEEE80211_HE_MCS_SUPPORT_0_11;
}
//check use_80 support
if(rwnx_hw->usbdev->chipid != PRODUCT_ID_AIC8800D81 &&
rwnx_hw->usbdev->chipid != PRODUCT_ID_AIC8800D81X2 &&
rwnx_hw->usbdev->chipid != PRODUCT_ID_AIC8800D89X2 &&
rwnx_hw->mod_params->use_80 == true){
rwnx_hw->mod_params->use_80 = false;
} else {
rwnx_hw->mod_params->use_80 = true;
}
//check sgi80 support
if(rwnx_hw->usbdev->chipid != PRODUCT_ID_AIC8800D81 &&
rwnx_hw->usbdev->chipid != PRODUCT_ID_AIC8800D81X2 &&
rwnx_hw->usbdev->chipid != PRODUCT_ID_AIC8800D89X2 &&
rwnx_hw->mod_params->sgi80 == true){
rwnx_hw->mod_params->sgi80 = false;
} else {
rwnx_hw->mod_params->sgi80 = true;
}
#ifdef CONFIG_5M10M
rwnx_hw->mod_params->he_mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_7;
@@ -66,5 +66,11 @@ int rwnx_handle_dynparams(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy);
void rwnx_custregd(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy);
void rwnx_enable_wapi(struct rwnx_hw *rwnx_hw);
void rwnx_enable_mfp(struct rwnx_hw *rwnx_hw);
struct ieee80211_regdomain *getRegdomainFromRwnxDB(struct wiphy *wiphy,
char *alpha2);
struct ieee80211_regdomain *getRegdomainFromRwnxDBIndex(struct wiphy *wiphy,
int index);
#endif /* _RWNX_MOD_PARAM_H_ */
+113 -97
View File
@@ -396,6 +396,40 @@ static inline int rwnx_rx_pktloss_notify_ind(struct rwnx_hw *rwnx_hw,
return 0;
}
static inline int rwnx_radar_detect_ind(struct rwnx_hw *rwnx_hw,
struct rwnx_cmd *cmd,
struct ipc_e2a_msg *msg)
{
struct radar_pulse_array_desc *pulses = (struct radar_pulse_array_desc *)msg->param;
int i;
RWNX_DBG(RWNX_FN_ENTRY_STR);
//printk("%s\n", __func__);
if(pulses->cnt == 0) {
printk("cnt error\n");
return -1;
}
if(rwnx_radar_detection_is_enable(&rwnx_hw->radar, pulses->idx)) {
for(i=0; i<pulses->cnt; i++) {
struct rwnx_radar_pulses *p = &rwnx_hw->radar.pulses[pulses->idx];
p->buffer[p->index] = pulses->pulse[i];
p->index = (p->index + 1)%RWNX_RADAR_PULSE_MAX;
if(p->count < RWNX_RADAR_PULSE_MAX)
p->count++;
//printk("pulse=%x\n", pulses->pulse[i]);
}
if(!work_pending(&rwnx_hw->radar.detection_work))
schedule_work(&rwnx_hw->radar.detection_work);
} else
printk("not enable\n");
return 0;
}
static inline int rwnx_apm_staloss_ind(struct rwnx_hw *rwnx_hw,
struct rwnx_cmd *cmd,
struct ipc_e2a_msg *msg)
@@ -681,6 +715,11 @@ static inline int rwnx_rx_scanu_result_ind(struct rwnx_hw *rwnx_hw,
struct ieee80211_channel *chan;
struct scanu_result_ind *ind = (struct scanu_result_ind *)msg->param;
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)ind->payload;
u64 tsf;
u8 *ie;
size_t ielen;
u16 capability, beacon_interval;
u16 len = ind->length;
#if 0
const u8 *ie = mgmt->u.beacon.variable;
@@ -699,20 +738,34 @@ static inline int rwnx_rx_scanu_result_ind(struct rwnx_hw *rwnx_hw,
chan = ieee80211_get_channel(rwnx_hw->wiphy, ind->center_freq);
if (chan != NULL) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
//ktime_t ts;
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
struct timespec ts;
get_monotonic_boottime(&ts);
//ts = ktime_get_real();
tsf = (u64)ts.tv_sec * 1000000 + div_u64(ts.tv_nsec, 1000);
mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000) + ts.tv_nsec/1000;
#else
#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0)
struct timespec ts;
ts = ktime_to_timespec(ktime_get_boottime());
tsf = (u64)ts.tv_sec * 1000000 + div_u64(ts.tv_nsec, 1000);
mgmt->u.probe_resp.timestamp = tsf;
#else
struct timespec64 ts;
ktime_get_real_ts64(&ts);
mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000) + ts.tv_nsec/1000;
#endif
bss = cfg80211_inform_bss_frame(rwnx_hw->wiphy, chan,
(struct ieee80211_mgmt *)ind->payload,
ind->length, ind->rssi * 100, GFP_ATOMIC);
ts = ktime_to_timespec64(ktime_get_boottime());
tsf = (u64)ts.tv_sec * 1000000 + div_u64(ts.tv_nsec, 1000);
mgmt->u.probe_resp.timestamp = tsf;
#endif
ie = mgmt->u.probe_resp.variable;
ielen = len - offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
/* framework use system bootup time */
bss = cfg80211_inform_bss(rwnx_hw->wiphy, chan,
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
CFG80211_BSS_FTYPE_UNKNOWN,
#endif
mgmt->bssid, tsf, capability, beacon_interval,
ie, ielen, ind->rssi * 100, GFP_ATOMIC);
#if 0
//print scan result info start
if(ie != NULL && bss != NULL){
@@ -737,7 +790,12 @@ static inline int rwnx_rx_scanu_result_ind(struct rwnx_hw *rwnx_hw,
#ifdef CONFIG_USE_WIRELESS_EXT
if(rwnx_hw->wext_scan){
list_for_each_entry(scan_re_wext, &rwnx_hw->wext_scanre_list, scanu_re_list) {
if (!memcmp(scan_re_wext->bss->bssid, bss->bssid, ETH_ALEN)) {
AICWFDBG(LOGDEBUG, "%s: BSSID already exists, no need to add again\r\n", __func__);
goto putbss;
}
}
scan_re_wext = (struct scanu_result_wext *)vmalloc(sizeof(struct scanu_result_wext));
scan_re_wext->ind = (struct scanu_result_ind *)vmalloc(sizeof(struct scanu_result_ind));
scan_re_wext->payload = (u32_l *)vmalloc(sizeof(u32_l) * ind->length);
@@ -757,7 +815,7 @@ static inline int rwnx_rx_scanu_result_ind(struct rwnx_hw *rwnx_hw,
#endif
}
putbss:
if (bss != NULL)
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)
cfg80211_put_bss(bss);
@@ -840,6 +898,7 @@ static inline void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
}
}
#endif
static inline int rwnx_rx_sm_connect_ind(struct rwnx_hw *rwnx_hw,
struct rwnx_cmd *cmd,
struct ipc_e2a_msg *msg)
@@ -851,9 +910,9 @@ static inline int rwnx_rx_sm_connect_ind(struct rwnx_hw *rwnx_hw,
const u8 *extcap_ie;
const struct ieee_types_extcap *extcap;
struct ieee80211_channel *chan;
struct cfg80211_bss *bss = NULL;
//struct cfg80211_bss *bss = NULL;
struct wireless_dev *wdev = NULL;
int retry_counter = 10;
//int retry_counter = 10;
RWNX_DBG(RWNX_FN_ENTRY_STR);
@@ -931,6 +990,13 @@ static inline int rwnx_rx_sm_connect_ind(struct rwnx_hw *rwnx_hw,
AICWFDBG(LOGDEBUG, "sta idx %d fc error %d\n", sta->sta_idx, atomic_read(&rwnx_hw->sta_flowctrl[sta->sta_idx].tx_pending_cnt));
}
#ifdef CONFIG_RADAR_OR_IR_DETECT
if (chan->flags & IEEE80211_CHAN_RADAR)
rwnx_radar_detection_enable(&rwnx_hw->radar,
RWNX_RADAR_DETECT_REPORT,
RWNX_RADAR_RIU);
#endif
if (rwnx_vif->wep_enabled)
rwnx_vif->wep_auth_err = false;
@@ -977,9 +1043,9 @@ static inline int rwnx_rx_sm_connect_ind(struct rwnx_hw *rwnx_hw,
rwnx_vif->wep_auth_err = true;
AICWFDBG(LOGINFO, "con ind wep_auth_err %d\n", rwnx_vif->wep_auth_err);
}
atomic_set(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED);
rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED);
}else{
atomic_set(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED);
rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED);
}
@@ -989,84 +1055,21 @@ static inline int rwnx_rx_sm_connect_ind(struct rwnx_hw *rwnx_hw,
ind->status_code,
(int)atomic_read(&rwnx_vif->drv_conn_state));
do {
bss = cfg80211_get_bss(wdev->wiphy, NULL, rwnx_vif->sta.bssid,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)
wdev->u.client.ssid, wdev->u.client.ssid_len,
#else
wdev->ssid, wdev->ssid_len,
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
wdev->conn_bss_type,
IEEE80211_PRIVACY_ANY);
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
IEEE80211_BSS_TYPE_ESS,
IEEE80211_PRIVACY_ANY);
#else
WLAN_CAPABILITY_ESS,
WLAN_CAPABILITY_PRIVACY);
#endif
if (!bss) {
printk("%s bss is NULL \r\n", __func__);
printk("%s bss ssid(%d):%s conn_bss_type:%d bss2 ssid(%d):%s conn_bss_type:%d\r\n",
__func__,
(int)rwnx_vif->sta.ssid_len,
rwnx_vif->sta.ssid,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
IEEE80211_BSS_TYPE_ESS,
#else
WLAN_CAPABILITY_ESS,
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)
(int)wdev->u.client.ssid_len,
wdev->u.client.ssid,
#else
(int)wdev->ssid_len,
wdev->ssid,
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
wdev->conn_bss_type
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
IEEE80211_BSS_TYPE_ESS
#else
WLAN_CAPABILITY_ESS
#endif
);
printk("%s rwnx_vif->sta.bssid %02x %02x %02x %02x %02x %02x \r\n", __func__,
rwnx_vif->sta.bssid[0], rwnx_vif->sta.bssid[1], rwnx_vif->sta.bssid[2],
rwnx_vif->sta.bssid[3], rwnx_vif->sta.bssid[4], rwnx_vif->sta.bssid[5]);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)
wdev->u.client.ssid_len = (int)rwnx_vif->sta.ssid_len;
memcpy(wdev->u.client.ssid, rwnx_vif->sta.ssid, wdev->u.client.ssid_len);
#else
wdev->ssid_len = (int)rwnx_vif->sta.ssid_len;
memcpy(wdev->ssid, rwnx_vif->sta.ssid, wdev->ssid_len);
#endif
msleep(100);
retry_counter--;
if(retry_counter == 0){
printk("%s bss recover fail \r\n", __func__);
break;
if(ind->status_code == 0 && (int)atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_DISCONNECTING){
AICWFDBG(LOGINFO, "%s the disconnection has been requested, return it\r\n", __func__);
goto exit;
}
}
} while (!bss);
if (!ind->roamed) {//not roaming
if (rwnx_vif->is_conn == 0) {
cfg80211_connect_result(dev, (const u8 *)ind->bssid.array, req_ie,
ind->assoc_req_ie_len, rsp_ie,
ind->assoc_rsp_ie_len, ind->status_code,
GFP_ATOMIC);
}
if (ind->status_code == 0) {
atomic_set(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_CONNECTED);
rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_CONNECTED);
} else {
atomic_set(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED);
rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED);
rwnx_external_auth_disable(rwnx_vif);
}
AICWFDBG(LOGINFO, "%s cfg80211_connect_result pass, rwnx_vif->drv_conn_state:%d\r\n", __func__, (int)atomic_read(&rwnx_vif->drv_conn_state));
@@ -1075,7 +1078,7 @@ static inline int rwnx_rx_sm_connect_ind(struct rwnx_hw *rwnx_hw,
if(ind->status_code != 0){
AICWFDBG(LOGINFO, "%s roaming fail to notify disconnect \r\n", __func__);
cfg80211_disconnected(dev, 0, NULL, 0,1, GFP_ATOMIC);
atomic_set(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED);
rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED);
rwnx_external_auth_disable(rwnx_vif);
}else{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
@@ -1099,7 +1102,6 @@ static inline int rwnx_rx_sm_connect_ind(struct rwnx_hw *rwnx_hw,
info.resp_ie_len = ind->assoc_rsp_ie_len;
AICWFDBG(LOGINFO, "%s roaming success to notify roam \r\n", __func__);
cfg80211_roamed(dev, &info, GFP_ATOMIC);
atomic_set(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_CONNECTED);
#else
chan = ieee80211_get_channel(rwnx_hw->wiphy, ind->center_freq);
AICWFDBG(LOGINFO, "%s roaming success to notify roam \r\n", __func__);
@@ -1114,11 +1116,21 @@ static inline int rwnx_rx_sm_connect_ind(struct rwnx_hw *rwnx_hw,
, ind->assoc_rsp_ie_len
, GFP_ATOMIC);
#endif /*LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)*/
atomic_set(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_CONNECTED);
rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_CONNECTED);
}
rwnx_vif->sta.is_roam = false;
}
if (ind->status_code == 0) {
netif_tx_start_all_queues(dev);
netif_carrier_on(dev);
}
exit:
rwnx_vif->sta.is_roam = false;
#ifdef CONFIG_DYNAMIC_PWR
rwnx_hw->sta_rssi_idx = ind->ap_idx;
#endif
return 0;
}
@@ -1167,7 +1179,8 @@ static inline int rwnx_rx_sm_disconnect_ind(struct rwnx_hw *rwnx_hw,
struct aicwf_rx_priv *rx_priv;
#endif
RWNX_DBG(RWNX_FN_ENTRY_STR);
//RWNX_DBG(RWNX_FN_ENTRY_STR);
AICWFDBG(LOGINFO, "%s reason code:%d \r\n", __func__, ind->reason_code);
if((int)atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_DISCONNECTED){
AICWFDBG(LOGINFO, "%s, is already disconnected, drop disconnect ind", __func__);
return 0;
@@ -1187,6 +1200,10 @@ static inline int rwnx_rx_sm_disconnect_ind(struct rwnx_hw *rwnx_hw,
AICWFDBG(LOGINFO, "%s roaming no rwnx_cfg80211_unlink_bss \r\n", __func__);
}
#ifdef CONFIG_DEBUG_FS
rwnx_dbgfs_unregister_rc_stat(rwnx_hw, rwnx_vif->sta.ap);
#endif
#ifdef CONFIG_BR_SUPPORT
struct rwnx_vif *vif = netdev_priv(dev);
/* clear bridge database */
@@ -1245,7 +1262,10 @@ static inline int rwnx_rx_sm_disconnect_ind(struct rwnx_hw *rwnx_hw,
rwnx_chanctx_unlink(rwnx_vif);
//msleep(200);
atomic_set(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED);
if (rwnx_vif->sta.is_roam == false) {
rwnx_set_conn_state(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED);
}
return 0;
}
@@ -1265,6 +1285,8 @@ static inline int rwnx_rx_sm_external_auth_required_ind(struct rwnx_hw *rwnx_hw,
RWNX_DBG(RWNX_FN_ENTRY_STR);
memset((void*)&params, 0, sizeof(struct cfg80211_external_auth_params));
params.action = NL80211_EXTERNAL_AUTH_START;
memcpy(params.bssid, ind->bssid.array, ETH_ALEN);
params.ssid.ssid_len = ind->ssid.length;
@@ -1282,13 +1304,6 @@ static inline int rwnx_rx_sm_external_auth_required_ind(struct rwnx_hw *rwnx_hw,
}
AICWFDBG(LOGINFO, "%s wdev->conn_owner_nlportid:%d \r\n", __func__, (int)wdev->conn_owner_nlportid);
if (wdev->conn_owner_nlportid != 0) {
rwnx_vif->sta.conn_owner_nlportid = wdev->conn_owner_nlportid;
} else {
AICWFDBG(LOGINFO, "%s try to recover conn_owner_nlportid\r\n", __func__);
wdev->conn_owner_nlportid = rwnx_vif->sta.conn_owner_nlportid;
}
if ((ind->vif_idx > NX_VIRT_DEV_MAX) || !rwnx_vif->up ||
(RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_STATION) ||
(ret = cfg80211_external_auth_request(dev, &params, GFP_ATOMIC))) {
@@ -1579,6 +1594,7 @@ static msg_cb_fct mm_hdlrs[MSG_I(MM_MAX)] = {
[MSG_I(MM_RSSI_STATUS_IND)] = rwnx_rx_rssi_status_ind,
[MSG_I(MM_PKTLOSS_IND)] = rwnx_rx_pktloss_notify_ind,
[MSG_I(MM_APM_STALOSS_IND)] = rwnx_apm_staloss_ind,
[MSG_I(MM_RADAR_DETECT_IND)] = rwnx_radar_detect_ind,
};
static msg_cb_fct scan_hdlrs[MSG_I(SCANU_MAX)] = {
File diff suppressed because it is too large Load Diff
+24 -1
View File
@@ -15,6 +15,11 @@
#include "rwnx_defs.h"
#ifdef RF_WRITE_FILE
#define FW_RF_CALIB_FILE "aic_rf_calib.bin"
#endif
int rwnx_send_reset(struct rwnx_hw *rwnx_hw);
int rwnx_send_start(struct rwnx_hw *rwnx_hw);
int rwnx_send_version_req(struct rwnx_hw *rwnx_hw, struct mm_version_cfm *cfm);
@@ -67,7 +72,7 @@ int rwnx_send_get_macaddr_req(struct rwnx_hw *rwnx_hw, struct mm_get_mac_addr_cf
#ifdef CONFIG_RWNX_FULLMAC
int rwnx_send_me_config_req(struct rwnx_hw *rwnx_hw);
int rwnx_send_me_chan_config_req(struct rwnx_hw *rwnx_hw);
int rwnx_send_me_chan_config_req(struct rwnx_hw *rwnx_hw, char *ccode);
int rwnx_send_me_set_control_port_req(struct rwnx_hw *rwnx_hw, bool opened,
u8 sta_idx);
int rwnx_send_me_sta_add(struct rwnx_hw *rwnx_hw, struct station_parameters *params,
@@ -153,6 +158,8 @@ int rwnx_send_dbg_get_sys_stat_req(struct rwnx_hw *rwnx_hw,
struct dbg_get_sys_stat_cfm *cfm);
int rwnx_send_dbg_mem_block_write_req(struct rwnx_hw *rwnx_hw, u32 mem_addr,
u32 mem_size, u32 *mem_data);
int rwnx_send_dbg_mem_block_read_req(struct rwnx_hw *rwnx_hw, u32 mem_addr,
u32 mem_size, struct dbg_mem_block_read_cfm *cfm);
int rwnx_send_dbg_start_app_req(struct rwnx_hw *rwnx_hw, u32 boot_addr,
u32 boot_type);
int rwnx_send_dbg_gpio_write_req(struct rwnx_hw *rwnx_hw, u8_l gpio_idx, u8_l gpio_val);
@@ -169,19 +176,35 @@ int rwnx_send_set_temp_comp_req(struct rwnx_hw *rwnx_hw, struct mm_set_vendor_sw
int rwnx_send_vendor_hwconfig_req(struct rwnx_hw *rwnx_hw, uint32_t hwconfig_id, int32_t *param, int32_t *param_out);
int rwnx_send_vendor_swconfig_req(struct rwnx_hw *rwnx_hw, uint32_t swconfig_id, int32_t *param_in, int32_t *param_out);
int rwnx_send_mask_set_ext_flags_req(struct rwnx_hw *rwnx_hw, uint32_t flags_mask, uint32_t flags_val, struct mm_set_vendor_swconfig_cfm *cfm);
int rwnx_send_vendor_hwconfig_req_x2(struct rwnx_hw *rwnx_hw, uint32_t hwconfig_id, int32_t *param, int32_t *param_out);
int rwnx_send_vendor_swconfig_req_x2(struct rwnx_hw *rwnx_hw, uint32_t swconfig_id, int32_t *param_in, int32_t *param_out);
int rwnx_send_get_fw_version_req(struct rwnx_hw *rwnx_hw, struct mm_get_fw_version_cfm *cfm);
int rwnx_send_txpwr_idx_req(struct rwnx_hw *rwnx_hw);
int rwnx_send_txpwr_ofst_req(struct rwnx_hw *rwnx_hw);
int rwnx_send_txpwr_ofst2x_req(struct rwnx_hw *rwnx_hw);
int rwnx_send_txpwr_ofst2x_v2_req(struct rwnx_hw *rwnx_hw);
int rwnx_send_set_filter(struct rwnx_hw *rwnx_hw, uint32_t filter);
int rwnx_send_txpwr_lvl_req(struct rwnx_hw *rwnx_hw);
int rwnx_send_txpwr_lvl_v3_req(struct rwnx_hw *rwnx_hw);
int rwnx_send_txpwr_lvl_v4_req(struct rwnx_hw *rwnx_hw);
int rwnx_send_txpwr_lvl_adj_req(struct rwnx_hw *rwnx_hw);
#ifdef CONFIG_WOWLAN
int rwnx_send_set_pkt_filter_req(struct rwnx_hw *rwnx_hw, u8_l *param);
int rwnx_send_dummy_reboot(struct rwnx_hw *rwnx_hw);
#endif
#ifdef CONFIG_DYNAMIC_PERPWR
int rwnx_send_txpwr_per_sta_req(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta);
#endif
//#ifdef CONFIG_USB_BT
int rwnx_send_reboot(struct rwnx_hw *rwnx_hw);
//#endif // CONFIG_USB_BT
int rwnx_send_pwm_init_req(struct rwnx_hw *rwnx_hw, u8 pwm_gpidx, u8 mode, u8 run, u32 tmr_cnt,
u32 dty_cnt, u32 step_val, u8 gpio_en, u8 gpio_dir, u8 gpio_val);
int rwnx_send_pwm_deinit_req(struct rwnx_hw *rwnx_hw, u8 pwm_gpidx, u8 gpio_en, u8 gpio_dir, u8 gpio_val);
void rwnx_set_pwm_tbl(struct rwnx_hw *rwnx_hw);
#endif /* _RWNX_MSG_TX_H_ */
File diff suppressed because it is too large Load Diff
+36 -2
View File
@@ -64,6 +64,31 @@ enum rwnx_platform_addr {
RWNX_ADDR_MAX,
};
typedef struct
{
txpwr_lvl_conf_t txpwr_lvl;
txpwr_lvl_conf_v2_t txpwr_lvl_v2;
txpwr_lvl_conf_v3_t txpwr_lvl_v3;
txpwr_lvl_conf_v4_t txpwr_lvl_v4;
txpwr_lvl_adj_conf_t txpwr_lvl_adj;
txpwr_loss_conf_t txpwr_loss;
txpwr_ofst_conf_t txpwr_ofst;
txpwr_ofst2x_conf_t txpwr_ofst2x;
txpwr_ofst2x_conf_v2_t txpwr_ofst2x_v2;
xtal_cap_conf_t xtal_cap;
} userconfig_info_t;
extern userconfig_info_t userconfig_info;
typedef enum {
REGIONS_SRRC,
REGIONS_FCC,
REGIONS_ETSI,
REGIONS_JP,
REGIONS_DEFAULT,
} Regions_code;
struct rwnx_hw;
/**
@@ -129,15 +154,24 @@ int is_file_exist(char* name);
void get_userconfig_txpwr_lvl_in_fdrv(txpwr_lvl_conf_t *txpwr_lvl);
void get_userconfig_txpwr_lvl_v2_in_fdrv(txpwr_lvl_conf_v2_t *txpwr_lvl_v2);
void get_userconfig_txpwr_lvl_v3_in_fdrv(txpwr_lvl_conf_v3_t *txpwr_lvl_v3);
void get_userconfig_txpwr_lvl_v4_in_fdrv(txpwr_lvl_conf_v4_t *txpwr_lvl_v4);
void get_userconfig_txpwr_lvl_adj_in_fdrv(txpwr_lvl_adj_conf_t *txpwr_lvl_adj);
void get_userconfig_txpwr_ofst_in_fdrv(txpwr_ofst_conf_t *txpwr_ofst);
void get_userconfig_txpwr_ofst2x_in_fdrv(txpwr_ofst2x_conf_t *txpwr_ofst2x);
void get_userconfig_txpwr_ofst2x_v2_in_fdrv(txpwr_ofst2x_conf_v2_t *txpwr_ofst2x_v2);
void get_userconfig_txpwr_loss(txpwr_loss_conf_t *txpwr_loss);
void set_txpwr_loss_ofst(s8_l value);
void rwnx_plat_userconfig_parsing(char *buffer, int size);
uint8_t get_ccode_region(char * ccode);
u8 get_region_index(char * name);
#ifdef CONFIG_POWER_LIMIT
int8_t rwnx_plat_powerlimit_save(u8_l band, char *channel, u8_l bw, char *limit, char *name);
void rwnx_plat_powerlimit_parsing(char *buffer, int size, char *cc);
int8_t get_powerlimit_by_freq(uint8_t band, uint16_t freq);
int8_t get_powerlimit_by_chnum(uint8_t chnum);
int8_t get_powerlimit_by_freq(uint8_t band, uint16_t freq, uint8_t r_idx);
int8_t get_powerlimit_by_chnum(uint8_t chnum, uint8_t r_idx, uint8_t bw);
#endif
int rwnx_platform_register_drv(void);
void rwnx_platform_unregister_drv(void);
+134 -16
View File
@@ -288,7 +288,7 @@ struct pri_detector {
*/
struct pri_detector_ops {
void (*init)(struct pri_detector *pde);
struct pri_sequence * (*add_pulse)(struct pri_detector *pde, u16 len, u64 ts, u16 pri);
struct pri_sequence * (*add_pulse)(struct rwnx_radar *radar, struct pri_detector *pde, u16 len, u64 ts, u16 pri);
int reset_on_pri_overflow;
};
@@ -708,7 +708,7 @@ static void pri_detector_reset(struct pri_detector *pde, u64 ts);
* - If not save this pulse in the list
*/
static
struct pri_sequence *pde_short_add_pulse(struct pri_detector *pde,
struct pri_sequence *pde_short_add_pulse(struct rwnx_radar *radar, struct pri_detector *pde,
u16 len, u64 ts, u16 pri)
{
u32 max_updated_seq;
@@ -798,12 +798,16 @@ void pde_long_init(struct pri_detector *pde)
* has been detected.
*/
static
struct pri_sequence *pde_long_add_pulse(struct pri_detector *pde,
struct pri_sequence *pde_long_add_pulse(struct rwnx_radar *radar, struct pri_detector *pde,
u16 len, u64 ts, u16 pri)
{
struct pri_sequence *ps;
const struct radar_detector_specs *rs = pde->rs;
if(radar->status != RWNX_RADAR_CAC_BUSY) {
return NULL;
}
if (list_empty(&pde->sequences)) {
/* First pulse, create a new sequence */
ps = pool_get_pseq_elem();
@@ -1066,6 +1070,35 @@ static void dfs_pattern_detector_pri_overflow(struct dfs_pattern_detector *dpd)
}
}
void print_radar_detect_info(struct pri_detector *pde, struct pri_sequence *ps)
{
struct radar_detector_specs *rs = (struct radar_detector_specs *)pde->rs;
struct pulse_elem *p;
u16 idx = 0;
AICWFDBG(LOGINFO, "aic dfs detected: %d, %d, %d\n", pde->window_size, pde->count, pde->max_count);
AICWFDBG(LOGINFO, "\t rs: %u %u\n", rs->type, rs->type_id);
AICWFDBG(LOGINFO, "\t rs: width[%u, %u]\n", rs->width_min, rs->width_max);
AICWFDBG(LOGINFO, "\t rs: pri[%u, %u] %u\n", rs->pri_min, rs->pri_max, rs->num_pri);
AICWFDBG(LOGINFO, "\t rs: %u/%u %u\n", rs->ppb, rs->ppb_thresh, rs->max_pri_tolerance);
AICWFDBG(LOGINFO, "\t ps.pri = %u\n" , ps->pri );
AICWFDBG(LOGINFO, "\t ps.dur = %u\n" , ps->dur );
AICWFDBG(LOGINFO, "\t ps.count = %u\n" , ps->count );
AICWFDBG(LOGINFO, "\t ps.count_falses = %u\n" , ps->count_falses );
AICWFDBG(LOGINFO, "\t ps.first_ts = %lu\n", (long unsigned int)ps->first_ts );
AICWFDBG(LOGINFO, "\t ps.last_ts = %lu\n", (long unsigned int)ps->last_ts );
AICWFDBG(LOGINFO, "\t ps.deadline_ts = %lu\n", (long unsigned int)ps->deadline_ts );
AICWFDBG(LOGINFO, "\t ps.ppb_thresh = %u\n" , ps->ppb_thresh );
AICWFDBG(LOGINFO, "\t pulses -->\n");
list_for_each_entry_reverse(p, &pde->pulses, head) {
AICWFDBG(LOGINFO, "\t %u: %lu\n", idx, (long unsigned int)p->ts);
idx++;
}
}
/**
* dfs_pattern_detector_add_pulse - Process one pulse
*
@@ -1082,7 +1115,7 @@ static void dfs_pattern_detector_pri_overflow(struct dfs_pattern_detector *dpd)
*
* @return True is the pulse complete a radar pattern, false otherwise
*/
static bool dfs_pattern_detector_add_pulse(struct dfs_pattern_detector *dpd,
static bool dfs_pattern_detector_add_pulse(struct rwnx_radar *radar, struct dfs_pattern_detector *dpd,
enum rwnx_radar_chain chain,
u16 freq, u16 pri, u16 len, u32 now)
{
@@ -1122,9 +1155,10 @@ static bool dfs_pattern_detector_add_pulse(struct dfs_pattern_detector *dpd,
}
pde = pri_detector_get(dpd, freq, i);
ps = pde->ops->add_pulse(pde, len, dpd->last_pulse_ts, pri);
ps = pde->ops->add_pulse(radar, pde, len, dpd->last_pulse_ts, pri);
if (ps != NULL) {
print_radar_detect_info(pde, ps);
#ifdef CREATE_TRACE_POINTS
trace_radar_detected(chain, dpd->region, pde->freq, i, ps->pri);
#endif
@@ -1207,6 +1241,8 @@ bool dfs_pattern_detector_set_domain(struct dfs_pattern_detector *dpd,
dpd->num_radar_types = rt->num_radar_types;
dpd->region = region;
AICWFDBG(LOGINFO,"set_region %d \n",region);
return true;
}
@@ -1269,6 +1305,8 @@ static void rwnx_radar_detected(struct rwnx_hw *rwnx_hw)
#ifdef CONFIG_RWNX_FULLMAC
struct cfg80211_chan_def chan_def;
RWNX_DBG(RWNX_FN_ENTRY_STR);
if (!rwnx_chanctx_valid(rwnx_hw, rwnx_hw->cur_chanctx)) {
WARN(1, "Radar detected without channel information");
return;
@@ -1296,6 +1334,9 @@ static void rwnx_radar_process_pulse(struct work_struct *ws)
u32 pulses[RWNX_RADAR_LAST][RWNX_RADAR_PULSE_MAX];
u16 pulses_count[RWNX_RADAR_LAST];
u32 now = jiffies; /* would be better to store jiffies value in IT handler */
#ifdef RWNX_RADAR_DUMP_EN
struct rwnx_radar_dump *rm = radar->rmem;
#endif
/* recopy pulses locally to avoid too long spin_lock */
spin_lock_bh(&radar->lock);
@@ -1344,11 +1385,51 @@ static void rwnx_radar_process_pulse(struct work_struct *ws)
#ifdef CREATE_TRACE_POINTS
trace_radar_pulse(chain, p);
#endif
if (dfs_pattern_detector_add_pulse(radar->dpd[chain], chain,
#ifdef RWNX_RADAR_DUMP_EN
if(chain == RWNX_RADAR_RIU) {
u16 pri;
struct dfs_pattern_detector *dpd = NULL;
rm->ps[rm->idx] = pulses[chain][i];
rm->tm[rm->idx] = now;
rm->cnt ++;
pri = p->rep;
dpd = radar->dpd[chain];
if (pri == 0) {
u32 delta_jiffie;
if (unlikely(now < dpd->prev_jiffies)) {
delta_jiffie = 0xffffffff - dpd->prev_jiffies + now;
} else {
delta_jiffie = now - dpd->prev_jiffies;
}
rm->ts[rm->idx] = dpd->last_pulse_ts + jiffies_to_usecs(delta_jiffie);
} else {
rm->ts[rm->idx] = dpd->last_pulse_ts + pri;
}
rm->idx = (rm->idx + 1) % RWNX_RADARR_DUMP_NB;
}
#endif
if((radar->status != RWNX_RADAR_CAC_BUSY) && (radar->status != RWNX_RADAR_INSERVICE_BUSY)) {
break;
}
AICWFDBG(LOGTRACE, "+r:%x\n", *(uint32_t *)p);
if (dfs_pattern_detector_add_pulse(radar, radar->dpd[chain], chain,
(s16)freq + (2 * p->freq),
p->rep, (p->len * 2), now)) {
u16 idx = radar->detected[chain].index;
#ifdef RWNX_RADAR_DUMP_EN
if (chain == RWNX_RADAR_RIU) {
int k;
AICWFDBG(LOGINFO, "\t received pulses %d %d\n", rm->cnt, rm->idx-1);
for(k=0; k<RWNX_RADARR_DUMP_NB; k++) {
AICWFDBG(LOGINFO, "\t %2d: %8x %10llu %10llu\n", rm->idx, rm->ps[rm->idx], rm->ts[rm->idx], rm->tm[rm->idx]);
rm->idx = (rm->idx + 1) % RWNX_RADARR_DUMP_NB;
}
}
#endif
if (chain == RWNX_RADAR_RIU) {
/* operating chain, inform upper layer to change channel */
if (radar->dpd[chain]->enabled == RWNX_RADAR_DETECT_REPORT) {
@@ -1399,11 +1480,11 @@ static void rwnx_radar_cac_work(struct work_struct *ws)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
&ctxt->chan_def,
#endif
NL80211_RADAR_CAC_FINISHED, GFP_KERNEL
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
, 0
#endif
);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
NL80211_RADAR_CAC_FINISHED, GFP_KERNEL, 0);
#else
NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
#endif
rwnx_send_apm_stop_cac_req(rwnx_hw, radar->cac_vif);
rwnx_chanctx_unlink(radar->cac_vif);
@@ -1411,6 +1492,36 @@ static void rwnx_radar_cac_work(struct work_struct *ws)
}
#endif /* CONFIG_RWNX_FULLMAC */
void rwnx_radar_reset_rmem(struct rwnx_radar *radar)
{
#ifdef RWNX_RADAR_DUMP_EN
if (radar->rmem != NULL) {
memset((void *)radar->rmem, 0, sizeof(*radar->rmem));
}
#endif
}
void rwnx_radar_init_rmem(struct rwnx_radar *radar)
{
#ifdef RWNX_RADAR_DUMP_EN
if (radar->rmem == NULL) {
radar->rmem = kmalloc(sizeof(*radar->rmem), GFP_ATOMIC);
}
rwnx_radar_reset_rmem(radar);
#endif
}
void rwnx_radar_deinit_rmem(struct rwnx_radar *radar)
{
#ifdef RWNX_RADAR_DUMP_EN
if (radar->rmem != NULL) {
kfree(radar->rmem);
}
#endif
}
bool rwnx_radar_detection_init(struct rwnx_radar *radar)
{
spin_lock_init(&radar->lock);
@@ -1422,6 +1533,10 @@ bool rwnx_radar_detection_init(struct rwnx_radar *radar)
radar->dpd[RWNX_RADAR_FCU] = dfs_pattern_detector_init(NL80211_DFS_UNSET,
RWNX_RADAR_FCU);
rwnx_radar_init_rmem(radar);
radar->status = RWNX_RADAR_IDLE;
AICWFDBG(LOGINFO, "DFS: radar st = %d\n", radar->status);
if (radar->dpd[RWNX_RADAR_FCU] == NULL) {
rwnx_radar_detection_deinit(radar);
return false;
@@ -1445,11 +1560,13 @@ void rwnx_radar_detection_deinit(struct rwnx_radar *radar)
dfs_pattern_detector_exit(radar->dpd[RWNX_RADAR_FCU]);
radar->dpd[RWNX_RADAR_FCU] = NULL;
}
rwnx_radar_deinit_rmem(radar);
}
bool rwnx_radar_set_domain(struct rwnx_radar *radar,
enum nl80211_dfs_regions region)
{
AICWFDBG(LOGINFO, "%s \n",__func__);
if (radar->dpd[0] == NULL)
return false;
#ifdef CREATE_TRACE_POINTS
@@ -1463,6 +1580,7 @@ bool rwnx_radar_set_domain(struct rwnx_radar *radar,
void rwnx_radar_detection_enable(struct rwnx_radar *radar, u8 enable, u8 chain)
{
//printk("%s enable:%u chain:%u \n",__func__,enable,chain);
if (chain < RWNX_RADAR_LAST ) {
#ifdef CREATE_TRACE_POINTS
trace_radar_enable_detection(radar->dpd[chain]->region, enable, chain);
@@ -1503,11 +1621,11 @@ void rwnx_radar_cancel_cac(struct rwnx_radar *radar)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
&ctxt->chan_def,
#endif
NL80211_RADAR_CAC_ABORTED, GFP_KERNEL
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
, 0
#endif
);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
NL80211_RADAR_CAC_FINISHED, GFP_KERNEL, 0);
#else
NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
#endif
rwnx_chanctx_unlink(radar->cac_vif);
}
+27 -1
View File
@@ -82,11 +82,33 @@ struct rwnx_radar_detected {
s16 freq[NX_NB_RADAR_DETECTED];
};
#define RWNX_RADAR_DUMP_EN 1
#ifdef RWNX_RADAR_DUMP_EN
#define RWNX_RADARR_DUMP_NB 32
struct rwnx_radar_dump {
u32 cnt;
u32 idx;
u32 ps[RWNX_RADARR_DUMP_NB];
u64 tm[RWNX_RADARR_DUMP_NB];
u64 ts[RWNX_RADARR_DUMP_NB];
};
#endif
enum rwnx_radar_status {
RWNX_RADAR_IDLE = 0,
RWNX_RADAR_CAC_BUSY = 1,
RWNX_RADAR_CAC_DONE = 2,
RWNX_RADAR_INSERVICE_BUSY = 3,
RWNX_RADAR_INSERVICE_DONE = 4
};
struct rwnx_radar {
struct rwnx_radar_pulses pulses[RWNX_RADAR_LAST];
struct dfs_pattern_detector *dpd[RWNX_RADAR_LAST];
struct rwnx_radar_detected detected[RWNX_RADAR_LAST];
#ifdef RWNX_RADAR_DUMP_EN
struct rwnx_radar_dump *rmem;
#endif
u16 status;
u16 sta_num;
struct work_struct detection_work; /* Work used to process radar pulses */
spinlock_t lock; /* lock for pulses processing */
@@ -97,6 +119,10 @@ struct rwnx_radar {
#endif
};
void rwnx_radar_reset_rmem(struct rwnx_radar *radar);
void rwnx_radar_init_rmem(struct rwnx_radar *radar);
void rwnx_radar_deinit_rmem(struct rwnx_radar *radar);
bool rwnx_radar_detection_init(struct rwnx_radar *radar);
void rwnx_radar_detection_deinit(struct rwnx_radar *radar);
bool rwnx_radar_set_domain(struct rwnx_radar *radar,
File diff suppressed because it is too large Load Diff
+8 -2
View File
@@ -326,8 +326,12 @@ struct hw_rxhdr {
u32 pattern;
};
extern const u8 legrates_lut[];
extern u16 legrates_lut_rate[];
struct rwnx_legrate {
int idx;
int rate;
};
extern struct rwnx_legrate legrates_lut[];
extern u16 tx_legrates_lut_rate[];
struct DHCPInfo {
@@ -376,6 +380,8 @@ void reord_timeout_handler (struct timer_list *t);
#endif
#endif
void rwnx_rxdata_process_amsdu(struct rwnx_hw *rwnx_hw, struct sk_buff *skb, u8 vif_idx,
struct sk_buff_head *list);
#ifdef CONFIG_HE_FOR_OLD_KERNEL
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 197)
+2
View File
@@ -135,6 +135,8 @@ static const char *const rwnx_mmid2str[MSG_I(MM_MAX)] = {
[MSG_I(MM_GET_WIFI_DISABLE_REQ)] = "MM_GET_WIFI_DISABLE_REQ",
[MSG_I(MM_GET_WIFI_DISABLE_CFM)] = "MM_GET_WIFI_DISABLE_CFM",
[MSG_I(MM_CFG_RSSI_CFM)] = "MM_CFG_RSSI_CFM",
[MSG_I(MM_SET_TXPWR_PER_STA_REQ)] = "MM_SET_TXPWR_PER_STA_REQ",
[MSG_I(MM_SET_TXPWR_PER_STA_CFM)] = "MM_SET_TXPWR_PER_STA_CFM",
};
static const char *const rwnx_dbgid2str[MSG_I(DBG_MAX)] = {
+186 -36
View File
@@ -18,6 +18,7 @@
#include "rwnx_events.h"
#include "rwnx_compat.h"
#include "aicwf_txrxif.h"
#include "rwnx_main.h"
#ifdef CONFIG_RWNX_MON_XMIT
#include <net/ieee80211_radiotap.h>
#endif
@@ -107,7 +108,7 @@ void rwnx_ps_bh_enable(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta,
spin_unlock_bh(&rwnx_hw->tx_lock);
//if (sta->ps.pkt_ready[LEGACY_PS_ID])
// rwnx_set_traffic_status(rwnx_hw, sta, true, LEGACY_PS_ID);
//rwnx_set_traffic_status(rwnx_hw, sta, true, LEGACY_PS_ID);
//if (sta->ps.pkt_ready[UAPSD_ID])
// rwnx_set_traffic_status(rwnx_hw, sta, true, UAPSD_ID);
@@ -132,8 +133,8 @@ void rwnx_ps_bh_enable(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta,
rwnx_txq_sta_start(sta, RWNX_TXQ_STOP_STA_PS, rwnx_hw);
spin_unlock_bh(&rwnx_hw->tx_lock);
//if (sta->ps.pkt_ready[LEGACY_PS_ID])
// rwnx_set_traffic_status(rwnx_hw, sta, false, LEGACY_PS_ID);
if (sta->ps.pkt_ready[LEGACY_PS_ID])
rwnx_set_traffic_status(rwnx_hw, sta, false, LEGACY_PS_ID);
//if (sta->ps.pkt_ready[UAPSD_ID])
// rwnx_set_traffic_status(rwnx_hw, sta, false, UAPSD_ID);
@@ -1466,6 +1467,7 @@ netdev_tx_t rwnx_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb->priority = 0;
#ifdef CONFIG_FILTER_TCP_ACK
if(cpu_to_le16(skb->len) <= MAX_TCP_ACK){
msgbuf=intf_tcp_alloc_msg(msgbuf);
msgbuf->rwnx_vif=rwnx_vif;
msgbuf->skb=skb;
@@ -1475,6 +1477,7 @@ netdev_tx_t rwnx_start_xmit(struct sk_buff *skb, struct net_device *dev)
move_tcpack_msg(rwnx_hw,msgbuf);
kfree(msgbuf);
}
}
#endif
memcpy(&eth_t, skb->data, sizeof(struct ethhdr));
@@ -1830,6 +1833,141 @@ int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta,
return 0;
}
#ifdef CONFIG_BAND_STEERING
void rwnx_probersp_work(struct work_struct *work)
{
struct ap_probe_rsp *rsp = container_of(work, struct ap_probe_rsp, rsp_work);
struct rwnx_vif *rwnx_vif = container_of(rsp, struct rwnx_vif, pb_pool[0]);
struct rwnx_hw *rwnx_hw = rwnx_vif->rwnx_hw;
struct sk_buff *skb = NULL;
struct rwnx_bcn *bcn = &rwnx_vif->ap.bcn;
unsigned int len = bcn->len;
u8_l *buf;
struct ieee80211_mgmt *mgmt;
bool robust;
u16_l headroom, frame_len;
struct rwnx_sta *sta = NULL;
struct rwnx_txq *txq;
struct rwnx_txhdr *txhdr;
struct rwnx_sw_txhdr *sw_txhdr;
struct txdesc_api *desc;
headroom = sizeof(struct rwnx_txhdr);
frame_len = len;
if (aicwf_band_steering_block_chk(rwnx_vif, rsp->da)) {
AICWFDBG(LOGSTEER, "usb %s, %d, probe_rsp refuse temp %pM\n", __func__, rwnx_vif->ap.freq, rsp->da);
goto free_use;
}
if (!bcn->head || bcn->head_len == 0 || bcn->head_len > frame_len) {
AICWFDBG(LOGSTEER, "%s bcn head NULL\n", __func__);
goto free_use;
}
skb = dev_alloc_skb(frame_len + headroom);
if (!skb) {
AICWFDBG(LOGERROR, "%s alloc skb fail\n", __func__);
goto free_use;
}
skb_reserve(skb, headroom);
buf = skb_put(skb, frame_len);
memcpy(buf, bcn->head, bcn->head_len);
buf += bcn->head_len;
*buf++ = WLAN_EID_TIM;
*buf++ = 4;
*buf++ = 0;
*buf++ = bcn->dtim;
*buf++ = 0;
*buf++ = 0;
if (bcn->tail) {
memcpy(buf, bcn->tail, bcn->tail_len);
buf += bcn->tail_len;
}
if (bcn->ies)
memcpy(buf, bcn->ies, bcn->ies_len);
mgmt = (struct ieee80211_mgmt *)skb->data;
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
memcpy (mgmt->da, rsp->da, ETH_ALEN);
rsp->in_use = false;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
robust = ieee80211_is_robust_mgmt_frame(skb);
#else
if (skb->len < 25)
robust = false;
robust = ieee80211_is_robust_mgmt_frame((void *)skb->data);
#endif
sta = rwnx_retrieve_sta(rwnx_hw, rwnx_vif, mgmt->da, mgmt->frame_control, true);
if (sta) {
txq = rwnx_txq_sta_get(sta, 8, rwnx_hw);
} else {
txq = rwnx_txq_vif_get(rwnx_vif, NX_UNK_TXQ_TYPE);
}
if (txq->idx == TXQ_INACTIVE) {
AICWFDBG(LOGERROR, "%s TXQ inactive\n", __func__);
goto fail;
}
skb_push(skb, headroom);
txhdr = (struct rwnx_txhdr *)skb->data;
txhdr->hw_hdr.cfm.status.value = 0;
sw_txhdr = kmem_cache_alloc(rwnx_hw->sw_txhdr_cache, GFP_ATOMIC);
if (unlikely(sw_txhdr == NULL)) {
AICWFDBG(LOGERROR, "%s cache fail\n", __func__);
goto fail;
}
txhdr->sw_hdr = sw_txhdr;
sw_txhdr->txq = txq;
sw_txhdr->frame_len = frame_len;
sw_txhdr->rwnx_sta = sta;
sw_txhdr->rwnx_vif = rwnx_vif;
sw_txhdr->skb = skb;
sw_txhdr->headroom = headroom;
sw_txhdr->map_len = skb->len - offsetof(struct rwnx_txhdr, hw_hdr);
#ifdef CONFIG_RWNX_AMSDUS_TX
sw_txhdr->amsdu.len = 0;
sw_txhdr->amsdu.nb = 0;
#endif
sw_txhdr->raw_frame = 0;
sw_txhdr->fixed_rate = 0;
desc = &sw_txhdr->desc;
desc->host.ethertype = 0;
desc->host.staid = (sta) ? sta->sta_idx : 0xFF;
desc->host.vif_idx = rwnx_vif->vif_index;
desc->host.tid = 0xFF;
desc->host.flags = TXU_CNTRL_MGMT;
if (robust)
desc->host.flags |= TXU_CNTRL_MGMT_ROBUST;
#ifdef CONFIG_RWNX_SPLIT_TX_BUF
desc->host.packet_len[0] = frame_len;
#else
desc->host.packet_len = frame_len;
#endif
desc->host.status_desc_addr = sw_txhdr->dma_addr;
spin_lock_bh(&rwnx_hw->tx_lock);
AICWFDBG(LOGSTEER, "usb p_rsp: %pM", mgmt->da);
// AICWFDBG(LOGDEBUG, "usb %s sta:%p skb:%p desc->host.staid:%d \r\n", __func__, sta, skb, desc->host.staid);
if (rwnx_txq_queue_skb(skb, txq, rwnx_hw, false))
rwnx_hwq_process(rwnx_hw, txq->hwq);
spin_unlock_bh(&rwnx_hw->tx_lock);
return;
fail:
if (sw_txhdr)
kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr);
dev_kfree_skb(skb);
free_use:
if (rsp->in_use)
rsp->in_use = false;
}
#endif
#ifdef CONFIG_RWNX_MON_XMIT
/**
* netdev_tx_t (*ndo_start_xmit)(struct sk_buff *skb,
@@ -1876,11 +2014,11 @@ netdev_tx_t rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *d
int nx_off_chan_txq_idx = NX_OFF_CHAN_TXQ_IDX;
rtap_hdr = (struct ieee80211_radiotap_header*)(rtap_buf);
rtap_len = ieee80211_get_radiotap_len(rtap_buf);
rtap_len = ieee80211_get_radiotap_len(rtap_buf);//max_length
frame_len = skb->len;
printk("rwnx_start_monitor_if_xmit, skb_len=%d, rtap_len=%d\n", skb->len, rtap_len);
AICWFDBG(LOGINFO, "rwnx_start_monitor_if_xmit, skb_len=%d, rtap_len=%d\n", skb->len, rtap_len);
//rwnx_data_dump((char*)__func__, skb->data, skb->len);
if((g_rwnx_plat->usbdev->chipid == PRODUCT_ID_AIC8801) ||
((g_rwnx_plat->usbdev->chipid == PRODUCT_ID_AIC8800DC ||
g_rwnx_plat->usbdev->chipid == PRODUCT_ID_AIC8800DW) && chip_id < 3)){
@@ -1888,14 +2026,20 @@ netdev_tx_t rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *d
}
if (unlikely(rtap_hdr->it_version))
if (unlikely(rtap_hdr->it_version)){
AICWFDBG(LOGERROR, "%s itv \r\n", __func__);
goto free_tag;
}
if (unlikely(skb->len < rtap_len))
if (unlikely(skb->len < rtap_len)){
AICWFDBG(LOGERROR, "%s skb->len < rtap_len \r\n", __func__);
goto free_tag;
}
if (unlikely(rtap_len < sizeof(struct ieee80211_radiotap_header)))
if (unlikely(rtap_len < sizeof(struct ieee80211_radiotap_header))){
AICWFDBG(LOGERROR, "%s rtap_len < sizeof(struct ieee80211_radiotap_header) \r\n", __func__);
goto free_tag;
}
frame_len -= rtap_len;
pframe = rtap_buf + rtap_len;
@@ -1907,39 +2051,44 @@ netdev_tx_t rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *d
if (ret) {
continue;
}
AICWFDBG(LOGDEBUG, "%s iterator.this_arg_index:%d iterator.this_arg:%x\r\n", __func__,
iterator.this_arg_index, *iterator.this_arg);
switch (iterator.this_arg_index) {
case IEEE80211_RADIOTAP_RATE:
// This is basic 802.11b/g rate; use MCS/VHT for higher rates
rate = *iterator.this_arg;
printk("rate=0x%x\n", rate);
AICWFDBG(LOGDEBUG, "rate=0x%x\n", rate);
for (idx = 0; idx < HW_RATE_MAX; idx++) {
if ((rate * 5) == tx_legrates_lut_rate[idx]) {
AICWFDBG(LOGDEBUG, "%s datarate:%d \r\n", __func__, tx_legrates_lut_rate[idx]);
break;
}
}
if (idx < HW_RATE_MAX) {
rate_idx = idx;
AICWFDBG(LOGDEBUG, "rate_idx = %d \r\n", rate_idx);
} else {
printk("invalid radiotap rate: %d\n", rate);
AICWFDBG(LOGERROR, "invalid radiotap rate: %d\n", rate);
}
break;
case IEEE80211_RADIOTAP_TX_FLAGS: {
u16_l txflags = get_unaligned_le16(iterator.this_arg);
printk("txflags=0x%x\n", txflags);
AICWFDBG(LOGDEBUG, "txflags=0x%x\n", txflags);
if ((txflags & IEEE80211_RADIOTAP_F_TX_NOACK) == 0) {
printk(" TX_NOACK\n");
AICWFDBG(LOGDEBUG, " TX_NOACK\n");
}
if (txflags & 0x0010) { // Use preconfigured seq num
// NOTE: this is currently ignored due to qos_en=_FALSE and HW seq num override
printk(" GetSequence\n");
AICWFDBG(LOGDEBUG, " GetSequence\n");
}
}
break;
case IEEE80211_RADIOTAP_MCS: {
u8_l mcs_have = iterator.this_arg[0];
printk("mcs_have=0x%x\n", mcs_have);
AICWFDBG(LOGDEBUG, "mcs_have=0x%x\n", mcs_have);
rate_fmt = FORMATMOD_HT_MF;
if (mcs_have & IEEE80211_RADIOTAP_MCS_HAVE_BW) {
u8_l bw = (iterator.this_arg[1] & IEEE80211_RADIOTAP_MCS_BW_MASK);
@@ -1953,7 +2102,7 @@ netdev_tx_t rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *d
bw = IEEE80211_RADIOTAP_MCS_BW_20;
ch_offset = 2; // CHNL_OFFSET_UPPER;
}
printk(" bw=%d, ch_offset=%d\n", bw, ch_offset);
AICWFDBG(LOGDEBUG, " bw=%d, ch_offset=%d\n", bw, ch_offset);
}
if (mcs_have & IEEE80211_RADIOTAP_MCS_HAVE_MCS) {
u8_l fixed_rate = iterator.this_arg[2] & 0x7f;
@@ -1961,17 +2110,17 @@ netdev_tx_t rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *d
fixed_rate = 0;
}
rate_idx = fixed_rate;
printk(" fixed_rate=0x%x\n", fixed_rate);
AICWFDBG(LOGDEBUG, " fixed_rate=0x%x\n", fixed_rate);
}
if ((mcs_have & IEEE80211_RADIOTAP_MCS_HAVE_GI) && (iterator.this_arg[1] & IEEE80211_RADIOTAP_MCS_SGI)) {
printk(" sgi\n");
AICWFDBG(LOGDEBUG, " sgi\n");
}
if ((mcs_have & IEEE80211_RADIOTAP_MCS_HAVE_FEC) && (iterator.this_arg[1] & IEEE80211_RADIOTAP_MCS_FEC_LDPC)) {
printk(" ldpc\n");
AICWFDBG(LOGDEBUG, " ldpc\n");
}
if (mcs_have & IEEE80211_RADIOTAP_MCS_HAVE_STBC) {
u8 stbc = (iterator.this_arg[1] & IEEE80211_RADIOTAP_MCS_STBC_MASK) >> IEEE80211_RADIOTAP_MCS_STBC_SHIFT;
printk(" stbc=0x%x\n", stbc);
AICWFDBG(LOGDEBUG, " stbc=0x%x\n", stbc);
}
}
break;
@@ -1981,17 +2130,17 @@ netdev_tx_t rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *d
u8 known = iterator.this_arg[0];
u8 flags = iterator.this_arg[2];
rate_fmt = FORMATMOD_VHT;
printk("known=0x%x, flags=0x%x\n", known, flags);
AICWFDBG(LOGDEBUG, "known=0x%x, flags=0x%x\n", known, flags);
// NOTE: this code currently only supports 1SS for radiotap defined rates
if ((known & IEEE80211_RADIOTAP_VHT_KNOWN_STBC) && (flags & IEEE80211_RADIOTAP_VHT_FLAG_STBC)) {
printk(" stbc\n");
AICWFDBG(LOGDEBUG, " stbc\n");
}
if ((known & IEEE80211_RADIOTAP_VHT_KNOWN_GI) && (flags & IEEE80211_RADIOTAP_VHT_FLAG_SGI)) {
printk(" sgi\n");
AICWFDBG(LOGDEBUG, " sgi\n");
}
if (known & IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH) {
u8_l bw = iterator.this_arg[3] & 0x1F;
printk(" bw=0x%x\n",bw);
AICWFDBG(LOGDEBUG, " bw=0x%x\n",bw);
// NOTE: there are various L and U, but we just use straight 20/40/80
// since it's not clear how to set CHNL_OFFSET_LOWER/_UPPER with different
// sideband sizes/configurations. TODO.
@@ -1999,26 +2148,26 @@ netdev_tx_t rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *d
txsig_bw = PHY_CHNL_BW_40;
if (bw == 0) {
txsig_bw = PHY_CHNL_BW_20;
printk(" 20M\n");
AICWFDBG(LOGDEBUG, " 20M\n");
} else if (bw >=1 && bw <= 3) {
printk(" 40M\n");
AICWFDBG(LOGDEBUG, " 40M\n");
} else if (bw >=4 && bw <= 10) {
printk(" 80M\n");
AICWFDBG(LOGDEBUG, " 80M\n");
} else if (bw >= 11 && bw <= 25) {
printk(" 160M\n");
AICWFDBG(LOGDEBUG, " 160M\n");
}
}
// User 0
nss = iterator.this_arg[4] & 0x0F; // Number of spatial streams
printk(" nss=0x%x\n", nss);
AICWFDBG(LOGINFO, " nss=0x%x\n", nss);
if (nss > 0) {
if (nss > 4) nss = 4;
mcs = (iterator.this_arg[4]>>4) & 0x0F; // MCS rate index
if (mcs > 8) mcs = 9;
rate_idx = mcs;
printk(" mcs=0x%x\n", mcs);
AICWFDBG(LOGDEBUG, " mcs=0x%x\n", mcs);
if (iterator.this_arg[8] & IEEE80211_RADIOTAP_CODING_LDPC_USER0) {
printk(" ldpc\n");
AICWFDBG(LOGDEBUG, " ldpc\n");
}
}
}
@@ -2048,13 +2197,13 @@ netdev_tx_t rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *d
}
if (data2 & IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN) {
u8 gi = (data5 & IEEE80211_RADIOTAP_HE_DATA5_GI) >> 4;
printk(" gi: %d\n", gi);
AICWFDBG(LOGDEBUG, " gi: %d\n", gi);
}
}
break;
default:
printk("unparsed arg: 0x%x\n",iterator.this_arg_index);
AICWFDBG(LOGERROR, "unparsed arg: 0x%x\n",iterator.this_arg_index);
break;
}
}
@@ -2089,14 +2238,14 @@ netdev_tx_t rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *d
txq = rwnx_txq_vif_get(vif, NX_UNK_TXQ_TYPE);
}
if (txq->idx == TXQ_INACTIVE) {
printk("TXQ_INACTIVE\n");
AICWFDBG(LOGERROR, "TXQ_INACTIVE\n");
goto free_tag;
}
// prepare to xmit
headroom = sizeof(struct rwnx_txhdr);
skb_mgmt = dev_alloc_skb(headroom + frame_len);
if (!skb_mgmt) {
printk("skb_mgmt alloc fail\n");
AICWFDBG(LOGERROR, "skb_mgmt alloc fail\n");
goto free_tag;
}
skb_reserve(skb_mgmt, headroom);
@@ -2118,7 +2267,7 @@ netdev_tx_t rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *d
sw_txhdr = kmem_cache_alloc(rwnx_hw->sw_txhdr_cache, GFP_ATOMIC);
if (unlikely(sw_txhdr == NULL)) {
dev_kfree_skb(skb_mgmt);
printk("sw_txhdr alloc fail\n");
AICWFDBG(LOGERROR, "sw_txhdr alloc fail\n");
goto free_tag;
}
txhdr->sw_hdr = sw_txhdr;
@@ -2160,6 +2309,7 @@ netdev_tx_t rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *d
desc->host.status_desc_addr = sw_txhdr->dma_addr;
spin_lock_bh(&rwnx_hw->tx_lock);
AICWFDBG(LOGTRACE, "%s send data\r\n", __func__);
if (rwnx_txq_queue_skb(skb_mgmt, txq, rwnx_hw, false))
rwnx_hwq_process(rwnx_hw, txq->hwq);
spin_unlock_bh(&rwnx_hw->tx_lock);
+4
View File
@@ -194,5 +194,9 @@ int rwnx_dbgfs_print_sta(char *buf, size_t size, struct rwnx_sta *sta,
void rwnx_txq_credit_update(struct rwnx_hw *rwnx_hw, int sta_idx, u8 tid,
s8 update);
void rwnx_tx_push(struct rwnx_hw *rwnx_hw, struct rwnx_txhdr *txhdr, int flags);
#ifdef CONFIG_BAND_STEERING
void rwnx_probersp_work(struct work_struct *work);
#endif
#endif /* _RWNX_TX_H_ */
@@ -1,5 +1,5 @@
#define RWNX_VERS_REV "1a4b0054d2M (master)"
#define RWNX_VERS_MOD "6.4.3.0"
#define RWNX_VERS_BANNER "rwnx v6.4.3.0 - 1a4b0054d2M (master)"
#define RELEASE_DATE "2024_0420_24c7777c"
#define RELEASE_DATE "2025_0423_71b66e7b"
@@ -0,0 +1,92 @@
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/platform_device.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
#include <linux/pm_wakeirq.h>
#else
#include <linux/pm_wakeup.h>
#endif
#include "rwnx_defs.h"
#include "rwnx_wakelock.h"
struct wakeup_source *rwnx_wakeup_init(const char *name)
{
struct wakeup_source *ws;
ws = wakeup_source_create(name);
wakeup_source_add(ws);
return ws;
}
void rwnx_wakeup_deinit(struct wakeup_source *ws)
{
if (ws && ws->active)
__pm_relax(ws);
wakeup_source_remove(ws);
wakeup_source_destroy(ws);
}
struct wakeup_source *rwnx_wakeup_register(struct device *dev, const char *name)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)
return wakeup_source_register(dev, name);
#else
#if defined(CONFIG_PLATFORM_ROCKCHIP2) || defined(CONFIG_PLATFORM_ROCKCHIP)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
return wakeup_source_register(dev, name);
#else
return wakeup_source_register(name);
#endif
#else
return wakeup_source_register(name);
#endif//#if defined(CONFIG_PLATFORM_ROCKCHIP2) || defined(CONFIG_PLATFORM_ROCKCHIP)
#endif//LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)
}
void rwnx_wakeup_unregister(struct wakeup_source *ws)
{
if (ws && ws->active)
__pm_relax(ws);
wakeup_source_unregister(ws);
}
void rwnx_wakeup_lock(struct wakeup_source *ws)
{
AICWFDBG(LOGDEBUG, "%s enter \r\n", __func__);
__pm_stay_awake(ws);
}
void rwnx_wakeup_unlock(struct wakeup_source *ws)
{
AICWFDBG(LOGDEBUG, "%s enter \r\n", __func__);
__pm_relax(ws);
}
void rwnx_wakeup_lock_timeout(struct wakeup_source *ws, unsigned int msec)
{
__pm_wakeup_event(ws, msec);
}
void aicwf_wakeup_lock_init(struct rwnx_hw *rwnx_hw)
{
rwnx_hw->ws_tx = rwnx_wakeup_init("rwnx_tx_wakelock");
rwnx_hw->ws_rx = rwnx_wakeup_init("rwnx_rx_wakelock");
rwnx_hw->ws_irqrx = rwnx_wakeup_init("rwnx_irqrx_wakelock");
rwnx_hw->ws_pwrctrl = rwnx_wakeup_init("rwnx_pwrcrl_wakelock");
}
void aicwf_wakeup_lock_deinit(struct rwnx_hw *rwnx_hw)
{
rwnx_wakeup_deinit(rwnx_hw->ws_tx);
rwnx_wakeup_deinit(rwnx_hw->ws_rx);
rwnx_wakeup_deinit(rwnx_hw->ws_irqrx);
rwnx_wakeup_deinit(rwnx_hw->ws_pwrctrl);
rwnx_hw->ws_tx = NULL;
rwnx_hw->ws_rx = NULL;
rwnx_hw->ws_irqrx = NULL;
rwnx_hw->ws_pwrctrl = NULL;
}
@@ -0,0 +1,21 @@
#ifndef __RWNX_WAKELOCK_H
#define __RWNX_WAKELOCK_H
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/platform_device.h>
struct wakeup_source *rwnx_wakeup_init(const char *name);
void rwnx_wakeup_deinit(struct wakeup_source *ws);
struct wakeup_source *rwnx_wakeup_register(struct device *dev, const char *name);
void rwnx_wakeup_unregister(struct wakeup_source *ws);
void rwnx_wakeup_lock(struct wakeup_source *ws);
void rwnx_wakeup_unlock(struct wakeup_source *ws);
void rwnx_wakeup_lock_timeout(struct wakeup_source *ws, unsigned int msec);
void aicwf_wakeup_lock_init(struct rwnx_hw *rwnx_hw);
void aicwf_wakeup_lock_deinit(struct rwnx_hw *rwnx_hw);
#endif
+11
View File
@@ -0,0 +1,11 @@
*.o
*.ko
*.order
*.symvers
*.o.d
*.o.cmd
*.ko.cmd
*.mod
*.mod.c*
.tmp_versions/
+7 -1
View File
@@ -7,11 +7,14 @@ CONFIG_M2D_OTA_AUTO_SUPPORT = n
CONFIG_LINK_DET_5G = y
CONFIG_FOR_IPCAM = n
CONFIG_USB_SUSPEND_REBOOT_TIME = n
CONFIG_SUPPORT_USB_SUSP = n
CONFIG_RADAR_OR_IR_DETECT =n
# Need to set fw path in BOARD_KERNEL_CMDLINE
CONFIG_USE_FW_REQUEST ?= n
CONFIG_PREALLOC_RX_SKB ?= n
CONFIG_PREALLOC_TXQ ?= y
CONFIG_BAND_STEERING = n
# Platform support list
CONFIG_PLATFORM_ROCKCHIP ?= n
@@ -39,7 +42,9 @@ ccflags-$(CONFIG_USE_FW_REQUEST) += -DCONFIG_USE_FW_REQUEST
ccflags-$(CONFIG_PREALLOC_RX_SKB) += -DCONFIG_PREALLOC_RX_SKB
ccflags-$(CONFIG_PREALLOC_TXQ) += -DCONFIG_PREALLOC_TXQ
ccflags-$(CONFIG_USB_SUSPEND_REBOOT_TIME) += -DCONFIG_USB_SUSPEND_REBOOT_TIME
ccflags-$(CONFIG_SUPPORT_USB_SUSP) += -DCONFIG_SUPPORT_USB_SUSP
ccflags-$(CONFIG_RADAR_OR_IR_DETECT) += -DCONFIG_RADAR_OR_IR_DETECT
ccflags-$(CONFIG_BAND_STEERING) += -DCONFIG_BAND_STEERING
obj-$(CONFIG_AIC_LOADFW_SUPPORT) := $(MODULE_NAME).o
$(MODULE_NAME)-y := aic_bluetooth_main.o \
@@ -48,6 +53,7 @@ $(MODULE_NAME)-y := aic_bluetooth_main.o \
aic_txrxif.o \
aicbluetooth_cmds.o \
aic_compat_8800d80.o \
aic_compat_8800d80x2.o \
md5.o
$(MODULE_NAME)-$(CONFIG_PREALLOC_RX_SKB) += aicwf_rx_prealloc.o
+128 -21
View File
@@ -17,7 +17,7 @@ void rwnx_release_firmware_common(u32** buffer);
extern int testmode;
extern u8 chip_id;
u8 chip_mcu_id = 0;
extern u8 chip_mcu_id;
typedef u32 (*array2_tbl_t)[2];
@@ -39,13 +39,26 @@ typedef struct {
#define AIC_PATCH_OFST(mem) ((size_t) &((aic_patch_t *)0)->mem)
#define AIC_PATCH_ADDR(mem) ((u32) (aic_patch_str_base + AIC_PATCH_OFST(mem)))
#define USER_PWROFST_COVER_CALIB_FLAG (0x01U << 0)
#define USER_CHAN_MAX_TXPWR_EN_FLAG (0x01U << 1)
#define USER_TX_USE_ANA_F_FLAG (0x01U << 2)
#define USER_APM_PRBRSP_OFFLOAD_DISABLE_FLAG (0x01U << 3)
#define USER_HE_MU_EDCA_UPDATE_DISABLE_FLAG (0x01U << 4)
#define CFG_PWROFST_COVER_CALIB 1
#ifdef CONFIG_POWER_LIMIT
#define CFG_USER_CHAN_MAX_TXPWR_EN 1
#else
#define CFG_USER_CHAN_MAX_TXPWR_EN 0
#endif
#define CFG_USER_TX_USE_ANA_F 0
#ifdef CONFIG_BAND_STEERING
#define CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE 1
#else
#define CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE 0
#endif
#define CFG_USER_EXT_FLAGS_EN (CFG_USER_CHAN_MAX_TXPWR_EN || CFG_USER_TX_USE_ANA_F)
#define CFG_USER_EXT_FLAGS_EN (CFG_PWROFST_COVER_CALIB || CFG_USER_CHAN_MAX_TXPWR_EN || CFG_USER_TX_USE_ANA_F|| CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE)
u32 patch_tbl_d80[][2] =
{
@@ -60,16 +73,26 @@ u32 patch_tbl_d80[][2] =
{0x0170, 0x0001000A},//rx aggr counter
#endif
#if CFG_USER_EXT_FLAGS_EN
{0x0188, 0x00000001
#if CFG_USER_CHAN_MAX_TXPWR_EN
#if CFG_USER_EXT_FLAGS_EN
{0x0188, 0x00000000
#if CFG_PWROFST_COVER_CALIB
| USER_PWROFST_COVER_CALIB_FLAG
#endif
#if CFG_USER_CHAN_MAX_TXPWR_EN
| USER_CHAN_MAX_TXPWR_EN_FLAG
#endif
#if CFG_USER_TX_USE_ANA_F
#endif
#if CFG_USER_TX_USE_ANA_F
| USER_TX_USE_ANA_F_FLAG
#endif
#endif
#if CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE
| USER_APM_PRBRSP_OFFLOAD_DISABLE_FLAG
#endif
}, // user_ext_flags
#endif
#endif
#ifdef CONFIG_RADAR_OR_IR_DETECT
{0x0019c,0x00000B00},
#endif
};
//adap test
@@ -314,6 +337,38 @@ int system_config_8800d80(struct aic_usb_dev *usb_dev){
}
static int aicbt_ext_patch_data_load(struct aic_usb_dev *usb_dev, struct aicbt_patch_info_t *patch_info)
{
int ret = 0;
uint32_t ext_patch_nb = patch_info->ext_patch_nb;
char ext_patch_file_name[50];
int index = 0;
uint32_t id = 0;
uint32_t addr = 0;
if (ext_patch_nb > 0){
for (index = 0; index < patch_info->ext_patch_nb; index++){
id = *(patch_info->ext_patch_param + (index * 2));
addr = *(patch_info->ext_patch_param + (index * 2) + 1);
memset(ext_patch_file_name, 0, sizeof(ext_patch_file_name));
sprintf(ext_patch_file_name,"%s%d.bin",
FW_PATCH_BASE_NAME_8800D80_U02_EXT,
id);
AICWFDBG(LOGDEBUG, "%s ext_patch_file_name:%s ext_patch_id:%x ext_patch_addr:%x \r\n",
__func__,ext_patch_file_name, id, addr);
if (rwnx_plat_bin_fw_upload_android(usb_dev, addr, ext_patch_file_name)) {
ret = -1;
break;
}
}
}
return ret;
}
int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
{
struct aicbt_patch_table *head = NULL;
@@ -331,6 +386,7 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
int i = 0;
#if 0
if (chip_id == CHIP_REV_U01) {
head = aicbt_patch_table_alloc(usb_dev, FW_PATCH_TABLE_NAME_8800D80);
} else {
@@ -358,7 +414,7 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
}
printk("addr_adid 0x%x, addr_patch 0x%x\n", patch_info.addr_adid, patch_info.addr_patch);
#endif
if(testmode == FW_NORMAL_MODE){
if (chip_id != CHIP_REV_U01){
@@ -369,16 +425,16 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_patch, FW_PATCH_BASE_NAME_8800D80_U02)) {
return -1;
}
#if 0
if (rwnx_plat_bin_fw_patch_table_upload_android(usb_dev, FW_PATCH_TABLE_NAME_8800D80_U02)) {
if (aicbt_ext_patch_data_load(usb_dev, &patch_info)) {
return -1;
}
#else
if (aicbt_patch_table_load(usb_dev, head)) {
return -1;
}
#endif
#endif
if (IS_CHIP_ID_H()){
if(rwnx_plat_bin_fw_upload_android(usb_dev, RAM_FMAC_FW_ADDR_8800D80_U02, FW_BASE_NAME_8800D80_H_U02))
return -1;
@@ -426,7 +482,7 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
}
}else if(testmode == FW_TEST_MODE){
if (chip_id != CHIP_REV_U01){
#if 0
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_adid, FW_ADID_BASE_NAME_8800D80_U02)) {
return -1;
}
@@ -434,15 +490,15 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_patch, FW_PATCH_BASE_NAME_8800D80_U02)) {
return -1;
}
#if 0
if (rwnx_plat_bin_fw_patch_table_upload_android(usb_dev, FW_PATCH_TABLE_NAME_8800D80_U02)) {
if (aicbt_ext_patch_data_load(usb_dev, &patch_info)) {
return -1;
}
#else
if (aicbt_patch_table_load(usb_dev, head)) {
return -1;
}
#endif
if (chip_mcu_id) {
int ret = 0;
@@ -452,7 +508,7 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
return -1;
}
}
#endif
if(rwnx_plat_bin_fw_upload_android(usb_dev, RAM_FMAC_RF_FW_ADDR_8800D80_U02, FW_RF_BASE_NAME_8800D80_U02)) {
AICWFDBG(LOGERROR,"%s wifi fw download fail \r\n", __func__);
return -1;
@@ -499,6 +555,7 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
///gpio_trigger_idx : 1 if wakeup_param->gpio_dft_lvl[1]=0xfe,this idx will be invalid.
wakeup_param->gpio_num[1] = 3;////default select gpiob2 for fw_wakeup_host
wakeup_param->gpio_dft_lvl[1] = 1;////0:defalut pull down, 1:default pull up
/********************************************************************/
/********************************************************************/
//MAX_AD_FILTER_NUM=5 :num 0
{
@@ -509,6 +566,16 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
wakeup_param->ad_filter[0].ad_data_mask = 0xffe00000;
wakeup_param->ad_filter[0].ad_role = ROLE_COMBO|(COMBO_0<<4);
wakeup_param->ad_filter[0].gpio_trigger_idx = TG_IDX_0;//0: match for wakeup_param->gpio_num[0] 1: match for wakeup_param->gpio_num[1]
/********************************************************************/
/*enable white list addr for paired remote ble addr. if all 0: all addr will use ad filter
wl_addr have value xx: only remote addr in white_list_addr will use ad filter
********************************************************************/
wakeup_param->ad_filter[0].wl_addr.addr[0] = 0;
wakeup_param->ad_filter[0].wl_addr.addr[1] = 0;
wakeup_param->ad_filter[0].wl_addr.addr[2] = 0;
wakeup_param->ad_filter[0].wl_addr.addr[3] = 0;
wakeup_param->ad_filter[0].wl_addr.addr[4] = 0;
wakeup_param->ad_filter[0].wl_addr.addr[5] = 0;
}
/********************************************************************/
//MAX_AD_FILTER_NUM=5 :num 1
@@ -520,6 +587,16 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
wakeup_param->ad_filter[1].ad_data_mask = 0xc0000000;
wakeup_param->ad_filter[1].ad_role = ROLE_COMBO|(COMBO_0<<4);
wakeup_param->ad_filter[1].gpio_trigger_idx = TG_IDX_0;//0: match for wakeup_param->gpio_num[0] 1: match for wakeup_param->gpio_num[1]
/********************************************************************/
/*enable white list addr for paired remote ble addr. if all 0: all addr will use ad filter
wl_addr have value xx: only remote addr in white_list_addr will use ad filter
********************************************************************/
wakeup_param->ad_filter[1].wl_addr.addr[0] = 0;
wakeup_param->ad_filter[1].wl_addr.addr[1] = 0;
wakeup_param->ad_filter[1].wl_addr.addr[2] = 0;
wakeup_param->ad_filter[1].wl_addr.addr[3] = 0;
wakeup_param->ad_filter[1].wl_addr.addr[4] = 0;
wakeup_param->ad_filter[1].wl_addr.addr[5] = 0;
}
/********************************************************************/
//MAX_AD_FILTER_NUM=5 :num 2
@@ -531,6 +608,16 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
wakeup_param->ad_filter[2].ad_data_mask = 0;
wakeup_param->ad_filter[2].ad_role = ROLE_ONLY;
wakeup_param->ad_filter[2].gpio_trigger_idx = TG_IDX_0;//0: match for wakeup_param->gpio_num[0] 1: match for wakeup_param->gpio_num[1]
/********************************************************************/
/*enable white list addr for paired remote ble addr. if all 0: all addr will use ad filter
wl_addr have value xx: only remote addr in white_list_addr will use ad filter
********************************************************************/
wakeup_param->ad_filter[2].wl_addr.addr[0] = 0;
wakeup_param->ad_filter[2].wl_addr.addr[1] = 0;
wakeup_param->ad_filter[2].wl_addr.addr[2] = 0;
wakeup_param->ad_filter[2].wl_addr.addr[3] = 0;
wakeup_param->ad_filter[2].wl_addr.addr[4] = 0;
wakeup_param->ad_filter[2].wl_addr.addr[5] = 0;
}
/********************************************************************/
//MAX_AD_FILTER_NUM=5 :num 3
@@ -542,6 +629,16 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
wakeup_param->ad_filter[3].ad_data_mask = 0;
wakeup_param->ad_filter[3].ad_role = ROLE_COMBO|(COMBO_1<<4);
wakeup_param->ad_filter[3].gpio_trigger_idx = TG_IDX_0;//0: match for wakeup_param->gpio_num[0] 1: match for wakeup_param->gpio_num[1]
/********************************************************************/
/*enable white list addr for paired remote ble addr. if all 0: all addr will use ad filter
wl_addr have value xx: only remote addr in white_list_addr will use ad filter
********************************************************************/
wakeup_param->ad_filter[3].wl_addr.addr[0] = 0;
wakeup_param->ad_filter[3].wl_addr.addr[1] = 0;
wakeup_param->ad_filter[3].wl_addr.addr[2] = 0;
wakeup_param->ad_filter[3].wl_addr.addr[3] = 0;
wakeup_param->ad_filter[3].wl_addr.addr[4] = 0;
wakeup_param->ad_filter[3].wl_addr.addr[5] = 0;
}
/********************************************************************/
//MAX_AD_FILTER_NUM=5 :num 4
@@ -553,11 +650,21 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
wakeup_param->ad_filter[4].ad_data_mask = 0xffe00000;
wakeup_param->ad_filter[4].ad_role = ROLE_COMBO|(COMBO_1<<4);
wakeup_param->ad_filter[4].gpio_trigger_idx = TG_IDX_0|TG_IDX_1;//0: match for wakeup_param->gpio_num[0] 1: match for wakeup_param->gpio_num[1]
/********************************************************************/
/*enable white list addr for paired remote ble addr. if all 0: all addr will use ad filter
wl_addr have value xx: only remote addr in white_list_addr will use ad filter
********************************************************************/
wakeup_param->ad_filter[4].wl_addr.addr[0] = 0;
wakeup_param->ad_filter[4].wl_addr.addr[1] = 0;
wakeup_param->ad_filter[4].wl_addr.addr[2] = 0;
wakeup_param->ad_filter[4].wl_addr.addr[3] = 0;
wakeup_param->ad_filter[4].wl_addr.addr[4] = 0;
wakeup_param->ad_filter[4].wl_addr.addr[5] = 0;
}
for(i = 0; i < (sizeof(struct ble_wakeup_param_t)/4 +1); i++){
printk("write_blocks[%d]:0x%08X \r\n", i, write_blocks[i]);
rwnx_send_dbg_mem_write_req(usb_dev, 0x15FF00 + (4 * i), write_blocks[i]);
rwnx_send_dbg_mem_write_req(usb_dev, 0x15FE00 + (4 * i), write_blocks[i]);
}
rwnx_send_dbg_start_app_req(usb_dev, RAM_FW_BLE_SCAN_WAKEUP_ADDR_8800D80, HOST_START_APP_AUTO);
kfree(wakeup_param);
@@ -15,13 +15,13 @@
#ifdef CONFIG_FOR_IPCAM
#define FW_BASE_NAME_8800D80_U02 "fmacfw_8800d80_u02_ipc.bin"
#define FW_BASE_NAME_8800D80_H_U02 "fmacfw_8800d80_h_u02_ipc.bin"
#else
#define FW_BASE_NAME_8800D80_U02 "fmacfw_8800d80_u02.bin"
#define FW_BASE_NAME_8800D80_H_U02 "fmacfw_8800d80_h_u02.bin"
#endif
#define FW_RF_BASE_NAME_8800D80_U02 "lmacfw_rf_8800d80_u02.bin"
#define FW_PATCH_BASE_NAME_8800D80_U02 "fw_patch_8800d80_u02.bin"
#define FW_PATCH_BASE_NAME_8800D80_U02_EXT "fw_patch_8800d80_u02_ext"
#define FW_ADID_BASE_NAME_8800D80_U02 "fw_adid_8800d80_u02.bin"
#define FW_CALIBMODE_NAME_8800D80_U02 "calibmode_8800d80.bin"
#define FW_PATCH_TABLE_NAME_8800D80_U02 "fw_patch_table_8800d80_u02.bin"
@@ -0,0 +1,767 @@
#include "aic_txrxif.h"
#include "aicwf_usb.h"
#include "aicbluetooth.h"
#include "aic_compat_8800d80x2.h"
#include "aicwf_debug.h"
extern int ble_scan_wakeup_reboot_time;
extern uint32_t ad_data_filter_mask;
extern uint32_t gpio_num;//default select gpiob2 for fw_wakeup_host
extern uint32_t gpio_dft_lvl;//0:defalut pull down, 1:default pull up
int rwnx_plat_bin_fw_upload_2(struct aic_usb_dev *usbdev, u32 fw_addr,
char *filename);
int rwnx_request_firmware_common(struct aic_usb_dev *usbdev,
u32** buffer, const char *filename);
void rwnx_plat_userconfig_parsing(char *buffer, int size);
void rwnx_release_firmware_common(u32** buffer);
extern int testmode;
extern u8 chip_id;
extern u8 chip_mcu_id;
typedef u32 (*array2_tbl_t)[2];
#define AIC_PATCH_MAGIG_NUM 0x48435450 // "PTCH"
#define AIC_PATCH_MAGIG_NUM_2 0x50544348 // "HCTP"
#define AIC_PATCH_BLOCK_MAX 4
typedef struct {
uint32_t magic_num;
uint32_t pair_start;
uint32_t magic_num_2;
uint32_t pair_count;
uint32_t block_dst[AIC_PATCH_BLOCK_MAX];
uint32_t block_src[AIC_PATCH_BLOCK_MAX];
uint32_t block_size[AIC_PATCH_BLOCK_MAX]; // word count
} aic_patch_t;
#define AIC_PATCH_OFST(mem) ((size_t) &((aic_patch_t *)0)->mem)
#define AIC_PATCH_ADDR(mem) ((u32) (aic_patch_str_base + AIC_PATCH_OFST(mem)))
#define USER_PWROFST_COVER_CALIB_FLAG (0x01U << 0)
#define USER_CHAN_MAX_TXPWR_EN_FLAG (0x01U << 1)
#define USER_TX_USE_ANA_F_FLAG (0x01U << 2)
#define USER_APM_PRBRSP_OFFLOAD_DISABLE_FLAG (0x01U << 3)
#define USER_HE_MU_EDCA_UPDATE_DISABLE_FLAG (0x01U << 4)
#ifdef CONFIG_POWER_LIMIT
#define CFG_USER_CHAN_MAX_TXPWR_EN 1
#else
#define CFG_USER_CHAN_MAX_TXPWR_EN 0
#endif
#define CFG_USER_TX_USE_ANA_F 0
#ifdef CONFIG_BAND_STEERING
#define CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE 1
#else
#define CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE 0
#endif
u32 patch_tbl_d80x2[][2] =
{
#ifdef CONFIG_PLATFORM_HI
{0x021c, 0x04000000},//hs amsdu
{0x0220, 0x04000000},//ss amsdu
{0x0224, 0x08000a01},//hs aggr
{0x0228, 0x08000a01},//ss aggr
#else
{0x021c, 0x04000000},//hs amsdu
{0x0220, 0x04010101},//ss amsdu
{0x0224, 0x50000a01},//hs aggr
{0x0228, 0x50000a00},//ss aggr
#endif
#if 0
#ifdef USE_5G
{0x00b4, 0xf3010001},
#else
{0x00b4, 0xf3010000},
#endif
#ifdef CONFIG_PLATFORM_HI
{0x0170, 0x00000001},//rx aggr counter
#else
{0x0170, 0x0000000A},//rx aggr counter
#endif
#endif
{0x01f0, 0x00000001
#if CFG_USER_CHAN_MAX_TXPWR_EN
| USER_CHAN_MAX_TXPWR_EN_FLAG
#endif
#if CFG_USER_TX_USE_ANA_F
| USER_TX_USE_ANA_F_FLAG
#endif
#if CFG_USER_APM_PRBRSP_OFFLOAD_DISABLE
| USER_APM_PRBRSP_OFFLOAD_DISABLE_FLAG
#endif
}, // user_ext_flags
};
//adap test
u32 adaptivity_patch_tbl_d80x2[][2] = {
{0x000C, 0x0000320A}, //linkloss_thd
{0x009C, 0x00000000}, //ac_param_conf
{0x01D0, 0x00010000}, //tx_adaptivity_en
};
u32 syscfg_tbl_masked_8800d80x2[][3] = {
};
u32 syscfg_tbl_8800d80x2[][2] = {
#ifdef CONFIG_PMIC_SETTING
{0x70001408, 0x00000000}, // stop wdg
#endif /* CONFIG_PMIC_SETTING */
{0x40500010, 0x00000006},//cpu performance
{0x40500024, 0x0000001f},
};
extern int adap_test;
#define NEW_PATCH_BUFFER_MAP 1
int aicwf_patch_config_8800d80x2(struct aic_usb_dev *usb_dev)
{
#if 1
u32 rd_patch_addr;
u32 aic_patch_addr;
u32 config_base, aic_patch_str_base;
#if (NEW_PATCH_BUFFER_MAP)
u32 patch_buff_addr, patch_buff_base, rd_version_addr, rd_version_val;
#endif
uint32_t start_addr;
u32 patch_addr;
u32 patch_cnt = sizeof(patch_tbl_d80x2) / 4 / 2;
struct dbg_mem_read_cfm rd_patch_addr_cfm;
int ret = 0;
int cnt = 0;
//adap test
int adap_patch_cnt = 0;
if (adap_test) {
AICWFDBG(LOGINFO, "%s adap test \r\n", __func__);
adap_patch_cnt = sizeof(adaptivity_patch_tbl_d80x2)/sizeof(u32)/2;
}
rd_patch_addr = RAM_FMAC_FW_ADDR_8800D80X2 + 0x01A8;
aic_patch_addr = rd_patch_addr + 8;
AICWFDBG(LOGERROR, "Read FW mem: %08x\n", rd_patch_addr);
if ((ret = rwnx_send_dbg_mem_read_req(usb_dev, rd_patch_addr, &rd_patch_addr_cfm))) {
AICWFDBG(LOGERROR, "setting base[0x%x] rd fail: %d\n", rd_patch_addr, ret);
return ret;
}
AICWFDBG(LOGERROR, "%x=%x\n", rd_patch_addr_cfm.memaddr, rd_patch_addr_cfm.memdata);
config_base = rd_patch_addr_cfm.memdata;
if ((ret = rwnx_send_dbg_mem_read_req(usb_dev, aic_patch_addr, &rd_patch_addr_cfm))) {
AICWFDBG(LOGERROR, "patch_str_base[0x%x] rd fail: %d\n", aic_patch_addr, ret);
return ret;
}
AICWFDBG(LOGERROR, "%x=%x\n", rd_patch_addr_cfm.memaddr, rd_patch_addr_cfm.memdata);
aic_patch_str_base = rd_patch_addr_cfm.memdata;
#if (NEW_PATCH_BUFFER_MAP)
rd_version_addr = RAM_FMAC_FW_ADDR_8800D80X2 + 0x01C;
if ((ret = rwnx_send_dbg_mem_read_req(usb_dev, rd_version_addr, &rd_patch_addr_cfm))) {
AICWFDBG(LOGERROR, "version val[0x%x] rd fail: %d\n", rd_version_addr, ret);
return ret;
}
rd_version_val = rd_patch_addr_cfm.memdata;
AICWFDBG(LOGINFO, "rd_version_val=%08X\n", rd_version_val);
usb_dev->fw_version_uint = rd_version_val;
patch_buff_addr = rd_patch_addr + 12;
ret = rwnx_send_dbg_mem_read_req(usb_dev, patch_buff_addr, &rd_patch_addr_cfm);
if (ret) {
AICWFDBG(LOGERROR, "patch buf rd fail\n");
return ret;
}
AICWFDBG(LOGINFO, "%x=%x\n", rd_patch_addr_cfm.memaddr, rd_patch_addr_cfm.memdata);
patch_buff_base = rd_patch_addr_cfm.memdata;
patch_addr = start_addr = patch_buff_base;
#endif
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, AIC_PATCH_ADDR(magic_num), AIC_PATCH_MAGIG_NUM))) {
AICWFDBG(LOGERROR, "maigic_num[0x%x] write fail: %d\n", AIC_PATCH_ADDR(magic_num), ret);
return ret;
}
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, AIC_PATCH_ADDR(magic_num_2), AIC_PATCH_MAGIG_NUM_2))) {
AICWFDBG(LOGERROR, "maigic_num[0x%x] write fail: %d\n", AIC_PATCH_ADDR(magic_num_2), ret);
return ret;
}
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, AIC_PATCH_ADDR(pair_start), patch_addr))) {
AICWFDBG(LOGERROR, "pair_start[0x%x] write fail: %d\n", AIC_PATCH_ADDR(pair_start), ret);
return ret;
}
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, AIC_PATCH_ADDR(pair_count), patch_cnt + adap_patch_cnt))) {
AICWFDBG(LOGERROR, "pair_count[0x%x] write fail: %d\n", AIC_PATCH_ADDR(pair_count), ret);
return ret;
}
for (cnt = 0; cnt < patch_cnt; cnt++) {
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, start_addr+8*cnt, patch_tbl_d80x2[cnt][0]+config_base))) {
AICWFDBG(LOGERROR, "%x write fail\n", start_addr+8*cnt);
return ret;
}
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, start_addr+8*cnt+4, patch_tbl_d80x2[cnt][1]))) {
AICWFDBG(LOGERROR, "%x write fail\n", start_addr+8*cnt+4);
return ret;
}
}
if (adap_test){
int tmp_cnt = patch_cnt + adap_patch_cnt;
AICWFDBG(LOGINFO, "%s set adap_test patch \r\n", __func__);
for (cnt = patch_cnt; cnt < tmp_cnt; cnt++) {
int tbl_idx = cnt - patch_cnt;
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, start_addr+8*cnt, adaptivity_patch_tbl_d80x2[tbl_idx][0]+config_base))) {
AICWFDBG(LOGERROR, "%x write fail\n", start_addr+8*cnt);
return ret;
}
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, start_addr+8*cnt+4, adaptivity_patch_tbl_d80x2[tbl_idx][1]))) {
AICWFDBG(LOGERROR, "%x write fail\n", start_addr+8*cnt+4);
return ret;
}
}
}
/*
* Patch block 0 ~ 3, that is void by default, can be set as:
*
* const u32 patch_block_0[3] = {0x11223344, 0x55667788, 0xaabbccdd};
* if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, (u32)(&aic_patch->block_dst[0]), 0x160000))) {
* printk("block_dst [0x%x] write fail: %d\n", (u32)(&aic_patch->block_dst[0]), ret);
* }
* if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, (u32)(&aic_patch->block_src[0]), 0x307000))) {
* printk("block_src [0x%x] write fail: %d\n", (u32)(&aic_patch->block_src[0]), ret);
* }
* if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, (u32)(&aic_patch->block_size[0]), sizeof(patch_block_0) / sizeof(u32)))) {
* printk("block_size[0x%x] write fail: %d\n", (u32)(&aic_patch->block_size[0]), ret);
* }
* if ((ret = rwnx_send_dbg_mem_block_write_req(usb_dev, 0x307000, sizeof(patch_block_0), patch_block_0))) {
* printk("blk set fail: %d\n", ret);
* }
*/
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, AIC_PATCH_ADDR(block_size[0]), 0))) {
AICWFDBG(LOGERROR, "block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[0]), ret);
return ret;
}
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, AIC_PATCH_ADDR(block_size[1]), 0))) {
AICWFDBG(LOGERROR, "block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[1]), ret);
return ret;
}
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, AIC_PATCH_ADDR(block_size[2]), 0))) {
AICWFDBG(LOGERROR, "block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[2]), ret);
return ret;
}
if ((ret = rwnx_send_dbg_mem_write_req(usb_dev, AIC_PATCH_ADDR(block_size[3]), 0))) {
AICWFDBG(LOGERROR, "block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[3]), ret);
return ret;
}
#endif
return 0;
}
#if 0
extern char aic_fw_path[200];
int rwnx_plat_userconfig_load_8800d80x2(struct aic_usb_dev *usb_dev){
int size;
u32 *dst=NULL;
char *filename = FW_USERCONFIG_NAME_8800D80X2;
AICWFDBG(LOGINFO, "userconfig file path:%s \r\n", filename);
/* load file */
size = rwnx_request_firmware_common(usb_dev, &dst, filename);
if (size <= 0) {
AICWFDBG(LOGERROR, "wrong size of firmware file\n");
dst = NULL;
return 0;
}
/* Copy the file on the Embedded side */
AICWFDBG(LOGINFO, "### Load file done: %s, size=%d\n", filename, size);
rwnx_plat_userconfig_parsing((char *)dst, size);
rwnx_release_firmware_common(&dst);
AICWFDBG(LOGINFO, "userconfig download complete\n\n");
return 0;
}
#endif
int system_config_8800d80x2(struct aic_usb_dev *usb_dev){
int syscfg_num;
int ret, cnt;
const u32 mem_addr = 0x40500000;
const u32 mem_addr2 = 0x40500004;
struct dbg_mem_read_cfm rd_mem_addr_cfm;
ret = rwnx_send_dbg_mem_read_req(usb_dev, mem_addr, &rd_mem_addr_cfm);
if (ret) {
printk("%x rd fail: %d\n", mem_addr, ret);
return ret;
}
chip_id = rd_mem_addr_cfm.memdata >> 16;
ret = rwnx_send_dbg_mem_read_req(usb_dev, mem_addr2, &rd_mem_addr_cfm);
if (ret) {
printk("%x rd fail: %d\n", mem_addr2, ret);
return ret;
}
if (((rd_mem_addr_cfm.memdata >> 17) & 0x01UL) == 0x00UL) {
chip_mcu_id = 1;
}
printk("chip_id=%x, chip_mcu_id = %d\n", chip_id, chip_mcu_id);
#if 1
syscfg_num = sizeof(syscfg_tbl_8800d80x2) / sizeof(u32) / 2;
for (cnt = 0; cnt < syscfg_num; cnt++) {
ret = rwnx_send_dbg_mem_write_req(usb_dev, syscfg_tbl_8800d80x2[cnt][0], syscfg_tbl_8800d80x2[cnt][1]);
if (ret) {
printk("%x write fail: %d\n", syscfg_tbl_8800d80x2[cnt][0], ret);
return ret;
}
}
syscfg_num = sizeof(syscfg_tbl_masked_8800d80x2) / sizeof(u32) / 3;
for (cnt = 0; cnt < syscfg_num; cnt++) {
ret = rwnx_send_dbg_mem_mask_write_req(usb_dev,
syscfg_tbl_masked_8800d80x2[cnt][0], syscfg_tbl_masked_8800d80x2[cnt][1], syscfg_tbl_masked_8800d80x2[cnt][2]);
if (ret) {
printk("%x mask write fail: %d\n", syscfg_tbl_masked_8800d80x2[cnt][0], ret);
return ret;
}
}
#endif
return 0;
}
static int aicbt_ext_patch_data_load(struct aic_usb_dev *usb_dev, struct aicbt_patch_info_t *patch_info)
{
int ret = 0;
uint32_t ext_patch_nb = patch_info->ext_patch_nb;
char ext_patch_file_name[50];
int index = 0;
uint32_t id = 0;
uint32_t addr = 0;
if (ext_patch_nb > 0){
for (index = 0; index < patch_info->ext_patch_nb; index++){
id = *(patch_info->ext_patch_param + (index * 2));
addr = *(patch_info->ext_patch_param + (index * 2) + 1);
memset(ext_patch_file_name, 0, sizeof(ext_patch_file_name));
sprintf(ext_patch_file_name,"%s%d.bin",
FW_PATCH_BASE_NAME_8800D80X2_U03_EXT,
id);
AICWFDBG(LOGDEBUG, "%s ext_patch_file_name:%s ext_patch_id:%x ext_patch_addr:%x \r\n",
__func__,ext_patch_file_name, id, addr);
if (rwnx_plat_bin_fw_upload_android(usb_dev, addr, ext_patch_file_name)) {
ret = -1;
break;
}
}
}
return ret;
}
int aicfw_download_fw_8800d80x2(struct aic_usb_dev *usb_dev)
{
#ifdef CONFIG_USB_BT
struct aicbt_patch_table *head = NULL;
struct aicbt_patch_info_t patch_info = {
.info_len = 0,
.adid_addrinf = 0,
.addr_adid = 0,
.patch_addrinf = 0,
.addr_patch = 0,
.reset_addr = 0,
.reset_val = 0,
.adid_flag_addr = 0,
.adid_flag = 0,
};
int i = 0;
if (chip_id < CHIP_REV_U05) {
head = aicbt_patch_table_alloc(usb_dev, FW_PATCH_TABLE_NAME_8800D80X2_U03);
} else {
head = aicbt_patch_table_alloc(usb_dev, FW_PATCH_TABLE_NAME_8800D80X2_U05);
}
if (head == NULL){
printk("aicbt_patch_table_alloc fail\n");
return -1;
}
if(head == NULL){
return -1;
}
if (chip_id < CHIP_REV_U05) {
patch_info.addr_adid = FW_RAM_ADID_BASE_ADDR_8800D80X2_U03;
patch_info.addr_patch = FW_RAM_PATCH_BASE_ADDR_8800D80X2_U03;
} else {
patch_info.addr_adid = FW_RAM_ADID_BASE_ADDR_8800D80X2_U05;
patch_info.addr_patch = FW_RAM_PATCH_BASE_ADDR_8800D80X2_U05;
}
aicbt_patch_info_unpack(&patch_info, head);
if(patch_info.info_len == 0) {
printk("%s, aicbt_patch_info_unpack fail\n", __func__);
return -1;
}
printk("addr_adid 0x%x, addr_patch 0x%x\n", patch_info.addr_adid, patch_info.addr_patch);
if (chip_mcu_id) {
int ret = 0;
u32 retry = 0;
const u32 mem_addr = 0x40506030;
const u32 mem_addr2 = 0x40506004;
u32 mem_data;
struct dbg_mem_read_cfm rd_mem_addr_cfm;
ret = rwnx_send_dbg_mem_read_req(usb_dev, mem_addr, &rd_mem_addr_cfm);
if (ret) {
printk("%x rd fail: %d\n", mem_addr, ret);
return ret;
}
if (0 == (rd_mem_addr_cfm.memdata & (0x01UL << 2))) {
ret = rwnx_send_dbg_mem_read_req(usb_dev, mem_addr2, &rd_mem_addr_cfm);
if (ret) {
printk("%x rd fail: %d\n", mem_addr2, ret);
return ret;
}
mem_data = (rd_mem_addr_cfm.memdata | (0x01UL << 17)) & (~(0x01UL << 18));
ret = rwnx_send_dbg_mem_write_req(usb_dev, mem_addr2, mem_data);
if (ret) {
printk("%x wr fail: %d\n", mem_addr2, ret);
return ret;
}
mdelay(1);
while (1) {
ret = rwnx_send_dbg_mem_read_req(usb_dev, mem_addr, &rd_mem_addr_cfm);
if (ret) {
printk("%x rd fail: %d\n", mem_addr, ret);
return ret;
}
if (0 == (rd_mem_addr_cfm.memdata & (0x01UL << 2))) {
mdelay(1);
retry++;
if (retry > 20) {
printk("bt pwron timeout\n");
return -1;
}
} else {
break;
}
}
}
}
#endif
if(testmode == FW_NORMAL_MODE){
if (chip_id < CHIP_REV_U05){
#ifdef CONFIG_USB_BT
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_adid, FW_ADID_BASE_NAME_8800D80X2_U03)) {
return -1;
}
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_patch, FW_PATCH_BASE_NAME_8800D80X2_U03)) {
return -1;
}
if (aicbt_ext_patch_data_load(usb_dev, &patch_info)) {
return -1;
}
if (aicbt_patch_table_load(usb_dev, head)) {
return -1;
}
mdelay(100);
#endif
if(rwnx_plat_bin_fw_upload_android(usb_dev, RAM_FMAC_FW_ADDR_8800D80X2, FW_BASE_NAME_8800D80X2)) {
return -1;
}
#if 0
if(rwnx_plat_bin_fw_upload_android(usb_dev, FW_RAM_CALIBMODE_ADDR_8800D80X2_U02, FW_CALIBMODE_NAME_8800D80X2_U02)) {
return -1;
}
if (rwnx_send_dbg_mem_write_req(usb_dev, 0x40500048, 0x1e0000))
return -1;
#endif
if (aicwf_patch_config_8800d80x2(usb_dev)) {
return -1;
}
if (rwnx_send_dbg_start_app_req(usb_dev, RAM_FMAC_FW_ADDR_8800D80X2, HOST_START_APP_AUTO)) {
return -1;
}
}else {
#ifdef CONFIG_USB_BT
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_adid, FW_ADID_BASE_NAME_8800D80X2_U05)) {
return -1;
}
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_patch, FW_PATCH_BASE_NAME_8800D80X2_U05)) {
return -1;
}
if (aicbt_ext_patch_data_load(usb_dev, &patch_info)) {
return -1;
}
if (aicbt_patch_table_load(usb_dev, head)) {
return -1;
}
mdelay(100);
#endif
if(rwnx_plat_bin_fw_upload_android(usb_dev, RAM_FMAC_FW_ADDR_8800D80X2, FW_BASE_NAME_8800D80X2)) {
return -1;
}
if (aicwf_patch_config_8800d80x2(usb_dev)) {
return -1;
}
if (rwnx_send_dbg_start_app_req(usb_dev, RAM_FMAC_FW_ADDR_8800D80X2, HOST_START_APP_AUTO)) {
return -1;
}
}
}else if(testmode == FW_TEST_MODE){
if (chip_id < CHIP_REV_U05){
#ifdef CONFIG_USB_BT
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_adid, FW_ADID_BASE_NAME_8800D80X2_U03)) {
return -1;
}
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_patch, FW_PATCH_BASE_NAME_8800D80X2_U03)) {
return -1;
}
if (aicbt_ext_patch_data_load(usb_dev, &patch_info)) {
return -1;
}
if (aicbt_patch_table_load(usb_dev, head)) {
return -1;
}
mdelay(100);
#endif
if (chip_mcu_id) {
int ret = 0;
ret = rwnx_plat_flash_bin_upload_android(usb_dev, FLASH_BIN_ADDR_8800M80X2, FLASH_BIN_8800M80X2);
if (ret && ret!= ENOENT) {
AICWFDBG(LOGERROR,"%s flash bin download fail \r\n", __func__);
return -1;
}
}
if(rwnx_plat_bin_fw_upload_android(usb_dev, RAM_FMAC_RF_FW_ADDR_8800D80X2, FW_RF_BASE_NAME_8800D80X2)) {
AICWFDBG(LOGERROR,"%s wifi fw download fail \r\n", __func__);
return -1;
}
if (rwnx_send_dbg_start_app_req(usb_dev, RAM_FMAC_RF_FW_ADDR_8800D80X2, HOST_START_APP_AUTO)) {
return -1;
}
} else {
#ifdef CONFIG_USB_BT
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_adid, FW_ADID_BASE_NAME_8800D80X2_U05)) {
return -1;
}
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_patch, FW_PATCH_BASE_NAME_8800D80X2_U05)) {
return -1;
}
if (aicbt_ext_patch_data_load(usb_dev, &patch_info)) {
return -1;
}
if (aicbt_patch_table_load(usb_dev, head)) {
return -1;
}
mdelay(100);
#endif
if(rwnx_plat_bin_fw_upload_android(usb_dev, RAM_FMAC_RF_FW_ADDR_8800D80X2, FW_RF_BASE_NAME_8800D80X2)) {
AICWFDBG(LOGERROR,"%s wifi fw download fail \r\n", __func__);
return -1;
}
if (rwnx_send_dbg_start_app_req(usb_dev, RAM_FMAC_RF_FW_ADDR_8800D80X2, HOST_START_APP_AUTO)) {
return -1;
}
}
}else if(testmode == FW_BLE_SCAN_AD_FILTER_MODE){
/*
data and ad_data_filter_mask instructions for use
ex.
data[18] = {0x46,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x30,0xff,0xff,0xff,0x43,0x52,0x45,0x4c,0x42};
mask = 1100 0000 0111 1111 1100 0000 0000 0000 = 0xc07fc000
data = 0x46,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x30,0xff,0xff,0xff,0x43,0x52,0x45,0x4c,0x42
mask = 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0...... fill 0
data & mask = "0x46 0x00" 0x00 0x00 0x00 0x00 0x00 0x00 0x00 "0x30 0xff 0xff 0x43 0x52 0x45 0x4c 0x42"
using data & mask value condition to wakeup host_wake_bt gpio
*/
struct ble_wakeup_param_t* wakeup_param = (struct ble_wakeup_param_t*)kmalloc(sizeof(struct ble_wakeup_param_t), GFP_KERNEL);
uint32_t *write_blocks = (uint32_t *)wakeup_param;
printk("%s ble scan wakeup \r\n", __func__);
memset(wakeup_param, 0, sizeof(struct ble_wakeup_param_t));
rwnx_plat_bin_fw_upload_android(usb_dev, RAM_FW_BLE_SCAN_WAKEUP_ADDR_8800D80, FW_BLE_SCAN_AD_FILTER_NAME);
wakeup_param->magic_num = 0x53454C42;//magic_num
wakeup_param->delay_scan_to = 1000;//delay start scan time(ms)
wakeup_param->reboot_to = ble_scan_wakeup_reboot_time;//reboot time
/******************************************************************/
///gpio_trigger_idx : 0 if wakeup_param->gpio_dft_lvl[0]=0xfe,this idx will be invalid.
wakeup_param->gpio_num[0] = gpio_num;////default select gpiob2 for fw_wakeup_host
wakeup_param->gpio_dft_lvl[0] = gpio_dft_lvl;////0:defalut pull down, 1:default pull up
///gpio_trigger_idx : 1 if wakeup_param->gpio_dft_lvl[1]=0xfe,this idx will be invalid.
wakeup_param->gpio_num[1] = 3;////default select gpiob2 for fw_wakeup_host
wakeup_param->gpio_dft_lvl[1] = 1;////0:defalut pull down, 1:default pull up
/********************************************************************/
/********************************************************************/
//MAX_AD_FILTER_NUM=5 :num 0
{
const uint8_t data[11] = {0x59,0x4B,0x32,0x42,0x41,0x5F,0x54,0x45,0x53,0x54,0x33};
wakeup_param->ad_filter[0].ad_len = 12;
wakeup_param->ad_filter[0].ad_type = 0x09;
memcpy(wakeup_param->ad_filter[0].ad_data, data,wakeup_param->ad_filter[0].ad_len-1);// 1111 1111 1110 0000 0000 0000 0000 0000 //0xffe00000
wakeup_param->ad_filter[0].ad_data_mask = 0xffe00000;
wakeup_param->ad_filter[0].ad_role = ROLE_COMBO|(COMBO_0<<4);
wakeup_param->ad_filter[0].gpio_trigger_idx = TG_IDX_0;//0: match for wakeup_param->gpio_num[0] 1: match for wakeup_param->gpio_num[1]
/********************************************************************/
/*enable white list addr for paired remote ble addr. if all 0: all addr will use ad filter
wl_addr have value xx: only remote addr in white_list_addr will use ad filter
********************************************************************/
wakeup_param->ad_filter[0].wl_addr.addr[0] = 0;
wakeup_param->ad_filter[0].wl_addr.addr[1] = 0;
wakeup_param->ad_filter[0].wl_addr.addr[2] = 0;
wakeup_param->ad_filter[0].wl_addr.addr[3] = 0;
wakeup_param->ad_filter[0].wl_addr.addr[4] = 0;
wakeup_param->ad_filter[0].wl_addr.addr[5] = 0;
}
/********************************************************************/
//MAX_AD_FILTER_NUM=5 :num 1
{
const uint8_t data[2] = {0x12,0x18};
wakeup_param->ad_filter[1].ad_len = 3;
wakeup_param->ad_filter[1].ad_type = 0x3;
memcpy(wakeup_param->ad_filter[1].ad_data, data,wakeup_param->ad_filter[1].ad_len-1);// 1100 0000 0000 0000 0000 0000 0000 0000 //0xc0000000
wakeup_param->ad_filter[1].ad_data_mask = 0xc0000000;
wakeup_param->ad_filter[1].ad_role = ROLE_COMBO|(COMBO_0<<4);
wakeup_param->ad_filter[1].gpio_trigger_idx = TG_IDX_0;//0: match for wakeup_param->gpio_num[0] 1: match for wakeup_param->gpio_num[1]
/********************************************************************/
/*enable white list addr for paired remote ble addr. if all 0: all addr will use ad filter
wl_addr have value xx: only remote addr in white_list_addr will use ad filter
********************************************************************/
wakeup_param->ad_filter[1].wl_addr.addr[0] = 0;
wakeup_param->ad_filter[1].wl_addr.addr[1] = 0;
wakeup_param->ad_filter[1].wl_addr.addr[2] = 0;
wakeup_param->ad_filter[1].wl_addr.addr[3] = 0;
wakeup_param->ad_filter[1].wl_addr.addr[4] = 0;
wakeup_param->ad_filter[1].wl_addr.addr[5] = 0;
}
/********************************************************************/
//MAX_AD_FILTER_NUM=5 :num 2
{
//const uint8_t data[11] = {0x59,0x4B,0x32,0x42,0x41,0x5F,0x54,0x45,0x53,0x54,0x33};
wakeup_param->ad_filter[2].ad_len = 0;
wakeup_param->ad_filter[2].ad_type = 0;
//memcpy(wakeup_param->ad_filter[2].ad_data, data,wakeup_param->ad_filter[2].ad_len-1);// 1100 0000 0111 1111 1100 0000 0000 0000 //0xc07fc000
wakeup_param->ad_filter[2].ad_data_mask = 0;
wakeup_param->ad_filter[2].ad_role = ROLE_ONLY;
wakeup_param->ad_filter[2].gpio_trigger_idx = TG_IDX_0;//0: match for wakeup_param->gpio_num[0] 1: match for wakeup_param->gpio_num[1]
/********************************************************************/
/*enable white list addr for paired remote ble addr. if all 0: all addr will use ad filter
wl_addr have value xx: only remote addr in white_list_addr will use ad filter
********************************************************************/
wakeup_param->ad_filter[2].wl_addr.addr[0] = 0;
wakeup_param->ad_filter[2].wl_addr.addr[1] = 0;
wakeup_param->ad_filter[2].wl_addr.addr[2] = 0;
wakeup_param->ad_filter[2].wl_addr.addr[3] = 0;
wakeup_param->ad_filter[2].wl_addr.addr[4] = 0;
wakeup_param->ad_filter[2].wl_addr.addr[5] = 0;
}
/********************************************************************/
//MAX_AD_FILTER_NUM=5 :num 3
{
//const uint8_t data[11] = {0x59,0x4B,0x32,0x42,0x41,0x5F,0x54,0x45,0x53,0x54,0x33};
wakeup_param->ad_filter[3].ad_len = 0;
wakeup_param->ad_filter[3].ad_type = 0;
//memcpy(wakeup_param->ad_filter[2].ad_data, data,wakeup_param->ad_filter[2].ad_len-1);// 1100 0000 0111 1111 1100 0000 0000 0000 //0xc07fc000
wakeup_param->ad_filter[3].ad_data_mask = 0;
wakeup_param->ad_filter[3].ad_role = ROLE_COMBO|(COMBO_1<<4);
wakeup_param->ad_filter[3].gpio_trigger_idx = TG_IDX_0;//0: match for wakeup_param->gpio_num[0] 1: match for wakeup_param->gpio_num[1]
/********************************************************************/
/*enable white list addr for paired remote ble addr. if all 0: all addr will use ad filter
wl_addr have value xx: only remote addr in white_list_addr will use ad filter
********************************************************************/
wakeup_param->ad_filter[3].wl_addr.addr[0] = 0;
wakeup_param->ad_filter[3].wl_addr.addr[1] = 0;
wakeup_param->ad_filter[3].wl_addr.addr[2] = 0;
wakeup_param->ad_filter[3].wl_addr.addr[3] = 0;
wakeup_param->ad_filter[3].wl_addr.addr[4] = 0;
wakeup_param->ad_filter[3].wl_addr.addr[5] = 0;
}
/********************************************************************/
//MAX_AD_FILTER_NUM=5 :num 4
{
//const uint8_t data[11] = {0x59,0x4B,0x32,0x42,0x41,0x5F,0x54,0x45,0x53,0x54,0x33};
wakeup_param->ad_filter[4].ad_len = 0;
wakeup_param->ad_filter[4].ad_type = 0x09;
//memcpy(wakeup_param->ad_filter[4].ad_data, data,wakeup_param->ad_filter[4].ad_len-1);// 1111 1111 1110 0000 0000 0000 0000 0000 //0xffe00000
wakeup_param->ad_filter[4].ad_data_mask = 0xffe00000;
wakeup_param->ad_filter[4].ad_role = ROLE_COMBO|(COMBO_1<<4);
wakeup_param->ad_filter[4].gpio_trigger_idx = TG_IDX_0|TG_IDX_1;//0: match for wakeup_param->gpio_num[0] 1: match for wakeup_param->gpio_num[1]
/********************************************************************/
/*enable white list addr for paired remote ble addr. if all 0: all addr will use ad filter
wl_addr have value xx: only remote addr in white_list_addr will use ad filter
********************************************************************/
wakeup_param->ad_filter[4].wl_addr.addr[0] = 0;
wakeup_param->ad_filter[4].wl_addr.addr[1] = 0;
wakeup_param->ad_filter[4].wl_addr.addr[2] = 0;
wakeup_param->ad_filter[4].wl_addr.addr[3] = 0;
wakeup_param->ad_filter[4].wl_addr.addr[4] = 0;
wakeup_param->ad_filter[4].wl_addr.addr[5] = 0;
}
for(i = 0; i < (sizeof(struct ble_wakeup_param_t)/4 +1); i++){
printk("write_blocks[%d]:0x%08X \r\n", i, write_blocks[i]);
rwnx_send_dbg_mem_write_req(usb_dev, 0x15FE00 + (4 * i), write_blocks[i]);
}
//rwnx_send_dbg_start_app_req(usb_dev, RAM_FW_BLE_SCAN_WAKEUP_ADDR_8800D80, HOST_START_APP_AUTO);
int ret;
ret = rwnx_send_dbg_mem_write_req(usb_dev, 0x40500048, RAM_FW_BLE_SCAN_WAKEUP_ADDR_8800D80);
if (ret) {
printk("%x write fail\n", ret);
}
ret = rwnx_send_dbg_mem_write_req(usb_dev, 0x4050012c, 0x00000040);
if (ret) {
printk("%x write fail\n", ret);
}
kfree(wakeup_param);
return -1;
}
return 0;
}
@@ -0,0 +1,45 @@
#include <linux/types.h>
#include "aicwf_usb.h"
#define USB_DEVICE_ID_AIC_8800D80X2 0x8D90
#define USB_DEVICE_ID_AIC_8800D81X2 0x8D91
#define USB_DEVICE_ID_AIC_8800D89X2 0x8D99
#ifdef CONFIG_FOR_IPCAM
#define FW_BASE_NAME_8800D80X2 "fmacfw_8800d80x2_ipc.bin"
#else
#define FW_BASE_NAME_8800D80X2 "fmacfw_8800d80x2.bin"
#endif
#define FW_RF_BASE_NAME_8800D80X2 "lmacfw_rf_8800d80x2.bin"
#define FW_PATCH_BASE_NAME_8800D80X2_U03 "fw_patch_8800d80x2_u03.bin"
#define FW_PATCH_BASE_NAME_8800D80X2_U03_EXT "fw_patch_8800d80x2_u03_ext"
#define FW_ADID_BASE_NAME_8800D80X2_U03 "fw_adid_8800d80x2_u03.bin"
#define FW_PATCH_TABLE_NAME_8800D80X2_U03 "fw_patch_table_8800d80x2_u03.bin"
#define FW_PATCH_BASE_NAME_8800D80X2_U05 "fw_patch_8800d80x2_u05.bin"
#define FW_PATCH_BASE_NAME_8800D80X2_U05_EXT "fw_patch_8800d80x2_u05_ext"
#define FW_ADID_BASE_NAME_8800D80X2_U05 "fw_adid_8800d80x2_u05.bin"
#define FW_PATCH_TABLE_NAME_8800D80X2_U05 "fw_patch_table_8800d80x2_u05.bin"
#define FLASH_BIN_8800M80X2 "host_wb_8800m80x2.bin"
#define FW_USERCONFIG_NAME_8800D80X2 "aic_userconfig_8800d80x2.txt"
#define RAM_FMAC_FW_ADDR_8800D80X2 0x120000
#define RAM_FMAC_RF_FW_ADDR_8800D80X2 0x120000
#define FW_RAM_ADID_BASE_ADDR_8800D80X2_U03 0x003018f8
#define FW_RAM_PATCH_BASE_ADDR_8800D80X2_U03 0x0030b494
#define FW_RAM_ADID_BASE_ADDR_8800D80X2_U05 0x003018f8
#define FW_RAM_PATCH_BASE_ADDR_8800D80X2_U05 0x0030b48c
#define FLASH_BIN_ADDR_8800M80X2 0x8000000
int aicwf_patch_config_8800d80x2(struct aic_usb_dev *usb_dev);
int rwnx_plat_userconfig_load_8800d80x2(struct aic_usb_dev *usbdev);
int system_config_8800d80x2(struct aic_usb_dev *usb_dev);
int aicfw_download_fw_8800d80x2(struct aic_usb_dev *usb_dev);
+1 -1
View File
@@ -18,7 +18,7 @@
#define DATA_BUF_MAX 2048
#define TXPKT_BLOCKSIZE 512
#define MAX_AGGR_TXPKT_LEN (1536*32)
#define CMD_TX_TIMEOUT 5000
#define CMD_TX_TIMEOUT 2000
#define TX_ALIGNMENT 4
#define RX_HWHRD_LEN 60 //58->60 word allined
+148 -3
View File
@@ -5,6 +5,7 @@
#include "aic_txrxif.h"
#include "md5.h"
#include "aicbluetooth.h"
#include "aicwf_debug.h"
#ifdef CONFIG_USE_FW_REQUEST
#include <linux/firmware.h>
#endif
@@ -16,6 +17,8 @@
#define GET_VALUE 3
extern int flash_erase_len;
int flash_write_size = 0;
u32 flash_write_bin_crc = 0;
typedef struct
{
@@ -147,6 +150,8 @@ enum aicbsp_cpmode_type {
///pwr lvl:20(min), 30 , 40 , 50 , 60(max)
#define AICBT_TXPWR_LVL 0x00006020
#define AICBT_TXPWR_LVL_8800d80 0x00006F2F
#define AICBT_TXPWR_LVL_8800d80x2 0x00006F2F
#define AICBSP_MODE_BT_HCI_MODE_NULL 0
#define AICBSP_MODE_BT_HCI_MODE_MB 1
@@ -155,6 +160,7 @@ enum aicbsp_cpmode_type {
#define AICBSP_HWINFO_DEFAULT (-1)
#define AICBSP_CPMODE_DEFAULT AICBSP_CPMODE_WORK
#define AICBT_BTMODE_DEFAULT_8800d80x2 AICBT_BTMODE_BT_ONLY_COANT
#define AICBT_BTMODE_DEFAULT_8800d80 AICBT_BTMODE_BT_ONLY_COANT
#define AICBT_BTMODE_DEFAULT AICBT_BTMODE_BT_ONLY
#define AICBT_BTPORT_DEFAULT AICBT_BTPORT_MB
@@ -163,6 +169,7 @@ enum aicbsp_cpmode_type {
#define AICBT_LPM_ENABLE_DEFAULT 0
#define AICBT_TXPWR_LVL_DEFAULT AICBT_TXPWR_LVL
#define AICBT_TXPWR_LVL_DEFAULT_8800d80 AICBT_TXPWR_LVL_8800d80
#define AICBT_TXPWR_LVL_DEFAULT_8800d80x2 AICBT_TXPWR_LVL_8800d80x2
#define AIC_HW_INFO 0x21
@@ -181,6 +188,83 @@ module_param_string(saved_sdk_ver, saved_sdk_ver,64, 0660);
#endif
const u32 crc_tab[256] =
{
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
};
u32 aic_crc32(u8 *p, u32 len, u32 crc)
{
while(len--)
{
crc = crc_tab[((crc & 0xFF) ^ *p++)] ^ (crc >> 8);
}
return crc;
}
int aic_bt_platform_init(struct aic_usb_dev *usbdev)
{
rwnx_cmd_mgr_init(&usbdev->cmd_mgr);
@@ -274,7 +358,9 @@ static int aic_load_firmware(u32 ** fw_buf, const char *name, struct device *dev
len = snprintf(path, FW_PATH_MAX, "%s/%s/%s",aic_default_fw_path, "aic8800", name);
} else if (usb_dev->chipid == PRODUCT_ID_AIC8800D80) {
len = snprintf(path, FW_PATH_MAX, "%s/%s/%s",aic_default_fw_path, "aic8800D80", name);
} else {
} else if (usb_dev->chipid == PRODUCT_ID_AIC8800D80X2) {
len = snprintf(path, FW_PATH_MAX, "%s/%s/%s",aic_default_fw_path, "aic8800D80X2", name);
}else {
printk("%s unknown chipid %d\n", __func__, usb_dev->chipid);
}
#else
@@ -671,9 +757,11 @@ int rwnx_plat_flash_bin_upload_android(struct aic_usb_dev *usbdev, u32 fw_addr,
int err=0;
const u32 mem_addr = fw_addr;
struct dbg_mem_read_cfm rd_mem_addr_cfm;
u32 crc = ~0UL;
/* load aic firmware */
size = aic_load_firmware(&dst, filename, dev);
flash_write_size = size;
if(size<=0){
printk("wrong size of firmware file\n");
vfree(dst);
@@ -716,6 +804,8 @@ int rwnx_plat_flash_bin_upload_android(struct aic_usb_dev *usbdev, u32 fw_addr,
/* Copy the file on the Embedded side */
printk("### Upload %s firmware, @ = %x size=%d\n", filename, fw_addr, size);
crc = aic_crc32((u8 *)dst, size, crc);
flash_write_bin_crc = crc;
if (size > 1024) {// > 1KB data
for (i = 0; i < (size - 1024); i += 1024) {//each time write 1KB
@@ -832,6 +922,16 @@ int get_adap_test(void){
return adap_test;
}
int get_flash_bin_size(void)
{
return flash_write_size;
}
u32 get_flash_bin_crc(void)
{
return flash_write_bin_crc;
}
EXPORT_SYMBOL(get_fw_path);
EXPORT_SYMBOL(get_testmode);
@@ -842,6 +942,9 @@ EXPORT_SYMBOL(get_hardware_info);
EXPORT_SYMBOL(get_adap_test);
EXPORT_SYMBOL(get_flash_bin_size);
EXPORT_SYMBOL(get_flash_bin_crc);
void get_userconfig_xtal_cap(xtal_cap_conf_t *xtal_cap)
{
@@ -1172,6 +1275,14 @@ static struct aicbt_info_t aicbt_info[] = {
},//PRODUCT_ID_AIC8800D80
{
},//PRODUCT_ID_AIC8800D81
{
.btmode = AICBT_BTMODE_DEFAULT_8800d80x2,
.btport = AICBT_BTPORT_DEFAULT,
.uart_baud = AICBT_UART_BAUD_DEFAULT,
.uart_flowctrl = AICBT_UART_FC_DEFAULT,
.lpm_enable = AICBT_LPM_ENABLE_DEFAULT,
.txpwr_lvl = AICBT_TXPWR_LVL_DEFAULT_8800d80x2,
},//PRODUCT_ID_AIC8800D80X2
};
int aicbt_patch_table_load(struct aic_usb_dev *usbdev, struct aicbt_patch_table *_head)
@@ -1223,13 +1334,47 @@ int aicbt_patch_table_load(struct aic_usb_dev *usbdev, struct aicbt_patch_table
int aicbt_patch_info_unpack(struct aicbt_patch_info_t *patch_info, struct aicbt_patch_table *head_t)
{
uint8_t *patch_info_array = (uint8_t*)patch_info;
int base_len = 0;
int memcpy_len = 0;
if (AICBT_PT_INF == head_t->type) {
base_len = ((offsetof(struct aicbt_patch_info_t, ext_patch_nb_addr) - offsetof(struct aicbt_patch_info_t, adid_addrinf) )/sizeof(uint32_t))/2;
AICWFDBG(LOGDEBUG, "%s head_t->len:%d base_len:%d \r\n", __func__, head_t->len, base_len);
if (head_t->len > base_len){
patch_info->info_len = base_len;
memcpy_len = patch_info->info_len + 1;//include ext patch nb
} else{
patch_info->info_len = head_t->len;
if(patch_info->info_len == 0)
memcpy_len = patch_info->info_len;
}
AICWFDBG(LOGDEBUG, "%s memcpy_len:%d \r\n", __func__, memcpy_len);
if (patch_info->info_len == 0)
return 0;
memcpy(&patch_info->adid_addrinf, head_t->data, patch_info->info_len * sizeof(uint32_t) * 2);
memcpy(((patch_info_array) + sizeof(patch_info->info_len)),
head_t->data,
memcpy_len * sizeof(uint32_t) * 2);
AICWFDBG(LOGDEBUG, "%s adid_addrinf:%x addr_adid:%x \r\n", __func__,
((struct aicbt_patch_info_t *)patch_info_array)->adid_addrinf,
((struct aicbt_patch_info_t *)patch_info_array)->addr_adid);
if (patch_info->ext_patch_nb > 0){
int index = 0;
patch_info->ext_patch_param = (uint32_t *)(head_t->data + ((memcpy_len) * 2));
for(index = 0; index < patch_info->ext_patch_nb; index++){
AICWFDBG(LOGDEBUG, "%s id:%x addr:%x \r\n", __func__,
*(patch_info->ext_patch_param + (index * 2)),
*(patch_info->ext_patch_param + (index * 2) + 1));
}
}
}
return 0;
}
int rwnx_plat_bin_fw_patch_table_upload_android(struct aic_usb_dev *usbdev, char *filename){
@@ -240,6 +240,7 @@ void aicwf_set_cmd_tx(void *dev, struct lmac_msg *msg, uint len)
struct aicwf_bus *bus = usbdev->bus_if;
u8 *buffer = bus->cmd_buf;
u16 index = 0;
int ret = 0;
memset(buffer, 0, CMD_BUF_MAX);
buffer[0] = (len+4) & 0x00ff;
@@ -261,7 +262,10 @@ void aicwf_set_cmd_tx(void *dev, struct lmac_msg *msg, uint len)
index += 2;
memcpy(&buffer[index], (u8 *)msg->param, msg->param_len);
aicwf_bus_txmsg(bus, buffer, len + 8);
ret = aicwf_bus_txmsg(bus, buffer, len + 8);
if (ret == -EIO) {
ret = aicwf_bus_txmsg(bus, buffer, len + 8);
}
}
static inline void *rwnx_msg_zalloc(lmac_msg_id_t const id,
@@ -59,6 +59,7 @@ struct lmac_msg
struct aicbt_patch_info_t {
uint32_t info_len;
//base len start
uint32_t adid_addrinf;
uint32_t addr_adid;
uint32_t patch_addrinf;
@@ -67,6 +68,12 @@ struct aicbt_patch_info_t {
uint32_t reset_val;
uint32_t adid_flag_addr;
uint32_t adid_flag;
//base len end
//ext patch nb
uint32_t ext_patch_nb_addr;
uint32_t ext_patch_nb;
uint32_t *ext_patch_param;
};
+94 -12
View File
@@ -25,6 +25,7 @@
#include "aicbluetooth.h"
#include "aicwf_debug.h"
#include "aic_compat_8800d80.h"
#include "aic_compat_8800d80x2.h"
#define JUMP_TABLE_BASE 0x161928
#define JUMP_TABLE_OFFSET(i) ((u32)(JUMP_TABLE_BASE+(i)*4))
@@ -37,6 +38,7 @@ extern uint32_t gpio_num;//default select gpiob2 for fw_wakeup_host
extern uint32_t gpio_dft_lvl;//0:defalut pull down, 1:default pull up
u8 chip_id = 0;
u8 chip_sub_id = 0;
u8 chip_mcu_id = 0;
int fw_loaded = 0;
void aicwf_usb_tx_flowctrl(struct aic_usb_dev *usb_dev, bool state)
@@ -821,7 +823,9 @@ static int aicwf_parse_usb(struct aic_usb_dev *usb_dev, struct usb_interface *in
#ifdef CONFIG_USB_MSG_EP
if ( usb_dev->msg_out_pipe != 0 &&
(usb_dev->chipid == PRODUCT_ID_AIC8801 ||
usb_dev->chipid == PRODUCT_ID_AIC8800D81)){
usb_dev->chipid == PRODUCT_ID_AIC8800D81||
usb_dev->chipid == PRODUCT_ID_AIC8800D81X2 ||
usb_dev->chipid == PRODUCT_ID_AIC8800D89X2)){
printk("TX Msg Bulk EP found\n");
usb_dev->use_msg_ep = 1;
}else{
@@ -838,12 +842,11 @@ static int aicwf_parse_usb(struct aic_usb_dev *usb_dev, struct usb_interface *in
#endif
#endif
if (usb->speed == USB_SPEED_HIGH) {
printk("Aic high speed USB device detected\n");
} else {
printk("Aic full speed USB device detected\n");
}
printk("Aic %s speed USB device detected\n",
(usb->speed == USB_SPEED_SUPER) ? "super" :
(usb->speed == USB_SPEED_HIGH) ? "high" :
(usb->speed == USB_SPEED_FULL) ? "full" :
(usb->speed == USB_SPEED_LOW) ? "low" : "NG");
exit:
return ret;
}
@@ -981,6 +984,11 @@ u32 patch_tbl[][2] ={
#endif
#ifdef CONFIG_USB_SUSPEND_REBOOT_TIME
{0x0110, 0x03e80001}//reboot time when usb suspend,0001 enables reboot on suspend, default 0x3e8 = 1000ms reboot
#else
#ifdef CONFIG_SUPPORT_USB_SUSP
//USB SUSP keep working 0x0100:enable 0x0000:disable
{0x0110, 0x00000100}
#endif
#endif
};
@@ -1133,6 +1141,8 @@ static int system_config(struct aic_usb_dev *usb_dev)
return system_config_8800(usb_dev);
}else if(usb_dev->chipid == PRODUCT_ID_AIC8800D80){
return system_config_8800d80(usb_dev);
}else if(usb_dev->chipid == PRODUCT_ID_AIC8800D80X2){
return system_config_8800d80x2(usb_dev);
}else{
return -1;
}
@@ -1345,6 +1355,18 @@ static int aicloadfw_chipmatch(struct aic_usb_dev *usb_dev, u16 vid, u16 pid){
usb_dev->chipid = PRODUCT_ID_AIC8800D81;
AICWFDBG(LOGINFO, "%s USE AIC8800D41\r\n", __func__);
return 0;
}else if(pid == USB_DEVICE_ID_AIC_8800D80X2 && vid == USB_VENDOR_ID_AIC_V2){
usb_dev->chipid = PRODUCT_ID_AIC8800D80X2;
AICWFDBG(LOGINFO, "%s USE AIC8800D80X2\r\n", __func__);
return 0;
}else if(pid == USB_DEVICE_ID_AIC_8800D81X2 && vid == USB_VENDOR_ID_AIC_V2){
usb_dev->chipid = PRODUCT_ID_AIC8800D81X2;
AICWFDBG(LOGINFO, "%s USE AIC8800D81X2\r\n", __func__);
return 0;
}else if(pid == USB_DEVICE_ID_AIC_8800D89X2 && vid == USB_VENDOR_ID_AIC_V2){
usb_dev->chipid = PRODUCT_ID_AIC8800D89X2;
AICWFDBG(LOGINFO, "%s USE AIC8800D89X2\r\n", __func__);
return 0;
}else{
return -1;
}
@@ -1451,6 +1473,7 @@ int aicfw_download_fw_8800(struct aic_usb_dev *usb_dev){
///gpio_trigger_idx : 1 if wakeup_param->gpio_dft_lvl[1]=0xfe,this idx will be invalid.
wakeup_param->gpio_num[1] = 3;////default select gpiob2 for fw_wakeup_host
wakeup_param->gpio_dft_lvl[1] = 1;////0:defalut pull down, 1:default pull up
/********************************************************************/
/********************************************************************/
//MAX_AD_FILTER_NUM=5 :num 0
{
@@ -1461,6 +1484,16 @@ int aicfw_download_fw_8800(struct aic_usb_dev *usb_dev){
wakeup_param->ad_filter[0].ad_data_mask = 0xffe00000;
wakeup_param->ad_filter[0].ad_role = ROLE_COMBO|(COMBO_0<<4);
wakeup_param->ad_filter[0].gpio_trigger_idx = TG_IDX_0;//0: match for wakeup_param->gpio_num[0] 1: match for wakeup_param->gpio_num[1]
/********************************************************************/
/*enable white list addr for paired remote ble addr. if all 0: all addr will use ad filter
wl_addr have value xx: only remote addr in white_list_addr will use ad filter
********************************************************************/
wakeup_param->ad_filter[0].wl_addr.addr[0] = 0;
wakeup_param->ad_filter[0].wl_addr.addr[1] = 0;
wakeup_param->ad_filter[0].wl_addr.addr[2] = 0;
wakeup_param->ad_filter[0].wl_addr.addr[3] = 0;
wakeup_param->ad_filter[0].wl_addr.addr[4] = 0;
wakeup_param->ad_filter[0].wl_addr.addr[5] = 0;
}
/********************************************************************/
//MAX_AD_FILTER_NUM=5 :num 1
@@ -1472,6 +1505,16 @@ int aicfw_download_fw_8800(struct aic_usb_dev *usb_dev){
wakeup_param->ad_filter[1].ad_data_mask = 0xc0000000;
wakeup_param->ad_filter[1].ad_role = ROLE_COMBO|(COMBO_0<<4);
wakeup_param->ad_filter[1].gpio_trigger_idx = TG_IDX_0;//0: match for wakeup_param->gpio_num[0] 1: match for wakeup_param->gpio_num[1]
/********************************************************************/
/*enable white list addr for paired remote ble addr. if all 0: all addr will use ad filter
wl_addr have value xx: only remote addr in white_list_addr will use ad filter
********************************************************************/
wakeup_param->ad_filter[1].wl_addr.addr[0] = 0;
wakeup_param->ad_filter[1].wl_addr.addr[1] = 0;
wakeup_param->ad_filter[1].wl_addr.addr[2] = 0;
wakeup_param->ad_filter[1].wl_addr.addr[3] = 0;
wakeup_param->ad_filter[1].wl_addr.addr[4] = 0;
wakeup_param->ad_filter[1].wl_addr.addr[5] = 0;
}
/********************************************************************/
//MAX_AD_FILTER_NUM=5 :num 2
@@ -1483,6 +1526,16 @@ int aicfw_download_fw_8800(struct aic_usb_dev *usb_dev){
wakeup_param->ad_filter[2].ad_data_mask = 0;
wakeup_param->ad_filter[2].ad_role = ROLE_ONLY;
wakeup_param->ad_filter[2].gpio_trigger_idx = TG_IDX_0;//0: match for wakeup_param->gpio_num[0] 1: match for wakeup_param->gpio_num[1]
/********************************************************************/
/*enable white list addr for paired remote ble addr. if all 0: all addr will use ad filter
wl_addr have value xx: only remote addr in white_list_addr will use ad filter
********************************************************************/
wakeup_param->ad_filter[2].wl_addr.addr[0] = 0;
wakeup_param->ad_filter[2].wl_addr.addr[1] = 0;
wakeup_param->ad_filter[2].wl_addr.addr[2] = 0;
wakeup_param->ad_filter[2].wl_addr.addr[3] = 0;
wakeup_param->ad_filter[2].wl_addr.addr[4] = 0;
wakeup_param->ad_filter[2].wl_addr.addr[5] = 0;
}
/********************************************************************/
//MAX_AD_FILTER_NUM=5 :num 3
@@ -1494,6 +1547,16 @@ int aicfw_download_fw_8800(struct aic_usb_dev *usb_dev){
wakeup_param->ad_filter[3].ad_data_mask = 0;
wakeup_param->ad_filter[3].ad_role = ROLE_COMBO|(COMBO_1<<4);
wakeup_param->ad_filter[3].gpio_trigger_idx = TG_IDX_0;//0: match for wakeup_param->gpio_num[0] 1: match for wakeup_param->gpio_num[1]
/********************************************************************/
/*enable white list addr for paired remote ble addr. if all 0: all addr will use ad filter
wl_addr have value xx: only remote addr in white_list_addr will use ad filter
********************************************************************/
wakeup_param->ad_filter[3].wl_addr.addr[0] = 0;
wakeup_param->ad_filter[3].wl_addr.addr[1] = 0;
wakeup_param->ad_filter[3].wl_addr.addr[2] = 0;
wakeup_param->ad_filter[3].wl_addr.addr[3] = 0;
wakeup_param->ad_filter[3].wl_addr.addr[4] = 0;
wakeup_param->ad_filter[3].wl_addr.addr[5] = 0;
}
/********************************************************************/
//MAX_AD_FILTER_NUM=5 :num 4
@@ -1505,11 +1568,21 @@ int aicfw_download_fw_8800(struct aic_usb_dev *usb_dev){
wakeup_param->ad_filter[4].ad_data_mask = 0xffe00000;
wakeup_param->ad_filter[4].ad_role = ROLE_COMBO|(COMBO_1<<4);
wakeup_param->ad_filter[4].gpio_trigger_idx = TG_IDX_0|TG_IDX_1;//0: match for wakeup_param->gpio_num[0] 1: match for wakeup_param->gpio_num[1]
/********************************************************************/
/*enable white list addr for paired remote ble addr. if all 0: all addr will use ad filter
wl_addr have value xx: only remote addr in white_list_addr will use ad filter
********************************************************************/
wakeup_param->ad_filter[4].wl_addr.addr[0] = 0;
wakeup_param->ad_filter[4].wl_addr.addr[1] = 0;
wakeup_param->ad_filter[4].wl_addr.addr[2] = 0;
wakeup_param->ad_filter[4].wl_addr.addr[3] = 0;
wakeup_param->ad_filter[4].wl_addr.addr[4] = 0;
wakeup_param->ad_filter[4].wl_addr.addr[5] = 0;
}
for(i = 0; i < (sizeof(struct ble_wakeup_param_t)/4 +1); i++){
printk("write_blocks[%d]:0x%08X \r\n", i, write_blocks[i]);
rwnx_send_dbg_mem_write_req(usb_dev, 0x15FF00 + (4 * i), write_blocks[i]);
rwnx_send_dbg_mem_write_req(usb_dev, 0x15FE00 + (4 * i), write_blocks[i]);
}
rwnx_send_dbg_start_app_req(usb_dev, RAM_FW_BLE_SCAN_WAKEUP_ADDR, HOST_START_APP_AUTO);
kfree(wakeup_param);
@@ -1580,6 +1653,8 @@ int aicfw_download_fw(struct aic_usb_dev *usb_dev)
return aicfw_download_fw_8800(usb_dev);
}else if(usb_dev->chipid == PRODUCT_ID_AIC8800D80){
return aicfw_download_fw_8800d80(usb_dev);
}else if(usb_dev->chipid == PRODUCT_ID_AIC8800D80X2){
return aicfw_download_fw_8800d80x2(usb_dev);
}else{
return -1;
}
@@ -1606,7 +1681,9 @@ static int aicwf_usb_probe(struct usb_interface *intf, const struct usb_device_i
if(fw_loaded == 1 &&
(id->idProduct == USB_DEVICE_ID_AIC_8801 ||
id->idProduct == USB_DEVICE_ID_AIC_8800D81 ||
id->idProduct == USB_DEVICE_ID_AIC_8800D41)){
id->idProduct == USB_DEVICE_ID_AIC_8800D41 ||
id->idProduct == USB_DEVICE_ID_AIC_8800D81X2 ||
id->idProduct == USB_DEVICE_ID_AIC_8800D89X2)){
return -1;
}
@@ -1673,15 +1750,17 @@ static int aicwf_usb_probe(struct usb_interface *intf, const struct usb_device_i
aic_bt_platform_init(usb_dev);
if (usb->speed != USB_SPEED_HIGH) {
printk("Aic full speed USB device detected\n");
if ((usb->speed != USB_SPEED_HIGH) && (usb->speed != USB_SPEED_SUPER)) {
printk("Aic USB device detected speed = %d\n", usb->speed);
system_reboot(usb_dev);
goto out_free_bus;
}
if(fw_loaded == 0 &&
(usb_dev->chipid == PRODUCT_ID_AIC8801 ||
usb_dev->chipid == PRODUCT_ID_AIC8800D81)){
usb_dev->chipid == PRODUCT_ID_AIC8800D81||
usb_dev->chipid == PRODUCT_ID_AIC8800D81X2 ||
usb_dev->chipid == PRODUCT_ID_AIC8800D89X2)){
rwnx_send_reboot(usb_dev);
goto out_free_bus;
}
@@ -1764,6 +1843,9 @@ static struct usb_device_id aicwf_usb_id_table[] = {
{USB_DEVICE(USB_VENDOR_ID_AIC, USB_DEVICE_ID_AIC_8800D81)},
{USB_DEVICE(USB_VENDOR_ID_AIC, USB_DEVICE_ID_AIC_8800D40)},
{USB_DEVICE(USB_VENDOR_ID_AIC, USB_DEVICE_ID_AIC_8800D41)},
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_DEVICE_ID_AIC_8800D80X2)},
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_DEVICE_ID_AIC_8800D81X2)},
{USB_DEVICE(USB_VENDOR_ID_AIC_V2, USB_DEVICE_ID_AIC_8800D89X2)},
{}
};
+15 -1
View File
@@ -21,12 +21,15 @@
/* USB Device ID */
#define USB_VENDOR_ID_AIC 0xA69C
#define USB_VENDOR_ID_AIC_V2 0x368B
#define USB_DEVICE_ID_AIC 0x8800
#define USB_DEVICE_ID_AIC_8801 0x8801
#define CHIP_REV_U01 0x1
#define CHIP_REV_U02 0x3
#define CHIP_REV_U03 0x7
#define CHIP_REV_U04 0xf
#define CHIP_REV_U05 0x1f
#define CHIP_SUB_REV_U04 0x20
enum AICWF_IC{
@@ -36,11 +39,14 @@ enum AICWF_IC{
PRODUCT_ID_AIC8800DW,
PRODUCT_ID_AIC8800D80,
PRODUCT_ID_AIC8800D81,
PRODUCT_ID_AIC8800D80X2,
PRODUCT_ID_AIC8800D81X2,
PRODUCT_ID_AIC8800D89X2,
};
#define AICWF_USB_RX_URBS (20)
#define AICWF_USB_TX_URBS (100)
#define AICWF_USB_TX_URBS (30)
#define AICWF_USB_TX_LOW_WATER (AICWF_USB_TX_URBS/4)
#define AICWF_USB_TX_HIGH_WATER (AICWF_USB_TX_LOW_WATER*3)
#define AICWF_USB_MAX_PKT_SIZE (2048)
@@ -84,6 +90,7 @@ enum AICWF_IC{
#define FW_RAM_PATCH_BASE_ADDR 0x00100000
#define FW_RAM_PATCH_BASE_ADDR_U03 0x00100000
#define FW_PATCH_TEST_BASE_ADDR 0x00100000
#define RAM_FW_BLE_WAKEUP_OUT_ADDR 0x0015f000
enum {
FW_NORMAL_MODE,
@@ -118,6 +125,7 @@ enum aicwf_usb_state {
#define MAX_GPIO_TRIGGER_NUM 2// Max user config num of gpio
#define MAX_ROLE_COMNO_IDX_NUM 2// Max num of ad role type combo,form( enum gpio_combo_idx)
#define AD_ROLE_FLAG 0x0f
#define ROLE_COMBO_IDX_FLAG 0xf0
@@ -136,6 +144,11 @@ enum gpio_trigger_bit {
TG_IDX_1 = (1<<1),
};
/* BD Address */
typedef struct {
uint8_t addr[6];
}bdaddr_t;
struct wakeup_ad_data_filter {
uint32_t ad_data_mask;
uint8_t gpio_trigger_idx;
@@ -143,6 +156,7 @@ struct wakeup_ad_data_filter {
uint8_t ad_len;
uint8_t ad_type;
uint8_t ad_data[31];
bdaddr_t wl_addr;
};
struct ble_wakeup_param_t {
@@ -1,4 +1,4 @@
#define RWNX_VERS_REV "1a4b0054d2M (master)"
#define RWNX_VERS_MOD "6.4.3.0"
#define RWNX_VERS_BANNER "rwnx v6.4.3.0 - 1a4b0054d2M (master)"
#define RELEASE_DATE "2024_0420_24c7777c"
#define RELEASE_DATE "2025_0423_71b66e7b"
+118
View File
@@ -0,0 +1,118 @@
# AIC POWERLIMIT 2024/1108/1900
# Max tx power reference: Linux wireless regulatory database for CRDA
# https://git.kernel.org/pub/scm/linux/kernel/git/sforshee/wireless-regdb.git/tree/db.txt
# If loss_value in aic_userconfig_8800d80.txt is enabled, the power value in this document will be subtracted from loss_value in actual judgment
# Table 1:
## 2.4G, 20M,#5#
## START
## SRRC FCC ETSI JP UNSET
CH01 15 15 15 15 15
CH02 16 16 16 16 16
CH03 16 16 16 16 16
CH04 16 16 16 16 16
CH05 16 16 16 16 16
CH06 16 16 16 16 16
CH07 16 16 16 16 16
CH08 16 16 16 16 16
CH09 16 16 16 16 16
CH10 16 16 16 16 16
CH11 16 16 16 16 16
CH12 12 12 12 12 12
CH13 12 12 12 12 12
CH14 NA NA NA 12 12
## END
# Table 2:
## 2.4G, 40M,#5#
## START
## SRRC FCC ETSI JP UNSET
CH01 NA NA NA NA NA
CH02 NA NA NA NA NA
CH03 16 16 16 16 16
CH04 16 16 16 16 16
CH05 16 16 16 16 16
CH06 16 16 16 16 16
CH07 16 16 16 16 16
CH08 16 16 16 16 16
CH09 16 16 16 16 16
CH10 16 16 16 16 16
CH11 16 16 16 16 16
CH12 NA NA NA NA NA
CH13 NA NA NA NA NA
CH14 NA NA NA NA NA
## END
# Table 3:
## 5G, 20M,#5#
## START
## SRRC FCC ETSI JP UNSET
# 5G Band 1
CH36 15 16 16 16 15
CH40 15 16 16 16 15
CH44 15 16 16 16 15
CH48 15 16 16 16 15
# 5G Band 2
CH52 15 16 16 16 15
CH56 15 16 16 16 15
CH60 15 16 16 16 15
CH64 15 16 16 16 15
# 5G Band 3
CH100 NA 16 16 16 15
CH104 NA 16 16 16 15
CH108 NA 16 16 16 15
CH112 NA 16 16 16 15
CH116 NA 16 16 16 15
CH120 NA 16 16 16 15
CH124 NA 16 16 16 15
CH128 NA 16 16 16 15
CH132 NA 16 16 16 15
CH136 NA 16 16 16 15
CH140 NA 16 16 16 15
CH144 NA NA 16 16 15
# 5G Band 4
CH149 16 16 11 NA 11
CH153 16 16 11 NA 11
CH157 16 16 11 NA 11
CH161 16 16 11 NA 11
CH165 16 16 11 NA 11
## END
# Table 4:
## 5G, 40M,#5#
## START
## SRRC FCC ETSI JP UNSET
# 5G Band 1
CH38 15 16 16 16 15
CH46 15 16 16 16 15
# 5G Band 2
CH54 15 16 16 16 15
CH62 15 16 16 16 15
# 5G Band 3
CH102 NA 16 16 16 15
CH110 NA 16 16 16 15
CH118 NA 16 16 16 15
CH126 NA 16 16 16 15
CH134 NA 16 16 16 15
CH142 NA 16 NA 16 15
# 5G Band 4
CH151 16 16 11 NA 11
CH159 16 16 11 NA 11
## END
# Table 5:
## 5G, 80M,#5#
## START
## SRRC FCC ETSI JP UNSET
# 5G Band 1
CH42 15 16 16 16 15
# 5G Band 2
CH58 15 16 16 16 15
# 5G Band 3
CH106 NA 16 16 16 15
CH122 NA 16 16 16 15
CH138 NA 16 NA NA 15
# 5G Band 4
CH155 16 16 11 NA 11
## END
+77 -63
View File
@@ -2,74 +2,88 @@
# txpwr_lvl
enable=1
lvl_11b_11ag_1m_2g4=20
lvl_11b_11ag_2m_2g4=20
lvl_11b_11ag_5m5_2g4=20
lvl_11b_11ag_11m_2g4=20
lvl_11b_11ag_6m_2g4=20
lvl_11b_11ag_9m_2g4=20
lvl_11b_11ag_12m_2g4=20
lvl_11b_11ag_18m_2g4=20
lvl_11b_11ag_24m_2g4=20
lvl_11b_11ag_36m_2g4=19
lvl_11b_11ag_48m_2g4=18
lvl_11b_11ag_54m_2g4=17
lvl_11n_11ac_mcs0_2g4=20
lvl_11n_11ac_mcs1_2g4=20
lvl_11n_11ac_mcs2_2g4=20
lvl_11n_11ac_mcs3_2g4=20
lvl_11n_11ac_mcs4_2g4=20
lvl_11n_11ac_mcs5_2g4=19
lvl_11n_11ac_mcs6_2g4=18
lvl_11n_11ac_mcs7_2g4=17
lvl_11n_11ac_mcs8_2g4=17
lvl_11n_11ac_mcs9_2g4=16
lvl_11ax_mcs0_2g4=20
lvl_11ax_mcs1_2g4=20
lvl_11ax_mcs2_2g4=20
lvl_11ax_mcs3_2g4=20
lvl_11ax_mcs4_2g4=20
lvl_11ax_mcs5_2g4=19
lvl_11ax_mcs6_2g4=18
lvl_11ax_mcs7_2g4=17
lvl_11ax_mcs8_2g4=17
lvl_11ax_mcs9_2g4=16
lvl_11ax_mcs10_2g4=15
lvl_11ax_mcs11_2g4=15
lvl_11a_6m_5g=19
lvl_11a_9m_5g=19
lvl_11a_12m_5g=19
lvl_11b_11ag_1m_2g4=18
lvl_11b_11ag_2m_2g4=18
lvl_11b_11ag_5m5_2g4=18
lvl_11b_11ag_11m_2g4=18
lvl_11b_11ag_6m_2g4=18
lvl_11b_11ag_9m_2g4=18
lvl_11b_11ag_12m_2g4=18
lvl_11b_11ag_18m_2g4=18
lvl_11b_11ag_24m_2g4=16
lvl_11b_11ag_36m_2g4=16
lvl_11b_11ag_48m_2g4=15
lvl_11b_11ag_54m_2g4=15
lvl_11n_11ac_mcs0_2g4=18
lvl_11n_11ac_mcs1_2g4=18
lvl_11n_11ac_mcs2_2g4=18
lvl_11n_11ac_mcs3_2g4=18
lvl_11n_11ac_mcs4_2g4=16
lvl_11n_11ac_mcs5_2g4=16
lvl_11n_11ac_mcs6_2g4=15
lvl_11n_11ac_mcs7_2g4=15
lvl_11n_11ac_mcs8_2g4=14
lvl_11n_11ac_mcs9_2g4=14
lvl_11ax_mcs0_2g4=18
lvl_11ax_mcs1_2g4=18
lvl_11ax_mcs2_2g4=18
lvl_11ax_mcs3_2g4=18
lvl_11ax_mcs4_2g4=16
lvl_11ax_mcs5_2g4=16
lvl_11ax_mcs6_2g4=15
lvl_11ax_mcs7_2g4=15
lvl_11ax_mcs8_2g4=14
lvl_11ax_mcs9_2g4=14
lvl_11ax_mcs10_2g4=13
lvl_11ax_mcs11_2g4=13
lvl_11a_6m_5g=18
lvl_11a_9m_5g=18
lvl_11a_12m_5g=18
lvl_11a_18m_5g=18
lvl_11a_24m_5g=18
lvl_11a_36m_5g=18
lvl_11a_48m_5g=18
lvl_11a_54m_5g=18
lvl_11n_11ac_mcs0_5g=19
lvl_11n_11ac_mcs1_5g=19
lvl_11n_11ac_mcs2_5g=19
lvl_11a_24m_5g=16
lvl_11a_36m_5g=16
lvl_11a_48m_5g=15
lvl_11a_54m_5g=15
lvl_11n_11ac_mcs0_5g=18
lvl_11n_11ac_mcs1_5g=18
lvl_11n_11ac_mcs2_5g=18
lvl_11n_11ac_mcs3_5g=18
lvl_11n_11ac_mcs4_5g=18
lvl_11n_11ac_mcs5_5g=18
lvl_11n_11ac_mcs6_5g=18
lvl_11n_11ac_mcs7_5g=17
lvl_11n_11ac_mcs8_5g=15
lvl_11n_11ac_mcs9_5g=15
lvl_11ax_mcs0_5g=19
lvl_11ax_mcs1_5g=19
lvl_11ax_mcs2_5g=19
lvl_11n_11ac_mcs4_5g=16
lvl_11n_11ac_mcs5_5g=16
lvl_11n_11ac_mcs6_5g=15
lvl_11n_11ac_mcs7_5g=15
lvl_11n_11ac_mcs8_5g=14
lvl_11n_11ac_mcs9_5g=14
lvl_11ax_mcs0_5g=18
lvl_11ax_mcs1_5g=18
lvl_11ax_mcs2_5g=18
lvl_11ax_mcs3_5g=18
lvl_11ax_mcs4_5g=18
lvl_11ax_mcs5_5g=18
lvl_11ax_mcs6_5g=18
lvl_11ax_mcs7_5g=17
lvl_11ax_mcs8_5g=15
lvl_11ax_mcs9_5g=15
lvl_11ax_mcs10_5g=13
lvl_11ax_mcs11_5g=13
lvl_11ax_mcs4_5g=16
lvl_11ax_mcs5_5g=16
lvl_11ax_mcs6_5g=14
lvl_11ax_mcs7_5g=14
lvl_11ax_mcs8_5g=13
lvl_11ax_mcs9_5g=13
lvl_11ax_mcs10_5g=12
lvl_11ax_mcs11_5g=12
# txpwr_lvl_adj
lvl_adj_enable=0
lvl_adj_2g4_chan_1_4=0
lvl_adj_2g4_chan_5_9=0
lvl_adj_2g4_chan_10_13=0
lvl_adj_5g_chan_42=0
lvl_adj_5g_chan_58=0
lvl_adj_5g_chan_106=0
lvl_adj_5g_chan_122=0
lvl_adj_5g_chan_138=0
lvl_adj_5g_chan_155=0
# txpwr_loss
loss_enable=0
loss_value=2
loss_enable_2g4=0
loss_value_2g4=2
loss_enable_5g=0
loss_value_5g=5
# txpwr_ofst
ofst_enable=0
@@ -0,0 +1,124 @@
# AIC USERCONFIG 2022/0803/1707
# txpwr_lvl
enable=1
lvl_11b_11ag_1m_2g4=20
lvl_11b_11ag_2m_2g4=20
lvl_11b_11ag_5m5_2g4=20
lvl_11b_11ag_11m_2g4=20
lvl_11b_11ag_6m_2g4=20
lvl_11b_11ag_9m_2g4=20
lvl_11b_11ag_12m_2g4=20
lvl_11b_11ag_18m_2g4=20
lvl_11b_11ag_24m_2g4=20
lvl_11b_11ag_36m_2g4=19
lvl_11b_11ag_48m_2g4=18
lvl_11b_11ag_54m_2g4=17
lvl_11n_11ac_mcs0_2g4=20
lvl_11n_11ac_mcs1_2g4=20
lvl_11n_11ac_mcs2_2g4=20
lvl_11n_11ac_mcs3_2g4=20
lvl_11n_11ac_mcs4_2g4=20
lvl_11n_11ac_mcs5_2g4=19
lvl_11n_11ac_mcs6_2g4=18
lvl_11n_11ac_mcs7_2g4=17
lvl_11n_11ac_mcs8_2g4=17
lvl_11n_11ac_mcs9_2g4=16
lvl_11ax_mcs0_2g4=20
lvl_11ax_mcs1_2g4=20
lvl_11ax_mcs2_2g4=20
lvl_11ax_mcs3_2g4=20
lvl_11ax_mcs4_2g4=20
lvl_11ax_mcs5_2g4=19
lvl_11ax_mcs6_2g4=18
lvl_11ax_mcs7_2g4=17
lvl_11ax_mcs8_2g4=17
lvl_11ax_mcs9_2g4=16
lvl_11ax_mcs10_2g4=15
lvl_11ax_mcs11_2g4=15
lvl_11a_6m_5g=19
lvl_11a_9m_5g=19
lvl_11a_12m_5g=19
lvl_11a_18m_5g=18
lvl_11a_24m_5g=18
lvl_11a_36m_5g=18
lvl_11a_48m_5g=18
lvl_11a_54m_5g=18
lvl_11n_11ac_mcs0_5g=19
lvl_11n_11ac_mcs1_5g=19
lvl_11n_11ac_mcs2_5g=19
lvl_11n_11ac_mcs3_5g=18
lvl_11n_11ac_mcs4_5g=18
lvl_11n_11ac_mcs5_5g=18
lvl_11n_11ac_mcs6_5g=18
lvl_11n_11ac_mcs7_5g=17
lvl_11n_11ac_mcs8_5g=15
lvl_11n_11ac_mcs9_5g=15
lvl_11ax_mcs0_5g=19
lvl_11ax_mcs1_5g=19
lvl_11ax_mcs2_5g=19
lvl_11ax_mcs3_5g=18
lvl_11ax_mcs4_5g=18
lvl_11ax_mcs5_5g=18
lvl_11ax_mcs6_5g=18
lvl_11ax_mcs7_5g=17
lvl_11ax_mcs8_5g=15
lvl_11ax_mcs9_5g=15
lvl_11ax_mcs10_5g=13
lvl_11ax_mcs11_5g=13
# txpwr_lvl_adj
lvl_adj_enable=0
lvl_adj_2g4_chan_1_4=0
lvl_adj_2g4_chan_5_9=0
lvl_adj_2g4_chan_10_13=0
lvl_adj_5g_chan_42=0
lvl_adj_5g_chan_58=0
lvl_adj_5g_chan_106=0
lvl_adj_5g_chan_122=0
lvl_adj_5g_chan_138=0
lvl_adj_5g_chan_155=0
# txpwr_loss
loss_enable_2g4=0
loss_value_2g4=2
loss_enable_5g=0
loss_value_5g=5
# txpwr_ofst
ofst_enable=0
ofst_2g4_11b_chan_1_4=0
ofst_2g4_11b_chan_5_9=0
ofst_2g4_11b_chan_10_13=0
ofst_2g4_ofdm_highrate_chan_1_4=0
ofst_2g4_ofdm_highrate_chan_5_9=0
ofst_2g4_ofdm_highrate_chan_10_13=0
ofst_2g4_ofdm_lowrate_chan_1_4=0
ofst_2g4_ofdm_lowrate_chan_5_9=0
ofst_2g4_ofdm_lowrate_chan_10_13=0
ofst_5g_ofdm_lowrate_chan_42=0
ofst_5g_ofdm_lowrate_chan_58=0
ofst_5g_ofdm_lowrate_chan_106=0
ofst_5g_ofdm_lowrate_chan_122=0
ofst_5g_ofdm_lowrate_chan_138=0
ofst_5g_ofdm_lowrate_chan_155=0
ofst_5g_ofdm_highrate_chan_42=0
ofst_5g_ofdm_highrate_chan_58=0
ofst_5g_ofdm_highrate_chan_106=0
ofst_5g_ofdm_highrate_chan_122=0
ofst_5g_ofdm_highrate_chan_138=0
ofst_5g_ofdm_highrate_chan_155=0
ofst_5g_ofdm_midrate_chan_42=0
ofst_5g_ofdm_midrate_chan_58=0
ofst_5g_ofdm_midrate_chan_106=0
ofst_5g_ofdm_midrate_chan_122=0
ofst_5g_ofdm_midrate_chan_138=0
ofst_5g_ofdm_midrate_chan_155=0
# xtal cap
xtal_enable=0
xtal_cap=24
xtal_cap_fine=31
@@ -0,0 +1,124 @@
# AIC USERCONFIG 2022/0803/1707
# txpwr_lvl
enable=1
lvl_11b_11ag_1m_2g4=18
lvl_11b_11ag_2m_2g4=18
lvl_11b_11ag_5m5_2g4=18
lvl_11b_11ag_11m_2g4=18
lvl_11b_11ag_6m_2g4=18
lvl_11b_11ag_9m_2g4=18
lvl_11b_11ag_12m_2g4=18
lvl_11b_11ag_18m_2g4=18
lvl_11b_11ag_24m_2g4=18
lvl_11b_11ag_36m_2g4=18
lvl_11b_11ag_48m_2g4=18
lvl_11b_11ag_54m_2g4=17
lvl_11n_11ac_mcs0_2g4=20
lvl_11n_11ac_mcs1_2g4=20
lvl_11n_11ac_mcs2_2g4=20
lvl_11n_11ac_mcs3_2g4=20
lvl_11n_11ac_mcs4_2g4=20
lvl_11n_11ac_mcs5_2g4=19
lvl_11n_11ac_mcs6_2g4=18
lvl_11n_11ac_mcs7_2g4=18
lvl_11n_11ac_mcs8_2g4=17
lvl_11n_11ac_mcs9_2g4=16
lvl_11ax_mcs0_2g4=20
lvl_11ax_mcs1_2g4=20
lvl_11ax_mcs2_2g4=20
lvl_11ax_mcs3_2g4=20
lvl_11ax_mcs4_2g4=20
lvl_11ax_mcs5_2g4=19
lvl_11ax_mcs6_2g4=18
lvl_11ax_mcs7_2g4=18
lvl_11ax_mcs8_2g4=17
lvl_11ax_mcs9_2g4=17
lvl_11ax_mcs10_2g4=16
lvl_11ax_mcs11_2g4=16
lvl_11a_6m_5g=18
lvl_11a_9m_5g=18
lvl_11a_12m_5g=18
lvl_11a_18m_5g=18
lvl_11a_24m_5g=18
lvl_11a_36m_5g=18
lvl_11a_48m_5g=18
lvl_11a_54m_5g=18
lvl_11n_11ac_mcs0_5g=20
lvl_11n_11ac_mcs1_5g=19
lvl_11n_11ac_mcs2_5g=19
lvl_11n_11ac_mcs3_5g=18
lvl_11n_11ac_mcs4_5g=18
lvl_11n_11ac_mcs5_5g=18
lvl_11n_11ac_mcs6_5g=18
lvl_11n_11ac_mcs7_5g=17
lvl_11n_11ac_mcs8_5g=16
lvl_11n_11ac_mcs9_5g=16
lvl_11ax_mcs0_5g=20
lvl_11ax_mcs1_5g=19
lvl_11ax_mcs2_5g=19
lvl_11ax_mcs3_5g=18
lvl_11ax_mcs4_5g=18
lvl_11ax_mcs5_5g=18
lvl_11ax_mcs6_5g=18
lvl_11ax_mcs7_5g=17
lvl_11ax_mcs8_5g=16
lvl_11ax_mcs9_5g=16
lvl_11ax_mcs10_5g=15
lvl_11ax_mcs11_5g=15
# txpwr_lvl_adj
lvl_adj_enable=0
lvl_adj_2g4_chan_1_4=0
lvl_adj_2g4_chan_5_9=0
lvl_adj_2g4_chan_10_13=0
lvl_adj_5g_chan_42=0
lvl_adj_5g_chan_58=0
lvl_adj_5g_chan_106=0
lvl_adj_5g_chan_122=0
lvl_adj_5g_chan_138=0
lvl_adj_5g_chan_155=0
# txpwr_loss
loss_enable_2g4=0
loss_value_2g4=2
loss_enable_5g=0
loss_value_5g=5
# txpwr_ofst
ofst_enable=0
ofst_2g4_11b_chan_1_4=0
ofst_2g4_11b_chan_5_9=0
ofst_2g4_11b_chan_10_13=0
ofst_2g4_ofdm_highrate_chan_1_4=0
ofst_2g4_ofdm_highrate_chan_5_9=0
ofst_2g4_ofdm_highrate_chan_10_13=0
ofst_2g4_ofdm_lowrate_chan_1_4=0
ofst_2g4_ofdm_lowrate_chan_5_9=0
ofst_2g4_ofdm_lowrate_chan_10_13=0
ofst_5g_ofdm_lowrate_chan_42=0
ofst_5g_ofdm_lowrate_chan_58=0
ofst_5g_ofdm_lowrate_chan_106=0
ofst_5g_ofdm_lowrate_chan_122=0
ofst_5g_ofdm_lowrate_chan_138=0
ofst_5g_ofdm_lowrate_chan_155=0
ofst_5g_ofdm_highrate_chan_42=0
ofst_5g_ofdm_highrate_chan_58=0
ofst_5g_ofdm_highrate_chan_106=0
ofst_5g_ofdm_highrate_chan_122=0
ofst_5g_ofdm_highrate_chan_138=0
ofst_5g_ofdm_highrate_chan_155=0
ofst_5g_ofdm_midrate_chan_42=0
ofst_5g_ofdm_midrate_chan_58=0
ofst_5g_ofdm_midrate_chan_106=0
ofst_5g_ofdm_midrate_chan_122=0
ofst_5g_ofdm_midrate_chan_138=0
ofst_5g_ofdm_midrate_chan_155=0
# xtal cap
xtal_enable=0
xtal_cap=24
xtal_cap_fine=31
@@ -0,0 +1,124 @@
# AIC USERCONFIG 2022/0803/1707
# txpwr_lvl
enable=1
lvl_11b_11ag_1m_2g4=20
lvl_11b_11ag_2m_2g4=20
lvl_11b_11ag_5m5_2g4=20
lvl_11b_11ag_11m_2g4=20
lvl_11b_11ag_6m_2g4=20
lvl_11b_11ag_9m_2g4=20
lvl_11b_11ag_12m_2g4=20
lvl_11b_11ag_18m_2g4=20
lvl_11b_11ag_24m_2g4=20
lvl_11b_11ag_36m_2g4=19
lvl_11b_11ag_48m_2g4=18
lvl_11b_11ag_54m_2g4=17
lvl_11n_11ac_mcs0_2g4=20
lvl_11n_11ac_mcs1_2g4=20
lvl_11n_11ac_mcs2_2g4=20
lvl_11n_11ac_mcs3_2g4=20
lvl_11n_11ac_mcs4_2g4=20
lvl_11n_11ac_mcs5_2g4=19
lvl_11n_11ac_mcs6_2g4=18
lvl_11n_11ac_mcs7_2g4=17
lvl_11n_11ac_mcs8_2g4=17
lvl_11n_11ac_mcs9_2g4=16
lvl_11ax_mcs0_2g4=20
lvl_11ax_mcs1_2g4=20
lvl_11ax_mcs2_2g4=20
lvl_11ax_mcs3_2g4=20
lvl_11ax_mcs4_2g4=20
lvl_11ax_mcs5_2g4=19
lvl_11ax_mcs6_2g4=18
lvl_11ax_mcs7_2g4=17
lvl_11ax_mcs8_2g4=17
lvl_11ax_mcs9_2g4=16
lvl_11ax_mcs10_2g4=15
lvl_11ax_mcs11_2g4=15
lvl_11a_6m_5g=19
lvl_11a_9m_5g=19
lvl_11a_12m_5g=19
lvl_11a_18m_5g=18
lvl_11a_24m_5g=18
lvl_11a_36m_5g=18
lvl_11a_48m_5g=18
lvl_11a_54m_5g=18
lvl_11n_11ac_mcs0_5g=19
lvl_11n_11ac_mcs1_5g=19
lvl_11n_11ac_mcs2_5g=19
lvl_11n_11ac_mcs3_5g=18
lvl_11n_11ac_mcs4_5g=18
lvl_11n_11ac_mcs5_5g=18
lvl_11n_11ac_mcs6_5g=18
lvl_11n_11ac_mcs7_5g=17
lvl_11n_11ac_mcs8_5g=15
lvl_11n_11ac_mcs9_5g=15
lvl_11ax_mcs0_5g=19
lvl_11ax_mcs1_5g=19
lvl_11ax_mcs2_5g=19
lvl_11ax_mcs3_5g=18
lvl_11ax_mcs4_5g=18
lvl_11ax_mcs5_5g=18
lvl_11ax_mcs6_5g=18
lvl_11ax_mcs7_5g=17
lvl_11ax_mcs8_5g=15
lvl_11ax_mcs9_5g=15
lvl_11ax_mcs10_5g=14
lvl_11ax_mcs11_5g=14
# txpwr_lvl_adj
lvl_adj_enable=0
lvl_adj_2g4_chan_1_4=0
lvl_adj_2g4_chan_5_9=0
lvl_adj_2g4_chan_10_13=0
lvl_adj_5g_chan_42=0
lvl_adj_5g_chan_58=0
lvl_adj_5g_chan_106=0
lvl_adj_5g_chan_122=0
lvl_adj_5g_chan_138=0
lvl_adj_5g_chan_155=0
# txpwr_loss
loss_enable_2g4=0
loss_value_2g4=2
loss_enable_5g=0
loss_value_5g=5
# txpwr_ofst
ofst_enable=0
ofst_2g4_11b_chan_1_4=0
ofst_2g4_11b_chan_5_9=0
ofst_2g4_11b_chan_10_13=0
ofst_2g4_ofdm_highrate_chan_1_4=0
ofst_2g4_ofdm_highrate_chan_5_9=0
ofst_2g4_ofdm_highrate_chan_10_13=0
ofst_2g4_ofdm_lowrate_chan_1_4=0
ofst_2g4_ofdm_lowrate_chan_5_9=0
ofst_2g4_ofdm_lowrate_chan_10_13=0
ofst_5g_ofdm_lowrate_chan_42=0
ofst_5g_ofdm_lowrate_chan_58=0
ofst_5g_ofdm_lowrate_chan_106=0
ofst_5g_ofdm_lowrate_chan_122=0
ofst_5g_ofdm_lowrate_chan_138=0
ofst_5g_ofdm_lowrate_chan_155=0
ofst_5g_ofdm_highrate_chan_42=0
ofst_5g_ofdm_highrate_chan_58=0
ofst_5g_ofdm_highrate_chan_106=0
ofst_5g_ofdm_highrate_chan_122=0
ofst_5g_ofdm_highrate_chan_138=0
ofst_5g_ofdm_highrate_chan_155=0
ofst_5g_ofdm_midrate_chan_42=0
ofst_5g_ofdm_midrate_chan_58=0
ofst_5g_ofdm_midrate_chan_106=0
ofst_5g_ofdm_midrate_chan_122=0
ofst_5g_ofdm_midrate_chan_138=0
ofst_5g_ofdm_midrate_chan_155=0
# xtal cap
xtal_enable=0
xtal_cap=24
xtal_cap_fine=31
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+118
View File
@@ -0,0 +1,118 @@
# AIC POWERLIMIT 2024/1108/1900
# Max tx power reference: Linux wireless regulatory database for CRDA
# https://git.kernel.org/pub/scm/linux/kernel/git/sforshee/wireless-regdb.git/tree/db.txt
# If loss_value in aic_userconfig_8800d80.txt is enabled, the power value in this document will be subtracted from loss_value in actual judgment
# Table 1:
## 2.4G, 20M,#5#
## START
## SRRC FCC ETSI JP UNSET
CH01 15 15 15 15 15
CH02 16 16 16 16 16
CH03 16 16 16 16 16
CH04 16 16 16 16 16
CH05 16 16 16 16 16
CH06 16 16 16 16 16
CH07 16 16 16 16 16
CH08 16 16 16 16 16
CH09 16 16 16 16 16
CH10 16 16 16 16 16
CH11 16 16 16 16 16
CH12 12 12 12 12 12
CH13 12 12 12 12 12
CH14 NA NA NA 12 12
## END
# Table 2:
## 2.4G, 40M,#5#
## START
## SRRC FCC ETSI JP UNSET
CH01 NA NA NA NA NA
CH02 NA NA NA NA NA
CH03 16 16 16 16 16
CH04 16 16 16 16 16
CH05 16 16 16 16 16
CH06 16 16 16 16 16
CH07 16 16 16 16 16
CH08 16 16 16 16 16
CH09 16 16 16 16 16
CH10 16 16 16 16 16
CH11 16 16 16 16 16
CH12 NA NA NA NA NA
CH13 NA NA NA NA NA
CH14 NA NA NA NA NA
## END
# Table 3:
## 5G, 20M,#5#
## START
## SRRC FCC ETSI JP UNSET
# 5G Band 1
CH36 15 16 16 16 15
CH40 15 16 16 16 15
CH44 15 16 16 16 15
CH48 15 16 16 16 15
# 5G Band 2
CH52 15 16 16 16 15
CH56 15 16 16 16 15
CH60 15 16 16 16 15
CH64 15 16 16 16 15
# 5G Band 3
CH100 NA 16 16 16 15
CH104 NA 16 16 16 15
CH108 NA 16 16 16 15
CH112 NA 16 16 16 15
CH116 NA 16 16 16 15
CH120 NA 16 16 16 15
CH124 NA 16 16 16 15
CH128 NA 16 16 16 15
CH132 NA 16 16 16 15
CH136 NA 16 16 16 15
CH140 NA 16 16 16 15
CH144 NA NA 16 16 15
# 5G Band 4
CH149 16 16 11 NA 11
CH153 16 16 11 NA 11
CH157 16 16 11 NA 11
CH161 16 16 11 NA 11
CH165 16 16 11 NA 11
## END
# Table 4:
## 5G, 40M,#5#
## START
## SRRC FCC ETSI JP UNSET
# 5G Band 1
CH38 15 16 16 16 15
CH46 15 16 16 16 15
# 5G Band 2
CH54 15 16 16 16 15
CH62 15 16 16 16 15
# 5G Band 3
CH102 NA 16 16 16 15
CH110 NA 16 16 16 15
CH118 NA 16 16 16 15
CH126 NA 16 16 16 15
CH134 NA 16 16 16 15
CH142 NA 16 NA 16 15
# 5G Band 4
CH151 16 16 11 NA 11
CH159 16 16 11 NA 11
## END
# Table 5:
## 5G, 80M,#5#
## START
## SRRC FCC ETSI JP UNSET
# 5G Band 1
CH42 15 16 16 16 15
# 5G Band 2
CH58 15 16 16 16 15
# 5G Band 3
CH106 NA 16 16 16 15
CH122 NA 16 16 16 15
CH138 NA 16 NA NA 15
# 5G Band 4
CH155 16 16 11 NA 11
## END
+118
View File
@@ -0,0 +1,118 @@
# AIC POWERLIMIT 2024/1108/1900
# Max tx power reference: Linux wireless regulatory database for CRDA
# https://git.kernel.org/pub/scm/linux/kernel/git/sforshee/wireless-regdb.git/tree/db.txt
# If loss_value in aic_userconfig_8800d80.txt is enabled, the power value in this document will be subtracted from loss_value in actual judgment
# Table 1:
## 2.4G, 20M,#5#
## START
## SRRC FCC ETSI JP UNSET
CH01 15 15 15 15 15
CH02 16 16 16 16 16
CH03 16 16 16 16 16
CH04 16 16 16 16 16
CH05 16 16 16 16 16
CH06 16 16 16 16 16
CH07 16 16 16 16 16
CH08 16 16 16 16 16
CH09 16 16 16 16 16
CH10 16 16 16 16 16
CH11 16 16 16 16 16
CH12 12 12 12 12 12
CH13 12 12 12 12 12
CH14 NA NA NA 12 12
## END
# Table 2:
## 2.4G, 40M,#5#
## START
## SRRC FCC ETSI JP UNSET
CH01 NA NA NA NA NA
CH02 NA NA NA NA NA
CH03 16 16 16 16 16
CH04 16 16 16 16 16
CH05 16 16 16 16 16
CH06 16 16 16 16 16
CH07 16 16 16 16 16
CH08 16 16 16 16 16
CH09 16 16 16 16 16
CH10 16 16 16 16 16
CH11 16 16 16 16 16
CH12 NA NA NA NA NA
CH13 NA NA NA NA NA
CH14 NA NA NA NA NA
## END
# Table 3:
## 5G, 20M,#5#
## START
## SRRC FCC ETSI JP UNSET
# 5G Band 1
CH36 15 16 16 16 15
CH40 15 16 16 16 15
CH44 15 16 16 16 15
CH48 15 16 16 16 15
# 5G Band 2
CH52 15 16 16 16 15
CH56 15 16 16 16 15
CH60 15 16 16 16 15
CH64 15 16 16 16 15
# 5G Band 3
CH100 NA 16 16 16 15
CH104 NA 16 16 16 15
CH108 NA 16 16 16 15
CH112 NA 16 16 16 15
CH116 NA 16 16 16 15
CH120 NA 16 16 16 15
CH124 NA 16 16 16 15
CH128 NA 16 16 16 15
CH132 NA 16 16 16 15
CH136 NA 16 16 16 15
CH140 NA 16 16 16 15
CH144 NA NA 16 16 15
# 5G Band 4
CH149 16 16 11 NA 11
CH153 16 16 11 NA 11
CH157 16 16 11 NA 11
CH161 16 16 11 NA 11
CH165 16 16 11 NA 11
## END
# Table 4:
## 5G, 40M,#5#
## START
## SRRC FCC ETSI JP UNSET
# 5G Band 1
CH38 15 16 16 16 15
CH46 15 16 16 16 15
# 5G Band 2
CH54 15 16 16 16 15
CH62 15 16 16 16 15
# 5G Band 3
CH102 NA 16 16 16 15
CH110 NA 16 16 16 15
CH118 NA 16 16 16 15
CH126 NA 16 16 16 15
CH134 NA 16 16 16 15
CH142 NA 16 NA 16 15
# 5G Band 4
CH151 16 16 11 NA 11
CH159 16 16 11 NA 11
## END
# Table 5:
## 5G, 80M,#5#
## START
## SRRC FCC ETSI JP UNSET
# 5G Band 1
CH42 15 16 16 16 15
# 5G Band 2
CH58 15 16 16 16 15
# 5G Band 3
CH106 NA 16 16 16 15
CH122 NA 16 16 16 15
CH138 NA 16 NA NA 15
# 5G Band 4
CH155 16 16 11 NA 11
## END
+62
View File
@@ -0,0 +1,62 @@
# AIC USERCONFIG 2022/0803/1707
# txpwr_lvl
enable=1
lvl_11b_11ag_1m_2g4=20
lvl_11b_11ag_2m_2g4=20
lvl_11b_11ag_5m5_2g4=20
lvl_11b_11ag_11m_2g4=20
lvl_11b_11ag_6m_2g4=20
lvl_11b_11ag_9m_2g4=20
lvl_11b_11ag_12m_2g4=20
lvl_11b_11ag_18m_2g4=20
lvl_11b_11ag_24m_2g4=18
lvl_11b_11ag_36m_2g4=18
lvl_11b_11ag_48m_2g4=16
lvl_11b_11ag_54m_2g4=16
lvl_11n_11ac_mcs0_2g4=20
lvl_11n_11ac_mcs1_2g4=20
lvl_11n_11ac_mcs2_2g4=20
lvl_11n_11ac_mcs3_2g4=20
lvl_11n_11ac_mcs4_2g4=18
lvl_11n_11ac_mcs5_2g4=18
lvl_11n_11ac_mcs6_2g4=16
lvl_11n_11ac_mcs7_2g4=16
lvl_11n_11ac_mcs8_2g4=16
lvl_11n_11ac_mcs9_2g4=16
lvl_11ax_mcs0_2g4=20
lvl_11ax_mcs1_2g4=20
lvl_11ax_mcs2_2g4=20
lvl_11ax_mcs3_2g4=20
lvl_11ax_mcs4_2g4=18
lvl_11ax_mcs5_2g4=18
lvl_11ax_mcs6_2g4=16
lvl_11ax_mcs7_2g4=16
lvl_11ax_mcs8_2g4=16
lvl_11ax_mcs9_2g4=16
lvl_11ax_mcs10_2g4=15
lvl_11ax_mcs11_2g4=15
# txpwr_loss
loss_enable_2g4=0
loss_value_2g4=2
loss_enable_5g=0
loss_value_5g=5
# txpwr_ofst
ofst_enable=0
ofst_chan_1_4=0
ofst_chan_5_9=0
ofst_chan_10_13=0
ofst_chan_36_64=0
ofst_chan_100_120=0
ofst_chan_122_140=0
ofst_chan_142_165=0
# xtal cap
xtal_enable=0
xtal_cap=24
xtal_cap_fine=31
+62
View File
@@ -0,0 +1,62 @@
# AIC USERCONFIG 2022/0803/1707
# txpwr_lvl
enable=1
lvl_11b_11ag_1m_2g4=20
lvl_11b_11ag_2m_2g4=20
lvl_11b_11ag_5m5_2g4=20
lvl_11b_11ag_11m_2g4=20
lvl_11b_11ag_6m_2g4=20
lvl_11b_11ag_9m_2g4=20
lvl_11b_11ag_12m_2g4=20
lvl_11b_11ag_18m_2g4=20
lvl_11b_11ag_24m_2g4=18
lvl_11b_11ag_36m_2g4=18
lvl_11b_11ag_48m_2g4=16
lvl_11b_11ag_54m_2g4=16
lvl_11n_11ac_mcs0_2g4=20
lvl_11n_11ac_mcs1_2g4=20
lvl_11n_11ac_mcs2_2g4=20
lvl_11n_11ac_mcs3_2g4=20
lvl_11n_11ac_mcs4_2g4=18
lvl_11n_11ac_mcs5_2g4=18
lvl_11n_11ac_mcs6_2g4=16
lvl_11n_11ac_mcs7_2g4=16
lvl_11n_11ac_mcs8_2g4=16
lvl_11n_11ac_mcs9_2g4=16
lvl_11ax_mcs0_2g4=20
lvl_11ax_mcs1_2g4=20
lvl_11ax_mcs2_2g4=20
lvl_11ax_mcs3_2g4=20
lvl_11ax_mcs4_2g4=18
lvl_11ax_mcs5_2g4=18
lvl_11ax_mcs6_2g4=16
lvl_11ax_mcs7_2g4=16
lvl_11ax_mcs8_2g4=16
lvl_11ax_mcs9_2g4=16
lvl_11ax_mcs10_2g4=15
lvl_11ax_mcs11_2g4=15
# txpwr_loss
loss_enable_2g4=0
loss_value_2g4=2
loss_enable_5g=0
loss_value_5g=5
# txpwr_ofst
ofst_enable=0
ofst_chan_1_4=0
ofst_chan_5_9=0
ofst_chan_10_13=0
ofst_chan_36_64=0
ofst_chan_100_120=0
ofst_chan_122_140=0
ofst_chan_142_165=0
# xtal cap
xtal_enable=0
xtal_cap=24
xtal_cap_fine=31
+62
View File
@@ -0,0 +1,62 @@
# AIC USERCONFIG 2022/0803/1707
# txpwr_lvl
enable=1
lvl_11b_11ag_1m_2g4=19
lvl_11b_11ag_2m_2g4=19
lvl_11b_11ag_5m5_2g4=19
lvl_11b_11ag_11m_2g4=19
lvl_11b_11ag_6m_2g4=19
lvl_11b_11ag_9m_2g4=19
lvl_11b_11ag_12m_2g4=19
lvl_11b_11ag_18m_2g4=19
lvl_11b_11ag_24m_2g4=18
lvl_11b_11ag_36m_2g4=18
lvl_11b_11ag_48m_2g4=16
lvl_11b_11ag_54m_2g4=16
lvl_11n_11ac_mcs0_2g4=18
lvl_11n_11ac_mcs1_2g4=18
lvl_11n_11ac_mcs2_2g4=18
lvl_11n_11ac_mcs3_2g4=18
lvl_11n_11ac_mcs4_2g4=18
lvl_11n_11ac_mcs5_2g4=18
lvl_11n_11ac_mcs6_2g4=18
lvl_11n_11ac_mcs7_2g4=17
lvl_11n_11ac_mcs8_2g4=16
lvl_11n_11ac_mcs9_2g4=16
lvl_11ax_mcs0_2g4=17
lvl_11ax_mcs1_2g4=17
lvl_11ax_mcs2_2g4=17
lvl_11ax_mcs3_2g4=17
lvl_11ax_mcs4_2g4=17
lvl_11ax_mcs5_2g4=17
lvl_11ax_mcs6_2g4=16
lvl_11ax_mcs7_2g4=16
lvl_11ax_mcs8_2g4=16
lvl_11ax_mcs9_2g4=16
lvl_11ax_mcs10_2g4=15
lvl_11ax_mcs11_2g4=15
# txpwr_loss
loss_enable_2g4=0
loss_value_2g4=2
loss_enable_5g=0
loss_value_5g=5
# txpwr_ofst
ofst_enable=0
ofst_chan_1_4=0
ofst_chan_5_9=0
ofst_chan_10_13=0
ofst_chan_36_64=0
ofst_chan_100_120=0
ofst_chan_122_140=0
ofst_chan_142_165=0
# xtal cap
xtal_enable=0
xtal_cap=24
xtal_cap_fine=31
@@ -0,0 +1,62 @@
# AIC USERCONFIG 2022/0803/1707
# txpwr_lvl
enable=1
lvl_11b_11ag_1m_2g4=21
lvl_11b_11ag_2m_2g4=21
lvl_11b_11ag_5m5_2g4=21
lvl_11b_11ag_11m_2g4=21
lvl_11b_11ag_6m_2g4=21
lvl_11b_11ag_9m_2g4=21
lvl_11b_11ag_12m_2g4=21
lvl_11b_11ag_18m_2g4=21
lvl_11b_11ag_24m_2g4=21
lvl_11b_11ag_36m_2g4=20
lvl_11b_11ag_48m_2g4=19
lvl_11b_11ag_54m_2g4=19
lvl_11n_11ac_mcs0_2g4=21
lvl_11n_11ac_mcs1_2g4=21
lvl_11n_11ac_mcs2_2g4=21
lvl_11n_11ac_mcs3_2g4=21
lvl_11n_11ac_mcs4_2g4=21
lvl_11n_11ac_mcs5_2g4=20
lvl_11n_11ac_mcs6_2g4=19
lvl_11n_11ac_mcs7_2g4=19
lvl_11n_11ac_mcs8_2g4=18
lvl_11n_11ac_mcs9_2g4=18
lvl_11ax_mcs0_2g4=21
lvl_11ax_mcs1_2g4=21
lvl_11ax_mcs2_2g4=21
lvl_11ax_mcs3_2g4=21
lvl_11ax_mcs4_2g4=21
lvl_11ax_mcs5_2g4=20
lvl_11ax_mcs6_2g4=19
lvl_11ax_mcs7_2g4=19
lvl_11ax_mcs8_2g4=18
lvl_11ax_mcs9_2g4=18
lvl_11ax_mcs10_2g4=17
lvl_11ax_mcs11_2g4=17
# txpwr_loss
loss_enable_2g4=0
loss_value_2g4=2
loss_enable_5g=0
loss_value_5g=5
# txpwr_ofst
ofst_enable=0
ofst_chan_1_4=0
ofst_chan_5_9=0
ofst_chan_10_13=0
ofst_chan_36_64=0
ofst_chan_100_120=0
ofst_chan_122_140=0
ofst_chan_142_165=0
# xtal cap
xtal_enable=0
xtal_cap=24
xtal_cap_fine=31
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

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