From 7ca1e08f7b6f75ee55dd3826028ffb868c5f7354 Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Sun, 30 Jul 2023 12:06:41 +0200 Subject: [PATCH 404/464] bes2600: Update the wifi driver from bestechnic (0.3.5_2023.0209) Import from https://gitlab.com/TuxThePenguin0/bes2600 New driver intended to work with Linux 6.3 provided by bestechnic. Despite the lower version number this does appear to be a newer version. Signed-off-by: Ondrej Jirman --- drivers/staging/bes2600/Kconfig | 42 +--- drivers/staging/bes2600/Makefile | 36 +-- drivers/staging/bes2600/ap.c | 68 +++--- drivers/staging/bes2600/ap.h | 2 +- drivers/staging/bes2600/bes2600.h | 51 +++-- drivers/staging/bes2600/bes2600_factory.c | 80 ++++++- drivers/staging/bes2600/bes2600_factory.h | 20 +- drivers/staging/bes2600/bes2600_sdio.c | 91 +++++++- drivers/staging/bes2600/bes_chardev.c | 87 ++++++-- drivers/staging/bes2600/bes_chardev.h | 35 ++- drivers/staging/bes2600/bes_fw.c | 8 +- .../bes2600/bes_nl80211_testmode_msg.h | 10 + drivers/staging/bes2600/bes_pwr.c | 66 ++++-- drivers/staging/bes2600/bes_pwr.h | 2 + drivers/staging/bes2600/bh.c | 20 +- drivers/staging/bes2600/debug.c | 6 +- drivers/staging/bes2600/epta_request.c | 24 +- drivers/staging/bes2600/main.c | 58 +++-- drivers/staging/bes2600/pm.c | 165 ++++++++++++-- drivers/staging/bes2600/pm.h | 7 + drivers/staging/bes2600/queue.c | 210 +++++++++++++++--- drivers/staging/bes2600/queue.h | 5 +- drivers/staging/bes2600/scan.c | 10 +- drivers/staging/bes2600/sta.c | 156 +++++++++---- drivers/staging/bes2600/sta.h | 2 +- drivers/staging/bes2600/tx_loop.c | 5 + drivers/staging/bes2600/tx_loop.h | 2 + drivers/staging/bes2600/txrx.c | 88 ++++++-- drivers/staging/bes2600/txrx_opt.c | 170 +++++++++++--- drivers/staging/bes2600/txrx_opt.h | 11 +- drivers/staging/bes2600/wifi_testmode_cmd.c | 1 + drivers/staging/bes2600/wsm.c | 68 ++++-- drivers/staging/bes2600/wsm.h | 65 ++++-- 33 files changed, 1280 insertions(+), 391 deletions(-) diff --git a/drivers/staging/bes2600/Kconfig b/drivers/staging/bes2600/Kconfig index 374c15db823f..9c8de42ea6e0 100644 --- a/drivers/staging/bes2600/Kconfig +++ b/drivers/staging/bes2600/Kconfig @@ -4,10 +4,6 @@ config BES2600 select CFG80211 select NL80211_TESTMODE default m - ---help--- - This is an experimental driver for the bes2600 chip-set. - Enabling this option enables the generic driver without - any platform support. if BES2600 @@ -15,68 +11,48 @@ config BES2600_WLAN_SDIO bool "SDIO bus interface support" depends on MMC default y - ---help--- - This option enables the SDIO bus interface support for Bes2600 - WLAN driver. Say Y if you want to use SDIO. + config BES2600_WLAN_USB bool "USB bus interface support" depends on USB default n - ---help--- - This option enables the USB bus interface support for Bes2600 - WLAN driver. Say Y if you want to use USB. + config BES2600_WLAN_SPI bool "SPI bus interface support" depends on SPI default n - ---help--- - This option enables the SPI bus interface support for Bes2600 - WLAN driver. Say Y if you want to use USB. + config BES2600_USE_GPIO_IRQ bool "Use GPIO interrupt" default n - ---help--- - Say Y here if you want to include GPIO IRQ support instead of SDIO IRQ. - If unsure, say N. + config BES2600_5GHZ_SUPPORT bool "5GHz band support" default y - ---help--- - Say Y if your device supports 5GHz band. - If unsure, say N. + config BES2600_WAPI_SUPPORT bool "WAPI support" default y - ---help--- - Say Y if your compat-wireless support WAPI. - If unsure, say N. + config BES2600_USE_STE_EXTENSIONS bool "STE extensions" default n - ---help--- - Say Y if you want to include STE extensions. - If unsure, say N. + config BES2600_DISABLE_BEACON_HINTS bool "Disable 11d beacon hints" default n - ---help--- - Say Y if you want to disable 11d beacon hints. - If unsure, say N. config BES2600_TESTMODE bool "bes2600 testmode support" select NL80211_TESTMODE default n - ---help--- - Say Y if you want to enable bes2600 testmode. - If unsure, say N. menu "Driver debug features" @@ -110,9 +86,7 @@ config BES2600_DUMP_ON_ERROR config BES2600_ITP bool "Enable ITP DebugFS" - ---help--- - Say Y if you want to include ITP code. - If unsure, say N. + endmenu diff --git a/drivers/staging/bes2600/Makefile b/drivers/staging/bes2600/Makefile index 103519907e4f..6b41436f6d4e 100644 --- a/drivers/staging/bes2600/Makefile +++ b/drivers/staging/bes2600/Makefile @@ -6,11 +6,9 @@ CONFIG_BES2600_WLAN_SPI ?= n CONFIG_BES2600_WLAN_USB ?= n CONFIG_BES2600_VENDOR_CMD ?= y -ifneq ($(CONFIG_BES2600_WLAN_USB),y) -CONFIG_BES2600_TESTMODE ?= y -endif +CONFIG_BES2600_TESTMODE ?= n -CONFIG_BES2600_WAPI_SUPPORT ?= y +CONFIG_BES2600_WAPI_SUPPORT ?= n CONFIG_BES2600_5GHZ_SUPPORT ?= y CONFIG_BES2600_STA_DEBUG ?= y CONFIG_BES2600_STATIC_SDD ?= y @@ -31,17 +29,19 @@ CONFIG_BES2600_ITP ?= n CONFIG_BES2600_NON_POWER_OF_TWO_BLOCKSIZES ?= n CONFIG_BES2600_CALIB_FROM_LINUX ?= y -CONFIG_BES2600_WIFI_BOOT_ON ?= n +CONFIG_BES2600_WIFI_BOOT_ON ?= y CONFIG_BES2600_BT_BOOT_ON ?= n PLAT_ALLWINNER_T507 ?= n PLAT_ALLWINNER_R329 ?= n -PLAT_ROCKCHIP ?= y +PLAT_ROCKCHIP ?= n PLAT_UBUNTU_VUB300 ?= n PLAT_QCOM_QM215 ?= n +PLAT_CVITEK_182X ?= n -BES2600_GPIO_WAKEUP_AP ?= y +BES2600_GPIO_WAKEUP_AP ?= n BES2600_WRITE_DPD_TO_FILE ?= n +BES2600_TX_MORE_RETRY ?= n # bes evb BES2600_INDEPENDENT_EVB ?= n @@ -54,13 +54,13 @@ BES2600_INTEGRATED_MODULE_V3 ?= n # 0: use dynamic_ps_timeout value # other: override dynamic_ps_timeout value -BES2600_FASTPS_IDLE_TIME ?= 0 +BES2600_FASTPS_IDLE_TIME ?= 8 #1.rock api(fixed macaddr) #2.read from file(macaddr of customers) #3.read from file(macaddr template) #4.random macaddr -GET_MAC_ADDR_METHOD ?= 4 +GET_MAC_ADDR_METHOD ?= 0 ifeq ($(CONFIG_BES2600_DEBUGFS),y) BES2600_DUMP_FW_DPD_LOG ?= n @@ -73,7 +73,7 @@ ccflags-y += -DVENDOR_XM_KEEPALIVE endif endif -BES2600_DRV_VERSION := bes2600_0.3.10_2022.1125 +BES2600_DRV_VERSION := bes2600_0.3.5_2023.0209 ifeq ($(GET_MAC_ADDR_METHOD)_$(PLAT_ROCKCHIP),1_n) $(error Parameter setting error, GET_MAC_ADDR_METHOD can only be set to 1 on rockchip platform) @@ -89,7 +89,8 @@ endif ifeq ($(CONFIG_BES2600_CALIB_FROM_LINUX),y) FACTORY_CRC_CHECK ?= n -FACTORY_SAVE_MULTI_PATH ?= n +FACTORY_SAVE_MULTI_PATH ?= y +STANDARD_FACTORY_EFUSE_FLAG ?= y ifeq ($(FACTORY_SAVE_MULTI_PATH),y) FACTORY_PATH ?= /data/cfg/bes2600_factory.txt FACTORY_DEFAULT_PATH ?= /lib/firmware/bes2600_factory.txt @@ -100,7 +101,7 @@ FACTORY_PATH ?= /vendor/firmware/bes2600_factory.txt endif endif -FACTORY_PATH ?= /vendor/lib/firmware/bes2600_factory.txt +FACTORY_PATH ?= /lib/firmware/bes2600_factory.txt # basic function define boolen_flag @@ -144,7 +145,7 @@ ccflags-y += -DBES_UNIFIED_PM endif # CONFIG_BES2600_WLAN_SPI ifeq ($(CONFIG_BES2600_WLAN_USB),y) -FW_DOWNLOAD_BY_USB ?= n +FW_DOWNLOAD_BY_USB ?= y ccflags-y += -DCONFIG_BES2600_WLAN_BES endif # CONFIG_BES2600_WLAN_USB @@ -179,6 +180,7 @@ ccflags-y += $(call boolen_flag,PLAT_ALLWINNER_T507,y) ccflags-y += $(call boolen_flag,PLAT_UBUNTU_VUB300,y) ccflags-y += $(call boolen_flag,PLAT_ROCKCHIP,y) ccflags-y += $(call boolen_flag,PLAT_QCOM_QM215,y) +ccflags-y += $(call boolen_flag,PLAT_CVITEK_182X,y) ccflags-y += $(call boolen_flag,CONFIG_BES2600_VENDOR_CMD,y) @@ -192,6 +194,7 @@ ccflags-y += $(call boolen_flag,WIFI_BT_COEXIST_EPTA_ENABLE,y) ccflags-y += $(call boolen_flag,WIFI_BT_COEXIST_EPTA_FDD,y) ccflags-y += $(call boolen_flag,CONFIG_BES2600_DISABLE_BEACON_HINTS,y) ccflags-y += $(call boolen_flag,CONFIG_BES2600_NON_POWER_OF_TWO_BLOCKSIZES,y) +ccflags-y += $(call boolen_flag,BES2600_TX_MORE_RETRY,y) ccflags-y += $(call boolen_flag,CONFIG_BES2600_ITP,y) ccflags-y += $(call boolen_flag,CONFIG_BES2600_DEBUGFS,y) @@ -244,6 +247,7 @@ ccflags-y += $(call boolen_flag,BES2600_WRITE_DPD_TO_FILE,y) ccflags-y += $(call boolen_flag,BES2600_DUMP_FW_DPD_LOG,y) ccflags-y += $(call string_flag,BES2600_DPD_LOG_PATH) +ccflags-y += $(call boolen_flag,STANDARD_FACTORY_EFUSE_FLAG,y) # internal feature options ccflags-y += -DAP_HT_CAP_UPDATE @@ -259,6 +263,10 @@ ccflags-y += -DCHIP_WIFI_ROM_VER=1 ccflags-y += -DWIFI_OUT_FEM=0 ccflags-y += -DRF_TX_CONTROL_IO=16 +# stbc rx option +ccflags-y += -DSTBC_RX_24G=0 +ccflags-y += -DSTBC_RX_5G=0 + #ccflags-y += -DP2P_STA_COEX #ccflags-y += -DCUSTOM_FEATURE #ccflags-y += -DMCAST_FWDING @@ -267,7 +275,7 @@ ccflags-y += -DRF_TX_CONTROL_IO=16 # For offloading probe response to FW, the extra IE must be included # in the probe response template #ccflags-y += -DPROBE_RESP_EXTRA_IE -#ccflags-y += -DIPV6_FILTERING +ccflags-y += -DIPV6_FILTERING # basic files for building module bes2600-y := \ diff --git a/drivers/staging/bes2600/ap.c b/drivers/staging/bes2600/ap.c index 2126e7b516da..c6a4b8c29106 100644 --- a/drivers/staging/bes2600/ap.c +++ b/drivers/staging/bes2600/ap.c @@ -30,7 +30,7 @@ #define BES2600_ENABLE_ARP_FILTER_OFFLOAD 3 -#define BES2600_KEEP_ALIVE_PERIOD (20) +#define BES2600_KEEP_ALIVE_PERIOD (15) #ifndef ERP_INFO_BYTE_OFFSET #define ERP_INFO_BYTE_OFFSET 2 @@ -249,8 +249,11 @@ static int bes2600_set_tim_impl(struct bes2600_vif *priv, bool aid0_bit_set) bes2600_dbg(BES2600_DBG_AP, "[AP] %s mcast: %s.\n", __func__, aid0_bit_set ? "ena" : "dis"); - skb = ieee80211_beacon_get_tim(priv->hw, priv->vif, - &tim_offset, &tim_length); + // skb = ieee80211_beacon_get_tim(priv->hw, priv->vif, + // &tim_offset, &tim_length); + skb = ieee80211_beacon_get_tim(priv->hw, priv->vif, + &tim_offset, &tim_length, 0); + if (!skb) { if (!__bes2600_flush(hw_priv, true, priv->if_id)) wsm_unlock_tx(hw_priv); @@ -393,18 +396,19 @@ static int bes2600_set_btcoexinfo(struct bes2600_vif *priv) void bes2600_bss_info_changed(struct ieee80211_hw *dev, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, - u32 changed) + u64 changed) { struct bes2600_common *hw_priv = dev->priv; struct bes2600_vif *priv = cw12xx_get_vif_from_ieee80211(vif); struct ieee80211_conf *conf = &dev->conf; const u8 override_fpsm_timeout = BES2600_FASTPS_IDLE_TIME; + struct ieee80211_vif_cfg cfg; #ifdef P2P_MULTIVIF if (priv->if_id == CW12XX_GENERIC_IF_ID) return; #endif - bes2600_info(BES2600_DBG_AP, "BSS CHANGED: %08x\n", changed); + bes2600_info(BES2600_DBG_AP, "BSS CHANGED: %08llx\n", changed); down(&hw_priv->conf_lock); if (changed & BSS_CHANGED_BSSID) { #ifdef CONFIG_BES2600_TESTMODE @@ -430,19 +434,19 @@ void bes2600_bss_info_changed(struct ieee80211_hw *dev, struct wsm_arp_ipv4_filter filter = {0}; int i; bes2600_dbg(BES2600_DBG_AP, "[STA] BSS_CHANGED_ARP_FILTER cnt: %d", - info->arp_addr_cnt); + vif->cfg.arp_addr_cnt); #ifdef WIFI_BT_COEXIST_EPTA_ENABLE - if (info->arp_addr_cnt > 0) { + if (vif->cfg.arp_addr_cnt > 0) { bwifi_change_current_status(hw_priv, BWIFI_STATUS_GOT_IP); } #endif /* Currently only one IP address is supported by firmware. * In case of more IPs arp filtering will be disabled. */ - if (info->arp_addr_cnt > 0 && - info->arp_addr_cnt <= WSM_MAX_ARP_IP_ADDRTABLE_ENTRIES) { - for (i = 0; i < info->arp_addr_cnt; i++) { - filter.ipv4Address[i] = info->arp_addr_list[i]; + if (vif->cfg.arp_addr_cnt > 0 && + vif->cfg.arp_addr_cnt <= WSM_MAX_ARP_IP_ADDRTABLE_ENTRIES) { + for (i = 0; i < vif->cfg.arp_addr_cnt; i++) { + filter.ipv4Address[i] = vif->cfg.arp_addr_list[i]; bes2600_dbg(BES2600_DBG_AP, "[STA] addr[%d]: 0x%X\n", i, filter.ipv4Address[i]); } @@ -490,7 +494,7 @@ void bes2600_bss_info_changed(struct ieee80211_hw *dev, priv->power_set_true = 0; priv->user_power_set_true = 0; - if(!info->ps) { + if(!cfg.ps) { bes2600_pwr_set_busy_event(priv->hw_priv, BES_PWR_LOCK_ON_PS_ACTIVE); } } @@ -498,7 +502,8 @@ void bes2600_bss_info_changed(struct ieee80211_hw *dev, bes2600_pwr_clear_busy_event(priv->hw_priv, BES_PWR_LOCK_ON_GET_IP); } -#ifdef IPV6_FILTERING +// #if (defined(IPV6_FILTERING) && LINUX_VERSION_CODE > KERNEL_VERSION(4,19,0)) +#if 0 if (changed & BSS_CHANGED_NDP_FILTER) { struct wsm_ndp_ipv6_filter filter = {0}; int i; @@ -606,7 +611,7 @@ void bes2600_bss_info_changed(struct ieee80211_hw *dev, priv->wep_default_key_id = -1; wsm_unlock_tx(hw_priv); - if (!info->assoc /* && !info->ibss_joined */) { + if (!cfg.assoc /* && !info->ibss_joined */) { #ifdef P2P_STA_COEX priv->cqm_link_loss_count = 400; priv->cqm_beacon_loss_count = 200; @@ -628,8 +633,8 @@ void bes2600_bss_info_changed(struct ieee80211_hw *dev, int is_combo = 0; int i; struct bes2600_vif *tmp_priv; - bes2600_info(BES2600_DBG_AP, "BSS_CHANGED_ASSOC assoc: %d.\n", info->assoc); - if (info->assoc) { /* TODO: ibss_joined */ + bes2600_info(BES2600_DBG_AP, "BSS_CHANGED_ASSOC assoc: %d.\n", vif->cfg.assoc ); + if (cfg.assoc) { /* TODO: ibss_joined */ struct ieee80211_sta *sta = NULL; if (info->dtim_period) priv->join_dtim_period = info->dtim_period; @@ -640,7 +645,9 @@ void bes2600_bss_info_changed(struct ieee80211_hw *dev, cancel_delayed_work_sync(&priv->join_timeout); bes2600_pwr_clear_busy_event(priv->hw_priv, BES_PWR_LOCK_ON_JOIN); bes2600_pwr_set_busy_event(priv->hw_priv, BES_PWR_LOCK_ON_GET_IP); - txrx_opt_timer_init(priv->hw_priv); +#ifdef BES2600_TX_RX_OPT + txrx_opt_timer_init(priv); +#endif } rcu_read_lock(); @@ -651,11 +658,11 @@ void bes2600_bss_info_changed(struct ieee80211_hw *dev, * mac80211 changes are available */ enum nl80211_channel_type ch_type; BUG_ON(!hw_priv->channel); - hw_priv->ht_info.ht_cap = sta->ht_cap; + hw_priv->ht_info.ht_cap = sta->deflink.ht_cap; priv->bss_params.operationalRateSet = __cpu_to_le32( bes2600_rate_mask_to_wsm(hw_priv, - sta->supp_rates[ + sta->deflink.supp_rates[ hw_priv->channel->band])); rcu_read_unlock(); ch_type = cfg80211_get_chandef_type(&info->chandef); @@ -769,7 +776,7 @@ void bes2600_bss_info_changed(struct ieee80211_hw *dev, priv->cqm_beacon_loss_count : priv->cqm_link_loss_count; - priv->bss_params.aid = info->aid; + priv->bss_params.aid = cfg.aid; if (priv->join_dtim_period < 1) priv->join_dtim_period = 1; @@ -975,7 +982,7 @@ void bes2600_bss_info_changed(struct ieee80211_hw *dev, if (changed & BSS_CHANGED_BANDWIDTH) { enum nl80211_channel_type ch_type = cfg80211_get_chandef_type(&info->chandef); - if (info->assoc && + if (cfg.assoc && hw_priv->ht_info.channel_type != ch_type && priv->join_status == BES2600_JOIN_STATUS_STA) { struct wsm_switch_channel channel; @@ -990,7 +997,7 @@ void bes2600_bss_info_changed(struct ieee80211_hw *dev, } if (changed & BSS_CHANGED_PS) { - if (info->ps == false) + if (cfg.ps == false) priv->powersave_mode.pmMode = WSM_PSM_ACTIVE; else if (conf->dynamic_ps_timeout <= 0) priv->powersave_mode.pmMode = WSM_PSM_PS; @@ -999,7 +1006,7 @@ void bes2600_bss_info_changed(struct ieee80211_hw *dev, /* set/clear ps active power busy event */ if(priv->join_status == BES2600_JOIN_STATUS_STA) { - if(!info->ps) { + if(!cfg.ps) { bes2600_pwr_set_busy_event(priv->hw_priv, BES_PWR_LOCK_ON_PS_ACTIVE); } else { bes2600_pwr_clear_busy_event(priv->hw_priv, BES_PWR_LOCK_ON_PS_ACTIVE); @@ -1292,7 +1299,8 @@ static int bes2600_upload_beacon(struct bes2600_vif *priv) #endif frame.rate = WSM_TRANSMIT_RATE_6; - frame.skb = ieee80211_beacon_get(priv->hw, priv->vif); + // frame.skb = ieee80211_beacon_get(priv->hw, priv->vif); + frame.skb = ieee80211_beacon_get(priv->hw, priv->vif, 0); if (WARN_ON(!frame.skb)) return -ENOMEM; @@ -1461,7 +1469,8 @@ static int bes2600_upload_null(struct bes2600_vif *priv) }; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) - frame.skb = ieee80211_nullfunc_get(priv->hw, priv->vif, false); + // frame.skb = ieee80211_nullfunc_get(priv->hw, priv->vif, false); + frame.skb = ieee80211_nullfunc_get(priv->hw, priv->vif, -1, true); #else frame.skb = ieee80211_nullfunc_get(priv->hw, priv->vif); #endif @@ -1486,7 +1495,8 @@ static int bes2600_upload_qosnull(struct bes2600_vif *priv) }; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) - frame.skb = ieee80211_nullfunc_get(priv->hw, priv->vif, true); + // frame.skb = ieee80211_nullfunc_get(priv->hw, priv->vif, true); + frame.skb = ieee80211_nullfunc_get(priv->hw, priv->vif, -1, true); #else frame.skb = ieee80211_nullfunc_get(priv->hw, priv->vif); #endif @@ -1609,7 +1619,8 @@ static int bes2600_start_ap(struct bes2600_vif *priv) #ifndef HIDDEN_SSID /* Get SSID */ - skb = ieee80211_beacon_get(priv->hw, priv->vif); + // skb = ieee80211_beacon_get(priv->hw, priv->vif); + skb = ieee80211_beacon_get(priv->hw, priv->vif, 0); if (WARN_ON(!skb)) return -ENOMEM; @@ -1960,7 +1971,8 @@ void bes2600_ht_info_update_work(struct work_struct *work) .count = 1, }; - skb = ieee80211_beacon_get(priv->hw, priv->vif); + // skb = ieee80211_beacon_get(priv->hw, priv->vif); + skb = ieee80211_beacon_get(priv->hw, priv->vif, 0); if (WARN_ON(!skb)) return; diff --git a/drivers/staging/bes2600/ap.h b/drivers/staging/bes2600/ap.h index f9d85d847397..63874ccf33e2 100644 --- a/drivers/staging/bes2600/ap.h +++ b/drivers/staging/bes2600/ap.h @@ -26,7 +26,7 @@ void bes2600_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif, void bes2600_bss_info_changed(struct ieee80211_hw *dev, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info, - u32 changed); + u64 changed); int bes2600_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, diff --git a/drivers/staging/bes2600/bes2600.h b/drivers/staging/bes2600/bes2600.h index ecfe154a0283..d31dd8cf683e 100644 --- a/drivers/staging/bes2600/bes2600.h +++ b/drivers/staging/bes2600/bes2600.h @@ -33,8 +33,8 @@ #define CW12XX_GENERIC_IF_ID (2) #define CW12XX_HOST_VIF0_11N_THROTTLE (63) #define CW12XX_HOST_VIF1_11N_THROTTLE (63) -#define CW12XX_HOST_VIF0_11BG_THROTTLE (15) -#define CW12XX_HOST_VIF1_11BG_THROTTLE (15) +#define CW12XX_HOST_VIF0_11BG_THROTTLE (20) +#define CW12XX_HOST_VIF1_11BG_THROTTLE (20) #if 0 #define CW12XX_FW_VIF0_THROTTLE (15) #define CW12XX_FW_VIF1_THROTTLE (15) @@ -374,6 +374,13 @@ struct bes2600_common { atomic_t bh_term; atomic_t bh_suspend; +#ifdef CONFIG_PM + /*Suspend*/ + u8 unjoin_if_id_slots; + bool suspend_in_progress; + struct notifier_block pm_notify; +#endif + struct workqueue_struct *bh_workqueue; struct work_struct bh_work; @@ -642,24 +649,28 @@ struct bes2600_vif { #endif bool pmf; - u32 hw_value; - /* dot11CountersTable */ - u32 dot11TransmittedFragmentCount; - u32 dot11MulticastTransmittedFrameCount; - u32 dot11FailedCount; - u32 dot11RetryCount; - u32 dot11MultipleRetryCount; - u32 dot11FrameDuplicateCount; - u32 dot11ReceivedFragmentCount; - u32 dot11RxReorderLeakCount; - u32 dot11ReceivedBytes; - u32 dot11ReceivedDataBytes; - u32 dot11MulticastReceivedFrameCount; - u32 dot11TransmittedFrameCount; - u32 dot11TransmittedBytes; - u32 dot11TransmittedDataBytes; - u32 dot11Txbps; - u32 dot11Rxbps; + u32 hw_value; + /* dot11CountersTable */ + u32 dot11TransmittedFragmentCount; + u32 dot11MulticastTransmittedFrameCount; + u32 dot11FailedCount; + u32 dot11RetryCount; + u32 dot11MultipleRetryCount; + u32 dot11FrameDuplicateCount; + u32 dot11ReceivedFragmentCount; + u32 dot11RxReorderLeakCount; + u32 dot11ReceivedBytes; + u32 dot11ReceivedDataBytes; + u32 dot11MulticastReceivedFrameCount; + u32 dot11TransmittedFrameCount; + u32 dot11TransmittedBytes; + u32 dot11TransmittedDataBytes; + u32 dot11Txbps; + u32 dot11Rxbps; + + /* used to calculate signal strength */ + s32 signal; + s32 signal_mul; }; struct bes2600_sta_priv { int link_id; diff --git a/drivers/staging/bes2600/bes2600_factory.c b/drivers/staging/bes2600/bes2600_factory.c index c525311c2a30..f1a7a84027c2 100644 --- a/drivers/staging/bes2600/bes2600_factory.c +++ b/drivers/staging/bes2600/bes2600_factory.c @@ -100,13 +100,17 @@ static int bes2600_factory_crc_check(struct factory_t *factory_data) { #ifdef FACTORY_CRC_CHECK u32 cal_crc = 0; + u32 crc_len = sizeof(factory_data_t); +#ifndef STANDARD_FACTORY_EFUSE_FLAG + crc_len = (crc_len - sizeof(u16) + 3) & (~0x3); +#endif if (!factory_data) { bes2600_err(BES2600_DBG_FACTORY, "%s NULL pointer err \n", __func__); return -1; } - cal_crc = factory_crc32((uint8_t *)(&(factory_data->data)), sizeof(factory_data_t)); + cal_crc = factory_crc32((uint8_t *)(&(factory_data->data)), crc_len); if (factory_data->head.crc != cal_crc) { bes2600_err(BES2600_DBG_CHARDEV, "bes2600 factory check failed, calc_crc:0x%08x factory_crc: 0x%08x\n", @@ -243,9 +247,19 @@ static inline int factory_parse(uint8_t *source_buf, struct factory_t *factory) &factory->data.bt_tx_power[0],\ &factory->data.bt_tx_power[1],\ &factory->data.bt_tx_power[2],\ - &factory->data.bt_tx_power[3]); + &factory->data.bt_tx_power[3] +#ifdef STANDARD_FACTORY_EFUSE_FLAG + ,&factory->data.select_efuse); +#else + ); +#endif - if (ret != 30) { +#ifndef STANDARD_FACTORY_EFUSE_FLAG + factory->data.select_efuse = 0; +#endif + + if (ret != FACTORY_MEMBER_NUM) + { bes2600_err(BES2600_DBG_FACTORY, "bes2600_factory.txt parse fail\n"); return -1; } @@ -401,6 +415,7 @@ void factory_little_endian_cvrt(u8 *data) TRANS_LE16(trans_data->data.tx_power_flags_5G); TRANS_LE16(trans_data->data.temperature_5G); + TRANS_LE16(trans_data->data.select_efuse); } @@ -520,6 +535,9 @@ static int bes2600_factory_cali_file_hdr_fill(struct factory_t **factory_head) (*factory_head)->data.bt_tx_power[1] = 0x10; (*factory_head)->data.bt_tx_power[2] = 0x05; (*factory_head)->data.bt_tx_power[3] = 0x15; +#ifdef STANDARD_FACTORY_EFUSE_FLAG + (*factory_head)->data.select_efuse = 0; +#endif return 0; } @@ -741,6 +759,49 @@ int16_t bes2600_wifi_cali_freq_write(struct wifi_freq_cali_t *data_cali) return ret; } +#ifdef STANDARD_FACTORY_EFUSE_FLAG +int16_t bes2600_select_efuse_flag_write(uint16_t select_efuse_flag) +{ + struct factory_t *factory_flag_p = NULL; + u8 *file_buffer = NULL; + int16_t ret = 0; + + if (!(file_buffer = bes2600_factory_get_file_buffer())) + return -FACTORY_GET_INPUT_NULL_POINTER; + + bes2600_factory_lock(); + + /** + * When it returns true, it means that the factory file has been read. + * When it returns false, it means that the factory file does not exist, + * or the operation of reading the text file fails. At this time, a new factory file will be created. + */ + if (bes2600_factory_file_status_read(file_buffer)) { + factory_flag_p = factory_p; + } else { + if (bes2600_factory_cali_file_hdr_fill(&factory_flag_p)) { + bes2600_warn(BES2600_DBG_FACTORY, "%s, create bes2600_factory.txt fail.", __func__); + ret = -FACTORY_FACTORY_TXT_CREATE_FAIL; + goto err; + } + } + + factory_flag_p->data.select_efuse = select_efuse_flag; + bes2600_dbg(BES2600_DBG_FACTORY, "%s: select_efuse = %x\n", __func__, select_efuse_flag); + + /* save to file */ + if (bes2600_wifi_cali_table_save(file_buffer, factory_flag_p)) { + ret = -FACTORY_SAVE_WRITE_ERR; + goto err; + } + +err: + bes2600_factory_free_file_buffer(file_buffer); + bes2600_factory_unlock(); + return ret; +} +#endif + int16_t vendor_set_power_cali_flag(struct wifi_power_cali_flag_t *cali_flag) { struct factory_t *factory_power_flag_p = NULL; @@ -823,13 +884,22 @@ static inline int factory_build(uint8_t *dest_buf, struct factory_t *factory) factory->data.bt_tx_power[0],\ factory->data.bt_tx_power[1],\ factory->data.bt_tx_power[2],\ - factory->data.bt_tx_power[3]); + factory->data.bt_tx_power[3] +#ifdef STANDARD_FACTORY_EFUSE_FLAG + ,factory->data.select_efuse); +#else + ); +#endif } static int bes2600_wifi_cali_table_save(u8 *file_buffer, struct factory_t *factory_save_p) { int ret = 0; int w_size; + u32 crc_len = sizeof(factory_data_t); +#ifndef STANDARD_FACTORY_EFUSE_FLAG + crc_len = (crc_len - sizeof(u16) + 3) & (~0x3); +#endif bes2600_info(BES2600_DBG_FACTORY, "enter %s\n", __func__); @@ -846,7 +916,7 @@ static int bes2600_wifi_cali_table_save(u8 *file_buffer, struct factory_t *facto file_buffer[FACTORY_MAX_SIZE - 1] = '\n'; factory_save_p->head.crc = - factory_crc32((uint8_t *)(&(factory_save_p->data)), sizeof(factory_data_t)); + factory_crc32((uint8_t *)(&(factory_save_p->data)), crc_len); w_size = factory_build(file_buffer, factory_save_p); diff --git a/drivers/staging/bes2600/bes2600_factory.h b/drivers/staging/bes2600/bes2600_factory.h index 473840282a82..3835b0d9c96c 100644 --- a/drivers/staging/bes2600/bes2600_factory.h +++ b/drivers/staging/bes2600/bes2600_factory.h @@ -19,7 +19,7 @@ #define NVREC_CURRENT_VERSION 2 #define FACTORY_MAX_SIZE 600 -#define STANDARD_FACTORY "##head\n\ +#define __STANDARD_FACTORY "##head\n\ magic:0x%hx\n\ version:0x%hx\n\ crc:0x%x\n\ @@ -53,8 +53,17 @@ temperature_5G:0x%hx\n\ bdr_div:0x%x\n\ bdr_power:0x%x\n\ edr_div:0x%x\n\ -edr_power:0x%x\n\ -%%%%\n" +edr_power:0x%x\n" + +#ifdef STANDARD_FACTORY_EFUSE_FLAG +#define STANDARD_FACTORY_EFUSE "##select_efuse_flag\nselect_efuse:%hx\n" +#define FACTORY_MEMBER_NUM 31 +#else +#define STANDARD_FACTORY_EFUSE +#define FACTORY_MEMBER_NUM 30 +#endif + +#define STANDARD_FACTORY __STANDARD_FACTORY STANDARD_FACTORY_EFUSE "%%%%\n" typedef struct { uint16_t magic; @@ -103,6 +112,7 @@ typedef struct { uint32_t bt_tx_power[4]; /* The temperature after 5G clibrating. */ uint16_t temperature_5G; + uint16_t select_efuse; } factory_data_t; struct factory_t { @@ -204,5 +214,7 @@ int16_t bes2600_wifi_cali_freq_write(struct wifi_freq_cali_t *data_cali); int16_t vendor_get_freq_cali(struct wifi_freq_cali_t *vendor_freq); int16_t vendor_get_power_cali(struct wifi_get_power_cali_t *power_cali); int16_t vendor_set_power_cali_flag(struct wifi_power_cali_flag_t *cali_flag); - +#ifdef STANDARD_FACTORY_EFUSE_FLAG +int16_t bes2600_select_efuse_flag_write(uint16_t select_efuse_flag); +#endif #endif diff --git a/drivers/staging/bes2600/bes2600_sdio.c b/drivers/staging/bes2600/bes2600_sdio.c index 5252951cc3bb..d9b60c72fd45 100644 --- a/drivers/staging/bes2600/bes2600_sdio.c +++ b/drivers/staging/bes2600/bes2600_sdio.c @@ -47,6 +47,15 @@ extern void sw_mci_rescan_card(unsigned id, unsigned insert); extern void sunxi_wlan_set_power(bool on_off); #endif +#ifdef PLAT_CVITEK_182X +#include + +extern int cvi_sdio_rescan(void); +extern int cvi_get_wifi_pwr_on_gpio(void); +extern int cvi_get_wifi_reset_gpio(void); +extern int cvi_get_wifi_wakeup_gpio(void); +#endif + #if defined(BES2600_BOOT_UART_TO_SDIO) static struct sbus_ops bes2600_sdio_sbus_ops; extern int bes2600_boot_uart_to_sdio(struct sbus_ops *ops); @@ -434,15 +443,23 @@ static int bes2600_sdio_reg_write(struct sbus_priv *self, u32 reg, #ifndef CONFIG_BES2600_USE_GPIO_IRQ static void bes2600_sdio_irq_handler(struct sdio_func *func) { +#ifdef PLAT_CVITEK_182X + int ret =0; +#endif struct sbus_priv *self = sdio_get_drvdata(func); unsigned long flags; - bes2600_dbg(BES2600_DBG_SDIO, "\n %s called, fw_started:%d \n", - __func__, self->fw_started); if (WARN_ON(!self)) { return; } + bes2600_dbg(BES2600_DBG_SDIO, "\n %s called, fw_started:%d \n", + __func__, self->fw_started); +#ifdef PLAT_CVITEK_182X + sdio_claim_host(func); + sdio_readb(func, 1, &ret); + sdio_release_host(func); +#endif if (likely(self->fw_started && self->core)) { queue_work(self->sdio_wq, &self->rx_work); self->last_irq_timestamp = jiffies; @@ -598,6 +615,16 @@ static int bes2600_sdio_off(const struct bes2600_platform_data_sdio *pdata) rockchip_wifi_power(0); #endif +#ifdef PLAT_CVITEK_182X + if (gpio_is_valid(pdata->powerup)) { + gpio_direction_output(pdata->powerup, 0); + } + + if (gpio_is_valid(pdata->reset)) { + gpio_direction_output(pdata->reset, 0); + } +#endif + if (pdata == NULL) return 0; @@ -626,6 +653,18 @@ static int bes2600_sdio_on(const struct bes2600_platform_data_sdio *pdata) rockchip_wifi_set_carddetect(1); #endif +#ifdef PLAT_CVITEK_182X + if (gpio_is_valid(pdata->powerup)) { + gpio_direction_output(pdata->powerup, 1); + } + + msleep(10); + if (gpio_is_valid(pdata->reset)) { + gpio_direction_output(pdata->reset, 0); + } + cvi_sdio_rescan(); +#endif + if (pdata != NULL) { #ifdef BES2600_INDEPENDENT_EVB if (gpio_is_valid(pdata->powerup)) { @@ -1019,6 +1058,10 @@ static void sdio_scan_work(struct work_struct *work) #ifdef PLAT_ROCKCHIP rockchip_wifi_set_carddetect(1); #endif + +#ifdef PLAT_CVITEK_182X + cvi_sdio_rescan(); +#endif bes2600_info(BES2600_DBG_SDIO, "%s: power down, rescan card\n", __FUNCTION__); } @@ -1362,7 +1405,7 @@ static int bes2600_sdio_misc_init(struct sbus_priv *self, struct bes2600_common return 0; } -#if defined(PLAT_ALLWINNER)|| defined (PLAT_ROCKCHIP) +#if defined(PLAT_ALLWINNER)|| defined (PLAT_ROCKCHIP) || defined(PLAT_CVITEK_182X) static struct bes2600_platform_data_sdio bes_sdio_plat_data = { #if defined(BES2600_INDEPENDENT_EVB) .reset = GPIOA(9), @@ -1380,27 +1423,34 @@ static struct bes2600_platform_data_sdio bes_sdio_plat_data = { .reset = -1, .powerup = -1, .wakeup = -1, +#elif defined(PLAT_CVITEK_182X) + .reset = -1, + .powerup = -1, + .wakeup = -1, + .host_wakeup = -1, #endif }; #endif struct bes2600_platform_data_sdio *bes2600_get_platform_data(void) { -#if defined(PLAT_ALLWINNER)|| defined (PLAT_ROCKCHIP) +#if defined(PLAT_ALLWINNER)|| defined (PLAT_ROCKCHIP) || defined(PLAT_CVITEK_182X) return &bes_sdio_plat_data; #else return NULL; #endif } -static void bes2600_get_gpio_from_dts(int *gpio_num, const char *gpio_name) + +static void __attribute__((unused)) bes2600_get_gpio_from_dts(int *gpio_num, const char *gpio_name) { int wakeup_gpio; - enum of_gpio_flags flags; + // enum of_gpio_flags flags; struct device_node *wireless_node; wireless_node = of_find_node_with_property(NULL, gpio_name); if(wireless_node != NULL){ - wakeup_gpio = of_get_named_gpio_flags(wireless_node, gpio_name, 0, &flags); + // wakeup_gpio = of_get_named_gpio_flags(wireless_node, gpio_name, 0, &flags); + wakeup_gpio = of_get_named_gpio(wireless_node, gpio_name, 0); if (gpio_is_valid(wakeup_gpio)) *gpio_num = wakeup_gpio; }else{ @@ -1408,6 +1458,7 @@ static void bes2600_get_gpio_from_dts(int *gpio_num, const char *gpio_name) } } + static int bes2600_platform_data_init(void) { int ret = 0; @@ -1416,6 +1467,9 @@ static int bes2600_platform_data_init(void) return 0; /* Ensure I/Os are pulled low */ +#ifdef PLAT_CVITEK_182X + pdata->reset=cvi_get_wifi_reset_gpio(); +#endif if (gpio_is_valid(pdata->reset)) { ret = gpio_request(pdata->reset, "bes2600_wlan_reset"); if (ret) { @@ -1427,7 +1481,9 @@ static int bes2600_platform_data_init(void) } else { bes2600_err(BES2600_DBG_SDIO, "reset is invalid\n"); } - +#ifdef PLAT_CVITEK_182X + pdata->powerup=cvi_get_wifi_pwr_on_gpio(); +#endif if (gpio_is_valid(pdata->powerup)) { ret = gpio_request(pdata->powerup, "bes2600_wlan_powerup"); if (ret) { @@ -1439,8 +1495,11 @@ static int bes2600_platform_data_init(void) } else { bes2600_err(BES2600_DBG_SDIO, "powerup is invalid\n"); } - +#ifdef PLAT_CVITEK_182X + pdata->wakeup=cvi_get_wifi_wakeup_gpio(); +#else bes2600_get_gpio_from_dts(&pdata->wakeup, "WIFI,host_wakeup_wifi"); +#endif if (gpio_is_valid(pdata->wakeup)) { ret = gpio_request(pdata->wakeup, "bes2600_wakeup"); if (ret) { @@ -1452,8 +1511,9 @@ static int bes2600_platform_data_init(void) } else { bes2600_err(BES2600_DBG_SDIO, "wakeup is invalid\n"); } - +#ifndef PLAT_CVITEK_182X bes2600_get_gpio_from_dts(&pdata->host_wakeup, "WIFI,host_wake_irq"); +#endif if (gpio_is_valid(pdata->host_wakeup)) { ret = gpio_request(pdata->host_wakeup, "bes2600_host_irq"); if (ret) { @@ -1957,6 +2017,14 @@ static void bes2600_sdio_power_down(struct sbus_priv *self) #if defined(PLAT_ALLWINNER) sunxi_wlan_set_power(false); #endif + +#ifdef PLAT_CVITEK_182X + struct bes2600_platform_data_sdio *pdata = bes2600_get_platform_data(); + + if (gpio_is_valid(pdata->powerup)) { + gpio_direction_output(pdata->powerup, 0); + } +#endif #endif msleep(10); @@ -2232,6 +2300,7 @@ static irqreturn_t bes2600_wlan_bt_hostwake_thread(int irq, void *dev_id) bes2600_info(BES2600_DBG_SDIO, "bes2600_wlan_hostwake:%d\n", dev_id == (void *)pdata); if (dev_id == (void *)pdata) { + bes2600_chrdev_wakeup_by_event_set(WAKEUP_EVENT_SETTING); pdata->wakeup_source = true; disable_irq_nosync(irq); return IRQ_HANDLED; @@ -2277,9 +2346,9 @@ static int bes2600_wlan_bt_hostwake_register(void) static void bes2600_wlan_bt_hostwake_unregister(void) { + int ret = 0; struct bes2600_platform_data_sdio *pdata = bes2600_get_platform_data(); - int ret = 0; #if defined(PLAT_ALLWINNER) int irq = sunxi_wlan_get_oob_irq(); #elif defined(PLAT_ROCKCHIP) diff --git a/drivers/staging/bes2600/bes_chardev.c b/drivers/staging/bes2600/bes_chardev.c index 77573e59952e..e4c81cf0c922 100644 --- a/drivers/staging/bes2600/bes_chardev.c +++ b/drivers/staging/bes2600/bes_chardev.c @@ -73,7 +73,10 @@ struct bes_cdev int no_dpd; #endif enum pend_read_op read_flag; - u32 wakeup_state; /* for userspace check wakeup reason */ + enum wakeup_event wakeup_by_event; /* used to filter unwanted event wakeup reason report */ + u16 wakeup_state; /* for userspace check wakeup reason */ + wait_queue_head_t wakeup_reason_wq; + u16 src_port; #ifdef BES2600_DUMP_FW_DPD_LOG u8 *dpd_log; u16 dpd_log_len; @@ -608,10 +611,17 @@ static ssize_t bes2600_chrdev_read(struct file *file, char __user *user_buf, { char buf[64] = {0}; unsigned int len; + long status = 0; switch (bes2600_cdev.read_flag) { case BES_CDEV_READ_WAKEUP_STATE: - len = sprintf(buf, "wakeup_state:%u\n", bes2600_cdev.wakeup_state); + if (bes2600_chrdev_wakeup_by_event_get() > WAKEUP_EVENT_NONE) { + status = wait_event_timeout(bes2600_cdev.wakeup_reason_wq, + bes2600_chrdev_wakeup_by_event_get() == WAKEUP_EVENT_NONE, HZ * 2); + WARN_ON(status <= 0); + } + len = sprintf(buf, "wakeup_reason: %u, src_port: %u\n", + bes2600_cdev.wakeup_state, bes2600_cdev.src_port); break; default: len = sprintf(buf, "dpd_calied:%d wifi_opened:%d bt_opened:%d fw_type:%d\n", @@ -729,13 +739,35 @@ static int bes2600_chrdev_write_dpd_data_to_file(const char *path, void *buffer, return ret; } +static bool bes2600_chrdev_dpd_is_vaild(u8 *dpd_data) +{ + u32 cal_crc = 0; + u32 dpd_crc = le32_to_cpup((__le32 *)(dpd_data)); + u32 dpd_ver = le32_to_cpup((__le32 *)(dpd_data + DPD_VERSION_OFFSET)); + + /* check version */ + if (dpd_ver < DPD_CUR_VERSION) + return false; + + cal_crc ^= 0xffffffffL; + cal_crc = crc32_le(cal_crc, dpd_data + 4, DPD_BIN_SIZE - 4); + cal_crc ^= 0xffffffffL; + + /* check if the dpd data is valid */ + if (cal_crc != dpd_crc) { + bes2600_err(BES2600_DBG_CHARDEV, + "bes2600 dpd data from file check failed, calc_crc:0x%08x dpd_crc: 0x%08x\n", + cal_crc, dpd_crc); + return false; + } + + return true; +} + static int bes2600_chrdev_read_and_check_dpd_data(const char *file, u8 **data, u32 *len) { int ret = 0; - u32 read_len = 0; u8* read_data = NULL; - u32 cal_crc = 0; - u32 dpd_crc = 0; struct file *fp; /* open file */ @@ -773,27 +805,16 @@ static int bes2600_chrdev_read_and_check_dpd_data(const char *file, u8 **data, u goto err2; } - /* calculate crc value */ - read_len = DPD_BIN_SIZE; - dpd_crc = *((u32 *)read_data); - cal_crc ^= 0xffffffffL; - cal_crc = crc32_le(cal_crc, read_data + 4, read_len - 4); - cal_crc ^= 0xffffffffL; - - /* check if the dpd data is valid */ - if(cal_crc != dpd_crc) { - bes2600_err(BES2600_DBG_CHARDEV, - "bes2600 dpd data from file check failed, calc_crc:0x%08x dpd_crc: 0x%08x\n", - cal_crc, dpd_crc); + /* check dpd version and crc */ + if (!bes2600_chrdev_dpd_is_vaild(read_data)) goto err2; - } /* close file */ filp_close(fp, NULL); /* copy data to external */ *data = read_data; - *len = read_len; + *len = DPD_BIN_SIZE;; /* output debug information */ bes2600_info(BES2600_DBG_CHARDEV, "read dpd data from %s\n", file); @@ -862,7 +883,7 @@ void bes2600_chrdev_free_dpd_data(void) int bes2600_chrdev_update_dpd_data(void) { u32 cal_crc = 0; - u32 dpd_crc = *((u32 *)bes2600_cdev.dpd_data); + u32 dpd_crc = le32_to_cpup((__le32 *)(bes2600_cdev.dpd_data)); /* check if the dpd data is valid */ cal_crc ^= 0xffffffffL; @@ -1165,7 +1186,7 @@ void bes2600_chrdev_start_bus_probe(void) spin_unlock(&bes2600_cdev.status_lock); cancel_delayed_work_sync(&bes2600_cdev.probe_timeout_work); - schedule_delayed_work(&bes2600_cdev.probe_timeout_work, (HZ * 8) / 10); + schedule_delayed_work(&bes2600_cdev.probe_timeout_work, 3 * HZ); } void bes2600_chrdev_bus_probe_notify(void) @@ -1178,13 +1199,30 @@ void bes2600_chrdev_bus_probe_notify(void) wake_up(&bes2600_cdev.probe_done_wq); } -void bes2600_chrdev_wifi_update_wakeup_reason(u32 val) +#if defined(CONFIG_BES2600_WLAN_SDIO) || defined(CONFIG_BES2600_WLAN_SPI) +void bes2600_chrdev_wifi_update_wakeup_reason(u16 reason, u16 port) { spin_lock(&bes2600_cdev.status_lock); - bes2600_cdev.wakeup_state = val; + bes2600_cdev.wakeup_state = reason; + bes2600_cdev.src_port = port; spin_unlock(&bes2600_cdev.status_lock); } +void bes2600_chrdev_wakeup_by_event_set(enum wakeup_event wakeup_event) +{ + spin_lock(&bes2600_cdev.status_lock); + bes2600_cdev.wakeup_by_event = wakeup_event; + spin_unlock(&bes2600_cdev.status_lock); + if (wakeup_event == WAKEUP_EVENT_NONE) + wake_up(&bes2600_cdev.wakeup_reason_wq); +} + +int bes2600_chrdev_wakeup_by_event_get(void) +{ + return bes2600_cdev.wakeup_by_event; +} +#endif + int bes2600_chrdev_init(struct sbus_ops *ops) { int ret = 0; @@ -1234,6 +1272,8 @@ int bes2600_chrdev_init(struct sbus_ops *ops) init_waitqueue_head(&bes2600_cdev.probe_done_wq); INIT_WORK(&bes2600_cdev.wifi_force_close_work, bes2600_chrdev_wifi_force_close_work); INIT_DELAYED_WORK(&bes2600_cdev.probe_timeout_work, bes2600_probe_timeout_work); + init_waitqueue_head(&bes2600_cdev.wakeup_reason_wq); + bes2600_chrdev_wakeup_by_event_set(WAKEUP_EVENT_NONE); #ifdef CONFIG_BES2600_WIFI_BOOT_ON bes2600_cdev.wifi_opened = true; #else @@ -1252,6 +1292,7 @@ int bes2600_chrdev_init(struct sbus_ops *ops) bes2600_cdev.bus_error = false; bes2600_cdev.halt_dev = false; bes2600_cdev.read_flag = BES_CDEV_READ_NUM_MAX; + bes2600_cdev.wakeup_by_event = false; bes2600_info(BES2600_DBG_CHARDEV, "%s done\n", __func__); return 0; diff --git a/drivers/staging/bes2600/bes_chardev.h b/drivers/staging/bes2600/bes_chardev.h index 8c7257c087a4..5c2519879135 100644 --- a/drivers/staging/bes2600/bes_chardev.h +++ b/drivers/staging/bes2600/bes_chardev.h @@ -16,8 +16,10 @@ #define BES2600_FW_TYPE_BT 2 #define BES2600_FW_TYPE_MAX_NUM 3 -#define DPD_BIN_SIZE 0x3AF8 +#define DPD_VERSION_OFFSET 0x3AF4 +#define DPD_BIN_SIZE 0x3B14 #define DPD_BIN_FILE_SIZE 0x4000 +#define DPD_CUR_VERSION 7 enum pend_read_op { BES_CDEV_READ_WAKEUP_STATE = 0, @@ -26,6 +28,25 @@ enum pend_read_op { BES_CDEV_READ_NUM_MAX, }; +enum wifi_wakeup_reason_code { + WAKEUP_REASON_WIFI_DEAUTH_DISASSOC = 0x1000, + WAKEUP_REASON_WIFI_BSSLOST, + /* add new here */ +}; + +enum bt_wakeup_reason_code { + WAKEUP_REASON_BT_PLAY = 0x0100, + /* add new here */ +}; + +enum wakeup_event { + WAKEUP_EVENT_NONE = 0, + WAKEUP_EVENT_SETTING, + WAKEUP_EVENT_WSME, + WAKEUP_EVENT_PEER_DETACH, + /* add new here */ +}; + /* dpd management */ u8* bes2600_chrdev_get_dpd_buffer(u32 size); int bes2600_chrdev_update_dpd_data(void); @@ -54,9 +75,17 @@ bool bes2600_chrdev_is_bus_error(void); void bes2600_chrdev_start_bus_probe(void); void bes2600_chrdev_bus_probe_notify(void); +#if defined(CONFIG_BES2600_WLAN_SDIO) || defined(CONFIG_BES2600_WLAN_SPI) /* set wifi wakeup state */ -void bes2600_chrdev_wifi_update_wakeup_reason(u32 val); - +void bes2600_chrdev_wifi_update_wakeup_reason(u16 reason, u16 port); +void bes2600_chrdev_wakeup_by_event_set(enum wakeup_event wakeup_event); +int bes2600_chrdev_wakeup_by_event_get(void); +#else +/* set wifi wakeup state */ +static inline void bes2600_chrdev_wifi_update_wakeup_reason(u16 reason, u16 port) { } +static inline void bes2600_chrdev_wakeup_by_event_set(enum wakeup_event wakeup_event) { } +static inline int bes2600_chrdev_wakeup_by_event_get(void) { return 0; } +#endif /* init and deinit module */ int bes2600_chrdev_init(struct sbus_ops *ops); void bes2600_chrdev_free(void); diff --git a/drivers/staging/bes2600/bes_fw.c b/drivers/staging/bes2600/bes_fw.c index 67f361c0431f..b32d514c0ec9 100644 --- a/drivers/staging/bes2600/bes_fw.c +++ b/drivers/staging/bes2600/bes_fw.c @@ -1341,7 +1341,13 @@ static int bes_read_dpd_data(struct sbus_ops *ops, struct sbus_priv *priv) goto exit; } - dpd_data = bes2600_chrdev_get_dpd_buffer(dpd_data_len); + /* dpd size check */ + if (dpd_data_len != DPD_BIN_SIZE) { + bes2600_err(BES2600_DBG_DOWNLOAD, "get dpd data size err:%u\n", dpd_data_len); + return -1; + } + + dpd_data = bes2600_chrdev_get_dpd_buffer(DPD_BIN_FILE_SIZE); if (!dpd_data) { ret = -ENOMEM; goto exit; diff --git a/drivers/staging/bes2600/bes_nl80211_testmode_msg.h b/drivers/staging/bes2600/bes_nl80211_testmode_msg.h index a05f9f862704..b70a0dddc6c3 100644 --- a/drivers/staging/bes2600/bes_nl80211_testmode_msg.h +++ b/drivers/staging/bes2600/bes_nl80211_testmode_msg.h @@ -27,6 +27,13 @@ struct bes_event_test_t { int dummy; }; +#ifdef STANDARD_FACTORY_EFUSE_FLAG +/*example command structure for set select efuse*/ +struct bes_select_calib_t { + uint16_t select_efuse_flag; +}; +#endif + /* vendor to mcu cmd msg reply structure */ struct vendor_rf_cmd_msg_reply { u32 id; @@ -65,6 +72,8 @@ enum bes_msg_id { BES_MSG_EPTA_PARM_CONFIG, BES_MSG_GET_KEEP_ALIVE_STREAM, BES_MSG_MCU_CPUUSAGE, + BES_MSG_SAVE_CALI_TXT_TO_EFUSE, + BES_MSG_SET_SELECT_EFUSE_FLAG, /* Add new IDs here */ BES_MSG_ID_MAX, @@ -78,6 +87,7 @@ enum vendor_rf_cmd_type { VENDOR_RF_SAVE_FREQOFFSET_CMD, VENDOR_RF_SAVE_POWERLEVEL_CMD, VENDOR_RF_POWER_CALIB_FINISH, + VENDOR_RF_GET_CALI_FROM_EFUSE, /* add new here */ VENDOR_RF_CMD_MAX, diff --git a/drivers/staging/bes2600/bes_pwr.c b/drivers/staging/bes2600/bes_pwr.c index 19d7ed26fde8..4da84cf519bc 100644 --- a/drivers/staging/bes2600/bes_pwr.c +++ b/drivers/staging/bes2600/bes_pwr.c @@ -436,8 +436,8 @@ static void bes2600_pwr_delete_all_cb(struct bes2600_common *hw_priv) /* delete all cb in exit_cb_list */ list_for_each_entry_safe(item1, temp1, &hw_priv->bes_power.exit_cb_list, link) { - list_del(&item->link); - kfree(item); + list_del(&item1->link); + kfree(item1); } mutex_unlock(&hw_priv->bes_power.pwr_cb_mutex); @@ -487,13 +487,14 @@ static int bes2600_pwr_enter_lp_mode(struct bes2600_common *hw_priv) if (priv->join_status == BES2600_JOIN_STATUS_STA && priv->bss_params.aid && - priv->setbssparams_done && - priv->filter4.enable) { + priv->setbssparams_done) { /* enable arp filter */ - bes2600_dbg(BES2600_DBG_PWR, "%s, arp filter, enable:%d addr:%s\n", - __func__, priv->filter4.enable, bes2600_get_mac_str(ip_str, priv->filter4.ipv4Address[0])); - ret = wsm_set_arp_ipv4_filter(hw_priv, &priv->filter4, priv->if_id); - bes2600_err_with_cond(ret, BES2600_DBG_PWR, "%s, set arp filter failed\n", __func__); + if (priv->filter4.enable) { + bes2600_dbg(BES2600_DBG_PWR, "%s, arp filter, enable:%d addr:%s\n", + __func__, priv->filter4.enable, bes2600_get_mac_str(ip_str, priv->filter4.ipv4Address[0])); + ret = wsm_set_arp_ipv4_filter(hw_priv, &priv->filter4, priv->if_id); + bes2600_err_with_cond(ret, BES2600_DBG_PWR, "%s, set arp filter failed\n", __func__); + } /* skip beacon receive if applications don't have muticast service */ if(priv->join_dtim_period && !priv->has_multicast_subscription) { @@ -501,14 +502,15 @@ static int bes2600_pwr_enter_lp_mode(struct bes2600_common *hw_priv) if(priv->join_dtim_period >= CONFIG_BES2600_LISTEN_INTERVAL) { listen_interval = priv->join_dtim_period; } else { - listen_interval = CONFIG_BES2600_LISTEN_INTERVAL / priv->join_dtim_period; + listen_interval = CONFIG_BES2600_LISTEN_INTERVAL / priv->join_dtim_period * priv->join_dtim_period; } ret = wsm_set_beacon_wakeup_period(hw_priv, 1, listen_interval, priv->if_id); bes2600_err_with_cond(ret, BES2600_DBG_PWR, "%s, set wakeup period failed\n", __func__); } /* Set Enable Broadcast Address Filter */ - priv->broadcast_filter.action_mode = WSM_FILTER_ACTION_FILTER_OUT; + priv->broadcast_filter.action_mode = priv->filter4.enable ? + WSM_FILTER_ACTION_FILTER_OUT : WSM_FILTER_ACTION_IGNORE; if (priv->join_status == BES2600_JOIN_STATUS_AP) priv->broadcast_filter.address_mode = WSM_FILTER_ADDR_MODE_A3; ret = bes2600_set_macaddrfilter(hw_priv, priv, (u8 *)&priv->broadcast_filter); @@ -587,15 +589,16 @@ static int bes2600_pwr_exit_lp_mode(struct bes2600_common *hw_priv) if (priv->join_status == BES2600_JOIN_STATUS_STA && priv->bss_params.aid && - priv->setbssparams_done && - priv->filter4.enable) { - /* enable arp filter */ - filter = priv->filter4; - filter.enable = false; - bes2600_dbg(BES2600_DBG_PWR, "%s, arp filter, enable:%d addr:%s\n", - __func__, filter.enable, bes2600_get_mac_str(ip_str, filter.ipv4Address[0])); - ret = wsm_set_arp_ipv4_filter(hw_priv, &filter, priv->if_id); - bes2600_err_with_cond(ret, BES2600_DBG_PWR, "%s, set arp filter failed\n", __func__); + priv->setbssparams_done) { + /* disable arp filter */ + if (priv->filter4.enable) { + filter = priv->filter4; + filter.enable = false; + bes2600_dbg(BES2600_DBG_PWR, "%s, arp filter, enable:%d addr:%s\n", + __func__, filter.enable, bes2600_get_mac_str(ip_str, filter.ipv4Address[0])); + ret = wsm_set_arp_ipv4_filter(hw_priv, &filter, priv->if_id); + bes2600_err_with_cond(ret, BES2600_DBG_PWR, "%s, set arp filter failed\n", __func__); + } /* set wakeup perioid */ wsm_set_beacon_wakeup_period(hw_priv, priv->join_dtim_period, 0, priv->if_id); @@ -1404,3 +1407,28 @@ int bes2600_pwr_busy_event_dump(struct bes2600_common *hw_priv, char *buffer, u3 return 0; } + +int bes2600_pwr_busy_event_record(struct bes2600_common *hw_priv, char *buffer, u32 buf_len) +{ + unsigned long max_timeout = 0; + struct bes2600_pwr_event_t *item = NULL; + unsigned long flags; + + if(!buffer) { + return -1; + } + + spin_lock_irqsave(&hw_priv->bes_power.pwr_lock, flags); + bes2600_update_power_delay_events(&hw_priv->bes_power, &max_timeout); + if(!list_empty(&hw_priv->bes_power.pending_event_list)) { + list_for_each_entry(item, &hw_priv->bes_power.pending_event_list, link) { + snprintf(buffer, buf_len, "Event: %9s. Flag: %s. timeout(ticks): %lu.\n", + bes2600_get_pwr_busy_event_name(item), + BES_PWR_IS_CONSTANT_EVENT(item->event) ? "C" : "D", + bes2600_get_pwr_busy_event_timeout(item)); + } + } + spin_unlock_irqrestore(&hw_priv->bes_power.pwr_lock, flags); + + return 0; +} \ No newline at end of file diff --git a/drivers/staging/bes2600/bes_pwr.h b/drivers/staging/bes2600/bes_pwr.h index 2c27f4293a55..1ba866c25c42 100644 --- a/drivers/staging/bes2600/bes_pwr.h +++ b/drivers/staging/bes2600/bes_pwr.h @@ -135,6 +135,7 @@ void bes2600_pwr_mcu_sleep_directly(struct bes2600_common *hw_priv); void bes2600_pwr_mark_ap_lp_bad(struct bes2600_common *hw_priv); void bes2600_pwr_clear_ap_lp_bad_mark(struct bes2600_common *hw_priv); int bes2600_pwr_busy_event_dump(struct bes2600_common *hw_priv, char *buffer, u32 buf_len); +int bes2600_pwr_busy_event_record(struct bes2600_common *hw_priv, char *buffer, u32 buf_len); #else static inline void bes2600_pwr_init(struct bes2600_common *hw_priv) { } static inline void bes2600_pwr_exit(struct bes2600_common *hw_priv) { } @@ -162,6 +163,7 @@ static inline void bes2600_pwr_mcu_sleep_directly(struct bes2600_common *hw_priv static inline void bes2600_pwr_mark_ap_lp_bad(struct bes2600_common *hw_priv) { } static inline void bes2600_pwr_clear_ap_lp_bad_mark(struct bes2600_common *hw_priv) { } static inline int bes2600_pwr_busy_event_dump(struct bes2600_common *hw_priv, char *buffer, u32 buf_len) { return 0; } +static inline int bes2600_pwr_busy_event_record(struct bes2600_common *hw_priv, char *buffer, u32 buf_len) { return 0; } #endif #endif \ No newline at end of file diff --git a/drivers/staging/bes2600/bh.c b/drivers/staging/bes2600/bh.c index fed5101d42c6..082eaa8e200f 100644 --- a/drivers/staging/bes2600/bh.c +++ b/drivers/staging/bes2600/bh.c @@ -955,6 +955,7 @@ static void bes2600_bh_parse_wakeup_event(struct bes2600_common *hw_priv, struct { struct wsm_hdr *wsm = (struct wsm_hdr *)skb->data; u16 wsm_id = __le16_to_cpu(wsm->id) & 0xFFF; + bool set_wakeup_reason_later = false; if (hw_priv->sbus_ops->wakeup_source && hw_priv->sbus_ops->wakeup_source(hw_priv->sbus_priv)) { @@ -966,15 +967,29 @@ static void bes2600_bh_parse_wakeup_event(struct bes2600_common *hw_priv, struct if (ieee80211_is_mgmt(fctl)) { u16 type = (fctl & cpu_to_le16(IEEE80211_FCTL_FTYPE)) >> 2; u16 stype = (fctl & cpu_to_le16(IEEE80211_FCTL_STYPE)) >> 4; + if (ieee80211_is_deauth(fctl) || ieee80211_is_disassoc(fctl)) { + bes2600_chrdev_wakeup_by_event_set(WAKEUP_EVENT_PEER_DETACH); + set_wakeup_reason_later = true; + bes2600_info(BES2600_DBG_BH, "Host was waked by mgmt(deauth or disassoc)\n"); + } bes2600_info(BES2600_DBG_BH, "Host was waked by mgmt, type:%d(%d)\n", type, stype); - } else if(ieee80211_is_data(fctl)){ + } else if (ieee80211_is_data(fctl)){ bes2600_bh_parse_data_pkt(hw_priv, skb); } else { bes2600_info(BES2600_DBG_BH, "Host was waked by unexpected frame, fctl:0x%04x\n", fctl); } + } else if (wsm_id == 0x0C31) { + bes2600_info(BES2600_DBG_BH, "Host was waked by BT:0x%04x.\n", wsm_id); + bes2600_chrdev_wifi_update_wakeup_reason(WAKEUP_REASON_BT_PLAY, 0); } else { + if (wsm_id == 0x0805) { + bes2600_chrdev_wakeup_by_event_set(WAKEUP_EVENT_WSME); + set_wakeup_reason_later = true; + } bes2600_info(BES2600_DBG_BH, "Host was waked by event:0x%04x.\n", wsm_id); } + if (!set_wakeup_reason_later) + bes2600_chrdev_wakeup_by_event_set(WAKEUP_EVENT_NONE); } } @@ -1451,7 +1466,8 @@ static int bes2600_bh(void *arg) if (!hw_priv->hw_bufs_used && !bes2600_pwr_device_is_idle(hw_priv) && - !atomic_read(&hw_priv->recent_scan)) { + !atomic_read(&hw_priv->recent_scan) && + bes2600_chrdev_is_signal_mode()) { status = 5 * HZ; } else if (hw_priv->hw_bufs_used) { /* Interrupt loss detection */ diff --git a/drivers/staging/bes2600/debug.c b/drivers/staging/bes2600/debug.c index c5bba0789a3c..0e51f53f3af2 100644 --- a/drivers/staging/bes2600/debug.c +++ b/drivers/staging/bes2600/debug.c @@ -82,7 +82,11 @@ static void bes2600_queue_status_show(struct seq_file *seq, seq_printf(seq, " pending: %ld\n", (long)q->num_pending); seq_printf(seq, " sent: %ld\n", (long)q->num_sent); seq_printf(seq, " locked: %s\n", q->tx_locked_cnt ? "yes" : "no"); - seq_printf(seq, " overfull: %s\n", q->overfull ? "yes" : "no"); + seq_printf(seq, " vif_overfull[0]: %s\n", q->vif_overfull[0] ? "yes" : "no"); + seq_printf(seq, " vif_overfull[1]: %s\n", q->vif_overfull[1] ? "yes" : "no"); +#ifdef P2P_MULTIVIF + seq_printf(seq, " vif_overfull[2]: %s\n", q->vif_overfull[2] ? "yes" : "no"); +#endif seq_puts(seq, " link map: 0-> "); for (if_id = 0; if_id < CW12XX_MAX_VIFS; if_id++) { for (i = 0; i < q->stats->map_capacity; ++i) diff --git a/drivers/staging/bes2600/epta_request.c b/drivers/staging/bes2600/epta_request.c index 44676dcbc6d7..abbd4abc31ae 100644 --- a/drivers/staging/bes2600/epta_request.c +++ b/drivers/staging/bes2600/epta_request.c @@ -105,8 +105,8 @@ typedef enum { BWIFI_BT_STATUS_SHUTDOWN = 0, BWIFI_BT_STATUS_DISCONNECTED = 1, BWIFI_BT_STATUS_CONNECTING = 2, - BWIFI_BT_STATUS_CONNECTED_SNIFF = 3,// - BWIFI_BT_STATUS_CONNECTED = 4,// + BWIFI_BT_STATUS_CONNECTED_SNIFF = 3, + BWIFI_BT_STATUS_CONNECTED = 4, } BWIFI_BT_STATUS_T; typedef enum { @@ -123,23 +123,23 @@ typedef enum { } BWIFI_BT_AUDIO_T; typedef enum { - BWIFI_BT_INQ_STOP = 0,// - BWIFI_BT_INQ_START = 1,// + BWIFI_BT_INQ_STOP = 0, + BWIFI_BT_INQ_START = 1, } BWIFI_BT_INQ_T; typedef enum { - BWIFI_LE_SCAN_STOP = 0,// - BWIFI_LE_SCAN_START = 1,// + BWIFI_LE_SCAN_STOP = 0, + BWIFI_LE_SCAN_START = 1, } BWIFI_BT_LE_SCAN_T; typedef enum { - BWIFI_LE_ADV_STOP = 0,// - BWIFI_LE_ADV_START = 1,// + BWIFI_LE_ADV_STOP = 0, + BWIFI_LE_ADV_START = 1, } BWIFI_BT_LE_ADV_T; typedef enum { - BWIFI_LE_DISCONNECTED = 0,// - BWIFI_LE_CONNECTED = 1,// + BWIFI_LE_DISCONNECTED = 0, + BWIFI_LE_CONNECTED = 1, } BWIFI_BT_LE_STATUS_T; enum COEX_BT_OPER_T { @@ -206,8 +206,8 @@ void coex_calc_wifi_scan_time(uint32_t *min_chan, uint32_t *max_chan) uint32_t time = coex_calc_bt_time(); if (time == 0) { - *min_chan = 90; - *max_chan = 90; + *min_chan = 100; + *max_chan = 100; } else if (time < 40000) { *min_chan = 50; *max_chan = 110; diff --git a/drivers/staging/bes2600/main.c b/drivers/staging/bes2600/main.c index 675839d7177a..cc33b16a3b5a 100644 --- a/drivers/staging/bes2600/main.c +++ b/drivers/staging/bes2600/main.c @@ -46,6 +46,9 @@ MODULE_AUTHOR("Dmitry Tarnyagin "); MODULE_DESCRIPTION("Softmac BES2600 common code"); MODULE_LICENSE("GPL"); MODULE_ALIAS("bes2600"); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) +MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); +#endif static u8 bes2600_mac_template[ETH_ALEN] = { #if (GET_MAC_ADDR_METHOD == 2)||(GET_MAC_ADDR_METHOD == 3) @@ -199,7 +202,7 @@ static struct ieee80211_supported_band bes2600_band_2ghz = { .n_bitrates = bes2600_g_rates_size, .ht_cap = { .cap = IEEE80211_HT_CAP_GRN_FLD | - (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | + (STBC_RX_24G << IEEE80211_HT_CAP_RX_STBC_SHIFT) | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | @@ -223,7 +226,7 @@ static struct ieee80211_supported_band bes2600_band_5ghz = { .n_bitrates = bes2600_a_rates_size, .ht_cap = { .cap = IEEE80211_HT_CAP_GRN_FLD | - (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | + (STBC_RX_5G << IEEE80211_HT_CAP_RX_STBC_SHIFT) | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | @@ -320,23 +323,23 @@ static const struct wiphy_wowlan_support bes2600_wowlan_support = { #endif #ifdef CONFIG_BES2600_WAPI_SUPPORT -static void bes2600_init_wapi_cipher(struct ieee80211_hw *hw) -{ - static struct ieee80211_cipher_scheme wapi_cs = { - .cipher = WLAN_CIPHER_SUITE_SMS4, - .iftype = BIT(NL80211_IFTYPE_STATION), - .hdr_len = 18, - .pn_len = 16, - .pn_off = 2, - .key_idx_off = 0, - .key_idx_mask = 0x01, - .key_idx_shift = 0, - .mic_len = 16 - }; - - hw->cipher_schemes = &wapi_cs; - hw->n_cipher_schemes = 1; -} +// static void bes2600_init_wapi_cipher(struct ieee80211_hw *hw) +// { +// static struct ieee80211_cipher_scheme wapi_cs = { +// .cipher = WLAN_CIPHER_SUITE_SMS4, +// .iftype = BIT(NL80211_IFTYPE_STATION), +// .hdr_len = 18, +// .pn_len = 16, +// .pn_off = 2, +// .key_idx_off = 0, +// .key_idx_mask = 0x01, +// .key_idx_shift = 0, +// .mic_len = 16 +// }; + +// hw->cipher_schemes = &wapi_cs; +// hw->n_cipher_schemes = 1; +// } #endif static void bes2600_get_base_mac(struct bes2600_common *hw_priv) @@ -532,7 +535,7 @@ struct ieee80211_hw *bes2600_init_common(size_t hw_priv_data_len) #ifdef CONFIG_BES2600_WAPI_SUPPORT hw_priv->last_ins_wapi_usk_id = -1; hw_priv->last_del_wapi_usk_id = -1; - bes2600_init_wapi_cipher(hw); + // bes2600_init_wapi_cipher(hw); #endif SET_IEEE80211_PERM_ADDR(hw, hw_priv->addresses[0].addr); @@ -609,6 +612,11 @@ struct ieee80211_hw *bes2600_init_common(size_t hw_priv_data_len) bes2600_tx_loop_init(hw_priv); +#ifdef CONFIG_PM + bes2600_suspend_status_set(hw_priv, false); + bes2600_pending_unjoin_reset(hw_priv); +#endif + #ifdef CONFIG_BES2600_TESTMODE hw_priv->test_frame.data = NULL; hw_priv->test_frame.len = 0; @@ -659,7 +667,9 @@ int bes2600_register_common(struct ieee80211_hw *dev) #endif /* CONFIG_BES2600_LEDS */ bes2600_debug_init_common(hw_priv); - +#ifdef CONFIG_PM + bes2600_register_pm_notifier(hw_priv); +#endif /* CONFIG_PM */ bes2600_info(BES2600_DBG_INIT, "is registered as '%s'\n", wiphy_name(dev->wiphy)); return 0; @@ -697,7 +707,9 @@ void bes2600_unregister_common(struct ieee80211_hw *dev) bes2600_unregister_bh(hw_priv); bes2600_debug_release_common(hw_priv); - +#ifdef CONFIG_PM + bes2600_unregister_pm_notifier(hw_priv); +#endif /* CONFIG_PM */ #ifdef CONFIG_BES2600_LEDS bes2600_unregister_leds(hw_priv); #endif /* CONFIG_BES2600_LEDS */ @@ -1014,7 +1026,7 @@ int access_file(char *path, char *buffer, int size, int isRead) #ifdef CONFIG_BES2600_WLAN_BES int bes2600_wifi_start(struct bes2600_common *hw_priv) { - int ret, if_id; + int ret = 0, if_id; #ifndef CONFIG_BES2600_WLAN_USB if(hw_priv->sbus_ops->gpio_wake) { hw_priv->sbus_ops->gpio_wake(hw_priv->sbus_priv, GPIO_WAKE_FLAG_WIFI_ON); diff --git a/drivers/staging/bes2600/pm.c b/drivers/staging/bes2600/pm.c index fbd6a8867332..d3213339e11c 100644 --- a/drivers/staging/bes2600/pm.c +++ b/drivers/staging/bes2600/pm.c @@ -11,6 +11,7 @@ #include #include +#include #include "bes2600.h" #include "pm.h" #include "sta.h" @@ -30,9 +31,9 @@ struct bes2600_udp_port_filter { struct bes2600_ether_type_filter { struct wsm_ether_type_filter_hdr hdr; - struct wsm_ether_type_filter ip; struct wsm_ether_type_filter pae; struct wsm_ether_type_filter wapi; + struct wsm_ether_type_filter append; } __packed; static struct bes2600_udp_port_filter bes2600_udp_port_filter_on = { @@ -65,12 +66,10 @@ static struct wsm_udp_port_filter_hdr bes2600_udp_port_filter_off = { #define ETH_P_WAPI 0x88B4 #endif +#define ETH_P_UNKNOWN 0xFFFF static struct bes2600_ether_type_filter bes2600_ether_type_filter_on = { .hdr.nrFilters = 3, - .ip = { - .filterAction = WSM_FILTER_ACTION_FILTER_OUT, - .etherType = __cpu_to_le16(ETH_P_IPV6), - }, + .hdr.extFlags = WSM_ETH_FILTER_EXT_DISABLE_IPV6_MATCH, // patch for disable lmac SUSPEND_MODE_IPV6_FIX .pae = { .filterAction = WSM_FILTER_ACTION_FILTER_IN, .etherType = __cpu_to_le16(ETH_P_PAE), @@ -79,6 +78,11 @@ static struct bes2600_ether_type_filter bes2600_ether_type_filter_on = { .filterAction = WSM_FILTER_ACTION_FILTER_IN, .etherType = __cpu_to_le16(ETH_P_WAPI), }, + // add for lmac ether filter strategy: If every filtermode is FilterIN, discard all the frame which is mismatched + .append = { + .filterAction = WSM_FILTER_ACTION_FILTER_OUT, + .etherType = __cpu_to_le16(ETH_P_UNKNOWN), + }, /* Please add other known ether types to be filtered out here and * update nrFilters field in the header. * Up to 4 filters are allowed. */ @@ -88,6 +92,25 @@ static struct wsm_ether_type_filter_hdr bes2600_ether_type_filter_off = { .nrFilters = 0, }; +#ifdef IPV6_FILTERING +static struct wsm_ipv6_filter bes2600_ipv6_filter_on = { + .hdr.numfilter = 1, + .hdr.action_mode = WSM_FILTER_ACTION_FILTER_IN, + .ipv6filter[0] = { + .filter_mode = WSM_FILTER_ACTION_FILTER_IN, + .address_mode = WSM_IP_DATA_FRAME_ADDRMODE_DEST, + /* a random ipvd addr, in order to filter all ipv6 packet */ + .ipv6 = {0x01, 0x28, 0x35, 0xde, 0xbf, 0x34, 0x9d, 0x8a, + 0x47, 0x62, 0x85, 0x69, 0x7e, 0x8c, 0x29, 0x38}, + } +}; + +static struct wsm_ipv6_filter bes2600_ipv6_filter_off = { + .hdr.numfilter = 0, + .hdr.action_mode = WSM_FILTER_ACTION_IGNORE, +}; +#endif + static int __bes2600_wow_suspend(struct bes2600_vif *priv, struct cfg80211_wowlan *wowlan); static int __bes2600_wow_resume(struct bes2600_vif *priv); @@ -102,6 +125,88 @@ struct bes2600_suspend_state { unsigned long link_id_gc; }; +void bes2600_suspend_status_set(struct bes2600_common *hw_priv, bool status) +{ + hw_priv->suspend_in_progress = status; +} + +bool bes2600_suspend_status_get(struct bes2600_common *hw_priv) +{ + return hw_priv->suspend_in_progress; +} + +void bes2600_pending_unjoin_reset(struct bes2600_common *hw_priv) +{ + hw_priv->unjoin_if_id_slots = 0x00; +} + +void bes2600_pending_unjoin_set(struct bes2600_common *hw_priv, int if_id) +{ + if(if_id > 1) + bes2600_err(BES2600_DBG_PM, "unexpected if_id: %d\n", if_id); + else + hw_priv->unjoin_if_id_slots |= (1 << if_id); +} + +bool bes2600_pending_unjoin_get(struct bes2600_common *hw_priv, int if_id) +{ + if(if_id > 1) { + bes2600_err(BES2600_DBG_PM, "unexpected if_id: %d\n", if_id); + return false; + } else + return hw_priv->unjoin_if_id_slots & (1 << if_id); +} + +static int bes2600_pm_notifier(struct notifier_block *notifier, + unsigned long pm_event, + void *unused) +{ + int if_id; + struct bes2600_vif *priv; + struct bes2600_common *hw_priv = container_of(notifier, + struct bes2600_common, + pm_notify); + + switch (pm_event) { + case PM_HIBERNATION_PREPARE: + case PM_SUSPEND_PREPARE: + bes2600_suspend_status_set(hw_priv, true); + break; + + case PM_POST_RESTORE: + case PM_POST_HIBERNATION: + case PM_POST_SUSPEND: + bes2600_suspend_status_set(hw_priv, false); + if(hw_priv->unjoin_if_id_slots) { + for(if_id = 0; if_id < 2; if_id++) { + if(bes2600_pending_unjoin_get(hw_priv, if_id)) { + priv = __cw12xx_hwpriv_to_vifpriv(hw_priv, if_id); + ieee80211_connection_loss(priv->vif); + } + } + bes2600_pending_unjoin_reset(hw_priv); + } + break; + + case PM_RESTORE_PREPARE: + default: + break; + } + + return NOTIFY_DONE; +} + +void bes2600_register_pm_notifier(struct bes2600_common *hw_priv) +{ + hw_priv->pm_notify.notifier_call = bes2600_pm_notifier; + register_pm_notifier(&hw_priv->pm_notify); +} + +void bes2600_unregister_pm_notifier(struct bes2600_common *hw_priv) +{ + unregister_pm_notifier(&hw_priv->pm_notify); +} + static long bes2600_suspend_work(struct delayed_work *work) { int ret = cancel_delayed_work(work); @@ -143,13 +248,14 @@ int bes2600_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) struct bes2600_vif *priv; int i, ret = 0; unsigned long begin, end, diff; + char *busy_event_buffer = NULL; bes2600_info(BES2600_DBG_PM, "bes2600_wow_suspend enter\n"); WARN_ON(!atomic_read(&hw_priv->num_vifs)); /* reset wakeup reason to default */ - bes2600_chrdev_wifi_update_wakeup_reason(0); + bes2600_chrdev_wifi_update_wakeup_reason(0, 0); #ifdef ROAM_OFFLOAD bes2600_for_each_vif(hw_priv, priv, i) { @@ -198,6 +304,18 @@ int bes2600_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) if (wait_event_timeout(hw_priv->bes_power.dev_lp_wq, bes2600_pwr_device_is_idle(hw_priv), HZ * 5) <= 0) { bes2600_err(BES2600_DBG_PM, "wait device idle timeout\n"); + busy_event_buffer = kmalloc(4096, GFP_KERNEL); + + if(!busy_event_buffer) + goto revert2; + + if(bes2600_pwr_busy_event_record(hw_priv, busy_event_buffer, 4096) == 0) { + bes2600_info(BES2600_DBG_PM, "%s\n", busy_event_buffer); + } else { + bes2600_err(BES2600_DBG_PM, "busy event show failed\n"); + } + + kfree(busy_event_buffer); goto revert2; } } @@ -287,10 +405,10 @@ static int __bes2600_wow_suspend(struct bes2600_vif *priv, int ret; #ifdef MCAST_FWDING - struct wsm_forwarding_offload fwdoffload = { - .fwenable = 0x1, - .flags = 0x1, - }; + struct wsm_forwarding_offload fwdoffload = { + .fwenable = 0x1, + .flags = 0x1, + }; #endif /* Do not suspend when join work is scheduled */ @@ -300,6 +418,11 @@ static int __bes2600_wow_suspend(struct bes2600_vif *priv, bes2600_set_ehter_and_udp_filter(hw_priv, &bes2600_ether_type_filter_on.hdr, &bes2600_udp_port_filter_on.hdr, priv->if_id); + /* Set ipv6 filer */ +#ifdef IPV6_FILTERING + wsm_set_ipv6_filter(hw_priv, &bes2600_ipv6_filter_on.hdr, priv->if_id); +#endif + if (priv->join_status == BES2600_JOIN_STATUS_AP) WARN_ON(wsm_set_keepalive_filter(priv, true)); @@ -307,7 +430,7 @@ static int __bes2600_wow_suspend(struct bes2600_vif *priv, if (priv->multicast_filter.numOfAddresses) { priv->multicast_filter.enable = __cpu_to_le32(2); wsm_set_multicast_filter(hw_priv, &priv->multicast_filter, priv->if_id); - } + } #ifdef MCAST_FWDING if (priv->join_status == BES2600_JOIN_STATUS_AP) @@ -362,7 +485,7 @@ static int __bes2600_wow_suspend(struct bes2600_vif *priv, if (priv->multicast_filter.numOfAddresses) { priv->multicast_filter.enable = __cpu_to_le32(1); wsm_set_multicast_filter(hw_priv, &priv->multicast_filter, priv->if_id); - } + } #ifdef MCAST_FWDING @@ -422,10 +545,10 @@ static int __bes2600_wow_resume(struct bes2600_vif *priv) struct bes2600_suspend_state *state; #ifdef MCAST_FWDING - struct wsm_forwarding_offload fwdoffload = { - .fwenable = 0x1, - .flags = 0x0, - }; + struct wsm_forwarding_offload fwdoffload = { + .fwenable = 0x1, + .flags = 0x0, + }; #endif state = pm_state_vif->suspend_state; pm_state_vif->suspend_state = NULL; @@ -443,7 +566,7 @@ static int __bes2600_wow_resume(struct bes2600_vif *priv) if (priv->multicast_filter.numOfAddresses) { priv->multicast_filter.enable = __cpu_to_le32(1); wsm_set_multicast_filter(hw_priv, &priv->multicast_filter, priv->if_id); - } + } #ifdef MCAST_FWDING if (priv->join_status == BES2600_JOIN_STATUS_AP) @@ -467,8 +590,14 @@ static int __bes2600_wow_resume(struct bes2600_vif *priv) /* Remove ethernet frame type filter */ wsm_set_ether_type_filter(hw_priv, &bes2600_ether_type_filter_off, priv->if_id); + + /* Remove ipv6 filer */ +#ifdef IPV6_FILTERING + wsm_set_ipv6_filter(hw_priv, &bes2600_ipv6_filter_off.hdr, priv->if_id); +#endif + /* Free memory */ kfree(state); return 0; -} +} \ No newline at end of file diff --git a/drivers/staging/bes2600/pm.h b/drivers/staging/bes2600/pm.h index dbf887367877..0f6943ecd870 100644 --- a/drivers/staging/bes2600/pm.h +++ b/drivers/staging/bes2600/pm.h @@ -21,6 +21,13 @@ struct bes2600_pm_state_vif { struct bes2600_suspend_state *suspend_state; }; +void bes2600_suspend_status_set(struct bes2600_common *hw_priv, bool status); +bool bes2600_suspend_status_get(struct bes2600_common *hw_priv); +void bes2600_pending_unjoin_reset(struct bes2600_common *hw_priv); +void bes2600_pending_unjoin_set(struct bes2600_common *hw_priv, int if_id); +bool bes2600_pending_unjoin_get(struct bes2600_common *hw_priv, int if_id); +void bes2600_register_pm_notifier(struct bes2600_common *hw_priv); +void bes2600_unregister_pm_notifier(struct bes2600_common *hw_priv); int bes2600_can_suspend(struct bes2600_common *priv); int bes2600_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan); diff --git a/drivers/staging/bes2600/queue.c b/drivers/staging/bes2600/queue.c index de8edb2a3433..868ad23e95a3 100644 --- a/drivers/staging/bes2600/queue.c +++ b/drivers/staging/bes2600/queue.c @@ -129,6 +129,34 @@ static void bes2600_queue_register_post_gc(struct list_head *gc_list, list_add_tail(&gc_item->head, gc_list); } +static void bes2600_queue_pending_record(struct list_head *pending_record_list, + struct bes2600_queue_item *pending_item) +{ + struct bes2600_queue_item *record_item; + + record_item = kmalloc(sizeof(struct bes2600_queue_item),GFP_ATOMIC); + BUG_ON(!record_item); + memcpy(record_item, pending_item, sizeof(struct bes2600_queue_item)); + record_item->skb = skb_clone(pending_item->skb, GFP_ATOMIC); + list_add_tail(&record_item->head, pending_record_list); +} + +static void bes2600_queue_vif_wake_subqueue(struct bes2600_queue_stats *stats, + struct bes2600_queue *queue, int vif) +{ + struct bes2600_vif *priv; + struct wireless_dev *wdev; + + priv = __cw12xx_hwpriv_to_vifpriv(stats->hw_priv, vif); + if (priv && unlikely(queue->vif_overfull[vif])) { + wdev = ieee80211_vif_to_wdev(priv->vif); + if (wdev->netdev && !ieee80211_queue_stopped(stats->hw_priv->hw, queue->queue_id)) { + queue->vif_overfull[vif] = false; + netif_wake_subqueue(wdev->netdev, queue->queue_id); + } + } +} + static void __bes2600_queue_gc(struct bes2600_queue *queue, struct list_head *head, bool unlock) @@ -136,6 +164,9 @@ static void __bes2600_queue_gc(struct bes2600_queue *queue, struct bes2600_queue_stats *stats = queue->stats; struct bes2600_queue_item *item = NULL; struct bes2600_vif *priv; + struct wireless_dev *wdev; + int throttle; + int vif_i; int if_id; bool wakeup_stats = false; @@ -169,17 +200,28 @@ static void __bes2600_queue_gc(struct bes2600_queue *queue, if (wakeup_stats) wake_up(&stats->wait_link_id_empty); - if (queue->overfull) { - if (queue->num_queued <= ((stats->hw_priv->vif0_throttle + - stats->hw_priv->vif1_throttle + 2)/2)) { - queue->overfull = false; - if (unlock) - __bes2600_queue_unlock(queue); - } else if (item) { - unsigned long tmo = item->queue_timestamp + queue->ttl; - mod_timer(&queue->gc, tmo); - bes2600_pwr_set_busy_event_with_timeout_async(stats->hw_priv, - BES_PWR_LOCK_ON_QUEUE_GC, jiffies_to_msecs(tmo - jiffies)); + for (vif_i = 0; vif_i < CW12XX_MAX_VIFS; vif_i++) { + if (vif_i == 0) + throttle = stats->hw_priv->vif0_throttle - (num_present_cpus() - 1); + else if (vif_i == 1) + throttle = stats->hw_priv->vif1_throttle - (num_present_cpus() - 1); + else + throttle = 2; + + priv = __cw12xx_hwpriv_to_vifpriv(stats->hw_priv, vif_i); + + if (priv && queue->vif_overfull[vif_i]) { + wdev = ieee80211_vif_to_wdev(priv->vif); + if (wdev->netdev && queue->num_queued_vif[vif_i] < (throttle + 1)/2 && unlock && + !ieee80211_queue_stopped(stats->hw_priv->hw, queue->queue_id)) { + queue->vif_overfull[vif_i] = false; + netif_wake_subqueue(wdev->netdev, queue->queue_id); + } else if (item) { + unsigned long tmo = item->queue_timestamp + queue->ttl; + mod_timer(&queue->gc, tmo); + bes2600_pwr_set_busy_event_with_timeout_async(stats->hw_priv, + BES_PWR_LOCK_ON_QUEUE_GC, jiffies_to_msecs(tmo - jiffies)); + } } } } @@ -282,14 +324,24 @@ int bes2600_queue_init(struct bes2600_queue *queue, /* TODO:COMBO: Flush only a particular interface specific parts */ int bes2600_queue_clear(struct bes2600_queue *queue, int if_id) { - int i, cnt, iter; + int i, cnt, iter, vif_i; struct bes2600_queue_stats *stats = queue->stats; LIST_HEAD(gc_list); + struct bes2600_queue_item *pending_item = NULL, *temp_pending_item = NULL; cnt = 0; spin_lock_bh(&queue->lock); queue->generation++; queue->generation &= 0xf; + + spin_lock(&stats->hw_priv->tx_loop.pending_record_lock); + if (!list_empty(&queue->pending)) { + list_for_each_entry_safe(pending_item, temp_pending_item, &queue->pending, head) { + bes2600_queue_pending_record(&stats->hw_priv->tx_loop.pending_record_list, pending_item); + } + } + spin_unlock(&stats->hw_priv->tx_loop.pending_record_lock); + list_splice_tail_init(&queue->queue, &queue->pending); while (!list_empty(&queue->pending)) { struct bes2600_queue_item *item = list_first_entry( @@ -334,9 +386,12 @@ int bes2600_queue_clear(struct bes2600_queue *queue, int if_id) } } spin_unlock_bh(&stats->lock); - if (unlikely(queue->overfull)) { - queue->overfull = false; - __bes2600_queue_unlock(queue); + if (CW12XX_ALL_IFS == if_id) { + for (vif_i = 0; vif_i < CW12XX_MAX_VIFS; vif_i++) { + bes2600_queue_vif_wake_subqueue(stats, queue, vif_i); + } + } else { + bes2600_queue_vif_wake_subqueue(stats, queue, if_id); } spin_unlock_bh(&queue->lock); wake_up(&stats->wait_link_id_empty); @@ -403,8 +458,15 @@ int bes2600_queue_put(struct bes2600_queue *queue, { int ret = 0; #ifdef CONFIG_BES2600_TESTMODE +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) + struct timespec64 tmval; +#else struct timeval tmval; +#endif #endif /*CONFIG_BES2600_TESTMODE*/ + struct bes2600_vif *priv; + struct wireless_dev *wdev; + int throttle = 0; LIST_HEAD(gc_list); struct bes2600_queue_stats *stats = queue->stats; @@ -436,8 +498,13 @@ int bes2600_queue_put(struct bes2600_queue *queue, } #endif #ifdef CONFIG_BES2600_TESTMODE +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) + ktime_get_real_ts64(&tmval); + item->qdelay_timestamp = tmval.tv_nsec / 1000; +#else do_gettimeofday(&tmval); item->qdelay_timestamp = tmval.tv_usec; +#endif #endif /*CONFIG_BES2600_TESTMODE*/ ++queue->num_queued; @@ -453,14 +520,24 @@ int bes2600_queue_put(struct bes2600_queue *queue, * TX may happen in parallel sometimes. * Leave extra queue slots so we don't overflow. */ - if (queue->overfull == false && - queue->num_queued >= - ((stats->hw_priv->vif0_throttle + - stats->hw_priv->vif1_throttle + 2) - - (num_present_cpus() - 1))) { - queue->overfull = true; - __bes2600_queue_lock(queue); - mod_timer(&queue->gc, jiffies); + if (txpriv->if_id == 0) + throttle = stats->hw_priv->vif0_throttle - (num_present_cpus() - 1); + else if (txpriv->if_id == 1) + throttle = stats->hw_priv->vif1_throttle - (num_present_cpus() - 1); + else if (txpriv->if_id == 2) + throttle = 2; + else + bes2600_warn(BES2600_DBG_TXRX, "%s: unexpected if_id = %d\n", __func__, txpriv->if_id); + + priv = __cw12xx_hwpriv_to_vifpriv(stats->hw_priv, txpriv->if_id); + + if (priv && queue->num_queued_vif[txpriv->if_id] >= throttle) { + wdev = ieee80211_vif_to_wdev(priv->vif); + if (wdev->netdev) { + queue->vif_overfull[txpriv->if_id] = true; + netif_stop_subqueue(wdev->netdev, queue->queue_id); + mod_timer(&queue->gc, jiffies); + } } } else { ret = -ENOENT; @@ -489,7 +566,11 @@ int bes2600_queue_get(struct bes2600_queue *queue, struct bes2600_queue_stats *stats = queue->stats; bool wakeup_stats = false; #ifdef CONFIG_BES2600_TESTMODE +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) + struct timespec64 tmval; +#else struct timeval tmval; +#endif #endif /*CONFIG_BES2600_TESTMODE*/ spin_lock_bh(&queue->lock); @@ -513,8 +594,13 @@ int bes2600_queue_get(struct bes2600_queue *queue, [item->txpriv.link_id]; item->xmit_timestamp = jiffies; #ifdef CONFIG_BES2600_TESTMODE +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) + ktime_get_real_ts64(&tmval); + item->mdelay_timestamp = tmval.tv_nsec / 1000; +#else do_gettimeofday(&tmval); item->mdelay_timestamp = tmval.tv_usec; +#endif #endif /*CONFIG_BES2600_TESTMODE*/ spin_lock_bh(&stats->lock); @@ -726,6 +812,9 @@ int bes2600_queue_remove(struct bes2600_queue *queue, u32 packetID) struct bes2600_queue_stats *stats = queue->stats; struct sk_buff *gc_skb = NULL; struct bes2600_txpriv gc_txpriv; + struct bes2600_vif *priv; + struct wireless_dev *wdev; + int throttle = 0; bes2600_queue_parse_id(packetID, &queue_generation, &queue_id, &item_generation, &item_id, &if_id, &link_id); @@ -758,9 +847,30 @@ int bes2600_queue_remove(struct bes2600_queue *queue, u32 packetID) spin_lock_bh(&hw_priv->tsm_lock); if (hw_priv->start_stop_tsm.start) { if (queue_id == hw_priv->tsm_info.ac) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) + struct timespec64 tmval; +#else struct timeval tmval; +#endif unsigned long queue_delay; unsigned long media_delay; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) + ktime_get_real_ts64(&tmval); + + if (tmval.tv_nsec / 1000 > item->qdelay_timestamp) + queue_delay = tmval.tv_nsec / 1000 - + item->qdelay_timestamp; + else + queue_delay = tmval.tv_nsec / 1000 + + 1000000 - item->qdelay_timestamp; + + if (tmval.tv_nsec / 1000 > item->mdelay_timestamp) + media_delay = tmval.tv_nsec / 1000 - + item->mdelay_timestamp; + else + media_delay = tmval.tv_nsec / 1000 + + 1000000 - item->mdelay_timestamp; +#else do_gettimeofday(&tmval); if (tmval.tv_usec > item->qdelay_timestamp) @@ -776,6 +886,7 @@ int bes2600_queue_remove(struct bes2600_queue *queue, u32 packetID) else media_delay = tmval.tv_usec + 1000000 - item->mdelay_timestamp; +#endif hw_priv->tsm_info.sum_media_delay += media_delay; hw_priv->tsm_info.sum_pkt_q_delay += queue_delay; @@ -796,10 +907,24 @@ int bes2600_queue_remove(struct bes2600_queue *queue, u32 packetID) */ list_move(&item->head, &queue->free_pool); - if (unlikely(queue->overfull) && - (queue->num_queued <= ((stats->hw_priv->vif0_throttle + stats->hw_priv->vif1_throttle + 2) / 2))) { - queue->overfull = false; - __bes2600_queue_unlock(queue); + if (if_id == 0) + throttle = stats->hw_priv->vif0_throttle - (num_present_cpus() - 1); + else if (if_id == 1) + throttle = stats->hw_priv->vif1_throttle - (num_present_cpus() - 1); + else if (if_id == 2) + throttle = 2; + else + bes2600_warn(BES2600_DBG_TXRX, "%s: unexpected if_id = %d\n", __func__, if_id); + + priv = __cw12xx_hwpriv_to_vifpriv(stats->hw_priv, if_id); + + if (priv && unlikely(queue->vif_overfull[if_id]) && + queue->num_queued_vif[if_id] < (throttle + 1)/2) { + wdev = ieee80211_vif_to_wdev(priv->vif); + if (wdev->netdev && !ieee80211_queue_stopped(stats->hw_priv->hw, queue->queue_id)) { + queue->vif_overfull[if_id] = false; + netif_wake_subqueue(wdev->netdev, queue->queue_id); + } } } spin_unlock_bh(&queue->lock); @@ -824,10 +949,25 @@ int bes2600_queue_get_skb(struct bes2600_queue *queue, u32 packetID, int ret = 0; u8 queue_generation, queue_id, item_generation, item_id, if_id, link_id; struct bes2600_queue_item *item; + struct bes2600_queue_item *record_item = NULL, *temp_record_item = NULL; bes2600_queue_parse_id(packetID, &queue_generation, &queue_id, &item_generation, &item_id, &if_id, &link_id); + spin_lock(&queue->stats->hw_priv->tx_loop.pending_record_lock); + if (!list_empty(&queue->stats->hw_priv->tx_loop.pending_record_list)) { + list_for_each_entry_safe(record_item, temp_record_item, &queue->stats->hw_priv->tx_loop.pending_record_list, head) { + if (record_item->packetID == packetID) { + list_del(&record_item->head); + dev_kfree_skb(record_item->skb); + kfree(record_item); + spin_unlock(&queue->stats->hw_priv->tx_loop.pending_record_lock); + return -EINVAL; + } + } + } + spin_unlock(&queue->stats->hw_priv->tx_loop.pending_record_lock); + item = &queue->pool[item_id]; spin_lock_bh(&queue->lock); @@ -835,6 +975,7 @@ int bes2600_queue_get_skb(struct bes2600_queue *queue, u32 packetID, /* TODO:COMBO: Add check for interface ID here */ if (unlikely(queue_generation != queue->generation)) { bes2600_info(BES2600_DBG_TXRX, "%s, Queue Generation is not equal\n", __func__); + WARN_ON(1); ret = -EINVAL; } else if (unlikely(item_id >= (unsigned) queue->capacity)) { WARN_ON(1); @@ -922,10 +1063,23 @@ void bes2600_queue_iterate_pending_packet(struct bes2600_queue *queue, { struct bes2600_queue_item *item = NULL; - if(list_empty(&queue->pending)) + if (list_empty(&queue->pending)) return; list_for_each_entry(item, &queue->pending, head) { iterate_cb(queue->stats->hw_priv, item->skb); } +} + +void bes2600_queue_iterate_record_pending_packet(struct bes2600_common *hw_priv, + void (*iterate_cb)(struct bes2600_common *hw_priv, struct sk_buff *skb)) +{ + struct bes2600_queue_item *item = NULL; + if (list_empty(&hw_priv->tx_loop.pending_record_list)) { + return; + } + + list_for_each_entry(item, &hw_priv->tx_loop.pending_record_list, head) { + iterate_cb(hw_priv, item->skb); + } } \ No newline at end of file diff --git a/drivers/staging/bes2600/queue.h b/drivers/staging/bes2600/queue.h index 803ceacff178..f0a40a404c47 100644 --- a/drivers/staging/bes2600/queue.h +++ b/drivers/staging/bes2600/queue.h @@ -41,7 +41,7 @@ struct bes2600_queue { struct list_head pending; int tx_locked_cnt; int *link_map_cache[CW12XX_MAX_VIFS]; - bool overfull; + bool vif_overfull[CW12XX_MAX_VIFS]; spinlock_t lock; u8 queue_id; u8 generation; @@ -169,5 +169,6 @@ int bes2600_sw_retry_requeue(struct bes2600_common *hw_priv, struct bes2600_queue *queue, u32 packetID, bool check); void bes2600_queue_iterate_pending_packet(struct bes2600_queue *queue, void (*iterate_cb)(struct bes2600_common *hw_priv, struct sk_buff *skb)); - +void bes2600_queue_iterate_record_pending_packet(struct bes2600_common *hw_priv, + void (*iterate_cb)(struct bes2600_common *hw_priv, struct sk_buff *skb)); #endif /* BES2600_QUEUE_H_INCLUDED */ diff --git a/drivers/staging/bes2600/scan.c b/drivers/staging/bes2600/scan.c index e0e13b3e5a0f..84a5373dc147 100644 --- a/drivers/staging/bes2600/scan.c +++ b/drivers/staging/bes2600/scan.c @@ -87,8 +87,8 @@ static int bes2600_disable_filtering(struct bes2600_vif *priv) priv->if_id); /* Beacon Filter Disable */ - bf_control.enabled = 0; - bf_control.bcn_count = 1; + bf_control.enabled = __cpu_to_le32(0); + bf_control.bcn_count = __cpu_to_le32(1); if (!ret) ret = wsm_beacon_filter_control(hw_priv, &bf_control, priv->if_id); @@ -651,8 +651,8 @@ void bes2600_scan_work(struct work_struct *work) if (scan.band == NL80211_BAND_2GHZ) { coex_calc_wifi_scan_time(&minChannelTime, &maxChannelTime); } else { - minChannelTime = 90; - maxChannelTime = 90; + minChannelTime = 100; + maxChannelTime = 100; } #endif @@ -1078,7 +1078,7 @@ void bes2600_probe_work(struct work_struct *work) return; } - if (bes2600_queue_get_skb(queue, hw_priv->pending_frame_id, + if (bes2600_queue_get_skb(queue, hw_priv->pending_frame_id, &frame.skb, &txpriv)) { up(&hw_priv->scan.lock); up(&hw_priv->conf_lock); diff --git a/drivers/staging/bes2600/sta.c b/drivers/staging/bes2600/sta.c index eed1c85fc67c..4fa7e4ad9999 100644 --- a/drivers/staging/bes2600/sta.c +++ b/drivers/staging/bes2600/sta.c @@ -38,7 +38,7 @@ #include "epta_request.h" #include "epta_coex.h" -#ifdef PLAT_ALLWINNER_R329 +#if defined(PLAT_ALLWINNER_R329) || defined(STANDARD_FACTORY_EFUSE_FLAG) #include "bes2600_factory.h" #endif @@ -132,7 +132,7 @@ static inline void __bes2600_bf_configure(struct bes2600_vif *priv) WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT | WSM_BEACON_FILTER_IE_HAS_APPEARED; - priv->bf_control.enabled = WSM_BEACON_FILTER_ENABLE; + priv->bf_control.enabled = __cpu_to_le32(WSM_BEACON_FILTER_ENABLE); } /* ******************************************************************** */ @@ -236,8 +236,20 @@ void bes2600_stop(struct ieee80211_hw *dev) spin_unlock(&hw_priv->event_queue_lock); __bes2600_free_event_queue(&list); - for (i = 0; i < 4; i++) - bes2600_queue_clear(&hw_priv->tx_queue[i], CW12XX_ALL_IFS); + spin_lock(&hw_priv->vif_list_lock); + bes2600_for_each_vif(hw_priv, priv, i) { + if (!priv) + continue; + if (!(hw_priv->if_id_slot & BIT(priv->if_id))) + return; + /* protect tx confirm flow */ + spin_lock(&priv->vif_lock); + for (i = 0; i < 4; i++) + bes2600_queue_clear(&hw_priv->tx_queue[i], i); + spin_unlock(&priv->vif_lock); + } + spin_unlock(&hw_priv->vif_list_lock); + /* HACK! */ if (atomic_xchg(&hw_priv->tx_lock, 1) != 1) @@ -424,6 +436,9 @@ void bes2600_remove_interface(struct ieee80211_hw *dev, bes2600_info(BES2600_DBG_STA, "AP REMOVE 11BG %d\n",hw_priv->vif0_throttle); } bes2600_pwr_clear_busy_event(hw_priv, BES2600_JOIN_STATUS_AP); +#ifdef BES2600_TX_RX_OPT + bes2600_txrx_opt_timer_restore(); +#endif break; case BES2600_JOIN_STATUS_MONITOR: bes2600_disable_listening(priv); @@ -600,12 +615,12 @@ void bes2600_update_filtering(struct bes2600_vif *priv) struct bes2600_common *hw_priv = cw12xx_vifpriv_to_hwpriv(priv); bool bssid_filtering = !priv->rx_filter.bssid; static struct wsm_beacon_filter_control bf_disabled = { - .enabled = 0, - .bcn_count = 1, + .enabled = __cpu_to_le32(0), + .bcn_count = __cpu_to_le32(1), }; bool ap_mode = 0; static struct wsm_beacon_filter_table bf_table_auto = { - .numOfIEs = __cpu_to_le32(2), + .numOfIEs = __cpu_to_le32(1), .entry[0].ieId = WLAN_EID_VENDOR_SPECIFIC, .entry[0].actionFlags = WSM_BEACON_FILTER_IE_HAS_CHANGED | WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT | @@ -613,18 +628,14 @@ void bes2600_update_filtering(struct bes2600_vif *priv) .entry[0].oui[0] = 0x50, .entry[0].oui[1] = 0x6F, .entry[0].oui[2] = 0x9A, - - .entry[1].ieId = WLAN_EID_HT_OPERATION, - .entry[1].actionFlags = WSM_BEACON_FILTER_IE_HAS_CHANGED | - WSM_BEACON_FILTER_IE_NO_LONGER_PRESENT | - WSM_BEACON_FILTER_IE_HAS_APPEARED, }; static struct wsm_beacon_filter_control bf_auto = { - .enabled = WSM_BEACON_FILTER_ENABLE | - WSM_BEACON_FILTER_AUTO_ERP, - .bcn_count = 1, + .enabled = __cpu_to_le32(WSM_BEACON_FILTER_ENABLE | + WSM_BEACON_FILTER_AUTO_ERP | WSM_BEACON_FILTER_AUTO_HT), + // .bcn_count = __cpu_to_le32(priv->bf_control.bcn_count); }; - bf_auto.bcn_count = priv->bf_control.bcn_count; + // bf_table_auto.numOfIEs = 0; /* No filtering to do - so discarding */ + bf_auto.bcn_count = __cpu_to_le32(priv->bf_control.bcn_count); if (priv->join_status == BES2600_JOIN_STATUS_PASSIVE) return; @@ -783,8 +794,8 @@ void bes2600_configure_filter(struct ieee80211_hw *hw, priv->rx_filter.bssid = (*total_flags & (FIF_OTHER_BSS | FIF_PROBE_REQ)) ? 1 : 0; priv->rx_filter.fcs = (*total_flags & FIF_FCSFAIL) ? 1 : 0; - priv->bf_control.bcn_count = (*total_flags & - (FIF_BCN_PRBRESP_PROMISC | FIF_PROBE_REQ)) ? 1 : 0; + priv->bf_control.bcn_count = __cpu_to_le32((*total_flags & + (FIF_BCN_PRBRESP_PROMISC | FIF_PROBE_REQ)) ? 1 : 0); #if 0 if (priv->listening ^ listening) { priv->listening = listening; @@ -800,7 +811,7 @@ void bes2600_configure_filter(struct ieee80211_hw *hw, } int bes2600_conf_tx(struct ieee80211_hw *dev, struct ieee80211_vif *vif, - u16 queue, const struct ieee80211_tx_queue_params *params) + unsigned int link_id, u16 queue, const struct ieee80211_tx_queue_params *params) { struct bes2600_common *hw_priv = dev->priv; struct bes2600_vif *priv = cw12xx_get_vif_from_ieee80211(vif); @@ -829,9 +840,9 @@ int bes2600_conf_tx(struct ieee80211_hw *dev, struct ieee80211_vif *vif, goto out; } - WSM_EDCA_SET(&priv->edca, queue, params->aifs, - params->cw_min, params->cw_max, params->txop, 0xc8, - params->uapsd); + WSM_EDCA_SET(&priv->edca, queue, params->aifs, + params->cw_min, params->cw_max, params->txop, 0xc8, + params->uapsd); ret = wsm_set_edca_params(hw_priv, &priv->edca, priv->if_id); if (ret) { ret = -EINVAL; @@ -1183,9 +1194,12 @@ int __bes2600_flush(struct bes2600_common *hw_priv, bool drop, int if_id) * Temporary workaround: 2s */ if (drop) { + /* protect tx confirm flow */ + spin_lock(&priv->vif_lock); for (i = 0; i < 4; ++i) bes2600_queue_clear(&hw_priv->tx_queue[i], if_id); + spin_unlock(&priv->vif_lock); } else { ret = wait_event_timeout( hw_priv->tx_queue_stats.wait_link_id_empty, @@ -1224,6 +1238,7 @@ void bes2600_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct bes2600_vif *priv = NULL; struct bes2600_common *hw_priv = hw->priv; unsigned int ret = 0; + int hw_bufs_used = 0; int i; /* get queue status */ @@ -1231,6 +1246,7 @@ void bes2600_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, priv = cw12xx_get_vif_from_ieee80211(vif); ret |= !bes2600_queue_stats_is_empty( &hw_priv->tx_queue_stats, -1, priv->if_id); + hw_bufs_used = hw_priv->hw_bufs_used_vif[priv->if_id]; } else { bes2600_for_each_vif(hw_priv, priv, i) { if (!priv) @@ -1239,11 +1255,12 @@ void bes2600_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, return; ret |= !bes2600_queue_stats_is_empty( &hw_priv->tx_queue_stats, -1, priv->if_id); + hw_bufs_used = hw_priv->hw_bufs_used; } } /* no need to do the next work if queue was already clear */ - if(ret == 0) { + if((ret == 0) && (hw_bufs_used == 0)) { bes2600_info(BES2600_DBG_STA, "no need to flush\n"); return; } @@ -1385,6 +1402,10 @@ void bes2600_event_handler(struct work_struct *work) break; case WSM_EVENT_BSS_LOST: { + if (bes2600_chrdev_wakeup_by_event_get() == WAKEUP_EVENT_WSME) { + bes2600_chrdev_wifi_update_wakeup_reason(WAKEUP_REASON_WIFI_BSSLOST, 0); + bes2600_chrdev_wakeup_by_event_set(WAKEUP_EVENT_NONE); + } spin_lock(&priv->bss_loss_lock); if (priv->bss_loss_status > BES2600_BSS_LOSS_NONE) { spin_unlock(&priv->bss_loss_lock); @@ -1498,11 +1519,22 @@ void bes2600_event_handler(struct work_struct *work) break; } case WSM_EVENT_WAKEUP_EVENT: - bes2600_info(BES2600_DBG_STA, "wifi wakeup, Reason:%u\n", event->evt.eventData); - bes2600_chrdev_wifi_update_wakeup_reason(event->evt.eventData); + { + if (bes2600_chrdev_wakeup_by_event_get() == WAKEUP_EVENT_WSME) { + u16 src_port, reason; + reason = event->evt.eventData & 0xFFFF; + src_port = event->evt.eventData >> 16; + src_port = __be16_to_cpu(src_port); + bes2600_info(BES2600_DBG_STA, "wifi wakeup, reason: %u, src_port: %u\n", reason, src_port); + bes2600_chrdev_wifi_update_wakeup_reason(reason, src_port); + bes2600_chrdev_wakeup_by_event_set(WAKEUP_EVENT_NONE); + } + } + break; } } + bes2600_chrdev_wakeup_by_event_set(WAKEUP_EVENT_NONE); up(&hw_priv->conf_lock); __bes2600_free_event_queue(&list); } @@ -1529,7 +1561,7 @@ void bes2600_bss_loss_work(struct work_struct *work) spin_lock(&priv->bss_loss_lock); #ifdef BSS_LOSS_CHECK - if (!priv->vif->bss_conf.assoc) { + if (!priv->vif->cfg.assoc) { priv->bss_loss_status = BES2600_BSS_LOSS_NONE; spin_unlock(&priv->bss_loss_lock); bl_ck_cnt = 0; @@ -1545,7 +1577,8 @@ void bes2600_bss_loss_work(struct work_struct *work) bl_ck_cnt = 0; bl_cfm_cnt = 0; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) - skb = ieee80211_nullfunc_get(priv->hw, priv->vif, false); + // skb = ieee80211_nullfunc_get(priv->hw, priv->vif, false); + skb = ieee80211_nullfunc_get(priv->hw, priv->vif, -1, false); #else skb = ieee80211_nullfunc_get(priv->hw, priv->vif); #endif @@ -1575,7 +1608,8 @@ void bes2600_bss_loss_work(struct work_struct *work) spin_unlock(&priv->bss_loss_lock); priv->bss_loss_status = BES2600_BSS_LOSS_CHECKING; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) - skb = ieee80211_nullfunc_get(priv->hw, priv->vif, false); + // skb = ieee80211_nullfunc_get(priv->hw, priv->vif, false); + skb = ieee80211_nullfunc_get(priv->hw, priv->vif, -1, false); #else skb = ieee80211_nullfunc_get(priv->hw, priv->vif); #endif @@ -1611,7 +1645,8 @@ void bes2600_bss_loss_work(struct work_struct *work) spin_unlock(&priv->bss_loss_lock); priv->bss_loss_status = BES2600_BSS_LOSS_CHECKING; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) - skb = ieee80211_nullfunc_get(priv->hw, priv->vif, false); + // skb = ieee80211_nullfunc_get(priv->hw, priv->vif, false); + skb = ieee80211_nullfunc_get(priv->hw, priv->vif, -1, false); #else skb = ieee80211_nullfunc_get(priv->hw, priv->vif); #endif @@ -1661,9 +1696,14 @@ void bes2600_connection_loss_work(struct work_struct *work) struct bes2600_vif *priv = container_of(work, struct bes2600_vif, connection_loss_work.work); + struct bes2600_common *hw_priv = cw12xx_vifpriv_to_hwpriv(priv); + bes2600_info(BES2600_DBG_STA, "[CQM] Reporting connection loss.\n"); bes2600_pwr_clear_busy_event(priv->hw_priv, BES_PWR_LOCK_ON_BSS_LOST); - ieee80211_connection_loss(priv->vif); + if(bes2600_suspend_status_get(hw_priv)) { + bes2600_pending_unjoin_set(hw_priv, priv->if_id); + } else + ieee80211_connection_loss(priv->vif); #ifdef WIFI_BT_COEXIST_EPTA_ENABLE // set disconnected in BSS_CHANGED_ASSOC // bwifi_change_current_status(hw_priv, BWIFI_STATUS_DISCONNECTED); @@ -2295,6 +2335,7 @@ void bes2600_join_work(struct work_struct *work) #else wsm_set_template_frame(hw_priv, &probe_tmp, priv->if_id); #endif + dev_kfree_skb(probe_tmp.skb); } if (wsm_join(hw_priv, &join, priv->if_id)) { @@ -2390,7 +2431,7 @@ void bes2600_unjoin_work(struct work_struct *work) cancel_work_sync(&priv->set_beacon_wakeup_period_work); memset(&priv->join_bssid[0], 0, sizeof(priv->join_bssid)); #ifdef BES2600_TX_RX_OPT - txrx_opt_timer_exit(hw_priv); + txrx_opt_timer_exit(priv); #endif bes2600_pwr_clear_busy_event(priv->hw_priv, BES_PWR_LOCK_ON_PS_ACTIVE); bes2600_pwr_clear_ap_lp_bad_mark(hw_priv); @@ -2838,11 +2879,15 @@ void bes2600_rem_chan_timeout(struct work_struct *work) void bes2600_dynamic_opt_txrx_work(struct work_struct *work) { + bool multivif_connected = false; struct bes2600_common *hw_priv = container_of(work, struct bes2600_common, dynamic_opt_txrx_work); - struct bes2600_vif *priv = __cw12xx_hwpriv_to_vifpriv(hw_priv, 0); - bes2600_dynamic_opt_rxtx(hw_priv,priv, 0); - bes2600_dbg(BES2600_DBG_STA, "bes2600_dynamic_opt_txrx_work called\n"); + struct bes2600_vif *priv = __cw12xx_hwpriv_to_vifpriv(hw_priv, 1); + + if (priv != NULL && priv->join_status > BES2600_JOIN_STATUS_MONITOR) { + multivif_connected = true; + } + bes2600_txrx_opt_multivif_connected_handler(hw_priv, multivif_connected); } @@ -2980,7 +3025,7 @@ static int bes2600_set_ipv6addrfilter(struct ieee80211_hw *hw, ipv6_info = (struct ipv6_addr_info *)&data[2]; /* Computing sizeof Mac addr filter */ - ipaddrfiltersize = sizeof(*ipv6_filter) + \ + ipaddrfiltersize = sizeof(struct wsm_ipv6_filter_header) + \ (no_of_ip_addr * sizeof(struct wsm_ip6_addr_info)); @@ -2989,8 +3034,8 @@ static int bes2600_set_ipv6addrfilter(struct ieee80211_hw *hw, ret = -ENOMEM; goto exit_p; } - ipv6_filter->action_mode = action_mode; - ipv6_filter->numfilter = no_of_ip_addr; + ipv6_filter->hdr.action_mode = action_mode; + ipv6_filter->hdr.numfilter = no_of_ip_addr; for (i = 0; i < no_of_ip_addr; i++) { ipv6_filter->ipv6filter[i].address_mode = \ @@ -3025,8 +3070,10 @@ void bes2600_set_data_filter(struct ieee80211_hw *hw, void *data, int len) { int ret = 0; - //struct bes2600_vif *priv = cw12xx_get_vif_from_ieee80211(vif); int filter_id; +#ifdef IPV6_FILTERING + struct bes2600_vif *priv = cw12xx_get_vif_from_ieee80211(vif); +#endif /*IPV6_FILTERING*/ if (!data) { ret = -EINVAL; @@ -4344,8 +4391,8 @@ static int net_device_en_ip_offload(struct ieee80211_hw *hw, struct ieee80211_vi } #endif /* CONFIG_BES2600_KEEP_ALIVE */ -#ifdef PLAT_ALLWINNER_R329 -static int bes2600_factory_cali_to_flash(struct ieee80211_hw *hw) +#if defined(PLAT_ALLWINNER_R329) || defined(STANDARD_FACTORY_EFUSE_FLAG) +static int bes2600_factory_cali_to_mcu(struct ieee80211_hw *hw, enum bes2600_rf_cmd_type cmd_type) { struct bes2600_common *hw_priv = hw->priv; u8 *factory_data = NULL; @@ -4367,8 +4414,8 @@ static int bes2600_factory_cali_to_flash(struct ieee80211_hw *hw) } else { bes2600_factory_data_check(factory_data); factory_little_endian_cvrt(factory_data); - ret = wsm_save_factory_txt_to_flash(hw_priv, factory_data, 0); - bes2600_err_with_cond(ret, BES2600_DBG_DOWNLOAD, "save factory data to flash failed.\n"); + ret = wsm_save_factory_txt_to_mcu(hw_priv, factory_data, 0, cmd_type); + bes2600_err_with_cond(ret, BES2600_DBG_DOWNLOAD, "save factory data to mcu failed.\n"); } bes2600_factory_free_file_buffer(file_buffer); bes2600_factory_unlock(); @@ -4377,7 +4424,16 @@ static int bes2600_factory_cali_to_flash(struct ieee80211_hw *hw) return bes2600_testmode_reply(hw->wiphy, &ret, sizeof(int)); return ret; +} +#endif +#ifdef STANDARD_FACTORY_EFUSE_FLAG +static int bes2600_set_select_efuse_flag_to_txt(struct ieee80211_hw *hw, + void *data, int len) +{ + struct bes_select_calib_t *test_p = (struct bes_select_calib_t *)data; + int ret = bes2600_select_efuse_flag_write(test_p->select_efuse_flag); + return bes2600_testmode_reply(hw->wiphy, &ret, sizeof(int)); } #endif @@ -4490,9 +4546,23 @@ int bes2600_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, voi break; case BES_MSG_SAVE_CALI_TXT_TO_FLASH: #ifdef PLAT_ALLWINNER_R329 - ret = bes2600_factory_cali_to_flash(hw); + ret = bes2600_factory_cali_to_mcu(hw, BES2600_RF_CMD_CALI_TXT_TO_FLASH); +#else + ret = -EPERM; +#endif + break; + case BES_MSG_SAVE_CALI_TXT_TO_EFUSE: +#ifdef STANDARD_FACTORY_EFUSE_FLAG + ret = bes2600_factory_cali_to_mcu(hw, BES2600_RF_CMD_CALI_TXT_TO_EFUSE); #else ret = -EPERM; +#endif + break; + case BES_MSG_SET_SELECT_EFUSE_FLAG: +#ifdef STANDARD_FACTORY_EFUSE_FLAG + ret = bes2600_set_select_efuse_flag_to_txt(hw, nla_data(data_p), nla_len(data_p)); +#else + ret = EPERM; #endif break; case BES_MSG_VENDOR_RF_CMD: diff --git a/drivers/staging/bes2600/sta.h b/drivers/staging/bes2600/sta.h index f97e8fc1bb21..229d1305f38f 100644 --- a/drivers/staging/bes2600/sta.h +++ b/drivers/staging/bes2600/sta.h @@ -36,7 +36,7 @@ void bes2600_configure_filter(struct ieee80211_hw *dev, unsigned int *total_flags, u64 multicast); int bes2600_conf_tx(struct ieee80211_hw *dev, struct ieee80211_vif *vif, - u16 queue, const struct ieee80211_tx_queue_params *params); + unsigned int link_id, u16 queue, const struct ieee80211_tx_queue_params *params); int bes2600_get_stats(struct ieee80211_hw *dev, struct ieee80211_low_level_stats *stats); /* Not more a part of interface? diff --git a/drivers/staging/bes2600/tx_loop.c b/drivers/staging/bes2600/tx_loop.c index dbd5c37c6b9d..69eef9f4c14f 100644 --- a/drivers/staging/bes2600/tx_loop.c +++ b/drivers/staging/bes2600/tx_loop.c @@ -27,6 +27,8 @@ void bes2600_tx_loop_init(struct bes2600_common *hw_priv) hw_priv->tx_loop.enabled = false; hw_priv->tx_loop.start_lmac_seq = 0; hw_priv->tx_loop.start_mcu_seq = 0; + INIT_LIST_HEAD(&hw_priv->tx_loop.pending_record_list); + spin_lock_init(&hw_priv->tx_loop.pending_record_lock); spin_lock_init(&hw_priv->tx_loop.tx_loop_lock); skb_queue_head_init(&hw_priv->tx_loop.rx_queue); } @@ -108,6 +110,9 @@ void bes2600_tx_loop_set_enable(struct bes2600_common *hw_priv) bes2600_queue_iterate_pending_packet(&hw_priv->tx_queue[i], bes2600_tx_loop_item_pending_item); } + spin_lock(&hw_priv->tx_loop.pending_record_lock); + bes2600_queue_iterate_record_pending_packet(hw_priv, bes2600_tx_loop_item_pending_item); + spin_unlock(&hw_priv->tx_loop.pending_record_lock); if (atomic_read(&hw_priv->bh_rx) > 0) wake_up(&hw_priv->bh_wq); diff --git a/drivers/staging/bes2600/tx_loop.h b/drivers/staging/bes2600/tx_loop.h index 7294025d8eca..f7325c9fae0f 100644 --- a/drivers/staging/bes2600/tx_loop.h +++ b/drivers/staging/bes2600/tx_loop.h @@ -21,6 +21,8 @@ struct bes2600_tx_loop u8 start_mcu_seq; struct sk_buff_head rx_queue; u8 *wsm_cmd_ptr; + struct list_head pending_record_list; + spinlock_t pending_record_lock; }; void bes2600_tx_loop_init(struct bes2600_common *hw_priv); diff --git a/drivers/staging/bes2600/txrx.c b/drivers/staging/bes2600/txrx.c index d9202bce7116..ce700bdcaf72 100644 --- a/drivers/staging/bes2600/txrx.c +++ b/drivers/staging/bes2600/txrx.c @@ -10,6 +10,7 @@ */ #include +#include #include #include @@ -90,28 +91,23 @@ static void tx_policy_build(const struct bes2600_common *hw_priv, BUG_ON(rates[0].idx < 0); memset(policy, 0, sizeof(*policy)); - /* minstrel is buggy a little bit, so distille - * incoming rates first. */ - /* Sort rates in descending order. */ + /* + * Calculate the count of rate list. + * Don't change the order of rate list, it will cause tp debounce at medium attenuation + * For some test, you may want to rate stable, you can use fix rate. + * The way of setting fix rate is writting /sys/kernel/debug/ieee80211/phy0/rc/fixed_rate_idx + * Note: if you want to use the function of fix rate, you need to make sure CONFIG_MAC80211_DEBUGFS is y + */ + for (i = 0; i < count; i++) { if (rates[i].idx < 0) { count = i; break; } - for (j= 0; j < count; j++) { - if (rates[j].idx < 0) { - continue; - } - - if (rates[j].idx < rates[j + 1].idx) { - struct ieee80211_tx_rate tmp = rates[j]; - rates[j] = rates[j + 1]; - rates[j + 1] = tmp; - } - } } + /* enhance throughput, more tx retry rate */ -#ifdef BES2600_TX_RX_OPT +#if defined(BES2600_TX_RX_OPT) && defined(BES2600_TX_MORE_RETRY) if (rates[0].flags & IEEE80211_TX_RC_MCS) { static int min_rate_index = 1; //min rate index is mcs1 static u8 last_rate_tx_cnt = 7; @@ -1073,7 +1069,7 @@ void bes2600_tx(struct ieee80211_hw *dev, int ret; struct bes2600_vif *priv; struct ieee80211_hdr *frame = (struct ieee80211_hdr *)skb->data; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; if (!skb->data) BUG_ON(1); @@ -1320,13 +1316,23 @@ void bes2600_tx_confirm_cb(struct bes2600_common *hw_priv, } else if ((hw_priv->start_stop_tsm.start) && (arg->status == WSM_STATUS_SUCCESS)) { if (queue_id == hw_priv->tsm_info.ac) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) + struct timespec64 tmval; + ktime_get_real_ts64(&tmval); +#else struct timeval tmval; do_gettimeofday(&tmval); +#endif pkt_delay = hw_priv->start_stop_tsm.packetization_delay; if (hw_priv->tsm_info.sta_roamed && !hw_priv->tsm_info.use_rx_roaming) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) + hw_priv->tsm_info.roam_delay = tmval.tv_nsec / 1000 - + hw_priv->tsm_info.txconf_timestamp_vo; +#else hw_priv->tsm_info.roam_delay = tmval.tv_usec - hw_priv->tsm_info.txconf_timestamp_vo; +#endif if (hw_priv->tsm_info.roam_delay > pkt_delay) hw_priv->tsm_info.roam_delay -= pkt_delay; bes2600_info(BES2600_DBG_TEST_MODE, "[TX] txConf" @@ -1334,7 +1340,11 @@ void bes2600_tx_confirm_cb(struct bes2600_common *hw_priv, hw_priv->tsm_info.roam_delay); hw_priv->tsm_info.sta_roamed = 0; } - hw_priv->tsm_info.txconf_timestamp_vo = tmval.tv_usec; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) + hw_priv->tsm_info.rx_timestamp_vo = tmval.tv_nsec / 1000; +#else + hw_priv->tsm_info.rx_timestamp_vo = tmval.tv_usec; +#endif } } spin_unlock_bh(&hw_priv->tsm_lock); @@ -1422,7 +1432,6 @@ void bes2600_tx_confirm_cb(struct bes2600_common *hw_priv, if (tx_count) ++tx_count; } - spin_unlock(&priv->vif_lock); for (i = 0; i < IEEE80211_TX_MAX_RATES; ++i) { if (tx->status.rates[i].count >= tx_count) { @@ -1440,6 +1449,7 @@ void bes2600_tx_confirm_cb(struct bes2600_common *hw_priv, } #ifdef KEY_FRAME_SW_RETRY if (bes2600_bh_sw_process(hw_priv, arg) == 0) { + spin_unlock(&priv->vif_lock); return; } #endif @@ -1449,6 +1459,7 @@ void bes2600_tx_confirm_cb(struct bes2600_common *hw_priv, #else bes2600_queue_remove(queue, arg->packetID); #endif /*CONFIG_BES2600_TESTMODE*/ + spin_unlock(&priv->vif_lock); }else { spin_unlock(&priv->vif_lock); return; @@ -1499,8 +1510,11 @@ void bes2600_skb_dtor(struct bes2600_common *hw_priv, tx_policy_put(hw_priv, txpriv->rate_id); } if (likely(!bes2600_is_itp(hw_priv))) { + if (priv) { + /* The interface may be already removed */ + bes2600_tx_status(priv, skb); + } ieee80211_tx_status(hw_priv->hw, skb); - bes2600_tx_status(priv, skb); } } @@ -1600,18 +1614,30 @@ void bes2600_rx_cb(struct bes2600_vif *priv, struct bes2600_link_entry *entry = NULL; bool early_data = false; size_t hdrlen = 0; + u64 tsf; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) + do { +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0) + struct timespec ts; + ts = ktime_to_timespec(ktime_get_boottime()); + tsf = (u64)ts.tv_sec * 1000000000 + ts.tv_nsec; +#else + struct timespec64 ts; + ts = ktime_to_timespec64(ktime_get_boottime()); + tsf = (u64)ts.tv_sec * 1000000000 + ts.tv_nsec; +#endif + hdr->boottime_ns = tsf; + } while (0); +#endif hdr->flag = 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) - hdr->boottime_ns = ktime_get_boot_ns(); -#endif if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED)) { /* STA is stopped. */ goto drop; } /* wakeup device based on frame type */ - if (!is_multicast_ether_addr(ieee80211_get_DA(frame))) { + if (!is_multicast_ether_addr(ieee80211_get_DA(frame)) && ieee80211_is_data(frame->frame_control)) { /* for unicast, wakeup device directly */ bes2600_pwr_set_busy_event_with_timeout_async( hw_priv, BES_PWR_LOCK_ON_RX, BES_PWR_EVENT_RX_TIMEOUT); @@ -1628,17 +1654,31 @@ void bes2600_rx_cb(struct bes2600_vif *priv, if (hw_priv->start_stop_tsm.start) { unsigned queue_id = skb_get_queue_mapping(skb); if (queue_id == 0) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) + struct timespec64 tmval; + ktime_get_real_ts64(&tmval); +#else struct timeval tmval; do_gettimeofday(&tmval); +#endif if (hw_priv->tsm_info.sta_roamed && - hw_priv->tsm_info.use_rx_roaming) { + hw_priv->tsm_info.use_rx_roaming) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) + hw_priv->tsm_info.roam_delay = tmval.tv_nsec / 1000 - + hw_priv->tsm_info.rx_timestamp_vo; +#else hw_priv->tsm_info.roam_delay = tmval.tv_usec - hw_priv->tsm_info.rx_timestamp_vo; +#endif bes2600_dbg(BES2600_DBG_TEST_MODE, "[RX] RxInd Roaming:" "roam_delay = %u\n", hw_priv->tsm_info.roam_delay); hw_priv->tsm_info.sta_roamed = 0; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) + hw_priv->tsm_info.rx_timestamp_vo = tmval.tv_nsec / 1000; +#else hw_priv->tsm_info.rx_timestamp_vo = tmval.tv_usec; +#endif } } spin_unlock_bh(&hw_priv->tsm_lock); diff --git a/drivers/staging/bes2600/txrx_opt.c b/drivers/staging/bes2600/txrx_opt.c index 15f6abbb666f..edc1691ce25b 100644 --- a/drivers/staging/bes2600/txrx_opt.c +++ b/drivers/staging/bes2600/txrx_opt.c @@ -27,6 +27,7 @@ #include "sbus.h" #include "bes2600_log.h" #include "bes_pwr.h" +#include "txrx_opt.h" #define TXRX_OPT_CLOSE_EDCA 0 #define TXRX_OPT_EDCA_MAX_LEVEL 4 @@ -34,15 +35,25 @@ #define TXRX_OPT_PEROID 500 #define TXRX_OPT_DEBUG 1 -#define TXRX_HIGH_TP_THRESHOLD_2G4 30000 //unit is kbps -#define TXRX_HIGH_TP_THRESHOLD_5G 40000 //unit is kbps -#define TXRX_HIGH_TP_DELTA_TIME_2G4 8 //unit ms -#define TXRX_HIGH_TP_DELTA_TIME_5G 6 //unit ms +#define TXRX_HIGH_TP_THRESHOLD_2G4 30000 // unit is kbps +#define TXRX_HIGH_TP_THRESHOLD_5G 40000 // unit is kbps +#define TXRX_HIGH_TP_DELTA_TIME_2G4 8 // unit ms +#define TXRX_HIGH_TP_DELTA_TIME_5G 6 // unit ms + +#define TXRX_RTS_PROT_TRIG_THRESH 80 // percent * 100 +#define TXRX_RTS_PROT_DURATION 10 // unit second + +#define TXRX_RTS_PROT_OPEN(x) (x = 512) +#define TXRX_RTS_PROT_CLOSE(x) (x = 2437) +#define TXRX_RTS_PROT_OPENED(x) (x < 1536) static uint32_t tx_delta_time_arr[4][TX_AVG_TIME_COUNT]; static uint32_t tx_queue_arr[4] = {0}; static uint32_t tx_delta_time_total = 0; static uint32_t tx_delta_time_total_cnt = 0; +static u8 cur_pwr_tbl = 1; +static u16 cur_rts_thres = 2437; +static unsigned long last_rts_set_time = -1; void bes2600_add_tx_delta_time(uint32_t tx_delta_time) { @@ -185,8 +196,9 @@ int bes2600_set_high_edca_params(struct bes2600_common *hw_priv, struct bes2600_ if (lev == level) return 0; - memcpy(&arg, &(priv->edca), sizeof(struct wsm_edca_params)); + lev = level; + memcpy(&arg, &(priv->edca), sizeof(struct wsm_edca_params)); if (level == 0) { bes2600_set_default_params(hw_priv, priv); @@ -245,6 +257,26 @@ void bes2600_set_dynamic_agc(struct bes2600_common *hw_priv, struct bes2600_vif { // todo set agc alg } + +int bes2600_update_pwr_table(struct bes2600_common *hw_priv, + struct bes2600_vif *priv, + u8 pwr_tbl_idx) +{ + int ret = 0; + static u8 cur_pwr_tbl_idx = 0xff; + + if (cur_pwr_tbl_idx != pwr_tbl_idx) { + cur_pwr_tbl_idx = pwr_tbl_idx; + ret = WARN_ON(wsm_write_mib(hw_priv, + WSM_MIB_ID_EXT_PWR_TBL_UPDATE, + (u8 *)&cur_pwr_tbl_idx, + sizeof(cur_pwr_tbl_idx), + priv->if_id)); + bes2600_info(BES2600_DBG_TXRX_OPT, "%s pwr_tbl_idx=%d\n\r", __func__, pwr_tbl_idx); + } + return ret; +} + int bes2600_get_tx_av_max_delta_time(void) { int max_avg = 0; @@ -278,8 +310,6 @@ void bes2600_dynamic_opt_rxtx(struct bes2600_common *hw_priv, struct bes2600_vif static u32 tx_bps = 0, rx_bps = 0; u32 total_kbps = 0; static int level; - int rts_value = 2347; - int short_gi = 0; /* calculate real time throughput */ if (hw_priv == NULL || priv == NULL) { @@ -295,6 +325,8 @@ void bes2600_dynamic_opt_rxtx(struct bes2600_common *hw_priv, struct bes2600_vif /* if tx/rx < 100k/s, close*/ if (total_kbps < 100) { level = 0; + last_rts_set_time = -1; + TXRX_RTS_PROT_CLOSE(cur_rts_thres); goto txrx_opt_clear; } @@ -305,16 +337,18 @@ void bes2600_dynamic_opt_rxtx(struct bes2600_common *hw_priv, struct bes2600_vif rx_cnt = (priv->dot11ReceivedFragmentCount - l_rx_cnt); ( (tx_cnt + tx_retry) > 0 ) ? (succPro = tx_cnt * 100 / (tx_cnt + tx_retry)) : (succPro = 0); - if (succPro != 0) { - /* hw value 21 is mcs7, dynamic set short GI */ - if (priv->hw_value == 21 && succPro > 90) - short_gi = 1; - else - short_gi = 0; - - /* dynamic set RTS/CTS */ - if (succPro < 80) - rts_value = 512; + bes2600_dbg(BES2600_DBG_TXRX_OPT, "%s, tx_cnt:%d prob:%d\n", __func__, tx_cnt, succPro); + + /* set rts/cts protection dynamically */ + if (tx_cnt > 50 && succPro != 0) { + if (succPro > TXRX_RTS_PROT_TRIG_THRESH && + TXRX_RTS_PROT_OPENED(cur_rts_thres) && + time_after(jiffies, last_rts_set_time + TXRX_RTS_PROT_DURATION * HZ)) { + TXRX_RTS_PROT_CLOSE(cur_rts_thres); + } else if (succPro <= TXRX_RTS_PROT_TRIG_THRESH){ + TXRX_RTS_PROT_OPEN(cur_rts_thres); + last_rts_set_time = jiffies; + } } /* dynamic set edca param */ @@ -348,14 +382,21 @@ void bes2600_dynamic_opt_rxtx(struct bes2600_common *hw_priv, struct bes2600_vif } } + + /* dynamic set power table */ + if (rssi <= BES2600_TX_RSSI_LOW) + cur_pwr_tbl = 2; // use high power table + else if(rssi >= BES2600_TX_RSSI_HIGH) + cur_pwr_tbl = 1; // use standard power table + #if TXRX_OPT_CLOSE_EDCA level = 0; #endif if (level > TXRX_OPT_EDCA_MAX_LEVEL) level = TXRX_OPT_EDCA_MAX_LEVEL; - bes2600_dbg(BES2600_DBG_TXRX_OPT, "txrx_opt: tx(cnt=%d retry=%d psr=%d tx_fail=%d (wsm rts=%d shortgi=%d level=%d) tx=%dk/s)\n\r", - tx_cnt, tx_retry, succPro, tx_fail, rts_value, short_gi, level, tx_bps / 128); + bes2600_dbg(BES2600_DBG_TXRX_OPT, "txrx_opt: tx(cnt=%d retry=%d psr=%d tx_fail=%d (wsm level=%d) tx=%dk/s)\n\r", + tx_cnt, tx_retry, succPro, tx_fail, level, tx_bps / 128); bes2600_dbg(BES2600_DBG_TXRX_OPT, "txrx_opt: rx(cnt=%d rx=%dk/s) total=%dk/s\n\r", rx_cnt, rx_bps / 128, total_kbps); bes2600_dbg(BES2600_DBG_TXRX_OPT, "txrx_opt: tx_delta_time=%d [%d %d %d %d] hw_value=%d ht=%d maxtxcnt=%d\n\r", bes2600_get_tx_delta_time(), bes2600_get_tx_ac_delta_time(0), bes2600_get_tx_ac_delta_time(1), @@ -367,10 +408,10 @@ void bes2600_dynamic_opt_rxtx(struct bes2600_common *hw_priv, struct bes2600_vif bes2600_set_cca_method(hw_priv, priv, 0); /* dynamic set agc */ bes2600_set_dynamic_agc(hw_priv, priv, 0); + bes2600_update_pwr_table(hw_priv, priv, cur_pwr_tbl); txrx_opt_clear: - bes2600_set_rts_threshold(priv->hw, rts_value); - bes2600_enable_tx_shortgi(hw_priv, priv, short_gi); bes2600_set_high_edca_params(hw_priv, priv, level); + bes2600_set_rts_threshold(hw_priv->hw, cur_rts_thres); bes2600_clear_tx_delta_time(); bes2600_clear_tx_ac_delta_time(0); bes2600_clear_tx_ac_delta_time(1); @@ -387,6 +428,21 @@ void bes2600_dynamic_opt_rxtx(struct bes2600_common *hw_priv, struct bes2600_vif static struct bes2600_common *txrx_hw_priv = NULL; +static bool bes2600_is_sta_connected(void) +{ + if (txrx_hw_priv == NULL) + return false; + else + return true; +} + +void bes2600_txrx_opt_timer_restore(void) +{ + if (bes2600_is_sta_connected()) { + mod_timer(&txrx_hw_priv->txrx_opt_timer, jiffies + msecs_to_jiffies(TXRX_OPT_PEROID)); + } +} + #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,15,0) static void txrx_opt_timer_callback(struct timer_list* data) #else @@ -395,7 +451,6 @@ static void txrx_opt_timer_callback(unsigned long data) { bes2600_dbg(BES2600_DBG_TXRX, "####Timer callback function Called time = %lu\n", jiffies); queue_work(txrx_hw_priv->workqueue, &txrx_hw_priv->dynamic_opt_txrx_work); - mod_timer(&txrx_hw_priv->txrx_opt_timer, jiffies + msecs_to_jiffies(TXRX_OPT_PEROID)); } static void txrx_opt_timer_start(struct bes2600_common *hw_priv) @@ -410,12 +465,39 @@ static void txrx_opt_timer_stop(struct bes2600_common *hw_priv) int bes2600_set_txrx_opt_default_param(struct bes2600_common * hw_priv) { - MIB_TXRX_OPT_PARAM g_txrx_param = {2, (PROCTECT_MODE_RTS_CTS | PROCTECT_MODE_RTS_CTS_RETRY), 2002}; + MIB_TXRX_OPT_PARAM g_txrx_param = {2, (PROCTECT_MODE_RTS_CTS | PROCTECT_MODE_RTS_CTS_RETRY), 3000}; struct bes2600_vif *priv = __cw12xx_hwpriv_to_vifpriv(hw_priv, 0); + struct ieee80211_sta *sta = NULL; + if (priv == NULL) return 0; + + /* reset states */ + cur_pwr_tbl = 1; + TXRX_RTS_PROT_CLOSE(cur_rts_thres); + last_rts_set_time = -1; memcpy(&hw_priv->txrx_opt_param, &g_txrx_param, sizeof(MIB_TXRX_OPT_PARAM)); + + /* reset device states */ bes2600_set_txrx_opt_param(hw_priv, priv, &hw_priv->txrx_opt_param); + bes2600_set_rts_threshold(hw_priv->hw, cur_rts_thres); // close rts/cts + bes2600_update_pwr_table(hw_priv, priv, cur_pwr_tbl); // use standard pwr table + + if (priv->join_status == BES2600_JOIN_STATUS_STA) { + sta = ieee80211_find_sta(priv->vif, priv->vif->bss_conf.bssid); + if (sta->deflink.ht_cap.ht_supported && + ((priv->vif->bss_conf.chandef.width == NL80211_CHAN_WIDTH_20 && + sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20) || + (priv->vif->bss_conf.chandef.width == NL80211_CHAN_WIDTH_40 && + sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40))) { + bes2600_info(BES2600_DBG_TXRX, "open short gi tx\n"); + bes2600_enable_tx_shortgi(hw_priv, priv, 1); + } else { + bes2600_info(BES2600_DBG_TXRX, "close short gi tx\n"); + bes2600_enable_tx_shortgi(hw_priv, priv, 0); + } + } + return 0; } @@ -425,14 +507,35 @@ int bes2600_set_txrx_opt_unjoin_param(struct bes2600_common * hw_priv) struct bes2600_vif *priv = __cw12xx_hwpriv_to_vifpriv(hw_priv, 0); if (priv == NULL) return 0; + + /* reset states */ + cur_pwr_tbl = 1; + bes2600_update_pwr_table(hw_priv, priv, cur_pwr_tbl); memcpy(&hw_priv->txrx_opt_param, &g_txrx_param, sizeof(MIB_TXRX_OPT_PARAM)); bes2600_set_txrx_opt_param(hw_priv, priv, &hw_priv->txrx_opt_param); return 0; } -int txrx_opt_timer_init(struct bes2600_common *hw_priv) +void bes2600_txrx_opt_multivif_connected_handler(struct bes2600_common *hw_priv, bool multivif_connected) { + struct bes2600_vif *priv = __cw12xx_hwpriv_to_vifpriv(hw_priv, 0); + + if (multivif_connected) { + bes2600_set_txrx_opt_default_param(hw_priv); + } else { + bes2600_dbg(BES2600_DBG_STA, "%s, rssi:%d\n", __func__, priv->signal); + bes2600_dynamic_opt_rxtx(hw_priv, priv, priv->signal); + mod_timer(&hw_priv->txrx_opt_timer, jiffies + msecs_to_jiffies(TXRX_OPT_PEROID)); + } +} + +int txrx_opt_timer_init(struct bes2600_vif *priv) +{ + struct bes2600_common *hw_priv = cw12xx_vifpriv_to_hwpriv(priv); bes2600_info(BES2600_DBG_TXRX_OPT, "txrx_opt_timer_init:%p", txrx_hw_priv); + if (priv->if_id != 0) + return 0; + if (!txrx_hw_priv) { txrx_hw_priv = hw_priv; bes2600_info(BES2600_DBG_TXRX, "####Timer init hw_priv = %p\n", txrx_hw_priv); @@ -452,16 +555,21 @@ int txrx_opt_timer_init(struct bes2600_common *hw_priv) return 0; } -void txrx_opt_timer_exit(struct bes2600_common *hw_priv) +void txrx_opt_timer_exit(struct bes2600_vif *priv) { + struct bes2600_common *hw_priv = cw12xx_vifpriv_to_hwpriv(priv); bes2600_info(BES2600_DBG_TXRX_OPT, "txrx_opt_timer_exit"); - del_timer_sync(&hw_priv->txrx_opt_timer); - cancel_work_sync(&hw_priv->dynamic_opt_txrx_work); - bes2600_pwr_unregister_en_lp_cb(hw_priv, txrx_opt_timer_stop); - bes2600_pwr_unregister_exit_lp_cb(hw_priv, txrx_opt_timer_start); - txrx_hw_priv = NULL; - bes2600_set_txrx_opt_unjoin_param(hw_priv); + if (priv->if_id == 0) { + del_timer_sync(&hw_priv->txrx_opt_timer); + cancel_work_sync(&hw_priv->dynamic_opt_txrx_work); + bes2600_pwr_unregister_en_lp_cb(hw_priv, txrx_opt_timer_stop); + bes2600_pwr_unregister_exit_lp_cb(hw_priv, txrx_opt_timer_start); + txrx_hw_priv = NULL; + bes2600_set_txrx_opt_unjoin_param(hw_priv); + } else if (priv->if_id == 1) { + bes2600_txrx_opt_timer_restore(); + } } diff --git a/drivers/staging/bes2600/txrx_opt.h b/drivers/staging/bes2600/txrx_opt.h index 582ff7fb5221..93c22f4bc5e8 100644 --- a/drivers/staging/bes2600/txrx_opt.h +++ b/drivers/staging/bes2600/txrx_opt.h @@ -19,13 +19,20 @@ #include /* open it for enhance wifi throughput */ #define BES2600_TX_RX_OPT 1 + +/* Threshold for powrt table switch */ +#define BES2600_TX_RSSI_LOW -65 +#define BES2600_TX_RSSI_HIGH -60 + void bes2600_add_tx_ac_delta_time(int ac, uint32_t del_time); void bes2600_add_tx_delta_time(uint32_t tx_time); void bes2600_rx_status(struct bes2600_vif *priv, struct sk_buff *skb); void bes2600_tx_status(struct bes2600_vif *priv, struct sk_buff *skb); void bes2600_dynamic_opt_rxtx(struct bes2600_common *hw_priv,struct bes2600_vif *priv, int rssi); -int txrx_opt_timer_init(struct bes2600_common *hw_priv); -int txrx_opt_timer_exit(struct bes2600_common *hw_priv); +void bes2600_txrx_opt_multivif_connected_handler(struct bes2600_common *hw_priv, bool multivif_connected); +void bes2600_txrx_opt_timer_restore(void); +int txrx_opt_timer_init(struct bes2600_vif *priv); +void txrx_opt_timer_exit(struct bes2600_vif *priv); #endif diff --git a/drivers/staging/bes2600/wifi_testmode_cmd.c b/drivers/staging/bes2600/wifi_testmode_cmd.c index 3b3583a6db3d..4022579444be 100644 --- a/drivers/staging/bes2600/wifi_testmode_cmd.c +++ b/drivers/staging/bes2600/wifi_testmode_cmd.c @@ -110,6 +110,7 @@ int bes2600_vendor_rf_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u8 case VENDOR_RF_NOSIGNALING_CMD: case VENDOR_RF_SAVE_FREQOFFSET_CMD: case VENDOR_RF_SAVE_POWERLEVEL_CMD: + case VENDOR_RF_GET_CALI_FROM_EFUSE: sema_init(&hw_priv->vendor_rf_cmd_replay_sema, 0); ret = wsm_vendor_rf_cmd(hw_priv, if_id, vendor_rf_cmd); diff --git a/drivers/staging/bes2600/wsm.c b/drivers/staging/bes2600/wsm.c index 8ba5ce0a0bb3..3dc8642129ff 100644 --- a/drivers/staging/bes2600/wsm.c +++ b/drivers/staging/bes2600/wsm.c @@ -314,6 +314,7 @@ int wsm_vendor_rf_test_indication(struct bes2600_common *hw_priv, struct wsm_buf break; case VENDOR_RF_SIGNALING_CMD: case VENDOR_RF_NOSIGNALING_CMD: + case VENDOR_RF_GET_CALI_FROM_EFUSE: bes2600_rf_cmd_msg_assembly(cmd_type, buf->data, wsm_len - sizeof(struct wsm_mcu_hdr)); break; default: @@ -1213,8 +1214,7 @@ int wsm_cpu_usage_cmd(struct bes2600_common *hw_priv) return -ENOMEM; } -#ifdef PLAT_ALLWINNER_R329 -int wsm_save_factory_txt_to_flash(struct bes2600_common *hw_priv, const u8 *data, int if_id) +int wsm_save_factory_txt_to_mcu(struct bes2600_common *hw_priv, const u8 *data, int if_id, enum bes2600_rf_cmd_type cmd_type) { int ret, i; const struct factory_t *factory_cali = (const struct factory_t *)data; @@ -1223,8 +1223,7 @@ int wsm_save_factory_txt_to_flash(struct bes2600_common *hw_priv, const u8 *data wsm_cmd_lock(hw_priv); /* cmd type */ - WSM_PUT32(buf, BES2600_RF_CMD_CALI_TXT_TO_FLASH); - + WSM_PUT32(buf, cmd_type); WSM_PUT32(buf, factory_cali->data.iQ_offset); WSM_PUT16(buf, factory_cali->data.freq_cal); @@ -1253,10 +1252,7 @@ int wsm_save_factory_txt_to_flash(struct bes2600_common *hw_priv, const u8 *data nomem: wsm_cmd_unlock(hw_priv); return -ENOMEM; - } -#endif - /* ******************************************************************** */ #ifdef MCAST_FWDING /* 3.66 */ @@ -1477,6 +1473,7 @@ static int wsm_receive_indication(struct bes2600_common *hw_priv, struct sk_buff **skb_p) { struct bes2600_vif *priv; + s8 pkt_signal = 0; hw_priv->rx_timestamp = jiffies; if (hw_priv->wsm_cbc.rx) { @@ -1542,8 +1539,23 @@ static int wsm_receive_indication(struct bes2600_common *hw_priv, /* If no RSSI subscription has been made, * convert RCPI to RSSI here */ - if (!priv->cqm_use_rssi) + if (!priv->cqm_use_rssi) { + pkt_signal = rx.rcpiRssi / 2 - 110; rx.rcpiRssi = rx.rcpiRssi / 2 - 110; + } + + if(ieee80211_is_data(hdr->frame_control)) { + if (priv->signal == 0) { + priv->signal = pkt_signal; + priv->signal_mul = pkt_signal * 100; + } else { + priv->signal_mul = priv->signal_mul * 80 / 100 + pkt_signal * 20; + priv->signal = priv->signal_mul / 100; + } + + bes2600_dbg(BES2600_DBG_TXRX, "pkt signal:%d\n", priv->signal); + } + fctl = *(__le16 *)buf->data; hdr_len = buf->data - buf->begin; @@ -1579,7 +1591,7 @@ static int wsm_receive_indication(struct bes2600_common *hw_priv, (*skb_p)->len, has_mmie, priv->pmf); if (has_mmie ^ priv->pmf) ignore = true; - } else if (ether_addr_equal(hdr->addr1, hw_priv->addresses[rx.if_id].addr)) { + } else if (ether_addr_equal(hdr->addr1, priv->vif->addr)) { bool has_protected = ieee80211_has_protected(fctl); bes2600_info(BES2600_DBG_WSM, "[WSM] RX unicast deauth: protected=%d, pmf=%d, connect_in_process=%d\n", has_protected, priv->pmf, atomic_read(&priv->connect_in_process)); @@ -1600,10 +1612,19 @@ static int wsm_receive_indication(struct bes2600_common *hw_priv, bes2600_info(BES2600_DBG_WSM, "[WSM] Issue unjoin command (RX).\n"); wsm_lock_tx_async(hw_priv); if (queue_work(hw_priv->workqueue, - &priv->unjoin_work) <= 0) + &priv->unjoin_work) <= 0) { wsm_unlock_tx(hw_priv); + } +#ifdef CONFIG_PM + else if(bes2600_suspend_status_get(hw_priv)) { + bes2600_pending_unjoin_set(hw_priv, priv->if_id); + } +#endif + if (bes2600_chrdev_wakeup_by_event_get() == WAKEUP_EVENT_PEER_DETACH) + bes2600_chrdev_wifi_update_wakeup_reason(WAKEUP_REASON_WIFI_DEAUTH_DISASSOC, 0); } } + bes2600_chrdev_wakeup_by_event_set(WAKEUP_EVENT_NONE); } hw_priv->wsm_cbc.rx(priv, &rx, skb_p); if (*skb_p) @@ -2014,7 +2035,7 @@ bool wsm_vif_flush_tx(struct bes2600_vif *priv) { struct bes2600_common *hw_priv = priv->hw_priv; unsigned long timestamp = jiffies; - long timeout; + unsigned long timeout; int i; int if_id = priv->if_id; @@ -2045,11 +2066,17 @@ bool wsm_vif_flush_tx(struct bes2600_vif *priv) if (!hw_priv->hw_bufs_used_vif[if_id]) return true; - timeout = timestamp + WSM_CMD_LAST_CHANCE_TIMEOUT - jiffies; - if (timeout < 0 || wait_event_timeout(hw_priv->bh_evt_wq, + /* calculate wait time */ + timeout = timestamp + WSM_CMD_LAST_CHANCE_TIMEOUT; + if (timeout >= jiffies) + timeout -= jiffies; + else + timeout += (ULONG_MAX - jiffies); + + /* wait packets on vif to be flushed */ + if (wait_event_timeout(hw_priv->bh_evt_wq, !hw_priv->hw_bufs_used_vif[if_id], timeout) <= 0) { - /* Hmmm... Not good. Frame had stuck in firmware. */ bes2600_chrdev_wifi_force_close(hw_priv, true); } @@ -2202,9 +2229,7 @@ int wsm_handle_rx(struct bes2600_common *hw_priv, int id, if (IS_DRIVER_TO_MCU_CMD(id)) ind_confirm_label = __le32_to_cpu(((struct wsm_mcu_hdr *)wsm)->handle_label); - if (id == 0x0C30) { - ret = wsm_bt_ts_request(hw_priv, &wsm_buf); - } else if (id == 0x404) { + if (id == 0x404) { ret = wsm_tx_confirm(hw_priv, &wsm_buf, interface_link_id); #ifdef MCAST_FWDING #if 1 @@ -2312,10 +2337,10 @@ int wsm_handle_rx(struct bes2600_common *hw_priv, int id, case 0x0C25: ret = wsm_vendor_rf_cmd_confirm(hw_priv, wsm_arg, &wsm_buf); break; +#endif /* CONFIG_BES2600_TESTMODE */ case 0x0C27: ret = wsm_driver_rf_cmd_confirm(hw_priv, wsm_arg, &wsm_buf); break; -#endif /* CONFIG_BES2600_TESTMODE */ #ifdef BES_UNIFIED_PM case 0x0424: /* wifi sleep disable */ break; @@ -2408,6 +2433,9 @@ int wsm_handle_rx(struct bes2600_common *hw_priv, int id, ret = wsm_vendor_rf_test_indication(hw_priv, &wsm_buf); break; #endif /* CONFIG_BES2600_TESTMODE */ + case 0x0C30: + ret = wsm_bt_ts_request(hw_priv, &wsm_buf); + break; default: break; } @@ -2712,7 +2740,7 @@ static int bes2600_get_prio_queue(struct bes2600_vif *priv, edca = &priv->edca.params[i]; score = ((edca->aifns + edca->cwMin) << 16) + (edca->cwMax - edca->cwMin) * - (get_random_int() & 0xFFFF); + (get_random_long() & 0xFFFF); if (score < best && (winner < 0 || i != 3)) { best = score; winner = i; @@ -3127,6 +3155,8 @@ static inline int get_interface_id_scanning(struct bes2600_common *hw_priv) { if (hw_priv->scan.req) return hw_priv->scan.if_id; + else if (hw_priv->scan.direct_probe == 1) + return hw_priv->scan.if_id; else return -1; } diff --git a/drivers/staging/bes2600/wsm.h b/drivers/staging/bes2600/wsm.h index 5bb5bace57ff..8e229a5428e1 100644 --- a/drivers/staging/bes2600/wsm.h +++ b/drivers/staging/bes2600/wsm.h @@ -379,6 +379,9 @@ struct bes2600_vif; #define WSM_PS_ERROR_AP_SENT_UNICAST_IN_DOZE 3 #define WSM_PS_ERROR_AP_NO_DATA_AFTER_TIM 4 +/* eth filter extended flags */ +#define WSM_ETH_FILTER_EXT_DISABLE_IPV6_MATCH BIT(0) + /* WSM events */ /* Error */ #define WSM_EVENT_ERROR (0) @@ -570,6 +573,7 @@ struct bes2600_vif; #define WSM_MIB_ID_EXT_TCP_KEEP_ALIVE_PERIOD (WSM_MIB_ID_EXT_BASE + 2) /* Mib to set tcp keep alive period */ #define WSM_MIB_ID_EXT_TX_SHORT_GI_ENABLED (WSM_MIB_ID_EXT_BASE + 3) /* Mib to set tx short enabled */ #define WSM_MIB_ID_EXT_TXRX_OPT_PARAM (WSM_MIB_ID_EXT_BASE + 4) /* Mib to set tx/rx opt param to enhance wifi throuhput */ +#define WSM_MIB_ID_EXT_PWR_TBL_UPDATE (WSM_MIB_ID_EXT_BASE + 5) /* Mib to update power table */ #ifdef IPV6_FILTERING @@ -591,6 +595,7 @@ struct bes2600_vif; #ifdef IPV6_FILTERING #define WSM_FRAME_TYPE_NA (7) +#define WSM_MAX_IPV6_ADDR_FILTER_ELTS (8) #endif /*IPV6_FILTERING*/ #define WSM_FRAME_GREENFIELD (0x80) /* See 4.11 */ @@ -653,6 +658,9 @@ struct bes2600_vif; #define WSM_FILTER_PORT_TYPE_DST (0) #define WSM_FILTER_PORT_TYPE_SRC (1) +#define WSM_IP_DATA_FRAME_ADDRMODE_SRC (0x01) +#define WSM_IP_DATA_FRAME_ADDRMODE_DEST (0x02) +#define WSM_IP_DATA_FRAME_ADDRMODE_TCPACK (0x03) struct wsm_hdr { @@ -1538,34 +1546,41 @@ static inline int wsm_set_beacon_filter_table(struct bes2600_common *hw_priv, struct wsm_beacon_filter_table *ft, int if_id) { + static __le32 numOfIEs; size_t size = __le32_to_cpu(ft->numOfIEs) * sizeof(struct wsm_beacon_filter_table_entry) + sizeof(__le32); + if (numOfIEs == ft->numOfIEs && numOfIEs == 0) { + return 0; + } + numOfIEs = ft->numOfIEs; return wsm_write_mib(hw_priv, WSM_MIB_ID_BEACON_FILTER_TABLE, ft, size, if_id); } #define WSM_BEACON_FILTER_ENABLE BIT(0) /* Enable/disable beacon filtering */ #define WSM_BEACON_FILTER_AUTO_ERP BIT(1) /* If 1 FW will handle ERP IE changes internally */ +#define WSM_BEACON_FILTER_AUTO_HT BIT(2) /* If 1 FW will handle HT OP IE changes internally */ struct wsm_beacon_filter_control { - int enabled; - int bcn_count; + __le32 enabled; + __le32 bcn_count; }; static inline int wsm_beacon_filter_control(struct bes2600_common *hw_priv, struct wsm_beacon_filter_control *arg, int if_id) { - struct { - __le32 enabled; - __le32 bcn_count; - } val; - val.enabled = __cpu_to_le32(arg->enabled); - val.bcn_count = __cpu_to_le32(arg->bcn_count); - return wsm_write_mib(hw_priv, WSM_MIB_ID_BEACON_FILTER_ENABLE, &val, - sizeof(val), if_id); + static __le32 enabled, bcn_count; + + if (enabled == arg->enabled && bcn_count == arg->bcn_count) { + return 0; + } + enabled = arg->enabled; + bcn_count = arg->bcn_count; + return wsm_write_mib(hw_priv, WSM_MIB_ID_BEACON_FILTER_ENABLE, arg, + sizeof(struct wsm_beacon_filter_control), if_id); } enum wsm_power_mode { @@ -1734,7 +1749,8 @@ static inline int wsm_set_tx_rate_retry_policy(struct bes2600_common *hw_priv, /* 4.32 SetEtherTypeDataFrameFilter */ struct wsm_ether_type_filter_hdr { u8 nrFilters; /* Up to WSM_MAX_FILTER_ELEMENTS */ - u8 reserved[3]; + u8 extFlags; + u8 reserved[2]; } __packed; struct wsm_ether_type_filter { @@ -1932,13 +1948,28 @@ struct wsm_ip6_addr_info { u8 ipv6[16]; }; -/* IPV6 Addr Filter */ -struct wsm_ipv6_filter { +struct wsm_ipv6_filter_header { u8 numfilter; u8 action_mode; u8 Reserved[2]; - struct wsm_ip6_addr_info ipv6filter[0]; +}; + +/* IPV6 Addr Filter */ +struct wsm_ipv6_filter { + struct wsm_ipv6_filter_header hdr; + struct wsm_ip6_addr_info ipv6filter[WSM_MAX_IPV6_ADDR_FILTER_ELTS]; } __packed; + +static inline int wsm_set_ipv6_filter(struct bes2600_common *hw_priv, + struct wsm_ipv6_filter_header *arg, + int if_id) +{ + size_t size = sizeof(struct wsm_ipv6_filter_header) + + arg->numfilter * sizeof(struct wsm_ip6_addr_info); + + return wsm_write_mib(hw_priv, WSM_MIB_IP_IPV6_ADDR_FILTER, + arg, size, if_id); +} #endif /*IPV6_FILTERING*/ struct wsm_ip4_addr_info { @@ -2157,6 +2188,7 @@ enum bes2600_rf_cmd_type { BES2600_RF_CMD_CH_INFO = 1, BES2600_RF_CMD_CPU_USAGE = 2, BES2600_RF_CMD_WIFI_STATUS = 3, + BES2600_RF_CMD_CALI_TXT_TO_EFUSE = 4, /* add new here */ BES2600_RF_CMD_MAX, @@ -2204,8 +2236,7 @@ int wsm_cpu_usage_cmd(struct bes2600_common *hw_priv); int wsm_wifi_status_cmd(struct bes2600_common *hw_priv, uint32_t status); -#ifdef PLAT_ALLWINNER_R329 -int wsm_save_factory_txt_to_flash(struct bes2600_common *hw_priv, const u8 *data, int if_id); +#if defined(PLAT_ALLWINNER_R329) || defined(STANDARD_FACTORY_EFUSE_FLAG) +int wsm_save_factory_txt_to_mcu(struct bes2600_common *hw_priv, const u8 *data, int if_id, enum bes2600_rf_cmd_type cmd_type); #endif - #endif /* BES2600_HWIO_H_INCLUDED */ -- 2.34.1