diff options
author | Marc Yang <yangyang@marvell.com> | 2013-05-10 17:48:52 -0700 |
---|---|---|
committer | Riham Haidar <rhaidar@nvidia.com> | 2013-06-12 18:52:10 -0700 |
commit | 2b28a245f5f773ec11de585aeaa641f35696f818 (patch) | |
tree | a59aee9a84d34171cd24f828d6a2dd24ee08277e /drivers | |
parent | 339d494c5790e7a96d00e94e7e6c68716644c18a (diff) |
net: wireless: sd8797: Update SD8797 WLAN driver
Signed-off-by: Marc Yang <yangyang@marvell.com>
Bug 1279040
Change-Id: Ifee06a06feb304b039f62f2a3730dc4f04f1e7b5
Signed-off-by: Nagarjuna Kristam <nkristam@nvidia.com>
Reviewed-on: http://git-master/r/235721
Reviewed-by: Mohan Thadikamalla <mohant@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'drivers')
59 files changed, 10496 insertions, 4064 deletions
diff --git a/drivers/net/wireless/sd8797/Makefile b/drivers/net/wireless/sd8797/Makefile index 4efa18a5b58e..394d5e542266 100644 --- a/drivers/net/wireless/sd8797/Makefile +++ b/drivers/net/wireless/sd8797/Makefile @@ -18,32 +18,46 @@ # ARE EXPRESSLY DISCLAIMED. The License provides additional details about # this warranty disclaimer. -# Enable CFG80211 for STA -ifeq ($(CONFIG_CFG80211),y) -CONFIG_STA_CFG80211=y -else -ifeq ($(CONFIG_CFG80211),m) -CONFIG_STA_CFG80211=y -else -CONFIG_STA_CFG80211=n -endif -endif +CC= $(CROSS_COMPILE)gcc +LD= $(CROSS_COMPILE)ld +BACKUP= /root/backup +YMD= `date +%Y%m%d%H%M` -# Enable CFG80211 for uAP -ifeq ($(CONFIG_CFG80211),y) -CONFIG_UAP_CFG80211=y -else -ifeq ($(CONFIG_CFG80211),m) -CONFIG_UAP_CFG80211=y -else -CONFIG_UAP_CFG80211=n -endif -endif +############################################################################# +# Configuration Options +############################################################################# + +# Re-association in driver +CONFIG_REASSOCIATION=y + +# Manufacturing firmware support +CONFIG_MFG_CMD_SUPPORT=y + +# Big-endian platform +CONFIG_BIG_ENDIAN=n + +# DFS testing support +CONFIG_DFS_TESTING_SUPPORT=y + +# Use static link for app build +export CONFIG_STATIC_LINK=y + +MODEXT = ko ############################################################################# # Compiler Flags ############################################################################# +EXTRA_CFLAGS += -I$(KERNELDIR)/include + +EXTRA_CFLAGS += -Idrivers/net/wireless/sd8797/mlan +EXTRA_CFLAGS += -DLINUX +EXTRA_CFLAGS += -DFPNUM='"69"' +EXTRA_CFLAGS += -DDEBUG_LEVEL1 +EXTRA_CFLAGS += -DPROC_DEBUG +EXTRA_CFLAGS += -DSDIO_MULTI_PORT_TX_AGGR +EXTRA_CFLAGS += -DSDIO_MULTI_PORT_RX_AGGR + ifeq ($(CONFIG_DEBUG),1) EXTRA_CFLAGS += -DDEBUG_LEVEL1 endif @@ -54,50 +68,26 @@ ifeq ($(CONFIG_DEBUG),2) DBG= -dbg endif -EXTRA_CFLAGS += -Idrivers/net/wireless/sd8797/mlan -EXTRA_CFLAGS += -DLINUX -EXTRA_CFLAGS += -DFPNUM='"69"' -EXTRA_CFLAGS += -DDEBUG_LEVEL1 -EXTRA_CFLAGS += -DPROC_DEBUG -EXTRA_CFLAGS += -DSDIO_MULTI_PORT_TX_AGGR -EXTRA_CFLAGS += -DSDIO_MULTI_PORT_RX_AGGR -EXTRA_CFLAGS += -DSDIO_SUSPEND_RESUME -EXTRA_CFLAGS += -DMMC_PM_KEEP_POWER -EXTRA_CFLAGS += -DDFS_TESTING_SUPPORT -EXTRA_CFLAGS += -DMFG_CMD_SUPPORT - ifeq ($(CONFIG_64BIT), y) EXTRA_CFLAGS += -DMLAN_64BIT endif ifeq ($(CONFIG_STA_SUPPORT),y) EXTRA_CFLAGS += -DSTA_SUPPORT +ifeq ($(CONFIG_REASSOCIATION),y) EXTRA_CFLAGS += -DREASSOCIATION -ifeq ($(CONFIG_STA_WEXT),y) - EXTRA_CFLAGS += -DSTA_WEXT -endif -ifeq ($(CONFIG_STA_CFG80211),y) - EXTRA_CFLAGS += -DSTA_CFG80211 endif else CONFIG_WIFI_DIRECT_SUPPORT=n CONFIG_WIFI_DISPLAY_SUPPORT=n -CONFIG_STA_WEXT=n CONFIG_STA_CFG80211=n endif ifeq ($(CONFIG_UAP_SUPPORT),y) EXTRA_CFLAGS += -DUAP_SUPPORT -ifeq ($(CONFIG_UAP_WEXT),y) - EXTRA_CFLAGS += -DUAP_WEXT -endif -ifeq ($(CONFIG_UAP_CFG80211),y) - EXTRA_CFLAGS += -DUAP_CFG80211 -endif else CONFIG_WIFI_DIRECT_SUPPORT=n CONFIG_WIFI_DISPLAY_SUPPORT=n -CONFIG_UAP_WEXT=n CONFIG_UAP_CFG80211=n endif @@ -108,14 +98,81 @@ ifeq ($(CONFIG_WIFI_DISPLAY_SUPPORT),y) EXTRA_CFLAGS += -DWIFI_DISPLAY_SUPPORT endif +ifeq ($(CONFIG_MFG_CMD_SUPPORT),y) + EXTRA_CFLAGS += -DMFG_CMD_SUPPORT +endif + ifeq ($(CONFIG_BIG_ENDIAN),y) EXTRA_CFLAGS += -DBIG_ENDIAN_SUPPORT endif +ifeq ($(CONFIG_DFS_TESTING_SUPPORT),y) + EXTRA_CFLAGS += -DDFS_TESTING_SUPPORT +endif + ############################################################################# # Make Targets ############################################################################# +# Enable CFG80211 for STA +ifeq ($(CONFIG_CFG80211),y) + CONFIG_STA_CFG80211=y +else +ifeq ($(CONFIG_CFG80211),m) + CONFIG_STA_CFG80211=y +else + CONFIG_STA_CFG80211=n +endif +endif + +# Enable CFG80211 for uAP +ifeq ($(CONFIG_CFG80211),y) + CONFIG_UAP_CFG80211=y +else +ifeq ($(CONFIG_CFG80211),m) + CONFIG_UAP_CFG80211=y +else + CONFIG_UAP_CFG80211=n +endif +endif + +ifneq ($(CONFIG_STA_SUPPORT),y) + CONFIG_WIFI_DIRECT_SUPPORT=n + CONFIG_WIFI_DISPLAY_SUPPORT=n + CONFIG_STA_CFG80211=n +endif + +ifneq ($(CONFIG_UAP_SUPPORT),y) + CONFIG_WIFI_DIRECT_SUPPORT=n + CONFIG_WIFI_DISPLAY_SUPPORT=n + CONFIG_UAP_CFG80211=n +endif + +ifeq ($(CONFIG_STA_SUPPORT),y) +ifeq ($(CONFIG_STA_CFG80211),y) + EXTRA_CFLAGS += -DSTA_CFG80211 +endif +endif +ifeq ($(CONFIG_UAP_SUPPORT),y) +ifeq ($(CONFIG_UAP_CFG80211),y) + EXTRA_CFLAGS += -DUAP_CFG80211 +endif +endif + +print: +ifeq ($(CONFIG_STA_SUPPORT),y) +ifeq ($(CONFIG_STA_CFG80211),n) + @echo "Can not build STA without WEXT or CFG80211" + exit 2 +endif +endif +ifeq ($(CONFIG_UAP_SUPPORT),y) +ifeq ($(CONFIG_UAP_CFG80211),n) + @echo "Can not build UAP without WEXT or CFG80211" + exit 2 +endif +endif + MOALOBJS = mlinux/moal_main.o \ mlinux/moal_ioctl.o \ mlinux/moal_shim.o \ @@ -176,11 +233,11 @@ MOALOBJS += mlinux/moal_proc.o MOALOBJS += mlinux/moal_debug.o endif -obj-m := mlan.o -mlan-objs := $(MLANOBJS) +obj-m := sd8797mlan.o +sd8797mlan-objs := $(MLANOBJS) MOALOBJS += mlinux/moal_sdio_mmc.o -obj-m += sd8xxx.o -sd8xxx-objs := $(MOALOBJS) +obj-m += sd8797.o +sd8797-objs := $(MOALOBJS) ############################################################### # End of file diff --git a/drivers/net/wireless/sd8797/mlan/mlan_11d.c b/drivers/net/wireless/sd8797/mlan/mlan_11d.c index 837349b1a34b..6c5672569aae 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_11d.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_11d.c @@ -34,6 +34,7 @@ Change log: Local Variables ********************************************************/ +#ifdef STA_SUPPORT /** Region code mapping */ typedef struct _region_code_mapping { @@ -59,7 +60,6 @@ static region_code_mapping_t region_code_mapping[] = { {"JP ", 0xFF}, /* Japan special */ }; -#ifdef STA_SUPPORT /** Default Tx power */ #define TX_PWR_DEFAULT 10 @@ -133,38 +133,6 @@ channels for 11J JP 10M channel gap */ /******************************************************** Local Functions ********************************************************/ - -/** - * @brief This function converts region string to integer code - * - * @param pmadapter A pointer to mlan_adapter structure - * @param region Region string - * @param code [output] Region code - * - * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE - */ -static mlan_status -wlan_11d_region_2_code(pmlan_adapter pmadapter, t_u8 * region, OUT t_u8 * code) -{ - t_u8 i; - t_u8 size = sizeof(region_code_mapping) / sizeof(region_code_mapping_t); - - ENTER(); - - /* Look for code in mapping table */ - for (i = 0; i < size; i++) { - if (!memcmp(pmadapter, region_code_mapping[i].region, - region, COUNTRY_CODE_LEN)) { - *code = region_code_mapping[i].code; - LEAVE(); - return MLAN_STATUS_SUCCESS; - } - } - - LEAVE(); - return MLAN_STATUS_FAILURE; -} - #ifdef STA_SUPPORT /** * @brief This function converts integer code to region string @@ -1434,22 +1402,14 @@ wlan_11d_cfg_domain_info(IN pmlan_adapter pmadapter, mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; mlan_ds_11d_domain_info *domain_info = MNULL; mlan_ds_11d_cfg *cfg_11d = MNULL; - t_u8 region_code = 0; + t_u8 cfp_bg = 0, cfp_a = 0; ENTER(); cfg_11d = (mlan_ds_11d_cfg *) pioctl_req->pbuf; domain_info = &cfg_11d->param.domain_info; - - /* Update region code and table based on country code */ - if (wlan_11d_region_2_code(pmadapter, domain_info->country_code, - ®ion_code) == MLAN_STATUS_SUCCESS) { - pmadapter->region_code = region_code; - ret = wlan_set_regiontable(pmpriv, region_code, pmadapter->fw_bands); - if (ret != MLAN_STATUS_SUCCESS) - goto done; - } - + memcpy(pmadapter, pmadapter->country_code, domain_info->country_code, + COUNTRY_CODE_LEN); wlan_11d_set_domain_info(pmpriv, domain_info->band, domain_info->country_code, domain_info->no_of_sub_band, @@ -1459,6 +1419,26 @@ wlan_11d_cfg_domain_info(IN pmlan_adapter pmadapter, if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; + /* Update region code and table based on country code */ + if (wlan_misc_country_2_cfp_table_code(pmadapter, + domain_info->country_code, &cfp_bg, + &cfp_a)) { + PRINTM(MIOCTL, "Country code %c%c not found!\n", + domain_info->country_code[0], domain_info->country_code[1]); + goto done; + } + pmadapter->cfp_code_bg = cfp_bg; + pmadapter->cfp_code_a = cfp_a; + if (cfp_bg && cfp_a && (cfp_bg == cfp_a)) + pmadapter->region_code = cfp_a; + else + pmadapter->region_code = 0; + if (wlan_set_regiontable(pmpriv, pmadapter->region_code, + pmadapter->config_bands | pmadapter-> + adhoc_start_band)) { + PRINTM(MIOCTL, "Fail to set regiontabl\n"); + goto done; + } done: LEAVE(); return ret; @@ -1486,21 +1466,35 @@ wlan_11d_handle_uap_domain_info(mlan_private * pmpriv, mlan_adapter *pmadapter = pmpriv->adapter; MrvlIEtypes_DomainParamSet_t *pdomain_tlv; t_u8 num_sub_band = 0; - t_u8 region_code = 0; + t_u8 cfp_bg = 0, cfp_a = 0; ENTER(); pdomain_tlv = (MrvlIEtypes_DomainParamSet_t *) domain_tlv; // update region code & table based on country string - if (wlan_11d_region_2_code(pmadapter, pdomain_tlv->country_code, - ®ion_code) == MLAN_STATUS_SUCCESS) { - pmadapter->region_code = region_code; - ret = wlan_set_regiontable(pmpriv, region_code, pmadapter->fw_bands); + if (wlan_misc_country_2_cfp_table_code(pmadapter, + pdomain_tlv->country_code, &cfp_bg, + &cfp_a) == MLAN_STATUS_SUCCESS) { + pmadapter->cfp_code_bg = cfp_bg; + pmadapter->cfp_code_a = cfp_a; + if (cfp_bg && cfp_a && (cfp_bg == cfp_a)) + pmadapter->region_code = cfp_a; + else + pmadapter->region_code = 0; + if (wlan_set_regiontable(pmpriv, pmadapter->region_code, + pmadapter->config_bands | pmadapter-> + adhoc_start_band)) { + ret = MLAN_STATUS_FAILURE; + goto done; + } } - num_sub_band = ((pdomain_tlv->header.len - COUNTRY_CODE_LEN) / - sizeof(IEEEtypes_SubbandSet_t)); + memcpy(pmadapter, pmadapter->country_code, pdomain_tlv->country_code, + COUNTRY_CODE_LEN); + num_sub_band = + ((pdomain_tlv->header.len - + COUNTRY_CODE_LEN) / sizeof(IEEEtypes_SubbandSet_t)); // TODO: don't just clobber pmadapter->domain_reg. // Add some checking or merging between STA & UAP domain_info @@ -1509,6 +1503,7 @@ wlan_11d_handle_uap_domain_info(mlan_private * pmpriv, num_sub_band, pdomain_tlv->sub_band); ret = wlan_11d_send_domain_info(pmpriv, pioctl_buf); + done: LEAVE(); return ret; } diff --git a/drivers/net/wireless/sd8797/mlan/mlan_11n.c b/drivers/net/wireless/sd8797/mlan/mlan_11n.c index 9ff5da752a41..4114ff551588 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_11n.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_11n.c @@ -61,7 +61,6 @@ wlan_11n_ioctl_max_tx_buf_size(IN pmlan_adapter pmadapter, mlan_ds_11n_cfg *cfg = MNULL; ENTER(); - cfg = (mlan_ds_11n_cfg *) pioctl_req->pbuf; cfg->param.tx_buf_size = (t_u32) pmadapter->max_tx_buf_size; pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE; @@ -405,6 +404,45 @@ wlan_11n_ioctl_addba_param(IN pmlan_adapter pmadapter, return ret; } +/** + * @brief This function send delba to specific tid + * + * @param priv A pointer to mlan_priv + * @param tid tid + * @return N/A + */ +void +wlan_11n_delba(mlan_private * priv, int tid) +{ + RxReorderTbl *rx_reor_tbl_ptr; + + ENTER(); + + if (! + (rx_reor_tbl_ptr = + (RxReorderTbl *) util_peek_list(priv->adapter->pmoal_handle, + &priv->rx_reorder_tbl_ptr, + priv->adapter->callbacks. + moal_spin_lock, + priv->adapter->callbacks. + moal_spin_unlock))) { + LEAVE(); + return; + } + + while (rx_reor_tbl_ptr != (RxReorderTbl *) & priv->rx_reorder_tbl_ptr) { + if (rx_reor_tbl_ptr->tid == tid) { + PRINTM(MIOCTL, "Send delba to tid=%d, " MACSTR "\n", tid, + MAC2STR(rx_reor_tbl_ptr->ta)); + wlan_send_delba(priv, MNULL, tid, rx_reor_tbl_ptr->ta, 0); + } + rx_reor_tbl_ptr = rx_reor_tbl_ptr->pnext; + } + + LEAVE(); + return; +} + /** * @brief Set/get addba reject set * @@ -432,13 +470,14 @@ wlan_11n_ioctl_addba_reject(IN pmlan_adapter pmadapter, MAX_NUM_TID); } else { if (pmpriv->media_connected == MTRUE) { - PRINTM(MERROR, "Can not set aggr priority table in connected" - " state\n"); - pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID; - LEAVE(); - return MLAN_STATUS_FAILURE; + for (i = 0; i < MAX_NUM_TID; i++) { + if (cfg->param.addba_reject[i] == ADDBA_RSP_STATUS_REJECT) { + PRINTM(MIOCTL, "Receive addba reject: tid=%d\n", i); + wlan_11n_delba(pmpriv, i); + } + } + wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DEFER_HANDLING, MNULL); } - for (i = 0; i < MAX_NUM_TID; i++) { /* For AMPDU */ if (cfg->param.addba_reject[i] > ADDBA_RSP_STATUS_REJECT) { @@ -605,10 +644,8 @@ wlan_11n_ioctl_delba(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) tid = cfg->param.del_ba.tid; peer_address = cfg->param.del_ba.peer_mac_addr; - PRINTM(MINFO, - "DelBA: direction %d, TID %d, peer address %02x:%02x:%02x:%02x:%02x:%02x\n", - cfg->param.del_ba.direction, tid, peer_address[0], peer_address[1], - peer_address[2], peer_address[3], peer_address[4], peer_address[5]); + PRINTM(MINFO, "DelBA: direction %d, TID %d, peer address " MACSTR "\n", + cfg->param.del_ba.direction, tid, MAC2STR(peer_address)); if (cfg->param.del_ba.direction & DELBA_RX) { rx_reor_tbl_ptr = @@ -730,6 +767,51 @@ wlan_11n_ioctl_rejectaddbareq(IN pmlan_adapter pmadapter, return ret; } +/** + * @brief This function will send DELBA to entries in the priv's + * Tx BA stream table + * + * @param priv A pointer to mlan_private + * @param tid TID + * + * @return N/A + */ +static void +wlan_send_delba_txbastream_tbl(pmlan_private priv, t_u8 tid) +{ + pmlan_adapter pmadapter = priv->adapter; + TxBAStreamTbl *tx_ba_stream_tbl_ptr; + + ENTER(); + + if (! + (tx_ba_stream_tbl_ptr = + (TxBAStreamTbl *) util_peek_list(pmadapter->pmoal_handle, + &priv->tx_ba_stream_tbl_ptr, + pmadapter->callbacks.moal_spin_lock, + pmadapter->callbacks. + moal_spin_unlock))) { + LEAVE(); + return; + } + + while (tx_ba_stream_tbl_ptr != + (TxBAStreamTbl *) & priv->tx_ba_stream_tbl_ptr) { + if (tx_ba_stream_tbl_ptr->ba_status == BA_STREAM_SETUP_COMPLETE) { + if (tid == tx_ba_stream_tbl_ptr->tid) { + PRINTM(MIOCTL, "Tx:Send delba to tid=%d, " MACSTR "\n", tid, + MAC2STR(tx_ba_stream_tbl_ptr->ra)); + wlan_send_delba(priv, MNULL, tx_ba_stream_tbl_ptr->tid, + tx_ba_stream_tbl_ptr->ra, 1); + } + } + tx_ba_stream_tbl_ptr = tx_ba_stream_tbl_ptr->pnext; + } + + LEAVE(); + return; +} + /** * @brief Set/get aggr_prio_tbl * @@ -759,11 +841,14 @@ wlan_11n_ioctl_aggr_prio_tbl(IN pmlan_adapter pmadapter, } } else { if (pmpriv->media_connected == MTRUE) { - PRINTM(MERROR, "Can not set aggr priority table in connected" - " state\n"); - pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID; - LEAVE(); - return MLAN_STATUS_FAILURE; + for (i = 0; i < MAX_NUM_TID; i++) { + if (cfg->param.aggr_prio_tbl.ampdu[i] == BA_STREAM_NOT_ALLOWED) { + PRINTM(MIOCTL, + "Receive aggrpriotbl: BA not allowed tid=%d\n", i); + wlan_send_delba_txbastream_tbl(pmpriv, i); + } + } + wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DEFER_HANDLING, MNULL); } for (i = 0; i < MAX_NUM_TID; i++) { @@ -1233,11 +1318,8 @@ wlan_ret_11n_addba_req(mlan_private * priv, HostCmd_DS_COMMAND * resp) padd_ba_rsp-> peer_mac_addr))) { PRINTM(MCMND, - "ADDBA REQ: %02x:%02x:%02x:%02x:%02x:%02x tid=%d ssn=%d win_size=%d,amsdu=%d\n", - padd_ba_rsp->peer_mac_addr[0], padd_ba_rsp->peer_mac_addr[1], - padd_ba_rsp->peer_mac_addr[2], padd_ba_rsp->peer_mac_addr[3], - padd_ba_rsp->peer_mac_addr[4], padd_ba_rsp->peer_mac_addr[5], - tid, padd_ba_rsp->ssn, + "ADDBA REQ: " MACSTR " tid=%d ssn=%d win_size=%d,amsdu=%d\n", + MAC2STR(padd_ba_rsp->peer_mac_addr), tid, padd_ba_rsp->ssn, ((padd_ba_rsp-> block_ack_param_set & BLOCKACKPARAM_WINSIZE_MASK) >> BLOCKACKPARAM_WINSIZE_POS), @@ -1797,6 +1879,10 @@ wlan_cmd_append_11n_tlv(IN mlan_private * pmpriv, memcpy(pmadapter, (t_u8 *) pext_cap + sizeof(MrvlIEtypesHeader_t), (t_u8 *) pbss_desc->pext_cap + sizeof(IEEEtypes_Header_t), pbss_desc->pext_cap->ieee_hdr.len); + if (!ISSUPP_EXTCAP_TDLS(pmpriv->ext_cap)) + RESET_EXTCAP_TDLS(pext_cap->ext_cap); + if (!ISSUPP_EXTCAP_INTERWORKING(pmpriv->ext_cap)) + RESET_EXTCAP_INTERWORKING(pext_cap->ext_cap); HEXDUMP("Extended Capabilities IE", (t_u8 *) pext_cap, sizeof(MrvlIETypes_ExtCap_t)); *ppbuffer += sizeof(MrvlIETypes_ExtCap_t); diff --git a/drivers/net/wireless/sd8797/mlan/mlan_11n_aggr.c b/drivers/net/wireless/sd8797/mlan/mlan_11n_aggr.c index 991670c4fcaa..7acaaa4b4aee 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_11n_aggr.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_11n_aggr.c @@ -182,11 +182,17 @@ static int wlan_11n_get_num_aggrpkts(t_u8 * data, int total_pkt_len) { int pkt_count = 0, pkt_len, pad; + t_u8 hdr_len = sizeof(Eth803Hdr_t); ENTER(); - while (total_pkt_len > 0) { + while (total_pkt_len >= hdr_len) { /* Length will be in network format, change it to host */ pkt_len = mlan_ntohs((*(t_u16 *) (data + (2 * MLAN_MAC_ADDR_LENGTH)))); + if (pkt_len > total_pkt_len) { + PRINTM(MERROR, "Error in packet length.\n"); + break; + } + pad = (((pkt_len + sizeof(Eth803Hdr_t)) & 3)) ? (4 - ((pkt_len + sizeof(Eth803Hdr_t)) & 3)) : 0; data += pkt_len + pad + sizeof(Eth803Hdr_t); @@ -224,6 +230,7 @@ wlan_11n_deaggregate_pkt(mlan_private * priv, pmlan_buffer pmbuf) t_u8 rfc1042_eth_hdr[MLAN_MAC_ADDR_LENGTH] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; + t_u8 hdr_len = sizeof(Eth803Hdr_t); ENTER(); @@ -239,7 +246,7 @@ wlan_11n_deaggregate_pkt(mlan_private * priv, pmlan_buffer pmbuf) pmbuf->use_count = wlan_11n_get_num_aggrpkts(data, total_pkt_len); - while (total_pkt_len > 0) { + while (total_pkt_len >= hdr_len) { prx_pkt = (RxPacketHdr_t *) data; /* Length will be in network format, change it to host */ pkt_len = mlan_ntohs((*(t_u16 *) (data + (2 * MLAN_MAC_ADDR_LENGTH)))); @@ -285,14 +292,16 @@ wlan_11n_deaggregate_pkt(mlan_private * priv, pmlan_buffer pmbuf) pkt_len); #ifdef UAP_SUPPORT - if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) + if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) { ret = wlan_uap_recv_packet(priv, daggr_mbuf); - else + } else { #endif /* UAP_SUPPORT */ ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle, daggr_mbuf); - +#ifdef UAP_SUPPORT + } +#endif /* UAP_SUPPORT */ switch (ret) { case MLAN_STATUS_PENDING: break; @@ -337,7 +346,7 @@ wlan_11n_aggregate_pkt(mlan_private * priv, raListTbl * pra_list, int pad = 0; mlan_status ret = MLAN_STATUS_SUCCESS; #ifdef DEBUG_LEVEL1 - t_u32 sec, usec; + t_u32 sec = 0, usec = 0; #endif mlan_tx_param tx_param; #ifdef STA_SUPPORT @@ -368,6 +377,8 @@ wlan_11n_aggregate_pkt(mlan_private * priv, raListTbl * pra_list, pmbuf_aggr->priority = pmbuf_src->priority; pmbuf_aggr->pbuf = data; pmbuf_aggr->data_offset = 0; + pmbuf_aggr->in_ts_sec = pmbuf_src->in_ts_sec; + pmbuf_aggr->in_ts_usec = pmbuf_src->in_ts_usec; /* Form AMSDU */ wlan_11n_form_amsdu_txpd(priv, pmbuf_aggr); diff --git a/drivers/net/wireless/sd8797/mlan/mlan_11n_rxreorder.c b/drivers/net/wireless/sd8797/mlan/mlan_11n_rxreorder.c index 1dd3f94431f9..0db9b99a4d12 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_11n_rxreorder.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_11n_rxreorder.c @@ -426,10 +426,9 @@ wlan_11n_create_rxreorder_tbl(mlan_private * priv, t_u8 * ta, int tid, if ((rx_reor_tbl_ptr = wlan_11n_get_rxreorder_tbl(priv, tid, ta))) { wlan_11n_dispatch_pkt_until_start_win(priv, rx_reor_tbl_ptr, seq_num); } else { - PRINTM(MDAT_D, "%s: seq_num %d, tid %d, ta %02x:%02x:%02x:%02x:" - "%02x:%02x, win_size %d\n", __FUNCTION__, - seq_num, tid, ta[0], ta[1], ta[2], ta[3], - ta[4], ta[5], win_size); + PRINTM(MDAT_D, "%s: seq_num %d, tid %d, ta " MACSTR + ", win_size %d\n", __FUNCTION__, + seq_num, tid, MAC2STR(ta), win_size); if (pmadapter->callbacks. moal_malloc(pmadapter->pmoal_handle, sizeof(RxReorderTbl), MLAN_MEM_DEF, (t_u8 **) & new_node)) { @@ -453,13 +452,10 @@ wlan_11n_create_rxreorder_tbl(mlan_private * priv, t_u8 * ta, int tid, } else { last_seq = priv->rx_seq[tid]; } - if ((last_seq != DEFAULT_SEQ_NUM) && (last_seq >= new_node->start_win)) { - PRINTM(MDAT_D, "Update start_win: last_seq=%d, start_win=%d\n", - last_seq, new_node->start_win); - new_node->start_win = last_seq + 1; - } + new_node->last_seq = last_seq; new_node->win_size = win_size; new_node->force_no_drop = MFALSE; + new_node->check_start_win = MTRUE; if (pmadapter->callbacks. moal_malloc(pmadapter->pmoal_handle, sizeof(t_void *) * win_size, @@ -471,7 +467,8 @@ wlan_11n_create_rxreorder_tbl(mlan_private * priv, t_u8 * ta, int tid, return; } - PRINTM(MDAT_D, "Create ReorderPtr: %p\n", new_node); + PRINTM(MDAT_D, "Create ReorderPtr: %p start_win=%d last_seq=%d\n", + new_node, new_node->start_win, last_seq); new_node->timer_context.ptr = new_node; new_node->timer_context.priv = priv; new_node->timer_context.timer_is_set = MFALSE; @@ -731,13 +728,41 @@ mlan_11n_rxreorder_pkt(void *priv, t_u16 seq_num, t_u16 tid, if (pkt_type == PKT_TYPE_AMSDU) PRINTM(MDAT_D, "AMSDU "); + if (rx_reor_tbl_ptr->check_start_win) { + rx_reor_tbl_ptr->check_start_win = MFALSE; + if ((seq_num != rx_reor_tbl_ptr->start_win) && + (rx_reor_tbl_ptr->last_seq != DEFAULT_SEQ_NUM)) { + end_win = + (rx_reor_tbl_ptr->start_win + rx_reor_tbl_ptr->win_size - + 1) & (MAX_TID_VALUE - 1); + if (((end_win > rx_reor_tbl_ptr->start_win) + && (rx_reor_tbl_ptr->last_seq >= + rx_reor_tbl_ptr->start_win) + && (rx_reor_tbl_ptr->last_seq < end_win)) || + ((end_win < rx_reor_tbl_ptr->start_win) && + ((rx_reor_tbl_ptr->last_seq >= rx_reor_tbl_ptr->start_win) + || (rx_reor_tbl_ptr->last_seq < end_win)))) { + PRINTM(MDAT_D, + "Update start_win: last_seq=%d, start_win=%d seq_num=%d\n", + rx_reor_tbl_ptr->last_seq, + rx_reor_tbl_ptr->start_win, seq_num); + rx_reor_tbl_ptr->start_win = rx_reor_tbl_ptr->last_seq + 1; + } else if ((seq_num < rx_reor_tbl_ptr->start_win) && + (seq_num > rx_reor_tbl_ptr->last_seq)) { + PRINTM(MDAT_D, + "Update start_win: last_seq=%d, start_win=%d seq_num=%d\n", + rx_reor_tbl_ptr->last_seq, + rx_reor_tbl_ptr->start_win, seq_num); + rx_reor_tbl_ptr->start_win = rx_reor_tbl_ptr->last_seq + 1; + } + } + } + prev_start_win = start_win = rx_reor_tbl_ptr->start_win; win_size = rx_reor_tbl_ptr->win_size; end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1); - PRINTM(MDAT_D, - "TID %d, TA %02x:%02x:%02x:%02x:%02x:%02x\n", - tid, ta[0], ta[1], ta[2], ta[3], ta[4], ta[5]); + PRINTM(MDAT_D, "TID %d, TA " MACSTR "\n", tid, MAC2STR(ta)); PRINTM(MDAT_D, "1:seq_num %d start_win %d win_size %d end_win %d\n", seq_num, start_win, win_size, end_win); @@ -864,10 +889,8 @@ mlan_11n_delete_bastream_tbl(mlan_private * priv, int tid, else cleanup_rx_reorder_tbl = (initiator) ? MFALSE : MTRUE; - PRINTM(MEVENT, "DELBA: %02x:%02x:%02x:%02x:%02x:%02x tid=%d," - "initiator=%d\n", peer_mac[0], - peer_mac[1], peer_mac[2], - peer_mac[3], peer_mac[4], peer_mac[5], tid, initiator); + PRINTM(MEVENT, "DELBA: " MACSTR " tid=%d," + "initiator=%d\n", MAC2STR(peer_mac), tid, initiator); if (cleanup_rx_reorder_tbl) { if (!(rx_reor_tbl_ptr = wlan_11n_get_rxreorder_tbl(priv, tid, @@ -920,11 +943,8 @@ wlan_ret_11n_addba_resp(mlan_private * priv, HostCmd_DS_COMMAND * resp) /* Check if we had rejected the ADDBA, if yes then do not create the stream */ if (padd_ba_rsp->status_code == BA_RESULT_SUCCESS) { PRINTM(MCMND, - "ADDBA RSP: %02x:%02x:%02x:%02x:%02x:%02x tid=%d ssn=%d win_size=%d,amsdu=%d\n", - padd_ba_rsp->peer_mac_addr[0], padd_ba_rsp->peer_mac_addr[1], - padd_ba_rsp->peer_mac_addr[2], padd_ba_rsp->peer_mac_addr[3], - padd_ba_rsp->peer_mac_addr[4], padd_ba_rsp->peer_mac_addr[5], - tid, padd_ba_rsp->ssn, + "ADDBA RSP: " MACSTR " tid=%d ssn=%d win_size=%d,amsdu=%d\n", + MAC2STR(padd_ba_rsp->peer_mac_addr), tid, padd_ba_rsp->ssn, ((padd_ba_rsp->block_ack_param_set & BLOCKACKPARAM_WINSIZE_MASK) >> BLOCKACKPARAM_WINSIZE_POS), padd_ba_rsp-> @@ -943,15 +963,11 @@ wlan_ret_11n_addba_resp(mlan_private * priv, HostCmd_DS_COMMAND * resp) rx_reor_tbl_ptr->amsdu = MFALSE; } } else { - PRINTM(MERROR, - "ADDBA RSP: Failed(%02x:%02x:%02x:%02x:%02x:%02x tid=%d)\n", - padd_ba_rsp->peer_mac_addr[0], padd_ba_rsp->peer_mac_addr[1], - padd_ba_rsp->peer_mac_addr[2], padd_ba_rsp->peer_mac_addr[3], - padd_ba_rsp->peer_mac_addr[4], padd_ba_rsp->peer_mac_addr[5], - tid); - if ((rx_reor_tbl_ptr = - wlan_11n_get_rxreorder_tbl(priv, tid, - padd_ba_rsp->peer_mac_addr))) { + PRINTM(MERROR, "ADDBA RSP: Failed(" MACSTR " tid=%d)\n", + MAC2STR(padd_ba_rsp->peer_mac_addr), tid); + if ((rx_reor_tbl_ptr = wlan_11n_get_rxreorder_tbl(priv, tid, + padd_ba_rsp-> + peer_mac_addr))) { wlan_11n_delete_rxreorder_tbl_entry(priv, rx_reor_tbl_ptr); } } @@ -1047,11 +1063,9 @@ wlan_11n_rxba_sync_event(mlan_private * priv, t_u8 * event_buf, t_u16 len) } tlv_rxba->seq_num = wlan_le16_to_cpu(tlv_rxba->seq_num); tlv_rxba->bitmap_len = wlan_le16_to_cpu(tlv_rxba->bitmap_len); - PRINTM(MEVENT, - "%02x:%02x:%02x:%02x:%02x:%02x tid=%d seq_num=%d bitmap_len=%d\n", - tlv_rxba->mac[0], tlv_rxba->mac[1], tlv_rxba->mac[2], - tlv_rxba->mac[3], tlv_rxba->mac[4], tlv_rxba->mac[5], - tlv_rxba->tid, tlv_rxba->seq_num, tlv_rxba->bitmap_len); + PRINTM(MEVENT, MACSTR " tid=%d seq_num=%d bitmap_len=%d\n", + MAC2STR(tlv_rxba->mac), tlv_rxba->tid, tlv_rxba->seq_num, + tlv_rxba->bitmap_len); rx_reor_tbl_ptr = wlan_11n_get_rxreorder_tbl(priv, tlv_rxba->tid, tlv_rxba->mac); if (!rx_reor_tbl_ptr) { diff --git a/drivers/net/wireless/sd8797/mlan/mlan_cfp.c b/drivers/net/wireless/sd8797/mlan/mlan_cfp.c index fbc2a7c4d208..e9369ecfed24 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_cfp.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_cfp.c @@ -944,17 +944,17 @@ wlan_misc_country_2_cfp_table_code(pmlan_adapter pmadapter, t_u8 * country_code, /** * @brief Use index to get the data rate * - * @param pmadapter A pointer to mlan_adapter structure - * @param index The index of data rate - * @param ht_info ht info + * @param pmadapter A pointer to mlan_adapter structure + * @param index The index of data rate + * @param ht_info HT info * - * @return Data rate or 0 + * @return Data rate or 0 */ - t_u32 wlan_index_to_data_rate(pmlan_adapter pmadapter, t_u8 index, t_u8 ht_info) { #define MCS_NUM_SUPP 16 + t_u16 mcs_num_supp = MCS_NUM_SUPP; t_u16 mcs_rate[4][MCS_NUM_SUPP] = { {0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e, 0x36, 0x6c, 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c} @@ -968,17 +968,19 @@ wlan_index_to_data_rate(pmlan_adapter pmadapter, t_u8 index, t_u8 ht_info) {0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90, 0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120} }; /* SG 20M */ - t_u32 rate = 0; + ENTER(); + if (pmadapter->usr_dev_mcs_support == HT_STREAM_MODE_1X1) + mcs_num_supp = 8; if (ht_info & MBIT(0)) { if (index == MLAN_RATE_BITMAP_MCS0) { if (ht_info & MBIT(2)) rate = 0x0D; /* MCS 32 SGI rate */ else rate = 0x0C; /* MCS 32 LGI rate */ - } else if (index < MCS_NUM_SUPP) { + } else if (index < mcs_num_supp) { if (ht_info & MBIT(1)) { if (ht_info & MBIT(2)) rate = mcs_rate[1][index]; /* SGI, 40M */ @@ -1184,7 +1186,7 @@ wlan_get_cfp_by_band_and_channel(pmlan_adapter pmadapter, } if (!cfp && channel) - PRINTM(MERROR, "wlan_get_cfp_by_band_and_channel(): cannot find " + PRINTM(MCMND, "wlan_get_cfp_by_band_and_channel(): cannot find " "cfp by band %d & channel %d\n", band, channel); LEAVE(); diff --git a/drivers/net/wireless/sd8797/mlan/mlan_cmdevt.c b/drivers/net/wireless/sd8797/mlan/mlan_cmdevt.c index 2b0c77632757..11c158cd997f 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_cmdevt.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_cmdevt.c @@ -45,6 +45,229 @@ Change Log: /******************************************************** Local Functions ********************************************************/ +#ifdef STA_SUPPORT +/** + * @brief Internal function used to flush the scan pending queue + * + * @param pmadapter A pointer to mlan_adapter structure + * + * @return N/A + */ +void +wlan_check_scan_queue(IN pmlan_adapter pmadapter) +{ + cmd_ctrl_node *pcmd_node = MNULL; + t_u16 num = 0; + + if (! + (pcmd_node = + (cmd_ctrl_node *) util_peek_list(pmadapter->pmoal_handle, + &pmadapter->scan_pending_q, + pmadapter->callbacks.moal_spin_lock, + pmadapter->callbacks. + moal_spin_unlock))) { + PRINTM(MERROR, "No pending scan command\n"); + return; + } + while (pcmd_node != (cmd_ctrl_node *) & pmadapter->scan_pending_q) { + num++; + pcmd_node = pcmd_node->pnext; + } + PRINTM(MERROR, "num_pending_scan=%d\n", num); +} +#endif + +/** + * @brief This function will dump the pending commands id + * + * @param pmadapter A pointer to mlan_adapter + * + * @return N/A + */ +static void +wlan_dump_pending_commands(pmlan_adapter pmadapter) +{ + cmd_ctrl_node *pcmd_node = MNULL; + HostCmd_DS_COMMAND *pcmd; + + ENTER(); + + if (! + (pcmd_node = + (cmd_ctrl_node *) util_peek_list(pmadapter->pmoal_handle, + &pmadapter->cmd_pending_q, + pmadapter->callbacks.moal_spin_lock, + pmadapter->callbacks. + moal_spin_unlock))) { + LEAVE(); + return; + } + while (pcmd_node != (cmd_ctrl_node *) & pmadapter->cmd_pending_q) { + pcmd = + (HostCmd_DS_COMMAND *) (pcmd_node->cmdbuf->pbuf + + pcmd_node->cmdbuf->data_offset); + PRINTM(MERROR, "pending command id: 0x%x\n", + wlan_le16_to_cpu(pcmd->command)); + pcmd_node = pcmd_node->pnext; + } +#ifdef STA_SUPPORT + wlan_check_scan_queue(pmadapter); +#endif + LEAVE(); + return; +} + +#define REASON_CODE_NO_CMD_NODE 1 +#define REASON_CODE_CMD_TIMEOUT 2 + +/** + * @brief This function dump debug info + * + * @return N/A + */ +t_void +wlan_dump_info(mlan_adapter * pmadapter, t_u8 reason) +{ + cmd_ctrl_node *pcmd_node = MNULL; +#ifdef DEBUG_LEVEL1 + t_u32 sec = 0, usec = 0; +#endif + t_u8 i; + t_u16 cmd_id, cmd_act; + mlan_private *pmpriv = MNULL; + + ENTER(); + + PRINTM(MERROR, "------------Dump info-----------\n", reason); + switch (reason) { + case REASON_CODE_NO_CMD_NODE: + pmadapter->dbg.num_no_cmd_node++; + PRINTM(MERROR, "No Free command node\n"); + wlan_dump_pending_commands(pmadapter); + break; + case REASON_CODE_CMD_TIMEOUT: + PRINTM(MERROR, "Commmand Timeout\n"); + break; + default: + break; + } + if (reason != REASON_CODE_CMD_TIMEOUT) { + if (!pmadapter->curr_cmd) { + PRINTM(MERROR, "CurCmd Empty\n"); + } else { + pcmd_node = pmadapter->curr_cmd; + cmd_id = pmadapter->dbg.last_cmd_id[pmadapter->dbg.last_cmd_index]; + cmd_act = + pmadapter->dbg.last_cmd_act[pmadapter->dbg.last_cmd_index]; + PRINTM_GET_SYS_TIME(MERROR, &sec, &usec); + PRINTM(MERROR, "Current cmd id (%lu.%06lu) = 0x%x, act = 0x%x \n", + sec, usec, cmd_id, cmd_act); + if (pcmd_node->cmdbuf) { + t_u8 *pcmd_buf; + pcmd_buf = + pcmd_node->cmdbuf->pbuf + pcmd_node->cmdbuf->data_offset + + INTF_HEADER_LEN; + for (i = 0; i < 16; i++) { + PRINTM(MERROR, "%02x ", *pcmd_buf++); + } + PRINTM(MERROR, "\n"); + } + pmpriv = pcmd_node->priv; + if (pmpriv) { + PRINTM(MERROR, "BSS type = %d BSS role= %d\n", pmpriv->bss_type, + pmpriv->bss_role); + } + } + } + PRINTM(MERROR, "mlan_processing =%d\n", pmadapter->mlan_processing); + PRINTM(MERROR, "more_task_flag = %d\n", pmadapter->more_task_flag); + PRINTM(MERROR, "num_cmd_timeout = %d\n", pmadapter->dbg.num_cmd_timeout); + PRINTM(MERROR, "last_cmd_index = %d\n", pmadapter->dbg.last_cmd_index); + PRINTM(MERROR, "last_cmd_id = "); + for (i = 0; i < DBG_CMD_NUM; i++) { + PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_cmd_id[i]); + } + PRINTM(MERROR, "\n"); + PRINTM(MERROR, "last_cmd_act = "); + for (i = 0; i < DBG_CMD_NUM; i++) { + PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_cmd_act[i]); + } + PRINTM(MERROR, "\n"); + PRINTM(MERROR, "last_cmd_resp_index = %d\n", + pmadapter->dbg.last_cmd_resp_index); + PRINTM(MERROR, "last_cmd_resp_id = "); + for (i = 0; i < DBG_CMD_NUM; i++) { + PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_cmd_resp_id[i]); + } + PRINTM(MERROR, "\n"); + PRINTM(MERROR, "last_event_index = %d\n", pmadapter->dbg.last_event_index); + PRINTM(MERROR, "last_event = "); + for (i = 0; i < DBG_CMD_NUM; i++) { + PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_event[i]); + } + PRINTM(MERROR, "\n"); + + PRINTM(MERROR, "num_data_h2c_failure = %d\n", + pmadapter->dbg.num_tx_host_to_card_failure); + PRINTM(MERROR, "num_cmd_h2c_failure = %d\n", + pmadapter->dbg.num_cmd_host_to_card_failure); + PRINTM(MERROR, "num_data_c2h_failure = %d\n", + pmadapter->dbg.num_rx_card_to_host_failure); + PRINTM(MERROR, "num_cmdevt_c2h_failure = %d\n", + pmadapter->dbg.num_cmdevt_card_to_host_failure); + PRINTM(MERROR, "num_int_read_failure = %d\n", + pmadapter->dbg.num_int_read_failure); + PRINTM(MERROR, "last_int_status = %d\n", pmadapter->dbg.last_int_status); + PRINTM(MERROR, "num_no_cmd_node = %d\n", pmadapter->dbg.num_no_cmd_node); + PRINTM(MERROR, "num_event_deauth = %d\n", pmadapter->dbg.num_event_deauth); + PRINTM(MERROR, "num_event_disassoc = %d\n", + pmadapter->dbg.num_event_disassoc); + PRINTM(MERROR, "num_event_link_lost = %d\n", + pmadapter->dbg.num_event_link_lost); + PRINTM(MERROR, "num_cmd_deauth = %d\n", pmadapter->dbg.num_cmd_deauth); + PRINTM(MERROR, "num_cmd_assoc_success = %d\n", + pmadapter->dbg.num_cmd_assoc_success); + PRINTM(MERROR, "num_cmd_assoc_failure = %d\n", + pmadapter->dbg.num_cmd_assoc_failure); + PRINTM(MERROR, "cmd_resp_received=%d\n", pmadapter->cmd_resp_received); + PRINTM(MERROR, "event_received=%d\n", pmadapter->event_received); + + PRINTM(MERROR, "max_tx_buf_size=%d\n", pmadapter->max_tx_buf_size); + PRINTM(MERROR, "tx_buf_size=%d\n", pmadapter->tx_buf_size); + PRINTM(MERROR, "curr_tx_buf_size=%d\n", pmadapter->curr_tx_buf_size); + + PRINTM(MERROR, "data_sent=%d cmd_sent=%d\n", pmadapter->data_sent, + pmadapter->cmd_sent); + + PRINTM(MERROR, "ps_mode=%d ps_state=%d\n", pmadapter->ps_mode, + pmadapter->ps_state); + PRINTM(MERROR, "wakeup_dev_req=%d wakeup_tries=%d\n", + pmadapter->pm_wakeup_card_req, pmadapter->pm_wakeup_fw_try); + PRINTM(MERROR, "hs_configured=%d hs_activated=%d\n", + pmadapter->is_hs_configured, pmadapter->hs_activated); + PRINTM(MERROR, "pps_uapsd_mode=%d sleep_pd=%d\n", pmadapter->pps_uapsd_mode, + pmadapter->sleep_period.period); + PRINTM(MERROR, "tx_lock_flag = %d\n", pmadapter->tx_lock_flag); + PRINTM(MERROR, "scan_processing = %d\n", pmadapter->scan_processing); + PRINTM(MERROR, "mp_rd_bitmap=0x%x curr_rd_port=0x%x\n", + pmadapter->mp_rd_bitmap, pmadapter->curr_rd_port); + PRINTM(MERROR, "mp_wr_bitmap=0x%x curr_wr_port=0x%x\n", + pmadapter->mp_wr_bitmap, pmadapter->curr_wr_port); + if (reason != REASON_CODE_CMD_TIMEOUT) { + if ((pmadapter->dbg.num_no_cmd_node >= 5) + || (pmadapter->pm_wakeup_card_req && pmadapter->pm_wakeup_fw_try) + ) { + if (pmpriv) + wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL); + else + wlan_recv_event(wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY), + MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL); + } + } + PRINTM(MERROR, "-------- Dump info End---------\n", reason); + LEAVE(); + return; +} /** * @brief This function convert a given character to hex @@ -107,8 +330,9 @@ wlan_parse_cal_cfg(t_u8 * src, t_size len, t_u8 * dst) dptr = dst; while (ptr - src < len) { - while (*ptr && (wlan_isspace(*ptr) || *ptr == '\t')) { + if (*ptr && (wlan_isspace(*ptr) || *ptr == '\t')) { ptr++; + continue; } if (wlan_isxdigit(*ptr)) { @@ -234,6 +458,49 @@ wlan_clean_cmd_node(pmlan_adapter pmadapter, cmd_ctrl_node * pcmd_node) return; } +#ifdef STA_SUPPORT +/** + * @brief This function will return the pointer to the first entry in + * pending cmd which matches the given req_id + * + * @param pmadapter A pointer to mlan_adapter + * @param req_id ioctl req_id. + * + * @return A pointer to first entry match pioctl_req + */ +static cmd_ctrl_node * +wlan_get_pending_ioctl_by_id(pmlan_adapter pmadapter, t_u32 req_id) +{ + cmd_ctrl_node *pcmd_node = MNULL; + mlan_ioctl_req *pioctl_buf = MNULL; + + ENTER(); + + if (! + (pcmd_node = + (cmd_ctrl_node *) util_peek_list(pmadapter->pmoal_handle, + &pmadapter->cmd_pending_q, + pmadapter->callbacks.moal_spin_lock, + pmadapter->callbacks. + moal_spin_unlock))) { + LEAVE(); + return MNULL; + } + while (pcmd_node != (cmd_ctrl_node *) & pmadapter->cmd_pending_q) { + if (pcmd_node->pioctl_buf) { + pioctl_buf = (mlan_ioctl_req *) pcmd_node->pioctl_buf; + if (pioctl_buf->req_id == req_id) { + LEAVE(); + return pcmd_node; + } + } + pcmd_node = pcmd_node->pnext; + } + LEAVE(); + return MNULL; +} +#endif + /** * @brief This function will return the pointer to the first entry in * pending cmd which matches the given pioctl_req @@ -261,7 +528,7 @@ wlan_get_pending_ioctl_cmd(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req) return MNULL; } while (pcmd_node != (cmd_ctrl_node *) & pmadapter->cmd_pending_q) { - if (pcmd_node->pioctl_buf == pioctl_req) { + if (pcmd_node->pioctl_buf && (pcmd_node->pioctl_buf == pioctl_req)) { LEAVE(); return pcmd_node; } @@ -271,6 +538,46 @@ wlan_get_pending_ioctl_cmd(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req) return MNULL; } +/** + * @brief This function will return the pointer to the first entry in + * pending cmd which matches the given bss_index + * + * @param pmadapter A pointer to mlan_adapter + * @param bss_index bss_index + * + * @return A pointer to first entry match pioctl_req + */ +static cmd_ctrl_node * +wlan_get_bss_pending_ioctl_cmd(pmlan_adapter pmadapter, t_u32 bss_index) +{ + cmd_ctrl_node *pcmd_node = MNULL; + mlan_ioctl_req *pioctl_buf = MNULL; + ENTER(); + + if (! + (pcmd_node = + (cmd_ctrl_node *) util_peek_list(pmadapter->pmoal_handle, + &pmadapter->cmd_pending_q, + pmadapter->callbacks.moal_spin_lock, + pmadapter->callbacks. + moal_spin_unlock))) { + LEAVE(); + return MNULL; + } + while (pcmd_node != (cmd_ctrl_node *) & pmadapter->cmd_pending_q) { + if (pcmd_node->pioctl_buf) { + pioctl_buf = (mlan_ioctl_req *) pcmd_node->pioctl_buf; + if (pioctl_buf->bss_index == bss_index) { + LEAVE(); + return pcmd_node; + } + } + pcmd_node = pcmd_node->pnext; + } + LEAVE(); + return MNULL; +} + /** * @brief This function handles the command response of host_cmd * @@ -345,7 +652,7 @@ wlan_dnld_cmd_to_fw(IN mlan_private * pmpriv, IN cmd_ctrl_node * pcmd_node) t_u16 cmd_code; t_u16 cmd_size; #ifdef DEBUG_LEVEL1 - t_u32 sec, usec; + t_u32 sec = 0, usec = 0; #endif ENTER(); @@ -447,7 +754,7 @@ wlan_dnld_cmd_to_fw(IN mlan_private * pmpriv, IN cmd_ctrl_node * pcmd_node) /* Setup the timer after transmit command */ pcb->moal_start_timer(pmadapter->pmoal_handle, pmadapter->pmlan_cmd_timer, - MFALSE, MRVDRV_TIMER_60S); + MFALSE, MRVDRV_TIMER_10S); pmadapter->cmd_timer_is_set = MTRUE; @@ -694,7 +1001,7 @@ wlan_process_event(pmlan_adapter pmadapter) pmlan_buffer pmbuf = pmadapter->pmlan_buffer_event; t_u32 eventcause = pmadapter->event_cause; #ifdef DEBUG_LEVEL1 - t_u32 in_ts_sec, in_ts_usec; + t_u32 in_ts_sec = 0, in_ts_usec = 0; #endif ENTER(); @@ -842,6 +1149,7 @@ wlan_prepare_cmd(IN mlan_private * pmpriv, if (pcmd_node == MNULL) { PRINTM(MERROR, "PREP_CMD: No free cmd node\n"); + wlan_dump_info(pmadapter, REASON_CODE_NO_CMD_NODE); if (pioctl_req) pioctl_req->status_code = MLAN_ERROR_NO_MEM; ret = MLAN_STATUS_FAILURE; @@ -973,10 +1281,6 @@ wlan_insert_cmd_to_pending_q(IN mlan_adapter * pmadapter, pcmd = (HostCmd_DS_COMMAND *) (pcmd_node->cmdbuf->pbuf + pcmd_node->cmdbuf->data_offset); - if (pcmd == MNULL) { - PRINTM(MERROR, "QUEUE_CMD: pcmd is MNULL\n"); - goto done; - } command = wlan_le16_to_cpu(pcmd->command); @@ -1113,7 +1417,7 @@ wlan_process_cmdresp(mlan_adapter * pmadapter) mlan_ioctl_req *pioctl_buf = MNULL; mlan_callbacks *pcb = (mlan_callbacks *) & pmadapter->callbacks; #ifdef DEBUG_LEVEL1 - t_u32 sec, usec; + t_u32 sec = 0, usec = 0; #endif t_u32 i; @@ -1158,7 +1462,7 @@ wlan_process_cmdresp(mlan_adapter * pmadapter) cmd_ctrl_node *free_cmd = pmadapter->curr_cmd; pmadapter->curr_cmd = MNULL; wlan_release_cmd_lock(pmadapter); - PRINTM(MERROR, "CMD_RESP: 0x%x been canceled!\n", + PRINTM(MCMND, "CMD_RESP: 0x%x been canceled!\n", wlan_le16_to_cpu(resp->command)); wlan_insert_cmd_to_free_q(pmadapter, free_cmd); if (pioctl_buf) @@ -1255,7 +1559,8 @@ wlan_process_cmdresp(mlan_adapter * pmadapter) if (pioctl_buf && (ret == MLAN_STATUS_SUCCESS)) pioctl_buf->status_code = MLAN_ERROR_NO_ERROR; - else if (pioctl_buf && (ret == MLAN_STATUS_FAILURE)) + else if (pioctl_buf && (ret == MLAN_STATUS_FAILURE) && + !pioctl_buf->status_code) pioctl_buf->status_code = MLAN_ERROR_CMD_RESP_FAIL; /* Clean up and put current command back to cmd_free_q */ @@ -1267,8 +1572,15 @@ wlan_process_cmdresp(mlan_adapter * pmadapter) if ((pmadapter->hw_status == WlanHardwareStatusInitializing) && (pmadapter->last_init_cmd == cmdresp_no)) { i = pmpriv->bss_index + 1; - while (!(pmpriv_next = pmadapter->priv[i]) && i < pmadapter->priv_num) + while (i < pmadapter->priv_num && !(pmpriv_next = pmadapter->priv[i])) i++; + if (pmpriv_next && pmpriv_next->bss_virtual) { + i = pmpriv_next->bss_index + 1; + /** skip virtual interface */ + while (i < pmadapter->priv_num && + !(pmpriv_next = pmadapter->priv[i])) + i++; + } if (!pmpriv_next || i >= pmadapter->priv_num) { #if defined(STA_SUPPORT) if (pmadapter->pwarm_reset_ioctl_req) { @@ -1307,7 +1619,7 @@ wlan_cmd_timeout_func(t_void * function_context) cmd_ctrl_node *pcmd_node = MNULL; mlan_ioctl_req *pioctl_buf = MNULL; #ifdef DEBUG_LEVEL1 - t_u32 sec, usec; + t_u32 sec = 0, usec = 0; #endif t_u8 i; mlan_private *pmpriv = MNULL; @@ -1327,119 +1639,41 @@ wlan_cmd_timeout_func(t_void * function_context) pioctl_buf->status_code = MLAN_ERROR_CMD_TIMEOUT; } - if (pcmd_node) { - pmadapter->dbg.timeout_cmd_id = - pmadapter->dbg.last_cmd_id[pmadapter->dbg.last_cmd_index]; - pmadapter->dbg.timeout_cmd_act = - pmadapter->dbg.last_cmd_act[pmadapter->dbg.last_cmd_index]; - PRINTM_GET_SYS_TIME(MERROR, &sec, &usec); - PRINTM(MERROR, "Timeout cmd id (%lu.%06lu) = 0x%x, act = 0x%x \n", sec, - usec, pmadapter->dbg.timeout_cmd_id, - pmadapter->dbg.timeout_cmd_act); - if (pcmd_node->cmdbuf) { - t_u8 *pcmd_buf; - pcmd_buf = - pcmd_node->cmdbuf->pbuf + pcmd_node->cmdbuf->data_offset + - INTF_HEADER_LEN; - for (i = 0; i < 16; i++) { - PRINTM(MERROR, "%02x ", *pcmd_buf++); - } - PRINTM(MERROR, "\n"); - } - - pmpriv = pcmd_node->priv; - if (pmpriv) { - PRINTM(MERROR, "BSS type = %d BSS role= %d\n", pmpriv->bss_type, - pmpriv->bss_role); - } - - PRINTM(MERROR, "num_cmd_timeout = %d\n", - pmadapter->dbg.num_cmd_timeout); - PRINTM(MERROR, "last_cmd_index = %d\n", pmadapter->dbg.last_cmd_index); - PRINTM(MERROR, "last_cmd_id = "); - for (i = 0; i < DBG_CMD_NUM; i++) { - PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_cmd_id[i]); - } - PRINTM(MERROR, "\n"); - PRINTM(MERROR, "last_cmd_act = "); - for (i = 0; i < DBG_CMD_NUM; i++) { - PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_cmd_act[i]); - } - PRINTM(MERROR, "\n"); - PRINTM(MERROR, "last_cmd_resp_index = %d\n", - pmadapter->dbg.last_cmd_resp_index); - PRINTM(MERROR, "last_cmd_resp_id = "); - for (i = 0; i < DBG_CMD_NUM; i++) { - PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_cmd_resp_id[i]); - } - PRINTM(MERROR, "\n"); - PRINTM(MERROR, "last_event_index = %d\n", - pmadapter->dbg.last_event_index); - PRINTM(MERROR, "last_event = "); - for (i = 0; i < DBG_CMD_NUM; i++) { - PRINTM(MERROR, "0x%x ", pmadapter->dbg.last_event[i]); + pmadapter->dbg.timeout_cmd_id = + pmadapter->dbg.last_cmd_id[pmadapter->dbg.last_cmd_index]; + pmadapter->dbg.timeout_cmd_act = + pmadapter->dbg.last_cmd_act[pmadapter->dbg.last_cmd_index]; + PRINTM_GET_SYS_TIME(MERROR, &sec, &usec); + PRINTM(MERROR, "Timeout cmd id (%lu.%06lu) = 0x%x, act = 0x%x \n", sec, + usec, pmadapter->dbg.timeout_cmd_id, pmadapter->dbg.timeout_cmd_act); + if (pcmd_node->cmdbuf) { + t_u8 *pcmd_buf; + pcmd_buf = + pcmd_node->cmdbuf->pbuf + pcmd_node->cmdbuf->data_offset + + INTF_HEADER_LEN; + for (i = 0; i < 16; i++) { + PRINTM(MERROR, "%02x ", *pcmd_buf++); } PRINTM(MERROR, "\n"); + } - PRINTM(MERROR, "num_data_h2c_failure = %d\n", - pmadapter->dbg.num_tx_host_to_card_failure); - PRINTM(MERROR, "num_cmd_h2c_failure = %d\n", - pmadapter->dbg.num_cmd_host_to_card_failure); - PRINTM(MERROR, "num_data_c2h_failure = %d\n", - pmadapter->dbg.num_rx_card_to_host_failure); - PRINTM(MERROR, "num_cmdevt_c2h_failure = %d\n", - pmadapter->dbg.num_cmdevt_card_to_host_failure); - PRINTM(MERROR, "num_int_read_failure = %d\n", - pmadapter->dbg.num_int_read_failure); - PRINTM(MERROR, "last_int_status = %d\n", - pmadapter->dbg.last_int_status); - - PRINTM(MERROR, "num_event_deauth = %d\n", - pmadapter->dbg.num_event_deauth); - PRINTM(MERROR, "num_event_disassoc = %d\n", - pmadapter->dbg.num_event_disassoc); - PRINTM(MERROR, "num_event_link_lost = %d\n", - pmadapter->dbg.num_event_link_lost); - PRINTM(MERROR, "num_cmd_deauth = %d\n", pmadapter->dbg.num_cmd_deauth); - PRINTM(MERROR, "num_cmd_assoc_success = %d\n", - pmadapter->dbg.num_cmd_assoc_success); - PRINTM(MERROR, "num_cmd_assoc_failure = %d\n", - pmadapter->dbg.num_cmd_assoc_failure); - PRINTM(MERROR, "cmd_resp_received=%d\n", pmadapter->cmd_resp_received); - PRINTM(MERROR, "event_received=%d\n", pmadapter->event_received); - - PRINTM(MERROR, "max_tx_buf_size=%d\n", pmadapter->max_tx_buf_size); - PRINTM(MERROR, "tx_buf_size=%d\n", pmadapter->tx_buf_size); - PRINTM(MERROR, "curr_tx_buf_size=%d\n", pmadapter->curr_tx_buf_size); - - PRINTM(MERROR, "data_sent=%d cmd_sent=%d\n", pmadapter->data_sent, - pmadapter->cmd_sent); - - PRINTM(MERROR, "ps_mode=%d ps_state=%d\n", pmadapter->ps_mode, - pmadapter->ps_state); - PRINTM(MERROR, "wakeup_dev_req=%d wakeup_tries=%d\n", - pmadapter->pm_wakeup_card_req, pmadapter->pm_wakeup_fw_try); - PRINTM(MERROR, "hs_configured=%d hs_activated=%d\n", - pmadapter->is_hs_configured, pmadapter->hs_activated); - PRINTM(MERROR, "pps_uapsd_mode=%d sleep_pd=%d\n", - pmadapter->pps_uapsd_mode, pmadapter->sleep_period.period); - PRINTM(MERROR, "tx_lock_flag = %d\n", pmadapter->tx_lock_flag); - PRINTM(MERROR, "scan_processing = %d\n", pmadapter->scan_processing); - - PRINTM(MERROR, "mp_rd_bitmap=0x%x curr_rd_port=0x%x\n", - pmadapter->mp_rd_bitmap, pmadapter->curr_rd_port); - PRINTM(MERROR, "mp_wr_bitmap=0x%x curr_wr_port=0x%x\n", - pmadapter->mp_wr_bitmap, pmadapter->curr_wr_port); + pmpriv = pcmd_node->priv; + if (pmpriv) { + PRINTM(MERROR, "BSS type = %d BSS role= %d\n", pmpriv->bss_type, + pmpriv->bss_role); } + wlan_dump_info(pmadapter, REASON_CODE_CMD_TIMEOUT); + if (pmadapter->hw_status == WlanHardwareStatusInitializing) wlan_init_fw_complete(pmadapter); - else + else { /* Signal MOAL to perform extra handling for debugging */ - if (pmpriv) { - wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL); - } else { - wlan_recv_event(wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY), - MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL); + if (pmpriv) { + wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL); + } else { + wlan_recv_event(wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY), + MLAN_EVENT_ID_DRV_DBG_DUMP, MNULL); + } } exit: @@ -1480,6 +1714,63 @@ wlan_flush_scan_queue(IN pmlan_adapter pmadapter) LEAVE(); } + +/** + * @brief Cancel pending SCAN ioctl cmd. + * + * @param pmadapter A pointer to mlan_adapter + * + * @return N/A + */ +t_void +wlan_cancel_pending_scan_cmd(pmlan_adapter pmadapter) +{ + pmlan_callbacks pcb = &pmadapter->callbacks; + cmd_ctrl_node *pcmd_node = MNULL; + mlan_ioctl_req *pioctl_buf = MNULL; + ENTER(); + + PRINTM(MIOCTL, "Cancel scan command\n"); + wlan_request_cmd_lock(pmadapter); + if (pmadapter->curr_cmd && pmadapter->curr_cmd->pioctl_buf) { + pioctl_buf = (mlan_ioctl_req *) pmadapter->curr_cmd->pioctl_buf; + if (pioctl_buf->req_id == MLAN_IOCTL_SCAN) { + PRINTM(MIOCTL, "wlan_cancel_scan: current command\n"); + pcmd_node = pmadapter->curr_cmd; + pcmd_node->pioctl_buf = MNULL; + pcmd_node->cmd_flag |= CMD_F_CANCELED; + pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL; + pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf, + MLAN_STATUS_FAILURE); + } + } + while ((pcmd_node = + wlan_get_pending_ioctl_by_id(pmadapter, + MLAN_IOCTL_SCAN)) != MNULL) { + PRINTM(MIOCTL, + "wlan_cancel_scan: find scan command in cmd_pending_q\n"); + util_unlink_list(pmadapter->pmoal_handle, &pmadapter->cmd_pending_q, + (pmlan_linked_list) pcmd_node, + pmadapter->callbacks.moal_spin_lock, + pmadapter->callbacks.moal_spin_unlock); + pioctl_buf = (mlan_ioctl_req *) pcmd_node->pioctl_buf; + pcmd_node->pioctl_buf = MNULL; + pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL; + pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf, + MLAN_STATUS_FAILURE); + wlan_release_cmd_lock(pmadapter); + wlan_insert_cmd_to_free_q(pmadapter, pcmd_node); + wlan_request_cmd_lock(pmadapter); + } + wlan_release_cmd_lock(pmadapter); + + /* IOCTL will be completed, avoid calling IOCTL complete again from EVENT */ + pmadapter->pext_scan_ioctl_req = MNULL; + /* Cancel all pending scan command */ + wlan_flush_scan_queue(pmadapter); + LEAVE(); + return; +} #endif /** @@ -1535,6 +1826,78 @@ wlan_cancel_all_pending_cmd(pmlan_adapter pmadapter) } /** + * @brief Cancel specific bss's pending ioctl cmd. + * + * @param pmadapter A pointer to mlan_adapter + * @param bss_index BSS index + * + * @return N/A + */ +t_void +wlan_cancel_bss_pending_cmd(pmlan_adapter pmadapter, t_u32 bss_index) +{ + pmlan_callbacks pcb = &pmadapter->callbacks; + cmd_ctrl_node *pcmd_node = MNULL; + mlan_ioctl_req *pioctl_buf = MNULL; +#ifdef STA_SUPPORT + t_u8 flash_scan = MFALSE; +#endif + ENTER(); + + PRINTM(MIOCTL, "MOAL Cancel BSS IOCTL: bss_index=%d\n", (int) bss_index); + wlan_request_cmd_lock(pmadapter); + if (pmadapter->curr_cmd && pmadapter->curr_cmd->pioctl_buf) { + pioctl_buf = (mlan_ioctl_req *) pmadapter->curr_cmd->pioctl_buf; + if (pioctl_buf->bss_index == bss_index) { + pcmd_node = pmadapter->curr_cmd; + pcmd_node->pioctl_buf = MNULL; + pcmd_node->cmd_flag |= CMD_F_CANCELED; +#ifdef STA_SUPPORT + if (pioctl_buf->req_id == MLAN_IOCTL_SCAN) + flash_scan = MTRUE; +#endif + pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL; + pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf, + MLAN_STATUS_FAILURE); + } + } + while ((pcmd_node = + wlan_get_bss_pending_ioctl_cmd(pmadapter, bss_index)) != MNULL) { + util_unlink_list(pmadapter->pmoal_handle, &pmadapter->cmd_pending_q, + (pmlan_linked_list) pcmd_node, + pmadapter->callbacks.moal_spin_lock, + pmadapter->callbacks.moal_spin_unlock); + pioctl_buf = (mlan_ioctl_req *) pcmd_node->pioctl_buf; + pcmd_node->pioctl_buf = MNULL; +#ifdef STA_SUPPORT + if (pioctl_buf->req_id == MLAN_IOCTL_SCAN) + flash_scan = MTRUE; +#endif + pioctl_buf->status_code = MLAN_ERROR_CMD_CANCEL; + pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_buf, + MLAN_STATUS_FAILURE); + wlan_release_cmd_lock(pmadapter); + wlan_insert_cmd_to_free_q(pmadapter, pcmd_node); + wlan_request_cmd_lock(pmadapter); + } + wlan_release_cmd_lock(pmadapter); +#ifdef STA_SUPPORT + if (pmadapter->pext_scan_ioctl_req && + (pmadapter->pext_scan_ioctl_req->bss_index == bss_index)) + flash_scan = MTRUE; + if (flash_scan) { + /* IOCTL will be completed, avoid calling IOCTL complete again from + EVENT */ + pmadapter->pext_scan_ioctl_req = MNULL; + /* Cancel all pending scan command */ + wlan_flush_scan_queue(pmadapter); + } +#endif + LEAVE(); + return; +} + +/** * @brief Cancel pending ioctl cmd. * * @param pmadapter A pointer to mlan_adapter @@ -2196,7 +2559,7 @@ wlan_ret_802_11_tx_rate_query(IN pmlan_private pmpriv, rate->param.data_rate.rx_ht_bw = MLAN_HT_BW40; else rate->param.data_rate.rx_ht_bw = MLAN_HT_BW20; - if (pmpriv->tx_htinfo & MBIT(2)) + if (pmpriv->rxpd_htinfo & MBIT(2)) rate->param.data_rate.rx_ht_gi = MLAN_HT_SGI; else rate->param.data_rate.rx_ht_gi = MLAN_HT_LGI; @@ -2231,7 +2594,8 @@ wlan_cmd_tx_rate_cfg(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND * cmd, IN t_u16 cmd_action, IN t_void * pdata_buf) { - HostCmd_DS_TX_RATE_CFG *rate_cfg = &cmd->params.tx_rate_cfg; + HostCmd_DS_TX_RATE_CFG *rate_cfg = + (HostCmd_DS_TX_RATE_CFG *) & (cmd->params.tx_rate_cfg); MrvlRateScope_t *rate_scope; MrvlRateDropPattern_t *rate_drop; t_u16 *pbitmap_rates = (t_u16 *) pdata_buf; @@ -2301,7 +2665,7 @@ wlan_ret_tx_rate_cfg(IN pmlan_private pmpriv, HostCmd_DS_TX_RATE_CFG *prate_cfg = MNULL; MrvlRateScope_t *prate_scope; MrvlIEtypesHeader_t *head = MNULL; - t_u16 tlv, tlv_buf_len; + t_u16 tlv, tlv_buf_len = 0; t_u8 *tlv_buf; t_u32 i; t_s32 index; @@ -2313,11 +2677,13 @@ wlan_ret_tx_rate_cfg(IN pmlan_private pmpriv, LEAVE(); return MLAN_STATUS_FAILURE; } - prate_cfg = &resp->params.tx_rate_cfg; + prate_cfg = (HostCmd_DS_TX_RATE_CFG *) & (resp->params.tx_rate_cfg); tlv_buf = (t_u8 *) ((t_u8 *) prate_cfg) + sizeof(HostCmd_DS_TX_RATE_CFG); - tlv_buf_len = *(t_u16 *) (tlv_buf + sizeof(t_u16)); - tlv_buf_len = wlan_le16_to_cpu(tlv_buf_len); + if (tlv_buf) { + tlv_buf_len = *(t_u16 *) (tlv_buf + sizeof(t_u16)); + tlv_buf_len = wlan_le16_to_cpu(tlv_buf_len); + } while (tlv_buf && tlv_buf_len > 0) { tlv = (*tlv_buf); @@ -2611,6 +2977,59 @@ wlan_ret_cfg_data(IN pmlan_private pmpriv, } /** + * @brief This function prepares command of mac_control. + * + * @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 command information buffer + * + * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE + */ +mlan_status +wlan_cmd_mac_control(IN pmlan_private pmpriv, + IN HostCmd_DS_COMMAND * pcmd, + IN t_u16 cmd_action, IN t_void * pdata_buf) +{ + HostCmd_DS_MAC_CONTROL *pmac = &pcmd->params.mac_ctrl; + t_u32 action = *((t_u32 *) pdata_buf); + + ENTER(); + + if (cmd_action != HostCmd_ACT_GEN_SET) { + PRINTM(MERROR, "wlan_cmd_mac_control(): support SET only.\n"); + LEAVE(); + return MLAN_STATUS_FAILURE; + } + + pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_MAC_CONTROL); + pcmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_MAC_CONTROL) + S_DS_GEN); + pmac->action = wlan_cpu_to_le32(action); + + LEAVE(); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief This function handles the command response of mac_control + * + * @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_mac_control(IN pmlan_private pmpriv, + IN HostCmd_DS_COMMAND * resp, + IN mlan_ioctl_req * pioctl_buf) +{ + ENTER(); + LEAVE(); + return MLAN_STATUS_SUCCESS; +} + +/** * @brief This function handles the command response of get_hw_spec * * @param pmpriv A pointer to mlan_private structure @@ -2681,10 +3100,8 @@ wlan_ret_get_hw_spec(IN pmlan_private pmpriv, PRINTM(MINFO, "GET_HW_SPEC: fw_release_number- 0x%X\n", wlan_le32_to_cpu(pmadapter->fw_release_number)); - PRINTM(MINFO, "GET_HW_SPEC: Permanent addr- %2x:%2x:%2x:%2x:%2x:%2x\n", - hw_spec->permanent_addr[0], hw_spec->permanent_addr[1], - hw_spec->permanent_addr[2], hw_spec->permanent_addr[3], - hw_spec->permanent_addr[4], hw_spec->permanent_addr[5]); + PRINTM(MINFO, "GET_HW_SPEC: Permanent addr- " MACSTR "\n", + MAC2STR(hw_spec->permanent_addr)); PRINTM(MINFO, "GET_HW_SPEC: hw_if_version=0x%X version=0x%X\n", wlan_le16_to_cpu(hw_spec->hw_if_version), wlan_le16_to_cpu(hw_spec->version)); @@ -2941,7 +3358,6 @@ wlan_ret_wifi_direct_mode(IN pmlan_private pmpriv, * * @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 pdata_buf A pointer to data buffer * @return MLAN_STATUS_SUCCESS */ @@ -3006,22 +3422,45 @@ wlan_cmd_802_11_rf_antenna(IN pmlan_private pmpriv, { HostCmd_DS_802_11_RF_ANTENNA *pantenna = &cmd->params.antenna; mlan_ds_ant_cfg *ant_cfg = (mlan_ds_ant_cfg *) pdata_buf; + typedef struct _HostCmd_DS_802_11_RF_ANTENNA_1X1 + { + /** Action */ + t_u16 action; + /** Antenna or 0xffff (diversity) */ + t_u16 antenna_mode; + } HostCmd_DS_802_11_RF_ANTENNA_1X1; + HostCmd_DS_802_11_RF_ANTENNA_1X1 *pantenna_1x1 = + (HostCmd_DS_802_11_RF_ANTENNA_1X1 *) & cmd->params.antenna; ENTER(); cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RF_ANTENNA); - cmd->size = - wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_RF_ANTENNA) + S_DS_GEN); + if (!IS_STREAM_2X2(pmpriv->adapter->feature_control)) + cmd->size = + wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_RF_ANTENNA_1X1) + + S_DS_GEN); + else + cmd->size = + wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_RF_ANTENNA) + S_DS_GEN); if (cmd_action == HostCmd_ACT_GEN_SET) { - pantenna->action_tx = wlan_cpu_to_le16(HostCmd_ACT_SET_TX); - pantenna->tx_antenna_mode = - wlan_cpu_to_le16((t_u16) ant_cfg->tx_antenna); - pantenna->action_rx = wlan_cpu_to_le16(HostCmd_ACT_SET_RX); - pantenna->rx_antenna_mode = - wlan_cpu_to_le16((t_u16) ant_cfg->rx_antenna); + if (IS_STREAM_2X2(pmpriv->adapter->feature_control)) { + pantenna->action_tx = wlan_cpu_to_le16(HostCmd_ACT_SET_TX); + pantenna->tx_antenna_mode = + wlan_cpu_to_le16((t_u16) ant_cfg->tx_antenna); + pantenna->action_rx = wlan_cpu_to_le16(HostCmd_ACT_SET_RX); + pantenna->rx_antenna_mode = + wlan_cpu_to_le16((t_u16) ant_cfg->rx_antenna); + } else { + pantenna_1x1->action = wlan_cpu_to_le16(HostCmd_ACT_SET_BOTH); + pantenna_1x1->antenna_mode = wlan_cpu_to_le16(*(t_u16 *) pdata_buf); + } } else { - pantenna->action_tx = wlan_cpu_to_le16(HostCmd_ACT_GET_TX); - pantenna->action_rx = wlan_cpu_to_le16(HostCmd_ACT_GET_RX); + if (IS_STREAM_2X2(pmpriv->adapter->feature_control)) { + pantenna->action_tx = wlan_cpu_to_le16(HostCmd_ACT_GET_TX); + pantenna->action_rx = wlan_cpu_to_le16(HostCmd_ACT_GET_RX); + } else { + pantenna_1x1->action = wlan_cpu_to_le16(HostCmd_ACT_GET_BOTH); + } } LEAVE(); return MLAN_STATUS_SUCCESS; @@ -3044,19 +3483,37 @@ wlan_ret_802_11_rf_antenna(IN pmlan_private pmpriv, HostCmd_DS_802_11_RF_ANTENNA *pantenna = &resp->params.antenna; t_u16 tx_ant_mode = wlan_le16_to_cpu(pantenna->tx_antenna_mode); t_u16 rx_ant_mode = wlan_le16_to_cpu(pantenna->rx_antenna_mode); + typedef struct _HostCmd_DS_802_11_RF_ANTENNA_1X1 + { + /** Action */ + t_u16 action; + /** Antenna or 0xffff (diversity) */ + t_u16 antenna_mode; + } HostCmd_DS_802_11_RF_ANTENNA_1X1; + HostCmd_DS_802_11_RF_ANTENNA_1X1 *pantenna_1x1 = + (HostCmd_DS_802_11_RF_ANTENNA_1X1 *) & resp->params.antenna; + t_u16 ant_mode = wlan_le16_to_cpu(pantenna_1x1->antenna_mode); mlan_ds_radio_cfg *radio = MNULL; ENTER(); - PRINTM(MINFO, "RF_ANT_RESP: Tx action = 0x%x, Tx Mode = 0x%04x" - " Rx action = 0x%x, Rx Mode = 0x%04x\n", - wlan_le16_to_cpu(pantenna->action_tx), tx_ant_mode, - wlan_le16_to_cpu(pantenna->action_rx), rx_ant_mode); + if (IS_STREAM_2X2(pmpriv->adapter->feature_control)) + PRINTM(MINFO, "RF_ANT_RESP: Tx action = 0x%x, Tx Mode = 0x%04x" + " Rx action = 0x%x, Rx Mode = 0x%04x\n", + wlan_le16_to_cpu(pantenna->action_tx), tx_ant_mode, + wlan_le16_to_cpu(pantenna->action_rx), rx_ant_mode); + else + PRINTM(MINFO, "RF_ANT_RESP: action = 0x%x, Mode = 0x%04x\n", + wlan_le16_to_cpu(pantenna_1x1->action), ant_mode); if (pioctl_buf) { radio = (mlan_ds_radio_cfg *) pioctl_buf->pbuf; - radio->param.ant_cfg.tx_antenna = tx_ant_mode; - radio->param.ant_cfg.rx_antenna = rx_ant_mode; + if (IS_STREAM_2X2(pmpriv->adapter->feature_control)) { + radio->param.ant_cfg.tx_antenna = tx_ant_mode; + radio->param.ant_cfg.rx_antenna = rx_ant_mode; + } else { + radio->param.antenna = ant_mode; + } } LEAVE(); @@ -3152,6 +3609,7 @@ wlan_cmd_reg_access(IN HostCmd_DS_COMMAND * cmd, /** * @brief This function handles the command response of reg_access * + * @param pmadapter A pointer to mlan_adapter structure * @param type The type of reg access (MAC, BBP or RF) * @param resp A pointer to HostCmd_DS_COMMAND * @param pioctl_buf A pointer to command buffer diff --git a/drivers/net/wireless/sd8797/mlan/mlan_decl.h b/drivers/net/wireless/sd8797/mlan/mlan_decl.h index ac24b5e79fc4..28ab785045e3 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_decl.h +++ b/drivers/net/wireless/sd8797/mlan/mlan_decl.h @@ -27,11 +27,11 @@ Change log: #define _MLAN_DECL_H_ /** MLAN release version */ -#define MLAN_RELEASE_VERSION "334" +#define MLAN_RELEASE_VERSION "394" /** Re-define generic data types for MLAN/MOAL */ /** Signed char (1-byte) */ -typedef char t_s8; +typedef signed char t_s8; /** Unsigned char (1-byte) */ typedef unsigned char t_u8; /** Signed short (2-bytes) */ @@ -101,6 +101,16 @@ typedef t_s32 t_sval; /** MLAN FALSE */ #define MFALSE (0) +#ifndef MACSTR +/** MAC address security format */ +#define MACSTR "%02x:XX:XX:XX:%02x:%02x" +#endif + +#ifndef MAC2STR +/** MAC address security print arguments */ +#define MAC2STR(a) (a)[0], (a)[4], (a)[5] +#endif + /** Macros for Data Alignment : size */ #define ALIGN_SZ(p, a) \ (((p) + ((a) - 1)) & ~((a) - 1)) @@ -296,26 +306,26 @@ typedef enum _mlan_error_code MLAN_ERROR_NO_ERROR = 0, /** Firmware/device errors below (MSB=0) */ MLAN_ERROR_FW_NOT_READY = 0x00000001, - MLAN_ERROR_FW_BUSY, - MLAN_ERROR_FW_CMDRESP, - MLAN_ERROR_DATA_TX_FAIL, - MLAN_ERROR_DATA_RX_FAIL, + MLAN_ERROR_FW_BUSY = 0x00000002, + MLAN_ERROR_FW_CMDRESP = 0x00000003, + MLAN_ERROR_DATA_TX_FAIL = 0x00000004, + MLAN_ERROR_DATA_RX_FAIL = 0x00000005, /** Driver errors below (MSB=1) */ MLAN_ERROR_PKT_SIZE_INVALID = 0x80000001, - MLAN_ERROR_PKT_TIMEOUT, - MLAN_ERROR_PKT_INVALID, - MLAN_ERROR_CMD_INVALID, - MLAN_ERROR_CMD_TIMEOUT, - MLAN_ERROR_CMD_DNLD_FAIL, - MLAN_ERROR_CMD_CANCEL, - MLAN_ERROR_CMD_RESP_FAIL, - MLAN_ERROR_CMD_ASSOC_FAIL, - MLAN_ERROR_CMD_SCAN_FAIL, - MLAN_ERROR_IOCTL_INVALID, - MLAN_ERROR_IOCTL_FAIL, - MLAN_ERROR_EVENT_UNKNOWN, - MLAN_ERROR_INVALID_PARAMETER, - MLAN_ERROR_NO_MEM, + MLAN_ERROR_PKT_TIMEOUT = 0x80000002, + MLAN_ERROR_PKT_INVALID = 0x80000003, + MLAN_ERROR_CMD_INVALID = 0x80000004, + MLAN_ERROR_CMD_TIMEOUT = 0x80000005, + MLAN_ERROR_CMD_DNLD_FAIL = 0x80000006, + MLAN_ERROR_CMD_CANCEL = 0x80000007, + MLAN_ERROR_CMD_RESP_FAIL = 0x80000008, + MLAN_ERROR_CMD_ASSOC_FAIL = 0x80000009, + MLAN_ERROR_CMD_SCAN_FAIL = 0x8000000A, + MLAN_ERROR_IOCTL_INVALID = 0x8000000B, + MLAN_ERROR_IOCTL_FAIL = 0x8000000C, + MLAN_ERROR_EVENT_UNKNOWN = 0x8000000D, + MLAN_ERROR_INVALID_PARAMETER = 0x8000000E, + MLAN_ERROR_NO_MEM = 0x8000000F, /** More to add */ } mlan_error_code; @@ -365,56 +375,60 @@ typedef enum _mlan_event_id { /* Event generated by firmware (MSB=0) */ MLAN_EVENT_ID_FW_UNKNOWN = 0x00000001, - MLAN_EVENT_ID_FW_ADHOC_LINK_SENSED, - MLAN_EVENT_ID_FW_ADHOC_LINK_LOST, - MLAN_EVENT_ID_FW_DISCONNECTED, - MLAN_EVENT_ID_FW_MIC_ERR_UNI, - MLAN_EVENT_ID_FW_MIC_ERR_MUL, - MLAN_EVENT_ID_FW_BCN_RSSI_LOW, - MLAN_EVENT_ID_FW_BCN_RSSI_HIGH, - MLAN_EVENT_ID_FW_BCN_SNR_LOW, - MLAN_EVENT_ID_FW_BCN_SNR_HIGH, - MLAN_EVENT_ID_FW_MAX_FAIL, - MLAN_EVENT_ID_FW_DATA_RSSI_LOW, - MLAN_EVENT_ID_FW_DATA_RSSI_HIGH, - MLAN_EVENT_ID_FW_DATA_SNR_LOW, - MLAN_EVENT_ID_FW_DATA_SNR_HIGH, - MLAN_EVENT_ID_FW_LINK_QUALITY, - MLAN_EVENT_ID_FW_PORT_RELEASE, - MLAN_EVENT_ID_FW_PRE_BCN_LOST, - MLAN_EVENT_ID_FW_WMM_CONFIG_CHANGE, - MLAN_EVENT_ID_FW_HS_WAKEUP, - MLAN_EVENT_ID_FW_BG_SCAN, - MLAN_EVENT_ID_FW_WEP_ICV_ERR, - MLAN_EVENT_ID_FW_STOP_TX, - MLAN_EVENT_ID_FW_START_TX, - MLAN_EVENT_ID_FW_CHANNEL_SWITCH_ANN, - MLAN_EVENT_ID_FW_RADAR_DETECTED, - MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY, - MLAN_EVENT_ID_FW_BW_CHANGED, + MLAN_EVENT_ID_FW_ADHOC_LINK_SENSED = 0x00000002, + MLAN_EVENT_ID_FW_ADHOC_LINK_LOST = 0x00000003, + MLAN_EVENT_ID_FW_DISCONNECTED = 0x00000004, + MLAN_EVENT_ID_FW_MIC_ERR_UNI = 0x00000005, + MLAN_EVENT_ID_FW_MIC_ERR_MUL = 0x00000006, + MLAN_EVENT_ID_FW_BCN_RSSI_LOW = 0x00000007, + MLAN_EVENT_ID_FW_BCN_RSSI_HIGH = 0x00000008, + MLAN_EVENT_ID_FW_BCN_SNR_LOW = 0x00000009, + MLAN_EVENT_ID_FW_BCN_SNR_HIGH = 0x0000000A, + MLAN_EVENT_ID_FW_MAX_FAIL = 0x0000000B, + MLAN_EVENT_ID_FW_DATA_RSSI_LOW = 0x0000000C, + MLAN_EVENT_ID_FW_DATA_RSSI_HIGH = 0x0000000D, + MLAN_EVENT_ID_FW_DATA_SNR_LOW = 0x0000000E, + MLAN_EVENT_ID_FW_DATA_SNR_HIGH = 0x0000000F, + MLAN_EVENT_ID_FW_LINK_QUALITY = 0x00000010, + MLAN_EVENT_ID_FW_PORT_RELEASE = 0x00000011, + MLAN_EVENT_ID_FW_PRE_BCN_LOST = 0x00000012, + MLAN_EVENT_ID_FW_DEBUG_INFO = 0x00000013, + MLAN_EVENT_ID_FW_WMM_CONFIG_CHANGE = 0x0000001A, + MLAN_EVENT_ID_FW_HS_WAKEUP = 0x0000001B, + MLAN_EVENT_ID_FW_BG_SCAN = 0x0000001D, + MLAN_EVENT_ID_FW_BG_SCAN_STOPPED = 0x0000001E, + MLAN_EVENT_ID_FW_WEP_ICV_ERR = 0x00000020, + MLAN_EVENT_ID_FW_STOP_TX = 0x00000021, + MLAN_EVENT_ID_FW_START_TX = 0x00000022, + MLAN_EVENT_ID_FW_CHANNEL_SWITCH_ANN = 0x00000023, + MLAN_EVENT_ID_FW_RADAR_DETECTED = 0x00000024, + MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY = 0x00000025, + MLAN_EVENT_ID_FW_BW_CHANGED = 0x00000026, #ifdef WIFI_DIRECT_SUPPORT - MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED, + MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED = 0x0000002B, #endif #ifdef UAP_SUPPORT - MLAN_EVENT_ID_UAP_FW_BSS_START, - MLAN_EVENT_ID_UAP_FW_BSS_ACTIVE, - MLAN_EVENT_ID_UAP_FW_BSS_IDLE, - MLAN_EVENT_ID_UAP_FW_STA_CONNECT, - MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT, + MLAN_EVENT_ID_UAP_FW_BSS_START = 0x0000002C, + MLAN_EVENT_ID_UAP_FW_BSS_ACTIVE = 0x0000002D, + MLAN_EVENT_ID_UAP_FW_BSS_IDLE = 0x0000002E, + MLAN_EVENT_ID_UAP_FW_STA_CONNECT = 0x00000030, + MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT = 0x00000031, #endif /* Event generated by MLAN driver (MSB=1) */ MLAN_EVENT_ID_DRV_CONNECTED = 0x80000001, - MLAN_EVENT_ID_DRV_DEFER_HANDLING, - MLAN_EVENT_ID_DRV_HS_ACTIVATED, - MLAN_EVENT_ID_DRV_HS_DEACTIVATED, - MLAN_EVENT_ID_DRV_MGMT_FRAME, - MLAN_EVENT_ID_DRV_OBSS_SCAN_PARAM, - MLAN_EVENT_ID_DRV_PASSTHRU, - MLAN_EVENT_ID_DRV_SCAN_REPORT, - MLAN_EVENT_ID_DRV_MEAS_REPORT, - MLAN_EVENT_ID_DRV_REPORT_STRING, - MLAN_EVENT_ID_DRV_DBG_DUMP, + MLAN_EVENT_ID_DRV_DEFER_HANDLING = 0x80000002, + MLAN_EVENT_ID_DRV_HS_ACTIVATED = 0x80000003, + MLAN_EVENT_ID_DRV_HS_DEACTIVATED = 0x80000004, + MLAN_EVENT_ID_DRV_MGMT_FRAME = 0x80000005, + MLAN_EVENT_ID_DRV_OBSS_SCAN_PARAM = 0x80000006, + MLAN_EVENT_ID_DRV_PASSTHRU = 0x80000007, + MLAN_EVENT_ID_DRV_SCAN_REPORT = 0x80000009, + MLAN_EVENT_ID_DRV_MEAS_REPORT = 0x8000000A, + MLAN_EVENT_ID_DRV_ASSOC_FAILURE_REPORT = 0x8000000B, + MLAN_EVENT_ID_DRV_REPORT_STRING = 0x8000000F, + MLAN_EVENT_ID_DRV_DBG_DUMP = 0x80000012, + MLAN_EVENT_ID_DRV_BGSCAN_RESULT = 0x80000013, } mlan_event_id; /** Data Structures */ @@ -552,6 +566,8 @@ typedef struct _mlan_bss_attr t_u32 bss_priority; /** BSS number */ t_u32 bss_num; + /** The BSS is virtual */ + t_u32 bss_virtual; } mlan_bss_attr, *pmlan_bss_attr; #ifdef PRAGMA_PACK @@ -711,6 +727,7 @@ typedef struct _mlan_callbacks mlan_status(*moal_ioctl_complete) (IN t_void * pmoal_handle, IN pmlan_ioctl_req pioctl_req, IN mlan_status status); + /** moal_alloc_mlan_buffer */ mlan_status(*moal_alloc_mlan_buffer) (IN t_void * pmoal_handle, IN t_u32 size, @@ -738,6 +755,11 @@ typedef struct _mlan_callbacks IN t_u32 size, IN t_u32 flag, OUT t_u8 ** ppbuf); /** moal_mfree */ mlan_status(*moal_mfree) (IN t_void * pmoal_handle, IN t_u8 * pbuf); + /** moal_vmalloc */ + mlan_status(*moal_vmalloc) (IN t_void * pmoal_handle, + IN t_u32 size, OUT t_u8 ** ppbuf); + /** moal_vfree */ + mlan_status(*moal_vfree) (IN t_void * pmoal_handle, IN t_u8 * pbuf); /** moal_memset */ t_void *(*moal_memset) (IN t_void * pmoal_handle, IN t_void * pmem, IN t_u8 byte, IN t_u32 num); @@ -787,7 +809,7 @@ typedef struct _mlan_callbacks IN t_void * plock); /** moal_print */ t_void(*moal_print) (IN t_void * pmoal_handle, - IN t_u32 level, IN t_s8 * pformat, IN ...); + IN t_u32 level, IN char *pformat, IN ...); /** moal_print_netintf */ t_void(*moal_print_netintf) (IN t_void * pmoal_handle, IN t_u32 bss_index, IN t_u32 level); @@ -807,6 +829,14 @@ typedef struct _mlan_callbacks /** Parameter disabled, override MLAN default setting */ #define MLAN_INIT_PARA_DISABLED 2 +/** Control bit for stream 2X2 */ +#define FEATURE_CTRL_STREAM_2X2 MBIT(6) +/** Control bit for DFS support */ +#define FEATURE_CTRL_DFS_SUPPORT MBIT(7) + +/** Default feature control */ +#define FEATURE_CTRL_DEFAULT 0xffffffff + /** mlan_device data structure */ typedef struct _mlan_device { @@ -846,6 +876,8 @@ typedef struct _mlan_device /** 802.11d configuration */ t_u32 cfg_11d; #endif + /** Feature control bitmask */ + t_u32 feature_control; } mlan_device, *pmlan_device; /** MLAN API function prototype */ diff --git a/drivers/net/wireless/sd8797/mlan/mlan_fw.h b/drivers/net/wireless/sd8797/mlan/mlan_fw.h index 8750844eece8..3e2538231e57 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_fw.h +++ b/drivers/net/wireless/sd8797/mlan/mlan_fw.h @@ -146,11 +146,11 @@ typedef enum _KEY_TYPE_ID /** Key type : WEP */ KEY_TYPE_ID_WEP = 0, /** Key type : TKIP */ - KEY_TYPE_ID_TKIP, + KEY_TYPE_ID_TKIP = 1, /** Key type : AES */ - KEY_TYPE_ID_AES, - KEY_TYPE_ID_WAPI, - KEY_TYPE_ID_AES_CMAC, + KEY_TYPE_ID_AES = 2, + KEY_TYPE_ID_WAPI = 3, + KEY_TYPE_ID_AES_CMAC = 4, } KEY_TYPE_ID; /** Key Info flag for multicast key */ @@ -371,6 +371,12 @@ typedef enum _WLAN_802_11_WEP_STATUS /** TLV type: MAX_MGMT_IE */ #define TLV_TYPE_MAX_MGMT_IE (PROPRIETARY_TLV_BASE_ID + 0xaa) // 0x01aa +/** TLV type: key param v2 */ +#define TLV_TYPE_KEY_PARAM_V2 (PROPRIETARY_TLV_BASE_ID + 0x9C) // 0x019C + +/** TLV type: hs wake hold off */ +#define TLV_TYPE_HS_WAKE_HOLDOFF (PROPRIETARY_TLV_BASE_ID + 0xB6) // 0x01b6 + /** TLV type : HT Capabilities */ #define TLV_TYPE_HT_CAP (PROPRIETARY_TLV_BASE_ID + 0x4a) // 0x014a /** TLV type : HT Information */ @@ -606,6 +612,25 @@ typedef enum _WLAN_802_11_WEP_STATUS /** RadioType : Set secondary channel */ #define SET_SECONDARYCHAN(RadioType, SECCHAN) (RadioType |= (SECCHAN << 4)) +/** ExtCap : Support for TDLS */ +#define ISSUPP_EXTCAP_TDLS(ext_cap) (ext_cap.TDLSSupport) +/** ExtCap : Set support TDLS */ +#define SET_EXTCAP_TDLS(ext_cap) (ext_cap.TDLSSupport = 1) +/** ExtCap : Reset support TDLS */ +#define RESET_EXTCAP_TDLS(ext_cap) (ext_cap.TDLSSupport = 0) +/** ExtCap : Support for Interworking */ +#define ISSUPP_EXTCAP_INTERWORKING(ext_cap) (ext_cap.Interworking) +/** ExtCap : Set support Interworking */ +#define SET_EXTCAP_INTERWORKING(ext_cap) (ext_cap.Interworking = 1) +/** ExtCap : Reset support Interworking */ +#define RESET_EXTCAP_INTERWORKING(ext_cap) (ext_cap.Interworking = 0) +/** ExtCap : Support for Operation Mode Notification */ +#define ISSUPP_EXTCAP_OPERMODENTF(ext_cap) (ext_cap.OperModeNtf) +/** ExtCap : Set support Operation Mode Notification */ +#define SET_EXTCAP_OPERMODENTF(ext_cap) (ext_cap.OperModeNtf = 1) +/** ExtCap : Reset support Operation Mode Notification */ +#define RESET_EXTCAP_OPERMODENTF(ext_cap) (ext_cap.OperModeNtf = 0) + /** LLC/SNAP header len */ #define LLC_SNAP_LEN 8 @@ -964,12 +989,12 @@ typedef enum _ENH_PS_MODES /** Buffer Constants */ /** Number of command buffers */ -#define MRVDRV_NUM_OF_CMD_BUFFER 20 +#define MRVDRV_NUM_OF_CMD_BUFFER 30 /** Size of command buffer */ #define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024) /** Maximum number of BSS Descriptors */ -#define MRVDRV_MAX_BSSID_LIST 64 +#define MRVDRV_MAX_BSSID_LIST 128 /** Host command flag in command */ #define CMD_F_HOSTCMD (1 << 0) @@ -1047,6 +1072,8 @@ typedef enum _ENH_PS_MODES /** Card Event definition : BG scan report */ #define EVENT_BG_SCAN_REPORT 0x00000018 +/** Card Event definition : BG scan stopped */ +#define EVENT_BG_SCAN_STOPPED 0x00000065 /** Card Event definition : Beacon RSSI low */ #define EVENT_RSSI_LOW 0x00000019 @@ -1120,6 +1147,9 @@ typedef enum _ENH_PS_MODES /** Event definition: Scan results through event */ #define EVENT_EXT_SCAN_REPORT 0x00000058 +/** Event definition : FW debug information */ +#define EVENT_FW_DEBUG_INFO 0x00000063 + /** Event definition: RXBA_SYNC */ #define EVENT_RXBA_SYNC 0x00000059 @@ -1213,6 +1243,16 @@ typedef MLAN_PACK_START struct _MrvlIEtypes_Data_t t_u8 data[1]; } MLAN_PACK_END MrvlIEtypes_Data_t; +#if defined(STA_SUPPORT) +/** Pairwise Cipher Suite length */ +#define PAIRWISE_CIPHER_SUITE_LEN 4 +/** AKM Suite length */ +#define AKM_SUITE_LEN 4 +/** MFPC bit in RSN capability */ +#define MFPC_BIT 7 +/** MFPR bit in RSN capability */ +#define MFPR_BIT 6 +#endif /** Bit mask for TxPD status field for null packet */ #define MRVDRV_TxPD_POWER_MGMT_NULL_PACKET 0x01 /** Bit mask for TxPD status field for last packet */ @@ -1225,6 +1265,7 @@ typedef MLAN_PACK_START struct _MrvlIEtypes_Data_t #define PKT_TYPE_AMSDU 0xE6 /** Packet type: BAR */ #define PKT_TYPE_BAR 0xE7 + /** Packet type: debugging */ #define PKT_TYPE_DEBUG 0xEF @@ -1746,38 +1787,112 @@ typedef MLAN_PACK_START struct _MrvlIEtypes_RsnParamSet_t t_u8 rsn_ie[1]; } MLAN_PACK_END MrvlIEtypes_RsnParamSet_t; -/** Key_param_set fixed length */ -#define KEYPARAMSET_FIXED_LEN 6 - +/** Key Info flag for multicast key */ +#define KEY_INFO_MCAST_KEY 0x01 +/** Key Info flag for unicast key */ +#define KEY_INFO_UCAST_KEY 0x02 +/** Key Info flag for enable key */ +#define KEY_INFO_ENABLE_KEY 0x04 +/** Key Info flag for default key */ +#define KEY_INFO_DEFAULT_KEY 0x08 +/** Key Info flag for TX key */ +#define KEY_INFO_TX_KEY 0x10 +/** Key Info flag for RX key */ +#define KEY_INFO_RX_KEY 0x20 +#define KEY_INFO_CMAC_AES_KEY 0x400 +/** PN size for WPA/WPA2 */ +#define WPA_PN_SIZE 8 /** PN size for PMF IGTK */ #define IGTK_PN_SIZE 8 -/** WPA AES IGTK key length */ -#define CMAC_AES_KEY_LEN 16 +/** WAPI KEY size */ +#define WAPI_KEY_SIZE 32 +/** key params fix size */ +#define KEY_PARAMS_FIXED_LEN 10 +/** key index mask */ +#define KEY_INDEX_MASK 0xf + +/** wep_param */ +typedef MLAN_PACK_START struct _wep_param_t +{ + /** key_len */ + t_u16 key_len; + /** wep key */ + t_u8 key[MAX_WEP_KEY_SIZE]; +} MLAN_PACK_END wep_param_t; + +/** tkip_param */ +typedef MLAN_PACK_START struct _tkip_param +{ + /** Rx packet num */ + t_u8 pn[WPA_PN_SIZE]; + /** key_len */ + t_u16 key_len; + /** tkip key */ + t_u8 key[WPA_TKIP_KEY_LEN]; +} MLAN_PACK_END tkip_param; + +/** aes_param */ +typedef MLAN_PACK_START struct _aes_param +{ + /** Rx packet num */ + t_u8 pn[WPA_PN_SIZE]; + /** key_len */ + t_u16 key_len; + /** aes key */ + t_u8 key[WPA_AES_KEY_LEN]; +} MLAN_PACK_END aes_param; + +/** wapi_param */ +typedef MLAN_PACK_START struct _wapi_param +{ + /** Rx packet num */ + t_u8 pn[PN_SIZE]; + /** key_len */ + t_u16 key_len; + /** wapi key */ + t_u8 key[WAPI_KEY_SIZE]; +} MLAN_PACK_END wapi_param; + /** cmac_aes_param */ -typedef MLAN_PACK_START struct _cmac_param +typedef MLAN_PACK_START struct _cmac_aes_param { /** IGTK pn */ t_u8 ipn[IGTK_PN_SIZE]; + /** key_len */ + t_u16 key_len; /** aes key */ t_u8 key[CMAC_AES_KEY_LEN]; -} MLAN_PACK_END cmac_param; +} MLAN_PACK_END cmac_aes_param; /** MrvlIEtype_KeyParamSet_t */ -typedef MLAN_PACK_START struct _MrvlIEtype_KeyParamSet_t +typedef MLAN_PACK_START struct _MrvlIEtype_KeyParamSetV2_t { /** Type ID */ t_u16 type; /** Length of Payload */ t_u16 length; - /** Type of Key: WEP=0, TKIP=1, AES=2 WAPI=3 AES_CMAC=4 */ - t_u16 key_type_id; + /** mac address */ + t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH]; + /** key index */ + t_u8 key_idx; + /** Type of Key: WEP=0, TKIP=1, AES=2, WAPI=3 AES_CMAC=4 */ + t_u8 key_type; /** Key Control Info specific to a key_type_id */ t_u16 key_info; - /** Length of key */ - t_u16 key_len; - /** Key material of size key_len */ - t_u8 key[50]; -} MLAN_PACK_END MrvlIEtype_KeyParamSet_t; + union + { + /** wep key param */ + wep_param_t wep; + /** tkip key param */ + tkip_param tkip; + /** aes key param */ + aes_param aes; + /** wapi key param */ + wapi_param wapi; + /** IGTK key param */ + cmac_aes_param cmac_aes; + } key_params; +} MLAN_PACK_END MrvlIEtype_KeyParamSetV2_t; /** HostCmd_DS_802_11_KEY_MATERIAL */ typedef MLAN_PACK_START struct _HostCmd_DS_802_11_KEY_MATERIAL @@ -1785,7 +1900,7 @@ typedef MLAN_PACK_START struct _HostCmd_DS_802_11_KEY_MATERIAL /** Action */ t_u16 action; /** Key parameter set */ - MrvlIEtype_KeyParamSet_t key_param_set; + MrvlIEtype_KeyParamSetV2_t key_param_set; } MLAN_PACK_END HostCmd_DS_802_11_KEY_MATERIAL; /** Data structure of WMM QoS information */ @@ -2183,9 +2298,7 @@ typedef MLAN_PACK_START struct _HostCmd_DS_802_11_MAC_ADDRESS typedef MLAN_PACK_START struct _HostCmd_DS_MAC_CONTROL { /** Action */ - t_u16 action; - /** Reserved field */ - t_u16 reserved; + t_u32 action; } MLAN_PACK_END HostCmd_DS_MAC_CONTROL; /** HostCmd_DS_CMD_TX_DATA_PAUSE */ @@ -2411,6 +2524,10 @@ typedef MLAN_PACK_START struct _HostCmd_DS_802_11_GET_LOG t_u32 reserved; /** Number of WEP icv error for each key */ t_u32 wep_icv_err_cnt[4]; + /** Beacon received count */ + t_u32 bcn_rcv_cnt; + /** Beacon missed count */ + t_u32 bcn_miss_cnt; } MLAN_PACK_END HostCmd_DS_802_11_GET_LOG; /**_HostCmd_TX_RATE_QUERY */ @@ -3657,6 +3774,15 @@ typedef MLAN_PACK_START struct _HostCmd_DS_HS_WAKEUP_REASON t_u16 wakeup_reason; } MLAN_PACK_END HostCmd_DS_HS_WAKEUP_REASON; +/** MrvlIEtypes_HsWakeHoldoff_t */ +typedef MLAN_PACK_START struct _MrvlIEtypes_HsWakeHoldoff_t +{ + /** Header */ + MrvlIEtypesHeader_t header; + /** Minimum delay between HsActive and HostWake (in msec) */ + t_u16 min_wake_holdoff; +} MLAN_PACK_END MrvlIEtypes_HsWakeHoldoff_t; + /** HostCmd_DS_INACTIVITY_TIMEOUT_EXT */ typedef MLAN_PACK_START struct _HostCmd_DS_INACTIVITY_TIMEOUT_EXT { diff --git a/drivers/net/wireless/sd8797/mlan/mlan_ieee.h b/drivers/net/wireless/sd8797/mlan/mlan_ieee.h index 976f1c7013a4..c11c911466e6 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_ieee.h +++ b/drivers/net/wireless/sd8797/mlan/mlan_ieee.h @@ -155,6 +155,15 @@ typedef MLAN_PACK_START struct _IEEEtypes_Generic_t } MLAN_PACK_END IEEEtypes_Generic_t, *pIEEEtypes_Generic_t; +/** TLV header */ +typedef MLAN_PACK_START struct _TLV_Generic_t +{ + /** Type */ + t_u16 type; + /** Length */ + t_u16 len; +} MLAN_PACK_END TLV_Generic_t, *pTLV_Generic_t; + /** Capability information mask */ #define CAPINFO_MASK (~(MBIT(15) | MBIT(14) | \ MBIT(12) | MBIT(11) | MBIT(9))) @@ -305,6 +314,8 @@ typedef t_u16 IEEEtypes_AId_t; /** IEEEtypes_StatusCode_t */ typedef t_u16 IEEEtypes_StatusCode_t; +/** Fixed size in assoc_resp */ +#define ASSOC_RESP_FIXED_SIZE 6 /** IEEEtypes_AssocRsp_t */ typedef MLAN_PACK_START struct _IEEEtypes_AssocRsp_t { @@ -329,6 +340,20 @@ typedef t_u8 WLAN_802_11_RATES[WLAN_SUPPORTED_RATES]; #define RSN_AKM_8021X 1 /** AKM: PSK */ #define RSN_AKM_PSK 2 +/** AKM: PSK SHA256 */ +#define RSN_AKM_PSK_SHA256 6 +#if defined(STA_SUPPORT) +/** Pairwise Cipher Suite length */ +#define PAIRWISE_CIPHER_SUITE_LEN 4 +/** AKM Suite length */ +#define AKM_SUITE_LEN 4 +/** MFPC bit in RSN capability */ +#define MFPC_BIT 7 +/** MFPR bit in RSN capability */ +#define MFPR_BIT 6 +/** PMF ORing mask */ +#define PMF_MASK 0x00c0 +#endif /** wpa_suite_t */ typedef MLAN_PACK_START struct _wpa_suite_t @@ -800,12 +825,147 @@ typedef struct MLAN_PACK_START _BSSCo2040_t t_u8 bss_co_2040_value; } MLAN_PACK_END BSSCo2040_t, *pBSSCo2040_t; +#ifdef BIG_ENDIAN_SUPPORT +/** Extended Capabilities Data */ +typedef struct MLAN_PACK_START _ExtCap_t +{ + /** Extended Capabilities value */ + t_u8 rsvdBit63:1; /* bit 63 */ + t_u8 OperModeNtf:1; /* bit 62 */ + t_u8 TDLSWildBandwidth:1; /* bit 61 */ + t_u8 rsvdBit60:1; /* bit 60 */ + t_u8 rsvdBit59:1; /* bit 59 */ + t_u8 rsvdBit58:1; /* bit 58 */ + t_u8 rsvdBit57:1; /* bit 57 */ + t_u8 rsvdBit56:1; /* bit 56 */ + t_u8 rsvdBit55:1; /* bit 55 */ + t_u8 rsvdBit54:1; /* bit 54 */ + t_u8 rsvdBit53:1; /* bit 53 */ + t_u8 rsvdBit52:1; /* bit 52 */ + t_u8 rsvdBit51:1; /* bit 51 */ + t_u8 rsvdBit50:1; /* bit 50 */ + t_u8 rsvdBit49:1; /* bit 49 */ + t_u8 rsvdBit48:1; /* bit 48 */ + t_u8 rsvdBit47:1; /* bit 47 */ + t_u8 rsvdBit46:1; /* bit 46 */ + t_u8 rsvdBit45:1; /* bit 45 */ + t_u8 rsvdBit44:1; /* bit 44 */ + t_u8 rsvdBit43:1; /* bit 43 */ + t_u8 rsvdBit42:1; /* bit 42 */ + t_u8 rsvdBit41:1; /* bit 41 */ + t_u8 rsvdBit40:1; /* bit 40 */ + t_u8 TDLSChlSwitchProhib:1; /* bit 39 */ + t_u8 TDLSProhibited:1; /* bit 38 */ + t_u8 TDLSSupport:1; /* bit 37 */ + t_u8 MSGCF_Capa:1; /* bit 36 */ + t_u8 Reserved35:1; /* bit 35 */ + t_u8 SSPN_Interface:1; /* bit 34 */ + t_u8 EBR:1; /* bit 33 */ + t_u8 Qos_Map:1; /* bit 32 */ + t_u8 Interworking:1; /* bit 31 */ + t_u8 TDLSChannelSwitching:1; /* bit 30 */ + t_u8 TDLSPeerPSMSupport:1; /* bit 29 */ + t_u8 TDLSPeerUAPSDSupport:1; /* bit 28 */ + t_u8 UTC:1; /* bit 27 */ + t_u8 DMS:1; /* bit 26 */ + t_u8 SSID_List:1; /* bit 25 */ + t_u8 ChannelUsage:1; /* bit 24 */ + t_u8 TimingMeasurement:1; /* bit 23 */ + t_u8 MultipleBSSID:1; /* bit 22 */ + t_u8 AC_StationCount:1; /* bit 21 */ + t_u8 QoSTrafficCap:1; /* bit 20 */ + t_u8 BSS_Transition:1; /* bit 19 */ + t_u8 TIM_Broadcast:1; /* bit 18 */ + t_u8 WNM_Sleep:1; /* bit 17 */ + t_u8 TFS:1; /* bit 16 */ + t_u8 GeospatialLocation:1; /* bit 15 */ + t_u8 CivicLocation:1; /* bit 14 */ + t_u8 CollocatedIntf:1; /* bit 13 */ + t_u8 ProxyARPService:1; /* bit 12 */ + t_u8 FMS:1; /* bit 11 */ + t_u8 LocationTracking:1; /* bit 10 */ + t_u8 MulticastDiagnostics:1; /* bit 9 */ + t_u8 Diagnostics:1; /* bit 8 */ + t_u8 Event:1; /* bit 7 */ + t_u8 SPSMP_Support:1; /* bit 6 */ + t_u8 Reserved5:1; /* bit 5 */ + t_u8 PSMP_Capable:1; /* bit 4 */ + t_u8 RejectUnadmFrame:1; /* bit 3 */ + t_u8 ExtChanSwitching:1; /* bit 2 */ + t_u8 Reserved1:1; /* bit 1 */ + t_u8 BSS_CoexistSupport:1; /* bit 0 */ +} MLAN_PACK_END ExtCap_t, *pExtCap_t; +#else /** Extended Capabilities Data */ typedef struct MLAN_PACK_START _ExtCap_t { /** Extended Capabilities value */ - t_u8 ext_cap_value; + t_u8 BSS_CoexistSupport:1; /* bit 0 */ + t_u8 Reserved1:1; /* bit 1 */ + t_u8 ExtChanSwitching:1; /* bit 2 */ + t_u8 RejectUnadmFrame:1; /* bit 3 */ + t_u8 PSMP_Capable:1; /* bit 4 */ + t_u8 Reserved5:1; /* bit 5 */ + t_u8 SPSMP_Support:1; /* bit 6 */ + t_u8 Event:1; /* bit 7 */ + t_u8 Diagnostics:1; /* bit 8 */ + t_u8 MulticastDiagnostics:1; /* bit 9 */ + t_u8 LocationTracking:1; /* bit 10 */ + t_u8 FMS:1; /* bit 11 */ + t_u8 ProxyARPService:1; /* bit 12 */ + t_u8 CollocatedIntf:1; /* bit 13 */ + t_u8 CivicLocation:1; /* bit 14 */ + t_u8 GeospatialLocation:1; /* bit 15 */ + t_u8 TFS:1; /* bit 16 */ + t_u8 WNM_Sleep:1; /* bit 17 */ + t_u8 TIM_Broadcast:1; /* bit 18 */ + t_u8 BSS_Transition:1; /* bit 19 */ + t_u8 QoSTrafficCap:1; /* bit 20 */ + t_u8 AC_StationCount:1; /* bit 21 */ + t_u8 MultipleBSSID:1; /* bit 22 */ + t_u8 TimingMeasurement:1; /* bit 23 */ + t_u8 ChannelUsage:1; /* bit 24 */ + t_u8 SSID_List:1; /* bit 25 */ + t_u8 DMS:1; /* bit 26 */ + t_u8 UTC:1; /* bit 27 */ + t_u8 TDLSPeerUAPSDSupport:1; /* bit 28 */ + t_u8 TDLSPeerPSMSupport:1; /* bit 29 */ + t_u8 TDLSChannelSwitching:1; /* bit 30 */ + t_u8 Interworking:1; /* bit 31 */ + t_u8 Qos_Map:1; /* bit 32 */ + t_u8 EBR:1; /* bit 33 */ + t_u8 SSPN_Interface:1; /* bit 34 */ + t_u8 Reserved35:1; /* bit 35 */ + t_u8 MSGCF_Capa:1; /* bit 36 */ + t_u8 TDLSSupport:1; /* bit 37 */ + t_u8 TDLSProhibited:1; /* bit 38 */ + t_u8 TDLSChlSwitchProhib:1; /* bit 39 */ + t_u8 rsvdBit40:1; /* bit 40 */ + t_u8 rsvdBit41:1; /* bit 41 */ + t_u8 rsvdBit42:1; /* bit 42 */ + t_u8 rsvdBit43:1; /* bit 43 */ + t_u8 rsvdBit44:1; /* bit 44 */ + t_u8 rsvdBit45:1; /* bit 45 */ + t_u8 rsvdBit46:1; /* bit 46 */ + t_u8 rsvdBit47:1; /* bit 47 */ + t_u8 rsvdBit48:1; /* bit 48 */ + t_u8 rsvdBit49:1; /* bit 49 */ + t_u8 rsvdBit50:1; /* bit 50 */ + t_u8 rsvdBit51:1; /* bit 51 */ + t_u8 rsvdBit52:1; /* bit 52 */ + t_u8 rsvdBit53:1; /* bit 53 */ + t_u8 rsvdBit54:1; /* bit 54 */ + t_u8 rsvdBit55:1; /* bit 55 */ + t_u8 rsvdBit56:1; /* bit 56 */ + t_u8 rsvdBit57:1; /* bit 57 */ + t_u8 rsvdBit58:1; /* bit 58 */ + t_u8 rsvdBit59:1; /* bit 59 */ + t_u8 rsvdBit60:1; /* bit 60 */ + t_u8 TDLSWildBandwidth:1; /* bit 61 */ + t_u8 OperModeNtf:1; /* bit 62 */ + t_u8 rsvdBit63:1; /* bit 63 */ } MLAN_PACK_END ExtCap_t, *pExtCap_t; +#endif /** Overlapping BSS Scan Parameters Data */ typedef struct MLAN_PACK_START _OverlapBSSScanParam_t @@ -1149,7 +1309,7 @@ typedef MLAN_PACK_START struct /** ssid match and RSSI exceeded */ #define BG_SCAN_SSID_RSSI_MATCH 0x0004 /** Maximum number of channels that can be sent in bg scan config */ -#define WLAN_BG_SCAN_CHAN_MAX 32 +#define WLAN_BG_SCAN_CHAN_MAX 38 /** * Input structure to configure bs scan cmd to firmware diff --git a/drivers/net/wireless/sd8797/mlan/mlan_init.c b/drivers/net/wireless/sd8797/mlan/mlan_init.c index 33357e3d75f9..09628b3fc683 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_init.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_init.c @@ -169,10 +169,15 @@ wlan_allocate_adapter(pmlan_adapter pmadapter) #ifdef STA_SUPPORT /* Allocate buffer to store the BSSID list */ buf_size = sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST; - ret = - pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle, buf_size, - MLAN_MEM_DEF, - (t_u8 **) & ptemp_scan_table); + if (pmadapter->callbacks.moal_vmalloc && pmadapter->callbacks.moal_vfree) + ret = + pmadapter->callbacks.moal_vmalloc(pmadapter->pmoal_handle, buf_size, + (t_u8 **) & ptemp_scan_table); + else + ret = + pmadapter->callbacks.moal_malloc(pmadapter->pmoal_handle, buf_size, + MLAN_MEM_DEF, + (t_u8 **) & ptemp_scan_table); if (ret != MLAN_STATUS_SUCCESS || !ptemp_scan_table) { PRINTM(MERROR, "Failed to allocate scan table\n"); LEAVE(); @@ -281,7 +286,7 @@ wlan_init_priv(pmlan_private priv) wlan_11d_priv_init(priv); wlan_11h_priv_init(priv); -#if defined(UAP_SUPPORT) +#ifdef UAP_SUPPORT priv->uap_bss_started = MFALSE; memset(pmadapter, &priv->uap_state_chan_cb, 0, sizeof(priv->uap_state_chan_cb)); @@ -320,6 +325,10 @@ wlan_init_priv(pmlan_private priv) memset(pmadapter, &priv->aes_key, 0, sizeof(priv->aes_key)); priv->wpa_ie_len = 0; priv->wpa_is_gtk_set = MFALSE; +#if defined(STA_SUPPORT) + priv->pmfcfg.mfpc = 0; + priv->pmfcfg.mfpr = 0; +#endif priv->sec_info.wapi_enabled = MFALSE; priv->wapi_ie_len = 0; priv->sec_info.wapi_key_on = MFALSE; @@ -336,6 +345,7 @@ wlan_init_priv(pmlan_private priv) #ifdef STA_SUPPORT priv->pcurr_bcn_buf = MNULL; priv->curr_bcn_size = 0; + memset(pmadapter, &priv->ext_cap, 0, sizeof(priv->ext_cap)); #endif /* STA_SUPPORT */ for (i = 0; i < MAX_NUM_TID; i++) @@ -367,7 +377,6 @@ t_void wlan_init_adapter(pmlan_adapter pmadapter) { opt_sleep_confirm_buffer *sleep_cfm_buf = MNULL; - ENTER(); sleep_cfm_buf = (opt_sleep_confirm_buffer *) (pmadapter->psleep_cfm->pbuf + @@ -508,6 +517,7 @@ wlan_init_adapter(pmlan_adapter pmadapter) pmadapter->hs_cfg.gpio = HOST_SLEEP_DEF_GPIO; pmadapter->hs_cfg.gap = HOST_SLEEP_DEF_GAP; pmadapter->hs_activated = MFALSE; + pmadapter->min_wake_holdoff = HOST_SLEEP_DEF_WAKE_HOLDOFF; memset(pmadapter, pmadapter->event_body, 0, sizeof(pmadapter->event_body)); pmadapter->hw_dot_11n_dev_cap = 0; @@ -526,7 +536,7 @@ wlan_init_adapter(pmlan_adapter pmadapter) wlan_11h_init(pmadapter); wlan_wmm_init(pmadapter); - + pmadapter->bypass_pkt_count = 0; if (pmadapter->psleep_cfm) { pmadapter->psleep_cfm->buf_type = MLAN_BUF_TYPE_CMD; pmadapter->psleep_cfm->data_len = sizeof(OPT_Confirm_Sleep); @@ -642,10 +652,6 @@ wlan_init_lock_list(IN pmlan_adapter pmadapter) } } - /* Initialize bypass_txq */ - util_init_list_head((t_void *) pmadapter->pmoal_handle, - &pmadapter->bypass_txq, MTRUE, - pmadapter->callbacks.moal_init_lock); /* Initialize cmd_free_q */ util_init_list_head((t_void *) pmadapter->pmoal_handle, &pmadapter->cmd_free_q, MTRUE, @@ -691,6 +697,10 @@ wlan_init_lock_list(IN pmlan_adapter pmadapter) util_init_list_head((t_void *) pmadapter->pmoal_handle, &priv->sta_list, MTRUE, pmadapter->callbacks.moal_init_lock); + /* Initialize bypass_txq */ + util_init_list_head((t_void *) pmadapter->pmoal_handle, + &priv->bypass_txq, MTRUE, + pmadapter->callbacks.moal_init_lock); } } @@ -745,9 +755,6 @@ wlan_free_lock_list(IN pmlan_adapter pmadapter) /* Free lists */ util_free_list_head((t_void *) pmadapter->pmoal_handle, - &pmadapter->bypass_txq, - pmadapter->callbacks.moal_free_lock); - util_free_list_head((t_void *) pmadapter->pmoal_handle, &pmadapter->cmd_free_q, pmadapter->callbacks.moal_free_lock); @@ -770,6 +777,9 @@ wlan_free_lock_list(IN pmlan_adapter pmadapter) util_free_list_head((t_void *) pmadapter->pmoal_handle, &priv->sta_list, priv->adapter->callbacks.moal_free_lock); + util_free_list_head((t_void *) pmadapter->pmoal_handle, + &priv->bypass_txq, + pmadapter->callbacks.moal_free_lock); for (j = 0; j < MAX_NUM_TID; ++j) util_free_list_head((t_void *) priv->adapter->pmoal_handle, @@ -808,7 +818,6 @@ wlan_init_timer(IN pmlan_adapter pmadapter) { mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_callbacks pcb = &pmadapter->callbacks; - ENTER(); if (pcb-> @@ -835,7 +844,6 @@ t_void wlan_free_timer(IN pmlan_adapter pmadapter) { pmlan_callbacks pcb = &pmadapter->callbacks; - ENTER(); if (pmadapter->pmlan_cmd_timer) @@ -917,7 +925,6 @@ t_void wlan_free_adapter(pmlan_adapter pmadapter) { mlan_callbacks *pcb = (mlan_callbacks *) & pmadapter->callbacks; - ENTER(); if (!pmadapter) { @@ -940,8 +947,12 @@ wlan_free_adapter(pmlan_adapter pmadapter) #ifdef STA_SUPPORT PRINTM(MINFO, "Free ScanTable\n"); if (pmadapter->pscan_table) { - pcb->moal_mfree(pmadapter->pmoal_handle, - (t_u8 *) pmadapter->pscan_table); + if (pcb->moal_vmalloc && pcb->moal_vfree) { + pcb->moal_vfree(pmadapter->pmoal_handle, + (t_u8 *) pmadapter->pscan_table); + } else + pcb->moal_mfree(pmadapter->pmoal_handle, + (t_u8 *) pmadapter->pscan_table); pmadapter->pscan_table = MNULL; } if (pmadapter->bcn_buf) { diff --git a/drivers/net/wireless/sd8797/mlan/mlan_ioctl.h b/drivers/net/wireless/sd8797/mlan/mlan_ioctl.h index 7cfc344bf0d4..606d161737f9 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_ioctl.h +++ b/drivers/net/wireless/sd8797/mlan/mlan_ioctl.h @@ -31,196 +31,204 @@ enum _mlan_ioctl_req_id { /* Scan Group */ MLAN_IOCTL_SCAN = 0x00010000, - MLAN_OID_SCAN_NORMAL, - MLAN_OID_SCAN_SPECIFIC_SSID, - MLAN_OID_SCAN_USER_CONFIG, - MLAN_OID_SCAN_CONFIG, - MLAN_OID_SCAN_GET_CURRENT_BSS, - MLAN_OID_SCAN_CANCEL, - MLAN_OID_SCAN_TABLE_FLUSH, - MLAN_OID_SCAN_BGSCAN_CONFIG, + MLAN_OID_SCAN_NORMAL = 0x00010001, + MLAN_OID_SCAN_SPECIFIC_SSID = 0x00010002, + MLAN_OID_SCAN_USER_CONFIG = 0x00010003, + MLAN_OID_SCAN_CONFIG = 0x00010004, + MLAN_OID_SCAN_GET_CURRENT_BSS = 0x00010005, + MLAN_OID_SCAN_CANCEL = 0x00010006, + MLAN_OID_SCAN_TABLE_FLUSH = 0x0001000A, + MLAN_OID_SCAN_BGSCAN_CONFIG = 0x0001000B, /* BSS Configuration Group */ MLAN_IOCTL_BSS = 0x00020000, - MLAN_OID_BSS_START, - MLAN_OID_BSS_STOP, - MLAN_OID_BSS_MODE, - MLAN_OID_BSS_CHANNEL, - MLAN_OID_BSS_CHANNEL_LIST, - MLAN_OID_BSS_MAC_ADDR, - MLAN_OID_BSS_MULTICAST_LIST, - MLAN_OID_BSS_FIND_BSS, - MLAN_OID_IBSS_BCN_INTERVAL, - MLAN_OID_IBSS_ATIM_WINDOW, - MLAN_OID_IBSS_CHANNEL, + MLAN_OID_BSS_START = 0x00020001, + MLAN_OID_BSS_STOP = 0x00020002, + MLAN_OID_BSS_MODE = 0x00020003, + MLAN_OID_BSS_CHANNEL = 0x00020004, + MLAN_OID_BSS_CHANNEL_LIST = 0x00020005, + MLAN_OID_BSS_MAC_ADDR = 0x00020006, + MLAN_OID_BSS_MULTICAST_LIST = 0x00020007, + MLAN_OID_BSS_FIND_BSS = 0x00020008, + MLAN_OID_IBSS_BCN_INTERVAL = 0x00020009, + MLAN_OID_IBSS_ATIM_WINDOW = 0x0002000A, + MLAN_OID_IBSS_CHANNEL = 0x0002000B, #ifdef UAP_SUPPORT - MLAN_OID_UAP_BSS_CONFIG, - MLAN_OID_UAP_DEAUTH_STA, - MLAN_OID_UAP_BSS_RESET, + MLAN_OID_UAP_BSS_CONFIG = 0x0002000C, + MLAN_OID_UAP_DEAUTH_STA = 0x0002000D, + MLAN_OID_UAP_BSS_RESET = 0x0002000E, #endif #if defined(STA_SUPPORT) && defined(UAP_SUPPORT) - MLAN_OID_BSS_ROLE, + MLAN_OID_BSS_ROLE = 0x0002000F, #endif #ifdef WIFI_DIRECT_SUPPORT - MLAN_OID_WIFI_DIRECT_MODE, + MLAN_OID_WIFI_DIRECT_MODE = 0x00020010, #endif #ifdef STA_SUPPORT - MLAN_OID_BSS_LISTEN_INTERVAL, + MLAN_OID_BSS_LISTEN_INTERVAL = 0x00020011, #endif + MLAN_OID_BSS_REMOVE = 0x00020014, /* Radio Configuration Group */ MLAN_IOCTL_RADIO_CFG = 0x00030000, - MLAN_OID_RADIO_CTRL, - MLAN_OID_BAND_CFG, - MLAN_OID_ANT_CFG, + MLAN_OID_RADIO_CTRL = 0x00030001, + MLAN_OID_BAND_CFG = 0x00030002, + MLAN_OID_ANT_CFG = 0x00030003, #ifdef WIFI_DIRECT_SUPPORT - MLAN_OID_REMAIN_CHAN_CFG, + MLAN_OID_REMAIN_CHAN_CFG = 0x00030004, #endif /* SNMP MIB Group */ MLAN_IOCTL_SNMP_MIB = 0x00040000, - MLAN_OID_SNMP_MIB_RTS_THRESHOLD, - MLAN_OID_SNMP_MIB_FRAG_THRESHOLD, - MLAN_OID_SNMP_MIB_RETRY_COUNT, + MLAN_OID_SNMP_MIB_RTS_THRESHOLD = 0x00040001, + MLAN_OID_SNMP_MIB_FRAG_THRESHOLD = 0x00040002, + MLAN_OID_SNMP_MIB_RETRY_COUNT = 0x00040003, #if defined(UAP_SUPPORT) - MLAN_OID_SNMP_MIB_DOT11D, - MLAN_OID_SNMP_MIB_DOT11H, + MLAN_OID_SNMP_MIB_DOT11D = 0x00040004, + MLAN_OID_SNMP_MIB_DOT11H = 0x00040005, #endif - MLAN_OID_SNMP_MIB_DTIM_PERIOD, + MLAN_OID_SNMP_MIB_DTIM_PERIOD = 0x00040006, /* Status Information Group */ MLAN_IOCTL_GET_INFO = 0x00050000, - MLAN_OID_GET_STATS, - MLAN_OID_GET_SIGNAL, - MLAN_OID_GET_FW_INFO, - MLAN_OID_GET_VER_EXT, - MLAN_OID_GET_BSS_INFO, - MLAN_OID_GET_DEBUG_INFO, + MLAN_OID_GET_STATS = 0x00050001, + MLAN_OID_GET_SIGNAL = 0x00050002, + MLAN_OID_GET_FW_INFO = 0x00050003, + MLAN_OID_GET_VER_EXT = 0x00050004, + MLAN_OID_GET_BSS_INFO = 0x00050005, + MLAN_OID_GET_DEBUG_INFO = 0x00050006, #ifdef UAP_SUPPORT - MLAN_OID_UAP_STA_LIST, + MLAN_OID_UAP_STA_LIST = 0x00050007, #endif /* Security Configuration Group */ MLAN_IOCTL_SEC_CFG = 0x00060000, - MLAN_OID_SEC_CFG_AUTH_MODE, - MLAN_OID_SEC_CFG_ENCRYPT_MODE, - MLAN_OID_SEC_CFG_WPA_ENABLED, - MLAN_OID_SEC_CFG_ENCRYPT_KEY, - MLAN_OID_SEC_CFG_PASSPHRASE, - MLAN_OID_SEC_CFG_EWPA_ENABLED, - MLAN_OID_SEC_CFG_ESUPP_MODE, - MLAN_OID_SEC_CFG_WAPI_ENABLED, - MLAN_OID_SEC_CFG_PORT_CTRL_ENABLED, + MLAN_OID_SEC_CFG_AUTH_MODE = 0x00060001, + MLAN_OID_SEC_CFG_ENCRYPT_MODE = 0x00060002, + MLAN_OID_SEC_CFG_WPA_ENABLED = 0x00060003, + MLAN_OID_SEC_CFG_ENCRYPT_KEY = 0x00060004, + MLAN_OID_SEC_CFG_PASSPHRASE = 0x00060005, + MLAN_OID_SEC_CFG_EWPA_ENABLED = 0x00060006, + MLAN_OID_SEC_CFG_ESUPP_MODE = 0x00060007, + MLAN_OID_SEC_CFG_WAPI_ENABLED = 0x00060009, + MLAN_OID_SEC_CFG_PORT_CTRL_ENABLED = 0x0006000A, /* Rate Group */ MLAN_IOCTL_RATE = 0x00070000, - MLAN_OID_RATE_CFG, - MLAN_OID_GET_DATA_RATE, - MLAN_OID_SUPPORTED_RATES, + MLAN_OID_RATE_CFG = 0x00070001, + MLAN_OID_GET_DATA_RATE = 0x00070002, + MLAN_OID_SUPPORTED_RATES = 0x00070003, /* Power Configuration Group */ MLAN_IOCTL_POWER_CFG = 0x00080000, - MLAN_OID_POWER_CFG, - MLAN_OID_POWER_CFG_EXT, + MLAN_OID_POWER_CFG = 0x00080001, + MLAN_OID_POWER_CFG_EXT = 0x00080002, /* Power Management Configuration Group */ MLAN_IOCTL_PM_CFG = 0x00090000, - MLAN_OID_PM_CFG_IEEE_PS, - MLAN_OID_PM_CFG_HS_CFG, - MLAN_OID_PM_CFG_INACTIVITY_TO, - MLAN_OID_PM_CFG_DEEP_SLEEP, - MLAN_OID_PM_CFG_SLEEP_PD, - MLAN_OID_PM_CFG_PS_CFG, - MLAN_OID_PM_CFG_SLEEP_PARAMS, + MLAN_OID_PM_CFG_IEEE_PS = 0x00090001, + MLAN_OID_PM_CFG_HS_CFG = 0x00090002, + MLAN_OID_PM_CFG_INACTIVITY_TO = 0x00090003, + MLAN_OID_PM_CFG_DEEP_SLEEP = 0x00090004, + MLAN_OID_PM_CFG_SLEEP_PD = 0x00090005, + MLAN_OID_PM_CFG_PS_CFG = 0x00090006, + MLAN_OID_PM_CFG_SLEEP_PARAMS = 0x00090008, #ifdef UAP_SUPPORT - MLAN_OID_PM_CFG_PS_MODE, + MLAN_OID_PM_CFG_PS_MODE = 0x00090009, #endif /* UAP_SUPPORT */ - MLAN_OID_PM_INFO, - MLAN_OID_PM_HS_WAKEUP_REASON, + MLAN_OID_PM_INFO = 0x0009000A, + MLAN_OID_PM_HS_WAKEUP_REASON = 0x0009000B, /* WMM Configuration Group */ MLAN_IOCTL_WMM_CFG = 0x000A0000, - MLAN_OID_WMM_CFG_ENABLE, - MLAN_OID_WMM_CFG_QOS, - MLAN_OID_WMM_CFG_ADDTS, - MLAN_OID_WMM_CFG_DELTS, - MLAN_OID_WMM_CFG_QUEUE_CONFIG, - MLAN_OID_WMM_CFG_QUEUE_STATS, - MLAN_OID_WMM_CFG_QUEUE_STATUS, - MLAN_OID_WMM_CFG_TS_STATUS, + MLAN_OID_WMM_CFG_ENABLE = 0x000A0001, + MLAN_OID_WMM_CFG_QOS = 0x000A0002, + MLAN_OID_WMM_CFG_ADDTS = 0x000A0003, + MLAN_OID_WMM_CFG_DELTS = 0x000A0004, + MLAN_OID_WMM_CFG_QUEUE_CONFIG = 0x000A0005, + MLAN_OID_WMM_CFG_QUEUE_STATS = 0x000A0006, + MLAN_OID_WMM_CFG_QUEUE_STATUS = 0x000A0007, + MLAN_OID_WMM_CFG_TS_STATUS = 0x000A0008, /* WPS Configuration Group */ MLAN_IOCTL_WPS_CFG = 0x000B0000, - MLAN_OID_WPS_CFG_SESSION, + MLAN_OID_WPS_CFG_SESSION = 0x000B0001, /* 802.11n Configuration Group */ MLAN_IOCTL_11N_CFG = 0x000C0000, - MLAN_OID_11N_CFG_TX, - MLAN_OID_11N_HTCAP_CFG, - MLAN_OID_11N_CFG_ADDBA_REJECT, - MLAN_OID_11N_CFG_AGGR_PRIO_TBL, - MLAN_OID_11N_CFG_ADDBA_PARAM, - MLAN_OID_11N_CFG_MAX_TX_BUF_SIZE, - MLAN_OID_11N_CFG_AMSDU_AGGR_CTRL, - MLAN_OID_11N_CFG_SUPPORTED_MCS_SET, - MLAN_OID_11N_CFG_TX_BF_CAP, - MLAN_OID_11N_CFG_TX_BF_CFG, - MLAN_OID_11N_CFG_STREAM_CFG, - MLAN_OID_11N_CFG_DELBA, - MLAN_OID_11N_CFG_REJECT_ADDBA_REQ, + MLAN_OID_11N_CFG_TX = 0x000C0001, + MLAN_OID_11N_HTCAP_CFG = 0x000C0002, + MLAN_OID_11N_CFG_ADDBA_REJECT = 0x000C0003, + MLAN_OID_11N_CFG_AGGR_PRIO_TBL = 0x000C0004, + MLAN_OID_11N_CFG_ADDBA_PARAM = 0x000C0005, + MLAN_OID_11N_CFG_MAX_TX_BUF_SIZE = 0x000C0006, + MLAN_OID_11N_CFG_AMSDU_AGGR_CTRL = 0x000C0007, + MLAN_OID_11N_CFG_SUPPORTED_MCS_SET = 0x000C0008, + MLAN_OID_11N_CFG_TX_BF_CAP = 0x000C0009, + MLAN_OID_11N_CFG_TX_BF_CFG = 0x000C000A, + MLAN_OID_11N_CFG_STREAM_CFG = 0x000C000B, + MLAN_OID_11N_CFG_DELBA = 0x000C000C, + MLAN_OID_11N_CFG_REJECT_ADDBA_REQ = 0x000C000D, /* 802.11d Configuration Group */ MLAN_IOCTL_11D_CFG = 0x000D0000, #ifdef STA_SUPPORT - MLAN_OID_11D_CFG_ENABLE, - MLAN_OID_11D_CLR_CHAN_TABLE, + MLAN_OID_11D_CFG_ENABLE = 0x000D0001, + MLAN_OID_11D_CLR_CHAN_TABLE = 0x000D0002, #endif /* STA_SUPPORT */ - MLAN_OID_11D_DOMAIN_INFO, + MLAN_OID_11D_DOMAIN_INFO = 0x000D0003, /* Register Memory Access Group */ MLAN_IOCTL_REG_MEM = 0x000E0000, - MLAN_OID_REG_RW, - MLAN_OID_EEPROM_RD, - MLAN_OID_MEM_RW, + MLAN_OID_REG_RW = 0x000E0001, + MLAN_OID_EEPROM_RD = 0x000E0002, + MLAN_OID_MEM_RW = 0x000E0003, /* Multi-Radio Configuration Group */ MLAN_IOCTL_MFR_CFG = 0x00100000, /* 802.11h Configuration Group */ MLAN_IOCTL_11H_CFG = 0x00110000, - MLAN_OID_11H_CHANNEL_CHECK, - MLAN_OID_11H_LOCAL_POWER_CONSTRAINT, + MLAN_OID_11H_CHANNEL_CHECK = 0x00110001, + MLAN_OID_11H_LOCAL_POWER_CONSTRAINT = 0x00110002, #if defined(DFS_TESTING_SUPPORT) - MLAN_OID_11H_DFS_TESTING, + MLAN_OID_11H_DFS_TESTING = 0x00110003, #endif /* Miscellaneous Configuration Group */ MLAN_IOCTL_MISC_CFG = 0x00200000, - MLAN_OID_MISC_GEN_IE, - MLAN_OID_MISC_REGION, - MLAN_OID_MISC_WARM_RESET, + MLAN_OID_MISC_GEN_IE = 0x00200001, + MLAN_OID_MISC_REGION = 0x00200002, + MLAN_OID_MISC_WARM_RESET = 0x00200003, #if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR) - MLAN_OID_MISC_SDIO_MPA_CTRL, + MLAN_OID_MISC_SDIO_MPA_CTRL = 0x00200006, #endif - MLAN_OID_MISC_HOST_CMD, - MLAN_OID_MISC_SYS_CLOCK, - MLAN_OID_MISC_SOFT_RESET, - MLAN_OID_MISC_WWS, - MLAN_OID_MISC_INIT_SHUTDOWN, - MLAN_OID_MISC_CUSTOM_IE, - MLAN_OID_MISC_TX_DATAPAUSE, - MLAN_OID_MISC_IP_ADDR, - MLAN_OID_MISC_MAC_CONTROL, - MLAN_OID_MISC_MEF_CFG, - MLAN_OID_MISC_CFP_CODE, - MLAN_OID_MISC_COUNTRY_CODE, - MLAN_OID_MISC_THERMAL, - MLAN_OID_MISC_RX_MGMT_IND, - MLAN_OID_MISC_SUBSCRIBE_EVENT, + MLAN_OID_MISC_HOST_CMD = 0x00200007, + MLAN_OID_MISC_SYS_CLOCK = 0x00200009, + MLAN_OID_MISC_SOFT_RESET = 0x0020000A, + MLAN_OID_MISC_WWS = 0x0020000B, + MLAN_OID_MISC_ASSOC_RSP = 0x0020000C, + MLAN_OID_MISC_INIT_SHUTDOWN = 0x0020000D, + MLAN_OID_MISC_CUSTOM_IE = 0x0020000F, + MLAN_OID_MISC_TX_DATAPAUSE = 0x00200012, + MLAN_OID_MISC_IP_ADDR = 0x00200013, + MLAN_OID_MISC_MAC_CONTROL = 0x00200014, + MLAN_OID_MISC_MEF_CFG = 0x00200015, + MLAN_OID_MISC_CFP_CODE = 0x00200016, + MLAN_OID_MISC_COUNTRY_CODE = 0x00200017, + MLAN_OID_MISC_THERMAL = 0x00200018, + MLAN_OID_MISC_RX_MGMT_IND = 0x00200019, + MLAN_OID_MISC_SUBSCRIBE_EVENT = 0x0020001A, #ifdef DEBUG_LEVEL1 - MLAN_OID_MISC_DRVDBG, + MLAN_OID_MISC_DRVDBG = 0x0020001B, +#endif + MLAN_OID_MISC_OTP_USER_DATA = 0x0020001D, + MLAN_OID_MISC_TXCONTROL = 0x00200020, +#ifdef STA_SUPPORT + MLAN_OID_MISC_EXT_CAP_CFG = 0x00200021, +#endif +#if defined(STA_SUPPORT) + MLAN_OID_MISC_PMFCFG = 0x00200022, #endif - MLAN_OID_MISC_OTP_USER_DATA, - MLAN_OID_MISC_TXCONTROL, }; /** Sub command size */ @@ -520,6 +528,8 @@ typedef struct _mlan_ssid_bssid mlan_802_11_mac_addr bssid; /** index in BSSID list, start from 1 */ t_u32 idx; + /** Receive signal strength in dBm */ + t_s32 rssi; } mlan_ssid_bssid; #ifdef UAP_SUPPORT @@ -610,6 +620,8 @@ typedef struct _mlan_ssid_bssid #define KEY_MGMT_PSK 0x02 /** Key_mgmt_eap */ #define KEY_MGMT_EAP 0x01 +/** Key_mgmt_psk_sha256 */ +#define KEY_MGMT_PSK_SHA256 0x100 /** TKIP */ #define CIPHER_TKIP 0x04 @@ -978,6 +990,11 @@ enum _mlan_band_def #define CHANNEL_BW_40MHZ_ABOVE 1 #define CHANNEL_BW_40MHZ_BELOW 3 +/** RF antenna selection */ +#define RF_ANTENNA_MASK(n) ((1<<(n))-1) +/** RF antenna auto select */ +#define RF_ANTENNA_AUTO 0xFFFF + /** Type definition of mlan_ds_band_cfg for MLAN_OID_BAND_CFG */ typedef struct _mlan_ds_band_cfg { @@ -1110,6 +1127,10 @@ typedef struct _mlan_ds_get_stats t_u32 tx_frame; /** WEP ICV error count */ t_u32 wep_icv_error[4]; + /** beacon recv count */ + t_u32 bcn_rcv_cnt; + /** beacon miss count */ + t_u32 bcn_miss_cnt; } mlan_ds_get_stats, *pmlan_ds_get_stats; /** Type definition of mlan_ds_uap_stats for MLAN_OID_GET_STATS */ @@ -1340,7 +1361,7 @@ typedef struct } tx_ba_stream_tbl; /** Debug command number */ -#define DBG_CMD_NUM 5 +#define DBG_CMD_NUM 10 /** mlan_debug_info data structure for MLAN_OID_GET_DEBUG_INFO */ typedef struct _mlan_debug_info @@ -1393,6 +1414,8 @@ typedef struct _mlan_debug_info t_u8 tx_lock_flag; /** Corresponds to port_open member of mlan_private */ t_u8 port_open; + /** bypass pkt count */ + t_u16 bypass_pkt_count; /** Corresponds to scan_processing member of mlan_adapter */ t_u32 scan_processing; /** Number of host to card command failures */ @@ -1443,7 +1466,8 @@ typedef struct _mlan_debug_info t_u16 last_event[DBG_CMD_NUM]; /** Last event index */ t_u16 last_event_index; - + /** Number of no free command node */ + t_u16 num_no_cmd_node; /** Corresponds to data_sent member of mlan_adapter */ t_u8 data_sent; /** Corresponds to cmd_sent member of mlan_adapter */ @@ -1716,7 +1740,8 @@ typedef struct _mlan_ds_sec_cfg enum _mlan_rate_type { MLAN_RATE_INDEX, - MLAN_RATE_VALUE + MLAN_RATE_VALUE, + MLAN_RATE_BITMAP }; /** Enumeration for rate format */ @@ -1734,7 +1759,7 @@ typedef struct _mlan_rate_cfg_t { /** Fixed rate: 0, auto rate: 1 */ t_u32 is_rate_auto; - /** Rate type. 0: index; 1: valude */ + /** Rate type. 0: index; 1: value; 2: bitmap */ t_u32 rate_type; /** Rate/MCS index or rate value if fixed rate */ t_u32 rate; @@ -1858,6 +1883,8 @@ typedef struct _mlan_ds_power_cfg #define HOST_SLEEP_COND_MAC_EVENT MBIT(2) /** Host sleep config condition: multicast data */ #define HOST_SLEEP_COND_MULTICAST_DATA MBIT(3) +/** Host sleep config condition: IPV6 packet */ +#define HOST_SLEEP_COND_IPV6_PACKET MBIT(31) /** Host sleep config conditions: Default */ #define HOST_SLEEP_DEF_COND (HOST_SLEEP_COND_BROADCAST_DATA | HOST_SLEEP_COND_UNICAST_DATA | HOST_SLEEP_COND_MAC_EVENT) @@ -1865,6 +1892,8 @@ typedef struct _mlan_ds_power_cfg #define HOST_SLEEP_DEF_GPIO 0xff /** Host sleep config gap : Default */ #define HOST_SLEEP_DEF_GAP 200 +/** Host sleep config min wake holdoff */ +#define HOST_SLEEP_DEF_WAKE_HOLDOFF 0; /** Type definition of mlan_ds_hs_cfg for MLAN_OID_PM_CFG_HS_CFG */ typedef struct _mlan_ds_hs_cfg @@ -2807,6 +2836,18 @@ typedef struct _mlan_ds_misc_sys_clock t_u16 sys_clk[MLAN_MAX_CLK_NUM]; } mlan_ds_misc_sys_clock; +/** Maximum response buffer length */ +#define ASSOC_RSP_BUF_SIZE 500 + +/** Type definition of mlan_ds_misc_assoc_rsp for MLAN_OID_MISC_ASSOC_RSP */ +typedef struct _mlan_ds_misc_assoc_rsp +{ + /** Associate response buffer */ + t_u8 assoc_resp_buf[ASSOC_RSP_BUF_SIZE]; + /** Response buffer length */ + t_u32 assoc_resp_len; +} mlan_ds_misc_assoc_rsp; + /** Enumeration for function init/shutdown */ enum _mlan_func_cmd { @@ -2827,6 +2868,8 @@ typedef struct _mlan_ds_misc_tx_datapause #define IPADDR_LEN (16) /** Max number of ip */ #define MAX_IPADDR (4) +/** IP address type - NONE*/ +#define IPADDR_TYPE_NONE (0) /** IP address type - IPv4*/ #define IPADDR_TYPE_IPV4 (1) /** IP operation remove */ @@ -2887,6 +2930,10 @@ typedef struct _mlan_ds_misc_country_code t_u8 country_code[COUNTRY_CODE_LEN]; } mlan_ds_misc_country_code; +/** action for set */ +#define SUBSCRIBE_EVT_ACT_BITWISE_SET 0x0002 +/** action for clear */ +#define SUBSCRIBE_EVT_ACT_BITWISE_CLR 0x0003 /** BITMAP for subscribe event rssi low */ #define SUBSCRIBE_EVT_RSSI_LOW MBIT(0) /** BITMAP for subscribe event snr low */ @@ -2917,6 +2964,8 @@ typedef struct _mlan_ds_misc_country_code /** Type definition of mlan_ds_subscribe_evt for MLAN_OID_MISC_CFP_CODE */ typedef struct _mlan_ds_subscribe_evt { + /** evt action */ + t_u16 evt_action; /** bitmap for subscribe event */ t_u16 evt_bitmap; /** Absolute value of RSSI threshold value (dBm) */ @@ -2989,6 +3038,16 @@ typedef struct _mlan_ds_misc_otp_user_data t_u8 user_data[MAX_OTP_USER_DATA_LEN]; } mlan_ds_misc_otp_user_data; +#if defined(STA_SUPPORT) +typedef struct _mlan_ds_misc_pmfcfg +{ + /** Management Frame Protection Capable */ + t_u8 mfpc; + /** Management Frame Protection Required */ + t_u8 mfpr; +} mlan_ds_misc_pmfcfg; +#endif + /** Type definition of mlan_ds_misc_cfg for MLAN_IOCTL_MISC_CFG */ typedef struct _mlan_ds_misc_cfg { @@ -3011,6 +3070,8 @@ typedef struct _mlan_ds_misc_cfg mlan_ds_misc_sys_clock sys_clock; /** WWS set/get for MLAN_OID_MISC_WWS */ t_u32 wws_cfg; + /** Get associate response for MLAN_OID_MISC_ASSOC_RSP */ + mlan_ds_misc_assoc_rsp assoc_resp; /** Function init/shutdown for MLAN_OID_MISC_INIT_SHUTDOWN */ t_u32 func_init_shutdown; /** Custom IE for MLAN_OID_MISC_CUSTOM_IE */ @@ -3037,9 +3098,15 @@ typedef struct _mlan_ds_misc_cfg /** Driver debug bit masks */ t_u32 drvdbg; #endif +#ifdef STA_SUPPORT + t_u8 ext_cap[8]; +#endif mlan_ds_misc_otp_user_data otp_user_data; /** Tx control */ t_u32 tx_control; +#if defined(STA_SUPPORT) + mlan_ds_misc_pmfcfg pmfcfg; +#endif } param; } mlan_ds_misc_cfg, *pmlan_ds_misc_cfg; diff --git a/drivers/net/wireless/sd8797/mlan/mlan_join.c b/drivers/net/wireless/sd8797/mlan/mlan_join.c index d3b45ed3e2d9..b59c4361bb41 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_join.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_join.c @@ -287,13 +287,13 @@ wlan_setup_rates_from_bssdesc(IN mlan_private * pmpriv, pmpriv->adapter->region_code == COUNTRY_CODE_JP_FF) && (pbss_desc->phy_param_set.ds_param_set.current_chan == 14)) { /* Special Case: For Japan, 11G rates on CH14 are not allowed */ - card_rates_size = wlan_get_active_data_rates(pmpriv, pmpriv->bss_mode, - BAND_B, card_rates); + card_rates_size = wlan_get_supported_rates(pmpriv, pmpriv->bss_mode, + BAND_B, card_rates); } else { /* Get the STA supported rates */ - card_rates_size = wlan_get_active_data_rates(pmpriv, pmpriv->bss_mode, - pmpriv->config_bands, - card_rates); + card_rates_size = wlan_get_supported_rates(pmpriv, pmpriv->bss_mode, + pmpriv->config_bands, + card_rates); } /* Get the common rates between AP and STA supported rates */ if (wlan_get_common_rates(pmpriv, pout_rates, WLAN_SUPPORTED_RATES, @@ -409,6 +409,111 @@ wlan_cmd_append_wapi_ie(mlan_private * priv, t_u8 ** ppBuffer) Global Functions ********************************************************/ /** + * @brief This function updates RSN IE in the association request. + * + * @param pmpriv A pointer to mlan_private structure + * + * @param ptlv_rsn_ie A pointer to rsn_ie TLV + */ +void +wlan_update_rsn_ie(mlan_private * pmpriv, + MrvlIEtypes_RsnParamSet_t * ptlv_rsn_ie) +{ + t_u16 *prsn_cap; + t_u16 *ptr; + t_u16 *akm_suite_count_ptr; + t_u16 pmf_mask = 0x00; + t_u8 *temp; + int pairwise_cipher_count = 0; + int akm_suite_count = 0; + int temp_akm_suite_count = 0; + int found = 0; + t_u8 sha_256_oui[4] = { 0x00, 0x0f, 0xac, 0x06 }; + mlan_adapter *pmadapter = pmpriv->adapter; + + pmf_mask = + (((pmpriv->pmfcfg.mfpc << MFPC_BIT) | (pmpriv->pmfcfg. + mfpr << MFPR_BIT)) | + (~PMF_MASK)); + /* prsn_cap = prsn_ie->rsn_ie + 2 bytes version + 4 bytes + group_cipher_suite + 2 bytes pairwise_cipher_count + + pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN + 2 bytes + akm_suite_count + akm_suite_count * AKM_SUITE_LEN */ + ptr = (t_u16 *) (ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8)); + pairwise_cipher_count = *ptr; + ptr = (t_u16 *) (ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8) + + sizeof(t_u16) + + pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN); + temp_akm_suite_count = *ptr; + akm_suite_count = *ptr; + /* Save pointer to akm_suite_count in RSN IE to update it later */ + akm_suite_count_ptr = ptr; + temp = ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8) + + sizeof(t_u16) + pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN + sizeof(t_u16); /* ptr + now + points + to + the + 1st + AKM + suite + */ + if (temp_akm_suite_count > 1) { + while (temp_akm_suite_count) { + if (!memcmp(pmadapter, temp, sha_256_oui, AKM_SUITE_LEN)) { + found = 1; + break; + } + temp += AKM_SUITE_LEN; + temp_akm_suite_count--; + } + if (found) { + /* Copy SHA256 as AKM suite */ + memcpy(pmadapter, + ptlv_rsn_ie->rsn_ie + (sizeof(t_u16) + 4 * sizeof(t_u8) + + sizeof(t_u16) + + pairwise_cipher_count * + PAIRWISE_CIPHER_SUITE_LEN + + sizeof(t_u16)), sha_256_oui, + AKM_SUITE_LEN); + /* Shift remaining bytes of RSN IE after this */ + memmove(pmadapter, + ptlv_rsn_ie->rsn_ie + (sizeof(t_u16) + 4 * sizeof(t_u8) + + sizeof(t_u16) + + pairwise_cipher_count * + PAIRWISE_CIPHER_SUITE_LEN + + sizeof(t_u16) + AKM_SUITE_LEN), + ptlv_rsn_ie->rsn_ie + (sizeof(t_u16) + 4 * sizeof(t_u8) + + sizeof(t_u16) + + pairwise_cipher_count * + PAIRWISE_CIPHER_SUITE_LEN + + sizeof(t_u16) + + akm_suite_count * AKM_SUITE_LEN), + ptlv_rsn_ie->header.len - (sizeof(t_u16) + + 4 * sizeof(t_u8) + + sizeof(t_u16) + + pairwise_cipher_count * + PAIRWISE_CIPHER_SUITE_LEN + + sizeof(t_u16) + + akm_suite_count * + AKM_SUITE_LEN)); + ptlv_rsn_ie->header.len = + ptlv_rsn_ie->header.len - (akm_suite_count - 1) * AKM_SUITE_LEN; + /* Update akm suite count */ + akm_suite_count = 1; + *akm_suite_count_ptr = akm_suite_count; + } + } + ptr = (t_u16 *) (ptlv_rsn_ie->rsn_ie + sizeof(t_u16) + 4 * sizeof(t_u8) + + sizeof(t_u16) + + pairwise_cipher_count * PAIRWISE_CIPHER_SUITE_LEN + + sizeof(t_u16) + akm_suite_count * AKM_SUITE_LEN); + prsn_cap = ptr; + *prsn_cap |= PMF_MASK; + *prsn_cap &= pmf_mask; +} + +/** * @brief This function prepares command of association. * * @param pmpriv A pointer to mlan_private structure @@ -508,7 +613,9 @@ wlan_cmd_802_11_associate(IN mlan_private * pmpriv, pauth_tlv = (MrvlIEtypes_AuthType_t *) pos; pauth_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_AUTH_TYPE); pauth_tlv->header.len = sizeof(pauth_tlv->auth_type); - if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled) + if ((pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled) + || (pmpriv->sec_info.authentication_mode == + MLAN_AUTH_MODE_NETWORKEAP)) pauth_tlv->auth_type = wlan_cpu_to_le16((t_u16) pmpriv->sec_info.authentication_mode); else @@ -608,6 +715,9 @@ wlan_cmd_802_11_associate(IN mlan_private * pmpriv, memcpy(pmadapter, prsn_ie_tlv->rsn_ie, &((*(pbss_desc->prsn_ie)).data[0]) , prsn_ie_tlv->header.len); + if (pmpriv->pmfcfg.mfpc || pmpriv->pmfcfg.mfpr) { + wlan_update_rsn_ie(pmpriv, prsn_ie_tlv); + } } else { ret = MLAN_STATUS_FAILURE; goto done; @@ -763,11 +873,18 @@ wlan_ret_802_11_associate(IN mlan_private * pmpriv, t_u8 enable_data = MTRUE; t_u8 event_buf[100]; mlan_event *pevent = (mlan_event *) event_buf; + t_u8 cur_mac[MLAN_MAC_ADDR_LENGTH]; + t_u8 media_connected = pmpriv->media_connected; + mlan_adapter *pmadapter = pmpriv->adapter; ENTER(); passoc_rsp = (IEEEtypes_AssocRsp_t *) & resp->params; passoc_rsp->status_code = wlan_le16_to_cpu(passoc_rsp->status_code); + if (pmpriv->media_connected == MTRUE) + memcpy(pmpriv->adapter, cur_mac, + pmpriv->curr_bss_params.bss_descriptor.mac_address, + MLAN_MAC_ADDR_LENGTH); HEXDUMP("ASSOC_RESP:", (t_u8 *) & resp->params, (resp->size - S_DS_GEN)); @@ -778,6 +895,19 @@ wlan_ret_802_11_associate(IN mlan_private * pmpriv, pmpriv->assoc_rsp_size); if (passoc_rsp->status_code) { + if (pmpriv->media_connected == MTRUE) { + if (pmpriv->port_ctrl_mode == MTRUE) + pmpriv->port_open = pmpriv->prior_port_status; + if (!memcmp + (pmpriv->adapter, cur_mac, + pmpriv->pattempted_bss_desc->mac_address, + MLAN_MAC_ADDR_LENGTH)) + wlan_reset_connect_state(pmpriv, MTRUE); + else + wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_ASSOC_FAILURE_REPORT, + MNULL); + } else + wlan_reset_connect_state(pmpriv, MTRUE); pmpriv->adapter->dbg.num_cmd_assoc_failure++; PRINTM(MERROR, "ASSOC_RESP: Association Failed, " "status code = %d, error = 0x%x, a_id = 0x%x\n", @@ -799,7 +929,8 @@ wlan_ret_802_11_associate(IN mlan_private * pmpriv, /* Set the attempted BSSID Index to current */ pbss_desc = pmpriv->pattempted_bss_desc; - PRINTM(MINFO, "ASSOC_RESP: %s\n", pbss_desc->ssid.ssid); + PRINTM(MCMND, "ASSOC_RESP: %-32s (a_id = 0x%x)\n", pbss_desc->ssid.ssid, + wlan_le16_to_cpu(passoc_rsp->a_id)); /* Make a copy of current BSSID descriptor */ memcpy(pmpriv->adapter, &pmpriv->curr_bss_params.bss_descriptor, @@ -883,7 +1014,24 @@ wlan_ret_802_11_associate(IN mlan_private * pmpriv, MLAN_MAC_ADDR_LENGTH); /* Add the ra_list here for infra mode as there will be only 1 ra always */ - wlan_ralist_add(pmpriv, pmpriv->curr_bss_params.bss_descriptor.mac_address); + if (media_connected) { + /** replace ralist's mac address with new mac address */ + if (0 == + wlan_ralist_update(pmpriv, cur_mac, + pmpriv->curr_bss_params.bss_descriptor. + mac_address)) + wlan_ralist_add(pmpriv, + pmpriv->curr_bss_params.bss_descriptor.mac_address); + wlan_11n_cleanup_reorder_tbl(pmpriv); + + pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, + pmpriv->wmm.ra_list_spinlock); + wlan_11n_deleteall_txbastream_tbl(pmpriv); + pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, + pmpriv->wmm.ra_list_spinlock); + } else + wlan_ralist_add(pmpriv, + pmpriv->curr_bss_params.bss_descriptor.mac_address); wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_CONNECTED, pevent); @@ -892,7 +1040,8 @@ wlan_ret_802_11_associate(IN mlan_private * pmpriv, if (!pmpriv->sec_info.wpa_enabled && !pmpriv->sec_info.wpa2_enabled - && !pmpriv->sec_info.ewpa_enabled && !pmpriv->sec_info.wapi_enabled) { + && !pmpriv->sec_info.ewpa_enabled + && !pmpriv->sec_info.wapi_enabled && !pmpriv->wps.session_enable) { /* We are in Open/WEP mode, open port immediately */ if (pmpriv->port_ctrl_mode == MTRUE) { pmpriv->port_open = MTRUE; @@ -912,7 +1061,8 @@ wlan_ret_802_11_associate(IN mlan_private * pmpriv, if (ret != MLAN_STATUS_SUCCESS) { if (passoc_rsp->status_code) pioctl_req->status_code = - wlan_le16_to_cpu(passoc_rsp->status_code); + (wlan_le16_to_cpu(*(t_u16 *) & passoc_rsp->capability) << + 16) + wlan_le16_to_cpu(passoc_rsp->status_code); else pioctl_req->status_code = MLAN_ERROR_CMD_ASSOC_FAIL; } else { @@ -949,6 +1099,7 @@ wlan_cmd_802_11_ad_hoc_start(IN mlan_private * pmpriv, MrvlIEtypes_RsnParamSet_t *prsn_ie_tlv; MrvlIETypes_HTCap_t *pht_cap; MrvlIETypes_HTInfo_t *pht_info; + t_u32 rx_mcs_supp = 0; /* wpa ie for WPA_NONE AES */ const t_u8 wpa_ie[24] = { 0xdd, 0x16, 0x00, 0x50, 0xf2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xf2, 0x04, 0x01, 0x00, 0x00, 0x50, @@ -1209,6 +1360,10 @@ wlan_cmd_802_11_ad_hoc_start(IN mlan_private * pmpriv, memset(pmadapter, pht_cap, 0, sizeof(MrvlIETypes_HTCap_t)); pht_cap->header.type = wlan_cpu_to_le16(HT_CAPABILITY); pht_cap->header.len = sizeof(HTCap_t); + rx_mcs_supp = GET_RXMCSSUPP(pmadapter->usr_dev_mcs_support); + /* Set MCS for 1x1/2x2 */ + memset(pmadapter, (t_u8 *) pht_cap->ht_cap.supported_mcs_set, 0xff, + rx_mcs_supp); wlan_fill_ht_cap_tlv(pmpriv, pht_cap, pmpriv->curr_bss_params.band); HEXDUMP("ADHOC_START: HT_CAPABILITIES IE", (t_u8 *) pht_cap, sizeof(MrvlIETypes_HTCap_t)); @@ -1281,7 +1436,7 @@ wlan_cmd_802_11_ad_hoc_join(IN mlan_private * pmpriv, t_u32 cmd_append_size = 0; t_u16 tmp_cap; t_u32 i, rates_size = 0; - t_u16 curr_pkt_filter; + t_u32 curr_pkt_filter; t_u8 *pos = (t_u8 *) padhoc_join + sizeof(HostCmd_DS_802_11_AD_HOC_JOIN); ENTER(); @@ -1336,13 +1491,8 @@ wlan_cmd_802_11_ad_hoc_join(IN mlan_private * pmpriv, /* Information on BSSID descriptor passed to FW */ PRINTM(MINFO, - "ADHOC_J_CMD: BSSID = %02x-%02x-%02x-%02x-%02x-%02x, SSID = %s\n", - padhoc_join->bss_descriptor.bssid[0], - padhoc_join->bss_descriptor.bssid[1], - padhoc_join->bss_descriptor.bssid[2], - padhoc_join->bss_descriptor.bssid[3], - padhoc_join->bss_descriptor.bssid[4], - padhoc_join->bss_descriptor.bssid[5], + "ADHOC_J_CMD: BSSID = " MACSTR ", SSID = %s\n", + MAC2STR(padhoc_join->bss_descriptor.bssid), padhoc_join->bss_descriptor.ssid); for (i = 0; i < WLAN_SUPPORTED_RATES && pbss_desc->supported_rates[i]; i++); @@ -1595,13 +1745,8 @@ wlan_ret_802_11_ad_hoc(IN mlan_private * pmpriv, } PRINTM(MINFO, "ADHOC_RESP: Channel = %d\n", pmpriv->adhoc_channel); - PRINTM(MINFO, "ADHOC_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n", - pmpriv->curr_bss_params.bss_descriptor.mac_address[0], - pmpriv->curr_bss_params.bss_descriptor.mac_address[1], - pmpriv->curr_bss_params.bss_descriptor.mac_address[2], - pmpriv->curr_bss_params.bss_descriptor.mac_address[3], - pmpriv->curr_bss_params.bss_descriptor.mac_address[4], - pmpriv->curr_bss_params.bss_descriptor.mac_address[5]); + PRINTM(MINFO, "ADHOC_RESP: BSSID = " MACSTR "\n", + MAC2STR(pmpriv->curr_bss_params.bss_descriptor.mac_address)); pevent->bss_index = pmpriv->bss_index; pevent->event_id = MLAN_EVENT_ID_DRV_CONNECTED; diff --git a/drivers/net/wireless/sd8797/mlan/mlan_main.h b/drivers/net/wireless/sd8797/mlan/mlan_main.h index 1e29c0464f5f..848137ba283a 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_main.h +++ b/drivers/net/wireless/sd8797/mlan/mlan_main.h @@ -30,31 +30,31 @@ Change log: #ifdef DEBUG_LEVEL1 extern t_void(*print_callback) (IN t_void * pmoal_handle, - IN t_u32 level, IN t_s8 * pformat, IN ...); + IN t_u32 level, IN char *pformat, IN ...); extern mlan_status(*get_sys_time_callback) (IN t_void * pmoal_handle, OUT t_u32 * psec, OUT t_u32 * pusec); -extern t_u32 drvdbg; +extern t_u32 mlan_drvdbg; #ifdef DEBUG_LEVEL2 -#define PRINTM_MINFO(msg...) do {if ((drvdbg & MINFO) && (print_callback)) \ +#define PRINTM_MINFO(msg...) do {if ((mlan_drvdbg & MINFO) && (print_callback)) \ print_callback(MNULL, MINFO, msg);} while(0) -#define PRINTM_MWARN(msg...) do {if ((drvdbg & MWARN) && (print_callback)) \ +#define PRINTM_MWARN(msg...) do {if ((mlan_drvdbg & MWARN) && (print_callback)) \ print_callback(MNULL, MWARN, msg);} while(0) -#define PRINTM_MENTRY(msg...) do {if ((drvdbg & MENTRY) && (print_callback)) \ +#define PRINTM_MENTRY(msg...) do {if ((mlan_drvdbg & MENTRY) && (print_callback)) \ print_callback(MNULL, MENTRY, msg);} while(0) #define PRINTM_GET_SYS_TIME(level, psec, pusec) \ do { \ - if ((level & drvdbg) && (get_sys_time_callback)) \ + if ((level & mlan_drvdbg) && (get_sys_time_callback)) \ get_sys_time_callback(MNULL, psec, pusec); \ } while (0) /** Hexdump for level-2 debugging */ #define HEXDUMP(x,y,z) \ do { \ - if ((drvdbg & (MHEX_DUMP | MINFO)) && (print_callback)) \ + if ((mlan_drvdbg & (MHEX_DUMP | MINFO)) && (print_callback)) \ print_callback(MNULL, MHEX_DUMP | MINFO, x, y, z); \ } while (0) @@ -66,7 +66,7 @@ do { \ #define PRINTM_GET_SYS_TIME(level, psec, pusec) \ do { \ - if ((level & drvdbg) && (get_sys_time_callback) \ + if ((level & mlan_drvdbg) && (get_sys_time_callback) \ && (level != MINFO) && (level != MWARN)) \ get_sys_time_callback(MNULL, psec, pusec); \ } while (0) @@ -76,39 +76,39 @@ do { \ #endif /* DEBUG_LEVEL2 */ -#define PRINTM_MFW_D(msg...) do {if ((drvdbg & MFW_D) && (print_callback)) \ +#define PRINTM_MFW_D(msg...) do {if ((mlan_drvdbg & MFW_D) && (print_callback)) \ print_callback(MNULL, MFW_D, msg);} while(0) -#define PRINTM_MCMD_D(msg...) do {if ((drvdbg & MCMD_D) && (print_callback)) \ +#define PRINTM_MCMD_D(msg...) do {if ((mlan_drvdbg & MCMD_D) && (print_callback)) \ print_callback(MNULL, MCMD_D, msg);} while(0) -#define PRINTM_MDAT_D(msg...) do {if ((drvdbg & MDAT_D) && (print_callback)) \ +#define PRINTM_MDAT_D(msg...) do {if ((mlan_drvdbg & MDAT_D) && (print_callback)) \ print_callback(MNULL, MDAT_D, msg);} while(0) -#define PRINTM_MIF_D(msg...) do {if ((drvdbg & MIF_D) && (print_callback)) \ +#define PRINTM_MIF_D(msg...) do {if ((mlan_drvdbg & MIF_D) && (print_callback)) \ print_callback(MNULL, MIF_D, msg);} while(0) -#define PRINTM_MIOCTL(msg...) do {if ((drvdbg & MIOCTL) && (print_callback)) \ +#define PRINTM_MIOCTL(msg...) do {if ((mlan_drvdbg & MIOCTL) && (print_callback)) \ print_callback(MNULL, MIOCTL, msg);} while(0) -#define PRINTM_MINTR(msg...) do {if ((drvdbg & MINTR) && (print_callback)) \ +#define PRINTM_MINTR(msg...) do {if ((mlan_drvdbg & MINTR) && (print_callback)) \ print_callback(MNULL, MINTR, msg);} while(0) -#define PRINTM_MEVENT(msg...) do {if ((drvdbg & MEVENT) && (print_callback)) \ +#define PRINTM_MEVENT(msg...) do {if ((mlan_drvdbg & MEVENT) && (print_callback)) \ print_callback(MNULL, MEVENT, msg);} while(0) -#define PRINTM_MCMND(msg...) do {if ((drvdbg & MCMND) && (print_callback)) \ +#define PRINTM_MCMND(msg...) do {if ((mlan_drvdbg & MCMND) && (print_callback)) \ print_callback(MNULL, MCMND, msg);} while(0) -#define PRINTM_MDATA(msg...) do {if ((drvdbg & MDATA) && (print_callback)) \ +#define PRINTM_MDATA(msg...) do {if ((mlan_drvdbg & MDATA) && (print_callback)) \ print_callback(MNULL, MDATA, msg);} while(0) -#define PRINTM_MERROR(msg...) do {if ((drvdbg & MERROR) && (print_callback)) \ +#define PRINTM_MERROR(msg...) do {if ((mlan_drvdbg & MERROR) && (print_callback)) \ print_callback(MNULL, MERROR, msg);} while(0) -#define PRINTM_MFATAL(msg...) do {if ((drvdbg & MFATAL) && (print_callback)) \ +#define PRINTM_MFATAL(msg...) do {if ((mlan_drvdbg & MFATAL) && (print_callback)) \ print_callback(MNULL, MFATAL, msg);} while(0) -#define PRINTM_MMSG(msg...) do {if ((drvdbg & MMSG) && (print_callback)) \ +#define PRINTM_MMSG(msg...) do {if ((mlan_drvdbg & MMSG) && (print_callback)) \ print_callback(MNULL, MMSG, msg);} while(0) -#define PRINTM(level,msg...) PRINTM_##level(msg) +#define PRINTM(level,msg...) PRINTM_##level((char*)msg) /** Log debug message */ #ifdef __GNUC__ #define PRINTM_NETINTF(level, pmpriv) \ do { \ - if ((drvdbg & level) && pmpriv \ + if ((mlan_drvdbg & level) && pmpriv \ && pmpriv->adapter->callbacks.moal_print_netintf) \ pmpriv->adapter->callbacks.moal_print_netintf( \ pmpriv->adapter->pmoal_handle, \ @@ -122,7 +122,7 @@ do { \ /** Debug hexdump for level-1 debugging */ #define DBG_HEXDUMP(level,x,y,z) \ do { \ - if ((drvdbg & level) && print_callback) \ + if ((mlan_drvdbg & level) && print_callback) \ print_callback(MNULL, MHEX_DUMP | level, x, y, z); \ } while (0) @@ -316,7 +316,7 @@ do { \ #define WLAN_UPLD_SIZE (2312) /** Maximum event buffer size */ -#define MAX_EVENT_SIZE 1024 +#define MAX_EVENT_SIZE 2048 #ifdef STA_SUPPORT /** Maximum buffer size for ARP filter */ @@ -388,7 +388,7 @@ do { \ #define DEFAULT_BCN_MISS_TIMEOUT 10 /** Maximum buffer space for beacons retrieved from scan responses */ -#define MAX_SCAN_BEACON_BUFFER 16384 +#define MAX_SCAN_BEACON_BUFFER 32768 /** Default buffer space for beacons retrieved from scan responses */ #define DEFAULT_SCAN_BEACON_BUFFER 4096 @@ -425,11 +425,6 @@ do { \ /** If OUI is found */ #define MLAN_OUI_PRESENT 1 -/** RF antenna selection */ -#define RF_ANTENNA_MASK(n) ((1<<(n))-1) -/** RF antenna auto select */ -#define RF_ANTENNA_AUTO 0xFFFF - /** Is cmd_resp, event or data packet received? */ #define IS_CARD_RX_RCVD(adapter) (adapter->cmd_resp_received || \ adapter->event_received || \ @@ -465,7 +460,7 @@ do { \ #define RX_LOW_THRESHOLD 128 /** Debug command number */ -#define DBG_CMD_NUM 5 +#define DBG_CMD_NUM 10 /** Info for debug purpose */ typedef struct _wlan_dbg @@ -518,6 +513,8 @@ typedef struct _wlan_dbg t_u16 last_event[DBG_CMD_NUM]; /** Last event index */ t_u16 last_event_index; + /** Number of no free command node */ + t_u16 num_no_cmd_node; } wlan_dbg; /** Hardware status codes */ @@ -900,6 +897,8 @@ typedef struct _mlan_private t_u8 bss_type; /** BSS role */ t_u8 bss_role; + /** BSS virtual flag */ + t_u8 bss_virtual; /** BSS Priority */ t_u8 bss_priority; /** BSS number */ @@ -912,7 +911,7 @@ typedef struct _mlan_private t_bool media_connected; /** Current packet filter */ - t_u16 curr_pkt_filter; + t_u32 curr_pkt_filter; /** Infrastructure mode */ t_u32 bss_mode; @@ -1010,12 +1009,14 @@ typedef struct _mlan_private wlan_802_11d_state_t state_11d; /** FSM variable for 11h support */ wlan_11h_interface_state_t intf_state_11h; -#if defined(UAP_SUPPORT) +#ifdef UAP_SUPPORT /** Whether UAP interface has started */ t_bool uap_bss_started; + /**UAP operating channel*/ + t_u8 uap_channel; /** state variable for UAP Get Info callback */ wlan_uap_get_info_cb_t uap_state_chan_cb; -#endif +#endif /* UAP_SUPPORT */ /** Security related */ /** Encryption parameter */ @@ -1032,8 +1033,11 @@ typedef struct _mlan_private t_u8 wpa_ie_len; /** GTK set flag */ t_u8 wpa_is_gtk_set; - /** AES key material */ - HostCmd_DS_802_11_KEY_MATERIAL aes_key; + mlan_ds_encrypt_key aes_key; +#if defined(STA_SUPPORT) + /* Mgmt Frame Protection config */ + mlan_ds_misc_pmfcfg pmfcfg; +#endif /** WAPI IE */ t_u8 wapi_ie[256]; /** WAPI IE length */ @@ -1103,10 +1107,15 @@ typedef struct _mlan_private /** Port open flag state at time of association attempt */ t_u8 prior_port_status; + /** Bypass TX queue */ + mlan_list_head bypass_txq; /** IP address operation */ t_u32 op_code; /** IP address */ t_u8 ip_addr[IPADDR_LEN]; +#ifdef STA_SUPPORT + ExtCap_t ext_cap; +#endif } mlan_private, *pmlan_private; /** BA stream status */ @@ -1161,6 +1170,8 @@ struct _RxReorderTbl t_u8 ta[MLAN_MAC_ADDR_LENGTH]; /** Start window */ int start_win; + /** last_seq */ + int last_seq; /** Window size */ int win_size; /** Pointer to pointer to RxReorderTbl */ @@ -1170,8 +1181,10 @@ struct _RxReorderTbl /** BA stream status */ baStatus_e ba_status; t_u8 amsdu; - /** no packet drop flag for rx_reorder_tbl */ + /** no packet drop flag for rx_reorder_tbl */ t_u8 force_no_drop; + /** flag for check start win */ + t_u8 check_start_win; }; /** BSS priority node */ @@ -1511,6 +1524,8 @@ typedef struct _mlan_adapter t_void *pmain_proc_lock; /** mlan_processing */ t_u32 mlan_processing; + /** more task flag */ + t_u32 more_task_flag; /** Max tx buf size */ t_u16 max_tx_buf_size; /** Tx buf size */ @@ -1806,9 +1821,11 @@ typedef struct _mlan_adapter /** 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; - /** Bypass TX queue */ - mlan_list_head bypass_txq; + /** Bypass TX queue pkt count */ + t_u16 bypass_pkt_count; #if defined(STA_SUPPORT) /** warm-reset IOCTL request buffer pointer */ pmlan_ioctl_req pwarm_reset_ioctl_req; @@ -1819,9 +1836,16 @@ typedef struct _mlan_adapter t_u8 *pcal_data; /** Cal data length */ t_u32 cal_data_len; + /** Feature control bitmask */ + t_u32 feature_control; } mlan_adapter, *pmlan_adapter; +/** Check if stream 2X2 enabled */ +#define IS_STREAM_2X2(x) ((x) & FEATURE_CTRL_STREAM_2X2) +/** Check if DFS support enabled */ +#define IS_DFS_SUPPORT(x) ((x) & FEATURE_CTRL_DFS_SUPPORT) + /** Ethernet packet type for EAPOL */ #define MLAN_ETHER_PKT_TYPE_EAPOL (0x888E) /** Ethernet packet type for WAPI */ @@ -1906,12 +1930,15 @@ 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_cancel_pending_scan_cmd(pmlan_adapter pmadapter); #endif /**Cancel pending command */ t_void wlan_cancel_all_pending_cmd(pmlan_adapter pmadapter); /**Cancel pending ioctl */ t_void wlan_cancel_pending_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req); +/**Cancel bss pending ioctl */ +t_void wlan_cancel_bss_pending_cmd(pmlan_adapter pmadapter, t_u32 bss_index); /** Insert command to free queue */ t_void wlan_insert_cmd_to_free_q(IN mlan_adapter * pmadapter, @@ -1954,7 +1981,7 @@ t_void wlan_clean_txrx(pmlan_private priv); t_void wlan_add_buf_bypass_txqueue(mlan_adapter * pmadapter, pmlan_buffer pmbuf); t_void wlan_process_bypass_tx(mlan_adapter * pmadapter); -t_void wlan_cleanup_bypass_txq(mlan_adapter * pmadapter); +t_void wlan_cleanup_bypass_txq(pmlan_private priv); t_u8 wlan_bypass_tx_list_empty(mlan_adapter * pmadapter); /** Check if this is the last packet */ @@ -2043,6 +2070,9 @@ mlan_status wlan_ret_remain_on_channel(IN pmlan_private pmpriv, mlan_status wlan_get_pm_info(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req); +mlan_status wlan_bss_ioctl_bss_remove(IN pmlan_adapter pmadapter, + IN pmlan_ioctl_req pioctl_req); + mlan_status wlan_get_hs_wakeup_reason(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req); @@ -2406,7 +2436,7 @@ wlan_is_tx_pause(mlan_private * priv, t_u8 * ra) return MFALSE; } -t_void wlan_updata_ralist_tx_pause(pmlan_private priv, t_u8 * mac, +t_void wlan_update_ralist_tx_pause(pmlan_private priv, t_u8 * mac, t_u8 tx_pause); #ifdef UAP_SUPPORT @@ -2430,6 +2460,15 @@ mlan_status wlan_ret_get_hw_spec(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND * resp, IN t_void * pioctl_buf); +mlan_status wlan_misc_ioctl_mac_control(IN pmlan_adapter pmadapter, + IN pmlan_ioctl_req pioctl_req); +mlan_status wlan_cmd_mac_control(IN pmlan_private pmpriv, + IN HostCmd_DS_COMMAND * pcmd, + IN t_u16 cmd_action, IN t_void * pdata_buf); +mlan_status wlan_ret_mac_control(IN pmlan_private pmpriv, + IN HostCmd_DS_COMMAND * resp, + IN mlan_ioctl_req * pioctl_buf); + mlan_status wlan_cmd_802_11_radio_control(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND * cmd, IN t_u16 cmd_action, @@ -2476,6 +2515,17 @@ mlan_status wlan_set_drvdbg(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req); #endif +#ifdef STA_SUPPORT +mlan_status wlan_misc_ext_capa_cfg(IN pmlan_adapter pmadapter, + IN pmlan_ioctl_req pioctl_req); + +t_u32 wlan_is_ext_capa_support(IN mlan_private * pmpriv); +#endif + +#ifdef STA_SUPPORT +void wlan_add_ext_capa_info_ie(IN mlan_private * pmpriv, OUT t_u8 ** pptlv_out); +#endif + mlan_status wlan_misc_otp_user_data(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req); @@ -2535,7 +2585,7 @@ wlan_copy_rates(t_u8 * dest, t_u32 pos, t_u8 * src, int len) * @return Length of string */ static INLINE t_u32 -wlan_strlen(const t_s8 * str) +wlan_strlen(const char *str) { t_u32 i; diff --git a/drivers/net/wireless/sd8797/mlan/mlan_meas.c b/drivers/net/wireless/sd8797/mlan/mlan_meas.c index d9da9da20756..19c4131c7bc1 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_meas.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_meas.c @@ -85,12 +85,8 @@ wlan_meas_dump_meas_req(const HostCmd_DS_MEASUREMENT_REQUEST * pmeas_req) PRINTM(MINFO, "Meas: Req: ------------------------------\n"); - PRINTM(MINFO, "Meas: Req: mac_addr: %02x:%02x:%02x:%02x:%02x:%02x\n", - pmeas_req->mac_addr[0], - pmeas_req->mac_addr[1], - pmeas_req->mac_addr[2], - pmeas_req->mac_addr[3], - pmeas_req->mac_addr[4], pmeas_req->mac_addr[5]); + PRINTM(MINFO, "Meas: Req: mac_addr: " MACSTR "\n", + MAC2STR(pmeas_req->mac_addr)); PRINTM(MINFO, "Meas: Req: dlgTkn: %d\n", pmeas_req->dialog_token); PRINTM(MINFO, "Meas: Req: mode: dm[%c] rpt[%c] req[%c]\n", @@ -136,12 +132,8 @@ wlan_meas_dump_meas_rpt(const HostCmd_DS_MEASUREMENT_REPORT * pmeas_rpt) ENTER(); PRINTM(MINFO, "Meas: Rpt: ------------------------------\n"); - PRINTM(MINFO, "Meas: Rpt: mac_addr: %02x:%02x:%02x:%02x:%02x:%02x\n", - pmeas_rpt->mac_addr[0], - pmeas_rpt->mac_addr[1], - pmeas_rpt->mac_addr[2], - pmeas_rpt->mac_addr[3], - pmeas_rpt->mac_addr[4], pmeas_rpt->mac_addr[5]); + PRINTM(MINFO, "Meas: Rpt: mac_addr: " MACSTR "\n", + MAC2STR(pmeas_rpt->mac_addr)); PRINTM(MINFO, "Meas: Rpt: dlgTkn: %d\n", pmeas_rpt->dialog_token); diff --git a/drivers/net/wireless/sd8797/mlan/mlan_misc.c b/drivers/net/wireless/sd8797/mlan/mlan_misc.c index 6f4073560b31..540147c1837e 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_misc.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_misc.c @@ -57,6 +57,8 @@ extern t_u8 ac_to_tid[4][2]; #define MLAN_CUSTOM_IE_AUTO_IDX_MASK 0xffff /** Custom IE mask for delete operation */ #define MLAN_CUSTOM_IE_DELETE_MASK 0 +/** Custom IE mask for create new index */ +#define MLAN_CUSTOM_IE_NEW_MASK 0x8000 /** Custom IE header size */ #define MLAN_CUSTOM_IE_HDR_SIZE (sizeof(custom_ie)-MAX_IE_SIZE) @@ -129,9 +131,9 @@ wlan_custom_ioctl_get_autoidx(IN pmlan_private pmpriv, (pmpriv->adapter, pmpriv->mgmt_ie[index].ie_buffer, ie_data->ie_buffer, pmpriv->mgmt_ie[index].ie_length)) { - PRINTM(MERROR, - "IE with the same mask exists at index %d\n", - index); + PRINTM(MINFO, + "IE with the same mask exists at index %d mask=0x%x\n", + index, mask); *idx = MLAN_CUSTOM_IE_AUTO_IDX_MASK; goto done; } @@ -208,6 +210,9 @@ wlan_custom_ioctl_auto_delete(IN pmlan_private pmpriv, MIN(MAX_IE_SIZE, ie_data->ie_length)); del_len = MIN(MAX_IE_SIZE, ie_data->ie_length); + if (MLAN_CUSTOM_IE_AUTO_IDX_MASK == idx) + ie_data->ie_index = 0; + for (index = 0; index < pmadapter->max_mgmt_ie_index; index++) { if (MLAN_CUSTOM_IE_AUTO_IDX_MASK != idx) index = idx; @@ -228,6 +233,9 @@ wlan_custom_ioctl_auto_delete(IN pmlan_private pmpriv, memcpy(pmpriv->adapter, &pmpriv->mgmt_ie[index].ie_buffer, ie, pmpriv->mgmt_ie[index].ie_length - del_len); pmpriv->mgmt_ie[index].ie_length -= del_len; + if (MLAN_CUSTOM_IE_AUTO_IDX_MASK == idx) + /* set a bit to indicate caller about update */ + ie_data->ie_index |= (((t_u16) 1) << index); insert = MTRUE; tmp_ie = pmpriv->mgmt_ie[index].ie_buffer; tmp_len = pmpriv->mgmt_ie[index].ie_length; @@ -376,8 +384,8 @@ wlan_get_info_debug_info(IN pmlan_adapter pmadapter, pmpriv->wmm_qosinfo = info->param.debug_info.qos_cfg; pmadapter->tx_lock_flag = info->param.debug_info.tx_lock_flag; pmpriv->port_open = info->param.debug_info.port_open; + pmadapter->bypass_pkt_count = info->param.debug_info.bypass_pkt_count; pmadapter->scan_processing = info->param.debug_info.scan_processing; - pmadapter->dbg.num_cmd_host_to_card_failure = info->param.debug_info.num_cmd_host_to_card_failure; pmadapter->dbg.num_cmd_sleep_cfm_host_to_card_failure = @@ -423,6 +431,7 @@ wlan_get_info_debug_info(IN pmlan_adapter pmadapter, sizeof(pmadapter->dbg.last_event)); pmadapter->dbg.last_event_index = info->param.debug_info.last_event_index; + pmadapter->dbg.num_no_cmd_node = info->param.debug_info.num_no_cmd_node; pmadapter->data_sent = info->param.debug_info.data_sent; pmadapter->cmd_sent = info->param.debug_info.cmd_sent; @@ -472,8 +481,8 @@ wlan_get_info_debug_info(IN pmlan_adapter pmadapter, info->param.debug_info.qos_cfg = pmpriv->wmm_qosinfo; info->param.debug_info.tx_lock_flag = pmadapter->tx_lock_flag; info->param.debug_info.port_open = pmpriv->port_open; + info->param.debug_info.bypass_pkt_count = pmadapter->bypass_pkt_count; info->param.debug_info.scan_processing = pmadapter->scan_processing; - info->param.debug_info.num_cmd_host_to_card_failure = pmadapter->dbg.num_cmd_host_to_card_failure; info->param.debug_info.num_cmd_sleep_cfm_host_to_card_failure @@ -517,6 +526,7 @@ wlan_get_info_debug_info(IN pmlan_adapter pmadapter, pmadapter->dbg.last_event, sizeof(pmadapter->dbg.last_event)); info->param.debug_info.last_event_index = pmadapter->dbg.last_event_index; + info->param.debug_info.num_no_cmd_node = pmadapter->dbg.num_no_cmd_node; info->param.debug_info.mp_rd_bitmap = pmadapter->mp_rd_bitmap; info->param.debug_info.mp_wr_bitmap = pmadapter->mp_wr_bitmap; info->param.debug_info.curr_rd_port = pmadapter->curr_rd_port; @@ -541,6 +551,47 @@ wlan_get_info_debug_info(IN pmlan_adapter pmadapter, } /** + * @brief Set/Get the MAC control configuration. + * + * @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_mac_control(IN pmlan_adapter pmadapter, + IN pmlan_ioctl_req pioctl_req) +{ + mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; + mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *) pioctl_req->pbuf; + mlan_status ret = MLAN_STATUS_SUCCESS; + t_u16 cmd_action = 0; + + ENTER(); + + misc = (mlan_ds_misc_cfg *) pioctl_req->pbuf; + + if (pioctl_req->action == MLAN_ACT_GET) { + misc->param.mac_ctrl = pmpriv->curr_pkt_filter; + } else { + pmpriv->curr_pkt_filter = misc->param.mac_ctrl; + cmd_action = HostCmd_ACT_GEN_SET; + + /* Send command to firmware */ + ret = wlan_prepare_cmd(pmpriv, + HostCmd_CMD_MAC_CONTROL, + cmd_action, 0, + (t_void *) pioctl_req, &misc->param.mac_ctrl); + + if (ret == MLAN_STATUS_SUCCESS) + ret = MLAN_STATUS_PENDING; + } + + LEAVE(); + return ret; +} + +/** * @brief This function wakes up the card. * * @param pmadapter A pointer to mlan_adapter structure @@ -749,6 +800,8 @@ wlan_free_mlan_buffer(mlan_adapter * pmadapter, pmlan_buffer pmbuf) ENTER(); if (pcb && pmbuf) { + if (pmbuf->flags & MLAN_BUF_FLAG_BRIDGE_BUF) + pmadapter->pending_bridge_pkts--; if (pmbuf->flags & MLAN_BUF_FLAG_MALLOC_BUF) pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *) pmbuf); else @@ -820,6 +873,24 @@ wlan_delay_func(mlan_adapter * pmadapter, t_u32 delay, t_delay_unit u) return; } +/** + * @brief BSS remove + * + * @param pmadapter A pointer to mlan_adapter structure + * @param pioctl_req A pointer to ioctl request buffer + * + * @return MLAN_STATUS_PENDING --success, MLAN_STATUS_FAILURE + */ +mlan_status +wlan_bss_ioctl_bss_remove(IN pmlan_adapter pmadapter, + IN pmlan_ioctl_req pioctl_req) +{ + ENTER(); + wlan_cancel_bss_pending_cmd(pmadapter, pioctl_req->bss_index); + LEAVE(); + return MLAN_STATUS_SUCCESS; +} + #if defined(STA_SUPPORT) && defined(UAP_SUPPORT) /** * @brief Set/Get BSS role @@ -947,7 +1018,8 @@ wlan_misc_ioctl_custom_ie_list(IN pmlan_adapter pmadapter, mlan_status ret = MLAN_STATUS_SUCCESS; mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *) pioctl_req->pbuf; custom_ie *ie_data = MNULL; - t_u16 cmd_action = 0, index, mask, i, len, app_data_len, ioctl_len; + t_u16 cmd_action = 0, index, mask, i, len, app_data_len; + t_s32 ioctl_len; t_u8 *tmp_ie; ENTER(); @@ -986,26 +1058,30 @@ wlan_misc_ioctl_custom_ie_list(IN pmlan_adapter pmadapter, if (ret == MLAN_STATUS_FAILURE) { goto done; } + index = ie_data->ie_index; memset(pmadapter, ie_data, 0, sizeof(custom_ie) * MAX_MGMT_IE_INDEX_TO_FW); len = 0; for (i = 0; i < pmadapter->max_mgmt_ie_index; i++) { - memcpy(pmadapter, (t_u8 *) ie_data + len, &i, - sizeof(ie_data->ie_index)); - len += sizeof(ie_data->ie_index); - memcpy(pmadapter, (t_u8 *) ie_data + len, - &pmpriv->mgmt_ie[i].mgmt_subtype_mask, - sizeof(ie_data->mgmt_subtype_mask)); - len += sizeof(ie_data->mgmt_subtype_mask); - memcpy(pmadapter, (t_u8 *) ie_data + len, - &pmpriv->mgmt_ie[i].ie_length, - sizeof(ie_data->ie_length)); - len += sizeof(ie_data->ie_length); - if (pmpriv->mgmt_ie[i].ie_length) { + /* Check if index is updated before sending to FW */ + if (index & ((t_u16) 1) << i) { + memcpy(pmadapter, (t_u8 *) ie_data + len, &i, + sizeof(ie_data->ie_index)); + len += sizeof(ie_data->ie_index); + memcpy(pmadapter, (t_u8 *) ie_data + len, + &pmpriv->mgmt_ie[i].mgmt_subtype_mask, + sizeof(ie_data->mgmt_subtype_mask)); + len += sizeof(ie_data->mgmt_subtype_mask); memcpy(pmadapter, (t_u8 *) ie_data + len, - &pmpriv->mgmt_ie[i].ie_buffer, - pmpriv->mgmt_ie[i].ie_length); - len += pmpriv->mgmt_ie[i].ie_length; + &pmpriv->mgmt_ie[i].ie_length, + sizeof(ie_data->ie_length)); + len += sizeof(ie_data->ie_length); + if (pmpriv->mgmt_ie[i].ie_length) { + memcpy(pmadapter, (t_u8 *) ie_data + len, + &pmpriv->mgmt_ie[i].ie_buffer, + pmpriv->mgmt_ie[i].ie_length); + len += pmpriv->mgmt_ie[i].ie_length; + } } } misc->param.cust_ie.len += len; @@ -1019,6 +1095,7 @@ wlan_misc_ioctl_custom_ie_list(IN pmlan_adapter pmadapter, ret = MLAN_STATUS_FAILURE; goto done; } + mask &= ~MLAN_CUSTOM_IE_NEW_MASK; if (MLAN_CUSTOM_IE_AUTO_IDX_MASK == index) { ret = MLAN_STATUS_SUCCESS; goto done; @@ -1092,7 +1169,18 @@ wlan_misc_ioctl_custom_ie_list(IN pmlan_adapter pmadapter, ie_data->ie_buffer, ie_data->ie_length)) { PRINTM(MIOCTL, "same custom ie already configured!\n"); - goto done; + if (ioctl_len <= 0 && misc->param.cust_ie.len == 0) { + goto done; + } else { + /* remove matching IE from app buffer */ + app_data_len -= + ie_data->ie_length + + MLAN_CUSTOM_IE_HDR_SIZE; + memmove(pmadapter, (t_u8 *) ie_data, + ie_data->ie_buffer + ie_data->ie_length, + ioctl_len); + continue; + } } } memset(pmadapter, &pmpriv->mgmt_ie[index], 0, @@ -1480,7 +1568,7 @@ wlan_set_drvdbg(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) ENTER(); /* Set driver debug bit masks */ - drvdbg = misc->param.drvdbg; + mlan_drvdbg = misc->param.drvdbg; LEAVE(); return ret; @@ -1577,10 +1665,8 @@ wlan_process_802dot11_mgmt_pkt(IN mlan_private * priv, (pmadapter, pieee_pkt_hdr->addr1, priv->curr_addr, MLAN_MAC_ADDR_LENGTH)) { PRINTM(MINFO, - "Dropping mgmt frame for others: type=%d %02x:%02x:%02x:%02x:%02x:%02x\n", - sub_type, pieee_pkt_hdr->addr1[0], pieee_pkt_hdr->addr1[1], - pieee_pkt_hdr->addr1[2], pieee_pkt_hdr->addr1[3], - pieee_pkt_hdr->addr1[4], pieee_pkt_hdr->addr1[5]); + "Dropping mgmt frame for others: type=%d " MACSTR "\n", + sub_type, MAC2STR(pieee_pkt_hdr->addr1)); LEAVE(); return ret; } @@ -1610,6 +1696,90 @@ wlan_process_802dot11_mgmt_pkt(IN mlan_private * priv, return MLAN_STATUS_SUCCESS; } +#ifdef STA_SUPPORT +/** + * @brief Extended capabilities configuration + * + * @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_ext_capa_cfg(IN pmlan_adapter pmadapter, + IN pmlan_ioctl_req pioctl_req) +{ + pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; + mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *) pioctl_req->pbuf; + mlan_status ret = MLAN_STATUS_SUCCESS; + + ENTER(); + + if (MLAN_ACT_GET == pioctl_req->action) + memcpy(pmpriv->adapter, &misc->param.ext_cap, &pmpriv->ext_cap, + sizeof(misc->param.ext_cap)); + else if (MLAN_ACT_SET == pioctl_req->action) { + memcpy(pmpriv->adapter, &pmpriv->ext_cap, &misc->param.ext_cap, + sizeof(misc->param.ext_cap)); + } + + LEAVE(); + return ret; +} + +/** + * @brief Check whether Extended Capabilities IE support + * + * @param pmpriv A pointer to mlan_private structure + * + * @return MTRUE or MFALSE; + */ +t_u32 +wlan_is_ext_capa_support(mlan_private * pmpriv) +{ + ENTER(); + + /* So far there are only three bits are meaningful */ + if (ISSUPP_EXTCAP_TDLS(pmpriv->ext_cap) + || ISSUPP_EXTCAP_INTERWORKING(pmpriv->ext_cap) + ) { + LEAVE(); + return MTRUE; + } else { + LEAVE(); + return MFALSE; + } +} +#endif + +#ifdef STA_SUPPORT +/** + * @brief Add Extended Capabilities IE + * + * @param pmpriv A pointer to mlan_private structure + * @param pptlv_out A pointer to TLV to fill in + * + * @return N/A + */ +void +wlan_add_ext_capa_info_ie(IN mlan_private * pmpriv, OUT t_u8 ** pptlv_out) +{ + MrvlIETypes_ExtCap_t *pext_cap = MNULL; + + ENTER(); + + pext_cap = (MrvlIETypes_ExtCap_t *) * pptlv_out; + memset(pmpriv->adapter, pext_cap, 0, sizeof(MrvlIETypes_ExtCap_t)); + pext_cap->header.type = wlan_cpu_to_le16(EXT_CAPABILITY); + pext_cap->header.len = wlan_cpu_to_le16(sizeof(ExtCap_t)); + memcpy(pmpriv->adapter, &pext_cap->ext_cap, &pmpriv->ext_cap, + sizeof(pmpriv->ext_cap)); + *pptlv_out += sizeof(MrvlIETypes_ExtCap_t); + + LEAVE(); +} +#endif + /** * @brief Get OTP user data * @@ -1895,42 +2065,64 @@ wlan_radio_ioctl_ant_cfg(IN pmlan_adapter pmadapter, mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; mlan_ds_radio_cfg *radio_cfg = MNULL; t_u16 cmd_action = 0; - mlan_ds_ant_cfg *ant_cfg; + mlan_ds_ant_cfg *ant_cfg = MNULL; + t_u16 *ant_cfg_1x1 = MNULL; ENTER(); radio_cfg = (mlan_ds_radio_cfg *) pioctl_req->pbuf; - ant_cfg = &radio_cfg->param.ant_cfg; + if (IS_STREAM_2X2(pmadapter->feature_control)) + ant_cfg = &radio_cfg->param.ant_cfg; if (pioctl_req->action == MLAN_ACT_SET) { /* User input validation */ - if (!ant_cfg->tx_antenna || - ant_cfg->tx_antenna & ~RF_ANTENNA_MASK(pmadapter-> - number_of_antenna)) { - PRINTM(MERROR, "Invalid antenna setting\n"); - pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER; - ret = MLAN_STATUS_FAILURE; - goto exit; - } - if (ant_cfg->rx_antenna) { - if (ant_cfg-> - rx_antenna & ~RF_ANTENNA_MASK(pmadapter->number_of_antenna)) { + if (IS_STREAM_2X2(pmadapter->feature_control)) { + if (!ant_cfg->tx_antenna || + ant_cfg->tx_antenna & ~RF_ANTENNA_MASK(pmadapter-> + number_of_antenna)) { PRINTM(MERROR, "Invalid antenna setting\n"); pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER; ret = MLAN_STATUS_FAILURE; goto exit; } - } else - ant_cfg->rx_antenna = ant_cfg->tx_antenna; + if (ant_cfg->rx_antenna) { + if (ant_cfg-> + rx_antenna & ~RF_ANTENNA_MASK(pmadapter-> + number_of_antenna)) { + PRINTM(MERROR, "Invalid antenna setting\n"); + pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER; + ret = MLAN_STATUS_FAILURE; + goto exit; + } + } else + ant_cfg->rx_antenna = ant_cfg->tx_antenna; + } else if ((!radio_cfg->param.antenna || + radio_cfg->param.antenna & ~RF_ANTENNA_MASK(pmadapter-> + number_of_antenna)) + && (radio_cfg->param.antenna != RF_ANTENNA_AUTO || + pmadapter->number_of_antenna <= 1)) { + PRINTM(MERROR, "Invalid antenna setting\n"); + pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER; + ret = MLAN_STATUS_FAILURE; + goto exit; + } cmd_action = HostCmd_ACT_GEN_SET; } else cmd_action = HostCmd_ACT_GEN_GET; + /* Cast it to t_u16, antenna mode for command HostCmd_CMD_802_11_RF_ANTENNA + requires 2 bytes */ + if (!IS_STREAM_2X2(pmadapter->feature_control)) + ant_cfg_1x1 = (t_u16 *) & radio_cfg->param.antenna; + /* Send request to firmware */ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_RF_ANTENNA, cmd_action, - 0, (t_void *) pioctl_req, (t_void *) ant_cfg); + 0, + (t_void *) pioctl_req, + (IS_STREAM_2X2(pmadapter->feature_control)) ? + (t_void *) ant_cfg : (t_void *) ant_cfg_1x1); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; @@ -1940,6 +2132,78 @@ wlan_radio_ioctl_ant_cfg(IN pmlan_adapter pmadapter, return ret; } +/** + * @brief Get rate bitmap + * + * @param pmadapter A pointer to mlan_adapter structure + * @param pioctl_req A pointer to ioctl request buffer + * + * @return MLAN_STATUS_PENDING --success, otherwise fail + */ +static mlan_status +wlan_rate_ioctl_get_rate_bitmap(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]; + + ENTER(); + + /* Send request to firmware */ + ret = wlan_prepare_cmd(pmpriv, + HostCmd_CMD_TX_RATE_CFG, + HostCmd_ACT_GEN_GET, + 0, (t_void *) pioctl_req, MNULL); + if (ret == MLAN_STATUS_SUCCESS) + ret = MLAN_STATUS_PENDING; + + LEAVE(); + return ret; +} + +/** + * @brief Set rate bitmap + * + * @param pmadapter A pointer to mlan_adapter structure + * @param pioctl_req A pointer to ioctl request buffer + * + * @return MLAN_STATUS_PENDING --success, otherwise fail + */ +static mlan_status +wlan_rate_ioctl_set_rate_bitmap(IN pmlan_adapter pmadapter, + IN pmlan_ioctl_req pioctl_req) +{ + mlan_ds_rate *ds_rate = MNULL; + mlan_status ret = MLAN_STATUS_FAILURE; + mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; + t_u16 *bitmap_rates = MNULL; + + ENTER(); + + ds_rate = (mlan_ds_rate *) pioctl_req->pbuf; + bitmap_rates = ds_rate->param.rate_cfg.bitmap_rates; + + PRINTM(MINFO, "RateBitmap=%04x%04x%04x%04x%04x%04x%04x%04x%04x%04x, " + "IsRateAuto=%d, DataRate=%d\n", + bitmap_rates[9], bitmap_rates[8], + bitmap_rates[7], bitmap_rates[6], + bitmap_rates[5], bitmap_rates[4], + bitmap_rates[3], bitmap_rates[2], + bitmap_rates[1], bitmap_rates[0], + pmpriv->is_data_rate_auto, pmpriv->data_rate); + + /* Send request to firmware */ + ret = wlan_prepare_cmd(pmpriv, + HostCmd_CMD_TX_RATE_CFG, + HostCmd_ACT_GEN_SET, + 0, (t_void *) pioctl_req, (t_void *) bitmap_rates); + if (ret == MLAN_STATUS_SUCCESS) + ret = MLAN_STATUS_PENDING; + + LEAVE(); + return ret; +} + /** * @brief Get rate value * @@ -2227,7 +2491,12 @@ wlan_rate_ioctl_cfg(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) ENTER(); rate = (mlan_ds_rate *) pioctl_req->pbuf; - if (rate->param.rate_cfg.rate_type == MLAN_RATE_VALUE) { + if (rate->param.rate_cfg.rate_type == MLAN_RATE_BITMAP) { + if (pioctl_req->action == MLAN_ACT_GET) + status = wlan_rate_ioctl_get_rate_bitmap(pmadapter, pioctl_req); + else + status = wlan_rate_ioctl_set_rate_bitmap(pmadapter, pioctl_req); + } else if (rate->param.rate_cfg.rate_type == MLAN_RATE_VALUE) { if (pioctl_req->action == MLAN_ACT_GET) status = wlan_rate_ioctl_get_rate_value(pmadapter, pioctl_req); else diff --git a/drivers/net/wireless/sd8797/mlan/mlan_scan.c b/drivers/net/wireless/sd8797/mlan/mlan_scan.c index 677ac6b0200b..a9cffd6d84d2 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_scan.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_scan.c @@ -97,19 +97,25 @@ typedef union /** Cipher suite definition */ enum cipher_suite { + CIPHER_SUITE_WEP40, CIPHER_SUITE_TKIP, CIPHER_SUITE_CCMP, + CIPHER_SUITE_WEP104, CIPHER_SUITE_MAX }; static t_u8 wpa_oui[CIPHER_SUITE_MAX][4] = { + {0x00, 0x50, 0xf2, 0x01}, /* WEP40 */ {0x00, 0x50, 0xf2, 0x02}, /* TKIP */ {0x00, 0x50, 0xf2, 0x04}, /* AES */ + {0x00, 0x50, 0xf2, 0x05}, /* WEP104 */ }; static t_u8 rsn_oui[CIPHER_SUITE_MAX][4] = { + {0x00, 0x0f, 0xac, 0x01}, /* WEP40 */ {0x00, 0x0f, 0xac, 0x02}, /* TKIP */ {0x00, 0x0f, 0xac, 0x04}, /* AES */ + {0x00, 0x0f, 0xac, 0x05}, /* WEP104 */ }; /** @@ -839,6 +845,7 @@ wlan_scan_setup_scan_config(IN mlan_private * pmpriv, MrvlIEtypes_NumProbes_t *pnum_probes_tlv; MrvlIEtypes_WildCardSsIdParamSet_t *pwildcard_ssid_tlv; MrvlIEtypes_RatesParamSet_t *prates_tlv; + const t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = { 0, 0, 0, 0, 0, 0 }; t_u8 *ptlv_pos; t_u32 num_probes; @@ -888,7 +895,6 @@ wlan_scan_setup_scan_config(IN mlan_private * pmpriv, /* Set the number of probes to send, use Adapter setting if unset */ num_probes = (puser_scan_in->num_probes ? puser_scan_in->num_probes : pmadapter->scan_probes); - /* * Set the BSSID filter to the incoming configuration, * if non-zero. If not set, it will remain disabled (all zeros). @@ -903,7 +909,7 @@ wlan_scan_setup_scan_config(IN mlan_private * pmpriv, ssid_idx++) { ssid_len = - wlan_strlen((t_s8 *) puser_scan_in->ssid_list[ssid_idx].ssid); + wlan_strlen((char *) puser_scan_in->ssid_list[ssid_idx].ssid); pwildcard_ssid_tlv = (MrvlIEtypes_WildCardSsIdParamSet_t *) ptlv_pos; @@ -1008,6 +1014,8 @@ wlan_scan_setup_scan_config(IN mlan_private * pmpriv, pht_cap->header.len = wlan_cpu_to_le16(pht_cap->header.len); } + if (wlan_is_ext_capa_support(pmpriv)) + wlan_add_ext_capa_info_ie(pmpriv, &ptlv_pos); wlan_add_wps_probe_request_ie(pmpriv, &ptlv_pos); /* @@ -1271,10 +1279,8 @@ wlan_interpret_bss_desc_with_ie(IN pmlan_adapter pmadapter, memcpy(pmadapter, pbss_entry->mac_address, pcurrent_ptr, MLAN_MAC_ADDR_LENGTH); - PRINTM(MINFO, "InterpretIE: AP MAC Addr-%02x:%02x:%02x:%02x:%02x:%02x\n", - pbss_entry->mac_address[0], pbss_entry->mac_address[1], - pbss_entry->mac_address[2], pbss_entry->mac_address[3], - pbss_entry->mac_address[4], pbss_entry->mac_address[5]); + PRINTM(MINFO, "InterpretIE: AP MAC Addr-" MACSTR "\n", + MAC2STR(pbss_entry->mac_address)); pcurrent_ptr += MLAN_MAC_ADDR_LENGTH; bytes_left_for_current_beacon -= MLAN_MAC_ADDR_LENGTH; @@ -1595,7 +1601,7 @@ wlan_interpret_bss_desc_with_ie(IN pmlan_adapter pmadapter, (IEEEtypes_OverlapBSSScanParam_t *) pcurrent_ptr; pbss_entry->overlap_bss_offset = (t_u16) (pcurrent_ptr - pbss_entry->pbeacon_buf); - HEXDUMP("InterpretIE: Resp HTCAP_IE", + HEXDUMP("InterpretIE: Resp OBSS_IE", (t_u8 *) pbss_entry->poverlap_bss_scan_param, (*(pbss_entry->poverlap_bss_scan_param)).ieee_hdr.len + sizeof(IEEEtypes_Header_t)); @@ -1974,11 +1980,9 @@ wlan_ret_802_11_scan_store_beacon(IN mlan_private * pmpriv, * No space for new beacon */ PRINTM(MCMND, "AppControl: No space beacon (%d): " - "%02x:%02x:%02x:%02x:%02x:%02x; sz=%03d, left=%03d\n", + MACSTR "; sz=%03d, left=%03d\n", beacon_idx, - pnew_beacon->mac_address[0], pnew_beacon->mac_address[1], - pnew_beacon->mac_address[2], pnew_beacon->mac_address[3], - pnew_beacon->mac_address[4], pnew_beacon->mac_address[5], + MAC2STR(pnew_beacon->mac_address), pnew_beacon->beacon_buf_size, (pmadapter->bcn_buf_size - (pmadapter->pbcn_buf_end - pmadapter->bcn_buf))); @@ -2138,15 +2142,10 @@ wlan_scan_process_results(IN mlan_private * pmpriv) } for (i = 0; i < pmadapter->num_in_scan_table; i++) - PRINTM(MINFO, "Scan:(%02d) %02x:%02x:%02x:%02x:%02x:%02x, " + PRINTM(MINFO, "Scan:(%02d) " MACSTR ", " "RSSI[%03d], SSID[%s]\n", i, - pmadapter->pscan_table[i].mac_address[0], - pmadapter->pscan_table[i].mac_address[1], - pmadapter->pscan_table[i].mac_address[2], - pmadapter->pscan_table[i].mac_address[3], - pmadapter->pscan_table[i].mac_address[4], - pmadapter->pscan_table[i].mac_address[5], + MAC2STR(pmadapter->pscan_table[i].mac_address), (t_s32) pmadapter->pscan_table[i].rssi, pmadapter->pscan_table[i].ssid.ssid); @@ -2473,6 +2472,25 @@ wlan_is_network_compatible(IN mlan_private * pmpriv, /* Static WEP enabled */ PRINTM(MINFO, "Disable 11n in WEP mode\n"); pbss_desc->disable_11n = MTRUE; + /* Reject the following cases: */ + /* case 1: RSN IE w/o WEP OUI and WPA IE w/o WEP OUI case 2: RSN IE + w/o WEP OUI and No WPA IE case 3: WPA IE w/o WEP OUI and No RSN + IE * */ + if (((pbss_desc->prsn_ie) && + ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id == RSN_IE)) || + ((pbss_desc->pwpa_ie) && + ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id == WPA_IE))) { + if (!is_rsn_oui_present + (pmpriv->adapter, pbss_desc, CIPHER_SUITE_WEP40) && + !is_rsn_oui_present(pmpriv->adapter, pbss_desc, + CIPHER_SUITE_WEP104) && + !is_wpa_oui_present(pmpriv->adapter, pbss_desc, + CIPHER_SUITE_WEP40) && + !is_wpa_oui_present(pmpriv->adapter, pbss_desc, + CIPHER_SUITE_WEP104)) + index = -1; + } + LEAVE(); return index; } else if (pmpriv->sec_info.wep_status == Wlan802_11WEPDisabled @@ -2967,11 +2985,8 @@ wlan_ret_802_11_scan(IN mlan_private * pmpriv, &pbss_info, &bytes_left) == MLAN_STATUS_SUCCESS) { - PRINTM(MINFO, "SCAN_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n", - bss_new_entry->mac_address[0], bss_new_entry->mac_address[1], - bss_new_entry->mac_address[2], bss_new_entry->mac_address[3], - bss_new_entry->mac_address[4], - bss_new_entry->mac_address[5]); + PRINTM(MINFO, "SCAN_RESP: BSSID = " MACSTR "\n", + MAC2STR(bss_new_entry->mac_address)); band = BAND_G; if (pchan_band_tlv) { @@ -3021,6 +3036,7 @@ wlan_ret_802_11_scan(IN mlan_private * pmpriv, bss_new_entry->ssid.ssid_len))) { PRINTM(MINFO, "SCAN_RESP: Duplicate of index: %d\n", bss_idx); + break; } /* @@ -3357,11 +3373,8 @@ wlan_parse_ext_scan_result(IN mlan_private * pmpriv, &pbss_info, &bytes_left) == MLAN_STATUS_SUCCESS) { - PRINTM(MINFO, "EXT_SCAN: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n", - bss_new_entry->mac_address[0], bss_new_entry->mac_address[1], - bss_new_entry->mac_address[2], bss_new_entry->mac_address[3], - bss_new_entry->mac_address[4], - bss_new_entry->mac_address[5]); + PRINTM(MINFO, "EXT_SCAN: BSSID = " MACSTR "\n", + MAC2STR(bss_new_entry->mac_address)); band = BAND_G; /* @@ -3847,7 +3860,7 @@ wlan_cmd_bgscan_config(IN mlan_private * pmpriv, && (*bg_scan_in->ssid_list[ssid_idx].ssid || bg_scan_in->ssid_list[ssid_idx].max_len)); ssid_idx++) { - ssid_len = wlan_strlen((t_s8 *) bg_scan_in->ssid_list[ssid_idx].ssid); + ssid_len = wlan_strlen((char *) bg_scan_in->ssid_list[ssid_idx].ssid); pwildcard_ssid_tlv = (MrvlIEtypes_WildCardSsIdParamSet_t *) tlv; pwildcard_ssid_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_WILDCARDSSID); @@ -4058,15 +4071,10 @@ wlan_find_ssid_in_list(IN mlan_private * pmpriv, || !memcmp(pmadapter, pmadapter->pscan_table[i].mac_address, bssid, MLAN_MAC_ADDR_LENGTH))) { - if (((mode == MLAN_BSS_MODE_INFRA) && - !wlan_is_band_compatible(pmpriv->config_bands, - pmadapter->pscan_table[i].bss_band)) - || - (wlan_find_cfp_by_band_and_channel - (pmadapter, (t_u8) pmadapter->pscan_table[i].bss_band, - (t_u16) pmadapter->pscan_table[i].channel) == MNULL)) { + if ((mode == MLAN_BSS_MODE_INFRA) && + !wlan_is_band_compatible(pmpriv->config_bands, + pmadapter->pscan_table[i].bss_band)) continue; - } switch (mode) { case MLAN_BSS_MODE_INFRA: @@ -4142,15 +4150,10 @@ wlan_find_bssid_in_list(IN mlan_private * pmpriv, if (!memcmp (pmadapter, pmadapter->pscan_table[i].mac_address, bssid, MLAN_MAC_ADDR_LENGTH)) { - if (((mode == MLAN_BSS_MODE_INFRA) && - !wlan_is_band_compatible(pmpriv->config_bands, - pmadapter->pscan_table[i].bss_band)) - || - (wlan_find_cfp_by_band_and_channel - (pmadapter, (t_u8) pmadapter->pscan_table[i].bss_band, - (t_u16) pmadapter->pscan_table[i].channel) == MNULL)) { + if ((mode == MLAN_BSS_MODE_INFRA) && + !wlan_is_band_compatible(pmpriv->config_bands, + pmadapter->pscan_table[i].bss_band)) continue; - } switch (mode) { case MLAN_BSS_MODE_INFRA: case MLAN_BSS_MODE_IBSS: @@ -4262,11 +4265,8 @@ wlan_find_best_network(IN mlan_private * pmpriv, } PRINTM(MINFO, "Best network found = [%s], " - "[%02x:%02x:%02x:%02x:%02x:%02x]\n", - preq_ssid_bssid->ssid.ssid, - preq_ssid_bssid->bssid[0], preq_ssid_bssid->bssid[1], - preq_ssid_bssid->bssid[2], preq_ssid_bssid->bssid[3], - preq_ssid_bssid->bssid[4], preq_ssid_bssid->bssid[5]); + "[" MACSTR "]\n", + preq_ssid_bssid->ssid.ssid, MAC2STR(preq_ssid_bssid->bssid)); done: LEAVE(); diff --git a/drivers/net/wireless/sd8797/mlan/mlan_sdio.c b/drivers/net/wireless/sd8797/mlan/mlan_sdio.c index 75799af4ae99..b7427c1682c1 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_sdio.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_sdio.c @@ -138,7 +138,7 @@ wlan_write_data_sync(mlan_adapter * pmadapter, mlan_buffer * pmbuf, t_u32 port) ret); if (MLAN_STATUS_SUCCESS != pcb->moal_write_reg(pmadapter->pmoal_handle, - HOST_TO_CARD_EVENT_REG, 0x04)) { + HOST_TO_CARD_EVENT_REG, HOST_TERM_CMD53)) { PRINTM(MERROR, "write CFG reg failed\n"); } ret = MLAN_STATUS_FAILURE; @@ -588,7 +588,7 @@ wlan_prog_fw_w_helper(IN pmlan_adapter pmadapter, IN pmlan_fw_image pmfw) i, offset); if (pcb-> moal_write_reg(pmadapter->pmoal_handle, HOST_TO_CARD_EVENT_REG, - 0x04) != MLAN_STATUS_SUCCESS) { + HOST_TERM_CMD53) != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "write CFG reg failed\n"); } ret = MLAN_STATUS_FAILURE; @@ -1186,7 +1186,6 @@ wlan_interrupt(pmlan_adapter pmadapter) t_u32 sdio_ireg = 0; ENTER(); - memset(pmadapter, &mbuf, 0, sizeof(mlan_buffer)); mbuf.pbuf = pmadapter->mp_regs; mbuf.data_len = MAX_MP_REGS; diff --git a/drivers/net/wireless/sd8797/mlan/mlan_sdio.h b/drivers/net/wireless/sd8797/mlan/mlan_sdio.h index f77397d66eb4..b5eb87706d96 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_sdio.h +++ b/drivers/net/wireless/sd8797/mlan/mlan_sdio.h @@ -27,9 +27,14 @@ Change log: #define _MLAN_SDIO_H /** Block mode */ +#ifndef BLOCK_MODE #define BLOCK_MODE 1 +#endif + /** Fixed address mode */ +#ifndef FIXED_ADDRESS #define FIXED_ADDRESS 0 +#endif /* Host Control Registers */ /** Host Control Registers : Host to Card Event */ @@ -45,12 +50,14 @@ Change log: /** Host Control Registers : Host interrupt RSR */ #define HOST_INT_RSR_REG 0x01 + /** Host Control Registers : Upload host interrupt RSR */ #define UP_LD_HOST_INT_RSR (0x1U) #define HOST_INT_RSR_MASK 0x3F /** Host Control Registers : Host interrupt mask */ #define HOST_INT_MASK_REG 0x02 + /** Host Control Registers : Upload host interrupt mask */ #define UP_LD_HOST_INT_MASK (0x1U) /** Host Control Registers : Download host interrupt mask */ @@ -62,6 +69,7 @@ Change log: /** Host Control Registers : Host interrupt status */ #define HOST_INT_STATUS_REG 0x03 + /** Host Control Registers : Upload host interrupt status */ #define UP_LD_HOST_INT_STATUS (0x1U) /** Host Control Registers : Download host interrupt status */ diff --git a/drivers/net/wireless/sd8797/mlan/mlan_shim.c b/drivers/net/wireless/sd8797/mlan/mlan_shim.c index ed7b89d535fb..4d650496039d 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_shim.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_shim.c @@ -107,7 +107,7 @@ t_void(*assert_callback) (IN t_void * pmoal_handle, IN t_u32 cond) = MNULL; /** Global moal_print callback */ t_void(*print_callback) (IN t_void * pmoal_handle, - IN t_u32 level, IN t_s8 * pformat, IN ...) = MNULL; + IN t_u32 level, IN char *pformat, IN ...) = MNULL; /** Global moal_get_system_time callback */ mlan_status(*get_sys_time_callback) (IN t_void * pmoal_handle, @@ -115,7 +115,7 @@ mlan_status(*get_sys_time_callback) (IN t_void * pmoal_handle, OUT t_u32 * pusec) = MNULL; /** Global driver debug mit masks */ -t_u32 drvdbg = DEFAULT_DEBUG_MASK; +t_u32 mlan_drvdbg = DEFAULT_DEBUG_MASK; #endif /******************************************************** @@ -178,15 +178,21 @@ mlan_register(IN pmlan_device pmdevice, OUT t_void ** ppmlan_adapter) MASSERT(pmdevice->callbacks.moal_memmove); /* Allocate memory for adapter structure */ - if ((pmdevice->callbacks. - moal_malloc(pmdevice->pmoal_handle, sizeof(mlan_adapter), MLAN_MEM_DEF, - (t_u8 **) & pmadapter) != MLAN_STATUS_SUCCESS) - || !pmadapter) { + if (pmdevice->callbacks.moal_vmalloc && pmdevice->callbacks.moal_vfree) + ret = pmdevice->callbacks.moal_vmalloc(pmdevice->pmoal_handle, + sizeof(mlan_adapter), + (t_u8 **) & pmadapter); + else + ret = pmdevice->callbacks.moal_malloc(pmdevice->pmoal_handle, + sizeof(mlan_adapter), + MLAN_MEM_DEF, + (t_u8 **) & pmadapter); + if ((ret != MLAN_STATUS_SUCCESS) || !pmadapter) { ret = MLAN_STATUS_FAILURE; goto exit_register; } - pmdevice->callbacks.moal_memset(pmadapter, pmadapter, + pmdevice->callbacks.moal_memset(pmdevice->pmoal_handle, pmadapter, 0, sizeof(mlan_adapter)); pcb = &pmadapter->callbacks; @@ -203,6 +209,7 @@ mlan_register(IN pmlan_device pmdevice, OUT t_void ** ppmlan_adapter) MASSERT(pcb->moal_recv_packet); MASSERT(pcb->moal_recv_event); MASSERT(pcb->moal_ioctl_complete); + MASSERT(pcb->moal_write_reg); MASSERT(pcb->moal_read_reg); MASSERT(pcb->moal_alloc_mlan_buffer); @@ -225,6 +232,8 @@ mlan_register(IN pmlan_device pmdevice, OUT t_void ** ppmlan_adapter) /* Save pmoal_handle */ pmadapter->pmoal_handle = pmdevice->pmoal_handle; + pmadapter->feature_control = pmdevice->feature_control; + if ((pmdevice->int_mode == INT_MODE_GPIO) && (pmdevice->gpio_pin == 0)) { PRINTM(MERROR, "SDIO_GPIO_INT_CONFIG: Invalid GPIO Pin\n"); ret = MLAN_STATUS_FAILURE; @@ -238,7 +247,7 @@ mlan_register(IN pmlan_device pmdevice, OUT t_void ** ppmlan_adapter) goto error; } #ifdef DEBUG_LEVEL1 - drvdbg = pmdevice->drvdbg; + mlan_drvdbg = pmdevice->drvdbg; #endif #ifdef MFG_CMD_SUPPORT @@ -261,7 +270,9 @@ mlan_register(IN pmlan_device pmdevice, OUT t_void ** ppmlan_adapter) #else pmadapter->init_para.cfg_11d = 0; #endif - pmadapter->init_para.dfs_master_radar_det_en = DFS_MASTER_RADAR_DETECT_EN; + if (IS_DFS_SUPPORT(pmadapter->feature_control)) + pmadapter->init_para.dfs_master_radar_det_en = + DFS_MASTER_RADAR_DETECT_EN; pmadapter->init_para.dfs_slave_radar_det_en = DFS_SLAVE_RADAR_DETECT_EN; pmadapter->priv_num = 0; @@ -269,12 +280,17 @@ mlan_register(IN pmlan_device pmdevice, OUT t_void ** ppmlan_adapter) pmadapter->priv[i] = MNULL; if (pmdevice->bss_attr[i].active == MTRUE) { /* For valid bss_attr, allocate memory for private structure */ - if ((pcb-> - moal_malloc(pmadapter->pmoal_handle, sizeof(mlan_private), - MLAN_MEM_DEF, - (t_u8 **) & pmadapter->priv[i]) != - MLAN_STATUS_SUCCESS) - || !pmadapter->priv[i]) { + if (pcb->moal_vmalloc && pcb->moal_vfree) + ret = + pcb->moal_vmalloc(pmadapter->pmoal_handle, + sizeof(mlan_private), + (t_u8 **) & pmadapter->priv[i]); + else + ret = + pcb->moal_malloc(pmadapter->pmoal_handle, + sizeof(mlan_private), MLAN_MEM_DEF, + (t_u8 **) & pmadapter->priv[i]); + if (ret != MLAN_STATUS_SUCCESS || !pmadapter->priv[i]) { ret = MLAN_STATUS_FAILURE; goto error; } @@ -296,8 +312,11 @@ mlan_register(IN pmlan_device pmdevice, OUT t_void ** ppmlan_adapter) else if (pmdevice->bss_attr[i].bss_type == MLAN_BSS_TYPE_UAP) pmadapter->priv[i]->bss_role = MLAN_BSS_ROLE_UAP; #ifdef WIFI_DIRECT_SUPPORT - else if (pmdevice->bss_attr[i].bss_type == MLAN_BSS_TYPE_WIFIDIRECT) + else if (pmdevice->bss_attr[i].bss_type == MLAN_BSS_TYPE_WIFIDIRECT) { pmadapter->priv[i]->bss_role = MLAN_BSS_ROLE_STA; + if (pmdevice->bss_attr[i].bss_virtual) + pmadapter->priv[i]->bss_virtual = MTRUE; + } #endif /* Save bss_index and bss_num */ pmadapter->priv[i]->bss_index = i; @@ -344,11 +363,19 @@ mlan_register(IN pmlan_device pmdevice, OUT t_void ** ppmlan_adapter) /* Free lock variables */ wlan_free_lock_list(pmadapter); for (i = 0; i < MLAN_MAX_BSS_NUM; i++) { - if (pmadapter->priv[i]) - pcb->moal_mfree(pmadapter->pmoal_handle, - (t_u8 *) pmadapter->priv[i]); + if (pmadapter->priv[i]) { + if (pcb->moal_vmalloc && pcb->moal_vfree) + pcb->moal_vfree(pmadapter->pmoal_handle, + (t_u8 *) pmadapter->priv[i]); + else + pcb->moal_mfree(pmadapter->pmoal_handle, + (t_u8 *) pmadapter->priv[i]); + } } - pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *) pmadapter); + if (pcb->moal_vmalloc && pcb->moal_vfree) + pcb->moal_vfree(pmadapter->pmoal_handle, (t_u8 *) pmadapter); + else + pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *) pmadapter); exit_register: LEAVE(); @@ -390,13 +417,20 @@ mlan_unregister(IN t_void * pmlan_adapter) /* Free private structures */ for (i = 0; i < pmadapter->priv_num; i++) { if (pmadapter->priv[i]) { - pcb->moal_mfree(pmadapter->pmoal_handle, - (t_u8 *) pmadapter->priv[i]); + if (pcb->moal_vmalloc && pcb->moal_vfree) + pcb->moal_vfree(pmadapter->pmoal_handle, + (t_u8 *) pmadapter->priv[i]); + else + pcb->moal_mfree(pmadapter->pmoal_handle, + (t_u8 *) pmadapter->priv[i]); } } /* Free mlan_adapter */ - pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *) pmadapter); + if (pcb->moal_vmalloc && pcb->moal_vfree) + pcb->moal_vfree(pmadapter->pmoal_handle, (t_u8 *) pmadapter); + else + pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *) pmadapter); LEAVE(); return ret; @@ -595,22 +629,9 @@ mlan_shutdown_fw(IN t_void * pmlan_adapter) pcb = &pmadapter->callbacks; - if (pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pmlan_lock) - != MLAN_STATUS_SUCCESS) { - ret = MLAN_STATUS_FAILURE; - goto exit_shutdown_fw; - } - - if (pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pmlan_lock) - != MLAN_STATUS_SUCCESS) { - ret = MLAN_STATUS_FAILURE; - goto exit_shutdown_fw; - } - /* Notify completion */ ret = wlan_shutdown_fw_complete(pmadapter); - exit_shutdown_fw: LEAVE(); return ret; } @@ -639,6 +660,7 @@ mlan_main_process(IN t_void * pmlan_adapter) /* Check if already processing */ if (pmadapter->mlan_processing) { + pmadapter->more_task_flag = MTRUE; pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pmain_proc_lock); goto exit_main_proc; @@ -649,6 +671,11 @@ mlan_main_process(IN t_void * pmlan_adapter) } process_start: do { + pcb->moal_spin_lock(pmadapter->pmoal_handle, + pmadapter->pmain_proc_lock); + pmadapter->more_task_flag = MFALSE; + pcb->moal_spin_unlock(pmadapter->pmoal_handle, + pmadapter->pmain_proc_lock); /* Is MLAN shutting down or not ready? */ if ((pmadapter->hw_status == WlanHardwareStatusClosing) || (pmadapter->hw_status == WlanHardwareStatusNotReady)) @@ -694,7 +721,8 @@ mlan_main_process(IN t_void * pmlan_adapter) (pmadapter->tx_lock_flag == MTRUE)) break; - if (pmadapter->scan_processing || pmadapter->data_sent + if (pmadapter->scan_processing + || pmadapter->data_sent || (wlan_bypass_tx_list_empty(pmadapter) && wlan_wmm_lists_empty(pmadapter)) || wlan_11h_radar_detected_tx_blocked(pmadapter) @@ -751,7 +779,8 @@ mlan_main_process(IN t_void * pmlan_adapter) } } - if (!pmadapter->scan_processing && !pmadapter->data_sent && + if (!pmadapter->scan_processing + && !pmadapter->data_sent && !wlan_11h_radar_detected_tx_blocked(pmadapter) && !wlan_bypass_tx_list_empty(pmadapter)) { PRINTM(MINFO, "mlan_send_pkt(): deq(bybass_txq)\n"); @@ -764,8 +793,8 @@ mlan_main_process(IN t_void * pmlan_adapter) } } - if (!pmadapter->scan_processing && !pmadapter->data_sent && - !wlan_wmm_lists_empty(pmadapter) + if (!pmadapter->scan_processing + && !pmadapter->data_sent && !wlan_wmm_lists_empty(pmadapter) && !wlan_11h_radar_detected_tx_blocked(pmadapter) ) { wlan_wmm_process_tx(pmadapter); @@ -795,10 +824,12 @@ mlan_main_process(IN t_void * pmlan_adapter) } while (MTRUE); - if ((pmadapter->sdio_ireg) || IS_CARD_RX_RCVD(pmadapter)) { + pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pmain_proc_lock); + if (pmadapter->more_task_flag == MTRUE) { + pcb->moal_spin_unlock(pmadapter->pmoal_handle, + pmadapter->pmain_proc_lock); goto process_start; } - pcb->moal_spin_lock(pmadapter->pmoal_handle, pmadapter->pmain_proc_lock); pmadapter->mlan_processing = MFALSE; pcb->moal_spin_unlock(pmadapter->pmoal_handle, pmadapter->pmain_proc_lock); diff --git a/drivers/net/wireless/sd8797/mlan/mlan_sta_cmd.c b/drivers/net/wireless/sd8797/mlan/mlan_sta_cmd.c index 787e5784ed43..52b6bced6009 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_sta_cmd.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_sta_cmd.c @@ -86,40 +86,6 @@ wlan_cmd_802_11_rssi_info(IN pmlan_private pmpriv, } /** - * @brief This function prepares command of mac_control. - * - * @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 command information buffer - * - * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE - */ -static mlan_status -wlan_cmd_mac_control(IN pmlan_private pmpriv, - IN HostCmd_DS_COMMAND * pcmd, - IN t_u16 cmd_action, IN t_void * pdata_buf) -{ - HostCmd_DS_MAC_CONTROL *pmac = &pcmd->params.mac_ctrl; - t_u16 action = *((t_u16 *) pdata_buf); - - ENTER(); - - if (cmd_action != HostCmd_ACT_GEN_SET) { - PRINTM(MERROR, "wlan_cmd_mac_control(): support SET only.\n"); - LEAVE(); - return MLAN_STATUS_FAILURE; - } - - pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_MAC_CONTROL); - pcmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_MAC_CONTROL) + S_DS_GEN); - pmac->action = wlan_cpu_to_le16(action); - - LEAVE(); - return MLAN_STATUS_SUCCESS; -} - -/** * @brief This function prepares command of snmp_mib. * * @param pmpriv A pointer to mlan_private structure @@ -355,6 +321,41 @@ wlan_cmd_802_11_rf_tx_power(IN pmlan_private pmpriv, return MLAN_STATUS_SUCCESS; } +#ifdef WIFI_DIRECT_SUPPORT +/** + * @brief Check if any p2p interface is conencted + * + * @param pmadapter A pointer to mlan_adapter structure + * + * @return MTRUE/MFALSE; + */ +static t_u8 +wlan_is_p2p_connected(IN pmlan_adapter pmadapter) +{ + int j; + pmlan_private priv; + ENTER(); + for (j = 0; j < pmadapter->priv_num; ++j) { + if ((priv = pmadapter->priv[j])) { + if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) { + if ((priv->bss_role == MLAN_BSS_ROLE_STA) && + (priv->media_connected == MTRUE)) { + LEAVE(); + return MTRUE; + } + if ((priv->bss_role == MLAN_BSS_ROLE_UAP) && + (priv->uap_bss_started == MTRUE)) { + LEAVE(); + return MTRUE; + } + } + } + } + LEAVE(); + return MFALSE; +} +#endif + /** * @brief This function prepares command of hs_cfg. * @@ -373,6 +374,8 @@ wlan_cmd_802_11_hs_cfg(IN pmlan_private pmpriv, pmlan_adapter pmadapter = pmpriv->adapter; HostCmd_DS_802_11_HS_CFG_ENH *phs_cfg = &cmd->params.opt_hs_cfg; t_u16 hs_activate = MFALSE; + t_u8 *tlv = (t_u8 *) phs_cfg + sizeof(HostCmd_DS_802_11_HS_CFG_ENH); + MrvlIEtypes_HsWakeHoldoff_t *holdoff_tlv = MNULL; ENTER(); @@ -391,25 +394,49 @@ wlan_cmd_802_11_hs_cfg(IN pmlan_private pmpriv, ((t_u8 *) phs_cfg) + sizeof(HostCmd_DS_802_11_HS_CFG_ENH), pmadapter->arp_filter, pmadapter->arp_filter_size); cmd->size = - (t_u16) wlan_cpu_to_le16(pmadapter->arp_filter_size + - sizeof(HostCmd_DS_802_11_HS_CFG_ENH) + - S_DS_GEN); + 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 = - wlan_cpu_to_le16(S_DS_GEN + sizeof(HostCmd_DS_802_11_HS_CFG_ENH)); + cmd->size = S_DS_GEN + sizeof(HostCmd_DS_802_11_HS_CFG_ENH); if (hs_activate) { + cmd->size = wlan_cpu_to_le16(cmd->size); phs_cfg->action = wlan_cpu_to_le16(HS_ACTIVATE); phs_cfg->params.hs_activate.resp_ctrl = wlan_cpu_to_le16(RESP_NEEDED); } else { phs_cfg->action = wlan_cpu_to_le16(HS_CONFIGURE); - phs_cfg->params.hs_config.conditions = - wlan_cpu_to_le32(pdata_buf->conditions); +#ifdef WIFI_DIRECT_SUPPORT + if (wlan_is_p2p_connected(pmadapter)) + phs_cfg->params.hs_config.conditions = + wlan_cpu_to_le32(pdata_buf-> + conditions | HOST_SLEEP_COND_MULTICAST_DATA); + else +#endif + phs_cfg->params.hs_config.conditions = + wlan_cpu_to_le32(pdata_buf->conditions); phs_cfg->params.hs_config.gpio = pdata_buf->gpio; phs_cfg->params.hs_config.gap = pdata_buf->gap; - PRINTM(MCMND, "HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n", + if (pmadapter->min_wake_holdoff) { + cmd->size += sizeof(MrvlIEtypes_HsWakeHoldoff_t); + holdoff_tlv = (MrvlIEtypes_HsWakeHoldoff_t *) tlv; + holdoff_tlv->header.type = + wlan_cpu_to_le16(TLV_TYPE_HS_WAKE_HOLDOFF); + holdoff_tlv->header.len = + wlan_cpu_to_le16(sizeof(MrvlIEtypes_HsWakeHoldoff_t) - + sizeof(MrvlIEtypesHeader_t)); + holdoff_tlv->min_wake_holdoff = + wlan_cpu_to_le16(pmadapter->min_wake_holdoff); + PRINTM(MCMND, "min_wake_holdoff=%d\n", pmadapter->min_wake_holdoff); + } + cmd->size = wlan_cpu_to_le16(cmd->size); + PRINTM(MCMND, + "HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x holdoff=%d\n", phs_cfg->params.hs_config.conditions, - phs_cfg->params.hs_config.gpio, phs_cfg->params.hs_config.gap); + phs_cfg->params.hs_config.gpio, phs_cfg->params.hs_config.gap, + pmadapter->min_wake_holdoff); } LEAVE(); @@ -578,9 +605,7 @@ wlan_cmd_802_11_deauthenticate(IN pmlan_private pmpriv, memcpy(pmpriv->adapter, pdeauth->mac_addr, (t_u8 *) pdata_buf, MLAN_MAC_ADDR_LENGTH); - PRINTM(MCMND, "Deauth: %02x:%02x:%02x:%02x:%02x:%02x\n", - pdeauth->mac_addr[0], pdeauth->mac_addr[1], pdeauth->mac_addr[2], - pdeauth->mac_addr[3], pdeauth->mac_addr[4], pdeauth->mac_addr[5]); + PRINTM(MCMND, "Deauth: " MACSTR "\n", MAC2STR(pdeauth->mac_addr)); if (pmpriv->adapter->state_11h.recvd_chanswann_event) { /** Reason code 36 = Requested from peer station as it is leaving the BSS */ @@ -621,74 +646,6 @@ wlan_cmd_802_11_ad_hoc_stop(IN pmlan_private pmpriv, } /** - * @brief This function sets WEP key(s) to key_param_set TLV(s). - * - * @param priv A pointer to mlan_private structure - * @param key_param_set A pointer to MrvlIEtype_KeyParamSet_t structure - * @param key_param_len A pointer to the length variable - * - * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE - */ -static mlan_status -wlan_set_keyparamset_wep(mlan_private * priv, - MrvlIEtype_KeyParamSet_t * key_param_set, - t_u16 * key_param_len) -{ - int cur_key_param_len = 0; - t_u8 i; - mlan_status ret = MLAN_STATUS_SUCCESS; - - ENTER(); - - /* Multi-key_param_set TLV is supported */ - for (i = 0; i < MRVL_NUM_WEP_KEY; i++) { - if ((priv->wep_key[i].key_length == WEP_40_BIT_LEN) || - (priv->wep_key[i].key_length == WEP_104_BIT_LEN)) { - key_param_set->type = wlan_cpu_to_le16(TLV_TYPE_KEY_MATERIAL); -/** Key_param_set WEP fixed length */ -#define KEYPARAMSET_WEP_FIXED_LEN 8 - key_param_set->length = - wlan_cpu_to_le16((t_u16) - (priv->wep_key[i].key_length + - KEYPARAMSET_WEP_FIXED_LEN)); - key_param_set->key_type_id = wlan_cpu_to_le16(KEY_TYPE_ID_WEP); - key_param_set->key_info = wlan_cpu_to_le16 - (KEY_INFO_WEP_ENABLED | KEY_INFO_WEP_UNICAST | - KEY_INFO_WEP_MCAST); - key_param_set->key_len = - (t_u16) wlan_cpu_to_le16(priv->wep_key[i].key_length); - /* Set WEP key index */ - key_param_set->key[0] = i; - /* Set default Tx key flag */ - if (i == (priv->wep_key_curr_index & HostCmd_WEP_KEY_INDEX_MASK)) - key_param_set->key[1] = 1; - else - key_param_set->key[1] = 0; - memmove(priv->adapter, &key_param_set->key[2], - priv->wep_key[i].key_material, priv->wep_key[i].key_length); - - cur_key_param_len = priv->wep_key[i].key_length + - KEYPARAMSET_WEP_FIXED_LEN + sizeof(MrvlIEtypesHeader_t); - *key_param_len += (t_u16) cur_key_param_len; - key_param_set = - (MrvlIEtype_KeyParamSet_t *) ((t_u8 *) key_param_set + - cur_key_param_len); - } else if (!priv->wep_key[i].key_length) { - continue; - } else { - PRINTM(MERROR, "key%d Length = %d is incorrect\n", (i + 1), - priv->wep_key[i].key_length); - ret = MLAN_STATUS_FAILURE; - goto done; - } - } - - done: - LEAVE(); - return ret; -} - -/** * @brief This function prepares command of key_material. * * @param pmpriv A pointer to mlan_private structure @@ -707,186 +664,203 @@ wlan_cmd_802_11_key_material(IN pmlan_private pmpriv, { HostCmd_DS_802_11_KEY_MATERIAL *pkey_material = &cmd->params.key_material; mlan_ds_encrypt_key *pkey = (mlan_ds_encrypt_key *) pdata_buf; - t_u16 key_param_len = 0; mlan_status ret = MLAN_STATUS_SUCCESS; - const t_u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; ENTER(); - + if (!pkey) { + ret = MLAN_STATUS_FAILURE; + goto done; + } cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL); pkey_material->action = wlan_cpu_to_le16(cmd_action); - if (cmd_action == HostCmd_ACT_GEN_GET) { - cmd->size = - wlan_cpu_to_le16(sizeof(pkey_material->action) + S_DS_GEN + - KEYPARAMSET_FIXED_LEN + - sizeof(MrvlIEtypesHeader_t)); - memset(pmpriv->adapter, &pkey_material->key_param_set, 0, - sizeof(MrvlIEtype_KeyParamSet_t)); + PRINTM(MCMND, "GET Key\n"); + pkey_material->key_param_set.key_idx = pkey->key_index & KEY_INDEX_MASK; pkey_material->key_param_set.type = - wlan_cpu_to_le16(TLV_TYPE_KEY_MATERIAL); + wlan_cpu_to_le16(TLV_TYPE_KEY_PARAM_V2); pkey_material->key_param_set.length = - wlan_cpu_to_le16(KEYPARAMSET_FIXED_LEN); + wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN); + memcpy(pmpriv->adapter, pkey_material->key_param_set.mac_addr, + pkey->mac_addr, MLAN_MAC_ADDR_LENGTH); if (pkey->key_flags & KEY_FLAG_GROUP_KEY) pkey_material->key_param_set.key_info |= KEY_INFO_MCAST_KEY; 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_AES_MCAST_IGTK; + pkey_material->key_param_set.key_info = KEY_INFO_CMAC_AES_KEY; pkey_material->key_param_set.key_info = wlan_cpu_to_le16(pkey_material->key_param_set.key_info); + cmd->size = + wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) + S_DS_GEN + + KEY_PARAMS_FIXED_LEN + + sizeof(pkey_material->action)); goto done; } - - if (!pkey) { - memset(pmpriv->adapter, &pkey_material->key_param_set, 0, - (MRVL_NUM_WEP_KEY * sizeof(MrvlIEtype_KeyParamSet_t))); - ret = - wlan_set_keyparamset_wep(pmpriv, &pkey_material->key_param_set, - &key_param_len); + memset(pmpriv->adapter, &pkey_material->key_param_set, 0, + sizeof(MrvlIEtype_KeyParamSetV2_t)); + if (pkey->key_flags & KEY_FLAG_REMOVE_KEY) { + pkey_material->action = wlan_cpu_to_le16(HostCmd_ACT_GEN_REMOVE); + pkey_material->key_param_set.type = + wlan_cpu_to_le16(TLV_TYPE_KEY_PARAM_V2); + pkey_material->key_param_set.length = + wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN); + pkey_material->key_param_set.key_idx = pkey->key_index & KEY_INDEX_MASK; + pkey_material->key_param_set.key_info = + KEY_INFO_MCAST_KEY | KEY_INFO_UCAST_KEY; + memcpy(pmpriv->adapter, pkey_material->key_param_set.mac_addr, + pkey->mac_addr, MLAN_MAC_ADDR_LENGTH); cmd->size = - wlan_cpu_to_le16(key_param_len + sizeof(pkey_material->action) + - S_DS_GEN); + wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) + S_DS_GEN + + KEY_PARAMS_FIXED_LEN + + sizeof(pkey_material->action)); + PRINTM(MCMND, "Remove Key\n"); goto done; - } else - memset(pmpriv->adapter, &pkey_material->key_param_set, 0, - sizeof(MrvlIEtype_KeyParamSet_t)); - if (pkey->is_wapi_key) { - PRINTM(MINFO, "Set WAPI Key\n"); - pkey_material->key_param_set.key_type_id = - wlan_cpu_to_le16(KEY_TYPE_ID_WAPI); - if (cmd_oid == KEY_INFO_ENABLED) - pkey_material->key_param_set.key_info = - wlan_cpu_to_le16(KEY_INFO_WAPI_ENABLED); - else - pkey_material->key_param_set.key_info = - !(wlan_cpu_to_le16(KEY_INFO_WAPI_ENABLED)); - - pkey_material->key_param_set.key[0] = (t_u8) pkey->key_index; - if (!pmpriv->sec_info.wapi_key_on) - pkey_material->key_param_set.key[1] = 1; - else - pkey_material->key_param_set.key[1] = 0; /* set 0 when re-key */ - - if (0 != memcmp(pmpriv->adapter, pkey->mac_addr, bc_mac, sizeof(bc_mac))) /* WAPI - pairwise - key: - unicast - */ - pkey_material->key_param_set.key_info |= - wlan_cpu_to_le16(KEY_INFO_WAPI_UNICAST); - else { /* WAPI group key: multicast */ + } + pkey_material->action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET); + pkey_material->key_param_set.key_idx = pkey->key_index & KEY_INDEX_MASK; + pkey_material->key_param_set.type = wlan_cpu_to_le16(TLV_TYPE_KEY_PARAM_V2); + pkey_material->key_param_set.key_info = KEY_INFO_ENABLE_KEY; + memcpy(pmpriv->adapter, pkey_material->key_param_set.mac_addr, + pkey->mac_addr, MLAN_MAC_ADDR_LENGTH); + if (pkey->key_len <= MAX_WEP_KEY_SIZE) { + pkey_material->key_param_set.length = + wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN + sizeof(wep_param_t)); + pkey_material->key_param_set.key_type = KEY_TYPE_ID_WEP; + if (pkey->is_current_wep_key) { pkey_material->key_param_set.key_info |= - wlan_cpu_to_le16(KEY_INFO_WAPI_MCAST); - pmpriv->sec_info.wapi_key_on = MTRUE; + KEY_INFO_MCAST_KEY | KEY_INFO_UCAST_KEY; + if (pkey_material->key_param_set.key_idx == + (pmpriv->wep_key_curr_index & KEY_INDEX_MASK)) + pkey_material->key_param_set.key_info |= KEY_INFO_DEFAULT_KEY; + } else { + if (pkey->key_flags & KEY_FLAG_GROUP_KEY) + pkey_material->key_param_set.key_info |= KEY_INFO_MCAST_KEY; + else + pkey_material->key_param_set.key_info |= KEY_INFO_UCAST_KEY; + if (pkey->key_flags & KEY_FLAG_SET_TX_KEY) + pkey_material->key_param_set.key_info |= KEY_INFO_DEFAULT_KEY; } - - pkey_material->key_param_set.type = - wlan_cpu_to_le16(TLV_TYPE_KEY_MATERIAL); - pkey_material->key_param_set.key_len = wlan_cpu_to_le16(WAPI_KEY_LEN); - memcpy(pmpriv->adapter, &pkey_material->key_param_set.key[2], + pkey_material->key_param_set.key_info = + wlan_cpu_to_le16(pkey_material->key_param_set.key_info); + pkey_material->key_param_set.key_params.wep.key_len = + wlan_cpu_to_le16(pkey->key_len); + memcpy(pmpriv->adapter, pkey_material->key_param_set.key_params.wep.key, pkey->key_material, pkey->key_len); + cmd->size = + wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) + S_DS_GEN + + KEY_PARAMS_FIXED_LEN + sizeof(wep_param_t) + + sizeof(pkey_material->action)); + PRINTM(MCMND, "Set WEP Key\n"); + goto done; + } + if (pkey->key_flags & KEY_FLAG_GROUP_KEY) + pkey_material->key_param_set.key_info |= KEY_INFO_MCAST_KEY; + else + pkey_material->key_param_set.key_info |= KEY_INFO_UCAST_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; + else + pkey_material->key_param_set.key_info |= KEY_INFO_RX_KEY; + if (pkey->is_wapi_key) { + pkey_material->key_param_set.key_type = KEY_TYPE_ID_WAPI; + memcpy(pmpriv->adapter, pkey_material->key_param_set.key_params.wapi.pn, + pkey->pn, PN_SIZE); + pkey_material->key_param_set.key_params.wapi.key_len = + wlan_cpu_to_le16(pkey->key_len); memcpy(pmpriv->adapter, - &pkey_material->key_param_set.key[2 + pkey->key_len], pkey->pn, - PN_SIZE); + pkey_material->key_param_set.key_params.wapi.key, + pkey->key_material, pkey->key_len); + if (!pmpriv->sec_info.wapi_key_on) + pkey_material->key_param_set.key_info |= KEY_INFO_DEFAULT_KEY; + if (pkey->key_flags & KEY_FLAG_GROUP_KEY) + pmpriv->sec_info.wapi_key_on = MTRUE; + pkey_material->key_param_set.key_info = + wlan_cpu_to_le16(pkey_material->key_param_set.key_info); pkey_material->key_param_set.length = - wlan_cpu_to_le16(WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN); - - key_param_len = - (WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN) + - sizeof(MrvlIEtypesHeader_t); + wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN + sizeof(wapi_param)); cmd->size = - wlan_cpu_to_le16(key_param_len + sizeof(pkey_material->action) + - S_DS_GEN); + wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) + S_DS_GEN + + KEY_PARAMS_FIXED_LEN + sizeof(wapi_param) + + sizeof(pkey_material->action)); + PRINTM(MCMND, "Set WAPI Key\n"); goto done; } - /* IGTK key length is the same as AES key length */ + if (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) { + /* Enable default key for WPA/WPA2 */ + if (!pmpriv->wpa_is_gtk_set) + pkey_material->key_param_set.key_info |= KEY_INFO_DEFAULT_KEY; + } else { + pkey_material->key_param_set.key_info |= KEY_INFO_DEFAULT_KEY; + /* Enable unicast bit for WPA-NONE/ADHOC_AES */ + if ((!pmpriv->sec_info.wpa2_enabled) && + (pkey->key_flags & KEY_FLAG_SET_TX_KEY)) + pkey_material->key_param_set.key_info |= KEY_INFO_UCAST_KEY; + } + pkey_material->key_param_set.key_info = + wlan_cpu_to_le16(pkey_material->key_param_set.key_info); if (pkey->key_len == WPA_AES_KEY_LEN && !(pkey->key_flags & KEY_FLAG_AES_MCAST_IGTK)) { - PRINTM(MCMND, "WPA_AES\n"); - pkey_material->key_param_set.key_type_id = - wlan_cpu_to_le16(KEY_TYPE_ID_AES); - if (cmd_oid == KEY_INFO_ENABLED) - pkey_material->key_param_set.key_info = - wlan_cpu_to_le16(KEY_INFO_AES_ENABLED); - else - pkey_material->key_param_set.key_info = - !(wlan_cpu_to_le16(KEY_INFO_AES_ENABLED)); - - if (pkey->key_index & MLAN_KEY_INDEX_UNICAST) /* AES pairwise key: - unicast */ - pkey_material->key_param_set.key_info |= - wlan_cpu_to_le16(KEY_INFO_AES_UNICAST); - else { /* AES group key: multicast */ - - pkey_material->key_param_set.key_info |= - wlan_cpu_to_le16(KEY_INFO_AES_MCAST); - } - } else if ((pkey->key_flags & KEY_FLAG_AES_MCAST_IGTK) && - pkey->key_len == WPA_IGTK_KEY_LEN) { - PRINTM(MCMND, "WPA_AES_CMAC\n"); - pkey_material->key_param_set.key_type_id = - wlan_cpu_to_le16(KEY_TYPE_ID_AES_CMAC); - if (cmd_oid == KEY_INFO_ENABLED) - pkey_material->key_param_set.key_info = - wlan_cpu_to_le16(KEY_INFO_AES_ENABLED); - else - pkey_material->key_param_set.key_info = - !(wlan_cpu_to_le16(KEY_INFO_AES_ENABLED)); - + if (pkey->key_flags & (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID)) + memcpy(pmpriv->adapter, + pkey_material->key_param_set.key_params.aes.pn, pkey->pn, + SEQ_MAX_SIZE); + pkey_material->key_param_set.key_type = KEY_TYPE_ID_AES; + pkey_material->key_param_set.key_params.aes.key_len = + wlan_cpu_to_le16(pkey->key_len); + memcpy(pmpriv->adapter, pkey_material->key_param_set.key_params.aes.key, + pkey->key_material, pkey->key_len); + pkey_material->key_param_set.length = + wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN + sizeof(aes_param)); + cmd->size = + wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) + S_DS_GEN + + KEY_PARAMS_FIXED_LEN + sizeof(aes_param) + + sizeof(pkey_material->action)); + PRINTM(MCMND, "Set AES Key\n"); + goto done; + } + if (pkey->key_len == WPA_IGTK_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(pmpriv->adapter, + pkey_material->key_param_set.key_params.cmac_aes.ipn, + pkey->pn, SEQ_MAX_SIZE); + pkey_material->key_param_set.key_info &= ~KEY_INFO_MCAST_KEY; pkey_material->key_param_set.key_info |= wlan_cpu_to_le16(KEY_INFO_AES_MCAST_IGTK); - } else if (pkey->key_len == WPA_TKIP_KEY_LEN) { - PRINTM(MCMND, "WPA_TKIP\n"); - pkey_material->key_param_set.key_type_id = - wlan_cpu_to_le16(KEY_TYPE_ID_TKIP); - pkey_material->key_param_set.key_info = - wlan_cpu_to_le16(KEY_INFO_TKIP_ENABLED); - - if (pkey->key_index & MLAN_KEY_INDEX_UNICAST) /* TKIP pairwise key: - unicast */ - pkey_material->key_param_set.key_info |= - wlan_cpu_to_le16(KEY_INFO_TKIP_UNICAST); - else /* TKIP group key: multicast */ - pkey_material->key_param_set.key_info |= - wlan_cpu_to_le16(KEY_INFO_TKIP_MCAST); + 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(pmpriv->adapter, + pkey_material->key_param_set.key_params.cmac_aes.key, + pkey->key_material, pkey->key_len); + pkey_material->key_param_set.length = + wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN + sizeof(cmac_aes_param)); + cmd->size = + wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) + S_DS_GEN + + KEY_PARAMS_FIXED_LEN + sizeof(cmac_aes_param) + + sizeof(pkey_material->action)); + PRINTM(MCMND, "Set CMAC AES Key\n"); + goto done; } - - if (pkey_material->key_param_set.key_type_id) { - pkey_material->key_param_set.type = - wlan_cpu_to_le16(TLV_TYPE_KEY_MATERIAL); - pkey_material->key_param_set.key_len = - wlan_cpu_to_le16((t_u16) pkey->key_len); - memcpy(pmpriv->adapter, pkey_material->key_param_set.key, + if (pkey->key_len == WPA_TKIP_KEY_LEN) { + if (pkey->key_flags & (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID)) + memcpy(pmpriv->adapter, + pkey_material->key_param_set.key_params.tkip.pn, pkey->pn, + SEQ_MAX_SIZE); + pkey_material->key_param_set.key_type = KEY_TYPE_ID_TKIP; + pkey_material->key_param_set.key_params.tkip.key_len = + wlan_cpu_to_le16(pkey->key_len); + memcpy(pmpriv->adapter, + pkey_material->key_param_set.key_params.tkip.key, pkey->key_material, pkey->key_len); pkey_material->key_param_set.length = - wlan_cpu_to_le16((t_u16) pkey->key_len + KEYPARAMSET_FIXED_LEN); - key_param_len = - (t_u16) (pkey->key_len + KEYPARAMSET_FIXED_LEN) + - sizeof(MrvlIEtypesHeader_t); - - /* key format with pn field is defined in Key Material V1 */ - if (pkey_material->key_param_set.key_type_id == - wlan_cpu_to_le16(KEY_TYPE_ID_AES_CMAC)) { - cmac_param *param; - param = (cmac_param *) pkey_material->key_param_set.key; - memcpy(pmpriv->adapter, param->ipn, pkey->pn, SEQ_MAX_SIZE); - memcpy(pmpriv->adapter, param->key, pkey->key_material, - pkey->key_len); - - pkey_material->key_param_set.key_len = - wlan_cpu_to_le16((t_u16) sizeof(cmac_param)); - pkey_material->key_param_set.length = - wlan_cpu_to_le16((t_u16) sizeof(cmac_param) + - KEYPARAMSET_FIXED_LEN); - key_param_len = - (t_u16) (sizeof(cmac_param) + KEYPARAMSET_FIXED_LEN) + - sizeof(MrvlIEtypesHeader_t); - } - + wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN + sizeof(tkip_param)); cmd->size = - wlan_cpu_to_le16(key_param_len + sizeof(pkey_material->action) + - S_DS_GEN); + wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) + S_DS_GEN + + KEY_PARAMS_FIXED_LEN + sizeof(tkip_param) + + sizeof(pkey_material->action)); + PRINTM(MCMND, "Set TKIP Key\n"); } done: LEAVE(); @@ -1024,7 +998,8 @@ wlan_cmd_802_11_supplicant_profile(IN pmlan_private pmpriv, IN t_u16 cmd_action, IN t_void * pdata_buf) { HostCmd_DS_802_11_SUPPLICANT_PROFILE *sup_profile = - &cmd->params.esupplicant_profile; + (HostCmd_DS_802_11_SUPPLICANT_PROFILE *) & (cmd->params. + esupplicant_profile); MrvlIEtypes_EncrProto_t *encr_proto_tlv = MNULL; MrvlIEtypes_Cipher_t *pcipher_tlv = MNULL; t_u8 *ptlv_buffer = (t_u8 *) sup_profile->tlv_buf; @@ -1296,8 +1271,7 @@ wlan_cmd_subscribe_event(IN pmlan_private pmpriv, cmd_size = sizeof(HostCmd_DS_SUBSCRIBE_EVENT) + S_DS_GEN; if (cmd_action == HostCmd_ACT_GEN_GET) goto done; -#define HostCmd_ACT_BITWISE_SET 0x02 - evt->action = wlan_cpu_to_le16(HostCmd_ACT_BITWISE_SET); + evt->action = wlan_cpu_to_le16(sub_evt->evt_action); evt->event_bitmap = wlan_cpu_to_le16(sub_evt->evt_bitmap); tlv = (t_u8 *) cmd + cmd_size; if (sub_evt->evt_bitmap & SUBSCRIBE_EVT_RSSI_LOW) { @@ -1660,7 +1634,8 @@ wlan_ops_sta_prepare_cmd(IN t_void * priv, cmd_ptr->params.rx_mgmt_ind.action = wlan_cpu_to_le16(cmd_action); cmd_ptr->params.rx_mgmt_ind.mgmt_subtype_mask = wlan_cpu_to_le32((t_u32) (*((t_u32 *) pdata_buf))); - cmd_ptr->size = wlan_cpu_to_le16(sizeof(t_u32) + S_DS_GEN); + cmd_ptr->size = + wlan_cpu_to_le16(sizeof(HostCmd_DS_RX_MGMT_IND) + S_DS_GEN); break; case HostCmd_CMD_802_11_RF_CHANNEL: ret = diff --git a/drivers/net/wireless/sd8797/mlan/mlan_sta_cmdresp.c b/drivers/net/wireless/sd8797/mlan/mlan_sta_cmdresp.c index 5b9a2508e986..ce9e70efbfe7 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_sta_cmdresp.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_sta_cmdresp.c @@ -32,7 +32,6 @@ Change log: #include "mlan_wmm.h" #include "mlan_11n.h" #include "mlan_11h.h" - #include "mlan_sdio.h" #include "mlan_meas.h" @@ -95,6 +94,9 @@ wlan_process_cmdresp_error(mlan_private * pmpriv, HostCmd_DS_COMMAND * resp, case HostCmd_CMD_MAC_CONTROL: break; + case HostCmd_CMD_802_11_ASSOCIATE: + wlan_reset_connect_state(pmpriv, MTRUE); + break; default: break; } @@ -128,6 +130,8 @@ wlan_ret_802_11_rssi_info(IN pmlan_private pmpriv, HostCmd_DS_802_11_RSSI_INFO_RSP *prssi_info_rsp = &resp->params.rssi_info_rsp; mlan_ds_get_info *pget_info = MNULL; + BSSDescriptor_t *pbss_desc; + t_s32 tbl_idx = 0; ENTER(); @@ -143,6 +147,16 @@ wlan_ret_802_11_rssi_info(IN pmlan_private pmpriv, pmpriv->bcn_rssi_avg = wlan_le16_to_cpu(prssi_info_rsp->bcn_rssi_avg); pmpriv->bcn_nf_avg = wlan_le16_to_cpu(prssi_info_rsp->bcn_nf_avg); + /* Get current BSS info */ + pbss_desc = &pmpriv->curr_bss_params.bss_descriptor; + tbl_idx = + wlan_find_ssid_in_list(pmpriv, &pbss_desc->ssid, pbss_desc->mac_address, + pmpriv->bss_mode); + if (tbl_idx >= 0) { + pbss_desc = &pmpriv->adapter->pscan_table[tbl_idx]; + pbss_desc->rssi = -pmpriv->bcn_rssi_avg; + } + /* Need to indicate IOCTL complete */ if (pioctl_buf != MNULL) { pget_info = (mlan_ds_get_info *) pioctl_buf->pbuf; @@ -182,25 +196,6 @@ wlan_ret_802_11_rssi_info(IN pmlan_private pmpriv, } /** - * @brief This function handles the command response of mac_control - * - * @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 - */ -static mlan_status -wlan_ret_mac_control(IN pmlan_private pmpriv, - IN HostCmd_DS_COMMAND * resp, - IN mlan_ioctl_req * pioctl_buf) -{ - ENTER(); - LEAVE(); - return MLAN_STATUS_SUCCESS; -} - -/** * @brief This function handles the command response of snmp_mib * * @param pmpriv A pointer to mlan_private structure @@ -325,6 +320,7 @@ wlan_ret_get_log(IN pmlan_private pmpriv, mlan_ds_get_info *pget_info = MNULL; ENTER(); + if (pioctl_buf) { pget_info = (mlan_ds_get_info *) pioctl_buf->pbuf; pget_info->param.stats.mcast_tx_frame = @@ -355,6 +351,10 @@ wlan_ret_get_log(IN pmlan_private pmpriv, wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[2]); pget_info->param.stats.wep_icv_error[3] = wlan_le32_to_cpu(pget_log->wep_icv_err_cnt[3]); + pget_info->param.stats.bcn_rcv_cnt = + wlan_le32_to_cpu(pget_log->bcn_rcv_cnt); + pget_info->param.stats.bcn_miss_cnt = + wlan_le32_to_cpu(pget_log->bcn_miss_cnt); /* Indicate ioctl complete */ pioctl_buf->data_read_written = sizeof(mlan_ds_get_info); } @@ -666,9 +666,7 @@ wlan_ret_802_11_mac_address(IN pmlan_private pmpriv, memcpy(pmpriv->adapter, pmpriv->curr_addr, pmac_addr->mac_addr, MLAN_MAC_ADDR_LENGTH); - PRINTM(MINFO, "MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", - pmpriv->curr_addr[0], pmpriv->curr_addr[1], pmpriv->curr_addr[2], - pmpriv->curr_addr[3], pmpriv->curr_addr[4], pmpriv->curr_addr[5]); + PRINTM(MINFO, "MAC address: " MACSTR "\n", MAC2STR(pmpriv->curr_addr)); if (pioctl_buf) { bss = (mlan_ds_bss *) pioctl_buf->pbuf; memcpy(pmpriv->adapter, &bss->param.mac_addr, pmpriv->curr_addr, @@ -791,44 +789,66 @@ wlan_ret_802_11_key_material(IN pmlan_private pmpriv, } else { if (pioctl_buf && (wlan_le16_to_cpu(pkey->key_param_set.type) == - TLV_TYPE_KEY_MATERIAL)) { - PRINTM(MIOCTL, "key_type_id=%d, key_len=%d, key_info=0x%x\n", - wlan_le16_to_cpu(pkey->key_param_set.key_type_id), - wlan_le16_to_cpu(pkey->key_param_set.key_len), - wlan_le16_to_cpu(pkey->key_param_set.key_info)); + TLV_TYPE_KEY_PARAM_V2)) { sec = (mlan_ds_sec_cfg *) pioctl_buf->pbuf; -#define WAPI_KEY_SIZE 32 - switch (wlan_le16_to_cpu(pkey->key_param_set.key_type_id)) { - case KEY_TYPE_ID_WEP: - sec->param.encrypt_key.key_index = pkey->key_param_set.key[0]; + memcpy(pmpriv->adapter, sec->param.encrypt_key.mac_addr, + pkey->key_param_set.mac_addr, MLAN_MAC_ADDR_LENGTH); + sec->param.encrypt_key.key_index = pkey->key_param_set.key_idx; + PRINTM(MIOCTL, + "key_type=%d, key_index=%d, key_info=0x%x " MACSTR "\n", + pkey->key_param_set.key_type, pkey->key_param_set.key_idx, + wlan_le16_to_cpu(pkey->key_param_set.key_info), + MAC2STR(sec->param.encrypt_key.mac_addr)); + switch (pkey->key_param_set.key_type) { + case KEY_TYPE_ID_WAPI: + sec->param.encrypt_key.is_wapi_key = MTRUE; sec->param.encrypt_key.key_len = - wlan_le16_to_cpu(pkey->key_param_set.key_len); + wlan_le16_to_cpu(pkey->key_param_set.key_params.wapi. + key_len); memcpy(pmpriv->adapter, sec->param.encrypt_key.key_material, - &pkey->key_param_set.key[2], + pkey->key_param_set.key_params.wapi.key, sec->param.encrypt_key.key_len); + memcpy(pmpriv->adapter, sec->param.encrypt_key.pn, + pkey->key_param_set.key_params.wapi.pn, PN_SIZE); break; case KEY_TYPE_ID_TKIP: sec->param.encrypt_key.key_len = - wlan_le16_to_cpu(pkey->key_param_set.key_len); + wlan_le16_to_cpu(pkey->key_param_set.key_params.tkip. + key_len); memcpy(pmpriv->adapter, sec->param.encrypt_key.key_material, - pkey->key_param_set.key, sec->param.encrypt_key.key_len); + pkey->key_param_set.key_params.tkip.key, + sec->param.encrypt_key.key_len); + memcpy(pmpriv->adapter, sec->param.encrypt_key.pn, + pkey->key_param_set.key_params.tkip.pn, WPA_PN_SIZE); break; case KEY_TYPE_ID_AES: - case KEY_TYPE_ID_AES_CMAC: sec->param.encrypt_key.key_len = - wlan_le16_to_cpu(pkey->key_param_set.key_len); + wlan_le16_to_cpu(pkey->key_param_set.key_params.aes. + key_len); memcpy(pmpriv->adapter, sec->param.encrypt_key.key_material, - pkey->key_param_set.key, sec->param.encrypt_key.key_len); + pkey->key_param_set.key_params.aes.key, + sec->param.encrypt_key.key_len); + memcpy(pmpriv->adapter, sec->param.encrypt_key.pn, + pkey->key_param_set.key_params.aes.pn, WPA_PN_SIZE); break; - case KEY_TYPE_ID_WAPI: - sec->param.encrypt_key.is_wapi_key = MTRUE; - sec->param.encrypt_key.key_index = pkey->key_param_set.key[0]; - sec->param.encrypt_key.key_len = WAPI_KEY_SIZE; + case KEY_TYPE_ID_AES_CMAC: + sec->param.encrypt_key.key_len = + wlan_le16_to_cpu(pkey->key_param_set.key_params.cmac_aes. + key_len); memcpy(pmpriv->adapter, sec->param.encrypt_key.key_material, - &pkey->key_param_set.key[2], + pkey->key_param_set.key_params.cmac_aes.key, sec->param.encrypt_key.key_len); memcpy(pmpriv->adapter, sec->param.encrypt_key.pn, - &pkey->key_param_set.key[2 + WAPI_KEY_SIZE], PN_SIZE); + pkey->key_param_set.key_params.cmac_aes.ipn, + IGTK_PN_SIZE); + break; + case KEY_TYPE_ID_WEP: + sec->param.encrypt_key.key_len = + wlan_le16_to_cpu(pkey->key_param_set.key_params.wep. + key_len); + memcpy(pmpriv->adapter, sec->param.encrypt_key.key_material, + pkey->key_param_set.key_params.wep.key, + sec->param.encrypt_key.key_len); break; } } @@ -1072,10 +1092,7 @@ wlan_ret_ibss_coalescing_status(IN pmlan_private pmpriv, return MLAN_STATUS_SUCCESS; } - PRINTM(MINFO, "New BSSID %02x:%02x:%02x:%02x:%02x:%02x\n", - pibss_coal_resp->bssid[0], pibss_coal_resp->bssid[1], - pibss_coal_resp->bssid[2], pibss_coal_resp->bssid[3], - pibss_coal_resp->bssid[4], pibss_coal_resp->bssid[5]); + PRINTM(MINFO, "New BSSID " MACSTR "\n", MAC2STR(pibss_coal_resp->bssid)); /* If rsp has MNULL BSSID, Just return..... No Action */ if (!memcmp @@ -1338,6 +1355,7 @@ wlan_ret_otp_user_data(IN pmlan_private pmpriv, /******************************************************** Global Functions ********************************************************/ + /** * @brief This function handles the station command response * @@ -1357,6 +1375,7 @@ wlan_ops_sta_process_cmdresp(IN t_void * priv, mlan_private *pmpriv = (mlan_private *) priv; HostCmd_DS_COMMAND *resp = (HostCmd_DS_COMMAND *) pcmd_buf; mlan_ioctl_req *pioctl_buf = (mlan_ioctl_req *) pioctl; + mlan_adapter *pmadapter = pmpriv->adapter; int ctr; @@ -1404,6 +1423,7 @@ wlan_ops_sta_process_cmdresp(IN t_void * priv, break; case HostCmd_CMD_802_11_BG_SCAN_QUERY: ret = wlan_ret_802_11_bgscan_query(pmpriv, resp, pioctl_buf); + wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_BGSCAN_RESULT, MNULL); PRINTM(MINFO, "CMD_RESP: BG_SCAN result is ready!\n"); break; case HostCmd_CMD_TXPWR_CFG: @@ -1598,6 +1618,7 @@ wlan_ops_sta_process_cmdresp(IN t_void * priv, case HostCmd_CMD_REJECT_ADDBA_REQ: ret = wlan_ret_reject_addba_req(pmpriv, resp, pioctl_buf); break; + default: PRINTM(MERROR, "CMD_RESP: Unknown command response %#x\n", resp->command); diff --git a/drivers/net/wireless/sd8797/mlan/mlan_sta_event.c b/drivers/net/wireless/sd8797/mlan/mlan_sta_event.c index fd408a6efe4b..7fce6e29a6e3 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_sta_event.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_sta_event.c @@ -82,11 +82,6 @@ wlan_reset_connect_state(pmlan_private priv, t_u8 drv_disconnect) ENTER(); - if (priv->media_connected != MTRUE) { - LEAVE(); - return; - } - PRINTM(MINFO, "Handles disconnect event.\n"); if (drv_disconnect) { @@ -227,11 +222,19 @@ wlan_ops_sta_process_event(IN t_void * priv) t_u8 event_buf[100]; t_u8 *evt_buf = MNULL; pmlan_buffer pmbuf = pmadapter->pmlan_buffer_event; + t_u16 reason_code; pmlan_callbacks pcb = &pmadapter->callbacks; mlan_event *pevent = (mlan_event *) event_buf; ENTER(); + /* Event length check */ + if ((pmbuf->data_len - sizeof(eventcause)) > MAX_EVENT_SIZE) { + pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID; + LEAVE(); + return MLAN_STATUS_FAILURE; + } + if (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE && pmbuf->data_len > sizeof(eventcause)) DBG_HEXDUMP(MEVT_D, "EVENT", pmbuf->pbuf + pmbuf->data_offset, @@ -249,20 +252,27 @@ wlan_ops_sta_process_event(IN t_void * priv) break; case EVENT_DEAUTHENTICATED: - PRINTM(MEVENT, "EVENT: Deauthenticated\n"); + reason_code = + *(t_u16 *) (pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause)); + PRINTM(MMSG, "wlan: EVENT: Deauthenticated (reason 0x%x)\n", + reason_code); pmadapter->dbg.num_event_deauth++; wlan_handle_disconnect_event(pmpriv); break; case EVENT_DISASSOCIATED: - PRINTM(MEVENT, "EVENT: Disassociated\n"); + reason_code = + *(t_u16 *) (pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause)); + PRINTM(MMSG, "wlan: EVENT: Disassociated (reason 0x%x)\n", reason_code); pmadapter->dbg.num_event_disassoc++; wlan_handle_disconnect_event(pmpriv); break; case EVENT_LINK_LOST: - PRINTM(MEVENT, "EVENT: Link lost\n"); + reason_code = + *(t_u16 *) (pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause)); + PRINTM(MMSG, "wlan: EVENT: Link lost (reason 0x%x)\n", reason_code); pmadapter->dbg.num_event_link_lost++; wlan_handle_disconnect_event(pmpriv); break; @@ -339,11 +349,34 @@ wlan_ops_sta_process_event(IN t_void * priv) wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_ADHOC_LINK_LOST, MNULL); break; + case EVENT_FW_DEBUG_INFO: + /* Allocate memory for event buffer */ + ret = pcb->moal_malloc(pmadapter->pmoal_handle, + MAX_EVENT_SIZE, MLAN_MEM_DEF, &evt_buf); + if ((ret == MLAN_STATUS_SUCCESS) && evt_buf) { + pevent = (pmlan_event) evt_buf; + pevent->bss_index = pmpriv->bss_index; + PRINTM(MEVENT, "EVENT: FW Debug Info\n"); + pevent->event_id = MLAN_EVENT_ID_FW_DEBUG_INFO; + pevent->event_len = pmbuf->data_len - sizeof(eventcause); + memcpy(pmadapter, + (t_u8 *) pevent->event_buf, + pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause), + pevent->event_len); + wlan_recv_event(pmpriv, pevent->event_id, pevent); + pcb->moal_mfree(pmadapter->pmoal_handle, evt_buf); + } + break; + case EVENT_BG_SCAN_REPORT: PRINTM(MEVENT, "EVENT: BGS_REPORT\n"); pmadapter->bgscan_reported = MTRUE; wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BG_SCAN, MNULL); break; + case EVENT_BG_SCAN_STOPPED: + PRINTM(MEVENT, "EVENT: BGS_STOPPED\n"); + wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BG_SCAN_STOPPED, MNULL); + break; case EVENT_PORT_RELEASE: PRINTM(MEVENT, "EVENT: PORT RELEASE\n"); @@ -429,7 +462,8 @@ wlan_ops_sta_process_event(IN t_void * priv) break; case EVENT_EXT_SCAN_REPORT: PRINTM(MEVENT, "EVENT: EXT_SCAN Report (%#x)\n", eventcause); - ret = wlan_handle_event_ext_scan_report(priv, pmbuf); + if (pmadapter->pext_scan_ioctl_req) + ret = wlan_handle_event_ext_scan_report(priv, pmbuf); break; case EVENT_MEAS_REPORT_RDY: PRINTM(MEVENT, "EVENT: Measurement Report Ready (%#x)\n", eventcause); @@ -619,6 +653,7 @@ wlan_ops_sta_process_event(IN t_void * priv) pEvtDat[3]); } break; + default: PRINTM(MEVENT, "EVENT: unknown event id: %#x\n", eventcause); wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_UNKNOWN, MNULL); diff --git a/drivers/net/wireless/sd8797/mlan/mlan_sta_ioctl.c b/drivers/net/wireless/sd8797/mlan/mlan_sta_ioctl.c index 2c1743025218..47c8e25c99f9 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_sta_ioctl.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_sta_ioctl.c @@ -54,27 +54,15 @@ Change log: static void wlan_enable_aes_key(pmlan_private pmpriv) { - mlan_ds_encrypt_key encrypt_key; ENTER(); - if (pmpriv->aes_key.key_param_set.key_len != WPA_AES_KEY_LEN) { + if (pmpriv->aes_key.key_len != WPA_AES_KEY_LEN) { LEAVE(); return; } - - memset(pmpriv->adapter, &encrypt_key, 0, sizeof(mlan_ds_encrypt_key)); - encrypt_key.key_len = WPA_AES_KEY_LEN; - encrypt_key.key_index = MLAN_KEY_INDEX_UNICAST; - memcpy(pmpriv->adapter, encrypt_key.key_material, - pmpriv->aes_key.key_param_set.key, encrypt_key.key_len); - wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL, - HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, MNULL, - &encrypt_key); - encrypt_key.key_index &= ~MLAN_KEY_INDEX_UNICAST; wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL, - HostCmd_ACT_GEN_SET, - KEY_INFO_ENABLED, MNULL, &encrypt_key); + HostCmd_ACT_GEN_SET, 0, MNULL, &pmpriv->aes_key); LEAVE(); return; @@ -330,6 +318,7 @@ wlan_get_info_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) memcpy(pmadapter, &pget_info->param.fw_info.mac_addr, pmpriv->curr_addr, MLAN_MAC_ADDR_LENGTH); pget_info->param.fw_info.fw_bands = pmadapter->fw_bands; + pget_info->param.fw_info.region_code = pmadapter->region_code; pget_info->param.fw_info.hw_dev_mcs_support = pmadapter->hw_dev_mcs_support; break; @@ -832,7 +821,7 @@ static mlan_status wlan_bss_ioctl_channel(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) { - mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; + mlan_private *pmpriv = MNULL; mlan_ds_bss *bss = MNULL; mlan_status ret = MLAN_STATUS_SUCCESS; chan_freq_power_t *cfp = MNULL; @@ -843,6 +832,7 @@ wlan_bss_ioctl_channel(IN pmlan_adapter pmadapter, LEAVE(); return MLAN_STATUS_FAILURE; } + pmpriv = pmadapter->priv[pioctl_req->bss_index]; bss = (mlan_ds_bss *) pioctl_req->pbuf; if (pioctl_req->action == MLAN_ACT_GET) { cfp = wlan_find_cfp_by_band_and_channel(pmadapter, @@ -1057,14 +1047,9 @@ wlan_bss_ioctl_start(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) goto start_ssid_done; } else { /* i >= 0 */ PRINTM(MERROR, - "SSID not found in scan list: ssid=%s, %02x:%02x:%02x:%02x:%02x:%02x, idx=%d\n", + "SSID not found in scan list: ssid=%s, " MACSTR ", idx=%d\n", bss->param.ssid_bssid.ssid.ssid, - bss->param.ssid_bssid.bssid[0], - bss->param.ssid_bssid.bssid[1], - bss->param.ssid_bssid.bssid[2], - bss->param.ssid_bssid.bssid[3], - bss->param.ssid_bssid.bssid[4], - bss->param.ssid_bssid.bssid[5], + MAC2STR(bss->param.ssid_bssid.bssid), (int) bss->param.ssid_bssid.idx); pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER; ret = MLAN_STATUS_FAILURE; @@ -1234,7 +1219,7 @@ wlan_bss_ioctl_listen_interval(IN pmlan_adapter pmadapter, return MLAN_STATUS_SUCCESS; } -/** +/* * @brief Set/Get beacon interval * * @param pmadapter A pointer to mlan_adapter structure @@ -1448,6 +1433,9 @@ wlan_bss_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) case MLAN_OID_BSS_LISTEN_INTERVAL: status = wlan_bss_ioctl_listen_interval(pmadapter, pioctl_req); break; + case MLAN_OID_BSS_REMOVE: + status = wlan_bss_ioctl_bss_remove(pmadapter, pioctl_req); + break; default: status = MLAN_STATUS_FAILURE; break; @@ -2276,317 +2264,6 @@ wlan_pm_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) } /** - * @brief Set/Get WMM status - * - * @param pmadapter A pointer to mlan_adapter structure - * @param pioctl_req A pointer to ioctl request buffer - * - * @return MLAN_STATUS_SUCCESS --success - */ -static mlan_status -wlan_wmm_ioctl_enable(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_wmm_cfg *wmm = MNULL; - ENTER(); - wmm = (mlan_ds_wmm_cfg *) pioctl_req->pbuf; - if (pioctl_req->action == MLAN_ACT_GET) - wmm->param.wmm_enable = (t_u32) pmpriv->wmm_required; - else - pmpriv->wmm_required = (t_u8) wmm->param.wmm_enable; - pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE; - LEAVE(); - return ret; -} - -/** - * @brief Set/Get WMM QoS configuration - * - * @param pmadapter A pointer to mlan_adapter structure - * @param pioctl_req A pointer to ioctl request buffer - * - * @return MLAN_STATUS_SUCCESS --success - */ -static mlan_status -wlan_wmm_ioctl_qos(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_wmm_cfg *wmm = MNULL; - - ENTER(); - - wmm = (mlan_ds_wmm_cfg *) pioctl_req->pbuf; - - if (pioctl_req->action == MLAN_ACT_GET) - wmm->param.qos_cfg = pmpriv->wmm_qosinfo; - else { - pmpriv->wmm_qosinfo = wmm->param.qos_cfg; - } - - pioctl_req->data_read_written = sizeof(t_u8) + MLAN_SUB_COMMAND_SIZE; - - LEAVE(); - return ret; -} - -/** - * @brief Request for add a TSPEC - * - * @param pmadapter A pointer to mlan_adapter structure - * @param pioctl_req A pointer to ioctl request buffer - * - * @return MLAN_STATUS_PENDING --success, otherwise fail - */ -static mlan_status -wlan_wmm_ioctl_addts_req(IN pmlan_adapter pmadapter, - IN pmlan_ioctl_req pioctl_req) -{ - mlan_status ret = MLAN_STATUS_SUCCESS; - pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; - mlan_ds_wmm_cfg *cfg = MNULL; - - ENTER(); - cfg = (mlan_ds_wmm_cfg *) pioctl_req->pbuf; - - /* Send request to firmware */ - ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_ADDTS_REQ, - 0, 0, (t_void *) pioctl_req, - (t_void *) & cfg->param.addts); - - if (ret == MLAN_STATUS_SUCCESS) - ret = MLAN_STATUS_PENDING; - - LEAVE(); - return ret; -} - -/** - * @brief Request for delete a TSPEC - * - * @param pmadapter A pointer to mlan_adapter structure - * @param pioctl_req A pointer to ioctl request buffer - * - * @return MLAN_STATUS_PENDING --success, otherwise fail - */ -static mlan_status -wlan_wmm_ioctl_delts_req(IN pmlan_adapter pmadapter, - IN pmlan_ioctl_req pioctl_req) -{ - mlan_status ret = MLAN_STATUS_SUCCESS; - pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; - mlan_ds_wmm_cfg *cfg = MNULL; - - ENTER(); - cfg = (mlan_ds_wmm_cfg *) pioctl_req->pbuf; - - /* Send request to firmware */ - ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_DELTS_REQ, - 0, 0, (t_void *) pioctl_req, - (t_void *) & cfg->param.delts); - - if (ret == MLAN_STATUS_SUCCESS) - ret = MLAN_STATUS_PENDING; - - LEAVE(); - return ret; -} - -/** - * @brief Set/Get a specified AC Queue's parameters - * - * @param pmadapter A pointer to mlan_adapter structure - * @param pioctl_req A pointer to ioctl request buffer - * - * @return MLAN_STATUS_PENDING --success, otherwise fail - */ -static mlan_status -wlan_wmm_ioctl_queue_config(IN pmlan_adapter pmadapter, - IN pmlan_ioctl_req pioctl_req) -{ - mlan_status ret = MLAN_STATUS_SUCCESS; - pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; - mlan_ds_wmm_cfg *cfg = MNULL; - - ENTER(); - cfg = (mlan_ds_wmm_cfg *) pioctl_req->pbuf; - - /* Send request to firmware */ - ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_QUEUE_CONFIG, - 0, 0, (t_void *) pioctl_req, - (t_void *) & cfg->param.q_cfg); - - if (ret == MLAN_STATUS_SUCCESS) - ret = MLAN_STATUS_PENDING; - - LEAVE(); - return ret; -} - -/** - * @brief To get and start/stop queue stats on a WMM AC - * - * @param pmadapter A pointer to mlan_adapter structure - * @param pioctl_req A pointer to ioctl request buffer - * - * @return MLAN_STATUS_PENDING --success, otherwise fail - */ -static mlan_status -wlan_wmm_ioctl_queue_stats(IN pmlan_adapter pmadapter, - IN pmlan_ioctl_req pioctl_req) -{ - mlan_status ret = MLAN_STATUS_SUCCESS; - pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; - mlan_ds_wmm_cfg *cfg = MNULL; - - ENTER(); - cfg = (mlan_ds_wmm_cfg *) pioctl_req->pbuf; - - /* Send request to firmware */ - ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_QUEUE_STATS, - 0, 0, (t_void *) pioctl_req, - (t_void *) & cfg->param.q_stats); - - if (ret == MLAN_STATUS_SUCCESS) - ret = MLAN_STATUS_PENDING; - - LEAVE(); - return ret; -} - -/** - * @brief Get the status of the WMM AC queues - * - * @param pmadapter A pointer to mlan_adapter structure - * @param pioctl_req A pointer to ioctl request buffer - * - * @return MLAN_STATUS_SUCCESS --success - */ -static mlan_status -wlan_wmm_ioctl_queue_status(IN pmlan_adapter pmadapter, - IN pmlan_ioctl_req pioctl_req) -{ - mlan_status ret = MLAN_STATUS_SUCCESS; - pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; - mlan_ds_wmm_cfg *cfg = MNULL; - mlan_ds_wmm_queue_status *pqstatus = MNULL; - WmmAcStatus_t *pac_status = MNULL; - mlan_wmm_ac_e ac_idx; - - ENTER(); - - cfg = (mlan_ds_wmm_cfg *) pioctl_req->pbuf; - pqstatus = (mlan_ds_wmm_queue_status *) & cfg->param.q_status; - - for (ac_idx = WMM_AC_BK; ac_idx <= WMM_AC_VO; ac_idx++) { - pac_status = &pmpriv->wmm.ac_status[ac_idx]; - - /* Firmware status */ - pqstatus->ac_status[ac_idx].flow_required = pac_status->flow_required; - pqstatus->ac_status[ac_idx].flow_created = pac_status->flow_created; - pqstatus->ac_status[ac_idx].disabled = pac_status->disabled; - - /* ACM bit reflected in firmware status (redundant) */ - pqstatus->ac_status[ac_idx].wmm_acm = pac_status->flow_required; - } - - LEAVE(); - return ret; -} - -/** - * @brief Get the status of the WMM Traffic Streams - * - * @param pmadapter A pointer to mlan_adapter structure - * @param pioctl_req A pointer to ioctl request buffer - * - * @return MLAN_STATUS_PENDING --success, otherwise fail - */ -static mlan_status -wlan_wmm_ioctl_ts_status(IN pmlan_adapter pmadapter, - IN pmlan_ioctl_req pioctl_req) -{ - mlan_status ret = MLAN_STATUS_SUCCESS; - pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; - mlan_ds_wmm_cfg *cfg = MNULL; - - ENTER(); - - cfg = (mlan_ds_wmm_cfg *) pioctl_req->pbuf; - - /* Send request to firmware */ - ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_TS_STATUS, - 0, 0, (t_void *) pioctl_req, - (t_void *) & cfg->param.ts_status); - - if (ret == MLAN_STATUS_SUCCESS) - ret = MLAN_STATUS_PENDING; - - LEAVE(); - return ret; -} - -/** - * @brief WMM configuration handler - * - * @param pmadapter A pointer to mlan_adapter structure - * @param pioctl_req A pointer to ioctl request buffer - * - * @return MLAN_STATUS_SUCCESS --success, otherwise fail - */ -static mlan_status -wlan_wmm_cfg_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) -{ - mlan_status status = MLAN_STATUS_SUCCESS; - mlan_ds_wmm_cfg *wmm = MNULL; - - ENTER(); - - if (pioctl_req->buf_len < sizeof(mlan_ds_wmm_cfg)) { - PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n"); - pioctl_req->data_read_written = 0; - pioctl_req->buf_len_needed = sizeof(mlan_ds_wmm_cfg); - pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER; - LEAVE(); - return MLAN_STATUS_RESOURCE; - } - wmm = (mlan_ds_wmm_cfg *) pioctl_req->pbuf; - switch (wmm->sub_command) { - case MLAN_OID_WMM_CFG_ENABLE: - status = wlan_wmm_ioctl_enable(pmadapter, pioctl_req); - break; - case MLAN_OID_WMM_CFG_QOS: - status = wlan_wmm_ioctl_qos(pmadapter, pioctl_req); - break; - case MLAN_OID_WMM_CFG_ADDTS: - status = wlan_wmm_ioctl_addts_req(pmadapter, pioctl_req); - break; - case MLAN_OID_WMM_CFG_DELTS: - status = wlan_wmm_ioctl_delts_req(pmadapter, pioctl_req); - break; - case MLAN_OID_WMM_CFG_QUEUE_CONFIG: - status = wlan_wmm_ioctl_queue_config(pmadapter, pioctl_req); - break; - case MLAN_OID_WMM_CFG_QUEUE_STATS: - status = wlan_wmm_ioctl_queue_stats(pmadapter, pioctl_req); - break; - case MLAN_OID_WMM_CFG_QUEUE_STATUS: - status = wlan_wmm_ioctl_queue_status(pmadapter, pioctl_req); - break; - case MLAN_OID_WMM_CFG_TS_STATUS: - status = wlan_wmm_ioctl_ts_status(pmadapter, pioctl_req); - break; - default: - pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID; - status = MLAN_STATUS_FAILURE; - break; - } - LEAVE(); - return status; -} - -/** * @brief Set/Get WPA IE * * @param priv A pointer to mlan_private structure @@ -2763,7 +2440,7 @@ wlan_sec_ioctl_port_ctrl_enable(IN pmlan_adapter pmadapter, if (pmpriv->port_ctrl_mode == MTRUE) { pmpriv->port_ctrl_mode = MFALSE; /* Cleanup the bypass TX queue */ - wlan_cleanup_bypass_txq(pmadapter); + wlan_cleanup_bypass_txq(pmpriv); } } } @@ -2831,6 +2508,30 @@ wlan_sec_ioctl_encrypt_mode(IN pmlan_adapter pmadapter, } /** + * @brief Get Random charactor + * + * @param pmadapter A pointer to mlan_adapter structure + * + * @return random charactor + */ +t_u8 +wlan_get_random_charactor(pmlan_adapter pmadapter) +{ + t_u32 sec, usec; + t_u8 ch = 0; + + ENTER(); + + pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec, + &usec); + sec = (sec & 0xFFFF) + (sec >> 16); + usec = (usec & 0xFFFF) + (usec >> 16); + ch = (((sec << 16) + usec) % 26) + 'a'; + LEAVE(); + return ch; +} + +/** * @brief Set/Get WPA status * * @param pmadapter A pointer to mlan_adapter structure @@ -2858,7 +2559,7 @@ wlan_sec_ioctl_wpa_enable(IN pmlan_adapter pmadapter, } /** clear adhoc aes flag, when WPA enabled */ pmpriv->adhoc_aes_enabled = MFALSE; - pmpriv->aes_key.key_param_set.key_len = 0; + pmpriv->aes_key.key_len = 0; } pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE; LEAVE(); @@ -2882,6 +2583,7 @@ wlan_sec_ioctl_set_wep_key(IN pmlan_adapter pmadapter, mlan_ds_sec_cfg *sec = MNULL; mrvl_wep_key_t *pwep_key = MNULL; int index; + int i = 0; ENTER(); @@ -2891,8 +2593,18 @@ wlan_sec_ioctl_set_wep_key(IN pmlan_adapter pmadapter, sec = (mlan_ds_sec_cfg *) pioctl_req->pbuf; if (sec->param.encrypt_key.key_index == MLAN_KEY_INDEX_DEFAULT) { index = pmpriv->wep_key_curr_index; + sec->param.encrypt_key.key_index = index; } else { if (sec->param.encrypt_key.key_index >= MRVL_NUM_WEP_KEY) { + if ((sec->param.encrypt_key.key_remove == MTRUE) && + (sec->param.encrypt_key.key_index <= 5)) { + /* call firmware remove key */ + ret = wlan_prepare_cmd(pmpriv, + HostCmd_CMD_802_11_KEY_MATERIAL, + HostCmd_ACT_GEN_SET, + 0, MNULL, &sec->param.encrypt_key); + goto exit; + } PRINTM(MERROR, "Key_index is invalid\n"); ret = MLAN_STATUS_FAILURE; goto exit; @@ -2907,14 +2619,28 @@ wlan_sec_ioctl_set_wep_key(IN pmlan_adapter pmadapter, if (sec->param.encrypt_key.key_remove == MTRUE) { memset(pmadapter, &pmpriv->wep_key[index], 0, sizeof(mrvl_wep_key_t)); + /* call firmware remove key */ + ret = wlan_prepare_cmd(pmpriv, + HostCmd_CMD_802_11_KEY_MATERIAL, + HostCmd_ACT_GEN_SET, + 0, MNULL, &sec->param.encrypt_key); + if (ret) + goto exit; } } else { if (sec->param.encrypt_key.key_len) { if ((sec->param.encrypt_key.key_len != WEP_104_BIT_LEN) && (sec->param.encrypt_key.key_len != WEP_40_BIT_LEN)) { - PRINTM(MERROR, "Invalid wep key len\n"); - ret = MLAN_STATUS_FAILURE; - goto exit; + PRINTM(MERROR, "Invalid wep key len=%d\n", + sec->param.encrypt_key.key_len); + /* We will use random key to clear the key buffer in FW */ + if (sec->param.encrypt_key.key_len < WEP_40_BIT_LEN) + sec->param.encrypt_key.key_len = WEP_40_BIT_LEN; + else + sec->param.encrypt_key.key_len = WEP_104_BIT_LEN; + for (i = 0; i < sec->param.encrypt_key.key_len; i++) + sec->param.encrypt_key.key_material[i] = + wlan_get_random_charactor(pmadapter); } pwep_key = &pmpriv->wep_key[index]; /* Cleanup */ @@ -2939,6 +2665,13 @@ wlan_sec_ioctl_set_wep_key(IN pmlan_adapter pmadapter, /* Copy the required key as the current key */ pwep_key = &pmpriv->wep_key[index]; if (!pwep_key->key_length) { + if (0 + || &pmpriv->sec_info.wpa_enabled + || &pmpriv->sec_info.wpa2_enabled + || &pmpriv->sec_info.wapi_enabled) { + ret = MLAN_STATUS_SUCCESS; + goto exit; + } PRINTM(MERROR, "Key %d not set,so cannot enable it\n", index); pioctl_req->status_code = MLAN_ERROR_CMD_RESP_FAIL; ret = MLAN_STATUS_FAILURE; @@ -2947,6 +2680,10 @@ wlan_sec_ioctl_set_wep_key(IN pmlan_adapter pmadapter, pmpriv->wep_key_curr_index = (t_u16) index; pmpriv->sec_info.wep_status = Wlan802_11WEPEnabled; } + if (sec->param.encrypt_key.key_flags && pwep_key->key_length) { + pmpriv->wep_key_curr_index = (t_u16) index; + pmpriv->sec_info.wep_status = Wlan802_11WEPEnabled; + } } if (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled) pmpriv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE; @@ -2962,15 +2699,29 @@ wlan_sec_ioctl_set_wep_key(IN pmlan_adapter pmadapter, 0, MNULL, &pmpriv->curr_pkt_filter); if (ret) goto exit; + if (!sec->param.encrypt_key.key_len) { + sec->param.encrypt_key.key_index = pwep_key->key_index; + sec->param.encrypt_key.key_len = pwep_key->key_length; + memcpy(pmadapter, sec->param.encrypt_key.key_material, + pwep_key->key_material, sec->param.encrypt_key.key_len); + } ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL, HostCmd_ACT_GEN_SET, - 0, (t_void *) pioctl_req, MNULL); + 0, + (t_void *) pioctl_req, &sec->param.encrypt_key); } else { if (pwep_key->key_length) { + if (!sec->param.encrypt_key.key_len) { + sec->param.encrypt_key.key_index = pwep_key->key_index; + sec->param.encrypt_key.key_len = pwep_key->key_length; + memcpy(pmadapter, sec->param.encrypt_key.key_material, + pwep_key->key_material, sec->param.encrypt_key.key_len); + } ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_KEY_MATERIAL, - HostCmd_ACT_GEN_SET, 0, MNULL, MNULL); + HostCmd_ACT_GEN_SET, + 0, MNULL, &sec->param.encrypt_key); if (ret) goto exit; } @@ -3003,8 +2754,6 @@ wlan_sec_ioctl_set_wpa_key(IN pmlan_adapter pmadapter, mlan_status ret = MLAN_STATUS_SUCCESS; mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; mlan_ds_sec_cfg *sec = MNULL; - t_u8 broadcast_mac_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - t_u8 remove_key = MFALSE; ENTER(); @@ -3016,34 +2765,12 @@ wlan_sec_ioctl_set_wpa_key(IN pmlan_adapter pmadapter, ret = MLAN_STATUS_FAILURE; goto exit; } - if ((pmpriv->bss_mode == MLAN_BSS_MODE_IBSS) && - pmpriv->sec_info.wpa_enabled) { - /* - * IBSS/WPA-None uses only one key (Group) for both receiving and - * sending unicast and multicast packets. - */ - /* Send the key as PTK to firmware */ - sec->param.encrypt_key.key_index = MLAN_KEY_INDEX_UNICAST; - ret = wlan_prepare_cmd(pmpriv, - HostCmd_CMD_802_11_KEY_MATERIAL, - HostCmd_ACT_GEN_SET, - KEY_INFO_ENABLED, - MNULL, &sec->param.encrypt_key); - if (ret) - goto exit; - - /* Send the key as GTK to firmware */ - sec->param.encrypt_key.key_index = ~MLAN_KEY_INDEX_UNICAST; - } if (sec->param.encrypt_key.key_len == WPA_AES_KEY_LEN) { /** back up adhoc AES key */ - memset(pmpriv->adapter, pmpriv->aes_key.key_param_set.key, 0, - sizeof(pmpriv->aes_key.key_param_set.key)); - pmpriv->aes_key.key_param_set.key_len = sec->param.encrypt_key.key_len; - memcpy(pmpriv->adapter, pmpriv->aes_key.key_param_set.key, - sec->param.encrypt_key.key_material, - pmpriv->aes_key.key_param_set.key_len); + memset(pmpriv->adapter, &pmpriv->aes_key, 0, sizeof(pmpriv->aes_key)); + memcpy(pmpriv->adapter, (t_u8 *) & pmpriv->aes_key, + (t_u8 *) & sec->param.encrypt_key, sizeof(pmpriv->aes_key)); } /** only adhoc aes key_index = MLAN_KEY_INDEX_UNICAST */ @@ -3057,36 +2784,18 @@ wlan_sec_ioctl_set_wpa_key(IN pmlan_adapter pmadapter, WPA_AES_KEY_LEN)) { PRINTM(MINFO, "Adhoc AES Enabled.\n"); pmpriv->adhoc_aes_enabled = MTRUE; - remove_key = MFALSE; } else { PRINTM(MINFO, "Adhoc AES Disabled.\n"); pmpriv->adhoc_aes_enabled = MFALSE; /** clear adhoc AES key */ - remove_key = MTRUE; - pmpriv->aes_key.key_param_set.key_len = 0; + pmpriv->aes_key.key_len = 0; } } - if (memcmp - (pmadapter, sec->param.encrypt_key.mac_addr, broadcast_mac_addr, - MLAN_MAC_ADDR_LENGTH)) - sec->param.encrypt_key.key_index = MLAN_KEY_INDEX_UNICAST; - - if (remove_key == MTRUE) { - /* Send request to firmware */ - ret = wlan_prepare_cmd(pmpriv, - HostCmd_CMD_802_11_KEY_MATERIAL, - HostCmd_ACT_GEN_SET, - !(KEY_INFO_ENABLED), - (t_void *) pioctl_req, &sec->param.encrypt_key); - } else { - /* Send request to firmware */ - ret = wlan_prepare_cmd(pmpriv, - HostCmd_CMD_802_11_KEY_MATERIAL, - HostCmd_ACT_GEN_SET, - KEY_INFO_ENABLED, - (t_void *) pioctl_req, &sec->param.encrypt_key); - } + ret = wlan_prepare_cmd(pmpriv, + HostCmd_CMD_802_11_KEY_MATERIAL, + HostCmd_ACT_GEN_SET, + 0, (t_void *) pioctl_req, &sec->param.encrypt_key); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; @@ -3119,11 +2828,11 @@ wlan_sec_ioctl_get_key(IN pmlan_adapter pmadapter, if ((sec->param.encrypt_key.key_index == MLAN_KEY_INDEX_UNICAST) && (sec->param.encrypt_key.key_len == WPA_AES_KEY_LEN)) { if (pmpriv->adhoc_aes_enabled == MTRUE && - (pmpriv->aes_key.key_param_set.key_len == WPA_AES_KEY_LEN)) { - HEXDUMP("Get ADHOCAES Key", pmpriv->aes_key.key_param_set.key, + (pmpriv->aes_key.key_len == WPA_AES_KEY_LEN)) { + HEXDUMP("Get ADHOCAES Key", pmpriv->aes_key.key_material, WPA_AES_KEY_LEN); memcpy(pmadapter, sec->param.encrypt_key.key_material, - pmpriv->aes_key.key_param_set.key, WPA_AES_KEY_LEN); + pmpriv->aes_key.key_material, WPA_AES_KEY_LEN); LEAVE(); return ret; } else { @@ -3166,13 +2875,12 @@ wlan_sec_ioctl_get_key(IN pmlan_adapter pmadapter, ) { /* Return WPA enabled */ sec->param.encrypt_key.key_disable = MFALSE; + memcpy(pmadapter, sec->param.encrypt_key.key_material, - pmpriv->aes_key.key_param_set.key, MIN(MLAN_MAX_KEY_LENGTH, - pmpriv->aes_key. - key_param_set. - key_len)); + pmpriv->aes_key.key_material, MIN(MLAN_MAX_KEY_LENGTH, + pmpriv->aes_key.key_len)); sec->param.encrypt_key.key_len = - MIN(MLAN_MAX_KEY_LENGTH, pmpriv->aes_key.key_param_set.key_len); + MIN(MLAN_MAX_KEY_LENGTH, pmpriv->aes_key.key_len); } else { sec->param.encrypt_key.key_disable = MTRUE; } @@ -3497,6 +3205,7 @@ wlan_set_gen_ie_helper(mlan_private * priv, t_u8 * ie_data_ptr, t_u16 ie_len) priv->gen_ie_buf_len = 0; priv->wps.session_enable = MFALSE; wlan_set_wpa_ie_helper(priv, MNULL, 0); + wlan_set_wapi_ie(priv, MNULL, 0); } else if (!ie_data_ptr) { /* MNULL check */ ret = MLAN_STATUS_FAILURE; @@ -3785,6 +3494,8 @@ wlan_wps_cfg_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) if (pioctl_req->action == MLAN_ACT_SET) { if (pwps->param.wps_session == MLAN_WPS_CFG_SESSION_START) pmpriv->wps.session_enable = MTRUE; + else + pmpriv->wps.session_enable = MFALSE; } else { pwps->param.wps_session = (t_u32) pmpriv->wps.session_enable; pioctl_req->data_read_written = sizeof(t_u32); @@ -4285,70 +3996,63 @@ wlan_misc_ioctl_sysclock(IN pmlan_adapter pmadapter, } /** - * @brief Send function softreset command to firmware + * @brief Get the associate response * * @param pmadapter A pointer to mlan_adapter structure * @param pioctl_req A pointer to ioctl request buffer * - * @return MLAN_STATUS_PENDING --success, otherwise fail + * @return MLAN_STATUS_SUCCESS --success */ static mlan_status -wlan_misc_ioctl_soft_reset(IN pmlan_adapter pmadapter, - IN pmlan_ioctl_req pioctl_req) +wlan_misc_ioctl_get_assoc_rsp(IN pmlan_adapter pmadapter, + IN pmlan_ioctl_req pioctl_req) { + mlan_ds_misc_cfg *misc = MNULL; mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; mlan_status ret = MLAN_STATUS_SUCCESS; ENTER(); - /* Send command to firmware */ - ret = wlan_prepare_cmd(pmpriv, - HostCmd_CMD_SOFT_RESET, - HostCmd_ACT_GEN_SET, - 0, (t_void *) pioctl_req, MNULL); - if (ret == MLAN_STATUS_SUCCESS) - ret = MLAN_STATUS_PENDING; + misc = (mlan_ds_misc_cfg *) pioctl_req->pbuf; + if ((pioctl_req->action == MLAN_ACT_GET) && pmpriv->assoc_rsp_size) { + memcpy(pmadapter, misc->param.assoc_resp.assoc_resp_buf, + pmpriv->assoc_rsp_buf, MIN(ASSOC_RSP_BUF_SIZE, + pmpriv->assoc_rsp_size)); + misc->param.assoc_resp.assoc_resp_len = + MIN(ASSOC_RSP_BUF_SIZE, pmpriv->assoc_rsp_size); + + /* Reset assoc buffer */ + pmpriv->assoc_rsp_size = 0; + } + LEAVE(); return ret; } /** - * @brief Set/Get the MAC control configuration. + * @brief Send function softreset command to firmware * - * @param pmadapter A pointer to mlan_adapter structure - * @param pioctl_req A pointer to ioctl request buffer + * @param pmadapter A pointer to mlan_adapter structure + * @param pioctl_req A pointer to ioctl request buffer * - * @return MLAN_STATUS_PENDING -- success, otherwise fail + * @return MLAN_STATUS_PENDING --success, otherwise fail */ -mlan_status -wlan_misc_ioctl_mac_control(IN pmlan_adapter pmadapter, - IN pmlan_ioctl_req pioctl_req) +static mlan_status +wlan_misc_ioctl_soft_reset(IN pmlan_adapter pmadapter, + IN pmlan_ioctl_req pioctl_req) { mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; - mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *) pioctl_req->pbuf; mlan_status ret = MLAN_STATUS_SUCCESS; - t_u16 cmd_action = 0; ENTER(); + /* Send command to firmware */ + ret = wlan_prepare_cmd(pmpriv, + HostCmd_CMD_SOFT_RESET, + HostCmd_ACT_GEN_SET, + 0, (t_void *) pioctl_req, MNULL); - misc = (mlan_ds_misc_cfg *) pioctl_req->pbuf; - - if (pioctl_req->action == MLAN_ACT_GET) { - misc->param.mac_ctrl = pmpriv->curr_pkt_filter; - } else { - pmpriv->curr_pkt_filter = misc->param.mac_ctrl; - cmd_action = HostCmd_ACT_GEN_SET; - - /* Send command to firmware */ - ret = wlan_prepare_cmd(pmpriv, - HostCmd_CMD_MAC_CONTROL, - cmd_action, 0, - (t_void *) pioctl_req, &misc->param.mac_ctrl); - - if (ret == MLAN_STATUS_SUCCESS) - ret = MLAN_STATUS_PENDING; - } - + if (ret == MLAN_STATUS_SUCCESS) + ret = MLAN_STATUS_PENDING; LEAVE(); return ret; } @@ -4517,7 +4221,10 @@ wlan_ipaddr_arp_filter(IN pmlan_adapter pmadapter, return ret; } -#define FLTR_BUF_IP_OFFSET 39 +#define FLTR_BUF_IP_OFFSET 24 +#define FLTR_BUF_IP_OFFSET_2_IP_1 9 +#define FLTR_BUF_IP_OFFSET_2_IP_2 26 + /** * @brief Enable/Disable Auto ARP resonse * @@ -4529,7 +4236,8 @@ wlan_ipaddr_arp_filter(IN pmlan_adapter pmadapter, */ mlan_status wlan_ipaddr_auto_arp_resp(IN pmlan_adapter pmadapter, - IN pmlan_ioctl_req pioctl_req, IN t_u32 ipv4_addr) + IN pmlan_ioctl_req pioctl_req, + IN t_u32 * ipv4_addr, IN t_u8 num_ipv4) { mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; mlan_status ret = MLAN_STATUS_SUCCESS; @@ -4539,13 +4247,20 @@ wlan_ipaddr_auto_arp_resp(IN pmlan_adapter pmadapter, mlan_ds_misc_cmd *hostcmd; t_u32 buf_len = 0; t_u8 *buf, *filter; - t_u8 fltr_buf[] = { 0x01, 0x10, 0x30, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x01, 0xff, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x41, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, - 0x06, 0x02, 0x02, 0x14, 0x00, 0x00, 0x00, 0x01, - 0x41, 0x44, 0x01, 0x00, 0x00, 0x00, 0x01, 0xc0, - 0xa8, 0x00, 0x68, 0x04, 0x02, 0x2e, 0x00, 0x00, - 0x00, 0x01, 0x41, 0x44 + + t_u8 fltr_buf[] = { 0x01, 0x10, 0x21, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x08, 0x06, 0x02, 0x02, 0x14, 0x00, 0x00, + 0x00, 0x01, 0x41, 0x01, 0x00, 0x00, 0x00, 0x01, + 0xc0, 0xa8, 0x01, 0x6d, 0x04, 0x02, 0x2e, 0x00, + 0x00, 0x00, 0x01, 0x41, 0x44 + }; + t_u8 fltr_buf_2_ip[] = { 0x01, 0x10, 0x33, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0xc0, 0xa8, 0x01, 0x6d, 0x04, 0x02, 0x2e, + 0x00, 0x00, 0x00, 0x01, 0x41, 0x01, 0x00, 0x00, + 0x00, 0x01, 0xc0, 0xa8, 0x02, 0x6d, 0x04, 0x02, + 0x2e, 0x00, 0x00, 0x00, 0x01, 0x41, 0x45, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x08, 0x06, 0x02, 0x02, + 0x14, 0x00, 0x00, 0x00, 0x01, 0x41, 0x44 }; ENTER(); @@ -4582,10 +4297,20 @@ wlan_ipaddr_auto_arp_resp(IN pmlan_adapter pmadapter, mefcmd->nentries = wlan_cpu_to_le16(1); buf_len += sizeof(HostCmd_DS_MEF_CFG); filter = buf + buf_len; - memcpy(pmpriv->adapter, filter, fltr_buf, sizeof(fltr_buf)); - memcpy(pmpriv->adapter, &filter[FLTR_BUF_IP_OFFSET], &ipv4_addr, - sizeof(ipv4_addr)); - buf_len += sizeof(fltr_buf); + if (num_ipv4 == 1) { + memcpy(pmpriv->adapter, filter, fltr_buf, sizeof(fltr_buf)); + memcpy(pmpriv->adapter, &filter[FLTR_BUF_IP_OFFSET], &ipv4_addr[0], + sizeof(t_u32)); + buf_len += sizeof(fltr_buf); + } else if (num_ipv4 >= 2) { + memcpy(pmpriv->adapter, filter, fltr_buf_2_ip, + sizeof(fltr_buf_2_ip)); + memcpy(pmpriv->adapter, &filter[FLTR_BUF_IP_OFFSET_2_IP_1], + &ipv4_addr[0], sizeof(t_u32)); + memcpy(pmpriv->adapter, &filter[FLTR_BUF_IP_OFFSET_2_IP_2], + &ipv4_addr[1], sizeof(t_u32)); + buf_len += sizeof(fltr_buf_2_ip); + } } hostcmd_hdr->size = wlan_cpu_to_le16(buf_len); hostcmd->len = buf_len; @@ -4727,7 +4452,8 @@ wlan_misc_ioctl_ipaddr_cfg(IN pmlan_adapter pmadapter, mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *) pioctl_req->pbuf; mlan_status ret = MLAN_STATUS_SUCCESS; - t_u32 ipv4_addr; + t_u32 ipv4_addr[MAX_IPADDR]; + int i = 0; ENTER(); @@ -4739,26 +4465,30 @@ wlan_misc_ioctl_ipaddr_cfg(IN pmlan_adapter pmadapter, goto done; } /* only one IP is supported in current firmware */ - memcpy(pmadapter, &ipv4_addr, misc->param.ipaddr_cfg.ip_addr[0], - sizeof(t_u32)); + for (i = 0; i < misc->param.ipaddr_cfg.ip_addr_num; i++) { + memcpy(pmadapter, &ipv4_addr[i], misc->param.ipaddr_cfg.ip_addr[i], + sizeof(t_u32)); + } if (misc->param.ipaddr_cfg.op_code != MLAN_IPADDR_OP_IP_REMOVE && - !ipv4_addr) { + !misc->param.ipaddr_cfg.ip_addr_num) { PRINTM(MERROR, "Invalid IPv4 address\n"); pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER; 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); + 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; if (misc->param.ipaddr_cfg.op_code & MLAN_IPADDR_OP_AUTO_ARP_RESP) - ret = wlan_ipaddr_auto_arp_resp(pmadapter, pioctl_req, ipv4_addr); + ret = wlan_ipaddr_auto_arp_resp(pmadapter, pioctl_req, + ipv4_addr, + misc->param.ipaddr_cfg.ip_addr_num); else if (pmpriv->op_code & MLAN_IPADDR_OP_AUTO_ARP_RESP) - ret = wlan_ipaddr_auto_arp_resp(pmadapter, pioctl_req, 0); + ret = wlan_ipaddr_auto_arp_resp(pmadapter, pioctl_req, MNULL, 0); if (ret == MLAN_STATUS_FAILURE) goto done; @@ -4808,19 +4538,6 @@ wlan_misc_ioctl_cfp_code_cfg(IN pmlan_adapter pmadapter, break; } } - if (!region_bg) { - for (i = 0; i < MRVDRV_MAX_CFP_CODE_BG; i++) { - /* Use the CFP code to search for the index */ - if (cfp_code->cfp_code_bg == cfp_code_index_bg[i]) - break; - } - if (i >= MRVDRV_MAX_CFP_CODE_BG) { - PRINTM(MERROR, "CFP Code not identified for BG\n"); - pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER; - ret = MLAN_STATUS_FAILURE; - goto done; - } - } if (!cfp_code->cfp_code_a) cfp_code->cfp_code_a = pmadapter->cfp_code_a; for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) { @@ -4926,6 +4643,38 @@ wlan_misc_ioctl_country_code(IN pmlan_adapter pmadapter, return ret; } +/** + * @brief Configure MFPC and MFPR for management frame protection + * + * @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_pmfcfg(IN pmlan_adapter pmadapter, IN mlan_ioctl_req * pioctl_req) +{ + pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; + mlan_status ret = MLAN_STATUS_SUCCESS; + mlan_ds_misc_cfg *cfg_misc = MNULL; + mlan_ds_misc_pmfcfg *pmfcfg; + + cfg_misc = (mlan_ds_misc_cfg *) pioctl_req->pbuf; + pmfcfg = &cfg_misc->param.pmfcfg; + + if (pioctl_req->action == MLAN_ACT_SET) { + pmpriv->pmfcfg.mfpc = pmfcfg->mfpc; + pmpriv->pmfcfg.mfpr = pmfcfg->mfpr; + } else { + /* GET operation */ + pmfcfg->mfpc = pmpriv->pmfcfg.mfpc; + pmfcfg->mfpr = pmpriv->pmfcfg.mfpr; + } + + LEAVE(); + return ret; +} + /** * @brief Miscellaneous configuration handler * @@ -4942,6 +4691,11 @@ wlan_misc_cfg_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) ENTER(); + if ((pioctl_req == MNULL) || (pioctl_req->pbuf == MNULL)) { + PRINTM(MERROR, "Request buffer not found!\n"); + LEAVE(); + return MLAN_STATUS_FAILURE; + } if (pioctl_req->buf_len < sizeof(mlan_ds_misc_cfg)) { PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n"); pioctl_req->data_read_written = 0; @@ -4950,11 +4704,6 @@ wlan_misc_cfg_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) LEAVE(); return MLAN_STATUS_RESOURCE; } - if ((pioctl_req == MNULL) || (pioctl_req->pbuf == MNULL)) { - PRINTM(MERROR, "Request buffer not found!\n"); - LEAVE(); - return MLAN_STATUS_FAILURE; - } misc = (mlan_ds_misc_cfg *) pioctl_req->pbuf; switch (misc->sub_command) { case MLAN_OID_MISC_GEN_IE: @@ -4980,6 +4729,9 @@ wlan_misc_cfg_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) case MLAN_OID_MISC_WWS: status = wlan_misc_ioctl_wws_cfg(pmadapter, pioctl_req); break; + case MLAN_OID_MISC_ASSOC_RSP: + status = wlan_misc_ioctl_get_assoc_rsp(pmadapter, pioctl_req); + break; case MLAN_OID_MISC_INIT_SHUTDOWN: status = wlan_misc_ioctl_init_shutdown(pmadapter, pioctl_req); break; @@ -5024,6 +4776,14 @@ wlan_misc_cfg_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) case MLAN_OID_MISC_TXCONTROL: status = wlan_misc_ioctl_txcontrol(pmadapter, pioctl_req); break; +#ifdef STA_SUPPORT + case MLAN_OID_MISC_EXT_CAP_CFG: + status = wlan_misc_ext_capa_cfg(pmadapter, pioctl_req); + break; +#endif + case MLAN_OID_MISC_PMFCFG: + status = wlan_misc_pmfcfg(pmadapter, pioctl_req); + break; default: if (pioctl_req) pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID; @@ -5142,7 +4902,7 @@ wlan_scan_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) status = wlan_set_get_scan_cfg(pmadapter, pioctl_req, MLAN_ACT_SET); break; case MLAN_OID_SCAN_CANCEL: - wlan_flush_scan_queue(pmadapter); + wlan_cancel_pending_scan_cmd(pmadapter); break; case MLAN_OID_SCAN_TABLE_FLUSH: status = wlan_flush_scan_table(pmadapter); @@ -5279,8 +5039,7 @@ wlan_find_bss(mlan_private * pmpriv, pmlan_ioctl_req pioctl_req) pmpriv->bss_mode); if (i < 0) { memcpy(pmadapter, mac, &bss->param.ssid_bssid.bssid, sizeof(mac)); - PRINTM(MERROR, "Can not find bssid %02x:%02x:%02x:%02x:%02x:%02x\n", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + PRINTM(MIOCTL, "Can not find bssid " MACSTR "\n", MAC2STR(mac)); pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER; LEAVE(); return MLAN_STATUS_FAILURE; @@ -5288,13 +5047,14 @@ wlan_find_bss(mlan_private * pmpriv, pmlan_ioctl_req pioctl_req) pbss_desc = &pmadapter->pscan_table[i]; memcpy(pmadapter, &bss->param.ssid_bssid.ssid, &pbss_desc->ssid, sizeof(mlan_802_11_ssid)); + bss->param.ssid_bssid.rssi = pbss_desc->rssi; /* index in bss list,start from 1 */ bss->param.ssid_bssid.idx = i + 1; } else if (bss->param.ssid_bssid.ssid.ssid_len) { i = wlan_find_ssid_in_list(pmpriv, &bss->param.ssid_bssid.ssid, MNULL, pmpriv->bss_mode); if (i < 0) { - PRINTM(MERROR, "Can not find ssid %s\n", + PRINTM(MIOCTL, "Can not find ssid %s\n", bss->param.ssid_bssid.ssid.ssid); pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER; LEAVE(); @@ -5303,6 +5063,7 @@ wlan_find_bss(mlan_private * pmpriv, pmlan_ioctl_req pioctl_req) pbss_desc = &pmadapter->pscan_table[i]; memcpy(pmadapter, (t_u8 *) & bss->param.ssid_bssid.bssid, (t_u8 *) & pbss_desc->mac_address, MLAN_MAC_ADDR_LENGTH); + bss->param.ssid_bssid.rssi = pbss_desc->rssi; /* index in bss list, start from 1 */ bss->param.ssid_bssid.idx = i + 1; } else { diff --git a/drivers/net/wireless/sd8797/mlan/mlan_sta_rx.c b/drivers/net/wireless/sd8797/mlan/mlan_sta_rx.c index a357103926f7..b0ff21d88c5a 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_sta_rx.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_sta_rx.c @@ -100,7 +100,7 @@ wlan_process_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf) if (dbgType == DBG_TYPE_SMALL) { PRINTM(MFW_D, "\n"); DBG_HEXDUMP(MFW_D, "FWDBG", - (t_s8 *) ((t_u8 *) & prx_pkt->eth803_hdr + + (char *) ((t_u8 *) & prx_pkt->eth803_hdr + SIZE_OF_DBG_STRUCT), prx_pd->rx_pkt_length); PRINTM(MFW_D, "FWDBG::\n"); } @@ -167,8 +167,8 @@ wlan_process_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf) MIN(prx_pd->rx_pkt_length, MAX_DATA_DUMP_LEN)); priv->rxpd_rate = prx_pd->rx_rate; - priv->rxpd_htinfo = prx_pd->ht_info; + pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &pmbuf->out_ts_sec, &pmbuf->out_ts_usec); diff --git a/drivers/net/wireless/sd8797/mlan/mlan_sta_tx.c b/drivers/net/wireless/sd8797/mlan/mlan_sta_tx.c index dafd1ac57a98..6191e4edeefc 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_sta_tx.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_sta_tx.c @@ -212,9 +212,12 @@ wlan_send_null_packet(pmlan_private priv, t_u8 flags) switch (ret) { case MLAN_STATUS_RESOURCE: - pmadapter->data_sent = MTRUE; - /* Fall through FAILURE handling */ + wlan_free_mlan_buffer(pmadapter, pmbuf); + PRINTM(MERROR, "STA Tx Error: Failed to send NULL packet!\n"); + pmadapter->dbg.num_tx_host_to_card_failure++; + goto done; case MLAN_STATUS_FAILURE: + pmadapter->data_sent = MFALSE; wlan_free_mlan_buffer(pmadapter, pmbuf); PRINTM(MERROR, "STA Tx Error: Failed to send NULL packet!\n"); pmadapter->dbg.num_tx_host_to_card_failure++; @@ -225,6 +228,8 @@ wlan_send_null_packet(pmlan_private priv, t_u8 flags) pmadapter->tx_lock_flag = MTRUE; break; case MLAN_STATUS_PENDING: + pmadapter->data_sent = MFALSE; + pmadapter->tx_lock_flag = MTRUE; break; default: break; diff --git a/drivers/net/wireless/sd8797/mlan/mlan_txrx.c b/drivers/net/wireless/sd8797/mlan/mlan_txrx.c index 9ae74bbad834..57c8ef23d43e 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_txrx.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_txrx.c @@ -61,10 +61,10 @@ mlan_status wlan_handle_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf) { mlan_status ret = MLAN_STATUS_SUCCESS; - pmlan_private priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY); + pmlan_private priv = MNULL; RxPD *prx_pd; #ifdef DEBUG_LEVEL1 - t_u32 sec, usec; + t_u32 sec = 0, usec = 0; #endif ENTER(); @@ -103,14 +103,13 @@ wlan_process_tx(pmlan_private priv, pmlan_buffer pmbuf, pmlan_adapter pmadapter = priv->adapter; t_u8 *head_ptr = MNULL; #ifdef DEBUG_LEVEL1 - t_u32 sec, usec; + t_u32 sec = 0, usec = 0; #endif #ifdef STA_SUPPORT TxPD *plocal_tx_pd = MNULL; #endif ENTER(); - head_ptr = (t_u8 *) priv->ops.process_txpd(priv, pmbuf); if (!head_ptr) { pmbuf->status_code = MLAN_ERROR_PKT_INVALID; @@ -142,6 +141,7 @@ wlan_process_tx(pmlan_private priv, pmlan_buffer pmbuf, wlan_write_data_complete(pmadapter, pmbuf, ret); break; case MLAN_STATUS_PENDING: + pmadapter->data_sent = MFALSE; DBG_HEXDUMP(MDAT_D, "Tx", head_ptr + INTF_HEADER_LEN, MIN(pmbuf->data_len + sizeof(TxPD), MAX_DATA_DUMP_LEN)); @@ -193,9 +193,6 @@ wlan_write_data_complete(IN pmlan_adapter pmadapter, pcb->moal_send_packet_complete(pmadapter->pmoal_handle, pmbuf, status); } else { - if (pmbuf->flags & MLAN_BUF_FLAG_BRIDGE_BUF) { - pmadapter->pending_bridge_pkts--; - } /* pmbuf was allocated by MLAN */ wlan_free_mlan_buffer(pmadapter, pmbuf); } @@ -265,16 +262,19 @@ wlan_recv_packet_complete(IN pmlan_adapter pmadapter, t_void wlan_add_buf_bypass_txqueue(mlan_adapter * pmadapter, pmlan_buffer pmbuf) { + pmlan_private priv = pmadapter->priv[pmbuf->bss_index]; ENTER(); if (pmbuf->buf_type != MLAN_BUF_TYPE_RAW_DATA) { pmbuf->buf_type = MLAN_BUF_TYPE_DATA; } - - util_enqueue_list_tail(pmadapter->pmoal_handle, &pmadapter->bypass_txq, - (pmlan_linked_list) pmbuf, - pmadapter->callbacks.moal_spin_lock, - pmadapter->callbacks.moal_spin_unlock); + pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, + priv->wmm.ra_list_spinlock); + pmadapter->bypass_pkt_count++; + util_enqueue_list_tail(pmadapter->pmoal_handle, &priv->bypass_txq, + (pmlan_linked_list) pmbuf, MNULL, MNULL); + pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, + priv->wmm.ra_list_spinlock); LEAVE(); } @@ -288,46 +288,34 @@ wlan_add_buf_bypass_txqueue(mlan_adapter * pmadapter, pmlan_buffer pmbuf) INLINE t_u8 wlan_bypass_tx_list_empty(mlan_adapter * pmadapter) { - t_u8 q_empty = MTRUE; - pmlan_callbacks pcb = &pmadapter->callbacks; - ENTER(); - - q_empty = (util_peek_list(pmadapter->pmoal_handle, &pmadapter->bypass_txq, - pcb->moal_spin_lock, - pcb->moal_spin_unlock)) ? MFALSE : MTRUE; - - LEAVE(); - return q_empty; + return ((pmadapter->bypass_pkt_count) ? MFALSE : MTRUE); } /** * @brief Clean up the By-pass TX queue * - * @param pmadapter Pointer to the mlan_adapter driver data struct + * @param priv Pointer to the mlan_private data struct * * @return N/A */ t_void -wlan_cleanup_bypass_txq(mlan_adapter * pmadapter) +wlan_cleanup_bypass_txq(mlan_private * priv) { pmlan_buffer pmbuf; + mlan_adapter *pmadapter = priv->adapter; ENTER(); - pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, - pmadapter->bypass_txq.plock); - + priv->wmm.ra_list_spinlock); while ((pmbuf = (pmlan_buffer) util_peek_list(pmadapter->pmoal_handle, - &pmadapter->bypass_txq, MNULL, - MNULL))) { - util_unlink_list(pmadapter->pmoal_handle, &pmadapter->bypass_txq, + &priv->bypass_txq, MNULL, MNULL))) { + util_unlink_list(pmadapter->pmoal_handle, &priv->bypass_txq, (pmlan_linked_list) pmbuf, MNULL, MNULL); wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE); + pmadapter->bypass_pkt_count--; } - pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, - pmadapter->bypass_txq.plock); - + priv->wmm.ra_list_spinlock); LEAVE(); } @@ -344,33 +332,48 @@ wlan_process_bypass_tx(pmlan_adapter pmadapter) pmlan_buffer pmbuf; mlan_tx_param tx_param; mlan_status status = MLAN_STATUS_SUCCESS; - + pmlan_private priv; + int j = 0; ENTER(); - - if ((pmbuf = (pmlan_buffer) util_dequeue_list(pmadapter->pmoal_handle, - &pmadapter->bypass_txq, + for (j = 0; j < pmadapter->priv_num; ++j) { + if ((priv = pmadapter->priv[j])) { + if ((pmbuf = + (pmlan_buffer) util_dequeue_list(pmadapter->pmoal_handle, + &priv->bypass_txq, pmadapter->callbacks. moal_spin_lock, pmadapter->callbacks. moal_spin_unlock))) { - PRINTM(MINFO, "Dequeuing bypassed packet %p\n", pmbuf); - /* XXX: nex_pkt_len ??? */ - tx_param.next_pkt_len = 0; - status = - wlan_process_tx(pmadapter->priv[pmbuf->bss_index], pmbuf, - &tx_param); - - if (status == MLAN_STATUS_RESOURCE) { - /* Queue the packet again so that it will be TX'ed later */ - util_enqueue_list_head(pmadapter->pmoal_handle, - &pmadapter->bypass_txq, - (pmlan_linked_list) pmbuf, - pmadapter->callbacks.moal_spin_lock, - pmadapter->callbacks.moal_spin_unlock); + PRINTM(MINFO, "Dequeuing bypassed packet %p\n", pmbuf); + /* XXX: nex_pkt_len ??? */ + tx_param.next_pkt_len = 0; + status = + wlan_process_tx(pmadapter->priv[pmbuf->bss_index], pmbuf, + &tx_param); + + if (status == MLAN_STATUS_RESOURCE) { + /* Queue the packet again so that it will be TX'ed later */ + util_enqueue_list_head(pmadapter->pmoal_handle, + &priv->bypass_txq, + (pmlan_linked_list) pmbuf, + pmadapter->callbacks.moal_spin_lock, + pmadapter->callbacks. + moal_spin_unlock); + } else { + pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, + priv->wmm. + ra_list_spinlock); + pmadapter->bypass_pkt_count--; + pmadapter->callbacks.moal_spin_unlock(pmadapter-> + pmoal_handle, + priv->wmm. + ra_list_spinlock); + } + break; + } else { + PRINTM(MINFO, "Nothing to send\n"); + } } - } else { - PRINTM(MINFO, "Nothing to send\n"); } - LEAVE(); } diff --git a/drivers/net/wireless/sd8797/mlan/mlan_uap_cmdevent.c b/drivers/net/wireless/sd8797/mlan/mlan_uap_cmdevent.c index 4801d2e809f5..08f26f039773 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_uap_cmdevent.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_uap_cmdevent.c @@ -72,6 +72,48 @@ uap_process_cmdresp_error(mlan_private * pmpriv, HostCmd_DS_COMMAND * resp, return; } +/** + * @brief This function will return the pointer to station entry in station list + * table which matches the give mac address + * + * @param priv A pointer to mlan_private + * + * @return A pointer to structure sta_node + */ +void +wlan_notify_station_deauth(mlan_private * priv) +{ + sta_node *sta_ptr; + t_u8 event_buf[100]; + mlan_event *pevent = (mlan_event *) event_buf; + t_u8 *pbuf; + + ENTER(); + if (!(sta_ptr = (sta_node *) util_peek_list(priv->adapter->pmoal_handle, + &priv->sta_list, + priv->adapter->callbacks. + moal_spin_lock, + priv->adapter->callbacks. + moal_spin_unlock))) { + LEAVE(); + return; + } + while (sta_ptr != (sta_node *) & priv->sta_list) { + memset(priv->adapter, event_buf, 0, sizeof(event_buf)); + pevent->bss_index = priv->bss_index; + pevent->event_id = MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT; + pevent->event_len = MLAN_MAC_ADDR_LENGTH + 2; + pbuf = (t_u8 *) pevent->event_buf; + /* reason field set to 0, Unspecified */ + memcpy(priv->adapter, pbuf + 2, sta_ptr->mac_addr, + MLAN_MAC_ADDR_LENGTH); + wlan_recv_event(priv, pevent->event_id, pevent); + sta_ptr = sta_ptr->pnext; + } + LEAVE(); + return; +} + /** * @brief This function prepares command of hs_cfg. * @@ -87,7 +129,10 @@ wlan_uap_cmd_802_11_hs_cfg(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND * cmd, IN t_u16 cmd_action, IN hs_config_param * pdata_buf) { - HostCmd_DS_802_11_HS_CFG_ENH *phs_cfg = &cmd->params.opt_hs_cfg; + HostCmd_DS_802_11_HS_CFG_ENH *phs_cfg = + (HostCmd_DS_802_11_HS_CFG_ENH *) & (cmd->params.opt_hs_cfg); + t_u8 *tlv = (t_u8 *) phs_cfg + sizeof(HostCmd_DS_802_11_HS_CFG_ENH); + MrvlIEtypes_HsWakeHoldoff_t *holdoff_tlv = MNULL; ENTER(); cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH); @@ -103,9 +148,25 @@ wlan_uap_cmd_802_11_hs_cfg(IN pmlan_private pmpriv, wlan_cpu_to_le32(pdata_buf->conditions); phs_cfg->params.hs_config.gpio = pdata_buf->gpio; phs_cfg->params.hs_config.gap = pdata_buf->gap; - PRINTM(MCMND, "HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n", + if (pmpriv->adapter->min_wake_holdoff) { + cmd->size = + wlan_cpu_to_le16(S_DS_GEN + + sizeof(HostCmd_DS_802_11_HS_CFG_ENH) + + sizeof(MrvlIEtypes_HsWakeHoldoff_t)); + holdoff_tlv = (MrvlIEtypes_HsWakeHoldoff_t *) tlv; + holdoff_tlv->header.type = + wlan_cpu_to_le16(TLV_TYPE_HS_WAKE_HOLDOFF); + holdoff_tlv->header.len = + wlan_cpu_to_le16(sizeof(MrvlIEtypes_HsWakeHoldoff_t) - + sizeof(MrvlIEtypesHeader_t)); + holdoff_tlv->min_wake_holdoff = + wlan_cpu_to_le16(pmpriv->adapter->min_wake_holdoff); + } + PRINTM(MCMND, + "HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x holdoff=%d\n", phs_cfg->params.hs_config.conditions, - phs_cfg->params.hs_config.gpio, phs_cfg->params.hs_config.gap); + phs_cfg->params.hs_config.gpio, phs_cfg->params.hs_config.gap, + pmpriv->adapter->min_wake_holdoff); } LEAVE(); return MLAN_STATUS_SUCCESS; @@ -208,16 +269,13 @@ wlan_process_tx_pause_event(pmlan_private priv, pmlan_buffer pevent) } if (tlv_type == TLV_TYPE_TX_PAUSE) { tx_pause_tlv = (MrvlIEtypes_tx_pause_t *) tlv; - PRINTM(MCMND, - "TxPause: %02x:%02x:%02x:%02x:%02x:%02x pause=%d, pkts=%d\n", - tx_pause_tlv->peermac[0], tx_pause_tlv->peermac[1], - tx_pause_tlv->peermac[2], tx_pause_tlv->peermac[3], - tx_pause_tlv->peermac[4], tx_pause_tlv->peermac[5], + PRINTM(MCMND, "TxPause: " MACSTR " pause=%d, pkts=%d\n", + MAC2STR(tx_pause_tlv->peermac), tx_pause_tlv->tx_pause, tx_pause_tlv->pkt_cnt); if ((sta_ptr = wlan_get_station_entry(priv, tx_pause_tlv->peermac))) { if (sta_ptr->tx_pause != tx_pause_tlv->tx_pause) { sta_ptr->tx_pause = tx_pause_tlv->tx_pause; - wlan_updata_ralist_tx_pause(priv, tx_pause_tlv->peermac, + wlan_update_ralist_tx_pause(priv, tx_pause_tlv->peermac, tx_pause_tlv->tx_pause); } } @@ -879,6 +937,8 @@ wlan_uap_cmd_ap_config(pmlan_private pmpriv, for (ac = 0; ac < 4; ac++) { tlv_wmm_parameter->wmm_para.ac_params[ac].aci_aifsn.aifsn = bss->param.bss_config.wmm_para.ac_params[ac].aci_aifsn.aifsn; + tlv_wmm_parameter->wmm_para.ac_params[ac].aci_aifsn.aci = + bss->param.bss_config.wmm_para.ac_params[ac].aci_aifsn.aci; tlv_wmm_parameter->wmm_para.ac_params[ac].ecw.ecw_max = bss->param.bss_config.wmm_para.ac_params[ac].ecw.ecw_max; tlv_wmm_parameter->wmm_para.ac_params[ac].ecw.ecw_min = @@ -1468,6 +1528,8 @@ wlan_uap_ret_cmd_ap_config(IN pmlan_private pmpriv, for (ac = 0; ac < 4; ac++) { bss->param.bss_config.wmm_para.ac_params[ac].aci_aifsn.aifsn = tlv_wmm_parameter->wmm_para.ac_params[ac].aci_aifsn.aifsn; + bss->param.bss_config.wmm_para.ac_params[ac].aci_aifsn.aci = + tlv_wmm_parameter->wmm_para.ac_params[ac].aci_aifsn.aci; bss->param.bss_config.wmm_para.ac_params[ac].ecw.ecw_max = tlv_wmm_parameter->wmm_para.ac_params[ac].ecw.ecw_max; bss->param.bss_config.wmm_para.ac_params[ac].ecw.ecw_min = @@ -1928,143 +1990,180 @@ wlan_uap_cmd_key_material(IN pmlan_private pmpriv, { HostCmd_DS_802_11_KEY_MATERIAL *pkey_material = &cmd->params.key_material; mlan_ds_encrypt_key *pkey = (mlan_ds_encrypt_key *) pdata_buf; - MrvlIEtypes_MacAddr_t *tlv = MNULL; - const t_u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - t_u16 key_param_len = 0; mlan_status ret = MLAN_STATUS_SUCCESS; sta_node *sta_ptr = MNULL; ENTER(); - + if (!pkey) { + ret = MLAN_STATUS_FAILURE; + goto done; + } cmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL); pkey_material->action = wlan_cpu_to_le16(cmd_action); - if (cmd_action == HostCmd_ACT_GEN_GET) { cmd->size = wlan_cpu_to_le16(sizeof(pkey_material->action) + S_DS_GEN); goto done; } - memset(pmpriv->adapter, &pkey_material->key_param_set, 0, - sizeof(MrvlIEtype_KeyParamSet_t)); - if (pkey->key_len && - memcmp(pmpriv->adapter, pkey->mac_addr, bc_mac, sizeof(bc_mac))) - pmpriv->adapter->scan_block = MFALSE; + sizeof(MrvlIEtype_KeyParamSetV2_t)); + if (pkey->key_flags & KEY_FLAG_REMOVE_KEY) { + pkey_material->action = wlan_cpu_to_le16(HostCmd_ACT_GEN_REMOVE); + pkey_material->key_param_set.type = + wlan_cpu_to_le16(TLV_TYPE_KEY_PARAM_V2); + pkey_material->key_param_set.length = + wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN); + pkey_material->key_param_set.key_idx = pkey->key_index & KEY_INDEX_MASK; + pkey_material->key_param_set.key_info = + KEY_INFO_MCAST_KEY | KEY_INFO_UCAST_KEY; + memcpy(pmpriv->adapter, pkey_material->key_param_set.mac_addr, + pkey->mac_addr, MLAN_MAC_ADDR_LENGTH); + cmd->size = + wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) + S_DS_GEN + + KEY_PARAMS_FIXED_LEN + + sizeof(pkey_material->action)); + PRINTM(MCMND, "Remove Key\n"); + goto done; + } + pkey_material->action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET); + pkey_material->key_param_set.key_idx = pkey->key_index & KEY_INDEX_MASK; + pkey_material->key_param_set.type = wlan_cpu_to_le16(TLV_TYPE_KEY_PARAM_V2); + pkey_material->key_param_set.key_info = KEY_INFO_ENABLE_KEY; + memcpy(pmpriv->adapter, pkey_material->key_param_set.mac_addr, + pkey->mac_addr, MLAN_MAC_ADDR_LENGTH); + if (pkey->key_len <= MAX_WEP_KEY_SIZE) { + pkey_material->key_param_set.length = + wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN + sizeof(wep_param_t)); + pkey_material->key_param_set.key_type = + wlan_cpu_to_le16(KEY_TYPE_ID_WEP); + pkey_material->key_param_set.key_info |= + KEY_INFO_MCAST_KEY | KEY_INFO_UCAST_KEY; + if (pkey_material->key_param_set.key_idx == + (pmpriv->wep_key_curr_index & KEY_INDEX_MASK)) + pkey_material->key_param_set.key_info |= KEY_INFO_DEFAULT_KEY; + pkey_material->key_param_set.key_info = + wlan_cpu_to_le16(pkey_material->key_param_set.key_info); + pkey_material->key_param_set.key_params.wep.key_len = + wlan_cpu_to_le16(pkey->key_len); + memcpy(pmpriv->adapter, pkey_material->key_param_set.key_params.wep.key, + pkey->key_material, pkey->key_len); + cmd->size = + wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) + S_DS_GEN + + KEY_PARAMS_FIXED_LEN + sizeof(wep_param_t) + + sizeof(pkey_material->action)); + PRINTM(MCMND, "Set WEP Key\n"); + goto done; + } + if (pkey->key_flags & KEY_FLAG_GROUP_KEY) { + pkey_material->key_param_set.key_info |= KEY_INFO_MCAST_KEY; + } 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; + if (pkey->key_flags & KEY_FLAG_SET_TX_KEY) + pkey_material->key_param_set.key_info |= + KEY_INFO_TX_KEY | KEY_INFO_RX_KEY; + else + pkey_material->key_param_set.key_info |= KEY_INFO_TX_KEY; if (pkey->is_wapi_key) { - PRINTM(MINFO, "Set WAPI Key\n"); - pkey_material->key_param_set.key_type_id = + pkey_material->key_param_set.key_type = wlan_cpu_to_le16(KEY_TYPE_ID_WAPI); - if (cmd_oid == KEY_INFO_ENABLED) - pkey_material->key_param_set.key_info = - wlan_cpu_to_le16(KEY_INFO_WAPI_ENABLED); - else - pkey_material->key_param_set.key_info = - !(wlan_cpu_to_le16(KEY_INFO_WAPI_ENABLED)); - - pkey_material->key_param_set.key[0] = pkey->key_index; + memcpy(pmpriv->adapter, pkey_material->key_param_set.key_params.wapi.pn, + pkey->pn, PN_SIZE); + pkey_material->key_param_set.key_params.wapi.key_len = + MIN(WAPI_KEY_SIZE, wlan_cpu_to_le16(pkey->key_len)); + memcpy(pmpriv->adapter, + pkey_material->key_param_set.key_params.wapi.key, + pkey->key_material, MIN(WAPI_KEY_SIZE, pkey->key_len)); if (!pmpriv->sec_info.wapi_key_on) - pkey_material->key_param_set.key[1] = 1; - else - pkey_material->key_param_set.key[1] = 0; /* set 0 when re-key */ - - if (0 != memcmp(pmpriv->adapter, pkey->mac_addr, bc_mac, sizeof(bc_mac))) { /* WAPI - pairwise - key: - unicast - */ - pkey_material->key_param_set.key_info |= - wlan_cpu_to_le16(KEY_INFO_WAPI_UNICAST); + pkey_material->key_param_set.key_info |= KEY_INFO_DEFAULT_KEY; + if (pkey->key_flags & KEY_FLAG_GROUP_KEY) { + pmpriv->sec_info.wapi_key_on = MTRUE; + } else { + /* WAPI pairwise key: unicast */ if ((sta_ptr = wlan_add_station_entry(pmpriv, pkey->mac_addr))) { PRINTM(MCMND, "station: wapi_key_on\n"); sta_ptr->wapi_key_on = MTRUE; } - } else { /* WAPI group key: multicast */ - pkey_material->key_param_set.key_info |= - wlan_cpu_to_le16(KEY_INFO_WAPI_MCAST); - pmpriv->sec_info.wapi_key_on = MTRUE; } - pkey_material->key_param_set.type = - wlan_cpu_to_le16(TLV_TYPE_KEY_MATERIAL); - pkey_material->key_param_set.key_len = wlan_cpu_to_le16(WAPI_KEY_LEN); - memcpy(pmpriv->adapter, &pkey_material->key_param_set.key[2], - pkey->key_material, pkey->key_len); + pkey_material->key_param_set.key_info = + wlan_cpu_to_le16(pkey_material->key_param_set.key_info); pkey_material->key_param_set.length = - wlan_cpu_to_le16(WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN); - - key_param_len = - (WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN) + - sizeof(MrvlIEtypesHeader_t); - tlv = - (MrvlIEtypes_MacAddr_t *) ((t_u8 *) & pkey_material->key_param_set + - key_param_len); - tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_STA_MAC_ADDRESS); - tlv->header.len = wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH); - memcpy(pmpriv->adapter, tlv->mac, pkey->mac_addr, MLAN_MAC_ADDR_LENGTH); + wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN + sizeof(wapi_param)); cmd->size = - wlan_cpu_to_le16(key_param_len + sizeof(pkey_material->action) + - S_DS_GEN + sizeof(MrvlIEtypes_MacAddr_t)); + wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) + S_DS_GEN + + KEY_PARAMS_FIXED_LEN + sizeof(wapi_param) + + sizeof(pkey_material->action)); + PRINTM(MCMND, "Set WAPI Key\n"); goto done; } - if (pkey->key_len == WPA_AES_KEY_LEN) { - PRINTM(MCMND, "WPA_AES\n"); - pkey_material->key_param_set.key_type_id = + pkey_material->key_param_set.key_info |= KEY_INFO_DEFAULT_KEY; + pkey_material->key_param_set.key_info = + wlan_cpu_to_le16(pkey_material->key_param_set.key_info); + if (pkey->key_len == WPA_AES_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(pmpriv->adapter, + pkey_material->key_param_set.key_params.aes.pn, pkey->pn, + SEQ_MAX_SIZE); + pkey_material->key_param_set.key_type = wlan_cpu_to_le16(KEY_TYPE_ID_AES); - if (cmd_oid == KEY_INFO_ENABLED) - pkey_material->key_param_set.key_info = - wlan_cpu_to_le16(KEY_INFO_AES_ENABLED); - else - pkey_material->key_param_set.key_info = - !(wlan_cpu_to_le16(KEY_INFO_AES_ENABLED)); - - if (memcmp(pmpriv->adapter, pkey->mac_addr, bc_mac, sizeof(bc_mac))) /* AES - pairwise - key: - unicast - */ - pkey_material->key_param_set.key_info |= - wlan_cpu_to_le16(KEY_INFO_AES_UNICAST); - else /* AES group key: multicast */ - pkey_material->key_param_set.key_info |= - wlan_cpu_to_le16(KEY_INFO_AES_MCAST); - } else if (pkey->key_len == WPA_TKIP_KEY_LEN) { - PRINTM(MCMND, "WPA_TKIP\n"); - pkey_material->key_param_set.key_type_id = - wlan_cpu_to_le16(KEY_TYPE_ID_TKIP); - pkey_material->key_param_set.key_info = - wlan_cpu_to_le16(KEY_INFO_TKIP_ENABLED); - - if (memcmp(pmpriv->adapter, pkey->mac_addr, bc_mac, sizeof(bc_mac))) /* TKIP - pairwise - key: - unicast - */ - pkey_material->key_param_set.key_info |= - wlan_cpu_to_le16(KEY_INFO_TKIP_UNICAST); - else /* TKIP group key: multicast */ - pkey_material->key_param_set.key_info |= - wlan_cpu_to_le16(KEY_INFO_TKIP_MCAST); + pkey_material->key_param_set.key_params.aes.key_len = + wlan_cpu_to_le16(pkey->key_len); + memcpy(pmpriv->adapter, pkey_material->key_param_set.key_params.aes.key, + pkey->key_material, pkey->key_len); + pkey_material->key_param_set.length = + wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN + sizeof(aes_param)); + cmd->size = + wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) + S_DS_GEN + + KEY_PARAMS_FIXED_LEN + sizeof(aes_param) + + sizeof(pkey_material->action)); + PRINTM(MCMND, "Set AES Key\n"); + goto done; } - - if (pkey_material->key_param_set.key_type_id) { - pkey_material->key_param_set.type = - wlan_cpu_to_le16(TLV_TYPE_KEY_MATERIAL); - pkey_material->key_param_set.key_len = wlan_cpu_to_le16(pkey->key_len); - memcpy(pmpriv->adapter, pkey_material->key_param_set.key, + if (pkey->key_len == WPA_IGTK_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(pmpriv->adapter, + pkey_material->key_param_set.key_params.cmac_aes.ipn, + pkey->pn, SEQ_MAX_SIZE); + pkey_material->key_param_set.key_info &= ~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; + pkey_material->key_param_set.key_params.cmac_aes.key_len = + wlan_cpu_to_le16(pkey->key_len); + memcpy(pmpriv->adapter, + pkey_material->key_param_set.key_params.cmac_aes.key, pkey->key_material, pkey->key_len); pkey_material->key_param_set.length = - wlan_cpu_to_le16((t_u16) pkey->key_len + KEYPARAMSET_FIXED_LEN); - key_param_len = - (pkey->key_len + KEYPARAMSET_FIXED_LEN) + - sizeof(MrvlIEtypesHeader_t); - - tlv = - (MrvlIEtypes_MacAddr_t *) ((t_u8 *) & pkey_material->key_param_set + - key_param_len); - tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_STA_MAC_ADDRESS); - tlv->header.len = wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH); - memcpy(pmpriv->adapter, tlv->mac, pkey->mac_addr, MLAN_MAC_ADDR_LENGTH); + wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN + sizeof(cmac_aes_param)); + cmd->size = + wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) + S_DS_GEN + + KEY_PARAMS_FIXED_LEN + sizeof(cmac_aes_param) + + sizeof(pkey_material->action)); + PRINTM(MCMND, "Set CMAC AES Key\n"); + goto done; + } + if (pkey->key_len == WPA_TKIP_KEY_LEN) { + if (pkey->key_flags & (KEY_FLAG_RX_SEQ_VALID | KEY_FLAG_TX_SEQ_VALID)) + memcpy(pmpriv->adapter, + pkey_material->key_param_set.key_params.tkip.pn, pkey->pn, + SEQ_MAX_SIZE); + pkey_material->key_param_set.key_type = + wlan_cpu_to_le16(KEY_TYPE_ID_TKIP); + pkey_material->key_param_set.key_params.tkip.key_len = + wlan_cpu_to_le16(pkey->key_len); + memcpy(pmpriv->adapter, + pkey_material->key_param_set.key_params.tkip.key, + pkey->key_material, pkey->key_len); + pkey_material->key_param_set.length = + wlan_cpu_to_le16(KEY_PARAMS_FIXED_LEN + sizeof(tkip_param)); cmd->size = - wlan_cpu_to_le16(key_param_len + sizeof(pkey_material->action) + - S_DS_GEN + sizeof(MrvlIEtypes_MacAddr_t)); + wlan_cpu_to_le16(sizeof(MrvlIEtypesHeader_t) + S_DS_GEN + + KEY_PARAMS_FIXED_LEN + sizeof(tkip_param) + + sizeof(pkey_material->action)); + PRINTM(MCMND, "Set TKIP Key\n"); } done: LEAVE(); @@ -2115,80 +2214,6 @@ wlan_uap_ret_sta_list(IN pmlan_private pmpriv, } /** - * @brief This function will search for wps/wpa/rsn/wapi IE - * - * - * @param priv A pointer to mlan_private - * @param ie_buf A pointer to ie_buf - * @param ie_len total ie length - * - * @return MTRUE/MFALSE - */ -t_u8 -wlan_check_specific_ie(pmlan_private priv, t_u8 * ie_buf, t_u8 ie_len) -{ - t_u32 bytes_left = ie_len; - t_u8 *pcurrent_ptr = ie_buf; - t_u16 total_ie_len; - IEEEtypes_ElementId_e element_id; - t_u8 element_len; - IEEEtypes_VendorSpecific_t *pvendor_ie; - const t_u8 wps_oui[4] = { 0x00, 0x50, 0xf2, 0x04 }; - const t_u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 }; - t_u8 find_wps_ie = 0; - t_u8 find_sec_ie = 0; - t_u8 ret = MFALSE; - - ENTER(); - - DBG_HEXDUMP(MCMD_D, "ie", ie_buf, ie_len); - while (bytes_left >= 2) { - element_id = (IEEEtypes_ElementId_e) (*((t_u8 *) pcurrent_ptr)); - element_len = *((t_u8 *) pcurrent_ptr + 1); - total_ie_len = element_len + sizeof(IEEEtypes_Header_t); - if (bytes_left < total_ie_len) { - PRINTM(MERROR, "InterpretIE: Error in processing IE, " - "bytes left < IE length\n"); - break; - } - switch (element_id) { - case WAPI_IE: - PRINTM(MCMND, "Find WAPI ie\n"); - find_sec_ie = MTRUE; - break; - case RSN_IE: - PRINTM(MCMND, "Find RSN ie\n"); - find_sec_ie = MTRUE; - break; - case VENDOR_SPECIFIC_221: - pvendor_ie = (IEEEtypes_VendorSpecific_t *) pcurrent_ptr; - if (!memcmp - (priv->adapter, pvendor_ie->vend_hdr.oui, wpa_oui, - sizeof(wpa_oui))) { - PRINTM(MCMND, "Find WPA ie\n"); - find_sec_ie = MTRUE; - } else - if (!memcmp - (priv->adapter, pvendor_ie->vend_hdr.oui, wps_oui, - sizeof(wps_oui))) { - PRINTM(MCMND, "Find WPS ie\n"); - find_wps_ie = MTRUE; - } - break; - default: - break; - } - pcurrent_ptr += element_len + 2; - /* Need to account for IE ID and IE Len */ - bytes_left -= (element_len + 2); - } - if (find_sec_ie || find_wps_ie) - ret = MTRUE; - LEAVE(); - return ret; -} - -/** * @brief This function will search for the specific ie * * @@ -2240,8 +2265,6 @@ wlan_check_sta_capability(pmlan_private priv, pmlan_buffer pevent, assoc_req_ie = (t_u8 *) tlv + sizeof(MrvlIETypes_MgmtFrameSet_t) + assoc_ie_len; - if (wlan_check_specific_ie(priv, assoc_req_ie, ie_len)) - priv->adapter->scan_block = MTRUE; sta_ptr->is_wmm_enabled = wlan_is_wmm_ie_present(priv->adapter, assoc_req_ie, ie_len); PRINTM(MCMND, "STA: is_wmm_enabled=%d\n", @@ -2295,7 +2318,8 @@ wlan_check_uap_capability(pmlan_private priv, pmlan_buffer pevent) (MrvlIEtypesHeader_t *) (pevent->pbuf + pevent->data_offset + BSS_START_EVENT_FIX_SIZE); const t_u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 }; - IEEEtypes_WmmParameter_t *pWmmParamIe = MNULL; + IEEEtypes_WmmParameter_t WmmParamIe; + MrvlIEtypes_channel_band_t *pChanInfo; priv->wmm_enabled = MFALSE; priv->pkt_fwd = MFALSE; priv->is_11n_enabled = MFALSE; @@ -2325,10 +2349,11 @@ wlan_check_uap_capability(pmlan_private priv, pmlan_buffer pevent) priv->wmm_enabled = MFALSE; wlan_wmm_setup_ac_downgrade(priv); priv->wmm_enabled = MTRUE; - pWmmParamIe = (IEEEtypes_WmmParameter_t *) ((t_u8 *) tlv + 2); - pWmmParamIe->vend_hdr.len = (t_u8) tlv_len; - pWmmParamIe->vend_hdr.element_id = WMM_IE; - wlan_wmm_setup_queue_priorities(priv, pWmmParamIe); + memcpy(priv->adapter, &WmmParamIe, ((t_u8 *) tlv + 2), + sizeof(IEEEtypes_WmmParameter_t)); + WmmParamIe.vend_hdr.len = (t_u8) tlv_len; + WmmParamIe.vend_hdr.element_id = WMM_IE; + wlan_wmm_setup_queue_priorities(priv, &WmmParamIe); } } if (tlv_type == TLV_TYPE_UAP_PKT_FWD_CTL) { @@ -2342,6 +2367,14 @@ wlan_check_uap_capability(pmlan_private priv, pmlan_buffer pevent) priv->pkt_fwd |= PKT_FWD_ENABLE_BIT; PRINTM(MCMND, "pkt_fwd DRV: 0x%x\n", priv->pkt_fwd); } + if (tlv_type == TLV_TYPE_UAP_CHAN_BAND_CONFIG) { + DBG_HEXDUMP(MCMD_D, "chan_band_config tlv", tlv, + tlv_len + sizeof(MrvlIEtypesHeader_t)); + pChanInfo = (MrvlIEtypes_channel_band_t *) tlv; + priv->uap_channel = pChanInfo->channel; + PRINTM(MCMND, "uap_channel FW: 0x%x\n", priv->uap_channel); + } + tlv_buf_left -= (sizeof(MrvlIEtypesHeader_t) + tlv_len); tlv = (MrvlIEtypesHeader_t *) ((t_u8 *) tlv + tlv_len + @@ -2555,6 +2588,9 @@ wlan_ops_uap_prepare_cmd(IN t_void * priv, case HostCmd_CMD_CFG_DATA: ret = wlan_cmd_cfg_data(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; + case HostCmd_CMD_MAC_CONTROL: + ret = wlan_cmd_mac_control(pmpriv, cmd_ptr, cmd_action, pdata_buf); + break; case HostCmd_CMD_802_11_SNMP_MIB: ret = wlan_uap_cmd_snmp_mib(pmpriv, cmd_ptr, cmd_action, cmd_oid, (pmlan_ioctl_req) pioctl_buf, pdata_buf); @@ -2633,7 +2669,8 @@ wlan_ops_uap_prepare_cmd(IN t_void * priv, cmd_ptr->params.rx_mgmt_ind.action = wlan_cpu_to_le16(cmd_action); cmd_ptr->params.rx_mgmt_ind.mgmt_subtype_mask = (t_u32) (*((t_u32 *) pdata_buf)); - cmd_ptr->size = wlan_cpu_to_le16(sizeof(t_u32) + S_DS_GEN); + cmd_ptr->size = + wlan_cpu_to_le16(sizeof(HostCmd_DS_RX_MGMT_IND) + S_DS_GEN); break; case HostCmd_CMD_CFG_TX_DATA_PAUSE: ret = wlan_uap_cmd_txdatapause(pmpriv, cmd_ptr, cmd_action, pdata_buf); @@ -2676,7 +2713,14 @@ wlan_ops_uap_prepare_cmd(IN t_void * priv, case HostCmd_CMD_MEM_ACCESS: ret = wlan_cmd_mem_access(cmd_ptr, cmd_action, pdata_buf); break; - + case HostCmd_CMD_WMM_QUEUE_CONFIG: + ret = wlan_cmd_wmm_queue_config(pmpriv, cmd_ptr, pdata_buf); + break; +#if defined(MUTLI_CHAN_SUPPORT) + case HostCmd_CMD_MULTI_CHAN_CONFIG: + ret = wlan_cmd_multi_chan_cfg(pmpriv, cmd_ptr, cmd_action, pdata_buf); + break; +#endif default: PRINTM(MERROR, "PREP_CMD: unknown command- %#x\n", cmd_no); if (pioctl_req) @@ -2733,9 +2777,8 @@ wlan_ops_uap_process_cmdresp(IN t_void * priv, wlan_11h_radar_detected_callback((t_void *) pmpriv); break; case HOST_CMD_APCMD_SYS_RESET: - ret = wlan_uap_ret_sys_reset(pmpriv, resp, pioctl_buf); - pmpriv->uap_bss_started = MFALSE; + ret = wlan_uap_ret_sys_reset(pmpriv, resp, pioctl_buf); wlan_11h_check_update_radar_det_state(pmpriv); break; case HOST_CMD_APCMD_SYS_INFO: @@ -2773,6 +2816,9 @@ wlan_ops_uap_process_cmdresp(IN t_void * priv, case HostCmd_CMD_CFG_DATA: ret = wlan_ret_cfg_data(pmpriv, resp, pioctl_buf); break; + case HostCmd_CMD_MAC_CONTROL: + ret = wlan_ret_mac_control(pmpriv, resp, pioctl_buf); + break; case HostCmd_CMD_802_11_HS_CFG_ENH: ret = wlan_ret_802_11_hs_cfg(pmpriv, resp, pioctl_buf); break; @@ -2863,7 +2909,9 @@ wlan_ops_uap_process_cmdresp(IN t_void * priv, case HostCmd_CMD_MEM_ACCESS: ret = wlan_ret_mem_access(pmpriv, resp, pioctl_buf); break; - + case HostCmd_CMD_WMM_QUEUE_CONFIG: + ret = wlan_ret_wmm_queue_config(pmpriv, resp, pioctl_buf); + break; default: PRINTM(MERROR, "CMD_RESP: Unknown command response %#x\n", resp->command); @@ -2899,6 +2947,13 @@ wlan_ops_uap_process_event(IN t_void * priv) ENTER(); + /* Event length check */ + if ((pmbuf->data_len - sizeof(eventcause)) > MAX_EVENT_SIZE) { + pmbuf->status_code = MLAN_ERROR_PKT_SIZE_INVALID; + LEAVE(); + return MLAN_STATUS_FAILURE; + } + /* Allocate memory for event buffer */ ret = pcb->moal_malloc(pmadapter->pmoal_handle, MAX_EVENT_SIZE, MLAN_MEM_DEF, @@ -2933,10 +2988,10 @@ wlan_ops_uap_process_event(IN t_void * priv) break; case EVENT_MICRO_AP_BSS_IDLE: PRINTM(MEVENT, "EVENT: MICRO_AP_BSS_IDLE\n"); - pmadapter->scan_block = MFALSE; pevent->event_id = MLAN_EVENT_ID_UAP_FW_BSS_IDLE; pmpriv->media_connected = MFALSE; wlan_clean_txrx(pmpriv); + wlan_notify_station_deauth(pmpriv); wlan_delete_station_list(pmpriv); break; case EVENT_PS_AWAKE: @@ -2959,11 +3014,12 @@ wlan_ops_uap_process_event(IN t_void * priv) wlan_check_ps_cond(pmadapter); break; case EVENT_MICRO_AP_STA_ASSOC: - PRINTM(MEVENT, "EVENT: MICRO_AP_STA_ASSOC\n"); wlan_process_sta_assoc_event(pmpriv, pevent, pmbuf); memcpy(pmadapter, sta_addr, pmadapter->event_body + 2, MLAN_MAC_ADDR_LENGTH); sta_ptr = wlan_add_station_entry(pmpriv, sta_addr); + PRINTM(MMSG, "wlan: EVENT: MICRO_AP_STA_ASSOC " MACSTR "\n", + MAC2STR(sta_addr)); if (pmpriv->is_11n_enabled) { wlan_check_sta_capability(pmpriv, pmbuf, sta_ptr); for (i = 0; i < MAX_NUM_TID; i++) { @@ -2979,8 +3035,6 @@ wlan_ops_uap_process_event(IN t_void * priv) pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU; break; case EVENT_MICRO_AP_STA_DEAUTH: - PRINTM(MEVENT, "EVENT: MICRO_AP_STA_DEAUTH\n"); - pmadapter->scan_block = MFALSE; pevent->event_id = MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT; pevent->bss_index = pmpriv->bss_index; pevent->event_len = pmbuf->data_len - 4; @@ -2990,6 +3044,8 @@ wlan_ops_uap_process_event(IN t_void * priv) wlan_recv_event(pmpriv, pevent->event_id, pevent); memcpy(pmadapter, sta_addr, pmadapter->event_body + 2, MLAN_MAC_ADDR_LENGTH); + PRINTM(MMSG, "wlan: EVENT: MICRO_AP_STA_DEAUTH " MACSTR "\n", + MAC2STR(sta_addr)); if (pmpriv->is_11n_enabled) { wlan_cleanup_reorder_tbl(pmpriv, sta_addr); pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, @@ -3097,6 +3153,20 @@ wlan_ops_uap_process_event(IN t_void * priv) pevent->event_id = MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED; break; #endif + + case EVENT_FW_DEBUG_INFO: + PRINTM(MERROR, "EVENT: FW Debug Info\n"); + memset(pmadapter, event_buf, 0x00, MAX_EVENT_SIZE); + pevent->bss_index = pmpriv->bss_index; + pevent->event_id = MLAN_EVENT_ID_FW_DEBUG_INFO; + pevent->event_len = pmbuf->data_len - sizeof(eventcause); + memcpy(pmadapter, + (t_u8 *) pevent->event_buf, + pmbuf->pbuf + pmbuf->data_offset + sizeof(eventcause), + pevent->event_len); + wlan_recv_event(pmpriv, pevent->event_id, pevent); + pevent->event_id = 0; // clear to avoid resending at end of fcn + break; default: pevent->event_id = MLAN_EVENT_ID_DRV_PASSTHRU; break; diff --git a/drivers/net/wireless/sd8797/mlan/mlan_uap_ioctl.c b/drivers/net/wireless/sd8797/mlan/mlan_uap_ioctl.c index 86b4942dff2f..58c69bdeea55 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_uap_ioctl.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_uap_ioctl.c @@ -682,7 +682,7 @@ wlan_uap_sec_ioctl_set_encrypt_key(IN pmlan_adapter pmadapter, LEAVE(); return MLAN_STATUS_FAILURE; } - if (!sec->param.encrypt_key.key_len) { + if (!sec->param.encrypt_key.key_remove && !sec->param.encrypt_key.key_len) { PRINTM(MCMND, "Skip set key with key_len = 0\n"); LEAVE(); return ret; @@ -867,11 +867,18 @@ wlan_uap_callback_domain_info(IN t_void * priv) wlan_uap_get_info_cb_t *puap_state_chan_cb = &pmpriv->uap_state_chan_cb; mlan_ds_11d_cfg *cfg11d; t_u8 band; + pmlan_adapter pmadapter = pmpriv->adapter; + pmlan_callbacks pcb = &pmadapter->callbacks; ENTER(); /* clear callback now that we're here */ puap_state_chan_cb->get_chan_callback = MNULL; + if (!puap_state_chan_cb->pioctl_req_curr) { + PRINTM(MERROR, "pioctl_req_curr is null\n"); + LEAVE(); + return ret; + } cfg11d = (mlan_ds_11d_cfg *) puap_state_chan_cb->pioctl_req_curr->pbuf; band = (puap_state_chan_cb->band_config & BAND_CONFIG_5GHZ) ? BAND_A : BAND_B; @@ -881,6 +888,12 @@ wlan_uap_callback_domain_info(IN t_void * priv) puap_state_chan_cb->pioctl_req_curr); if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; + else { + puap_state_chan_cb->pioctl_req_curr->status_code = MLAN_STATUS_FAILURE; + pcb->moal_ioctl_complete(pmadapter->pmoal_handle, + puap_state_chan_cb->pioctl_req_curr, + MLAN_STATUS_FAILURE); + } puap_state_chan_cb->pioctl_req_curr = MNULL; // prevent re-use LEAVE(); @@ -1248,8 +1261,8 @@ wlan_ops_uap_ioctl(t_void * adapter, pmlan_ioctl_req pioctl_req) mlan_ds_misc_cfg *misc = MNULL; mlan_ds_sec_cfg *sec = MNULL; mlan_ds_pm_cfg *pm = MNULL; - mlan_ds_snmp_mib *snmp = MNULL; mlan_ds_11d_cfg *cfg11d = MNULL; + mlan_ds_snmp_mib *snmp = MNULL; mlan_ds_11h_cfg *cfg11h = MNULL; mlan_ds_radio_cfg *radiocfg = MNULL; mlan_ds_rate *rate = MNULL; @@ -1281,6 +1294,8 @@ wlan_ops_uap_ioctl(t_void * adapter, pmlan_ioctl_req pioctl_req) else if (bss->sub_command == MLAN_OID_WIFI_DIRECT_MODE) status = wlan_bss_ioctl_wifi_direct_mode(pmadapter, pioctl_req); #endif + else if (bss->sub_command == MLAN_OID_BSS_REMOVE) + status = wlan_bss_ioctl_bss_remove(pmadapter, pioctl_req); break; case MLAN_IOCTL_GET_INFO: pget_info = (mlan_ds_get_info *) pioctl_req->pbuf; @@ -1329,6 +1344,8 @@ wlan_ops_uap_ioctl(t_void * adapter, pmlan_ioctl_req pioctl_req) #endif if (misc->sub_command == MLAN_OID_MISC_TXCONTROL) status = wlan_misc_ioctl_txcontrol(pmadapter, pioctl_req); + if (misc->sub_command == MLAN_OID_MISC_MAC_CONTROL) + status = wlan_misc_ioctl_mac_control(pmadapter, pioctl_req); break; case MLAN_IOCTL_PM_CFG: pm = (mlan_ds_pm_cfg *) pioctl_req->pbuf; @@ -1404,6 +1421,9 @@ wlan_ops_uap_ioctl(t_void * adapter, pmlan_ioctl_req pioctl_req) else if (reg_mem->sub_command == MLAN_OID_MEM_RW) status = wlan_reg_mem_ioctl_mem_rw(pmadapter, pioctl_req); break; + case MLAN_IOCTL_WMM_CFG: + status = wlan_wmm_cfg_ioctl(pmadapter, pioctl_req); + break; default: pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID; break; diff --git a/drivers/net/wireless/sd8797/mlan/mlan_uap_txrx.c b/drivers/net/wireless/sd8797/mlan/mlan_uap_txrx.c index 746d4547a82d..45c116a4c40a 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_uap_txrx.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_uap_txrx.c @@ -354,10 +354,8 @@ wlan_uap_recv_packet(IN mlan_private * priv, IN pmlan_buffer pmbuf) DBG_HEXDUMP(MDAT_D, "uap_recv_packet", pmbuf->pbuf + pmbuf->data_offset, MIN(pmbuf->data_len, MAX_DATA_DUMP_LEN)); - PRINTM(MDATA, "AMSDU dest %02x:%02x:%02x:%02x:%02x:%02x\n", - prx_pkt->eth803_hdr.dest_addr[0], prx_pkt->eth803_hdr.dest_addr[1], - prx_pkt->eth803_hdr.dest_addr[2], prx_pkt->eth803_hdr.dest_addr[3], - prx_pkt->eth803_hdr.dest_addr[4], prx_pkt->eth803_hdr.dest_addr[5]); + PRINTM(MDATA, "AMSDU dest " MACSTR "\n", + MAC2STR(prx_pkt->eth803_hdr.dest_addr)); /* don't do packet forwarding in disconnected state */ if ((priv->media_connected == MFALSE) || @@ -419,13 +417,8 @@ wlan_uap_recv_packet(IN mlan_private * priv, IN pmlan_buffer pmbuf) wlan_check_unicast_packet(priv, prx_pkt->eth803_hdr.dest_addr)) { /* drop packet */ - PRINTM(MDATA, "Drop AMSDU dest %02x:%02x:%02x:%02x:%02x:%02x\n", - prx_pkt->eth803_hdr.dest_addr[0], - prx_pkt->eth803_hdr.dest_addr[1], - prx_pkt->eth803_hdr.dest_addr[2], - prx_pkt->eth803_hdr.dest_addr[3], - prx_pkt->eth803_hdr.dest_addr[4], - prx_pkt->eth803_hdr.dest_addr[5]); + PRINTM(MDATA, "Drop AMSDU dest " MACSTR "\n", + MAC2STR(prx_pkt->eth803_hdr.dest_addr)); goto done; } } @@ -469,10 +462,8 @@ wlan_process_uap_rx_packet(IN mlan_private * priv, IN pmlan_buffer pmbuf) PRINTM(MINFO, "RX Data: data_len - prx_pd->rx_pkt_offset = %d - %d = %d\n", pmbuf->data_len, prx_pd->rx_pkt_offset, pmbuf->data_len - prx_pd->rx_pkt_offset); - PRINTM(MDATA, "Rx dest %02x:%02x:%02x:%02x:%02x:%02x\n", - prx_pkt->eth803_hdr.dest_addr[0], prx_pkt->eth803_hdr.dest_addr[1], - prx_pkt->eth803_hdr.dest_addr[2], prx_pkt->eth803_hdr.dest_addr[3], - prx_pkt->eth803_hdr.dest_addr[4], prx_pkt->eth803_hdr.dest_addr[5]); + PRINTM(MDATA, "Rx dest " MACSTR "\n", + MAC2STR(prx_pkt->eth803_hdr.dest_addr)); /* don't do packet forwarding in disconnected state */ /* don't do packet forwarding when packet > 1514 */ @@ -521,18 +512,14 @@ wlan_process_uap_rx_packet(IN mlan_private * priv, IN pmlan_buffer pmbuf) } else if (MLAN_STATUS_FAILURE == wlan_check_unicast_packet(priv, prx_pkt->eth803_hdr.dest_addr)) { - PRINTM(MDATA, "Drop Pkts: Rx dest %02x:%02x:%02x:%02x:%02x:%02x\n", - prx_pkt->eth803_hdr.dest_addr[0], - prx_pkt->eth803_hdr.dest_addr[1], - prx_pkt->eth803_hdr.dest_addr[2], - prx_pkt->eth803_hdr.dest_addr[3], - prx_pkt->eth803_hdr.dest_addr[4], - prx_pkt->eth803_hdr.dest_addr[5]); + PRINTM(MDATA, "Drop Pkts: Rx dest " MACSTR "\n", + MAC2STR(prx_pkt->eth803_hdr.dest_addr)); pmbuf->status_code = MLAN_ERROR_PKT_INVALID; wlan_free_mlan_buffer(pmadapter, pmbuf); goto done; } } + upload: /* Chop off RxPD */ pmbuf->data_len -= prx_pd->rx_pkt_offset; diff --git a/drivers/net/wireless/sd8797/mlan/mlan_wmm.c b/drivers/net/wireless/sd8797/mlan/mlan_wmm.c index daf798265b98..f347a8019227 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_wmm.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_wmm.c @@ -571,7 +571,7 @@ wlan_send_wmmac_host_event(pmlan_private priv, pevent->bss_index = priv->bss_index; pevent->event_id = MLAN_EVENT_ID_DRV_REPORT_STRING; - pevent->event_len = wlan_strlen((const t_s8 *) (pevent->event_buf)); + pevent->event_len = wlan_strlen((const char *) (pevent->event_buf)); wlan_recv_event(priv, MLAN_EVENT_ID_DRV_REPORT_STRING, pevent); LEAVE(); @@ -702,6 +702,7 @@ wlan_wmm_get_highest_priolist_ptr(pmlan_adapter pmadapter, if ((bssprio_node = bssprio_node->pnext) == (mlan_bssprio_node *) & pmadapter->bssprio_tbl[j].bssprio_head) bssprio_node = bssprio_node->pnext; + pmadapter->bssprio_tbl[j].bssprio_cur = bssprio_node; } while (bssprio_node != bssprio_head); } @@ -1033,7 +1034,7 @@ wlan_dequeue_tx_packet(pmlan_adapter pmadapter) * @return N/A */ t_void -wlan_updata_ralist_tx_pause(pmlan_private priv, t_u8 * mac, t_u8 tx_pause) +wlan_update_ralist_tx_pause(pmlan_private priv, t_u8 * mac, t_u8 tx_pause) { raListTbl *ra_list; int i; @@ -1128,9 +1129,7 @@ wlan_clean_txrx(pmlan_private priv) ENTER(); - if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) { - wlan_cleanup_bypass_txq(pmadapter); - } + wlan_cleanup_bypass_txq(priv); wlan_11n_cleanup_reorder_tbl(priv); @@ -1162,9 +1161,6 @@ wlan_clean_txrx(pmlan_private priv) MP_TX_AGGR_BUF_RESET(priv->adapter); #endif -#ifdef SDIO_MULTI_PORT_RX_AGGR - MP_RX_AGGR_BUF_RESET(priv->adapter); -#endif wlan_wmm_delete_all_ralist(priv); memcpy(pmadapter, tos_to_tid, ac_to_tid, sizeof(tos_to_tid)); for (i = 0; i < MAX_NUM_TID; i++) { @@ -1384,15 +1380,8 @@ wlan_wmm_init(pmlan_adapter pmadapter) if ((priv = pmadapter->priv[j])) { for (i = 0; i < MAX_NUM_TID; ++i) { priv->aggr_prio_tbl[i].amsdu = BA_STREAM_NOT_ALLOWED; -#ifdef WIFI_DIRECT_SUPPORT - if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) - priv->aggr_prio_tbl[i].ampdu_ap = - priv->aggr_prio_tbl[i].ampdu_user = - BA_STREAM_NOT_ALLOWED; - else -#endif - priv->aggr_prio_tbl[i].ampdu_ap = - priv->aggr_prio_tbl[i].ampdu_user = tos_to_tid_inv[i]; + priv->aggr_prio_tbl[i].ampdu_ap = + priv->aggr_prio_tbl[i].ampdu_user = tos_to_tid_inv[i]; priv->wmm.pkts_queued[i] = 0; priv->wmm.tid_tbl_ptr[i].ra_list_curr = MNULL; } @@ -1606,13 +1595,9 @@ wlan_ralist_update(mlan_private * priv, t_u8 * old_ra, t_u8 * new_ra) ra_list->packet_count = 0; ra_list->ba_packet_threshold = wlan_get_random_ba_threshold(priv->adapter); - PRINTM(MINFO, - "ralist_update: %p, %d, %02x:%02x:%02x:%02x:%02x:%02x-->" - "%02x:%02x:%02x:%02x:%02x:%02x\n", ra_list, - ra_list->is_11n_enabled, ra_list->ra[0], ra_list->ra[1], - ra_list->ra[2], ra_list->ra[3], ra_list->ra[4], - ra_list->ra[5], new_ra[0], new_ra[1], new_ra[2], new_ra[3], - new_ra[4], new_ra[5]); + PRINTM(MINFO, "ralist_update: %p, %d, " MACSTR "-->" MACSTR "\n", + ra_list, ra_list->is_11n_enabled, MAC2STR(ra_list->ra), + MAC2STR(new_ra)); memcpy(priv->adapter, ra_list->ra, new_ra, MLAN_MAC_ADDR_LENGTH); } @@ -2065,11 +2050,9 @@ wlan_del_tx_pkts_in_ralist(pmlan_private priv, &ra_list->buf_head, MNULL, MNULL))) { PRINTM(MDATA, - "Drop pkts: tid=%d tx_pause=%d pkts=%d brd_pkts=%d %02x:%02x:%02x:%02x:%02x:%02x\n", - tid, ra_list->tx_pause, ra_list->total_pkts, - pmadapter->pending_bridge_pkts, ra_list->ra[0], - ra_list->ra[1], ra_list->ra[2], ra_list->ra[3], - ra_list->ra[4], ra_list->ra[5]); + "Drop pkts: tid=%d tx_pause=%d pkts=%d brd_pkts=%d " + MACSTR "\n", tid, ra_list->tx_pause, ra_list->total_pkts, + pmadapter->pending_bridge_pkts, MAC2STR(ra_list->ra)); wlan_write_data_complete(pmadapter, pmbuf, MLAN_STATUS_FAILURE); priv->wmm.pkts_queued[tid]--; priv->num_drop_pkts++; @@ -2344,70 +2327,6 @@ wlan_ret_wmm_delts_req(IN pmlan_private pmpriv, } /** - * @brief This function prepares the command of WMM_QUEUE_CONFIG - * - * @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 - * @return MLAN_STATUS_SUCCESS - */ -mlan_status -wlan_cmd_wmm_queue_config(IN pmlan_private pmpriv, - OUT HostCmd_DS_COMMAND * cmd, IN t_void * pdata_buf) -{ - mlan_ds_wmm_queue_config *pqcfg = (mlan_ds_wmm_queue_config *) pdata_buf; - HostCmd_DS_WMM_QUEUE_CONFIG *pcmd_qcfg = &cmd->params.queue_config; - - ENTER(); - - cmd->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_QUEUE_CONFIG); - cmd->size = wlan_cpu_to_le16(sizeof(pcmd_qcfg->action) - + sizeof(pcmd_qcfg->access_category) - + sizeof(pcmd_qcfg->msdu_lifetime_expiry) - + S_DS_GEN); - cmd->result = 0; - - pcmd_qcfg->action = pqcfg->action; - pcmd_qcfg->access_category = pqcfg->access_category; - pcmd_qcfg->msdu_lifetime_expiry = - wlan_cpu_to_le16(pqcfg->msdu_lifetime_expiry); - - LEAVE(); - return MLAN_STATUS_SUCCESS; -} - -/** - * @brief This function handles the command response of WMM_QUEUE_CONFIG - * - * @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_wmm_queue_config(IN pmlan_private pmpriv, - const IN HostCmd_DS_COMMAND * resp, - OUT mlan_ioctl_req * pioctl_buf) -{ - mlan_ds_wmm_cfg *pwmm = MNULL; - const HostCmd_DS_WMM_QUEUE_CONFIG *presp_qcfg = &resp->params.queue_config; - - ENTER(); - - if (pioctl_buf) { - pwmm = (mlan_ds_wmm_cfg *) pioctl_buf->pbuf; - pwmm->param.q_cfg.action = presp_qcfg->action; - pwmm->param.q_cfg.access_category = presp_qcfg->access_category; - pwmm->param.q_cfg.msdu_lifetime_expiry = - wlan_le16_to_cpu(presp_qcfg->msdu_lifetime_expiry); - } - - LEAVE(); - return MLAN_STATUS_SUCCESS; -} - -/** * @brief This function prepares the command of WMM_QUEUE_STATS * * @param pmpriv A pointer to mlan_private structure @@ -2552,4 +2471,381 @@ wlan_ret_wmm_ts_status(IN pmlan_private pmpriv, LEAVE(); return MLAN_STATUS_SUCCESS; } + +/** + * @brief Set/Get WMM status + * + * @param pmadapter A pointer to mlan_adapter structure + * @param pioctl_req A pointer to ioctl request buffer + * + * @return MLAN_STATUS_SUCCESS --success + */ +static mlan_status +wlan_wmm_ioctl_enable(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_wmm_cfg *wmm = MNULL; + ENTER(); + wmm = (mlan_ds_wmm_cfg *) pioctl_req->pbuf; + if (pioctl_req->action == MLAN_ACT_GET) + wmm->param.wmm_enable = (t_u32) pmpriv->wmm_required; + else + pmpriv->wmm_required = (t_u8) wmm->param.wmm_enable; + pioctl_req->data_read_written = sizeof(t_u32) + MLAN_SUB_COMMAND_SIZE; + LEAVE(); + return ret; +} + +/** + * @brief Set/Get WMM QoS configuration + * + * @param pmadapter A pointer to mlan_adapter structure + * @param pioctl_req A pointer to ioctl request buffer + * + * @return MLAN_STATUS_SUCCESS --success + */ +static mlan_status +wlan_wmm_ioctl_qos(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_wmm_cfg *wmm = MNULL; + + ENTER(); + + wmm = (mlan_ds_wmm_cfg *) pioctl_req->pbuf; + + if (pioctl_req->action == MLAN_ACT_GET) + wmm->param.qos_cfg = pmpriv->wmm_qosinfo; + else { + pmpriv->wmm_qosinfo = wmm->param.qos_cfg; + } + + pioctl_req->data_read_written = sizeof(t_u8) + MLAN_SUB_COMMAND_SIZE; + + LEAVE(); + return ret; +} + +/** + * @brief Request for add a TSPEC + * + * @param pmadapter A pointer to mlan_adapter structure + * @param pioctl_req A pointer to ioctl request buffer + * + * @return MLAN_STATUS_PENDING --success, otherwise fail + */ +static mlan_status +wlan_wmm_ioctl_addts_req(IN pmlan_adapter pmadapter, + IN pmlan_ioctl_req pioctl_req) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; + mlan_ds_wmm_cfg *cfg = MNULL; + + ENTER(); + cfg = (mlan_ds_wmm_cfg *) pioctl_req->pbuf; + + /* Send request to firmware */ + ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_ADDTS_REQ, + 0, 0, (t_void *) pioctl_req, + (t_void *) & cfg->param.addts); + + if (ret == MLAN_STATUS_SUCCESS) + ret = MLAN_STATUS_PENDING; + + LEAVE(); + return ret; +} + +/** + * @brief Request for delete a TSPEC + * + * @param pmadapter A pointer to mlan_adapter structure + * @param pioctl_req A pointer to ioctl request buffer + * + * @return MLAN_STATUS_PENDING --success, otherwise fail + */ +static mlan_status +wlan_wmm_ioctl_delts_req(IN pmlan_adapter pmadapter, + IN pmlan_ioctl_req pioctl_req) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; + mlan_ds_wmm_cfg *cfg = MNULL; + + ENTER(); + cfg = (mlan_ds_wmm_cfg *) pioctl_req->pbuf; + + /* Send request to firmware */ + ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_DELTS_REQ, + 0, 0, (t_void *) pioctl_req, + (t_void *) & cfg->param.delts); + + if (ret == MLAN_STATUS_SUCCESS) + ret = MLAN_STATUS_PENDING; + + LEAVE(); + return ret; +} + +/** + * @brief To get and start/stop queue stats on a WMM AC + * + * @param pmadapter A pointer to mlan_adapter structure + * @param pioctl_req A pointer to ioctl request buffer + * + * @return MLAN_STATUS_PENDING --success, otherwise fail + */ +static mlan_status +wlan_wmm_ioctl_queue_stats(IN pmlan_adapter pmadapter, + IN pmlan_ioctl_req pioctl_req) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; + mlan_ds_wmm_cfg *cfg = MNULL; + + ENTER(); + cfg = (mlan_ds_wmm_cfg *) pioctl_req->pbuf; + + /* Send request to firmware */ + ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_QUEUE_STATS, + 0, 0, (t_void *) pioctl_req, + (t_void *) & cfg->param.q_stats); + + if (ret == MLAN_STATUS_SUCCESS) + ret = MLAN_STATUS_PENDING; + + LEAVE(); + return ret; +} + +/** + * @brief Get the status of the WMM AC queues + * + * @param pmadapter A pointer to mlan_adapter structure + * @param pioctl_req A pointer to ioctl request buffer + * + * @return MLAN_STATUS_SUCCESS --success + */ +static mlan_status +wlan_wmm_ioctl_queue_status(IN pmlan_adapter pmadapter, + IN pmlan_ioctl_req pioctl_req) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; + mlan_ds_wmm_cfg *cfg = MNULL; + mlan_ds_wmm_queue_status *pqstatus = MNULL; + WmmAcStatus_t *pac_status = MNULL; + mlan_wmm_ac_e ac_idx; + + ENTER(); + + cfg = (mlan_ds_wmm_cfg *) pioctl_req->pbuf; + pqstatus = (mlan_ds_wmm_queue_status *) & cfg->param.q_status; + + for (ac_idx = WMM_AC_BK; ac_idx <= WMM_AC_VO; ac_idx++) { + pac_status = &pmpriv->wmm.ac_status[ac_idx]; + + /* Firmware status */ + pqstatus->ac_status[ac_idx].flow_required = pac_status->flow_required; + pqstatus->ac_status[ac_idx].flow_created = pac_status->flow_created; + pqstatus->ac_status[ac_idx].disabled = pac_status->disabled; + + /* ACM bit reflected in firmware status (redundant) */ + pqstatus->ac_status[ac_idx].wmm_acm = pac_status->flow_required; + } + + LEAVE(); + return ret; +} + +/** + * @brief Get the status of the WMM Traffic Streams + * + * @param pmadapter A pointer to mlan_adapter structure + * @param pioctl_req A pointer to ioctl request buffer + * + * @return MLAN_STATUS_PENDING --success, otherwise fail + */ +static mlan_status +wlan_wmm_ioctl_ts_status(IN pmlan_adapter pmadapter, + IN pmlan_ioctl_req pioctl_req) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; + mlan_ds_wmm_cfg *cfg = MNULL; + + ENTER(); + + cfg = (mlan_ds_wmm_cfg *) pioctl_req->pbuf; + + /* Send request to firmware */ + ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_TS_STATUS, + 0, 0, (t_void *) pioctl_req, + (t_void *) & cfg->param.ts_status); + + if (ret == MLAN_STATUS_SUCCESS) + ret = MLAN_STATUS_PENDING; + + LEAVE(); + return ret; +} #endif /* STA_SUPPORT */ + +/** + * @brief This function prepares the command of WMM_QUEUE_CONFIG + * + * @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 + * @return MLAN_STATUS_SUCCESS + */ +mlan_status +wlan_cmd_wmm_queue_config(IN pmlan_private pmpriv, + OUT HostCmd_DS_COMMAND * cmd, IN t_void * pdata_buf) +{ + mlan_ds_wmm_queue_config *pqcfg = (mlan_ds_wmm_queue_config *) pdata_buf; + HostCmd_DS_WMM_QUEUE_CONFIG *pcmd_qcfg = &cmd->params.queue_config; + + ENTER(); + + cmd->command = wlan_cpu_to_le16(HostCmd_CMD_WMM_QUEUE_CONFIG); + cmd->size = wlan_cpu_to_le16(sizeof(pcmd_qcfg->action) + + sizeof(pcmd_qcfg->access_category) + + sizeof(pcmd_qcfg->msdu_lifetime_expiry) + + S_DS_GEN); + cmd->result = 0; + + pcmd_qcfg->action = pqcfg->action; + pcmd_qcfg->access_category = pqcfg->access_category; + pcmd_qcfg->msdu_lifetime_expiry = + wlan_cpu_to_le16(pqcfg->msdu_lifetime_expiry); + + LEAVE(); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief This function handles the command response of WMM_QUEUE_CONFIG + * + * @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_wmm_queue_config(IN pmlan_private pmpriv, + const IN HostCmd_DS_COMMAND * resp, + OUT mlan_ioctl_req * pioctl_buf) +{ + mlan_ds_wmm_cfg *pwmm = MNULL; + const HostCmd_DS_WMM_QUEUE_CONFIG *presp_qcfg = &resp->params.queue_config; + + ENTER(); + + if (pioctl_buf) { + pwmm = (mlan_ds_wmm_cfg *) pioctl_buf->pbuf; + pwmm->param.q_cfg.action = presp_qcfg->action; + pwmm->param.q_cfg.access_category = presp_qcfg->access_category; + pwmm->param.q_cfg.msdu_lifetime_expiry = + wlan_le16_to_cpu(presp_qcfg->msdu_lifetime_expiry); + } + + LEAVE(); + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Set/Get a specified AC Queue's parameters + * + * @param pmadapter A pointer to mlan_adapter structure + * @param pioctl_req A pointer to ioctl request buffer + * + * @return MLAN_STATUS_PENDING --success, otherwise fail + */ +static mlan_status +wlan_wmm_ioctl_queue_config(IN pmlan_adapter pmadapter, + IN pmlan_ioctl_req pioctl_req) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; + mlan_ds_wmm_cfg *cfg = MNULL; + + ENTER(); + cfg = (mlan_ds_wmm_cfg *) pioctl_req->pbuf; + + /* Send request to firmware */ + ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_WMM_QUEUE_CONFIG, + 0, 0, (t_void *) pioctl_req, + (t_void *) & cfg->param.q_cfg); + + if (ret == MLAN_STATUS_SUCCESS) + ret = MLAN_STATUS_PENDING; + + LEAVE(); + return ret; +} + +/** + * @brief WMM configuration handler + * + * @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_wmm_cfg_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) +{ + mlan_status status = MLAN_STATUS_SUCCESS; + mlan_ds_wmm_cfg *wmm = MNULL; + + ENTER(); + + if (pioctl_req->buf_len < sizeof(mlan_ds_wmm_cfg)) { + PRINTM(MWARN, "MLAN bss IOCTL length is too short.\n"); + pioctl_req->data_read_written = 0; + pioctl_req->buf_len_needed = sizeof(mlan_ds_wmm_cfg); + pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER; + LEAVE(); + return MLAN_STATUS_RESOURCE; + } + wmm = (mlan_ds_wmm_cfg *) pioctl_req->pbuf; + switch (wmm->sub_command) { +#ifdef STA_SUPPORT + case MLAN_OID_WMM_CFG_ENABLE: + status = wlan_wmm_ioctl_enable(pmadapter, pioctl_req); + break; + case MLAN_OID_WMM_CFG_QOS: + status = wlan_wmm_ioctl_qos(pmadapter, pioctl_req); + break; + case MLAN_OID_WMM_CFG_ADDTS: + status = wlan_wmm_ioctl_addts_req(pmadapter, pioctl_req); + break; + case MLAN_OID_WMM_CFG_DELTS: + status = wlan_wmm_ioctl_delts_req(pmadapter, pioctl_req); + break; + case MLAN_OID_WMM_CFG_QUEUE_STATS: + status = wlan_wmm_ioctl_queue_stats(pmadapter, pioctl_req); + break; + case MLAN_OID_WMM_CFG_QUEUE_STATUS: + status = wlan_wmm_ioctl_queue_status(pmadapter, pioctl_req); + break; + case MLAN_OID_WMM_CFG_TS_STATUS: + status = wlan_wmm_ioctl_ts_status(pmadapter, pioctl_req); + break; +#endif + case MLAN_OID_WMM_CFG_QUEUE_CONFIG: + status = wlan_wmm_ioctl_queue_config(pmadapter, pioctl_req); + break; + default: + pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID; + status = MLAN_STATUS_FAILURE; + break; + } + LEAVE(); + return status; +} diff --git a/drivers/net/wireless/sd8797/mlan/mlan_wmm.h b/drivers/net/wireless/sd8797/mlan/mlan_wmm.h index 89a2c8f37e49..e36dea734b6d 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_wmm.h +++ b/drivers/net/wireless/sd8797/mlan/mlan_wmm.h @@ -138,10 +138,6 @@ extern mlan_status wlan_cmd_wmm_addts_req(IN pmlan_private pmpriv, extern mlan_status wlan_cmd_wmm_delts_req(IN pmlan_private pmpriv, OUT HostCmd_DS_COMMAND * cmd, IN t_void * pdata_buf); -/** WMM QUEUE_CONFIG command handler */ -extern mlan_status wlan_cmd_wmm_queue_config(IN pmlan_private pmpriv, - OUT HostCmd_DS_COMMAND * cmd, - IN t_void * pdata_buf); /** WMM QUEUE_STATS command handler */ extern mlan_status wlan_cmd_wmm_queue_stats(IN pmlan_private pmpriv, OUT HostCmd_DS_COMMAND * cmd, @@ -165,10 +161,6 @@ extern mlan_status wlan_ret_wmm_addts_req(IN pmlan_private pmpriv, extern mlan_status wlan_ret_wmm_delts_req(IN pmlan_private pmpriv, const IN HostCmd_DS_COMMAND * resp, OUT mlan_ioctl_req * pioctl_buf); -/** WMM QUEUE_CONFIG command response handler */ -extern mlan_status wlan_ret_wmm_queue_config(IN pmlan_private pmpriv, - const IN HostCmd_DS_COMMAND * resp, - OUT mlan_ioctl_req * pioctl_buf); /** WMM QUEUE_STATS command response handler */ extern mlan_status wlan_ret_wmm_queue_stats(IN pmlan_private pmpriv, const IN HostCmd_DS_COMMAND * resp, @@ -179,4 +171,16 @@ extern mlan_status wlan_ret_wmm_ts_status(IN pmlan_private pmpriv, OUT mlan_ioctl_req * pioctl_buf); #endif /* STA_SUPPORT */ +/** WMM QUEUE_CONFIG command handler */ +extern mlan_status wlan_cmd_wmm_queue_config(IN pmlan_private pmpriv, + OUT HostCmd_DS_COMMAND * cmd, + IN t_void * pdata_buf); + +/** WMM QUEUE_CONFIG command response handler */ +extern mlan_status wlan_ret_wmm_queue_config(IN pmlan_private pmpriv, + const IN HostCmd_DS_COMMAND * resp, + OUT mlan_ioctl_req * pioctl_buf); + +mlan_status wlan_wmm_cfg_ioctl(IN pmlan_adapter pmadapter, + IN pmlan_ioctl_req pioctl_req); #endif /* !_MLAN_WMM_H_ */ diff --git a/drivers/net/wireless/sd8797/mlinux/mlan_decl.h b/drivers/net/wireless/sd8797/mlinux/mlan_decl.h index ac24b5e79fc4..28ab785045e3 100644 --- a/drivers/net/wireless/sd8797/mlinux/mlan_decl.h +++ b/drivers/net/wireless/sd8797/mlinux/mlan_decl.h @@ -27,11 +27,11 @@ Change log: #define _MLAN_DECL_H_ /** MLAN release version */ -#define MLAN_RELEASE_VERSION "334" +#define MLAN_RELEASE_VERSION "394" /** Re-define generic data types for MLAN/MOAL */ /** Signed char (1-byte) */ -typedef char t_s8; +typedef signed char t_s8; /** Unsigned char (1-byte) */ typedef unsigned char t_u8; /** Signed short (2-bytes) */ @@ -101,6 +101,16 @@ typedef t_s32 t_sval; /** MLAN FALSE */ #define MFALSE (0) +#ifndef MACSTR +/** MAC address security format */ +#define MACSTR "%02x:XX:XX:XX:%02x:%02x" +#endif + +#ifndef MAC2STR +/** MAC address security print arguments */ +#define MAC2STR(a) (a)[0], (a)[4], (a)[5] +#endif + /** Macros for Data Alignment : size */ #define ALIGN_SZ(p, a) \ (((p) + ((a) - 1)) & ~((a) - 1)) @@ -296,26 +306,26 @@ typedef enum _mlan_error_code MLAN_ERROR_NO_ERROR = 0, /** Firmware/device errors below (MSB=0) */ MLAN_ERROR_FW_NOT_READY = 0x00000001, - MLAN_ERROR_FW_BUSY, - MLAN_ERROR_FW_CMDRESP, - MLAN_ERROR_DATA_TX_FAIL, - MLAN_ERROR_DATA_RX_FAIL, + MLAN_ERROR_FW_BUSY = 0x00000002, + MLAN_ERROR_FW_CMDRESP = 0x00000003, + MLAN_ERROR_DATA_TX_FAIL = 0x00000004, + MLAN_ERROR_DATA_RX_FAIL = 0x00000005, /** Driver errors below (MSB=1) */ MLAN_ERROR_PKT_SIZE_INVALID = 0x80000001, - MLAN_ERROR_PKT_TIMEOUT, - MLAN_ERROR_PKT_INVALID, - MLAN_ERROR_CMD_INVALID, - MLAN_ERROR_CMD_TIMEOUT, - MLAN_ERROR_CMD_DNLD_FAIL, - MLAN_ERROR_CMD_CANCEL, - MLAN_ERROR_CMD_RESP_FAIL, - MLAN_ERROR_CMD_ASSOC_FAIL, - MLAN_ERROR_CMD_SCAN_FAIL, - MLAN_ERROR_IOCTL_INVALID, - MLAN_ERROR_IOCTL_FAIL, - MLAN_ERROR_EVENT_UNKNOWN, - MLAN_ERROR_INVALID_PARAMETER, - MLAN_ERROR_NO_MEM, + MLAN_ERROR_PKT_TIMEOUT = 0x80000002, + MLAN_ERROR_PKT_INVALID = 0x80000003, + MLAN_ERROR_CMD_INVALID = 0x80000004, + MLAN_ERROR_CMD_TIMEOUT = 0x80000005, + MLAN_ERROR_CMD_DNLD_FAIL = 0x80000006, + MLAN_ERROR_CMD_CANCEL = 0x80000007, + MLAN_ERROR_CMD_RESP_FAIL = 0x80000008, + MLAN_ERROR_CMD_ASSOC_FAIL = 0x80000009, + MLAN_ERROR_CMD_SCAN_FAIL = 0x8000000A, + MLAN_ERROR_IOCTL_INVALID = 0x8000000B, + MLAN_ERROR_IOCTL_FAIL = 0x8000000C, + MLAN_ERROR_EVENT_UNKNOWN = 0x8000000D, + MLAN_ERROR_INVALID_PARAMETER = 0x8000000E, + MLAN_ERROR_NO_MEM = 0x8000000F, /** More to add */ } mlan_error_code; @@ -365,56 +375,60 @@ typedef enum _mlan_event_id { /* Event generated by firmware (MSB=0) */ MLAN_EVENT_ID_FW_UNKNOWN = 0x00000001, - MLAN_EVENT_ID_FW_ADHOC_LINK_SENSED, - MLAN_EVENT_ID_FW_ADHOC_LINK_LOST, - MLAN_EVENT_ID_FW_DISCONNECTED, - MLAN_EVENT_ID_FW_MIC_ERR_UNI, - MLAN_EVENT_ID_FW_MIC_ERR_MUL, - MLAN_EVENT_ID_FW_BCN_RSSI_LOW, - MLAN_EVENT_ID_FW_BCN_RSSI_HIGH, - MLAN_EVENT_ID_FW_BCN_SNR_LOW, - MLAN_EVENT_ID_FW_BCN_SNR_HIGH, - MLAN_EVENT_ID_FW_MAX_FAIL, - MLAN_EVENT_ID_FW_DATA_RSSI_LOW, - MLAN_EVENT_ID_FW_DATA_RSSI_HIGH, - MLAN_EVENT_ID_FW_DATA_SNR_LOW, - MLAN_EVENT_ID_FW_DATA_SNR_HIGH, - MLAN_EVENT_ID_FW_LINK_QUALITY, - MLAN_EVENT_ID_FW_PORT_RELEASE, - MLAN_EVENT_ID_FW_PRE_BCN_LOST, - MLAN_EVENT_ID_FW_WMM_CONFIG_CHANGE, - MLAN_EVENT_ID_FW_HS_WAKEUP, - MLAN_EVENT_ID_FW_BG_SCAN, - MLAN_EVENT_ID_FW_WEP_ICV_ERR, - MLAN_EVENT_ID_FW_STOP_TX, - MLAN_EVENT_ID_FW_START_TX, - MLAN_EVENT_ID_FW_CHANNEL_SWITCH_ANN, - MLAN_EVENT_ID_FW_RADAR_DETECTED, - MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY, - MLAN_EVENT_ID_FW_BW_CHANGED, + MLAN_EVENT_ID_FW_ADHOC_LINK_SENSED = 0x00000002, + MLAN_EVENT_ID_FW_ADHOC_LINK_LOST = 0x00000003, + MLAN_EVENT_ID_FW_DISCONNECTED = 0x00000004, + MLAN_EVENT_ID_FW_MIC_ERR_UNI = 0x00000005, + MLAN_EVENT_ID_FW_MIC_ERR_MUL = 0x00000006, + MLAN_EVENT_ID_FW_BCN_RSSI_LOW = 0x00000007, + MLAN_EVENT_ID_FW_BCN_RSSI_HIGH = 0x00000008, + MLAN_EVENT_ID_FW_BCN_SNR_LOW = 0x00000009, + MLAN_EVENT_ID_FW_BCN_SNR_HIGH = 0x0000000A, + MLAN_EVENT_ID_FW_MAX_FAIL = 0x0000000B, + MLAN_EVENT_ID_FW_DATA_RSSI_LOW = 0x0000000C, + MLAN_EVENT_ID_FW_DATA_RSSI_HIGH = 0x0000000D, + MLAN_EVENT_ID_FW_DATA_SNR_LOW = 0x0000000E, + MLAN_EVENT_ID_FW_DATA_SNR_HIGH = 0x0000000F, + MLAN_EVENT_ID_FW_LINK_QUALITY = 0x00000010, + MLAN_EVENT_ID_FW_PORT_RELEASE = 0x00000011, + MLAN_EVENT_ID_FW_PRE_BCN_LOST = 0x00000012, + MLAN_EVENT_ID_FW_DEBUG_INFO = 0x00000013, + MLAN_EVENT_ID_FW_WMM_CONFIG_CHANGE = 0x0000001A, + MLAN_EVENT_ID_FW_HS_WAKEUP = 0x0000001B, + MLAN_EVENT_ID_FW_BG_SCAN = 0x0000001D, + MLAN_EVENT_ID_FW_BG_SCAN_STOPPED = 0x0000001E, + MLAN_EVENT_ID_FW_WEP_ICV_ERR = 0x00000020, + MLAN_EVENT_ID_FW_STOP_TX = 0x00000021, + MLAN_EVENT_ID_FW_START_TX = 0x00000022, + MLAN_EVENT_ID_FW_CHANNEL_SWITCH_ANN = 0x00000023, + MLAN_EVENT_ID_FW_RADAR_DETECTED = 0x00000024, + MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY = 0x00000025, + MLAN_EVENT_ID_FW_BW_CHANGED = 0x00000026, #ifdef WIFI_DIRECT_SUPPORT - MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED, + MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED = 0x0000002B, #endif #ifdef UAP_SUPPORT - MLAN_EVENT_ID_UAP_FW_BSS_START, - MLAN_EVENT_ID_UAP_FW_BSS_ACTIVE, - MLAN_EVENT_ID_UAP_FW_BSS_IDLE, - MLAN_EVENT_ID_UAP_FW_STA_CONNECT, - MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT, + MLAN_EVENT_ID_UAP_FW_BSS_START = 0x0000002C, + MLAN_EVENT_ID_UAP_FW_BSS_ACTIVE = 0x0000002D, + MLAN_EVENT_ID_UAP_FW_BSS_IDLE = 0x0000002E, + MLAN_EVENT_ID_UAP_FW_STA_CONNECT = 0x00000030, + MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT = 0x00000031, #endif /* Event generated by MLAN driver (MSB=1) */ MLAN_EVENT_ID_DRV_CONNECTED = 0x80000001, - MLAN_EVENT_ID_DRV_DEFER_HANDLING, - MLAN_EVENT_ID_DRV_HS_ACTIVATED, - MLAN_EVENT_ID_DRV_HS_DEACTIVATED, - MLAN_EVENT_ID_DRV_MGMT_FRAME, - MLAN_EVENT_ID_DRV_OBSS_SCAN_PARAM, - MLAN_EVENT_ID_DRV_PASSTHRU, - MLAN_EVENT_ID_DRV_SCAN_REPORT, - MLAN_EVENT_ID_DRV_MEAS_REPORT, - MLAN_EVENT_ID_DRV_REPORT_STRING, - MLAN_EVENT_ID_DRV_DBG_DUMP, + MLAN_EVENT_ID_DRV_DEFER_HANDLING = 0x80000002, + MLAN_EVENT_ID_DRV_HS_ACTIVATED = 0x80000003, + MLAN_EVENT_ID_DRV_HS_DEACTIVATED = 0x80000004, + MLAN_EVENT_ID_DRV_MGMT_FRAME = 0x80000005, + MLAN_EVENT_ID_DRV_OBSS_SCAN_PARAM = 0x80000006, + MLAN_EVENT_ID_DRV_PASSTHRU = 0x80000007, + MLAN_EVENT_ID_DRV_SCAN_REPORT = 0x80000009, + MLAN_EVENT_ID_DRV_MEAS_REPORT = 0x8000000A, + MLAN_EVENT_ID_DRV_ASSOC_FAILURE_REPORT = 0x8000000B, + MLAN_EVENT_ID_DRV_REPORT_STRING = 0x8000000F, + MLAN_EVENT_ID_DRV_DBG_DUMP = 0x80000012, + MLAN_EVENT_ID_DRV_BGSCAN_RESULT = 0x80000013, } mlan_event_id; /** Data Structures */ @@ -552,6 +566,8 @@ typedef struct _mlan_bss_attr t_u32 bss_priority; /** BSS number */ t_u32 bss_num; + /** The BSS is virtual */ + t_u32 bss_virtual; } mlan_bss_attr, *pmlan_bss_attr; #ifdef PRAGMA_PACK @@ -711,6 +727,7 @@ typedef struct _mlan_callbacks mlan_status(*moal_ioctl_complete) (IN t_void * pmoal_handle, IN pmlan_ioctl_req pioctl_req, IN mlan_status status); + /** moal_alloc_mlan_buffer */ mlan_status(*moal_alloc_mlan_buffer) (IN t_void * pmoal_handle, IN t_u32 size, @@ -738,6 +755,11 @@ typedef struct _mlan_callbacks IN t_u32 size, IN t_u32 flag, OUT t_u8 ** ppbuf); /** moal_mfree */ mlan_status(*moal_mfree) (IN t_void * pmoal_handle, IN t_u8 * pbuf); + /** moal_vmalloc */ + mlan_status(*moal_vmalloc) (IN t_void * pmoal_handle, + IN t_u32 size, OUT t_u8 ** ppbuf); + /** moal_vfree */ + mlan_status(*moal_vfree) (IN t_void * pmoal_handle, IN t_u8 * pbuf); /** moal_memset */ t_void *(*moal_memset) (IN t_void * pmoal_handle, IN t_void * pmem, IN t_u8 byte, IN t_u32 num); @@ -787,7 +809,7 @@ typedef struct _mlan_callbacks IN t_void * plock); /** moal_print */ t_void(*moal_print) (IN t_void * pmoal_handle, - IN t_u32 level, IN t_s8 * pformat, IN ...); + IN t_u32 level, IN char *pformat, IN ...); /** moal_print_netintf */ t_void(*moal_print_netintf) (IN t_void * pmoal_handle, IN t_u32 bss_index, IN t_u32 level); @@ -807,6 +829,14 @@ typedef struct _mlan_callbacks /** Parameter disabled, override MLAN default setting */ #define MLAN_INIT_PARA_DISABLED 2 +/** Control bit for stream 2X2 */ +#define FEATURE_CTRL_STREAM_2X2 MBIT(6) +/** Control bit for DFS support */ +#define FEATURE_CTRL_DFS_SUPPORT MBIT(7) + +/** Default feature control */ +#define FEATURE_CTRL_DEFAULT 0xffffffff + /** mlan_device data structure */ typedef struct _mlan_device { @@ -846,6 +876,8 @@ typedef struct _mlan_device /** 802.11d configuration */ t_u32 cfg_11d; #endif + /** Feature control bitmask */ + t_u32 feature_control; } mlan_device, *pmlan_device; /** MLAN API function prototype */ diff --git a/drivers/net/wireless/sd8797/mlinux/mlan_ieee.h b/drivers/net/wireless/sd8797/mlinux/mlan_ieee.h index 976f1c7013a4..c11c911466e6 100644 --- a/drivers/net/wireless/sd8797/mlinux/mlan_ieee.h +++ b/drivers/net/wireless/sd8797/mlinux/mlan_ieee.h @@ -155,6 +155,15 @@ typedef MLAN_PACK_START struct _IEEEtypes_Generic_t } MLAN_PACK_END IEEEtypes_Generic_t, *pIEEEtypes_Generic_t; +/** TLV header */ +typedef MLAN_PACK_START struct _TLV_Generic_t +{ + /** Type */ + t_u16 type; + /** Length */ + t_u16 len; +} MLAN_PACK_END TLV_Generic_t, *pTLV_Generic_t; + /** Capability information mask */ #define CAPINFO_MASK (~(MBIT(15) | MBIT(14) | \ MBIT(12) | MBIT(11) | MBIT(9))) @@ -305,6 +314,8 @@ typedef t_u16 IEEEtypes_AId_t; /** IEEEtypes_StatusCode_t */ typedef t_u16 IEEEtypes_StatusCode_t; +/** Fixed size in assoc_resp */ +#define ASSOC_RESP_FIXED_SIZE 6 /** IEEEtypes_AssocRsp_t */ typedef MLAN_PACK_START struct _IEEEtypes_AssocRsp_t { @@ -329,6 +340,20 @@ typedef t_u8 WLAN_802_11_RATES[WLAN_SUPPORTED_RATES]; #define RSN_AKM_8021X 1 /** AKM: PSK */ #define RSN_AKM_PSK 2 +/** AKM: PSK SHA256 */ +#define RSN_AKM_PSK_SHA256 6 +#if defined(STA_SUPPORT) +/** Pairwise Cipher Suite length */ +#define PAIRWISE_CIPHER_SUITE_LEN 4 +/** AKM Suite length */ +#define AKM_SUITE_LEN 4 +/** MFPC bit in RSN capability */ +#define MFPC_BIT 7 +/** MFPR bit in RSN capability */ +#define MFPR_BIT 6 +/** PMF ORing mask */ +#define PMF_MASK 0x00c0 +#endif /** wpa_suite_t */ typedef MLAN_PACK_START struct _wpa_suite_t @@ -800,12 +825,147 @@ typedef struct MLAN_PACK_START _BSSCo2040_t t_u8 bss_co_2040_value; } MLAN_PACK_END BSSCo2040_t, *pBSSCo2040_t; +#ifdef BIG_ENDIAN_SUPPORT +/** Extended Capabilities Data */ +typedef struct MLAN_PACK_START _ExtCap_t +{ + /** Extended Capabilities value */ + t_u8 rsvdBit63:1; /* bit 63 */ + t_u8 OperModeNtf:1; /* bit 62 */ + t_u8 TDLSWildBandwidth:1; /* bit 61 */ + t_u8 rsvdBit60:1; /* bit 60 */ + t_u8 rsvdBit59:1; /* bit 59 */ + t_u8 rsvdBit58:1; /* bit 58 */ + t_u8 rsvdBit57:1; /* bit 57 */ + t_u8 rsvdBit56:1; /* bit 56 */ + t_u8 rsvdBit55:1; /* bit 55 */ + t_u8 rsvdBit54:1; /* bit 54 */ + t_u8 rsvdBit53:1; /* bit 53 */ + t_u8 rsvdBit52:1; /* bit 52 */ + t_u8 rsvdBit51:1; /* bit 51 */ + t_u8 rsvdBit50:1; /* bit 50 */ + t_u8 rsvdBit49:1; /* bit 49 */ + t_u8 rsvdBit48:1; /* bit 48 */ + t_u8 rsvdBit47:1; /* bit 47 */ + t_u8 rsvdBit46:1; /* bit 46 */ + t_u8 rsvdBit45:1; /* bit 45 */ + t_u8 rsvdBit44:1; /* bit 44 */ + t_u8 rsvdBit43:1; /* bit 43 */ + t_u8 rsvdBit42:1; /* bit 42 */ + t_u8 rsvdBit41:1; /* bit 41 */ + t_u8 rsvdBit40:1; /* bit 40 */ + t_u8 TDLSChlSwitchProhib:1; /* bit 39 */ + t_u8 TDLSProhibited:1; /* bit 38 */ + t_u8 TDLSSupport:1; /* bit 37 */ + t_u8 MSGCF_Capa:1; /* bit 36 */ + t_u8 Reserved35:1; /* bit 35 */ + t_u8 SSPN_Interface:1; /* bit 34 */ + t_u8 EBR:1; /* bit 33 */ + t_u8 Qos_Map:1; /* bit 32 */ + t_u8 Interworking:1; /* bit 31 */ + t_u8 TDLSChannelSwitching:1; /* bit 30 */ + t_u8 TDLSPeerPSMSupport:1; /* bit 29 */ + t_u8 TDLSPeerUAPSDSupport:1; /* bit 28 */ + t_u8 UTC:1; /* bit 27 */ + t_u8 DMS:1; /* bit 26 */ + t_u8 SSID_List:1; /* bit 25 */ + t_u8 ChannelUsage:1; /* bit 24 */ + t_u8 TimingMeasurement:1; /* bit 23 */ + t_u8 MultipleBSSID:1; /* bit 22 */ + t_u8 AC_StationCount:1; /* bit 21 */ + t_u8 QoSTrafficCap:1; /* bit 20 */ + t_u8 BSS_Transition:1; /* bit 19 */ + t_u8 TIM_Broadcast:1; /* bit 18 */ + t_u8 WNM_Sleep:1; /* bit 17 */ + t_u8 TFS:1; /* bit 16 */ + t_u8 GeospatialLocation:1; /* bit 15 */ + t_u8 CivicLocation:1; /* bit 14 */ + t_u8 CollocatedIntf:1; /* bit 13 */ + t_u8 ProxyARPService:1; /* bit 12 */ + t_u8 FMS:1; /* bit 11 */ + t_u8 LocationTracking:1; /* bit 10 */ + t_u8 MulticastDiagnostics:1; /* bit 9 */ + t_u8 Diagnostics:1; /* bit 8 */ + t_u8 Event:1; /* bit 7 */ + t_u8 SPSMP_Support:1; /* bit 6 */ + t_u8 Reserved5:1; /* bit 5 */ + t_u8 PSMP_Capable:1; /* bit 4 */ + t_u8 RejectUnadmFrame:1; /* bit 3 */ + t_u8 ExtChanSwitching:1; /* bit 2 */ + t_u8 Reserved1:1; /* bit 1 */ + t_u8 BSS_CoexistSupport:1; /* bit 0 */ +} MLAN_PACK_END ExtCap_t, *pExtCap_t; +#else /** Extended Capabilities Data */ typedef struct MLAN_PACK_START _ExtCap_t { /** Extended Capabilities value */ - t_u8 ext_cap_value; + t_u8 BSS_CoexistSupport:1; /* bit 0 */ + t_u8 Reserved1:1; /* bit 1 */ + t_u8 ExtChanSwitching:1; /* bit 2 */ + t_u8 RejectUnadmFrame:1; /* bit 3 */ + t_u8 PSMP_Capable:1; /* bit 4 */ + t_u8 Reserved5:1; /* bit 5 */ + t_u8 SPSMP_Support:1; /* bit 6 */ + t_u8 Event:1; /* bit 7 */ + t_u8 Diagnostics:1; /* bit 8 */ + t_u8 MulticastDiagnostics:1; /* bit 9 */ + t_u8 LocationTracking:1; /* bit 10 */ + t_u8 FMS:1; /* bit 11 */ + t_u8 ProxyARPService:1; /* bit 12 */ + t_u8 CollocatedIntf:1; /* bit 13 */ + t_u8 CivicLocation:1; /* bit 14 */ + t_u8 GeospatialLocation:1; /* bit 15 */ + t_u8 TFS:1; /* bit 16 */ + t_u8 WNM_Sleep:1; /* bit 17 */ + t_u8 TIM_Broadcast:1; /* bit 18 */ + t_u8 BSS_Transition:1; /* bit 19 */ + t_u8 QoSTrafficCap:1; /* bit 20 */ + t_u8 AC_StationCount:1; /* bit 21 */ + t_u8 MultipleBSSID:1; /* bit 22 */ + t_u8 TimingMeasurement:1; /* bit 23 */ + t_u8 ChannelUsage:1; /* bit 24 */ + t_u8 SSID_List:1; /* bit 25 */ + t_u8 DMS:1; /* bit 26 */ + t_u8 UTC:1; /* bit 27 */ + t_u8 TDLSPeerUAPSDSupport:1; /* bit 28 */ + t_u8 TDLSPeerPSMSupport:1; /* bit 29 */ + t_u8 TDLSChannelSwitching:1; /* bit 30 */ + t_u8 Interworking:1; /* bit 31 */ + t_u8 Qos_Map:1; /* bit 32 */ + t_u8 EBR:1; /* bit 33 */ + t_u8 SSPN_Interface:1; /* bit 34 */ + t_u8 Reserved35:1; /* bit 35 */ + t_u8 MSGCF_Capa:1; /* bit 36 */ + t_u8 TDLSSupport:1; /* bit 37 */ + t_u8 TDLSProhibited:1; /* bit 38 */ + t_u8 TDLSChlSwitchProhib:1; /* bit 39 */ + t_u8 rsvdBit40:1; /* bit 40 */ + t_u8 rsvdBit41:1; /* bit 41 */ + t_u8 rsvdBit42:1; /* bit 42 */ + t_u8 rsvdBit43:1; /* bit 43 */ + t_u8 rsvdBit44:1; /* bit 44 */ + t_u8 rsvdBit45:1; /* bit 45 */ + t_u8 rsvdBit46:1; /* bit 46 */ + t_u8 rsvdBit47:1; /* bit 47 */ + t_u8 rsvdBit48:1; /* bit 48 */ + t_u8 rsvdBit49:1; /* bit 49 */ + t_u8 rsvdBit50:1; /* bit 50 */ + t_u8 rsvdBit51:1; /* bit 51 */ + t_u8 rsvdBit52:1; /* bit 52 */ + t_u8 rsvdBit53:1; /* bit 53 */ + t_u8 rsvdBit54:1; /* bit 54 */ + t_u8 rsvdBit55:1; /* bit 55 */ + t_u8 rsvdBit56:1; /* bit 56 */ + t_u8 rsvdBit57:1; /* bit 57 */ + t_u8 rsvdBit58:1; /* bit 58 */ + t_u8 rsvdBit59:1; /* bit 59 */ + t_u8 rsvdBit60:1; /* bit 60 */ + t_u8 TDLSWildBandwidth:1; /* bit 61 */ + t_u8 OperModeNtf:1; /* bit 62 */ + t_u8 rsvdBit63:1; /* bit 63 */ } MLAN_PACK_END ExtCap_t, *pExtCap_t; +#endif /** Overlapping BSS Scan Parameters Data */ typedef struct MLAN_PACK_START _OverlapBSSScanParam_t @@ -1149,7 +1309,7 @@ typedef MLAN_PACK_START struct /** ssid match and RSSI exceeded */ #define BG_SCAN_SSID_RSSI_MATCH 0x0004 /** Maximum number of channels that can be sent in bg scan config */ -#define WLAN_BG_SCAN_CHAN_MAX 32 +#define WLAN_BG_SCAN_CHAN_MAX 38 /** * Input structure to configure bs scan cmd to firmware diff --git a/drivers/net/wireless/sd8797/mlinux/mlan_ioctl.h b/drivers/net/wireless/sd8797/mlinux/mlan_ioctl.h index 7cfc344bf0d4..606d161737f9 100644 --- a/drivers/net/wireless/sd8797/mlinux/mlan_ioctl.h +++ b/drivers/net/wireless/sd8797/mlinux/mlan_ioctl.h @@ -31,196 +31,204 @@ enum _mlan_ioctl_req_id { /* Scan Group */ MLAN_IOCTL_SCAN = 0x00010000, - MLAN_OID_SCAN_NORMAL, - MLAN_OID_SCAN_SPECIFIC_SSID, - MLAN_OID_SCAN_USER_CONFIG, - MLAN_OID_SCAN_CONFIG, - MLAN_OID_SCAN_GET_CURRENT_BSS, - MLAN_OID_SCAN_CANCEL, - MLAN_OID_SCAN_TABLE_FLUSH, - MLAN_OID_SCAN_BGSCAN_CONFIG, + MLAN_OID_SCAN_NORMAL = 0x00010001, + MLAN_OID_SCAN_SPECIFIC_SSID = 0x00010002, + MLAN_OID_SCAN_USER_CONFIG = 0x00010003, + MLAN_OID_SCAN_CONFIG = 0x00010004, + MLAN_OID_SCAN_GET_CURRENT_BSS = 0x00010005, + MLAN_OID_SCAN_CANCEL = 0x00010006, + MLAN_OID_SCAN_TABLE_FLUSH = 0x0001000A, + MLAN_OID_SCAN_BGSCAN_CONFIG = 0x0001000B, /* BSS Configuration Group */ MLAN_IOCTL_BSS = 0x00020000, - MLAN_OID_BSS_START, - MLAN_OID_BSS_STOP, - MLAN_OID_BSS_MODE, - MLAN_OID_BSS_CHANNEL, - MLAN_OID_BSS_CHANNEL_LIST, - MLAN_OID_BSS_MAC_ADDR, - MLAN_OID_BSS_MULTICAST_LIST, - MLAN_OID_BSS_FIND_BSS, - MLAN_OID_IBSS_BCN_INTERVAL, - MLAN_OID_IBSS_ATIM_WINDOW, - MLAN_OID_IBSS_CHANNEL, + MLAN_OID_BSS_START = 0x00020001, + MLAN_OID_BSS_STOP = 0x00020002, + MLAN_OID_BSS_MODE = 0x00020003, + MLAN_OID_BSS_CHANNEL = 0x00020004, + MLAN_OID_BSS_CHANNEL_LIST = 0x00020005, + MLAN_OID_BSS_MAC_ADDR = 0x00020006, + MLAN_OID_BSS_MULTICAST_LIST = 0x00020007, + MLAN_OID_BSS_FIND_BSS = 0x00020008, + MLAN_OID_IBSS_BCN_INTERVAL = 0x00020009, + MLAN_OID_IBSS_ATIM_WINDOW = 0x0002000A, + MLAN_OID_IBSS_CHANNEL = 0x0002000B, #ifdef UAP_SUPPORT - MLAN_OID_UAP_BSS_CONFIG, - MLAN_OID_UAP_DEAUTH_STA, - MLAN_OID_UAP_BSS_RESET, + MLAN_OID_UAP_BSS_CONFIG = 0x0002000C, + MLAN_OID_UAP_DEAUTH_STA = 0x0002000D, + MLAN_OID_UAP_BSS_RESET = 0x0002000E, #endif #if defined(STA_SUPPORT) && defined(UAP_SUPPORT) - MLAN_OID_BSS_ROLE, + MLAN_OID_BSS_ROLE = 0x0002000F, #endif #ifdef WIFI_DIRECT_SUPPORT - MLAN_OID_WIFI_DIRECT_MODE, + MLAN_OID_WIFI_DIRECT_MODE = 0x00020010, #endif #ifdef STA_SUPPORT - MLAN_OID_BSS_LISTEN_INTERVAL, + MLAN_OID_BSS_LISTEN_INTERVAL = 0x00020011, #endif + MLAN_OID_BSS_REMOVE = 0x00020014, /* Radio Configuration Group */ MLAN_IOCTL_RADIO_CFG = 0x00030000, - MLAN_OID_RADIO_CTRL, - MLAN_OID_BAND_CFG, - MLAN_OID_ANT_CFG, + MLAN_OID_RADIO_CTRL = 0x00030001, + MLAN_OID_BAND_CFG = 0x00030002, + MLAN_OID_ANT_CFG = 0x00030003, #ifdef WIFI_DIRECT_SUPPORT - MLAN_OID_REMAIN_CHAN_CFG, + MLAN_OID_REMAIN_CHAN_CFG = 0x00030004, #endif /* SNMP MIB Group */ MLAN_IOCTL_SNMP_MIB = 0x00040000, - MLAN_OID_SNMP_MIB_RTS_THRESHOLD, - MLAN_OID_SNMP_MIB_FRAG_THRESHOLD, - MLAN_OID_SNMP_MIB_RETRY_COUNT, + MLAN_OID_SNMP_MIB_RTS_THRESHOLD = 0x00040001, + MLAN_OID_SNMP_MIB_FRAG_THRESHOLD = 0x00040002, + MLAN_OID_SNMP_MIB_RETRY_COUNT = 0x00040003, #if defined(UAP_SUPPORT) - MLAN_OID_SNMP_MIB_DOT11D, - MLAN_OID_SNMP_MIB_DOT11H, + MLAN_OID_SNMP_MIB_DOT11D = 0x00040004, + MLAN_OID_SNMP_MIB_DOT11H = 0x00040005, #endif - MLAN_OID_SNMP_MIB_DTIM_PERIOD, + MLAN_OID_SNMP_MIB_DTIM_PERIOD = 0x00040006, /* Status Information Group */ MLAN_IOCTL_GET_INFO = 0x00050000, - MLAN_OID_GET_STATS, - MLAN_OID_GET_SIGNAL, - MLAN_OID_GET_FW_INFO, - MLAN_OID_GET_VER_EXT, - MLAN_OID_GET_BSS_INFO, - MLAN_OID_GET_DEBUG_INFO, + MLAN_OID_GET_STATS = 0x00050001, + MLAN_OID_GET_SIGNAL = 0x00050002, + MLAN_OID_GET_FW_INFO = 0x00050003, + MLAN_OID_GET_VER_EXT = 0x00050004, + MLAN_OID_GET_BSS_INFO = 0x00050005, + MLAN_OID_GET_DEBUG_INFO = 0x00050006, #ifdef UAP_SUPPORT - MLAN_OID_UAP_STA_LIST, + MLAN_OID_UAP_STA_LIST = 0x00050007, #endif /* Security Configuration Group */ MLAN_IOCTL_SEC_CFG = 0x00060000, - MLAN_OID_SEC_CFG_AUTH_MODE, - MLAN_OID_SEC_CFG_ENCRYPT_MODE, - MLAN_OID_SEC_CFG_WPA_ENABLED, - MLAN_OID_SEC_CFG_ENCRYPT_KEY, - MLAN_OID_SEC_CFG_PASSPHRASE, - MLAN_OID_SEC_CFG_EWPA_ENABLED, - MLAN_OID_SEC_CFG_ESUPP_MODE, - MLAN_OID_SEC_CFG_WAPI_ENABLED, - MLAN_OID_SEC_CFG_PORT_CTRL_ENABLED, + MLAN_OID_SEC_CFG_AUTH_MODE = 0x00060001, + MLAN_OID_SEC_CFG_ENCRYPT_MODE = 0x00060002, + MLAN_OID_SEC_CFG_WPA_ENABLED = 0x00060003, + MLAN_OID_SEC_CFG_ENCRYPT_KEY = 0x00060004, + MLAN_OID_SEC_CFG_PASSPHRASE = 0x00060005, + MLAN_OID_SEC_CFG_EWPA_ENABLED = 0x00060006, + MLAN_OID_SEC_CFG_ESUPP_MODE = 0x00060007, + MLAN_OID_SEC_CFG_WAPI_ENABLED = 0x00060009, + MLAN_OID_SEC_CFG_PORT_CTRL_ENABLED = 0x0006000A, /* Rate Group */ MLAN_IOCTL_RATE = 0x00070000, - MLAN_OID_RATE_CFG, - MLAN_OID_GET_DATA_RATE, - MLAN_OID_SUPPORTED_RATES, + MLAN_OID_RATE_CFG = 0x00070001, + MLAN_OID_GET_DATA_RATE = 0x00070002, + MLAN_OID_SUPPORTED_RATES = 0x00070003, /* Power Configuration Group */ MLAN_IOCTL_POWER_CFG = 0x00080000, - MLAN_OID_POWER_CFG, - MLAN_OID_POWER_CFG_EXT, + MLAN_OID_POWER_CFG = 0x00080001, + MLAN_OID_POWER_CFG_EXT = 0x00080002, /* Power Management Configuration Group */ MLAN_IOCTL_PM_CFG = 0x00090000, - MLAN_OID_PM_CFG_IEEE_PS, - MLAN_OID_PM_CFG_HS_CFG, - MLAN_OID_PM_CFG_INACTIVITY_TO, - MLAN_OID_PM_CFG_DEEP_SLEEP, - MLAN_OID_PM_CFG_SLEEP_PD, - MLAN_OID_PM_CFG_PS_CFG, - MLAN_OID_PM_CFG_SLEEP_PARAMS, + MLAN_OID_PM_CFG_IEEE_PS = 0x00090001, + MLAN_OID_PM_CFG_HS_CFG = 0x00090002, + MLAN_OID_PM_CFG_INACTIVITY_TO = 0x00090003, + MLAN_OID_PM_CFG_DEEP_SLEEP = 0x00090004, + MLAN_OID_PM_CFG_SLEEP_PD = 0x00090005, + MLAN_OID_PM_CFG_PS_CFG = 0x00090006, + MLAN_OID_PM_CFG_SLEEP_PARAMS = 0x00090008, #ifdef UAP_SUPPORT - MLAN_OID_PM_CFG_PS_MODE, + MLAN_OID_PM_CFG_PS_MODE = 0x00090009, #endif /* UAP_SUPPORT */ - MLAN_OID_PM_INFO, - MLAN_OID_PM_HS_WAKEUP_REASON, + MLAN_OID_PM_INFO = 0x0009000A, + MLAN_OID_PM_HS_WAKEUP_REASON = 0x0009000B, /* WMM Configuration Group */ MLAN_IOCTL_WMM_CFG = 0x000A0000, - MLAN_OID_WMM_CFG_ENABLE, - MLAN_OID_WMM_CFG_QOS, - MLAN_OID_WMM_CFG_ADDTS, - MLAN_OID_WMM_CFG_DELTS, - MLAN_OID_WMM_CFG_QUEUE_CONFIG, - MLAN_OID_WMM_CFG_QUEUE_STATS, - MLAN_OID_WMM_CFG_QUEUE_STATUS, - MLAN_OID_WMM_CFG_TS_STATUS, + MLAN_OID_WMM_CFG_ENABLE = 0x000A0001, + MLAN_OID_WMM_CFG_QOS = 0x000A0002, + MLAN_OID_WMM_CFG_ADDTS = 0x000A0003, + MLAN_OID_WMM_CFG_DELTS = 0x000A0004, + MLAN_OID_WMM_CFG_QUEUE_CONFIG = 0x000A0005, + MLAN_OID_WMM_CFG_QUEUE_STATS = 0x000A0006, + MLAN_OID_WMM_CFG_QUEUE_STATUS = 0x000A0007, + MLAN_OID_WMM_CFG_TS_STATUS = 0x000A0008, /* WPS Configuration Group */ MLAN_IOCTL_WPS_CFG = 0x000B0000, - MLAN_OID_WPS_CFG_SESSION, + MLAN_OID_WPS_CFG_SESSION = 0x000B0001, /* 802.11n Configuration Group */ MLAN_IOCTL_11N_CFG = 0x000C0000, - MLAN_OID_11N_CFG_TX, - MLAN_OID_11N_HTCAP_CFG, - MLAN_OID_11N_CFG_ADDBA_REJECT, - MLAN_OID_11N_CFG_AGGR_PRIO_TBL, - MLAN_OID_11N_CFG_ADDBA_PARAM, - MLAN_OID_11N_CFG_MAX_TX_BUF_SIZE, - MLAN_OID_11N_CFG_AMSDU_AGGR_CTRL, - MLAN_OID_11N_CFG_SUPPORTED_MCS_SET, - MLAN_OID_11N_CFG_TX_BF_CAP, - MLAN_OID_11N_CFG_TX_BF_CFG, - MLAN_OID_11N_CFG_STREAM_CFG, - MLAN_OID_11N_CFG_DELBA, - MLAN_OID_11N_CFG_REJECT_ADDBA_REQ, + MLAN_OID_11N_CFG_TX = 0x000C0001, + MLAN_OID_11N_HTCAP_CFG = 0x000C0002, + MLAN_OID_11N_CFG_ADDBA_REJECT = 0x000C0003, + MLAN_OID_11N_CFG_AGGR_PRIO_TBL = 0x000C0004, + MLAN_OID_11N_CFG_ADDBA_PARAM = 0x000C0005, + MLAN_OID_11N_CFG_MAX_TX_BUF_SIZE = 0x000C0006, + MLAN_OID_11N_CFG_AMSDU_AGGR_CTRL = 0x000C0007, + MLAN_OID_11N_CFG_SUPPORTED_MCS_SET = 0x000C0008, + MLAN_OID_11N_CFG_TX_BF_CAP = 0x000C0009, + MLAN_OID_11N_CFG_TX_BF_CFG = 0x000C000A, + MLAN_OID_11N_CFG_STREAM_CFG = 0x000C000B, + MLAN_OID_11N_CFG_DELBA = 0x000C000C, + MLAN_OID_11N_CFG_REJECT_ADDBA_REQ = 0x000C000D, /* 802.11d Configuration Group */ MLAN_IOCTL_11D_CFG = 0x000D0000, #ifdef STA_SUPPORT - MLAN_OID_11D_CFG_ENABLE, - MLAN_OID_11D_CLR_CHAN_TABLE, + MLAN_OID_11D_CFG_ENABLE = 0x000D0001, + MLAN_OID_11D_CLR_CHAN_TABLE = 0x000D0002, #endif /* STA_SUPPORT */ - MLAN_OID_11D_DOMAIN_INFO, + MLAN_OID_11D_DOMAIN_INFO = 0x000D0003, /* Register Memory Access Group */ MLAN_IOCTL_REG_MEM = 0x000E0000, - MLAN_OID_REG_RW, - MLAN_OID_EEPROM_RD, - MLAN_OID_MEM_RW, + MLAN_OID_REG_RW = 0x000E0001, + MLAN_OID_EEPROM_RD = 0x000E0002, + MLAN_OID_MEM_RW = 0x000E0003, /* Multi-Radio Configuration Group */ MLAN_IOCTL_MFR_CFG = 0x00100000, /* 802.11h Configuration Group */ MLAN_IOCTL_11H_CFG = 0x00110000, - MLAN_OID_11H_CHANNEL_CHECK, - MLAN_OID_11H_LOCAL_POWER_CONSTRAINT, + MLAN_OID_11H_CHANNEL_CHECK = 0x00110001, + MLAN_OID_11H_LOCAL_POWER_CONSTRAINT = 0x00110002, #if defined(DFS_TESTING_SUPPORT) - MLAN_OID_11H_DFS_TESTING, + MLAN_OID_11H_DFS_TESTING = 0x00110003, #endif /* Miscellaneous Configuration Group */ MLAN_IOCTL_MISC_CFG = 0x00200000, - MLAN_OID_MISC_GEN_IE, - MLAN_OID_MISC_REGION, - MLAN_OID_MISC_WARM_RESET, + MLAN_OID_MISC_GEN_IE = 0x00200001, + MLAN_OID_MISC_REGION = 0x00200002, + MLAN_OID_MISC_WARM_RESET = 0x00200003, #if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR) - MLAN_OID_MISC_SDIO_MPA_CTRL, + MLAN_OID_MISC_SDIO_MPA_CTRL = 0x00200006, #endif - MLAN_OID_MISC_HOST_CMD, - MLAN_OID_MISC_SYS_CLOCK, - MLAN_OID_MISC_SOFT_RESET, - MLAN_OID_MISC_WWS, - MLAN_OID_MISC_INIT_SHUTDOWN, - MLAN_OID_MISC_CUSTOM_IE, - MLAN_OID_MISC_TX_DATAPAUSE, - MLAN_OID_MISC_IP_ADDR, - MLAN_OID_MISC_MAC_CONTROL, - MLAN_OID_MISC_MEF_CFG, - MLAN_OID_MISC_CFP_CODE, - MLAN_OID_MISC_COUNTRY_CODE, - MLAN_OID_MISC_THERMAL, - MLAN_OID_MISC_RX_MGMT_IND, - MLAN_OID_MISC_SUBSCRIBE_EVENT, + MLAN_OID_MISC_HOST_CMD = 0x00200007, + MLAN_OID_MISC_SYS_CLOCK = 0x00200009, + MLAN_OID_MISC_SOFT_RESET = 0x0020000A, + MLAN_OID_MISC_WWS = 0x0020000B, + MLAN_OID_MISC_ASSOC_RSP = 0x0020000C, + MLAN_OID_MISC_INIT_SHUTDOWN = 0x0020000D, + MLAN_OID_MISC_CUSTOM_IE = 0x0020000F, + MLAN_OID_MISC_TX_DATAPAUSE = 0x00200012, + MLAN_OID_MISC_IP_ADDR = 0x00200013, + MLAN_OID_MISC_MAC_CONTROL = 0x00200014, + MLAN_OID_MISC_MEF_CFG = 0x00200015, + MLAN_OID_MISC_CFP_CODE = 0x00200016, + MLAN_OID_MISC_COUNTRY_CODE = 0x00200017, + MLAN_OID_MISC_THERMAL = 0x00200018, + MLAN_OID_MISC_RX_MGMT_IND = 0x00200019, + MLAN_OID_MISC_SUBSCRIBE_EVENT = 0x0020001A, #ifdef DEBUG_LEVEL1 - MLAN_OID_MISC_DRVDBG, + MLAN_OID_MISC_DRVDBG = 0x0020001B, +#endif + MLAN_OID_MISC_OTP_USER_DATA = 0x0020001D, + MLAN_OID_MISC_TXCONTROL = 0x00200020, +#ifdef STA_SUPPORT + MLAN_OID_MISC_EXT_CAP_CFG = 0x00200021, +#endif +#if defined(STA_SUPPORT) + MLAN_OID_MISC_PMFCFG = 0x00200022, #endif - MLAN_OID_MISC_OTP_USER_DATA, - MLAN_OID_MISC_TXCONTROL, }; /** Sub command size */ @@ -520,6 +528,8 @@ typedef struct _mlan_ssid_bssid mlan_802_11_mac_addr bssid; /** index in BSSID list, start from 1 */ t_u32 idx; + /** Receive signal strength in dBm */ + t_s32 rssi; } mlan_ssid_bssid; #ifdef UAP_SUPPORT @@ -610,6 +620,8 @@ typedef struct _mlan_ssid_bssid #define KEY_MGMT_PSK 0x02 /** Key_mgmt_eap */ #define KEY_MGMT_EAP 0x01 +/** Key_mgmt_psk_sha256 */ +#define KEY_MGMT_PSK_SHA256 0x100 /** TKIP */ #define CIPHER_TKIP 0x04 @@ -978,6 +990,11 @@ enum _mlan_band_def #define CHANNEL_BW_40MHZ_ABOVE 1 #define CHANNEL_BW_40MHZ_BELOW 3 +/** RF antenna selection */ +#define RF_ANTENNA_MASK(n) ((1<<(n))-1) +/** RF antenna auto select */ +#define RF_ANTENNA_AUTO 0xFFFF + /** Type definition of mlan_ds_band_cfg for MLAN_OID_BAND_CFG */ typedef struct _mlan_ds_band_cfg { @@ -1110,6 +1127,10 @@ typedef struct _mlan_ds_get_stats t_u32 tx_frame; /** WEP ICV error count */ t_u32 wep_icv_error[4]; + /** beacon recv count */ + t_u32 bcn_rcv_cnt; + /** beacon miss count */ + t_u32 bcn_miss_cnt; } mlan_ds_get_stats, *pmlan_ds_get_stats; /** Type definition of mlan_ds_uap_stats for MLAN_OID_GET_STATS */ @@ -1340,7 +1361,7 @@ typedef struct } tx_ba_stream_tbl; /** Debug command number */ -#define DBG_CMD_NUM 5 +#define DBG_CMD_NUM 10 /** mlan_debug_info data structure for MLAN_OID_GET_DEBUG_INFO */ typedef struct _mlan_debug_info @@ -1393,6 +1414,8 @@ typedef struct _mlan_debug_info t_u8 tx_lock_flag; /** Corresponds to port_open member of mlan_private */ t_u8 port_open; + /** bypass pkt count */ + t_u16 bypass_pkt_count; /** Corresponds to scan_processing member of mlan_adapter */ t_u32 scan_processing; /** Number of host to card command failures */ @@ -1443,7 +1466,8 @@ typedef struct _mlan_debug_info t_u16 last_event[DBG_CMD_NUM]; /** Last event index */ t_u16 last_event_index; - + /** Number of no free command node */ + t_u16 num_no_cmd_node; /** Corresponds to data_sent member of mlan_adapter */ t_u8 data_sent; /** Corresponds to cmd_sent member of mlan_adapter */ @@ -1716,7 +1740,8 @@ typedef struct _mlan_ds_sec_cfg enum _mlan_rate_type { MLAN_RATE_INDEX, - MLAN_RATE_VALUE + MLAN_RATE_VALUE, + MLAN_RATE_BITMAP }; /** Enumeration for rate format */ @@ -1734,7 +1759,7 @@ typedef struct _mlan_rate_cfg_t { /** Fixed rate: 0, auto rate: 1 */ t_u32 is_rate_auto; - /** Rate type. 0: index; 1: valude */ + /** Rate type. 0: index; 1: value; 2: bitmap */ t_u32 rate_type; /** Rate/MCS index or rate value if fixed rate */ t_u32 rate; @@ -1858,6 +1883,8 @@ typedef struct _mlan_ds_power_cfg #define HOST_SLEEP_COND_MAC_EVENT MBIT(2) /** Host sleep config condition: multicast data */ #define HOST_SLEEP_COND_MULTICAST_DATA MBIT(3) +/** Host sleep config condition: IPV6 packet */ +#define HOST_SLEEP_COND_IPV6_PACKET MBIT(31) /** Host sleep config conditions: Default */ #define HOST_SLEEP_DEF_COND (HOST_SLEEP_COND_BROADCAST_DATA | HOST_SLEEP_COND_UNICAST_DATA | HOST_SLEEP_COND_MAC_EVENT) @@ -1865,6 +1892,8 @@ typedef struct _mlan_ds_power_cfg #define HOST_SLEEP_DEF_GPIO 0xff /** Host sleep config gap : Default */ #define HOST_SLEEP_DEF_GAP 200 +/** Host sleep config min wake holdoff */ +#define HOST_SLEEP_DEF_WAKE_HOLDOFF 0; /** Type definition of mlan_ds_hs_cfg for MLAN_OID_PM_CFG_HS_CFG */ typedef struct _mlan_ds_hs_cfg @@ -2807,6 +2836,18 @@ typedef struct _mlan_ds_misc_sys_clock t_u16 sys_clk[MLAN_MAX_CLK_NUM]; } mlan_ds_misc_sys_clock; +/** Maximum response buffer length */ +#define ASSOC_RSP_BUF_SIZE 500 + +/** Type definition of mlan_ds_misc_assoc_rsp for MLAN_OID_MISC_ASSOC_RSP */ +typedef struct _mlan_ds_misc_assoc_rsp +{ + /** Associate response buffer */ + t_u8 assoc_resp_buf[ASSOC_RSP_BUF_SIZE]; + /** Response buffer length */ + t_u32 assoc_resp_len; +} mlan_ds_misc_assoc_rsp; + /** Enumeration for function init/shutdown */ enum _mlan_func_cmd { @@ -2827,6 +2868,8 @@ typedef struct _mlan_ds_misc_tx_datapause #define IPADDR_LEN (16) /** Max number of ip */ #define MAX_IPADDR (4) +/** IP address type - NONE*/ +#define IPADDR_TYPE_NONE (0) /** IP address type - IPv4*/ #define IPADDR_TYPE_IPV4 (1) /** IP operation remove */ @@ -2887,6 +2930,10 @@ typedef struct _mlan_ds_misc_country_code t_u8 country_code[COUNTRY_CODE_LEN]; } mlan_ds_misc_country_code; +/** action for set */ +#define SUBSCRIBE_EVT_ACT_BITWISE_SET 0x0002 +/** action for clear */ +#define SUBSCRIBE_EVT_ACT_BITWISE_CLR 0x0003 /** BITMAP for subscribe event rssi low */ #define SUBSCRIBE_EVT_RSSI_LOW MBIT(0) /** BITMAP for subscribe event snr low */ @@ -2917,6 +2964,8 @@ typedef struct _mlan_ds_misc_country_code /** Type definition of mlan_ds_subscribe_evt for MLAN_OID_MISC_CFP_CODE */ typedef struct _mlan_ds_subscribe_evt { + /** evt action */ + t_u16 evt_action; /** bitmap for subscribe event */ t_u16 evt_bitmap; /** Absolute value of RSSI threshold value (dBm) */ @@ -2989,6 +3038,16 @@ typedef struct _mlan_ds_misc_otp_user_data t_u8 user_data[MAX_OTP_USER_DATA_LEN]; } mlan_ds_misc_otp_user_data; +#if defined(STA_SUPPORT) +typedef struct _mlan_ds_misc_pmfcfg +{ + /** Management Frame Protection Capable */ + t_u8 mfpc; + /** Management Frame Protection Required */ + t_u8 mfpr; +} mlan_ds_misc_pmfcfg; +#endif + /** Type definition of mlan_ds_misc_cfg for MLAN_IOCTL_MISC_CFG */ typedef struct _mlan_ds_misc_cfg { @@ -3011,6 +3070,8 @@ typedef struct _mlan_ds_misc_cfg mlan_ds_misc_sys_clock sys_clock; /** WWS set/get for MLAN_OID_MISC_WWS */ t_u32 wws_cfg; + /** Get associate response for MLAN_OID_MISC_ASSOC_RSP */ + mlan_ds_misc_assoc_rsp assoc_resp; /** Function init/shutdown for MLAN_OID_MISC_INIT_SHUTDOWN */ t_u32 func_init_shutdown; /** Custom IE for MLAN_OID_MISC_CUSTOM_IE */ @@ -3037,9 +3098,15 @@ typedef struct _mlan_ds_misc_cfg /** Driver debug bit masks */ t_u32 drvdbg; #endif +#ifdef STA_SUPPORT + t_u8 ext_cap[8]; +#endif mlan_ds_misc_otp_user_data otp_user_data; /** Tx control */ t_u32 tx_control; +#if defined(STA_SUPPORT) + mlan_ds_misc_pmfcfg pmfcfg; +#endif } param; } mlan_ds_misc_cfg, *pmlan_ds_misc_cfg; diff --git a/drivers/net/wireless/sd8797/mlinux/moal_cfg80211.c b/drivers/net/wireless/sd8797/mlinux/moal_cfg80211.c index b3896efc5567..229e47f04ae5 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_cfg80211.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_cfg80211.c @@ -137,7 +137,7 @@ const u32 cfg80211_cipher_suites[] = { WLAN_CIPHER_SUITE_AES_CMAC, }; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) #ifdef UAP_SUPPORT /** Network device handlers for uAP */ extern const struct net_device_ops woal_uap_netdev_ops; @@ -171,7 +171,7 @@ woal_get_wiphy_priv(struct wiphy *wiphy) /** * @brief Get the private structure from net device * - * @param wiphy A pointer to net_device structure + * @param dev A pointer to net_device structure * * @return Pointer to moal_private */ @@ -182,6 +182,105 @@ woal_get_netdev_priv(struct net_device *dev) } /** + * @brief Check if any interface is active + * + * @param handle A pointer to moal_handle + * + * + * @return MTRUE/MFALSE; + */ +t_u8 +woal_is_any_interface_active(moal_handle * handle) +{ + int i; + for (i = 0; i < handle->priv_num; i++) { +#ifdef STA_SUPPORT + if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA) { + if (handle->priv[i]->media_connected == MTRUE) + return MTRUE; + } +#endif +#ifdef UAP_SUPPORT + if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_UAP) { + if (handle->priv[i]->bss_started == MTRUE) + return MTRUE; + } +#endif + } + return MFALSE; +} + +/** + * @brief Get current frequency of active interface + * + * @param handle A pointer to moal_handle + * + * @return channel frequency + */ +int +woal_get_active_intf_freq(moal_handle * handle) +{ + int i; + for (i = 0; i < handle->priv_num; i++) { +#ifdef STA_SUPPORT + if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA) { + if (handle->priv[i]->media_connected == MTRUE) + return ieee80211_channel_to_frequency(handle->priv[i]->channel, + (handle->priv[i]-> + channel <= + 14 ? IEEE80211_BAND_2GHZ + : IEEE80211_BAND_5GHZ)); + } +#endif +#ifdef UAP_SUPPORT + if (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_UAP) { + if (handle->priv[i]->bss_started == MTRUE) + return ieee80211_channel_to_frequency(handle->priv[i]->channel, + (handle->priv[i]-> + channel <= + 14 ? IEEE80211_BAND_2GHZ + : IEEE80211_BAND_5GHZ)); + } +#endif + } + return 0; +} + +/** + * @brief Convert driver band configuration to IEEE band type + * + * @param band Driver band configuration + * + * @return IEEE band type + */ +t_u8 +woal_band_cfg_to_ieee_band(t_u32 band) +{ + t_u8 ret_radio_type; + + ENTER(); + + switch (band) { + case BAND_A: + case BAND_AN: + case BAND_A | BAND_AN: + ret_radio_type = IEEE80211_BAND_5GHZ; + break; + case BAND_B: + case BAND_G: + case BAND_B | BAND_G: + case BAND_GN: + case BAND_B | BAND_GN: + default: + ret_radio_type = IEEE80211_BAND_2GHZ; + break; + } + + LEAVE(); + return ret_radio_type; +} + +/** * @brief Set/Enable encryption key * * @param priv A pointer to moal_private structure @@ -269,25 +368,22 @@ woal_cfg80211_set_key(moal_private * priv, t_u8 is_enable_wep, seq_len); } } - if (cipher != WLAN_CIPHER_SUITE_WEP40 && - cipher != WLAN_CIPHER_SUITE_WEP104) { - if (addr) { - memcpy(sec->param.encrypt_key.mac_addr, addr, ETH_ALEN); - if (0 == - memcmp(sec->param.encrypt_key.mac_addr, bcast_addr, - ETH_ALEN)) - sec->param.encrypt_key.key_flags = KEY_FLAG_GROUP_KEY; - else - sec->param.encrypt_key.key_flags = KEY_FLAG_SET_TX_KEY; - } else { - memcpy(sec->param.encrypt_key.mac_addr, bcast_addr, ETH_ALEN); + if (addr) { + memcpy(sec->param.encrypt_key.mac_addr, addr, ETH_ALEN); + if (0 == + memcmp(sec->param.encrypt_key.mac_addr, bcast_addr, ETH_ALEN)) sec->param.encrypt_key.key_flags = KEY_FLAG_GROUP_KEY; - } - if (seq && seq_len) { - memcpy(sec->param.encrypt_key.pn, seq, seq_len); - sec->param.encrypt_key.key_flags |= KEY_FLAG_RX_SEQ_VALID; - } + else + sec->param.encrypt_key.key_flags = KEY_FLAG_SET_TX_KEY; + } else { + memcpy(sec->param.encrypt_key.mac_addr, bcast_addr, ETH_ALEN); + sec->param.encrypt_key.key_flags = KEY_FLAG_GROUP_KEY; } + if (seq && seq_len) { + memcpy(sec->param.encrypt_key.pn, seq, seq_len); + sec->param.encrypt_key.key_flags |= KEY_FLAG_RX_SEQ_VALID; + } + if (cipher == WLAN_CIPHER_SUITE_AES_CMAC) { sec->param.encrypt_key.key_flags |= KEY_FLAG_AES_MCAST_IGTK; } @@ -354,8 +450,41 @@ woal_cfg80211_set_wep_keys(moal_private * priv, const t_u8 * key, int key_len, return ret; } -#if defined(WIFI_DIRECT_SUPPORT) -#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION +/** + * @brief clear all mgmt ies + * + * @param priv A pointer to moal private structure + * @return N/A + */ +void +woal_clear_all_mgmt_ies(moal_private * priv) +{ + t_u16 mask = 0; + /* clear BEACON WPS/P2P IE */ + if (priv->beacon_wps_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK) { + PRINTM(MCMND, "Clear BEACON WPS ie\n"); + woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL, 0, NULL, 0, NULL, 0, + MGMT_MASK_BEACON_WPS_P2P); + } + /* clear mgmt frame ies */ + if (priv->probereq_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK) + mask |= MGMT_MASK_PROBE_REQ; + if (priv->beacon_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK) + mask |= MGMT_MASK_BEACON; + if (priv->proberesp_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK) + mask |= MGMT_MASK_PROBE_RESP; + if (priv->assocresp_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK) + mask |= MGMT_MASK_ASSOC_RESP; + if (mask) { + PRINTM(MCMND, "Clear IES: 0x%x 0x%x 0x%x 0x%x\n", priv->beacon_index, + priv->probereq_index, priv->proberesp_index, + priv->assocresp_index); + woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL, 0, NULL, 0, NULL, 0, + mask); + } +} + +#if defined(STA_SUPPORT) && defined(UAP_SUPPORT) /** * @brief set bss role * @@ -365,7 +494,7 @@ woal_cfg80211_set_wep_keys(moal_private * priv, const t_u8 * key, int key_len, * * @return 0 -- success, otherwise fail */ -static int +int woal_cfg80211_bss_role_cfg(moal_private * priv, t_u16 action, t_u8 * bss_role) { int ret = 0; @@ -384,6 +513,10 @@ woal_cfg80211_bss_role_cfg(moal_private * priv, t_u16 action, t_u8 * bss_role) } if (action == MLAN_ACT_SET) { + /* set back the mac address */ + woal_request_set_mac_address(priv); + /* clear the mgmt ies */ + woal_clear_all_mgmt_ies(priv); /* Initialize private structures */ woal_init_priv(priv, MOAL_IOCTL_WAIT); @@ -396,6 +529,10 @@ woal_cfg80211_bss_role_cfg(moal_private * priv, t_u16 action, t_u8 * bss_role) LEAVE(); return ret; } +#endif + +#if defined(WIFI_DIRECT_SUPPORT) +#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION /** * @brief initialize p2p client for wpa_supplicant @@ -544,6 +681,7 @@ woal_cfg80211_deinit_p2p(moal_private * priv) t_u16 wifi_direct_mode; t_u8 bss_role; t_u8 channel_status; + moal_private *remain_priv = NULL; ENTER(); @@ -556,18 +694,33 @@ woal_cfg80211_deinit_p2p(moal_private * priv) /* cancel previous remain on channel */ if (priv->phandle->remain_on_channel) { + remain_priv = priv->phandle->priv[priv->phandle->remain_bss_index]; + if (!remain_priv) { + PRINTM(MERROR, "deinit_p2p: wrong remain_bss_index=%d\n", + priv->phandle->remain_bss_index); + ret = -EFAULT; + goto done; + } if (woal_cfg80211_remain_on_channel_cfg - (priv, MOAL_IOCTL_WAIT, MTRUE, &channel_status, NULL, 0, 0)) { - PRINTM(MERROR, "Fail to cancel remain on channel\n"); + (remain_priv, MOAL_IOCTL_WAIT, MTRUE, &channel_status, NULL, 0, + 0)) { + PRINTM(MERROR, "deinit_p2p: Fail to cancel remain on channel\n"); ret = -EFAULT; goto done; } if (priv->phandle->cookie) { - cfg80211_remain_on_channel_expired(priv->netdev, - priv->phandle->cookie, - &priv->phandle->chan, - priv->phandle->channel_type, - GFP_ATOMIC); + cfg80211_remain_on_channel_expired( +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) + remain_priv->netdev, +#else + remain_priv->wdev, +#endif + priv->phandle->cookie, + &priv->phandle->chan, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) + priv->phandle->channel_type, +#endif + GFP_ATOMIC); priv->phandle->cookie = 0; } priv->phandle->remain_on_channel = MFALSE; @@ -625,7 +778,9 @@ woal_cfg80211_change_virtual_intf(struct wiphy *wiphy, moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); mlan_ds_bss *bss = NULL; mlan_ioctl_req *req = NULL; +#if defined(STA_SUPPORT) && defined(UAP_SUPPORT) t_u8 bss_role; +#endif ENTER(); @@ -633,24 +788,41 @@ woal_cfg80211_change_virtual_intf(struct wiphy *wiphy, PRINTM(MINFO, "Already set to required type\n"); goto done; } - PRINTM(MIOCTL, "change virturl intf=%d\n", type); + PRINTM(MIOCTL, "%s: change virturl intf=%d\n", dev->name, type); #if defined(WIFI_DIRECT_SUPPORT) #if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION /** cancel previous remain on channel to avoid firmware hang */ if (priv->phandle->remain_on_channel) { t_u8 channel_status; + moal_private *remain_priv = NULL; + remain_priv = priv->phandle->priv[priv->phandle->remain_bss_index]; + if (!remain_priv) { + PRINTM(MERROR, "change_virtual_intf:wrong remain_bss_index=%d\n", + priv->phandle->remain_bss_index); + ret = -EFAULT; + goto done; + } if (woal_cfg80211_remain_on_channel_cfg - (priv, MOAL_IOCTL_WAIT, MTRUE, &channel_status, NULL, 0, 0)) { - PRINTM(MERROR, "Fail to cancel remain on channel\n"); + (remain_priv, MOAL_IOCTL_WAIT, MTRUE, &channel_status, NULL, 0, + 0)) { + PRINTM(MERROR, + "change_virtual_intf: Fail to cancel remain on channel\n"); ret = -EFAULT; goto done; } if (priv->phandle->cookie) { - cfg80211_remain_on_channel_expired(priv->netdev, - priv->phandle->cookie, - &priv->phandle->chan, - priv->phandle->channel_type, - GFP_ATOMIC); + cfg80211_remain_on_channel_expired( +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) + remain_priv->netdev, +#else + remain_priv->wdev, +#endif + priv->phandle->cookie, + &priv->phandle->chan, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) + priv->phandle->channel_type, +#endif + GFP_ATOMIC); priv->phandle->cookie = 0; } priv->phandle->remain_on_channel = MFALSE; @@ -699,11 +871,14 @@ woal_cfg80211_change_virtual_intf(struct wiphy *wiphy, } #endif /* KERNEL_VERSION */ #endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */ +#if defined(STA_SUPPORT) && defined(UAP_SUPPORT) if (priv->bss_type == MLAN_BSS_TYPE_UAP) { + woal_cfg80211_del_beacon(wiphy, dev); bss_role = MLAN_BSS_ROLE_STA; woal_cfg80211_bss_role_cfg(priv, MLAN_ACT_SET, &bss_role); PRINTM(MIOCTL, "set bss role for STA\n"); } +#endif bss->param.bss_mode = MLAN_BSS_MODE_INFRA; priv->wdev->iftype = NL80211_IFTYPE_STATION; PRINTM(MINFO, "Setting interface type to managed\n"); @@ -744,11 +919,16 @@ woal_cfg80211_change_virtual_intf(struct wiphy *wiphy, priv->wdev->iftype = NL80211_IFTYPE_P2P_GO; #endif #endif +#if defined(STA_SUPPORT) && defined(UAP_SUPPORT) if (priv->bss_type == MLAN_BSS_TYPE_STA) { + if (priv->probereq_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK) + woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL, 0, NULL, 0, + NULL, 0, MGMT_MASK_PROBE_REQ); bss_role = MLAN_BSS_ROLE_UAP; woal_cfg80211_bss_role_cfg(priv, MLAN_ACT_SET, &bss_role); PRINTM(MIOCTL, "set bss role for AP\n"); } +#endif if (type == NL80211_IFTYPE_AP) priv->wdev->iftype = NL80211_IFTYPE_AP; PRINTM(MINFO, "Setting interface type to P2P GO\n"); @@ -794,7 +974,8 @@ woal_cfg80211_change_virtual_intf(struct wiphy *wiphy, int woal_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) { - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = NULL; + moal_handle *handle = (moal_handle *) woal_get_wiphy_priv(wiphy); #ifdef UAP_CFG80211 #ifdef UAP_SUPPORT mlan_uap_bss_param sys_cfg; @@ -806,6 +987,7 @@ woal_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) ENTER(); + priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY); if (rts_thr == MLAN_FRAG_RTS_DISABLED) rts_thr = MLAN_RTS_MAX_VALUE; if (frag_thr == MLAN_FRAG_RTS_DISABLED) @@ -861,6 +1043,7 @@ woal_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) return -EFAULT; } +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36) || defined(COMPAT_WIRELESS) /** * @brief Request the driver to add a key * @@ -873,6 +1056,19 @@ woal_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) * * @return 0 -- success, otherwise fail */ +#else +/** + * @brief Request the driver to add a key + * + * @param wiphy A pointer to wiphy structure + * @param netdev A pointer to net_device structure + * @param key_index Key index + * @param mac_addr MAC address (NULL for group key) + * @param params A pointer to key_params structure + * + * @return 0 -- success, otherwise fail + */ +#endif int woal_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, t_u8 key_index, @@ -899,6 +1095,7 @@ woal_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, return 0; } +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36) || defined(COMPAT_WIRELESS) /** * @brief Request the driver to delete a key * @@ -910,6 +1107,18 @@ woal_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, * * @return 0 -- success, otherwise fail */ +#else +/** + * @brief Request the driver to delete a key + * + * @param wiphy A pointer to wiphy structure + * @param netdev A pointer to net_device structure + * @param key_index Key index + * @param mac_addr MAC address (NULL for group key) + * + * @return 0 -- success, otherwise fail + */ +#endif int woal_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, t_u8 key_index, @@ -934,6 +1143,7 @@ woal_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, return 0; } +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,37) || defined(COMPAT_WIRELESS) /** * @brief Request to enable WEP key to driver * @@ -945,6 +1155,17 @@ woal_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, * * @return 0 -- success, otherwise fail */ +#else +/** + * @brief Request to enable WEP key to driver + * + * @param wiphy A pointer to wiphy structure + * @param netdev A pointer to net_device structure + * @param key_index Key index + * + * @return 0 -- success, otherwise fail + */ +#endif int woal_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev, t_u8 key_index @@ -960,7 +1181,7 @@ woal_cfg80211_set_default_key(struct wiphy *wiphy, ENTER(); woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info); - if (bss_info.wep_status) { + if (!bss_info.wep_status) { LEAVE(); return ret; } @@ -974,6 +1195,19 @@ woal_cfg80211_set_default_key(struct wiphy *wiphy, return ret; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) || defined(COMPAT_WIRELESS) +/** + * @brief Request the driver to change the channel + * + * @param wiphy A pointer to wiphy structure + * @param dev A pointer to net_device structure + * @param chan A pointer to ieee80211_channel structure + * @param channel_type Channel type of nl80211_channel_type + * + * @return 0 -- success, otherwise fail + */ +#else /** * @brief Request the driver to change the channel * @@ -983,6 +1217,7 @@ woal_cfg80211_set_default_key(struct wiphy *wiphy, * * @return 0 -- success, otherwise fail */ +#endif int woal_cfg80211_set_channel(struct wiphy *wiphy, #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) || defined(COMPAT_WIRELESS) @@ -995,30 +1230,179 @@ woal_cfg80211_set_channel(struct wiphy *wiphy, moal_private *priv = NULL; ENTER(); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) || defined(COMPAT_WIRELESS) if (dev) priv = woal_get_netdev_priv(dev); - else #endif - priv = (moal_private *) woal_get_wiphy_priv(wiphy); +#endif + if (!priv) { + moal_handle *handle = (moal_handle *) woal_get_wiphy_priv(wiphy); + if (handle) + priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY); + } + if (priv) { #ifdef STA_CFG80211 #ifdef STA_SUPPORT - if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) { - if (priv->media_connected == MTRUE) { - PRINTM(MERROR, "This configuration is valid only when station " - "is not connected\n"); - LEAVE(); - return -EINVAL; + if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) { + if (priv->media_connected == MTRUE) { + PRINTM(MERROR, "This configuration is valid only when station " + "is not connected\n"); + LEAVE(); + return -EINVAL; + } + ret = woal_set_rf_channel(priv, chan, channel_type); } - ret = woal_set_rf_channel(priv, chan, channel_type); +#endif +#endif + priv->channel = ieee80211_frequency_to_channel(chan->center_freq); } + // set monitor channel support + + LEAVE(); + return ret; +} #endif + +/** + * @brief Request the driver to set the bitrate + * + * @param wiphy A pointer to wiphy structure + * @param dev A pointer to net_device structure + * @param peer A pointer to peer address + * @param mask A pointer to cfg80211_bitrate_mask structure + * + * @return 0 -- success, otherwise fail + */ +int +woal_cfg80211_set_bitrate_mask(struct wiphy *wiphy, + struct net_device *dev, + const u8 * peer, + const struct cfg80211_bitrate_mask *mask) +{ + int ret = 0; + mlan_status status = MLAN_STATUS_SUCCESS; + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); + mlan_bss_info bss_info; + enum ieee80211_band band; + mlan_ioctl_req *req = NULL; + mlan_ds_rate *rate = NULL; + mlan_rate_cfg_t *rate_cfg = NULL; + + ENTER(); + + if (priv->media_connected == MFALSE) { + PRINTM(MERROR, "Can not set data rate in disconnected state\n"); + ret = -EINVAL; + goto done; + } + + status = woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info); + if (status) + goto done; + band = woal_band_cfg_to_ieee_band(bss_info.bss_band); + + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + rate = (mlan_ds_rate *) req->pbuf; + rate_cfg = &rate->param.rate_cfg; + rate->sub_command = MLAN_OID_RATE_CFG; + req->req_id = MLAN_IOCTL_RATE; + req->action = MLAN_ACT_SET; + rate_cfg->rate_type = MLAN_RATE_BITMAP; + + /* Fill HR/DSSS rates. */ + if (band == IEEE80211_BAND_2GHZ) + rate_cfg->bitmap_rates[0] = mask->control[band].legacy & 0x000f; + + /* Fill OFDM rates */ + if (band == IEEE80211_BAND_2GHZ) + rate_cfg->bitmap_rates[1] = (mask->control[band].legacy & 0x0ff0) >> 4; + else + rate_cfg->bitmap_rates[1] = mask->control[band].legacy; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) + /* Fill MCS rates */ + rate_cfg->bitmap_rates[2] = mask->control[band].mcs[0]; + if (priv->phandle->card_type == CARD_TYPE_SD8797) + rate_cfg->bitmap_rates[2] |= mask->control[band].mcs[1] << 8; #endif - priv->channel = ieee80211_frequency_to_channel(chan->center_freq); + + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; + } + + done: LEAVE(); return ret; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) || defined(COMPAT_WIRELESS) +/** + * @brief Request the driver to set antenna configuration + * + * @param wiphy A pointer to wiphy structure + * @param tx_ant Bitmaps of allowed antennas to use for TX + * @param rx_ant Bitmaps of allowed antennas to use for RX + * + * @return 0 -- success, otherwise fail + */ +int +woal_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant) +{ + moal_handle *handle = (moal_handle *) woal_get_wiphy_priv(wiphy); + moal_private *priv = NULL; + mlan_ds_radio_cfg *radio = NULL; + mlan_ioctl_req *req = NULL; + int ret = 0; + + ENTER(); + + if (!handle) { + PRINTM(MFATAL, "Unable to get handle\n"); + ret = -EINVAL; + goto done; + } + priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY); + if (!priv) { + ret = -EINVAL; + goto done; + } + + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + radio = (mlan_ds_radio_cfg *) req->pbuf; + radio->sub_command = MLAN_OID_ANT_CFG; + req->req_id = MLAN_IOCTL_RADIO_CFG; + req->action = MLAN_ACT_SET; + radio->param.ant_cfg.tx_antenna = tx_ant; + radio->param.ant_cfg.rx_antenna = rx_ant; + + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; + } + + done: + if (req) + kfree(req); + /* Driver must return -EINVAL to cfg80211 */ + if (ret) + ret = -EINVAL; + LEAVE(); + return ret; +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) /** * @brief register/unregister mgmt frame forwarding * @@ -1033,11 +1417,30 @@ void woal_cfg80211_mgmt_frame_register(struct wiphy *wiphy, struct net_device *dev, u16 frame_type, bool reg) +#else +/** + * @brief register/unregister mgmt frame forwarding + * + * @param wiphy A pointer to wiphy structure + * @param wdev A pointer to wireless_dev structure + * @param frame_type Bit mask for mgmt frame type + * @param reg Register or unregister + * + * @return 0 -- success, otherwise fail + */ +void +woal_cfg80211_mgmt_frame_register(struct wiphy *wiphy, + struct wireless_dev *wdev, u16 frame_type, + bool reg) +#endif { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct net_device *dev = wdev->netdev; +#endif moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); mlan_status status = MLAN_STATUS_SUCCESS; t_u32 mgmt_subtype_mask = 0x0; - static t_u32 last_mgmt_subtype_mask = 0x0; + t_u32 last_mgmt_subtype_mask = priv->mgmt_subtype_mask; ENTER(); #ifdef UAP_SUPPORT @@ -1055,8 +1458,8 @@ woal_cfg80211_mgmt_frame_register(struct wiphy *wiphy, /* clear mgmt_subtype_mask */ mgmt_subtype_mask = last_mgmt_subtype_mask & ~BIT(frame_type >> 4); } - PRINTM(MIOCTL, "mgmt_subtype_mask=0x%x last_mgmt_subtype_mask=0x%x\n", - mgmt_subtype_mask, last_mgmt_subtype_mask); + PRINTM(MIOCTL, "%s: mgmt_subtype_mask=0x%x last_mgmt_subtype_mask=0x%x\n", + dev->name, mgmt_subtype_mask, last_mgmt_subtype_mask); if (mgmt_subtype_mask != last_mgmt_subtype_mask) { last_mgmt_subtype_mask = mgmt_subtype_mask; @@ -1065,11 +1468,53 @@ woal_cfg80211_mgmt_frame_register(struct wiphy *wiphy, itself. */ status = woal_reg_rx_mgmt_ind(priv, MLAN_ACT_SET, &mgmt_subtype_mask, MOAL_NO_WAIT); + priv->mgmt_subtype_mask = last_mgmt_subtype_mask; } LEAVE(); } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) || defined(COMPAT_WIRELESS) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) +/** + * @brief tx mgmt frame + * + * @param wiphy A pointer to wiphy structure + * @param wdev A pointer to wireless_dev structure + * @param chan A pointer to ieee80211_channel structure + * @param offchan Off channel or not + * @param wait Duration to wait + * @param buf Frame buffer + * @param len Frame length + * @param no_cck No CCK check + * @param dont_wait_for_ack Do not wait for ACK + * @param cookie A pointer to frame cookie + * + * @return 0 -- success, otherwise fail + */ +#else +/** + * @brief tx mgmt frame + * + * @param wiphy A pointer to wiphy structure + * @param wdev A pointer to wireless_dev structure + * @param chan A pointer to ieee80211_channel structure + * @param offchan Off channel or not + * @param channel_type Channel type + * @param channel_type_valid Is channel type valid or not + * @param wait Duration to wait + * @param buf Frame buffer + * @param len Frame length + * @param no_cck No CCK check + * @param dont_wait_for_ack Do not wait for ACK + * @param cookie A pointer to frame cookie + * + * @return 0 -- success, otherwise fail + */ +#endif +#else /** * @brief tx mgmt frame * @@ -1079,19 +1524,66 @@ woal_cfg80211_mgmt_frame_register(struct wiphy *wiphy, * @param offchan Off channel or not * @param channel_type Channel type * @param channel_type_valid Is channel type valid or not + * @param wait Duration to wait * @param buf Frame buffer * @param len Frame length + * @param no_cck No CCK check + * @param dont_wait_for_ack Do not wait for ACK * @param cookie A pointer to frame cookie * * @return 0 -- success, otherwise fail */ +#endif +#else +/** + * @brief tx mgmt frame + * + * @param wiphy A pointer to wiphy structure + * @param dev A pointer to net_device structure + * @param chan A pointer to ieee80211_channel structure + * @param offchan Off channel or not + * @param channel_type Channel type + * @param channel_type_valid Is channel type valid or not + * @param wait Duration to wait + * @param buf Frame buffer + * @param len Frame length + * @param no_cck No CCK check + * @param cookie A pointer to frame cookie + * + * @return 0 -- success, otherwise fail + */ +#endif +#else +/** + * @brief tx mgmt frame + * + * @param wiphy A pointer to wiphy structure + * @param dev A pointer to net_device structure + * @param chan A pointer to ieee80211_channel structure + * @param offchan Off channel or not + * @param channel_type Channel type + * @param channel_type_valid Is channel type valid or not + * @param wait Duration to wait + * @param buf Frame buffer + * @param len Frame length + * @param cookie A pointer to frame cookie + * + * @return 0 -- success, otherwise fail + */ +#endif int woal_cfg80211_mgmt_tx(struct wiphy *wiphy, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) struct net_device *dev, +#else + struct wireless_dev *wdev, +#endif struct ieee80211_channel *chan, bool offchan, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) enum nl80211_channel_type channel_type, - bool channel_type_valid, unsigned int wait, - const u8 * buf, size_t len, + bool channel_type_valid, +#endif + unsigned int wait, const u8 * buf, size_t len, #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) || defined(COMPAT_WIRELESS) bool no_cck, #endif @@ -1100,6 +1592,9 @@ woal_cfg80211_mgmt_tx(struct wiphy *wiphy, #endif u64 * cookie) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct net_device *dev = wdev->netdev; +#endif moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); int ret = 0; pmlan_buffer pmbuf = NULL; @@ -1113,6 +1608,7 @@ woal_cfg80211_mgmt_tx(struct wiphy *wiphy, #if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION t_u8 channel_status; t_u32 duration; + moal_private *remain_priv = NULL; #endif #endif @@ -1130,7 +1626,8 @@ woal_cfg80211_mgmt_tx(struct wiphy *wiphy, PD/GO negotiation, so we should call remain_on_channel_cfg in order to receive action frame from peer device */ framectrl = ((const struct ieee80211_mgmt *) buf)->frame_control; - PRINTM(MIOCTL, "Mgmt: framectrl=0x%x\n", framectrl); + PRINTM(MIOCTL, "Mgmt TX %s => framectrl = 0x%x freq = %d\n", dev->name, + framectrl, chan->center_freq); if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) && (framectrl == IEEE80211_STYPE_PROBE_RESP)) { PRINTM(MIOCTL, "Skip send probe_resp in GO/UAP mode\n"); @@ -1140,21 +1637,41 @@ woal_cfg80211_mgmt_tx(struct wiphy *wiphy, #if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION if ((priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) && (framectrl == IEEE80211_STYPE_ACTION)) { -#define MGMT_TX_DEFAULT_WAIT_TIME 2000 + if (priv->phandle->is_go_timer_set) { + woal_cancel_timer(&priv->phandle->go_timer); + priv->phandle->is_go_timer_set = MFALSE; + } +#define MGMT_TX_DEFAULT_WAIT_TIME 1000 /** cancel previous remain on channel */ if (priv->phandle->remain_on_channel) { + remain_priv = priv->phandle->priv[priv->phandle->remain_bss_index]; + if (!remain_priv) { + PRINTM(MERROR, "mgmt_tx:Wrong remain_bss_index=%d\n", + priv->phandle->remain_bss_index); + ret = -EFAULT; + goto done; + } if (woal_cfg80211_remain_on_channel_cfg - (priv, MOAL_IOCTL_WAIT, MTRUE, &channel_status, NULL, 0, 0)) { - PRINTM(MERROR, "Fail to cancel remain on channel\n"); + (remain_priv, MOAL_IOCTL_WAIT, MTRUE, &channel_status, NULL, 0, + 0)) { + PRINTM(MERROR, "mgmt_tx:Fail to cancel remain on channel\n"); ret = -EFAULT; goto done; } if (priv->phandle->cookie) { - cfg80211_remain_on_channel_expired(priv->netdev, - priv->phandle->cookie, - &priv->phandle->chan, - priv->phandle->channel_type, - GFP_ATOMIC); + cfg80211_remain_on_channel_expired( +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) + remain_priv->netdev, +#else + remain_priv->wdev, +#endif + priv->phandle->cookie, + &priv->phandle->chan, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) + priv->phandle-> + channel_type, +#endif + GFP_ATOMIC); priv->phandle->cookie = 0; } priv->phandle->remain_on_channel = MFALSE; @@ -1166,6 +1683,7 @@ woal_cfg80211_mgmt_tx(struct wiphy *wiphy, duration = wait; if (!wait) duration = MGMT_TX_DEFAULT_WAIT_TIME; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) if (channel_type_valid) ret = woal_cfg80211_remain_on_channel_cfg(priv, MOAL_IOCTL_WAIT, @@ -1173,6 +1691,7 @@ woal_cfg80211_mgmt_tx(struct wiphy *wiphy, chan, channel_type, duration); else +#endif ret = woal_cfg80211_remain_on_channel_cfg(priv, MOAL_IOCTL_WAIT, MFALSE, &channel_status, @@ -1183,9 +1702,12 @@ woal_cfg80211_mgmt_tx(struct wiphy *wiphy, goto done; } priv->phandle->remain_on_channel = MTRUE; + priv->phandle->remain_bss_index = priv->bss_index; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) priv->phandle->channel_type = channel_type; +#endif memcpy(&priv->phandle->chan, chan, sizeof(struct ieee80211_channel)); - PRINTM(MIOCTL, "Mgmt Tx: Set remain channel=%d\n", + PRINTM(MIOCTL, "%s: Mgmt Tx: Set remain channel=%d\n", dev->name, ieee80211_frequency_to_channel(chan->center_freq)); } #endif @@ -1233,15 +1755,27 @@ woal_cfg80211_mgmt_tx(struct wiphy *wiphy, atomic_inc(&priv->phandle->tx_pending); queue_work(priv->phandle->workqueue, &priv->phandle->main_work); - /* delay 20ms to guarantee the packet has been already tx'ed becuase if - we call cfg80211_mgmt_tx_status() immediately, then wpa_supplicant - will call cancel_remain_on_channel(), which may affect the mgmt - frame tx */ - mdelay(20); +#if defined(WIFI_DIRECT_SUPPORT) +#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION + /* Delay 30ms to guarantee the packet has been already tx'ed, becuase + if we call cfg80211_mgmt_tx_status() immediately, then + wpa_supplicant will call cancel_remain_on_channel(), which may + affect the mgmt frame tx. Meanwhile it is only necessary for P2P + action handshake to wait 30ms. */ + if ((priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) && + (framectrl == IEEE80211_STYPE_ACTION)) + woal_sched_timeout(30); +#endif +#endif /* Notify the mgmt tx status */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) || defined(COMPAT_WIRELESS) +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) cfg80211_mgmt_tx_status(dev, *cookie, buf, len, true, GFP_ATOMIC); +#else + cfg80211_mgmt_tx_status(priv->wdev, *cookie, buf, len, true, + GFP_ATOMIC); +#endif #endif break; case MLAN_STATUS_SUCCESS: @@ -1287,29 +1821,6 @@ woal_parse_ie_tlv(const t_u8 * ie, int len, t_u8 id) return NULL; } -/** - * @brief This function returns priv - * based on mgmt ie index - * - * @param handle A pointer to moal_handle - * @param index mgmt ie index - * - * @return Pointer to moal_private - */ -static moal_private * -woal_get_priv_by_mgmt_index(moal_handle * handle, t_u16 index) -{ - int i; - - for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) { - if (handle->priv[i]) { - if (handle->priv[i]->probereq_index == index) - return (handle->priv[i]); - } - } - return NULL; -} - /** * @brief Add custom ie to mgmt frames. * @@ -1380,7 +1891,6 @@ woal_cfg80211_custom_ie(moal_private * priv, pos += len; custom_ie->len += len; } - ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); if (ioctl_req == NULL) { ret = -ENOMEM; @@ -1450,6 +1960,48 @@ woal_cfg80211_custom_ie(moal_private * priv, } /** + * @brief Find first P2P ie + * + * @param ie Pointer to IEs + * @param len Total length of ie + * @param ie_out Pointer to out IE buf + * + * @return out IE length + */ +static t_u16 +woal_get_first_p2p_ie(const t_u8 * ie, int len, t_u8 * ie_out) +{ + int left_len = len; + const t_u8 *pos = ie; + int length; + t_u8 id = 0; + t_u16 out_len = 0; + IEEEtypes_VendorSpecific_t *pVendorIe = NULL; + const u8 p2p_oui[4] = { 0x50, 0x6f, 0x9a, 0x09 }; + + while (left_len >= 2) { + length = *(pos + 1); + id = *pos; + if ((length + 2) > left_len) + break; + if (id == VENDOR_SPECIFIC_221) { + pVendorIe = (IEEEtypes_VendorSpecific_t *) pos; + if (!memcmp + (pVendorIe->vend_hdr.oui, p2p_oui, + sizeof(pVendorIe->vend_hdr.oui)) && + pVendorIe->vend_hdr.oui_type == p2p_oui[3]) { + memcpy(ie_out + out_len, pos, length + 2); + out_len += length + 2; + break; + } + } + pos += (length + 2); + left_len -= (length + 2); + } + return out_len; +} + +/** * @brief Filter specific IE in ie buf * * @param ie Pointer to IEs @@ -1460,7 +2012,7 @@ woal_cfg80211_custom_ie(moal_private * priv, * @return out IE length */ static t_u16 -woal_filter_beacon_ies(const t_u8 * ie, int len, t_u8 * ie_out, t_u8 wps_flag) +woal_filter_beacon_ies(const t_u8 * ie, int len, t_u8 * ie_out, t_u16 wps_flag) { int left_len = len; const t_u8 *pos = ie; @@ -1472,6 +2024,7 @@ woal_filter_beacon_ies(const t_u8 * ie, int len, t_u8 * ie_out, t_u8 wps_flag) const u8 p2p_oui[4] = { 0x50, 0x6f, 0x9a, 0x09 }; const u8 wfd_oui[4] = { 0x50, 0x6f, 0x9a, 0x0a }; const t_u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 }; + t_u8 find_p2p_ie = MFALSE; /* ERP_INFO/EXTENDED_SUPPORT_RATES/HT_CAPABILITY/HT_OPERATION/WMM and WPS/P2P/WFD IE will be fileter out */ @@ -1489,21 +2042,37 @@ woal_filter_beacon_ies(const t_u8 * ie, int len, t_u8 * ie_out, t_u8 wps_flag) case VENDOR_SPECIFIC_221: /* filter out wmm ie */ pVendorIe = (IEEEtypes_VendorSpecific_t *) pos; - if (!memcmp(pVendorIe->vend_hdr.oui, wmm_oui, sizeof(wmm_oui))) + if (!memcmp + (pVendorIe->vend_hdr.oui, wmm_oui, + sizeof(pVendorIe->vend_hdr.oui)) && + pVendorIe->vend_hdr.oui_type == wmm_oui[3]) + break; + /* filter out wps ie */ + if ((!memcmp + (pVendorIe->vend_hdr.oui, wps_oui, + sizeof(pVendorIe->vend_hdr.oui)) && + pVendorIe->vend_hdr.oui_type == wps_oui[3]) && + (wps_flag & IE_MASK_WPS)) break; - if (wps_flag) { - /* filter out wps/p2p ie */ - pVendorIe = (IEEEtypes_VendorSpecific_t *) pos; - if (memcmp(pVendorIe->vend_hdr.oui, wps_oui, sizeof(wps_oui)) && - memcmp(pVendorIe->vend_hdr.oui, p2p_oui, sizeof(p2p_oui)) && - memcmp(pVendorIe->vend_hdr.oui, wfd_oui, sizeof(wfd_oui))) { - memcpy(ie_out + out_len, pos, length + 2); - out_len += length + 2; + /* filter out first p2p ie */ + if ((!memcmp + (pVendorIe->vend_hdr.oui, p2p_oui, + sizeof(pVendorIe->vend_hdr.oui)) && + pVendorIe->vend_hdr.oui_type == p2p_oui[3])) { + if (!find_p2p_ie && (wps_flag & IE_MASK_P2P)) { + find_p2p_ie = MTRUE; + break; } - } else { - memcpy(ie_out + out_len, pos, length + 2); - out_len += length + 2; } + /* filter out wfd ie */ + if ((!memcmp + (pVendorIe->vend_hdr.oui, wfd_oui, + sizeof(pVendorIe->vend_hdr.oui)) && + pVendorIe->vend_hdr.oui_type == wfd_oui[3]) && + (wps_flag & IE_MASK_WFD)) + break; + memcpy(ie_out + out_len, pos, length + 2); + out_len += length + 2; break; default: memcpy(ie_out + out_len, pos, length + 2); @@ -1516,6 +2085,86 @@ woal_filter_beacon_ies(const t_u8 * ie, int len, t_u8 * ie_out, t_u8 wps_flag) return out_len; } +#ifdef WIFI_DIRECT_SUPPORT +/** + * @brief Check if selected_registrar_on in wps_ie + * + * @param ie Pointer to IEs + * @param len Total length of ie + * + * @return MTRUE/MFALSE + */ +t_u8 +is_selected_registrar_on(const t_u8 * ie, int len) +{ +#define WPS_IE_FIX_LEN 6 +#define TLV_ID_SELECTED_REGISTRAR 0x1041 + int left_len = len - WPS_IE_FIX_LEN; + TLV_Generic_t *tlv = (TLV_Generic_t *) (ie + WPS_IE_FIX_LEN); + u16 tlv_type, tlv_len; + u8 *pos = NULL; + while (left_len > sizeof(TLV_Generic_t)) { + tlv_type = ntohs(tlv->type); + tlv_len = ntohs(tlv->len); + if (tlv_type == TLV_ID_SELECTED_REGISTRAR) { + PRINTM(MIOCTL, "Selected Registrar found !"); + pos = (u8 *) tlv + sizeof(TLV_Generic_t); + if (*pos == 1) + return MTRUE; + else + return MFALSE; + } + tlv = (TLV_Generic_t *) ((u8 *) tlv + tlv_len + sizeof(TLV_Generic_t)); + left_len -= tlv_len + sizeof(TLV_Generic_t); + } + return MFALSE; +} + +/** + * @brief Check if selected_registrar_on in ies + * + * @param ie Pointer to IEs + * @param len Total length of ie + * + * + * @return MTRUE/MFALSE + */ +static t_u16 +woal_is_selected_registrar_on(const t_u8 * ie, int len) +{ + int left_len = len; + const t_u8 *pos = ie; + int length; + t_u8 id = 0; + IEEEtypes_VendorSpecific_t *pVendorIe = NULL; + const u8 wps_oui[4] = { 0x00, 0x50, 0xf2, 0x04 }; + + while (left_len >= 2) { + length = *(pos + 1); + id = *pos; + if ((length + 2) > left_len) + break; + switch (id) { + case VENDOR_SPECIFIC_221: + pVendorIe = (IEEEtypes_VendorSpecific_t *) pos; + if (!memcmp + (pVendorIe->vend_hdr.oui, wps_oui, + sizeof(pVendorIe->vend_hdr.oui)) && + pVendorIe->vend_hdr.oui_type == wps_oui[3]) { + PRINTM(MIOCTL, "Find WPS ie\n"); + return is_selected_registrar_on(pos, length + 2); + } + break; + default: + break; + } + pos += (length + 2); + left_len -= (length + 2); + } + return MFALSE; +} +#endif + /** * @brief config AP or GO for mgmt frame ies. * @@ -1553,14 +2202,11 @@ woal_cfg80211_mgmt_frame_ie(moal_private * priv, t_u16 proberesp_index = priv->proberesp_index; t_u16 assocresp_index = priv->assocresp_index; t_u16 probereq_index = priv->probereq_index; - moal_private *pmpriv = NULL; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) && !defined(COMPAT_WIRELESS) t_u16 beacon_wps_index = priv->beacon_wps_index; -#endif + t_u16 proberesp_p2p_index = priv->proberesp_p2p_index; ENTER(); -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) && !defined(COMPAT_WIRELESS) if (mask & MGMT_MASK_BEACON_WPS_P2P) { if (!(beacon_ies_data = kmalloc(sizeof(custom_ie), GFP_KERNEL))) { ret = -ENOMEM; @@ -1568,6 +2214,14 @@ woal_cfg80211_mgmt_frame_ie(moal_private * priv, } memset(beacon_ies_data, 0x00, sizeof(custom_ie)); if (beacon_ies && beacon_ies_len) { +#ifdef WIFI_DIRECT_SUPPORT + if (woal_is_selected_registrar_on(beacon_ies, beacon_ies_len)) { + PRINTM(MIOCTL, "selected_registrar is on\n"); + priv->phandle->is_go_timer_set = MTRUE; + woal_mod_timer(&priv->phandle->go_timer, MOAL_TIMER_10S); + } else + PRINTM(MIOCTL, "selected_registrar is off\n"); +#endif beacon_ies_data->ie_index = beacon_wps_index; beacon_ies_data->mgmt_subtype_mask = MGMT_MASK_BEACON; beacon_ies_data->ie_length = beacon_ies_len; @@ -1590,12 +2244,14 @@ woal_cfg80211_mgmt_frame_ie(moal_private * priv, proberesp_ies_data, &proberesp_index, assocresp_ies_data, &assocresp_index, probereq_ies_data, &probereq_index)) { + PRINTM(MERROR, "Fail to set beacon wps IE\n"); ret = -EFAULT; } priv->beacon_wps_index = beacon_wps_index; + PRINTM(MIOCTL, "beacon_wps_index=0x%x\n", beacon_wps_index); goto done; } -#endif + if (mask & MGMT_MASK_BEACON) { if (!(beacon_ies_data = kmalloc(sizeof(custom_ie), GFP_KERNEL))) { ret = -ENOMEM; @@ -1634,24 +2290,15 @@ woal_cfg80211_mgmt_frame_ie(moal_private * priv, if (beacon_ies && beacon_ies_len) { /* set the beacon ies */ beacon_ies_data->ie_index = beacon_index; - beacon_ies_data->mgmt_subtype_mask = MGMT_MASK_BEACON; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) && !defined(COMPAT_WIRELESS) - beacon_ies_data->mgmt_subtype_mask |= - MGMT_MASK_ASSOC_RESP | MGMT_MASK_PROBE_RESP; - beacon_ies_data->ie_length = - woal_filter_beacon_ies(beacon_ies, beacon_ies_len, - beacon_ies_data->ie_buffer, MTRUE); -#else - /* wpa_supplicant 1.x, will pass beacon_ie, probe_resp_ie and - asso_resp_ie wpa_supplicant 1.0/2.x, will pass beacon_ie, - prebe_resp_ie Only beacon_ie include RSN/WPA IE, other ies only - include wps/p2p ie */ - beacon_ies_data->mgmt_subtype_mask |= + beacon_ies_data->mgmt_subtype_mask = MGMT_MASK_BEACON | MGMT_MASK_ASSOC_RESP | MGMT_MASK_PROBE_RESP; - beacon_ies_data->ie_length = - woal_filter_beacon_ies(beacon_ies, beacon_ies_len, - beacon_ies_data->ie_buffer, MFALSE); -#endif + beacon_ies_data->ie_length = woal_filter_beacon_ies(beacon_ies, + beacon_ies_len, + beacon_ies_data-> + ie_buffer, + IE_MASK_WPS | + IE_MASK_WFD | + IE_MASK_P2P); } else { /* clear the beacon ies */ if (beacon_index > MAX_MGMT_IE_INDEX) { @@ -1669,20 +2316,54 @@ woal_cfg80211_mgmt_frame_ie(moal_private * priv, if (proberesp_ies_data) { memset(proberesp_ies_data, 0x00, sizeof(custom_ie)); if (proberesp_ies && proberesp_ies_len) { + /* set the probe response p2p ies */ + proberesp_ies_data->ie_index = proberesp_p2p_index; + proberesp_ies_data->mgmt_subtype_mask = MGMT_MASK_PROBE_RESP; + proberesp_ies_data->ie_length = woal_get_first_p2p_ie(proberesp_ies, + proberesp_ies_len, + proberesp_ies_data-> + ie_buffer); + } else { + /* clear the probe response p2p ies */ + if (proberesp_p2p_index > MAX_MGMT_IE_INDEX) { + PRINTM(MERROR, + "Invalid proberesp_p2p_index for mgmt frame ie.\n"); + goto done; + } + proberesp_ies_data->ie_index = proberesp_p2p_index; + proberesp_ies_data->mgmt_subtype_mask = MLAN_CUSTOM_IE_DELETE_MASK; + proberesp_ies_data->ie_length = 0; + proberesp_p2p_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; + } + if (MLAN_STATUS_SUCCESS != + woal_cfg80211_custom_ie(priv, NULL, &beacon_index, + proberesp_ies_data, &proberesp_p2p_index, + NULL, &assocresp_index, + NULL, &probereq_index)) { + PRINTM(MERROR, "Fail to set proberesp p2p IE\n"); + ret = -EFAULT; + goto done; + } + priv->proberesp_p2p_index = proberesp_p2p_index; + PRINTM(MIOCTL, "proberesp_p2p=0x%x\n", proberesp_p2p_index); + memset(proberesp_ies_data, 0x00, sizeof(custom_ie)); + if (proberesp_ies && proberesp_ies_len) { /* set the probe response ies */ - // proberesp_ies_data->ie_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; proberesp_ies_data->ie_index = proberesp_index; proberesp_ies_data->mgmt_subtype_mask = MGMT_MASK_PROBE_RESP; - proberesp_ies_data->ie_length = proberesp_ies_len; - pos = proberesp_ies_data->ie_buffer; - memcpy(pos, proberesp_ies, proberesp_ies_len); + if (MLAN_CUSTOM_IE_AUTO_IDX_MASK == proberesp_index) + proberesp_ies_data->mgmt_subtype_mask |= + MLAN_CUSTOM_IE_NEW_MASK; + proberesp_ies_data->ie_length = + woal_filter_beacon_ies(proberesp_ies, proberesp_ies_len, + proberesp_ies_data->ie_buffer, + IE_MASK_P2P); } else { /* clear the probe response ies */ if (proberesp_index > MAX_MGMT_IE_INDEX) { PRINTM(MERROR, "Invalid probe resp index for mgmt frame ie.\n"); goto done; } - proberesp_ies_data->ie_index = proberesp_index; proberesp_ies_data->mgmt_subtype_mask = MLAN_CUSTOM_IE_DELETE_MASK; proberesp_ies_data->ie_length = 0; @@ -1714,39 +2395,33 @@ woal_cfg80211_mgmt_frame_ie(moal_private * priv, if (probereq_ies_data) { memset(probereq_ies_data, 0x00, sizeof(custom_ie)); - if ((probereq_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK) && - (priv->probereq_index != probereq_index)) { - pmpriv = woal_get_priv_by_mgmt_index(priv->phandle, probereq_index); - if (pmpriv) { - probereq_ies_data->ie_index = probereq_index; - probereq_ies_data->mgmt_subtype_mask = - MLAN_CUSTOM_IE_DELETE_MASK; - probereq_ies_data->ie_length = 0; - probereq_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; - pmpriv->probereq_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; - if (MLAN_STATUS_SUCCESS != - woal_cfg80211_custom_ie(pmpriv, NULL, &beacon_index, - NULL, &proberesp_index, - NULL, &assocresp_index, - probereq_ies_data, - &probereq_index)) { - ret = -EFAULT; - goto done; - } - memset(probereq_ies_data, 0x00, sizeof(custom_ie)); - } - } if (probereq_ies && probereq_ies_len) { /* set the probe req ies */ probereq_ies_data->ie_index = probereq_index; probereq_ies_data->mgmt_subtype_mask = MGMT_MASK_PROBE_REQ; - probereq_ies_data->ie_length = probereq_ies_len; - pos = probereq_ies_data->ie_buffer; - memcpy(pos, probereq_ies, probereq_ies_len); +#if defined(WIFI_DIRECT_SUPPORT) +#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION + if (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT) { + /* filter out P2P/WFD ie */ + probereq_ies_data->ie_length = + woal_filter_beacon_ies(probereq_ies, probereq_ies_len, + probereq_ies_data->ie_buffer, + IE_MASK_P2P | IE_MASK_WFD); + } else { +#endif /* KERNEL_VERSION */ +#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */ + probereq_ies_data->ie_length = probereq_ies_len; + pos = probereq_ies_data->ie_buffer; + memcpy(pos, probereq_ies, probereq_ies_len); +#if defined(WIFI_DIRECT_SUPPORT) +#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION + } +#endif /* KERNEL_VERSION */ +#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */ } else { /* clear the probe req ies */ if (probereq_index > MAX_MGMT_IE_INDEX) { - PRINTM(MERROR, "Invalid probe resp index for mgmt frame ie.\n"); + PRINTM(MERROR, "Invalid probe req index for mgmt frame ie.\n"); goto done; } probereq_ies_data->ie_index = probereq_index; @@ -1761,6 +2436,7 @@ woal_cfg80211_mgmt_frame_ie(moal_private * priv, proberesp_ies_data, &proberesp_index, assocresp_ies_data, &assocresp_index, probereq_ies_data, &probereq_index)) { + PRINTM(MERROR, "Fail to set beacon proberesp assoc probereq IES\n"); ret = -EFAULT; goto done; } @@ -1772,6 +2448,8 @@ woal_cfg80211_mgmt_frame_ie(moal_private * priv, priv->proberesp_index = proberesp_index; if (probereq_ies_data) priv->probereq_index = probereq_index; + PRINTM(MIOCTL, "beacon=%x assocresp=%x proberesp=%x probereq=%x\n", + beacon_index, assocresp_index, proberesp_index, probereq_index); done: if (beacon_ies_data) kfree(beacon_ies_data); diff --git a/drivers/net/wireless/sd8797/mlinux/moal_cfg80211.h b/drivers/net/wireless/sd8797/mlinux/moal_cfg80211.h index d0b459980384..99fb84dcbc8b 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_cfg80211.h +++ b/drivers/net/wireless/sd8797/mlinux/moal_cfg80211.h @@ -37,6 +37,7 @@ /* define for custom ie operation */ #define MLAN_CUSTOM_IE_AUTO_IDX_MASK 0xffff #define MLAN_CUSTOM_IE_DELETE_MASK 0x0 +#define MLAN_CUSTOM_IE_NEW_MASK 0x8000 #define TLV_TYPE_MGMT_IE 0x0169 #define MGMT_MASK_ASSOC_REQ 0x01 #define MGMT_MASK_REASSOC_REQ 0x04 @@ -46,6 +47,9 @@ #define MGMT_MASK_PROBE_RESP 0x20 #define MGMT_MASK_BEACON 0x100 #define MGMT_MASK_BEACON_WPS_P2P 0x8000 +#define IE_MASK_WPS 0x0001 +#define IE_MASK_P2P 0x0002 +#define IE_MASK_WFD 0x0004 /** * If multiple wiphys are registered e.g. a regular netdev with @@ -62,6 +66,8 @@ void *woal_get_wiphy_priv(struct wiphy *wiphy); /* Get the private structure from net device */ void *woal_get_netdev_priv(struct net_device *dev); +t_u8 woal_band_cfg_to_ieee_band(t_u32 band); + int woal_cfg80211_change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, enum nl80211_iftype type, @@ -83,22 +89,32 @@ int woal_cfg80211_del_key(struct wiphy *wiphy, #endif const t_u8 * mac_addr); +int woal_cfg80211_set_bitrate_mask(struct wiphy *wiphy, + struct net_device *dev, + const u8 * peer, + const struct cfg80211_bitrate_mask *mask); + +int woal_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant); + #ifdef STA_CFG80211 #ifdef STA_SUPPORT int woal_set_rf_channel(moal_private * priv, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type); mlan_status woal_inform_bss_from_scan_result(moal_private * priv, - mlan_802_11_ssid * ssid); + mlan_ssid_bssid * ssid_bssid, + t_u8 wait_option); #endif #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) int woal_cfg80211_set_channel(struct wiphy *wiphy, #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) || defined(COMPAT_WIRELESS) struct net_device *dev, #endif struct ieee80211_channel *chan, enum nl80211_channel_type channel_type); +#endif #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,37) || defined(COMPAT_WIRELESS) int woal_cfg80211_set_default_key(struct wiphy *wiphy, @@ -110,15 +126,25 @@ int woal_cfg80211_set_default_key(struct wiphy *wiphy, #endif void woal_cfg80211_mgmt_frame_register(struct wiphy *wiphy, - struct net_device *dev, t_u16 frame_type, - bool reg); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct wireless_dev *wdev, +#else + struct net_device *dev, +#endif + t_u16 frame_type, bool reg); int woal_cfg80211_mgmt_tx(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct wireless_dev *wdev, +#else struct net_device *dev, +#endif struct ieee80211_channel *chan, bool offchan, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) enum nl80211_channel_type channel_type, - bool channel_type_valid, unsigned int wait, - const u8 * buf, size_t len, + bool channel_type_valid, +#endif + unsigned int wait, const u8 * buf, size_t len, #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) || defined(COMPAT_WIRELESS) bool no_cck, #endif @@ -127,10 +153,50 @@ int woal_cfg80211_mgmt_tx(struct wiphy *wiphy, #endif u64 * cookie); +mlan_status woal_register_cfg80211(moal_private * priv); + extern struct ieee80211_supported_band cfg80211_band_2ghz; extern struct ieee80211_supported_band cfg80211_band_5ghz; extern const u32 cfg80211_cipher_suites[10]; +#if defined(STA_SUPPORT) && defined(UAP_SUPPORT) +int woal_cfg80211_bss_role_cfg(moal_private * priv, t_u16 action, + t_u8 * bss_role); +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) +struct wireless_dev *woal_cfg80211_add_virtual_intf(struct wiphy *wiphy, + const char *name, + enum nl80211_iftype type, + u32 * flags, + struct vif_params *params); +#else +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) +struct wireless_dev *woal_cfg80211_add_virtual_intf(struct wiphy *wiphy, + char *name, + enum nl80211_iftype type, + u32 * flags, + struct vif_params *params); +#else +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,37) || defined(COMPAT_WIRELESS) +struct net_device *woal_cfg80211_add_virtual_intf(struct wiphy *wiphy, + char *name, + enum nl80211_iftype type, + u32 * flags, + struct vif_params *params); +#else +int woal_cfg80211_add_virtual_intf(struct wiphy *wiphy, + char *name, enum nl80211_iftype type, + u32 * flags, struct vif_params *params); +#endif +#endif +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) +int woal_cfg80211_del_virtual_intf(struct wiphy *wiphy, + struct wireless_dev *wdev); +#else +int woal_cfg80211_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev); +#endif + #if defined(WIFI_DIRECT_SUPPORT) /** Define kernel version for wifi direct */ #if !defined(COMPAT_WIRELESS) @@ -142,6 +208,27 @@ extern const u32 cfg80211_cipher_suites[10]; /** Define for remain on channel duration timer */ #define MAX_REMAIN_ON_CHANNEL_DURATION (1000 * 5) +int woal_cfg80211_init_p2p_client(moal_private * priv); + +int woal_cfg80211_init_p2p_go(moal_private * priv); + +int woal_cfg80211_deinit_p2p(moal_private * priv); + +int woal_cfg80211_remain_on_channel_cfg(moal_private * priv, + t_u8 wait_option, t_u8 remove, + t_u8 * status, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + t_u32 duration); +int woal_uap_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, + u8 * mac, struct station_info *stainfo); + +void woal_remove_virtual_interface(moal_handle * handle); + +#endif /* KERNEL_VERSION */ +#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */ + +#ifdef UAP_CFG80211 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) int woal_cfg80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, @@ -161,26 +248,13 @@ int woal_cfg80211_set_beacon(struct wiphy *wiphy, #endif int woal_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev); - -int woal_cfg80211_init_p2p_client(moal_private * priv); - -int woal_cfg80211_init_p2p_go(moal_private * priv); - -int woal_cfg80211_deinit_p2p(moal_private * priv); - -int woal_cfg80211_remain_on_channel_cfg(moal_private * priv, - t_u8 wait_option, t_u8 remove, - t_u8 * status, - struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type, - t_u32 duration); -int woal_uap_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, - u8 * mac, struct station_info *stainfo); -#endif /* KERNEL_VERSION */ -#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */ +int woal_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *dev, u8 * mac_addr); +#endif const t_u8 *woal_parse_ie_tlv(const t_u8 * ie, int len, t_u8 id); +void woal_clear_all_mgmt_ies(moal_private * priv); int woal_cfg80211_mgmt_frame_ie(moal_private * priv, const t_u8 * beacon_ies, size_t beacon_ies_len, const t_u8 * proberesp_ies, @@ -190,6 +264,12 @@ int woal_cfg80211_mgmt_frame_ie(moal_private * priv, const t_u8 * probereq_ies, size_t probereq_ies_len, t_u16 mask); +t_u8 woal_is_any_interface_active(moal_handle * handle); + +int woal_get_active_intf_freq(moal_handle * handle); + void woal_cfg80211_setup_ht_cap(struct ieee80211_sta_ht_cap *ht_info, t_u32 dev_cap, t_u8 * mcs_set); +int woal_cfg80211_assoc(moal_private * priv, void *sme); + #endif /* _MOAL_CFG80211_H_ */ diff --git a/drivers/net/wireless/sd8797/mlinux/moal_debug.c b/drivers/net/wireless/sd8797/mlinux/moal_debug.c index f731da551e7f..0c19d5effbf8 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_debug.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_debug.c @@ -100,6 +100,9 @@ static struct debug_data items[] = { , {"port_open", item_size(port_open), item_addr(port_open)} , + {"bypass_pkt_count", item_size(bypass_pkt_count), + item_addr(bypass_pkt_count)} + , {"scan_processing", item_size(scan_processing), item_addr(scan_processing)} , {"num_tx_timeout", item_size(num_tx_timeout), item_addr(num_tx_timeout)} @@ -127,6 +130,8 @@ static struct debug_data items[] = { {"last_event_index", item_size(last_event_index), item_addr(last_event_index)} , + {"num_no_cmd_node", item_size(num_no_cmd_node), item_addr(num_no_cmd_node)} + , {"num_cmd_h2c_fail", item_size(num_cmd_host_to_card_failure), item_addr(num_cmd_host_to_card_failure)} , @@ -194,6 +199,9 @@ static struct debug_data items[] = { {"malloc_count", item_handle_size(malloc_count), item_handle_addr(malloc_count)} , + {"vmalloc_count", item_handle_size(vmalloc_count), + item_handle_addr(vmalloc_count)} + , {"mbufalloc_count", item_handle_size(mbufalloc_count), item_handle_addr(mbufalloc_count)} , @@ -253,6 +261,9 @@ static struct debug_data uap_items[] = { , {"tx_pkts_queued", item_size(tx_pkts_queued), item_addr(tx_pkts_queued)} , + {"bypass_pkt_count", item_size(bypass_pkt_count), + item_addr(bypass_pkt_count)} + , {"num_bridge_pkts", item_size(num_bridge_pkts), item_addr(num_bridge_pkts)} , {"num_drop_pkts", item_size(num_drop_pkts), item_addr(num_drop_pkts)} @@ -282,6 +293,8 @@ static struct debug_data uap_items[] = { {"last_event_index", item_size(last_event_index), item_addr(last_event_index)} , + {"num_no_cmd_node", item_size(num_no_cmd_node), item_addr(num_no_cmd_node)} + , {"num_cmd_h2c_fail", item_size(num_cmd_host_to_card_failure), item_addr(num_cmd_host_to_card_failure)} , @@ -333,6 +346,9 @@ static struct debug_data uap_items[] = { {"malloc_count", item_handle_size(malloc_count), item_handle_addr(malloc_count)} , + {"vmalloc_count", item_handle_size(vmalloc_count), + item_handle_addr(vmalloc_count)} + , {"mbufalloc_count", item_handle_size(mbufalloc_count), item_handle_addr(mbufalloc_count)} , @@ -417,6 +433,11 @@ woal_debug_read(char *page, char **s, off_t off, int cnt, int *eof, void *data) else p += sprintf(p, "%s=%d\n", d[i].name, val); } +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) + for (i = 0; i < 4; i++) + p += sprintf(p, "wmm_tx_pending[%d]:%d\n", i, + atomic_read(&priv->wmm_tx_pending[i])); +#endif if (info.tx_tbl_num) { p += sprintf(p, "Tx BA stream table:\n"); for (i = 0; i < info.tx_tbl_num; i++) { @@ -490,12 +511,13 @@ woal_debug_write(struct file *f, const char *buf, unsigned long cnt, void *data) return MLAN_STATUS_FAILURE; } - pdata = (char *) kmalloc(cnt, GFP_KERNEL); + pdata = (char *) kmalloc(cnt + 1, GFP_KERNEL); if (pdata == NULL) { MODULE_PUT; LEAVE(); return 0; } + memset(pdata, 0, cnt + 1); if (copy_from_user(pdata, buf, cnt)) { PRINTM(MERROR, "Copy from user failed\n"); @@ -539,8 +561,9 @@ woal_debug_write(struct file *f, const char *buf, unsigned long cnt, void *data) kfree(pdata); #ifdef DEBUG_LEVEL1 - if (last_drvdbg != drvdbg) + if (last_drvdbg != drvdbg) { woal_set_drvdbg(priv, drvdbg); + } #endif /* Set debug information */ @@ -607,7 +630,7 @@ woal_debug_entry(moal_private * priv) #endif priv->items_priv.priv = priv; - handle_items = 7; + handle_items = 8; #ifdef SDIO_MMC_DEBUG handle_items += 2; #endif diff --git a/drivers/net/wireless/sd8797/mlinux/moal_eth_ioctl.c b/drivers/net/wireless/sd8797/mlinux/moal_eth_ioctl.c index aab4e5a1a40d..86c7bc73b239 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_eth_ioctl.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_eth_ioctl.c @@ -63,7 +63,7 @@ static t_u8 SupportedAdhocBand[] = { /******************************************************** Global Variables ********************************************************/ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) #ifdef UAP_SUPPORT /** Network device handlers for uAP */ extern const struct net_device_ops woal_uap_netdev_ops; @@ -75,6 +75,7 @@ extern const struct net_device_ops woal_netdev_ops; #endif extern int cfg80211_wext; +extern int hw_test; /******************************************************** Local Functions ********************************************************/ @@ -149,8 +150,7 @@ woal_set_ap_wps_p2p_ie(moal_private * priv, t_u8 * ie, size_t len) ENTER(); ie_len = len - 2; - if (ie_len <= 0 || ie_len > MAX_IE_SIZE) { - // TO DO need handle IE large then 256 + if (ie_len <= 0) { PRINTM(MERROR, "IE len error: %d\n", ie_len); ret = -EFAULT; goto done; @@ -867,7 +867,7 @@ woal_priv_delba(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) if (user_data_len > 3 || (!(data[0] & (DELBA_TX | DELBA_RX))) || - (data[1] != DELBA_ALL_TIDS && !(data[1] >= 0 && data[1] <= 7))) { + (data[1] != DELBA_ALL_TIDS && !(data[1] <= 7))) { /* Incorrect number of arguments */ PRINTM(MERROR, "%d: Invalid arguments\n", __LINE__); ret = -EINVAL; @@ -1332,6 +1332,94 @@ woal_setget_priv_txratecfg(moal_private * priv, t_u8 * respbuf, } +#ifdef STA_SUPPORT +/** + * @brief Get statistics information + * + * @param priv A pointer to moal_private structure + * @param wait_option Wait option + * @param stats A pointer to mlan_ds_get_stats structure + * + * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail + */ +mlan_status +woal_get_stats_info(moal_private * priv, t_u8 wait_option, + mlan_ds_get_stats * stats) +{ + int ret = 0; + mlan_ds_get_info *info = NULL; + mlan_ioctl_req *req = NULL; + mlan_status status = MLAN_STATUS_SUCCESS; + ENTER(); + + /* Allocate an IOCTL request buffer */ + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + + /* Fill request buffer */ + info = (mlan_ds_get_info *) req->pbuf; + info->sub_command = MLAN_OID_GET_STATS; + req->req_id = MLAN_IOCTL_GET_INFO; + req->action = MLAN_ACT_GET; + + /* Send IOCTL request to MLAN */ + status = woal_request_ioctl(priv, req, wait_option); + if (status == MLAN_STATUS_SUCCESS) { + if (stats) + memcpy(stats, &info->param.stats, sizeof(mlan_ds_get_stats)); +#if defined(STA_WEXT) || defined(UAP_WEXT) + priv->w_stats.discard.fragment = info->param.stats.fcs_error; + priv->w_stats.discard.retries = info->param.stats.retry; + priv->w_stats.discard.misc = info->param.stats.ack_failure; +#endif + } + done: + if (req && (status != MLAN_STATUS_PENDING)) + kfree(req); + LEAVE(); + return status; +} + +/** + * @brief Get wireless stats information + * + * @param priv A pointer to moal_private structure + * @param respbuf A pointer to response buffer + * @param respbuflen Available length of response buffer + * + * @return Number of bytes written, negative for failure. + */ +int +woal_get_priv_getlog(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) +{ + int ret = 0; + mlan_ds_get_stats *stats; + ENTER(); + + if (respbuflen < sizeof(*stats)) { + PRINTM(MERROR, "Get log: respbuflen (%d) too small!", (int) respbuflen); + ret = -EFAULT; + goto done; + } + stats = (mlan_ds_get_stats *) respbuf; + if (MLAN_STATUS_SUCCESS != + woal_get_stats_info(priv, MOAL_IOCTL_WAIT, stats)) { + PRINTM(MERROR, "Get log: Failed to get stats info!"); + ret = -EFAULT; + goto done; + } + + ret = sizeof(mlan_ds_get_stats); + + done: + LEAVE(); + return ret; +} +#endif + /** * @brief Set/Get esupplicant mode configurations * @@ -1508,8 +1596,8 @@ woal_setget_priv_passphrase(moal_private * priv, t_u8 * respbuf, break; } sec->param.passphrase.psk_type = MLAN_PSK_PASSPHRASE; - strncpy(sec->param.passphrase.psk.passphrase.passphrase, end, - sizeof(sec->param.passphrase.psk.passphrase.passphrase)); + memcpy(sec->param.passphrase.psk.passphrase.passphrase, end, + sizeof(sec->param.passphrase.psk.passphrase.passphrase)); sec->param.passphrase.psk.passphrase.passphrase_len = strlen(end); PRINTM(MINFO, "passphrase=%s, len=%d\n", sec->param.passphrase.psk.passphrase.passphrase, @@ -1581,7 +1669,6 @@ woal_setget_priv_passphrase(moal_private * priv, t_u8 * respbuf, int woal_priv_deauth(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) { - mlan_ioctl_req *req = NULL; int ret = 0; t_u8 mac[ETH_ALEN]; @@ -1601,8 +1688,6 @@ woal_priv_deauth(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) } done: - if (req) - kfree(req); LEAVE(); return ret; } @@ -1632,12 +1717,8 @@ woal_priv_ap_deauth(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) memset(&deauth_param, 0, sizeof(mlan_deauth_param)); memcpy(&deauth_param, data_ptr, sizeof(mlan_deauth_param)); - PRINTM(MIOCTL, - "ioctl deauth station: %02x:%02x:%02x:%02x:%02x:%02x, reason=%d\n", - deauth_param.mac_addr[0], deauth_param.mac_addr[1], - deauth_param.mac_addr[2], deauth_param.mac_addr[3], - deauth_param.mac_addr[4], deauth_param.mac_addr[5], - deauth_param.reason_code); + PRINTM(MIOCTL, "ioctl deauth station: " MACSTR ", reason=%d\n", + MAC2STR(deauth_param.mac_addr), deauth_param.reason_code); ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss)); if (ioctl_req == NULL) { @@ -1796,12 +1877,12 @@ woal_priv_bssrole(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) ENTER(); + memset((char *) data, 0, sizeof(data)); if (strlen(respbuf) == (strlen(CMD_MARVELL) + strlen(PRIV_CMD_BSSROLE))) { /* GET operation */ user_data_len = 0; } else { /* SET operation */ - memset((char *) data, 0, sizeof(data)); parse_arguments(respbuf + strlen(CMD_MARVELL) + strlen(PRIV_CMD_BSSROLE), data, sizeof(data) / sizeof(int), &user_data_len); @@ -2031,6 +2112,76 @@ woal_priv_getscantable(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) LEAVE(); return ret; } + +/** + * @brief Extended capabilities configuration + * + * @param priv A pointer to moal_private structure + * @param respbuf A pointer to response buffer + * @param respbuflen Available length of response buffer + * + * @return Number of bytes written, negative for failure. + */ +int +woal_priv_extcapcfg(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) +{ + int ret, header; + mlan_ioctl_req *req = NULL; + mlan_ds_misc_cfg *cfg = NULL; + IEEEtypes_Header_t *ie; + + ENTER(); + + if (!respbuf) { + LEAVE(); + return 0; + } + + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + + cfg = (mlan_ds_misc_cfg *) req->pbuf; + cfg->sub_command = MLAN_OID_MISC_EXT_CAP_CFG; + req->req_id = MLAN_IOCTL_MISC_CFG; + header = strlen(CMD_MARVELL) + strlen(PRIV_CMD_EXTCAPCFG); + if (strlen(respbuf) == header) + /* GET operation */ + req->action = MLAN_ACT_GET; + else { + /* SET operation */ + ie = (IEEEtypes_Header_t *) (respbuf + header); + if (ie->len > sizeof(ExtCap_t)) { + PRINTM(MERROR, "Extended Capability lenth is invalid\n"); + ret = -EFAULT; + goto done; + } + req->action = MLAN_ACT_SET; + memset(&cfg->param.ext_cap, 0, sizeof(ExtCap_t) - ie->len); + memcpy(&cfg->param.ext_cap, ie + 1, ie->len); + } + + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; + } + + memset(respbuf, 0, respbuflen); + ie = (IEEEtypes_Header_t *) respbuf; + ie->element_id = EXT_CAPABILITY; + ie->len = sizeof(ExtCap_t); + memcpy(ie + 1, &cfg->param.ext_cap, sizeof(ExtCap_t)); + + ret = sizeof(ie) + ie->len; + + done: + if (req) + kfree(req); + LEAVE(); + return ret; +} #endif /** @@ -2124,6 +2275,12 @@ woal_priv_setgetipaddr(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) ENTER(); + if (priv->bss_type != MLAN_BSS_TYPE_STA) { + PRINTM(MIOCTL, "Bss type[%d]: Not STA, ignore it\n", priv->bss_type); + ret = sprintf(respbuf, "OK\n") + 1; + goto done; + } + header = strlen(CMD_MARVELL) + strlen(PRIV_CMD_IPADDR); data_length = strlen(respbuf) - header; @@ -2209,12 +2366,12 @@ woal_priv_setwpssession(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) ENTER(); + memset((char *) data, 0, sizeof(data)); if (strlen(respbuf) == (strlen(CMD_MARVELL) + strlen(PRIV_CMD_WPSSESSION))) { /* GET operation */ user_data_len = 0; } else { /* SET operation */ - memset((char *) data, 0, sizeof(data)); parse_arguments(respbuf + strlen(CMD_MARVELL) + strlen(PRIV_CMD_WPSSESSION), data, sizeof(data) / sizeof(int), &user_data_len); @@ -2404,8 +2561,6 @@ woal_priv_setgettcpackenh(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) t_u32 data[1]; int ret = 0; int user_data_len = 0; - struct list_head *link = NULL; - struct tcp_sess *tcp_sess = NULL; ENTER(); @@ -2438,16 +2593,7 @@ woal_priv_setgettcpackenh(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) PRINTM(MINFO, "Disabling TCP Ack enhancement\n"); priv->enable_tcp_ack_enh = MFALSE; /* release the tcp sessions if any */ - while (!list_empty(&priv->tcp_sess_queue)) { - link = priv->tcp_sess_queue.next; - tcp_sess = list_entry(link, struct tcp_sess, link); - PRINTM(MINFO, - "Disable TCP ACK Enh: release a tcp session in dl. (src: ipaddr 0x%08x, port: %d. dst: ipaddr 0x%08x, port: %d\n", - tcp_sess->src_ip_addr, tcp_sess->src_tcp_port, - tcp_sess->dst_ip_addr, tcp_sess->dst_tcp_port); - list_del(link); - kfree(tcp_sess); - } + woal_flush_tcp_sess_queue(priv); } else { PRINTM(MERROR, "Unknown option = %u\n", data[0]); ret = -EINVAL; @@ -2530,6 +2676,11 @@ woal_priv_assocessid(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) PRINTM(MINFO, "Requested new SSID = %s\n", (char *) req_ssid.ssid); memcpy(&ssid_bssid.ssid, &req_ssid, sizeof(mlan_802_11_ssid)); + if (MTRUE == woal_is_connected(priv, &ssid_bssid)) { + PRINTM(MIOCTL, "Already connect to the network\n"); + ret = sprintf(respbuf, "Has already connected to this ESSID!\n") + 1; + goto setessid_ret; + } memcpy(&priv->prev_ssid_bssid.ssid, &req_ssid, sizeof(mlan_802_11_ssid)); /* disconnect before driver assoc */ @@ -2769,6 +2920,7 @@ woal_priv_set_get_drvdbg(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) LEAVE(); return ret; } + #endif /** @@ -3064,10 +3216,8 @@ woal_priv_set_ap(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) awrq = (struct sockaddr *) &(mwr->u.ap_addr); - PRINTM(MINFO, "ASSOC: WAP: sa_data: %02x:%02x:%02x:%02x:%02x:%02x\n", - (t_u8) awrq->sa_data[0], (t_u8) awrq->sa_data[1], - (t_u8) awrq->sa_data[2], (t_u8) awrq->sa_data[3], - (t_u8) awrq->sa_data[4], (t_u8) awrq->sa_data[5]); + PRINTM(MINFO, "ASSOC: WAP: sa_data: " MACSTR "\n", + MAC2STR((t_u8 *) awrq->sa_data)); if (MLAN_STATUS_SUCCESS != woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) { @@ -3093,8 +3243,6 @@ woal_priv_set_ap(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) if (bss_info.media_connected == MTRUE) { if (!memcmp(awrq->sa_data, &bss_info.bssid, ETH_ALEN)) goto done; - /* disconnect before try to assoicate to the new AP */ - woal_disconnect(priv, MOAL_IOCTL_WAIT, NULL); } memcpy(&ssid_bssid.bssid, awrq->sa_data, ETH_ALEN); } @@ -3213,6 +3361,12 @@ woal_priv_set_power(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) ENTER(); + if (hw_test) { + PRINTM(MIOCTL, "block set power in hw_test mode\n"); + LEAVE(); + return ret; + } + data_ptr = respbuf + (strlen(CMD_MARVELL) + strlen(PRIV_CMD_SET_POWER)); mwr = (struct mwreq *) data_ptr; @@ -3308,6 +3462,10 @@ woal_priv_set_essid(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) PRINTM(MINFO, "Requested new SSID = %s\n", (char *) req_ssid.ssid); memcpy(&ssid_bssid.ssid, &req_ssid, sizeof(mlan_802_11_ssid)); + if (MTRUE == woal_is_connected(priv, &ssid_bssid)) { + PRINTM(MIOCTL, "Already connect to the network\n"); + goto setessid_ret; + } if (mwr->u.essid.flags != 0xFFFF) { if (MLAN_STATUS_SUCCESS != woal_find_essid(priv, &ssid_bssid)) { @@ -3322,8 +3480,6 @@ woal_priv_set_essid(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) } - /* disconnect before try to associate */ - woal_disconnect(priv, MOAL_IOCTL_WAIT, NULL); mode = woal_get_mode(priv, MOAL_IOCTL_WAIT); if (mode != MW_MODE_ADHOC) { @@ -3547,6 +3703,63 @@ woal_priv_get_power(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) LEAVE(); return ret; } + +/** + * @brief Set/Get power save mode + * + * @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_set_get_psmode(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) +{ + int ret = 0; + int data = 0; + int user_data_len = 0, header_len = 0; + t_u32 action = MLAN_ACT_GET; + + ENTER(); + + header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_PSMODE); + + if (strlen(respbuf) == header_len) { + /* GET operation */ + user_data_len = 0; + action = MLAN_ACT_GET; + } else { + /* SET operation */ + parse_arguments(respbuf + header_len, &data, sizeof(data) / sizeof(int), + &user_data_len); + action = MLAN_ACT_SET; + } + + if (sizeof(int) * user_data_len > sizeof(data)) { + PRINTM(MERROR, "Too many arguments\n"); + ret = -EINVAL; + goto done; + } + + /* Flip the value */ + data = !data; + + if (MLAN_STATUS_SUCCESS != woal_set_get_power_mgmt(priv, action, &data, 0)) { + ret = -EFAULT; + goto done; + } + + if (action == MLAN_ACT_SET) + data = !data; + + memcpy(respbuf, (t_u8 *) & data, sizeof(data)); + ret = sizeof(data); + + done: + LEAVE(); + return ret; +} #endif /* STA_SUPPORT */ /** @@ -3737,7 +3950,7 @@ woal_priv_txpowercfg(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) goto done; pcfg->param.power_ext.len = user_data_len; memcpy((t_u8 *) & pcfg->param.power_ext.power_data, - (t_u8 *) data, sizeof(int) * sizeof(data)); + (t_u8 *) data, sizeof(data)); } if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { ret = -EFAULT; @@ -4522,6 +4735,881 @@ woal_priv_mgmt_frame_passthru_ctrl(moal_private * priv, t_u8 * respbuf, } /** + * @brief Private IOCTL entry to send an ADDTS TSPEC + * + * Receive a ADDTS command from the application. The command structure + * contains a TSPEC and timeout in milliseconds. The timeout is performed + * in the firmware after the ADDTS command frame is sent. + * + * The TSPEC is received in the API as an opaque block. The firmware will + * send the entire data block, including the bytes after the TSPEC. This + * is done to allow extra IEs to be packaged with the TSPEC in the ADDTS + * action frame. + * + * The IOCTL structure contains two return fields: + * - The firmware command result, which indicates failure and timeouts + * - The IEEE Status code which contains the corresponding value from + * any ADDTS response frame received. + * + * In addition, the opaque TSPEC data block passed in is replaced with the + * TSPEC received in the ADDTS response frame. In case of failure, the + * AP may modify the TSPEC on return and in the case of success, the + * medium time is returned as calculated by the AP. Along with the TSPEC, + * any IEs that are sent in the ADDTS response are also returned and can be + * parsed using the IOCTL length as an indicator of extra elements. + * + * The return value to the application layer indicates a driver execution + * success or failure. A successful return could still indicate a firmware + * failure or AP negotiation failure via the commandResult field copied + * back to the application. + * + * @param priv Pointer to the mlan_private driver data struct + * @param respbuf A pointer to response buffer + * @param respbuflen Available length of response buffer + * + * @return Number of bytes written if successful else negative value + */ +static int +woal_priv_wmm_addts_req_ioctl(moal_private * priv, t_u8 * respbuf, + t_u32 respbuflen) +{ + mlan_ioctl_req *req = NULL; + mlan_ds_wmm_cfg *cfg = NULL; + wlan_ioctl_wmm_addts_req_t addts_ioctl; + int ret = 0, header_len = 0, copy_len = sizeof(addts_ioctl); + t_u8 *data_ptr; + + ENTER(); + + header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_ADDTS); + data_ptr = respbuf + header_len; + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + + req->req_id = MLAN_IOCTL_WMM_CFG; + cfg = (mlan_ds_wmm_cfg *) req->pbuf; + cfg->sub_command = MLAN_OID_WMM_CFG_ADDTS; + + memset(&addts_ioctl, 0x00, sizeof(addts_ioctl)); + + memcpy((t_u8 *) & addts_ioctl, data_ptr, sizeof(addts_ioctl)); + + cfg->param.addts.timeout = addts_ioctl.timeout_ms; + cfg->param.addts.ie_data_len = (t_u8) addts_ioctl.ie_data_len; + + memcpy(cfg->param.addts.ie_data, + addts_ioctl.ie_data, cfg->param.addts.ie_data_len); + + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; + } + addts_ioctl.cmd_result = cfg->param.addts.result; + addts_ioctl.ieee_status_code = (t_u8) cfg->param.addts.status_code; + addts_ioctl.ie_data_len = cfg->param.addts.ie_data_len; + + memcpy(addts_ioctl.ie_data, + cfg->param.addts.ie_data, cfg->param.addts.ie_data_len); + + copy_len = (sizeof(addts_ioctl) + - sizeof(addts_ioctl.ie_data) + + cfg->param.addts.ie_data_len); + + memcpy(respbuf, (t_u8 *) & addts_ioctl, copy_len); + ret = copy_len; + + done: + if (req) + kfree(req); + LEAVE(); + return ret; +} + +/** + * @brief Private IOCTL entry to send a DELTS TSPEC + * + * Receive a DELTS command from the application. The command structure + * contains a TSPEC and reason code along with space for a command result + * to be returned. The information is packaged is sent to the wlan_cmd.c + * firmware command prep and send routines for execution in the firmware. + * + * The reason code is not used for WMM implementations but is indicated in + * the 802.11e specification. + * + * The return value to the application layer indicates a driver execution + * success or failure. A successful return could still indicate a firmware + * failure via the cmd_result field copied back to the application. + * + * @param priv Pointer to the mlan_private driver data struct + * @param respbuf A pointer to response buffer + * @param respbuflen Available length of response buffer + * + * @return Number of bytes written if successful else negative value + */ +static int +woal_priv_wmm_delts_req_ioctl(moal_private * priv, t_u8 * respbuf, + t_u32 respbuflen) +{ + mlan_ioctl_req *req = NULL; + mlan_ds_wmm_cfg *cfg = NULL; + wlan_ioctl_wmm_delts_req_t delts_ioctl; + int ret = 0, header_len = 0, copy_len = 0; + t_u8 *data_ptr; + + ENTER(); + + header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_DELTS); + data_ptr = respbuf + header_len; + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + + req->req_id = MLAN_IOCTL_WMM_CFG; + cfg = (mlan_ds_wmm_cfg *) req->pbuf; + cfg->sub_command = MLAN_OID_WMM_CFG_DELTS; + + memset(&delts_ioctl, 0x00, sizeof(delts_ioctl)); + + if (strlen(respbuf) > header_len) { + copy_len = MIN(strlen(data_ptr), sizeof(delts_ioctl)); + memcpy((t_u8 *) & delts_ioctl, data_ptr, copy_len); + + cfg->param.delts.status_code = (t_u32) delts_ioctl.ieee_reason_code; + cfg->param.delts.ie_data_len = (t_u8) delts_ioctl.ie_data_len; + + memcpy(cfg->param.delts.ie_data, + delts_ioctl.ie_data, cfg->param.delts.ie_data_len); + + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, + MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; + } + + /* Return the firmware command result back to the application layer */ + delts_ioctl.cmd_result = cfg->param.delts.result; + copy_len = sizeof(delts_ioctl); + memcpy(respbuf, (t_u8 *) & delts_ioctl, copy_len); + ret = copy_len; + } + + done: + if (req) + kfree(req); + LEAVE(); + return ret; +} + +/** + * @brief Private IOCTL entry to get/set a specified AC Queue's parameters + * + * Receive a AC Queue configuration command which is used to get, set, or + * default the parameters associated with a specific WMM AC Queue. + * + * @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_qconfig(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) +{ + mlan_ioctl_req *req = NULL; + mlan_ds_wmm_cfg *pwmm = NULL; + mlan_ds_wmm_queue_config *pqcfg = NULL; + wlan_ioctl_wmm_queue_config_t qcfg_ioctl; + t_u8 *data_ptr; + int ret = 0; + + ENTER(); + + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + + req->req_id = MLAN_IOCTL_WMM_CFG; + pwmm = (mlan_ds_wmm_cfg *) req->pbuf; + pwmm->sub_command = MLAN_OID_WMM_CFG_QUEUE_CONFIG; + + memset(&qcfg_ioctl, 0x00, sizeof(qcfg_ioctl)); + pqcfg = (mlan_ds_wmm_queue_config *) & pwmm->param.q_cfg; + data_ptr = respbuf + (strlen(CMD_MARVELL) + strlen(PRIV_CMD_QCONFIG)); + + memcpy((t_u8 *) & qcfg_ioctl, data_ptr, sizeof(qcfg_ioctl)); + pqcfg->action = qcfg_ioctl.action; + pqcfg->access_category = qcfg_ioctl.access_category; + pqcfg->msdu_lifetime_expiry = qcfg_ioctl.msdu_lifetime_expiry; + + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; + } + memset(&qcfg_ioctl, 0x00, sizeof(qcfg_ioctl)); + qcfg_ioctl.action = pqcfg->action; + qcfg_ioctl.access_category = pqcfg->access_category; + qcfg_ioctl.msdu_lifetime_expiry = pqcfg->msdu_lifetime_expiry; + memcpy(data_ptr, (t_u8 *) & qcfg_ioctl, sizeof(qcfg_ioctl)); + ret = strlen(CMD_MARVELL) + strlen(PRIV_CMD_QCONFIG) + sizeof(qcfg_ioctl); + done: + if (req) + kfree(req); + LEAVE(); + return ret; +} + +/** + * @brief Private IOCTL entry to get the status of the WMM queues + * + * Return the following information for each WMM AC: + * - WMM IE Acm Required + * - Firmware Flow Required + * - Firmware Flow Established + * - Firmware Queue Enabled + * - Firmware Delivery Enabled + * - Firmware Trigger Enabled + * + * @param priv Pointer to the moal_private driver data struct + * @param respbuf A pointer to response buffer + * @param respbuflen Available length of response buffer + * + * @return Number of bytes written if successful else negative value + */ +static int +woal_priv_wmm_queue_status_ioctl(moal_private * priv, t_u8 * respbuf, + t_u32 respbuflen) +{ + mlan_ioctl_req *req = NULL; + mlan_ds_wmm_cfg *pwmm = NULL; + wlan_ioctl_wmm_queue_status_t qstatus_ioctl; + int ret = 0, header_len = 0; + + ENTER(); + + header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_QSTATUS); + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + + req->req_id = MLAN_IOCTL_WMM_CFG; + pwmm = (mlan_ds_wmm_cfg *) req->pbuf; + pwmm->sub_command = MLAN_OID_WMM_CFG_QUEUE_STATUS; + + if (strlen(respbuf) == header_len) { + if (MLAN_STATUS_SUCCESS != + woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; + } + + memset(&qstatus_ioctl, 0x00, sizeof(qstatus_ioctl)); + memcpy((void *) &qstatus_ioctl, (void *) &pwmm->param.q_status, + sizeof(qstatus_ioctl)); + memcpy(respbuf, (t_u8 *) & qstatus_ioctl, sizeof(qstatus_ioctl)); + ret = sizeof(qstatus_ioctl); + } + + done: + if (req) + kfree(req); + LEAVE(); + return ret; +} + +/** + * @brief Private IOCTL entry to get the status of the WMM Traffic Streams + * + * @param priv Pointer to the moal_private driver data struct + * @param respbuf A pointer to response buffer + * @param respbuflen Available length of response buffer + * + * @return Number of bytes written if successful else negative value + */ +static int +woal_priv_wmm_ts_status_ioctl(moal_private * priv, t_u8 * respbuf, + t_u32 respbuflen) +{ + mlan_ioctl_req *req = NULL; + mlan_ds_wmm_cfg *pwmm = NULL; + wlan_ioctl_wmm_ts_status_t ts_status_ioctl; + int ret = 0, header_len = 0; + t_u8 *data_ptr; + + ENTER(); + + header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_TS_STATUS); + data_ptr = respbuf + header_len; + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + + req->req_id = MLAN_IOCTL_WMM_CFG; + pwmm = (mlan_ds_wmm_cfg *) req->pbuf; + pwmm->sub_command = MLAN_OID_WMM_CFG_TS_STATUS; + + memset(&ts_status_ioctl, 0x00, sizeof(ts_status_ioctl)); + + memcpy((t_u8 *) & ts_status_ioctl, data_ptr, sizeof(ts_status_ioctl)); + + memset(&pwmm->param.ts_status, 0x00, sizeof(ts_status_ioctl)); + pwmm->param.ts_status.tid = ts_status_ioctl.tid; + + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; + } + + memset(&ts_status_ioctl, 0x00, sizeof(ts_status_ioctl)); + memcpy((void *) &ts_status_ioctl, (void *) &pwmm->param.ts_status, + sizeof(ts_status_ioctl)); + memcpy(respbuf, (t_u8 *) & ts_status_ioctl, sizeof(ts_status_ioctl)); + ret = sizeof(ts_status_ioctl); + + done: + if (req) + kfree(req); + LEAVE(); + return ret; +} + +/** + * @brief Set/Get MAC control + * + * @param priv A pointer to moal_private structure + * @param respbuf A pointer to response buffer + * @param respbuflen Available length of response buffer + * + * @return Number of bytes written, negative for failure. + */ +int +woal_priv_macctrl(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) +{ + int data = 0; + mlan_ioctl_req *req = NULL; + mlan_ds_misc_cfg *cfg = NULL; + int ret = 0; + int user_data_len = 0, header_len = 0; + + ENTER(); + + header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_MAC_CTRL); + if (strlen(respbuf) == header_len) { + /* GET operation */ + user_data_len = 0; + } else { + /* SET operation */ + parse_arguments(respbuf + header_len, &data, 1, &user_data_len); + } + + if (user_data_len > 1) { + PRINTM(MERROR, "Invalid number of arguments\n"); + ret = -EINVAL; + goto done; + } + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + + cfg = (mlan_ds_misc_cfg *) req->pbuf; + cfg->sub_command = MLAN_OID_MISC_MAC_CONTROL; + req->req_id = MLAN_IOCTL_MISC_CFG; + + if (user_data_len == 0) + req->action = MLAN_ACT_GET; + else { + cfg->param.mac_ctrl = (t_u32) data; + req->action = MLAN_ACT_SET; + } + + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; + } + + memcpy(respbuf, (t_u8 *) & cfg->param.mac_ctrl, sizeof(data)); + ret = sizeof(data); + + done: + if (req) + kfree(req); + LEAVE(); + return ret; +} + +/** + * @brief Get connection status + * + * @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 + */ +int +woal_priv_getwap(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) +{ + int ret = 0; +#ifdef STA_SUPPORT + mlan_bss_info bss_info; +#endif + + ENTER(); + +#ifdef STA_SUPPORT + if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) { + memset(&bss_info, 0, sizeof(bss_info)); + + woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info); + + if (bss_info.media_connected == MTRUE) { + memcpy(respbuf, (t_u8 *) & bss_info.bssid, MLAN_MAC_ADDR_LENGTH); + } else { + memset(respbuf, 0, MLAN_MAC_ADDR_LENGTH); + } + } +#endif +#ifdef UAP_SUPPORT + if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) { + if (priv->bss_started) { + memcpy(respbuf, priv->current_addr, MLAN_MAC_ADDR_LENGTH); + } else { + memset(respbuf, 0, MLAN_MAC_ADDR_LENGTH); + } + } +#endif + ret = MLAN_MAC_ADDR_LENGTH; + LEAVE(); + return ret; +} + +/** + * @brief Set/Get Region Code + * + * @param priv A pointer to moal_private structure + * @param respbuf A pointer to response buffer + * @param respbuflen Available length of response buffer + * + * @return Number of bytes written, negative for failure. + */ +int +woal_priv_region_code(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) +{ + int data = 0; + mlan_ioctl_req *req = NULL; + mlan_ds_misc_cfg *cfg = NULL; + int ret = 0; + int user_data_len = 0, header_len = 0; + + ENTER(); + + header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_REGION_CODE); + if (strlen(respbuf) == header_len) { + /* GET operation */ + user_data_len = 0; + } else { + /* SET operation */ + parse_arguments(respbuf + header_len, &data, 1, &user_data_len); + } + + if (user_data_len > 1) { + PRINTM(MERROR, "Invalid number of arguments\n"); + ret = -EINVAL; + goto done; + } + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + + cfg = (mlan_ds_misc_cfg *) req->pbuf; + cfg->sub_command = MLAN_OID_MISC_REGION; + req->req_id = MLAN_IOCTL_MISC_CFG; + + if (user_data_len == 0) + req->action = MLAN_ACT_GET; + else { + cfg->param.region_code = (t_u32) data; + req->action = MLAN_ACT_SET; + } + + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; + } + + memcpy(respbuf, (t_u8 *) & cfg->param.region_code, sizeof(data)); + ret = sizeof(data); + + done: + if (req) + kfree(req); + LEAVE(); + return ret; +} + +/** + * @brief Set/Get FW side mac address + * + * @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 + */ +int +woal_priv_fwmacaddr(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) +{ + t_u8 data[ETH_ALEN]; + int ret = 0; + int header_len = 0; + mlan_ioctl_req *req = NULL; + mlan_ds_bss *bss = NULL; + + ENTER(); + + header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_FWMACADDR); + + /* Allocate an IOCTL request buffer */ + req = (mlan_ioctl_req *) woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + /* Fill request buffer */ + bss = (mlan_ds_bss *) req->pbuf; + bss->sub_command = MLAN_OID_BSS_MAC_ADDR; + req->req_id = MLAN_IOCTL_BSS; + + if (strlen(respbuf) == header_len) { + /* GET operation */ + req->action = MLAN_ACT_GET; + } else { + /* SET operation */ + req->action = MLAN_ACT_SET; + memset(data, 0, sizeof(data)); + woal_mac2u8(data, respbuf + header_len); + memcpy(bss->param.mac_addr, data, ETH_ALEN); + } + + /* Send IOCTL request to MLAN */ + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; + } + + memcpy(respbuf, bss->param.mac_addr, sizeof(data)); + ret = sizeof(data); + HEXDUMP("FW MAC Addr:", respbuf, ETH_ALEN); + + done: + if (req) + kfree(req); + LEAVE(); + return ret; +} + +#if defined(WIFI_DIRECT_SUPPORT) +#ifdef STA_CFG80211 +#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION +/** + * @brief Set offchannel + * + * @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 + */ +int +woal_priv_offchannel(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) +{ + int data[3]; + int ret = 0; + t_u8 status = 1; + int user_data_len = 0, header_len = 0; + + ENTER(); + + memset(data, 0, sizeof(data)); + + header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_OFFCHANNEL); + + if (header_len == strlen(respbuf)) { + /* Query current remain on channel status */ + if (priv->phandle->remain_on_channel) + ret = + sprintf(respbuf, + "There is pending remain on channel from bss %d\n", + priv->phandle->remain_bss_index) + 1; + else + ret = + sprintf(respbuf, "There is no pending remain on channel\n") + 1; + goto done; + } else + parse_arguments(respbuf + header_len, data, sizeof(data) / sizeof(int), + &user_data_len); + + if (sizeof(int) * user_data_len > sizeof(data)) { + PRINTM(MERROR, "Too many arguments\n"); + ret = -EINVAL; + goto done; + } + + if (user_data_len >= 1) { + if ((data[0] != 0) && (data[0] != 1)) { + PRINTM(MERROR, "action (%d) must be either 0 or 1\n", data[0]); + ret = -EINVAL; + goto done; + } + } + if (user_data_len == 2) { + if (data[0] == 1) { + PRINTM(MERROR, "channel and duration must both the mentioned\n"); + ret = -EINVAL; + goto done; + } else { + PRINTM(MWARN, + "extra arguments are ignored since action is 'cancel'\n"); + } + } + if (user_data_len == 3) { + if (data[0] == 1) { + if (data[1] < 0) { + PRINTM(MERROR, "channel cannot be negative\n"); + ret = -EINVAL; + goto done; + } + if (data[2] < 0) { + PRINTM(MERROR, "duration cannot be negative\n"); + ret = -EINVAL; + goto done; + } + } + } + + if (data[0] == 0) { + if (!priv->phandle->remain_on_channel) { + ret = + sprintf(respbuf, + "There is no pending remain on channel to be canceled\n") + + 1; + goto done; + } + if (woal_cfg80211_remain_on_channel_cfg + (priv, MOAL_IOCTL_WAIT, MTRUE, &status, NULL, 0, 0)) { + PRINTM(MERROR, "remain_on_channel: Failed to cancel\n"); + ret = -EFAULT; + goto done; + } + if (status == MLAN_STATUS_SUCCESS) + priv->phandle->remain_on_channel = MFALSE; + } else if (data[0] == 1) { + if (woal_cfg80211_remain_on_channel_cfg + (priv, MOAL_IOCTL_WAIT, MFALSE, &status, + ieee80211_get_channel(priv->wdev->wiphy, + ieee80211_channel_to_frequency(data[1] +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) || defined(COMPAT_WIRELESS) + , + (data[1] <= + 14 ? + IEEE80211_BAND_2GHZ + : + IEEE80211_BAND_5GHZ) +#endif + )), 0, (t_u32) data[2])) { + PRINTM(MERROR, "remain_on_channel: Failed to start\n"); + ret = -EFAULT; + goto done; + } + if (status == MLAN_STATUS_SUCCESS) { + priv->phandle->remain_on_channel = MTRUE; + priv->phandle->remain_bss_index = priv->bss_index; + } + } + + if (status != MLAN_STATUS_SUCCESS) + ret = -EFAULT; + else + ret = sprintf(respbuf, "OK\n") + 1; + + done: + LEAVE(); + return ret; +} +#endif +#endif +#endif + +#if defined(STA_SUPPORT) +/** + * @brief Make PMF bit required/optional + * @param priv Pointer to moal_private structure + * @param respbuf Pointer to response buffer + * @param resplen Response buffer length + * + * @return 0 -- success, otherwise fail + */ +int +woal_priv_set_get_pmfcfg(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) +{ + int data[2] = { 0, 0 }; + mlan_ioctl_req *req = NULL; + mlan_ds_misc_cfg *cfg = NULL; + mlan_ds_misc_pmfcfg *pmfcfg; + int ret = 0; + int user_data_len = 0, header_len = 0; + + ENTER(); + + header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_PMFCFG); + if (strlen(respbuf) == header_len) { + /* GET operation */ + user_data_len = 0; + } else { + /* SET operation */ + parse_arguments(respbuf + header_len, data, sizeof(data) / sizeof(int), + &user_data_len); + } + + if (user_data_len > 2) { + PRINTM(MERROR, "Invalid number of arguments\n"); + ret = -EINVAL; + goto done; + } + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + + cfg = (mlan_ds_misc_cfg *) req->pbuf; + pmfcfg = (mlan_ds_misc_pmfcfg *) & cfg->param.pmfcfg; + cfg->sub_command = MLAN_OID_MISC_PMFCFG; + req->req_id = MLAN_IOCTL_MISC_CFG; + + if (user_data_len == 0) + req->action = MLAN_ACT_GET; + else { + pmfcfg->mfpc = (t_u8) data[0]; + pmfcfg->mfpr = (t_u8) data[1]; + req->action = MLAN_ACT_SET; + } + + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; + } + + memcpy(respbuf, (t_u8 *) & cfg->param.pmfcfg, sizeof(mlan_ds_misc_pmfcfg)); + ret = sizeof(mlan_ds_misc_pmfcfg); + + done: + if (req) + kfree(req); + LEAVE(); + return ret; +} +#endif + +/** + * @brief Get/Set inactivity timeout extend + * @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_inactivity_timeout_ext(moal_private * priv, t_u8 * respbuf, + t_u32 respbuflen) +{ + int data[4]; + mlan_ioctl_req *req = NULL; + mlan_ds_pm_cfg *pmcfg = NULL; + pmlan_ds_inactivity_to inac_to = NULL; + int ret = 0; + int user_data_len = 0, header_len = 0; + + ENTER(); + + header_len = strlen(CMD_MARVELL) + strlen(PRIV_CMD_INACTIVITYTO); + memset(data, 0, sizeof(data)); + if (strlen(respbuf) == header_len) { + /* GET operation */ + user_data_len = 0; + } else { + /* SET operation */ + parse_arguments(respbuf + header_len, data, sizeof(data) / sizeof(int), + &user_data_len); + } + + if (user_data_len != 0 && user_data_len != 3 && user_data_len != 4) { + PRINTM(MERROR, "Invalid number of parameters\n"); + ret = -EINVAL; + goto done; + } + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + + pmcfg = (mlan_ds_pm_cfg *) req->pbuf; + inac_to = &pmcfg->param.inactivity_to; + pmcfg->sub_command = MLAN_OID_PM_CFG_INACTIVITY_TO; + req->req_id = MLAN_IOCTL_PM_CFG; + req->action = MLAN_ACT_GET; + + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; + } + + if (user_data_len) { + inac_to->timeout_unit = data[0]; + inac_to->unicast_timeout = data[1]; + inac_to->mcast_timeout = data[2]; + if (user_data_len == 4) + inac_to->ps_entry_timeout = data[3]; + req->action = MLAN_ACT_SET; + + if (MLAN_STATUS_SUCCESS != + woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; + } + } else { + data[0] = inac_to->timeout_unit; + data[1] = inac_to->unicast_timeout; + data[2] = inac_to->mcast_timeout; + data[3] = inac_to->ps_entry_timeout; + + memcpy(respbuf, (t_u8 *) data, sizeof(data)); + ret = sizeof(data); + } + + done: + if (req) + kfree(req); + LEAVE(); + return ret; +} + +/** * @brief Set priv command for Android * @param dev A pointer to net_device structure * @param req A pointer to ifreq structure @@ -4561,7 +5649,8 @@ woal_android_priv_cmd(struct net_device *dev, struct ifreq *req) ret = -ENOMEM; goto done; } - if (copy_from_user(buf, priv_cmd.buf, priv_cmd.total_len)) { + if (copy_from_user + (buf, priv_cmd.buf, MIN((CMD_BUF_LEN - 1), priv_cmd.total_len))) { ret = -EFAULT; goto done; } @@ -4655,6 +5744,15 @@ woal_android_priv_cmd(struct net_device *dev, struct ifreq *req) /* Set/Get tx rate cfg */ len = woal_setget_priv_txratecfg(priv, buf, priv_cmd.total_len); goto handled; +#ifdef STA_SUPPORT + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_GETLOG, + strlen(PRIV_CMD_GETLOG)) == 0) { + /* Get wireless stats information */ + len = woal_get_priv_getlog(priv, buf, priv_cmd.total_len); + goto handled; +#endif } else if (strnicmp (buf + strlen(CMD_MARVELL), PRIV_CMD_CUSTOMIE, @@ -4732,6 +5830,13 @@ woal_android_priv_cmd(struct net_device *dev, struct ifreq *req) /* Get scan table */ len = woal_priv_getscantable(priv, buf, priv_cmd.total_len); goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_EXTCAPCFG, + strlen(PRIV_CMD_EXTCAPCFG)) == 0) { + /* Extended capabilities configure */ + len = woal_priv_extcapcfg(priv, buf, priv_cmd.total_len); + goto handled; #endif } else if (strnicmp @@ -4881,6 +5986,13 @@ woal_android_priv_cmd(struct net_device *dev, struct ifreq *req) /* Get power management parameters */ len = woal_priv_get_power(priv, buf, priv_cmd.total_len); goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_PSMODE, + strlen(PRIV_CMD_PSMODE)) == 0) { + /* Set/Get PS mode */ + len = woal_priv_set_get_psmode(priv, buf, priv_cmd.total_len); + goto handled; #endif } else if (strnicmp @@ -4963,6 +6075,123 @@ woal_android_priv_cmd(struct net_device *dev, struct ifreq *req) woal_priv_mgmt_frame_passthru_ctrl(priv, buf, priv_cmd.total_len); goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_QCONFIG, + strlen(PRIV_CMD_QCONFIG)) == 0) { + /* Queue config */ + len = woal_priv_qconfig(priv, buf, priv_cmd.total_len); + goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_ADDTS, + strlen(PRIV_CMD_ADDTS)) == 0) { + /* Send an ADDTS TSPEC */ + len = woal_priv_wmm_addts_req_ioctl(priv, buf, priv_cmd.total_len); + goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_DELTS, + strlen(PRIV_CMD_DELTS)) == 0) { + /* Send a DELTS TSPE */ + len = woal_priv_wmm_delts_req_ioctl(priv, buf, priv_cmd.total_len); + goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_QSTATUS, + strlen(PRIV_CMD_QSTATUS)) == 0) { + /* Get the status of the WMM queues */ + len = + woal_priv_wmm_queue_status_ioctl(priv, buf, priv_cmd.total_len); + goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_TS_STATUS, + strlen(PRIV_CMD_TS_STATUS)) == 0) { + /* Get the status of the WMM Traffic Streams */ + len = woal_priv_wmm_ts_status_ioctl(priv, buf, priv_cmd.total_len); + goto handled; +#ifdef STA_SUPPORT + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_QOS_CFG, + strlen(PRIV_CMD_QOS_CFG)) == 0) { + t_u32 action = MLAN_ACT_GET; + if (strlen(buf) == strlen(CMD_MARVELL) + strlen(PRIV_CMD_QOS_CFG)) { + pdata = buf; /* GET operation */ + } else { + pdata = buf + strlen(CMD_MARVELL) + strlen(PRIV_CMD_QOS_CFG); + action = MLAN_ACT_SET; /* SET operation */ + } + if (MLAN_STATUS_SUCCESS != woal_priv_qos_cfg(priv, action, pdata)) { + ret = -EFAULT; + goto done; + } + if (action == MLAN_ACT_GET) + len = sizeof(t_u8); + goto handled; +#endif + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_MAC_CTRL, + strlen(PRIV_CMD_MAC_CTRL)) == 0) { + /* MAC CTRL */ + len = woal_priv_macctrl(priv, buf, priv_cmd.total_len); + goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_GETWAP, + strlen(PRIV_CMD_GETWAP)) == 0) { + /* Get WAP */ + len = woal_priv_getwap(priv, buf, priv_cmd.total_len); + goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_REGION_CODE, + strlen(PRIV_CMD_REGION_CODE)) == 0) { + /* Region Code */ + len = woal_priv_region_code(priv, buf, priv_cmd.total_len); + goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_FWMACADDR, + strlen(PRIV_CMD_FWMACADDR)) == 0) { + /* Set FW MAC address */ + len = woal_priv_fwmacaddr(priv, buf, priv_cmd.total_len); + goto handled; +#if defined(WIFI_DIRECT_SUPPORT) +#ifdef STA_CFG80211 +#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_OFFCHANNEL, + strlen(PRIV_CMD_OFFCHANNEL)) == 0) { + if (IS_STA_CFG80211(cfg80211_wext)) { + /* Set offchannel */ + len = woal_priv_offchannel(priv, buf, priv_cmd.total_len); + } else + len = sprintf(buf, "CFG80211 is not enabled\n") + 1; + goto handled; +#endif +#endif +#endif +#if defined(STA_SUPPORT) + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_PMFCFG, + strlen(PRIV_CMD_PMFCFG)) == 0) { + /* Configure PMF */ + len = woal_priv_set_get_pmfcfg(priv, buf, priv_cmd.total_len); + goto handled; +#endif + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_INACTIVITYTO, + strlen(PRIV_CMD_INACTIVITYTO)) == 0) { + /* Get/Set inactivity timeout extend */ + len = + woal_priv_inactivity_timeout_ext(priv, buf, priv_cmd.total_len); + goto handled; } else { /* Fall through, after stripping off the custom header */ buf += strlen(CMD_MARVELL); @@ -4971,7 +6200,8 @@ woal_android_priv_cmd(struct net_device *dev, struct ifreq *req) #ifdef STA_SUPPORT if (strncmp(buf, "RSSILOW-THRESHOLD", strlen("RSSILOW-THRESHOLD")) == 0) { pdata = buf + strlen("RSSILOW-THRESHOLD") + 1; - if (MLAN_STATUS_SUCCESS != woal_set_rssi_low_threshold(priv, pdata)) { + if (MLAN_STATUS_SUCCESS != + woal_set_rssi_low_threshold(priv, pdata, MOAL_IOCTL_WAIT)) { ret = -EFAULT; goto done; } @@ -5048,16 +6278,44 @@ woal_android_priv_cmd(struct net_device *dev, struct ifreq *req) len = sprintf(buf, "OK\n") + 1; } else if (strncmp(buf, "POWERMODE", strlen("POWERMODE")) == 0) { pdata = buf + strlen("POWERMODE") + 1; - if (MLAN_STATUS_SUCCESS != woal_set_powermode(priv, pdata)) { - ret = -EFAULT; - goto done; + if (!hw_test) { + if (MLAN_STATUS_SUCCESS != woal_set_powermode(priv, pdata)) { + ret = -EFAULT; + goto done; + } + } + len = sprintf(buf, "OK\n") + 1; + } else if (strncmp(buf, "SETROAMING", strlen("SETROAMING")) == 0) { + pdata = buf + strlen("SETROAMING") + 1; +#ifdef STA_CFG80211 + if (*pdata == '1') { + priv->roaming_enabled = MTRUE; + PRINTM(MIOCTL, "Roaming enabled\n"); + } else if (*pdata == '0') { + priv->roaming_enabled = MFALSE; + PRINTM(MIOCTL, "Roaming disabled\n"); } +#endif len = sprintf(buf, "OK\n") + 1; } else if (strncmp(buf, "COUNTRY", strlen("COUNTRY")) == 0) { + if ((strlen(buf) - strlen("COUNTRY") - 1) > COUNTRY_CODE_LEN + || (strlen(buf) - strlen("COUNTRY") - 1) <= 0) { + PRINTM(MERROR, "Invalid country length\n"); + ret = -EFAULT; + goto done; + } memset(country_code, 0, sizeof(country_code)); memcpy(country_code, buf + strlen("COUNTRY") + 1, strlen(buf) - strlen("COUNTRY") - 1); PRINTM(MIOCTL, "Set COUNTRY %s\n", country_code); +#ifdef STA_CFG80211 + if (IS_STA_CFG80211(cfg80211_wext)) { + PRINTM(MIOCTL, "Notify country code=%s\n", country_code); + regulatory_hint(priv->wdev->wiphy, country_code); + len = sprintf(buf, "OK\n") + 1; + goto done; + } +#endif if (MLAN_STATUS_SUCCESS != woal_set_region_code(priv, country_code)) { ret = -EFAULT; goto done; @@ -5117,6 +6375,9 @@ woal_android_priv_cmd(struct net_device *dev, struct ifreq *req) else if (strncmp(buf, "SETSUSPENDOPT", strlen("SETSUSPENDOPT")) == 0) { /* it will be done by GUI */ len = sprintf(buf, "OK\n") + 1; + } else if (strncmp(buf, "SETSUSPENDMODE", strlen("SETSUSPENDMODE")) == 0) { + /* it will be done by GUI */ + len = sprintf(buf, "OK\n") + 1; } else if (strncmp(buf, "BTCOEXMODE", strlen("BTCOEXMODE")) == 0) { len = sprintf(buf, "OK\n") + 1; } else if (strncmp(buf, "BTCOEXSCAN-START", strlen("BTCOEXSCAN-START")) == @@ -5139,7 +6400,7 @@ woal_android_priv_cmd(struct net_device *dev, struct ifreq *req) len = sprintf(buf, "OK\n") + 1; } else if (strncmp(buf, "BGSCAN-STOP", strlen("BGSCAN-STOP")) == 0) { if (priv->bg_scan_start && !priv->scan_cfg.rssi_threshold) { - if (MLAN_STATUS_SUCCESS != woal_stop_bg_scan(priv)) { + if (MLAN_STATUS_SUCCESS != woal_stop_bg_scan(priv, MOAL_NO_WAIT)) { ret = -EFAULT; goto done; } @@ -5166,7 +6427,7 @@ woal_android_priv_cmd(struct net_device *dev, struct ifreq *req) else if (strncmp(buf, "GET_EVENT", strlen("GET_EVENT")) == 0) { if (IS_STA_CFG80211(cfg80211_wext)) { if (priv->last_event & EVENT_BG_SCAN_REPORT) - woal_inform_bss_from_scan_result(priv, NULL); + woal_inform_bss_from_scan_result(priv, NULL, MOAL_IOCTL_WAIT); } len = sprintf(buf, "EVENT=%d\n", priv->last_event) + 1; priv->last_event = 0; @@ -5190,10 +6451,12 @@ woal_android_priv_cmd(struct net_device *dev, struct ifreq *req) len = sprintf(buf, "OK\n") + 1; } else if (strncmp(buf, "QOSINFO", strlen("QOSINFO")) == 0) { pdata = buf + strlen("QOSINFO") + 1; - if (MLAN_STATUS_SUCCESS != woal_set_qos_cfg(priv, pdata)) { +#ifdef STA_SUPPORT + if (MLAN_STATUS_SUCCESS != woal_priv_qos_cfg(priv, MLAN_ACT_SET, pdata)) { ret = -EFAULT; goto done; } +#endif len = sprintf(buf, "OK\n") + 1; } else if (strncmp(buf, "SLEEPPD", strlen("SLEEPPD")) == 0) { pdata = buf + strlen("SLEEPPD") + 1; @@ -5209,6 +6472,7 @@ woal_android_priv_cmd(struct net_device *dev, struct ifreq *req) "SET_AP_WPS_P2P_IE 2" -- proberesp IE "SET_AP_WPS_P2P_IE 4" -- assocresp IE */ #if defined(STA_CFG80211) && defined(UAP_CFG80211) +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) if (MLAN_STATUS_SUCCESS != woal_set_ap_wps_p2p_ie(priv, (t_u8 *) pdata, priv_cmd.used_len - strlen @@ -5218,6 +6482,7 @@ woal_android_priv_cmd(struct net_device *dev, struct ifreq *req) goto done; } #endif +#endif len = sprintf(buf, "OK\n") + 1; } #endif @@ -5258,8 +6523,9 @@ woal_android_priv_cmd(struct net_device *dev, struct ifreq *req) ret = -EFAULT; } } else { - PRINTM(MERROR, "%s: the buffer supplied by appl is too small.\n", - __FUNCTION__); + PRINTM(MERROR, + "%s: the buffer supplied by appl is too small (supplied: %d, used: %d)\n", + __FUNCTION__, priv_cmd.total_len, priv_cmd.used_len); ret = -EFAULT; } } else { diff --git a/drivers/net/wireless/sd8797/mlinux/moal_eth_ioctl.h b/drivers/net/wireless/sd8797/mlinux/moal_eth_ioctl.h index 4dbc0f073098..d755b0d72099 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_eth_ioctl.h +++ b/drivers/net/wireless/sd8797/mlinux/moal_eth_ioctl.h @@ -54,6 +54,7 @@ Change log: #define PRIV_CMD_REJECTADDBAREQ "rejectaddbareq" #define PRIV_CMD_DATARATE "getdatarate" #define PRIV_CMD_TXRATECFG "txratecfg" +#define PRIV_CMD_GETLOG "getlog" #define PRIV_CMD_ESUPPMODE "esuppmode" #define PRIV_CMD_PASSPHRASE "passphrase" #define PRIV_CMD_DEAUTH "deauth" @@ -70,6 +71,7 @@ Change log: #ifdef STA_SUPPORT #define PRIV_CMD_GETSCANTABLE "getscantable" #define PRIV_CMD_SETUSERSCAN "setuserscan" +#define PRIV_CMD_EXTCAPCFG "extcapcfg" #endif #define PRIV_CMD_DEEPSLEEP "deepsleep" #define PRIV_CMD_IPADDR "ipaddr" @@ -98,6 +100,7 @@ Change log: #define PRIV_CMD_SET_AUTH "setauth" #define PRIV_CMD_GET_AP "getap" #define PRIV_CMD_GET_POWER "getpower" +#define PRIV_CMD_PSMODE "psmode" #endif #define PRIV_CMD_WARMRESET "warmreset" #define PRIV_CMD_TXPOWERCFG "txpowercfg" @@ -110,6 +113,23 @@ Change log: #define PRIV_CMD_SDCMD52RW "sdcmd52rw" #define PRIV_CMD_ARPFILTER "arpfilter" #define PRIV_CMD_MGMT_FRAME_CTRL "mgmtframectrl" +#define PRIV_CMD_QCONFIG "qconfig" +#define PRIV_CMD_ADDTS "addts" +#define PRIV_CMD_DELTS "delts" +#define PRIV_CMD_QSTATUS "qstatus" +#define PRIV_CMD_TS_STATUS "ts_status" +#define PRIV_CMD_QOS_CFG "qoscfg" +#define PRIV_CMD_MAC_CTRL "macctrl" +#define PRIV_CMD_GETWAP "getwap" +#define PRIV_CMD_REGION_CODE "regioncode" +#define PRIV_CMD_FWMACADDR "fwmacaddr" +#if defined(WIFI_DIRECT_SUPPORT) +#define PRIV_CMD_OFFCHANNEL "offchannel" +#endif +#if defined(STA_SUPPORT) +#define PRIV_CMD_PMFCFG "pmfcfg" +#endif +#define PRIV_CMD_INACTIVITYTO "inactivityto" /** Private command ID for Android default commands */ #define WOAL_ANDROID_DEF_CMD (SIOCDEVPRIVATE + 1) @@ -163,6 +183,10 @@ typedef struct _android_wifi_priv_cmd #define MW_MODE_MONITOR 6 /* Passive monitor (listen only) */ #define MW_MODE_MESH 7 /* Mesh (IEEE 802.11s) network */ +#define MW_POWER_TYPE 0xF000 /* Type of parameter */ +#define MW_POWER_PERIOD 0x1000 /* Value is a period/duration of */ +#define MW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */ + #define MW_AUTH_INDEX 0x0FFF #define MW_AUTH_FLAGS 0xF000 #define MW_AUTH_WPA_VERSION 0 diff --git a/drivers/net/wireless/sd8797/mlinux/moal_ioctl.c b/drivers/net/wireless/sd8797/mlinux/moal_ioctl.c index fa288c9ce517..07188725a47b 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_ioctl.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_ioctl.c @@ -80,13 +80,25 @@ static region_code_mapping_t region_code_mapping[] = { {"CN ", 0x50}, /* China */ {"JP ", 0xFF}, /* Japan special */ }; + +/** EEPROM Region code mapping table */ +static region_code_mapping_t hw_region_code_mapping[] = { + {"US ", 0x10}, /* US FCC */ + {"CA ", 0x20}, /* IC Canada */ + {"KR ", 0x30}, /* Korea */ + {"CN ", 0x50}, /* China */ + {"ES ", 0x31}, /* Spain */ + {"FR ", 0x32}, /* France */ + {"JP ", 0x40}, /* Japan */ + {"JP ", 0x41}, /* Japan */ +}; #endif /******************************************************** Global Variables ********************************************************/ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) #ifdef UAP_SUPPORT /** Network device handlers for uAP */ extern const struct net_device_ops woal_uap_netdev_ops; @@ -127,6 +139,40 @@ region_string_2_region_code(char *region_string) LEAVE(); return (region_code_mapping[0].code); } + +/** + * @brief This function converts region string to region code + * + * @param region_code region code + * + * @return Region string or NULL + */ +char * +region_code_2_string(t_u8 region_code) +{ + t_u8 i; + t_u8 size = sizeof(hw_region_code_mapping) / sizeof(region_code_mapping_t); + + ENTER(); + for (i = 0; i < size; i++) { + if (hw_region_code_mapping[i].code == region_code) { + LEAVE(); + return hw_region_code_mapping[i].region; + } + } + LEAVE(); + return NULL; +} + +t_u8 +woal_is_valid_alpha2(char *alpha2) +{ + if (!alpha2 || strlen(alpha2) < 2) + return MFALSE; + if (isalpha(alpha2[0]) && isalpha(alpha2[1])) + return MTRUE; + return MFALSE; +} #endif /** @@ -185,9 +231,11 @@ woal_fill_wait_queue(moal_private * priv, wait_queue * wait, t_u8 wait_option) case MOAL_CMD_WAIT: wait->wait = &priv->cmd_wait_q; break; +#ifdef CONFIG_PROC_FS case MOAL_PROC_WAIT: wait->wait = &priv->proc_wait_q; break; +#endif #if defined(STA_WEXT) || defined(UAP_WEXT) case MOAL_WSTATS_WAIT: if (IS_STA_OR_UAP_WEXT(cfg80211_wext)) @@ -221,18 +269,21 @@ woal_wait_ioctl_complete(moal_private * priv, mlan_ioctl_req * req, case MOAL_NO_WAIT: break; case MOAL_IOCTL_WAIT: - wait_event_interruptible(priv->ioctl_wait_q, wait->condition); + wait_event_interruptible_exclusive(priv->ioctl_wait_q, wait->condition); break; case MOAL_CMD_WAIT: - wait_event_interruptible(priv->cmd_wait_q, wait->condition); + wait_event_interruptible_exclusive(priv->cmd_wait_q, wait->condition); break; +#ifdef CONFIG_PROC_FS case MOAL_PROC_WAIT: - wait_event_interruptible(priv->proc_wait_q, wait->condition); + wait_event_interruptible_exclusive(priv->proc_wait_q, wait->condition); break; +#endif #if defined(STA_WEXT) || defined(UAP_WEXT) case MOAL_WSTATS_WAIT: if (IS_STA_OR_UAP_WEXT(cfg80211_wext)) - wait_event_interruptible(priv->w_stats_wait_q, wait->condition); + wait_event_interruptible_exclusive(priv->w_stats_wait_q, + wait->condition); break; #endif } @@ -394,7 +445,7 @@ woal_request_ioctl(moal_private * priv, mlan_ioctl_req * req, t_u8 wait_option) priv->phandle->cac_period == MTRUE) { t_u32 sub_command; /* CAC checking period left to complete jiffies */ - unsigned long cac_left_jiffies; + long cac_left_jiffies; sub_command = *(t_u32 *) req->pbuf; @@ -467,6 +518,7 @@ woal_request_ioctl(moal_private * priv, mlan_ioctl_req * req, t_u8 wait_option) req->reserved_1 = 0; /* Call MLAN ioctl handle */ + atomic_inc(&priv->phandle->ioctl_pending); spin_lock_irqsave(&priv->phandle->driver_lock, flags); status = mlan_ioctl(priv->phandle->pmlan_adapter, req); spin_unlock_irqrestore(&priv->phandle->driver_lock, flags); @@ -476,7 +528,6 @@ woal_request_ioctl(moal_private * priv, mlan_ioctl_req * req, t_u8 wait_option) "IOCTL pending: %p id=0x%x, sub_id=0x%x wait_option=%d, action=%d\n", req, req->req_id, (*(t_u32 *) req->pbuf), wait_option, (int) req->action); - atomic_inc(&priv->phandle->ioctl_pending); /* Status pending, wake up main process */ queue_work(priv->phandle->workqueue, &priv->phandle->main_work); @@ -494,6 +545,7 @@ woal_request_ioctl(moal_private * priv, mlan_ioctl_req * req, t_u8 wait_option) req, req->req_id, (*(t_u32 *) req->pbuf), wait_option, (int) req->action, status); default: + atomic_dec(&priv->phandle->ioctl_pending); break; } @@ -536,11 +588,6 @@ woal_request_set_mac_address(moal_private * priv) status = woal_request_ioctl(priv, req, MOAL_CMD_WAIT); if (status == MLAN_STATUS_SUCCESS) { memcpy(priv->netdev->dev_addr, priv->current_addr, ETH_ALEN); -#if defined(STA_CFG80211) || defined(UAP_CFG80211) - if (IS_STA_OR_UAP_CFG80211(cfg80211_wext) && priv->wdev && - priv->wdev->wiphy) - memcpy(priv->wdev->wiphy->perm_addr, priv->current_addr, ETH_ALEN); -#endif HEXDUMP("priv->MacAddr:", priv->current_addr, ETH_ALEN); } else { PRINTM(MERROR, "set mac address failed! status=%d, error_code=0x%x\n", @@ -673,8 +720,12 @@ woal_bss_start(moal_private * priv, t_u8 wait_option, ENTER(); - /* Stop the O.S. TX queue if needed */ + /* Stop the O.S. TX queue When we are roaming */ woal_stop_queue(priv->netdev); + if (priv->media_connected == MFALSE) { + if (netif_carrier_ok(priv->netdev)) + netif_carrier_off(priv->netdev); + } /* Allocate an IOCTL request buffer */ req = (mlan_ioctl_req *) woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss)); @@ -693,7 +744,11 @@ woal_bss_start(moal_private * priv, t_u8 wait_option, /* Send IOCTL request to MLAN */ status = woal_request_ioctl(priv, req, wait_option); - +#ifdef STA_CFG80211 +#ifdef STA_SUPPORT + priv->assoc_status = req->status_code; +#endif +#endif done: if (req) kfree(req); @@ -714,7 +769,6 @@ mlan_status woal_get_bss_info(moal_private * priv, t_u8 wait_option, mlan_bss_info * bss_info) { - int ret = 0; mlan_ioctl_req *req = NULL; mlan_ds_get_info *info = NULL; mlan_status status = MLAN_STATUS_SUCCESS; @@ -723,7 +777,8 @@ woal_get_bss_info(moal_private * priv, t_u8 wait_option, /* Allocate an IOCTL request buffer */ req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info)); if (req == NULL) { - ret = -ENOMEM; + PRINTM(MERROR, "Fail to allocate the buffer for get bss_info\n"); + status = MLAN_STATUS_FAILURE; goto done; } @@ -736,9 +791,8 @@ woal_get_bss_info(moal_private * priv, t_u8 wait_option, /* Send IOCTL request to MLAN */ status = woal_request_ioctl(priv, req, wait_option); if (status == MLAN_STATUS_SUCCESS) { - if (bss_info) { + if (bss_info) memcpy(bss_info, &info->param.bss_info, sizeof(mlan_bss_info)); - } } done: if (req && (status != MLAN_STATUS_PENDING)) @@ -1076,11 +1130,11 @@ woal_set_get_power_mgmt(moal_private * priv, pm_cfg->param.ps_mode = 0; else { /* Check not support case only (vwrq->disabled == FALSE) */ - if ((power_type & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { + if ((power_type & MW_POWER_TYPE) == MW_POWER_TIMEOUT) { PRINTM(MERROR, "Setting power timeout is not supported\n"); ret = MLAN_STATUS_FAILURE; goto done; - } else if ((power_type & IW_POWER_TYPE) == IW_POWER_PERIOD) { + } else if ((power_type & MW_POWER_TYPE) == MW_POWER_PERIOD) { PRINTM(MERROR, "Setting power period is not supported\n"); ret = MLAN_STATUS_FAILURE; goto done; @@ -1199,6 +1253,49 @@ woal_set_get_data_rate(moal_private * priv, LEAVE(); return ret; } + +/** + * @brief Get assoc_resp buffer + * + * @param priv A pointer to moal_private structure + * @param assoc_rsp A pointer to mlan_ds_misc_assoc_rsp structure + * + * @return MLAN_STATUS_SUCCESS -- success, otherwise fail + */ +mlan_status +woal_get_assoc_rsp(moal_private * priv, mlan_ds_misc_assoc_rsp * assoc_rsp) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + mlan_ds_misc_cfg *misc = NULL; + mlan_ioctl_req *req = NULL; + + ENTER(); + + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); + if (req == NULL) { + PRINTM(MERROR, "Fail to allocate buffer for get assoc resp\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + req->req_id = MLAN_IOCTL_MISC_CFG; + misc = (pmlan_ds_misc_cfg) req->pbuf; + misc->sub_command = MLAN_OID_MISC_ASSOC_RSP; + req->action = MLAN_ACT_GET; + + if (MLAN_STATUS_SUCCESS == woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + if (assoc_rsp) + memcpy(assoc_rsp, &misc->param.assoc_resp, + sizeof(mlan_ds_misc_assoc_rsp)); + } else { + ret = MLAN_STATUS_FAILURE; + } + done: + if (req) + kfree(req); + LEAVE(); + return ret; +} #endif /** @@ -1241,11 +1338,6 @@ woal_request_get_fw_info(moal_private * priv, t_u8 wait_option, memcpy(priv->current_addr, &info->param.fw_info.mac_addr, sizeof(mlan_802_11_mac_addr)); memcpy(priv->netdev->dev_addr, priv->current_addr, ETH_ALEN); -#if defined(STA_CFG80211) || defined(UAP_CFG80211) - if (IS_STA_OR_UAP_CFG80211(cfg80211_wext) && priv->wdev && - priv->wdev->wiphy) - memcpy(priv->wdev->wiphy->perm_addr, priv->current_addr, ETH_ALEN); -#endif if (fw_info) memcpy(fw_info, &info->param.fw_info, sizeof(mlan_fw_info)); DBG_HEXDUMP(MCMD_D, "mac", priv->current_addr, 6); @@ -1702,6 +1794,7 @@ woal_send_host_packet(struct net_device *dev, struct ifreq *req) /** * @brief Set/Get CUSTOM_IE ioctl handler * + * @param priv A pointer to moal_private structure * @param mask Mask to set or clear from caller * @param ie IE buffer to set for beacon * @param ie_len Length of the IE @@ -1780,7 +1873,6 @@ woal_get_bss_type(struct net_device *dev, struct ifreq *req) return ret; } -#if defined(WIFI_DIRECT_SUPPORT) #if defined(STA_SUPPORT) && defined(UAP_SUPPORT) /** * @brief Swithces BSS role of interface @@ -1838,7 +1930,7 @@ woal_bss_role_cfg(moal_private * priv, t_u8 action, if (*bss_role == MLAN_BSS_ROLE_UAP) { /* Switch: STA -> uAP */ /* Setup the OS Interface to our functions */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,29) dev->do_ioctl = woal_uap_do_ioctl; dev->set_multicast_list = woal_uap_set_multicast_list; #else @@ -1846,20 +1938,18 @@ woal_bss_role_cfg(moal_private * priv, t_u8 action, #endif #ifdef UAP_WEXT if (IS_UAP_WEXT(cfg80211_wext)) { -#ifdef WIRELESS_EXT #if WIRELESS_EXT < 21 dev->get_wireless_stats = woal_get_uap_wireless_stats; #endif dev->wireless_handlers = (struct iw_handler_def *) &woal_uap_handler_def; -#endif /* WIRELESS_EXT */ init_waitqueue_head(&priv->w_stats_wait_q); } #endif /* UAP_WEXT */ } else if (*bss_role == MLAN_BSS_ROLE_STA) { /* Switch: uAP -> STA */ /* Setup the OS Interface to our functions */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,29) dev->do_ioctl = woal_do_ioctl; dev->set_multicast_list = woal_set_multicast_list; #else @@ -1867,13 +1957,11 @@ woal_bss_role_cfg(moal_private * priv, t_u8 action, #endif #ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext)) { -#ifdef WIRELESS_EXT #if WIRELESS_EXT < 21 dev->get_wireless_stats = woal_get_wireless_stats; #endif dev->wireless_handlers = (struct iw_handler_def *) &woal_handler_def; -#endif init_waitqueue_head(&priv->w_stats_wait_q); } #endif /* STA_WEXT */ @@ -1911,9 +1999,11 @@ woal_set_get_bss_role(moal_private * priv, struct iwreq *wrq) ret = -EFAULT; goto done; } - if ((bss_role != MLAN_BSS_ROLE_STA && - bss_role != MLAN_BSS_ROLE_UAP) || - (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT)) { + if ((bss_role != MLAN_BSS_ROLE_STA && bss_role != MLAN_BSS_ROLE_UAP) +#if defined(WIFI_DIRECT_SUPPORT) + || (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT) +#endif + ) { PRINTM(MWARN, "Invalid BSS role\n"); ret = -EINVAL; goto done; @@ -1942,6 +2032,10 @@ woal_set_get_bss_role(moal_private * priv, struct iwreq *wrq) } wrq->u.data.length = 1; } else { +#if defined(STA_CFG80211) || defined(UAP_CFG80211) + if (IS_STA_OR_UAP_CFG80211(cfg80211_wext)) + woal_clear_all_mgmt_ies(priv); +#endif /* Initialize private structures */ woal_init_priv(priv, MOAL_IOCTL_WAIT); @@ -1956,7 +2050,71 @@ woal_set_get_bss_role(moal_private * priv, struct iwreq *wrq) } #endif /* STA_WEXT || UAP_WEXT */ #endif /* STA_SUPPORT && UAP_SUPPORT */ -#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */ + +/** + * @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->ip_addr_type != IPADDR_TYPE_NONE) { + memcpy(ipaddr_cfg.ip_addr[ipaddr_cfg.ip_addr_num], priv->ip_addr, + 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; + memcpy(&misc->param.ipaddr_cfg, &ipaddr_cfg, sizeof(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 (req && (ret != MLAN_STATUS_PENDING)) + kfree(req); + LEAVE(); + return ret; +} /** * @brief Get Host Sleep parameters @@ -2029,6 +2187,9 @@ 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); + /* remove auto arp from FW */ + woal_set_auto_arp(priv->phandle, MFALSE); + LEAVE(); return ret; } @@ -2062,9 +2223,45 @@ woal_enable_hs(moal_private * priv) hs_actived = MTRUE; goto done; } +#if defined(WIFI_DIRECT_SUPPORT) +#if defined(STA_CFG80211) && defined(UAP_CFG80211) + /* cancel pending remain on channel */ + if (priv->phandle->remain_on_channel) { + t_u8 channel_status; + moal_private *remain_priv = + priv->phandle->priv[priv->phandle->remain_bss_index]; + if (remain_priv) { + woal_cfg80211_remain_on_channel_cfg(remain_priv, MOAL_NO_WAIT, + MTRUE, &channel_status, NULL, 0, + 0); + if (priv->phandle->cookie) { + cfg80211_remain_on_channel_expired( +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) + remain_priv->netdev, +#else + remain_priv->wdev, +#endif + priv->phandle->cookie, + &priv->phandle->chan, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) + priv->phandle-> + channel_type, +#endif + GFP_ATOMIC); + priv->phandle->cookie = 0; + } + } + priv->phandle->remain_on_channel = MFALSE; + } +#endif +#endif + #ifdef STA_SUPPORT woal_reconfig_bgscan(priv->phandle); #endif + + /* Set auto arp response configuration to Fw */ + woal_set_auto_arp(handle, MTRUE); /* Enable Host Sleep */ handle->hs_activate_wait_q_woken = MFALSE; memset(&hscfg, 0, sizeof(mlan_ds_hs_cfg)); @@ -2117,6 +2314,7 @@ woal_enable_hs(moal_private * priv) } #endif +#ifdef CONFIG_PROC_FS /** * @brief This function send soft_reset command to firmware * @@ -2149,6 +2347,7 @@ woal_request_soft_reset(moal_handle * handle) LEAVE(); return ret; } +#endif /* CONFIG_PROC_FS */ /** * @brief Set wapi enable @@ -2216,7 +2415,7 @@ woal_get_version(moal_handle * handle, char *version, int max_len) snprintf(fw_ver, sizeof(fw_ver), "%u.%u.%u.p%u", ver.c[2], ver.c[1], ver.c[0], ver.c[3]); - snprintf(version, max_len, driver_version, fw_ver); + snprintf(version, max_len, handle->driver_version, fw_ver); LEAVE(); } @@ -2817,7 +3016,7 @@ woal_set_remain_channel_ioctl(moal_private * priv, t_u8 wait_option, sizeof(mlan_ds_remain_chan)); } done: - if (req) + if (req && (ret != MLAN_STATUS_PENDING)) kfree(req); LEAVE(); return ret; @@ -3141,10 +3340,8 @@ woal_find_best_network(moal_private * priv, t_u8 wait_option, if (ret == MLAN_STATUS_SUCCESS) { memcpy(ssid_bssid, &bss->param.ssid_bssid, sizeof(mlan_ssid_bssid)); mac = (t_u8 *) & ssid_bssid->bssid; - PRINTM(MINFO, - "Find network: ssid=%s, %02x:%02x:%02x:%02x:%02x:%02x, idx=%d\n", - ssid_bssid->ssid.ssid, mac[0], mac[1], mac[2], mac[3], mac[4], - mac[5], (int) ssid_bssid->idx); + PRINTM(MINFO, "Find network: ssid=%s, " MACSTR ", idx=%d\n", + ssid_bssid->ssid.ssid, MAC2STR(mac), (int) ssid_bssid->idx); } done: @@ -3513,11 +3710,54 @@ woal_request_userscan(moal_private * priv, } /** + * @brief woal_get_scan_config + * + * @param priv A pointer to moal_private structure + * @param scan_cfg A pointer to scan_cfg structure + * + * + * @return MLAN_STATUS_SUCCESS -- success, otherwise fail + */ +mlan_status +woal_get_scan_config(moal_private * priv, mlan_scan_cfg * scan_cfg) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + mlan_ds_scan *scan = NULL; + mlan_ioctl_req *req = NULL; + + ENTER(); + + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan)); + if (req == NULL) { + ret = MLAN_STATUS_FAILURE; + goto done; + } + scan = (mlan_ds_scan *) req->pbuf; + scan->sub_command = MLAN_OID_SCAN_CONFIG; + req->req_id = MLAN_IOCTL_SCAN; + req->action = MLAN_ACT_GET; + memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg)); + if (MLAN_STATUS_SUCCESS == woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + if (scan_cfg) { + memcpy(scan_cfg, &scan->param.scan_cfg, sizeof(mlan_scan_cfg)); + } + } else { + ret = MLAN_STATUS_FAILURE; + } + done: + if (req) + kfree(req); + LEAVE(); + return ret; +} + +/** * @brief set scan time * * @param priv A pointer to moal_private structure - * @param passive_scan_time passive scan time - * @param specific_scan_time specific scan time + * @param active_scan_time Active scan time + * @param passive_scan_time Passive scan time + * @param specific_scan_time Specific scan time * * @return MLAN_STATUS_SUCCESS -- success, otherwise fail */ @@ -3528,9 +3768,15 @@ woal_set_scan_time(moal_private * priv, t_u16 active_scan_time, mlan_status ret = MLAN_STATUS_SUCCESS; mlan_ds_scan *scan = NULL; mlan_ioctl_req *req = NULL; + mlan_scan_cfg scan_cfg; ENTER(); + memset(&scan_cfg, 0, sizeof(scan_cfg)); + if (MLAN_STATUS_SUCCESS != woal_get_scan_config(priv, &scan_cfg)) { + ret = MLAN_STATUS_FAILURE; + goto done; + } req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan)); if (req == NULL) { ret = MLAN_STATUS_FAILURE; @@ -3541,9 +3787,13 @@ woal_set_scan_time(moal_private * priv, t_u16 active_scan_time, req->req_id = MLAN_IOCTL_SCAN; req->action = MLAN_ACT_SET; memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg)); - scan->param.scan_cfg.scan_time.active_scan_time = active_scan_time; - scan->param.scan_cfg.scan_time.specific_scan_time = specific_scan_time; - scan->param.scan_cfg.scan_time.passive_scan_time = passive_scan_time; + scan_cfg.scan_time.active_scan_time = active_scan_time; + scan_cfg.scan_time.specific_scan_time = specific_scan_time; + scan_cfg.scan_time.passive_scan_time = passive_scan_time; + PRINTM(MIOCTL, "Set specific=%d, active=%d, passive=%d\n", + (int) active_scan_time, (int) passive_scan_time, + (int) specific_scan_time); + memcpy(&scan->param.scan_cfg, &scan_cfg, sizeof(mlan_scan_cfg)); if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) ret = MLAN_STATUS_FAILURE; done: @@ -3815,25 +4065,86 @@ woal_set_bg_scan(moal_private * priv, char *buf, int length) return ret; } +#ifdef STA_CFG80211 +/** + * @brief set bgscan and new rssi_low_threshold + * + * @param priv A pointer to moal_private structure + * @param set_rssi flag for set rssi_low_threshold + * + * @return N/A + */ +void +woal_config_bgscan_and_rssi(moal_private * priv, t_u8 set_rssi) +{ + char rssi_low[10]; + mlan_bss_info bss_info; + int band = 0; + + ENTER(); + memset(&bss_info, 0, sizeof(bss_info)); + woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info); + if (!bss_info.media_connected) { + PRINTM(MIOCTL, "We already lost connection\n"); + LEAVE(); + return; + } + memset(&priv->scan_cfg, 0, sizeof(priv->scan_cfg)); + strncpy(priv->scan_cfg.ssid_list[0].ssid, bss_info.ssid.ssid, + bss_info.ssid.ssid_len); + priv->scan_cfg.ssid_list[0].max_len = 0; + + priv->scan_cfg.report_condition = BG_SCAN_SSID_RSSI_MATCH; + priv->scan_cfg.rssi_threshold = priv->rssi_low - RSSI_HYSTERESIS; + priv->scan_cfg.repeat_count = DEF_REPEAT_COUNT; + priv->scan_cfg.scan_interval = MIN_BGSCAN_INTERVAL; + woal_get_band(priv, &band); + switch (band) { + case WIFI_FREQUENCY_BAND_2GHZ: + priv->scan_cfg.chan_list[0].radio_type = 0 | BAND_SPECIFIED; + break; + case WIFI_FREQUENCY_BAND_5GHZ: + priv->scan_cfg.chan_list[0].radio_type = 1 | BAND_SPECIFIED; + break; + default: + break; + } + priv->scan_cfg.bss_type = MLAN_BSS_MODE_INFRA; + priv->scan_cfg.action = BG_SCAN_ACT_SET; + priv->scan_cfg.enable = MTRUE; + woal_request_bgscan(priv, MOAL_NO_WAIT, &priv->scan_cfg); + if (set_rssi && + ((priv->rssi_low + RSSI_HYSTERESIS) <= LOWEST_RSSI_THRESHOLD)) { + priv->rssi_low += RSSI_HYSTERESIS; + sprintf(rssi_low, "%d", priv->rssi_low); + woal_set_rssi_low_threshold(priv, rssi_low, MOAL_NO_WAIT); + } + LEAVE(); +} +#endif + /** * @brief stop bg scan * * @param priv A pointer to moal_private structure + * @param wait_option wait option * * @return MLAN_STATUS_SUCCESS -- success, otherwise fail */ mlan_status -woal_stop_bg_scan(moal_private * priv) +woal_stop_bg_scan(moal_private * priv, t_u8 wait_option) { wlan_bgscan_cfg scan_cfg; + mlan_status ret = MLAN_STATUS_SUCCESS; ENTER(); memset(&scan_cfg, 0, sizeof(scan_cfg)); scan_cfg.action = BG_SCAN_ACT_SET; scan_cfg.enable = MFALSE; - return woal_request_bgscan(priv, MOAL_IOCTL_WAIT, &scan_cfg); + ret = woal_request_bgscan(priv, wait_option, &scan_cfg); LEAVE(); + return ret; } /** @@ -3865,12 +4176,13 @@ woal_reconfig_bgscan(moal_handle * handle) * @brief set rssi low threshold * * @param priv A pointer to moal_private structure - * @param rssi A pointer to low rssi + * @param rssi A pointer to low rssi + * @param wait_option Wait option * * @return MLAN_STATUS_SUCCESS -- success, otherwise fail */ mlan_status -woal_set_rssi_low_threshold(moal_private * priv, char *rssi) +woal_set_rssi_low_threshold(moal_private * priv, char *rssi, t_u8 wait_option) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_ioctl_req *req = NULL; @@ -3883,19 +4195,20 @@ woal_set_rssi_low_threshold(moal_private * priv, char *rssi) req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); if (req == NULL) { - ret = -ENOMEM; + ret = MLAN_STATUS_FAILURE; goto done; } misc = (mlan_ds_misc_cfg *) req->pbuf; req->req_id = MLAN_IOCTL_MISC_CFG; misc->sub_command = MLAN_OID_MISC_SUBSCRIBE_EVENT; req->action = MLAN_ACT_SET; + misc->param.subscribe_event.evt_action = SUBSCRIBE_EVT_ACT_BITWISE_SET; misc->param.subscribe_event.evt_bitmap = SUBSCRIBE_EVT_RSSI_LOW; misc->param.subscribe_event.evt_bitmap |= SUBSCRIBE_EVT_PRE_BEACON_LOST; misc->param.subscribe_event.pre_beacon_miss = DEFAULT_PRE_BEACON_MISS; if (MLAN_STATUS_SUCCESS != woal_atoi(&low_rssi, rssi)) { - ret = -EFAULT; + ret = MLAN_STATUS_FAILURE; goto done; } #ifdef STA_CFG80211 @@ -3903,12 +4216,13 @@ woal_set_rssi_low_threshold(moal_private * priv, char *rssi) #endif misc->param.subscribe_event.low_rssi = low_rssi; misc->param.subscribe_event.low_rssi_freq = 0; - if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { - ret = -EFAULT; + ret = woal_request_ioctl(priv, req, wait_option); + if (ret == MLAN_STATUS_FAILURE) { + PRINTM(MERROR, "request set rssi_low_threshold fail!\n"); goto done; } done: - if (req) + if (req && (ret != MLAN_STATUS_PENDING)) kfree(req); LEAVE(); return ret; @@ -3920,11 +4234,12 @@ woal_set_rssi_low_threshold(moal_private * priv, char *rssi) * * @param priv A pointer to moal_private structure * @param event_id event id. + * @param wait_option wait option * * @return MLAN_STATUS_SUCCESS -- success, otherwise fail */ mlan_status -woal_set_rssi_threshold(moal_private * priv, t_u32 event_id) +woal_set_rssi_threshold(moal_private * priv, t_u32 event_id, t_u8 wait_option) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_ioctl_req *req = NULL; @@ -3957,20 +4272,22 @@ woal_set_rssi_threshold(moal_private * priv, t_u32 event_id) req->req_id = MLAN_IOCTL_MISC_CFG; misc->sub_command = MLAN_OID_MISC_SUBSCRIBE_EVENT; req->action = MLAN_ACT_SET; + if (!event_id && !priv->cqm_rssi_thold && !priv->cqm_rssi_hyst) + misc->param.subscribe_event.evt_action = SUBSCRIBE_EVT_ACT_BITWISE_CLR; + else + misc->param.subscribe_event.evt_action = SUBSCRIBE_EVT_ACT_BITWISE_SET; misc->param.subscribe_event.evt_bitmap = SUBSCRIBE_EVT_RSSI_LOW | SUBSCRIBE_EVT_RSSI_HIGH; misc->param.subscribe_event.low_rssi_freq = 0; misc->param.subscribe_event.low_rssi = priv->last_rssi_low; misc->param.subscribe_event.high_rssi_freq = 0; misc->param.subscribe_event.high_rssi = priv->last_rssi_high; - PRINTM(MIOCTL, "rssi_low=%d, rssi_high=%d\n", (int) priv->last_rssi_low, - (int) priv->last_rssi_high); - if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { - ret = -EFAULT; - goto done; - } + PRINTM(MIOCTL, "rssi_low=%d, rssi_high=%d action=%d\n", + (int) priv->last_rssi_low, (int) priv->last_rssi_high, + misc->param.subscribe_event.evt_action); + ret = woal_request_ioctl(priv, req, wait_option); done: - if (req) + if (req && (ret != MLAN_STATUS_PENDING)) kfree(req); LEAVE(); return ret; @@ -4023,8 +4340,14 @@ woal_set_scan_type(moal_private * priv, t_u32 scan_type) mlan_status ret = MLAN_STATUS_SUCCESS; mlan_ds_scan *scan = NULL; mlan_ioctl_req *req = NULL; + mlan_scan_cfg scan_cfg; ENTER(); + memset(&scan_cfg, 0, sizeof(scan_cfg)); + if (MLAN_STATUS_SUCCESS != woal_get_scan_config(priv, &scan_cfg)) { + ret = MLAN_STATUS_FAILURE; + goto done; + } req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan)); if (req == NULL) { @@ -4036,8 +4359,54 @@ woal_set_scan_type(moal_private * priv, t_u32 scan_type) req->req_id = MLAN_IOCTL_SCAN; req->action = MLAN_ACT_SET; memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg)); - scan->param.scan_cfg.scan_type = scan_type; + scan_cfg.scan_type = scan_type; + PRINTM(MIOCTL, "Set scan_type=%d\n", (int) scan_type); + memcpy(&scan->param.scan_cfg, &scan_cfg, sizeof(mlan_scan_cfg)); + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) + ret = MLAN_STATUS_FAILURE; + done: + if (req) + kfree(req); + LEAVE(); + return ret; +} +/** + * @brief enable/disable ext_scan + * + * @param priv A pointer to moal_private structure + * @param enable MTRUE -- enable, MFALSE --disable + * + * @return MLAN_STATUS_SUCCESS -- success, otherwise fail + */ +mlan_status +woal_enable_ext_scan(moal_private * priv, t_u8 enable) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + mlan_ds_scan *scan = NULL; + mlan_ioctl_req *req = NULL; + mlan_scan_cfg scan_cfg; + + ENTER(); + memset(&scan_cfg, 0, sizeof(scan_cfg)); + if (MLAN_STATUS_SUCCESS != woal_get_scan_config(priv, &scan_cfg)) { + ret = MLAN_STATUS_FAILURE; + goto done; + } + + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan)); + if (req == NULL) { + ret = MLAN_STATUS_FAILURE; + goto done; + } + scan = (mlan_ds_scan *) req->pbuf; + scan->sub_command = MLAN_OID_SCAN_CONFIG; + req->req_id = MLAN_IOCTL_SCAN; + req->action = MLAN_ACT_SET; + memset(&scan->param.scan_cfg, 0, sizeof(mlan_scan_cfg)); + scan_cfg.ext_scan = enable; + PRINTM(MIOCTL, "Set ext_scan=%d\n", (int) enable); + memcpy(&scan->param.scan_cfg, &scan_cfg, sizeof(mlan_scan_cfg)); if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) ret = MLAN_STATUS_FAILURE; done: @@ -4418,15 +4787,16 @@ woal_remove_rxfilter(moal_private * priv, char *rxfilter) } /** - * @brief Set QoS configuration + * @brief Set/Get WMM IE QoS configuration * * @param priv A pointer to moal_private structure + * @param action Action set or get * @param qos_cfg A pointer to QoS configuration structure * * @return MLAN_STATUS_SUCCESS -- success, otherwise fail */ mlan_status -woal_set_qos_cfg(moal_private * priv, char *qos_cfg) +woal_priv_qos_cfg(moal_private * priv, t_u32 action, char *qos_cfg) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_ds_wmm_cfg *cfg = NULL; @@ -4434,11 +4804,16 @@ woal_set_qos_cfg(moal_private * priv, char *qos_cfg) int qosinfo = 0; ENTER(); - if (MLAN_STATUS_SUCCESS != woal_atoi(&qosinfo, qos_cfg)) { + + if (qos_cfg == NULL) { + PRINTM(MERROR, "QOS info buffer is null\n"); + return MLAN_STATUS_FAILURE; + } + if ((action == MLAN_ACT_SET) && + (MLAN_STATUS_SUCCESS != woal_atoi(&qosinfo, qos_cfg))) { ret = MLAN_STATUS_FAILURE; goto done; } - PRINTM(MIOCTL, "set qosinfo=%d\n", qosinfo); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wmm_cfg)); if (req == NULL) { ret = MLAN_STATUS_FAILURE; @@ -4447,10 +4822,15 @@ woal_set_qos_cfg(moal_private * priv, char *qos_cfg) cfg = (mlan_ds_wmm_cfg *) req->pbuf; cfg->sub_command = MLAN_OID_WMM_CFG_QOS; req->req_id = MLAN_IOCTL_WMM_CFG; - req->action = MLAN_ACT_SET; - cfg->param.qos_cfg = (t_u8) qosinfo; + req->action = action; + if (action == MLAN_ACT_SET) { + cfg->param.qos_cfg = (t_u8) qosinfo; + PRINTM(MIOCTL, "set qosinfo=%d\n", qosinfo); + } if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) ret = MLAN_STATUS_FAILURE; + if (action == MLAN_ACT_GET) + *qos_cfg = cfg->param.qos_cfg; done: if (req) kfree(req); diff --git a/drivers/net/wireless/sd8797/mlinux/moal_main.c b/drivers/net/wireless/sd8797/mlinux/moal_main.c index 2bc1ba28b5db..293782ef5d69 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_main.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_main.c @@ -43,8 +43,6 @@ Change log: #include "moal_uap_cfg80211.h" #endif #endif -#include <linux/platform_device.h> -#include <linux/wlan_plat.h> #include "moal_eth_ioctl.h" #include <linux/if_ether.h> @@ -68,6 +66,11 @@ char driver_version[] = #endif " "; +/** SD8797 Card */ +#define CARD_SD8797 "SD8797" +/** SD8782 Card */ +#define CARD_SD8782 "SD8782" + /** Firmware name */ char *fw_name = NULL; int req_fw_nowait = 0; @@ -113,6 +116,10 @@ char *uap_name = NULL; int max_wfd_bss = DEF_WIFIDIRECT_BSS; /** WIFIDIRECT interface name */ char *wfd_name = NULL; +#if defined(STA_CFG80211) && defined(UAP_CFG80211) +/** max VIRTUAL bss */ +int max_vir_bss = DEF_VIRTUAL_BSS; +#endif #endif #ifdef SDIO_SUSPEND_RESUME @@ -130,19 +137,21 @@ char *cal_data_cfg = NULL; /** Init config file (MAC address, register etc.) */ char *init_cfg = NULL; -/** Enable minicard power-up/down */ -int minicard_pwrup = 1; -/** Pointer to struct with control hooks */ -struct wifi_platform_data *wifi_control_data = NULL; - +#if defined(STA_WEXT) || defined(UAP_WEXT) /** CFG80211 and WEXT mode */ int cfg80211_wext = STA_WEXT_MASK | UAP_WEXT_MASK; +#else +/** CFG80211 and WEXT mode */ +int cfg80211_wext = STA_CFG80211_MASK | UAP_CFG80211_MASK; +#endif /** Work queue priority */ int wq_sched_prio = 0; /** Work queue scheduling policy */ int wq_sched_policy = SCHED_NORMAL; +int hw_test = 0; + /** woal_callbacks */ static mlan_callbacks woal_callbacks = { .moal_get_fw_data = moal_get_fw_data, @@ -154,12 +163,15 @@ static mlan_callbacks woal_callbacks = { .moal_ioctl_complete = moal_ioctl_complete, .moal_alloc_mlan_buffer = moal_alloc_mlan_buffer, .moal_free_mlan_buffer = moal_free_mlan_buffer, + .moal_write_reg = moal_write_reg, .moal_read_reg = moal_read_reg, .moal_write_data_sync = moal_write_data_sync, .moal_read_data_sync = moal_read_data_sync, .moal_malloc = moal_malloc, .moal_mfree = moal_mfree, + .moal_vmalloc = moal_vmalloc, + .moal_vfree = moal_vfree, .moal_memset = moal_memset, .moal_memcpy = moal_memcpy, .moal_memmove = moal_memmove, @@ -201,10 +213,6 @@ int drv_mode = DRV_MODE_UAP; /** Semaphore for add/remove card */ struct semaphore AddRemoveCardSem; /** - * the maximum number of adapter supported - **/ -#define MAX_MLAN_ADAPTER 2 -/** * The global variable of a pointer to moal_handle * structure variable **/ @@ -217,6 +225,7 @@ moal_handle *m_handle[MAX_MLAN_ADAPTER]; #define DEFAULT_DEBUG_MASK (MMSG | MFATAL | MERROR) #endif /* DEBUG_LEVEL2 */ t_u32 drvdbg = DEFAULT_DEBUG_MASK; + #endif /* DEBUG_LEVEL1 */ int woal_open(struct net_device *dev); @@ -224,12 +233,97 @@ int woal_close(struct net_device *dev); int woal_set_mac_address(struct net_device *dev, void *addr); void woal_tx_timeout(struct net_device *dev); struct net_device_stats *woal_get_stats(struct net_device *dev); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) u16 woal_select_queue(struct net_device *dev, struct sk_buff *skb); #endif mlan_debug_info info; +static int woal_netdevice_event(struct notifier_block *nb, unsigned long event, + void *ptr); +static struct notifier_block woal_notifier = { + .notifier_call = woal_netdevice_event +}; + +/** + * @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[10]; +#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 +#if defined(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 */ + memcpy(priv->ip_addr, &ifa->ifa_address, sizeof(ifa->ifa_address)); + priv->ip_addr_type = IPADDR_TYPE_IPV4; +#ifdef STA_CFG80211 + if (!hw_test && priv->roaming_enabled) { + sprintf(rssi_low, "%d", priv->rssi_low); + woal_set_rssi_low_threshold(priv, rssi_low, MOAL_CMD_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; +} + /** * @brief This function validates a SSID as being able to be printed * @@ -281,6 +375,53 @@ woal_go_timer_func(void *context) #endif #endif +/** + * @brief check if we already connect to the AP. + * @param priv A pointer to moal_private structure + * @param ssid_bssid A pointer to mlan_ssid_bssid structure + * + * @return MTRUE/MFALSE; + */ +int +woal_is_connected(moal_private * priv, mlan_ssid_bssid * ssid_bssid) +{ + mlan_bss_info bss_info; + int ret = MFALSE; + t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 }; + ENTER(); + memset(&bss_info, 0, sizeof(bss_info)); + if (MLAN_STATUS_SUCCESS != + woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) + goto done; + if (bss_info.media_connected) { + if (memcmp(ssid_bssid->bssid, zero_mac, sizeof(zero_mac))) { + if (ssid_bssid->ssid.ssid_len) { // compare ssid and bssid + if ((ssid_bssid->ssid.ssid_len == bss_info.ssid.ssid_len) && + !memcmp(ssid_bssid->ssid.ssid, bss_info.ssid.ssid, + bss_info.ssid.ssid_len) && + !memcmp(ssid_bssid->bssid, bss_info.bssid, + MLAN_MAC_ADDR_LENGTH)) + ret = MTRUE; + } else { // compare bssid + if (!memcmp + (ssid_bssid->bssid, bss_info.bssid, MLAN_MAC_ADDR_LENGTH)) { + ret = MTRUE; + } + } + } else { // compare ssid + if (ssid_bssid->ssid.ssid_len && + (ssid_bssid->ssid.ssid_len == bss_info.ssid.ssid_len) && + !memcmp(ssid_bssid->ssid.ssid, bss_info.ssid.ssid, + bss_info.ssid.ssid_len)) { + ret = MTRUE; + } + } + } + done: + LEAVE(); + return ret; +} + /** * @brief Get mode * @@ -321,13 +462,13 @@ woal_get_mode(moal_private * priv, t_u8 wait_option) if (status == MLAN_STATUS_SUCCESS) { switch (bss->param.bss_mode) { case MLAN_BSS_MODE_INFRA: - mode = IW_MODE_INFRA; + mode = MW_MODE_INFRA; break; case MLAN_BSS_MODE_IBSS: - mode = IW_MODE_ADHOC; + mode = MW_MODE_ADHOC; break; default: - mode = IW_MODE_AUTO; + mode = MW_MODE_AUTO; break; } } @@ -357,6 +498,11 @@ woal_update_drv_tbl(moal_handle * handle, int drv_mode_local) unsigned int intf_num = 0; int i = 0, j = 0; mlan_bss_attr *bss_tbl = NULL; +#if defined(WIFI_DIRECT_SUPPORT) +#if defined(STA_CFG80211) && defined(UAP_CFG80211) + int last_wfd_index = 0; +#endif +#endif ENTER(); @@ -391,6 +537,9 @@ woal_update_drv_tbl(moal_handle * handle, int drv_mode_local) max_wfd_bss = DEF_WIFIDIRECT_BSS; } intf_num += max_wfd_bss; +#if defined(STA_CFG80211) && defined(UAP_CFG80211) + intf_num += max_vir_bss; +#endif } #endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */ @@ -422,6 +571,7 @@ woal_update_drv_tbl(moal_handle * handle, int drv_mode_local) bss_tbl[i].active = MTRUE; bss_tbl[i].bss_priority = 0; bss_tbl[i].bss_num = j; + bss_tbl[i].bss_virtual = MFALSE; i++; } } @@ -437,6 +587,7 @@ woal_update_drv_tbl(moal_handle * handle, int drv_mode_local) bss_tbl[i].active = MTRUE; bss_tbl[i].bss_priority = 0; bss_tbl[i].bss_num = j; + bss_tbl[i].bss_virtual = MFALSE; i++; } } @@ -452,11 +603,31 @@ woal_update_drv_tbl(moal_handle * handle, int drv_mode_local) bss_tbl[i].active = MTRUE; bss_tbl[i].bss_priority = 0; bss_tbl[i].bss_num = j; + bss_tbl[i].bss_virtual = MFALSE; i++; } +#if defined(STA_CFG80211) && defined(UAP_CFG80211) + last_wfd_index = j; +#endif } #endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */ +#if defined(WIFI_DIRECT_SUPPORT) +#if defined(STA_CFG80211) && defined(UAP_CFG80211) + /** append virtual interface at the end of table */ + for (j = 0; j < max_vir_bss; j++) { + if (i >= intf_num) + break; + bss_tbl[i].bss_type = MLAN_BSS_TYPE_WIFIDIRECT; + bss_tbl[i].frame_type = MLAN_DATA_FRAME_TYPE_ETH_II; + bss_tbl[i].active = MTRUE; + bss_tbl[i].bss_priority = 0; + bss_tbl[i].bss_num = j + last_wfd_index; + bss_tbl[i].bss_virtual = MTRUE; + i++; + } +#endif +#endif /* Clear existing table, if any */ if (handle->drv_mode.bss_attr != NULL) { kfree(handle->drv_mode.bss_attr); @@ -471,12 +642,21 @@ woal_update_drv_tbl(moal_handle * handle, int drv_mode_local) handle->drv_mode.fw_name = fw_name; } else { #if defined(UAP_SUPPORT) && defined(STA_SUPPORT) - handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME; + if (handle->card_type == CARD_TYPE_SD8782) + handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME_8782; + else + handle->drv_mode.fw_name = DEFAULT_AP_STA_FW_NAME; #else #ifdef UAP_SUPPORT - handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME; + if (handle->card_type == CARD_TYPE_SD8782) + handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME_8782; + else + handle->drv_mode.fw_name = DEFAULT_AP_FW_NAME; #else - handle->drv_mode.fw_name = DEFAULT_FW_NAME; + if (handle->card_type == CARD_TYPE_SD8782) + handle->drv_mode.fw_name = DEFAULT_FW_NAME_8782; + else + handle->drv_mode.fw_name = DEFAULT_FW_NAME; #endif /* UAP_SUPPORT */ #endif /* UAP_SUPPORT && STA_SUPPORT */ } @@ -522,6 +702,13 @@ woal_init_sw(moal_handle * handle) } #endif /* STA_SUPPORT */ + /* Update driver version */ + if (handle->card_type == CARD_TYPE_SD8782) + memcpy(driver_version, CARD_SD8782, strlen(CARD_SD8782)); + else if (handle->card_type == CARD_TYPE_SD8797) + memcpy(driver_version, CARD_SD8797, strlen(CARD_SD8797)); + memcpy(handle->driver_version, driver_version, strlen(driver_version)); + if (woal_update_drv_tbl(handle, drv_mode) != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "Could not update driver mode table\n"); LEAVE(); @@ -531,7 +718,7 @@ woal_init_sw(moal_handle * handle) /* PnP and power profile */ handle->surprise_removed = MFALSE; init_waitqueue_head(&handle->init_wait_q); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) spin_lock_init(&handle->queue_lock); #endif spin_lock_init(&handle->driver_lock); @@ -577,6 +764,7 @@ woal_init_sw(moal_handle * handle) woal_initialize_timer(&handle->go_timer, woal_go_timer_func, handle); handle->is_go_timer_set = MFALSE; + handle->remain_on_channel = MFALSE; #endif #endif @@ -612,6 +800,9 @@ woal_init_sw(moal_handle * handle) device.mpa_rx_cfg = MLAN_INIT_PARA_DISABLED; #endif #endif + device.feature_control = FEATURE_CTRL_DEFAULT; + if (handle->card_type == CARD_TYPE_SD8782) + device.feature_control = 0; for (i = 0; i < handle->drv_mode.intf_num; i++) { device.bss_attr[i].bss_type = handle->drv_mode.bss_attr[i].bss_type; @@ -620,6 +811,8 @@ woal_init_sw(moal_handle * handle) device.bss_attr[i].bss_priority = handle->drv_mode.bss_attr[i].bss_priority; device.bss_attr[i].bss_num = handle->drv_mode.bss_attr[i].bss_num; + device.bss_attr[i].bss_virtual = + handle->drv_mode.bss_attr[i].bss_virtual; } memcpy(&device.callbacks, &woal_callbacks, sizeof(mlan_callbacks)); @@ -650,6 +843,15 @@ woal_free_moal_handle(moal_handle * handle) LEAVE(); return; } +#if defined(STA_CFG80211) || defined(UAP_CFG80211) + /* Unregister wiphy device and free */ + if (handle->wiphy) { + wiphy_unregister(handle->wiphy); + wiphy_free(handle->wiphy); + handle->wiphy = NULL; + } +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) if ((handle->nl_sk) && ((handle->nl_sk)->sk_socket)) { sock_release((handle->nl_sk)->sk_socket); @@ -846,6 +1048,18 @@ woal_process_init_cfg(moal_handle * handle, t_u8 * data, t_size size) bss_mac_name, bss_mac_addr); woal_mac2u8(handle->priv[i]->current_addr, bss_mac_addr); +#if defined(WIFI_DIRECT_SUPPORT) +#if defined(STA_CFG80211) && defined(UAP_CFG80211) +#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION + if (handle->priv[i]->bss_type == + MLAN_BSS_TYPE_WIFIDIRECT) { + handle->priv[i]->current_addr[0] |= 0x02; + PRINTM(MCMND, "Set WFD device addr: " MACSTR "\n", + MAC2STR(handle->priv[i]->current_addr)); + } +#endif +#endif +#endif /* Set WLAN MAC addresses */ if (MLAN_STATUS_SUCCESS != woal_request_set_mac_address(handle->priv[i])) { @@ -878,11 +1092,8 @@ woal_process_init_cfg(moal_handle * handle, t_u8 * data, t_size size) goto done; } intf_s = intf_e + 1; - if (intf_s != NULL) - intf_e = strchr(intf_s, ','); - else - intf_e = NULL; - if (intf_s != NULL && intf_e != NULL) { + intf_e = strchr(intf_s, ','); + if (intf_e != NULL) { if ((intf_e - intf_s) >= MAX_PARAM_LEN) { PRINTM(MERROR, "Regsier offset is too long %d\n", __LINE__); goto done; @@ -895,17 +1106,12 @@ woal_process_init_cfg(moal_handle * handle, t_u8 * data, t_size size) goto done; } intf_s = intf_e + 1; - if (intf_s != NULL) { - if ((strlen(intf_s) >= MAX_PARAM_LEN)) { - PRINTM(MERROR, "Regsier value is too long %d\n", __LINE__); - goto done; - } - /* Copy value */ - strncpy(value, intf_s, sizeof(value)); - } else { - PRINTM(MERROR, "Wrong config file format %d\n", __LINE__); + if ((strlen(intf_s) >= MAX_PARAM_LEN)) { + PRINTM(MERROR, "Regsier value is too long %d\n", __LINE__); goto done; } + /* Copy value */ + strncpy(value, intf_s, strlen(intf_s)); if (MLAN_STATUS_SUCCESS != woal_process_regrdwr(handle, type, offset, value)) { @@ -990,13 +1196,15 @@ woal_add_card_dpc(moal_handle * handle) /* Add interfaces */ for (i = 0; i < handle->drv_mode.intf_num; i++) { + if (handle->drv_mode.bss_attr[i].bss_virtual) + continue; if (!woal_add_interface (handle, handle->priv_num, handle->drv_mode.bss_attr[i].bss_type)) { ret = MLAN_STATUS_FAILURE; goto err; } - handle->priv_num++; } + register_inetaddr_notifier(&woal_notifier); if (init_cfg) { if (MLAN_STATUS_SUCCESS != woal_set_user_init_data(handle)) { PRINTM(MFATAL, "Set user init data and param failed\n"); @@ -1004,10 +1212,10 @@ woal_add_card_dpc(moal_handle * handle) goto err; } } - err: if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "Failed to add interface\n"); + unregister_inetaddr_notifier(&woal_notifier); for (i = 0; i < handle->priv_num; i++) woal_remove_interface(handle, i); handle->priv_num = 0; @@ -1181,29 +1389,9 @@ woal_request_fw(moal_handle * handle) { mlan_status ret = MLAN_STATUS_SUCCESS; int err; - t_u32 revision_id = 0; ENTER(); - if (!fw_name) { -/** Revision ID register */ -#define REV_ID_REG 0x5c - sdio_claim_host(((struct sdio_mmc_card *) handle->card)->func); - woal_read_reg(handle, REV_ID_REG, &revision_id); - sdio_release_host(((struct sdio_mmc_card *) handle->card)->func); - /* Check revision ID */ - switch (revision_id) { - case SD8797_A0: - handle->drv_mode.fw_name = SD8797_A0_FW_NAME; - break; - case SD8797_B0: - handle->drv_mode.fw_name = SD8797_B0_FW_NAME; - break; - default: - break; - } - } - if (req_fw_nowait) { #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32) if ((err = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, @@ -1346,7 +1534,7 @@ static struct device_type wlan_type = {.name = "wlan", }; #endif #ifdef STA_SUPPORT -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) /** Network device handlers */ const struct net_device_ops woal_netdev_ops = { .ndo_open = woal_open, @@ -1374,13 +1562,13 @@ const struct net_device_ops woal_netdev_ops = { * * @return MLAN_STATUS_SUCCESS */ -static mlan_status +mlan_status woal_init_sta_dev(struct net_device *dev, moal_private * priv) { ENTER(); /* Setup the OS Interface to our functions */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,29) dev->open = woal_open; dev->hard_start_xmit = woal_hard_start_xmit; dev->stop = woal_close; @@ -1393,8 +1581,8 @@ woal_init_sta_dev(struct net_device *dev, moal_private * priv) dev->netdev_ops = &woal_netdev_ops; #endif dev->watchdog_timeo = MRVDRV_DEFAULT_WATCHDOG_TIMEOUT; - dev->hard_header_len += MLAN_MIN_DATA_HEADER_LEN + sizeof(mlan_buffer); -#ifdef WIRELESS_EXT + dev->hard_header_len += MLAN_MIN_DATA_HEADER_LEN + sizeof(mlan_buffer) + + priv->extra_tx_head_len; #ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext)) { #if WIRELESS_EXT < 21 @@ -1403,13 +1591,14 @@ woal_init_sta_dev(struct net_device *dev, moal_private * priv) dev->wireless_handlers = (struct iw_handler_def *) &woal_handler_def; } #endif -#endif dev->flags |= IFF_BROADCAST | IFF_MULTICAST; /* Initialize private structure */ init_waitqueue_head(&priv->ioctl_wait_q); init_waitqueue_head(&priv->cmd_wait_q); +#ifdef CONFIG_PROC_FS init_waitqueue_head(&priv->proc_wait_q); +#endif #ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext)) init_waitqueue_head(&priv->w_stats_wait_q); @@ -1421,7 +1610,7 @@ woal_init_sta_dev(struct net_device *dev, moal_private * priv) #endif /* STA_SUPPORT */ #ifdef UAP_SUPPORT -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) /** Network device handlers */ const struct net_device_ops woal_uap_netdev_ops = { .ndo_open = woal_open, @@ -1449,7 +1638,7 @@ const struct net_device_ops woal_uap_netdev_ops = { * * @return MLAN_STATUS_SUCCESS */ -static mlan_status +mlan_status woal_init_uap_dev(struct net_device *dev, moal_private * priv) { mlan_status status = MLAN_STATUS_SUCCESS; @@ -1457,7 +1646,7 @@ woal_init_uap_dev(struct net_device *dev, moal_private * priv) ENTER(); /* Setup the OS Interface to our functions */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,29) dev->open = woal_open; dev->hard_start_xmit = woal_hard_start_xmit; dev->stop = woal_close; @@ -1470,9 +1659,9 @@ woal_init_uap_dev(struct net_device *dev, moal_private * priv) dev->netdev_ops = &woal_uap_netdev_ops; #endif dev->watchdog_timeo = MRVDRV_DEFAULT_UAP_WATCHDOG_TIMEOUT; - dev->hard_header_len += MLAN_MIN_DATA_HEADER_LEN + sizeof(mlan_buffer); + dev->hard_header_len += MLAN_MIN_DATA_HEADER_LEN + sizeof(mlan_buffer) + + priv->extra_tx_head_len; #ifdef UAP_WEXT -#ifdef WIRELESS_EXT if (IS_UAP_WEXT(cfg80211_wext)) { #if WIRELESS_EXT < 21 dev->get_wireless_stats = woal_get_uap_wireless_stats; @@ -1480,14 +1669,15 @@ woal_init_uap_dev(struct net_device *dev, moal_private * priv) dev->wireless_handlers = (struct iw_handler_def *) &woal_uap_handler_def; } -#endif /* WIRELESS_EXT */ #endif /* UAP_WEXT */ dev->flags |= IFF_BROADCAST | IFF_MULTICAST; /* Initialize private structure */ init_waitqueue_head(&priv->ioctl_wait_q); init_waitqueue_head(&priv->cmd_wait_q); +#ifdef CONFIG_PROC_FS init_waitqueue_head(&priv->proc_wait_q); +#endif #ifdef UAP_WEXT if (IS_UAP_WEXT(cfg80211_wext)) init_waitqueue_head(&priv->w_stats_wait_q); @@ -1517,7 +1707,7 @@ woal_add_interface(moal_handle * handle, t_u8 bss_index, t_u8 bss_type) ENTER(); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) #define MAX_WMM_QUEUE 4 /* Allocate an Ethernet device */ if (!(dev = alloc_etherdev_mq(sizeof(moal_private), MAX_WMM_QUEUE))) { @@ -1574,6 +1764,7 @@ woal_add_interface(moal_handle * handle, t_u8 bss_index, t_u8 bss_type) priv->netdev = dev; priv->bss_index = bss_index; priv->bss_type = bss_type; + priv->extra_tx_head_len = 0; if (bss_type == MLAN_BSS_TYPE_STA) priv->bss_role = MLAN_BSS_ROLE_STA; else if (bss_type == MLAN_BSS_TYPE_UAP) @@ -1584,6 +1775,7 @@ woal_add_interface(moal_handle * handle, t_u8 bss_index, t_u8 bss_type) #endif INIT_LIST_HEAD(&priv->tcp_sess_queue); + spin_lock_init(&priv->tcp_sess_lock); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) SET_MODULE_OWNER(dev); @@ -1602,6 +1794,16 @@ woal_add_interface(moal_handle * handle, t_u8 bss_index, t_u8 bss_type) goto error; } #endif + handle->priv_num++; +#if defined(STA_CFG80211) || defined(UAP_CFG80211) + if (!priv->phandle->wiphy && IS_STA_OR_UAP_CFG80211(cfg80211_wext)) { + if (woal_register_cfg80211(priv)) { + PRINTM(MERROR, "Cannot register with cfg80211\n"); + goto error; + } + } +#endif + #ifdef STA_CFG80211 #ifdef STA_SUPPORT if ((priv->bss_role == MLAN_BSS_ROLE_STA) && IS_STA_CFG80211(cfg80211_wext)) { @@ -1635,7 +1837,7 @@ woal_add_interface(moal_handle * handle, t_u8 bss_index, t_u8 bss_type) /* Initialize priv structure */ woal_init_priv(priv, MOAL_CMD_WAIT); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) SET_NETDEV_DEV(dev, handle->hotplug_device); #endif @@ -1656,6 +1858,18 @@ woal_add_interface(moal_handle * handle, t_u8 bss_index, t_u8 bss_type) if (handle->set_mac_addr) { memset(priv->current_addr, 0, ETH_ALEN); memcpy(priv->current_addr, handle->mac_addr, ETH_ALEN); +#if defined(WIFI_DIRECT_SUPPORT) +#if defined(STA_CFG80211) && defined(UAP_CFG80211) +#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION + if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) { + priv->current_addr[0] |= 0x02; + PRINTM(MCMND, "Set WFD device addr: " MACSTR "\n", + MAC2STR(priv->current_addr)); + } +#endif +#endif +#endif + if (MLAN_STATUS_SUCCESS != woal_request_set_mac_address(priv)) { PRINTM(MERROR, "Set MAC address failed\n"); goto error; @@ -1672,18 +1886,17 @@ woal_add_interface(moal_handle * handle, t_u8 bss_index, t_u8 bss_type) LEAVE(); return priv; error: - if (dev && dev->reg_state == NETREG_REGISTERED) - unregister_netdev(dev); + handle->priv_num = bss_index; #if defined(STA_CFG80211) || defined(UAP_CFG80211) /* Unregister wiphy device and free */ - if (priv->wdev && IS_STA_OR_UAP_CFG80211(cfg80211_wext)) { - wiphy_unregister(priv->wdev->wiphy); - wiphy_free(priv->wdev->wiphy); - /* Free wireless device */ - kfree(priv->wdev); - priv->wdev = NULL; + if (priv) { + if (priv->wdev && IS_STA_OR_UAP_CFG80211(cfg80211_wext)) { + priv->wdev = NULL; + } } #endif + if (dev && dev->reg_state == NETREG_REGISTERED) + unregister_netdev(dev); if (dev) free_netdev(dev); LEAVE(); @@ -1723,6 +1936,8 @@ woal_remove_interface(moal_handle * handle, t_u8 bss_index) } #endif } + woal_flush_tcp_sess_queue(priv); + #ifdef CONFIG_PROC_FS #ifdef PROC_DEBUG /* Remove proc debug */ @@ -1745,10 +1960,6 @@ woal_remove_interface(moal_handle * handle, t_u8 bss_index) #if defined(STA_CFG80211) || defined(UAP_CFG80211) /* Unregister wiphy device and free */ if (priv->wdev && IS_STA_OR_UAP_CFG80211(cfg80211_wext)) { - wiphy_unregister(priv->wdev->wiphy); - wiphy_free(priv->wdev->wiphy); - /* Free wireless device */ - kfree(priv->wdev); priv->wdev = NULL; } #endif @@ -1825,7 +2036,7 @@ woal_hexval(char chr) return 0; } -#ifdef STA_WEXT +#ifdef STA_SUPPORT #endif /** @@ -1851,138 +2062,6 @@ woal_terminate_workqueue(moal_handle * handle) LEAVE(); } -/* Support for Cardhu wifi gpio toggling */ -/** - * @brief Sets the card detect state - * - * @param on 0: Card will be made undetected - * 1: Card will be detected - * - * @return 0 - */ -static int -wifi_set_carddetect(int on) -{ - ENTER(); - PRINTM(MMSG, "%s = %d\n", __FUNCTION__, on); - if (wifi_control_data && wifi_control_data->set_carddetect) { - wifi_control_data->set_carddetect(on); - } - LEAVE(); - return 0; -} - -/** - * @brief Sets the power state to On or Off after 'msec' millisecond - * - * @param on 0: Card will be powered on - * 1: Card will be powered off - * @param msec Delay in millisecond - * - * @return 0 - */ -static int -wifi_set_power(int on, unsigned long msec) -{ - ENTER(); - PRINTM(MMSG, "%s = %d\n", __FUNCTION__, on); - if (wifi_control_data && wifi_control_data->set_power) { - wifi_control_data->set_power(on); - } - if (msec) - mdelay(msec); - LEAVE(); - return 0; -} - -/** - * @brief Probes an wifi device - * - * @param pdev A pointer to the platform_device structure - * - * @return 0 - */ -static int -wifi_probe(struct platform_device *pdev) -{ - struct wifi_platform_data *wifi_ctrl = - (struct wifi_platform_data *) (pdev->dev.platform_data); - - ENTER(); - - wifi_control_data = wifi_ctrl; - wifi_set_power(1, 0); /* Power On */ - wifi_set_carddetect(1); /* CardDetect (0->1) */ - - LEAVE(); - return 0; -} - -/** - * @brief Removes an wifi device - * - * @param pdev A pointer to the platform_device structure - * - * @return 0 - */ -static int -wifi_remove(struct platform_device *pdev) -{ - struct wifi_platform_data *wifi_ctrl = - (struct wifi_platform_data *) (pdev->dev.platform_data); - - ENTER(); - - wifi_control_data = wifi_ctrl; - wifi_set_power(0, 0); /* Power Off */ - wifi_set_carddetect(0); /* CardDetect (1->0) */ - - LEAVE(); - return 0; -} - -static struct platform_driver wifi_device = { - .probe = wifi_probe, - .remove = wifi_remove, - .driver = { - .name = "mrvl8797_wlan", - } -}; - -/** - * @brief Adds an wifi device - * @return 0 --success, otherwise fail - */ -static int -wifi_add_dev(void) -{ - int ret = 0; - - ENTER(); - - if (minicard_pwrup) - ret = platform_driver_register(&wifi_device); - - LEAVE(); - return ret; -} - -/** - * @brief Removes an wifi device - * - * @return N/A - */ -static void -wifi_del_dev(void) -{ - ENTER(); - - if (minicard_pwrup) - platform_driver_unregister(&wifi_device); - - LEAVE(); -} - /******************************************************** Global Functions ********************************************************/ @@ -2015,6 +2094,17 @@ woal_open(struct net_device *dev) (priv->media_connected || priv->is_adhoc_link_sensed)) carrier_on = MTRUE; #endif +#if defined(WIFI_DIRECT_SUPPORT) +#if defined(STA_CFG80211) && defined(UAP_CFG80211) +#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION + if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT && + IS_STA_CFG80211(cfg80211_wext)) { + priv->phandle->wiphy->interface_modes |= MBIT(NL80211_IFTYPE_P2P_GO) | + MBIT(NL80211_IFTYPE_P2P_CLIENT); + } +#endif +#endif +#endif if (carrier_on == MTRUE) { if (!netif_carrier_ok(priv->netdev)) netif_carrier_on(priv->netdev); @@ -2043,14 +2133,37 @@ woal_close(struct net_device *dev) ENTER(); #ifdef STA_SUPPORT #ifdef STA_CFG80211 + if (IS_STA_CFG80211(cfg80211_wext) && (priv->bss_type == MLAN_BSS_TYPE_STA)) + woal_clear_conn_params(priv); if (IS_STA_CFG80211(cfg80211_wext) && priv->scan_request) { cfg80211_scan_done(priv->scan_request, MTRUE); priv->scan_request = NULL; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) || defined(COMPAT_WIRELESS) + if (IS_STA_CFG80211(cfg80211_wext) && priv->sched_scanning) { + woal_stop_bg_scan(priv, MOAL_IOCTL_WAIT); + priv->bg_scan_start = MFALSE; + priv->bg_scan_reported = MFALSE; + cfg80211_sched_scan_stopped(priv->wdev->wiphy); + priv->sched_scanning = MFALSE; + } +#endif +#endif +#endif + if (!priv->bss_virtual) + woal_stop_queue(priv->netdev); +#if defined(WIFI_DIRECT_SUPPORT) +#if defined(STA_CFG80211) && defined(UAP_CFG80211) +#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION + if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT && !priv->bss_virtual && + IS_STA_CFG80211(cfg80211_wext) && IS_UAP_CFG80211(cfg80211_wext)) { + priv->phandle->wiphy->interface_modes &= ~(MBIT(NL80211_IFTYPE_P2P_GO) | + MBIT + (NL80211_IFTYPE_P2P_CLIENT)); + } +#endif #endif #endif - woal_stop_queue(priv->netdev); - MODULE_PUT; LEAVE(); @@ -2082,6 +2195,17 @@ woal_set_mac_address(struct net_device *dev, void *addr) HEXDUMP("addr:", (t_u8 *) phw_addr->sa_data, ETH_ALEN); memcpy(priv->current_addr, phw_addr->sa_data, ETH_ALEN); +#if defined(WIFI_DIRECT_SUPPORT) +#if defined(STA_CFG80211) && defined(UAP_CFG80211) +#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION + if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) { + priv->current_addr[0] |= 0x02; + PRINTM(MCMND, "Set WFD device addr: " MACSTR "\n", + MAC2STR(priv->current_addr)); + } +#endif +#endif +#endif if (MLAN_STATUS_SUCCESS != woal_request_set_mac_address(priv)) { PRINTM(MERROR, "Set MAC address failed\n"); /* For failure restore the MAC address */ @@ -2097,6 +2221,66 @@ woal_set_mac_address(struct net_device *dev, void *addr) } /** + * @brief Check driver status + * + * @param handle A pointer to moal_handle + * + * @return MTRUE/MFALSE + */ +static t_u8 +woal_check_driver_status(moal_handle * handle) +{ + moal_private *priv = NULL; + int i = 0; + ENTER(); + priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY); + if (!priv || woal_get_debug_info(priv, MOAL_CMD_WAIT, &info)) { + PRINTM(MERROR, "Could not retrieve debug information from MLAN\n"); + LEAVE(); + return MTRUE; + } + if (info.num_cmd_timeout) { + PRINTM(MERROR, "num_cmd_timeout = %d\n", info.num_cmd_timeout); + PRINTM(MERROR, "Timeout cmd id = 0x%x, act = 0x%x \n", + info.timeout_cmd_id, info.timeout_cmd_act); + LEAVE(); + return MTRUE; + } + if (info.num_no_cmd_node) { + PRINTM(MERROR, "num_no_cmd_node = %d\n", info.num_no_cmd_node); + LEAVE(); + return MTRUE; + } + for (i = 0; i < handle->priv_num; i++) { + if ((priv = handle->priv[i])) { + if (priv->num_tx_timeout >= NUM_TX_TIMEOUT_THRESHOLD) { + PRINTM(MERROR, "num_tx_timeout = %d\n", priv->num_tx_timeout); + LEAVE(); + return MTRUE; + } + } + } + if (info.data_sent || info.cmd_sent) { + if ((jiffies - handle->last_int_jiffies) > MAX_INT_IDLE_TIME) { + PRINTM(MERROR, "data_sent=%d cmd_sent=%d\n", info.data_sent, + info.cmd_sent); + LEAVE(); + return MTRUE; + } + } + if (info.pm_wakeup_card_req && info.pm_wakeup_fw_try) { + if ((jiffies - handle->last_int_jiffies) > MAX_INT_IDLE_TIME) { + PRINTM(MERROR, "wakeup_dev_req=%d wakeup_tries=%d\n", + info.pm_wakeup_card_req, info.pm_wakeup_fw_try); + LEAVE(); + return MTRUE; + } + } + LEAVE(); + return MFALSE; +} + +/** * @brief Display MLAN debug information * * @param priv A pointer to moal_private @@ -2210,6 +2394,9 @@ woal_tx_timeout(struct net_device *dev) if (priv->num_tx_timeout == NUM_TX_TIMEOUT_THRESHOLD) { woal_mlan_debug_info(priv); woal_moal_debug_info(priv, NULL, MFALSE); +#if defined(DEBUG_LEVEL1) +#endif + } LEAVE(); @@ -2229,7 +2416,7 @@ woal_get_stats(struct net_device *dev) return &priv->stats; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) /** * @brief This function handles wmm queue select * @@ -2270,13 +2457,34 @@ woal_select_queue(struct net_device * dev, struct sk_buff * skb) #endif /** + * @brief This function flush tcp session queue + * + * @param priv A pointer to moal_private structure + * + * @return N/A + */ +void +woal_flush_tcp_sess_queue(moal_private * priv) +{ + struct tcp_sess *tcp_sess = NULL, *tmp_node; + unsigned long flags; + spin_lock_irqsave(&priv->tcp_sess_lock, flags); + list_for_each_entry_safe(tcp_sess, tmp_node, &priv->tcp_sess_queue, link) { + list_del(&tcp_sess->link); + kfree(tcp_sess); + } + INIT_LIST_HEAD(&priv->tcp_sess_queue); + spin_unlock_irqrestore(&priv->tcp_sess_lock, flags); +} + +/** * @brief This function gets tcp session from the tcp session queue * * @param priv A pointer to moal_private structure * @param src_ip IP address of the device * @param src_port TCP port of the device * @param dst_ip IP address of the client - * @param src_port TCP port of the client + * @param dst_port TCP port of the client * * @return A pointer to the tcp session data structure, if found. * Otherwise, null @@ -2302,50 +2510,6 @@ woal_get_tcp_sess(moal_private * priv, } /** - * @brief This function checks received tcp packet for FIN - * and release the tcp session if received - * - * @param priv A pointer to moal_private structure - * @param skb A pointer to sk_buff structure - * - * @return None - */ -void -woal_check_tcp_fin(moal_private * priv, struct sk_buff *skb) -{ - struct ethhdr *ethh = NULL; - struct iphdr *iph = NULL; - struct tcphdr *tcph = NULL; - struct tcp_sess *tcp_sess = NULL; - - ENTER(); - - ethh = eth_hdr(skb); - if (ntohs(ethh->h_proto) == ETH_P_IP) { - iph = (struct iphdr *) ((t_u8 *) ethh + sizeof(struct ethhdr)); - if (iph->protocol == IPPROTO_TCP) { - tcph = (struct tcphdr *) ((t_u8 *) iph + iph->ihl * 4); - if (tcph->fin) { - tcp_sess = woal_get_tcp_sess(priv, iph->daddr, - tcph->dest, iph->saddr, - tcph->source); - if (tcp_sess != NULL) { - PRINTM(MINFO, - "TX: release a tcp session in dl. (src: ipaddr 0x%08x, port: %d. dst: ipaddr 0x%08x, port: %d\n", - iph->daddr, tcph->dest, iph->saddr, tcph->source); - /* remove the tcp session from the queue */ - list_del(&tcp_sess->link); - kfree(tcp_sess); - } else { - PRINTM(MINFO, "Tx: released TCP session is not found.\n "); - } - } - } - } - LEAVE(); -} - -/** * @brief This function process tcp ack packets * * @param priv A pointer to moal_private structure @@ -2368,6 +2532,7 @@ woal_process_tcp_ack(moal_private * priv, mlan_buffer * pmbuf) t_u8 opt_len = 0; t_u8 *pos = NULL; t_u32 win_size = 0; + unsigned long flags; #define TCP_ACK_DELAY 3 #define TCP_ACK_INIT_WARMING_UP 1000 /* initial */ @@ -2378,33 +2543,38 @@ woal_process_tcp_ack(moal_private * priv, mlan_buffer * pmbuf) /** check the tcp packet */ ethh = (struct ethhdr *) (pmbuf->pbuf + pmbuf->data_offset); if (ntohs(ethh->h_proto) != ETH_P_IP) { + LEAVE(); return 0; } iph = (struct iphdr *) ((t_u8 *) ethh + sizeof(struct ethhdr)); if (iph->protocol != IPPROTO_TCP) { + LEAVE(); return 0; } tcph = (struct tcphdr *) ((t_u8 *) iph + iph->ihl * 4); + spin_lock_irqsave(&priv->tcp_sess_lock, flags); if (tcph->syn & tcph->ack) { - /* respond to a TCP request. create a tcp session */ - if (!(tcp_sess = kmalloc(sizeof(struct tcp_sess), GFP_ATOMIC))) { - PRINTM(MERROR, "Fail to allocate tcp_sess.\n"); - return 0; + tcp_sess = woal_get_tcp_sess(priv, iph->saddr, tcph->source, + iph->daddr, tcph->dest); + if (!tcp_sess) { + /* respond to a TCP request. create a tcp session */ + if (!(tcp_sess = kmalloc(sizeof(struct tcp_sess), GFP_ATOMIC))) { + PRINTM(MERROR, "Fail to allocate tcp_sess.\n"); + goto done; + } + memset(tcp_sess, 0, sizeof(struct tcp_sess)); + tcp_sess->src_ip_addr = iph->saddr; /* my ip addr */ + tcp_sess->dst_ip_addr = iph->daddr; + tcp_sess->src_tcp_port = tcph->source; + tcp_sess->dst_tcp_port = tcph->dest; + INIT_LIST_HEAD(&tcp_sess->link); + list_add_tail(&tcp_sess->link, &priv->tcp_sess_queue); + PRINTM(MINFO, + "create a tcp session. (src: ipaddr 0x%08x, port: %d. dst: ipaddr 0x%08x, port: %d\n", + iph->saddr, tcph->source, iph->daddr, tcph->dest); } - memset(tcp_sess, 0, sizeof(struct tcp_sess)); - tcp_sess->src_ip_addr = iph->saddr; /* my ip addr */ - tcp_sess->dst_ip_addr = iph->daddr; - tcp_sess->src_tcp_port = tcph->source; - tcp_sess->dst_tcp_port = tcph->dest; tcp_sess->start_cnt = TCP_ACK_INIT_WARMING_UP; - - INIT_LIST_HEAD(&tcp_sess->link); - list_add_tail(&tcp_sess->link, &priv->tcp_sess_queue); - PRINTM(MINFO, - "create a tcp session. (src: ipaddr 0x%08x, port: %d. dst: ipaddr 0x%08x, port: %d\n", - iph->saddr, tcph->source, iph->daddr, tcph->dest); - /* parse tcp options for the window scale */ len = (tcph->doff * 4) - sizeof(struct tcphdr); pos = (t_u8 *) (tcph + 1); @@ -2440,12 +2610,12 @@ woal_process_tcp_ack(moal_private * priv, mlan_buffer * pmbuf) tcp_sess = woal_get_tcp_sess(priv, iph->saddr, tcph->source, iph->daddr, tcph->dest); if (tcp_sess == NULL) { - return 0; + goto done; } /** do not drop the ack packets initially */ if (tcp_sess->start_cnt) { tcp_sess->start_cnt--; - return 0; + goto done; } /* check the window size. */ @@ -2475,7 +2645,6 @@ woal_process_tcp_ack(moal_private * priv, mlan_buffer * pmbuf) ack_seq = tcp_sess->ack_seq; tcp_sess->ack_seq = ntohl(tcph->ack_seq); tcp_sess->ack_cnt = 0; - ret = 0; } } } else if (tcph->fin) { @@ -2492,6 +2661,8 @@ woal_process_tcp_ack(moal_private * priv, mlan_buffer * pmbuf) PRINTM(MINFO, "released TCP session is not found.\n "); } } + done: + spin_unlock_irqrestore(&priv->tcp_sess_lock, flags); LEAVE(); return ret; } @@ -2511,6 +2682,10 @@ woal_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) mlan_buffer *pmbuf = NULL; mlan_status status; struct sk_buff *new_skb = NULL; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) + t_u32 index = 0; + t_u32 tid = 0; +#endif ENTER(); @@ -2530,15 +2705,14 @@ woal_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) priv->stats.tx_dropped++; goto done; } - if (skb->cloned || - (skb_headroom(skb) < - (MLAN_MIN_DATA_HEADER_LEN + sizeof(mlan_buffer)))) { + if (skb->cloned || (skb_headroom(skb) < (MLAN_MIN_DATA_HEADER_LEN + + sizeof(mlan_buffer) + + priv->extra_tx_head_len))) { PRINTM(MWARN, "Tx: Insufficient skb headroom %d\n", skb_headroom(skb)); /* Insufficient skb headroom - allocate a new skb */ - new_skb = - skb_realloc_headroom(skb, - MLAN_MIN_DATA_HEADER_LEN + - sizeof(mlan_buffer)); + new_skb = skb_realloc_headroom(skb, MLAN_MIN_DATA_HEADER_LEN + + sizeof(mlan_buffer) + + priv->extra_tx_head_len); if (unlikely(!new_skb)) { PRINTM(MERROR, "Tx: Cannot allocate skb\n"); dev_kfree_skb_any(skb); @@ -2557,16 +2731,30 @@ woal_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) if (priv->enable_tcp_ack_enh == MTRUE) { if (woal_process_tcp_ack(priv, pmbuf)) { /* the ack packet has been dropped */ + priv->stats.tx_dropped++; + goto done; } } - status = mlan_send_packet(priv->phandle->pmlan_adapter, pmbuf); switch (status) { case MLAN_STATUS_PENDING: atomic_inc(&priv->phandle->tx_pending); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) + tid = pmbuf->priority; + index = + mlan_select_wmm_queue(priv->phandle->pmlan_adapter, priv->bss_index, + tid); + atomic_inc(&priv->wmm_tx_pending[index]); + if (atomic_read(&priv->wmm_tx_pending[index]) >= MAX_TX_PENDING) { + struct netdev_queue *txq = netdev_get_tx_queue(priv->netdev, index); + netif_tx_stop_queue(txq); + PRINTM(MINFO, "Stop Kernel Queue : %d\n", index); + } +#else 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) */ queue_work(priv->phandle->workqueue, &priv->phandle->main_work); break; case MLAN_STATUS_SUCCESS: @@ -2795,8 +2983,6 @@ woal_set_multicast_list(struct net_device *dev) void woal_init_priv(moal_private * priv, t_u8 wait_option) { - struct list_head *link = NULL; - struct tcp_sess *tcp_sess = NULL; ENTER(); #ifdef STA_SUPPORT if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) { @@ -2814,27 +3000,11 @@ woal_init_priv(moal_private * priv, t_u8 wait_option) priv->reassoc_on = MFALSE; priv->set_asynced_essid_flag = MFALSE; #endif -#ifdef STA_CFG80211 - if (IS_STA_CFG80211(cfg80211_wext)) { - if (priv->bss_type == MLAN_BSS_TYPE_STA -#if defined(WIFI_DIRECT_SUPPORT) -#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION - || priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT -#endif -#endif - ) - woal_cfg80211_sta_init_wiphy(priv, wait_option); - } -#endif } #endif /* STA_SUPPORT */ #ifdef UAP_SUPPORT if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) { priv->bss_started = MFALSE; -#ifdef UAP_CFG80211 - if (IS_UAP_CFG80211(cfg80211_wext)) - woal_cfg80211_uap_init_wiphy(priv, wait_option); -#endif } #endif priv->media_connected = MFALSE; @@ -2844,34 +3014,42 @@ woal_init_priv(moal_private * priv, t_u8 wait_option) priv->beacon_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; priv->proberesp_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; priv->assocresp_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) && !defined(COMPAT_WIRELESS) priv->beacon_wps_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; -#endif + priv->proberesp_p2p_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; #endif #ifdef STA_SUPPORT #endif priv->enable_tcp_ack_enh = MTRUE; - while (!list_empty(&priv->tcp_sess_queue)) { - link = priv->tcp_sess_queue.next; - tcp_sess = list_entry(link, struct tcp_sess, link); - PRINTM(MINFO, - "warm reset: release a tcp session in dl. (src: ipaddr 0x%08x, port: %d. dst: ipaddr 0x%08x, port: %d\n", - tcp_sess->src_ip_addr, tcp_sess->src_tcp_port, - tcp_sess->dst_ip_addr, tcp_sess->dst_tcp_port); - list_del(link); - kfree(tcp_sess); - } woal_request_get_fw_info(priv, wait_option, NULL); + #if defined(WIFI_DIRECT_SUPPORT) #if defined(STA_CFG80211) && defined(UAP_CFG80211) #if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION - if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) { - priv->current_addr[0] |= 0x02; - woal_request_set_mac_address(priv); - memcpy(priv->netdev->dev_addr, priv->current_addr, ETH_ALEN); - } +#ifdef MFG_CMD_SUPPORT + if (mfg_mode != MLAN_INIT_PARA_ENABLED) +#endif + if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) { + if (priv->bss_virtual) { + if (priv->pa_netdev) { + memcpy(priv->current_addr, priv->pa_netdev->dev_addr, + ETH_ALEN); + priv->current_addr[4] ^= 0x80; + woal_request_set_mac_address(priv); + memcpy(priv->netdev->dev_addr, priv->current_addr, + ETH_ALEN); + PRINTM(MCMND, "Set WFD interface addr: " MACSTR "\n", + MAC2STR(priv->current_addr)); + } + } else { + priv->current_addr[0] |= 0x02; + woal_request_set_mac_address(priv); + memcpy(priv->netdev->dev_addr, priv->current_addr, ETH_ALEN); + PRINTM(MCMND, "Set WFD device addr: " MACSTR "\n", + MAC2STR(priv->current_addr)); + } + } #endif #endif #endif @@ -3027,6 +3205,13 @@ woal_alloc_mlan_buffer(moal_handle * handle, int size) struct sk_buff *skb; ENTER(); + + if (size <= 0) { + PRINTM(MERROR, "Buffer size must be positive\n"); + LEAVE(); + return NULL; + } + if (!(pmbuf = kmalloc(sizeof(mlan_buffer), GFP_ATOMIC))) { PRINTM(MERROR, "%s: Fail to alloc mlan buffer\n", __FUNCTION__); LEAVE(); @@ -3104,8 +3289,8 @@ woal_free_mlan_buffer(moal_handle * handle, pmlan_buffer pmbuf) return; } -#ifdef STA_WEXT -#endif +#ifdef STA_SUPPORT +#endif /* STA_SUPPORT */ /** * @brief This function handles events generated by firmware @@ -3122,9 +3307,11 @@ woal_broadcast_event(moal_private * priv, t_u8 * payload, t_u32 len) struct sk_buff *skb = NULL; struct nlmsghdr *nlh = NULL; moal_handle *handle = priv->phandle; + struct net_device *netdev = priv->netdev; struct sock *sk = handle->nl_sk; ENTER(); + len += 1; /* space for the '\0' character at the end */ /* interface name to be prepended to event */ if ((len + IFNAMSIZ) > NL_MAX_PAYLOAD #ifdef WIFI_DIRECT_SUPPORT @@ -3163,11 +3350,15 @@ woal_broadcast_event(moal_private * priv, t_u8 * payload, t_u32 len) /* Data */ skb_put(skb, nlh->nlmsg_len); - memcpy(NLMSG_DATA(nlh), priv->netdev->name, IFNAMSIZ); + memcpy(NLMSG_DATA(nlh), netdev->name, IFNAMSIZ); memcpy(((t_u8 *) (NLMSG_DATA(nlh))) + IFNAMSIZ, payload, len); /* From Kernel */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) NETLINK_CB(skb).pid = 0; +#else + NETLINK_CB(skb).portid = 0; +#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) /* Multicast message */ @@ -3182,7 +3373,11 @@ woal_broadcast_event(moal_private * priv, t_u8 * payload, t_u32 len) #endif /* Send message */ - netlink_broadcast(sk, skb, 0, NL_MULTICAST_GROUP, GFP_ATOMIC); + ret = netlink_broadcast(sk, skb, 0, NL_MULTICAST_GROUP, GFP_ATOMIC); + if (ret) { + PRINTM(MWARN, "netlink_broadcast failed: ret=%d\n", ret); + goto done; + } ret = MLAN_STATUS_SUCCESS; } else { @@ -3251,6 +3446,16 @@ woal_reassociation_thread(void *data) PRINTM(MEVENT, "Reassoc: Thread waking up...\n"); reassoc_timer_req = MFALSE; +#ifdef STA_CFG80211 + for (i = 0; i < handle->priv_num && (priv = handle->priv[i]); i++) { + if (priv->roaming_required) { + priv->roaming_required = MFALSE; + PRINTM(MEVENT, "Try to roaming......\n"); + woal_start_roaming(priv); + break; + } + } +#endif for (i = 0; i < handle->priv_num && (priv = handle->priv[i]); i++) { @@ -3326,6 +3531,12 @@ woal_reassociation_thread(void *data) status = woal_find_best_network(priv, MOAL_CMD_WAIT, &ssid_bssid); + /** The find AP without ssid, we need re-search */ + if (status == MLAN_STATUS_SUCCESS && !ssid_bssid.ssid.ssid_len) { + PRINTM(MINFO, "Reassoc: Skip AP without ssid\n"); + status = MLAN_STATUS_FAILURE; + } + if (priv->set_asynced_essid_flag != MTRUE && MLAN_STATUS_SUCCESS != status) { PRINTM(MINFO, "Reassoc: AP not found in scan list\n"); @@ -3405,7 +3616,7 @@ woal_reassociation_thread(void *data) if (reassoc_timer_req == MTRUE) { handle->is_reassoc_timer_set = MTRUE; - if (priv->set_asynced_essid_flag == MTRUE) { + if (priv && (priv->set_asynced_essid_flag == MTRUE)) { PRINTM(MERROR, "Set Async ESSID: No AP found or assoc failed. \n"); priv->set_asynced_essid_flag = MFALSE; @@ -3416,7 +3627,9 @@ woal_reassociation_thread(void *data) woal_mod_timer(&handle->reassoc_timer, timer_val); } } else { - priv->set_asynced_essid_flag = MFALSE; + if (priv) { + priv->set_asynced_essid_flag = MFALSE; + } } } woal_deactivate_thread(pmoal_thread); @@ -3471,6 +3684,7 @@ woal_send_disconnect_to_system(moal_private * priv) woal_stop_queue(priv->netdev); if (netif_carrier_ok(priv->netdev)) netif_carrier_off(priv->netdev); + woal_flush_tcp_sess_queue(priv); #ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext)) { memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN); @@ -3480,10 +3694,10 @@ woal_send_disconnect_to_system(moal_private * priv) #endif #ifdef STA_CFG80211 if (IS_STA_CFG80211(cfg80211_wext)) { - if (!priv->cfg_disconnect && + if (!priv->cfg_disconnect && !priv->cfg_connect && priv->wdev && priv->wdev->iftype != NL80211_IFTYPE_ADHOC) { - PRINTM(MINFO, "Successfully disconnected from %pM:" - " Reason code %d\n", priv->cfg_bssid, + PRINTM(MMSG, "wlan: Disconnected from " MACSTR ":" + " Reason code %d\n", MAC2STR(priv->cfg_bssid), WLAN_REASON_DEAUTH_LEAVING); /* This function must be called only when disconnect issued by the FW, i.e. disconnected by AP. For IBSS mode this call is not @@ -3493,12 +3707,16 @@ woal_send_disconnect_to_system(moal_private * priv) GFP_KERNEL); } priv->cfg_disconnect = 0; + if (!woal_is_any_interface_active(priv->phandle)) + woal_set_scan_time(priv, ACTIVE_SCAN_CHAN_TIME, + PASSIVE_SCAN_CHAN_TIME, SPECIFIC_SCAN_CHAN_TIME); } #endif /* STA_CFG80211 */ memset(event_buf, 0, sizeof(event_buf)); custom_len = strlen(CUS_EVT_AP_CONNECTED); - strncpy(event_buf, CUS_EVT_AP_CONNECTED, custom_len); + strncpy(event_buf, CUS_EVT_AP_CONNECTED, + MIN((sizeof(event_buf) - 1), custom_len)); woal_broadcast_event(priv, event_buf, custom_len + ETH_ALEN); LEAVE(); } @@ -3591,7 +3809,7 @@ woal_moal_debug_info(moal_private * priv, moal_handle * handle, u8 flag) { moal_handle *phandle = NULL; char buf[MLAN_MAX_VER_STR_LEN]; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) int i = 0; #endif @@ -3615,6 +3833,18 @@ woal_moal_debug_info(moal_private * priv, moal_handle * handle, u8 flag) PRINTM(MERROR, "ioctl_pending = %d\n", atomic_read(&phandle->ioctl_pending)); PRINTM(MERROR, "tx_pending = %d\n", atomic_read(&phandle->tx_pending)); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) + if (priv) { + PRINTM(MERROR, "wmm_tx_pending[0] = %d\n", + atomic_read(&priv->wmm_tx_pending[0])); + PRINTM(MERROR, "wmm_tx_pending[1] = %d\n", + atomic_read(&priv->wmm_tx_pending[1])); + PRINTM(MERROR, "wmm_tx_pending[2] = %d\n", + atomic_read(&priv->wmm_tx_pending[2])); + PRINTM(MERROR, "wmm_tx_pending[3] = %d\n", + atomic_read(&priv->wmm_tx_pending[3])); + } +#endif PRINTM(MERROR, "rx_pending = %d\n", atomic_read(&phandle->rx_pending)); PRINTM(MERROR, "lock_count = %d\n", atomic_read(&phandle->lock_count)); PRINTM(MERROR, "malloc_count = %d\n", atomic_read(&phandle->malloc_count)); @@ -3631,11 +3861,11 @@ woal_moal_debug_info(moal_private * priv, moal_handle * handle, u8 flag) MFALSE) ? "Disconnected" : "Connected")); PRINTM(MERROR, "carrier %s\n", ((netif_carrier_ok(priv->netdev)) ? "on" : "off")); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) for (i = 0; i < (priv->netdev->num_tx_queues); i++) { PRINTM(MERROR, "tx queue %d: %s\n", i, ((netif_tx_queue_stopped - (netdev_get_tx_queue(priv->netdev, 0))) ? "stopped" : + (netdev_get_tx_queue(priv->netdev, i))) ? "stopped" : "started")); } #else @@ -3722,8 +3952,16 @@ woal_interrupt(moal_handle * handle) LEAVE(); return; } + handle->last_int_jiffies = jiffies; /* call mlan_interrupt to read int status */ mlan_interrupt(handle->pmlan_adapter); +#ifdef SDIO_SUSPEND_RESUME + if (handle->is_suspended) { + PRINTM(MINTR, "Receive interrupt in hs_suspended\n"); + LEAVE(); + return; + } +#endif handle->main_state = MOAL_START_MAIN_PROCESS; /* Call MLAN main process */ mlan_main_process(handle->pmlan_adapter); @@ -3746,6 +3984,11 @@ woal_add_card(void *card) mlan_status status = MLAN_STATUS_SUCCESS; int netlink_num = NETLINK_MARVELL; int index = 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct netlink_kernel_cfg cfg = { + .groups = NL_MULTICAST_GROUP, + }; +#endif ENTER(); @@ -3785,7 +4028,11 @@ woal_add_card(void *card) } } + /* Update card type */ + woal_sdio_update_card_type(handle, card); + ((struct sdio_mmc_card *) card)->handle = handle; + #ifdef STA_SUPPORT handle->scan_pending_on_block = MFALSE; MOAL_INIT_SEMAPHORE(&handle->async_sem); @@ -3811,9 +4058,18 @@ woal_add_card(void *card) netlink_kernel_create(netlink_num, NL_MULTICAST_GROUP, NULL, NULL, THIS_MODULE); #else +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) handle->nl_sk = netlink_kernel_create(&init_net, netlink_num, NL_MULTICAST_GROUP, NULL, NULL, THIS_MODULE); +#else +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) + handle->nl_sk = + netlink_kernel_create(&init_net, netlink_num, THIS_MODULE, &cfg); +#else + handle->nl_sk = netlink_kernel_create(&init_net, netlink_num, &cfg); +#endif +#endif #endif #endif #endif @@ -3871,6 +4127,15 @@ woal_add_card(void *card) return handle; err_init_fw: + if ((handle->hardware_status == HardwareStatusFwReady) || + (handle->hardware_status == HardwareStatusReady)) { + PRINTM(MINFO, "shutdown mlan\n"); + handle->init_wait_q_woken = MFALSE; + status = mlan_shutdown_fw(handle->pmlan_adapter); + if (status == MLAN_STATUS_PENDING) + wait_event_interruptible(handle->init_wait_q, + handle->init_wait_q_woken); + } /* Unregister device */ PRINTM(MINFO, "unregister device\n"); woal_unregister_dev(handle); @@ -3887,15 +4152,6 @@ woal_add_card(void *card) #endif /* REASSOCIATION */ woal_terminate_workqueue(handle); err_kmalloc: - if ((handle->hardware_status == HardwareStatusFwReady) || - (handle->hardware_status == HardwareStatusReady)) { - PRINTM(MINFO, "shutdown mlan\n"); - handle->init_wait_q_woken = MFALSE; - status = mlan_shutdown_fw(handle->pmlan_adapter); - if (status == MLAN_STATUS_PENDING) - wait_event_interruptible(handle->init_wait_q, - handle->init_wait_q_woken); - } woal_free_moal_handle(handle); if (index < MAX_MLAN_ADAPTER) { m_handle[index] = NULL; @@ -3967,7 +4223,15 @@ woal_remove_card(void *card) atomic_read(&handle->tx_pending), atomic_read(&handle->ioctl_pending)); } - + unregister_inetaddr_notifier(&woal_notifier); +#if defined(WIFI_DIRECT_SUPPORT) +#if defined(STA_CFG80211) && defined(UAP_CFG80211) +#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION + /* Remove virtual interface */ + woal_remove_virtual_interface(handle); +#endif +#endif +#endif /* Remove interface */ for (i = 0; i < handle->priv_num; i++) woal_remove_interface(handle, i); @@ -4020,6 +4284,7 @@ woal_remove_card(void *card) return MLAN_STATUS_SUCCESS; } +#ifdef CONFIG_PROC_FS /** * @brief This function switch the drv_mode * @@ -4072,6 +4337,8 @@ woal_switch_drv_mode(moal_handle * handle, t_u32 mode) atomic_read(&handle->ioctl_pending)); } + unregister_inetaddr_notifier(&woal_notifier); + /* Remove interface */ for (i = 0; i < handle->priv_num; i++) woal_remove_interface(handle, i); @@ -4111,6 +4378,7 @@ woal_switch_drv_mode(moal_handle * handle, t_u32 mode) LEAVE(); return status; } +#endif /** * @brief This function initializes module. @@ -4125,6 +4393,7 @@ woal_init_module(void) ENTER(); + PRINTM(MMSG, "wlan: Loading MWLAN driver\n"); /* Init the wlan_private pointer array first */ for (index = 0; index < MAX_MLAN_ADAPTER; index++) { m_handle[index] = NULL; @@ -4132,10 +4401,12 @@ woal_init_module(void) /* Init mutex */ MOAL_INIT_SEMAPHORE(&AddRemoveCardSem); - wifi_add_dev(); - /* 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"); LEAVE(); return ret; @@ -4155,6 +4426,7 @@ woal_cleanup_module(void) ENTER(); + PRINTM(MMSG, "wlan: Unloading MWLAN driver\n"); if (MOAL_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem)) goto exit_sem_err; for (index = 0; index < MAX_MLAN_ADAPTER; index++) { @@ -4163,13 +4435,15 @@ woal_cleanup_module(void) continue; if (!handle->priv_num) goto exit; + if (MTRUE == woal_check_driver_status(handle)) + goto exit; #ifdef SDIO_SUSPEND_RESUME #ifdef MMC_PM_KEEP_POWER if (handle->is_suspended == MTRUE) { woal_sdio_resume(&(((struct sdio_mmc_card *) handle->card)->func)-> dev); } -#endif +#endif /* MMC_PM_KEEP_POWER */ #endif /* SDIO_SUSPEND_RESUME */ for (i = 0; i < handle->priv_num; i++) { @@ -4179,10 +4453,23 @@ woal_cleanup_module(void) woal_disconnect(handle->priv[i], MOAL_CMD_WAIT, NULL); #ifdef STA_CFG80211 if (IS_STA_CFG80211(cfg80211_wext) && + (handle->priv[i]->bss_type == MLAN_BSS_TYPE_STA)) + woal_clear_conn_params(handle->priv[i]); + if (IS_STA_CFG80211(cfg80211_wext) && handle->priv[i]->scan_request) { cfg80211_scan_done(handle->priv[i]->scan_request, MTRUE); handle->priv[i]->scan_request = NULL; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) || defined(COMPAT_WIRELESS) + if (IS_STA_CFG80211(cfg80211_wext) && + handle->priv[i]->sched_scanning) { + woal_stop_bg_scan(handle->priv[i], MOAL_IOCTL_WAIT); + handle->priv[i]->bg_scan_start = MFALSE; + handle->priv[i]->bg_scan_reported = MFALSE; + cfg80211_sched_scan_stopped(handle->priv[i]->wdev->wiphy); + handle->priv[i]->sched_scanning = MFALSE; + } +#endif #endif } #endif @@ -4195,10 +4482,7 @@ woal_cleanup_module(void) } #endif #if defined(STA_CFG80211) || defined(UAP_CFG80211) - if (handle->priv[i]->probereq_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK) - woal_cfg80211_mgmt_frame_ie(handle->priv[i], NULL, 0, NULL, 0, - NULL, 0, NULL, 0, - MGMT_MASK_PROBE_REQ); + woal_clear_all_mgmt_ies(handle->priv[i]); #endif } @@ -4220,14 +4504,39 @@ woal_cleanup_module(void) exit_sem_err: /* Unregister from bus */ woal_bus_unregister(); - wifi_del_dev(); + PRINTM(MMSG, "wlan: Driver unloaded\n"); LEAVE(); } +#ifndef MODULE +#ifdef MFG_CMD_SUPPORT +/** + * @brief This function handle the mfg_mode from kernel boot command + * + * @param str buffer for mfg_mode + * @return N/A + */ +static int __init +mfg_mode_setup(char *str) +{ + int val = -1; + get_option(&str, &val); + if (val > 0) + mfg_mode = 1; + PRINTM(MMSG, "mfg_mode=%d\n", mfg_mode); + return 1; +} + +__setup("mfg_mode=", mfg_mode_setup); +#endif +#endif + module_init(woal_init_module); module_exit(woal_cleanup_module); +module_param(hw_test, int, 0); +MODULE_PARM_DESC(hw_test, "0: Disable hardware test; 1: Enable hardware test"); module_param(fw_name, charp, 0); MODULE_PARM_DESC(fw_name, "Firmware name"); module_param(req_fw_nowait, int, 0); @@ -4263,6 +4572,10 @@ module_param(max_wfd_bss, int, 0); MODULE_PARM_DESC(max_wfd_bss, "Number of WIFIDIRECT interfaces (1)"); module_param(wfd_name, charp, 0); MODULE_PARM_DESC(wfd_name, "WIFIDIRECT interface name"); +#if defined(STA_CFG80211) && defined(UAP_CFG80211) +module_param(max_vir_bss, int, 0); +MODULE_PARM_DESC(max_vir_bss, "Number of Virtual interfaces (0)"); +#endif #endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */ #ifdef DEBUG_LEVEL1 module_param(drvdbg, uint, 0); @@ -4289,9 +4602,6 @@ module_param(init_cfg, charp, 0); MODULE_PARM_DESC(init_cfg, "Init config file name"); module_param(cal_data_cfg, charp, 0); MODULE_PARM_DESC(cal_data_cfg, "Calibration data file name"); -module_param(minicard_pwrup, int, 1); -MODULE_PARM_DESC(minicard_pwrup, - "1: Driver load clears PDn/Rst, unload sets (default); 0: Don't do this."); module_param(cfg80211_wext, int, 0); MODULE_PARM_DESC(cfg80211_wext, #ifdef STA_WEXT diff --git a/drivers/net/wireless/sd8797/mlinux/moal_main.h b/drivers/net/wireless/sd8797/mlinux/moal_main.h index de70eef66179..76a95e36a7ba 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_main.h +++ b/drivers/net/wireless/sd8797/mlinux/moal_main.h @@ -51,6 +51,7 @@ Change log: #include <linux/vmalloc.h> #include <linux/ptrace.h> #include <linux/string.h> +#include <linux/irqreturn.h> #include <linux/list.h> #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) @@ -85,19 +86,20 @@ Change log: #include <net/sock.h> #include <net/arp.h> #include <linux/rtnetlink.h> +#include <linux/inetdevice.h> #include <linux/firmware.h> #include "mlan.h" #include "moal_shim.h" /* Wireless header */ -#include <linux/wireless.h> #if defined(STA_CFG80211) || defined(UAP_CFG80211) #include <net/lib80211.h> #include <net/cfg80211.h> #include <net/ieee80211_radiotap.h> #endif #if defined(STA_WEXT) || defined(UAP_WEXT) +#include <linux/wireless.h> #include <net/iw_handler.h> #include "moal_wext.h" #endif @@ -139,7 +141,9 @@ enum MOAL_NO_WAIT, MOAL_IOCTL_WAIT, MOAL_CMD_WAIT, +#ifdef CONFIG_PROC_FS MOAL_PROC_WAIT, +#endif MOAL_WSTATS_WAIT }; @@ -500,7 +504,7 @@ in4_pton(const char *src, int srclen, u8 * dst, int delim, const char **end) #define REQUEST_FW_TIMEOUT 30 /** Default watchdog timeout */ -#define MRVDRV_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ) +#define MRVDRV_DEFAULT_WATCHDOG_TIMEOUT (10 * HZ) #ifdef UAP_SUPPORT /** Default watchdog timeout @@ -518,9 +522,68 @@ in4_pton(const char *src, int srclen, u8 * dst, int delim, const char **end) /** AP connected event */ #define CUS_EVT_AP_CONNECTED "EVENT=AP_CONNECTED" -/** Port release event */ -#ifndef CUS_EVT_PORT_RELEASE -#define CUS_EVT_PORT_RELEASE "EVENT=PORT_RELEASE" +/** Custom event : BW changed */ +#define CUS_EVT_BW_CHANGED "EVENT=BW_CHANGED" +/** Custom event : OBSS scan parameter */ +#define CUS_EVT_OBSS_SCAN_PARAM "EVENT=OBSS_SCAN_PARAM" + +/** Custom event : AdHoc link sensed */ +#define CUS_EVT_ADHOC_LINK_SENSED "EVENT=ADHOC_LINK_SENSED" +/** Custom event : AdHoc link lost */ +#define CUS_EVT_ADHOC_LINK_LOST "EVENT=ADHOC_LINK_LOST" +/** Custom event : MIC failure, unicast */ +#define CUS_EVT_MLME_MIC_ERR_UNI "MLME-MICHAELMICFAILURE.indication unicast " +/** Custom event : MIC failure, multicast */ +#define CUS_EVT_MLME_MIC_ERR_MUL "MLME-MICHAELMICFAILURE.indication multicast " +/** Custom event : Beacon RSSI low */ +#define CUS_EVT_BEACON_RSSI_LOW "EVENT=BEACON_RSSI_LOW" +/** Custom event : Beacon SNR low */ +#define CUS_EVT_BEACON_SNR_LOW "EVENT=BEACON_SNR_LOW" +/** Custom event : Beacon RSSI high */ +#define CUS_EVT_BEACON_RSSI_HIGH "EVENT=BEACON_RSSI_HIGH" +/** Custom event : Beacon SNR high */ +#define CUS_EVT_BEACON_SNR_HIGH "EVENT=BEACON_SNR_HIGH" +/** Custom event : Max fail */ +#define CUS_EVT_MAX_FAIL "EVENT=MAX_FAIL" +/** Custom event : Data RSSI low */ +#define CUS_EVT_DATA_RSSI_LOW "EVENT=DATA_RSSI_LOW" +/** Custom event : Data SNR low */ +#define CUS_EVT_DATA_SNR_LOW "EVENT=DATA_SNR_LOW" +/** Custom event : Data RSSI high */ +#define CUS_EVT_DATA_RSSI_HIGH "EVENT=DATA_RSSI_HIGH" +/** Custom event : Data SNR high */ +#define CUS_EVT_DATA_SNR_HIGH "EVENT=DATA_SNR_HIGH" +/** Custom event : Link Quality */ +#define CUS_EVT_LINK_QUALITY "EVENT=LINK_QUALITY" +/** Custom event : Port Release */ +#define CUS_EVT_PORT_RELEASE "EVENT=PORT_RELEASE" +/** Custom event : Pre-Beacon Lost */ +#define CUS_EVT_PRE_BEACON_LOST "EVENT=PRE_BEACON_LOST" + +/** Custom event : Deep Sleep awake */ +#define CUS_EVT_DEEP_SLEEP_AWAKE "EVENT=DS_AWAKE" + +/** Custom event : Host Sleep activated */ +#define CUS_EVT_HS_ACTIVATED "HS_ACTIVATED " +/** Custom event : Host Sleep deactivated */ +#define CUS_EVT_HS_DEACTIVATED "HS_DEACTIVATED " +/** Custom event : Host Sleep wakeup */ +#define CUS_EVT_HS_WAKEUP "HS_WAKEUP" + +/** Custom event : WEP ICV error */ +#define CUS_EVT_WEP_ICV_ERR "EVENT=WEP_ICV_ERR" + +/** Custom event : Channel Switch Announcment */ +#define CUS_EVT_CHANNEL_SWITCH_ANN "EVENT=CHANNEL_SWITCH_ANN" + +/** Custom indiciation message sent to the application layer for WMM changes */ +#define WMM_CONFIG_CHANGE_INDICATION "WMM_CONFIG_CHANGE.indication" + +#ifdef UAP_SUPPORT +/** Custom event : STA connected */ +#define CUS_EVT_STA_CONNECTED "EVENT=STA_CONNECTED" +/** Custom event : STA disconnected */ +#define CUS_EVT_STA_DISCONNECTED "EVENT=STA_DISCONNECTED" #endif /** 10 seconds */ @@ -530,6 +593,21 @@ in4_pton(const char *src, int srclen, u8 * dst, int delim, const char **end) /** 1 second */ #define MOAL_TIMER_1S 1000 +/** passive scan time */ +#define PASSIVE_SCAN_CHAN_TIME 110 +/** active scan time */ +#define ACTIVE_SCAN_CHAN_TIME 110 +/** specific scan time */ +#define SPECIFIC_SCAN_CHAN_TIME 110 +/** passive scan time */ +#define INIT_PASSIVE_SCAN_CHAN_TIME 80 +/** active scan time */ +#define INIT_ACTIVE_SCAN_CHAN_TIME 80 +/** specific scan time */ +#define INIT_SPECIFIC_SCAN_CHAN_TIME 80 +/** specific scan time after connected */ +#define MIN_SPECIFIC_SCAN_CHAN_TIME 40 + /** Default value of re-assoc timer */ #define REASSOC_TIMER_DEFAULT 500 @@ -636,8 +714,19 @@ typedef struct _wait_queue #define MAX_WIFIDIRECT_BSS 1 /** Default WIFIDIRECT BSS */ #define DEF_WIFIDIRECT_BSS 1 +#if defined(STA_CFG80211) && defined(UAP_CFG80211) +#define DEF_VIRTUAL_BSS 0 +#endif #endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */ +/** max interrupt idle time 3 sceond */ +#define MAX_INT_IDLE_TIME 3*HZ + +/** + * the maximum number of adapter supported + **/ +#define MAX_MLAN_ADAPTER 2 + typedef struct _moal_drv_mode { /** driver mode */ @@ -710,6 +799,8 @@ struct _moal_private t_u8 bss_type; /** BSS role */ t_u8 bss_role; + /** bss virtual flag */ + t_u8 bss_virtual; /** MAC address information */ t_u8 current_addr[ETH_ALEN]; /** Media connection status */ @@ -718,25 +809,51 @@ struct _moal_private /** uAP started or not */ BOOLEAN bss_started; #endif + /** IP addr type */ + t_u32 ip_addr_type; + /** IP addr */ + t_u8 ip_addr[IPADDR_LEN]; #ifdef STA_SUPPORT /** scan type */ t_u8 scan_type; /** bg_scan_start */ t_u8 bg_scan_start; - /** bg_scan reported */ + /** bg_scan reported */ t_u8 bg_scan_reported; - /** bg_scan config */ + /** bg_scan config */ wlan_bgscan_cfg scan_cfg; + /** sched scaning flag */ + t_u8 sched_scanning; +#ifdef STA_CFG80211 + /** roaming enabled flag */ + t_u8 roaming_enabled; + /** rssi low threshold */ + int rssi_low; + /** channel for connect */ + struct ieee80211_channel conn_chan; + /** bssid for connect */ + t_u8 conn_bssid[ETH_ALEN]; + /** ssid for connect */ + t_u8 conn_ssid[MLAN_MAX_SSID_LENGTH]; + /** key data */ + t_u8 conn_wep_key[MAX_WEP_KEY_SIZE]; + /** connection param */ + struct cfg80211_connect_params sme_current; + /** roaming required flag */ + t_u8 roaming_required; +#endif #endif /** Net device pointer */ struct net_device *netdev; /** Net device statistics structure */ struct net_device_stats stats; #if defined(STA_CFG80211) || defined(UAP_CFG80211) - /** Country code for regulatory domain */ - t_u8 country_code[COUNTRY_CODE_LEN]; /** Wireless device pointer */ struct wireless_dev *wdev; + /** Wireless device */ + struct wireless_dev w_dev; + /** Net device pointer */ + struct net_device *pa_netdev; /** channel parameter for UAP/GO */ t_u16 channel; /** cipher */ @@ -751,15 +868,17 @@ struct _moal_private t_u16 beacon_index; /** proberesp ie index */ t_u16 proberesp_index; + /** proberesp_p2p_index */ + t_u16 proberesp_p2p_index; /** assocresp ie index */ t_u16 assocresp_index; /** probereq index for mgmt ie */ t_u16 probereq_index; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) && !defined(COMPAT_WIRELESS) + /** mgmt_subtype_mask */ + t_u32 mgmt_subtype_mask; /** beacon wps index for mgmt ie */ t_u16 beacon_wps_index; #endif -#endif #ifdef STA_CFG80211 #ifdef STA_SUPPORT /** CFG80211 scan request description */ @@ -768,6 +887,10 @@ struct _moal_private t_u8 cfg_bssid[ETH_ALEN]; /** Disconnect request from CFG80211 */ bool cfg_disconnect; + /** connect request from CFG80211 */ + bool cfg_connect; + /** assoc status */ + t_u32 assoc_status; /** rssi_threshold */ s32 cqm_rssi_thold; /** rssi hysteresis */ @@ -790,7 +913,7 @@ struct _moal_private /** Proc entry */ struct proc_dir_entry *proc_entry; /** Proc entry name */ - t_s8 proc_entry_name[IFNAMSIZ]; + char proc_entry_name[IFNAMSIZ]; /** PROC wait queue */ wait_queue_head_t proc_wait_q __ATTRIB_ALIGN__; #endif /* CONFIG_PROC_FS */ @@ -851,6 +974,13 @@ struct _moal_private struct list_head tcp_sess_queue; /** TCP Ack enhance flag */ t_u8 enable_tcp_ack_enh; + /** TCP session spin lock */ + spinlock_t tcp_sess_lock; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) + atomic_t wmm_tx_pending[4]; +#endif + /** per interface extra headroom */ + t_u16 extra_tx_head_len; }; /** Handle data structure for MOAL */ @@ -916,6 +1046,8 @@ struct _moal_handle atomic_t lock_count; /** Malloc count */ atomic_t malloc_count; + /** vmalloc count */ + atomic_t vmalloc_count; /** mlan buffer alloc count */ atomic_t mbufalloc_count; #if defined(SDIO_SUSPEND_RESUME) @@ -938,18 +1070,30 @@ struct _moal_handle /** Bitmap for re-association on/off */ t_u8 reassoc_on; #endif /* REASSOCIATION */ + t_u32 last_int_jiffies; /** Driver workqueue */ struct workqueue_struct *workqueue; /** main work */ struct work_struct main_work; #if defined(STA_CFG80211) || defined(UAP_CFG80211) + struct wiphy *wiphy; + /** Country code for regulatory domain */ + t_u8 country_code[COUNTRY_CODE_LEN]; + /** band */ + enum ieee80211_band band; + /** first scan done flag */ + t_u8 first_scan_done; #ifdef WIFI_DIRECT_SUPPORT /** remain on channel flag */ t_u8 remain_on_channel; + /** bss index for remain on channel */ + t_u8 remain_bss_index; /** ieee802_11_channel */ struct ieee80211_channel chan; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) /** channel type */ enum nl80211_channel_type channel_type; +#endif /** cookie */ t_u64 cookie; /** GO timer set flag */ @@ -957,6 +1101,10 @@ struct _moal_handle /** GO timer */ moal_drv_timer go_timer __ATTRIB_ALIGN__; #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)|| defined(COMPAT_WIRELESS) + /** cfg80211_suspend status */ + t_u8 cfg80211_suspend; +#endif #endif /** Read SDIO registers for debugging */ t_u32 sdio_reg_dbg; @@ -1002,12 +1150,16 @@ struct _moal_handle t_u8 cmd52_reg; /** cmd52 value */ t_u8 cmd52_val; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) /** spinlock to stop_queue/wake_queue*/ spinlock_t queue_lock; #endif /** Driver spin lock */ spinlock_t driver_lock; + /** Card type */ + t_u16 card_type; + /** Card specific driver version */ + t_s8 driver_version[MLAN_MAX_VER_STR_LEN]; }; /** @@ -1039,7 +1191,7 @@ woal_set_trans_start(struct net_device *dev) static inline void woal_start_queue(struct net_device *dev) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,29) netif_start_queue(dev); #else netif_tx_start_all_queues(dev); @@ -1056,7 +1208,7 @@ woal_start_queue(struct net_device *dev) static inline void woal_stop_queue(struct net_device *dev) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) unsigned long flags; moal_private *priv = (moal_private *) netdev_priv(dev); spin_lock_irqsave(&priv->phandle->queue_lock, flags); @@ -1081,7 +1233,7 @@ woal_stop_queue(struct net_device *dev) static inline void woal_wake_queue(struct net_device *dev) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) unsigned long flags; moal_private *priv = (moal_private *) netdev_priv(dev); spin_lock_irqsave(&priv->phandle->queue_lock, flags); @@ -1094,38 +1246,57 @@ woal_wake_queue(struct net_device *dev) #endif } -/** Max number of char in custom event - use multiple of them if needed */ -#define IW_CUSTOM_MAX 256 /* In bytes */ - /** Debug Macro definition*/ #ifdef DEBUG_LEVEL1 extern t_u32 drvdbg; +#define LOG_CTRL(level) (0) + #ifdef DEBUG_LEVEL2 -#define PRINTM_MINFO(msg...) do {if (drvdbg & MINFO) printk(KERN_DEBUG msg);} while(0) -#define PRINTM_MWARN(msg...) do {if (drvdbg & MWARN) printk(KERN_DEBUG msg);} while(0) -#define PRINTM_MENTRY(msg...) do {if (drvdbg & MENTRY) printk(KERN_DEBUG msg);} while(0) +#define PRINTM_MINFO(level,msg...) do {woal_print(level,msg); \ + if (drvdbg & MINFO) printk(KERN_DEBUG msg);} while(0) +#define PRINTM_MWARN(level,msg...) do {woal_print(level,msg); \ + if (drvdbg & MWARN) printk(KERN_DEBUG msg);} while(0) +#define PRINTM_MENTRY(level,msg...) do {woal_print(level,msg); \ + if (drvdbg & MENTRY) printk(KERN_DEBUG msg);} while(0) #else -#define PRINTM_MINFO(msg...) do {} while (0) -#define PRINTM_MWARN(msg...) do {} while (0) -#define PRINTM_MENTRY(msg...) do {} while (0) +#define PRINTM_MINFO(level,msg...) do {} while (0) +#define PRINTM_MWARN(level,msg...) do {} while (0) +#define PRINTM_MENTRY(level,msg...) do {} while (0) #endif /* DEBUG_LEVEL2 */ -#define PRINTM_MFW_D(msg...) do {if (drvdbg & MFW_D) printk(KERN_DEBUG msg);} while(0) -#define PRINTM_MCMD_D(msg...) do {if (drvdbg & MCMD_D) printk(KERN_DEBUG msg);} while(0) -#define PRINTM_MDAT_D(msg...) do {if (drvdbg & MDAT_D) printk(KERN_DEBUG msg);} while(0) -#define PRINTM_MIF_D(msg...) do {if (drvdbg & MIF_D) printk(KERN_DEBUG msg);} while(0) +#define PRINTM_MFW_D(level,msg...) do {woal_print(level,msg); \ + if (drvdbg & MFW_D) printk(KERN_DEBUG msg);} while(0) +#define PRINTM_MCMD_D(level,msg...) do {woal_print(level,msg); \ + if (drvdbg & MCMD_D) printk(KERN_DEBUG msg);} while(0) +#define PRINTM_MDAT_D(level,msg...) do {woal_print(level,msg); \ + if (drvdbg & MDAT_D) printk(KERN_DEBUG msg);} while(0) +#define PRINTM_MIF_D(level,msg...) do {woal_print(level,msg); \ + if (drvdbg & MIF_D) printk(KERN_DEBUG msg);} while(0) + +#define PRINTM_MIOCTL(level,msg...) do {woal_print(level,msg); \ + if (drvdbg & MIOCTL) printk(KERN_DEBUG msg);} while(0) +#define PRINTM_MINTR(level,msg...) do {woal_print(level,msg); \ + if (drvdbg & MINTR) printk(KERN_DEBUG msg);} while(0) +#define PRINTM_MEVENT(level,msg...) do {woal_print(level,msg); \ + if (drvdbg & MEVENT) printk(msg);} while(0) +#define PRINTM_MCMND(level,msg...) do {woal_print(level,msg); \ + if (drvdbg & MCMND) printk(KERN_DEBUG msg);} while(0) +#define PRINTM_MDATA(level,msg...) do {woal_print(level,msg); \ + if (drvdbg & MDATA) printk(KERN_DEBUG msg);} while(0) +#define PRINTM_MERROR(level,msg...) do {woal_print(level,msg); \ + if (drvdbg & MERROR) printk(KERN_ERR msg);} while(0) +#define PRINTM_MFATAL(level,msg...) do {woal_print(level,msg); \ + if (drvdbg & MFATAL) printk(KERN_ERR msg);} while(0) +#define PRINTM_MMSG(level,msg...) do {woal_print(level,msg); \ + if (drvdbg & MMSG) printk(KERN_ALERT msg);} while(0) -#define PRINTM_MIOCTL(msg...) do {if (drvdbg & MIOCTL) printk(KERN_DEBUG msg);} while(0) -#define PRINTM_MINTR(msg...) do {if (drvdbg & MINTR) printk(KERN_DEBUG msg);} while(0) -#define PRINTM_MEVENT(msg...) do {if (drvdbg & MEVENT) printk(msg);} while(0) -#define PRINTM_MCMND(msg...) do {if (drvdbg & MCMND) printk(KERN_DEBUG msg);} while(0) -#define PRINTM_MDATA(msg...) do {if (drvdbg & MDATA) printk(KERN_DEBUG msg);} while(0) -#define PRINTM_MERROR(msg...) do {if (drvdbg & MERROR) printk(KERN_ERR msg);} while(0) -#define PRINTM_MFATAL(msg...) do {if (drvdbg & MFATAL) printk(KERN_ERR msg);} while(0) -#define PRINTM_MMSG(msg...) do {if (drvdbg & MMSG) printk(KERN_ALERT msg);} while(0) +static inline void +woal_print(t_u32 level, char *fmt, ...) +{ +} -#define PRINTM(level,msg...) PRINTM_##level(msg) +#define PRINTM(level,msg...) PRINTM_##level(level,msg) #else @@ -1154,34 +1325,43 @@ do { \ #define MAX_DUMP_PER_LINE 16 static inline void -hexdump(char *prompt, t_u8 * buf, int len) +hexdump(t_u32 level, char *prompt, t_u8 * buf, int len) { int i; char dbgdumpbuf[DBG_DUMP_BUF_LEN]; char *ptr = dbgdumpbuf; - printk(KERN_DEBUG "%s:\n", prompt); + if (drvdbg & level) + printk(KERN_DEBUG "%s:\n", prompt); for (i = 1; i <= len; i++) { ptr += snprintf(ptr, 4, "%02x ", *buf); buf++; if (i % MAX_DUMP_PER_LINE == 0) { *ptr = 0; - printk(KERN_DEBUG "%s\n", dbgdumpbuf); + if (drvdbg & level) + printk(KERN_DEBUG "%s\n", dbgdumpbuf); ptr = dbgdumpbuf; } } if (len % MAX_DUMP_PER_LINE) { *ptr = 0; - printk(KERN_DEBUG "%s\n", dbgdumpbuf); + if (drvdbg & level) + printk(KERN_DEBUG "%s\n", dbgdumpbuf); } } -#define DBG_HEXDUMP_MERROR(x,y,z) do {if (drvdbg & MERROR) hexdump(x,y,z);} while(0) -#define DBG_HEXDUMP_MCMD_D(x,y,z) do {if (drvdbg & MCMD_D) hexdump(x,y,z);} while(0) -#define DBG_HEXDUMP_MDAT_D(x,y,z) do {if (drvdbg & MDAT_D) hexdump(x,y,z);} while(0) -#define DBG_HEXDUMP_MIF_D(x,y,z) do {if (drvdbg & MIF_D) hexdump(x,y,z);} while(0) -#define DBG_HEXDUMP_MEVT_D(x,y,z) do {if (drvdbg & MEVT_D) hexdump(x,y,z);} while(0) -#define DBG_HEXDUMP_MFW_D(x,y,z) do {if (drvdbg & MFW_D) hexdump(x,y,z);} while(0) +#define DBG_HEXDUMP_MERROR(x,y,z) do {if ((drvdbg & MERROR) || \ + LOG_CTRL(MERROR)) hexdump(MERROR,x,y,z);} while(0) +#define DBG_HEXDUMP_MCMD_D(x,y,z) do {if ((drvdbg & MCMD_D) || \ + LOG_CTRL(MCMD_D)) hexdump(MCMD_D,x,y,z);} while(0) +#define DBG_HEXDUMP_MDAT_D(x,y,z) do {if ((drvdbg & MDAT_D) || \ + LOG_CTRL(MDAT_D)) hexdump(MDAT_D,x,y,z);} while(0) +#define DBG_HEXDUMP_MIF_D(x,y,z) do {if ((drvdbg & MIF_D) || \ + LOG_CTRL(MIF_D)) hexdump(MIF_D,x,y,z);} while(0) +#define DBG_HEXDUMP_MEVT_D(x,y,z) do {if ((drvdbg & MEVT_D) || \ + LOG_CTRL(MEVT_D)) hexdump(MEVT_D,x,y,z);} while(0) +#define DBG_HEXDUMP_MFW_D(x,y,z) do {if ((drvdbg & MFW_D) || \ + LOG_CTRL(MFW_D)) hexdump(MFW_D,x,y,z);} while(0) #define DBG_HEXDUMP(level,x,y,z) DBG_HEXDUMP_##level(x,y,z) #else @@ -1190,7 +1370,8 @@ hexdump(char *prompt, t_u8 * buf, int len) #endif #ifdef DEBUG_LEVEL2 -#define HEXDUMP(x,y,z) do {if (drvdbg & MINFO) hexdump(x,y,z);} while(0) +#define HEXDUMP(x,y,z) do {if ((drvdbg & MINFO) || \ + LOG_CTRL(MINFO)) hexdump(MINFO,x,y,z);} while(0) #else /** Do nothing since debugging is not turned on */ #define HEXDUMP(x,y,z) do {} while (0) @@ -1248,6 +1429,30 @@ woal_get_priv(moal_handle * handle, mlan_bss_role bss_role) return NULL; } +/** + * @brief This function returns first available priv + * based on the BSS type + * + * @param handle A pointer to moal_handle + * @param bss_type BSS type or MLAN_BSS_TYPE_ANY + * + * @return Pointer to moal_private + */ +static inline moal_private * +woal_get_priv_bss_type(moal_handle * handle, mlan_bss_type bss_type) +{ + int i; + + for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) { + if (handle->priv[i]) { + if (bss_type == MLAN_BSS_TYPE_ANY || + handle->priv[i]->bss_type == bss_type) + return (handle->priv[i]); + } + } + return NULL; +} + /** Max line length allowed in init config file */ #define MAX_LINE_LEN 256 /** Max MAC address string length allowed */ @@ -1282,6 +1487,11 @@ typedef struct _HostCmd_DS_802_11_CFG_DATA t_u8 data[1]; } __ATTRIB_PACK__ HostCmd_DS_802_11_CFG_DATA; +/** SD8797 card type */ +#define CARD_TYPE_SD8797 0x01 +/** SD8782 card type */ +#define CARD_TYPE_SD8782 0x02 + /** combo scan header */ #define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00" /** combo scan header size */ @@ -1300,6 +1510,19 @@ typedef struct _HostCmd_DS_802_11_CFG_DATA #define WEXT_BGSCAN_INTERVAL_SECTION 'T' /** BGSCAN REPEAT SECTION */ #define WEXT_BGSCAN_REPEAT_SECTION 'E' +/** Min BGSCAN interval 30 second */ +#define MIN_BGSCAN_INTERVAL 30000 +/** default repeat count */ +#define DEF_REPEAT_COUNT 6 + +/** default rssi low threshold */ +#define DEFAULT_RSSI_LOW_THRESHOLD 70 +/** RSSI HYSTERSIS */ +#define RSSI_HYSTERESIS 6 +/** lowest rssi threshold */ +#define LOWEST_RSSI_THRESHOLD 82 +/** delta rssi */ +#define DELTA_RSSI 10 /** NL80211 scan configuration header */ #define NL80211_SCANCFG_HEADER "SCAN-CFG " @@ -1356,14 +1579,14 @@ mlan_status woal_remove_card(void *card); /** broadcast event */ mlan_status woal_broadcast_event(moal_private * priv, t_u8 * payload, t_u32 len); +#ifdef CONFIG_PROC_FS /** switch driver mode */ mlan_status woal_switch_drv_mode(moal_handle * handle, t_u32 mode); +#endif /** Interrupt handler */ void woal_interrupt(moal_handle * handle); -#ifdef STA_WEXT -#endif /** Get version */ void woal_get_version(moal_handle * handle, char *version, int maxlen); /** Get Driver Version */ @@ -1388,7 +1611,9 @@ void woal_request_set_multicast_list(moal_private * priv, /** Request IOCTL action */ mlan_status woal_request_ioctl(moal_private * priv, mlan_ioctl_req * req, t_u8 wait_option); +#ifdef CONFIG_PROC_FS mlan_status woal_request_soft_reset(moal_handle * handle); +#endif #ifdef PROC_DEBUG /** Get debug information */ mlan_status woal_get_debug_info(moal_private * priv, t_u8 wait_option, @@ -1432,19 +1657,23 @@ void woal_send_disconnect_to_system(moal_private * priv); void woal_send_mic_error_event(moal_private * priv, t_u32 event); void woal_ioctl_get_bss_resp(moal_private * priv, mlan_ds_bss * bss); void woal_ioctl_get_info_resp(moal_private * priv, mlan_ds_get_info * info); +mlan_status woal_get_assoc_rsp(moal_private * priv, + mlan_ds_misc_assoc_rsp * assoc_rsp); /** Get signal information */ mlan_status woal_get_signal_info(moal_private * priv, t_u8 wait_option, mlan_ds_get_signal * signal); /** Get mode */ t_u32 woal_get_mode(moal_private * priv, t_u8 wait_option); +char *region_code_2_string(t_u8 region_code); +t_u8 woal_is_valid_alpha2(char *alpha2); +/** Get statistics information */ +mlan_status woal_get_stats_info(moal_private * priv, t_u8 wait_option, + mlan_ds_get_stats * stats); #ifdef STA_WEXT /** Get data rates */ mlan_status woal_get_data_rates(moal_private * priv, t_u8 wait_option, moal_802_11_rates * m_rates); -void woal_send_iwevcustom_event(moal_private * priv, t_s8 * str); -/** Get statistics information */ -mlan_status woal_get_stats_info(moal_private * priv, t_u8 wait_option, - mlan_ds_get_stats * stats); +void woal_send_iwevcustom_event(moal_private * priv, char *str); /** Get channel list */ mlan_status woal_get_channel_list(moal_private * priv, t_u8 wait_option, mlan_chan_list * chanlist); @@ -1528,7 +1757,6 @@ int woal_get_bss_type(struct net_device *dev, struct ifreq *req); #if defined(STA_WEXT) || defined(UAP_WEXT) int woal_host_command(moal_private * priv, struct iwreq *wrq); #endif -#if defined(WIFI_DIRECT_SUPPORT) #if defined(STA_SUPPORT) && defined(UAP_SUPPORT) mlan_status woal_bss_role_cfg(moal_private * priv, t_u8 action, t_u8 wait_option, t_u8 * bss_role); @@ -1539,7 +1767,6 @@ void woal_go_timer_func(void *context); int woal_set_get_bss_role(moal_private * priv, struct iwreq *wrq); #endif #endif -#endif #if defined(WIFI_DIRECT_SUPPORT) || defined(UAP_SUPPORT) /** hostcmd ioctl for uap, wifidirect */ int woal_hostcmd_ioctl(struct net_device *dev, struct ifreq *req); @@ -1574,6 +1801,8 @@ void woal_debug_remove(moal_private * priv); /** check pm info */ mlan_status woal_get_pm_info(moal_private * priv, mlan_ds_ps_info * pm_info); +/** get mlan debug info */ +void woal_mlan_debug_info(moal_private * priv); #ifdef REASSOCIATION int woal_reassociation_thread(void *data); @@ -1583,12 +1812,17 @@ void woal_reassoc_timer_func(void *context); t_void woal_main_work_queue(struct work_struct *work); int woal_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); +#ifdef STA_SUPPORT +mlan_status woal_init_sta_dev(struct net_device *dev, moal_private * priv); +#endif +#ifdef UAP_SUPPORT +mlan_status woal_init_uap_dev(struct net_device *dev, moal_private * priv); +#endif moal_private *woal_add_interface(moal_handle * handle, t_u8 bss_num, t_u8 bss_type); void woal_remove_interface(moal_handle * handle, t_u8 bss_index); void woal_set_multicast_list(struct net_device *dev); mlan_status woal_request_fw(moal_handle * handle); - int woal_11h_channel_check_ioctl(moal_private * priv); void woal_cancel_cac_block(moal_private * priv); void woal_moal_debug_info(moal_private * priv, moal_handle * handle, u8 flag); @@ -1596,6 +1830,7 @@ void woal_moal_debug_info(moal_private * priv, moal_handle * handle, u8 flag); #ifdef STA_SUPPORT mlan_status woal_get_powermode(moal_private * priv, int *powermode); mlan_status woal_set_scan_type(moal_private * priv, t_u32 scan_type); +mlan_status woal_enable_ext_scan(moal_private * priv, t_u8 enable); mlan_status woal_set_powermode(moal_private * priv, char *powermode); int woal_find_essid(moal_private * priv, mlan_ssid_bssid * ssid_bssid); mlan_status woal_do_scan(moal_private * priv, wlan_user_scan_cfg * scan_cfg); @@ -1607,30 +1842,38 @@ mlan_status woal_get_band(moal_private * priv, int *band); mlan_status woal_set_band(moal_private * priv, char *pband); mlan_status woal_add_rxfilter(moal_private * priv, char *rxfilter); mlan_status woal_remove_rxfilter(moal_private * priv, char *rxfilter); -mlan_status woal_set_qos_cfg(moal_private * priv, char *qos_cfg); +mlan_status woal_priv_qos_cfg(moal_private * priv, t_u32 action, char *qos_cfg); int woal_set_sleeppd(moal_private * priv, char *psleeppd); int woal_set_scan_cfg(moal_private * priv, char *buf, int length); /* EVENT: BCN_RSSI_LOW */ #define EVENT_BCN_RSSI_LOW 0x0001 /* EVENT: PRE_BCN_LOST */ #define EVENT_PRE_BCN_LOST 0x0002 -mlan_status woal_set_rssi_low_threshold(moal_private * priv, char *rssi); -mlan_status woal_set_rssi_threshold(moal_private * priv, t_u32 event_id); +mlan_status woal_set_rssi_low_threshold(moal_private * priv, char *rssi, + t_u8 wait_option); +mlan_status woal_set_rssi_threshold(moal_private * priv, t_u32 event_id, + t_u8 wait_option); /* EVENT: BG_SCAN_REPORT */ #define EVENT_BG_SCAN_REPORT 0x0004 mlan_status woal_set_bg_scan(moal_private * priv, char *buf, int length); -mlan_status woal_stop_bg_scan(moal_private * priv); +mlan_status woal_stop_bg_scan(moal_private * priv, t_u8 wait_option); void woal_reconfig_bgscan(moal_handle * handle); +#ifdef STA_CFG80211 +void woal_config_bgscan_and_rssi(moal_private * priv, t_u8 set_rssi); +void woal_save_conn_params(moal_private * priv, + struct cfg80211_connect_params *sme); +void woal_clear_conn_params(moal_private * priv); +void woal_start_roaming(moal_private * priv); +#endif +mlan_status woal_request_bgscan(moal_private * priv, t_u8 wait_option, + wlan_bgscan_cfg * scan_cfg); #endif -struct tcp_sess *woal_get_tcp_sess(moal_private * priv, - t_u32 src_ip, t_u16 src_port, - t_u32 dst_ip, t_u16 dst_port); -void woal_check_tcp_fin(moal_private * priv, struct sk_buff *skb); - +void woal_flush_tcp_sess_queue(moal_private * priv); void wlan_scan_create_brief_table_entry(t_u8 ** ppbuffer, BSSDescriptor_t * pbss_desc); int wlan_get_scan_table_ret_entry(BSSDescriptor_t * pbss_desc, t_u8 ** ppbuffer, int *pspace_left); BOOLEAN woal_ssid_valid(mlan_802_11_ssid * pssid); +int woal_is_connected(moal_private * priv, mlan_ssid_bssid * ssid_bssid); #endif /* _MOAL_MAIN_H */ diff --git a/drivers/net/wireless/sd8797/mlinux/moal_priv.c b/drivers/net/wireless/sd8797/mlinux/moal_priv.c index fd866346ee63..559da684299c 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_priv.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_priv.c @@ -27,9 +27,6 @@ Change log: #include "moal_main.h" #include "moal_sdio.h" -#if defined(STA_CFG80211) && defined(UAP_CFG80211) -#include "moal_cfg80211.h" -#endif #include "moal_eth_ioctl.h" /******************************************************** @@ -63,6 +60,97 @@ extern int cfg80211_wext; Local Functions ********************************************************/ +/** + * @brief Associated to a specific indexed entry in the ScanTable + * + * @param priv A pointer to moal_private structure + * @param req A pointer to ifreq structure + * + * @return 0 --success, otherwise fail + */ +static int +woal_associate_ssid_bssid(moal_private * priv, struct iwreq *wrq) +{ + mlan_ssid_bssid ssid_bssid; +#ifdef REASSOCIATION + mlan_bss_info bss_info; +#endif + char buf[64]; + t_u8 buflen; + t_u8 mac_idx; + t_u8 i; + + ENTER(); + + mac_idx = 0; + buflen = MIN(wrq->u.data.length, (sizeof(buf) - 1)); + memset(buf, 0, sizeof(buf)); + + if (buflen < (3 * ETH_ALEN) + 2) { + PRINTM(MERROR, "Associate: Insufficient length in IOCTL input\n"); + + /* buffer should be at least 3 characters per BSSID octet "00:" ** plus + a space separater and at least 1 char in the SSID */ + LEAVE(); + return -EINVAL; + } + + if (copy_from_user(buf, wrq->u.data.pointer, buflen) != 0) { + /* copy_from_user failed */ + PRINTM(MERROR, "Associate: copy from user failed\n"); + LEAVE(); + return -EINVAL; + } + + for (i = 0; (i < buflen) && (buf[i] == ' '); i++) { + /* Skip white space */ + } + + /* Copy/Convert the BSSID */ + for (; (i < buflen) && (mac_idx < ETH_ALEN) && (buf[i] != ' '); i++) { + if (buf[i] == ':') { + mac_idx++; + } else { + ssid_bssid.bssid[mac_idx] = (t_u8) woal_atox(buf + i); + + while ((isxdigit(buf[i + 1]) && (i < buflen))) { + /* Skip entire hex value */ + i++; + } + } + } + + /* Skip one space between the BSSID and start of the SSID */ + i++; + + /* Copy the SSID */ + ssid_bssid.ssid.ssid_len = buflen - i - 1; + memcpy(ssid_bssid.ssid.ssid, buf + i, sizeof(ssid_bssid.ssid.ssid)); + + PRINTM(MCMND, "iwpriv assoc: AP=[" MACSTR "], ssid(%d)=[%s]\n", + MAC2STR(ssid_bssid.bssid), + (int) ssid_bssid.ssid.ssid_len, ssid_bssid.ssid.ssid); + + if (MLAN_STATUS_SUCCESS != woal_bss_start(priv, + MOAL_IOCTL_WAIT, &ssid_bssid)) { + LEAVE(); + return -EFAULT; + } +#ifdef REASSOCIATION + memset(&bss_info, 0x00, sizeof(bss_info)); + if (MLAN_STATUS_SUCCESS == woal_get_bss_info(priv, + MOAL_IOCTL_WAIT, &bss_info)) { + memcpy(&priv->prev_ssid_bssid.ssid, + &bss_info.ssid, sizeof(mlan_802_11_ssid)); + memcpy(&priv->prev_ssid_bssid.bssid, + &bss_info.bssid, MLAN_MAC_ADDR_LENGTH); + } +#endif /* REASSOCIATION */ + + LEAVE(); + return 0; +} + /** * @brief Copy Rates * @@ -369,15 +457,18 @@ static int woal_deep_sleep_ioctl(moal_private * priv, struct iwreq *wrq) { int ret = 0; + int user_data_len; t_u32 deep_sleep = DEEP_SLEEP_OFF; t_u32 data[2]; + int copy_len; t_u16 idletime = DEEP_SLEEP_IDLE_TIME; ENTER(); - if (wrq->u.data.length == 1 || wrq->u.data.length == 2) { - if (copy_from_user - (&data, wrq->u.data.pointer, wrq->u.data.length * sizeof(int))) { + user_data_len = wrq->u.data.length; + copy_len = MIN(sizeof(data), sizeof(int) * user_data_len); + if (user_data_len == 1 || user_data_len == 2) { + if (copy_from_user(&data, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "Copy from user failed\n"); LEAVE(); return -EFAULT; @@ -392,7 +483,7 @@ woal_deep_sleep_ioctl(moal_private * priv, struct iwreq *wrq) } } else if (deep_sleep == DEEP_SLEEP_ON) { PRINTM(MINFO, "Enter Deep Sleep Mode\n"); - if (wrq->u.data.length == 2) + if (user_data_len == 2) idletime = data[1]; else idletime = 0; @@ -406,8 +497,8 @@ woal_deep_sleep_ioctl(moal_private * priv, struct iwreq *wrq) LEAVE(); return -EINVAL; } - } else if (wrq->u.data.length > 2) { - PRINTM(MERROR, "Invalid number of arguments %d\n", wrq->u.data.length); + } else if (user_data_len > 2) { + PRINTM(MERROR, "Invalid number of arguments %d\n", user_data_len); LEAVE(); return -EINVAL; } else { /* Display Deep Sleep settings */ @@ -445,7 +536,7 @@ woal_deep_sleep_ioctl(moal_private * priv, struct iwreq *wrq) static int woal_11n_htcap_cfg(moal_private * priv, struct iwreq *wrq) { - int data[2]; + int data[2], copy_len; mlan_ioctl_req *req = NULL; mlan_ds_11n_cfg *cfg_11n = NULL; int ret = 0; @@ -468,13 +559,13 @@ woal_11n_htcap_cfg(moal_private * priv, struct iwreq *wrq) cfg_11n->sub_command = MLAN_OID_11N_HTCAP_CFG; req->req_id = MLAN_IOCTL_11N_CFG; + copy_len = MIN(sizeof(data), sizeof(int) * data_length); if (data_length == 0) { /* Get 11n tx parameters from MLAN */ req->action = MLAN_ACT_GET; cfg_11n->param.htcap_cfg.misc_cfg = BAND_SELECT_BG; } else { - if (copy_from_user - (data, wrq->u.data.pointer, data_length * sizeof(int))) { + if (copy_from_user(data, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; @@ -547,18 +638,20 @@ woal_11n_htcap_cfg(moal_private * priv, struct iwreq *wrq) static int woal_11n_amsdu_aggr_ctrl(moal_private * priv, struct iwreq *wrq) { - int data[2]; + int data[2], copy_len; mlan_ioctl_req *req = NULL; mlan_ds_11n_cfg *cfg_11n = NULL; int ret = 0; + int data_length = wrq->u.data.length; ENTER(); - if ((wrq->u.data.length != 0) && (wrq->u.data.length != 1)) { + if ((data_length != 0) && (data_length != 1)) { PRINTM(MERROR, "Invalid number of arguments\n"); ret = -EINVAL; goto done; } + copy_len = MIN(sizeof(data), sizeof(int) * data_length); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg)); if (req == NULL) { ret = -ENOMEM; @@ -569,12 +662,11 @@ woal_11n_amsdu_aggr_ctrl(moal_private * priv, struct iwreq *wrq) cfg_11n->sub_command = MLAN_OID_11N_CFG_AMSDU_AGGR_CTRL; req->req_id = MLAN_IOCTL_11N_CFG; - if (wrq->u.data.length == 0) { + if (data_length == 0) { /* Get 11n tx parameters from MLAN */ req->action = MLAN_ACT_GET; - } else if (wrq->u.data.length == 1) { - if (copy_from_user(data, wrq->u.data.pointer, - wrq->u.data.length * sizeof(int))) { + } else if (data_length == 1) { + if (copy_from_user(data, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; @@ -614,7 +706,7 @@ woal_11n_amsdu_aggr_ctrl(moal_private * priv, struct iwreq *wrq) static int woal_11n_tx_cfg(moal_private * priv, struct iwreq *wrq) { - int data[2]; + int data[2], copy_len; mlan_ioctl_req *req = NULL; mlan_ds_11n_cfg *cfg_11n = NULL; int ret = 0; @@ -627,6 +719,7 @@ woal_11n_tx_cfg(moal_private * priv, struct iwreq *wrq) ret = -EINVAL; goto done; } + copy_len = MIN(sizeof(data), sizeof(int) * data_length); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg)); if (req == NULL) { ret = -ENOMEM; @@ -637,13 +730,12 @@ woal_11n_tx_cfg(moal_private * priv, struct iwreq *wrq) cfg_11n->sub_command = MLAN_OID_11N_CFG_TX; req->req_id = MLAN_IOCTL_11N_CFG; - if (wrq->u.data.length == 0) { + if (data_length == 0) { /* Get 11n tx parameters from MLAN */ req->action = MLAN_ACT_GET; cfg_11n->param.tx_cfg.misc_cfg = BAND_SELECT_BG; } else { - if (copy_from_user - (data, wrq->u.data.pointer, data_length * sizeof(int))) { + if (copy_from_user(data, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; @@ -714,10 +806,11 @@ woal_11n_tx_cfg(moal_private * priv, struct iwreq *wrq) static int woal_11n_prio_tbl(moal_private * priv, struct iwreq *wrq) { - int data[MAX_NUM_TID * 2], i, j; + int data[MAX_NUM_TID * 2], i, j, copy_len; mlan_ioctl_req *req = NULL; mlan_ds_11n_cfg *cfg_11n = NULL; int ret = 0; + int data_length = wrq->u.data.length; ENTER(); @@ -725,6 +818,7 @@ woal_11n_prio_tbl(moal_private * priv, struct iwreq *wrq) LEAVE(); return -EINVAL; } + copy_len = MIN(sizeof(data), sizeof(int) * data_length); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg)); if (req == NULL) { @@ -735,7 +829,7 @@ woal_11n_prio_tbl(moal_private * priv, struct iwreq *wrq) cfg_11n->sub_command = MLAN_OID_11N_CFG_AGGR_PRIO_TBL; req->req_id = MLAN_IOCTL_11N_CFG; - if (wrq->u.data.length == 0) { + if (data_length == 0) { /* Get aggr priority table from MLAN */ req->action = MLAN_ACT_GET; if (MLAN_STATUS_SUCCESS != @@ -755,14 +849,13 @@ woal_11n_prio_tbl(moal_private * priv, struct iwreq *wrq) ret = -EFAULT; goto error; } - } else if (wrq->u.data.length == 16) { - if (copy_from_user(data, wrq->u.data.pointer, - sizeof(int) * wrq->u.data.length)) { + } else if (data_length == 16) { + if (copy_from_user(data, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto error; } - for (i = 0, j = 0; i < (wrq->u.data.length); i = i + 2, ++j) { + for (i = 0, j = 0; i < (data_length); i = i + 2, ++j) { if ((data[i] > 7 && data[i] != 0xff) || (data[i + 1] > 7 && data[i + 1] != 0xff)) { PRINTM(MERROR, "Invalid priority, valid value 0-7 or 0xff.\n"); @@ -805,12 +898,13 @@ woal_11n_prio_tbl(moal_private * priv, struct iwreq *wrq) static int woal_addba_reject(moal_private * priv, struct iwreq *wrq) { - int data[MAX_NUM_TID], ret = 0, i; + int data[MAX_NUM_TID], ret = 0, i, copy_len; mlan_ioctl_req *req = NULL; mlan_ds_11n_cfg *cfg_11n = NULL; - + int data_length = wrq->u.data.length; ENTER(); + copy_len = MIN(sizeof(data), sizeof(int) * data_length); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg)); if (req == NULL) { LEAVE(); @@ -820,7 +914,7 @@ woal_addba_reject(moal_private * priv, struct iwreq *wrq) cfg_11n->sub_command = MLAN_OID_11N_CFG_ADDBA_REJECT; req->req_id = MLAN_IOCTL_11N_CFG; - if (wrq->u.data.length == 0) { + if (data_length == 0) { PRINTM(MERROR, "Addba reject moal\n"); /* Get aggr priority table from MLAN */ req->action = MLAN_ACT_GET; @@ -841,14 +935,13 @@ woal_addba_reject(moal_private * priv, struct iwreq *wrq) ret = -EFAULT; goto error; } - } else if (wrq->u.data.length == 8) { - if (copy_from_user(data, wrq->u.data.pointer, - sizeof(int) * wrq->u.data.length)) { + } else if (data_length == 8) { + if (copy_from_user(data, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto error; } - for (i = 0; i < (wrq->u.data.length); ++i) { + for (i = 0; i < (data_length); ++i) { if (data[i] != 0 && data[i] != 1) { PRINTM(MERROR, "addba reject only takes argument as 0 or 1\n"); ret = -EFAULT; @@ -888,12 +981,14 @@ woal_addba_reject(moal_private * priv, struct iwreq *wrq) static int woal_addba_para_updt(moal_private * priv, struct iwreq *wrq) { - int data[5], ret = 0; + int data[5], ret = 0, copy_len; mlan_ioctl_req *req = NULL; mlan_ds_11n_cfg *cfg_11n = NULL; + int data_length = wrq->u.data.length; ENTER(); + copy_len = MIN(sizeof(data), sizeof(int) * data_length); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg)); if (req == NULL) { LEAVE(); @@ -903,7 +998,7 @@ woal_addba_para_updt(moal_private * priv, struct iwreq *wrq) cfg_11n->sub_command = MLAN_OID_11N_CFG_ADDBA_PARAM; req->req_id = MLAN_IOCTL_11N_CFG; - if (wrq->u.data.length == 0) { + if (data_length == 0) { /* Get Add BA parameters from MLAN */ req->action = MLAN_ACT_GET; if (MLAN_STATUS_SUCCESS != @@ -926,9 +1021,8 @@ woal_addba_para_updt(moal_private * priv, struct iwreq *wrq) ret = -EFAULT; goto error; } - } else if (wrq->u.data.length == 5) { - if (copy_from_user - (data, wrq->u.data.pointer, wrq->u.data.length * sizeof(int))) { + } else if (data_length == 5) { + if (copy_from_user(data, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto error; @@ -1043,7 +1137,7 @@ woal_txbuf_cfg(moal_private * priv, struct iwreq *wrq) static int woal_hs_cfg(moal_private * priv, struct iwreq *wrq, BOOLEAN invoke_hostcmd) { - int data[3]; + int data[3], copy_len; int ret = 0; mlan_ds_hs_cfg hscfg; t_u16 action; @@ -1054,14 +1148,14 @@ woal_hs_cfg(moal_private * priv, struct iwreq *wrq, BOOLEAN invoke_hostcmd) memset(data, 0, sizeof(data)); memset(&hscfg, 0, sizeof(mlan_ds_hs_cfg)); + copy_len = MIN(sizeof(data), sizeof(int) * data_length); if (data_length == 0) { action = MLAN_ACT_GET; } else { action = MLAN_ACT_SET; if (data_length >= 1 && data_length <= 3) { - if (copy_from_user - (data, wrq->u.data.pointer, sizeof(int) * data_length)) { + if (copy_from_user(data, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; @@ -1171,7 +1265,7 @@ woal_hs_setpara(moal_private * priv, struct iwreq *wrq) static int woal_inactivity_timeout_ext(moal_private * priv, struct iwreq *wrq) { - int data[4]; + int data[4], copy_len; int ret = 0; mlan_ioctl_req *req = NULL; mlan_ds_pm_cfg *pmcfg = NULL; @@ -1180,6 +1274,7 @@ woal_inactivity_timeout_ext(moal_private * priv, struct iwreq *wrq) ENTER(); + copy_len = MIN(sizeof(data), sizeof(int) * data_length); memset(data, 0, sizeof(data)); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg)); if (req == NULL) { @@ -1201,8 +1296,7 @@ woal_inactivity_timeout_ext(moal_private * priv, struct iwreq *wrq) req->action = MLAN_ACT_GET; if (data_length) { - if (copy_from_user - (data, wrq->u.data.pointer, sizeof(int) * data_length)) { + if (copy_from_user(data, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; @@ -1253,7 +1347,7 @@ woal_inactivity_timeout_ext(moal_private * priv, struct iwreq *wrq) static int woal_ecl_sys_clock(moal_private * priv, struct iwreq *wrq) { - int data[64]; + int data[64], copy_len; int ret = 0; mlan_ioctl_req *req = NULL; mlan_ds_misc_cfg *cfg = NULL; @@ -1263,6 +1357,7 @@ woal_ecl_sys_clock(moal_private * priv, struct iwreq *wrq) ENTER(); memset(data, 0, sizeof(data)); + copy_len = MIN(sizeof(data), sizeof(int) * data_length); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); if (req == NULL) { @@ -1278,8 +1373,7 @@ woal_ecl_sys_clock(moal_private * priv, struct iwreq *wrq) req->action = MLAN_ACT_GET; else if (data_length <= MLAN_MAX_CLK_NUM) { req->action = MLAN_ACT_SET; - if (copy_from_user - (data, wrq->u.data.pointer, sizeof(int) * data_length)) { + if (copy_from_user(data, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; @@ -1371,7 +1465,7 @@ woal_band_cfg(moal_private * priv, struct iwreq *wrq) int ret = 0; unsigned int i; int data[4]; - int user_data_len = wrq->u.data.length; + int user_data_len = wrq->u.data.length, copy_len; t_u32 infra_band = 0; t_u32 adhoc_band = 0; t_u32 adhoc_channel = 0; @@ -1394,6 +1488,7 @@ woal_band_cfg(moal_private * priv, struct iwreq *wrq) } } + copy_len = MIN(sizeof(data), sizeof(int) * user_data_len); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg)); if (req == NULL) { ret = -ENOMEM; @@ -1429,8 +1524,7 @@ woal_band_cfg(moal_private * priv, struct iwreq *wrq) goto error; } } else { - if (copy_from_user - (data, wrq->u.data.pointer, sizeof(int) * user_data_len)) { + if (copy_from_user(data, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto error; @@ -1517,7 +1611,7 @@ woal_band_cfg(moal_private * priv, struct iwreq *wrq) static int woal_reg_read_write(moal_private * priv, struct iwreq *wrq) { - int data[3]; + int data[3], copy_len; int ret = 0; mlan_ioctl_req *req = NULL; mlan_ds_reg_mem *reg = NULL; @@ -1526,6 +1620,7 @@ woal_reg_read_write(moal_private * priv, struct iwreq *wrq) ENTER(); memset(data, 0, sizeof(data)); + copy_len = MIN(sizeof(data), sizeof(int) * data_length); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_reg_mem)); if (req == NULL) { @@ -1545,7 +1640,7 @@ woal_reg_read_write(moal_private * priv, struct iwreq *wrq) ret = -EINVAL; goto done; } - if (copy_from_user(data, wrq->u.data.pointer, sizeof(int) * data_length)) { + if (copy_from_user(data, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; @@ -1588,7 +1683,7 @@ woal_reg_read_write(moal_private * priv, struct iwreq *wrq) static int woal_read_eeprom(moal_private * priv, struct iwreq *wrq) { - int data[2]; + int data[2], copy_len; int ret = 0; mlan_ioctl_req *req = NULL; mlan_ds_reg_mem *reg = NULL; @@ -1597,6 +1692,7 @@ woal_read_eeprom(moal_private * priv, struct iwreq *wrq) ENTER(); memset(data, 0, sizeof(data)); + copy_len = MIN(sizeof(data), sizeof(int) * data_length); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_reg_mem)); if (req == NULL) { @@ -1614,7 +1710,7 @@ woal_read_eeprom(moal_private * priv, struct iwreq *wrq) ret = -EINVAL; goto done; } - if (copy_from_user(data, wrq->u.data.pointer, sizeof(int) * data_length)) { + if (copy_from_user(data, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; @@ -1661,11 +1757,12 @@ woal_mem_read_write(moal_private * priv, struct iwreq *wrq) int ret = 0; mlan_ioctl_req *req = NULL; mlan_ds_reg_mem *reg_mem = NULL; - int data_length = wrq->u.data.length; + int data_length = wrq->u.data.length, copy_len; ENTER(); memset(data, 0, sizeof(data)); + copy_len = MIN(sizeof(data), sizeof(int) * data_length); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_reg_mem)); if (req == NULL) { @@ -1687,7 +1784,7 @@ woal_mem_read_write(moal_private * priv, struct iwreq *wrq) ret = -EINVAL; goto done; } - if (copy_from_user(data, wrq->u.data.pointer, sizeof(int) * data_length)) { + if (copy_from_user(data, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; @@ -1770,7 +1867,9 @@ woal_get_log(moal_private * priv, struct iwreq *wrq) "wepicverrcnt-1 %u\n" "wepicverrcnt-2 %u\n" "wepicverrcnt-3 %u\n" - "wepicverrcnt-4 %u\n", + "wepicverrcnt-4 %u\n" + "beacon_rcnt %u\n" + "beacon_mcnt %u\n", stats.mcast_tx_frame, stats.failed, stats.retry, @@ -1785,7 +1884,8 @@ woal_get_log(moal_private * priv, struct iwreq *wrq) stats.tx_frame, stats.wep_icv_error[0], stats.wep_icv_error[1], - stats.wep_icv_error[2], stats.wep_icv_error[3]); + stats.wep_icv_error[2], + stats.wep_icv_error[3], stats.bcn_rcv_cnt, stats.bcn_miss_cnt); wrq->u.data.length = strlen(buf) + 1; if (copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length)) { PRINTM(MERROR, "Copy to user failed\n"); @@ -1846,7 +1946,7 @@ woal_deauth(moal_private * priv, struct iwreq *wrq) static int woal_tx_power_cfg(moal_private * priv, struct iwreq *wrq) { - int data[5], user_data_len; + int data[5], user_data_len, copy_len; int ret = 0; mlan_bss_info bss_info; mlan_ds_power_cfg *pcfg = NULL; @@ -1858,6 +1958,7 @@ woal_tx_power_cfg(moal_private * priv, struct iwreq *wrq) memset(data, 0, sizeof(data)); user_data_len = wrq->u.data.length; + copy_len = MIN(sizeof(data), sizeof(int) * user_data_len); if (user_data_len) { if (sizeof(int) * user_data_len > sizeof(data)) { @@ -1865,8 +1966,7 @@ woal_tx_power_cfg(moal_private * priv, struct iwreq *wrq) ret = -EINVAL; goto done; } - if (copy_from_user - (data, wrq->u.data.pointer, sizeof(int) * user_data_len)) { + if (copy_from_user(data, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; @@ -2381,12 +2481,13 @@ woal_set_get_radio(moal_private * priv, struct iwreq *wrq) static int woal_drv_dbg(moal_private * priv, struct iwreq *wrq) { - int data[4]; + int data[4], copy_len; int ret = 0; - + int data_length = wrq->u.data.length; ENTER(); - if (!wrq->u.data.length) { + copy_len = MIN(sizeof(data), sizeof(int) * data_length); + if (!data_length) { data[0] = drvdbg; /* Return the current driver debug bit masks */ if (copy_to_user(wrq->u.data.pointer, data, sizeof(int))) { @@ -2395,10 +2496,9 @@ woal_drv_dbg(moal_private * priv, struct iwreq *wrq) goto drvdbgexit; } wrq->u.data.length = 1; - } else if (wrq->u.data.length < 3) { + } else if (data_length < 3) { /* Get the driver debug bit masks from user */ - if (copy_from_user - (data, wrq->u.data.pointer, sizeof(int) * wrq->u.data.length)) { + if (copy_from_user(data, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto drvdbgexit; @@ -2637,7 +2737,8 @@ woal_sleep_params_ioctl(moal_private * priv, struct iwreq *wrq) mlan_ioctl_req *req = NULL; mlan_ds_pm_cfg *pm = NULL; mlan_ds_sleep_params *psleep_params = NULL; - int data[6] = { 0 }, i; + int data[6] = { 0 }, i, copy_len; + int data_length = wrq->u.data.length; #ifdef DEBUG_LEVEL1 char err_str[][35] = { {"sleep clock error in ppm"}, {"wakeup offset in usec"}, @@ -2648,6 +2749,7 @@ woal_sleep_params_ioctl(moal_private * priv, struct iwreq *wrq) ENTER(); + copy_len = MIN(sizeof(data), sizeof(int) * data_length); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg)); if (req == NULL) { LEAVE(); @@ -2659,11 +2761,10 @@ woal_sleep_params_ioctl(moal_private * priv, struct iwreq *wrq) req->req_id = MLAN_IOCTL_PM_CFG; psleep_params = (pmlan_ds_sleep_params) & pm->param.sleep_params; - if (wrq->u.data.length == 0) { + if (data_length == 0) { req->action = MLAN_ACT_GET; - } else if (wrq->u.data.length == 6) { - if (copy_from_user(data, wrq->u.data.pointer, sizeof(int) * - wrq->u.data.length)) { + } else if (data_length == 6) { + if (copy_from_user(data, wrq->u.data.pointer, copy_len)) { /* copy_from_user failed */ PRINTM(MERROR, "S_PARAMS: copy from user failed\n"); LEAVE(); @@ -3264,28 +3365,30 @@ static int woal_passphrase(moal_private * priv, struct iwreq *wrq) { t_u16 len = 0; - static char buf[256]; + char buf[256]; char *begin, *end, *opt; int ret = 0, action = -1, i; mlan_ds_sec_cfg *sec = NULL; mlan_ioctl_req *req = NULL; t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 }; t_u8 *mac = NULL; + int data_length = wrq->u.data.length, copy_len; ENTER(); - if (!wrq->u.data.length || wrq->u.data.length >= sizeof(buf)) { + if (!data_length || data_length >= sizeof(buf)) { PRINTM(MERROR, "Argument missing or too long for setpassphrase\n"); ret = -EINVAL; goto done; } + memset(buf, 0, sizeof(buf)); + copy_len = data_length; - if (copy_from_user(buf, wrq->u.data.pointer, wrq->u.data.length)) { + if (copy_from_user(buf, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; } - buf[wrq->u.data.length] = '\0'; /* Parse the buf to get the cmd_action */ begin = buf; @@ -3347,8 +3450,8 @@ woal_passphrase(moal_private * priv, struct iwreq *wrq) break; } sec->param.passphrase.psk_type = MLAN_PSK_PASSPHRASE; - strncpy(sec->param.passphrase.psk.passphrase.passphrase, end, - sizeof(sec->param.passphrase.psk.passphrase.passphrase)); + memcpy(sec->param.passphrase.psk.passphrase.passphrase, end, + sizeof(sec->param.passphrase.psk.passphrase.passphrase)); sec->param.passphrase.psk.passphrase.passphrase_len = strlen(end); PRINTM(MINFO, "passphrase=%s, len=%d\n", sec->param.passphrase.psk.passphrase.passphrase, @@ -3483,11 +3586,12 @@ woal_adhoc_aes_ioctl(moal_private * priv, struct iwreq *wrq) mlan_ds_sec_cfg *sec = NULL; mlan_ioctl_req *req = NULL; t_u8 bcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - + int data_length = wrq->u.data.length, copy_len; ENTER(); memset(key_ascii, 0x00, sizeof(key_ascii)); memset(key_hex, 0x00, sizeof(key_hex)); + memset(buf, 0x00, sizeof(buf)); /* Get current BSS information */ memset(&bss_info, 0, sizeof(bss_info)); @@ -3504,21 +3608,21 @@ woal_adhoc_aes_ioctl(moal_private * priv, struct iwreq *wrq) ret = -ENOMEM; goto done; } + copy_len = data_length; - if (wrq->u.data.length) { - if (wrq->u.data.length >= sizeof(buf)) { + if (data_length) { + if (data_length >= sizeof(buf)) { PRINTM(MERROR, "Too many arguments\n"); ret = -EINVAL; goto done; } - if (copy_from_user(buf, wrq->u.data.pointer, wrq->u.data.length)) { + if (copy_from_user(buf, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; } - buf[wrq->u.data.length] = '\0'; - if (wrq->u.data.length == 1) { + if (data_length == 1) { /* Get Adhoc AES Key */ req->req_id = MLAN_IOCTL_SEC_CFG; req->action = MLAN_ACT_GET; @@ -3541,7 +3645,7 @@ woal_adhoc_aes_ioctl(moal_private * priv, struct iwreq *wrq) tmp = key_ascii; for (i = 0; i < sizeof(key_hex); i++) tmp += sprintf((char *) tmp, "%02x", key_hex[i]); - } else if (wrq->u.data.length >= 2) { + } else if (data_length >= 2) { /* Parse the buf to get the cmd_action */ action = woal_atox(&buf[0]); if (action < 1 || action > 2) { @@ -3575,7 +3679,7 @@ woal_adhoc_aes_ioctl(moal_private * priv, struct iwreq *wrq) ret = -EFAULT; goto done; } - } else if (action == 2) { + } else { /* Clear Adhoc AES Key */ sec->param.encrypt_key.key_len = AES_KEY_LEN; sec->param.encrypt_key.key_index = MLAN_KEY_INDEX_UNICAST; @@ -3590,10 +3694,6 @@ woal_adhoc_aes_ioctl(moal_private * priv, struct iwreq *wrq) ret = -EFAULT; goto done; } - } else { - PRINTM(MERROR, "Invalid argument\n"); - ret = -EINVAL; - goto done; } } @@ -3630,9 +3730,12 @@ 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; 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; @@ -3643,11 +3746,11 @@ woal_arp_filter(moal_private * priv, struct iwreq *wrq) 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 = wrq->u.data.length; + 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, wrq->u.data.length)) { + (misc->param.gen_ie.ie_data, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "copy from user failed\n"); ret = -EFAULT; goto done; @@ -3693,7 +3796,7 @@ woal_set_get_ip_addr(moal_private * priv, struct iwreq *wrq) ioctl_req->action = MLAN_ACT_GET; } else { if (copy_from_user(buf, wrq->u.data.pointer, - MIN(IPADDR_MAX_BUF - 1, wrq->u.data.length))) { + MIN(IPADDR_MAX_BUF - 1, data_length))) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; @@ -3709,7 +3812,7 @@ woal_set_get_ip_addr(moal_private * priv, struct iwreq *wrq) ioctl_req->action = MLAN_ACT_SET; /* only one IP is supported in current firmware */ memset(misc->param.ipaddr_cfg.ip_addr[0], 0, IPADDR_LEN); - in4_pton(&buf[2], MIN((IPADDR_MAX_BUF - 3), (wrq->u.data.length - 2)), + in4_pton(&buf[2], MIN((IPADDR_MAX_BUF - 3), (data_length - 2)), misc->param.ipaddr_cfg.ip_addr[0], ' ', NULL); /* only one IP is supported in current firmware */ misc->param.ipaddr_cfg.ip_addr_num = 1; @@ -4538,7 +4641,7 @@ woal_cmd53rdwr_ioctl(moal_private * priv, struct iwreq *wrq) pattern_len = wrq->u.data.length - 11; if (pattern_len > total_len) pattern_len = total_len; - memset(data, 0, sizeof(data)); + memset(data, 0, WOAL_2K_BYTES); /* Copy/duplicate the pattern to data buffer */ for (pos = 0; pos < total_len; pos++) @@ -4573,7 +4676,7 @@ woal_cmd53rdwr_ioctl(moal_private * priv, struct iwreq *wrq) static int woal_do_sdio_mpa_ctrl(moal_private * priv, struct iwreq *wrq) { - int data[6], data_length = wrq->u.data.length; + int data[6], data_length = wrq->u.data.length, copy_len; int ret = 0; mlan_ds_misc_cfg *misc = NULL; mlan_ioctl_req *req = NULL; @@ -4585,6 +4688,7 @@ woal_do_sdio_mpa_ctrl(moal_private * priv, struct iwreq *wrq) ret = -EINVAL; goto done; } + copy_len = MIN(sizeof(data), sizeof(int) * data_length); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); if (req == NULL) { @@ -4627,13 +4731,10 @@ woal_do_sdio_mpa_ctrl(moal_private * priv, struct iwreq *wrq) goto done; } - if (sizeof(data) >= sizeof(int) * data_length) { - if (copy_from_user(data, wrq->u.data.pointer, - sizeof(int) * data_length)) { - PRINTM(MINFO, "Copy from user failed\n"); - ret = -EFAULT; - goto done; - } + if (copy_from_user(data, wrq->u.data.pointer, copy_len)) { + PRINTM(MINFO, "Copy from user failed\n"); + ret = -EFAULT; + goto done; } switch (data_length) { @@ -4690,17 +4791,19 @@ woal_set_get_scan_cfg(moal_private * priv, struct iwreq *wrq) { int ret = 0; int arg_len = 7; - int data[arg_len]; + int data[arg_len], copy_len; mlan_ds_scan *scan = NULL; mlan_ioctl_req *req = NULL; + int data_length = wrq->u.data.length; ENTER(); + copy_len = MIN(sizeof(data), sizeof(int) * data_length); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_scan)); if (req == NULL) { ret = -ENOMEM; goto done; } - if (wrq->u.data.length > arg_len) { + if (data_length > arg_len) { ret = -EINVAL; goto done; } @@ -4708,9 +4811,9 @@ woal_set_get_scan_cfg(moal_private * priv, struct iwreq *wrq) scan->sub_command = MLAN_OID_SCAN_CONFIG; req->req_id = MLAN_IOCTL_SCAN; memset(data, 0, sizeof(data)); - if (wrq->u.data.length) { - if (copy_from_user - (data, wrq->u.data.pointer, (wrq->u.data.length * sizeof(int)))) { + + if (data_length) { + if (copy_from_user(data, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; @@ -4750,7 +4853,7 @@ woal_set_get_scan_cfg(moal_private * priv, struct iwreq *wrq) ret = -EFAULT; goto done; } - if (!wrq->u.data.length) { + if (!data_length) { memcpy(data, &scan->param.scan_cfg, sizeof(data)); if (copy_to_user(wrq->u.data.pointer, data, sizeof(data))) { ret = -EFAULT; @@ -4776,24 +4879,26 @@ woal_set_get_scan_cfg(moal_private * priv, struct iwreq *wrq) static int woal_set_get_ps_cfg(moal_private * priv, struct iwreq *wrq) { - int data[7], ret = 0; + int data[7], copy_len, ret = 0; mlan_ds_pm_cfg *pm_cfg = NULL; mlan_ioctl_req *req = NULL; int allowed = 3; int i = 3; + int data_length = wrq->u.data.length; ENTER(); allowed++; /* For ad-hoc awake period parameter */ allowed++; /* For beacon missing timeout parameter */ allowed += 2; /* For delay to PS and PS mode parameters */ + copy_len = MIN(sizeof(data), sizeof(int) * data_length); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg)); if (req == NULL) { ret = -ENOMEM; goto done; } - if (wrq->u.data.length > allowed) { + if (data_length > allowed) { ret = -EINVAL; goto done; } @@ -4801,9 +4906,9 @@ woal_set_get_ps_cfg(moal_private * priv, struct iwreq *wrq) pm_cfg->sub_command = MLAN_OID_PM_CFG_PS_CFG; req->req_id = MLAN_IOCTL_PM_CFG; memset(data, 0, sizeof(data)); - if (wrq->u.data.length) { - if (copy_from_user - (data, wrq->u.data.pointer, (wrq->u.data.length * sizeof(int)))) { + + if (data_length) { + if (copy_from_user(data, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; @@ -4844,7 +4949,7 @@ woal_set_get_ps_cfg(moal_private * priv, struct iwreq *wrq) goto done; } i++; - if (wrq->u.data.length < allowed - 1) + if (data_length < allowed - 1) data[i] = DELAY_TO_PS_UNCHANGED; else if ((data[i] < MIN_DELAY_TO_PS) || (data[i] > MAX_DELAY_TO_PS)) { PRINTM(MERROR, "Invalid argument for delay to PS\n"); @@ -5542,10 +5647,11 @@ woal_dfs_testing(moal_private * priv, struct iwreq *wrq) mlan_ioctl_req *req = NULL; mlan_ds_11h_cfg *ds_11hcfg = NULL; int ret = 0; - int data[4]; + int data[4], copy_len; int data_length = wrq->u.data.length; ENTER(); + copy_len = MIN(sizeof(data), sizeof(int) * data_length); /* Allocate an IOCTL request buffer */ req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg)); if (req == NULL) { @@ -5561,8 +5667,7 @@ woal_dfs_testing(moal_private * priv, struct iwreq *wrq) if (!data_length) { req->action = MLAN_ACT_GET; } else if (data_length == 4) { - if (copy_from_user - (data, wrq->u.data.pointer, sizeof(int) * data_length)) { + if (copy_from_user(data, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; @@ -5701,7 +5806,7 @@ static int woal_cfp_code(moal_private * priv, struct iwreq *wrq) { int ret = 0; - int data[2]; + int data[2], copy_len; int data_length = wrq->u.data.length; mlan_ioctl_req *req = NULL; mlan_ds_misc_cfg *misc_cfg = NULL; @@ -5714,6 +5819,7 @@ woal_cfp_code(moal_private * priv, struct iwreq *wrq) ret = -EINVAL; goto done; } + copy_len = MIN(sizeof(data), sizeof(int) * data_length); /* Allocate an IOCTL request buffer */ req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); @@ -5731,8 +5837,7 @@ woal_cfp_code(moal_private * priv, struct iwreq *wrq) if (!data_length) { req->action = MLAN_ACT_GET; } else { - if (copy_from_user - (data, wrq->u.data.pointer, sizeof(int) * data_length)) { + if (copy_from_user(data, wrq->u.data.pointer, copy_len)) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; @@ -6065,6 +6170,9 @@ woal_wext_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd) case WOAL_ADHOC_AES: ret = woal_adhoc_aes_ioctl(priv, wrq); break; + case WOAL_ASSOCIATE: + ret = woal_associate_ssid_bssid(priv, wrq); + break; case WOAL_WMM_QUEUE_STATUS: ret = woal_wmm_queue_status_ioctl(priv, wrq); break; @@ -6203,54 +6311,6 @@ woal_wext_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd) } /** - * @brief Get statistics information - * - * @param priv A pointer to moal_private structure - * @param wait_option Wait option - * @param stats A pointer to mlan_ds_get_stats structure - * - * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail - */ -mlan_status -woal_get_stats_info(moal_private * priv, t_u8 wait_option, - mlan_ds_get_stats * stats) -{ - int ret = 0; - mlan_ds_get_info *info = NULL; - mlan_ioctl_req *req = NULL; - mlan_status status = MLAN_STATUS_SUCCESS; - ENTER(); - - /* Allocate an IOCTL request buffer */ - req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info)); - if (req == NULL) { - ret = -ENOMEM; - goto done; - } - - /* Fill request buffer */ - info = (mlan_ds_get_info *) req->pbuf; - info->sub_command = MLAN_OID_GET_STATS; - req->req_id = MLAN_IOCTL_GET_INFO; - req->action = MLAN_ACT_GET; - - /* Send IOCTL request to MLAN */ - status = woal_request_ioctl(priv, req, wait_option); - if (status == MLAN_STATUS_SUCCESS) { - if (stats) - memcpy(stats, &info->param.stats, sizeof(mlan_ds_get_stats)); - priv->w_stats.discard.fragment = info->param.stats.fcs_error; - priv->w_stats.discard.retries = info->param.stats.retry; - priv->w_stats.discard.misc = info->param.stats.ack_failure; - } - done: - if (req && (status != MLAN_STATUS_PENDING)) - kfree(req); - LEAVE(); - return status; -} - -/** * @brief Get data rates * * @param priv A pointer to moal_private structure diff --git a/drivers/net/wireless/sd8797/mlinux/moal_priv.h b/drivers/net/wireless/sd8797/mlinux/moal_priv.h index 1c24f30502f6..494a2cae7837 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_priv.h +++ b/drivers/net/wireless/sd8797/mlinux/moal_priv.h @@ -179,6 +179,7 @@ Change log: #define WOAL_PASSPHRASE 1 /** Private command to get/set Ad-Hoc AES */ #define WOAL_ADHOC_AES 2 +#define WOAL_ASSOCIATE 3 /** Private command ID to get WMM queue status */ #define WOAL_WMM_QUEUE_STATUS 4 /** Private command ID to get Traffic stream status */ @@ -570,6 +571,11 @@ static const struct iw_priv_args woal_private_args[] = { IW_PRIV_TYPE_CHAR | 256, "adhocaes"}, { + WOAL_ASSOCIATE, + IW_PRIV_TYPE_CHAR | 256, + IW_PRIV_TYPE_CHAR | 256, + "associate"}, + { WOAL_WMM_QUEUE_STATUS, IW_PRIV_TYPE_CHAR | 256, IW_PRIV_TYPE_CHAR | 256, diff --git a/drivers/net/wireless/sd8797/mlinux/moal_proc.c b/drivers/net/wireless/sd8797/mlinux/moal_proc.c index 356fc79b9bed..5d43583fc1cd 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_proc.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_proc.c @@ -95,7 +95,7 @@ woal_info_proc_read(char *page, char **start, off_t offset, int mc_count = netdev_mc_count(netdev); #endif /* < 2.6.35 */ #else -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) int i = 0; #endif /* >= 2.6.29 */ #endif @@ -199,7 +199,7 @@ woal_info_proc_read(char *page, char **start, off_t offset, p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors); p += sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev)) ? "on" : "off")); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) for (i = 0; i < netdev->num_tx_queues; i++) { p += sprintf(p, "tx queue %d: %s\n", i, ((netif_tx_queue_stopped(netdev_get_tx_queue(netdev, 0))) ? @@ -268,7 +268,8 @@ parse_cmd52_string(const char __user * buffer, size_t len, int *func, int *reg, string = (char *) kmalloc(CMD52_STR_LEN, GFP_KERNEL); memset(string, 0, CMD52_STR_LEN); - memcpy(string, buffer + strlen("sdcmd52rw="), len - strlen("sdcmd52rw=")); + memcpy(string, buffer + strlen("sdcmd52rw="), + MIN((CMD52_STR_LEN - 1), (len - strlen("sdcmd52rw=")))); string = strstrip(string); *func = -1; @@ -316,6 +317,8 @@ woal_config_write(struct file *f, const char *buf, unsigned long cnt, t_u32 config_data = 0; moal_handle *handle = (moal_handle *) data; int func, reg, val; + int copy_len; + moal_private *priv = NULL; ENTER(); if (!MODULE_GET) { @@ -329,7 +332,8 @@ woal_config_write(struct file *f, const char *buf, unsigned long cnt, return (int) cnt; } memset(databuf, 0, sizeof(databuf)); - if (copy_from_user(databuf, buf, cnt)) { + copy_len = MIN((sizeof(databuf) - 1), cnt); + if (copy_from_user(databuf, buf, copy_len)) { MODULE_PUT; LEAVE(); return 0; @@ -359,6 +363,14 @@ woal_config_write(struct file *f, const char *buf, unsigned long cnt, parse_cmd52_string(databuf, (size_t) cnt, &func, ®, &val); woal_sdio_read_write_cmd52(handle, func, reg, val); } + if (!strncmp(databuf, "debug_dump", strlen("debug_dump"))) { + priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY); + if (priv) { + woal_mlan_debug_info(priv); + woal_moal_debug_info(priv, NULL, MFALSE); + } + } + MODULE_PUT; LEAVE(); return (int) cnt; diff --git a/drivers/net/wireless/sd8797/mlinux/moal_sdio.h b/drivers/net/wireless/sd8797/mlinux/moal_sdio.h index 5a5bc2c3718c..e4560f9dd8ca 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_sdio.h +++ b/drivers/net/wireless/sd8797/mlinux/moal_sdio.h @@ -49,17 +49,11 @@ Change log: #define FIXED_ADDRESS 0 #endif -/** SD8797 chip revision ID */ -#define SD8797_A0 0x00 -#define SD8797_B0 0x10 - -#define SD8797_A0_FW_NAME "mrvl/sd8797_uapsta_a0.bin" -#define SD8797_B0_FW_NAME "mrvl/sd8797_uapsta.bin" - #ifdef STA_SUPPORT /** Default firmware name */ #define DEFAULT_FW_NAME "mrvl/sd8797_uapsta.bin" +#define DEFAULT_FW_NAME_8782 "mrvl/sd8782_uapsta.bin" #ifndef DEFAULT_FW_NAME #define DEFAULT_FW_NAME "" @@ -70,6 +64,7 @@ Change log: /** Default firmware name */ #define DEFAULT_AP_FW_NAME "mrvl/sd8797_uapsta.bin" +#define DEFAULT_AP_FW_NAME_8782 "mrvl/sd8782_uapsta.bin" #ifndef DEFAULT_AP_FW_NAME #define DEFAULT_AP_FW_NAME "" @@ -79,6 +74,7 @@ Change log: /** Default firmaware name */ #define DEFAULT_AP_STA_FW_NAME "mrvl/sd8797_uapsta.bin" +#define DEFAULT_AP_STA_FW_NAME_8782 "mrvl/sd8782_uapsta.bin" #ifndef DEFAULT_AP_STA_FW_NAME #define DEFAULT_AP_STA_FW_NAME "" @@ -87,6 +83,8 @@ Change log: /******************************************************** Global Functions ********************************************************/ +/** Function to update the SDIO card type */ +t_void woal_sdio_update_card_type(moal_handle * handle, t_void * card); /** Function to write register */ mlan_status woal_write_reg(moal_handle * handle, t_u32 reg, t_u32 data); diff --git a/drivers/net/wireless/sd8797/mlinux/moal_sdio_mmc.c b/drivers/net/wireless/sd8797/mlinux/moal_sdio_mmc.c index ad42fdefa9d5..3dce9bf07e75 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_sdio_mmc.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_sdio_mmc.c @@ -47,10 +47,13 @@ extern int pm_keep_power; /** Device ID for SD8797 */ #define SD_DEVICE_ID_8797 (0x9129) +/** Device ID for SD8782 */ +#define SD_DEVICE_ID_8782 (0x9121) /** WLAN IDs */ static const struct sdio_device_id wlan_ids[] = { {SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8797)}, + {SDIO_DEVICE(MARVELL_VENDOR_ID, SD_DEVICE_ID_8782)}, {}, }; @@ -75,7 +78,7 @@ static struct sdio_driver REFDATA wlan_sdio = { .id_table = wlan_ids, .probe = woal_sdio_probe, .remove = woal_sdio_remove, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) .drv = { .owner = THIS_MODULE, #ifdef SDIO_SUSPEND_RESUME @@ -107,36 +110,49 @@ void woal_dump_sdio_reg(moal_handle * handle) { int ret = 0; - t_u8 data; - data = - sdio_f0_readb(((struct sdio_mmc_card *) handle->card)->func, 0x05, - &ret); - PRINTM(MMSG, "fun0: reg 0x05=0x%x ret=%d\n", data, ret); - data = - sdio_f0_readb(((struct sdio_mmc_card *) handle->card)->func, 0x04, - &ret); - PRINTM(MMSG, "fun0: reg 0x04=0x%x ret=%d\n", data, ret); - data = - sdio_readb(((struct sdio_mmc_card *) handle->card)->func, 0x03, &ret); - PRINTM(MMSG, "fun1: reg 0x03=0x%x ret=%d\n", data, ret); - data = - sdio_readb(((struct sdio_mmc_card *) handle->card)->func, 0x04, &ret); - PRINTM(MMSG, "fun1: reg 0x04=0x%x ret=%d\n", data, ret); - data = - sdio_readb(((struct sdio_mmc_card *) handle->card)->func, 0x05, &ret); - PRINTM(MMSG, "fun1: reg 0x05=0x%x ret=%d\n", data, ret); - data = - sdio_readb(((struct sdio_mmc_card *) handle->card)->func, 0x60, &ret); - PRINTM(MMSG, "fun1: reg 0x60=0x%x ret=%d\n", data, ret); - data = - sdio_readb(((struct sdio_mmc_card *) handle->card)->func, 0x61, &ret); - PRINTM(MMSG, "fun1: reg 0x61=0x%x ret=%d\n", data, ret); + t_u8 data, i, len; + int fun0_reg[] = { 0x05, 0x04 }; + int fun1_reg[] = { 0x03, 0x04, 0x05, 0x60, 0x61 }; + + len = sizeof(fun0_reg) / sizeof(fun0_reg[0]); + for (i = 0; i < len; i++) { + data = sdio_f0_readb(((struct sdio_mmc_card *) handle->card)->func, + fun0_reg[i], &ret); + PRINTM(MMSG, "fun0: reg 0x%02x=0x%02x ret=%d\n", fun0_reg[i], data, + ret); + } + + len = sizeof(fun1_reg) / sizeof(fun1_reg[0]); + for (i = 0; i < len; i++) { + data = sdio_readb(((struct sdio_mmc_card *) handle->card)->func, + fun1_reg[i], &ret); + PRINTM(MMSG, "fun1: reg 0x%02x=0x%02x ret=%d\n", fun1_reg[i], data, + ret); + } return; } /******************************************************** Global Functions ********************************************************/ +/** @brief This function updates the SDIO card types + * + * @param handle A Pointer to the moal_handle structure + * @param card A Pointer to card + * + * @return N/A + */ +t_void +woal_sdio_update_card_type(moal_handle * handle, t_void * card) +{ + struct sdio_mmc_card *cardp = (struct sdio_mmc_card *) card; + + /* Update card type */ + if (cardp->func->device == SD_DEVICE_ID_8797) + handle->card_type = CARD_TYPE_SD8797; + else if (cardp->func->device == SD_DEVICE_ID_8782) + handle->card_type = CARD_TYPE_SD8782; +} /** * @brief This function handles the interrupt. @@ -182,7 +198,7 @@ woal_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) ENTER(); - PRINTM(MINFO, "vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n", + PRINTM(MMSG, "vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n", func->vendor, func->device, func->class, func->num); card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL); @@ -292,24 +308,18 @@ woal_sdio_suspend(struct device *dev) ENTER(); PRINTM(MCMND, "<--- Enter woal_sdio_suspend --->\n"); - if (func) { - pm_flags = sdio_get_host_pm_caps(func); - PRINTM(MCMND, "%s: suspend: PM flags = 0x%x\n", sdio_func_id(func), - pm_flags); - if (!(pm_flags & MMC_PM_KEEP_POWER)) { - PRINTM(MERROR, "%s: cannot remain alive while host is suspended\n", - sdio_func_id(func)); - LEAVE(); - return -ENOSYS; - } - cardp = sdio_get_drvdata(func); - if (!cardp || !cardp->handle) { - PRINTM(MERROR, "Card or moal_handle structure is not valid\n"); - LEAVE(); - return MLAN_STATUS_SUCCESS; - } - } else { - PRINTM(MERROR, "sdio_func is not specified\n"); + pm_flags = sdio_get_host_pm_caps(func); + PRINTM(MCMND, "%s: suspend: PM flags = 0x%x\n", sdio_func_id(func), + pm_flags); + if (!(pm_flags & MMC_PM_KEEP_POWER)) { + PRINTM(MERROR, "%s: cannot remain alive while host is suspended\n", + sdio_func_id(func)); + LEAVE(); + return -ENOSYS; + } + cardp = sdio_get_drvdata(func); + if (!cardp || !cardp->handle) { + PRINTM(MERROR, "Card or moal_handle structure is not valid\n"); LEAVE(); return MLAN_STATUS_SUCCESS; } @@ -355,6 +365,9 @@ woal_sdio_suspend(struct device *dev) #endif } else { PRINTM(MMSG, "HS not actived, suspend fail!"); + handle->suspend_fail = MTRUE; + for (i = 0; i < handle->priv_num; i++) + netif_device_attach(handle->priv[i]->netdev); ret = -EBUSY; goto done; } @@ -384,18 +397,12 @@ woal_sdio_resume(struct device *dev) ENTER(); PRINTM(MCMND, "<--- Enter woal_sdio_resume --->\n"); - if (func) { - pm_flags = sdio_get_host_pm_caps(func); - PRINTM(MCMND, "%s: resume: PM flags = 0x%x\n", sdio_func_id(func), - pm_flags); - cardp = sdio_get_drvdata(func); - if (!cardp || !cardp->handle) { - PRINTM(MERROR, "Card or moal_handle structure is not valid\n"); - LEAVE(); - return MLAN_STATUS_SUCCESS; - } - } else { - PRINTM(MERROR, "sdio_func is not specified\n"); + pm_flags = sdio_get_host_pm_caps(func); + PRINTM(MCMND, "%s: resume: PM flags = 0x%x\n", sdio_func_id(func), + pm_flags); + cardp = sdio_get_drvdata(func); + if (!cardp || !cardp->handle) { + PRINTM(MERROR, "Card or moal_handle structure is not valid\n"); LEAVE(); return MLAN_STATUS_SUCCESS; } diff --git a/drivers/net/wireless/sd8797/mlinux/moal_shim.c b/drivers/net/wireless/sd8797/mlinux/moal_shim.c index efdcaacd2031..08c9a12f00d6 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_shim.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_shim.c @@ -50,6 +50,7 @@ typedef struct _moal_lock ********************************************************/ extern int cfg80211_wext; +extern int hw_test; /******************************************************** Local Functions ********************************************************/ @@ -72,7 +73,9 @@ moal_malloc(IN t_void * pmoal_handle, IN t_u32 size, IN t_u32 flag, OUT t_u8 ** ppbuf) { moal_handle *handle = (moal_handle *) pmoal_handle; - t_u32 mem_flag = GFP_ATOMIC; /* Default type: GFP_ATOMIC */ + t_u32 mem_flag = (in_interrupt() || irqs_disabled() || + !write_can_lock(&dev_base_lock)) ? GFP_ATOMIC : + GFP_KERNEL; if (flag & MLAN_MEM_DMA) mem_flag |= GFP_DMA; @@ -107,6 +110,50 @@ moal_mfree(IN t_void * pmoal_handle, IN t_u8 * pbuf) return MLAN_STATUS_SUCCESS; } +/** + * @brief Alloc a vitual-address-continuous buffer + * + * @param pmoal_handle Pointer to the MOAL context + * @param size The size of the buffer to be allocated + * @param ppbuf Pointer to a buffer location to store buffer pointer allocated + * + * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE + */ +mlan_status +moal_vmalloc(IN t_void * pmoal_handle, IN t_u32 size, OUT t_u8 ** ppbuf) +{ + moal_handle *handle = (moal_handle *) pmoal_handle; + + if (!(*ppbuf = vmalloc(size))) { + PRINTM(MERROR, "%s: vmalloc (%d bytes) failed!", __FUNCTION__, + (int) size); + return MLAN_STATUS_FAILURE; + } + atomic_inc(&handle->vmalloc_count); + + return MLAN_STATUS_SUCCESS; +} + +/** + * @brief Free a buffer allocated by vmalloc + * + * @param pmoal_handle Pointer to the MOAL context + * @param pbuf Pointer to the buffer to be freed + * + * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE + */ +mlan_status +moal_vfree(IN t_void * pmoal_handle, IN t_u8 * pbuf) +{ + moal_handle *handle = (moal_handle *) pmoal_handle; + + if (!pbuf) + return MLAN_STATUS_FAILURE; + vfree(pbuf); + atomic_dec(&handle->vmalloc_count); + return MLAN_STATUS_SUCCESS; +} + /** * @brief Fill memory with constant byte * @@ -527,7 +574,7 @@ moal_ioctl_complete(IN t_void * pmoal_handle, (pioctl_req->action == MLAN_ACT_GET)) woal_process_ioctl_resp(priv, pioctl_req); if (status != MLAN_STATUS_SUCCESS) - PRINTM(MERROR, + PRINTM(MIOCTL, "IOCTL failed: id=0x%x, action=%d, status_code=0x%x\n", pioctl_req->req_id, (int) pioctl_req->action, pioctl_req->status_code); @@ -589,7 +636,11 @@ moal_send_packet_complete(IN t_void * pmoal_handle, moal_private *priv = NULL; moal_handle *handle = (moal_handle *) pmoal_handle; struct sk_buff *skb = NULL; - int i; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) + t_u32 tid = 0; + t_u32 index = 0; +#endif + ENTER(); if (pmbuf && pmbuf->buf_type == MLAN_BUF_TYPE_RAW_DATA) { woal_free_mlan_buffer(handle, pmbuf); @@ -609,7 +660,24 @@ moal_send_packet_complete(IN t_void * pmoal_handle, } else { priv->stats.tx_errors++; } +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) + tid = pmbuf->priority; + index = + mlan_select_wmm_queue(priv->phandle->pmlan_adapter, + priv->bss_index, tid); + atomic_dec(&handle->tx_pending); + if (atomic_dec_return(&priv->wmm_tx_pending[index]) < + LOW_TX_PENDING) { + struct netdev_queue *txq = + netdev_get_tx_queue(priv->netdev, index); + if (netif_tx_queue_stopped(txq)) { + netif_tx_wake_queue(txq); + PRINTM(MINFO, "Wakeup Kernel Queue:%d\n", index); + } + } +#else /* #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) */ if (atomic_dec_return(&handle->tx_pending) < LOW_TX_PENDING) { + int i; for (i = 0; i < handle->priv_num; i++) { #ifdef STA_SUPPORT if ((GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA) @@ -626,6 +694,7 @@ moal_send_packet_complete(IN t_void * pmoal_handle, #endif } } +#endif /* #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) */ } } if (skb) @@ -745,10 +814,6 @@ moal_recv_packet(IN t_void * pmoal_handle, IN pmlan_buffer pmbuf) skb->protocol = eth_type_trans(skb, priv->netdev); skb->ip_summed = CHECKSUM_NONE; - if (priv->enable_tcp_ack_enh == MTRUE) { - woal_check_tcp_fin(priv, skb); - } - priv->stats.rx_bytes += skb->len; priv->stats.rx_packets++; if (in_interrupt()) @@ -777,7 +842,7 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) int custom_len = 0; #endif moal_private *priv = NULL; -#if defined(STA_WEXT) || defined(UAP_SUPPORT) +#if defined(STA_SUPPORT) || defined(UAP_SUPPORT) moal_private *pmpriv = NULL; #endif #if defined(STA_WEXT) || defined(UAP_WEXT) @@ -790,6 +855,7 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) #if defined(SDIO_SUSPEND_RESUME) mlan_ds_ps_info pm_info; #endif + ENTER(); PRINTM(MEVENT, "event id:0x%x\n", pmevent->event_id); @@ -798,6 +864,10 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) PRINTM(MERROR, "%s: priv is null\n", __FUNCTION__); goto done; } + if (priv->netdev == NULL) { + PRINTM(MERROR, "%s: netdev is null\n", __FUNCTION__); + goto done; + } switch (pmevent->event_id) { #ifdef STA_SUPPORT case MLAN_EVENT_ID_FW_ADHOC_LINK_SENSED: @@ -809,6 +879,8 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) if (IS_STA_WEXT(cfg80211_wext)) woal_send_iwevcustom_event(priv, CUS_EVT_ADHOC_LINK_SENSED); #endif + woal_broadcast_event(priv, CUS_EVT_ADHOC_LINK_SENSED, + strlen(CUS_EVT_ADHOC_LINK_SENSED)); break; case MLAN_EVENT_ID_FW_ADHOC_LINK_LOST: @@ -820,6 +892,8 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) if (IS_STA_WEXT(cfg80211_wext)) woal_send_iwevcustom_event(priv, CUS_EVT_ADHOC_LINK_LOST); #endif + woal_broadcast_event(priv, CUS_EVT_ADHOC_LINK_LOST, + strlen(CUS_EVT_ADHOC_LINK_LOST)); break; case MLAN_EVENT_ID_DRV_CONNECTED: @@ -832,13 +906,17 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) } #endif #ifdef STA_CFG80211 - if (IS_STA_CFG80211(cfg80211_wext)) + if (IS_STA_CFG80211(cfg80211_wext)) { memcpy(priv->cfg_bssid, pmevent->event_buf, ETH_ALEN); + woal_set_scan_time(priv, ACTIVE_SCAN_CHAN_TIME, + PASSIVE_SCAN_CHAN_TIME, + MIN_SPECIFIC_SCAN_CHAN_TIME); + } #endif custom_len = strlen(CUS_EVT_AP_CONNECTED); memmove(pmevent->event_buf + custom_len, pmevent->event_buf, pmevent->event_len); - strncpy(pmevent->event_buf, CUS_EVT_AP_CONNECTED, custom_len); + memcpy(pmevent->event_buf, CUS_EVT_AP_CONNECTED, custom_len); pmevent->event_len += custom_len; woal_broadcast_event(priv, pmevent->event_buf, pmevent->event_len); priv->media_connected = MTRUE; @@ -863,12 +941,18 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) #endif #ifdef STA_CFG80211 if (IS_STA_CFG80211(cfg80211_wext)) { - woal_inform_bss_from_scan_result(priv, NULL); + woal_inform_bss_from_scan_result(priv, NULL, MOAL_NO_WAIT); PRINTM(MINFO, "Reporting scan results\n"); if (priv->scan_request) { cfg80211_scan_done(priv->scan_request, MFALSE); priv->scan_request = NULL; } + if (!priv->phandle->first_scan_done) { + priv->phandle->first_scan_done = MTRUE; + woal_set_scan_time(priv, ACTIVE_SCAN_CHAN_TIME, + PASSIVE_SCAN_CHAN_TIME, + SPECIFIC_SCAN_CHAN_TIME); + } } #endif /* STA_CFG80211 */ @@ -879,15 +963,18 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) break; case MLAN_EVENT_ID_DRV_OBSS_SCAN_PARAM: + memmove((pmevent->event_buf + strlen(CUS_EVT_OBSS_SCAN_PARAM) + 1), + pmevent->event_buf, pmevent->event_len); + memcpy(pmevent->event_buf, (t_u8 *) CUS_EVT_OBSS_SCAN_PARAM, + strlen(CUS_EVT_OBSS_SCAN_PARAM)); + pmevent->event_buf[strlen(CUS_EVT_OBSS_SCAN_PARAM)] = 0; + woal_broadcast_event(priv, pmevent->event_buf, + pmevent->event_len + + strlen(CUS_EVT_OBSS_SCAN_PARAM)); + #ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext)) { memset(&wrqu, 0, sizeof(union iwreq_data)); - memmove((pmevent->event_buf + strlen(CUS_EVT_OBSS_SCAN_PARAM) + 1), - pmevent->event_buf, pmevent->event_len); - memcpy(pmevent->event_buf, (t_u8 *) CUS_EVT_OBSS_SCAN_PARAM, - strlen(CUS_EVT_OBSS_SCAN_PARAM)); - pmevent->event_buf[strlen(CUS_EVT_OBSS_SCAN_PARAM)] = 0; - wrqu.data.pointer = pmevent->event_buf; wrqu.data.length = pmevent->event_len + strlen(CUS_EVT_OBSS_SCAN_PARAM) + 1; @@ -897,15 +984,17 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) #endif break; case MLAN_EVENT_ID_FW_BW_CHANGED: + memmove((pmevent->event_buf + strlen(CUS_EVT_BW_CHANGED) + 1), + pmevent->event_buf, pmevent->event_len); + memcpy(pmevent->event_buf, (t_u8 *) CUS_EVT_BW_CHANGED, + strlen(CUS_EVT_BW_CHANGED)); + pmevent->event_buf[strlen(CUS_EVT_BW_CHANGED)] = 0; + woal_broadcast_event(priv, pmevent->event_buf, + pmevent->event_len + strlen(CUS_EVT_BW_CHANGED)); + #ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext)) { memset(&wrqu, 0, sizeof(union iwreq_data)); - memmove((pmevent->event_buf + strlen(CUS_EVT_BW_CHANGED) + 1), - pmevent->event_buf, pmevent->event_len); - memcpy(pmevent->event_buf, (t_u8 *) CUS_EVT_BW_CHANGED, - strlen(CUS_EVT_BW_CHANGED)); - pmevent->event_buf[strlen(CUS_EVT_BW_CHANGED)] = 0; - wrqu.data.pointer = pmevent->event_buf; wrqu.data.length = pmevent->event_len + strlen(CUS_EVT_BW_CHANGED) + 1; @@ -954,6 +1043,8 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) GFP_KERNEL); } #endif + woal_broadcast_event(priv, CUS_EVT_MLME_MIC_ERR_UNI, + strlen(CUS_EVT_MLME_MIC_ERR_UNI)); break; case MLAN_EVENT_ID_FW_MIC_ERR_MUL: #ifdef STA_WEXT @@ -972,6 +1063,8 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) GFP_KERNEL); } #endif + woal_broadcast_event(priv, CUS_EVT_MLME_MIC_ERR_MUL, + strlen(CUS_EVT_MLME_MIC_ERR_MUL)); break; case MLAN_EVENT_ID_FW_BCN_RSSI_LOW: #ifdef STA_WEXT @@ -986,9 +1079,12 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) GFP_KERNEL); priv->last_event |= EVENT_BCN_RSSI_LOW; #endif - woal_set_rssi_threshold(priv, MLAN_EVENT_ID_FW_BCN_RSSI_LOW); + if (!hw_test && priv->roaming_enabled) + woal_config_bgscan_and_rssi(priv, MTRUE); } #endif + woal_broadcast_event(priv, CUS_EVT_BEACON_RSSI_LOW, + strlen(CUS_EVT_BEACON_RSSI_LOW)); break; case MLAN_EVENT_ID_FW_BCN_RSSI_HIGH: #ifdef STA_WEXT @@ -1003,58 +1099,76 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, GFP_KERNEL); #endif - woal_set_rssi_threshold(priv, MLAN_EVENT_ID_FW_BCN_RSSI_HIGH); + woal_set_rssi_threshold(priv, MLAN_EVENT_ID_FW_BCN_RSSI_HIGH, + MOAL_NO_WAIT); } } #endif + woal_broadcast_event(priv, CUS_EVT_BEACON_RSSI_HIGH, + strlen(CUS_EVT_BEACON_RSSI_HIGH)); break; case MLAN_EVENT_ID_FW_BCN_SNR_LOW: #ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext)) woal_send_iwevcustom_event(priv, CUS_EVT_BEACON_SNR_LOW); #endif + woal_broadcast_event(priv, CUS_EVT_BEACON_SNR_LOW, + strlen(CUS_EVT_BEACON_SNR_LOW)); break; case MLAN_EVENT_ID_FW_BCN_SNR_HIGH: #ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext)) woal_send_iwevcustom_event(priv, CUS_EVT_BEACON_SNR_HIGH); #endif + woal_broadcast_event(priv, CUS_EVT_BEACON_SNR_HIGH, + strlen(CUS_EVT_BEACON_SNR_HIGH)); break; case MLAN_EVENT_ID_FW_MAX_FAIL: #ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext)) woal_send_iwevcustom_event(priv, CUS_EVT_MAX_FAIL); #endif + woal_broadcast_event(priv, CUS_EVT_MAX_FAIL, strlen(CUS_EVT_MAX_FAIL)); break; case MLAN_EVENT_ID_FW_DATA_RSSI_LOW: #ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext)) woal_send_iwevcustom_event(priv, CUS_EVT_DATA_RSSI_LOW); #endif + woal_broadcast_event(priv, CUS_EVT_DATA_RSSI_LOW, + strlen(CUS_EVT_DATA_RSSI_LOW)); break; case MLAN_EVENT_ID_FW_DATA_SNR_LOW: #ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext)) woal_send_iwevcustom_event(priv, CUS_EVT_DATA_SNR_LOW); #endif + woal_broadcast_event(priv, CUS_EVT_DATA_SNR_LOW, + strlen(CUS_EVT_DATA_SNR_LOW)); break; case MLAN_EVENT_ID_FW_DATA_RSSI_HIGH: #ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext)) woal_send_iwevcustom_event(priv, CUS_EVT_DATA_RSSI_HIGH); #endif + woal_broadcast_event(priv, CUS_EVT_DATA_RSSI_HIGH, + strlen(CUS_EVT_DATA_RSSI_HIGH)); break; case MLAN_EVENT_ID_FW_DATA_SNR_HIGH: #ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext)) woal_send_iwevcustom_event(priv, CUS_EVT_DATA_SNR_HIGH); #endif + woal_broadcast_event(priv, CUS_EVT_DATA_SNR_HIGH, + strlen(CUS_EVT_DATA_SNR_HIGH)); break; case MLAN_EVENT_ID_FW_LINK_QUALITY: #ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext)) woal_send_iwevcustom_event(priv, CUS_EVT_LINK_QUALITY); #endif + woal_broadcast_event(priv, CUS_EVT_LINK_QUALITY, + strlen(CUS_EVT_LINK_QUALITY)); break; case MLAN_EVENT_ID_FW_PORT_RELEASE: #ifdef STA_WEXT @@ -1078,19 +1192,29 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) 0, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); if (bss) cfg80211_unlink_bss(priv->wdev->wiphy, bss); - cfg80211_cqm_rssi_notify(priv->netdev, - NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, - GFP_KERNEL); + if (!hw_test && priv->roaming_enabled) + woal_config_bgscan_and_rssi(priv, MFALSE); priv->last_event |= EVENT_PRE_BCN_LOST; } #endif #endif + woal_broadcast_event(priv, CUS_EVT_PRE_BEACON_LOST, + strlen(CUS_EVT_PRE_BEACON_LOST)); + break; + case MLAN_EVENT_ID_FW_DEBUG_INFO: +#ifdef STA_WEXT + if (IS_STA_WEXT(cfg80211_wext)) + woal_send_iwevcustom_event(priv, pmevent->event_buf); +#endif + woal_broadcast_event(priv, pmevent->event_buf, pmevent->event_len); break; case MLAN_EVENT_ID_FW_WMM_CONFIG_CHANGE: #ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext)) woal_send_iwevcustom_event(priv, WMM_CONFIG_CHANGE_INDICATION); #endif + woal_broadcast_event(priv, WMM_CONFIG_CHANGE_INDICATION, + strlen(WMM_CONFIG_CHANGE_INDICATION)); break; case MLAN_EVENT_ID_DRV_REPORT_STRING: @@ -1099,6 +1223,8 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) if (IS_STA_WEXT(cfg80211_wext)) woal_send_iwevcustom_event(priv, pmevent->event_buf); #endif + woal_broadcast_event(priv, pmevent->event_buf, + strlen(pmevent->event_buf)); break; case MLAN_EVENT_ID_FW_WEP_ICV_ERR: DBG_HEXDUMP(MCMD_D, "WEP ICV error", pmevent->event_buf, @@ -1107,6 +1233,8 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) if (IS_STA_WEXT(cfg80211_wext)) woal_send_iwevcustom_event(priv, CUS_EVT_WEP_ICV_ERR); #endif + woal_broadcast_event(priv, CUS_EVT_WEP_ICV_ERR, + strlen(CUS_EVT_WEP_ICV_ERR)); break; case MLAN_EVENT_ID_DRV_DEFER_HANDLING: @@ -1114,6 +1242,8 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) break; case MLAN_EVENT_ID_DRV_DBG_DUMP: woal_moal_debug_info(priv, NULL, MFALSE); +#if defined(DEBUG_LEVEL1) +#endif break; case MLAN_EVENT_ID_FW_BG_SCAN: if (priv->media_connected == MTRUE) @@ -1128,21 +1258,54 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) #ifdef STA_CFG80211 if (IS_STA_CFG80211(cfg80211_wext)) { priv->last_event |= EVENT_BG_SCAN_REPORT; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) || defined(COMPAT_WIRELESS) - if (priv->mrvl_rssi_low) { - cfg80211_cqm_rssi_notify(priv->netdev, - NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, - GFP_KERNEL); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) || defined(COMPAT_WIRELESS) + if (priv->sched_scanning && !priv->phandle->cfg80211_suspend) { + mlan_scan_resp scan_resp; + woal_get_scan_table(priv, MOAL_NO_WAIT, &scan_resp); + PRINTM(MIOCTL, "Trigger mlan get bgscan result\n"); + } +#endif + if (!hw_test && priv->roaming_enabled) { + priv->roaming_required = MTRUE; + wake_up_interruptible(&priv->phandle->reassoc_thread.wait_q); + } + } +#endif + break; + case MLAN_EVENT_ID_FW_BG_SCAN_STOPPED: +#ifdef STA_CFG80211 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) || defined(COMPAT_WIRELESS) + if (IS_STA_CFG80211(cfg80211_wext)) { + if (priv->sched_scanning) { + cfg80211_sched_scan_stopped(priv->wdev->wiphy); + PRINTM(MEVENT, "Sched_Scan stopped\n"); + priv->sched_scanning = MFALSE; } + } #endif +#endif + break; + case MLAN_EVENT_ID_DRV_BGSCAN_RESULT: +#ifdef STA_CFG80211 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) || defined(COMPAT_WIRELESS) + if (IS_STA_CFG80211(cfg80211_wext)) { + if (priv->sched_scanning && !priv->phandle->cfg80211_suspend) { + woal_inform_bss_from_scan_result(priv, NULL, MOAL_NO_WAIT); + cfg80211_sched_scan_results(priv->wdev->wiphy); + priv->last_event = 0; + PRINTM(MEVENT, "Reporting Sched_Scan results\n"); + } } #endif +#endif break; case MLAN_EVENT_ID_FW_CHANNEL_SWITCH_ANN: #ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext)) woal_send_iwevcustom_event(priv, CUS_EVT_CHANNEL_SWITCH_ANN); #endif + woal_broadcast_event(priv, CUS_EVT_CHANNEL_SWITCH_ANN, + strlen(CUS_EVT_CHANNEL_SWITCH_ANN)); break; #endif /* STA_SUPPORT */ case MLAN_EVENT_ID_FW_STOP_TX: @@ -1158,15 +1321,19 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) case MLAN_EVENT_ID_FW_HS_WAKEUP: /* simulate HSCFG_CANCEL command */ woal_cancel_hs(priv, MOAL_NO_WAIT); -#ifdef STA_WEXT #ifdef STA_SUPPORT +#ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext) && (pmpriv = woal_get_priv((moal_handle *) pmoal_handle, MLAN_BSS_ROLE_STA))) woal_send_iwevcustom_event(pmpriv, CUS_EVT_HS_WAKEUP); -#endif /* STA_SUPPORT */ #endif /* STA_WEXT */ + if ((pmpriv = + woal_get_priv((moal_handle *) pmoal_handle, MLAN_BSS_ROLE_STA))) + woal_broadcast_event(pmpriv, CUS_EVT_HS_WAKEUP, + strlen(CUS_EVT_HS_WAKEUP)); +#endif /* STA_SUPPORT */ #ifdef UAP_SUPPORT if ((pmpriv = woal_get_priv((moal_handle *) pmoal_handle, MLAN_BSS_ROLE_UAP))) { @@ -1177,8 +1344,8 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) #endif /* UAP_SUPPORT */ break; case MLAN_EVENT_ID_DRV_HS_ACTIVATED: -#ifdef STA_WEXT #ifdef STA_SUPPORT +#ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext) && (pmpriv = woal_get_priv((moal_handle *) pmoal_handle, @@ -1186,8 +1353,12 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) { woal_send_iwevcustom_event(pmpriv, CUS_EVT_HS_ACTIVATED); } -#endif /* STA_SUPPORT */ #endif /* STA_WEXT */ + if ((pmpriv = + woal_get_priv((moal_handle *) pmoal_handle, MLAN_BSS_ROLE_STA))) + woal_broadcast_event(pmpriv, CUS_EVT_HS_ACTIVATED, + strlen(CUS_EVT_HS_ACTIVATED)); +#endif /* STA_SUPPORT */ #if defined(UAP_SUPPORT) if ((pmpriv = woal_get_priv((moal_handle *) pmoal_handle, MLAN_BSS_ROLE_UAP))) { @@ -1211,8 +1382,8 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) #endif break; case MLAN_EVENT_ID_DRV_HS_DEACTIVATED: -#ifdef STA_WEXT #ifdef STA_SUPPORT +#ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext) && (pmpriv = woal_get_priv((moal_handle *) pmoal_handle, @@ -1220,8 +1391,12 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) { woal_send_iwevcustom_event(pmpriv, CUS_EVT_HS_DEACTIVATED); } -#endif -#endif +#endif /* STA_WEXT */ + if ((pmpriv = + woal_get_priv((moal_handle *) pmoal_handle, MLAN_BSS_ROLE_STA))) + woal_broadcast_event(pmpriv, CUS_EVT_HS_DEACTIVATED, + strlen(CUS_EVT_HS_DEACTIVATED)); +#endif /* STA_SUPPORT */ #if defined(UAP_SUPPORT) if ((pmpriv = woal_get_priv((moal_handle *) pmoal_handle, MLAN_BSS_ROLE_UAP))) { @@ -1237,9 +1412,24 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) #ifdef UAP_SUPPORT case MLAN_EVENT_ID_UAP_FW_BSS_START: priv->bss_started = MTRUE; + if (!netif_carrier_ok(priv->netdev)) + netif_carrier_on(priv->netdev); + woal_start_queue(priv->netdev); memcpy(priv->current_addr, pmevent->event_buf + 6, ETH_ALEN); memcpy(priv->netdev->dev_addr, priv->current_addr, ETH_ALEN); woal_broadcast_event(priv, pmevent->event_buf, pmevent->event_len); +#ifdef STA_SUPPORT +#ifdef STA_CFG80211 + if (IS_STA_CFG80211(cfg80211_wext)) { + if ((pmpriv = + woal_get_priv((moal_handle *) pmoal_handle, + MLAN_BSS_ROLE_STA))) + woal_set_scan_time(pmpriv, ACTIVE_SCAN_CHAN_TIME, + PASSIVE_SCAN_CHAN_TIME, + MIN_SPECIFIC_SCAN_CHAN_TIME); + } +#endif +#endif break; case MLAN_EVENT_ID_UAP_FW_BSS_ACTIVE: priv->media_connected = MTRUE; @@ -1250,24 +1440,29 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) break; case MLAN_EVENT_ID_UAP_FW_BSS_IDLE: priv->media_connected = MFALSE; - woal_stop_queue(priv->netdev); - if (netif_carrier_ok(priv->netdev)) - netif_carrier_off(priv->netdev); woal_broadcast_event(priv, pmevent->event_buf, pmevent->event_len); break; #ifdef WIFI_DIRECT_SUPPORT #if defined(STA_CFG80211) || defined(UAP_CFG80211) case MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED: if (IS_STA_OR_UAP_CFG80211(cfg80211_wext)) { - PRINTM(MEVENT, "FW_REMAIN_ON_CH0ANNEL_EXPIRED cookie = %#llx\n", + PRINTM(MEVENT, "FW_REMAIN_ON_CHANNEL_EXPIRED cookie = %#llx\n", priv->phandle->cookie); priv->phandle->remain_on_channel = MFALSE; if (priv->phandle->cookie) { - cfg80211_remain_on_channel_expired(priv->netdev, - priv->phandle->cookie, - &priv->phandle->chan, - priv->phandle->channel_type, - GFP_ATOMIC); + cfg80211_remain_on_channel_expired( +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) + priv->netdev, +#else + priv->wdev, +#endif + priv->phandle->cookie, + &priv->phandle->chan, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) + priv->phandle-> + channel_type, +#endif + GFP_ATOMIC); priv->phandle->cookie = 0; } } @@ -1285,7 +1480,10 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) /* copy the station mac address */ memset(addr, 0xFF, ETH_ALEN); memcpy(addr, pmevent->event_buf, ETH_ALEN); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) || defined(COMPAT_WIRELESS) + /** these field add in kernel 3.2, but some kernel do have the pacth to + * support it,like T3T and pxa978T 3.0.31 JB, these patch are + * needed to support wpa_supplicant 2.x */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,31) || defined(COMPAT_WIRELESS) if (pmevent->event_len > ETH_ALEN) { /* set station info filled flag */ sinfo.filled |= STATION_INFO_ASSOC_REQ_IES; @@ -1301,14 +1499,17 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) (t_u8 *) addr, &sinfo, GFP_KERNEL); } #endif /* UAP_CFG80211 */ + memmove((pmevent->event_buf + strlen(CUS_EVT_STA_CONNECTED) + 1), + pmevent->event_buf, pmevent->event_len); + memcpy(pmevent->event_buf, (t_u8 *) CUS_EVT_STA_CONNECTED, + strlen(CUS_EVT_STA_CONNECTED)); + pmevent->event_buf[strlen(CUS_EVT_STA_CONNECTED)] = 0; + woal_broadcast_event(priv, pmevent->event_buf, + pmevent->event_len + + strlen(CUS_EVT_STA_CONNECTED)); #ifdef UAP_WEXT if (IS_UAP_WEXT(cfg80211_wext)) { memset(&wrqu, 0, sizeof(union iwreq_data)); - memmove((pmevent->event_buf + strlen(CUS_EVT_STA_CONNECTED) + 1), - pmevent->event_buf, pmevent->event_len); - memcpy(pmevent->event_buf, (t_u8 *) CUS_EVT_STA_CONNECTED, - strlen(CUS_EVT_STA_CONNECTED)); - pmevent->event_buf[strlen(CUS_EVT_STA_CONNECTED)] = 0; wrqu.data.pointer = pmevent->event_buf; if ((pmevent->event_len + strlen(CUS_EVT_STA_CONNECTED) + 1) > IW_CUSTOM_MAX) @@ -1332,15 +1533,18 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) #endif /* KERNEL_VERSION */ } #endif /* UAP_CFG80211 */ + memmove((pmevent->event_buf + strlen(CUS_EVT_STA_DISCONNECTED) + 1), + pmevent->event_buf, pmevent->event_len); + memcpy(pmevent->event_buf, (t_u8 *) CUS_EVT_STA_DISCONNECTED, + strlen(CUS_EVT_STA_DISCONNECTED)); + pmevent->event_buf[strlen(CUS_EVT_STA_DISCONNECTED)] = 0; + woal_broadcast_event(priv, pmevent->event_buf, + pmevent->event_len + + strlen(CUS_EVT_STA_DISCONNECTED)); + #ifdef UAP_WEXT if (IS_UAP_WEXT(cfg80211_wext)) { memset(&wrqu, 0, sizeof(union iwreq_data)); - memmove((pmevent->event_buf + strlen(CUS_EVT_STA_DISCONNECTED) + 1), - pmevent->event_buf, pmevent->event_len); - memcpy(pmevent->event_buf, (t_u8 *) CUS_EVT_STA_DISCONNECTED, - strlen(CUS_EVT_STA_DISCONNECTED)); - pmevent->event_buf[strlen(CUS_EVT_STA_DISCONNECTED)] = 0; - wrqu.data.pointer = pmevent->event_buf; wrqu.data.length = pmevent->event_len + strlen(CUS_EVT_STA_DISCONNECTED) + 1; @@ -1363,6 +1567,19 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) /* frmctl + durationid + addr1 + addr2 + addr3 + seqctl */ #define PACKET_ADDR4_POS (2 + 2 + 6 + 6 + 6 + 2) t_u8 *pkt; + int freq = + priv->phandle->remain_on_channel ? priv->phandle->chan. + center_freq : woal_get_active_intf_freq(priv->phandle); + + if (!freq) { + if (!priv->phandle->chan.center_freq) { + PRINTM(MERROR, + "Skip to report mgmt packet to cfg80211\n"); + break; + } + freq = priv->phandle->chan.center_freq; + } + pkt = ((t_u8 *) pmevent->event_buf + sizeof(pmevent->event_id)); /* move addr4 */ @@ -1370,18 +1587,31 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) pkt + PACKET_ADDR4_POS + ETH_ALEN, pmevent->event_len - sizeof(pmevent->event_id) - PACKET_ADDR4_POS - ETH_ALEN); + PRINTM(MIOCTL, + "Mgmt RX %s <= framectrl = 0x%x freq = %d roc = %d\n", + priv->netdev->name, + ((struct ieee80211_mgmt *) pkt)->frame_control, freq, + priv->phandle->remain_on_channel); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) - cfg80211_rx_mgmt(priv->netdev, priv->phandle->chan.center_freq, - 0, ((const t_u8 *) pmevent->event_buf) - + sizeof(pmevent->event_id), - pmevent->event_len - sizeof(pmevent->event_id) - - MLAN_MAC_ADDR_LENGTH, GFP_ATOMIC); + cfg80211_rx_mgmt( +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + priv->wdev, #else - cfg80211_rx_mgmt(priv->netdev, priv->phandle->chan.center_freq, - 0, ((const t_u8 *) pmevent->event_buf) - + sizeof(pmevent->event_id), - pmevent->event_len - sizeof(pmevent->event_id) - - MLAN_MAC_ADDR_LENGTH, GFP_ATOMIC); + priv->netdev, +#endif + freq, 0, + ((const t_u8 *) pmevent->event_buf) + + sizeof(pmevent->event_id), + pmevent->event_len - + sizeof(pmevent->event_id) - + MLAN_MAC_ADDR_LENGTH, GFP_ATOMIC); +#else + cfg80211_rx_mgmt(priv->netdev, freq, + ((const t_u8 *) pmevent->event_buf) + + sizeof(pmevent->event_id), + pmevent->event_len - + sizeof(pmevent->event_id) - + MLAN_MAC_ADDR_LENGTH, GFP_ATOMIC); #endif } #endif /* KERNEL_VERSION */ @@ -1393,6 +1623,19 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) case MLAN_EVENT_ID_DRV_PASSTHRU: woal_broadcast_event(priv, pmevent->event_buf, pmevent->event_len); break; + case MLAN_EVENT_ID_DRV_ASSOC_FAILURE_REPORT: + PRINTM(MINFO, "Assoc result\n"); + + if (priv->media_connected) { + PRINTM(MINFO, "Assoc_Rpt: Media Connected\n"); + if (!netif_carrier_ok(priv->netdev)) { + PRINTM(MINFO, "Assoc_Rpt: Carrier On\n"); + netif_carrier_on(priv->netdev); + } + PRINTM(MINFO, "Assoc_Rpt: Queue Start\n"); + woal_wake_queue(priv->netdev); + } + break; case MLAN_EVENT_ID_DRV_MEAS_REPORT: /* We have received measurement report, wakeup measurement wait queue */ PRINTM(MINFO, "Measurement Report\n"); @@ -1437,6 +1680,7 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) PRINTM(MMSG, "BSS START Complete!\n"); } } + default: break; } @@ -1455,7 +1699,7 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) * @return N/A */ t_void -moal_print(IN t_void * pmoal_handle, IN t_u32 level, IN t_s8 * pformat, IN ...) +moal_print(IN t_void * pmoal_handle, IN t_u32 level, IN char *pformat, IN ...) { #ifdef DEBUG_LEVEL1 va_list args; @@ -1489,9 +1733,11 @@ moal_print(IN t_void * pmoal_handle, IN t_u32 level, IN t_s8 * pformat, IN ...) DBG_HEXDUMP(MEVT_D, (char *) pformat, buf, len); } } else { - va_start(args, pformat); - vprintk(pformat, args); - va_end(args); + if (drvdbg & level) { + va_start(args, pformat); + vprintk(pformat, args); + va_end(args); + } } #endif /* DEBUG_LEVEL1 */ } @@ -1511,10 +1757,12 @@ moal_print_netintf(IN t_void * pmoal_handle, IN t_u32 bss_index, IN t_u32 level) #ifdef DEBUG_LEVEL1 moal_handle *phandle = (moal_handle *) pmoal_handle; - if (phandle && (drvdbg & level)) { + if (phandle) { if ((bss_index < MLAN_MAX_BSS_NUM) && phandle->priv[bss_index] && - phandle->priv[bss_index]->netdev) - printk("%s: ", phandle->priv[bss_index]->netdev->name); + phandle->priv[bss_index]->netdev) { + if (drvdbg & level) + printk("%s: ", phandle->priv[bss_index]->netdev->name); + } } #endif /* DEBUG_LEVEL1 */ } @@ -1530,6 +1778,7 @@ moal_print_netintf(IN t_void * pmoal_handle, IN t_u32 bss_index, IN t_u32 level) t_void moal_assert(IN t_void * pmoal_handle, IN t_u32 cond) { - if (!cond) + if (!cond) { panic("Assert failed: Panic!"); + } } diff --git a/drivers/net/wireless/sd8797/mlinux/moal_shim.h b/drivers/net/wireless/sd8797/mlinux/moal_shim.h index ee50a2105f0f..76be517d9858 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_shim.h +++ b/drivers/net/wireless/sd8797/mlinux/moal_shim.h @@ -43,6 +43,7 @@ mlan_status moal_free_mlan_buffer(IN t_void * pmoal_handle, mlan_status moal_send_packet_complete(IN t_void * pmoal_handle, IN pmlan_buffer pmbuf, IN mlan_status status); + /** moal_write_reg */ mlan_status moal_write_reg(IN t_void * pmoal_handle, IN t_u32 reg, IN t_u32 data); @@ -60,6 +61,9 @@ mlan_status moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent); mlan_status moal_malloc(IN t_void * pmoal_handle, IN t_u32 size, IN t_u32 flag, OUT t_u8 ** ppbuf); mlan_status moal_mfree(IN t_void * pmoal_handle, IN t_u8 * pbuf); +mlan_status moal_vmalloc(IN t_void * pmoal_handle, + IN t_u32 size, OUT t_u8 ** ppbuf); +mlan_status moal_vfree(IN t_void * pmoal_handle, IN t_u8 * pbuf); t_void *moal_memset(IN t_void * pmoal_handle, IN t_void * pmem, IN t_u8 byte, IN t_u32 num); t_void *moal_memcpy(IN t_void * pmoal_handle, @@ -77,7 +81,7 @@ mlan_status moal_init_lock(IN t_void * pmoal_handle, OUT t_void ** pplock); mlan_status moal_free_lock(IN t_void * pmoal_handle, IN t_void * plock); mlan_status moal_spin_lock(IN t_void * pmoal_handle, IN t_void * plock); mlan_status moal_spin_unlock(IN t_void * pmoal_handle, IN t_void * plock); -t_void moal_print(IN t_void * pmoal_handle, IN t_u32 level, IN t_s8 * pformat, +t_void moal_print(IN t_void * pmoal_handle, IN t_u32 level, IN char *pformat, IN ...); t_void moal_print_netintf(IN t_void * pmoal_handle, IN t_u32 bss_index, IN t_u32 level); diff --git a/drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.c b/drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.c index 51027a98aff7..7e28dec0dd38 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.c @@ -21,11 +21,25 @@ #include "moal_cfg80211.h" #include "moal_sta_cfg80211.h" -static int woal_cfg80211_reg_notifier(struct wiphy *wiphy, - struct regulatory_request *request); +#include "moal_eth_ioctl.h" +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) +static void +#else +static int +#endif + + +woal_cfg80211_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) +static int woal_cfg80211_scan(struct wiphy *wiphy, + struct cfg80211_scan_request *request); +#else static int woal_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_scan_request *request); +#endif static int woal_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_connect_params *sme); @@ -41,6 +55,10 @@ static int woal_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev, int idx, t_u8 * mac, struct station_info *sinfo); +static int woal_cfg80211_dump_survey(struct wiphy *wiphy, + struct net_device *dev, int idx, + struct survey_info *survey); + static int woal_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, bool enabled, int timeout); @@ -51,6 +69,9 @@ static int woal_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy, #endif static int woal_cfg80211_set_tx_power(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) + struct wireless_dev *wdev, +#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) && !defined(COMPAT_WIRELESS) enum tx_power_setting type, #else @@ -68,34 +89,61 @@ static int woal_cfg80211_leave_ibss(struct wiphy *wiphy, #if defined(WIFI_DIRECT_SUPPORT) #if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION static int woal_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct wireless_dev *wdev, +#else struct net_device *dev, +#endif u64 cookie); -void woal_cfg80211_remain_on_channel_done(void *context); - static int woal_cfg80211_remain_on_channel(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct wireless_dev *wdev, +#else struct net_device *dev, +#endif struct ieee80211_channel *chan, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) enum nl80211_channel_type - channel_type, unsigned int duration, - u64 * cookie); + channel_type, +#endif + unsigned int duration, u64 * cookie); static int woal_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct wireless_dev *wdev, +#else struct net_device *dev, +#endif u64 cookie); #endif /* KERNEL_VERSION */ #endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */ -/** cfg80211 STA operations */ -static struct cfg80211_ops woal_cfg80211_sta_ops = { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) || defined(COMPAT_WIRELESS) +int woal_cfg80211_sched_scan_start(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_sched_scan_request *request); +int woal_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev); +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)|| defined(COMPAT_WIRELESS) +int woal_cfg80211_resume(struct wiphy *wiphy); +int woal_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow); +#endif + +/** cfg80211 operations */ +static struct cfg80211_ops woal_cfg80211_ops = { .change_virtual_intf = woal_cfg80211_change_virtual_intf, .scan = woal_cfg80211_scan, .connect = woal_cfg80211_connect, .disconnect = woal_cfg80211_disconnect, .get_station = woal_cfg80211_get_station, .dump_station = woal_cfg80211_dump_station, + .dump_survey = woal_cfg80211_dump_survey, .set_wiphy_params = woal_cfg80211_set_wiphy_params, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) .set_channel = woal_cfg80211_set_channel, +#endif .join_ibss = woal_cfg80211_join_ibss, .leave_ibss = woal_cfg80211_leave_ibss, .add_key = woal_cfg80211_add_key, @@ -103,10 +151,24 @@ static struct cfg80211_ops woal_cfg80211_sta_ops = { .set_default_key = woal_cfg80211_set_default_key, .set_power_mgmt = woal_cfg80211_set_power_mgmt, .set_tx_power = woal_cfg80211_set_tx_power, + .set_bitrate_mask = woal_cfg80211_set_bitrate_mask, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) || defined(COMPAT_WIRELESS) + .sched_scan_start = woal_cfg80211_sched_scan_start, + .sched_scan_stop = woal_cfg80211_sched_scan_stop, +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)|| defined(COMPAT_WIRELESS) + .suspend = woal_cfg80211_suspend, + .resume = woal_cfg80211_resume, +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) || defined(COMPAT_WIRELESS) + .set_antenna = woal_cfg80211_set_antenna, +#endif #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) || defined(COMPAT_WIRELESS) .set_cqm_rssi_config = woal_cfg80211_set_cqm_rssi_config, #endif #ifdef UAP_CFG80211 + .add_virtual_intf = woal_cfg80211_add_virtual_intf, + .del_virtual_intf = woal_cfg80211_del_virtual_intf, #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) .start_ap = woal_cfg80211_add_beacon, .change_beacon = woal_cfg80211_set_beacon, @@ -116,53 +178,32 @@ static struct cfg80211_ops woal_cfg80211_sta_ops = { .set_beacon = woal_cfg80211_set_beacon, .del_beacon = woal_cfg80211_del_beacon, #endif + .del_station = woal_cfg80211_del_station, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) || defined(COMPAT_WIRELESS) .mgmt_frame_register = woal_cfg80211_mgmt_frame_register, .mgmt_tx = woal_cfg80211_mgmt_tx, #endif -#endif -}; - #if defined(WIFI_DIRECT_SUPPORT) #if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION -/** cfg80211 Wifi Direct operations */ -static struct cfg80211_ops woal_cfg80211_wifi_direct_ops = { - .change_virtual_intf = woal_cfg80211_change_virtual_intf, - .scan = woal_cfg80211_scan, - .connect = woal_cfg80211_connect, - .disconnect = woal_cfg80211_disconnect, - .get_station = woal_cfg80211_get_station, - .dump_station = woal_cfg80211_dump_station, - .set_wiphy_params = woal_cfg80211_set_wiphy_params, - .set_channel = woal_cfg80211_set_channel, - .add_key = woal_cfg80211_add_key, - .del_key = woal_cfg80211_del_key, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) - .start_ap = woal_cfg80211_add_beacon, - .change_beacon = woal_cfg80211_set_beacon, - .stop_ap = woal_cfg80211_del_beacon, -#else - .add_beacon = woal_cfg80211_add_beacon, - .set_beacon = woal_cfg80211_set_beacon, - .del_beacon = woal_cfg80211_del_beacon, -#endif - .mgmt_frame_register = woal_cfg80211_mgmt_frame_register, - .mgmt_tx = woal_cfg80211_mgmt_tx, .mgmt_tx_cancel_wait = woal_cfg80211_mgmt_tx_cancel_wait, .remain_on_channel = woal_cfg80211_remain_on_channel, .cancel_remain_on_channel = woal_cfg80211_cancel_remain_on_channel, - .set_default_key = woal_cfg80211_set_default_key, - .set_power_mgmt = woal_cfg80211_set_power_mgmt, - .set_tx_power = woal_cfg80211_set_tx_power, +#endif +#endif +#endif }; -#endif /* KERNEL_VERSION */ -#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */ + +/** Region code mapping */ +typedef struct _region_code_t +{ + /** Region */ + t_u8 region[COUNTRY_CODE_LEN]; +} region_code_t; /******************************************************** Local Variables ********************************************************/ -#if defined(WIFI_DIRECT_SUPPORT) -#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) || defined(COMPAT_WIRELESS) static const struct ieee80211_txrx_stypes ieee80211_mgmt_stypes[NUM_NL80211_IFTYPES] = { [NL80211_IFTYPE_ADHOC] = { @@ -189,6 +230,8 @@ static const struct ieee80211_txrx_stypes .tx = 0x0000, .rx = 0x0000, }, +#if defined(WIFI_DIRECT_SUPPORT) +#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION [NL80211_IFTYPE_P2P_CLIENT] = { .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | BIT(IEEE80211_STYPE_PROBE_RESP >> 4), @@ -197,8 +240,7 @@ static const struct ieee80211_txrx_stypes }, [NL80211_IFTYPE_P2P_GO] = { .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | - // BIT(IEEE80211_STYPE_PROBE_RESP >> 4) | - 0, + BIT(IEEE80211_STYPE_PROBE_RESP >> 4), .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | @@ -207,6 +249,8 @@ static const struct ieee80211_txrx_stypes BIT(IEEE80211_STYPE_DEAUTH >> 4) | BIT(IEEE80211_STYPE_ACTION >> 4), }, +#endif +#endif [NL80211_IFTYPE_MESH_POINT] = { .tx = 0x0000, .rx = 0x0000, @@ -214,7 +258,11 @@ static const struct ieee80211_txrx_stypes }; #endif -#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */ + +extern moal_handle *m_handle[]; +extern int hw_test; +/** Region alpha2 string */ +char *reg_alpha2 = NULL; /******************************************************** Global Variables @@ -223,6 +271,38 @@ static const struct ieee80211_txrx_stypes /******************************************************** Local Functions ********************************************************/ + +/** + * @brief This function check cfg80211 special region code. + * + * @param region_string Region string + * + * @return MTRUE/MFALSE + */ +t_u8 +is_cfg80211_special_region_code(char *region_string) +{ + t_u8 i; + t_u8 size = 0; + region_code_t cfg80211_special_region_code[] = + { {"00 "}, {"99 "}, {"98 "}, {"97 "} }; + + size = sizeof(cfg80211_special_region_code) / sizeof(region_code_t); + + for (i = 0; i < COUNTRY_CODE_LEN && region_string[i]; i++) { + region_string[i] = toupper(region_string[i]); + } + + for (i = 0; i < size; i++) { + if (!memcmp(region_string, + cfg80211_special_region_code[i].region, COUNTRY_CODE_LEN)) { + PRINTM(MIOCTL, "special region code=%s\n", region_string); + return MTRUE; + } + } + return MFALSE; +} + /** * @brief Get the encryption mode from cipher * @@ -240,7 +320,7 @@ woal_cfg80211_get_encryption_mode(t_u32 cipher, int *wpa_enabled) *wpa_enabled = 0; switch (cipher) { - case IW_AUTH_CIPHER_NONE: + case MW_AUTH_CIPHER_NONE: encrypt_mode = MLAN_ENCRYPTION_MODE_NONE; break; case WLAN_CIPHER_SUITE_WEP40: @@ -266,6 +346,36 @@ woal_cfg80211_get_encryption_mode(t_u32 cipher, int *wpa_enabled) } /** + * @brief get associate failure status code + * + * @param priv Pointer to the moal_private driver data struct + * + * @return IEEE status code + */ +static int +woal_get_assoc_status(moal_private * priv) +{ + int ret = WLAN_STATUS_UNSPECIFIED_FAILURE; + t_u16 status = (t_u16) (priv->assoc_status & 0xffff); + t_u16 cap = (t_u16) (priv->assoc_status >> 16); + + switch (cap) { + case 0xfffd: + case 0xfffe: + ret = status; + break; + case 0xfffc: + ret = WLAN_STATUS_AUTH_TIMEOUT; + break; + default: + break; + } + PRINTM(MCMND, "Assoc fail: status=%d, cap=0x%x, IEEE status=%d\n", status, + cap, ret); + return ret; +} + +/** * @brief Check the pairwise or group cipher for * WEP enabled or not * @@ -364,40 +474,6 @@ woal_channel_to_nl80211_channel_type(int channel_type) } /** - * @brief Convert driver band configuration to IEEE band type - * - * @param band Driver band configuration - * - * @return IEEE band type - */ -t_u8 -woal_band_cfg_to_ieee_band(t_u32 band) -{ - t_u8 ret_radio_type; - - ENTER(); - - switch (band) { - case BAND_A: - case BAND_AN: - case BAND_A | BAND_AN: - ret_radio_type = IEEE80211_BAND_5GHZ; - break; - case BAND_B: - case BAND_G: - case BAND_B | BAND_G: - case BAND_GN: - case BAND_B | BAND_GN: - default: - ret_radio_type = IEEE80211_BAND_2GHZ; - break; - } - - LEAVE(); - return ret_radio_type; -} - -/** * @brief Convert NL80211 interface type to MLAN_BSS_MODE_* * * @param iftype Interface type of NL80211 @@ -508,7 +584,10 @@ woal_cfg80211_assoc_ies_cfg(moal_private * priv, t_u8 * ie, int ie_len) break; case VENDOR_SPECIFIC_221: pvendor_ie = (IEEEtypes_VendorSpecific_t *) pcurrent_ptr; - if (!memcmp(pvendor_ie->vend_hdr.oui, wps_oui, sizeof(wps_oui))) { + if (!memcmp + (pvendor_ie->vend_hdr.oui, wps_oui, + sizeof(pvendor_ie->vend_hdr.oui)) && + (pvendor_ie->vend_hdr.oui_type == wps_oui[3])) { PRINTM(MIOCTL, "Enable WPS session\n"); woal_wps_cfg(priv, MTRUE); } @@ -561,7 +640,6 @@ woal_send_domain_info_cmd_fw(moal_private * priv) t_u8 first_chan = 0, next_chan = 0, max_pwr = 0; t_u8 i, flag = 0; mlan_ds_11d_cfg *cfg_11d = NULL; - mlan_ds_radio_cfg *radio_cfg = NULL; mlan_ioctl_req *req = NULL; ENTER(); @@ -571,31 +649,22 @@ woal_send_domain_info_cmd_fw(moal_private * priv) ret = MLAN_STATUS_FAILURE; goto done; } - - /* Allocate an IOCTL request buffer */ - req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg)); - if (req == NULL) { + band = priv->phandle->band; + if (!priv->wdev->wiphy->bands[band]) { + PRINTM(MERROR, "11D: setting domain info in FW failed band=%d", band); ret = MLAN_STATUS_FAILURE; goto done; } - radio_cfg = (mlan_ds_radio_cfg *) req->pbuf; - radio_cfg->sub_command = MLAN_OID_BAND_CFG; - req->req_id = MLAN_IOCTL_RADIO_CFG; - req->action = MLAN_ACT_GET; - if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { - ret = MLAN_STATUS_FAILURE; - goto done; - } - band = woal_band_cfg_to_ieee_band(radio_cfg->param.band_cfg.config_bands); - if (!priv->wdev->wiphy->bands[band]) { - PRINTM(MERROR, "11D: setting domain info in FW failed"); - ret = MLAN_STATUS_FAILURE; + if (MTRUE == is_cfg80211_special_region_code(priv->phandle->country_code)) { + PRINTM(MIOCTL, + "skip region code config, cfg80211 special region code: %s\n", + priv->phandle->country_code); goto done; } - kfree(req); - req = NULL; - + PRINTM(MIOCTL, "Send domain info: country=%c%c band=%d\n", + priv->phandle->country_code[0], priv->phandle->country_code[1], + band); /* Allocate an IOCTL request buffer */ req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11d_cfg)); if (req == NULL) { @@ -608,8 +677,8 @@ woal_send_domain_info_cmd_fw(moal_private * priv) req->action = MLAN_ACT_SET; /* Set country code */ - cfg_11d->param.domain_info.country_code[0] = priv->country_code[0]; - cfg_11d->param.domain_info.country_code[1] = priv->country_code[1]; + cfg_11d->param.domain_info.country_code[0] = priv->phandle->country_code[0]; + cfg_11d->param.domain_info.country_code[1] = priv->phandle->country_code[1]; cfg_11d->param.domain_info.country_code[2] = ' '; cfg_11d->param.domain_info.band = band; @@ -711,29 +780,27 @@ woal_set_rf_channel(moal_private * priv, ret = -EFAULT; goto done; } - if (chan) { - req->action = MLAN_ACT_SET; - /* Set appropriate bands */ - if (chan->band == IEEE80211_BAND_2GHZ) - config_bands = BAND_B | BAND_G | BAND_GN; - else - config_bands = BAND_AN | BAND_A; - if (mode == MLAN_BSS_MODE_IBSS) { - radio_cfg->param.band_cfg.adhoc_start_band = config_bands; - radio_cfg->param.band_cfg.adhoc_channel = - ieee80211_frequency_to_channel(chan->center_freq); - } - /* Set channel offset */ - radio_cfg->param.band_cfg.sec_chan_offset = - woal_cfg80211_channel_type_to_channel(channel_type); + req->action = MLAN_ACT_SET; + priv->phandle->band = chan->band; + /* Set appropriate bands */ + if (chan->band == IEEE80211_BAND_2GHZ) + config_bands = BAND_B | BAND_G | BAND_GN; + else + config_bands = BAND_AN | BAND_A; + if (mode == MLAN_BSS_MODE_IBSS) { + radio_cfg->param.band_cfg.adhoc_start_band = config_bands; + radio_cfg->param.band_cfg.adhoc_channel = + ieee80211_frequency_to_channel(chan->center_freq); + } + /* Set channel offset */ + radio_cfg->param.band_cfg.sec_chan_offset = + woal_cfg80211_channel_type_to_channel(channel_type); - if (MLAN_STATUS_SUCCESS != - woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { - ret = -EFAULT; - goto done; - } - woal_send_domain_info_cmd_fw(priv); + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; } + woal_send_domain_info_cmd_fw(priv); PRINTM(MINFO, "Setting band %d, channel bandwidth %d and mode = %d channel=%d\n", @@ -869,13 +936,15 @@ woal_cfg80211_set_auth(moal_private * priv, int encrypt_mode, int wpa_enabled) * - WPA IE * - RSN IE * - * @param priv A pointer to moal_private structure - * @param ssid A pointer to mlan_802_11_ssid structure + * @param priv A pointer to moal_private structure + * @param ssid_bssid A pointer to A pointer to mlan_ssid_bssid structure + * @param wait_option wait_option * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status -woal_inform_bss_from_scan_result(moal_private * priv, mlan_802_11_ssid * ssid) +woal_inform_bss_from_scan_result(moal_private * priv, + mlan_ssid_bssid * ssid_bssid, t_u8 wait_option) { mlan_status ret = MLAN_STATUS_SUCCESS; struct ieee80211_channel *chan; @@ -893,8 +962,7 @@ woal_inform_bss_from_scan_result(moal_private * priv, mlan_802_11_ssid * ssid) memset(&scan_resp, 0, sizeof(scan_resp)); if (MLAN_STATUS_SUCCESS != woal_get_scan_table(priv, - MOAL_IOCTL_WAIT, - &scan_resp)) { + wait_option, &scan_resp)) { ret = MLAN_STATUS_FAILURE; goto done; } @@ -902,15 +970,19 @@ woal_inform_bss_from_scan_result(moal_private * priv, mlan_802_11_ssid * ssid) if (scan_resp.num_in_scan_table) { scan_table = (BSSDescriptor_t *) scan_resp.pscan_table; for (i = 0; i < scan_resp.num_in_scan_table; i++) { - if (ssid) { + if (ssid_bssid) { /* Inform specific BSS only */ - if (memcmp(ssid->ssid, scan_table[i].ssid.ssid, ssid->ssid_len)) + if (memcmp(ssid_bssid->ssid.ssid, scan_table[i].ssid.ssid, + ssid_bssid->ssid.ssid_len) || + memcmp(ssid_bssid->bssid, scan_table[i].mac_address, + ETH_ALEN)) continue; } if (!scan_table[i].freq) { - PRINTM(MERROR, "Invalid channel number %d\n", - (int) scan_table[i].channel); - continue; + scan_table[i].freq = + ieee80211_channel_to_frequency((int) scan_table[i].channel, + woal_band_cfg_to_ieee_band + (scan_table[i].bss_band)); } chan = ieee80211_get_channel(priv->wdev->wiphy, scan_table[i].freq); if (!chan) { @@ -932,8 +1004,14 @@ woal_inform_bss_from_scan_result(moal_private * priv, mlan_802_11_ssid * ssid) -RSSI_DBM_TO_MDM(scan_table[i].rssi), GFP_KERNEL); if (pub) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) pub->len_information_elements = pub->len_beacon_ies; +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) + cfg80211_put_bss(priv->wdev->wiphy, pub); +#else cfg80211_put_bss(pub); +#endif } } } @@ -1007,13 +1085,98 @@ woal_cfg80211_inform_ibss_bss(moal_private * priv, beacon_interval, ie_buf, ie_len, signal.bcn_rssi_avg, GFP_KERNEL); if (bss) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) + cfg80211_put_bss(priv->wdev->wiphy, bss); +#else cfg80211_put_bss(bss); +#endif done: LEAVE(); return ret; } /** + * @brief Process country IE before assoicate + * + * @param priv A pointer to moal_private structure + * @param bss A pointer to cfg80211_bss structure + * + * @return 0 -- success, otherwise fail + */ +static int +woal_process_country_ie(moal_private * priv, struct cfg80211_bss *bss) +{ + u8 *country_ie, country_ie_len; + int ret = 0; + mlan_ioctl_req *req = NULL; + mlan_ds_11d_cfg *cfg_11d = NULL; + + ENTER(); + country_ie = (u8 *) ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY); + if (!country_ie) { + PRINTM(MIOCTL, "No country IE found!\n"); + woal_send_domain_info_cmd_fw(priv); + LEAVE(); + return 0; + } + + country_ie_len = country_ie[1]; + if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) { + PRINTM(MIOCTL, "Wrong Country IE length!\n"); + woal_send_domain_info_cmd_fw(priv); + LEAVE(); + return 0; + } + PRINTM(MIOCTL, "Find bss country IE: %c%c band=%d\n", country_ie[2], + country_ie[3], priv->phandle->band); + priv->phandle->country_code[0] = country_ie[2]; + priv->phandle->country_code[1] = country_ie[3]; + priv->phandle->country_code[2] = ' '; + if (MLAN_STATUS_SUCCESS != + woal_set_region_code(priv, priv->phandle->country_code)) + PRINTM(MERROR, "Set country code failed!\n"); + + /* Allocate an IOCTL request buffer */ + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11d_cfg)); + if (req == NULL) { + PRINTM(MERROR, "Fail to allocate mlan_ds_11d_cfg buffer\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + + cfg_11d = (mlan_ds_11d_cfg *) req->pbuf; + cfg_11d->sub_command = MLAN_OID_11D_DOMAIN_INFO; + req->req_id = MLAN_IOCTL_11D_CFG; + req->action = MLAN_ACT_SET; + + /* Set country code */ + cfg_11d->param.domain_info.country_code[0] = priv->phandle->country_code[0]; + cfg_11d->param.domain_info.country_code[1] = priv->phandle->country_code[1]; + cfg_11d->param.domain_info.country_code[2] = ' '; + + /** IEEE80211_BAND_2GHZ or IEEE80211_BAND_5GHZ */ + cfg_11d->param.domain_info.band = priv->phandle->band; + + country_ie_len -= IEEE80211_COUNTRY_STRING_LEN; + cfg_11d->param.domain_info.no_of_sub_band = + country_ie_len / sizeof(struct ieee80211_country_ie_triplet); + memcpy((u8 *) cfg_11d->param.domain_info.sub_band, + &country_ie[2] + IEEE80211_COUNTRY_STRING_LEN, country_ie_len); + + /* Send domain info command to FW */ + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + ret = MLAN_STATUS_FAILURE; + PRINTM(MERROR, "11D: Error setting domain info in FW\n"); + goto done; + } + done: + if (req) + kfree(req); + LEAVE(); + return ret; +} + +/** * @brief Request the driver for (re)association * * @param priv A pointer to moal_private structure @@ -1021,7 +1184,7 @@ woal_cfg80211_inform_ibss_bss(moal_private * priv, * * @return 0 -- success, otherwise fail */ -static int +int woal_cfg80211_assoc(moal_private * priv, void *sme) { struct cfg80211_ibss_params *ibss_param = NULL; @@ -1042,6 +1205,7 @@ woal_cfg80211_assoc(moal_private * priv, void *sme) struct ieee80211_channel *channel = NULL; t_u16 beacon_interval = 0; bool privacy; + struct cfg80211_bss *bss = NULL; ENTER(); @@ -1052,29 +1216,46 @@ woal_cfg80211_assoc(moal_private * priv, void *sme) ssid = ibss_param->ssid; ssid_len = ibss_param->ssid_len; bssid = ibss_param->bssid; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) channel = ibss_param->channel; +#else + channel = ibss_param->chandef.chan; +#endif + if (channel) + priv->phandle->band = channel->band; if (ibss_param->ie_len) ie = ibss_param->ie; ie_len = ibss_param->ie_len; beacon_interval = ibss_param->beacon_interval; privacy = ibss_param->privacy; + } else { conn_param = (struct cfg80211_connect_params *) sme; ssid = conn_param->ssid; ssid_len = conn_param->ssid_len; bssid = conn_param->bssid; channel = conn_param->channel; + if (channel) + priv->phandle->band = channel->band; if (conn_param->ie_len) ie = conn_param->ie; ie_len = conn_param->ie_len; privacy = conn_param->privacy; + bss = + cfg80211_get_bss(priv->wdev->wiphy, channel, bssid, ssid, ssid_len, + WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); + if (bss) { + woal_process_country_ie(priv, bss); + cfg80211_put_bss(bss); + } else + woal_send_domain_info_cmd_fw(priv); } memset(&req_ssid, 0, sizeof(mlan_802_11_ssid)); memset(&ssid_bssid, 0, sizeof(mlan_ssid_bssid)); req_ssid.ssid_len = ssid_len; - if (ssid_len > IW_ESSID_MAX_SIZE) { + if (ssid_len > MW_ESSID_MAX_SIZE) { PRINTM(MERROR, "Invalid SSID - aborting\n"); ret = -EINVAL; goto done; @@ -1264,7 +1445,8 @@ woal_cfg80211_assoc(moal_private * priv, void *sme) } /* Disconnect before try to associate */ - woal_disconnect(priv, MOAL_IOCTL_WAIT, NULL); + if (mode == MLAN_BSS_MODE_IBSS) + woal_disconnect(priv, MOAL_IOCTL_WAIT, NULL); if (mode != MLAN_BSS_MODE_IBSS) { if (MLAN_STATUS_SUCCESS != @@ -1275,7 +1457,8 @@ woal_cfg80211_assoc(moal_private * priv, void *sme) /* Inform the BSS information to kernel, otherwise kernel will give a panic after successful assoc */ if (MLAN_STATUS_SUCCESS != - woal_inform_bss_from_scan_result(priv, &req_ssid)) { + woal_inform_bss_from_scan_result(priv, &ssid_bssid, + MOAL_IOCTL_WAIT)) { ret = -EFAULT; goto done; } @@ -1284,8 +1467,8 @@ woal_cfg80211_assoc(moal_private * priv, void *sme) /* Adhoc start, Check the channel command */ woal_11h_channel_check_ioctl(priv); - PRINTM(MINFO, "Trying to associate to %s and bssid %pM\n", - (char *) req_ssid.ssid, ssid_bssid.bssid); + PRINTM(MINFO, "Trying to associate to %s and bssid " MACSTR "\n", + (char *) req_ssid.ssid, MAC2STR(ssid_bssid.bssid)); /* Zero SSID implies use BSSID to connect */ if (bssid) @@ -1311,9 +1494,15 @@ woal_cfg80211_assoc(moal_private * priv, void *sme) done: if (ret) { + /* clear the encryption mode */ + woal_cfg80211_set_auth(priv, MLAN_ENCRYPTION_MODE_NONE, MFALSE); /* clear IE */ ie_len = 0; - woal_set_get_gen_ie(priv, MLAN_ACT_SET, NULL, &ie_len); + if (MLAN_STATUS_SUCCESS != + woal_set_get_gen_ie(priv, MLAN_ACT_SET, NULL, &ie_len)) { + PRINTM(MERROR, "Could not clear RSN IE\n"); + ret = -EFAULT; + } } if (req) kfree(req); @@ -1388,6 +1577,9 @@ woal_cfg80211_dump_station_info(moal_private * priv, struct station_info *sinfo) mlan_ds_get_signal signal; mlan_ioctl_req *req = NULL; mlan_ds_rate *rate = NULL; + t_u16 Rates[12] = + { 0x02, 0x04, 0x0B, 0x16, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, + 0x6c }; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) || defined(COMPAT_WIRELESS) mlan_bss_info bss_info; t_u8 dtim_period = 0; @@ -1420,14 +1612,20 @@ woal_cfg80211_dump_station_info(moal_private * priv, struct station_info *sinfo) ret = MLAN_STATUS_FAILURE; goto done; } - sinfo->txrate.flags = RATE_INFO_FLAGS_MCS; - if (rate->param.data_rate.tx_ht_bw == MLAN_HT_BW40) { - sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; - } - if (rate->param.data_rate.tx_ht_gi == MLAN_HT_SGI) { - sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; + if (rate->param.data_rate.tx_data_rate >= MLAN_RATE_INDEX_MCS0) { + sinfo->txrate.flags = RATE_INFO_FLAGS_MCS; + if (rate->param.data_rate.tx_ht_bw == MLAN_HT_BW40) { + sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; + } + if (rate->param.data_rate.tx_ht_gi == MLAN_HT_SGI) { + sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; + } + sinfo->txrate.mcs = + rate->param.data_rate.tx_data_rate - MLAN_RATE_INDEX_MCS0; + } else { + /* Bit rate is in 500 kb/s units. Convert it to 100kb/s units */ + sinfo->txrate.legacy = Rates[rate->param.data_rate.tx_data_rate] * 5; } - sinfo->txrate.mcs = rate->param.data_rate.tx_data_rate; sinfo->rx_bytes = priv->stats.rx_bytes; sinfo->tx_bytes = priv->stats.tx_bytes; sinfo->rx_packets = priv->stats.rx_packets; @@ -1476,52 +1674,85 @@ woal_cfg80211_dump_station_info(moal_private * priv, struct station_info *sinfo) * * @return 0 */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) +static void +#else static int +#endif woal_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) { - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = NULL; + moal_handle *handle = (moal_handle *) woal_get_wiphy_priv(wiphy); +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0) int ret = 0; +#endif ENTER(); + priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY); if (!priv) { PRINTM(MFATAL, "Unable to get priv in %s()\n", __FUNCTION__); LEAVE(); +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0) return -EINVAL; +#else + return; +#endif } - PRINTM(MINFO, "cfg80211 regulatory domain callback " + PRINTM(MIOCTL, "cfg80211 regulatory domain callback " "%c%c\n", request->alpha2[0], request->alpha2[1]); - - if (MLAN_STATUS_SUCCESS != woal_set_region_code(priv, request->alpha2)) + if (MTRUE == is_cfg80211_special_region_code(request->alpha2)) { + PRINTM(MIOCTL, "Skip configure special region code\n"); + LEAVE(); + return ret; + } + handle->country_code[0] = request->alpha2[0]; + handle->country_code[1] = request->alpha2[1]; + handle->country_code[2] = ' '; + if (MLAN_STATUS_SUCCESS != woal_set_region_code(priv, handle->country_code)) PRINTM(MERROR, "Set country code failed!\n"); - memcpy(priv->country_code, request->alpha2, COUNTRY_CODE_LEN); - switch (request->initiator) { case NL80211_REGDOM_SET_BY_DRIVER: - PRINTM(MINFO, "Regulatory domain BY_DRIVER\n"); + PRINTM(MIOCTL, "Regulatory domain BY_DRIVER\n"); break; case NL80211_REGDOM_SET_BY_CORE: - PRINTM(MINFO, "Regulatory domain BY_CORE\n"); + PRINTM(MIOCTL, "Regulatory domain BY_CORE\n"); break; case NL80211_REGDOM_SET_BY_USER: - PRINTM(MINFO, "Regulatory domain BY_USER\n"); + PRINTM(MIOCTL, "Regulatory domain BY_USER\n"); break; /* TODO: apply driver specific changes in channel flags based on the request initiator if necessory. * */ case NL80211_REGDOM_SET_BY_COUNTRY_IE: - PRINTM(MINFO, "Regulatory domain BY_COUNTRY_IE\n"); + PRINTM(MIOCTL, "Regulatory domain BY_COUNTRY_IE\n"); break; } - - if (MLAN_STATUS_SUCCESS != woal_send_domain_info_cmd_fw(priv)) - ret = -EFAULT; - + if (priv->wdev && priv->wdev->wiphy && + (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)) + woal_send_domain_info_cmd_fw(priv); LEAVE(); +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0) return ret; +#endif } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) +/** + * @brief Request the driver to do a scan. Always returning + * zero meaning that the scan request is given to driver, + * and will be valid until passed to cfg80211_scan_done(). + * To inform scan results, call cfg80211_inform_bss(). + * + * @param wiphy A pointer to wiphy structure + * @param request A pointer to cfg80211_scan_request structure + * + * @return 0 -- success, otherwise fail + */ +static int +woal_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) +#else /** * @brief Request the driver to do a scan. Always returning * zero meaning that the scan request is given to driver, @@ -1537,7 +1768,11 @@ woal_cfg80211_reg_notifier(struct wiphy *wiphy, static int woal_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_scan_request *request) +#endif { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct net_device *dev = request->wdev->netdev; +#endif moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); wlan_user_scan_cfg scan_req; mlan_bss_info bss_info; @@ -1547,28 +1782,35 @@ woal_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, ENTER(); PRINTM(MINFO, "Received scan request on %s\n", dev->name); -#if defined(WIFI_DIRECT_SUPPORT) -#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION +#ifdef UAP_CFG80211 if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) { LEAVE(); cfg80211_scan_done(request, MTRUE); return 0; } #endif -#endif + if (priv->phandle->scan_pending_on_block == MTRUE) { PRINTM(MINFO, "scan already in processing...\n"); LEAVE(); return -EBUSY; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) || defined(COMPAT_WIRELESS) + if (priv->last_event & EVENT_BG_SCAN_REPORT) { + PRINTM(MINFO, "block scan while pending BGSCAN result\n"); + priv->last_event = 0; + cfg80211_scan_done(request, MTRUE); + LEAVE(); + return 0; + } +#endif #if defined(STA_CFG80211) || defined(UAP_CFG80211) #ifdef WIFI_DIRECT_SUPPORT - if (priv->phandle->remain_on_channel || priv->phandle->is_go_timer_set) { - PRINTM(MINFO, "block scan ... remain_on_channel=%d go_timer=%d\n", - priv->phandle->remain_on_channel, - priv->phandle->is_go_timer_set); + if (priv->phandle->is_go_timer_set) { + PRINTM(MINFO, "block scan in go timer....\n"); + cfg80211_scan_done(request, MTRUE); LEAVE(); - return -EBUSY; + return 0; } #endif #endif @@ -1602,23 +1844,32 @@ woal_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, #if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT && priv->scan_request->n_ssids) { - if (!memcmp(scan_req.ssid_list[i - 1].ssid, "DIRECT-", 7)) { - /* Enable wildcard ssid scan */ - memcpy(scan_req.ssid_list[i].ssid, "DIRECT-*", 8); - scan_req.ssid_list[i].max_len = 0xff; + if (!memcmp(scan_req.ssid_list[0].ssid, "DIRECT-", 7)) { + scan_req.ssid_list[0].max_len = 0xfe; } } #endif #endif - for (i = 0; i < priv->scan_request->n_channels; i++) { + for (i = 0; + i < MIN(WLAN_USER_SCAN_CHAN_MAX, priv->scan_request->n_channels); + i++) { chan = priv->scan_request->channels[i]; scan_req.chan_list[i].chan_number = chan->hw_value; scan_req.chan_list[i].radio_type = chan->band; - if (chan->flags & IEEE80211_CHAN_DISABLED) + if (chan->flags & (IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_RADAR)) scan_req.chan_list[i].scan_type = MLAN_SCAN_TYPE_PASSIVE; else scan_req.chan_list[i].scan_type = MLAN_SCAN_TYPE_ACTIVE; scan_req.chan_list[i].scan_time = 0; +#if defined(WIFI_DIRECT_SUPPORT) +#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION + if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT && + priv->scan_request->n_ssids) { + if (!memcmp(scan_req.ssid_list[0].ssid, "DIRECT-", 7)) + scan_req.chan_list[i].scan_time = MIN_SPECIFIC_SCAN_CHAN_TIME; + } +#endif +#endif } if (priv->scan_request->ie && priv->scan_request->ie_len) { if (MLAN_STATUS_SUCCESS != @@ -1627,14 +1878,15 @@ woal_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, (t_u8 *) priv->scan_request->ie, priv->scan_request->ie_len, MGMT_MASK_PROBE_REQ)) { - PRINTM(MERROR, "Fail to set mgmt frame IE\n"); + PRINTM(MERROR, "Fail to set scan request IE\n"); ret = -EFAULT; goto done; } } else { /** Clear SCAN IE in Firmware */ - woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL, 0, NULL, 0, NULL, 0, - MGMT_MASK_PROBE_REQ); + if (priv->probereq_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK) + woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL, 0, NULL, 0, NULL, + 0, MGMT_MASK_PROBE_REQ); } if (MLAN_STATUS_SUCCESS != woal_do_scan(priv, &scan_req)) { PRINTM(MERROR, "woal_do_scan fails!\n"); @@ -1642,8 +1894,10 @@ woal_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, goto done; } done: - if (ret) + if (ret) { + cfg80211_scan_done(request, MTRUE); priv->scan_request = NULL; + } LEAVE(); return ret; } @@ -1664,11 +1918,18 @@ woal_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, { moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); int ret = 0; + mlan_bss_info bss_info; + mlan_ssid_bssid ssid_bssid; ENTER(); PRINTM(MINFO, "Received association request on %s\n", dev->name); - +#ifdef UAP_CFG80211 + if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) { + LEAVE(); + return 0; + } +#endif if (priv->wdev->iftype != NL80211_IFTYPE_STATION #if defined(WIFI_DIRECT_SUPPORT) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) || defined(COMPAT_WIRELESS) @@ -1681,6 +1942,24 @@ woal_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, LEAVE(); return -EINVAL; } + + memset(&ssid_bssid, 0, sizeof(ssid_bssid)); + memcpy(&ssid_bssid.ssid.ssid, sme->ssid, sme->ssid_len); + ssid_bssid.ssid.ssid_len = sme->ssid_len; + if (sme->bssid) + memcpy(&ssid_bssid.bssid, sme->bssid, ETH_ALEN); + if (MTRUE == woal_is_connected(priv, &ssid_bssid)) { + /* Inform the BSS information to kernel, otherwise * kernel will give a + panic after successful assoc */ + woal_inform_bss_from_scan_result(priv, &ssid_bssid, MOAL_IOCTL_WAIT); + cfg80211_connect_result(priv->netdev, priv->cfg_bssid, NULL, 0, + NULL, 0, WLAN_STATUS_SUCCESS, GFP_KERNEL); + PRINTM(MMSG, "wlan: already connected to bssid " MACSTR "\n", + MAC2STR(priv->cfg_bssid)); + LEAVE(); + return 0; + } + /** cancel pending scan */ woal_cancel_scan(priv, MOAL_IOCTL_WAIT); #if defined(WIFI_DIRECT_SUPPORT) @@ -1704,28 +1983,38 @@ woal_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, #endif #endif + priv->cfg_connect = MTRUE; if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE) woal_set_scan_type(priv, MLAN_SCAN_TYPE_ACTIVE); + priv->assoc_status = 0; ret = woal_cfg80211_assoc(priv, (void *) sme); if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE) woal_set_scan_type(priv, MLAN_SCAN_TYPE_PASSIVE); - + priv->cfg_connect = MFALSE; if (!ret) { cfg80211_connect_result(priv->netdev, priv->cfg_bssid, NULL, 0, NULL, 0, WLAN_STATUS_SUCCESS, GFP_KERNEL); - PRINTM(MINFO, "Associated to bssid %pM successfully\n", - priv->cfg_bssid); + PRINTM(MMSG, "wlan: Connected to bssid " MACSTR " successfully\n", + MAC2STR(priv->cfg_bssid)); + priv->rssi_low = DEFAULT_RSSI_LOW_THRESHOLD; + if (priv->bss_type == MLAN_BSS_TYPE_STA) + woal_save_conn_params(priv, sme); + memset(&bss_info, 0, sizeof(bss_info)); + woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info); + priv->channel = bss_info.bss_chan; + } else { - PRINTM(MINFO, "Association to bssid %pM failed\n", priv->cfg_bssid); + PRINTM(MINFO, "wlan: Failed to connect to bssid " MACSTR "\n", + MAC2STR(priv->cfg_bssid)); cfg80211_connect_result(priv->netdev, priv->cfg_bssid, NULL, 0, - NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, + NULL, 0, woal_get_assoc_status(priv), GFP_KERNEL); memset(priv->cfg_bssid, 0, ETH_ALEN); } LEAVE(); - return ret; + return 0; } /** @@ -1745,7 +2034,12 @@ woal_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, ENTER(); PRINTM(MINFO, "Received disassociation request on %s\n", dev->name); - +#ifdef UAP_CFG80211 + if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) { + LEAVE(); + return 0; + } +#endif if (priv->cfg_disconnect) { PRINTM(MERROR, "Disassociation already in progress\n"); LEAVE(); @@ -1765,10 +2059,13 @@ woal_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, return -EFAULT; } - PRINTM(MINFO, "Successfully disconnected from %pM: Reason code %d\n", - priv->cfg_bssid, reason_code); + PRINTM(MINFO, "Successfully disconnected from " MACSTR ": Reason code %d\n", + MAC2STR(priv->cfg_bssid), reason_code); memset(priv->cfg_bssid, 0, ETH_ALEN); + if (priv->bss_type == MLAN_BSS_TYPE_STA) + woal_clear_conn_params(priv); + priv->channel = 0; LEAVE(); return 0; @@ -1862,6 +2159,59 @@ woal_cfg80211_dump_station(struct wiphy *wiphy, } /** + * @brief Request the driver to dump survey info + * + * @param wiphy A pointer to wiphy structure + * @param dev A pointer to net_device structure + * @param idx Station index + * @param survey A pointer to survey_info structure + * + * @return 0 -- success, otherwise fail + */ +static int +woal_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *dev, + int idx, struct survey_info *survey) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); + mlan_bss_info bss_info; + enum ieee80211_band band; + ENTER(); +#ifdef UAP_CFG80211 + if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) { + LEAVE(); + return -EFAULT; + } +#endif + if (!priv->media_connected || idx != 0) { + PRINTM(MINFO, "cfg80211: Media not connected or" + " not for this station!\n"); + LEAVE(); + return -ENOENT; + } + + memset(&bss_info, 0, sizeof(bss_info)); + if (MLAN_STATUS_SUCCESS != + woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) { + ret = -EFAULT; + goto done; + } + band = woal_band_cfg_to_ieee_band(bss_info.bss_band); + survey->channel = + ieee80211_get_channel(wiphy, + ieee80211_channel_to_frequency(bss_info.bss_chan, + band)); + + if (bss_info.bcn_nf_last) { + survey->filled = SURVEY_INFO_NOISE_DBM; + survey->noise = bss_info.bcn_nf_last; + } + done: + LEAVE(); + return ret; +} + +/** * @brief Request the driver to Join the specified * IBSS (or create if necessary) * @@ -1892,7 +2242,7 @@ woal_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, if (!ret) { cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL); PRINTM(MINFO, "Joined/created adhoc network with bssid" - " %pM successfully\n", priv->cfg_bssid); + MACSTR " successfully\n", MAC2STR(priv->cfg_bssid)); } else { PRINTM(MINFO, "Failed creating/joining adhoc network\n"); memset(priv->cfg_bssid, 0, ETH_ALEN); @@ -1930,7 +2280,7 @@ woal_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) priv->cfg_disconnect = 1; - PRINTM(MINFO, "Leaving from IBSS %pM\n", priv->cfg_bssid); + PRINTM(MINFO, "Leaving from IBSS " MACSTR "\n", MAC2STR(priv->cfg_bssid)); if (woal_disconnect(priv, MOAL_IOCTL_WAIT, priv->cfg_bssid) != MLAN_STATUS_SUCCESS) { LEAVE(); @@ -1962,7 +2312,11 @@ woal_cfg80211_set_power_mgmt(struct wiphy *wiphy, moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); ENTER(); - + if (hw_test) { + PRINTM(MIOCTL, "block set power in hw_test mode\n"); + LEAVE(); + return ret; + } if (enabled) disabled = 0; else @@ -1988,6 +2342,9 @@ woal_cfg80211_set_power_mgmt(struct wiphy *wiphy, */ static int woal_cfg80211_set_tx_power(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) + struct wireless_dev *wdev, +#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) && !defined(COMPAT_WIRELESS) enum tx_power_setting type, #else @@ -1996,11 +2353,13 @@ woal_cfg80211_set_tx_power(struct wiphy *wiphy, int dbm) { int ret = 0; - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = NULL; + moal_handle *handle = (moal_handle *) woal_get_wiphy_priv(wiphy); mlan_power_cfg_t power_cfg; ENTER(); + priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY); if (!priv) { PRINTM(MFATAL, "Unable to get priv in %s()\n", __FUNCTION__); LEAVE(); @@ -2042,7 +2401,7 @@ woal_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy, PRINTM(MIOCTL, "rssi_thold=%d rssi_hyst=%d\n", (int) rssi_thold, (int) rssi_hyst); - woal_set_rssi_threshold(priv, 0); + woal_set_rssi_threshold(priv, 0, MOAL_IOCTL_WAIT); LEAVE(); return 0; } @@ -2075,10 +2434,20 @@ woal_cfg80211_remain_on_channel_cfg(moal_private * priv, int ret = 0; ENTER(); + + if (!status || (!chan && !remove)) { + LEAVE(); + return -EFAULT; + } memset(&chan_cfg, 0, sizeof(mlan_ds_remain_chan)); if (remove) { chan_cfg.remove = MTRUE; } else { + if (priv->phandle->is_go_timer_set) { + PRINTM(MINFO, "block remain on channel while go timer is on\n"); + LEAVE(); + return -EBUSY; + } if (chan->band == IEEE80211_BAND_2GHZ) chan_cfg.bandcfg = 0; else if (chan->band == IEEE80211_BAND_5GHZ) @@ -2108,6 +2477,20 @@ woal_cfg80211_remain_on_channel_cfg(moal_private * priv, return ret; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) +/** + * @brief tx mgmt frame + * + * @param wiphy A pointer to wiphy structure + * @param wdev A pointer to wireless_dev structure + * @param cookie A pointer to frame cookie + * + * @return 0 -- success, otherwise fail + */ +static int +woal_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, u64 cookie) +#else /** * @brief tx mgmt frame * @@ -2120,27 +2503,46 @@ woal_cfg80211_remain_on_channel_cfg(moal_private * priv, static int woal_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, struct net_device *dev, u64 cookie) +#endif { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct net_device *dev = wdev->netdev; +#endif moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); int ret = 0; t_u8 status = 1; + moal_private *remain_priv = NULL; ENTER(); if (priv->phandle->remain_on_channel) { - if (woal_cfg80211_remain_on_channel_cfg(priv, - MOAL_IOCTL_WAIT, MTRUE, &status, - NULL, 0, 0)) { - PRINTM(MERROR, "Fail to cancel remain on channel\n"); + remain_priv = priv->phandle->priv[priv->phandle->remain_bss_index]; + if (!remain_priv) { + PRINTM(MERROR, "mgmt_tx_cancel_wait: Wrong remain_bss_index=%d\n", + priv->phandle->remain_bss_index); + ret = -EFAULT; + goto done; + } + if (woal_cfg80211_remain_on_channel_cfg + (remain_priv, MOAL_IOCTL_WAIT, MTRUE, &status, NULL, 0, 0)) { + PRINTM(MERROR, + "mgmt_tx_cancel_wait: Fail to cancel remain on channel\n"); ret = -EFAULT; goto done; } if (priv->phandle->cookie) { - cfg80211_remain_on_channel_expired(priv->netdev, - priv->phandle->cookie, - &priv->phandle->chan, - priv->phandle->channel_type, - GFP_ATOMIC); + cfg80211_remain_on_channel_expired( +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) + remain_priv->netdev, +#else + remain_priv->wdev, +#endif + priv->phandle->cookie, + &priv->phandle->chan, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) + priv->phandle->channel_type, +#endif + GFP_ATOMIC); priv->phandle->cookie = 0; } priv->phandle->remain_on_channel = MFALSE; @@ -2151,6 +2553,28 @@ woal_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, return ret; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) +/** + * @brief Make chip remain on channel + * + * @param wiphy A pointer to wiphy structure + * @param wdev A pointer to wireless_dev structure + * @param chan A pointer to ieee80211_channel structure + * @param channel_type Channel type + * @param duration Duration for timer + * @param cookie A pointer to timer cookie + * + * @return 0 -- success, otherwise fail + */ +static int +woal_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) + enum nl80211_channel_type channel_type, +#endif + unsigned int duration, u64 * cookie) +#else /** * @brief Make chip remain on channel * @@ -2169,10 +2593,15 @@ woal_cfg80211_remain_on_channel(struct wiphy *wiphy, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type, unsigned int duration, u64 * cookie) +#endif { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct net_device *dev = wdev->netdev; +#endif moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); int ret = 0; t_u8 status = 1; + moal_private *remain_priv = NULL; ENTER(); @@ -2183,10 +2612,17 @@ woal_cfg80211_remain_on_channel(struct wiphy *wiphy, } /** cancel previous remain on channel */ if (priv->phandle->remain_on_channel) { - if (woal_cfg80211_remain_on_channel_cfg(priv, - MOAL_IOCTL_WAIT, MTRUE, &status, - NULL, 0, 0)) { - PRINTM(MERROR, "Fail to cancel remain on channel\n"); + remain_priv = priv->phandle->priv[priv->phandle->remain_bss_index]; + if (!remain_priv) { + PRINTM(MERROR, "remain_on_channel: Wrong remain_bss_index=%d\n", + priv->phandle->remain_bss_index); + ret = -EFAULT; + goto done; + } + if (woal_cfg80211_remain_on_channel_cfg + (remain_priv, MOAL_IOCTL_WAIT, MTRUE, &status, NULL, 0, 0)) { + PRINTM(MERROR, + "remain_on_channel: Fail to cancel remain on channel\n"); ret = -EFAULT; goto done; } @@ -2197,7 +2633,12 @@ woal_cfg80211_remain_on_channel(struct wiphy *wiphy, woal_cancel_scan(priv, MOAL_IOCTL_WAIT); if (MLAN_STATUS_SUCCESS != woal_cfg80211_remain_on_channel_cfg(priv, MOAL_IOCTL_WAIT, - MFALSE, &status, chan, channel_type, + MFALSE, &status, chan, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) + channel_type, +#else + 0, +#endif (t_u32) duration)) { ret = -EFAULT; goto done; @@ -2208,13 +2649,25 @@ woal_cfg80211_remain_on_channel(struct wiphy *wiphy, /* we need update the value cookie */ *cookie = (u64) random32() | 1; priv->phandle->remain_on_channel = MTRUE; + priv->phandle->remain_bss_index = priv->bss_index; priv->phandle->cookie = *cookie; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) priv->phandle->channel_type = channel_type; +#endif memcpy(&priv->phandle->chan, chan, sizeof(struct ieee80211_channel)); - cfg80211_ready_on_channel(dev, *cookie, chan, - channel_type, duration, GFP_KERNEL); - PRINTM(MIOCTL, "Set remain on Channel: channel=%d cookie = %#llx\n", - ieee80211_frequency_to_channel(chan->center_freq), + cfg80211_ready_on_channel( +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) + dev, +#else + priv->wdev, +#endif + *cookie, chan, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) + channel_type, +#endif + duration, GFP_KERNEL); + PRINTM(MIOCTL, "%s: Set remain on Channel: channel=%d cookie = %#llx\n", + dev->name, ieee80211_frequency_to_channel(chan->center_freq), priv->phandle->cookie); } done: @@ -2222,6 +2675,20 @@ woal_cfg80211_remain_on_channel(struct wiphy *wiphy, return ret; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) +/** + * @brief Cancel remain on channel + * + * @param wiphy A pointer to wiphy structure + * @param wdev A pointer to wireless_dev structure + * @param cookie A pointer to timer cookie + * + * @return 0 -- success, otherwise fail + */ +static int +woal_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, u64 cookie) +#else /** * @brief Cancel remain on channel * @@ -2234,17 +2701,29 @@ woal_cfg80211_remain_on_channel(struct wiphy *wiphy, static int woal_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, u64 cookie) +#endif { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct net_device *dev = wdev->netdev; +#endif moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); + moal_private *remain_priv = NULL; int ret = 0; t_u8 status = 1; ENTER(); PRINTM(MIOCTL, "Cancel remain on Channel: cookie = %#llx\n", cookie); - if (woal_cfg80211_remain_on_channel_cfg(priv, - MOAL_IOCTL_WAIT, MTRUE, &status, - NULL, 0, 0)) { - PRINTM(MERROR, "Fail to cancel remain on channel\n"); + remain_priv = priv->phandle->priv[priv->phandle->remain_bss_index]; + if (!remain_priv) { + PRINTM(MERROR, "cancel_remain_on_channel: Wrong remain_bss_index=%d\n", + priv->phandle->remain_bss_index); + ret = -EFAULT; + goto done; + } + if (woal_cfg80211_remain_on_channel_cfg + (remain_priv, MOAL_IOCTL_WAIT, MTRUE, &status, NULL, 0, 0)) { + PRINTM(MERROR, + "cancel_remain_on_channel: Fail to cancel remain on channel\n"); ret = -EFAULT; goto done; } @@ -2259,6 +2738,397 @@ woal_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, #endif /* KERNEL_VERSION */ #endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) || defined(COMPAT_WIRELESS) +/** + * @brief start sched scan + * + * @param wiphy A pointer to wiphy structure + * @param dev A pointer to net_device structure + * @param request A pointer to struct cfg80211_sched_scan_request + * + * @return 0 -- success, otherwise fail + */ +int +woal_cfg80211_sched_scan_start(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_sched_scan_request *request) +{ + struct ieee80211_channel *chan = NULL; + int i = 0; + int ret = 0; + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); + struct cfg80211_ssid *ssid = NULL; + ENTER(); +#ifdef UAP_CFG80211 + if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) { + LEAVE(); + return -EFAULT; + } +#endif + + memset(&priv->scan_cfg, 0, sizeof(priv->scan_cfg)); + if ((!request || !request->n_ssids || !request->n_match_sets)) { + PRINTM(MERROR, "Invalid sched_scan req parameter\n"); + LEAVE(); + return -EINVAL; + } + PRINTM(MIOCTL, + "%s sched scan: n_ssids=%d n_match_sets=%d n_channels=%d interval=%d ie_len=%d\n", + priv->netdev->name, request->n_ssids, request->n_match_sets, + request->n_channels, request->interval, request->ie_len); + /** cancel pending scan */ + woal_cancel_scan(priv, MOAL_IOCTL_WAIT); + for (i = 0; i < request->n_match_sets; i++) { + ssid = &request->match_sets[i].ssid; + strncpy(priv->scan_cfg.ssid_list[i].ssid, ssid->ssid, ssid->ssid_len); + priv->scan_cfg.ssid_list[i].max_len = 0; + PRINTM(MIOCTL, "sched scan: ssid=%s\n", ssid->ssid); + } + for (i = 0; i < MIN(WLAN_BG_SCAN_CHAN_MAX, request->n_channels); i++) { + chan = request->channels[i]; + priv->scan_cfg.chan_list[i].chan_number = chan->hw_value; + priv->scan_cfg.chan_list[i].radio_type = chan->band; + if (chan->flags & (IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_RADAR)) + priv->scan_cfg.chan_list[i].scan_type = MLAN_SCAN_TYPE_PASSIVE; + else + priv->scan_cfg.chan_list[i].scan_type = MLAN_SCAN_TYPE_ACTIVE; + priv->scan_cfg.chan_list[i].scan_time = 0; + } + + /** set scan request IES */ + if (request->ie && request->ie_len) { + if (MLAN_STATUS_SUCCESS != + woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, + NULL, 0, NULL, 0, + (t_u8 *) request->ie, request->ie_len, + MGMT_MASK_PROBE_REQ)) { + PRINTM(MERROR, "Fail to set sched scan IE\n"); + ret = -EFAULT; + goto done; + } + } else { + /** Clear SCAN IE in Firmware */ + if (priv->probereq_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK) + woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL, 0, NULL, 0, NULL, + 0, MGMT_MASK_PROBE_REQ); + } + + /* Interval between scan cycles in milliseconds,supplicant set to 10 second + */ + /* We want to use 30 second for per scan cycle */ + priv->scan_cfg.scan_interval = MIN_BGSCAN_INTERVAL; + if (request->interval > MIN_BGSCAN_INTERVAL) + priv->scan_cfg.scan_interval = request->interval; + + priv->scan_cfg.repeat_count = DEF_REPEAT_COUNT; + priv->scan_cfg.report_condition = BG_SCAN_SSID_MATCH; + priv->scan_cfg.bss_type = MLAN_BSS_MODE_INFRA; + priv->scan_cfg.action = BG_SCAN_ACT_SET; + priv->scan_cfg.enable = MTRUE; + + if (MLAN_STATUS_SUCCESS == + woal_request_bgscan(priv, MOAL_IOCTL_WAIT, &priv->scan_cfg)) { + priv->sched_scanning = MTRUE; + priv->bg_scan_start = MTRUE; + priv->bg_scan_reported = MFALSE; + } else + ret = -EFAULT; + done: + LEAVE(); + return ret; +} + +/** + * @brief stop sched scan + * + * @param wiphy A pointer to wiphy structure + * @param dev A pointer to net_device structure + * + * @return 0 -- success, otherwise fail + */ +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"); + priv->sched_scanning = MFALSE; + woal_stop_bg_scan(priv, MOAL_NO_WAIT); + priv->bg_scan_start = MFALSE; + priv->bg_scan_reported = MFALSE; + LEAVE(); + return 0; +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) || defined(COMPAT_WIRELESS) +/** + * @brief cfg80211_resume handler + * + * @param wiphy A pointer to wiphy structure + * + * @return 0 -- success, otherwise fail + */ +int +woal_cfg80211_resume(struct wiphy *wiphy) +{ + moal_handle *handle = (moal_handle *) woal_get_wiphy_priv(wiphy); + int i; + for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) { + if (handle->priv[i] && + (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA)) { + if ((handle->priv[i]->last_event & EVENT_BG_SCAN_REPORT) && + handle->priv[i]->sched_scanning) { + woal_inform_bss_from_scan_result(handle->priv[i], NULL, + MOAL_CMD_WAIT); + cfg80211_sched_scan_results(handle->priv[i]->wdev->wiphy); + handle->priv[i]->last_event = 0; + PRINTM(MIOCTL, "Report sched scan result in cfg80211 resume\n"); + } + } + } + handle->cfg80211_suspend = MFALSE; + PRINTM(MIOCTL, "woal_cfg80211_resume\n"); + return 0; +} + +/** + * @brief cfg80211_suspend handler + * + * @param wiphy A pointer to wiphy structure + * @param wow A pointer to cfg80211_wowlan + * + * @return 0 -- success, otherwise fail + */ +int +woal_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow) +{ + moal_handle *handle = (moal_handle *) woal_get_wiphy_priv(wiphy); + int i; + for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) { + if (handle->priv[i] && + (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA)) { + if (handle->priv[i]->scan_request) { + PRINTM(MIOCTL, + "Cancel pending scan in woal_cfg80211_suspend\n"); + woal_cancel_scan(handle->priv[i], MOAL_IOCTL_WAIT); + } + handle->priv[i]->last_event = 0; + } + } + PRINTM(MIOCTL, "woal_cfg80211_suspended\n"); + handle->cfg80211_suspend = MTRUE; + return 0; +} +#endif + +/** + * @brief Save connect parameters for roaming + * + * @param priv A pointer to moal_private + * @param sme A pointer to cfg80211_connect_params structure + */ +void +woal_save_conn_params(moal_private * priv, struct cfg80211_connect_params *sme) +{ + ENTER(); + memcpy(&priv->sme_current, sme, sizeof(struct cfg80211_connect_params)); + if (sme->channel) { + priv->sme_current.channel = &priv->conn_chan; + memcpy(priv->sme_current.channel, sme->channel, + sizeof(struct ieee80211_channel)); + } + if (sme->bssid) { + priv->sme_current.bssid = priv->conn_bssid; + memcpy(priv->sme_current.bssid, sme->bssid, MLAN_MAC_ADDR_LENGTH); + } + if (sme->ssid && sme->ssid_len) { + priv->sme_current.ssid = priv->conn_ssid; + memset(priv->conn_ssid, 0, MLAN_MAX_SSID_LENGTH); + memcpy(priv->sme_current.ssid, sme->ssid, sme->ssid_len); + } + if (sme->ie && sme->ie_len) { + priv->sme_current.ie = kzalloc(sme->ie_len, GFP_KERNEL); + memcpy(priv->sme_current.ie, sme->ie, sme->ie_len); + } + if (sme->key && sme->key_len && (sme->key_len <= MAX_WEP_KEY_SIZE)) { + priv->sme_current.key = priv->conn_wep_key; + memcpy((t_u8 *) priv->sme_current.key, sme->key, sme->key_len); + } +} + +/** + * @brief clear connect parameters for ing + * + * @param priv A pointer to moal_private + */ +void +woal_clear_conn_params(moal_private * priv) +{ + ENTER(); + if (priv->sme_current.ie_len && priv->sme_current.ie) + kfree(priv->sme_current.ie); + memset(&priv->sme_current, 0, sizeof(struct cfg80211_connect_params)); + priv->roaming_required = MFALSE; + LEAVE(); +} + +/** + * @brief Start roaming: driver handle roaming + * + * @param priv A pointer to moal_private structure + * + * @return N/A + */ +void +woal_start_roaming(moal_private * priv) +{ + mlan_ds_get_signal signal; + mlan_ssid_bssid ssid_bssid; + char rssi_low[10]; + int ret = 0; + mlan_ds_misc_assoc_rsp assoc_rsp; + IEEEtypes_AssocRsp_t *passoc_rsp = NULL; + + ENTER(); + if (priv->last_event & EVENT_BG_SCAN_REPORT) { + woal_inform_bss_from_scan_result(priv, NULL, MOAL_CMD_WAIT); + PRINTM(MIOCTL, "Report bgscan result\n"); + } + if (priv->media_connected == MFALSE || !priv->sme_current.ssid_len) { + PRINTM(MIOCTL, "Not connected, ignore roaming\n"); + LEAVE(); + return; + } + + /* Get signal information from the firmware */ + memset(&signal, 0, sizeof(mlan_ds_get_signal)); + if (MLAN_STATUS_SUCCESS != + woal_get_signal_info(priv, MOAL_CMD_WAIT, &signal)) { + PRINTM(MERROR, "Error getting signal information\n"); + ret = -EFAULT; + goto done; + } + memset(&ssid_bssid, 0, sizeof(mlan_ssid_bssid)); + ssid_bssid.ssid.ssid_len = priv->sme_current.ssid_len; + memcpy(ssid_bssid.ssid.ssid, priv->sme_current.ssid, + priv->sme_current.ssid_len); + if (MLAN_STATUS_SUCCESS != + woal_find_best_network(priv, MOAL_IOCTL_WAIT, &ssid_bssid)) { + PRINTM(MIOCTL, "Can not find better network\n"); + ret = -EFAULT; + goto done; + } + /* check if we found different AP */ + if (!memcmp(&ssid_bssid.bssid, priv->cfg_bssid, MLAN_MAC_ADDR_LENGTH)) { + PRINTM(MIOCTL, "This is the same AP, no roaming\n"); + ret = -EFAULT; + goto done; + } + PRINTM(MIOCTL, "Find AP: bssid=" MACSTR ", signal=%d\n", + MAC2STR(ssid_bssid.bssid), ssid_bssid.rssi); + /* check signal */ + if (!(priv->last_event & EVENT_PRE_BCN_LOST)) { + if ((abs(signal.bcn_rssi_avg) - abs(ssid_bssid.rssi)) < DELTA_RSSI) { + PRINTM(MERROR, "New AP's signal is not good too.\n"); + ret = -EFAULT; + goto done; + } + } + /* start roaming to new AP */ + priv->sme_current.bssid = priv->conn_bssid; + memcpy(priv->sme_current.bssid, &ssid_bssid.bssid, MLAN_MAC_ADDR_LENGTH); + ret = woal_cfg80211_assoc(priv, (void *) &priv->sme_current); + if (!ret) { + woal_inform_bss_from_scan_result(priv, NULL, MOAL_CMD_WAIT); + memset(&assoc_rsp, 0, sizeof(mlan_ds_misc_assoc_rsp)); + woal_get_assoc_rsp(priv, &assoc_rsp); + passoc_rsp = (IEEEtypes_AssocRsp_t *) assoc_rsp.assoc_resp_buf; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) || defined(COMPAT_WIRELESS) + cfg80211_roamed(priv->netdev, NULL, priv->cfg_bssid, + priv->sme_current.ie, priv->sme_current.ie_len, + passoc_rsp->ie_buffer, + assoc_rsp.assoc_resp_len - ASSOC_RESP_FIXED_SIZE, + GFP_KERNEL); +#else + cfg80211_roamed(priv->netdev, priv->cfg_bssid, priv->sme_current.ie, + priv->sme_current.ie_len, passoc_rsp->ie_buffer, + assoc_rsp.assoc_resp_len - ASSOC_RESP_FIXED_SIZE, + GFP_KERNEL); +#endif + PRINTM(MIOCTL, "Roamed to bssid " MACSTR " successfully\n", + MAC2STR(priv->cfg_bssid)); + } else { + PRINTM(MIOCTL, "Roaming to bssid " MACSTR " failed\n", + MAC2STR(ssid_bssid.bssid)); + } + done: + /* config rssi low threshold again */ + priv->last_event = 0; + priv->rssi_low = DEFAULT_RSSI_LOW_THRESHOLD; + sprintf(rssi_low, "%d", priv->rssi_low); + woal_set_rssi_low_threshold(priv, rssi_low, MOAL_CMD_WAIT); + LEAVE(); + return; +} + +/** + * @brief Register the device with cfg80211 + * + * @param dev A pointer to net_device structure + * @param bss_type BSS type + * + * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE + */ +mlan_status +woal_register_sta_cfg80211(struct net_device * dev, t_u8 bss_type) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + moal_private *priv = (moal_private *) netdev_priv(dev); + struct wireless_dev *wdev = NULL; + int disabled = 0; + + ENTER(); + + wdev = (struct wireless_dev *) &priv->w_dev; + memset(wdev, 0, sizeof(struct wireless_dev)); + wdev->wiphy = priv->phandle->wiphy; + if (!wdev->wiphy) { + LEAVE(); + return MLAN_STATUS_FAILURE; + } + if (bss_type == MLAN_BSS_TYPE_STA) { + wdev->iftype = NL80211_IFTYPE_STATION; + priv->roaming_enabled = MFALSE; + priv->roaming_required = MFALSE; + } +#if defined(WIFI_DIRECT_SUPPORT) +#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION + if (bss_type == MLAN_BSS_TYPE_WIFIDIRECT) + wdev->iftype = NL80211_IFTYPE_STATION; +#endif +#endif + + dev_net_set(dev, wiphy_net(wdev->wiphy)); + dev->ieee80211_ptr = wdev; + SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy)); + priv->wdev = wdev; + /* Get IEEE power save mode */ + if (MLAN_STATUS_SUCCESS == + woal_set_get_power_mgmt(priv, MLAN_ACT_GET, &disabled, 0)) { + /* Save the IEEE power save mode to wiphy, because after * warmreset + wiphy power save should be updated instead * of using the last saved + configuration */ + if (disabled) + priv->wdev->ps = MFALSE; + else + priv->wdev->ps = MTRUE; + } + woal_send_domain_info_cmd_fw(priv); + LEAVE(); + return ret; +} + /** * @brief Initialize the wiphy * @@ -2268,28 +3138,26 @@ woal_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status -woal_cfg80211_sta_init_wiphy(moal_private * priv, t_u8 wait_option) +woal_cfg80211_init_wiphy(moal_private * priv, t_u8 wait_option) { - int retry_count, rts_thr, frag_thr, disabled; + mlan_status ret = MLAN_STATUS_SUCCESS; + int retry_count, rts_thr, frag_thr; struct wiphy *wiphy = NULL; mlan_ioctl_req *req = NULL; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) || defined(COMPAT_WIRELESS) + mlan_ds_radio_cfg *radio = NULL; +#endif mlan_ds_11n_cfg *cfg_11n = NULL; t_u32 hw_dev_cap; ENTER(); - if (priv->wdev) - wiphy = priv->wdev->wiphy; - else { - PRINTM(MERROR, "Invalid parameter when init wiphy.\n"); - goto done; - } - + wiphy = priv->phandle->wiphy; /* Get 11n tx parameters from MLAN */ req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg)); if (req == NULL) { - LEAVE(); - return MLAN_STATUS_FAILURE; + ret = MLAN_STATUS_FAILURE; + goto done; } cfg_11n = (mlan_ds_11n_cfg *) req->pbuf; cfg_11n->sub_command = MLAN_OID_11N_HTCAP_CFG; @@ -2298,9 +3166,8 @@ woal_cfg80211_sta_init_wiphy(moal_private * priv, t_u8 wait_option) cfg_11n->param.htcap_cfg.hw_cap_req = MTRUE; if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, wait_option)) { - kfree(req); - LEAVE(); - return MLAN_STATUS_FAILURE; + ret = MLAN_STATUS_FAILURE; + goto done; } hw_dev_cap = cfg_11n->param.htcap_cfg.htcap; @@ -2311,9 +3178,8 @@ woal_cfg80211_sta_init_wiphy(moal_private * priv, t_u8 wait_option) req->action = MLAN_ACT_GET; if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, wait_option)) { - kfree(req); - LEAVE(); - return MLAN_STATUS_FAILURE; + ret = MLAN_STATUS_FAILURE; + goto done; } /* Initialize parameters for 2GHz and 5GHz bands */ @@ -2327,21 +3193,43 @@ woal_cfg80211_sta_init_wiphy(moal_private * priv, t_u8 wait_option) if (req) kfree(req); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) || defined(COMPAT_WIRELESS) + /* Get antenna modes */ + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg)); + if (req == NULL) { + ret = MLAN_STATUS_FAILURE; + goto done; + } + radio = (mlan_ds_radio_cfg *) req->pbuf; + radio->sub_command = MLAN_OID_ANT_CFG; + req->req_id = MLAN_IOCTL_RADIO_CFG; + req->action = MLAN_ACT_GET; + + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + ret = MLAN_STATUS_FAILURE; + goto done; + } + + /* Set available antennas to wiphy */ + wiphy->available_antennas_tx = radio->param.ant_cfg.tx_antenna; + wiphy->available_antennas_rx = radio->param.ant_cfg.rx_antenna; +#endif /* LINUX_VERSION_CODE */ + /* Set retry limit count to wiphy */ if (MLAN_STATUS_SUCCESS != woal_set_get_retry(priv, MLAN_ACT_GET, wait_option, &retry_count)) { - LEAVE(); - return MLAN_STATUS_FAILURE; + ret = MLAN_STATUS_FAILURE; + goto done; } wiphy->retry_long = (t_u8) retry_count; wiphy->retry_short = (t_u8) retry_count; wiphy->max_scan_ie_len = MAX_IE_SIZE; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) || defined(COMPAT_WIRELESS) + wiphy->mgmt_stypes = ieee80211_mgmt_stypes; +#endif #if defined(WIFI_DIRECT_SUPPORT) #if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION - /* we should add mgmt_stypes for both STA & Wifi Direct, while only - initialize duration_timer for Wifi Direct */ - wiphy->mgmt_stypes = ieee80211_mgmt_stypes; wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION; #endif /* KERNEL_VERSION */ #endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */ @@ -2349,8 +3237,8 @@ woal_cfg80211_sta_init_wiphy(moal_private * priv, t_u8 wait_option) /* Set RTS threshold to wiphy */ if (MLAN_STATUS_SUCCESS != woal_set_get_rts(priv, MLAN_ACT_GET, wait_option, &rts_thr)) { - LEAVE(); - return MLAN_STATUS_FAILURE; + ret = MLAN_STATUS_FAILURE; + goto done; } if (rts_thr < MLAN_RTS_MIN_VALUE || rts_thr > MLAN_RTS_MAX_VALUE) rts_thr = MLAN_FRAG_RTS_DISABLED; @@ -2359,169 +3247,138 @@ woal_cfg80211_sta_init_wiphy(moal_private * priv, t_u8 wait_option) /* Set fragment threshold to wiphy */ if (MLAN_STATUS_SUCCESS != woal_set_get_frag(priv, MLAN_ACT_GET, wait_option, &frag_thr)) { - LEAVE(); - return MLAN_STATUS_FAILURE; + ret = MLAN_STATUS_FAILURE; + goto done; } if (frag_thr < MLAN_RTS_MIN_VALUE || frag_thr > MLAN_RTS_MAX_VALUE) frag_thr = MLAN_FRAG_RTS_DISABLED; wiphy->frag_threshold = (t_u32) frag_thr; - /* Get IEEE power save mode */ - if (MLAN_STATUS_SUCCESS != woal_set_get_power_mgmt(priv, - MLAN_ACT_GET, &disabled, - 0)) { - LEAVE(); - return MLAN_STATUS_FAILURE; - } - /* Save the IEEE power save mode to wiphy, because after warmreset wiphy - power save should be updated instead of using the last saved - configuration */ - if (disabled) - priv->wdev->ps = MFALSE; - else - priv->wdev->ps = MTRUE; - done: LEAVE(); - return MLAN_STATUS_SUCCESS; + if (req) + kfree(req); + return ret; } -/** - * @brief Register the device with cfg80211 +/* + * This function registers the device with CFG802.11 subsystem. * - * @param dev A pointer to net_device structure - * @param bss_type BSS type + * @param priv A pointer to moal_private * - * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status -woal_register_sta_cfg80211(struct net_device * dev, t_u8 bss_type) +woal_register_cfg80211(moal_private * priv) { mlan_status ret = MLAN_STATUS_SUCCESS; - moal_private *priv = (moal_private *) netdev_priv(dev); + struct wiphy *wiphy; void *wdev_priv = NULL; - struct wireless_dev *wdev = NULL; mlan_fw_info fw_info; + char *country = NULL; + int index = 0; ENTER(); - /* Allocate wireless device */ - wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); - if (!wdev) { - PRINTM(MERROR, "Could not allocate wireless device\n"); - ret = MLAN_STATUS_FAILURE; - goto err_wdev; - } - - if (bss_type == MLAN_BSS_TYPE_STA) - /* Allocate wiphy */ - wdev->wiphy = wiphy_new(&woal_cfg80211_sta_ops, sizeof(moal_private *)); -#if defined(WIFI_DIRECT_SUPPORT) -#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION - else if (bss_type == MLAN_BSS_TYPE_WIFIDIRECT) - /* Allocate wiphy */ - wdev->wiphy = - wiphy_new(&woal_cfg80211_wifi_direct_ops, sizeof(moal_private *)); -#endif -#endif - else { - PRINTM(MERROR, "Unexpected bss_type when register cfg80211\n"); - ret = MLAN_STATUS_FAILURE; - goto err_wdev; - } - - if (!wdev->wiphy) { + wiphy = wiphy_new(&woal_cfg80211_ops, sizeof(moal_handle *)); + if (!wiphy) { PRINTM(MERROR, "Could not allocate wiphy device\n"); ret = MLAN_STATUS_FAILURE; - goto err_wdev; + goto err_wiphy; } - if (bss_type == MLAN_BSS_TYPE_STA) { - wdev->iftype = NL80211_IFTYPE_STATION; - wdev->wiphy->interface_modes = -#ifdef UAP_CFG80211 - MBIT(NL80211_IFTYPE_AP) | -#endif /* UAP_CFG80211 */ - MBIT(NL80211_IFTYPE_STATION) | MBIT(NL80211_IFTYPE_ADHOC); - wdev->wiphy->max_scan_ssids = 10; - } -#if defined(WIFI_DIRECT_SUPPORT) -#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION - if (bss_type == MLAN_BSS_TYPE_WIFIDIRECT) { - wdev->iftype = NL80211_IFTYPE_STATION; - wdev->wiphy->interface_modes = MBIT(NL80211_IFTYPE_STATION) | - MBIT(NL80211_IFTYPE_P2P_GO) | - MBIT(NL80211_IFTYPE_P2P_CLIENT) | - MBIT(NL80211_IFTYPE_ADHOC) | MBIT(NL80211_IFTYPE_AP) | 0; - wdev->wiphy->max_scan_ssids = 10; - } -#endif -#endif - - /* Set phy name like net device name */ - dev_set_name(&wdev->wiphy->dev, dev->name); + wiphy->max_scan_ssids = MRVDRV_MAX_SSID_LIST_LENGTH; + wiphy->max_scan_ie_len = MAX_IE_SIZE; + wiphy->interface_modes = 0; + wiphy->interface_modes = + MBIT(NL80211_IFTYPE_STATION) | MBIT(NL80211_IFTYPE_ADHOC) | + MBIT(NL80211_IFTYPE_AP); /* Make this wiphy known to this driver only */ - wdev->wiphy->privid = mrvl_wiphy_privid; - + wiphy->privid = mrvl_wiphy_privid; /* Supported bands */ - wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &cfg80211_band_2ghz; - if (MLAN_STATUS_SUCCESS == - woal_request_get_fw_info(priv, MOAL_CMD_WAIT, &fw_info)) { - if (fw_info.fw_bands & BAND_A) - wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &cfg80211_band_5ghz; - } -#define PASSIVE_SCAN_CHAN_TIME 130 -#define ACTIVE_SCAN_CHAN_TIME 130 -#define SPECIFIC_SCAN_CHAN_TIME 40 - woal_set_scan_time(priv, ACTIVE_SCAN_CHAN_TIME, PASSIVE_SCAN_CHAN_TIME, - SPECIFIC_SCAN_CHAN_TIME); - /* Initialize cipher suits */ - wdev->wiphy->cipher_suites = cfg80211_cipher_suites; - wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cfg80211_cipher_suites); + wiphy->bands[IEEE80211_BAND_2GHZ] = &cfg80211_band_2ghz; + + woal_request_get_fw_info(priv, MOAL_CMD_WAIT, &fw_info); + if (fw_info.fw_bands & BAND_A) { + wiphy->bands[IEEE80211_BAND_5GHZ] = &cfg80211_band_5ghz; + /** reduce scan time from 110ms to 80ms */ + woal_set_scan_time(priv, INIT_ACTIVE_SCAN_CHAN_TIME, + INIT_PASSIVE_SCAN_CHAN_TIME, + INIT_SPECIFIC_SCAN_CHAN_TIME); + } else + woal_set_scan_time(priv, ACTIVE_SCAN_CHAN_TIME, PASSIVE_SCAN_CHAN_TIME, + SPECIFIC_SCAN_CHAN_TIME); + woal_enable_ext_scan(priv, MTRUE); + priv->phandle->band = IEEE80211_BAND_2GHZ; - wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + /* Initialize cipher suits */ + wiphy->cipher_suites = cfg80211_cipher_suites; + wiphy->n_cipher_suites = ARRAY_SIZE(cfg80211_cipher_suites); - /* We are using custom domains */ - wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; + memcpy(wiphy->perm_addr, priv->current_addr, ETH_ALEN); + wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; - wdev->wiphy->reg_notifier = woal_cfg80211_reg_notifier; + wiphy->flags = 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) + wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_OFFCHAN_TX; + wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; +#endif +#ifdef ANDROID_KERNEL + wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME; +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) || defined(COMPAT_WIRELESS) + wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; + 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; +#endif - /* Set moal_private pointer in wiphy_priv */ - wdev_priv = wiphy_priv(wdev->wiphy); + wiphy->reg_notifier = woal_cfg80211_reg_notifier; - *(unsigned long *) wdev_priv = (unsigned long) priv; + /* Set struct moal_handle pointer in wiphy_priv */ + wdev_priv = wiphy_priv(wiphy); + *(unsigned long *) wdev_priv = (unsigned long) priv->phandle; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) || defined(COMPAT_WIRELESS) - set_wiphy_dev(wdev->wiphy, (struct device *) priv->phandle->hotplug_device); + set_wiphy_dev(wiphy, (struct device *) priv->phandle->hotplug_device); #endif - - if (wiphy_register(wdev->wiphy) < 0) { + /* Set phy name */ + for (index = 0; index < MAX_MLAN_ADAPTER; index++) { + if (m_handle[index] == priv->phandle) { + dev_set_name(&wiphy->dev, "mwiphy%d", index); + break; + } + } + if (wiphy_register(wiphy) < 0) { PRINTM(MERROR, "Wiphy device registration failed!\n"); ret = MLAN_STATUS_FAILURE; - goto err_wdev; + goto err_wiphy; } - - dev_net_set(dev, wiphy_net(wdev->wiphy)); - dev->ieee80211_ptr = wdev; - SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy)); - priv->wdev = wdev; - - if (ret != MLAN_STATUS_SUCCESS) { - PRINTM(MERROR, "Wiphy device registration failed!\n"); + /** we will try driver parameter first */ + if (reg_alpha2 && woal_is_valid_alpha2(reg_alpha2)) { + PRINTM(MIOCTL, "Notify reg_alpha2 %c%c\n", reg_alpha2[0], + reg_alpha2[1]); + regulatory_hint(wiphy, reg_alpha2); } else { - PRINTM(MINFO, "Successfully registered wiphy device\n"); - LEAVE(); - return ret; + country = region_code_2_string(fw_info.region_code); + if (country) { + PRINTM(MIOCTL, "Notify hw region code=%d %c%c\n", + fw_info.region_code, country[0], country[1]); + regulatory_hint(wiphy, country); + } else + PRINTM(MERROR, "hw region code=%d not supported\n", + fw_info.region_code); } - wiphy_unregister(wdev->wiphy); - err_wdev: - dev->ieee80211_ptr = NULL; - if (wdev) { - if (wdev->wiphy) - wiphy_free(wdev->wiphy); - kfree(wdev); - } + priv->phandle->wiphy = wiphy; + woal_cfg80211_init_wiphy(priv, MOAL_CMD_WAIT); + + return ret; + err_wiphy: + if (wiphy) + wiphy_free(wiphy); LEAVE(); return ret; } + +module_param(reg_alpha2, charp, 0); +MODULE_PARM_DESC(reg_alpha2, "Regulatory alpha2"); diff --git a/drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.h b/drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.h index a83957c5c031..4de8b90db7db 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.h +++ b/drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.h @@ -26,7 +26,6 @@ #define RSSI_DBM_TO_MDM(x) ((x) * 100) mlan_status woal_register_sta_cfg80211(struct net_device *dev, t_u8 bss_type); -mlan_status woal_cfg80211_sta_init_wiphy(moal_private * priv, t_u8 wait_option); mlan_status woal_cfg80211_set_key(moal_private * priv, t_u8 is_enable_wep, diff --git a/drivers/net/wireless/sd8797/mlinux/moal_uap.c b/drivers/net/wireless/sd8797/mlinux/moal_uap.c index 170f31a1bfbf..ddac122f6948 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_uap.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_uap.c @@ -1302,14 +1302,14 @@ woal_uap_ioctl(struct net_device *dev, struct ifreq *req) case UAP_SNMP_MIB: ret = woal_uap_snmp_mib(dev, req); break; - case UAP_DOMAIN_INFO: - ret = woal_uap_domain_info(dev, req); - break; #ifdef DFS_TESTING_SUPPORT case UAP_DFS_TESTING: ret = woal_uap_dfs_testing(dev, req); break; #endif + case UAP_DOMAIN_INFO: + ret = woal_uap_domain_info(dev, req); + break; case UAP_TX_BF_CFG: ret = woal_uap_tx_bf_cfg(dev, req); break; @@ -1367,12 +1367,8 @@ woal_uap_sta_deauth_ioctl(struct net_device *dev, struct ifreq *req) goto done; } - PRINTM(MIOCTL, - "ioctl deauth station: %02x:%02x:%02x:%02x:%02x:%02x, reason=%d\n", - deauth_param.mac_addr[0], deauth_param.mac_addr[1], - deauth_param.mac_addr[2], deauth_param.mac_addr[3], - deauth_param.mac_addr[4], deauth_param.mac_addr[5], - deauth_param.reason_code); + PRINTM(MIOCTL, "ioctl deauth station: " MACSTR ", reason=%d\n", + MAC2STR(deauth_param.mac_addr), deauth_param.reason_code); ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss)); if (ioctl_req == NULL) { @@ -2083,12 +2079,12 @@ woal_uap_set_11n_status(mlan_uap_bss_param * sys_cfg, t_u8 action) * @return 0 --success, otherwise fail */ int -woal_uap_ap_cfg_parse_data(mlan_uap_bss_param * ap_cfg, t_s8 * buf) +woal_uap_ap_cfg_parse_data(mlan_uap_bss_param * ap_cfg, char *buf) { int ret = 0, atoi_ret; int set_sec = 0, set_key = 0, set_chan = 0; int set_preamble = 0, set_scb = 0, set_ssid = 0; - t_s8 *begin = buf, *value = NULL, *opt = NULL; + char *begin = buf, *value = NULL, *opt = NULL; ENTER(); @@ -2282,7 +2278,7 @@ int woal_uap_set_ap_cfg(moal_private * priv, t_u8 * data, int len) { int ret = 0; - static t_s8 buf[MAX_BUF_LEN]; + static char buf[MAX_BUF_LEN]; mlan_uap_bss_param sys_config; int restart = 0; @@ -2296,7 +2292,7 @@ woal_uap_set_ap_cfg(moal_private * priv, t_u8 * data, int len) } memset(buf, 0, MAX_BUF_LEN); - memcpy(buf, data, len); + memcpy(buf, data, MIN(len, (sizeof(buf) - 1))); /* Initialize the uap bss values which are uploaded from firmware */ woal_uap_get_bss_param(priv, &sys_config, MOAL_IOCTL_WAIT); @@ -2412,9 +2408,13 @@ woal_uap_bss_ctrl(moal_private * priv, t_u8 wait_option, int data) goto done; } - if (data == UAP_BSS_STOP || data == UAP_BSS_RESET) + if (data == UAP_BSS_STOP || data == UAP_BSS_RESET) { priv->bss_started = MFALSE; - + woal_stop_queue(priv->netdev); + if (netif_carrier_ok(priv->netdev)) + netif_carrier_off(priv->netdev); + woal_flush_tcp_sess_queue(priv); + } done: if (req) kfree(req); @@ -2503,6 +2503,7 @@ woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd) return ret; } +#ifdef CONFIG_PROC_FS /** * @brief Get version * @@ -2536,7 +2537,7 @@ woal_uap_get_version(moal_private * priv, char *version, int max_len) if (status == MLAN_STATUS_SUCCESS) { PRINTM(MINFO, "MOAL UAP VERSION: %s\n", info->param.ver_ext.version_str); - snprintf(version, max_len, driver_version, + snprintf(version, max_len, priv->phandle->driver_version, info->param.ver_ext.version_str); } @@ -2546,6 +2547,7 @@ woal_uap_get_version(moal_private * priv, char *version, int max_len) LEAVE(); return; } +#endif /** * @brief Get uap statistics diff --git a/drivers/net/wireless/sd8797/mlinux/moal_uap.h b/drivers/net/wireless/sd8797/mlinux/moal_uap.h index b617e0aaf728..62d628a074c6 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_uap.h +++ b/drivers/net/wireless/sd8797/mlinux/moal_uap.h @@ -343,6 +343,25 @@ typedef struct _snmp_mib_para /** Oid for 802.11H enable/disable */ #define OID_80211H_ENABLE 0x000a +#ifdef DFS_TESTING_SUPPORT +/** dfs_testing parameters */ +typedef struct _dfs_testing_param +{ + /** subcmd */ + t_u32 subcmd; + /** Set/Get */ + t_u32 action; + /** user CAC period (msec) */ + t_u16 usr_cac_period; + /** user NOP period (sec) */ + t_u16 usr_nop_period; + /** don't change channel on radar */ + t_u8 no_chan_change; + /** fixed channel to change to on radar */ + t_u8 fixed_new_chan; +} dfs_testing_para; +#endif + /** domain_info parameters */ typedef struct _domain_info_param { @@ -363,29 +382,12 @@ typedef struct _domain_info_param #define MAX_DOMAIN_TLV_LEN (TLV_HEADER_LEN + COUNTRY_CODE_LEN \ + (SUB_BAND_LEN * MAX_SUB_BANDS)) -#ifdef DFS_TESTING_SUPPORT -/** dfs_testing parameters */ -typedef struct _dfs_testing_param -{ - /** subcmd */ - t_u32 subcmd; - /** Set/Get */ - t_u32 action; - /** user CAC period (msec) */ - t_u16 usr_cac_period; - /** user NOP period (sec) */ - t_u16 usr_nop_period; - /** don't change channel on radar */ - t_u8 no_chan_change; - /** fixed channel to change to on radar */ - t_u8 fixed_new_chan; -} dfs_testing_para; -#endif - void woal_uap_set_multicast_list(struct net_device *dev); int woal_uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd); int woal_uap_bss_ctrl(moal_private * priv, t_u8 wait_option, int data); +#ifdef CONFIG_PROC_FS void woal_uap_get_version(moal_private * priv, char *version, int max_len); +#endif mlan_status woal_uap_get_stats(moal_private * priv, t_u8 wait_option, mlan_ds_uap_stats * ustats); #if defined(UAP_WEXT) || defined(UAP_CFG80211) diff --git a/drivers/net/wireless/sd8797/mlinux/moal_uap_cfg80211.c b/drivers/net/wireless/sd8797/mlinux/moal_uap_cfg80211.c index f7907edffc73..917123f6978b 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_uap_cfg80211.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_uap_cfg80211.c @@ -21,118 +21,6 @@ #include "moal_cfg80211.h" #include "moal_uap_cfg80211.h" - -/* these 3 function will be called in woal_cfg80211_wifi_direct_ops */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) -int woal_cfg80211_add_beacon(struct wiphy *wiphy, - struct net_device *dev, - struct cfg80211_ap_settings *params); - -int woal_cfg80211_set_beacon(struct wiphy *wiphy, - struct net_device *dev, - struct cfg80211_beacon_data *params); -#else -int woal_cfg80211_add_beacon(struct wiphy *wiphy, - struct net_device *dev, - struct beacon_parameters *params); - -int woal_cfg80211_set_beacon(struct wiphy *wiphy, - struct net_device *dev, - struct beacon_parameters *params); -#endif - -int woal_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev); - -static int woal_uap_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_scan_request *request); - -static int woal_uap_cfg80211_connect(struct wiphy *wiphy, - struct net_device *dev, - struct cfg80211_connect_params *sme); - -static int woal_uap_cfg80211_disconnect(struct wiphy *wiphy, - struct net_device *dev, - t_u16 reason_code); - -int woal_uap_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, - u8 * mac, struct station_info *stainfo); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) || defined(COMPAT_WIRELESS) -static const struct ieee80211_txrx_stypes - ieee80211_uap_mgmt_stypes[NUM_NL80211_IFTYPES] = { - [NL80211_IFTYPE_ADHOC] = { - .tx = 0x0000, - .rx = 0x0000, - }, - [NL80211_IFTYPE_STATION] = { - .tx = BIT(IEEE80211_STYPE_ACTION >> 4), - .rx = BIT(IEEE80211_STYPE_ACTION >> 4), - }, - [NL80211_IFTYPE_AP] = { - .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | - BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | - BIT(IEEE80211_STYPE_DISASSOC >> 4) | - BIT(IEEE80211_STYPE_AUTH >> 4) | - BIT(IEEE80211_STYPE_DEAUTH >> 4) | - BIT(IEEE80211_STYPE_ACTION >> 4), - }, - [NL80211_IFTYPE_AP_VLAN] = { - .tx = 0x0000, - .rx = 0x0000, - }, - [NL80211_IFTYPE_P2P_CLIENT] = { - .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_RESP >> 4), - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4), - }, - [NL80211_IFTYPE_P2P_GO] = { - .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | - // BIT(IEEE80211_STYPE_PROBE_RESP >> 4) | - 0, - .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | - BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | - BIT(IEEE80211_STYPE_DISASSOC >> 4) | - BIT(IEEE80211_STYPE_AUTH >> 4) | - BIT(IEEE80211_STYPE_DEAUTH >> 4) | - BIT(IEEE80211_STYPE_ACTION >> 4), - }, - [NL80211_IFTYPE_MESH_POINT] = { - .tx = 0x0000, - .rx = 0x0000, - }, -}; -#endif - -/** cfg80211 uAP operations */ -static struct cfg80211_ops woal_cfg80211_uap_ops = { - .set_channel = woal_cfg80211_set_channel, - .scan = woal_uap_cfg80211_scan, - .connect = woal_uap_cfg80211_connect, - .disconnect = woal_uap_cfg80211_disconnect, - .set_wiphy_params = woal_cfg80211_set_wiphy_params, - .change_virtual_intf = woal_cfg80211_change_virtual_intf, - .add_key = woal_cfg80211_add_key, - .del_key = woal_cfg80211_del_key, - .set_default_key = woal_cfg80211_set_default_key, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) - .start_ap = woal_cfg80211_add_beacon, - .change_beacon = woal_cfg80211_set_beacon, - .stop_ap = woal_cfg80211_del_beacon, -#else - .add_beacon = woal_cfg80211_add_beacon, - .set_beacon = woal_cfg80211_set_beacon, - .del_beacon = woal_cfg80211_del_beacon, -#endif - .get_station = woal_uap_cfg80211_get_station, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) || defined(COMPAT_WIRELESS) - .mgmt_frame_register = woal_cfg80211_mgmt_frame_register, - .mgmt_tx = woal_cfg80211_mgmt_tx, -#endif -}; - /******************************************************** Local Variables ********************************************************/ @@ -149,7 +37,6 @@ static struct cfg80211_ops woal_cfg80211_uap_ops = { Global Functions ********************************************************/ -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) && !defined(COMPAT_WIRELESS) /** * @brief Verify RSN IE * @@ -170,6 +57,7 @@ woal_check_rsn_ie(IEEEtypes_Rsn_t * rsn_ie, mlan_uap_bss_param * sys_config) return MFALSE; sys_config->wpa_cfg.group_cipher = 0; sys_config->wpa_cfg.pairwise_cipher_wpa2 = 0; + sys_config->key_mgmt = 0; /* check the group cipher */ switch (rsn_ie->group_cipher.type) { case WPA_CIPHER_TKIP: @@ -204,14 +92,16 @@ woal_check_rsn_ie(IEEEtypes_Rsn_t * rsn_ie, mlan_uap_bss_param * sys_config) if (left < (sizeof(wpa_suite_auth_key_mgmt_t) + (count - 1) * sizeof(wpa_suite))) return MFALSE; - for (i = 0; i < count; i++) { switch (key_mgmt->list[i].type) { case RSN_AKM_8021X: - sys_config->key_mgmt = KEY_MGMT_EAP; + sys_config->key_mgmt |= KEY_MGMT_EAP; break; case RSN_AKM_PSK: - sys_config->key_mgmt = KEY_MGMT_PSK; + sys_config->key_mgmt |= KEY_MGMT_PSK; + break; + case RSN_AKM_PSK_SHA256: + sys_config->key_mgmt |= KEY_MGMT_PSK_SHA256; break; } } @@ -293,10 +183,10 @@ woal_check_wpa_ie(IEEEtypes_Wpa_t * wpa_ie, mlan_uap_bss_param * sys_config) * @return MTRUE/MFALSE */ static t_u8 -woal_find_wpa_ies(t_u8 * ie, int len, mlan_uap_bss_param * sys_config) +woal_find_wpa_ies(const t_u8 * ie, int len, mlan_uap_bss_param * sys_config) { int bytes_left = len; - t_u8 *pcurrent_ptr = ie; + const t_u8 *pcurrent_ptr = ie; t_u16 total_ie_len; t_u8 element_len; t_u8 wpa2 = 0; @@ -323,10 +213,14 @@ woal_find_wpa_ies(t_u8 * ie, int len, mlan_uap_bss_param * sys_config) break; case VENDOR_SPECIFIC_221: pvendor_ie = (IEEEtypes_VendorSpecific_t *) pcurrent_ptr; - if (!memcmp(pvendor_ie->vend_hdr.oui, wpa_oui, sizeof(wpa_oui))) + if (!memcmp + (pvendor_ie->vend_hdr.oui, wpa_oui, + sizeof(pvendor_ie->vend_hdr.oui)) && + (pvendor_ie->vend_hdr.oui_type == wpa_oui[3])) { wpa = woal_check_wpa_ie((IEEEtypes_Wpa_t *) pcurrent_ptr, sys_config); + } break; default: break; @@ -347,7 +241,6 @@ woal_find_wpa_ies(t_u8 * ie, int len, mlan_uap_bss_param * sys_config) } return ret; } -#endif /** secondary channel is below */ #define SECOND_CHANNEL_BELOW 0x30 @@ -475,6 +368,8 @@ woal_cfg80211_beacon_config(moal_private * priv, /* Setting the default values */ sys_config.channel = 6; sys_config.preamble_type = 0; + sys_config.mgmt_ie_passthru_mask = priv->mgmt_subtype_mask; + memcpy(sys_config.mac_addr, priv->current_addr, ETH_ALEN); if (priv->bss_type == MLAN_BSS_TYPE_UAP) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) @@ -530,11 +425,18 @@ woal_cfg80211_beacon_config(moal_private * priv, sys_config.auth_mode = MLAN_AUTH_MODE_SHARED; else sys_config.auth_mode = MLAN_AUTH_MODE_OPEN; - + if (params->crypto.n_akm_suites) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) + woal_find_wpa_ies(params->beacon.tail, (int) params->beacon.tail_len, + &sys_config); +#else + woal_find_wpa_ies(params->tail, params->tail_len, &sys_config); +#endif + } for (i = 0; i < params->crypto.n_akm_suites; i++) { switch (params->crypto.akm_suites[i]) { case WLAN_AKM_SUITE_8021X: - sys_config.key_mgmt = KEY_MGMT_EAP; + sys_config.key_mgmt |= KEY_MGMT_EAP; if ((params->crypto.wpa_versions & NL80211_WPA_VERSION_1) && (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)) sys_config.protocol = PROTOCOL_WPA | PROTOCOL_WPA2; @@ -544,7 +446,7 @@ woal_cfg80211_beacon_config(moal_private * priv, sys_config.protocol = PROTOCOL_WPA; break; case WLAN_AKM_SUITE_PSK: - sys_config.key_mgmt = KEY_MGMT_PSK; + sys_config.key_mgmt |= KEY_MGMT_PSK; if ((params->crypto.wpa_versions & NL80211_WPA_VERSION_1) && (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)) sys_config.protocol = PROTOCOL_WPA | PROTOCOL_WPA2; @@ -647,8 +549,8 @@ woal_cfg80211_beacon_config(moal_private * priv, if (capab_info & WLAN_CAPABILITY_PRIVACY) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) if (MFALSE == - woal_find_wpa_ies(params->beacon.tail, params->beacon.tail_len, - &sys_config)) + woal_find_wpa_ies(params->beacon.tail, + (int) params->beacon.tail_len, &sys_config)) #else if (MFALSE == woal_find_wpa_ies(params->tail, params->tail_len, &sys_config)) @@ -683,34 +585,485 @@ woal_cfg80211_beacon_config(moal_private * priv, return ret; } -static int -woal_uap_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_scan_request *request) +#if defined(WIFI_DIRECT_SUPPORT) +#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION +/** + * @brief Callback function for virtual interface + * setup + * + * @param dev A pointer to structure net_device + * + * @return N/A + */ +static void +woal_virt_if_setup(struct net_device *dev) +{ + ENTER(); + ether_setup(dev); + dev->destructor = free_netdev; + LEAVE(); +} + +/** + * @brief This function adds a new interface. It will + * allocate, initialize and register the device. + * + * @param handle A pointer to moal_handle structure + * @param bss_index BSS index number + * @param bss_type BSS type + * + * @return A pointer to the new priv structure + */ +moal_private * +woal_alloc_virt_interface(moal_handle * handle, t_u8 bss_index, t_u8 bss_type, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) + const +#endif + char *name) { + struct net_device *dev = NULL; + moal_private *priv = NULL; ENTER(); - cfg80211_scan_done(request, MTRUE); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) +#ifndef MAX_WMM_QUEUE +#define MAX_WMM_QUEUE 4 +#endif + /* Allocate an Ethernet device */ + if (! + (dev = + alloc_netdev_mq(sizeof(moal_private), name, woal_virt_if_setup, + MAX_WMM_QUEUE))) { +#else + if (!(dev = alloc_netdev(sizeof(moal_private), name, woal_virt_if_setup))) { +#endif + PRINTM(MFATAL, "Init virtual ethernet device failed\n"); + goto error; + } + /* Allocate device name */ + if ((dev_alloc_name(dev, name) < 0)) { + PRINTM(MERROR, "Could not allocate device name\n"); + goto error; + } + + priv = (moal_private *) netdev_priv(dev); + /* Save the priv to handle */ + handle->priv[bss_index] = priv; + + /* Use the same handle structure */ + priv->phandle = handle; + priv->netdev = dev; + priv->bss_index = bss_index; + priv->bss_type = bss_type; + priv->bss_role = MLAN_BSS_ROLE_STA; + INIT_LIST_HEAD(&priv->tcp_sess_queue); + spin_lock_init(&priv->tcp_sess_lock); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + SET_MODULE_OWNER(dev); +#endif + + PRINTM(MCMND, "Alloc virtual interface%s\n", dev->name); + + LEAVE(); + return priv; + error: + if (dev) + free_netdev(dev); LEAVE(); - return 0; + return NULL; } -static int -woal_uap_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_connect_params *sme) +/** + * @brief Request the driver to add a virtual interface + * + * @param wiphy A pointer to wiphy structure + * @param name Virtual interface name + * @param type Virtual interface type + * @param flags Flags for the virtual interface + * @param params A pointer to vif_params structure + * @param new_dev new net_device to return + * + * @return 0 -- success, otherwise fail + */ +int +woal_cfg80211_add_virt_if(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) + const +#endif + char *name, enum nl80211_iftype type, u32 * flags, + struct vif_params *params, + struct net_device **new_dev) { + int ret = 0; + struct net_device *ndev = NULL; + moal_private *priv, *new_priv; + moal_handle *handle = (moal_handle *) woal_get_wiphy_priv(wiphy); + struct wireless_dev *wdev = NULL; + ENTER(); + ASSERT_RTNL(); + priv = + (moal_private *) woal_get_priv_bss_type(handle, + MLAN_BSS_TYPE_WIFIDIRECT); + if (priv->phandle->drv_mode.intf_num == priv->phandle->priv_num) { + PRINTM(MERROR, "max virtual interface limit reached\n"); + LEAVE(); + return -ENOMEM; + } + if ((type != NL80211_IFTYPE_P2P_CLIENT) && (type != NL80211_IFTYPE_P2P_GO)) { + PRINTM(MERROR, "Invalid iftype: %d\n", type); + LEAVE(); + return -EINVAL; + } + + handle = priv->phandle; + /* Cancel previous scan req */ + woal_cancel_scan(priv, MOAL_IOCTL_WAIT); + new_priv = + woal_alloc_virt_interface(handle, handle->priv_num, + MLAN_BSS_TYPE_WIFIDIRECT, name); + if (!new_priv) { + PRINTM(MERROR, "Add virtual interface fail."); + LEAVE(); + return -EFAULT; + } + handle->priv_num++; + + wdev = (struct wireless_dev *) &new_priv->w_dev; + memset(wdev, 0, sizeof(struct wireless_dev)); + ndev = new_priv->netdev; + SET_NETDEV_DEV(ndev, wiphy_dev(wiphy)); + ndev->ieee80211_ptr = wdev; + wdev->iftype = type; + wdev->wiphy = wiphy; + new_priv->wdev = wdev; + new_priv->bss_virtual = MTRUE; + new_priv->pa_netdev = priv->netdev; + + woal_init_sta_dev(ndev, new_priv); + + /* Initialize priv structure */ + woal_init_priv(new_priv, MOAL_CMD_WAIT); + /** Init to GO/CLIENT mode */ + if (type == NL80211_IFTYPE_P2P_CLIENT) + woal_cfg80211_init_p2p_client(new_priv); + else if (type == NL80211_IFTYPE_P2P_GO) + woal_cfg80211_init_p2p_go(new_priv); + ret = register_netdevice(ndev); + if (ret) { + handle->priv[new_priv->bss_index] = NULL; + handle->priv_num--; + free_netdev(ndev); + ndev = NULL; + PRINTM(MFATAL, "register net_device failed, ret=%d\n", ret); + goto done; + } + netif_carrier_off(ndev); + woal_stop_queue(ndev); + if (new_dev) + *new_dev = ndev; + done: + if (ret) { + if (ndev && ndev->reg_state == NETREG_REGISTERED) + unregister_netdevice(ndev); + } LEAVE(); - return 0; + return ret; } -static int -woal_uap_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, - t_u16 reason_code) +/** + * @brief Notify mlan BSS will be removed. + * + * @param priv A pointer to moal_private structure + * + * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail + */ +mlan_status +woal_bss_remove(moal_private * priv) +{ + mlan_ioctl_req *req = NULL; + mlan_ds_bss *bss = NULL; + mlan_status status; + + ENTER(); + + /* Allocate an IOCTL request buffer */ + req = (mlan_ioctl_req *) woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss)); + if (req == NULL) { + status = MLAN_STATUS_FAILURE; + goto done; + } + + /* Fill request buffer */ + bss = (mlan_ds_bss *) req->pbuf; + bss->sub_command = MLAN_OID_BSS_REMOVE; + req->req_id = MLAN_IOCTL_BSS; + req->action = MLAN_ACT_SET; + /* Send IOCTL request to MLAN */ + status = woal_request_ioctl(priv, req, MOAL_CMD_WAIT); + + done: + if (req && (status != MLAN_STATUS_PENDING)) + kfree(req); + LEAVE(); + return status; +} + +/** + * @brief This function removes an virtual interface. + * + * @param wiphy A pointer to the wiphy structure + * @param dev A pointer to the net_device structure + * + * @return 0 -- success, otherwise fail + */ +int +woal_cfg80211_del_virt_if(struct wiphy *wiphy, struct net_device *dev) +{ + int ret = 0; + int i = 0; + moal_private *priv = NULL; + moal_private *vir_priv = NULL; + moal_private *remain_priv = NULL; + moal_handle *handle = (moal_handle *) woal_get_wiphy_priv(wiphy); + + priv = + (moal_private *) woal_get_priv_bss_type(handle, + MLAN_BSS_TYPE_WIFIDIRECT); + for (i = 0; i < priv->phandle->priv_num; i++) { + if ((vir_priv = priv->phandle->priv[i])) { + if (vir_priv->netdev == dev) { + PRINTM(MIOCTL, "Find virtual interface, index=%d\n", i); + break; + } + } + } + if (vir_priv && vir_priv->netdev == dev) { + woal_stop_queue(dev); + netif_carrier_off(dev); + netif_device_detach(dev); + woal_cancel_scan(vir_priv, MOAL_IOCTL_WAIT); + /* cancel previous remain on channel to avoid firmware hang */ + if (priv->phandle->remain_on_channel) { + t_u8 channel_status; + remain_priv = priv->phandle->priv[priv->phandle->remain_bss_index]; + if (remain_priv) { + if (woal_cfg80211_remain_on_channel_cfg + (remain_priv, MOAL_IOCTL_WAIT, MTRUE, &channel_status, NULL, + 0, 0)) + PRINTM(MERROR, + "del_virt_if: Fail to cancel remain on channel\n"); + + if (priv->phandle->cookie) { + cfg80211_remain_on_channel_expired( +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) + remain_priv->netdev, +#else + remain_priv->wdev, +#endif + priv->phandle->cookie, + &priv->phandle->chan, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) + priv->phandle-> + channel_type, +#endif + GFP_ATOMIC); + priv->phandle->cookie = 0; + } + priv->phandle->remain_on_channel = MFALSE; + } + } + + woal_clear_all_mgmt_ies(vir_priv); + woal_cfg80211_deinit_p2p(vir_priv); + woal_bss_remove(vir_priv); + /* Last reference is our one */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) + PRINTM(MINFO, "refcnt = %d\n", atomic_read(&dev->refcnt)); +#else + PRINTM(MINFO, "refcnt = %d\n", netdev_refcnt_read(dev)); +#endif + PRINTM(MINFO, "netdev_finish_unregister: %s\n", dev->name); + /* Clear the priv in handle */ + vir_priv->phandle->priv[vir_priv->bss_index] = NULL; + priv->phandle->priv_num--; + if (dev->reg_state == NETREG_REGISTERED) + unregister_netdevice(dev); + } + return ret; +} + +/** + * @brief This function removes an virtual interface. + * + * @param handle A pointer to the moal_handle structure + * + * @return N/A + */ +void +woal_remove_virtual_interface(moal_handle * handle) { + moal_private *priv = NULL; + int vir_intf = 0; + int i = 0; ENTER(); + rtnl_lock(); + for (i = 0; i < handle->priv_num; i++) { + if ((priv = handle->priv[i])) { + if (priv->bss_virtual) { + PRINTM(MCMND, "Remove virtual interface %s\n", + priv->netdev->name); + netif_device_detach(priv->netdev); + if (priv->netdev->reg_state == NETREG_REGISTERED) + unregister_netdevice(priv->netdev); + handle->priv[i] = NULL; + vir_intf++; + } + } + } + rtnl_unlock(); + handle->priv_num -= vir_intf; LEAVE(); - return 0; +} +#endif +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,37) || defined(COMPAT_WIRELESS) +/** + * @brief Request the driver to add a virtual interface + * + * @param wiphy A pointer to wiphy structure + * @param name Virtual interface name + * @param type Virtual interface type + * @param flags Flags for the virtual interface + * @param params A pointer to vif_params structure + * + * @return A pointer to net_device -- success, otherwise null + */ +struct net_device * +woal_cfg80211_add_virtual_intf(struct wiphy *wiphy, + char *name, enum nl80211_iftype type, + u32 * flags, struct vif_params *params) +#else +/** + * @brief Request the driver to add a virtual interface + * + * @param wiphy A pointer to wiphy structure + * @param name Virtual interface name + * @param type Virtual interface type + * @param flags Flags for the virtual interface + * @param params A pointer to vif_params structure + * + * @return 0 -- success, otherwise fail + */ +int +woal_cfg80211_add_virtual_intf(struct wiphy *wiphy, + char *name, enum nl80211_iftype type, + u32 * flags, struct vif_params *params) +#endif +#else +/** + * @brief Request the driver to add a virtual interface + * + * @param wiphy A pointer to wiphy structure + * @param name Virtual interface name + * @param type Virtual interface type + * @param flags Flags for the virtual interface + * @param params A pointer to vif_params structure + * + * @return A pointer to wireless_dev -- success, otherwise null + */ +struct wireless_dev * +woal_cfg80211_add_virtual_intf(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) + const +#endif + char *name, enum nl80211_iftype type, + u32 * flags, struct vif_params *params) +#endif +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,37) || defined(COMPAT_WIRELESS) + struct net_device *ndev = NULL; +#endif + int ret = 0; + + ENTER(); + PRINTM(MIOCTL, "add virtual intf: %d name: %s\n", type, name); + switch (type) { +#if defined(WIFI_DIRECT_SUPPORT) +#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION + case NL80211_IFTYPE_P2P_CLIENT: + case NL80211_IFTYPE_P2P_GO: + ret = + woal_cfg80211_add_virt_if(wiphy, name, type, flags, params, &ndev); + break; +#endif +#endif + default: + PRINTM(MWARN, "Not supported if type: %d\n", type); + ret = -EFAULT; + break; + } + LEAVE(); +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,37) || defined(COMPAT_WIRELESS) + if (ret) + return NULL; + else + return ndev; +#else + return ret; +#endif +#else + if (ret) + return NULL; + else + return (ndev->ieee80211_ptr); +#endif +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) +/** + * @brief Request the driver to del a virtual interface + * + * @param wiphy A pointer to wiphy structure + * @param dev The pointer to net_device + * + * @return 0 -- success, otherwise fail + */ +int +woal_cfg80211_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev) +#else +/** + * @brief Request the driver to del a virtual interface + * + * @param wiphy A pointer to wiphy structure + * @param wdev The pointer to wireless_dev + * + * @return 0 -- success, otherwise fail + */ +int +woal_cfg80211_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) +#endif +{ + int ret = 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct net_device *dev = wdev->netdev; +#endif + ENTER(); + + PRINTM(MIOCTL, "del virtual intf %s\n", dev->name); + ASSERT_RTNL(); +#if defined(WIFI_DIRECT_SUPPORT) +#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION + ret = woal_cfg80211_del_virt_if(wiphy, dev); +#endif +#endif + LEAVE(); + return ret; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) @@ -748,12 +1101,16 @@ woal_cfg80211_add_beacon(struct wiphy *wiphy, ENTER(); - PRINTM(MIOCTL, "add beacon\n"); + PRINTM(MMSG, "wlan: Starting AP\n"); #ifdef STA_CFG80211 /*** cancel pending scan */ woal_cancel_scan(priv, MOAL_IOCTL_WAIT); #endif if (params != NULL) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) + priv->channel = + ieee80211_frequency_to_channel(params->channel->center_freq); +#endif /* bss config */ if (MLAN_STATUS_SUCCESS != woal_cfg80211_beacon_config(priv, params)) { ret = -EFAULT; @@ -806,6 +1163,41 @@ woal_cfg80211_add_beacon(struct wiphy *wiphy, goto done; } } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) || defined(COMPAT_WIRELESS) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) + if (params->beacon.beacon_ies && params->beacon.beacon_ies_len) { + if (MLAN_STATUS_SUCCESS != woal_cfg80211_mgmt_frame_ie(priv, + params->beacon. + beacon_ies, + params->beacon. + beacon_ies_len, + NULL, 0, NULL, 0, + NULL, 0, + MGMT_MASK_BEACON_WPS_P2P)) + { + PRINTM(MERROR, "Failed to set beacon wps/p2p ie\n"); + ret = -EFAULT; + goto done; + } + } +#else + if (params->beacon_ies && params->beacon_ies_len) { + if (MLAN_STATUS_SUCCESS != woal_cfg80211_mgmt_frame_ie(priv, + params-> + beacon_ies, + params-> + beacon_ies_len, + NULL, 0, NULL, 0, + NULL, 0, + MGMT_MASK_BEACON_WPS_P2P)) + { + PRINTM(MERROR, "Failed to set beacon wps/p2p ie\n"); + ret = -EFAULT; + goto done; + } + } +#endif +#endif /* if the bss is stopped, then start it */ if (priv->bss_started == MFALSE) { @@ -816,6 +1208,7 @@ woal_cfg80211_add_beacon(struct wiphy *wiphy, } } + PRINTM(MMSG, "wlan: AP started\n"); done: LEAVE(); return ret; @@ -868,7 +1261,7 @@ woal_cfg80211_set_beacon(struct wiphy *wiphy, } } #else - if (params->beacon_ies && params->beacon_ies_len) { + if (params->tail && params->tail_len) { if (MLAN_STATUS_SUCCESS != woal_cfg80211_mgmt_frame_ie(priv, params->tail, params->tail_len, NULL, 0, NULL, 0, @@ -877,7 +1270,22 @@ woal_cfg80211_set_beacon(struct wiphy *wiphy, goto done; } } - + if (params->beacon_ies && params->beacon_ies_len) { + if (MLAN_STATUS_SUCCESS != woal_cfg80211_mgmt_frame_ie(priv, + params-> + beacon_ies, + params-> + beacon_ies_len, + NULL, 0, + NULL, 0, + NULL, 0, + MGMT_MASK_BEACON_WPS_P2P)) + { + PRINTM(MERROR, "Failed to set beacon wps/p2p ie\n"); + ret = -EFAULT; + goto done; + } + } if (params->proberesp_ies && params->proberesp_ies_len) { if (MLAN_STATUS_SUCCESS != woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, @@ -888,7 +1296,6 @@ woal_cfg80211_set_beacon(struct wiphy *wiphy, goto done; } } - if (params->assocresp_ies && params->assocresp_ies_len) { if (MLAN_STATUS_SUCCESS != woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL, 0, @@ -920,10 +1327,13 @@ woal_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) { moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); int ret = 0; +#ifdef STA_SUPPORT + moal_private *pmpriv = NULL; +#endif ENTER(); - PRINTM(MIOCTL, "del beacon\n"); + PRINTM(MMSG, "wlan: Stoping AP\n"); /* if the bss is still running, then stop it */ if (priv->bss_started == MTRUE) { if (MLAN_STATUS_SUCCESS != @@ -936,45 +1346,89 @@ woal_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) ret = -EFAULT; goto done; } + /* Set WLAN MAC addresses */ + if (MLAN_STATUS_SUCCESS != woal_request_set_mac_address(priv)) { + PRINTM(MERROR, "Set MAC address failed\n"); + ret = -EFAULT; + goto done; + } } -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) && !defined(COMPAT_WIRELESS) - /* clear BEACON WPS/P2P IE */ - if (MLAN_STATUS_SUCCESS != - woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL, 0, NULL, 0, NULL, 0, - MGMT_MASK_BEACON_WPS_P2P)) { - ret = -EFAULT; - goto done; + woal_clear_all_mgmt_ies(priv); + +#ifdef STA_SUPPORT + if (!woal_is_any_interface_active(priv->phandle)) { + if ((pmpriv = + woal_get_priv((moal_handle *) priv->phandle, MLAN_BSS_ROLE_STA))) { + woal_set_scan_time(pmpriv, ACTIVE_SCAN_CHAN_TIME, + PASSIVE_SCAN_CHAN_TIME, SPECIFIC_SCAN_CHAN_TIME); + } } #endif - /* clear mgmt frame ies */ + + priv->cipher = 0; + priv->key_len = 0; + priv->channel = 0; + PRINTM(MMSG, "wlan: AP stopped\n"); + done: + LEAVE(); + return ret; +} + +/** + * @brief send deauth to station + * + * @param A pointer to moal_private + * @param mac A pointer to station mac address + * + * @return 0 -- success, otherwise fail + */ +static int +woal_deauth_station(moal_private * priv, u8 * mac_addr) +{ + mlan_ioctl_req *ioctl_req = NULL; + mlan_ds_bss *bss = NULL; + int ret = 0; + + ENTER(); + + ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss)); + if (ioctl_req == NULL) { + ret = -ENOMEM; + goto done; + } + bss = (mlan_ds_bss *) ioctl_req->pbuf; + bss->sub_command = MLAN_OID_UAP_DEAUTH_STA; + ioctl_req->req_id = MLAN_IOCTL_BSS; + ioctl_req->action = MLAN_ACT_SET; + + memcpy(bss->param.deauth_param.mac_addr, mac_addr, MLAN_MAC_ADDR_LENGTH); +#define REASON_CODE_DEAUTH_LEAVING 3 + bss->param.deauth_param.reason_code = REASON_CODE_DEAUTH_LEAVING; if (MLAN_STATUS_SUCCESS != - woal_cfg80211_mgmt_frame_ie(priv, NULL, 0, NULL, 0, NULL, 0, NULL, 0, - MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP | - MGMT_MASK_ASSOC_RESP)) { + woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT)) { ret = -EFAULT; goto done; } - priv->cipher = 0; - priv->key_len = 0; done: + if (ioctl_req) + kfree(ioctl_req); LEAVE(); return ret; } /** - * @brief Get station info + * @brief del station * * @param wiphy A pointer to wiphy structure * @param dev A pointer to net_device structure * @param mac A pointer to station mac address - * @param stainfo A pointer to station_info structure * * @return 0 -- success, otherwise fail */ int -woal_uap_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, - u8 * mac, struct station_info *stainfo) +woal_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, + u8 * mac_addr) { moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); int ret = -EFAULT; @@ -986,9 +1440,17 @@ woal_uap_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, if (priv->media_connected == MFALSE) { PRINTM(MINFO, "cfg80211: Media not connected!\n"); LEAVE(); - return -ENOENT; + return 0; } + if (mac_addr) { + PRINTM(MIOCTL, "del station: " MACSTR "\n", MAC2STR(mac_addr)); + ret = woal_deauth_station(priv, mac_addr); + woal_sched_timeout(100); + LEAVE(); + return ret; + } + PRINTM(MIOCTL, "del all station\n"); /* Allocate an IOCTL request buffer */ ioctl_req = (mlan_ioctl_req *) woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info)); @@ -1006,116 +1468,83 @@ woal_uap_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT)) { goto done; } + if (!info->param.sta_list.sta_count) + goto done; for (i = 0; i < info->param.sta_list.sta_count; i++) { - if (!memcmp(info->param.sta_list.info[i].mac_address, mac, ETH_ALEN)) { - PRINTM(MIOCTL, - "Get station: %02x:%02x:%02x:%02x:%02x:%02x RSSI=%d\n", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], - (int) info->param.sta_list.info[i].rssi); - stainfo->filled = STATION_INFO_INACTIVE_TIME | STATION_INFO_SIGNAL; - stainfo->inactive_time = 0; - stainfo->signal = info->param.sta_list.info[i].rssi; - ret = 0; - break; - } + PRINTM(MIOCTL, "deauth station " MACSTR "\n", + MAC2STR(info->param.sta_list.info[i].mac_address)); + ret = + woal_deauth_station(priv, info->param.sta_list.info[i].mac_address); } + woal_sched_timeout(100); done: if (ioctl_req) kfree(ioctl_req); LEAVE(); return ret; + } /** - * @brief Initialize the uAP wiphy + * @brief Get station info * - * @param priv A pointer to moal_private structure - * @param wait_option Wait option + * @param wiphy A pointer to wiphy structure + * @param dev A pointer to net_device structure + * @param mac A pointer to station mac address + * @param stainfo A pointer to station_info structure * - * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE + * @return 0 -- success, otherwise fail */ -mlan_status -woal_cfg80211_uap_init_wiphy(moal_private * priv, t_u8 wait_option) +int +woal_uap_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, + u8 * mac, struct station_info *stainfo) { - struct wiphy *wiphy; - mlan_uap_bss_param ap_cfg; - mlan_ioctl_req *req = NULL; - mlan_ds_11n_cfg *cfg_11n = NULL; - t_u32 hw_dev_cap; + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); + int ret = -EFAULT; + int i = 0; + mlan_ds_get_info *info = NULL; + mlan_ioctl_req *ioctl_req = NULL; ENTER(); - - if (priv->wdev) - wiphy = priv->wdev->wiphy; - else { - PRINTM(MERROR, "Invalid parameter when init wiphy.\n"); - LEAVE(); - return MLAN_STATUS_FAILURE; - } - if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, - MLAN_ACT_GET, - wait_option, &ap_cfg)) { - LEAVE(); - return MLAN_STATUS_FAILURE; - } - - /* Get 11n tx parameters from MLAN */ - req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg)); - if (req == NULL) { + if (priv->media_connected == MFALSE) { + PRINTM(MINFO, "cfg80211: Media not connected!\n"); LEAVE(); - return MLAN_STATUS_FAILURE; + return -ENOENT; } - cfg_11n = (mlan_ds_11n_cfg *) req->pbuf; - cfg_11n->sub_command = MLAN_OID_11N_HTCAP_CFG; - req->req_id = MLAN_IOCTL_11N_CFG; - req->action = MLAN_ACT_GET; - cfg_11n->param.htcap_cfg.hw_cap_req = MTRUE; - if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, wait_option)) { - kfree(req); - LEAVE(); - return MLAN_STATUS_FAILURE; + /* Allocate an IOCTL request buffer */ + ioctl_req = + (mlan_ioctl_req *) woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_get_info)); + if (ioctl_req == NULL) { + ret = -ENOMEM; + goto done; } - hw_dev_cap = cfg_11n->param.htcap_cfg.htcap; - /* Get supported MCS sets */ - memset(req->pbuf, 0, sizeof(mlan_ds_11n_cfg)); - cfg_11n->sub_command = MLAN_OID_11N_CFG_SUPPORTED_MCS_SET; - req->req_id = MLAN_IOCTL_11N_CFG; - req->action = MLAN_ACT_GET; + info = (mlan_ds_get_info *) ioctl_req->pbuf; + info->sub_command = MLAN_OID_UAP_STA_LIST; + ioctl_req->req_id = MLAN_IOCTL_GET_INFO; + ioctl_req->action = MLAN_ACT_GET; - if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, wait_option)) { - kfree(req); - LEAVE(); - return MLAN_STATUS_FAILURE; + if (MLAN_STATUS_SUCCESS != + woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT)) { + goto done; } - - /* Initialize parameters for 2GHz and 5GHz bands */ - woal_cfg80211_setup_ht_cap(&wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, - hw_dev_cap, cfg_11n->param.supported_mcs_set); - /* For 2.4G band only card, this shouldn't be set */ - if (wiphy->bands[IEEE80211_BAND_5GHZ]) - woal_cfg80211_setup_ht_cap(&wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, - hw_dev_cap, - cfg_11n->param.supported_mcs_set); - if (req) - kfree(req); - - /* Set retry limit count to wiphy */ - wiphy->retry_long = (t_u8) ap_cfg.retry_limit; - wiphy->retry_short = (t_u8) ap_cfg.retry_limit; - wiphy->max_scan_ie_len = MAX_IE_SIZE; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) || defined(COMPAT_WIRELESS) - wiphy->mgmt_stypes = ieee80211_uap_mgmt_stypes; -#endif - /* Set RTS threshold to wiphy */ - wiphy->rts_threshold = (t_u32) ap_cfg.rts_threshold; - - /* Set fragment threshold to wiphy */ - wiphy->frag_threshold = (t_u32) ap_cfg.frag_threshold; - + for (i = 0; i < info->param.sta_list.sta_count; i++) { + if (!memcmp(info->param.sta_list.info[i].mac_address, mac, ETH_ALEN)) { + PRINTM(MIOCTL, "Get station: " MACSTR " RSSI=%d\n", MAC2STR(mac), + (int) info->param.sta_list.info[i].rssi); + stainfo->filled = STATION_INFO_INACTIVE_TIME | STATION_INFO_SIGNAL; + stainfo->inactive_time = 0; + stainfo->signal = info->param.sta_list.info[i].rssi; + ret = 0; + break; + } + } + done: + if (ioctl_req) + kfree(ioctl_req); LEAVE(); - return MLAN_STATUS_SUCCESS; + return ret; } /** @@ -1131,91 +1560,26 @@ woal_register_uap_cfg80211(struct net_device * dev, t_u8 bss_type) { mlan_status ret = MLAN_STATUS_SUCCESS; moal_private *priv = (moal_private *) netdev_priv(dev); - void *wdev_priv = NULL; struct wireless_dev *wdev = NULL; - mlan_fw_info fw_info; ENTER(); - /* Allocate wireless device */ - wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); - if (!wdev) { - PRINTM(MERROR, "Could not allocate wireless device\n"); - ret = MLAN_STATUS_FAILURE; - goto err_wdev; - } + wdev = (struct wireless_dev *) &priv->w_dev; + memset(wdev, 0, sizeof(struct wireless_dev)); - /* Allocate wiphy */ - wdev->wiphy = wiphy_new(&woal_cfg80211_uap_ops, sizeof(moal_private *)); + wdev->wiphy = priv->phandle->wiphy; if (!wdev->wiphy) { - PRINTM(MERROR, "Could not allocate wiphy device\n"); - ret = MLAN_STATUS_FAILURE; - goto err_wdev; + LEAVE(); + return MLAN_STATUS_FAILURE; } - if (bss_type == MLAN_BSS_TYPE_UAP) { - dev_set_name(&wdev->wiphy->dev, dev->name); + if (bss_type == MLAN_BSS_TYPE_UAP) wdev->iftype = NL80211_IFTYPE_AP; - wdev->wiphy->interface_modes = - MBIT(NL80211_IFTYPE_AP) | MBIT(NL80211_IFTYPE_STATION) | 0; - wdev->wiphy->max_scan_ssids = 10; - } - - /* Make this wiphy known to this driver only */ - wdev->wiphy->privid = mrvl_wiphy_privid; - - /* Supported bands */ - wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &cfg80211_band_2ghz; - if (MLAN_STATUS_SUCCESS == - woal_request_get_fw_info(priv, MOAL_CMD_WAIT, &fw_info)) { - if (fw_info.fw_bands & BAND_A) - wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &cfg80211_band_5ghz; - } - - /* Initialize cipher suits */ - wdev->wiphy->cipher_suites = cfg80211_cipher_suites; - wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cfg80211_cipher_suites); - - wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; - - /* We are using custom domains */ - wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; - - wdev->wiphy->reg_notifier = NULL; // TODO: woal_cfg80211_reg_notifier; - - /* Set moal_private pointer in wiphy_priv */ - wdev_priv = wiphy_priv(wdev->wiphy); - - *(unsigned long *) wdev_priv = (unsigned long) priv; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) || defined(COMPAT_WIRELESS) - set_wiphy_dev(wdev->wiphy, (struct device *) priv->phandle->hotplug_device); -#endif - - if (wiphy_register(wdev->wiphy) < 0) { - PRINTM(MERROR, "Wiphy device registration failed!\n"); - ret = MLAN_STATUS_FAILURE; - goto err_wdev; - } dev_net_set(dev, wiphy_net(wdev->wiphy)); dev->ieee80211_ptr = wdev; SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy)); priv->wdev = wdev; - if (ret != MLAN_STATUS_SUCCESS) { - PRINTM(MERROR, "Wiphy device registration failed!\n"); - } else { - PRINTM(MINFO, "Successfully registered wiphy device\n"); - LEAVE(); - return ret; - } - - wiphy_unregister(wdev->wiphy); - err_wdev: - dev->ieee80211_ptr = NULL; - if (wdev && wdev->wiphy) - wiphy_free(wdev->wiphy); - kfree(wdev); LEAVE(); return ret; } diff --git a/drivers/net/wireless/sd8797/mlinux/moal_uap_cfg80211.h b/drivers/net/wireless/sd8797/mlinux/moal_uap_cfg80211.h index 74c6f1a4e59b..9af1030367e0 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_uap_cfg80211.h +++ b/drivers/net/wireless/sd8797/mlinux/moal_uap_cfg80211.h @@ -25,6 +25,5 @@ #include "moal_uap.h" mlan_status woal_register_uap_cfg80211(struct net_device *dev, t_u8 bss_type); -mlan_status woal_cfg80211_uap_init_wiphy(moal_private * priv, t_u8 wait_option); #endif /* _MOAL_UAP_CFG80211_H_ */ diff --git a/drivers/net/wireless/sd8797/mlinux/moal_uap_wext.c b/drivers/net/wireless/sd8797/mlinux/moal_uap_wext.c index 96322fc39522..a4f0e53bc063 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_uap_wext.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_uap_wext.c @@ -255,10 +255,8 @@ woal_set_wap(struct net_device *dev, struct iw_request_info *info, goto done; } - PRINTM(MINFO, "ASSOC: WAP: uAP bss : %02x:%02x:%02x:%02x:%02x:%02x\n", - (t_u8) awrq->sa_data[0], (t_u8) awrq->sa_data[1], - (t_u8) awrq->sa_data[2], (t_u8) awrq->sa_data[3], - (t_u8) awrq->sa_data[4], (t_u8) awrq->sa_data[5]); + PRINTM(MINFO, "ASSOC: WAP: uAP bss : " MACSTR "\n", + MAC2STR((t_u8 *) awrq->sa_data)); /* * Using this ioctl to start/stop the BSS, return if bss @@ -481,7 +479,7 @@ woal_set_encode(struct net_device *dev, struct iw_request_info *info, /* Check index */ key_index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - if (key_index > 3) { + if ((key_index > 3) || (key_index < 0)) { PRINTM(MERROR, "Key index #%d out of range\n", key_index); ret = -EINVAL; goto done; @@ -516,16 +514,14 @@ woal_set_encode(struct net_device *dev, struct iw_request_info *info, sys_cfg->wep_cfg.key2.key_index = 2; sys_cfg->wep_cfg.key3.key_index = 3; - if (key_index >= 0 && key_index <= 3) { - if (key_index == 0) - pkey = &sys_cfg->wep_cfg.key0; - else if (key_index == 1) - pkey = &sys_cfg->wep_cfg.key1; - else if (key_index == 2) - pkey = &sys_cfg->wep_cfg.key2; - else if (key_index == 3) - pkey = &sys_cfg->wep_cfg.key3; - } + if (key_index == 0) + pkey = &sys_cfg->wep_cfg.key0; + else if (key_index == 1) + pkey = &sys_cfg->wep_cfg.key1; + else if (key_index == 2) + pkey = &sys_cfg->wep_cfg.key2; + else if (key_index == 3) + pkey = &sys_cfg->wep_cfg.key3; if (!(dwrq->flags & IW_ENCODE_NOKEY) && dwrq->length) { if (dwrq->length > MAX_WEP_KEY_SIZE) { @@ -533,18 +529,6 @@ woal_set_encode(struct net_device *dev, struct iw_request_info *info, ret = -E2BIG; goto done; } - if (key_index < 0) { - /* Get current default key index */ - if (ap_cfg->wep_cfg.key0.is_default) - pkey = &sys_cfg->wep_cfg.key0; - if (ap_cfg->wep_cfg.key1.is_default) - pkey = &sys_cfg->wep_cfg.key1; - if (ap_cfg->wep_cfg.key2.is_default) - pkey = &sys_cfg->wep_cfg.key2; - if (ap_cfg->wep_cfg.key3.is_default) - pkey = &sys_cfg->wep_cfg.key3; - } - sys_cfg->protocol = PROTOCOL_STATIC_WEP; memcpy(pkey->key, extra, dwrq->length); /* Set the length */ @@ -881,7 +865,7 @@ woal_set_encode_ext(struct net_device *dev, ENTER(); key_index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - if (key_index < 0 || key_index > 3) { + if (key_index < 0 || key_index > 5) { ret = -EINVAL; goto done; } @@ -915,10 +899,12 @@ woal_set_encode_ext(struct net_device *dev, pwep_key = &sys_cfg.wep_cfg.key3; break; } - pwep_key->key_index = key_index; - pwep_key->is_default = MTRUE; - pwep_key->length = ext->key_len; - memcpy(pwep_key->key, pkey_material, ext->key_len); + if (pwep_key) { + pwep_key->key_index = key_index; + pwep_key->is_default = MTRUE; + pwep_key->length = ext->key_len; + memcpy(pwep_key->key, pkey_material, ext->key_len); + } } else { /* Set GTK/PTK key */ req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg)); @@ -949,16 +935,14 @@ woal_set_encode_ext(struct net_device *dev, SEQ_MAX_SIZE); } PRINTM(MIOCTL, - "set uap wpa key key_index=%d, key_len=%d key_flags=0x%x %02x:%02x:%02x:%02x:%02x:%02x\n", - key_index, ext->key_len, sec->param.encrypt_key.key_flags, - sec->param.encrypt_key.mac_addr[0], - sec->param.encrypt_key.mac_addr[1], - sec->param.encrypt_key.mac_addr[2], - sec->param.encrypt_key.mac_addr[3], - sec->param.encrypt_key.mac_addr[4], - sec->param.encrypt_key.mac_addr[5]); + "set uap wpa key key_index=%d, key_len=%d key_flags=0x%x " MACSTR + "\n", key_index, ext->key_len, sec->param.encrypt_key.key_flags, + MAC2STR(sec->param.encrypt_key.mac_addr)); DBG_HEXDUMP(MCMD_D, "uap wpa key", pkey_material, ext->key_len); +#define IW_ENCODE_ALG_AES_CMAC 5 + if (ext->alg == IW_ENCODE_ALG_AES_CMAC) + sec->param.encrypt_key.key_flags |= KEY_FLAG_AES_MCAST_IGTK; if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { ret = -EFAULT; @@ -1033,9 +1017,8 @@ woal_set_mlme(struct net_device *dev, memset(sta_addr, 0, ETH_ALEN); if ((mlme->cmd == IW_MLME_DEAUTH) || (mlme->cmd == IW_MLME_DISASSOC)) { memcpy(sta_addr, (t_u8 *) mlme->addr.sa_data, ETH_ALEN); - PRINTM(MIOCTL, "Deauth station: %02x:%02x:%02x:%02x:%02x:%02x, " - "reason=%d\n", sta_addr[0], sta_addr[1], sta_addr[2], - sta_addr[3], sta_addr[4], sta_addr[5], mlme->reason_code); + PRINTM(MIOCTL, "Deauth station: " MACSTR ", " + "reason=%d\n", MAC2STR(sta_addr), mlme->reason_code); /* FIXME: For flushing all stations we need to use zero MAC, but right now the FW does not support this. So, manually delete each one @@ -1073,8 +1056,8 @@ woal_set_mlme(struct net_device *dev, } req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss)); if (req == NULL) { - LEAVE(); - return -ENOMEM; + ret = -ENOMEM; + goto done; } bss = (mlan_ds_bss *) req->pbuf; bss->sub_command = MLAN_OID_UAP_DEAUTH_STA; diff --git a/drivers/net/wireless/sd8797/mlinux/moal_wext.c b/drivers/net/wireless/sd8797/mlinux/moal_wext.c index f327c53a9506..073639625f28 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_wext.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_wext.c @@ -42,7 +42,7 @@ Change log: /******************************************************** Global Variables ********************************************************/ - +extern int hw_test; /******************************************************** Local Functions ********************************************************/ @@ -321,9 +321,9 @@ woal_get_freq(struct net_device *dev, struct iw_request_info *info, ret = -EFAULT; goto done; } - fwrq->m = (long) bss->param.bss_chan.freq * 100000; + fwrq->m = (long) bss->param.bss_chan.freq; fwrq->i = (long) bss->param.bss_chan.channel; - fwrq->e = 1; + fwrq->e = 6; fwrq->flags = IW_FREQ_FIXED; done: if (req) @@ -456,10 +456,8 @@ woal_set_wap(struct net_device *dev, struct iw_request_info *info, goto done; } - PRINTM(MINFO, "ASSOC: WAP: sa_data: %02x:%02x:%02x:%02x:%02x:%02x\n", - (t_u8) awrq->sa_data[0], (t_u8) awrq->sa_data[1], - (t_u8) awrq->sa_data[2], (t_u8) awrq->sa_data[3], - (t_u8) awrq->sa_data[4], (t_u8) awrq->sa_data[5]); + PRINTM(MINFO, "ASSOC: WAP: sa_data: " MACSTR "\n", + MAC2STR((t_u8 *) awrq->sa_data)); if (MLAN_STATUS_SUCCESS != woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info)) { @@ -485,8 +483,6 @@ woal_set_wap(struct net_device *dev, struct iw_request_info *info, if (bss_info.media_connected == MTRUE) { if (!memcmp(awrq->sa_data, &bss_info.bssid, ETH_ALEN)) goto done; - /* disconnect before try to assoicate to the new AP */ - woal_disconnect(priv, MOAL_IOCTL_WAIT, NULL); } memcpy(&ssid_bssid.bssid, awrq->sa_data, ETH_ALEN); } @@ -698,6 +694,11 @@ woal_set_power(struct net_device *dev, struct iw_request_info *info, ENTER(); + if (hw_test) { + PRINTM(MIOCTL, "block set power in hw_test mode\n"); + LEAVE(); + return ret; + } disabled = vwrq->disabled; if (MLAN_STATUS_SUCCESS != woal_set_get_power_mgmt(priv, @@ -1409,14 +1410,9 @@ woal_set_encode_ext(struct net_device *dev, sec->param.encrypt_key.key_remove = MTRUE; sec->param.encrypt_key.key_index = key_index; sec->param.encrypt_key.key_flags = KEY_FLAG_REMOVE_KEY; - PRINTM(MIOCTL, - "Remove key key_index=%d, dwrq->flags=0x%x %02x:%02x:%02x:%02x:%02x:%02x\n", - key_index, dwrq->flags, sec->param.encrypt_key.mac_addr[0], - sec->param.encrypt_key.mac_addr[1], - sec->param.encrypt_key.mac_addr[2], - sec->param.encrypt_key.mac_addr[3], - sec->param.encrypt_key.mac_addr[4], - sec->param.encrypt_key.mac_addr[5]); + PRINTM(MIOCTL, "Remove key key_index=%d, dwrq->flags=0x%x " MACSTR "\n", + key_index, dwrq->flags, + MAC2STR(sec->param.encrypt_key.mac_addr)); } else if (ext->key_len <= MAX_WEP_KEY_SIZE) { /* Set WEP key */ sec->param.encrypt_key.key_index = key_index; @@ -1444,14 +1440,9 @@ woal_set_encode_ext(struct net_device *dev, memcpy(sec->param.encrypt_key.key_material, pkey_material, ext->key_len); PRINTM(MIOCTL, - "set wpa key key_index=%d, key_len=%d key_flags=0x%x %02x:%02x:%02x:%02x:%02x:%02x\n", - key_index, ext->key_len, sec->param.encrypt_key.key_flags, - sec->param.encrypt_key.mac_addr[0], - sec->param.encrypt_key.mac_addr[1], - sec->param.encrypt_key.mac_addr[2], - sec->param.encrypt_key.mac_addr[3], - sec->param.encrypt_key.mac_addr[4], - sec->param.encrypt_key.mac_addr[5]); + "set wpa key key_index=%d, key_len=%d key_flags=0x%x " MACSTR + "\n", key_index, ext->key_len, sec->param.encrypt_key.key_flags, + MAC2STR(sec->param.encrypt_key.mac_addr)); DBG_HEXDUMP(MCMD_D, "wpa key", pkey_material, ext->key_len); #define IW_ENCODE_ALG_AES_CMAC 5 if (ext->alg == IW_ENCODE_ALG_AES_CMAC) @@ -1979,7 +1970,8 @@ woal_set_priv(struct net_device *dev, struct iw_request_info *info, PRINTM(MIOCTL, "SIOCSIWPRIV requst = %s\n", buf); if (strncmp(buf, "RSSILOW-THRESHOLD", strlen("RSSILOW-THRESHOLD")) == 0) { pdata = buf + strlen("RSSILOW-THRESHOLD") + 1; - if (MLAN_STATUS_SUCCESS != woal_set_rssi_low_threshold(priv, pdata)) { + if (MLAN_STATUS_SUCCESS != + woal_set_rssi_low_threshold(priv, pdata, MOAL_IOCTL_WAIT)) { ret = -EFAULT; goto done; } @@ -2045,9 +2037,11 @@ woal_set_priv(struct net_device *dev, struct iw_request_info *info, len = sprintf(buf, "OK\n") + 1; } else if (strncmp(buf, "POWERMODE", strlen("POWERMODE")) == 0) { pdata = buf + strlen("POWERMODE") + 1; - if (MLAN_STATUS_SUCCESS != woal_set_powermode(priv, pdata)) { - ret = -EFAULT; - goto done; + if (!hw_test) { + if (MLAN_STATUS_SUCCESS != woal_set_powermode(priv, pdata)) { + ret = -EFAULT; + goto done; + } } len = sprintf(buf, "OK\n") + 1; } else if (strncmp(buf, "COUNTRY", strlen("COUNTRY")) == 0) { @@ -2106,7 +2100,7 @@ woal_set_priv(struct net_device *dev, struct iw_request_info *info, len = sprintf(buf, "OK\n") + 1; } else if (strncmp(buf, "BGSCAN-STOP", strlen("BGSCAN-STOP")) == 0) { if (priv->bg_scan_start && !priv->scan_cfg.rssi_threshold) { - if (MLAN_STATUS_SUCCESS != woal_stop_bg_scan(priv)) { + if (MLAN_STATUS_SUCCESS != woal_stop_bg_scan(priv, MOAL_IOCTL_WAIT)) { ret = -EFAULT; goto done; } @@ -2144,7 +2138,7 @@ woal_set_priv(struct net_device *dev, struct iw_request_info *info, len = sprintf(buf, "OK\n") + 1; } else if (strncmp(buf, "QOSINFO", strlen("QOSINFO")) == 0) { pdata = buf + strlen("QOSINFO") + 1; - if (MLAN_STATUS_SUCCESS != woal_set_qos_cfg(priv, pdata)) { + if (MLAN_STATUS_SUCCESS != woal_priv_qos_cfg(priv, MLAN_ACT_SET, pdata)) { ret = -EFAULT; goto done; } @@ -2334,6 +2328,10 @@ woal_set_essid(struct net_device *dev, struct iw_request_info *info, PRINTM(MINFO, "Requested new SSID = %s\n", (char *) req_ssid.ssid); memcpy(&ssid_bssid.ssid, &req_ssid, sizeof(mlan_802_11_ssid)); + if (MTRUE == woal_is_connected(priv, &ssid_bssid)) { + PRINTM(MIOCTL, "Already connect to the network\n"); + goto setessid_ret; + } if (dwrq->flags != 0xFFFF) { if (MLAN_STATUS_SUCCESS != woal_find_essid(priv, &ssid_bssid)) { @@ -2348,9 +2346,10 @@ woal_set_essid(struct net_device *dev, struct iw_request_info *info, } - /* disconnect before try to associate */ - woal_disconnect(priv, MOAL_IOCTL_WAIT, NULL); mode = woal_get_mode(priv, MOAL_IOCTL_WAIT); + if (mode == IW_MODE_ADHOC) + /* disconnect before try to associate */ + woal_disconnect(priv, MOAL_IOCTL_WAIT, NULL); if (mode != IW_MODE_ADHOC) { if (MLAN_STATUS_SUCCESS != @@ -2523,7 +2522,7 @@ woal_get_scan(struct net_device *dev, struct iw_request_info *info, break; } if (!scan_table[i].freq) { - PRINTM(MERROR, "Invalid channel number %d\n", + PRINTM(MWARN, "Invalid channel number %d\n", (int) scan_table[i].channel); continue; } @@ -2555,7 +2554,7 @@ woal_get_scan(struct net_device *dev, struct iw_request_info *info, iwe.len = IW_EV_POINT_LEN + iwe.u.data.length; current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, - (t_s8 *) scan_table[i].ssid.ssid); + (char *) scan_table[i].ssid.ssid); /* Add mode */ iwe.cmd = SIOCGIWMODE; @@ -2572,8 +2571,8 @@ woal_get_scan(struct net_device *dev, struct iw_request_info *info, /* Frequency */ iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = (long) scan_table[i].freq * 100000; - iwe.u.freq.e = 1; + iwe.u.freq.m = (long) scan_table[i].freq; + iwe.u.freq.e = 6; iwe.u.freq.flags = IW_FREQ_FIXED; iwe.len = IW_EV_FREQ_LEN; current_ev = @@ -2865,7 +2864,7 @@ static const iw_handler woal_private_handler[] = { * @return N/A */ void -woal_send_iwevcustom_event(moal_private * priv, t_s8 * str) +woal_send_iwevcustom_event(moal_private * priv, char *str) { union iwreq_data iwrq; char buf[IW_CUSTOM_MAX]; @@ -3009,10 +3008,12 @@ woal_get_wireless_stats(struct net_device *dev) /* Send RSSI command to get beacon RSSI/NF, valid only if associated */ if (priv->media_connected == MTRUE) { - woal_get_signal_info(priv, wait_option, NULL); - priv->w_stats.qual.qual = woal_rssi_to_quality((t_s16) - (priv->w_stats.qual. - level - 0x100)); + if (MLAN_STATUS_SUCCESS == + woal_get_signal_info(priv, wait_option, NULL)) { + priv->w_stats.qual.qual = + woal_rssi_to_quality((t_s16) + (priv->w_stats.qual.level - 0x100)); + } } #if WIRELESS_EXT > 18 priv->w_stats.qual.updated |= (IW_QUAL_ALL_UPDATED | IW_QUAL_DBM); diff --git a/drivers/net/wireless/sd8797/mlinux/moal_wext.h b/drivers/net/wireless/sd8797/mlinux/moal_wext.h index cf1ebc4beccf..5a69c25eeb5e 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_wext.h +++ b/drivers/net/wireless/sd8797/mlinux/moal_wext.h @@ -27,70 +27,6 @@ Change log: #ifndef _WOAL_WEXT_H_ #define _WOAL_WEXT_H_ -/** Custom event : AdHoc link sensed */ -#define CUS_EVT_ADHOC_LINK_SENSED "EVENT=ADHOC_LINK_SENSED" -/** Custom event : AdHoc link lost */ -#define CUS_EVT_ADHOC_LINK_LOST "EVENT=ADHOC_LINK_LOST" -/** Custom event : MIC failure, unicast */ -#define CUS_EVT_MLME_MIC_ERR_UNI "MLME-MICHAELMICFAILURE.indication unicast " -/** Custom event : MIC failure, multicast */ -#define CUS_EVT_MLME_MIC_ERR_MUL "MLME-MICHAELMICFAILURE.indication multicast " -/** Custom event : Beacon RSSI low */ -#define CUS_EVT_BEACON_RSSI_LOW "EVENT=BEACON_RSSI_LOW" -/** Custom event : Beacon SNR low */ -#define CUS_EVT_BEACON_SNR_LOW "EVENT=BEACON_SNR_LOW" -/** Custom event : Beacon RSSI high */ -#define CUS_EVT_BEACON_RSSI_HIGH "EVENT=BEACON_RSSI_HIGH" -/** Custom event : Beacon SNR high */ -#define CUS_EVT_BEACON_SNR_HIGH "EVENT=BEACON_SNR_HIGH" -/** Custom event : Max fail */ -#define CUS_EVT_MAX_FAIL "EVENT=MAX_FAIL" -/** Custom event : Data RSSI low */ -#define CUS_EVT_DATA_RSSI_LOW "EVENT=DATA_RSSI_LOW" -/** Custom event : Data SNR low */ -#define CUS_EVT_DATA_SNR_LOW "EVENT=DATA_SNR_LOW" -/** Custom event : Data RSSI high */ -#define CUS_EVT_DATA_RSSI_HIGH "EVENT=DATA_RSSI_HIGH" -/** Custom event : Data SNR high */ -#define CUS_EVT_DATA_SNR_HIGH "EVENT=DATA_SNR_HIGH" -/** Custom event : Link Quality */ -#define CUS_EVT_LINK_QUALITY "EVENT=LINK_QUALITY" -/** Custom event : Port Release */ -#define CUS_EVT_PORT_RELEASE "EVENT=PORT_RELEASE" -/** Custom event : Pre-Beacon Lost */ -#define CUS_EVT_PRE_BEACON_LOST "EVENT=PRE_BEACON_LOST" - -/** Custom event : Deep Sleep awake */ -#define CUS_EVT_DEEP_SLEEP_AWAKE "EVENT=DS_AWAKE" - -/** Custom event : Host Sleep activated */ -#define CUS_EVT_HS_ACTIVATED "HS_ACTIVATED " -/** Custom event : Host Sleep deactivated */ -#define CUS_EVT_HS_DEACTIVATED "HS_DEACTIVATED " -/** Custom event : Host Sleep wakeup */ -#define CUS_EVT_HS_WAKEUP "HS_WAKEUP" - -/** Custom event : WEP ICV error */ -#define CUS_EVT_WEP_ICV_ERR "EVENT=WEP_ICV_ERR" - -/** Custom event : Channel Switch Announcment */ -#define CUS_EVT_CHANNEL_SWITCH_ANN "EVENT=CHANNEL_SWITCH_ANN" - -/** Custom event : BW changed */ -#define CUS_EVT_BW_CHANGED "EVENT=BW_CHANGED" -/** Custom event : OBSS scan parameter */ -#define CUS_EVT_OBSS_SCAN_PARAM "EVENT=OBSS_SCAN_PARAM" -/** Custom indiciation message sent to the application layer for WMM changes */ -#define WMM_CONFIG_CHANGE_INDICATION "WMM_CONFIG_CHANGE.indication" - -#ifdef UAP_SUPPORT -#ifdef UAP_WEXT -/** Custom event : STA connected */ -#define CUS_EVT_STA_CONNECTED "EVENT=STA_CONNECTED" -/** Custom event : STA disconnected */ -#define CUS_EVT_STA_DISCONNECTED "EVENT=STA_DISCONNECTED" -#endif -#endif /** NF value for default scan */ #define MRVDRV_NF_DEFAULT_SCAN_VALUE (-96) |