mirror of
https://github.com/shenmintao/aic8800d80.git
synced 2026-09-26 17:44:16 +00:00
init: add source codes from tenda
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="5721", SYMLINK+="aicudisk", RUN+="/usr/bin/eject /dev/%k"
|
||||
KERNEL=="sd*", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="5723", SYMLINK+="tendaudisk", RUN+="/usr/bin/eject /dev/%k"
|
||||
@@ -0,0 +1,12 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := bt_test
|
||||
LOCAL_SRC_FILES := bt_test.c
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := wifi_test
|
||||
LOCAL_SRC_FILES := wifi_test.c
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
#CROSS_COMPILE := /opt/toolchains/mips-gcc540-glibc222-64bit-r3.3.0/bin/mips-linux-gnu-
|
||||
|
||||
LDFLAGS := -lpthread
|
||||
|
||||
default: all
|
||||
|
||||
all: wifi_test bt_test
|
||||
|
||||
wifi_test: wifi_test.o
|
||||
$(CROSS_COMPILE)gcc $+ -o $@
|
||||
|
||||
bt_test: bt_test.o
|
||||
$(CROSS_COMPILE)gcc $+ $(LDFLAGS) -o $@
|
||||
|
||||
%.o: %.c
|
||||
$(CROSS_COMPILE)gcc -c $+ -o $@
|
||||
|
||||
clean:
|
||||
rm *.o wifi_test bt_test
|
||||
|
||||
install:
|
||||
sudo cp wifi_test /sbin
|
||||
sudo cp bt_test /sbin
|
||||
@@ -0,0 +1,288 @@
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
#include<stdlib.h>
|
||||
#include <errno.h>
|
||||
#define WIFI_DRIVER_FW_PATH "sta"
|
||||
#define WIFI_DRIVER_MODULE_NAME "rwnx_fdrv"
|
||||
#define WIFI_DRIVER_MODULE_PATH "/vendor/modules/rwnx_fdrv.ko"
|
||||
#define MAX_DRV_CMD_SIZE 1536
|
||||
#define TXRX_PARA SIOCDEVPRIVATE+1
|
||||
|
||||
static const char IFACE_DIR[] = "";
|
||||
static const char DRIVER_MODULE_NAME[] = "rwnx_fdrv";
|
||||
static const char DRIVER_MODULE_TAG[] = WIFI_DRIVER_MODULE_NAME " ";
|
||||
static const char DRIVER_MODULE_PATH[] = WIFI_DRIVER_MODULE_PATH;
|
||||
static const char DRIVER_MODULE_ARG[] = "";
|
||||
static const char FIRMWARE_LOADER[] = "";
|
||||
static const char DRIVER_PROP_NAME[] = "wlan.driver.status";
|
||||
|
||||
#ifndef TEMP_FAILURE_RETRY
|
||||
#define TEMP_FAILURE_RETRY(expression) \
|
||||
(__extension__ \
|
||||
({ long int __result; \
|
||||
do __result = (long int) (expression); \
|
||||
while (__result == -1L && errno == EINTR); \
|
||||
__result; }))
|
||||
#endif
|
||||
|
||||
typedef struct android_wifi_priv_cmd {
|
||||
char *buf;
|
||||
int used_len;
|
||||
int total_len;
|
||||
} android_wifi_priv_cmd;
|
||||
|
||||
int wifi_send_cmd_to_net_interface(const char* if_name, int argC, char *argV[])
|
||||
{
|
||||
int sock;
|
||||
struct ifreq ifr;
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
char buf[MAX_DRV_CMD_SIZE];
|
||||
struct android_wifi_priv_cmd priv_cmd;
|
||||
char is_param_err = 0;
|
||||
int buf_len = 0;
|
||||
|
||||
sock = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (sock < 0) {
|
||||
printf("bad sock!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strcpy(ifr.ifr_name, if_name);
|
||||
|
||||
if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
|
||||
printf("%s Could not read interface %s flags: %s",__func__, if_name, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(ifr.ifr_flags & IFF_UP)) {
|
||||
printf("%s is not up!\n",if_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// printf("ifr.ifr_name = %s\n", ifr.ifr_name);
|
||||
memset(&priv_cmd, 0, sizeof(priv_cmd));
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
for(i=2; i<argC; i++){
|
||||
strcat(buf, argV[i]);
|
||||
strcat(buf, " ");
|
||||
}
|
||||
|
||||
priv_cmd.buf = buf;
|
||||
priv_cmd.used_len = strlen(buf);
|
||||
priv_cmd.total_len = sizeof(buf);
|
||||
ifr.ifr_data = (void*)&priv_cmd;
|
||||
|
||||
printf("%s:\n", argV[2]);
|
||||
if (strcasecmp(argV[2], "SET_TX") == 0) {
|
||||
if (argC < 8) {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if (strcasecmp(argV[2], "SET_TXTONE") == 0) {
|
||||
if (((argC == 4) && (argV[3][0] != '0'))
|
||||
|| ((argC == 5) && (argV[3][0] == '0'))) {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(argV[2], "SET_RX") == 0)
|
||||
|| (strcasecmp(argV[2], "SET_POWER") == 0)) {
|
||||
if (argC < 5) {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(argV[2], "SET_XTAL_CAP") == 0)
|
||||
|| (strcasecmp(argV[2], "SET_XTAL_CAP_FINE") == 0)) {
|
||||
if (argC < 4) {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(argV[2], "GET_EFUSE_BLOCK") == 0)
|
||||
|| (strcasecmp(argV[2], "SET_FREQ_CAL") == 0)) {
|
||||
if (argC < 4) {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(argV[2], "SET_MAC_ADDR") == 0)
|
||||
|| (strcasecmp(argV[2], "SET_BT_MAC_ADDR") == 0)) {
|
||||
if (argC < 8) {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if (strcasecmp(argV[2], "SET_VENDOR_INFO") == 0) {
|
||||
if (argC < 4) {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(argV[2], "RDWR_PWRIDX") == 0)
|
||||
|| (strcasecmp(argV[2], "RDWR_PWROFST") == 0)
|
||||
|| (strcasecmp(argV[2], "RDWR_EFUSE_PWROFST") == 0)) {
|
||||
if (((argC == 4) && (argV[3][0] != '0'))
|
||||
|| (argC == 5)
|
||||
|| ((argC == 6) && (argV[3][0] == '0'))) {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(argV[2], "RDWR_DRVIBIT") == 0)
|
||||
|| (strcasecmp(argV[2], "RDWR_EFUSE_DRVIBIT") == 0)) {
|
||||
if (((argC == 4) && (argV[3][0] != '0'))
|
||||
|| ((argC == 5) && (argV[3][0] == '0'))) {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(argV[2], "BT_RESET") == 0)) {
|
||||
char bt_reset_hci_cmd[32] = "01 03 0c 00";
|
||||
if (argC == 3) {
|
||||
buf_len = priv_cmd.used_len;
|
||||
memcpy(&priv_cmd.buf[buf_len], &bt_reset_hci_cmd[0], strlen(bt_reset_hci_cmd));
|
||||
buf_len += strlen(bt_reset_hci_cmd);
|
||||
priv_cmd.used_len = buf_len;
|
||||
} else {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(argV[2], "BT_TXDH") == 0)) {
|
||||
char bt_txdh_hci_cmd[255] = "01 06 18 0e ";
|
||||
if (argC == 17) {
|
||||
buf_len = priv_cmd.used_len;
|
||||
int arg_len = strlen(argV[2]);
|
||||
int txdh_cmd_len = strlen(bt_txdh_hci_cmd);
|
||||
memcpy(&bt_txdh_hci_cmd[txdh_cmd_len], &priv_cmd.buf[arg_len+1], buf_len - arg_len - 1);
|
||||
memcpy(&priv_cmd.buf[arg_len+1], &bt_txdh_hci_cmd[0], strlen(bt_txdh_hci_cmd));
|
||||
buf_len += strlen(bt_txdh_hci_cmd);
|
||||
priv_cmd.used_len = buf_len;
|
||||
} else {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(argV[2], "BT_RXDH") == 0)) {
|
||||
if (argC == 16) {
|
||||
char bt_rxdh_hci_cmd[255] = "01 0b 18 0d ";
|
||||
buf_len = priv_cmd.used_len;
|
||||
int arg_len = strlen(argV[2]);
|
||||
int rxdh_cmd_len = strlen(bt_rxdh_hci_cmd);
|
||||
memcpy(&bt_rxdh_hci_cmd[rxdh_cmd_len], &priv_cmd.buf[arg_len+1], buf_len - arg_len - 1);
|
||||
memcpy(&priv_cmd.buf[arg_len+1], &bt_rxdh_hci_cmd[0], strlen(bt_rxdh_hci_cmd));
|
||||
buf_len += strlen(bt_rxdh_hci_cmd);
|
||||
priv_cmd.used_len = buf_len;
|
||||
} else {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(argV[2], "BT_STOP") == 0)) {
|
||||
char bt_stop_hci_cmd[255] = "01 0C 18 01 ";
|
||||
if (argC == 4) {
|
||||
buf_len = priv_cmd.used_len;
|
||||
int arg_len = strlen(argV[2]);
|
||||
int stop_cmd_len = strlen(bt_stop_hci_cmd);
|
||||
memcpy(&bt_stop_hci_cmd[stop_cmd_len], &priv_cmd.buf[arg_len+1], buf_len - arg_len - 1);
|
||||
memcpy(&priv_cmd.buf[arg_len+1], &bt_stop_hci_cmd[0], strlen(bt_stop_hci_cmd));
|
||||
buf_len += strlen(bt_stop_hci_cmd);
|
||||
priv_cmd.used_len = buf_len;
|
||||
} else {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else {
|
||||
is_param_err = 0;
|
||||
}
|
||||
|
||||
if (is_param_err) {
|
||||
printf("param error!!!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((ret = ioctl(sock, TXRX_PARA, &ifr)) < 0) {
|
||||
printf("%s: error ioctl[TX_PARA] ret= %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
memcpy(&priv_cmd, ifr.ifr_data, sizeof(struct android_wifi_priv_cmd));
|
||||
if (strcasecmp(argV[2], "SET_FREQ_CAL") == 0)
|
||||
printf("done: freq_cal: 0x%8x\n", *(unsigned int *)priv_cmd.buf);
|
||||
else if (strcasecmp(argV[2], "GET_EFUSE_BLOCK") == 0)
|
||||
printf("done:efuse: 0x%8x\n", *(unsigned int *)priv_cmd.buf);
|
||||
else if (strcasecmp(argV[2], "SET_XTAL_CAP") == 0)
|
||||
printf("done:xtal cap: 0x%x\n", *(unsigned int *)priv_cmd.buf);
|
||||
else if (strcasecmp(argV[2], "SET_XTAL_CAP_FINE") == 0)
|
||||
printf("done:xtal cap fine: 0x%x\n", *(unsigned int *)priv_cmd.buf);
|
||||
else if (strcasecmp(argV[2], "GET_RX_RESULT") == 0)
|
||||
printf("done: getrx fcsok=%d, total=%d\n", *(unsigned int *)priv_cmd.buf, *(unsigned int *)&priv_cmd.buf[4]);
|
||||
else if (strcasecmp(argV[2], "GET_MAC_ADDR") == 0) {
|
||||
printf("done: get macaddr = %x : %x : %x : %x : %x : %x\n",
|
||||
*(unsigned char *)&priv_cmd.buf[5], *(unsigned char *)&priv_cmd.buf[4], *(unsigned char *)&priv_cmd.buf[3],
|
||||
*(unsigned char *)&priv_cmd.buf[2], *(unsigned char *)&priv_cmd.buf[1], *(unsigned char *)&priv_cmd.buf[0]);
|
||||
} else if (strcasecmp(argV[2], "GET_BT_MAC_ADDR") == 0) {
|
||||
printf("done: get bt macaddr = %x : %x : %x : %x : %x : %x\n",
|
||||
*(unsigned char *)&priv_cmd.buf[5], *(unsigned char *)&priv_cmd.buf[4], *(unsigned char *)&priv_cmd.buf[3],
|
||||
*(unsigned char *)&priv_cmd.buf[2], *(unsigned char *)&priv_cmd.buf[1], *(unsigned char *)&priv_cmd.buf[0]);
|
||||
} else if (strcasecmp(argV[2], "GET_FREQ_CAL") == 0) {
|
||||
unsigned int val = *(unsigned int *)&priv_cmd.buf[0];
|
||||
printf("done: get_freq_cal: xtal_cap=0x%x, xtal_cap_fine=%x\n", val & 0x0000ffff, (val >> 16) & 0x0000ffff);
|
||||
} else if (strcasecmp(argV[2], "GET_VENDOR_INFO") == 0) {
|
||||
printf("done: get_vendor_info = 0x%x\n", *(unsigned char *)&priv_cmd.buf[0]);
|
||||
} else if (strcasecmp(argV[2], "RDWR_PWRMM") == 0) {
|
||||
printf("done: txpwr manual mode = %x\n", *(unsigned int *)&priv_cmd.buf[0]);
|
||||
} else if (strcasecmp(argV[2], "RDWR_PWRIDX") == 0) {
|
||||
char *buff = &priv_cmd.buf[0];
|
||||
printf("done:\n"
|
||||
"txpwr index 2.4g:\n"
|
||||
" [0]=%d(ofdmlowrate)\n"
|
||||
" [1]=%d(ofdmhighrate)\n"
|
||||
" [2]=%d(ofdm1024qam)\n"
|
||||
" [3]=%d(dsss)\n", buff[0], buff[1], buff[2], buff[3]);
|
||||
printf("txpwr index 5g:\n"
|
||||
" [0]=%d(ofdmlowrate)\n"
|
||||
" [1]=%d(ofdmhighrate)\n"
|
||||
" [2]=%d(ofdm1024qam)\n", buff[4], buff[5], buff[6]);
|
||||
} else if (strcasecmp(argV[2], "RDWR_PWROFST") == 0) {
|
||||
char *buff = &priv_cmd.buf[0];
|
||||
printf("done:\n"
|
||||
"txpwr offset 2.4g:\n"
|
||||
" [0]=%d(ch1~4)\n"
|
||||
" [1]=%d(ch5~9)\n"
|
||||
" [2]=%d(ch10~13)\n", buff[0], buff[1], buff[2]);
|
||||
printf("txpwr offset 5g:\n"
|
||||
" [0]=%d(ch36~64)\n"
|
||||
" [1]=%d(ch100~120)\n"
|
||||
" [2]=%d(ch122~140)\n"
|
||||
" [3]=%d(ch142~165)\n", buff[3], buff[4], buff[5], buff[6]);
|
||||
} else if (strcasecmp(argV[2], "RDWR_DRVIBIT") == 0) {
|
||||
char *buff = &priv_cmd.buf[0];
|
||||
int idx = 0;
|
||||
printf("done: 2.4g txgain tbl pa drv_ibit:\n");
|
||||
for (idx = 0; idx < 16; idx++) {
|
||||
printf(" %x", buff[idx]);
|
||||
if (!((idx + 1) & 0x03)) {
|
||||
printf(" [%x~%x]\n", idx - 3, idx);
|
||||
}
|
||||
}
|
||||
} else if (strcasecmp(argV[2], "RDWR_EFUSE_PWROFST") == 0) {
|
||||
char *buff = &priv_cmd.buf[0];
|
||||
printf("done:\n"
|
||||
"efuse txpwr offset 2.4g:\n"
|
||||
" [0]=%d(ch1~4)\n"
|
||||
" [1]=%d(ch5~9)\n"
|
||||
" [2]=%d(ch10~13)\n", buff[0], buff[1], buff[2]);
|
||||
printf("efuse txpwr offset 5g:\n"
|
||||
" [0]=%d(ch36~64)\n"
|
||||
" [1]=%d(ch100~120)\n"
|
||||
" [2]=%d(ch122~140)\n"
|
||||
" [3]=%d(ch142~165)\n", buff[3], buff[4], buff[5], buff[6]);
|
||||
} else if (strcasecmp(argV[2], "RDWR_EFUSE_DRVIBIT") == 0) {
|
||||
printf("done: efsue 2.4g txgain tbl pa drv_ibit: %x\n", priv_cmd.buf[0]);
|
||||
} else {
|
||||
printf("done\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argC, char *argV[])
|
||||
{
|
||||
|
||||
char* ins = "insmod";
|
||||
char* rm = "rmmod";
|
||||
char* ko = "rwnx_fdrv.ko";
|
||||
|
||||
// printf("enter!!!AIC argC=%d argV[0]=%s argV[1]=%s argV[2]=%s\n", argC, argV[0], argV[1],argV[2]);
|
||||
if(argC >= 3)
|
||||
wifi_send_cmd_to_net_interface(argV[1], argC, argV);
|
||||
else
|
||||
printf("Bad parameter! %d\n",argC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,770 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <pthread.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
|
||||
//tool role
|
||||
#define SERVER 0
|
||||
#define CLIENT 1
|
||||
#define WLAN_CLIENT 2
|
||||
|
||||
//interface
|
||||
#define UART 0
|
||||
#define USB 1
|
||||
#define WLAN 2
|
||||
|
||||
//uart param
|
||||
#define BAUDRATE 1500000
|
||||
#define DATABITS 8
|
||||
#define PARTY 'N'
|
||||
#define STOP '1'
|
||||
#define SOFTWARE_HANDSHAKE 0
|
||||
#define HARDWARE_HANDSHAKE 0
|
||||
|
||||
//socket param
|
||||
#define BT_HCI_TOOL_PORT 5001
|
||||
#define SOCKER_BUFFER_SIZE 1024
|
||||
|
||||
#define OK 0
|
||||
#define ERR -1
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
#define DOWN_FW_CFG _IOW('E', 176, int)
|
||||
#define GET_USB_INFO _IOR('E', 180, int)
|
||||
|
||||
#define WLAN_CMD_MAX_CNT 256
|
||||
#define TXRX_PARA SIOCDEVPRIVATE+1
|
||||
|
||||
int server_or_client = SERVER;
|
||||
int interface = USB;
|
||||
int bt_dev_fd = 0;
|
||||
|
||||
char s_baudrate[8];
|
||||
|
||||
char* s_hci_command[256];
|
||||
char w_ifname[64];
|
||||
char *w_command[WLAN_CMD_MAX_CNT];
|
||||
char hci_event[256];
|
||||
|
||||
char dev_path[] = "/dev/aicbt_dev";
|
||||
|
||||
char hci_reset[] = { 0x01, 0x03, 0x0c, 0x00 };
|
||||
|
||||
|
||||
typedef struct android_wifi_priv_cmd {
|
||||
char *buf;
|
||||
int used_len;
|
||||
int total_len;
|
||||
} android_wifi_priv_cmd;
|
||||
|
||||
|
||||
void helper(){
|
||||
printf("\t<-s> to be tool service. ex. \"bt_test -s uart 115200 /dev/ttyS0\" or \"bt_test -s usb\" or \"bt_test -s wlan wlan0\"\n");
|
||||
//printf("\t<-s> to be tool service. ex. -s uart 115200 noflow and -s usb\n");
|
||||
printf("\t<-c> to send hci cmd to interface.\n");
|
||||
printf("\t<-w> to send wlan cmd to interface.\n");
|
||||
}
|
||||
|
||||
int parse_cmd_line(int argc, char **argv){
|
||||
int command_number = argc;
|
||||
int command_counter = 1;
|
||||
int hci_command_counter = 0;
|
||||
//int error_command = 0;
|
||||
|
||||
while(command_counter < command_number){
|
||||
if(!strcmp(argv[command_counter], "-s")){
|
||||
if(!(command_number >= 3)){
|
||||
printf("error command \r\n");
|
||||
return ERR;
|
||||
}
|
||||
printf("bt_hci_tool server setting\r\n");
|
||||
server_or_client = SERVER;
|
||||
command_counter++;
|
||||
if(!strcmp(argv[command_counter], "usb")){
|
||||
printf("use USB\r\n");
|
||||
interface = USB;
|
||||
return OK;
|
||||
}else if(!strcmp(argv[command_counter], "uart")){
|
||||
interface = UART;
|
||||
if(command_number != 5){
|
||||
printf("error command \r\n");
|
||||
return ERR;
|
||||
}
|
||||
command_counter++;
|
||||
memcpy(s_baudrate, argv[command_counter], strlen(argv[command_counter]));
|
||||
command_counter++;
|
||||
memset(dev_path, 0, strlen(dev_path));
|
||||
memcpy(dev_path, argv[command_counter], strlen(argv[command_counter]));
|
||||
printf("use UART %d %s\r\n", atoi(s_baudrate), dev_path);
|
||||
return OK;
|
||||
}else if(!strcmp(argv[command_counter], "wlan")){
|
||||
interface = WLAN;
|
||||
if(command_number != 4){
|
||||
printf("error command \r\n");
|
||||
return ERR;
|
||||
}
|
||||
command_counter++;
|
||||
memcpy(w_ifname, argv[command_counter], strlen(argv[command_counter]));
|
||||
printf("use WLAN %s\r\n", w_ifname);
|
||||
return OK;
|
||||
}else{
|
||||
printf("interface set error\r\n");
|
||||
return ERR;
|
||||
}
|
||||
}else if(!strcmp(argv[command_counter], "-c")){
|
||||
server_or_client = CLIENT;
|
||||
command_counter++;
|
||||
hci_command_counter = 0;
|
||||
while(command_counter < command_number){
|
||||
s_hci_command[hci_command_counter++] = argv[command_counter];
|
||||
command_counter++;
|
||||
}
|
||||
return OK;
|
||||
} else if (!strcmp(argv[command_counter], "-w")) {
|
||||
int w_command_counter = 0;
|
||||
server_or_client = WLAN_CLIENT;
|
||||
if (command_number >= WLAN_CMD_MAX_CNT) {
|
||||
printf("too much args\r\n");
|
||||
return ERR;
|
||||
}
|
||||
command_counter++;
|
||||
while (command_counter < command_number) {
|
||||
w_command[w_command_counter++] = argv[command_counter];
|
||||
command_counter++;
|
||||
}
|
||||
return OK;
|
||||
}else{
|
||||
if (strcmp(argv[1], "-h") != 0) {
|
||||
printf("unknow command %s \r\n", argv[command_counter]);
|
||||
}
|
||||
helper();
|
||||
return ERR;
|
||||
}
|
||||
|
||||
command_counter++;
|
||||
}
|
||||
|
||||
helper();
|
||||
return ERR;
|
||||
|
||||
}
|
||||
|
||||
void uart_set_options(int baudrate, int databits,
|
||||
char parity, char stop, int softwareHandshake, int hardwareHandshake)
|
||||
{
|
||||
struct termios newtio;
|
||||
if (tcgetattr(bt_dev_fd, &newtio)!=0)
|
||||
{
|
||||
printf("tcgetattr() 3 failed \n");
|
||||
}
|
||||
|
||||
speed_t _baud=0;
|
||||
printf("set baudrate:%d\n", baudrate);
|
||||
|
||||
switch (baudrate)
|
||||
{
|
||||
#ifdef B0
|
||||
case 0: _baud=B0; break;
|
||||
#endif
|
||||
#ifdef B50
|
||||
case 50: _baud=B50; break;
|
||||
#endif
|
||||
#ifdef B75
|
||||
case 75: _baud=B75; break;
|
||||
#endif
|
||||
#ifdef B110
|
||||
case 110: _baud=B110; break;
|
||||
#endif
|
||||
#ifdef B134
|
||||
case 134: _baud=B134; break;
|
||||
#endif
|
||||
#ifdef B150
|
||||
case 150: _baud=B150; break;
|
||||
#endif
|
||||
#ifdef B200
|
||||
case 200: _baud=B200; break;
|
||||
#endif
|
||||
#ifdef B300
|
||||
case 300: _baud=B300; break;
|
||||
#endif
|
||||
#ifdef B600
|
||||
case 600: _baud=B600; break;
|
||||
#endif
|
||||
#ifdef B1200
|
||||
case 1200: _baud=B1200; break;
|
||||
#endif
|
||||
#ifdef B1800
|
||||
case 1800: _baud=B1800; break;
|
||||
#endif
|
||||
#ifdef B2400
|
||||
case 2400: _baud=B2400; break;
|
||||
#endif
|
||||
#ifdef B4800
|
||||
case 4800: _baud=B4800; break;
|
||||
#endif
|
||||
#ifdef B7200
|
||||
case 7200: _baud=B7200; break;
|
||||
#endif
|
||||
#ifdef B9600
|
||||
case 9600: _baud=B9600; break;
|
||||
#endif
|
||||
#ifdef B14400
|
||||
case 14400: _baud=B14400; break;
|
||||
#endif
|
||||
#ifdef B19200
|
||||
case 19200: _baud=B19200; break;
|
||||
#endif
|
||||
#ifdef B28800
|
||||
case 28800: _baud=B28800; break;
|
||||
#endif
|
||||
#ifdef B38400
|
||||
case 38400: _baud=B38400; break;
|
||||
#endif
|
||||
#ifdef B57600
|
||||
case 57600: _baud=B57600; break;
|
||||
#endif
|
||||
#ifdef B76800
|
||||
case 76800: _baud=B76800; break;
|
||||
#endif
|
||||
#ifdef B115200
|
||||
case 115200: _baud=B115200; break;
|
||||
#endif
|
||||
#ifdef B128000
|
||||
case 128000: _baud=B128000; break;
|
||||
#endif
|
||||
#ifdef B230400
|
||||
case 230400: _baud=B230400; break;
|
||||
#endif
|
||||
#ifdef B460800
|
||||
case 460800: _baud=B460800; break;
|
||||
#endif
|
||||
#ifdef B576000
|
||||
case 576000: _baud=B576000; break;
|
||||
#endif
|
||||
#ifdef B921600
|
||||
case 921600: _baud=B921600; break;
|
||||
#endif
|
||||
#ifdef B1500000
|
||||
case 1500000: _baud=B1500000; break;
|
||||
#endif
|
||||
#ifdef B2000000
|
||||
case 2000000: _baud=B2000000; break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
cfsetospeed(&newtio, (speed_t)_baud);
|
||||
cfsetispeed(&newtio, (speed_t)_baud);
|
||||
|
||||
/* We generate mark and space parity ourself. */
|
||||
if (databits == 7 && (parity=='M' || parity == 'S'))
|
||||
{
|
||||
databits = 8;
|
||||
}
|
||||
switch (databits)
|
||||
{
|
||||
case 5:
|
||||
newtio.c_cflag = (newtio.c_cflag & ~CSIZE) | CS5;
|
||||
break;
|
||||
case 6:
|
||||
newtio.c_cflag = (newtio.c_cflag & ~CSIZE) | CS6;
|
||||
break;
|
||||
case 7:
|
||||
newtio.c_cflag = (newtio.c_cflag & ~CSIZE) | CS7;
|
||||
break;
|
||||
case 8:
|
||||
default:
|
||||
newtio.c_cflag = (newtio.c_cflag & ~CSIZE) | CS8;
|
||||
break;
|
||||
}
|
||||
newtio.c_cflag |= CLOCAL | CREAD;
|
||||
|
||||
//parity
|
||||
newtio.c_cflag &= ~(PARENB | PARODD);
|
||||
if (parity == 'E')
|
||||
{
|
||||
newtio.c_cflag |= PARENB;
|
||||
}
|
||||
else if (parity== 'O')
|
||||
{
|
||||
newtio.c_cflag |= (PARENB | PARODD);
|
||||
}
|
||||
|
||||
//hardware handshake
|
||||
newtio.c_cflag &= ~CRTSCTS;
|
||||
|
||||
//stopbits
|
||||
if (stop=='2')
|
||||
{
|
||||
newtio.c_cflag |= CSTOPB;
|
||||
}
|
||||
else
|
||||
{
|
||||
newtio.c_cflag &= ~CSTOPB;
|
||||
}
|
||||
|
||||
newtio.c_iflag=IGNBRK;
|
||||
|
||||
//software handshake
|
||||
if (softwareHandshake)
|
||||
{
|
||||
newtio.c_iflag |= IXON | IXOFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
newtio.c_iflag &= ~(IXON|IXOFF|IXANY);
|
||||
}
|
||||
|
||||
newtio.c_lflag=0;
|
||||
newtio.c_oflag=0;
|
||||
|
||||
// newtio.c_cc[VTIME]=1;
|
||||
// newtio.c_cc[VMIN]=60;
|
||||
|
||||
if (tcsetattr(bt_dev_fd, TCSANOW, &newtio)!=0)
|
||||
{
|
||||
printf("tcsetattr() 1 failed \n");
|
||||
}
|
||||
|
||||
if (tcgetattr(bt_dev_fd, &newtio)!=0)
|
||||
{
|
||||
printf("tcsetattr() 4 failed \n");
|
||||
}
|
||||
|
||||
//hardware handshake
|
||||
if (hardwareHandshake)
|
||||
{
|
||||
newtio.c_cflag |= CRTSCTS;
|
||||
}
|
||||
else
|
||||
{
|
||||
newtio.c_cflag &= ~CRTSCTS;
|
||||
}
|
||||
|
||||
if (tcsetattr(bt_dev_fd, TCSANOW, &newtio)!=0)
|
||||
{
|
||||
printf("tcsetattr() 2 failed \n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned char atoh(char* s_data){
|
||||
unsigned char ret_value;
|
||||
char temp_value = 0;
|
||||
|
||||
//h
|
||||
if(s_data[0] >= 48 && s_data[0] <= 57){
|
||||
temp_value = s_data[0] - 48;
|
||||
}else if(s_data[0] >= 65 && s_data[0] <= 70){
|
||||
temp_value = (s_data[0] - 65) + 10;
|
||||
}else if(s_data[0] >= 97 && s_data[0] <= 102){
|
||||
temp_value = (s_data[0] - 97) + 10;
|
||||
}
|
||||
|
||||
ret_value = temp_value;
|
||||
ret_value = ret_value << 4;
|
||||
//printf("atoh1: ret_value:%x\r\n", ret_value);
|
||||
//l
|
||||
if(s_data[1] >= 48 && s_data[1] <= 57){
|
||||
temp_value = s_data[1] - 48;
|
||||
}else if(s_data[1] >= 65 && s_data[1] <= 70){
|
||||
temp_value = (s_data[1] - 65) + 10;
|
||||
}else if(s_data[1] >= 97 && s_data[1] <= 102){
|
||||
temp_value = (s_data[1] - 97) + 10;
|
||||
}
|
||||
|
||||
ret_value |= temp_value;
|
||||
//printf("atoh2: ret_value:%x\r\n", ret_value);
|
||||
|
||||
return ret_value;
|
||||
|
||||
}
|
||||
|
||||
int send_to_server(unsigned char* buffer, int len){
|
||||
int client_socket;
|
||||
struct sockaddr_in serverAddr;
|
||||
//unsigned long long package_totel_counter = 0;
|
||||
|
||||
if((client_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0){
|
||||
return ERR;
|
||||
}
|
||||
|
||||
serverAddr.sin_family = AF_INET;
|
||||
serverAddr.sin_port = htons(BT_HCI_TOOL_PORT);
|
||||
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
|
||||
if(connect(client_socket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0){
|
||||
return ERR;
|
||||
}
|
||||
|
||||
send(client_socket, buffer, len, 0);
|
||||
return OK;
|
||||
}
|
||||
|
||||
void send_hci_command(){
|
||||
int i = 0;
|
||||
int command_len = 0;
|
||||
unsigned char buffer[SOCKER_BUFFER_SIZE];
|
||||
|
||||
// printf("send hci command: \r\n");
|
||||
|
||||
for(i = 0;i < 256; i++){
|
||||
if(s_hci_command[i] == NULL){
|
||||
command_len = i;
|
||||
break;
|
||||
}
|
||||
|
||||
buffer[i] = atoh(s_hci_command[i]);
|
||||
// printf("%02X ", buffer[i]);
|
||||
}
|
||||
|
||||
send_to_server(buffer, i);
|
||||
|
||||
// printf("\r\n");
|
||||
}
|
||||
|
||||
void send_wlan_command(void)
|
||||
{
|
||||
int i = 0;
|
||||
int command_len = 0;
|
||||
unsigned char buffer[SOCKER_BUFFER_SIZE] = {0,};
|
||||
while ((w_command[i] != NULL) && (i < WLAN_CMD_MAX_CNT)) {
|
||||
strcat((char*)&buffer[0], w_command[i]);
|
||||
strcat((char*)&buffer[0], " ");
|
||||
i++;
|
||||
}
|
||||
command_len = strlen((char*)&buffer[0]);
|
||||
printf("command_len:%d \r\n", command_len);
|
||||
if (command_len > 1) {
|
||||
//command_len--; // rm last space
|
||||
//buffer[command_len] = '\0';
|
||||
send_to_server(buffer, command_len);
|
||||
}
|
||||
}
|
||||
|
||||
int hci_send(char* data, int len){
|
||||
int i = 0;
|
||||
unsigned char tmp_data[len];
|
||||
|
||||
printf("COMMAND(%d): \r\n", len);
|
||||
for(i = 0; i < len; i++){
|
||||
tmp_data[i] = (unsigned char)data[i];
|
||||
printf("%02X ", tmp_data[i]);
|
||||
}
|
||||
printf("\r\n");
|
||||
|
||||
len = write(bt_dev_fd, tmp_data, len);
|
||||
if (len < 0) {
|
||||
printf("write data error \n");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
int hci_recv(char* data, int len){
|
||||
int i = 0;
|
||||
unsigned char tmp_byte[64];// = 0x00;
|
||||
|
||||
memset(data, 0, len);
|
||||
|
||||
len = read(bt_dev_fd, data, len);
|
||||
if (len < 0) {
|
||||
printf("read error \n");
|
||||
return FALSE;
|
||||
}
|
||||
printf("EVENT(%d): \r\n", len);
|
||||
for(i = 0; i < len; i++){
|
||||
tmp_byte[i] = (unsigned char)data[i];
|
||||
printf("%02X ", tmp_byte[i]);
|
||||
}
|
||||
printf("\r\n");
|
||||
|
||||
if(tmp_byte[1] == 0x0D) {
|
||||
uint32_t rx_pkt_len = tmp_byte[4] | (tmp_byte[5] << 8) | (tmp_byte[6] << 16) | (tmp_byte[7] << 24);
|
||||
uint32_t total_rx_pkts = tmp_byte[8] | (tmp_byte[9] << 8) | (tmp_byte[10] << 16) | (tmp_byte[11] << 24);
|
||||
uint32_t rx_ok_pkts = tmp_byte[12] | (tmp_byte[13] << 8) | (tmp_byte[14] << 16) | (tmp_byte[15] << 24);
|
||||
uint32_t rx_err_pkts = tmp_byte[16] | (tmp_byte[17] << 8) | (tmp_byte[18] << 16) | (tmp_byte[19] << 24);
|
||||
uint32_t rx_err_bits = tmp_byte[20] | (tmp_byte[21] << 8) | (tmp_byte[22] << 16) | (tmp_byte[23] << 24);
|
||||
float per = (float) 100 * rx_err_pkts / total_rx_pkts;
|
||||
float ber = (float) 10000 * rx_err_bits / (total_rx_pkts * rx_pkt_len * 8) ;
|
||||
printf("rx result: pkt_len=%d, total=%d, ok=%d, err=%d, err_bits=%d, per=%.2f%%, ber=%.4f%%%%%%\n",
|
||||
rx_pkt_len, total_rx_pkts, rx_ok_pkts, rx_err_pkts, rx_err_bits, per, ber);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int wlan_send(char *data, int len)
|
||||
{
|
||||
int sock;
|
||||
struct ifreq ifr;
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
char wl_cmd[64];
|
||||
struct android_wifi_priv_cmd priv_cmd;
|
||||
char is_param_err = 0;
|
||||
int buf_len = 0;
|
||||
int argC = 0;
|
||||
int idx = 0;
|
||||
|
||||
sock = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (sock < 0) {
|
||||
printf("bad sock!\n");
|
||||
return ERR;
|
||||
}
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strcpy(ifr.ifr_name, w_ifname);
|
||||
|
||||
if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
|
||||
printf("%s Could not read interface %s flags: %s",__func__, w_ifname, strerror(errno));
|
||||
return ERR;
|
||||
}
|
||||
|
||||
if (!(ifr.ifr_flags & IFF_UP)) {
|
||||
printf("%s is not up!\n",w_ifname);
|
||||
return ERR;
|
||||
}
|
||||
|
||||
printf("ifr.ifr_name = %s\n", ifr.ifr_name);
|
||||
memset(&priv_cmd, 0, sizeof(priv_cmd));
|
||||
memset(wl_cmd, 0, sizeof(wl_cmd));
|
||||
// extract wlan command & argC
|
||||
for (i = 0; i < len; i++) {
|
||||
if (data[i] != ' ') {
|
||||
if (argC == 0) {
|
||||
wl_cmd[i] = data[i];
|
||||
}
|
||||
} else {
|
||||
argC++;
|
||||
}
|
||||
}
|
||||
printf("wl_cmd=%s, argC=%d\r\n", wl_cmd, argC);
|
||||
|
||||
priv_cmd.buf = data;
|
||||
priv_cmd.used_len = len;
|
||||
priv_cmd.total_len = SOCKER_BUFFER_SIZE;
|
||||
ifr.ifr_data = (void*)&priv_cmd;
|
||||
|
||||
if ((strcasecmp(wl_cmd, "BT_RESET") == 0)) {
|
||||
char bt_reset_hci_cmd[32] = "01 03 0c 00";
|
||||
if (argC == 1) {
|
||||
buf_len = priv_cmd.used_len;
|
||||
memcpy(&priv_cmd.buf[buf_len], &bt_reset_hci_cmd[0], strlen(bt_reset_hci_cmd));
|
||||
buf_len += strlen(bt_reset_hci_cmd);
|
||||
priv_cmd.used_len = buf_len;
|
||||
} else {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(wl_cmd, "BT_TXDH") == 0)) {
|
||||
char bt_txdh_hci_cmd[255] = "01 06 18 0e ";
|
||||
if (argC == 15) {
|
||||
buf_len = priv_cmd.used_len;
|
||||
int arg_len = strlen("BT_TXDH");
|
||||
int txdh_cmd_len = strlen(bt_txdh_hci_cmd);
|
||||
memcpy(&bt_txdh_hci_cmd[txdh_cmd_len], &priv_cmd.buf[arg_len+1], buf_len - arg_len - 1);
|
||||
memcpy(&priv_cmd.buf[arg_len+1], &bt_txdh_hci_cmd[0], strlen(bt_txdh_hci_cmd));
|
||||
buf_len += strlen(bt_txdh_hci_cmd);
|
||||
priv_cmd.used_len = buf_len;
|
||||
} else {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(wl_cmd, "BT_RXDH") == 0)) {
|
||||
if (argC == 14) {
|
||||
char bt_rxdh_hci_cmd[255] = "01 0b 18 0d ";
|
||||
buf_len = priv_cmd.used_len;
|
||||
int arg_len = strlen("BT_RXDH");
|
||||
int rxdh_cmd_len = strlen(bt_rxdh_hci_cmd);
|
||||
memcpy(&bt_rxdh_hci_cmd[rxdh_cmd_len], &priv_cmd.buf[arg_len+1], buf_len - arg_len - 1);
|
||||
memcpy(&priv_cmd.buf[arg_len+1], &bt_rxdh_hci_cmd[0], strlen(bt_rxdh_hci_cmd));
|
||||
buf_len += strlen(bt_rxdh_hci_cmd);
|
||||
priv_cmd.used_len = buf_len;
|
||||
} else {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(wl_cmd, "BT_STOP") == 0)) {
|
||||
char bt_stop_hci_cmd[255] = "01 0C 18 01 ";
|
||||
if (argC == 2) {
|
||||
buf_len = priv_cmd.used_len;
|
||||
int arg_len = strlen("BT_STOP");
|
||||
int stop_cmd_len = strlen(bt_stop_hci_cmd);
|
||||
memcpy(&bt_stop_hci_cmd[stop_cmd_len], &priv_cmd.buf[arg_len+1], buf_len - arg_len - 1);
|
||||
memcpy(&priv_cmd.buf[arg_len+1], &bt_stop_hci_cmd[0], strlen(bt_stop_hci_cmd));
|
||||
buf_len += strlen(bt_stop_hci_cmd);
|
||||
priv_cmd.used_len = buf_len;
|
||||
} else if ((strcasecmp(wl_cmd, "BT_DATA") == 0)) {
|
||||
//char bt_raw_data_cmd[255];
|
||||
int arg_len = strlen(wl_cmd);
|
||||
buf_len = priv_cmd.used_len;
|
||||
memcpy(&priv_cmd.buf[arg_len+1], &priv_cmd.buf[arg_len+1], buf_len - arg_len - 1);
|
||||
priv_cmd.used_len = buf_len - arg_len - 1;
|
||||
} else {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else {
|
||||
is_param_err = 0;
|
||||
}
|
||||
if (is_param_err) {
|
||||
printf("param error!!!\n");
|
||||
return ERR;
|
||||
}
|
||||
if ((ret = ioctl(sock, TXRX_PARA, &ifr)) < 0) {
|
||||
printf("%s: error ioctl[TX_PARA] ret= %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
memcpy(&priv_cmd, ifr.ifr_data, sizeof(struct android_wifi_priv_cmd));
|
||||
if (strcasecmp(wl_cmd, "GET_BT_RX_RESULT") == 0) {
|
||||
printf("done: get bt rx total=%d, ok=%d, err=%d\n", *(unsigned int *)priv_cmd.buf,
|
||||
*(unsigned int *)&priv_cmd.buf[4],
|
||||
*(unsigned int *)&priv_cmd.buf[8]);
|
||||
} else if (strcasecmp(wl_cmd, "BT_DATA") == 0) {
|
||||
unsigned char *buff = (unsigned char *)&priv_cmd.buf[1];
|
||||
int len = priv_cmd.buf[0];
|
||||
printf("done: %d\n", len);
|
||||
for (idx = 0; idx < len; idx++) {
|
||||
printf("%02x ", buff[idx]);
|
||||
}
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("done\n");
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
int dev_open(){
|
||||
int n = 0;
|
||||
|
||||
bt_dev_fd = open(dev_path, O_RDWR | O_NDELAY);
|
||||
if(bt_dev_fd < 0) {
|
||||
printf("dev_path %s fail to open \r\n", dev_path);
|
||||
return ERR;
|
||||
}
|
||||
if(interface == UART){
|
||||
tcflush(bt_dev_fd, TCIOFLUSH);
|
||||
n = fcntl(bt_dev_fd, F_GETFL, 0);
|
||||
fcntl(bt_dev_fd, F_SETFL, n & ~O_NDELAY);
|
||||
uart_set_options(/*BAUDRATE*/atoi(s_baudrate), DATABITS, PARTY, STOP, SOFTWARE_HANDSHAKE, HARDWARE_HANDSHAKE);
|
||||
}else{
|
||||
ioctl(bt_dev_fd, DOWN_FW_CFG);
|
||||
ioctl(bt_dev_fd, GET_USB_INFO);
|
||||
}
|
||||
printf("bt dev open successful\r\n");
|
||||
return OK;
|
||||
}
|
||||
|
||||
void dev_close(){
|
||||
close(bt_dev_fd);
|
||||
}
|
||||
|
||||
|
||||
int socket_init(){
|
||||
int client;
|
||||
int server_socket;
|
||||
struct sockaddr_in server_addr;
|
||||
struct sockaddr_in clientAddr;
|
||||
int addr_len = sizeof(clientAddr);
|
||||
char buffer[SOCKER_BUFFER_SIZE];
|
||||
int recv_len = 0;
|
||||
|
||||
if((server_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0){
|
||||
return ERR;
|
||||
}
|
||||
|
||||
//bzero(&server_addr, sizeof(server_addr));
|
||||
memset(&server_addr, 0, sizeof(server_addr));
|
||||
server_addr.sin_family = AF_INET;
|
||||
server_addr.sin_port = htons(BT_HCI_TOOL_PORT);
|
||||
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
//setsockopt(server_socket ,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL));
|
||||
|
||||
if(bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0){
|
||||
printf("binding error\r\n");
|
||||
return ERR;
|
||||
}
|
||||
|
||||
if(listen(server_socket, 5) < 0){
|
||||
printf("listen error");
|
||||
return ERR;
|
||||
}
|
||||
|
||||
while(1){
|
||||
client = accept(server_socket, (struct sockaddr*)&clientAddr, (socklen_t*)&addr_len);
|
||||
if(client == ERR){
|
||||
return 0;
|
||||
}
|
||||
recv_len = recv(client, buffer, SOCKER_BUFFER_SIZE, 0);
|
||||
if ((interface == USB) || (interface == UART)) {
|
||||
hci_send(buffer, recv_len);
|
||||
} else {
|
||||
wlan_send(buffer, recv_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void* hci_recv_thread( void *arg ){
|
||||
printf("hci recv thread ready %p\r\n", arg);
|
||||
while(1){
|
||||
hci_recv(hci_event, sizeof(hci_event));
|
||||
// exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
void start_server(){
|
||||
int ret = ERR;
|
||||
if ((interface == USB) || (interface == UART)) {
|
||||
pthread_t hci_recv_th;
|
||||
//init bt communication
|
||||
ret = dev_open();
|
||||
if(ret == ERR){
|
||||
printf("dev_open fail \r\n");
|
||||
return;
|
||||
}
|
||||
//test to send reset
|
||||
printf("to test hci reset for bt device\r\n");
|
||||
hci_send(hci_reset, sizeof(hci_reset));
|
||||
hci_recv(hci_event, sizeof(hci_event));
|
||||
ret = pthread_create( &hci_recv_th, NULL, hci_recv_thread, NULL);
|
||||
printf("bt device test ok \r\n");
|
||||
} else if (interface == WLAN) {
|
||||
char buf[SOCKER_BUFFER_SIZE] = {"BT_RESET "};
|
||||
wlan_send(buf, strlen(buf));
|
||||
}
|
||||
|
||||
//init localhost socket
|
||||
ret = socket_init();
|
||||
if (!ret) {
|
||||
printf("socket init done\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
int ret = parse_cmd_line(argc, argv);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
if(server_or_client == SERVER){
|
||||
start_server();
|
||||
} else if (server_or_client == CLIENT) {
|
||||
send_hci_command();
|
||||
} else {
|
||||
send_wlan_command();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,426 @@
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
#include<stdlib.h>
|
||||
#include <errno.h>
|
||||
#define WIFI_DRIVER_FW_PATH "sta"
|
||||
#define WIFI_DRIVER_MODULE_NAME "rwnx_fdrv"
|
||||
#define WIFI_DRIVER_MODULE_PATH "/vendor/modules/rwnx_fdrv.ko"
|
||||
#define MAX_DRV_CMD_SIZE 1536
|
||||
#define TXRX_PARA SIOCDEVPRIVATE+1
|
||||
|
||||
#define EFUSE_CMD_OLD_FORMAT_EN 0
|
||||
|
||||
//static const char IFACE_DIR[] = "";
|
||||
//static const char DRIVER_MODULE_NAME[] = "rwnx_fdrv";
|
||||
//static const char DRIVER_MODULE_TAG[] = WIFI_DRIVER_MODULE_NAME " ";
|
||||
//static const char DRIVER_MODULE_PATH[] = WIFI_DRIVER_MODULE_PATH;
|
||||
//static const char DRIVER_MODULE_ARG[] = "";
|
||||
//static const char FIRMWARE_LOADER[] = "";
|
||||
//static const char DRIVER_PROP_NAME[] = "wlan.driver.status";
|
||||
|
||||
#ifndef TEMP_FAILURE_RETRY
|
||||
#define TEMP_FAILURE_RETRY(expression) \
|
||||
(__extension__ \
|
||||
({ long int __result; \
|
||||
do __result = (long int) (expression); \
|
||||
while (__result == -1L && errno == EINTR); \
|
||||
__result; }))
|
||||
#endif
|
||||
|
||||
typedef struct android_wifi_priv_cmd {
|
||||
char *buf;
|
||||
int used_len;
|
||||
int total_len;
|
||||
} android_wifi_priv_cmd;
|
||||
typedef struct cob_result_ptr_t {
|
||||
u_int16_t dut_rcv_golden_num;
|
||||
u_int8_t golden_rcv_dut_num;
|
||||
int8_t rssi_static;
|
||||
int8_t snr_static;
|
||||
int8_t dut_rssi_static;
|
||||
u_int16_t reserved;
|
||||
}cob_result_ptr_t;
|
||||
int wifi_send_cmd_to_net_interface(const char* if_name, int argC, char *argV[])
|
||||
{
|
||||
int sock;
|
||||
struct ifreq ifr;
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
char buf[MAX_DRV_CMD_SIZE];
|
||||
struct android_wifi_priv_cmd priv_cmd;
|
||||
struct cob_result_ptr_t *cob_result_ptr;
|
||||
char is_param_err = 0;
|
||||
int buf_len = 0;
|
||||
int idx = 0;
|
||||
|
||||
sock = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (sock < 0) {
|
||||
printf("bad sock!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strcpy(ifr.ifr_name, if_name);
|
||||
|
||||
if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
|
||||
printf("%s Could not read interface %s flags: %s",__func__, if_name, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(ifr.ifr_flags & IFF_UP)) {
|
||||
printf("%s is not up!\n",if_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// printf("ifr.ifr_name = %s\n", ifr.ifr_name);
|
||||
memset(&priv_cmd, 0, sizeof(priv_cmd));
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
for(i=2; i<argC; i++){
|
||||
strcat(buf, argV[i]);
|
||||
strcat(buf, " ");
|
||||
}
|
||||
|
||||
priv_cmd.buf = buf;
|
||||
priv_cmd.used_len = strlen(buf);
|
||||
priv_cmd.total_len = sizeof(buf);
|
||||
ifr.ifr_data = (void*)&priv_cmd;
|
||||
|
||||
printf("%s:\n", argV[2]);
|
||||
if (strcasecmp(argV[2], "SET_TX") == 0) {
|
||||
if (argC < 8) {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if (strcasecmp(argV[2], "SET_TXTONE") == 0) {
|
||||
if (((argC == 4) && (argV[3][0] != '0'))
|
||||
|| ((argC == 5) && (argV[3][0] == '0'))) {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(argV[2], "SET_RX") == 0)
|
||||
|| (strcasecmp(argV[2], "SET_POWER") == 0)
|
||||
|| (strcasecmp(argV[2], "SET_COB_CAL") == 0)) {
|
||||
if (argC < 5) {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(argV[2], "SET_XTAL_CAP") == 0)
|
||||
|| (strcasecmp(argV[2], "SET_XTAL_CAP_FINE") == 0)) {
|
||||
if (argC < 4) {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(argV[2], "GET_EFUSE_BLOCK") == 0)
|
||||
|| (strcasecmp(argV[2], "SET_FREQ_CAL") == 0)
|
||||
|| (strcasecmp(argV[2], "SET_FREQ_CAL_FINE") == 0)) {
|
||||
if (argC < 4) {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(argV[2], "SET_MAC_ADDR") == 0)
|
||||
|| (strcasecmp(argV[2], "SET_BT_MAC_ADDR") == 0)) {
|
||||
if (argC < 8) {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if (strcasecmp(argV[2], "SET_VENDOR_INFO") == 0) {
|
||||
if (argC < 4) {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if (strcasecmp(argV[2], "GET_VENDOR_INFO") == 0) {
|
||||
if (argC < 3) {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(argV[2], "RDWR_PWRIDX") == 0)
|
||||
|| (strcasecmp(argV[2], "RDWR_PWRLVL") == 0)
|
||||
|| (strcasecmp(argV[2], "RDWR_PWROFST") == 0)
|
||||
|| (strcasecmp(argV[2], "RDWR_EFUSE_PWROFST") == 0)) {
|
||||
if (((argC == 4) && (argV[3][0] != '0'))
|
||||
|| (argC == 5)
|
||||
|| ((argC == 6) && (argV[3][0] == '0'))) {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(argV[2], "RDWR_DRVIBIT") == 0)
|
||||
|| (strcasecmp(argV[2], "RDWR_EFUSE_DRVIBIT") == 0)) {
|
||||
if (((argC == 4) && (argV[3][0] != '0'))
|
||||
|| ((argC == 5) && (argV[3][0] == '0'))) {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(argV[2], "SET_PAPR") == 0)) {
|
||||
if (argC < 4) {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(argV[2], "BT_RESET") == 0)) {
|
||||
char bt_reset_hci_cmd[32] = "01 03 0c 00";
|
||||
if (argC == 3) {
|
||||
buf_len = priv_cmd.used_len;
|
||||
memcpy(&priv_cmd.buf[buf_len], &bt_reset_hci_cmd[0], strlen(bt_reset_hci_cmd));
|
||||
buf_len += strlen(bt_reset_hci_cmd);
|
||||
priv_cmd.used_len = buf_len;
|
||||
} else {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(argV[2], "BT_TXDH") == 0)) {
|
||||
char bt_txdh_hci_cmd[255] = "01 06 18 0e ";
|
||||
if (argC == 17) {
|
||||
buf_len = priv_cmd.used_len;
|
||||
int arg_len = strlen(argV[2]);
|
||||
int txdh_cmd_len = strlen(bt_txdh_hci_cmd);
|
||||
memcpy(&bt_txdh_hci_cmd[txdh_cmd_len], &priv_cmd.buf[arg_len+1], buf_len - arg_len - 1);
|
||||
memcpy(&priv_cmd.buf[arg_len+1], &bt_txdh_hci_cmd[0], strlen(bt_txdh_hci_cmd));
|
||||
buf_len += strlen(bt_txdh_hci_cmd);
|
||||
priv_cmd.used_len = buf_len;
|
||||
} else {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(argV[2], "BT_RXDH") == 0)) {
|
||||
if (argC == 16) {
|
||||
char bt_rxdh_hci_cmd[255] = "01 0b 18 0d ";
|
||||
buf_len = priv_cmd.used_len;
|
||||
int arg_len = strlen(argV[2]);
|
||||
int rxdh_cmd_len = strlen(bt_rxdh_hci_cmd);
|
||||
memcpy(&bt_rxdh_hci_cmd[rxdh_cmd_len], &priv_cmd.buf[arg_len+1], buf_len - arg_len - 1);
|
||||
memcpy(&priv_cmd.buf[arg_len+1], &bt_rxdh_hci_cmd[0], strlen(bt_rxdh_hci_cmd));
|
||||
buf_len += strlen(bt_rxdh_hci_cmd);
|
||||
priv_cmd.used_len = buf_len;
|
||||
} else {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(argV[2], "BT_STOP") == 0)) {
|
||||
char bt_stop_hci_cmd[255] = "01 0C 18 01 ";
|
||||
if (argC == 4) {
|
||||
buf_len = priv_cmd.used_len;
|
||||
int arg_len = strlen(argV[2]);
|
||||
int stop_cmd_len = strlen(bt_stop_hci_cmd);
|
||||
memcpy(&bt_stop_hci_cmd[stop_cmd_len], &priv_cmd.buf[arg_len+1], buf_len - arg_len - 1);
|
||||
memcpy(&priv_cmd.buf[arg_len+1], &bt_stop_hci_cmd[0], strlen(bt_stop_hci_cmd));
|
||||
buf_len += strlen(bt_stop_hci_cmd);
|
||||
priv_cmd.used_len = buf_len;
|
||||
} else {
|
||||
is_param_err = 1;
|
||||
}
|
||||
} else if ((strcasecmp(argV[2], "BT_DATA") == 0)) {
|
||||
//char bt_raw_data_cmd[255];
|
||||
int arg_len = strlen(argV[2]);
|
||||
buf_len = priv_cmd.used_len;
|
||||
memcpy(&priv_cmd.buf[arg_len+1], &priv_cmd.buf[arg_len+1], buf_len - arg_len - 1);
|
||||
priv_cmd.used_len = buf_len - arg_len - 1;
|
||||
} else {
|
||||
is_param_err = 0;
|
||||
}
|
||||
|
||||
if (is_param_err) {
|
||||
printf("param error!!!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((ret = ioctl(sock, TXRX_PARA, &ifr)) < 0) {
|
||||
printf("cmd or param error\n");
|
||||
printf("%s: error ioctl[TX_PARA] ret= %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
memcpy(&priv_cmd, ifr.ifr_data, sizeof(struct android_wifi_priv_cmd));
|
||||
if (strcasecmp(argV[2], "SET_FREQ_CAL") == 0) {
|
||||
#if (EFUSE_CMD_OLD_FORMAT_EN)
|
||||
printf("done: freq_cal: 0x%8x\n", *(unsigned int *)priv_cmd.buf);
|
||||
#else
|
||||
signed char rem_cnt = (signed char)priv_cmd.buf[1];
|
||||
if (rem_cnt < 0) {
|
||||
printf("failed to set freq_cal, no room!\n");
|
||||
} else {
|
||||
printf("done: freq_cal: 0x%2x (remain:%x)\n", (unsigned char)priv_cmd.buf[0], rem_cnt);
|
||||
}
|
||||
#endif
|
||||
} else if (strcasecmp(argV[2], "SET_FREQ_CAL_FINE") == 0) {
|
||||
#if (EFUSE_CMD_OLD_FORMAT_EN)
|
||||
printf("done: freq_cal_fine: 0x%8x\n", *(unsigned int *)priv_cmd.buf);
|
||||
#else
|
||||
signed char rem_cnt = (signed char)priv_cmd.buf[1];
|
||||
if (rem_cnt < 0) {
|
||||
printf("failed to set freq_cal_fine, no room!\n");
|
||||
} else {
|
||||
printf("done: freq_cal_fine: 0x%2x (remain:%x)\n", (unsigned char)priv_cmd.buf[0], rem_cnt);
|
||||
}
|
||||
#endif
|
||||
} else if (strcasecmp(argV[2], "GET_EFUSE_BLOCK") == 0)
|
||||
printf("done:efuse: 0x%8x\n", *(unsigned int *)priv_cmd.buf);
|
||||
else if (strcasecmp(argV[2], "SET_XTAL_CAP") == 0)
|
||||
printf("done:xtal cap: 0x%x\n", *(unsigned int *)priv_cmd.buf);
|
||||
else if (strcasecmp(argV[2], "SET_XTAL_CAP_FINE") == 0)
|
||||
printf("done:xtal cap fine: 0x%x\n", *(unsigned int *)priv_cmd.buf);
|
||||
else if (strcasecmp(argV[2], "GET_RX_RESULT") == 0)
|
||||
printf("done: getrx fcsok=%d, total=%d\n", *(unsigned int *)priv_cmd.buf, *(unsigned int *)&priv_cmd.buf[4]);
|
||||
else if (strcasecmp(argV[2], "GET_MAC_ADDR") == 0) {
|
||||
printf("done: get macaddr = %02x : %02x : %02x : %02x : %02x : %02x\n",
|
||||
*(unsigned char *)&priv_cmd.buf[5], *(unsigned char *)&priv_cmd.buf[4], *(unsigned char *)&priv_cmd.buf[3],
|
||||
*(unsigned char *)&priv_cmd.buf[2], *(unsigned char *)&priv_cmd.buf[1], *(unsigned char *)&priv_cmd.buf[0]);
|
||||
#if (!EFUSE_CMD_OLD_FORMAT_EN)
|
||||
printf(" (remain:%x)\n", priv_cmd.buf[6]);
|
||||
#endif
|
||||
} else if (strcasecmp(argV[2], "GET_BT_MAC_ADDR") == 0) {
|
||||
printf("done: get bt macaddr = %02x : %02x : %02x : %02x : %02x : %02x\n",
|
||||
*(unsigned char *)&priv_cmd.buf[5], *(unsigned char *)&priv_cmd.buf[4], *(unsigned char *)&priv_cmd.buf[3],
|
||||
*(unsigned char *)&priv_cmd.buf[2], *(unsigned char *)&priv_cmd.buf[1], *(unsigned char *)&priv_cmd.buf[0]);
|
||||
#if (!EFUSE_CMD_OLD_FORMAT_EN)
|
||||
printf(" (remain:%x)\n", priv_cmd.buf[6]);
|
||||
#endif
|
||||
} else if (strcasecmp(argV[2], "GET_FREQ_CAL") == 0) {
|
||||
#if (EFUSE_CMD_OLD_FORMAT_EN)
|
||||
printf("done: get_freq_cal: xtal_cap=0x%x, xtal_cap_fine=0x%x\n", val & 0x000000ff, (val >> 8) & 0x000000ff);
|
||||
#else
|
||||
unsigned int val = *(unsigned int *)&priv_cmd.buf[0];
|
||||
printf("done: get_freq_cal: xtal_cap=0x%x (remain:%x), xtal_cap_fine=0x%x (remain:%x)\n",
|
||||
val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff, (val >> 24) & 0xff);
|
||||
#endif
|
||||
} else if (strcasecmp(argV[2], "GET_VENDOR_INFO") == 0) {
|
||||
#if (EFUSE_CMD_OLD_FORMAT_EN)
|
||||
printf("done: get_vendor_info = 0x%x\n", *(unsigned char *)&priv_cmd.buf[0]);
|
||||
#else
|
||||
printf("done: get_vendor_info = 0x%x (remain:%x)\n", *(unsigned char *)&priv_cmd.buf[0], priv_cmd.buf[1]);
|
||||
#endif
|
||||
} else if (strcasecmp(argV[2], "RDWR_PWRMM") == 0) {
|
||||
printf("done: txpwr manual mode = %x\n", *(unsigned int *)&priv_cmd.buf[0]);
|
||||
} else if (strcasecmp(argV[2], "RDWR_PWRIDX") == 0) {
|
||||
char *buff = &priv_cmd.buf[0];
|
||||
printf("done:\n"
|
||||
"txpwr index 2.4g:\n"
|
||||
" [0]=%d(ofdmlowrate)\n"
|
||||
" [1]=%d(ofdm64qam)\n"
|
||||
" [2]=%d(ofdm256qam)\n"
|
||||
" [3]=%d(ofdm1024qam)\n"
|
||||
" [4]=%d(dsss)\n", buff[0], buff[1], buff[2], buff[3], buff[4]);
|
||||
printf("txpwr index 5g:\n"
|
||||
" [0]=%d(ofdmlowrate)\n"
|
||||
" [1]=%d(ofdm64qam)\n"
|
||||
" [2]=%d(ofdm256qam)\n"
|
||||
" [3]=%d(ofdm1024qam)\n", buff[5], buff[6], buff[7], buff[8]);
|
||||
} else if (strcasecmp(argV[2], "RDWR_PWRLVL") == 0) {
|
||||
char *buff = &priv_cmd.buf[0];
|
||||
int grp, idx;
|
||||
printf("done:\n"
|
||||
"txpwr index 2.4g: [0]:11b+11a/g, [1]:11n/11ac, [2]:11ax\n");
|
||||
for (grp = 0; grp < 3; grp++) {
|
||||
int cnt = 12;
|
||||
if (grp == 1) {
|
||||
cnt = 10;
|
||||
}
|
||||
printf(" [%x] =", grp);
|
||||
for (idx = 0; idx < cnt; idx++) {
|
||||
if (idx && !(idx & 0x3)) {
|
||||
printf(" ");
|
||||
}
|
||||
printf(" %2d", buff[12 * grp + idx]);
|
||||
}
|
||||
printf("\r\n");
|
||||
}
|
||||
} else if (strcasecmp(argV[2], "RDWR_PWROFST") == 0) {
|
||||
char *buff = &priv_cmd.buf[0];
|
||||
|
||||
printf("done:\n"
|
||||
"txpwr offset 2.4g: \n"
|
||||
" [0]=%d(ch1~4)\n"
|
||||
" [1]=%d(ch5~9)\n"
|
||||
" [2]=%d(ch10~13)\n", (int8_t)buff[0], (int8_t)buff[1], (int8_t)buff[2]);
|
||||
printf("txpwr offset 5g:\n"
|
||||
" [0]=%d(ch36~64)\n"
|
||||
" [1]=%d(ch100~120)\n"
|
||||
" [2]=%d(ch122~140)\n"
|
||||
" [3]=%d(ch142~165)\n", (int8_t)buff[3], (int8_t)buff[4], (int8_t)buff[5], (int8_t)buff[6]);
|
||||
} else if (strcasecmp(argV[2], "RDWR_DRVIBIT") == 0) {
|
||||
char *buff = &priv_cmd.buf[0];
|
||||
printf("done: 2.4g txgain tbl pa drv_ibit:\n");
|
||||
for (idx = 0; idx < 16; idx++) {
|
||||
printf(" %x", buff[idx]);
|
||||
if (!((idx + 1) & 0x03)) {
|
||||
printf(" [%x~%x]\n", idx - 3, idx);
|
||||
}
|
||||
}
|
||||
} else if (strcasecmp(argV[2], "RDWR_EFUSE_PWROFST") == 0) {
|
||||
char *buff = &priv_cmd.buf[0];
|
||||
#if (EFUSE_CMD_OLD_FORMAT_EN)
|
||||
printf("done:\n"
|
||||
"efuse txpwr offset 2.4g:\n"
|
||||
" [0]=%d(ch1~4)\n"
|
||||
" [1]=%d(ch5~9)\n"
|
||||
" [2]=%d(ch10~13)\n", (int8_t)buff[0], (int8_t)buff[1], (int8_t)buff[2]);
|
||||
printf("efuse txpwr offset 5g:\n"
|
||||
" [0]=%d(ch36~64)\n"
|
||||
" [1]=%d(ch100~120)\n"
|
||||
" [2]=%d(ch122~140)\n"
|
||||
" [3]=%d(ch142~165)\n", (int8_t)buff[3], (int8_t)buff[4], (int8_t)buff[5], (int8_t)buff[6]);
|
||||
#else
|
||||
printf("done:\n"
|
||||
"efuse txpwr offset 2.4g:\n"
|
||||
" [0]=%d(remain:%x, ch1~4)\n"
|
||||
" [1]=%d(remain:%x, ch5~9)\n"
|
||||
" [2]=%d(remain:%x, ch10~13)\n",
|
||||
(int8_t)buff[0], (int8_t)buff[3],
|
||||
(int8_t)buff[1], (int8_t)buff[4],
|
||||
(int8_t)buff[2], (int8_t)buff[5]);
|
||||
if (ret > 6) { // 5g_en
|
||||
printf("efuse txpwr offset 5g:\n"
|
||||
" [0]=%d(remain:%x, ch36~64)\n"
|
||||
" [1]=%d(remain:%x, ch100~120)\n"
|
||||
" [2]=%d(remain:%x, ch122~140)\n"
|
||||
" [3]=%d(remain:%x, ch142~165)\n",
|
||||
(int8_t)buff[6], (int8_t)buff[10],
|
||||
(int8_t)buff[7], (int8_t)buff[11],
|
||||
(int8_t)buff[8], (int8_t)buff[12],
|
||||
(int8_t)buff[9], (int8_t)buff[13]);
|
||||
}
|
||||
#endif
|
||||
} else if (strcasecmp(argV[2], "RDWR_EFUSE_DRVIBIT") == 0) {
|
||||
#if (EFUSE_CMD_OLD_FORMAT_EN)
|
||||
printf("done: efsue 2.4g txgain tbl pa drv_ibit: %x\n", priv_cmd.buf[0]);
|
||||
#else
|
||||
int val = *(int *)&priv_cmd.buf[0];
|
||||
if (val < 0) {
|
||||
printf("failed to rd/wr efuse drv_ibit, ret=%d\n", val);
|
||||
} else {
|
||||
printf("done: efsue 2.4g txgain tbl pa drv_ibit: %x (remain: %x)\n", priv_cmd.buf[0], priv_cmd.buf[1]);
|
||||
}
|
||||
#endif
|
||||
} else if (strcasecmp(argV[2], "GET_CAL_XTAL_RES") == 0) {
|
||||
unsigned int val = *(unsigned int *)&priv_cmd.buf[0];
|
||||
printf("done: get_cal_xtal_res: cap=0x%x, cap_fine=0x%x\n", val & 0x000000ff, (val >> 8) & 0x000000ff);
|
||||
} else if ((strcasecmp(argV[2], "GET_COB_CAL_RES") == 0) || (strcasecmp(argV[2], "DO_COB_TEST") == 0)){
|
||||
unsigned int val = *(unsigned int *)&priv_cmd.buf[0];
|
||||
unsigned int val0 = *(unsigned int *)&priv_cmd.buf[4];
|
||||
cob_result_ptr = (cob_result_ptr_t *) (unsigned int *)&priv_cmd.buf[8];
|
||||
printf("done:\ncap= 0x%x cap_fine= 0x%x freq_ofst= %d Hz golden_rcv_dut= %d tx_rssi= %d dBm snr= %d dB dut_rcv_godlden= %d rx_rssi= %d dBm\n",
|
||||
val & 0x000000ff, (val >> 8) & 0x000000ff, val0, cob_result_ptr->golden_rcv_dut_num, cob_result_ptr->rssi_static, cob_result_ptr->snr_static, cob_result_ptr->dut_rcv_golden_num, cob_result_ptr->dut_rssi_static);
|
||||
} else if (strcasecmp(argV[2], "GET_BT_RX_RESULT") == 0) {
|
||||
printf("done: get bt rx total=%d, ok=%d, err=%d\n", *(unsigned int *)priv_cmd.buf,
|
||||
*(unsigned int *)&priv_cmd.buf[4],
|
||||
*(unsigned int *)&priv_cmd.buf[8]);
|
||||
} else if (strcasecmp(argV[2], "BT_DATA") == 0) {
|
||||
unsigned char *buff = (unsigned char *)&priv_cmd.buf[1];
|
||||
int len = priv_cmd.buf[0];
|
||||
printf("done: %d\n", len);
|
||||
for (idx = 0; idx < len; idx++) {
|
||||
printf("%02x ", buff[idx]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
else {
|
||||
printf("done\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argC, char *argV[])
|
||||
{
|
||||
|
||||
//char* ins = "insmod";
|
||||
//char* rm = "rmmod";
|
||||
//char* ko = "rwnx_fdrv.ko";
|
||||
|
||||
// printf("enter!!!AIC argC=%d argV[0]=%s argV[1]=%s argV[2]=%s\n", argC, argV[0], argV[1],argV[2]);
|
||||
if(argC >= 3)
|
||||
wifi_send_cmd_to_net_interface(argV[1], argC, argV);
|
||||
else
|
||||
printf("Bad parameter! %d\n",argC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
config AIC_WLAN_SUPPORT
|
||||
bool "AIC wireless Support"
|
||||
default n
|
||||
help
|
||||
This is support for aic wireless chip.
|
||||
|
||||
if AIC_WLAN_SUPPORT
|
||||
source "drivers/net/wireless/aic8800/aic8800_fdrv/Kconfig"
|
||||
source "drivers/net/wireless/aic8800/aic_load_fw/Kconfig"
|
||||
endif
|
||||
@@ -0,0 +1,80 @@
|
||||
CONFIG_AIC_LOADFW_SUPPORT := m
|
||||
CONFIG_AIC8800_WLAN_SUPPORT := m
|
||||
|
||||
obj-$(CONFIG_AIC_LOADFW_SUPPORT) += aic_load_fw/
|
||||
obj-$(CONFIG_AIC8800_WLAN_SUPPORT) += aic8800_fdrv/
|
||||
|
||||
########## config option ##########
|
||||
export CONFIG_USE_FW_REQUEST = n
|
||||
export CONFIG_PREALLOC_RX_SKB = n
|
||||
export CONFIG_PREALLOC_TXQ = y
|
||||
###################################
|
||||
|
||||
########## platform support list ##########
|
||||
export CONFIG_PLATFORM_ROCKCHIP = n
|
||||
export CONFIG_PLATFORM_ALLWINNER = n
|
||||
export CONFIG_PLATFORM_AMLOGIC = n
|
||||
export CONFIG_PLATFORM_HI = n
|
||||
export CONFIG_PLATFORM_UBUNTU = y
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y)
|
||||
ARCH = arm64
|
||||
KDIR = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel
|
||||
CROSS_COMPILE = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
|
||||
ccflags-y += -DANDROID_PLATFORM
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_ALLWINNER), y)
|
||||
KDIR = /home/yaya/E/Allwinner/R818/R818/AndroidQ/lichee/kernel/linux-4.9
|
||||
ARCH = arm64
|
||||
CROSS_COMPILE = /home/yaya/E/Allwinner/R818/R818/AndroidQ/lichee/out/gcc-linaro-5.3.1-2016.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
|
||||
ccflags-y += -DANDROID_PLATFORM
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_AMLOGIC), y)
|
||||
ccflags-y += -DANDROID_PLATFORM
|
||||
ARCH = arm
|
||||
CROSS_COMPILE = /home/yaya/D/Workspace/CyberQuantum/JinHaoYue/amls905x3/SDK/20191101-0tt-asop/android9.0/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androidkernel-
|
||||
KDIR = /home/yaya/D/Workspace/CyberQuantum/JinHaoYue/amls905x3/SDK/20191101-0tt-asop/android9.0/out/target/product/u202/obj/KERNEL_OBJ/
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_HI), y)
|
||||
ccflags-y += -DANDROID_PLATFORM
|
||||
ARCH = arm
|
||||
CROSS_COMPILE = /home/yaya/D/Workspace/CyberQuantum/JinHaoYue/amls905x3/SDK/20191101-0tt-asop/android9.0/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androidkernel-
|
||||
KDIR = /home/yaya/D/Workspace/CyberQuantum/JinHaoYue/amls905x3/SDK/20191101-0tt-asop/android9.0/out/target/product/u202/obj/KERNEL_OBJ/
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_UBUNTU), y)
|
||||
KDIR = /lib/modules/$(shell uname -r)/build
|
||||
PWD = $(shell pwd)
|
||||
KVER = $(shell uname -r)
|
||||
MODDESTDIR = /lib/modules/$(KVER)/kernel/drivers/net/wireless/aic8800
|
||||
SUBARCH = $(shell uname -m | sed -e s/i.86/i386/ -e s/armv.l/arm/ -e s/aarch64/arm64/)
|
||||
ARCH ?= $(SUBARCH)
|
||||
CROSS_COMPILE ?=
|
||||
endif
|
||||
|
||||
###########################################
|
||||
|
||||
MAKEFLAGS +=-j$(shell nproc)
|
||||
|
||||
all: modules
|
||||
modules:
|
||||
make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
|
||||
|
||||
install:
|
||||
mkdir -p $(MODDESTDIR)
|
||||
install -p -m 644 aic_load_fw/aic_load_fw.ko $(MODDESTDIR)/
|
||||
install -p -m 644 aic8800_fdrv/aic8800_fdrv.ko $(MODDESTDIR)/
|
||||
/sbin/depmod -a ${KVER}
|
||||
|
||||
uninstall:
|
||||
rm -rfv $(MODDESTDIR)/aic_load_fw.ko
|
||||
rm -rfv $(MODDESTDIR)/aic8800_fdrv.ko
|
||||
/sbin/depmod -a ${KVER}
|
||||
|
||||
clean:
|
||||
cd aic_load_fw/;make clean;cd ..
|
||||
cd aic8800_fdrv/;make clean;cd ..
|
||||
rm -rf modules.order Module.symvers .modules.order.cmd .Module.symvers.cmd .tmp_versions/
|
||||
@@ -0,0 +1,36 @@
|
||||
config AIC8800_WLAN_SUPPORT
|
||||
tristate "AIC8800 wlan Support"
|
||||
help
|
||||
This is support for aic wifi driver.
|
||||
|
||||
#choice
|
||||
# depends on AIC8800_WLAN_SUPPORT
|
||||
# prompt "Select 8800 support platform"
|
||||
#
|
||||
# config PLATFORM_ROCHCHIP
|
||||
# bool "PLATFORM_ROCHCHIP"
|
||||
# depends on AIC8800_WLAN_SUPPORT
|
||||
#
|
||||
# config PLATFORM_ALLWINNER
|
||||
# bool "PLATFORM_ALLWINNER"
|
||||
# depends on AIC8800_WLAN_SUPPORT
|
||||
#
|
||||
# config PLATFORM_AMLOGIC
|
||||
# bool "PLATFORM_AMLOGIC"
|
||||
# depends on AIC8800_WLAN_SUPPORT
|
||||
#
|
||||
# config PLATFORM_UBUNTU
|
||||
# bool "PLATFORM_UBUNTU"
|
||||
# depends on AIC8800_WLAN_SUPPORT
|
||||
#
|
||||
#endchoice
|
||||
#
|
||||
#config USE_5G
|
||||
# bool "AIC8800 force enable 5G"
|
||||
# ---help---
|
||||
# This is parameter that force enable 5G.
|
||||
#
|
||||
#config HE_FOR_OLD_KERNEL
|
||||
# bool "AIC8800 support AX for old kernel"
|
||||
# ---help---
|
||||
# This is parameter that enable AX for old kernel.
|
||||
@@ -0,0 +1,384 @@
|
||||
EXTRA_CFLAGS += $(USER_EXTRA_CFLAGS)
|
||||
EXTRA_CFLAGS += -Wno-implicit-fallthrough
|
||||
#EXTRA_CFLAGS += -Wno-unused-variable
|
||||
|
||||
RWNX_VERS_NUM := 6.4.3.0
|
||||
|
||||
CONFIG_AIC8800_WLAN_SUPPORT = m
|
||||
MODULE_NAME = aic8800_fdrv
|
||||
CONFIG_COUNTRY_CODE = "00"
|
||||
|
||||
# Support of bootrom start
|
||||
CONFIG_START_FROM_BOOTROM = y
|
||||
|
||||
# Support of pmic setting, new version bootrom avaliable
|
||||
CONFIG_PMIC_SETTING ?=n
|
||||
|
||||
# Select 8800DC/DW DCDC_VRF mode, check your board
|
||||
CONFIG_VRF_DCDC_MODE = y
|
||||
|
||||
# ROM patch enabled option
|
||||
CONFIG_ROM_PATCH_EN ?=y
|
||||
|
||||
#
|
||||
# WAITING FOR KCONFIG {
|
||||
#
|
||||
CONFIG_RWNX_SOFTMAC ?= n
|
||||
CONFIG_RWNX_FULLMAC ?= y
|
||||
CONFIG_RWNX_FHOST ?= n
|
||||
|
||||
#
|
||||
# DEBUG OPTIONS
|
||||
CONFIG_RWNX_UM_HELPER_DFLT ?= "/dini/dini_bin/rwnx_umh.sh"
|
||||
CONFIG_AIC_FW_PATH = "/vendor/etc/firmware"
|
||||
export CONFIG_AIC_FW_PATH
|
||||
|
||||
#
|
||||
# FW ARCH:
|
||||
CONFIG_RWNX_SDM ?= n
|
||||
CONFIG_RWNX_TL4 ?= n
|
||||
|
||||
# IPC version
|
||||
CONFIG_RWNX_OLD_IPC ?= n
|
||||
|
||||
# Support of P2P DebugFS for enabling/disabling NoA and OppPS
|
||||
CONFIG_RWNX_P2P_DEBUGFS ?= y
|
||||
|
||||
#
|
||||
# } // WAITING FOR KCONFIG
|
||||
#
|
||||
|
||||
# Enable A-MSDU support (need FW support)
|
||||
## Select this if FW is compiled with AMSDU support
|
||||
CONFIG_RWNX_SPLIT_TX_BUF ?= n
|
||||
## Select this TO send AMSDU
|
||||
CONFIG_RWNX_AMSDUS_TX ?= n
|
||||
|
||||
# Enable BFMER support (need FW support)
|
||||
CONFIG_RWNX_BFMER ?= n
|
||||
|
||||
CONFIG_SDIO_SUPPORT =n
|
||||
CONFIG_USB_SUPPORT =y
|
||||
CONFIG_RX_REORDER =y
|
||||
CONFIG_ARP_OFFLOAD =y
|
||||
CONFIG_USE_5G = y
|
||||
CONFIG_RADAR_OR_IR_DETECT =n
|
||||
CONFIG_DOWNLOAD_FW =n
|
||||
CONFIG_RFTEST=y
|
||||
CONFIG_USB_BT=y
|
||||
CONFIG_MAC_RANDOM_IF_NO_MAC_IN_EFUSE = y
|
||||
CONFIG_WPA3_FOR_OLD_KERNEL = n
|
||||
CONFIG_HE_FOR_OLD_KERNEL = n
|
||||
CONFIG_VHT_FOR_OLD_KERNEL = n
|
||||
# CONFIG_COEX = n for BT_ONLY, CONFIG_COEX =y for combo and sw
|
||||
CONFIG_COEX = y
|
||||
CONFIG_ALIGN_8BYTES = y
|
||||
CONFIG_TXRX_THREAD_PRIO = y
|
||||
CONFIG_USB_ALIGN_DATA = y
|
||||
CONFIG_RX_TASKLET = n
|
||||
CONFIG_TX_TASKLET = n
|
||||
CONFIG_RX_NETIF_RECV_SKB = y
|
||||
CONFIG_BR_SUPPORT = n
|
||||
CONFIG_USB_MSG_OUT_EP = y
|
||||
CONFIG_USB_MSG_IN_EP = y
|
||||
CONFIG_USB_RX_REASSEMBLE = n
|
||||
|
||||
#DCDW support tx aggr, D80 support both
|
||||
CONFIG_USB_RX_AGGR = n
|
||||
CONFIG_USB_TX_AGGR = n
|
||||
|
||||
CONFIG_USB_NO_TRANS_DMA_MAP = n
|
||||
CONFIG_GPIO_WAKEUP = n
|
||||
CONFIG_CREATE_TRACE_POINTS = n
|
||||
CONFIG_SUPPORT_REALTIME_CHANGE_MAC = y
|
||||
CONFIG_USE_USB_ZERO_PACKET = y
|
||||
CONFIG_DEBUG_FS = n
|
||||
CONFIG_STA_SCAN_WHEN_P2P_WORKING = y
|
||||
CONFIG_SET_VENDOR_EXTENSION_IE = n
|
||||
CONFIG_VENDOR_GPIO = n
|
||||
CONFIG_FWLOG_EN = n
|
||||
CONFIG_FOR_IPCAM = n
|
||||
CONFIG_5M10M = n
|
||||
# Need to set fw path in BOARD_KERNEL_CMDLINE
|
||||
CONFIG_USE_FW_REQUEST ?= n
|
||||
CONFIG_USE_P2P0 = n
|
||||
CONFIG_ONE_TXQ = n
|
||||
CONFIG_PER_STA_FC = n
|
||||
CONFIG_PREALLOC_RX_SKB ?= n
|
||||
CONFIG_PREALLOC_TXQ ?= y
|
||||
CONFIG_USE_WIRELESS_EXT = y
|
||||
CONFIG_DPD = y
|
||||
CONFIG_FORCE_DPD_CALIB = y
|
||||
CONFIG_GKI = n
|
||||
CONFIG_SCHED_SCAN = n
|
||||
CONFIG_TEMP_COMP = n
|
||||
CONFIG_POWER_LIMIT = n
|
||||
# CONFIG_MCC = n for sta and p2p concurrent in same channel.
|
||||
CONFIG_MCC = y
|
||||
CONFIG_LOAD_BT_PATCH_IN_FDRV = n
|
||||
|
||||
ifneq ($(CONFIG_WIRELESS_EXT), y)
|
||||
CONFIG_USE_WIRELESS_EXT = n
|
||||
endif
|
||||
|
||||
# Support of MU-MIMO transmission (need FW support)
|
||||
ifeq ($(CONFIG_RWNX_BFMER), y)
|
||||
CONFIG_RWNX_MUMIMO_TX ?= n
|
||||
else
|
||||
CONFIG_RWNX_MUMIMO_TX = n
|
||||
endif
|
||||
|
||||
# Enable handling of radar event
|
||||
CONFIG_RWNX_RADAR ?= y
|
||||
|
||||
# Enable HW queue for Broadcast/Multicast traffic (need FW support)
|
||||
CONFIG_RWNX_BCMC ?= y
|
||||
|
||||
# Enable Monitor+Data interface support (need FW support)
|
||||
CONFIG_RWNX_MON_DATA =n
|
||||
CONFIG_RWNX_MON_XMIT ?= n
|
||||
CONFIG_RWNX_MON_RXFILTER ?= n
|
||||
|
||||
CONFIG_FILTER_TCP_ACK =y
|
||||
|
||||
# extra DEBUG config
|
||||
CONFIG_RWNX_SW_PROFILING ?= n
|
||||
CONFIG_RWNX_DBG ?= y
|
||||
BR_NAME = br0
|
||||
|
||||
obj-$(CONFIG_AIC8800_WLAN_SUPPORT) := $(MODULE_NAME).o
|
||||
$(MODULE_NAME)-y := \
|
||||
rwnx_msg_tx.o \
|
||||
rwnx_msg_rx.o \
|
||||
rwnx_utils.o \
|
||||
rwnx_cmds.o \
|
||||
rwnx_irqs.o \
|
||||
rwnx_cfgfile.o \
|
||||
rwnx_strs.o \
|
||||
rwnx_rx.o \
|
||||
rwnx_tx.o \
|
||||
rwnx_txq.o \
|
||||
rwnx_main.o \
|
||||
rwnx_mod_params.o \
|
||||
rwnx_mesh.o \
|
||||
rwnx_platform.o \
|
||||
rwnx_pci.o \
|
||||
rwnx_dini.o \
|
||||
rwnx_v7.o \
|
||||
ipc_host.o \
|
||||
rwnx_tdls.o \
|
||||
regdb.o \
|
||||
md5.o \
|
||||
aic_vendor.o \
|
||||
aic_priv_cmd.o \
|
||||
aicwf_compat_8800dc.o \
|
||||
aicwf_compat_8800d80.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
|
||||
$(MODULE_NAME)-$(CONFIG_DEBUG_FS) += rwnx_fw_trace.o
|
||||
$(MODULE_NAME)-$(CONFIG_NL80211_TESTMODE) += rwnx_testmode.o
|
||||
$(MODULE_NAME)-$(CONFIG_RWNX_BFMER) += rwnx_bfmer.o
|
||||
$(MODULE_NAME)-$(CONFIG_RWNX_MUMIMO_TX) += rwnx_mu_group.o
|
||||
$(MODULE_NAME)-$(CONFIG_SDIO_SUPPORT) += sdio_host.o
|
||||
$(MODULE_NAME)-$(CONFIG_SDIO_SUPPORT) += aicwf_txrxif.o
|
||||
$(MODULE_NAME)-$(CONFIG_SDIO_SUPPORT) += aicwf_sdio.o
|
||||
$(MODULE_NAME)-$(CONFIG_FILTER_TCP_ACK) += aicwf_tcp_ack.o
|
||||
|
||||
$(MODULE_NAME)-$(CONFIG_USB_SUPPORT) += usb_host.o
|
||||
$(MODULE_NAME)-$(CONFIG_USB_SUPPORT) += aicwf_txrxif.o
|
||||
$(MODULE_NAME)-$(CONFIG_USB_SUPPORT) += aicwf_usb.o
|
||||
$(MODULE_NAME)-$(CONFIG_USE_WIRELESS_EXT) += aicwf_wext_linux.o
|
||||
$(MODULE_NAME)-$(CONFIG_GKI) += rwnx_gki.o
|
||||
|
||||
ccflags-$(CONFIG_DEBUG_FS) += -DCONFIG_RWNX_DEBUGFS
|
||||
ccflags-$(CONFIG_DEBUG_FS) += -DCONFIG_RWNX_UM_HELPER_DFLT=\"$(CONFIG_RWNX_UM_HELPER_DFLT)\"
|
||||
ccflags-$(CONFIG_RWNX_P2P_DEBUGFS) += -DCONFIG_RWNX_P2P_DEBUGFS
|
||||
|
||||
# FW VARS
|
||||
ccflags-y += -DNX_VIRT_DEV_MAX=4
|
||||
|
||||
#for 8800D and DCDW u01
|
||||
#ccflags-y += -DNX_REMOTE_STA_MAX=8
|
||||
|
||||
#for 8800DCDW u02
|
||||
ccflags-y += -DNX_REMOTE_STA_MAX_FOR_OLD_IC=8
|
||||
ccflags-y += -DNX_REMOTE_STA_MAX=32
|
||||
|
||||
ccflags-y += -DNX_MU_GROUP_MAX=62
|
||||
ccflags-y += -DNX_TXDESC_CNT=64
|
||||
ccflags-y += -DNX_TX_MAX_RATES=4
|
||||
ccflags-y += -DNX_CHAN_CTXT_CNT=3
|
||||
|
||||
# FW ARCH:
|
||||
ccflags-$(CONFIG_RWNX_SDM) += -DCONFIG_RWNX_SDM
|
||||
ccflags-$(CONFIG_RWNX_TL4) += -DCONFIG_RWNX_TL4
|
||||
ccflags-$(CONFIG_RWNX_OLD_IPC) += -DCONFIG_RWNX_OLD_IPC
|
||||
ccflags-$(CONFIG_START_FROM_BOOTROM) += -DCONFIG_START_FROM_BOOTROM
|
||||
ccflags-$(CONFIG_PMIC_SETTING) += -DCONFIG_PMIC_SETTING
|
||||
ccflags-$(CONFIG_VRF_DCDC_MODE) += -DCONFIG_VRF_DCDC_MODE
|
||||
ccflags-$(CONFIG_ROM_PATCH_EN) += -DCONFIG_ROM_PATCH_EN
|
||||
ccflags-$(CONFIG_WPA3_FOR_OLD_KERNEL) += -DCONFIG_WPA3_FOR_OLD_KERNEL
|
||||
ccflags-$(CONFIG_HE_FOR_OLD_KERNEL) += -DCONFIG_HE_FOR_OLD_KERNEL
|
||||
ccflags-$(CONFIG_VHT_FOR_OLD_KERNEL) += -DCONFIG_VHT_FOR_OLD_KERNEL
|
||||
ccflags-$(CONFIG_COEX) += -DCONFIG_COEX
|
||||
|
||||
ccflags-y += -DCONFIG_RWNX_FULLMAC
|
||||
ccflags-y += -I$(src)/.
|
||||
ccflags-$(CONFIG_RWNX_RADAR) += -DCONFIG_RWNX_RADAR
|
||||
ccflags-$(CONFIG_RWNX_MON_DATA) += -DCONFIG_RWNX_MON_DATA
|
||||
ccflags-$(CONFIG_RWNX_MON_XMIT) += -DCONFIG_RWNX_MON_XMIT
|
||||
ccflags-$(CONFIG_RWNX_MON_RXFILTER) += -DCONFIG_RWNX_MON_RXFILTER
|
||||
ccflags-$(CONFIG_RWNX_BFMER) += -DCONFIG_RWNX_BFMER
|
||||
ccflags-$(CONFIG_RWNX_SPLIT_TX_BUF) += -DCONFIG_RWNX_SPLIT_TX_BUF
|
||||
ifeq ($(CONFIG_RWNX_SPLIT_TX_BUF), y)
|
||||
ccflags-$(CONFIG_RWNX_AMSDUS_TX) += -DCONFIG_RWNX_AMSDUS_TX
|
||||
endif
|
||||
ccflags-$(CONFIG_RWNX_DBG) += -DCONFIG_RWNX_DBG
|
||||
ccflags-$(CONFIG_RWNX_SW_PROFILING) += -DCONFIG_RWNX_SW_PROFILING
|
||||
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
|
||||
|
||||
ifeq ($(CONFIG_SDIO_SUPPORT), y)
|
||||
ccflags-y += -DAICWF_SDIO_SUPPORT
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_USB_SUPPORT), y)
|
||||
ccflags-y += -DAICWF_USB_SUPPORT
|
||||
endif
|
||||
ifeq ($(CONFIG_BR_SUPPORT), y)
|
||||
ccflags-y += -DCONFIG_BR_SUPPORT
|
||||
ccflags-y += '-DCONFIG_BR_SUPPORT_BRNAME="'$(BR_NAME)'"'
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_RWNX_MUMIMO_TX), y)
|
||||
ccflags-y += -DCONFIG_USER_MAX=2
|
||||
else
|
||||
ccflags-y += -DCONFIG_USER_MAX=1
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_RWNX_BCMC), y)
|
||||
ccflags-y += -DNX_TXQ_CNT=5
|
||||
else
|
||||
ccflags-y += -DNX_TXQ_CNT=4
|
||||
endif
|
||||
|
||||
# For old kernel (<=3.19)
|
||||
ifeq ($(shell test $(VERSION) -lt 4 -a "$(CONFIG_VENDOR_RWNX)" = y ; echo $$?),0)
|
||||
ccflags-y += -DCONFIG_VENDOR_RWNX_VHT_NO80
|
||||
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_DOWNLOAD_FW) += -DCONFIG_DOWNLOAD_FW
|
||||
ccflags-$(CONFIG_USB_BT) += -DCONFIG_USB_BT
|
||||
ccflags-$(CONFIG_ALIGN_8BYTES) += -DCONFIG_ALIGN_8BYTES
|
||||
ccflags-$(CONFIG_TXRX_THREAD_PRIO) += -DCONFIG_TXRX_THREAD_PRIO
|
||||
ccflags-$(CONFIG_USB_ALIGN_DATA) += -DCONFIG_USB_ALIGN_DATA
|
||||
ccflags-$(CONFIG_MAC_RANDOM_IF_NO_MAC_IN_EFUSE) += -DCONFIG_MAC_RANDOM_IF_NO_MAC_IN_EFUSE
|
||||
ccflags-$(CONFIG_VENDOR_GPIO) += -DCONFIG_VENDOR_GPIO
|
||||
ccflags-y += -DDEFAULT_COUNTRY_CODE=""\$(CONFIG_COUNTRY_CODE)"\"
|
||||
ccflags-$(CONFIG_RX_NETIF_RECV_SKB) += -DCONFIG_RX_NETIF_RECV_SKB
|
||||
ccflags-$(CONFIG_USB_MSG_OUT_EP) += -DCONFIG_USB_MSG_OUT_EP
|
||||
ccflags-$(CONFIG_USB_MSG_IN_EP) += -DCONFIG_USB_MSG_IN_EP
|
||||
ccflags-$(CONFIG_USB_RX_REASSEMBLE) += -DCONFIG_USB_RX_REASSEMBLE
|
||||
ccflags-$(CONFIG_USB_RX_AGGR) += -DCONFIG_USB_RX_AGGR
|
||||
ccflags-$(CONFIG_USB_TX_AGGR) += -DCONFIG_USB_TX_AGGR
|
||||
ccflags-$(CONFIG_USB_NO_TRANS_DMA_MAP) += -DCONFIG_USB_NO_TRANS_DMA_MAP
|
||||
ccflags-$(CONFIG_GPIO_WAKEUP) += -DCONFIG_GPIO_WAKEUP
|
||||
ccflags-$(CONFIG_CREATE_TRACE_POINTS) += -DCREATE_TRACE_POINTS
|
||||
ccflags-$(CONFIG_RX_TASKLET) += -DCONFIG_RX_TASKLET
|
||||
ccflags-$(CONFIG_TX_TASKLET) += -DCONFIG_TX_TASKLET
|
||||
ccflags-$(CONFIG_USE_USB_ZERO_PACKET) += -DCONFIG_USE_USB_ZERO_PACKET
|
||||
ccflags-$(CONFIG_STA_SCAN_WHEN_P2P_WORKING) += -DCONFIG_STA_SCAN_WHEN_P2P_WORKING
|
||||
ccflags-$(CONFIG_SUPPORT_REALTIME_CHANGE_MAC) += -DCONFIG_SUPPORT_REALTIME_CHANGE_MAC
|
||||
ccflags-$(CONFIG_SET_VENDOR_EXTENSION_IE) += -DCONFIG_SET_VENDOR_EXTENSION_IE
|
||||
ccflags-$(CONFIG_FWLOG_EN) += -DCONFIG_FWLOG_EN
|
||||
ccflags-$(CONFIG_FOR_IPCAM) += -DCONFIG_FOR_IPCAM -DCONFIG_ONE_TXQ
|
||||
ccflags-$(CONFIG_5M10M) += -DCONFIG_5M10M
|
||||
ccflags-$(CONFIG_USE_FW_REQUEST) += -DCONFIG_USE_FW_REQUEST
|
||||
ccflags-$(CONFIG_USE_P2P0) += -DCONFIG_USE_P2P0
|
||||
ccflags-$(CONFIG_ONE_TXQ) += -DCONFIG_ONE_TXQ
|
||||
ccflags-$(CONFIG_PER_STA_FC) += -DCONFIG_PER_STA_FC
|
||||
ccflags-$(CONFIG_PREALLOC_RX_SKB) += -DCONFIG_PREALLOC_RX_SKB
|
||||
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_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
|
||||
MAKEFLAGS +=-j$(shell nproc)
|
||||
|
||||
# Platform support list
|
||||
CONFIG_PLATFORM_ROCKCHIP ?= n
|
||||
CONFIG_PLATFORM_ALLWINNER ?= n
|
||||
CONFIG_PLATFORM_AMLOGIC ?= n
|
||||
CONFIG_PLATFORM_HI ?= n
|
||||
CONFIG_PLATFORM_UBUNTU ?= y
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y)
|
||||
ARCH := arm64
|
||||
KDIR ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel
|
||||
CROSS_COMPILE := /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
|
||||
ccflags-y += -DANDROID_PLATFORM
|
||||
ccflags-y += -DCONFIG_PLATFORM_ROCKCHIP
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_ALLWINNER), y)
|
||||
KDIR ?= /home/yaya/E/Allwinner/R818/R818/AndroidQ/lichee/kernel/linux-4.9
|
||||
ARCH ?= arm64
|
||||
CROSS_COMPILE ?= /home/yaya/E/Allwinner/R818/R818/AndroidQ/lichee/out/gcc-linaro-5.3.1-2016.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
|
||||
ccflags-y += -DANDROID_PLATFORM
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_AMLOGIC), y)
|
||||
ccflags-y += -DANDROID_PLATFORM
|
||||
ARCH ?= arm
|
||||
CROSS_COMPILE ?= /home/yaya/D/Workspace/CyberQuantum/JinHaoYue/amls905x3/SDK/20191101-0tt-asop/android9.0/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androidkernel-
|
||||
KDIR ?= /home/yaya/D/Workspace/CyberQuantum/JinHaoYue/amls905x3/SDK/20191101-0tt-asop/android9.0/out/target/product/u202/obj/KERNEL_OBJ/
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_HI), y)
|
||||
ccflags-y += -DANDROID_PLATFORM
|
||||
ccflags-y += -DCONFIG_PLATFORM_HI
|
||||
ARCH ?= arm
|
||||
CROSS_COMPILE ?= /home/yaya/D/Workspace/CyberQuantum/JinHaoYue/amls905x3/SDK/20191101-0tt-asop/android9.0/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androidkernel-
|
||||
KDIR ?= /home/yaya/D/Workspace/CyberQuantum/JinHaoYue/amls905x3/SDK/20191101-0tt-asop/android9.0/out/target/product/u202/obj/KERNEL_OBJ/
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_UBUNTU), y)
|
||||
KDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
#KDIR ?= ~/D/Workspace/CyberQuantum/Linux/linux-4.15/
|
||||
PWD ?= $(shell pwd)
|
||||
KVER ?= $(shell uname -r)
|
||||
MODDESTDIR ?= /lib/modules/$(KVER)/kernel/drivers/net/wireless/aic8800
|
||||
SUBARCH = $(shell uname -m | sed -e s/i.86/i386/ -e s/armv.l/arm/ -e s/aarch64/arm64/)
|
||||
ARCH ?= $(SUBARCH)
|
||||
CROSS_COMPILE ?=
|
||||
endif
|
||||
|
||||
|
||||
all: modules
|
||||
modules:
|
||||
# make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) LLVM=1 LLVM_IAS=1 modules
|
||||
make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
|
||||
install:
|
||||
mkdir -p $(MODDESTDIR)
|
||||
install -p -m 644 $(MODULE_NAME).ko $(MODDESTDIR)
|
||||
/sbin/depmod -a ${KVER}
|
||||
|
||||
uninstall:
|
||||
rm -rfv $(MODDESTDIR)/$(MODULE_NAME).ko
|
||||
/sbin/depmod -a ${KVER}
|
||||
|
||||
clean:
|
||||
rm -rf *.o *.ko *.o.* *.mod.* modules.* Module.* .a* .o* .*.o.* *.mod .tmp* .cache.mk .modules.order.cmd .Module.symvers.cmd
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,73 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2007 - 2017 Realtek Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef _AIC_BR_EXT_H_
|
||||
#define _AIC_BR_EXT_H_
|
||||
|
||||
#define CL_IPV6_PASS 1
|
||||
#define MACADDRLEN 6
|
||||
#define WLAN_ETHHDR_LEN 14
|
||||
|
||||
#define NAT25_HASH_BITS 4
|
||||
#define NAT25_HASH_SIZE (1 << NAT25_HASH_BITS)
|
||||
#define NAT25_AGEING_TIME 300
|
||||
|
||||
#define NDEV_FMT "%s"
|
||||
#define NDEV_ARG(ndev) ndev->name
|
||||
#define ADPT_FMT "%s"
|
||||
//#define ADPT_ARG(adapter) (adapter->pnetdev ? adapter->pnetdev->name : NULL)
|
||||
#define FUNC_NDEV_FMT "%s(%s)"
|
||||
#define FUNC_NDEV_ARG(ndev) __func__, ndev->name
|
||||
#define FUNC_ADPT_FMT "%s(%s)"
|
||||
//#define FUNC_ADPT_ARG(adapter) __func__, (adapter->pnetdev ? adapter->pnetdev->name : NULL)
|
||||
#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
|
||||
#define MAC_ARG(x) ((u8 *)(x))[0], ((u8 *)(x))[1], ((u8 *)(x))[2], ((u8 *)(x))[3], ((u8 *)(x))[4], ((u8 *)(x))[5]
|
||||
|
||||
|
||||
#ifdef CL_IPV6_PASS
|
||||
#define MAX_NETWORK_ADDR_LEN 17
|
||||
#else
|
||||
#define MAX_NETWORK_ADDR_LEN 11
|
||||
#endif
|
||||
|
||||
struct nat25_network_db_entry {
|
||||
struct nat25_network_db_entry *next_hash;
|
||||
struct nat25_network_db_entry **pprev_hash;
|
||||
atomic_t use_count;
|
||||
unsigned char macAddr[6];
|
||||
unsigned long ageing_timer;
|
||||
unsigned char networkAddr[MAX_NETWORK_ADDR_LEN];
|
||||
};
|
||||
|
||||
enum NAT25_METHOD {
|
||||
NAT25_MIN,
|
||||
NAT25_CHECK,
|
||||
NAT25_INSERT,
|
||||
NAT25_LOOKUP,
|
||||
NAT25_PARSE,
|
||||
NAT25_MAX
|
||||
};
|
||||
|
||||
struct br_ext_info {
|
||||
unsigned int nat25_disable;
|
||||
unsigned int macclone_enable;
|
||||
unsigned int dhcp_bcst_disable;
|
||||
int addPPPoETag; /* 1: Add PPPoE relay-SID, 0: disable */
|
||||
unsigned char nat25_dmzMac[MACADDRLEN];
|
||||
unsigned int nat25sc_disable;
|
||||
};
|
||||
|
||||
void nat25_db_cleanup(struct rwnx_vif *vif);
|
||||
|
||||
#endif /* _AIC_BR_EXT_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file private_cmd.h
|
||||
*
|
||||
* Copyright (C) Aicsemi 2018-2024
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _AIC_PRIV_CMD_H_
|
||||
#define _AIC_PRIV_CMD_H_
|
||||
|
||||
#include "rwnx_defs.h"
|
||||
|
||||
typedef struct _android_wifi_priv_cmd {
|
||||
char *buf;
|
||||
int used_len;
|
||||
int total_len;
|
||||
} android_wifi_priv_cmd;
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
typedef struct _compat_android_wifi_priv_cmd {
|
||||
compat_caddr_t buf;
|
||||
int used_len;
|
||||
int total_len;
|
||||
} compat_android_wifi_priv_cmd;
|
||||
#endif /* CONFIG_COMPAT */
|
||||
|
||||
int android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd);
|
||||
|
||||
#endif /* _AIC_PRIV_CMD_H_ */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,346 @@
|
||||
#ifndef _AIC_VENDOR_H
|
||||
#define _AIC_VENDOR_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define GOOGLE_OUI 0x001A11
|
||||
#define BRCM_OUI 0x001018
|
||||
|
||||
typedef enum {
|
||||
START_MKEEP_ALIVE,
|
||||
STOP_MKEEP_ALIVE,
|
||||
} GetCmdType;
|
||||
|
||||
typedef enum {
|
||||
/* don't use 0 as a valid subcommand */
|
||||
VENDOR_NL80211_SUBCMD_UNSPECIFIED,
|
||||
|
||||
/* define all vendor startup commands between 0x0 and 0x0FFF */
|
||||
VENDOR_NL80211_SUBCMD_RANGE_START = 0x0001,
|
||||
VENDOR_NL80211_SUBCMD_RANGE_END = 0x0FFF,
|
||||
|
||||
/* define all GScan related commands between 0x1000 and 0x10FF */
|
||||
ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START = 0x1000,
|
||||
ANDROID_NL80211_SUBCMD_GSCAN_RANGE_END = 0x10FF,
|
||||
|
||||
/* define all NearbyDiscovery related commands between 0x1100 and 0x11FF */
|
||||
ANDROID_NL80211_SUBCMD_NBD_RANGE_START = 0x1100,
|
||||
ANDROID_NL80211_SUBCMD_NBD_RANGE_END = 0x11FF,
|
||||
|
||||
/* define all RTT related commands between 0x1100 and 0x11FF */
|
||||
ANDROID_NL80211_SUBCMD_RTT_RANGE_START = 0x1100,
|
||||
ANDROID_NL80211_SUBCMD_RTT_RANGE_END = 0x11FF,
|
||||
|
||||
ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START = 0x1200,
|
||||
ANDROID_NL80211_SUBCMD_LSTATS_RANGE_END = 0x12FF,
|
||||
|
||||
/* define all Logger related commands between 0x1400 and 0x14FF */
|
||||
ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START = 0x1400,
|
||||
ANDROID_NL80211_SUBCMD_DEBUG_RANGE_END = 0x14FF,
|
||||
|
||||
/* define all wifi offload related commands between 0x1600 and 0x16FF */
|
||||
ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START = 0x1600,
|
||||
ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_END = 0x16FF,
|
||||
|
||||
/* define all NAN related commands between 0x1700 and 0x17FF */
|
||||
ANDROID_NL80211_SUBCMD_NAN_RANGE_START = 0x1700,
|
||||
ANDROID_NL80211_SUBCMD_NAN_RANGE_END = 0x17FF,
|
||||
|
||||
/* define all Android Packet Filter related commands between 0x1800 and 0x18FF */
|
||||
ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START = 0x1800,
|
||||
ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_END = 0x18FF,
|
||||
|
||||
/* This is reserved for future usage */
|
||||
|
||||
} ANDROID_VENDOR_SUB_COMMAND;
|
||||
|
||||
typedef enum {
|
||||
WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE = ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START,
|
||||
WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE,
|
||||
} WIFI_OFFLOAD_SUB_COMMAND;
|
||||
|
||||
|
||||
enum mkeep_alive_attributes {
|
||||
MKEEP_ALIVE_ATTRIBUTE_ID = 0x1,
|
||||
MKEEP_ALIVE_ATTRIBUTE_IP_PKT,
|
||||
MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN,
|
||||
MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR,
|
||||
MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR,
|
||||
MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC,
|
||||
MKEEP_ALIVE_ATTRIBUTE_AFTER_LAST,
|
||||
MKEEP_ALIVE_ATTRIBUTE_MAX = MKEEP_ALIVE_ATTRIBUTE_AFTER_LAST - 1
|
||||
};
|
||||
|
||||
enum debug_sub_command {
|
||||
LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START,
|
||||
LOGGER_TRIGGER_MEM_DUMP,
|
||||
LOGGER_GET_MEM_DUMP,
|
||||
LOGGER_GET_VER,
|
||||
LOGGER_GET_RING_STATUS,
|
||||
LOGGER_GET_RING_DATA,
|
||||
LOGGER_GET_FEATURE,
|
||||
LOGGER_RESET_LOGGING,
|
||||
LOGGER_TRIGGER_DRIVER_MEM_DUMP,
|
||||
LOGGER_GET_DRIVER_MEM_DUMP,
|
||||
LOGGER_START_PKT_FATE_MONITORING,
|
||||
LOGGER_GET_TX_PKT_FATES,
|
||||
LOGGER_GET_RX_PKT_FATES,
|
||||
LOGGER_GET_WAKE_REASON_STATS,
|
||||
LOGGER_DEBUG_GET_DUMP,
|
||||
LOGGER_FILE_DUMP_DONE_IND,
|
||||
LOGGER_SET_HAL_START,
|
||||
LOGGER_HAL_STOP,
|
||||
LOGGER_SET_HAL_PID,
|
||||
};
|
||||
|
||||
enum logger_attributes {
|
||||
LOGGER_ATTRIBUTE_INVALID = 0,
|
||||
LOGGER_ATTRIBUTE_DRIVER_VER,
|
||||
LOGGER_ATTRIBUTE_FW_VER,
|
||||
LOGGER_ATTRIBUTE_RING_ID,
|
||||
LOGGER_ATTRIBUTE_RING_NAME,
|
||||
LOGGER_ATTRIBUTE_RING_FLAGS,
|
||||
LOGGER_ATTRIBUTE_LOG_LEVEL,
|
||||
LOGGER_ATTRIBUTE_LOG_TIME_INTVAL,
|
||||
LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE,
|
||||
LOGGER_ATTRIBUTE_FW_DUMP_LEN,
|
||||
LOGGER_ATTRIBUTE_FW_DUMP_DATA,
|
||||
// LOGGER_ATTRIBUTE_FW_ERR_CODE,
|
||||
LOGGER_ATTRIBUTE_RING_DATA,
|
||||
LOGGER_ATTRIBUTE_RING_STATUS,
|
||||
LOGGER_ATTRIBUTE_RING_NUM,
|
||||
LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN,
|
||||
LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA,
|
||||
LOGGER_ATTRIBUTE_PKT_FATE_NUM,
|
||||
LOGGER_ATTRIBUTE_PKT_FATE_DATA,
|
||||
LOGGER_ATTRIBUTE_AFTER_LAST,
|
||||
LOGGER_ATTRIBUTE_MAX = LOGGER_ATTRIBUTE_AFTER_LAST - 1,
|
||||
};
|
||||
|
||||
enum wifi_sub_command {
|
||||
GSCAN_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START,
|
||||
GSCAN_SUBCMD_SET_CONFIG, /* 0x1001 */
|
||||
GSCAN_SUBCMD_SET_SCAN_CONFIG, /* 0x1002 */
|
||||
GSCAN_SUBCMD_ENABLE_GSCAN, /* 0x1003 */
|
||||
GSCAN_SUBCMD_GET_SCAN_RESULTS, /* 0x1004 */
|
||||
GSCAN_SUBCMD_SCAN_RESULTS, /* 0x1005 */
|
||||
GSCAN_SUBCMD_SET_HOTLIST, /* 0x1006 */
|
||||
GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG, /* 0x1007 */
|
||||
GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, /* 0x1008 */
|
||||
GSCAN_SUBCMD_GET_CHANNEL_LIST, /* 0x1009 */
|
||||
WIFI_SUBCMD_GET_FEATURE_SET, /* 0x100A */
|
||||
WIFI_SUBCMD_GET_FEATURE_SET_MATRIX, /* 0x100B */
|
||||
WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, /* 0x100C */
|
||||
WIFI_SUBCMD_NODFS_SET, /* 0x100D */
|
||||
WIFI_SUBCMD_SET_COUNTRY_CODE, /* 0x100E */
|
||||
/* Add more sub commands here */
|
||||
GSCAN_SUBCMD_SET_EPNO_SSID, /* 0x100F */
|
||||
WIFI_SUBCMD_SET_SSID_WHITE_LIST, /* 0x1010 */
|
||||
WIFI_SUBCMD_SET_ROAM_PARAMS, /* 0x1011 */
|
||||
WIFI_SUBCMD_ENABLE_LAZY_ROAM, /* 0x1012 */
|
||||
WIFI_SUBCMD_SET_BSSID_PREF, /* 0x1013 */
|
||||
WIFI_SUBCMD_SET_BSSID_BLACKLIST, /* 0x1014 */
|
||||
GSCAN_SUBCMD_ANQPO_CONFIG, /* 0x1015 */
|
||||
WIFI_SUBCMD_SET_RSSI_MONITOR, /* 0x1016 */
|
||||
WIFI_SUBCMD_CONFIG_ND_OFFLOAD, /* 0x1017 */
|
||||
/* Add more sub commands here */
|
||||
GSCAN_SUBCMD_MAX,
|
||||
APF_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START,
|
||||
APF_SUBCMD_SET_FILTER,
|
||||
};
|
||||
|
||||
enum gscan_attributes {
|
||||
GSCAN_ATTRIBUTE_NUM_BUCKETS = 10,
|
||||
GSCAN_ATTRIBUTE_BASE_PERIOD,
|
||||
GSCAN_ATTRIBUTE_BUCKETS_BAND,
|
||||
GSCAN_ATTRIBUTE_BUCKET_ID,
|
||||
GSCAN_ATTRIBUTE_BUCKET_PERIOD,
|
||||
GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS,
|
||||
GSCAN_ATTRIBUTE_BUCKET_CHANNELS,
|
||||
GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN,
|
||||
GSCAN_ATTRIBUTE_REPORT_THRESHOLD,
|
||||
GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE,
|
||||
GSCAN_ATTRIBUTE_BAND = GSCAN_ATTRIBUTE_BUCKETS_BAND,
|
||||
|
||||
GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20,
|
||||
GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, /* indicates no more results */
|
||||
GSCAN_ATTRIBUTE_FLUSH_FEATURE, /* Flush all the configs */
|
||||
GSCAN_ENABLE_FULL_SCAN_RESULTS,
|
||||
GSCAN_ATTRIBUTE_REPORT_EVENTS,
|
||||
|
||||
/* remaining reserved for additional attributes */
|
||||
GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30,
|
||||
GSCAN_ATTRIBUTE_FLUSH_RESULTS,
|
||||
GSCAN_ATTRIBUTE_SCAN_RESULTS, /* flat array of wifi_scan_result */
|
||||
GSCAN_ATTRIBUTE_SCAN_ID, /* indicates scan number */
|
||||
GSCAN_ATTRIBUTE_SCAN_FLAGS, /* indicates if scan was aborted */
|
||||
GSCAN_ATTRIBUTE_AP_FLAGS, /* flags on significant change event */
|
||||
GSCAN_ATTRIBUTE_NUM_CHANNELS,
|
||||
GSCAN_ATTRIBUTE_CHANNEL_LIST,
|
||||
GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK,
|
||||
|
||||
GSCAN_ATTRIBUTE_AFTER_LAST,
|
||||
GSCAN_ATTRIBUTE_MAX = GSCAN_ATTRIBUTE_AFTER_LAST - 1,
|
||||
};
|
||||
|
||||
enum andr_wifi_attributes {
|
||||
ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET,
|
||||
ANDR_WIFI_ATTRIBUTE_FEATURE_SET,
|
||||
ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI,
|
||||
ANDR_WIFI_ATTRIBUTE_NODFS_SET,
|
||||
ANDR_WIFI_ATTRIBUTE_COUNTRY,
|
||||
ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE,
|
||||
// Add more attribute here
|
||||
ANDR_WIFI_ATTRIBUTE_AFTER_LAST,
|
||||
ANDR_WIFI_ATTRIBUTE_MAX = ANDR_WIFI_ATTRIBUTE_AFTER_LAST - 1,
|
||||
};
|
||||
|
||||
enum wifi_support_feature {
|
||||
/* Feature enums */
|
||||
WIFI_FEATURE_INFRA = 0x0001, /* Basic infrastructure mode */
|
||||
WIFI_FEATURE_INFRA_5G = 0x0002, /* Support for 5, GHz Band */
|
||||
WIFI_FEATURE_HOTSPOT = 0x0004, /* Support for GAS/ANQP */
|
||||
WIFI_FEATURE_P2P = 0x0008, /* Wifi-Direct */
|
||||
WIFI_FEATURE_SOFT_AP = 0x0010, /* Soft AP */
|
||||
WIFI_FEATURE_GSCAN = 0x0020, /* Google-Scan APIs */
|
||||
WIFI_FEATURE_NAN = 0x0040, /* Neighbor Awareness Networking */
|
||||
WIFI_FEATURE_D2D_RTT = 0x0080, /* Device-to-device RTT */
|
||||
WIFI_FEATURE_D2AP_RTT = 0x0100, /* Device-to-AP RTT */
|
||||
WIFI_FEATURE_BATCH_SCAN = 0x0200, /* Batched Scan (legacy) */
|
||||
WIFI_FEATURE_PNO = 0x0400, /* Preferred network offload */
|
||||
WIFI_FEATURE_ADDITIONAL_STA = 0x0800, /* Support for two STAs */
|
||||
WIFI_FEATURE_TDLS = 0x1000, /* Tunnel directed link setup */
|
||||
WIFI_FEATURE_TDLS_OFFCHANNEL = 0x2000, /* Support for TDLS off channel */
|
||||
WIFI_FEATURE_EPR = 0x4000, /* Enhanced power reporting */
|
||||
WIFI_FEATURE_AP_STA = 0x8000, /* Support for AP STA Concurrency */
|
||||
WIFI_FEATURE_LINK_LAYER_STATS = 0x10000, /* Support for Linkstats */
|
||||
WIFI_FEATURE_LOGGER = 0x20000, /* WiFi Logger */
|
||||
WIFI_FEATURE_HAL_EPNO = 0x40000, /* WiFi PNO enhanced */
|
||||
WIFI_FEATURE_RSSI_MONITOR = 0x80000, /* RSSI Monitor */
|
||||
WIFI_FEATURE_MKEEP_ALIVE = 0x100000, /* WiFi mkeep_alive */
|
||||
WIFI_FEATURE_CONFIG_NDO = 0x200000, /* ND offload configure */
|
||||
WIFI_FEATURE_TX_TRANSMIT_POWER = 0x400000, /* Capture Tx transmit power levels */
|
||||
WIFI_FEATURE_CONTROL_ROAMING = 0x800000, /* Enable/Disable firmware roaming */
|
||||
WIFI_FEATURE_IE_WHITELIST = 0x1000000, /* Support Probe IE white listing */
|
||||
WIFI_FEATURE_SCAN_RAND = 0x2000000, /* Support MAC & Probe Sequence Number randomization */
|
||||
WIFI_FEATURE_INVALID = 0xFFFFFFFF, /* Invalid Feature */
|
||||
};
|
||||
|
||||
enum wifi_logger_feature {
|
||||
WIFI_LOGGER_MEMORY_DUMP_SUPPORTED = (1 << (0)), // Memory dump of FW
|
||||
WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED = (1 << (1)), // PKT status
|
||||
WIFI_LOGGER_CONNECT_EVENT_SUPPORTED = (1 << (2)), // Connectivity event
|
||||
WIFI_LOGGER_POWER_EVENT_SUPPORTED = (1 << (3)), // POWER of Driver
|
||||
WIFI_LOGGER_WAKE_LOCK_SUPPORTED = (1 << (4)), // WAKE LOCK of Driver
|
||||
WIFI_LOGGER_VERBOSE_SUPPORTED = (1 << (5)), // verbose log of FW
|
||||
WIFI_LOGGER_WATCHDOG_TIMER_SUPPORTED = (1 << (6)), // monitor the health of FW
|
||||
WIFI_LOGGER_DRIVER_DUMP_SUPPORTED = (1 << (7)), // dumps driver state
|
||||
WIFI_LOGGER_PACKET_FATE_SUPPORTED = (1 << (8)), // tracks connection packets' fate
|
||||
};
|
||||
|
||||
enum wake_stats_attributes {
|
||||
WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT,
|
||||
WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE,
|
||||
WAKE_STAT_ATTRIBUTE_CMD_EVENT_COUNT,
|
||||
WAKE_STAT_ATTRIBUTE_CMD_COUNT_USED,
|
||||
WAKE_STAT_ATTRIBUTE_TOTAL_DRIVER_FW,
|
||||
WAKE_STAT_ATTRIBUTE_DRIVER_FW_WAKE,
|
||||
WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT,
|
||||
WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT_USED,
|
||||
WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE,
|
||||
WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT,
|
||||
WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT,
|
||||
WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT,
|
||||
WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT,
|
||||
WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT,
|
||||
WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA,
|
||||
WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA,
|
||||
WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS,
|
||||
WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT,
|
||||
WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT,
|
||||
WAKE_STAT_ATTRIBUTE_OTHER__RX_MULTICAST_ADD_CNT,
|
||||
WAKE_STAT_ATTRIBUTE_RX_MULTICAST_PKT_INFO,
|
||||
WAKE_STAT_ATTRIBUTE_AFTER_LAST,
|
||||
WAKE_STAT_ATTRIBUTE_MAX = WAKE_STAT_ATTRIBUTE_AFTER_LAST - 1,
|
||||
};
|
||||
|
||||
enum vendor_nl80211_subcmd {
|
||||
/* copied from wpa_supplicant brcm definations */
|
||||
VENDOR_NL80211_SUBCMD_UNSPEC = 0,
|
||||
VENDOR_NL80211_SUBCMD_SET_PMK = 4,
|
||||
VENDOR_NL80211_SUBCMD_SET_MAC = 6,
|
||||
VENDOR_NL80211_SCMD_ACS = 9,
|
||||
VENDOR_NL80211_SCMD_MAX = 10,
|
||||
};
|
||||
|
||||
enum nl80211_vendor_subcmd_attributes {
|
||||
WIFI_VENDOR_ATTR_DRIVER_CMD = 0,
|
||||
WIFI_VENDOR_ATTR_DRIVER_KEY_PMK = 1,
|
||||
WIFI_VENDOR_ATTR_DRIVER_MAC_ADDR = 3,
|
||||
WIFI_VENDOR_ATTR_DRIVER_AFTER_LAST = 5,
|
||||
WIFI_VENDOR_ATTR_DRIVER_MAX =
|
||||
WIFI_VENDOR_ATTR_DRIVER_AFTER_LAST - 1,
|
||||
};
|
||||
|
||||
typedef int wifi_ring_buffer_id;
|
||||
|
||||
struct wifi_ring_buffer_status {
|
||||
u8 name[32];
|
||||
u32 flags;
|
||||
wifi_ring_buffer_id ring_id;
|
||||
u32 ring_buffer_byte_size;
|
||||
u32 verbose_level;
|
||||
u32 written_bytes;
|
||||
u32 read_bytes;
|
||||
u32 written_records;
|
||||
};
|
||||
|
||||
struct rx_data_cnt_details_t {
|
||||
int rx_unicast_cnt; /*Total rx unicast packet which woke up host */
|
||||
int rx_multicast_cnt; /*Total rx multicast packet which woke up host */
|
||||
int rx_broadcast_cnt; /*Total rx broadcast packet which woke up host */
|
||||
};
|
||||
|
||||
struct rx_wake_pkt_type_classification_t {
|
||||
int icmp_pkt; /*wake icmp packet count */
|
||||
int icmp6_pkt; /*wake icmp6 packet count */
|
||||
int icmp6_ra; /*wake icmp6 RA packet count */
|
||||
int icmp6_na; /*wake icmp6 NA packet count */
|
||||
int icmp6_ns; /*wake icmp6 NS packet count */
|
||||
//ToDo: Any more interesting classification to add?
|
||||
};
|
||||
|
||||
struct rx_multicast_cnt_t{
|
||||
int ipv4_rx_multicast_addr_cnt; /*Rx wake packet was ipv4 multicast */
|
||||
int ipv6_rx_multicast_addr_cnt; /*Rx wake packet was ipv6 multicast */
|
||||
int other_rx_multicast_addr_cnt;/*Rx wake packet was non-ipv4 and non-ipv6*/
|
||||
};
|
||||
|
||||
struct wlan_driver_wake_reason_cnt_t {
|
||||
int total_cmd_event_wake; /* Total count of cmd event wakes */
|
||||
int *cmd_event_wake_cnt; /* Individual wake count array, each index a reason */
|
||||
int cmd_event_wake_cnt_sz; /* Max number of cmd event wake reasons */
|
||||
int cmd_event_wake_cnt_used; /* Number of cmd event wake reasons specific to the driver */
|
||||
|
||||
int total_driver_fw_local_wake; /* Total count of drive/fw wakes, for local reasons */
|
||||
int *driver_fw_local_wake_cnt; /* Individual wake count array, each index a reason */
|
||||
int driver_fw_local_wake_cnt_sz; /* Max number of local driver/fw wake reasons */
|
||||
int driver_fw_local_wake_cnt_used; /* Number of local driver/fw wake reasons specific to the driver */
|
||||
|
||||
int total_rx_data_wake; /* total data rx packets, that woke up host */
|
||||
struct rx_data_cnt_details_t rx_wake_details;
|
||||
struct rx_wake_pkt_type_classification_t rx_wake_pkt_classification_info;
|
||||
struct rx_multicast_cnt_t rx_multicast_wake_pkt_info;
|
||||
};
|
||||
|
||||
typedef struct wl_mkeep_alive_pkt {
|
||||
u16 version; /* Version for mkeep_alive */
|
||||
u16 length; /* length of fixed parameters in the structure */
|
||||
u32 period_msec; /* high bit on means immediate send */
|
||||
u16 len_bytes;
|
||||
u8 keep_alive_id; /* 0 - 3 for N = 4 */
|
||||
u8 data[1];
|
||||
} wl_mkeep_alive_pkt_t;
|
||||
|
||||
#endif /* _AIC_VENDOR_H */
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
#include "rwnx_main.h"
|
||||
#include "rwnx_msg_tx.h"
|
||||
#include "reg_access.h"
|
||||
|
||||
#define FW_USERCONFIG_NAME_8800D80 "aic_userconfig_8800d80.txt"
|
||||
#define FW_POWERLIMIT_NAME_8800D80 "aic_powerlimit_8800d80.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(char *buffer, int size);
|
||||
void rwnx_release_firmware_common(u32** buffer);
|
||||
|
||||
|
||||
int aicwf_set_rf_config_8800d80(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if ((ret = rwnx_send_txpwr_lvl_v3_req(rwnx_hw))) {
|
||||
return -1;
|
||||
}
|
||||
if ((ret = rwnx_send_txpwr_lvl_adj_req(rwnx_hw))) {
|
||||
return -1;
|
||||
}
|
||||
if ((ret = rwnx_send_txpwr_ofst2x_req(rwnx_hw))) {
|
||||
return -1;
|
||||
}
|
||||
if ((ret = rwnx_send_rf_calib_req(rwnx_hw, cfm))) {
|
||||
return -1;
|
||||
}
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
||||
int rwnx_plat_userconfig_load_8800d80(struct rwnx_hw *rwnx_hw){
|
||||
int size;
|
||||
u32 *dst=NULL;
|
||||
char *filename = FW_USERCONFIG_NAME_8800D80;
|
||||
|
||||
#ifndef ANDROID_PLATFORM
|
||||
sprintf(aic_fw_path, "%s/%s", aic_fw_path, "aic8800D80");
|
||||
#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((char *)dst, size);
|
||||
|
||||
rwnx_release_firmware_common(&dst);
|
||||
|
||||
AICWFDBG(LOGINFO, "userconfig download complete\n\n");
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
#ifdef CONFIG_POWER_LIMIT
|
||||
extern char default_ccode[];
|
||||
int rwnx_plat_powerlimit_load_8800d80(struct rwnx_hw *rwnx_hw)
|
||||
{
|
||||
int size;
|
||||
u32 *dst=NULL;
|
||||
char *filename = FW_POWERLIMIT_NAME_8800D80;
|
||||
|
||||
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, default_ccode);
|
||||
|
||||
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_8800d80(struct rwnx_hw *rwnx_hw);
|
||||
#ifdef CONFIG_POWER_LIMIT
|
||||
int rwnx_plat_powerlimit_load_8800d80(struct rwnx_hw *rwnx_hw);
|
||||
#endif
|
||||
int aicwf_set_rf_config_8800d80(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,50 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
#ifdef CONFIG_DPD
|
||||
typedef struct {
|
||||
uint32_t bit_mask[3];
|
||||
uint32_t reserved;
|
||||
uint32_t dpd_high[96];
|
||||
uint32_t dpd_11b[96];
|
||||
uint32_t dpd_low[96];
|
||||
uint32_t idac_11b[48];
|
||||
uint32_t idac_high[48];
|
||||
uint32_t idac_low[48];
|
||||
uint32_t loft_res[18];
|
||||
uint32_t rx_iqim_res[16];
|
||||
} rf_misc_ram_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t bit_mask[4];
|
||||
uint32_t dpd_high[96];
|
||||
uint32_t loft_res[18];
|
||||
} rf_misc_ram_lite_t;
|
||||
|
||||
#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
|
||||
#define DPD_RESULT_SIZE_8800DC sizeof(rf_misc_ram_lite_t)
|
||||
|
||||
extern rf_misc_ram_lite_t dpd_res;
|
||||
#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
|
||||
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);
|
||||
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
|
||||
int aicwf_dpd_result_load_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *dpd_res);
|
||||
int aicwf_dpd_result_write_8800dc(void *buf, int buf_len);
|
||||
#endif
|
||||
#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);
|
||||
int rwnx_plat_userconfig_load_8800dw(struct rwnx_hw *rwnx_hw);
|
||||
#ifdef CONFIG_POWER_LIMIT
|
||||
int rwnx_plat_powerlimit_load_8800dcdw(struct rwnx_hw *rwnx_hw, uint16_t chip_id);
|
||||
#endif
|
||||
void system_config_8800dc(struct rwnx_hw *rwnx_hw);
|
||||
@@ -0,0 +1,52 @@
|
||||
|
||||
|
||||
#define RWNX_FN_ENTRY_STR ">>> %s()\n", __func__
|
||||
|
||||
|
||||
|
||||
/* message levels */
|
||||
#define LOGERROR 0x0001
|
||||
#define LOGINFO 0x0002
|
||||
#define LOGTRACE 0x0004
|
||||
#define LOGDEBUG 0x0008
|
||||
#define LOGDATA 0x0010
|
||||
|
||||
extern int aicwf_dbg_level;
|
||||
void rwnx_data_dump(char* tag, void* data, unsigned long len);
|
||||
|
||||
#define AICWF_LOG "AICWFDBG("
|
||||
|
||||
#define AICWFDBG(level, args, arg...) \
|
||||
do { \
|
||||
if (aicwf_dbg_level & level) { \
|
||||
printk(AICWF_LOG#level")\t" args, ##arg); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define RWNX_DBG(fmt, ...) \
|
||||
do { \
|
||||
if (aicwf_dbg_level & LOGTRACE) { \
|
||||
printk(AICWF_LOG"LOGTRACE)\t"fmt , ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
#define RWNX_DBG(fmt, ...) \
|
||||
do { \
|
||||
if (aicwf_dbg_level & LOGTRACE) { \
|
||||
printk(AICWF_LOG"LOGTRACE"")\t" fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#define AICWFDBG(args, level) \
|
||||
do { \
|
||||
if (aicwf_dbg_level & level) { \
|
||||
printk(AICWF_LOG"(%s)\t" ,#level); \
|
||||
printf args; \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
#ifndef _AICWF_RX_PREALLOC_H_
|
||||
#define _AICWF_RX_PREALLOC_H_
|
||||
|
||||
#ifdef CONFIG_PREALLOC_RX_SKB
|
||||
|
||||
struct rx_buff {
|
||||
struct list_head queue;
|
||||
unsigned char *data;
|
||||
u32 len;
|
||||
uint8_t *start;
|
||||
uint8_t *end;
|
||||
uint8_t *read;
|
||||
};
|
||||
|
||||
struct aicwf_rx_buff_list {
|
||||
struct list_head rxbuff_list;
|
||||
atomic_t rxbuff_list_len;
|
||||
};
|
||||
|
||||
extern struct rx_buff *aicwf_prealloc_rxbuff_alloc(spinlock_t *lock);
|
||||
extern void aicwf_prealloc_rxbuff_free(struct rx_buff *rxbuff, spinlock_t *lock);
|
||||
extern int aicwf_prealloc_init(void);
|
||||
extern void aicwf_prealloc_exit(void);
|
||||
extern int aicwf_rxbuff_size_get(void);
|
||||
#endif
|
||||
#endif /* _AICWF_RX_PREALLOC_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* aicwf_sdio.h
|
||||
*
|
||||
* SDIO function declarations
|
||||
*
|
||||
* Copyright (C) AICSemi 2018-2020
|
||||
*/
|
||||
|
||||
#ifndef _AICWF_SDMMC_H_
|
||||
#define _AICWF_SDMMC_H_
|
||||
|
||||
#ifdef AICWF_SDIO_SUPPORT
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/ieee80211.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include "rwnx_cmds.h"
|
||||
#define AICWF_SDIO_NAME "aicwf_sdio"
|
||||
#define SDIOWIFI_FUNC_BLOCKSIZE 512
|
||||
|
||||
#define SDIO_VENDOR_ID_AIC 0x8800
|
||||
#define SDIO_DEVICE_ID_AIC 0x0001
|
||||
#define SDIOWIFI_BYTEMODE_LEN_REG 0x02
|
||||
#define SDIOWIFI_INTR_CONFIG_REG 0x04
|
||||
#define SDIOWIFI_SLEEP_REG 0x05
|
||||
#define SDIOWIFI_WAKEUP_REG 0x09
|
||||
#define SDIOWIFI_FLOW_CTRL_REG 0x0A
|
||||
#define SDIOWIFI_REGISTER_BLOCK 0x0B
|
||||
#define SDIOWIFI_BYTEMODE_ENABLE_REG 0x11
|
||||
#define SDIOWIFI_BLOCK_CNT_REG 0x12
|
||||
#define SDIOWIFI_FLOWCTRL_MASK_REG 0x7F
|
||||
|
||||
#define SDIOWIFI_PWR_CTRL_INTERVAL 30
|
||||
#define FLOW_CTRL_RETRY_COUNT 50
|
||||
#define BUFFER_SIZE 1536
|
||||
#define TAIL_LEN 4
|
||||
#define TXQLEN (2048*4)
|
||||
|
||||
#define SDIO_SLEEP_ST 0
|
||||
#define SDIO_ACTIVE_ST 1
|
||||
|
||||
typedef enum {
|
||||
SDIO_TYPE_DATA = 0X00,
|
||||
SDIO_TYPE_CFG = 0X10,
|
||||
SDIO_TYPE_CFG_CMD_RSP = 0X11,
|
||||
SDIO_TYPE_CFG_DATA_CFM = 0X12
|
||||
} sdio_type;
|
||||
|
||||
struct rwnx_hw;
|
||||
|
||||
|
||||
struct aic_sdio_dev {
|
||||
struct rwnx_hw *rwnx_hw;
|
||||
struct sdio_func *func;
|
||||
struct device *dev;
|
||||
struct aicwf_bus *bus_if;
|
||||
struct rwnx_cmd_mgr cmd_mgr;
|
||||
|
||||
struct aicwf_rx_priv *rx_priv;
|
||||
struct aicwf_tx_priv *tx_priv;
|
||||
u32 state;
|
||||
|
||||
//for sdio pwr ctrl
|
||||
struct timer_list timer;
|
||||
uint active_duration;
|
||||
struct completion pwrctrl_trgg;
|
||||
struct task_struct *pwrctl_tsk;
|
||||
spinlock_t pwrctl_lock;
|
||||
struct semaphore pwrctl_wakeup_sema;
|
||||
};
|
||||
int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val);
|
||||
void aicwf_sdio_hal_irqhandler(struct sdio_func *func);
|
||||
void aicwf_sdio_pwrctl_timer(struct aic_sdio_dev *sdiodev, uint duration);
|
||||
int aicwf_sdio_pwr_stctl(struct aic_sdio_dev *sdiodev, uint target);
|
||||
int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev);
|
||||
void aicwf_sdio_func_deinit(struct aic_sdio_dev *sdiodev);
|
||||
int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev);
|
||||
int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct sk_buff *skbbuf, u32 size);
|
||||
int aicwf_sdio_send_pkt(struct aic_sdio_dev *sdiodev, u8 *buf, uint count);
|
||||
void *aicwf_sdio_bus_init(struct aic_sdio_dev *sdiodev);
|
||||
void aicwf_sdio_release(struct aic_sdio_dev *sdiodev);
|
||||
void aicwf_sdio_exit(void);
|
||||
void aicwf_sdio_register(void);
|
||||
int aicwf_sdio_txpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt);
|
||||
int sdio_bustx_thread(void *data);
|
||||
int sdio_busrx_thread(void *data);
|
||||
int aicwf_sdio_aggr(struct aicwf_tx_priv *tx_priv, struct sk_buff *pkt);
|
||||
int aicwf_sdio_send(struct aicwf_tx_priv *tx_priv);
|
||||
void aicwf_sdio_aggr_send(struct aicwf_tx_priv *tx_priv);
|
||||
void aicwf_sdio_aggrbuf_reset(struct aicwf_tx_priv* tx_priv);
|
||||
extern void aicwf_hostif_ready(void);
|
||||
#ifdef CONFIG_PLATFORM_NANOPI
|
||||
extern void extern_wifi_set_enable(int is_on);
|
||||
extern void sdio_reinit(void);
|
||||
#endif /*CONFIG_PLATFORM_NANOPI*/
|
||||
|
||||
#endif /* AICWF_SDIO_SUPPORT */
|
||||
|
||||
#endif /*_AICWF_SDMMC_H_*/
|
||||
@@ -0,0 +1,633 @@
|
||||
#include"aicwf_tcp_ack.h"
|
||||
//#include"rwnx_tx.h"
|
||||
//#include "aicwf_tcp_ack.h"
|
||||
#include"rwnx_defs.h"
|
||||
extern int intf_tx(struct rwnx_hw *priv,struct msg_buf *msg);
|
||||
struct msg_buf *intf_tcp_alloc_msg(struct msg_buf *msg)
|
||||
{
|
||||
//printk("%s \n",__func__);
|
||||
int len=sizeof(struct msg_buf) ;
|
||||
msg = kzalloc(len , GFP_ATOMIC);
|
||||
if(!msg)
|
||||
printk("%s: alloc failed \n", __func__);
|
||||
memset(msg,0,len);
|
||||
return msg;
|
||||
}
|
||||
|
||||
void intf_tcp_drop_msg(struct rwnx_hw *priv,
|
||||
struct msg_buf *msg)
|
||||
{
|
||||
//printk("%s \n",__func__);
|
||||
if (msg->skb)
|
||||
dev_kfree_skb_any(msg->skb);
|
||||
|
||||
kfree(msg);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
|
||||
void tcp_ack_timeout(unsigned long data)
|
||||
#else
|
||||
void tcp_ack_timeout(struct timer_list *t)
|
||||
#endif
|
||||
{
|
||||
//printk("%s \n",__func__);
|
||||
struct tcp_ack_info *ack_info;
|
||||
struct msg_buf *msg;
|
||||
struct tcp_ack_manage *ack_m = NULL;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
|
||||
ack_info = (struct tcp_ack_info *)data;
|
||||
#else
|
||||
ack_info = container_of(t,struct tcp_ack_info,timer);
|
||||
#endif
|
||||
|
||||
ack_m = container_of(ack_info, struct tcp_ack_manage,
|
||||
ack_info[ack_info->ack_info_num]);
|
||||
|
||||
write_seqlock_bh(&ack_info->seqlock);
|
||||
msg = ack_info->msgbuf;
|
||||
if (ack_info->busy && msg && !ack_info->in_send_msg) {
|
||||
ack_info->msgbuf = NULL;
|
||||
ack_info->drop_cnt = 0;
|
||||
ack_info->in_send_msg = msg;
|
||||
write_sequnlock_bh(&ack_info->seqlock);
|
||||
intf_tx(ack_m->priv, msg);//send skb
|
||||
//ack_info->in_send_msg = NULL;//add by dwx
|
||||
//write_sequnlock_bh(&ack_info->seqlock);
|
||||
//intf_tx(ack_m->priv, msg);
|
||||
return;
|
||||
}
|
||||
write_sequnlock_bh(&ack_info->seqlock);
|
||||
}
|
||||
|
||||
void tcp_ack_init(struct rwnx_hw *priv)
|
||||
{
|
||||
int i;
|
||||
struct tcp_ack_info *ack_info;
|
||||
struct tcp_ack_manage *ack_m = &priv->ack_m;
|
||||
|
||||
printk("========== tcp ack debug %s \n",__func__);
|
||||
memset(ack_m, 0, sizeof(struct tcp_ack_manage));
|
||||
ack_m->priv = priv;
|
||||
spin_lock_init(&ack_m->lock);
|
||||
atomic_set(&ack_m->max_drop_cnt, TCP_ACK_DROP_CNT);
|
||||
ack_m->last_time = jiffies;
|
||||
ack_m->timeout = msecs_to_jiffies(ACK_OLD_TIME);
|
||||
|
||||
for (i = 0; i < TCP_ACK_NUM; i++) {
|
||||
ack_info = &ack_m->ack_info[i];
|
||||
ack_info->ack_info_num = i;
|
||||
seqlock_init(&ack_info->seqlock);
|
||||
ack_info->last_time = jiffies;
|
||||
ack_info->timeout = msecs_to_jiffies(ACK_OLD_TIME);
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
|
||||
setup_timer(&ack_info->timer, tcp_ack_timeout,
|
||||
(unsigned long)ack_info);
|
||||
#else
|
||||
timer_setup(&ack_info->timer,tcp_ack_timeout,0);
|
||||
#endif
|
||||
}
|
||||
|
||||
atomic_set(&ack_m->enable, 1);
|
||||
ack_m->ack_winsize = MIN_WIN;
|
||||
}
|
||||
|
||||
void tcp_ack_deinit(struct rwnx_hw *priv)
|
||||
{
|
||||
int i;
|
||||
struct tcp_ack_manage *ack_m = &priv->ack_m;
|
||||
struct msg_buf *drop_msg = NULL;
|
||||
|
||||
printk("%s \n",__func__);
|
||||
atomic_set(&ack_m->enable, 0);
|
||||
|
||||
for (i = 0; i < TCP_ACK_NUM; i++) {
|
||||
drop_msg = NULL;
|
||||
|
||||
write_seqlock_bh(&ack_m->ack_info[i].seqlock);
|
||||
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);
|
||||
|
||||
if (drop_msg)
|
||||
intf_tcp_drop_msg(priv, drop_msg);//drop skb
|
||||
}
|
||||
}
|
||||
|
||||
int tcp_check_quick_ack(unsigned char *buf,
|
||||
struct tcp_ack_msg *msg)
|
||||
{
|
||||
int ip_hdr_len;
|
||||
unsigned char *temp;
|
||||
struct ethhdr *ethhdr;
|
||||
struct iphdr *iphdr;
|
||||
struct tcphdr *tcphdr;
|
||||
|
||||
ethhdr = (struct ethhdr *)buf;
|
||||
if (ethhdr->h_proto != htons(ETH_P_IP))
|
||||
return 0;
|
||||
iphdr = (struct iphdr *)(ethhdr + 1);
|
||||
if (iphdr->version != 4 || iphdr->protocol != IPPROTO_TCP)
|
||||
return 0;
|
||||
ip_hdr_len = iphdr->ihl * 4;
|
||||
temp = (unsigned char *)(iphdr) + ip_hdr_len;
|
||||
tcphdr = (struct tcphdr *)temp;
|
||||
/* TCP_FLAG_ACK */
|
||||
if (!(temp[13] & 0x10))
|
||||
return 0;
|
||||
|
||||
if (temp[13] & 0x8) {
|
||||
msg->saddr = iphdr->daddr;
|
||||
msg->daddr = iphdr->saddr;
|
||||
msg->source = tcphdr->dest;
|
||||
msg->dest = tcphdr->source;
|
||||
msg->seq = ntohl(tcphdr->seq);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int is_drop_tcp_ack(struct tcphdr *tcphdr, int tcp_tot_len,
|
||||
unsigned short *win_scale)
|
||||
{
|
||||
//printk("%s \n",__func__);
|
||||
int drop = 1;
|
||||
int len = tcphdr->doff * 4;
|
||||
unsigned char *ptr;
|
||||
|
||||
if(tcp_tot_len > len) {
|
||||
drop = 0;
|
||||
} else {
|
||||
len -= sizeof(struct tcphdr);
|
||||
ptr = (unsigned char *)(tcphdr + 1);
|
||||
|
||||
while ((len > 0) && drop) {
|
||||
int opcode = *ptr++;
|
||||
int opsize;
|
||||
|
||||
switch (opcode) {
|
||||
case TCPOPT_EOL:
|
||||
break;
|
||||
case TCPOPT_NOP:
|
||||
len--;
|
||||
continue;
|
||||
default:
|
||||
opsize = *ptr++;
|
||||
if (opsize < 2)
|
||||
break;
|
||||
if (opsize > len)
|
||||
break;
|
||||
|
||||
switch (opcode) {
|
||||
/* TODO: Add other ignore opt */
|
||||
case TCPOPT_TIMESTAMP:
|
||||
break;
|
||||
case TCPOPT_WINDOW:
|
||||
if (*ptr < 15)
|
||||
*win_scale = (1 << (*ptr));
|
||||
printk("%d\n",*win_scale);
|
||||
break;
|
||||
default:
|
||||
drop = 2;
|
||||
}
|
||||
|
||||
ptr += opsize - 2;
|
||||
len -= opsize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return drop;
|
||||
}
|
||||
|
||||
|
||||
/* flag:0 for not tcp ack
|
||||
* 1 for ack which can be drop
|
||||
* 2 for other ack whith more info
|
||||
*/
|
||||
|
||||
int tcp_check_ack(unsigned char *buf,
|
||||
struct tcp_ack_msg *msg,
|
||||
unsigned short *win_scale)
|
||||
{
|
||||
int ret;
|
||||
int ip_hdr_len;
|
||||
int tcp_tot_len;
|
||||
unsigned char *temp;
|
||||
struct ethhdr *ethhdr;
|
||||
struct iphdr *iphdr;
|
||||
struct tcphdr *tcphdr;
|
||||
|
||||
ethhdr =(struct ethhdr *)buf;
|
||||
if (ethhdr->h_proto != htons(ETH_P_IP))
|
||||
return 0;
|
||||
|
||||
iphdr = (struct iphdr *)(ethhdr + 1);
|
||||
if (iphdr->version != 4 || iphdr->protocol != IPPROTO_TCP)
|
||||
return 0;
|
||||
|
||||
ip_hdr_len = iphdr->ihl * 4;
|
||||
temp = (unsigned char *)(iphdr) + ip_hdr_len;
|
||||
tcphdr = (struct tcphdr *)temp;
|
||||
/* TCP_FLAG_ACK */
|
||||
if (!(temp[13] & 0x10))
|
||||
return 0;
|
||||
|
||||
tcp_tot_len = ntohs(iphdr->tot_len) - ip_hdr_len;// tcp total len
|
||||
ret = is_drop_tcp_ack(tcphdr, tcp_tot_len, win_scale);
|
||||
//printk("is drop:%d \n",ret);
|
||||
|
||||
if (ret > 0) {
|
||||
msg->saddr = iphdr->saddr;
|
||||
msg->daddr = iphdr->daddr;
|
||||
msg->source = tcphdr->source;
|
||||
msg->dest = tcphdr->dest;
|
||||
msg->seq = ntohl(tcphdr->ack_seq);
|
||||
msg->win = ntohs(tcphdr->window);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* return val: -1 for not match, others for match */
|
||||
int tcp_ack_match(struct tcp_ack_manage *ack_m,
|
||||
struct tcp_ack_msg *ack_msg)
|
||||
{
|
||||
int i, ret = -1;
|
||||
unsigned start;
|
||||
struct tcp_ack_info *ack_info;
|
||||
struct tcp_ack_msg *ack;
|
||||
|
||||
for (i = 0; ((ret < 0) && (i < TCP_ACK_NUM)); i++) {
|
||||
ack_info = &ack_m->ack_info[i];
|
||||
do {
|
||||
start = read_seqbegin(&ack_info->seqlock);
|
||||
ret = -1;
|
||||
|
||||
ack = &ack_info->ack_msg;
|
||||
if (ack_info->busy &&
|
||||
ack->dest == ack_msg->dest &&
|
||||
ack->source == ack_msg->source &&
|
||||
ack->saddr == ack_msg->saddr &&
|
||||
ack->daddr == ack_msg->daddr)
|
||||
ret = i;
|
||||
} while(read_seqretry(&ack_info->seqlock, start));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void tcp_ack_update(struct tcp_ack_manage *ack_m)
|
||||
{
|
||||
int i;
|
||||
struct tcp_ack_info *ack_info;
|
||||
|
||||
if (time_after(jiffies, ack_m->last_time + ack_m->timeout)) {
|
||||
spin_lock_bh(&ack_m->lock);
|
||||
ack_m->last_time = jiffies;
|
||||
for (i = TCP_ACK_NUM - 1; i >= 0; i--) {
|
||||
ack_info = &ack_m->ack_info[i];
|
||||
write_seqlock_bh(&ack_info->seqlock);
|
||||
if (ack_info->busy &&
|
||||
time_after(jiffies, ack_info->last_time +
|
||||
ack_info->timeout)) {
|
||||
ack_m->free_index = i;
|
||||
ack_m->max_num--;
|
||||
ack_info->busy = 0;
|
||||
}
|
||||
write_sequnlock_bh(&ack_info->seqlock);
|
||||
}
|
||||
spin_unlock_bh(&ack_m->lock);
|
||||
}
|
||||
}
|
||||
|
||||
/* return val: -1 for no index, others for index */
|
||||
int tcp_ack_alloc_index(struct tcp_ack_manage *ack_m)
|
||||
{
|
||||
int i, ret = -1;
|
||||
struct tcp_ack_info *ack_info;
|
||||
unsigned start;
|
||||
|
||||
spin_lock_bh(&ack_m->lock);
|
||||
if (ack_m->max_num == TCP_ACK_NUM) {
|
||||
spin_unlock_bh(&ack_m->lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ack_m->free_index >= 0) {
|
||||
i = ack_m->free_index;
|
||||
ack_m->free_index = -1;
|
||||
ack_m->max_num++;
|
||||
spin_unlock_bh(&ack_m->lock);
|
||||
return i;
|
||||
}
|
||||
|
||||
for (i = 0; ((ret < 0) && (i < TCP_ACK_NUM)); i++) {
|
||||
ack_info = &ack_m->ack_info[i];
|
||||
do {
|
||||
start = read_seqbegin(&ack_info->seqlock);
|
||||
ret = -1;
|
||||
if (!ack_info->busy) {
|
||||
ack_m->free_index = -1;
|
||||
ack_m->max_num++;
|
||||
ret = i;
|
||||
}
|
||||
} while(read_seqretry(&ack_info->seqlock, start));
|
||||
}
|
||||
spin_unlock_bh(&ack_m->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* return val: 0 for not handle tx, 1 for handle tx */
|
||||
int tcp_ack_handle(struct msg_buf *new_msgbuf,
|
||||
struct tcp_ack_manage *ack_m,
|
||||
struct tcp_ack_info *ack_info,
|
||||
struct tcp_ack_msg *ack_msg,
|
||||
int type)
|
||||
{
|
||||
int quick_ack = 0;
|
||||
struct tcp_ack_msg *ack;
|
||||
int ret = 0;
|
||||
struct msg_buf *drop_msg = NULL;
|
||||
|
||||
//printk("%s %d",__func__,type);
|
||||
write_seqlock_bh(&ack_info->seqlock);
|
||||
|
||||
ack_info->last_time = jiffies;
|
||||
ack = &ack_info->ack_msg;
|
||||
|
||||
if (type == 2) {
|
||||
if (U32_BEFORE(ack->seq, ack_msg->seq)) {
|
||||
ack->seq = ack_msg->seq;
|
||||
if (ack_info->psh_flag &&
|
||||
!U32_BEFORE(ack_msg->seq,
|
||||
ack_info->psh_seq)) {
|
||||
ack_info->psh_flag = 0;
|
||||
}
|
||||
|
||||
if (ack_info->msgbuf) {
|
||||
//printk("%lx \n",ack_info->msgbuf);
|
||||
drop_msg = ack_info->msgbuf;
|
||||
ack_info->msgbuf = NULL;
|
||||
del_timer(&ack_info->timer);
|
||||
}else{
|
||||
//printk("msgbuf is NULL \n");
|
||||
}
|
||||
|
||||
ack_info->in_send_msg = NULL;
|
||||
ack_info->drop_cnt = atomic_read(&ack_m->max_drop_cnt);
|
||||
} else {
|
||||
printk("%s before abnormal ack: %d, %d\n",
|
||||
__func__, ack->seq, ack_msg->seq);
|
||||
drop_msg = new_msgbuf;
|
||||
ret = 1;
|
||||
}
|
||||
} else if (U32_BEFORE(ack->seq, ack_msg->seq)) {
|
||||
if (ack_info->msgbuf) {
|
||||
drop_msg = ack_info->msgbuf;
|
||||
ack_info->msgbuf = NULL;
|
||||
}
|
||||
|
||||
if (ack_info->psh_flag &&
|
||||
!U32_BEFORE(ack_msg->seq, ack_info->psh_seq)) {
|
||||
ack_info->psh_flag = 0;
|
||||
quick_ack = 1;
|
||||
} else {
|
||||
ack_info->drop_cnt++;
|
||||
}
|
||||
|
||||
ack->seq = ack_msg->seq;
|
||||
|
||||
if (quick_ack || (!ack_info->in_send_msg &&
|
||||
(ack_info->drop_cnt >=
|
||||
atomic_read(&ack_m->max_drop_cnt)))) {
|
||||
ack_info->drop_cnt = 0;
|
||||
ack_info->in_send_msg = new_msgbuf;
|
||||
del_timer(&ack_info->timer);
|
||||
} else {
|
||||
ret = 1;
|
||||
ack_info->msgbuf = new_msgbuf;
|
||||
if (!timer_pending(&ack_info->timer))
|
||||
mod_timer(&ack_info->timer,
|
||||
(jiffies + msecs_to_jiffies(5)));
|
||||
}
|
||||
} else {
|
||||
printk("%s before ack: %d, %d\n",
|
||||
__func__, ack->seq, ack_msg->seq);
|
||||
drop_msg = new_msgbuf;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
write_sequnlock_bh(&ack_info->seqlock);
|
||||
|
||||
if (drop_msg)
|
||||
intf_tcp_drop_msg(ack_m->priv, drop_msg);// drop skb
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tcp_ack_handle_new(struct msg_buf *new_msgbuf,
|
||||
struct tcp_ack_manage *ack_m,
|
||||
struct tcp_ack_info *ack_info,
|
||||
struct tcp_ack_msg *ack_msg,
|
||||
int type)
|
||||
{
|
||||
int quick_ack = 0;
|
||||
struct tcp_ack_msg *ack;
|
||||
int ret = 0;
|
||||
struct msg_buf *drop_msg = NULL;
|
||||
struct msg_buf * send_msg = NULL;
|
||||
//printk("",);
|
||||
write_seqlock_bh(&ack_info->seqlock);
|
||||
|
||||
ack_info->last_time = jiffies;
|
||||
ack = &ack_info->ack_msg;
|
||||
|
||||
if(U32_BEFORE(ack->seq, ack_msg->seq)){
|
||||
if (ack_info->msgbuf) {
|
||||
drop_msg = ack_info->msgbuf;
|
||||
ack_info->msgbuf = NULL;
|
||||
//ack_info->drop_cnt++;
|
||||
}
|
||||
|
||||
if (ack_info->psh_flag &&
|
||||
!U32_BEFORE(ack_msg->seq, ack_info->psh_seq)) {
|
||||
ack_info->psh_flag = 0;
|
||||
quick_ack = 1;
|
||||
} else {
|
||||
ack_info->drop_cnt++;
|
||||
}
|
||||
|
||||
ack->seq = ack_msg->seq;
|
||||
|
||||
if(quick_ack || (!ack_info->in_send_msg &&
|
||||
(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;
|
||||
del_timer(&ack_info->timer);
|
||||
}else{
|
||||
ret = 1;
|
||||
ack_info->msgbuf = new_msgbuf;
|
||||
if (!timer_pending(&ack_info->timer))
|
||||
mod_timer(&ack_info->timer,
|
||||
(jiffies + msecs_to_jiffies(5)));
|
||||
}
|
||||
|
||||
//ret = 1;
|
||||
}else {
|
||||
printk("%s before ack: %d, %d\n",
|
||||
__func__, ack->seq, ack_msg->seq);
|
||||
drop_msg = new_msgbuf;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
/*if(send_msg){
|
||||
intf_tx(ack_m->priv,send_msg);
|
||||
ack_info->in_send_msg=NULL;
|
||||
}*/
|
||||
|
||||
//ack_info->in_send_msg=NULL;
|
||||
|
||||
write_sequnlock_bh(&ack_info->seqlock);
|
||||
|
||||
/*if(send_msg){
|
||||
intf_tx(ack_m->priv,send_msg);
|
||||
//ack_info->in_send_msg=NULL;
|
||||
}*/
|
||||
|
||||
if (drop_msg)
|
||||
intf_tcp_drop_msg(ack_m->priv, drop_msg);// drop skb
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
void filter_rx_tcp_ack(struct rwnx_hw *priv,
|
||||
unsigned char *buf, unsigned plen)
|
||||
{
|
||||
int index;
|
||||
struct tcp_ack_msg ack_msg;
|
||||
struct tcp_ack_info *ack_info;
|
||||
struct tcp_ack_manage *ack_m = &priv->ack_m;
|
||||
|
||||
if (!atomic_read(&ack_m->enable))
|
||||
return;
|
||||
|
||||
if ((plen > MAX_TCP_ACK) ||
|
||||
!tcp_check_quick_ack(buf, &ack_msg))
|
||||
return;
|
||||
|
||||
index = tcp_ack_match(ack_m, &ack_msg);
|
||||
if (index >= 0) {
|
||||
ack_info = ack_m->ack_info + index;
|
||||
write_seqlock_bh(&ack_info->seqlock);
|
||||
ack_info->psh_flag = 1;
|
||||
ack_info->psh_seq = ack_msg.seq;
|
||||
write_sequnlock_bh(&ack_info->seqlock);
|
||||
}
|
||||
}
|
||||
|
||||
/* return val: 0 for not filter, 1 for filter */
|
||||
int filter_send_tcp_ack(struct rwnx_hw *priv,
|
||||
struct msg_buf *msgbuf,
|
||||
unsigned char *buf, unsigned int plen)
|
||||
{
|
||||
// printk("%s \n",__func__);
|
||||
int ret = 0;
|
||||
int index, drop;
|
||||
unsigned short win_scale = 0;
|
||||
unsigned int win = 0;
|
||||
struct tcp_ack_msg ack_msg;
|
||||
struct tcp_ack_msg *ack;
|
||||
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);
|
||||
if (!drop && (0 == win_scale))
|
||||
return 0;
|
||||
|
||||
index = tcp_ack_match(ack_m, &ack_msg);
|
||||
if (index >= 0) {
|
||||
ack_info = ack_m->ack_info + index;
|
||||
if ((0 != win_scale) &&
|
||||
(ack_info->win_scale != win_scale)) {
|
||||
write_seqlock_bh(&ack_info->seqlock);
|
||||
ack_info->win_scale = win_scale;
|
||||
write_sequnlock_bh(&ack_info->seqlock);
|
||||
}
|
||||
|
||||
if (drop > 0 && atomic_read(&ack_m->enable)) {
|
||||
win = ack_info->win_scale * ack_msg.win;
|
||||
if ((win_scale!=0) && (win < (ack_m->ack_winsize * SIZE_KB)))
|
||||
{
|
||||
drop = 2;
|
||||
printk("%d %d %d",win_scale,win,(ack_m->ack_winsize * SIZE_KB));
|
||||
}
|
||||
ret = tcp_ack_handle_new(msgbuf, ack_m, ack_info,
|
||||
&ack_msg, drop);
|
||||
}
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
index = tcp_ack_alloc_index(ack_m);
|
||||
if (index >= 0) {
|
||||
write_seqlock_bh(&ack_m->ack_info[index].seqlock);
|
||||
ack_m->ack_info[index].busy = 1;
|
||||
ack_m->ack_info[index].psh_flag = 0;
|
||||
ack_m->ack_info[index].last_time = jiffies;
|
||||
ack_m->ack_info[index].drop_cnt =
|
||||
atomic_read(&ack_m->max_drop_cnt);
|
||||
ack_m->ack_info[index].win_scale =
|
||||
(win_scale != 0) ? win_scale : 1;
|
||||
|
||||
//ack_m->ack_info[index].msgbuf = NULL;
|
||||
//ack_m->ack_info[index].in_send_msg = NULL;
|
||||
ack = &ack_m->ack_info[index].ack_msg;
|
||||
ack->dest = ack_msg.dest;
|
||||
ack->source = ack_msg.source;
|
||||
ack->saddr = ack_msg.saddr;
|
||||
ack->daddr = ack_msg.daddr;
|
||||
ack->seq = ack_msg.seq;
|
||||
write_sequnlock_bh(&ack_m->ack_info[index].seqlock);
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void move_tcpack_msg(struct rwnx_hw *priv,
|
||||
struct msg_buf *msg)
|
||||
{
|
||||
struct tcp_ack_info *ack_info;
|
||||
struct tcp_ack_manage *ack_m = &priv->ack_m;
|
||||
int i = 0;
|
||||
|
||||
if (!atomic_read(&ack_m->enable))
|
||||
return;
|
||||
|
||||
//if (msg->len > MAX_TCP_ACK)
|
||||
// return;
|
||||
|
||||
for (i = 0; i < TCP_ACK_NUM; i++) {
|
||||
ack_info = &ack_m->ack_info[i];
|
||||
write_seqlock_bh(&ack_info->seqlock);
|
||||
if (ack_info->busy && (ack_info->in_send_msg == msg))
|
||||
ack_info->in_send_msg = NULL;
|
||||
write_sequnlock_bh(&ack_info->seqlock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
#ifndef _AICWF_TCP_ACK_H_
|
||||
#define _AICWF_TCP_ACK_H_
|
||||
|
||||
#include <uapi/linux/if_ether.h>
|
||||
#include <uapi/linux/tcp.h>
|
||||
#include <uapi/linux/ip.h>
|
||||
#include <uapi/linux/in.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <net/tcp.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
|
||||
#define TCP_ACK_NUM 32
|
||||
#define TCP_ACK_EXIT_VAL 0x800
|
||||
#define TCP_ACK_DROP_CNT 10
|
||||
|
||||
#define ACK_OLD_TIME 4000
|
||||
#define U32_BEFORE(a, b) ((__s32)((__u32)a - (__u32)b) <= 0)
|
||||
|
||||
#define MAX_TCP_ACK 200
|
||||
/*min window size in KB, it's 256KB*/
|
||||
#define MIN_WIN 256
|
||||
#define SIZE_KB 1024
|
||||
|
||||
|
||||
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 {
|
||||
u16 source;
|
||||
u16 dest;
|
||||
s32 saddr;
|
||||
s32 daddr;
|
||||
u32 seq;
|
||||
u16 win;
|
||||
};
|
||||
|
||||
|
||||
struct tcp_ack_info {
|
||||
int ack_info_num;
|
||||
int busy;
|
||||
int drop_cnt;
|
||||
int psh_flag;
|
||||
u32 psh_seq;
|
||||
u16 win_scale;
|
||||
/* seqlock for ack info */
|
||||
seqlock_t seqlock;
|
||||
unsigned long last_time;
|
||||
unsigned long timeout;
|
||||
struct timer_list timer;
|
||||
struct msg_buf *msgbuf;
|
||||
struct msg_buf *in_send_msg;
|
||||
struct tcp_ack_msg ack_msg;
|
||||
};
|
||||
|
||||
struct tcp_ack_manage {
|
||||
/* 1 filter */
|
||||
atomic_t enable;
|
||||
int max_num;
|
||||
int free_index;
|
||||
unsigned long last_time;
|
||||
unsigned long timeout;
|
||||
atomic_t max_drop_cnt;
|
||||
/* lock for tcp ack alloc and free */
|
||||
spinlock_t lock;
|
||||
struct rwnx_hw *priv;
|
||||
struct tcp_ack_info ack_info[TCP_ACK_NUM];
|
||||
/*size in KB*/
|
||||
unsigned int ack_winsize;
|
||||
};
|
||||
|
||||
struct msg_buf *intf_tcp_alloc_msg(struct msg_buf *msg);
|
||||
|
||||
void tcp_ack_init(struct rwnx_hw *priv);
|
||||
|
||||
void tcp_ack_deinit(struct rwnx_hw *priv);
|
||||
|
||||
|
||||
int is_drop_tcp_ack(struct tcphdr *tcphdr, int tcp_tot_len, unsigned short *win_scale);
|
||||
|
||||
int is_tcp_ack(struct sk_buff *skb, unsigned short *win_scale);
|
||||
|
||||
int filter_send_tcp_ack(struct rwnx_hw *priv, struct msg_buf *msgbuf,unsigned char *buf, unsigned int plen);
|
||||
|
||||
void filter_rx_tcp_ack(struct rwnx_hw *priv,unsigned char *buf, unsigned plen);
|
||||
|
||||
void move_tcpack_msg(struct rwnx_hw *priv, struct msg_buf * msg);
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,304 @@
|
||||
/**
|
||||
* aicwf_txrxif.h
|
||||
*
|
||||
* bus function declarations
|
||||
*
|
||||
* Copyright (C) AICSemi 2018-2020
|
||||
*/
|
||||
|
||||
#ifndef _AICWF_TXRXIF_H_
|
||||
#define _AICWF_TXRXIF_H_
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/sched.h>
|
||||
#include "ipc_shared.h"
|
||||
#include "aicwf_rx_prealloc.h"
|
||||
#ifdef AICWF_SDIO_SUPPORT
|
||||
#include "aicwf_sdio.h"
|
||||
#else
|
||||
#include "aicwf_usb.h"
|
||||
#endif
|
||||
|
||||
#define CMD_BUF_MAX 1536
|
||||
#define DATA_BUF_MAX 2048
|
||||
#define TXPKT_BLOCKSIZE 512
|
||||
#define MAX_AGGR_TXPKT_LEN (1536*64)
|
||||
#define CMD_TX_TIMEOUT 5000
|
||||
#define TX_ALIGNMENT 4
|
||||
|
||||
#ifdef CONFIG_USB_TX_AGGR
|
||||
#define MAX_USB_AGGR_TXPKT_LEN (1536*15)
|
||||
#endif
|
||||
|
||||
#define RX_HWHRD_LEN 60 //58->60 word allined
|
||||
#define CCMP_OR_WEP_INFO 8
|
||||
#define MAX_RXQLEN 2000
|
||||
#define RX_ALIGNMENT 4
|
||||
|
||||
#define DEBUG_ERROR_LEVEL 0
|
||||
#define DEBUG_DEBUG_LEVEL 1
|
||||
#define DEBUG_INFO_LEVEL 2
|
||||
|
||||
#define DBG_LEVEL DEBUG_DEBUG_LEVEL
|
||||
|
||||
#define txrx_err(fmt, ...) pr_err("txrx_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__)
|
||||
#define sdio_err(fmt, ...) pr_err("sdio_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__)
|
||||
#define usb_err(fmt, ...) pr_err("usb_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__)
|
||||
#if DBG_LEVEL >= DEBUG_DEBUG_LEVEL
|
||||
#define txrx_dbg(fmt, ...) printk("txrx: " fmt, ##__VA_ARGS__)
|
||||
#define sdio_dbg(fmt, ...) printk("aicsdio: " fmt, ##__VA_ARGS__)
|
||||
#define usb_dbg(fmt, ...) printk("aicusb: " fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define txrx_dbg(fmt, ...)
|
||||
#define sdio_dbg(fmt, ...)
|
||||
#define usb_dbg(fmt, ...)
|
||||
#endif
|
||||
#if DBG_LEVEL >= DEBUG_INFO_LEVEL
|
||||
#define txrx_info(fmt, ...) printk("aicsdio: " fmt, ##__VA_ARGS__)
|
||||
#define sdio_info(fmt, ...) printk("aicsdio: " fmt, ##__VA_ARGS__)
|
||||
#define usb_info(fmt, ...) printk("aicusb: " fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define txrx_info(fmt, ...)
|
||||
#define sdio_info(fmt, ...)
|
||||
#define usb_info(fmt, ...)
|
||||
#endif
|
||||
|
||||
enum aicwf_bus_state {
|
||||
BUS_DOWN_ST,
|
||||
BUS_UP_ST
|
||||
};
|
||||
|
||||
struct aicwf_bus_ops {
|
||||
int (*start) (struct device * dev);
|
||||
void (*stop) (struct device * dev);
|
||||
int (*txdata) (struct device * dev, struct sk_buff * skb);
|
||||
int (*txmsg) (struct device * dev, u8 * msg, uint len);
|
||||
};
|
||||
|
||||
struct frame_queue {
|
||||
u16 num_prio;
|
||||
u16 hi_prio;
|
||||
u16 qmax; /* max number of queued frames */
|
||||
u16 qcnt;
|
||||
struct sk_buff_head queuelist[8];
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PREALLOC_RX_SKB
|
||||
struct rx_frame_queue {
|
||||
u16 qmax; /* max number of queued frames */
|
||||
u16 qcnt;
|
||||
struct list_head queuelist;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct aicwf_bus {
|
||||
union {
|
||||
struct aic_sdio_dev *sdio;
|
||||
struct aic_usb_dev *usb;
|
||||
} bus_priv;
|
||||
struct device *dev;
|
||||
struct aicwf_bus_ops *ops;
|
||||
enum aicwf_bus_state state;
|
||||
u8 *cmd_buf;
|
||||
struct completion bustx_trgg;
|
||||
struct completion busrx_trgg;
|
||||
#ifdef CONFIG_USB_MSG_IN_EP
|
||||
struct completion msg_busrx_trgg;
|
||||
#endif
|
||||
|
||||
struct task_struct *bustx_thread;
|
||||
struct task_struct *busrx_thread;
|
||||
#ifdef CONFIG_USB_MSG_IN_EP
|
||||
struct task_struct *msg_busrx_thread;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
struct aicwf_tx_priv {
|
||||
#ifdef AICWF_SDIO_SUPPORT
|
||||
struct aic_sdio_dev *sdiodev;
|
||||
int fw_avail_bufcnt;
|
||||
//for cmd tx
|
||||
u8 *cmd_buf;
|
||||
uint cmd_len;
|
||||
bool cmd_txstate;
|
||||
bool cmd_tx_succ;
|
||||
struct semaphore cmd_txsema;
|
||||
wait_queue_head_t cmd_txdone_wait;
|
||||
//for data tx
|
||||
atomic_t tx_pktcnt;
|
||||
|
||||
struct frame_queue txq;
|
||||
spinlock_t txqlock;
|
||||
struct semaphore txctl_sema;
|
||||
#endif
|
||||
#ifdef AICWF_USB_SUPPORT
|
||||
struct aic_usb_dev *usbdev;
|
||||
#ifdef CONFIG_USB_TX_AGGR
|
||||
int fw_avail_bufcnt;
|
||||
|
||||
//for data tx
|
||||
atomic_t tx_pktcnt;
|
||||
|
||||
struct frame_queue txq;
|
||||
spinlock_t txqlock;
|
||||
spinlock_t txdlock;
|
||||
#endif
|
||||
#endif//AICWF_USB_SUPPORT
|
||||
struct sk_buff *aggr_buf;
|
||||
atomic_t aggr_count;
|
||||
u8 *head;
|
||||
u8 *tail;
|
||||
};
|
||||
|
||||
|
||||
#ifdef AICWF_RX_REORDER
|
||||
#define MAX_REORD_RXFRAME 250
|
||||
#define REORDER_UPDATE_TIME 500//50
|
||||
#define AICWF_REORDER_WINSIZE 64
|
||||
//SN_LESS(a, b) a-b<0 is ture
|
||||
#define SN_LESS(a, b) (((a-b)&0x800)!=0)
|
||||
#define SN_EQUAL(a, b) (a == b)
|
||||
|
||||
struct reord_ctrl {
|
||||
struct aicwf_rx_priv *rx_priv;
|
||||
u8 enable;
|
||||
u16 ind_sn;
|
||||
u8 wsize_b;
|
||||
spinlock_t reord_list_lock;
|
||||
struct list_head reord_list;
|
||||
struct timer_list reord_timer;
|
||||
struct work_struct reord_timer_work;
|
||||
};
|
||||
|
||||
struct reord_ctrl_info {
|
||||
u8 mac_addr[6];
|
||||
struct reord_ctrl preorder_ctrl[8];
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
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 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;
|
||||
struct reord_ctrl *preorder_ctrl;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct aicwf_rx_priv {
|
||||
#ifdef AICWF_SDIO_SUPPORT
|
||||
struct aic_sdio_dev *sdiodev;
|
||||
#endif
|
||||
#ifdef AICWF_USB_SUPPORT
|
||||
struct aic_usb_dev *usbdev;
|
||||
#endif
|
||||
|
||||
void *rwnx_vif;
|
||||
atomic_t rx_cnt;
|
||||
u32 data_len;
|
||||
spinlock_t rxqlock;
|
||||
#ifdef CONFIG_PREALLOC_RX_SKB
|
||||
struct rx_frame_queue rxq;
|
||||
#else
|
||||
struct frame_queue rxq;
|
||||
#endif
|
||||
#ifdef CONFIG_USB_RX_REASSEMBLE
|
||||
struct sk_buff *rx_reassemble_skb;
|
||||
u32 rx_reassemble_total_len;
|
||||
u32 rx_reassemble_cur_len;
|
||||
u32 rx_reassemble_total_frags;
|
||||
u32 rx_reassemble_cur_frags;
|
||||
|
||||
struct sk_buff *rx_msg_reassemble_skb;
|
||||
u32 rx_msg_reassemble_total_len;
|
||||
u32 rx_msg_reassemble_cur_len;
|
||||
u32 rx_msg_reassemble_total_frags;
|
||||
u32 rx_msg_reassemble_cur_frags;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_MSG_IN_EP
|
||||
atomic_t msg_rx_cnt;
|
||||
spinlock_t msg_rxqlock;
|
||||
struct frame_queue msg_rxq;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef AICWF_RX_REORDER
|
||||
spinlock_t freeq_lock;
|
||||
struct list_head rxframes_freequeue;
|
||||
struct list_head stas_reord_list;
|
||||
spinlock_t stas_reord_lock;
|
||||
struct recv_msdu *recv_frames;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PREALLOC_RX_SKB
|
||||
spinlock_t rxbuff_lock;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
static inline int aicwf_bus_start(struct aicwf_bus *bus)
|
||||
{
|
||||
return bus->ops->start(bus->dev);
|
||||
}
|
||||
|
||||
static inline void aicwf_bus_stop(struct aicwf_bus *bus)
|
||||
{
|
||||
bus->ops->stop(bus->dev);
|
||||
}
|
||||
|
||||
static inline int aicwf_bus_txdata(struct aicwf_bus *bus, struct sk_buff *skb)
|
||||
{
|
||||
return bus->ops->txdata(bus->dev, skb);
|
||||
}
|
||||
|
||||
static inline int aicwf_bus_txmsg(struct aicwf_bus *bus, u8 *msg, uint len)
|
||||
{
|
||||
return bus->ops->txmsg(bus->dev, msg, len);
|
||||
}
|
||||
|
||||
static inline void aicwf_sched_timeout(u32 millisec)
|
||||
{
|
||||
ulong timeout = 0, expires = 0;
|
||||
expires = jiffies + msecs_to_jiffies(millisec);
|
||||
timeout = millisec;
|
||||
|
||||
while (timeout) {
|
||||
timeout = schedule_timeout(timeout);
|
||||
if (time_after(jiffies, expires))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int aicwf_bus_init(uint bus_hdrlen, struct device *dev);
|
||||
void aicwf_bus_deinit(struct device *dev);
|
||||
void aicwf_tx_deinit(struct aicwf_tx_priv* tx_priv);
|
||||
void aicwf_rx_deinit(struct aicwf_rx_priv* rx_priv);
|
||||
struct aicwf_tx_priv* aicwf_tx_init(void *arg);
|
||||
struct aicwf_rx_priv* aicwf_rx_init(void *arg);
|
||||
void aicwf_frame_queue_init(struct frame_queue *pq, int num_prio, int max_len);
|
||||
void aicwf_frame_queue_flush(struct frame_queue *pq);
|
||||
bool aicwf_frame_enq(struct device *dev, struct frame_queue *q, struct sk_buff *pkt, int prio);
|
||||
bool aicwf_rxframe_enqueue(struct device *dev, struct frame_queue *q, struct sk_buff *pkt);
|
||||
bool aicwf_is_framequeue_empty(struct frame_queue *pq);
|
||||
void aicwf_frame_tx(void *dev, struct sk_buff *skb);
|
||||
void aicwf_dev_skb_free(struct sk_buff *skb);
|
||||
struct sk_buff *aicwf_frame_dequeue(struct frame_queue *pq);
|
||||
struct sk_buff *aicwf_frame_queue_peek_tail(struct frame_queue *pq, int *prio_out);
|
||||
#ifdef CONFIG_PREALLOC_RX_SKB
|
||||
void rxbuff_queue_flush(struct aicwf_rx_priv* rx_priv);
|
||||
void aicwf_rxframe_queue_init_2(struct rx_frame_queue *pq, int max_len);
|
||||
void rxbuff_free(struct rx_buff *rxbuff);
|
||||
struct rx_buff *rxbuff_dequeue(struct rx_frame_queue *pq);
|
||||
bool aicwf_rxbuff_enqueue(struct device *dev, struct rx_frame_queue *rxq, struct rx_buff *pkt);
|
||||
extern struct aicwf_rx_buff_list aic_rx_buff_list;
|
||||
#endif
|
||||
|
||||
#endif /* _AICWF_TXRXIF_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,198 @@
|
||||
/**
|
||||
* aicwf_usb.h
|
||||
*
|
||||
* USB function declarations
|
||||
*
|
||||
* Copyright (C) AICSemi 2018-2020
|
||||
*/
|
||||
|
||||
#ifndef _AICWF_USB_H_
|
||||
#define _AICWF_USB_H_
|
||||
|
||||
#include <linux/usb.h>
|
||||
#include "rwnx_cmds.h"
|
||||
|
||||
#ifdef AICWF_USB_SUPPORT
|
||||
|
||||
/* USB Device ID */
|
||||
#define USB_VENDOR_ID_AIC 0xA69C
|
||||
#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
|
||||
#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
|
||||
|
||||
#endif
|
||||
|
||||
enum AICWF_IC{
|
||||
PRODUCT_ID_AIC8801 = 0,
|
||||
PRODUCT_ID_AIC8800DC,
|
||||
PRODUCT_ID_AIC8800DW,
|
||||
PRODUCT_ID_AIC8800D81
|
||||
};
|
||||
|
||||
|
||||
#define AICWF_USB_RX_URBS (20)//(200)
|
||||
#ifdef CONFIG_USB_MSG_IN_EP
|
||||
#define AICWF_USB_MSG_RX_URBS (100)
|
||||
#endif
|
||||
#ifdef CONFIG_USB_TX_AGGR
|
||||
#define TXQLEN (2048*4)
|
||||
#define AICWF_USB_TX_URBS (50)
|
||||
#else
|
||||
#define AICWF_USB_TX_URBS 50//(100)
|
||||
#endif
|
||||
#define AICWF_USB_TX_LOW_WATER (AICWF_USB_TX_URBS/4)//25%
|
||||
#define AICWF_USB_TX_HIGH_WATER (AICWF_USB_TX_LOW_WATER*3)//75%
|
||||
#ifdef CONFIG_PLATFORM_HI
|
||||
#define AICWF_USB_AGGR_MAX_PKT_SIZE (2048*1)
|
||||
#else
|
||||
#define AICWF_USB_AGGR_MAX_PKT_SIZE (2048*10)
|
||||
#endif
|
||||
#define AICWF_USB_MSG_MAX_PKT_SIZE (2048)
|
||||
#define AICWF_USB_MAX_PKT_SIZE (2048)
|
||||
#define AICWF_USB_FC_PERSTA_HIGH_WATER 64
|
||||
#define AICWF_USB_FC_PERSTA_LOW_WATER 16
|
||||
|
||||
|
||||
typedef enum {
|
||||
USB_TYPE_DATA = 0X00,
|
||||
USB_TYPE_CFG = 0X10,
|
||||
USB_TYPE_CFG_CMD_RSP = 0X11,
|
||||
USB_TYPE_CFG_DATA_CFM = 0X12,
|
||||
USB_TYPE_CFG_PRINT = 0X13
|
||||
} usb_type;
|
||||
|
||||
enum aicwf_usb_state {
|
||||
USB_DOWN_ST,
|
||||
USB_UP_ST,
|
||||
USB_SLEEP_ST
|
||||
};
|
||||
|
||||
struct aicwf_usb_buf {
|
||||
struct list_head list;
|
||||
struct aic_usb_dev *usbdev;
|
||||
struct urb *urb;
|
||||
struct sk_buff *skb;
|
||||
#ifdef CONFIG_PREALLOC_RX_SKB
|
||||
struct rx_buff *rx_buff;
|
||||
#endif
|
||||
#ifdef CONFIG_USB_NO_TRANS_DMA_MAP
|
||||
u8 *data_buf;
|
||||
dma_addr_t data_dma_trans_addr;
|
||||
#endif
|
||||
bool cfm;
|
||||
#ifdef CONFIG_USB_TX_AGGR
|
||||
u8 aggr_cnt;
|
||||
#endif
|
||||
u8* usb_align_data;
|
||||
};
|
||||
|
||||
struct aic_usb_dev {
|
||||
struct rwnx_hw *rwnx_hw;
|
||||
struct aicwf_bus *bus_if;
|
||||
struct usb_device *udev;
|
||||
struct device *dev;
|
||||
struct aicwf_rx_priv* rx_priv;
|
||||
enum aicwf_usb_state state;
|
||||
struct rwnx_cmd_mgr cmd_mgr;
|
||||
|
||||
#ifdef CONFIG_USB_TX_AGGR
|
||||
struct aicwf_tx_priv *tx_priv;
|
||||
#endif
|
||||
|
||||
struct usb_anchor rx_submitted;
|
||||
struct work_struct rx_urb_work;
|
||||
#ifdef CONFIG_USB_MSG_IN_EP
|
||||
struct usb_anchor msg_rx_submitted;
|
||||
struct work_struct msg_rx_urb_work;
|
||||
#endif
|
||||
|
||||
spinlock_t rx_free_lock;
|
||||
spinlock_t tx_free_lock;
|
||||
spinlock_t tx_post_lock;
|
||||
spinlock_t tx_flow_lock;
|
||||
#ifdef CONFIG_USB_MSG_IN_EP
|
||||
spinlock_t msg_rx_free_lock;
|
||||
#endif
|
||||
|
||||
struct list_head rx_free_list;
|
||||
struct list_head tx_free_list;
|
||||
struct list_head tx_post_list;
|
||||
#ifdef CONFIG_USB_MSG_IN_EP
|
||||
struct list_head msg_rx_free_list;
|
||||
#endif
|
||||
|
||||
uint bulk_in_pipe;
|
||||
uint bulk_out_pipe;
|
||||
#ifdef CONFIG_USB_MSG_OUT_EP
|
||||
uint msg_out_pipe;
|
||||
#endif
|
||||
#ifdef CONFIG_USB_MSG_IN_EP
|
||||
uint msg_in_pipe;
|
||||
#endif
|
||||
|
||||
int tx_free_count;
|
||||
int tx_post_count;
|
||||
bool rx_prepare_ready;
|
||||
#if 0
|
||||
struct aicwf_usb_buf usb_tx_buf[AICWF_USB_TX_URBS];
|
||||
struct aicwf_usb_buf usb_rx_buf[AICWF_USB_RX_URBS];
|
||||
#else
|
||||
struct aicwf_usb_buf *usb_tx_buf;
|
||||
struct aicwf_usb_buf *usb_rx_buf;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_MSG_IN_EP
|
||||
struct aicwf_usb_buf usb_msg_rx_buf[AICWF_USB_MSG_RX_URBS];
|
||||
#endif
|
||||
|
||||
int msg_finished;
|
||||
wait_queue_head_t msg_wait;
|
||||
ulong msg_busy;
|
||||
struct urb *msg_out_urb;
|
||||
#ifdef CONFIG_USB_NO_TRANS_DMA_MAP
|
||||
dma_addr_t cmd_dma_trans_addr;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RX_TASKLET//AIDEN tasklet
|
||||
struct tasklet_struct recv_tasklet;
|
||||
#endif
|
||||
#ifdef CONFIG_TX_TASKLET//AIDEN tasklet
|
||||
struct tasklet_struct xmit_tasklet;
|
||||
#endif
|
||||
u16 chipid;
|
||||
bool tbusy;
|
||||
};
|
||||
|
||||
extern void aicwf_usb_exit(void);
|
||||
extern void aicwf_usb_register(void);
|
||||
extern void aicwf_usb_tx_flowctrl(struct rwnx_hw *rwnx_hw, bool state);
|
||||
#ifdef CONFIG_USB_MSG_IN_EP
|
||||
int usb_msg_busrx_thread(void *data);
|
||||
#endif
|
||||
int usb_bustx_thread(void *data);
|
||||
int usb_busrx_thread(void *data);
|
||||
|
||||
|
||||
extern void aicwf_hostif_ready(void);
|
||||
|
||||
#endif /* AICWF_USB_SUPPORT */
|
||||
#endif /* _AICWF_USB_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
|
||||
struct scanu_result_wext{
|
||||
struct list_head scanu_re_list;
|
||||
struct cfg80211_bss *bss;
|
||||
struct scanu_result_ind *ind;
|
||||
u32_l *payload;
|
||||
};
|
||||
|
||||
void aicwf_set_wireless_ext( struct net_device *ndev, struct rwnx_hw *rwnx_hw);
|
||||
void aicwf_scan_complete_event(struct net_device *dev);
|
||||
|
||||
@@ -0,0 +1,376 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file hal_desc.h
|
||||
*
|
||||
* @brief File containing the definition of HW descriptors.
|
||||
*
|
||||
* Contains the definition and structures used by HW
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2011-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _HAL_DESC_H_
|
||||
#define _HAL_DESC_H_
|
||||
|
||||
#include "lmac_types.h"
|
||||
|
||||
/* Rate and policy table */
|
||||
|
||||
#define N_CCK 8
|
||||
#define N_OFDM 8
|
||||
#define N_HT (8 * 2 * 2 * 4)
|
||||
#define N_VHT (10 * 4 * 2 * 8)
|
||||
#define N_HE_SU (12 * 4 * 3 * 8)
|
||||
#define N_HE_MU (12 * 6 * 3 * 8)
|
||||
|
||||
/* conversion table from NL80211 to MACHW enum */
|
||||
extern const int chnl2bw[];
|
||||
|
||||
/* conversion table from MACHW to NL80211 enum */
|
||||
extern const int bw2chnl[];
|
||||
|
||||
/* Rate cntrl info */
|
||||
#define MCS_INDEX_TX_RCX_OFT 0
|
||||
#define MCS_INDEX_TX_RCX_MASK (0x7F << MCS_INDEX_TX_RCX_OFT)
|
||||
#define BW_TX_RCX_OFT 7
|
||||
#define BW_TX_RCX_MASK (0x3 << BW_TX_RCX_OFT)
|
||||
#define SHORT_GI_TX_RCX_OFT 9
|
||||
#define SHORT_GI_TX_RCX_MASK (0x1 << SHORT_GI_TX_RCX_OFT)
|
||||
#define PRE_TYPE_TX_RCX_OFT 10
|
||||
#define PRE_TYPE_TX_RCX_MASK (0x1 << PRE_TYPE_TX_RCX_OFT)
|
||||
#define FORMAT_MOD_TX_RCX_OFT 11
|
||||
#define FORMAT_MOD_TX_RCX_MASK (0x7 << FORMAT_MOD_TX_RCX_OFT)
|
||||
|
||||
/* Values for formatModTx */
|
||||
#define FORMATMOD_NON_HT 0
|
||||
#define FORMATMOD_NON_HT_DUP_OFDM 1
|
||||
#define FORMATMOD_HT_MF 2
|
||||
#define FORMATMOD_HT_GF 3
|
||||
#define FORMATMOD_VHT 4
|
||||
#define FORMATMOD_HE_SU 5
|
||||
#define FORMATMOD_HE_MU 6
|
||||
#define FORMATMOD_HE_ER 7
|
||||
|
||||
/* Values for navProtFrmEx */
|
||||
#define NAV_PROT_NO_PROT_BIT 0
|
||||
#define NAV_PROT_SELF_CTS_BIT 1
|
||||
#define NAV_PROT_RTS_CTS_BIT 2
|
||||
#define NAV_PROT_RTS_CTS_WITH_QAP_BIT 3
|
||||
#define NAV_PROT_STBC_BIT 4
|
||||
|
||||
/* THD MACCTRLINFO2 fields, used in struct umacdesc umac.flags */
|
||||
/// WhichDescriptor definition - contains aMPDU bit and position value
|
||||
/// Offset of WhichDescriptor field in the MAC CONTROL INFO 2 word
|
||||
#define WHICHDESC_OFT 19
|
||||
/// Mask of the WhichDescriptor field
|
||||
#define WHICHDESC_MSK (0x07 << WHICHDESC_OFT)
|
||||
/// Only 1 THD possible, describing an unfragmented MSDU
|
||||
#define WHICHDESC_UNFRAGMENTED_MSDU (0x00 << WHICHDESC_OFT)
|
||||
/// THD describing the first MPDU of a fragmented MSDU
|
||||
#define WHICHDESC_FRAGMENTED_MSDU_FIRST (0x01 << WHICHDESC_OFT)
|
||||
/// THD describing intermediate MPDUs of a fragmented MSDU
|
||||
#define WHICHDESC_FRAGMENTED_MSDU_INT (0x02 << WHICHDESC_OFT)
|
||||
/// THD describing the last MPDU of a fragmented MSDU
|
||||
#define WHICHDESC_FRAGMENTED_MSDU_LAST (0x03 << WHICHDESC_OFT)
|
||||
/// THD for extra descriptor starting an AMPDU
|
||||
#define WHICHDESC_AMPDU_EXTRA (0x04 << WHICHDESC_OFT)
|
||||
/// THD describing the first MPDU of an A-MPDU
|
||||
#define WHICHDESC_AMPDU_FIRST (0x05 << WHICHDESC_OFT)
|
||||
/// THD describing intermediate MPDUs of an A-MPDU
|
||||
#define WHICHDESC_AMPDU_INT (0x06 << WHICHDESC_OFT)
|
||||
/// THD describing the last MPDU of an A-MPDU
|
||||
#define WHICHDESC_AMPDU_LAST (0x07 << WHICHDESC_OFT)
|
||||
|
||||
/// aMPDU bit offset
|
||||
#define AMPDU_OFT 21
|
||||
/// aMPDU bit
|
||||
#define AMPDU_BIT CO_BIT(AMPDU_OFT)
|
||||
|
||||
enum {
|
||||
HW_RATE_1MBPS = 0,
|
||||
HW_RATE_2MBPS = 1,
|
||||
HW_RATE_5_5MBPS = 2,
|
||||
HW_RATE_11MBPS = 3,
|
||||
HW_RATE_6MBPS = 4,
|
||||
HW_RATE_9MBPS = 5,
|
||||
HW_RATE_12MBPS = 6,
|
||||
HW_RATE_18MBPS = 7,
|
||||
HW_RATE_24MBPS = 8,
|
||||
HW_RATE_36MBPS = 9,
|
||||
HW_RATE_48MBPS = 10,
|
||||
HW_RATE_54MBPS = 11,
|
||||
HW_RATE_MAX
|
||||
};
|
||||
|
||||
union rwnx_mcs_index {
|
||||
struct {
|
||||
u32 mcs : 3;
|
||||
u32 nss : 2;
|
||||
} ht;
|
||||
struct {
|
||||
u32 mcs : 4;
|
||||
u32 nss : 3;
|
||||
} vht;
|
||||
struct {
|
||||
u32 mcs : 4;
|
||||
u32 nss : 3;
|
||||
} he;
|
||||
u32 legacy : 7;
|
||||
};
|
||||
|
||||
/* c.f RW-WLAN-nX-MAC-HW-UM */
|
||||
union rwnx_rate_ctrl_info {
|
||||
struct {
|
||||
u32 mcsIndexTx : 7;
|
||||
u32 bwTx : 2;
|
||||
u32 giAndPreTypeTx : 2;
|
||||
u32 formatModTx : 3;
|
||||
u32 navProtFrmEx : 3;
|
||||
u32 mcsIndexProtTx : 7;
|
||||
u32 bwProtTx : 2;
|
||||
u32 formatModProtTx : 3;
|
||||
u32 nRetry : 3;
|
||||
};
|
||||
u32 value;
|
||||
};
|
||||
|
||||
/* c.f RW-WLAN-nX-MAC-HW-UM */
|
||||
struct rwnx_power_ctrl_info {
|
||||
u32 txPwrLevelPT : 8;
|
||||
u32 txPwrLevelProtPT : 8;
|
||||
u32 reserved :16;
|
||||
};
|
||||
|
||||
/* c.f RW-WLAN-nX-MAC-HW-UM */
|
||||
union rwnx_pol_phy_ctrl_info_1 {
|
||||
struct {
|
||||
u32 rsvd1 : 3;
|
||||
u32 bfFrmEx : 1;
|
||||
u32 numExtnSS : 2;
|
||||
u32 fecCoding : 1;
|
||||
u32 stbc : 2;
|
||||
u32 rsvd2 : 5;
|
||||
u32 nTx : 3;
|
||||
u32 nTxProt : 3;
|
||||
};
|
||||
u32 value;
|
||||
};
|
||||
|
||||
/* c.f RW-WLAN-nX-MAC-HW-UM */
|
||||
union rwnx_pol_phy_ctrl_info_2 {
|
||||
struct {
|
||||
u32 antennaSet : 8;
|
||||
u32 smmIndex : 8;
|
||||
u32 beamFormed : 1;
|
||||
};
|
||||
u32 value;
|
||||
};
|
||||
|
||||
/* c.f RW-WLAN-nX-MAC-HW-UM */
|
||||
union rwnx_pol_mac_ctrl_info_1 {
|
||||
struct {
|
||||
u32 keySRamIndex : 10;
|
||||
u32 keySRamIndexRA : 10;
|
||||
};
|
||||
u32 value;
|
||||
};
|
||||
|
||||
/* c.f RW-WLAN-nX-MAC-HW-UM */
|
||||
union rwnx_pol_mac_ctrl_info_2 {
|
||||
struct {
|
||||
u32 longRetryLimit : 8;
|
||||
u32 shortRetryLimit : 8;
|
||||
u32 rtsThreshold : 12;
|
||||
};
|
||||
u32 value;
|
||||
};
|
||||
|
||||
#define POLICY_TABLE_PATTERN 0xBADCAB1E
|
||||
|
||||
struct tx_policy_tbl {
|
||||
/* Unique Pattern at the start of Policy Table */
|
||||
u32 upatterntx;
|
||||
/* PHY Control 1 Information used by MAC HW */
|
||||
union rwnx_pol_phy_ctrl_info_1 phyctrlinfo_1;
|
||||
/* PHY Control 2 Information used by MAC HW */
|
||||
union rwnx_pol_phy_ctrl_info_2 phyctrlinfo_2;
|
||||
/* MAC Control 1 Information used by MAC HW */
|
||||
union rwnx_pol_mac_ctrl_info_1 macctrlinfo_1;
|
||||
/* MAC Control 2 Information used by MAC HW */
|
||||
union rwnx_pol_mac_ctrl_info_2 macctrlinfo_2;
|
||||
|
||||
union rwnx_rate_ctrl_info ratectrlinfos[NX_TX_MAX_RATES];
|
||||
struct rwnx_power_ctrl_info powerctrlinfos[NX_TX_MAX_RATES];
|
||||
};
|
||||
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
|
||||
/**
|
||||
* struct rwnx_hw_txstatus - Bitfield of confirmation status
|
||||
*
|
||||
* @tx_done: packet has been processed by the firmware.
|
||||
* @retry_required: packet has been transmitted but not acknoledged.
|
||||
* Driver must repush it.
|
||||
* @sw_retry_required: packet has not been transmitted (FW wasn't able to push
|
||||
* it when it received it: not active channel ...). Driver must repush it.
|
||||
* @acknowledged: packet has been acknowledged by peer
|
||||
*/
|
||||
union rwnx_hw_txstatus {
|
||||
struct {
|
||||
u32 tx_done : 1;
|
||||
u32 retry_required : 1;
|
||||
u32 sw_retry_required : 1;
|
||||
u32 acknowledged : 1;
|
||||
u32 reserved :28;
|
||||
};
|
||||
u32 value;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct tx_cfm_tag - Structure indicating the status and other
|
||||
* information about the transmission
|
||||
*
|
||||
* @pn: PN that was used for the transmission
|
||||
* @sn: Sequence number of the packet
|
||||
* @timestamp: Timestamp of first transmission of this MPDU
|
||||
* @credits: Number of credits to be reallocated for the txq that push this
|
||||
* buffer (can be 0 or 1)
|
||||
* @ampdu_size: Size of the ampdu in which the frame has been transmitted if
|
||||
* this was the last frame of the a-mpdu, and 0 if the frame is not the last
|
||||
* frame on a a-mdpu.
|
||||
* 1 means that the frame has been transmitted as a singleton.
|
||||
* @amsdu_size: Size, in bytes, allowed to create a-msdu.
|
||||
* @status: transmission status
|
||||
*/
|
||||
struct tx_cfm_tag
|
||||
{
|
||||
u16_l pn[4];
|
||||
u16_l sn;
|
||||
u16_l timestamp;
|
||||
s8_l credits;
|
||||
u8_l ampdu_size;
|
||||
#ifdef CONFIG_RWNX_SPLIT_TX_BUF
|
||||
u16_l amsdu_size;
|
||||
#endif
|
||||
union rwnx_hw_txstatus status;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rwnx_hw_txhdr - Hardware part of tx header
|
||||
*
|
||||
* @cfm: Information updated by fw/hardware after sending a frame
|
||||
*/
|
||||
struct rwnx_hw_txhdr {
|
||||
struct tx_cfm_tag cfm;
|
||||
};
|
||||
|
||||
#endif /* CONFIG_RWNX_FULLMAC */
|
||||
|
||||
/* Modem */
|
||||
|
||||
#define MDM_PHY_CONFIG_TRIDENT 0
|
||||
#define MDM_PHY_CONFIG_ELMA 1
|
||||
#define MDM_PHY_CONFIG_KARST 2
|
||||
|
||||
// MODEM features (from reg_mdm_stat.h)
|
||||
/// MUMIMOTX field bit
|
||||
#define MDM_MUMIMOTX_BIT ((u32)0x80000000)
|
||||
/// MUMIMOTX field position
|
||||
#define MDM_MUMIMOTX_POS 31
|
||||
/// MUMIMORX field bit
|
||||
#define MDM_MUMIMORX_BIT ((u32)0x40000000)
|
||||
/// MUMIMORX field position
|
||||
#define MDM_MUMIMORX_POS 30
|
||||
/// BFMER field bit
|
||||
#define MDM_BFMER_BIT ((u32)0x20000000)
|
||||
/// BFMER field position
|
||||
#define MDM_BFMER_POS 29
|
||||
/// BFMEE field bit
|
||||
#define MDM_BFMEE_BIT ((u32)0x10000000)
|
||||
/// BFMEE field position
|
||||
#define MDM_BFMEE_POS 28
|
||||
/// LDPCDEC field bit
|
||||
#define MDM_LDPCDEC_BIT ((u32)0x08000000)
|
||||
/// LDPCDEC field position
|
||||
#define MDM_LDPCDEC_POS 27
|
||||
/// LDPCENC field bit
|
||||
#define MDM_LDPCENC_BIT ((u32)0x04000000)
|
||||
/// LDPCENC field position
|
||||
#define MDM_LDPCENC_POS 26
|
||||
/// CHBW field mask
|
||||
#define MDM_CHBW_MASK ((u32)0x03000000)
|
||||
/// CHBW field LSB position
|
||||
#define MDM_CHBW_LSB 24
|
||||
/// CHBW field width
|
||||
#define MDM_CHBW_WIDTH ((u32)0x00000002)
|
||||
/// DSSSCCK field bit
|
||||
#define MDM_DSSSCCK_BIT ((u32)0x00800000)
|
||||
/// DSSSCCK field position
|
||||
#define MDM_DSSSCCK_POS 23
|
||||
/// VHT field bit
|
||||
#define MDM_VHT_BIT ((u32)0x00400000)
|
||||
/// VHT field position
|
||||
#define MDM_VHT_POS 22
|
||||
/// HE field bit
|
||||
#define MDM_HE_BIT ((u32)0x00200000)
|
||||
/// HE field position
|
||||
#define MDM_HE_POS 21
|
||||
/// ESS field bit
|
||||
#define MDM_ESS_BIT ((u32)0x00100000)
|
||||
/// ESS field position
|
||||
#define MDM_ESS_POS 20
|
||||
/// RFMODE field mask
|
||||
#define MDM_RFMODE_MASK ((u32)0x000F0000)
|
||||
/// RFMODE field LSB position
|
||||
#define MDM_RFMODE_LSB 16
|
||||
/// RFMODE field width
|
||||
#define MDM_RFMODE_WIDTH ((u32)0x00000004)
|
||||
/// NSTS field mask
|
||||
#define MDM_NSTS_MASK ((u32)0x0000F000)
|
||||
/// NSTS field LSB position
|
||||
#define MDM_NSTS_LSB 12
|
||||
/// NSTS field width
|
||||
#define MDM_NSTS_WIDTH ((u32)0x00000004)
|
||||
/// NSS field mask
|
||||
#define MDM_NSS_MASK ((u32)0x00000F00)
|
||||
/// NSS field LSB position
|
||||
#define MDM_NSS_LSB 8
|
||||
/// NSS field width
|
||||
#define MDM_NSS_WIDTH ((u32)0x00000004)
|
||||
/// NTX field mask
|
||||
#define MDM_NTX_MASK ((u32)0x000000F0)
|
||||
/// NTX field LSB position
|
||||
#define MDM_NTX_LSB 4
|
||||
/// NTX field width
|
||||
#define MDM_NTX_WIDTH ((u32)0x00000004)
|
||||
/// NRX field mask
|
||||
#define MDM_NRX_MASK ((u32)0x0000000F)
|
||||
/// NRX field LSB position
|
||||
#define MDM_NRX_LSB 0
|
||||
/// NRX field width
|
||||
#define MDM_NRX_WIDTH ((u32)0x00000004)
|
||||
|
||||
#define __MDM_PHYCFG_FROM_VERS(v) (((v) & MDM_RFMODE_MASK) >> MDM_RFMODE_LSB)
|
||||
|
||||
#define RIU_FCU_PRESENT_MASK ((u32)0xFF000000)
|
||||
#define RIU_FCU_PRESENT_LSB 24
|
||||
|
||||
#define __RIU_FCU_PRESENT(v) (((v) & RIU_FCU_PRESENT_MASK) >> RIU_FCU_PRESENT_LSB == 5)
|
||||
|
||||
/// AGC load version field mask
|
||||
#define RIU_AGC_LOAD_MASK ((u32)0x00C00000)
|
||||
/// AGC load version field LSB position
|
||||
#define RIU_AGC_LOAD_LSB 22
|
||||
|
||||
#define __RIU_AGCLOAD_FROM_VERS(v) (((v) & RIU_AGC_LOAD_MASK) >> RIU_AGC_LOAD_LSB)
|
||||
|
||||
#define __FPGA_TYPE(v) (((v) & 0xFFFF0000) >> 16)
|
||||
|
||||
#define __MDM_MAJOR_VERSION(v) (((v) & 0xFF000000) >> 24)
|
||||
#define __MDM_MINOR_VERSION(v) (((v) & 0x00FF0000) >> 16)
|
||||
|
||||
|
||||
#endif // _HAL_DESC_H_
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
****************************************************************************************
|
||||
*
|
||||
* @file ipc_compat.h
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2011-2019
|
||||
*
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _IPC_H_
|
||||
#define _IPC_H_
|
||||
|
||||
#define __INLINE static __attribute__((__always_inline__)) inline
|
||||
|
||||
#define __ALIGN4 __aligned(4)
|
||||
|
||||
#define ASSERT_ERR(condition) \
|
||||
do { \
|
||||
if (unlikely(!(condition))) { \
|
||||
printk(KERN_ERR "%s:%d:ASSERT_ERR(" #condition ")\n", __FILE__, __LINE__); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#endif /* _IPC_H_ */
|
||||
@@ -0,0 +1,771 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file ipc_host.c
|
||||
*
|
||||
* @brief IPC module.
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2011-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
* INCLUDE FILES
|
||||
******************************************************************************
|
||||
*/
|
||||
#ifndef __KERNEL__
|
||||
#include <stdio.h>
|
||||
#define REG_SW_SET_PROFILING(env, value) do{ }while(0)
|
||||
#define REG_SW_CLEAR_PROFILING(env, value) do{ }while(0)
|
||||
#define REG_SW_CLEAR_HOSTBUF_IDX_PROFILING(env) do{ }while(0)
|
||||
#define REG_SW_SET_HOSTBUF_IDX_PROFILING(env, val) do{ }while(0)
|
||||
#else
|
||||
#include <linux/spinlock.h>
|
||||
#include "rwnx_defs.h"
|
||||
#include "rwnx_prof.h"
|
||||
#endif
|
||||
|
||||
#include "reg_ipc_app.h"
|
||||
#include "ipc_host.h"
|
||||
|
||||
/*
|
||||
* TYPES DEFINITION
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
const int nx_txdesc_cnt[] =
|
||||
{
|
||||
NX_TXDESC_CNT0,
|
||||
NX_TXDESC_CNT1,
|
||||
NX_TXDESC_CNT2,
|
||||
NX_TXDESC_CNT3,
|
||||
#if NX_TXQ_CNT == 5
|
||||
NX_TXDESC_CNT4,
|
||||
#endif
|
||||
};
|
||||
|
||||
const int nx_txdesc_cnt_msk[] =
|
||||
{
|
||||
NX_TXDESC_CNT0 - 1,
|
||||
NX_TXDESC_CNT1 - 1,
|
||||
NX_TXDESC_CNT2 - 1,
|
||||
NX_TXDESC_CNT3 - 1,
|
||||
#if NX_TXQ_CNT == 5
|
||||
NX_TXDESC_CNT4 - 1,
|
||||
#endif
|
||||
};
|
||||
|
||||
const int nx_txuser_cnt[] =
|
||||
{
|
||||
CONFIG_USER_MAX,
|
||||
CONFIG_USER_MAX,
|
||||
CONFIG_USER_MAX,
|
||||
CONFIG_USER_MAX,
|
||||
#if NX_TXQ_CNT == 5
|
||||
1,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* FUNCTIONS DEFINITIONS
|
||||
******************************************************************************
|
||||
*/
|
||||
/**
|
||||
* ipc_host_rxdesc_handler() - Handle the reception of a Rx Descriptor
|
||||
*
|
||||
* @env: pointer to the IPC Host environment
|
||||
*
|
||||
* Called from general IRQ handler when status %IPC_IRQ_E2A_RXDESC is set
|
||||
*/
|
||||
static void ipc_host_rxdesc_handler(struct ipc_host_env_tag *env)
|
||||
{
|
||||
// For profiling
|
||||
REG_SW_SET_PROFILING(env->pthis, SW_PROF_IRQ_E2A_RXDESC);
|
||||
|
||||
// LMAC has triggered an IT saying that a reception has occurred.
|
||||
// Then we first need to check the validity of the current hostbuf, and the validity
|
||||
// of the next hostbufs too, because it is likely that several hostbufs have been
|
||||
// filled within the time needed for this irq handling
|
||||
do {
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
// call the external function to indicate that a RX descriptor is received
|
||||
if (env->cb.recv_data_ind(env->pthis,
|
||||
env->ipc_host_rxdesc_array[env->ipc_host_rxdesc_idx].hostid) != 0)
|
||||
#else
|
||||
// call the external function to indicate that a RX packet is received
|
||||
if (env->cb.recv_data_ind(env->pthis,
|
||||
env->ipc_host_rxbuf_array[env->ipc_host_rxbuf_idx].hostid) != 0)
|
||||
#endif //(CONFIG_RWNX_FULLMAC)
|
||||
break;
|
||||
|
||||
}while(1);
|
||||
|
||||
// For profiling
|
||||
REG_SW_CLEAR_PROFILING(env->pthis, SW_PROF_IRQ_E2A_RXDESC);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipc_host_radar_handler() - Handle the reception of radar events
|
||||
*
|
||||
* @env: pointer to the IPC Host environment
|
||||
*
|
||||
* Called from general IRQ handler when status %IPC_IRQ_E2A_RADAR is set
|
||||
*/
|
||||
static void ipc_host_radar_handler(struct ipc_host_env_tag *env)
|
||||
{
|
||||
#ifdef CONFIG_RWNX_RADAR
|
||||
// LMAC has triggered an IT saying that a radar event has been sent to upper layer.
|
||||
// Then we first need to check the validity of the current msg buf, and the validity
|
||||
// of the next buffers too, because it is likely that several buffers have been
|
||||
// filled within the time needed for this irq handling
|
||||
// call the external function to indicate that a RX packet is received
|
||||
spin_lock_bh(&((struct rwnx_hw *)env->pthis)->radar.lock);
|
||||
while (env->cb.recv_radar_ind(env->pthis,
|
||||
env->ipc_host_radarbuf_array[env->ipc_host_radarbuf_idx].hostid) == 0)
|
||||
;
|
||||
spin_unlock_bh(&((struct rwnx_hw *)env->pthis)->radar.lock);
|
||||
#endif /* CONFIG_RWNX_RADAR */
|
||||
}
|
||||
|
||||
/**
|
||||
* ipc_host_unsup_rx_vec_handler() - Handle the reception of unsupported rx vector
|
||||
*
|
||||
* @env: pointer to the IPC Host environment
|
||||
*
|
||||
* Called from general IRQ handler when status %IPC_IRQ_E2A_UNSUP_RX_VEC is set
|
||||
*/
|
||||
static void ipc_host_unsup_rx_vec_handler(struct ipc_host_env_tag *env)
|
||||
{
|
||||
while (env->cb.recv_unsup_rx_vec_ind(env->pthis,
|
||||
env->ipc_host_unsuprxvecbuf_array[env->ipc_host_unsuprxvecbuf_idx].hostid) == 0)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipc_host_msg_handler() - Handler for firmware message
|
||||
*
|
||||
* @env: pointer to the IPC Host environment
|
||||
*
|
||||
* Called from general IRQ handler when status %IPC_IRQ_E2A_MSG is set
|
||||
*/
|
||||
static void ipc_host_msg_handler(struct ipc_host_env_tag *env)
|
||||
{
|
||||
// For profiling
|
||||
REG_SW_SET_PROFILING(env->pthis, SW_PROF_IRQ_E2A_MSG);
|
||||
|
||||
// LMAC has triggered an IT saying that a message has been sent to upper layer.
|
||||
// Then we first need to check the validity of the current msg buf, and the validity
|
||||
// of the next buffers too, because it is likely that several buffers have been
|
||||
// filled within the time needed for this irq handling
|
||||
// call the external function to indicate that a RX packet is received
|
||||
while (env->cb.recv_msg_ind(env->pthis,
|
||||
env->ipc_host_msgbuf_array[env->ipc_host_msge2a_idx].hostid) == 0)
|
||||
;
|
||||
|
||||
|
||||
// For profiling
|
||||
REG_SW_CLEAR_PROFILING(env->pthis, SW_PROF_IRQ_E2A_MSG);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* ipc_host_msgack_handler() - Handle the reception of message acknowledgement
|
||||
*
|
||||
* @env: pointer to the IPC Host environment
|
||||
*
|
||||
* Called from general IRQ handler when status %IPC_IRQ_E2A_MSG_ACK is set
|
||||
*/
|
||||
static void ipc_host_msgack_handler(struct ipc_host_env_tag *env)
|
||||
{
|
||||
void *hostid = env->msga2e_hostid;
|
||||
|
||||
ASSERT_ERR(hostid);
|
||||
ASSERT_ERR(env->msga2e_cnt == (((struct lmac_msg *)(&env->shared->msg_a2e_buf.msg))->src_id & 0xFF));
|
||||
|
||||
env->msga2e_hostid = NULL;
|
||||
env->msga2e_cnt++;
|
||||
env->cb.recv_msgack_ind(env->pthis, hostid);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipc_host_dbg_handler() - Handle the reception of Debug event
|
||||
*
|
||||
* @env: pointer to the IPC Host environment
|
||||
*
|
||||
* Called from general IRQ handler when status %IPC_IRQ_E2A_DBG is set
|
||||
*/
|
||||
static void ipc_host_dbg_handler(struct ipc_host_env_tag *env)
|
||||
{
|
||||
// For profiling
|
||||
REG_SW_SET_PROFILING(env->pthis, SW_PROF_IRQ_E2A_DBG);
|
||||
|
||||
// LMAC has triggered an IT saying that a DBG message has been sent to upper layer.
|
||||
// Then we first need to check the validity of the current buffer, and the validity
|
||||
// of the next buffers too, because it is likely that several buffers have been
|
||||
// filled within the time needed for this irq handling
|
||||
// call the external function to indicate that a RX packet is received
|
||||
while(env->cb.recv_dbg_ind(env->pthis,
|
||||
env->ipc_host_dbgbuf_array[env->ipc_host_dbg_idx].hostid) == 0)
|
||||
;
|
||||
|
||||
// For profiling
|
||||
REG_SW_CLEAR_PROFILING(env->pthis, SW_PROF_IRQ_E2A_DBG);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipc_host_tx_cfm_handler() - Handle the reception of TX confirmation
|
||||
*
|
||||
* @env: pointer to the IPC Host environment
|
||||
* @queue_idx: index of the hardware on which the confirmation has been received
|
||||
* @user_pos: index of the user position
|
||||
*
|
||||
* Called from general IRQ handler when status %IPC_IRQ_E2A_TXCFM is set
|
||||
*/
|
||||
static void ipc_host_tx_cfm_handler(struct ipc_host_env_tag *env,
|
||||
const int queue_idx, const int user_pos)
|
||||
{
|
||||
// TX confirmation descriptors have been received
|
||||
REG_SW_SET_PROFILING(env->pthis, SW_PROF_IRQ_E2A_TXCFM);
|
||||
while (1)
|
||||
{
|
||||
// Get the used index and increase it. We do the increase before knowing if the
|
||||
// current buffer is confirmed because the callback function may call the
|
||||
// ipc_host_txdesc_get() in case flow control was enabled and the index has to be
|
||||
// already at the good value to ensure that the test of FIFO full is correct
|
||||
uint32_t used_idx = env->txdesc_used_idx[queue_idx][user_pos]++;
|
||||
uint32_t used_idx_mod = used_idx & nx_txdesc_cnt_msk[queue_idx];
|
||||
void *host_id = env->tx_host_id[queue_idx][user_pos][used_idx_mod];
|
||||
|
||||
// Reset the host id in the array
|
||||
env->tx_host_id[queue_idx][user_pos][used_idx_mod] = 0;
|
||||
|
||||
// call the external function to indicate that a TX packet is freed
|
||||
if (host_id == 0)
|
||||
{
|
||||
// No more confirmations, so put back the used index at its initial value
|
||||
env->txdesc_used_idx[queue_idx][user_pos] = used_idx;
|
||||
break;
|
||||
}
|
||||
|
||||
if (env->cb.send_data_cfm(env->pthis, host_id) != 0)
|
||||
{
|
||||
// No more confirmations, so put back the used index at its initial value
|
||||
env->txdesc_used_idx[queue_idx][user_pos] = used_idx;
|
||||
env->tx_host_id[queue_idx][user_pos][used_idx_mod] = host_id;
|
||||
// and exit the loop
|
||||
break;
|
||||
}
|
||||
|
||||
REG_SW_SET_PROFILING_CHAN(env->pthis, SW_PROF_CHAN_CTXT_CFM_HDL_BIT);
|
||||
REG_SW_CLEAR_PROFILING_CHAN(env->pthis, SW_PROF_CHAN_CTXT_CFM_HDL_BIT);
|
||||
}
|
||||
|
||||
REG_SW_CLEAR_PROFILING(env->pthis, SW_PROF_IRQ_E2A_TXCFM);
|
||||
}
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
*/
|
||||
bool ipc_host_tx_frames_pending(struct ipc_host_env_tag *env)
|
||||
{
|
||||
int i, j;
|
||||
bool tx_frames_pending = false;
|
||||
|
||||
for (i = 0; (i < IPC_TXQUEUE_CNT) && !tx_frames_pending; i++)
|
||||
{
|
||||
for (j = 0; j < nx_txuser_cnt[i]; j++)
|
||||
{
|
||||
uint32_t used_idx = env->txdesc_used_idx[i][j];
|
||||
uint32_t free_idx = env->txdesc_free_idx[i][j];
|
||||
|
||||
// Check if this queue is empty or not
|
||||
if (used_idx != free_idx)
|
||||
{
|
||||
// The queue is not empty, update the flag and exit
|
||||
tx_frames_pending = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (tx_frames_pending);
|
||||
}
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
*/
|
||||
void *ipc_host_tx_flush(struct ipc_host_env_tag *env, const int queue_idx, const int user_pos)
|
||||
{
|
||||
uint32_t used_idx = env->txdesc_used_idx[queue_idx][user_pos];
|
||||
void *host_id = env->tx_host_id[queue_idx][user_pos][used_idx & nx_txdesc_cnt_msk[queue_idx]];
|
||||
|
||||
// call the external function to indicate that a TX packet is freed
|
||||
if (host_id != 0)
|
||||
{
|
||||
// Reset the host id in the array
|
||||
env->tx_host_id[queue_idx][user_pos][used_idx & nx_txdesc_cnt_msk[queue_idx]] = 0;
|
||||
|
||||
// Increment the used index
|
||||
env->txdesc_used_idx[queue_idx][user_pos]++;
|
||||
}
|
||||
|
||||
return (host_id);
|
||||
}
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
*/
|
||||
void ipc_host_init(struct ipc_host_env_tag *env,
|
||||
struct ipc_host_cb_tag *cb,
|
||||
struct ipc_shared_env_tag *shared_env_ptr,
|
||||
void *pthis)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int size;
|
||||
unsigned int * dst;
|
||||
|
||||
// Reset the environments
|
||||
// Reset the IPC Shared memory
|
||||
#if 0
|
||||
/* check potential platform bug on multiple stores */
|
||||
memset(shared_env_ptr, 0, sizeof(struct ipc_shared_env_tag));
|
||||
#else
|
||||
dst = (unsigned int *)shared_env_ptr;
|
||||
size = (unsigned int)sizeof(struct ipc_shared_env_tag);
|
||||
for (i=0; i < size; i+=4)
|
||||
{
|
||||
*dst++ = 0;
|
||||
}
|
||||
#endif
|
||||
// Reset the IPC Host environment
|
||||
memset(env, 0, sizeof(struct ipc_host_env_tag));
|
||||
|
||||
// Initialize the shared environment pointer
|
||||
env->shared = shared_env_ptr;
|
||||
|
||||
// Save the callbacks in our own environment
|
||||
env->cb = *cb;
|
||||
|
||||
// Save the pointer to the register base
|
||||
env->pthis = pthis;
|
||||
|
||||
// Initialize buffers numbers and buffers sizes needed for DMA Receptions
|
||||
env->rx_bufnb = IPC_RXBUF_CNT;
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
env->rxdesc_nb = IPC_RXDESC_CNT;
|
||||
#endif //(CONFIG_RWNX_FULLMAC)
|
||||
env->radar_bufnb = IPC_RADARBUF_CNT;
|
||||
env->radar_bufsz = sizeof(struct radar_pulse_array_desc);
|
||||
env->unsuprxvec_bufnb = IPC_UNSUPRXVECBUF_CNT;
|
||||
env->unsuprxvec_bufsz = max(sizeof(struct rx_vector_desc), (size_t) RADIOTAP_HDR_MAX_LEN) +
|
||||
RADIOTAP_HDR_VEND_MAX_LEN + UNSUP_RX_VEC_DATA_LEN;
|
||||
env->ipc_e2amsg_bufnb = IPC_MSGE2A_BUF_CNT;
|
||||
env->ipc_e2amsg_bufsz = sizeof(struct ipc_e2a_msg);
|
||||
env->ipc_dbg_bufnb = IPC_DBGBUF_CNT;
|
||||
env->ipc_dbg_bufsz = sizeof(struct ipc_dbg_msg);
|
||||
|
||||
for (i = 0; i < CONFIG_USER_MAX; i++)
|
||||
{
|
||||
// Initialize the pointers to the hostid arrays
|
||||
env->tx_host_id[0][i] = env->tx_host_id0[i];
|
||||
env->tx_host_id[1][i] = env->tx_host_id1[i];
|
||||
env->tx_host_id[2][i] = env->tx_host_id2[i];
|
||||
env->tx_host_id[3][i] = env->tx_host_id3[i];
|
||||
#if NX_TXQ_CNT == 5
|
||||
env->tx_host_id[4][i] = NULL;
|
||||
#endif
|
||||
|
||||
// Initialize the pointers to the TX descriptor arrays
|
||||
env->txdesc[0][i] = shared_env_ptr->txdesc0[i];
|
||||
env->txdesc[1][i] = shared_env_ptr->txdesc1[i];
|
||||
env->txdesc[2][i] = shared_env_ptr->txdesc2[i];
|
||||
env->txdesc[3][i] = shared_env_ptr->txdesc3[i];
|
||||
#if NX_TXQ_CNT == 5
|
||||
env->txdesc[4][i] = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NX_TXQ_CNT == 5
|
||||
env->tx_host_id[4][0] = env->tx_host_id4[0];
|
||||
env->txdesc[4][0] = shared_env_ptr->txdesc4[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
*/
|
||||
void ipc_host_patt_addr_push(struct ipc_host_env_tag *env, uint32_t addr)
|
||||
{
|
||||
struct ipc_shared_env_tag *shared_env_ptr = env->shared;
|
||||
|
||||
// Copy the address
|
||||
shared_env_ptr->pattern_addr = addr;
|
||||
}
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
*/
|
||||
int ipc_host_rxbuf_push(struct ipc_host_env_tag *env,
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
uint32_t hostid,
|
||||
#endif
|
||||
uint32_t hostbuf)
|
||||
{
|
||||
struct ipc_shared_env_tag *shared_env_ptr = env->shared;
|
||||
|
||||
REG_SW_CLEAR_HOSTBUF_IDX_PROFILING(env->pthis);
|
||||
REG_SW_SET_HOSTBUF_IDX_PROFILING(env->pthis, env->ipc_host_rxbuf_idx);
|
||||
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
// Copy the hostbuf (DMA address) in the ipc shared memory
|
||||
shared_env_ptr->host_rxbuf[env->ipc_host_rxbuf_idx].hostid = hostid;
|
||||
shared_env_ptr->host_rxbuf[env->ipc_host_rxbuf_idx].dma_addr = hostbuf;
|
||||
#else
|
||||
// Save the hostid and the hostbuf in global array
|
||||
env->ipc_host_rxbuf_array[env->ipc_host_rxbuf_idx].hostid = hostid;
|
||||
env->ipc_host_rxbuf_array[env->ipc_host_rxbuf_idx].dma_addr = hostbuf;
|
||||
|
||||
shared_env_ptr->host_rxbuf[env->ipc_host_rxbuf_idx] = hostbuf;
|
||||
#endif //(CONFIG_RWNX_FULLMAC)
|
||||
|
||||
// Signal to the embedded CPU that at least one buffer is available
|
||||
ipc_app2emb_trigger_set(shared_env_ptr, IPC_IRQ_A2E_RXBUF_BACK);
|
||||
|
||||
// Increment the array index
|
||||
env->ipc_host_rxbuf_idx = (env->ipc_host_rxbuf_idx +1)%IPC_RXBUF_CNT;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
/**
|
||||
******************************************************************************
|
||||
*/
|
||||
int ipc_host_rxdesc_push(struct ipc_host_env_tag *env, void *hostid,
|
||||
uint32_t hostbuf)
|
||||
{
|
||||
struct ipc_shared_env_tag *shared_env_ptr = env->shared;
|
||||
|
||||
// Reset the RX Descriptor DMA Address and increment the counter
|
||||
env->ipc_host_rxdesc_array[env->ipc_host_rxdesc_idx].dma_addr = hostbuf;
|
||||
env->ipc_host_rxdesc_array[env->ipc_host_rxdesc_idx].hostid = hostid;
|
||||
|
||||
shared_env_ptr->host_rxdesc[env->ipc_host_rxdesc_idx].dma_addr = hostbuf;
|
||||
|
||||
// Signal to the embedded CPU that at least one descriptor is available
|
||||
ipc_app2emb_trigger_set(shared_env_ptr, IPC_IRQ_A2E_RXDESC_BACK);
|
||||
|
||||
env->ipc_host_rxdesc_idx = (env->ipc_host_rxdesc_idx + 1) % IPC_RXDESC_CNT;
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif /* CONFIG_RWNX_FULLMAC */
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
*/
|
||||
int ipc_host_radarbuf_push(struct ipc_host_env_tag *env, void *hostid,
|
||||
uint32_t hostbuf)
|
||||
{
|
||||
struct ipc_shared_env_tag *shared_env_ptr = env->shared;
|
||||
|
||||
// Save the hostid and the hostbuf in global array
|
||||
env->ipc_host_radarbuf_array[env->ipc_host_radarbuf_idx].hostid = hostid;
|
||||
env->ipc_host_radarbuf_array[env->ipc_host_radarbuf_idx].dma_addr = hostbuf;
|
||||
|
||||
// Copy the hostbuf (DMA address) in the ipc shared memory
|
||||
shared_env_ptr->radarbuf_hostbuf[env->ipc_host_radarbuf_idx] = hostbuf;
|
||||
|
||||
// Increment the array index
|
||||
env->ipc_host_radarbuf_idx = (env->ipc_host_radarbuf_idx +1)%IPC_RADARBUF_CNT;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
int ipc_host_unsup_rx_vec_buf_push(struct ipc_host_env_tag *env,
|
||||
void *hostid,
|
||||
uint32_t hostbuf)
|
||||
{
|
||||
struct ipc_shared_env_tag *shared_env_ptr = env->shared;
|
||||
|
||||
env->ipc_host_unsuprxvecbuf_array[env->ipc_host_unsuprxvecbuf_idx].hostid = hostid;
|
||||
env->ipc_host_unsuprxvecbuf_array[env->ipc_host_unsuprxvecbuf_idx].dma_addr = hostbuf;
|
||||
|
||||
// Copy the hostbuf (DMA address) in the ipc shared memory
|
||||
shared_env_ptr->unsuprxvecbuf_hostbuf[env->ipc_host_unsuprxvecbuf_idx] = hostbuf;
|
||||
|
||||
// Increment the array index
|
||||
env->ipc_host_unsuprxvecbuf_idx = (env->ipc_host_unsuprxvecbuf_idx + 1)%IPC_UNSUPRXVECBUF_CNT;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
*/
|
||||
int ipc_host_msgbuf_push(struct ipc_host_env_tag *env, void *hostid,
|
||||
uint32_t hostbuf)
|
||||
{
|
||||
struct ipc_shared_env_tag *shared_env_ptr = env->shared;
|
||||
|
||||
// Save the hostid and the hostbuf in global array
|
||||
env->ipc_host_msgbuf_array[env->ipc_host_msge2a_idx].hostid = hostid;
|
||||
env->ipc_host_msgbuf_array[env->ipc_host_msge2a_idx].dma_addr = hostbuf;
|
||||
|
||||
// Copy the hostbuf (DMA address) in the ipc shared memory
|
||||
shared_env_ptr->msg_e2a_hostbuf_addr[env->ipc_host_msge2a_idx] = hostbuf;
|
||||
|
||||
// Increment the array index
|
||||
env->ipc_host_msge2a_idx = (env->ipc_host_msge2a_idx +1)%IPC_MSGE2A_BUF_CNT;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
*/
|
||||
int ipc_host_dbgbuf_push(struct ipc_host_env_tag *env, void *hostid,
|
||||
uint32_t hostbuf)
|
||||
{
|
||||
struct ipc_shared_env_tag *shared_env_ptr = env->shared;
|
||||
|
||||
// Save the hostid and the hostbuf in global array
|
||||
env->ipc_host_dbgbuf_array[env->ipc_host_dbg_idx].hostid = hostid;
|
||||
env->ipc_host_dbgbuf_array[env->ipc_host_dbg_idx].dma_addr = hostbuf;
|
||||
|
||||
// Copy the hostbuf (DMA address) in the ipc shared memory
|
||||
shared_env_ptr->dbg_hostbuf_addr[env->ipc_host_dbg_idx] = hostbuf;
|
||||
|
||||
// Increment the array index
|
||||
env->ipc_host_dbg_idx = (env->ipc_host_dbg_idx +1)%IPC_DBGBUF_CNT;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
*/
|
||||
void ipc_host_dbginfobuf_push(struct ipc_host_env_tag *env, uint32_t infobuf)
|
||||
{
|
||||
struct ipc_shared_env_tag *shared_env_ptr = env->shared;
|
||||
|
||||
// Copy the hostbuf (DMA address) in the ipc shared memory
|
||||
shared_env_ptr->la_dbginfo_addr = infobuf;
|
||||
}
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
*/
|
||||
volatile struct txdesc_host *ipc_host_txdesc_get(struct ipc_host_env_tag *env, const int queue_idx, const int user_pos)
|
||||
{
|
||||
volatile struct txdesc_host *txdesc_free;
|
||||
uint32_t used_idx = env->txdesc_used_idx[queue_idx][user_pos];
|
||||
uint32_t free_idx = env->txdesc_free_idx[queue_idx][user_pos];
|
||||
|
||||
ASSERT_ERR(queue_idx < IPC_TXQUEUE_CNT);
|
||||
ASSERT_ERR((free_idx - used_idx) <= nx_txdesc_cnt[queue_idx]);
|
||||
|
||||
// Check if a free descriptor is available
|
||||
if (free_idx != (used_idx + nx_txdesc_cnt[queue_idx]))
|
||||
{
|
||||
// Get the pointer to the first free descriptor
|
||||
txdesc_free = env->txdesc[queue_idx][user_pos] + (free_idx & nx_txdesc_cnt_msk[queue_idx]);
|
||||
}
|
||||
else
|
||||
{
|
||||
txdesc_free = NULL;
|
||||
}
|
||||
|
||||
return txdesc_free;
|
||||
}
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
*/
|
||||
void ipc_host_txdesc_push(struct ipc_host_env_tag *env, const int queue_idx,
|
||||
const int user_pos, void *host_id)
|
||||
{
|
||||
uint32_t free_idx = env->txdesc_free_idx[queue_idx][user_pos] & nx_txdesc_cnt_msk[queue_idx];
|
||||
volatile struct txdesc_host *txdesc_pushed = env->txdesc[queue_idx][user_pos] + free_idx;
|
||||
|
||||
|
||||
// Descriptor is now ready
|
||||
txdesc_pushed->ready = 0xFFFFFFFF;
|
||||
|
||||
// Save the host id in the environment
|
||||
env->tx_host_id[queue_idx][user_pos][free_idx] = host_id;
|
||||
|
||||
// Increment the index
|
||||
env->txdesc_free_idx[queue_idx][user_pos]++;
|
||||
|
||||
// trigger interrupt!!!
|
||||
//REG_SW_SET_PROFILING(env->pthis, CO_BIT(queue_idx+SW_PROF_IRQ_A2E_TXDESC_FIRSTBIT));
|
||||
ipc_app2emb_trigger_setf(env->shared, CO_BIT(user_pos + queue_idx * CONFIG_USER_MAX +
|
||||
IPC_IRQ_A2E_TXDESC_FIRSTBIT));
|
||||
}
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
*/
|
||||
void ipc_host_irq(struct ipc_host_env_tag *env, uint32_t status)
|
||||
{
|
||||
// Acknowledge the pending interrupts
|
||||
ipc_emb2app_ack_clear(env->shared, status);
|
||||
// And re-read the status, just to be sure that the acknowledgment is
|
||||
// effective when we start the interrupt handling
|
||||
ipc_emb2app_status_get(env->shared);
|
||||
|
||||
// Optimized for only one IRQ at a time
|
||||
if (status & IPC_IRQ_E2A_RXDESC)
|
||||
{
|
||||
// handle the RX descriptor reception
|
||||
ipc_host_rxdesc_handler(env);
|
||||
}
|
||||
if (status & IPC_IRQ_E2A_MSG_ACK)
|
||||
{
|
||||
ipc_host_msgack_handler(env);
|
||||
}
|
||||
if (status & IPC_IRQ_E2A_MSG)
|
||||
{
|
||||
ipc_host_msg_handler(env);
|
||||
}
|
||||
if (status & IPC_IRQ_E2A_TXCFM)
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifdef __KERNEL__
|
||||
spin_lock_bh(&((struct rwnx_hw *)env->pthis)->tx_lock);
|
||||
#endif
|
||||
// handle the TX confirmation reception
|
||||
for (i = 0; i < IPC_TXQUEUE_CNT; i++)
|
||||
{
|
||||
int j = 0;
|
||||
#ifdef CONFIG_RWNX_MUMIMO_TX
|
||||
for (; j < nx_txuser_cnt[i]; j++)
|
||||
#endif
|
||||
{
|
||||
uint32_t q_bit = CO_BIT(j + i * CONFIG_USER_MAX + IPC_IRQ_E2A_TXCFM_POS);
|
||||
if (status & q_bit)
|
||||
{
|
||||
// handle the confirmation
|
||||
ipc_host_tx_cfm_handler(env, i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef __KERNEL__
|
||||
spin_unlock_bh(&((struct rwnx_hw *)env->pthis)->tx_lock);
|
||||
#endif
|
||||
}
|
||||
if (status & IPC_IRQ_E2A_RADAR)
|
||||
{
|
||||
// handle the radar event reception
|
||||
ipc_host_radar_handler(env);
|
||||
}
|
||||
|
||||
if (status & IPC_IRQ_E2A_UNSUP_RX_VEC)
|
||||
{
|
||||
// handle the unsupported rx vector reception
|
||||
ipc_host_unsup_rx_vec_handler(env);
|
||||
}
|
||||
|
||||
if (status & IPC_IRQ_E2A_DBG)
|
||||
{
|
||||
ipc_host_dbg_handler(env);
|
||||
}
|
||||
|
||||
if (status & IPC_IRQ_E2A_TBTT_PRIM)
|
||||
{
|
||||
env->cb.prim_tbtt_ind(env->pthis);
|
||||
}
|
||||
|
||||
if (status & IPC_IRQ_E2A_TBTT_SEC)
|
||||
{
|
||||
env->cb.sec_tbtt_ind(env->pthis);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
*/
|
||||
int ipc_host_msg_push(struct ipc_host_env_tag *env, void *msg_buf, uint16_t len)
|
||||
{
|
||||
int i;
|
||||
uint32_t *src, *dst;
|
||||
|
||||
REG_SW_SET_PROFILING(env->pthis, SW_PROF_IPC_MSGPUSH);
|
||||
|
||||
ASSERT_ERR(!env->msga2e_hostid);
|
||||
ASSERT_ERR(round_up(len, 4) <= sizeof(env->shared->msg_a2e_buf.msg));
|
||||
|
||||
// Copy the message into the IPC MSG buffer
|
||||
#ifdef __KERNEL__
|
||||
src = (uint32_t*)((struct rwnx_cmd *)msg_buf)->a2e_msg;
|
||||
#else
|
||||
src = (uint32_t*) msg_buf;
|
||||
#endif
|
||||
dst = (uint32_t*)&(env->shared->msg_a2e_buf.msg);
|
||||
|
||||
// Copy the message in the IPC queue
|
||||
for (i=0; i<len; i+=4)
|
||||
{
|
||||
*dst++ = *src++;
|
||||
}
|
||||
|
||||
env->msga2e_hostid = msg_buf;
|
||||
|
||||
// Trigger the irq to send the message to EMB
|
||||
ipc_app2emb_trigger_set(env->shared, IPC_IRQ_A2E_MSG);
|
||||
|
||||
REG_SW_CLEAR_PROFILING(env->pthis, SW_PROF_IPC_MSGPUSH);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
*/
|
||||
void ipc_host_enable_irq(struct ipc_host_env_tag *env, uint32_t value)
|
||||
{
|
||||
// Enable the handled interrupts
|
||||
ipc_emb2app_unmask_set(env->shared, value);
|
||||
}
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
*/
|
||||
void ipc_host_disable_irq(struct ipc_host_env_tag *env, uint32_t value)
|
||||
{
|
||||
// Enable the handled interrupts
|
||||
ipc_emb2app_unmask_clear(env->shared, value);
|
||||
}
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
*/
|
||||
uint32_t ipc_host_get_status(struct ipc_host_env_tag *env)
|
||||
{
|
||||
volatile uint32_t status;
|
||||
|
||||
status = ipc_emb2app_status_get(env->shared);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
*/
|
||||
uint32_t ipc_host_get_rawstatus(struct ipc_host_env_tag *env)
|
||||
{
|
||||
volatile uint32_t rawstatus;
|
||||
|
||||
rawstatus = ipc_emb2app_rawstatus_get(env->shared);
|
||||
|
||||
return rawstatus;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,508 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file ipc_host.h
|
||||
*
|
||||
* @brief IPC module.
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2011-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#ifndef _IPC_HOST_H_
|
||||
#define _IPC_HOST_H_
|
||||
|
||||
/*
|
||||
* INCLUDE FILES
|
||||
******************************************************************************
|
||||
*/
|
||||
#include "ipc_shared.h"
|
||||
#ifndef __KERNEL__
|
||||
#include "arch.h"
|
||||
#else
|
||||
#include "ipc_compat.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ENUMERATION
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
enum ipc_host_desc_status
|
||||
{
|
||||
/// Descriptor is IDLE
|
||||
IPC_HOST_DESC_IDLE = 0,
|
||||
/// Data can be forwarded
|
||||
IPC_HOST_DESC_FORWARD,
|
||||
/// Data has to be kept in UMAC memory
|
||||
IPC_HOST_DESC_KEEP,
|
||||
/// Delete stored packet
|
||||
IPC_HOST_DESC_DELETE,
|
||||
/// Update Frame Length status
|
||||
IPC_HOST_DESC_LEN_UPDATE,
|
||||
};
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @brief This structure is used to initialize the MAC SW
|
||||
*
|
||||
* The WLAN device driver provides functions call-back with this structure
|
||||
******************************************************************************
|
||||
*/
|
||||
struct ipc_host_cb_tag
|
||||
{
|
||||
/// WLAN driver call-back function: send_data_cfm
|
||||
int (*send_data_cfm)(void *pthis, void *host_id);
|
||||
|
||||
/// WLAN driver call-back function: recv_data_ind
|
||||
uint8_t (*recv_data_ind)(void *pthis, void *host_id);
|
||||
|
||||
/// WLAN driver call-back function: recv_radar_ind
|
||||
uint8_t (*recv_radar_ind)(void *pthis, void *host_id);
|
||||
|
||||
/// WLAN driver call-back function: recv_unsup_rx_vec_ind
|
||||
uint8_t (*recv_unsup_rx_vec_ind)(void *pthis, void *host_id);
|
||||
|
||||
/// WLAN driver call-back function: recv_msg_ind
|
||||
uint8_t (*recv_msg_ind)(void *pthis, void *host_id);
|
||||
|
||||
/// WLAN driver call-back function: recv_msgack_ind
|
||||
uint8_t (*recv_msgack_ind)(void *pthis, void *host_id);
|
||||
|
||||
/// WLAN driver call-back function: recv_dbg_ind
|
||||
uint8_t (*recv_dbg_ind)(void *pthis, void *host_id);
|
||||
|
||||
/// WLAN driver call-back function: prim_tbtt_ind
|
||||
void (*prim_tbtt_ind)(void *pthis);
|
||||
|
||||
/// WLAN driver call-back function: sec_tbtt_ind
|
||||
void (*sec_tbtt_ind)(void *pthis);
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Struct used to store information about host buffers (DMA Address and local pointer)
|
||||
*/
|
||||
struct ipc_hostbuf
|
||||
{
|
||||
void *hostid; ///< ptr to hostbuf client (ipc_host client) structure
|
||||
uint32_t dma_addr; ///< ptr to real hostbuf dma address
|
||||
};
|
||||
|
||||
/// Definition of the IPC Host environment structure.
|
||||
struct ipc_host_env_tag
|
||||
{
|
||||
/// Structure containing the callback pointers
|
||||
struct ipc_host_cb_tag cb;
|
||||
|
||||
/// Pointer to the shared environment
|
||||
struct ipc_shared_env_tag *shared;
|
||||
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
// Array used to store the descriptor addresses
|
||||
struct ipc_hostbuf ipc_host_rxdesc_array[IPC_RXDESC_CNT];
|
||||
// Index of the host RX descriptor array (ipc_shared environment)
|
||||
uint8_t ipc_host_rxdesc_idx;
|
||||
/// Store the number of RX Descriptors
|
||||
uint8_t rxdesc_nb;
|
||||
#endif //(CONFIG_RWNX_FULLMAC)
|
||||
|
||||
/// Fields for Data Rx handling
|
||||
// Index used for ipc_host_rxbuf_array to point to current buffer
|
||||
uint8_t ipc_host_rxbuf_idx;
|
||||
// Store the number of Rx Data buffers
|
||||
uint32_t rx_bufnb;
|
||||
// Store the size of the Rx Data buffers
|
||||
uint32_t rx_bufsz;
|
||||
|
||||
/// Fields for Radar events handling
|
||||
// Global array used to store the hostid and hostbuf addresses
|
||||
struct ipc_hostbuf ipc_host_radarbuf_array[IPC_RADARBUF_CNT];
|
||||
// Index used for ipc_host_rxbuf_array to point to current buffer
|
||||
uint8_t ipc_host_radarbuf_idx;
|
||||
// Store the number of radar event buffers
|
||||
uint32_t radar_bufnb;
|
||||
// Store the size of the radar event buffers
|
||||
uint32_t radar_bufsz;
|
||||
|
||||
///Fields for Unsupported frame handling
|
||||
// Global array used to store the hostid and hostbuf addresses
|
||||
struct ipc_hostbuf ipc_host_unsuprxvecbuf_array[IPC_UNSUPRXVECBUF_CNT];
|
||||
// Index used for ipc_host_unsuprxvecbuf_array to point to current buffer
|
||||
uint8_t ipc_host_unsuprxvecbuf_idx;
|
||||
// Store the number of unsupported rx vector buffers
|
||||
uint32_t unsuprxvec_bufnb;
|
||||
// Store the size of unsupported rx vector buffers
|
||||
uint32_t unsuprxvec_bufsz;
|
||||
|
||||
// Index used that points to the first free TX desc
|
||||
uint32_t txdesc_free_idx[IPC_TXQUEUE_CNT][CONFIG_USER_MAX];
|
||||
// Index used that points to the first used TX desc
|
||||
uint32_t txdesc_used_idx[IPC_TXQUEUE_CNT][CONFIG_USER_MAX];
|
||||
// Array storing the currently pushed host ids for the BK queue
|
||||
void *tx_host_id0[CONFIG_USER_MAX][NX_TXDESC_CNT0];
|
||||
// Array storing the currently pushed host ids for the BE queue
|
||||
void *tx_host_id1[CONFIG_USER_MAX][NX_TXDESC_CNT1];
|
||||
// Array storing the currently pushed host ids for the VI queue
|
||||
void *tx_host_id2[CONFIG_USER_MAX][NX_TXDESC_CNT2];
|
||||
// Array storing the currently pushed host ids for the VO queue
|
||||
void *tx_host_id3[CONFIG_USER_MAX][NX_TXDESC_CNT3];
|
||||
#if NX_TXQ_CNT == 5
|
||||
// Array storing the currently pushed host ids for the BCN queue
|
||||
void *tx_host_id4[1][NX_TXDESC_CNT4];
|
||||
#endif
|
||||
// Pointer to the different host ids arrays, per IPC queue
|
||||
void **tx_host_id[IPC_TXQUEUE_CNT][CONFIG_USER_MAX];
|
||||
// Pointer to the different TX descriptor arrays, per IPC queue
|
||||
volatile struct txdesc_host *txdesc[IPC_TXQUEUE_CNT][CONFIG_USER_MAX];
|
||||
|
||||
/// Fields for Emb->App MSGs handling
|
||||
// Global array used to store the hostid and hostbuf addresses for msg/ind
|
||||
struct ipc_hostbuf ipc_host_msgbuf_array[IPC_MSGE2A_BUF_CNT];
|
||||
// Index of the MSG E2A buffers array to point to current buffer
|
||||
uint8_t ipc_host_msge2a_idx;
|
||||
// Store the number of E2A MSG buffers
|
||||
uint32_t ipc_e2amsg_bufnb;
|
||||
// Store the size of the E2A MSG buffers
|
||||
uint32_t ipc_e2amsg_bufsz;
|
||||
|
||||
/// E2A ACKs of A2E MSGs
|
||||
uint8_t msga2e_cnt;
|
||||
void *msga2e_hostid;
|
||||
|
||||
/// Fields for Debug MSGs handling
|
||||
// Global array used to store the hostid and hostbuf addresses for Debug messages
|
||||
struct ipc_hostbuf ipc_host_dbgbuf_array[IPC_DBGBUF_CNT];
|
||||
// Index of the Debug messages buffers array to point to current buffer
|
||||
uint8_t ipc_host_dbg_idx;
|
||||
// Store the number of Debug messages buffers
|
||||
uint32_t ipc_dbg_bufnb;
|
||||
// Store the size of the Debug messages buffers
|
||||
uint32_t ipc_dbg_bufsz;
|
||||
|
||||
/// Pointer to the attached object (used in callbacks and register accesses)
|
||||
void *pthis;
|
||||
};
|
||||
|
||||
extern const int nx_txdesc_cnt[];
|
||||
extern const int nx_txuser_cnt[];
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @brief Returns the full/not full status of the queue the index of which is
|
||||
* passed as parameter.
|
||||
*
|
||||
* @param[in] env Pointer to the IPC host environment
|
||||
* @param[in] queue_idx Index of the queue to be checked
|
||||
*
|
||||
* @return true if the queue is full, false otherwise
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
__INLINE bool ipc_host_queue_full(struct ipc_host_env_tag *env,
|
||||
const int queue_idx)
|
||||
{
|
||||
return (env->txdesc_free_idx[queue_idx] ==
|
||||
(env->txdesc_used_idx[queue_idx] + nx_txdesc_cnt[queue_idx]));
|
||||
}
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @brief Initialize the IPC running on the Application CPU.
|
||||
*
|
||||
* This function:
|
||||
* - initializes the IPC software environments
|
||||
* - enables the interrupts in the IPC block
|
||||
*
|
||||
* @param[in] env Pointer to the IPC host environment
|
||||
*
|
||||
* @warning Since this function resets the IPC Shared memory, it must be called
|
||||
* before the LMAC FW is launched because LMAC sets some init values in IPC
|
||||
* Shared memory at boot.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
void ipc_host_init(struct ipc_host_env_tag *env,
|
||||
struct ipc_host_cb_tag *cb,
|
||||
struct ipc_shared_env_tag *shared_env_ptr,
|
||||
void *pthis);
|
||||
|
||||
/** @addtogroup IPC_TX
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @brief Retrieve a new free Tx descriptor (host side).
|
||||
*
|
||||
* This function returns a pointer to the next Tx descriptor available from the
|
||||
* queue queue_idx to the host driver. The driver will have to fill it with the
|
||||
* appropriate endianness and to send it to the
|
||||
* emb side with ipc_host_txdesc_push().
|
||||
*
|
||||
* This function should only be called once until ipc_host_txdesc_push() is called.
|
||||
*
|
||||
* This function will return NULL if the queue is full.
|
||||
*
|
||||
* @param[in] env Pointer to the IPC host environment
|
||||
* @param[in] queue_idx Queue index. The index can be inferred from the
|
||||
* user priority of the incoming packet.
|
||||
* @param[in] user_pos User position. If MU-MIMO is not used, this value
|
||||
* shall be 0.
|
||||
* @return Pointer to the next Tx descriptor free. This can
|
||||
* point to the host memory or to shared memory,
|
||||
* depending on IPC implementation.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
volatile struct txdesc_host *ipc_host_txdesc_get(struct ipc_host_env_tag *env,
|
||||
const int queue_idx,
|
||||
const int user_pos);
|
||||
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @brief Push a filled Tx descriptor (host side).
|
||||
*
|
||||
* This function sets the next Tx descriptor available by the host side:
|
||||
* - as used for the host side
|
||||
* - as available for the emb side.
|
||||
* The Tx descriptor must be correctly filled before calling this function.
|
||||
*
|
||||
* This function may trigger an IRQ to the emb CPU depending on the interrupt
|
||||
* mitigation policy and on the push count.
|
||||
*
|
||||
* @param[in] env Pointer to the IPC host environment
|
||||
* @param[in] queue_idx Queue index. Same value than ipc_host_txdesc_get()
|
||||
* @param[in] user_pos User position. If MU-MIMO is not used, this value
|
||||
* shall be 0.
|
||||
* @param[in] host_id Parameter indicated by the IPC at TX confirmation,
|
||||
* that allows the driver finding the buffer
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
void ipc_host_txdesc_push(struct ipc_host_env_tag *env, const int queue_idx,
|
||||
const int user_pos, void *host_id);
|
||||
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @brief Check if there are TX frames pending in the TX queues.
|
||||
*
|
||||
* @param[in] env Pointer to the IPC host environment
|
||||
*
|
||||
* @return true if there are frames pending, false otherwise.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
bool ipc_host_tx_frames_pending(struct ipc_host_env_tag *env);
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @brief Get and flush a packet from the IPC queue passed as parameter.
|
||||
*
|
||||
* @param[in] env Pointer to the IPC host environment
|
||||
* @param[in] queue_idx Index of the queue to flush
|
||||
* @param[in] user_pos User position to flush
|
||||
*
|
||||
* @return The flushed hostid if there is one, 0 otherwise.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
void *ipc_host_tx_flush(struct ipc_host_env_tag *env, const int queue_idx,
|
||||
const int user_pos);
|
||||
|
||||
/// @} IPC_TX
|
||||
|
||||
/** @addtogroup IPC_RX
|
||||
* @{
|
||||
*/
|
||||
void ipc_host_patt_addr_push(struct ipc_host_env_tag *env, uint32_t addr);
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @brief Push a pre-allocated buffer descriptor for Rx packet (host side)
|
||||
*
|
||||
* This function should be called by the host IRQ handler to supply the
|
||||
* embedded side with new empty buffer.
|
||||
*
|
||||
* @param[in] env Pointer to the IPC host environment
|
||||
* @param[in] hostid Packet ID used by the host (skbuff pointer on Linux)
|
||||
* @param[in] hostbuf Pointer to the start of the buffer payload in the
|
||||
* host memory (this may be inferred from the skbuff?)
|
||||
* The length of this buffer should be predefined
|
||||
* between host and emb statically (constant needed?).
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
int ipc_host_rxbuf_push(struct ipc_host_env_tag *env,
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
uint32_t hostid,
|
||||
#endif
|
||||
uint32_t hostbuf);
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @brief Push a pre-allocated Descriptor
|
||||
*
|
||||
* This function should be called by the host IRQ handler to supply the
|
||||
* embedded side with new empty buffer.
|
||||
*
|
||||
* @param[in] env Pointer to the IPC host environment
|
||||
* @param[in] hostid Address of packet for host
|
||||
* @param[in] hostbuf Pointer to the start of the buffer payload in the
|
||||
* host memory. The length of this buffer should be
|
||||
* predefined between host and emb statically.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
int ipc_host_rxdesc_push(struct ipc_host_env_tag *env, void *hostid,
|
||||
uint32_t hostbuf);
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @brief Push a pre-allocated radar event buffer descriptor
|
||||
*
|
||||
* This function is called at Init time to initialize all radar event buffers.
|
||||
* Then each time embedded send a radar event, this function is used to push
|
||||
* back the same buffer once it has been handled.
|
||||
*
|
||||
* @param[in] env Pointer to the IPC host environment
|
||||
* @param[in] hostid Address of packet for host
|
||||
* @param[in] hostbuf Pointer to the start of the buffer payload in the
|
||||
* host memory. The length of this buffer should be
|
||||
* predefined between host and emb statically.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
int ipc_host_radarbuf_push(struct ipc_host_env_tag *env, void *hostid,
|
||||
uint32_t hostbuf);
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @brief Push a pre-allocated unsupported rx vector buffer descriptor
|
||||
*
|
||||
* This function is called at Init time to initialize all unsupported rx vector
|
||||
* buffers. Then each time the embedded sends a unsupported rx vector, this
|
||||
* function is used to push a new unsupported rx vector buffer.
|
||||
*
|
||||
* @param[in] env Pointer to the IPC host environment
|
||||
* @param[in] hostid Address of packet for host
|
||||
* @param[in] hostbuf Pointer to the start of the buffer payload in the
|
||||
* host memory. The length of this buffer should be
|
||||
* predefined between host and emb statically.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
int ipc_host_unsup_rx_vec_buf_push(struct ipc_host_env_tag *env, void *hostid,
|
||||
uint32_t hostbuf);
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @brief Push a pre-allocated buffer descriptor for IPC MSGs (host side)
|
||||
*
|
||||
* This function is called at Init time to initialize all Emb2App messages
|
||||
* buffers. Then each time embedded send a IPC message, this function is used
|
||||
* to push back the same buffer once it has been handled.
|
||||
*
|
||||
* @param[in] env Pointer to the IPC host environment
|
||||
* @param[in] hostid Address of buffer for host
|
||||
* @param[in] hostbuf Address of buffer for embedded
|
||||
* The length of this buffer should be predefined
|
||||
* between host and emb statically.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
int ipc_host_msgbuf_push(struct ipc_host_env_tag *env, void *hostid,
|
||||
uint32_t hostbuf);
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @brief Push a pre-allocated buffer descriptor for Debug messages (host side)
|
||||
*
|
||||
* This function is called at Init time to initialize all debug messages.
|
||||
* Then each time embedded send a debug message, this function is used to push
|
||||
* back the same buffer once it has been handled.
|
||||
*
|
||||
* @param[in] env Pointer to the IPC host environment
|
||||
* @param[in] hostid Address of buffer for host
|
||||
* @param[in] hostbuf Address of buffer for embedded
|
||||
* The length of this buffer should be predefined
|
||||
* between host and emb statically.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
int ipc_host_dbgbuf_push(struct ipc_host_env_tag *env, void *hostid,
|
||||
uint32_t hostbuf);
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @brief Push the pre-allocated logic analyzer and debug information buffer
|
||||
*
|
||||
* @param[in] env Pointer to the IPC host environment
|
||||
* @param[in] infobuf Address of buffer for embedded
|
||||
* The length of this buffer should be predefined
|
||||
* between host and emb statically.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
void ipc_host_dbginfobuf_push(struct ipc_host_env_tag *env, uint32_t infobuf);
|
||||
|
||||
/// @} IPC_RX
|
||||
|
||||
|
||||
|
||||
/** @addtogroup IPC_MISC
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @brief Handle all IPC interrupts on the host side.
|
||||
*
|
||||
* The following interrupts should be handled:
|
||||
* Tx confirmation, Rx buffer requests, Rx packet ready and kernel messages
|
||||
*
|
||||
* @param[in] env Pointer to the IPC host environment
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
void ipc_host_irq(struct ipc_host_env_tag *env, uint32_t status);
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @brief Send a message to the embedded side
|
||||
*
|
||||
* @param[in] env Pointer to the IPC host environment
|
||||
* @param[in] msg_buf Pointer to the message buffer
|
||||
* @param[in] msg_len Length of the message to be transmitted
|
||||
*
|
||||
* @return Non-null value on failure
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
int ipc_host_msg_push(struct ipc_host_env_tag *env, void *msg_buf, uint16_t len);
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @brief Enable IPC interrupts
|
||||
*
|
||||
* @param[in] env Global ipc_host environment pointer
|
||||
* @param[in] value Bitfield of the interrupts to enable
|
||||
*
|
||||
* @warning After calling this function, IPC interrupts can be triggered at any
|
||||
* time. Potentially, an interrupt could happen even before returning from the
|
||||
* function if there is a request pending from the embedded side.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
void ipc_host_enable_irq(struct ipc_host_env_tag *env, uint32_t value);
|
||||
void ipc_host_disable_irq(struct ipc_host_env_tag *env, uint32_t value);
|
||||
|
||||
uint32_t ipc_host_get_status(struct ipc_host_env_tag *env);
|
||||
uint32_t ipc_host_get_rawstatus(struct ipc_host_env_tag *env);
|
||||
|
||||
/// @} IPC_MISC
|
||||
|
||||
|
||||
#endif // _IPC_HOST_H_
|
||||
@@ -0,0 +1,802 @@
|
||||
/**
|
||||
****************************************************************************************
|
||||
*
|
||||
* @file ipc_shared.h
|
||||
*
|
||||
* @brief Shared data between both IPC modules.
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2011-2019
|
||||
*
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _IPC_SHARED_H_
|
||||
#define _IPC_SHARED_H_
|
||||
|
||||
/*
|
||||
* INCLUDE FILES
|
||||
****************************************************************************************
|
||||
*/
|
||||
#include "ipc_compat.h"
|
||||
#include "lmac_mac.h"
|
||||
|
||||
/*
|
||||
* DEFINES AND MACROS
|
||||
****************************************************************************************
|
||||
*/
|
||||
#define CO_BIT(pos) (1U<<(pos))
|
||||
|
||||
#define IPC_TXQUEUE_CNT NX_TXQ_CNT
|
||||
#define NX_TXDESC_CNT0 8
|
||||
#define NX_TXDESC_CNT1 64
|
||||
#define NX_TXDESC_CNT2 64
|
||||
#define NX_TXDESC_CNT3 32
|
||||
#if NX_TXQ_CNT == 5
|
||||
#define NX_TXDESC_CNT4 8
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Number of Host buffers available for Data Rx handling (through DMA)
|
||||
*/
|
||||
#define IPC_RXBUF_CNT 128
|
||||
|
||||
/*
|
||||
* Number of shared descriptors available for Data RX handling
|
||||
*/
|
||||
#define IPC_RXDESC_CNT 128
|
||||
|
||||
/*
|
||||
* Number of Host buffers available for Radar events handling (through DMA)
|
||||
*/
|
||||
#define IPC_RADARBUF_CNT 16
|
||||
|
||||
/*
|
||||
* Number of Host buffers available for unsupported Rx vectors handling (through DMA)
|
||||
*/
|
||||
#define IPC_UNSUPRXVECBUF_CNT 8
|
||||
|
||||
/*
|
||||
* Size of RxVector
|
||||
*/
|
||||
#define IPC_RXVEC_SIZE 16
|
||||
|
||||
/*
|
||||
* Number of Host buffers available for Emb->App MSGs sending (through DMA)
|
||||
*/
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
#define IPC_MSGE2A_BUF_CNT 64
|
||||
#endif
|
||||
/*
|
||||
* Number of Host buffers available for Debug Messages sending (through DMA)
|
||||
*/
|
||||
#define IPC_DBGBUF_CNT 32
|
||||
|
||||
/*
|
||||
* Length used in MSGs structures
|
||||
*/
|
||||
#define IPC_A2E_MSG_BUF_SIZE 127 // size in 4-byte words
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
#define IPC_E2A_MSG_SIZE_BASE 256 // size in 4-byte words
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RWNX_TL4
|
||||
#define IPC_E2A_MSG_PARAM_SIZE (IPC_E2A_MSG_SIZE_BASE + (IPC_E2A_MSG_SIZE_BASE / 2))
|
||||
#else
|
||||
#define IPC_E2A_MSG_PARAM_SIZE IPC_E2A_MSG_SIZE_BASE
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Debug messages buffers size (in bytes)
|
||||
*/
|
||||
#define IPC_DBG_PARAM_SIZE 256
|
||||
|
||||
/*
|
||||
* Define used for Rx hostbuf validity.
|
||||
* This value should appear only when hostbuf was used for a Reception.
|
||||
*/
|
||||
#define RX_DMA_OVER_PATTERN 0xAAAAAA00
|
||||
|
||||
/*
|
||||
* Define used for MSG buffers validity.
|
||||
* This value will be written only when a MSG buffer is used for sending from Emb to App.
|
||||
*/
|
||||
#define IPC_MSGE2A_VALID_PATTERN 0xADDEDE2A
|
||||
|
||||
/*
|
||||
* Define used for Debug messages buffers validity.
|
||||
* This value will be written only when a DBG buffer is used for sending from Emb to App.
|
||||
*/
|
||||
#define IPC_DBG_VALID_PATTERN 0x000CACA0
|
||||
|
||||
/*
|
||||
* Length of the receive vectors, in bytes
|
||||
*/
|
||||
#define DMA_HDR_PHYVECT_LEN 36
|
||||
|
||||
/*
|
||||
* Maximum number of payload addresses and lengths present in the descriptor
|
||||
*/
|
||||
#define NX_TX_PAYLOAD_MAX 6
|
||||
|
||||
/*
|
||||
* Message struct/ID API version
|
||||
*/
|
||||
#define MSG_API_VER 15
|
||||
|
||||
/*
|
||||
****************************************************************************************
|
||||
*/
|
||||
// c.f LMAC/src/tx/tx_swdesc.h
|
||||
/// Descriptor filled by the Host
|
||||
struct hostdesc
|
||||
{
|
||||
/// Pointer to packet payload
|
||||
//u32_l packet_addr;
|
||||
/// Size of the payload
|
||||
u16_l packet_len;
|
||||
u16_l flags_ext;
|
||||
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
/// Address of the status descriptor in host memory (used for confirmation upload)
|
||||
u32_l status_desc_addr;
|
||||
/// Destination Address
|
||||
struct mac_addr eth_dest_addr;
|
||||
/// Source Address
|
||||
struct mac_addr eth_src_addr;
|
||||
/// Ethernet Type
|
||||
u16_l ethertype;
|
||||
#else /* ! CONFIG_RWNX_FULLMAC */
|
||||
#ifdef CONFIG_RWNX_AGG_TX
|
||||
///Sequence Number for AMPDU MPDUs - for quick check if it's allowed within window
|
||||
u16_l sn;
|
||||
#endif /* CONFIG_RWNX_AGG_TX */
|
||||
/// Padding between the buffer control structure and the MPDU in host memory
|
||||
u8_l padding;
|
||||
#endif /* CONFIG_RWNX_FULLMAC */
|
||||
u8_l ac;
|
||||
/// Packet TID (0xFF if not a QoS frame)
|
||||
u8_l tid;
|
||||
/// Interface Id
|
||||
u8_l vif_idx;
|
||||
/// Station Id (0xFF if station is unknown)
|
||||
u8_l staid;
|
||||
#ifdef CONFIG_RWNX_MUMIMO_TX
|
||||
/// MU-MIMO information (GroupId and User Position in the group) - The GroupId
|
||||
/// is located on bits 0-5 and the User Position on bits 6-7. The GroupId value is set
|
||||
/// to 63 if MU-MIMO shall not be used
|
||||
u8_l mumimo_info;
|
||||
#endif /* CONFIG_RWNX_MUMIMO_TX */
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
/// TX flags
|
||||
u16_l flags;
|
||||
#endif /* CONFIG_RWNX_FULLMAC */
|
||||
};
|
||||
|
||||
/// Descriptor filled by the UMAC
|
||||
struct umacdesc
|
||||
{
|
||||
#ifdef CONFIG_RWNX_AGG_TX
|
||||
///First Sequence Number of the BlockAck window
|
||||
u16_l sn_win;
|
||||
/// Flags from UMAC (match tx_hd.macctrlinfo2 format)
|
||||
u32_l flags;
|
||||
/// PHY related flags field - rate, GI type, BW type - filled by driver
|
||||
u32_l phy_flags;
|
||||
#endif //(CONFIG_RWNX_AGG_TX)
|
||||
};
|
||||
|
||||
struct txdesc_api
|
||||
{
|
||||
/// Information provided by Host
|
||||
struct hostdesc host;
|
||||
};
|
||||
|
||||
|
||||
struct txdesc_host
|
||||
{
|
||||
u32_l ready;
|
||||
|
||||
/// API of the embedded part
|
||||
struct txdesc_api api;
|
||||
};
|
||||
|
||||
/// Comes from ipc_dma.h
|
||||
/// Element in the pool of TX DMA bridge descriptors.
|
||||
struct dma_desc
|
||||
{
|
||||
/** Application subsystem address which is used as source address for DMA payload
|
||||
* transfer*/
|
||||
u32_l src;
|
||||
/** Points to the start of the embedded data buffer associated with this descriptor.
|
||||
* This address acts as the destination address for the DMA payload transfer*/
|
||||
u32_l dest;
|
||||
/// Complete length of the buffer in memory
|
||||
u16_l length;
|
||||
/// Control word for the DMA engine (e.g. for interrupt generation)
|
||||
u16_l ctrl;
|
||||
/// Pointer to the next element of the chained list
|
||||
u32_l next;
|
||||
};
|
||||
|
||||
// Comes from la.h
|
||||
/// Length of the configuration data of a logic analyzer
|
||||
#define LA_CONF_LEN 10
|
||||
|
||||
/// Structure containing the configuration data of a logic analyzer
|
||||
struct la_conf_tag
|
||||
{
|
||||
u32_l conf[LA_CONF_LEN];
|
||||
u32_l trace_len;
|
||||
u32_l diag_conf;
|
||||
};
|
||||
|
||||
/// Size of a logic analyzer memory
|
||||
#define LA_MEM_LEN (1024 * 1024)
|
||||
|
||||
/// Type of errors
|
||||
enum
|
||||
{
|
||||
/// Recoverable error, not requiring any action from Upper MAC
|
||||
DBG_ERROR_RECOVERABLE = 0,
|
||||
/// Fatal error, requiring Upper MAC to reset Lower MAC and HW and restart operation
|
||||
DBG_ERROR_FATAL
|
||||
};
|
||||
|
||||
/// Maximum length of the SW diag trace
|
||||
#define DBG_SW_DIAG_MAX_LEN 1024
|
||||
|
||||
/// Maximum length of the error trace
|
||||
#define DBG_ERROR_TRACE_SIZE 256
|
||||
|
||||
/// Number of MAC diagnostic port banks
|
||||
#define DBG_DIAGS_MAC_MAX 48
|
||||
|
||||
/// Number of PHY diagnostic port banks
|
||||
#define DBG_DIAGS_PHY_MAX 32
|
||||
|
||||
/// Maximum size of the RX header descriptor information in the debug dump
|
||||
#define DBG_RHD_MEM_LEN (5 * 1024)
|
||||
|
||||
/// Maximum size of the RX buffer descriptor information in the debug dump
|
||||
#define DBG_RBD_MEM_LEN (5 * 1024)
|
||||
|
||||
/// Maximum size of the TX header descriptor information in the debug dump
|
||||
#define DBG_THD_MEM_LEN (10 * 1024)
|
||||
|
||||
/// Structure containing the information about the PHY channel that is used
|
||||
struct phy_channel_info
|
||||
{
|
||||
/// PHY channel information 1
|
||||
u32_l info1;
|
||||
/// PHY channel information 2
|
||||
u32_l info2;
|
||||
};
|
||||
|
||||
/// Debug information forwarded to host when an error occurs
|
||||
struct dbg_debug_info_tag
|
||||
{
|
||||
/// Type of error (0: recoverable, 1: fatal)
|
||||
u32_l error_type;
|
||||
/// Pointer to the first RX Header Descriptor chained to the MAC HW
|
||||
u32_l rhd;
|
||||
/// Size of the RX header descriptor buffer
|
||||
u32_l rhd_len;
|
||||
/// Pointer to the first RX Buffer Descriptor chained to the MAC HW
|
||||
u32_l rbd;
|
||||
/// Size of the RX buffer descriptor buffer
|
||||
u32_l rbd_len;
|
||||
/// Pointer to the first TX Header Descriptors chained to the MAC HW
|
||||
u32_l thd[NX_TXQ_CNT];
|
||||
/// Size of the TX header descriptor buffer
|
||||
u32_l thd_len[NX_TXQ_CNT];
|
||||
/// MAC HW diag configuration
|
||||
u32_l hw_diag;
|
||||
/// Error message
|
||||
u32_l error[DBG_ERROR_TRACE_SIZE/4];
|
||||
/// SW diag configuration length
|
||||
u32_l sw_diag_len;
|
||||
/// SW diag configuration
|
||||
u32_l sw_diag[DBG_SW_DIAG_MAX_LEN/4];
|
||||
/// PHY channel information
|
||||
struct phy_channel_info chan_info;
|
||||
/// Embedded LA configuration
|
||||
struct la_conf_tag la_conf;
|
||||
/// MAC diagnostic port state
|
||||
u16_l diags_mac[DBG_DIAGS_MAC_MAX];
|
||||
/// PHY diagnostic port state
|
||||
u16_l diags_phy[DBG_DIAGS_PHY_MAX];
|
||||
/// MAC HW RX Header descriptor pointer
|
||||
u32_l rhd_hw_ptr;
|
||||
/// MAC HW RX Buffer descriptor pointer
|
||||
u32_l rbd_hw_ptr;
|
||||
};
|
||||
|
||||
/// Full debug dump that is forwarded to host in case of error
|
||||
struct dbg_debug_dump_tag
|
||||
{
|
||||
/// Debug information
|
||||
struct dbg_debug_info_tag dbg_info;
|
||||
|
||||
/// RX header descriptor memory
|
||||
u32_l rhd_mem[DBG_RHD_MEM_LEN/4];
|
||||
|
||||
/// RX buffer descriptor memory
|
||||
u32_l rbd_mem[DBG_RBD_MEM_LEN/4];
|
||||
|
||||
/// TX header descriptor memory
|
||||
u32_l thd_mem[NX_TXQ_CNT][DBG_THD_MEM_LEN/4];
|
||||
|
||||
/// Logic analyzer memory
|
||||
u32_l la_mem[LA_MEM_LEN/4];
|
||||
};
|
||||
|
||||
|
||||
/// Number of pulses in a radar event structure
|
||||
#define RADAR_PULSE_MAX 4
|
||||
|
||||
/// Definition of an array of radar pulses
|
||||
struct radar_pulse_array_desc
|
||||
{
|
||||
/// Buffer containing the radar pulses
|
||||
u32_l pulse[RADAR_PULSE_MAX];
|
||||
/// Index of the radar detection chain that detected those pulses
|
||||
u32_l idx;
|
||||
/// Number of valid pulses in the buffer
|
||||
u32_l cnt;
|
||||
};
|
||||
|
||||
/// Bit mapping inside a radar pulse element
|
||||
struct radar_pulse {
|
||||
s32_l freq:6; /** Freq (resolution is 2Mhz range is [-Fadc/4 .. Fadc/4]) */
|
||||
u32_l fom:4; /** Figure of Merit */
|
||||
u32_l len:6; /** Length of the current radar pulse (resolution is 2us) */
|
||||
u32_l rep:16; /** Time interval between the previous radar event
|
||||
and the current one (in us) */
|
||||
};
|
||||
|
||||
/// Definition of a RX vector descriptor
|
||||
struct rx_vector_desc
|
||||
{
|
||||
/// PHY channel information
|
||||
struct phy_channel_info phy_info;
|
||||
|
||||
/// RX vector 1
|
||||
u32_l rx_vect1[IPC_RXVEC_SIZE/4];
|
||||
|
||||
/// Used to print a valid rx vector
|
||||
u32_l pattern;
|
||||
};
|
||||
|
||||
///
|
||||
struct rxdesc_tag
|
||||
{
|
||||
/// Host Buffer Address
|
||||
u32_l host_id;
|
||||
/// Length
|
||||
u32_l frame_len;
|
||||
/// Status
|
||||
u16_l status;
|
||||
};
|
||||
|
||||
/**
|
||||
****************************************************************************************
|
||||
* @defgroup IPC IPC
|
||||
* @ingroup NXMAC
|
||||
* @brief Inter Processor Communication module.
|
||||
*
|
||||
* The IPC module implements the protocol to communicate between the Host CPU
|
||||
* and the Embedded CPU.
|
||||
*
|
||||
* @see http://en.wikipedia.org/wiki/Circular_buffer
|
||||
* For more information about the ring buffer typical use and difficulties.
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
****************************************************************************************
|
||||
* @addtogroup IPC_TX IPC Tx path
|
||||
* @ingroup IPC
|
||||
* @brief IPC Tx path structures and functions
|
||||
*
|
||||
* A typical use case of the IPC Tx path API:
|
||||
* @msc
|
||||
* hscale = "2";
|
||||
*
|
||||
* a [label=Driver],
|
||||
* b [label="IPC host"],
|
||||
* c [label="IPC emb"],
|
||||
* d [label=Firmware];
|
||||
*
|
||||
* --- [label="Tx descriptor queue example"];
|
||||
* a=>a [label="Driver receives a Tx packet from OS"];
|
||||
* a=>b [label="ipc_host_txdesc_get()"];
|
||||
* a<<b [label="struct txdesc_host *"];
|
||||
* a=>a [label="Driver fill the descriptor"];
|
||||
* a=>b [label="ipc_host_txdesc_push()"];
|
||||
* ... [label="(several Tx desc can be pushed)"];
|
||||
* b:>c [label="Tx desc queue filled IRQ"];
|
||||
* c=>>d [label="EDCA sub-scheduler callback"];
|
||||
* c<<d [label="Tx desc queue to pop"];
|
||||
* c=>>d [label="UMAC Tx desc callback"];
|
||||
* ... [label="(several Tx desc can be popped)"];
|
||||
* d=>d [label="Packets are sent or discarded"];
|
||||
* --- [label="Tx confirm queue example"];
|
||||
* c<=d [label="ipc_emb_txcfm_push()"];
|
||||
* c>>d [label="Request accepted"];
|
||||
* ... [label="(several Tx cfm can be pushed)"];
|
||||
* b<:c [label="Tx cfm queue filled IRQ"];
|
||||
* a<<=b [label="Driver's Tx Confirm callback"];
|
||||
* a=>b [label="ipc_host_txcfm_pop()"];
|
||||
* a<<b [label="struct ipc_txcfm"];
|
||||
* a<=a [label="Packets are freed by the driver"];
|
||||
* @endmsc
|
||||
*
|
||||
* @{
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
/// @} IPC_TX
|
||||
|
||||
/**
|
||||
****************************************************************************************
|
||||
* @defgroup IPC_RX IPC Rx path
|
||||
* @ingroup IPC
|
||||
* @brief IPC Rx path functions and structures
|
||||
*
|
||||
* A typical use case of the IPC Rx path API:
|
||||
* @msc
|
||||
* hscale = "2";
|
||||
*
|
||||
* a [label=Firmware],
|
||||
* b [label="IPC emb"],
|
||||
* c [label="IPC host"],
|
||||
* d [label=Driver];
|
||||
*
|
||||
* --- [label="Rx buffer and desc queues usage example"];
|
||||
* d=>c [label="ipc_host_rxbuf_push()"];
|
||||
* d=>c [label="ipc_host_rxbuf_push()"];
|
||||
* d=>c [label="ipc_host_rxbuf_push()"];
|
||||
* ... [label="(several Rx buffer are pushed)"];
|
||||
* a=>a [label=" Frame is received\n from the medium"];
|
||||
* a<<b [label="struct ipc_rxbuf"];
|
||||
* a=>a [label=" Firmware fill the buffer\n with received frame"];
|
||||
* a<<b [label="Push accepted"];
|
||||
* ... [label="(several Rx desc can be pushed)"];
|
||||
* b:>c [label="Rx desc queue filled IRQ"];
|
||||
* c=>>d [label="Driver Rx packet callback"];
|
||||
* c<=d [label="ipc_host_rxdesc_pop()"];
|
||||
* d=>d [label="Rx packet is handed \nover to the OS "];
|
||||
* ... [label="(several Rx desc can be poped)"];
|
||||
* --- [label="Rx buffer request exemple"];
|
||||
* b:>c [label="Low Rx buffer count IRQ"];
|
||||
* a<<b [label="struct ipc_rxbuf"];
|
||||
* c=>>d [label="Driver Rx buffer callback"];
|
||||
* d=>c [label="ipc_host_rxbuf_push()"];
|
||||
* d=>c [label="ipc_host_rxbuf_push()"];
|
||||
* d=>c [label="ipc_host_rxbuf_push()"];
|
||||
* ... [label="(several Rx buffer are pushed)"];
|
||||
* @endmsc
|
||||
*
|
||||
* @addtogroup IPC_RX
|
||||
* @{
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
/// @} IPC_RX
|
||||
|
||||
|
||||
|
||||
/**
|
||||
****************************************************************************************
|
||||
* @defgroup IPC_MISC IPC Misc
|
||||
* @ingroup IPC
|
||||
* @brief IPC miscellaneous functions
|
||||
****************************************************************************************
|
||||
*/
|
||||
/** IPC header structure. This structure is stored at the beginning of every IPC message.
|
||||
* @warning This structure's size must NOT exceed 4 bytes in length.
|
||||
*/
|
||||
struct ipc_header
|
||||
{
|
||||
/// IPC message type.
|
||||
u16_l type;
|
||||
/// IPC message size in number of bytes.
|
||||
u16_l size;
|
||||
};
|
||||
|
||||
struct ipc_msg_elt
|
||||
{
|
||||
/// Message header (alignment forced on word size, see allocation in shared env).
|
||||
struct ipc_header header __ALIGN4;
|
||||
};
|
||||
|
||||
/// Message structure for MSGs from Emb to App
|
||||
struct ipc_e2a_msg
|
||||
{
|
||||
u16_l id; ///< Message id.
|
||||
u16_l dummy_dest_id;
|
||||
u16_l dummy_src_id;
|
||||
u16_l param_len; ///< Parameter embedded struct length.
|
||||
u32_l pattern; ///< Used to stamp a valid MSG buffer
|
||||
u32_l param[IPC_E2A_MSG_PARAM_SIZE]; ///< Parameter embedded struct. Must be word-aligned.
|
||||
};
|
||||
|
||||
/// Message structure for Debug messages from Emb to App
|
||||
struct ipc_dbg_msg
|
||||
{
|
||||
u32_l string[IPC_DBG_PARAM_SIZE/4]; ///< Debug string
|
||||
u32_l pattern; ///< Used to stamp a valid buffer
|
||||
};
|
||||
|
||||
/// Message structure for MSGs from App to Emb.
|
||||
/// Actually a sub-structure will be used when filling the messages.
|
||||
struct ipc_a2e_msg
|
||||
{
|
||||
u32_l dummy_word; // used to cope with kernel message structure
|
||||
u32_l msg[IPC_A2E_MSG_BUF_SIZE]; // body of the msg
|
||||
};
|
||||
|
||||
struct ipc_shared_rx_buf
|
||||
{
|
||||
/// < ptr to hostbuf client (ipc_host client) structure
|
||||
u32_l hostid;
|
||||
/// < ptr to real hostbuf dma address
|
||||
u32_l dma_addr;
|
||||
};
|
||||
|
||||
struct ipc_shared_rx_desc
|
||||
{
|
||||
/// DMA Address
|
||||
u32_l dma_addr;
|
||||
};
|
||||
|
||||
/// Structure containing FW characteristics for compatibility checking
|
||||
struct compatibility_tag {
|
||||
/// Size of IPC shared memory
|
||||
u16_l ipc_shared_size;
|
||||
/// Message struct/ID API version
|
||||
u16_l msg_api;
|
||||
/// Version of IPC shared
|
||||
u8_l ipc_shared_version;
|
||||
/// Number of host buffers available for Emb->App MSGs sending
|
||||
u8_l msge2a_buf_cnt;
|
||||
/// Number of host buffers available for Debug Messages sending
|
||||
u8_l dbgbuf_cnt;
|
||||
/// Number of host buffers available for Radar events handling
|
||||
u8_l radarbuf_cnt;
|
||||
/// Number of host buffers available for unsupported Rx vectors handling
|
||||
u8_l unsuprxvecbuf_cnt;
|
||||
/// Number of shared descriptors available for Data RX handling
|
||||
u8_l rxdesc_cnt;
|
||||
/// Number of host buffers available for Data Rx handling
|
||||
u8_l rxbuf_cnt;
|
||||
/// Number of descriptors in BK TX queue (power of 2, min 4, max 64)
|
||||
u8_l bk_txq;
|
||||
/// Number of descriptors in BE TX queue (power of 2, min 4, max 64)
|
||||
u8_l be_txq;
|
||||
/// Number of descriptors in VI TX queue (power of 2, min 4, max 64)
|
||||
u8_l vi_txq;
|
||||
/// Number of descriptors in VO TX queue (power of 2, min 4, max 64)
|
||||
u8_l vo_txq;
|
||||
/// Number of descriptors in BCN TX queue (power of 2, min 4, max 64)
|
||||
u8_l bcn_txq;
|
||||
};
|
||||
|
||||
/*
|
||||
* TYPE and STRUCT DEFINITIONS
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
// Indexes are defined in the MIB shared structure
|
||||
struct ipc_shared_env_tag
|
||||
{
|
||||
volatile struct compatibility_tag comp_info; //FW characteristics
|
||||
|
||||
volatile struct ipc_a2e_msg msg_a2e_buf; // room for MSG to be sent from App to Emb
|
||||
|
||||
// Fields for MSGs sending from Emb to App
|
||||
volatile struct ipc_e2a_msg msg_e2a_buf; // room to build the MSG to be DMA Xferred
|
||||
volatile struct dma_desc msg_dma_desc; // DMA descriptor for Emb->App MSGs Xfers
|
||||
volatile u32_l msg_e2a_hostbuf_addr [IPC_MSGE2A_BUF_CNT]; // buffers @ for DMA Xfers
|
||||
|
||||
// Fields for Debug MSGs sending from Emb to App
|
||||
volatile struct ipc_dbg_msg dbg_buf; // room to build the MSG to be DMA Xferred
|
||||
volatile struct dma_desc dbg_dma_desc; // DMA descriptor for Emb->App MSGs Xfers
|
||||
volatile u32_l dbg_hostbuf_addr [IPC_DBGBUF_CNT]; // buffers @ for MSGs DMA Xfers
|
||||
volatile u32_l la_dbginfo_addr; // Host buffer address for the debug information
|
||||
volatile u32_l pattern_addr;
|
||||
volatile u32_l radarbuf_hostbuf [IPC_RADARBUF_CNT]; // buffers @ for Radar Events
|
||||
volatile u32_l unsuprxvecbuf_hostbuf [IPC_UNSUPRXVECBUF_CNT]; // buffers @ for unsupported Rx vectors
|
||||
volatile struct txdesc_host txdesc0[CONFIG_USER_MAX][NX_TXDESC_CNT0];
|
||||
volatile struct txdesc_host txdesc1[CONFIG_USER_MAX][NX_TXDESC_CNT1];
|
||||
volatile struct txdesc_host txdesc2[CONFIG_USER_MAX][NX_TXDESC_CNT2];
|
||||
volatile struct txdesc_host txdesc3[CONFIG_USER_MAX][NX_TXDESC_CNT3];
|
||||
#if NX_TXQ_CNT == 5
|
||||
volatile struct txdesc_host txdesc4[1][NX_TXDESC_CNT4];
|
||||
#endif
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
// RX Descriptors Array
|
||||
volatile struct ipc_shared_rx_desc host_rxdesc[IPC_RXDESC_CNT];
|
||||
// RX Buffers Array
|
||||
volatile struct ipc_shared_rx_buf host_rxbuf[IPC_RXBUF_CNT];
|
||||
#else
|
||||
// buffers @ for Data Rx
|
||||
volatile u32_l host_rxbuf[IPC_RXBUF_CNT];
|
||||
#endif /* CONFIG_RWNX_FULLMAC */
|
||||
|
||||
u32_l buffered[NX_REMOTE_STA_MAX][TID_MAX];
|
||||
|
||||
volatile uint16_t trace_pattern;
|
||||
volatile uint32_t trace_start;
|
||||
volatile uint32_t trace_end;
|
||||
volatile uint32_t trace_size;
|
||||
volatile uint32_t trace_offset;
|
||||
volatile uint32_t trace_nb_compo;
|
||||
volatile uint32_t trace_offset_compo;
|
||||
};
|
||||
|
||||
extern struct ipc_shared_env_tag ipc_shared_env;
|
||||
|
||||
|
||||
/*
|
||||
* TYPE and STRUCT DEFINITIONS
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
// IRQs from app to emb
|
||||
/// Interrupts bits used for the TX descriptors of the AC queues
|
||||
#ifdef CONFIG_RWNX_MUMIMO_TX
|
||||
#ifdef CONFIG_RWNX_OLD_IPC
|
||||
#error "MU-MIMO cannot be compiled for old IPC"
|
||||
#endif
|
||||
/// Interrupts bits used
|
||||
#if CONFIG_USER_MAX > 3
|
||||
#define IPC_IRQ_A2E_USER_MSK 0xF
|
||||
#elif CONFIG_USER_MAX > 2
|
||||
#define IPC_IRQ_A2E_USER_MSK 0x7
|
||||
#else
|
||||
#define IPC_IRQ_A2E_USER_MSK 0x3
|
||||
#endif
|
||||
|
||||
/// Offset of the interrupts for AC0
|
||||
#define IPC_IRQ_A2E_AC0_OFT 8
|
||||
/// Mask of the interrupts for AC0
|
||||
#define IPC_IRQ_A2E_AC0_MSK (IPC_IRQ_A2E_USER_MSK << IPC_IRQ_A2E_AC0_OFT)
|
||||
/// Offset of the interrupts for AC1
|
||||
#define IPC_IRQ_A2E_AC1_OFT (IPC_IRQ_A2E_AC0_OFT + CONFIG_USER_MAX)
|
||||
/// Mask of the interrupts for AC1
|
||||
#define IPC_IRQ_A2E_AC1_MSK (IPC_IRQ_A2E_USER_MSK << IPC_IRQ_A2E_AC1_OFT)
|
||||
/// Offset of the interrupts for AC2
|
||||
#define IPC_IRQ_A2E_AC2_OFT (IPC_IRQ_A2E_AC1_OFT + CONFIG_USER_MAX)
|
||||
/// Mask of the interrupts for AC2
|
||||
#define IPC_IRQ_A2E_AC2_MSK (IPC_IRQ_A2E_USER_MSK << IPC_IRQ_A2E_AC2_OFT)
|
||||
/// Offset of the interrupts for AC3
|
||||
#define IPC_IRQ_A2E_AC3_OFT (IPC_IRQ_A2E_AC2_OFT + CONFIG_USER_MAX)
|
||||
/// Mask of the interrupts for AC3
|
||||
#define IPC_IRQ_A2E_AC3_MSK (IPC_IRQ_A2E_USER_MSK << IPC_IRQ_A2E_AC3_OFT)
|
||||
/// Offset of the interrupts for BCN
|
||||
#define IPC_IRQ_A2E_BCN_OFT (IPC_IRQ_A2E_AC3_OFT + CONFIG_USER_MAX)
|
||||
/// Mask of the interrupts for BCN
|
||||
#define IPC_IRQ_A2E_BCN_MSK CO_BIT(IPC_IRQ_A2E_BCN_OFT)
|
||||
|
||||
#define IPC_IRQ_A2E_AC_TXDESC (IPC_IRQ_A2E_AC0_MSK | IPC_IRQ_A2E_AC1_MSK | \
|
||||
IPC_IRQ_A2E_AC2_MSK | IPC_IRQ_A2E_AC3_MSK)
|
||||
|
||||
/// Interrupts bits used for the TX descriptors of the BCN queue
|
||||
#if NX_TXQ_CNT < 5
|
||||
#define IPC_IRQ_A2E_BCN_TXDESC 0
|
||||
#else
|
||||
#define IPC_IRQ_A2E_BCN_TXDESC (0x01 << IPC_IRQ_A2E_BCN_OFT)
|
||||
#endif
|
||||
|
||||
/// IPC TX descriptor interrupt mask
|
||||
#define IPC_IRQ_A2E_TXDESC (IPC_IRQ_A2E_AC_TXDESC | IPC_IRQ_A2E_BCN_TXDESC)
|
||||
#else
|
||||
/// IPC TX descriptor interrupt mask
|
||||
#define IPC_IRQ_A2E_TXDESC 0xFF00
|
||||
#endif
|
||||
|
||||
#define IPC_IRQ_A2E_TXDESC_FIRSTBIT (8)
|
||||
#define IPC_IRQ_A2E_RXBUF_BACK CO_BIT(5)
|
||||
#define IPC_IRQ_A2E_RXDESC_BACK CO_BIT(4)
|
||||
|
||||
#define IPC_IRQ_A2E_MSG CO_BIT(1)
|
||||
#define IPC_IRQ_A2E_DBG CO_BIT(0)
|
||||
|
||||
#define IPC_IRQ_A2E_ALL (IPC_IRQ_A2E_TXDESC|IPC_IRQ_A2E_MSG|IPC_IRQ_A2E_DBG)
|
||||
|
||||
// IRQs from emb to app
|
||||
#define IPC_IRQ_E2A_TXCFM_POS 7
|
||||
|
||||
#ifdef CONFIG_RWNX_MUMIMO_TX
|
||||
#ifdef CONFIG_RWNX_OLD_IPC
|
||||
#error "MU-MIMO cannot be compiled for old IPC"
|
||||
#endif
|
||||
/// Interrupts bits used
|
||||
#if CONFIG_USER_MAX > 3
|
||||
#define IPC_IRQ_E2A_USER_MSK 0xF
|
||||
#elif CONFIG_USER_MAX > 2
|
||||
#define IPC_IRQ_E2A_USER_MSK 0x7
|
||||
#else
|
||||
#define IPC_IRQ_E2A_USER_MSK 0x3
|
||||
#endif
|
||||
|
||||
/// Offset of the interrupts for AC0
|
||||
#define IPC_IRQ_E2A_AC0_OFT IPC_IRQ_E2A_TXCFM_POS
|
||||
/// Mask of the interrupts for AC0
|
||||
#define IPC_IRQ_E2A_AC0_MSK (IPC_IRQ_E2A_USER_MSK << IPC_IRQ_E2A_AC0_OFT)
|
||||
/// Offset of the interrupts for AC1
|
||||
#define IPC_IRQ_E2A_AC1_OFT (IPC_IRQ_E2A_AC0_OFT + CONFIG_USER_MAX)
|
||||
/// Mask of the interrupts for AC1
|
||||
#define IPC_IRQ_E2A_AC1_MSK (IPC_IRQ_E2A_USER_MSK << IPC_IRQ_E2A_AC1_OFT)
|
||||
/// Offset of the interrupts for AC2
|
||||
#define IPC_IRQ_E2A_AC2_OFT (IPC_IRQ_E2A_AC1_OFT + CONFIG_USER_MAX)
|
||||
/// Mask of the interrupts for AC2
|
||||
#define IPC_IRQ_E2A_AC2_MSK (IPC_IRQ_E2A_USER_MSK << IPC_IRQ_E2A_AC2_OFT)
|
||||
/// Offset of the interrupts for AC3
|
||||
#define IPC_IRQ_E2A_AC3_OFT (IPC_IRQ_E2A_AC2_OFT + CONFIG_USER_MAX)
|
||||
/// Mask of the interrupts for AC3
|
||||
#define IPC_IRQ_E2A_AC3_MSK (IPC_IRQ_E2A_USER_MSK << IPC_IRQ_E2A_AC3_OFT)
|
||||
/// Offset of the interrupts for BCN
|
||||
#define IPC_IRQ_E2A_BCN_OFT (IPC_IRQ_E2A_AC3_OFT + CONFIG_USER_MAX)
|
||||
/// Mask of the interrupts for BCN
|
||||
#define IPC_IRQ_E2A_BCN_MSK CO_BIT(IPC_IRQ_E2A_BCN_OFT)
|
||||
|
||||
#define IPC_IRQ_E2A_AC_TXCFM (IPC_IRQ_E2A_AC0_MSK | IPC_IRQ_E2A_AC1_MSK | \
|
||||
IPC_IRQ_E2A_AC2_MSK | IPC_IRQ_E2A_AC3_MSK)
|
||||
|
||||
/// Interrupts bits used for the TX descriptors of the BCN queue
|
||||
#if NX_TXQ_CNT < 5
|
||||
#define IPC_IRQ_E2A_BCN_TXCFM 0
|
||||
#else
|
||||
#define IPC_IRQ_E2A_BCN_TXCFM (0x01 << IPC_IRQ_E2A_BCN_OFT)
|
||||
#endif
|
||||
|
||||
/// IPC TX descriptor interrupt mask
|
||||
#define IPC_IRQ_E2A_TXCFM (IPC_IRQ_E2A_AC_TXCFM | IPC_IRQ_E2A_BCN_TXCFM)
|
||||
|
||||
#else
|
||||
|
||||
#define IPC_IRQ_E2A_TXCFM ((1 << NX_TXQ_CNT) - 1 ) << IPC_IRQ_E2A_TXCFM_POS
|
||||
|
||||
#endif /* CONFIG_RWNX_MUMIMO_TX */
|
||||
|
||||
#define IPC_IRQ_E2A_UNSUP_RX_VEC CO_BIT(7)
|
||||
#define IPC_IRQ_E2A_RADAR CO_BIT(6)
|
||||
#define IPC_IRQ_E2A_TBTT_SEC CO_BIT(5)
|
||||
#define IPC_IRQ_E2A_TBTT_PRIM CO_BIT(4)
|
||||
#define IPC_IRQ_E2A_RXDESC CO_BIT(3)
|
||||
#define IPC_IRQ_E2A_MSG_ACK CO_BIT(2)
|
||||
#define IPC_IRQ_E2A_MSG CO_BIT(1)
|
||||
#define IPC_IRQ_E2A_DBG CO_BIT(0)
|
||||
|
||||
#define IPC_IRQ_E2A_ALL ( IPC_IRQ_E2A_TXCFM \
|
||||
| IPC_IRQ_E2A_RXDESC \
|
||||
| IPC_IRQ_E2A_MSG_ACK \
|
||||
| IPC_IRQ_E2A_MSG \
|
||||
| IPC_IRQ_E2A_DBG \
|
||||
| IPC_IRQ_E2A_TBTT_PRIM \
|
||||
| IPC_IRQ_E2A_TBTT_SEC \
|
||||
| IPC_IRQ_E2A_RADAR \
|
||||
| IPC_IRQ_E2A_UNSUP_RX_VEC)
|
||||
|
||||
// FLAGS for RX desc
|
||||
#define IPC_RX_FORWARD CO_BIT(1)
|
||||
#define IPC_RX_INTRABSS CO_BIT(0)
|
||||
|
||||
|
||||
// IPC message TYPE
|
||||
enum
|
||||
{
|
||||
IPC_MSG_NONE = 0,
|
||||
IPC_MSG_WRAP,
|
||||
IPC_MSG_KMSG,
|
||||
|
||||
IPC_DBG_STRING,
|
||||
|
||||
};
|
||||
|
||||
#endif // _IPC_SHARED_H_
|
||||
|
||||
@@ -0,0 +1,588 @@
|
||||
/**
|
||||
****************************************************************************************
|
||||
*
|
||||
* @file lmac_mac_types.h
|
||||
*
|
||||
* @brief MAC related definitions.
|
||||
*
|
||||
* Adapted from mac_types.h to used lmac_types.h instead of standard types
|
||||
* eg: perl -pi -e '$_ =~ s/uint(\d{1,2})_t/u$1_l/g; \
|
||||
* $_ =~ s/int(\d{1,2})_t/s$1_l/g; \
|
||||
* $_ =~ s/CO_BIT/BIT/g;' lmac_mac.h
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2011-2019
|
||||
*
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef LMAC_MAC_H_
|
||||
#define LMAC_MAC_H_
|
||||
|
||||
#include "lmac_types.h"
|
||||
|
||||
/// Interface types
|
||||
enum mac_vif_type
|
||||
{
|
||||
/// ESS STA interface
|
||||
VIF_STA,
|
||||
/// IBSS STA interface
|
||||
VIF_IBSS,
|
||||
/// AP interface
|
||||
VIF_AP,
|
||||
/// Mesh Point interface
|
||||
VIF_MESH_POINT,
|
||||
/// Monitor interface
|
||||
VIF_MONITOR,
|
||||
/// Unknown type
|
||||
VIF_UNKNOWN
|
||||
};
|
||||
|
||||
/// MAC address length in bytes.
|
||||
#define MAC_ADDR_LEN 6
|
||||
|
||||
/// MAC address structure.
|
||||
struct mac_addr
|
||||
{
|
||||
/// Array of 16-bit words that make up the MAC address.
|
||||
u16_l array[MAC_ADDR_LEN/2];
|
||||
};
|
||||
|
||||
/// SSID maximum length.
|
||||
#define MAC_SSID_LEN 32
|
||||
|
||||
/// SSID.
|
||||
struct mac_ssid
|
||||
{
|
||||
/// Actual length of the SSID.
|
||||
u8_l length;
|
||||
/// Array containing the SSID name.
|
||||
u8_l array[MAC_SSID_LEN];
|
||||
};
|
||||
|
||||
/// BSS type
|
||||
enum mac_bss_type
|
||||
{
|
||||
INFRASTRUCTURE_MODE = 1,
|
||||
INDEPENDENT_BSS_MODE,
|
||||
ANY_BSS_MODE
|
||||
};
|
||||
|
||||
/// Channel Band
|
||||
enum mac_chan_band
|
||||
{
|
||||
/// 2.4GHz Band
|
||||
PHY_BAND_2G4,
|
||||
/// 5GHz band
|
||||
PHY_BAND_5G,
|
||||
/// Number of bands
|
||||
PHY_BAND_MAX,
|
||||
};
|
||||
|
||||
/// Operating Channel Bandwidth
|
||||
enum mac_chan_bandwidth
|
||||
{
|
||||
/// 20MHz BW
|
||||
PHY_CHNL_BW_20,
|
||||
/// 40MHz BW
|
||||
PHY_CHNL_BW_40,
|
||||
/// 80MHz BW
|
||||
PHY_CHNL_BW_80,
|
||||
/// 160MHz BW
|
||||
PHY_CHNL_BW_160,
|
||||
/// 80+80MHz BW
|
||||
PHY_CHNL_BW_80P80,
|
||||
/// Reserved BW
|
||||
PHY_CHNL_BW_OTHER,
|
||||
};
|
||||
|
||||
/// max number of channels in the 2.4 GHZ band
|
||||
#define MAC_DOMAINCHANNEL_24G_MAX 14
|
||||
|
||||
/// max number of channels in the 5 GHZ band
|
||||
#define MAC_DOMAINCHANNEL_5G_MAX 28
|
||||
|
||||
/// Channel Flag
|
||||
enum mac_chan_flags
|
||||
{
|
||||
/// Cannot initiate radiation on this channel
|
||||
CHAN_NO_IR = BIT(0),
|
||||
/// Channel is not allowed
|
||||
CHAN_DISABLED = BIT(1),
|
||||
/// Radar detection required on this channel
|
||||
CHAN_RADAR = BIT(2),
|
||||
};
|
||||
|
||||
/// Primary Channel definition
|
||||
struct mac_chan_def
|
||||
{
|
||||
/// Frequency of the channel (in MHz)
|
||||
u16_l freq;
|
||||
/// RF band (@ref mac_chan_band)
|
||||
u8_l band;
|
||||
/// Additional information (@ref mac_chan_flags)
|
||||
u8_l flags;
|
||||
/// Max transmit power allowed on this channel (dBm)
|
||||
s8_l tx_power;
|
||||
};
|
||||
|
||||
/// Operating Channel
|
||||
struct mac_chan_op
|
||||
{
|
||||
/// Band (@ref mac_chan_band)
|
||||
u8_l band;
|
||||
/// Channel type (@ref mac_chan_bandwidth)
|
||||
u8_l type;
|
||||
/// Frequency for Primary 20MHz channel (in MHz)
|
||||
u16_l prim20_freq;
|
||||
/// Frequency center of the contiguous channel or center of Primary 80+80 (in MHz)
|
||||
u16_l center1_freq;
|
||||
/// Frequency center of the non-contiguous secondary 80+80 (in MHz)
|
||||
u16_l center2_freq;
|
||||
/// Max transmit power allowed on this channel (dBm)
|
||||
s8_l tx_power;
|
||||
/// Additional information (@ref mac_chan_flags)
|
||||
u8_l flags;
|
||||
};
|
||||
|
||||
/// Cipher suites (order is important as it is used by MACHW)
|
||||
enum mac_cipher_suite
|
||||
{
|
||||
/// 00-0F-AC 1
|
||||
MAC_CIPHER_WEP40 = 0,
|
||||
/// 00-0F-AC 2
|
||||
MAC_CIPHER_TKIP = 1,
|
||||
/// 00-0F-AC 4
|
||||
MAC_CIPHER_CCMP = 2,
|
||||
/// 00-0F-AC 5
|
||||
MAC_CIPHER_WEP104 = 3,
|
||||
/// 00-14-72 1
|
||||
MAC_CIPHER_WPI_SMS4 = 4,
|
||||
/// 00-0F-AC 6 (aka AES_CMAC)
|
||||
MAC_CIPHER_BIP_CMAC_128 = 5,
|
||||
|
||||
// following cipher are not supported by MACHW
|
||||
/// 00-0F-AC 08
|
||||
MAC_CIPHER_GCMP_128,
|
||||
/// 00-0F-AC 09
|
||||
MAC_CIPHER_GCMP_256,
|
||||
/// 00-0F-AC 10
|
||||
MAC_CIPHER_CCMP_256,
|
||||
/// 00-0F-AC 11
|
||||
MAC_CIPHER_BIP_GMAC_128,
|
||||
/// 00-0F-AC 12
|
||||
MAC_CIPHER_BIP_GMAC_256,
|
||||
/// 00-0F-AC 13
|
||||
MAC_CIPHER_BIP_CMAC_256,
|
||||
|
||||
MAC_CIPHER_INVALID = 0xFF
|
||||
};
|
||||
|
||||
/// Authentication and Key Management suite
|
||||
enum mac_akm_suite
|
||||
{
|
||||
/// No security
|
||||
MAC_AKM_NONE,
|
||||
/// Pre RSN (WEP or WPA)
|
||||
MAC_AKM_PRE_RSN,
|
||||
/// 00-0F-AC 1
|
||||
MAC_AKM_8021X,
|
||||
/// 00-0F-AC 2
|
||||
MAC_AKM_PSK,
|
||||
/// 00-0F-AC 3
|
||||
MAC_AKM_FT_8021X,
|
||||
/// 00-0F-AC 4
|
||||
MAC_AKM_FT_PSK,
|
||||
/// 00-0F-AC 5
|
||||
MAC_AKM_8021X_SHA256,
|
||||
/// 00-0F-AC 6
|
||||
MAC_AKM_PSK_SHA256,
|
||||
/// 00-0F-AC 7
|
||||
MAC_AKM_TDLS,
|
||||
/// 00-0F-AC 8
|
||||
MAC_AKM_SAE,
|
||||
/// 00-0F-AC 9
|
||||
MAC_AKM_FT_OVER_SAE,
|
||||
/// 00-0F-AC 11
|
||||
MAC_AKM_8021X_SUITE_B,
|
||||
/// 00-0F-AC 12
|
||||
MAC_AKM_8021X_SUITE_B_192,
|
||||
/// 00-0F-AC 14
|
||||
MAC_AKM_FILS_SHA256,
|
||||
/// 00-0F-AC 15
|
||||
MAC_AKM_FILS_SHA384,
|
||||
/// 00-0F-AC 16
|
||||
MAC_AKM_FT_FILS_SHA256,
|
||||
/// 00-0F-AC 17
|
||||
MAC_AKM_FT_FILS_SHA384,
|
||||
/// 00-0F-AC 18
|
||||
MAC_AKM_OWE,
|
||||
|
||||
/// 00-14-72 1
|
||||
MAC_AKM_WAPI_CERT,
|
||||
/// 00-14-72 2
|
||||
MAC_AKM_WAPI_PSK,
|
||||
};
|
||||
|
||||
/// Scan result element, parsed from beacon or probe response frames.
|
||||
struct mac_scan_result
|
||||
{
|
||||
/// Scan result is valid
|
||||
bool valid_flag;
|
||||
/// Network BSSID.
|
||||
struct mac_addr bssid;
|
||||
/// Network name.
|
||||
struct mac_ssid ssid;
|
||||
/// Network type (@ref mac_bss_type).
|
||||
u16_l bsstype;
|
||||
/// Network channel.
|
||||
struct mac_chan_def *chan;
|
||||
/// Network beacon period (in TU).
|
||||
u16_l beacon_period;
|
||||
/// Capability information
|
||||
u16_l cap_info;
|
||||
/// Supported AKM (bit-field of @ref mac_akm_suite)
|
||||
u32_l akm;
|
||||
/// Group cipher (bit-field of @ref mac_cipher_suite)
|
||||
u16_l group_cipher;
|
||||
/// Group cipher (bit-field of @ref mac_cipher_suite)
|
||||
u16_l pairwise_cipher;
|
||||
/// RSSI of the scanned BSS (in dBm)
|
||||
s8_l rssi;
|
||||
///Multi-BSSID index (0 if this is the reference (i.e. transmitted) BSSID)
|
||||
u8_l mluti_bssid_index;
|
||||
///Maximum BSSID indicator
|
||||
u8_l max_bssid_indicator;
|
||||
};
|
||||
|
||||
/// Legacy rate 802.11 definitions
|
||||
enum mac_legacy_rates
|
||||
{
|
||||
/// DSSS/CCK 1Mbps
|
||||
MAC_RATE_1MBPS = 2,
|
||||
/// DSSS/CCK 2Mbps
|
||||
MAC_RATE_2MBPS = 4,
|
||||
/// DSSS/CCK 5.5Mbps
|
||||
MAC_RATE_5_5MBPS = 11,
|
||||
/// OFDM 6Mbps
|
||||
MAC_RATE_6MBPS = 12,
|
||||
/// OFDM 9Mbps
|
||||
MAC_RATE_9MBPS = 18,
|
||||
/// DSSS/CCK 11Mbps
|
||||
MAC_RATE_11MBPS = 22,
|
||||
/// OFDM 12Mbps
|
||||
MAC_RATE_12MBPS = 24,
|
||||
/// OFDM 18Mbps
|
||||
MAC_RATE_18MBPS = 36,
|
||||
/// OFDM 24Mbps
|
||||
MAC_RATE_24MBPS = 48,
|
||||
/// OFDM 36Mbps
|
||||
MAC_RATE_36MBPS = 72,
|
||||
/// OFDM 48Mbps
|
||||
MAC_RATE_48MBPS = 96,
|
||||
/// OFDM 54Mbps
|
||||
MAC_RATE_54MBPS = 108
|
||||
};
|
||||
|
||||
/// BSS Membership Selector definitions
|
||||
enum mac_bss_membership
|
||||
{
|
||||
/// HT PHY
|
||||
MAC_BSS_MEMBERSHIP_HT_PHY = 127,
|
||||
/// VHT PHY
|
||||
MAC_BSS_MEMBERSHIP_VHT_PHY = 126,
|
||||
};
|
||||
|
||||
/// MAC rateset maximum length
|
||||
#define MAC_RATESET_LEN 12
|
||||
|
||||
/// Structure containing the legacy rateset of a station
|
||||
struct mac_rateset
|
||||
{
|
||||
/// Number of legacy rates supported
|
||||
u8_l length;
|
||||
/// Array of legacy rates
|
||||
u8_l array[MAC_RATESET_LEN];
|
||||
};
|
||||
|
||||
/// MAC Security Key maximum length
|
||||
#define MAC_SEC_KEY_LEN 32 // TKIP keys 256 bits (max length) with MIC keys
|
||||
|
||||
/// Structure defining a security key
|
||||
struct mac_sec_key
|
||||
{
|
||||
/// Key material length
|
||||
u8_l length;
|
||||
/// Key material
|
||||
u32_l array[MAC_SEC_KEY_LEN/4];
|
||||
};
|
||||
|
||||
/// Access Category enumeration
|
||||
enum mac_ac
|
||||
{
|
||||
/// Background
|
||||
AC_BK = 0,
|
||||
/// Best-effort
|
||||
AC_BE,
|
||||
/// Video
|
||||
AC_VI,
|
||||
/// Voice
|
||||
AC_VO,
|
||||
/// Number of access categories
|
||||
AC_MAX
|
||||
};
|
||||
|
||||
/// Traffic ID enumeration
|
||||
enum mac_tid
|
||||
{
|
||||
/// TID_0. Mapped to @ref AC_BE as per 802.11 standard.
|
||||
TID_0,
|
||||
/// TID_1. Mapped to @ref AC_BK as per 802.11 standard.
|
||||
TID_1,
|
||||
/// TID_2. Mapped to @ref AC_BK as per 802.11 standard.
|
||||
TID_2,
|
||||
/// TID_3. Mapped to @ref AC_BE as per 802.11 standard.
|
||||
TID_3,
|
||||
/// TID_4. Mapped to @ref AC_VI as per 802.11 standard.
|
||||
TID_4,
|
||||
/// TID_5. Mapped to @ref AC_VI as per 802.11 standard.
|
||||
TID_5,
|
||||
/// TID_6. Mapped to @ref AC_VO as per 802.11 standard.
|
||||
TID_6,
|
||||
/// TID_7. Mapped to @ref AC_VO as per 802.11 standard.
|
||||
TID_7,
|
||||
/// Non standard Management TID used internally
|
||||
TID_MGT,
|
||||
/// Number of TID supported
|
||||
TID_MAX
|
||||
};
|
||||
|
||||
/// MCS bitfield maximum size (in bytes)
|
||||
#define MAX_MCS_LEN 16 // 16 * 8 = 128
|
||||
|
||||
/// MAC HT capability information element
|
||||
struct mac_htcapability
|
||||
{
|
||||
/// HT capability information
|
||||
u16_l ht_capa_info;
|
||||
/// A-MPDU parameters
|
||||
u8_l a_mpdu_param;
|
||||
/// Supported MCS
|
||||
u8_l mcs_rate[MAX_MCS_LEN];
|
||||
/// HT extended capability information
|
||||
u16_l ht_extended_capa;
|
||||
/// Beamforming capability information
|
||||
u32_l tx_beamforming_capa;
|
||||
/// Antenna selection capability information
|
||||
u8_l asel_capa;
|
||||
};
|
||||
|
||||
/// MAC VHT capability information element
|
||||
struct mac_vhtcapability
|
||||
{
|
||||
/// VHT capability information
|
||||
u32_l vht_capa_info;
|
||||
/// RX MCS map
|
||||
u16_l rx_mcs_map;
|
||||
/// RX highest data rate
|
||||
u16_l rx_highest;
|
||||
/// TX MCS map
|
||||
u16_l tx_mcs_map;
|
||||
/// TX highest data rate
|
||||
u16_l tx_highest;
|
||||
};
|
||||
|
||||
/// Length (in bytes) of the MAC HE capability field
|
||||
#define MAC_HE_MAC_CAPA_LEN 6
|
||||
/// Length (in bytes) of the PHY HE capability field
|
||||
#define MAC_HE_PHY_CAPA_LEN 11
|
||||
/// Maximum length (in bytes) of the PPE threshold data
|
||||
#define MAC_HE_PPE_THRES_MAX_LEN 25
|
||||
|
||||
/// Structure listing the per-NSS, per-BW supported MCS combinations
|
||||
struct mac_he_mcs_nss_supp
|
||||
{
|
||||
/// per-NSS supported MCS in RX, for BW <= 80MHz
|
||||
u16_l rx_mcs_80;
|
||||
/// per-NSS supported MCS in TX, for BW <= 80MHz
|
||||
u16_l tx_mcs_80;
|
||||
/// per-NSS supported MCS in RX, for BW = 160MHz
|
||||
u16_l rx_mcs_160;
|
||||
/// per-NSS supported MCS in TX, for BW = 160MHz
|
||||
u16_l tx_mcs_160;
|
||||
/// per-NSS supported MCS in RX, for BW = 80+80MHz
|
||||
u16_l rx_mcs_80p80;
|
||||
/// per-NSS supported MCS in TX, for BW = 80+80MHz
|
||||
u16_l tx_mcs_80p80;
|
||||
};
|
||||
|
||||
/// MAC HE capability information element
|
||||
struct mac_hecapability
|
||||
{
|
||||
/// MAC HE capabilities
|
||||
u8_l mac_cap_info[MAC_HE_MAC_CAPA_LEN];
|
||||
/// PHY HE capabilities
|
||||
u8_l phy_cap_info[MAC_HE_PHY_CAPA_LEN];
|
||||
/// Supported MCS combinations
|
||||
struct mac_he_mcs_nss_supp mcs_supp;
|
||||
/// PPE Thresholds data
|
||||
u8_l ppe_thres[MAC_HE_PPE_THRES_MAX_LEN];
|
||||
};
|
||||
|
||||
/// Station flags
|
||||
enum mac_sta_flags
|
||||
{
|
||||
/// Bit indicating that a STA has QoS (WMM) capability
|
||||
STA_QOS_CAPA = BIT(0),
|
||||
/// Bit indicating that a STA has HT capability
|
||||
STA_HT_CAPA = BIT(1),
|
||||
/// Bit indicating that a STA has VHT capability
|
||||
STA_VHT_CAPA = BIT(2),
|
||||
/// Bit indicating that a STA has MFP capability
|
||||
STA_MFP_CAPA = BIT(3),
|
||||
/// Bit indicating that the STA included the Operation Notification IE
|
||||
STA_OPMOD_NOTIF = BIT(4),
|
||||
/// Bit indicating that a STA has HE capability
|
||||
STA_HE_CAPA = BIT(5),
|
||||
};
|
||||
|
||||
/// Connection flags
|
||||
enum mac_connection_flags
|
||||
{
|
||||
/// Flag indicating whether the control port is controlled by host or not
|
||||
CONTROL_PORT_HOST = BIT(0),
|
||||
/// Flag indicating whether the control port frame shall be sent unencrypted
|
||||
CONTROL_PORT_NO_ENC = BIT(1),
|
||||
/// Flag indicating whether HT and VHT shall be disabled or not
|
||||
DISABLE_HT = BIT(2),
|
||||
/// Flag indicating whether WPA or WPA2 authentication is in use
|
||||
WPA_WPA2_IN_USE = BIT(3),
|
||||
/// Flag indicating whether MFP is in use
|
||||
MFP_IN_USE = BIT(4),
|
||||
// Flag indicating Roam
|
||||
REASSOCIATION = BIT(5),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_HE_FOR_OLD_KERNEL
|
||||
#define IEEE80211_HE_MAC_CAP2_ALL_ACK 0x02
|
||||
#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G 0x02
|
||||
#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G 0x04
|
||||
#define IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD 0x20
|
||||
#define IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US 0x40
|
||||
#define IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS 0x80
|
||||
#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_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
|
||||
#define IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA 0x40
|
||||
#define IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE 0x01
|
||||
#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4 0x0c
|
||||
#define IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK 0x40
|
||||
#define IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK 0x80
|
||||
#define IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU 0x01
|
||||
#define IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU 0x02
|
||||
#define IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB 0x04
|
||||
#define IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB 0x08
|
||||
#define IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT 0x80
|
||||
#define IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO 0x40
|
||||
#define IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI 0x04
|
||||
#define IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G 0x02
|
||||
#define IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB 0x10
|
||||
#define IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB 0x20
|
||||
|
||||
struct ieee80211_he_cap_elem {
|
||||
u8 mac_cap_info[6];
|
||||
u8 phy_cap_info[11];
|
||||
} __packed;
|
||||
|
||||
struct ieee80211_he_mcs_nss_supp {
|
||||
__le16 rx_mcs_80;
|
||||
__le16 tx_mcs_80;
|
||||
__le16 rx_mcs_160;
|
||||
__le16 tx_mcs_160;
|
||||
__le16 rx_mcs_80p80;
|
||||
__le16 tx_mcs_80p80;
|
||||
} __packed;
|
||||
|
||||
#define IEEE80211_HE_PPE_THRES_MAX_LEN 25
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
|
||||
#define WLAN_EID_EXTENSION 255
|
||||
/* Element ID Extensions for Element ID 255 */
|
||||
|
||||
enum ieee80211_eid_ext {
|
||||
WLAN_EID_EXT_ASSOC_DELAY_INFO = 1,
|
||||
WLAN_EID_EXT_FILS_REQ_PARAMS = 2,
|
||||
WLAN_EID_EXT_FILS_KEY_CONFIRM = 3,
|
||||
WLAN_EID_EXT_FILS_SESSION = 4,
|
||||
WLAN_EID_EXT_FILS_HLP_CONTAINER = 5,
|
||||
WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN = 6,
|
||||
WLAN_EID_EXT_KEY_DELIVERY = 7,
|
||||
WLAN_EID_EXT_FILS_WRAPPED_DATA = 8,
|
||||
WLAN_EID_EXT_FILS_PUBLIC_KEY = 12,
|
||||
WLAN_EID_EXT_FILS_NONCE = 13,
|
||||
WLAN_EID_EXT_FUTURE_CHAN_GUIDANCE = 14,
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
|
||||
#define WLAN_EID_EXT_HE_CAPABILITY 35
|
||||
#define WLAN_EID_EXT_HE_OPERATION 36
|
||||
#define WLAN_EID_EXT_UORA 37
|
||||
#define WLAN_EID_EXT_HE_MU_EDCA 38
|
||||
#define WLAN_EID_EXT_HE_SPR 39
|
||||
#define WLAN_EID_EXT_NDP_FEEDBACK_REPORT_PARAMSET 41
|
||||
#define WLAN_EID_EXT_BSS_COLOR_CHG_ANN 42
|
||||
#define WLAN_EID_EXT_QUIET_TIME_PERIOD_SETUP 43
|
||||
#define WLAN_EID_EXT_ESS_REPORT 45
|
||||
#define WLAN_EID_EXT_OPS 46
|
||||
#define WLAN_EID_EXT_HE_BSS_LOAD 47
|
||||
#define WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME 52
|
||||
#define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55
|
||||
#define WLAN_EID_EXT_NON_INHERITANCE 56
|
||||
#define WLAN_EID_EXT_KNOWN_BSSID 57
|
||||
#define WLAN_EID_EXT_SHORT_SSID_LIST 58
|
||||
#define WLAN_EID_EXT_HE_6GHZ_CAPA 59
|
||||
#define WLAN_EID_EXT_UL_MU_POWER_CAPA 60
|
||||
#define WLAN_EID_EXT_EHT_OPERATION 106
|
||||
#define WLAN_EID_EXT_EHT_MULTI_LINK 107
|
||||
#define WLAN_EID_EXT_EHT_CAPABILITY 108
|
||||
|
||||
#endif
|
||||
|
||||
struct ieee80211_sta_he_cap {
|
||||
bool has_he;
|
||||
struct ieee80211_he_cap_elem he_cap_elem;
|
||||
struct ieee80211_he_mcs_nss_supp he_mcs_nss_supp;
|
||||
u8 ppe_thres[IEEE80211_HE_PPE_THRES_MAX_LEN];
|
||||
};
|
||||
|
||||
struct ieee80211_sband_iftype_data {
|
||||
u16 types_mask;
|
||||
struct ieee80211_sta_he_cap he_cap;
|
||||
};
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL)
|
||||
struct ieee80211_vht_mcs_info {
|
||||
__le16 rx_mcs_map;
|
||||
__le16 rx_highest;
|
||||
__le16 tx_mcs_map;
|
||||
__le16 tx_highest;
|
||||
} __packed;
|
||||
|
||||
struct ieee80211_vht_cap {
|
||||
__le32 vht_cap_info;
|
||||
struct ieee80211_vht_mcs_info supp_mcs;
|
||||
};
|
||||
#define WLAN_EID_VHT_CAPABILITY 191
|
||||
|
||||
struct ieee80211_sta_vht_cap {
|
||||
bool vht_supported;
|
||||
u32 cap; /* use IEEE80211_VHT_CAP_ */
|
||||
struct ieee80211_vht_mcs_info vht_mcs;
|
||||
};
|
||||
#endif
|
||||
#endif // LMAC_MAC_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
****************************************************************************************
|
||||
*
|
||||
* @file co_types.h
|
||||
*
|
||||
* @brief This file replaces the need to include stdint or stdbool typical headers,
|
||||
* which may not be available in all toolchains, and adds new types
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2009-2019
|
||||
*
|
||||
* $Rev: $
|
||||
*
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _LMAC_INT_H_
|
||||
#define _LMAC_INT_H_
|
||||
|
||||
|
||||
/**
|
||||
****************************************************************************************
|
||||
* @addtogroup CO_INT
|
||||
* @ingroup COMMON
|
||||
* @brief Common integer standard types (removes use of stdint)
|
||||
*
|
||||
* @{
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* DEFINES
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/types.h>
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)
|
||||
#include <linux/bits.h>
|
||||
#else
|
||||
#include <linux/bitops.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RWNX_TL4
|
||||
typedef uint16_t u8_l;
|
||||
typedef int16_t s8_l;
|
||||
typedef uint16_t bool_l;
|
||||
#else
|
||||
typedef uint8_t u8_l;
|
||||
typedef int8_t s8_l;
|
||||
typedef bool bool_l;
|
||||
#endif
|
||||
typedef uint16_t u16_l;
|
||||
typedef int16_t s16_l;
|
||||
typedef uint32_t u32_l;
|
||||
typedef int32_t s32_l;
|
||||
typedef uint64_t u64_l;
|
||||
|
||||
|
||||
|
||||
/// @} CO_INT
|
||||
#endif // _LMAC_INT_H_
|
||||
@@ -0,0 +1,161 @@
|
||||
#include <linux/memory.h>
|
||||
#include "md5.h"
|
||||
|
||||
unsigned char PADDING[]={0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
|
||||
void MD5Init(MD5_CTX *context)
|
||||
{
|
||||
context->count[0] = 0;
|
||||
context->count[1] = 0;
|
||||
context->state[0] = 0x67452301;
|
||||
context->state[1] = 0xEFCDAB89;
|
||||
context->state[2] = 0x98BADCFE;
|
||||
context->state[3] = 0x10325476;
|
||||
}
|
||||
void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen)
|
||||
{
|
||||
unsigned int i = 0,index = 0,partlen = 0;
|
||||
index = (context->count[0] >> 3) & 0x3F;
|
||||
partlen = 64 - index;
|
||||
context->count[0] += inputlen << 3;
|
||||
if(context->count[0] < (inputlen << 3))
|
||||
context->count[1]++;
|
||||
context->count[1] += inputlen >> 29;
|
||||
|
||||
if(inputlen >= partlen)
|
||||
{
|
||||
memcpy(&context->buffer[index],input,partlen);
|
||||
MD5Transform(context->state,context->buffer);
|
||||
for(i = partlen;i+64 <= inputlen;i+=64)
|
||||
MD5Transform(context->state,&input[i]);
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 0;
|
||||
}
|
||||
memcpy(&context->buffer[index],&input[i],inputlen-i);
|
||||
}
|
||||
void MD5Final(MD5_CTX *context,unsigned char digest[16])
|
||||
{
|
||||
unsigned int index = 0,padlen = 0;
|
||||
unsigned char bits[8];
|
||||
index = (context->count[0] >> 3) & 0x3F;
|
||||
padlen = (index < 56)?(56-index):(120-index);
|
||||
MD5Encode(bits,context->count,8);
|
||||
MD5Update(context,PADDING,padlen);
|
||||
MD5Update(context,bits,8);
|
||||
MD5Encode(digest,context->state,16);
|
||||
}
|
||||
void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len)
|
||||
{
|
||||
unsigned int i = 0,j = 0;
|
||||
while(j < len)
|
||||
{
|
||||
output[j] = input[i] & 0xFF;
|
||||
output[j+1] = (input[i] >> 8) & 0xFF;
|
||||
output[j+2] = (input[i] >> 16) & 0xFF;
|
||||
output[j+3] = (input[i] >> 24) & 0xFF;
|
||||
i++;
|
||||
j+=4;
|
||||
}
|
||||
}
|
||||
void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len)
|
||||
{
|
||||
unsigned int i = 0,j = 0;
|
||||
while(j < len)
|
||||
{
|
||||
output[i] = (input[j]) |
|
||||
(input[j+1] << 8) |
|
||||
(input[j+2] << 16) |
|
||||
(input[j+3] << 24);
|
||||
i++;
|
||||
j+=4;
|
||||
}
|
||||
}
|
||||
void MD5Transform(unsigned int state[4],unsigned char block[64])
|
||||
{
|
||||
unsigned int a = state[0];
|
||||
unsigned int b = state[1];
|
||||
unsigned int c = state[2];
|
||||
unsigned int d = state[3];
|
||||
unsigned int x[64];
|
||||
MD5Decode(x,block,64);
|
||||
FF(a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */
|
||||
FF(d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */
|
||||
FF(c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */
|
||||
FF(b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */
|
||||
FF(a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */
|
||||
FF(d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */
|
||||
FF(c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */
|
||||
FF(b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */
|
||||
FF(a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */
|
||||
FF(d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */
|
||||
FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */
|
||||
FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */
|
||||
FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */
|
||||
FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */
|
||||
FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */
|
||||
FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */
|
||||
|
||||
/* Round 2 */
|
||||
GG(a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */
|
||||
GG(d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */
|
||||
GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */
|
||||
GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */
|
||||
GG(a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */
|
||||
GG(d, a, b, c, x[10], 9, 0x2441453); /* 22 */
|
||||
GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */
|
||||
GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */
|
||||
GG(a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */
|
||||
GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */
|
||||
GG(c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */
|
||||
GG(b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */
|
||||
GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */
|
||||
GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */
|
||||
GG(c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */
|
||||
GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */
|
||||
|
||||
/* Round 3 */
|
||||
HH(a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */
|
||||
HH(d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */
|
||||
HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */
|
||||
HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */
|
||||
HH(a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */
|
||||
HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */
|
||||
HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */
|
||||
HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */
|
||||
HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */
|
||||
HH(d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */
|
||||
HH(c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */
|
||||
HH(b, c, d, a, x[ 6], 23, 0x4881d05); /* 44 */
|
||||
HH(a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */
|
||||
HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */
|
||||
HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */
|
||||
HH(b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */
|
||||
|
||||
/* Round 4 */
|
||||
II(a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */
|
||||
II(d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */
|
||||
II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */
|
||||
II(b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */
|
||||
II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */
|
||||
II(d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */
|
||||
II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */
|
||||
II(b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */
|
||||
II(a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */
|
||||
II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */
|
||||
II(c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */
|
||||
II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */
|
||||
II(a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */
|
||||
II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */
|
||||
II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */
|
||||
II(b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef MD5_H
|
||||
#define MD5_H
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int count[2];
|
||||
unsigned int state[4];
|
||||
unsigned char buffer[64];
|
||||
}MD5_CTX;
|
||||
|
||||
|
||||
#define F(x,y,z) ((x & y) | (~x & z))
|
||||
#define G(x,y,z) ((x & z) | (y & ~z))
|
||||
#define H(x,y,z) (x^y^z)
|
||||
#define I(x,y,z) (y ^ (x | ~z))
|
||||
#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n)))
|
||||
#define FF(a,b,c,d,x,s,ac) \
|
||||
{ \
|
||||
a += F(b,c,d) + x + ac; \
|
||||
a = ROTATE_LEFT(a,s); \
|
||||
a += b; \
|
||||
}
|
||||
#define GG(a,b,c,d,x,s,ac) \
|
||||
{ \
|
||||
a += G(b,c,d) + x + ac; \
|
||||
a = ROTATE_LEFT(a,s); \
|
||||
a += b; \
|
||||
}
|
||||
#define HH(a,b,c,d,x,s,ac) \
|
||||
{ \
|
||||
a += H(b,c,d) + x + ac; \
|
||||
a = ROTATE_LEFT(a,s); \
|
||||
a += b; \
|
||||
}
|
||||
#define II(a,b,c,d,x,s,ac) \
|
||||
{ \
|
||||
a += I(b,c,d) + x + ac; \
|
||||
a = ROTATE_LEFT(a,s); \
|
||||
a += b; \
|
||||
}
|
||||
void MD5Init(MD5_CTX *context);
|
||||
void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen);
|
||||
void MD5Final(MD5_CTX *context,unsigned char digest[16]);
|
||||
void MD5Transform(unsigned int state[4],unsigned char block[64]);
|
||||
void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len);
|
||||
void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file reg_access.h
|
||||
*
|
||||
* @brief Definitions and macros for MAC HW and platform register accesses
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2011-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef REG_ACCESS_H_
|
||||
#define REG_ACCESS_H_
|
||||
|
||||
/*****************************************************************************
|
||||
* Addresses within RWNX_ADDR_CPU
|
||||
*****************************************************************************/
|
||||
#define RAM_LMAC_FW_ADDR 0x00150000
|
||||
|
||||
#define ROM_FMAC_FW_ADDR 0x00010000
|
||||
#define RAM_FMAC_FW_ADDR 0x00120000
|
||||
#define ROM_FMAC_PATCH_ADDR 0x00180000
|
||||
#ifdef CONFIG_DPD
|
||||
#define ROM_FMAC_CALIB_ADDR 0x00130000
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Addresses within RWNX_ADDR_SYSTEM
|
||||
*****************************************************************************/
|
||||
/* Shard RAM */
|
||||
#define SHARED_RAM_START_ADDR 0x00000000
|
||||
|
||||
/* IPC registers */
|
||||
#define IPC_REG_BASE_ADDR 0x00800000
|
||||
|
||||
/* System Controller Registers */
|
||||
#define SYSCTRL_SIGNATURE_ADDR 0x00900000
|
||||
// old diag register name
|
||||
#define SYSCTRL_DIAG_CONF_ADDR 0x00900068
|
||||
#define SYSCTRL_PHYDIAG_CONF_ADDR 0x00900074
|
||||
#define SYSCTRL_RIUDIAG_CONF_ADDR 0x00900078
|
||||
// new diag register name
|
||||
#define SYSCTRL_DIAG_CONF0 0x00900064
|
||||
#define SYSCTRL_DIAG_CONF1 0x00900068
|
||||
#define SYSCTRL_DIAG_CONF2 0x00900074
|
||||
#define SYSCTRL_DIAG_CONF3 0x00900078
|
||||
#define SYSCTRL_MISC_CNTL_ADDR 0x009000E0
|
||||
#define BOOTROM_ENABLE BIT(4)
|
||||
#define FPGA_B_RESET BIT(1)
|
||||
#define SOFT_RESET BIT(0)
|
||||
|
||||
/* MAC platform */
|
||||
#define NXMAC_VERSION_1_ADDR 0x00B00004
|
||||
#define NXMAC_MU_MIMO_TX_BIT BIT(19)
|
||||
#define NXMAC_BFMER_BIT BIT(18)
|
||||
#define NXMAC_BFMEE_BIT BIT(17)
|
||||
#define NXMAC_MAC_80211MH_FORMAT_BIT BIT(16)
|
||||
#define NXMAC_COEX_BIT BIT(14)
|
||||
#define NXMAC_WAPI_BIT BIT(13)
|
||||
#define NXMAC_TPC_BIT BIT(12)
|
||||
#define NXMAC_VHT_BIT BIT(11)
|
||||
#define NXMAC_HT_BIT BIT(10)
|
||||
#define NXMAC_RCE_BIT BIT(8)
|
||||
#define NXMAC_CCMP_BIT BIT(7)
|
||||
#define NXMAC_TKIP_BIT BIT(6)
|
||||
#define NXMAC_WEP_BIT BIT(5)
|
||||
#define NXMAC_SECURITY_BIT BIT(4)
|
||||
#define NXMAC_SME_BIT BIT(3)
|
||||
#define NXMAC_HCCA_BIT BIT(2)
|
||||
#define NXMAC_EDCA_BIT BIT(1)
|
||||
#define NXMAC_QOS_BIT BIT(0)
|
||||
|
||||
#define NXMAC_RX_CNTRL_ADDR 0x00B00060
|
||||
#define NXMAC_EN_DUPLICATE_DETECTION_BIT BIT(31)
|
||||
#define NXMAC_ACCEPT_UNKNOWN_BIT BIT(30)
|
||||
#define NXMAC_ACCEPT_OTHER_DATA_FRAMES_BIT BIT(29)
|
||||
#define NXMAC_ACCEPT_QO_S_NULL_BIT BIT(28)
|
||||
#define NXMAC_ACCEPT_QCFWO_DATA_BIT BIT(27)
|
||||
#define NXMAC_ACCEPT_Q_DATA_BIT BIT(26)
|
||||
#define NXMAC_ACCEPT_CFWO_DATA_BIT BIT(25)
|
||||
#define NXMAC_ACCEPT_DATA_BIT BIT(24)
|
||||
#define NXMAC_ACCEPT_OTHER_CNTRL_FRAMES_BIT BIT(23)
|
||||
#define NXMAC_ACCEPT_CF_END_BIT BIT(22)
|
||||
#define NXMAC_ACCEPT_ACK_BIT BIT(21)
|
||||
#define NXMAC_ACCEPT_CTS_BIT BIT(20)
|
||||
#define NXMAC_ACCEPT_RTS_BIT BIT(19)
|
||||
#define NXMAC_ACCEPT_PS_POLL_BIT BIT(18)
|
||||
#define NXMAC_ACCEPT_BA_BIT BIT(17)
|
||||
#define NXMAC_ACCEPT_BAR_BIT BIT(16)
|
||||
#define NXMAC_ACCEPT_OTHER_MGMT_FRAMES_BIT BIT(15)
|
||||
#define NXMAC_ACCEPT_BFMEE_FRAMES_BIT BIT(14)
|
||||
#define NXMAC_ACCEPT_ALL_BEACON_BIT BIT(13)
|
||||
#define NXMAC_ACCEPT_NOT_EXPECTED_BA_BIT BIT(12)
|
||||
#define NXMAC_ACCEPT_DECRYPT_ERROR_FRAMES_BIT BIT(11)
|
||||
#define NXMAC_ACCEPT_BEACON_BIT BIT(10)
|
||||
#define NXMAC_ACCEPT_PROBE_RESP_BIT BIT(9)
|
||||
#define NXMAC_ACCEPT_PROBE_REQ_BIT BIT(8)
|
||||
#define NXMAC_ACCEPT_MY_UNICAST_BIT BIT(7)
|
||||
#define NXMAC_ACCEPT_UNICAST_BIT BIT(6)
|
||||
#define NXMAC_ACCEPT_ERROR_FRAMES_BIT BIT(5)
|
||||
#define NXMAC_ACCEPT_OTHER_BSSID_BIT BIT(4)
|
||||
#define NXMAC_ACCEPT_BROADCAST_BIT BIT(3)
|
||||
#define NXMAC_ACCEPT_MULTICAST_BIT BIT(2)
|
||||
#define NXMAC_DONT_DECRYPT_BIT BIT(1)
|
||||
#define NXMAC_EXC_UNENCRYPTED_BIT BIT(0)
|
||||
|
||||
#define NXMAC_DEBUG_PORT_SEL_ADDR 0x00B00510
|
||||
#define NXMAC_SW_SET_PROFILING_ADDR 0x00B08564
|
||||
#define NXMAC_SW_CLEAR_PROFILING_ADDR 0x00B08568
|
||||
|
||||
/* Modem Status */
|
||||
#define MDM_HDMCONFIG_ADDR 0x00C00000
|
||||
|
||||
/* Clock gating configuration */
|
||||
#define MDM_MEMCLKCTRL0_ADDR 0x00C00848
|
||||
#define MDM_CLKGATEFCTRL0_ADDR 0x00C00874
|
||||
#define CRM_CLKGATEFCTRL0_ADDR 0x00940010
|
||||
|
||||
/* AGC (trident) */
|
||||
#define AGC_RWNXAGCCNTL_ADDR 0x00C02060
|
||||
|
||||
/* LDPC RAM*/
|
||||
#define PHY_LDPC_RAM_ADDR 0x00C09000
|
||||
|
||||
/* FCU (elma )*/
|
||||
#define FCU_RWNXFCAGCCNTL_ADDR 0x00C09034
|
||||
|
||||
/* AGC RAM */
|
||||
#define PHY_AGC_UCODE_ADDR 0x00C0A000
|
||||
|
||||
/* RIU */
|
||||
#define RIU_RWNXVERSION_ADDR 0x00C0B000
|
||||
#define RIU_RWNXDYNAMICCONFIG_ADDR 0x00C0B008
|
||||
#define RIU_AGCMEMBISTSTAT_ADDR 0x00C0B238
|
||||
#define RIU_AGCMEMSIGNATURESTAT_ADDR 0x00C0B23C
|
||||
#define RIU_RWNXAGCCNTL_ADDR 0x00C0B390
|
||||
|
||||
/* FCU RAM */
|
||||
#define PHY_FCU_UCODE_ADDR 0x00C0E000
|
||||
|
||||
/* RF ITF */
|
||||
#define FPGAB_MPIF_SEL_ADDR 0x00C10030
|
||||
#define RF_V6_DIAGPORT_CONF1_ADDR 0x00C10010
|
||||
#define RF_v6_PHYDIAG_CONF1_ADDR 0x00C10018
|
||||
|
||||
#define RF_V7_DIAGPORT_CONF1_ADDR 0x00F10010
|
||||
#define RF_v7_PHYDIAG_CONF1_ADDR 0x00F10018
|
||||
|
||||
/*****************************************************************************
|
||||
* Macros for generated register files
|
||||
*****************************************************************************/
|
||||
/* Macros for IPC registers access (used in reg_ipc_app.h) */
|
||||
#define REG_IPC_APP_RD(env, INDEX) \
|
||||
(*(volatile u32*)((u8*)env + IPC_REG_BASE_ADDR + 4*(INDEX)))
|
||||
|
||||
#define REG_IPC_APP_WR(env, INDEX, value) \
|
||||
(*(volatile u32*)((u8*)env + IPC_REG_BASE_ADDR + 4*(INDEX)) = value)
|
||||
|
||||
#endif /* REG_ACCESS_H_ */
|
||||
@@ -0,0 +1,299 @@
|
||||
/**
|
||||
****************************************************************************************
|
||||
*
|
||||
* @file rwnx_ipc_app.h
|
||||
*
|
||||
* @brief IPC module register definitions
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2011-2019
|
||||
*
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _REG_IPC_APP_H_
|
||||
#define _REG_IPC_APP_H_
|
||||
|
||||
#ifndef __KERNEL__
|
||||
#include <stdint.h>
|
||||
#include "arch.h"
|
||||
#else
|
||||
#include "ipc_compat.h"
|
||||
#endif
|
||||
#include "reg_access.h"
|
||||
|
||||
#define REG_IPC_APP_DECODING_MASK 0x0000007F
|
||||
|
||||
/**
|
||||
* @brief APP2EMB_TRIGGER register definition
|
||||
* <pre>
|
||||
* Bits Field Name Reset Value
|
||||
* ----- ------------------ -----------
|
||||
* 31:00 APP2EMB_TRIGGER 0x0
|
||||
* </pre>
|
||||
*/
|
||||
#define IPC_APP2EMB_TRIGGER_ADDR 0x12000000
|
||||
#define IPC_APP2EMB_TRIGGER_OFFSET 0x00000000
|
||||
#define IPC_APP2EMB_TRIGGER_INDEX 0x00000000
|
||||
#define IPC_APP2EMB_TRIGGER_RESET 0x00000000
|
||||
|
||||
__INLINE u32 ipc_app2emb_trigger_get(void *env)
|
||||
{
|
||||
return REG_IPC_APP_RD(env, IPC_APP2EMB_TRIGGER_INDEX);
|
||||
}
|
||||
|
||||
__INLINE void ipc_app2emb_trigger_set(void *env, u32 value)
|
||||
{
|
||||
REG_IPC_APP_WR(env, IPC_APP2EMB_TRIGGER_INDEX, value);
|
||||
}
|
||||
|
||||
// field definitions
|
||||
#define IPC_APP2EMB_TRIGGER_MASK ((u32)0xFFFFFFFF)
|
||||
#define IPC_APP2EMB_TRIGGER_LSB 0
|
||||
#define IPC_APP2EMB_TRIGGER_WIDTH ((u32)0x00000020)
|
||||
|
||||
#define IPC_APP2EMB_TRIGGER_RST 0x0
|
||||
|
||||
__INLINE u32 ipc_app2emb_trigger_getf(void *env)
|
||||
{
|
||||
u32 localVal = REG_IPC_APP_RD(env, IPC_APP2EMB_TRIGGER_INDEX);
|
||||
ASSERT_ERR((localVal & ~((u32)0xFFFFFFFF)) == 0);
|
||||
return (localVal >> 0);
|
||||
}
|
||||
|
||||
__INLINE void ipc_app2emb_trigger_setf(void *env, u32 app2embtrigger)
|
||||
{
|
||||
ASSERT_ERR((((u32)app2embtrigger << 0) & ~((u32)0xFFFFFFFF)) == 0);
|
||||
REG_IPC_APP_WR(env, IPC_APP2EMB_TRIGGER_INDEX, (u32)app2embtrigger << 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief EMB2APP_RAWSTATUS register definition
|
||||
* <pre>
|
||||
* Bits Field Name Reset Value
|
||||
* ----- ------------------ -----------
|
||||
* 31:00 EMB2APP_RAWSTATUS 0x0
|
||||
* </pre>
|
||||
*/
|
||||
#define IPC_EMB2APP_RAWSTATUS_ADDR 0x12000004
|
||||
#define IPC_EMB2APP_RAWSTATUS_OFFSET 0x00000004
|
||||
#define IPC_EMB2APP_RAWSTATUS_INDEX 0x00000001
|
||||
#define IPC_EMB2APP_RAWSTATUS_RESET 0x00000000
|
||||
|
||||
__INLINE u32 ipc_emb2app_rawstatus_get(void *env)
|
||||
{
|
||||
return REG_IPC_APP_RD(env, IPC_EMB2APP_RAWSTATUS_INDEX);
|
||||
}
|
||||
|
||||
__INLINE void ipc_emb2app_rawstatus_set(void *env, u32 value)
|
||||
{
|
||||
REG_IPC_APP_WR(env, IPC_EMB2APP_RAWSTATUS_INDEX, value);
|
||||
}
|
||||
|
||||
// field definitions
|
||||
#define IPC_EMB2APP_RAWSTATUS_MASK ((u32)0xFFFFFFFF)
|
||||
#define IPC_EMB2APP_RAWSTATUS_LSB 0
|
||||
#define IPC_EMB2APP_RAWSTATUS_WIDTH ((u32)0x00000020)
|
||||
|
||||
#define IPC_EMB2APP_RAWSTATUS_RST 0x0
|
||||
|
||||
__INLINE u32 ipc_emb2app_rawstatus_getf(void *env)
|
||||
{
|
||||
u32 localVal = REG_IPC_APP_RD(env, IPC_EMB2APP_RAWSTATUS_INDEX);
|
||||
ASSERT_ERR((localVal & ~((u32)0xFFFFFFFF)) == 0);
|
||||
return (localVal >> 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief EMB2APP_ACK register definition
|
||||
* <pre>
|
||||
* Bits Field Name Reset Value
|
||||
* ----- ------------------ -----------
|
||||
* 31:00 EMB2APP_ACK 0x0
|
||||
* </pre>
|
||||
*/
|
||||
#define IPC_EMB2APP_ACK_ADDR 0x12000008
|
||||
#define IPC_EMB2APP_ACK_OFFSET 0x00000008
|
||||
#define IPC_EMB2APP_ACK_INDEX 0x00000002
|
||||
#define IPC_EMB2APP_ACK_RESET 0x00000000
|
||||
|
||||
__INLINE u32 ipc_emb2app_ack_get(void *env)
|
||||
{
|
||||
return REG_IPC_APP_RD(env, IPC_EMB2APP_ACK_INDEX);
|
||||
}
|
||||
|
||||
__INLINE void ipc_emb2app_ack_clear(void *env, u32 value)
|
||||
{
|
||||
REG_IPC_APP_WR(env, IPC_EMB2APP_ACK_INDEX, value);
|
||||
}
|
||||
|
||||
// field definitions
|
||||
#define IPC_EMB2APP_ACK_MASK ((u32)0xFFFFFFFF)
|
||||
#define IPC_EMB2APP_ACK_LSB 0
|
||||
#define IPC_EMB2APP_ACK_WIDTH ((u32)0x00000020)
|
||||
|
||||
#define IPC_EMB2APP_ACK_RST 0x0
|
||||
|
||||
__INLINE u32 ipc_emb2app_ack_getf(void *env)
|
||||
{
|
||||
u32 localVal = REG_IPC_APP_RD(env, IPC_EMB2APP_ACK_INDEX);
|
||||
ASSERT_ERR((localVal & ~((u32)0xFFFFFFFF)) == 0);
|
||||
return (localVal >> 0);
|
||||
}
|
||||
|
||||
__INLINE void ipc_emb2app_ack_clearf(void *env, u32 emb2appack)
|
||||
{
|
||||
ASSERT_ERR((((u32)emb2appack << 0) & ~((u32)0xFFFFFFFF)) == 0);
|
||||
REG_IPC_APP_WR(env, IPC_EMB2APP_ACK_INDEX, (u32)emb2appack << 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief EMB2APP_UNMASK_SET register definition
|
||||
* <pre>
|
||||
* Bits Field Name Reset Value
|
||||
* ----- ------------------ -----------
|
||||
* 31:00 EMB2APP_UNMASK 0x0
|
||||
* </pre>
|
||||
*/
|
||||
#define IPC_EMB2APP_UNMASK_SET_ADDR 0x1200000C
|
||||
#define IPC_EMB2APP_UNMASK_SET_OFFSET 0x0000000C
|
||||
#define IPC_EMB2APP_UNMASK_SET_INDEX 0x00000003
|
||||
#define IPC_EMB2APP_UNMASK_SET_RESET 0x00000000
|
||||
|
||||
__INLINE u32 ipc_emb2app_unmask_get(void *env)
|
||||
{
|
||||
return REG_IPC_APP_RD(env, IPC_EMB2APP_UNMASK_SET_INDEX);
|
||||
}
|
||||
|
||||
__INLINE void ipc_emb2app_unmask_set(void *env, u32 value)
|
||||
{
|
||||
REG_IPC_APP_WR(env, IPC_EMB2APP_UNMASK_SET_INDEX, value);
|
||||
}
|
||||
|
||||
// field definitions
|
||||
#define IPC_EMB2APP_UNMASK_MASK ((u32)0xFFFFFFFF)
|
||||
#define IPC_EMB2APP_UNMASK_LSB 0
|
||||
#define IPC_EMB2APP_UNMASK_WIDTH ((u32)0x00000020)
|
||||
|
||||
#define IPC_EMB2APP_UNMASK_RST 0x0
|
||||
|
||||
__INLINE u32 ipc_emb2app_unmask_getf(void *env)
|
||||
{
|
||||
u32 localVal = REG_IPC_APP_RD(env, IPC_EMB2APP_UNMASK_SET_INDEX);
|
||||
ASSERT_ERR((localVal & ~((u32)0xFFFFFFFF)) == 0);
|
||||
return (localVal >> 0);
|
||||
}
|
||||
|
||||
__INLINE void ipc_emb2app_unmask_setf(void *env, u32 emb2appunmask)
|
||||
{
|
||||
ASSERT_ERR((((u32)emb2appunmask << 0) & ~((u32)0xFFFFFFFF)) == 0);
|
||||
REG_IPC_APP_WR(env, IPC_EMB2APP_UNMASK_SET_INDEX, (u32)emb2appunmask << 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief EMB2APP_UNMASK_CLEAR register definition
|
||||
* <pre>
|
||||
* Bits Field Name Reset Value
|
||||
* ----- ------------------ -----------
|
||||
* 31:00 EMB2APP_UNMASK 0x0
|
||||
* </pre>
|
||||
*/
|
||||
#define IPC_EMB2APP_UNMASK_CLEAR_ADDR 0x12000010
|
||||
#define IPC_EMB2APP_UNMASK_CLEAR_OFFSET 0x00000010
|
||||
#define IPC_EMB2APP_UNMASK_CLEAR_INDEX 0x00000004
|
||||
#define IPC_EMB2APP_UNMASK_CLEAR_RESET 0x00000000
|
||||
|
||||
__INLINE void ipc_emb2app_unmask_clear(void *env, u32 value)
|
||||
{
|
||||
REG_IPC_APP_WR(env, IPC_EMB2APP_UNMASK_CLEAR_INDEX, value);
|
||||
}
|
||||
|
||||
// fields defined in symmetrical set/clear register
|
||||
__INLINE void ipc_emb2app_unmask_clearf(void *env, u32 emb2appunmask)
|
||||
{
|
||||
ASSERT_ERR((((u32)emb2appunmask << 0) & ~((u32)0xFFFFFFFF)) == 0);
|
||||
REG_IPC_APP_WR(env, IPC_EMB2APP_UNMASK_CLEAR_INDEX, (u32)emb2appunmask << 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief EMB2APP_STATUS register definition
|
||||
* <pre>
|
||||
* Bits Field Name Reset Value
|
||||
* ----- ------------------ -----------
|
||||
* 31:00 EMB2APP_STATUS 0x0
|
||||
* </pre>
|
||||
*/
|
||||
#ifdef CONFIG_RWNX_OLD_IPC
|
||||
#define IPC_EMB2APP_STATUS_ADDR 0x12000014
|
||||
#define IPC_EMB2APP_STATUS_OFFSET 0x00000014
|
||||
#define IPC_EMB2APP_STATUS_INDEX 0x00000005
|
||||
#else
|
||||
#define IPC_EMB2APP_STATUS_ADDR 0x1200001C
|
||||
#define IPC_EMB2APP_STATUS_OFFSET 0x0000001C
|
||||
#define IPC_EMB2APP_STATUS_INDEX 0x00000007
|
||||
#endif
|
||||
#define IPC_EMB2APP_STATUS_RESET 0x00000000
|
||||
|
||||
__INLINE u32 ipc_emb2app_status_get(void *env)
|
||||
{
|
||||
return REG_IPC_APP_RD(env, IPC_EMB2APP_STATUS_INDEX);
|
||||
}
|
||||
|
||||
__INLINE void ipc_emb2app_status_set(void *env, u32 value)
|
||||
{
|
||||
REG_IPC_APP_WR(env, IPC_EMB2APP_STATUS_INDEX, value);
|
||||
}
|
||||
|
||||
// field definitions
|
||||
#define IPC_EMB2APP_STATUS_MASK ((u32)0xFFFFFFFF)
|
||||
#define IPC_EMB2APP_STATUS_LSB 0
|
||||
#define IPC_EMB2APP_STATUS_WIDTH ((u32)0x00000020)
|
||||
|
||||
#define IPC_EMB2APP_STATUS_RST 0x0
|
||||
|
||||
__INLINE u32 ipc_emb2app_status_getf(void *env)
|
||||
{
|
||||
u32 localVal = REG_IPC_APP_RD(env, IPC_EMB2APP_STATUS_INDEX);
|
||||
ASSERT_ERR((localVal & ~((u32)0xFFFFFFFF)) == 0);
|
||||
return (localVal >> 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief APP_SIGNATURE register definition
|
||||
* <pre>
|
||||
* Bits Field Name Reset Value
|
||||
* ----- ------------------ ----------
|
||||
* 31:00 APP_SIGNATURE 0x0
|
||||
* </pre>
|
||||
*/
|
||||
#define IPC_APP_SIGNATURE_ADDR 0x12000040
|
||||
#define IPC_APP_SIGNATURE_OFFSET 0x00000040
|
||||
#define IPC_APP_SIGNATURE_INDEX 0x00000010
|
||||
#define IPC_APP_SIGNATURE_RESET 0x00000000
|
||||
|
||||
__INLINE u32 ipc_app_signature_get(void *env)
|
||||
{
|
||||
return REG_IPC_APP_RD(env, IPC_APP_SIGNATURE_INDEX);
|
||||
}
|
||||
|
||||
__INLINE void ipc_app_signature_set(void *env, u32 value)
|
||||
{
|
||||
REG_IPC_APP_WR(env, IPC_APP_SIGNATURE_INDEX, value);
|
||||
}
|
||||
|
||||
// field definitions
|
||||
#define IPC_APP_SIGNATURE_MASK ((u32)0xFFFFFFFF)
|
||||
#define IPC_APP_SIGNATURE_LSB 0
|
||||
#define IPC_APP_SIGNATURE_WIDTH ((u32)0x00000020)
|
||||
|
||||
#define IPC_APP_SIGNATURE_RST 0x0
|
||||
|
||||
__INLINE u32 ipc_app_signature_getf(void *env)
|
||||
{
|
||||
u32 localVal = REG_IPC_APP_RD(env, IPC_APP_SIGNATURE_INDEX);
|
||||
ASSERT_ERR((localVal & ~((u32)0xFFFFFFFF)) == 0);
|
||||
return (localVal >> 0);
|
||||
}
|
||||
|
||||
|
||||
#endif // _REG_IPC_APP_H_
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_bfmer.c
|
||||
*
|
||||
* @brief VHT Beamformer function definitions
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2016-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* INCLUDE FILES
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include "rwnx_bfmer.h"
|
||||
|
||||
/**
|
||||
* FUNCTION DEFINITIONS
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
int rwnx_bfmer_report_add(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta,
|
||||
unsigned int length)
|
||||
{
|
||||
gfp_t flags;
|
||||
struct rwnx_bfmer_report *bfm_report ;
|
||||
|
||||
if (in_softirq())
|
||||
flags = GFP_ATOMIC;
|
||||
else
|
||||
flags = GFP_KERNEL;
|
||||
|
||||
/* Allocate a structure that will contain the beamforming report */
|
||||
bfm_report = kmalloc(sizeof(*bfm_report) + length, flags);
|
||||
|
||||
|
||||
/* Check report allocation */
|
||||
if (!bfm_report) {
|
||||
/* Do not use beamforming */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Store report length */
|
||||
bfm_report->length = length;
|
||||
|
||||
/*
|
||||
* Need to provide a Virtual Address to the MAC so that it can
|
||||
* upload the received Beamforming Report in driver memory
|
||||
*/
|
||||
bfm_report->dma_addr = dma_map_single(rwnx_hw->dev, &bfm_report->report[0],
|
||||
length, DMA_FROM_DEVICE);
|
||||
|
||||
/* Check DMA mapping result */
|
||||
if (dma_mapping_error(rwnx_hw->dev, bfm_report->dma_addr)) {
|
||||
/* Free allocated report */
|
||||
kfree(bfm_report);
|
||||
/* And leave */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Store report structure */
|
||||
rwnx_sta->bfm_report = bfm_report;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rwnx_bfmer_report_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta)
|
||||
{
|
||||
/* Verify if a report has been allocated */
|
||||
if (rwnx_sta->bfm_report) {
|
||||
struct rwnx_bfmer_report *bfm_report = rwnx_sta->bfm_report;
|
||||
|
||||
/* Unmap DMA region */
|
||||
dma_unmap_single(rwnx_hw->dev, bfm_report->dma_addr,
|
||||
bfm_report->length, DMA_BIDIRECTIONAL);
|
||||
|
||||
/* Free allocated report structure and clean the pointer */
|
||||
kfree(bfm_report);
|
||||
rwnx_sta->bfm_report = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
u8 rwnx_bfmer_get_rx_nss(const struct ieee80211_vht_cap *vht_capa)
|
||||
{
|
||||
int i;
|
||||
u8 rx_nss = 0;
|
||||
u16 rx_mcs_map = le16_to_cpu(vht_capa->supp_mcs.rx_mcs_map);
|
||||
|
||||
for (i = 7; i >= 0; i--) {
|
||||
u8 mcs = (rx_mcs_map >> (2 * i)) & 3;
|
||||
|
||||
if (mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED) {
|
||||
rx_nss = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rx_nss;
|
||||
}
|
||||
#endif /* CONFIG_RWNX_FULLMAC */
|
||||
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_bfmer.h
|
||||
*
|
||||
* @brief VHT Beamformer function declarations
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2016-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _RWNX_BFMER_H_
|
||||
#define _RWNX_BFMER_H_
|
||||
|
||||
/**
|
||||
* INCLUDE FILES
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "rwnx_defs.h"
|
||||
|
||||
/**
|
||||
* DEFINES
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/// Maximal supported report length (in bytes)
|
||||
#define RWNX_BFMER_REPORT_MAX_LEN 2048
|
||||
|
||||
/// Size of the allocated report space (twice the maximum report length)
|
||||
#define RWNX_BFMER_REPORT_SPACE_SIZE (RWNX_BFMER_REPORT_MAX_LEN * 2)
|
||||
|
||||
/**
|
||||
* TYPE DEFINITIONS
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
* Structure used to store a beamforming report.
|
||||
*/
|
||||
struct rwnx_bfmer_report {
|
||||
dma_addr_t dma_addr; /* Virtual address provided to MAC for
|
||||
DMA transfer of the Beamforming Report */
|
||||
unsigned int length; /* Report Length */
|
||||
u8 report[1]; /* Report to be used for VHT TX Beamforming */
|
||||
};
|
||||
|
||||
/**
|
||||
* FUNCTION DECLARATIONS
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @brief Allocate memory aiming to contains the Beamforming Report received
|
||||
* from a Beamformee capable capable.
|
||||
* The providing length shall be large enough to contain the VHT Compressed
|
||||
* Beaforming Report and the MU Exclusive part.
|
||||
* It also perform a DMA Mapping providing an address to be provided to the HW
|
||||
* responsible for the DMA transfer of the report.
|
||||
* If successful a struct rwnx_bfmer_report object is allocated, it's address
|
||||
* is stored in rwnx_sta->bfm_report.
|
||||
*
|
||||
* @param[in] rwnx_hw PHY Information
|
||||
* @param[in] rwnx_sta Peer STA Information
|
||||
* @param[in] length Memory size to be allocated
|
||||
*
|
||||
* @return 0 if operation is successful, else -1.
|
||||
******************************************************************************
|
||||
*/
|
||||
int rwnx_bfmer_report_add(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta,
|
||||
unsigned int length);
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @brief Free a previously allocated memory intended to be used for
|
||||
* Beamforming Reports.
|
||||
*
|
||||
* @param[in] rwnx_hw PHY Information
|
||||
* @param[in] rwnx_sta Peer STA Information
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
void rwnx_bfmer_report_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta);
|
||||
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
/**
|
||||
******************************************************************************
|
||||
* @brief Parse a Rx VHT-MCS map in order to deduce the maximum number of
|
||||
* Spatial Streams supported by a beamformee.
|
||||
*
|
||||
* @param[in] vht_capa Received VHT Capability field.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
u8 rwnx_bfmer_get_rx_nss(const struct ieee80211_vht_cap *vht_capa);
|
||||
#endif /* CONFIG_RWNX_FULLMAC */
|
||||
|
||||
#endif /* _RWNX_BFMER_H_ */
|
||||
@@ -0,0 +1,237 @@
|
||||
/**
|
||||
****************************************************************************************
|
||||
*
|
||||
* @file rwnx_configparse.c
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
****************************************************************************************
|
||||
*/
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
#include "rwnx_defs.h"
|
||||
#include "rwnx_cfgfile.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static const char *rwnx_find_tag(const u8 *file_data, unsigned int file_size,
|
||||
const char *tag_name, unsigned int tag_len)
|
||||
{
|
||||
unsigned int curr, line_start = 0, line_size;
|
||||
|
||||
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
||||
|
||||
/* Walk through all the lines of the configuration file */
|
||||
while (line_start < file_size) {
|
||||
/* Search the end of the current line (or the end of the file) */
|
||||
for (curr = line_start; curr < file_size; curr++)
|
||||
if (file_data[curr] == '\n')
|
||||
break;
|
||||
|
||||
/* Compute the line size */
|
||||
line_size = curr - line_start;
|
||||
|
||||
/* Check if this line contains the expected tag */
|
||||
if ((line_size == (strlen(tag_name) + tag_len)) &&
|
||||
(!strncmp(&file_data[line_start], tag_name, strlen(tag_name))))
|
||||
return (&file_data[line_start + strlen(tag_name)]);
|
||||
|
||||
/* Move to next line */
|
||||
line_start = curr + 1;
|
||||
}
|
||||
|
||||
/* Tag not found */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the Config file used at init time
|
||||
*/
|
||||
int rwnx_parse_configfile(struct rwnx_hw *rwnx_hw, const char *filename,
|
||||
struct rwnx_conf_file *config)
|
||||
{
|
||||
const struct firmware *config_fw;
|
||||
u8 dflt_mac[ETH_ALEN] = { 0, 111, 111, 111, 111, 0 };
|
||||
int ret;
|
||||
const u8 *tag_ptr;
|
||||
|
||||
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
||||
|
||||
if ((ret = request_firmware(&config_fw, filename, rwnx_hw->dev))) {
|
||||
printk(KERN_CRIT "%s: Failed to get %s (%d)\n", __func__, filename, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get MAC Address */
|
||||
tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size,
|
||||
"MAC_ADDR=", strlen("00:00:00:00:00:00"));
|
||||
if (tag_ptr != NULL) {
|
||||
u8 *addr = config->mac_addr;
|
||||
if (sscanf(tag_ptr,
|
||||
"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
|
||||
addr + 0, addr + 1, addr + 2,
|
||||
addr + 3, addr + 4, addr + 5) != ETH_ALEN)
|
||||
memcpy(config->mac_addr, dflt_mac, ETH_ALEN);
|
||||
} else
|
||||
memcpy(config->mac_addr, dflt_mac, ETH_ALEN);
|
||||
|
||||
RWNX_DBG("MAC Address is:\n%pM\n", config->mac_addr);
|
||||
|
||||
/* Release the configuration file */
|
||||
release_firmware(config_fw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the Config file used at init time
|
||||
*/
|
||||
int rwnx_parse_phy_configfile(struct rwnx_hw *rwnx_hw, const char *filename,
|
||||
struct rwnx_phy_conf_file *config, int path)
|
||||
{
|
||||
const struct firmware *config_fw;
|
||||
int ret;
|
||||
const u8 *tag_ptr;
|
||||
|
||||
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
||||
|
||||
if ((ret = request_firmware(&config_fw, filename, rwnx_hw->dev))) {
|
||||
printk(KERN_CRIT "%s: Failed to get %s (%d)\n", __func__, filename, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get Trident path mapping */
|
||||
tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size,
|
||||
"TRD_PATH_MAPPING=", strlen("00"));
|
||||
if (tag_ptr != NULL) {
|
||||
u8 val;
|
||||
if (sscanf(tag_ptr, "%hhx", &val) == 1)
|
||||
config->trd.path_mapping = val;
|
||||
else
|
||||
config->trd.path_mapping = path;
|
||||
} else
|
||||
config->trd.path_mapping = path;
|
||||
|
||||
RWNX_DBG("Trident path mapping is: %d\n", config->trd.path_mapping);
|
||||
|
||||
/* Get DC offset compensation */
|
||||
tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size,
|
||||
"TX_DC_OFF_COMP=", strlen("00000000"));
|
||||
if (tag_ptr != NULL) {
|
||||
if (sscanf(tag_ptr, "%08x", &config->trd.tx_dc_off_comp) != 1)
|
||||
config->trd.tx_dc_off_comp = 0;
|
||||
} else
|
||||
config->trd.tx_dc_off_comp = 0;
|
||||
|
||||
RWNX_DBG("TX DC offset compensation is: %08X\n", config->trd.tx_dc_off_comp);
|
||||
|
||||
/* Get Karst TX IQ compensation value for path0 on 2.4GHz */
|
||||
tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size,
|
||||
"KARST_TX_IQ_COMP_2_4G_PATH_0=", strlen("00000000"));
|
||||
if (tag_ptr != NULL) {
|
||||
if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_2_4G[0]) != 1)
|
||||
config->karst.tx_iq_comp_2_4G[0] = 0x01000000;
|
||||
} else
|
||||
config->karst.tx_iq_comp_2_4G[0] = 0x01000000;
|
||||
|
||||
RWNX_DBG("Karst TX IQ compensation for path 0 on 2.4GHz is: %08X\n", config->karst.tx_iq_comp_2_4G[0]);
|
||||
|
||||
/* Get Karst TX IQ compensation value for path1 on 2.4GHz */
|
||||
tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size,
|
||||
"KARST_TX_IQ_COMP_2_4G_PATH_1=", strlen("00000000"));
|
||||
if (tag_ptr != NULL) {
|
||||
if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_2_4G[1]) != 1)
|
||||
config->karst.tx_iq_comp_2_4G[1] = 0x01000000;
|
||||
} else
|
||||
config->karst.tx_iq_comp_2_4G[1] = 0x01000000;
|
||||
|
||||
RWNX_DBG("Karst TX IQ compensation for path 1 on 2.4GHz is: %08X\n", config->karst.tx_iq_comp_2_4G[1]);
|
||||
|
||||
/* Get Karst RX IQ compensation value for path0 on 2.4GHz */
|
||||
tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size,
|
||||
"KARST_RX_IQ_COMP_2_4G_PATH_0=", strlen("00000000"));
|
||||
if (tag_ptr != NULL) {
|
||||
if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_2_4G[0]) != 1)
|
||||
config->karst.rx_iq_comp_2_4G[0] = 0x01000000;
|
||||
} else
|
||||
config->karst.rx_iq_comp_2_4G[0] = 0x01000000;
|
||||
|
||||
RWNX_DBG("Karst RX IQ compensation for path 0 on 2.4GHz is: %08X\n", config->karst.rx_iq_comp_2_4G[0]);
|
||||
|
||||
/* Get Karst RX IQ compensation value for path1 on 2.4GHz */
|
||||
tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size,
|
||||
"KARST_RX_IQ_COMP_2_4G_PATH_1=", strlen("00000000"));
|
||||
if (tag_ptr != NULL) {
|
||||
if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_2_4G[1]) != 1)
|
||||
config->karst.rx_iq_comp_2_4G[1] = 0x01000000;
|
||||
} else
|
||||
config->karst.rx_iq_comp_2_4G[1] = 0x01000000;
|
||||
|
||||
RWNX_DBG("Karst RX IQ compensation for path 1 on 2.4GHz is: %08X\n", config->karst.rx_iq_comp_2_4G[1]);
|
||||
|
||||
/* Get Karst TX IQ compensation value for path0 on 5GHz */
|
||||
tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size,
|
||||
"KARST_TX_IQ_COMP_5G_PATH_0=", strlen("00000000"));
|
||||
if (tag_ptr != NULL) {
|
||||
if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_5G[0]) != 1)
|
||||
config->karst.tx_iq_comp_5G[0] = 0x01000000;
|
||||
} else
|
||||
config->karst.tx_iq_comp_5G[0] = 0x01000000;
|
||||
|
||||
RWNX_DBG("Karst TX IQ compensation for path 0 on 5GHz is: %08X\n", config->karst.tx_iq_comp_5G[0]);
|
||||
|
||||
/* Get Karst TX IQ compensation value for path1 on 5GHz */
|
||||
tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size,
|
||||
"KARST_TX_IQ_COMP_5G_PATH_1=", strlen("00000000"));
|
||||
if (tag_ptr != NULL) {
|
||||
if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_5G[1]) != 1)
|
||||
config->karst.tx_iq_comp_5G[1] = 0x01000000;
|
||||
} else
|
||||
config->karst.tx_iq_comp_5G[1] = 0x01000000;
|
||||
|
||||
RWNX_DBG("Karst TX IQ compensation for path 1 on 5GHz is: %08X\n", config->karst.tx_iq_comp_5G[1]);
|
||||
|
||||
/* Get Karst RX IQ compensation value for path0 on 5GHz */
|
||||
tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size,
|
||||
"KARST_RX_IQ_COMP_5G_PATH_0=", strlen("00000000"));
|
||||
if (tag_ptr != NULL) {
|
||||
if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_5G[0]) != 1)
|
||||
config->karst.rx_iq_comp_5G[0] = 0x01000000;
|
||||
} else
|
||||
config->karst.rx_iq_comp_5G[0] = 0x01000000;
|
||||
|
||||
RWNX_DBG("Karst RX IQ compensation for path 0 on 5GHz is: %08X\n", config->karst.rx_iq_comp_5G[0]);
|
||||
|
||||
/* Get Karst RX IQ compensation value for path1 on 5GHz */
|
||||
tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size,
|
||||
"KARST_RX_IQ_COMP_5G_PATH_1=", strlen("00000000"));
|
||||
if (tag_ptr != NULL) {
|
||||
if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_5G[1]) != 1)
|
||||
config->karst.rx_iq_comp_5G[1] = 0x01000000;
|
||||
} else
|
||||
config->karst.rx_iq_comp_5G[1] = 0x01000000;
|
||||
|
||||
RWNX_DBG("Karst RX IQ compensation for path 1 on 5GHz is: %08X\n", config->karst.rx_iq_comp_5G[1]);
|
||||
|
||||
/* Get Karst default path */
|
||||
tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size,
|
||||
"KARST_DEFAULT_PATH=", strlen("00"));
|
||||
if (tag_ptr != NULL) {
|
||||
u8 val;
|
||||
if (sscanf(tag_ptr, "%hhx", &val) == 1)
|
||||
config->karst.path_used = val;
|
||||
else
|
||||
config->karst.path_used = path;
|
||||
} else
|
||||
config->karst.path_used = path;
|
||||
|
||||
RWNX_DBG("Karst default path is: %d\n", config->karst.path_used);
|
||||
|
||||
/* Release the configuration file */
|
||||
release_firmware(config_fw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
****************************************************************************************
|
||||
*
|
||||
* @file rwnx_cfgfile.h
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _RWNX_CFGFILE_H_
|
||||
#define _RWNX_CFGFILE_H_
|
||||
|
||||
/*
|
||||
* Structure used to retrieve information from the Config file used at Initialization time
|
||||
*/
|
||||
struct rwnx_conf_file {
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure used to retrieve information from the PHY Config file used at Initialization time
|
||||
*/
|
||||
struct rwnx_phy_conf_file {
|
||||
struct phy_trd_cfg_tag trd;
|
||||
struct phy_karst_cfg_tag karst;
|
||||
};
|
||||
|
||||
int rwnx_parse_configfile(struct rwnx_hw *rwnx_hw, const char *filename,
|
||||
struct rwnx_conf_file *config);
|
||||
|
||||
int rwnx_parse_phy_configfile(struct rwnx_hw *rwnx_hw, const char *filename,
|
||||
struct rwnx_phy_conf_file *config, int path);
|
||||
|
||||
#endif /* _RWNX_CFGFILE_H_ */
|
||||
@@ -0,0 +1,545 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* rwnx_cmds.c
|
||||
*
|
||||
* Handles queueing (push to IPC, ack/cfm from IPC) of commands issued to
|
||||
* LMAC FW
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2014-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
//#define CREATE_TRACE_POINTS
|
||||
#include <linux/list.h>
|
||||
|
||||
#include "rwnx_cmds.h"
|
||||
#include "rwnx_defs.h"
|
||||
#include "rwnx_strs.h"
|
||||
#include "rwnx_events.h"
|
||||
#include "aicwf_txrxif.h"
|
||||
#ifdef AICWF_SDIO_SUPPORT
|
||||
#include "aicwf_sdio.h"
|
||||
#else
|
||||
#include "aicwf_usb.h"
|
||||
#endif
|
||||
/**
|
||||
*
|
||||
*/
|
||||
extern int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val);
|
||||
|
||||
void rwnx_cmd_free(struct rwnx_cmd *cmd);
|
||||
|
||||
static void cmd_dump(const struct rwnx_cmd *cmd)
|
||||
{
|
||||
printk(KERN_CRIT "tkn[%d] flags:%04x result:%3d cmd:%4d-%-24s - reqcfm(%4d-%-s)\n",
|
||||
cmd->tkn, cmd->flags, cmd->result, cmd->id, RWNX_ID2STR(cmd->id),
|
||||
cmd->reqid, cmd->reqid != (lmac_msg_id_t)-1 ? RWNX_ID2STR(cmd->reqid) : "none");
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
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--;
|
||||
|
||||
cmd->flags |= RWNX_CMD_FLAG_DONE;
|
||||
if (cmd->flags & RWNX_CMD_FLAG_NONBLOCK) {
|
||||
rwnx_cmd_free(cmd);//kfree(cmd);AIDEN
|
||||
} else {
|
||||
if (RWNX_CMD_WAIT_COMPLETE(cmd->flags)) {
|
||||
cmd->result = 0;
|
||||
complete(&cmd->complete);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int cmd_mgr_queue_force_defer(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd)
|
||||
{
|
||||
bool defer_push = false;
|
||||
|
||||
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
||||
#ifdef CREATE_TRACE_POINTS
|
||||
trace_msg_send(cmd->id);
|
||||
#endif
|
||||
spin_lock_bh(&cmd_mgr->lock);
|
||||
|
||||
if (cmd_mgr->state == RWNX_CMD_MGR_STATE_CRASHED) {
|
||||
printk(KERN_CRIT"cmd queue crashed\n");
|
||||
cmd->result = -EPIPE;
|
||||
spin_unlock_bh(&cmd_mgr->lock);
|
||||
return -EPIPE;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_RWNX_FHOST
|
||||
if (!list_empty(&cmd_mgr->cmds)) {
|
||||
if (cmd_mgr->queue_sz == cmd_mgr->max_queue_sz) {
|
||||
printk(KERN_CRIT"Too many cmds (%d) already queued\n",
|
||||
cmd_mgr->max_queue_sz);
|
||||
cmd->result = -ENOMEM;
|
||||
spin_unlock_bh(&cmd_mgr->lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
cmd->flags |= RWNX_CMD_FLAG_WAIT_PUSH;
|
||||
defer_push = true;
|
||||
|
||||
if (cmd->flags & RWNX_CMD_FLAG_REQ_CFM)
|
||||
cmd->flags |= RWNX_CMD_FLAG_WAIT_CFM;
|
||||
|
||||
cmd->tkn = cmd_mgr->next_tkn++;
|
||||
cmd->result = -EINTR;
|
||||
|
||||
if (!(cmd->flags & RWNX_CMD_FLAG_NONBLOCK))
|
||||
init_completion(&cmd->complete);
|
||||
|
||||
list_add_tail(&cmd->list, &cmd_mgr->cmds);
|
||||
cmd_mgr->queue_sz++;
|
||||
spin_unlock_bh(&cmd_mgr->lock);
|
||||
|
||||
WAKE_CMD_WORK(cmd_mgr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rwnx_msg_free_(struct lmac_msg *msg);
|
||||
|
||||
|
||||
static int cmd_mgr_queue(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd)
|
||||
{
|
||||
int ret = 0;
|
||||
#ifdef AICWF_SDIO_SUPPORT
|
||||
struct aic_sdio_dev *sdiodev = container_of(cmd_mgr, struct aic_sdio_dev, cmd_mgr);
|
||||
#endif
|
||||
#ifdef AICWF_USB_SUPPORT
|
||||
|
||||
struct aic_usb_dev *usbdev = container_of(cmd_mgr, struct aic_usb_dev, cmd_mgr);
|
||||
#endif
|
||||
bool defer_push = false;
|
||||
|
||||
//RWNX_DBG(RWNX_FN_ENTRY_STR);
|
||||
#ifdef CREATE_TRACE_POINTS
|
||||
trace_msg_send(cmd->id);
|
||||
#endif
|
||||
spin_lock_bh(&cmd_mgr->lock);
|
||||
|
||||
if (cmd_mgr->state == RWNX_CMD_MGR_STATE_CRASHED) {
|
||||
printk(KERN_CRIT"cmd queue crashed\n");
|
||||
cmd->result = -EPIPE;
|
||||
spin_unlock_bh(&cmd_mgr->lock);
|
||||
return -EPIPE;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_RWNX_FHOST
|
||||
if (!list_empty(&cmd_mgr->cmds)) {
|
||||
struct rwnx_cmd *last;
|
||||
|
||||
if (cmd_mgr->queue_sz == cmd_mgr->max_queue_sz) {
|
||||
printk(KERN_CRIT"Too many cmds (%d) already queued\n",
|
||||
cmd_mgr->max_queue_sz);
|
||||
cmd->result = -ENOMEM;
|
||||
spin_unlock_bh(&cmd_mgr->lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
last = list_entry(cmd_mgr->cmds.prev, struct rwnx_cmd, list);
|
||||
if (last->flags & (RWNX_CMD_FLAG_WAIT_ACK | RWNX_CMD_FLAG_WAIT_PUSH | RWNX_CMD_FLAG_WAIT_CFM)) {
|
||||
#if 0 // queue even NONBLOCK command.
|
||||
if (cmd->flags & RWNX_CMD_FLAG_NONBLOCK) {
|
||||
printk(KERN_CRIT"cmd queue busy\n");
|
||||
cmd->result = -EBUSY;
|
||||
spin_unlock_bh(&cmd_mgr->lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
#endif
|
||||
cmd->flags |= RWNX_CMD_FLAG_WAIT_PUSH;
|
||||
defer_push = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
cmd->flags |= RWNX_CMD_FLAG_WAIT_ACK;
|
||||
#endif
|
||||
if (cmd->flags & RWNX_CMD_FLAG_REQ_CFM)
|
||||
cmd->flags |= RWNX_CMD_FLAG_WAIT_CFM;
|
||||
|
||||
cmd->tkn = cmd_mgr->next_tkn++;
|
||||
cmd->result = -EINTR;
|
||||
|
||||
if (!(cmd->flags & RWNX_CMD_FLAG_NONBLOCK))
|
||||
init_completion(&cmd->complete);
|
||||
|
||||
list_add_tail(&cmd->list, &cmd_mgr->cmds);
|
||||
cmd_mgr->queue_sz++;
|
||||
|
||||
if(cmd->a2e_msg->id == ME_TRAFFIC_IND_REQ
|
||||
#ifdef AICWF_ARP_OFFLOAD
|
||||
|| cmd->a2e_msg->id == MM_SET_ARPOFFLOAD_REQ
|
||||
#endif
|
||||
) {
|
||||
defer_push = true;
|
||||
cmd->flags |= RWNX_CMD_FLAG_WAIT_PUSH;
|
||||
//printk("defer push: tkn=%d\r\n", cmd->tkn);
|
||||
}
|
||||
|
||||
spin_unlock_bh(&cmd_mgr->lock);
|
||||
if (!defer_push) {
|
||||
AICWFDBG(LOGTRACE, "queue:id=%x, param_len=%u\n",cmd->a2e_msg->id, cmd->a2e_msg->param_len);
|
||||
|
||||
#ifdef AICWF_SDIO_SUPPORT
|
||||
aicwf_set_cmd_tx((void *)(sdiodev), cmd->a2e_msg, sizeof(struct lmac_msg) + cmd->a2e_msg->param_len);
|
||||
#else
|
||||
aicwf_set_cmd_tx((void *)(usbdev), cmd->a2e_msg, sizeof(struct lmac_msg) + cmd->a2e_msg->param_len);
|
||||
#endif
|
||||
//rwnx_ipc_msg_push(rwnx_hw, cmd, RWNX_CMD_A2EMSG_LEN(cmd->a2e_msg));
|
||||
|
||||
kfree(cmd->a2e_msg);
|
||||
} else {
|
||||
if(cmd_mgr->queue_sz <= 1){
|
||||
WAKE_CMD_WORK(cmd_mgr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(cmd->flags & RWNX_CMD_FLAG_NONBLOCK)) {
|
||||
#ifdef CONFIG_RWNX_FHOST
|
||||
if (wait_for_completion_killable(&cmd->complete)) {
|
||||
cmd->result = -EINTR;
|
||||
spin_lock_bh(&cmd_mgr->lock);
|
||||
cmd_complete(cmd_mgr, cmd);
|
||||
spin_unlock_bh(&cmd_mgr->lock);
|
||||
/* TODO: kill the cmd at fw level */
|
||||
}
|
||||
#else
|
||||
unsigned long tout = msecs_to_jiffies(RWNX_80211_CMD_TIMEOUT_MS/*AIDEN workaround* cmd_mgr->queue_sz*/);
|
||||
if (!wait_for_completion_killable_timeout(&cmd->complete, tout)) {
|
||||
printk(KERN_CRIT"%s cmd timed-out cmd_mgr->queue_sz:%d\n", __func__,cmd_mgr->queue_sz);
|
||||
#ifdef AICWF_SDIO_SUPPORT
|
||||
ret = aicwf_sdio_writeb(sdiodev, SDIOWIFI_WAKEUP_REG, 2);
|
||||
if (ret < 0) {
|
||||
sdio_err("reg:%d write failed!\n", SDIOWIFI_WAKEUP_REG);
|
||||
}
|
||||
#endif
|
||||
|
||||
cmd_dump(cmd);
|
||||
spin_lock_bh(&cmd_mgr->lock);
|
||||
|
||||
cmd_mgr->state = RWNX_CMD_MGR_STATE_CRASHED;
|
||||
if (!(cmd->flags & RWNX_CMD_FLAG_DONE)) {
|
||||
cmd->result = -ETIMEDOUT;
|
||||
cmd_complete(cmd_mgr, cmd);
|
||||
}
|
||||
ret = -ETIMEDOUT;
|
||||
spin_unlock_bh(&cmd_mgr->lock);
|
||||
}
|
||||
else{
|
||||
rwnx_cmd_free(cmd);//kfree(cmd);AIDEN
|
||||
if(!list_empty(&cmd_mgr->cmds) && usbdev->state == USB_UP_ST)
|
||||
WAKE_CMD_WORK(cmd_mgr);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
cmd->result = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static int cmd_mgr_llind(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd)
|
||||
{
|
||||
struct rwnx_cmd *cur, *acked = NULL, *next = NULL;
|
||||
|
||||
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
||||
|
||||
spin_lock_bh(&cmd_mgr->lock);
|
||||
list_for_each_entry(cur, &cmd_mgr->cmds, list) {
|
||||
if (!acked) {
|
||||
if (cur->tkn == cmd->tkn) {
|
||||
if (WARN_ON_ONCE(cur != cmd)) {
|
||||
cmd_dump(cmd);
|
||||
}
|
||||
acked = cur;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (cur->flags & RWNX_CMD_FLAG_WAIT_PUSH) {
|
||||
next = cur;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!acked) {
|
||||
printk(KERN_CRIT "Error: acked cmd not found\n");
|
||||
} else {
|
||||
cmd->flags &= ~RWNX_CMD_FLAG_WAIT_ACK;
|
||||
if (RWNX_CMD_WAIT_COMPLETE(cmd->flags))
|
||||
cmd_complete(cmd_mgr, cmd);
|
||||
}
|
||||
|
||||
if (next) {
|
||||
#if 0 //there is no ack
|
||||
struct rwnx_hw *rwnx_hw = container_of(cmd_mgr, struct rwnx_hw, cmd_mgr);
|
||||
next->flags &= ~RWNX_CMD_FLAG_WAIT_PUSH;
|
||||
rwnx_ipc_msg_push(rwnx_hw, next, RWNX_CMD_A2EMSG_LEN(next->a2e_msg));
|
||||
kfree(next->a2e_msg);
|
||||
#endif
|
||||
}
|
||||
spin_unlock(&cmd_mgr->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cmd_mgr_task_process(struct work_struct *work)
|
||||
{
|
||||
struct rwnx_cmd_mgr *cmd_mgr = container_of(work, struct rwnx_cmd_mgr, cmdWork);
|
||||
struct rwnx_cmd *cur, *next = NULL;
|
||||
unsigned long tout;
|
||||
|
||||
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
||||
|
||||
while(1) {
|
||||
next = NULL;
|
||||
spin_lock_bh(&cmd_mgr->lock);
|
||||
|
||||
list_for_each_entry(cur, &cmd_mgr->cmds, list) {
|
||||
if (cur->flags & RWNX_CMD_FLAG_WAIT_PUSH) { //just judge the first
|
||||
next = cur;
|
||||
}
|
||||
break;
|
||||
}
|
||||
spin_unlock_bh(&cmd_mgr->lock);
|
||||
|
||||
if(next == NULL)
|
||||
break;
|
||||
|
||||
if (next) {
|
||||
#ifdef AICWF_SDIO_SUPPORT
|
||||
struct aic_sdio_dev *sdiodev = container_of(cmd_mgr, struct aic_sdio_dev, cmd_mgr);
|
||||
#endif
|
||||
#ifdef AICWF_USB_SUPPORT
|
||||
struct aic_usb_dev *usbdev = container_of(cmd_mgr, struct aic_usb_dev, cmd_mgr);
|
||||
#endif
|
||||
next->flags &= ~RWNX_CMD_FLAG_WAIT_PUSH;
|
||||
|
||||
//printk("cmd_process, cmd->id=%d, tkn=%d\r\n",next->reqid, next->tkn);
|
||||
//rwnx_ipc_msg_push(rwnx_hw, next, RWNX_CMD_A2EMSG_LEN(next->a2e_msg));
|
||||
#ifdef AICWF_SDIO_SUPPORT
|
||||
aicwf_set_cmd_tx((void *)(sdiodev), next->a2e_msg, sizeof(struct lmac_msg) + next->a2e_msg->param_len);
|
||||
#else
|
||||
aicwf_set_cmd_tx((void *)(usbdev), next->a2e_msg, sizeof(struct lmac_msg) + next->a2e_msg->param_len);
|
||||
#endif
|
||||
kfree(next->a2e_msg);
|
||||
|
||||
tout = msecs_to_jiffies(RWNX_80211_CMD_TIMEOUT_MS * cmd_mgr->queue_sz);
|
||||
if (!wait_for_completion_killable_timeout(&next->complete, tout)) {
|
||||
printk(KERN_CRIT"%s cmd timed-out cmd_mgr->queue_sz:%d\n", __func__, cmd_mgr->queue_sz);
|
||||
cmd_dump(next);
|
||||
spin_lock_bh(&cmd_mgr->lock);
|
||||
//AIDEN workaround
|
||||
cmd_mgr->state = RWNX_CMD_MGR_STATE_CRASHED;
|
||||
if (!(next->flags & RWNX_CMD_FLAG_DONE)) {
|
||||
next->result = -ETIMEDOUT;
|
||||
cmd_complete(cmd_mgr, next);
|
||||
}
|
||||
spin_unlock_bh(&cmd_mgr->lock);
|
||||
} else
|
||||
rwnx_cmd_free(next);//kfree(next);AIDEN
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int cmd_mgr_run_callback(struct rwnx_hw *rwnx_hw, struct rwnx_cmd *cmd,
|
||||
struct rwnx_cmd_e2amsg *msg, msg_cb_fct cb)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (! cb){
|
||||
return 0;
|
||||
}
|
||||
//RWNX_DBG(RWNX_FN_ENTRY_STR);
|
||||
#ifndef CONFIG_DEBUG_ATOMIC_SLEEP
|
||||
//spin_lock_bh(&rwnx_hw->cb_lock);
|
||||
#endif
|
||||
res = cb(rwnx_hw, cmd, msg);
|
||||
#ifndef CONFIG_DEBUG_ATOMIC_SLEEP
|
||||
//spin_unlock_bh(&rwnx_hw->cb_lock);
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
*/
|
||||
static int cmd_mgr_msgind(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd_e2amsg *msg,
|
||||
msg_cb_fct cb)
|
||||
{
|
||||
#ifdef AICWF_SDIO_SUPPORT
|
||||
struct aic_sdio_dev *sdiodev = container_of(cmd_mgr, struct aic_sdio_dev, cmd_mgr);
|
||||
struct rwnx_hw *rwnx_hw = sdiodev->rwnx_hw;
|
||||
#endif
|
||||
#ifdef AICWF_USB_SUPPORT
|
||||
struct aic_usb_dev *usbdev = container_of(cmd_mgr, struct aic_usb_dev, cmd_mgr);
|
||||
struct rwnx_hw *rwnx_hw = usbdev->rwnx_hw;
|
||||
#endif
|
||||
struct rwnx_cmd *cmd, *pos;
|
||||
bool found = false;
|
||||
|
||||
// RWNX_DBG(RWNX_FN_ENTRY_STR);
|
||||
#ifdef CREATE_TRACE_POINTS
|
||||
trace_msg_recv(msg->id);
|
||||
#endif
|
||||
AICWFDBG(LOGTRACE, "%s cmd->id=%d\n", __func__, msg->id);
|
||||
spin_lock_bh(&cmd_mgr->lock);
|
||||
list_for_each_entry_safe(cmd, pos, &cmd_mgr->cmds, list) {
|
||||
if (cmd->reqid == msg->id &&
|
||||
(cmd->flags & RWNX_CMD_FLAG_WAIT_CFM)) {
|
||||
|
||||
if (!cmd_mgr_run_callback(rwnx_hw, cmd, msg, cb)) {
|
||||
found = true;
|
||||
cmd->flags &= ~RWNX_CMD_FLAG_WAIT_CFM;
|
||||
|
||||
if (WARN((msg->param_len > RWNX_CMD_E2AMSG_LEN_MAX),
|
||||
"Unexpect E2A msg len %d > %d\n", msg->param_len,
|
||||
RWNX_CMD_E2AMSG_LEN_MAX)) {
|
||||
msg->param_len = RWNX_CMD_E2AMSG_LEN_MAX;
|
||||
}
|
||||
|
||||
if (cmd->e2a_msg && msg->param_len)
|
||||
memcpy(cmd->e2a_msg, &msg->param, msg->param_len);
|
||||
|
||||
if (RWNX_CMD_WAIT_COMPLETE(cmd->flags))
|
||||
cmd_complete(cmd_mgr, cmd);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&cmd_mgr->lock);
|
||||
|
||||
if (!found)
|
||||
cmd_mgr_run_callback(rwnx_hw, NULL, msg, cb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void cmd_mgr_print(struct rwnx_cmd_mgr *cmd_mgr)
|
||||
{
|
||||
struct rwnx_cmd *cur;
|
||||
|
||||
spin_lock_bh(&cmd_mgr->lock);
|
||||
RWNX_DBG("q_sz/max: %2d / %2d - next tkn: %d\n",
|
||||
cmd_mgr->queue_sz, cmd_mgr->max_queue_sz,
|
||||
cmd_mgr->next_tkn);
|
||||
list_for_each_entry(cur, &cmd_mgr->cmds, list) {
|
||||
cmd_dump(cur);
|
||||
}
|
||||
spin_unlock_bh(&cmd_mgr->lock);
|
||||
}
|
||||
|
||||
static void cmd_mgr_drain(struct rwnx_cmd_mgr *cmd_mgr)
|
||||
{
|
||||
struct rwnx_cmd *cur, *nxt;
|
||||
|
||||
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
||||
|
||||
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--;
|
||||
if (!(cur->flags & RWNX_CMD_FLAG_NONBLOCK))
|
||||
complete(&cur->complete);
|
||||
}
|
||||
spin_unlock_bh(&cmd_mgr->lock);
|
||||
}
|
||||
|
||||
void rwnx_cmd_mgr_init(struct rwnx_cmd_mgr *cmd_mgr)
|
||||
{
|
||||
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
||||
|
||||
INIT_LIST_HEAD(&cmd_mgr->cmds);
|
||||
cmd_mgr->state = RWNX_CMD_MGR_STATE_INITED;
|
||||
spin_lock_init(&cmd_mgr->lock);
|
||||
cmd_mgr->max_queue_sz = RWNX_CMD_MAX_QUEUED;
|
||||
cmd_mgr->queue = &cmd_mgr_queue;
|
||||
cmd_mgr->print = &cmd_mgr_print;
|
||||
cmd_mgr->drain = &cmd_mgr_drain;
|
||||
cmd_mgr->llind = &cmd_mgr_llind;
|
||||
cmd_mgr->msgind = &cmd_mgr_msgind;
|
||||
|
||||
INIT_WORK(&cmd_mgr->cmdWork, cmd_mgr_task_process);
|
||||
cmd_mgr->cmd_wq = create_singlethread_workqueue("cmd_wq");
|
||||
if (!cmd_mgr->cmd_wq) {
|
||||
txrx_err("insufficient memory to create cmd workqueue.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void rwnx_cmd_mgr_deinit(struct rwnx_cmd_mgr *cmd_mgr)
|
||||
{
|
||||
if(cmd_mgr->print && cmd_mgr->drain){
|
||||
cmd_mgr->print(cmd_mgr);
|
||||
cmd_mgr->drain(cmd_mgr);
|
||||
cmd_mgr->print(cmd_mgr);
|
||||
flush_workqueue(cmd_mgr->cmd_wq);
|
||||
destroy_workqueue(cmd_mgr->cmd_wq);
|
||||
memset(cmd_mgr, 0, sizeof(*cmd_mgr));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void aicwf_set_cmd_tx(void *dev, struct lmac_msg *msg, uint len)
|
||||
{
|
||||
u8 *buffer = NULL;
|
||||
u16 index = 0;
|
||||
#ifdef AICWF_SDIO_SUPPORT
|
||||
struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *)dev;
|
||||
struct aicwf_bus *bus = sdiodev->bus_if;
|
||||
#else
|
||||
struct aic_usb_dev *usbdev = (struct aic_usb_dev *)dev;
|
||||
struct aicwf_bus *bus = NULL;
|
||||
if (!usbdev->state) {
|
||||
printk("down msg \n");
|
||||
return;
|
||||
}
|
||||
bus = usbdev->bus_if;
|
||||
#endif
|
||||
buffer = bus->cmd_buf;
|
||||
|
||||
memset(buffer, 0, CMD_BUF_MAX);
|
||||
buffer[0] = (len+4) & 0x00ff;
|
||||
buffer[1] = ((len+4) >> 8) &0x0f;
|
||||
buffer[2] = 0x11;
|
||||
buffer[3] = 0x0;
|
||||
index += 4;
|
||||
//there is a dummy word
|
||||
index += 4;
|
||||
|
||||
//make sure little endian
|
||||
put_u16(&buffer[index], msg->id);
|
||||
index += 2;
|
||||
put_u16(&buffer[index], msg->dest_id);
|
||||
index += 2;
|
||||
put_u16(&buffer[index], msg->src_id);
|
||||
index += 2;
|
||||
put_u16(&buffer[index], msg->param_len);
|
||||
index += 2;
|
||||
memcpy(&buffer[index], (u8 *)msg->param, msg->param_len);
|
||||
|
||||
aicwf_bus_txmsg(bus, buffer, len + 8);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* rwnx_cmds.h
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2014-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _RWNX_CMDS_H_
|
||||
#define _RWNX_CMDS_H_
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/module.h>
|
||||
#include "lmac_msg.h"
|
||||
|
||||
#ifdef CONFIG_RWNX_SDM
|
||||
#define RWNX_80211_CMD_TIMEOUT_MS (20 * 300)
|
||||
#elif defined(CONFIG_RWNX_FHOST)
|
||||
#define RWNX_80211_CMD_TIMEOUT_MS (10000)
|
||||
#else
|
||||
#define RWNX_80211_CMD_TIMEOUT_MS 4000//500//300
|
||||
#endif
|
||||
|
||||
#define RWNX_CMD_FLAG_NONBLOCK BIT(0)
|
||||
#define RWNX_CMD_FLAG_REQ_CFM BIT(1)
|
||||
#define RWNX_CMD_FLAG_WAIT_PUSH BIT(2)
|
||||
#define RWNX_CMD_FLAG_WAIT_ACK BIT(3)
|
||||
#define RWNX_CMD_FLAG_WAIT_CFM BIT(4)
|
||||
#define RWNX_CMD_FLAG_DONE BIT(5)
|
||||
/* ATM IPC design makes it possible to get the CFM before the ACK,
|
||||
* otherwise this could have simply been a state enum */
|
||||
#define RWNX_CMD_WAIT_COMPLETE(flags) \
|
||||
(!(flags & (RWNX_CMD_FLAG_WAIT_ACK | RWNX_CMD_FLAG_WAIT_CFM)))
|
||||
|
||||
#define RWNX_CMD_MAX_QUEUED 16//8 AIDEN
|
||||
|
||||
#ifdef CONFIG_RWNX_FHOST
|
||||
#include "ipc_fhost.h"
|
||||
#define rwnx_cmd_e2amsg ipc_fhost_msg
|
||||
#define rwnx_cmd_a2emsg ipc_fhost_msg
|
||||
#define RWNX_CMD_A2EMSG_LEN(m) (m->param_len)
|
||||
#define RWNX_CMD_E2AMSG_LEN_MAX IPC_FHOST_MSG_BUF_SIZE
|
||||
struct rwnx_term_stream;
|
||||
|
||||
#else /* !CONFIG_RWNX_FHOST*/
|
||||
#include "ipc_shared.h"
|
||||
#define rwnx_cmd_e2amsg ipc_e2a_msg
|
||||
#define rwnx_cmd_a2emsg lmac_msg
|
||||
#define RWNX_CMD_A2EMSG_LEN(m) (sizeof(struct lmac_msg) + m->param_len)
|
||||
#define RWNX_CMD_E2AMSG_LEN_MAX (IPC_E2A_MSG_PARAM_SIZE * 4)
|
||||
|
||||
#endif /* CONFIG_RWNX_FHOST*/
|
||||
|
||||
struct rwnx_hw;
|
||||
struct rwnx_cmd;
|
||||
typedef int (*msg_cb_fct)(struct rwnx_hw *rwnx_hw, struct rwnx_cmd *cmd,
|
||||
struct rwnx_cmd_e2amsg *msg);
|
||||
static inline void put_u16(u8 *buf, u16 data)
|
||||
{
|
||||
buf[0] = (u8)(data&0x00ff);
|
||||
buf[1] = (u8)((data >> 8)&0x00ff);
|
||||
}
|
||||
|
||||
enum rwnx_cmd_mgr_state {
|
||||
RWNX_CMD_MGR_STATE_DEINIT,
|
||||
RWNX_CMD_MGR_STATE_INITED,
|
||||
RWNX_CMD_MGR_STATE_CRASHED,
|
||||
};
|
||||
|
||||
struct rwnx_cmd {
|
||||
struct list_head list;
|
||||
lmac_msg_id_t id;
|
||||
lmac_msg_id_t reqid;
|
||||
struct rwnx_cmd_a2emsg *a2e_msg;
|
||||
char *e2a_msg;
|
||||
u32 tkn;
|
||||
u16 flags;
|
||||
|
||||
struct completion complete;
|
||||
u32 result;
|
||||
u8 used;
|
||||
int array_id;
|
||||
#ifdef CONFIG_RWNX_FHOST
|
||||
struct rwnx_term_stream *stream;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct rwnx_cmd_mgr {
|
||||
enum rwnx_cmd_mgr_state state;
|
||||
spinlock_t lock;
|
||||
u32 next_tkn;
|
||||
u32 queue_sz;
|
||||
u32 max_queue_sz;
|
||||
|
||||
struct list_head cmds;
|
||||
|
||||
int (*queue)(struct rwnx_cmd_mgr *, struct rwnx_cmd *);
|
||||
int (*llind)(struct rwnx_cmd_mgr *, struct rwnx_cmd *);
|
||||
int (*msgind)(struct rwnx_cmd_mgr *, struct rwnx_cmd_e2amsg *, msg_cb_fct);
|
||||
void (*print)(struct rwnx_cmd_mgr *);
|
||||
void (*drain)(struct rwnx_cmd_mgr *);
|
||||
|
||||
struct work_struct cmdWork;
|
||||
struct workqueue_struct *cmd_wq;
|
||||
};
|
||||
|
||||
#define WAKE_CMD_WORK(cmd_mgr) \
|
||||
do { \
|
||||
queue_work((cmd_mgr)->cmd_wq, &cmd_mgr->cmdWork); \
|
||||
} while (0)
|
||||
|
||||
void rwnx_cmd_mgr_init(struct rwnx_cmd_mgr *cmd_mgr);
|
||||
void rwnx_cmd_mgr_deinit(struct rwnx_cmd_mgr *cmd_mgr);
|
||||
int cmd_mgr_queue_force_defer(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd);
|
||||
void aicwf_set_cmd_tx(void *dev, struct lmac_msg *msg, uint len);
|
||||
|
||||
#endif /* _RWNX_CMDS_H_ */
|
||||
@@ -0,0 +1,431 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_compat.h
|
||||
*
|
||||
* Ensure driver compilation for linux 3.16 to 3.19
|
||||
*
|
||||
* To avoid too many #if LINUX_VERSION_CODE if the code, when prototype change
|
||||
* between different kernel version:
|
||||
* - For external function, define a macro whose name is the function name with
|
||||
* _compat suffix and prototype (actually the number of parameter) of the
|
||||
* latest version. Then latest version this macro simply call the function
|
||||
* and for older kernel version it call the function adapting the api.
|
||||
* - For internal function (e.g. cfg80211_ops) do the same but the macro name
|
||||
* doesn't need to have the _compat suffix when the function is not used
|
||||
* directly by the driver
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2018
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#ifndef _RWNX_COMPAT_H_
|
||||
#define _RWNX_COMPAT_H_
|
||||
#include <linux/version.h>
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
|
||||
#error "Minimum kernel version supported is 3.10"
|
||||
#endif
|
||||
|
||||
/* Generic */
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)
|
||||
#define __bf_shf(x) (__builtin_ffsll(x) - 1)
|
||||
#define FIELD_PREP(_mask, _val) \
|
||||
(((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask))
|
||||
#else
|
||||
#include <linux/bitfield.h>
|
||||
#endif
|
||||
|
||||
/* CFG80211 */
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0)
|
||||
#define IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK IEEE80211_HE_MAC_CAP3_MAX_A_AMPDU_LEN_EXP_MASK
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 15, 60)
|
||||
#define IEEE80211_MAX_AMPDU_BUF IEEE80211_MAX_AMPDU_BUF_HE
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
|
||||
#define IEEE80211_RADIOTAP_HE 23
|
||||
#define IEEE80211_RADIOTAP_HE_MU 24
|
||||
|
||||
struct ieee80211_radiotap_he {
|
||||
__le16 data1, data2, data3, data4, data5, data6;
|
||||
};
|
||||
|
||||
enum ieee80211_radiotap_he_bits {
|
||||
IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MASK = 3,
|
||||
IEEE80211_RADIOTAP_HE_DATA1_FORMAT_SU = 0,
|
||||
IEEE80211_RADIOTAP_HE_DATA1_FORMAT_EXT_SU = 1,
|
||||
IEEE80211_RADIOTAP_HE_DATA1_FORMAT_MU = 2,
|
||||
IEEE80211_RADIOTAP_HE_DATA1_FORMAT_TRIG = 3,
|
||||
|
||||
IEEE80211_RADIOTAP_HE_DATA1_BSS_COLOR_KNOWN = 0x0004,
|
||||
IEEE80211_RADIOTAP_HE_DATA1_BEAM_CHANGE_KNOWN = 0x0008,
|
||||
IEEE80211_RADIOTAP_HE_DATA1_UL_DL_KNOWN = 0x0010,
|
||||
IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN = 0x0020,
|
||||
IEEE80211_RADIOTAP_HE_DATA1_DATA_DCM_KNOWN = 0x0040,
|
||||
IEEE80211_RADIOTAP_HE_DATA1_CODING_KNOWN = 0x0080,
|
||||
IEEE80211_RADIOTAP_HE_DATA1_LDPC_XSYMSEG_KNOWN = 0x0100,
|
||||
IEEE80211_RADIOTAP_HE_DATA1_STBC_KNOWN = 0x0200,
|
||||
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE_KNOWN = 0x0400,
|
||||
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE2_KNOWN = 0x0800,
|
||||
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE3_KNOWN = 0x1000,
|
||||
IEEE80211_RADIOTAP_HE_DATA1_SPTL_REUSE4_KNOWN = 0x2000,
|
||||
IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN = 0x4000,
|
||||
IEEE80211_RADIOTAP_HE_DATA1_DOPPLER_KNOWN = 0x8000,
|
||||
|
||||
IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_KNOWN = 0x0001,
|
||||
IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN = 0x0002,
|
||||
IEEE80211_RADIOTAP_HE_DATA2_NUM_LTF_SYMS_KNOWN = 0x0004,
|
||||
IEEE80211_RADIOTAP_HE_DATA2_PRE_FEC_PAD_KNOWN = 0x0008,
|
||||
IEEE80211_RADIOTAP_HE_DATA2_TXBF_KNOWN = 0x0010,
|
||||
IEEE80211_RADIOTAP_HE_DATA2_PE_DISAMBIG_KNOWN = 0x0020,
|
||||
IEEE80211_RADIOTAP_HE_DATA2_TXOP_KNOWN = 0x0040,
|
||||
IEEE80211_RADIOTAP_HE_DATA2_MIDAMBLE_KNOWN = 0x0080,
|
||||
IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET = 0x3f00,
|
||||
IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET_KNOWN = 0x4000,
|
||||
IEEE80211_RADIOTAP_HE_DATA2_PRISEC_80_SEC = 0x8000,
|
||||
|
||||
IEEE80211_RADIOTAP_HE_DATA3_BSS_COLOR = 0x003f,
|
||||
IEEE80211_RADIOTAP_HE_DATA3_BEAM_CHANGE = 0x0040,
|
||||
IEEE80211_RADIOTAP_HE_DATA3_UL_DL = 0x0080,
|
||||
IEEE80211_RADIOTAP_HE_DATA3_DATA_MCS = 0x0f00,
|
||||
IEEE80211_RADIOTAP_HE_DATA3_DATA_DCM = 0x1000,
|
||||
IEEE80211_RADIOTAP_HE_DATA3_CODING = 0x2000,
|
||||
IEEE80211_RADIOTAP_HE_DATA3_LDPC_XSYMSEG = 0x4000,
|
||||
IEEE80211_RADIOTAP_HE_DATA3_STBC = 0x8000,
|
||||
|
||||
IEEE80211_RADIOTAP_HE_DATA4_SU_MU_SPTL_REUSE = 0x000f,
|
||||
IEEE80211_RADIOTAP_HE_DATA4_MU_STA_ID = 0x7ff0,
|
||||
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE1 = 0x000f,
|
||||
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE2 = 0x00f0,
|
||||
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE3 = 0x0f00,
|
||||
IEEE80211_RADIOTAP_HE_DATA4_TB_SPTL_REUSE4 = 0xf000,
|
||||
|
||||
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC = 0x000f,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ = 0,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_40MHZ = 1,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_80MHZ = 2,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_160MHZ = 3,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_26T = 4,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_52T = 5,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_106T = 6,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_242T = 7,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_484T = 8,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_996T = 9,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_2x996T = 10,
|
||||
|
||||
IEEE80211_RADIOTAP_HE_DATA5_GI = 0x0030,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_GI_0_8 = 0,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_GI_1_6 = 1,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_GI_3_2 = 2,
|
||||
|
||||
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE = 0x00c0,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN = 0,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_1X = 1,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_2X = 2,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X = 3,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_NUM_LTF_SYMS = 0x0700,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_PRE_FEC_PAD = 0x3000,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_TXBF = 0x4000,
|
||||
IEEE80211_RADIOTAP_HE_DATA5_PE_DISAMBIG = 0x8000,
|
||||
|
||||
IEEE80211_RADIOTAP_HE_DATA6_NSTS = 0x000f,
|
||||
IEEE80211_RADIOTAP_HE_DATA6_DOPPLER = 0x0010,
|
||||
IEEE80211_RADIOTAP_HE_DATA6_TXOP = 0x7f00,
|
||||
IEEE80211_RADIOTAP_HE_DATA6_MIDAMBLE_PDCTY = 0x8000,
|
||||
};
|
||||
|
||||
struct ieee80211_radiotap_he_mu {
|
||||
__le16 flags1, flags2;
|
||||
u8 ru_ch1[4];
|
||||
u8 ru_ch2[4];
|
||||
};
|
||||
|
||||
enum ieee80211_radiotap_he_mu_bits {
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS = 0x000f,
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_MCS_KNOWN = 0x0010,
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM = 0x0020,
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_DCM_KNOWN = 0x0040,
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_CTR_26T_RU_KNOWN = 0x0080,
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_RU_KNOWN = 0x0100,
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_RU_KNOWN = 0x0200,
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU_KNOWN = 0x1000,
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH1_CTR_26T_RU = 0x2000,
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_COMP_KNOWN = 0x4000,
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN = 0x8000,
|
||||
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW = 0x0003,
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_20MHZ = 0x0000,
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_40MHZ = 0x0001,
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_80MHZ = 0x0002,
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_160MHZ = 0x0003,
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN = 0x0004,
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_COMP = 0x0008,
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS2_SIG_B_SYMS_USERS = 0x00f0,
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW = 0x0300,
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS2_PUNC_FROM_SIG_A_BW_KNOWN= 0x0400,
|
||||
IEEE80211_RADIOTAP_HE_MU_FLAGS2_CH2_CTR_26T_RU = 0x0800,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)
|
||||
#define rwnx_cfg80211_add_iface(wiphy, name, name_assign_type, type, params) \
|
||||
rwnx_cfg80211_add_iface(wiphy, name, type, u32 *flags, params)
|
||||
#else
|
||||
#define rwnx_cfg80211_add_iface(wiphy, name, name_assign_type, type, params) \
|
||||
rwnx_cfg80211_add_iface(wiphy, name, name_assign_type, type, u32 *flags, params)
|
||||
#endif
|
||||
|
||||
#define rwnx_cfg80211_change_iface(wiphy, dev, type, params) \
|
||||
rwnx_cfg80211_change_iface(wiphy, dev, type, u32 *flags, params)
|
||||
|
||||
#define CCFS0(vht) vht->center_freq_seg1_idx
|
||||
#define CCFS1(vht) vht->center_freq_seg2_idx
|
||||
|
||||
#else
|
||||
#define CCFS0(vht) vht->center_freq_seg0_idx
|
||||
#define CCFS1(vht) vht->center_freq_seg1_idx
|
||||
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
|
||||
#define cfg80211_cqm_rssi_notify(dev, event, level, gfp) \
|
||||
cfg80211_cqm_rssi_notify(dev, event, gfp)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)
|
||||
#define ieee80211_amsdu_to_8023s(skb, list, addr, iftype, extra_headroom, check_da, check_sa) \
|
||||
ieee80211_amsdu_to_8023s(skb, list, addr, iftype, extra_headroom, false)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0)
|
||||
#define NUM_NL80211_BANDS IEEE80211_NUM_BANDS
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
|
||||
#define cfg80211_disconnected(dev, reason, ie, len, local, gfp) \
|
||||
cfg80211_disconnected(dev, reason, ie, len, gfp)
|
||||
#endif
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !(defined CONFIG_VENDOR_RWNX)
|
||||
#define ieee80211_chandef_to_operating_class(chan_def, op_class) 0
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
|
||||
#define SURVEY_INFO_TIME SURVEY_INFO_CHANNEL_TIME
|
||||
#define SURVEY_INFO_TIME_BUSY SURVEY_INFO_CHANNEL_TIME_BUSY
|
||||
#define SURVEY_INFO_TIME_EXT_BUSY SURVEY_INFO_CHANNEL_TIME_EXT_BUSY
|
||||
#define SURVEY_INFO_TIME_RX SURVEY_INFO_CHANNEL_TIME_RX
|
||||
#define SURVEY_INFO_TIME_TX SURVEY_INFO_CHANNEL_TIME_TX
|
||||
|
||||
#define SURVEY_TIME(s) s->channel_time
|
||||
#define SURVEY_TIME_BUSY(s) s->channel_time_busy
|
||||
#else
|
||||
#define SURVEY_TIME(s) s->time
|
||||
#define SURVEY_TIME_BUSY(s) s->time_busy
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
|
||||
#define cfg80211_ch_switch_started_notify(dev, chandef, count)
|
||||
|
||||
#define WLAN_BSS_COEX_INFORMATION_REQUEST BIT(0)
|
||||
#define WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING BIT(2)
|
||||
#define WLAN_EXT_CAPA4_TDLS_BUFFER_STA BIT(4)
|
||||
#define WLAN_EXT_CAPA4_TDLS_PEER_PSM BIT(5)
|
||||
#define WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH BIT(6)
|
||||
#define WLAN_EXT_CAPA5_TDLS_CH_SW_PROHIBITED BIT(7)
|
||||
#define NL80211_FEATURE_TDLS_CHANNEL_SWITCH 0
|
||||
|
||||
#define STA_TDLS_INITIATOR(sta) 0
|
||||
|
||||
#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
|
||||
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
|
||||
#define cfg80211_rx_mgmt(wdev, freq, rssi, buf, len, flags) \
|
||||
cfg80211_rx_mgmt(wdev, freq, rssi, buf, len, flags, GFP_ATOMIC)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0)
|
||||
#define cfg80211_rx_mgmt(wdev, freq, rssi, buf, len, flags) \
|
||||
cfg80211_rx_mgmt(wdev, freq, rssi, buf, len, GFP_ATOMIC)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
|
||||
|
||||
#if 0
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
|
||||
#define rwnx_cfg80211_tdls_mgmt(wiphy, dev, peer, act, tok, status, peer_capability, initiator, buf, len) \
|
||||
rwnx_cfg80211_tdls_mgmt(wiphy, dev, peer, act, tok, status, peer_capability, buf, len)
|
||||
#else
|
||||
#define rwnx_cfg80211_tdls_mgmt(wiphy, dev, peer, act, tok, status, peer_capability, initiator, buf, len) \
|
||||
rwnx_cfg80211_tdls_mgmt(wiphy, dev, peer, act, tok, status, buf, len)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct ieee80211_wmm_ac_param {
|
||||
u8 aci_aifsn; /* AIFSN, ACM, ACI */
|
||||
u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */
|
||||
__le16 txop_limit;
|
||||
} __packed;
|
||||
|
||||
struct ieee80211_wmm_param_ie {
|
||||
u8 element_id; /* Element ID: 221 (0xdd); */
|
||||
u8 len; /* Length: 24 */
|
||||
/* required fields for WMM version 1 */
|
||||
u8 oui[3]; /* 00:50:f2 */
|
||||
u8 oui_type; /* 2 */
|
||||
u8 oui_subtype; /* 1 */
|
||||
u8 version; /* 1 for WMM version 1.0 */
|
||||
u8 qos_info; /* AP/STA specific QoS info */
|
||||
u8 reserved; /* 0 */
|
||||
/* AC_BE, AC_BK, AC_VI, AC_VO */
|
||||
struct ieee80211_wmm_ac_param ac[4];
|
||||
} __packed;
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
|
||||
enum {
|
||||
IEEE80211_HE_MCS_SUPPORT_0_7 = 0,
|
||||
IEEE80211_HE_MCS_SUPPORT_0_9 = 1,
|
||||
IEEE80211_HE_MCS_SUPPORT_0_11 = 2,
|
||||
IEEE80211_HE_MCS_NOT_SUPPORTED = 3,
|
||||
};
|
||||
#endif
|
||||
|
||||
/* MAC80211 */
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0)
|
||||
#define rwnx_ops_mgd_prepare_tx(hw, vif, duration) \
|
||||
rwnx_ops_mgd_prepare_tx(hw, vif)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
|
||||
|
||||
#define RX_ENC_HT(s) s->flag |= RX_FLAG_HT
|
||||
#define RX_ENC_HT_GF(s) s->flag |= (RX_FLAG_HT | RX_FLAG_HT_GF)
|
||||
#define RX_ENC_VHT(s) s->flag |= RX_FLAG_HT
|
||||
#define RX_ENC_HE(s) s->flag |= RX_FLAG_HT
|
||||
#define RX_ENC_FLAG_SHORT_GI(s) s->flag |= RX_FLAG_SHORT_GI
|
||||
#define RX_ENC_FLAG_SHORT_PRE(s) s->flag |= RX_FLAG_SHORTPRE
|
||||
#define RX_ENC_FLAG_LDPC(s) s->flag |= RX_FLAG_LDPC
|
||||
#define RX_BW_40MHZ(s) s->flag |= RX_FLAG_40MHZ
|
||||
#define RX_BW_80MHZ(s) s->vht_flag |= RX_VHT_FLAG_80MHZ
|
||||
#define RX_BW_160MHZ(s) s->vht_flag |= RX_VHT_FLAG_160MHZ
|
||||
#define RX_NSS(s) s->vht_nss
|
||||
|
||||
#else
|
||||
#define RX_ENC_HT(s) s->encoding = RX_ENC_HT
|
||||
#define RX_ENC_HT_GF(s) { s->encoding = RX_ENC_HT; \
|
||||
s->enc_flags |= RX_ENC_FLAG_HT_GF; }
|
||||
#define RX_ENC_VHT(s) s->encoding = RX_ENC_VHT
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
|
||||
#define RX_ENC_HE(s) s->encoding = RX_ENC_VHT
|
||||
#else
|
||||
#define RX_ENC_HE(s) s->encoding = RX_ENC_HE
|
||||
#endif
|
||||
#define RX_ENC_FLAG_SHORT_GI(s) s->enc_flags |= RX_ENC_FLAG_SHORT_GI
|
||||
#define RX_ENC_FLAG_SHORT_PRE(s) s->enc_flags |= RX_ENC_FLAG_SHORTPRE
|
||||
#define RX_ENC_FLAG_LDPC(s) s->enc_flags |= RX_ENC_FLAG_LDPC
|
||||
#define RX_BW_40MHZ(s) s->bw = RATE_INFO_BW_40
|
||||
#define RX_BW_80MHZ(s) s->bw = RATE_INFO_BW_80
|
||||
#define RX_BW_160MHZ(s) s->bw = RATE_INFO_BW_160
|
||||
#define RX_NSS(s) s->nss
|
||||
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
|
||||
#define ieee80211_cqm_rssi_notify(vif, event, level, gfp) \
|
||||
ieee80211_cqm_rssi_notify(vif, event, gfp)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_VENDOR_RWNX_AMSDUS_TX
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0))
|
||||
#define rwnx_ops_ampdu_action(hw, vif, params) \
|
||||
rwnx_ops_ampdu_action(hw, vif, enum ieee80211_ampdu_mlme_action action, \
|
||||
struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size)
|
||||
#elif (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0))
|
||||
#define rwnx_ops_ampdu_action(hw, vif, params) \
|
||||
rwnx_ops_ampdu_action(hw, vif, enum ieee80211_ampdu_mlme_action action, \
|
||||
struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size, \
|
||||
bool amsdu)
|
||||
#endif
|
||||
#endif /* CONFIG_VENDOR_RWNX_AMSDUS_TX */
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
|
||||
#define IEEE80211_HW_SUPPORT_FAST_XMIT 0
|
||||
#define ieee80211_hw_check(hw, feat) (hw->flags & IEEE80211_HW_##feat)
|
||||
#define ieee80211_hw_set(hw, feat) {hw->flags |= IEEE80211_HW_##feat;}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
|
||||
#define rwnx_ops_sw_scan_start(hw, vif, mac_addr) \
|
||||
rwnx_ops_sw_scan_start(hw)
|
||||
#define rwnx_ops_sw_scan_complete(hw, vif) \
|
||||
rwnx_ops_sw_scan_complete(hw)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
|
||||
#define rwnx_ops_hw_scan(hw, vif, hw_req) \
|
||||
rwnx_ops_hw_scan(hw, vif, struct cfg80211_scan_request *req)
|
||||
#endif
|
||||
|
||||
/* NET */
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
|
||||
#define rwnx_select_queue(dev, skb, sb_dev) \
|
||||
rwnx_select_queue(dev, skb)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
|
||||
#define rwnx_select_queue(dev, skb, sb_dev) \
|
||||
rwnx_select_queue(dev, skb, void *accel_priv, select_queue_fallback_t fallback)
|
||||
#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)
|
||||
#define rwnx_select_queue(dev, skb, sb_dev) \
|
||||
rwnx_select_queue(dev, skb, sb_dev, select_queue_fallback_t fallback)
|
||||
#else
|
||||
#define rwnx_select_queue(dev, skb, sb_dev) \
|
||||
rwnx_select_queue(dev, skb, sb_dev)
|
||||
#endif
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0)) && !(defined CONFIG_VENDOR_RWNX)
|
||||
#define sk_pacing_shift_update(sk, shift)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
|
||||
#define alloc_netdev_mqs(size, name, assign, setup, txqs, rxqs) \
|
||||
alloc_netdev_mqs(size, name, setup, txqs, rxqs)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
|
||||
#define NET_NAME_UNKNOWN 0
|
||||
#endif
|
||||
|
||||
/* TRACE */
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
|
||||
#define trace_print_symbols_seq ftrace_print_symbols_seq
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
|
||||
#define trace_seq_buffer_ptr(p) p->buffer + p->len
|
||||
#endif
|
||||
|
||||
/* TIME */
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0)
|
||||
#define time64_to_tm(t, o, tm) time_to_tm((time_t)t, o, tm)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
|
||||
#define ktime_get_real_seconds get_seconds
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
|
||||
typedef __s64 time64_t;
|
||||
#endif
|
||||
|
||||
#endif /* _RWNX_COMPAT_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,203 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_debugfs.h
|
||||
*
|
||||
* @brief Miscellaneous utility function definitions
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _RWNX_DEBUGFS_H_
|
||||
#define _RWNX_DEBUGFS_H_
|
||||
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/version.h>
|
||||
#include "rwnx_fw_trace.h"
|
||||
|
||||
struct rwnx_hw;
|
||||
struct rwnx_sta;
|
||||
|
||||
/* some macros taken from iwlwifi */
|
||||
/* TODO: replace with generic read and fill read buffer in open to avoid double
|
||||
* reads */
|
||||
#define DEBUGFS_ADD_FILE(name, parent, mode) do { \
|
||||
if (!debugfs_create_file(#name, mode, parent, rwnx_hw, \
|
||||
&rwnx_dbgfs_##name##_ops)) \
|
||||
goto err; \
|
||||
} while (0)
|
||||
|
||||
#define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \
|
||||
struct dentry *__tmp; \
|
||||
__tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \
|
||||
parent, ptr); \
|
||||
if (IS_ERR(__tmp) || !__tmp) \
|
||||
goto err; \
|
||||
} while (0)
|
||||
|
||||
#define DEBUGFS_ADD_X64(name, parent, ptr) do { \
|
||||
struct dentry *__tmp; \
|
||||
__tmp = debugfs_create_x64(#name, S_IWUSR | S_IRUSR, \
|
||||
parent, ptr); \
|
||||
if (IS_ERR(__tmp) || !__tmp) \
|
||||
goto err; \
|
||||
} while (0)
|
||||
|
||||
#define DEBUGFS_ADD_U64(name, parent, ptr, mode) do { \
|
||||
struct dentry *__tmp; \
|
||||
__tmp = debugfs_create_u64(#name, mode, \
|
||||
parent, ptr); \
|
||||
if (IS_ERR(__tmp) || !__tmp) \
|
||||
goto err; \
|
||||
} while (0)
|
||||
|
||||
#define DEBUGFS_ADD_X32(name, parent, ptr) do { \
|
||||
struct dentry *__tmp; \
|
||||
__tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR, \
|
||||
parent, ptr); \
|
||||
if (IS_ERR(__tmp) || !__tmp) \
|
||||
goto err; \
|
||||
} while (0)
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)
|
||||
#define DEBUGFS_ADD_U32(name, parent, ptr, mode) do { \
|
||||
debugfs_create_u32(#name, mode, \
|
||||
parent, ptr); \
|
||||
} while (0)
|
||||
#else
|
||||
#define DEBUGFS_ADD_U32(name, parent, ptr, mode) do { \
|
||||
struct dentry *__tmp; \
|
||||
__tmp = debugfs_create_u32(#name, mode, \
|
||||
parent, ptr); \
|
||||
if (IS_ERR(__tmp) || !__tmp) \
|
||||
goto err; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
|
||||
/* file operation */
|
||||
#define DEBUGFS_READ_FUNC(name) \
|
||||
static ssize_t rwnx_dbgfs_##name##_read(struct file *file, \
|
||||
char __user *user_buf, \
|
||||
size_t count, loff_t *ppos);
|
||||
|
||||
#define DEBUGFS_WRITE_FUNC(name) \
|
||||
static ssize_t rwnx_dbgfs_##name##_write(struct file *file, \
|
||||
const char __user *user_buf,\
|
||||
size_t count, loff_t *ppos);
|
||||
|
||||
#define DEBUGFS_OPEN_FUNC(name) \
|
||||
static int rwnx_dbgfs_##name##_open(struct inode *inode, \
|
||||
struct file *file);
|
||||
|
||||
#define DEBUGFS_RELEASE_FUNC(name) \
|
||||
static int rwnx_dbgfs_##name##_release(struct inode *inode, \
|
||||
struct file *file);
|
||||
|
||||
#define DEBUGFS_READ_FILE_OPS(name) \
|
||||
DEBUGFS_READ_FUNC(name); \
|
||||
static const struct file_operations rwnx_dbgfs_##name##_ops = { \
|
||||
.read = rwnx_dbgfs_##name##_read, \
|
||||
.open = simple_open, \
|
||||
.llseek = generic_file_llseek, \
|
||||
};
|
||||
|
||||
#define DEBUGFS_WRITE_FILE_OPS(name) \
|
||||
DEBUGFS_WRITE_FUNC(name); \
|
||||
static const struct file_operations rwnx_dbgfs_##name##_ops = { \
|
||||
.write = rwnx_dbgfs_##name##_write, \
|
||||
.open = simple_open, \
|
||||
.llseek = generic_file_llseek, \
|
||||
};
|
||||
|
||||
#define DEBUGFS_READ_WRITE_FILE_OPS(name) \
|
||||
DEBUGFS_READ_FUNC(name); \
|
||||
DEBUGFS_WRITE_FUNC(name); \
|
||||
static const struct file_operations rwnx_dbgfs_##name##_ops = { \
|
||||
.write = rwnx_dbgfs_##name##_write, \
|
||||
.read = rwnx_dbgfs_##name##_read, \
|
||||
.open = simple_open, \
|
||||
.llseek = generic_file_llseek, \
|
||||
};
|
||||
|
||||
#define DEBUGFS_READ_WRITE_OPEN_RELEASE_FILE_OPS(name) \
|
||||
DEBUGFS_READ_FUNC(name); \
|
||||
DEBUGFS_WRITE_FUNC(name); \
|
||||
DEBUGFS_OPEN_FUNC(name); \
|
||||
DEBUGFS_RELEASE_FUNC(name); \
|
||||
static const struct file_operations rwnx_dbgfs_##name##_ops = { \
|
||||
.write = rwnx_dbgfs_##name##_write, \
|
||||
.read = rwnx_dbgfs_##name##_read, \
|
||||
.open = rwnx_dbgfs_##name##_open, \
|
||||
.release = rwnx_dbgfs_##name##_release, \
|
||||
.llseek = generic_file_llseek, \
|
||||
};
|
||||
|
||||
|
||||
#ifdef CONFIG_RWNX_DEBUGFS
|
||||
|
||||
struct rwnx_debugfs {
|
||||
unsigned long long rateidx;
|
||||
struct dentry *dir;
|
||||
bool trace_prst;
|
||||
|
||||
char helper_cmd[64];
|
||||
//struct work_struct helper_work;
|
||||
bool helper_scheduled;
|
||||
spinlock_t umh_lock;
|
||||
bool unregistering;
|
||||
|
||||
#ifndef CONFIG_RWNX_FHOST
|
||||
struct rwnx_fw_log fw_log;
|
||||
#endif /* CONFIG_RWNX_FHOST */
|
||||
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
struct work_struct rc_stat_work;
|
||||
uint8_t rc_sta[NX_REMOTE_STA_MAX];
|
||||
uint8_t rc_write;
|
||||
uint8_t rc_read;
|
||||
struct dentry *dir_rc;
|
||||
struct dentry *dir_sta[NX_REMOTE_STA_MAX];
|
||||
int rc_config[NX_REMOTE_STA_MAX];
|
||||
struct list_head rc_config_save;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
|
||||
// Max duration in msecs to save rate config for a sta after disconnection
|
||||
#define RC_CONFIG_DUR 600000
|
||||
|
||||
struct rwnx_rc_config_save {
|
||||
struct list_head list;
|
||||
unsigned long timestamp;
|
||||
int rate;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
};
|
||||
#endif
|
||||
|
||||
int rwnx_dbgfs_register(struct rwnx_hw *rwnx_hw, const char *name);
|
||||
void rwnx_dbgfs_unregister(struct rwnx_hw *rwnx_hw);
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
void rwnx_dbgfs_register_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta);
|
||||
void rwnx_dbgfs_unregister_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta);
|
||||
#endif
|
||||
#else
|
||||
|
||||
struct rwnx_debugfs {
|
||||
};
|
||||
|
||||
static inline int rwnx_dbgfs_register(struct rwnx_hw *rwnx_hw, const char *name) { return 0; }
|
||||
static inline void rwnx_dbgfs_unregister(struct rwnx_hw *rwnx_hw) {}
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
static inline void rwnx_dbgfs_register_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) {}
|
||||
static inline void rwnx_dbgfs_unregister_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) {}
|
||||
#endif
|
||||
#endif /* CONFIG_RWNX_DEBUGFS */
|
||||
|
||||
|
||||
#endif /* _RWNX_DEBUGFS_H_ */
|
||||
@@ -0,0 +1,803 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_defs.h
|
||||
*
|
||||
* @brief Main driver structure declarations for fullmac driver
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _RWNX_DEFS_H_
|
||||
#define _RWNX_DEFS_H_
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dmapool.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "rwnx_mod_params.h"
|
||||
#include "rwnx_debugfs.h"
|
||||
#include "rwnx_tx.h"
|
||||
#include "rwnx_rx.h"
|
||||
#include "rwnx_radar.h"
|
||||
#include "rwnx_utils.h"
|
||||
#include "rwnx_mu_group.h"
|
||||
#include "rwnx_platform.h"
|
||||
#include "rwnx_cmds.h"
|
||||
#include "rwnx_compat.h"
|
||||
#ifdef CONFIG_FILTER_TCP_ACK
|
||||
#include "aicwf_tcp_ack.h"
|
||||
#endif
|
||||
|
||||
#ifdef AICWF_SDIO_SUPPORT
|
||||
#include "aicwf_sdio.h"
|
||||
#include "sdio_host.h"
|
||||
#endif
|
||||
|
||||
#ifdef AICWF_USB_SUPPORT
|
||||
#include "usb_host.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BR_SUPPORT
|
||||
#include "aic_br_ext.h"
|
||||
#endif /* CONFIG_BR_SUPPORT */
|
||||
|
||||
#define WPI_HDR_LEN 18
|
||||
#define WPI_PN_LEN 16
|
||||
#define WPI_PN_OFST 2
|
||||
#define WPI_MIC_LEN 16
|
||||
#define WPI_KEY_LEN 32
|
||||
#define WPI_SUBKEY_LEN 16 // WPI key is actually two 16bytes key
|
||||
|
||||
#define LEGACY_PS_ID 0
|
||||
#define UAPSD_ID 1
|
||||
|
||||
#define PS_SP_INTERRUPTED 255
|
||||
#define MAC_ADDR_LEN 6
|
||||
|
||||
//because android kernel 5.15 uses kernel 6.0 or 6.1 kernel api
|
||||
#ifdef ANDROID_PLATFORM
|
||||
#define HIGH_KERNEL_VERSION KERNEL_VERSION(5, 15, 41)
|
||||
#define HIGH_KERNEL_VERSION2 KERNEL_VERSION(5, 15, 41)
|
||||
#define HIGH_KERNEL_VERSION3 KERNEL_VERSION(5, 15, 104)
|
||||
#define HIGH_KERNEL_VERSION4 KERNEL_VERSION(6, 1, 0)
|
||||
#else
|
||||
#define HIGH_KERNEL_VERSION KERNEL_VERSION(6, 0, 0)
|
||||
#define HIGH_KERNEL_VERSION2 KERNEL_VERSION(6, 1, 0)
|
||||
#define HIGH_KERNEL_VERSION3 KERNEL_VERSION(6, 3, 0)
|
||||
#define HIGH_KERNEL_VERSION4 KERNEL_VERSION(6, 3, 0)
|
||||
#endif
|
||||
|
||||
#ifndef IEEE80211_MAX_AMPDU_BUF
|
||||
#define IEEE80211_MAX_AMPDU_BUF 0x100
|
||||
#endif
|
||||
#ifndef IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB
|
||||
#define IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB 0x08
|
||||
#endif
|
||||
#ifndef IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB
|
||||
#define IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB 0x04
|
||||
#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 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,
|
||||
NL80211_AC_VI,
|
||||
NL80211_AC_BE,
|
||||
NL80211_AC_BK,
|
||||
NL80211_NUM_ACS
|
||||
};
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL)
|
||||
struct ieee80211_vht_operation {
|
||||
u8 vht_op_info_chwidth;
|
||||
u8 vht_op_info_chan_center_freq_seg1_idx;
|
||||
u8 vht_op_info_chan_center_freq_seg2_idx;
|
||||
__le16 vht_basic_mcs_set;
|
||||
} __packed;
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)
|
||||
#define NL80211_IFTYPE_P2P_DEVICE 10
|
||||
#define IEEE80211_RADIOTAP_AMPDU_STATUS 20
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL)
|
||||
#define IEEE80211_RADIOTAP_VHT 21
|
||||
#define IEEE80211_RADIOTAP_VHT_KNOWN_GI 0x0004
|
||||
#define IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH 0x0040
|
||||
|
||||
#define IEEE80211_RADIOTAP_VHT_FLAG_STBC 0x01
|
||||
#define IEEE80211_RADIOTAP_VHT_FLAG_SGI 0x04
|
||||
|
||||
#define NL80211_FEATURE_CELL_BASE_REG_HINTS 1 << 3
|
||||
#define NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL 1 << 4
|
||||
#define NL80211_FEATURE_SAE 1 << 5
|
||||
#define NL80211_FEATURE_LOW_PRIORITY_SCAN 1 << 6
|
||||
#define NL80211_FEATURE_SCAN_FLUSH 1 << 7
|
||||
#define NL80211_FEATURE_AP_SCAN 1 << 8
|
||||
#define NL80211_FEATURE_VIF_TXPOWER 1 << 9
|
||||
#define NL80211_FEATURE_NEED_OBSS_SCAN 1 << 10
|
||||
#define NL80211_FEATURE_P2P_GO_CTWIN 1 << 11
|
||||
#define NL80211_FEATURE_P2P_GO_OPPPS 1 << 12
|
||||
|
||||
/* 802.11ac VHT Capabilities */
|
||||
#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000
|
||||
#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001
|
||||
#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 0x00000002
|
||||
#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ 0x00000004
|
||||
#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ 0x00000008
|
||||
#define IEEE80211_VHT_CAP_RXLDPC 0x00000010
|
||||
#define IEEE80211_VHT_CAP_SHORT_GI_80 0x00000020
|
||||
#define IEEE80211_VHT_CAP_SHORT_GI_160 0x00000040
|
||||
#define IEEE80211_VHT_CAP_TXSTBC 0x00000080
|
||||
#define IEEE80211_VHT_CAP_RXSTBC_1 0x00000100
|
||||
#define IEEE80211_VHT_CAP_RXSTBC_2 0x00000200
|
||||
#define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300
|
||||
#define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400
|
||||
#define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800
|
||||
#define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000
|
||||
#define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX 0x00006000
|
||||
#define IEEE80211_VHT_CAP_SOUNDING_DIMENTION_MAX 0x00030000
|
||||
#define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000
|
||||
#define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000
|
||||
#define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000
|
||||
#define IEEE80211_VHT_CAP_HTC_VHT 0x00400000
|
||||
#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT 23
|
||||
#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK \
|
||||
(7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT)
|
||||
#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB 0x08000000
|
||||
#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB 0x0c000000
|
||||
#define IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN 0x10000000
|
||||
#define IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN 0x20000000
|
||||
|
||||
enum ieee80211_vht_mcs_support {
|
||||
IEEE80211_VHT_MCS_SUPPORT_0_7 = 0,
|
||||
IEEE80211_VHT_MCS_SUPPORT_0_8 = 1,
|
||||
IEEE80211_VHT_MCS_SUPPORT_0_9 = 2,
|
||||
IEEE80211_VHT_MCS_NOT_SUPPORTED = 3,
|
||||
};
|
||||
|
||||
enum nl80211_chan_width {
|
||||
NL80211_CHAN_WIDTH_20_NOHT,
|
||||
NL80211_CHAN_WIDTH_20,
|
||||
NL80211_CHAN_WIDTH_40,
|
||||
NL80211_CHAN_WIDTH_80,
|
||||
NL80211_CHAN_WIDTH_80P80,
|
||||
NL80211_CHAN_WIDTH_160,
|
||||
};
|
||||
|
||||
struct cfg80211_chan_def {
|
||||
struct ieee80211_channel *chan;
|
||||
enum nl80211_chan_width width;
|
||||
u32 center_freq1;
|
||||
u32 center_freq2;
|
||||
};
|
||||
|
||||
enum nl80211_mesh_power_mode {
|
||||
NL80211_MESH_POWER_UNKNOWN,
|
||||
NL80211_MESH_POWER_ACTIVE,
|
||||
NL80211_MESH_POWER_LIGHT_SLEEP,
|
||||
NL80211_MESH_POWER_DEEP_SLEEP,
|
||||
__NL80211_MESH_POWER_AFTER_LAST,
|
||||
NL80211_MESH_POWER_MAX = __NL80211_MESH_POWER_AFTER_LAST - 1
|
||||
};
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)
|
||||
#define NL80211_MESHCONF_POWER_MODE 26
|
||||
|
||||
/*
|
||||
* TDLS capabililites to be enabled in the 5th byte of the
|
||||
* @WLAN_EID_EXT_CAPABILITY information element
|
||||
*/
|
||||
#define WLAN_EXT_CAPA5_TDLS_ENABLED BIT(5)
|
||||
#define WLAN_EXT_CAPA5_TDLS_PROHIBITED BIT(6)
|
||||
|
||||
#define WLAN_EXT_CAPA8_OPMODE_NOTIF BIT(6)
|
||||
|
||||
/* TDLS specific payload type in the LLC/SNAP header */
|
||||
#define WLAN_TDLS_SNAP_RFTYPE 0x2
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* struct rwnx_bcn - Information of the beacon in used (AP mode)
|
||||
*
|
||||
* @head: head portion of beacon (before TIM IE)
|
||||
* @tail: tail portion of beacon (after TIM IE)
|
||||
* @ies: extra IEs (not used ?)
|
||||
* @head_len: length of head data
|
||||
* @tail_len: length of tail data
|
||||
* @ies_len: length of extra IEs data
|
||||
* @tim_len: length of TIM IE
|
||||
* @len: Total beacon len (head + tim + tail + extra)
|
||||
* @dtim: dtim period
|
||||
*/
|
||||
struct rwnx_bcn {
|
||||
u8 *head;
|
||||
u8 *tail;
|
||||
u8 *ies;
|
||||
size_t head_len;
|
||||
size_t tail_len;
|
||||
size_t ies_len;
|
||||
size_t tim_len;
|
||||
size_t len;
|
||||
u8 dtim;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rwnx_key - Key information
|
||||
*
|
||||
* @hw_idx: Idx of the key from hardware point of view
|
||||
*/
|
||||
struct rwnx_key {
|
||||
u8 hw_idx;
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure containing information about a Mesh Path
|
||||
*/
|
||||
struct rwnx_mesh_path {
|
||||
struct list_head list; /* For rwnx_vif.mesh_paths */
|
||||
u8 path_idx; /* Path Index */
|
||||
struct mac_addr tgt_mac_addr; /* Target MAC Address */
|
||||
struct rwnx_sta *p_nhop_sta; /* Pointer to the Next Hop STA */
|
||||
};
|
||||
|
||||
struct rwnx_mesh_proxy {
|
||||
struct list_head list; /* For rwnx_vif.mesh_proxy */
|
||||
struct mac_addr ext_sta_addr; /* Address of the External STA */
|
||||
struct mac_addr proxy_addr; /* Proxy MAC Address */
|
||||
bool local; /* Indicate if interface is a proxy for the device */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rwnx_csa - Information for CSA (Channel Switch Announcement)
|
||||
*
|
||||
* @vif: Pointer to the vif doing the CSA
|
||||
* @bcn: Beacon to use after CSA
|
||||
* @elem: IPC buffer to send the new beacon to the fw
|
||||
* @chandef: defines the channel to use after the switch
|
||||
* @count: Current csa counter
|
||||
* @status: Status of the CSA at fw level
|
||||
* @ch_idx: Index of the new channel context
|
||||
* @work: work scheduled at the end of CSA
|
||||
*/
|
||||
struct rwnx_csa {
|
||||
struct rwnx_vif *vif;
|
||||
struct rwnx_bcn bcn;
|
||||
struct rwnx_ipc_elem_var elem;
|
||||
struct cfg80211_chan_def chandef;
|
||||
int count;
|
||||
int status;
|
||||
int ch_idx;
|
||||
struct work_struct work;
|
||||
};
|
||||
|
||||
struct apm_probe_sta {
|
||||
u8 sta_mac_addr[6];
|
||||
u8 vif_idx;
|
||||
u64 probe_id;
|
||||
struct work_struct apmprobestaWork;
|
||||
struct workqueue_struct *apmprobesta_wq;
|
||||
};
|
||||
|
||||
/// Possible States of the TDLS link.
|
||||
enum tdls_status_tag {
|
||||
/// TDLS link is not active (no TDLS peer connected)
|
||||
TDLS_LINK_IDLE,
|
||||
/// TDLS Setup Request transmitted
|
||||
TDLS_SETUP_REQ_TX,
|
||||
/// TDLS Setup Response transmitted
|
||||
TDLS_SETUP_RSP_TX,
|
||||
/// TDLS link is active (TDLS peer connected)
|
||||
TDLS_LINK_ACTIVE,
|
||||
/// TDLS Max Number of states.
|
||||
TDLS_STATE_MAX
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure used to save information relative to the TDLS peer.
|
||||
* This is also linked within the rwnx_hw vifs list.
|
||||
*
|
||||
*/
|
||||
struct rwnx_tdls {
|
||||
bool active; /* Indicate if TDLS link is active */
|
||||
bool initiator; /* Indicate if TDLS peer is the TDLS initiator */
|
||||
bool chsw_en; /* Indicate if channel switch is enabled */
|
||||
u8 last_tid; /* TID of the latest MPDU transmitted over the
|
||||
TDLS direct link to the TDLS STA */
|
||||
u16 last_sn; /* Sequence number of the latest MPDU transmitted
|
||||
over the TDLS direct link to the TDLS STA */
|
||||
bool ps_on; /* Indicate if the power save is enabled on the
|
||||
TDLS STA */
|
||||
bool chsw_allowed; /* Indicate if TDLS channel switch is allowed */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* enum rwnx_ap_flags - AP flags
|
||||
*
|
||||
* @RWNX_AP_ISOLATE Isolate clients (i.e. Don't brige packets transmitted by
|
||||
* one client for another one)
|
||||
*/
|
||||
enum rwnx_ap_flags {
|
||||
RWNX_AP_ISOLATE = BIT(0),
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure used to save information relative to the managed interfaces.
|
||||
* This is also linked within the rwnx_hw vifs list.
|
||||
*
|
||||
*/
|
||||
struct rwnx_vif {
|
||||
struct list_head list;
|
||||
struct rwnx_hw *rwnx_hw;
|
||||
struct wireless_dev wdev;
|
||||
struct net_device *ndev;
|
||||
struct net_device_stats net_stats;
|
||||
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 */
|
||||
bool up; /* Indicate if associated netdev is up
|
||||
(i.e. Interface is created at fw level) */
|
||||
bool use_4addr; /* Should we use 4addresses mode */
|
||||
bool is_resending; /* Indicate if a frame is being resent on this interface */
|
||||
bool user_mpm; /* In case of Mesh Point VIF, indicate if MPM is handled by userspace */
|
||||
bool roc_tdls; /* Indicate if the ROC has been called by a
|
||||
TDLS station */
|
||||
u8 tdls_status; /* Status of the TDLS link */
|
||||
bool tdls_chsw_prohibited; /* Indicate if TDLS Channel Switch is prohibited */
|
||||
bool wep_enabled; /* 1 if WEP is enabled */
|
||||
bool wep_auth_err; /* 1 if auth status code is not supported auth alg when WEP enabled */
|
||||
enum nl80211_auth_type last_auth_type; /* Authentication type (algorithm) sent in the last connection
|
||||
when WEP enabled */
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
struct rwnx_sta *ap; /* Pointer to the peer STA entry allocated for
|
||||
the AP */
|
||||
struct rwnx_sta *tdls_sta; /* Pointer to the TDLS station */
|
||||
bool external_auth; /* Indicate if external authentication is in progress */
|
||||
u32 group_cipher_type;
|
||||
u32 paired_cipher_type;
|
||||
//connected network info start
|
||||
char ssid[33];//ssid max is 32, but this has one spare for '\0'
|
||||
int ssid_len;
|
||||
u8 bssid[ETH_ALEN];
|
||||
u32 conn_owner_nlportid;
|
||||
bool is_roam;
|
||||
//connected network info end
|
||||
} sta;
|
||||
struct
|
||||
{
|
||||
u16 flags; /* see rwnx_ap_flags */
|
||||
struct list_head sta_list; /* List of STA connected to the AP */
|
||||
struct rwnx_bcn bcn; /* beacon */
|
||||
u8 bcmc_index; /* Index of the BCMC sta to use */
|
||||
#if (defined CONFIG_HE_FOR_OLD_KERNEL) || (defined CONFIG_VHT_FOR_OLD_KERNEL)
|
||||
u8 aic_index;
|
||||
#endif
|
||||
struct rwnx_csa *csa;
|
||||
|
||||
struct list_head mpath_list; /* List of Mesh Paths used on this interface */
|
||||
struct list_head proxy_list; /* List of Proxies Information used on this interface */
|
||||
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 */
|
||||
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;
|
||||
struct
|
||||
{
|
||||
struct rwnx_vif *master; /* pointer on master interface */
|
||||
struct rwnx_sta *sta_4a;
|
||||
} ap_vlan;
|
||||
};
|
||||
|
||||
u8_l key_has_add;
|
||||
u8_l is_p2p_vif;
|
||||
struct apm_probe_sta sta_probe;
|
||||
|
||||
#ifdef CONFIG_BR_SUPPORT
|
||||
spinlock_t br_ext_lock;
|
||||
/* unsigned int macclone_completed; */
|
||||
struct nat25_network_db_entry *nethash[NAT25_HASH_SIZE];
|
||||
int pppoe_connection_in_progress;
|
||||
unsigned char pppoe_addr[MACADDRLEN];
|
||||
unsigned char scdb_mac[MACADDRLEN];
|
||||
unsigned char scdb_ip[4];
|
||||
struct nat25_network_db_entry *scdb_entry;
|
||||
unsigned char br_mac[MACADDRLEN];
|
||||
unsigned char br_ip[4];
|
||||
|
||||
struct br_ext_info ethBrExtInfo;
|
||||
#endif /* CONFIG_BR_SUPPORT */
|
||||
|
||||
};
|
||||
|
||||
#define RWNX_VIF_TYPE(rwnx_vif) (rwnx_vif->wdev.iftype)
|
||||
|
||||
/**
|
||||
* Structure used to store information relative to PS mode.
|
||||
*
|
||||
* @active: True when the sta is in PS mode.
|
||||
* If false, other values should be ignored
|
||||
* @pkt_ready: Number of packets buffered for the sta in drv's txq
|
||||
* (1 counter for Legacy PS and 1 for U-APSD)
|
||||
* @sp_cnt: Number of packets that remain to be pushed in the service period.
|
||||
* 0 means that no service period is in progress
|
||||
* (1 counter for Legacy PS and 1 for U-APSD)
|
||||
*/
|
||||
struct rwnx_sta_ps {
|
||||
bool active;
|
||||
u16 pkt_ready[2];
|
||||
u16 sp_cnt[2];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rwnx_rx_rate_stats - Store statistics for RX rates
|
||||
*
|
||||
* @table: Table indicating how many frame has been receive which each
|
||||
* rate index. Rate index is the same as the one used by RC algo for TX
|
||||
* @size: Size of the table array
|
||||
* @cpt: number of frames received
|
||||
*/
|
||||
struct rwnx_rx_rate_stats {
|
||||
int *table;
|
||||
int size;
|
||||
int cpt;
|
||||
int rate_cnt;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rwnx_sta_stats - Structure Used to store statistics specific to a STA
|
||||
*
|
||||
* @last_rx: Hardware vector of the last received frame
|
||||
* @rx_rate: Statistics of the received rates
|
||||
*/
|
||||
struct rwnx_sta_stats {
|
||||
//#ifdef CONFIG_RWNX_DEBUGFS
|
||||
struct hw_vect last_rx;
|
||||
struct rwnx_rx_rate_stats rx_rate;
|
||||
//#endif
|
||||
};
|
||||
|
||||
#if (defined CONFIG_HE_FOR_OLD_KERNEL) || (defined CONFIG_VHT_FOR_OLD_KERNEL)
|
||||
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 */
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Structure used to save information relative to the managed stations.
|
||||
*/
|
||||
struct rwnx_sta {
|
||||
struct list_head list;
|
||||
u16 aid; /* association ID */
|
||||
u8 sta_idx; /* Identifier of the station */
|
||||
u8 vif_idx; /* Identifier of the VIF (fw id) the station
|
||||
belongs to */
|
||||
u8 vlan_idx; /* Identifier of the VLAN VIF (fw id) the station
|
||||
belongs to (= vif_idx if no vlan in used) */
|
||||
enum nl80211_band band; /* Band */
|
||||
enum nl80211_chan_width width; /* Channel width */
|
||||
u16 center_freq; /* Center frequency */
|
||||
u32 center_freq1; /* Center frequency 1 */
|
||||
u32 center_freq2; /* Center frequency 2 */
|
||||
u8 ch_idx; /* Identifier of the channel
|
||||
context the station belongs to */
|
||||
bool qos; /* Flag indicating if the station
|
||||
supports QoS */
|
||||
u8 acm; /* Bitfield indicating which queues
|
||||
have AC mandatory */
|
||||
u16 uapsd_tids; /* Bitfield indicating which tids are subject to
|
||||
UAPSD */
|
||||
u8 mac_addr[ETH_ALEN]; /* MAC address of the station */
|
||||
struct rwnx_key key;
|
||||
bool valid; /* Flag indicating if the entry is valid */
|
||||
struct rwnx_sta_ps ps; /* Information when STA is in PS (AP only) */
|
||||
#ifdef CONFIG_RWNX_BFMER
|
||||
struct rwnx_bfmer_report *bfm_report; /* Beamforming report to be used for
|
||||
VHT TX Beamforming */
|
||||
#ifdef CONFIG_RWNX_MUMIMO_TX
|
||||
struct rwnx_sta_group_info group_info; /* MU grouping information for the STA */
|
||||
#endif /* CONFIG_RWNX_MUMIMO_TX */
|
||||
#endif /* CONFIG_RWNX_BFMER */
|
||||
|
||||
bool ht; /* Flag indicating if the station
|
||||
supports HT */
|
||||
bool vht; /* Flag indicating if the station
|
||||
supports VHT */
|
||||
u32 ac_param[AC_MAX]; /* EDCA parameters */
|
||||
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 */
|
||||
};
|
||||
|
||||
static inline const u8 *rwnx_sta_addr(struct rwnx_sta *rwnx_sta) {
|
||||
return rwnx_sta->mac_addr;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RWNX_SPLIT_TX_BUF
|
||||
struct rwnx_amsdu_stats {
|
||||
int done;
|
||||
int failed;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct rwnx_stats {
|
||||
int cfm_balance[NX_TXQ_CNT];
|
||||
unsigned long last_rx, last_tx; /* jiffies */
|
||||
int ampdus_tx[IEEE80211_MAX_AMPDU_BUF];
|
||||
int ampdus_rx[IEEE80211_MAX_AMPDU_BUF];
|
||||
int ampdus_rx_map[4];
|
||||
int ampdus_rx_miss;
|
||||
#ifdef CONFIG_RWNX_SPLIT_TX_BUF
|
||||
struct rwnx_amsdu_stats amsdus[NX_TX_PAYLOAD_MAX];
|
||||
#endif
|
||||
int amsdus_rx[64];
|
||||
};
|
||||
|
||||
struct rwnx_sec_phy_chan {
|
||||
u16 prim20_freq;
|
||||
u16 center_freq1;
|
||||
u16 center_freq2;
|
||||
enum nl80211_band band;
|
||||
u8 type;
|
||||
};
|
||||
|
||||
/* Structure that will contains all RoC information received from cfg80211 */
|
||||
struct rwnx_roc_elem {
|
||||
struct wireless_dev *wdev;
|
||||
struct ieee80211_channel *chan;
|
||||
unsigned int duration;
|
||||
/* Used to avoid call of CFG80211 callback upon expiration of RoC */
|
||||
bool mgmt_roc;
|
||||
/* Indicate if we have switch on the RoC channel */
|
||||
bool on_chan;
|
||||
};
|
||||
|
||||
/* Structure containing channel survey information received from MAC */
|
||||
struct rwnx_survey_info {
|
||||
// Filled
|
||||
u32 filled;
|
||||
// Amount of time in ms the radio spent on the channel
|
||||
u32 chan_time_ms;
|
||||
// Amount of time the primary channel was sensed busy
|
||||
u32 chan_time_busy_ms;
|
||||
// Noise in dbm
|
||||
s8 noise_dbm;
|
||||
};
|
||||
|
||||
#define RWNX_CH_NOT_SET 0xFF
|
||||
#define RWNX_INVALID_VIF 0xFF
|
||||
#define RWNX_INVALID_STA 0xFF
|
||||
|
||||
/* Structure containing channel context information */
|
||||
struct rwnx_chanctx {
|
||||
struct cfg80211_chan_def chan_def; /* channel description */
|
||||
u8 count; /* number of vif using this ctxt */
|
||||
};
|
||||
|
||||
/**
|
||||
* rwnx_phy_info - Phy information
|
||||
*
|
||||
* @phy_cnt: Number of phy interface
|
||||
* @cfg: Configuration send to firmware
|
||||
* @sec_chan: Channel configuration of the second phy interface (if phy_cnt > 1)
|
||||
* @limit_bw: Set to true to limit BW on requested channel. Only set to use
|
||||
* VHT with old radio that don't support 80MHz (deprecated)
|
||||
*/
|
||||
struct rwnx_phy_info {
|
||||
u8 cnt;
|
||||
struct phy_cfg_tag cfg;
|
||||
struct rwnx_sec_phy_chan sec_chan;
|
||||
bool limit_bw;
|
||||
};
|
||||
|
||||
/* rwnx driver status */
|
||||
|
||||
enum rwnx_drv_connect_status {
|
||||
RWNX_DRV_STATUS_DISCONNECTED = 0,
|
||||
RWNX_DRV_STATUS_DISCONNECTING,
|
||||
RWNX_DRV_STATUS_CONNECTING,
|
||||
RWNX_DRV_STATUS_CONNECTED,
|
||||
};
|
||||
|
||||
|
||||
struct sta_tx_flowctrl {
|
||||
atomic_t tx_pending_cnt;
|
||||
u8 flowctrl;
|
||||
};
|
||||
|
||||
struct rwnx_hw {
|
||||
struct rwnx_mod_params *mod_params;
|
||||
struct device *dev;
|
||||
#ifdef AICWF_SDIO_SUPPORT
|
||||
struct aic_sdio_dev *sdiodev;
|
||||
#endif
|
||||
#ifdef AICWF_USB_SUPPORT
|
||||
struct aic_usb_dev *usbdev;
|
||||
#endif
|
||||
struct wiphy *wiphy;
|
||||
struct list_head vifs;
|
||||
struct rwnx_vif *vif_table[NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX]; /* indexed with fw id */
|
||||
struct rwnx_sta sta_table[NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX];
|
||||
#ifdef CONFIG_HE_FOR_OLD_KERNEL
|
||||
struct aic_sta aic_table[NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX];
|
||||
#endif
|
||||
struct rwnx_survey_info survey[SCAN_CHANNEL_MAX];
|
||||
struct cfg80211_scan_request *scan_request;
|
||||
#ifdef CONFIG_SCHED_SCAN
|
||||
struct cfg80211_sched_scan_request *sched_scan_req;
|
||||
#endif
|
||||
struct rwnx_chanctx chanctx_table[NX_CHAN_CTXT_CNT];
|
||||
u8 cur_chanctx;
|
||||
|
||||
u8 monitor_vif; /* FW id of the monitor interface, RWNX_INVALID_VIF if no monitor vif at fw level */
|
||||
#ifdef CONFIG_FILTER_TCP_ACK
|
||||
/* tcp ack management */
|
||||
struct tcp_ack_manage ack_m;
|
||||
#endif
|
||||
/* RoC Management */
|
||||
struct rwnx_roc_elem *roc_elem; /* Information provided by cfg80211 in its remain on channel request */
|
||||
u32 roc_cookie_cnt; /* Counter used to identify RoC request sent by cfg80211 */
|
||||
|
||||
struct rwnx_cmd_mgr *cmd_mgr;
|
||||
|
||||
struct rwnx_plat *plat;
|
||||
|
||||
spinlock_t tx_lock;
|
||||
spinlock_t cb_lock;
|
||||
struct mutex mutex; /* per-device perimeter lock */
|
||||
|
||||
struct tasklet_struct task;
|
||||
struct mm_version_cfm version_cfm; /* Lower layers versions - obtained via MM_VERSION_REQ */
|
||||
|
||||
u32 tcp_pacing_shift;
|
||||
|
||||
/* IPC */
|
||||
struct ipc_host_env_tag *ipc_env;
|
||||
#ifdef AICWF_SDIO_SUPPORT
|
||||
struct sdio_host_env_tag sdio_env;
|
||||
#endif
|
||||
#ifdef AICWF_USB_SUPPORT
|
||||
struct usb_host_env_tag usb_env;
|
||||
#endif
|
||||
|
||||
struct rwnx_ipc_elem_pool e2amsgs_pool;
|
||||
struct rwnx_ipc_elem_pool dbgmsgs_pool;
|
||||
struct rwnx_ipc_elem_pool e2aradars_pool;
|
||||
struct rwnx_ipc_elem_var pattern_elem;
|
||||
struct rwnx_ipc_dbgdump_elem dbgdump_elem;
|
||||
struct rwnx_ipc_elem_pool e2arxdesc_pool;
|
||||
struct rwnx_ipc_skb_elem *e2aunsuprxvec_elems;
|
||||
//struct rwnx_ipc_rxbuf_elems rxbuf_elems;
|
||||
struct rwnx_ipc_elem_var scan_ie;
|
||||
|
||||
struct kmem_cache *sw_txhdr_cache;
|
||||
|
||||
struct rwnx_debugfs debugfs;
|
||||
struct rwnx_stats stats;
|
||||
|
||||
#ifdef CONFIG_PREALLOC_TXQ
|
||||
struct rwnx_txq *txq;
|
||||
#else
|
||||
struct rwnx_txq txq[NX_NB_TXQ];
|
||||
#endif
|
||||
struct rwnx_hwq hwq[NX_TXQ_CNT];
|
||||
|
||||
u64 avail_idx_map;
|
||||
u8 vif_started;
|
||||
bool adding_sta;
|
||||
struct rwnx_phy_info phy;
|
||||
|
||||
struct rwnx_radar radar;
|
||||
|
||||
/* extended capabilities supported */
|
||||
u8 ext_capa[8];
|
||||
|
||||
#ifdef CONFIG_RWNX_MUMIMO_TX
|
||||
struct rwnx_mu_info mu;
|
||||
#endif
|
||||
u8 is_p2p_alive;
|
||||
u8 is_p2p_connected;
|
||||
struct timer_list p2p_alive_timer;
|
||||
struct rwnx_vif *p2p_dev_vif;
|
||||
atomic_t p2p_alive_timer_count;
|
||||
bool band_5g_support;
|
||||
bool fwlog_en;
|
||||
bool scanning;
|
||||
bool p2p_working;
|
||||
|
||||
struct work_struct apmStalossWork;
|
||||
struct workqueue_struct *apmStaloss_wq;
|
||||
u8 apm_vif_idx;
|
||||
u8 sta_mac_addr[6];
|
||||
#ifdef CONFIG_SCHED_SCAN
|
||||
bool is_sched_scan;
|
||||
#endif//CONFIG_SCHED_SCAN
|
||||
|
||||
struct sta_tx_flowctrl sta_flowctrl[NX_REMOTE_STA_MAX];
|
||||
#if 0
|
||||
bool he_flag;
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
|
||||
struct mac_chan_op ap_chan;
|
||||
struct ieee80211_channel set_chan;
|
||||
#endif
|
||||
#ifdef CONFIG_VHT_FOR_OLD_KERNEL
|
||||
struct ieee80211_sta_vht_cap vht_cap_2G;
|
||||
struct ieee80211_sta_vht_cap vht_cap_5G;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USE_WIRELESS_EXT
|
||||
bool wext_scan;
|
||||
struct completion wext_scan_com;
|
||||
struct list_head wext_scanre_list;
|
||||
char wext_essid[32];
|
||||
int support_freqs[SCAN_CHANNEL_MAX];
|
||||
int support_freqs_number;
|
||||
#endif
|
||||
};
|
||||
|
||||
u8 *rwnx_build_bcn(struct rwnx_bcn *bcn, struct cfg80211_beacon_data *new);
|
||||
|
||||
void rwnx_chanctx_link(struct rwnx_vif *vif, u8 idx,
|
||||
struct cfg80211_chan_def *chandef);
|
||||
void rwnx_chanctx_unlink(struct rwnx_vif *vif);
|
||||
int rwnx_chanctx_valid(struct rwnx_hw *rwnx_hw, u8 idx);
|
||||
|
||||
extern u8 chip_id;
|
||||
static inline bool is_multicast_sta(int sta_idx)
|
||||
{
|
||||
|
||||
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)){
|
||||
return (sta_idx >= NX_REMOTE_STA_MAX_FOR_OLD_IC);
|
||||
}else{
|
||||
return (sta_idx >= NX_REMOTE_STA_MAX);
|
||||
}
|
||||
|
||||
}
|
||||
struct rwnx_sta *rwnx_get_sta(struct rwnx_hw *rwnx_hw, const u8 *mac_addr);
|
||||
|
||||
static inline uint8_t master_vif_idx(struct rwnx_vif *vif)
|
||||
{
|
||||
if (unlikely(vif->wdev.iftype == NL80211_IFTYPE_AP_VLAN)) {
|
||||
return vif->ap_vlan.master->vif_index;
|
||||
} else {
|
||||
return vif->vif_index;
|
||||
}
|
||||
}
|
||||
|
||||
void rwnx_external_auth_enable(struct rwnx_vif *vif);
|
||||
void rwnx_external_auth_disable(struct rwnx_vif *vif);
|
||||
|
||||
#endif /* _RWNX_DEFS_H_ */
|
||||
@@ -0,0 +1,294 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_dini.c - Add support for dini platform
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "rwnx_dini.h"
|
||||
#include "rwnx_defs.h"
|
||||
#include "rwnx_irqs.h"
|
||||
#include "reg_access.h"
|
||||
|
||||
/* Config FPGA is accessed via bar0 */
|
||||
#define CFPGA_DMA0_CTRL_REG 0x02C
|
||||
#define CFPGA_DMA1_CTRL_REG 0x04C
|
||||
#define CFPGA_DMA2_CTRL_REG 0x06C
|
||||
#define CFPGA_UINTR_SRC_REG 0x0E8
|
||||
#define CFPGA_UINTR_MASK_REG 0x0EC
|
||||
#define CFPGA_BAR4_HIADDR_REG 0x100
|
||||
#define CFPGA_BAR4_LOADDR_REG 0x104
|
||||
#define CFPGA_BAR4_LOADDR_MASK_REG 0x110
|
||||
#define CFPGA_BAR_TOUT 0x120
|
||||
|
||||
#define CFPGA_DMA_CTRL_ENABLE 0x00001400
|
||||
#define CFPGA_DMA_CTRL_DISABLE 0x00001000
|
||||
#define CFPGA_DMA_CTRL_CLEAR 0x00001800
|
||||
#define CFPGA_DMA_CTRL_REREAD_TIME_MASK (BIT(10) - 1)
|
||||
|
||||
#define CFPGA_BAR4_LOADDR_MASK_MAX 0xFF000000
|
||||
|
||||
#define CFPGA_PCIEX_IT 0x00000001
|
||||
#define CFPGA_ALL_ITS 0x0000000F
|
||||
|
||||
/* Programmable BAR4 Window start address */
|
||||
#define CPU_RAM_WINDOW_HIGH 0x00000000
|
||||
#define CPU_RAM_WINDOW_LOW 0x00000000
|
||||
#define AHB_BRIDGE_WINDOW_HIGH 0x00000000
|
||||
#define AHB_BRIDGE_WINDOW_LOW 0x60000000
|
||||
|
||||
struct rwnx_dini
|
||||
{
|
||||
u8 *pci_bar0_vaddr;
|
||||
u8 *pci_bar4_vaddr;
|
||||
};
|
||||
|
||||
static const u32 mv_cfg_fpga_dma_ctrl_regs[] = {
|
||||
CFPGA_DMA0_CTRL_REG,
|
||||
CFPGA_DMA1_CTRL_REG,
|
||||
CFPGA_DMA2_CTRL_REG
|
||||
};
|
||||
|
||||
/* This also clears running transactions */
|
||||
static void dini_dma_on(struct rwnx_dini *rwnx_dini)
|
||||
{
|
||||
int i;
|
||||
u32 reread_time;
|
||||
volatile void *reg;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mv_cfg_fpga_dma_ctrl_regs); i++) {
|
||||
reg = rwnx_dini->pci_bar0_vaddr + mv_cfg_fpga_dma_ctrl_regs[i];
|
||||
reread_time = readl(reg) & CFPGA_DMA_CTRL_REREAD_TIME_MASK;
|
||||
|
||||
writel(CFPGA_DMA_CTRL_CLEAR | reread_time, reg);
|
||||
writel(CFPGA_DMA_CTRL_ENABLE | reread_time, reg);
|
||||
}
|
||||
}
|
||||
|
||||
/* This also clears running transactions */
|
||||
static void dini_dma_off(struct rwnx_dini *rwnx_dini)
|
||||
{
|
||||
int i;
|
||||
u32 reread_time;
|
||||
volatile void *reg;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mv_cfg_fpga_dma_ctrl_regs); i++) {
|
||||
reg = rwnx_dini->pci_bar0_vaddr + mv_cfg_fpga_dma_ctrl_regs[i];
|
||||
reread_time = readl(reg) & CFPGA_DMA_CTRL_REREAD_TIME_MASK;
|
||||
|
||||
writel(CFPGA_DMA_CTRL_DISABLE | reread_time, reg);
|
||||
writel(CFPGA_DMA_CTRL_CLEAR | reread_time, reg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Configure address range for BAR4.
|
||||
* By default BAR4_LOADDR_MASK value is 0xFF000000, then there is no need to
|
||||
* change it because the addresses we need to access are covered by this mask
|
||||
*/
|
||||
static void dini_set_bar4_win(u32 low, u32 high, struct rwnx_dini *rwnx_dini)
|
||||
{
|
||||
writel(low, rwnx_dini->pci_bar0_vaddr + CFPGA_BAR4_LOADDR_REG);
|
||||
writel(high, rwnx_dini->pci_bar0_vaddr + CFPGA_BAR4_HIADDR_REG);
|
||||
writel(CFPGA_BAR4_LOADDR_MASK_MAX,
|
||||
rwnx_dini->pci_bar0_vaddr + CFPGA_BAR4_LOADDR_MASK_REG);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable User Interrupts of CFPGA that trigger PCIe IRQs on PCIE_10
|
||||
* and request the corresponding IRQ line
|
||||
*/
|
||||
int rwnx_cfpga_irq_enable(struct rwnx_hw *rwnx_hw)
|
||||
{
|
||||
struct rwnx_plat *rwnx_plat = rwnx_hw->plat;
|
||||
struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv;
|
||||
unsigned int cfpga_uintr_mask;
|
||||
volatile void *reg;
|
||||
int ret;
|
||||
|
||||
/* sched_setscheduler on ONESHOT threaded irq handler for BCNs ? */
|
||||
if ((ret = request_irq(rwnx_hw->plat->pci_dev->irq, rwnx_irq_hdlr, 0,
|
||||
"rwnx", rwnx_hw)))
|
||||
return ret;
|
||||
|
||||
reg = rwnx_dini->pci_bar0_vaddr + CFPGA_UINTR_MASK_REG;
|
||||
cfpga_uintr_mask = readl(reg);
|
||||
writel(cfpga_uintr_mask | CFPGA_PCIEX_IT, reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable User Interrupts of CFPGA that trigger PCIe IRQs on PCIE_10
|
||||
* and free the corresponding IRQ line
|
||||
*/
|
||||
int rwnx_cfpga_irq_disable(struct rwnx_hw *rwnx_hw)
|
||||
{
|
||||
struct rwnx_plat *rwnx_plat = rwnx_hw->plat;
|
||||
struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv;
|
||||
unsigned int cfpga_uintr_mask;
|
||||
volatile void *reg;
|
||||
|
||||
reg = rwnx_dini->pci_bar0_vaddr + CFPGA_UINTR_MASK_REG;
|
||||
cfpga_uintr_mask = readl(reg);
|
||||
writel(cfpga_uintr_mask & ~CFPGA_PCIEX_IT, reg);
|
||||
|
||||
free_irq(rwnx_hw->plat->pci_dev->irq, rwnx_hw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rwnx_dini_platform_enable(struct rwnx_hw *rwnx_hw)
|
||||
{
|
||||
struct rwnx_plat *rwnx_plat = rwnx_hw->plat;
|
||||
struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv;
|
||||
|
||||
#ifdef CONFIG_RWNX_SDM
|
||||
writel(0x0000FFFF, rwnx_dini->pci_bar0_vaddr + CFPGA_BAR_TOUT);
|
||||
#endif
|
||||
|
||||
dini_dma_on(rwnx_dini);
|
||||
return rwnx_cfpga_irq_enable(rwnx_hw);
|
||||
}
|
||||
|
||||
static int rwnx_dini_platform_disable(struct rwnx_hw *rwnx_hw)
|
||||
{
|
||||
struct rwnx_plat *rwnx_plat = rwnx_hw->plat;
|
||||
struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv;
|
||||
int ret;
|
||||
|
||||
ret = rwnx_cfpga_irq_disable(rwnx_hw);
|
||||
dini_dma_off(rwnx_dini);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rwnx_dini_platform_deinit(struct rwnx_plat *rwnx_plat)
|
||||
{
|
||||
struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv;
|
||||
|
||||
pci_disable_device(rwnx_plat->pci_dev);
|
||||
iounmap(rwnx_dini->pci_bar0_vaddr);
|
||||
iounmap(rwnx_dini->pci_bar4_vaddr);
|
||||
pci_release_regions(rwnx_plat->pci_dev);
|
||||
|
||||
kfree(rwnx_plat);
|
||||
}
|
||||
|
||||
static u8* rwnx_dini_get_address(struct rwnx_plat *rwnx_plat, int addr_name,
|
||||
unsigned int offset)
|
||||
{
|
||||
struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv;
|
||||
|
||||
if (WARN(addr_name >= RWNX_ADDR_MAX, "Invalid address %d", addr_name))
|
||||
return NULL;
|
||||
|
||||
if (addr_name == RWNX_ADDR_CPU)
|
||||
dini_set_bar4_win(CPU_RAM_WINDOW_LOW, CPU_RAM_WINDOW_HIGH, rwnx_dini);
|
||||
else
|
||||
dini_set_bar4_win(AHB_BRIDGE_WINDOW_LOW, AHB_BRIDGE_WINDOW_HIGH, rwnx_dini);
|
||||
|
||||
return rwnx_dini->pci_bar4_vaddr + offset;
|
||||
}
|
||||
|
||||
static void rwnx_dini_ack_irq(struct rwnx_plat *rwnx_plat)
|
||||
{
|
||||
struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv;
|
||||
|
||||
writel(CFPGA_ALL_ITS, rwnx_dini->pci_bar0_vaddr + CFPGA_UINTR_SRC_REG);
|
||||
}
|
||||
|
||||
static const u32 rwnx_dini_config_reg[] = {
|
||||
NXMAC_DEBUG_PORT_SEL_ADDR,
|
||||
SYSCTRL_DIAG_CONF_ADDR,
|
||||
RF_V6_DIAGPORT_CONF1_ADDR,
|
||||
RF_v6_PHYDIAG_CONF1_ADDR,
|
||||
};
|
||||
|
||||
static int rwnx_dini_get_config_reg(struct rwnx_plat *rwnx_plat, const u32 **list)
|
||||
{
|
||||
if (!list)
|
||||
return 0;
|
||||
|
||||
*list = rwnx_dini_config_reg;
|
||||
return ARRAY_SIZE(rwnx_dini_config_reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* rwnx_dini_platform_init - Initialize the DINI platform
|
||||
*
|
||||
* @pci_dev PCI device
|
||||
* @rwnx_plat Pointer on struct rwnx_stat * to be populated
|
||||
*
|
||||
* @return 0 on success, < 0 otherwise
|
||||
*
|
||||
* Allocate and initialize a rwnx_plat structure for the dini platform.
|
||||
*/
|
||||
int rwnx_dini_platform_init(struct pci_dev *pci_dev, struct rwnx_plat **rwnx_plat)
|
||||
{
|
||||
struct rwnx_dini *rwnx_dini;
|
||||
u16 pci_cmd;
|
||||
int ret = 0;
|
||||
|
||||
*rwnx_plat = kzalloc(sizeof(struct rwnx_plat) + sizeof(struct rwnx_dini),
|
||||
GFP_KERNEL);
|
||||
if (!*rwnx_plat)
|
||||
return -ENOMEM;
|
||||
|
||||
rwnx_dini = (struct rwnx_dini *)(*rwnx_plat)->priv;
|
||||
|
||||
/* Hotplug fixups */
|
||||
pci_read_config_word(pci_dev, PCI_COMMAND, &pci_cmd);
|
||||
pci_cmd |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
|
||||
pci_write_config_word(pci_dev, PCI_COMMAND, pci_cmd);
|
||||
pci_write_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES >> 2);
|
||||
|
||||
if ((ret = pci_enable_device(pci_dev))) {
|
||||
dev_err(&(pci_dev->dev), "pci_enable_device failed\n");
|
||||
goto out_enable;
|
||||
}
|
||||
|
||||
pci_set_master(pci_dev);
|
||||
|
||||
if ((ret = pci_request_regions(pci_dev, KBUILD_MODNAME))) {
|
||||
dev_err(&(pci_dev->dev), "pci_request_regions failed\n");
|
||||
goto out_request;
|
||||
}
|
||||
|
||||
if (!(rwnx_dini->pci_bar0_vaddr = (u8 *)pci_ioremap_bar(pci_dev, 0))) {
|
||||
dev_err(&(pci_dev->dev), "pci_ioremap_bar(%d) failed\n", 0);
|
||||
ret = -ENOMEM;
|
||||
goto out_bar0;
|
||||
}
|
||||
if (!(rwnx_dini->pci_bar4_vaddr = (u8 *)pci_ioremap_bar(pci_dev, 4))) {
|
||||
dev_err(&(pci_dev->dev), "pci_ioremap_bar(%d) failed\n", 4);
|
||||
ret = -ENOMEM;
|
||||
goto out_bar4;
|
||||
}
|
||||
|
||||
(*rwnx_plat)->enable = rwnx_dini_platform_enable;
|
||||
(*rwnx_plat)->disable = rwnx_dini_platform_disable;
|
||||
(*rwnx_plat)->deinit = rwnx_dini_platform_deinit;
|
||||
(*rwnx_plat)->get_address = rwnx_dini_get_address;
|
||||
(*rwnx_plat)->ack_irq = rwnx_dini_ack_irq;
|
||||
(*rwnx_plat)->get_config_reg = rwnx_dini_get_config_reg;
|
||||
|
||||
#ifdef CONFIG_RWNX_SDM
|
||||
writel(0x0000FFFF, rwnx_dini->pci_bar0_vaddr + CFPGA_BAR_TOUT);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
out_bar4:
|
||||
iounmap(rwnx_dini->pci_bar0_vaddr);
|
||||
out_bar0:
|
||||
pci_release_regions(pci_dev);
|
||||
out_request:
|
||||
pci_disable_device(pci_dev);
|
||||
out_enable:
|
||||
kfree(*rwnx_plat);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
****************************************************************************************
|
||||
*
|
||||
* @file rwnx_dini.h
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _RWNX_DINI_H_
|
||||
#define _RWNX_DINI_H_
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include "rwnx_platform.h"
|
||||
|
||||
int rwnx_dini_platform_init(struct pci_dev *pci_dev,
|
||||
struct rwnx_plat **rwnx_plat);
|
||||
|
||||
#endif /* _RWNX_DINI_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,568 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_fw_dump.c
|
||||
*
|
||||
* @brief Definition of debug fs entries to process fw dump
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
#include "rwnx_defs.h"
|
||||
#include "rwnx_debugfs.h"
|
||||
|
||||
static ssize_t rwnx_dbgfs_rhd_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rwnx_hw *priv = file->private_data;
|
||||
struct dbg_debug_dump_tag *dump = priv->dbgdump_elem.buf.addr;
|
||||
ssize_t read;
|
||||
|
||||
mutex_lock(&priv->dbgdump_elem.mutex);
|
||||
if (!priv->debugfs.trace_prst) {
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
read = simple_read_from_buffer(user_buf, count, ppos,
|
||||
dump->rhd_mem,
|
||||
dump->dbg_info.rhd_len);
|
||||
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return read;
|
||||
}
|
||||
|
||||
DEBUGFS_READ_FILE_OPS(rhd);
|
||||
|
||||
static ssize_t rwnx_dbgfs_rbd_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rwnx_hw *priv = file->private_data;
|
||||
struct dbg_debug_dump_tag *dump = priv->dbgdump_elem.buf.addr;
|
||||
ssize_t read;
|
||||
|
||||
mutex_lock(&priv->dbgdump_elem.mutex);
|
||||
if (!priv->debugfs.trace_prst) {
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
read = simple_read_from_buffer(user_buf, count, ppos,
|
||||
dump->rbd_mem,
|
||||
dump->dbg_info.rbd_len);
|
||||
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return read;
|
||||
}
|
||||
|
||||
DEBUGFS_READ_FILE_OPS(rbd);
|
||||
|
||||
static ssize_t rwnx_dbgfs_thdx_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos, int idx)
|
||||
{
|
||||
struct rwnx_hw *priv = file->private_data;
|
||||
struct dbg_debug_dump_tag *dump = priv->dbgdump_elem.buf.addr;
|
||||
ssize_t read;
|
||||
|
||||
mutex_lock(&priv->dbgdump_elem.mutex);
|
||||
if (!priv->debugfs.trace_prst) {
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
read = simple_read_from_buffer(user_buf, count, ppos,
|
||||
&dump->thd_mem[idx],
|
||||
dump->dbg_info.thd_len[idx]);
|
||||
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return read;
|
||||
}
|
||||
|
||||
static ssize_t rwnx_dbgfs_thd0_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return rwnx_dbgfs_thdx_read(file, user_buf, count, ppos, 0);
|
||||
}
|
||||
DEBUGFS_READ_FILE_OPS(thd0);
|
||||
|
||||
static ssize_t rwnx_dbgfs_thd1_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return rwnx_dbgfs_thdx_read(file, user_buf, count, ppos, 1);
|
||||
}
|
||||
DEBUGFS_READ_FILE_OPS(thd1);
|
||||
|
||||
static ssize_t rwnx_dbgfs_thd2_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return rwnx_dbgfs_thdx_read(file, user_buf, count, ppos, 2);
|
||||
}
|
||||
DEBUGFS_READ_FILE_OPS(thd2);
|
||||
|
||||
static ssize_t rwnx_dbgfs_thd3_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return rwnx_dbgfs_thdx_read(file, user_buf, count, ppos, 3);
|
||||
}
|
||||
DEBUGFS_READ_FILE_OPS(thd3);
|
||||
|
||||
#if (NX_TXQ_CNT == 5)
|
||||
static ssize_t rwnx_dbgfs_thd4_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return rwnx_dbgfs_thdx_read(file, user_buf, count, ppos, 4);
|
||||
}
|
||||
DEBUGFS_READ_FILE_OPS(thd4);
|
||||
#endif
|
||||
|
||||
static ssize_t rwnx_dbgfs_mactrace_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rwnx_hw *priv = file->private_data;
|
||||
struct dbg_debug_dump_tag *dump = priv->dbgdump_elem.buf.addr;
|
||||
ssize_t read;
|
||||
|
||||
mutex_lock(&priv->dbgdump_elem.mutex);
|
||||
if (!priv->debugfs.trace_prst) {
|
||||
char msg[64];
|
||||
|
||||
scnprintf(msg, sizeof(msg), "Force trigger\n");
|
||||
rwnx_dbgfs_trigger_fw_dump(priv, msg);
|
||||
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
read = simple_read_from_buffer(user_buf, count, ppos,
|
||||
dump->la_mem,
|
||||
dump->dbg_info.la_conf.trace_len);
|
||||
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
|
||||
return read;
|
||||
}
|
||||
DEBUGFS_READ_FILE_OPS(mactrace);
|
||||
|
||||
static ssize_t rwnx_dbgfs_macdiags_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rwnx_hw *priv = file->private_data;
|
||||
struct dbg_debug_dump_tag *dump = priv->dbgdump_elem.buf.addr;
|
||||
ssize_t read;
|
||||
|
||||
mutex_lock(&priv->dbgdump_elem.mutex);
|
||||
if (!priv->debugfs.trace_prst) {
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
read = simple_read_from_buffer(user_buf, count, ppos,
|
||||
dump->dbg_info.diags_mac,
|
||||
DBG_DIAGS_MAC_MAX * 2);
|
||||
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return read;
|
||||
}
|
||||
|
||||
DEBUGFS_READ_FILE_OPS(macdiags);
|
||||
|
||||
static ssize_t rwnx_dbgfs_phydiags_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rwnx_hw *priv = file->private_data;
|
||||
struct dbg_debug_dump_tag *dump = priv->dbgdump_elem.buf.addr;
|
||||
ssize_t read;
|
||||
|
||||
mutex_lock(&priv->dbgdump_elem.mutex);
|
||||
if (!priv->debugfs.trace_prst) {
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
read = simple_read_from_buffer(user_buf, count, ppos,
|
||||
dump->dbg_info.diags_phy,
|
||||
DBG_DIAGS_PHY_MAX * 2);
|
||||
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return read;
|
||||
}
|
||||
|
||||
DEBUGFS_READ_FILE_OPS(phydiags);
|
||||
|
||||
static ssize_t rwnx_dbgfs_hwdiags_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rwnx_hw *priv = file->private_data;
|
||||
struct dbg_debug_dump_tag *dump = priv->dbgdump_elem.buf.addr;
|
||||
char buf[16];
|
||||
int ret;
|
||||
|
||||
mutex_lock(&priv->dbgdump_elem.mutex);
|
||||
if (!priv->debugfs.trace_prst) {
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count),
|
||||
"%08X\n", dump->dbg_info.hw_diag);
|
||||
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, ret);
|
||||
}
|
||||
|
||||
DEBUGFS_READ_FILE_OPS(hwdiags);
|
||||
|
||||
static ssize_t rwnx_dbgfs_plfdiags_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rwnx_hw *priv = file->private_data;
|
||||
struct dbg_debug_dump_tag *dump = priv->dbgdump_elem.buf.addr;
|
||||
char buf[16];
|
||||
int ret;
|
||||
|
||||
mutex_lock(&priv->dbgdump_elem.mutex);
|
||||
if (!priv->debugfs.trace_prst) {
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count),
|
||||
"%08X\n", dump->dbg_info.la_conf.diag_conf);
|
||||
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, ret);
|
||||
}
|
||||
|
||||
DEBUGFS_READ_FILE_OPS(plfdiags);
|
||||
|
||||
static ssize_t rwnx_dbgfs_swdiags_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rwnx_hw *priv = file->private_data;
|
||||
struct dbg_debug_dump_tag *dump = priv->dbgdump_elem.buf.addr;
|
||||
ssize_t read;
|
||||
|
||||
mutex_lock(&priv->dbgdump_elem.mutex);
|
||||
if (!priv->debugfs.trace_prst) {
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
read = simple_read_from_buffer(user_buf, count, ppos,
|
||||
&dump->dbg_info.sw_diag,
|
||||
dump->dbg_info.sw_diag_len);
|
||||
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return read;
|
||||
}
|
||||
|
||||
DEBUGFS_READ_FILE_OPS(swdiags);
|
||||
|
||||
static ssize_t rwnx_dbgfs_error_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rwnx_hw *priv = file->private_data;
|
||||
struct dbg_debug_dump_tag *dump = priv->dbgdump_elem.buf.addr;
|
||||
ssize_t read;
|
||||
|
||||
mutex_lock(&priv->dbgdump_elem.mutex);
|
||||
if (!priv->debugfs.trace_prst) {
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
read = simple_read_from_buffer(user_buf, count, ppos,
|
||||
dump->dbg_info.error,
|
||||
strlen((char *)dump->dbg_info.error));
|
||||
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return read;
|
||||
}
|
||||
|
||||
DEBUGFS_READ_FILE_OPS(error);
|
||||
|
||||
static ssize_t rwnx_dbgfs_rxdesc_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rwnx_hw *priv = file->private_data;
|
||||
struct dbg_debug_dump_tag *dump = priv->dbgdump_elem.buf.addr;
|
||||
char buf[32];
|
||||
int ret;
|
||||
ssize_t read;
|
||||
|
||||
mutex_lock(&priv->dbgdump_elem.mutex);
|
||||
if (!priv->debugfs.trace_prst) {
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count),
|
||||
"%08X\n%08X\n", dump->dbg_info.rhd,
|
||||
dump->dbg_info.rbd);
|
||||
read = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
|
||||
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return read;
|
||||
}
|
||||
|
||||
DEBUGFS_READ_FILE_OPS(rxdesc);
|
||||
|
||||
static ssize_t rwnx_dbgfs_txdesc_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rwnx_hw *priv = file->private_data;
|
||||
struct dbg_debug_dump_tag *dump = priv->dbgdump_elem.buf.addr;
|
||||
char buf[64];
|
||||
int len = 0;
|
||||
int i;
|
||||
|
||||
mutex_lock(&priv->dbgdump_elem.mutex);
|
||||
if (!priv->debugfs.trace_prst) {
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < NX_TXQ_CNT; i++) {
|
||||
len += scnprintf(&buf[len], min_t(size_t, sizeof(buf) - len - 1, count),
|
||||
"%08X\n", dump->dbg_info.thd[i]);
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
DEBUGFS_READ_FILE_OPS(txdesc);
|
||||
|
||||
static ssize_t rwnx_dbgfs_macrxptr_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rwnx_hw *priv = file->private_data;
|
||||
struct dbg_debug_dump_tag *dump = priv->dbgdump_elem.buf.addr;
|
||||
ssize_t read;
|
||||
|
||||
mutex_lock(&priv->dbgdump_elem.mutex);
|
||||
if (!priv->debugfs.trace_prst) {
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
read = simple_read_from_buffer(user_buf, count, ppos,
|
||||
&dump->dbg_info.rhd_hw_ptr,
|
||||
2 * sizeof(dump->dbg_info.rhd_hw_ptr));
|
||||
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return read;
|
||||
}
|
||||
|
||||
DEBUGFS_READ_FILE_OPS(macrxptr);
|
||||
|
||||
static ssize_t rwnx_dbgfs_lamacconf_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rwnx_hw *priv = file->private_data;
|
||||
struct dbg_debug_dump_tag *dump = priv->dbgdump_elem.buf.addr;
|
||||
ssize_t read;
|
||||
|
||||
mutex_lock(&priv->dbgdump_elem.mutex);
|
||||
if (!priv->debugfs.trace_prst) {
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
read = simple_read_from_buffer(user_buf, count, ppos,
|
||||
dump->dbg_info.la_conf.conf,
|
||||
LA_CONF_LEN * 4);
|
||||
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return read;
|
||||
}
|
||||
DEBUGFS_READ_FILE_OPS(lamacconf);
|
||||
|
||||
static ssize_t rwnx_dbgfs_chaninfo_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rwnx_hw *priv = file->private_data;
|
||||
struct dbg_debug_dump_tag *dump = priv->dbgdump_elem.buf.addr;
|
||||
char buf[4 * 32];
|
||||
int ret;
|
||||
|
||||
mutex_lock(&priv->dbgdump_elem.mutex);
|
||||
if (!priv->debugfs.trace_prst) {
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count),
|
||||
"type: %d\n"
|
||||
"prim20_freq: %d MHz\n"
|
||||
"center1_freq: %d MHz\n"
|
||||
"center2_freq: %d MHz\n",
|
||||
(dump->dbg_info.chan_info.info1 >> 8) & 0xFF,
|
||||
(dump->dbg_info.chan_info.info1 >> 16) & 0xFFFF,
|
||||
(dump->dbg_info.chan_info.info2 >> 0) & 0xFFFF,
|
||||
(dump->dbg_info.chan_info.info2 >> 16) & 0xFFFF);
|
||||
|
||||
mutex_unlock(&priv->dbgdump_elem.mutex);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, ret);
|
||||
}
|
||||
|
||||
DEBUGFS_READ_FILE_OPS(chaninfo);
|
||||
|
||||
static ssize_t rwnx_dbgfs_um_helper_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rwnx_hw *priv = file->private_data;
|
||||
char buf[sizeof(priv->debugfs.helper_cmd)];
|
||||
int ret;
|
||||
|
||||
ret = scnprintf(buf, min_t(size_t, sizeof(buf) - 1, count),
|
||||
"%s", priv->debugfs.helper_cmd);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, ret);
|
||||
}
|
||||
|
||||
static ssize_t rwnx_dbgfs_um_helper_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct rwnx_hw *priv = file->private_data;
|
||||
int eobuf = min_t(size_t, sizeof(priv->debugfs.helper_cmd) - 1, count);
|
||||
|
||||
priv->debugfs.helper_cmd[eobuf] = '\0';
|
||||
if (copy_from_user(priv->debugfs.helper_cmd, user_buf, eobuf))
|
||||
return -EFAULT;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(um_helper);
|
||||
|
||||
/*
|
||||
* Calls a userspace pgm
|
||||
*/
|
||||
int rwnx_um_helper(struct rwnx_debugfs *rwnx_debugfs, const char *cmd)
|
||||
{
|
||||
char *envp[] = { "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
|
||||
char **argv;
|
||||
int argc, ret;
|
||||
|
||||
if (!rwnx_debugfs->dir ||
|
||||
!strlen((cmd = cmd ? cmd : rwnx_debugfs->helper_cmd)))
|
||||
return 0;
|
||||
argv = argv_split(in_interrupt() ? GFP_ATOMIC : GFP_KERNEL, cmd, &argc);
|
||||
if (!argc)
|
||||
return PTR_ERR(argv);
|
||||
|
||||
if ((ret = call_usermodehelper(argv[0], argv, envp,
|
||||
UMH_WAIT_PROC | UMH_KILLABLE)))
|
||||
printk(KERN_CRIT "Failed to call %s (%s returned %d)\n",
|
||||
argv[0], cmd, ret);
|
||||
argv_free(argv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rwnx_um_helper_work(struct work_struct *ws)
|
||||
{
|
||||
struct rwnx_debugfs *rwnx_debugfs = container_of(ws, struct rwnx_debugfs,
|
||||
helper_work);
|
||||
struct rwnx_hw *rwnx_hw = container_of(rwnx_debugfs, struct rwnx_hw,
|
||||
debugfs);
|
||||
rwnx_um_helper(rwnx_debugfs, NULL);
|
||||
if (!rwnx_debugfs->unregistering)
|
||||
rwnx_umh_done(rwnx_hw);
|
||||
rwnx_debugfs->helper_scheduled = false;
|
||||
}
|
||||
|
||||
int rwnx_trigger_um_helper(struct rwnx_debugfs *rwnx_debugfs)
|
||||
{
|
||||
struct rwnx_hw *rwnx_hw = container_of(rwnx_debugfs, struct rwnx_hw,
|
||||
debugfs);
|
||||
|
||||
if (rwnx_debugfs->helper_scheduled == true) {
|
||||
dev_err(rwnx_hw->dev, "%s: Already scheduled\n", __func__);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
spin_lock_bh(&rwnx_debugfs->umh_lock);
|
||||
if (rwnx_debugfs->unregistering) {
|
||||
spin_unlock_bh(&rwnx_debugfs->umh_lock);
|
||||
dev_err(rwnx_hw->dev, "%s: unregistering\n", __func__);
|
||||
return -ENOENT;
|
||||
}
|
||||
rwnx_debugfs->helper_scheduled = true;
|
||||
schedule_work(&rwnx_debugfs->helper_work);
|
||||
spin_unlock_bh(&rwnx_debugfs->umh_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rwnx_dbgfs_register_fw_dump(struct rwnx_hw *rwnx_hw,
|
||||
struct dentry *dir_drv,
|
||||
struct dentry *dir_diags)
|
||||
{
|
||||
|
||||
struct rwnx_debugfs *rwnx_debugfs = &rwnx_hw->debugfs;
|
||||
|
||||
BUILD_BUG_ON(sizeof(CONFIG_RWNX_UM_HELPER_DFLT) >=
|
||||
sizeof(rwnx_debugfs->helper_cmd));
|
||||
strncpy(rwnx_debugfs->helper_cmd,
|
||||
CONFIG_RWNX_UM_HELPER_DFLT, sizeof(rwnx_debugfs->helper_cmd));
|
||||
INIT_WORK(&rwnx_debugfs->helper_work, rwnx_um_helper_work);
|
||||
DEBUGFS_ADD_FILE(um_helper, dir_drv, S_IWUSR | S_IRUSR);
|
||||
|
||||
rwnx_debugfs->trace_prst = rwnx_debugfs->helper_scheduled = false;
|
||||
spin_lock_init(&rwnx_debugfs->umh_lock);
|
||||
DEBUGFS_ADD_FILE(rhd, dir_diags, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(rbd, dir_diags, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(thd0, dir_diags, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(thd1, dir_diags, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(thd2, dir_diags, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(thd3, dir_diags, S_IRUSR);
|
||||
#if (NX_TXQ_CNT == 5)
|
||||
DEBUGFS_ADD_FILE(thd4, dir_diags, S_IRUSR);
|
||||
#endif
|
||||
DEBUGFS_ADD_FILE(mactrace, dir_diags, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(macdiags, dir_diags, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(phydiags, dir_diags, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(plfdiags, dir_diags, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(hwdiags, dir_diags, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(swdiags, dir_diags, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(error, dir_diags, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(rxdesc, dir_diags, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(txdesc, dir_diags, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(macrxptr, dir_diags, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(lamacconf, dir_diags, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(chaninfo, dir_diags, S_IRUSR);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_fw_trace.c
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2017-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/delay.h>
|
||||
#include "rwnx_fw_trace.h"
|
||||
|
||||
int rwnx_fw_log_init(struct rwnx_fw_log *fw_log)
|
||||
{
|
||||
u8 *buf = kmalloc(FW_LOG_SIZE, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
fw_log->buf.data = buf;
|
||||
fw_log->buf.start = fw_log->buf.data;
|
||||
fw_log->buf.size = 0;
|
||||
fw_log->buf.end = fw_log->buf.data;
|
||||
fw_log->buf.dataend = fw_log->buf.data + FW_LOG_SIZE;
|
||||
spin_lock_init(&fw_log->lock);
|
||||
|
||||
printk("fw_log_init: %lx, %lx\n", (unsigned long)fw_log->buf.start, (unsigned long)(fw_log->buf.dataend));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rwnx_fw_log_deinit(struct rwnx_fw_log *fw_log)
|
||||
{
|
||||
if (!fw_log)
|
||||
return;
|
||||
|
||||
if (fw_log->buf.data)
|
||||
kfree(fw_log->buf.data);
|
||||
fw_log->buf.start = NULL;
|
||||
fw_log->buf.end = NULL;
|
||||
fw_log->buf.size = 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* rwnx_fw_trace.h
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2017-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _RWNX_FW_TRACE_H_
|
||||
#define _RWNX_FW_TRACE_H_
|
||||
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#define FW_LOG_SIZE (10240)
|
||||
|
||||
struct rwnx_fw_log_buf {
|
||||
uint8_t *data;
|
||||
uint8_t *start;
|
||||
uint8_t *end;
|
||||
uint8_t *dataend;
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
struct rwnx_fw_log {
|
||||
struct rwnx_fw_log_buf buf;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
int rwnx_fw_log_init(struct rwnx_fw_log *fw_log);
|
||||
void rwnx_fw_log_deinit(struct rwnx_fw_log *fw_log);
|
||||
#endif /* _RWNX_FW_TRACE_H_ */
|
||||
@@ -0,0 +1,18 @@
|
||||
#include <linux/version.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
|
||||
void rwnx_gki_skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct sk_buff *prev = old;
|
||||
struct sk_buff *next = prev->next;
|
||||
spin_lock_irqsave(&list->lock, flags);
|
||||
WRITE_ONCE(newsk->next, next);
|
||||
WRITE_ONCE(newsk->prev, prev);
|
||||
WRITE_ONCE(next->prev, newsk);
|
||||
WRITE_ONCE(prev->next, newsk);
|
||||
list->qlen++;
|
||||
spin_unlock_irqrestore(&list->lock, flags);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef __RWNX_GKI_H
|
||||
#define __RWNX_GKI_H
|
||||
|
||||
#ifdef CONFIG_GKI
|
||||
void rwnx_gki_skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list);
|
||||
#define rwnx_skb_append rwnx_gki_skb_append
|
||||
#else
|
||||
#define rwnx_skb_append skb_append
|
||||
#endif//CONFIG_GKI
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_irqs.c
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include "rwnx_defs.h"
|
||||
#include "ipc_host.h"
|
||||
#include "rwnx_prof.h"
|
||||
|
||||
/**
|
||||
* rwnx_irq_hdlr - IRQ handler
|
||||
*
|
||||
* Handler registerd by the platform driver
|
||||
*/
|
||||
irqreturn_t rwnx_irq_hdlr(int irq, void *dev_id)
|
||||
{
|
||||
struct rwnx_hw *rwnx_hw = (struct rwnx_hw *)dev_id;
|
||||
disable_irq_nosync(irq);
|
||||
tasklet_schedule(&rwnx_hw->task);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* rwnx_task - Bottom half for IRQ handler
|
||||
*
|
||||
* Read irq status and process accordingly
|
||||
*/
|
||||
void rwnx_task(unsigned long data)
|
||||
{
|
||||
struct rwnx_hw *rwnx_hw = (struct rwnx_hw *)data;
|
||||
REG_SW_SET_PROFILING(rwnx_hw, SW_PROF_RWNX_IPC_IRQ_HDLR);
|
||||
|
||||
#if 0
|
||||
struct rwnx_plat *rwnx_plat = rwnx_hw->plat;
|
||||
u32 status, statuses = 0;
|
||||
|
||||
/* Ack unconditionnally in case ipc_host_get_status does not see the irq */
|
||||
rwnx_plat->ack_irq(rwnx_plat);
|
||||
|
||||
while ((status = ipc_host_get_status(rwnx_hw->ipc_env))) {
|
||||
statuses |= status;
|
||||
/* All kinds of IRQs will be handled in one shot (RX, MSG, DBG, ...)
|
||||
* this will ack IPC irqs not the cfpga irqs */
|
||||
ipc_host_irq(rwnx_hw->ipc_env, status);
|
||||
|
||||
rwnx_plat->ack_irq(rwnx_plat);
|
||||
}
|
||||
#endif
|
||||
//if (statuses & IPC_IRQ_E2A_RXDESC)
|
||||
// rwnx_hw->stats.last_rx = now;
|
||||
//if (statuses & IPC_IRQ_E2A_TXCFM)
|
||||
// rwnx_hw->stats.last_tx = now;
|
||||
AICWFDBG(LOGTRACE, "rwnx_task\n");
|
||||
spin_lock_bh(&rwnx_hw->tx_lock);
|
||||
rwnx_hwq_process_all(rwnx_hw);
|
||||
spin_unlock_bh(&rwnx_hw->tx_lock);
|
||||
#if 0
|
||||
enable_irq(rwnx_platform_get_irq(rwnx_plat));
|
||||
#endif
|
||||
REG_SW_CLEAR_PROFILING(rwnx_hw, SW_PROF_RWNX_IPC_IRQ_HDLR);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_irqs.h
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#ifndef _RWNX_IRQS_H_
|
||||
#define _RWNX_IRQS_H_
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
/* IRQ handler to be registered by platform driver */
|
||||
irqreturn_t rwnx_irq_hdlr(int irq, void *dev_id);
|
||||
|
||||
void rwnx_task(unsigned long data);
|
||||
|
||||
#endif /* _RWNX_IRQS_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_main.h
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _RWNX_MAIN_H_
|
||||
#define _RWNX_MAIN_H_
|
||||
|
||||
#include "rwnx_defs.h"
|
||||
|
||||
int rwnx_cfg80211_init(struct rwnx_plat *rwnx_plat, void **platform_data);
|
||||
void rwnx_cfg80211_deinit(struct rwnx_hw *rwnx_hw);
|
||||
extern int testmode;
|
||||
extern u8 chip_id;
|
||||
extern u8 chip_sub_id;
|
||||
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)
|
||||
|
||||
#endif /* _RWNX_MAIN_H_ */
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
****************************************************************************************
|
||||
*
|
||||
* @file rwnx_mesh.c
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2016-2019
|
||||
*
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* INCLUDE FILES
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
#include "rwnx_mesh.h"
|
||||
|
||||
/**
|
||||
* FUNCTION DEFINITIONS
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
struct rwnx_mesh_proxy *rwnx_get_mesh_proxy_info(struct rwnx_vif *p_rwnx_vif, u8 *p_sta_addr, bool local)
|
||||
{
|
||||
struct rwnx_mesh_proxy *p_mesh_proxy = NULL;
|
||||
struct rwnx_mesh_proxy *p_cur_proxy;
|
||||
|
||||
/* Look for proxied devices with provided address */
|
||||
list_for_each_entry(p_cur_proxy, &p_rwnx_vif->ap.proxy_list, list) {
|
||||
if (p_cur_proxy->local != local) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!memcmp(&p_cur_proxy->ext_sta_addr, p_sta_addr, ETH_ALEN)) {
|
||||
p_mesh_proxy = p_cur_proxy;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the found information */
|
||||
return p_mesh_proxy;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
****************************************************************************************
|
||||
*
|
||||
* @file rwnx_mesh.h
|
||||
*
|
||||
* @brief VHT Beamformer function declarations
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2016-2019
|
||||
*
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _RWNX_MESH_H_
|
||||
#define _RWNX_MESH_H_
|
||||
|
||||
/**
|
||||
* INCLUDE FILES
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
#include "rwnx_defs.h"
|
||||
|
||||
/**
|
||||
* DEFINES
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* TYPE DEFINITIONS
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* FUNCTION DECLARATIONS
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
****************************************************************************************
|
||||
* @brief TODO [LT]
|
||||
****************************************************************************************
|
||||
*/
|
||||
struct rwnx_mesh_proxy *rwnx_get_mesh_proxy_info(struct rwnx_vif *p_rwnx_vif, u8 *p_sta_addr, bool local);
|
||||
|
||||
#endif /* _RWNX_MESH_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_mod_params.h
|
||||
*
|
||||
* @brief Declaration of module parameters
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _RWNX_MOD_PARAM_H_
|
||||
#define _RWNX_MOD_PARAM_H_
|
||||
|
||||
struct rwnx_mod_params {
|
||||
bool ht_on;
|
||||
bool vht_on;
|
||||
bool he_on;
|
||||
int mcs_map;
|
||||
int he_mcs_map;
|
||||
bool he_ul_on;
|
||||
bool ldpc_on;
|
||||
bool stbc_on;
|
||||
bool gf_rx_on;
|
||||
int phy_cfg;
|
||||
int uapsd_timeout;
|
||||
bool ap_uapsd_on;
|
||||
bool sgi;
|
||||
bool sgi80;
|
||||
bool use_2040;
|
||||
bool use_80;
|
||||
bool custregd;
|
||||
bool custchan;
|
||||
int nss;
|
||||
int amsdu_rx_max;
|
||||
bool bfmee;
|
||||
bool bfmer;
|
||||
bool mesh;
|
||||
bool murx;
|
||||
bool mutx;
|
||||
bool mutx_on;
|
||||
unsigned int roc_dur_max;
|
||||
int listen_itv;
|
||||
bool listen_bcmc;
|
||||
int lp_clk_ppm;
|
||||
bool ps_on;
|
||||
int tx_lft;
|
||||
int amsdu_maxnb;
|
||||
int uapsd_queues;
|
||||
bool tdls;
|
||||
bool uf;
|
||||
bool auto_reply;
|
||||
char *ftl;
|
||||
bool dpsm;
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
bool ant_div;
|
||||
#endif /* CONFIG_RWNX_FULLMAC */
|
||||
};
|
||||
|
||||
extern struct rwnx_mod_params rwnx_mod_params;
|
||||
|
||||
struct rwnx_hw;
|
||||
struct wiphy;
|
||||
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);
|
||||
|
||||
#endif /* _RWNX_MOD_PARAM_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
****************************************************************************************
|
||||
*
|
||||
* @file rwnx_msg_rx.h
|
||||
*
|
||||
* @brief RX function declarations
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _RWNX_MSG_RX_H_
|
||||
#define _RWNX_MSG_RX_H_
|
||||
|
||||
void rwnx_rx_handle_msg(struct rwnx_hw *rwnx_hw, struct ipc_e2a_msg *msg);
|
||||
void rwnx_rx_handle_print(struct rwnx_hw *rwnx_hw, u8 *msg, u32 len);
|
||||
|
||||
#endif /* _RWNX_MSG_RX_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,187 @@
|
||||
/**
|
||||
****************************************************************************************
|
||||
*
|
||||
* @file rwnx_msg_tx.h
|
||||
*
|
||||
* @brief TX function declarations
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _RWNX_MSG_TX_H_
|
||||
#define _RWNX_MSG_TX_H_
|
||||
|
||||
#include "rwnx_defs.h"
|
||||
|
||||
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);
|
||||
int rwnx_send_add_if(struct rwnx_hw *rwnx_hw, const unsigned char *mac,
|
||||
enum nl80211_iftype iftype, bool p2p, struct mm_add_if_cfm *cfm);
|
||||
int rwnx_send_remove_if(struct rwnx_hw *rwnx_hw, u8 vif_index, bool defer);
|
||||
int rwnx_send_set_channel(struct rwnx_hw *rwnx_hw, int phy_idx,
|
||||
struct mm_set_channel_cfm *cfm);
|
||||
int rwnx_send_key_add(struct rwnx_hw *rwnx_hw, u8 vif_idx, u8 sta_idx, bool pairwise,
|
||||
u8 *key, u8 key_len, u8 key_idx, u8 cipher_suite,
|
||||
struct mm_key_add_cfm *cfm);
|
||||
int rwnx_send_key_del(struct rwnx_hw *rwnx_hw, uint8_t hw_key_idx);
|
||||
int rwnx_send_bcn(struct rwnx_hw *rwnx_hw,u8 *buf, u8 vif_idx, u16 bcn_len);
|
||||
|
||||
int rwnx_send_bcn_change(struct rwnx_hw *rwnx_hw, u8 vif_idx, u32 bcn_addr,
|
||||
u16 bcn_len, u16 tim_oft, u16 tim_len, u16 *csa_oft);
|
||||
int rwnx_send_tim_update(struct rwnx_hw *rwnx_hw, u8 vif_idx, u16 aid,
|
||||
u8 tx_status);
|
||||
int rwnx_send_roc(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif,
|
||||
struct ieee80211_channel *chan, unsigned int duration, struct mm_remain_on_channel_cfm *roc_cfm);
|
||||
int rwnx_send_cancel_roc(struct rwnx_hw *rwnx_hw);
|
||||
int rwnx_send_set_power(struct rwnx_hw *rwnx_hw, u8 vif_idx, s8 pwr,
|
||||
struct mm_set_power_cfm *cfm);
|
||||
int rwnx_send_set_edca(struct rwnx_hw *rwnx_hw, u8 hw_queue, u32 param,
|
||||
bool uapsd, u8 inst_nbr);
|
||||
int rwnx_send_tdls_chan_switch_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif,
|
||||
struct rwnx_sta *rwnx_sta, bool sta_initiator,
|
||||
u8 oper_class, struct cfg80211_chan_def *chandef,
|
||||
struct tdls_chan_switch_cfm *cfm);
|
||||
int rwnx_send_tdls_cancel_chan_switch_req(struct rwnx_hw *rwnx_hw,
|
||||
struct rwnx_vif *rwnx_vif,
|
||||
struct rwnx_sta *rwnx_sta,
|
||||
struct tdls_cancel_chan_switch_cfm *cfm);
|
||||
|
||||
#ifdef CONFIG_RWNX_P2P_DEBUGFS
|
||||
int rwnx_send_p2p_oppps_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif,
|
||||
u8 ctw, struct mm_set_p2p_oppps_cfm *cfm);
|
||||
int rwnx_send_p2p_noa_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif,
|
||||
int count, int interval, int duration,
|
||||
bool dyn_noa, struct mm_set_p2p_noa_cfm *cfm);
|
||||
#endif /* CONFIG_RWNX_P2P_DEBUGFS */
|
||||
|
||||
#ifdef AICWF_ARP_OFFLOAD
|
||||
int rwnx_send_arpoffload_en_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif,
|
||||
u32_l ipaddr, u8_l enable);
|
||||
#endif
|
||||
int rwnx_send_rf_config_req(struct rwnx_hw *rwnx_hw, u8_l ofst, u8_l sel, u8_l *tbl, u16_l len);
|
||||
int rwnx_send_rf_calib_req(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm);
|
||||
int rwnx_send_get_macaddr_req(struct rwnx_hw *rwnx_hw, struct mm_get_mac_addr_cfm *cfm);
|
||||
|
||||
#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_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,
|
||||
const u8 *mac, u8 inst_nbr, struct me_sta_add_cfm *cfm);
|
||||
int rwnx_send_me_sta_del(struct rwnx_hw *rwnx_hw, u8 sta_idx, bool tdls_sta);
|
||||
int rwnx_send_me_traffic_ind(struct rwnx_hw *rwnx_hw, u8 sta_idx, bool uapsd, u8 tx_status);
|
||||
int rwnx_send_me_rc_stats(struct rwnx_hw *rwnx_hw, u8 sta_idx,
|
||||
struct me_rc_stats_cfm *cfm);
|
||||
int rwnx_send_me_rc_set_rate(struct rwnx_hw *rwnx_hw,
|
||||
u8 sta_idx,
|
||||
u16 rate_idx);
|
||||
int rwnx_send_me_set_ps_mode(struct rwnx_hw *rwnx_hw, u8 ps_mode);
|
||||
int rwnx_send_me_set_lp_level(struct rwnx_hw *rwnx_hw, u8 lp_level);
|
||||
int rwnx_send_sm_connect_req(struct rwnx_hw *rwnx_hw,
|
||||
struct rwnx_vif *rwnx_vif,
|
||||
struct cfg80211_connect_params *sme,
|
||||
struct sm_connect_cfm *cfm);
|
||||
int rwnx_send_sm_disconnect_req(struct rwnx_hw *rwnx_hw,
|
||||
struct rwnx_vif *rwnx_vif,
|
||||
u16 reason);
|
||||
int rwnx_send_sm_external_auth_required_rsp(struct rwnx_hw *rwnx_hw,
|
||||
struct rwnx_vif *rwnx_vif,
|
||||
u16 status);
|
||||
int rwnx_send_apm_start_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif,
|
||||
struct cfg80211_ap_settings *settings,
|
||||
struct apm_start_cfm *cfm,
|
||||
struct rwnx_ipc_elem_var *elem);
|
||||
int rwnx_send_apm_stop_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif);
|
||||
int rwnx_send_scanu_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif,
|
||||
struct cfg80211_scan_request *param);
|
||||
int rwnx_send_scanu_cancel_req(struct rwnx_hw *rwnx_hw,
|
||||
struct scan_cancel_cfm *cfm);
|
||||
|
||||
int rwnx_send_apm_start_cac_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
struct apm_start_cac_cfm *cfm);
|
||||
int rwnx_send_apm_stop_cac_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif);
|
||||
int rwnx_send_tdls_peer_traffic_ind_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif);
|
||||
int rwnx_send_config_monitor_req(struct rwnx_hw *rwnx_hw,
|
||||
struct cfg80211_chan_def *chandef,
|
||||
struct me_config_monitor_cfm *cfm);
|
||||
int rwnx_send_mesh_start_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif,
|
||||
const struct mesh_config *conf, const struct mesh_setup *setup,
|
||||
struct mesh_start_cfm *cfm);
|
||||
int rwnx_send_mesh_stop_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif,
|
||||
struct mesh_stop_cfm *cfm);
|
||||
int rwnx_send_mesh_update_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif,
|
||||
u32 mask, const struct mesh_config *p_mconf, struct mesh_update_cfm *cfm);
|
||||
int rwnx_send_mesh_peer_info_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif,
|
||||
u8 sta_idx, struct mesh_peer_info_cfm *cfm);
|
||||
void rwnx_send_mesh_peer_update_ntf(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif,
|
||||
u8 sta_idx, u8 mlink_state);
|
||||
void rwnx_send_mesh_path_create_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, u8 *tgt_addr);
|
||||
int rwnx_send_mesh_path_update_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, const u8 *tgt_addr,
|
||||
const u8 *p_nhop_addr, struct mesh_path_update_cfm *cfm);
|
||||
void rwnx_send_mesh_proxy_add_req(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, u8 *ext_addr);
|
||||
#endif /* CONFIG_RWNX_FULLMAC */
|
||||
|
||||
#ifdef CONFIG_RWNX_BFMER
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
void rwnx_send_bfmer_enable(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta,
|
||||
const struct ieee80211_vht_cap *vht_cap);
|
||||
#endif /* CONFIG_RWNX_FULLMAC */
|
||||
#ifdef CONFIG_RWNX_MUMIMO_TX
|
||||
int rwnx_send_mu_group_update_req(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta);
|
||||
#endif /* CONFIG_RWNX_MUMIMO_TX */
|
||||
#endif /* CONFIG_RWNX_BFMER */
|
||||
|
||||
/* Debug messages */
|
||||
int rwnx_send_dbg_trigger_req(struct rwnx_hw *rwnx_hw, char *msg);
|
||||
int rwnx_send_dbg_mem_read_req(struct rwnx_hw *rwnx_hw, u32 mem_addr,
|
||||
struct dbg_mem_read_cfm *cfm);
|
||||
int rwnx_send_dbg_mem_write_req(struct rwnx_hw *rwnx_hw, u32 mem_addr,
|
||||
u32 mem_data);
|
||||
int rwnx_send_dbg_mem_mask_write_req(struct rwnx_hw *rwnx_hw, u32 mem_addr,
|
||||
u32 mem_mask, u32 mem_data);
|
||||
int rwnx_send_dbg_set_mod_filter_req(struct rwnx_hw *rwnx_hw, u32 filter);
|
||||
#ifdef CONFIG_RFTEST
|
||||
int rwnx_send_rftest_req(struct rwnx_hw *rwnx_hw, u32_l cmd, u32_l argc, u8_l *argv, struct dbg_rftest_cmd_cfm *cfm);
|
||||
#endif
|
||||
int rwnx_send_dbg_set_sev_filter_req(struct rwnx_hw *rwnx_hw, u32 filter);
|
||||
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_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);
|
||||
int rwnx_send_dbg_gpio_read_req(struct rwnx_hw *rwnx_hw, u8_l gpio_idx, struct dbg_gpio_read_cfm *cfm);
|
||||
int rwnx_send_dbg_gpio_init_req(struct rwnx_hw *rwnx_hw, u8_l gpio_idx, u8_l gpio_dir, u8_l gpio_val);
|
||||
int rwnx_send_cfg_rssi_req(struct rwnx_hw *rwnx_hw, u8 vif_index, int rssi_thold, u32 rssi_hyst);
|
||||
int rwnx_send_disable_agg_req(struct rwnx_hw *rwnx_hw, u8_l agg_disable, u8_l agg_disable_rx, u8_l sta_idx);
|
||||
int rwnx_send_coex_req(struct rwnx_hw *rwnx_hw, u8_l disable_coexnull, u8_l enable_nullcts);
|
||||
int rwnx_send_get_sta_info_req(struct rwnx_hw *rwnx_hw, u8_l sta_idx, struct mm_get_sta_info_cfm *cfm);
|
||||
int rwnx_send_set_stack_start_req(struct rwnx_hw *rwnx_hw, u8_l on, u8_l efuse_valid, u8_l set_vendor_info,
|
||||
u8_l fwtrace_redir_en, struct mm_set_stack_start_cfm *cfm);
|
||||
int rwnx_send_txop_req(struct rwnx_hw *rwnx_hw, uint16_t *txop, u8_l long_nav_en, u8_l cfe_en);
|
||||
int rwnx_send_set_temp_comp_req(struct rwnx_hw *rwnx_hw, struct mm_set_vendor_swconfig_cfm *cfm);
|
||||
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_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_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_adj_req(struct rwnx_hw *rwnx_hw);
|
||||
|
||||
//#ifdef CONFIG_USB_BT
|
||||
int rwnx_send_reboot(struct rwnx_hw *rwnx_hw);
|
||||
//#endif // CONFIG_USB_BT
|
||||
|
||||
|
||||
#endif /* _RWNX_MSG_TX_H_ */
|
||||
@@ -0,0 +1,659 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_mu_group.c
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2016-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "rwnx_defs.h"
|
||||
#include "rwnx_msg_tx.h"
|
||||
#include "rwnx_events.h"
|
||||
|
||||
|
||||
/**
|
||||
* rwnx_mu_group_sta_init - Initialize group information for a STA
|
||||
*
|
||||
* @sta: Sta to initialize
|
||||
*/
|
||||
void rwnx_mu_group_sta_init(struct rwnx_sta *sta,
|
||||
const struct ieee80211_vht_cap *vht_cap)
|
||||
{
|
||||
sta->group_info.map = 0;
|
||||
sta->group_info.cnt = 0;
|
||||
sta->group_info.active.next = LIST_POISON1;
|
||||
sta->group_info.update.next = LIST_POISON1;
|
||||
sta->group_info.last_update = 0;
|
||||
sta->group_info.traffic = 0;
|
||||
sta->group_info.group = 0;
|
||||
|
||||
if (!vht_cap ||
|
||||
!(vht_cap->vht_cap_info & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) {
|
||||
sta->group_info.map = RWNX_SU_GROUP;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* rwnx_mu_group_sta_del - Remove a sta from all MU group
|
||||
*
|
||||
* @rwnx_hw: main driver data
|
||||
* @sta: STA to remove
|
||||
*
|
||||
* Remove one sta from all the MU groups it belongs to.
|
||||
*/
|
||||
void rwnx_mu_group_sta_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta)
|
||||
{
|
||||
struct rwnx_mu_info *mu = &rwnx_hw->mu;
|
||||
int i, j, group_id;
|
||||
bool lock_taken;
|
||||
u64 map;
|
||||
|
||||
lock_taken = (down_interruptible(&mu->lock) == 0);
|
||||
|
||||
group_sta_for_each(sta, group_id, map) {
|
||||
struct rwnx_mu_group *group = rwnx_mu_group_from_id(mu, group_id);
|
||||
|
||||
for (i = 0; i < CONFIG_USER_MAX; i++) {
|
||||
if (group->users[i] == sta) {
|
||||
group->users[i] = NULL;
|
||||
group->user_cnt --;
|
||||
/* Don't keep group with only one user */
|
||||
if (group->user_cnt == 1) {
|
||||
for (j = 0; j < CONFIG_USER_MAX; j++) {
|
||||
if (group->users[j]) {
|
||||
group->users[j]->group_info.cnt--;
|
||||
group->users[j]->group_info.map &= ~BIT_ULL(group->group_id);
|
||||
if (group->users[j]->group_info.group == group_id)
|
||||
group->users[j]->group_info.group = 0;
|
||||
group->user_cnt --;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mu->group_cnt--;
|
||||
trace_mu_group_delete(group->group_id);
|
||||
} else {
|
||||
trace_mu_group_update(group);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
WARN((i == CONFIG_USER_MAX), "sta %d doesn't belongs to group %d",
|
||||
sta->sta_idx, group_id);
|
||||
}
|
||||
|
||||
sta->group_info.map = 0;
|
||||
sta->group_info.cnt = 0;
|
||||
sta->group_info.traffic = 0;
|
||||
|
||||
if (sta->group_info.active.next != LIST_POISON1)
|
||||
list_del(&sta->group_info.active);
|
||||
|
||||
if (sta->group_info.update.next != LIST_POISON1)
|
||||
list_del(&sta->group_info.update);
|
||||
|
||||
if (lock_taken)
|
||||
up(&mu->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* rwnx_mu_group_sta_get_map - Get the list of group a STA belongs to
|
||||
*
|
||||
* @sta: pointer to the sta
|
||||
*
|
||||
* @return the list of group a STA belongs to as a bitfield
|
||||
*/
|
||||
u64 rwnx_mu_group_sta_get_map(struct rwnx_sta *sta)
|
||||
{
|
||||
if (sta)
|
||||
return sta->group_info.map;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* rwnx_mu_group_sta_get_pos - Get sta position in a group
|
||||
*
|
||||
* @rwnx_hw: main driver data
|
||||
* @sta: pointer to the sta
|
||||
* @group_id: Group id
|
||||
*
|
||||
* @return the positon of @sta in group @group_id or -1 if the sta
|
||||
* doesn't belongs to the group (or group id is invalid)
|
||||
*/
|
||||
int rwnx_mu_group_sta_get_pos(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta,
|
||||
int group_id)
|
||||
{
|
||||
struct rwnx_mu_group *group;
|
||||
int i;
|
||||
|
||||
group = rwnx_mu_group_from_id(&rwnx_hw->mu, group_id);
|
||||
if (!group)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < CONFIG_USER_MAX; i++) {
|
||||
if (group->users[i] == sta)
|
||||
return i;
|
||||
}
|
||||
|
||||
WARN(1, "sta %d doesn't belongs to group %d",
|
||||
sta->sta_idx, group_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* rwnx_mu_group_move_head - Move (or add) one element at the top of a list
|
||||
*
|
||||
* @list: list pointer
|
||||
* @elem: element to move (or add) at the top of @list
|
||||
*
|
||||
*/
|
||||
static inline
|
||||
void rwnx_mu_group_move_head(struct list_head *list, struct list_head *elem)
|
||||
{
|
||||
if (elem->next != LIST_POISON1) {
|
||||
__list_del_entry(elem);
|
||||
}
|
||||
list_add(elem, list);
|
||||
}
|
||||
|
||||
/**
|
||||
* rwnx_mu_group_remove_users - Remove all the users of a group
|
||||
*
|
||||
* @mu: pointer on MU info
|
||||
* @group: pointer on group to remove users from
|
||||
*
|
||||
* Loop over all users one one group and remove this group from their
|
||||
* map (and count).
|
||||
* Each users is also added to the update_sta list, so that group info
|
||||
* will be resent to fw for this user.
|
||||
*/
|
||||
static inline
|
||||
void rwnx_mu_group_remove_users(struct rwnx_mu_info *mu,
|
||||
struct rwnx_mu_group *group)
|
||||
{
|
||||
struct rwnx_sta *sta;
|
||||
int i, group_id = group->group_id;
|
||||
|
||||
for (i = 0; i < CONFIG_USER_MAX; i++) {
|
||||
if (group->users[i]) {
|
||||
sta = group->users[i];
|
||||
group->users[i] = NULL;
|
||||
sta->group_info.cnt--;
|
||||
sta->group_info.map &= ~BIT_ULL(group_id);
|
||||
rwnx_mu_group_move_head(&mu->update_sta,
|
||||
&sta->group_info.update);
|
||||
}
|
||||
}
|
||||
|
||||
if (group->user_cnt)
|
||||
mu->group_cnt--;
|
||||
group->user_cnt = 0;
|
||||
trace_mu_group_delete(group_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* rwnx_mu_group_add_users - Add users to a group
|
||||
*
|
||||
* @mu: pointer on MU info
|
||||
* @group: pointer on group to add users in
|
||||
* @nb_user: number of users to ad
|
||||
* @users: table of user to add
|
||||
*
|
||||
* Add @nb_users to @group (which may already have users)
|
||||
* Each new users is added to the first free position.
|
||||
* It is assume that @group has at least @nb_user free position. If it is not
|
||||
* case it only add the number of users needed to complete the group.
|
||||
* Each users (effectively added to @group) is also added to the update_sta
|
||||
* list, so that group info will be resent to fw for this user.
|
||||
*/
|
||||
static inline
|
||||
void rwnx_mu_group_add_users(struct rwnx_mu_info *mu,
|
||||
struct rwnx_mu_group *group,
|
||||
int nb_user, struct rwnx_sta **users)
|
||||
{
|
||||
int i, j, group_id = group->group_id;
|
||||
|
||||
if (!group->user_cnt)
|
||||
mu->group_cnt++;
|
||||
|
||||
j = 0;
|
||||
for (i = 0; i < nb_user ; i++) {
|
||||
for (; j < CONFIG_USER_MAX ; j++) {
|
||||
if (group->users[j] == NULL) {
|
||||
group->users[j] = users[i];
|
||||
users[i]->group_info.cnt ++;
|
||||
users[i]->group_info.map |= BIT_ULL(group_id);
|
||||
|
||||
rwnx_mu_group_move_head(&(mu->update_sta),
|
||||
&(users[i]->group_info.update));
|
||||
group->user_cnt ++;
|
||||
j ++;
|
||||
break;
|
||||
}
|
||||
|
||||
WARN(j == (CONFIG_USER_MAX - 1),
|
||||
"Too many user for group %d (nb_user=%d)",
|
||||
group_id, group->user_cnt + nb_user - i);
|
||||
}
|
||||
}
|
||||
|
||||
trace_mu_group_update(group);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* rwnx_mu_group_create_one - create on group with a specific group of user
|
||||
*
|
||||
* @mu: pointer on MU info
|
||||
* @nb_user: number of user to include in the group (<= CONFIG_USER_MAX)
|
||||
* @users: table of users
|
||||
*
|
||||
* Try to create a new group with a specific group of users.
|
||||
* 1- First it checks if a group containing all this users already exists.
|
||||
*
|
||||
* 2- Then it checks if it is possible to complete a group which already
|
||||
* contains at least one user.
|
||||
*
|
||||
* 3- Finally it create a new group. To do so, it take take the last group of
|
||||
* the active_groups list, remove all its current users and add the new ones
|
||||
*
|
||||
* In all cases, the group selected is moved at the top of the active_groups
|
||||
* list
|
||||
*
|
||||
* @return 1 if a new group has been created and 0 otherwise
|
||||
*/
|
||||
static
|
||||
int rwnx_mu_group_create_one(struct rwnx_mu_info *mu, int nb_user,
|
||||
struct rwnx_sta **users, int *nb_group_left)
|
||||
{
|
||||
int i, group_id;
|
||||
struct rwnx_mu_group *group;
|
||||
u64 group_match;
|
||||
u64 group_avail;
|
||||
|
||||
group_match = users[0]->group_info.map;
|
||||
group_avail = users[0]->group_info.map;
|
||||
for (i = 1; i < nb_user ; i++) {
|
||||
group_match &= users[i]->group_info.map;
|
||||
group_avail |= users[i]->group_info.map;
|
||||
|
||||
}
|
||||
|
||||
if (group_match) {
|
||||
/* a group (or more) with all the users already exist */
|
||||
group_id = RWNX_GET_FIRST_GROUP_ID(group_match);
|
||||
group = rwnx_mu_group_from_id(mu, group_id);
|
||||
rwnx_mu_group_move_head(&mu->active_groups, &group->list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_USER_MAX > 2
|
||||
if (group_avail) {
|
||||
/* check if we can complete a group */
|
||||
struct rwnx_sta *users2[CONFIG_USER_MAX];
|
||||
int nb_user2;
|
||||
|
||||
group_for_each(group_id, group_avail) {
|
||||
group = rwnx_mu_group_from_id(mu, group_id);
|
||||
if (group->user_cnt == CONFIG_USER_MAX)
|
||||
continue;
|
||||
|
||||
nb_user2 = 0;
|
||||
for (i = 0; i < nb_user ; i++) {
|
||||
if (!(users[i]->group_info.map & BIT_ULL(group_id))) {
|
||||
users2[nb_user2] = users[i];
|
||||
nb_user2++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((group->user_cnt + nb_user2) <= CONFIG_USER_MAX) {
|
||||
rwnx_mu_group_add_users(mu, group, nb_user2, users2);
|
||||
rwnx_mu_group_move_head(&mu->active_groups, &group->list);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_USER_MAX > 2*/
|
||||
|
||||
/* create a new group */
|
||||
group = list_last_entry(&mu->active_groups, struct rwnx_mu_group, list);
|
||||
rwnx_mu_group_remove_users(mu, group);
|
||||
rwnx_mu_group_add_users(mu, group, nb_user, users);
|
||||
rwnx_mu_group_move_head(&mu->active_groups, &group->list);
|
||||
(*nb_group_left)--;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* rwnx_mu_group_create - Create new groups containing one specific sta
|
||||
*
|
||||
* @mu: pointer on MU info
|
||||
* @sta: sta to add in each group
|
||||
* @nb_group_left: maximum number to new group allowed. (updated on exit)
|
||||
*
|
||||
* This will try to create "all the possible" group with a specific sta being
|
||||
* a member of all these group.
|
||||
* The function simply loops over the @active_sta list (starting from @sta).
|
||||
* When it has (CONFIG_USER_MAX - 1) users it try to create a new group with
|
||||
* these users (plus @sta).
|
||||
* Loops end when there is no more users, or no more new group is allowed
|
||||
*
|
||||
*/
|
||||
static
|
||||
void rwnx_mu_group_create(struct rwnx_mu_info *mu, struct rwnx_sta *sta,
|
||||
int *nb_group_left)
|
||||
{
|
||||
struct rwnx_sta *user_sta = sta;
|
||||
struct rwnx_sta *users[CONFIG_USER_MAX];
|
||||
int nb_user = 1;
|
||||
|
||||
users[0] = sta;
|
||||
while (*nb_group_left) {
|
||||
|
||||
list_for_each_entry_continue(user_sta, &mu->active_sta, group_info.active) {
|
||||
users[nb_user] = user_sta;
|
||||
if (++nb_user == CONFIG_USER_MAX) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (nb_user > 1) {
|
||||
if (rwnx_mu_group_create_one(mu, nb_user, users, nb_group_left))
|
||||
(*nb_group_left)--;
|
||||
|
||||
if (nb_user < CONFIG_USER_MAX)
|
||||
break;
|
||||
else
|
||||
nb_user = 1;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* rwnx_mu_group_work - process function of the "group_work"
|
||||
*
|
||||
* The work is scheduled when several sta (MU beamformee capable) are active.
|
||||
* When called, the @active_sta contains the list of the active sta (starting
|
||||
* from the most recent one), and @active_groups is the list of all possible
|
||||
* groups ordered so that the first one is the most recently used.
|
||||
*
|
||||
* This function will create new groups, starting from group containing the
|
||||
* most "active" sta.
|
||||
* For example if the list of sta is :
|
||||
* sta8 -> sta3 -> sta4 -> sta7 -> sta1
|
||||
* and the number of user per group is 3, it will create grooups :
|
||||
* - sta8 / sta3 / sta4
|
||||
* - sta8 / sta7 / sta1
|
||||
* - sta3 / sta4 / sta7
|
||||
* - sta3 / sta1
|
||||
* - sta4 / sta7 / sta1
|
||||
* - sta7 / sta1
|
||||
*
|
||||
* To create new group, the least used group are first selected.
|
||||
* It is only allowed to create NX_MU_GROUP_MAX per iteration.
|
||||
*
|
||||
* Once groups have been updated, mu group information is update to the fw.
|
||||
* To do so it use the @update_sta list to know which sta has been affected.
|
||||
* As it is necessary to wait for fw confirmation before using this new group
|
||||
* MU is temporarily disabled during group update
|
||||
*
|
||||
* Work is then rescheduled.
|
||||
*
|
||||
* At the end of the function, both @active_sta and @update_sta list are empty.
|
||||
*
|
||||
* Note:
|
||||
* - This is still a WIP, and will require more tuning
|
||||
* - not all combinations are created, to avoid to much processing.
|
||||
* - reschedule delay should be adaptative
|
||||
*/
|
||||
void rwnx_mu_group_work(struct work_struct *ws)
|
||||
{
|
||||
struct delayed_work *dw = container_of(ws, struct delayed_work, work);
|
||||
struct rwnx_mu_info *mu = container_of(dw, struct rwnx_mu_info, group_work);
|
||||
struct rwnx_hw *rwnx_hw = container_of(mu, struct rwnx_hw, mu);
|
||||
struct rwnx_sta *sta, *next;
|
||||
int nb_group_left = NX_MU_GROUP_MAX;
|
||||
|
||||
if (WARN(!rwnx_hw->mod_params->mutx,
|
||||
"In group formation work, but mutx disabled"))
|
||||
return;
|
||||
|
||||
if (down_interruptible(&mu->lock) != 0)
|
||||
return;
|
||||
|
||||
mu->update_count++;
|
||||
if (!mu->update_count)
|
||||
mu->update_count++;
|
||||
|
||||
list_for_each_entry_safe(sta, next, &mu->active_sta, group_info.active) {
|
||||
if (nb_group_left)
|
||||
rwnx_mu_group_create(mu, sta, &nb_group_left);
|
||||
|
||||
sta->group_info.last_update = mu->update_count;
|
||||
list_del(&sta->group_info.active);
|
||||
}
|
||||
|
||||
if (! list_empty(&mu->update_sta)) {
|
||||
list_for_each_entry_safe(sta, next, &mu->update_sta, group_info.update) {
|
||||
rwnx_send_mu_group_update_req(rwnx_hw, sta);
|
||||
list_del(&sta->group_info.update);
|
||||
}
|
||||
}
|
||||
|
||||
mu->next_group_select = jiffies;
|
||||
rwnx_mu_group_sta_select(rwnx_hw);
|
||||
up(&mu->lock);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* rwnx_mu_group_init - Initialize MU groups
|
||||
*
|
||||
* @rwnx_hw: main driver data
|
||||
*
|
||||
* Initialize all MU group
|
||||
*/
|
||||
void rwnx_mu_group_init(struct rwnx_hw *rwnx_hw)
|
||||
{
|
||||
struct rwnx_mu_info *mu = &rwnx_hw->mu;
|
||||
int i;
|
||||
|
||||
INIT_LIST_HEAD(&mu->active_groups);
|
||||
INIT_LIST_HEAD(&mu->active_sta);
|
||||
INIT_LIST_HEAD(&mu->update_sta);
|
||||
|
||||
for (i = 0; i < NX_MU_GROUP_MAX; i++) {
|
||||
int j;
|
||||
mu->groups[i].user_cnt = 0;
|
||||
mu->groups[i].group_id = i + 1;
|
||||
for (j = 0; j < CONFIG_USER_MAX; j++) {
|
||||
mu->groups[i].users[j] = NULL;
|
||||
}
|
||||
list_add(&mu->groups[i].list, &mu->active_groups);
|
||||
}
|
||||
|
||||
mu->update_count = 1;
|
||||
mu->group_cnt = 0;
|
||||
mu->next_group_select = jiffies;
|
||||
INIT_DELAYED_WORK(&mu->group_work, rwnx_mu_group_work);
|
||||
sema_init(&mu->lock, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* rwnx_mu_set_active_sta - mark a STA as active
|
||||
*
|
||||
* @rwnx_hw: main driver data
|
||||
* @sta: pointer to the sta
|
||||
* @traffic: Number of buffers to add in the sta's traffic counter
|
||||
*
|
||||
* If @sta is MU beamformee capable (and MU-MIMO tx is enabled) move the
|
||||
* sta at the top of the @active_sta list.
|
||||
* It also schedule the group_work if not already scheduled and the list
|
||||
* contains more than one sta.
|
||||
*
|
||||
* If a STA was already in the list during the last group update
|
||||
* (i.e. sta->group_info.last_update == mu->update_count) it is not added
|
||||
* back to the list until a sta that wasn't active during the last update is
|
||||
* added. This is to avoid scheduling group update with a list of sta that
|
||||
* were all already in the list during previous update.
|
||||
*
|
||||
* It is called with mu->lock taken.
|
||||
*/
|
||||
void rwnx_mu_set_active_sta(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta,
|
||||
int traffic)
|
||||
{
|
||||
struct rwnx_mu_info *mu = &rwnx_hw->mu;
|
||||
|
||||
if (!sta || (sta->group_info.map & RWNX_SU_GROUP))
|
||||
return;
|
||||
|
||||
sta->group_info.traffic += traffic;
|
||||
|
||||
if ((sta->group_info.last_update != mu->update_count) ||
|
||||
!list_empty(&mu->active_sta)) {
|
||||
|
||||
rwnx_mu_group_move_head(&mu->active_sta, &sta->group_info.active);
|
||||
|
||||
if (!delayed_work_pending(&mu->group_work) &&
|
||||
!list_is_singular(&mu->active_sta)) {
|
||||
schedule_delayed_work(&mu->group_work,
|
||||
msecs_to_jiffies(RWNX_MU_GROUP_INTERVAL));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* rwnx_mu_set_active_group - mark a MU group as active
|
||||
*
|
||||
* @rwnx_hw: main driver data
|
||||
* @group_id: Group id
|
||||
*
|
||||
* move a group at the top of the @active_groups list
|
||||
*/
|
||||
void rwnx_mu_set_active_group(struct rwnx_hw *rwnx_hw, int group_id)
|
||||
{
|
||||
struct rwnx_mu_info *mu = &rwnx_hw->mu;
|
||||
struct rwnx_mu_group *group = rwnx_mu_group_from_id(mu, group_id);
|
||||
|
||||
rwnx_mu_group_move_head(&mu->active_groups, &group->list);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* rwnx_mu_group_sta_select - Select the best group for MU stas
|
||||
*
|
||||
* @rwnx_hw: main driver data
|
||||
*
|
||||
* For each MU capable client of AP interfaces this function tries to select
|
||||
* the best group to use.
|
||||
*
|
||||
* In first pass, gather information from all stations to form statistics
|
||||
* for each group for the previous @RWNX_MU_GROUP_SELECT_INTERVAL interval:
|
||||
* - number of buffers transmitted
|
||||
* - number of user
|
||||
*
|
||||
* Then groups with more than 2 active users, are assigned after being ordered
|
||||
* by traffic :
|
||||
* - group with highest traffic is selected: set this group for all its users
|
||||
* - update nb_users for all others group (as one sta may be in several groups)
|
||||
* - select the next group that have still mor than 2 users and assign it.
|
||||
* - continue until all group are processed
|
||||
*
|
||||
*/
|
||||
void rwnx_mu_group_sta_select(struct rwnx_hw *rwnx_hw)
|
||||
{
|
||||
struct rwnx_mu_info *mu = &rwnx_hw->mu;
|
||||
int nb_users[NX_MU_GROUP_MAX + 1];
|
||||
int traffic[NX_MU_GROUP_MAX + 1];
|
||||
int order[NX_MU_GROUP_MAX + 1];
|
||||
struct rwnx_sta *sta;
|
||||
struct rwnx_vif *vif;
|
||||
struct list_head *head;
|
||||
u64 map;
|
||||
int i, j, update, group_id, tmp, cnt = 0;
|
||||
|
||||
if (!mu->group_cnt || time_before(jiffies, mu->next_group_select))
|
||||
return;
|
||||
|
||||
list_for_each_entry(vif, &rwnx_hw->vifs, list) {
|
||||
|
||||
if (RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_AP)
|
||||
continue;
|
||||
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
head = &vif->ap.sta_list;
|
||||
#else
|
||||
head = &vif->stations;
|
||||
#endif /* CONFIG_RWNX_FULLMAC */
|
||||
|
||||
memset(nb_users, 0, sizeof(nb_users));
|
||||
memset(traffic, 0, sizeof(traffic));
|
||||
list_for_each_entry(sta, head, list) {
|
||||
int sta_traffic = sta->group_info.traffic;
|
||||
|
||||
/* reset statistics for next selection */
|
||||
sta->group_info.traffic = 0;
|
||||
if (sta->group_info.group)
|
||||
trace_mu_group_selection(sta, 0);
|
||||
sta->group_info.group = 0;
|
||||
|
||||
if (sta->group_info.cnt == 0 ||
|
||||
sta_traffic < RWNX_MU_GROUP_MIN_TRAFFIC)
|
||||
continue;
|
||||
|
||||
group_sta_for_each(sta, group_id, map) {
|
||||
nb_users[group_id]++;
|
||||
traffic[group_id] += sta_traffic;
|
||||
|
||||
/* list group with 2 users or more */
|
||||
if (nb_users[group_id] == 2)
|
||||
order[cnt++] = group_id;
|
||||
}
|
||||
}
|
||||
|
||||
/* reorder list of group with more that 2 users */
|
||||
update = 1;
|
||||
while(update) {
|
||||
update = 0;
|
||||
for (i = 0; i < cnt - 1; i++) {
|
||||
if (traffic[order[i]] < traffic[order[i + 1]]) {
|
||||
tmp = order[i];
|
||||
order[i] = order[i + 1];
|
||||
order[i + 1] = tmp;
|
||||
update = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* now assign group in traffic order */
|
||||
for (i = 0; i < cnt ; i ++) {
|
||||
struct rwnx_mu_group *group;
|
||||
group_id = order[i];
|
||||
|
||||
if (nb_users[group_id] < 2)
|
||||
continue;
|
||||
|
||||
group = rwnx_mu_group_from_id(mu, group_id);
|
||||
for (j = 0; j < CONFIG_USER_MAX ; j++) {
|
||||
if (group->users[j]) {
|
||||
trace_mu_group_selection(group->users[j], group_id);
|
||||
group->users[j]->group_info.group = group_id;
|
||||
|
||||
group_sta_for_each(group->users[j], tmp, map) {
|
||||
if (group_id != tmp)
|
||||
nb_users[tmp]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mu->next_group_select = jiffies +
|
||||
msecs_to_jiffies(RWNX_MU_GROUP_SELECT_INTERVAL);
|
||||
mu->next_group_select |= 1;
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_mu_group.h
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2016-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#ifndef _RWNX_MU_GROUP_H_
|
||||
#define _RWNX_MU_GROUP_H_
|
||||
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/semaphore.h>
|
||||
|
||||
struct rwnx_hw;
|
||||
struct rwnx_sta;
|
||||
|
||||
#ifdef CONFIG_RWNX_MUMIMO_TX
|
||||
|
||||
/**
|
||||
* struct rwnx_sta_group_info - Group Information for a STA
|
||||
*
|
||||
* @active: node for @mu->active_sta list
|
||||
* @update: node for @mu->update_sta list
|
||||
* @cnt: Number of groups the STA belongs to
|
||||
* @map: Bitfield of groups the sta belongs to
|
||||
* @traffic: Number of buffers sent since previous group selection
|
||||
* @group: Id of the group selected by previous group selection
|
||||
* (cf @rwnx_mu_group_sta_select)
|
||||
*/
|
||||
struct rwnx_sta_group_info {
|
||||
struct list_head active;
|
||||
struct list_head update;
|
||||
u16 last_update;
|
||||
int cnt;
|
||||
u64 map;
|
||||
int traffic;
|
||||
u8 group;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mu_group_info - Information about the users of a group
|
||||
*
|
||||
* @list: node for mu->active_groups
|
||||
* @group_id: Group identifier
|
||||
* @user_cnt: Number of the users in the group
|
||||
* @users: Pointer to the sta, ordered by user position
|
||||
*/
|
||||
struct rwnx_mu_group {
|
||||
struct list_head list;
|
||||
int group_id;
|
||||
int user_cnt;
|
||||
struct rwnx_sta *users[CONFIG_USER_MAX];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rwnx_mu_info - Information about all MU group
|
||||
*
|
||||
* @active_groups: List of all possible groups. Ordered from the most recently
|
||||
* used one to the least one (and possibly never used)
|
||||
* @active_sta: List of MU beamformee sta that have been active (since previous
|
||||
* group update). Ordered from the most recently active.
|
||||
* @update_sta: List of sta whose group information has changed and need to be
|
||||
* updated at fw level
|
||||
* @groups: Table of all groups
|
||||
* @group_work: Work item used to schedule group update
|
||||
* @update_count: Counter used to identify the last group formation update.
|
||||
* (cf rwnx_sta_group_info.last_update)
|
||||
* @lock: Lock taken during group update. If tx happens lock is taken, then tx
|
||||
* will not used MU.
|
||||
* @next_group_assign: Next time the group selection should be run
|
||||
* (ref @rwnx_mu_group_sta_select)
|
||||
* @group_cnt: Number of group created
|
||||
*/
|
||||
struct rwnx_mu_info {
|
||||
struct list_head active_groups;
|
||||
struct list_head active_sta;
|
||||
struct list_head update_sta;
|
||||
struct rwnx_mu_group groups[NX_MU_GROUP_MAX];
|
||||
struct delayed_work group_work;
|
||||
u16 update_count;
|
||||
struct semaphore lock;
|
||||
unsigned long next_group_select;
|
||||
u8 group_cnt;
|
||||
};
|
||||
|
||||
#define RWNX_SU_GROUP BIT_ULL(0)
|
||||
#define RWNX_MU_GROUP_MASK 0x7ffffffffffffffeULL
|
||||
#define RWNX_MU_GROUP_INTERVAL 200 /* in ms */
|
||||
#define RWNX_MU_GROUP_SELECT_INTERVAL 100 /* in ms */
|
||||
// minimum traffic in a RWNX_MU_GROUP_SELECT_INTERVAL to consider the sta
|
||||
#define RWNX_MU_GROUP_MIN_TRAFFIC 50 /* in number of packet */
|
||||
|
||||
|
||||
#define RWNX_GET_FIRST_GROUP_ID(map) (fls64(map) - 1)
|
||||
|
||||
#define group_sta_for_each(sta, id, map) \
|
||||
map = sta->group_info.map & RWNX_MU_GROUP_MASK; \
|
||||
for (id = (fls64(map) - 1) ; id > 0 ; \
|
||||
map &= ~(u64)BIT_ULL(id), id = (fls64(map) - 1))
|
||||
|
||||
#define group_for_each(id, map) \
|
||||
for (id = (fls64(map) - 1) ; id > 0 ; \
|
||||
map &= ~(u64)BIT_ULL(id), id = (fls64(map) - 1))
|
||||
|
||||
#define RWNX_MUMIMO_INFO_POS_ID(info) (((info) >> 6) & 0x3)
|
||||
#define RWNX_MUMIMO_INFO_GROUP_ID(info) ((info) & 0x3f)
|
||||
|
||||
static inline
|
||||
struct rwnx_mu_group *rwnx_mu_group_from_id(struct rwnx_mu_info *mu, int id)
|
||||
{
|
||||
if (id > NX_MU_GROUP_MAX)
|
||||
return NULL;
|
||||
|
||||
return &mu->groups[id - 1];
|
||||
}
|
||||
|
||||
|
||||
void rwnx_mu_group_sta_init(struct rwnx_sta *sta,
|
||||
const struct ieee80211_vht_cap *vht_cap);
|
||||
void rwnx_mu_group_sta_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta);
|
||||
u64 rwnx_mu_group_sta_get_map(struct rwnx_sta *sta);
|
||||
int rwnx_mu_group_sta_get_pos(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta,
|
||||
int group_id);
|
||||
|
||||
void rwnx_mu_group_init(struct rwnx_hw *rwnx_hw);
|
||||
|
||||
void rwnx_mu_set_active_sta(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta,
|
||||
int traffic);
|
||||
void rwnx_mu_set_active_group(struct rwnx_hw *rwnx_hw, int group_id);
|
||||
void rwnx_mu_group_sta_select(struct rwnx_hw *rwnx_hw);
|
||||
|
||||
|
||||
#else /* ! CONFIG_RWNX_MUMIMO_TX */
|
||||
|
||||
static inline
|
||||
void rwnx_mu_group_sta_init(struct rwnx_sta *sta,
|
||||
const struct ieee80211_vht_cap *vht_cap)
|
||||
{}
|
||||
|
||||
static inline
|
||||
void rwnx_mu_group_sta_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta)
|
||||
{}
|
||||
|
||||
static inline
|
||||
u64 rwnx_mu_group_sta_get_map(struct rwnx_sta *sta)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
int rwnx_mu_group_sta_get_pos(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta,
|
||||
int group_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
void rwnx_mu_group_init(struct rwnx_hw *rwnx_hw)
|
||||
{}
|
||||
|
||||
static inline
|
||||
void rwnx_mu_set_active_sta(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta,
|
||||
int traffic)
|
||||
{}
|
||||
|
||||
static inline
|
||||
void rwnx_mu_set_active_group(struct rwnx_hw *rwnx_hw, int group_id)
|
||||
{}
|
||||
|
||||
static inline
|
||||
void rwnx_mu_group_sta_select(struct rwnx_hw *rwnx_hw)
|
||||
{}
|
||||
|
||||
#endif /* CONFIG_RWNX_MUMIMO_TX */
|
||||
|
||||
#endif /* _RWNX_MU_GROUP_H_ */
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_pci.c
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#include <linux/pci.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "rwnx_defs.h"
|
||||
#include "rwnx_dini.h"
|
||||
#include "rwnx_v7.h"
|
||||
|
||||
#define PCI_VENDOR_ID_DINIGROUP 0x17DF
|
||||
#define PCI_DEVICE_ID_DINIGROUP_DNV6_F2PCIE 0x1907
|
||||
|
||||
#define PCI_DEVICE_ID_XILINX_CEVA_VIRTEX7 0x7011
|
||||
|
||||
static const struct pci_device_id rwnx_pci_ids[] = {
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_DINIGROUP, PCI_DEVICE_ID_DINIGROUP_DNV6_F2PCIE)},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_XILINX_CEVA_VIRTEX7)},
|
||||
{0,}
|
||||
};
|
||||
|
||||
|
||||
/* Uncomment this for depmod to create module alias */
|
||||
/* We don't want this on development platform */
|
||||
//MODULE_DEVICE_TABLE(pci, rwnx_pci_ids);
|
||||
|
||||
static int rwnx_pci_probe(struct pci_dev *pci_dev,
|
||||
const struct pci_device_id *pci_id)
|
||||
{
|
||||
struct rwnx_plat *rwnx_plat = NULL;
|
||||
void *drvdata;
|
||||
int ret = -ENODEV;
|
||||
|
||||
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
||||
|
||||
if (pci_id->vendor == PCI_VENDOR_ID_DINIGROUP) {
|
||||
ret = rwnx_dini_platform_init(pci_dev, &rwnx_plat);
|
||||
} else if (pci_id->vendor == PCI_VENDOR_ID_XILINX) {
|
||||
ret = rwnx_v7_platform_init(pci_dev, &rwnx_plat);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rwnx_plat->pci_dev = pci_dev;
|
||||
|
||||
ret = rwnx_platform_init(rwnx_plat, &drvdata);
|
||||
pci_set_drvdata(pci_dev, drvdata);
|
||||
|
||||
if (ret)
|
||||
rwnx_plat->deinit(rwnx_plat);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rwnx_pci_remove(struct pci_dev *pci_dev)
|
||||
{
|
||||
struct rwnx_hw *rwnx_hw;
|
||||
struct rwnx_plat *rwnx_plat;
|
||||
|
||||
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
||||
|
||||
rwnx_hw = pci_get_drvdata(pci_dev);
|
||||
rwnx_plat = rwnx_hw->plat;
|
||||
|
||||
rwnx_platform_deinit(rwnx_hw);
|
||||
rwnx_plat->deinit(rwnx_plat);
|
||||
|
||||
pci_set_drvdata(pci_dev, NULL);
|
||||
}
|
||||
|
||||
static struct pci_driver rwnx_pci_drv = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = rwnx_pci_ids,
|
||||
.probe = rwnx_pci_probe,
|
||||
.remove = rwnx_pci_remove
|
||||
};
|
||||
|
||||
int rwnx_pci_register_drv(void)
|
||||
{
|
||||
return pci_register_driver(&rwnx_pci_drv);
|
||||
}
|
||||
|
||||
void rwnx_pci_unregister_drv(void)
|
||||
{
|
||||
pci_unregister_driver(&rwnx_pci_drv);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_pci.h
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _RWNX_PCI_H_
|
||||
#define _RWNX_PCI_H_
|
||||
|
||||
int rwnx_pci_register_drv(void);
|
||||
void rwnx_pci_unregister_drv(void);
|
||||
|
||||
#endif /* _RWNX_PCI_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_platorm.h
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _RWNX_PLATFORM_H_
|
||||
#define _RWNX_PLATFORM_H_
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include "lmac_msg.h"
|
||||
|
||||
|
||||
#define RWNX_CONFIG_FW_NAME "rwnx_settings.ini"
|
||||
#define RWNX_PHY_CONFIG_TRD_NAME "rwnx_trident.ini"
|
||||
#define RWNX_PHY_CONFIG_KARST_NAME "rwnx_karst.ini"
|
||||
#define RWNX_AGC_FW_NAME "agcram.bin"
|
||||
#define RWNX_LDPC_RAM_NAME "ldpcram.bin"
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
#define RWNX_MAC_FW_BASE_NAME "fmacfw"
|
||||
#elif defined CONFIG_RWNX_FHOST
|
||||
#define RWNX_MAC_FW_BASE_NAME "fhostfw"
|
||||
#endif /* CONFIG_RWNX_FULLMAC */
|
||||
|
||||
#ifdef CONFIG_RWNX_TL4
|
||||
#define RWNX_MAC_FW_NAME RWNX_MAC_FW_BASE_NAME".hex"
|
||||
#else
|
||||
#define RWNX_MAC_FW_NAME RWNX_MAC_FW_BASE_NAME".ihex"
|
||||
#define RWNX_MAC_FW_NAME2 RWNX_MAC_FW_BASE_NAME".bin"
|
||||
#endif
|
||||
|
||||
#define RWNX_FCU_FW_NAME "fcuram.bin"
|
||||
#if (defined(CONFIG_DPD) && !defined(CONFIG_FORCE_DPD_CALIB))
|
||||
#define FW_DPDRESULT_NAME_8800DC "aic_dpdresult_lite_8800dc.bin"
|
||||
#endif
|
||||
|
||||
#define POWER_LEVEL_INVALID_VAL (127)
|
||||
|
||||
enum {
|
||||
FW_NORMAL_MODE = 0,
|
||||
FW_RFTEST_MODE = 1,
|
||||
FW_BLE_SCAN_WAKEUP_MODE = 2,
|
||||
FW_M2D_OTA_MODE = 3,
|
||||
FW_DPDCALIB_MODE = 4,
|
||||
FW_BLE_SCAN_AD_FILTER_MODE = 5,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Type of memory to access (cf rwnx_plat.get_address)
|
||||
*
|
||||
* @RWNX_ADDR_CPU To access memory of the embedded CPU
|
||||
* @RWNX_ADDR_SYSTEM To access memory/registers of one subsystem of the
|
||||
* embedded system
|
||||
*
|
||||
*/
|
||||
enum rwnx_platform_addr {
|
||||
RWNX_ADDR_CPU,
|
||||
RWNX_ADDR_SYSTEM,
|
||||
RWNX_ADDR_MAX,
|
||||
};
|
||||
|
||||
struct rwnx_hw;
|
||||
|
||||
/**
|
||||
* struct rwnx_plat - Operation pointers for RWNX PCI platform
|
||||
*
|
||||
* @pci_dev: pointer to pci dev
|
||||
* @enabled: Set if embedded platform has been enabled (i.e. fw loaded and
|
||||
* ipc started)
|
||||
* @enable: Configure communication with the fw (i.e. configure the transfers
|
||||
* enable and register interrupt)
|
||||
* @disable: Stop communication with the fw
|
||||
* @deinit: Free all ressources allocated for the embedded platform
|
||||
* @get_address: Return the virtual address to access the requested address on
|
||||
* the platform.
|
||||
* @ack_irq: Acknowledge the irq at link level.
|
||||
* @get_config_reg: Return the list (size + pointer) of registers to restore in
|
||||
* order to reload the platform while keeping the current configuration.
|
||||
*
|
||||
* @priv Private data for the link driver
|
||||
*/
|
||||
struct rwnx_plat {
|
||||
struct pci_dev *pci_dev;
|
||||
|
||||
#ifdef AICWF_SDIO_SUPPORT
|
||||
struct aic_sdio_dev *sdiodev;
|
||||
#endif
|
||||
|
||||
#ifdef AICWF_USB_SUPPORT
|
||||
struct aic_usb_dev *usbdev;
|
||||
#endif
|
||||
bool enabled;
|
||||
bool wait_disconnect_cb;
|
||||
|
||||
int (*enable)(struct rwnx_hw *rwnx_hw);
|
||||
int (*disable)(struct rwnx_hw *rwnx_hw);
|
||||
void (*deinit)(struct rwnx_plat *rwnx_plat);
|
||||
u8* (*get_address)(struct rwnx_plat *rwnx_plat, int addr_name,
|
||||
unsigned int offset);
|
||||
void (*ack_irq)(struct rwnx_plat *rwnx_plat);
|
||||
int (*get_config_reg)(struct rwnx_plat *rwnx_plat, const u32 **list);
|
||||
|
||||
u8 priv[0] __aligned(sizeof(void *));
|
||||
};
|
||||
|
||||
#define RWNX_ADDR(plat, base, offset) \
|
||||
plat->get_address(plat, base, offset)
|
||||
|
||||
#define RWNX_REG_READ(plat, base, offset) \
|
||||
readl(plat->get_address(plat, base, offset))
|
||||
|
||||
#define RWNX_REG_WRITE(val, plat, base, offset) \
|
||||
writel(val, plat->get_address(plat, base, offset))
|
||||
|
||||
extern struct rwnx_plat *g_rwnx_plat;
|
||||
|
||||
int rwnx_platform_init(struct rwnx_plat *rwnx_plat, void **platform_data);
|
||||
void rwnx_platform_deinit(struct rwnx_hw *rwnx_hw);
|
||||
|
||||
int rwnx_platform_on(struct rwnx_hw *rwnx_hw, void *config);
|
||||
void rwnx_platform_off(struct rwnx_hw *rwnx_hw, void **config);
|
||||
|
||||
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_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_loss(txpwr_loss_conf_t *txpwr_loss);
|
||||
void rwnx_plat_userconfig_parsing(char *buffer, int size);
|
||||
#ifdef CONFIG_POWER_LIMIT
|
||||
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);
|
||||
#endif
|
||||
int rwnx_platform_register_drv(void);
|
||||
void rwnx_platform_unregister_drv(void);
|
||||
|
||||
extern struct device *rwnx_platform_get_dev(struct rwnx_plat *rwnx_plat);
|
||||
|
||||
static inline unsigned int rwnx_platform_get_irq(struct rwnx_plat *rwnx_plat)
|
||||
{
|
||||
return rwnx_plat->pci_dev->irq;
|
||||
}
|
||||
|
||||
#endif /* _RWNX_PLATFORM_H_ */
|
||||
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
****************************************************************************************
|
||||
*
|
||||
* @file rwnx_prof.h
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _RWNX_PROF_H_
|
||||
#define _RWNX_PROF_H_
|
||||
|
||||
#include "reg_access.h"
|
||||
#include "rwnx_platform.h"
|
||||
|
||||
static inline void rwnx_prof_set(struct rwnx_hw *rwnx_hw, int val)
|
||||
{
|
||||
struct rwnx_plat *rwnx_plat = rwnx_hw->plat;
|
||||
RWNX_REG_WRITE(val, rwnx_plat, RWNX_ADDR_SYSTEM, NXMAC_SW_SET_PROFILING_ADDR);
|
||||
}
|
||||
|
||||
static inline void rwnx_prof_clear(struct rwnx_hw *rwnx_hw, int val)
|
||||
{
|
||||
struct rwnx_plat *rwnx_plat = rwnx_hw->plat;
|
||||
RWNX_REG_WRITE(val, rwnx_plat, RWNX_ADDR_SYSTEM, NXMAC_SW_CLEAR_PROFILING_ADDR);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Defines for SW Profiling registers values */
|
||||
enum {
|
||||
TX_IPC_IRQ,
|
||||
TX_IPC_EVT,
|
||||
TX_PREP_EVT,
|
||||
TX_DMA_IRQ,
|
||||
TX_MAC_IRQ,
|
||||
TX_PAYL_HDL,
|
||||
TX_CFM_EVT,
|
||||
TX_IPC_CFM,
|
||||
RX_MAC_IRQ, // 8
|
||||
RX_TRIGGER_EVT,
|
||||
RX_DMA_IRQ,
|
||||
RX_DMA_EVT,
|
||||
RX_IPC_IND,
|
||||
RX_MPDU_XFER,
|
||||
DBG_PROF_MAX
|
||||
};
|
||||
#endif
|
||||
|
||||
enum {
|
||||
SW_PROF_HOSTBUF_IDX = 12,
|
||||
/****** IPC IRQs related signals ******/
|
||||
/* E2A direction */
|
||||
SW_PROF_IRQ_E2A_RXDESC = 16, // to make sure we let 16 bits available for LMAC FW
|
||||
SW_PROF_IRQ_E2A_TXCFM,
|
||||
SW_PROF_IRQ_E2A_DBG,
|
||||
SW_PROF_IRQ_E2A_MSG,
|
||||
SW_PROF_IPC_MSGPUSH,
|
||||
SW_PROF_MSGALLOC,
|
||||
SW_PROF_MSGIND,
|
||||
SW_PROF_DBGIND,
|
||||
|
||||
/* A2E direction */
|
||||
SW_PROF_IRQ_A2E_TXCFM_BACK,
|
||||
|
||||
/****** Driver functions related signals ******/
|
||||
SW_PROF_WAIT_QUEUE_STOP,
|
||||
SW_PROF_WAIT_QUEUE_WAKEUP,
|
||||
SW_PROF_RWNXDATAIND,
|
||||
SW_PROF_RWNX_IPC_IRQ_HDLR,
|
||||
SW_PROF_RWNX_IPC_THR_IRQ_HDLR,
|
||||
SW_PROF_IEEE80211RX,
|
||||
SW_PROF_RWNX_PATTERN,
|
||||
SW_PROF_MAX
|
||||
};
|
||||
|
||||
// [LT]For debug purpose only
|
||||
#if (0)
|
||||
#define SW_PROF_CHAN_CTXT_CFM_HDL_BIT (21)
|
||||
#define SW_PROF_CHAN_CTXT_CFM_BIT (22)
|
||||
#define SW_PROF_CHAN_CTXT_CFM_SWDONE_BIT (23)
|
||||
#define SW_PROF_CHAN_CTXT_PUSH_BIT (24)
|
||||
#define SW_PROF_CHAN_CTXT_QUEUE_BIT (25)
|
||||
#define SW_PROF_CHAN_CTXT_TX_BIT (26)
|
||||
#define SW_PROF_CHAN_CTXT_TX_PAUSE_BIT (27)
|
||||
#define SW_PROF_CHAN_CTXT_PSWTCH_BIT (28)
|
||||
#define SW_PROF_CHAN_CTXT_SWTCH_BIT (29)
|
||||
|
||||
// TO DO: update this
|
||||
|
||||
#define REG_SW_SET_PROFILING_CHAN(env, bit) \
|
||||
rwnx_prof_set((struct rwnx_hw*)env, BIT(bit))
|
||||
|
||||
#define REG_SW_CLEAR_PROFILING_CHAN(env, bit) \
|
||||
rwnx_prof_clear((struct rwnx_hw*)env, BIT(bit))
|
||||
|
||||
#else
|
||||
#define SW_PROF_CHAN_CTXT_CFM_HDL_BIT (0)
|
||||
#define SW_PROF_CHAN_CTXT_CFM_BIT (0)
|
||||
#define SW_PROF_CHAN_CTXT_CFM_SWDONE_BIT (0)
|
||||
#define SW_PROF_CHAN_CTXT_PUSH_BIT (0)
|
||||
#define SW_PROF_CHAN_CTXT_QUEUE_BIT (0)
|
||||
#define SW_PROF_CHAN_CTXT_TX_BIT (0)
|
||||
#define SW_PROF_CHAN_CTXT_TX_PAUSE_BIT (0)
|
||||
#define SW_PROF_CHAN_CTXT_PSWTCH_BIT (0)
|
||||
#define SW_PROF_CHAN_CTXT_SWTCH_BIT (0)
|
||||
|
||||
#define REG_SW_SET_PROFILING_CHAN(env, bit) do {} while (0)
|
||||
#define REG_SW_CLEAR_PROFILING_CHAN(env, bit) do {} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RWNX_SW_PROFILING
|
||||
/* Macros for SW PRofiling registers access */
|
||||
#define REG_SW_SET_PROFILING(env, bit) \
|
||||
rwnx_prof_set((struct rwnx_hw*)env, BIT(bit))
|
||||
|
||||
#define REG_SW_SET_HOSTBUF_IDX_PROFILING(env, val) \
|
||||
rwnx_prof_set((struct rwnx_hw*)env, val<<(SW_PROF_HOSTBUF_IDX))
|
||||
|
||||
#define REG_SW_CLEAR_PROFILING(env, bit) \
|
||||
rwnx_prof_clear((struct rwnx_hw*)env, BIT(bit))
|
||||
|
||||
#define REG_SW_CLEAR_HOSTBUF_IDX_PROFILING(env) \
|
||||
rwnx_prof_clear((struct rwnx_hw*)env,0x0F<<(SW_PROF_HOSTBUF_IDX))
|
||||
|
||||
#else
|
||||
#define REG_SW_SET_PROFILING(env, value) do {} while (0)
|
||||
#define REG_SW_CLEAR_PROFILING(env, value) do {} while (0)
|
||||
#define REG_SW_SET_HOSTBUF_IDX_PROFILING(env, val) do {} while (0)
|
||||
#define REG_SW_CLEAR_HOSTBUF_IDX_PROFILING(env) do {} while (0)
|
||||
#endif
|
||||
|
||||
#endif /* _RWNX_PROF_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,160 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_radar.h
|
||||
*
|
||||
* @brief Functions to handle radar detection
|
||||
*
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#ifndef _RWNX_RADAR_H_
|
||||
#define _RWNX_RADAR_H_
|
||||
|
||||
#include <linux/nl80211.h>
|
||||
|
||||
struct rwnx_vif;
|
||||
struct rwnx_hw;
|
||||
|
||||
enum rwnx_radar_chain {
|
||||
RWNX_RADAR_RIU = 0,
|
||||
RWNX_RADAR_FCU,
|
||||
RWNX_RADAR_LAST
|
||||
};
|
||||
|
||||
enum rwnx_radar_detector {
|
||||
RWNX_RADAR_DETECT_DISABLE = 0, /* Ignore radar pulses */
|
||||
RWNX_RADAR_DETECT_ENABLE = 1, /* Process pattern detection but do not
|
||||
report radar to upper layer (for test) */
|
||||
RWNX_RADAR_DETECT_REPORT = 2 /* Process pattern detection and report
|
||||
radar to upper layer. */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_RWNX_RADAR
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#define RWNX_RADAR_PULSE_MAX 32
|
||||
|
||||
/**
|
||||
* struct rwnx_radar_pulses - List of pulses reported by HW
|
||||
* @index: write index
|
||||
* @count: number of valid pulses
|
||||
* @buffer: buffer of pulses
|
||||
*/
|
||||
struct rwnx_radar_pulses {
|
||||
/* Last radar pulses received */
|
||||
int index;
|
||||
int count;
|
||||
u32 buffer[RWNX_RADAR_PULSE_MAX];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dfs_pattern_detector - DFS pattern detector
|
||||
* @region: active DFS region, NL80211_DFS_UNSET until set
|
||||
* @num_radar_types: number of different radar types
|
||||
* @last_pulse_ts: time stamp of last valid pulse in usecs
|
||||
* @prev_jiffies:
|
||||
* @radar_detector_specs: array of radar detection specs
|
||||
* @channel_detectors: list connecting channel_detector elements
|
||||
*/
|
||||
struct dfs_pattern_detector {
|
||||
u8 enabled;
|
||||
enum nl80211_dfs_regions region;
|
||||
u8 num_radar_types;
|
||||
u64 last_pulse_ts;
|
||||
u32 prev_jiffies;
|
||||
const struct radar_detector_specs *radar_spec;
|
||||
struct list_head detectors[];
|
||||
};
|
||||
|
||||
#define NX_NB_RADAR_DETECTED 4
|
||||
|
||||
/**
|
||||
* struct rwnx_radar_detected - List of radar detected
|
||||
*/
|
||||
struct rwnx_radar_detected {
|
||||
u16 index;
|
||||
u16 count;
|
||||
s64 time[NX_NB_RADAR_DETECTED];
|
||||
s16 freq[NX_NB_RADAR_DETECTED];
|
||||
};
|
||||
|
||||
|
||||
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];
|
||||
struct work_struct detection_work; /* Work used to process radar pulses */
|
||||
spinlock_t lock; /* lock for pulses processing */
|
||||
|
||||
/* In softmac cac is handled by mac80211 */
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
struct delayed_work cac_work; /* Work used to handle CAC */
|
||||
struct rwnx_vif *cac_vif; /* vif on which we started CAC */
|
||||
#endif
|
||||
};
|
||||
|
||||
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,
|
||||
enum nl80211_dfs_regions region);
|
||||
void rwnx_radar_detection_enable(struct rwnx_radar *radar, u8 enable, u8 chain);
|
||||
bool rwnx_radar_detection_is_enable(struct rwnx_radar *radar, u8 chain);
|
||||
void rwnx_radar_start_cac(struct rwnx_radar *radar, u32 cac_time_ms,
|
||||
struct rwnx_vif *vif);
|
||||
void rwnx_radar_cancel_cac(struct rwnx_radar *radar);
|
||||
void rwnx_radar_detection_enable_on_cur_channel(struct rwnx_hw *rwnx_hw);
|
||||
int rwnx_radar_dump_pattern_detector(char *buf, size_t len,
|
||||
struct rwnx_radar *radar, u8 chain);
|
||||
int rwnx_radar_dump_radar_detected(char *buf, size_t len,
|
||||
struct rwnx_radar *radar, u8 chain);
|
||||
|
||||
#else
|
||||
|
||||
struct rwnx_radar {
|
||||
};
|
||||
|
||||
static inline bool rwnx_radar_detection_init(struct rwnx_radar *radar)
|
||||
{return true;}
|
||||
|
||||
static inline void rwnx_radar_detection_deinit(struct rwnx_radar *radar)
|
||||
{}
|
||||
|
||||
static inline bool rwnx_radar_set_domain(struct rwnx_radar *radar,
|
||||
enum nl80211_dfs_regions region)
|
||||
{return true;}
|
||||
|
||||
static inline void rwnx_radar_detection_enable(struct rwnx_radar *radar,
|
||||
u8 enable, u8 chain)
|
||||
{}
|
||||
|
||||
static inline bool rwnx_radar_detection_is_enable(struct rwnx_radar *radar,
|
||||
u8 chain)
|
||||
{return false;}
|
||||
|
||||
static inline void rwnx_radar_start_cac(struct rwnx_radar *radar,
|
||||
u32 cac_time_ms, struct rwnx_vif *vif)
|
||||
{}
|
||||
|
||||
static inline void rwnx_radar_cancel_cac(struct rwnx_radar *radar)
|
||||
{}
|
||||
|
||||
static inline void rwnx_radar_detection_enable_on_cur_channel(struct rwnx_hw *rwnx_hw)
|
||||
{}
|
||||
|
||||
static inline int rwnx_radar_dump_pattern_detector(char *buf, size_t len,
|
||||
struct rwnx_radar *radar,
|
||||
u8 chain)
|
||||
{return 0;}
|
||||
|
||||
static inline int rwnx_radar_dump_radar_detected(char *buf, size_t len,
|
||||
struct rwnx_radar *radar,
|
||||
u8 chain)
|
||||
{return 0;}
|
||||
|
||||
#endif /* CONFIG_RWNX_RADAR */
|
||||
|
||||
#endif // _RWNX_RADAR_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,402 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_rx.h
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#ifndef _RWNX_RX_H_
|
||||
#define _RWNX_RX_H_
|
||||
|
||||
#include "aicwf_txrxif.h"
|
||||
|
||||
#define SERVER_PORT 67
|
||||
#define CLIENT_PORT 68
|
||||
#define DHCP_MAGIC 0x63825363
|
||||
#define DHCP_ACK 5
|
||||
#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */
|
||||
#define DHCP_OPTION_END 255
|
||||
|
||||
enum rx_status_bits
|
||||
{
|
||||
/// The buffer can be forwarded to the networking stack
|
||||
RX_STAT_FORWARD = 1 << 0,
|
||||
/// A new buffer has to be allocated
|
||||
RX_STAT_ALLOC = 1 << 1,
|
||||
/// The buffer has to be deleted
|
||||
RX_STAT_DELETE = 1 << 2,
|
||||
/// The length of the buffer has to be updated
|
||||
RX_STAT_LEN_UPDATE = 1 << 3,
|
||||
/// The length in the Ethernet header has to be updated
|
||||
RX_STAT_ETH_LEN_UPDATE = 1 << 4,
|
||||
/// Simple copy
|
||||
RX_STAT_COPY = 1 << 5,
|
||||
/// Spurious frame (inform upper layer and discard)
|
||||
RX_STAT_SPURIOUS = 1 << 6,
|
||||
/// packet for monitor interface
|
||||
RX_STAT_MONITOR = 1 << 7,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Decryption status subfields.
|
||||
* {
|
||||
*/
|
||||
#define RWNX_RX_HD_DECR_UNENC 0 // ENCRYPTION TYPE NONE
|
||||
#define RWNX_RX_HD_DECR_WEP 1 // ENCRYPTION TYPE WEP
|
||||
#define RWNX_RX_HD_DECR_TKIP 2 // ENCRYPTION TYPE TKIP
|
||||
#define RWNX_RX_HD_DECR_CCMP128 3 // ENCRYPTION TYPE CCMP128
|
||||
#define RWNX_RX_HD_DECR_CCMP256 4 // ENCRYPTION TYPE CCMP256
|
||||
#define RWNX_RX_HD_DECR_GCMP128 5 // ENCRYPTION TYPE GCMP128
|
||||
#define RWNX_RX_HD_DECR_GCMP256 6 // ENCRYPTION TYPE GCMP256
|
||||
#define RWNX_RX_HD_DECR_WAPI 7 // ENCRYPTION TYPE WAPI
|
||||
// @}
|
||||
|
||||
//#ifdef CONFIG_RWNX_MON_DATA
|
||||
#if 0
|
||||
#define RX_MACHDR_BACKUP_LEN 64
|
||||
#endif
|
||||
|
||||
struct rx_vector_1_old {
|
||||
/** Receive Vector 1a */
|
||||
u32 leg_length :12;
|
||||
u32 leg_rate : 4;
|
||||
u32 ht_length :16;
|
||||
|
||||
/** Receive Vector 1b */
|
||||
u32 _ht_length : 4; // FIXME
|
||||
u32 short_gi : 1;
|
||||
u32 stbc : 2;
|
||||
u32 smoothing : 1;
|
||||
u32 mcs : 7;
|
||||
u32 pre_type : 1;
|
||||
u32 format_mod : 3;
|
||||
u32 ch_bw : 2;
|
||||
u32 n_sts : 3;
|
||||
u32 lsig_valid : 1;
|
||||
u32 sounding : 1;
|
||||
u32 num_extn_ss : 2;
|
||||
u32 aggregation : 1;
|
||||
u32 fec_coding : 1;
|
||||
u32 dyn_bw : 1;
|
||||
u32 doze_not_allowed : 1;
|
||||
|
||||
/** Receive Vector 1c */
|
||||
u32 antenna_set : 8;
|
||||
u32 partial_aid : 9;
|
||||
u32 group_id : 6;
|
||||
u32 first_user : 1;
|
||||
s32 rssi1 : 8;
|
||||
|
||||
/** Receive Vector 1d */
|
||||
s32 rssi2 : 8;
|
||||
s32 rssi3 : 8;
|
||||
s32 rssi4 : 8;
|
||||
u32 reserved_1d : 8;
|
||||
};
|
||||
|
||||
struct rx_leg_vect
|
||||
{
|
||||
u8 dyn_bw_in_non_ht : 1;
|
||||
u8 chn_bw_in_non_ht : 2;
|
||||
u8 rsvd_nht : 4;
|
||||
u8 lsig_valid : 1;
|
||||
} __packed;
|
||||
|
||||
struct rx_ht_vect
|
||||
{
|
||||
u16 sounding : 1;
|
||||
u16 smoothing : 1;
|
||||
u16 short_gi : 1;
|
||||
u16 aggregation : 1;
|
||||
u16 stbc : 1;
|
||||
u16 num_extn_ss : 2;
|
||||
u16 lsig_valid : 1;
|
||||
u16 mcs : 7;
|
||||
u16 fec : 1;
|
||||
u16 length :16;
|
||||
} __packed;
|
||||
|
||||
struct rx_vht_vect
|
||||
{
|
||||
u8 sounding : 1;
|
||||
u8 beamformed : 1;
|
||||
u8 short_gi : 1;
|
||||
u8 rsvd_vht1 : 1;
|
||||
u8 stbc : 1;
|
||||
u8 doze_not_allowed : 1;
|
||||
u8 first_user : 1;
|
||||
u8 rsvd_vht2 : 1;
|
||||
u16 partial_aid : 9;
|
||||
u16 group_id : 6;
|
||||
u16 rsvd_vht3 : 1;
|
||||
u32 mcs : 4;
|
||||
u32 nss : 3;
|
||||
u32 fec : 1;
|
||||
u32 length :20;
|
||||
u32 rsvd_vht4 : 4;
|
||||
} __packed;
|
||||
|
||||
struct rx_he_vect
|
||||
{
|
||||
u8 sounding : 1;
|
||||
u8 beamformed : 1;
|
||||
u8 gi_type : 2;
|
||||
u8 stbc : 1;
|
||||
u8 rsvd_he1 : 3;
|
||||
|
||||
u8 uplink_flag : 1;
|
||||
u8 beam_change : 1;
|
||||
u8 dcm : 1;
|
||||
u8 he_ltf_type : 2;
|
||||
u8 doppler : 1;
|
||||
u8 rsvd_he2 : 2;
|
||||
|
||||
u8 bss_color : 6;
|
||||
u8 rsvd_he3 : 2;
|
||||
|
||||
u8 txop_duration : 7;
|
||||
u8 rsvd_he4 : 1;
|
||||
|
||||
u8 pe_duration : 4;
|
||||
u8 spatial_reuse : 4;
|
||||
|
||||
u8 sig_b_comp_mode : 1;
|
||||
u8 dcm_sig_b : 1;
|
||||
u8 mcs_sig_b : 3;
|
||||
u8 ru_size : 3;
|
||||
|
||||
u32 mcs : 4;
|
||||
u32 nss : 3;
|
||||
u32 fec : 1;
|
||||
u32 length :20;
|
||||
u32 rsvd_he6 : 4;
|
||||
} __packed;
|
||||
|
||||
struct rx_vector_1 {
|
||||
u8 format_mod : 4;
|
||||
u8 ch_bw : 3;
|
||||
u8 pre_type : 1;
|
||||
u8 antenna_set : 8;
|
||||
s32 rssi_leg : 8;
|
||||
u32 leg_length :12;
|
||||
u32 leg_rate : 4;
|
||||
s32 rssi1 : 8;
|
||||
|
||||
union
|
||||
{
|
||||
struct rx_leg_vect leg;
|
||||
struct rx_ht_vect ht;
|
||||
struct rx_vht_vect vht;
|
||||
struct rx_he_vect he;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct rx_vector_2_old {
|
||||
/** Receive Vector 2a */
|
||||
u32 rcpi : 8;
|
||||
u32 evm1 : 8;
|
||||
u32 evm2 : 8;
|
||||
u32 evm3 : 8;
|
||||
|
||||
/** Receive Vector 2b */
|
||||
u32 evm4 : 8;
|
||||
u32 reserved2b_1 : 8;
|
||||
u32 reserved2b_2 : 8;
|
||||
u32 reserved2b_3 : 8;
|
||||
|
||||
};
|
||||
|
||||
struct rx_vector_2 {
|
||||
/** Receive Vector 2a */
|
||||
u32 rcpi1 : 8;
|
||||
u32 rcpi2 : 8;
|
||||
u32 rcpi3 : 8;
|
||||
u32 rcpi4 : 8;
|
||||
|
||||
/** Receive Vector 2b */
|
||||
u32 evm1 : 8;
|
||||
u32 evm2 : 8;
|
||||
u32 evm3 : 8;
|
||||
u32 evm4 : 8;
|
||||
};
|
||||
|
||||
struct phy_channel_info_desc {
|
||||
/** PHY channel information 1 */
|
||||
u32 phy_band : 8;
|
||||
u32 phy_channel_type : 8;
|
||||
u32 phy_prim20_freq : 16;
|
||||
/** PHY channel information 2 */
|
||||
u32 phy_center1_freq : 16;
|
||||
u32 phy_center2_freq : 16;
|
||||
};
|
||||
|
||||
struct hw_vect {
|
||||
/** Total length for the MPDU transfer */
|
||||
u32 len :16;
|
||||
|
||||
u32 reserved : 8;//data type is included
|
||||
/** AMPDU Status Information */
|
||||
u32 mpdu_cnt : 6;
|
||||
u32 ampdu_cnt : 2;
|
||||
|
||||
/** TSF Low */
|
||||
__le32 tsf_lo;
|
||||
/** TSF High */
|
||||
__le32 tsf_hi;
|
||||
|
||||
/** Receive Vector 1 */
|
||||
struct rx_vector_1 rx_vect1;
|
||||
/** Receive Vector 2 */
|
||||
struct rx_vector_2 rx_vect2;
|
||||
|
||||
/** Status **/
|
||||
u32 rx_vect2_valid : 1;
|
||||
u32 resp_frame : 1;
|
||||
/** Decryption Status */
|
||||
u32 decr_status : 3;
|
||||
u32 rx_fifo_oflow : 1;
|
||||
|
||||
/** Frame Unsuccessful */
|
||||
u32 undef_err : 1;
|
||||
u32 phy_err : 1;
|
||||
u32 fcs_err : 1;
|
||||
u32 addr_mismatch : 1;
|
||||
u32 ga_frame : 1;
|
||||
u32 current_ac : 2;
|
||||
|
||||
u32 frm_successful_rx : 1;
|
||||
/** Descriptor Done */
|
||||
u32 desc_done_rx : 1;
|
||||
/** Key Storage RAM Index */
|
||||
u32 key_sram_index : 10;
|
||||
/** Key Storage RAM Index Valid */
|
||||
u32 key_sram_v : 1;
|
||||
u32 type : 2;
|
||||
u32 subtype : 4;
|
||||
};
|
||||
|
||||
//#ifdef CONFIG_RWNX_MON_DATA
|
||||
#if 0
|
||||
/// MAC header backup descriptor
|
||||
struct mon_machdrdesc
|
||||
{
|
||||
/// Length of the buffer
|
||||
u32 buf_len;
|
||||
/// Buffer containing mac header, LLC and SNAP
|
||||
u8 buffer[RX_MACHDR_BACKUP_LEN];
|
||||
};
|
||||
#endif
|
||||
|
||||
struct hw_rxhdr {
|
||||
/** RX vector */
|
||||
struct hw_vect hwvect;
|
||||
|
||||
/** PHY channel information */
|
||||
struct phy_channel_info_desc phy_info;
|
||||
|
||||
/** RX flags */
|
||||
u32 flags_is_amsdu : 1;
|
||||
u32 flags_is_80211_mpdu: 1;
|
||||
u32 flags_is_4addr : 1;
|
||||
u32 flags_new_peer : 1;
|
||||
#if defined(AICWF_SDIO_SUPPORT) || defined(AICWF_USB_SUPPORT)
|
||||
u32 flags_user_prio : 1; // aic: fw not fill any more
|
||||
u32 flags_need_reord : 1;
|
||||
u32 flags_upload : 1;
|
||||
#else
|
||||
u32 flags_user_prio : 3;
|
||||
#endif
|
||||
#ifndef AICWF_RX_REORDER
|
||||
u32 flags_rsvd0 : 1;
|
||||
#else
|
||||
u32 is_monitor_vif : 1;
|
||||
#endif
|
||||
u32 flags_vif_idx : 8; // 0xFF if invalid VIF index
|
||||
u32 flags_sta_idx : 8; // 0xFF if invalid STA index
|
||||
u32 flags_dst_idx : 8; // 0xFF if unknown destination STA
|
||||
//#ifdef CONFIG_RWNX_MON_DATA
|
||||
#if 0
|
||||
/// MAC header backup descriptor (used only for MSDU when there is a monitor and a data interface)
|
||||
struct mon_machdrdesc mac_hdr_backup;
|
||||
#endif
|
||||
/** Pattern indicating if the buffer is available for the driver */
|
||||
u32 pattern;
|
||||
};
|
||||
|
||||
extern const u8 legrates_lut[];
|
||||
extern u16 legrates_lut_rate[];
|
||||
extern u16 tx_legrates_lut_rate[];
|
||||
|
||||
struct DHCPInfo {
|
||||
u8 op;
|
||||
u8 htype;
|
||||
u8 hlen;
|
||||
u8 hops;
|
||||
u32 xid;
|
||||
u16 secs;
|
||||
u16 flags;
|
||||
u32 ciaddr;
|
||||
u32 yiaddr;
|
||||
u32 siaddr;
|
||||
u32 giaddr;
|
||||
u8 chaddr[16];
|
||||
u8 sname[64];
|
||||
u8 file[128];
|
||||
u32 cookie;
|
||||
u8 options[308]; /* 312 - cookie */
|
||||
};
|
||||
|
||||
u8 rwnx_unsup_rx_vec_ind(void *pthis, void *hostid);
|
||||
u8 rwnx_rxdataind(void *pthis, void *hostid);
|
||||
u8 rwnx_rxdataind_aicwf(struct rwnx_hw *rwnx_hw, void *hostid, void *rx_priv);
|
||||
int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv);
|
||||
#ifdef CONFIG_USB_MSG_IN_EP
|
||||
int aicwf_process_msg_rxframes(struct aicwf_rx_priv *rx_priv);
|
||||
#endif
|
||||
|
||||
#ifdef AICWF_ARP_OFFLOAD
|
||||
void arpoffload_proc(struct sk_buff *skb, struct rwnx_vif *rwnx_vif);
|
||||
#endif
|
||||
#ifdef AICWF_RX_REORDER
|
||||
struct recv_msdu *reord_rxframe_alloc(spinlock_t *lock, struct list_head *q);
|
||||
void reord_rxframe_free(spinlock_t *lock, struct list_head *q, struct list_head *list);
|
||||
struct reord_ctrl_info *reord_init_sta( struct aicwf_rx_priv *rx_priv, const u8 *mac_addr);
|
||||
void reord_deinit_sta(struct aicwf_rx_priv *rx_priv, struct reord_ctrl_info *reord_info);
|
||||
int reord_need_check(struct reord_ctrl *preorder_ctrl, u16 seq_num);
|
||||
int reord_rxframe_enqueue(struct reord_ctrl *preorder_ctrl, struct recv_msdu *prframe);
|
||||
void reord_timeout_worker(struct work_struct *work);
|
||||
int reord_single_frame_ind(struct aicwf_rx_priv *rx_priv, struct recv_msdu *prframe);
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0)
|
||||
void reord_timeout_handler (ulong data);
|
||||
#else
|
||||
void reord_timeout_handler (struct timer_list *t);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HE_FOR_OLD_KERNEL
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 197)
|
||||
struct element {
|
||||
u8 id;
|
||||
u8 datalen;
|
||||
u8 data[];
|
||||
};
|
||||
/* element iteration helpers */
|
||||
#define for_each_element(_elem, _data, _datalen) \
|
||||
for (_elem = (const struct element *)(_data); \
|
||||
(const u8 *)(_data) + (_datalen) - (const u8 *)_elem >= \
|
||||
(int)sizeof(*_elem) && \
|
||||
(const u8 *)(_data) + (_datalen) - (const u8 *)_elem >= \
|
||||
(int)sizeof(*_elem) + _elem->datalen; \
|
||||
_elem = (const struct element *)(_elem->data + _elem->datalen))
|
||||
|
||||
#define for_each_element_id(element, _id, data, datalen) \
|
||||
for_each_element(element, data, datalen) \
|
||||
if (element->id == (_id))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* _RWNX_RX_H_ */
|
||||
@@ -0,0 +1,267 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_strs.c
|
||||
*
|
||||
* @brief Miscellaneous debug strings
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2014-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "lmac_msg.h"
|
||||
|
||||
static const char *const rwnx_mmid2str[MSG_I(MM_MAX)] = {
|
||||
[MSG_I(MM_RESET_REQ)] = "MM_RESET_REQ",
|
||||
[MSG_I(MM_RESET_CFM)] = "MM_RESET_CFM",
|
||||
[MSG_I(MM_START_REQ)] = "MM_START_REQ",
|
||||
[MSG_I(MM_START_CFM)] = "MM_START_CFM",
|
||||
[MSG_I(MM_VERSION_REQ)] = "MM_VERSION_REQ",
|
||||
[MSG_I(MM_VERSION_CFM)] = "MM_VERSION_CFM",
|
||||
[MSG_I(MM_ADD_IF_REQ)] = "MM_ADD_IF_REQ",
|
||||
[MSG_I(MM_ADD_IF_CFM)] = "MM_ADD_IF_CFM",
|
||||
[MSG_I(MM_REMOVE_IF_REQ)] = "MM_REMOVE_IF_REQ",
|
||||
[MSG_I(MM_REMOVE_IF_CFM)] = "MM_REMOVE_IF_CFM",
|
||||
[MSG_I(MM_STA_ADD_REQ)] = "MM_STA_ADD_REQ",
|
||||
[MSG_I(MM_STA_ADD_CFM)] = "MM_STA_ADD_CFM",
|
||||
[MSG_I(MM_STA_DEL_REQ)] = "MM_STA_DEL_REQ",
|
||||
[MSG_I(MM_STA_DEL_CFM)] = "MM_STA_DEL_CFM",
|
||||
[MSG_I(MM_SET_FILTER_REQ)] = "MM_SET_FILTER_REQ",
|
||||
[MSG_I(MM_SET_FILTER_CFM)] = "MM_SET_FILTER_CFM",
|
||||
[MSG_I(MM_SET_CHANNEL_REQ)] = "MM_SET_CHANNEL_REQ",
|
||||
[MSG_I(MM_SET_CHANNEL_CFM)] = "MM_SET_CHANNEL_CFM",
|
||||
[MSG_I(MM_SET_DTIM_REQ)] = "MM_SET_DTIM_REQ",
|
||||
[MSG_I(MM_SET_DTIM_CFM)] = "MM_SET_DTIM_CFM",
|
||||
[MSG_I(MM_SET_BEACON_INT_REQ)] = "MM_SET_BEACON_INT_REQ",
|
||||
[MSG_I(MM_SET_BEACON_INT_CFM)] = "MM_SET_BEACON_INT_CFM",
|
||||
[MSG_I(MM_SET_BASIC_RATES_REQ)] = "MM_SET_BASIC_RATES_REQ",
|
||||
[MSG_I(MM_SET_BASIC_RATES_CFM)] = "MM_SET_BASIC_RATES_CFM",
|
||||
[MSG_I(MM_SET_BSSID_REQ)] = "MM_SET_BSSID_REQ",
|
||||
[MSG_I(MM_SET_BSSID_CFM)] = "MM_SET_BSSID_CFM",
|
||||
[MSG_I(MM_SET_EDCA_REQ)] = "MM_SET_EDCA_REQ",
|
||||
[MSG_I(MM_SET_EDCA_CFM)] = "MM_SET_EDCA_CFM",
|
||||
[MSG_I(MM_SET_MODE_REQ)] = "MM_SET_MODE_REQ",
|
||||
[MSG_I(MM_SET_MODE_CFM)] = "MM_SET_MODE_CFM",
|
||||
[MSG_I(MM_SET_VIF_STATE_REQ)] = "MM_SET_VIF_STATE_REQ",
|
||||
[MSG_I(MM_SET_VIF_STATE_CFM)] = "MM_SET_VIF_STATE_CFM",
|
||||
[MSG_I(MM_SET_SLOTTIME_REQ)] = "MM_SET_SLOTTIME_REQ",
|
||||
[MSG_I(MM_SET_SLOTTIME_CFM)] = "MM_SET_SLOTTIME_CFM",
|
||||
[MSG_I(MM_SET_IDLE_REQ)] = "MM_SET_IDLE_REQ",
|
||||
[MSG_I(MM_SET_IDLE_CFM)] = "MM_SET_IDLE_CFM",
|
||||
[MSG_I(MM_KEY_ADD_REQ)] = "MM_KEY_ADD_REQ",
|
||||
[MSG_I(MM_KEY_ADD_CFM)] = "MM_KEY_ADD_CFM",
|
||||
[MSG_I(MM_KEY_DEL_REQ)] = "MM_KEY_DEL_REQ",
|
||||
[MSG_I(MM_KEY_DEL_CFM)] = "MM_KEY_DEL_CFM",
|
||||
[MSG_I(MM_BA_ADD_REQ)] = "MM_BA_ADD_REQ",
|
||||
[MSG_I(MM_BA_ADD_CFM)] = "MM_BA_ADD_CFM",
|
||||
[MSG_I(MM_BA_DEL_REQ)] = "MM_BA_DEL_REQ",
|
||||
[MSG_I(MM_BA_DEL_CFM)] = "MM_BA_DEL_CFM",
|
||||
[MSG_I(MM_PRIMARY_TBTT_IND)] = "MM_PRIMARY_TBTT_IND",
|
||||
[MSG_I(MM_SECONDARY_TBTT_IND)] = "MM_SECONDARY_TBTT_IND",
|
||||
[MSG_I(MM_SET_POWER_REQ)] = "MM_SET_POWER_REQ",
|
||||
[MSG_I(MM_SET_POWER_CFM)] = "MM_SET_POWER_CFM",
|
||||
[MSG_I(MM_DBG_TRIGGER_REQ)] = "MM_DBG_TRIGGER_REQ",
|
||||
[MSG_I(MM_SET_PS_MODE_REQ)] = "MM_SET_PS_MODE_REQ",
|
||||
[MSG_I(MM_SET_PS_MODE_CFM)] = "MM_SET_PS_MODE_CFM",
|
||||
[MSG_I(MM_CHAN_CTXT_ADD_REQ)] = "MM_CHAN_CTXT_ADD_REQ",
|
||||
[MSG_I(MM_CHAN_CTXT_ADD_CFM)] = "MM_CHAN_CTXT_ADD_CFM",
|
||||
[MSG_I(MM_CHAN_CTXT_DEL_REQ)] = "MM_CHAN_CTXT_DEL_REQ",
|
||||
[MSG_I(MM_CHAN_CTXT_DEL_CFM)] = "MM_CHAN_CTXT_DEL_CFM",
|
||||
[MSG_I(MM_CHAN_CTXT_LINK_REQ)] = "MM_CHAN_CTXT_LINK_REQ",
|
||||
[MSG_I(MM_CHAN_CTXT_LINK_CFM)] = "MM_CHAN_CTXT_LINK_CFM",
|
||||
[MSG_I(MM_CHAN_CTXT_UNLINK_REQ)] = "MM_CHAN_CTXT_UNLINK_REQ",
|
||||
[MSG_I(MM_CHAN_CTXT_UNLINK_CFM)] = "MM_CHAN_CTXT_UNLINK_CFM",
|
||||
[MSG_I(MM_CHAN_CTXT_UPDATE_REQ)] = "MM_CHAN_CTXT_UPDATE_REQ",
|
||||
[MSG_I(MM_CHAN_CTXT_UPDATE_CFM)] = "MM_CHAN_CTXT_UPDATE_CFM",
|
||||
[MSG_I(MM_CHAN_CTXT_SCHED_REQ)] = "MM_CHAN_CTXT_SCHED_REQ",
|
||||
[MSG_I(MM_CHAN_CTXT_SCHED_CFM)] = "MM_CHAN_CTXT_SCHED_CFM",
|
||||
[MSG_I(MM_BCN_CHANGE_REQ)] = "MM_BCN_CHANGE_REQ",
|
||||
[MSG_I(MM_BCN_CHANGE_CFM)] = "MM_BCN_CHANGE_CFM",
|
||||
[MSG_I(MM_TIM_UPDATE_REQ)] = "MM_TIM_UPDATE_REQ",
|
||||
[MSG_I(MM_TIM_UPDATE_CFM)] = "MM_TIM_UPDATE_CFM",
|
||||
[MSG_I(MM_CONNECTION_LOSS_IND)] = "MM_CONNECTION_LOSS_IND",
|
||||
[MSG_I(MM_CHANNEL_SWITCH_IND)] = "MM_CHANNEL_SWITCH_IND",
|
||||
[MSG_I(MM_CHANNEL_PRE_SWITCH_IND)] = "MM_CHANNEL_PRE_SWITCH_IND",
|
||||
[MSG_I(MM_REMAIN_ON_CHANNEL_REQ)] = "MM_REMAIN_ON_CHANNEL_REQ",
|
||||
[MSG_I(MM_REMAIN_ON_CHANNEL_CFM)] = "MM_REMAIN_ON_CHANNEL_CFM",
|
||||
[MSG_I(MM_REMAIN_ON_CHANNEL_EXP_IND)] = "MM_REMAIN_ON_CHANNEL_EXP_IND",
|
||||
[MSG_I(MM_PS_CHANGE_IND)] = "MM_PS_CHANGE_IND",
|
||||
[MSG_I(MM_TRAFFIC_REQ_IND)] = "MM_TRAFFIC_REQ_IND",
|
||||
[MSG_I(MM_SET_PS_OPTIONS_REQ)] = "MM_SET_PS_OPTIONS_REQ",
|
||||
[MSG_I(MM_SET_PS_OPTIONS_CFM)] = "MM_SET_PS_OPTIONS_CFM",
|
||||
[MSG_I(MM_P2P_VIF_PS_CHANGE_IND)] = "MM_P2P_VIF_PS_CHANGE_IND",
|
||||
[MSG_I(MM_CSA_COUNTER_IND)] = "MM_CSA_COUNTER_IND",
|
||||
[MSG_I(MM_CHANNEL_SURVEY_IND)] = "MM_CHANNEL_SURVEY_IND",
|
||||
[MSG_I(MM_SET_P2P_NOA_REQ)] = "MM_SET_P2P_NOA_REQ",
|
||||
[MSG_I(MM_SET_P2P_OPPPS_REQ)] = "MM_SET_P2P_OPPPS_REQ",
|
||||
[MSG_I(MM_SET_P2P_NOA_CFM)] = "MM_SET_P2P_NOA_CFM",
|
||||
[MSG_I(MM_SET_P2P_OPPPS_CFM)] = "MM_SET_P2P_OPPPS_CFM",
|
||||
[MSG_I(MM_CFG_RSSI_REQ)] = "MM_CFG_RSSI_REQ",
|
||||
[MSG_I(MM_RSSI_STATUS_IND)] = "MM_RSSI_STATUS_IND",
|
||||
[MSG_I(MM_CSA_FINISH_IND)] = "MM_CSA_FINISH_IND",
|
||||
[MSG_I(MM_CSA_TRAFFIC_IND)] = "MM_CSA_TRAFFIC_IND",
|
||||
[MSG_I(MM_MU_GROUP_UPDATE_REQ)] = "MM_MU_GROUP_UPDATE_REQ",
|
||||
[MSG_I(MM_MU_GROUP_UPDATE_CFM)] = "MM_MU_GROUP_UPDATE_CFM",
|
||||
|
||||
[MSG_I(MM_SET_ARPOFFLOAD_REQ)] = "MM_SET_ARPOFFLOAD_REQ",
|
||||
[MSG_I(MM_SET_ARPOFFLOAD_CFM)] = "MM_SET_ARPOFFLOAD_CFM",
|
||||
[MSG_I(MM_SET_AGG_DISABLE_REQ)] = "MM_SET_AGG_DISABLE_REQ",
|
||||
[MSG_I(MM_SET_AGG_DISABLE_CFM)] = "MM_SET_AGG_DISABLE_CFM",
|
||||
[MSG_I(MM_SET_COEX_REQ)] = "MM_SET_COEX_REQ",
|
||||
[MSG_I(MM_SET_COEX_CFM)] = "MM_SET_COEX_CFM",
|
||||
[MSG_I(MM_SET_RF_CONFIG_REQ)] = "MM_SET_RF_CONFIG_REQ",
|
||||
[MSG_I(MM_SET_RF_CONFIG_CFM)] = "MM_SET_RF_CONFIG_CFM",
|
||||
[MSG_I(MM_SET_RF_CALIB_REQ)] = "MM_SET_RF_CALIB_REQ",
|
||||
[MSG_I(MM_SET_RF_CALIB_CFM)] = "MM_SET_RF_CALIB_CFM",
|
||||
|
||||
[MSG_I(MM_GET_MAC_ADDR_REQ)] = "MM_GET_MAC_ADDR_REQ",
|
||||
[MSG_I(MM_GET_MAC_ADDR_CFM)] = "MM_GET_MAC_ADDR_CFM",
|
||||
[MSG_I(MM_GET_STA_INFO_REQ)] = "MM_GET_STA_INFO_REQ",
|
||||
[MSG_I(MM_GET_STA_INFO_CFM)] = "MM_GET_STA_INFO_CFM",
|
||||
[MSG_I(MM_SET_TXPWR_IDX_LVL_REQ)] = "MM_SET_TXPWR_IDX_LVL_REQ",
|
||||
[MSG_I(MM_SET_TXPWR_IDX_LVL_CFM)] = "MM_SET_TXPWR_IDX_LVL_CFM",
|
||||
[MSG_I(MM_SET_TXPWR_OFST_REQ)] = "MM_SET_TXPWR_OFST_REQ",
|
||||
[MSG_I(MM_SET_TXPWR_OFST_CFM)] = "MM_SET_TXPWR_OFST_CFM",
|
||||
[MSG_I(MM_SET_STACK_START_REQ)] = "MM_SET_STACK_START_REQ",
|
||||
[MSG_I(MM_SET_STACK_START_CFM)] = "MM_SET_STACK_START_CFM",
|
||||
[MSG_I(MM_APM_STALOSS_IND)] = "MM_APM_STALOSS_IND",
|
||||
[MSG_I(MM_SET_VENDOR_HWCONFIG_REQ)] = "MM_SET_VENDOR_HWCONFIG_REQ",
|
||||
[MSG_I(MM_SET_VENDOR_HWCONFIG_CFM)] = "MM_SET_VENDOR_HWCONFIG_CFM",
|
||||
[MSG_I(MM_GET_FW_VERSION_REQ)] = "MM_GET_FW_VERSION_REQ",
|
||||
[MSG_I(MM_GET_FW_VERSION_CFM)] = "MM_GET_FW_VERSION_CFM",
|
||||
[MSG_I(MM_SET_RESUME_RESTORE_REQ)] = "MM_SET_RESUME_RESTORE_REQ",
|
||||
[MSG_I(MM_SET_RESUME_RESTORE_CFM)] = "MM_SET_RESUME_RESTORE_CFM",
|
||||
[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",
|
||||
};
|
||||
|
||||
static const char *const rwnx_dbgid2str[MSG_I(DBG_MAX)] = {
|
||||
[MSG_I(DBG_MEM_READ_REQ)] = "DBG_MEM_READ_REQ",
|
||||
[MSG_I(DBG_MEM_READ_CFM)] = "DBG_MEM_READ_CFM",
|
||||
[MSG_I(DBG_MEM_WRITE_REQ)] = "DBG_MEM_WRITE_REQ",
|
||||
[MSG_I(DBG_MEM_WRITE_CFM)] = "DBG_MEM_WRITE_CFM",
|
||||
[MSG_I(DBG_SET_MOD_FILTER_REQ)] = "DBG_SET_MOD_FILTER_REQ",
|
||||
[MSG_I(DBG_SET_MOD_FILTER_CFM)] = "DBG_SET_MOD_FILTER_CFM",
|
||||
[MSG_I(DBG_SET_SEV_FILTER_REQ)] = "DBG_SET_SEV_FILTER_REQ",
|
||||
[MSG_I(DBG_SET_SEV_FILTER_CFM)] = "DBG_SET_SEV_FILTER_CFM",
|
||||
[MSG_I(DBG_ERROR_IND)] = "DBG_ERROR_IND",
|
||||
[MSG_I(DBG_GET_SYS_STAT_REQ)] = "DBG_GET_SYS_STAT_REQ",
|
||||
[MSG_I(DBG_GET_SYS_STAT_CFM)] = "DBG_GET_SYS_STAT_CFM",
|
||||
};
|
||||
|
||||
static const char *const rwnx_scanid2str[MSG_I(SCAN_MAX)] = {
|
||||
[MSG_I(SCAN_START_REQ)] = "SCAN_START_REQ",
|
||||
[MSG_I(SCAN_START_CFM)] = "SCAN_START_CFM",
|
||||
[MSG_I(SCAN_DONE_IND)] = "SCAN_DONE_IND",
|
||||
};
|
||||
|
||||
static const char *const rwnx_tdlsid2str[MSG_I(TDLS_MAX)] = {
|
||||
[MSG_I(TDLS_CHAN_SWITCH_CFM)] = "TDLS_CHAN_SWITCH_CFM",
|
||||
[MSG_I(TDLS_CHAN_SWITCH_REQ)] = "TDLS_CHAN_SWITCH_REQ",
|
||||
[MSG_I(TDLS_CHAN_SWITCH_IND)] = "TDLS_CHAN_SWITCH_IND",
|
||||
[MSG_I(TDLS_CHAN_SWITCH_BASE_IND)] = "TDLS_CHAN_SWITCH_BASE_IND",
|
||||
[MSG_I(TDLS_CANCEL_CHAN_SWITCH_REQ)] = "TDLS_CANCEL_CHAN_SWITCH_REQ",
|
||||
[MSG_I(TDLS_CANCEL_CHAN_SWITCH_CFM)] = "TDLS_CANCEL_CHAN_SWITCH_CFM",
|
||||
[MSG_I(TDLS_PEER_PS_IND)] = "TDLS_PEER_PS_IND",
|
||||
[MSG_I(TDLS_PEER_TRAFFIC_IND_REQ)] = "TDLS_PEER_TRAFFIC_IND_REQ",
|
||||
[MSG_I(TDLS_PEER_TRAFFIC_IND_CFM)] = "TDLS_PEER_TRAFFIC_IND_CFM",
|
||||
};
|
||||
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
|
||||
static const char *const rwnx_scanuid2str[MSG_I(SCANU_MAX)] = {
|
||||
[MSG_I(SCANU_START_REQ)] = "SCANU_START_REQ",
|
||||
[MSG_I(SCANU_START_CFM)] = "SCANU_START_CFM",
|
||||
[MSG_I(SCANU_JOIN_REQ)] = "SCANU_JOIN_REQ",
|
||||
[MSG_I(SCANU_JOIN_CFM)] = "SCANU_JOIN_CFM",
|
||||
[MSG_I(SCANU_RESULT_IND)] = "SCANU_RESULT_IND",
|
||||
[MSG_I(SCANU_FAST_REQ)] = "SCANU_FAST_REQ",
|
||||
[MSG_I(SCANU_FAST_CFM)] = "SCANU_FAST_CFM",
|
||||
[MSG_I(SCANU_VENDOR_IE_REQ)] = "SCANU_VENDOR_IE_REQ",
|
||||
[MSG_I(SCANU_VENDOR_IE_CFM)] = "SCANU_VENDOR_IE_CFM",
|
||||
[MSG_I(SCANU_START_CFM_ADDTIONAL)] = "SCANU_START_CFM_ADDTIONAL",
|
||||
[MSG_I(SCANU_CANCEL_REQ)] = "SCANU_CANCEL_REQ",
|
||||
[MSG_I(SCANU_CANCEL_CFM)] = "SCANU_CANCEL_CFM",
|
||||
};
|
||||
|
||||
static const char *const rwnx_meid2str[MSG_I(ME_MAX)] = {
|
||||
[MSG_I(ME_CONFIG_REQ)] = "ME_CONFIG_REQ",
|
||||
[MSG_I(ME_CONFIG_CFM)] = "ME_CONFIG_CFM",
|
||||
[MSG_I(ME_CHAN_CONFIG_REQ)] = "ME_CHAN_CONFIG_REQ",
|
||||
[MSG_I(ME_CHAN_CONFIG_CFM)] = "ME_CHAN_CONFIG_CFM",
|
||||
[MSG_I(ME_SET_CONTROL_PORT_REQ)] = "ME_SET_CONTROL_PORT_REQ",
|
||||
[MSG_I(ME_SET_CONTROL_PORT_CFM)] = "ME_SET_CONTROL_PORT_CFM",
|
||||
[MSG_I(ME_TKIP_MIC_FAILURE_IND)] = "ME_TKIP_MIC_FAILURE_IND",
|
||||
[MSG_I(ME_STA_ADD_REQ)] = "ME_STA_ADD_REQ",
|
||||
[MSG_I(ME_STA_ADD_CFM)] = "ME_STA_ADD_CFM",
|
||||
[MSG_I(ME_STA_DEL_REQ)] = "ME_STA_DEL_REQ",
|
||||
[MSG_I(ME_STA_DEL_CFM)] = "ME_STA_DEL_CFM",
|
||||
[MSG_I(ME_TX_CREDITS_UPDATE_IND)]= "ME_TX_CREDITS_UPDATE_IND",
|
||||
[MSG_I(ME_RC_STATS_REQ)] = "ME_RC_STATS_REQ",
|
||||
[MSG_I(ME_RC_STATS_CFM)] = "ME_RC_STATS_CFM",
|
||||
[MSG_I(ME_RC_SET_RATE_REQ)] = "ME_RC_SET_RATE_REQ",
|
||||
[MSG_I(ME_TRAFFIC_IND_REQ)] = "ME_TRAFFIC_IND_REQ",
|
||||
[MSG_I(ME_TRAFFIC_IND_CFM)] = "ME_TRAFFIC_IND_CFM",
|
||||
[MSG_I(ME_SET_PS_MODE_REQ)] = "ME_SET_PS_MODE_REQ",
|
||||
[MSG_I(ME_SET_PS_MODE_CFM)] = "ME_SET_PS_MODE_CFM",
|
||||
};
|
||||
|
||||
static const char *const rwnx_smid2str[MSG_I(SM_MAX)] = {
|
||||
[MSG_I(SM_CONNECT_REQ)] = "SM_CONNECT_REQ",
|
||||
[MSG_I(SM_CONNECT_CFM)] = "SM_CONNECT_CFM",
|
||||
[MSG_I(SM_CONNECT_IND)] = "SM_CONNECT_IND",
|
||||
[MSG_I(SM_DISCONNECT_REQ)] = "SM_DISCONNECT_REQ",
|
||||
[MSG_I(SM_DISCONNECT_CFM)] = "SM_DISCONNECT_CFM",
|
||||
[MSG_I(SM_DISCONNECT_IND)] = "SM_DISCONNECT_IND",
|
||||
[MSG_I(SM_EXTERNAL_AUTH_REQUIRED_IND)] = "SM_EXTERNAL_AUTH_REQUIRED_IND",
|
||||
[MSG_I(SM_EXTERNAL_AUTH_REQUIRED_RSP)] = "SM_EXTERNAL_AUTH_REQUIRED_RSP",
|
||||
[MSG_I(SM_EXTERNAL_AUTH_REQUIRED_RSP_CFM)] = "SM_EXTERNAL_AUTH_REQUIRED_RSP_CFM",
|
||||
};
|
||||
|
||||
static const char *const rwnx_apmid2str[MSG_I(APM_MAX)] = {
|
||||
[MSG_I(APM_START_REQ)] = "APM_START_REQ",
|
||||
[MSG_I(APM_START_CFM)] = "APM_START_CFM",
|
||||
[MSG_I(APM_STOP_REQ)] = "APM_STOP_REQ",
|
||||
[MSG_I(APM_STOP_CFM)] = "APM_STOP_CFM",
|
||||
[MSG_I(APM_START_CAC_REQ)] = "APM_START_CAC_REQ",
|
||||
[MSG_I(APM_START_CAC_CFM)] = "APM_START_CAC_CFM",
|
||||
[MSG_I(APM_STOP_CAC_REQ)] = "APM_STOP_CAC_REQ",
|
||||
[MSG_I(APM_STOP_CAC_CFM)] = "APM_STOP_CAC_CFM",
|
||||
[MSG_I(APM_SET_BEACON_IE_REQ)] = "APM_SET_BEACON_IE_REQ",
|
||||
[MSG_I(APM_SET_BEACON_IE_CFM)] = "APM_SET_BEACON_IE_CFM",
|
||||
};
|
||||
|
||||
static const char *const rwnx_meshid2str[MSG_I(MESH_MAX)] = {
|
||||
[MSG_I(MESH_START_REQ)] = "MESH_START_REQ",
|
||||
[MSG_I(MESH_START_CFM)] = "MESH_START_CFM",
|
||||
[MSG_I(MESH_STOP_REQ)] = "MESH_STOP_REQ",
|
||||
[MSG_I(MESH_STOP_CFM)] = "MESH_STOP_CFM",
|
||||
[MSG_I(MESH_UPDATE_REQ)] = "MESH_UPDATE_REQ",
|
||||
[MSG_I(MESH_UPDATE_CFM)] = "MESH_UPDATE_CFM",
|
||||
[MSG_I(MESH_PATH_CREATE_REQ)] = "MESH_PATH_CREATE_REQ",
|
||||
[MSG_I(MESH_PATH_CREATE_CFM)] = "MESH_PATH_CREATE_CFM",
|
||||
[MSG_I(MESH_PATH_UPDATE_REQ)] = "MESH_PATH_UPDATE_REQ",
|
||||
[MSG_I(MESH_PATH_UPDATE_CFM)] = "MESH_PATH_UPDATE_CFM",
|
||||
[MSG_I(MESH_PROXY_ADD_REQ)] = "MESH_PROXY_ADD_REQ",
|
||||
[MSG_I(MESH_PEER_UPDATE_IND)] = "MESH_PEER_UPDATE_IND",
|
||||
[MSG_I(MESH_PATH_UPDATE_IND)] = "MESH_PATH_UPDATE_IND",
|
||||
[MSG_I(MESH_PROXY_UPDATE_IND)] = "MESH_PROXY_UPDATE_IND",
|
||||
};
|
||||
|
||||
#endif /* CONFIG_RWNX_FULLMAC */
|
||||
|
||||
const char *const *rwnx_id2str[TASK_LAST_EMB + 1] = {
|
||||
[TASK_MM] = rwnx_mmid2str,
|
||||
[TASK_DBG] = rwnx_dbgid2str,
|
||||
[TASK_SCAN] = rwnx_scanid2str,
|
||||
[TASK_TDLS] = rwnx_tdlsid2str,
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
[TASK_SCANU] = rwnx_scanuid2str,
|
||||
[TASK_ME] = rwnx_meid2str,
|
||||
[TASK_SM] = rwnx_smid2str,
|
||||
[TASK_APM] = rwnx_apmid2str,
|
||||
[TASK_MESH] = rwnx_meshid2str,
|
||||
#endif
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
****************************************************************************************
|
||||
*
|
||||
* @file rwnx_strs.h
|
||||
*
|
||||
* @brief Miscellaneous debug strings
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2014-2019
|
||||
*
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _RWNX_STRS_H_
|
||||
#define _RWNX_STRS_H_
|
||||
|
||||
#ifdef CONFIG_RWNX_FHOST
|
||||
|
||||
#define RWNX_ID2STR(tag) "Cmd"
|
||||
|
||||
#else
|
||||
#include "lmac_msg.h"
|
||||
|
||||
#define RWNX_ID2STR(tag) (((MSG_T(tag) < ARRAY_SIZE(rwnx_id2str)) && \
|
||||
(rwnx_id2str[MSG_T(tag)]) && \
|
||||
((rwnx_id2str[MSG_T(tag)])[MSG_I(tag)])) ? \
|
||||
(rwnx_id2str[MSG_T(tag)])[MSG_I(tag)] : "unknown")
|
||||
|
||||
extern const char *const *rwnx_id2str[TASK_LAST_EMB + 1];
|
||||
#endif /* CONFIG_RWNX_FHOST */
|
||||
|
||||
#endif /* _RWNX_STRS_H_ */
|
||||
@@ -0,0 +1,796 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_tx.c
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* INCLUDE FILES
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "rwnx_tdls.h"
|
||||
#include "rwnx_compat.h"
|
||||
|
||||
/**
|
||||
* FUNCTION DEFINITIONS
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
static u16
|
||||
rwnx_get_tdls_sta_capab(struct rwnx_vif *rwnx_vif, u16 status_code)
|
||||
{
|
||||
u16 capab = 0;
|
||||
|
||||
/* The capability will be 0 when sending a failure code */
|
||||
if (status_code != 0)
|
||||
return capab;
|
||||
|
||||
if (rwnx_vif->sta.ap->band != NL80211_BAND_2GHZ)
|
||||
return capab;
|
||||
|
||||
capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
|
||||
capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
|
||||
|
||||
return capab;
|
||||
}
|
||||
|
||||
static int
|
||||
rwnx_tdls_prepare_encap_data(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif,
|
||||
const u8 *peer, u8 action_code, u8 dialog_token,
|
||||
u16 status_code, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tdls_data *tf;
|
||||
tf = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_data) - sizeof(tf->u));
|
||||
|
||||
// set eth header
|
||||
memcpy(tf->da, peer, ETH_ALEN);
|
||||
memcpy(tf->sa, rwnx_hw->wiphy->perm_addr, ETH_ALEN);
|
||||
tf->ether_type = cpu_to_be16(ETH_P_TDLS);
|
||||
|
||||
// set common TDLS info
|
||||
tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
|
||||
tf->category = WLAN_CATEGORY_TDLS;
|
||||
tf->action_code = action_code;
|
||||
|
||||
// set action specific TDLS info
|
||||
switch (action_code) {
|
||||
case WLAN_TDLS_SETUP_REQUEST:
|
||||
skb_put(skb, sizeof(tf->u.setup_req));
|
||||
tf->u.setup_req.dialog_token = dialog_token;
|
||||
tf->u.setup_req.capability =
|
||||
cpu_to_le16(rwnx_get_tdls_sta_capab(rwnx_vif, status_code));
|
||||
break;
|
||||
|
||||
case WLAN_TDLS_SETUP_RESPONSE:
|
||||
skb_put(skb, sizeof(tf->u.setup_resp));
|
||||
tf->u.setup_resp.status_code = cpu_to_le16(status_code);
|
||||
tf->u.setup_resp.dialog_token = dialog_token;
|
||||
tf->u.setup_resp.capability =
|
||||
cpu_to_le16(rwnx_get_tdls_sta_capab(rwnx_vif, status_code));
|
||||
break;
|
||||
|
||||
case WLAN_TDLS_SETUP_CONFIRM:
|
||||
skb_put(skb, sizeof(tf->u.setup_cfm));
|
||||
tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
|
||||
tf->u.setup_cfm.dialog_token = dialog_token;
|
||||
break;
|
||||
|
||||
case WLAN_TDLS_TEARDOWN:
|
||||
skb_put(skb, sizeof(tf->u.teardown));
|
||||
tf->u.teardown.reason_code = cpu_to_le16(status_code);
|
||||
break;
|
||||
|
||||
case WLAN_TDLS_DISCOVERY_REQUEST:
|
||||
skb_put(skb, sizeof(tf->u.discover_req));
|
||||
tf->u.discover_req.dialog_token = dialog_token;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
rwnx_prep_tdls_direct(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif,
|
||||
const u8 *peer, u8 action_code, u8 dialog_token,
|
||||
u16 status_code, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
|
||||
mgmt = (void *)skb_put(skb, 24);
|
||||
memset(mgmt, 0, 24);
|
||||
memcpy(mgmt->da, peer, ETH_ALEN);
|
||||
memcpy(mgmt->sa, rwnx_hw->wiphy->perm_addr, ETH_ALEN);
|
||||
memcpy(mgmt->bssid, rwnx_vif->sta.ap->mac_addr, ETH_ALEN);
|
||||
|
||||
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
|
||||
IEEE80211_STYPE_ACTION);
|
||||
|
||||
switch (action_code) {
|
||||
case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
|
||||
skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp));
|
||||
mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
|
||||
mgmt->u.action.u.tdls_discover_resp.action_code = WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
|
||||
mgmt->u.action.u.tdls_discover_resp.dialog_token = dialog_token;
|
||||
mgmt->u.action.u.tdls_discover_resp.capability =
|
||||
cpu_to_le16(rwnx_get_tdls_sta_capab(rwnx_vif, status_code));
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
rwnx_add_srates_ie(struct rwnx_hw *rwnx_hw, struct sk_buff *skb)
|
||||
{
|
||||
u8 i, rates, *pos;
|
||||
int rate;
|
||||
struct ieee80211_supported_band *rwnx_band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ];
|
||||
|
||||
rates = 8;
|
||||
|
||||
if (skb_tailroom(skb) < rates + 2)
|
||||
return -ENOMEM;
|
||||
|
||||
pos = skb_put(skb, rates + 2);
|
||||
*pos++ = WLAN_EID_SUPP_RATES;
|
||||
*pos++ = rates;
|
||||
for (i = 0; i < rates; i++) {
|
||||
rate = rwnx_band_2GHz->bitrates[i].bitrate;
|
||||
rate = DIV_ROUND_UP(rate, 5);
|
||||
*pos++ = (u8)rate;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
rwnx_add_ext_srates_ie(struct rwnx_hw *rwnx_hw, struct sk_buff *skb)
|
||||
{
|
||||
u8 i, exrates, *pos;
|
||||
int rate;
|
||||
struct ieee80211_supported_band *rwnx_band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ];
|
||||
|
||||
exrates = rwnx_band_2GHz->n_bitrates - 8;
|
||||
|
||||
if (skb_tailroom(skb) < exrates + 2)
|
||||
return -ENOMEM;
|
||||
|
||||
pos = skb_put(skb, exrates + 2);
|
||||
*pos++ = WLAN_EID_EXT_SUPP_RATES;
|
||||
*pos++ = exrates;
|
||||
for (i = 8; i < (8+exrates); i++) {
|
||||
rate = rwnx_band_2GHz->bitrates[i].bitrate;
|
||||
rate = DIV_ROUND_UP(rate, 5);
|
||||
*pos++ = (u8)rate;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rwnx_tdls_add_supp_channels(struct rwnx_hw *rwnx_hw, struct sk_buff *skb)
|
||||
{
|
||||
/*
|
||||
* Add possible channels for TDLS. These are channels that are allowed
|
||||
* to be active.
|
||||
*/
|
||||
u8 subband_cnt = 0;
|
||||
u8 *pos_subband;
|
||||
u8 *pos = skb_put(skb, 2);
|
||||
struct ieee80211_supported_band *rwnx_band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ];
|
||||
//#ifdef USE_5G
|
||||
struct ieee80211_supported_band *rwnx_band_5GHz = rwnx_hw->wiphy->bands[NL80211_BAND_5GHZ];
|
||||
//#endif
|
||||
|
||||
*pos++ = WLAN_EID_SUPPORTED_CHANNELS;
|
||||
|
||||
/*
|
||||
* 5GHz and 2GHz channels numbers can overlap. Ignore this for now, as
|
||||
* this doesn't happen in real world scenarios.
|
||||
*/
|
||||
|
||||
/* 2GHz, with 5MHz spacing */
|
||||
pos_subband = skb_put(skb, 2);
|
||||
if (rwnx_band_2GHz->n_channels > 0)
|
||||
{
|
||||
*pos_subband++ = ieee80211_frequency_to_channel(rwnx_band_2GHz->channels[0].center_freq);
|
||||
*pos_subband++ = rwnx_band_2GHz->n_channels;
|
||||
subband_cnt++;
|
||||
}
|
||||
|
||||
/* 5GHz, with 20MHz spacing */
|
||||
pos_subband = skb_put(skb, 2);
|
||||
//#ifdef USE_5G
|
||||
if(rwnx_hw->band_5g_support){
|
||||
if (rwnx_band_5GHz->n_channels > 0)
|
||||
{
|
||||
*pos_subband++ = ieee80211_frequency_to_channel(rwnx_band_5GHz->channels[0].center_freq);
|
||||
*pos_subband++ = rwnx_band_5GHz->n_channels;
|
||||
subband_cnt++;
|
||||
}
|
||||
}
|
||||
//#endif
|
||||
/* length */
|
||||
*pos = 2 * subband_cnt;
|
||||
}
|
||||
|
||||
static void
|
||||
rwnx_tdls_add_ext_capab(struct rwnx_hw *rwnx_hw, struct sk_buff *skb)
|
||||
{
|
||||
u8 *pos = (void *)skb_put(skb, 7);
|
||||
bool chan_switch = rwnx_hw->wiphy->features &
|
||||
NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
|
||||
|
||||
*pos++ = WLAN_EID_EXT_CAPABILITY;
|
||||
*pos++ = 5; /* len */
|
||||
*pos++ = 0x0;
|
||||
*pos++ = 0x0;
|
||||
*pos++ = 0x0;
|
||||
*pos++ = WLAN_EXT_CAPA4_TDLS_BUFFER_STA |
|
||||
(chan_switch ? WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH : 0);
|
||||
*pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED;
|
||||
}
|
||||
|
||||
static void
|
||||
rwnx_add_wmm_info_ie(struct sk_buff *skb, u8 qosinfo)
|
||||
{
|
||||
u8 *pos = (void *)skb_put(skb, 9);
|
||||
|
||||
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
*pos++ = 7; /* len */
|
||||
*pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
|
||||
*pos++ = 0x50;
|
||||
*pos++ = 0xf2;
|
||||
*pos++ = 2; /* WME */
|
||||
*pos++ = 0; /* WME info */
|
||||
*pos++ = 1; /* WME ver */
|
||||
*pos++ = qosinfo; /* U-APSD no in use */
|
||||
}
|
||||
|
||||
/* translate numbering in the WMM parameter IE to the mac80211 notation */
|
||||
static u8 rwnx_ac_from_wmm(int ac)
|
||||
{
|
||||
switch (ac) {
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
case 0:
|
||||
return AC_BE;
|
||||
case 1:
|
||||
return AC_BK;
|
||||
case 2:
|
||||
return AC_VI;
|
||||
case 3:
|
||||
return AC_VO;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rwnx_add_wmm_param_ie(struct sk_buff *skb, u8 acm_bits, u32 *ac_params)
|
||||
{
|
||||
struct ieee80211_wmm_param_ie *wmm;
|
||||
int i, j;
|
||||
u8 cw_min, cw_max;
|
||||
bool acm;
|
||||
|
||||
wmm = (void *)skb_put(skb, sizeof(struct ieee80211_wmm_param_ie));
|
||||
memset(wmm, 0, sizeof(*wmm));
|
||||
|
||||
wmm->element_id = WLAN_EID_VENDOR_SPECIFIC;
|
||||
wmm->len = sizeof(*wmm) - 2;
|
||||
|
||||
wmm->oui[0] = 0x00; /* Microsoft OUI 00:50:F2 */
|
||||
wmm->oui[1] = 0x50;
|
||||
wmm->oui[2] = 0xf2;
|
||||
wmm->oui_type = 2; /* WME */
|
||||
wmm->oui_subtype = 1; /* WME param */
|
||||
wmm->version = 1; /* WME ver */
|
||||
wmm->qos_info = 0; /* U-APSD not in use */
|
||||
|
||||
/*
|
||||
* Use the EDCA parameters defined for the BSS, or default if the AP
|
||||
* doesn't support it, as mandated by 802.11-2012 section 10.22.4
|
||||
*/
|
||||
for (i = 0; i < AC_MAX; i++) {
|
||||
j = rwnx_ac_from_wmm(i);
|
||||
cw_min = (ac_params[j] & 0xF0 ) >> 4;
|
||||
cw_max = (ac_params[j] & 0xF00 ) >> 8;
|
||||
acm = (acm_bits & (1 << j)) != 0;
|
||||
|
||||
wmm->ac[i].aci_aifsn = (i << 5) | (acm << 4) | (ac_params[j] & 0xF);
|
||||
wmm->ac[i].cw = (cw_max << 4) | cw_min;
|
||||
wmm->ac[i].txop_limit = (ac_params[j] & 0x0FFFF000 ) >> 12;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rwnx_tdls_add_oper_classes(struct rwnx_vif *rwnx_vif, struct sk_buff *skb)
|
||||
{
|
||||
u8 *pos;
|
||||
u8 op_class;
|
||||
struct cfg80211_chan_def chan_def;
|
||||
struct ieee80211_channel chan;
|
||||
|
||||
chan.band = rwnx_vif->sta.ap->band;
|
||||
chan.center_freq = rwnx_vif->sta.ap->center_freq;
|
||||
chan_def.chan = &chan;
|
||||
chan_def.width = rwnx_vif->sta.ap->width;
|
||||
chan_def.center_freq1 = rwnx_vif->sta.ap->center_freq1;
|
||||
chan_def.center_freq2 = rwnx_vif->sta.ap->center_freq2;
|
||||
|
||||
if (!ieee80211_chandef_to_operating_class(&chan_def, &op_class))
|
||||
return;
|
||||
|
||||
pos = skb_put(skb, 4);
|
||||
*pos++ = WLAN_EID_SUPPORTED_REGULATORY_CLASSES;
|
||||
*pos++ = 2; /* len */
|
||||
|
||||
// current op class
|
||||
*pos++ = op_class;
|
||||
*pos++ = op_class; /* give current operating class as alternate too */
|
||||
|
||||
// need to add 5GHz classes?
|
||||
}
|
||||
|
||||
static void
|
||||
rwnx_ie_build_ht_cap(struct sk_buff *skb, struct ieee80211_sta_ht_cap *ht_cap,
|
||||
u16 cap)
|
||||
{
|
||||
u8 *pos;
|
||||
__le16 tmp;
|
||||
|
||||
pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
|
||||
*pos++ = WLAN_EID_HT_CAPABILITY;
|
||||
*pos++ = sizeof(struct ieee80211_ht_cap);
|
||||
memset(pos, 0, sizeof(struct ieee80211_ht_cap));
|
||||
|
||||
/* capability flags */
|
||||
tmp = cpu_to_le16(cap);
|
||||
memcpy(pos, &tmp, sizeof(u16));
|
||||
pos += sizeof(u16);
|
||||
|
||||
/* AMPDU parameters */
|
||||
*pos++ = ht_cap->ampdu_factor |
|
||||
(ht_cap->ampdu_density <<
|
||||
IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
|
||||
|
||||
/* MCS set */
|
||||
memcpy(pos, &ht_cap->mcs, sizeof(ht_cap->mcs));
|
||||
pos += sizeof(ht_cap->mcs);
|
||||
|
||||
/* extended capabilities */
|
||||
pos += sizeof(__le16);
|
||||
|
||||
/* BF capabilities */
|
||||
pos += sizeof(__le32);
|
||||
|
||||
/* antenna selection */
|
||||
pos += sizeof(u8);
|
||||
}
|
||||
|
||||
static void
|
||||
rwnx_ie_build_vht_cap(struct sk_buff *skb, struct ieee80211_sta_vht_cap *vht_cap,
|
||||
u32 cap)
|
||||
{
|
||||
u8 *pos;
|
||||
__le32 tmp;
|
||||
|
||||
pos = skb_put(skb, 14);
|
||||
|
||||
*pos++ = WLAN_EID_VHT_CAPABILITY;
|
||||
*pos++ = sizeof(struct ieee80211_vht_cap);
|
||||
memset(pos, 0, sizeof(struct ieee80211_vht_cap));
|
||||
|
||||
/* capability flags */
|
||||
tmp = cpu_to_le32(cap);
|
||||
memcpy(pos, &tmp, sizeof(u32));
|
||||
pos += sizeof(u32);
|
||||
|
||||
/* VHT MCS set */
|
||||
memcpy(pos, &vht_cap->vht_mcs, sizeof(vht_cap->vht_mcs));
|
||||
pos += sizeof(vht_cap->vht_mcs);
|
||||
}
|
||||
|
||||
static void
|
||||
rwnx_tdls_add_bss_coex_ie(struct sk_buff *skb)
|
||||
{
|
||||
u8 *pos = (void *)skb_put(skb, 3);
|
||||
|
||||
*pos++ = WLAN_EID_BSS_COEX_2040;
|
||||
*pos++ = 1; /* len */
|
||||
|
||||
*pos++ = WLAN_BSS_COEX_INFORMATION_REQUEST;
|
||||
}
|
||||
|
||||
static void
|
||||
rwnx_tdls_add_link_ie(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif,
|
||||
struct sk_buff *skb, const u8 *peer,
|
||||
bool initiator)
|
||||
{
|
||||
struct ieee80211_tdls_lnkie *lnkid;
|
||||
const u8 *init_addr, *rsp_addr;
|
||||
|
||||
if (initiator) {
|
||||
init_addr = rwnx_hw->wiphy->perm_addr;
|
||||
rsp_addr = peer;
|
||||
} else {
|
||||
init_addr = peer;
|
||||
rsp_addr = rwnx_hw->wiphy->perm_addr;
|
||||
}
|
||||
|
||||
lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
|
||||
|
||||
lnkid->ie_type = WLAN_EID_LINK_ID;
|
||||
lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2;
|
||||
|
||||
memcpy(lnkid->bssid, rwnx_vif->sta.ap->mac_addr, ETH_ALEN);
|
||||
memcpy(lnkid->init_sta, init_addr, ETH_ALEN);
|
||||
memcpy(lnkid->resp_sta, rsp_addr, ETH_ALEN);
|
||||
}
|
||||
|
||||
static void
|
||||
rwnx_tdls_add_aid_ie(struct rwnx_vif *rwnx_vif, struct sk_buff *skb)
|
||||
{
|
||||
u8 *pos = (void *)skb_put(skb, 4);
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
|
||||
*pos++ = WLAN_EID_AID;
|
||||
#else
|
||||
*pos++ = 197;
|
||||
#endif
|
||||
*pos++ = 2; /* len */
|
||||
*pos++ = rwnx_vif->sta.ap->aid;
|
||||
}
|
||||
|
||||
static u8 *
|
||||
rwnx_ie_build_ht_oper(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif,
|
||||
u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
|
||||
u16 prot_mode)
|
||||
{
|
||||
struct ieee80211_ht_operation *ht_oper;
|
||||
/* Build HT Information */
|
||||
*pos++ = WLAN_EID_HT_OPERATION;
|
||||
*pos++ = sizeof(struct ieee80211_ht_operation);
|
||||
ht_oper = (struct ieee80211_ht_operation *)pos;
|
||||
ht_oper->primary_chan = ieee80211_frequency_to_channel(
|
||||
rwnx_vif->sta.ap->center_freq);
|
||||
switch (rwnx_vif->sta.ap->width) {
|
||||
case NL80211_CHAN_WIDTH_160:
|
||||
case NL80211_CHAN_WIDTH_80P80:
|
||||
case NL80211_CHAN_WIDTH_80:
|
||||
case NL80211_CHAN_WIDTH_40:
|
||||
if (rwnx_vif->sta.ap->center_freq1 > rwnx_vif->sta.ap->center_freq)
|
||||
ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
|
||||
else
|
||||
ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
|
||||
break;
|
||||
default:
|
||||
ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE;
|
||||
break;
|
||||
}
|
||||
if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 &&
|
||||
rwnx_vif->sta.ap->width != NL80211_CHAN_WIDTH_20_NOHT &&
|
||||
rwnx_vif->sta.ap->width != NL80211_CHAN_WIDTH_20)
|
||||
ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
|
||||
|
||||
ht_oper->operation_mode = cpu_to_le16(prot_mode);
|
||||
ht_oper->stbc_param = 0x0000;
|
||||
|
||||
/* It seems that Basic MCS set and Supported MCS set
|
||||
are identical for the first 10 bytes */
|
||||
memset(&ht_oper->basic_set, 0, 16);
|
||||
memcpy(&ht_oper->basic_set, &ht_cap->mcs, 10);
|
||||
|
||||
return pos + sizeof(struct ieee80211_ht_operation);
|
||||
}
|
||||
|
||||
static u8 *
|
||||
rwnx_ie_build_vht_oper(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif,
|
||||
u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
|
||||
u16 prot_mode)
|
||||
{
|
||||
struct ieee80211_vht_operation *vht_oper;
|
||||
/* Build HT Information */
|
||||
*pos++ = WLAN_EID_VHT_OPERATION;
|
||||
*pos++ = sizeof(struct ieee80211_vht_operation);
|
||||
vht_oper = (struct ieee80211_vht_operation *)pos;
|
||||
|
||||
switch (rwnx_vif->sta.ap->width) {
|
||||
case NL80211_CHAN_WIDTH_80:
|
||||
vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ; // Channel Width
|
||||
CCFS0(vht_oper) =
|
||||
ieee80211_frequency_to_channel(rwnx_vif->sta.ap->center_freq); // Channel Center Frequency Segment 0
|
||||
CCFS1(vht_oper) = 0; // Channel Center Frequency Segment 1 (N.A.)
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_160:
|
||||
vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_160MHZ; // Channel Width
|
||||
CCFS0(vht_oper) =
|
||||
ieee80211_frequency_to_channel(rwnx_vif->sta.ap->center_freq); // Channel Center Frequency Segment 0
|
||||
CCFS1(vht_oper) = 0; // Channel Center Frequency Segment 1 (N.A.)
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_80P80:
|
||||
vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80P80MHZ; // Channel Width
|
||||
CCFS0(vht_oper) =
|
||||
ieee80211_frequency_to_channel(rwnx_vif->sta.ap->center_freq1); // Channel Center Frequency Segment 0
|
||||
CCFS1(vht_oper) =
|
||||
ieee80211_frequency_to_channel(rwnx_vif->sta.ap->center_freq2); // Channel Center Frequency Segment 1
|
||||
break;
|
||||
default:
|
||||
vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_USE_HT;
|
||||
CCFS0(vht_oper) = 0;
|
||||
CCFS1(vht_oper) = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
vht_oper->basic_mcs_set = cpu_to_le16(rwnx_hw->mod_params->mcs_map);
|
||||
|
||||
return pos + sizeof(struct ieee80211_vht_operation);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
rwnx_tdls_add_setup_start_ies(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif,
|
||||
struct sk_buff *skb, const u8 *peer,
|
||||
u8 action_code, bool initiator,
|
||||
const u8 *extra_ies, size_t extra_ies_len)
|
||||
{
|
||||
enum nl80211_band band = rwnx_vif->sta.ap->band;
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_sta_ht_cap ht_cap;
|
||||
struct ieee80211_sta_vht_cap vht_cap;
|
||||
size_t offset = 0, noffset;
|
||||
u8 *pos;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
rwnx_add_srates_ie(rwnx_hw, skb);
|
||||
rwnx_add_ext_srates_ie(rwnx_hw, skb);
|
||||
rwnx_tdls_add_supp_channels(rwnx_hw, skb);
|
||||
rwnx_tdls_add_ext_capab(rwnx_hw, skb);
|
||||
|
||||
/* add the QoS element if we support it */
|
||||
if (/*local->hw.queues >= IEEE80211_NUM_ACS &&*/
|
||||
action_code != WLAN_PUB_ACTION_TDLS_DISCOVER_RES)
|
||||
rwnx_add_wmm_info_ie(skb, 0); /* no U-APSD */
|
||||
|
||||
rwnx_tdls_add_oper_classes(rwnx_vif, skb);
|
||||
|
||||
/*
|
||||
* with TDLS we can switch channels, and HT-caps are not necessarily
|
||||
* the same on all bands. The specification limits the setup to a
|
||||
* single HT-cap, so use the current band for now.
|
||||
*/
|
||||
sband = rwnx_hw->wiphy->bands[band];
|
||||
memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap));
|
||||
if (((action_code == WLAN_TDLS_SETUP_REQUEST) ||
|
||||
(action_code == WLAN_TDLS_SETUP_RESPONSE) ||
|
||||
(action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES)) &&
|
||||
ht_cap.ht_supported /* (!sta || sta->sta.ht_cap.ht_supported)*/) {
|
||||
rwnx_ie_build_ht_cap(skb, &ht_cap, ht_cap.cap);
|
||||
}
|
||||
|
||||
if (ht_cap.ht_supported &&
|
||||
(ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
|
||||
rwnx_tdls_add_bss_coex_ie(skb);
|
||||
|
||||
rwnx_tdls_add_link_ie(rwnx_hw, rwnx_vif, skb, peer, initiator);
|
||||
|
||||
memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap));
|
||||
if (vht_cap.vht_supported) {
|
||||
rwnx_tdls_add_aid_ie(rwnx_vif, skb);
|
||||
rwnx_ie_build_vht_cap(skb, &vht_cap, vht_cap.cap);
|
||||
// Operating mode Notification (optional)
|
||||
}
|
||||
|
||||
/* add any remaining IEs */
|
||||
if (extra_ies_len) {
|
||||
noffset = extra_ies_len;
|
||||
pos = skb_put(skb, noffset - offset);
|
||||
memcpy(pos, extra_ies + offset, noffset - offset);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
rwnx_tdls_add_setup_cfm_ies(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif,
|
||||
struct sk_buff *skb, const u8 *peer, bool initiator,
|
||||
const u8 *extra_ies, size_t extra_ies_len)
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
enum nl80211_band band = rwnx_vif->sta.ap->band;
|
||||
struct ieee80211_sta_ht_cap ht_cap;
|
||||
struct ieee80211_sta_vht_cap vht_cap;
|
||||
|
||||
size_t offset = 0, noffset;
|
||||
struct rwnx_sta *sta, *ap_sta;
|
||||
u8 *pos;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
sta = rwnx_get_sta(rwnx_hw, peer);
|
||||
ap_sta = rwnx_vif->sta.ap;
|
||||
if (WARN_ON_ONCE(!sta || !ap_sta)) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
/* add the QoS param IE if both the peer and we support it */
|
||||
if (sta->qos)
|
||||
rwnx_add_wmm_param_ie(skb, ap_sta->acm, ap_sta->ac_param);
|
||||
|
||||
/* if HT support is only added in TDLS, we need an HT-operation IE */
|
||||
sband = rwnx_hw->wiphy->bands[band];
|
||||
memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap));
|
||||
if (ht_cap.ht_supported && !ap_sta->ht && sta->ht) {
|
||||
pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation));
|
||||
/* send an empty HT operation IE */
|
||||
rwnx_ie_build_ht_oper(rwnx_hw, rwnx_vif, pos, &ht_cap, 0);
|
||||
}
|
||||
|
||||
rwnx_tdls_add_link_ie(rwnx_hw, rwnx_vif, skb, peer, initiator);
|
||||
|
||||
memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap));
|
||||
if (vht_cap.vht_supported && !ap_sta->vht && sta->vht) {
|
||||
pos = skb_put(skb, 2 + sizeof(struct ieee80211_vht_operation));
|
||||
rwnx_ie_build_vht_oper(rwnx_hw, rwnx_vif, pos, &ht_cap, 0);
|
||||
// Operating mode Notification (optional)
|
||||
}
|
||||
|
||||
/* add any remaining IEs */
|
||||
if (extra_ies_len) {
|
||||
noffset = extra_ies_len;
|
||||
pos = skb_put(skb, noffset - offset);
|
||||
memcpy(pos, extra_ies + offset, noffset - offset);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void
|
||||
rwnx_tdls_add_ies(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif,
|
||||
struct sk_buff *skb, const u8 *peer,
|
||||
u8 action_code, u16 status_code,
|
||||
bool initiator, const u8 *extra_ies,
|
||||
size_t extra_ies_len, u8 oper_class,
|
||||
struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
switch (action_code) {
|
||||
case WLAN_TDLS_SETUP_REQUEST:
|
||||
case WLAN_TDLS_SETUP_RESPONSE:
|
||||
case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
|
||||
if (status_code == 0)
|
||||
rwnx_tdls_add_setup_start_ies(rwnx_hw, rwnx_vif, skb, peer, action_code,
|
||||
initiator, extra_ies, extra_ies_len);
|
||||
break;
|
||||
case WLAN_TDLS_SETUP_CONFIRM:
|
||||
if (status_code == 0)
|
||||
rwnx_tdls_add_setup_cfm_ies(rwnx_hw, rwnx_vif, skb, peer, initiator,
|
||||
extra_ies, extra_ies_len);
|
||||
break;
|
||||
|
||||
case WLAN_TDLS_TEARDOWN:
|
||||
case WLAN_TDLS_DISCOVERY_REQUEST:
|
||||
if (extra_ies_len)
|
||||
memcpy(skb_put(skb, extra_ies_len), extra_ies,
|
||||
extra_ies_len);
|
||||
if (status_code == 0 || action_code == WLAN_TDLS_TEARDOWN)
|
||||
rwnx_tdls_add_link_ie(rwnx_hw, rwnx_vif, skb, peer, initiator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
rwnx_tdls_send_mgmt_packet_data(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif,
|
||||
const u8 *peer, u8 action_code, u8 dialog_token,
|
||||
u16 status_code, u32 peer_capability, bool initiator,
|
||||
const u8 *extra_ies, size_t extra_ies_len, u8 oper_class,
|
||||
struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int ret = 0;
|
||||
struct ieee80211_supported_band *rwnx_band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ];
|
||||
//#ifdef USE_5G
|
||||
struct ieee80211_supported_band *rwnx_band_5GHz = rwnx_hw->wiphy->bands[NL80211_BAND_5GHZ];
|
||||
//#endif
|
||||
int channels = rwnx_band_2GHz->n_channels;
|
||||
|
||||
if (rwnx_hw->band_5g_support){
|
||||
channels += rwnx_band_5GHz->n_channels;
|
||||
}
|
||||
|
||||
skb = netdev_alloc_skb(rwnx_vif->ndev,
|
||||
sizeof(struct ieee80211_tdls_data) + // ethhdr + TDLS info
|
||||
10 + /* supported rates */
|
||||
6 + /* extended supported rates */
|
||||
(2 + channels) + /* supported channels */
|
||||
//#ifdef USE_5G
|
||||
//(2 + rwnx_band_2GHz->n_channels + rwnx_band_5GHz->n_channels) + /* supported channels */
|
||||
//#else
|
||||
//(2 + rwnx_band_2GHz->n_channels) + /* supported channels */
|
||||
//#endif
|
||||
sizeof(struct ieee_types_extcap) +
|
||||
sizeof(struct ieee80211_wmm_param_ie) +
|
||||
4 + /* oper classes */
|
||||
28 + //sizeof(struct ieee80211_ht_cap) +
|
||||
sizeof(struct ieee_types_bss_co_2040) +
|
||||
sizeof(struct ieee80211_tdls_lnkie) +
|
||||
(2 + sizeof(struct ieee80211_vht_cap)) +
|
||||
4 + /*AID*/
|
||||
(2 + sizeof(struct ieee80211_ht_operation)) +
|
||||
extra_ies_len);
|
||||
|
||||
if (!skb)
|
||||
return 0;
|
||||
|
||||
switch (action_code) {
|
||||
case WLAN_TDLS_SETUP_REQUEST:
|
||||
case WLAN_TDLS_SETUP_RESPONSE:
|
||||
case WLAN_TDLS_SETUP_CONFIRM:
|
||||
case WLAN_TDLS_TEARDOWN:
|
||||
case WLAN_TDLS_DISCOVERY_REQUEST:
|
||||
ret = rwnx_tdls_prepare_encap_data(rwnx_hw, rwnx_vif, peer, action_code,
|
||||
dialog_token, status_code, skb);
|
||||
break;
|
||||
|
||||
case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
|
||||
ret = rwnx_prep_tdls_direct(rwnx_hw, rwnx_vif, peer, action_code,
|
||||
dialog_token, status_code, skb);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -ENOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
rwnx_tdls_add_ies(rwnx_hw, rwnx_vif, skb, peer, action_code, status_code,
|
||||
initiator, extra_ies, extra_ies_len, oper_class, chandef);
|
||||
|
||||
if (action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) {
|
||||
u64 cookie;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
|
||||
struct cfg80211_mgmt_tx_params params;
|
||||
|
||||
params.len = skb->len;
|
||||
params.buf = skb->data;
|
||||
ret = rwnx_start_mgmt_xmit(rwnx_vif, NULL, ¶ms, false, &cookie);
|
||||
#else
|
||||
ret = rwnx_start_mgmt_xmit(rwnx_vif, NULL, NULL, false, 0, skb->data, skb->len, false, false, &cookie);
|
||||
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (action_code) {
|
||||
case WLAN_TDLS_SETUP_REQUEST:
|
||||
case WLAN_TDLS_SETUP_RESPONSE:
|
||||
case WLAN_TDLS_SETUP_CONFIRM:
|
||||
skb->priority = 2;
|
||||
break;
|
||||
default:
|
||||
skb->priority = 5;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = rwnx_select_txq(rwnx_vif, skb);
|
||||
ret = rwnx_start_xmit(skb, rwnx_vif->ndev);
|
||||
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
dev_kfree_skb(skb);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_tdls.h
|
||||
*
|
||||
* @brief TDLS function declarations
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef RWNX_TDLS_H_
|
||||
#define RWNX_TDLS_H_
|
||||
|
||||
#include "rwnx_defs.h"
|
||||
|
||||
struct ieee_types_header {
|
||||
u8 element_id;
|
||||
u8 len;
|
||||
} __packed;
|
||||
|
||||
struct ieee_types_bss_co_2040 {
|
||||
struct ieee_types_header ieee_hdr;
|
||||
u8 bss_2040co;
|
||||
} __packed;
|
||||
|
||||
struct ieee_types_extcap {
|
||||
struct ieee_types_header ieee_hdr;
|
||||
u8 ext_capab[8];
|
||||
} __packed;
|
||||
|
||||
struct ieee_types_vht_cap {
|
||||
struct ieee_types_header ieee_hdr;
|
||||
struct ieee80211_vht_cap vhtcap;
|
||||
} __packed;
|
||||
|
||||
struct ieee_types_vht_oper {
|
||||
struct ieee_types_header ieee_hdr;
|
||||
struct ieee80211_vht_operation vhtoper;
|
||||
} __packed;
|
||||
|
||||
struct ieee_types_aid {
|
||||
struct ieee_types_header ieee_hdr;
|
||||
u16 aid;
|
||||
} __packed;
|
||||
|
||||
int rwnx_tdls_send_mgmt_packet_data(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif,
|
||||
const u8 *peer, u8 action_code, u8 dialog_token,
|
||||
u16 status_code, u32 peer_capability, bool initiator,
|
||||
const u8 *extra_ies, size_t extra_ies_len, u8 oper_class,
|
||||
struct cfg80211_chan_def *chandef);
|
||||
|
||||
#endif /* RWNX_TDLS_H_ */
|
||||
@@ -0,0 +1,226 @@
|
||||
/**
|
||||
****************************************************************************************
|
||||
*
|
||||
* @file rwnx_testmode.c
|
||||
*
|
||||
* @brief Test mode function definitions
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
#include <net/mac80211.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include "rwnx_testmode.h"
|
||||
#include "rwnx_msg_tx.h"
|
||||
#include "rwnx_dini.h"
|
||||
#include "reg_access.h"
|
||||
|
||||
/*
|
||||
* This function handles the user application commands for register access.
|
||||
*
|
||||
* It retrieves command ID carried with RWNX_TM_ATTR_COMMAND and calls to the
|
||||
* handlers respectively.
|
||||
*
|
||||
* If it's an unknown commdn ID, -ENOSYS is returned; or -ENOMSG if the
|
||||
* mandatory fields(RWNX_TM_ATTR_REG_OFFSET,RWNX_TM_ATTR_REG_VALUE32)
|
||||
* are missing; Otherwise 0 is replied indicating the success of the command execution.
|
||||
*
|
||||
* If RWNX_TM_ATTR_COMMAND is RWNX_TM_CMD_APP2DEV_REG_READ, the register read
|
||||
* value is returned with RWNX_TM_ATTR_REG_VALUE32.
|
||||
*
|
||||
* @hw: ieee80211_hw object that represents the device
|
||||
* @tb: general message fields from the user space
|
||||
*/
|
||||
int rwnx_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
{
|
||||
struct rwnx_hw *rwnx_hw = hw->priv;
|
||||
u32 mem_addr, val32;
|
||||
struct sk_buff *skb;
|
||||
int status = 0;
|
||||
|
||||
/* First check if register address is there */
|
||||
if (!tb[RWNX_TM_ATTR_REG_OFFSET]) {
|
||||
printk("Error finding register offset\n");
|
||||
return -ENOMSG;
|
||||
}
|
||||
|
||||
mem_addr = nla_get_u32(tb[RWNX_TM_ATTR_REG_OFFSET]);
|
||||
|
||||
switch (nla_get_u32(tb[RWNX_TM_ATTR_COMMAND])) {
|
||||
case RWNX_TM_CMD_APP2DEV_REG_READ:
|
||||
{
|
||||
struct dbg_mem_read_cfm mem_read_cfm;
|
||||
|
||||
/*** Send the command to the LMAC ***/
|
||||
if ((status = rwnx_send_dbg_mem_read_req(rwnx_hw, mem_addr, &mem_read_cfm)))
|
||||
return status;
|
||||
|
||||
/* Allocate the answer message */
|
||||
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
|
||||
if (!skb) {
|
||||
printk("Error allocating memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
val32 = mem_read_cfm.memdata;
|
||||
if (nla_put_u32(skb, RWNX_TM_ATTR_REG_VALUE32, val32))
|
||||
goto nla_put_failure;
|
||||
|
||||
/* Send the answer to upper layer */
|
||||
status = cfg80211_testmode_reply(skb);
|
||||
if (status < 0)
|
||||
printk("Error sending msg : %d\n", status);
|
||||
}
|
||||
break;
|
||||
|
||||
case RWNX_TM_CMD_APP2DEV_REG_WRITE:
|
||||
{
|
||||
if (!tb[RWNX_TM_ATTR_REG_VALUE32]) {
|
||||
printk("Error finding value to write\n");
|
||||
return -ENOMSG;
|
||||
} else {
|
||||
val32 = nla_get_u32(tb[RWNX_TM_ATTR_REG_VALUE32]);
|
||||
/* Send the command to the LMAC */
|
||||
if ((status = rwnx_send_dbg_mem_write_req(rwnx_hw, mem_addr, val32)))
|
||||
return status;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("Unknown testmode register command ID\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
nla_put_failure:
|
||||
kfree_skb(skb);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles the user application commands for Debug filter settings.
|
||||
*
|
||||
* @hw: ieee80211_hw object that represents the device
|
||||
* @tb: general message fields from the user space
|
||||
*/
|
||||
int rwnx_testmode_dbg_filter(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
{
|
||||
struct rwnx_hw *rwnx_hw = hw->priv;
|
||||
u32 filter;
|
||||
int status = 0;
|
||||
|
||||
/* First check if the filter is there */
|
||||
if (!tb[RWNX_TM_ATTR_REG_FILTER]) {
|
||||
printk("Error finding filter value\n");
|
||||
return -ENOMSG;
|
||||
}
|
||||
|
||||
filter = nla_get_u32(tb[RWNX_TM_ATTR_REG_FILTER]);
|
||||
RWNX_DBG("testmode debug filter, setting: 0x%x\n", filter);
|
||||
|
||||
switch (nla_get_u32(tb[RWNX_TM_ATTR_COMMAND])) {
|
||||
case RWNX_TM_CMD_APP2DEV_SET_DBGMODFILTER:
|
||||
{
|
||||
/* Send the command to the LMAC */
|
||||
if ((status = rwnx_send_dbg_set_mod_filter_req(rwnx_hw, filter)))
|
||||
return status;
|
||||
}
|
||||
break;
|
||||
case RWNX_TM_CMD_APP2DEV_SET_DBGSEVFILTER:
|
||||
{
|
||||
/* Send the command to the LMAC */
|
||||
if ((status = rwnx_send_dbg_set_sev_filter_req(rwnx_hw, filter)))
|
||||
return status;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("Unknown testmode register command ID\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles the user application commands for register access without using
|
||||
* the normal LMAC messaging way.
|
||||
* This time register access will be done through direct PCI BAR windows. This can be used
|
||||
* to access registers even when the :AMC FW is stuck.
|
||||
*
|
||||
* @hw: ieee80211_hw object that represents the device
|
||||
* @tb: general message fields from the user space
|
||||
*/
|
||||
int rwnx_testmode_reg_dbg(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
{
|
||||
struct rwnx_hw *rwnx_hw = hw->priv;
|
||||
struct rwnx_plat *rwnx_plat = rwnx_hw->plat;
|
||||
u32 mem_addr;
|
||||
struct sk_buff *skb;
|
||||
int status = 0;
|
||||
volatile unsigned int reg_value = 0;
|
||||
unsigned int offset;
|
||||
|
||||
/* First check if register address is there */
|
||||
if (!tb[RWNX_TM_ATTR_REG_OFFSET]) {
|
||||
printk("Error finding register offset\n");
|
||||
return -ENOMSG;
|
||||
}
|
||||
|
||||
mem_addr = nla_get_u32(tb[RWNX_TM_ATTR_REG_OFFSET]);
|
||||
offset = mem_addr & 0x00FFFFFF;
|
||||
|
||||
switch (nla_get_u32(tb[RWNX_TM_ATTR_COMMAND])) {
|
||||
case RWNX_TM_CMD_APP2DEV_REG_READ_DBG:
|
||||
{
|
||||
/*** Send the command to the LMAC ***/
|
||||
reg_value = RWNX_REG_READ(rwnx_plat, RWNX_ADDR_SYSTEM, offset);
|
||||
|
||||
/* Allocate the answer message */
|
||||
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
|
||||
if (!skb) {
|
||||
printk("Error allocating memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (nla_put_u32(skb, RWNX_TM_ATTR_REG_VALUE32, reg_value))
|
||||
goto nla_put_failure;
|
||||
|
||||
/* Send the answer to upper layer */
|
||||
status = cfg80211_testmode_reply(skb);
|
||||
if (status < 0)
|
||||
printk("Error sending msg : %d\n", status);
|
||||
}
|
||||
break;
|
||||
|
||||
case RWNX_TM_CMD_APP2DEV_REG_WRITE_DBG:
|
||||
{
|
||||
if (!tb[RWNX_TM_ATTR_REG_VALUE32]) {
|
||||
printk("Error finding value to write\n");
|
||||
return -ENOMSG;
|
||||
} else {
|
||||
reg_value = nla_get_u32(tb[RWNX_TM_ATTR_REG_VALUE32]);
|
||||
|
||||
/* Send the command to the LMAC */
|
||||
RWNX_REG_WRITE(reg_value, rwnx_plat, RWNX_ADDR_SYSTEM,
|
||||
offset);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("Unknown testmode register command ID\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
nla_put_failure:
|
||||
kfree_skb(skb);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
****************************************************************************************
|
||||
*
|
||||
* @file rwnx_testmode.h
|
||||
*
|
||||
* @brief Test mode function declarations
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
****************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef RWNX_TESTMODE_H_
|
||||
#define RWNX_TESTMODE_H_
|
||||
|
||||
#include <net/mac80211.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
/* Commands from user space to kernel space(RWNX_TM_CMD_APP2DEV_XX) and
|
||||
* from and kernel space to user space(RWNX_TM_CMD_DEV2APP_XX).
|
||||
* The command ID is carried with RWNX_TM_ATTR_COMMAND.
|
||||
*/
|
||||
enum rwnx_tm_cmd_t {
|
||||
/* commands from user application to access register */
|
||||
RWNX_TM_CMD_APP2DEV_REG_READ = 1,
|
||||
RWNX_TM_CMD_APP2DEV_REG_WRITE,
|
||||
|
||||
/* commands from user application to select the Debug levels */
|
||||
RWNX_TM_CMD_APP2DEV_SET_DBGMODFILTER,
|
||||
RWNX_TM_CMD_APP2DEV_SET_DBGSEVFILTER,
|
||||
|
||||
/* commands to access registers without sending messages to LMAC layer,
|
||||
* this must be used when LMAC FW is stuck. */
|
||||
RWNX_TM_CMD_APP2DEV_REG_READ_DBG,
|
||||
RWNX_TM_CMD_APP2DEV_REG_WRITE_DBG,
|
||||
|
||||
RWNX_TM_CMD_MAX,
|
||||
};
|
||||
|
||||
enum rwnx_tm_attr_t {
|
||||
RWNX_TM_ATTR_NOT_APPLICABLE = 0,
|
||||
|
||||
RWNX_TM_ATTR_COMMAND,
|
||||
|
||||
/* When RWNX_TM_ATTR_COMMAND is RWNX_TM_CMD_APP2DEV_REG_XXX,
|
||||
* The mandatory fields are:
|
||||
* RWNX_TM_ATTR_REG_OFFSET for the offset of the target register;
|
||||
* RWNX_TM_ATTR_REG_VALUE32 for value */
|
||||
RWNX_TM_ATTR_REG_OFFSET,
|
||||
RWNX_TM_ATTR_REG_VALUE32,
|
||||
|
||||
/* When RWNX_TM_ATTR_COMMAND is RWNX_TM_CMD_APP2DEV_SET_DBGXXXFILTER,
|
||||
* The mandatory field is RWNX_TM_ATTR_REG_FILTER. */
|
||||
RWNX_TM_ATTR_REG_FILTER,
|
||||
|
||||
RWNX_TM_ATTR_MAX,
|
||||
};
|
||||
|
||||
/***********************************************************************/
|
||||
int rwnx_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb);
|
||||
int rwnx_testmode_dbg_filter(struct ieee80211_hw *hw, struct nlattr **tb);
|
||||
int rwnx_testmode_reg_dbg(struct ieee80211_hw *hw, struct nlattr **tb);
|
||||
|
||||
#endif /* RWNX_TESTMODE_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,198 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_tx.h
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#ifndef _RWNX_TX_H_
|
||||
#define _RWNX_TX_H_
|
||||
|
||||
#include <linux/ieee80211.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include "lmac_types.h"
|
||||
#include "ipc_shared.h"
|
||||
#include "rwnx_txq.h"
|
||||
#include "hal_desc.h"
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
|
||||
#define IEEE80211_NUM_TIDS 16
|
||||
#endif
|
||||
|
||||
#define RWNX_HWQ_BK 0
|
||||
#define RWNX_HWQ_BE 1
|
||||
#define RWNX_HWQ_VI 2
|
||||
#define RWNX_HWQ_VO 3
|
||||
#define RWNX_HWQ_BCMC 4
|
||||
#define RWNX_HWQ_NB NX_TXQ_CNT
|
||||
#define RWNX_HWQ_ALL_ACS (RWNX_HWQ_BK | RWNX_HWQ_BE | RWNX_HWQ_VI | RWNX_HWQ_VO)
|
||||
#define RWNX_HWQ_ALL_ACS_BIT ( BIT(RWNX_HWQ_BK) | BIT(RWNX_HWQ_BE) | \
|
||||
BIT(RWNX_HWQ_VI) | BIT(RWNX_HWQ_VO) )
|
||||
|
||||
#define RWNX_TX_LIFETIME_MS 1000
|
||||
#define RWNX_TX_MAX_RATES NX_TX_MAX_RATES
|
||||
|
||||
#define RWNX_SWTXHDR_ALIGN_SZ 4
|
||||
#define RWNX_SWTXHDR_ALIGN_MSK (RWNX_SWTXHDR_ALIGN_SZ - 1)
|
||||
#define RWNX_SWTXHDR_ALIGN_PADS(x) \
|
||||
((RWNX_SWTXHDR_ALIGN_SZ - ((x) & RWNX_SWTXHDR_ALIGN_MSK)) \
|
||||
& RWNX_SWTXHDR_ALIGN_MSK)
|
||||
#if RWNX_SWTXHDR_ALIGN_SZ & RWNX_SWTXHDR_ALIGN_MSK
|
||||
#error bad RWNX_SWTXHDR_ALIGN_SZ
|
||||
#endif
|
||||
|
||||
#define AMSDU_PADDING(x) ((4 - ((x) & 0x3)) & 0x3)
|
||||
|
||||
#define TXU_CNTRL_RETRY BIT(0)
|
||||
#define TXU_CNTRL_MORE_DATA BIT(2)
|
||||
#define TXU_CNTRL_MGMT BIT(3)
|
||||
#define TXU_CNTRL_MGMT_NO_CCK BIT(4)
|
||||
#define TXU_CNTRL_AMSDU BIT(6)
|
||||
#define TXU_CNTRL_MGMT_ROBUST BIT(7)
|
||||
#define TXU_CNTRL_USE_4ADDR BIT(8)
|
||||
#define TXU_CNTRL_EOSP BIT(9)
|
||||
#define TXU_CNTRL_MESH_FWD BIT(10)
|
||||
#define TXU_CNTRL_TDLS BIT(11)
|
||||
|
||||
extern const int rwnx_tid2hwq[IEEE80211_NUM_TIDS];
|
||||
|
||||
/**
|
||||
* struct rwnx_amsdu_txhdr - Structure added in skb headroom (instead of
|
||||
* rwnx_txhdr) for amsdu subframe buffer (except for the first subframe
|
||||
* that has a normal rwnx_txhdr)
|
||||
*
|
||||
* @list List of other amsdu subframe (rwnx_sw_txhdr.amsdu.hdrs)
|
||||
* @map_len Length to be downloaded for this subframe
|
||||
* @dma_addr Buffer address form embedded point of view
|
||||
* @skb skb
|
||||
* @pad padding added before this subframe
|
||||
* (only use when amsdu must be dismantled)
|
||||
* @msdu_len Size, in bytes, of the MSDU (without padding nor amsdu header)
|
||||
*/
|
||||
struct rwnx_amsdu_txhdr {
|
||||
struct list_head list;
|
||||
size_t map_len;
|
||||
dma_addr_t dma_addr;
|
||||
struct sk_buff *skb;
|
||||
u16 pad;
|
||||
u16 msdu_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rwnx_amsdu - Structure to manage creation of an A-MSDU, updated
|
||||
* only In the first subframe of an A-MSDU
|
||||
*
|
||||
* @hdrs List of subframe of rwnx_amsdu_txhdr
|
||||
* @len Current size for this A-MDSU (doesn't take padding into account)
|
||||
* 0 means that no amsdu is in progress
|
||||
* @nb Number of subframe in the amsdu
|
||||
* @pad Padding to add before adding a new subframe
|
||||
*/
|
||||
struct rwnx_amsdu {
|
||||
struct list_head hdrs;
|
||||
u16 len;
|
||||
u8 nb;
|
||||
u8 pad;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rwnx_sw_txhdr - Software part of tx header
|
||||
*
|
||||
* @rwnx_sta sta to which this buffer is addressed
|
||||
* @rwnx_vif vif that send the buffer
|
||||
* @txq pointer to TXQ used to send the buffer
|
||||
* @hw_queue Index of the HWQ used to push the buffer.
|
||||
* May be different than txq->hwq->id on confirmation.
|
||||
* @frame_len Size of the frame (doesn't not include mac header)
|
||||
* (Only used to update stat, can't we use skb->len instead ?)
|
||||
* @headroom Headroom added in skb to add rwnx_txhdr
|
||||
* (Only used to remove it before freeing skb, is it needed ?)
|
||||
* @amsdu Description of amsdu whose first subframe is this buffer
|
||||
* (amsdu.nb = 0 means this buffer is not part of amsdu)
|
||||
* @skb skb received from transmission
|
||||
* @map_len Length mapped for DMA (only rwnx_hw_txhdr and data are mapped)
|
||||
* @dma_addr DMA address after mapping
|
||||
* @desc Buffer description that will be copied in shared mem for FW
|
||||
*/
|
||||
struct rwnx_sw_txhdr {
|
||||
struct rwnx_sta *rwnx_sta;
|
||||
struct rwnx_vif *rwnx_vif;
|
||||
struct rwnx_txq *txq;
|
||||
u8 hw_queue;
|
||||
u16 frame_len;
|
||||
u16 headroom;
|
||||
#ifdef CONFIG_RWNX_AMSDUS_TX
|
||||
struct rwnx_amsdu amsdu;
|
||||
#endif
|
||||
u32 need_cfm;
|
||||
struct sk_buff *skb;
|
||||
|
||||
size_t map_len;
|
||||
dma_addr_t dma_addr;
|
||||
struct txdesc_api desc;
|
||||
u8 raw_frame;
|
||||
u8 fixed_rate;
|
||||
u16 rate_config;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rwnx_txhdr - Stucture to control transimission of packet
|
||||
* (Added in skb headroom)
|
||||
*
|
||||
* @sw_hdr: Information from driver
|
||||
* @cache_guard:
|
||||
* @hw_hdr: Information for/from hardware
|
||||
*/
|
||||
struct rwnx_txhdr {
|
||||
struct rwnx_sw_txhdr *sw_hdr;
|
||||
char cache_guard[L1_CACHE_BYTES];
|
||||
struct rwnx_hw_txhdr hw_hdr;
|
||||
};
|
||||
|
||||
u16 rwnx_select_txq(struct rwnx_vif *rwnx_vif, struct sk_buff *skb);
|
||||
netdev_tx_t rwnx_start_xmit(struct sk_buff *skb, struct net_device *dev);
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
|
||||
int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta,
|
||||
struct cfg80211_mgmt_tx_params *params, bool offchan,
|
||||
u64 *cookie);
|
||||
#else
|
||||
int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta,
|
||||
struct ieee80211_channel *channel, bool offchan,
|
||||
unsigned int wait, const u8* buf, size_t len,
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
|
||||
bool no_cck,
|
||||
#endif
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
|
||||
bool dont_wait_for_ack,
|
||||
#endif
|
||||
u64 *cookie);
|
||||
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
|
||||
#ifdef CONFIG_RWNX_MON_XMIT
|
||||
int rwnx_start_monitor_if_xmit(struct sk_buff *skb, struct net_device *dev);
|
||||
#endif
|
||||
int rwnx_txdatacfm(void *pthis, void *host_id);
|
||||
|
||||
struct rwnx_hw;
|
||||
struct rwnx_sta;
|
||||
void rwnx_set_traffic_status(struct rwnx_hw *rwnx_hw,
|
||||
struct rwnx_sta *sta,
|
||||
bool available,
|
||||
u8 ps_id);
|
||||
void rwnx_ps_bh_enable(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta,
|
||||
bool enable);
|
||||
void rwnx_ps_bh_traffic_req(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta,
|
||||
u16 pkt_req, u8 ps_id);
|
||||
|
||||
void rwnx_switch_vif_sta_txq(struct rwnx_sta *sta, struct rwnx_vif *old_vif,
|
||||
struct rwnx_vif *new_vif);
|
||||
|
||||
int rwnx_dbgfs_print_sta(char *buf, size_t size, struct rwnx_sta *sta,
|
||||
struct rwnx_hw *rwnx_hw);
|
||||
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);
|
||||
|
||||
#endif /* _RWNX_TX_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,397 @@
|
||||
/**
|
||||
****************************************************************************************
|
||||
*
|
||||
* @file rwnx_txq.h
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
****************************************************************************************
|
||||
*/
|
||||
#ifndef _RWNX_TXQ_H_
|
||||
#define _RWNX_TXQ_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/ieee80211.h>
|
||||
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
/**
|
||||
* Fullmac TXQ configuration:
|
||||
* - STA: 1 TXQ per TID (limited to 8)
|
||||
* 1 TXQ for bufferable MGT frames
|
||||
* - VIF: 1 TXQ for Multi/Broadcast +
|
||||
* 1 TXQ for MGT for unknown STAs or non-bufferable MGT frames
|
||||
* - 1 TXQ for offchannel transmissions
|
||||
*
|
||||
*
|
||||
* Txq mapping looks like
|
||||
* for NX_REMOTE_STA_MAX=10 and NX_VIRT_DEV_MAX=4
|
||||
*
|
||||
* | TXQ | NDEV_ID | VIF | STA | TID | HWQ |
|
||||
* |-----+---------+-----+-------+------+-----|-
|
||||
* | 0 | 0 | | 0 | 0 | 1 | 9 TXQ per STA
|
||||
* | 1 | 1 | | 0 | 1 | 0 | (8 data + 1 mgmt)
|
||||
* | 2 | 2 | | 0 | 2 | 0 |
|
||||
* | 3 | 3 | | 0 | 3 | 1 |
|
||||
* | 4 | 4 | | 0 | 4 | 2 |
|
||||
* | 5 | 5 | | 0 | 5 | 2 |
|
||||
* | 6 | 6 | | 0 | 6 | 3 |
|
||||
* | 7 | 7 | | 0 | 7 | 3 |
|
||||
* | 8 | N/A | | 0 | MGMT | 3 |
|
||||
* |-----+---------+-----+-------+------+-----|-
|
||||
* | ... | | | | | | Same for all STAs
|
||||
* |-----+---------+-----+-------+------+-----|-
|
||||
* | 90 | 80 | 0 | BC/MC | 0 | 1/4 | 1 TXQ for BC/MC per VIF
|
||||
* | ... | | | | | |
|
||||
* | 93 | 80 | 3 | BC/MC | 0 | 1/4 |
|
||||
* |-----+---------+-----+-------+------+-----|-
|
||||
* | 94 | N/A | 0 | N/A | MGMT | 3 | 1 TXQ for unknown STA per VIF
|
||||
* | ... | | | | | |
|
||||
* | 97 | N/A | 3 | N/A | MGMT | 3 |
|
||||
* |-----+---------+-----+-------+------+-----|-
|
||||
* | 98 | N/A | | N/A | MGMT | 3 | 1 TXQ for offchannel frame
|
||||
*/
|
||||
#define NX_NB_TID_PER_STA 8
|
||||
#define NX_NB_TXQ_PER_STA (NX_NB_TID_PER_STA + 1)
|
||||
#define NX_NB_TXQ_PER_VIF 2
|
||||
#define NX_NB_TXQ ((NX_NB_TXQ_PER_STA * NX_REMOTE_STA_MAX) + \
|
||||
(NX_NB_TXQ_PER_VIF * NX_VIRT_DEV_MAX) + 1)
|
||||
|
||||
#define NX_FIRST_VIF_TXQ_IDX (NX_REMOTE_STA_MAX * NX_NB_TXQ_PER_STA)
|
||||
#define NX_FIRST_BCMC_TXQ_IDX NX_FIRST_VIF_TXQ_IDX
|
||||
#define NX_FIRST_UNK_TXQ_IDX (NX_FIRST_BCMC_TXQ_IDX + NX_VIRT_DEV_MAX)
|
||||
|
||||
#define NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC (NX_REMOTE_STA_MAX_FOR_OLD_IC * NX_NB_TXQ_PER_STA)
|
||||
#define NX_FIRST_BCMC_TXQ_IDX_FOR_OLD_IC NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC
|
||||
#define NX_FIRST_UNK_TXQ_IDX_FOR_OLD_IC (NX_FIRST_BCMC_TXQ_IDX_FOR_OLD_IC + NX_VIRT_DEV_MAX)
|
||||
|
||||
|
||||
#define NX_OFF_CHAN_TXQ_IDX (NX_FIRST_VIF_TXQ_IDX + \
|
||||
(NX_VIRT_DEV_MAX * NX_NB_TXQ_PER_VIF))
|
||||
|
||||
#define NX_OFF_CHAN_TXQ_IDX_FOR_OLD_IC (NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC + \
|
||||
(NX_VIRT_DEV_MAX * NX_NB_TXQ_PER_VIF))
|
||||
|
||||
|
||||
#define NX_BCMC_TXQ_TYPE 0
|
||||
#define NX_UNK_TXQ_TYPE 1
|
||||
|
||||
/**
|
||||
* Each data TXQ is a netdev queue. TXQ to send MGT are not data TXQ as
|
||||
* they did not recieved buffer from netdev interface.
|
||||
* Need to allocate the maximum case.
|
||||
* AP : all STAs + 1 BC/MC
|
||||
*/
|
||||
#define NX_NB_NDEV_TXQ ((NX_NB_TID_PER_STA * NX_REMOTE_STA_MAX) + 1 )
|
||||
#define NX_NB_NDEV_TXQ_FOR_OLD_IC ((NX_NB_TID_PER_STA * NX_REMOTE_STA_MAX_FOR_OLD_IC) + 1)
|
||||
|
||||
#define NX_BCMC_TXQ_NDEV_IDX (NX_NB_TID_PER_STA * NX_REMOTE_STA_MAX)
|
||||
#define NX_BCMC_TXQ_NDEV_IDX_FOR_OLD_IC (NX_NB_TID_PER_STA * NX_REMOTE_STA_MAX_FOR_OLD_IC)
|
||||
#define NX_STA_NDEV_IDX(tid, sta_idx) ((tid) + (sta_idx) * NX_NB_TID_PER_STA)
|
||||
#define NDEV_NO_TXQ 0xffff
|
||||
#if (NX_NB_NDEV_TXQ >= NDEV_NO_TXQ)
|
||||
#error("Need to increase struct rwnx_txq->ndev_idx size")
|
||||
#endif
|
||||
|
||||
/* stop netdev queue when number of queued buffers if greater than this */
|
||||
#define RWNX_NDEV_FLOW_CTRL_STOP 64
|
||||
/* restart netdev queue when number of queued buffers is lower than this */
|
||||
#define RWNX_NDEV_FLOW_CTRL_RESTART 64
|
||||
|
||||
#endif /* CONFIG_RWNX_FULLMAC */
|
||||
|
||||
#define TXQ_INACTIVE 0xffff
|
||||
#if (NX_NB_TXQ >= TXQ_INACTIVE)
|
||||
#error("Need to increase struct rwnx_txq->idx size")
|
||||
#endif
|
||||
|
||||
#define NX_TXQ_INITIAL_CREDITS 64
|
||||
|
||||
/**
|
||||
* TXQ tid sorted by decreasing priority
|
||||
*/
|
||||
extern const int nx_tid_prio[NX_NB_TID_PER_STA];
|
||||
|
||||
/**
|
||||
* struct rwnx_hwq - Structure used to save information relative to
|
||||
* an AC TX queue (aka HW queue)
|
||||
* @list: List of TXQ, that have buffers ready for this HWQ
|
||||
* @credits: available credit for the queue (i.e. nb of buffers that
|
||||
* can be pushed to FW )
|
||||
* @id Id of the HWQ among RWNX_HWQ_....
|
||||
* @size size of the queue
|
||||
* @need_processing Indicate if hwq should be processed
|
||||
* @len number of packet ready to be pushed to fw for this HW queue
|
||||
* @len_stop threshold to stop mac80211(i.e. netdev) queues. Stop queue when
|
||||
* driver has more than @len_stop packets ready.
|
||||
* @len_start threshold to wake mac8011 queues. Wake queue when driver has
|
||||
* less than @len_start packets ready.
|
||||
*/
|
||||
struct rwnx_hwq {
|
||||
struct list_head list;
|
||||
u8 size;
|
||||
u8 id;
|
||||
bool need_processing;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum rwnx_push_flags - Flags of pushed buffer
|
||||
*
|
||||
* @RWNX_PUSH_RETRY Pushing a buffer for retry
|
||||
* @RWNX_PUSH_IMMEDIATE Pushing a buffer without queuing it first
|
||||
*/
|
||||
enum rwnx_push_flags {
|
||||
RWNX_PUSH_RETRY = BIT(0),
|
||||
RWNX_PUSH_IMMEDIATE = BIT(1),
|
||||
};
|
||||
|
||||
/**
|
||||
* enum rwnx_txq_flags - TXQ status flag
|
||||
*
|
||||
* @RWNX_TXQ_IN_HWQ_LIST: The queue is scheduled for transmission
|
||||
* @RWNX_TXQ_STOP_FULL: No more credits for the queue
|
||||
* @RWNX_TXQ_STOP_CSA: CSA is in progress
|
||||
* @RWNX_TXQ_STOP_STA_PS: Destiniation sta is currently in power save mode
|
||||
* @RWNX_TXQ_STOP_VIF_PS: Vif owning this queue is currently in power save mode
|
||||
* @RWNX_TXQ_STOP_CHAN: Channel of this queue is not the current active channel
|
||||
* @RWNX_TXQ_STOP_MU_POS: TXQ is stopped waiting for all the buffers pushed to
|
||||
* fw to be confirmed
|
||||
* @RWNX_TXQ_STOP: All possible reason to have a txq stopped
|
||||
* @RWNX_TXQ_NDEV_FLOW_CTRL: associated netdev queue is currently stopped.
|
||||
* Note: when a TXQ is flowctrl it is NOT stopped
|
||||
*/
|
||||
enum rwnx_txq_flags {
|
||||
RWNX_TXQ_IN_HWQ_LIST = BIT(0),
|
||||
RWNX_TXQ_STOP_FULL = BIT(1),
|
||||
RWNX_TXQ_STOP_CSA = BIT(2),
|
||||
RWNX_TXQ_STOP_STA_PS = BIT(3),
|
||||
RWNX_TXQ_STOP_VIF_PS = BIT(4),
|
||||
RWNX_TXQ_STOP_CHAN = BIT(5),
|
||||
RWNX_TXQ_STOP_MU_POS = BIT(6),
|
||||
RWNX_TXQ_STOP = (RWNX_TXQ_STOP_FULL | RWNX_TXQ_STOP_CSA |
|
||||
RWNX_TXQ_STOP_STA_PS | RWNX_TXQ_STOP_VIF_PS |
|
||||
RWNX_TXQ_STOP_CHAN) ,
|
||||
RWNX_TXQ_NDEV_FLOW_CTRL = BIT(7),
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct rwnx_txq - Structure used to save information relative to
|
||||
* a RA/TID TX queue
|
||||
*
|
||||
* @idx: Unique txq idx. Set to TXQ_INACTIVE if txq is not used.
|
||||
* @status: bitfield of @rwnx_txq_flags.
|
||||
* @credits: available credit for the queue (i.e. nb of buffers that
|
||||
* can be pushed to FW).
|
||||
* @pkt_sent: number of consecutive pkt sent without leaving HW queue list
|
||||
* @pkt_pushed: number of pkt currently pending for transmission confirmation
|
||||
* @sched_list: list node for HW queue schedule list (rwnx_hwq.list)
|
||||
* @sk_list: list of buffers to push to fw
|
||||
* @last_retry_skb: pointer on the last skb in @sk_list that is a retry.
|
||||
* (retry skb are stored at the beginning of the list)
|
||||
* NULL if no retry skb is queued in @sk_list
|
||||
* @nb_retry: Number of retry packet queued.
|
||||
* @hwq: Pointer on the associated HW queue.
|
||||
* @push_limit: number of packet to push before removing the txq from hwq list.
|
||||
* (we always have push_limit < skb_queue_len(sk_list))
|
||||
* @tid: TID
|
||||
*
|
||||
* FULLMAC specific
|
||||
* @ps_id: Index to use for Power save mode (LEGACY or UAPSD)
|
||||
* @ndev_idx: txq idx from netdev point of view (0xFF for non netdev queue)
|
||||
* @ndev: pointer to ndev of the corresponding vif
|
||||
* @amsdu: pointer to rwnx_sw_txhdr of the first subframe of the A-MSDU.
|
||||
* NULL if no A-MSDU frame is in construction
|
||||
* @amsdu_len: Maximum size allowed for an A-MSDU. 0 means A-MSDU not allowed
|
||||
*/
|
||||
struct rwnx_txq {
|
||||
u16 idx;
|
||||
u8 status;
|
||||
s8 credits;
|
||||
u8 pkt_sent;
|
||||
u8 pkt_pushed[CONFIG_USER_MAX];
|
||||
struct list_head sched_list;
|
||||
struct sk_buff_head sk_list;
|
||||
struct sk_buff *last_retry_skb;
|
||||
struct rwnx_hwq *hwq;
|
||||
int nb_retry;
|
||||
u8 push_limit;
|
||||
u8 tid;
|
||||
#ifdef CONFIG_MAC80211_TXQ
|
||||
unsigned long nb_ready_mac80211;
|
||||
#endif
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
struct rwnx_sta *sta;
|
||||
u8 ps_id;
|
||||
u16 ndev_idx;
|
||||
struct net_device *ndev;
|
||||
#ifdef CONFIG_RWNX_AMSDUS_TX
|
||||
struct rwnx_sw_txhdr *amsdu;
|
||||
u16 amsdu_len;
|
||||
#endif /* CONFIG_RWNX_AMSDUS_TX */
|
||||
#endif /* CONFIG_RWNX_FULLMAC */
|
||||
#ifdef CONFIG_RWNX_MUMIMO_TX
|
||||
u8 mumimo_info;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct rwnx_sta;
|
||||
struct rwnx_vif;
|
||||
struct rwnx_hw;
|
||||
struct rwnx_sw_txhdr;
|
||||
|
||||
#ifdef CONFIG_RWNX_MUMIMO_TX
|
||||
#define RWNX_TXQ_GROUP_ID(txq) ((txq)->mumimo_info & 0x3f)
|
||||
#define RWNX_TXQ_POS_ID(txq) (((txq)->mumimo_info >> 6) & 0x3)
|
||||
#else
|
||||
#define RWNX_TXQ_GROUP_ID(txq) 0
|
||||
#define RWNX_TXQ_POS_ID(txq) 0
|
||||
#endif /* CONFIG_RWNX_MUMIMO_TX */
|
||||
|
||||
static inline bool rwnx_txq_is_stopped(struct rwnx_txq *txq)
|
||||
{
|
||||
return (txq->status & RWNX_TXQ_STOP);
|
||||
}
|
||||
|
||||
static inline bool rwnx_txq_is_full(struct rwnx_txq *txq)
|
||||
{
|
||||
return (txq->status & RWNX_TXQ_STOP_FULL);
|
||||
}
|
||||
|
||||
static inline bool rwnx_txq_is_scheduled(struct rwnx_txq *txq)
|
||||
{
|
||||
return (txq->status & RWNX_TXQ_IN_HWQ_LIST);
|
||||
}
|
||||
|
||||
/**
|
||||
* foreach_sta_txq - Macro to iterate over all TXQ of a STA in increasing
|
||||
* TID order
|
||||
*
|
||||
* @sta: pointer to rwnx_sta
|
||||
* @txq: pointer to rwnx_txq updated with the next TXQ at each iteration
|
||||
* @tid: int updated with the TXQ tid at each iteration
|
||||
* @rwnx_hw: main driver data
|
||||
*/
|
||||
#ifdef CONFIG_MAC80211_TXQ
|
||||
#define foreach_sta_txq(sta, txq, tid, rwnx_hw) \
|
||||
for (tid = 0, txq = rwnx_txq_sta_get(sta, 0); \
|
||||
tid < NX_NB_TXQ_PER_STA; \
|
||||
tid++, txq = rwnx_txq_sta_get(sta, tid))
|
||||
|
||||
#elif defined(CONFIG_RWNX_FULLMAC) /* CONFIG_RWNX_FULLMAC */
|
||||
#define foreach_sta_txq(sta, txq, tid, rwnx_hw) \
|
||||
for (tid = 0, txq = rwnx_txq_sta_get(sta, 0, rwnx_hw); \
|
||||
tid < (is_multicast_sta(sta->sta_idx) ? 1 : NX_NB_TXQ_PER_STA); \
|
||||
tid++, txq++)
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* foreach_sta_txq_prio - Macro to iterate over all TXQ of a STA in
|
||||
* decreasing priority order
|
||||
*
|
||||
* @sta: pointer to rwnx_sta
|
||||
* @txq: pointer to rwnx_txq updated with the next TXQ at each iteration
|
||||
* @tid: int updated with the TXQ tid at each iteration
|
||||
* @i: int updated with ieration count
|
||||
* @rwnx_hw: main driver data
|
||||
*
|
||||
* Note: For fullmac txq for mgmt frame is skipped
|
||||
*/
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
#define foreach_sta_txq_prio(sta, txq, tid, i, rwnx_hw) \
|
||||
for (i = 0, tid = nx_tid_prio[0], txq = rwnx_txq_sta_get(sta, tid, rwnx_hw); \
|
||||
i < NX_NB_TID_PER_STA; \
|
||||
i++, tid = nx_tid_prio[i], txq = rwnx_txq_sta_get(sta, tid, rwnx_hw))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* foreach_vif_txq - Macro to iterate over all TXQ of a VIF (in AC order)
|
||||
*
|
||||
* @vif: pointer to rwnx_vif
|
||||
* @txq: pointer to rwnx_txq updated with the next TXQ at each iteration
|
||||
* @ac: int updated with the TXQ ac at each iteration
|
||||
*/
|
||||
#ifdef CONFIG_MAC80211_TXQ
|
||||
#define foreach_vif_txq(vif, txq, ac) \
|
||||
for (ac = RWNX_HWQ_BK, txq = rwnx_txq_vif_get(vif, ac); \
|
||||
ac < NX_NB_TXQ_PER_VIF; \
|
||||
ac++, txq = rwnx_txq_vif_get(vif, ac))
|
||||
|
||||
#else
|
||||
#define foreach_vif_txq(vif, txq, ac) \
|
||||
for (ac = RWNX_HWQ_BK, txq = &vif->txqs[0]; \
|
||||
ac < NX_NB_TXQ_PER_VIF; \
|
||||
ac++, txq++)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
struct rwnx_txq *rwnx_txq_sta_get(struct rwnx_sta *sta, u8 tid,
|
||||
struct rwnx_hw * rwnx_hw);
|
||||
struct rwnx_txq *rwnx_txq_vif_get(struct rwnx_vif *vif, u8 type);
|
||||
#endif /* CONFIG_RWNX_FULLMAC */
|
||||
|
||||
/**
|
||||
* rwnx_txq_vif_get_status - return status bits related to the vif
|
||||
*
|
||||
* @rwnx_vif: Pointer to vif structure
|
||||
*/
|
||||
static inline u8 rwnx_txq_vif_get_status(struct rwnx_vif *rwnx_vif)
|
||||
{
|
||||
struct rwnx_txq *txq = rwnx_txq_vif_get(rwnx_vif, 0);
|
||||
return (txq->status & (RWNX_TXQ_STOP_CHAN | RWNX_TXQ_STOP_VIF_PS));
|
||||
}
|
||||
|
||||
void rwnx_txq_vif_init(struct rwnx_hw * rwnx_hw, struct rwnx_vif *vif,
|
||||
u8 status);
|
||||
void rwnx_txq_vif_deinit(struct rwnx_hw * rwnx_hw, struct rwnx_vif *vif);
|
||||
void rwnx_txq_sta_init(struct rwnx_hw * rwnx_hw, struct rwnx_sta *rwnx_sta,
|
||||
u8 status);
|
||||
void rwnx_txq_sta_deinit(struct rwnx_hw * rwnx_hw, struct rwnx_sta *rwnx_sta);
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
void rwnx_txq_unk_vif_init(struct rwnx_vif *rwnx_vif);
|
||||
void rwnx_txq_unk_vif_deinit(struct rwnx_vif *vif);
|
||||
void rwnx_txq_offchan_init(struct rwnx_vif *rwnx_vif);
|
||||
void rwnx_txq_offchan_deinit(struct rwnx_vif *rwnx_vif);
|
||||
void rwnx_txq_tdls_vif_init(struct rwnx_vif *rwnx_vif);
|
||||
void rwnx_txq_tdls_vif_deinit(struct rwnx_vif *vif);
|
||||
void rwnx_txq_tdls_sta_start(struct rwnx_vif *rwnx_vif, u16 reason,
|
||||
struct rwnx_hw *rwnx_hw);
|
||||
void rwnx_txq_tdls_sta_stop(struct rwnx_vif *rwnx_vif, u16 reason,
|
||||
struct rwnx_hw *rwnx_hw);
|
||||
#endif
|
||||
|
||||
|
||||
void rwnx_txq_add_to_hw_list(struct rwnx_txq *txq);
|
||||
void rwnx_txq_del_from_hw_list(struct rwnx_txq *txq);
|
||||
void rwnx_txq_stop(struct rwnx_txq *txq, u16 reason);
|
||||
void rwnx_txq_start(struct rwnx_txq *txq, u16 reason);
|
||||
void rwnx_txq_vif_start(struct rwnx_vif *vif, u16 reason,
|
||||
struct rwnx_hw *rwnx_hw);
|
||||
void rwnx_txq_vif_stop(struct rwnx_vif *vif, u16 reason,
|
||||
struct rwnx_hw *rwnx_hw);
|
||||
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
void rwnx_txq_sta_start(struct rwnx_sta *sta, u16 reason,
|
||||
struct rwnx_hw *rwnx_hw);
|
||||
void rwnx_txq_sta_stop(struct rwnx_sta *sta, u16 reason,
|
||||
struct rwnx_hw *rwnx_hw);
|
||||
void rwnx_txq_offchan_start(struct rwnx_hw *rwnx_hw);
|
||||
void rwnx_txq_sta_switch_vif(struct rwnx_sta *sta, struct rwnx_vif *old_vif,
|
||||
struct rwnx_vif *new_vif);
|
||||
|
||||
#endif /* CONFIG_RWNX_FULLMAC */
|
||||
|
||||
int rwnx_txq_queue_skb(struct sk_buff *skb, struct rwnx_txq *txq,
|
||||
struct rwnx_hw *rwnx_hw, bool retry);
|
||||
void rwnx_txq_confirm_any(struct rwnx_hw *rwnx_hw, struct rwnx_txq *txq,
|
||||
struct rwnx_hwq *hwq, struct rwnx_sw_txhdr *sw_txhdr);
|
||||
|
||||
|
||||
void rwnx_hwq_init(struct rwnx_hw *rwnx_hw);
|
||||
void rwnx_hwq_process(struct rwnx_hw *rwnx_hw, struct rwnx_hwq *hwq);
|
||||
void rwnx_hwq_process_all(struct rwnx_hw *rwnx_hw);
|
||||
|
||||
#endif /* _RWNX_TXQ_H_ */
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* rwnx_utils.c
|
||||
*
|
||||
* IPC utility function definitions
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*/
|
||||
#include "rwnx_utils.h"
|
||||
#include "rwnx_defs.h"
|
||||
#include "rwnx_rx.h"
|
||||
#include "rwnx_tx.h"
|
||||
#include "rwnx_msg_rx.h"
|
||||
#include "rwnx_debugfs.h"
|
||||
#include "rwnx_prof.h"
|
||||
#include "ipc_host.h"
|
||||
|
||||
|
||||
extern int get_testmode(void);
|
||||
extern void get_fw_path(char* fw_path);
|
||||
extern int testmode;
|
||||
extern char aic_fw_path[200];
|
||||
|
||||
int rwnx_init_aic(struct rwnx_hw *rwnx_hw)
|
||||
{
|
||||
RWNX_DBG(RWNX_FN_ENTRY_STR);
|
||||
#ifdef AICWF_SDIO_SUPPORT
|
||||
aicwf_sdio_host_init(&(rwnx_hw->sdio_env), NULL, NULL, rwnx_hw);
|
||||
#else
|
||||
aicwf_usb_host_init(&(rwnx_hw->usb_env), NULL, NULL, rwnx_hw);
|
||||
#endif
|
||||
rwnx_cmd_mgr_init(rwnx_hw->cmd_mgr);
|
||||
|
||||
testmode = get_testmode();
|
||||
memset(aic_fw_path, 0, 200);
|
||||
get_fw_path(aic_fw_path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* rwnx_ipc_utils.h
|
||||
*
|
||||
* IPC utility function declarations
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*/
|
||||
#ifndef _RWNX_IPC_UTILS_H_
|
||||
#define _RWNX_IPC_UTILS_H_
|
||||
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/dmapool.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
#include "lmac_msg.h"
|
||||
#include "aicwf_debug.h"
|
||||
|
||||
|
||||
#if 0
|
||||
#ifdef CONFIG_RWNX_DBG
|
||||
/* #define RWNX_DBG(format, arg...) pr_warn(format, ## arg) */
|
||||
#define RWNX_DBG printk
|
||||
#else
|
||||
#define RWNX_DBG(a...) do {} while (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
enum rwnx_dev_flag {
|
||||
RWNX_DEV_RESTARTING,
|
||||
RWNX_DEV_STACK_RESTARTING,
|
||||
RWNX_DEV_STARTED,
|
||||
};
|
||||
|
||||
struct rwnx_hw;
|
||||
struct rwnx_sta;
|
||||
|
||||
/**
|
||||
* struct rwnx_ipc_elem - Generic IPC buffer of fixed size
|
||||
*
|
||||
* @addr: Host address of the buffer.
|
||||
* @dma_addr: DMA address of the buffer.
|
||||
*/
|
||||
struct rwnx_ipc_elem {
|
||||
void *addr;
|
||||
dma_addr_t dma_addr;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rwnx_ipc_elem_pool - Generic pool of IPC buffers of fixed size
|
||||
*
|
||||
* @nb: Number of buffers currenlty allocated in the pool
|
||||
* @buf: Array of buffers (size of array is @nb)
|
||||
* @pool: DMA pool in which buffers have been allocated
|
||||
*/
|
||||
struct rwnx_ipc_elem_pool {
|
||||
int nb;
|
||||
struct rwnx_ipc_elem *buf;
|
||||
struct dma_pool *pool;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rwnx_ipc_elem - Generic IPC buffer of variable size
|
||||
*
|
||||
* @addr: Host address of the buffer.
|
||||
* @dma_addr: DMA address of the buffer.
|
||||
* @size: Size, in bytes, of the buffer
|
||||
*/
|
||||
struct rwnx_ipc_elem_var {
|
||||
void *addr;
|
||||
dma_addr_t dma_addr;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rwnx_ipc_dbgdump_elem - IPC buffer for debug dump
|
||||
*
|
||||
* @mutex: Mutex to protect access to debug dump
|
||||
* @buf: IPC buffer
|
||||
*/
|
||||
struct rwnx_ipc_dbgdump_elem {
|
||||
struct mutex mutex;
|
||||
struct rwnx_ipc_elem_var buf;
|
||||
};
|
||||
|
||||
static const u32 rwnx_rxbuff_pattern = 0xCAFEFADE;
|
||||
|
||||
/*
|
||||
* Maximum Length of Radiotap header vendor specific data(in bytes)
|
||||
*/
|
||||
#define RADIOTAP_HDR_VEND_MAX_LEN 16
|
||||
|
||||
/*
|
||||
* Maximum Radiotap Header Length without vendor specific data (in bytes)
|
||||
*/
|
||||
#define RADIOTAP_HDR_MAX_LEN 80
|
||||
|
||||
/*
|
||||
* Unsupported HT Frame data length (in bytes)
|
||||
*/
|
||||
#define UNSUP_RX_VEC_DATA_LEN 2
|
||||
|
||||
/**
|
||||
* struct rwnx_ipc_skb_elem - IPC buffer for SKB element
|
||||
*
|
||||
* @skb: Pointer to the skb buffer allocated
|
||||
* @dma_addr: DMA address of the data buffer fo skb
|
||||
*
|
||||
*/
|
||||
struct rwnx_ipc_skb_elem {
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t dma_addr;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_RWNX_FULLMAC
|
||||
|
||||
/* Maximum number of rx buffer the fw may use at the same time */
|
||||
#define RWNX_RXBUFF_MAX (64 * NX_REMOTE_STA_MAX)
|
||||
|
||||
/**
|
||||
* struct rwnx_ipc_rxbuf_elems - IPC buffers for RX
|
||||
*
|
||||
* @skb: Array of buffer push to FW.
|
||||
* @idx: Index of the last pushed skb.(Use to find the next free entry quicker)
|
||||
*
|
||||
* Note: contrary to softmac version, dma_addr are stored inside skb->cb.
|
||||
* (cf &struct rwnx_skb_cb)
|
||||
*/
|
||||
struct rwnx_ipc_rxbuf_elems {
|
||||
struct sk_buff *skb[RWNX_RXBUFF_MAX];
|
||||
int idx;
|
||||
};
|
||||
|
||||
#endif /* CONFIG_RWNX_FULLMAC */
|
||||
#endif /* _RWNX_IPC_UTILS_H_ */
|
||||
@@ -0,0 +1,192 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_v7.c - Support for v7 platform
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "rwnx_v7.h"
|
||||
#include "rwnx_defs.h"
|
||||
#include "rwnx_irqs.h"
|
||||
#include "reg_access.h"
|
||||
#include "hal_desc.h"
|
||||
|
||||
struct rwnx_v7
|
||||
{
|
||||
u8 *pci_bar0_vaddr;
|
||||
u8 *pci_bar1_vaddr;
|
||||
};
|
||||
|
||||
static int rwnx_v7_platform_enable(struct rwnx_hw *rwnx_hw)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* sched_setscheduler on ONESHOT threaded irq handler for BCNs ? */
|
||||
ret = request_irq(rwnx_hw->plat->pci_dev->irq, rwnx_irq_hdlr, 0,
|
||||
"rwnx", rwnx_hw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rwnx_v7_platform_disable(struct rwnx_hw *rwnx_hw)
|
||||
{
|
||||
free_irq(rwnx_hw->plat->pci_dev->irq, rwnx_hw);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rwnx_v7_platform_deinit(struct rwnx_plat *rwnx_plat)
|
||||
{
|
||||
#ifdef CONFIG_PCI
|
||||
struct rwnx_v7 *rwnx_v7 = (struct rwnx_v7 *)rwnx_plat->priv;
|
||||
|
||||
pci_disable_device(rwnx_plat->pci_dev);
|
||||
iounmap(rwnx_v7->pci_bar0_vaddr);
|
||||
iounmap(rwnx_v7->pci_bar1_vaddr);
|
||||
pci_release_regions(rwnx_plat->pci_dev);
|
||||
pci_clear_master(rwnx_plat->pci_dev);
|
||||
pci_disable_msi(rwnx_plat->pci_dev);
|
||||
#endif
|
||||
kfree(rwnx_plat);
|
||||
}
|
||||
|
||||
static u8* rwnx_v7_get_address(struct rwnx_plat *rwnx_plat, int addr_name,
|
||||
unsigned int offset)
|
||||
{
|
||||
struct rwnx_v7 *rwnx_v7 = (struct rwnx_v7 *)rwnx_plat->priv;
|
||||
|
||||
if (WARN(addr_name >= RWNX_ADDR_MAX, "Invalid address %d", addr_name))
|
||||
return NULL;
|
||||
|
||||
if (addr_name == RWNX_ADDR_CPU)
|
||||
return rwnx_v7->pci_bar0_vaddr + offset;
|
||||
else
|
||||
return rwnx_v7->pci_bar1_vaddr + offset;
|
||||
}
|
||||
|
||||
static void rwnx_v7_ack_irq(struct rwnx_plat *rwnx_plat)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static const u32 rwnx_v7_config_reg[] = {
|
||||
NXMAC_DEBUG_PORT_SEL_ADDR,
|
||||
SYSCTRL_DIAG_CONF_ADDR,
|
||||
SYSCTRL_PHYDIAG_CONF_ADDR,
|
||||
SYSCTRL_RIUDIAG_CONF_ADDR,
|
||||
RF_V7_DIAGPORT_CONF1_ADDR,
|
||||
};
|
||||
|
||||
static const u32 rwnx_v7_he_config_reg[] = {
|
||||
SYSCTRL_DIAG_CONF0,
|
||||
SYSCTRL_DIAG_CONF1,
|
||||
SYSCTRL_DIAG_CONF2,
|
||||
SYSCTRL_DIAG_CONF3,
|
||||
};
|
||||
|
||||
static int rwnx_v7_get_config_reg(struct rwnx_plat *rwnx_plat, const u32 **list)
|
||||
{
|
||||
u32 fpga_sign;
|
||||
|
||||
if (!list)
|
||||
return 0;
|
||||
|
||||
fpga_sign = RWNX_REG_READ(rwnx_plat, RWNX_ADDR_SYSTEM, SYSCTRL_SIGNATURE_ADDR);
|
||||
if (__FPGA_TYPE(fpga_sign) == 0xc0ca) {
|
||||
*list = rwnx_v7_he_config_reg;
|
||||
return ARRAY_SIZE(rwnx_v7_he_config_reg);
|
||||
} else {
|
||||
*list = rwnx_v7_config_reg;
|
||||
return ARRAY_SIZE(rwnx_v7_config_reg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* rwnx_v7_platform_init - Initialize the DINI platform
|
||||
*
|
||||
* @pci_dev PCI device
|
||||
* @rwnx_plat Pointer on struct rwnx_stat * to be populated
|
||||
*
|
||||
* @return 0 on success, < 0 otherwise
|
||||
*
|
||||
* Allocate and initialize a rwnx_plat structure for the dini platform.
|
||||
*/
|
||||
int rwnx_v7_platform_init(struct pci_dev *pci_dev, struct rwnx_plat **rwnx_plat)
|
||||
{
|
||||
struct rwnx_v7 *rwnx_v7;
|
||||
u16 pci_cmd;
|
||||
int ret = 0;
|
||||
|
||||
*rwnx_plat = kzalloc(sizeof(struct rwnx_plat) + sizeof(struct rwnx_v7),
|
||||
GFP_KERNEL);
|
||||
if (!*rwnx_plat)
|
||||
return -ENOMEM;
|
||||
|
||||
rwnx_v7 = (struct rwnx_v7 *)(*rwnx_plat)->priv;
|
||||
|
||||
/* Hotplug fixups */
|
||||
pci_read_config_word(pci_dev, PCI_COMMAND, &pci_cmd);
|
||||
pci_cmd |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
|
||||
pci_write_config_word(pci_dev, PCI_COMMAND, pci_cmd);
|
||||
pci_write_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES >> 2);
|
||||
|
||||
if ((ret = pci_enable_device(pci_dev))) {
|
||||
dev_err(&(pci_dev->dev), "pci_enable_device failed\n");
|
||||
goto out_enable;
|
||||
}
|
||||
|
||||
pci_set_master(pci_dev);
|
||||
|
||||
if ((ret = pci_request_regions(pci_dev, KBUILD_MODNAME))) {
|
||||
dev_err(&(pci_dev->dev), "pci_request_regions failed\n");
|
||||
goto out_request;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
if (pci_enable_msi(pci_dev))
|
||||
{
|
||||
dev_err(&(pci_dev->dev), "pci_enable_msi failed\n");
|
||||
goto out_msi;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(rwnx_v7->pci_bar0_vaddr = (u8 *)pci_ioremap_bar(pci_dev, 0))) {
|
||||
dev_err(&(pci_dev->dev), "pci_ioremap_bar(%d) failed\n", 0);
|
||||
ret = -ENOMEM;
|
||||
goto out_bar0;
|
||||
}
|
||||
if (!(rwnx_v7->pci_bar1_vaddr = (u8 *)pci_ioremap_bar(pci_dev, 1))) {
|
||||
dev_err(&(pci_dev->dev), "pci_ioremap_bar(%d) failed\n", 1);
|
||||
ret = -ENOMEM;
|
||||
goto out_bar1;
|
||||
}
|
||||
|
||||
(*rwnx_plat)->enable = rwnx_v7_platform_enable;
|
||||
(*rwnx_plat)->disable = rwnx_v7_platform_disable;
|
||||
(*rwnx_plat)->deinit = rwnx_v7_platform_deinit;
|
||||
(*rwnx_plat)->get_address = rwnx_v7_get_address;
|
||||
(*rwnx_plat)->ack_irq = rwnx_v7_ack_irq;
|
||||
(*rwnx_plat)->get_config_reg = rwnx_v7_get_config_reg;
|
||||
|
||||
return 0;
|
||||
|
||||
out_bar1:
|
||||
iounmap(rwnx_v7->pci_bar0_vaddr);
|
||||
out_bar0:
|
||||
#ifdef CONFIG_PCI
|
||||
pci_disable_msi(pci_dev);
|
||||
out_msi:
|
||||
#endif
|
||||
pci_release_regions(pci_dev);
|
||||
out_request:
|
||||
#ifdef CONFIG_PCI
|
||||
pci_clear_master(pci_dev);
|
||||
#endif
|
||||
pci_disable_device(pci_dev);
|
||||
out_enable:
|
||||
kfree(*rwnx_plat);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file rwnx_v7.h
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2012-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _RWNX_V7_H_
|
||||
#define _RWNX_V7_H_
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include "rwnx_platform.h"
|
||||
|
||||
int rwnx_v7_platform_init(struct pci_dev *pci_dev,
|
||||
struct rwnx_plat **rwnx_plat);
|
||||
|
||||
#endif /* _RWNX_V7_H_ */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user