From 78e5dbb5676a14da3bcdb74db9db6c94c442508c Mon Sep 17 00:00:00 2001 From: "Jude.Lee" Date: Fri, 27 Nov 2015 18:12:51 +0900 Subject: [PATCH] Update the version 11.0 of wilc3000 kernel driver Signed-off-by: Jude.Lee --- wilc3000/Makefile | 1 - wilc3000/at_pwr_dev.h | 9 +- wilc3000/at_pwr_dev_main.c | 145 +- wilc3000/core_configurator.c | 801 -------- wilc3000/host_interface.c | 17 +- wilc3000/linux_mon.c | 83 +- wilc3000/linux_wlan.c | 113 +- wilc3000/linux_wlan_common.h | 2 + wilc3000/linux_wlan_sdio.c | 0 wilc3000/linux_wlan_sdio.h | 79 +- wilc3000/linux_wlan_spi.c | 19 +- wilc3000/wilc_host_ap.c | 3042 ---------------------------- wilc3000/wilc_host_ap.h | 287 --- wilc3000/wilc_sdio.c | 5 - wilc3000/wilc_spi.c | 4 - wilc3000/wilc_wfi_cfg_operations.c | 61 +- wilc3000/wilc_wfi_cfg_operations.h | 4 - wilc3000/wilc_wlan.c | 103 +- wilc3000/wilc_wlan.h | 6 - wilc3000/wilc_wlan_cfg.c | 32 - wilc3000/wilc_wlan_if.h | 7 - 21 files changed, 282 insertions(+), 4538 deletions(-) mode change 100755 => 100644 wilc3000/at_pwr_dev.h mode change 100755 => 100644 wilc3000/at_pwr_dev_main.c mode change 100755 => 100644 wilc3000/linux_wlan.c mode change 100755 => 100644 wilc3000/linux_wlan_common.h mode change 100755 => 100644 wilc3000/linux_wlan_sdio.c delete mode 100644 wilc3000/wilc_host_ap.c delete mode 100644 wilc3000/wilc_host_ap.h mode change 100755 => 100644 wilc3000/wilc_sdio.c diff --git a/wilc3000/Makefile b/wilc3000/Makefile index 835992e..5314137 100755 --- a/wilc3000/Makefile +++ b/wilc3000/Makefile @@ -11,7 +11,6 @@ ccflags-y += -Wno-unused-function ccflags-y += -DWILC_BT_COEXISTENCE -DDOWNLOAD_BT_FW wilc3000-y += atl_msg_queue.o -wilc3000-y += wilc_host_ap.o wilc3000-y += wilc_wfi_cfg_operations.o wilc3000-y += wilc_wlan.o wilc3000-y += wilc_wlan_cfg.o diff --git a/wilc3000/at_pwr_dev.h b/wilc3000/at_pwr_dev.h old mode 100755 new mode 100644 index f2274e1..6617fba --- a/wilc3000/at_pwr_dev.h +++ b/wilc3000/at_pwr_dev.h @@ -59,12 +59,6 @@ enum BUS_RELEASE { RELEASE_ALLOW_SLEEP = 1, }; -enum CHIP_PS_STATE { - CHIP_WAKEDUP = 0, - CHIP_SLEEPING_AUTO = 1, - CHIP_SLEEPING_MANUAL = 2 -}; - struct wilc_wlan_os_context { void *os_private; void *hif_critical_section; @@ -138,8 +132,7 @@ typedef int (*WILCpfChangeCoexMode)(u8); extern struct wilc_hif_func hif_sdio; extern struct wilc_hif_func hif_spi; -extern enum CHIP_PS_STATE genuChipPSstate; -extern unsigned int int_clrd; + #ifdef WILC_SDIO extern struct semaphore sdio_probe_sync; diff --git a/wilc3000/at_pwr_dev_main.c b/wilc3000/at_pwr_dev_main.c old mode 100755 new mode 100644 index 2c27f41..3a9441f --- a/wilc3000/at_pwr_dev_main.c +++ b/wilc3000/at_pwr_dev_main.c @@ -39,14 +39,9 @@ #else #include "linux_wlan_spi.h" #endif /* WILC_SDIO */ -#ifdef WILC_FULLY_HOSTING_AP -#include "wilc_host_ap.h" -#endif /* WILC_FULLY_HOSTING_AP */ #define DOWNLOAD_BT_FW_ONCE -unsigned int int_clrd; - struct pwr_dev_t { struct mutex cs; uint8_t bus_registered[PWR_DEV_SRC_MAX]; @@ -121,11 +116,6 @@ static const struct file_operations pugs_fops = { .write = pwr_dev_write }; -enum CHIP_PS_STATE genuChipPSstate = CHIP_WAKEDUP; -EXPORT_SYMBOL(genuChipPSstate); - -enum CHIP_PS_STATE genuChipPSstateFromWifi; - int at_pwr_dev_init(void) { int ret = 0; @@ -165,6 +155,9 @@ int at_pwr_dev_init(void) mutex_init(&pwr_dev.cs); mutex_init(&pwr_dev.hif_cs); + + /*initialize Chip_En and ResetN */ + linux_wlan_device_power(0); return ret; } @@ -401,8 +394,14 @@ static int cmd_handle_bt_power_up(int source) unsigned int reg; PRINT_D(PWRDEV_DBG, "AT PWR: bt_power_up\n"); - at_pwr_power_up(PWR_DEV_SRC_BT); - at_pwr_register_bus(PWR_DEV_SRC_BT); + ret = at_pwr_power_up(PWR_DEV_SRC_BT); + if(ret != 0){ + goto _fail_1; + } + ret = at_pwr_register_bus(PWR_DEV_SRC_BT); + if(ret != 0){ + goto _fail_2; + } /*TicketId883*/ /*Set BT bit in global mode reg*/ @@ -414,14 +413,14 @@ static int cmd_handle_bt_power_up(int source) if (!ret) { PRINT_ER("[wilc start]: fail read reg %x ...\n", rGLOBAL_MODE_CONTROL); release_bus(RELEASE_ALLOW_SLEEP, PWR_DEV_SRC_BT); - return ret; + goto _fail_3; } reg |= BIT1; ret = pwr_dev.hif_func.hif_write_reg(rGLOBAL_MODE_CONTROL, reg); if (!ret) { PRINT_ER("[wilc start]: fail write reg %x ...\n", rGLOBAL_MODE_CONTROL); release_bus(RELEASE_ALLOW_SLEEP, PWR_DEV_SRC_BT); - return ret; + goto _fail_3; } release_bus(RELEASE_ALLOW_SLEEP, PWR_DEV_SRC_BT); @@ -439,7 +438,7 @@ static int cmd_handle_bt_power_up(int source) if (!ret) { PRINT_ER("[wilc start]: fail read reg %x ...\n", rCOEXIST_CTL); release_bus(RELEASE_ALLOW_SLEEP, PWR_DEV_SRC_BT); - return ret; + goto _fail_3; } /*Force BT*/ reg |= BIT0 | BIT9; @@ -448,7 +447,7 @@ static int cmd_handle_bt_power_up(int source) if (!ret) { PRINT_ER( "[wilc start]: fail write reg %x ...\n", rCOEXIST_CTL); release_bus(RELEASE_ALLOW_SLEEP, PWR_DEV_SRC_BT); - return ret; + goto _fail_3; } /*TicketId1115*/ @@ -457,14 +456,14 @@ static int cmd_handle_bt_power_up(int source) if (!ret) { PRINT_ER("[wilc start]: fail read reg %x ...\n", rCOE_AUTO_PS_ON_NULL_PKT); release_bus(RELEASE_ALLOW_SLEEP, PWR_DEV_SRC_BT); - return ret; + goto _fail_3; } reg &= ~BIT30; ret = pwr_dev.hif_func.hif_write_reg(rCOE_AUTO_PS_ON_NULL_PKT, reg); if (!ret) { PRINT_ER( "[wilc start]: fail write reg %x ...\n", rCOE_AUTO_PS_ON_NULL_PKT); release_bus(RELEASE_ALLOW_SLEEP, PWR_DEV_SRC_BT); - return ret; + goto _fail_3; } /*TicketId1115*/ @@ -473,14 +472,14 @@ static int cmd_handle_bt_power_up(int source) if (!ret) { PRINT_ER("[wilc start]: fail read reg %x ...\n", rCOE_AUTO_PS_OFF_NULL_PKT); release_bus(RELEASE_ALLOW_SLEEP, PWR_DEV_SRC_BT); - return ret; + goto _fail_3; } reg &= ~BIT30; ret = pwr_dev.hif_func.hif_write_reg(rCOE_AUTO_PS_OFF_NULL_PKT, reg); if (!ret) { PRINT_ER( "[wilc start]: fail write reg %x ...\n", rCOE_AUTO_PS_OFF_NULL_PKT); release_bus(RELEASE_ALLOW_SLEEP, PWR_DEV_SRC_BT); - return ret; + goto _fail_3; } release_bus(RELEASE_ALLOW_SLEEP, PWR_DEV_SRC_BT); @@ -497,8 +496,34 @@ static int cmd_handle_bt_power_up(int source) } #endif /*WILC_BT_COEXISTENCE*/ } - + + // Enable BT wakeup + acquire_bus(ACQUIRE_AND_WAKEUP, PWR_DEV_SRC_BT); + + ret = pwr_dev.hif_func.hif_read_reg(rPWR_SEQ_MISC_CTRL, ®); + if (!ret) { + PRINT_ER( "[wilc start]: fail read reg %x ...\n", rPWR_SEQ_MISC_CTRL); + release_bus(RELEASE_ALLOW_SLEEP, PWR_DEV_SRC_BT); + return ret; + } + reg |= BIT29; + ret = pwr_dev.hif_func.hif_write_reg(rPWR_SEQ_MISC_CTRL, reg); + if (!ret) { + PRINT_ER( "[wilc start]: fail write reg %x ...\n", rPWR_SEQ_MISC_CTRL); + release_bus(RELEASE_ALLOW_SLEEP, PWR_DEV_SRC_BT); + return ret; + } + + release_bus(RELEASE_ALLOW_SLEEP, PWR_DEV_SRC_BT); + return 0; + +_fail_3: + at_pwr_unregister_bus(PWR_DEV_SRC_BT); +_fail_2: + at_pwr_power_down(PWR_DEV_SRC_BT); +_fail_1: + return ret; } @@ -516,7 +541,7 @@ static int cmd_handle_bt_power_down(int source) /* Adjust coexistence module. This should be done from the FW in the future*/ if (pwr_dev.bus_registered[PWR_DEV_SRC_BT] == true) { - acquire_bus(ACQUIRE_AND_WAKEUP, PWR_DEV_SRC_WIFI); + acquire_bus(ACQUIRE_AND_WAKEUP, PWR_DEV_SRC_BT); ret = pwr_dev.hif_func.hif_read_reg(rGLOBAL_MODE_CONTROL, ®); if (!ret) { @@ -593,14 +618,14 @@ static int cmd_handle_bt_power_down(int source) // Disable BT wakeup ret = pwr_dev.hif_func.hif_read_reg(rPWR_SEQ_MISC_CTRL, ®); if (!ret) { - PRINT_ER( "[wilc start]: fail write reg %x ...\n", rCOEXIST_CTL); + PRINT_ER( "[wilc start]: fail read reg %x ...\n", rPWR_SEQ_MISC_CTRL); release_bus(RELEASE_ALLOW_SLEEP, PWR_DEV_SRC_BT); return ret; } reg &= ~ BIT29; ret = pwr_dev.hif_func.hif_write_reg(rPWR_SEQ_MISC_CTRL, reg); if (!ret) { - PRINT_ER( "[wilc start]: fail write reg %x ...\n", rCOEXIST_CTL); + PRINT_ER( "[wilc start]: fail write reg %x ...\n", rPWR_SEQ_MISC_CTRL); release_bus(RELEASE_ALLOW_SLEEP, PWR_DEV_SRC_BT); return ret; } @@ -710,8 +735,6 @@ void chip_allow_sleep(int source) pwr_dev.hif_func.hif_write_reg(0x1, reg & ~(1 << 1)); #endif /* WILC_SDIO */ } - if (source == PWR_DEV_SRC_WIFI) - genuChipPSstate = CHIP_SLEEPING_AUTO; pwr_dev.keep_awake[source] = false; } @@ -734,6 +757,11 @@ void chip_wakeup(int source) int wake_seq_trials = 5; + if(pwr_dev.bus_registered[source] != true){ + PRINT_ER("Wakeup request for source that didn't register bus!"); + return -1; + } + pwr_dev.hif_func.hif_read_reg(u32WakeupReg, &wakeup_reg_val); do { pwr_dev.hif_func.hif_write_reg(u32WakeupReg, wakeup_reg_val | u32WakepBit); @@ -772,7 +800,6 @@ void chip_wakeup(int source) } while (((clk_status_reg_val & u32ClkStsBit) == 0) && (wake_seq_trials-- > 0)); - genuChipPSstate = CHIP_WAKEDUP; pwr_dev.keep_awake[source] = true; } @@ -781,10 +808,9 @@ void acquire_bus(enum BUS_ACQUIRE acquire, int source) { mutex_lock(&pwr_dev.hif_cs); - if (genuChipPSstate != CHIP_WAKEDUP) { - if (acquire == ACQUIRE_AND_WAKEUP) - chip_wakeup(source); - } + if (acquire == ACQUIRE_AND_WAKEUP) + chip_wakeup(source); + } EXPORT_SYMBOL(acquire_bus); @@ -798,10 +824,43 @@ void release_bus(enum BUS_RELEASE release, int source) } EXPORT_SYMBOL(release_bus); - #define _linux_wlan_device_detection() {} - #define _linux_wlan_device_removal() {} - #define _linux_wlan_device_power_on() {} - #define _linux_wlan_device_power_off() {} +#if defined(PLAT_SAMA5D4) +#define _linux_wlan_device_detection() {} +#define _linux_wlan_device_removal() {} +#define _linux_wlan_device_power_on() wifi_pm_power(1) +#define _linux_wlan_device_power_off() wifi_pm_power(0) +#else +#define _linux_wlan_device_detection() {} +#define _linux_wlan_device_removal() {} +#define _linux_wlan_device_power_on() {} +#define _linux_wlan_device_power_off() {} +#endif + +#if defined(PLAT_SAMA5D4) +void wifi_pm_power(int power) +{ + + PRINT_D(INIT_DBG, "wifi_pm : %d \n", power); + if (gpio_request(GPIO_NUM_CHIP_EN, "CHIP_EN") == 0 && gpio_request(GPIO_NUM_RESET, "RESET") == 0) + { + gpio_direction_output(GPIO_NUM_CHIP_EN, 0); + gpio_direction_output(GPIO_NUM_RESET, 0); + if (power) + { + gpio_set_value(GPIO_NUM_CHIP_EN , 1); + mdelay(5); + gpio_set_value(GPIO_NUM_RESET , 1); + } + else + { + gpio_set_value(GPIO_NUM_RESET , 0); + gpio_set_value(GPIO_NUM_CHIP_EN , 0); + } + gpio_free(GPIO_NUM_CHIP_EN); + gpio_free(GPIO_NUM_RESET); + } +} +#endif static int linux_wlan_device_power(int on_off) { @@ -824,12 +883,9 @@ static int linux_wlan_device_detection(int on_off) PRINT_D(INIT_DBG,"linux_wlan_device_detection.. (%d)\n", on_off); #ifdef WILC_SDIO - if ( on_off ) - { + if ( on_off ) { _linux_wlan_device_detection(); - } - else - { + } else { _linux_wlan_device_removal(); } #endif @@ -854,7 +910,7 @@ int at_pwr_power_up(int source) PRINT_WRN(PWRDEV_DBG, "Device already up. request source is %s\n", (source == PWR_DEV_SRC_WIFI ? "Wifi" : "BT")); } else { - printk("POWER UP\n"); + PRINT_D(PWRDEV_DBG, "WILC POWER UP\n"); linux_wlan_device_power(0); linux_wlan_device_power(1); msleep(100); @@ -865,6 +921,7 @@ int at_pwr_power_up(int source) return 0; } + EXPORT_SYMBOL(at_pwr_power_up); static int wilc_bt_firmware_download(void) @@ -900,7 +957,7 @@ static int wilc_bt_firmware_download(void) ret = -1; goto _fail_1; } - acquire_bus(ACQUIRE_AND_WAKEUP, PWR_DEV_SRC_WIFI); + acquire_bus(ACQUIRE_AND_WAKEUP, PWR_DEV_SRC_BT); ret = pwr_dev.hif_func.hif_write_reg(0x4f0000, 0x71); if (!ret) { @@ -980,7 +1037,7 @@ static int wilc_bt_firmware_download(void) /* Copy firmware into a DMA coherent buffer */ memcpy(dma_buffer, &buffer[offset], size2); - acquire_bus(ACQUIRE_AND_WAKEUP, PWR_DEV_SRC_WIFI); + acquire_bus(ACQUIRE_AND_WAKEUP, PWR_DEV_SRC_BT); ret = pwr_dev.hif_func.hif_block_tx(addr, dma_buffer, size2); @@ -1021,7 +1078,7 @@ static int wilc_bt_start(void) uint32_t val32 = 0; int ret = 0; - acquire_bus(ACQUIRE_AND_WAKEUP, PWR_DEV_SRC_WIFI); + acquire_bus(ACQUIRE_AND_WAKEUP, PWR_DEV_SRC_BT); PRINT_D(PWRDEV_DBG, "Starting BT firmware\n"); diff --git a/wilc3000/core_configurator.c b/wilc3000/core_configurator.c index ddf868e..e37c0be 100644 --- a/wilc3000/core_configurator.c +++ b/wilc3000/core_configurator.c @@ -40,15 +40,6 @@ enum tenuBasicFrmType { FRAME_TYPE_FORCE_32BIT = 0xFFFFFFFF }; - -/* Basic Frame Classes */ -enum tenuFrameClass { - CLASS1_FRAME_TYPE = 0x00, - CLASS2_FRAME_TYPE = 0x01, - CLASS3_FRAME_TYPE = 0x02, - FRAME_CLASS_FORCE_32BIT = 0xFFFFFFFF -}; - /* Element ID of various Information Elements */ enum tenuInfoElemID { ISSID = 0, /* Service Set Identifier */ @@ -105,10 +96,6 @@ static struct semaphore SemHandleSendPkt; static struct semaphore SemHandlePktResp; static s8 *gps8ConfigPacket; static struct tstrConfigPktInfo gstrConfigPktInfo; -static u8 g_seqno; -static s16 g_wid_num = -1; -static u16 Res_Len; -static u8 g_oper_mode = SET_CFG; /* WID Switches */ static struct tstrWID gastrWIDs[] = { @@ -238,166 +225,6 @@ static struct tstrWID gastrWIDs[] = { u16 g_num_total_switches = (sizeof(gastrWIDs) / sizeof(struct tstrWID)); -static inline u8 ascii_hex_to_dec(u8 num) -{ - if ((num >= '0') && (num <= '9')) - return (num - '0'); - else if ((num >= 'A') && (num <= 'F')) - return (10 + (num - 'A')); - else if ((num >= 'a') && (num <= 'f')) - return (10 + (num - 'a')); - - return INVALID; -} - -static inline u8 get_hex_char(u8 inp) -{ - u8 *d2htab = "0123456789ABCDEF"; - - return d2htab[inp & 0xF]; -} - -/* - * This function extracts the MAC address held in a string in standard format - * into another buffer as integers. - */ -static inline u16 extract_mac_addr(char *str, u8 *buff) -{ - *buff = 0; - while (*str != '\0') { - if ((*str == ':') || (*str == '-')) - *(++buff) = 0; - else - *buff = (*buff << 4) + ascii_hex_to_dec(*str); - - str++; - } - - return MAC_ADDR_LEN; -} - -/* - * This function creates MAC address in standard format from a buffer of - * integers. - */ -static inline void create_mac_addr(u8 *str, u8 *buff) -{ - unsigned int i = 0; - unsigned int j = 0; - - for (i = 0; i < MAC_ADDR_LEN; i++) { - str[j++] = get_hex_char((u8)((buff[i] >> 4) & 0x0F)); - str[j++] = get_hex_char((u8)(buff[i] & 0x0F)); - str[j++] = ':'; - } - str[--j] = '\0'; -} - -/* - * This function converts the IP address string in dotted decimal format to - * unsigned integer. This functionality is similar to the library function - * inet_addr() but is reimplemented here since I could not confirm that - * inet_addr is platform independent. - * ips=>IP Address String in dotted decimal format - * ipn=>Pointer to IP Address in integer format - */ -static inline u8 conv_ip_to_int(u8 *ips, unsigned int *ipn) -{ - u8 i = 0; - u8 ipb = 0; - - *ipn = 0; - /* Integer to string for each component */ - while (ips[i] != '\0') { - if (ips[i] == '.') { - *ipn = ((*ipn) << 8) | ipb; - ipb = 0; - } else { - ipb = ipb * 10 + ascii_hex_to_dec(ips[i]); - } - i++; - } - - /* The last byte of the IP address is read in here */ - *ipn = ((*ipn) << 8) | ipb; - - return 0; -} - -/* - * This function converts the IP address from integer format to dotted - * decimal string format. Alternative to std library fn inet_ntoa(). - * ips=>Buffer to hold IP Address String dotted decimal format (Min 17B) - * ipn=>IP Address in integer format - */ -static inline u8 conv_int_to_ip(u8 *ips, unsigned int ipn) -{ - u8 i = 0; - u8 ipb = 0; - u8 cnt = 0; - u8 ipbsize = 0; - - for (cnt = 4; cnt > 0; cnt--) { - ipb = (ipn >> (8 * (cnt - 1))) & 0xFF; - - if (ipb >= 100) - ipbsize = 2; - else if (ipb >= 10) - ipbsize = 1; - else - ipbsize = 0; - - switch (ipbsize) { - case 2: - ips[i++] = get_hex_char(ipb / 100); - ipb %= 100; - - case 1: - ips[i++] = get_hex_char(ipb / 10); - ipb %= 10; - - default: - ips[i++] = get_hex_char(ipb); - } - - if (cnt > 1) - ips[i++] = '.'; - } - - ips[i] = '\0'; - - return i; -} - -static inline enum WID_TYPE get_wid_type(unsigned int wid_num) -{ - /* Check for iconfig specific WID types first */ - if ((wid_num == WID_BSSID) || - (wid_num == WID_MAC_ADDR) || - (wid_num == WID_IP_ADDRESS) || - (wid_num == WID_HUT_DEST_ADDR)) - return WID_ADR; - - if ((WID_1X_SERV_ADDR == wid_num) || - (WID_STACK_IP_ADDR == wid_num) || - (WID_STACK_NETMASK_ADDR == wid_num)) - return WID_IP; - - /* Next check for standard WID types */ - if (wid_num < 0x1000) - return WID_CHAR; - else if (wid_num < 0x2000) - return WID_SHORT; - else if (wid_num < 0x3000) - return WID_INT; - else if (wid_num < 0x4000) - return WID_STR; - else if (wid_num < 0x5000) - return WID_BIN_DATA; - - return WID_UNDEF; -} - /* * This function extracts the beacon period field from the beacon or probe * response frame. @@ -438,16 +265,6 @@ static inline unsigned int get_beacon_timestamp_hi(u8 *data) return time_stamp; } -/* - * This function extracts the 'frame type' bits from the MAC header of the - * input frame. - * Returns the value in the LSB of the returned value. - */ -static inline enum tenuBasicFrmType get_type(u8 *header) -{ - return ((enum tenuBasicFrmType)(header[0] & 0x0C)); -} - /* * This function extracts the 'frame type and sub type' bits from the MAC * header of the input frame. @@ -969,624 +786,6 @@ signed int DeallocateSurveyResults(struct wid_site_survey_reslts *pstrSurveyResu } #endif /* CONNECT_DIRECT */ -/* - * This function processes a WID of type WID_CHAR and - * updates the cfg packet with the supplied value. - */ -void ProcessCharWid(char *pcPacket, signed int *ps32PktLen, - struct tstrWID *pstrWID, s8 *ps8WidVal) -{ - u8 *pu8val = (u8 *)ps8WidVal; - u8 u8val = 0; - signed int s32PktLen = *ps32PktLen; - - if (NULL == pstrWID) { - PRINT_WRN(CORECONFIG_DBG,"Can't set CHAR val 0x%x ,NULL structure\n",u8val); - return; - } - - /* WID */ - pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid & 0xFF); - pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid >> 8) & 0xFF; - if (g_oper_mode == SET_CFG) { - u8val = *pu8val; - - /* Length */ - pcPacket[s32PktLen++] = sizeof(u8); - - /* Value */ - pcPacket[s32PktLen++] = u8val; - } - *ps32PktLen = s32PktLen; -} - -/* - * This function processes a WID of type WID_SHORT and - * updates the cfg packet with the supplied value. - */ -void ProcessShortWid(char *pcPacket, signed int *ps32PktLen, - struct tstrWID *pstrWID, s8 *ps8WidVal) -{ - u16 *pu16val = (u16 *)ps8WidVal; - u16 u16val = 0; - signed int s32PktLen = *ps32PktLen; - - if (NULL == pstrWID) { - PRINT_WRN(CORECONFIG_DBG,"Can't set SHORT val 0x%x ,NULL structure\n",u16val); - return; - } - - /* WID */ - pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid & 0xFF); - pcPacket[s32PktLen++] = (u8)((pstrWID->u16WIDid >> 8) & 0xFF); - - if (g_oper_mode == SET_CFG) { - u16val = *pu16val; - - /* Length */ - pcPacket[s32PktLen++] = sizeof(u16); - - /* Value */ - pcPacket[s32PktLen++] = (u8)(u16val & 0xFF); - pcPacket[s32PktLen++] = (u8)((u16val >> 8) & 0xFF); - } - *ps32PktLen = s32PktLen; -} - -/* - * This function processes a WID of type WID_INT and - * updates the cfg packet with the supplied value. - */ -void ProcessIntWid(char *pcPacket, signed int *ps32PktLen, - struct tstrWID *pstrWID, s8 *ps8WidVal) -{ - unsigned int *pu32val = (unsigned int *)ps8WidVal; - unsigned int u32val = 0; - signed int s32PktLen = *ps32PktLen; - - if (NULL == pstrWID) { - PRINT_WRN(CORECONFIG_DBG,"Can't set INT val 0x%x , NULL structure\n", u32val); - return; - } - - /* WID */ - pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid & 0xFF); - pcPacket[s32PktLen++] = (u8)((pstrWID->u16WIDid >> 8) & 0xFF); - - if (g_oper_mode == SET_CFG) { - u32val = *pu32val; - - /* Length */ - pcPacket[s32PktLen++] = sizeof(unsigned int); - - /* Value */ - pcPacket[s32PktLen++] = (u8)(u32val & 0xFF); - pcPacket[s32PktLen++] = (u8)((u32val >> 8) & 0xFF); - pcPacket[s32PktLen++] = (u8)((u32val >> 16) & 0xFF); - pcPacket[s32PktLen++] = (u8)((u32val >> 24) & 0xFF); - } - *ps32PktLen = s32PktLen; -} - -/* - * This function processes a WID of type WID_IP and - * updates the cfg packet with the supplied value. - */ -void ProcessIPwid(char *pcPacket, signed int *ps32PktLen, - struct tstrWID *pstrWID, u8 *pu8ip) -{ - unsigned int u32val = 0; - signed int s32PktLen = *ps32PktLen; - - if (NULL == pstrWID) { - PRINT_WRN(CORECONFIG_DBG,"Can't set IP Addr , NULL structure\n"); - return; - } - - /* WID */ - pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid & 0xFF); - pcPacket[s32PktLen++] = (u8)((pstrWID->u16WIDid >> 8) & 0xFF); - - if (g_oper_mode == SET_CFG) { - /* Length */ - pcPacket[s32PktLen++] = sizeof(unsigned int); - - /* Convert the IP Address String to Integer */ - conv_ip_to_int(pu8ip, &u32val); - - /* Value */ - pcPacket[s32PktLen++] = (u8)(u32val & 0xFF); - pcPacket[s32PktLen++] = (u8)((u32val >> 8) & 0xFF); - pcPacket[s32PktLen++] = (u8)((u32val >> 16) & 0xFF); - pcPacket[s32PktLen++] = (u8)((u32val >> 24) & 0xFF); - } - *ps32PktLen = s32PktLen; -} - -/* - * This function processes a WID of type WID_STR and - * updates the cfg packet with the supplied value. - */ -void ProcessStrWid(char *pcPacket, signed int *ps32PktLen, - struct tstrWID *pstrWID, u8 *pu8val, signed int s32ValueSize) -{ - u16 u16MsgLen = 0; - u16 idx = 0; - signed int s32PktLen = *ps32PktLen; - - if (NULL == pstrWID) { - PRINT_WRN(CORECONFIG_DBG,"Can't set STR val, NULL structure\n"); - return; - } - - /* WID */ - pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid & 0xFF); - pcPacket[s32PktLen++] = (u8)((pstrWID->u16WIDid >> 8) & 0xFF); - - if (g_oper_mode == SET_CFG) { - /* Message Length */ - u16MsgLen = (u16)s32ValueSize; - - /* Length */ - pcPacket[s32PktLen++] = (u8)u16MsgLen; - - /* Value */ - for (idx = 0; idx < u16MsgLen; idx++) - pcPacket[s32PktLen++] = pu8val[idx]; - } - *ps32PktLen = s32PktLen; -} - -/* - * This function processes a WID of type WID_ADR and - * updates the cfg packet with the supplied value. - */ -void ProcessAdrWid(char *pcPacket, signed int *ps32PktLen, - struct tstrWID *pstrWID, u8 *pu8val) -{ - u16 u16MsgLen = 0; - signed int s32PktLen = *ps32PktLen; - - if (NULL == pstrWID) { - PRINT_WRN(CORECONFIG_DBG,"Can't set Addr WID, NULL structure\n"); - return; - } - - /* WID */ - pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid & 0xFF); - pcPacket[s32PktLen++] = (u8)((pstrWID->u16WIDid >> 8) & 0xFF); - - if (g_oper_mode == SET_CFG) { - /* Message Length */ - u16MsgLen = MAC_ADDR_LEN; - - /* Length */ - pcPacket[s32PktLen++] = (u8)u16MsgLen; - - /* Value */ - extract_mac_addr(pu8val, pcPacket + s32PktLen); - s32PktLen += u16MsgLen; - } - *ps32PktLen = s32PktLen; -} - -/* - * This function processes a WID of type WID_BIN_DATA and - * updates the cfg packet with the supplied value. - */ -void ProcessBinWid(char *pcPacket, signed int *ps32PktLen, - struct tstrWID *pstrWID, u8 *pu8val, signed int s32ValueSize) -{ - u16 u16MsgLen = 0; - u16 idx = 0; - signed int s32PktLen = *ps32PktLen; - u8 u8checksum = 0; - - if (NULL == pstrWID) { - PRINT_WRN(CORECONFIG_DBG,"Can't set BIN val, NULL structure\n"); - return; - } - - /* WID */ - pcPacket[s32PktLen++] = (u8)(pstrWID->u16WIDid & 0xFF); - pcPacket[s32PktLen++] = (u8)((pstrWID->u16WIDid >> 8) & 0xFF); - - if (g_oper_mode == SET_CFG) { - /* Message Length */ - u16MsgLen = (u16)s32ValueSize; - - /* Length */ - pcPacket[s32PktLen++] = (u8)(u16MsgLen & 0xFF); - pcPacket[s32PktLen++] = (u8)((u16MsgLen >> 8) & 0xFF); - - /* Value */ - for (idx = 0; idx < u16MsgLen; idx++) - pcPacket[s32PktLen++] = pu8val[idx]; - - /* checksum */ - for (idx = 0; idx < u16MsgLen; idx++) - u8checksum += pcPacket[MSG_HEADER_LEN + idx + 4]; - - pcPacket[s32PktLen++] = u8checksum; - } - *ps32PktLen = s32PktLen; -} - -/* This function parses the response frame got from the device */ -signed int further_process_response(u8 *resp, - u16 u16WIDid, - u16 cfg_len, - bool process_wid_num, - unsigned int cnt, - struct tstrWID *pstrWIDresult) -{ - unsigned int retval = 0; - unsigned int idx = 0; - u8 cfg_chr = 0; - u16 cfg_sht = 0; - unsigned int cfg_int = 0; - u8 cfg_str[256] = {0}; - enum WID_TYPE enuWIDtype = WID_UNDEF; - - if (process_wid_num) - enuWIDtype = get_wid_type(g_wid_num); - else - enuWIDtype = gastrWIDs[cnt].enuWIDtype; - - switch (enuWIDtype) { - case WID_CHAR: - { - cfg_chr = resp[idx]; - /*Set local copy of WID*/ - *pstrWIDresult->ps8WidVal = cfg_chr; - break; - } - - case WID_SHORT: - { - u16 *pu16val = (u16 *)(pstrWIDresult->ps8WidVal); - - cfg_sht = MAKE_WORD16(resp[idx], resp[idx + 1]); - *pu16val = cfg_sht; - break; - } - - case WID_INT: - { - unsigned int *pu32val = (unsigned int *)(pstrWIDresult->ps8WidVal); - - cfg_int = MAKE_WORD32( - MAKE_WORD16(resp[idx], resp[idx + 1]), - MAKE_WORD16(resp[idx + 2], resp[idx + 3]) - ); - *pu32val = cfg_int; - break; - } - - case WID_STR: - { - memcpy(cfg_str, resp + idx, cfg_len); - - if (pstrWIDresult->s32ValueSize >= cfg_len) { - memcpy(pstrWIDresult->ps8WidVal, cfg_str, cfg_len); - pstrWIDresult->s32ValueSize = cfg_len; - } else { - PRINT_ER("allocated WID buffer length is smaller than the received WID Length \n"); - retval = -2; - } - - break; - } - - case WID_ADR: - create_mac_addr(cfg_str, resp + idx); - - strncpy(pstrWIDresult->ps8WidVal, cfg_str, strlen(cfg_str)); - pstrWIDresult->ps8WidVal[strlen(cfg_str)] = '\0'; - break; - - case WID_IP: - cfg_int = MAKE_WORD32( - MAKE_WORD16(resp[idx], resp[idx + 1]), - MAKE_WORD16(resp[idx + 2], resp[idx + 3]) - ); - conv_int_to_ip(cfg_str, cfg_int); - break; - - case WID_BIN_DATA: - { - if (pstrWIDresult->s32ValueSize >= cfg_len) { - memcpy(pstrWIDresult->ps8WidVal, resp + idx, cfg_len); - pstrWIDresult->s32ValueSize = cfg_len; - } else { - PRINT_ER("Allocated WID buffer length is smaller than the received WID Length Err(%d)\n",retval); - retval = -2; - } - } - break; - - default: - PRINT_ER("ERROR: Check config database: Error(%d)\n",retval); - retval = -2; - } - - return retval; -} - -/* - * This function parses the command-line options and - * creates the config packets which can be sent to the WLAN station - */ -signed int ParseResponse(u8 *resp, struct tstrWID *pstrWIDcfgResult) -{ - u16 u16RespLen = 0; - u16 u16WIDid = 0; - u16 cfg_len = 0; - enum WID_TYPE enuWIDtype = WID_UNDEF; - bool num_wid_processed = false; - unsigned int cnt = 0; - unsigned int idx = 0; - unsigned int ResCnt = 0; - /* Check whether the received frame is a valid response */ - if (RESP_MSG_TYPE != resp[0]) { - PRINT_INFO(CORECONFIG_DBG,"Received Message format incorrect.\n"); - return -1; - } - - /* Extract Response Length */ - u16RespLen = MAKE_WORD16(resp[2], resp[3]); - Res_Len = u16RespLen; - - for (idx = MSG_HEADER_LEN; idx < u16RespLen; ) { - u16WIDid = MAKE_WORD16(resp[idx], resp[idx + 1]); - cfg_len = resp[idx + 2]; - /* Incase of Bin Type Wid, the length is given by two byte field */ - enuWIDtype = get_wid_type(u16WIDid); - if (WID_BIN_DATA == enuWIDtype) { - cfg_len |= ((u16)resp[idx + 3] << 8) & 0xFF00; - idx++; - } - idx += 3; - if ((u16WIDid == g_wid_num) && (!num_wid_processed)) { - num_wid_processed = true; - - if (-2 == further_process_response(&resp[idx], u16WIDid, cfg_len, true, 0, &pstrWIDcfgResult[ResCnt])) - return -2; - ResCnt++; - } else { - for (cnt = 0; cnt < g_num_total_switches; cnt++) { - if (gastrWIDs[cnt].u16WIDid == u16WIDid) { - if (-2 == further_process_response(&resp[idx], u16WIDid, cfg_len, false, cnt, - &pstrWIDcfgResult[ResCnt])) - return -2; - ResCnt++; - } - } - } idx += cfg_len; - /* In case if BIN type Wid, The last byte of the Cfg packet is the */ - /* Checksum. The WID Length field does not accounts for the checksum. */ - /* The Checksum is discarded. */ - if (WID_BIN_DATA == enuWIDtype) - idx++; - } - - return 0; -} - -/* - * parses the write response [just detects its status: success or failure] - */ - -signed int ParseWriteResponse(u8 *pu8RespBuffer) -{ - signed int s32Error = ATL_FAIL; - u16 u16RespLen = 0; - u16 u16WIDtype = (u16)WID_NIL; - - /* Check whether the received frame is a valid response */ - if (RESP_MSG_TYPE != pu8RespBuffer[0]) { - PRINT_ER("Received Message format incorrect.\n"); - return ATL_FAIL; - } - - /* Extract Response Length */ - u16RespLen = MAKE_WORD16(pu8RespBuffer[2], pu8RespBuffer[3]); - - u16WIDtype = MAKE_WORD16(pu8RespBuffer[4], pu8RespBuffer[5]); - - /* Check for WID_STATUS ID and then check the length and status value */ - if ((u16WIDtype == WID_STATUS) && - (pu8RespBuffer[6] == 1) && - (pu8RespBuffer[7] == WRITE_RESP_SUCCESS)) { - s32Error = WRITE_RESP_SUCCESS; - return s32Error; - } - - /* If the length or status are not as expected return failure */ - s32Error = ATL_FAIL; - return s32Error; -} - -/* - * creates the header of the Configuration Packet - */ - -signed int CreatePacketHeader(char *pcpacket, signed int *ps32PacketLength) -{ - signed int s32Error = ATL_SUCCESS; - u16 u16MsgLen = (u16)(*ps32PacketLength); - u16 u16MsgInd = 0; - - /* The format of the message is: */ - /* +-------------------------------------------------------------------+ */ - /* | Message Type | Message ID | Message Length |Message body | */ - /* +-------------------------------------------------------------------+ */ - /* | 1 Byte | 1 Byte | 2 Bytes | Message Length - 4 | */ - /* +-------------------------------------------------------------------+ */ - - /* The format of a message body of a message type 'W' is: */ - /* +-------------------------------------------------------------------+ */ - /* | WID0 | WID0 Length | WID0 Value | ......................... | */ - /* +-------------------------------------------------------------------+ */ - /* | 2 Bytes | 1 Byte | WID0 Length | ......................... | */ - /* +-------------------------------------------------------------------+ */ - /* Message Type */ - if (g_oper_mode == SET_CFG) - pcpacket[u16MsgInd++] = WRITE_MSG_TYPE; - else - pcpacket[u16MsgInd++] = QUERY_MSG_TYPE; - - /* Sequence Number */ - pcpacket[u16MsgInd++] = g_seqno++; - - /* Message Length */ - pcpacket[u16MsgInd++] = (u8)(u16MsgLen & 0xFF); - pcpacket[u16MsgInd++] = (u8)((u16MsgLen >> 8) & 0xFF); - - *ps32PacketLength = u16MsgLen; - - return s32Error; -} - -/* - * creates Configuration packet based on the Input WIDs - * @pstrWIDs WIDs to be sent in the configuration packet - * @u32WIDsCount number of WIDs to be sent in the configuration packet - * @ps8packet The created Configuration Packet - * @ps32PacketLength Length of the created Configuration Packet - */ - -signed int CreateConfigPacket(s8 *ps8packet, signed int *ps32PacketLength, - struct tstrWID *pstrWIDs, unsigned int u32WIDsCount) -{ - signed int s32Error = ATL_SUCCESS; - unsigned int u32idx = 0; - *ps32PacketLength = MSG_HEADER_LEN; - for (u32idx = 0; u32idx < u32WIDsCount; u32idx++) { - switch (pstrWIDs[u32idx].enuWIDtype) { - case WID_CHAR: - ProcessCharWid(ps8packet, ps32PacketLength, &pstrWIDs[u32idx], - pstrWIDs[u32idx].ps8WidVal); - break; - - case WID_SHORT: - ProcessShortWid(ps8packet, ps32PacketLength, &pstrWIDs[u32idx], - pstrWIDs[u32idx].ps8WidVal); - break; - - case WID_INT: - ProcessIntWid(ps8packet, ps32PacketLength, &pstrWIDs[u32idx], - pstrWIDs[u32idx].ps8WidVal); - break; - - case WID_STR: - ProcessStrWid(ps8packet, ps32PacketLength, &pstrWIDs[u32idx], - pstrWIDs[u32idx].ps8WidVal, pstrWIDs[u32idx].s32ValueSize); - break; - - case WID_IP: - ProcessIPwid(ps8packet, ps32PacketLength, &pstrWIDs[u32idx], - pstrWIDs[u32idx].ps8WidVal); - break; - - case WID_BIN_DATA: - ProcessBinWid(ps8packet, ps32PacketLength, &pstrWIDs[u32idx], - pstrWIDs[u32idx].ps8WidVal, pstrWIDs[u32idx].s32ValueSize); - break; - - default: - PRINT_ER("ERROR: Check Config database\n"); - } - } - - CreatePacketHeader(ps8packet, ps32PacketLength); - - return s32Error; -} - -signed int ConfigWaitResponse(char *pcRespBuffer, signed int s32MaxRespBuffLen, - signed int *ps32BytesRead, bool bRespRequired) -{ - signed int s32Error = ATL_SUCCESS; - - if (gstrConfigPktInfo.bRespRequired) { - down(&SemHandlePktResp); - - *ps32BytesRead = gstrConfigPktInfo.s32BytesRead; - } - - memset((void *)(&gstrConfigPktInfo), 0, sizeof(struct tstrConfigPktInfo)); - - return s32Error; -} - -signed int ConfigProvideResponse(char *pcRespBuffer, signed int s32RespLen) -{ - signed int s32Error = ATL_SUCCESS; - - if (gstrConfigPktInfo.bRespRequired) { - if (s32RespLen <= gstrConfigPktInfo.s32MaxRespBuffLen) { - memcpy(gstrConfigPktInfo.pcRespBuffer, pcRespBuffer, s32RespLen); - gstrConfigPktInfo.s32BytesRead = s32RespLen; - } else { - memcpy(gstrConfigPktInfo.pcRespBuffer, pcRespBuffer, gstrConfigPktInfo.s32MaxRespBuffLen); - gstrConfigPktInfo.s32BytesRead = gstrConfigPktInfo.s32MaxRespBuffLen; - PRINT_ER("BusProvideResponse() Response greater than the prepared Buffer Size \n"); - } - - up(&SemHandlePktResp); - } - - return s32Error; -} - -/* - * writes the received packet pu8RxPacket in the global Rx FIFO buffer - */ - -signed int ConfigPktReceived(u8 *pu8RxPacket, signed int s32RxPacketLen) -{ - signed int s32Error = ATL_SUCCESS; - u8 u8MsgType = 0; - - u8MsgType = pu8RxPacket[0]; - - switch (u8MsgType) { - case 'R': - { - ConfigProvideResponse(pu8RxPacket, s32RxPacketLen); - - break; - } - - case 'N': - { - PRINT_INFO(CORECONFIG_DBG,"NetworkInfo packet received\n"); - NetworkInfoReceived(pu8RxPacket, s32RxPacketLen); - break; - } - - case 'I': - { - GnrlAsyncInfoReceived(pu8RxPacket, s32RxPacketLen); - break; - } - - case 'S': - { - host_int_ScanCompleteReceived(pu8RxPacket, s32RxPacketLen); - break; - } - - default: - { - PRINT_ER("ConfigPktReceived(): invalid received msg type at the Core Configurator \n"); - } - } - - return s32Error; -} - /* * Deinitializes the Core Configurator */ diff --git a/wilc3000/host_interface.c b/wilc3000/host_interface.c index 77ece0b..af8eea5 100644 --- a/wilc3000/host_interface.c +++ b/wilc3000/host_interface.c @@ -553,7 +553,7 @@ static signed int Handle_SendBufferedEAP(void *drvHandler, pstrHostIFSendBufferedEAP->pfFreeEAPBuffParams(pstrHostIFSendBufferedEAP->pvUserArg); /*Free allocated buffer*/ - if (pstrHostIFSendBufferedEAP->pu8Buff == NULL) { + if (pstrHostIFSendBufferedEAP->pu8Buff != NULL) { kfree(pstrHostIFSendBufferedEAP->pu8Buff); pstrHostIFSendBufferedEAP->pu8Buff = NULL; } @@ -4690,6 +4690,8 @@ static int hostIFthread(void *pvArg) PRINT_D(HOSTINF_DBG, "Releasing thread exit semaphore\n"); up(&hSemHostIFthrdEnd); + while (!kthread_should_stop()) + schedule(); return 0; } @@ -4748,7 +4750,15 @@ signed int host_int_send_buffered_eap(struct WFIDrvHandle *hWFIDrv, strHostIFmsg.uniHostIFmsgBody.strHostIFSendBufferedEAP.u32Size = u32Size; strHostIFmsg.uniHostIFmsgBody.strHostIFSendBufferedEAP.u32PktOffset = u32PktOffset; strHostIFmsg.uniHostIFmsgBody.strHostIFSendBufferedEAP.pu8Buff = kmalloc(u32Size + u32PktOffset, GFP_ATOMIC); - memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFSendBufferedEAP.pu8Buff, pu8Buff, u32Size + u32PktOffset); + if(strHostIFmsg.uniHostIFmsgBody.strHostIFSendBufferedEAP.pu8Buff != NULL) + { + memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFSendBufferedEAP.pu8Buff, pu8Buff, u32Size + u32PktOffset); + } + else + { + ATL_ERRORREPORT(s32Error, ATL_NO_MEM); + } + strHostIFmsg.uniHostIFmsgBody.strHostIFSendBufferedEAP.pvUserArg = pvUserArg; /* send the message */ @@ -6562,6 +6572,9 @@ signed int host_int_deinit(struct WFIDrvHandle *hWFIDrv, char* pcIfName, u8 u8If down(&hSemHostIFthrdEnd); + kthread_stop(HostIFthreadHandler); + HostIFthreadHandler = NULL; + ATL_MsgQueueDestroy(&gMsgQHostIF); msgQ_created = 0; } diff --git a/wilc3000/linux_mon.c b/wilc3000/linux_mon.c index 0428bee..a80ff5c 100644 --- a/wilc3000/linux_mon.c +++ b/wilc3000/linux_mon.c @@ -21,9 +21,8 @@ #include "wilc_wlan_if.h" #include "wilc_wlan.h" #include "linux_wlan.h" -#ifdef WILC_FULLY_HOSTING_AP -#include "wilc_host_ap.h" -#endif /* WILC_FULLY_HOSTING_AP */ + + #ifdef WILC_AP_EXTERNAL_MLME struct wilc_wfi_radiotap_hdr { @@ -155,10 +154,10 @@ static void mgmt_tx_complete(void *priv, int status) } /* incase of fully hosting mode, the freeing will be done in response to the cfg packet */ - #ifndef WILC_FULLY_HOSTING_AP + kfree(pv_data->buff); kfree(pv_data); - #endif /* WILC_FULLY_HOSTING_AP */ + } static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len) @@ -179,30 +178,16 @@ static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len) return ATL_FAIL; } - #ifdef WILC_FULLY_HOSTING_AP - /* add space for the pointer to tx_complete_mon_data*/ - len += sizeof(struct tx_complete_mon_data *); - #endif /* WILC_FULLY_HOSTING_AP */ - mgmt_tx->buff = kmalloc(len, GFP_ATOMIC); if (mgmt_tx->buff == NULL) { + kfree(mgmt_tx); return ATL_FAIL; } mgmt_tx->size = len; - #ifndef WILC_FULLY_HOSTING_AP - memcpy(mgmt_tx->buff, buf, len); - #else /* WILC_FULLY_HOSTING_AP */ - memcpy(mgmt_tx->buff, buf, len - sizeof(struct tx_complete_mon_data *)); - memcpy((mgmt_tx->buff) + (len - sizeof(struct tx_complete_mon_data *)), - &mgmt_tx, sizeof(struct tx_complete_mon_data *)); - /* filter data frames to handle it's PS*/ - if (filter_monitor_data_frames((mgmt_tx->buff), len) == true) - return; - - #endif /* WILC_FULLY_HOSTING_AP */ + memcpy(mgmt_tx->buff, buf, len); g_linux_wlan->oup.wlan_add_mgmt_to_tx_que(mgmt_tx, mgmt_tx->buff, mgmt_tx->size, mgmt_tx_complete); @@ -305,62 +290,6 @@ static const struct net_device_ops wilc_wfi_netdev_ops = { .ndo_start_xmit = WILC_WFI_mon_xmit, }; -#ifdef WILC_FULLY_HOSTING_AP -/* - * report the status of transmitted mgmt frames to HOSTAPD - * @priv pointer to tx_complete_mon_data struct - * @bStatus status of transmission - */ -void WILC_mgm_HOSTAPD_ACK(void *priv, bool bStatus) -{ - struct sk_buff *skb; - struct wilc_wfi_radiotap_cb_hdr *cb_hdr; - - struct tx_complete_mon_data *pv_data = (struct tx_complete_mon_data *)priv; - u8 *buf = pv_data->buff; - - /* len of the original frame without the added pointer at the tail*/ - u16 u16len = (pv_data->size) - sizeof(struct tx_complete_mon_data *); - - { - skb = dev_alloc_skb(u16len + sizeof(struct wilc_wfi_radiotap_cb_hdr)); - - memcpy(skb_put(skb, u16len), pv_data->buff, u16len); - - cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *)skb_push(skb, sizeof(*cb_hdr)); - memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr)); - - cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */ - - cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr)); - - cb_hdr->hdr.it_present = cpu_to_le32( - (1 << IEEE80211_RADIOTAP_RATE) | - (1 << IEEE80211_RADIOTAP_TX_FLAGS)); - - cb_hdr->rate = 5; - - if (bStatus) - cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_RTS; - else - cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_FAIL; - - skb->dev = wilc_wfi_mon; - skb_set_mac_header(skb, 0); - skb->ip_summed = CHECKSUM_UNNECESSARY; - skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = htons(ETH_P_802_2); - memset(skb->cb, 0, sizeof(skb->cb)); - - netif_rx(skb); - } - - /* incase of fully hosting mode, the freeing will be done in response to the cfg packet */ - kfree(pv_data->buff); - kfree(pv_data); -} -#endif /* WILC_FULLY_HOSTING_AP */ - static void WILC_WFI_mon_setup(struct net_device *dev) { u8 mac_add[] = {0x00, 0x50, 0xc2, 0x5e, 0x10, 0x8f}; diff --git a/wilc3000/linux_wlan.c b/wilc3000/linux_wlan.c old mode 100755 new mode 100644 index d0f5be1..ec2ef53 --- a/wilc3000/linux_wlan.c +++ b/wilc3000/linux_wlan.c @@ -51,9 +51,6 @@ #else #include "linux_wlan_spi.h" #endif /* WILC_SDIO */ -#ifdef WILC_FULLY_HOSTING_AP -#include "wilc_host_ap.h" -#endif /* WILC_FULLY_HOSTING_AP */ #include "at_pwr_dev.h" #include "linux_wlan.h" @@ -83,9 +80,6 @@ struct android_wifi_priv_cmd { static struct semaphore close_exit_sync; -unsigned int int_rcvdU; -unsigned int int_rcvdB; - static int wlan_deinit_locks(struct linux_wlan *nic); static void wlan_deinitialize_threads(struct linux_wlan *nic); @@ -428,8 +422,7 @@ void linux_wlan_disable_irq(int wait) #if (!defined WILC_SDIO) || (defined WILC_SDIO_IRQ_GPIO) static irqreturn_t isr_uh_routine(int irq, void *user_data) { - int_rcvdU++; - PRINT_D(INT_DBG, "Interrupt received UH\n"); +PRINT_D(INT_DBG, "Interrupt received UH\n"); #if (RX_BH_TYPE != RX_BH_THREADED_IRQ) linux_wlan_disable_irq(IRQ_NO_WAIT); #endif @@ -481,7 +474,6 @@ static void isr_bh_routine(struct work_struct *work) #endif } - int_rcvdB++; PRINT_D(INT_DBG, "Interrupt received BH\n"); if (g_linux_wlan->oup.wlan_handle_rx_isr != 0) g_linux_wlan->oup.wlan_handle_rx_isr(); @@ -510,7 +502,7 @@ static int isr_bh_routine(void *vp) break; } - int_rcvdB++; + PRINT_D(INT_DBG, "Interrupt received BH\n"); if (g_linux_wlan->oup.wlan_handle_rx_isr != 0) g_linux_wlan->oup.wlan_handle_rx_isr(); @@ -534,7 +526,7 @@ static int init_irq(struct linux_wlan *p_nic) if ((gpio_request(GPIO_NUM, "WILC_INTR") == 0) && (gpio_direction_input(GPIO_NUM) == 0)) { gpio_export(GPIO_NUM, 1); - nic->dev_irq_num = gpio_to_irq(GPIO_NUM); + nic->dev_irq_num = OMAP_GPIO_IRQ(GPIO_NUM); irq_set_irq_type(nic->dev_irq_num, IRQ_TYPE_LEVEL_LOW); } else { ret = -1; @@ -1054,13 +1046,6 @@ static int linux_wlan_init_test_config(struct net_device *dev, struct linux_wlan 1, 0, 0)) goto _fail_; -#ifdef SWITCH_LOG_TERMINAL - c_val[0] = AUTO_PROT; - if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_LOGTerminal_Switch, c_val, - 1, 0, 0)) - goto _fail_; -#endif /* SWITCH_LOG_TERMINAL */ - c_val[0] = ACTIVE_SCAN; if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_SCAN_TYPE, c_val, 1, 0, 0)) goto _fail_; @@ -1284,6 +1269,8 @@ static int linux_wlan_init_test_config(struct net_device *dev, struct linux_wlan void wilc_wlan_deinit(struct linux_wlan *nic) { + int ret = 0; + if (g_linux_wlan->wilc_initialized) { PRINT_D(INIT_DBG, "Deinitializing wilc ...\n"); @@ -1319,7 +1306,13 @@ void wilc_wlan_deinit(struct linux_wlan *nic) if (&g_linux_wlan->oup != NULL) if (g_linux_wlan->oup.wlan_stop != NULL) - g_linux_wlan->oup.wlan_stop(); + { + ret = g_linux_wlan->oup.wlan_stop(); + if(ret == 0) + { + PRINT_ER("failed in wlan_stop\n"); + } + } PRINT_D(INIT_DBG, "Deinitializing WILC Wlan\n"); at_wlan_deinit(nic); @@ -1408,13 +1401,9 @@ void linux_to_wlan(struct wilc_wlan_inp *nwi, struct linux_wlan *nic) nwi->io_func.io_type = HIF_SPI; #endif - /*for now - to be revised*/ - #ifdef WILC_FULLY_HOSTING_AP - /* incase of Fully hosted AP, all non cfg pkts are processed here*/ - nwi->net_func.rx_indicate = WILC_Process_rx_frame; - #else + nwi->net_func.rx_indicate = frmw_to_linux; - #endif /* WILC_FULLY_HOSTING_AP */ + nwi->net_func.rx_complete = linux_wlan_rx_complete; nwi->indicate_func.mac_indicate = linux_wlan_mac_indicate; } @@ -1743,8 +1732,10 @@ int mac_open(struct net_device *ndev) struct perInterface_wlan *nic; u8 mac_add[ETH_ALEN] = {0}; + #ifndef HW_HAS_EFUSED_MAC_ADDR unsigned char mac_address[NUM_CONCURRENT_IFC][ETH_ALEN] = {{0x00, 0x80, 0xC2, 0x5E, 0xa2, 0x01} /*IFC_0 mac address*/ , {0x00, 0x80, 0xC2, 0x5E, 0xa2, 0x02}}; /*IFC_1 mac address*/ + #endif int ifc; int ret = 0; int i = 0; @@ -1793,13 +1784,15 @@ int mac_open(struct net_device *ndev) goto _err_; } host_int_set_wfi_drv_handler((unsigned int)priv->hWILCWFIDrv, nic->iftype, ndev->name); + #ifndef HW_HAS_EFUSED_MAC_ADDR + PRINT_D(INIT_DBG, "HW doesn't have Efused mac address, set mac address from host\n"); host_int_set_MacAddress(priv->hWILCWFIDrv, mac_address[ifc]); + #endif host_int_get_MacAddress(priv->hWILCWFIDrv, mac_add); PRINT_D(INIT_DBG, "Mac address: %x:%x:%x:%x:%x:%x\n", mac_add[0], mac_add[1], mac_add[2], mac_add[3], mac_add[4], mac_add[5]); - - /*loop through the NUM of supported devices and set the MAC address*/ - memcpy(g_linux_wlan->strInterfaceInfo[ifc].aSrcAddress, mac_address[ifc], ETH_ALEN); + + memcpy(g_linux_wlan->strInterfaceInfo[ifc].aSrcAddress, mac_add, ETH_ALEN); g_linux_wlan->strInterfaceInfo[ifc].drvHandler = (unsigned int)priv->hWILCWFIDrv; /* TODO: get MAC address whenever the source is EPROM - hardcoded and copy it to ndev*/ @@ -1811,7 +1804,7 @@ int mac_open(struct net_device *ndev) ret = -EINVAL; goto _err_; } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) + WILC_WFI_frame_register(nic->wilc_netdev->ieee80211_ptr->wiphy, nic->wilc_netdev, nic->g_struct_frame_reg[0].frame_type, @@ -1820,7 +1813,6 @@ int mac_open(struct net_device *ndev) nic->wilc_netdev, nic->g_struct_frame_reg[1].frame_type, nic->g_struct_frame_reg[1].reg); -#endif netif_wake_queue(ndev); g_linux_wlan->open_ifcs++; nic->mac_opened = 1; @@ -1970,8 +1962,6 @@ int mac_xmit(struct sk_buff *skb, struct net_device *ndev) nic = netdev_priv(ndev); - PRINT_D(INT_DBG, "\n========\n IntUH: %d - IntBH: %d - IntCld:\n========\n", - int_rcvdU, int_rcvdB); PRINT_D(TX_DBG, "Sending packet just received from TCP/IP\n"); /* Stop the network interface queue */ @@ -2015,14 +2005,12 @@ int mac_xmit(struct sk_buff *skb, struct net_device *ndev) nic->netstats.tx_packets++; nic->netstats.tx_bytes += tx_data->size; tx_data->pBssid = g_linux_wlan->strInterfaceInfo[nic->u8IfIdx].aBSSID; - #ifndef WILC_FULLY_HOSTING_AP + QueueCount = g_linux_wlan->oup.wlan_add_to_tx_que((void *)tx_data, tx_data->buff, tx_data->size, linux_wlan_tx_complete); - #else - QueueCount = WILC_Xmit_data((void *)tx_data, HOST_TO_WLAN); - #endif /* WILC_FULLY_HOSTING_AP */ + if (QueueCount > FLOW_CONTROL_UPPER_THRESHOLD) { netif_stop_queue(g_linux_wlan->strInterfaceInfo[0].wilc_netdev); @@ -2095,8 +2083,9 @@ int mac_close(struct net_device *ndev) #endif } - up(&close_exit_sync); nic->mac_opened = 0; + up(&close_exit_sync); + return 0; } @@ -2249,9 +2238,23 @@ void frmw_to_linux(uint8_t *buff, uint32_t size, uint32_t pkt_offset) /*Allocate memory*/ if (priv->pStrBufferedEAP == NULL) { priv->pStrBufferedEAP = kmalloc(sizeof(struct wilc_buffered_eap), GFP_ATOMIC); - priv->pStrBufferedEAP->pu8buff = NULL; + if(priv->pStrBufferedEAP != NULL) + { + priv->pStrBufferedEAP->pu8buff = NULL; + priv->pStrBufferedEAP->u32Size = 0; + priv->pStrBufferedEAP->u32PktOffset = 0; + } + else + { + PRINT_ER("failed to alloc priv->pStrBufferedEAP\n"); + return; + } } - kfree(priv->pStrBufferedEAP->pu8buff); + else + { + kfree(priv->pStrBufferedEAP->pu8buff); + } + priv->pStrBufferedEAP->pu8buff = kmalloc(size + pkt_offset, GFP_ATOMIC); priv->pStrBufferedEAP->u32Size = size; @@ -2272,8 +2275,6 @@ void frmw_to_linux(uint8_t *buff, uint32_t size, uint32_t pkt_offset) if (skb == NULL) return; - skb_reserve(skb, (unsigned int)skb->data & 0x3); - if (g_linux_wlan == NULL || wilc_netdev == NULL) PRINT_ER("wilc_netdev in g_linux_wlan is NULL"); skb->dev = wilc_netdev; @@ -2352,8 +2353,6 @@ int wilc_netdev_init(void) /*create the common structure*/ /*Reset interrupt count debug*/ - int_rcvdU = 0; - int_rcvdB = 0; #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP register_inetaddr_notifier(&g_dev_notifier); #endif @@ -2422,7 +2421,7 @@ static int __init init_wilc_driver(void) { int ret = 0; - PRINT_D(INIT_DBG, "WILC3000 driver v10\n"); + PRINT_D(INIT_DBG, "WILC3000 driver v11\n"); set_pf_chip_sleep_manually(chip_sleep_manually); set_pf_get_num_conn_ifcs( linux_wlan_get_num_conn_ifcs); set_pf_host_wakeup_notify(wilc_host_wakeup_notify); @@ -2464,22 +2463,10 @@ static void __exit exit_wilc_driver(void) if ((g_linux_wlan != NULL) && (((g_linux_wlan->strInterfaceInfo[0].wilc_netdev) != NULL) || ((g_linux_wlan->strInterfaceInfo[1].wilc_netdev) != NULL))) { -#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP - unregister_inetaddr_notifier(&g_dev_notifier); -#endif for (i = 0; i < NUM_CONCURRENT_IFC; i++) nic[i] = netdev_priv(g_linux_wlan->strInterfaceInfo[i].wilc_netdev); - } - - if ((g_linux_wlan != NULL) && g_linux_wlan->wilc_firmware != NULL) { - release_firmware(g_linux_wlan->wilc_firmware); - g_linux_wlan->wilc_firmware = NULL; - } - - if ((g_linux_wlan != NULL) && - (((g_linux_wlan->strInterfaceInfo[0].wilc_netdev) != NULL) || - ((g_linux_wlan->strInterfaceInfo[1].wilc_netdev) != NULL))) { + PRINT_D(INIT_DBG, "Waiting for mac_close ....\n"); if (down_timeout(&close_exit_sync, msecs_to_jiffies(CLOSE_TIMEOUT)) < 0) @@ -2491,7 +2478,10 @@ static void __exit exit_wilc_driver(void) //close all opened interfaces if (g_linux_wlan->strInterfaceInfo[i].wilc_netdev != NULL) if (nic[i]->mac_opened) + { + PRINT_D(INIT_DBG, "calling mac_close from exit_drv\n"); mac_close(g_linux_wlan->strInterfaceInfo[i].wilc_netdev); + } } for (i = 0; i < NUM_CONCURRENT_IFC; i++) { PRINT_D(INIT_DBG, "Unregistering netdev %p\n", g_linux_wlan->strInterfaceInfo[i].wilc_netdev); @@ -2503,6 +2493,15 @@ static void __exit exit_wilc_driver(void) } } + #ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP + unregister_inetaddr_notifier(&g_dev_notifier); + #endif + + if ((g_linux_wlan != NULL) && g_linux_wlan->wilc_firmware != NULL) { + release_firmware(g_linux_wlan->wilc_firmware); + g_linux_wlan->wilc_firmware = NULL; + } + at_pwr_unregister_bus(PWR_DEV_SRC_WIFI); if (g_linux_wlan != NULL) { diff --git a/wilc3000/linux_wlan_common.h b/wilc3000/linux_wlan_common.h old mode 100755 new mode 100644 index a99ff0c..154a2b5 --- a/wilc3000/linux_wlan_common.h +++ b/wilc3000/linux_wlan_common.h @@ -88,6 +88,8 @@ enum debug_region{ #define MODALIAS "wilc_spi" #define GPIO_NUM 46 #define MIN_SPEED 24000000 +#define GPIO_NUM_RESET 60 +#define GPIO_NUM_CHIP_EN 94 #endif #if defined(PLAT_SAMA5D3) diff --git a/wilc3000/linux_wlan_sdio.c b/wilc3000/linux_wlan_sdio.c old mode 100755 new mode 100644 diff --git a/wilc3000/linux_wlan_sdio.h b/wilc3000/linux_wlan_sdio.h index 4725114..31188eb 100644 --- a/wilc3000/linux_wlan_sdio.h +++ b/wilc3000/linux_wlan_sdio.h @@ -1,32 +1,32 @@ -/* - * Atmel WILC3000 802.11 b/g/n and Bluetooth Combo driver - * - * Copyright (c) 2015 Atmel Corportation - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef LINUX_WLAN_SDIO_H -#define LINUX_WLAN_SDIO_H - -#include -#include "wilc_type.h" - -#ifdef WILC_SDIO -extern struct sdio_func *local_sdio_func; -extern struct sdio_driver wilc_bus; -#endif /* WILC_SDIO */ -extern volatile int probe; +/* + * Atmel WILC3000 802.11 b/g/n and Bluetooth Combo driver + * + * Copyright (c) 2015 Atmel Corportation + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef LINUX_WLAN_SDIO_H +#define LINUX_WLAN_SDIO_H + +#include +#include "wilc_type.h" + +#ifdef WILC_SDIO +extern struct sdio_func *local_sdio_func; +extern struct sdio_driver wilc_bus; +#endif /* WILC_SDIO */ +extern volatile int probe; struct sdio_cmd52_t { uint32_t read_write : 1; @@ -46,14 +46,13 @@ struct sdio_cmd53_t { uint8_t *buffer; uint32_t block_size; }; -typedef void (*wilc_debug_func)(uint32_t, char *, ...); -typedef void (*isr_handler_t)(void); -int linux_sdio_init(void *); -void linux_sdio_deinit(void *); -int linux_sdio_cmd52(struct sdio_cmd52_t *cmd); -int linux_sdio_cmd53(struct sdio_cmd53_t *cmd); -int enable_sdio_interrupt(isr_handler_t isr_handler); -void disable_sdio_interrupt(void); -int linux_sdio_set_max_speed(void); - -#endif /* LINUX_WLAN_SDIO_H */ +typedef void (*wilc_debug_func)(uint32_t, char *, ...); +typedef void (*isr_handler_t)(void); +int linux_sdio_init(void *); +void linux_sdio_deinit(void *); +int linux_sdio_cmd52(struct sdio_cmd52_t *cmd); +int linux_sdio_cmd53(struct sdio_cmd53_t *cmd); +int enable_sdio_interrupt(isr_handler_t isr_handler); +void disable_sdio_interrupt(void); + +#endif /* LINUX_WLAN_SDIO_H */ diff --git a/wilc3000/linux_wlan_spi.c b/wilc3000/linux_wlan_spi.c index 062bbb2..6a2c189 100644 --- a/wilc3000/linux_wlan_spi.c +++ b/wilc3000/linux_wlan_spi.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include @@ -50,19 +50,12 @@ static int wilc_bus_remove(struct spi_device *spi) return 0; } -static const struct of_device_id wilc3000_of_match[] = { - { .compatible = "atmel,wilc_spi", }, - {} -}; - -MODULE_DEVICE_TABLE(of, wilc3000_of_match); struct spi_driver wilc_bus __refdata = { - .driver = { - .name = MODALIAS, - .of_match_table = wilc3000_of_match, - }, - .probe = wilc_bus_probe, - .remove = __exit_p(wilc_bus_remove), + .driver = { + .name = MODALIAS, + }, + .probe = wilc_bus_probe, + .remove = __devexit_p(wilc_bus_remove), }; void linux_spi_deinit(void *vp) diff --git a/wilc3000/wilc_host_ap.c b/wilc3000/wilc_host_ap.c deleted file mode 100644 index 58a57a3..0000000 --- a/wilc3000/wilc_host_ap.c +++ /dev/null @@ -1,3042 +0,0 @@ -/* - * Atmel WILC3000 802.11 b/g/n and Bluetooth Combo driver - * - * Copyright (c) 2015 Atmel Corportation - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "linux_wlan_common.h" -#include "atl_error_support.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "linux/string.h" -#include "wilc_host_ap.h" -#include "linux_wlan.h" - -#ifdef WILC_FULLY_HOSTING_AP - -struct tx_complete_data { - struct tx_complete_data *next; - int size; - void *buff; - struct sk_buff *skb; -}; - -/*****************************************************************************/ -/* Static Global Variables */ -/*****************************************************************************/ - -static const u8 g_bmap[8] = {1, 2, 4, 8, 16, 32, 64, 128}; /* Bit map */ - -/*****************************************************************************/ -/* Global variables */ -/*****************************************************************************/ - -struct table_elmnt *g_sta_table[MAX_HASH_VALUES] = {0, }; - -struct beacon_info strBeaconInfo = {0}; -u8 g_snap_header[SNAP_HDR_ID_LEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00}; - -/* Power management related globals */ -u8 g_num_sta_ps = 0; /* Num of STA in PS */ -unsigned int g_num_mc_bc_pkt = 0; /* Num of BC/MC pkts in PSQ */ -unsigned int g_num_ps_pkt = 0; /* Num of UC/BC/MC pkts in PSQ */ -u16 g_num_mc_bc_qd_pkt = 0; /* Num of BC/MC pkts in Hw */ -struct list_buff g_mc_q; -/* u8 g_vbmap[VBMAP_SIZE] = {0,}; */ -/* u8 g_tim_element_index = 0; */ -/* u16 g_tim_element_trailer_len = 0; */ -struct q_head g_ps_pending_q = {0, }; -u16 g_aging_thresh_in_sec = AGING_THR_IN_SEC; -struct WILC_ieee80211_sta *g_max_ps_ae = NULL; /* Association entry of STA, with max num of PS pkts */ - -static void *find_entry(u8 *key); -static void add_entry(void *entry, u8 *key); -static void delete_entry(u8 *key); -static void frmw_to_linux(uint8_t *buff, uint32_t size); -static void ap_enabled_rx_data(u8 *msg); -static enum REQUEUE_STATUS requeue_ps_packet(struct WILC_ieee80211_sta *ae, struct list_buff *qh, - bool ps_q_legacy, bool eosp); -static bool buffer_tx_packet(u8 *entry, u8 *da, u8 priority, - struct tx_complete_data *tx_dscr); -static void handle_ps_tx_comp_ap(struct tx_complete_data *tx_dscr); -static void check_and_reset_tim_bit(u16 asoc_id); -static bool handle_ps_poll(struct wlan_rx *wlan_rx); - -/* This function returns whether the Multicast bit is set in the given beacon*/ -/* frame */ -inline bool get_mc_bit_bcn(void) -{ - bool ret_value; - - ret_value = (bool)(strBeaconInfo.u8beacon_frame[strBeaconInfo.u8tim_element_index + BMAP_CTRL_OFFSET] & - 0x01); - return ret_value; -} - -/* This function returns whether the Multicast bit is set in the given beacon*/ -/* frame */ -inline void reset_mc_bit_bcn(void) -{ - strBeaconInfo.u8beacon_frame[strBeaconInfo.u8tim_element_index + TIM_OFFSET] &= 0xFE; - strBeaconInfo.u8beacon_frame[strBeaconInfo.u8tim_element_index + BMAP_CTRL_OFFSET] &= 0xFE; -} - -/* - * @brief WILC_beacon_tx_complete - * @details call back function for beacon transmission through vmm , does nothing at the moment - * @return - * @author Abd Al-Rahman Diab - * @date 09 APRIL 2013 - * @version 1.0 - */ -static void WILC_beacon_tx_complete(void *priv, int status) -{ - /* Do nothing */ - - /* - * struct beacon_data* pv_data = (struct beacon_data*)priv; - * u8 * buf= pv_data->buff; - * - * if(status == 1) - * { - * if(buf[0] == 0x80 || buf[0] == 0xb0) - * PRINT_D(HOSTAPD_DBG, "Packet sent successfully - Size = %d - Address = %p.\n",pv_data->size,pv_data->buff); - * } - * else - * { - * PRINT_D(HOSTAPD_DBG, "Couldn't send packet - Size = %d - Address = %p.\n",pv_data->size,pv_data->buff); - * } - */ -} - -/* - * @brief WILC_beacon_xmit - * @details send beacon frame to firmware - * @param[in] u8 *buf : pointer to the beacon frame - * size_t len : beacon frame length - * @return Error code. - * @author Abd Al-Rahman Diab - * @date 09 APRIL 2013 - * @version 1.0 - */ -static int WILC_beacon_xmit(const u8 *buf, size_t len) -{ - struct beacon_data *strBeacon_tx = NULL; - - /* allocate the struct beacon_data struct */ - strBeacon_tx = kmalloc(sizeof(struct beacon_data), GFP_ATOMIC); - if (strBeacon_tx == NULL) { - PRINT_ER("Failed to allocate memory for mgmt_tx structure\n"); - return ATL_FAIL; - } - - /* allocate buffer for beacon data within the struct beacon_data struct */ - strBeacon_tx->buff = kmalloc(len, GFP_ATOMIC); - if (strBeacon_tx->buff == NULL) { - PRINT_ER("Failed to allocate memory for mgmt_tx buff\n"); - return ATL_FAIL; - } - - /* fill in the beacon data stuct */ - memcpy(strBeacon_tx->buff, buf, len); - strBeacon_tx->size = len; - - /* the actual transmission of beacon to firmware*/ - wilc_wlan_txq_add_mgmt_pkt(strBeacon_tx, strBeacon_tx->buff, strBeacon_tx->size, WILC_beacon_tx_complete); - - return 0; -} - -/** - * @brief host_add_beacon - * @details Setting add beacon params in message queue - * @param[in] struct WFIDrvHandle *hWFIDrv, unsigned int u32Interval, - * unsigned int u32DTIMPeriod,unsigned int u32HeadLen, u8* pu8Head, - * unsigned int u32TailLen, u8* pu8Tail - * @return Error code. - * @author Abd Al-Rahman Diab - * @date - * @version 1.0 - */ -signed int host_add_beacon(struct WFIDrvHandle *hWFIDrv, unsigned int u32Interval, - unsigned int u32DTIMPeriod, - unsigned int u32HeadLen, u8 *pu8Head, - unsigned int u32TailLen, u8 *pu8Tail) -{ - signed int s32Error = ATL_SUCCESS; - bool bIsBeaconSet = false; - u8 *pu8BeaconFrame; - u16 u16size = 0; - struct wilc_wlan_dev *strWlan = Get_wlan_context(&u16size); - - if (u16size != sizeof(struct wilc_wlan_dev)) - PRINT_ER("size of struct wilc_wlan_dev in wilc_wlan != it's size in wilc_host_ap\n"); - - - /* calculate beacon length */ - strBeaconInfo.u16beacon_len = u32HeadLen + u32TailLen + DEFAULT_TIM_LEN + 2; - PRINT_D(HOSTAPD_DBG, "beacon_len=%d\n", strBeaconInfo.u16beacon_len); - - /* set beacon interval in chip */ - if (u32Interval > 0) { - strBeaconInfo.u16Beacon_Period = u32Interval; - PRINT_D(HOSTAPD_DBG, "Beacon_Period=%d\n", strBeaconInfo.u16Beacon_Period); - strWlan->hif_func.hif_write_reg(rMAC_BEACON_PERIOD, u32Interval); - } - - /* allocate beacon frame */ - if (strBeaconInfo.u8beacon_frame == NULL) { - PRINT_D(HOSTAPD_DBG, "beacon_frame wasn't allocated. allocating new buffers\n"); - /* Allocate 2 global beacon buffers as the beacon for AP may be modfied */ - /* for which 2 buffers are needed. */ - strBeaconInfo.u8beacon_frame = kmalloc(strBeaconInfo.u16beacon_len, GFP_ATOMIC); - if (strBeaconInfo.u8beacon_frame == NULL) { - PRINT_ER("Couldn't allocate beacon_frame\n"); - /* Exception - no memory for beacons */ - s32Error = ATL_FAIL; - return s32Error; - } - } else { - bIsBeaconSet = true; - } - /* set beacon DTIM period in chip */ - if (u32DTIMPeriod > 0) { - strBeaconInfo.u8DTIMPeriod = u32DTIMPeriod; - PRINT_D(HOSTAPD_DBG, "DTIMPeriod=%d\n", strBeaconInfo.u8DTIMPeriod); - strWlan->hif_func.hif_write_reg(rMAC_DTIM_PERIOD, u32DTIMPeriod); - } - - /* save TIM element location within the beacon */ - strBeaconInfo.u8tim_element_index = u32HeadLen; - strBeaconInfo.u16tim_element_trailer_len = u32TailLen; - - /* Copy beacon head part*/ - pu8BeaconFrame = strBeaconInfo.u8beacon_frame; - memcpy(pu8BeaconFrame, pu8Head, u32HeadLen); - pu8BeaconFrame += u32HeadLen; - - /* Set the TIM element field with default parameters and update the */ - /* index value with the default length. */ - *(pu8BeaconFrame++) = ITIM; - *(pu8BeaconFrame++) = DEFAULT_TIM_LEN; - *(pu8BeaconFrame++) = 0; - *(pu8BeaconFrame++) = strBeaconInfo.u8DTIMPeriod; - *(pu8BeaconFrame++) = 0; - *(pu8BeaconFrame++) = 0; - - memcpy(pu8BeaconFrame, pu8Tail, u32TailLen); - pu8BeaconFrame += u32TailLen; - - WILC_beacon_xmit(strBeaconInfo.u8beacon_frame, strBeaconInfo.u16beacon_len); - - PRINT_D(HOSTAPD_DBG, "Starting TSF timer\n"); - - /* Initialize the virtual bitmap */ - strBeaconInfo.u8vbmap[TYPE_OFFSET] = ITIM; /* Element ID */ - strBeaconInfo.u8vbmap[LENGTH_OFFSET] = DEFAULT_TIM_LEN; /* Element Length */ - strBeaconInfo.u8vbmap[DTIM_CNT_OFFSET] = 0; /* Dtim Count */ - strBeaconInfo.u8vbmap[DTIM_PERIOD_OFFSET] = strBeaconInfo.u8DTIMPeriod; /* Dtim Period */ - strBeaconInfo.u8vbmap[BMAP_CTRL_OFFSET] = 0; /* Bitmap Control */ - strBeaconInfo.u8vbmap[TIM_OFFSET] = 0; /* Copy TIM element */ - - /* Start TSF timer in chip to start sending beacons*/ - strWlan->hif_func.hif_write_reg(rMAC_TSF_CON, BIT1 | BIT0); - - return s32Error; -} - -/* - * @brief host_del_beacon - * @details delete the allocated beacon - * @param[in] struct WFIDrvHandle *hWFIDrv - * @return Error code. - * @author Abd Al-Rahman Diab - * @date 09 APRIL 2013 - * @version 1.0 - */ -signed int host_del_beacon(struct WFIDrvHandle *hWFIDrv) -{ - signed int s32Error = ATL_SUCCESS; - - PRINT_D(HOSTAPD_DBG, "host_del_beacon\n"); - - if (strBeaconInfo.u8beacon_frame != NULL) { - kfree(strBeaconInfo.u8beacon_frame); - strBeaconInfo.u8beacon_frame = NULL; - strBeaconInfo.u16beacon_len = 0; - } - - ATL_ERRORCHECK(s32Error); - - ATL_CATCH(s32Error){ - } - return s32Error; -} - -/* - * @brief handle tbtt ISR and send updated beacon to chip - * @details - * @param[in] - * @return - * @author Abd Al-Rahman Diab - * @date 09 APRIL 2013 - * @version 1.0 - */ -void process_tbtt_isr(void) -{ - u16 i = 0; - u8 u8OldTimLen = 0; - unsigned int dtim_count = 0; - u16 u16size = 0; - struct wilc_wlan_dev *strWlan = Get_wlan_context(&u16size); - - /* Warning : This is a development only print to notify the developer, it should be removed later on */ - if (u16size != sizeof(struct wilc_wlan_dev)) - PRINT_ER("size of struct wilc_wlan_dev in wilc_wlan != it's size in wilc_host_ap\n"); - - /* PRINT_D(HOSTAPD_DBG, "--IN process_tbtt_isr--\n"); */ - - /* Read the current DTIM count from H/W */ - strWlan->hif_func.hif_read_reg(rMAC_DTIM_COUNT_ADDR, &dtim_count); - - /* If the beacon pointer has been updated to a new value, the free */ - /* beacon buffer index is updated to the other buffer. */ - if (dtim_count == 0) { - dtim_count = strBeaconInfo.u8DTIMPeriod - 1; - - /* The beacon transmitted at this TBTT is the DTIM. Requeue all */ - /* MC/BC packets to the high priority queue. */ - /* Check if the beacon that is being transmitted has the MC bit */ - /* set */ - if (true == get_mc_bit_bcn()) - while (requeue_ps_packet(NULL, &g_mc_q, true, false) == PKT_REQUEUED) - ; - - } else { - /* Do nothing */ - dtim_count--; - } - /* If the buffer that is not currently in use has not been freed*/ - if (strBeaconInfo.u8beacon_frame != NULL) { -#ifdef WILC_AP_EXTERNAL_MLME - - /* Shift the position of the trailer after the TIM element if needed*/ - u8OldTimLen = strBeaconInfo.u8beacon_frame[strBeaconInfo.u8tim_element_index + LENGTH_OFFSET]; - if (u8OldTimLen > strBeaconInfo.u8vbmap[LENGTH_OFFSET]) { - unsigned int u32ShiftOffset = u8OldTimLen - strBeaconInfo.u8vbmap[LENGTH_OFFSET]; - unsigned int u32TrailerIndex = strBeaconInfo.u8tim_element_index + u8OldTimLen + 2; - /*need to shrink the old TIM; i.e. shift the trailer backwards*/ - for (i = u32TrailerIndex; i < (u32TrailerIndex + strBeaconInfo.u16tim_element_trailer_len); i++) - strBeaconInfo.u8beacon_frame[i - u32ShiftOffset] = strBeaconInfo.u8beacon_frame[i]; - } else if (u8OldTimLen < strBeaconInfo.u8vbmap[LENGTH_OFFSET]) { - unsigned int u32ShiftOffset = strBeaconInfo.u8vbmap[LENGTH_OFFSET] - u8OldTimLen; - unsigned int u32TrailerIndex = strBeaconInfo.u8tim_element_index + u8OldTimLen + 2; - /*need to enlarge the old TIM; i.e. shift the trailer forward*/ - for (i = (u32TrailerIndex + strBeaconInfo.u16tim_element_trailer_len - 1); i >= u32TrailerIndex; i--) - strBeaconInfo.u8beacon_frame[i + u32ShiftOffset] = strBeaconInfo.u8beacon_frame[i]; - } - /* Other wise TIM element has the same length, and no shifting is required*/ -#endif /*WILC_AP_EXTERNAL_MLME*/ - strBeaconInfo.u8vbmap[DTIM_CNT_OFFSET] = dtim_count; - - for (i = 0; i < strBeaconInfo.u8vbmap[LENGTH_OFFSET] + 2; i++) { - strBeaconInfo.u8beacon_frame[strBeaconInfo.u8tim_element_index + i] = - strBeaconInfo.u8vbmap[i]; - } - strBeaconInfo.u16beacon_len = strBeaconInfo.u8tim_element_index + strBeaconInfo.u16tim_element_trailer_len + - strBeaconInfo.u8vbmap[LENGTH_OFFSET] + 2; - - /* The status of BC/MC packets queued for PS should be updated only */ - /* in DTIM beacon dtim_count==0. For the rest of the becons reset */ - /* the BC/MC bit in TIM */ - if (dtim_count != 0) - reset_mc_bit_bcn(); - - /* send the updated beacon to firmware */ - WILC_beacon_xmit(strBeaconInfo.u8beacon_frame, strBeaconInfo.u16beacon_len); - } -} - -/*****************************************************************************/ -/* Inline Functions */ -/*****************************************************************************/ - -/* List buffer is a queue maintained as a singly-linked link list of the */ -/* elements to be stored in the queue. It uses 4 bytes from the element */ -/* itself to store the link address of the next element. This has low */ -/* processing overhead & memory requirements. However, it assumes the */ -/* availability of the extra 4 Bytes in the element for creating the */ -/* link. These 4 bytes are specified by the user during the */ -/* initialization phase & the assigned bytes should not be modified by */ -/* the user. */ -/* Note that no critical sections are currently used in this module. Hence */ -/* a List Buffer should be accessed from only one context/thread. */ - -/* This function initializes the List Buffer handle. The offset within the */ -/* element which can be used for storing the link is specified as input. */ -inline void init_list_buffer(struct list_buff *lbuff, unsigned int lnk_byte_ofst) -{ - lbuff->head = NULL; - lbuff->tail = NULL; - lbuff->count = 0; - lbuff->lnk_byte_ofst = lnk_byte_ofst; -} - -/* This function adds a new element to the end of the queue. */ -inline void add_list_element(struct list_buff *lbuff, void *elem) -{ - NEXT_ELEMENT_ADDR(elem, lbuff->lnk_byte_ofst) = 0; - - if (lbuff->tail == NULL) - lbuff->head = elem; - else - NEXT_ELEMENT_ADDR(lbuff->tail, lbuff->lnk_byte_ofst) = (unsigned int)elem; - - lbuff->tail = elem; - lbuff->count++; -} - -/* This function removes the first element from the head of the queue */ -inline void *remove_list_element_head(struct list_buff *lbuff) -{ - void *retval = NULL; - - if (lbuff->head == NULL) - return NULL; - - retval = lbuff->head; - lbuff->head = (void *)NEXT_ELEMENT_ADDR(lbuff->head, lbuff->lnk_byte_ofst); - - if (lbuff->head == NULL) - lbuff->tail = NULL; - - lbuff->count--; - - return retval; -} - -/* This function removes a given element from the queue */ -/* The previous element also needs to be given. The previous element ptr */ -/* will be NULL if the curr element is the head */ -/* CAUTION: There is no check done if the element exist in the link list */ -inline void remove_list_element(struct list_buff *lbuff, void *prev_el, - void *curr_el) -{ - void *next_el; - - next_el = (void *)NEXT_ELEMENT_ADDR(curr_el, lbuff->lnk_byte_ofst); - - if (prev_el == NULL) - /* The current element is the head */ - lbuff->head = next_el; - else - NEXT_ELEMENT_ADDR(prev_el, lbuff->lnk_byte_ofst) = (unsigned int)next_el; - - if (next_el == NULL) - /* The current element is the tail */ - lbuff->tail = prev_el; - - lbuff->count--; -} - -/* This function is used to check the head of the queue */ -inline void *peek_list(struct list_buff *lbuff) -{ - return lbuff->head; -} - -/* This function is used to get the pointer to the next element in the list */ -/* The reference is the current element */ -inline void *next_element_list(struct list_buff *lbuff, void *curr_el) -{ - if (curr_el == NULL) - return lbuff->head; - else - return (void *)NEXT_ELEMENT_ADDR(curr_el, lbuff->lnk_byte_ofst); -} - -/* This function merges 2 queues of the SAME type */ -/* Queue 2 is reset */ -inline void merge_list(struct list_buff *q1, struct list_buff *q2) -{ - if (q1->head == NULL) - q1->head = q2->head; - else - NEXT_ELEMENT_ADDR(q1->tail, q1->lnk_byte_ofst) - = (unsigned int) q2->head; - - if (q2->tail != NULL) - q1->tail = q2->tail; - - q1->count += q2->count; - - /* empty the 2nd Q */ - q2->head = NULL; - q2->tail = NULL; - q2->count = 0; -} - -/*! - * @fn void WILC_AP_AddSta(u8 *mac, struct station_parameters *params) - * @brief add a station entry in the stations' table - * @details Stations are identified by the SSID - * @return - * @todo - * @sa - * @author Adham Abozaeid - * @date 9 May 2013 - * @version 1.1 moved to driver - */ -inline void WILC_AP_AddSta(u8 *mac, struct station_parameters *params) -{ - u8 au8Sa[6]; - u8 *pu8CurrData; - struct WILC_ieee80211_sta *pstrAsocEntry = NULL; - unsigned int i; - bool bIsPrevAsoc = false; - u8 ht_info_mod = 0; - u16 u16CapInfo = 0; - - memcpy(au8Sa, mac, ETH_ALEN); - - PRINT_D(HOSTAPD_DBG, "Add station BSSID: %x, %x, %x,%x,%x,%x,\n", - au8Sa[0], au8Sa[1], au8Sa[2], au8Sa[3], au8Sa[4], au8Sa[5]); - - pstrAsocEntry = (struct WILC_ieee80211_sta *)find_entry(au8Sa); - - pstrAsocEntry = kmalloc(sizeof(struct WILC_ieee80211_sta), GFP_ATOMIC); - - if (pstrAsocEntry == NULL) { - PRINT_ER("No memory available to add new station\n"); - return; - } - - /* Reset the AE Handle */ - memset(pstrAsocEntry, 0, sizeof(struct WILC_ieee80211_sta)); - - /* TODO: Implement inactivity timer */ - /*Add timer for the first new station entry*/ - /* if(g_inactive_timer == 0) - * { - * PRINTK("FIRST STA: CREATE TIMER\n"); - * g_inactive_timer = create_alarm(ap_inactive_timeout, 0,"sta_inactive"); - * start_alarm(g_inactive_timer,1000); - * } - */ - - add_entry((void *)pstrAsocEntry, au8Sa); - pstrAsocEntry->aging_cnt = 0; - - /* Set the power save state to default ACTIVE. Will be checked/updated */ - /* as required later. */ - pstrAsocEntry->ps_state = ACTIVE_PS; - pstrAsocEntry->ps_poll_rsp_qed = false; - pstrAsocEntry->num_ps_pkt = 0; - pstrAsocEntry->num_qd_pkt = 0; - init_list_buffer(&(pstrAsocEntry->ps_q_lgcy), - 0); - - pstrAsocEntry->u16AID = params->aid; - PRINT_D(HOSTAPD_DBG, "Assoc ID: %x\n", pstrAsocEntry->u16AID); - - /* TODO: Really ? */ - /* The 2 MSB bits of Association ID is set to 1 as required by the */ - /* standard. */ - /* pstrAsocEntry->asoc_id = (pstrAsocEntry->sta_index | 0xc000); */ - - pstrAsocEntry->op_rates.num_rates = params->supported_rates_len; - /* strStaParams.pu8Rates = params->supported_rates; */ - - if (pstrAsocEntry->op_rates.num_rates > MAX_RATES_SUPPORTED) { - PRINT_ER("number of rates %d exceeds MAX_NUM_RATES %d. will use max!\n", - pstrAsocEntry->op_rates.num_rates, MAX_RATES_SUPPORTED); - pstrAsocEntry->op_rates.num_rates = MAX_RATES_SUPPORTED; - } - PRINT_D(HOSTAPD_DBG, "Num rates: %d\n", pstrAsocEntry->op_rates.num_rates); - - for (i = 0; i < pstrAsocEntry->op_rates.num_rates; i++) { - pstrAsocEntry->op_rates.rates[i] = (params->supported_rates)[i] & 0x7F; - PRINT_D(HOSTAPD_DBG, "%d ", pstrAsocEntry->op_rates.rates[i]); - } - PRINT_D(HOSTAPD_DBG, "\n"); - - /* TODO: Rates should be sorted by here, if not, the code should sort it*/ -#if 0 - for (i = 0; i < num_rates; i++) { - u8 min = (ae->op_rates.rates[i] & 0x7F); - u8 mid = i; - u8 tmp = 0; - - for (j = i + 1; j < num_rates; j++) { - if (min > (ae->op_rates.rates[j] & 0x7F)) { - min = (ae->op_rates.rates[j] & 0x7F); - mid = j; - } - } - - tmp = ae->op_rates.rates[i]; - ae->op_rates.rates[i] = ae->op_rates.rates[mid]; - ae->op_rates.rates[mid] = tmp; - } -#endif - - /* TODO: If the STA does not support all the basic rates respond with */ - /* failure (unsupported rates) status. */ -#if 0 - for (i = 0; i < get_num_basic_rates(); i++) { - bool found = false; - u8 mac_br = get_mac_basic_rate(i); - - for (j = 0; j < pstrAsocEntry->op_rates.num_rates; j++) { - if ((pstrAsocEntry->op_rates.rates[j] & 0x7F) == (mac_br & 0x7F)) { - found = true; - break; - } - } - - /* Return unsupported rates if the joining station does not */ - /* support any of the basic rates. */ - if (found == false) - return UNSUP_RATE; - } -#endif - - /* TODO: Add 11n support */ - pstrAsocEntry->ht_cap.ht_supported = (params->ht_capa != NULL); - PRINT_D(HOSTAPD_DBG, "HT supported: %d\n", pstrAsocEntry->ht_cap.ht_supported); - if (pstrAsocEntry->ht_cap.ht_supported) { - /* - * pu8CurrData += WILC_AP_ParseHTCap(pu8CurrData, &pstrAsocEntry->ht_hdl, - * bIsPrevAsoc, &ht_info_mod);*/ - u16CapInfo = params->ht_capa->cap_info; - pstrAsocEntry->ht_cap.cap = params->ht_capa->cap_info; - } - /* If the STA is not HT capable disallow association if 11n operating */ - /* mode is not HT_MIXED. If it is HT_MIXED, update the Operating Mode to */ - /* 3. Also update the global number of non-HT STAs */ - /* if(pstrAsocEntry->ht_cap.ht_supported == 0) */ - /* { */ - /* TODO: update this according to the FSM */ - /*if(get_11n_op_mode() == HT_MIXED_MODE) - * { - * if(mget_HTOperatingMode() != 3) - * { - * ht_info_mod = 1; - * set_ht_operating_mode(3); - * disable_rifs(); - * } - * - * g_num_sta_nonht_asoc++; - * - * // If auto protection is set, and neither ERP nor HT protection - * // is currently in use, enable HT protection. - * //if((is_autoprot_enabled() == true) && - * (get_protection() != ERP_PROT) && - * (get_protection() != HT_PROT)) - * { - * set_protection(HT_PROT); - * } - * } - * else - * { - * // return STA_NOT_HTCAP; - * PRINT_D(HOSTAPD_DBG, "Station is not HT capable and AP mode don't support HT_MIXED_MODE"); - * }*/ - /* } */ - - /* Print the STA's HT-Capabilities */ - /*PRINT_D(HOSTAPD_DBG, "STA HT-Capabilities:\n\r"); - * PRINT_D(HOSTAPD_DBG, "ht_capable = %x\n\r", pstrAsocEntry->ht_hdl.ht_capable); - * PRINT_D(HOSTAPD_DBG, "ldpc_cod_cap = %x\n\r", pstrAsocEntry->ht_hdl.ldpc_cod_cap); - * PRINT_D(HOSTAPD_DBG, "smps_mode = %x\n\r", pstrAsocEntry->ht_hdl.smps_mode); - * PRINT_D(HOSTAPD_DBG, "greenfield = %x\n\r", pstrAsocEntry->ht_hdl.greenfield); - * PRINT_D(HOSTAPD_DBG, "short_gi_20 = %x\n\r", pstrAsocEntry->ht_hdl.short_gi_20); - * PRINT_D(HOSTAPD_DBG, "short_gi_40 = %x\n\r", pstrAsocEntry->ht_hdl.short_gi_40); - * PRINT_D(HOSTAPD_DBG, "rx_stbc = %x\n\r", pstrAsocEntry->ht_hdl.rx_stbc); - * PRINT_D(HOSTAPD_DBG, "max_rx_ampdu_factor = %x\n\r", pstrAsocEntry->ht_hdl.max_rx_ampdu_factor); - * PRINT_D(HOSTAPD_DBG, "min_mpdu_start_spacing = %x\n\r", pstrAsocEntry->ht_hdl.min_mpdu_start_spacing); - * PRINT_D(HOSTAPD_DBG, "htc_support = %x\n\r", pstrAsocEntry->ht_hdl.htc_support); - * PRINT_D(HOSTAPD_DBG, "sta_amsdu_maxsize = %x\n\r", pstrAsocEntry->ht_hdl.sta_amsdu_maxsize); - * PRINT_D(HOSTAPD_DBG, "chan_width = %x\n\r", pstrAsocEntry->ht_hdl.chan_width); - * PRINT_D(HOSTAPD_DBG, "dsss_cck_40mhz = %x\n\r", pstrAsocEntry->ht_hdl.dsss_cck_40mhz);*/ - /* PRINT_D(HOSTAPD_DBG, "cipher_type = %x\n\r", pstrAsocEntry->cipher_type); */ - - /* return SUCCESSFUL_STATUSCODE; */ - - /* TODO: Update This in the firmware */ - /* Update the tx rate index */ - /* pstrAsocEntry->tx_rate_index = pstrAsocEntry->op_rates.num_rates - 1; */ - - /* Assign the index to the maximum rate supported by the station */ - /* pstrAsocEntry->tx_rate_mbps = get_user_rate((u8) */ - /* (pstrAsocEntry->op_rates.rates[pstrAsocEntry->op_rates.num_rates- 1] & 0x7F)); */ - - /* TODO: Do we need this */ - #if 0 - /* If the associated STA does not support Short Slot Time option, */ - /* the AP needs to use Long Slot Time from the next beacon interval. */ - if ((u16CapInfo & SHORTSLOT) != SHORTSLOT) { - /* If STA is already associated as a long slot STA, don't update */ - /* g_num_sta_no_short_slot */ - if ((pstrAsocEntry->state != ASOC) || (pstrAsocEntry->short_slot == 1)) { - /* Set the short slot supported field to 0. Also increment */ - /* the global indicating number of stations not supporting */ - /* ShortSlot */ - pstrAsocEntry->short_slot = 0; - g_num_sta_no_short_slot++; - - disable_short_slot(); - set_machw_long_slot_select(); - } - } else { - /* If STA is already associated as a long slot STA, but trying */ - /* to reassociate as a short slot STA, update the global */ - /* g_num_sta_no_short_slot */ - if ((pstrAsocEntry->state == ASOC) && (pstrAsocEntry->short_slot == 0)) { - g_num_sta_no_short_slot--; - if (g_num_sta_no_short_slot == 0) - if (g_short_slot_allowed == true) { - enable_short_slot(); - set_machw_short_slot_select(); - } - - } - pstrAsocEntry->short_slot = 1; - } - - /* Check if the station is 11b station and enable the ERP protection */ - /* If the running mode is G_ONLY_MODE, it would have returned */ - /* UNSUP_RATE and not allow the station to associate with AP. */ - if (pstrAsocEntry->op_rates.num_rates <= NUM_BR_PHY_802_11G_11B_1) { - /* If STA is already associated as an non ERP STA, do not update */ - /* g_num_sta_non_erp */ - if ((pstrAsocEntry->state != ASOC) || - (u8NumRatesOld > NUM_BR_PHY_802_11G_11B_1)) { - /* The associated STA is 11b (non-ERP) station */ - g_num_sta_non_erp++; - - /* Enable protection in case of auto protection */ - if (is_autoprot_enabled() == true) { - set_protection(ERP_PROT); - set_machw_prot_control(); - } - } - } else { - /* If STA is already associated as a non ERP STA, but trying to */ - /* reassociate as an ERP STA, update g_num_sta_non_erp */ - if ((pstrAsocEntry->state == ASOC) && - (u8NumRatesOld <= NUM_BR_PHY_802_11G_11B_1)) { - g_num_sta_non_erp--; - - if (g_num_sta_non_erp == 0) { - if (is_autoprot_enabled() == true) { - set_protection(ERP_PROT); - set_machw_prot_control(); - } - } - } - } - - /* Check if the station supports only long preamble */ - if ((u16CapInfo & SHORTPREAMBLE) != SHORTPREAMBLE) { - /* If STA is already associated as a long preamble STA, do not */ - /* update g_num_sta_no_short_pream */ - if ((pstrAsocEntry->state != ASOC) || (pstrAsocEntry->short_preamble == 1)) { - /* Set the short preamble supported field to 0 and increment */ - /* the global indicating number of stations not supporting */ - /* short preamble. */ - pstrAsocEntry->short_preamble = 0; - g_num_sta_no_short_pream++; - g_short_preamble_enabled = false; - set_machw_prot_pream(1); - } - } else { - /* If STA is already associated as a long preamble STA, but */ - /* trying to reassociate as a short preamble STA, update */ - /* g_num_sta_no_short_pream */ - if ((pstrAsocEntry->state == ASOC) && (pstrAsocEntry->short_preamble == 0)) { - g_num_sta_no_short_pream--; - if (g_num_sta_no_short_pream == 0) { - g_short_preamble_enabled = true; - set_machw_prot_pream(0); - } - } - pstrAsocEntry->short_preamble = 1; - } - #endif - - /* Update the protocol capability in association entry for the STA */ - - /* TODO: Update This in the firmware */ - /* Update the retry rate set table for this station based on the current */ - /* transmit rate of this station */ - /* update_entry_retry_rate_set((void *)pstrAsocEntry, get_phy_rate(get_tx_rate_ap(pstrAsocEntry))); */ - - /* TODO: Autorate is not enabled in our case */ -#if 0 - /* Update the minimum and maximum rate index in the global auto */ - /* rate table for this STA */ - update_min_rate_idx_ap(pstrAsocEntry); - update_max_rate_idx_ap(pstrAsocEntry); - - /* Update the current transmit rate index to minimum supported */ - /* rate index in case of auto rate */ - init_tx_rate_idx_ap(pstrAsocEntry); - reinit_tx_rate_idx_ap(pstrAsocEntry); - - ar_stats_init(&(pstrAsocEntry->ar_stats)); -#endif /* AUTORATE_FEATURE */ - - pstrAsocEntry->state = ASOC; -} - -/*! - * @fn void WILC_AP_EditSta(u8 *mac, struct station_parameters *params) - * @brief Edits a station entry in the stations' table - * @details Stations are identified by the SSID - * @return - * @todo - * @sa - * @author Adham Abozaeid - * @date 9 May 2013 - * @version 1.1 moved to driver - */ -inline void WILC_AP_EditSta(u8 *mac, struct station_parameters *params) -{ - u8 au8Sa[6]; - struct WILC_ieee80211_sta *pstrAsocEntry = NULL; - u8 u8NumRatesOld = 0; - u16 u16Mask, u16Set; - - memcpy(au8Sa, mac, ETH_ALEN); - - PRINT_D(HOSTAPD_DBG, "change station : BSSID: %x, %x, %x,%x,%x,%x,\n", - au8Sa[0], au8Sa[1], au8Sa[2], au8Sa[3], au8Sa[4], au8Sa[5]); - - pstrAsocEntry = (struct WILC_ieee80211_sta *)find_entry(au8Sa); - - if (pstrAsocEntry->state == ASOC) { - u8NumRatesOld = pstrAsocEntry->op_rates.num_rates; - - /* TODO: add security key */ - #if 0 - /*Associated Station*/ - if (is_wep_allowed() == true) { - PRINTK("SETTING WEP ENTRY\n"); - add_wep_entry(pstrAsocEntry->sta_index, mget_WEPDefaultKeyID(), au8Sa); - } - #endif - } - - u16Mask = params->sta_flags_mask; - u16Set = params->sta_flags_set; -} - -/*! - * @fn inline void WILC_AP_RemoveSta(u8 * pu8StaInfo) - * @brief Removes station from the stations' table - * @details Stations are identified by the SSID - * @return - * @todo - * @sa - * @author Adham Abozaeid - * @date 4 July 2012 - * @version 1.1 moved to driver - */ -inline void WILC_AP_RemoveSta(u8 *mac) -{ - struct WILC_ieee80211_sta *pstrAsocEntry = NULL; - u8 au8Sa[6]; - u8 *pu8CurrData; - struct table_elmnt *tbl_elm = 0; - u8 elem_numb = 0; - unsigned int i; - - memcpy(au8Sa, mac, ETH_ALEN); - - PRINT_D(HOSTAPD_DBG, "Removing stationg BSSID: %x, %x, %x,%x,%x,%x,\n", - au8Sa[0], au8Sa[1], au8Sa[2], au8Sa[3], au8Sa[4], au8Sa[5]); - pstrAsocEntry = (struct WILC_ieee80211_sta *)find_entry(au8Sa); - - if (pstrAsocEntry != NULL) - delete_entry(au8Sa); - else - PRINT_ER("couldn't find station in table\n"); - - /* TODO: Implement inactivity timer */ - #if 0 - for (i = 0; i < MAX_HASH_VALUES; i++) { - tbl_elm = g_sta_table[i]; - if (tbl_elm) { - PRINTK("There exists assoc stats dont DELETE\n"); - elem_numb++; - break; - } - } - if (elem_numb == 0) - if (g_inactive_timer) { - PRINTK("DELETING ALARM\n"); - delete_alarm(g_inactive_timer); - } - - #endif -} - -/*****************************************************************************/ -/* Inline functions */ -/*****************************************************************************/ - -/* This function checks whether SNAP header is present in the frame */ -inline bool is_snap_header_present(struct wlan_rx *strWlan_rx) -{ - u8 *data = NULL; - - if (strWlan_rx->u16data_len < SNAP_HDR_LEN) - return false; - - data = strWlan_rx->u8msa + strWlan_rx->u8hdr_len; - - if (memcmp(data, g_snap_header, SNAP_HDR_ID_LEN) != 0) - return false; - - return true; -} - -/* This function sets the 'frame control' bits in the MAC header of the */ -/* input frame to the given 16-bit value. */ -inline void set_frame_control(u8 *header, u16 fc) -{ - header[0] = (u8)(fc & 0x00FF); - header[1] = (u8)(fc >> 8); -} - -inline u8 set_mac_hdr(u8 *mac_hdr) -{ - set_frame_control(mac_hdr, DATA); - - return MAC_HDR_LEN; -} - -/* Update the MAC header depending on the protocol */ -inline u8 set_mac_hdr_prot(u8 *mac_hdr, u8 priority, - u8 service_class, bool qos, bool is_ht, - u8 is_amsdu) -{ - /* TODO: implement 11n */ -#if 0 - if (true == qos) { - u8 mac_hdr_len = 0; - - mac_hdr_len = set_mac_hdr_11e(mac_hdr, priority, service_class); - - if (true == is_ht) - mac_hdr_len += set_ht_control(mac_hdr, mac_hdr_len); - - if (true == is_amsdu) - advt_amsdu_frame(mac_hdr); - - return mac_hdr_len; - } -#endif - return set_mac_hdr(mac_hdr); -} - -/* This function adjusts the frame descriptor data length and offset to */ -/* account for presence of SNAP header */ -inline void adjust_for_snap_header(struct wlan_rx *strWlan_rx) -{ - strWlan_rx->u16data_len -= SNAP_HDR_LEN; - strWlan_rx->u8hdr_len += SNAP_HDR_LEN; -} - -/* This function sets the 'from ds' bit in the MAC header of the input frame */ -/* to the given value stored in the LSB bit. */ -/* The bit position of the 'from ds' in the 'frame control field' of the MAC */ -/* header is represented by the bit pattern 0x00000010. */ -inline void set_from_ds(u8 *header, u8 from_ds) -{ - header[1] &= 0xFD; - header[1] |= (from_ds << 1); -} - -/* This function sets the 'address1' field in the MAC header of the input */ -/* frame to the input MAC Address 'addr'. The 16 LSB bits of 'addr' are */ -/* ignored. */ -inline void set_address1(u8 *msa, u8 *addr) -{ - memcpy(msa + 4, addr, ETH_ALEN); -} - -/* This function sets the 'address2' field in the MAC header of the input */ -/* frame to the input MAC Address 'addr'. The 16 LSB bits of 'addr' are */ -/* ignored. */ -inline void set_address2(u8 *msa, u8 *addr) -{ - memcpy(msa + 10, addr, ETH_ALEN); -} - -/* This function sets the 'address3' field in the MAC header of the input */ -/* frame to the input MAC Address 'addr'. The 16 LSB bits of 'addr' are */ -/* ignored. */ -inline void set_address3(u8 *msa, u8 *addr) -{ - memcpy(msa + 16, addr, ETH_ALEN); -} - -/* This function extracts the MAC Address in 'address1' field of the MAC */ -/* header and updates the MAC Address in the allocated 'addr' variable. */ -inline void get_address1(u8 *msa, u8 *addr) -{ - memcpy(addr, msa + 4, ETH_ALEN); -} - -/* This function returns the pointer to the MAC Address in 'Address-1" field */ -/* of the MAC header. */ -inline u8 *get_address1_ptr(u8 *msa) -{ - return (msa + 4); -} - -/* This function extracts the MAC Address in 'address2' field of the MAC */ -/* header and updates the MAC Address in the allocated 'addr' variable. */ -inline void get_address2(u8 *msa, u8 *addr) -{ - memcpy(addr, msa + 10, ETH_ALEN); -} - -/* This function extracts the MAC Address in 'address3' field of the MAC */ -/* header and updates the MAC Address in the allocated 'addr' variable. */ -inline void get_address3(u8 *msa, u8 *addr) -{ - memcpy(addr, msa + 16, ETH_ALEN); -} - -/* This function returns the pointer to the MAC Address in 'Address-3" field */ -/* of the MAC header. */ -inline u8 *get_address3_ptr(u8 *msa) -{ - return (msa + 16); -} - -/* This function extracts the 'frame type' bits from the MAC header of the */ -/* input frame. */ -/* Returns the value in the LSB of the returned value. */ -inline enum BASICTYPE get_type(u8 *header) -{ - return ((enum BASICTYPE)(header[0] & 0x0C)); -} - -/* This function extracts the 'frame type and sub type' bits from the MAC */ -/* header of the input frame. */ -/* Returns the value in the LSB of the returned value. */ -inline enum TYPESUBTYPE get_sub_type(u8 *header) -{ - return ((enum TYPESUBTYPE)(header[0] & 0xFC)); -} - -/* This function extracts the 'to ds' bit from the MAC header of the input */ -/* frame. */ -/* Returns the value in the LSB of the returned value. */ -inline u8 get_to_ds(u8 *header) -{ - return (header[1] & 0x01); -} - -/* This function extracts the 'from ds' bit from the MAC header of the input */ -/* frame. */ -/* Returns the value in the LSB of the returned value. */ -inline u8 get_from_ds(u8 *header) -{ - return ((header[1] & 0x02) >> 1); -} - -/* This function extracts the 'power management' bit from the MAC header of */ -/* the input frame. */ -/* Returns the value in the LSB of the returned value. */ -inline u8 get_pwr_mgt(u8 *header) -{ - return ((header[1] & 0x10) >> 4); -} - -/* This function compares the address with the (last bit on air) BIT24 to */ -/* determine if the address is a group address. */ -/* Returns true if the input address has the group bit set. */ -inline bool is_group(u8 *addr) -{ - if ((addr[0] & BIT0) != 0) - return true; - - return false; -} - -inline bool is_sub_type_null_prot(u16 frm_type) -{ - if (frm_type == QOS_NULL_FRAME) - return true; - - return false; -} - -/* This function extracts the 'protocol version' bits from the MAC header of */ -/* the input frame. */ -/* Returns the value in the LSB of the returned value. */ -inline u8 get_protocol_version(u8 *header) -{ - return header[0] & 0x03; -} - -/* This function is used to handle the Address4 field in the header. */ -/* This checks the from and to DS bits in the header and if both are set */ -/* returns true, false otherwise */ -inline bool check_from_to_ds(struct wlan_rx *wlan_rx) -{ - if (wlan_rx->u8frm_ds && wlan_rx->u8to_ds) - return true; - - return false; -} - -/* This function compares two given MAC addresses (m1 and m2). */ -/* Returns bool, true if the two addresses are same and false otherwise. */ -inline bool mac_addr_cmp(u8 *m1, u8 *m2) -{ - if (memcmp(m1, m2, 6) == 0) - return true; - - return false; -} - -/* In AP/STA mode, check if the packet is from this BSS, once state is ENABLED */ -inline bool check_bssid_match(struct wlan_rx *strWlan_rx) -{ - struct linux_wlan *pd = g_linux_wlan; - u8 *u8macaddr = NULL; - - /* TODO: add FSM */ - /* if((get_mac_state() == ENABLED) && (strWlan_rx->type != CONTROL)) */ - if (strWlan_rx->enumType != CONTROL) { - /* Management frames are processed (probe request may have broadcast */ - /* cast BSSID, coalescing may be required) */ - if (strWlan_rx->enumType == MANAGEMENT) - return true; - - /* Warning: temperorary untill FSM is implemented */ - if ((pd->wilc_netdev) == NULL) - return false; - - /** - * get the bssid address, since we are th AP , the dev address is the BSSID - **/ - /* PRINT_D(HOSTAPD_DBG, "Calling cfg_get to get MAC_ADDR\n"); */ - u8macaddr = (u8 *) pd->wilc_netdev->dev_addr; - /* PRINT_D(HOSTAPD_DBG, "%2x.%2x.%2x.%2x.%2x.%2x.\n",u8macaddr[0],u8macaddr[1],u8macaddr[2],u8macaddr[3],u8macaddr[4],u8macaddr[5]); */ - - if (mac_addr_cmp(strWlan_rx->u8bssid, u8macaddr) == false) - return false; - } - - return true; -} - -/* This function extracts the updates the SA, DA & BSSID address pointers to */ -/* addr1, addr2 & addr3 fields in the WLAN RX structure. */ -inline void set_SA_DA_BSSID_ptr(struct wlan_rx *strWlan_rx) -{ - u8 frm_ds = strWlan_rx->u8frm_ds; - u8 to_ds = strWlan_rx->u8to_ds; - - if ((to_ds == 0) && (frm_ds == 0)) { - strWlan_rx->u8sa = strWlan_rx->u8addr2; - strWlan_rx->u8da = strWlan_rx->u8addr1; - strWlan_rx->u8bssid = strWlan_rx->u8addr3; - } else if ((to_ds == 0) && (frm_ds == 1)) { - strWlan_rx->u8sa = strWlan_rx->u8addr3; - strWlan_rx->u8da = strWlan_rx->u8addr1; - strWlan_rx->u8bssid = strWlan_rx->u8addr2; - } else if ((to_ds == 1) && (frm_ds == 0)) { - strWlan_rx->u8sa = strWlan_rx->u8addr2; - strWlan_rx->u8da = strWlan_rx->u8addr3; - strWlan_rx->u8bssid = strWlan_rx->u8addr1; - } - - strWlan_rx->u8ta = strWlan_rx->u8addr2; -} - -/* This function checks if QoS bit is set in the given QoS frame */ -inline bool is_qos_bit_set(u8 *msa) -{ - return (msa[0] & 0x80) ? true : false; -} - -/* This function sets the 'more data' bit in the MAC header of the input */ -/* frame to the LSB of the given value. */ -/* The bit position of the 'more data' bit in the 'frame control field' of */ -/* the MAC header is represented by the bit pattern 0x00100000. */ -inline void set_more_data(u8 *header, u8 more_data) -{ - header[1] &= 0xDF; - header[1] |= (more_data << 5); -} - -/* This function sets the end of service period bit */ -inline void set_qos_prot(u8 *msa) -{ -#if 0 /* def MAC_WMM */ - set_eosp(msa); -#endif /* MAC_WMM */ -} - -/* This function sets the AID0 bit or the Bit 7 in bit map control according */ -/* to the type given as input. */ -inline void set_dtim_bit(u8 type) -{ - if (type == AID0_BIT) - strBeaconInfo.u8vbmap[TIM_OFFSET] |= 0x1; /* AID = 0 */ - else - strBeaconInfo.u8vbmap[BMAP_CTRL_OFFSET] |= 0x1; /* Set multicast bit */ -} - -/* This function resets the AID0 bit or Bit 7 in bit map control according */ -/* to the type given as input. */ -inline void reset_dtim_bit(u8 type) -{ - if (type == AID0_BIT) - strBeaconInfo.u8vbmap[TIM_OFFSET] &= 0xFE; /* AID = 0 */ - else - strBeaconInfo.u8vbmap[BMAP_CTRL_OFFSET] &= 0xFE; /* Reset multicast bit */ -} - -/* This function extracts the 'order' bit from the frame control field */ -/* within the MAC header. */ -inline u8 get_order_bit(u8 *header) -{ - return ((header[1] & 0x80) >> 7); -} - -/* This function check whether the MAC header contains HT control field */ -inline bool is_ht_frame(u8 *header) -{ - if ((true == is_qos_bit_set(header)) && (1 == get_order_bit(header))) - return true; - - return false; -} - -/* This function extracts the destination MAC Address from the incoming WLAN */ -/* packet based on the 'to ds' bit,and updates the MAC Address in the */ -/* allocated 'addr' variable. */ -inline void get_DA(u8 *data, u8 *da) -{ - if (get_to_ds(data) == 1) - get_address3(data, da); - else - get_address1(data, da); -} - -/* This function extracts the destination MAC Address from the incoming WLAN */ -/* packet based on the 'to ds' bit and returns the pointer to the same. */ -inline u8 *get_DA_ptr(u8 *data) -{ - if (get_to_ds(data) == 1) - return get_address3_ptr(data); - - return get_address1_ptr(data); -} - -/* Get the MAC header length depending on the protocol used */ -inline u8 get_mac_hdr_len(u8 *msa) -{ - u8 mac_hdr_len = MAC_HDR_LEN; - - /* The MAC Header len is 26 only when in QOD Data frames */ - if ((is_qos_bit_set(msa) == true) && (get_type(msa) == DATA_BASICTYPE)) - mac_hdr_len += QOS_CTRL_FIELD_LEN; - - if (true == is_ht_frame(msa)) - mac_hdr_len += HT_CTRL_FIELD_LEN; - - return mac_hdr_len; -} - -/* update the appropriate PS queue counters after a Tx complete interrupt */ -/* returns true if TIM needs to be reset */ -inline bool update_ps_counts_txcomp(struct WILC_ieee80211_sta *ae, u8 *msa) -{ - bool retval = false; - - /* TBD: Device a method avoid all this processing in every Tx comp */ - /* interrupt */ -#if 0 /* def MAC_WMM */ - BOOL_T del_ena = false; - - if (true == is_qos_bit_set(msa)) { - u8 priority = get_tid_value(msa); - - if (true == check_ac_is_del_en(ae, priority)) - del_ena = true; - } - - if (true == del_ena) { - /* Check the no. of packets queued for a USP, if an USP is in */ - /* progress. Clear the flag if all packets queued in an USP are */ - /* transmitted */ - /* This is done to ignore multiple trigger frames during an USP */ - /* "USP_in_progress" flag is cleared when the STA wakes up */ - - if (ae->USP_in_progress == true) { - ae->num_USP_pkts_qed--; - if (ae->num_USP_pkts_qed == 0) - ae->USP_in_progress = false; - } - } else -#endif /* MAC_WMM */ - { - /* Non Delivery PS Q Frame are sent only on PS poll */ - /* Clear the Flag for PS poll response */ - /* ae->ps_poll_rsp_qed = false; */ - } - - if (ae->num_qd_pkt) - ae->num_qd_pkt--; - -#if 0 /* def MAC_WMM */ - if (is_all_ac_del(ae) == true) { - if ((ae->num_ps_pkt + ae->num_qd_pkt) == 0) - retval = true; - } else -#endif /* MAC_WMM */ - { - /* If no packets are queued in Sw PSQ or Hw for the */ - /* station, reset TIM bit */ - if ((ae->num_ps_pkt + ae->num_qd_pkt) == 0) - retval = true; - } - - return retval; -} - -/* Adjust length and data offset of the received packet */ -/* Returns the length of the frame header. */ -inline u16 modify_frame_length(u8 *msa, u16 *rx_len, u16 *data_len) -{ - unsigned int mac_hdr_len = get_mac_hdr_len(msa); - - /* Start of data is end of mac header offseted by the security header */ - *data_len = *rx_len - mac_hdr_len; - - /* If MAC header length is not a multiple of 4 (QOS is Enabled), then */ - /* the H/w will be offsetting two extra bytes after the header to make */ - /* it word aligned */ - if (mac_hdr_len & 3) - mac_hdr_len += 2; - - return mac_hdr_len; -} - -inline void flush_ps_queues(struct WILC_ieee80211_sta *ae) -{ - struct tx_complete_data *tx_dscr = NULL; - - /* Free the elements in Legacy PS queue */ - while (NULL != (tx_dscr = remove_list_element_head(&(ae->ps_q_lgcy)))) { - if (tx_dscr->skb) - dev_kfree_skb(tx_dscr->skb); - - kfree(tx_dscr); - - g_num_ps_pkt--; - } - -#if 0 /* def MAC_WMM */ - /* Free the elements in Delivery enabled PS queue */ - while (NULL != (tx_dscr = remove_list_element_head(&(ae->ps_q_del_ac)))) { - /* Free the buffers associated with the transmit descriptor */ - free_tx_dscr(tx_dscr); - g_num_ps_pkt--; - } - ae->num_ps_pkt_del_ac = 0; - ae->USP_in_progress = false; -#endif /* MAC_WMM */ -} - -/* This function handles the change of state of a station from power save to */ -/* active state by requeing all buffered packets to the H/w queue. */ -/* It also reduces the global count of power save stations and requeues all */ -/* multicast/broadcast packets if this count becomes 0. */ -inline void handle_ps_sta_change_to_active(struct WILC_ieee80211_sta *ae) -{ - enum REQUEUE_STATUS status = RE_Q_ERROR; - - /* handle_ba_active_ap_prot(ae); */ - - /* Continue to requeue buffered packets from the station's power save */ - /* queue to the MAC H/w queue till the power save queue is empty. */ - - /* status = handle_ps_sta_change_to_active_prot(ae); */ -/* - * if(status == PKT_NOT_REQUEUED) - * { - * return; - * } - * else*/ - { - while ((status = requeue_ps_packet(ae, &(ae->ps_q_lgcy), true, false)) - == PKT_REQUEUED) - ; -#if 0 /* def PS_DSCR_JIT */ - /* This path is not valid currently */ - /* May be valid if descriptor are not buffered and are */ - /* created just in time before transmission */ - if (status == PKT_NOT_REQUEUED) - handle_requeue_pending_packet(ae, &g_ps_pending_q, true); - -#endif /* PS_DSCR_JIT */ - } - - /* To be safe flush all the PS queues. Though they should have been */ - /* handled in the requeuing functions */ - /* Reset other variables and TIM */ - flush_ps_queues(ae); - ae->ps_poll_rsp_qed = false; - check_and_reset_tim_bit(ae->u16AID); - - /* Decrement the global power save station count */ - g_num_sta_ps--; - - /* If there are no stations in Power save mode, requeue all multicast/ */ - /* broadcast packets. */ - if (g_num_sta_ps == 0) - while (requeue_ps_packet(NULL, &g_mc_q, true, false) == PKT_REQUEUED) - ; -} - -/* This function handles the change of state of a station from active to */ -/* power save state by removing all packets from the H/w queue and buffering */ -/* these in the S/w power save queue. Also ii increments the global count of */ -/* power save stations. In case this is the only station in power save state */ -/* the multicast/broadcast packets also need to be removed from the H/w */ -/* queues and buffered in the multicast queue. */ -inline void handle_ps_sta_change_to_powersave(struct WILC_ieee80211_sta *ae) -{ - bool ps_del_en_ac = false; - - /* TBD. Remove packets from all H/w queue destined for this station and */ - /* add to the ae queue. */ - - if (g_num_sta_ps == 0) { - /* TODO: add mc/bc frames from hardware tx queue to ps queue */ - /* TBD - no stations were in power save. mc/bc packets need to be */ - /* removed and added to g_mc_q */ - } - - /* To be safe flush all the PS queues. Though they should have been */ - /* handled in the requeuing functions */ - /* Reset other variables and TIM */ - flush_ps_queues(ae); - ae->ps_poll_rsp_qed = false; - - /* TODO: decide wither to set flags here */ - /* update_ps_flags_ap(ae, false, num_elements_moved,ps_del_en_ac); */ - - /* Power Save buffering for 11n protocol related */ - /* handle_ps_sta_change_to_powersave_prot(ae); */ - - /* Increment the global power save station count */ - g_num_sta_ps++; -} - -/* - * @brief This function checks the power save state of the station - * from all received packets. - * - * @details The power management bit in the received packet is - * checked and the association entry of the corresponding - * transmitting station is updated with the power save - * state. Also if there is any change in power save state - * the appropriate handling function is called. - * - * @param[in] 1) Pointer to association entry - * 2) Power Save value - * - * @return - * @author Abd Al-Rahman Diab - * @date 5 june 2013 - * @version 1.0 - */ -void check_ps_state(struct WILC_ieee80211_sta *ae, enum STA_PS_STATE ps) -{ - /* 1 - POWER_SAVE, 0 - ACTIVE */ - if ((ae == NULL) || (ae->ps_state == ps)) - /* There is no change in station power save mode. Do nothing. */ - return; - - /* Station has changed power save state. Update the entry and handle the */ - /* change as required. */ - ae->ps_state = ps; - - if (ps == ACTIVE_PS) - handle_ps_sta_change_to_active(ae); - else - handle_ps_sta_change_to_powersave(ae); - -} - -/* - * @brief filter_wlan_rx_frame - * @details This function filters the incoming wlan rx packet and - * sends the results of the operation. - * @param[in] 1) MAC header of incoming packet. - * 2) Pointer to rx descriptor - * 3) Pointer to wlan_rx structure - * @return True if the frame is to be discarded, False otherwise - * @author Abd Al-Rahman Diab - * @date 21 APRIL 2013 - * @version 1.0 - */ -bool filter_wlan_rx_frame(struct wlan_rx *strWlan_rx) -{ - struct WILC_ieee80211_sta *ae = (struct WILC_ieee80211_sta *)strWlan_rx->u8sa_entry; - u8 *msa = strWlan_rx->u8msa; - - if (strWlan_rx->enumType == DATA_BASICTYPE) { - if (ae == 0) - /* TODO: handle this station either by reporting to HOSTAPD or sending deauth frame */ - /* Send the De-authentication Frame to the station */ - /* send_deauth_frame(wlan_rx->ta, error); */ - - /* Return TRUE for filter frame */ - return true; - else if (ae->state != ASOC) - - /* TODO: handle this station either by reporting to HOSTAPD or sending disassoc frame */ - /* Send the Disassociation Frame to the station */ - /* send_disasoc_frame(wlan_rx->ta, error); */ - - /* Return TRUE for filter frame */ - return true; - - - /* This STA is active, set the count to 0 */ - ae->aging_cnt = 0; - } else { - if (ae != 0) { - - /* This STA is active, set the count to 0 */ - ae->aging_cnt = 0; - - } - } - return false; -} - -/* - * @brief WILC_Process_rx_frame - * @details handle incoming data & mgmt frames - * @param[in] u8Buff : pointer to frame - * u32Size : size of frame buffer - * @return 1 if it's data frame, 0 otherwise - * @author Abd Al-Rahman Diab - * @date 21 APRIL 2013 - * @version 1.0 - */ -void WILC_Process_rx_frame(u8 *u8Buff, unsigned int u32Size) -{ - struct wlan_rx strWlan_rx = {0}; - unsigned int min_pkt_len = MAC_HDR_LEN; /* null frame */ - u8 *mac_addr = g_linux_wlan->wilc_netdev->dev_addr; - - /* skip the host header offset */ - u8Buff += HOST_HDR_OFFSET; - - /* Extract Addresses from the MAC Header */ - get_address1(u8Buff, strWlan_rx.u8addr1); - get_address2(u8Buff, strWlan_rx.u8addr2); - get_address3(u8Buff, strWlan_rx.u8addr3); - - strWlan_rx.enumType = get_type(u8Buff); - strWlan_rx.u8frm_ds = get_from_ds(u8Buff); - strWlan_rx.u8to_ds = get_to_ds(u8Buff); - strWlan_rx.u8Sub_type = get_sub_type(u8Buff); - strWlan_rx.bIs_grp_addr = is_group(strWlan_rx.u8addr1); - - strWlan_rx.u16rx_len = u32Size; - strWlan_rx.u8msa = u8Buff; - - /* Update the SA, DA & BSSID pointers to corresponding addr1, addr2 or */ - /* addr3 fields of wlan_rx structure. */ - set_SA_DA_BSSID_ptr(&strWlan_rx); - - /* TODO: Update the statistics for get_station */ - /* update_debug_rx_stats(status); */ - - /* Exception case 1: Maximum length exceeded */ - if (strWlan_rx.u16rx_len > MAX_MSDU_LEN) { - PRINT_D(HOSTAPD_DBG, "HwEr:RxMaxLenExc:%d > %d\n\r", strWlan_rx.u16rx_len, MAX_MSDU_LEN); - /* g_mac_stats.pwrx_maxlenexc++; */ - /* Do nothing and return */ - return; - } - - /* Exception case 2: Protocol Version Match Fail */ - if (get_protocol_version(u8Buff) != PROTOCOL_VERSION) { - PRINT_D(HOSTAPD_DBG, "HwEr:RxFrmHdrProtVerFail\n\r"); - /* g_mac_stats.rxfrmhdrprotverfail++; */ - /* Do nothing and return */ - return; - } - - /* Exception case 3: Address-4 Field Present */ - if (check_from_to_ds(&strWlan_rx) == true) { - PRINT_D(HOSTAPD_DBG, "HwEr:RxFrmHdrAddr4Prsnt\n\r"); - /* g_mac_stats.rxfrmhdraddr4prsnt++; */ - /* Do nothing and return */ - return; - } - - /* Exception case 4: BSSID Match Fail */ - if (check_bssid_match(&strWlan_rx) == false) { - if (strWlan_rx.bIs_grp_addr == false) - PRINT_D(HOSTAPD_DBG, "HwEr:RxFrmHdrBssidChkFail\n\r"); - /* g_mac_stats.rxfrmhdrbssidchkfail++; */ - /* Do nothing and return */ - return; - } - - if (strWlan_rx.u8Sub_type == PS_POLL) - min_pkt_len = PS_POLL_LEN - FCS_LEN; - - /* Exception case 6: Less than minimum acceptable length */ - if (strWlan_rx.u16rx_len < min_pkt_len) { - PRINT_D(HOSTAPD_DBG, "HwEr:RxMinLenExc: %d < %d\n\r", strWlan_rx.u16rx_len, min_pkt_len); - /* g_mac_stats.pwrx_minlenexc++; */ - /* Do nothing and return */ - return; - } - - /* TODO: decide if i need these 2 elements */ - /* Extract required parameters from the frame header */ - /* wlan_rx.priority_val = get_priority_value(msa); */ - /* wlan_rx.service_class = get_ack_policy(msa, wlan_rx.addr1); */ - - strWlan_rx.u8sa_entry = find_entry(strWlan_rx.u8addr2); - - /* Exception case 8: Not a BC/MC frame and not directed */ - if ((strWlan_rx.bIs_grp_addr == false) && - (mac_addr_cmp(strWlan_rx.u8addr1, mac_addr) == false)) { - u8 *addr1 = strWlan_rx.u8addr1; - - PRINT_D(HOSTAPD_DBG, "HwEr:RxUnexpFrm:%x:%x:%x:%x:%x:%x\n\r", addr1[0], addr1[1], addr1[2], - addr1[3], addr1[4], addr1[5]); - /* g_mac_stats.rxunexpfrm++; */ - /* Do nothing and return */ - return; - } - - /* Filter the frame based on mode of operation */ - if (filter_wlan_rx_frame(&strWlan_rx) == true) - /* g_mac_stats.pewrxft++; */ - return; - - /* Modify the frame length and get the frame header length depending on */ - /* the QoS and HT features enabled. */ - strWlan_rx.u8hdr_len = modify_frame_length(strWlan_rx.u8msa, - &(strWlan_rx.u16rx_len), &(strWlan_rx.u16data_len)); - - /* Check for the type of frame and process accordingly */ - if ((strWlan_rx.bIs_grp_addr == false) && (strWlan_rx.enumType == CONTROL)) { - /* TODO: we don't handle BA control frames , so we only need to handle PS POLL frames with Power managemnet */ - if (handle_ps_poll(&strWlan_rx) == false) { - /* TODO: add support for 11n */ - /* Handle control frames other than PS Poll */ - /* ap_enabled_rx_control((u8 *)req); */ - } - } else if (strWlan_rx.enumType == MANAGEMENT) { - unsigned int *u32header = 0; - - /* TODO: update statistics */ - /* Update receive MIB counters */ - /* mincr_ReceivedFragmentCount(); */ - - /* Get WILC header */ - /* u32header = (strWlan_rx.u8msa)-HOST_HDR_OFFSET; */ - - WILC_WFI_monitor_rx(strWlan_rx.u8msa, strWlan_rx.u16rx_len); - } else if (strWlan_rx.enumType == DATA_BASICTYPE) { - /* TODO: MEASURE_PROCESSING_DELAY */ - /* - * #ifdef MEASURE_PROCESSING_DELAY - * g_delay_stats.numrxdscr += num_dscr; - * #endif // MEASURE_PROCESSING_DELAY - * - * - * // TODO: update statistics - * // Update receive MIB counters - * // if(wlan_rx.is_grp_addr == true) { - * print_log_debug_level_1("\n[DL1][INFO][Rx] {Multicast WLAN Rx}"); - * mincr_MulticastReceivedFrameCount(); - * } else { - * print_log_debug_level_1("\n[DL1][INFO][Rx] {Unicast WLAN Rx}"); - * mincr_ReceivedFragmentCount(); - * } - * - * update_rx_mib_prot(msa, wlan_rx.data_len);*/ - - ap_enabled_rx_data(&strWlan_rx); - } -} - -/* - * @brief ap_enabled_rx_data - * @details This function handles the incoming DATA frame to send to the host. - * @author Abd Al-Rahman Diab - * @date 09 APRIL 2013 - * @version 1.0 - */ -void ap_enabled_rx_data(u8 *msg) -{ - /* u8 priority_rx = 0; */ - enum STA_PS_STATE ps = ACTIVE_PS; - u8 data_trailer = 0; - u8 *buffer = 0; - u8 *host_hdr = 0; - struct wlan_rx *wlan_rx = (struct wlan_rx *)msg; - u8 *msa = wlan_rx->u8msa; - struct WILC_ieee80211_sta *da_ae = 0; - struct WILC_ieee80211_sta *sa_ae = 0; - struct tx_complete_data *tx_data = NULL; - /* msdu_desc_t *frame_desc = 0; */ - /* CIPHER_T ct = (CIPHER_T)wlan_rx->ct; */ - /* MSDU_PROC_STATUS_T status = PROC_ERROR; */ - enum TYPESUBTYPE frm_type = DATA; - /* msdu_indicate_t msdu = {{0},}; */ - /* msdu_proc_state_t msdu_state = {0}; */ - - /* Get association entry for the source address */ - sa_ae = (struct WILC_ieee80211_sta *)wlan_rx->u8sa_entry; - - /* Power management checks */ - ps = (enum STA_PS_STATE)get_pwr_mgt(msa); - frm_type = (enum TYPESUBTYPE)wlan_rx->u8Sub_type; - - /* TODO: add PS */ - /* Check if the received function is the Null function Packet */ - if ((frm_type == NULL_FRAME) || - (is_sub_type_null_prot(frm_type) == true)) { - check_ps_state(sa_ae, ps); - -/* #ifdef DEBUG_MODE */ - /* g_mac_stats.pewrxnf++; */ -/* #endif / * DEBUG_MODE * / */ - return; - } - - /* Get the priority of the incoming frame */ - /* priority_rx = wlan_rx->priority_val; */ - /* msdu.priority = priority_rx; */ - - /* Check for WMM-PS trigger frame and process accordingly */ - /* pwr_mgt_handle_prot(sa_ae, ps, priority_rx, msa); */ - - /* TODO: add PS */ - /* Check the Power Save Bit in the receive frame */ - check_ps_state(sa_ae, ps); - - /* Create the MSDU descriptors for the received frame */ - - /* Create the MSDU decsriptor */ - /* status = update_msdu_info(wlan_rx, &msdu, &msdu_state); */ - - /* Get the frame descriptor pointer */ - /* frame_desc = &(msdu.frame_desc); */ - - /* Get association entry based on the source address to determine */ - /* the next path of the packet. */ - sa_ae = (struct WILC_ieee80211_sta *)find_entry(wlan_rx->u8sa); - da_ae = (struct WILC_ieee80211_sta *)find_entry(wlan_rx->u8da); - - if (da_ae != 0) { - /* u8 key_type = 0; */ - /* bool wlan2wlan = false; */ - bool use_same_buffer = true; - - /* CipherType is reset to no encryption and is set as per the */ - /* policy used for the out going sta */ - /* ct = NO_ENCRYP; */ - - /* Set the Key type required for transmission */ - /* key_type = UCAST_KEY_TYPE; */ - - /* If the station is associated with the AP, the packet is put */ - /* onto the wireless network. */ - if (da_ae->state == ASOC) { - /* TODO: recheck this */ - /* If the received frame is not a QoS frame, create a */ - /* copy of the frame in a separate buffer to fit the QoS */ - /* header. */ - /* if(is_qos_bit_set(msa) == false) */ - /* use_same_buffer = false; */ - - /* The MAC Header offset field in TX-Dscr is 8 bits long. */ - /* Hence a frame copy is created if the MAC Header field */ - /* exceeds 256 when it is created in place. */ - /* if(frame_desc->data_offset > 255) */ - /* use_same_buffer = false; */ - - /* TODO: security stuff */ - /* Before forwarding the packet onto the WLAN interface */ - /* security checks needs to performed on the states of the */ - /* transmitting and receiving stations */ - /* wlan2wlan = check_sec_ucast_wlan_2_wlan_ap(da_ae, sa_ae, &ct, */ - /* &data_trailer); */ - - /* Update length of the frame to accommodate the security */ - /* trailers if any. */ - /* update_frame_length(frame_desc, data_trailer); */ - - /* if(wlan2wlan == true) */ - /* { */ - - /* send this packet to wlan interface */ - tx_data = kmalloc(sizeof(struct tx_complete_data), GFP_ATOMIC); - - if (tx_data == NULL) { - PRINT_ER("Failed to allocate memory for tx_data structure\n"); - return; - } - - /* Set Address1 field in the WLAN Header with destination address */ - set_address1(msa, wlan_rx->u8da); - - /* Set Address2 field in the WLAN Header with the BSSID */ - set_address2(msa, wlan_rx->u8bssid); - - /* Set Address2 field in the WLAN Header with the source address */ - set_address3(msa, wlan_rx->u8sa); - - tx_data->buff = msa; - tx_data->size = wlan_rx->u16rx_len; - tx_data->skb = NULL; - WILC_Xmit_data((void *)tx_data, WLAN_TO_WLAN); - - /* } */ - - /* TODO: update stat */ - /* g_mac_stats.pewrxu++; */ - } - } else { - /* Broadcast/Multicast frames need to be forwarded on WLAN also */ - if (is_group(wlan_rx->u8da) == true) { - /* CIPHER_T grp_ct = NO_ENCRYP; */ - - /* Before forwarding the packet on WLAN and HOST interface */ - /* security checks needs to performed on the states of the */ - /* transmitting station */ - /* if(ap_check_sec_tx_sta_state(sa_ae) != true) */ - /* { */ - /* continue; */ - /* } */ - -/* #ifdef DEBUG_MODE */ - /* g_mac_stats.pewrxb++; */ -/* #endif / * DEBUG_MODE * / */ - - /* Before forwarding the packet on the WLAN interface */ - /* security checks needs to performed on the states of the */ - /* transmitting station */ - /* data_trailer = check_sec_bcast_wlan_2_wlan_ap(&grp_ct); */ - - /* Update the length of the frame to accommodate the */ - /* security trailers if any. */ - /* update_frame_length(frame_desc, data_trailer); */ - - tx_data = kmalloc(sizeof(struct tx_complete_data), GFP_ATOMIC); - - if (tx_data == NULL) { - PRINT_ER("Failed to allocate memory for tx_data structure\n"); - return; - } - - /* Set Address1 field in the WLAN Header with destination address */ - set_address1(msa, wlan_rx->u8da); - - /* Set Address2 field in the WLAN Header with the BSSID */ - set_address2(msa, wlan_rx->u8bssid); - - /* Set Address2 field in the WLAN Header with the source address */ - set_address3(msa, wlan_rx->u8sa); - - tx_data->buff = msa; - tx_data->size = wlan_rx->u16rx_len; - tx_data->skb = NULL; - WILC_Xmit_data((void *)tx_data, WLAN_TO_WLAN); - } - /* else */ - /* { */ - /* Packet is a Unicast packet to the AP */ -/* #ifdef DEBUG_MODE */ - /* g_mac_stats.pewrxu++; */ -/* #endif / * DEBUG_MODE * / */ - /* } */ - - /* Check for SNAP header at beginning of the data and set the */ - /* data pointer and length accordingly. */ - if (true == is_snap_header_present(wlan_rx)) - /* If received packet is a security handshake packet process */ - /* it in the security layer */ - /*if(is_sec_handshake_pkt_ap(sa_ae, frame_desc->buffer_addr, - * frame_desc->data_offset, - * frame_desc->data_len, - * (CIPHER_T)wlan_rx->ct) == true) - * { - * continue; - * }*/ - - /* Adjust the frame to account for the SNAP header */ - adjust_for_snap_header(wlan_rx); - /* else */ - /* { */ - /* Before forwarding the packet on WLAN and HOST interface */ - /* security checks needs to performed on the states of the */ - /* transmitting station */ - /* if(ap_check_sec_tx_sta_state(sa_ae) != true) */ - /* { */ - /* continue; */ - /* } */ - /* } */ - - /* Call MSDU Indicate API with the MSDU to be sent to the host */ - - /* msdu_indicate_ap(&msdu); */ - host_hdr = msa + ((wlan_rx->u8hdr_len) - ETHERNET_HDR_LEN); - - memcpy(host_hdr, wlan_rx->u8da, ETH_ALEN); - memcpy(host_hdr + 6, wlan_rx->u8sa, ETH_ALEN); - - buffer = msa + wlan_rx->u8hdr_len - ETHERNET_HDR_LEN; - - frmw_to_linux(buffer, (wlan_rx->u16data_len) + ETHERNET_HDR_LEN); - } -} - -static void linux_FH_wlan_tx_complete(void *priv, int status) -{ - struct tx_complete_data *pv_data = (struct tx_complete_data *)priv; - - if (status == 1) - PRINT_D(TX_DBG, "Packet sent successfully - Size = %d - Address = %p - SKB = %p\n", pv_data->size, pv_data->buff, pv_data->skb); - else - PRINT_D(TX_DBG, "Couldn't send packet - Size = %d - Address = %p - SKB = %p\n", pv_data->size, pv_data->buff, pv_data->skb); - - /* Power Management */ - handle_ps_tx_comp_ap(pv_data); - - /* Free the SK Buffer, its work is done */ - if (pv_data->skb) - dev_kfree_skb(pv_data->skb); - - kfree(pv_data); -} - -/* - * @brief WILC_Xmit_data - * @details This function transmit the data frames to firmware. - * @Processing This function computes hash value of a given MAC address. - * This value is used to access the hash table. - * @return hash value - * @author Abd Al-Rahman Diab - * @date 09 APRIL 2013 - * @version 1.0 - */ -int WILC_Xmit_data(void *ptx_data, enum Data_Interface InterfaceType) -{ - struct tx_complete_data *tx_data = (struct tx_complete_data *)ptx_data; - struct sk_buff *skb = tx_data->skb; - struct sk_buff *xmit_skb; - struct ethhdr *eth; - struct WILC_ieee80211_sta *asoc_entry = NULL; - u8 ethsaddr[ETH_ALEN]; - u8 ethdaddr[ETH_ALEN]; - u8 mac_hdr_len; - u8 *da; - u8 service_class, is_qos, is_htc, is_amsdu; - u8 priority = BEST_EFFORT_PRIORITY; /* TODO: this should not be fixed */ - u8 *BSSID = g_linux_wlan->wilc_netdev->dev_addr; - u8 *snap_hdr; - u8 *mac_hdr; - u8 *data_start; - u16 eth_type; - u16 pkt_len = 0; - u16 data_len = 0; - u16 u16size = 0; - - int QueueCount = 0; - - if (InterfaceType == HOST_TO_WLAN) { - pkt_len = skb->len; - - eth = (struct ethhdr *)(skb->data); - - /* Set the destination address field in the WLAN Tx Request structure. */ - memcpy(ethdaddr, ð->h_dest, ETH_ALEN); - - /* For AP, the source address should be sent with the frame. */ - memcpy(ethsaddr, ð->h_source, ETH_ALEN); - - /* Here check whether the destination is associated, */ - /* If its not associated, then drop the packet */ - - /* For unicast packets, check if the destination STA is associated. */ - if (is_group(ethdaddr) == false) { - /* Get association entry for association state */ - asoc_entry = (struct WILC_ieee80211_sta *)find_entry(ethdaddr); - - /* If the destination STA is not associated free the data packet and */ - /* return. */ - if ((asoc_entry == 0) || (asoc_entry->state != ASOC)) { - /* Wait for station to be associated */ - - /* Free the SK Buffer */ - dev_kfree_skb(skb); - kfree(tx_data); - return; - } - - service_class = NORMAL_ACK; - } else { - service_class = BCAST_NO_ACK; - } - /* allocate new skb to accomodate the MAC header */ - xmit_skb = dev_alloc_skb((skb->len) + ETH_ETHERNET_HDR_OFFSET); - - /* Check whether QoS option is implemented */ - /* TODO: 11n is not enabled yet */ - is_qos = 0; /* is_qos_required(sta_index); */ - - /* Check whether receiver is HT capable */ - /* HTC is not supported yet */ - is_htc = 0; - - /* we currently don't support amsdu */ - is_amsdu = 0; - - mac_hdr = xmit_skb->data; - } else if (InterfaceType == WLAN_TO_WLAN) { - /* TODO: try to eliminate the copying here to improve performance */ - - skb = dev_alloc_skb(tx_data->size); - - memcpy(skb->data, tx_data->buff, tx_data->size); - - /* frames coming from wlan are freed within vmm handle rxq - * null frames from ps-poll are freed here - */ - if (get_sub_type(tx_data->buff) == NULL_FRAME) - kfree(tx_data->buff); - - /* Check whether receiver is HT capable */ - /* HTC is not supported yet */ - is_htc = 0; - - /* we currently don't support amsdu */ - is_amsdu = 0; - - mac_hdr = skb->data; - - #if 0 - if (is_group(da) == false) - service_class = NORMAL_ACK; - else - service_class = BCAST_NO_ACK; - - #endif - - tx_data->buff = skb->data; - tx_data->skb = skb; - - } else if (InterfaceType == MONITOR_TO_WLAN) { - mac_hdr = tx_data->buff; - - /* Get the Destination address */ - da = get_DA_ptr(mac_hdr); - - /* Get association entry for association state */ - asoc_entry = (struct WILC_ieee80211_sta *)find_entry(da); - - if (buffer_tx_packet(asoc_entry, da, priority, tx_data) == false) - wilc_wlan_txq_add_mgmt_pkt((void *)tx_data, tx_data->buff, tx_data->size, linux_FH_wlan_tx_complete); - - return; - } - - mac_hdr_len = set_mac_hdr_prot(mac_hdr, priority, - service_class, is_qos, - is_htc, is_amsdu); - - set_from_ds(mac_hdr, 1); - - if (InterfaceType == HOST_TO_WLAN) { - /* TODO: add security */ - /* if(ct != NO_ENCRYP) */ - /* set_wep(mac_hdr, 1); */ - - /* Set Address1 field in the WLAN Header with destination address */ - set_address1(mac_hdr, ethdaddr); - - /* Set Address2 field in the WLAN Header with the BSSID */ - set_address2(mac_hdr, BSSID); - - /* Set Address2 field in the WLAN Header with the source address */ - set_address3(mac_hdr, ethsaddr); - - /* Get the Destination address */ - da = get_DA_ptr(mac_hdr); - - /* SNAP header needs to be set for IP/ARP packets. Note that there is */ - /* sufficient space allocated for SNAP and MAC header in the buffer. */ - - /* Extract the type of the ethernet packet and set the SNAP header */ - /* contents. Also set the data pointer field in the WLAN Tx Request */ - /* structure, as required, to the correct value. */ - - #ifdef LITTLE_ENDIAN - eth_type = eth->h_proto; - #else - eth_type = (eth->h_proto >> 8) | (eth->h_proto << 8); - #endif - - if ((eth_type == ARP_TYPE) || - (eth_type == IP_TYPE) || - (eth_type == ONE_X_TYPE) || - (eth_type == VLAN_TYPE) || - (eth_type == LLTD_TYPE)) { - /* The SNAP header is set before the ethernet payload. */ - /* */ - /* +--------+--------+--------+----------+---------+---------------+ */ - /* | DSAP | SSAP | UI | OUI | EthType | EthPayload | */ - /* +--------+--------+--------+----------+---------+---------------+ */ - /* | 1 byte | 1 byte | 1 byte | 3 bytes | 2 bytes | x bytes | */ - /* +--------+--------+--------+----------+---------+---------------+ */ - /* <---------------- SNAP Header ----------------> */ - /* <------------------------ 802.11 Payload -----------------------> */ - snap_hdr = xmit_skb->data + mac_hdr_len; - - *snap_hdr++ = 0xAA; - *snap_hdr++ = 0xAA; - *snap_hdr++ = 0x03; - *snap_hdr++ = 0x00; - *snap_hdr++ = 0x00; - *snap_hdr++ = 0x00; - *snap_hdr++ = (u8)((eth_type >> 8) & 0x00ff); - *snap_hdr++ = (u8)(eth_type & 0x00ff); - - /* Set the data length parameter to the MAC data length only (does */ - /* not include headers) */ - data_len = pkt_len + mac_hdr_len - ETHERNET_HDR_LEN + SNAP_HDR_LEN; - - data_start = snap_hdr; - - /* Note that the Ethernet Type field is already set in the ethernet */ - /* header and follows this. */ - } else { - /* Set the data length parameter to the MAC data length only (does */ - /* not include headers) */ - data_len = pkt_len + mac_hdr_len - ETHERNET_HDR_LEN; - - data_start = xmit_skb->data + mac_hdr_len; - } - - memcpy(data_start, (skb->data) + ETHERNET_HDR_LEN, pkt_len - ETHERNET_HDR_LEN); - - dev_kfree_skb(skb); - - tx_data->buff = xmit_skb->data; - tx_data->size = data_len; - tx_data->skb = xmit_skb; - } else { - /* Get the Destination address */ - da = get_DA_ptr(mac_hdr); - - /* Get association entry for association state */ - asoc_entry = (struct WILC_ieee80211_sta *)find_entry(da); - } - - if (buffer_tx_packet(asoc_entry, da, priority, tx_data) == false) - QueueCount = wilc_FH_wlan_txq_add_net_pkt((void *)tx_data, - tx_data->buff, - tx_data->size, - linux_FH_wlan_tx_complete); - - return QueueCount; -} - -/* - * @brief hash - * @details This function computes the hash value for given address. - * @Processing This function computes hash value of a given MAC address. - * This value is used to access the hash table. - * @return hash value - * @author Abd Al-Rahman Diab - * @date 09 APRIL 2013 - * @version 1.0 - */ -unsigned int hash(u8 *addr) -{ - unsigned int sum = 0; - unsigned int i = 0; - - for (i = 0; i < 6; i++) - sum += addr[i]; - - return sum % MAX_HASH_VALUES; -} - -/* - * @brief find_entry - * @details This function searches the table for an entry having the given key value. - * @Processing The hash value (val) for the given key is computed - * using the hash function. The table entry holding the - * given key is then searched. If such an entry is - * found the pointer to the entry stored in the table - * entry is returned. - * @return The element of the corresponding table entry, if an entry , having a key - * identical to the given key was found. - * Zero is returned if no matching entry is found. - * @author Abd Al-Rahman Diab - * @date 09 APRIL 2013 - * @version 1.0 - */ -void *find_entry(u8 *key) -{ - struct table_elmnt *tbl_ptr = 0; - unsigned int val = 0; - - /* Zero entry is fixed for Bcast/Mcast address */ - /* If the address is BCast/MCast Address, return 0 */ - if (key[0] & BIT0) - return 0; - - - /* Calculate hash value for the key */ - val = hash(key); - tbl_ptr = g_sta_table[val]; - - while (tbl_ptr) { - if (mac_addr_cmp(tbl_ptr->key, key) == true) - return tbl_ptr->element; - - tbl_ptr = tbl_ptr->next_hash_elmnt; - } - - return 0; -} - -/* - * @brief add_entry - * @details This function adds an entry to asoc table.. - * @Processing A table element is created. The entry and key values - * are set in table element and the table element is - * inserted in the appropriate hash bucket of association - * table. - * - * There is no maximum limit set for creation of assoc - * entries. But there is a maximum limit for number of - * associated stations, MAX_ELEMENTS. - * @author Abd Al-Rahman Diab - * @date 09 APRIL 2013 - * @version 1.0 - */ -void add_entry(void *entry, u8 *key) -{ - unsigned int val = 0; - struct table_elmnt *new_elm = 0; - - /* Create a buffer to hold table element */ - new_elm = kmalloc(sizeof(struct table_elmnt), GFP_ATOMIC); - - if (new_elm == NULL) - return; - - /* Compute the hash value */ - val = hash(key); - - /* Insert the element at head of the hash */ - memcpy(new_elm->key, key, ETH_ALEN); - - new_elm->next_hash_elmnt = g_sta_table[val]; - new_elm->element = entry; - - g_sta_table[val] = new_elm; -} - -/* - * @brief delete_entry - * @details This function deletes the entry having the given key - * value from the table. The space occupied by the entry - * is not freed here. - * - * @Processing The hash value (val) for the given key is computed - * using the hash function. The table entry holding the - * given key is then searched. If such an entry is - * found the corresponding table entry is removed from - * the hash list and freed. If no matching entry is - * found no action is taken. - * @author Abd Al-Rahman Diab - * @date 09 APRIL 2013 - * @version 1.0 - */ -void delete_entry(u8 *key) -{ - struct table_elmnt *tbl_ptr = 0; - struct table_elmnt *prev_ptr = 0; - unsigned int val = 0; - - /* Calculate hash value for the key */ - val = hash(key); - - /* Initialize temporary pointers to be used in the loop below */ - tbl_ptr = g_sta_table[val]; - prev_ptr = g_sta_table[val]; - - /* Given the hash bucket, find out the entry that has the key */ - while (tbl_ptr) { - if (mac_addr_cmp(tbl_ptr->key, key) == true) { - /* Got a match. Modify the next pointer of the element pointing */ - /* to this element. */ - if (tbl_ptr == g_sta_table[val]) - /* The element to be freed is the first element */ - g_sta_table[val] = tbl_ptr->next_hash_elmnt; - else - /* The element to be freed is not the first element */ - prev_ptr->next_hash_elmnt = tbl_ptr->next_hash_elmnt; - - /* TODO: recheck this */ - /* Free the element referred to by this key */ - /* delete_element(tbl_ptr->element); */ - kfree(tbl_ptr->element); - - /* Free this element */ - kfree(tbl_ptr); - - return; - } - - prev_ptr = tbl_ptr; - tbl_ptr = tbl_ptr->next_hash_elmnt; - } -} - -/*****************************************************************************/ -/* */ -/* Function Name : handle_ps_tx_comp_ap */ -/* */ -/* Description : This function handles transmit complete interrupt for */ -/* power management purpose. */ -/* */ -/* Inputs : 1) Pointer to the transmit descriptor */ -/* */ -/* Globals : g_num_mc_bc_pkt */ -/* */ -/* Processing : This function checks if the frame transmitted was a */ -/* broadcast/multicast frame. If so it reduces the global */ -/* bc/mc packet count in case it is non-zero (indicating */ -/* that the packets were queued). If it is unicast the */ -/* association entry is searched and corresponding number */ -/* of packets are decremented if non-zero (indicating they */ -/* were queued). */ -/* */ -/* Outputs : None */ -/* Returns : None */ -/* Issues : None */ -/* */ -/* Revision History: */ -/* */ -/* DD MM YYYY Author(s) Changes (Describe the changes made) */ -/* 24 10 2005 Ittiam Draft */ -/* */ -/*****************************************************************************/ -void handle_ps_tx_comp_ap(struct tx_complete_data *tx_dscr) -{ - struct WILC_ieee80211_sta *ae; - u8 *msa = tx_dscr->buff; - u8 *da = NULL; - - /* Get the Destination address */ - da = get_DA_ptr(msa); - - ae = (struct WILC_ieee80211_sta *)find_entry(da); - - if (is_group(da) == true) { - if (g_num_mc_bc_qd_pkt > 0) { - g_num_mc_bc_qd_pkt--; - - /* If no packets are queued in Sw PSQ or Hw for the */ - /* station, reset DTIM bit */ - if ((g_num_mc_bc_pkt + g_num_mc_bc_qd_pkt) == 0) { - reset_dtim_bit(AID0_BIT); - reset_dtim_bit(DTIM_BIT); - } - } - } else { - if (ae == 0) - /* Exception. Should not happen */ - return; - - /* Reset the age counter as this STA is active */ - ae->aging_cnt = 0; - - /* Get the type of frame transmitted */ - if (get_type(msa) == (enum BASICTYPE)(DATA)) - if (true == update_ps_counts_txcomp(ae, msa)) - check_and_reset_tim_bit(ae->u16AID); - - } -} - -/*****************************************************************************/ -/* */ -/* Function Name : check_and_reset_tim_bit */ -/* */ -/* Description : This function sets the TIM bit corresponding to the */ -/* association ID in virtual bit map. */ -/* */ -/* Inputs : 1) Association ID */ -/* */ -/* Globals : g_vbmap */ -/* */ -/* Processing : This function is called whenever a packet is removed */ -/* from the power save queue for a sleeping station. Given */ -/* the association ID, set the bit corresponding to that. */ -/* Recalculate length and offset fields and update the */ -/* the virtual bit map. */ -/* */ -/* Outputs : None */ -/* Returns : None */ -/* Issues : None */ -/* */ -/* Revision History: */ -/* */ -/* DD MM YYYY Author(s) Changes (Describe the changes made) */ -/* 24 10 2005 Ittiam Draft */ -/* */ -/*****************************************************************************/ - -void check_and_reset_tim_bit(u16 asoc_id) -{ - u8 byte_offset = 0; - u8 bit_offset = 0; - u8 pvb_offset = 0; - u8 length = 0; - u8 new_pvb_offset = 0; - int16_t i = 0; - u8 new_length = MIN_TIM_LEN; - - /* Traffic Indication Virtual Bit Map within the AP, generates the TIM */ - /* such that if a station has buffered packets, then the corresponding */ - /* bit (which can be found from the association ID) is set. The byte */ - /* offset is obtained by dividing the association ID by '8' and the bit */ - /* offset is the remainder of the association ID when divided by '8'. */ - byte_offset = (asoc_id & (~0xC000)) >> 3; - bit_offset = (asoc_id & (~0xC000)) & 0x07; - - /* Calculate the current byte offset in vbmap */ - pvb_offset = (strBeaconInfo.u8vbmap[BMAP_CTRL_OFFSET] & 0xFE) >> 1; - length = strBeaconInfo.u8vbmap[LENGTH_OFFSET]; - - /* Reset the TIM bit */ - strBeaconInfo.u8vbmap[TIM_OFFSET + byte_offset] &= ~g_bmap[bit_offset]; - - /* Calculate new offset using the following algorithm: */ - /* The new offset will be equal to or greater than the current offset as */ - /* the TIM bit is reset. Also the new TIM length cannot be more the */ - /* existing length. So the algorithm is starting from old offset to */ - /* old offset + TIM length, find out the first occurance of non-zero byte*/ - /* in the TIM element array. This will be the new offset. If no non-zero */ - /* bytes are found, new offset is zero (as initialized). */ - for (i = pvb_offset; i < pvb_offset + length - MIN_TIM_LEN; i++) { - if (strBeaconInfo.u8vbmap[TIM_OFFSET + i]) { - new_pvb_offset = i; - break; - } - } - - /* Calculate new length using the following algorithm */ - /* The new TIM length will be less than or equal to old length as TIM bit*/ - /* is reset. Having new offset calculated, the new length can be */ - /* calculated as the last occurance of non-zero byte from new offset to */ - /* new offset+old length in the TIM element array. (In other words the */ - /* first occurance of non-zero byte in the reverse direction) */ - for (i = pvb_offset + length - MIN_TIM_LEN; i >= 0; i--) { - if (strBeaconInfo.u8vbmap[TIM_OFFSET + i]) { - new_length += (i - new_pvb_offset); - break; - } - } - - /* Assign the new offset and length to the vbmap */ - strBeaconInfo.u8vbmap[BMAP_CTRL_OFFSET] |= (new_pvb_offset & 0xEF) << 1; - strBeaconInfo.u8vbmap[LENGTH_OFFSET] = new_length; -} - -/* - * @brief delete_entry - * @details This function requeues a packet in the H/w queue for - * transmission after removing it from the S/w queue where - * it was buffered for power management purpose. - * - * @Processing First the H/w queue is checked to see if it is full. - * If H/w queue is full then pkt is not requeued. - * If H/w queue is available then pkt is requeued. - * A packet is removed from the head of the given power - * save queue. The transmit descriptor is extracted and - * added to the H/w queue. The power save queue element - * buffer is freed. - * @author Abd Al-Rahman Diab - * @date 05 june 2013 - * @version 1.0 - */ -enum REQUEUE_STATUS requeue_ps_packet(struct WILC_ieee80211_sta *ae, struct list_buff *qh, - bool ps_q_legacy, bool eosp) -{ - u8 q_num = 0; - u8 *mac_hdr = 0; - u8 addr1[6] = {0}; - u8 tx_rate = 0; - u8 pream = 0; - u8 srv_cls = 0; - u8 tid = 0; - unsigned int phy_tx_mode = 0; - bool is_qos = false; - unsigned int retry_set[2] = {0}; - struct tx_complete_data *tx_dscr = 0; - - /* Remove the power save queue element structure from the head of the */ - /* given queue. */ - tx_dscr = remove_list_element_head(qh); - - /* If the queue has no packets return false to indicate that no packets */ - /* were available to be requeued. */ - if (tx_dscr == 0) - return NO_PKT_IN_QUEUE; - - /* Extract the pointer to the MAC header from the Tx-Descriptor */ - mac_hdr = tx_dscr->buff; - - /* Extract DA, TID and QoS from the MAC header of the MSDU */ - get_address1(mac_hdr, addr1); - tid = BEST_EFFORT_PRIORITY; /* get_priority_value(mac_hdr); */ - is_qos = is_qos_bit_set(mac_hdr); - - /* Peek and check if the queue is empty. If so, set the more data bit to */ - /* 0. Otherwise set it to 1. */ - if (peek_list(qh) == NULL) { - if (is_qos == true) - /* TODO: look at this comment if you will handle addba & delba */ - /* make sure this is not a management frame with Action subtype and BA category */ - /* if((is_qos == true) && ( !((get_sub_type(mac_hdr) == ACTION ) && (mac_hdr[MAC_HDR_LEN+CATEGORY_OFFSET] == BA_CATEGORY)))) */ - set_qos_prot(mac_hdr); - - set_more_data(mac_hdr, 0); - } else { - set_more_data(mac_hdr, 1); - } -#if 0 - /* Currently disabled */ - /* If current sp length = max sp length-1 eosp bit set and END_OF_QUEUE */ - /* is returned */ - if (ps_q_legacy == false) - if (is_end_prot(ae) == true) { - set_qos_prot(mac_hdr); - end_of_q = true; - } - -#endif - - /* If current sp length = max sp length-1 eosp bit set and END_OF_QUEUE */ - /* is returned */ - if (true == eosp) - set_qos_prot(mac_hdr); - - /* Update PS queue counters */ - if (ps_q_legacy == true) { - if (is_group(addr1) == true) - g_num_mc_bc_pkt--; - else - ae->num_ps_pkt--; - } else { - /* ae->num_ps_pkt_del_ac--; */ - } - g_num_ps_pkt--; - - /* Check if the packet needs to be buffered for BA. If Block ACK session */ - /* is active then donot queue in the HW queue. */ - /* When STA has come out of sleep then BA is !HALTED */ - - /* TODO: add this check when enabling 11n */ - /* if(false == is_serv_cls_buff_pkt((u8 *)ae, q_num, tid, tx_dscr)) */ - { - /* TODO: add EAPOL and other monitor types check here */ - if (get_sub_type(tx_dscr->buff) == NULL_FRAME) - wilc_wlan_txq_add_mgmt_pkt((void *)tx_dscr, - tx_dscr->buff, - tx_dscr->size, - linux_FH_wlan_tx_complete); - else - wilc_FH_wlan_txq_add_net_pkt((void *)tx_dscr, - tx_dscr->buff, - tx_dscr->size, - linux_FH_wlan_tx_complete); - - if (is_group(addr1) == true) - g_num_mc_bc_qd_pkt++; - else - ae->num_qd_pkt++; - - } - - return PKT_REQUEUED; -} - -/* - * @brief set_tim_bit - * @details This function sets the TIM bit corresponding to the - * association ID in virtual bit map. - * - * @Processing This function is called whenever a new packet is added - * to the power save queue for a sleeping station. Given - * the association ID, set the bit corresponding to that. - * If this bit is not already included in the offset and - * length fields of virtual bit map adjust offset and - * length fields. - * - * @author Abd Al-Rahman Diab - * @date 05 june 2013 - * @version 1.0 - */ -void set_tim_bit(u16 asoc_id) -{ - u8 byte_offset = 0; - u8 bit_offset = 0; - u8 pvb_offset = 0; - u8 length = 0; - - /* Traffic Indication Virtual Bit Map within the AP, generates the TIM */ - /* such that if a station has buffered packets, then the corresponding */ - /* bit (which can be found from the association ID) is set. The byte */ - /* offset is obtained by dividing the association ID by '8' and the bit */ - /* offset is the remainder of the association ID when divided by '8'. */ - byte_offset = (asoc_id & (~0xC000)) >> 3; - bit_offset = (asoc_id & (~0xC000)) & 0x07; - - /* Calculate the current byte offset in vbmap */ - pvb_offset = (strBeaconInfo.u8vbmap[BMAP_CTRL_OFFSET] & 0xFE) >> 1; - length = strBeaconInfo.u8vbmap[LENGTH_OFFSET]; - - /* Compare the existing offset and the offset for the new STA. Create */ - /* new length and offset and add that to vbmap. */ - if (byte_offset < pvb_offset) { - pvb_offset = byte_offset; - length = pvb_offset - byte_offset; - } else if (byte_offset > pvb_offset + length - MIN_TIM_LEN) { - length += byte_offset - pvb_offset; - } - /* Set the TIM bit and length */ - strBeaconInfo.u8vbmap[TIM_OFFSET + byte_offset] |= g_bmap[bit_offset]; - strBeaconInfo.u8vbmap[LENGTH_OFFSET] = length; -} - -/* - * @brief update_ps_flags_ap - * @details This function updates the flags after a packet in enqued - * in the power save buffer - * - * @Processing This function updates the flags after a packet in enqued - * in the power save buffer - * - * @author Abd Al-Rahman Diab - * @date 05 june 2013 - * @version 1.0 - */ -void update_ps_flags_ap(struct WILC_ieee80211_sta *ae, bool bc_mc_pkt, - u8 num_buff_added, bool ps_add_del_ac) -{ - if (num_buff_added == 0) - return; - - if (bc_mc_pkt == true) { - /* The global count for queued BC/MC packets is incremented here. */ - /* This count is checked for resetting the AID0 bit in the TIM */ - /* element once all buffered BC/MC packets have been transmitted. It */ - /* is decremented in Tx complete for BC/MC packets. */ - g_num_mc_bc_pkt += num_buff_added; - g_num_ps_pkt++; - - /* Set the AID0 bit. This is reset BC/MC packet queue becomes empty. */ - /* It is updated in transmit complete processing. */ - set_dtim_bit(AID0_BIT); - set_dtim_bit(DTIM_BIT); - } else { - ae->num_ps_pkt += num_buff_added; - g_num_ps_pkt += num_buff_added; - - /* Set the TIM bit for this station */ - set_tim_bit(ae->u16AID); - } -} - -/*****************************************************************************/ -/* */ -/* Function Name : is_ps_buff_pkt_ap */ -/* */ -/* Description : This function checks if a packet requries buffering */ -/* based on the power save state of the destination. */ -/* */ -/* Inputs : 1) Pointer to the association table */ -/* 2) Pointer to the destination address */ -/* 3) Pointer to the Q-number */ -/* 4) Pointer to the Q-head to which the packet must be q-d */ -/* */ -/* Globals : g_mc_q */ -/* g_num_mc_bc_pkt */ -/* g_num_sta_ps */ -/* */ -/* Processing : In case the packet is a broadcast/multicast packet, the */ -/* global g_num_sta_ps is checked to determine if any of */ -/* the associated stations are in power save mode. */ -/* In case of a unicast packet the association */ -/* entry is checked to determine the power save state of */ -/* the station. The queue limits are checked and if the */ -/* maximum is reached the queue header pointer is set to */ -/* zero so that the calling function can free the buffer. */ -/* Otherwise the queue details are set appropriately. */ -/* */ -/* Outputs : Q-Num to which the packet must be queued and the Queue */ -/* pointer to which the packet must be queued. */ -/* */ -/* Returns : true, if the packet should be buffered for power save */ -/* false, if the packet should not be buffered */ -/* */ -/* Issues : None */ -/* */ -/* Revision History: */ -/* */ -/* DD MM YYYY Author(s) Changes (Describe the changes made) */ -/* 24 10 2005 Draft */ -/* */ -/*****************************************************************************/ - -bool is_ps_buff_pkt_ap(struct WILC_ieee80211_sta *ae, u8 *da, struct tx_complete_data *dscr) -{ - bool ps_del_en_ac = false; - bool bc_mc_pkt = is_group(da); - u8 priority = 0; - struct list_buff *qh = NULL; - - /* check if pkt is BC/MC or Unicast */ - if (bc_mc_pkt == true) { - if (g_num_sta_ps == 0) - /* All stations are in Active mode. No buffering required. */ - return false; - - /* If the global BC/MC queue has not reached the maximum size */ - /* received BC/MC packet should be queued in it. Else packet */ - /* should be dropped */ - - if (g_num_ps_pkt < PS_PKT_Q_MAX_LEN) - qh = &g_mc_q; - } else { - if (ae == 0) - /* Exception. Should not occur. */ - return false; - - if (ae->ps_state == ACTIVE_PS) - /* Station is in Active mode. No buffering required. */ - return false; - - if (g_num_ps_pkt < PS_PKT_Q_MAX_LEN) - qh = (&(ae->ps_q_lgcy)); - - } - - if (qh != NULL) { - add_list_element(qh, dscr); - update_ps_flags_ap(ae, bc_mc_pkt, 1, false); - } else { - if (dscr->skb) - dev_kfree_skb(dscr->skb); - - kfree(dscr); - } - - return true; -} - -/*****************************************************************************/ -/* */ -/* Function Name : buffer_tx_packet */ -/* */ -/* Description : This function buffers a packet ready for transmission */ -/* */ -/* Inputs : 1) Pointer to the transmit descriptor */ -/* 2) Number of the queue to which the packet belongs */ -/* 3) Destination address */ -/* */ -/* Globals : g_mc_q */ -/* g_num_mc_bc_pkt */ -/* g_num_sta_ps */ -/* */ -/* Processing : The packet is buffered based on the service class or the */ -/* power save mode of the receiving STA */ -/* */ -/* Outputs : None */ -/* */ -/* Returns : true, if the given packet is buffered in any queue */ -/* false, if the packet is not buffered and can be sent */ -/* */ -/* Issues : None */ -/* */ -/* Revision History: */ -/* */ -/* DD MM YYYY Author(s) Changes (Describe the changes made) */ -/* 24 10 2005 Draft */ -/* */ -/*****************************************************************************/ - -bool buffer_tx_packet(u8 *entry, u8 *da, u8 priority, - struct tx_complete_data *tx_dscr) -{ - if (true == is_ps_buff_pkt_ap((struct WILC_ieee80211_sta *)entry, da, tx_dscr)) -#ifdef DEBUG_MODE - g_mac_stats.psbuff++; -#endif /* DEBUG_MODE */ - -#if 0 /* open this if you handle Block Ack */ - else if (true == is_serv_cls_buff_pkt(entry, priority, tx_dscr)) -#ifdef DEBUG_MODE - g_mac_stats.bapendingtx++; -#endif /* DEBUG_MODE */ - -#endif - else - return false; - - /* If the packet is buffered return true */ - return true; -} - -/*****************************************************************************/ -/* */ -/* Function Name : tx_null_frame */ -/* */ -/* Description : This function prepares and sends a NULL frame to the */ -/* given station. */ -/* */ -/* Inputs : 1) Address of station to which NULL frame is directed */ -/* */ -/* Globals : None */ -/* */ -/* Processing : The NULL frame is prepared and added to the H/w queue */ -/* with the required descriptor. */ -/* */ -/* Outputs : None */ -/* Returns : None */ -/* Issues : None */ -/* */ -/* Revision History: */ -/* */ -/* DD MM YYYY Author(s) Changes (Describe the changes made) */ -/* 24 10 2005 Draft */ -/* */ -/*****************************************************************************/ - -void tx_null_frame(u8 *sa, struct WILC_ieee80211_sta *ae, bool is_qos, u8 priority, u8 more_data) -{ - u8 q_num = 0; - u8 tx_rate = 0; - u8 pream = 0; - struct tx_complete_data *tx_data; - u8 *msa = 0; - u8 len = 0; - /* unsigned int phy_tx_mode = 0; */ - /* unsigned int retry_set[2] = {0}; */ - - /* Allocate buffer for the NULL frame and set its contents */ - tx_data = kmalloc(sizeof(struct tx_complete_data), GFP_ATOMIC); - - if (tx_data == NULL) - PRINT_ER("Failed to allocate memory for tx_data structure\n"); - - if (is_qos == true) { - /* len = set_frame_ctrl_qos_null_ap(msa, priority, 0); */ - /* q_num = get_txq_num(priority); */ - } else { - len = MAC_HDR_LEN; /* + FCS_LEN; */ - - msa = kmalloc(len, GFP_ATOMIC); - - if (msa == NULL) { - PRINT_ER("No Mem for NULL Tx DSCR\n"); - kfree(tx_data); - return; - } - - tx_data->buff = msa; - tx_data->size = len; - tx_data->skb = NULL; - - set_frame_control(msa, (u16)NULL_FRAME); - - /* NULL frames will be put in Normal priority queue */ - /* q_num = NORMAL_PRI_Q; */ - } - - /* Set the from ds bit */ - set_from_ds(msa, 1); - - /* Set the address fields */ - set_address1(msa, sa); - set_address2(msa, g_linux_wlan->wilc_netdev->dev_addr); - set_address3(msa, g_linux_wlan->wilc_netdev->dev_addr); - - /* Get the transmit rate for the associated station based on the */ - /* auto-rate, multi-rate or user-rate settings. The preamble must be */ - /* set accordingly. */ - /* tx_rate = get_tx_rate_to_sta(ae); */ - /* pream = get_preamble(tx_rate); */ - - /* Update the retry set information for this frame */ - /* update_retry_rate_set(1, tx_rate, ae, retry_set); */ - - /* Get the PHY transmit mode based on the transmit rate and preamble */ - /* phy_tx_mode = get_dscr_phy_tx_mode(tx_rate, pream, (void *)ae); */ - - /* Create the transmit descriptor and set the contents */ - /* tx_dscr = create_default_tx_dscr(0, 0, 0); */ - - WILC_Xmit_data((void *)tx_data, WLAN_TO_WLAN); -} - -/*****************************************************************************/ -/* */ -/* Function Name : handle_ps_poll */ -/* */ -/* Description : This function handles a received PS-Poll frame in the */ -/* access point mode. */ -/* */ -/* Inputs : 1) Pointer to the PS-Poll frame */ -/* */ -/* Globals : None */ -/* */ -/* Processing : This function checks if a previous PS-Poll frame is yet */ -/* to be processed (checks a flag in the association entry) */ -/* If not, the first frame from the power save queue is */ -/* requeued. If requeuing is not successful, a null frame */ -/* is transmitted to the station. */ -/* */ -/* Outputs : None */ -/* */ -/* Returns : BOOL_T, 1, If it was a PS Poll frame */ -/* 0, otherwise */ -/* Issues : None */ -/* */ -/* Revision History: */ -/* */ -/* DD MM YYYY Author(s) Changes (Describe the changes made) */ -/* 24 10 2005 Draft */ -/* */ -/*****************************************************************************/ - -bool handle_ps_poll(struct wlan_rx *wlan_rx) -{ - struct WILC_ieee80211_sta *ae = (struct WILC_ieee80211_sta *)(wlan_rx->u8sa_entry); - - /* Check if the frame is a PS Poll frame and return 0 if not */ - if (wlan_rx->u8Sub_type != PS_POLL) - return false; - - /* PS-Poll frames are processed only if the station is associated to AP. */ - if ((ae == 0) || (ae->state != ASOC)) - /* TODO: find a way to make hostapd send a deauth frame */ - /* Send a De-authentication Frame to the station as PS-Poll is a */ - /* Class 3 frame. */ - /* send_deauth_frame(wlan_rx->sa, (u16)CLASS3_ERR); */ - - /* No further processing is required */ - return true; - - if (ae->ps_poll_rsp_qed == true) - /* If a frame has been queued in response to a previous PS Poll */ - /* received, further PS Poll frames will not be honoured till the */ - /* response frame exchange is complete (indicated by resetting this */ - /* flag in the Tx Complete for this frame). */ - return true; - - /* Requeue one buffered packet from the station's non-delivery enabled Q */ - /* to the MAC H/w queue */ - /* If the non-delivery enabled Q is empty queue a NULL frame */ - /* ASSUMPTION: legacy queue should be empty if all queues are delivery */ - /* enabled */ - if (peek_list(&(ae->ps_q_lgcy)) == NULL) - tx_null_frame(wlan_rx->u8sa, ae, false, 0, 0); - else - requeue_ps_packet(ae, &(ae->ps_q_lgcy), true, false); - - ae->ps_poll_rsp_qed = true; - - return true; -} - -/* - * @brief filter_monitor_data_frames - * @details This function check for data frames sent by hostapd and - * transmit it through the data path - * - * @author Abd Al-Rahman Diab - * @date 05 june 2013 - * @version 1.0 - */ -bool filter_monitor_data_frames(u8 *buf, u16 len) -{ - bool ret = false; - struct tx_complete_data *tx_data = NULL; - - if (get_type(buf) == DATA_BASICTYPE) { - tx_data = kmalloc(sizeof(struct tx_complete_data), GFP_ATOMIC); - - if (tx_data == NULL) { - PRINT_ER("Failed to allocate memory for tx_data structure\n"); - return ret; - } - - tx_data->buff = buf; - tx_data->size = len; - tx_data->skb = NULL; - WILC_Xmit_data((void *)tx_data, MONITOR_TO_WLAN); - - ret = true; - } - - return ret; -} - -#endif - diff --git a/wilc3000/wilc_host_ap.h b/wilc3000/wilc_host_ap.h deleted file mode 100644 index b1fa9ed..0000000 --- a/wilc3000/wilc_host_ap.h +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Atmel WILC3000 802.11 b/g/n and Bluetooth Combo driver - * - * Copyright (c) 2015 Atmel Corportation - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef __WILC_HOST_AP__ -#define __WILC_HOST_AP__ - -#include "wilc_wlan_if.h" -#include "wilc_wlan.h" -#include "host_interface.h" -#include "wilc_wfi_netdevice.h" - -#ifdef WILC_FULLY_HOSTING_AP -#define ITIM 5 /* Traffic Information Map */ -#define DEFAULT_TIM_LEN 4 -#define FCS_LEN 4 -#define VBMAP_SIZE 256 -#define MAX_LISTEN_INT 10 -#define VBMAP_SIZE 256 -#define MIN_TIM_LEN 4 -#define PS_PKT_Q_MAX_LEN 16 -/* - * Time out for discarding a packets in - * PS queues in millisecs - */ -#define PS_BUFF_TO 500 -#define AGING_THR_IN_SEC 60 -#define WORD_OFFSET_4 4 -#define TX_DSCR_NEXT_ADDR_WORD_OFFSET WORD_OFFSET_4 -#define WIFI_PERIPH_BASE 0x00000000 -#define WIFI_PA_BASE (WIFI_PERIPH_BASE + 0x9800) -#define PA_BASE WIFI_PA_BASE -#define rMAC_DTIM_COUNT_ADDR ((unsigned int)(PA_BASE + 0x021C)) -#define rMAC_BEACON_PERIOD ((unsigned int)(PA_BASE + 0x020C)) -#define rMAC_DTIM_PERIOD ((unsigned int)(PA_BASE + 0x0210)) -#define rMAC_TSF_CON ((unsigned int)(PA_BASE + 0x0200)) -#define BEST_EFFORT_PRIORITY 0 -#define NORMAL_ACK 0 -#define BCAST_NO_ACK 4 -#define PROTOCOL_VERSION 0x00 -#define MAX_MSDU_LEN 1596 -#define PS_POLL_LEN 20 -#define QOS_CTRL_FIELD_LEN 2 -#define HT_CTRL_FIELD_LEN 4 /* Length of HT Control Field */ -#define IS_MANAGMEMENT 0x100 -#define IS_MANAGMEMENT_CALLBACK 0x080 -#define IS_MGMT_STATUS_SUCCES 0x040 -#define GET_PKT_OFFSET(a) (((a) >> 22) & 0x1ff) - -/* Maximum number of hash values possible for the Sta Entry Table */ -#define MAX_HASH_VALUES 16 -#define SNAP_HDR_ID_LEN 6 -#define ETH_PKT_TYPE_OFFSET 12 -#define IP_TYPE 0x0800 -#define ARP_TYPE 0x0806 -#define ONE_X_TYPE 0x888E -#define VLAN_TYPE 0x8100 -#define LLTD_TYPE 0x88D9 -#define UDP_TYPE 0x11 -#define TCP_TYPE 0x06 - -#define NEXT_ELEMENT_ADDR(base, ofst) (*((unsigned int *)((u8 *)base + ofst))) - -/* Basic Frame Type Codes (2-bit) */ -enum BASICTYPE { - CONTROL = 0x04, - DATA_BASICTYPE = 0x08, - MANAGEMENT = 0x00, - RESERVED = 0x0C -}; - -enum STA_PS_STATE { - ACTIVE_PS = 0, - POWER_SAVE = 1 -}; - -enum TIMBIT { - AID0_BIT = 0, - DTIM_BIT = 1 -}; - -enum REQUEUE_STATUS { - RE_Q_ERROR = 0, - NO_PKT_IN_QUEUE = 1, - PKT_REQUEUED = 2, - END_OF_QUEUE = 3, - PKT_NOT_REQUEUED = 4 -}; - -/* Data Pathes */ -enum Data_Interface { - HOST_TO_WLAN = 0, - WLAN_TO_WLAN = 1, - MONITOR_TO_WLAN = 2 -}; - -/* Capability Information field bit assignments */ -enum CAPABILITY { - ESS = 0x01, /* ESS capability */ - IBSS = 0x02, /* IBSS mode */ - POLLABLE = 0x04, /* CF Pollable */ - POLLREQ = 0x08, /* Request to be polled */ - PRIVACY = 0x10, /* WEP encryption supported */ - SHORTPREAMBLE = 0x20, /* Short Preamble is supported */ - SHORTSLOT = 0x400, /* Short Slot is supported */ - PBCC = 0x40, /* PBCC */ - CHANNELAGILITY = 0x80, /* Channel Agility */ - SPECTRUM_MGMT = 0x100, /* Spectrum Management */ - DSSS_OFDM = 0x2000 /* DSSS-OFDM */ -}; - -/* Authentication/Association states of STAs maintained by the Access Point */ -enum STATIONSTATE { - AUTH_COMPLETE = 1, /* Authenticated */ - AUTH_KEY_SEQ1 = 2, /* Shared Key Auth (Sequence 1) done */ - ASOC = 3 /* Associated */ -}; - -enum OFFSET { - TYPE_OFFSET = 0, - LENGTH_OFFSET = 1, - DTIM_CNT_OFFSET = 2, - DTIM_PERIOD_OFFSET = 3, - BMAP_CTRL_OFFSET = 4, - TIM_OFFSET = 5 -}; - -/* Frame Type and Subtype Codes (6-bit) */ -enum TYPESUBTYPE { - ASSOC_REQ = 0x00, - ASSOC_RSP = 0x10, - REASSOC_REQ = 0x20, - REASSOC_RSP = 0x30, - PROBE_REQ = 0x40, - PROBE_RSP = 0x50, - BEACON = 0x80, - ATIM = 0x90, - DISASOC = 0xA0, - AUTH = 0xB0, - DEAUTH = 0xC0, - ACTION = 0xD0, - PS_POLL = 0xA4, - RTS = 0xB4, - CTS = 0xC4, - ACK = 0xD4, - CFEND = 0xE4, - CFEND_ACK = 0xF4, - DATA = 0x08, - DATA_ACK = 0x18, - DATA_POLL = 0x28, - DATA_POLL_ACK = 0x38, - NULL_FRAME = 0x48, - CFACK = 0x58, - CFPOLL = 0x68, - CFPOLL_ACK = 0x78, - QOS_DATA = 0x88, - QOS_DATA_ACK = 0x98, - QOS_DATA_POLL = 0xA8, - QOS_DATA_POLL_ACK = 0xB8, - QOS_NULL_FRAME = 0xC8, - QOS_CFPOLL = 0xE8, - QOS_CFPOLL_ACK = 0xF8, - BLOCKACK_REQ = 0x84, - BLOCKACK = 0x94 -}; - -/*****************************************************************************/ -/* Structures */ -/*****************************************************************************/ -struct q_entry { - void *fa; /* Pointer to the element in the queue */ - struct _q_entry_t *tqe_next; /* Pointer to the next element */ - struct _q_entry_t *tqe_prev; /* Pointer to the previous element */ -}; - -struct q_head { - struct q_entry *head; - struct q_entry *tail; -}; - -struct list_buff { - void *head; /* Head Element of the List */ - void *tail; /* Tail Element of the List */ - u16 count; /* Number of Elements in the List */ - u16 lnk_byte_ofst; /* Offset to Link Pointer in the List in Bytes */ -}; - -/* - * Basic rate set. - * This contains the set of basic rates supported by any IBSS. - */ -struct rate_t { - u8 rates[MAX_RATES_SUPPORTED]; - u8 num_rates; -}; - -struct beacon_data { - int size; - void *buff; -}; - -struct beacon_info { - u16 u16beacon_len; - u8 *u8beacon_frame; - u8 u8tim_element_index; - u16 u16tim_element_trailer_len; - u8 u8vbmap[VBMAP_SIZE]; - u8 u8DTIMPeriod; - u16 u16Beacon_Period; -}; - -struct wlan_rx { - u8 service_class; /* Service class extracted from header */ - u8 priority_val; /* Priority value extracted from header */ - u8 u8hdr_len; /* Length of header including offset */ - u16 u16data_len; /* Length of the frame excluding headers */ - u16 u16rx_len; /* Length of the frame including the headers */ - u8 *u8sa_entry; /* Source Address station entry */ - u8 *u8msa; /* MAC header start address */ - u8 u8addr1[6]; /* Address1 field extracted from header */ - u8 u8addr2[6]; /* Address2 field extracted from header */ - u8 u8addr3[6]; /* Address3 field extracted from header */ - u8 *u8sa; /* Pointer to source address */ - u8 *u8da; /* Pointer to destination address */ - u8 *u8bssid; /* Pointer to BSSID */ - u8 *u8ta; /* Pointer to Transmitter address */ - enum BASICTYPE enumType; /* Packet type extracted from the header */ - u8 u8Sub_type; /* Packet Sub type extracted from the header */ - u8 u8frm_ds; /* From DS field of MAC header */ - u8 u8to_ds; /* To DS field of MAC header */ - bool bIs_grp_addr; /* Group address flag */ -}; - -struct WILC_ieee80211_sta { - u32 supp_rates[IEEE80211_NUM_BANDS]; - u8 addr[ETH_ALEN]; /* MAC address of the STA */ - u16 u16AID; /* Association ID of the STA */ - enum STATIONSTATE state; /* Auth/Asoc state of the STA */ - struct ieee80211_sta_ht_cap ht_cap; - unsigned int aging_cnt; /* Aging cnt for STA */ - struct rate_t op_rates; /* Operational rates of the STA */ - enum STA_PS_STATE ps_state; /* Power save state of the STA */ - struct list_buff ps_q_lgcy; /* Power save queue for the STA */ - u16 num_ps_pkt; /* Number of UC pkts queued in PSQ */ - u16 num_qd_pkt; /* Number of UC pkts queued in HW */ - bool ps_poll_rsp_qed; /* Flag to indicate PS poll rsp is already queued and pending */ -}; - -struct table_elmnt { - u8 key[6]; /* Key, i.e. the MAC address */ - void *element; /* Pointer to the table element */ - struct table_elmnt *next_hash_elmnt; /* Pointer to next bucket element */ -}; - -signed int host_add_beacon(struct WFIDrvHandle *hWFIDrv, unsigned int u32Interval, - unsigned int u32DTIMPeriod, - unsigned int u32HeadLen, u8 *pu8Head, - unsigned int u32TailLen, u8 *pu8Tail); -signed int host_del_beacon(struct WFIDrvHandle *hWFIDrv); -inline void WILC_AP_AddSta(u8 *mac, struct station_parameters *params); -inline void WILC_AP_EditSta(u8 *mac, struct station_parameters *params); -inline void WILC_AP_RemoveSta(u8 *mac); -void process_tbtt_isr(void); -struct wilc_wlan_dev *Get_wlan_context(u16 *pu16size); -#ifdef WILC_AP_EXTERNAL_MLME -int wilc_wlan_txq_add_mgmt_pkt(void *priv, uint8_t *buffer, uint32_t buffer_size, wilc_tx_complete_func_t func); -#endif -int wilc_FH_wlan_txq_add_net_pkt(void *priv, uint8_t *buffer, uint32_t buffer_size, wilc_tx_complete_func_t func); -void WILC_Process_rx_frame(u8 *u8Buff, unsigned int u32Size); -int WILC_Xmit_data(void *ptx_data, enum Data_Interface InterfaceType); -bool filter_monitor_data_frames(u8 *buf, u16 len); -#endif /* WILC_FULLY_HOSTING_AP */ -#endif diff --git a/wilc3000/wilc_sdio.c b/wilc3000/wilc_sdio.c old mode 100755 new mode 100644 index 2cd7dfb..e18b7e3 --- a/wilc3000/wilc_sdio.c +++ b/wilc3000/wilc_sdio.c @@ -157,8 +157,6 @@ static int sdio_clear_int(void) reg &= ~0x1; sdio_write_reg(WILC_HOST_RX_CTRL_0, reg); - int_clrd++; - return 1; } #else @@ -173,8 +171,6 @@ static int sdio_clear_int(void) cmd.data = 0; g_sdio.sdio_cmd52(&cmd); - int_clrd++; - return cmd.data; } #endif /* WILC_SDIO_IRQ_GPIO */ @@ -697,7 +693,6 @@ int sdio_init(struct wilc_wlan_inp *inp) g_sdio.has_thrpt_enh3 = 1; PRINT_D(BUS_DBG, "has_thrpt_enh3 = %d\n", g_sdio.has_thrpt_enh3); } - int_clrd = 0; return 1; _fail_: diff --git a/wilc3000/wilc_spi.c b/wilc3000/wilc_spi.c index ec73724..0d245a5 100644 --- a/wilc3000/wilc_spi.c +++ b/wilc3000/wilc_spi.c @@ -992,8 +992,6 @@ static int spi_clear_int(void) reg &= ~0x1; spi_write_reg(WILC_HOST_RX_CTRL_0, reg); - int_clrd++; - return 1; } @@ -1120,8 +1118,6 @@ static int spi_init(struct wilc_wlan_inp *inp) g_spi.has_thrpt_enh = 1; isinit = 1; - int_clrd = 0; - return 1; } diff --git a/wilc3000/wilc_wfi_cfg_operations.c b/wilc3000/wilc_wfi_cfg_operations.c index bb541e8..862ca82 100644 --- a/wilc3000/wilc_wfi_cfg_operations.c +++ b/wilc3000/wilc_wfi_cfg_operations.c @@ -2358,6 +2358,7 @@ int WILC_WFI_mgmt_tx(struct wiphy *wiphy, mgmt_tx->buff = kmalloc(buf_len, GFP_ATOMIC); if (NULL == mgmt_tx->buff) { PRINT_ER("Failed to allocate memory for mgmt_tx buff\n"); + kfree(mgmt_tx); return ATL_FAIL; } memcpy(mgmt_tx->buff, buf, len); @@ -2858,20 +2859,12 @@ static int WILC_WFI_start_ap(struct wiphy *wiphy, struct net_device *dev, if (s32Error != ATL_SUCCESS) PRINT_ER("Error in setting channel\n"); #endif - -#ifndef WILC_FULLY_HOSTING_AP + s32Error = host_int_add_beacon(priv->hWILCWFIDrv, settings->beacon_interval, settings->dtim_period, beacon->head_len, (u8 *)beacon->head, beacon->tail_len, (u8 *)beacon->tail); -#else - s32Error = host_add_beacon(priv->hWILCWFIDrv, - settings->beacon_interval, - settings->dtim_period, - beacon->head_len, (u8 *)beacon->head, - beacon->tail_len, (u8 *)beacon->tail); -#endif return s32Error; } @@ -2897,19 +2890,12 @@ static int WILC_WFI_change_beacon(struct wiphy *wiphy, struct net_device *dev, priv = wiphy_priv(wiphy); PRINT_D(HOSTAPD_DBG, "Setting beacon\n"); -#ifndef WILC_FULLY_HOSTING_AP s32Error = host_int_add_beacon(priv->hWILCWFIDrv, 0, 0, beacon->head_len, (u8 *)beacon->head, beacon->tail_len, (u8 *)beacon->tail); -#else - s32Error = host_add_beacon(priv->hWILCWFIDrv, - 0, - 0, - beacon->head_len, (u8 *)beacon->head, - beacon->tail_len, (u8 *)beacon->tail); -#endif + return s32Error; } @@ -2937,11 +2923,8 @@ static int WILC_WFI_stop_ap(struct wiphy *wiphy, struct net_device *dev) /*BugID_5188*/ linux_wlan_set_bssid(dev, NullBssid); -#ifndef WILC_FULLY_HOSTING_AP s32Error = host_int_del_beacon(priv->hWILCWFIDrv); -#else - s32Error = host_del_beacon(priv->hWILCWFIDrv); -#endif + ATL_ERRORCHECK(s32Error); ATL_CATCH(s32Error){ @@ -2985,17 +2968,11 @@ static int WILC_WFI_add_beacon(struct wiphy *wiphy, struct net_device *dev, } } -#ifndef WILC_FULLY_HOSTING_AP s32Error = host_int_add_beacon(priv->hWILCWFIDrv, info->interval, info->dtim_period, info->head_len, info->head, info->tail_len, info->tail); -#else - s32Error = host_add_beacon(priv->hWILCWFIDrv, info->interval, - info->dtim_period, - info->head_len, info->head, - info->tail_len, info->tail); -#endif + return s32Error; } @@ -3045,11 +3022,8 @@ static int WILC_WFI_del_beacon(struct wiphy *wiphy, struct net_device *dev) /*BugID_5188*/ linux_wlan_set_bssid(dev, NullBssid); - #ifndef WILC_FULLY_HOSTING_AP s32Error = host_int_del_beacon(priv->hWILCWFIDrv); - #else - s32Error = host_del_beacon(priv->hWILCWFIDrv); - #endif + ATL_ERRORCHECK(s32Error); @@ -3083,7 +3057,6 @@ static int WILC_WFI_add_station(struct wiphy *wiphy, struct net_device *dev, nic = netdev_priv(dev); if (nic->iftype == AP_MODE || nic->iftype == GO_MODE) { - #ifndef WILC_FULLY_HOSTING_AP memcpy(strStaParams.au8BSSID, mac, ETH_ALEN); memcpy(priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid], mac, ETH_ALEN); @@ -3125,16 +3098,6 @@ static int WILC_WFI_add_station(struct wiphy *wiphy, struct net_device *dev, s32Error = host_int_add_station(priv->hWILCWFIDrv, &strStaParams); ATL_ERRORCHECK(s32Error); - #else - PRINT_D(CFG80211_DBG, "Adding station parameters %d\n", params->aid); - memcpy(priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid], mac, ETH_ALEN); - - PRINT_D(CFG80211_DBG, "BSSID = %x%x%x%x%x%x\n", priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][0], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][1], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][2], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][3], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][4], - priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][5]); - - WILC_AP_AddSta(mac, params); - ATL_ERRORCHECK(s32Error); - #endif /* WILC_FULLY_HOSTING_AP */ } ATL_CATCH(s32Error){ @@ -3175,11 +3138,8 @@ static int WILC_WFI_del_station(struct wiphy *wiphy, struct net_device *dev, PRINT_D(CFG80211_DBG, "With mac address: %x%x%x%x%x%x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } - #ifndef WILC_FULLY_HOSTING_AP s32Error = host_int_del_station(priv->hWILCWFIDrv, mac); - #else - WILC_AP_RemoveSta(mac); - #endif /* WILC_FULLY_HOSTING_AP */ + ATL_ERRORCHECK(s32Error); } @@ -3214,7 +3174,6 @@ static int WILC_WFI_change_station(struct wiphy *wiphy, struct net_device *dev, nic = netdev_priv(dev); if (nic->iftype == AP_MODE || nic->iftype == GO_MODE) { - #ifndef WILC_FULLY_HOSTING_AP memcpy(strStaParams.au8BSSID, mac, ETH_ALEN); strStaParams.u16AssocID = params->aid; @@ -3253,10 +3212,6 @@ static int WILC_WFI_change_station(struct wiphy *wiphy, struct net_device *dev, s32Error = host_int_edit_station(priv->hWILCWFIDrv, &strStaParams); ATL_ERRORCHECK(s32Error); - #else - WILC_AP_EditSta(mac, params); - ATL_ERRORCHECK(s32Error); - #endif /* WILC_FULLY_HOSTING_AP */ } ATL_CATCH(s32Error){ @@ -3457,9 +3412,7 @@ static struct cfg80211_ops WILC_WFI_cfg80211_ops = { .del_station = WILC_WFI_del_station, .change_station = WILC_WFI_change_station, #endif /* WILC_AP_EXTERNAL_MLME*/ - #ifndef WILC_FULLY_HOSTING_AP .get_station = WILC_WFI_get_station, - #endif .dump_station = WILC_WFI_dump_station, .change_bss = WILC_WFI_change_bss, /* .auth = WILC_WFI_auth, */ diff --git a/wilc3000/wilc_wfi_cfg_operations.h b/wilc3000/wilc_wfi_cfg_operations.h index c6e96c1..2526cf4 100644 --- a/wilc3000/wilc_wfi_cfg_operations.h +++ b/wilc3000/wilc_wfi_cfg_operations.h @@ -20,10 +20,6 @@ #define NM_WFI_CFGOPERATIONS #include "wilc_wfi_netdevice.h" -#ifdef WILC_FULLY_HOSTING_AP -#include "wilc_host_ap.h" -#endif - extern u8 g_wilc_initialized; extern int connecting; extern struct timer_list hEAPFrameBuffTimer; diff --git a/wilc3000/wilc_wlan.c b/wilc3000/wilc_wlan.c index 7ac7e61..9f275da 100644 --- a/wilc3000/wilc_wlan.c +++ b/wilc3000/wilc_wlan.c @@ -424,8 +424,11 @@ static int wilc_wlan_txq_add_cfg_pkt(uint8_t *buffer, uint32_t buffer_size) tqe = kmalloc(sizeof(*tqe), GFP_KERNEL); if (NULL == tqe) + { + up(p->cfg_wait); return 0; - + } + tqe->type = WILC_CFG_PKT; tqe->buffer = buffer; tqe->buffer_size = buffer_size; @@ -440,8 +443,10 @@ static int wilc_wlan_txq_add_cfg_pkt(uint8_t *buffer, uint32_t buffer_size) PRINT_D(TX_DBG, "Adding the config packet at the Queue tail\n"); if (wilc_wlan_txq_add_to_head(tqe)) + { + up(p->cfg_wait); return 0; - + } return 1; } @@ -453,8 +458,11 @@ static int wilc_wlan_txq_add_net_pkt(void *priv, uint8_t *buffer, struct txq_entry_t *tqe; if (p->quit) + { + PRINT_D(TX_DBG, "drv is quitting, return from net_pkt\n"); + func(priv, 0); return 0; - + } if (!(g_wlan.initialized)) { PRINT_D(TX_DBG, "not_init, return from net_pkt\n"); func(priv, 0); @@ -463,7 +471,11 @@ static int wilc_wlan_txq_add_net_pkt(void *priv, uint8_t *buffer, tqe = kmalloc(sizeof(*tqe), GFP_KERNEL); if (tqe == NULL) + { + PRINT_D(TX_DBG, "malloc failed, return from net_pkt\n"); + func(priv, 0); return 0; + } tqe->type = WILC_NET_PKT; tqe->buffer = buffer; tqe->buffer_size = buffer_size; @@ -492,7 +504,11 @@ int wilc_wlan_txq_add_mgmt_pkt(void *priv, uint8_t *buffer, struct txq_entry_t *tqe; if (p->quit) + { + PRINT_D(TX_DBG, "drv is quitting, return from mgmt_pkt\n"); + func(priv, 0); return 0; + } if (!(g_wlan.initialized)) { PRINT_D(TX_DBG, "not_init, return from mgmt_pkt\n"); @@ -502,7 +518,11 @@ int wilc_wlan_txq_add_mgmt_pkt(void *priv, uint8_t *buffer, tqe = kmalloc(sizeof(*tqe), GFP_KERNEL); if (NULL == tqe) - return 0; + { + PRINT_D(TX_DBG, "malloc failed, return from mgmt_pkt\n"); + func(priv, 0); + return 0; + } tqe->type = WILC_MGMT_PKT; tqe->buffer = buffer; tqe->buffer_size = buffer_size; @@ -511,37 +531,12 @@ int wilc_wlan_txq_add_mgmt_pkt(void *priv, uint8_t *buffer, #ifdef TCP_ACK_FILTER tqe->tcp_PendingAck_index = NOT_TCP_ACK; #endif - PRINT_D(TX_DBG, "Adding Network packet at the Queue tail\n"); + PRINT_D(TX_DBG, "Adding Mgmt packet at the Queue tail\n"); wilc_wlan_txq_add_to_tail(tqe); return 1; } -#ifdef WILC_FULLY_HOSTING_AP -int wilc_FH_wlan_txq_add_net_pkt(void *priv, uint8_t *buffer, - uint32_t buffer_size, - wilc_tx_complete_func_t func) -{ - struct wilc_wlan_dev *p = (struct wilc_wlan_dev *)&g_wlan; - struct txq_entry_t *tqe; - - if (p->quit) - return 0; - - tqe = kmalloc(sizeof(*tqe), GFP_KERNEL); - if (NULL == tqe) - return 0; - tqe->type = WILC_FH_DATA_PKT; - tqe->buffer = buffer; - tqe->buffer_size = buffer_size; - tqe->tx_complete_func = func; - tqe->priv = priv; - PRINT_D(TX_DBG, "Adding mgmt packet at the Queue tail\n"); - wilc_wlan_txq_add_to_tail(tqe); - /* return number of itemes in the queue */ - return p->txq_entries; -} -#endif /* WILC_FULLY_HOSTING_AP*/ #endif /* WILC_AP_EXTERNAL_MLME */ static struct txq_entry_t *wilc_wlan_txq_get_first(void) { @@ -625,8 +620,7 @@ void chip_sleep_manually(unsigned int u32SleepTime, int source) /* Trigger the manual sleep interrupt host_interrupt_4 */ g_wlan.hif_func.hif_write_reg(0x10B8, 1); - genuChipPSstate = CHIP_SLEEPING_MANUAL; - release_bus(RELEASE_ONLY, PWR_DEV_SRC_WIFI); + release_bus(RELEASE_ONLY, source); } void wilc_host_sleep_notify( int source) @@ -684,10 +678,6 @@ static int wilc_wlan_handle_txq(uint32_t *pu32TxqCount) */ else if (tqe->type == WILC_NET_PKT) vmm_sz = ETH_ETHERNET_HDR_OFFSET; - #ifdef WILC_FULLY_HOSTING_AP - else if (tqe->type == WILC_FH_DATA_PKT) - vmm_sz = FH_TX_HOST_HDR_OFFSET; - #endif #ifdef WILC_AP_EXTERNAL_MLME else vmm_sz = HOST_HDR_OFFSET; @@ -884,11 +874,6 @@ static int wilc_wlan_handle_txq(uint32_t *pu32TxqCount) /*copy the bssid at the sart of the buffer*/ memcpy(&txb[offset + 4], pBSSID, 6); } - #ifdef WILC_FULLY_HOSTING_AP - else if (tqe->type == WILC_FH_DATA_PKT) { - buffer_offset = FH_TX_HOST_HDR_OFFSET; - } - #endif else { buffer_offset = HOST_HDR_OFFSET; } @@ -1331,6 +1316,11 @@ static int wilc_bt_firmware_download(const uint8_t *buffer, uint32_t buffer_size ret = p->hif_func.hif_block_tx(addr, dma_buffer, size2); if (!ret) break; + /* + * Ticket #878: delay after the block tx, or else the FW will be downloaded + * corrupted in the IRAM for an unknown reason + */ + mdelay(1); addr += size2; offset += size2; @@ -1505,6 +1495,22 @@ static int wilc_wlan_stop(void) return ret; } + /* Inform the power sequencer to ignore WIFI sleep signal on making chip sleep decision */ + ret = p->hif_func.hif_read_reg(rPWR_SEQ_MISC_CTRL, ®); + if (!ret) { + PRINT_ER("Error while reading reg\n"); + release_bus(RELEASE_ALLOW_SLEEP, PWR_DEV_SRC_WIFI); + return ret; + } + + reg &= ~BIT28; + ret = p->hif_func.hif_write_reg(rPWR_SEQ_MISC_CTRL, reg); + if (!ret) { + PRINT_ER("Error while writing reg\n"); + release_bus(RELEASE_ALLOW_SLEEP, PWR_DEV_SRC_WIFI); + return ret; + } + ret = p->hif_func.hif_read_reg(WILC_GLB_RESET_0, ®); if (!ret) { PRINT_ER("Error while reading reg\n"); @@ -1620,8 +1626,8 @@ static void wilc_wlan_cleanup(void) rqe = wilc_wlan_rxq_remove(); if (NULL == rqe) break; - #ifdef MEMORY_DYNAMIC - kfree(tqe->buffer); + #ifndef MEMORY_STATIC + kfree(rqe->buffer); #endif kfree(rqe); } while (1); @@ -1966,9 +1972,6 @@ int at_wlan_init(struct wilc_wlan_inp *inp, struct wilc_wlan_oup *oup) #if defined(WILC_AP_EXTERNAL_MLME) || defined(WILC_P2P) oup->wlan_add_mgmt_to_tx_que = wilc_wlan_txq_add_mgmt_pkt; -#ifdef WILC_FULLY_HOSTING_AP - oup->wlan_add_data_to_tx_que = wilc_FH_wlan_txq_add_net_pkt; -#endif #endif if (!init_chip()) { @@ -1992,11 +1995,3 @@ int at_wlan_init(struct wilc_wlan_inp *inp, struct wilc_wlan_oup *oup) } - -#ifdef WILC_FULLY_HOSTING_AP -struct wilc_wlan_dev *Get_wlan_context(u16 *pu16size) -{ - *pu16size = sizeof(struct wilc_wlan_dev); - return &g_wlan; -} -#endif diff --git a/wilc3000/wilc_wlan.h b/wilc3000/wilc_wlan.h index 25dc0fc..2eacafc 100644 --- a/wilc3000/wilc_wlan.h +++ b/wilc3000/wilc_wlan.h @@ -58,9 +58,6 @@ uint32_t wilc_get_chipid(uint8_t update); #define ETH_CONFIG_PKT_HDR_LEN UDP_DATA_OFFSET #define ETH_CONFIG_PKT_HDR_OFFSET (ETH_ETHERNET_HDR_OFFSET \ + ETH_CONFIG_PKT_HDR_LEN) -#ifdef WILC_FULLY_HOSTING_AP -#define FH_TX_HOST_HDR_OFFSET 24 -#endif /* * Endian Conversion @@ -154,9 +151,6 @@ uint32_t wilc_get_chipid(uint8_t update); */ #ifdef WILC_AP_EXTERNAL_MLME #define WILC_MGMT_PKT 2 -#ifdef WILC_FULLY_HOSTING_AP -#define WILC_FH_DATA_PKT 4 -#endif /* WILC_FULLY_HOSTING_AP */ #endif /* WILC_AP_EXTERNAL_MLME */ #define WILC_CFG_SET 1 #define WILC_CFG_QUERY 0 diff --git a/wilc3000/wilc_wlan_cfg.c b/wilc3000/wilc_wlan_cfg.c index be51a44..9c3a401 100644 --- a/wilc3000/wilc_wlan_cfg.c +++ b/wilc3000/wilc_wlan_cfg.c @@ -21,11 +21,6 @@ #include "wilc_wlan_cfg.h" #include "core_configurator.h" -#ifdef WILC_FULLY_HOSTING_AP -#include "wilc_host_ap.h" -void WILC_mgm_HOSTAPD_ACK(void *priv, bool bStatus); -#endif - struct wilc_mac_cfg_t { int mac_status; uint8_t mac_address[7]; @@ -493,18 +488,6 @@ static int wilc_wlan_cfg_indicate_rx(uint8_t *frame, int size, struct wilc_cfg_r uint8_t msg_type; uint8_t msg_id; uint16_t msg_len; -#ifdef WILC_FULLY_HOSTING_AP - unsigned int *ptru32Frame; - bool bStatus = frame[2]; - -#ifdef BIG_ENDIAN - ptru32Frame = (frame[4] << 24) | (frame[5] << 16) | - (frame[6] << 8) | frame[7]; - #else - ptru32Frame = (frame[7] << 24) | (frame[6] << 16) | - (frame[5] << 8) | frame[4]; -#endif /* BIG_ENDIAN */ -#endif /* WILC_FULLY_HOSTING_AP */ msg_type = frame[0]; msg_id = frame[1]; /* seq no */ @@ -535,12 +518,7 @@ static int wilc_wlan_cfg_indicate_rx(uint8_t *frame, int size, struct wilc_cfg_r GnrlAsyncInfoReceived(frame - 4, size + 4); break; case 'L': - #ifndef SWITCH_LOG_TERMINAL PRINT_ER("Unexpected firmware log message received\n"); - #else - PRINT_D(FIRM_DBG, "\nFIRMWARE LOGS :\n<<\n%s\n>>\n", frame); - break; -#endif case 'N': NetworkInfoReceived(frame - 4, size + 4); rsp->type = 0; @@ -549,16 +527,6 @@ static int wilc_wlan_cfg_indicate_rx(uint8_t *frame, int size, struct wilc_cfg_r PRINT_INFO(RX_DBG,"Scan Notification Received\n"); host_int_ScanCompleteReceived(frame - 4, size + 4); break; -#ifdef WILC_FULLY_HOSTING_AP - case 'T': - PRINT_INFO(RX_DBG,"TBTT Notification Received\n"); - process_tbtt_isr(); - break; - case 'A': - PRINT_INFO(RX_DBG,"HOSTAPD ACK Notification Received\n"); - WILC_mgm_HOSTAPD_ACK(ptru32Frame, bStatus); - break; -#endif default: PRINT_INFO(RX_DBG,"unknown message type %d-%d-%d-%d-%d-%d-%d-%d\n", frame[0], frame[1], frame[2], frame[3], frame[4], diff --git a/wilc3000/wilc_wlan_if.h b/wilc3000/wilc_wlan_if.h index 26617e3..2191685 100644 --- a/wilc3000/wilc_wlan_if.h +++ b/wilc3000/wilc_wlan_if.h @@ -44,9 +44,6 @@ #define WILC_MAC_INDICATE_SCAN 0x2 struct tx_complete_data { -#ifdef WILC_FULLY_HOSTING_AP - struct tx_complete_data *next; -#endif int size; void *buff; uint8_t *pBssid; @@ -78,10 +75,6 @@ struct wilc_wlan_oup { #if defined(WILC_AP_EXTERNAL_MLME) || defined(WILC_P2P) int (*wlan_add_mgmt_to_tx_que)(void *, uint8_t *, uint32_t, wilc_tx_complete_func_t); -#ifdef WILC_FULLY_HOSTING_AP - int (*wlan_add_data_to_tx_que)(void *, uint8_t *, - uint32_t, wilc_tx_complete_func_t); -#endif #endif };