feat: update new aic driver version

This commit is contained in:
Shen Mintao committed 2025-07-24 11:20:36 +08:00
1 parent 99210d657b
commit 3800c225ac
101 files changed
+12814 -4038

No files matched your search

+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
+549 -31
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);
AICWFDBG(LOGINFO, "max_pwr:%d\n", settx_param.max_pwr);
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) {
@@ -1350,11 +1677,13 @@ int handle_private_cmd(struct net_device *net, char *command, u32 cmd_len)
}
#define RWNX_COUNTRY_CODE_LEN 2
#define CMD_SET_COUNTRY "COUNTRY"
#define CMD_SET_VENDOR_EX_IE "SET_VENDOR_EX_IE"
#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_COUNTRY "COUNTRY"
#define CMD_SET_VENDOR_EX_IE "SET_VENDOR_EX_IE"
#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,8 +2060,8 @@ 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__);
ret = -EFAULT;
AICWFDBG(LOGINFO, "%s: failed to copy data to user buffer\n", __FUNCTION__);
ret = -EFAULT;
}
}
else {
@@ -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,61 +3038,81 @@ 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;
}
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
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, cfg_base + 0x14, &cfm);
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, boot_argc_read_addr, &cfm);
if (ret) {
AICWFDBG(LOGERROR, "rf misc ram[0x%x] rd fail: %d\n", cfg_base + 0x14, 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;
}
misc_ram_addr = cfm.memdata;
AICWFDBG(LOGERROR, "misc_ram_addr=%x\n", misc_ram_addr);
// 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 (chip_mcu_id) {
ret = rwnx_send_dbg_mem_read_req(rwnx_hw, flash_size_mem_addr, &cfm);
if (ret) {
AICWFDBG(LOGERROR, "bit_mask[0x%x] rd fail: %d\n", ram_base_addr + i * 4, ret);
AICWFDBG(LOGERROR, "flash size[0x%x] rd fail: %d\n", flash_size_mem_addr, ret);
return ret;
}
bit_mask[i] = cfm.memdata;
}
AICWFDBG(LOGTRACE, "bit_mask:%x,%x,%x,%x\n",bit_mask[0],bit_mask[1],bit_mask[2],bit_mask[3]);
if ((bit_mask[0] == 0) && ((bit_mask[1] & 0xFFF00000) == 0x80000000) &&
(bit_mask[2] == 0) && ((bit_mask[3] & 0xFFFFFF00) == 0x00000000)) {
if (valid_out) {
*valid_out = 1;
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) {
cfg_base = RAM_LMAC_FW_ADDR + 0x0164;
}
// init misc ram
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;
AICWFDBG(LOGERROR, "misc_ram_addr=%x\n", misc_ram_addr);
// 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;
}
bit_mask[i] = cfm.memdata;
}
AICWFDBG(LOGTRACE, "bit_mask:%x,%x,%x,%x\n",bit_mask[0],bit_mask[1],bit_mask[2],bit_mask[3]);
if ((bit_mask[0] == 0) && ((bit_mask[1] & 0xFFF00000) == 0x80000000) &&
(bit_mask[2] == 0) && ((bit_mask[3] & 0xFFFFFF00) == 0x00000000)) {
if (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
+2 -11
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
del_timer_sync(&sdiodev->timer);
} 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
+8 -27
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
del_timer(&ack_m->ack_info[i].timer);
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
del_timer(&ack_info->timer);
}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
del_timer(&ack_info->timer);
} 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
del_timer(&ack_info->timer);
#endif
//send_msg = new_msgbuf;
ack_info->in_send_msg = new_msgbuf;
del_timer(&ack_info->timer);
}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 {
+214 -195
View File
@@ -221,7 +221,7 @@ void aicwf_bus_deinit(struct device *dev)
}else{
AICWFDBG(LOGINFO, "%s g_rwnx_plat->enabled is false\r\n", __func__);
}
#endif
#ifdef AICWF_SDIO_SUPPORT
sdiodev =bus_if->bus_priv.sdio;
@@ -257,7 +257,7 @@ void aicwf_bus_deinit(struct device *dev)
rwnx_cmd_mgr_deinit(&usb->cmd_mgr);
#ifdef CONFIG_TX_TASKLET//AIDEN tasklet
tasklet_kill(&usb->xmit_tasklet);
tasklet_kill(&usb->xmit_tasklet);
#endif
AICWFDBG(LOGINFO, "%s Exit \n", __func__);
@@ -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,55 +371,55 @@ 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 */
u16 pkt_len = 0;
//struct sk_buff *skb_inblock = NULL;
u16 aggr_len = 0, adjust_len = 0;
u8 *data = NULL;
u8_l *msg = NULL;
int ret = 0;
unsigned long flags = 0;
struct sk_buff *skb = NULL; /* Packet for event or data frames */
u16 pkt_len = 0;
//struct sk_buff *skb_inblock = NULL;
u16 aggr_len = 0, adjust_len = 0;
u8 *data = NULL;
u8_l *msg = NULL;
while (1) {
//aicwf_usb_rx_submit_all_urb_(rx_priv->usbdev);
spin_lock_irqsave(&rx_priv->rxqlock, flags);
if(aicwf_is_framequeue_empty(&rx_priv->rxq)) {
usb_info("no more rxdata\n");
spin_unlock_irqrestore(&rx_priv->rxqlock,flags);
break;
}
skb = aicwf_frame_dequeue(&rx_priv->rxq);
spin_unlock_irqrestore(&rx_priv->rxqlock, flags);
if (skb == NULL) {
txrx_err("skb_error\r\n");
break;
}
data = skb->data;
pkt_len = (*skb->data | (*(skb->data + 1) << 8));
//printk("p:%d, s:%d , %x\n", pkt_len, skb->len, data[2]);
while (1) {
//aicwf_usb_rx_submit_all_urb_(rx_priv->usbdev);
spin_lock_irqsave(&rx_priv->rxqlock, flags);
if(aicwf_is_framequeue_empty(&rx_priv->rxq)) {
usb_info("no more rxdata\n");
spin_unlock_irqrestore(&rx_priv->rxqlock,flags);
break;
}
skb = aicwf_frame_dequeue(&rx_priv->rxq);
spin_unlock_irqrestore(&rx_priv->rxqlock, flags);
if (skb == NULL) {
txrx_err("skb_error\r\n");
break;
}
data = skb->data;
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;
}
#endif
if((skb->data[2] & USB_TYPE_CFG) != USB_TYPE_CFG) { // type : data
if((skb->data[2] & USB_TYPE_CFG) != USB_TYPE_CFG) { // type : data
#if 0
aggr_len = pkt_len + RX_HWHRD_LEN;
if (aggr_len & (RX_ALIGNMENT - 1))
adjust_len = roundup(aggr_len, RX_ALIGNMENT);
else
adjust_len = aggr_len;
skb_inblock = __dev_alloc_skb(aggr_len + CCMP_OR_WEP_INFO, GFP_ATOMIC);//8 is for ccmp mic or wep icv
if(skb_inblock == NULL){
txrx_err("no more space! skip!\n");
skb_pull(skb, adjust_len);
continue;
}
skb_put(skb_inblock, aggr_len);
memcpy(skb_inblock->data, data, aggr_len);
#if 0//AIDEN
@@ -425,14 +429,14 @@ int aicwf_tasklet_rxframes(struct aicwf_rx_priv *rx_priv)
rwnx_rxdataind_aicwf(rx_priv->usbdev->rwnx_hw, skb, (void *)rx_priv);
///TODO: here need to add rx data process
//skb_pull(skb, adjust_len);
}
else { // type : config
aggr_len = pkt_len;
if (aggr_len & (RX_ALIGNMENT - 1))
adjust_len = roundup(aggr_len, RX_ALIGNMENT);
else
adjust_len = aggr_len;
}
else { // type : config
aggr_len = pkt_len;
if (aggr_len & (RX_ALIGNMENT - 1))
adjust_len = roundup(aggr_len, RX_ALIGNMENT);
else
adjust_len = aggr_len;
msg = kmalloc(aggr_len+4, GFP_ATOMIC);
if(msg == NULL){
txrx_err("no more space for msg!\n");
@@ -442,22 +446,23 @@ int aicwf_tasklet_rxframes(struct aicwf_rx_priv *rx_priv)
memcpy(msg, data, aggr_len + 4);
if((*(msg + 2) & 0x7f) == USB_TYPE_CFG_CMD_RSP)
rwnx_rx_handle_msg(rx_priv->usbdev->rwnx_hw, (struct ipc_e2a_msg *)(msg + 4));
if((*(msg + 2) & 0x7f) == USB_TYPE_CFG_DATA_CFM)
aicwf_usb_host_tx_cfm_handler(&(rx_priv->usbdev->rwnx_hw->usb_env), (u32 *)(msg + 4));
skb_pull(skb, adjust_len+4);
kfree(msg);
dev_kfree_skb(skb);
}
//dev_kfree_skb(skb);
atomic_dec(&rx_priv->rx_cnt);
}
return ret;
//dev_kfree_skb(skb);
atomic_dec(&rx_priv->rx_cnt);
}
return ret;
}
#endif
extern bool rx_urb_sched;
int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv)
{
#ifdef AICWF_SDIO_SUPPORT
@@ -580,17 +585,17 @@ 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;
}
#endif
if((data[2] & USB_TYPE_CFG) != USB_TYPE_CFG) { // type : data
aggr_len = pkt_len + RX_HWHRD_LEN;
aggr_len = pkt_len + RX_HWHRD_LEN;
skb_inblock = __dev_alloc_skb(aggr_len + CCMP_OR_WEP_INFO, GFP_KERNEL);
if (skb_inblock == NULL) {
txrx_err("no more space! skip\n");
@@ -598,11 +603,12 @@ int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv)
atomic_dec(&rx_priv->rx_cnt);
return -EBADE;
}
skb_put(skb_inblock, aggr_len);
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;
@@ -618,21 +624,26 @@ int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv)
return -EBADE;
}
memcpy(msg, data, aggr_len + 4);
if(((*(msg + 2) & 0x7f) == USB_TYPE_CFG_CMD_RSP) && (rx_priv->usbdev->bus_if->state != (int)USB_DOWN_ST))
rwnx_rx_handle_msg(rx_priv->usbdev->rwnx_hw, (struct ipc_e2a_msg *)(msg + 4));
if((*(msg + 2) & 0x7f) == USB_TYPE_CFG_DATA_CFM)
aicwf_usb_host_tx_cfm_handler(&(rx_priv->usbdev->rwnx_hw->usb_env), (u32 *)(msg + 4));
if ((*(msg + 2) & 0x7f) == USB_TYPE_CFG_PRINT)
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{
@@ -645,7 +656,7 @@ int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv)
}
buffer = rxbuff_dequeue(&rx_priv->rxq);
spin_unlock_irqrestore(&rx_priv->rxqlock, flags);
if (buffer == NULL) {
txrx_err("skb_error\r\n");
ASSERT_ERR(1);
@@ -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;
@@ -669,7 +681,7 @@ int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv)
atomic_dec(&rx_priv->rx_cnt);
continue;
}
skb_put(skb_inblock, pkt_len + RX_HWHRD_LEN);
memcpy(skb_inblock->data, data, pkt_len + RX_HWHRD_LEN);
rwnx_rxdataind_aicwf(rx_priv->usbdev->rwnx_hw, skb_inblock, (void *)rx_priv);
@@ -680,7 +692,7 @@ int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv)
adjust_len = roundup(aggr_len, RX_ALIGNMENT);
else
adjust_len = aggr_len;
msg = kmalloc(aggr_len+4, GFP_KERNEL);
if(msg == NULL){
txrx_err("no more space for msg!\n");
@@ -688,169 +700,176 @@ int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv)
return -EBADE;
}
memcpy(msg, data, aggr_len + 4);
if(((*(msg + 2) & 0x7f) == USB_TYPE_CFG_CMD_RSP) && (rx_priv->usbdev->bus_if->state != (int)USB_DOWN_ST))
rwnx_rx_handle_msg(rx_priv->usbdev->rwnx_hw, (struct ipc_e2a_msg *)(msg + 4));
if((*(msg + 2) & 0x7f) == USB_TYPE_CFG_DATA_CFM)
aicwf_usb_host_tx_cfm_handler(&(rx_priv->usbdev->rwnx_hw->usb_env), (u32 *)(msg + 4));
if ((*(msg + 2) & 0x7f) == USB_TYPE_CFG_PRINT)
rwnx_rx_handle_print(rx_priv->usbdev->rwnx_hw, msg + 4, aggr_len);
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
if(aicwf_usb_rx_aggr){
while (1) {
spin_lock_irqsave(&rx_priv->rxqlock, flags);
if(aicwf_is_framequeue_empty(&rx_priv->rxq)) {
usb_info("no more rxdata\n");
spin_unlock_irqrestore(&rx_priv->rxqlock,flags);
break;
}
skb = aicwf_frame_dequeue(&rx_priv->rxq);
spin_unlock_irqrestore(&rx_priv->rxqlock, flags);
if(aicwf_usb_rx_aggr){
while (1) {
spin_lock_irqsave(&rx_priv->rxqlock, flags);
if(aicwf_is_framequeue_empty(&rx_priv->rxq)) {
usb_info("no more rxdata\n");
spin_unlock_irqrestore(&rx_priv->rxqlock,flags);
break;
}
skb = aicwf_frame_dequeue(&rx_priv->rxq);
spin_unlock_irqrestore(&rx_priv->rxqlock, flags);
if (skb == NULL) {
txrx_err("skb_error\r\n");
ASSERT_ERR(1);
break;
}
while(aicwf_another_ptk(skb)) {
cnt++;
if (cnt > 30) {
//printk("%s err, break %d\n", __func__, cnt);
//break;
}
data = skb->data;
pkt_len = (*skb->data | (*(skb->data + 1) << 8));
//printk("p:%d, s:%d , %x\n", pkt_len, skb->len, data[2]);
if (skb == NULL) {
txrx_err("skb_error\r\n");
ASSERT_ERR(1);
break;
}
while(aicwf_another_ptk(skb)) {
cnt++;
if (cnt > 30) {
//printk("%s err, break %d\n", __func__, cnt);
//break;
}
data = skb->data;
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
aggr_len = pkt_len + RX_HWHRD_LEN;
adjust_len = aggr_len;
skb_inblock = __dev_alloc_skb(aggr_len + CCMP_OR_WEP_INFO, GFP_KERNEL);//8 is for ccmp mic or wep icv
if(skb_inblock == NULL){
txrx_err("no more space! skip!\n");
skb_pull(skb, adjust_len);
continue;
}
if((skb->data[2] & USB_TYPE_CFG) != USB_TYPE_CFG) { // type : data
aggr_len = pkt_len + RX_HWHRD_LEN;
adjust_len = aggr_len;
skb_inblock = __dev_alloc_skb(aggr_len + CCMP_OR_WEP_INFO, GFP_KERNEL);//8 is for ccmp mic or wep icv
if(skb_inblock == NULL){
txrx_err("no more space! skip!\n");
skb_pull(skb, adjust_len);
continue;
}
skb_put(skb_inblock, aggr_len);
memcpy(skb_inblock->data, data, aggr_len);
rwnx_rxdataind_aicwf(rx_priv->usbdev->rwnx_hw, skb_inblock, (void *)rx_priv);
skb_put(skb_inblock, aggr_len);
memcpy(skb_inblock->data, data, aggr_len);
rwnx_rxdataind_aicwf(rx_priv->usbdev->rwnx_hw, skb_inblock, (void *)rx_priv);
///TODO: here need to add rx data process
///TODO: here need to add rx data process
skb_pull(skb, adjust_len);
skb_pull(skb, adjust_len);
}
else { // type : config
aggr_len = pkt_len;
if (aggr_len & (RX_ALIGNMENT - 1))
adjust_len = roundup(aggr_len, RX_ALIGNMENT);
else
adjust_len = aggr_len;
}
else { // type : config
aggr_len = pkt_len;
if (aggr_len & (RX_ALIGNMENT - 1))
adjust_len = roundup(aggr_len, RX_ALIGNMENT);
else
adjust_len = aggr_len;
msg = kmalloc(aggr_len+4, GFP_KERNEL);//hdr(4)+config(aggrlen)
if(msg == NULL){
txrx_err("no more space for msg!\n");
aicwf_dev_skb_free(skb);
return -EBADE;
}
memcpy(msg, data, aggr_len + 4);
msg = kmalloc(aggr_len+4, GFP_KERNEL);//hdr(4)+config(aggrlen)
if(msg == NULL){
txrx_err("no more space for msg!\n");
aicwf_dev_skb_free(skb);
return -EBADE;
}
memcpy(msg, data, aggr_len + 4);
if(((*(msg + 2) & 0x7f) == USB_TYPE_CFG_CMD_RSP) && (rx_priv->usbdev->bus_if->state != (int)USB_DOWN_ST))
rwnx_rx_handle_msg(rx_priv->usbdev->rwnx_hw, (struct ipc_e2a_msg *)(msg + 4));
if(((*(msg + 2) & 0x7f) == USB_TYPE_CFG_CMD_RSP) && (rx_priv->usbdev->bus_if->state != (int)USB_DOWN_ST))
rwnx_rx_handle_msg(rx_priv->usbdev->rwnx_hw, (struct ipc_e2a_msg *)(msg + 4));
if((*(msg + 2) & 0x7f) == USB_TYPE_CFG_DATA_CFM)
aicwf_usb_host_tx_cfm_handler(&(rx_priv->usbdev->rwnx_hw->usb_env), (u32 *)(msg + 4));
if((*(msg + 2) & 0x7f) == USB_TYPE_CFG_DATA_CFM)
aicwf_usb_host_tx_cfm_handler(&(rx_priv->usbdev->rwnx_hw->usb_env), (u32 *)(msg + 4));
if ((*(msg + 2) & 0x7f) == USB_TYPE_CFG_PRINT)
rwnx_rx_handle_print(rx_priv->usbdev->rwnx_hw, msg + 4, aggr_len);
if ((*(msg + 2) & 0x7f) == USB_TYPE_CFG_PRINT)
rwnx_rx_handle_print(rx_priv->usbdev->rwnx_hw, msg + 4, aggr_len);
skb_pull(skb, adjust_len+4);
kfree(msg);
skb_pull(skb, adjust_len+4);
kfree(msg);
}
}
dev_kfree_skb(skb);
atomic_dec(&rx_priv->rx_cnt);
}
}else{
while (1) {
spin_lock_irqsave(&rx_priv->rxqlock, flags);
if(aicwf_is_framequeue_empty(&rx_priv->rxq)) {
usb_info("no more rxdata\n");
spin_unlock_irqrestore(&rx_priv->rxqlock,flags);
break;
}
skb = aicwf_frame_dequeue(&rx_priv->rxq);
spin_unlock_irqrestore(&rx_priv->rxqlock, flags);
}
}
dev_kfree_skb(skb);
atomic_dec(&rx_priv->rx_cnt);
}
}else{
while (1) {
spin_lock_irqsave(&rx_priv->rxqlock, flags);
if(aicwf_is_framequeue_empty(&rx_priv->rxq)) {
usb_info("no more rxdata\n");
spin_unlock_irqrestore(&rx_priv->rxqlock,flags);
break;
}
skb = aicwf_frame_dequeue(&rx_priv->rxq);
spin_unlock_irqrestore(&rx_priv->rxqlock, flags);
if (skb == NULL) {
txrx_err("skb_error\r\n");
ASSERT_ERR(1);
break;
}
data = skb->data;
pkt_len = (*skb->data | (*(skb->data + 1) << 8));
//printk("p:%d, s:%d , %x\n", pkt_len, skb->len, data[2]);
if (skb == NULL) {
txrx_err("skb_error\r\n");
ASSERT_ERR(1);
break;
}
data = skb->data;
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;
}
#endif
if((skb->data[2] & USB_TYPE_CFG) != USB_TYPE_CFG) { // type : data
rwnx_rxdataind_aicwf(rx_priv->usbdev->rwnx_hw, skb, (void *)rx_priv);
}
else { // type : config
aggr_len = pkt_len;
if (aggr_len & (RX_ALIGNMENT - 1))
adjust_len = roundup(aggr_len, RX_ALIGNMENT);
else
adjust_len = aggr_len;
if((skb->data[2] & USB_TYPE_CFG) != USB_TYPE_CFG) { // type : data
rwnx_rxdataind_aicwf(rx_priv->usbdev->rwnx_hw, skb, (void *)rx_priv);
}
else { // type : config
aggr_len = pkt_len;
if (aggr_len & (RX_ALIGNMENT - 1))
adjust_len = roundup(aggr_len, RX_ALIGNMENT);
else
adjust_len = aggr_len;
msg = kmalloc(aggr_len+4, GFP_KERNEL);
if(msg == NULL){
txrx_err("no more space for msg!\n");
aicwf_dev_skb_free(skb);
return -EBADE;
}
memcpy(msg, data, aggr_len + 4);
msg = kmalloc(aggr_len+4, GFP_KERNEL);
if(msg == NULL){
txrx_err("no more space for msg!\n");
aicwf_dev_skb_free(skb);
return -EBADE;
}
memcpy(msg, data, aggr_len + 4);
if(((*(msg + 2) & 0x7f) == USB_TYPE_CFG_CMD_RSP) && (rx_priv->usbdev->bus_if->state != (int)USB_DOWN_ST))
rwnx_rx_handle_msg(rx_priv->usbdev->rwnx_hw, (struct ipc_e2a_msg *)(msg + 4));
if(((*(msg + 2) & 0x7f) == USB_TYPE_CFG_CMD_RSP) && (rx_priv->usbdev->bus_if->state != (int)USB_DOWN_ST))
rwnx_rx_handle_msg(rx_priv->usbdev->rwnx_hw, (struct ipc_e2a_msg *)(msg + 4));
if((*(msg + 2) & 0x7f) == USB_TYPE_CFG_DATA_CFM)
aicwf_usb_host_tx_cfm_handler(&(rx_priv->usbdev->rwnx_hw->usb_env), (u32 *)(msg + 4));
if((*(msg + 2) & 0x7f) == USB_TYPE_CFG_DATA_CFM)
aicwf_usb_host_tx_cfm_handler(&(rx_priv->usbdev->rwnx_hw->usb_env), (u32 *)(msg + 4));
if ((*(msg + 2) & 0x7f) == USB_TYPE_CFG_PRINT)
rwnx_rx_handle_print(rx_priv->usbdev->rwnx_hw, msg + 4, aggr_len);
if ((*(msg + 2) & 0x7f) == USB_TYPE_CFG_PRINT)
rwnx_rx_handle_print(rx_priv->usbdev->rwnx_hw, msg + 4, aggr_len);
skb_pull(skb, adjust_len+4);
kfree(msg);
dev_kfree_skb(skb);
}
atomic_dec(&rx_priv->rx_cnt);
}
}
skb_pull(skb, adjust_len+4);
kfree(msg);
dev_kfree_skb(skb);
}
atomic_dec(&rx_priv->rx_cnt);
}
}
#endif
return ret;
@@ -887,7 +906,7 @@ int aicwf_process_msg_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]);
#if 0 //amsdu > 1600
if (pkt_len > 1600) {
if (pkt_len > 1600) {
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++;
}
+17 -8
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
@@ -178,13 +179,21 @@ struct reord_ctrl_info {
};
struct recv_msdu {
struct sk_buff *pkt;
u8 tid;
u8 forward;
u16 seq_num;
uint len;
u8 *rx_data;
//for pending rx reorder list
struct sk_buff *pkt;
u8 tid;
u8 forward;
u16 seq_num;
//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
struct list_head rxframe_list;
+262 -179
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)
{
@@ -154,23 +157,23 @@ static void aicwf_usb_msg_rx_buf_put(struct aic_usb_dev *usb_dev, struct aicwf_u
void rwnx_stop_sta_all_queues(struct rwnx_sta *sta, struct rwnx_hw *rwnx_hw)
{
u8 tid;
struct rwnx_txq *txq;
for(tid=0; tid<8; tid++) {
txq = rwnx_txq_sta_get(sta, tid, rwnx_hw);
netif_stop_subqueue(txq->ndev, txq->ndev_idx);
}
}
u8 tid;
struct rwnx_txq *txq;
for(tid=0; tid<8; tid++) {
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)
{
u8 tid;
struct rwnx_txq *txq;
for(tid=0; tid<8; tid++) {
txq = rwnx_txq_sta_get(sta, tid, rwnx_hw);
netif_wake_subqueue(txq->ndev, txq->ndev_idx);
}
}
u8 tid;
struct rwnx_txq *txq;
for(tid=0; tid<8; tid++) {
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,68 +260,68 @@ 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;
struct rx_buff *rx_buff = NULL;
unsigned long flags = 0;
rx_buff = usb_buf->rx_buff;
usb_buf->rx_buff = NULL;
atomic_dec(&rx_urb_cnt);
if(atomic_read(&rx_urb_cnt) < 10){
AICWFDBG(LOGDEBUG, "%s %d \r\n", __func__, atomic_read(&rx_urb_cnt));
//printk("%s %d \r\n", __func__, atomic_read(&rx_urb_cnt));
}
{
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;
struct rx_buff *rx_buff = NULL;
unsigned long flags = 0;
rx_buff = usb_buf->rx_buff;
usb_buf->rx_buff = NULL;
atomic_dec(&rx_urb_cnt);
if(atomic_read(&rx_urb_cnt) < 10){
AICWFDBG(LOGDEBUG, "%s %d \r\n", __func__, atomic_read(&rx_urb_cnt));
//printk("%s %d \r\n", __func__, atomic_read(&rx_urb_cnt));
}
if(!usb_dev->rwnx_hw){
aicwf_prealloc_rxbuff_free(rx_buff, &rx_priv->rxbuff_lock);
aicwf_usb_rx_buf_put(usb_dev, usb_buf);
AICWFDBG(LOGERROR, "usb_dev->rwnx_hw is not ready \r\n");
return;
}
if (urb->actual_length > urb->transfer_buffer_length) {
aicwf_prealloc_rxbuff_free(rx_buff, &rx_priv->rxbuff_lock);
aicwf_usb_rx_buf_put(usb_dev, usb_buf);
aicwf_usb_rx_submit_all_urb_(usb_dev);
return;
}
if (urb->status != 0 || !urb->actual_length) {
aicwf_prealloc_rxbuff_free(rx_buff, &rx_priv->rxbuff_lock);
aicwf_usb_rx_buf_put(usb_dev, usb_buf);
if(urb->status < 0){
AICWFDBG(LOGDEBUG, "%s urb->status:%d \r\n", __func__, urb->status);
if(g_rwnx_plat->wait_disconnect_cb == false){
g_rwnx_plat->wait_disconnect_cb = true;
if(atomic_read(&aicwf_deinit_atomic) > 0){
atomic_set(&aicwf_deinit_atomic, 0);
down(&aicwf_deinit_sem);
AICWFDBG(LOGINFO, "%s need to wait for disconnect callback \r\n", __func__);
}else{
g_rwnx_plat->wait_disconnect_cb = false;
}
}
if(!usb_dev->rwnx_hw){
aicwf_prealloc_rxbuff_free(rx_buff, &rx_priv->rxbuff_lock);
aicwf_usb_rx_buf_put(usb_dev, usb_buf);
AICWFDBG(LOGERROR, "usb_dev->rwnx_hw is not ready \r\n");
return;
}
if (urb->actual_length > urb->transfer_buffer_length) {
aicwf_prealloc_rxbuff_free(rx_buff, &rx_priv->rxbuff_lock);
aicwf_usb_rx_buf_put(usb_dev, usb_buf);
}else{
//schedule_work(&usb_dev->rx_urb_work);
aicwf_usb_rx_submit_all_urb_(usb_dev);
return;
}
if (urb->status != 0 || !urb->actual_length) {
aicwf_prealloc_rxbuff_free(rx_buff, &rx_priv->rxbuff_lock);
aicwf_usb_rx_buf_put(usb_dev, usb_buf);
if(urb->status < 0){
AICWFDBG(LOGDEBUG, "%s urb->status:%d \r\n", __func__, urb->status);
if(g_rwnx_plat->wait_disconnect_cb == false){
g_rwnx_plat->wait_disconnect_cb = true;
if(atomic_read(&aicwf_deinit_atomic) > 0){
atomic_set(&aicwf_deinit_atomic, 0);
down(&aicwf_deinit_sem);
AICWFDBG(LOGINFO, "%s need to wait for disconnect callback \r\n", __func__);
}else{
g_rwnx_plat->wait_disconnect_cb = false;
}
}
return;
}else{
//schedule_work(&usb_dev->rx_urb_work);
aicwf_usb_rx_submit_all_urb_(usb_dev);
return;
}
}
}
if (usb_dev->state == USB_UP_ST) {
spin_lock_irqsave(&rx_priv->rxqlock, flags);
if (aicwf_usb_rx_aggr) {
rx_buff->len = urb->actual_length;
//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);
usb_err("rx_priv->rxq is over flow!!!\n");
@@ -328,7 +332,7 @@ static void aicwf_usb_rx_complete(struct urb *urb)
}
spin_unlock_irqrestore(&rx_priv->rxqlock, flags);
atomic_inc(&rx_priv->rx_cnt);
if(atomic_read(&rx_priv->rx_cnt) == 1){
complete(&rx_priv->usbdev->bus_if->busrx_trgg);
}
@@ -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);
@@ -751,9 +755,10 @@ static int aicwf_usb_submit_rx_urb(struct aic_usb_dev *usb_dev,
rx_buff = aicwf_prealloc_rxbuff_alloc(&usb_dev->rx_priv->rxbuff_lock);
if (rx_buff == NULL) {
AICWFDBG(LOGERROR, "failed to alloc rxbuff\r\n");
aicwf_usb_rx_buf_put(usb_dev, usb_buf);
return -1;
}
aicwf_usb_rx_buf_put(usb_dev, usb_buf);
rx_urb_sched = true;
return -1;
}
rx_buff->len = 0;
rx_buff->start = rx_buff->data;
rx_buff->read = rx_buff->start;
@@ -801,9 +806,9 @@ 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*/);
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;
@@ -836,10 +841,10 @@ static int aicwf_usb_submit_rx_urb(struct aic_usb_dev *usb_dev,
aicwf_usb_rx_buf_put(usb_dev, usb_buf);
msleep(100);
return -1;
return -1;
}else{
atomic_inc(&rx_urb_cnt);
}
atomic_inc(&rx_urb_cnt);
}
return 0;
}
#endif
@@ -857,7 +862,7 @@ static void aicwf_usb_rx_submit_all_urb(struct aic_usb_dev *usb_dev)
while((usb_buf = aicwf_usb_rx_buf_get(usb_dev)) != NULL) {
if (aicwf_usb_submit_rx_urb(usb_dev, usb_buf)) {
AICWFDBG(LOGERROR, "sub rx fail\n");
return;
return;
#if 0
AICWFDBG(LOGERROR, "usb rx refill fail\n");
if (usb_dev->state != USB_UP_ST)
@@ -1330,11 +1335,11 @@ int usb_busrx_thread(void *data)
#ifdef CONFIG_TXRX_THREAD_PRIO
if (busrx_thread_prio > 0) {
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0))
sched_set_fifo_low(current);
sched_set_fifo_low(current);
#else
struct sched_param param;
param.sched_priority = (busrx_thread_prio < MAX_RT_PRIO)?busrx_thread_prio:(MAX_RT_PRIO-1);
sched_setscheduler(current, SCHED_FIFO, &param);
struct sched_param param;
param.sched_priority = (busrx_thread_prio < MAX_RT_PRIO)?busrx_thread_prio:(MAX_RT_PRIO-1);
sched_setscheduler(current, SCHED_FIFO, &param);
#endif
}
#endif
@@ -1373,19 +1378,19 @@ int usb_msg_busrx_thread(void *data)
struct aicwf_bus *bus_if = rx_priv->usbdev->bus_if;
#ifdef CONFIG_TXRX_THREAD_PRIO
if (busrx_thread_prio > 0) {
if (busrx_thread_prio > 0) {
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0))
sched_set_fifo_low(current);
sched_set_fifo_low(current);
#else
struct sched_param param;
param.sched_priority = (busrx_thread_prio < MAX_RT_PRIO)?busrx_thread_prio:(MAX_RT_PRIO-1);
sched_setscheduler(current, SCHED_FIFO, &param);
struct sched_param param;
param.sched_priority = (busrx_thread_prio < MAX_RT_PRIO)?busrx_thread_prio:(MAX_RT_PRIO-1);
sched_setscheduler(current, SCHED_FIFO, &param);
#endif
}
}
#endif
AICWFDBG(LOGINFO, "%s the policy of current thread is:%d\n", __func__, current->policy);
AICWFDBG(LOGINFO, "%s the rt_priority of current thread is:%d\n", __func__, current->rt_priority);
AICWFDBG(LOGINFO, "%s the current pid is:%d\n", __func__, current->pid);
AICWFDBG(LOGINFO, "%s the policy of current thread is:%d\n", __func__, current->policy);
AICWFDBG(LOGINFO, "%s the rt_priority of current thread is:%d\n", __func__, current->rt_priority);
AICWFDBG(LOGINFO, "%s the current pid is:%d\n", __func__, current->pid);
@@ -1504,7 +1509,7 @@ static void aicwf_usb_free_urb(struct list_head *q, spinlock_t *qlock)
spin_lock_irqsave(qlock, flags);
list_for_each_entry_safe(usb_buf, tmp, q, list) {
spin_unlock_irqrestore(qlock, flags);
spin_unlock_irqrestore(qlock, flags);
if (!usb_buf->urb) {
usb_err("bad usb_buf\n");
spin_lock_irqsave(qlock, flags);
@@ -1605,7 +1610,7 @@ err:
static int aicwf_usb_alloc_msg_rx_urb(struct aic_usb_dev *usb_dev)
{
int i;
AICWFDBG(LOGINFO, "%s AICWF_USB_MSG_RX_URBS:%d \r\n", __func__, AICWF_USB_MSG_RX_URBS);
for (i = 0; i < AICWF_USB_MSG_RX_URBS; i++) {
@@ -1728,7 +1733,8 @@ 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
int align;
u8 *buf_align;
int align;
#endif
if (usb_dev->state != USB_UP_ST) {
@@ -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{
@@ -1933,7 +1956,7 @@ static void aicwf_usb_cancel_all_urbs_(struct aic_usb_dev *usb_dev)
usb_kill_anchored_urbs(&usb_dev->rx_submitted);
#ifdef CONFIG_USB_MSG_IN_EP
if(usb_dev->msg_in_pipe){
usb_kill_anchored_urbs(&usb_dev->msg_rx_submitted);
usb_kill_anchored_urbs(&usb_dev->msg_rx_submitted);
}
#endif
}
@@ -1956,8 +1979,8 @@ static void aicwf_usb_bus_stop(struct device *dev)
return;
if(g_rwnx_plat && g_rwnx_plat->wait_disconnect_cb == true){
atomic_set(&aicwf_deinit_atomic, 1);
up(&aicwf_deinit_sem);
atomic_set(&aicwf_deinit_atomic, 1);
up(&aicwf_deinit_sem);
}
aicwf_usb_state_change(usb_dev, USB_DOWN_ST);
//aicwf_usb_cancel_all_urbs(usb_dev);//AIDEN
@@ -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;
}
@@ -2193,17 +2221,33 @@ static int aicwf_parse_usb(struct aic_usb_dev *usb_dev, struct usb_interface *in
}
#endif
#ifdef CONFIG_USB_MSG_IN_EP
if(usb_dev->chipid != PRODUCT_ID_AIC8801){
if (usb_dev->msg_in_pipe == 0) {
AICWFDBG(LOGINFO, "No RX Msg (in) Bulk EP found\n");
}
if(usb_dev->chipid != PRODUCT_ID_AIC8801){
if (usb_dev->msg_in_pipe == 0) {
AICWFDBG(LOGINFO, "No RX Msg (in) Bulk EP found\n");
}
}
#endif
if (usb->speed == USB_SPEED_HIGH){
AICWFDBG(LOGINFO, "Aic high speed USB device detected\n");
}else{
AICWFDBG(LOGINFO, "Aic full speed USB device detected\n");
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");
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,11 +2347,42 @@ 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__);
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;
@@ -2326,7 +2403,7 @@ static int aicwf_usb_probe(struct usb_interface *intf, const struct usb_device_i
#endif
usb_dev = kzalloc(sizeof(struct aic_usb_dev), GFP_ATOMIC);
AICWFDBG(LOGDEBUG, "%s usb_dev:%d usb_tx_buf:%d usb_rx_buf:%d\r\n",
__func__,
(int)sizeof(struct aic_usb_dev),
@@ -2361,7 +2438,7 @@ static int aicwf_usb_probe(struct usb_interface *intf, const struct usb_device_i
memset(usb_dev->usb_tx_buf,
0,
(int)(sizeof(struct aicwf_usb_buf) * AICWF_USB_TX_URBS));
memset(usb_dev->usb_rx_buf,
0,
(int)(sizeof(struct aicwf_usb_buf) * AICWF_USB_RX_URBS));
@@ -2370,9 +2447,12 @@ static int aicwf_usb_probe(struct usb_interface *intf, const struct usb_device_i
usb_dev->udev = usb;
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) {
AICWFDBG(LOGERROR, "%s pid:0x%04X vid:0x%04X unsupport\n",
__func__, id->idVendor, id->idProduct);
@@ -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
@@ -2468,7 +2551,7 @@ static void aicwf_usb_disconnect(struct usb_interface *intf)
{
struct aic_usb_dev *usb_dev =
(struct aic_usb_dev *) usb_get_intfdata(intf);
AICWFDBG(LOGINFO, "%s Enter\r\n", __func__);
AICWFDBG(LOGINFO, "%s Enter\r\n", __func__);
if(g_rwnx_plat->wait_disconnect_cb == false){
atomic_set(&aicwf_deinit_atomic, 0);
@@ -2505,59 +2588,53 @@ static void aicwf_usb_disconnect(struct usb_interface *intf)
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;
#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_device_detach(rwnx_vif->ndev);
}
#endif
aicwf_usb_state_change(usb_dev, USB_SLEEP_ST);
(struct aic_usb_dev *) usb_get_intfdata(intf);
struct rwnx_vif *rwnx_vif, *tmp;
AICWFDBG(LOGINFO, "%s enter\r\n", __func__);
#ifdef CONFIG_WOWLAN
rwnx_send_dummy_reboot(usb_dev->rwnx_hw);
#endif
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);
}
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__);
(struct aic_usb_dev *) usb_get_intfdata(intf);
struct rwnx_vif *rwnx_vif, *tmp;
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);
}
#ifdef CONFIG_GPIO_WAKEUP
// spin_lock_irqsave(&irq_lock, irqflags);
// rwnx_disable_hostwake_irq();
// spin_unlock_irqrestore(&irq_lock, irqflags);
atomic_dec(&irq_count);
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_device_attach(rwnx_vif->ndev);
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);
}
#endif
if (usb_dev->state == USB_UP_ST)
return 0;
aicwf_bus_start(usb_dev->bus_if);
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
{}
};
@@ -2619,7 +2702,7 @@ void aicwf_usb_exit(void)
{
int retry = 5;
AICWFDBG(LOGINFO, "%s Enter\r\n", __func__);
AICWFDBG(LOGDEBUG, "%s in_interrupt:%d in_softirq:%d in_atomic:%d\r\n", __func__, (int)in_interrupt(), (int)in_softirq(), (int)in_atomic());
do{
@@ -2631,7 +2714,7 @@ void aicwf_usb_exit(void)
break;
}
}while(atomic_read(&aicwf_deinit_atomic) == 0);
atomic_set(&aicwf_deinit_atomic, 0);
if(down_timeout(&aicwf_deinit_sem, msecs_to_jiffies(SEM_TIMOUT)) != 0){
AICWFDBG(LOGERROR, "%s semaphore waiting timeout\r\n", __func__);
+33 -22
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_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_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_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
+274 -12
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;
@@ -1304,7 +1349,13 @@ struct mm_get_sta_info_cfm
{
u32_l rate_info;
u32_l txfailed;
u8 rssi;
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,
@@ -2005,7 +2133,8 @@ struct mm_set_channel_access_req
u8_l long_nav_en;
u8_l cfe_en;
u8_l rc_retry_cnt[3];
s8_l ccademod_th;
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
+64 -7
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
spin_lock_bh(&cmd_mgr->lock);
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,8 +389,16 @@ void cmd_mgr_task_process(struct work_struct *work)
cmd_complete(cmd_mgr, next);
}
spin_unlock_bh(&cmd_mgr->lock);
} else
rwnx_cmd_free(next);//kfree(next);AIDEN
} 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_ */
+128 -41
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)
rwnx_hw->vht_cap_5G.cap |= IEEE80211_VHT_CAP_TXSTBC;
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)
band_5GHz->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
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)
band_2GHz->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
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,8 +1225,14 @@ 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)
{
he_cap->he_cap_elem.phy_cap_info[0] |=
@@ -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,8 +1372,14 @@ 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)
{
he_cap->he_cap_elem.phy_cap_info[0] |=
@@ -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,8 +1500,14 @@ 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)
{
he_cap->he_cap_elem.phy_cap_info[0] |=
@@ -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));
@@ -1703,21 +1778,33 @@ int rwnx_handle_dynparams(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy)
#endif
//check he_mcs max
if(rwnx_hw->usbdev->chipid != PRODUCT_ID_AIC8800D81 &&
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_ */
+116 -100
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();
get_monotonic_boottime(&ts);
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(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;
}
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;
}
}
} 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;
}
netif_tx_start_all_queues(dev);
netif_carrier_on(dev);
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);
+136 -18
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,
(s16)freq + (2 * p->freq),
p->rep, (p->len * 2), now)) {
#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