diff --git a/mxm_wifiex/wlan_src/Makefile b/mxm_wifiex/wlan_src/Makefile index 72cf963..c3742f5 100644 --- a/mxm_wifiex/wlan_src/Makefile +++ b/mxm_wifiex/wlan_src/Makefile @@ -45,7 +45,7 @@ CONFIG_PCIE8997=y CONFIG_SD8987=y CONFIG_SD9097=n CONFIG_SD9177=n -CONFIG_SD8801=n +CONFIG_SD8801=y CONFIG_USB8801=n CONFIG_USB9097=n CONFIG_PCIE9097=n @@ -130,6 +130,8 @@ CONFIG_IMX_SUPPORT=y ifeq ($(CONFIG_IMX_SUPPORT),y) ccflags-y += -DIMX_SUPPORT endif +KERNELDIR ?= /usr/src/arm/linux_5_10_y_kernel/linux-nxp +CROSS_COMPILE ?= /opt/fsl-imx-internal-xwayland/5.10-gatesgarth/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/aarch64-poky-linux- LD += -S diff --git a/mxm_wifiex/wlan_src/README_MLAN b/mxm_wifiex/wlan_src/README_MLAN index 0d3ccf6..03860b6 100644 --- a/mxm_wifiex/wlan_src/README_MLAN +++ b/mxm_wifiex/wlan_src/README_MLAN @@ -9,7 +9,7 @@ Goto source code directory wlan_src/. make [clean] build The driver and utility binaries can be found in ../bin_xxxx directory. - The driver code supports Linux kernel from 2.6.32 to 5.8.0. + The driver code supports Linux kernel from 2.6.32 to 5.13.4. 2) FOR DRIVER INSTALL @@ -49,7 +49,10 @@ dev_cap_mask= mac_addr=xx:xx:xx:xx:xx:xx auto_ds=0|1|2 + ext_scan=0|1|2 + net_rx=0|1 ps_mode=0|1|2 + sched_scan=0|1 max_tx_buf=2048|4096|8192 pm_keep_power=1|0 shutdown_hs=1|0 @@ -151,10 +154,10 @@ num_rx_pkts_err = carrier "on" | "off" tx queue "stopped" | "started" - tkip_mic_failures = 0 // Only for uAP + tkip_mic_failures = 0 // Only for uAP (use of WEP/TKIP is not recommended anymore) ccmp_decrypt_errors = 0 // Only for uAP - wep_undecryptable_count = 0 // Only for uAP - wep_icv_error_count = 0 // Only for uAP + wep_undecryptable_count = 0 // Only for uAP (use of WEP/TKIP is not recommended anymore) + wep_icv_error_count = 0 // Only for uAP (use of WEP/TKIP is not recommended anymore) decrypt_failure_count = 0 // Only for uAP mcast_tx_count = 0 // Only for uAP failed_count = 0 // Only for uAP @@ -168,7 +171,7 @@ mcast_rx_frame_count = 0 // Only for uAP fcs_error_count = 0 // Only for uAP tx_frame_count = 0 // Only for uAP - rsna_tkip_cm_invoked = 0 // Only for uAP + rsna_tkip_cm_invoked = 0 // Only for uAP (use of WEP/TKIP is not recommended anymore) rsna_4way_hshk_failures = 0 // Only for uAP The following debug info are provided in /proc/net/mwlan/adapterX/mlanY|uapY|wfdY/debug, @@ -259,6 +262,10 @@ Examples: echo "debug_dump" > /proc/mwlan/adapterX/config # dump driver internal debug status. + To obtain fw dump or driver dump, use command: + cat /proc/mwlan/adapter0/drv_dump > file_drv_dump #save the drv dump to file_drv_dump + cat /proc/mwlan/adapter0/fw_dump > file_fw_dump #save the fw dump to file_fw_dump + cat /proc/mwlan/adapter1/drv_dump > file_drv_dump_2 #save the adapter1 drv dump to file_drv_dump_2 Use dmesg or cat /var/log/debug to check driver debug messages. @@ -538,7 +545,7 @@ getlog dot11TransmittedFrameCount Increments for each successfully transmitted MSDU - dot11WeplcvErrCnt Increment when WEP decryption error for key index 0.3 + dot11WeplcvErrCnt Increment when WEP (use of WEP/TKIP is not recommended anymore)decryption error for key index 0.3 beaconReceivedCnt Increments when received beacon @@ -581,9 +588,9 @@ getlog dot11RSNAStatsRobustMgmtCCMPReplays Increments when a robust management frame discarded by CCMP replay error - dot11RSNAStatsTKIPICVErrors Increments when a MPDU discarded by TKIP ICV error + dot11RSNAStatsTKIPICVErrors Increments when a MPDU discarded by TKIP ICV error //(use of WEP/TKIP is not recommended anymore) - dot11RSNAStatsTKIPReplays Increments when a MPDU discarded by TKIP replay error + dot11RSNAStatsTKIPReplays Increments when a MPDU discarded by TKIP replay error //(use of WEP/TKIP is not recommended anymore) dot11RSNAStatsCCMPDecryptErrors Increments when a MPDU discarded by CCMP decryption error diff --git a/mxm_wifiex/wlan_src/mapp/mlanconfig/config/ed_mac_ctrl_V1_8801.conf b/mxm_wifiex/wlan_src/mapp/mlanconfig/config/ed_mac_ctrl_V1_8801.conf new file mode 100644 index 0000000..c673547 --- /dev/null +++ b/mxm_wifiex/wlan_src/mapp/mlanconfig/config/ed_mac_ctrl_V1_8801.conf @@ -0,0 +1,15 @@ +# File : ed_mac_ctrl_V1_8801.conf +# +# ./mlanutl mlan0 hostcmd config/ed_mac_ctrl_V1_8801.conf ed_mac_ctrl +# +# +## Set Energy Detect Threshold for EU Adaptivity test + +ed_mac_ctrl={ + CmdCode=0x0124 #Command code, DO NOT change this line + Enable:2=0x1 # 0 - disable EU adaptivity + # 1 - enable EU adaptivity + + Offset:2=0x1b # 0 - Default Energy Detect threshold + #offset value range: 0x80 to 0x7F +} diff --git a/mxm_wifiex/wlan_src/mapp/mlanutl/mlanutl.c b/mxm_wifiex/wlan_src/mapp/mlanutl/mlanutl.c index 8dad9fd..8cee774 100644 --- a/mxm_wifiex/wlan_src/mapp/mlanutl/mlanutl.c +++ b/mxm_wifiex/wlan_src/mapp/mlanutl/mlanutl.c @@ -1588,7 +1588,11 @@ static int process_getlog(int argc, char *argv[]) "gOwnrshpCtlErrCnt %u\n" "gOwnrshpBcnErrCnt %u\n" "gOwnrshpMgtErrCnt %u\n" - "gOwnrshpDatErrCnt %u\n", + "gOwnrshpDatErrCnt %u\n" + "bigtk_mmeGoodCnt %u\n" + "bigtk_replayErrCnt %u\n" + "bigtk_micErrCnt %u\n" + "bigtk_mmeNotFoundCnt %u\n", stats->rx_stuck_issue_cnt[0], stats->rx_stuck_issue_cnt[1], stats->rx_stuck_recovery_cnt, stats->rx_stuck_tsf[0], @@ -1601,7 +1605,9 @@ static int process_getlog(int argc, char *argv[]) stats->rx_Isr2_NotDone_Cnt, stats->gdma_abort_cnt, stats->g_reset_rx_mac_cnt, stats->dwCtlErrCnt, stats->dwBcnErrCnt, stats->dwMgtErrCnt, - stats->dwDatErrCnt); + stats->dwDatErrCnt, stats->bigtk_mmeGoodCnt, + stats->bigtk_replayErrCnt, stats->bigtk_micErrCnt, + stats->bigtk_mmeNotFoundCnt); } if (cmd->used_len == sizeof(struct eth_priv_get_log)) { diff --git a/mxm_wifiex/wlan_src/mapp/mlanutl/mlanutl.h b/mxm_wifiex/wlan_src/mapp/mlanutl/mlanutl.h index c949d30..1b70de6 100644 --- a/mxm_wifiex/wlan_src/mapp/mlanutl/mlanutl.h +++ b/mxm_wifiex/wlan_src/mapp/mlanutl/mlanutl.h @@ -374,6 +374,14 @@ struct eth_priv_get_log { t_u32 dwMgtErrCnt; /*Control Ownership error count*/ t_u32 dwDatErrCnt; + /*BIGTK MME good count*/ + t_u32 bigtk_mmeGoodCnt; + /*BIGTK Replay error count*/ + t_u32 bigtk_replayErrCnt; + /*BIGTK MIC error count*/ + t_u32 bigtk_micErrCnt; + /*BIGTK MME not included count*/ + t_u32 bigtk_mmeNotFoundCnt; }; /** MLAN MAC Address Length */ diff --git a/mxm_wifiex/wlan_src/mlan/mlan_11ac.c b/mxm_wifiex/wlan_src/mlan/mlan_11ac.c index 07d685d..0cbc1b3 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_11ac.c +++ b/mxm_wifiex/wlan_src/mlan/mlan_11ac.c @@ -29,8 +29,6 @@ #include "mlan_11n.h" #include "mlan_11ac.h" -#define NO_NSS_SUPPORT 0x3 - /******************************************************** Local Variables ********************************************************/ @@ -197,7 +195,6 @@ static void wlan_fill_cap_info(mlan_private *priv, VHT_capa_t *vht_cap, t_u8 bands) { t_u32 usr_dot_11ac_dev_cap; - ENTER(); if (bands & BAND_A) @@ -207,6 +204,7 @@ static void wlan_fill_cap_info(mlan_private *priv, VHT_capa_t *vht_cap, vht_cap->vht_cap_info = usr_dot_11ac_dev_cap; + RESET_VHTCAP_MAXMPDULEN(vht_cap->vht_cap_info); LEAVE(); } diff --git a/mxm_wifiex/wlan_src/mlan/mlan_11ax.c b/mxm_wifiex/wlan_src/mlan/mlan_11ax.c index e391b2b..6a94fcc 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_11ax.c +++ b/mxm_wifiex/wlan_src/mlan/mlan_11ax.c @@ -163,6 +163,10 @@ t_u16 wlan_fill_he_cap_tlv(mlan_private *pmpriv, t_u8 band, t_u16 rx_nss = 0, tx_nss = 0; #endif MrvlIEtypes_He_cap_t *phecap = MNULL; + t_u8 nss = 0; + t_u16 cfg_value = 0; + t_u16 hw_value = 0; + MrvlIEtypes_He_cap_t *phw_hecap = MNULL; if (!phe_cap) { LEAVE(); @@ -173,11 +177,13 @@ t_u16 wlan_fill_he_cap_tlv(mlan_private *pmpriv, t_u8 band, pmpriv->user_hecap_len, sizeof(MrvlIEtypes_He_cap_t)); len = pmpriv->user_hecap_len; + phw_hecap = (MrvlIEtypes_He_cap_t *)pmadapter->hw_he_cap; } else { memcpy_ext(pmadapter, (t_u8 *)phe_cap, pmpriv->user_2g_he_cap, pmpriv->user_2g_hecap_len, sizeof(MrvlIEtypes_He_cap_t)); len = pmpriv->user_2g_hecap_len; + phw_hecap = (MrvlIEtypes_He_cap_t *)pmadapter->hw_2g_he_cap; } phe_cap->type = wlan_cpu_to_le16(phe_cap->type); phe_cap->len = wlan_cpu_to_le16(phe_cap->len); @@ -199,18 +205,39 @@ t_u16 wlan_fill_he_cap_tlv(mlan_private *pmpriv, t_u8 band, } #endif phecap = (MrvlIEtypes_He_cap_t *)phe_cap; - phecap->rx_mcs_80 = wlan_cpu_to_le16(0xfffe); - phecap->tx_mcs_80 = wlan_cpu_to_le16(0xfffe); + for (nss = 1; nss <= 8; nss++) { + cfg_value = GET_HE_NSSMCS(phecap->rx_mcs_80, nss); + hw_value = GET_HE_NSSMCS(phw_hecap->rx_mcs_80, nss); #if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \ defined(PCIE9097) || defined(SD9097) || defined(USB9097) - if (IS_CARD9098(pmpriv->adapter->card_type) || - IS_CARD9097(pmpriv->adapter->card_type)) { - if (rx_nss == 2) - phecap->rx_mcs_80 = wlan_cpu_to_le16(0xfffa); - if (tx_nss == 2) - phecap->tx_mcs_80 = wlan_cpu_to_le16(0xfffa); - } + if ((rx_nss != 0) && (nss > rx_nss)) + cfg_value = NO_NSS_SUPPORT; #endif + if ((hw_value == NO_NSS_SUPPORT) || + (cfg_value == NO_NSS_SUPPORT)) + SET_HE_NSSMCS(phecap->rx_mcs_80, nss, NO_NSS_SUPPORT); + else + SET_HE_NSSMCS(phecap->rx_mcs_80, nss, + MIN(cfg_value, hw_value)); + } + for (nss = 1; nss <= 8; nss++) { + cfg_value = GET_HE_NSSMCS(phecap->tx_mcs_80, nss); + hw_value = GET_HE_NSSMCS(phw_hecap->tx_mcs_80, nss); +#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \ + defined(PCIE9097) || defined(SD9097) || defined(USB9097) + if ((tx_nss != 0) && (nss > tx_nss)) + cfg_value = NO_NSS_SUPPORT; +#endif + if ((hw_value == NO_NSS_SUPPORT) || + (cfg_value == NO_NSS_SUPPORT)) + SET_HE_NSSMCS(phecap->tx_mcs_80, nss, NO_NSS_SUPPORT); + else + SET_HE_NSSMCS(phecap->tx_mcs_80, nss, + MIN(cfg_value, hw_value)); + } + PRINTM(MCMND, "Set: HE rx mcs set 0x%08x tx mcs set 0x%08x\n", + phecap->rx_mcs_80, phecap->tx_mcs_80); + DBG_HEXDUMP(MCMD_D, "fill_11ax_tlv", (t_u8 *)phecap, len); LEAVE(); return len; @@ -236,6 +263,10 @@ int wlan_cmd_append_11ax_tlv(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc, defined(PCIE9097) || defined(SD9097) || defined(USB9097) t_u16 rx_nss = 0, tx_nss = 0; #endif + t_u8 nss = 0; + t_u16 cfg_value = 0; + t_u16 hw_value = 0; + MrvlIEtypes_He_cap_t *phw_hecap = MNULL; ENTER(); @@ -260,12 +291,14 @@ int wlan_cmd_append_11ax_tlv(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc, pmpriv->user_hecap_len, pmpriv->user_hecap_len); *ppbuffer += pmpriv->user_hecap_len; len = pmpriv->user_hecap_len; + phw_hecap = (MrvlIEtypes_He_cap_t *)pmadapter->hw_he_cap; } else { memcpy_ext(pmadapter, *ppbuffer, pmpriv->user_2g_he_cap, pmpriv->user_2g_hecap_len, pmpriv->user_2g_hecap_len); *ppbuffer += pmpriv->user_2g_hecap_len; len = pmpriv->user_2g_hecap_len; + phw_hecap = (MrvlIEtypes_He_cap_t *)pmadapter->hw_2g_he_cap; } phecap->type = wlan_cpu_to_le16(phecap->type); phecap->len = wlan_cpu_to_le16(phecap->len); @@ -289,18 +322,38 @@ int wlan_cmd_append_11ax_tlv(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc, rx_nss = tx_nss = 1; } #endif - phecap->rx_mcs_80 = wlan_cpu_to_le16(0xfffe); - phecap->tx_mcs_80 = wlan_cpu_to_le16(0xfffe); + for (nss = 1; nss <= 8; nss++) { + cfg_value = GET_HE_NSSMCS(phecap->rx_mcs_80, nss); + hw_value = GET_HE_NSSMCS(phw_hecap->rx_mcs_80, nss); #if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \ defined(PCIE9097) || defined(SD9097) || defined(USB9097) - if (IS_CARD9098(pmpriv->adapter->card_type) || - IS_CARD9097(pmpriv->adapter->card_type)) { - if (rx_nss == 2) - phecap->rx_mcs_80 = wlan_cpu_to_le16(0xfffa); - if (tx_nss == 2) - phecap->tx_mcs_80 = wlan_cpu_to_le16(0xfffa); - } + if ((rx_nss != 0) && (nss > rx_nss)) + cfg_value = NO_NSS_SUPPORT; #endif + if ((hw_value == NO_NSS_SUPPORT) || + (cfg_value == NO_NSS_SUPPORT)) + SET_HE_NSSMCS(phecap->rx_mcs_80, nss, NO_NSS_SUPPORT); + else + SET_HE_NSSMCS(phecap->rx_mcs_80, nss, + MIN(cfg_value, hw_value)); + } + for (nss = 1; nss <= 8; nss++) { + cfg_value = GET_HE_NSSMCS(phecap->tx_mcs_80, nss); + hw_value = GET_HE_NSSMCS(phw_hecap->tx_mcs_80, nss); +#if defined(PCIE9098) || defined(SD9098) || defined(USB9098) || \ + defined(PCIE9097) || defined(SD9097) || defined(USB9097) + if ((tx_nss != 0) && (nss > tx_nss)) + cfg_value = NO_NSS_SUPPORT; +#endif + if ((hw_value == NO_NSS_SUPPORT) || + (cfg_value == NO_NSS_SUPPORT)) + SET_HE_NSSMCS(phecap->tx_mcs_80, nss, NO_NSS_SUPPORT); + else + SET_HE_NSSMCS(phecap->tx_mcs_80, nss, + MIN(cfg_value, hw_value)); + } + PRINTM(MCMND, "Set: HE rx mcs set 0x%08x tx mcs set 0x%08x\n", + phecap->rx_mcs_80, phecap->tx_mcs_80); if (!bw_80p80) { /** reset BIT3 and BIT4 channel width ,not support 80 + 80*/ /** not support 160Mhz now, if support,not reset bit3 */ diff --git a/mxm_wifiex/wlan_src/mlan/mlan_11ax.h b/mxm_wifiex/wlan_src/mlan/mlan_11ax.h index edc1fd0..8a8c3f9 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_11ax.h +++ b/mxm_wifiex/wlan_src/mlan/mlan_11ax.h @@ -28,6 +28,16 @@ /** device support 2.4G 242 tone RUs */ #define AX_2G_20MHZ_SUPPORT MBIT(5) +/* + * 0 indicates support for HE-MCS 0-7 for n spatial streams + * 1 indicates support for HE-MCS 0-9 for n spatial streams + * 2 indicates support for HE-MCS 0-11 for n spatial streams + * 3 indicates that n spatial streams is not supported for HE PPDUs + */ +#define GET_HE_NSSMCS(MCSMapSet, nss) ((MCSMapSet >> (2 * (nss - 1))) & 0x3) +#define SET_HE_NSSMCS(MCSMapSet, nss, value) \ + (MCSMapSet |= (value & 0x3) << (2 * (nss - 1))) + t_u8 wlan_check_11ax_twt_supported(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc); mlan_status wlan_11ax_ioctl_twtcfg(pmlan_adapter pmadapter, diff --git a/mxm_wifiex/wlan_src/mlan/mlan_11h.c b/mxm_wifiex/wlan_src/mlan/mlan_11h.c index 0781cc0..bf68c99 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_11h.c +++ b/mxm_wifiex/wlan_src/mlan/mlan_11h.c @@ -1306,6 +1306,8 @@ wlan_11h_prepare_custom_ie_chansw(mlan_adapter *pmadapter, pvhttpcEnv_ie->local_max_tp_20mhz = 0xff; pvhttpcEnv_ie->local_max_tp_40mhz = 0xff; pvhttpcEnv_ie->local_max_tp_80mhz = 0xff; + pvhttpcEnv_ie->local_max_tp_160mhz_80_80mhz = + 0xff; pChanSwWrap_ie->len += sizeof(IEEEtypes_VhtTpcEnvelope_t); diff --git a/mxm_wifiex/wlan_src/mlan/mlan_11n_aggr.c b/mxm_wifiex/wlan_src/mlan/mlan_11n_aggr.c index 7538899..af501f0 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_11n_aggr.c +++ b/mxm_wifiex/wlan_src/mlan/mlan_11n_aggr.c @@ -230,6 +230,13 @@ mlan_status wlan_11n_deaggregate_pkt(mlan_private *priv, pmlan_buffer pmbuf) t_u8 hdr_len = sizeof(Eth803Hdr_t); t_u8 eapol_type[2] = {0x88, 0x8e}; t_u8 tdls_action_type[2] = {0x89, 0x0d}; + t_u32 in_ts_sec, in_ts_usec; + t_u32 out_ts_sec, out_ts_usec; + t_u32 in_copy_ts_sec, in_copy_ts_usec; + t_u32 out_copy_ts_sec, out_copy_ts_usec; + pmlan_callbacks pcb = &pmadapter->callbacks; + t_u32 copy_delay = 0; + t_u32 delay = 0; ENTER(); @@ -260,7 +267,9 @@ mlan_status wlan_11n_deaggregate_pkt(mlan_private *priv, pmlan_buffer pmbuf) total_pkt_len); goto done; } - + if (pmadapter->tp_state_on) + pcb->moal_get_system_time(pmadapter->pmoal_handle, &in_ts_sec, + &in_ts_usec); pmbuf->use_count = wlan_11n_get_num_aggrpkts(data, total_pkt_len); // rx_trace 7 @@ -321,10 +330,23 @@ mlan_status wlan_11n_deaggregate_pkt(mlan_private *priv, pmlan_buffer pmbuf) daggr_mbuf->extra_ts_usec = pmbuf->extra_ts_usec; daggr_mbuf->pparent = pmbuf; daggr_mbuf->priority = pmbuf->priority; + if (pmadapter->tp_state_on) + pcb->moal_get_system_time(pmadapter->pmoal_handle, + &in_copy_ts_sec, + &in_copy_ts_usec); memcpy_ext(pmadapter, daggr_mbuf->pbuf + daggr_mbuf->data_offset, data, pkt_len, daggr_mbuf->data_len); - + if (pmadapter->tp_state_on) { + pcb->moal_get_system_time(pmadapter->pmoal_handle, + &out_copy_ts_sec, + &out_copy_ts_usec); + copy_delay += + (t_s32)(out_copy_ts_sec - in_copy_ts_sec) * + 1000000; + copy_delay += + (t_s32)(out_copy_ts_usec - in_copy_ts_usec); + } #ifdef UAP_SUPPORT if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) { ret = wlan_uap_recv_packet(priv, daggr_mbuf); @@ -385,6 +407,14 @@ mlan_status wlan_11n_deaggregate_pkt(mlan_private *priv, pmlan_buffer pmbuf) data += pkt_len + pad; } + if (pmadapter->tp_state_on) { + pcb->moal_get_system_time(pmadapter->pmoal_handle, &out_ts_sec, + &out_ts_usec); + delay += (t_s32)(out_ts_sec - in_ts_sec) * 1000000; + delay += (t_s32)(out_ts_usec - in_ts_usec); + pmadapter->callbacks.moal_amsdu_tp_accounting( + pmadapter->pmoal_handle, delay, copy_delay); + } done: priv->msdu_in_rx_amsdu_cnt += pmbuf->use_count; diff --git a/mxm_wifiex/wlan_src/mlan/mlan_cfp.c b/mxm_wifiex/wlan_src/mlan/mlan_cfp.c index 9b14c9a..e9f6a89 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_cfp.c +++ b/mxm_wifiex/wlan_src/mlan/mlan_cfp.c @@ -2214,6 +2214,7 @@ t_u32 wlan_get_supported_rates(mlan_private *pmpriv, t_u32 bss_mode, case BAND_B | BAND_G: case BAND_A | BAND_B | BAND_G: case BAND_A | BAND_B: + case BAND_A | BAND_B | BAND_G | BAND_GN: case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN: case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC: case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC | diff --git a/mxm_wifiex/wlan_src/mlan/mlan_cmdevt.c b/mxm_wifiex/wlan_src/mlan/mlan_cmdevt.c index f41a437..6b9d127 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_cmdevt.c +++ b/mxm_wifiex/wlan_src/mlan/mlan_cmdevt.c @@ -83,6 +83,104 @@ done: LEAVE(); } +/** + * @brief This function check if cmd allowed to send to firmware + * during scan + * + * @param cmd_id cmd id + * + * @return MTRUE/MFALSE + */ +static t_u8 wlan_is_cmd_allowed_during_scan(t_u16 cmd_id) +{ + t_u8 ret = MTRUE; + ENTER(); + switch (cmd_id) { + case HostCmd_CMD_FUNC_INIT: + case HostCmd_CMD_CFG_DATA: + case HostCmd_CMD_REGION_POWER_CFG: + case HostCmd_CHANNEL_TRPC_CONFIG: + case HostCmd_CMD_FUNC_SHUTDOWN: + case HostCmd_CMD_802_11_ASSOCIATE: + case HostCmd_CMD_802_11_DEAUTHENTICATE: + case HostCmd_CMD_802_11_DISASSOCIATE: + case HostCmd_CMD_802_11_AD_HOC_START: + case HostCmd_CMD_802_11_AD_HOC_JOIN: + case HostCmd_CMD_802_11_AD_HOC_STOP: + case HostCmd_CMD_11N_ADDBA_REQ: + case HostCmd_CMD_11N_ADDBA_RSP: + case HostCmd_CMD_11N_DELBA: + case HostCmd_CMD_802_11_REMAIN_ON_CHANNEL: + case HostCmd_CMD_TDLS_CONFIG: + case HostCmd_CMD_TDLS_OPERATION: + case HostCmd_CMD_SOFT_RESET: +#ifdef UAP_SUPPORT + case HOST_CMD_APCMD_SYS_RESET: + case HOST_CMD_APCMD_BSS_START: + case HOST_CMD_APCMD_BSS_STOP: + case HOST_CMD_APCMD_STA_DEAUTH: +#endif + case HostCMD_APCMD_ACS_SCAN: + ret = MFALSE; + break; + default: + break; + } + LEAVE(); + return ret; +} + +/** + * @brief This function move the cmd from scan_pending_q to + * cmd_pending_q + * + * @param cmd_id cmd id + * + * @return MTRUE/MFALSE + */ +t_void wlan_move_cmd_to_cmd_pending_q(pmlan_adapter pmadapter) +{ + cmd_ctrl_node *pcmd_node = MNULL; + + ENTER(); + + wlan_request_cmd_lock(pmadapter); + while ((pcmd_node = (cmd_ctrl_node *)util_peek_list( + pmadapter->pmoal_handle, &pmadapter->scan_pending_q, + MNULL, MNULL))) { + util_unlink_list(pmadapter->pmoal_handle, + &pmadapter->scan_pending_q, + (pmlan_linked_list)pcmd_node, MNULL, MNULL); + wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node, MTRUE); + } + wlan_release_cmd_lock(pmadapter); + LEAVE(); +} + +/** + * @brief This function inserts command node to scan_pending_q or + * cmd_pending_q + * + * @param pmpriv A pointer to mlan_private structure + * @param pcmd_node A pointer to cmd_ctrl_node structure + * @return N/A + */ + +static t_void wlan_queue_cmd(mlan_private *pmpriv, cmd_ctrl_node *pcmd_node, + t_u16 cmd_no) +{ + ENTER(); + if (pmpriv->adapter->scan_processing && + pmpriv->adapter->ext_scan_type == EXT_SCAN_ENHANCE) { + if (MFALSE == wlan_is_cmd_allowed_during_scan(cmd_no)) { + wlan_queue_scan_cmd(pmpriv, pcmd_node); + return; + } + } + wlan_insert_cmd_to_pending_q(pmpriv->adapter, pcmd_node, MTRUE); + LEAVE(); +} + /** * @brief Internal function used to flush the scan pending queue * @@ -330,7 +428,12 @@ static t_void wlan_dump_info(mlan_adapter *pmadapter, t_u8 reason) PRINTM(MERROR, "mp_wr_bitmap=0x%x curr_wr_port=0x%x\n", pmadapter->pcard_sd->mp_wr_bitmap, pmadapter->pcard_sd->curr_wr_port); - PRINTM(MERROR, "mp_invalid_update=%d\n", + PRINTM(MMSG, "mp_data_port_mask = 0x%x\n", + pmadapter->pcard_sd->mp_data_port_mask); + + PRINTM(MERROR, + "last_recv_rd_bitmap=0x%x mp_invalid_update=%d\n", + pmadapter->pcard_sd->last_recv_rd_bitmap, pmadapter->pcard_sd->mp_invalid_update); PRINTM(MERROR, "last_recv_wr_bitmap=0x%x last_mp_index=%d\n", pmadapter->pcard_sd->last_recv_wr_bitmap, @@ -915,10 +1018,12 @@ static mlan_status wlan_ret_host_cmd(pmlan_private pmpriv, * @param pmpriv A pointer to mlan_private structure * @param cmd A pointer to HostCmd_DS_COMMAND structure * @param pdata_buf A pointer to data buffer + * @param cmd_no A pointer to cmd_no * @return MLAN_STATUS_SUCCESS */ static mlan_status wlan_cmd_host_cmd(pmlan_private pmpriv, - HostCmd_DS_COMMAND *cmd, t_void *pdata_buf) + HostCmd_DS_COMMAND *cmd, t_void *pdata_buf, + t_u16 *cmd_no) { mlan_ds_misc_cmd *pcmd_ptr = (mlan_ds_misc_cmd *)pdata_buf; @@ -927,7 +1032,9 @@ static mlan_status wlan_cmd_host_cmd(pmlan_private pmpriv, /* Copy the HOST command to command buffer */ memcpy_ext(pmpriv->adapter, (void *)cmd, pcmd_ptr->cmd, pcmd_ptr->len, MRVDRV_SIZE_OF_CMD_BUFFER); - PRINTM(MINFO, "Host command size = %d\n", pcmd_ptr->len); + *cmd_no = wlan_le16_to_cpu(cmd->command); + PRINTM(MCMND, "Prepare Host command: 0x%x size = %d\n", *cmd_no, + pcmd_ptr->len); LEAVE(); return MLAN_STATUS_SUCCESS; } @@ -972,11 +1079,7 @@ static t_u16 wlan_get_cmd_timeout(t_u16 cmd_id) case HOST_CMD_APCMD_STA_DEAUTH: #endif case HostCMD_APCMD_ACS_SCAN: -#ifdef IMX_SUPPORT - timeout = MRVDRV_TIMER_10S; -#else timeout = MRVDRV_TIMER_5S; -#endif break; default: #ifdef IMX_SUPPORT @@ -985,15 +1088,15 @@ static t_u16 wlan_get_cmd_timeout(t_u16 cmd_id) * timeout are observed for commands like 0x5e, 0x16, 0xd1. * Observed that response has come just after default timeout of * 2 seconds for these commands. This random timeout is not - * observed when the default timeout is increased to 10 seconds - * (As an work around, Increase the default timeout to 10 + * observed when the default timeout is increased to 5 seconds + * (As an work around, Increase the default timeout to 5 * seconds. Need to further debug exact reason for delay in cmd * responses) * */ - timeout = MRVDRV_TIMER_10S; + timeout = MRVDRV_TIMER_1S * 5; #else - timeout = MRVDRV_TIMER_1S * 2; + timeout = MRVDRV_TIMER_1S * 5; #endif break; } @@ -1717,7 +1820,7 @@ mlan_status wlan_prepare_cmd(mlan_private *pmpriv, t_u16 cmd_no, cmd_oid, pioctl_buf, pdata_buf, cmd_ptr); else { - ret = wlan_cmd_host_cmd(pmpriv, cmd_ptr, pdata_buf); + ret = wlan_cmd_host_cmd(pmpriv, cmd_ptr, pdata_buf, &cmd_no); pcmd_node->cmd_flag |= CMD_F_HOSTCMD; } @@ -1744,7 +1847,7 @@ mlan_status wlan_prepare_cmd(mlan_private *pmpriv, t_u16 cmd_no, pmadapter->ext_scan && pmadapter->ext_scan_enh && pmadapter->ext_scan_type == EXT_SCAN_ENHANCE) { wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node, - MFALSE); + MTRUE); } else wlan_queue_scan_cmd(pmpriv, pcmd_node); } else { @@ -1755,8 +1858,7 @@ mlan_status wlan_prepare_cmd(mlan_private *pmpriv, t_u16 cmd_no, wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node, MFALSE); else - wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node, - MTRUE); + wlan_queue_cmd(pmpriv, pcmd_node, cmd_no); #ifdef STA_SUPPORT } #endif @@ -5490,6 +5592,242 @@ mlan_status wlan_ret_p2p_params_config(pmlan_private pmpriv, } #endif +/** + * @brief This function prepares command of GPIO TSF LATCH. + * + * @param pmpriv A pointer to mlan_private structure + * @param cmd A pointer to HostCmd_DS_COMMAND structure + * @param cmd_action The action: GET or SET + * @param pioctl_buf A pointer to mlan_ioctl_req buf + * @param pdata_buf A pointer to data buffer + * + * @return MLAN_STATUS_SUCCESS + */ +mlan_status wlan_cmd_gpio_tsf_latch(pmlan_private pmpriv, + HostCmd_DS_COMMAND *cmd, t_u16 cmd_action, + mlan_ioctl_req *pioctl_buf, + t_void *pdata_buf) +{ + HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG *gpio_tsf_config = + &cmd->params.gpio_tsf_latch; + mlan_ds_gpio_tsf_latch *cfg = (mlan_ds_gpio_tsf_latch *)pdata_buf; + mlan_ds_misc_cfg *misc_cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf; + + mlan_ds_tsf_info *tsf_info = (mlan_ds_tsf_info *)pdata_buf; + MrvlIEtypes_GPIO_TSF_LATCH_CONFIG *gpio_tsf_latch_config = MNULL; + MrvlIEtypes_GPIO_TSF_LATCH_REPORT *gpio_tsf_latch_report = MNULL; + t_u8 *tlv = MNULL; + ENTER(); + + cmd->size = sizeof(HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG) + S_DS_GEN; + cmd->command = wlan_cpu_to_le16(HOST_CMD_GPIO_TSF_LATCH_PARAM_CONFIG); + gpio_tsf_config->action = wlan_cpu_to_le16(cmd_action); + if (cmd_action == HostCmd_ACT_GEN_SET) { + tlv = (t_u8 *)gpio_tsf_config->tlv_buf; + if (misc_cfg->sub_command == MLAN_OID_MISC_GPIO_TSF_LATCH) { + gpio_tsf_latch_config = + (MrvlIEtypes_GPIO_TSF_LATCH_CONFIG *)tlv; + gpio_tsf_latch_config->header.type = wlan_cpu_to_le16( + TLV_TYPE_GPIO_TSF_LATCH_CONFIG); + gpio_tsf_latch_config->header.len = wlan_cpu_to_le16( + sizeof(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG) - + sizeof(MrvlIEtypesHeader_t)); + gpio_tsf_latch_config->clock_sync_mode = + cfg->clock_sync_mode; + gpio_tsf_latch_config->clock_sync_Role = + cfg->clock_sync_Role; + gpio_tsf_latch_config->clock_sync_gpio_pin_number = + cfg->clock_sync_gpio_pin_number; + gpio_tsf_latch_config->clock_sync_gpio_level_toggle = + cfg->clock_sync_gpio_level_toggle; + gpio_tsf_latch_config->clock_sync_gpio_pulse_width = + wlan_cpu_to_le16( + cfg->clock_sync_gpio_pulse_width); + cmd->size += sizeof(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG); + tlv += sizeof(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG); + PRINTM(MCMND, + "Set GPIO TSF latch config: Mode=%d Role=%d, GPIO Pin Number=%d, GPIO level/toggle=%d GPIO pulse width=%d\n", + cfg->clock_sync_mode, cfg->clock_sync_Role, + cfg->clock_sync_gpio_pin_number, + cfg->clock_sync_gpio_level_toggle, + (int)cfg->clock_sync_gpio_pulse_width); + } + } else if (cmd_action == HostCmd_ACT_GEN_GET) { + tlv = (t_u8 *)gpio_tsf_config->tlv_buf; + if (misc_cfg->sub_command == MLAN_OID_MISC_GPIO_TSF_LATCH) { + gpio_tsf_latch_config = + (MrvlIEtypes_GPIO_TSF_LATCH_CONFIG *)tlv; + gpio_tsf_latch_config->header.type = wlan_cpu_to_le16( + TLV_TYPE_GPIO_TSF_LATCH_CONFIG); + gpio_tsf_latch_config->header.len = wlan_cpu_to_le16( + sizeof(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG) - + sizeof(MrvlIEtypesHeader_t)); + cmd->size += sizeof(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG); + tlv += sizeof(MrvlIEtypes_GPIO_TSF_LATCH_CONFIG); + } + + if (misc_cfg->sub_command == MLAN_OID_MISC_GET_TSF_INFO) { + gpio_tsf_latch_report = + (MrvlIEtypes_GPIO_TSF_LATCH_REPORT *)tlv; + gpio_tsf_latch_report->header.type = wlan_cpu_to_le16( + TLV_TYPE_GPIO_TSF_LATCH_REPORT); + gpio_tsf_latch_report->header.len = wlan_cpu_to_le16( + sizeof(MrvlIEtypes_GPIO_TSF_LATCH_REPORT) - + sizeof(MrvlIEtypesHeader_t)); + gpio_tsf_latch_report->tsf_format = + wlan_cpu_to_le16(tsf_info->tsf_format); + PRINTM(MCMND, "Get TSF info: format=%d\n", + tsf_info->tsf_format); + cmd->size += sizeof(MrvlIEtypes_GPIO_TSF_LATCH_REPORT); + } + } + cmd->size = wlan_cpu_to_le16(cmd->size); + LEAVE(); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief This function handles the command response of GPIO TSF Latch + * + * @param pmpriv A pointer to mlan_private structure + * @param resp A pointer to HostCmd_DS_COMMAND + * @param pioctl_buf A pointer to mlan_ioctl_req structure + * + * @return MLAN_STATUS_SUCCESS + */ +mlan_status wlan_ret_gpio_tsf_latch(pmlan_private pmpriv, + HostCmd_DS_COMMAND *resp, + mlan_ioctl_req *pioctl_buf) +{ + HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG *gpio_tsf_config = + &resp->params.gpio_tsf_latch; + mlan_ds_misc_cfg *cfg = MNULL; + MrvlIEtypes_GPIO_TSF_LATCH_CONFIG *gpio_tsf_latch_config = MNULL; + MrvlIEtypes_GPIO_TSF_LATCH_REPORT *gpio_tsf_latch_report = MNULL; + MrvlIEtypesHeader_t *tlv = MNULL; + t_u16 tlv_buf_left = 0; + t_u16 tlv_type = 0; + t_u16 tlv_len = 0; + + ENTER(); + if (wlan_le16_to_cpu(gpio_tsf_config->action) == HostCmd_ACT_GEN_GET) { + if (pioctl_buf) { + cfg = (mlan_ds_misc_cfg *)pioctl_buf->pbuf; + tlv = (MrvlIEtypesHeader_t *)(gpio_tsf_config->tlv_buf); + tlv_buf_left = + resp->size - + (sizeof(HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG) + + S_DS_GEN); + while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) { + tlv_type = wlan_le16_to_cpu(tlv->type); + tlv_len = wlan_le16_to_cpu(tlv->len); + if (tlv_buf_left < + (tlv_len + sizeof(MrvlIEtypesHeader_t))) { + PRINTM(MERROR, + "Error processing gpio tsf latch config TLVs, bytes left < TLV length\n"); + break; + } + switch (tlv_type) { + case TLV_TYPE_GPIO_TSF_LATCH_CONFIG: + if (cfg->sub_command == + MLAN_OID_MISC_GPIO_TSF_LATCH) { + gpio_tsf_latch_config = + (MrvlIEtypes_GPIO_TSF_LATCH_CONFIG + *)tlv; + cfg->param.gpio_tsf_latch_config + .clock_sync_mode = + gpio_tsf_latch_config + ->clock_sync_mode; + cfg->param.gpio_tsf_latch_config + .clock_sync_Role = + gpio_tsf_latch_config + ->clock_sync_Role; + cfg->param.gpio_tsf_latch_config + .clock_sync_gpio_pin_number = + gpio_tsf_latch_config + ->clock_sync_gpio_pin_number; + cfg->param.gpio_tsf_latch_config + .clock_sync_gpio_level_toggle = + gpio_tsf_latch_config + ->clock_sync_gpio_level_toggle; + cfg->param.gpio_tsf_latch_config + .clock_sync_gpio_pulse_width = + wlan_le16_to_cpu( + gpio_tsf_latch_config + ->clock_sync_gpio_pulse_width); + PRINTM(MCMND, + "Get GPIO TSF latch config: Mode=%d Role=%d, GPIO Pin Number=%d, GPIO level/toggle=%d GPIO pulse width=%d\n", + cfg->param + .gpio_tsf_latch_config + .clock_sync_mode, + cfg->param + .gpio_tsf_latch_config + .clock_sync_Role, + cfg->param + .gpio_tsf_latch_config + .clock_sync_gpio_pin_number, + cfg->param + .gpio_tsf_latch_config + .clock_sync_gpio_level_toggle, + (int)cfg->param + .gpio_tsf_latch_config + .clock_sync_gpio_pulse_width); + } + break; + case TLV_TYPE_GPIO_TSF_LATCH_REPORT: + if (cfg->sub_command == + MLAN_OID_MISC_GET_TSF_INFO) { + gpio_tsf_latch_report = + (MrvlIEtypes_GPIO_TSF_LATCH_REPORT + *)tlv; + cfg->param.tsf_info + .tsf_format = wlan_le16_to_cpu( + gpio_tsf_latch_report + ->tsf_format); + cfg->param.tsf_info + .tsf_info = wlan_le16_to_cpu( + gpio_tsf_latch_report + ->tsf_info); + cfg->param.tsf_info + .tsf = wlan_le64_to_cpu( + gpio_tsf_latch_report + ->tsf); + cfg->param.tsf_info + .tsf_offset = wlan_le16_to_cpu( + gpio_tsf_latch_report + ->tsf_offset); + PRINTM(MCMND, + "Get GPIO TSF latch report : format=%d\n info=%d tsf=%llu offset=%d", + cfg->param.tsf_info + .tsf_format, + cfg->param.tsf_info + .tsf_info, + cfg->param.tsf_info.tsf, + cfg->param.tsf_info + .tsf_offset); + } + break; + default: + break; + } + tlv_buf_left -= + tlv_len + sizeof(MrvlIEtypesHeader_t); + tlv = (MrvlIEtypesHeader_t + *)((t_u8 *)tlv + tlv_len + + sizeof(MrvlIEtypesHeader_t)); + } + if (cfg->sub_command == MLAN_OID_MISC_GPIO_TSF_LATCH) + pioctl_buf->data_read_written = + sizeof(mlan_ds_gpio_tsf_latch); + else if (cfg->sub_command == MLAN_OID_MISC_GET_TSF_INFO) + pioctl_buf->data_read_written = + sizeof(mlan_ds_tsf_info); + } + } + LEAVE(); + return MLAN_STATUS_SUCCESS; +} + /** * @brief This function prepares command of mimo switch configuration. * diff --git a/mxm_wifiex/wlan_src/mlan/mlan_decl.h b/mxm_wifiex/wlan_src/mlan/mlan_decl.h index 0347721..319dc7c 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_decl.h +++ b/mxm_wifiex/wlan_src/mlan/mlan_decl.h @@ -24,7 +24,7 @@ #define _MLAN_DECL_H_ /** MLAN release version */ -#define MLAN_RELEASE_VERSION "266.p4" +#define MLAN_RELEASE_VERSION "283" /** Re-define generic data types for MLAN/MOAL */ /** Signed char (1-byte) */ @@ -2039,7 +2039,8 @@ typedef struct _mlan_callbacks { t_u32 drop_point); void (*moal_tp_accounting_rx_param)(t_void *pmoal, unsigned int type, unsigned int rsvd1); - + void (*moal_amsdu_tp_accounting)(t_void *pmoal, t_s32 delay, + t_s32 copy_delay); } mlan_callbacks, *pmlan_callbacks; /** Parameter unchanged, use MLAN default setting */ @@ -2180,6 +2181,8 @@ typedef struct _mlan_device { t_u32 drv_mode; /** dfs w53 cfg */ t_u8 dfs53cfg; + /** extend enhance scan */ + t_u8 ext_scan; } mlan_device, *pmlan_device; /** MLAN API function prototype */ @@ -2253,4 +2256,9 @@ MLAN_API mlan_status mlan_ioctl(t_void *padapter, pmlan_ioctl_req pioctl_req); /** mlan select wmm queue */ MLAN_API t_u8 mlan_select_wmm_queue(t_void *padapter, t_u8 bss_num, t_u8 tid); +/** mlan mask host interrupt */ +MLAN_API mlan_status mlan_disable_host_int(t_void *padapter); +/** mlan unmask host interrupt */ +MLAN_API mlan_status mlan_enable_host_int(t_void *padapter); + #endif /* !_MLAN_DECL_H_ */ diff --git a/mxm_wifiex/wlan_src/mlan/mlan_fw.h b/mxm_wifiex/wlan_src/mlan/mlan_fw.h index 4617f9b..1308a1f 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_fw.h +++ b/mxm_wifiex/wlan_src/mlan/mlan_fw.h @@ -185,6 +185,10 @@ typedef enum _KEY_TYPE_ID { KEY_TYPE_ID_GCMP_256 = 6, /** Key type : CCMP_256 */ KEY_TYPE_ID_CCMP_256 = 7, + /** Key type : GMAC_128 */ + KEY_TYPE_ID_BIP_GMAC_128 = 8, + /** Key type : GMAC_256 */ + KEY_TYPE_ID_BIP_GMAC_256 = 9, } KEY_TYPE_ID; /** Key Info flag for multicast key */ @@ -222,6 +226,7 @@ typedef enum _KEY_INFO_AES { #define CMAC_AES_KEY_LEN 16 /** IGTK key length */ #define WPA_IGTK_KEY_LEN 16 +#define WPA_IGTK_256_KEY_LEN 32 /** WAPI key length */ #define WAPI_KEY_LEN 50 @@ -326,6 +331,9 @@ typedef enum _WLAN_802_11_WEP_STATUS { /**TLV type : Host MLME Flag*/ #define TLV_TYPE_HOST_MLME (PROPRIETARY_TLV_BASE_ID + 307) +/** TLV type : AP wacp mode */ +#define TLV_TYPE_UAP_WACP_MODE (PROPRIETARY_TLV_BASE_ID + 0x147) /* 0x0247 */ + /** TLV type : Vendor Specific IE */ #define TLV_TYPE_VENDOR_SPECIFIC_IE 0x00dd @@ -359,6 +367,8 @@ typedef enum _WLAN_802_11_WEP_STATUS { #define TLV_TYPE_WILDCARDSSID (PROPRIETARY_TLV_BASE_ID + 0x12) /* 0x0112 */ /** TLV type : TSF timestamp */ #define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 0x13) /* 0x0113 */ +/** TLV type : ARP filter */ +#define TLV_TYPE_ARP_FILTER (PROPRIETARY_TLV_BASE_ID + 0x15) /* 0x0115 */ /** TLV type : Beacon RSSI high */ #define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 0x16) /* 0x0116 */ /** TLV type : Beacon SNR high */ @@ -475,6 +485,10 @@ typedef enum _WLAN_802_11_WEP_STATUS { /** TLV type : p2p opp ps */ #define TLV_TYPE_WIFI_DIRECT_OPP_PS (PROPRIETARY_TLV_BASE_ID + 0x84) #endif /* WIFI_DIRECT_SUPPORT */ +/** TLV type : GPIO TSF LATCH CONFIG */ +#define TLV_TYPE_GPIO_TSF_LATCH_CONFIG (PROPRIETARY_TLV_BASE_ID + 0x153) +/** TLV type : GPIO TSF LATCH REPORT*/ +#define TLV_TYPE_GPIO_TSF_LATCH_REPORT (PROPRIETARY_TLV_BASE_ID + 0x154) /** TLV : 20/40 coex config */ #define TLV_TYPE_2040_BSS_COEX_CONTROL \ @@ -884,6 +898,9 @@ typedef enum _WLAN_802_11_WEP_STATUS { /** Set VHT Cap Info: Max MPDU length */ #define SET_VHTCAP_MAXMPDULEN(VHTCapInfo, value) (VHTCapInfo |= (value & 0x03)) +/** Reset VHT Cap Info: Max MPDU length */ +#define RESET_VHTCAP_MAXMPDULEN(VHTCapInfo) (VHTCapInfo &= ~(MBIT(0) | MBIT(1))) + /** SET VHT CapInfo: Supported Channel Width SET (2 bits)*/ #define SET_VHTCAP_CHWDSET(VHTCapInfo, value) \ (VHTCapInfo |= ((value & 0x3) << 2)) @@ -978,6 +995,7 @@ typedef enum _WLAN_802_11_WEP_STATUS { #define SET_OPER_MODE_1NSS(oper_mode) \ (oper_mode &= ~(MBIT(4) | MBIT(5) | MBIT(6))) +#define NO_NSS_SUPPORT 0x3 #define GET_VHTMCS(MCSMapSet) (MCSMapSet & 0xFFFF) #define GET_VHTNSSMCS(MCSMapSet, nss) ((MCSMapSet >> (2 * (nss - 1))) & 0x3) #define RET_VHTNSSMCS(MCSMapSet, nss) ((MCSMapSet >> (2 * (nss - 1))) & 0x3) @@ -1356,6 +1374,8 @@ typedef enum _WLAN_802_11_WEP_STATUS { #define FW_CAPINFO_EXT_NO_80MHZ MBIT(8) /** FW cap info bit 9: Multi BSSID Support */ #define FW_CAPINFO_EXT_MULTI_BSSID MBIT(9) +/** FW cap info bit 10: Beacon Protection Support */ +#define FW_CAPINFO_EXT_BEACON_PROT MBIT(10) /** Check if 5G 1x1 only is supported by firmware */ #define IS_FW_SUPPORT_5G_1X1_ONLY(_adapter) \ @@ -1384,6 +1404,9 @@ typedef enum _WLAN_802_11_WEP_STATUS { /** Check if Multi BSSID supported by firmware */ #define IS_FW_SUPPORT_MULTIBSSID(_adapter) \ (_adapter->fw_cap_ext & FW_CAPINFO_EXT_MULTI_BSSID) +/** Check if Beacon Protection supported by firmware */ +#define IS_FW_SUPPORT_BEACON_PROT(_adapter) \ + (_adapter->fw_cap_ext & FW_CAPINFO_EXT_BEACON_PROT) /** MrvlIEtypes_PrevBssid_t */ typedef MLAN_PACK_START struct _MrvlIEtypes_PrevBssid_t { @@ -1505,6 +1528,8 @@ typedef MLAN_PACK_START struct _MrvlIEtypes_He_cap_t { #define HOST_CMD_WIFI_DIRECT_MODE_CONFIG 0x00eb #endif +/** Host Command ID: GPIO TSF LATCH */ +#define HOST_CMD_GPIO_TSF_LATCH_PARAM_CONFIG 0x0278 /** Host Command ID: Remain On Channel */ #define HostCmd_CMD_802_11_REMAIN_ON_CHANNEL 0x010d @@ -1544,6 +1569,8 @@ typedef MLAN_PACK_START struct _MrvlIEtypes_He_cap_t { /** Host Command ID : Configure ADHOC_OVER_IP parameters */ #define HostCmd_CMD_WMM_PARAM_CONFIG 0x023a +#define HostCmd_CMD_IPV6_RA_OFFLOAD_CFG 0x0238 + #ifdef STA_SUPPORT /** Host Command ID : set/get sta configure */ #define HostCmd_CMD_STA_CONFIGURE 0x023f @@ -1565,7 +1592,11 @@ typedef MLAN_PACK_START struct _MrvlIEtypes_Reg_type_t { } MLAN_PACK_END MrvlIEtypes_Reg_type_t; #endif +/** use to query chan region cfg setting in firmware */ #define HostCmd_CMD_CHAN_REGION_CFG 0x0242 +/** used in hostcmd to download region power cfg setting to firmware */ +#define HostCmd_CMD_REGION_POWER_CFG 0x0249 + /* mod_grp */ typedef enum _mod_grp { MOD_CCK, // 0 @@ -1983,7 +2014,7 @@ typedef enum _ENH_PS_MODES { #define TDLS_EVENT_TYPE_CHAN_SWITCH_STOPPED 9 /** Packet received on direct link */ -#define RXPD_FLAG_PKT_DIRECT_LINK 1 +#define RXPD_FLAG_PKT_DIRECT_LINK MBIT(0) /** TDLS base channel */ #define TDLS_BASE_CHANNEL 0 /** TDLS off channel */ @@ -2100,6 +2131,7 @@ typedef MLAN_PACK_START struct _MrvlIEtypes_TDLS_Idle_Timeout_t { /** Packet type: 802.11 */ #define PKT_TYPE_802DOT11 0x05 + #define PKT_TYPE_MGMT_FRAME 0xE5 /** Packet type: AMSDU */ #define PKT_TYPE_AMSDU 0xE6 @@ -2192,6 +2224,9 @@ typedef MLAN_PACK_START struct _RxPD { /** rx info */ t_u32 rx_info; + /** Reserved */ + t_u8 reserved3[8]; + } MLAN_PACK_END RxPD, *PRxPD; /** IEEEtypes_FrameCtl_t*/ @@ -2761,6 +2796,16 @@ typedef MLAN_PACK_START struct _cmac_aes_param { t_u8 key[CMAC_AES_KEY_LEN]; } MLAN_PACK_END cmac_aes_param; +/** gmac_aes_256_param */ +typedef MLAN_PACK_START struct _gmac_aes_256_param { + /** IGTK pn */ + t_u8 ipn[IGTK_PN_SIZE]; + /** key_len */ + t_u16 key_len; + /** aes key */ + t_u8 key[WPA_IGTK_256_KEY_LEN]; +} MLAN_PACK_END gmac_aes_256_param; + /** gmac_param */ typedef MLAN_PACK_START struct _gcmp_param { /** GCMP pn */ @@ -2973,6 +3018,39 @@ typedef MLAN_PACK_START struct _HostCmd_DS_CHANNEL_TRPC_CONFIG { // MrvlIETypes_ChanTRPCConfig_t tlv[]; } MLAN_PACK_END HostCmd_DS_CHANNEL_TRPC_CONFIG; +/** Address type: broadcast */ +#define ADDR_TYPE_BROADCAST 1 +/* Address type: unicast */ +#define ADDR_TYPE_UNICAST 2 +/* Address type: multicast */ +#define ADDR_TYPE_MULTICAST 3 + +/** Ether type: any */ +#define ETHER_TYPE_ANY 0xffff +/** Ether type: ARP */ +#define ETHER_TYPE_ARP 0x0608 + +/** IPv4 address any */ +#define IPV4_ADDR_ANY 0xffffffff + +/** Header structure for ARP filter */ +typedef MLAN_PACK_START struct _arpfilter_header { + /** Type */ + t_u16 type; + /** TLV length */ + t_u16 len; +} MLAN_PACK_END arpfilter_header; + +/** Filter entry structure */ +typedef MLAN_PACK_START struct _filter_entry { + /** Address type */ + t_u16 addr_type; + /** Ether type */ + t_u16 eth_type; + /** IPv4 address */ + t_u32 ipv4_addr; +} MLAN_PACK_END filter_entry; + typedef MLAN_PACK_START struct _HostCmd_DS_MEF_CFG { /** Criteria */ t_u32 criteria; @@ -3710,6 +3788,14 @@ typedef MLAN_PACK_START struct _HostCmd_DS_802_11_GET_LOG { t_u32 dwMgtErrCnt; /*Control Ownership error count*/ t_u32 dwDatErrCnt; + /*BIGTK MME good count*/ + t_u32 bigtk_mmeGoodCnt; + /*BIGTK Replay error count*/ + t_u32 bigtk_replayErrCnt; + /*BIGTK MIC error count*/ + t_u32 bigtk_micErrCnt; + /*BIGTK MME not included count*/ + t_u32 bigtk_mmeNotFoundCnt; } MLAN_PACK_END HostCmd_DS_802_11_GET_LOG; /* maln wifi rate */ @@ -4325,6 +4411,48 @@ typedef MLAN_PACK_START struct _HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG { } MLAN_PACK_END HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG; #endif +/** MrvlIEtypes_GPIO_TSF_LATCH_CONFIG*/ +typedef MLAN_PACK_START struct _MrvlIEtypes_GPIO_TSF_LATCH_CONFIG { + /** Header */ + MrvlIEtypesHeader_t header; + /**clock sync Mode */ + t_u8 clock_sync_mode; + /**clock sync Role */ + t_u8 clock_sync_Role; + /**clock sync GPIO Pin Number */ + t_u8 clock_sync_gpio_pin_number; + /**clock sync GPIO Level or Toggle */ + t_u8 clock_sync_gpio_level_toggle; + /**clock sync GPIO Pulse Width */ + t_u16 clock_sync_gpio_pulse_width; + +} MLAN_PACK_END MrvlIEtypes_GPIO_TSF_LATCH_CONFIG; + +/** MrvlIEtypes_GPIO_TSF_LATCH_REPORT */ +typedef MLAN_PACK_START struct _MrvlIEtypes_GPIO_TSF_LATCH_REPORT { + /** Header */ + MrvlIEtypesHeader_t header; + /**get tsf info format */ + t_u16 tsf_format; + /**tsf info */ + t_u16 tsf_info; + /**tsf */ + t_u64 tsf; + /**Positive or negative offset in microsecond from Beacon TSF to GPIO + * toggle TSF */ + t_s32 tsf_offset; +} MLAN_PACK_END MrvlIEtypes_GPIO_TSF_LATCH_REPORT; + +/** HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG */ +typedef MLAN_PACK_START struct _HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG { + /** Action 0-GET, 1-SET */ + t_u16 action; + /** MrvlIEtypes_GPIO_TSF_LATCH_CONFIG + * MrvlIEtypes_GPIO_TSF_LATCH_REPORT + */ + t_u8 tlv_buf[]; +} MLAN_PACK_END HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG; + MLAN_PACK_START struct coalesce_filt_field_param { t_u8 operation; t_u8 operand_len; @@ -6267,6 +6395,14 @@ typedef MLAN_PACK_START struct _MrvlIEtypes_wmm_parameter_t { WmmParameter_t wmm_para; } MLAN_PACK_END MrvlIEtypes_wmm_parameter_t; +/** MrvlIEtypes_wacp_mode_t */ +typedef MLAN_PACK_START struct _MrvlIEtypes_wacp_mode_t { + /** Header */ + MrvlIEtypesHeader_t header; + /** wacp_mode */ + t_u8 wacp_mode; +} MLAN_PACK_END MrvlIEtypes_wacp_mode_t; + /** SNMP_MIB_UAP_INDEX */ typedef enum _SNMP_MIB_UAP_INDEX { tkip_mic_failures = 0x0b, @@ -7018,6 +7154,22 @@ typedef MLAN_PACK_START struct _HostCmd_DS_SENSOR_TEMP { t_u32 temperature; } MLAN_PACK_END HostCmd_DS_SENSOR_TEMP; +#define TLV_TYPE_IPV6_RA_OFFLOAD (PROPRIETARY_TLV_BASE_ID + 0xE6) /** 0x1E6*/ +typedef MLAN_PACK_START struct { + MrvlIEtypesHeader_t Header; + t_u8 ipv6_addr[16]; +} MLAN_PACK_END MrvlIETypes_IPv6AddrParamSet_t; + +typedef MLAN_PACK_START struct _HostCmd_DS_IPV6_RA_OFFLOAD { + /** 0x0000: Get IPv6 RA Offload configuration + * 0x0001: Set IPv6 RA Offload configuration + */ + t_u16 action; + /** 0x00: disable IPv6 RA Offload; 0x01: enable IPv6 RA offload */ + t_u8 enable; + MrvlIETypes_IPv6AddrParamSet_t ipv6_addr_param; +} MLAN_PACK_END HostCmd_DS_IPV6_RA_OFFLOAD; + #ifdef STA_SUPPORT typedef MLAN_PACK_START struct _HostCmd_DS_STA_CONFIGURE { /** Action Set or get */ @@ -7504,6 +7656,7 @@ typedef struct MLAN_PACK_START _HostCmd_DS_COMMAND { HostCmd_DS_WIFI_DIRECT_MODE wifi_direct_mode; HostCmd_DS_WIFI_DIRECT_PARAM_CONFIG p2p_params_config; #endif + HostCmd_DS_GPIO_TSF_LATCH_PARAM_CONFIG gpio_tsf_latch; HostCmd_DS_COALESCE_CONFIG coalesce_config; HostCmd_DS_HS_WAKEUP_REASON hs_wakeup_reason; HostCmd_DS_PACKET_AGGR_CTRL aggr_ctrl; @@ -7520,6 +7673,7 @@ typedef struct MLAN_PACK_START _HostCmd_DS_COMMAND { HostCmd_DS_SENSOR_TEMP temp_sensor; HostCMD_DS_APCMD_ACS_SCAN acs_scan; HostCmd_DS_MIMO_SWITCH mimo_switch; + HostCmd_DS_IPV6_RA_OFFLOAD ipv6_ra_offload; #ifdef STA_SUPPORT HostCmd_DS_STA_CONFIGURE sta_cfg; #endif diff --git a/mxm_wifiex/wlan_src/mlan/mlan_ieee.h b/mxm_wifiex/wlan_src/mlan/mlan_ieee.h index 906a345..329aa77 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_ieee.h +++ b/mxm_wifiex/wlan_src/mlan/mlan_ieee.h @@ -1403,6 +1403,8 @@ typedef MLAN_PACK_START struct { t_u8 local_max_tp_20mhz; /**< Local Maximum Transmit Power for 20 MHZ>*/ t_u8 local_max_tp_40mhz; /**< Local Maximum Transmit Power for 40 MHZ>*/ t_u8 local_max_tp_80mhz; /**< Local Maximum Transmit Power for 80 MHZ>*/ + t_u8 local_max_tp_160mhz_80_80mhz; /**< Local Maximum Transmit Power for + 160/80+80 MHZ>*/ } MLAN_PACK_END IEEEtypes_VhtTpcEnvelope_t; /* IEEE Quiet Period Element (7.3.2.23) */ diff --git a/mxm_wifiex/wlan_src/mlan/mlan_init.c b/mxm_wifiex/wlan_src/mlan/mlan_init.c index 201ac3f..15f6406 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_init.c +++ b/mxm_wifiex/wlan_src/mlan/mlan_init.c @@ -474,6 +474,9 @@ mlan_status wlan_init_priv(pmlan_private priv) wlan_11h_priv_init(priv); #ifdef UAP_SUPPORT + priv->is_11n_enabled = MFALSE; + priv->is_11ac_enabled = MFALSE; + priv->is_11ax_enabled = MFALSE; priv->uap_bss_started = MFALSE; priv->uap_host_based = MFALSE; memset(pmadapter, &priv->uap_state_chan_cb, 0, @@ -516,10 +519,13 @@ mlan_status wlan_init_priv(pmlan_private priv) #if defined(STA_SUPPORT) priv->pmfcfg.mfpc = 0; priv->pmfcfg.mfpr = 0; + memset(pmadapter, &priv->pmfcfg, 0, sizeof(priv->pmfcfg)); #endif priv->sec_info.wapi_enabled = MFALSE; priv->wapi_ie_len = 0; priv->sec_info.wapi_key_on = MFALSE; + priv->osen_ie_len = 0; + memset(pmadapter, &priv->osen_ie, 0, sizeof(priv->osen_ie)); memset(pmadapter, &priv->wps, 0, sizeof(priv->wps)); memset(pmadapter, &priv->gen_ie_buf, 0, sizeof(priv->gen_ie_buf)); @@ -527,6 +533,7 @@ mlan_status wlan_init_priv(pmlan_private priv) #endif /* STA_SUPPORT */ priv->wmm_required = MTRUE; priv->wmm_enabled = MFALSE; + priv->disconnect_reason_code = 0; priv->wmm_qosinfo = 0; priv->saved_wmm_qosinfo = 0; priv->host_tdls_cs_support = MTRUE; @@ -534,8 +541,14 @@ mlan_status wlan_init_priv(pmlan_private priv) priv->tdls_cs_channel = 0; priv->supp_regulatory_class_len = 0; priv->chan_supp_len = 0; + memset(pmadapter, &priv->chan_supp, 0, sizeof(priv->chan_supp)); + memset(pmadapter, &priv->supp_regulatory_class, 0, + sizeof(priv->supp_regulatory_class)); priv->tdls_idle_time = TDLS_IDLE_TIMEOUT; priv->txaggrctrl = MTRUE; + for (i = 0; i < MAX_MGMT_IE_INDEX; i++) + memset(pmadapter, &priv->mgmt_ie[i], 0, sizeof(custom_ie)); + priv->mgmt_frame_passthru_mask = 0; #ifdef STA_SUPPORT priv->pcurr_bcn_buf = MNULL; priv->curr_bcn_size = 0; @@ -549,6 +562,10 @@ mlan_status wlan_init_priv(pmlan_private priv) sizeof(priv->ext_cap), sizeof(priv->def_ext_cap)); #endif /* STA_SUPPORT */ + priv->amsdu_rx_cnt = 0; + priv->msdu_in_rx_amsdu_cnt = 0; + priv->amsdu_tx_cnt = 0; + priv->msdu_in_tx_amsdu_cnt = 0; for (i = 0; i < MAX_NUM_TID; i++) priv->addba_reject[i] = ADDBA_RSP_STATUS_ACCEPT; priv->addba_reject[6] = ADDBA_RSP_STATUS_REJECT; @@ -578,9 +595,12 @@ mlan_status wlan_init_priv(pmlan_private priv) } #endif priv->user_rxwinsize = priv->add_ba_param.rx_win_size; - + memset(pmadapter, priv->rx_seq, 0, sizeof(priv->rx_seq)); priv->port_ctrl_mode = MTRUE; priv->port_open = MFALSE; + priv->prior_port_status = MFALSE; + priv->tx_pause = MFALSE; + priv->hotspot_cfg = 0; priv->intf_hr_len = pmadapter->ops.intf_header_len; #ifdef USB @@ -634,7 +654,17 @@ t_void wlan_init_adapter(pmlan_adapter pmadapter) #ifdef STA_SUPPORT pmadapter->pwarm_reset_ioctl_req = MNULL; #endif + pmadapter->pscan_ioctl_req = MNULL; pmadapter->cmd_sent = MFALSE; + pmadapter->mlan_processing = MFALSE; + pmadapter->main_process_cnt = 0; + pmadapter->mlan_rx_processing = MFALSE; + pmadapter->more_rx_task_flag = MFALSE; + pmadapter->more_task_flag = MFALSE; + pmadapter->delay_task_flag = MFALSE; + pmadapter->data_sent = MFALSE; + pmadapter->data_sent_cnt = 0; + #ifdef SDIO if (IS_SD(pmadapter->card_type)) { pmadapter->pcard_sd->int_mode = pmadapter->init_para.int_mode; @@ -687,13 +717,20 @@ t_void wlan_init_adapter(pmlan_adapter pmadapter) pmadapter->cmd_resp_received = MFALSE; pmadapter->event_received = MFALSE; pmadapter->data_received = MFALSE; - + pmadapter->seq_num = 0; + pmadapter->num_cmd_timeout = 0; + pmadapter->last_init_cmd = 0; + pmadapter->pending_ioctl = MFALSE; + pmadapter->scan_processing = MFALSE; pmadapter->cmd_timer_is_set = MFALSE; + pmadapter->dnld_cmd_in_secs = 0; /* PnP and power profile */ pmadapter->surprise_removed = MFALSE; /* FW hang report */ pmadapter->fw_hang_report = MFALSE; + pmadapter->ecsa_enable = MFALSE; + pmadapter->getlog_enable = MFALSE; if (!pmadapter->init_para.ps_mode) { pmadapter->ps_mode = DEFAULT_PS_MODE; @@ -727,7 +764,14 @@ t_void wlan_init_adapter(pmlan_adapter pmadapter) memset(pmadapter, pmadapter->pscan_table, 0, (sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST)); pmadapter->active_scan_triggered = MFALSE; - pmadapter->ext_scan = EXT_SCAN_TYPE_ENH; + if (!pmadapter->init_para.ext_scan) + pmadapter->ext_scan = EXT_SCAN_TYPE_ENH; + else if (pmadapter->init_para.ext_scan == EXT_SCAN_TYPE_ENH) + pmadapter->ext_scan = EXT_SCAN_TYPE_ENH; + else + pmadapter->ext_scan = MTRUE; + pmadapter->ext_scan_enh = MFALSE; + pmadapter->ext_scan_timeout = MFALSE; pmadapter->scan_probes = DEFAULT_PROBES; memset(pmadapter, pmadapter->bcn_buf, 0, pmadapter->bcn_buf_size); @@ -760,6 +804,7 @@ t_void wlan_init_adapter(pmlan_adapter pmadapter) */ pmadapter->pm_wakeup_card_req = MFALSE; + pmadapter->pm_wakeup_timeout = 0; pmadapter->pm_wakeup_fw_try = MFALSE; @@ -871,6 +916,8 @@ t_void wlan_init_adapter(pmlan_adapter pmadapter) memset(pmadapter, &pmadapter->saved_sleep_period, 0, sizeof(pmadapter->saved_sleep_period)); pmadapter->tx_lock_flag = MFALSE; + pmadapter->rx_lock_flag = MFALSE; + pmadapter->main_lock_flag = MFALSE; pmadapter->null_pkt_interval = 0; pmadapter->fw_bands = 0; pmadapter->config_bands = 0; @@ -889,6 +936,11 @@ t_void wlan_init_adapter(pmlan_adapter pmadapter) MRVDRV_DEFAULT_COUNTRY_CODE, COUNTRY_CODE_LEN, COUNTRY_CODE_LEN); pmadapter->bcn_miss_time_out = DEFAULT_BCN_MISS_TIMEOUT; +#ifdef STA_SUPPORT + memset(pmadapter, &pmadapter->arp_filter, 0, + sizeof(pmadapter->arp_filter)); + pmadapter->arp_filter_size = 0; +#endif /* STA_SUPPORT */ #ifdef PCIE if (IS_PCIE(pmadapter->card_type)) { diff --git a/mxm_wifiex/wlan_src/mlan/mlan_ioctl.h b/mxm_wifiex/wlan_src/mlan/mlan_ioctl.h index a9d3c79..0aa139c 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_ioctl.h +++ b/mxm_wifiex/wlan_src/mlan/mlan_ioctl.h @@ -298,6 +298,7 @@ enum _mlan_ioctl_req_id { MLAN_OID_MISC_COALESCE_CFG = 0x0020002E, MLAN_OID_MISC_TDLS_IDLE_TIME = 0x0020002F, MLAN_OID_MISC_GET_SENSOR_TEMP = 0x00200030, + MLAN_OID_MISC_IPV6_RA_OFFLOAD = 0x00200036, MLAN_OID_MISC_GTK_REKEY_OFFLOAD = 0x00200037, MLAN_OID_MISC_OPER_CLASS = 0x00200038, MLAN_OID_MISC_PMIC_CFG = 0x00200039, @@ -340,6 +341,11 @@ enum _mlan_ioctl_req_id { MLAN_OID_MISC_TP_STATE = 0x0020007D, MLAN_OID_MISC_HAL_PHY_CFG = 0x0020007E, MLAN_OID_MISC_RF_TEST_HE_POWER = 0X0020007F, +#ifdef UAP_SUPPORT + MLAN_OID_MISC_WACP_MODE = 0x00200081, +#endif + MLAN_OID_MISC_GPIO_TSF_LATCH = 0x00200082, + MLAN_OID_MISC_GET_TSF_INFO = 0x00200083, }; /** Sub command size */ @@ -1646,6 +1652,14 @@ typedef struct _mlan_ds_get_stats { t_u32 dwMgtErrCnt; /*Control Ownership error count*/ t_u32 dwDatErrCnt; + /*BIGTK MME good count*/ + t_u32 bigtk_mmeGoodCnt; + /*BIGTK Replay error count*/ + t_u32 bigtk_replayErrCnt; + /*BIGTK MIC error count*/ + t_u32 bigtk_micErrCnt; + /*BIGTK MME not included count*/ + t_u32 bigtk_mmeNotFoundCnt; } mlan_ds_get_stats, *pmlan_ds_get_stats; /** Type definition of mlan_ds_uap_stats for MLAN_OID_GET_STATS */ @@ -1827,6 +1841,8 @@ typedef struct _mlan_fw_info { t_u8 max_ap_assoc_sta; /** Bandwidth not support 80Mhz */ t_u8 prohibit_80mhz; + /** FW support beacon protection */ + t_u8 fw_beacon_prot; } mlan_fw_info, *pmlan_fw_info; /** Version string buffer length */ @@ -1844,6 +1860,14 @@ typedef struct _mlan_ver_ext { /** Extended Capabilities Data */ typedef struct MLAN_PACK_START _ExtCap_t { /** Extended Capabilities value */ + t_u8 rsvdBit87 : 1; /* bit 87 */ + t_u8 rsvdBit86 : 1; /* bit 86 */ + t_u8 rsvdBit85 : 1; /* bit 85 */ + t_u8 beacon_prot : 1; /* bit 84 */ + t_u8 rsvdBit83 : 1; /* bit 83 */ + t_u8 rsvdBit82 : 1; /* bit 82 */ + t_u8 rsvdBit81 : 1; /* bit 81 */ + t_u8 rsvdBit80 : 1; /* bit 80 */ t_u8 rsvdBit79 : 1; /* bit 79 */ t_u8 TWTResp : 1; /* bit 78 */ t_u8 TWTReq : 1; /* bit 77 */ @@ -2009,6 +2033,14 @@ typedef struct MLAN_PACK_START _ExtCap_t { t_u8 TWTReq : 1; /* bit 77 */ t_u8 TWTResp : 1; /* bit 78 */ t_u8 rsvdBit79 : 1; /* bit 79 */ + t_u8 rsvdBit80 : 1; /* bit 80 */ + t_u8 rsvdBit81 : 1; /* bit 81 */ + t_u8 rsvdBit82 : 1; /* bit 82 */ + t_u8 rsvdBit83 : 1; /* bit 83 */ + t_u8 beacon_prot : 1; /* bit 84 */ + t_u8 rsvdBit85 : 1; /* bit 85 */ + t_u8 rsvdBit86 : 1; /* bit 86 */ + t_u8 rsvdBit87 : 1; /* bit 87 */ } MLAN_PACK_END ExtCap_t, *pExtCap_t; #endif @@ -2215,7 +2247,7 @@ typedef struct _mlan_debug_info { /** Corresponds to port_open member of mlan_private */ t_u8 port_open; /** bypass pkt count */ - t_u16 bypass_pkt_count; + t_u32 bypass_pkt_count; /** Corresponds to scan_processing member of mlan_adapter */ t_u32 scan_processing; /** Corresponds to mlan_processing member of mlan_adapter */ @@ -2265,6 +2297,10 @@ typedef struct _mlan_debug_info { t_u32 mpa_sent_no_ports; /** last recv wr_bitmap */ t_u32 last_recv_wr_bitmap; + /** last recv rd_bitmap */ + t_u32 last_recv_rd_bitmap; + /** mp_data_port_mask */ + t_u32 mp_data_port_mask; /** last mp_wr_bitmap */ t_u32 last_mp_wr_bitmap[SDIO_MP_DBG_NUM]; /** last ports for cmd53 write data */ @@ -2480,7 +2516,7 @@ typedef enum { AssocAgentAuth_FastBss, AssocAgentAuth_FastBss_Skip, AssocAgentAuth_Network_EAP, - AssocAgentAuth_Wpa3Sae, + AssocAgentAuth_Wpa3Sae = 6, AssocAgentAuth_Auto, } AssocAgentAuthType_e; @@ -2549,6 +2585,10 @@ enum _mlan_psk_type { #define KEY_FLAG_GCMP_256 0x00000040 /** key flag for ccmp 256 */ #define KEY_FLAG_CCMP_256 0x00000080 +/** key flag for GMAC_128 */ +#define KEY_FLAG_GMAC_128 0x00000100 +/** key flag for GMAC_256 */ +#define KEY_FLAG_GMAC_256 0x00000200 /** Type definition of mlan_ds_encrypt_key for MLAN_OID_SEC_CFG_ENCRYPT_KEY */ typedef struct _mlan_ds_encrypt_key { @@ -4219,6 +4259,9 @@ typedef struct _mlan_ds_11h_cfg { /** Enumeration for IE type */ enum _mlan_ie_type { MLAN_IE_TYPE_GEN_IE = 0, +#ifdef STA_SUPPORT + MLAN_IE_TYPE_ARP_FILTER, +#endif /* STA_SUPPORT */ }; /** Type definition of mlan_ds_misc_gen_ie for MLAN_OID_MISC_GEN_IE */ @@ -4376,6 +4419,8 @@ typedef struct _mlan_ds_misc_cck_desense_cfg { #define IPADDR_TYPE_IPV4 (1) /** IP operation remove */ #define MLAN_IPADDR_OP_IP_REMOVE (0) +/** IP operation ARP filter */ +#define MLAN_IPADDR_OP_ARP_FILTER MBIT(0) /** IP operation ARP response */ #define MLAN_IPADDR_OP_AUTO_ARP_RESP MBIT(1) @@ -4391,6 +4436,14 @@ typedef struct _mlan_ds_misc_ipaddr_cfg { t_u8 ip_addr[MAX_IPADDR][IPADDR_LEN]; } mlan_ds_misc_ipaddr_cfg; +/** Type definnition of mlan_ds_misc_ipv6_ra_offload for + * MLAN_OID_MISC_IPV6_RA_OFFLOAD*/ +typedef struct _mlan_ds_misc_ipv6_ra_offload { + /** 0: disable; 1: enable*/ + t_u8 enable; + t_u8 ipv6_addr[16]; +} mlan_ds_misc_ipv6_ra_offload; + /* MEF configuration disable */ #define MEF_CFG_DISABLE 0 /* MEF configuration Rx filter enable */ @@ -4647,6 +4700,33 @@ typedef struct _mlan_ds_wifi_direct_config { } mlan_ds_wifi_direct_config; #endif +/** Type definition of mlan_ds_gpio_tsf_latch */ +typedef struct _mlan_ds_gpio_tsf_latch { + /**clock sync Mode */ + t_u8 clock_sync_mode; + /**clock sync Role */ + t_u8 clock_sync_Role; + /**clock sync GPIO Pin Number */ + t_u8 clock_sync_gpio_pin_number; + /**clock sync GPIO Level or Toggle */ + t_u8 clock_sync_gpio_level_toggle; + /**clock sync GPIO Pulse Width */ + t_u16 clock_sync_gpio_pulse_width; +} mlan_ds_gpio_tsf_latch; + +/** Type definition of mlan_ds_tsf_info */ +typedef struct _mlan_ds_tsf_info { + /**get tsf info format */ + t_u16 tsf_format; + /**tsf info */ + t_u16 tsf_info; + /**tsf */ + t_u64 tsf; + /**Positive or negative offset in microsecond from Beacon TSF to GPIO + * toggle TSF */ + t_s32 tsf_offset; +} mlan_ds_tsf_info; + #if defined(STA_SUPPORT) typedef struct _mlan_ds_misc_pmfcfg { /** Management Frame Protection Capable */ @@ -4851,6 +4931,8 @@ typedef struct _mef_entry_t { typedef struct _mlan_ds_misc_mef_flt_cfg { /** Type of action*/ int mef_act_type; + /** Operation code*/ + t_u32 op_code; /** NV Filter Criteria*/ t_u32 criteria; /** NV MEF entry*/ @@ -5236,6 +5318,8 @@ typedef struct _mlan_ds_misc_cfg { mlan_ds_misc_tx_datapause tx_datapause; /** IP address configuration */ mlan_ds_misc_ipaddr_cfg ipaddr_cfg; + /** IPv6 Router Advertisement offload configuration */ + mlan_ds_misc_ipv6_ra_offload ipv6_ra_offload; /** MAC control for MLAN_OID_MISC_MAC_CONTROL */ t_u32 mac_ctrl; /** MEF configuration for MLAN_OID_MISC_MEF_CFG */ @@ -5274,6 +5358,8 @@ typedef struct _mlan_ds_misc_cfg { #ifdef WIFI_DIRECT_SUPPORT mlan_ds_wifi_direct_config p2p_config; #endif + mlan_ds_gpio_tsf_latch gpio_tsf_latch_config; + mlan_ds_tsf_info tsf_info; mlan_ds_coalesce_cfg coalesce_cfg; t_u8 low_pwr_mode; /** MEF-FLT-CONFIG for MLAN_OID_MISC_NV_FLT_CFG */ @@ -5325,6 +5411,9 @@ typedef struct _mlan_ds_misc_cfg { mlan_ds_misc_dot11mc_unassoc_ftm_cfg dot11mc_unassoc_ftm_cfg; mlan_ds_misc_tp_state tp_state; mlan_ds_hal_phy_cfg_params hal_phy_cfg_params; +#ifdef UAP_SUPPORT + t_u8 wacp_mode; +#endif } param; } mlan_ds_misc_cfg, *pmlan_ds_misc_cfg; diff --git a/mxm_wifiex/wlan_src/mlan/mlan_join.c b/mxm_wifiex/wlan_src/mlan/mlan_join.c index 080ca90..4a1377d 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_join.c +++ b/mxm_wifiex/wlan_src/mlan/mlan_join.c @@ -1360,14 +1360,21 @@ mlan_status wlan_ret_802_11_associate(mlan_private *pmpriv, mlan_adapter *pmadapter = pmpriv->adapter; assoc_logger_data *assoc_succ; mlan_ds_bss *bss; + IEEEtypes_MgmtHdr_t *hdr; ENTER(); - if (pmpriv->curr_bss_params.host_mlme) - passoc_rsp = - (IEEEtypes_AssocRsp_t *)((t_u8 *)(&resp->params) + + if (pmpriv->curr_bss_params.host_mlme) { + hdr = (IEEEtypes_MgmtHdr_t *)&resp->params; + if (!memcmp(pmpriv->adapter, hdr->BssId, + pmpriv->pattempted_bss_desc->mac_address, + MLAN_MAC_ADDR_LENGTH)) + passoc_rsp = (IEEEtypes_AssocRsp_t + *)((t_u8 *)(&resp->params) + sizeof(IEEEtypes_MgmtHdr_t)); - else + else + passoc_rsp = (IEEEtypes_AssocRsp_t *)&resp->params; + } else passoc_rsp = (IEEEtypes_AssocRsp_t *)&resp->params; passoc_rsp->status_code = wlan_le16_to_cpu(passoc_rsp->status_code); @@ -1432,7 +1439,6 @@ mlan_status wlan_ret_802_11_associate(mlan_private *pmpriv, /* Send a Media Connected event, according to the Spec */ pmpriv->media_connected = MTRUE; - pmpriv->adapter->pps_uapsd_mode = MFALSE; pmpriv->adapter->tx_lock_flag = MFALSE; pmpriv->adapter->delay_null_pkt = MFALSE; diff --git a/mxm_wifiex/wlan_src/mlan/mlan_main.h b/mxm_wifiex/wlan_src/mlan/mlan_main.h index e7b738c..c024b3f 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_main.h +++ b/mxm_wifiex/wlan_src/mlan/mlan_main.h @@ -402,6 +402,11 @@ extern t_void (*assert_callback)(t_void *pmoal_handle, t_u32 cond); /** Maximum event buffer size */ #define MAX_EVENT_SIZE (3 * 1024) +#ifdef STA_SUPPORT +/** Maximum buffer size for ARP filter */ +#define ARP_FILTER_MAX_BUF_SIZE 68 +#endif /* STA_SUPPORT */ + /** 60 seconds */ #define MRVDRV_TIMER_60S 60000 /** 10 seconds */ @@ -1817,6 +1822,8 @@ typedef struct _mef_cfg_data { /** Type definition of mef_entry*/ typedef struct _mef_entry { + /** Flag for auto arp entry*/ + int enable_autoarp_entry; /** Num for wowlan entry*/ int num_wowlan_entry; /** Num for IPv6 neighbor solicitation message offload */ @@ -1892,6 +1899,7 @@ typedef struct _mlan_init_para { /** adma ring size */ t_u16 ring_size; #endif + t_u8 ext_scan; } mlan_init_para, *pmlan_init_para; #ifdef SDIO @@ -2018,6 +2026,8 @@ typedef struct _mlan_sdio_card { t_u32 mpa_sent_no_ports; /** last wr_bitmap from FW */ t_u32 last_recv_wr_bitmap; + /** last wr_bitmap from FW */ + t_u32 last_recv_rd_bitmap; /** last mp_wr_bitmap */ t_u32 last_mp_wr_bitmap[SDIO_MP_DBG_NUM]; /** last ports for cmd53 write data */ @@ -2265,6 +2275,10 @@ typedef struct _adapter_operations { pmlan_buffer pmbuf); /** handle dump interface specific info */ mlan_status (*debug_dump)(mlan_adapter *pmadapter); + /** disable host interrupt */ + mlan_status (*disable_host_int)(mlan_adapter *pmadapter); + /** enable host interrupt */ + mlan_status (*enable_host_int)(mlan_adapter *pmadapter); /**Interface header length*/ t_u32 intf_header_len; } mlan_adapter_operations; @@ -2405,8 +2419,6 @@ typedef struct _mlan_adapter { * FALSE - No cmd response to process */ t_u8 cmd_resp_received; - /** block download cmd to firmware */ - t_u8 cmd_lock; /** Event received: * TRUE - Event received from fw, and yet to process * FALSE - No events to process @@ -2687,6 +2699,12 @@ typedef struct _mlan_adapter { /** RX pending for forwarding packets */ mlan_scalar pending_bridge_pkts; +#ifdef STA_SUPPORT + /** ARP filter buffer */ + t_u8 arp_filter[ARP_FILTER_MAX_BUF_SIZE]; + /** ARP filter buffer size */ + t_u32 arp_filter_size; +#endif /* STA_SUPPORT */ /** Minimum delay between HsActive and HostWake (in msec) */ t_u16 min_wake_holdoff; /** Host sleep wake interval(in msec) */ @@ -2714,7 +2732,7 @@ typedef struct _mlan_adapter { /** management frame wakeup filter config */ mlan_mgmt_frame_wakeup mgmt_filter[MAX_MGMT_FRAME_FILTER]; /** Bypass TX queue pkt count */ - t_u16 bypass_pkt_count; + t_u32 bypass_pkt_count; #ifdef STA_SUPPORT /** warm-reset IOCTL request buffer pointer */ pmlan_ioctl_req pwarm_reset_ioctl_req; @@ -2901,6 +2919,7 @@ t_void wlan_release_cmd_lock(mlan_adapter *pmadapter); #ifdef STA_SUPPORT /** Flush the scan pending queue */ t_void wlan_flush_scan_queue(pmlan_adapter pmadapter); +t_void wlan_move_cmd_to_cmd_pending_q(pmlan_adapter pmadapter); mlan_status wlan_cancel_pending_scan_cmd(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req); #endif @@ -3118,6 +3137,17 @@ mlan_status wlan_ret_p2p_params_config(pmlan_private pmpriv, mlan_status wlan_misc_p2p_config(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req); #endif +mlan_status wlan_cmd_gpio_tsf_latch(pmlan_private pmpriv, + HostCmd_DS_COMMAND *cmd, t_u16 cmd_action, + mlan_ioctl_req *pioctl_buf, + t_void *pdata_buf); +mlan_status wlan_ret_gpio_tsf_latch(pmlan_private pmpriv, + HostCmd_DS_COMMAND *resp, + mlan_ioctl_req *pioctl_buf); +mlan_status wlan_misc_gpio_tsf_latch_config(pmlan_adapter pmadapter, + pmlan_ioctl_req pioctl_req); +mlan_status wlan_misc_get_tsf_info(pmlan_adapter pmadapter, + pmlan_ioctl_req pioctl_req); /** get ralist info */ int wlan_get_ralist_info(mlan_private *priv, pralist_info buf); /** dump ralist */ @@ -3804,6 +3834,7 @@ mlan_status wlan_set_drvdbg(pmlan_adapter pmadapter, mlan_status wlan_misc_hotspot_cfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req); + #ifdef STA_SUPPORT mlan_status wlan_misc_ext_capa_cfg(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req); @@ -3986,6 +4017,12 @@ mlan_status wlan_cmd_config_dyn_bw(pmlan_private pmpriv, mlan_status wlan_ret_dyn_bw(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp, mlan_ioctl_req *pioctl_buf); +#ifdef UAP_SUPPORT +/** wacp mode misc ioctl */ +mlan_status wlan_misc_ioctl_wacp_mode(pmlan_adapter pmadapter, + mlan_ioctl_req *pioctl_req); +#endif + mlan_status wlan_power_ioctl_set_get_lpm(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req); mlan_status wlan_cmd_set_get_low_power_mode_cfg(pmlan_private pmpriv, diff --git a/mxm_wifiex/wlan_src/mlan/mlan_misc.c b/mxm_wifiex/wlan_src/mlan/mlan_misc.c index 66f7d13..c2db6da 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_misc.c +++ b/mxm_wifiex/wlan_src/mlan/mlan_misc.c @@ -531,6 +531,10 @@ mlan_status wlan_get_info_debug_info(pmlan_adapter pmadapter, pmadapter->pcard_sd->mpa_sent_no_ports; debug_info->last_recv_wr_bitmap = pmadapter->pcard_sd->last_recv_wr_bitmap; + debug_info->last_recv_rd_bitmap = + pmadapter->pcard_sd->last_recv_rd_bitmap; + debug_info->mp_data_port_mask = + pmadapter->pcard_sd->mp_data_port_mask; debug_info->last_mp_index = pmadapter->pcard_sd->last_mp_index; memcpy_ext( @@ -1769,11 +1773,8 @@ sta_node *wlan_get_station_entry(mlan_private *priv, t_u8 *mac) sta_node *wlan_add_station_entry(mlan_private *priv, t_u8 *mac) { sta_node *sta_ptr = MNULL; - mlan_adapter *pmadapter = priv->adapter; ENTER(); - pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, - priv->wmm.ra_list_spinlock); sta_ptr = wlan_get_station_entry(priv, mac); if (sta_ptr) @@ -1782,8 +1783,6 @@ sta_node *wlan_add_station_entry(mlan_private *priv, t_u8 *mac) sizeof(sta_node), MLAN_MEM_DEF, (t_u8 **)&sta_ptr)) { PRINTM(MERROR, "Failed to allocate memory for station node\n"); - pmadapter->callbacks.moal_spin_unlock( - pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock); LEAVE(); return MNULL; } @@ -1791,7 +1790,9 @@ sta_node *wlan_add_station_entry(mlan_private *priv, t_u8 *mac) memcpy_ext(priv->adapter, sta_ptr->mac_addr, mac, MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH); util_enqueue_list_tail(priv->adapter->pmoal_handle, &priv->sta_list, - (pmlan_linked_list)sta_ptr, MNULL, MNULL); + (pmlan_linked_list)sta_ptr, + priv->adapter->callbacks.moal_spin_lock, + priv->adapter->callbacks.moal_spin_unlock); #ifdef DRV_EMBEDDED_AUTHENTICATOR if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) && IsAuthenticatorEnabled(priv->psapriv)) @@ -1799,8 +1800,6 @@ sta_node *wlan_add_station_entry(mlan_private *priv, t_u8 *mac) &sta_ptr->cm_connectioninfo, mac); #endif done: - pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, - priv->wmm.ra_list_spinlock); LEAVE(); return sta_ptr; } @@ -1817,10 +1816,7 @@ done: t_void wlan_delete_station_entry(mlan_private *priv, t_u8 *mac) { sta_node *sta_ptr = MNULL; - mlan_adapter *pmadapter = priv->adapter; ENTER(); - pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, - priv->wmm.ra_list_spinlock); sta_ptr = wlan_get_station_entry(priv, mac); if (sta_ptr) { #ifdef DRV_EMBEDDED_AUTHENTICATOR @@ -1830,12 +1826,13 @@ t_void wlan_delete_station_entry(mlan_private *priv, t_u8 *mac) sta_ptr->cm_connectioninfo); #endif util_unlink_list(priv->adapter->pmoal_handle, &priv->sta_list, - (pmlan_linked_list)sta_ptr, MNULL, MNULL); + (pmlan_linked_list)sta_ptr, + priv->adapter->callbacks.moal_spin_lock, + priv->adapter->callbacks.moal_spin_unlock); priv->adapter->callbacks.moal_mfree(priv->adapter->pmoal_handle, (t_u8 *)sta_ptr); } - pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, - priv->wmm.ra_list_spinlock); + LEAVE(); return; } @@ -3404,15 +3401,15 @@ mlan_status wlan_process_802dot11_mgmt_pkt(mlan_private *priv, t_u8 *payload, #endif if (priv->bss_role == MLAN_BSS_ROLE_STA) { if (priv->curr_bss_params.host_mlme) { - if (memcmp(pmadapter, pieee_pkt_hdr->addr2, + if (memcmp(pmadapter, pieee_pkt_hdr->addr3, (t_u8 *)priv->curr_bss_params .bss_descriptor.mac_address, MLAN_MAC_ADDR_LENGTH)) { - PRINTM(MINFO, - "Dropping mgmt frame from others: type=%d " MACSTR + PRINTM(MCMND, + "Dropping Deauth frame from other bssid: type=%d " MACSTR "\n", sub_type, - MAC2STR(pieee_pkt_hdr->addr2)); + MAC2STR(pieee_pkt_hdr->addr3)); LEAVE(); return ret; } @@ -4865,6 +4862,75 @@ mlan_status wlan_misc_p2p_config(pmlan_adapter pmadapter, } #endif +/** + * @brief Set/Get GPIO TSF Latch config + * + * @param pmadapter A pointer to mlan_adapter structure + * @param pioctl_req A pointer to ioctl request buffer + * + * @return MLAN_STATUS_SUCCESS --success, otherwise fail + */ +mlan_status wlan_misc_gpio_tsf_latch_config(pmlan_adapter pmadapter, + pmlan_ioctl_req pioctl_req) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + mlan_ds_misc_cfg *misc_cfg = MNULL; + t_u16 cmd_action = 0; + mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; + + ENTER(); + + misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf; + if (pioctl_req->action == MLAN_ACT_SET) + cmd_action = HostCmd_ACT_GEN_SET; + else + cmd_action = HostCmd_ACT_GEN_GET; + + /* Send request to firmware */ + ret = wlan_prepare_cmd(pmpriv, HOST_CMD_GPIO_TSF_LATCH_PARAM_CONFIG, + cmd_action, 0, (t_void *)pioctl_req, + &misc_cfg->param.gpio_tsf_latch_config); + + if (ret == MLAN_STATUS_SUCCESS) + ret = MLAN_STATUS_PENDING; + + LEAVE(); + return ret; +} + +/** + * @brief Get TSF info + * + * @param pmadapter A pointer to mlan_adapter structure + * @param pioctl_req A pointer to ioctl request buffer + * + * @return MLAN_STATUS_SUCCESS --success, otherwise fail + */ +mlan_status wlan_misc_get_tsf_info(pmlan_adapter pmadapter, + pmlan_ioctl_req pioctl_req) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + mlan_ds_misc_cfg *misc_cfg = MNULL; + t_u16 cmd_action = 0; + mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; + + ENTER(); + + misc_cfg = (mlan_ds_misc_cfg *)pioctl_req->pbuf; + cmd_action = HostCmd_ACT_GEN_GET; + + /* Send request to firmware */ + ret = wlan_prepare_cmd(pmpriv, HOST_CMD_GPIO_TSF_LATCH_PARAM_CONFIG, + cmd_action, 0, (t_void *)pioctl_req, + &misc_cfg->param.tsf_info); + + if (ret == MLAN_STATUS_SUCCESS) + ret = MLAN_STATUS_PENDING; + + LEAVE(); + return ret; +} + /** * @brief Set coalesce config * @@ -5689,6 +5755,7 @@ mlan_status wlan_process_mef_cfg_cmd(mlan_private *pmpriv, /** check how many entries in adapter*/ pmef = &pmadapter->entry_cfg; + entry_num += pmef->enable_autoarp_entry; entry_num += pmef->num_wowlan_entry; entry_num += pmef->num_ipv6_ns_offload; if (!entry_num) { @@ -5710,6 +5777,12 @@ mlan_status wlan_process_mef_cfg_cmd(mlan_private *pmpriv, memset(pmadapter, mef.pentry, 0, sizeof(mef_entry_t) * entry_num); pentry = mef.pentry; /** Fill mef_entry_t structure*/ + /** Copy Auto arp response entry*/ + if (pmef->enable_autoarp_entry) { + memcpy_ext(pmadapter, pentry, &pmef->entry[5], + sizeof(mef_entry_t), sizeof(mef_entry_t)); + pentry += pmef->enable_autoarp_entry; + } /** Copy wowlan entry*/ if (pmef->num_wowlan_entry) { memcpy_ext(pmadapter, pentry, &pmef->entry[6], @@ -5770,6 +5843,29 @@ mlan_status wlan_misc_ioctl_mef_flt_cfg(pmlan_adapter pmadapter, &mef_cfg->mef_entry, sizeof(mef_entry_t), sizeof(mef_entry_t)); } + /** Set AUTO ARP Entry to adapter*/ + if (mef_cfg->mef_act_type == MEF_ACT_AUTOARP) { + if (mef_cfg->op_code & MLAN_IPADDR_OP_AUTO_ARP_RESP) { + pmef->enable_autoarp_entry = 1; + pmef->criteria |= mef_cfg->criteria; + memcpy_ext(pmadapter, &pmef->entry[5], + &mef_cfg->mef_entry, + sizeof(mef_entry_t), + sizeof(mef_entry_t)); + if (MLAN_STATUS_SUCCESS != + wlan_process_mef_cfg_cmd( + pmadapter + ->priv[pioctl_req->bss_index], + pmadapter)) + PRINTM(MERROR, + "Set MEF Entries Error\n"); + } else if (mef_cfg->op_code & + MLAN_IPADDR_OP_IP_REMOVE) { + pmef->enable_autoarp_entry = 0; + memset(pmadapter, &pmef->entry[5], 0, + sizeof(mef_entry_t)); + } + } break; case MLAN_ACT_GET: if (mef_cfg->mef_act_type == MEF_ACT_WOWLAN) @@ -6800,3 +6896,41 @@ mlan_status wlan_misc_ioctl_range_ext(pmlan_adapter pmadapter, LEAVE(); return ret; } + +#ifdef UAP_SUPPORT +/** + * @brief set wacp mode + * + * @param pmadapter A pointer to mlan_adapter structure + * @param pioctl_req A pointer to ioctl request buffer + * + * @return MLAN_STATUS_PENDING --success, otherwise fail + */ +mlan_status wlan_misc_ioctl_wacp_mode(IN pmlan_adapter pmadapter, + IN pmlan_ioctl_req pioctl_req) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; + mlan_ds_misc_cfg *misc = MNULL; + t_u16 cmd_action; + + ENTER(); + + misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf; + + if (pioctl_req->action == MLAN_ACT_SET) + cmd_action = HostCmd_ACT_GEN_SET; + else + cmd_action = HostCmd_ACT_GEN_GET; + + ret = wlan_prepare_cmd(pmpriv, HOST_CMD_APCMD_SYS_CONFIGURE, cmd_action, + 0, (t_void *)pioctl_req, + (t_void *)&misc->param.wacp_mode); + + if (ret == MLAN_STATUS_SUCCESS) + ret = MLAN_STATUS_PENDING; + + LEAVE(); + return ret; +} +#endif diff --git a/mxm_wifiex/wlan_src/mlan/mlan_module.c b/mxm_wifiex/wlan_src/mlan/mlan_module.c index c890666..67a6d7a 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_module.c +++ b/mxm_wifiex/wlan_src/mlan/mlan_module.c @@ -57,6 +57,8 @@ EXPORT_SYMBOL(mlan_is_main_process_running); #ifdef PCIE EXPORT_SYMBOL(mlan_set_int_mode); #endif +EXPORT_SYMBOL(mlan_disable_host_int); +EXPORT_SYMBOL(mlan_enable_host_int); MODULE_DESCRIPTION("M-WLAN MLAN Driver"); MODULE_AUTHOR("NXP"); diff --git a/mxm_wifiex/wlan_src/mlan/mlan_scan.c b/mxm_wifiex/wlan_src/mlan/mlan_scan.c index cce5986..4fcd638 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_scan.c +++ b/mxm_wifiex/wlan_src/mlan/mlan_scan.c @@ -46,7 +46,7 @@ Change log: /** minimum scan time for passive to active scan */ #define MIN_PASSIVE_TO_ACTIVE_SCAN_TIME 150 -#define MRVDRV_MAX_CHANNELS_PER_SCAN 40 +#define MRVDRV_MAX_CHANNELS_PER_SCAN 38 /** The maximum number of channels the firmware can scan per command */ #define MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN 4 @@ -4832,7 +4832,6 @@ mlan_status wlan_cmd_802_11_scan_ext(mlan_private *pmpriv, (t_u16)(sizeof(pext_scan_cmd->reserved)) + S_DS_GEN)); pext_scan_cmd->ext_scan_type = EXT_SCAN_CANCEL; - pmpriv->adapter->cmd_lock = MFALSE; LEAVE(); return MLAN_STATUS_SUCCESS; } @@ -4902,7 +4901,6 @@ mlan_status wlan_ret_802_11_scan_ext(mlan_private *pmpriv, LEAVE(); return MLAN_STATUS_SUCCESS; } else if (ext_scan_type == EXT_SCAN_ENHANCE) { - pmpriv->adapter->cmd_lock = MTRUE; /* Setup the timer after scan command response */ pcb->moal_start_timer(pmpriv->adapter->pmoal_handle, pmpriv->adapter->pmlan_cmd_timer, MFALSE, @@ -5902,6 +5900,7 @@ done: MLAN_STATUS_SUCCESS); } wlan_release_cmd_lock(pmadapter); + wlan_move_cmd_to_cmd_pending_q(pmadapter); pmadapter->bgscan_reported = MFALSE; wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_SCAN_REPORT, MNULL); LEAVE(); diff --git a/mxm_wifiex/wlan_src/mlan/mlan_sdio.c b/mxm_wifiex/wlan_src/mlan/mlan_sdio.c index f0dab5e..ab0bc8a 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_sdio.c +++ b/mxm_wifiex/wlan_src/mlan/mlan_sdio.c @@ -290,6 +290,7 @@ static const struct _mlan_sdio_card_reg mlan_reg_sd8977_sd8997 = { .winner_check_reg = 0xFC, }; #endif + #ifdef SD8997 static const struct _mlan_card_info mlan_card_info_sd8997 = { .max_tx_buf_size = MLAN_TX_DATA_BUF_SIZE_4K, @@ -1235,6 +1236,8 @@ static mlan_status wlan_decode_rx_packet(mlan_adapter *pmadapter, { t_u8 *cmd_buf; t_u32 event; + t_u32 in_ts_sec, in_ts_usec; + pmlan_callbacks pcb = &pmadapter->callbacks; ENTER(); @@ -1277,19 +1280,43 @@ static mlan_status wlan_decode_rx_packet(mlan_adapter *pmadapter, pmbuf->data_len = (pmadapter->upld_len - SDIO_INTF_HEADER_LEN); pmbuf->data_offset += SDIO_INTF_HEADER_LEN; if (pmadapter->rx_work_flag) { - if (lock_flag) - pmadapter->callbacks.moal_spin_lock( + // rx_trace 5 + if (pmadapter->tp_state_on) { + pmadapter->callbacks.moal_tp_accounting( + pmadapter->pmoal_handle, pmbuf, + 5 /*RX_DROP_P1*/); + pcb->moal_get_system_time( + pmadapter->pmoal_handle, &in_ts_sec, + &in_ts_usec); + pmbuf->in_ts_sec = in_ts_sec; + pmbuf->in_ts_usec = in_ts_usec; + } + if (pmadapter->tp_state_drop_point == + 5 /*RX_DROP_P1*/) { + pmadapter->ops.data_complete( + pmadapter, pmbuf, MLAN_STATUS_SUCCESS); + } else { + if (lock_flag) + pmadapter->callbacks.moal_spin_lock( + pmadapter->pmoal_handle, + pmadapter->rx_data_queue.plock); + util_enqueue_list_tail( pmadapter->pmoal_handle, - pmadapter->rx_data_queue.plock); - util_enqueue_list_tail(pmadapter->pmoal_handle, - &pmadapter->rx_data_queue, - (pmlan_linked_list)pmbuf, MNULL, - MNULL); - pmadapter->rx_pkts_queued++; - if (lock_flag) - pmadapter->callbacks.moal_spin_unlock( - pmadapter->pmoal_handle, - pmadapter->rx_data_queue.plock); + &pmadapter->rx_data_queue, + (pmlan_linked_list)pmbuf, MNULL, MNULL); + pmadapter->rx_pkts_queued++; + if (pmadapter->tp_state_on) + pmadapter->callbacks + .moal_tp_accounting_rx_param( + pmadapter->pmoal_handle, + 1, + pmadapter + ->rx_pkts_queued); + if (lock_flag) + pmadapter->callbacks.moal_spin_unlock( + pmadapter->pmoal_handle, + pmadapter->rx_data_queue.plock); + } } else { wlan_handle_rx_packet(pmadapter, pmbuf); } @@ -2397,6 +2424,80 @@ mlan_status wlan_get_sdio_device(pmlan_adapter pmadapter) return ret; } +/** + * @brief This function dump the mp registers when issue happened + * + * @param pmadapter A pointer to mlan_adapter structure + * @return N/A + */ +void wlan_dump_mp_registers(pmlan_adapter pmadapter) +{ + t_u32 mp_wr_bitmap; + t_bool new_mode = pmadapter->pcard_sd->supports_sdio_new_mode; + t_u32 mp_rd_bitmap; + t_u16 rx_len = 0; + const mlan_sdio_card_reg *reg = pmadapter->pcard_sd->reg; + t_u8 cmd_rd_len_0 = reg->cmd_rd_len_0; + t_u8 cmd_rd_len_1 = reg->cmd_rd_len_1; + t_u8 host_int_status_reg = reg->host_int_status_reg; + t_u32 sdio_ireg = 0; + + mp_wr_bitmap = (t_u32)pmadapter->pcard_sd->mp_regs[reg->wr_bitmap_l]; + mp_wr_bitmap |= ((t_u32)pmadapter->pcard_sd->mp_regs[reg->wr_bitmap_u]) + << 8; + if (new_mode) { + mp_wr_bitmap |= + ((t_u32)pmadapter->pcard_sd->mp_regs[reg->wr_bitmap_1l]) + << 16; + mp_wr_bitmap |= + ((t_u32)pmadapter->pcard_sd->mp_regs[reg->wr_bitmap_1u]) + << 24; + } + PRINTM(MMSG, "wlan: mp_data_port_mask = 0x%x\n", + pmadapter->pcard_sd->mp_data_port_mask); + PRINTM(MMSG, "wlan: HW wr_bitmap=0x%08x Host: wr_bitmap=0x%08x\n", + mp_wr_bitmap, pmadapter->pcard_sd->mp_wr_bitmap); + mp_rd_bitmap = (t_u32)pmadapter->pcard_sd->mp_regs[reg->rd_bitmap_l]; + mp_rd_bitmap |= ((t_u32)pmadapter->pcard_sd->mp_regs[reg->rd_bitmap_u]) + << 8; + if (new_mode) { + mp_rd_bitmap |= + ((t_u32)pmadapter->pcard_sd->mp_regs[reg->rd_bitmap_1l]) + << 16; + mp_rd_bitmap |= + ((t_u32)pmadapter->pcard_sd->mp_regs[reg->rd_bitmap_1u]) + << 24; + } + PRINTM(MMSG, "wlan: HW rd_bitmap=0x%08x Host: rd_bitmap=0x%08x\n", + mp_rd_bitmap, pmadapter->pcard_sd->mp_rd_bitmap); + + if (new_mode) { + rx_len = ((t_u16)pmadapter->pcard_sd->mp_regs[cmd_rd_len_1]) + << 8; + rx_len |= (t_u16)pmadapter->pcard_sd->mp_regs[cmd_rd_len_0]; + PRINTM(MMSG, "wlan: cmd rx buffer rx_len = %d\n", rx_len); + } + PRINTM(MMSG, "wlan: HW sdio_ireg = 0x%x\n", + pmadapter->pcard_sd->mp_regs[host_int_status_reg]); + sdio_ireg = pmadapter->pcard_sd->mp_regs[host_int_status_reg]; + + if (new_mode && rx_len) + sdio_ireg |= UP_LD_CMD_PORT_HOST_INT_STATUS; + + if (!(pmadapter->pcard_sd->mp_wr_bitmap & + pmadapter->pcard_sd->mp_data_port_mask)) { + if (mp_wr_bitmap & pmadapter->pcard_sd->mp_data_port_mask) + sdio_ireg |= DN_LD_HOST_INT_STATUS; + } + + if ((!pmadapter->pcard_sd->mp_rd_bitmap) && mp_rd_bitmap) + sdio_ireg |= UP_LD_HOST_INT_STATUS; + + pmadapter->pcard_sd->mp_regs[host_int_status_reg] = sdio_ireg; + PRINTM(MMSG, "wlan: recovered sdio_ireg=0x%x\n", sdio_ireg); + return; +} + /** * @brief This function gets interrupt status. * @@ -2405,10 +2506,12 @@ mlan_status wlan_get_sdio_device(pmlan_adapter pmadapter) */ static mlan_status wlan_sdio_interrupt(t_u16 msg_id, pmlan_adapter pmadapter) { + mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_callbacks pcb = &pmadapter->callbacks; mlan_buffer mbuf; t_u32 sdio_ireg = 0; t_u8 offset = 0; + t_u8 i = 0; int max_mp_regs = pmadapter->pcard_sd->reg->max_mp_regs; t_u8 host_int_status_reg = pmadapter->pcard_sd->reg->host_int_status_reg; @@ -2419,20 +2522,32 @@ static mlan_status wlan_sdio_interrupt(t_u16 msg_id, pmlan_adapter pmadapter) memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer)); mbuf.pbuf = pmadapter->pcard_sd->mp_regs + offset; mbuf.data_len = MIN(max_mp_regs, MLAN_SDIO_BLOCK_SIZE); - - if (MLAN_STATUS_SUCCESS != - pcb->moal_read_data_sync(pmadapter->pmoal_handle, &mbuf, - (REG_PORT + offset) | - MLAN_SDIO_BYTE_MODE_MASK, - 0)) { - PRINTM(MERROR, - "moal_read_data_sync: read registers failed\n"); - pmadapter->dbg.num_int_read_failure++; - goto done; - } + do { + ret = pcb->moal_read_data_sync( + pmadapter->pmoal_handle, &mbuf, + (REG_PORT + offset) | MLAN_SDIO_BYTE_MODE_MASK, + 0); + if (ret != MLAN_STATUS_SUCCESS) { + PRINTM(MERROR, + "wlan: cmd53 read regs failed: %d port=%x retry=%d\n", + ret, REG_PORT + offset, i); + i++; + pcb->moal_write_reg(pmadapter->pmoal_handle, + HOST_TO_CARD_EVENT_REG, + HOST_TERM_CMD53); + if (i > MAX_WRITE_IOMEM_RETRY) { + PRINTM(MERROR, + "wlan: Fail to read mp_regs\n"); + pmadapter->dbg.num_int_read_failure++; + goto done; + } + } + } while (ret == MLAN_STATUS_FAILURE); offset += mbuf.data_len; max_mp_regs -= mbuf.data_len; } + if (i > 0) + wlan_dump_mp_registers(pmadapter); DBG_HEXDUMP(MIF_D, "SDIO MP Registers", pmadapter->pcard_sd->mp_regs, max_mp_regs); @@ -2669,6 +2784,8 @@ static mlan_status wlan_process_sdio_int_status(mlan_adapter *pmadapter) if (pmadapter->data_sent && (pmadapter->pcard_sd->mp_wr_bitmap & (1 << pmadapter->pcard_sd->curr_wr_port))) { + pmadapter->callbacks.moal_tp_accounting_rx_param( + pmadapter->pmoal_handle, 3, 0); PRINTM(MINFO, " <--- Tx DONE Interrupt --->\n"); pmadapter->data_sent = MFALSE; } @@ -2699,8 +2816,13 @@ static mlan_status wlan_process_sdio_int_status(mlan_adapter *pmadapter) ->mp_regs[reg->rd_bitmap_1u]) << 24; } + pmadapter->pcard_sd->last_recv_rd_bitmap = + pmadapter->pcard_sd->mp_rd_bitmap; + PRINTM(MINTR, "UPLD: rd_bitmap=0x%08x\n", pmadapter->pcard_sd->mp_rd_bitmap); + pmadapter->callbacks.moal_tp_accounting_rx_param( + pmadapter->pmoal_handle, 0, 0); while (MTRUE) { ret = wlan_get_rd_port(pmadapter, &port); @@ -3522,6 +3644,8 @@ mlan_adapter_operations mlan_sdio_ops = { .data_complete = wlan_sdio_data_evt_complete, .cmdrsp_complete = wlan_sdio_data_evt_complete, .handle_rx_packet = wlan_sdio_handle_rx_packet, + .disable_host_int = wlan_disable_sdio_host_int, + .enable_host_int = wlan_enable_sdio_host_int, .intf_header_len = SDIO_INTF_HEADER_LEN, }; diff --git a/mxm_wifiex/wlan_src/mlan/mlan_shim.c b/mxm_wifiex/wlan_src/mlan/mlan_shim.c index e4dc13a..9618752 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_shim.c +++ b/mxm_wifiex/wlan_src/mlan/mlan_shim.c @@ -414,6 +414,7 @@ mlan_status mlan_register(pmlan_device pmdevice, t_void **ppmlan_adapter) pmadapter->init_para.mfg_mode = pmdevice->mfg_mode; #endif pmadapter->init_para.auto_ds = pmdevice->auto_ds; + pmadapter->init_para.ext_scan = pmdevice->ext_scan; pmadapter->init_para.ps_mode = pmdevice->ps_mode; if (pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_2K || pmdevice->max_tx_buf == MLAN_TX_DATA_BUF_SIZE_4K || @@ -644,6 +645,74 @@ mlan_status mlan_dnld_fw(t_void *padapter, pmlan_fw_image pmfw) return ret; } +/** + * @brief This function mask host interrupt from firmware + * + * @param padapter A pointer to a t_void pointer to store + * mlan_adapter structure pointer + * + * @return MLAN_STATUS_SUCCESS + * The firmware download succeeded. + * MLAN_STATUS_FAILURE + * The firmware download failed. + */ +mlan_status mlan_disable_host_int(t_void *padapter) +{ + mlan_status ret = MLAN_STATUS_FAILURE; + mlan_adapter *pmadapter = (mlan_adapter *)padapter; + + ENTER(); + MASSERT(padapter); + + /* mask host interrupt from firmware */ + if (pmadapter->ops.disable_host_int) { + ret = pmadapter->ops.disable_host_int(pmadapter); + if (ret != MLAN_STATUS_SUCCESS) { + PRINTM(MERROR, + "mlan_disable_host_int fail ret = 0x%x\n", ret); + LEAVE(); + return ret; + } + } + + LEAVE(); + return ret; +} + +/** + * @brief This function unmask host interrupt from firmware + * + * @param padapter A pointer to a t_void pointer to store + * mlan_adapter structure pointer + * + * @return MLAN_STATUS_SUCCESS + * The firmware download succeeded. + * MLAN_STATUS_FAILURE + * The firmware download failed. + */ +mlan_status mlan_enable_host_int(t_void *padapter) +{ + mlan_status ret = MLAN_STATUS_FAILURE; + mlan_adapter *pmadapter = (mlan_adapter *)padapter; + + ENTER(); + MASSERT(padapter); + + /* unmask host interrupt from firmware */ + if (pmadapter->ops.enable_host_int) { + ret = pmadapter->ops.enable_host_int(pmadapter); + if (ret != MLAN_STATUS_SUCCESS) { + PRINTM(MERROR, "mlan_enable_host_int fail ret = 0x%x\n", + ret); + LEAVE(); + return ret; + } + } + + LEAVE(); + return ret; +} + /** * @brief This function pass init param to MLAN * @@ -1164,7 +1233,6 @@ process_start: wlan_11h_radar_detected_tx_blocked(pmadapter)) { if (pmadapter->cmd_sent || pmadapter->curr_cmd || - pmadapter->cmd_lock || !wlan_is_send_cmd_allowed( pmadapter->tdls_status) || !wlan_is_cmd_pending(pmadapter)) { @@ -1224,7 +1292,6 @@ process_start: pmadapter->vdll_ctrl.pending_block = MNULL; } if (!pmadapter->cmd_sent && !pmadapter->curr_cmd && - !pmadapter->cmd_lock && wlan_is_send_cmd_allowed(pmadapter->tdls_status)) { if (wlan_exec_next_cmd(pmadapter) == MLAN_STATUS_FAILURE) { diff --git a/mxm_wifiex/wlan_src/mlan/mlan_sta_cmd.c b/mxm_wifiex/wlan_src/mlan/mlan_sta_cmd.c index 00b0aeb..36d2860 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_sta_cmd.c +++ b/mxm_wifiex/wlan_src/mlan/mlan_sta_cmd.c @@ -686,7 +686,22 @@ static mlan_status wlan_cmd_802_11_hs_cfg(pmlan_private pmpriv, } cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH); - cmd->size = S_DS_GEN + sizeof(HostCmd_DS_802_11_HS_CFG_ENH); + if (!hs_activate && (pdata_buf->conditions != HOST_SLEEP_CFG_CANCEL) && + ((pmadapter->arp_filter_size > 0) && + (pmadapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) { + PRINTM(MINFO, "Attach %d bytes ArpFilter to HSCfg cmd\n", + pmadapter->arp_filter_size); + memcpy_ext(pmpriv->adapter, + ((t_u8 *)phs_cfg) + + sizeof(HostCmd_DS_802_11_HS_CFG_ENH), + pmadapter->arp_filter, pmadapter->arp_filter_size, + pmadapter->arp_filter_size); + cmd->size = pmadapter->arp_filter_size + + sizeof(HostCmd_DS_802_11_HS_CFG_ENH) + S_DS_GEN; + tlv = (t_u8 *)phs_cfg + sizeof(HostCmd_DS_802_11_HS_CFG_ENH) + + pmadapter->arp_filter_size; + } else + cmd->size = S_DS_GEN + sizeof(HostCmd_DS_802_11_HS_CFG_ENH); if (hs_activate) { cmd->size = wlan_cpu_to_le16(cmd->size); @@ -1265,7 +1280,12 @@ static mlan_status wlan_cmd_802_11_key_material(pmlan_private pmpriv, ~(wlan_cpu_to_le16(KEY_INFO_MCAST_KEY)); pkey_material->key_param_set.key_info |= wlan_cpu_to_le16(KEY_INFO_AES_MCAST_IGTK); - pkey_material->key_param_set.key_type = KEY_TYPE_ID_AES_CMAC; + if (pkey->key_flags & KEY_FLAG_GMAC_128) + pkey_material->key_param_set.key_type = + KEY_TYPE_ID_BIP_GMAC_128; + else + pkey_material->key_param_set.key_type = + KEY_TYPE_ID_AES_CMAC; pkey_material->key_param_set.key_params.cmac_aes.key_len = wlan_cpu_to_le16(pkey->key_len); memcpy_ext(pmpriv->adapter, @@ -1277,7 +1297,39 @@ static mlan_status wlan_cmd_802_11_key_material(pmlan_private pmpriv, S_DS_GEN + KEY_PARAMS_FIXED_LEN + sizeof(cmac_aes_param) + sizeof(pkey_material->action)); - PRINTM(MCMND, "Set CMAC AES Key\n"); + if (pkey->key_flags & KEY_FLAG_GMAC_128) + PRINTM(MCMND, "Set AES 128 GMAC Key\n"); + else + PRINTM(MCMND, "Set CMAC AES Key\n"); + goto done; + } + if (pkey->key_len == WPA_IGTK_256_KEY_LEN && + (pkey->key_flags & KEY_FLAG_AES_MCAST_IGTK)) { + if (pkey->key_flags & + (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID)) + memcpy_ext(pmpriv->adapter, + pkey_material->key_param_set.key_params + .cmac_aes.ipn, + pkey->pn, SEQ_MAX_SIZE, IGTK_PN_SIZE); + pkey_material->key_param_set.key_info &= + ~(wlan_cpu_to_le16(KEY_INFO_MCAST_KEY)); + pkey_material->key_param_set.key_info |= + wlan_cpu_to_le16(KEY_INFO_AES_MCAST_IGTK); + pkey_material->key_param_set.key_type = + KEY_TYPE_ID_BIP_GMAC_256; + pkey_material->key_param_set.key_params.cmac_aes.key_len = + wlan_cpu_to_le16(pkey->key_len); + memcpy_ext(pmpriv->adapter, + pkey_material->key_param_set.key_params.cmac_aes.key, + pkey->key_material, pkey->key_len, + WPA_IGTK_256_KEY_LEN); + pkey_material->key_param_set.length = wlan_cpu_to_le16( + KEY_PARAMS_FIXED_LEN + sizeof(gmac_aes_256_param)); + cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) + + S_DS_GEN + KEY_PARAMS_FIXED_LEN + + sizeof(gmac_aes_256_param) + + sizeof(pkey_material->action)); + PRINTM(MCMND, "Set AES 256 GMAC Key\n"); goto done; } if (pkey->key_len == WPA_TKIP_KEY_LEN) { @@ -2679,6 +2731,47 @@ mlan_status wlan_cmd_arb_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *cmd, return MLAN_STATUS_SUCCESS; } +/** + * @brief This function set ipv6 ra offload configuration. + * + * @param pmpriv A pointer to mlan_private structure + * @param pcmd A pointer to HostCmd_DS_COMMAND structure + * @param cmd_action Command action + * @param pdata_buf A pointer to information buffer + * @return N/A + */ + +mlan_status wlan_cmd_ipv6_ra_offload(mlan_private *pmpriv, + HostCmd_DS_COMMAND *pcmd, t_u16 cmd_action, + void *pdata_buf) +{ + HostCmd_DS_IPV6_RA_OFFLOAD *ipv6_ra_cfg = &pcmd->params.ipv6_ra_offload; + mlan_ds_misc_ipv6_ra_offload *ipv6_ra_offload = + (mlan_ds_misc_ipv6_ra_offload *)pdata_buf; + MrvlIEtypesHeader_t *ie = &ipv6_ra_cfg->ipv6_addr_param.Header; + + ENTER(); + + pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_IPV6_RA_OFFLOAD_CFG); + ipv6_ra_cfg->action = wlan_cpu_to_le16(cmd_action); + if (cmd_action == HostCmd_ACT_GEN_SET) { + ipv6_ra_cfg->enable = ipv6_ra_offload->enable; + ie->type = wlan_cpu_to_le16(TLV_TYPE_IPV6_RA_OFFLOAD); + ie->len = wlan_cpu_to_le16(16); + memcpy_ext(pmpriv->adapter, + ipv6_ra_cfg->ipv6_addr_param.ipv6_addr, + ipv6_ra_offload->ipv6_addr, 16, + sizeof(ipv6_ra_cfg->ipv6_addr_param.ipv6_addr)); + pcmd->size = wlan_cpu_to_le16( + S_DS_GEN + sizeof(HostCmd_DS_IPV6_RA_OFFLOAD)); + } else if (cmd_action == HostCmd_ACT_GEN_GET) + pcmd->size = wlan_cpu_to_le16(S_DS_GEN + + sizeof(ipv6_ra_cfg->action)); + + LEAVE(); + return MLAN_STATUS_SUCCESS; +} + /** * @brief This function sends get sta band channel command to firmware. * @@ -3310,6 +3403,10 @@ mlan_status wlan_ops_sta_prepare_cmd(t_void *priv, t_u16 cmd_no, case HostCmd_CMD_802_11_MIMO_SWITCH: ret = wlan_cmd_802_11_mimo_switch(pmpriv, cmd_ptr, pdata_buf); break; + case HostCmd_CMD_IPV6_RA_OFFLOAD_CFG: + ret = wlan_cmd_ipv6_ra_offload(pmpriv, cmd_ptr, cmd_action, + pdata_buf); + break; case HostCmd_CMD_STA_CONFIGURE: ret = wlan_cmd_sta_config(pmpriv, cmd_ptr, cmd_action, pioctl_buf, pdata_buf); @@ -3368,6 +3465,10 @@ mlan_status wlan_ops_sta_prepare_cmd(t_void *priv, t_u16 cmd_no, case HostCmd_CMD_TWT_CFG: ret = wlan_cmd_twt_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; + case HOST_CMD_GPIO_TSF_LATCH_PARAM_CONFIG: + ret = wlan_cmd_gpio_tsf_latch(pmpriv, cmd_ptr, cmd_action, + pioctl_buf, pdata_buf); + break; case HostCmd_CMD_RX_ABORT_CFG: ret = wlan_cmd_rxabortcfg(pmpriv, cmd_ptr, cmd_action, pdata_buf); diff --git a/mxm_wifiex/wlan_src/mlan/mlan_sta_cmdresp.c b/mxm_wifiex/wlan_src/mlan/mlan_sta_cmdresp.c index 0e85b9c..59b660e 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_sta_cmdresp.c +++ b/mxm_wifiex/wlan_src/mlan/mlan_sta_cmdresp.c @@ -751,6 +751,14 @@ static mlan_status wlan_ret_get_log(pmlan_private pmpriv, wlan_le32_to_cpu(pget_log->dwMgtErrCnt); pget_info->param.stats.dwDatErrCnt = wlan_le32_to_cpu(pget_log->dwDatErrCnt); + pget_info->param.stats.bigtk_mmeGoodCnt = + wlan_le32_to_cpu(pget_log->bigtk_mmeGoodCnt); + pget_info->param.stats.bigtk_replayErrCnt = + wlan_le32_to_cpu(pget_log->bigtk_replayErrCnt); + pget_info->param.stats.bigtk_micErrCnt = + wlan_le32_to_cpu(pget_log->bigtk_micErrCnt); + pget_info->param.stats.bigtk_mmeNotFoundCnt = + wlan_le32_to_cpu(pget_log->bigtk_mmeNotFoundCnt); if (pmpriv->adapter->getlog_enable) { pget_info->param.stats.tx_frag_cnt = @@ -2472,6 +2480,40 @@ mlan_status wlan_ret_arb_cfg(pmlan_private pmpriv, HostCmd_DS_COMMAND *resp, return MLAN_STATUS_SUCCESS; } +/** + * @brief This function handles the command response of ipv6 ra offload feature + * + * @param pmpriv A pointer to mlan_private structure + * @param resp A pointer to HostCmd_DS_COMMAND + * @param pioctl_buf A pointer to mlan_ioctl_req structure + * + * @return MLAN_STATUS_SUCCESS + */ +mlan_status wlan_ret_ipv6_ra_offload(pmlan_private pmpriv, + HostCmd_DS_COMMAND *resp, + mlan_ioctl_req *pioctl_buf) +{ + HostCmd_DS_IPV6_RA_OFFLOAD *ipv6_ra_resp = + &resp->params.ipv6_ra_offload; + mlan_ds_misc_cfg *misc = MNULL; + mlan_ds_misc_ipv6_ra_offload *ipv6_ra = MNULL; + + ENTER(); + + if (pioctl_buf && (pioctl_buf->action == MLAN_ACT_GET)) { + misc = (mlan_ds_misc_cfg *)pioctl_buf->pbuf; + ipv6_ra = (mlan_ds_misc_ipv6_ra_offload *)&misc->param + .ipv6_ra_offload; + ipv6_ra->enable = ipv6_ra_resp->enable; + memcpy_ext(pmpriv->adapter, ipv6_ra->ipv6_addr, + ipv6_ra_resp->ipv6_addr_param.ipv6_addr, 16, + sizeof(ipv6_ra->ipv6_addr)); + } + + LEAVE(); + return MLAN_STATUS_SUCCESS; +} + /** * @brief This function handles the command response of sta get band and * channel @@ -3196,6 +3238,9 @@ mlan_status wlan_ops_sta_process_cmdresp(t_void *priv, t_u16 cmdresp_no, break; case HostCmd_CMD_802_11_MIMO_SWITCH: break; + case HostCmd_CMD_IPV6_RA_OFFLOAD_CFG: + ret = wlan_ret_ipv6_ra_offload(pmpriv, resp, pioctl_buf); + break; case HostCmd_CMD_STA_CONFIGURE: ret = wlan_ret_sta_config(pmpriv, resp, pioctl_buf); break; @@ -3240,6 +3285,9 @@ mlan_status wlan_ops_sta_process_cmdresp(t_void *priv, t_u16 cmdresp_no, break; case HostCmd_CMD_TWT_CFG: break; + case HOST_CMD_GPIO_TSF_LATCH_PARAM_CONFIG: + ret = wlan_ret_gpio_tsf_latch(pmpriv, resp, pioctl_buf); + break; case HostCmd_CMD_RX_ABORT_CFG: ret = wlan_ret_rxabortcfg(pmpriv, resp, pioctl_buf); break; diff --git a/mxm_wifiex/wlan_src/mlan/mlan_sta_event.c b/mxm_wifiex/wlan_src/mlan/mlan_sta_event.c index db93a7b..29bad5b 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_sta_event.c +++ b/mxm_wifiex/wlan_src/mlan/mlan_sta_event.c @@ -1004,7 +1004,6 @@ mlan_status wlan_ops_sta_process_event(t_void *priv) PRINTM(MEVENT, "EVENT: EXT_SCAN status report (%d)\n", pmbuf->data_len); pmadapter->ext_scan_timeout = MFALSE; - pmadapter->cmd_lock = MFALSE; ret = wlan_handle_event_ext_scan_status(priv, pmbuf); break; case EVENT_MEAS_REPORT_RDY: diff --git a/mxm_wifiex/wlan_src/mlan/mlan_sta_ioctl.c b/mxm_wifiex/wlan_src/mlan/mlan_sta_ioctl.c index b8aec45..10a1303 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_sta_ioctl.c +++ b/mxm_wifiex/wlan_src/mlan/mlan_sta_ioctl.c @@ -356,12 +356,8 @@ static mlan_status wlan_get_info_bss_info(pmlan_adapter pmadapter, info->param.bss_info.listen_interval = pmpriv->listen_interval; /* Association ID */ - if (pmpriv->assoc_rsp_buf) - info->param.bss_info.assoc_id = - (t_u16)((IEEEtypes_AssocRsp_t *)pmpriv->assoc_rsp_buf) - ->a_id; - else - info->param.bss_info.assoc_id = 0; + info->param.bss_info.assoc_id = + (t_u16)((IEEEtypes_AssocRsp_t *)pmpriv->assoc_rsp_buf)->a_id; /* AP/Peer supported rates */ memset(pmadapter, info->param.bss_info.peer_supp_rates, 0, @@ -462,6 +458,8 @@ static mlan_status wlan_get_info_ioctl(pmlan_adapter pmadapter, pget_info->param.fw_info.antinfo = pmadapter->antinfo; pget_info->param.fw_info.max_ap_assoc_sta = pmadapter->max_sta_conn; + pget_info->param.fw_info.fw_beacon_prot = + IS_FW_SUPPORT_BEACON_PROT(pmadapter) ? 0x01 : 0x00; break; case MLAN_OID_GET_BSS_INFO: status = wlan_get_info_bss_info(pmadapter, pioctl_req); @@ -2882,9 +2880,9 @@ static mlan_status wlan_sec_ioctl_set_wep_key(pmlan_adapter pmadapter, /* Copy the required key as the current key */ pwep_key = &pmpriv->wep_key[index]; if (!pwep_key->key_length) { - if (&pmpriv->sec_info.wpa_enabled || - &pmpriv->sec_info.wpa2_enabled || - &pmpriv->sec_info.wapi_enabled) { + if (pmpriv->sec_info.wpa_enabled || + pmpriv->sec_info.wpa2_enabled || + pmpriv->sec_info.wapi_enabled) { ret = MLAN_STATUS_SUCCESS; goto exit; } @@ -3944,6 +3942,28 @@ static mlan_status wlan_misc_ioctl_gen_ie(pmlan_adapter pmadapter, (t_u16)misc->param.gen_ie.len); } break; + case MLAN_IE_TYPE_ARP_FILTER: + memset(pmadapter, pmadapter->arp_filter, 0, + sizeof(pmadapter->arp_filter)); + if (misc->param.gen_ie.len > ARP_FILTER_MAX_BUF_SIZE) { + pmadapter->arp_filter_size = 0; + PRINTM(MERROR, "Invalid ARP Filter Size\n"); + pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER; + ret = MLAN_STATUS_FAILURE; + } else if (misc->param.gen_ie.len <= + sizeof(MrvlIEtypesHeader_t)) { + pmadapter->arp_filter_size = 0; + PRINTM(MINFO, "Clear ARP filter\n"); + } else { + memcpy_ext(pmadapter, pmadapter->arp_filter, + misc->param.gen_ie.ie_data, + misc->param.gen_ie.len, + ARP_FILTER_MAX_BUF_SIZE); + pmadapter->arp_filter_size = misc->param.gen_ie.len; + HEXDUMP("ArpFilter", pmadapter->arp_filter, + pmadapter->arp_filter_size); + } + break; default: PRINTM(MERROR, "Invalid IE type\n"); pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER; @@ -4321,6 +4341,84 @@ static mlan_status wlan_misc_ioctl_subscribe_evt(pmlan_adapter pmadapter, return ret; } +/** + * @brief Set ARP filter based on IP address + * + * @param pmadapter A pointer to mlan_adapter structure + * @param pioctl_req A pointer to ioctl request buffer + * @param ipv4_addr ipv4 Address + * + * @return MLAN_STATUS_PENDING --success, otherwise fail + */ +static mlan_status wlan_ipaddr_arp_filter(pmlan_adapter pmadapter, + pmlan_ioctl_req pioctl_req, + t_u32 ipv4_addr) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + pmlan_callbacks pcb = &pmadapter->callbacks; + t_u8 *buf; + arpfilter_header *arpfilter = MNULL; + filter_entry *entry = MNULL; + t_u32 len; + + ENTER(); + + pcb->moal_malloc(pmadapter->pmoal_handle, MRVDRV_SIZE_OF_CMD_BUFFER, + MLAN_MEM_DEF, &buf); + if (!buf) { + ret = MLAN_STATUS_FAILURE; + goto done; + } + + /* Construct the ARP filter TLV */ + arpfilter = (arpfilter_header *)buf; + arpfilter->type = wlan_cpu_to_le16(TLV_TYPE_ARP_FILTER); + + if (ipv4_addr) { + arpfilter->len = wlan_cpu_to_le16(sizeof(filter_entry) * 3); + entry = (filter_entry *)(buf + sizeof(arpfilter_header)); + entry->addr_type = wlan_cpu_to_le16(ADDR_TYPE_BROADCAST); + entry->eth_type = wlan_cpu_to_le16(ETHER_TYPE_ARP); + entry->ipv4_addr = wlan_cpu_to_le32(ipv4_addr); + entry++; + entry->addr_type = wlan_cpu_to_le16(ADDR_TYPE_UNICAST); + entry->eth_type = wlan_cpu_to_le16(ETHER_TYPE_ANY); + entry->ipv4_addr = wlan_cpu_to_le32(IPV4_ADDR_ANY); + entry++; + entry->addr_type = wlan_cpu_to_le16(ADDR_TYPE_MULTICAST); + entry->eth_type = wlan_cpu_to_le16(ETHER_TYPE_ANY); + entry->ipv4_addr = wlan_cpu_to_le32(IPV4_ADDR_ANY); + } else + arpfilter->len = 0; + + /* Update the total length */ + len = sizeof(arpfilter_header) + wlan_le16_to_cpu(arpfilter->len); + + memset(pmadapter, pmadapter->arp_filter, 0, + sizeof(pmadapter->arp_filter)); + if (len > ARP_FILTER_MAX_BUF_SIZE) { + pmadapter->arp_filter_size = 0; + PRINTM(MERROR, "Invalid ARP Filter Size\n"); + pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER; + ret = MLAN_STATUS_FAILURE; + } else if (len <= sizeof(MrvlIEtypesHeader_t)) { + pmadapter->arp_filter_size = 0; + PRINTM(MINFO, "Clear ARP filter\n"); + } else { + memcpy_ext(pmadapter, pmadapter->arp_filter, buf, len, + ARP_FILTER_MAX_BUF_SIZE); + pmadapter->arp_filter_size = len; + HEXDUMP("ArpFilter", pmadapter->arp_filter, + pmadapter->arp_filter_size); + } + +done: + if (buf) + pcb->moal_mfree(pmadapter->pmoal_handle, buf); + LEAVE(); + return ret; +} + /** * @brief MEF configuration * @@ -4470,6 +4568,13 @@ static mlan_status wlan_misc_ioctl_ipaddr_cfg(pmlan_adapter pmadapter, ret = MLAN_STATUS_FAILURE; goto done; } + if (misc->param.ipaddr_cfg.op_code & MLAN_IPADDR_OP_ARP_FILTER) + ret = wlan_ipaddr_arp_filter(pmadapter, pioctl_req, + ipv4_addr[0]); + else if (pmpriv->op_code & MLAN_IPADDR_OP_ARP_FILTER) + ret = wlan_ipaddr_arp_filter(pmadapter, pioctl_req, 0); + if (ret == MLAN_STATUS_FAILURE) + goto done; /* Save the values in MLAN */ if (pioctl_req->action == MLAN_ACT_SET) { @@ -4755,6 +4860,40 @@ static mlan_status wlan_misc_ioctl_get_sensor_temp(pmlan_adapter pmadapter, return ret; } +/** + * @brief IPv6 Router Advertisement offload configuration + * + * @param pmadapter A pointer to mlan_adapter structure + * @param pioctl_req Pointer to the IOCTL request buffer + * + * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE + */ +mlan_status wlan_misc_ioctl_ipv6_ra_offload(pmlan_adapter pmadapter, + mlan_ioctl_req *pioctl_req) +{ + pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; + mlan_ds_misc_cfg *misc = MNULL; + t_u16 cmd_action = 0; + mlan_status ret = MLAN_STATUS_SUCCESS; + + ENTER(); + + misc = (mlan_ds_misc_cfg *)pioctl_req->pbuf; + if (pioctl_req->action == MLAN_ACT_SET) + cmd_action = HostCmd_ACT_GEN_SET; + else if (pioctl_req->action == MLAN_ACT_GET) + cmd_action = HostCmd_ACT_GEN_GET; + + ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_IPV6_RA_OFFLOAD_CFG, + cmd_action, 0, (t_void *)pioctl_req, + &misc->param.ipv6_ra_offload); + if (ret == MLAN_STATUS_SUCCESS) + ret = MLAN_STATUS_PENDING; + + LEAVE(); + return ret; +} + /** * @brief Gtk Rekey Offload * @@ -4882,6 +5021,7 @@ static mlan_status wlan_misc_cfg_ioctl(pmlan_adapter pmadapter, status = wlan_misc_ioctl_region(pmadapter, pioctl_req); break; case MLAN_OID_MISC_WARM_RESET: + PRINTM(MCMND, "Request WARM RESET\n"); util_enqueue_list_tail(pmadapter->pmoal_handle, &pmadapter->ioctl_pending_q, (pmlan_linked_list)pioctl_req, @@ -5022,6 +5162,9 @@ static mlan_status wlan_misc_cfg_ioctl(pmlan_adapter pmadapter, status = wlan_misc_ioctl_operclass_validation(pmadapter, pioctl_req); break; + case MLAN_OID_MISC_IPV6_RA_OFFLOAD: + status = wlan_misc_ioctl_ipv6_ra_offload(pmadapter, pioctl_req); + break; case MLAN_OID_MISC_GTK_REKEY_OFFLOAD: status = wlan_misc_ioctl_gtk_rekey_offload(pmadapter, pioctl_req); @@ -5073,6 +5216,12 @@ static mlan_status wlan_misc_cfg_ioctl(pmlan_adapter pmadapter, case MLAN_OID_MISC_HAL_PHY_CFG: status = wlan_misc_hal_phy_cfg(pmadapter, pioctl_req); break; + case MLAN_OID_MISC_GPIO_TSF_LATCH: + status = wlan_misc_gpio_tsf_latch_config(pmadapter, pioctl_req); + break; + case MLAN_OID_MISC_GET_TSF_INFO: + status = wlan_misc_get_tsf_info(pmadapter, pioctl_req); + break; case MLAN_OID_MISC_RX_ABORT_CFG: status = wlan_misc_ioctl_rxabortcfg(pmadapter, pioctl_req); break; diff --git a/mxm_wifiex/wlan_src/mlan/mlan_uap_cmdevent.c b/mxm_wifiex/wlan_src/mlan/mlan_uap_cmdevent.c index 046b230..b0d15a0 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_uap_cmdevent.c +++ b/mxm_wifiex/wlan_src/mlan/mlan_uap_cmdevent.c @@ -1462,7 +1462,6 @@ static mlan_status wlan_uap_cmd_ap_config(pmlan_private pmpriv, cmd_size += sizeof(MrvlIEtypes_preamble_t); tlv += sizeof(MrvlIEtypes_preamble_t); } - cmd->size = (t_u16)wlan_cpu_to_le16(cmd_size); PRINTM(MCMND, "AP config: cmd_size=%d\n", cmd_size); LEAVE(); @@ -1512,6 +1511,7 @@ static mlan_status wlan_uap_cmd_sys_configure(pmlan_private pmpriv, t_u16 req_len = 0, travel_len = 0; custom_ie *cptr = MNULL; mlan_status ret = MLAN_STATUS_SUCCESS; + MrvlIEtypes_wacp_mode_t *tlv_wacp_mode = MNULL; ENTER(); @@ -1900,6 +1900,21 @@ static mlan_status wlan_uap_cmd_sys_configure(pmlan_private pmpriv, misc->param.cust_ie.len); } } + if (misc->sub_command == MLAN_OID_MISC_WACP_MODE) { + tlv_wacp_mode = (MrvlIEtypes_wacp_mode_t *) + sys_config->tlv_buffer; + tlv_wacp_mode->header.type = + wlan_cpu_to_le16(TLV_TYPE_UAP_WACP_MODE); + tlv_wacp_mode->header.len = + wlan_cpu_to_le16(sizeof(t_u8)); + if (cmd_action == HostCmd_ACT_GEN_SET) { + tlv_wacp_mode->wacp_mode = + misc->param.wacp_mode; + } + cmd->size = wlan_cpu_to_le16( + sizeof(HostCmd_DS_SYS_CONFIG) - 1 + S_DS_GEN + + sizeof(MrvlIEtypes_wacp_mode_t)); + } } done: LEAVE(); @@ -3186,6 +3201,15 @@ static mlan_status wlan_uap_ret_get_log(pmlan_private pmpriv, wlan_le32_to_cpu(pget_log->dwMgtErrCnt); pget_info->param.stats.dwDatErrCnt = wlan_le32_to_cpu(pget_log->dwDatErrCnt); + pget_info->param.stats.bigtk_mmeGoodCnt = + wlan_le32_to_cpu(pget_log->bigtk_mmeGoodCnt); + pget_info->param.stats.bigtk_replayErrCnt = + wlan_le32_to_cpu(pget_log->bigtk_replayErrCnt); + pget_info->param.stats.bigtk_micErrCnt = + wlan_le32_to_cpu(pget_log->bigtk_micErrCnt); + pget_info->param.stats.bigtk_mmeNotFoundCnt = + wlan_le32_to_cpu(pget_log->bigtk_mmeNotFoundCnt); + if (pmpriv->adapter->getlog_enable) { pget_info->param.stats.tx_frag_cnt = wlan_le32_to_cpu(pget_log->tx_frag_cnt); @@ -3426,7 +3450,7 @@ static mlan_status wlan_uap_cmd_key_material(pmlan_private pmpriv, else pkey_material->key_param_set.key_info |= KEY_INFO_UCAST_KEY; if (pkey->key_flags & KEY_FLAG_AES_MCAST_IGTK) - pkey_material->key_param_set.key_info = KEY_INFO_CMAC_AES_KEY; + pkey_material->key_param_set.key_info |= KEY_INFO_CMAC_AES_KEY; if (pkey->key_flags & KEY_FLAG_SET_TX_KEY) pkey_material->key_param_set.key_info |= KEY_INFO_TX_KEY | KEY_INFO_RX_KEY; @@ -3505,7 +3529,12 @@ static mlan_status wlan_uap_cmd_key_material(pmlan_private pmpriv, ~(wlan_cpu_to_le16(KEY_INFO_MCAST_KEY)); pkey_material->key_param_set.key_info |= wlan_cpu_to_le16(KEY_INFO_AES_MCAST_IGTK); - pkey_material->key_param_set.key_type = KEY_TYPE_ID_AES_CMAC; + if (pkey->key_flags & KEY_FLAG_GMAC_128) + pkey_material->key_param_set.key_type = + KEY_TYPE_ID_BIP_GMAC_128; + else + pkey_material->key_param_set.key_type = + KEY_TYPE_ID_AES_CMAC; pkey_material->key_param_set.key_params.cmac_aes.key_len = wlan_cpu_to_le16(pkey->key_len); memcpy_ext(pmpriv->adapter, @@ -3517,7 +3546,39 @@ static mlan_status wlan_uap_cmd_key_material(pmlan_private pmpriv, S_DS_GEN + KEY_PARAMS_FIXED_LEN + sizeof(cmac_aes_param) + sizeof(pkey_material->action)); - PRINTM(MCMND, "Set CMAC AES Key\n"); + if (pkey->key_flags & KEY_FLAG_GMAC_128) + PRINTM(MCMND, "Set AES 128 GMAC Key\n"); + else + PRINTM(MCMND, "Set CMAC AES Key\n"); + goto done; + } + if (pkey->key_len == WPA_IGTK_256_KEY_LEN && + (pkey->key_flags & KEY_FLAG_AES_MCAST_IGTK)) { + if (pkey->key_flags & + (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID)) + memcpy_ext(pmpriv->adapter, + pkey_material->key_param_set.key_params + .cmac_aes.ipn, + pkey->pn, SEQ_MAX_SIZE, IGTK_PN_SIZE); + pkey_material->key_param_set.key_info &= + ~(wlan_cpu_to_le16(KEY_INFO_MCAST_KEY)); + pkey_material->key_param_set.key_info |= + wlan_cpu_to_le16(KEY_INFO_AES_MCAST_IGTK); + pkey_material->key_param_set.key_type = + KEY_TYPE_ID_BIP_GMAC_256; + pkey_material->key_param_set.key_params.cmac_aes.key_len = + wlan_cpu_to_le16(pkey->key_len); + memcpy_ext(pmpriv->adapter, + pkey_material->key_param_set.key_params.cmac_aes.key, + pkey->key_material, pkey->key_len, + WPA_IGTK_256_KEY_LEN); + pkey_material->key_param_set.length = wlan_cpu_to_le16( + KEY_PARAMS_FIXED_LEN + sizeof(gmac_aes_256_param)); + cmd->size = wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) + + S_DS_GEN + KEY_PARAMS_FIXED_LEN + + sizeof(gmac_aes_256_param) + + sizeof(pkey_material->action)); + PRINTM(MCMND, "Set AES 256 GMAC Key\n"); goto done; } if (pkey->key_len == WPA_TKIP_KEY_LEN) { @@ -4515,6 +4576,10 @@ mlan_status wlan_ops_uap_prepare_cmd(t_void *priv, t_u16 cmd_no, pdata_buf); break; #endif + case HOST_CMD_GPIO_TSF_LATCH_PARAM_CONFIG: + ret = wlan_cmd_gpio_tsf_latch(pmpriv, cmd_ptr, cmd_action, + pioctl_buf, pdata_buf); + break; case HostCmd_CMD_802_11_RF_ANTENNA: ret = wlan_cmd_802_11_rf_antenna(pmpriv, cmd_ptr, cmd_action, pdata_buf); @@ -4921,6 +4986,9 @@ mlan_status wlan_ops_uap_process_cmdresp(t_void *priv, t_u16 cmdresp_no, ret = wlan_ret_p2p_params_config(pmpriv, resp, pioctl_buf); break; #endif + case HOST_CMD_GPIO_TSF_LATCH_PARAM_CONFIG: + ret = wlan_ret_gpio_tsf_latch(pmpriv, resp, pioctl_buf); + break; case HostCmd_CMD_802_11_RF_ANTENNA: ret = wlan_ret_802_11_rf_antenna(pmpriv, resp, pioctl_buf); break; diff --git a/mxm_wifiex/wlan_src/mlan/mlan_uap_ioctl.c b/mxm_wifiex/wlan_src/mlan/mlan_uap_ioctl.c index eda871d..892f764 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_uap_ioctl.c +++ b/mxm_wifiex/wlan_src/mlan/mlan_uap_ioctl.c @@ -2007,6 +2007,11 @@ mlan_status wlan_ops_uap_ioctl(t_void *adapter, pmlan_ioctl_req pioctl_req) if (misc->sub_command == MLAN_OID_MISC_WIFI_DIRECT_CONFIG) status = wlan_misc_p2p_config(pmadapter, pioctl_req); #endif + if (misc->sub_command == MLAN_OID_MISC_GPIO_TSF_LATCH) + status = wlan_misc_gpio_tsf_latch_config(pmadapter, + pioctl_req); + if (misc->sub_command == MLAN_OID_MISC_GET_TSF_INFO) + status = wlan_misc_get_tsf_info(pmadapter, pioctl_req); if (misc->sub_command == MLAN_OID_MISC_DFS_REAPTER_MODE) { mlan_ds_misc_cfg *misc_cfg = MNULL; @@ -2088,6 +2093,9 @@ mlan_status wlan_ops_uap_ioctl(t_void *adapter, pmlan_ioctl_req pioctl_req) if (misc->sub_command == MLAN_OID_MISC_RANGE_EXT) status = wlan_misc_ioctl_range_ext(pmadapter, pioctl_req); + if (misc->sub_command == MLAN_OID_MISC_WACP_MODE) + status = wlan_misc_ioctl_wacp_mode(pmadapter, + pioctl_req); break; case MLAN_IOCTL_POWER_CFG: power = (mlan_ds_power_cfg *)pioctl_req->pbuf; diff --git a/mxm_wifiex/wlan_src/mlan/mlan_uap_txrx.c b/mxm_wifiex/wlan_src/mlan/mlan_uap_txrx.c index e8e3085..31c548a 100644 --- a/mxm_wifiex/wlan_src/mlan/mlan_uap_txrx.c +++ b/mxm_wifiex/wlan_src/mlan/mlan_uap_txrx.c @@ -244,6 +244,7 @@ t_void *wlan_ops_uap_process_txpd(t_void *priv, pmlan_buffer pmbuf) plocal_tx_pd->tx_pkt_type = (t_u16)pkt_type; plocal_tx_pd->tx_control = tx_control; } + if (pmbuf->flags & MLAN_BUF_FLAG_TX_CTRL) { if (pmbuf->u.tx_info.data_rate) { memcpy_ext(pmpriv->adapter, dst_mac, @@ -423,7 +424,7 @@ mlan_status wlan_ops_uap_process_rx_packet(t_void *adapter, pmlan_buffer pmbuf) } #endif - pmbuf->priority = prx_pd->priority; + pmbuf->priority |= prx_pd->priority; memcpy_ext(pmadapter, ta, prx_pkt->eth803_hdr.src_addr, MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH); if ((rx_pkt_type != PKT_TYPE_BAR) && (prx_pd->priority < MAX_NUM_TID)) { diff --git a/mxm_wifiex/wlan_src/mlinux/mlan_decl.h b/mxm_wifiex/wlan_src/mlinux/mlan_decl.h index 0347721..319dc7c 100644 --- a/mxm_wifiex/wlan_src/mlinux/mlan_decl.h +++ b/mxm_wifiex/wlan_src/mlinux/mlan_decl.h @@ -24,7 +24,7 @@ #define _MLAN_DECL_H_ /** MLAN release version */ -#define MLAN_RELEASE_VERSION "266.p4" +#define MLAN_RELEASE_VERSION "283" /** Re-define generic data types for MLAN/MOAL */ /** Signed char (1-byte) */ @@ -2039,7 +2039,8 @@ typedef struct _mlan_callbacks { t_u32 drop_point); void (*moal_tp_accounting_rx_param)(t_void *pmoal, unsigned int type, unsigned int rsvd1); - + void (*moal_amsdu_tp_accounting)(t_void *pmoal, t_s32 delay, + t_s32 copy_delay); } mlan_callbacks, *pmlan_callbacks; /** Parameter unchanged, use MLAN default setting */ @@ -2180,6 +2181,8 @@ typedef struct _mlan_device { t_u32 drv_mode; /** dfs w53 cfg */ t_u8 dfs53cfg; + /** extend enhance scan */ + t_u8 ext_scan; } mlan_device, *pmlan_device; /** MLAN API function prototype */ @@ -2253,4 +2256,9 @@ MLAN_API mlan_status mlan_ioctl(t_void *padapter, pmlan_ioctl_req pioctl_req); /** mlan select wmm queue */ MLAN_API t_u8 mlan_select_wmm_queue(t_void *padapter, t_u8 bss_num, t_u8 tid); +/** mlan mask host interrupt */ +MLAN_API mlan_status mlan_disable_host_int(t_void *padapter); +/** mlan unmask host interrupt */ +MLAN_API mlan_status mlan_enable_host_int(t_void *padapter); + #endif /* !_MLAN_DECL_H_ */ diff --git a/mxm_wifiex/wlan_src/mlinux/mlan_ieee.h b/mxm_wifiex/wlan_src/mlinux/mlan_ieee.h index 906a345..329aa77 100644 --- a/mxm_wifiex/wlan_src/mlinux/mlan_ieee.h +++ b/mxm_wifiex/wlan_src/mlinux/mlan_ieee.h @@ -1403,6 +1403,8 @@ typedef MLAN_PACK_START struct { t_u8 local_max_tp_20mhz; /**< Local Maximum Transmit Power for 20 MHZ>*/ t_u8 local_max_tp_40mhz; /**< Local Maximum Transmit Power for 40 MHZ>*/ t_u8 local_max_tp_80mhz; /**< Local Maximum Transmit Power for 80 MHZ>*/ + t_u8 local_max_tp_160mhz_80_80mhz; /**< Local Maximum Transmit Power for + 160/80+80 MHZ>*/ } MLAN_PACK_END IEEEtypes_VhtTpcEnvelope_t; /* IEEE Quiet Period Element (7.3.2.23) */ diff --git a/mxm_wifiex/wlan_src/mlinux/mlan_ioctl.h b/mxm_wifiex/wlan_src/mlinux/mlan_ioctl.h index a9d3c79..0aa139c 100644 --- a/mxm_wifiex/wlan_src/mlinux/mlan_ioctl.h +++ b/mxm_wifiex/wlan_src/mlinux/mlan_ioctl.h @@ -298,6 +298,7 @@ enum _mlan_ioctl_req_id { MLAN_OID_MISC_COALESCE_CFG = 0x0020002E, MLAN_OID_MISC_TDLS_IDLE_TIME = 0x0020002F, MLAN_OID_MISC_GET_SENSOR_TEMP = 0x00200030, + MLAN_OID_MISC_IPV6_RA_OFFLOAD = 0x00200036, MLAN_OID_MISC_GTK_REKEY_OFFLOAD = 0x00200037, MLAN_OID_MISC_OPER_CLASS = 0x00200038, MLAN_OID_MISC_PMIC_CFG = 0x00200039, @@ -340,6 +341,11 @@ enum _mlan_ioctl_req_id { MLAN_OID_MISC_TP_STATE = 0x0020007D, MLAN_OID_MISC_HAL_PHY_CFG = 0x0020007E, MLAN_OID_MISC_RF_TEST_HE_POWER = 0X0020007F, +#ifdef UAP_SUPPORT + MLAN_OID_MISC_WACP_MODE = 0x00200081, +#endif + MLAN_OID_MISC_GPIO_TSF_LATCH = 0x00200082, + MLAN_OID_MISC_GET_TSF_INFO = 0x00200083, }; /** Sub command size */ @@ -1646,6 +1652,14 @@ typedef struct _mlan_ds_get_stats { t_u32 dwMgtErrCnt; /*Control Ownership error count*/ t_u32 dwDatErrCnt; + /*BIGTK MME good count*/ + t_u32 bigtk_mmeGoodCnt; + /*BIGTK Replay error count*/ + t_u32 bigtk_replayErrCnt; + /*BIGTK MIC error count*/ + t_u32 bigtk_micErrCnt; + /*BIGTK MME not included count*/ + t_u32 bigtk_mmeNotFoundCnt; } mlan_ds_get_stats, *pmlan_ds_get_stats; /** Type definition of mlan_ds_uap_stats for MLAN_OID_GET_STATS */ @@ -1827,6 +1841,8 @@ typedef struct _mlan_fw_info { t_u8 max_ap_assoc_sta; /** Bandwidth not support 80Mhz */ t_u8 prohibit_80mhz; + /** FW support beacon protection */ + t_u8 fw_beacon_prot; } mlan_fw_info, *pmlan_fw_info; /** Version string buffer length */ @@ -1844,6 +1860,14 @@ typedef struct _mlan_ver_ext { /** Extended Capabilities Data */ typedef struct MLAN_PACK_START _ExtCap_t { /** Extended Capabilities value */ + t_u8 rsvdBit87 : 1; /* bit 87 */ + t_u8 rsvdBit86 : 1; /* bit 86 */ + t_u8 rsvdBit85 : 1; /* bit 85 */ + t_u8 beacon_prot : 1; /* bit 84 */ + t_u8 rsvdBit83 : 1; /* bit 83 */ + t_u8 rsvdBit82 : 1; /* bit 82 */ + t_u8 rsvdBit81 : 1; /* bit 81 */ + t_u8 rsvdBit80 : 1; /* bit 80 */ t_u8 rsvdBit79 : 1; /* bit 79 */ t_u8 TWTResp : 1; /* bit 78 */ t_u8 TWTReq : 1; /* bit 77 */ @@ -2009,6 +2033,14 @@ typedef struct MLAN_PACK_START _ExtCap_t { t_u8 TWTReq : 1; /* bit 77 */ t_u8 TWTResp : 1; /* bit 78 */ t_u8 rsvdBit79 : 1; /* bit 79 */ + t_u8 rsvdBit80 : 1; /* bit 80 */ + t_u8 rsvdBit81 : 1; /* bit 81 */ + t_u8 rsvdBit82 : 1; /* bit 82 */ + t_u8 rsvdBit83 : 1; /* bit 83 */ + t_u8 beacon_prot : 1; /* bit 84 */ + t_u8 rsvdBit85 : 1; /* bit 85 */ + t_u8 rsvdBit86 : 1; /* bit 86 */ + t_u8 rsvdBit87 : 1; /* bit 87 */ } MLAN_PACK_END ExtCap_t, *pExtCap_t; #endif @@ -2215,7 +2247,7 @@ typedef struct _mlan_debug_info { /** Corresponds to port_open member of mlan_private */ t_u8 port_open; /** bypass pkt count */ - t_u16 bypass_pkt_count; + t_u32 bypass_pkt_count; /** Corresponds to scan_processing member of mlan_adapter */ t_u32 scan_processing; /** Corresponds to mlan_processing member of mlan_adapter */ @@ -2265,6 +2297,10 @@ typedef struct _mlan_debug_info { t_u32 mpa_sent_no_ports; /** last recv wr_bitmap */ t_u32 last_recv_wr_bitmap; + /** last recv rd_bitmap */ + t_u32 last_recv_rd_bitmap; + /** mp_data_port_mask */ + t_u32 mp_data_port_mask; /** last mp_wr_bitmap */ t_u32 last_mp_wr_bitmap[SDIO_MP_DBG_NUM]; /** last ports for cmd53 write data */ @@ -2480,7 +2516,7 @@ typedef enum { AssocAgentAuth_FastBss, AssocAgentAuth_FastBss_Skip, AssocAgentAuth_Network_EAP, - AssocAgentAuth_Wpa3Sae, + AssocAgentAuth_Wpa3Sae = 6, AssocAgentAuth_Auto, } AssocAgentAuthType_e; @@ -2549,6 +2585,10 @@ enum _mlan_psk_type { #define KEY_FLAG_GCMP_256 0x00000040 /** key flag for ccmp 256 */ #define KEY_FLAG_CCMP_256 0x00000080 +/** key flag for GMAC_128 */ +#define KEY_FLAG_GMAC_128 0x00000100 +/** key flag for GMAC_256 */ +#define KEY_FLAG_GMAC_256 0x00000200 /** Type definition of mlan_ds_encrypt_key for MLAN_OID_SEC_CFG_ENCRYPT_KEY */ typedef struct _mlan_ds_encrypt_key { @@ -4219,6 +4259,9 @@ typedef struct _mlan_ds_11h_cfg { /** Enumeration for IE type */ enum _mlan_ie_type { MLAN_IE_TYPE_GEN_IE = 0, +#ifdef STA_SUPPORT + MLAN_IE_TYPE_ARP_FILTER, +#endif /* STA_SUPPORT */ }; /** Type definition of mlan_ds_misc_gen_ie for MLAN_OID_MISC_GEN_IE */ @@ -4376,6 +4419,8 @@ typedef struct _mlan_ds_misc_cck_desense_cfg { #define IPADDR_TYPE_IPV4 (1) /** IP operation remove */ #define MLAN_IPADDR_OP_IP_REMOVE (0) +/** IP operation ARP filter */ +#define MLAN_IPADDR_OP_ARP_FILTER MBIT(0) /** IP operation ARP response */ #define MLAN_IPADDR_OP_AUTO_ARP_RESP MBIT(1) @@ -4391,6 +4436,14 @@ typedef struct _mlan_ds_misc_ipaddr_cfg { t_u8 ip_addr[MAX_IPADDR][IPADDR_LEN]; } mlan_ds_misc_ipaddr_cfg; +/** Type definnition of mlan_ds_misc_ipv6_ra_offload for + * MLAN_OID_MISC_IPV6_RA_OFFLOAD*/ +typedef struct _mlan_ds_misc_ipv6_ra_offload { + /** 0: disable; 1: enable*/ + t_u8 enable; + t_u8 ipv6_addr[16]; +} mlan_ds_misc_ipv6_ra_offload; + /* MEF configuration disable */ #define MEF_CFG_DISABLE 0 /* MEF configuration Rx filter enable */ @@ -4647,6 +4700,33 @@ typedef struct _mlan_ds_wifi_direct_config { } mlan_ds_wifi_direct_config; #endif +/** Type definition of mlan_ds_gpio_tsf_latch */ +typedef struct _mlan_ds_gpio_tsf_latch { + /**clock sync Mode */ + t_u8 clock_sync_mode; + /**clock sync Role */ + t_u8 clock_sync_Role; + /**clock sync GPIO Pin Number */ + t_u8 clock_sync_gpio_pin_number; + /**clock sync GPIO Level or Toggle */ + t_u8 clock_sync_gpio_level_toggle; + /**clock sync GPIO Pulse Width */ + t_u16 clock_sync_gpio_pulse_width; +} mlan_ds_gpio_tsf_latch; + +/** Type definition of mlan_ds_tsf_info */ +typedef struct _mlan_ds_tsf_info { + /**get tsf info format */ + t_u16 tsf_format; + /**tsf info */ + t_u16 tsf_info; + /**tsf */ + t_u64 tsf; + /**Positive or negative offset in microsecond from Beacon TSF to GPIO + * toggle TSF */ + t_s32 tsf_offset; +} mlan_ds_tsf_info; + #if defined(STA_SUPPORT) typedef struct _mlan_ds_misc_pmfcfg { /** Management Frame Protection Capable */ @@ -4851,6 +4931,8 @@ typedef struct _mef_entry_t { typedef struct _mlan_ds_misc_mef_flt_cfg { /** Type of action*/ int mef_act_type; + /** Operation code*/ + t_u32 op_code; /** NV Filter Criteria*/ t_u32 criteria; /** NV MEF entry*/ @@ -5236,6 +5318,8 @@ typedef struct _mlan_ds_misc_cfg { mlan_ds_misc_tx_datapause tx_datapause; /** IP address configuration */ mlan_ds_misc_ipaddr_cfg ipaddr_cfg; + /** IPv6 Router Advertisement offload configuration */ + mlan_ds_misc_ipv6_ra_offload ipv6_ra_offload; /** MAC control for MLAN_OID_MISC_MAC_CONTROL */ t_u32 mac_ctrl; /** MEF configuration for MLAN_OID_MISC_MEF_CFG */ @@ -5274,6 +5358,8 @@ typedef struct _mlan_ds_misc_cfg { #ifdef WIFI_DIRECT_SUPPORT mlan_ds_wifi_direct_config p2p_config; #endif + mlan_ds_gpio_tsf_latch gpio_tsf_latch_config; + mlan_ds_tsf_info tsf_info; mlan_ds_coalesce_cfg coalesce_cfg; t_u8 low_pwr_mode; /** MEF-FLT-CONFIG for MLAN_OID_MISC_NV_FLT_CFG */ @@ -5325,6 +5411,9 @@ typedef struct _mlan_ds_misc_cfg { mlan_ds_misc_dot11mc_unassoc_ftm_cfg dot11mc_unassoc_ftm_cfg; mlan_ds_misc_tp_state tp_state; mlan_ds_hal_phy_cfg_params hal_phy_cfg_params; +#ifdef UAP_SUPPORT + t_u8 wacp_mode; +#endif } param; } mlan_ds_misc_cfg, *pmlan_ds_misc_cfg; diff --git a/mxm_wifiex/wlan_src/mlinux/moal_cfg80211.c b/mxm_wifiex/wlan_src/mlinux/moal_cfg80211.c index 3343843..bafe406 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_cfg80211.c +++ b/mxm_wifiex/wlan_src/mlinux/moal_cfg80211.c @@ -412,6 +412,7 @@ mlan_status woal_cfg80211_set_key(moal_private *priv, t_u8 is_enable_wep, cipher != WLAN_CIPHER_SUITE_GCMP && #endif #if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE + cipher != WLAN_CIPHER_SUITE_BIP_GMAC_128 && cipher != WLAN_CIPHER_SUITE_BIP_GMAC_256 && cipher != WLAN_CIPHER_SUITE_GCMP_256 && #endif @@ -480,11 +481,21 @@ mlan_status woal_cfg80211_set_key(moal_private *priv, t_u8 is_enable_wep, if (cipher == WLAN_CIPHER_SUITE_AES_CMAC #if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE - || cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 + || cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 || + cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 #endif ) { sec->param.encrypt_key.key_flags |= KEY_FLAG_AES_MCAST_IGTK; + +#if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE + if (cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128) + sec->param.encrypt_key.key_flags |= + KEY_FLAG_GMAC_128; + else if (cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256) + sec->param.encrypt_key.key_flags |= + KEY_FLAG_GMAC_256; +#endif } } else { if (key_index == KEY_INDEX_CLEAR_ALL) @@ -1511,6 +1522,17 @@ int woal_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, } #endif +#if KERNEL_VERSION(5, 10, 0) <= CFG80211_VERSION_CODE +int woal_cfg80211_set_default_beacon_key(struct wiphy *wiphy, + struct net_device *netdev, + t_u8 key_index) +{ + PRINTM(MINFO, "set default beacon key, key index=%d\n", key_index); + + return 0; +} +#endif + #if KERNEL_VERSION(3, 1, 0) <= CFG80211_VERSION_CODE /** * @brief Set GTK rekey data to driver @@ -4599,7 +4621,47 @@ void woal_cfg80211_notify_sched_scan_stop(moal_private *priv) #endif ); priv->sched_scanning = MFALSE; - PRINTM(MEVENT, "Sched_Scan stopped\n"); + PRINTM(MEVENT, "Notify sched scan stopped\n"); +} + +/** + * @brief sched_scan work handler + * + * @param work a pointer to work_struct + * + * @return 0 -- success, otherwise fail + */ +void woal_sched_scan_work_queue(struct work_struct *work) +{ + struct delayed_work *delayed_work = + container_of(work, struct delayed_work, work); + moal_private *priv = + container_of(delayed_work, moal_private, sched_scan_work); + ENTER(); + + if (priv->sched_scanning) + woal_cfg80211_notify_sched_scan_stop(priv); + + LEAVE(); +} + +/** + * @brief report sched_scan result to kernel + * + * @param priv A pointer moal_private structure + * + * @return N/A + */ +void woal_report_sched_scan_result(moal_private *priv) +{ + cfg80211_sched_scan_results(priv->wdev->wiphy +#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) + , + priv->bg_scan_reqid +#endif + ); + queue_delayed_work(priv->sched_scan_workqueue, &priv->sched_scan_work, + msecs_to_jiffies(2000)); } #endif #endif diff --git a/mxm_wifiex/wlan_src/mlinux/moal_cfg80211.h b/mxm_wifiex/wlan_src/mlinux/moal_cfg80211.h index 6bafc1b..d723540 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_cfg80211.h +++ b/mxm_wifiex/wlan_src/mlinux/moal_cfg80211.h @@ -48,6 +48,9 @@ #define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06 #endif #if KERNEL_VERSION(4, 0, 0) <= CFG80211_VERSION_CODE +#ifndef WLAN_CIPHER_SUITE_BIP_GMAC_128 +#define WLAN_CIPHER_SUITE_BIP_GMAC_128 0x000FAC0B +#endif #ifndef WLAN_CIPHER_SUITE_BIP_GMAC_256 #define WLAN_CIPHER_SUITE_BIP_GMAC_256 0x000FAC0C #endif @@ -206,6 +209,12 @@ int woal_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, t_u8 key_index); #endif +#if KERNEL_VERSION(5, 10, 0) <= CFG80211_VERSION_CODE +int woal_cfg80211_set_default_beacon_key(struct wiphy *wiphy, + struct net_device *netdev, + t_u8 key_index); +#endif + #if KERNEL_VERSION(3, 1, 0) <= CFG80211_VERSION_CODE int woal_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_gtk_rekey_data *data); @@ -356,7 +365,7 @@ int woal_cfg80211_deinit_p2p(moal_private *priv); #endif /* WIFI_DIRECT_SUPPORT */ /** Define for remain on channel duration timer */ -#define MAX_REMAIN_ON_CHANNEL_DURATION (1000) +#define MAX_REMAIN_ON_CHANNEL_DURATION (5000) int woal_cfg80211_remain_on_channel_cfg(moal_private *priv, t_u8 wait_option, t_u8 remove, t_u8 *status, @@ -453,6 +462,8 @@ void woal_channel_switch_event(moal_private *priv, chan_band_info *pchan_info); #if KERNEL_VERSION(3, 2, 0) <= CFG80211_VERSION_CODE void woal_bgscan_stop_event(moal_private *priv); void woal_cfg80211_notify_sched_scan_stop(moal_private *priv); +void woal_sched_scan_work_queue(struct work_struct *work); +void woal_report_sched_scan_result(moal_private *priv); #endif #endif diff --git a/mxm_wifiex/wlan_src/mlinux/moal_cfg80211_util.c b/mxm_wifiex/wlan_src/mlinux/moal_cfg80211_util.c index 8dd2404..d5289db 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_cfg80211_util.c +++ b/mxm_wifiex/wlan_src/mlinux/moal_cfg80211_util.c @@ -48,6 +48,10 @@ static const struct nl80211_vendor_cmd_info vendor_events[] = { .vendor_id = MRVL_VENDOR_ID, .subcmd = event_hang, }, /*event_id 0*/ + { + .vendor_id = MRVL_VENDOR_ID, + .subcmd = event_fw_dump_done, + }, /*event_id 1*/ { .vendor_id = MRVL_VENDOR_ID, .subcmd = event_rssi_monitor, @@ -242,6 +246,20 @@ int woal_cfg80211_vendor_event(moal_private *priv, int event, t_u8 *data, return ret; } +/** + * @brief send fw dump complete event to vendorhal + * + * @param priv A pointer to moal_private + * + * @return N/A + */ +void woal_cfg80211_vendor_event_fw_dump(moal_private *priv) +{ + PRINTM(MEVENT, "wlan: Notify FW dump complete event\n"); + woal_cfg80211_vendor_event(priv, event_fw_dump_done, CUS_EVT_FW_DUMP, + strlen(CUS_EVT_FW_DUMP)); +} + /** * @brief send dfs vendor event to kernel * @@ -675,7 +693,6 @@ static int woal_cfg80211_subcmd_get_drv_dump(struct wiphy *wiphy, int ret = MLAN_STATUS_SUCCESS; int length = 0; char driver_dump_file[128]; - char path_name[64]; struct sk_buff *skb = NULL; ENTER(); @@ -687,12 +704,12 @@ static int woal_cfg80211_subcmd_get_drv_dump(struct wiphy *wiphy, dev = wdev->netdev; priv = (moal_private *)woal_get_netdev_priv(dev); handle = priv->phandle; - memset(path_name, 0, sizeof(path_name)); - woal_create_dump_dir(handle, path_name, sizeof(path_name)); - PRINTM(MMSG, "driver dump path name is %s\n", path_name); - woal_dump_drv_info(handle, path_name); memset(driver_dump_file, 0, sizeof(driver_dump_file)); - sprintf(driver_dump_file, "%s/%s", path_name, "file_drv_info"); + sprintf(driver_dump_file, "/proc/mwlan/"); + if (handle->handle_idx) + sprintf(driver_dump_file, "drv_dump%d", handle->handle_idx); + else + sprintf(driver_dump_file, "drv_dump"); PRINTM(MMSG, "driver dump file is %s\n", driver_dump_file); length = sizeof(driver_dump_file); skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, length); @@ -2762,9 +2779,6 @@ static int woal_cfg80211_subcmd_link_statistic_get(struct wiphy *wiphy, t_u64 max_msec = (t_u64)24 * (t_u64)24 * (t_u64)3600 * (t_u64)1000; moal_handle *handle = priv->phandle; - if (priv->media_connected == MFALSE) - return -EFAULT; - /* Allocate an IOCTL request buffer */ req = woal_alloc_mlan_ioctl_req(sizeof(t_u32) + BUF_MAXLEN); if (req == NULL) { diff --git a/mxm_wifiex/wlan_src/mlinux/moal_cfg80211_util.h b/mxm_wifiex/wlan_src/mlinux/moal_cfg80211_util.h index d1c3f3b..95781f0 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_cfg80211_util.h +++ b/mxm_wifiex/wlan_src/mlinux/moal_cfg80211_util.h @@ -603,6 +603,7 @@ enum mrvl_wlan_vendor_attr_wifi_logger { /**vendor event*/ enum vendor_event { event_hang = 0, + event_fw_dump_done = 1, event_rssi_monitor = 0x1501, event_cloud_keep_alive = 0x10003, event_dfs_radar_detected = 0x10004, diff --git a/mxm_wifiex/wlan_src/mlinux/moal_debug.c b/mxm_wifiex/wlan_src/mlinux/moal_debug.c index 2192610..a158702 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_debug.c +++ b/mxm_wifiex/wlan_src/mlinux/moal_debug.c @@ -1032,6 +1032,9 @@ static int woal_debug_read(struct seq_file *sfp, void *data) mp_aggr_pkt_limit = info->mp_aggr_pkt_limit; seq_printf(sfp, "last_recv_wr_bitmap=0x%x last_mp_index=%d\n", info->last_recv_wr_bitmap, info->last_mp_index); + seq_printf(sfp, + "last_recv_rd_bitmap=0x%x mp_data_port_mask=0x%x\n", + info->last_recv_rd_bitmap, info->mp_data_port_mask); for (i = 0; i < SDIO_MP_DBG_NUM; i++) { seq_printf( sfp, @@ -1076,6 +1079,7 @@ static int woal_debug_read(struct seq_file *sfp, void *data) #endif seq_printf(sfp, "tcp_ack_drop_cnt=%d\n", priv->tcp_ack_drop_cnt); seq_printf(sfp, "tcp_ack_cnt=%d\n", priv->tcp_ack_cnt); + seq_printf(sfp, "tcp_ack_payload=%d\n", priv->tcp_ack_payload); #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29) for (i = 0; i < 4; i++) seq_printf(sfp, "wmm_tx_pending[%d]:%d\n", i, diff --git a/mxm_wifiex/wlan_src/mlinux/moal_eth_ioctl.c b/mxm_wifiex/wlan_src/mlinux/moal_eth_ioctl.c index 8b12de3..be9f40e 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_eth_ioctl.c +++ b/mxm_wifiex/wlan_src/mlinux/moal_eth_ioctl.c @@ -6552,6 +6552,58 @@ done: } #endif /* SDIO */ +#ifdef STA_SUPPORT +/** + * @brief arpfilter ioctl function + * + * @param priv A pointer to moal_private structure + * @param respbuf A pointer to response buffer + * @param respbuflen Available length of response buffer + * + * @return 0 --success, otherwise fail + */ +static int woal_priv_arpfilter(moal_private *priv, t_u8 *respbuf, + t_u32 respbuflen) +{ + int ret = 0; + mlan_ds_misc_cfg *misc = NULL; + mlan_ioctl_req *req = NULL; + t_u8 *data_ptr = NULL; + t_u32 buf_len = 0; + mlan_status status = MLAN_STATUS_SUCCESS; + + ENTER(); + + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + misc = (mlan_ds_misc_cfg *)req->pbuf; + misc->sub_command = MLAN_OID_MISC_GEN_IE; + req->req_id = MLAN_IOCTL_MISC_CFG; + req->action = MLAN_ACT_SET; + misc->param.gen_ie.type = MLAN_IE_TYPE_ARP_FILTER; + + data_ptr = respbuf + (strlen(CMD_NXP) + strlen(PRIV_CMD_ARPFILTER)); + buf_len = *((t_u16 *)data_ptr); + misc->param.gen_ie.len = buf_len; + moal_memcpy_ext(priv->phandle, (void *)(misc->param.gen_ie.ie_data), + data_ptr + sizeof(buf_len), buf_len, MAX_IE_SIZE); + + status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT); + if (status != MLAN_STATUS_SUCCESS) { + ret = -EFAULT; + goto done; + } +done: + if (status != MLAN_STATUS_PENDING) + kfree(req); + LEAVE(); + return ret; +} +#endif /* STA_SUPPORT */ + /** * @brief Set / Get Auto ARP Response configuration * @@ -10889,6 +10941,7 @@ static int woal_channel_switch(moal_private *priv, t_u8 block_tx, pvhttpcEnv_ie->local_max_tp_20mhz = 0xff; pvhttpcEnv_ie->local_max_tp_40mhz = 0xff; pvhttpcEnv_ie->local_max_tp_80mhz = 0xff; + pvhttpcEnv_ie->local_max_tp_160mhz_80_80mhz = 0xff; pChanSwWrap_ie->len += sizeof(IEEEtypes_VhtTpcEnvelope_t); pcust_chansw_ie->ie_length += pChanSwWrap_ie->len + sizeof(IEEEtypes_Header_t); @@ -12801,6 +12854,192 @@ done: #endif #endif +/** + * @brief Set/Get GPIO TSF latch clock sync config parameters + * @param priv Pointer to moal_private structure + * @param respbuf Pointer to response buffer + * @param resplen Response buffer length + * + * @return Number of bytes written, negative for failure. + */ +static int woal_priv_cfg_clock_sync(moal_private *priv, t_u8 *respbuf, + t_u32 respbuflen) +{ + int header_len = 0, user_data_len = 0; + int ret = 0, data[5]; + mlan_ds_gpio_tsf_latch *clock_sync_cfg = NULL; + mlan_ioctl_req *req = NULL; + mlan_ds_misc_cfg *misc_cfg = NULL; + mlan_status status = MLAN_STATUS_SUCCESS; + + ENTER(); + + header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_CFG_CLOCK_SYNC); + + memset(data, 0, sizeof(data)); + parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data), + &user_data_len); + + if (user_data_len > 5) { + PRINTM(MERROR, "invalid parameters\n"); + ret = -EINVAL; + goto done; + } + + /* Allocate an IOCTL request buffer */ + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + + /* Fill request buffer */ + req->req_id = MLAN_IOCTL_MISC_CFG; + misc_cfg = (mlan_ds_misc_cfg *)req->pbuf; + misc_cfg->sub_command = MLAN_OID_MISC_GPIO_TSF_LATCH; + clock_sync_cfg = &misc_cfg->param.gpio_tsf_latch_config; + memset(clock_sync_cfg, 0, sizeof(mlan_ds_gpio_tsf_latch)); + + if ((int)strlen(respbuf) == header_len) { + /* GET operation */ + req->action = MLAN_ACT_GET; + user_data_len = 0; + } else { + req->action = MLAN_ACT_SET; + switch (user_data_len) { + case 5: + clock_sync_cfg->clock_sync_gpio_pulse_width = + (t_u16)data[4]; + /* fall through */ + case 4: + if (data[3] < 0 || data[3] > 1) { + PRINTM(MERROR, "Invalid Level/Trigger\n"); + ret = -EINVAL; + goto done; + } + clock_sync_cfg->clock_sync_gpio_level_toggle = + (t_u8)data[3]; + /* fall through */ + case 3: + if (data[2] < 1 || data[2] > 255) { + PRINTM(MERROR, + "Invalid number of GPIO Pin Number\n"); + ret = -EINVAL; + goto done; + } + clock_sync_cfg->clock_sync_gpio_pin_number = + (t_u8)data[2]; + /* fall through */ + case 2: + if (data[1] < 0 || data[1] > 2) { + PRINTM(MERROR, "Invalid Role\n"); + ret = -EINVAL; + goto done; + } + clock_sync_cfg->clock_sync_Role = (t_u8)data[1]; + /* fall through */ + case 1: + if (data[0] < 0 || data[0] > 2) { + PRINTM(MERROR, "Invalid Mode\n"); + ret = -EINVAL; + goto done; + } + clock_sync_cfg->clock_sync_mode = (t_u8)data[0]; + break; + default: + break; + } + } + /* Send IOCTL request to MLAN */ + status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT); + if (status != MLAN_STATUS_SUCCESS) { + ret = -EFAULT; + goto done; + } + + if (!user_data_len) { + moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)clock_sync_cfg, + sizeof(mlan_ds_gpio_tsf_latch), respbuflen); + ret = sizeof(mlan_ds_gpio_tsf_latch); + } + +done: + if (status != MLAN_STATUS_PENDING) + kfree(req); + + LEAVE(); + return ret; +} + +/** + * @brief Set/Get GPIO TSF latch get tsf info config parameters + * @param priv Pointer to moal_private structure + * @param respbuf Pointer to response buffer + * @param resplen Response buffer length + * + * @return Number of bytes written, negative for failure. + */ +static int woal_priv_cfg_get_tsf_info(moal_private *priv, t_u8 *respbuf, + t_u32 respbuflen) +{ + int header_len = 0, user_data_len = 0; + int ret = 0, data[1]; + mlan_ds_tsf_info *tsf_info; + mlan_ioctl_req *req = NULL; + mlan_ds_misc_cfg *misc_cfg = NULL; + mlan_status status = MLAN_STATUS_SUCCESS; + + ENTER(); + + header_len = strlen(CMD_NXP) + strlen(PRIV_CMD_CFG_GET_TSF_INFO); + + memset(data, 0, sizeof(data)); + parse_arguments(respbuf + header_len, data, ARRAY_SIZE(data), + &user_data_len); + + if (user_data_len > 1) { + PRINTM(MERROR, "invalid parameters\n"); + ret = -EINVAL; + goto done; + } + /* Allocate an IOCTL request buffer */ + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + + /* Fill request buffer */ + req->req_id = MLAN_IOCTL_MISC_CFG; + req->action = MLAN_ACT_GET; + misc_cfg = (mlan_ds_misc_cfg *)req->pbuf; + misc_cfg->sub_command = MLAN_OID_MISC_GET_TSF_INFO; + tsf_info = &misc_cfg->param.tsf_info; + memset(tsf_info, 0, sizeof(mlan_ds_tsf_info)); + if (user_data_len == 1) { + if (data[0] < 0 || data[0] > 1) { + PRINTM(MERROR, "Invalid tsf Format\n"); + ret = -EINVAL; + goto done; + } + tsf_info->tsf_format = data[0]; + } + status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT); + if (status != MLAN_STATUS_SUCCESS) { + ret = -EFAULT; + goto done; + } + moal_memcpy_ext(priv->phandle, respbuf, (t_u8 *)tsf_info, + sizeof(mlan_ds_tsf_info), respbuflen); + ret = sizeof(mlan_ds_tsf_info); +done: + if (status != MLAN_STATUS_PENDING) + kfree(req); + + LEAVE(); + return ret; +} + #if defined(STA_CFG80211) || defined(UAP_CFG80211) #ifdef WIFI_DIRECT_SUPPORT #define DEF_NOA_INTERVAL 100 @@ -15875,6 +16114,14 @@ int woal_android_priv_cmd(struct net_device *dev, struct ifreq *req) strlen(PRIV_CMD_HAL_PHY_CFG) - strlen(CMD_NXP); len = woal_priv_hal_phy_cfg_cmd(priv, pdata, len); goto handled; +#ifdef STA_SUPPORT + } else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_ARPFILTER, + strlen(PRIV_CMD_ARPFILTER)) == 0) { + /* ARPFilter Configuration */ + len = woal_priv_arpfilter(priv, buf, + priv_cmd.total_len); + goto handled; +#endif } else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_AUTO_ARP, strlen(PRIV_CMD_AUTO_ARP)) == 0) { /* Auto ARP enable/disable */ @@ -16266,6 +16513,20 @@ int woal_android_priv_cmd(struct net_device *dev, struct ifreq *req) goto handled; #endif #endif + } else if (strnicmp(buf + strlen(CMD_NXP), + PRIV_CMD_CFG_CLOCK_SYNC, + strlen(PRIV_CMD_CFG_CLOCK_SYNC)) == 0) { + /* Set/Get P2P NoA (Notice of Absence) parameters */ + len = woal_priv_cfg_clock_sync(priv, buf, + priv_cmd.total_len); + goto handled; + } else if (strnicmp(buf + strlen(CMD_NXP), + PRIV_CMD_CFG_GET_TSF_INFO, + strlen(PRIV_CMD_CFG_GET_TSF_INFO)) == 0) { + /* Set/Get P2P OPP-PS parameters */ + len = woal_priv_cfg_get_tsf_info(priv, buf, + priv_cmd.total_len); + goto handled; } else if (strnicmp(buf + strlen(CMD_NXP), PRIV_CMD_DFS_REPEATER_CFG, strlen(PRIV_CMD_DFS_REPEATER_CFG)) == 0) { @@ -17179,10 +17440,12 @@ int wlan_get_scan_table_ret_entry(BSSDescriptor_t *pbss_desc, t_u8 **ppbuffer, * @return 0 --success, otherwise fail */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) -int woal_do_ioctl(struct net_device *dev, struct ifreq *req, void __user *data, int cmd) +int woal_do_ioctl(struct net_device *dev, struct ifreq *req, void __user *data, + int cmd) #else int woal_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd) #endif + { int ret = 0; diff --git a/mxm_wifiex/wlan_src/mlinux/moal_eth_ioctl.h b/mxm_wifiex/wlan_src/mlinux/moal_eth_ioctl.h index 450b3ad..460c97b 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_eth_ioctl.h +++ b/mxm_wifiex/wlan_src/mlinux/moal_eth_ioctl.h @@ -148,6 +148,7 @@ typedef struct _chan_stats { #ifdef SDIO #define PRIV_CMD_SDCMD52RW "sdcmd52rw" #endif +#define PRIV_CMD_ARPFILTER "arpfilter" #define PRIV_CMD_HOTSPOTCFG "hotspotcfg" #define PRIV_CMD_MGMT_FRAME_CTRL "mgmtframectrl" #define PRIV_CMD_QCONFIG "qconfig" @@ -235,6 +236,8 @@ typedef struct _chan_stats { #define PRIV_CMD_CFG_OPP_PS "cfg_opp_ps" #endif #endif +#define PRIV_CMD_CFG_CLOCK_SYNC "clocksync" +#define PRIV_CMD_CFG_GET_TSF_INFO "gettsfinfo" #define PRIV_CMD_DFS_REPEATER_CFG "dfs_repeater" #ifdef WIFI_DIRECT_SUPPORT #if defined(STA_CFG80211) || defined(UAP_CFG80211) @@ -365,11 +368,11 @@ typedef struct _ssu_params_cfg { #define PRIV_CMD_LPM "lpm" #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) -int woal_do_ioctl(struct net_device *dev, struct ifreq *req, void __user *data, int cmd); +int woal_do_ioctl(struct net_device *dev, struct ifreq *req, void __user *data, + int cmd); #else int woal_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd); #endif - /* * For android private commands, fixed value of ioctl is used. * Internally commands are differentiated using strings. diff --git a/mxm_wifiex/wlan_src/mlinux/moal_init.c b/mxm_wifiex/wlan_src/mlinux/moal_init.c index d46cb7d..dfeb7da 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_init.c +++ b/mxm_wifiex/wlan_src/mlinux/moal_init.c @@ -66,12 +66,19 @@ static int host_mlme; /** Auto deep sleep */ static int auto_ds; +/** net_rx mode*/ +static int net_rx; + +static int ext_scan; + /** IEEE PS mode */ static int ps_mode; /** passive to active scan */ static int p2a_scan; /** scan chan gap */ static int scan_chan_gap; +/** sched scan */ +static int sched_scan = 1; /** Max Tx buffer size */ int max_tx_buf; @@ -89,6 +96,8 @@ static int max_uap_bss = DEF_UAP_BSS; static char *uap_name; /** Max uAP station number */ static int uap_max_sta; +/** WACP mode */ +static int wacp_mode = WACP_MODE_DEFAULT; #endif #ifdef WIFI_DIRECT_SUPPORT @@ -116,6 +125,7 @@ static int slew_rate = 3; int tx_work = 0; static int rps = 0; static int tx_skb_clone = 0; +static int pmqos = 0; #if defined(STA_SUPPORT) /** 802.11d configuration */ @@ -147,7 +157,8 @@ static char *band_steer_cfg; #if defined(STA_WEXT) || defined(UAP_WEXT) /** CFG80211 and WEXT mode */ -static int cfg80211_wext = STA_WEXT_MASK | UAP_WEXT_MASK; +static int cfg80211_wext = + STA_WEXT_MASK | UAP_WEXT_MASK | STA_CFG80211_MASK | UAP_CFG80211_MASK; #else /** CFG80211 mode */ static int cfg80211_wext = STA_CFG80211_MASK | UAP_CFG80211_MASK; @@ -250,6 +261,9 @@ t_u32 drvdbg = DEFAULT_DEBUG_MASK; #endif /* DEBUG_LEVEL1 */ static card_type_entry card_type_map_tbl[] = { +#ifdef SD8801 + {CARD_TYPE_SD8801, 0, CARD_SD8801}, +#endif #ifdef SD8887 {CARD_TYPE_SD8887, 0, CARD_SD8887}, #endif @@ -289,6 +303,10 @@ static card_type_entry card_type_map_tbl[] = { #ifdef PCIE9098 {CARD_TYPE_PCIE9098, 0, CARD_PCIE9098}, #endif +#ifdef USB8801 + {CARD_TYPE_USB8801, 0, CARD_USB8801}, +#endif + #ifdef USB8897 {CARD_TYPE_USB8897, 0, CARD_USB8897}, #endif @@ -651,6 +669,18 @@ static mlan_status parse_cfg_read_block(t_u8 *data, t_u32 size, goto err; params->auto_ds = out_data; PRINTM(MMSG, "auto_ds = %d\n", params->auto_ds); + } else if (strncmp(line, "net_rx", strlen("net_rx")) == 0) { + if (parse_line_read_int(line, &out_data) != + MLAN_STATUS_SUCCESS) + goto err; + params->net_rx = out_data; + PRINTM(MMSG, "net_rx = %d\n", params->net_rx); + } else if (strncmp(line, "ext_scan", strlen("ext_scan")) == 0) { + if (parse_line_read_int(line, &out_data) != + MLAN_STATUS_SUCCESS) + goto err; + params->ext_scan = out_data; + PRINTM(MMSG, "ext_scan = %d\n", params->ext_scan); } else if (strncmp(line, "ps_mode", strlen("ps_mode")) == 0) { if (parse_line_read_int(line, &out_data) != MLAN_STATUS_SUCCESS) @@ -671,6 +701,13 @@ static mlan_status parse_cfg_read_block(t_u8 *data, t_u32 size, params->scan_chan_gap = out_data; PRINTM(MMSG, "scan_chan_gap = %d\n", params->scan_chan_gap); + } else if (strncmp(line, "sched_scan", strlen("sched_scan")) == + 0) { + if (parse_line_read_int(line, &out_data) != + MLAN_STATUS_SUCCESS) + goto err; + params->sched_scan = out_data; + PRINTM(MMSG, "sched_scan = %d\n", params->sched_scan); } else if (strncmp(line, "max_tx_buf", strlen("max_tx_buf")) == 0) { if (parse_line_read_int(line, &out_data) != @@ -1110,6 +1147,17 @@ static mlan_status parse_cfg_read_block(t_u8 *data, t_u32 size, moal_extflg_isset(handle, EXT_TX_SKB_CLONE) ? "on" : "off"); + } else if (strncmp(line, "pmqos", strlen("pmqos")) == 0) { + if (parse_line_read_int(line, &out_data) != + MLAN_STATUS_SUCCESS) + goto err; + if (out_data) + moal_extflg_set(handle, EXT_PMQOS); + else + moal_extflg_clear(handle, EXT_PMQOS); + PRINTM(MMSG, "pmqos %s\n", + moal_extflg_isset(handle, EXT_PMQOS) ? "on" : + "off"); } #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) else if (strncmp(line, "dfs_offload", strlen("dfs_offload")) == @@ -1192,6 +1240,13 @@ static mlan_status parse_cfg_read_block(t_u8 *data, t_u32 size, goto err; params->uap_max_sta = out_data; PRINTM(MMSG, "uap_max_sta=%d\n", params->uap_max_sta); + } else if (strncmp(line, "wacp_mode", strlen("wacp_mode")) == + 0) { + if (parse_line_read_int(line, &out_data) != + MLAN_STATUS_SUCCESS) + goto err; + params->wacp_mode = out_data; + PRINTM(MMSG, "wacp_moe=%d\n", params->wacp_mode); } #endif #if defined(STA_CFG80211) || defined(UAP_CFG80211) @@ -1282,10 +1337,12 @@ static void woal_setup_module_param(moal_handle *handle, moal_mod_para *params) handle->params.max_uap_bss = max_uap_bss; woal_dup_string(&handle->params.uap_name, uap_name); handle->params.uap_max_sta = uap_max_sta; + handle->params.wacp_mode = wacp_mode; if (params) { handle->params.max_uap_bss = params->max_uap_bss; woal_dup_string(&handle->params.uap_name, params->uap_name); handle->params.uap_max_sta = params->uap_max_sta; + handle->params.wacp_mode = params->wacp_mode; } #endif /* UAP_SUPPORT */ #ifdef WIFI_DIRECT_SUPPORT @@ -1304,15 +1361,25 @@ static void woal_setup_module_param(moal_handle *handle, moal_mod_para *params) handle->params.auto_ds = auto_ds; if (params) handle->params.auto_ds = params->auto_ds; + handle->params.net_rx = net_rx; + if (params) + handle->params.net_rx = params->net_rx; + + handle->params.ext_scan = ext_scan; + if (params) + handle->params.ext_scan = params->ext_scan; + handle->params.ps_mode = ps_mode; handle->params.p2a_scan = p2a_scan; handle->params.scan_chan_gap = scan_chan_gap; + handle->params.sched_scan = sched_scan; handle->params.max_tx_buf = max_tx_buf; if (params) { handle->params.ps_mode = params->ps_mode; handle->params.max_tx_buf = params->max_tx_buf; handle->params.p2a_scan = params->p2a_scan; handle->params.scan_chan_gap = params->scan_chan_gap; + handle->params.sched_scan = params->sched_scan; } #if defined(SDIO) if (intmode) @@ -1458,6 +1525,8 @@ static void woal_setup_module_param(moal_handle *handle, moal_mod_para *params) moal_extflg_set(handle, EXT_RPS); if (tx_skb_clone) moal_extflg_set(handle, EXT_TX_SKB_CLONE); + if (pmqos) + moal_extflg_set(handle, EXT_PMQOS); #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) if (dfs_offload) @@ -1682,6 +1751,11 @@ void woal_init_from_dev_tree(void) PRINTM(MIOCTL, "tx_skb_clone=0x%x\n", data); tx_skb_clone = data; } + } else if (!strncmp(prop->name, "pmqos", strlen("pmqos"))) { + if (!of_property_read_u32(dt_node, prop->name, &data)) { + PRINTM(MIOCTL, "pmqos=0x%x\n", data); + pmqos = data; + } } #ifdef MFG_CMD_SUPPORT else if (!strncmp(prop->name, "mfg_mode", strlen("mfg_mode"))) { @@ -1931,8 +2005,21 @@ void woal_init_from_dev_tree(void) PRINTM(MERROR, "uap_max_sta=0x%x\n", data); uap_max_sta = data; } + } else if (!strncmp(prop->name, "wacp_mode", + strlen("wacp_mode"))) { + if (!of_property_read_u32(dt_node, prop->name, &data)) { + PRINTM(MERROR, "wacp_mode=0x%x\n", data); + wacp_mode = data; + } } #endif + else if (!strncmp(prop->name, "sched_scan", + strlen("sched_scan"))) { + if (!of_property_read_u32(dt_node, prop->name, &data)) { + PRINTM(MIOCTL, "sched_scan=%d\n", data); + sched_scan = data; + } + } } LEAVE(); return; @@ -2179,6 +2266,10 @@ module_param(auto_ds, int, 0660); MODULE_PARM_DESC( auto_ds, "0: MLAN default; 1: Enable auto deep sleep; 2: Disable auto deep sleep"); +module_param(ext_scan, int, 0660); +MODULE_PARM_DESC( + ext_scan, + "0: MLAN default; 1: Enable Extended Scan; 2: Enable Enhanced Extended Scan"); module_param(ps_mode, int, 0660); MODULE_PARM_DESC( ps_mode, @@ -2191,6 +2282,9 @@ module_param(scan_chan_gap, int, 0660); MODULE_PARM_DESC( scan_chan_gap, "Time gap between two scans in milliseconds when connected to AP(max value 500ms)"); +module_param(sched_scan, int, 0); +MODULE_PARM_DESC(sched_scan, + "0: disable sched_scan; 1: enable sched_scan default"); module_param(max_tx_buf, int, 0); MODULE_PARM_DESC(max_tx_buf, "Maximum Tx buffer size (2048/4096/8192)"); @@ -2226,6 +2320,8 @@ MODULE_PARM_DESC(rps, "1: Enable rps; 0: Disable rps"); module_param(tx_skb_clone, uint, 0660); MODULE_PARM_DESC(tx_skb_clone, "1: Enable tx_skb_clone; 0: Disable tx_skb_clone"); +module_param(pmqos, uint, 0660); +MODULE_PARM_DESC(pmqos, "1: Enable pmqos; 0: Disable pmqos"); module_param(dpd_data_cfg, charp, 0); MODULE_PARM_DESC(dpd_data_cfg, "DPD data file name"); @@ -2289,7 +2385,9 @@ MODULE_PARM_DESC(wakelock_timeout, "set wakelock_timeout value (ms)"); module_param(dev_cap_mask, uint, 0); MODULE_PARM_DESC(dev_cap_mask, "Device capability mask"); - +module_param(net_rx, int, 0); +MODULE_PARM_DESC(net_rx, + "0: use netif_rx_ni in rx; 1: use netif_receive_skb in rx"); #ifdef SDIO module_param(sdio_rx_aggr, int, 0); MODULE_PARM_DESC(sdio_rx_aggr, @@ -2364,6 +2462,10 @@ MODULE_PARM_DESC(dfs_offload, "1: enable dfs offload; 0: disable dfs offload."); #ifdef UAP_SUPPORT module_param(uap_max_sta, int, 0); MODULE_PARM_DESC(uap_max_sta, "Maximum station number for UAP/GO."); +module_param(wacp_mode, int, 0); +MODULE_PARM_DESC( + wacp_mode, + "WACP mode for UAP/GO 0: WACP_MODE_DEFAULT; 1: WACP_MODE_1; 2: WACP_MODE_2"); #endif #if defined(STA_CFG80211) || defined(UAP_CFG80211) #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) diff --git a/mxm_wifiex/wlan_src/mlinux/moal_ioctl.c b/mxm_wifiex/wlan_src/mlinux/moal_ioctl.c index 8e4f209..8a19127 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_ioctl.c +++ b/mxm_wifiex/wlan_src/mlinux/moal_ioctl.c @@ -626,7 +626,8 @@ mlan_status woal_request_ioctl(moal_private *priv, mlan_ioctl_req *req, sub_command = *(t_u32 *)req->pbuf; - if (sub_command != MLAN_OID_GET_DEBUG_INFO) { + if (sub_command != MLAN_OID_GET_DEBUG_INFO && + sub_command != MLAN_OID_MISC_WARM_RESET) { if (priv->phandle->surprise_removed == MTRUE || priv->phandle->driver_status) { PRINTM(MCMND, @@ -2720,6 +2721,300 @@ done: #endif /* STA_WEXT || UAP_WEXT */ #endif /* STA_SUPPORT && UAP_SUPPORT */ +/** + * @brief Enable IPv6 Router Advertisement offload + * + * @param handle A pointer to moal_handle structure + * @param enable enable or disable + * + * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise + * fail + */ +static mlan_status woal_set_ipv6_ra_offload(moal_handle *handle, t_u8 enable) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + moal_private *priv = NULL; + mlan_ds_misc_cfg *misc = NULL; + mlan_ioctl_req *req = NULL; + mlan_ds_misc_ipv6_ra_offload *ipv6_ra; + int i = 0; + + ENTER(); + + for (i = 0; i < handle->priv_num && (priv = handle->priv[i]); i++) { + if (priv->ipv6_addr_configured) + break; + } + + if (!priv || !priv->ipv6_addr_configured) { + PRINTM(MIOCTL, "No IPv6 address configured\n"); + goto done; + } + + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); + if (req == NULL) { + PRINTM(MIOCTL, "IOCTL req allocated failed!\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + misc = (mlan_ds_misc_cfg *)req->pbuf; + misc->sub_command = MLAN_OID_MISC_IPV6_RA_OFFLOAD; + req->req_id = MLAN_IOCTL_MISC_CFG; + req->action = MLAN_ACT_SET; + ipv6_ra = &misc->param.ipv6_ra_offload; + ipv6_ra->enable = enable; + moal_memcpy_ext(priv->phandle, ipv6_ra->ipv6_addr, priv->ipv6_addr, 16, + sizeof(ipv6_ra->ipv6_addr)); + ret = woal_request_ioctl(woal_get_priv(handle, MLAN_BSS_ROLE_STA), req, + MOAL_NO_WAIT); + if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING) + PRINTM(MIOCTL, "Set IPv6 RA offload failed\n"); + +done: + if (ret != MLAN_STATUS_PENDING && req != NULL) + kfree(req); + LEAVE(); + return ret; +} + +/** + * @brief Enable IPv6 Neighbor Solicitation offload + * + * @param handle A pointer to moal_handle structure + * @param enable enable or disable mef entry + * + * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise + * fail + */ +static mlan_status woal_set_ipv6_ns_offload(moal_handle *handle) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + mlan_ds_misc_cfg *misc = NULL; + mlan_ioctl_req *req = NULL; + mlan_ds_misc_mef_flt_cfg *mef_cfg = NULL; + mef_entry_t *entry = NULL; + mef_filter_t *filter = NULL; + + ENTER(); + + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); + if (req == NULL) { + PRINTM(MIOCTL, "IOCTL req allocated failed!\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + misc = (mlan_ds_misc_cfg *)req->pbuf; + misc->sub_command = MLAN_OID_MISC_MEF_FLT_CFG; + req->req_id = MLAN_IOCTL_MISC_CFG; + req->action = MLAN_ACT_SET; + + mef_cfg = (mlan_ds_misc_mef_flt_cfg *)(&misc->param.mef_flt_cfg); + mef_cfg->mef_act_type = MEF_ACT_IPV6_NS; + mef_cfg->criteria = (MBIT(1) | MBIT(3)); + + entry = (mef_entry_t *)&mef_cfg->mef_entry; + entry->mode = MBIT(0); + entry->action = 0x40; + + filter = (mef_filter_t *)entry->filter_item; + filter->fill_flag = (FILLING_TYPE | FILLING_REPEAT | FILLING_OFFSET | + FILLING_BYTE_SEQ); + filter->type = TYPE_BYTE_EQ; + filter->repeat = 1; + filter->offset = 20; + filter->num_byte_seq = 2; + moal_memcpy_ext(handle, filter->byte_seq, "\x86\xdd", 2, + sizeof(filter->byte_seq)); + entry->rpn[1] = RPN_TYPE_AND; + + filter++; + filter->fill_flag = (FILLING_TYPE | FILLING_REPEAT | FILLING_OFFSET | + FILLING_BYTE_SEQ); + filter->type = TYPE_BYTE_EQ; + filter->repeat = 1; + filter->offset = 62; + filter->num_byte_seq = 1; + moal_memcpy_ext(handle, filter->byte_seq, "\x87", 1, + sizeof(filter->byte_seq)); + + entry->filter_num = 2; + + ret = woal_request_ioctl(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), req, + MOAL_NO_WAIT); + if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING) + PRINTM(MIOCTL, "Set ipv6 ns offload failed! ret=%d\n", ret); + +done: + if (ret != MLAN_STATUS_PENDING) + kfree(req); + LEAVE(); + return ret; +} + +/** + * @brief Set auto arp resp + * + * @param handle A pointer to moal_handle structure + * @param enable enable/disable + * + * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, + * otherwise fail + */ +static mlan_status woal_set_auto_arp(moal_handle *handle, t_u8 enable) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + int i = 0; + moal_private *priv = NULL; + mlan_ds_misc_cfg *misc = NULL; + mlan_ioctl_req *req = NULL; + mlan_ds_misc_ipaddr_cfg ipaddr_cfg; + + ENTER(); + + memset(&ipaddr_cfg, 0, sizeof(ipaddr_cfg)); + for (i = 0; i < handle->priv_num && (priv = handle->priv[i]); i++) { + if (priv && priv->ip_addr_type != IPADDR_TYPE_NONE) { + moal_memcpy_ext( + handle, + ipaddr_cfg.ip_addr[ipaddr_cfg.ip_addr_num], + priv->ip_addr, IPADDR_LEN, IPADDR_LEN); + ipaddr_cfg.ip_addr_num++; + } + } + if (ipaddr_cfg.ip_addr_num == 0) { + PRINTM(MIOCTL, "No IP addr configured.\n"); + goto done; + } + + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); + if (req == NULL) { + PRINTM(MIOCTL, "IOCTL req allocated failed!\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + misc = (mlan_ds_misc_cfg *)req->pbuf; + misc->sub_command = MLAN_OID_MISC_IP_ADDR; + req->req_id = MLAN_IOCTL_MISC_CFG; + req->action = MLAN_ACT_SET; + moal_memcpy_ext(handle, &misc->param.ipaddr_cfg, &ipaddr_cfg, + sizeof(ipaddr_cfg), sizeof(misc->param.ipaddr_cfg)); + if (enable) { + misc->param.ipaddr_cfg.op_code = MLAN_IPADDR_OP_ARP_FILTER | + MLAN_IPADDR_OP_AUTO_ARP_RESP; + misc->param.ipaddr_cfg.ip_addr_type = IPADDR_TYPE_IPV4; + } else { + /** remove ip */ + misc->param.ipaddr_cfg.op_code = MLAN_IPADDR_OP_IP_REMOVE; + } + ret = woal_request_ioctl(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), req, + MOAL_NO_WAIT); + if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING) + PRINTM(MIOCTL, "Set auto arp IOCTL failed!\n"); +done: + if (ret != MLAN_STATUS_PENDING) + kfree(req); + LEAVE(); + return ret; +} + +/** + * @brief Set auto arp resp with enhancement method + * + * @param handle A pointer to moal_handle structure + * @param enable enable/disable + * + * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, + * otherwise fail + */ +mlan_status woal_set_auto_arp_ext(moal_handle *handle, t_u8 enable) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + int i = 0, ip_addr_num = 0; + moal_private *priv = NULL; + mlan_ds_misc_cfg *misc = NULL; + mlan_ioctl_req *req = NULL; + mlan_ds_misc_mef_flt_cfg *mef_cfg = NULL; + mef_entry_t *entry = NULL; + mef_filter_t *filter = NULL; + t_u8 ip_addr[MAX_IPADDR][IPADDR_LEN]; + + ENTER(); + + memset(&mef_cfg, 0, sizeof(mef_cfg)); + for (i = 0; i < handle->priv_num && (priv = handle->priv[i]); i++) { + if (priv && priv->ip_addr_type != IPADDR_TYPE_NONE) { + moal_memcpy_ext(handle, ip_addr[ip_addr_num], + priv->ip_addr, IPADDR_LEN, IPADDR_LEN); + ip_addr_num++; + } + } + if (ip_addr_num == 0) { + PRINTM(MIOCTL, "No IP addr configured.\n"); + goto done; + } + + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); + if (req == NULL) { + PRINTM(MIOCTL, "IOCTL req allocated failed!\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + misc = (mlan_ds_misc_cfg *)req->pbuf; + misc->sub_command = MLAN_OID_MISC_MEF_FLT_CFG; + req->req_id = MLAN_IOCTL_MISC_CFG; + req->action = MLAN_ACT_SET; + + mef_cfg = (mlan_ds_misc_mef_flt_cfg *)(&(misc->param.mef_flt_cfg)); + mef_cfg->mef_act_type = MEF_ACT_AUTOARP; + mef_cfg->criteria = (MBIT(0) | MBIT(1)); + + entry = (mef_entry_t *)&mef_cfg->mef_entry; + entry->mode = MBIT(0); + entry->action = 0x10; + + filter = (mef_filter_t *)(entry->filter_item); + filter->fill_flag = (FILLING_TYPE | FILLING_REPEAT | FILLING_OFFSET | + FILLING_BYTE_SEQ); + filter->type = TYPE_BYTE_EQ; + filter->repeat = 1; + filter->offset = 20; + filter->num_byte_seq = 2; + moal_memcpy_ext(handle, filter->byte_seq, "\x08\x06", 2, + sizeof(filter->byte_seq)); + entry->rpn[1] = RPN_TYPE_AND; + + for (i = 0; i < ip_addr_num; i++) { + filter++; + filter->fill_flag = (FILLING_TYPE | FILLING_REPEAT | + FILLING_OFFSET | FILLING_BYTE_SEQ); + filter->type = TYPE_BYTE_EQ; + filter->repeat = 1; + filter->offset = 46; + filter->num_byte_seq = 4; + moal_memcpy_ext(handle, filter->byte_seq, &ip_addr[i], + sizeof(t_u32), sizeof(filter->byte_seq)); + if (i > 1) + entry->rpn[i] = RPN_TYPE_OR; + } + entry->filter_num = ip_addr_num + 1; + + if (enable) + mef_cfg->op_code = MLAN_IPADDR_OP_ARP_FILTER | + MLAN_IPADDR_OP_AUTO_ARP_RESP; + else + /** remove ip */ + mef_cfg->op_code = MLAN_IPADDR_OP_IP_REMOVE; + ret = woal_request_ioctl(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), req, + MOAL_NO_WAIT); + if (ret != MLAN_STATUS_SUCCESS && ret != MLAN_STATUS_PENDING) + PRINTM(MIOCTL, "Set auto arp IOCTL failed!\n"); +done: + if (ret != MLAN_STATUS_PENDING) + kfree(req); + LEAVE(); + return ret; +} + /** * @brief Set/Get DTIM period * @@ -2952,6 +3247,22 @@ mlan_status woal_cancel_hs(moal_private *priv, t_u8 wait_option) hscfg.is_invoke_hostcmd = MTRUE; ret = woal_set_get_hs_params(priv, MLAN_ACT_SET, wait_option, &hscfg); +#if IS_ENABLED(CONFIG_IPV6) + if (priv->phandle->hs_auto_arp) { + PRINTM(MIOCTL, "Canecl Host Sleep... remove ipv6 offload\n"); + /** Set ipv6 router advertisement message offload */ + woal_set_ipv6_ra_offload(priv->phandle, MFALSE); + } +#endif + + if (priv->phandle->hs_auto_arp) { + PRINTM(MIOCTL, "Cancel Host Sleep... remove FW auto arp\n"); + /* remove auto arp from FW */ + woal_set_auto_arp(priv->phandle, MFALSE); + /* remove auto arp from FW */ + woal_set_auto_arp_ext(priv->phandle, MFALSE); + } + #ifdef STA_CFG80211 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) handle = priv->phandle; @@ -3062,6 +3373,24 @@ int woal_enable_hs(moal_private *priv) woal_reconfig_bgscan(priv->phandle); #endif +#if IS_ENABLED(CONFIG_IPV6) + if (handle->hs_auto_arp) { + PRINTM(MIOCTL, "Host Sleep enabled... set ipv6 offload\n"); + /** Set ipv6 router advertisement message offload */ + woal_set_ipv6_ra_offload(handle, MTRUE); + /** Set Neighbor Solitation message offload */ + woal_set_ipv6_ns_offload(handle); + } +#endif + + if (handle->hs_auto_arp) { + PRINTM(MIOCTL, "Host Sleep enabled... set FW auto arp\n"); + /* Set auto arp response configuration to Fw */ + woal_set_auto_arp(handle, MTRUE); + /* Set auto arp response configuration to Fw */ + woal_set_auto_arp_ext(handle, MTRUE); + } + #ifdef STA_CFG80211 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) if (GTK_REKEY_OFFLOAD_SUSPEND == handle->params.gtk_rekey_offload) { diff --git a/mxm_wifiex/wlan_src/mlinux/moal_main.c b/mxm_wifiex/wlan_src/mlinux/moal_main.c index be43cc4..822c450 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_main.c +++ b/mxm_wifiex/wlan_src/mlinux/moal_main.c @@ -65,6 +65,10 @@ Change log: #include #endif +#if IS_ENABLED(CONFIG_IPV6) +#include +#endif + /******************************************************** Global Variables ********************************************************/ @@ -724,6 +728,7 @@ static mlan_callbacks woal_callbacks = { #endif .moal_tp_accounting = moal_tp_accounting, .moal_tp_accounting_rx_param = moal_tp_accounting_rx_param, + .moal_amsdu_tp_accounting = moal_amsdu_tp_accounting, }; int woal_open(struct net_device *dev); @@ -766,6 +771,34 @@ static moal_handle *reset_handle; static struct workqueue_struct *hang_workqueue; /** Hang work */ static struct work_struct hang_work; +/** register workqueue */ +static struct workqueue_struct *register_workqueue; +/** register work */ +static struct work_struct register_work; + +/** + * @brief This function send fw dump event to kernel + * + * @param priv Pointer to structure moal_private + * + * @return N/A + */ +void woal_send_fw_dump_complete_event(moal_private *priv) +{ + int cfg80211_wext = priv->phandle->params.cfg80211_wext; +#ifdef STA_WEXT + if (IS_STA_WEXT(cfg80211_wext)) + woal_send_iwevcustom_event(priv, CUS_EVT_FW_DUMP_DONE); +#endif +#ifdef STA_CFG80211 + if (IS_STA_CFG80211(cfg80211_wext)) + woal_cfg80211_vendor_event_fw_dump(priv); +#endif + woal_broadcast_event(priv, CUS_EVT_FW_DUMP_DONE, + strlen(CUS_EVT_FW_DUMP_DONE)); + + return; +} /** * @brief This function process FW hang @@ -777,28 +810,97 @@ static struct work_struct hang_work; static void woal_hang_work_queue(struct work_struct *work) { int i; + moal_private *priv; + int cfg80211_wext = 0; + ENTER(); if (!reset_handle) { LEAVE(); return; } - flush_workqueue(reset_handle->workqueue); - flush_workqueue(reset_handle->evt_workqueue); - if (reset_handle->rx_workqueue) { - flush_workqueue(reset_handle->rx_workqueue); + cfg80211_wext = reset_handle->params.cfg80211_wext; + // stop pending scan +#ifdef STA_CFG80211 + if (IS_STA_CFG80211(cfg80211_wext) && reset_handle->scan_request) { + moal_private *scan_priv = reset_handle->scan_priv; + /** some supplicant can not handle SCAN abort event */ + if (scan_priv->bss_type == MLAN_BSS_TYPE_STA) + woal_cfg80211_scan_done(reset_handle->scan_request, + MTRUE); + else + woal_cfg80211_scan_done(reset_handle->scan_request, + MFALSE); + reset_handle->scan_request = NULL; + reset_handle->scan_priv = NULL; + reset_handle->scan_pending_on_block = MFALSE; + MOAL_REL_SEMAPHORE(&reset_handle->async_sem); } - mlan_ioctl(reset_handle->pmlan_adapter, NULL); +#endif for (i = 0; i < reset_handle->priv_num; i++) { - if (reset_handle->priv[i] && reset_handle->priv[i]->netdev) { - PRINTM(MMSG, "Close netdev %s\n", - reset_handle->priv[i]->netdev->name); - rtnl_lock(); - dev_close(reset_handle->priv[i]->netdev); - rtnl_unlock(); - break; + if (reset_handle->priv[i]) { + priv = reset_handle->priv[i]; + woal_stop_queue(priv->netdev); + if (netif_carrier_ok(priv->netdev)) + netif_carrier_off(priv->netdev); + priv->media_connected = MFALSE; + // disconnect +#ifdef STA_CFG80211 +#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) + if (IS_STA_CFG80211(cfg80211_wext) && + priv->wdev->current_bss) { +#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) + if (priv->host_mlme) + woal_host_mlme_disconnect( + priv, + MLAN_REASON_DEAUTH_LEAVING, + NULL); + else +#endif + cfg80211_disconnected(priv->netdev, 0, + NULL, 0, +#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) + true, +#endif + GFP_KERNEL); + } +#endif +#endif + // stop bgscan +#ifdef STA_CFG80211 +#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) + if (IS_STA_CFG80211(cfg80211_wext) && + priv->sched_scanning) { + priv->bg_scan_start = MFALSE; + priv->bg_scan_reported = MFALSE; + cfg80211_sched_scan_stopped(priv->wdev->wiphy +#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) + , + priv->bg_scan_reqid +#endif + ); + priv->sched_scanning = MFALSE; + } +#endif +#endif } } + + woal_flush_workqueue(reset_handle); + mlan_ioctl(reset_handle->pmlan_adapter, NULL); + priv = woal_get_priv(reset_handle, MLAN_BSS_ROLE_ANY); + if (priv) { + woal_broadcast_event(priv, CUS_EVT_DRIVER_HANG, + strlen(CUS_EVT_DRIVER_HANG)); +#ifdef STA_CFG80211 +#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) + if (IS_STA_OR_UAP_CFG80211(cfg80211_wext)) + woal_cfg80211_vendor_event(priv, event_hang, + CUS_EVT_DRIVER_HANG, + strlen(CUS_EVT_DRIVER_HANG)); +#endif +#endif + } reset_handle = NULL; LEAVE(); } @@ -858,6 +960,164 @@ t_u8 woal_is_any_interface_active(moal_handle *handle) return MFALSE; } +/** + * @brief This function handle the net interface ipaddr change event + * + * @param nb pointer to the notifier_block + * @param event event type + * @param ptr pointer to event struct + * + * @return NOTIFY_DONE or NOTIFY_OK + */ +static int woal_netdevice_event(struct notifier_block *nb, unsigned long event, + void *ptr) +{ + struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; + struct net_device *ndev; + moal_private *priv; + + int ret = NOTIFY_OK; +#ifdef STA_CFG80211 + char rssi_low[11]; +#endif + ENTER(); + + ndev = ifa->ifa_dev->dev; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29) + if (!ndev || ndev->netdev_ops->ndo_open != woal_open) +#else + if (!ndev || ndev->open != woal_open) +#endif + { + PRINTM(MIOCTL, "IP changes not for us, ignore. ndev[%p]\n", + ndev); + if (ndev) + PRINTM(MIOCTL, "changes on %s\n", ndev->name); + ret = NOTIFY_DONE; + goto done; + } + priv = (moal_private *)netdev_priv(ndev); + if (priv->bss_type != MLAN_BSS_TYPE_STA +#ifdef WIFI_DIRECT_SUPPORT + && priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT +#endif + ) { + PRINTM(MIOCTL, "Bss type [%d] is not STA/P2P, ignore\n", + (int)priv->bss_type); + ret = NOTIFY_DONE; + goto done; + } + + switch (event) { + case NETDEV_UP: + PRINTM(MIOCTL, "[%s]: New ip addr: 0x%08x\n", ndev->name, + ifa->ifa_address); + /* Save the IP addr now */ + moal_memcpy_ext(priv->phandle, priv->ip_addr, &ifa->ifa_address, + sizeof(ifa->ifa_address), + sizeof(priv->ip_addr)); + priv->ip_addr_type = IPADDR_TYPE_IPV4; +#ifdef STA_CFG80211 + if (!moal_extflg_isset(priv->phandle, EXT_HW_TEST) && + priv->roaming_enabled) { + snprintf(rssi_low, sizeof(rssi_low), "%d", + priv->rssi_low); + woal_set_rssi_low_threshold(priv, rssi_low, + MOAL_IOCTL_WAIT); + } +#endif + break; + case NETDEV_DOWN: + PRINTM(MIOCTL, "[%s]: Ip addr removed.\n", ndev->name); + priv->ip_addr_type = IPADDR_TYPE_NONE; + memset(priv->ip_addr, 0, sizeof(priv->ip_addr)); + break; + default: + PRINTM(MIOCTL, "[%s]: Ignore event: %u\n", ndev->name, + (unsigned int)event); + ret = NOTIFY_DONE; + goto done; + } + +done: + LEAVE(); + return ret; +} + +#if IS_ENABLED(CONFIG_IPV6) +/** + * @brief This function handle the net interface ipv6 address change event + * + * @param nb pointer to the notifier_block + * @param event event type + * @param ptr pointer to event struct + * + * @return NOTIFY_DONE or NOTIFY_OK + */ +static int woal_inet6_netdeive_event(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; + struct net_device *ndev = ifa->idev->dev; + moal_private *priv; + int ret = NOTIFY_OK; + + ENTER(); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29) + if (!ndev || ndev->netdev_ops->ndo_open != woal_open) +#else + if (!ndev || ndev->open != woal_open) +#endif + { + PRINTM(MIOCTL, "IPV6 changes not for us, ignore. ndev[%p]\n", + ndev); + if (ndev) + PRINTM(MIOCTL, "changes on %s\n", ndev->name); + ret = NOTIFY_DONE; + goto done; + } + priv = (moal_private *)netdev_priv(ndev); + if (!priv) { + PRINTM(MERROR, "Invalid private structure\n"); + goto done; + } + if (priv->bss_type != MLAN_BSS_TYPE_STA +#ifdef WIFI_DIRECT_SUPPORT + && priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT +#endif + ) { + PRINTM(MIOCTL, "Bss type [%d] is not STA/P2P, ignore\n", + (int)priv->bss_type); + ret = NOTIFY_DONE; + goto done; + } + + switch (event) { + case NETDEV_UP: + PRINTM(MIOCTL, "[%s]: New ipv6 addr\n", ndev->name); + moal_memcpy_ext(priv->phandle, priv->ipv6_addr, + (t_u8 *)&ifa->addr, sizeof(priv->ipv6_addr), + sizeof(priv->ipv6_addr)); + priv->ipv6_addr_configured = MTRUE; + break; + case NETDEV_DOWN: + PRINTM(MIOCTL, "[%s]: Ipv6 addr removed.\n", ndev->name); + memset(priv->ipv6_addr, 0, sizeof(priv->ipv6_addr)); + priv->ipv6_addr_configured = MFALSE; + break; + default: + PRINTM(MIOCTL, "[%s]: Ignore event: %u\n", ndev->name, + (unsigned int)event); + ret = NOTIFY_DONE; + goto done; + } +done: + LEAVE(); + return ret; +} +#endif + /** * @brief This function validates a SSID as being able to be printed * @@ -1470,6 +1730,11 @@ mlan_status woal_init_sw(moal_handle *handle) handle->is_reassoc_timer_set = MFALSE; #endif /* REASSOCIATION */ + /* Initialize the timer for the FW dump*/ + woal_initialize_timer(&handle->fw_dump_timer, woal_fw_dump_timer_func, + handle); + handle->is_fw_dump_timer_set = MFALSE; + #ifdef WIFI_DIRECT_SUPPORT #if defined(STA_CFG80211) && defined(UAP_CFG80211) /* Initialize the timer for GO timeout */ @@ -1514,6 +1779,7 @@ mlan_status woal_init_sw(moal_handle *handle) device.fixed_beacon_buffer = (t_u32)moal_extflg_isset(handle, EXT_FIX_BCN_BUF); device.auto_ds = (t_u32)handle->params.auto_ds; + device.ext_scan = (t_u8)handle->params.ext_scan; device.ps_mode = (t_u32)handle->params.ps_mode; device.passive_to_active_scan = (t_u8)handle->params.p2a_scan; device.max_tx_buf = (t_u32)handle->params.max_tx_buf; @@ -2348,7 +2614,7 @@ mlan_status woal_vdll_req_fw(moal_handle *handle) if (vdll_fw) { PRINTM(MMSG, "VDLL: Request firmware: %s\n", vdll_fw); if (req_fw_nowait) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0) if ((request_firmware_nowait( THIS_MODULE, FW_ACTION_UEVENT, vdll_fw, handle->hotplug_device, GFP_KERNEL, handle, @@ -2487,8 +2753,9 @@ static t_u32 woal_set_user_init_data(moal_handle *handle, int type, ENTER(); if (type == INIT_CFG_DATA) { + PRINTM(MMSG, "Request firmware: %s\n", init_cfg); if (req_fw_nowait) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0) if ((request_firmware_nowait( THIS_MODULE, FW_ACTION_UEVENT, init_cfg, handle->hotplug_device, GFP_KERNEL, handle, @@ -2536,10 +2803,11 @@ static t_u32 woal_set_user_init_data(moal_handle *handle, int type, ret = MLAN_STATUS_FAILURE; goto done; } + PRINTM(MMSG, "Request firmware: %s\n", country_txpwrlimit); /* 'country_txpwrlimit' holds the value of Configured Tx Power * Limit */ if (req_fw_nowait) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0) if ((request_firmware_nowait( THIS_MODULE, FW_ACTION_UEVENT, country_txpwrlimit, handle->hotplug_device, @@ -2580,9 +2848,16 @@ static t_u32 woal_set_user_init_data(moal_handle *handle, int type, handle->init_user_conf_wait_q, handle->init_user_conf_wait_flag); } else { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) + int status = + request_firmware_direct(&handle->user_data, + country_txpwrlimit, + handle->hotplug_device); +#else int status = request_firmware(&handle->user_data, country_txpwrlimit, handle->hotplug_device); +#endif /* File does not exist, skip download */ if (status == -ENOENT) { ret = MLAN_STATUS_FILE_ERR; @@ -2596,8 +2871,9 @@ static t_u32 woal_set_user_init_data(moal_handle *handle, int type, } } } else if (type == INIT_HOSTCMD_CFG_DATA) { + PRINTM(MMSG, "Request firmware: %s\n", init_hostcmd_cfg); if (req_fw_nowait) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0) if ((request_firmware_nowait( THIS_MODULE, FW_ACTION_UEVENT, init_hostcmd_cfg, handle->hotplug_device, @@ -2648,8 +2924,9 @@ static t_u32 woal_set_user_init_data(moal_handle *handle, int type, } } if (type == BAND_STEER_CFG_DATA) { + PRINTM(MMSG, "Request firmware: %s\n", band_steer_cfg); if (req_fw_nowait) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0) if ((request_firmware_nowait( THIS_MODULE, FW_ACTION_UEVENT, band_steer_cfg, handle->hotplug_device, @@ -2728,6 +3005,52 @@ done: return ret; } +static int woal_netdevice_event(struct notifier_block *nb, unsigned long event, + void *ptr); + +#ifdef UAP_SUPPORT +/** + * @brief Configure WACP Mode + * + * @param priv A pointer to moal_private structure + * @param wait_option Wait option + * + * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, + * otherwise fail + */ +mlan_status woal_set_wacp_mode(moal_private *priv, t_u8 wait_option) +{ + // moal_private *priv = NULL; + mlan_ioctl_req *req = NULL; + mlan_ds_misc_cfg *pcfg_misc = NULL; + mlan_status status; + + ENTER(); + + /* Allocate an IOCTL request buffer */ + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); + if (req == NULL) { + status = MLAN_STATUS_FAILURE; + goto done; + } + + /* Fill request buffer */ + pcfg_misc = (mlan_ds_misc_cfg *)req->pbuf; + pcfg_misc->sub_command = MLAN_OID_MISC_WACP_MODE; + req->req_id = MLAN_IOCTL_MISC_CFG; + req->action = MLAN_ACT_SET; + pcfg_misc->param.wacp_mode = priv->phandle->params.wacp_mode; + + /* Send IOCTL request to MLAN */ + status = woal_request_ioctl(priv, req, wait_option); +done: + if (status != MLAN_STATUS_PENDING) + kfree(req); + LEAVE(); + return status; +} +#endif + /** * @brief Configure aggrctrl * @@ -2775,85 +3098,6 @@ done: return status; } -#ifdef CONFIG_RPS -static ssize_t woal_set_rps_map(struct netdev_rx_queue *queue, const char *buf, - size_t len) -{ - struct rps_map *old_map, *map; - cpumask_var_t mask; - int err, cpu, i; - static DEFINE_MUTEX(local_rps_map_mutex); - - if (!queue || !queue->dev) { - PRINTM(MERROR, "%s: queue=%px or queue->dev is NULL\n", - __func__, queue); - return -EINVAL; - } - - if (!alloc_cpumask_var(&mask, GFP_KERNEL)) { - PRINTM(MERROR, "%s: alloc_cpumask_var fail.\n", __func__); - return -ENOMEM; - } - - err = bitmap_parse(buf, len, cpumask_bits(mask), nr_cpumask_bits); - if (err) { - PRINTM(MERROR, "%s: bitmap_parse fail err=%d.\n", __func__, - err); - free_cpumask_var(mask); - return err; - } - - map = kzalloc(max_t(unsigned int, RPS_MAP_SIZE(cpumask_weight(mask)), - L1_CACHE_BYTES), - GFP_KERNEL); - if (!map) { - PRINTM(MERROR, "%s: kzalloc map fail.\n", __func__); - free_cpumask_var(mask); - return -ENOMEM; - } - - i = 0; - for_each_cpu_and (cpu, mask, cpu_online_mask) { - PRINTM(MCMND, "map->cpus[%d]=%d\n", i, cpu); - map->cpus[i++] = cpu; - } - - if (i) { - map->len = i; - PRINTM(MCMND, "map->len=%d\n", map->len); - } else { - kfree(map); - map = NULL; - } - - mutex_lock(&local_rps_map_mutex); - old_map = rcu_dereference_protected( - queue->rps_map, mutex_is_locked(&local_rps_map_mutex)); - rcu_assign_pointer(queue->rps_map, map); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) - if (map) - static_branch_inc(&rps_needed); - if (old_map) - static_branch_dec(&rps_needed); -#else - if (map) - static_key_slow_inc(&rps_needed); - if (old_map) - static_key_slow_dec(&rps_needed); - -#endif - mutex_unlock(&local_rps_map_mutex); - - if (old_map) - kfree_rcu(old_map, rcu); - - PRINTM(MMSG, "%s on %s: buf=%s(%u) (%d i=%d)\n", __func__, - queue->dev->name, buf, (t_u32)len, nr_cpumask_bits, i); - free_cpumask_var(mask); - return len; -} -#endif - /** * @brief Add interfaces DPC * @@ -2894,6 +3138,12 @@ static mlan_status woal_add_card_dpc(moal_handle *handle) woal_get_version(handle, str_buf, sizeof(str_buf) - 1); PRINTM(MMSG, "wlan: version = %s\n", str_buf); + handle->woal_notifier.notifier_call = woal_netdevice_event; + if (register_inetaddr_notifier(&handle->woal_notifier)) { + PRINTM(MFATAL, + "Error registering register_inetaddr_notifier\n"); + goto err; + } #ifdef MFG_CMD_SUPPORT if (handle->params.mfg_mode == MLAN_INIT_PARA_ENABLED) goto done; @@ -2963,24 +3213,12 @@ static mlan_status woal_add_card_dpc(moal_handle *handle) woal_set_uap_operation_ctrl(handle); #endif -#ifdef CONFIG_RPS - if (moal_extflg_isset(handle, EXT_RPS)) { - moal_private *priv_rps = - woal_get_priv_bss_type(handle, MLAN_BSS_TYPE_STA); - if (priv_rps) { - char *rps_buf = "f"; - PRINTM(MCMND, - "num_rx_queues=%u real_num_rx_queues=%u\n", - priv_rps->netdev->num_rx_queues, - priv_rps->netdev->real_num_rx_queues); - for (i = 0; - i < (int)MIN(priv_rps->netdev->num_rx_queues, - priv_rps->netdev->real_num_rx_queues); - i++) { - woal_set_rps_map(&(priv_rps->netdev->_rx[i]), - rps_buf, strlen(rps_buf)); - } - } +#if IS_ENABLED(CONFIG_IPV6) + handle->woal_inet6_notifier.notifier_call = woal_inet6_netdeive_event; + if (register_inet6addr_notifier(&handle->woal_inet6_notifier)) { + PRINTM(MFATAL, + "Error registering register_inet6addr_notifier\n"); + goto err; } #endif @@ -2994,6 +3232,10 @@ err: } if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "Failed to add interface\n"); + unregister_inetaddr_notifier(&handle->woal_notifier); +#if IS_ENABLED(CONFIG_IPV6) + unregister_inet6addr_notifier(&handle->woal_inet6_notifier); +#endif for (i = 0; i < MIN(MLAN_MAX_BSS_NUM, handle->priv_num); i++) woal_remove_interface(handle, i); @@ -3024,8 +3266,9 @@ static mlan_status woal_req_dpd_data(moal_handle *handle, ENTER(); if (dpd_data_cfg && strncmp(dpd_data_cfg, "none", strlen("none"))) { + PRINTM(MMSG, "Request firmware: %s\n", dpd_data_cfg); if (req_fw_nowait) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0) if ((request_firmware_nowait( THIS_MODULE, FW_ACTION_UEVENT, dpd_data_cfg, handle->hotplug_device, GFP_KERNEL, handle, @@ -3105,7 +3348,7 @@ static mlan_status woal_req_txpwr_data(moal_handle *handle, PRINTM(MMSG, "Download txpwrlimit_cfg=%s\n", handle->params.txpwrlimit_cfg); if (req_fw_nowait) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0) if ((request_firmware_nowait( THIS_MODULE, FW_ACTION_UEVENT, txpwrlimit_cfg, handle->hotplug_device, @@ -3186,8 +3429,9 @@ static mlan_status woal_req_cal_data(moal_handle *handle, ENTER(); /** Cal data request */ if (cal_data_cfg && strncmp(cal_data_cfg, "none", strlen("none"))) { + PRINTM(MMSG, "Request firmware: %s\n", cal_data_cfg); if (req_fw_nowait) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0) if ((request_firmware_nowait( THIS_MODULE, FW_ACTION_UEVENT, cal_data_cfg, handle->hotplug_device, GFP_KERNEL, handle, @@ -3346,7 +3590,8 @@ static mlan_status woal_init_fw_dpc(moal_handle *handle) } #endif /* USB_NEW_FW_DNLD */ PRINTM(MMSG, "WLAN FW is active\n"); - handle->driver_status = MFALSE; + if (!handle->fw_reload) + handle->driver_status = MFALSE; } moal_get_boot_ktime(handle, &handle->on_time); @@ -3379,11 +3624,12 @@ static mlan_status woal_init_fw_dpc(moal_handle *handle) goto done; } #endif /* USB */ - if (handle->fw_reload) - goto done; - handle->init_wait_q_woken = MFALSE; - ret = mlan_set_init_param(handle->pmlan_adapter, ¶m); + if (handle->fw_reload) { + LEAVE(); + return ret; + } + handle->init_wait_q_woken = MFALSE; ret = mlan_init_fw(handle->pmlan_adapter); if (ret == MLAN_STATUS_FAILURE) { wifi_status = 2; @@ -3392,15 +3638,9 @@ static mlan_status woal_init_fw_dpc(moal_handle *handle) handle->hardware_status = HardwareStatusReady; goto done; } -#ifdef SD9177 - if (IS_SD9177(handle->card_type)) - wait_event_timeout(handle->init_wait_q, - handle->init_wait_q_woken, 10 * HZ); - else -#endif - /* Wait for mlan_init to complete */ - wait_event_timeout(handle->init_wait_q, - handle->init_wait_q_woken, 5 * HZ); + /* Wait for mlan_init to complete */ + wait_event_timeout(handle->init_wait_q, handle->init_wait_q_woken, + 10 * HZ); if (handle->hardware_status != HardwareStatusReady) { woal_moal_debug_info(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), handle, MTRUE); @@ -3519,7 +3759,7 @@ mlan_status woal_request_fw(moal_handle *handle) PRINTM(MMSG, "Request firmware: %s\n", handle->drv_mode.fw_name); if (req_fw_nowait && !handle->fw_reload) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0) err = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT, handle->drv_mode.fw_name, handle->hotplug_device, @@ -3831,7 +4071,7 @@ const struct net_device_ops woal_uap_netdev_ops = { .ndo_start_xmit = woal_hard_start_xmit, .ndo_stop = woal_close, #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) - .ndo_siocdevprivate = woal_uap_do_ioctl, + .ndo_siocdevprivate = woal_do_ioctl, #else .ndo_do_ioctl = woal_uap_do_ioctl, #endif @@ -3917,6 +4157,9 @@ moal_private *woal_add_interface(moal_handle *handle, t_u8 bss_index, moal_private *priv = NULL; char name[256]; int i = 0; +#ifdef STA_CFG80211 + char sched_scan_str[256]; +#endif #ifdef UAP_CFG80211 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) char csa_str[256]; @@ -3989,10 +4232,11 @@ moal_private *woal_add_interface(moal_handle *handle, t_u8 bss_index, priv->bss_index = bss_index; priv->bss_type = bss_type; priv->extra_tx_head_len = 0; - if (bss_type == MLAN_BSS_TYPE_STA) + if (bss_type == MLAN_BSS_TYPE_STA) { priv->bss_role = MLAN_BSS_ROLE_STA; - else if (bss_type == MLAN_BSS_TYPE_UAP) + } else if (bss_type == MLAN_BSS_TYPE_UAP) { priv->bss_role = MLAN_BSS_ROLE_UAP; + } #ifdef WIFI_DIRECT_SUPPORT else if (bss_type == MLAN_BSS_TYPE_WIFIDIRECT) priv->bss_role = MLAN_BSS_ROLE_STA; @@ -4114,6 +4358,16 @@ moal_private *woal_add_interface(moal_handle *handle, t_u8 bss_index, goto error; } } + strcpy(sched_scan_str, "SCHED_SCAN"); + strcat(sched_scan_str, name); + priv->sched_scan_workqueue = alloc_workqueue( + sched_scan_str, WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1); + if (!priv->sched_scan_workqueue) { + PRINTM(MERROR, "cannot alloc sched_scan workqueue \n"); + goto error; + } + INIT_DELAYED_WORK(&priv->sched_scan_work, woal_sched_scan_work_queue); + #endif /* STA_SUPPORT */ #endif /* STA_CFG80211 */ #ifdef UAP_CFG80211 @@ -4226,6 +4480,12 @@ error: destroy_workqueue(priv->mclist_workqueue); priv->mclist_workqueue = NULL; } +#ifdef STA_CFG80211 + if (priv->sched_scan_workqueue) { + destroy_workqueue(priv->sched_scan_workqueue); + priv->sched_scan_workqueue = NULL; + } +#endif #if defined(STA_CFG80211) || defined(UAP_CFG80211) if (priv->wdev && IS_STA_OR_UAP_CFG80211(handle->params.cfg80211_wext)) @@ -4264,6 +4524,7 @@ void woal_remove_interface(moal_handle *handle, t_u8 bss_index) union iwreq_data wrqu; #endif int i = 0; + ENTER(); if (!priv || !priv->netdev) @@ -4333,6 +4594,13 @@ void woal_remove_interface(moal_handle *handle, t_u8 bss_index) priv->mclist_workqueue = NULL; } +#ifdef STA_CFG80211 + if (priv->sched_scan_workqueue) { + destroy_workqueue(priv->sched_scan_workqueue); + priv->sched_scan_workqueue = NULL; + } +#endif + #if defined(STA_CFG80211) || defined(UAP_CFG80211) /* Unregister wiphy device and free */ if (priv->wdev && IS_STA_OR_UAP_CFG80211(handle->params.cfg80211_wext)) @@ -4611,6 +4879,29 @@ static void woal_flush_evt_queue(moal_handle *handle) spin_unlock_irqrestore(&handle->evt_lock, flags); } +/** + * @brief This function flush all works in the queue + * + * @param handle A pointer to moal_handle + * + * @return N/A + */ +void woal_flush_workqueue(moal_handle *handle) +{ + ENTER(); + + /* Terminate main workqueue */ + if (handle->workqueue) + flush_workqueue(handle->workqueue); + if (handle->rx_workqueue) + flush_workqueue(handle->rx_workqueue); + if (handle->evt_workqueue) + flush_workqueue(handle->evt_workqueue); + if (handle->tx_workqueue) + flush_workqueue(handle->tx_workqueue); + LEAVE(); +} + /** * @brief This function cancel all works in the queue * and destroy the main workqueue. @@ -4667,8 +4958,8 @@ int woal_open(struct net_device *dev) struct usb_interface *intf = ((struct usb_card_rec *)priv->phandle->card)->intf; #else - struct usb_device *udev = - ((struct usb_card_rec *)(priv->phandle->card))->udev; + // struct usb_device *udev = ((struct usb_card_rec + // *)(priv->phandle->card))->udev; #endif /* < 2.6.34 */ #endif /* USB_SUSPEND_RESUME */ t_u8 carrier_on = MFALSE; @@ -4690,7 +4981,7 @@ int woal_open(struct net_device *dev) return -EIO; } #else - atomic_set(&udev->dev.power.usage_count, 1); + // atomic_set(&udev->dev.power.usage_count, 1); #endif /* < 2.6.34 */ } #endif /* USB_SUSPEND_RESUME */ @@ -4738,6 +5029,7 @@ int woal_open(struct net_device *dev) (priv->media_connected || priv->is_adhoc_link_sensed)) carrier_on = MTRUE; #endif + if (carrier_on == MTRUE) { if (!netif_carrier_ok(priv->netdev)) netif_carrier_on(priv->netdev); @@ -4766,8 +5058,8 @@ int woal_close(struct net_device *dev) struct usb_interface *intf = ((struct usb_card_rec *)priv->phandle->card)->intf; #else - struct usb_device *udev = - ((struct usb_card_rec *)(priv->phandle->card))->udev; + // struct usb_device *udev = ((struct usb_card_rec + // *)(priv->phandle->card))->udev; #endif /* < 2.6.34 */ #endif /* USB_SUSPEND_RESUME */ #ifdef STA_CFG80211 @@ -4819,7 +5111,7 @@ int woal_close(struct net_device *dev) #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34) usb_autopm_put_interface(intf); #else - atomic_set(&udev->dev.power.usage_count, 0); + // atomic_set(&udev->dev.power.usage_count, 0); #endif /* < 2.6.34 */ } #endif /* USB_SUSPEND_RESUME */ @@ -5069,8 +5361,11 @@ void woal_mlan_debug_info(moal_private *priv) (unsigned int)info->mp_rd_bitmap, info->curr_rd_port); PRINTM(MERROR, "mp_wr_bitmap=0x%x curr_wr_port=0x%x\n", (unsigned int)info->mp_wr_bitmap, info->curr_wr_port); - PRINTM(MERROR, "mp_invalid_update=%d\n", - info->mp_invalid_update); + PRINTM(MERROR, "mp_data_port_mask=0x%x\n", + info->mp_data_port_mask); + PRINTM(MERROR, + "last_recv_rd_bitmap=0x%x mp_invalid_update=%d\n", + info->last_recv_rd_bitmap, info->mp_invalid_update); mp_aggr_pkt_limit = info->mp_aggr_pkt_limit; PRINTM(MERROR, "last_recv_wr_bitmap=0x%x last_mp_index = %d\n", info->last_recv_wr_bitmap, info->last_mp_index); @@ -5200,7 +5495,7 @@ void woal_tx_timeout(struct net_device *dev ) { moal_private *priv = (moal_private *)netdev_priv(dev); - + t_u8 auto_fw_dump = MFALSE; ENTER(); priv->num_tx_timeout++; @@ -5209,20 +5504,13 @@ void woal_tx_timeout(struct net_device *dev woal_set_trans_start(dev); if (priv->num_tx_timeout == NUM_TX_TIMEOUT_THRESHOLD) { + if (drvdbg & MFW_D) + auto_fw_dump = MTRUE; woal_mlan_debug_info(priv); woal_moal_debug_info(priv, NULL, MFALSE); - woal_broadcast_event(priv, CUS_EVT_DRIVER_HANG, - strlen(CUS_EVT_DRIVER_HANG)); -#if defined(STA_CFG80211) || defined(UAP_CFG80211) -#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) - if (IS_STA_OR_UAP_CFG80211(priv->phandle->params.cfg80211_wext)) - woal_cfg80211_vendor_event(priv, event_hang, - CUS_EVT_DRIVER_HANG, - strlen(CUS_EVT_DRIVER_HANG)); -#endif -#endif priv->phandle->driver_status = MTRUE; - woal_process_hang(priv->phandle); + if (!auto_fw_dump && !priv->phandle->fw_dump) + woal_process_hang(priv->phandle); wifi_status = 3; } @@ -5704,6 +5992,7 @@ static int woal_process_tcp_ack(moal_private *priv, mlan_buffer *pmbuf) if (*((t_u8 *)tcph + 13) == 0x10) { /* Only replace ACK */ if (ntohs(iph->tot_len) > (iph->ihl + tcph->doff) * 4) { + priv->tcp_ack_payload++; /* Don't drop ACK with payload */ /* TODO: should we delete previous TCP session */ LEAVE(); @@ -5846,12 +6135,14 @@ static int woal_start_xmit(moal_private *priv, struct sk_buff *skb) if (new_skb != skb) dev_kfree_skb_any(skb); skb = new_skb; + PRINTM(MINFO, "new skb headroom %d\n", skb_headroom(skb)); } pmbuf = (mlan_buffer *)skb->head; memset((t_u8 *)pmbuf, 0, sizeof(mlan_buffer)); pmbuf->bss_index = priv->bss_index; woal_fill_mlan_buffer(priv, pmbuf, skb); + if (priv->enable_tcp_ack_enh == MTRUE) { ret = woal_process_tcp_ack(priv, pmbuf); if (ret) @@ -5880,6 +6171,7 @@ static int woal_start_xmit(moal_private *priv, struct sk_buff *skb) priv->phandle->tx_time_start.time_usec); } atomic_inc(&priv->phandle->tx_pending); + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29) atomic_inc(&priv->wmm_tx_pending[index]); if (atomic_read(&priv->wmm_tx_pending[index]) >= @@ -5895,6 +6187,7 @@ static int woal_start_xmit(moal_private *priv, struct sk_buff *skb) if (atomic_read(&priv->phandle->tx_pending) >= MAX_TX_PENDING) woal_stop_queue(priv->netdev); #endif /*#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)*/ + if (!mlan_is_main_process_running(priv->phandle->pmlan_adapter)) queue_work(priv->phandle->workqueue, &priv->phandle->main_work); @@ -6188,6 +6481,12 @@ void woal_init_priv(moal_private *priv, t_u8 wait_option) priv->scan_type = MLAN_SCAN_TYPE_ACTIVE; priv->bg_scan_start = MFALSE; priv->bg_scan_reported = MFALSE; + priv->sched_scanning = MFALSE; +#ifdef STA_CFG80211 + priv->roaming_enabled = MFALSE; + priv->roaming_required = MFALSE; +#endif + memset(&priv->nick_name, 0, sizeof(priv->nick_name)); priv->num_tx_timeout = 0; priv->rx_filter = 0; @@ -6208,6 +6507,9 @@ void woal_init_priv(moal_private *priv, t_u8 wait_option) #ifdef UAP_SUPPORT if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) { priv->bss_started = MFALSE; + priv->uap_host_based = MFALSE; + priv->skip_cac = MFALSE; + #ifdef UAP_CFG80211 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) memset(&priv->chan, 0, sizeof(struct cfg80211_chan_def)); @@ -6239,11 +6541,17 @@ void woal_init_priv(moal_private *priv, t_u8 wait_option) priv->proberesp_p2p_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; priv->assocresp_qos_map_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; priv->beacon_vendor_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; + priv->mgmt_subtype_mask = 0; + priv->cfg_disconnect = MFALSE; + priv->cfg_connect = MFALSE; #endif #ifdef STA_SUPPORT #endif priv->enable_tcp_ack_enh = MTRUE; + priv->tcp_ack_drop_cnt = 0; + priv->tcp_ack_cnt = 0; + priv->tcp_ack_payload = 0; priv->tcp_ack_max_hold = TCP_ACK_MAX_HOLD; priv->enable_auto_tdls = MFALSE; @@ -6308,9 +6616,15 @@ void woal_init_priv(moal_private *priv, t_u8 wait_option) woal_request_set_mac_address(priv, MOAL_IOCTL_WAIT); moal_memcpy_ext(priv->phandle, priv->netdev->dev_addr, priv->current_addr, ETH_ALEN, ETH_ALEN); +#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) + priv->host_mlme = 0; + priv->auth_flag = 0; + priv->auth_alg = 0xFFFF; +#endif #ifdef UAP_SUPPORT priv->user_cac_period_msec = 0; + priv->chan_under_nop = MFALSE; #endif LEAVE(); } @@ -6419,6 +6733,11 @@ int woal_reset_intf(moal_private *priv, t_u8 wait_option, int all_intf) } #endif /* REASSOCIATION */ + if (handle->is_fw_dump_timer_set) { + woal_cancel_timer(&handle->fw_dump_timer); + handle->is_fw_dump_timer_set = MFALSE; + } + #ifdef WIFI_DIRECT_SUPPORT #if defined(STA_CFG80211) && defined(UAP_CFG80211) if (handle->is_go_timer_set) { @@ -7183,6 +7502,26 @@ void woal_reassoc_timer_func(void *context) } #endif /* REASSOCIATION */ +/** + * @brief This function triggers process hang + * re-assoc thread. + * + * @param context A pointer to context + * @return N/A + */ +void woal_fw_dump_timer_func(void *context) +{ + moal_handle *handle = (moal_handle *)context; + + ENTER(); + + PRINTM(MMSG, "fw_dump_timer fired.\n"); + handle->is_fw_dump_timer_set = MFALSE; + woal_process_hang(handle); + LEAVE(); + return; +} + #ifdef STA_SUPPORT /** * @brief update dscp mapping from assoc_resp/reassoc_resp @@ -7388,164 +7727,95 @@ t_void woal_send_disconnect_to_system(moal_private *priv, } #endif /* STA_SUPPORT */ -#if defined(PCIE) +#define OFFSET_SEQNUM 4 +#define OFFSET_TYPE 8 +#define DUMP_TYPE_ENDE 2 /** - * @brief This function stores the SSU dumps in a file + * @brief This function stores the FW dumps received from events * * @param phandle A pointer to moal_handle * @param pmevent A pointer to mlan_event structure * * @return N/A */ -t_void woal_store_ssu_dump(moal_handle *phandle, mlan_event *pmevent) -{ - struct dentry *dentry; - struct path path; - struct file *pfile_ssudump = NULL; - char dw_string[10]; - loff_t pos = 0; - t_u32 i; - t_u32 *tmpbuf; - - ENTER(); - dentry = kern_path_create(AT_FDCWD, "/data", &path, 1); - if (IS_ERR(dentry)) { - goto save_ssudump; - } -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) - vfs_mkdir(path.dentry->d_inode, dentry, 0777); -#else - vfs_mkdir(&init_user_ns, path.dentry->d_inode, dentry, 0777); -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0) - mutex_unlock(&path.dentry->d_inode->i_mutex); -#else - done_path_create(&path, dentry); -#endif - -save_ssudump: - pfile_ssudump = filp_open("/data/ssudump.txt", - O_CREAT | O_WRONLY | O_APPEND, 0644); - if (IS_ERR(pfile_ssudump)) { - PRINTM(MERROR, "Cannot create ssu dump file\n"); - LEAVE(); - return; - } - DBG_HEXDUMP(MEVT_D, "SSU addr", pmevent->event_buf, 8); - moal_memcpy_ext(phandle, &tmpbuf, pmevent->event_buf, sizeof(t_ptr), - sizeof(t_ptr)); - PRINTM(MEVENT, "woal_store_ssu_dump: tmpbuf %p\n", tmpbuf); - for (i = 0; i < pmevent->event_len / 4; i++) { - if ((i + 1) % 8 == 0) - snprintf(dw_string, sizeof(dw_string), "%08x\n", - *tmpbuf); - else - snprintf(dw_string, sizeof(dw_string), "%08x ", - *tmpbuf); -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) - vfs_write(pfile_ssudump, (const char __user *)dw_string, 9, - &pos); -#else - kernel_write(pfile_ssudump, dw_string, 9, &pos); -#endif - tmpbuf++; - } - filp_close(pfile_ssudump, NULL); - LEAVE(); - return; -} -#endif /* SSU_SUPPORT */ - -#define OFFSET_SEQNUM 4 -#define OFFSET_TYPE 8 -#define DUMP_TYPE_ENDE 2 t_void woal_store_firmware_dump(moal_handle *phandle, mlan_event *pmevent) { - struct file *pfile_fwdump = NULL; - loff_t pos = 0; + int ret = 0; t_u16 seqnum; t_u16 type = 0; - t_u8 path_name[64]; - moal_handle *ref_handle = NULL; + t_u8 *pos; ENTER(); - if (phandle->fwdump_fname) - pfile_fwdump = filp_open(phandle->fwdump_fname, - O_CREAT | O_WRONLY | O_APPEND, 0644); - else { - seqnum = woal_le16_to_cpu( - *(t_u16 *)(pmevent->event_buf + OFFSET_SEQNUM)); - type = woal_le16_to_cpu( - *(t_u16 *)(pmevent->event_buf + OFFSET_TYPE)); - if (seqnum == 1) { - if (drvdbg & MFW_D) - drvdbg &= ~MFW_D; - phandle->fw_dump_len = 0; - PRINTM(MMSG, - "==== Start Receive FW dump event ====\n"); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) - /** Create dump directort*/ - woal_create_dump_dir(phandle, path_name, - sizeof(path_name)); -#else - memset(path_name, 0, sizeof(path_name)); - strcpy(path_name, "/data"); -#endif - PRINTM(MMSG, "Firmware Dump directory name is %s\n", - path_name); - ref_handle = (moal_handle *)phandle->pref_mac; - if (ref_handle) - woal_dump_drv_info(ref_handle, path_name); - woal_dump_drv_info(phandle, path_name); - if (fwdump_fname) { - memset(fwdump_fname, 0, 64); - } else { - gfp_t flag; - flag = (in_atomic() || irqs_disabled()) ? - GFP_ATOMIC : - GFP_KERNEL; - fwdump_fname = kzalloc(64, flag); - } - sprintf(fwdump_fname, "%s/file_fwdump", path_name); - pfile_fwdump = - filp_open(fwdump_fname, - O_CREAT | O_WRONLY | O_APPEND, 0644); - if (IS_ERR(pfile_fwdump)) { - memset(fwdump_fname, 0, 64); - sprintf(fwdump_fname, "%s/%s", "/var", - "file_fwdump"); - pfile_fwdump = - filp_open(fwdump_fname, - O_CREAT | O_WRONLY | O_APPEND, - 0644); - } - } else - pfile_fwdump = - filp_open(fwdump_fname, - O_CREAT | O_WRONLY | O_APPEND, 0644); - } - if (IS_ERR(pfile_fwdump)) { - PRINTM(MERROR, "Cannot create firmware dump file\n"); + if (!phandle || !pmevent) { + PRINTM(MERROR, "Could not dump firmware info\n"); LEAVE(); return; } + seqnum = woal_le16_to_cpu( + *(t_u16 *)(pmevent->event_buf + OFFSET_SEQNUM)); + type = woal_le16_to_cpu(*(t_u16 *)(pmevent->event_buf + OFFSET_TYPE)); + + if (seqnum == 1) { + if (drvdbg & MFW_D) + drvdbg &= ~MFW_D; + if (phandle->fw_dump == MFALSE) { + PRINTM(MMSG, "=====FW trigger dump====\n"); + phandle->fw_dump = MTRUE; + phandle->is_fw_dump_timer_set = MTRUE; + woal_mod_timer(&phandle->fw_dump_timer, MOAL_TIMER_5S); + } + + if (!phandle->fw_dump_buf) { + ret = moal_vmalloc(phandle, FW_DUMP_INFO_LEN, + &phandle->fw_dump_buf); + if (ret != MLAN_STATUS_SUCCESS || + !phandle->fw_dump_buf) { + PRINTM(MERROR, + "Failed to vmalloc fw dump buffer\n"); + LEAVE(); + return; + } + } else { + memset(phandle->fw_dump_buf, 0x00, FW_DUMP_INFO_LEN); + } + phandle->fw_dump_len = 0; + PRINTM(MMSG, "==== Start Receive FW dump event ====\n"); + } else { + if (!phandle->fw_dump_buf || !phandle->fw_dump_len) { + PRINTM(MERROR, + "Error! Fw dump buffer is null or dump len is zero\n"); + LEAVE(); + return; + } + } + pos = phandle->fw_dump_buf + phandle->fw_dump_len; + moal_memcpy_ext(phandle, pos, pmevent->event_buf + OFFSET_SEQNUM, + pmevent->event_len - OFFSET_SEQNUM, + FW_DUMP_INFO_LEN - phandle->fw_dump_len); phandle->fw_dump_len += pmevent->event_len - OFFSET_SEQNUM; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) - vfs_write(pfile_fwdump, - (const char __user *)pmevent->event_buf + OFFSET_SEQNUM, - pmevent->event_len - OFFSET_SEQNUM, &pos); -#else - kernel_write(pfile_fwdump, pmevent->event_buf + OFFSET_SEQNUM, - pmevent->event_len - OFFSET_SEQNUM, &pos); -#endif - filp_close(pfile_fwdump, NULL); + + PRINTM(MINFO, "fw dump event: evt_len=%d toal_len=%ld\n", + pmevent->event_len, (long int)phandle->fw_dump_len); if (type == DUMP_TYPE_ENDE) { PRINTM(MMSG, "==== FW DUMP END: %ld bytes ====\n", (long int)phandle->fw_dump_len); + woal_append_end_block(phandle); phandle->fw_dump = MFALSE; + woal_send_fw_dump_complete_event( + woal_get_priv(phandle, MLAN_BSS_ROLE_ANY)); mlan_pm_wakeup_card(phandle->pmlan_adapter, MFALSE); + if (phandle->is_fw_dump_timer_set) { + woal_cancel_timer(&phandle->fw_dump_timer); + phandle->is_fw_dump_timer_set = MFALSE; + } +#ifdef USB + if (IS_USB(phandle->card_type)) + phandle->driver_status = MTRUE; +#endif + woal_process_hang(phandle); } + LEAVE(); return; } @@ -7829,8 +8099,11 @@ static int woal_dump_mlan_drv_info(moal_private *priv, t_u8 *buf) ptr += sprintf(ptr, "mp_wr_bitmap=0x%x curr_wr_port=0x%x\n", (unsigned int)info->mp_wr_bitmap, info->curr_wr_port); - ptr += sprintf(ptr, "mp_invalid_update=%d\n", - info->mp_invalid_update); + ptr += sprintf(ptr, "mp_data_port_mask=0x%x\n", + info->mp_data_port_mask); + ptr += sprintf( + ptr, "last_recv_rd_bitmap=0x%x mp_invalid_update=%d\n", + info->last_recv_rd_bitmap, info->mp_invalid_update); mp_aggr_pkt_limit = info->mp_aggr_pkt_limit; ptr += sprintf(ptr, "last_recv_wr_bitmap=0x%x last_mp_index = %d\n", @@ -7926,81 +8199,6 @@ static int woal_dump_mlan_drv_info(moal_private *priv, t_u8 *buf) LEAVE(); return ptr - (char *)buf; } -#define HostCmd_CMD_CFG_DATA 0x008f -#define DEF_FW_PATH "/lib/firmware/" -#define DEF_HOSTCMD_PATH "/lib/firmware/nxp/hostcmd.conf" -/** - * @brief This function save the hostcmd response to file - * - * @param phandle A pointer to moal_handle - * @param pevent A pointer to mlan_cmdresp_event - * - * @return N/A - */ -t_void woal_save_host_cmdresp(moal_handle *phandle, mlan_cmdresp_event *pevent) -{ - HostCmd_DS_GEN *resp; - char file_path[256]; - struct file *pfile = NULL; - char *dpd_data_cfg = phandle->params.dpd_data_cfg; - int ret; - t_u8 *buf; - t_u16 command; - int len = 0; - char *ptr; - loff_t pos = 0; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) - mm_segment_t fs; -#endif - - resp = (HostCmd_DS_GEN *)pevent->resp; - command = woal_le16_to_cpu(resp->command); - memset(file_path, 0, sizeof(file_path)); - ret = moal_vmalloc(phandle, pevent->event_len * 5, &buf); - if (ret != MLAN_STATUS_SUCCESS || !buf) { - PRINTM(MERROR, "Fail to allocate memory to save hostcmd\n"); - return; - } - memset(buf, 0, pevent->event_len * 5); - ptr = (char *)buf; - switch (command) { - case HostCmd_CMD_CFG_DATA: - if (dpd_data_cfg) - sprintf(file_path, "%s%s", DEF_FW_PATH, dpd_data_cfg); - else - sprintf(file_path, "%s", DEF_HOSTCMD_PATH); - break; - default: - sprintf(file_path, "%s", DEF_HOSTCMD_PATH); - break; - } - pfile = filp_open(file_path, O_CREAT | O_WRONLY | O_APPEND, 0644); - if (IS_ERR(pfile)) { - PRINTM(MERROR, "Cannot create file %s\n", file_path); - moal_vfree(phandle, buf); - return; - } - ptr += sprintf(ptr, "hostcmd_%02x=={\n", command); - ptr += woal_save_hex_dump(ROW_SIZE_16, resp, pevent->event_len, MFALSE, - ptr); - ptr += sprintf(ptr, "}\n"); - len = ptr - (char *)buf; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) - fs = get_fs(); - set_fs(KERNEL_DS); - vfs_write(pfile, (const char __user *)buf, len, &pos); - set_fs(fs); -#else - kernel_write(pfile, buf, len, &pos); -#endif - PRINTM(MMSG, "Save hostcmd 0x%02x, cmd len=%d file len=%d to file %s\n", - command, pevent->event_len, len, file_path); - if (buf) - moal_vfree(phandle, buf); - filp_close(pfile, NULL); - return; -} /** * @brief This function dump moal hex to file @@ -8109,232 +8307,123 @@ static int woal_dump_mlan_hex(moal_private *priv, t_u8 *buf) return ptr - (char *)buf; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) -/** - * @brief This function create dump directory - * - * @param phandle A pointer to moal_handle - * @param dir_buf A pointer to dir_buf buffer - * @param buf_size Size of dir_buf buffer - * - * @return N/A - */ -void woal_create_dump_dir(moal_handle *phandle, char *dir_buf, int buf_size) -{ - struct dentry *dentry; - struct path path; - t_u32 sec, usec; - int ret; - - ENTER(); - - if (!phandle || !dir_buf) { - PRINTM(MERROR, "Can't create directory\n"); - ret = MLAN_STATUS_FAILURE; - goto done; - } - - moal_get_system_time(phandle, &sec, &usec); - memset(dir_buf, 0, buf_size); - sprintf(dir_buf, "%s%u", "/data/dump_", sec); - - dentry = kern_path_create(AT_FDCWD, dir_buf, &path, 1); - if (IS_ERR(dentry)) { - PRINTM(MERROR, - "Create directory %s error, try create dir in /var", - dir_buf); - memset(dir_buf, 0, buf_size); - sprintf(dir_buf, "%s%u", "/var/dump_", sec); - dentry = kern_path_create(AT_FDCWD, dir_buf, &path, 1); - } - if (IS_ERR(dentry)) { - PRINTM(MERROR, "Create directory %s error, use default folder", - dir_buf); - goto default_dir; - } -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0) - ret = vfs_mkdir(path.dentry->d_inode, dentry, 0777); -#else - ret = vfs_mkdir(&init_user_ns, path.dentry->d_inode, dentry, 0777); -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0) - mutex_unlock(&path.dentry->d_inode->i_mutex); -#else - done_path_create(&path, dentry); -#endif - - if (ret < 0) { - PRINTM(MERROR, - "Create directory failure, use default folder\n"); - PRINTM(MERROR, "Create directory failure, ret = %d\n", ret); - goto default_dir; - } else { - PRINTM(MMSG, "Create directory %s successfully\n", dir_buf); - goto done; - } - -default_dir: - memset(dir_buf, 0, buf_size); - sprintf(dir_buf, "%s", "/data"); -done: - LEAVE(); -} -#endif - -/** - * @brief This function save dump buf to file - * - * @param dir_name A pointer to directory name - * @param file_name A pointer to file name - * @param buf A pointer to dump data - * @param buf_len The length of dump buf - * - * @return SUCCESS OR FAILURE - */ -mlan_status woal_save_dump_info_to_file(char *dir_name, char *file_name, - t_u8 *buf, t_u32 buf_len) -{ - mlan_status ret = MLAN_STATUS_SUCCESS; - struct file *pfile = NULL; - t_u8 name[64]; - loff_t pos; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) - mm_segment_t fs; -#endif - - ENTER(); - - if (!dir_name || !file_name || !buf) { - PRINTM(MERROR, "Can't save dump info to file\n"); - ret = MLAN_STATUS_FAILURE; - goto done; - } - - memset(name, 0, sizeof(name)); - sprintf(name, "%s/%s", dir_name, file_name); - pfile = filp_open(name, O_CREAT | O_RDWR, 0644); - if (IS_ERR(pfile)) { - PRINTM(MMSG, - "Create file %s error, try to save dump file in /var\n", - name); - memset(name, 0, sizeof(name)); - sprintf(name, "%s/%s", "/var", file_name); - pfile = filp_open(name, O_CREAT | O_RDWR, 0644); - } - if (IS_ERR(pfile)) { - PRINTM(MERROR, "Create Dump file for %s error\n", name); - ret = MLAN_STATUS_FAILURE; - goto done; - } - - PRINTM(MMSG, "Dump data %s saved in %s\n", file_name, name); - - pos = 0; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) - fs = get_fs(); - set_fs(KERNEL_DS); - vfs_write(pfile, (const char __user *)buf, buf_len, &pos); - set_fs(fs); -#else - kernel_write(pfile, buf, buf_len, &pos); -#endif - filp_close(pfile, NULL); - - PRINTM(MMSG, "Dump data %s saved in %s successfully\n", file_name, - name); - -done: - LEAVE(); - return ret; -} - /** * @brief This function dump drv info to file * * @param phandle A pointer to moal_handle - * @param dir_name A pointer to directory name + * @param dump_len A point to hold the len of drv info memory * - * @return N/A + * @return A pointer to drv_info memory */ -void woal_dump_drv_info(moal_handle *phandle, t_u8 *dir_name) +t_u8 *woal_dump_drv_info(moal_handle *phandle, t_u32 *dump_len) { - int ret = 0; - struct file *pfile = NULL; t_u8 *drv_buf = NULL; - t_u8 file_name[64]; t_u32 len = 0; t_u32 total_len = 0; - moal_private *woal_handle = NULL; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) - mm_segment_t fs; -#endif t_u32 drv_info_size = DRV_INFO_SIZE; - - ENTER(); - - PRINTM(MMSG, "=== START DRIVER INFO DUMP==="); - memset(file_name, 0, sizeof(file_name)); - if (phandle->second_mac) - sprintf(file_name, "%s/%s", dir_name, "file_drv_info_2"); - else - sprintf(file_name, "%s/%s", dir_name, "file_drv_info"); - pfile = filp_open(file_name, O_CREAT | O_RDWR, 0644); - if (IS_ERR(pfile)) { - PRINTM(MMSG, - "Create file %s error, try create /var/file_drv_info", - file_name); - pfile = filp_open("/var/file_drv_info", O_CREAT | O_RDWR, 0644); - } else { - PRINTM(MMSG, "DRV dump data in %s\n", file_name); - } - if (IS_ERR(pfile)) { - PRINTM(MMSG, "Create file_drv_info file failed\n"); + int ret; + if (phandle->priv_num > 3) + drv_info_size += (phandle->priv_num - 3) * DRV_INFO_PER_INTF; + PRINTM(MERROR, "=== START DRIVER INFO DUMP==="); + ret = moal_vmalloc(phandle, drv_info_size, &drv_buf); + if ((ret != MLAN_STATUS_SUCCESS) || !drv_buf) { + PRINTM(MERROR, "Error: vmalloc drv buffer failed!\n"); goto done; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) - fs = get_fs(); - set_fs(KERNEL_DS); -#endif - woal_handle = woal_get_priv(phandle, MLAN_BSS_ROLE_ANY); + len = woal_dump_moal_drv_info(phandle, drv_buf); + total_len += len; + len = woal_dump_mlan_drv_info(woal_get_priv(phandle, MLAN_BSS_ROLE_ANY), + drv_buf + total_len); + total_len += len; + len = woal_dump_moal_hex(phandle, drv_buf + total_len); + total_len += len; + len = woal_dump_mlan_hex(woal_get_priv(phandle, MLAN_BSS_ROLE_ANY), + drv_buf + total_len); + total_len += len; - if (woal_handle != NULL) { - if (phandle->priv_num > 3) - drv_info_size += - (phandle->priv_num - 3) * DRV_INFO_PER_INTF; - ret = moal_vmalloc(phandle, drv_info_size, &drv_buf); - if ((ret != MLAN_STATUS_SUCCESS) || !drv_buf) { - PRINTM(MERROR, "Error: vmalloc drv buffer failed!\n"); - goto done; - } - len = woal_dump_moal_drv_info(phandle, drv_buf); - total_len += len; - len = woal_dump_mlan_drv_info(woal_handle, drv_buf + total_len); - total_len += len; - len = woal_dump_moal_hex(phandle, drv_buf + total_len); - total_len += len; - len = woal_dump_mlan_hex(woal_handle, drv_buf + total_len); - total_len += len; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) - vfs_write(pfile, (const char __user *)drv_buf, total_len, - &pfile->f_pos); -#else - kernel_write(pfile, drv_buf, total_len, &pfile->f_pos); -#endif - } - PRINTM(MMSG, "Drv info total bytes = %ld (0x%lx)\n", + PRINTM(MERROR, "Drv info total bytes = %ld (0x%lx)\n", (long int)total_len, (long unsigned int)total_len); - filp_close(pfile, NULL); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) - set_fs(fs); -#endif - PRINTM(MMSG, "=== DRIVER INFO DUMP END==="); + PRINTM(MERROR, "=== DRIVER INFO DUMP END==="); + *dump_len = total_len; done: - if (drv_buf) - moal_vfree(phandle, drv_buf); + return drv_buf; +} + +/** + * @brief This function adds header and copy the src data to buf + * + * @param phandle A pointer to moal_handle + * @param src A ponter to source buffer + * @param len Length of raw data + * @param type Dump type + * + * return Total len of buf + */ +int woal_save_dump_info_to_buf(moal_handle *phandle, t_u8 *src, t_u32 len, + t_u32 type) +{ + mem_dump_header header; + t_u32 left_len = 0; + t_u32 len_to_copy = 0; + int total_len = 0; + t_u8 *dest = NULL; + int count = 0; + int pad = 0; + dest = phandle->fw_dump_buf + phandle->fw_dump_len; + + left_len = len; + while (left_len) { + header.type = type; + if (left_len < 1024) + len_to_copy = left_len; + else + len_to_copy = 1024; + header.len = (t_u16)(len_to_copy + sizeof(t_u32)); + header.start_addr = count * 1024; + moal_memcpy_ext(phandle, dest, &header, sizeof(mem_dump_header), + FW_DUMP_INFO_LEN - phandle->fw_dump_len); + dest += sizeof(mem_dump_header); + moal_memcpy_ext(phandle, dest, src, len_to_copy, + FW_DUMP_INFO_LEN - phandle->fw_dump_len - + sizeof(mem_dump_header)); + dest += len_to_copy; + src += len_to_copy; + left_len -= len_to_copy; + // 8 bytes align + pad = (header.len & 7) ? (8 - (header.len & 7)) : 0; + dest += pad; + total_len += pad + len_to_copy + sizeof(mem_dump_header); + count++; + } + phandle->fw_dump_len += total_len; + PRINTM(MMSG, "type=%d, len=%d block=%d total=%d\n", type, len, count, + total_len); + return total_len; +} + +/** + * @brief This function append end block to dump file + * + * @param phandle A pointer to moal_handle + * + * return N/A + */ +void woal_append_end_block(moal_handle *phandle) +{ + mem_dump_header header; + t_u8 *pos = phandle->fw_dump_buf + phandle->fw_dump_len; + ENTER(); + memset(&header, 0, sizeof(header)); + header.type = FW_DUMP_TYPE_ENDED; + header.len = 0; + moal_memcpy_ext(phandle, pos, &header, sizeof(mem_dump_header), + FW_DUMP_INFO_LEN - phandle->fw_dump_len); + phandle->fw_dump_len += sizeof(mem_dump_header); + PRINTM(MMSG, "fw dump total length is %ld\n", + (long int)phandle->fw_dump_len); LEAVE(); + return; } /** @@ -8578,14 +8667,14 @@ mlan_status woal_request_country_power_table(moal_private *priv, char *country) memset(file_path, 0, sizeof(file_path)); strncpy(file_path + strlen(file_path), country_name, strlen(country_name)); -#if defined(STA_CFG80211) || defined(UAP_CFG80211) - handle->country_code[0] = '0'; - handle->country_code[1] = '0'; -#endif PRINTM(MMSG, "Trying again download country_power_tble: %s\n", file_path); ret = woal_set_user_init_data(handle, COUNTRY_POWER_TABLE, MOAL_IOCTL_WAIT, file_path); + if (!ret) { + handle->country_code[0] = '0'; + handle->country_code[1] = '0'; + } } #endif #endif @@ -9395,12 +9484,7 @@ mlan_status woal_remove_card(void *card) woal_process_rf_test_mode(handle, MFG_CMD_UNSET_TEST_MODE); handle->surprise_removed = MTRUE; - flush_workqueue(handle->workqueue); - flush_workqueue(handle->evt_workqueue); - if (handle->rx_workqueue) - flush_workqueue(handle->rx_workqueue); - if (handle->tx_workqueue) - flush_workqueue(handle->tx_workqueue); + woal_flush_workqueue(handle); if (moal_extflg_isset(handle, EXT_NAPI)) { napi_disable(&handle->napi_rx); @@ -9444,6 +9528,10 @@ mlan_status woal_remove_card(void *card) atomic_read(&handle->tx_pending), atomic_read(&handle->ioctl_pending)); } + unregister_inetaddr_notifier(&handle->woal_notifier); +#if IS_ENABLED(CONFIG_IPV6) + unregister_inet6addr_notifier(&handle->woal_inet6_notifier); +#endif #if defined(STA_CFG80211) || defined(UAP_CFG80211) #if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39) @@ -9502,6 +9590,13 @@ mlan_status woal_remove_card(void *card) while (handle->reassoc_thread.pid) woal_sched_timeout(2); #endif /* REASSOCIATION */ + + PRINTM(MINFO, "Free FW dump timer\n"); + if (handle->is_fw_dump_timer_set) { + woal_cancel_timer(&handle->fw_dump_timer); + handle->is_fw_dump_timer_set = MFALSE; + } + #ifdef CONFIG_PROC_FS woal_proc_exit(handle); #endif @@ -9593,6 +9688,11 @@ mlan_status woal_switch_drv_mode(moal_handle *handle, t_u32 mode) atomic_read(&handle->ioctl_pending)); } + unregister_inetaddr_notifier(&handle->woal_notifier); +#if IS_ENABLED(CONFIG_IPV6) + unregister_inet6addr_notifier(&handle->woal_inet6_notifier); +#endif + /* Remove interface */ for (i = 0; i < MIN(MLAN_MAX_BSS_NUM, handle->priv_num); i++) woal_remove_interface(handle, i); @@ -9747,11 +9847,17 @@ static void woal_pre_reset(moal_handle *handle) { int intf_num; ENTER(); + handle->driver_status = MTRUE; /** detach network interface */ for (intf_num = 0; intf_num < handle->priv_num; intf_num++) { woal_stop_queue(handle->priv[intf_num]->netdev); netif_device_detach(handle->priv[intf_num]->netdev); } + woal_flush_workqueue(handle); + /** mask host interrupt from firmware */ + mlan_disable_host_int(handle->pmlan_adapter); + /** cancel all pending commands */ + mlan_ioctl(handle->pmlan_adapter, NULL); handle->fw_reload = MTRUE; woal_update_firmware_name(handle); #ifdef USB @@ -9777,7 +9883,6 @@ static void woal_post_reset(moal_handle *handle) ENTER(); /** un-block IOCTL */ handle->fw_reload = MFALSE; - handle->driver_status = MFALSE; /* Restart the firmware */ req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); if (req) { @@ -9794,6 +9899,7 @@ static void woal_post_reset(moal_handle *handle) } kfree(req); } + handle->driver_status = MFALSE; handle->hardware_status = HardwareStatusReady; /* Reset all interfaces */ woal_reset_intf(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), @@ -9826,6 +9932,18 @@ static void woal_post_reset(moal_handle *handle) woal_start_queue(handle->priv[intf_num]->netdev); } done: + if (handle->dpd_data) { + release_firmware(handle->dpd_data); + handle->dpd_data = NULL; + } + if (handle->txpwr_data) { + release_firmware(handle->txpwr_data); + handle->txpwr_data = NULL; + } + if (handle->user_data) { + release_firmware(handle->user_data); + handle->user_data = NULL; + } LEAVE(); return; } @@ -9910,10 +10028,17 @@ done: return; } -/** Register to bus driver function */ -static mlan_status woal_bus_register(void) +/** + * @brief This function register to bus driver + * + * @param work a pointer to struct work_struct + * + * @return N/A + */ +static void woal_bus_register(struct work_struct *work) { mlan_status ret = MLAN_STATUS_SUCCESS; + PRINTM(MMSG, "wlan: Register to Bus Driver...\n"); #ifdef SDIO #ifdef SDIO_MMC /* Register SDIO driver */ @@ -9946,11 +10071,17 @@ static mlan_status woal_bus_register(void) goto out; } #endif + PRINTM(MMSG, "wlan: Register to Bus Driver Done\n"); out: - return ret; + return; } -/** Unregister from bus driver function */ +/** + * @brief This function unregister from bus driver + * + * + * @return N/A + */ static void woal_bus_unregister(void) { #ifdef SDIO @@ -10017,13 +10148,23 @@ static int woal_init_module(void) #endif MLAN_INIT_WORK(&hang_work, woal_hang_work_queue); - /* Register with bus */ - ret = woal_bus_register(); - if (ret == MLAN_STATUS_SUCCESS) - PRINTM(MMSG, "wlan: Driver loaded successfully\n"); - else - PRINTM(MMSG, "wlan: Driver loading failed\n"); - + /* Create workqueue for hang process */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14) + /* For kernel less than 2.6.14 name can not be greater than 10 + characters */ + register_workqueue = create_workqueue("MOAL_REGISTER_WORKQ"); +#else +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) + register_workqueue = + alloc_workqueue("MOAL_REGISTER_WORK_QUEUE", + WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1); +#else + register_workqueue = create_workqueue("MOAL_REGISTER_WORK_QUEUE"); +#endif +#endif + MLAN_INIT_WORK(®ister_work, woal_bus_register); + queue_work(register_workqueue, ®ister_work); + PRINTM(MMSG, "wlan: Driver loaded successfully\n"); LEAVE(); return ret; } @@ -10205,6 +10346,12 @@ exit_sem_err: destroy_workqueue(hang_workqueue); hang_workqueue = NULL; } + if (register_workqueue) { + flush_workqueue(register_workqueue); + destroy_workqueue(register_workqueue); + register_workqueue = NULL; + } + woal_root_proc_remove(); LEAVE(); diff --git a/mxm_wifiex/wlan_src/mlinux/moal_main.h b/mxm_wifiex/wlan_src/mlinux/moal_main.h index 1ddd4a1..0446fee 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_main.h +++ b/mxm_wifiex/wlan_src/mlinux/moal_main.h @@ -697,6 +697,8 @@ out: #define NUM_TX_TIMEOUT_THRESHOLD 10 /** Custom event : DRIVER HANG */ #define CUS_EVT_DRIVER_HANG "EVENT=DRIVER_HANG" +/** Custom event : FW_DUMP */ +#define CUS_EVT_FW_DUMP "EVENT=FW_DUMP" /** TDLS connected event */ #define CUS_EVT_TDLS_CONNECTED "EVENT=TDLS_CONNECTED" @@ -786,6 +788,8 @@ typedef enum { /** Custom indiciation message sent to the application layer for WMM changes */ #define WMM_CONFIG_CHANGE_INDICATION "WMM_CONFIG_CHANGE.indication" +#define CUS_EVT_FW_DUMP_DONE "EVENT=FW_DUMP_DONE" + #ifdef UAP_SUPPORT /** Custom event : STA connected */ #define CUS_EVT_STA_CONNECTED "EVENT=STA_CONNECTED" @@ -831,9 +835,9 @@ typedef enum { #define MAX_RX_PENDING_THRHLD 50 /** high rx pending packets */ -#define HIGH_RX_PENDING 100 +#define USB_HIGH_RX_PENDING 100 /** low rx pending packets */ -#define LOW_RX_PENDING 80 +#define USB_LOW_RX_PENDING 80 /** MAX Tx Pending count */ #define MAX_TX_PENDING 800 @@ -937,6 +941,11 @@ typedef struct _wait_queue { #define MAX_UAP_BSS 1 /** Default uAP BSS */ #define DEF_UAP_BSS 1 + +/** WACP Modes for uAP */ +#define WACP_MODE_DEFAULT 0 +#define WACP_MODE_1 1 +#define WACP_MODE_2 2 #endif #ifdef WIFI_DIRECT_SUPPORT /** Driver mode WIFIDIRECT bit */ @@ -1266,12 +1275,14 @@ struct _moal_private { BOOLEAN media_connected; /** mclist work queue */ struct workqueue_struct *mclist_workqueue; - /** csa work */ + /** mclist work */ struct work_struct mclist_work; /** Statistics of tcp ack tx dropped */ t_u32 tcp_ack_drop_cnt; /** Statistics of tcp ack tx in total from kernel */ t_u32 tcp_ack_cnt; + /** Statistics of tcp ack with payload*/ + t_u32 tcp_ack_payload; #ifdef UAP_SUPPORT /** uAP started or not */ BOOLEAN bss_started; @@ -1302,6 +1313,12 @@ struct _moal_private { #endif #endif #endif + /** IP addr type */ + t_u32 ip_addr_type; + /** IP addr */ + t_u8 ip_addr[IPADDR_LEN]; + t_u8 ipv6_addr_configured; + t_u8 ipv6_addr[16]; #ifdef STA_SUPPORT /** scan type */ t_u8 scan_type; @@ -1315,6 +1332,10 @@ struct _moal_private { wlan_bgscan_cfg scan_cfg; /** sched scaning flag */ t_u8 sched_scanning; + /** sched_scan work queue */ + struct workqueue_struct *sched_scan_workqueue; + /** sched_scan work */ + struct delayed_work sched_scan_work; /** bgscan request id */ t_u64 bg_scan_reqid; #ifdef STA_CFG80211 @@ -1694,6 +1715,7 @@ enum ext_mod_params { EXT_TX_WORK, EXT_RPS, EXT_TX_SKB_CLONE, + EXT_PMQOS, EXT_MAX_PARAM, }; @@ -1717,6 +1739,7 @@ typedef struct _moal_mod_para { int max_uap_bss; char *uap_name; int uap_max_sta; + int wacp_mode; #endif /* UAP_SUPPORT */ #ifdef WIFI_DIRECT_SUPPORT int max_wfd_bss; @@ -1726,10 +1749,13 @@ typedef struct _moal_mod_para { #endif #endif /* WIFI_DIRECT_SUPPORT */ int auto_ds; + int net_rx; + int ext_scan; int ps_mode; int p2a_scan; /** scan chan gap */ int scan_chan_gap; + int sched_scan; int max_tx_buf; #if defined(SDIO) int gpiopin; @@ -1790,7 +1816,7 @@ void woal_set_tp_state(moal_private *priv); #define RX_DROP_P3 (MAX_TP_ACCOUNT_DROP_POINT_NUM + 2) #define RX_DROP_P4 (MAX_TP_ACCOUNT_DROP_POINT_NUM + 3) #define RX_DROP_P5 (MAX_TP_ACCOUNT_DROP_POINT_NUM + 4) -#define TXRX_MAX_SAMPLE 100 +#define TXRX_MAX_SAMPLE 60 #define RX_TIME_PKT (MAX_TP_ACCOUNT_DROP_POINT_NUM + 5) #define TX_TIME_PKT (MAX_TP_ACCOUNT_DROP_POINT_NUM + 6) @@ -1838,6 +1864,9 @@ typedef struct _moal_tp_acnt_t { unsigned long rx_delay1_driver[TXRX_MAX_SAMPLE]; unsigned long rx_delay2_driver[TXRX_MAX_SAMPLE]; unsigned long rx_delay_kernel[TXRX_MAX_SAMPLE]; + unsigned long rx_amsdu_delay[TXRX_MAX_SAMPLE]; + unsigned long rx_amsdu_copy_delay[TXRX_MAX_SAMPLE]; + t_u8 rx_amsdu_index; t_u8 rx_index; t_u8 tx_index; /* TP account mode 0-disable 1-enable */ @@ -2126,14 +2155,25 @@ struct _moal_handle { t_u8 driver_state; /** ioctl timeout */ t_u8 ioctl_timeout; + /** Pointer of fw dump buffer */ + t_u8 *drv_dump_buf; + /** drv dump len */ + t_u32 drv_dump_len; /** FW dump state */ t_u8 fw_dump; /** event fw dump */ t_u8 event_fw_dump; + /** Re-association timer set flag */ + BOOLEAN is_fw_dump_timer_set; + /** Re-association timer */ + moal_drv_timer fw_dump_timer __ATTRIB_ALIGN__; /** fw dump buffer total len */ t_u64 fw_dump_len; + /** Pointer of fw dump buffer */ + t_u8 *fw_dump_buf; /** FW dump full name */ t_u8 firmware_dump_file[128]; + #ifdef SDIO /** cmd52 function */ t_u8 cmd52_func; @@ -2170,6 +2210,9 @@ struct _moal_handle { /* feature_control */ t_u32 feature_control; struct notifier_block woal_notifier; +#if IS_ENABLED(CONFIG_IPV6) + struct notifier_block woal_inet6_notifier; +#endif mlan_ds_misc_keep_alive keep_alive[MAX_KEEP_ALIVE_ID]; struct net_device napi_dev; struct napi_struct napi_rx; @@ -2809,6 +2852,7 @@ mlan_status woal_init_sw(moal_handle *handle); void woal_update_firmware_name(moal_handle *handle); /** cancel all works in the queue */ void woal_terminate_workqueue(moal_handle *handle); +void woal_flush_workqueue(moal_handle *handle); /** initializes firmware */ mlan_status woal_init_fw(moal_handle *handle); /** frees the structure of moal_handle */ @@ -2932,12 +2976,24 @@ int woal_enable_hs(moal_private *priv); /** Get wakeup reason */ mlan_status woal_get_wakeup_reason(moal_private *priv, mlan_ds_hs_wakeup_reason *wakeup_reason); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) -void woal_create_dump_dir(moal_handle *phandle, char *dir_buf, int buf_size); -#endif -mlan_status woal_save_dump_info_to_file(char *dir_name, char *file_name, - t_u8 *buf, t_u32 buf_len); -void woal_dump_drv_info(moal_handle *phandle, t_u8 *dir_name); +#define FW_DUMP_INFO_LEN 0x280000 +/** mem dump header */ +typedef struct { + /** seq number */ + t_u16 seq_num; + /** resvered */ + t_u16 reserved; + /** type */ + t_u16 type; + /** len */ + t_u16 len; + /** start addr */ + t_u32 start_addr; +} mem_dump_header; +int woal_save_dump_info_to_buf(moal_handle *phandle, t_u8 *src, t_u32 len, + t_u32 type); +void woal_append_end_block(moal_handle *phandle); +t_u8 *woal_dump_drv_info(moal_handle *phandle, t_u32 *dump_len); #define FW_DUMP_TYPE_ENDED 0x002 #define FW_DUMP_TYPE_MEM_ITCM 0x004 @@ -2955,13 +3011,8 @@ void woal_dump_firmware_info_v3(moal_handle *phandle); #endif /* SDIO_MMC */ /* Store the FW dumps received from events in a file */ void woal_store_firmware_dump(moal_handle *phandle, pmlan_event pmevent); +void woal_send_fw_dump_complete_event(moal_private *priv); -#if defined(PCIE) -void woal_store_ssu_dump(moal_handle *phandle, pmlan_event pmevent); -#endif /* SSU_SUPPORT */ - -/** save hostcmd response to file */ -t_void woal_save_host_cmdresp(moal_handle *phandle, mlan_cmdresp_event *pevent); int woal_pre_warmreset(moal_private *priv); int woal_warmreset(moal_private *priv); @@ -3180,6 +3231,8 @@ int woal_reassociation_thread(void *data); void woal_reassoc_timer_func(void *context); #endif /* REASSOCIATION */ +void woal_fw_dump_timer_func(void *context); + t_void woal_main_work_queue(struct work_struct *work); t_void woal_rx_work_queue(struct work_struct *work); t_void woal_evt_work_queue(struct work_struct *work); @@ -3287,6 +3340,7 @@ void woal_hist_data_add(moal_private *priv, t_u16 rx_rate, t_s8 snr, t_s8 nflr, t_u8 antenna); mlan_status woal_set_hotspotcfg(moal_private *priv, t_u8 wait_option, t_u32 hotspotcfg); + mlan_status woal_set_get_wowlan_config(moal_private *priv, t_u16 action, t_u8 wait_option, mlan_ds_misc_mef_flt_cfg *mefcfg); @@ -3308,8 +3362,15 @@ int woal_priv_save_cloud_keep_alive_params( moal_private *priv, t_u8 mkeep_alive_id, t_u8 enable, t_u16 ether_type, t_u8 *ip_pkt, t_u16 ip_pkt_len, t_u8 *src_mac, t_u8 *dst_mac, t_u32 period_msec, t_u32 retry_interval, t_u8 retry_cnt); +#ifdef UAP_SUPPORT +mlan_status woal_set_wacp_mode(moal_private *priv, t_u8 wait_option); +#endif mlan_status woal_init_aggr_ctrl(moal_handle *handle, t_u8 wait_option); +#if defined(STA_CFG80211) || defined(UAP_CFG80211) +void woal_cfg80211_vendor_event_fw_dump(moal_private *priv); +#endif + #ifdef STA_CFG80211 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) mlan_status woal_set_rekey_data(moal_private *priv, diff --git a/mxm_wifiex/wlan_src/mlinux/moal_pcie.c b/mxm_wifiex/wlan_src/mlinux/moal_pcie.c index 6392759..0c29b21 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_pcie.c +++ b/mxm_wifiex/wlan_src/mlinux/moal_pcie.c @@ -36,6 +36,10 @@ Change log: #endif #endif +#if IS_ENABLED(CONFIG_IPV6) +#include +#endif + /******************************************************** Local Variables ********************************************************/ @@ -266,6 +270,11 @@ static mlan_status woal_do_flr(moal_handle *handle, bool prepare, bool flr_flag) atomic_read(&handle->ioctl_pending)); } + unregister_inetaddr_notifier(&handle->woal_notifier); +#if IS_ENABLED(CONFIG_IPV6) + unregister_inet6addr_notifier(&handle->woal_inet6_notifier); +#endif + /* Remove interface */ for (i = 0; i < handle->priv_num; i++) woal_remove_interface(handle, i); @@ -582,12 +591,7 @@ static int woal_pcie_suspend(struct pci_dev *pdev, pm_message_t state) goto done; } } - flush_workqueue(handle->workqueue); - flush_workqueue(handle->evt_workqueue); - if (handle->rx_workqueue) - flush_workqueue(handle->rx_workqueue); - if (handle->tx_workqueue) - flush_workqueue(handle->tx_workqueue); + woal_flush_workqueue(handle); if (!keep_power) { woal_do_flr(handle, true, false); handle->surprise_removed = MTRUE; @@ -1906,8 +1910,8 @@ static void woal_pcie_dump_fw_info_v1(moal_handle *phandle) rdwr_status stat; t_u8 i = 0; t_u8 read_reg = 0; - t_u32 memory_size = 0, DEBUG_MEMDUMP_FINISH; - t_u8 path_name[64], file_name[32], firmware_dump_file[128]; + t_u32 memory_size = 0; + t_u32 memdump_finsh = 0; t_u8 *end_ptr = NULL; memory_type_mapping *mem_type_mapping_tbl = mem_type_mapping_tbl_8897; @@ -1915,16 +1919,17 @@ static void woal_pcie_dump_fw_info_v1(moal_handle *phandle) PRINTM(MERROR, "Could not dump firmwware info\n"); return; } - DEBUG_MEMDUMP_FINISH = DEBUG_MEMDUMP_FINISH_8897; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) - /** Create dump directory*/ - woal_create_dump_dir(phandle, path_name, sizeof(path_name)); -#else - memset(path_name, 0, sizeof(path_name)); - strcpy(path_name, "/data"); -#endif - PRINTM(MMSG, "Directory name is %s\n", path_name); - woal_dump_drv_info(phandle, path_name); + if (!phandle->fw_dump_buf) { + ret = moal_vmalloc(phandle, FW_DUMP_INFO_LEN, + &(phandle->fw_dump_buf)); + if (ret != MLAN_STATUS_SUCCESS || !phandle->fw_dump_buf) { + PRINTM(MERROR, "Failed to vmalloc fw dump bufffer\n"); + return; + } + } else { + memset(phandle->fw_dump_buf, 0x00, FW_DUMP_INFO_LEN); + } + phandle->fw_dump_len = 0; /* start dump fw memory */ moal_get_system_time(phandle, &sec, &usec); PRINTM(MMSG, "====PCIE DEBUG MODE OUTPUT START: %u.%06u ====\n", sec, @@ -1960,7 +1965,7 @@ static void woal_pcie_dump_fw_info_v1(moal_handle *phandle) if (memory_size == 0) { PRINTM(MMSG, "Firmware Dump Finished!\n"); ret = woal_pcie_write_reg(phandle, DEBUG_DUMP_CTRL_REG, - DEBUG_MEMDUMP_FINISH); + memdump_finsh); if (ret) { PRINTM(MERROR, "PCIE Write MEMDUMP_FINISH ERR\n"); @@ -2013,17 +2018,11 @@ static void woal_pcie_dump_fw_info_v1(moal_handle *phandle) (unsigned int)(dbg_ptr - mem_type_mapping_tbl[idx] .mem_Ptr)); - memset(file_name, 0, sizeof(file_name)); - sprintf(file_name, "%s%s", "file_pcie_", - mem_type_mapping_tbl[idx].mem_name); - if (MLAN_STATUS_SUCCESS != - woal_save_dump_info_to_file( - path_name, file_name, - mem_type_mapping_tbl[idx].mem_Ptr, - memory_size)) - PRINTM(MMSG, - "Can't save dump file %s in %s\n", - file_name, path_name); + woal_save_dump_info_to_buf( + phandle, + mem_type_mapping_tbl[idx].mem_Ptr, + memory_size, + mem_type_mapping_tbl[idx].type); moal_vfree(phandle, mem_type_mapping_tbl[idx].mem_Ptr); mem_type_mapping_tbl[idx].mem_Ptr = NULL; @@ -2031,15 +2030,11 @@ static void woal_pcie_dump_fw_info_v1(moal_handle *phandle) } } while (1); } + woal_append_end_block(phandle); moal_get_system_time(phandle, &sec, &usec); PRINTM(MMSG, "====PCIE DEBUG MODE OUTPUT END: %u.%06u ====\n", sec, usec); /* end dump fw memory */ - memset(firmware_dump_file, 0, sizeof(firmware_dump_file)); - sprintf(firmware_dump_file, "%s/%s", path_name, file_name); - moal_memcpy_ext(phandle, phandle->firmware_dump_file, - firmware_dump_file, sizeof(firmware_dump_file), - sizeof(phandle->firmware_dump_file)); done: for (idx = 0; idx < dump_num && idx < ARRAY_SIZE(mem_type_mapping_tbl_8897); @@ -2073,8 +2068,6 @@ static void woal_pcie_dump_fw_info_v2(moal_handle *phandle) t_u8 doneflag = 0; rdwr_status stat; t_u32 memory_size = 0; - t_u8 path_name[64], file_name[32], firmware_dump_file[128]; - moal_handle *ref_handle; t_u8 *end_ptr = NULL; memory_type_mapping *mem_type_mapping_tbl = &mem_type_mapping_tbl_8997; t_u32 dump_start_reg = 0; @@ -2097,18 +2090,6 @@ static void woal_pcie_dump_fw_info_v2(moal_handle *phandle) } } #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) - /** Create dump directory*/ - woal_create_dump_dir(phandle, path_name, sizeof(path_name)); -#else - memset(path_name, 0, sizeof(path_name)); - strcpy(path_name, "/data"); -#endif - PRINTM(MMSG, "Create DUMP directory success:dir_name=%s\n", path_name); - ref_handle = (moal_handle *)phandle->pref_mac; - if (ref_handle) - woal_dump_drv_info(ref_handle, path_name); - woal_dump_drv_info(phandle, path_name); /* start dump fw memory */ moal_get_system_time(phandle, &sec, &usec); @@ -2206,17 +2187,14 @@ static void woal_pcie_dump_fw_info_v2(moal_handle *phandle) mem_type_mapping_tbl->mem_name, dbg_ptr - mem_type_mapping_tbl->mem_Ptr); #endif - memset(file_name, 0, sizeof(file_name)); - sprintf(file_name, "%s%s", "file_pcie_", - mem_type_mapping_tbl->mem_name); - if (MLAN_STATUS_SUCCESS != - woal_save_dump_info_to_file( - path_name, file_name, - mem_type_mapping_tbl->mem_Ptr, - dbg_ptr - mem_type_mapping_tbl->mem_Ptr)) - PRINTM(MMSG, "Can't save dump file %s in %s\n", - file_name, path_name); - moal_vfree(phandle, mem_type_mapping_tbl->mem_Ptr); + if (phandle->fw_dump_buf) { + moal_vfree(phandle, phandle->fw_dump_buf); + phandle->fw_dump_buf = NULL; + phandle->fw_dump_len = 0; + } + phandle->fw_dump_buf = mem_type_mapping_tbl->mem_Ptr; + phandle->fw_dump_len = + dbg_ptr - mem_type_mapping_tbl->mem_Ptr; mem_type_mapping_tbl->mem_Ptr = NULL; break; } @@ -2225,11 +2203,6 @@ static void woal_pcie_dump_fw_info_v2(moal_handle *phandle) PRINTM(MMSG, "====PCIE DEBUG MODE OUTPUT END: %u.%06u ====\n", sec, usec); /* end dump fw memory */ - memset(firmware_dump_file, 0, sizeof(firmware_dump_file)); - sprintf(firmware_dump_file, "%s/%s", path_name, file_name); - moal_memcpy_ext(phandle, phandle->firmware_dump_file, - firmware_dump_file, sizeof(firmware_dump_file), - sizeof(phandle->firmware_dump_file)); done: if (mem_type_mapping_tbl->mem_Ptr) { moal_vfree(phandle, mem_type_mapping_tbl->mem_Ptr); @@ -2273,13 +2246,18 @@ static void woal_pcie_dump_fw_info(moal_handle *phandle) if (phandle->event_fw_dump) { phandle->event_fw_dump = MFALSE; queue_work(phandle->workqueue, &phandle->main_work); + phandle->is_fw_dump_timer_set = MTRUE; + woal_mod_timer(&phandle->fw_dump_timer, MOAL_TIMER_5S); return; } } #endif + woal_send_fw_dump_complete_event( + woal_get_priv(phandle, MLAN_BSS_ROLE_ANY)); phandle->fw_dump = MFALSE; mlan_pm_wakeup_card(phandle->pmlan_adapter, MFALSE); queue_work(phandle->workqueue, &phandle->main_work); + woal_process_hang(phandle); } static mlan_status woal_pcie_get_fw_name(moal_handle *handle) diff --git a/mxm_wifiex/wlan_src/mlinux/moal_priv.c b/mxm_wifiex/wlan_src/mlinux/moal_priv.c index 7005caf..50dd12c 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_priv.c +++ b/mxm_wifiex/wlan_src/mlinux/moal_priv.c @@ -803,7 +803,7 @@ static int woal_11n_prio_tbl(moal_private *priv, struct iwreq *wrq) ENTER(); - if ((wrq->u.data.pointer == NULL)) { + if (wrq->u.data.pointer == NULL) { LEAVE(); return -EINVAL; } @@ -3898,6 +3898,57 @@ done: return ret; } +/** + * @brief arpfilter ioctl function + * + * @param priv A pointer to moal_private structure + * @param wrq A pointer to iwreq structure + * @return 0 --success, otherwise fail + */ +static int woal_arp_filter(moal_private *priv, struct iwreq *wrq) +{ + int ret = 0; + mlan_ds_misc_cfg *misc = NULL; + mlan_ioctl_req *req = NULL; + int data_length = wrq->u.data.length, copy_len; + mlan_status status = MLAN_STATUS_SUCCESS; + + ENTER(); + + copy_len = MIN(sizeof(misc->param.gen_ie.ie_data), + sizeof(int) * data_length); + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + misc = (mlan_ds_misc_cfg *)req->pbuf; + misc->sub_command = MLAN_OID_MISC_GEN_IE; + req->req_id = MLAN_IOCTL_MISC_CFG; + req->action = MLAN_ACT_SET; + misc->param.gen_ie.type = MLAN_IE_TYPE_ARP_FILTER; + misc->param.gen_ie.len = data_length; + + /* get the whole command from user */ + if (copy_from_user(misc->param.gen_ie.ie_data, wrq->u.data.pointer, + copy_len)) { + PRINTM(MERROR, "copy from user failed\n"); + ret = -EFAULT; + goto done; + } + + status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT); + if (status != MLAN_STATUS_SUCCESS) { + ret = -EFAULT; + goto done; + } +done: + if (status != MLAN_STATUS_PENDING) + kfree(req); + LEAVE(); + return ret; +} + /** * @brief Set/get IP address * @@ -6634,6 +6685,9 @@ int woal_wext_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd) case WOAL_HOST_CMD: ret = woal_host_command(priv, wrq); break; + case WOAL_ARP_FILTER: + ret = woal_arp_filter(priv, wrq); + break; case WOAL_SET_INTS_GET_CHARS: switch ((int)wrq->u.data.flags) { case WOAL_READ_EEPROM: diff --git a/mxm_wifiex/wlan_src/mlinux/moal_priv.h b/mxm_wifiex/wlan_src/mlinux/moal_priv.h index 5dba96a..67bbf78 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_priv.h +++ b/mxm_wifiex/wlan_src/mlinux/moal_priv.h @@ -235,6 +235,9 @@ Change log: /** Private command ID for hostcmd */ #define WOAL_HOST_CMD (WOAL_IOCTL + 17) +/** Private command ID for arpfilter */ +#define WOAL_ARP_FILTER (WOAL_IOCTL + 19) + /** Private command ID to set ints and get chars */ #define WOAL_SET_INTS_GET_CHARS (WOAL_IOCTL + 21) /** Private command ID to read EEPROM data */ diff --git a/mxm_wifiex/wlan_src/mlinux/moal_proc.c b/mxm_wifiex/wlan_src/mlinux/moal_proc.c index 3b1c3be..8fc7b3e 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_proc.c +++ b/mxm_wifiex/wlan_src/mlinux/moal_proc.c @@ -513,7 +513,10 @@ static ssize_t woal_config_write(struct file *f, const char __user *buf, #endif /* SD */ if (!strncmp(databuf, "debug_dump", strlen("debug_dump"))) { PRINTM(MERROR, "Recevie debug_dump command\n"); - handle->driver_status = MTRUE; +#ifdef USB + if (!IS_USB(handle->card_type)) +#endif + handle->driver_status = MTRUE; ref_handle = (moal_handle *)handle->pref_mac; if (ref_handle) { priv = woal_get_priv(ref_handle, MLAN_BSS_ROLE_ANY); @@ -799,6 +802,156 @@ static const struct file_operations config_proc_fops = { }; #endif +static int woal_drv_dump_read(struct seq_file *sfp, void *data) +{ + moal_handle *handle = (moal_handle *)sfp->private; + int ret = 0; + + ENTER(); + + if (MODULE_GET == 0) { + LEAVE(); + return 0; + } + + if (!handle) { + PRINTM(MERROR, "handle is NULL!\n"); + LEAVE(); + return 0; + } + if (!handle->drv_dump_buf || !handle->drv_dump_len) + handle->drv_dump_buf = + woal_dump_drv_info(handle, &handle->drv_dump_len); + if (!handle->drv_dump_buf || !handle->drv_dump_len) { + PRINTM(MERROR, + "driver dump buffer is NULL or total length is zero\n"); + goto done; + } + if (sfp->size < handle->drv_dump_len) { + PRINTM(MERROR, + "drv dump size too big, size=%d, drv_dump_len=%d\n", + (int)sfp->size, handle->drv_dump_len); + sfp->count = sfp->size; + ret = 0; + MODULE_PUT; + return ret; + } + memset(sfp->buf, 0x00, sfp->size); + sfp->count = handle->drv_dump_len; + moal_memcpy_ext(handle, sfp->buf, handle->drv_dump_buf, + handle->drv_dump_len, sfp->size); +done: + moal_vfree(handle, handle->drv_dump_buf); + handle->drv_dump_len = 0; + handle->drv_dump_buf = NULL; + MODULE_PUT; + LEAVE(); + return 0; +} + +static int woal_drv_dump_proc_open(struct inode *inode, struct file *file) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) + return single_open(file, woal_drv_dump_read, PDE_DATA(inode)); +#else + return single_open(file, woal_drv_dump_read, PDE(inode)->data); +#endif +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) +static const struct proc_ops drv_dump_fops = { + .proc_open = woal_drv_dump_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, +}; +#else +static const struct file_operations drv_dump_fops = { + .owner = THIS_MODULE, + .open = woal_drv_dump_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +#endif + +static int woal_fw_dump_read(struct seq_file *sfp, void *data) +{ + moal_handle *handle = (moal_handle *)sfp->private; + int ret = 0; + + ENTER(); + + if (MODULE_GET == 0) { + LEAVE(); + return 0; + } + + if (!handle) { + PRINTM(MERROR, "handle is null!\n"); + goto done; + } + + if (handle->fw_dump == MTRUE) { + PRINTM(MERROR, "fw dump is in progress\n"); + goto done; + } + + if (!handle->fw_dump_buf || !handle->fw_dump_len) { + PRINTM(MERROR, + "fw dump buffer is NULL or total length is zero\n"); + goto done; + } + + if (sfp->size < handle->fw_dump_len) { + PRINTM(MERROR, + "fw dump size too big, size=%d, fw_dump_len=%ld\n", + (int)sfp->size, (long int)handle->fw_dump_len); + sfp->count = sfp->size; + ret = 0; + MODULE_PUT; + return ret; + } + + sfp->count = handle->fw_dump_len; + moal_memcpy_ext(handle, sfp->buf, handle->fw_dump_buf, + handle->fw_dump_len, sfp->size); + moal_vfree(handle, handle->fw_dump_buf); + handle->fw_dump_buf = NULL; + handle->fw_dump_len = 0; + +done: + MODULE_PUT; + LEAVE(); + return 0; +} + +static int woal_fw_dump_proc_open(struct inode *inode, struct file *file) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) + return single_open(file, woal_fw_dump_read, PDE_DATA(inode)); +#else + return single_open(file, woal_fw_dump_read, PDE(inode)->data); +#endif +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) +static const struct proc_ops fw_dump_fops = { + .proc_open = woal_fw_dump_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, +}; +#else +static const struct file_operations fw_dump_fops = { + .owner = THIS_MODULE, + .open = woal_fw_dump_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +#endif + /** * @brief wifi status proc read function * @@ -875,7 +1028,7 @@ int woal_string_to_number(char *s) } else base = 10; - for (s = s; *s; s++) { + for (; *s; s++) { if ((*s >= '0') && (*s <= '9')) r = (r * base) + (*s - '0'); else if ((*s >= 'A') && (*s <= 'F')) @@ -910,7 +1063,7 @@ mlan_status woal_root_proc_init(void) } /* create /proc/mwlan/wifi_status */ - proc_create_data(STATUS_PROC, 0644, proc_mwlan, &wifi_status_proc_fops, + proc_create_data(STATUS_PROC, 0666, proc_mwlan, &wifi_status_proc_fops, NULL); LEAVE(); @@ -949,6 +1102,8 @@ void woal_proc_init(moal_handle *handle) struct proc_dir_entry *pde = proc_mwlan; #endif char config_proc_dir[20]; + char drv_dump_dir[20]; + char fw_dump_dir[20]; ENTER(); @@ -992,7 +1147,7 @@ void woal_proc_init(moal_handle *handle) strcpy(config_proc_dir, "config"); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) - r = proc_create_data(config_proc_dir, 0644, handle->proc_wlan, + r = proc_create_data(config_proc_dir, 0666, handle->proc_wlan, &config_proc_fops, handle); #else r = create_proc_entry(config_proc_dir, 0644, handle->proc_wlan); @@ -1004,6 +1159,34 @@ void woal_proc_init(moal_handle *handle) if (!r) PRINTM(MERROR, "Fail to create proc config\n"); + strcpy(drv_dump_dir, "drv_dump"); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + r = proc_create_data(drv_dump_dir, 0644, handle->proc_wlan, + &drv_dump_fops, handle); +#else + r = create_proc_entry(drv_dump_dir, 0644, handle->proc_wlan); + if (r) { + r->data = handle; + r->proc_fops = &drv_dump_fops; + } +#endif + if (!r) + PRINTM(MERROR, "Failed to create proc drv dump\n"); + + strcpy(fw_dump_dir, "fw_dump"); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) + r = proc_create_data(fw_dump_dir, 0644, handle->proc_wlan, + &fw_dump_fops, handle); +#else + r = create_proc_entry(fw_dump_dir, 0644, handle->proc_wlan); + if (r) { + r->data = handle; + r->proc_fops = &fw_dump_fops; + } +#endif + if (!r) + PRINTM(MERROR, "Failed to create proc fw dump\n"); + done: LEAVE(); } @@ -1018,6 +1201,8 @@ done: void woal_proc_exit(moal_handle *handle) { char config_proc_dir[20]; + char drv_dump_dir[20]; + char fw_dump_dir[20]; ENTER(); @@ -1025,6 +1210,10 @@ void woal_proc_exit(moal_handle *handle) if (handle->proc_wlan) { strcpy(config_proc_dir, "config"); remove_proc_entry(config_proc_dir, handle->proc_wlan); + strcpy(drv_dump_dir, "drv_dump"); + remove_proc_entry(drv_dump_dir, handle->proc_wlan); + strcpy(fw_dump_dir, "fw_dump"); + remove_proc_entry(fw_dump_dir, handle->proc_wlan); #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) /* Remove only if we are the only instance using this */ @@ -1042,6 +1231,16 @@ void woal_proc_exit(moal_handle *handle) } #endif } + if (handle->fw_dump_buf) { + moal_vfree(handle, handle->fw_dump_buf); + handle->fw_dump_buf = NULL; + handle->fw_dump_len = 0; + } + if (handle->drv_dump_buf) { + moal_vfree(handle, handle->drv_dump_buf); + handle->drv_dump_len = 0; + handle->drv_dump_buf = NULL; + } LEAVE(); } diff --git a/mxm_wifiex/wlan_src/mlinux/moal_sdio_mmc.c b/mxm_wifiex/wlan_src/mlinux/moal_sdio_mmc.c index 2fab6e6..8fa8db7 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_sdio_mmc.c +++ b/mxm_wifiex/wlan_src/mlinux/moal_sdio_mmc.c @@ -1670,7 +1670,6 @@ void woal_dump_firmware_info(moal_handle *phandle) { int ret = 0; unsigned int reg, reg_start, reg_end; - t_u8 path_name[64], file_name[32]; t_u8 *ITCM_Ptr = NULL; t_u8 *DTCM_Ptr = NULL; t_u8 *SQRAM_Ptr = NULL; @@ -1686,15 +1685,17 @@ void woal_dump_firmware_info(moal_handle *phandle) PRINTM(MERROR, "Could not dump firmwware info\n"); return; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) - /** Create dump directort*/ - woal_create_dump_dir(phandle, path_name, sizeof(path_name)); -#else - memset(path_name, 0, sizeof(path_name)); - strcpy(path_name, "/data"); -#endif - PRINTM(MMSG, "Directory name is %s\n", path_name); - woal_dump_drv_info(phandle, path_name); + if (!phandle->fw_dump_buf) { + ret = moal_vmalloc(phandle, FW_DUMP_INFO_LEN, + &(phandle->fw_dump_buf)); + if (ret != MLAN_STATUS_SUCCESS || !phandle->fw_dump_buf) { + PRINTM(MERROR, "Failed to vmalloc fw dump bufffer\n"); + return; + } + } else { + memset(phandle->fw_dump_buf, 0x00, FW_DUMP_INFO_LEN); + } + phandle->fw_dump_len = 0; #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32) sdio_claim_host(((struct sdio_mmc_card *)phandle->card)->func); @@ -1792,13 +1793,8 @@ void woal_dump_firmware_info(moal_handle *phandle) PRINTM(MMSG, "ITCM done: size=0x%x\n", dbg_ptr - ITCM_Ptr); #endif - memset(file_name, 0, sizeof(file_name)); - sprintf(file_name, "%s", "file_sdio_ITCM"); - if (MLAN_STATUS_SUCCESS != - woal_save_dump_info_to_file(path_name, file_name, - ITCM_Ptr, ITCM_SIZE)) - PRINTM(MMSG, "Can't save dump file %s in %s\n", - file_name, path_name); + woal_save_dump_info_to_buf(phandle, ITCM_Ptr, ITCM_SIZE, + FW_DUMP_TYPE_MEM_ITCM); dbg_ptr = DTCM_Ptr; end_ptr = DTCM_Ptr + dtcm_size; moal_get_system_time(phandle, &sec, &usec); @@ -1814,13 +1810,8 @@ void woal_dump_firmware_info(moal_handle *phandle) PRINTM(MMSG, "DTCM done: size=0x%x\n", dbg_ptr - DTCM_Ptr); #endif - memset(file_name, 0, sizeof(file_name)); - sprintf(file_name, "%s", "file_sdio_DTCM"); - if (MLAN_STATUS_SUCCESS != - woal_save_dump_info_to_file(path_name, file_name, - DTCM_Ptr, dtcm_size)) - PRINTM(MMSG, "Can't save dump file %s in %s\n", - file_name, path_name); + woal_save_dump_info_to_buf(phandle, ITCM_Ptr, dtcm_size, + FW_DUMP_TYPE_MEM_DTCM); dbg_ptr = SQRAM_Ptr; end_ptr = SQRAM_Ptr + sqram_size; moal_get_system_time(phandle, &sec, &usec); @@ -1836,13 +1827,9 @@ void woal_dump_firmware_info(moal_handle *phandle) PRINTM(MMSG, "SQRAM done: size=0x%x\n", dbg_ptr - SQRAM_Ptr); #endif - memset(file_name, 0, sizeof(file_name)); - sprintf(file_name, "%s", "file_sdio_SQRAM"); - if (MLAN_STATUS_SUCCESS != - woal_save_dump_info_to_file(path_name, file_name, - SQRAM_Ptr, sqram_size)) - PRINTM(MMSG, "Can't save dump file %s in %s\n", - file_name, path_name); + woal_save_dump_info_to_buf(phandle, SQRAM_Ptr, + sqram_size, + FW_DUMP_TYPE_MEM_SQRAM); PRINTM(MMSG, "End output!\n"); break; default: @@ -1850,6 +1837,7 @@ void woal_dump_firmware_info(moal_handle *phandle) } } while (ctrl_data != DEBUG_SQRAM_DONE); + woal_append_end_block(phandle); PRINTM(MMSG, "The output ITCM/DTCM/SQRAM have been saved to files successfully!\n"); moal_get_system_time(phandle, &sec, &usec); @@ -1890,7 +1878,6 @@ void woal_dump_firmware_info_v2(moal_handle *phandle) t_u8 i = 0; t_u8 read_reg = 0; t_u32 memory_size = 0; - t_u8 path_name[64], file_name[32], firmware_dump_file[128]; t_u8 *end_ptr = NULL; t_u8 dbg_dump_start_reg = 0; t_u8 dbg_dump_end_reg = 0; @@ -1905,16 +1892,17 @@ void woal_dump_firmware_info_v2(moal_handle *phandle) dbg_dump_end_reg = phandle->card_info->dump_fw_end_reg; dbg_dump_ctrl_reg = phandle->card_info->dump_fw_ctrl_reg; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) - /** Create dump directort*/ - woal_create_dump_dir(phandle, path_name, sizeof(path_name)); -#else - memset(path_name, 0, sizeof(path_name)); - strcpy(path_name, "/data"); -#endif - PRINTM(MMSG, "Directory name is %s\n", path_name); - - woal_dump_drv_info(phandle, path_name); + if (!phandle->fw_dump_buf) { + ret = moal_vmalloc(phandle, FW_DUMP_INFO_LEN, + &(phandle->fw_dump_buf)); + if (ret != MLAN_STATUS_SUCCESS || !phandle->fw_dump_buf) { + PRINTM(MERROR, "Failed to vmalloc fw dump bufffer\n"); + return; + } + } else { + memset(phandle->fw_dump_buf, 0x00, FW_DUMP_INFO_LEN); + } + phandle->fw_dump_len = 0; /* start dump fw memory */ moal_get_system_time(phandle, &sec, &usec); @@ -2009,17 +1997,11 @@ void woal_dump_firmware_info_v2(moal_handle *phandle) dbg_ptr - mem_type_mapping_tbl[idx] .mem_Ptr); #endif - memset(file_name, 0, sizeof(file_name)); - sprintf(file_name, "%s%s", "file_sdio_", - mem_type_mapping_tbl[idx].mem_name); - if (MLAN_STATUS_SUCCESS != - woal_save_dump_info_to_file( - path_name, file_name, - mem_type_mapping_tbl[idx].mem_Ptr, - memory_size)) - PRINTM(MERROR, - "Can't save dump file %s in %s\n", - file_name, path_name); + woal_save_dump_info_to_buf( + phandle, + mem_type_mapping_tbl[idx].mem_Ptr, + memory_size, + mem_type_mapping_tbl[idx].type); moal_vfree(phandle, mem_type_mapping_tbl[idx].mem_Ptr); mem_type_mapping_tbl[idx].mem_Ptr = NULL; @@ -2027,14 +2009,10 @@ void woal_dump_firmware_info_v2(moal_handle *phandle) } } while (1); } + woal_append_end_block(phandle); moal_get_system_time(phandle, &sec, &usec); PRINTM(MMSG, "==== DEBUG MODE OUTPUT END: %u.%06u ====\n", sec, usec); /* end dump fw memory */ - memset(firmware_dump_file, 0, sizeof(firmware_dump_file)); - sprintf(firmware_dump_file, "%s/%s", path_name, file_name); - moal_memcpy_ext(phandle, phandle->firmware_dump_file, - firmware_dump_file, sizeof(firmware_dump_file), - sizeof(phandle->firmware_dump_file)); done: for (idx = 0; idx < dump_num; idx++) { if (mem_type_mapping_tbl[idx].mem_Ptr) { @@ -2065,8 +2043,6 @@ void woal_dump_firmware_info_v3(moal_handle *phandle) t_u8 doneflag = 0; rdwr_status stat; t_u32 memory_size = 0; - t_u8 path_name[64], file_name[32], firmware_dump_file[128]; - moal_handle *ref_handle; t_u8 *end_ptr = NULL; t_u8 dbg_dump_start_reg = 0; t_u8 dbg_dump_end_reg = 0; @@ -2093,19 +2069,6 @@ void woal_dump_firmware_info_v3(moal_handle *phandle) dbg_dump_start_reg = phandle->card_info->dump_fw_start_reg; dbg_dump_end_reg = phandle->card_info->dump_fw_end_reg; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) - /** Create dump directort*/ - woal_create_dump_dir(phandle, path_name, sizeof(path_name)); -#else - memset(path_name, 0, sizeof(path_name)); - strcpy(path_name, "/data"); -#endif - PRINTM(MMSG, "Directory name is %s\n", path_name); - ref_handle = (moal_handle *)phandle->pref_mac; - if (ref_handle) - woal_dump_drv_info(ref_handle, path_name); - woal_dump_drv_info(phandle, path_name); - /* start dump fw memory */ moal_get_system_time(phandle, &sec, &usec); PRINTM(MMSG, "==== DEBUG MODE OUTPUT START: %u.%06u ====\n", sec, usec); @@ -2201,18 +2164,14 @@ void woal_dump_firmware_info_v3(moal_handle *phandle) dbg_ptr - pmem_type_mapping_tbl->mem_Ptr); #endif - memset(file_name, 0, sizeof(file_name)); - sprintf(file_name, "%s%s", "file_sdio_", - pmem_type_mapping_tbl->mem_name); - if (MLAN_STATUS_SUCCESS != - woal_save_dump_info_to_file( - path_name, file_name, - pmem_type_mapping_tbl->mem_Ptr, - dbg_ptr - pmem_type_mapping_tbl->mem_Ptr)) - PRINTM(MERROR, - "Can't save dump file %s in %s\n", - file_name, path_name); - moal_vfree(phandle, pmem_type_mapping_tbl->mem_Ptr); + if (phandle->fw_dump_buf) { + moal_vfree(phandle, phandle->fw_dump_buf); + phandle->fw_dump_buf = NULL; + phandle->fw_dump_len = 0; + } + phandle->fw_dump_buf = pmem_type_mapping_tbl->mem_Ptr; + phandle->fw_dump_len = + dbg_ptr - pmem_type_mapping_tbl->mem_Ptr; pmem_type_mapping_tbl->mem_Ptr = NULL; break; } @@ -2220,11 +2179,6 @@ void woal_dump_firmware_info_v3(moal_handle *phandle) moal_get_system_time(phandle, &sec, &usec); PRINTM(MMSG, "==== DEBUG MODE OUTPUT END: %u.%06u ====\n", sec, usec); /* end dump fw memory */ - memset(firmware_dump_file, 0, sizeof(firmware_dump_file)); - sprintf(firmware_dump_file, "%s/%s", path_name, file_name); - moal_memcpy_ext(phandle, phandle->firmware_dump_file, - firmware_dump_file, sizeof(firmware_dump_file), - sizeof(phandle->firmware_dump_file)); done: if (pmem_type_mapping_tbl->mem_Ptr) { moal_vfree(phandle, pmem_type_mapping_tbl->mem_Ptr); @@ -2329,6 +2283,8 @@ static void woal_sdiommc_dump_fw_info(moal_handle *phandle) if (phandle->event_fw_dump) { phandle->event_fw_dump = MFALSE; queue_work(phandle->workqueue, &phandle->main_work); + phandle->is_fw_dump_timer_set = MTRUE; + woal_mod_timer(&phandle->fw_dump_timer, MOAL_TIMER_5S); return; } } @@ -2337,9 +2293,12 @@ static void woal_sdiommc_dump_fw_info(moal_handle *phandle) woal_dump_firmware_info(phandle); } #endif + woal_send_fw_dump_complete_event( + woal_get_priv(phandle, MLAN_BSS_ROLE_ANY)); phandle->fw_dump = MFALSE; mlan_pm_wakeup_card(phandle->pmlan_adapter, MFALSE); queue_work(phandle->workqueue, &phandle->main_work); + woal_process_hang(phandle); return; } diff --git a/mxm_wifiex/wlan_src/mlinux/moal_shim.c b/mxm_wifiex/wlan_src/mlinux/moal_shim.c index e76d6ba..663fa48 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_shim.c +++ b/mxm_wifiex/wlan_src/mlinux/moal_shim.c @@ -653,6 +653,28 @@ mlan_status moal_spin_unlock(t_void *pmoal, t_void *plock) return MLAN_STATUS_SUCCESS; } +/** + * @brief This function collects AMSDU TP statistics. + * + * @param pmoal Pointer to the MOAL context + * @param amsdu_process_delay amsdu process time + * @param amsdu_copy_delay amsdu copy time + * + * @return N/A + */ +void moal_amsdu_tp_accounting(t_void *pmoal, t_s32 amsdu_process_delay, + t_s32 amsdu_copy_delay) +{ + moal_handle *handle = (moal_handle *)pmoal; + handle->tp_acnt.rx_amsdu_delay[handle->tp_acnt.rx_amsdu_index] = + amsdu_process_delay; + handle->tp_acnt.rx_amsdu_copy_delay[handle->tp_acnt.rx_amsdu_index] = + amsdu_copy_delay; + handle->tp_acnt.rx_amsdu_index++; + if (handle->tp_acnt.rx_amsdu_index >= TXRX_MAX_SAMPLE) + handle->tp_acnt.rx_amsdu_index = 0; +} + /** * @brief This function collects TP statistics. * @@ -1189,13 +1211,13 @@ mlan_status moal_recv_complete(t_void *pmoal, pmlan_buffer pmbuf, t_u32 port, else { woal_free_mlan_buffer(handle, pmbuf); if ((atomic_read(&handle->rx_pending) < - LOW_RX_PENDING) && + USB_LOW_RX_PENDING) && atomic_read(&cardp->rx_data_urb_pending) < MVUSB_RX_DATA_URB) woal_usb_submit_rx_data_urbs(handle); } } else if (port == cardp->rx_data_ep) { - if ((atomic_read(&handle->rx_pending) < LOW_RX_PENDING) && + if ((atomic_read(&handle->rx_pending) < USB_LOW_RX_PENDING) && atomic_read(&cardp->rx_data_urb_pending) < MVUSB_RX_DATA_URB) woal_usb_submit_rx_data_urbs(handle); @@ -1327,6 +1349,7 @@ mlan_status moal_recv_packet(t_void *pmoal, pmlan_buffer pmbuf) t_u8 rx_info_flag = MFALSE; int j; struct ethhdr *ethh = NULL; + struct net_device *netdev = NULL; ENTER(); if (pmbuf) { @@ -1411,8 +1434,10 @@ mlan_status moal_recv_packet(t_void *pmoal, pmlan_buffer pmbuf) "\n", priv->netdev->name, MAC2STR(ethh->h_source)); - skb->dev = priv->netdev; - skb->protocol = eth_type_trans(skb, priv->netdev); + if (!netdev) + netdev = priv->netdev; + skb->dev = netdev; + skb->protocol = eth_type_trans(skb, netdev); skb->ip_summed = CHECKSUM_NONE; #if defined(USB) || defined(PCIE) @@ -1530,8 +1555,15 @@ mlan_status moal_recv_packet(t_void *pmoal, pmlan_buffer pmbuf) if (atomic_read(&handle->rx_pending) > MAX_RX_PENDING_THRHLD) netif_rx(skb); - else - netif_rx_ni(skb); + else { + if (handle->params.net_rx == MTRUE) { + local_bh_disable(); + netif_receive_skb(skb); + local_bh_enable(); + } else { + netif_rx_ni(skb); + } + } } if (priv->phandle->tp_acnt.on) { if (pmbuf && pmbuf->in_ts_sec) @@ -1546,52 +1578,56 @@ done: } #if defined(PCIE) || defined(SDIO) -void woal_request_busfreq_pmqos_add(t_u16 card_type) +void woal_request_busfreq_pmqos_add(t_void *handle) { + moal_handle *pmhandle = (moal_handle *)handle; #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 70) #ifdef IMX_SUPPORT - if (IS_PCIE(card_type)) { + if (IS_PCIE(pmhandle->card_type)) { request_bus_freq(BUS_FREQ_HIGH); } #endif #endif - + if (moal_extflg_isset(pmhandle, EXT_PMQOS)) { #if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 6, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) #ifdef IMX_SUPPORT - pm_qos_add_request(&woal_pm_qos_req, PM_QOS_CPU_DMA_LATENCY, 0); + pm_qos_add_request(&woal_pm_qos_req, PM_QOS_CPU_DMA_LATENCY, 0); #endif #endif #elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0) #ifdef IMX_SUPPORT - cpu_latency_qos_add_request(&woal_pm_qos_req, 0); + cpu_latency_qos_add_request(&woal_pm_qos_req, 0); #endif #endif - + } return; } -void woal_release_busfreq_pmqos_remove(t_u16 card_type) +void woal_release_busfreq_pmqos_remove(t_void *handle) { + moal_handle *pmhandle = (moal_handle *)handle; #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 70) #ifdef IMX_SUPPORT - if (IS_PCIE(card_type)) { + if (IS_PCIE(pmhandle->card_type)) { release_bus_freq(BUS_FREQ_HIGH); } #endif #endif + if (moal_extflg_isset(pmhandle, EXT_PMQOS)) { #if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 6, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) #ifdef IMX_SUPPORT - pm_qos_remove_request(&woal_pm_qos_req); + pm_qos_remove_request(&woal_pm_qos_req); #endif #endif #elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0) #ifdef IMX_SUPPORT - cpu_latency_qos_remove_request(&woal_pm_qos_req); + cpu_latency_qos_remove_request(&woal_pm_qos_req); #endif #endif + } return; } #endif /*defined(PCIE) || defined(SDIO)*/ @@ -1612,7 +1648,7 @@ static int woal_check_media_connected(t_void *pmoal) i++) { if (!pmpriv) continue; - if ((pmpriv->media_connected == MTRUE)) { + if (pmpriv->media_connected == MTRUE) { return MTRUE; } } @@ -1630,17 +1666,17 @@ static void moal_connection_status_check_pmqos(t_void *pmoal) { moal_handle *pmhandle = (moal_handle *)pmoal; if ((woal_check_media_connected(pmoal) == MTRUE)) { - if ((pmhandle->request_pm == MFALSE)) { + if (pmhandle->request_pm == MFALSE) { pmhandle->request_pm = MTRUE; #if defined(PCIE) || defined(SDIO) - woal_request_busfreq_pmqos_add(pmhandle->card_type); + woal_request_busfreq_pmqos_add(pmhandle); #endif } } else { if (pmhandle->request_pm == MTRUE) { pmhandle->request_pm = MFALSE; #if defined(PCIE) || defined(SDIO) - woal_release_busfreq_pmqos_remove(pmhandle->card_type); + woal_release_busfreq_pmqos_remove(pmhandle); #endif } } @@ -1725,8 +1761,14 @@ mlan_status moal_recv_event(t_void *pmoal, pmlan_event pmevent) #endif t_u8 radar_detected; + t_u8 auto_fw_dump = MFALSE; ENTER(); if (pmevent->event_id == MLAN_EVENT_ID_FW_DUMP_INFO) { + if (!handle->is_fw_dump_timer_set) { + PRINTM(MMSG, "FW trigger fw dump\n"); + handle->is_fw_dump_timer_set = MTRUE; + woal_mod_timer(&handle->fw_dump_timer, MOAL_TIMER_5S); + } woal_store_firmware_dump(pmoal, pmevent); handle->driver_status = MTRUE; ref_handle = (moal_handle *)handle->pref_mac; @@ -1740,12 +1782,10 @@ mlan_status moal_recv_event(t_void *pmoal, pmlan_event pmevent) PRINTM(MEVENT, "event id:0x%x\n", pmevent->event_id); #if defined(PCIE) if (pmevent->event_id == MLAN_EVENT_ID_SSU_DUMP_FILE) { - woal_store_ssu_dump(pmoal, pmevent); goto done; } #endif /* SSU_SUPPORT */ if (pmevent->event_id == MLAN_EVENT_ID_STORE_HOST_CMD_RESP) { - woal_save_host_cmdresp(handle, (mlan_cmdresp_event *)pmevent); goto done; } priv = woal_bss_index_to_priv(pmoal, pmevent->bss_index); @@ -2278,18 +2318,12 @@ mlan_status moal_recv_event(t_void *pmoal, pmlan_event pmevent) ref_handle = (moal_handle *)priv->phandle->pref_mac; if (ref_handle) ref_handle->driver_status = MTRUE; + if (drvdbg & MFW_D) + auto_fw_dump = MTRUE; + woal_moal_debug_info(priv, NULL, MFALSE); - woal_broadcast_event(priv, CUS_EVT_DRIVER_HANG, - strlen(CUS_EVT_DRIVER_HANG)); -#ifdef STA_CFG80211 -#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) - if (IS_STA_OR_UAP_CFG80211(cfg80211_wext)) - woal_cfg80211_vendor_event(priv, event_hang, - CUS_EVT_DRIVER_HANG, - strlen(CUS_EVT_DRIVER_HANG)); -#endif -#endif - woal_process_hang(priv->phandle); + if (!auto_fw_dump && !handle->fw_dump) + woal_process_hang(priv->phandle); wifi_status = 2; break; case MLAN_EVENT_ID_DRV_WIFI_STATUS: @@ -2337,6 +2371,18 @@ mlan_status moal_recv_event(t_void *pmoal, pmlan_event pmevent) #endif wake_up_interruptible( &priv->phandle->reassoc_thread.wait_q); + } else { +#if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 35) + if (priv->mrvl_rssi_low) { + cfg80211_cqm_rssi_notify( + priv->netdev, + NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, +#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) + 0, +#endif + GFP_KERNEL); + } +#endif } } #endif @@ -2359,14 +2405,10 @@ mlan_status moal_recv_event(t_void *pmoal, pmlan_event pmevent) !priv->phandle->cfg80211_suspend) { woal_inform_bss_from_scan_result(priv, NULL, MOAL_NO_WAIT); - cfg80211_sched_scan_results(priv->wdev->wiphy -#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) - , - priv->bg_scan_reqid -#endif - ); + PRINTM(MMSG, + "wlan: Report sched_scan result\n"); + woal_report_sched_scan_result(priv); priv->last_event = 0; - woal_bgscan_stop_event(priv); PRINTM(MEVENT, "Reporting Sched_Scan results\n"); } @@ -2988,6 +3030,11 @@ mlan_status moal_recv_event(t_void *pmoal, pmlan_event pmevent) PRINTM(MEVENT, "HostMlme %s: Receive deauth/disassociate\n", priv->netdev->name); + if (!priv->wdev->current_bss) { + PRINTM(MEVENT, + "HostMlme: Drop deauth/disassociate, current_bss = null\n"); + break; + } priv->cfg_disconnect = MTRUE; woal_mgmt_frame_register( priv, @@ -3003,11 +3050,6 @@ mlan_status moal_recv_event(t_void *pmoal, pmlan_event pmevent) priv->host_mlme = MFALSE; priv->auth_flag = 0; priv->auth_alg = 0xFFFF; - if (!priv->wdev->current_bss) { - PRINTM(MEVENT, - "HostMlme: Drop deauth/disassociate, we already disconnected\n"); - break; - } } #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) woal_rx_mgmt_pkt_event( diff --git a/mxm_wifiex/wlan_src/mlinux/moal_shim.h b/mxm_wifiex/wlan_src/mlinux/moal_shim.h index 3d768bd..79568f4 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_shim.h +++ b/mxm_wifiex/wlan_src/mlinux/moal_shim.h @@ -118,12 +118,14 @@ mlan_status moal_stop_timer(t_void *pmoal, t_void *ptimer); void moal_tp_accounting(t_void *pmoal, void *buf, t_u32 drop_point); void moal_tp_accounting_rx_param(t_void *pmoal, unsigned int type, unsigned int rsvd1); +void moal_amsdu_tp_accounting(t_void *pmoal, t_s32 amsdu_process_delay, + t_s32 amsdu_copy_delay); #if defined(PCIE) || defined(SDIO) /* pmqos busfreq add request handler*/ -void woal_request_busfreq_pmqos_add(t_u16 card_type); +void woal_request_busfreq_pmqos_add(t_void *pmhandle); /* pmqos busfreq remove handler*/ -void woal_release_busfreq_pmqos_remove(t_u16 card_type); +void woal_release_busfreq_pmqos_remove(t_void *pmhandle); #endif #endif /*_MOAL_H */ diff --git a/mxm_wifiex/wlan_src/mlinux/moal_sta_cfg80211.c b/mxm_wifiex/wlan_src/mlinux/moal_sta_cfg80211.c index 7f817f7..c115b75 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_sta_cfg80211.c +++ b/mxm_wifiex/wlan_src/mlinux/moal_sta_cfg80211.c @@ -40,7 +40,7 @@ static const u32 cfg80211_cipher_suites[] = { WLAN_CIPHER_SUITE_TKIP, WLAN_CIPHER_SUITE_CCMP, WLAN_CIPHER_SUITE_SMS4, WLAN_CIPHER_SUITE_AES_CMAC, #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) - WLAN_CIPHER_SUITE_BIP_GMAC_256, + WLAN_CIPHER_SUITE_BIP_GMAC_128, WLAN_CIPHER_SUITE_BIP_GMAC_256, #endif #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) WLAN_CIPHER_SUITE_GCMP, @@ -295,6 +295,10 @@ static struct cfg80211_ops woal_cfg80211_ops = { #if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) .set_default_mgmt_key = woal_cfg80211_set_default_mgmt_key, #endif +#if CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) + .set_default_beacon_key = woal_cfg80211_set_default_beacon_key, +#endif + #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) .set_rekey_data = woal_cfg80211_set_rekey_data, #endif @@ -810,6 +814,7 @@ static int woal_cfg80211_assoc_ies_cfg(moal_private *priv, t_u8 *ie, int ie_len, PRINTM(MIOCTL, "Enable WPS session\n"); woal_wps_cfg(priv, MTRUE); } + if (!memcmp(pvendor_ie->vend_hdr.oui, hs20_oui, sizeof(pvendor_ie->vend_hdr.oui)) && (pvendor_ie->vend_hdr.oui_type == hs20_oui[3])) { @@ -1983,6 +1988,9 @@ static int woal_cfg80211_authenticate(struct wiphy *wiphy, return -EINVAL; } + /** cancel pending scan */ + woal_cancel_scan(priv, MOAL_IOCTL_WAIT); + ssid_bssid = kzalloc(sizeof(mlan_ssid_bssid), GFP_ATOMIC); if (!ssid_bssid) { PRINTM(MERROR, "Fail to allocate ssid_bssid buffer\n"); @@ -2023,10 +2031,6 @@ static int woal_cfg80211_authenticate(struct wiphy *wiphy, LEAVE(); return -EBUSY; } - - /** cancel pending scan */ - woal_cancel_scan(priv, MOAL_IOCTL_WAIT); - #ifdef WIFI_DIRECT_SUPPORT if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT && (priv->wdev->iftype == NL80211_IFTYPE_STATION || @@ -2498,6 +2502,9 @@ static int woal_cfg80211_associate(struct wiphy *wiphy, struct net_device *dev, return -EBUSY; } + /** cancel pending scan */ + woal_cancel_scan(priv, MOAL_IOCTL_WAIT); + priv->cfg_connect = MTRUE; priv->assoc_status = 0; priv->auth_alg = 0xFFFF; @@ -3403,8 +3410,9 @@ static int compare(const void *lhs, const void *rhs) return 0; } + /** - * @brief This function update channel region config + * @brief This function get channel reg_rule flags * * @param buf Buffer containing channel region config * @param num_chan Length of buffer @@ -3412,6 +3420,78 @@ static int compare(const void *lhs, const void *rhs) * * @return N/A */ +t_u32 woal_get_chan_rule_flags(mlan_ds_custom_reg_domain *custom_reg, + t_u8 channel) +{ + t_u16 num_chan = 0; + t_u32 flags = 0; + int idx; + t_u16 chflags; + + num_chan = custom_reg->num_bg_chan; + num_chan += custom_reg->num_a_chan; + for (idx = 0; idx < num_chan; idx++) { + chflags = custom_reg->cfp_tbl[idx].dynamic.flags; + if (chflags & NXP_CHANNEL_DISABLED) + continue; + if (custom_reg->cfp_tbl[idx].channel == channel) { + if (chflags & NXP_CHANNEL_PASSIVE) + flags |= NL80211_RRF_NO_IR; + if (chflags & NXP_CHANNEL_DFS) + flags |= NL80211_RRF_DFS; + if (chflags & NXP_CHANNEL_NO_OFDM) + flags |= NL80211_RRF_NO_OFDM; + break; + } + } + return flags; +} + +/** + * @brief This function update the beaconng flags of channel + * + * @param custom_reg pointer to mlan_ds_custom_reg_domain + * + * @return pointer to ieee80211_regdomain + */ + +static void +woal_reg_apply_beaconing_flags(struct wiphy *wiphy, + mlan_ds_custom_reg_domain *custom_reg) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + int band, i; + t_u32 rule_flags = 0; + + for (band = 0; band < NUM_NL80211_BANDS; band++) { + sband = wiphy->bands[band]; + if (!sband) + continue; + + for (i = 0; i < sband->n_channels; i++) { + ch = &sband->channels[i]; + + if (ch->flags & + (IEEE80211_CHAN_DISABLED | IEEE80211_CHAN_RADAR)) + continue; + + rule_flags = woal_get_chan_rule_flags(custom_reg, + ch->hw_value); + + if (!(rule_flags & NL80211_RRF_NO_IR)) + ch->flags &= ~IEEE80211_CHAN_NO_IR; + } + } +} + +/** + * @brief This function create the custom regdomain + * + * @param custom_reg pointer to mlan_ds_custom_reg_domain + * + * @return pointer to ieee80211_regdomain + */ static struct ieee80211_regdomain * create_custom_regdomain(mlan_ds_custom_reg_domain *custom_reg) { @@ -3439,65 +3519,6 @@ create_custom_regdomain(mlan_ds_custom_reg_domain *custom_reg) if (!regd) { return NULL; } -#define NXP_CHANNEL_TMP_NOHT40 MBIT(15) - /* preprocess 2.4G 40MHz support */ - for (idx = 0; idx < num_chan; idx++) { - chan = custom_reg->cfp_tbl[idx].channel; - if (!chan) { - if (regd) - kfree(regd); - return NULL; - } - - if (chan > 14) - continue; - - chflags = custom_reg->cfp_tbl[idx].dynamic.flags; - - if (chflags & NXP_CHANNEL_DISABLED) - continue; - - /* duplicate a temp flag */ - if (chflags & NXP_CHANNEL_NOHT40) - chflags |= NXP_CHANNEL_TMP_NOHT40; - } - for (idx = 0; idx < num_chan; idx++) { - chan = custom_reg->cfp_tbl[idx].channel; - if (!chan) { - if (regd) - kfree(regd); - return NULL; - } - - if (chan > 14) - continue; - - chflags = custom_reg->cfp_tbl[idx].dynamic.flags; - - if (chflags & NXP_CHANNEL_DISABLED) - continue; - - /* 40 MHz band of one center channel will spread to upper and - * lower 2 channels */ - /* Mark HT40 flag for all channels of this 40 MHz band */ - if (!(chflags & NXP_CHANNEL_TMP_NOHT40)) { - if (idx >= 2) - custom_reg->cfp_tbl[idx - 2].dynamic.flags &= - ~NXP_CHANNEL_NOHT40; - if (idx >= 1) - custom_reg->cfp_tbl[idx - 1].dynamic.flags &= - ~NXP_CHANNEL_NOHT40; - if (idx < (num_chan - 1)) - custom_reg->cfp_tbl[idx + 1].dynamic.flags &= - ~NXP_CHANNEL_NOHT40; - if (idx < (num_chan - 2)) - custom_reg->cfp_tbl[idx + 2].dynamic.flags &= - ~NXP_CHANNEL_NOHT40; - } else { - custom_reg->cfp_tbl[idx].dynamic.flags &= - ~NXP_CHANNEL_TMP_NOHT40; - } - } for (idx = 0; idx < num_chan; idx++) { enum ieee80211_band band; @@ -3679,8 +3700,13 @@ static int woal_update_custom_regdomain(moal_private *priv, struct wiphy *wiphy) wiphy->regulatory_flags &= ~(REGULATORY_STRICT_REG | REGULATORY_CUSTOM_REG); wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED; - regulatory_set_wiphy_regd(wiphy, regd); + ret = regulatory_set_wiphy_regd(wiphy, regd); kfree(regd); + if (!ret) { + woal_sched_timeout(100); + woal_reg_apply_beaconing_flags( + wiphy, &misc->param.custom_reg_domain); + } } done: if (status != MLAN_STATUS_PENDING) @@ -3821,8 +3847,7 @@ woal_cfg80211_reg_notifier(struct wiphy *wiphy, break; } if (priv->wdev && priv->wdev->wiphy && - (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) && - (MTRUE != is_cfg80211_special_region_code(region))) { + (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)) { band = priv->phandle->band; priv->phandle->band = IEEE80211_BAND_2GHZ; woal_send_domain_info_cmd_fw(priv, MOAL_IOCTL_WAIT); @@ -4049,12 +4074,19 @@ static t_u8 woal_is_scan_result_expired(moal_private *priv) } #endif #endif - + if (!priv->media_connected) { + LEAVE(); + return MTRUE; + } if (MLAN_STATUS_SUCCESS != woal_get_scan_table(priv, MOAL_IOCTL_WAIT, &scan_resp)) { LEAVE(); return MTRUE; } + if (!scan_resp.num_in_scan_table) { + LEAVE(); + return MTRUE; + } woal_get_monotonic_time(&t); /** scan result expired value */ #define SCAN_RESULT_EXPIRTED 1 @@ -4232,8 +4264,7 @@ static int woal_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, if (scan_req->scan_chan_gap && priv->phandle->pref_mac) scan_req->scan_chan_gap |= GAP_FLAG_OPTIONAL; - if (priv->phandle->scan_request->n_channels <= 38 && - !woal_is_any_interface_active(priv->phandle)) { + if (priv->phandle->scan_request->n_channels <= 38) { if (scan_cfg.ext_scan == 3) scan_req->ext_scan_type = EXT_SCAN_ENHANCE; } @@ -5087,6 +5118,8 @@ static int woal_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, return 0; } + /** cancel pending scan */ + woal_cancel_scan(priv, MOAL_IOCTL_WAIT); priv->cfg_disconnect = MTRUE; if (woal_disconnect(priv, MOAL_IOCTL_WAIT_TIMEOUT, priv->cfg_bssid, reason_code) != MLAN_STATUS_SUCCESS) { @@ -6150,6 +6183,7 @@ int woal_cfg80211_sched_scan_start(struct wiphy *wiphy, struct net_device *dev, MAC2STR(priv->scan_cfg.random_mac)); if (MLAN_STATUS_SUCCESS == woal_request_bgscan(priv, MOAL_IOCTL_WAIT, &priv->scan_cfg)) { + PRINTM(MMSG, "wlan: sched scan start\n"); priv->sched_scanning = MTRUE; priv->bg_scan_start = MTRUE; priv->bg_scan_reported = MFALSE; @@ -6180,7 +6214,7 @@ int woal_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev { moal_private *priv = (moal_private *)woal_get_netdev_priv(dev); ENTER(); - PRINTM(MIOCTL, "sched scan stop\n"); + PRINTM(MMSG, "wlan: sched scan stop\n"); priv->sched_scanning = MFALSE; woal_stop_bg_scan(priv, MOAL_NO_WAIT); priv->bg_scan_start = MFALSE; @@ -6224,16 +6258,10 @@ int woal_cfg80211_resume(struct wiphy *wiphy) woal_inform_bss_from_scan_result( handle->priv[i], NULL, MOAL_IOCTL_WAIT); - cfg80211_sched_scan_results( - handle->priv[i]->wdev->wiphy -#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) - , - 0 -#endif - ); - woal_bgscan_stop_event(handle->priv[i]); + woal_report_sched_scan_result( + handle->priv[i]); handle->priv[i]->last_event = 0; - PRINTM(MIOCTL, + PRINTM(MCMND, "Report sched scan result in cfg80211 resume\n"); } if (!moal_extflg_isset(handle, EXT_HW_TEST) && @@ -8075,7 +8103,6 @@ static int woal_cfg80211_change_station(struct wiphy *wiphy, int ret = 0; ENTER(); - /**do nothing*/ LEAVE(); @@ -9142,6 +9169,10 @@ static mlan_status woal_cfg80211_init_wiphy(moal_private *priv, woal_cfg80211_setup_ht_cap( &wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, hw_dev_cap, cfg_11n->param.supported_mcs_set); +#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) + woal_cfg80211_setup_vht_cap( + priv, &wiphy->bands[IEEE80211_BAND_2GHZ]->vht_cap); +#endif #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) woal_cfg80211_setup_he_cap(priv, wiphy->bands[IEEE80211_BAND_2GHZ]); @@ -9462,19 +9493,22 @@ mlan_status woal_register_cfg80211(moal_private *priv) if (!moal_extflg_isset(priv->phandle, EXT_HOST_MLME)) #endif wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME; + #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) + if (priv->phandle->params.sched_scan) { #if CFG80211_VERSION_CODE < KERNEL_VERSION(4, 12, 0) - wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; + wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; #else - wiphy->max_sched_scan_reqs = 1; + wiphy->max_sched_scan_reqs = 1; #endif - wiphy->max_sched_scan_ssids = MRVDRV_MAX_SSID_LIST_LENGTH; - wiphy->max_sched_scan_ie_len = MAX_IE_SIZE; - wiphy->max_match_sets = MRVDRV_MAX_SSID_LIST_LENGTH; + wiphy->max_sched_scan_ssids = MRVDRV_MAX_SSID_LIST_LENGTH; + wiphy->max_sched_scan_ie_len = MAX_IE_SIZE; + wiphy->max_match_sets = MRVDRV_MAX_SSID_LIST_LENGTH; #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) - wiphy->max_sched_scan_plans = 3; - wiphy->max_sched_scan_plan_iterations = 100; + wiphy->max_sched_scan_plans = 3; + wiphy->max_sched_scan_plan_iterations = 100; #endif + } #endif #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER; @@ -9494,7 +9528,6 @@ mlan_status woal_register_cfg80211(moal_private *priv) if (moal_extflg_isset(priv->phandle, EXT_HOST_MLME)) wiphy->features |= NL80211_FEATURE_SAE; #endif - #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) wiphy->features |= NL80211_FEATURE_NEED_OBSS_SCAN; #endif @@ -9518,6 +9551,13 @@ mlan_status woal_register_cfg80211(moal_private *priv) wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR; #endif + +#if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA); + wiphy_ext_feature_set(wiphy, + NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED); +#endif + #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL); #endif @@ -9525,6 +9565,16 @@ mlan_status woal_register_cfg80211(moal_private *priv) if (moal_extflg_isset(priv->phandle, EXT_HOST_MLME)) wiphy->features |= NL80211_FEATURE_SK_TX_STATUS; #endif + +#if CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) + if (fw_info.fw_beacon_prot) { + wiphy_ext_feature_set(wiphy, + NL80211_EXT_FEATURE_BEACON_PROTECTION); + wiphy_ext_feature_set( + wiphy, NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT); + } +#endif + /* Set struct moal_handle pointer in wiphy_priv */ wdev_priv = wiphy_priv(wiphy); *(unsigned long *)wdev_priv = (unsigned long)priv->phandle; diff --git a/mxm_wifiex/wlan_src/mlinux/moal_uap.c b/mxm_wifiex/wlan_src/mlinux/moal_uap.c index b925c36..0f890ef 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_uap.c +++ b/mxm_wifiex/wlan_src/mlinux/moal_uap.c @@ -4224,7 +4224,8 @@ void woal_uap_set_multicast_list(struct net_device *dev) * @return 0 --success, otherwise fail */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) -int woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req, void __user *data, int cmd) +int woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req, + void __user *data, int cmd) #else int woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd) #endif diff --git a/mxm_wifiex/wlan_src/mlinux/moal_uap.h b/mxm_wifiex/wlan_src/mlinux/moal_uap.h index 461d275..07052db 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_uap.h +++ b/mxm_wifiex/wlan_src/mlinux/moal_uap.h @@ -531,11 +531,14 @@ typedef struct _domain_info_param { int woal_set_get_uap_power_mode(moal_private *priv, t_u32 action, mlan_ds_ps_mgmt *ps_mgmt); void woal_uap_set_multicast_list(struct net_device *dev); + #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) -int woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req, void __user *data, int cmd); +int woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req, + void __user *data, int cmd); #else int woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd); #endif + int woal_uap_bss_ctrl(moal_private *priv, t_u8 wait_option, int data); #ifdef UAP_CFG80211 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) @@ -567,6 +570,7 @@ mlan_status woal_set_get_sys_config(moal_private *priv, t_u16 action, mlan_status woal_set_get_ap_wmm_para(moal_private *priv, t_u16 action, wmm_parameter_t *ap_wmm_para); int woal_uap_set_ap_cfg(moal_private *priv, t_u8 *data, int len); + int woal_uap_set_11ac_status(moal_private *priv, t_u8 action, t_u8 vht20_40, IEEEtypes_VHTCap_t *vhtcap_ie); int woal_11ax_cfg(moal_private *priv, t_u8 action, mlan_ds_11ax_he_cfg *he_cfg); diff --git a/mxm_wifiex/wlan_src/mlinux/moal_uap_cfg80211.c b/mxm_wifiex/wlan_src/mlinux/moal_uap_cfg80211.c index 4f2290f..0a61a12 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_uap_cfg80211.c +++ b/mxm_wifiex/wlan_src/mlinux/moal_uap_cfg80211.c @@ -1377,6 +1377,19 @@ static int woal_cfg80211_beacon_config(moal_private *priv, ret = -EFAULT; goto done; } + + /** Set wacp_mode for uAP/P2P-GO */ + if (priv->phandle->params.wacp_mode) { + PRINTM(MIOCTL, "wacp_mode: %d\n", + priv->phandle->params.wacp_mode); + if (MLAN_STATUS_SUCCESS != + woal_set_wacp_mode(priv, MOAL_IOCTL_WAIT)) { + PRINTM(MERROR, "Set wacp_mode failed\n"); + ret = -EFAULT; + goto done; + } + } + #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) woal_enable_dfs_support(priv, &priv->chan); #endif @@ -1846,7 +1859,7 @@ int woal_cfg80211_del_virt_if(struct wiphy *wiphy, struct net_device *dev) priv->phandle->priv_num--; if (dev->reg_state == NETREG_REGISTERED) #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) - cfg80211_unregister_netdevice(dev); + cfg80211_unregister_netdevice(ndev); #else unregister_netdevice(dev); #endif @@ -1889,7 +1902,7 @@ void woal_remove_virtual_interface(moal_handle *handle) if (priv->netdev->reg_state == NETREG_REGISTERED) #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) - cfg80211_unregister_netdevice(priv->netdev); + cfg80211_unregister_netdevice(ndev); #else unregister_netdevice(priv->netdev); #endif @@ -2104,6 +2117,7 @@ int woal_cfg80211_del_virtual_intf(struct wiphy *wiphy, #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) struct net_device *dev = wdev->netdev; #endif + ENTER(); PRINTM(MIOCTL, "del virtual intf %s\n", dev->name); diff --git a/mxm_wifiex/wlan_src/mlinux/moal_uap_priv.c b/mxm_wifiex/wlan_src/mlinux/moal_uap_priv.c index e2da631..b28e0db 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_uap_priv.c +++ b/mxm_wifiex/wlan_src/mlinux/moal_uap_priv.c @@ -111,20 +111,20 @@ int woal_uap_do_priv_ioctl(struct net_device *dev, struct ifreq *req, int cmd) break; } break; -#ifdef WIFI_DIRECT_SUPPORT -#if defined(STA_SUPPORT) && defined(UAP_SUPPORT) case WOAL_UAP_SETONEINT_GETONEINT: switch (wrq->u.data.flags) { +#ifdef WIFI_DIRECT_SUPPORT +#if defined(STA_SUPPORT) && defined(UAP_SUPPORT) case WOAL_UAP_SET_GET_BSS_ROLE: ret = woal_set_get_bss_role(priv, wrq); break; +#endif +#endif default: ret = -EINVAL; break; } break; -#endif -#endif case WOAL_UAP_HOST_CMD: ret = woal_host_command(priv, wrq); break; diff --git a/mxm_wifiex/wlan_src/mlinux/moal_uap_priv.h b/mxm_wifiex/wlan_src/mlinux/moal_uap_priv.h index ef1dfe9..dcb391a 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_uap_priv.h +++ b/mxm_wifiex/wlan_src/mlinux/moal_uap_priv.h @@ -56,10 +56,10 @@ Change log: /** Private command ID to get extended version */ #define WOAL_UAP_VEREXT 2 -#ifdef WIFI_DIRECT_SUPPORT -#if defined(STA_SUPPORT) && defined(UAP_SUPPORT) /** Private command ID to set one int/get one int */ #define WOAL_UAP_SETONEINT_GETONEINT (WOAL_UAP_IOCTL + 5) +#ifdef WIFI_DIRECT_SUPPORT +#if defined(STA_SUPPORT) && defined(UAP_SUPPORT) /** Private command ID for set/get BSS role */ #define WOAL_UAP_SET_GET_BSS_ROLE 1 #endif diff --git a/mxm_wifiex/wlan_src/mlinux/moal_uap_wext.c b/mxm_wifiex/wlan_src/mlinux/moal_uap_wext.c index df0525e..ac3b136 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_uap_wext.c +++ b/mxm_wifiex/wlan_src/mlinux/moal_uap_wext.c @@ -75,14 +75,15 @@ static const struct iw_priv_args woal_uap_priv_args[] = { "version"}, {WOAL_UAP_VEREXT, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_CHAR | 128, "verext"}, -#ifdef WIFI_DIRECT_SUPPORT -#if defined(STA_SUPPORT) && defined(UAP_SUPPORT) {WOAL_UAP_SETONEINT_GETONEINT, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1, ""}, +#ifdef WIFI_DIRECT_SUPPORT +#if defined(STA_SUPPORT) && defined(UAP_SUPPORT) {WOAL_UAP_SET_GET_BSS_ROLE, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1, "bssrole"}, #endif #endif + {WOAL_UAP_SET_GET_256_CHAR, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_CHAR | 256, ""}, {WOAL_WL_FW_RELOAD, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_CHAR | 256, diff --git a/mxm_wifiex/wlan_src/mlinux/moal_usb.c b/mxm_wifiex/wlan_src/mlinux/moal_usb.c index 2544c8a..56b602c 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_usb.c +++ b/mxm_wifiex/wlan_src/mlinux/moal_usb.c @@ -266,13 +266,13 @@ static void woal_usb_receive(struct urb *urb) if (status == MLAN_STATUS_PENDING) { queue_work(handle->workqueue, &handle->main_work); /* urb for data_ep is re-submitted now, unless we reach - * HIGH_RX_PENDING */ + * USB_HIGH_RX_PENDING */ /* urb for cmd_ep will be re-submitted in callback * moal_recv_complete */ if (cardp->rx_cmd_ep == context->ep) goto rx_exit; else if (atomic_read(&handle->rx_pending) >= - HIGH_RX_PENDING) { + USB_HIGH_RX_PENDING) { context->pmbuf = NULL; goto rx_exit; } @@ -1919,6 +1919,8 @@ static void woal_usb_dump_fw_info(moal_handle *phandle) if (status != MLAN_STATUS_PENDING) kfree(req); + phandle->is_fw_dump_timer_set = MTRUE; + woal_mod_timer(&phandle->fw_dump_timer, MOAL_TIMER_5S); done: LEAVE(); diff --git a/mxm_wifiex/wlan_src/mlinux/moal_wext.c b/mxm_wifiex/wlan_src/mlinux/moal_wext.c index a99ad47..f808ab0 100644 --- a/mxm_wifiex/wlan_src/mlinux/moal_wext.c +++ b/mxm_wifiex/wlan_src/mlinux/moal_wext.c @@ -197,6 +197,8 @@ static const struct iw_priv_args woal_private_args[] = { "sysclock"}, {WOAL_HOST_CMD, IW_PRIV_TYPE_BYTE | 2047, IW_PRIV_TYPE_BYTE | 2047, "hostcmd"}, + {WOAL_ARP_FILTER, IW_PRIV_TYPE_BYTE | 2047, IW_PRIV_TYPE_BYTE | 2047, + "arpfilter"}, {WOAL_SET_INTS_GET_CHARS, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_BYTE | 256, ""}, {WOAL_READ_EEPROM, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_BYTE | 256,