From 2b8a795846f0501dff448d6aa090ca6292bd6a27 Mon Sep 17 00:00:00 2001 From: Alex Zhao Date: Wed, 11 Dec 2019 14:34:37 +0800 Subject: [PATCH] net: wireless: update bcmdhd driver to 1.579.77.41.22 Change-Id: Ib5df542df130214999a3c2d4361c265fa8bcc39f Signed-off-by: Alex Zhao --- .../rockchip_wlan/rkwifi/bcmdhd/Makefile | 52 +- .../rockchip_wlan/rkwifi/bcmdhd/bcmevent.c | 7 + .../rkwifi/bcmdhd/bcmsdh_linux.c | 6 +- .../rkwifi/bcmdhd/bcmsdh_sdmmc.c | 67 +- .../rockchip_wlan/rkwifi/bcmdhd/bcmutils.c | 2 +- .../rockchip_wlan/rkwifi/bcmdhd/dbus.c | 37 +- .../rockchip_wlan/rkwifi/bcmdhd/dhd.h | 26 +- .../rockchip_wlan/rkwifi/bcmdhd/dhd_cdc.c | 6 +- .../rkwifi/bcmdhd/dhd_cfg80211.c | 2 - .../rockchip_wlan/rkwifi/bcmdhd/dhd_common.c | 147 +- .../rockchip_wlan/rkwifi/bcmdhd/dhd_config.c | 2039 +++++--- .../rockchip_wlan/rkwifi/bcmdhd/dhd_config.h | 144 +- .../rockchip_wlan/rkwifi/bcmdhd/dhd_debug.c | 6 +- .../rockchip_wlan/rkwifi/bcmdhd/dhd_gpio.c | 7 +- .../rockchip_wlan/rkwifi/bcmdhd/dhd_ip.c | 22 +- .../rockchip_wlan/rkwifi/bcmdhd/dhd_linux.c | 536 ++- .../rockchip_wlan/rkwifi/bcmdhd/dhd_linux.h | 4 +- .../rkwifi/bcmdhd/dhd_linux_platdev.c | 13 +- .../rockchip_wlan/rkwifi/bcmdhd/dhd_msgbuf.c | 5 +- .../rockchip_wlan/rkwifi/bcmdhd/dhd_pcie.c | 35 +- .../rkwifi/bcmdhd/dhd_pcie_linux.c | 22 +- .../rockchip_wlan/rkwifi/bcmdhd/dhd_pno.c | 14 +- .../rockchip_wlan/rkwifi/bcmdhd/dhd_rtt.c | 4 +- .../rockchip_wlan/rkwifi/bcmdhd/dhd_sdio.c | 140 +- .../rkwifi/bcmdhd/dhd_static_buf.c | 20 +- .../rkwifi/bcmdhd/include/802.11.h | 13 + .../rkwifi/bcmdhd/include/bcmip.h | 15 + .../rkwifi/bcmdhd/include/bcmsdpcm.h | 1 + .../rkwifi/bcmdhd/include/brcm_nl80211.h | 10 +- .../rkwifi/bcmdhd/include/dhdioctl.h | 6 + .../rkwifi/bcmdhd/include/epivers.h | 2 +- .../rkwifi/bcmdhd/include/linux_osl.h | 8 + .../rkwifi/bcmdhd/include/linuxver.h | 37 + .../rkwifi/bcmdhd/include/wlioctl.h | 22 +- .../rkwifi/bcmdhd/include/wlioctl_defs.h | 34 +- .../rockchip_wlan/rkwifi/bcmdhd/include/wpa.h | 30 + .../rockchip_wlan/rkwifi/bcmdhd/linux_osl.c | 58 +- .../rockchip_wlan/rkwifi/bcmdhd/wl_android.c | 252 +- .../rockchip_wlan/rkwifi/bcmdhd/wl_android.h | 94 +- .../rkwifi/bcmdhd/wl_android_ext.c | 4244 ++++++++++++----- .../rockchip_wlan/rkwifi/bcmdhd/wl_cfg80211.c | 1022 +++- .../rockchip_wlan/rkwifi/bcmdhd/wl_cfg80211.h | 163 +- .../rkwifi/bcmdhd/wl_cfg_btcoex.c | 25 +- .../rockchip_wlan/rkwifi/bcmdhd/wl_cfgp2p.c | 18 +- .../rockchip_wlan/rkwifi/bcmdhd/wl_cfgp2p.h | 29 +- .../rkwifi/bcmdhd/wl_cfgvendor.c | 90 +- .../rkwifi/bcmdhd/wl_cfgvendor.h | 75 +- .../rockchip_wlan/rkwifi/bcmdhd/wl_escan.c | 1221 ++--- .../rockchip_wlan/rkwifi/bcmdhd/wl_escan.h | 89 +- .../rockchip_wlan/rkwifi/bcmdhd/wl_event.c | 504 ++ .../rockchip_wlan/rkwifi/bcmdhd/wl_iw.c | 904 ++-- .../rockchip_wlan/rkwifi/bcmdhd/wl_iw.h | 18 +- .../rkwifi/bcmdhd/wldev_common.c | 20 +- 53 files changed, 8629 insertions(+), 3738 deletions(-) create mode 100644 drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_event.c diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile index aa5e43119fd7..6ef3dfd8b1db 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Makefile @@ -1,13 +1,13 @@ # SPDX-License-Identifier: GPL-2.0 # bcmdhd -# 1. WL_IFACE_COMB_NUM_CHANNELS must be added if Android version is 4.4 with Kernel version 3.0~3.4, -# otherwise please remove it. MODULE_NAME = bcmdhd CONFIG_BCMDHD_SDIO := y #CONFIG_BCMDHD_PCIE := y #CONFIG_BCMDHD_USB := y + CONFIG_BCMDHD_OOB := y +#CONFIG_BCMDHD_CUSB := y CONFIG_BCMDHD_PROPTXSTATUS := y CONFIG_BCMDHD_AG := y #CONFIG_DHD_USE_STATIC_BUF := y @@ -20,10 +20,10 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \ -DBCMDONGLEHOST -DUNRELEASEDCHIP -DBCMDMA32 -DBCMFILEIMAGE \ -DDHDTHREAD -DDHD_DEBUG -DSHOW_EVENTS -DBCMDBG -DGET_OTP_MAC_ENABLE \ -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT -DSUPPORT_PM2_ONLY \ - -DKEEP_ALIVE -DPKT_FILTER_SUPPORT -DPNO_SUPPORT -DDHDTCPACK_SUPPRESS \ + -DKEEP_ALIVE -DPKT_FILTER_SUPPORT -DDHDTCPACK_SUPPRESS \ -DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT \ - -DMULTIPLE_SUPPLICANT -DTSQ_MULTIPLIER -DMFP \ - -DWL_EXT_IAPSTA -DSUPPORT_P2P_GO_PS \ + -DMULTIPLE_SUPPLICANT -DTSQ_MULTIPLIER -DMFP -DDHD_8021X_DUMP \ + -DWL_EXT_IAPSTA -DWL_ESCAN \ -DENABLE_INSMOD_NO_FW_LOAD -DDHD_UNSUPPORT_IF_CNTS \ -Idrivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd \ -Idrivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include @@ -31,15 +31,16 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \ DHDOFILES = aiutils.o siutils.o sbutils.o bcmutils.o bcmwifi_channels.o \ dhd_linux.o dhd_linux_platdev.o dhd_linux_sched.o dhd_pno.o \ dhd_common.o dhd_ip.o dhd_linux_wq.o dhd_custom_gpio.o \ - bcmevent.o hndpmu.o linux_osl.o wldev_common.o wl_android.o \ - dhd_debug_linux.o dhd_debug.o dhd_mschdbg.o \ - hnd_pktq.o hnd_pktpool.o dhd_config.o wl_android_ext.o + bcmevent.o hndpmu.o linux_osl.o wldev_common.o wl_android.o bcmxtlv.o \ + dhd_debug_linux.o dhd_debug.o dhd_mschdbg.o hnd_pktq.o hnd_pktpool.o \ + dhd_config.o wl_event.o wl_android_ext.o wl_escan.o #BCMDHD_SDIO ifneq ($(CONFIG_BCMDHD_SDIO),) DHDCFLAGS += -DBCMSDIO -DMMC_SDIO_ABORT -DBCMLXSDMMC -DUSE_SDIOFIFO_IOVAR \ -DSDTEST -DBDC -DDHD_USE_IDLECOUNT -DCUSTOM_SDIO_F2_BLKSIZE=256 \ - -DBCMSDIOH_TXGLOM -DBCMSDIOH_TXGLOM_EXT -DRXFRAME_THREAD + -DBCMSDIOH_TXGLOM -DBCMSDIOH_TXGLOM_EXT -DRXFRAME_THREAD \ + -DDHDENABLE_TAILPAD -DSUPPORT_P2P_GO_PS -DBCMSDIO_RXLIM_POST ifeq ($(CONFIG_BCMDHD_OOB),y) DHDCFLAGS += -DOOB_INTR_ONLY -DCUSTOMER_OOB -DHW_OOB ifeq ($(CONFIG_BCMDHD_DISABLE_WOWLAN),y) @@ -48,7 +49,6 @@ endif else DHDCFLAGS += -DSDIO_ISR_THREAD endif - DHDOFILES += bcmsdh.o bcmsdh_linux.o bcmsdh_sdmmc.o bcmsdh_sdmmc_linux.o \ dhd_sdio.o dhd_cdc.o dhd_wlfc.o endif @@ -57,10 +57,10 @@ endif ifneq ($(CONFIG_BCMDHD_PCIE),) DHDCFLAGS += -DPCIE_FULL_DONGLE -DBCMPCIE -DCUSTOM_DPC_PRIO_SETTING=-1 \ -DDONGLE_ENABLE_ISOLATION +DHDCFLAGS += -DDHD_LB -DDHD_LB_RXP -DDHD_LB_STATS #-DDHD_LB_TXP ifneq ($(CONFIG_PCI_MSI),) DHDCFLAGS += -DDHD_USE_MSI endif - DHDOFILES += dhd_pcie.o dhd_pcie_linux.o pcie_core.o dhd_flowring.o \ dhd_msgbuf.o endif @@ -75,7 +75,6 @@ ifneq ($(CONFIG_BCMDHD_CUSB),) DHDCFLAGS += -DBCMUSBDEV_COMPOSITE DHDCFLAGS :=$(filter-out -DENABLE_INSMOD_NO_FW_LOAD,$(DHDCFLAGS)) endif - DHDOFILES += dbus.o dbus_usb.o dbus_usb_linux.o dhd_cdc.o dhd_wlfc.o endif @@ -95,18 +94,20 @@ endif #VTS_SUPPORT ifeq ($(CONFIG_VTS_SUPPORT),y) ifneq ($(CONFIG_CFG80211),) -DHDCFLAGS += -DGSCAN_SUPPORT -DRTT_SUPPORT -DCUSTOM_FORCE_NODFS_FLAG \ - -DLINKSTAT_SUPPORT -DDEBUGABILITY -DDBG_PKT_MON -DPKT_FILTER_SUPPORT \ - -DAPF -DNDO_CONFIG_SUPPORT -DRSSI_MONITOR_SUPPORT -DDHD_WAKE_STATUS \ - -DCUSTOM_COUNTRY_CODE -DDHD_FW_COREDUMP -DEXPLICIT_DISCIF_CLEANUP - -DHDOFILES += bcmxtlv.o dhd_rtt.o bcm_app_utils.o +DHDCFLAGS += -DGSCAN_SUPPORT -DRTT_SUPPORT -DLINKSTAT_SUPPORT \ + -DCUSTOM_COUNTRY_CODE \ + -DDEBUGABILITY -DDBG_PKT_MON -DDHD_FW_COREDUMP \ + -DAPF -DNDO_CONFIG_SUPPORT -DRSSI_MONITOR_SUPPORT -DDHD_WAKE_STATUS +DHDOFILES += dhd_rtt.o bcm_app_utils.o endif endif # MESH support for kernel 3.10 later ifeq ($(CONFIG_WL_MESH),y) DHDCFLAGS += -DWLMESH +ifneq ($(CONFIG_CFG80211),) + DHDCFLAGS += -DWLMESH_CFG80211 +endif ifneq ($(CONFIG_BCMDHD_PCIE),) DHDCFLAGS += -DBCM_HOST_BUF -DDMA_HOST_BUFFER_LEN=0x80000 endif @@ -115,9 +116,9 @@ endif DHDCFLAGS :=$(filter-out -DSET_RANDOM_MAC_SOFTAP,$(DHDCFLAGS)) endif -#obj-$(CONFIG_RKWIFI) += bcmdhd.o -obj-$(CONFIG_AP6XXX) += bcmdhd.o -bcmdhd-objs += $(DHDOFILES) +#obj-$(CONFIG_RKWIFI) += $(MODULE_NAME).o +obj-$(CONFIG_AP6XXX) += $(MODULE_NAME).o +$(MODULE_NAME)-objs += $(DHDOFILES) ifeq ($(CONFIG_MACH_PLATFORM),y) DHDOFILES += dhd_gpio.o @@ -140,17 +141,14 @@ ifeq ($(CONFIG_DHD_USE_STATIC_BUF),y) endif ifneq ($(CONFIG_WIRELESS_EXT),) - DHDOFILES += wl_iw.o wl_escan.o - DHDCFLAGS += -DSOFTAP -DWL_WIRELESS_EXT -DUSE_IW -DWL_ESCAN + DHDOFILES += wl_iw.o + DHDCFLAGS += -DSOFTAP -DWL_WIRELESS_EXT -DUSE_IW endif ifneq ($(CONFIG_CFG80211),) DHDOFILES += wl_cfg80211.o wl_cfgp2p.o wl_linux_mon.o wl_cfg_btcoex.o wl_cfgvendor.o DHDOFILES += dhd_cfg80211.o DHDCFLAGS += -DWL_CFG80211 -DWLP2P -DWL_CFG80211_STA_EVENT -DWL_ENABLE_P2P_IF # DHDCFLAGS += -DWL_IFACE_COMB_NUM_CHANNELS - DHDCFLAGS += -DCUSTOM_ROAM_TRIGGER_SETTING=-65 - DHDCFLAGS += -DCUSTOM_ROAM_DELTA_SETTING=15 - DHDCFLAGS += -DCUSTOM_KEEP_ALIVE_SETTING=28000 DHDCFLAGS += -DCUSTOM_PNO_EVENT_LOCK_xTIME=7 DHDCFLAGS += -DWL_SUPPORT_AUTO_CHANNEL DHDCFLAGS += -DWL_SUPPORT_BACKPORTED_KPATCHES @@ -158,6 +156,8 @@ ifneq ($(CONFIG_CFG80211),) DHDCFLAGS += -DVSDB -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST DHDCFLAGS += -DWLTDLS -DMIRACAST_AMPDU_SIZE=8 DHDCFLAGS += -DWL_VIRTUAL_APSTA + DHDCFLAGS += -DPNO_SUPPORT -DEXPLICIT_DISCIF_CLEANUP + DHDCFLAGS += -DWL_SAE endif EXTRA_CFLAGS = $(DHDCFLAGS) ifeq ($(CONFIG_BCMDHD),m) diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmevent.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmevent.c index f8c2f161b0ba..1e44ad7d4101 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmevent.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmevent.c @@ -108,6 +108,10 @@ static const bcmevent_name_str_t bcmevent_names[] = { BCMEVENT_NAME(WLC_E_ACTION_FRAME), BCMEVENT_NAME(WLC_E_ACTION_FRAME_RX), BCMEVENT_NAME(WLC_E_ACTION_FRAME_COMPLETE), +#ifdef BCMWAPI_WAI + BCMEVENT_NAME(WLC_E_WAI_STA_EVENT), + BCMEVENT_NAME(WLC_E_WAI_MSG), +#endif /* BCMWAPI_WAI */ BCMEVENT_NAME(WLC_E_ESCAN_RESULT), BCMEVENT_NAME(WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE), #ifdef WLP2P @@ -169,6 +173,9 @@ static const bcmevent_name_str_t bcmevent_names[] = { #if defined(BT_WIFI_HANDOVER) || defined(WL_TBOW) BCMEVENT_NAME(WLC_E_BT_WIFI_HANDOVER_REQ), #endif +#ifdef WLFBT + BCMEVENT_NAME(WLC_E_FBT_AUTH_REQ_IND), +#endif /* WLFBT */ BCMEVENT_NAME(WLC_E_AUTHORIZED), BCMEVENT_NAME(WLC_E_PROBREQ_MSG_RX), BCMEVENT_NAME(WLC_E_CSA_START_IND), diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmsdh_linux.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmsdh_linux.c index 41462a37e6e6..dadfbb2628d2 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmsdh_linux.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmsdh_linux.c @@ -222,10 +222,13 @@ int bcmsdh_get_total_wake(bcmsdh_info_t *bcmsdh) int bcmsdh_set_get_wake(bcmsdh_info_t *bcmsdh, int flag) { +#if defined(OOB_INTR_ONLY) bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt; unsigned long flags; - int ret; +#endif + int ret = 0; +#if defined(OOB_INTR_ONLY) spin_lock_irqsave(&bcmsdh_osinfo->oob_irq_spinlock, flags); ret = bcmsdh->pkt_wake; @@ -233,6 +236,7 @@ int bcmsdh_set_get_wake(bcmsdh_info_t *bcmsdh, int flag) bcmsdh->pkt_wake = flag; spin_unlock_irqrestore(&bcmsdh_osinfo->oob_irq_spinlock, flags); +#endif return ret; } #endif /* DHD_WAKE_STATUS */ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmsdh_sdmmc.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmsdh_sdmmc.c index cb54b832017e..5a3fe7c3b117 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmsdh_sdmmc.c @@ -84,11 +84,6 @@ static void IRQHandlerF2(struct sdio_func *func); static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr); #if defined(ENABLE_INSMOD_NO_FW_LOAD) && !defined(BUS_POWER_RESTORE) extern int sdio_reset_comm(struct mmc_card *card); -#else -int sdio_reset_comm(struct mmc_card *card) -{ - return 0; -} #endif #ifdef GLOBAL_SDMMC_INSTANCE extern PBCMSDH_SDMMC_INSTANCE gInstance; @@ -599,6 +594,7 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name, /* Now set it */ si->client_block_size[func] = blksize; +#ifdef USE_DYNAMIC_F2_BLKSIZE if (si->func[func] == NULL) { sd_err(("%s: SDIO Device not present\n", __FUNCTION__)); bcmerror = BCME_NORESOURCE; @@ -610,6 +606,7 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name, sd_err(("%s: Failed to set F%d blocksize to %d(%d)\n", __FUNCTION__, func, blksize, bcmerror)); sdio_release_host(si->func[func]); +#endif /* USE_DYNAMIC_F2_BLKSIZE */ break; } @@ -835,10 +832,10 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by #if defined(MMC_SDIO_ABORT) int sdio_abort_retry = MMC_SDIO_ABORT_RETRY_LIMIT; #endif - struct timespec now, before = {}; + struct osl_timespec now, before; if (sd_msglevel & SDH_COST_VAL) - getnstimeofday(&before); + osl_do_gettimeofday(&before); sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __FUNCTION__, rw, func, regaddr)); @@ -939,6 +936,26 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by } } #endif /* MMC_SDIO_ABORT */ + /* to allow abort command through F1 */ +#if defined(SDIO_ISR_THREAD) + else if (regaddr == SDIOD_CCCR_INTR_EXTN) { + while (sdio_abort_retry--) { + if (sd->func[func]) { + sdio_claim_host(sd->func[func]); + /* + * this sdio_f0_writeb() can be replaced with + * another api depending upon MMC driver change. + * As of this time, this is temporaray one + */ + sdio_writeb(sd->func[func], + *byte, regaddr, &err_ret); + sdio_release_host(sd->func[func]); + } + if (!err_ret) + break; + } + } +#endif else if (regaddr < 0xF0) { sd_err(("bcmsdh_sdmmc: F0 Wr:0x%02x: write disallowed\n", regaddr)); } else { @@ -980,7 +997,7 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by } if (sd_msglevel & SDH_COST_VAL) { - getnstimeofday(&now); + osl_do_gettimeofday(&now); sd_cost(("%s: rw=%d len=1 cost=%lds %luus\n", __FUNCTION__, rw, now.tv_sec-before.tv_sec, now.tv_nsec/1000-before.tv_nsec/1000)); } @@ -1008,10 +1025,10 @@ sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint add #if defined(MMC_SDIO_ABORT) int sdio_abort_retry = MMC_SDIO_ABORT_RETRY_LIMIT; #endif - struct timespec now, before = {}; + struct osl_timespec now, before; if (sd_msglevel & SDH_COST_VAL) - getnstimeofday(&before); + osl_do_gettimeofday(&before); if (func == 0) { sd_err(("%s: Only CMD52 allowed to F0.\n", __FUNCTION__)); @@ -1074,7 +1091,7 @@ sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint add } if (sd_msglevel & SDH_COST_VAL) { - getnstimeofday(&now); + osl_do_gettimeofday(&now); sd_cost(("%s: rw=%d, len=%d cost=%lds %luus\n", __FUNCTION__, rw, nbytes, now.tv_sec-before.tv_sec, now.tv_nsec/1000 - before.tv_nsec/1000)); } @@ -1104,7 +1121,7 @@ sdioh_request_packet_chain(sdioh_info_t *sd, uint fix_inc, uint write, uint func uint8 *localbuf = NULL; uint local_plen = 0; uint pkt_len = 0; - struct timespec now, before = {}; + struct osl_timespec now, before; sd_trace(("%s: Enter\n", __FUNCTION__)); ASSERT(pkt); @@ -1112,7 +1129,7 @@ sdioh_request_packet_chain(sdioh_info_t *sd, uint fix_inc, uint write, uint func DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL); if (sd_msglevel & SDH_COST_VAL) - getnstimeofday(&before); + osl_do_gettimeofday(&before); blk_size = sd->client_block_size[func]; max_blk_count = min(host->max_blk_count, (uint)MAX_IO_RW_EXTENDED_BLK); @@ -1229,10 +1246,10 @@ sdioh_request_packet_chain(sdioh_info_t *sd, uint fix_inc, uint write, uint func goto txglomfail; } } - + bcopy(buf, (localbuf + local_plen), pkt_len); local_plen += pkt_len; - if (PKTNEXT(sd->osh, pnext)) + if (PKTNEXT(sd->osh, pnext)) continue; buf = localbuf; @@ -1286,7 +1303,7 @@ txglomfail: MFREE(sd->osh, localbuf, ttl_len); if (sd_msglevel & SDH_COST_VAL) { - getnstimeofday(&now); + osl_do_gettimeofday(&now); sd_cost(("%s: rw=%d, ttl_len=%d, cost=%lds %luus\n", __FUNCTION__, write, ttl_len, now.tv_sec-before.tv_sec, now.tv_nsec/1000-before.tv_nsec/1000)); } @@ -1302,13 +1319,13 @@ sdioh_buffer_tofrom_bus(sdioh_info_t *sd, uint fix_inc, uint write, uint func, { bool fifo = (fix_inc == SDIOH_DATA_FIX); int err_ret = 0; - struct timespec now, before = {}; + struct osl_timespec now, before; sd_trace(("%s: Enter\n", __FUNCTION__)); ASSERT(buf); if (sd_msglevel & SDH_COST_VAL) - getnstimeofday(&before); + osl_do_gettimeofday(&before); /* NOTE: * For all writes, each packet length is aligned to 32 (or 4) @@ -1342,7 +1359,7 @@ sdioh_buffer_tofrom_bus(sdioh_info_t *sd, uint fix_inc, uint write, uint func, sd_trace(("%s: Exit\n", __FUNCTION__)); if (sd_msglevel & SDH_COST_VAL) { - getnstimeofday(&now); + osl_do_gettimeofday(&now); sd_cost(("%s: rw=%d, len=%d cost=%lds %luus\n", __FUNCTION__, write, len, now.tv_sec-before.tv_sec, now.tv_nsec/1000 - before.tv_nsec/1000)); } @@ -1368,14 +1385,14 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u { SDIOH_API_RC status; void *tmppkt; - struct timespec now, before = {}; + struct osl_timespec now, before; sd_trace(("%s: Enter\n", __FUNCTION__)); DHD_PM_RESUME_WAIT(sdioh_request_buffer_wait); DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL); if (sd_msglevel & SDH_COST_VAL) - getnstimeofday(&before); + osl_do_gettimeofday(&before); if (pkt) { #ifdef BCMSDIOH_TXGLOM @@ -1420,7 +1437,7 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u PKTFREE_STATIC(sd->osh, tmppkt, write ? TRUE : FALSE); if (sd_msglevel & SDH_COST_VAL) { - getnstimeofday(&now); + osl_do_gettimeofday(&now); sd_cost(("%s: len=%d cost=%lds %luus\n", __FUNCTION__, buf_len, now.tv_sec-before.tv_sec, now.tv_nsec/1000 - before.tv_nsec/1000)); } @@ -1583,11 +1600,13 @@ sdioh_start(sdioh_info_t *sd, int stage) 2.6.27. The implementation prior to that is buggy, and needs broadcom's patch for it */ +#if defined(ENABLE_INSMOD_NO_FW_LOAD) && !defined(BUS_POWER_RESTORE) if ((ret = sdio_reset_comm(sd->func[0]->card))) { sd_err(("%s Failed, error = %d\n", __FUNCTION__, ret)); return ret; - } - else { + } else +#endif + { sd->num_funcs = 2; sd->sd_blockmode = TRUE; sd->use_client_ints = TRUE; diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmutils.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmutils.c index 05ee100fb492..1ba8481c50ec 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmutils.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/bcmutils.c @@ -2634,7 +2634,7 @@ process_nvram_vars(char *varbuf, unsigned int len) break; nv_ver[n-1] = varbuf[n]; } - printk("NVRAM version: %s\n", nv_ver); + printf("NVRAM version: %s\n", nv_ver); } for (n = 0; n < len; n++) { diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dbus.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dbus.c index 00a75e6101b2..dcd8282401f8 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dbus.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dbus.c @@ -645,8 +645,10 @@ dbus_get_fw_nvram(dhd_bus_t *dhd_bus, char *pfw_path, char *pnv_path) bcmerror = DBUS_ERR_NVRAM; goto err; } - if (nv_image) + if (nv_image) { dhd_os_close_image(nv_image); + nv_image = NULL; + } /* For Get first block of fw to calculate total_len */ file_exists = ((pfw_path != NULL) && (pfw_path[0] != '\0')); @@ -2686,35 +2688,6 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) return bcmerror; } -void -dhd_set_path_params(struct dhd_bus *bus) -{ - /* External conf takes precedence if specified */ - dhd_conf_preinit(bus->dhd); - - if (bus->dhd->conf_path[0] == '\0') { - dhd_conf_set_path(bus->dhd, "config.txt", bus->dhd->conf_path, bus->nv_path); - } - if (bus->dhd->clm_path[0] == '\0') { - dhd_conf_set_path(bus->dhd, "clm.blob", bus->dhd->clm_path, bus->fw_path); - } -#ifdef CONFIG_PATH_AUTO_SELECT - dhd_conf_set_conf_name_by_chip(bus->dhd, bus->dhd->conf_path); -#endif - - dhd_conf_read_config(bus->dhd, bus->dhd->conf_path); - - dhd_conf_set_fw_name_by_chip(bus->dhd, bus->fw_path); - dhd_conf_set_nv_name_by_chip(bus->dhd, bus->nv_path); - dhd_conf_set_clm_name_by_chip(bus->dhd, bus->dhd->clm_path); - - printf("Final fw_path=%s\n", bus->fw_path); - printf("Final nv_path=%s\n", bus->nv_path); - printf("Final clm_path=%s\n", bus->dhd->clm_path); - printf("Final conf_path=%s\n", bus->dhd->conf_path); - -} - void dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path, char *pclm_path, char *pconf_path) @@ -2731,7 +2704,7 @@ dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, bus->dhd->clm_path = pclm_path; bus->dhd->conf_path = pconf_path; - dhd_set_path_params(bus); + dhd_conf_set_path_params(bus->dhd, NULL, bus->fw_path, bus->nv_path); } @@ -2799,6 +2772,8 @@ dhd_dbus_probe_cb(void *arg, const char *desc, uint32 bustype, if (dbus_download_firmware(bus, bus->fw_path, bus->nv_path) != DBUS_OK) goto fail; #endif + } else { + goto fail; } } } else { diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd.h index 4a92d2f86715..3f8ca8adce44 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd.h @@ -352,9 +352,10 @@ enum dhd_bus_ds_state { enum dhd_prealloc_index { DHD_PREALLOC_PROT = 0, - DHD_PREALLOC_RXBUF, - DHD_PREALLOC_DATABUF, - DHD_PREALLOC_OSL_BUF, + DHD_PREALLOC_RXBUF = 1, + DHD_PREALLOC_DATABUF = 2, + DHD_PREALLOC_OSL_BUF = 3, + DHD_PREALLOC_SKB_BUF = 4, #if defined(STATIC_WL_PRIV_STRUCT) DHD_PREALLOC_WIPHY_ESCAN0 = 5, #endif /* STATIC_WL_PRIV_STRUCT */ @@ -370,7 +371,7 @@ enum dhd_prealloc_index { DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX = 16, DHD_PREALLOC_DHD_PKTLOG_DUMP_BUF = 17, DHD_PREALLOC_STAT_REPORT_BUF = 18, - DHD_PREALLOC_WL_ESCAN_INFO = 19, + DHD_PREALLOC_WL_ESCAN = 19, DHD_PREALLOC_FW_VERBOSE_RING = 20, DHD_PREALLOC_FW_EVENT_RING = 21, DHD_PREALLOC_DHD_EVENT_RING = 22, @@ -1040,18 +1041,22 @@ typedef struct dhd_pub { char *conf_path; /* module_param: path to config vars file */ struct dhd_conf *conf; /* Bus module handle */ void *adapter; /* adapter information, interrupt, fw path etc. */ + void *event_params; #ifdef BCMDBUS bool dhd_remove; #endif /* BCMDBUS */ -#if defined(WL_WIRELESS_EXT) -#if defined(WL_ESCAN) - void *escan; -#else - void *iscan; +#ifdef WL_ESCAN + struct wl_escan_info *escan; #endif +#if defined(WL_WIRELESS_EXT) + void *wext_info; #endif #ifdef WL_EXT_IAPSTA void *iapsta_params; +#endif + int hostsleep; +#ifdef SENDPROB + bool recv_probereq; #endif } dhd_pub_t; @@ -1535,7 +1540,7 @@ extern void dhd_os_dhdiovar_lock(dhd_pub_t *pub); extern void dhd_os_dhdiovar_unlock(dhd_pub_t *pub); extern int dhd_os_proto_block(dhd_pub_t * pub); extern int dhd_os_proto_unblock(dhd_pub_t * pub); -extern int dhd_os_ioctl_resp_wait(dhd_pub_t * pub, uint * condition, bool resched); +extern int dhd_os_ioctl_resp_wait(dhd_pub_t * pub, uint * condition); extern int dhd_os_ioctl_resp_wake(dhd_pub_t * pub); extern unsigned int dhd_os_get_ioctl_resp_timeout(void); extern void dhd_os_set_ioctl_resp_timeout(unsigned int timeout_msec); @@ -1877,6 +1882,7 @@ extern uint dhd_console_ms; extern uint android_msg_level; extern uint config_msg_level; extern uint sd_msglevel; +extern uint dump_msg_level; #ifdef BCMDBUS extern uint dbus_msglevel; #endif /* BCMDBUS */ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_cdc.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_cdc.c index 3fb5e457040a..21286dded828 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_cdc.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_cdc.c @@ -116,7 +116,7 @@ dhdcdc_msg(dhd_pub_t *dhd) #endif /* BCMDBUS */ #ifdef BCMDBUS - timeout = dhd_os_ioctl_resp_wait(dhd, &prot->ctl_completed, false); + timeout = dhd_os_ioctl_resp_wait(dhd, &prot->ctl_completed); if ((!timeout) || (!prot->ctl_completed)) { DHD_ERROR(("Txctl timeout %d ctl_completed %d\n", timeout, prot->ctl_completed)); @@ -138,7 +138,7 @@ dhdcdc_msg(dhd_pub_t *dhd) /* interrupt polling is sucessfully submitted. Wait for dongle to send * interrupt */ - timeout = dhd_os_ioctl_resp_wait(dhd, &prot->ctl_completed, false); + timeout = dhd_os_ioctl_resp_wait(dhd, &prot->ctl_completed); if (!timeout) { DHD_ERROR(("intr poll wait timed out\n")); } @@ -172,7 +172,7 @@ dhdcdc_cmplt(dhd_pub_t *dhd, uint32 id, uint32 len) DHD_OS_IOCTL_RESP_UNLOCK(dhd); goto done; } - timeout = dhd_os_ioctl_resp_wait(dhd, &prot->ctl_completed, false); + timeout = dhd_os_ioctl_resp_wait(dhd, &prot->ctl_completed); if ((!timeout) || (!prot->ctl_completed)) { DHD_ERROR(("Rxctl timeout %d ctl_completed %d\n", timeout, prot->ctl_completed)); diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_cfg80211.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_cfg80211.c index b98fcd36f599..d01e7680142d 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_cfg80211.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_cfg80211.c @@ -161,10 +161,8 @@ void dhd_netdev_free(struct net_device *ndev) #ifdef WL_CFG80211 ndev = dhd_cfg80211_netdev_free(ndev); #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) if (ndev) free_netdev(ndev); -#endif } static s32 diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_common.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_common.c index a556587b1cb9..ba03a50dfed6 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_common.c @@ -53,12 +53,13 @@ #include #include -#include #include #include #include #include #include +#include +#include #ifdef WL_CFG80211 #include @@ -828,6 +829,9 @@ dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifidx, wl_ioctl_t *ioc, void *buf, int len) #ifdef DUMP_IOCTL_IOV_LIST dhd_iov_li_t *iov_li; #endif /* DUMP_IOCTL_IOV_LIST */ + int hostsleep_set = 0; + int hostsleep_val = 0; + #ifdef KEEPIF_ON_DEVICE_RESET if (ioc->cmd == WLC_GET_VAR) { dbus_config_t config; @@ -919,7 +923,11 @@ dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifidx, wl_ioctl_t *ioc, void *buf, int len) } } #endif /* DUMP_IOCTL_IOV_LIST */ + if (dhd_conf_check_hostsleep(dhd_pub, ioc->cmd, ioc->buf, len, + &hostsleep_set, &hostsleep_val, &ret)) + goto exit; ret = dhd_prot_ioctl(dhd_pub, ifidx, ioc, buf, len); + dhd_conf_get_hostsleep(dhd_pub, hostsleep_set, hostsleep_val, ret); #ifdef DUMP_IOCTL_IOV_LIST if (ret == -ETIMEDOUT) { DHD_ERROR(("Last %d issued commands: Latest one is at bottom.\n", @@ -983,6 +991,7 @@ dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifidx, wl_ioctl_t *ioc, void *buf, int len) dhd_pub->busstate = DHD_BUS_DOWN; } +exit: DHD_LINUX_GENERAL_LOCK(dhd_pub, flags); DHD_BUS_BUSY_CLEAR_IN_IOVAR(dhd_pub); dhd_os_busbusy_wake(dhd_pub); @@ -3272,7 +3281,6 @@ dhd_print_buf(void *pbuf, int len, int bytes_per_line) #define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) #endif -#if defined(PKT_FILTER_SUPPORT) || defined(DHD_PKT_LOGGING) /* Convert user's input in hex pattern to byte-size mask */ int wl_pattern_atoh(char *src, char *dst) @@ -3297,7 +3305,6 @@ wl_pattern_atoh(char *src, char *dst) } return i; } -#endif /* PKT_FILTER_SUPPORT || DHD_PKT_LOGGING */ #ifdef PKT_FILTER_SUPPORT void @@ -3655,7 +3662,7 @@ dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg) rc = rc >= 0 ? 0 : rc; if (rc) - DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n", + DHD_ERROR(("%s: failed to add pktfilter %s, retcode = %d\n", __FUNCTION__, arg, rc)); else DHD_TRACE(("%s: successfully added pktfilter %s\n", @@ -4263,7 +4270,6 @@ dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd) if (bcn_li_dtim == 0) { bcn_li_dtim = 1; } - bcn_li_dtim = MAX(dhd->suspend_bcn_li_dtim, bcn_li_dtim); } else { /* attemp to use platform defined dtim skip interval */ bcn_li_dtim = dhd->suspend_bcn_li_dtim; @@ -4291,8 +4297,6 @@ dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd) } } - if (dhd->conf->suspend_bcn_li_dtim >= 0) - bcn_li_dtim = dhd->conf->suspend_bcn_li_dtim; DHD_ERROR(("%s beacon=%d bcn_li_dtim=%d DTIM=%d Listen=%d\n", __FUNCTION__, ap_beacon, bcn_li_dtim, dtim_period, CUSTOM_LISTEN_INTERVAL)); @@ -4994,69 +4998,78 @@ void dhd_free_download_buffer(dhd_pub_t *dhd, void *buffer, int length) } #if defined(DHD_8021X_DUMP) -#define EAP_PRINT(str) \ - DHD_ERROR(("ETHER_TYPE_802_1X[%s] [%s]: " str "\n", \ - ifname, direction ? "TX" : "RX")); +#define EAP_PRINT(x, args...) \ + do { \ + if (dump_msg_level & DUMP_EAPOL_VAL) { \ + printk("[dhd-%s] 802_1X " x " [%s] : (%s) %s (%s)\n", ifname, ## args, \ + tx?"TX":"RX", tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf); \ + } \ + } while (0) #else -#define EAP_PRINT(str) +#define EAP_PRINT(x, args...) #endif /* DHD_8021X_DUMP */ /* Parse EAPOL 4 way handshake messages */ void dhd_dump_eapol_4way_message(dhd_pub_t *dhd, char *ifname, - char *dump_data, bool direction) + char *dump_data, bool tx) { unsigned char type; int pair, ack, mic, kerr, req, sec, install; - unsigned short us_tmp; + unsigned short us_tmp, key_len; + char seabuf[ETHER_ADDR_STR_LEN]=""; + char deabuf[ETHER_ADDR_STR_LEN]=""; + + bcm_ether_ntoa((struct ether_addr *)dump_data, deabuf); + bcm_ether_ntoa((struct ether_addr *)(dump_data+6), seabuf); type = dump_data[15]; if (type == 0) { if ((dump_data[22] == 1) && (dump_data[18] == 1)) { - dhd->conf->eapol_status = EAPOL_STATUS_WPS_REQID; - EAP_PRINT("EAP Packet, Request, Identity"); + dhd->conf->eapol_status = EAPOL_STATUS_REQID; + EAP_PRINT("Request, Identity"); } else if ((dump_data[22] == 1) && (dump_data[18] == 2)) { - dhd->conf->eapol_status = EAPOL_STATUS_WPS_RSPID; - EAP_PRINT("EAP Packet, Response, Identity"); + dhd->conf->eapol_status = EAPOL_STATUS_RSPID; + EAP_PRINT("Response, Identity"); } else if (dump_data[22] == 254) { if (dump_data[30] == 1) { - dhd->conf->eapol_status = EAPOL_STATUS_WPS_WSC_START; - EAP_PRINT("EAP Packet, WSC Start"); + dhd->conf->eapol_status = EAPOL_STATUS_WSC_START; + EAP_PRINT("WSC Start"); } else if (dump_data[30] == 4) { if (dump_data[41] == 4) { dhd->conf->eapol_status = EAPOL_STATUS_WPS_M1; - EAP_PRINT("EAP Packet, WPS M1"); + EAP_PRINT("WPS M1"); } else if (dump_data[41] == 5) { dhd->conf->eapol_status = EAPOL_STATUS_WPS_M2; - EAP_PRINT("EAP Packet, WPS M2"); + EAP_PRINT("WPS M2"); } else if (dump_data[41] == 7) { dhd->conf->eapol_status = EAPOL_STATUS_WPS_M3; - EAP_PRINT("EAP Packet, WPS M3"); + EAP_PRINT("WPS M3"); } else if (dump_data[41] == 8) { dhd->conf->eapol_status = EAPOL_STATUS_WPS_M4; - EAP_PRINT("EAP Packet, WPS M4"); + EAP_PRINT("WPS M4"); } else if (dump_data[41] == 9) { dhd->conf->eapol_status = EAPOL_STATUS_WPS_M5; - EAP_PRINT("EAP Packet, WPS M5"); + EAP_PRINT("WPS M5"); } else if (dump_data[41] == 10) { dhd->conf->eapol_status = EAPOL_STATUS_WPS_M6; - EAP_PRINT("EAP Packet, WPS M6"); + EAP_PRINT("WPS M6"); } else if (dump_data[41] == 11) { dhd->conf->eapol_status = EAPOL_STATUS_WPS_M7; - EAP_PRINT("EAP Packet, WPS M7"); + EAP_PRINT("WPS M7"); } else if (dump_data[41] == 12) { dhd->conf->eapol_status = EAPOL_STATUS_WPS_M8; - EAP_PRINT("EAP Packet, WPS M8"); + EAP_PRINT("WPS M8"); } } else if (dump_data[30] == 5) { - dhd->conf->eapol_status = EAPOL_STATUS_WPS_DONE; - EAP_PRINT("EAP Packet, WSC Done"); + dhd->conf->eapol_status = EAPOL_STATUS_WSC_DONE; + EAP_PRINT("WSC Done"); } } else { - DHD_ERROR(("ETHER_TYPE_802_1X[%s] [%s]: ver %d, type %d, replay %d\n", - ifname, direction ? "TX" : "RX", - dump_data[14], dump_data[15], dump_data[30])); + EAP_PRINT("ver %d, type %d, replay %d", + dump_data[14], dump_data[15], dump_data[30]); } - } else if (type == 3 && dump_data[18] == 2) { + } + else if (type == 3 && dump_data[18] == 2) { us_tmp = (dump_data[19] << 8) | dump_data[20]; pair = 0 != (us_tmp & 0x08); ack = 0 != (us_tmp & 0x80); @@ -5066,27 +5079,59 @@ dhd_dump_eapol_4way_message(dhd_pub_t *dhd, char *ifname, sec = 0 != (us_tmp & 0x200); install = 0 != (us_tmp & 0x40); - if (!sec && !mic && ack && !install && pair && !kerr && !req) { - dhd->conf->eapol_status = EAPOL_STATUS_WPA_M1; - EAP_PRINT("EAPOL Packet, 4-way handshake, M1"); - } else if (pair && !install && !ack && mic && !sec && !kerr && !req) { - dhd->conf->eapol_status = EAPOL_STATUS_WPA_M2; - EAP_PRINT("EAPOL Packet, 4-way handshake, M2"); - } else if (pair && ack && mic && sec && !kerr && !req) { - dhd->conf->eapol_status = EAPOL_STATUS_WPA_M3; - EAP_PRINT("EAPOL Packet, 4-way handshake, M3"); - } else if (pair && !install && !ack && mic && sec && !req && !kerr) { - dhd->conf->eapol_status = EAPOL_STATUS_WPA_M4; - EAP_PRINT("EAPOL Packet, 4-way handshake, M4"); + if (!req && !kerr && !sec && !mic && ack && !install && pair) { + dhd->conf->eapol_status = EAPOL_STATUS_4WAY_M1; + EAP_PRINT("WPA2 4-way M1(0x%04x)", us_tmp); + } else if (!req && !kerr && !sec && mic && !ack && !install && pair) { + dhd->conf->eapol_status = EAPOL_STATUS_4WAY_M2; + EAP_PRINT("WPA2 4-way M2(0x%04x)", us_tmp); + } else if (!req && !kerr && sec && mic && ack && pair) { + dhd->conf->eapol_status = EAPOL_STATUS_4WAY_M3; + EAP_PRINT("WPA2 4-way M3(0x%04x)", us_tmp); + } else if (!req && !kerr && sec && mic && !ack && !install && pair) { + dhd->conf->eapol_status = EAPOL_STATUS_4WAY_M4; + EAP_PRINT("WPA2 4-way M4(0x%04x)", us_tmp); } else { - DHD_ERROR(("ETHER_TYPE_802_1X[%s] [%s]: ver %d, type %d, replay %d\n", - ifname, direction ? "TX" : "RX", - dump_data[14], dump_data[15], dump_data[30])); + EAP_PRINT("ver %d, type %d, key_info 0x%x, replay %d", + dump_data[14], dump_data[15], us_tmp, dump_data[30]); + } + } + else if (type == 3 && dump_data[18] == 254) { + us_tmp = (dump_data[19] << 8) | dump_data[20]; + req = 0 != (us_tmp & 0x800); + kerr = 0 != (us_tmp & 0x400); + sec = 0 != (us_tmp & 0x200); + mic = 0 != (us_tmp & 0x100); + ack = 0 != (us_tmp & 0x80); + install = 0 != (us_tmp & 0x40); + pair = 0 != (us_tmp & 0x08); + key_len = (dump_data[111] << 8) | dump_data[112]; + + if (!req && !kerr && !sec && !mic && ack && !install && pair) { + dhd->conf->eapol_status = EAPOL_STATUS_4WAY_M1; + EAP_PRINT("WPA 4-way M1(0x%04x)", us_tmp); + } else if (!req && !kerr && !sec && mic && !ack && !install && pair && key_len) { + dhd->conf->eapol_status = EAPOL_STATUS_4WAY_M2; + EAP_PRINT("WPA 4-way M2(0x%04x)", us_tmp); + } else if (!req && !kerr && !sec && mic && ack && install && pair) { + dhd->conf->eapol_status = EAPOL_STATUS_4WAY_M3; + EAP_PRINT("WPA 4-way M3(0x%04x)", us_tmp); + } else if (!req && !kerr && !sec && mic && !ack && !install && pair) { + dhd->conf->eapol_status = EAPOL_STATUS_4WAY_M4; + EAP_PRINT("WPA 4-way M4(0x%04x)", us_tmp); + } else if (!req && !kerr && sec && mic && ack && !install && !pair) { + dhd->conf->eapol_status = EAPOL_STATUS_GROUPKEY_M1; + EAP_PRINT("GROUP Key M1(0x%04x)", us_tmp); + } else if (!req && !kerr && sec && mic && !ack && !install && !pair) { + dhd->conf->eapol_status = EAPOL_STATUS_GROUPKEY_M2; + EAP_PRINT("GROUP Key M2(0x%04x)", us_tmp); + } else { + EAP_PRINT("ver %d, type %d, key_type %d, key_info 0x%x, replay %d", + dump_data[14], dump_data[15], dump_data[18], us_tmp, dump_data[30]); } } else { - DHD_ERROR(("ETHER_TYPE_802_1X[%s] [%s]: ver %d, type %d, replay %d\n", - ifname, direction ? "TX" : "RX", - dump_data[14], dump_data[15], dump_data[30])); + EAP_PRINT("ver %d, type %d, replay %d", + dump_data[14], dump_data[15], dump_data[30]); } } diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.c index d11a4b1311cd..dc80027e906d 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -11,128 +12,153 @@ #include #include #endif +#ifdef WL_CFG80211 +#include +#endif #include #include +#include /* message levels */ -#define CONFIG_ERROR_LEVEL 0x0001 -#define CONFIG_TRACE_LEVEL 0x0002 +#define CONFIG_ERROR_LEVEL (1 << 0) +#define CONFIG_TRACE_LEVEL (1 << 1) +#define CONFIG_MSG_LEVEL (1 << 15) -uint config_msg_level = CONFIG_ERROR_LEVEL; +uint config_msg_level = CONFIG_ERROR_LEVEL | CONFIG_MSG_LEVEL; +uint dump_msg_level = 0; -#define CONFIG_ERROR(x) \ +#define CONFIG_MSG(x, args...) \ + do { \ + if (config_msg_level & CONFIG_MSG_LEVEL) { \ + printk(KERN_ERR "[dhd] %s : " x, __func__, ## args); \ + } \ + } while (0) +#define CONFIG_ERROR(x, args...) \ do { \ if (config_msg_level & CONFIG_ERROR_LEVEL) { \ - printk(KERN_ERR "CONFIG-ERROR) "); \ - printk x; \ + printk(KERN_ERR "[dhd] CONFIG-ERROR) %s : " x, __func__, ## args); \ } \ } while (0) -#define CONFIG_TRACE(x) \ +#define CONFIG_TRACE(x, args...) \ do { \ if (config_msg_level & CONFIG_TRACE_LEVEL) { \ - printk(KERN_ERR "CONFIG-TRACE) "); \ - printk x; \ + printk(KERN_ERR "[dhd] CONFIG-TRACE) %s : " x, __func__, ## args); \ } \ } while (0) -#define MAXSZ_BUF 1000 -#define MAXSZ_CONFIG 4096 +#define MAXSZ_BUF 4096 +#define MAXSZ_CONFIG 8192 +#ifndef WL_CFG80211 #define htod32(i) i #define htod16(i) i #define dtoh32(i) i #define dtoh16(i) i #define htodchanspec(i) i #define dtohchanspec(i) i +#endif + +#if defined(SUSPEND_EVENT) && defined(PROP_TXSTATUS) +#if defined(BCMSDIO) || defined(BCMDBUS) +#include +#endif /* BCMSDIO || BCMDBUS */ +#endif /* SUSPEND_EVENT && PROP_TXSTATUS */ + +#define MAX_EVENT_BUF_NUM 16 +typedef struct eventmsg_buf { + u16 num; + struct { + u16 type; + bool set; + } event [MAX_EVENT_BUF_NUM]; +} eventmsg_buf_t; typedef struct cihp_name_map_t { uint chip; uint chiprev; uint ag_type; - bool clm; char *chip_name; char *module_name; } cihp_name_map_t; /* Map of WLC_E events to connection failure strings */ #define DONT_CARE 9999 -const cihp_name_map_t chip_name_map [] = { - /* ChipID Chiprev AG CLM ChipName ModuleName */ +const cihp_name_map_t chip_name_map[] = { + /* ChipID Chiprev AG ChipName ModuleName */ #ifdef BCMSDIO - {BCM43362_CHIP_ID, 0, DONT_CARE, FALSE, "RK901a0", ""}, - //{BCM43362_CHIP_ID, 1, DONT_CARE, FALSE, "RK901a2", "AP6210"}, - {BCM43362_CHIP_ID, 1, DONT_CARE, FALSE, "bcm40181a2", "ap6181"}, - {BCM4330_CHIP_ID, 4, FW_TYPE_G, FALSE, "RK903b2", ""}, - {BCM4330_CHIP_ID, 4, FW_TYPE_AG, FALSE, "RK903_ag", "AP6330"}, - {BCM43430_CHIP_ID, 0, DONT_CARE, FALSE, "bcm43438a0", "ap6212"}, - {BCM43430_CHIP_ID, 1, DONT_CARE, FALSE, "bcm43438a1", "ap6212a"}, - {BCM43430_CHIP_ID, 2, DONT_CARE, FALSE, "bcm43436b0", "ap6236"}, - {BCM43012_CHIP_ID, 1, DONT_CARE, TRUE, "bcm43013b0", ""}, - {BCM4334_CHIP_ID, 3, DONT_CARE, FALSE, "bcm4334b1_ag", ""}, - {BCM43340_CHIP_ID, 2, DONT_CARE, FALSE, "bcm43341b0_ag", ""}, - {BCM43341_CHIP_ID, 2, DONT_CARE, FALSE, "bcm43341b0_ag", ""}, - {BCM4324_CHIP_ID, 5, DONT_CARE, FALSE, "bcm43241b4_ag", "ap62x2"}, - {BCM4335_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4339a0_ag", "AP6335"}, - {BCM4339_CHIP_ID, 1, DONT_CARE, FALSE, "bcm4339a0_ag", "AP6335"}, - {BCM4345_CHIP_ID, 6, DONT_CARE, FALSE, "bcm43455c0_ag", "ap6255"}, - {BCM43454_CHIP_ID, 6, DONT_CARE, FALSE, "bcm43455c0_ag", ""}, - {BCM4345_CHIP_ID, 9, DONT_CARE, FALSE, "bcm43456c5_ag", "ap6256"}, - {BCM43454_CHIP_ID, 9, DONT_CARE, FALSE, "bcm43456c5_ag", ""}, - {BCM4354_CHIP_ID, 1, DONT_CARE, FALSE, "bcm4354a1_ag", "ap6354"}, - {BCM4354_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4356a2_ag", "ap6356"}, - {BCM4356_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4356a2_ag", "ap6356"}, - {BCM4371_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4356a2_ag", ""}, - {BCM43569_CHIP_ID, 3, DONT_CARE, FALSE, "bcm4358a3_ag", ""}, - {BCM4359_CHIP_ID, 5, DONT_CARE, FALSE, "bcm4359b1_ag", ""}, - {BCM4359_CHIP_ID, 9, DONT_CARE, FALSE, "bcm4359c0_ag", "ap6398s"}, - {BCM4362_CHIP_ID, 0, DONT_CARE, TRUE, "bcm43752a0_ag", ""}, + {BCM43362_CHIP_ID, 0, DONT_CARE, "bcm40181a0", ""}, + {BCM43362_CHIP_ID, 1, DONT_CARE, "bcm40181a2", "ap6181"}, + {BCM4330_CHIP_ID, 4, FW_TYPE_G, "RK903b2", ""}, + {BCM4330_CHIP_ID, 4, FW_TYPE_AG, "RK903_ag", "AP6330"}, + {BCM43430_CHIP_ID, 0, DONT_CARE, "bcm43438a0", "ap6212"}, + {BCM43430_CHIP_ID, 1, DONT_CARE, "bcm43438a1", "ap6212a"}, + {BCM43430_CHIP_ID, 2, DONT_CARE, "bcm43436b0", "ap6236"}, + {BCM43012_CHIP_ID, 1, FW_TYPE_G, "bcm43013b0", ""}, + {BCM43012_CHIP_ID, 1, FW_TYPE_AG, "bcm43013c0_ag", ""}, + {BCM43012_CHIP_ID, 2, DONT_CARE, "bcm43013c1_ag", ""}, + {BCM4334_CHIP_ID, 3, DONT_CARE, "bcm4334b1_ag", ""}, + {BCM43340_CHIP_ID, 2, DONT_CARE, "bcm43341b0_ag", ""}, + {BCM43341_CHIP_ID, 2, DONT_CARE, "bcm43341b0_ag", ""}, + {BCM4324_CHIP_ID, 5, DONT_CARE, "bcm43241b4_ag", "ap62x2"}, + {BCM4335_CHIP_ID, 2, DONT_CARE, "bcm4339a0_ag", "AP6335"}, + {BCM4339_CHIP_ID, 1, DONT_CARE, "bcm4339a0_ag", "AP6335"}, + {BCM4345_CHIP_ID, 6, DONT_CARE, "bcm43455c0_ag", "ap6255"}, + {BCM43454_CHIP_ID, 6, DONT_CARE, "bcm43455c0_ag", ""}, + {BCM4345_CHIP_ID, 9, DONT_CARE, "bcm43456c5_ag", "ap6256"}, + {BCM43454_CHIP_ID, 9, DONT_CARE, "bcm43456c5_ag", ""}, + {BCM4354_CHIP_ID, 1, DONT_CARE, "bcm4354a1_ag", "ap6354"}, + {BCM4354_CHIP_ID, 2, DONT_CARE, "bcm4356a2_ag", "ap6356"}, + {BCM4356_CHIP_ID, 2, DONT_CARE, "bcm4356a2_ag", "ap6356"}, + {BCM4371_CHIP_ID, 2, DONT_CARE, "bcm4356a2_ag", ""}, + {BCM43569_CHIP_ID, 3, DONT_CARE, "bcm4358a3_ag", ""}, + {BCM4359_CHIP_ID, 5, DONT_CARE, "bcm4359b1_ag", ""}, + {BCM4359_CHIP_ID, 9, DONT_CARE, "bcm4359c0_ag", "ap6398s"}, #endif #ifdef BCMPCIE - {BCM4354_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4356a2_pcie_ag", ""}, - {BCM4356_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4356a2_pcie_ag", ""}, - {BCM4359_CHIP_ID, 9, DONT_CARE, FALSE, "bcm4359c0_pcie_ag", ""}, - {BCM4362_CHIP_ID, 0, DONT_CARE, TRUE, "bcm43752a0_pcie_ag", ""}, + {BCM4354_CHIP_ID, 2, DONT_CARE, "bcm4356a2_pcie_ag", ""}, + {BCM4356_CHIP_ID, 2, DONT_CARE, "bcm4356a2_pcie_ag", ""}, + {BCM4359_CHIP_ID, 9, DONT_CARE, "bcm4359c0_pcie_ag", ""}, #endif #ifdef BCMDBUS - {BCM43143_CHIP_ID, 2, DONT_CARE, FALSE, "bcm43143b0", ""}, - {BCM43242_CHIP_ID, 1, DONT_CARE, FALSE, "bcm43242a1_ag", ""}, - {BCM43569_CHIP_ID, 2, DONT_CARE, FALSE, "bcm4358u_ag", ""}, + {BCM43143_CHIP_ID, 2, DONT_CARE, "bcm43143b0", ""}, + {BCM43242_CHIP_ID, 1, DONT_CARE, "bcm43242a1_ag", ""}, + {BCM43569_CHIP_ID, 2, DONT_CARE, "bcm4358u_ag", ""}, #endif }; +void +dhd_conf_free_chip_nv_path_list(wl_chip_nv_path_list_ctrl_t *chip_nv_list) +{ + CONFIG_TRACE("called\n"); + + if (chip_nv_list->m_chip_nv_path_head) { + CONFIG_TRACE("Free %p\n", chip_nv_list->m_chip_nv_path_head); + kfree(chip_nv_list->m_chip_nv_path_head); + } + chip_nv_list->count = 0; +} + #ifdef BCMSDIO void dhd_conf_free_mac_list(wl_mac_list_ctrl_t *mac_list) { int i; - CONFIG_TRACE(("%s called\n", __FUNCTION__)); + CONFIG_TRACE("called\n"); if (mac_list->m_mac_list_head) { for (i=0; icount; i++) { if (mac_list->m_mac_list_head[i].mac) { - CONFIG_TRACE(("%s Free mac %p\n", __FUNCTION__, mac_list->m_mac_list_head[i].mac)); + CONFIG_TRACE("Free mac %p\n", mac_list->m_mac_list_head[i].mac); kfree(mac_list->m_mac_list_head[i].mac); } } - CONFIG_TRACE(("%s Free m_mac_list_head %p\n", __FUNCTION__, mac_list->m_mac_list_head)); + CONFIG_TRACE("Free m_mac_list_head %p\n", mac_list->m_mac_list_head); kfree(mac_list->m_mac_list_head); } mac_list->count = 0; } -void -dhd_conf_free_chip_nv_path_list(wl_chip_nv_path_list_ctrl_t *chip_nv_list) -{ - CONFIG_TRACE(("%s called\n", __FUNCTION__)); - - if (chip_nv_list->m_chip_nv_path_head) { - CONFIG_TRACE(("%s Free %p\n", __FUNCTION__, chip_nv_list->m_chip_nv_path_head)); - kfree(chip_nv_list->m_chip_nv_path_head); - } - chip_nv_list->count = 0; -} - #if defined(HW_OOB) || defined(FORCE_WOWLAN) void dhd_conf_set_hw_oob_intr(bcmsdh_info_t *sdh, uint chip) @@ -140,7 +166,7 @@ dhd_conf_set_hw_oob_intr(bcmsdh_info_t *sdh, uint chip) uint32 gpiocontrol, addr; if (CHIPID(chip) == BCM43362_CHIP_ID) { - printf("%s: Enable HW OOB for 43362\n", __FUNCTION__); + CONFIG_MSG("Enable HW OOB for 43362\n"); addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, gpiocontrol); gpiocontrol = bcmsdh_reg_read(sdh, addr, 4); gpiocontrol |= 0x2; @@ -181,12 +207,12 @@ dhd_conf_set_blksize(bcmsdh_info_t *sdh) bcmsdh_iovar_op(sdh, "sd_blocksize", &fn, sizeof(int32), &cur_blksize, sizeof(int32), FALSE); if (cur_blksize != blksize) { - printf("%s: fn=%d, blksize=%d, cur_blksize=%d\n", __FUNCTION__, + CONFIG_MSG("fn=%d, blksize=%d, cur_blksize=%d\n", fn, blksize, cur_blksize); blksize |= (fn<<16); if (bcmsdh_iovar_op(sdh, "sd_blocksize", NULL, 0, &blksize, sizeof(blksize), TRUE) != BCME_OK) { - DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize")); + CONFIG_ERROR("fail on get sd_blocksize"); err = -1; } } @@ -205,13 +231,13 @@ dhd_conf_get_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, uint8 *mac) uint8 *cis; if (!(cis = MALLOC(dhd->osh, SBSDIO_CIS_SIZE_LIMIT))) { - CONFIG_ERROR(("%s: cis malloc failed\n", __FUNCTION__)); + CONFIG_ERROR("cis malloc failed\n"); return err; } bzero(cis, SBSDIO_CIS_SIZE_LIMIT); if ((err = bcmsdh_cis_read(sdh, 0, cis, SBSDIO_CIS_SIZE_LIMIT))) { - CONFIG_ERROR(("%s: cis read err %d\n", __FUNCTION__, err)); + CONFIG_ERROR("cis read err %d\n", err); MFREE(dhd->osh, cis, SBSDIO_CIS_SIZE_LIMIT); return err; } @@ -234,8 +260,8 @@ dhd_conf_get_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, uint8 *mac) if (tpl_link == 0xff) break; if (config_msg_level & CONFIG_TRACE_LEVEL) { - printf("%s: tpl_code=0x%02x, tpl_link=0x%02x, tag=0x%02x\n", - __FUNCTION__, tpl_code, tpl_link, *ptr); + CONFIG_MSG("tpl_code=0x%02x, tpl_link=0x%02x, tag=0x%02x\n", + tpl_code, tpl_link, *ptr); printk("%s: value:", __FUNCTION__); for (i=0; i= mac_range[j].nic_start && nic <= mac_range[j].nic_end) { strcpy(name_ptr, mac_list[i].name); - printf("%s: matched oui=0x%06X, nic=0x%06X\n", - __FUNCTION__, oui, nic); - printf("%s: fw_path=%s\n", __FUNCTION__, fw_path); + CONFIG_MSG("matched oui=0x%06X, nic=0x%06X\n", oui, nic); + CONFIG_MSG("fw_path=%s\n", fw_path); return; } } @@ -358,7 +384,8 @@ dhd_conf_set_fw_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, char *fw_path) } void -dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, char *nv_path) +dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, + char *nv_path) { int i, j; uint8 mac[6]={0}; @@ -374,7 +401,7 @@ dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, char *nv_path) return; if (dhd_conf_get_mac(dhd, sdh, mac)) { - CONFIG_ERROR(("%s: Can not read MAC address\n", __FUNCTION__)); + CONFIG_ERROR("Can not read MAC address\n"); return; } oui = (mac[0] << 16) | (mac[1] << 8) | (mac[2]); @@ -395,9 +422,8 @@ dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, char *nv_path) if (oui == mac_range[j].oui) { if (nic >= mac_range[j].nic_start && nic <= mac_range[j].nic_end) { strcpy(pnv_name, mac_list[i].name); - printf("%s: matched oui=0x%06X, nic=0x%06X\n", - __FUNCTION__, oui, nic); - printf("%s: nv_path=%s\n", __FUNCTION__, nv_path); + CONFIG_MSG("matched oui=0x%06X, nic=0x%06X\n", oui, nic); + CONFIG_MSG("nv_path=%s\n", nv_path); return; } } @@ -407,21 +433,40 @@ dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, char *nv_path) #endif void -dhd_conf_free_country_list(conf_country_list_t *country_list) +dhd_conf_free_country_list(struct dhd_conf *conf) { - int i; + country_list_t *country = conf->country_head; + int count = 0; - CONFIG_TRACE(("%s called\n", __FUNCTION__)); - for (i=0; icount; i++) { - if (country_list->cspec[i]) { - CONFIG_TRACE(("%s Free cspec %p\n", __FUNCTION__, country_list->cspec[i])); - kfree(country_list->cspec[i]); - } + CONFIG_TRACE("called\n"); + while (country) { + CONFIG_TRACE("Free cspec %s\n", country->cspec.country_abbrev); + conf->country_head = country->next; + kfree(country); + country = conf->country_head; + count++; } - country_list->count = 0; + CONFIG_TRACE("%d country released\n", count); } void +dhd_conf_free_mchan_list(struct dhd_conf *conf) +{ + mchan_params_t *mchan = conf->mchan; + int count = 0; + + CONFIG_TRACE("called\n"); + while (mchan) { + CONFIG_TRACE("Free cspec %p\n", mchan); + conf->mchan = mchan->next; + kfree(mchan); + mchan = conf->mchan; + count++; + } + CONFIG_TRACE("%d mchan released\n", count); +} + +int dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path) { int fw_type, ag_type; @@ -438,8 +483,8 @@ dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path) if (fw_path[0] == '\0') #endif { - printf("firmware path is null\n"); - return; + CONFIG_MSG("firmware path is null\n"); + return 0; } } #ifndef FW_PATH_AUTO_SELECT @@ -474,10 +519,10 @@ dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path) else fw_type = FW_TYPE_STA; - for (i = 0; i < sizeof(chip_name_map)/sizeof(chip_name_map[0]); i++) { + for (i = 0; i < sizeof(chip_name_map)/sizeof(chip_name_map[0]); i++) { const cihp_name_map_t* row = &chip_name_map[i]; if (row->chip == chip && row->chiprev == chiprev && - (row->ag_type == ag_type || row->ag_type == DONT_CARE)) { + (row->ag_type == ag_type || row->ag_type == DONT_CARE)) { strcpy(name_ptr, "fw_"); strcat(fw_path, row->chip_name); #ifdef BCMUSBDEV_COMPOSITE @@ -500,11 +545,12 @@ dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path) dhd->conf->fw_type = fw_type; - CONFIG_TRACE(("%s: firmware_path=%s\n", __FUNCTION__, fw_path)); + CONFIG_TRACE("firmware_path=%s\n", fw_path); + return ag_type; } void -dhd_conf_set_clm_name_by_chip(dhd_pub_t *dhd, char *clm_path) +dhd_conf_set_clm_name_by_chip(dhd_pub_t *dhd, char *clm_path, int ag_type) { uint chip, chiprev; int i; @@ -514,7 +560,7 @@ dhd_conf_set_clm_name_by_chip(dhd_pub_t *dhd, char *clm_path) chiprev = dhd->conf->chiprev; if (clm_path[0] == '\0') { - printf("clm path is null\n"); + CONFIG_MSG("clm path is null\n"); return; } @@ -529,20 +575,21 @@ dhd_conf_set_clm_name_by_chip(dhd_pub_t *dhd, char *clm_path) } name_ptr = &clm_path[i]; - for (i = 0; i < sizeof(chip_name_map)/sizeof(chip_name_map[0]); i++) { + for (i = 0; i < sizeof(chip_name_map)/sizeof(chip_name_map[0]); i++) { const cihp_name_map_t* row = &chip_name_map[i]; - if (row->chip == chip && row->chiprev == chiprev && row->clm) { + if (row->chip == chip && row->chiprev == chiprev && + (row->ag_type == ag_type || row->ag_type == DONT_CARE)) { strcpy(name_ptr, "clm_"); strcat(clm_path, row->chip_name); strcat(clm_path, ".blob"); } } - CONFIG_TRACE(("%s: clm_path=%s\n", __FUNCTION__, clm_path)); + CONFIG_TRACE("clm_path=%s\n", clm_path); } void -dhd_conf_set_nv_name_by_chip(dhd_pub_t *dhd, char *nv_path) +dhd_conf_set_nv_name_by_chip(dhd_pub_t *dhd, char *nv_path, int ag_type) { uint chip, chiprev; int i; @@ -557,7 +604,7 @@ dhd_conf_set_nv_name_by_chip(dhd_pub_t *dhd, char *nv_path) if (nv_path[0] == '\0') #endif { - printf("nvram path is null\n"); + CONFIG_MSG("nvram path is null\n"); return; } } @@ -573,9 +620,11 @@ dhd_conf_set_nv_name_by_chip(dhd_pub_t *dhd, char *nv_path) } name_ptr = &nv_path[i]; - for (i = 0; i < sizeof(chip_name_map)/sizeof(chip_name_map[0]); i++) { + for (i = 0; i < sizeof(chip_name_map)/sizeof(chip_name_map[0]); i++) { const cihp_name_map_t* row = &chip_name_map[i]; - if (row->chip == chip && row->chiprev == chiprev && strlen(row->module_name)) { + if (row->chip == chip && row->chiprev == chiprev && + (row->ag_type == ag_type || row->ag_type == DONT_CARE) && + strlen(row->module_name)) { strcpy(name_ptr, "nvram_"); strcat(name_ptr, row->module_name); #ifdef BCMUSBDEV_COMPOSITE @@ -593,16 +642,16 @@ dhd_conf_set_nv_name_by_chip(dhd_pub_t *dhd, char *nv_path) } } - CONFIG_TRACE(("%s: nvram_path=%s\n", __FUNCTION__, nv_path)); + CONFIG_TRACE("nvram_path=%s\n", nv_path); } void -dhd_conf_set_path(dhd_pub_t *dhd, char *dst_name, char *dst_path, char *src_path) +dhd_conf_copy_path(dhd_pub_t *dhd, char *dst_name, char *dst_path, char *src_path) { int i; if (src_path[0] == '\0') { - printf("src_path is null\n"); + CONFIG_MSG("src_path is null\n"); return; } else strcpy(dst_path, src_path); @@ -618,7 +667,7 @@ dhd_conf_set_path(dhd_pub_t *dhd, char *dst_name, char *dst_path, char *src_path } strcpy(&dst_path[i], dst_name); - CONFIG_TRACE(("%s: dst_path=%s\n", __FUNCTION__, dst_path)); + CONFIG_TRACE("dst_path=%s\n", dst_path); } #ifdef CONFIG_PATH_AUTO_SELECT @@ -633,7 +682,7 @@ dhd_conf_set_conf_name_by_chip(dhd_pub_t *dhd, char *conf_path) chiprev = dhd->conf->chiprev; if (conf_path[0] == '\0') { - printf("config path is null\n"); + CONFIG_MSG("config path is null\n"); return; } @@ -657,10 +706,45 @@ dhd_conf_set_conf_name_by_chip(dhd_pub_t *dhd, char *conf_path) } } - CONFIG_TRACE(("%s: config_path=%s\n", __FUNCTION__, conf_path)); + CONFIG_TRACE("config_path=%s\n", conf_path); } #endif +void +dhd_conf_set_path_params(dhd_pub_t *dhd, void *sdh, + char *fw_path, char *nv_path) +{ + int ag_type = DONT_CARE; + + /* External conf takes precedence if specified */ + dhd_conf_preinit(dhd); + + if (dhd->conf_path[0] == '\0') { + dhd_conf_copy_path(dhd, "config.txt", dhd->conf_path, nv_path); + } + if (dhd->clm_path[0] == '\0') { + dhd_conf_copy_path(dhd, "clm.blob", dhd->clm_path, fw_path); + } +#ifdef CONFIG_PATH_AUTO_SELECT + dhd_conf_set_conf_name_by_chip(dhd, dhd->conf_path); +#endif + + dhd_conf_read_config(dhd, dhd->conf_path); + + ag_type = dhd_conf_set_fw_name_by_chip(dhd, fw_path); + dhd_conf_set_nv_name_by_chip(dhd, nv_path, ag_type); + dhd_conf_set_clm_name_by_chip(dhd, dhd->clm_path, ag_type); +#ifdef BCMSDIO + dhd_conf_set_fw_name_by_mac(dhd, (bcmsdh_info_t *)sdh, fw_path); + dhd_conf_set_nv_name_by_mac(dhd, (bcmsdh_info_t *)sdh, nv_path); +#endif + + CONFIG_MSG("Final fw_path=%s\n", fw_path); + CONFIG_MSG("Final nv_path=%s\n", nv_path); + CONFIG_MSG("Final clm_path=%s\n", dhd->clm_path); + CONFIG_MSG("Final conf_path=%s\n", dhd->conf_path); +} + int dhd_conf_set_intiovar(dhd_pub_t *dhd, uint cmd, char *name, int val, int def, bool down) @@ -671,17 +755,17 @@ dhd_conf_set_intiovar(dhd_pub_t *dhd, uint cmd, char *name, int val, if (val >= def) { if (down) { if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, NULL, 0, TRUE, 0)) < 0) - CONFIG_ERROR(("%s: WLC_DOWN setting failed %d\n", __FUNCTION__, ret)); + CONFIG_ERROR("WLC_DOWN setting failed %d\n", ret); } if (cmd == WLC_SET_VAR) { - CONFIG_TRACE(("%s: set %s %d\n", __FUNCTION__, name, val)); + CONFIG_TRACE("set %s %d\n", name, val); bcm_mkiovar(name, (char *)&val, sizeof(val), iovbuf, sizeof(iovbuf)); if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) - CONFIG_ERROR(("%s: %s setting failed %d\n", __FUNCTION__, name, ret)); + CONFIG_ERROR("%s setting failed %d\n", name, ret); } else { - CONFIG_TRACE(("%s: set %s %d %d\n", __FUNCTION__, name, cmd, val)); + CONFIG_TRACE("set %s %d %d\n", name, cmd, val); if ((ret = dhd_wl_ioctl_cmd(dhd, cmd, &val, sizeof(val), TRUE, 0)) < 0) - CONFIG_ERROR(("%s: %s setting failed %d\n", __FUNCTION__, name, ret)); + CONFIG_ERROR("%s setting failed %d\n", name, ret); } } @@ -689,31 +773,37 @@ dhd_conf_set_intiovar(dhd_pub_t *dhd, uint cmd, char *name, int val, } int -dhd_conf_set_bufiovar(dhd_pub_t *dhd, uint cmd, char *name, char *buf, - int len, bool down) +dhd_conf_set_bufiovar(dhd_pub_t *dhd, int ifidx, uint cmd, char *name, + char *buf, int len, bool down) { char iovbuf[WLC_IOCTL_SMLEN]; + s32 iovar_len; int ret = -1; if (down) { - if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, NULL, 0, TRUE, 0)) < 0) - CONFIG_ERROR(("%s: WLC_DOWN setting failed %d\n", __FUNCTION__, ret)); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, NULL, 0, TRUE, ifidx)) < 0) + CONFIG_ERROR("WLC_DOWN setting failed %d\n", ret); } if (cmd == WLC_SET_VAR) { - bcm_mkiovar(name, buf, len, iovbuf, sizeof(iovbuf)); - if ((ret = dhd_wl_ioctl_cmd(dhd, cmd, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) - CONFIG_ERROR(("%s: %s setting failed %d\n", __FUNCTION__, name, ret)); + iovar_len = bcm_mkiovar(name, buf, len, iovbuf, sizeof(iovbuf)); + if (iovar_len > 0) + ret = dhd_wl_ioctl_cmd(dhd, cmd, iovbuf, iovar_len, TRUE, ifidx); + else + ret = BCME_BUFTOOSHORT; + if (ret < 0) + CONFIG_ERROR("%s setting failed %d, len=%d\n", name, ret, len); } else { - if ((ret = dhd_wl_ioctl_cmd(dhd, cmd, buf, len, TRUE, 0)) < 0) - CONFIG_ERROR(("%s: %s setting failed %d\n", __FUNCTION__, name, ret)); + if ((ret = dhd_wl_ioctl_cmd(dhd, cmd, buf, len, TRUE, ifidx)) < 0) + CONFIG_ERROR("%s setting failed %d\n", name, ret); } return ret; } int -dhd_conf_get_iovar(dhd_pub_t *dhd, int cmd, char *name, char *buf, int len, int ifidx) +dhd_conf_get_iovar(dhd_pub_t *dhd, int ifidx, int cmd, char *name, + char *buf, int len) { char iovbuf[WLC_IOCTL_SMLEN]; int ret = -1; @@ -724,21 +814,21 @@ dhd_conf_get_iovar(dhd_pub_t *dhd, int cmd, char *name, char *buf, int len, int if (!ret) { memcpy(buf, iovbuf, len); } else { - CONFIG_ERROR(("%s: get iovar %s failed %d\n", __FUNCTION__, name, ret)); + CONFIG_ERROR("get iovar %s failed %d\n", name, ret); } } else { - CONFIG_ERROR(("%s: mkiovar %s failed\n", __FUNCTION__, name)); + CONFIG_ERROR("mkiovar %s failed\n", name); } } else { ret = dhd_wl_ioctl_cmd(dhd, cmd, buf, len, FALSE, 0); if (ret < 0) - CONFIG_ERROR(("%s: get iovar %s failed %d\n", __FUNCTION__, name, ret)); + CONFIG_ERROR("get iovar %s failed %d\n", name, ret); } return ret; } -uint +int dhd_conf_get_band(dhd_pub_t *dhd) { int band = -1; @@ -746,7 +836,7 @@ dhd_conf_get_band(dhd_pub_t *dhd) if (dhd && dhd->conf) band = dhd->conf->band; else - CONFIG_ERROR(("%s: dhd or conf is NULL\n", __FUNCTION__)); + CONFIG_ERROR("dhd or conf is NULL\n"); return band; } @@ -758,8 +848,9 @@ dhd_conf_get_country(dhd_pub_t *dhd, wl_country_t *cspec) memset(cspec, 0, sizeof(wl_country_t)); bcm_mkiovar("country", NULL, 0, (char*)cspec, sizeof(wl_country_t)); - if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cspec, sizeof(wl_country_t), FALSE, 0)) < 0) - CONFIG_ERROR(("%s: country code getting failed %d\n", __FUNCTION__, bcmerror)); + if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cspec, sizeof(wl_country_t), + FALSE, 0)) < 0) + CONFIG_ERROR("country code getting failed %d\n", bcmerror); return bcmerror; } @@ -767,20 +858,28 @@ dhd_conf_get_country(dhd_pub_t *dhd, wl_country_t *cspec) int dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec) { - int bcmerror = -1, i; + int bcmerror = -1; struct dhd_conf *conf = dhd->conf; - conf_country_list_t *country_list = &conf->country_list; + country_list_t *country = conf->country_head; - for (i = 0; i < country_list->count; i++) { - if (!strncmp(cspec->country_abbrev, country_list->cspec[i]->country_abbrev, 2)) { - memcpy(cspec->ccode, country_list->cspec[i]->ccode, WLC_CNTRY_BUF_SZ); - cspec->rev = country_list->cspec[i]->rev; + while (country != NULL) { + if (!strncmp("**", country->cspec.country_abbrev, 2)) { + memcpy(cspec->ccode, country->cspec.ccode, WLC_CNTRY_BUF_SZ); + cspec->rev = country->cspec.rev; bcmerror = 0; + break; + } else if (!strncmp(cspec->country_abbrev, + country->cspec.country_abbrev, 2)) { + memcpy(cspec->ccode, country->cspec.ccode, WLC_CNTRY_BUF_SZ); + cspec->rev = country->cspec.rev; + bcmerror = 0; + break; } + country = country->next; } if (!bcmerror) - printf("%s: %s/%d\n", __FUNCTION__, cspec->ccode, cspec->rev); + CONFIG_MSG("%s/%d\n", cspec->ccode, cspec->rev); return bcmerror; } @@ -792,10 +891,12 @@ dhd_conf_set_country(dhd_pub_t *dhd, wl_country_t *cspec) memset(&dhd->dhd_cspec, 0, sizeof(wl_country_t)); - printf("%s: set country %s, revision %d\n", __FUNCTION__, cspec->ccode, cspec->rev); - dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "country", (char *)cspec, sizeof(wl_country_t), FALSE); + CONFIG_MSG("set country %s, revision %d\n", cspec->ccode, cspec->rev); + bcmerror = dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "country", (char *)cspec, + sizeof(wl_country_t), FALSE); dhd_conf_get_country(dhd, cspec); - printf("Country code: %s (%s/%d)\n", cspec->country_abbrev, cspec->ccode, cspec->rev); + CONFIG_MSG("Country code: %s (%s/%d)\n", + cspec->country_abbrev, cspec->ccode, cspec->rev); return bcmerror; } @@ -804,7 +905,7 @@ int dhd_conf_fix_country(dhd_pub_t *dhd) { int bcmerror = -1; - uint band; + int band; wl_uint32_list_t *list; u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)]; wl_country_t cspec; @@ -816,16 +917,17 @@ dhd_conf_fix_country(dhd_pub_t *dhd) memset(valid_chan_list, 0, sizeof(valid_chan_list)); list = (wl_uint32_list_t *)(void *) valid_chan_list; list->count = htod32(WL_NUMCHANNELS); - if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VALID_CHANNELS, valid_chan_list, sizeof(valid_chan_list), FALSE, 0)) < 0) { - CONFIG_ERROR(("%s: get channels failed with %d\n", __FUNCTION__, bcmerror)); + if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VALID_CHANNELS, valid_chan_list, + sizeof(valid_chan_list), FALSE, 0)) < 0) { + CONFIG_ERROR("get channels failed with %d\n", bcmerror); } band = dhd_conf_get_band(dhd); - if (bcmerror || ((band==WLC_BAND_AUTO || band==WLC_BAND_2G) && + if (bcmerror || ((band==WLC_BAND_AUTO || band==WLC_BAND_2G || band==-1) && dtoh32(list->count)<11)) { - CONFIG_ERROR(("%s: bcmerror=%d, # of channels %d\n", - __FUNCTION__, bcmerror, dtoh32(list->count))); + CONFIG_ERROR("bcmerror=%d, # of channels %d\n", + bcmerror, dtoh32(list->count)); dhd_conf_map_country_list(dhd, &dhd->conf->cspec); if ((bcmerror = dhd_conf_set_country(dhd, &dhd->conf->cspec)) < 0) { strcpy(cspec.country_abbrev, "US"); @@ -854,7 +956,7 @@ dhd_conf_match_channel(dhd_pub_t *dhd, uint32 channel) } } else { match = true; - CONFIG_ERROR(("%s: dhd or conf is NULL\n", __FUNCTION__)); + CONFIG_ERROR("dhd or conf is NULL\n"); } return match; @@ -870,24 +972,105 @@ dhd_conf_set_roam(dhd_pub_t *dhd) dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "roam_off", dhd->conf->roam_off, 0, FALSE); if (!conf->roam_off || !conf->roam_off_suspend) { - printf("%s: set roam_trigger %d\n", __FUNCTION__, conf->roam_trigger[0]); - dhd_conf_set_bufiovar(dhd, WLC_SET_ROAM_TRIGGER, "WLC_SET_ROAM_TRIGGER", - (char *)conf->roam_trigger, sizeof(conf->roam_trigger), FALSE); + CONFIG_MSG("set roam_trigger %d\n", conf->roam_trigger[0]); + dhd_conf_set_bufiovar(dhd, 0, WLC_SET_ROAM_TRIGGER, "WLC_SET_ROAM_TRIGGER", + (char *)conf->roam_trigger, sizeof(conf->roam_trigger), FALSE); - printf("%s: set roam_scan_period %d\n", __FUNCTION__, conf->roam_scan_period[0]); - dhd_conf_set_bufiovar(dhd, WLC_SET_ROAM_SCAN_PERIOD, "WLC_SET_ROAM_SCAN_PERIOD", - (char *)conf->roam_scan_period, sizeof(conf->roam_scan_period), FALSE); + CONFIG_MSG("set roam_scan_period %d\n", conf->roam_scan_period[0]); + dhd_conf_set_bufiovar(dhd, 0, WLC_SET_ROAM_SCAN_PERIOD, "WLC_SET_ROAM_SCAN_PERIOD", + (char *)conf->roam_scan_period, sizeof(conf->roam_scan_period), FALSE); - printf("%s: set roam_delta %d\n", __FUNCTION__, conf->roam_delta[0]); - dhd_conf_set_bufiovar(dhd, WLC_SET_ROAM_DELTA, "WLC_SET_ROAM_DELTA", - (char *)conf->roam_delta, sizeof(conf->roam_delta), FALSE); + CONFIG_MSG("set roam_delta %d\n", conf->roam_delta[0]); + dhd_conf_set_bufiovar(dhd, 0, WLC_SET_ROAM_DELTA, "WLC_SET_ROAM_DELTA", + (char *)conf->roam_delta, sizeof(conf->roam_delta), FALSE); - dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "fullroamperiod", dhd->conf->fullroamperiod, 1, FALSE); + dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "fullroamperiod", + dhd->conf->fullroamperiod, 1, FALSE); } return bcmerror; } +void +dhd_conf_add_to_eventbuffer(struct eventmsg_buf *ev, u16 event, bool set) +{ + if (!ev || (event > WLC_E_LAST)) + return; + + if (ev->num < MAX_EVENT_BUF_NUM) { + ev->event[ev->num].type = event; + ev->event[ev->num].set = set; + ev->num++; + } else { + CONFIG_ERROR("evenbuffer doesn't support > %u events. Update" + " the define MAX_EVENT_BUF_NUM \n", MAX_EVENT_BUF_NUM); + ASSERT(0); + } +} + +s32 +dhd_conf_apply_eventbuffer(dhd_pub_t *dhd, eventmsg_buf_t *ev) +{ + char eventmask[WL_EVENTING_MASK_LEN]; + int i, ret = 0; + + if (!ev || (!ev->num)) + return -EINVAL; + + /* Read event_msgs mask */ + ret = dhd_conf_get_iovar(dhd, 0, WLC_GET_VAR, "event_msgs", eventmask, + sizeof(eventmask)); + if (unlikely(ret)) { + CONFIG_ERROR("Get event_msgs error (%d)\n", ret); + goto exit; + } + + /* apply the set bits */ + for (i = 0; i < ev->num; i++) { + if (ev->event[i].set) + setbit(eventmask, ev->event[i].type); + else + clrbit(eventmask, ev->event[i].type); + } + + /* Write updated Event mask */ + ret = dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "event_msgs", eventmask, + sizeof(eventmask), FALSE); + if (unlikely(ret)) { + CONFIG_ERROR("Set event_msgs error (%d)\n", ret); + } + +exit: + return ret; +} + +int +dhd_conf_enable_roam_offload(dhd_pub_t *dhd, int enable) +{ + int err; + eventmsg_buf_t ev_buf; + + if (dhd->conf->roam_off_suspend) + return 0; + + err = dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "roam_offload", enable, 0, FALSE); + if (err) + return err; + + bzero(&ev_buf, sizeof(eventmsg_buf_t)); + dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_PSK_SUP, !enable); + dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_REQ_IE, !enable); + dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_RESP_IE, !enable); + dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_REASSOC, !enable); + dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_JOIN, !enable); + dhd_conf_add_to_eventbuffer(&ev_buf, WLC_E_ROAM, !enable); + err = dhd_conf_apply_eventbuffer(dhd, &ev_buf); + + CONFIG_TRACE("roam_offload %d\n", enable); + + return err; +} + void dhd_conf_set_bw_cap(dhd_pub_t *dhd) { @@ -900,21 +1083,23 @@ dhd_conf_set_bw_cap(dhd_pub_t *dhd) memset(¶m, 0, sizeof(param)); param.band = WLC_BAND_2G; param.bw_cap = (uint)dhd->conf->bw_cap[0]; - printf("%s: set bw_cap 2g 0x%x\n", __FUNCTION__, param.bw_cap); - dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "bw_cap", (char *)¶m, sizeof(param), TRUE); + CONFIG_MSG("set bw_cap 2g 0x%x\n", param.bw_cap); + dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "bw_cap", (char *)¶m, + sizeof(param), FALSE); } if (dhd->conf->bw_cap[1] >= 0) { memset(¶m, 0, sizeof(param)); param.band = WLC_BAND_5G; param.bw_cap = (uint)dhd->conf->bw_cap[1]; - printf("%s: set bw_cap 5g 0x%x\n", __FUNCTION__, param.bw_cap); - dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "bw_cap", (char *)¶m, sizeof(param), TRUE); + CONFIG_MSG("set bw_cap 5g 0x%x\n", param.bw_cap); + dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "bw_cap", (char *)¶m, + sizeof(param), FALSE); } } void -dhd_conf_get_wme(dhd_pub_t *dhd, int mode, edcf_acparam_t *acp) +dhd_conf_get_wme(dhd_pub_t *dhd, int ifidx, int mode, edcf_acparam_t *acp) { int bcmerror = -1; char iovbuf[WLC_IOCTL_SMLEN]; @@ -930,42 +1115,40 @@ dhd_conf_get_wme(dhd_pub_t *dhd, int mode, edcf_acparam_t *acp) bcm_mkiovar("wme_ac_sta", NULL, 0, iovbuf, sizeof(iovbuf)); else bcm_mkiovar("wme_ac_ap", NULL, 0, iovbuf, sizeof(iovbuf)); - if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0)) < 0) { - CONFIG_ERROR(("%s: wme_ac_sta getting failed %d\n", __FUNCTION__, bcmerror)); + if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), + FALSE, ifidx)) < 0) { + CONFIG_ERROR("wme_ac_sta getting failed %d\n", bcmerror); return; } memcpy((char*)acp, iovbuf, sizeof(edcf_acparam_t)*AC_COUNT); acparam = &acp[AC_BK]; - CONFIG_TRACE(("%s: BK: aci %d aifsn %d ecwmin %d ecwmax %d txop 0x%x\n", - __FUNCTION__, + CONFIG_TRACE("BK: aci %d aifsn %d ecwmin %d ecwmax %d txop 0x%x\n", acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK, acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT, - acparam->TXOP)); + acparam->TXOP); acparam = &acp[AC_BE]; - CONFIG_TRACE(("%s: BE: aci %d aifsn %d ecwmin %d ecwmax %d txop 0x%x\n", - __FUNCTION__, + CONFIG_TRACE("BE: aci %d aifsn %d ecwmin %d ecwmax %d txop 0x%x\n", acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK, acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT, - acparam->TXOP)); + acparam->TXOP); acparam = &acp[AC_VI]; - CONFIG_TRACE(("%s: VI: aci %d aifsn %d ecwmin %d ecwmax %d txop 0x%x\n", - __FUNCTION__, + CONFIG_TRACE("VI: aci %d aifsn %d ecwmin %d ecwmax %d txop 0x%x\n", acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK, acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT, - acparam->TXOP)); + acparam->TXOP); acparam = &acp[AC_VO]; - CONFIG_TRACE(("%s: VO: aci %d aifsn %d ecwmin %d ecwmax %d txop 0x%x\n", - __FUNCTION__, + CONFIG_TRACE("VO: aci %d aifsn %d ecwmin %d ecwmax %d txop 0x%x\n", acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK, acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT, - acparam->TXOP)); + acparam->TXOP); return; } void -dhd_conf_update_wme(dhd_pub_t *dhd, int mode, edcf_acparam_t *acparam_cur, int aci) +dhd_conf_update_wme(dhd_pub_t *dhd, int ifidx, int mode, + edcf_acparam_t *acparam_cur, int aci) { int aifsn, ecwmin, ecwmax, txop; edcf_acparam_t *acp; @@ -1004,9 +1187,8 @@ dhd_conf_update_wme(dhd_pub_t *dhd, int mode, edcf_acparam_t *acparam_cur, int a acp->ECW = ((acp->ECW & EDCF_ECWMAX_MASK) | (ecwmin & EDCF_ECWMIN_MASK)); acp->TXOP = txop; - printf("%s: wme_ac %s aci %d aifsn %d ecwmin %d ecwmax %d txop 0x%x\n", - __FUNCTION__, mode?"ap":"sta", - acp->ACI, acp->ACI&EDCF_AIFSN_MASK, + CONFIG_MSG("wme_ac %s aci %d aifsn %d ecwmin %d ecwmax %d txop 0x%x\n", + mode?"ap":"sta", acp->ACI, acp->ACI&EDCF_AIFSN_MASK, acp->ECW&EDCF_ECWMIN_MASK, (acp->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT, acp->TXOP); @@ -1016,36 +1198,38 @@ dhd_conf_update_wme(dhd_pub_t *dhd, int mode, edcf_acparam_t *acparam_cur, int a * NOTE: only one of the four ACs can be set at a time. */ if (mode == 0) - dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "wme_ac_sta", (char *)acp, sizeof(edcf_acparam_t), FALSE); + dhd_conf_set_bufiovar(dhd, ifidx, WLC_SET_VAR, "wme_ac_sta", (char *)acp, + sizeof(edcf_acparam_t), FALSE); else - dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "wme_ac_ap", (char *)acp, sizeof(edcf_acparam_t), FALSE); + dhd_conf_set_bufiovar(dhd, ifidx, WLC_SET_VAR, "wme_ac_ap", (char *)acp, + sizeof(edcf_acparam_t), FALSE); } void -dhd_conf_set_wme(dhd_pub_t *dhd, int mode) +dhd_conf_set_wme(dhd_pub_t *dhd, int ifidx, int mode) { edcf_acparam_t acparam_cur[AC_COUNT]; if (dhd && dhd->conf) { if (!dhd->conf->force_wme_ac) { - CONFIG_TRACE(("%s: force_wme_ac is not enabled %d\n", - __FUNCTION__, dhd->conf->force_wme_ac)); + CONFIG_TRACE("force_wme_ac is not enabled %d\n", + dhd->conf->force_wme_ac); return; } - CONFIG_TRACE(("%s: Before change:\n", __FUNCTION__)); - dhd_conf_get_wme(dhd, mode, acparam_cur); + CONFIG_TRACE("Before change:\n"); + dhd_conf_get_wme(dhd, ifidx, mode, acparam_cur); - dhd_conf_update_wme(dhd, mode, &acparam_cur[AC_BK], AC_BK); - dhd_conf_update_wme(dhd, mode, &acparam_cur[AC_BE], AC_BE); - dhd_conf_update_wme(dhd, mode, &acparam_cur[AC_VI], AC_VI); - dhd_conf_update_wme(dhd, mode, &acparam_cur[AC_VO], AC_VO); + dhd_conf_update_wme(dhd, ifidx, mode, &acparam_cur[AC_BK], AC_BK); + dhd_conf_update_wme(dhd, ifidx, mode, &acparam_cur[AC_BE], AC_BE); + dhd_conf_update_wme(dhd, ifidx, mode, &acparam_cur[AC_VI], AC_VI); + dhd_conf_update_wme(dhd, ifidx, mode, &acparam_cur[AC_VO], AC_VO); - CONFIG_TRACE(("%s: After change:\n", __FUNCTION__)); - dhd_conf_get_wme(dhd, mode, acparam_cur); + CONFIG_TRACE("After change:\n"); + dhd_conf_get_wme(dhd, ifidx, mode, acparam_cur); } else { - CONFIG_ERROR(("%s: dhd or conf is NULL\n", __FUNCTION__)); + CONFIG_ERROR("dhd or conf is NULL\n"); } return; @@ -1054,18 +1238,19 @@ dhd_conf_set_wme(dhd_pub_t *dhd, int mode) void dhd_conf_set_mchan_bw(dhd_pub_t *dhd, int p2p_mode, int miracast_mode) { - int i; struct dhd_conf *conf = dhd->conf; + mchan_params_t *mchan = conf->mchan; bool set = true; - for (i=0; imchan[i].bw >= 0); - set &= ((conf->mchan[i].p2p_mode == -1) | (conf->mchan[i].p2p_mode == p2p_mode)); - set &= ((conf->mchan[i].miracast_mode == -1) | (conf->mchan[i].miracast_mode == miracast_mode)); + set &= (mchan->bw >= 0); + set &= ((mchan->p2p_mode == -1) | (mchan->p2p_mode == p2p_mode)); + set &= ((mchan->miracast_mode == -1) | (mchan->miracast_mode == miracast_mode)); if (set) { - dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "mchan_bw", conf->mchan[i].bw, 0, FALSE); + dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "mchan_bw", mchan->bw, 0, FALSE); } + mchan = mchan->next; } return; @@ -1082,13 +1267,13 @@ dhd_conf_add_pkt_filter(dhd_pub_t *dhd) /* * Filter in less pkt: ARP(0x0806, ID is 105), BRCM(0x886C), 802.1X(0x888E) * 1) dhd_master_mode=1 - * 2) pkt_filter_del=100, 102, 103, 104, 105 + * 2) pkt_filter_delete=100, 102, 103, 104, 105, 106, 107 * 3) pkt_filter_add=131 0 0 12 0xFFFF 0x886C, 132 0 0 12 0xFFFF 0x888E * 4) magic_pkt_filter_add=141 0 1 12 */ for(i=0; iconf->pkt_filter_add.count; i++) { dhd->pktfilter[i+dhd->pktfilter_count] = dhd->conf->pkt_filter_add.filter[i]; - printf("%s: %s\n", __FUNCTION__, dhd->pktfilter[i+dhd->pktfilter_count]); + CONFIG_MSG("%s\n", dhd->pktfilter[i+dhd->pktfilter_count]); } dhd->pktfilter_count += i; @@ -1115,7 +1300,7 @@ dhd_conf_del_pkt_filter(dhd_pub_t *dhd, uint32 id) if (dhd && dhd->conf) { for (i=0; iconf->pkt_filter_del.count; i++) { if (id == dhd->conf->pkt_filter_del.id[i]) { - printf("%s: %d\n", __FUNCTION__, dhd->conf->pkt_filter_del.id[i]); + CONFIG_MSG("%d\n", dhd->conf->pkt_filter_del.id[i]); return true; } } @@ -1161,59 +1346,606 @@ dhd_conf_get_pm(dhd_pub_t *dhd) return -1; } -#define AP_IN_SUSPEND 1 -#define AP_DOWN_IN_SUSPEND 2 int -dhd_conf_get_ap_mode_in_suspend(dhd_pub_t *dhd) +dhd_conf_check_hostsleep(dhd_pub_t *dhd, int cmd, void *buf, int len, + int *hostsleep_set, int *hostsleep_val, int *ret) { - int mode = 0; - - /* returned ap_in_suspend value: - * 0: nothing - * 1: ap enabled in suspend - * 2: ap enabled, but down in suspend - */ - if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) { - mode = dhd->conf->ap_in_suspend; - } - - return mode; -} - -int -dhd_conf_set_ap_in_suspend(dhd_pub_t *dhd, int suspend) -{ - int mode = 0; - uint wl_down = 1; - - mode = dhd_conf_get_ap_mode_in_suspend(dhd); - if (mode) - printf("%s: suspend %d, mode %d\n", __FUNCTION__, suspend, mode); - if (suspend) { - if (mode == AP_IN_SUSPEND) { -#ifdef SUSPEND_EVENT - if (dhd->conf->suspend_eventmask_enable) { - char *eventmask = dhd->conf->suspend_eventmask; - dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "event_msgs", eventmask, sizeof(eventmask), TRUE); + if (dhd->conf->insuspend & (NO_TXCTL_IN_SUSPEND | WOWL_IN_SUSPEND)) { + if (cmd == WLC_SET_VAR) { + char *psleep = NULL; + psleep = strstr(buf, "hostsleep"); + if (psleep) { + *hostsleep_set = 1; + memcpy(hostsleep_val, psleep+strlen("hostsleep")+1, sizeof(int)); } -#endif - } else if (mode == AP_DOWN_IN_SUSPEND) - dhd_wl_ioctl_cmd(dhd, WLC_DOWN, (char *)&wl_down, sizeof(wl_down), TRUE, 0); - } else { - if (mode == AP_IN_SUSPEND) { -#ifdef SUSPEND_EVENT - if (dhd->conf->suspend_eventmask_enable) { - char *eventmask = dhd->conf->resume_eventmask; - dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "event_msgs", eventmask, sizeof(eventmask), TRUE); + } + if (dhd->hostsleep && (!*hostsleep_set || *hostsleep_val)) { + CONFIG_TRACE("block all none hostsleep clr cmd\n"); + *ret = BCME_EPERM; + goto exit; + } else if (*hostsleep_set && *hostsleep_val) { + CONFIG_TRACE("hostsleep %d => %d\n", dhd->hostsleep, *hostsleep_val); + dhd->hostsleep = *hostsleep_val; + if (dhd->conf->insuspend & NO_TXDATA_IN_SUSPEND) { + dhd_txflowcontrol(dhd, ALL_INTERFACES, ON); } -#endif - } else if (mode == AP_DOWN_IN_SUSPEND) { - wl_down = 0; - dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&wl_down, sizeof(wl_down), TRUE, 0); + if (dhd->hostsleep == 2) { + *ret = 0; + goto exit; + } + } else if (dhd->hostsleep == 2 && !*hostsleep_val) { + CONFIG_TRACE("hostsleep %d => %d\n", dhd->hostsleep, *hostsleep_val); + dhd->hostsleep = *hostsleep_val; + if (dhd->conf->insuspend & NO_TXDATA_IN_SUSPEND) { + dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF); + } + *ret = 0; + goto exit; } } - return mode; + return 0; +exit: + return -1; +} + +void +dhd_conf_get_hostsleep(dhd_pub_t *dhd, + int hostsleep_set, int hostsleep_val, int ret) +{ + if (dhd->conf->insuspend & (NO_TXCTL_IN_SUSPEND | WOWL_IN_SUSPEND)) { + if (hostsleep_set) { + if (hostsleep_val && ret) { + CONFIG_TRACE("reset hostsleep %d => 0\n", dhd->hostsleep); + dhd->hostsleep = 0; + if (dhd->conf->insuspend & NO_TXDATA_IN_SUSPEND) { + dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF); + } + } else if (!hostsleep_val && !ret) { + CONFIG_TRACE("set hostsleep %d => 0\n", dhd->hostsleep); + dhd->hostsleep = 0; + if (dhd->conf->insuspend & NO_TXDATA_IN_SUSPEND) { + dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF); + } + } + } + } +} + +#ifdef WL_EXT_WOWL +#define WL_WOWL_TCPFIN (1 << 26) +typedef struct wl_wowl_pattern2 { + char cmd[4]; + wl_wowl_pattern_t wowl_pattern; +} wl_wowl_pattern2_t; +static int +dhd_conf_wowl_pattern(dhd_pub_t *dhd, bool add, char *data) +{ + uint buf_len = 0; + int id, type, polarity, offset; + char cmd[4]="\0", mask[128]="\0", pattern[128]="\0", mask_tmp[128]="\0", *pmask_tmp; + uint32 masksize, patternsize, pad_len = 0; + wl_wowl_pattern2_t *wowl_pattern2 = NULL; + char *mask_and_pattern; + int ret = 0, i, j, v; + + if (data) { + if (add) + strcpy(cmd, "add"); + else + strcpy(cmd, "clr"); + if (!strcmp(cmd, "clr")) { + CONFIG_TRACE("wowl_pattern clr\n"); + ret = dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "wowl_pattern", cmd, + sizeof(cmd), FALSE); + goto exit; + } + sscanf(data, "%d %d %d %d %s %s", &id, &type, &polarity, &offset, + mask_tmp, pattern); + masksize = strlen(mask_tmp) -2; + CONFIG_TRACE("0 mask_tmp=%s, masksize=%d\n", mask_tmp, masksize); + + // add pading + if (masksize % 16) + pad_len = (16 - masksize % 16); + for (i=0; icmd, cmd, sizeof(cmd)); + wowl_pattern2->wowl_pattern.id = id; + wowl_pattern2->wowl_pattern.type = 0; + wowl_pattern2->wowl_pattern.offset = offset; + mask_and_pattern = (char*)wowl_pattern2 + sizeof(wl_wowl_pattern2_t); + + wowl_pattern2->wowl_pattern.masksize = masksize; + ret = wl_pattern_atoh(mask, mask_and_pattern); + if (ret == -1) { + CONFIG_ERROR("rejecting mask=%s\n", mask); + goto exit; + } + + mask_and_pattern += wowl_pattern2->wowl_pattern.masksize; + wowl_pattern2->wowl_pattern.patternoffset = sizeof(wl_wowl_pattern_t) + + wowl_pattern2->wowl_pattern.masksize; + + wowl_pattern2->wowl_pattern.patternsize = patternsize; + ret = wl_pattern_atoh(pattern, mask_and_pattern); + if (ret == -1) { + CONFIG_ERROR("rejecting pattern=%s\n", pattern); + goto exit; + } + + CONFIG_TRACE("%s %d %s %s\n", cmd, offset, mask, pattern); + + ret = dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "wowl_pattern", + (char *)wowl_pattern2, buf_len, FALSE); + } + +exit: + if (wowl_pattern2) + kfree(wowl_pattern2); + return ret; +} + +static int +dhd_conf_wowl_wakeind(dhd_pub_t *dhd, bool clear) +{ + s8 iovar_buf[WLC_IOCTL_SMLEN]; + wl_wowl_wakeind_t *wake = NULL; + int ret = -1; + char clr[6]="clear", wakeind_str[32]="\0"; + + if (clear) { + CONFIG_TRACE("wowl_wakeind clear\n"); + ret = dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "wowl_wakeind", + clr, sizeof(clr), 0); + } else { + ret = dhd_conf_get_iovar(dhd, 0, WLC_GET_VAR, "wowl_wakeind", + iovar_buf, sizeof(iovar_buf)); + if (!ret) { + wake = (wl_wowl_wakeind_t *) iovar_buf; + if (wake->ucode_wakeind & WL_WOWL_MAGIC) + strcpy(wakeind_str, "(MAGIC packet)"); + if (wake->ucode_wakeind & WL_WOWL_NET) + strcpy(wakeind_str, "(Netpattern)"); + if (wake->ucode_wakeind & WL_WOWL_DIS) + strcpy(wakeind_str, "(Disassoc/Deauth)"); + if (wake->ucode_wakeind & WL_WOWL_BCN) + strcpy(wakeind_str, "(Loss of beacon)"); + if (wake->ucode_wakeind & WL_WOWL_TCPKEEP_TIME) + strcpy(wakeind_str, "(TCPKA timeout)"); + if (wake->ucode_wakeind & WL_WOWL_TCPKEEP_DATA) + strcpy(wakeind_str, "(TCPKA data)"); + if (wake->ucode_wakeind & WL_WOWL_TCPFIN) + strcpy(wakeind_str, "(TCP FIN)"); + CONFIG_MSG("wakeind=0x%x %s\n", wake->ucode_wakeind, wakeind_str); + } + } + + return ret; +} +#endif + +int +dhd_conf_mkeep_alive(dhd_pub_t *dhd, int ifidx, int id, int period, + char *packet, bool bcast) +{ + wl_mkeep_alive_pkt_t *mkeep_alive_pktp; + int ret = 0, len_bytes=0, buf_len=0; + char *buf = NULL, *iovar_buf = NULL; + uint8 *pdata; + + CONFIG_TRACE("id=%d, period=%d, packet=%s\n", id, period, packet); + if (period >= 0) { + buf = kmalloc(WLC_IOCTL_SMLEN, GFP_KERNEL); + if (buf == NULL) { + CONFIG_ERROR("Failed to allocate buffer of %d bytes\n", WLC_IOCTL_SMLEN); + goto exit; + } + iovar_buf = kmalloc(WLC_IOCTL_SMLEN, GFP_KERNEL); + if (iovar_buf == NULL) { + CONFIG_ERROR("Failed to allocate buffer of %d bytes\n", WLC_IOCTL_SMLEN); + goto exit; + } + mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *)buf; + mkeep_alive_pktp->version = htod16(WL_MKEEP_ALIVE_VERSION); + mkeep_alive_pktp->length = htod16(WL_MKEEP_ALIVE_FIXED_LEN); + mkeep_alive_pktp->keep_alive_id = id; + buf_len += WL_MKEEP_ALIVE_FIXED_LEN; + mkeep_alive_pktp->period_msec = period; + if (packet && strlen(packet)) { + len_bytes = wl_pattern_atoh(packet, (char *)mkeep_alive_pktp->data); + buf_len += len_bytes; + if (bcast) { + memcpy(mkeep_alive_pktp->data, ðer_bcast, ETHER_ADDR_LEN); + } + ret = dhd_conf_get_iovar(dhd, ifidx, WLC_GET_VAR, "cur_etheraddr", + iovar_buf, WLC_IOCTL_SMLEN); + if (!ret) { + pdata = mkeep_alive_pktp->data; + memcpy(pdata+6, iovar_buf, ETHER_ADDR_LEN); + } + } + mkeep_alive_pktp->len_bytes = htod16(len_bytes); + ret = dhd_conf_set_bufiovar(dhd, ifidx, WLC_SET_VAR, "mkeep_alive", + buf, buf_len, FALSE); + } + +exit: + if (buf) + kfree(buf); + if (iovar_buf) + kfree(iovar_buf); + return ret; +} + +#ifdef ARP_OFFLOAD_SUPPORT +void +dhd_conf_set_garp(dhd_pub_t *dhd, int ifidx, uint32 ipa, bool enable) +{ + int i, len = 0, total_len = WLC_IOCTL_SMLEN; + char *iovar_buf = NULL, *packet = NULL; + + if (!dhd->conf->garp || ifidx != 0 || !(dhd->op_mode & DHD_FLAG_STA_MODE)) + return; + + CONFIG_TRACE("enable=%d\n", enable); + + if (enable) { + iovar_buf = kmalloc(total_len, GFP_KERNEL); + if (iovar_buf == NULL) { + CONFIG_ERROR("Failed to allocate buffer of %d bytes\n", total_len); + goto exit; + } + packet = kmalloc(total_len, GFP_KERNEL); + if (packet == NULL) { + CONFIG_ERROR("Failed to allocate buffer of %d bytes\n", total_len); + goto exit; + } + dhd_conf_get_iovar(dhd, ifidx, WLC_GET_VAR, "cur_etheraddr", iovar_buf, total_len); + + len += snprintf(packet+len, total_len, "0xffffffffffff"); + for (i=0; i>8)&0xff, (ipa>>16)&0xff, (ipa>>24)&0xff); + len += snprintf(packet+len, total_len, "ffffffffffffc0a80101000000000000000000000000000000000000"); + } + + dhd_conf_mkeep_alive(dhd, ifidx, 0, dhd->conf->keep_alive_period, packet, TRUE); + +exit: + if (iovar_buf) + kfree(iovar_buf); + if (packet) + kfree(packet); + return; +} +#endif + +uint +dhd_conf_get_insuspend(dhd_pub_t *dhd, uint mask) +{ + uint insuspend = 0; + + if (dhd->op_mode & DHD_FLAG_STA_MODE) { + insuspend = dhd->conf->insuspend & + (NO_EVENT_IN_SUSPEND | NO_TXDATA_IN_SUSPEND | NO_TXCTL_IN_SUSPEND | + ROAM_OFFLOAD_IN_SUSPEND | WOWL_IN_SUSPEND); + } else if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) { + insuspend = dhd->conf->insuspend & + (NO_EVENT_IN_SUSPEND | NO_TXDATA_IN_SUSPEND | NO_TXCTL_IN_SUSPEND | + AP_DOWN_IN_SUSPEND | AP_FILTER_IN_SUSPEND); + } + + return (insuspend & mask); +} + +#ifdef SUSPEND_EVENT +void +dhd_conf_set_suspend_event(dhd_pub_t *dhd, int suspend) +{ + struct dhd_conf *conf = dhd->conf; + struct ether_addr bssid; + char suspend_eventmask[WL_EVENTING_MASK_LEN]; + wl_event_msg_t msg; + int pm; +#ifdef WL_CFG80211 + struct net_device *net; +#endif /* defined(WL_CFG80211) */ + + if (suspend) { +#ifdef PROP_TXSTATUS +#if defined(BCMSDIO) || defined(BCMDBUS) + if (dhd->wlfc_enabled) { + dhd_wlfc_deinit(dhd); + conf->wlfc = TRUE; + } else { + conf->wlfc = FALSE; + } +#endif /* BCMSDIO || BCMDBUS */ +#endif /* PROP_TXSTATUS */ + dhd_conf_get_iovar(dhd, 0, WLC_GET_VAR, "event_msgs", + conf->resume_eventmask, sizeof(conf->resume_eventmask)); + memset(suspend_eventmask, 0, sizeof(suspend_eventmask)); + setbit(suspend_eventmask, WLC_E_ESCAN_RESULT); + dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "event_msgs", + suspend_eventmask, sizeof(suspend_eventmask), FALSE); + if (dhd->op_mode & DHD_FLAG_STA_MODE) { + memset(&bssid, 0, ETHER_ADDR_LEN); + dhd_wl_ioctl_cmd(dhd, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, FALSE, 0); + if (memcmp(ðer_null, &bssid, ETHER_ADDR_LEN)) + memcpy(&conf->bssid_insuspend, &bssid, ETHER_ADDR_LEN); + else + memset(&conf->bssid_insuspend, 0, ETHER_ADDR_LEN); + } + } + else { + dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "event_msgs", + conf->resume_eventmask, sizeof(conf->resume_eventmask), FALSE); + if (dhd->op_mode & DHD_FLAG_STA_MODE) { + if (memcmp(ðer_null, &conf->bssid_insuspend, ETHER_ADDR_LEN)) { + memset(&bssid, 0, ETHER_ADDR_LEN); + dhd_wl_ioctl_cmd(dhd, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, + FALSE, 0); + if (memcmp(ðer_null, &bssid, ETHER_ADDR_LEN)) { + dhd_conf_set_intiovar(dhd, WLC_SET_PM, "WLC_SET_PM", 0, 0, FALSE); + dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "send_nulldata", + (char *)&bssid, ETHER_ADDR_LEN, FALSE); + OSL_SLEEP(100); + if (conf->pm >= 0) + pm = conf->pm; + else + pm = PM_FAST; + dhd_conf_set_intiovar(dhd, WLC_SET_PM, "WLC_SET_PM", pm, 0, FALSE); + } else { + CONFIG_TRACE("send WLC_E_DEAUTH_IND event\n"); + bzero(&msg, sizeof(wl_event_msg_t)); + memcpy(&msg.addr, &conf->bssid_insuspend, ETHER_ADDR_LEN); + msg.event_type = hton32(WLC_E_DEAUTH_IND); + msg.status = 0; + msg.reason = hton32(DOT11_RC_DEAUTH_LEAVING); +#if defined(WL_EXT_IAPSTA) || defined(USE_IW) + wl_ext_event_send(dhd->event_params, &msg, NULL); +#endif +#ifdef WL_CFG80211 + net = dhd_idx2net(dhd, 0); + if (net) { + wl_cfg80211_event(net, &msg, NULL); + } +#endif /* defined(WL_CFG80211) */ + } + } +#ifdef PROP_TXSTATUS +#if defined(BCMSDIO) || defined(BCMDBUS) + if (conf->wlfc) { + dhd_wlfc_init(dhd); + dhd_conf_set_intiovar(dhd, WLC_UP, "WLC_UP", 0, 0, FALSE); + } +#endif +#endif /* PROP_TXSTATUS */ + } + } + +} +#endif + +#if defined(WL_CFG80211) || defined(WL_ESCAN) +static void +dhd_conf_wait_event_complete(struct dhd_pub *dhd, int ifidx) +{ + s32 timeout = -1; + + timeout = wait_event_interruptible_timeout(dhd->conf->event_complete, + wl_ext_event_complete(dhd, ifidx), msecs_to_jiffies(10000)); + if (timeout <= 0 || !wl_ext_event_complete(dhd, ifidx)) { + wl_ext_event_complete(dhd, ifidx); + CONFIG_ERROR("timeout\n"); + } +} +#endif + +int +dhd_conf_set_suspend_resume(dhd_pub_t *dhd, int suspend, int suspend_mode) +{ + struct dhd_conf *conf = dhd->conf; + uint insuspend = 0; + int pm; +#ifdef BCMSDIO + uint32 intstatus = 0; + int ret = 0; +#endif +#ifdef WL_EXT_WOWL + int i; +#endif + + if (conf->suspend_mode != AUTO_SUSPEND && conf->suspend_mode != suspend_mode) + return 0; + + insuspend = dhd_conf_get_insuspend(dhd, ALL_IN_SUSPEND); + if (insuspend) + CONFIG_MSG("op_mode %d, suspend %d, suspended %d, insuspend 0x%x, suspend_mode=%d\n", + dhd->op_mode, suspend, conf->suspended, insuspend, suspend_mode); + + if (conf->suspended == suspend) { + return 0; + } + + if (suspend) { + if (dhd->op_mode & DHD_FLAG_STA_MODE) { + dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "roam_off", + dhd->conf->roam_off_suspend, 0, FALSE); + dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "bcn_li_dtim", + dhd->conf->suspend_bcn_li_dtim, 0, FALSE); + if (insuspend & ROAM_OFFLOAD_IN_SUSPEND) + dhd_conf_enable_roam_offload(dhd, 2); + } else if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) { + if (insuspend & AP_DOWN_IN_SUSPEND) { + dhd_conf_set_intiovar(dhd, WLC_DOWN, "WLC_DOWN", 1, 0, FALSE); + } + } +#if defined(WL_CFG80211) || defined(WL_ESCAN) + if (insuspend & (NO_EVENT_IN_SUSPEND|NO_TXCTL_IN_SUSPEND|WOWL_IN_SUSPEND)) { + if (conf->suspend_mode == PM_NOTIFIER && suspend_mode == PM_NOTIFIER) + dhd_conf_wait_event_complete(dhd, 0); + } +#endif + if (insuspend & NO_TXDATA_IN_SUSPEND) { + dhd_txflowcontrol(dhd, ALL_INTERFACES, ON); + } +#if defined(WL_CFG80211) || defined(WL_ESCAN) + if (insuspend & (NO_EVENT_IN_SUSPEND|NO_TXCTL_IN_SUSPEND|WOWL_IN_SUSPEND)) { + if (conf->suspend_mode == PM_NOTIFIER && suspend_mode == PM_NOTIFIER) + wl_ext_user_sync(dhd, 0, TRUE); + } +#endif +#ifdef SUSPEND_EVENT + if (insuspend & NO_EVENT_IN_SUSPEND) { + dhd_conf_set_suspend_event(dhd, suspend); + } +#endif + if (dhd->op_mode & DHD_FLAG_STA_MODE) { + if (conf->pm_in_suspend >= 0) + pm = conf->pm_in_suspend; + else if (conf->pm >= 0) + pm = conf->pm; + else + pm = PM_FAST; + dhd_conf_set_intiovar(dhd, WLC_SET_PM, "WLC_SET_PM", pm, 0, FALSE); + } +#ifdef WL_EXT_WOWL + if ((insuspend & WOWL_IN_SUSPEND) && dhd_master_mode) { + dhd_conf_wowl_pattern(dhd, FALSE, "clr"); + for(i=0; ipkt_filter_add.count; i++) { + dhd_conf_wowl_pattern(dhd, TRUE, conf->pkt_filter_add.filter[i]); + } + dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "wowl", conf->wowl, 0, FALSE); + dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "wowl_activate", 1, 0, FALSE); + dhd_conf_wowl_wakeind(dhd, TRUE); + dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "hostsleep", 1, 0, FALSE); +#ifdef BCMSDIO + ret = dhd_bus_sleep(dhd, TRUE, &intstatus); + CONFIG_TRACE("ret = %d, intstatus = 0x%x\n", ret, intstatus); +#endif + } else +#endif + if (insuspend & NO_TXCTL_IN_SUSPEND) { + dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "hostsleep", 2, 0, FALSE); +#ifdef BCMSDIO + ret = dhd_bus_sleep(dhd, TRUE, &intstatus); + CONFIG_TRACE("ret = %d, intstatus = 0x%x\n", ret, intstatus); +#endif + } + conf->suspended = TRUE; + } else { + if (insuspend & (WOWL_IN_SUSPEND | NO_TXCTL_IN_SUSPEND)) { + dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "hostsleep", 0, 0, FALSE); + } +#ifdef WL_EXT_WOWL + if (insuspend & WOWL_IN_SUSPEND) { + dhd_conf_wowl_wakeind(dhd, FALSE); + dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "wowl_activate", 0, 0, FALSE); + dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "wowl", 0, 0, FALSE); + dhd_conf_wowl_pattern(dhd, FALSE, "clr"); + } +#endif + dhd_conf_get_iovar(dhd, 0, WLC_GET_PM, "WLC_GET_PM", (char *)&pm, sizeof(pm)); + CONFIG_TRACE("PM in suspend = %d\n", pm); +#ifdef SUSPEND_EVENT + if (insuspend & NO_EVENT_IN_SUSPEND) { + dhd_conf_set_suspend_event(dhd, suspend); + } +#endif +#if defined(WL_CFG80211) || defined(WL_ESCAN) + if (insuspend & (NO_EVENT_IN_SUSPEND|NO_TXCTL_IN_SUSPEND|WOWL_IN_SUSPEND)) { + if (conf->suspend_mode == PM_NOTIFIER && suspend_mode == PM_NOTIFIER) + wl_ext_user_sync(dhd, 0, FALSE); + } +#endif + if (insuspend & NO_TXDATA_IN_SUSPEND) { + dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF); + } + if (dhd->op_mode & DHD_FLAG_STA_MODE) { + if (insuspend & ROAM_OFFLOAD_IN_SUSPEND) + dhd_conf_enable_roam_offload(dhd, 0); + dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "bcn_li_dtim", 0, 0, FALSE); + dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "roam_off", + dhd->conf->roam_off, 0, FALSE); + } else if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) { + if (insuspend & AP_DOWN_IN_SUSPEND) { + dhd_conf_set_intiovar(dhd, WLC_UP, "WLC_UP", 0, 0, FALSE); + } + } + if (dhd->op_mode & DHD_FLAG_STA_MODE) { + if (conf->pm >= 0) + pm = conf->pm; + else + pm = PM_FAST; + dhd_conf_set_intiovar(dhd, WLC_SET_PM, "WLC_SET_PM", pm, 0, FALSE); + } + conf->suspended = FALSE; + } + + return 0; } #ifdef PROP_TXSTATUS @@ -1260,14 +1992,14 @@ dhd_conf_get_disable_proptx(dhd_pub_t *dhd) disable_proptx = 1; } - printf("%s: fw_proptx=%d, disable_proptx=%d\n", __FUNCTION__, fw_proptx, disable_proptx); + CONFIG_MSG("fw_proptx=%d, disable_proptx=%d\n", fw_proptx, disable_proptx); return disable_proptx; } #endif uint -pick_config_vars(char *varbuf, uint len, uint start_pos, char *pickbuf) +pick_config_vars(char *varbuf, uint len, uint start_pos, char *pickbuf, int picklen) { bool findNewline, changenewline=FALSE, pick=FALSE; int column; @@ -1277,7 +2009,7 @@ pick_config_vars(char *varbuf, uint len, uint start_pos, char *pickbuf) column = 0; if (start_pos >= len) { - CONFIG_ERROR(("%s: wrong start pos\n", __FUNCTION__)); + CONFIG_ERROR("wrong start pos\n"); return 0; } @@ -1320,6 +2052,8 @@ pick_config_vars(char *varbuf, uint len, uint start_pos, char *pickbuf) if (pick) { if (varbuf[n] == 0x9) continue; + if (pick_column >= picklen) + break; pickbuf[pick_column] = varbuf[n]; pick_column++; } @@ -1328,6 +2062,34 @@ pick_config_vars(char *varbuf, uint len, uint start_pos, char *pickbuf) return n; // return current position } +bool +dhd_conf_read_chiprev(dhd_pub_t *dhd, int *chip_match, + char *full_param, uint len_param) +{ + char *data = full_param+len_param, *pick_tmp, *pch; + uint chip = 0, rev = 0; + + /* Process chip, regrev: + * chip=[chipid], rev==[rev] + * Ex: chip=0x4359, rev=9 + */ + if (!strncmp("chip=", full_param, len_param)) { + chip = (int)simple_strtol(data, NULL, 0); + pick_tmp = data; + pch = bcmstrstr(pick_tmp, "rev="); + if (pch) { + rev = (int)simple_strtol(pch+strlen("rev="), NULL, 0); + } + if (chip == dhd->conf->chip && rev == dhd->conf->chiprev) + *chip_match = 1; + else + *chip_match = 0; + CONFIG_MSG("chip=0x%x, rev=%d, chip_match=%d\n", chip, rev, *chip_match); + } + + return TRUE; +} + bool dhd_conf_read_log_level(dhd_pub_t *dhd, char *full_param, uint len_param) { @@ -1335,44 +2097,48 @@ dhd_conf_read_log_level(dhd_pub_t *dhd, char *full_param, uint len_param) if (!strncmp("dhd_msg_level=", full_param, len_param)) { dhd_msg_level = (int)simple_strtol(data, NULL, 0); - printf("%s: dhd_msg_level = 0x%X\n", __FUNCTION__, dhd_msg_level); + CONFIG_MSG("dhd_msg_level = 0x%X\n", dhd_msg_level); + } + else if (!strncmp("dump_msg_level=", full_param, len_param)) { + dump_msg_level = (int)simple_strtol(data, NULL, 0); + CONFIG_MSG("dump_msg_level = 0x%X\n", dump_msg_level); } #ifdef BCMSDIO else if (!strncmp("sd_msglevel=", full_param, len_param)) { sd_msglevel = (int)simple_strtol(data, NULL, 0); - printf("%s: sd_msglevel = 0x%X\n", __FUNCTION__, sd_msglevel); + CONFIG_MSG("sd_msglevel = 0x%X\n", sd_msglevel); } #endif #ifdef BCMDBUS else if (!strncmp("dbus_msglevel=", full_param, len_param)) { dbus_msglevel = (int)simple_strtol(data, NULL, 0); - printf("%s: dbus_msglevel = 0x%X\n", __FUNCTION__, dbus_msglevel); + CONFIG_MSG("dbus_msglevel = 0x%X\n", dbus_msglevel); } #endif else if (!strncmp("android_msg_level=", full_param, len_param)) { android_msg_level = (int)simple_strtol(data, NULL, 0); - printf("%s: android_msg_level = 0x%X\n", __FUNCTION__, android_msg_level); + CONFIG_MSG("android_msg_level = 0x%X\n", android_msg_level); } else if (!strncmp("config_msg_level=", full_param, len_param)) { config_msg_level = (int)simple_strtol(data, NULL, 0); - printf("%s: config_msg_level = 0x%X\n", __FUNCTION__, config_msg_level); + CONFIG_MSG("config_msg_level = 0x%X\n", config_msg_level); } #ifdef WL_CFG80211 else if (!strncmp("wl_dbg_level=", full_param, len_param)) { wl_dbg_level = (int)simple_strtol(data, NULL, 0); - printf("%s: wl_dbg_level = 0x%X\n", __FUNCTION__, wl_dbg_level); + CONFIG_MSG("wl_dbg_level = 0x%X\n", wl_dbg_level); } #endif #if defined(WL_WIRELESS_EXT) else if (!strncmp("iw_msg_level=", full_param, len_param)) { iw_msg_level = (int)simple_strtol(data, NULL, 0); - printf("%s: iw_msg_level = 0x%X\n", __FUNCTION__, iw_msg_level); + CONFIG_MSG("iw_msg_level = 0x%X\n", iw_msg_level); } #endif #if defined(DHD_DEBUG) else if (!strncmp("dhd_console_ms=", full_param, len_param)) { dhd_console_ms = (int)simple_strtol(data, NULL, 0); - printf("%s: dhd_console_ms = 0x%X\n", __FUNCTION__, dhd_console_ms); + CONFIG_MSG("dhd_console_ms = 0x%X\n", dhd_console_ms); } #endif else @@ -1390,25 +2156,25 @@ dhd_conf_read_wme_ac_value(wme_param_t *wme, char *pick, int ac_val) pch = bcmstrstr(pick_tmp, "aifsn "); if (pch) { wme->aifsn[ac_val] = (int)simple_strtol(pch+strlen("aifsn "), NULL, 0); - printf("%s: ac_val=%d, aifsn=%d\n", __FUNCTION__, ac_val, wme->aifsn[ac_val]); + CONFIG_MSG("ac_val=%d, aifsn=%d\n", ac_val, wme->aifsn[ac_val]); } pick_tmp = pick; pch = bcmstrstr(pick_tmp, "ecwmin "); if (pch) { wme->ecwmin[ac_val] = (int)simple_strtol(pch+strlen("ecwmin "), NULL, 0); - printf("%s: ac_val=%d, ecwmin=%d\n", __FUNCTION__, ac_val, wme->ecwmin[ac_val]); + CONFIG_MSG("ac_val=%d, ecwmin=%d\n", ac_val, wme->ecwmin[ac_val]); } pick_tmp = pick; pch = bcmstrstr(pick_tmp, "ecwmax "); if (pch) { wme->ecwmax[ac_val] = (int)simple_strtol(pch+strlen("ecwmax "), NULL, 0); - printf("%s: ac_val=%d, ecwmax=%d\n", __FUNCTION__, ac_val, wme->ecwmax[ac_val]); + CONFIG_MSG("ac_val=%d, ecwmax=%d\n", ac_val, wme->ecwmax[ac_val]); } pick_tmp = pick; pch = bcmstrstr(pick_tmp, "txop "); if (pch) { wme->txop[ac_val] = (int)simple_strtol(pch+strlen("txop "), NULL, 0); - printf("%s: ac_val=%d, txop=0x%x\n", __FUNCTION__, ac_val, wme->txop[ac_val]); + CONFIG_MSG("ac_val=%d, txop=0x%x\n", ac_val, wme->txop[ac_val]); } } @@ -1424,7 +2190,7 @@ dhd_conf_read_wme_ac_params(dhd_pub_t *dhd, char *full_param, uint len_param) if (!strncmp("force_wme_ac=", full_param, len_param)) { conf->force_wme_ac = (int)simple_strtol(data, NULL, 10); - printf("%s: force_wme_ac = %d\n", __FUNCTION__, conf->force_wme_ac); + CONFIG_MSG("force_wme_ac = %d\n", conf->force_wme_ac); } else if (!strncmp("wme_ac_sta_be=", full_param, len_param)) { dhd_conf_read_wme_ac_value(&conf->wme_sta, data, AC_BE); @@ -1456,6 +2222,7 @@ dhd_conf_read_wme_ac_params(dhd_pub_t *dhd, char *full_param, uint len_param) return true; } +#ifdef BCMSDIO bool dhd_conf_read_fw_by_mac(dhd_pub_t *dhd, char *full_param, uint len_param) { @@ -1481,25 +2248,28 @@ dhd_conf_read_fw_by_mac(dhd_pub_t *dhd, char *full_param, uint len_param) */ if (!strncmp("fw_by_mac=", full_param, len_param)) { + dhd_conf_free_mac_list(&conf->fw_by_mac); pick_tmp = data; pch = bcmstrtok(&pick_tmp, " ", 0); conf->fw_by_mac.count = (uint32)simple_strtol(pch, NULL, 0); - if (!(mac_list = kmalloc(sizeof(wl_mac_list_t)*conf->fw_by_mac.count, GFP_KERNEL))) { + if (!(mac_list = kmalloc(sizeof(wl_mac_list_t)*conf->fw_by_mac.count, + GFP_KERNEL))) { conf->fw_by_mac.count = 0; - CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); + CONFIG_ERROR("kmalloc failed\n"); } - printf("%s: fw_count=%d\n", __FUNCTION__, conf->fw_by_mac.count); + CONFIG_MSG("fw_count=%d\n", conf->fw_by_mac.count); conf->fw_by_mac.m_mac_list_head = mac_list; for (i=0; ifw_by_mac.count; i++) { pch = bcmstrtok(&pick_tmp, " ", 0); strcpy(mac_list[i].name, pch); pch = bcmstrtok(&pick_tmp, " ", 0); mac_list[i].count = (uint32)simple_strtol(pch, NULL, 0); - printf("%s: name=%s, mac_count=%d\n", __FUNCTION__, + CONFIG_MSG("name=%s, mac_count=%d\n", mac_list[i].name, mac_list[i].count); - if (!(mac_range = kmalloc(sizeof(wl_mac_range_t)*mac_list[i].count, GFP_KERNEL))) { + if (!(mac_range = kmalloc(sizeof(wl_mac_range_t)*mac_list[i].count, + GFP_KERNEL))) { mac_list[i].count = 0; - CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); + CONFIG_ERROR("kmalloc failed\n"); break; } mac_list[i].mac = mac_range; @@ -1510,9 +2280,8 @@ dhd_conf_read_fw_by_mac(dhd_pub_t *dhd, char *full_param, uint len_param) mac_range[j].nic_start = (uint32)simple_strtol(pch, NULL, 0); pch = bcmstrtok(&pick_tmp, " ", 0); mac_range[j].nic_end = (uint32)simple_strtol(pch, NULL, 0); - printf("%s: oui=0x%06X, nic_start=0x%06X, nic_end=0x%06X\n", - __FUNCTION__, mac_range[j].oui, - mac_range[j].nic_start, mac_range[j].nic_end); + CONFIG_MSG("oui=0x%06X, nic_start=0x%06X, nic_end=0x%06X\n", + mac_range[j].oui, mac_range[j].nic_start, mac_range[j].nic_end); } } } @@ -1536,25 +2305,28 @@ dhd_conf_read_nv_by_mac(dhd_pub_t *dhd, char *full_param, uint len_param) * [nv_by_mac]: The same format as fw_by_mac */ if (!strncmp("nv_by_mac=", full_param, len_param)) { + dhd_conf_free_mac_list(&conf->nv_by_mac); pick_tmp = data; pch = bcmstrtok(&pick_tmp, " ", 0); conf->nv_by_mac.count = (uint32)simple_strtol(pch, NULL, 0); - if (!(mac_list = kmalloc(sizeof(wl_mac_list_t)*conf->nv_by_mac.count, GFP_KERNEL))) { + if (!(mac_list = kmalloc(sizeof(wl_mac_list_t)*conf->nv_by_mac.count, + GFP_KERNEL))) { conf->nv_by_mac.count = 0; - CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); + CONFIG_ERROR("kmalloc failed\n"); } - printf("%s: nv_count=%d\n", __FUNCTION__, conf->nv_by_mac.count); + CONFIG_MSG("nv_count=%d\n", conf->nv_by_mac.count); conf->nv_by_mac.m_mac_list_head = mac_list; for (i=0; inv_by_mac.count; i++) { pch = bcmstrtok(&pick_tmp, " ", 0); strcpy(mac_list[i].name, pch); pch = bcmstrtok(&pick_tmp, " ", 0); mac_list[i].count = (uint32)simple_strtol(pch, NULL, 0); - printf("%s: name=%s, mac_count=%d\n", __FUNCTION__, + CONFIG_MSG("name=%s, mac_count=%d\n", mac_list[i].name, mac_list[i].count); - if (!(mac_range = kmalloc(sizeof(wl_mac_range_t)*mac_list[i].count, GFP_KERNEL))) { + if (!(mac_range = kmalloc(sizeof(wl_mac_range_t)*mac_list[i].count, + GFP_KERNEL))) { mac_list[i].count = 0; - CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); + CONFIG_ERROR("kmalloc failed\n"); break; } mac_list[i].mac = mac_range; @@ -1565,9 +2337,8 @@ dhd_conf_read_nv_by_mac(dhd_pub_t *dhd, char *full_param, uint len_param) mac_range[j].nic_start = (uint32)simple_strtol(pch, NULL, 0); pch = bcmstrtok(&pick_tmp, " ", 0); mac_range[j].nic_end = (uint32)simple_strtol(pch, NULL, 0); - printf("%s: oui=0x%06X, nic_start=0x%06X, nic_end=0x%06X\n", - __FUNCTION__, mac_range[j].oui, - mac_range[j].nic_start, mac_range[j].nic_end); + CONFIG_MSG("oui=0x%06X, nic_start=0x%06X, nic_end=0x%06X\n", + mac_range[j].oui, mac_range[j].nic_start, mac_range[j].nic_end); } } } @@ -1576,6 +2347,7 @@ dhd_conf_read_nv_by_mac(dhd_pub_t *dhd, char *full_param, uint len_param) return true; } +#endif bool dhd_conf_read_nv_by_chip(dhd_pub_t *dhd, char *full_param, uint len_param) @@ -1593,14 +2365,16 @@ dhd_conf_read_nv_by_chip(dhd_pub_t *dhd, char *full_param, uint len_param) * 43430 0 nvram_ap6212.txt 43430 1 nvram_ap6212a.txt \ */ if (!strncmp("nv_by_chip=", full_param, len_param)) { + dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip); pick_tmp = data; pch = bcmstrtok(&pick_tmp, " ", 0); conf->nv_by_chip.count = (uint32)simple_strtol(pch, NULL, 0); - if (!(chip_nv_path = kmalloc(sizeof(wl_mac_list_t)*conf->nv_by_chip.count, GFP_KERNEL))) { + if (!(chip_nv_path = kmalloc(sizeof(wl_mac_list_t)*conf->nv_by_chip.count, + GFP_KERNEL))) { conf->nv_by_chip.count = 0; - CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); + CONFIG_ERROR("kmalloc failed\n"); } - printf("%s: nv_by_chip_count=%d\n", __FUNCTION__, conf->nv_by_chip.count); + CONFIG_MSG("nv_by_chip_count=%d\n", conf->nv_by_chip.count); conf->nv_by_chip.m_chip_nv_path_head = chip_nv_path; for (i=0; inv_by_chip.count; i++) { pch = bcmstrtok(&pick_tmp, " ", 0); @@ -1609,7 +2383,7 @@ dhd_conf_read_nv_by_chip(dhd_pub_t *dhd, char *full_param, uint len_param) chip_nv_path[i].chiprev = (uint32)simple_strtol(pch, NULL, 0); pch = bcmstrtok(&pick_tmp, " ", 0); strcpy(chip_nv_path[i].name, pch); - printf("%s: chip=0x%x, chiprev=%d, name=%s\n", __FUNCTION__, + CONFIG_MSG("chip=0x%x, chiprev=%d, name=%s\n", chip_nv_path[i].chip, chip_nv_path[i].chiprev, chip_nv_path[i].name); } } @@ -1630,33 +2404,30 @@ dhd_conf_read_roam_params(dhd_pub_t *dhd, char *full_param, uint len_param) conf->roam_off = 0; else conf->roam_off = 1; - printf("%s: roam_off = %d\n", __FUNCTION__, conf->roam_off); + CONFIG_MSG("roam_off = %d\n", conf->roam_off); } else if (!strncmp("roam_off_suspend=", full_param, len_param)) { if (!strncmp(data, "0", 1)) conf->roam_off_suspend = 0; else conf->roam_off_suspend = 1; - printf("%s: roam_off_suspend = %d\n", __FUNCTION__, conf->roam_off_suspend); + CONFIG_MSG("roam_off_suspend = %d\n", conf->roam_off_suspend); } else if (!strncmp("roam_trigger=", full_param, len_param)) { conf->roam_trigger[0] = (int)simple_strtol(data, NULL, 10); - printf("%s: roam_trigger = %d\n", __FUNCTION__, - conf->roam_trigger[0]); + CONFIG_MSG("roam_trigger = %d\n", conf->roam_trigger[0]); } else if (!strncmp("roam_scan_period=", full_param, len_param)) { conf->roam_scan_period[0] = (int)simple_strtol(data, NULL, 10); - printf("%s: roam_scan_period = %d\n", __FUNCTION__, - conf->roam_scan_period[0]); + CONFIG_MSG("roam_scan_period = %d\n", conf->roam_scan_period[0]); } else if (!strncmp("roam_delta=", full_param, len_param)) { conf->roam_delta[0] = (int)simple_strtol(data, NULL, 10); - printf("%s: roam_delta = %d\n", __FUNCTION__, conf->roam_delta[0]); + CONFIG_MSG("roam_delta = %d\n", conf->roam_delta[0]); } else if (!strncmp("fullroamperiod=", full_param, len_param)) { conf->fullroamperiod = (int)simple_strtol(data, NULL, 10); - printf("%s: fullroamperiod = %d\n", __FUNCTION__, - conf->fullroamperiod); + CONFIG_MSG("fullroamperiod = %d\n", conf->fullroamperiod); } else return false; @@ -1664,24 +2435,33 @@ dhd_conf_read_roam_params(dhd_pub_t *dhd, char *full_param, uint len_param) } bool -dhd_conf_read_country_list(dhd_pub_t *dhd, char *full_param, uint len_param) +dhd_conf_read_country(dhd_pub_t *dhd, char *full_param, uint len_param) { - int i; - char *pch, *pick_tmp, *pick_tmp2; struct dhd_conf *conf = dhd->conf; + country_list_t *country_next = NULL, *country; + int i, count = 0; + char *pch, *pick_tmp, *pick_tmp2; char *data = full_param+len_param; - wl_country_t *cspec; - conf_country_list_t *country_list = NULL; + uint len_data = strlen(data); /* Process country_list: * country_list=[country1]:[ccode1]/[regrev1], * [country2]:[ccode2]/[regrev2] \ * Ex: country_list=US:US/0, TW:TW/1 */ - if (!strncmp("country_list=", full_param, len_param)) { - country_list = &dhd->conf->country_list; + if (!strncmp("ccode=", full_param, len_param)) { + len_data = min((uint)WLC_CNTRY_BUF_SZ, len_data); + memset(&conf->cspec, 0, sizeof(wl_country_t)); + memcpy(conf->cspec.country_abbrev, data, len_data); + memcpy(conf->cspec.ccode, data, len_data); + CONFIG_MSG("ccode = %s\n", conf->cspec.ccode); } - if (country_list) { + else if (!strncmp("regrev=", full_param, len_param)) { + conf->cspec.rev = (int32)simple_strtol(data, NULL, 10); + CONFIG_MSG("regrev = %d\n", conf->cspec.rev); + } + else if (!strncmp("country_list=", full_param, len_param)) { + dhd_conf_free_country_list(conf); pick_tmp = data; for (i=0; icountry_abbrev, pch); + memcpy(country->cspec.country_abbrev, pch, 2); pch = bcmstrtok(&pick_tmp2, "/", 0); if (!pch) { - kfree(cspec); + kfree(country); break; } - memcpy(cspec->ccode, pch, 2); + memcpy(country->cspec.ccode, pch, 2); pch = bcmstrtok(&pick_tmp2, "/", 0); if (!pch) { - kfree(cspec); + kfree(country); break; } - cspec->rev = (int32)simple_strtol(pch, NULL, 10); - country_list->count++; - country_list->cspec[i] = cspec; - CONFIG_TRACE(("%s: country_list abbrev=%s, ccode=%s, regrev=%d\n", __FUNCTION__, - cspec->country_abbrev, cspec->ccode, cspec->rev)); - } - if (!strncmp("country_list=", full_param, len_param)) { - printf("%s: %d country in list\n", __FUNCTION__, conf->country_list.count); + country->cspec.rev = (int32)simple_strtol(pch, NULL, 10); + count++; + if (!conf->country_head) { + conf->country_head = country; + country_next = country; + } else { + country_next->next = country; + country_next = country; + } + CONFIG_TRACE("abbrev=%s, ccode=%s, regrev=%d\n", + country->cspec.country_abbrev, country->cspec.ccode, country->cspec.rev); } + CONFIG_MSG("%d country in list\n", count); } else return false; @@ -1731,6 +2515,7 @@ dhd_conf_read_mchan_params(dhd_pub_t *dhd, char *full_param, uint len_param) int i; char *pch, *pick_tmp, *pick_tmp2; struct dhd_conf *conf = dhd->conf; + mchan_params_t *mchan_next = NULL, *mchan; char *data = full_param+len_param; /* Process mchan_bw: @@ -1738,51 +2523,65 @@ dhd_conf_read_mchan_params(dhd_pub_t *dhd, char *full_param, uint len_param) * Ex: mchan_bw=80/go/source, 30/gc/sink */ if (!strncmp("mchan_bw=", full_param, len_param)) { + dhd_conf_free_mchan_list(conf); pick_tmp = data; for (i=0; imchan[i].bw = (int)simple_strtol(pch, NULL, 0); - if (conf->mchan[i].bw < 0 || conf->mchan[i].bw > 100) { - CONFIG_ERROR(("%s: wrong bw %d\n", __FUNCTION__, conf->mchan[i].bw)); - conf->mchan[i].bw = 0; - break; - } } + memset(mchan, 0, sizeof(mchan_params_t)); + + mchan->bw = (int)simple_strtol(pch, NULL, 0); + if (mchan->bw < 0 || mchan->bw > 100) { + CONFIG_ERROR("wrong bw %d\n", mchan->bw); + kfree(mchan); + break; + } + pch = bcmstrtok(&pick_tmp2, "/", 0); if (!pch) { + kfree(mchan); break; } else { if (bcmstrstr(pch, "any")) { - conf->mchan[i].p2p_mode = -1; + mchan->p2p_mode = -1; } else if (bcmstrstr(pch, "go")) { - conf->mchan[i].p2p_mode = WL_P2P_IF_GO; + mchan->p2p_mode = WL_P2P_IF_GO; } else if (bcmstrstr(pch, "gc")) { - conf->mchan[i].p2p_mode = WL_P2P_IF_CLIENT; + mchan->p2p_mode = WL_P2P_IF_CLIENT; } } pch = bcmstrtok(&pick_tmp2, "/", 0); if (!pch) { + kfree(mchan); break; } else { if (bcmstrstr(pch, "any")) { - conf->mchan[i].miracast_mode = -1; + mchan->miracast_mode = -1; } else if (bcmstrstr(pch, "source")) { - conf->mchan[i].miracast_mode = MIRACAST_SOURCE; + mchan->miracast_mode = MIRACAST_SOURCE; } else if (bcmstrstr(pch, "sink")) { - conf->mchan[i].miracast_mode = MIRACAST_SINK; + mchan->miracast_mode = MIRACAST_SINK; } } - } - for (i=0; imchan[i].bw >= 0) - printf("%s: mchan_bw=%d/%d/%d\n", __FUNCTION__, - conf->mchan[i].bw, conf->mchan[i].p2p_mode, conf->mchan[i].miracast_mode); + if (!conf->mchan) { + conf->mchan = mchan; + mchan_next = mchan; + } else { + mchan_next->next = mchan; + mchan_next = mchan; + } + CONFIG_TRACE("mchan_bw=%d/%d/%d\n", mchan->bw,mchan->p2p_mode, + mchan->miracast_mode); } } else @@ -1802,7 +2601,7 @@ dhd_conf_read_pkt_filter(dhd_pub_t *dhd, char *full_param, uint len_param) /* Process pkt filter: * 1) pkt_filter_add=99 0 0 0 0x000000000000 0x000000000000 - * 2) pkt_filter_del=100, 102, 103, 104, 105 + * 2) pkt_filter_delete=100, 102, 103, 104, 105 * 3) magic_pkt_filter_add=141 0 1 12 */ if (!strncmp("dhd_master_mode=", full_param, len_param)) { @@ -1810,7 +2609,7 @@ dhd_conf_read_pkt_filter(dhd_pub_t *dhd, char *full_param, uint len_param) dhd_master_mode = FALSE; else dhd_master_mode = TRUE; - printf("%s: dhd_master_mode = %d\n", __FUNCTION__, dhd_master_mode); + CONFIG_MSG("dhd_master_mode = %d\n", dhd_master_mode); } else if (!strncmp("pkt_filter_add=", full_param, len_param)) { pick_tmp = data; @@ -1818,13 +2617,15 @@ dhd_conf_read_pkt_filter(dhd_pub_t *dhd, char *full_param, uint len_param) i=0; while (pch != NULL && ipkt_filter_add.filter[i][0], pch); - printf("%s: pkt_filter_add[%d][] = %s\n", __FUNCTION__, i, &conf->pkt_filter_add.filter[i][0]); + CONFIG_MSG("pkt_filter_add[%d][] = %s\n", + i, &conf->pkt_filter_add.filter[i][0]); pch = bcmstrtok(&pick_tmp, ",.-", 0); i++; } conf->pkt_filter_add.count = i; } - else if (!strncmp("pkt_filter_del=", full_param, len_param)) { + else if (!strncmp("pkt_filter_delete=", full_param, len_param) || + !strncmp("pkt_filter_del=", full_param, len_param)) { pick_tmp = data; pch = bcmstrtok(&pick_tmp, " ,.-", 0); i=0; @@ -1834,18 +2635,22 @@ dhd_conf_read_pkt_filter(dhd_pub_t *dhd, char *full_param, uint len_param) i++; } conf->pkt_filter_del.count = i; - printf("%s: pkt_filter_del id = ", __FUNCTION__); + CONFIG_MSG("pkt_filter_del id = "); for (i=0; ipkt_filter_del.count; i++) printf("%d ", conf->pkt_filter_del.id[i]); printf("\n"); } else if (!strncmp("magic_pkt_filter_add=", full_param, len_param)) { + if (conf->magic_pkt_filter_add) { + kfree(conf->magic_pkt_filter_add); + conf->magic_pkt_filter_add = NULL; + } if (!(conf->magic_pkt_filter_add = kmalloc(MAGIC_PKT_FILTER_LEN, GFP_KERNEL))) { - CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); + CONFIG_ERROR("kmalloc failed\n"); } else { memset(conf->magic_pkt_filter_add, 0, MAGIC_PKT_FILTER_LEN); strcpy(conf->magic_pkt_filter_add, data); - printf("%s: magic_pkt_filter_add = %s\n", __FUNCTION__, conf->magic_pkt_filter_add); + CONFIG_MSG("magic_pkt_filter_add = %s\n", conf->magic_pkt_filter_add); } } else @@ -1856,6 +2661,9 @@ dhd_conf_read_pkt_filter(dhd_pub_t *dhd, char *full_param, uint len_param) #endif #ifdef ISAM_PREINIT +#if !defined(WL_EXT_IAPSTA) +#error "WL_EXT_IAPSTA should be defined to enable ISAM_PREINIT" +#endif /* !WL_EXT_IAPSTA */ /* * isam_init=mode [sta|ap|apsta|dualap] vifname [wlan1] * isam_config=ifname [wlan0|wlan1] ssid [xxx] chan [x] @@ -1873,15 +2681,15 @@ dhd_conf_read_isam(dhd_pub_t *dhd, char *full_param, uint len_param) if (!strncmp("isam_init=", full_param, len_param)) { sprintf(conf->isam_init, "isam_init %s", data); - printf("%s: isam_init=%s\n", __FUNCTION__, conf->isam_init); + CONFIG_MSG("isam_init=%s\n", conf->isam_init); } else if (!strncmp("isam_config=", full_param, len_param)) { sprintf(conf->isam_config, "isam_config %s", data); - printf("%s: isam_config=%s\n", __FUNCTION__, conf->isam_config); + CONFIG_MSG("isam_config=%s\n", conf->isam_config); } else if (!strncmp("isam_enable=", full_param, len_param)) { sprintf(conf->isam_enable, "isam_enable %s", data); - printf("%s: isam_enable=%s\n", __FUNCTION__, conf->isam_enable); + CONFIG_MSG("isam_enable=%s\n", conf->isam_enable); } else return false; @@ -1900,35 +2708,43 @@ dhd_conf_read_dhcp_params(dhd_pub_t *dhd, char *full_param, uint len_param) if (!strncmp("dhcpc_enable=", full_param, len_param)) { conf->dhcpc_enable = (int)simple_strtol(data, NULL, 10); - printf("%s: dhcpc_enable = %d\n", __FUNCTION__, conf->dhcpc_enable); + CONFIG_MSG("dhcpc_enable = %d\n", conf->dhcpc_enable); } else if (!strncmp("dhcpd_enable=", full_param, len_param)) { conf->dhcpd_enable = (int)simple_strtol(data, NULL, 10); - printf("%s: dhcpd_enable = %d\n", __FUNCTION__, conf->dhcpd_enable); + CONFIG_MSG("dhcpd_enable = %d\n", conf->dhcpd_enable); } else if (!strncmp("dhcpd_ip_addr=", full_param, len_param)) { - if (!bcm_atoipv4(data, &ipa_set)) - printf("%s : dhcpd_ip_addr adress setting failed.\n", __FUNCTION__); - conf->dhcpd_ip_addr = ipa_set; - printf("%s: dhcpd_ip_addr = %s\n",__FUNCTION__, data); + if (!bcm_atoipv4(data, &ipa_set)) { + CONFIG_ERROR("dhcpd_ip_addr adress setting failed.n"); + return false; + } + memcpy(&conf->dhcpd_ip_addr, &ipa_set, sizeof(struct ipv4_addr)); + CONFIG_MSG("dhcpd_ip_addr = %s\n", data); } else if (!strncmp("dhcpd_ip_mask=", full_param, len_param)) { - if (!bcm_atoipv4(data, &ipa_set)) - printf("%s : dhcpd_ip_mask adress setting failed.\n", __FUNCTION__); - conf->dhcpd_ip_mask = ipa_set; - printf("%s: dhcpd_ip_mask = %s\n",__FUNCTION__, data); + if (!bcm_atoipv4(data, &ipa_set)) { + CONFIG_ERROR("dhcpd_ip_mask adress setting failed\n"); + return false; + } + memcpy(&conf->dhcpd_ip_mask, &ipa_set, sizeof(struct ipv4_addr)); + CONFIG_MSG("dhcpd_ip_mask = %s\n", data); } else if (!strncmp("dhcpd_ip_start=", full_param, len_param)) { - if (!bcm_atoipv4(data, &ipa_set)) - printf("%s : dhcpd_ip_start adress setting failed.\n", __FUNCTION__); - conf->dhcpd_ip_start = ipa_set; - printf("%s: dhcpd_ip_start = %s\n",__FUNCTION__, data); + if (!bcm_atoipv4(data, &ipa_set)) { + CONFIG_ERROR("dhcpd_ip_start adress setting failed\n"); + return false; + } + memcpy(&conf->dhcpd_ip_start, &ipa_set, sizeof(struct ipv4_addr)); + CONFIG_MSG("dhcpd_ip_start = %s\n", data); } else if (!strncmp("dhcpd_ip_end=", full_param, len_param)) { - if (!bcm_atoipv4(data, &ipa_set)) - printf("%s : dhcpd_ip_end adress setting failed.\n", __FUNCTION__); - conf->dhcpd_ip_end = ipa_set; - printf("%s: dhcpd_ip_end = %s\n",__FUNCTION__, data); + if (!bcm_atoipv4(data, &ipa_set)) { + CONFIG_ERROR("dhcpd_ip_end adress setting failed\n"); + return false; + } + memcpy(&conf->dhcpd_ip_end, &ipa_set, sizeof(struct ipv4_addr)); + CONFIG_MSG("dhcpd_ip_end = %s\n", data); } else return false; @@ -1949,7 +2765,7 @@ dhd_conf_read_sdio_params(dhd_pub_t *dhd, char *full_param, uint len_param) dhd_doflow = FALSE; else dhd_doflow = TRUE; - printf("%s: dhd_doflow = %d\n", __FUNCTION__, dhd_doflow); + CONFIG_MSG("dhd_doflow = %d\n", dhd_doflow); } else if (!strncmp("dhd_slpauto=", full_param, len_param) || !strncmp("kso_enable=", full_param, len_param)) { @@ -1957,23 +2773,19 @@ dhd_conf_read_sdio_params(dhd_pub_t *dhd, char *full_param, uint len_param) dhd_slpauto = FALSE; else dhd_slpauto = TRUE; - printf("%s: dhd_slpauto = %d\n", __FUNCTION__, dhd_slpauto); + CONFIG_MSG("dhd_slpauto = %d\n", dhd_slpauto); } else if (!strncmp("use_rxchain=", full_param, len_param)) { conf->use_rxchain = (int)simple_strtol(data, NULL, 10); - printf("%s: use_rxchain = %d\n", __FUNCTION__, conf->use_rxchain); + CONFIG_MSG("use_rxchain = %d\n", conf->use_rxchain); } else if (!strncmp("dhd_txminmax=", full_param, len_param)) { conf->dhd_txminmax = (uint)simple_strtol(data, NULL, 10); - printf("%s: dhd_txminmax = %d\n", __FUNCTION__, conf->dhd_txminmax); + CONFIG_MSG("dhd_txminmax = %d\n", conf->dhd_txminmax); } else if (!strncmp("txinrx_thres=", full_param, len_param)) { conf->txinrx_thres = (int)simple_strtol(data, NULL, 10); - printf("%s: txinrx_thres = %d\n", __FUNCTION__, conf->txinrx_thres); - } - else if (!strncmp("sd_f2_blocksize=", full_param, len_param)) { - conf->sd_f2_blocksize = (int)simple_strtol(data, NULL, 10); - printf("%s: sd_f2_blocksize = %d\n", __FUNCTION__, conf->sd_f2_blocksize); + CONFIG_MSG("txinrx_thres = %d\n", conf->txinrx_thres); } #if defined(HW_OOB) else if (!strncmp("oob_enabled_later=", full_param, len_param)) { @@ -1981,34 +2793,30 @@ dhd_conf_read_sdio_params(dhd_pub_t *dhd, char *full_param, uint len_param) conf->oob_enabled_later = FALSE; else conf->oob_enabled_later = TRUE; - printf("%s: oob_enabled_later = %d\n", __FUNCTION__, conf->oob_enabled_later); + CONFIG_MSG("oob_enabled_later = %d\n", conf->oob_enabled_later); } #endif else if (!strncmp("dpc_cpucore=", full_param, len_param)) { conf->dpc_cpucore = (int)simple_strtol(data, NULL, 10); - printf("%s: dpc_cpucore = %d\n", __FUNCTION__, conf->dpc_cpucore); + CONFIG_MSG("dpc_cpucore = %d\n", conf->dpc_cpucore); } else if (!strncmp("rxf_cpucore=", full_param, len_param)) { conf->rxf_cpucore = (int)simple_strtol(data, NULL, 10); - printf("%s: rxf_cpucore = %d\n", __FUNCTION__, conf->rxf_cpucore); - } - else if (!strncmp("orphan_move=", full_param, len_param)) { - conf->orphan_move = (int)simple_strtol(data, NULL, 10); - printf("%s: orphan_move = %d\n", __FUNCTION__, conf->orphan_move); + CONFIG_MSG("rxf_cpucore = %d\n", conf->rxf_cpucore); } #if defined(BCMSDIOH_TXGLOM) else if (!strncmp("txglomsize=", full_param, len_param)) { conf->txglomsize = (uint)simple_strtol(data, NULL, 10); if (conf->txglomsize > SDPCM_MAXGLOM_SIZE) conf->txglomsize = SDPCM_MAXGLOM_SIZE; - printf("%s: txglomsize = %d\n", __FUNCTION__, conf->txglomsize); + CONFIG_MSG("txglomsize = %d\n", conf->txglomsize); } else if (!strncmp("txglom_ext=", full_param, len_param)) { if (!strncmp(data, "0", 1)) conf->txglom_ext = FALSE; else conf->txglom_ext = TRUE; - printf("%s: txglom_ext = %d\n", __FUNCTION__, conf->txglom_ext); + CONFIG_MSG("txglom_ext = %d\n", conf->txglom_ext); if (conf->txglom_ext) { if ((conf->chip == BCM43362_CHIP_ID) || (conf->chip == BCM4330_CHIP_ID)) conf->txglom_bucket_size = 1680; @@ -2016,34 +2824,52 @@ dhd_conf_read_sdio_params(dhd_pub_t *dhd, char *full_param, uint len_param) conf->chip == BCM4334_CHIP_ID || conf->chip == BCM4324_CHIP_ID) conf->txglom_bucket_size = 1684; } - printf("%s: txglom_bucket_size = %d\n", __FUNCTION__, conf->txglom_bucket_size); + CONFIG_MSG("txglom_bucket_size = %d\n", conf->txglom_bucket_size); } else if (!strncmp("bus:rxglom=", full_param, len_param)) { if (!strncmp(data, "0", 1)) conf->bus_rxglom = FALSE; else conf->bus_rxglom = TRUE; - printf("%s: bus:rxglom = %d\n", __FUNCTION__, conf->bus_rxglom); + CONFIG_MSG("bus:rxglom = %d\n", conf->bus_rxglom); } else if (!strncmp("deferred_tx_len=", full_param, len_param)) { conf->deferred_tx_len = (int)simple_strtol(data, NULL, 10); - printf("%s: deferred_tx_len = %d\n", __FUNCTION__, conf->deferred_tx_len); + CONFIG_MSG("deferred_tx_len = %d\n", conf->deferred_tx_len); } else if (!strncmp("txctl_tmo_fix=", full_param, len_param)) { conf->txctl_tmo_fix = (int)simple_strtol(data, NULL, 0); - printf("%s: txctl_tmo_fix = %d\n", __FUNCTION__, conf->txctl_tmo_fix); + CONFIG_MSG("txctl_tmo_fix = %d\n", conf->txctl_tmo_fix); } else if (!strncmp("tx_max_offset=", full_param, len_param)) { conf->tx_max_offset = (int)simple_strtol(data, NULL, 10); - printf("%s: tx_max_offset = %d\n", __FUNCTION__, conf->tx_max_offset); + CONFIG_MSG("tx_max_offset = %d\n", conf->tx_max_offset); } else if (!strncmp("txglom_mode=", full_param, len_param)) { if (!strncmp(data, "0", 1)) conf->txglom_mode = FALSE; else conf->txglom_mode = TRUE; - printf("%s: txglom_mode = %d\n", __FUNCTION__, conf->txglom_mode); + CONFIG_MSG("txglom_mode = %d\n", conf->txglom_mode); } +#if defined(SDIO_ISR_THREAD) + else if (!strncmp("intr_extn=", full_param, len_param)) { + if (!strncmp(data, "0", 1)) + conf->intr_extn = FALSE; + else + conf->intr_extn = TRUE; + CONFIG_MSG("intr_extn = %d\n", conf->intr_extn); + } +#endif +#ifdef BCMSDIO_RXLIM_POST + else if (!strncmp("rxlim_en=", full_param, len_param)) { + if (!strncmp(data, "0", 1)) + conf->rxlim_en = FALSE; + else + conf->rxlim_en = TRUE; + CONFIG_MSG("rxlim_en = %d\n", conf->rxlim_en); + } +#endif #endif else return false; @@ -2064,7 +2890,7 @@ dhd_conf_read_pcie_params(dhd_pub_t *dhd, char *full_param, uint len_param) conf->bus_deepsleep_disable = 0; else conf->bus_deepsleep_disable = 1; - printf("%s: bus:deepsleep_disable = %d\n", __FUNCTION__, conf->bus_deepsleep_disable); + CONFIG_MSG("bus:deepsleep_disable = %d\n", conf->bus_deepsleep_disable); } else return false; @@ -2084,38 +2910,39 @@ dhd_conf_read_pm_params(dhd_pub_t *dhd, char *full_param, uint len_param) conf->deepsleep = TRUE; else conf->deepsleep = FALSE; - printf("%s: deepsleep = %d\n", __FUNCTION__, conf->deepsleep); + CONFIG_MSG("deepsleep = %d\n", conf->deepsleep); } else if (!strncmp("PM=", full_param, len_param)) { conf->pm = (int)simple_strtol(data, NULL, 10); - printf("%s: PM = %d\n", __FUNCTION__, conf->pm); + CONFIG_MSG("PM = %d\n", conf->pm); } else if (!strncmp("pm_in_suspend=", full_param, len_param)) { conf->pm_in_suspend = (int)simple_strtol(data, NULL, 10); - printf("%s: pm_in_suspend = %d\n", __FUNCTION__, conf->pm_in_suspend); + CONFIG_MSG("pm_in_suspend = %d\n", conf->pm_in_suspend); + } + else if (!strncmp("suspend_mode=", full_param, len_param)) { + conf->suspend_mode = (int)simple_strtol(data, NULL, 0); + CONFIG_MSG("suspend_mode = %d\n", conf->suspend_mode); } else if (!strncmp("suspend_bcn_li_dtim=", full_param, len_param)) { conf->suspend_bcn_li_dtim = (int)simple_strtol(data, NULL, 10); - printf("%s: suspend_bcn_li_dtim = %d\n", __FUNCTION__, conf->suspend_bcn_li_dtim); + CONFIG_MSG("suspend_bcn_li_dtim = %d\n", conf->suspend_bcn_li_dtim); } else if (!strncmp("xmit_in_suspend=", full_param, len_param)) { if (!strncmp(data, "1", 1)) - conf->xmit_in_suspend = TRUE; + conf->insuspend &= ~NO_TXDATA_IN_SUSPEND; else - conf->xmit_in_suspend = FALSE; - printf("%s: xmit_in_suspend = %d\n", __FUNCTION__, conf->xmit_in_suspend); + conf->insuspend |= NO_TXDATA_IN_SUSPEND; + CONFIG_MSG("insuspend = 0x%x\n", conf->insuspend); } - else if (!strncmp("ap_in_suspend=", full_param, len_param)) { - conf->ap_in_suspend = (int)simple_strtol(data, NULL, 10); - printf("%s: ap_in_suspend = %d\n", __FUNCTION__, conf->ap_in_suspend); + else if (!strncmp("insuspend=", full_param, len_param)) { + conf->insuspend = (int)simple_strtol(data, NULL, 0); + CONFIG_MSG("insuspend = 0x%x\n", conf->insuspend); } -#ifdef SUSPEND_EVENT - else if (!strncmp("suspend_eventmask_enable=", full_param, len_param)) { - if (!strncmp(data, "1", 1)) - conf->suspend_eventmask_enable = TRUE; - else - conf->suspend_eventmask_enable = FALSE; - printf("%s: suspend_eventmask_enable = %d\n", __FUNCTION__, conf->suspend_eventmask_enable); +#ifdef WL_EXT_WOWL + else if (!strncmp("wowl=", full_param, len_param)) { + conf->wowl = (int)simple_strtol(data, NULL, 0); + CONFIG_MSG("wowl = 0x%x\n", conf->wowl); } #endif else @@ -2124,25 +2951,46 @@ dhd_conf_read_pm_params(dhd_pub_t *dhd, char *full_param, uint len_param) return true; } +#ifdef GET_CUSTOM_MAC_FROM_CONFIG +int +bcm_str2hex(const char *p, char *ea, int size) +{ + int i = 0; + char *ep; + + for (;;) { + ea[i++] = (char) bcm_strtoul(p, &ep, 16); + p = ep; + if (!*p++ || i == size) + break; + } + + return (i == size); +} +#endif + bool dhd_conf_read_others(dhd_pub_t *dhd, char *full_param, uint len_param) { struct dhd_conf *conf = dhd->conf; char *data = full_param+len_param; - uint len_data = strlen(data); char *pch, *pick_tmp; int i; +#ifdef GET_CUSTOM_MAC_FROM_CONFIG + struct ether_addr ea_addr; + char macpad[56]; +#endif if (!strncmp("dhd_poll=", full_param, len_param)) { if (!strncmp(data, "0", 1)) conf->dhd_poll = 0; else conf->dhd_poll = 1; - printf("%s: dhd_poll = %d\n", __FUNCTION__, conf->dhd_poll); + CONFIG_MSG("dhd_poll = %d\n", conf->dhd_poll); } else if (!strncmp("dhd_watchdog_ms=", full_param, len_param)) { dhd_watchdog_ms = (int)simple_strtol(data, NULL, 10); - printf("%s: dhd_watchdog_ms = %d\n", __FUNCTION__, dhd_watchdog_ms); + CONFIG_MSG("dhd_watchdog_ms = %d\n", dhd_watchdog_ms); } else if (!strncmp("band=", full_param, len_param)) { /* Process band: @@ -2154,39 +3002,29 @@ dhd_conf_read_others(dhd_pub_t *dhd, char *full_param, uint len_param) conf->band = WLC_BAND_5G; else conf->band = WLC_BAND_AUTO; - printf("%s: band = %d\n", __FUNCTION__, conf->band); + CONFIG_MSG("band = %d\n", conf->band); } else if (!strncmp("bw_cap_2g=", full_param, len_param)) { conf->bw_cap[0] = (uint)simple_strtol(data, NULL, 0); - printf("%s: bw_cap_2g = %d\n", __FUNCTION__, conf->bw_cap[0]); + CONFIG_MSG("bw_cap_2g = %d\n", conf->bw_cap[0]); } else if (!strncmp("bw_cap_5g=", full_param, len_param)) { conf->bw_cap[1] = (uint)simple_strtol(data, NULL, 0); - printf("%s: bw_cap_5g = %d\n", __FUNCTION__, conf->bw_cap[1]); + CONFIG_MSG("bw_cap_5g = %d\n", conf->bw_cap[1]); } else if (!strncmp("bw_cap=", full_param, len_param)) { pick_tmp = data; pch = bcmstrtok(&pick_tmp, " ,.-", 0); if (pch != NULL) { conf->bw_cap[0] = (uint32)simple_strtol(pch, NULL, 0); - printf("%s: bw_cap 2g = %d\n", __FUNCTION__, conf->bw_cap[0]); + CONFIG_MSG("bw_cap 2g = %d\n", conf->bw_cap[0]); } pch = bcmstrtok(&pick_tmp, " ,.-", 0); if (pch != NULL) { conf->bw_cap[1] = (uint32)simple_strtol(pch, NULL, 0); - printf("%s: bw_cap 5g = %d\n", __FUNCTION__, conf->bw_cap[1]); + CONFIG_MSG("bw_cap 5g = %d\n", conf->bw_cap[1]); } } - else if (!strncmp("ccode=", full_param, len_param)) { - memset(&conf->cspec, 0, sizeof(wl_country_t)); - memcpy(conf->cspec.country_abbrev, data, len_data); - memcpy(conf->cspec.ccode, data, len_data); - printf("%s: ccode = %s\n", __FUNCTION__, conf->cspec.ccode); - } - else if (!strncmp("regrev=", full_param, len_param)) { - conf->cspec.rev = (int32)simple_strtol(data, NULL, 10); - printf("%s: regrev = %d\n", __FUNCTION__, conf->cspec.rev); - } else if (!strncmp("channels=", full_param, len_param)) { pick_tmp = data; pch = bcmstrtok(&pick_tmp, " ,.-", 0); @@ -2197,93 +3035,118 @@ dhd_conf_read_others(dhd_pub_t *dhd, char *full_param, uint len_param) i++; } conf->channels.count = i; - printf("%s: channels = ", __FUNCTION__); + CONFIG_MSG("channels = "); for (i=0; ichannels.count; i++) printf("%d ", conf->channels.channel[i]); printf("\n"); } else if (!strncmp("keep_alive_period=", full_param, len_param)) { conf->keep_alive_period = (uint)simple_strtol(data, NULL, 10); - printf("%s: keep_alive_period = %d\n", __FUNCTION__, - conf->keep_alive_period); + CONFIG_MSG("keep_alive_period = %d\n", conf->keep_alive_period); } - else if (!strncmp("phy_oclscdenable=", full_param, len_param)) { - conf->phy_oclscdenable = (int)simple_strtol(data, NULL, 10); - printf("%s: phy_oclscdenable = %d\n", __FUNCTION__, conf->phy_oclscdenable); +#ifdef ARP_OFFLOAD_SUPPORT + else if (!strncmp("garp=", full_param, len_param)) { + if (!strncmp(data, "0", 1)) + conf->garp = FALSE; + else + conf->garp = TRUE; + CONFIG_MSG("garp = %d\n", conf->garp); } +#endif else if (!strncmp("srl=", full_param, len_param)) { conf->srl = (int)simple_strtol(data, NULL, 10); - printf("%s: srl = %d\n", __FUNCTION__, conf->srl); + CONFIG_MSG("srl = %d\n", conf->srl); } else if (!strncmp("lrl=", full_param, len_param)) { conf->lrl = (int)simple_strtol(data, NULL, 10); - printf("%s: lrl = %d\n", __FUNCTION__, conf->lrl); + CONFIG_MSG("lrl = %d\n", conf->lrl); } else if (!strncmp("bcn_timeout=", full_param, len_param)) { conf->bcn_timeout= (uint)simple_strtol(data, NULL, 10); - printf("%s: bcn_timeout = %d\n", __FUNCTION__, conf->bcn_timeout); - } - else if (!strncmp("txbf=", full_param, len_param)) { - conf->txbf = (int)simple_strtol(data, NULL, 10); - printf("%s: txbf = %d\n", __FUNCTION__, conf->txbf); + CONFIG_MSG("bcn_timeout = %d\n", conf->bcn_timeout); } else if (!strncmp("frameburst=", full_param, len_param)) { conf->frameburst = (int)simple_strtol(data, NULL, 10); - printf("%s: frameburst = %d\n", __FUNCTION__, conf->frameburst); + CONFIG_MSG("frameburst = %d\n", conf->frameburst); } else if (!strncmp("disable_proptx=", full_param, len_param)) { conf->disable_proptx = (int)simple_strtol(data, NULL, 10); - printf("%s: disable_proptx = %d\n", __FUNCTION__, conf->disable_proptx); + CONFIG_MSG("disable_proptx = %d\n", conf->disable_proptx); } #ifdef DHDTCPACK_SUPPRESS else if (!strncmp("tcpack_sup_mode=", full_param, len_param)) { conf->tcpack_sup_mode = (uint)simple_strtol(data, NULL, 10); - printf("%s: tcpack_sup_mode = %d\n", __FUNCTION__, conf->tcpack_sup_mode); + CONFIG_MSG("tcpack_sup_mode = %d\n", conf->tcpack_sup_mode); } #endif else if (!strncmp("pktprio8021x=", full_param, len_param)) { conf->pktprio8021x = (int)simple_strtol(data, NULL, 10); - printf("%s: pktprio8021x = %d\n", __FUNCTION__, conf->pktprio8021x); + CONFIG_MSG("pktprio8021x = %d\n", conf->pktprio8021x); } #if defined(BCMSDIO) || defined(BCMPCIE) else if (!strncmp("dhd_txbound=", full_param, len_param)) { dhd_txbound = (uint)simple_strtol(data, NULL, 10); - printf("%s: dhd_txbound = %d\n", __FUNCTION__, dhd_txbound); + CONFIG_MSG("dhd_txbound = %d\n", dhd_txbound); } else if (!strncmp("dhd_rxbound=", full_param, len_param)) { dhd_rxbound = (uint)simple_strtol(data, NULL, 10); - printf("%s: dhd_rxbound = %d\n", __FUNCTION__, dhd_rxbound); + CONFIG_MSG("dhd_rxbound = %d\n", dhd_rxbound); } #endif + else if (!strncmp("orphan_move=", full_param, len_param)) { + conf->orphan_move = (int)simple_strtol(data, NULL, 10); + CONFIG_MSG("orphan_move = %d\n", conf->orphan_move); + } else if (!strncmp("tsq=", full_param, len_param)) { conf->tsq = (int)simple_strtol(data, NULL, 10); - printf("%s: tsq = %d\n", __FUNCTION__, conf->tsq); + CONFIG_MSG("tsq = %d\n", conf->tsq); } else if (!strncmp("ctrl_resched=", full_param, len_param)) { conf->ctrl_resched = (int)simple_strtol(data, NULL, 10); - printf("%s: ctrl_resched = %d\n", __FUNCTION__, conf->ctrl_resched); - } - else if (!strncmp("dhd_ioctl_timeout_msec=", full_param, len_param)) { - conf->dhd_ioctl_timeout_msec = (int)simple_strtol(data, NULL, 10); - printf("%s: dhd_ioctl_timeout_msec = %d\n", __FUNCTION__, conf->dhd_ioctl_timeout_msec); + CONFIG_MSG("ctrl_resched = %d\n", conf->ctrl_resched); } else if (!strncmp("in4way=", full_param, len_param)) { conf->in4way = (int)simple_strtol(data, NULL, 0); - printf("%s: in4way = 0x%x\n", __FUNCTION__, conf->in4way); - } - else if (!strncmp("max_wait_gc_time=", full_param, len_param)) { - conf->max_wait_gc_time = (int)simple_strtol(data, NULL, 0); - printf("%s: max_wait_gc_time = %d\n", __FUNCTION__, conf->max_wait_gc_time); + CONFIG_MSG("in4way = 0x%x\n", conf->in4way); } else if (!strncmp("wl_preinit=", full_param, len_param)) { + if (conf->wl_preinit) { + kfree(conf->wl_preinit); + conf->wl_preinit = NULL; + } if (!(conf->wl_preinit = kmalloc(len_param+1, GFP_KERNEL))) { - CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); + CONFIG_ERROR("kmalloc failed\n"); } else { memset(conf->wl_preinit, 0, len_param+1); strcpy(conf->wl_preinit, data); - printf("%s: wl_preinit = %s\n", __FUNCTION__, conf->wl_preinit); + CONFIG_MSG("wl_preinit = %s\n", conf->wl_preinit); } } +#ifdef GET_CUSTOM_MAC_FROM_CONFIG + else if (!strncmp("mac=", full_param, len_param)) { + if (!bcm_ether_atoe(data, &ea_addr)) { + CONFIG_ERROR("mac adress read error"); + return false; + } + memcpy(&conf->hw_ether, &ea_addr, ETHER_ADDR_LEN); + CONFIG_MSG("mac = %s\n", data); + } + else if (!strncmp("macpad=", full_param, len_param)) { + if (!bcm_str2hex(data, macpad, sizeof(macpad))) { + CONFIG_ERROR("macpad adress read error"); + return false; + } + memcpy(&conf->hw_ether[ETHER_ADDR_LEN], macpad, sizeof(macpad)); + if (config_msg_level & CONFIG_TRACE_LEVEL) { + printf("macpad =\n"); + for (i=0; ihw_ether[ETHER_ADDR_LEN+i]); + if ((i+1)%8 == 0) + printf("\n"); + } + } + } +#endif else return false; @@ -2293,39 +3156,37 @@ dhd_conf_read_others(dhd_pub_t *dhd, char *full_param, uint len_param) int dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path) { - int bcmerror = -1; - uint len = 0, start_pos=0; - void * image = NULL; - char * memblock = NULL; + int bcmerror = -1, chip_match = -1; + uint len = 0, start_pos=0, end_pos=0; + void *image = NULL; + char *memblock = NULL; char *bufp, *pick = NULL, *pch; bool conf_file_exists; uint len_param; conf_file_exists = ((conf_path != NULL) && (conf_path[0] != '\0')); if (!conf_file_exists) { - printf("%s: config path %s\n", __FUNCTION__, conf_path); + CONFIG_MSG("config path %s\n", conf_path); return (0); } if (conf_file_exists) { image = dhd_os_open_image(conf_path); if (image == NULL) { - printf("%s: Ignore config file %s\n", __FUNCTION__, conf_path); + CONFIG_MSG("Ignore config file %s\n", conf_path); goto err; } } memblock = MALLOC(dhd->osh, MAXSZ_CONFIG); if (memblock == NULL) { - CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n", - __FUNCTION__, MAXSZ_CONFIG)); + CONFIG_ERROR("Failed to allocate memory %d bytes\n", MAXSZ_CONFIG); goto err; } pick = MALLOC(dhd->osh, MAXSZ_BUF); if (!pick) { - CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n", - __FUNCTION__, MAXSZ_BUF)); + CONFIG_ERROR("Failed to allocate memory %d bytes\n", MAXSZ_BUF); goto err; } @@ -2339,32 +3200,41 @@ dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path) while (start_pos < len) { memset(pick, 0, MAXSZ_BUF); - start_pos = pick_config_vars(bufp, len, start_pos, pick); + end_pos = pick_config_vars(bufp, len, start_pos, pick, MAXSZ_BUF); + if (end_pos - start_pos >= MAXSZ_BUF) + CONFIG_ERROR("out of buf to read MAXSIZ_BUF=%d\n", MAXSZ_BUF); + start_pos = end_pos; pch = strchr(pick, '='); if (pch != NULL) { len_param = pch-pick+1; if (len_param == strlen(pick)) { - CONFIG_ERROR(("%s: not a right parameter %s\n", __FUNCTION__, pick)); + CONFIG_ERROR("not a right parameter %s\n", pick); continue; } } else { - CONFIG_ERROR(("%s: not a right parameter %s\n", __FUNCTION__, pick)); + CONFIG_ERROR("not a right parameter %s\n", pick); continue; } + dhd_conf_read_chiprev(dhd, &chip_match, pick, len_param); + if (!chip_match) + continue; + if (dhd_conf_read_log_level(dhd, pick, len_param)) continue; else if (dhd_conf_read_roam_params(dhd, pick, len_param)) continue; else if (dhd_conf_read_wme_ac_params(dhd, pick, len_param)) continue; +#ifdef BCMSDIO else if (dhd_conf_read_fw_by_mac(dhd, pick, len_param)) continue; else if (dhd_conf_read_nv_by_mac(dhd, pick, len_param)) continue; +#endif else if (dhd_conf_read_nv_by_chip(dhd, pick, len_param)) continue; - else if (dhd_conf_read_country_list(dhd, pick, len_param)) + else if (dhd_conf_read_country(dhd, pick, len_param)) continue; else if (dhd_conf_read_mchan_params(dhd, pick, len_param)) continue; @@ -2398,7 +3268,7 @@ dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path) bcmerror = 0; } else { - CONFIG_ERROR(("%s: error reading config file: %d\n", __FUNCTION__, len)); + CONFIG_ERROR("error reading config file: %d\n", len); bcmerror = BCME_SDIO_ERROR; } @@ -2418,7 +3288,7 @@ err: int dhd_conf_set_chiprev(dhd_pub_t *dhd, uint chip, uint chiprev) { - printf("%s: chip=0x%x, chiprev=%d\n", __FUNCTION__, chip, chiprev); + CONFIG_MSG("chip=0x%x, chiprev=%d\n", chip, chiprev); dhd->conf->chip = chip; dhd->conf->chiprev = chiprev; return 0; @@ -2459,6 +3329,17 @@ dhd_conf_set_txglom_params(dhd_pub_t *dhd, bool enable) } #endif // other parameters set in preinit or config.txt + if (conf->txglom_ext) + CONFIG_MSG("txglom_ext=%d, txglom_bucket_size=%d\n", + conf->txglom_ext, conf->txglom_bucket_size); + CONFIG_MSG("txglom_mode=%s\n", + conf->txglom_mode==SDPCM_TXGLOM_MDESC?"multi-desc":"copy"); + CONFIG_MSG("txglomsize=%d, deferred_tx_len=%d\n", + conf->txglomsize, conf->deferred_tx_len); + CONFIG_MSG("txinrx_thres=%d, dhd_txminmax=%d\n", + conf->txinrx_thres, conf->dhd_txminmax); + CONFIG_MSG("tx_max_offset=%d, txctl_tmo_fix=%d\n", + conf->tx_max_offset, conf->txctl_tmo_fix); } else { // clear txglom parameters conf->txglom_ext = FALSE; @@ -2466,17 +3347,6 @@ dhd_conf_set_txglom_params(dhd_pub_t *dhd, bool enable) conf->txglomsize = 0; conf->deferred_tx_len = 0; } - if (conf->txglom_ext) - printf("%s: txglom_ext=%d, txglom_bucket_size=%d\n", __FUNCTION__, - conf->txglom_ext, conf->txglom_bucket_size); - printf("%s: txglom_mode=%s\n", __FUNCTION__, - conf->txglom_mode==SDPCM_TXGLOM_MDESC?"multi-desc":"copy"); - printf("%s: txglomsize=%d, deferred_tx_len=%d\n", __FUNCTION__, - conf->txglomsize, conf->deferred_tx_len); - printf("%s: txinrx_thres=%d, dhd_txminmax=%d\n", __FUNCTION__, - conf->txinrx_thres, conf->dhd_txminmax); - printf("%s: tx_max_offset=%d, txctl_tmo_fix=%d\n", __FUNCTION__, - conf->tx_max_offset, conf->txctl_tmo_fix); } #endif @@ -2491,9 +3361,9 @@ dhd_conf_rsdb_mode(dhd_pub_t *dhd, char *buf) rsdb_mode_cfg.config = (int)simple_strtol(pch, NULL, 0); if (pch) { - dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "rsdb_mode", (char *)&rsdb_mode_cfg, + dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "rsdb_mode", (char *)&rsdb_mode_cfg, sizeof(rsdb_mode_cfg), TRUE); - printf("%s: rsdb_mode %d\n", __FUNCTION__, rsdb_mode_cfg.config); + CONFIG_MSG("rsdb_mode %d\n", rsdb_mode_cfg.config); } return 0; @@ -2573,8 +3443,9 @@ void dhd_conf_postinit_ioctls(dhd_pub_t *dhd) { struct dhd_conf *conf = dhd->conf; + char wl_preinit[] = "assoc_retry_max=30"; - dhd_conf_set_intiovar(dhd, WLC_UP, "up", 0, 0, FALSE); + dhd_conf_set_intiovar(dhd, WLC_UP, "WLC_UP", 0, 0, FALSE); dhd_conf_map_country_list(dhd, &conf->cspec); dhd_conf_set_country(dhd, &conf->cspec); dhd_conf_fix_country(dhd); @@ -2582,8 +3453,8 @@ dhd_conf_postinit_ioctls(dhd_pub_t *dhd) dhd_conf_set_intiovar(dhd, WLC_SET_BAND, "WLC_SET_BAND", conf->band, 0, FALSE); dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "bcn_timeout", conf->bcn_timeout, 0, FALSE); - dhd_conf_set_intiovar(dhd, WLC_SET_PM, "PM", conf->pm, 0, FALSE); - dhd_conf_set_intiovar(dhd, WLC_SET_SRL, "WLC_SET_SRL", conf->srl, 0, TRUE); + dhd_conf_set_intiovar(dhd, WLC_SET_PM, "WLC_SET_PM", conf->pm, 0, FALSE); + dhd_conf_set_intiovar(dhd, WLC_SET_SRL, "WLC_SET_SRL", conf->srl, 0, FALSE); dhd_conf_set_intiovar(dhd, WLC_SET_LRL, "WLC_SET_LRL", conf->lrl, 0, FALSE); dhd_conf_set_bw_cap(dhd); dhd_conf_set_roam(dhd); @@ -2594,27 +3465,40 @@ dhd_conf_postinit_ioctls(dhd_pub_t *dhd) #endif /* defined(BCMPCIE) */ #ifdef IDHCP - dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "dhcpc_enable", conf->dhcpc_enable, 0, FALSE); - if (dhd->conf->dhcpd_enable >= 0) { - dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "dhcpd_ip_addr", + dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "dhcpc_enable", conf->dhcpc_enable, + 0, FALSE); + if (conf->dhcpd_enable >= 0) { + dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "dhcpd_ip_addr", (char *)&conf->dhcpd_ip_addr, sizeof(conf->dhcpd_ip_addr), FALSE); - dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "dhcpd_ip_mask", + dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "dhcpd_ip_mask", (char *)&conf->dhcpd_ip_mask, sizeof(conf->dhcpd_ip_mask), FALSE); - dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "dhcpd_ip_start", + dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "dhcpd_ip_start", (char *)&conf->dhcpd_ip_start, sizeof(conf->dhcpd_ip_start), FALSE); - dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "dhcpd_ip_end", + dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "dhcpd_ip_end", (char *)&conf->dhcpd_ip_end, sizeof(conf->dhcpd_ip_end), FALSE); dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "dhcpd_enable", conf->dhcpd_enable, 0, FALSE); } #endif - dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "txbf", conf->txbf, 0, FALSE); - dhd_conf_set_intiovar(dhd, WLC_SET_FAKEFRAG, "WLC_SET_FAKEFRAG", conf->frameburst, 0, FALSE); + dhd_conf_set_intiovar(dhd, WLC_SET_FAKEFRAG, "WLC_SET_FAKEFRAG", + conf->frameburst, 0, FALSE); + dhd_conf_set_wl_preinit(dhd, wl_preinit); +#if defined(BCMSDIO) + { + char ampdu_mpdu[] = "ampdu_mpdu=16"; + dhd_conf_set_wl_preinit(dhd, ampdu_mpdu); + } +#endif + if (conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID || + conf->chip == BCM4371_CHIP_ID || conf->chip == BCM4359_CHIP_ID || + conf->chip == BCM43569_CHIP_ID) { + dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "txbf", 1, 0, FALSE); + } dhd_conf_set_wl_preinit(dhd, conf->wl_preinit); #ifndef WL_CFG80211 - dhd_conf_set_intiovar(dhd, WLC_UP, "up", 0, 0, FALSE); + dhd_conf_set_intiovar(dhd, WLC_UP, "WLC_UP", 0, 0, FALSE); #endif } @@ -2623,16 +3507,16 @@ int dhd_conf_preinit(dhd_pub_t *dhd) { struct dhd_conf *conf = dhd->conf; - int i; - CONFIG_TRACE(("%s: Enter\n", __FUNCTION__)); + CONFIG_TRACE("Enter\n"); #ifdef BCMSDIO dhd_conf_free_mac_list(&conf->fw_by_mac); dhd_conf_free_mac_list(&conf->nv_by_mac); - dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip); #endif - dhd_conf_free_country_list(&conf->country_list); + dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip); + dhd_conf_free_country_list(conf); + dhd_conf_free_mchan_list(conf); if (conf->magic_pkt_filter_add) { kfree(conf->magic_pkt_filter_add); conf->magic_pkt_filter_add = NULL; @@ -2641,7 +3525,6 @@ dhd_conf_preinit(dhd_pub_t *dhd) kfree(conf->wl_preinit); conf->wl_preinit = NULL; } - memset(&conf->country_list, 0, sizeof(conf_country_list_t)); conf->band = -1; memset(&conf->bw_cap, -1, sizeof(conf->bw_cap)); if (conf->chip == BCM43362_CHIP_ID || conf->chip == BCM4330_CHIP_ID) { @@ -2651,8 +3534,7 @@ dhd_conf_preinit(dhd_pub_t *dhd) } else if (conf->chip == BCM4335_CHIP_ID || conf->chip == BCM4339_CHIP_ID || conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID || conf->chip == BCM4345_CHIP_ID || conf->chip == BCM4371_CHIP_ID || - conf->chip == BCM43569_CHIP_ID || conf->chip == BCM4359_CHIP_ID || - conf->chip == BCM4362_CHIP_ID) { + conf->chip == BCM43569_CHIP_ID || conf->chip == BCM4359_CHIP_ID) { strcpy(conf->cspec.country_abbrev, "CN"); strcpy(conf->cspec.ccode, "CN"); conf->cspec.rev = 38; @@ -2664,34 +3546,20 @@ dhd_conf_preinit(dhd_pub_t *dhd) memset(&conf->channels, 0, sizeof(wl_channel_list_t)); conf->roam_off = 1; conf->roam_off_suspend = 1; -#ifdef CUSTOM_ROAM_TRIGGER_SETTING - conf->roam_trigger[0] = CUSTOM_ROAM_TRIGGER_SETTING; -#else conf->roam_trigger[0] = -65; -#endif conf->roam_trigger[1] = WLC_BAND_ALL; conf->roam_scan_period[0] = 10; conf->roam_scan_period[1] = WLC_BAND_ALL; -#ifdef CUSTOM_ROAM_DELTA_SETTING - conf->roam_delta[0] = CUSTOM_ROAM_DELTA_SETTING; -#else - conf->roam_delta[0] = 15; -#endif + conf->roam_delta[0] = 10; conf->roam_delta[1] = WLC_BAND_ALL; -#ifdef FULL_ROAMING_SCAN_PERIOD_60_SEC - conf->fullroamperiod = 60; -#else /* FULL_ROAMING_SCAN_PERIOD_60_SEC */ - conf->fullroamperiod = 120; -#endif /* FULL_ROAMING_SCAN_PERIOD_60_SEC */ -#ifdef CUSTOM_KEEP_ALIVE_SETTING - conf->keep_alive_period = CUSTOM_KEEP_ALIVE_SETTING; -#else - conf->keep_alive_period = 28000; + conf->fullroamperiod = 20; + conf->keep_alive_period = 30000; +#ifdef ARP_OFFLOAD_SUPPORT + conf->garp = FALSE; #endif conf->force_wme_ac = 0; memset(&conf->wme_sta, 0, sizeof(wme_param_t)); memset(&conf->wme_ap, 0, sizeof(wme_param_t)); - conf->phy_oclscdenable = -1; #ifdef PKT_FILTER_SUPPORT memset(&conf->pkt_filter_add, 0, sizeof(conf_pkt_filter_add_t)); memset(&conf->pkt_filter_del, 0, sizeof(conf_pkt_filter_del_t)); @@ -2699,7 +3567,6 @@ dhd_conf_preinit(dhd_pub_t *dhd) conf->srl = -1; conf->lrl = -1; conf->bcn_timeout = 16; - conf->txbf = -1; conf->disable_proptx = -1; conf->dhd_poll = -1; #ifdef BCMSDIO @@ -2708,16 +3575,20 @@ dhd_conf_preinit(dhd_pub_t *dhd) conf->txglom_ext = FALSE; conf->tx_max_offset = 0; conf->txglomsize = SDPCM_DEFGLOM_SIZE; - conf->txctl_tmo_fix = -1; + conf->txctl_tmo_fix = 300; conf->txglom_mode = SDPCM_TXGLOM_CPY; conf->deferred_tx_len = 0; conf->dhd_txminmax = 1; conf->txinrx_thres = -1; - conf->sd_f2_blocksize = 0; +#if defined(SDIO_ISR_THREAD) + conf->intr_extn = FALSE; +#endif +#ifdef BCMSDIO_RXLIM_POST + conf->rxlim_en = TRUE; +#endif #if defined(HW_OOB) conf->oob_enabled_later = FALSE; #endif - conf->orphan_move = 0; #endif #ifdef BCMPCIE conf->bus_deepsleep_disable = 1; @@ -2728,18 +3599,29 @@ dhd_conf_preinit(dhd_pub_t *dhd) conf->deepsleep = FALSE; conf->pm = -1; conf->pm_in_suspend = -1; + conf->suspend_mode = EARLY_SUSPEND; conf->suspend_bcn_li_dtim = -1; - conf->xmit_in_suspend = TRUE; - conf->ap_in_suspend = 0; +#ifdef WL_EXT_WOWL + dhd_master_mode = TRUE; + conf->wowl = WL_WOWL_NET|WL_WOWL_DIS|WL_WOWL_BCN; + conf->insuspend = WOWL_IN_SUSPEND | NO_TXDATA_IN_SUSPEND; +#else + conf->insuspend = 0; +#endif + conf->suspended = FALSE; #ifdef SUSPEND_EVENT - conf->suspend_eventmask_enable = FALSE; - memset(&conf->suspend_eventmask, 0, sizeof(conf->suspend_eventmask)); memset(&conf->resume_eventmask, 0, sizeof(conf->resume_eventmask)); + memset(&conf->bssid_insuspend, 0, ETHER_ADDR_LEN); + conf->wlfc = FALSE; +#endif +#ifdef GET_CUSTOM_MAC_FROM_CONFIG + memset(&conf->hw_ether, 0, sizeof(conf->hw_ether)); #endif #ifdef IDHCP conf->dhcpc_enable = -1; conf->dhcpd_enable = -1; #endif + conf->orphan_move = 0; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) conf->tsq = 10; #else @@ -2754,22 +3636,29 @@ dhd_conf_preinit(dhd_pub_t *dhd) #endif conf->pktprio8021x = -1; conf->ctrl_resched = 2; - conf->dhd_ioctl_timeout_msec = 0; conf->in4way = NO_SCAN_IN4WAY | WAIT_DISCONNECTED; - conf->max_wait_gc_time = 300; #ifdef ISAM_PREINIT memset(conf->isam_init, 0, sizeof(conf->isam_init)); memset(conf->isam_config, 0, sizeof(conf->isam_config)); memset(conf->isam_enable, 0, sizeof(conf->isam_enable)); #endif - for (i=0; imchan[i], -1, sizeof(mchan_params_t)); - } - if (conf->chip == BCM4335_CHIP_ID || conf->chip == BCM4339_CHIP_ID || +#if defined(SDIO_ISR_THREAD) + if (conf->chip == BCM43012_CHIP_ID || + conf->chip == BCM4335_CHIP_ID || conf->chip == BCM4339_CHIP_ID || + conf->chip == BCM43454_CHIP_ID || conf->chip == BCM4345_CHIP_ID || conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID || conf->chip == BCM4345_CHIP_ID || conf->chip == BCM4371_CHIP_ID || - conf->chip == BCM43569_CHIP_ID || conf->chip == BCM4359_CHIP_ID || - conf->chip == BCM4362_CHIP_ID) { + conf->chip == BCM4359_CHIP_ID) { + conf->intr_extn = TRUE; + } +#endif + if ((conf->chip == BCM43430_CHIP_ID && conf->chiprev == 2) || + conf->chip == BCM43012_CHIP_ID || + conf->chip == BCM4335_CHIP_ID || conf->chip == BCM4339_CHIP_ID || + conf->chip == BCM43454_CHIP_ID || conf->chip == BCM4345_CHIP_ID || + conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID || + conf->chip == BCM4345_CHIP_ID || conf->chip == BCM4371_CHIP_ID || + conf->chip == BCM43569_CHIP_ID || conf->chip == BCM4359_CHIP_ID) { #ifdef DHDTCPACK_SUPPRESS #ifdef BCMSDIO conf->tcpack_sup_mode = TCPACK_SUP_REPLACE; @@ -2779,17 +3668,15 @@ dhd_conf_preinit(dhd_pub_t *dhd) dhd_rxbound = 128; dhd_txbound = 64; #endif - conf->txbf = 1; conf->frameburst = 1; #ifdef BCMSDIO conf->dhd_txminmax = -1; conf->txinrx_thres = 128; - conf->sd_f2_blocksize = CUSTOM_SDIO_F2_BLKSIZE; +#endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) conf->orphan_move = 1; #else conf->orphan_move = 0; -#endif #endif } @@ -2815,6 +3702,7 @@ dhd_conf_preinit(dhd_pub_t *dhd) if (conf->txglomsize > SDPCM_MAXGLOM_SIZE) conf->txglomsize = SDPCM_MAXGLOM_SIZE; #endif + init_waitqueue_head(&conf->event_complete); return 0; } @@ -2822,21 +3710,24 @@ dhd_conf_preinit(dhd_pub_t *dhd) int dhd_conf_reset(dhd_pub_t *dhd) { + struct dhd_conf *conf = dhd->conf; + #ifdef BCMSDIO - dhd_conf_free_mac_list(&dhd->conf->fw_by_mac); - dhd_conf_free_mac_list(&dhd->conf->nv_by_mac); - dhd_conf_free_chip_nv_path_list(&dhd->conf->nv_by_chip); + dhd_conf_free_mac_list(&conf->fw_by_mac); + dhd_conf_free_mac_list(&conf->nv_by_mac); #endif - dhd_conf_free_country_list(&dhd->conf->country_list); - if (dhd->conf->magic_pkt_filter_add) { - kfree(dhd->conf->magic_pkt_filter_add); - dhd->conf->magic_pkt_filter_add = NULL; + dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip); + dhd_conf_free_country_list(conf); + dhd_conf_free_mchan_list(conf); + if (conf->magic_pkt_filter_add) { + kfree(conf->magic_pkt_filter_add); + conf->magic_pkt_filter_add = NULL; } - if (dhd->conf->wl_preinit) { - kfree(dhd->conf->wl_preinit); - dhd->conf->wl_preinit = NULL; + if (conf->wl_preinit) { + kfree(conf->wl_preinit); + conf->wl_preinit = NULL; } - memset(dhd->conf, 0, sizeof(dhd_conf_t)); + memset(conf, 0, sizeof(dhd_conf_t)); return 0; } @@ -2845,15 +3736,15 @@ dhd_conf_attach(dhd_pub_t *dhd) { dhd_conf_t *conf; - CONFIG_TRACE(("%s: Enter\n", __FUNCTION__)); + CONFIG_TRACE("Enter\n"); if (dhd->conf != NULL) { - printf("%s: config is attached before!\n", __FUNCTION__); + CONFIG_MSG("config is attached before!\n"); return 0; } /* Allocate private bus interface state */ if (!(conf = MALLOC(dhd->osh, sizeof(dhd_conf_t)))) { - CONFIG_ERROR(("%s: MALLOC failed\n", __FUNCTION__)); + CONFIG_ERROR("MALLOC failed\n"); goto fail; } memset(conf, 0, sizeof(dhd_conf_t)); @@ -2871,24 +3762,26 @@ fail: void dhd_conf_detach(dhd_pub_t *dhd) { - CONFIG_TRACE(("%s: Enter\n", __FUNCTION__)); + struct dhd_conf *conf = dhd->conf; + CONFIG_TRACE("Enter\n"); if (dhd->conf) { #ifdef BCMSDIO - dhd_conf_free_mac_list(&dhd->conf->fw_by_mac); - dhd_conf_free_mac_list(&dhd->conf->nv_by_mac); - dhd_conf_free_chip_nv_path_list(&dhd->conf->nv_by_chip); + dhd_conf_free_mac_list(&conf->fw_by_mac); + dhd_conf_free_mac_list(&conf->nv_by_mac); #endif - dhd_conf_free_country_list(&dhd->conf->country_list); - if (dhd->conf->magic_pkt_filter_add) { - kfree(dhd->conf->magic_pkt_filter_add); - dhd->conf->magic_pkt_filter_add = NULL; + dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip); + dhd_conf_free_country_list(conf); + dhd_conf_free_mchan_list(conf); + if (conf->magic_pkt_filter_add) { + kfree(conf->magic_pkt_filter_add); + conf->magic_pkt_filter_add = NULL; } - if (dhd->conf->wl_preinit) { - kfree(dhd->conf->wl_preinit); - dhd->conf->wl_preinit = NULL; + if (conf->wl_preinit) { + kfree(conf->wl_preinit); + conf->wl_preinit = NULL; } - MFREE(dhd->osh, dhd->conf, sizeof(dhd_conf_t)); + MFREE(dhd->osh, conf, sizeof(dhd_conf_t)); } dhd->conf = NULL; } diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.h index 6bf5574b9b0f..414f8f1b00f6 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_config.h @@ -1,4 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ + #ifndef _dhd_config_ #define _dhd_config_ @@ -85,17 +86,18 @@ typedef struct conf_pkt_filter_del { } conf_pkt_filter_del_t; #endif -#define CONFIG_COUNTRY_LIST_SIZE 100 -typedef struct conf_country_list { - uint32 count; - wl_country_t *cspec[CONFIG_COUNTRY_LIST_SIZE]; -} conf_country_list_t; +#define CONFIG_COUNTRY_LIST_SIZE 500 +typedef struct country_list { + struct country_list *next; + wl_country_t cspec; +} country_list_t; /* mchan_params */ #define MCHAN_MAX_NUM 4 #define MIRACAST_SOURCE 1 #define MIRACAST_SINK 2 typedef struct mchan_params { + struct mchan_params *next; int bw; int p2p_mode; int miracast_mode; @@ -108,36 +110,57 @@ enum in4way_flags { WAIT_DISCONNECTED = (1 << (3)), }; +enum in_suspend_flags { + NO_EVENT_IN_SUSPEND = (1 << (0)), + NO_TXDATA_IN_SUSPEND = (1 << (1)), + NO_TXCTL_IN_SUSPEND = (1 << (2)), + AP_DOWN_IN_SUSPEND = (1 << (3)), + ROAM_OFFLOAD_IN_SUSPEND = (1 << (4)), + AP_FILTER_IN_SUSPEND = (1 << (5)), + WOWL_IN_SUSPEND = (1 << (6)), + ALL_IN_SUSPEND = 0xFFFFFFFF, +}; + +enum in_suspend_mode { + AUTO_SUSPEND = -1, + EARLY_SUSPEND = 0, + PM_NOTIFIER = 1 +}; + enum eapol_status { EAPOL_STATUS_NONE = 0, - EAPOL_STATUS_WPS_REQID, - EAPOL_STATUS_WPS_RSPID, - EAPOL_STATUS_WPS_WSC_START, - EAPOL_STATUS_WPS_M1, - EAPOL_STATUS_WPS_M2, - EAPOL_STATUS_WPS_M3, - EAPOL_STATUS_WPS_M4, - EAPOL_STATUS_WPS_M5, - EAPOL_STATUS_WPS_M6, - EAPOL_STATUS_WPS_M7, - EAPOL_STATUS_WPS_M8, - EAPOL_STATUS_WPS_DONE, - EAPOL_STATUS_WPA_START, - EAPOL_STATUS_WPA_M1, - EAPOL_STATUS_WPA_M2, - EAPOL_STATUS_WPA_M3, - EAPOL_STATUS_WPA_M4, - EAPOL_STATUS_WPA_END + EAPOL_STATUS_REQID = 1, + EAPOL_STATUS_RSPID = 2, + EAPOL_STATUS_WSC_START = 3, + EAPOL_STATUS_WPS_M1 = 4, + EAPOL_STATUS_WPS_M2 = 5, + EAPOL_STATUS_WPS_M3 = 6, + EAPOL_STATUS_WPS_M4 = 7, + EAPOL_STATUS_WPS_M5 = 8, + EAPOL_STATUS_WPS_M6 = 9, + EAPOL_STATUS_WPS_M7 = 10, + EAPOL_STATUS_WPS_M8 = 11, + EAPOL_STATUS_WSC_DONE = 12, + EAPOL_STATUS_4WAY_START = 13, + EAPOL_STATUS_4WAY_M1 = 14, + EAPOL_STATUS_4WAY_M2 = 15, + EAPOL_STATUS_4WAY_M3 = 16, + EAPOL_STATUS_4WAY_M4 = 17, + EAPOL_STATUS_GROUPKEY_M1 = 18, + EAPOL_STATUS_GROUPKEY_M2 = 19, + EAPOL_STATUS_4WAY_DONE = 20 }; typedef struct dhd_conf { uint chip; uint chiprev; int fw_type; +#ifdef BCMSDIO wl_mac_list_ctrl_t fw_by_mac; wl_mac_list_ctrl_t nv_by_mac; +#endif wl_chip_nv_path_list_ctrl_t nv_by_chip; - conf_country_list_t country_list; + country_list_t *country_head; int band; int bw_cap[2]; wl_country_t cspec; @@ -149,10 +172,12 @@ typedef struct dhd_conf { int roam_delta[2]; int fullroamperiod; uint keep_alive_period; +#ifdef ARP_OFFLOAD_SUPPORT + bool garp; +#endif int force_wme_ac; wme_param_t wme_sta; wme_param_t wme_ap; - int phy_oclscdenable; #ifdef PKT_FILTER_SUPPORT conf_pkt_filter_add_t pkt_filter_add; conf_pkt_filter_del_t pkt_filter_del; @@ -161,7 +186,6 @@ typedef struct dhd_conf { int srl; int lrl; uint bcn_timeout; - int txbf; int disable_proptx; int dhd_poll; #ifdef BCMSDIO @@ -185,9 +209,13 @@ typedef struct dhd_conf { int txglom_bucket_size; int txinrx_thres; int dhd_txminmax; // -1=DATABUFCNT(bus) - uint sd_f2_blocksize; bool oob_enabled_later; - int orphan_move; +#if defined(SDIO_ISR_THREAD) + bool intr_extn; +#endif +#ifdef BCMSDIO_RXLIM_POST + bool rxlim_en; +#endif #endif #ifdef BCMPCIE int bus_deepsleep_disable; @@ -198,17 +226,18 @@ typedef struct dhd_conf { bool deepsleep; int pm; int pm_in_suspend; + int suspend_mode; int suspend_bcn_li_dtim; #ifdef DHDTCPACK_SUPPRESS uint8 tcpack_sup_mode; #endif int pktprio8021x; - int xmit_in_suspend; - int ap_in_suspend; + uint insuspend; + bool suspended; #ifdef SUSPEND_EVENT - bool suspend_eventmask_enable; - char suspend_eventmask[WL_EVENTING_MASK_LEN]; char resume_eventmask[WL_EVENTING_MASK_LEN]; + struct ether_addr bssid_insuspend; + bool wlfc; #endif #ifdef IDHCP int dhcpc_enable; @@ -224,42 +253,40 @@ typedef struct dhd_conf { char isam_enable[50]; #endif int ctrl_resched; - int dhd_ioctl_timeout_msec; - struct mchan_params mchan[MCHAN_MAX_NUM]; + mchan_params_t *mchan; char *wl_preinit; int tsq; + int orphan_move; uint eapol_status; uint in4way; - uint max_wait_gc_time; +#ifdef WL_EXT_WOWL + uint wowl; +#endif +#ifdef GET_CUSTOM_MAC_FROM_CONFIG + char hw_ether[62]; +#endif + wait_queue_head_t event_complete; } dhd_conf_t; #ifdef BCMSDIO int dhd_conf_get_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, uint8 *mac); -void dhd_conf_set_fw_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, char *fw_path); -void dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, char *nv_path); #if defined(HW_OOB) || defined(FORCE_WOWLAN) void dhd_conf_set_hw_oob_intr(bcmsdh_info_t *sdh, uint chip); #endif void dhd_conf_set_txglom_params(dhd_pub_t *dhd, bool enable); int dhd_conf_set_blksize(bcmsdh_info_t *sdh); #endif -void dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path); -void dhd_conf_set_clm_name_by_chip(dhd_pub_t *dhd, char *clm_path); -void dhd_conf_set_nv_name_by_chip(dhd_pub_t *dhd, char *nv_path); -void dhd_conf_set_path(dhd_pub_t *dhd, char *dst_name, char *dst_path, char *src_path); -#ifdef CONFIG_PATH_AUTO_SELECT -void dhd_conf_set_conf_name_by_chip(dhd_pub_t *dhd, char *conf_path); -#endif -int dhd_conf_set_intiovar(dhd_pub_t *dhd, uint cmd, char *name, int val, int def, bool down); -int dhd_conf_get_iovar(dhd_pub_t *dhd, int cmd, char *name, char *buf, int len, int ifidx); -int dhd_conf_set_bufiovar(dhd_pub_t *dhd, uint cmd, char *name, char *buf, int len, bool down); -uint dhd_conf_get_band(dhd_pub_t *dhd); +void dhd_conf_set_path_params(dhd_pub_t *dhd, void *sdh, + char *fw_path, char *nv_path); +int dhd_conf_set_intiovar(dhd_pub_t *dhd, uint cmd, char *name, int val, + int def, bool down); +int dhd_conf_get_band(dhd_pub_t *dhd); int dhd_conf_set_country(dhd_pub_t *dhd, wl_country_t *cspec); int dhd_conf_get_country(dhd_pub_t *dhd, wl_country_t *cspec); int dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec); int dhd_conf_fix_country(dhd_pub_t *dhd); bool dhd_conf_match_channel(dhd_pub_t *dhd, uint32 channel); -void dhd_conf_set_wme(dhd_pub_t *dhd, int mode); +void dhd_conf_set_wme(dhd_pub_t *dhd, int ifidx, int mode); void dhd_conf_set_mchan_bw(dhd_pub_t *dhd, int go, int source); void dhd_conf_add_pkt_filter(dhd_pub_t *dhd); bool dhd_conf_del_pkt_filter(dhd_pub_t *dhd, uint32 id); @@ -269,17 +296,28 @@ int dhd_conf_set_chiprev(dhd_pub_t *dhd, uint chip, uint chiprev); uint dhd_conf_get_chip(void *context); uint dhd_conf_get_chiprev(void *context); int dhd_conf_get_pm(dhd_pub_t *dhd); - +int dhd_conf_check_hostsleep(dhd_pub_t *dhd, int cmd, void *buf, int len, + int *hostsleep_set, int *hostsleep_val, int *ret); +void dhd_conf_get_hostsleep(dhd_pub_t *dhd, + int hostsleep_set, int hostsleep_val, int ret); +int dhd_conf_mkeep_alive(dhd_pub_t *dhd, int ifidx, int id, int period, + char *packet, bool bcast); +#ifdef ARP_OFFLOAD_SUPPORT +void dhd_conf_set_garp(dhd_pub_t *dhd, int ifidx, uint32 ipa, bool enable); +#endif #ifdef PROP_TXSTATUS int dhd_conf_get_disable_proptx(dhd_pub_t *dhd); #endif -int dhd_conf_get_ap_mode_in_suspend(dhd_pub_t *dhd); -int dhd_conf_set_ap_in_suspend(dhd_pub_t *dhd, int suspend); +uint dhd_conf_get_insuspend(dhd_pub_t *dhd, uint mask); +int dhd_conf_set_suspend_resume(dhd_pub_t *dhd, int suspend, int suspend_mode); void dhd_conf_postinit_ioctls(dhd_pub_t *dhd); int dhd_conf_preinit(dhd_pub_t *dhd); int dhd_conf_reset(dhd_pub_t *dhd); int dhd_conf_attach(dhd_pub_t *dhd); void dhd_conf_detach(dhd_pub_t *dhd); void *dhd_get_pub(struct net_device *dev); -void *dhd_get_conf(struct net_device *dev); +int wl_pattern_atoh(char *src, char *dst); +#ifdef BCMSDIO +extern int dhd_bus_sleep(dhd_pub_t *dhdp, bool sleep, uint32 *intstatus); +#endif #endif /* _dhd_config_ */ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_debug.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_debug.c index cd4c6f7e75f0..1afbeb659102 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_debug.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_debug.c @@ -1272,7 +1272,7 @@ dhd_dbg_set_event_log_tag(dhd_pub_t *dhdp, uint16 tag, uint8 set) ret = dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); if (ret) { - DHD_ERROR(("%s set log tag iovar failed %d\n", __FUNCTION__, ret)); + /* DHD_ERROR(("%s set log tag iovar failed %d\n", __FUNCTION__, ret)); */ } } @@ -1473,9 +1473,9 @@ __dhd_dbg_pkt_hash(uintptr_t pkt, uint32 pktid) uint32 __dhd_dbg_driver_ts_usec(void) { - struct timespec ts; + struct osl_timespec ts; - get_monotonic_boottime(&ts); + osl_get_monotonic_boottime(&ts); return ((uint32)(__TIMESPEC_TO_US(ts))); } diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_gpio.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_gpio.c index 7a407d5a0586..e5faafd3337e 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_gpio.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_gpio.c @@ -45,14 +45,15 @@ dhd_wlan_set_power(int on } rockchip_wifi_power(1); #if defined(BUS_POWER_RESTORE) -#if defined(BCMSDIO) +#if defined(BCMSDIO) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)) if (adapter->sdio_func && adapter->sdio_func->card && adapter->sdio_func->card->host) { + mdelay(100); printf("======== mmc_power_restore_host! ========\n"); mmc_power_restore_host(adapter->sdio_func->card->host); } #elif defined(BCMPCIE) - OSL_SLEEP(50); /* delay needed to be able to restore PCIe configuration registers */ if (adapter->pci_dev) { + mdelay(100); printf("======== pci_set_power_state PCI_D0! ========\n"); pci_set_power_state(adapter->pci_dev, PCI_D0); if (adapter->pci_saved_state) @@ -69,7 +70,7 @@ dhd_wlan_set_power(int on mdelay(100); } else { #if defined(BUS_POWER_RESTORE) -#if defined(BCMSDIO) +#if defined(BCMSDIO) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)) if (adapter->sdio_func && adapter->sdio_func->card && adapter->sdio_func->card->host) { printf("======== mmc_power_save_host! ========\n"); mmc_power_save_host(adapter->sdio_func->card->host); diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_ip.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_ip.c index 47cfe8ac72ff..bf8264ab944b 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_ip.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_ip.c @@ -127,7 +127,7 @@ typedef struct { int ifidx; uint8 supp_cnt; dhd_pub_t *dhdp; - struct timer_list timer; + timer_list_compat_t timer; } tcpack_info_t; typedef struct _tdata_psh_info_t { @@ -287,20 +287,10 @@ static void _tdata_psh_info_pool_deinit(dhd_pub_t *dhdp, return; } -static void dhd_tcpack_send( -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - struct timer_list *t -#else - ulong data -#endif -) +static void dhd_tcpack_send(ulong data) { tcpack_sup_module_t *tcpack_sup_mod; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - tcpack_info_t *cur_tbl = from_timer(cur_tbl, t, timer); -#else tcpack_info_t *cur_tbl = (tcpack_info_t *)data; -#endif dhd_pub_t *dhdp; int ifidx; void* pkt; @@ -474,13 +464,7 @@ int dhd_tcpack_suppress_set(dhd_pub_t *dhdp, uint8 mode) tcpack_info_t *tcpack_info_tbl = &tcpack_sup_module->tcpack_info_tbl[i]; tcpack_info_tbl->dhdp = dhdp; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - timer_setup(&tcpack_info_tbl->timer, dhd_tcpack_send, 0); -#else - init_timer(&tcpack_info_tbl->timer); - tcpack_info_tbl->timer.data = (ulong)tcpack_info_tbl; - tcpack_info_tbl->timer.function = dhd_tcpack_send; -#endif + init_timer_compat(&tcpack_info_tbl->timer, dhd_tcpack_send, tcpack_info_tbl); } break; } diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux.c index f3ad4029e18c..c366cb4c6256 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux.c @@ -84,6 +84,9 @@ #include #include #include +#ifdef WL_ESCAN +#include +#endif #include #include #ifdef CONFIG_HAS_WAKELOCK @@ -290,9 +293,6 @@ static u32 vendor_oui = CONFIG_DHD_SET_RANDOM_MAC_VAL; #endif #include -#ifdef WL_ESCAN -#include -#endif /* Maximum STA per radio */ #define DHD_MAX_STA 32 @@ -349,6 +349,7 @@ MODULE_LICENSE("GPL and additional rights"); DEFINE_MUTEX(_dhd_mutex_lock_); #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */ #endif +static int dhd_suspend_resume_helper(struct dhd_info *dhd, int val, int force); #ifdef CONFIG_BCM_DETECT_CONSECUTIVE_HANG #define MAX_CONSECUTIVE_HANG_COUNTS 5 @@ -375,8 +376,10 @@ extern bool dhd_wlfc_skip_fc(void * dhdp, uint8 idx); extern void dhd_wlfc_plat_init(void *dhd); extern void dhd_wlfc_plat_deinit(void *dhd); #endif /* PROP_TXSTATUS */ +#ifdef USE_DYNAMIC_F2_BLKSIZE extern uint sd_f2_blocksize; extern int dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size); +#endif /* USE_DYNAMIC_F2_BLKSIZE */ #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 15) const char * @@ -634,10 +637,10 @@ typedef struct dhd_info { wait_queue_head_t dhd_bus_busy_state_wait; uint32 default_wd_interval; - struct timer_list timer; + timer_list_compat_t timer; bool wd_timer_valid; #ifdef DHD_PCIE_RUNTIMEPM - struct timer_list rpm_timer; + timer_list_compat_t rpm_timer; bool rpm_timer_valid; tsk_ctl_t thr_rpm_ctl; #endif /* DHD_PCIE_RUNTIMEPM */ @@ -713,7 +716,7 @@ typedef struct dhd_info { #ifdef BCM_FD_AGGR void *rpc_th; void *rpc_osh; - struct timer_list rpcth_timer; + timer_list_compat_t rpcth_timer; bool rpcth_timer_active; uint8 fdaggr; #endif @@ -743,11 +746,11 @@ typedef struct dhd_info { #endif /* DHD_WET */ #ifdef DHD_DEBUG dhd_dump_t *dump; - struct timer_list join_timer; + timer_list_compat_t join_timer; u32 join_timeout_val; bool join_timer_active; uint scan_time_count; - struct timer_list scan_timer; + timer_list_compat_t scan_timer; bool scan_timer_active; #endif #if defined(DHD_LB) @@ -887,7 +890,7 @@ typedef struct dhd_info { #ifdef SHOW_LOGTRACE struct sk_buff_head evt_trace_queue ____cacheline_aligned; #endif - struct timer_list timesync_timer; + timer_list_compat_t timesync_timer; #if defined(BT_OVER_SDIO) char btfw_path[PATH_MAX]; #endif /* defined (BT_OVER_SDIO) */ @@ -1095,6 +1098,14 @@ extern int h2d_max_txpost; module_param(h2d_max_txpost, int, 0644); #endif /* PCIE_FULL_DONGLE */ +#ifdef DHD_ARP_DUMP +#include +static const char arp_types[][10] = { + "NA", "REQUEST", "RESPONSE" +}; +static void dhd_arp_dump(char *ifname, uint8 *pktdata, bool tx); +#endif /* DHD_ARP_DUMP */ + #ifdef DHD_DHCP_DUMP struct bootp_fmt { struct iphdr ip_header; @@ -2004,15 +2015,25 @@ static int dhd_pm_callback(struct notifier_block *nfb, unsigned long action, voi break; } -#if defined(SUPPORT_P2P_GO_PS) && defined(PROP_TXSTATUS) + printf("%s: action=%ld, suspend=%d, suspend_mode=%d\n", + __FUNCTION__, action, suspend, dhdinfo->pub.conf->suspend_mode); if (suspend) { DHD_OS_WAKE_LOCK_WAIVE(&dhdinfo->pub); + if (dhdinfo->pub.conf->suspend_mode == PM_NOTIFIER) + dhd_suspend_resume_helper(dhdinfo, suspend, 0); +#if defined(SUPPORT_P2P_GO_PS) && defined(PROP_TXSTATUS) dhd_wlfc_suspend(&dhdinfo->pub); +#endif /* defined(SUPPORT_P2P_GO_PS) && defined(PROP_TXSTATUS) */ + dhd_conf_set_suspend_resume(&dhdinfo->pub, suspend, PM_NOTIFIER); DHD_OS_WAKE_LOCK_RESTORE(&dhdinfo->pub); } else { + dhd_conf_set_suspend_resume(&dhdinfo->pub, suspend, PM_NOTIFIER); +#if defined(SUPPORT_P2P_GO_PS) && defined(PROP_TXSTATUS) dhd_wlfc_resume(&dhdinfo->pub); - } #endif /* defined(SUPPORT_P2P_GO_PS) && defined(PROP_TXSTATUS) */ + if (dhdinfo->pub.conf->suspend_mode == PM_NOTIFIER) + dhd_suspend_resume_helper(dhdinfo, suspend, 0); + } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (LINUX_VERSION_CODE <= \ KERNEL_VERSION(2, 6, 39)) @@ -3269,14 +3290,16 @@ dhd_enable_packet_filter(int value, dhd_pub_t *dhd) int i; DHD_ERROR(("%s: enter, value = %d\n", __FUNCTION__, value)); - if ((dhd->op_mode & DHD_FLAG_HOSTAP_MODE) && value) { + if ((dhd->op_mode & DHD_FLAG_HOSTAP_MODE) && value && + !dhd_conf_get_insuspend(dhd, AP_FILTER_IN_SUSPEND)) { DHD_ERROR(("%s: DHD_FLAG_HOSTAP_MODE\n", __FUNCTION__)); return; } /* 1 - Enable packet filter, only allow unicast packet to send up */ /* 0 - Disable packet filter */ if (dhd_pkt_filter_enable && (!value || - (dhd_support_sta_mode(dhd) && !dhd->dhcp_in_progress))) + (dhd_support_sta_mode(dhd) && !dhd->dhcp_in_progress) || + dhd_conf_get_insuspend(dhd, AP_FILTER_IN_SUSPEND))) { for (i = 0; i < dhd->pktfilter_count; i++) { // terence 20160615: fix building error if ARP_OFFLOAD_SUPPORT removed @@ -3370,7 +3393,9 @@ dhd_packet_filter_add_remove(dhd_pub_t *dhdp, int add_remove, int num) static int dhd_set_suspend(int value, dhd_pub_t *dhd) { +#ifndef SUPPORT_PM2_ONLY int power_mode = PM_MAX; +#endif /* SUPPORT_PM2_ONLY */ #ifdef SUPPORT_SENSORHUB shub_control_t shub_ctl; #endif /* SUPPORT_SENSORHUB */ @@ -3385,7 +3410,7 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) int roam_time_thresh = 0; /* (ms) */ #endif /* CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND */ #ifndef ENABLE_FW_ROAM_SUSPEND - uint roamvar = dhd->conf->roam_off_suspend; + uint roamvar = 1; #endif /* ENABLE_FW_ROAM_SUSPEND */ #ifdef ENABLE_BCN_LI_BCN_WAKEUP int bcn_li_bcn; @@ -3436,12 +3461,6 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) /* set specific cpucore */ dhd_set_cpucore(dhd, TRUE); #endif /* CUSTOM_SET_CPUCORE */ - - if (dhd->conf->pm >= 0) - power_mode = dhd->conf->pm; - else - power_mode = PM_FAST; - if (dhd->up) { if (value && dhd->in_suspend) { #ifdef PKT_FILTER_SUPPORT @@ -3450,10 +3469,10 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) /* Kernel suspended */ DHD_ERROR(("%s: force extra suspend setting\n", __FUNCTION__)); - if (dhd->conf->pm_in_suspend >= 0) - power_mode = dhd->conf->pm_in_suspend; +#ifndef SUPPORT_PM2_ONLY dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, - sizeof(power_mode), TRUE, 0); + sizeof(power_mode), TRUE, 0); +#endif /* SUPPORT_PM2_ONLY */ #ifdef PKT_FILTER_SUPPORT /* Enable packet filter, @@ -3606,9 +3625,9 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) } #endif /* DYNAMIC_SWOOB_DURATION */ #endif /* DHD_USE_EARLYSUSPEND */ - dhd_conf_set_ap_in_suspend(dhd, value); + dhd_conf_set_suspend_resume(dhd, value, EARLY_SUSPEND); } else { - dhd_conf_set_ap_in_suspend(dhd, value); + dhd_conf_set_suspend_resume(dhd, value, EARLY_SUSPEND); #ifdef PKT_FILTER_SUPPORT dhd->early_suspended = 0; #endif @@ -3642,7 +3661,7 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) #ifndef SUPPORT_PM2_ONLY power_mode = PM_FAST; dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, - sizeof(power_mode), TRUE, 0); + sizeof(power_mode), TRUE, 0); #endif /* SUPPORT_PM2_ONLY */ #ifdef PKT_FILTER_SUPPORT /* disable pkt filter */ @@ -3739,11 +3758,6 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) NULL, 0, TRUE); #endif /* ENABLE_IPMCAST_FILTER */ #endif /* DHD_USE_EARLYSUSPEND */ - - /* terence 2017029: Reject in early suspend */ - if (!dhd->conf->xmit_in_suspend) { - dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF); - } } } dhd_suspend_unlock(dhd); @@ -3762,7 +3776,7 @@ static int dhd_suspend_resume_helper(struct dhd_info *dhd, int val, int force) /* Set flag when early suspend was called */ dhdp->in_suspend = val; if ((force || !dhdp->suspend_disable_flag) && - (dhd_support_sta_mode(dhdp) || dhd_conf_get_ap_mode_in_suspend(dhdp))) + (dhd_support_sta_mode(dhdp) || dhd_conf_get_insuspend(dhdp, ALL_IN_SUSPEND))) { ret = dhd_set_suspend(val, dhdp); } @@ -4665,7 +4679,7 @@ dhd_trx_dump(struct net_device *ndev, uint8 *dump_data, uint datalen, bool tx) ifname = ndev ? ndev->name : "N/A"; if (protocol != ETHER_TYPE_BRCM) { - DHD_ERROR(("%s DUMP[%s] - %s\n", tx?"Tx":"Rx", ifname, + DHD_ERROR(("[dhd-%s] %s DUMP - %s\n", ifname, tx?"Tx":"Rx", _get_packet_type_str(protocol))); #if defined(DHD_TX_FULL_DUMP) || defined(DHD_RX_FULL_DUMP) prhex("Data", dump_data, datalen); @@ -4843,6 +4857,11 @@ __dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) dhd_icmp_dump(dhd_ifname(dhdp, ifidx), pktdata, TRUE); #endif /* DHD_ICMP_DUMP */ } +#ifdef DHD_ARP_DUMP + if (ntoh16(eh->ether_type) == ETHER_TYPE_ARP) { + dhd_arp_dump(dhd_ifname(dhdp, ifidx), pktdata, TRUE); + } +#endif /* DHD_ARP_DUMP */ } else { PKTCFREE(dhdp->osh, pktbuf, TRUE); return BCME_ERROR; @@ -5051,16 +5070,6 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net) return -ENODEV; } - /* terence 2017029: Reject in early suspend */ - if (!dhd->pub.conf->xmit_in_suspend && dhd->pub.early_suspended) { - dhd_txflowcontrol(&dhd->pub, ALL_INTERFACES, ON); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)) - return -ENODEV; -#else - return NETDEV_TX_BUSY; -#endif - } - DHD_GENERAL_LOCK(&dhd->pub, flags); DHD_BUS_BUSY_SET_IN_TX(&dhd->pub); DHD_GENERAL_UNLOCK(&dhd->pub, flags); @@ -5200,6 +5209,12 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net) bcm_object_trace_opr(skb, BCM_OBJDBG_ADD_PKT, __FUNCTION__, __LINE__); } + /* move from dhdsdio_sendfromq(), try to orphan skb early */ + if (dhd->pub.conf->orphan_move == 2) + PKTORPHAN(skb, dhd->pub.conf->tsq); + else if (dhd->pub.conf->orphan_move == 3) + skb_orphan(skb); + /* Convert to packet */ if (!(pktbuf = PKTFRMNATIVE(dhd->pub.osh, skb))) { DHD_ERROR(("%s: PKTFRMNATIVE failed\n", @@ -5908,6 +5923,11 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) dhd_icmp_dump(dhd_ifname(dhdp, ifidx), dump_data, FALSE); #endif /* DHD_ICMP_DUMP */ } +#ifdef DHD_ARP_DUMP + if (ntoh16(eh->ether_type) == ETHER_TYPE_ARP) { + dhd_arp_dump(dhd_ifname(dhdp, ifidx), dump_data, FALSE); + } +#endif /* DHD_ARP_DUMP */ #ifdef DHD_RX_DUMP dhd_trx_dump(dhd_idx2net(dhdp, ifidx), dump_data, skb->len, FALSE); #endif /* DHD_RX_DUMP */ @@ -6035,7 +6055,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) continue; } -#ifdef DHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT +#if defined(DHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT) && !defined(SENDPROB) #ifdef DHD_USE_STATIC_CTRLBUF PKTFREE_STATIC(dhdp->osh, pktbuf, FALSE); #else @@ -6043,6 +6063,16 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) #endif /* DHD_USE_STATIC_CTRLBUF */ continue; #else +#ifdef SENDPROB + if (!dhdp->recv_probereq || (event.event_type != WLC_E_PROBREQ_MSG)) { +#ifdef DHD_USE_STATIC_CTRLBUF + PKTFREE_STATIC(dhdp->osh, pktbuf, FALSE); +#else + PKTFREE(dhdp->osh, pktbuf, FALSE); +#endif /* DHD_USE_STATIC_CTRLBUF */ + continue; + } +#endif /* * For the event packets, there is a possibility * of ifidx getting modifed.Thus update the ifp @@ -6339,19 +6369,9 @@ dhd_watchdog_thread(void *data) complete_and_exit(&tsk->completed, 0); } -static void dhd_watchdog( -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - struct timer_list *t -#else - ulong data -#endif -) +static void dhd_watchdog(ulong data) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - dhd_info_t *dhd = from_timer(dhd, t, timer); -#else dhd_info_t *dhd = (dhd_info_t *)data; -#endif unsigned long flags; if (dhd->pub.dongle_reset) { @@ -6431,19 +6451,9 @@ dhd_rpm_state_thread(void *data) complete_and_exit(&tsk->completed, 0); } -static void dhd_runtimepm( -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - struct timer_list *t -#else - ulong data -#endif -) +static void dhd_runtimepm(ulong data) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - dhd_info_t *dhd = from_timer(dhd, t, rpm_timer); -#else dhd_info_t *dhd = (dhd_info_t *)data; -#endif if (dhd->pub.dongle_reset) { return; @@ -7088,6 +7098,7 @@ static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error) dhdp->hang_reason = HANG_REASON_IOCTL_RESP_TIMEOUT; } } + printf("%s\n", info_string); net_os_send_hang_message(net); return TRUE; } @@ -8277,15 +8288,31 @@ dhd_stop(struct net_device *net) OLD_MOD_DEC_USE_COUNT; exit: +#if defined(WL_WIRELESS_EXT) + if (ifidx == 0) { + wl_iw_down(net, &dhd->pub); + } +#endif /* defined(WL_WIRELESS_EXT) */ +#ifdef WL_ESCAN + if (ifidx == 0) { + wl_escan_down(net, &dhd->pub); + } +#endif /* WL_ESCAN */ if (ifidx == 0 && !dhd_download_fw_on_driverload) { #if defined(BT_OVER_SDIO) dhd_bus_put(&dhd->pub, WLAN_MODULE); wl_android_set_wifi_on_flag(FALSE); #else wl_android_wifi_off(net, TRUE); +#if defined(WL_EXT_IAPSTA) || defined(USE_IW) || defined(WL_ESCAN) #ifdef WL_EXT_IAPSTA wl_ext_iapsta_dettach_netdev(net, ifidx); -#endif +#endif /* WL_EXT_IAPSTA */ +#ifdef WL_ESCAN + wl_escan_event_dettach(net, &dhd->pub); +#endif /* WL_ESCAN */ + wl_ext_event_dettach_netdev(net, ifidx); +#endif /* WL_EXT_IAPSTA || USE_IW || WL_ESCAN */ } else { if (dhd->pub.conf->deepsleep) dhd_deepsleep(dhd, 1); @@ -8360,7 +8387,6 @@ dhd_open(struct net_device *net) #endif #if defined(WL_EXT_IAPSTA) && defined(ISAM_PREINIT) int bytes_written = 0; - struct dhd_conf *conf; #endif if (!dhd_download_fw_on_driverload) { @@ -8405,6 +8431,7 @@ dhd_open(struct net_device *net) DHD_ERROR(("%s: WLAN interface is not brought down\n", __FUNCTION__)); dhd_stop(net); } else { + DHD_MUTEX_UNLOCK(); return -1; } } @@ -8457,9 +8484,15 @@ dhd_open(struct net_device *net) atomic_set(&dhd->pend_8021x_cnt, 0); if (!dhd_download_fw_on_driverload) { DHD_ERROR(("\n%s\n", dhd_version)); +#if defined(WL_EXT_IAPSTA) || defined(USE_IW) || defined(WL_ESCAN) + wl_ext_event_attach_netdev(net, ifidx, dhd->iflist[ifidx]->bssidx); +#ifdef WL_ESCAN + wl_escan_event_attach(net, &dhd->pub); +#endif /* WL_ESCAN */ #ifdef WL_EXT_IAPSTA wl_ext_iapsta_attach_netdev(net, ifidx, dhd->iflist[ifidx]->bssidx); -#endif +#endif /* WL_EXT_IAPSTA */ +#endif /* WL_EXT_IAPSTA || USE_IW || WL_ESCAN */ #if defined(USE_INITIAL_SHORT_DWELL_TIME) g_first_broadcast_scan = TRUE; #endif @@ -8475,14 +8508,6 @@ dhd_open(struct net_device *net) ret = -1; goto exit; } -#if defined(WL_EXT_IAPSTA) && defined(ISAM_PREINIT) - conf = dhd_get_conf(net); - if (conf) { - wl_android_ext_priv_cmd(net, conf->isam_init, 0, &bytes_written); - wl_android_ext_priv_cmd(net, conf->isam_config, 0, &bytes_written); - wl_android_ext_priv_cmd(net, conf->isam_enable, 0, &bytes_written); - } -#endif } #ifdef FIX_CPU_MIN_CLOCK if (dhd_get_fw_mode(dhd) == DHD_FLAG_HOSTAP_MODE) { @@ -8647,6 +8672,29 @@ dhd_open(struct net_device *net) dhd_set_scb_probe(&dhd->pub); #endif /* NUM_SCB_MAX_PROBE */ #endif /* WL_CFG80211 */ +#if defined(WL_WIRELESS_EXT) + if (unlikely(wl_iw_up(net, &dhd->pub))) { + DHD_ERROR(("%s: failed to bring up wext\n", __FUNCTION__)); + ret = -1; + goto exit; + } +#endif +#ifdef WL_ESCAN + if (unlikely(wl_escan_up(net, &dhd->pub))) { + DHD_ERROR(("%s: failed to bring up escan\n", __FUNCTION__)); + ret = -1; + goto exit; + } +#endif /* WL_ESCAN */ +#if defined(ISAM_PREINIT) + if (!dhd_download_fw_on_driverload) { + if (dhd->pub.conf) { + wl_android_ext_priv_cmd(net, dhd->pub.conf->isam_init, 0, &bytes_written); + wl_android_ext_priv_cmd(net, dhd->pub.conf->isam_config, 0, &bytes_written); + wl_android_ext_priv_cmd(net, dhd->pub.conf->isam_enable, 0, &bytes_written); + } + } +#endif } /* Allow transmit calls */ @@ -8881,27 +8929,20 @@ dhd_allocate_if(dhd_pub_t *dhdpub, int ifidx, const char *name, ifp->net->name[IFNAMSIZ - 1] = '\0'; } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 9)) +#define IFP_NET_DESTRUCTOR ifp->net->priv_destructor +#else +#define IFP_NET_DESTRUCTOR ifp->net->destructor +#endif // endif + #ifdef WL_CFG80211 if (ifidx == 0) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) - ifp->net->destructor = free_netdev; -#else - ifp->net->needs_free_netdev = true; -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) */ + IFP_NET_DESTRUCTOR = free_netdev; } else { -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) - ifp->net->destructor = dhd_netdev_free; -#else - ifp->net->needs_free_netdev = true; - ifp->net->priv_destructor = dhd_netdev_free; -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) */ + IFP_NET_DESTRUCTOR = dhd_netdev_free; } #else -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) - ifp->net->destructor = free_netdev; -#else - ifp->net->needs_free_netdev = true; -#endif + IFP_NET_DESTRUCTOR = free_netdev; #endif /* WL_CFG80211 */ strncpy(ifp->name, ifp->net->name, IFNAMSIZ); ifp->name[IFNAMSIZ - 1] = '\0'; @@ -8987,9 +9028,15 @@ dhd_remove_if(dhd_pub_t *dhdpub, int ifidx, bool need_rtnl_lock) unregister_netdev(ifp->net); else unregister_netdevice(ifp->net); +#if defined(WL_EXT_IAPSTA) || defined(USE_IW) || defined(WL_ESCAN) #ifdef WL_EXT_IAPSTA wl_ext_iapsta_dettach_netdev(ifp->net, ifidx); -#endif +#endif /* WL_EXT_IAPSTA */ +#ifdef WL_ESCAN + wl_escan_event_dettach(ifp->net, dhdpub); +#endif /* WL_ESCAN */ + wl_ext_event_dettach_netdev(ifp->net, ifidx); +#endif /* WL_EXT_IAPSTA || USE_IW || WL_ESCAN */ } ifp->net = NULL; } @@ -9572,27 +9619,33 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen #ifdef DHD_LOG_DUMP dhd_log_dump_init(&dhd->pub); #endif /* DHD_LOG_DUMP */ -#if defined(WL_WIRELESS_EXT) +#if defined(WL_EXT_IAPSTA) || defined(USE_IW) || defined(WL_ESCAN) + if (wl_ext_event_attach(net, &dhd->pub) != 0) { + DHD_ERROR(("wl_ext_event_attach failed\n")); + goto fail; + } #ifdef WL_ESCAN + /* Attach and link in the escan */ if (wl_escan_attach(net, &dhd->pub) != 0) { DHD_ERROR(("wl_escan_attach failed\n")); goto fail; } -#else +#endif /* WL_ESCAN */ +#ifdef WL_EXT_IAPSTA + if (wl_ext_iapsta_attach(&dhd->pub) != 0) { + DHD_ERROR(("wl_ext_iapsta_attach failed\n")); + goto fail; + } +#endif /* WL_EXT_IAPSTA */ +#endif /* WL_EXT_IAPSTA || USE_IW || WL_ESCAN */ +#if defined(WL_WIRELESS_EXT) /* Attach and link in the iw */ if (wl_iw_attach(net, &dhd->pub) != 0) { DHD_ERROR(("wl_iw_attach failed\n")); goto fail; } dhd_state |= DHD_ATTACH_STATE_WL_ATTACH; -#endif /* WL_ESCAN */ #endif /* defined(WL_WIRELESS_EXT) */ -#ifdef WL_EXT_IAPSTA - if (wl_ext_iapsta_attach(&dhd->pub) != 0) { - DHD_ERROR(("wl_ext_iapsta_attach failed\n")); - goto fail; - } -#endif #ifdef SHOW_LOGTRACE ret = dhd_init_logstrs_array(osh, &dhd->event_data); @@ -9631,13 +9684,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen #ifndef BCMDBUS /* Set up the watchdog timer */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - timer_setup(&dhd->timer, dhd_watchdog, 0); -#else - init_timer(&dhd->timer); - dhd->timer.data = (ulong)dhd; - dhd->timer.function = dhd_watchdog; -#endif + init_timer_compat(&dhd->timer, dhd_watchdog, dhd); dhd->default_wd_interval = dhd_watchdog_ms; if (dhd_watchdog_prio >= 0) { @@ -9653,13 +9700,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen #ifdef DHD_PCIE_RUNTIMEPM /* Setup up the runtime PM Idlecount timer */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - timer_setup(&dhd->rpm_timer, dhd_runtimepm, 0); -#else - init_timer(&dhd->rpm_timer); - dhd->rpm_timer.data = (ulong)dhd; - dhd->rpm_timer.function = dhd_runtimepm; -#endif + init_timer_compat(&dhd->rpm_timer, dhd_runtimepm, dhd); dhd->rpm_timer_valid = FALSE; dhd->thr_rpm_ctl.thr_pid = DHD_PID_KT_INVALID; @@ -10961,9 +11002,18 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) DHD_INFO(("%s : Set IOCTL response time.\n", __FUNCTION__)); } #ifdef GET_CUSTOM_MAC_ENABLE + memset(hw_ether, 0, sizeof(hw_ether)); ret = wifi_platform_get_mac_addr(dhd->info->adapter, hw_ether); +#ifdef GET_CUSTOM_MAC_FROM_CONFIG + if (!memcmp(ðer_null, &dhd->conf->hw_ether, ETHER_ADDR_LEN)) { + ret = 0; + } else +#endif if (!ret) { memset(buf, 0, sizeof(buf)); +#ifdef GET_CUSTOM_MAC_FROM_CONFIG + memcpy(hw_ether, &dhd->conf->hw_ether, sizeof(dhd->conf->hw_ether)); +#endif bcopy(hw_ether, ea_addr.octet, sizeof(struct ether_addr)); bcm_mkiovar("cur_etheraddr", (void *)&ea_addr, ETHER_ADDR_LEN, buf, sizeof(buf)); ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0); @@ -10972,14 +11022,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) bcm_mkiovar("hw_ether", hw_ether, sizeof(hw_ether), buf, sizeof(buf)); ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0); if (ret) { - int i; DHD_ERROR(("%s: can't set MAC address MAC="MACDBG", error=%d\n", __FUNCTION__, MAC2STRDBG(hw_ether), ret)); - for (i=0; iconf->sd_f2_blocksize) - dhdsdio_func_blocksize(dhd, 2, dhd->conf->sd_f2_blocksize); -#endif #if defined(RSDB_MODE_FROM_FILE) (void)dhd_rsdb_mode_from_file(dhd); @@ -11566,7 +11610,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif #ifndef WL_CFG80211 setbit(eventmask, WLC_E_PMKID_CACHE); - setbit(eventmask, WLC_E_TXFAIL); +// setbit(eventmask, WLC_E_TXFAIL); // terence 20181106: remove unnecessary event #endif setbit(eventmask, WLC_E_JOIN_START); // setbit(eventmask, WLC_E_SCAN_COMPLETE); // terence 20150628: remove redundant event @@ -11632,9 +11676,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) dhd_update_flow_prio_map(dhd, DHD_FLOW_PRIO_LLR_MAP); #endif /* defined(BCMPCIE) && defined(EAPOL_PKT_PRIO) */ -#ifdef SUSPEND_EVENT - bcopy(eventmask, dhd->conf->resume_eventmask, WL_EVENTING_MASK_LEN); -#endif /* Write updated Event mask */ ret = dhd_iovar(dhd, 0, "event_msgs", eventmask, WL_EVENTING_MASK_LEN, NULL, 0, TRUE); if (ret < 0) { @@ -11809,20 +11850,29 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) memset(buf, 0, sizeof(buf)); ret = dhd_iovar(dhd, 0, "clmver", NULL, 0, buf, sizeof(buf), FALSE); if (ret < 0) - DHD_ERROR(("%s failed %d\n", __FUNCTION__, ret)); + DHD_ERROR(("%s clmver failed %d\n", __FUNCTION__, ret)); else { - char *clmver_temp_buf = NULL; + char *ver_temp_buf = NULL, *ver_date_buf = NULL; + int len; - if ((clmver_temp_buf = bcmstrstr(buf, "Data:")) == NULL) { + if ((ver_temp_buf = bcmstrstr(buf, "Data:")) == NULL) { DHD_ERROR(("Couldn't find \"Data:\"\n")); } else { - ptr = (clmver_temp_buf + strlen("Data:")); - if ((clmver_temp_buf = bcmstrtok(&ptr, "\n", 0)) == NULL) { + ver_date_buf = bcmstrstr(buf, "Creation:"); + ptr = (ver_temp_buf + strlen("Data:")); + if ((ver_temp_buf = bcmstrtok(&ptr, "\n", 0)) == NULL) { DHD_ERROR(("Couldn't find New line character\n")); } else { memset(clm_version, 0, CLM_VER_STR_LEN); - strncpy(clm_version, clmver_temp_buf, - MIN(strlen(clmver_temp_buf), CLM_VER_STR_LEN - 1)); + len = snprintf(clm_version, CLM_VER_STR_LEN - 1, "%s", ver_temp_buf); + if (ver_date_buf) { + ptr = (ver_date_buf + strlen("Creation:")); + ver_date_buf = bcmstrtok(&ptr, "\n", 0); + if (ver_date_buf) + snprintf(clm_version+len, CLM_VER_STR_LEN-1-len, + " (%s)", ver_date_buf); + } + DHD_INFO(("CLM version = %s\n", clm_version)); } } } @@ -12323,6 +12373,7 @@ static int dhd_inetaddr_notifier_call(struct notifier_block *this, __FUNCTION__)); aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, TRUE, idx); #endif /* AOE_IP_ALIAS_SUPPORT */ + dhd_conf_set_garp(dhd_pub, idx, ifa->ifa_address, TRUE); break; case NETDEV_DOWN: @@ -12341,6 +12392,7 @@ static int dhd_inetaddr_notifier_call(struct notifier_block *this, dhd_aoe_hostip_clr(&dhd->pub, idx); dhd_aoe_arp_clr(&dhd->pub, idx); } + dhd_conf_set_garp(dhd_pub, idx, ifa->ifa_address, FALSE); break; default: @@ -12595,10 +12647,17 @@ dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock) if (ifidx == 0) printf("%s\n", dhd_version); + else { +#if defined(WL_EXT_IAPSTA) || defined(USE_IW) || defined(WL_ESCAN) + wl_ext_event_attach_netdev(net, ifidx, ifp->bssidx); +#ifdef WL_ESCAN + wl_escan_event_attach(net, dhdp); +#endif /* WL_ESCAN */ #ifdef WL_EXT_IAPSTA - else wl_ext_iapsta_attach_netdev(net, ifidx, ifp->bssidx); -#endif +#endif /* WL_EXT_IAPSTA */ +#endif /* WL_EXT_IAPSTA || USE_IW || WL_ESCAN */ + } if (ifidx != 0) { if (_dhd_set_mac_address(dhd, ifidx, net->dev_addr) == 0) DHD_INFO(("%s: MACID is overwritten\n", __FUNCTION__)); @@ -12615,11 +12674,20 @@ dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock) DHD_ERROR(("couldn't register the net device [%s], err %d\n", net->name, err)); goto fail; } + if (ifidx == 0) { +#if defined(WL_EXT_IAPSTA) || defined(USE_IW) || defined(WL_ESCAN) + wl_ext_event_attach_netdev(net, ifidx, ifp->bssidx); +#ifdef WL_ESCAN + wl_escan_event_attach(net, dhdp); +#endif /* WL_ESCAN */ #ifdef WL_EXT_IAPSTA - if (ifidx == 0) wl_ext_iapsta_attach_netdev(net, ifidx, ifp->bssidx); +#endif /* WL_EXT_IAPSTA */ +#endif /* WL_EXT_IAPSTA || USE_IW || WL_ESCAN */ + } +#ifdef WL_EXT_IAPSTA wl_ext_iapsta_attach_name(net, ifidx); -#endif +#endif /* WL_EXT_IAPSTA */ @@ -12669,6 +12737,9 @@ dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock) dhd->bus_user_count--; #endif /* BT_OVER_SDIO */ } +#if defined(WL_WIRELESS_EXT) + wl_iw_down(net, &dhd->pub); +#endif /* defined(WL_WIRELESS_EXT) */ } #endif /* OEM_ANDROID && (BCMPCIE || (BCMLXSDMMC && KERNEL_VERSION >= 2.6.27)) */ return 0; @@ -12832,18 +12903,20 @@ void dhd_detach(dhd_pub_t *dhdp) #endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */ #if defined(WL_WIRELESS_EXT) -#ifdef WL_ESCAN - wl_escan_detach(dhdp); -#else if (dhd->dhd_state & DHD_ATTACH_STATE_WL_ATTACH) { /* Detatch and unlink in the iw */ - wl_iw_detach(dhdp); + wl_iw_detach(dev, dhdp); } -#endif /* WL_ESCAN */ #endif /* defined(WL_WIRELESS_EXT) */ +#if defined(WL_EXT_IAPSTA) || defined(USE_IW) || defined(WL_ESCAN) #ifdef WL_EXT_IAPSTA wl_ext_iapsta_dettach(dhdp); -#endif +#endif /* WL_EXT_IAPSTA */ +#ifdef WL_ESCAN + wl_escan_detach(dev, dhdp); +#endif /* WL_ESCAN */ + wl_ext_event_dettach(dhdp); +#endif /* WL_EXT_IAPSTA || USE_IW || WL_ESCAN */ #ifdef DHD_ULP dhd_ulp_deinit(dhd->pub.osh, dhdp); @@ -13307,21 +13380,25 @@ dhd_reboot_callback(struct notifier_block *this, unsigned long code, void *unuse return NOTIFY_DONE; } +#ifdef CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP static int wifi_init_thread(void *data) { dhd_module_init(); - return 0; } +#endif int rockchip_wifi_init_module_rkwifi(void) { +#ifdef CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP struct task_struct *kthread = NULL; kthread = kthread_run(wifi_init_thread, NULL, "wifi_init_thread"); if (IS_ERR(kthread)) pr_err("create wifi_init_thread failed.\n"); - +#else + dhd_module_init(); +#endif return 0; } @@ -13431,15 +13508,10 @@ dhd_os_set_ioctl_resp_timeout(unsigned int timeout_msec) } int -dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition, bool resched) +dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition) { dhd_info_t * dhd = (dhd_info_t *)(pub->info); - int timeout, timeout_tmp = dhd_ioctl_timeout_msec; - - if (!resched && pub->conf->ctrl_resched>0 && pub->conf->dhd_ioctl_timeout_msec>0) { - timeout_tmp = dhd_ioctl_timeout_msec; - dhd_ioctl_timeout_msec = pub->conf->dhd_ioctl_timeout_msec; - } + int timeout; /* Convert timeout in millsecond to jiffies */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) @@ -13452,10 +13524,6 @@ dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition, bool resched) timeout = wait_event_timeout(dhd->ioctl_resp_wait, (*condition), timeout); - if (!resched && pub->conf->ctrl_resched>0 && pub->conf->dhd_ioctl_timeout_msec>0) { - dhd_ioctl_timeout_msec = timeout_tmp; - } - DHD_PERIM_LOCK(pub); return timeout; @@ -14022,23 +14090,9 @@ dhd_wl_host_event(dhd_info_t *dhd, int ifidx, void *pktdata, uint16 pktlen, if (bcmerror != BCME_OK) return (bcmerror); -#if defined(WL_EXT_IAPSTA) - wl_ext_iapsta_event(dhd->iflist[ifidx]->net, event, *data); -#endif /* defined(WL_EXT_IAPSTA) */ -#if defined(WL_WIRELESS_EXT) - if (event->bsscfgidx == 0) { - /* - * Wireless ext is on primary interface only - */ - - ASSERT(dhd->iflist[ifidx] != NULL); - ASSERT(dhd->iflist[ifidx]->net != NULL); - - if (dhd->iflist[ifidx]->net) { - wl_iw_event(dhd->iflist[ifidx]->net, event, *data); - } - } -#endif /* defined(WL_WIRELESS_EXT) */ +#if defined(WL_EXT_IAPSTA) || defined(USE_IW) + wl_ext_event_send(dhd->pub.event_params, event, *data); +#endif #ifdef WL_CFG80211 ASSERT(dhd->iflist[ifidx] != NULL); @@ -15771,6 +15825,8 @@ static void dhd_hang_process(void *dhd_info, void *event_info, u8 event) struct net_device *dev; dhd = (dhd_info_t *)dhd_info; + if (!dhd || !dhd->iflist[0]) + return; dev = dhd->iflist[0]->net; if (dev) { @@ -16265,13 +16321,13 @@ write_dump_to_file(dhd_pub_t *dhd, uint8 *buf, int size, char *fname) int ret = 0; char memdump_path[128]; char memdump_type[32]; - struct timeval curtime; + struct osl_timespec curtime; uint32 file_mode; /* Init file name */ memset(memdump_path, 0, sizeof(memdump_path)); memset(memdump_type, 0, sizeof(memdump_type)); - do_gettimeofday(&curtime); + osl_do_gettimeofday(&curtime); dhd_convert_memdump_type_to_str(dhd->memdump_type, memdump_type); #ifdef CUSTOMER_HW4_DEBUG snprintf(memdump_path, sizeof(memdump_path), "%s%s_%s_%ld.%ld", @@ -18003,7 +18059,7 @@ do_dhd_log_dump(dhd_pub_t *dhdp) loff_t pos = 0; unsigned int wr_size = 0; char dump_path[128]; - struct timeval curtime; + struct osl_timespec curtime; uint32 file_mode; unsigned long flags = 0; struct dhd_log_dump_buf *dld_buf = &g_dld_buf[0]; @@ -18027,7 +18083,7 @@ do_dhd_log_dump(dhd_pub_t *dhdp) /* Init file name */ memset(dump_path, 0, sizeof(dump_path)); - do_gettimeofday(&curtime); + osl_do_gettimeofday(&curtime); snprintf(dump_path, sizeof(dump_path), "%s_%ld.%ld", DHD_COMMON_DUMP_PATH "debug_dump", (unsigned long)curtime.tv_sec, (unsigned long)curtime.tv_usec); @@ -18656,7 +18712,67 @@ dhd_linux_get_primary_netdev(dhd_pub_t *dhdp) return NULL; } +#ifdef DHD_ARP_DUMP +#define ARP_PRINT(str) \ + do { \ + DHD_ERROR(("[dhd-%s] " str " [%s] : %s(%s) %s %s(%s)\n", \ + ifname, tx?"TX":"RX", \ + tx?sabuf:dabuf, tx?seabuf:deabuf, \ + tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf)); \ + } while (0) + +#define ARP_PRINT_OTHER(str) \ + do { \ + DHD_ERROR(("[dhd-%s] " str " [%s] : %s(%s) %s %s(%s) op_code=%d\n", \ + ifname, tx?"TX":"RX", \ + tx?sabuf:dabuf, tx?seabuf:deabuf, \ + tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, opcode)); \ + } while (0) + +static void +dhd_arp_dump(char *ifname, uint8 *pktdata, bool tx) +{ + uint8 *pkt = (uint8 *)&pktdata[ETHER_HDR_LEN]; + struct bcmarp *arph = (struct bcmarp *)pkt; + uint16 opcode; + char sabuf[20]="", dabuf[20]=""; + char seabuf[ETHER_ADDR_STR_LEN]=""; + char deabuf[ETHER_ADDR_STR_LEN]=""; + + if (!(dump_msg_level & DUMP_ARP_VAL)) + return; + + /* validation check */ + if (arph->htype != hton16(HTYPE_ETHERNET) || + arph->hlen != ETHER_ADDR_LEN || + arph->plen != 4) { + return; + } + + opcode = ntoh16(arph->oper); + bcm_ip_ntoa((struct ipv4_addr *)arph->src_ip, sabuf); + bcm_ip_ntoa((struct ipv4_addr *)arph->dst_ip, dabuf); + bcm_ether_ntoa((struct ether_addr *)arph->dst_eth, deabuf); + bcm_ether_ntoa((struct ether_addr *)arph->src_eth, seabuf); + if (opcode == ARP_OPC_REQUEST) { + ARP_PRINT("ARP REQUEST "); + } else if (opcode == ARP_OPC_REPLY) { + ARP_PRINT("ARP RESPONSE"); + } else { + ARP_PRINT_OTHER("ARP OTHER"); + } +} +#endif /* DHD_ARP_DUMP */ + #ifdef DHD_DHCP_DUMP +#define DHCP_PRINT(str) \ + do { \ + DHD_ERROR(("[dhd-%s] " str " %8s, %8s [%s] : %s(%s) %s %s(%s)\n", \ + ifname, dhcp_types[dhcp_type], dhcp_ops[b->op], \ + tx?"TX":"RX", \ + tx?sabuf:dabuf, tx?seabuf:deabuf, \ + tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf)); \ + } while (0) static void dhd_dhcp_dump(char *ifname, uint8 *pktdata, bool tx) { @@ -18664,6 +18780,13 @@ dhd_dhcp_dump(char *ifname, uint8 *pktdata, bool tx) struct iphdr *h = &b->ip_header; uint8 *ptr, *opt, *end = (uint8 *) b + ntohs(b->ip_header.tot_len); int dhcp_type = 0, len, opt_len; + uint32 ip_saddr, ip_daddr; + char sabuf[20]="", dabuf[20]=""; + char seabuf[ETHER_ADDR_STR_LEN]=""; + char deabuf[ETHER_ADDR_STR_LEN]=""; + + if (!(dump_msg_level & DUMP_DHCP_VAL)) + return; /* check IP header */ if (h->ihl != 5 || h->version != 4 || h->protocol != IPPROTO_UDP) { @@ -18680,6 +18803,12 @@ dhd_dhcp_dump(char *ifname, uint8 *pktdata, bool tx) if (ntohs(h->tot_len) < ntohs(b->udp_header.len) + sizeof(struct iphdr)) { return; } + ip_saddr = h->saddr; + ip_daddr = h->daddr; + bcm_ip_ntoa((struct ipv4_addr *)&ip_saddr, sabuf); + bcm_ip_ntoa((struct ipv4_addr *)&ip_daddr, dabuf); + bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf); + bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf); len = ntohs(b->udp_header.len) - sizeof(struct udphdr); opt_len = len @@ -18701,9 +18830,7 @@ dhd_dhcp_dump(char *ifname, uint8 *pktdata, bool tx) if (*opt == 53) { if (opt[1]) { dhcp_type = opt[2]; - DHD_ERROR(("DHCP[%s] - %s [%s] [%s]\n", - ifname, dhcp_types[dhcp_type], - tx ? "TX" : "RX", dhcp_ops[b->op])); + DHCP_PRINT("DHCP"); break; } } @@ -18713,12 +18840,25 @@ dhd_dhcp_dump(char *ifname, uint8 *pktdata, bool tx) #endif /* DHD_DHCP_DUMP */ #ifdef DHD_ICMP_DUMP +#define ICMP_PRINT(str) \ + do { \ + DHD_ERROR(("[dhd-%s] " str " [%2s] : %s(%s) %s %s(%s)\n", \ + ifname, tx?"TX":"RX", tx?sabuf:dabuf, tx?seabuf:deabuf, \ + tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf)); \ + } while (0) static void dhd_icmp_dump(char *ifname, uint8 *pktdata, bool tx) { uint8 *pkt = (uint8 *)&pktdata[ETHER_HDR_LEN]; struct iphdr *iph = (struct iphdr *)pkt; struct icmphdr *icmph; + uint32 ip_saddr, ip_daddr; + char sabuf[20]="", dabuf[20]=""; + char seabuf[ETHER_ADDR_STR_LEN]=""; + char deabuf[ETHER_ADDR_STR_LEN]=""; + + if (!(dump_msg_level & DUMP_ICMP_VAL)) + return; /* check IP header */ if (iph->ihl != 5 || iph->version != 4 || iph->protocol != IP_PROT_ICMP) { @@ -18726,15 +18866,18 @@ dhd_icmp_dump(char *ifname, uint8 *pktdata, bool tx) } icmph = (struct icmphdr *)((uint8 *)pkt + sizeof(struct iphdr)); + ip_saddr = iph->saddr; + ip_daddr = iph->daddr; + bcm_ip_ntoa((struct ipv4_addr *)&ip_saddr, sabuf); + bcm_ip_ntoa((struct ipv4_addr *)&ip_daddr, dabuf); + bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf); + bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf); if (icmph->type == ICMP_ECHO) { - DHD_ERROR(("PING REQUEST[%s] [%s] : SEQNUM=%d\n", - ifname, tx ? "TX" : "RX", ntoh16(icmph->un.echo.sequence))); + ICMP_PRINT("PING REQUEST"); } else if (icmph->type == ICMP_ECHOREPLY) { - DHD_ERROR(("PING REPLY[%s] [%s] : SEQNUM=%d\n", - ifname, tx ? "TX" : "RX", ntoh16(icmph->un.echo.sequence))); + ICMP_PRINT("PING REPLY "); } else { - DHD_ERROR(("ICMP [%s] [%s] : TYPE=%d, CODE=%d\n", - ifname, tx ? "TX" : "RX", icmph->type, icmph->code)); + ICMP_PRINT("ICMP "); } } #endif /* DHD_ICMP_DUMP */ @@ -19754,17 +19897,6 @@ void *dhd_get_pub(struct net_device *dev) } } -void *dhd_get_conf(struct net_device *dev) -{ - dhd_info_t *dhdinfo = *(dhd_info_t **)netdev_priv(dev); - if (dhdinfo) - return (void *)dhdinfo->pub.conf; - else { - printf("%s: null dhdinfo\n", __FUNCTION__); - return NULL; - } -} - bool dhd_os_wd_timer_enabled(void *bus) { dhd_pub_t *pub = bus; diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux.h index 248f5271da0b..c97450fbdd3f 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux.h @@ -107,9 +107,9 @@ struct wifi_platform_data { int (*set_carddetect)(int val); void *(*mem_prealloc)(int section, unsigned long size); int (*get_mac_addr)(unsigned char *buf); -#if defined(CUSTOM_COUNTRY_CODE) +#ifdef CUSTOM_FORCE_NODFS_FLAG void *(*get_country_code)(char *ccode, u32 flags); -#else /* defined (CUSTOM_COUNTRY_CODE) */ +#else /* defined (CUSTOM_FORCE_NODFS_FLAG) */ void *(*get_country_code)(char *ccode); #endif }; diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux_platdev.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux_platdev.c index 651017838977..4d75cd3981c1 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux_platdev.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_linux_platdev.c @@ -307,7 +307,7 @@ wifi_platform_get_country_code(wifi_adapter_info_t *adapter, char *ccode) DHD_TRACE(("%s\n", __FUNCTION__)); if (plat_data->get_country_code) { -#ifdef CUSTOM_COUNTRY_CODE +#ifdef CUSTOM_FORCE_NODFS_FLAG return plat_data->get_country_code(ccode, flags); #else return plat_data->get_country_code(ccode); @@ -892,6 +892,9 @@ fail: wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY); wifi_platform_bus_enumerate(adapter, FALSE); } +#else + /* x86 bring-up PC needs no power-up operations */ + err = dhd_bus_register(); #endif return err; @@ -906,11 +909,13 @@ static int dhd_wifi_platform_load_sdio(void) #ifdef BCMDBUS static int dhd_wifi_platform_load_usb(void) { + int err = 0; +#if !defined(DHD_PRELOAD) wifi_adapter_info_t *adapter; s32 timeout = -1; int i; - int err = 0; enum wifi_adapter_status wait_status; +#endif err = dhd_bus_register(); if (err) { @@ -918,6 +923,7 @@ static int dhd_wifi_platform_load_usb(void) goto exit; } +#if !defined(DHD_PRELOAD) /* power up all adapters */ for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) { adapter = &dhd_wifi_platdata->adapters[i]; @@ -944,10 +950,12 @@ static int dhd_wifi_platform_load_usb(void) goto fail; } } +#endif exit: return err; +#if !defined(DHD_PRELOAD) fail: dhd_bus_unregister(); /* power down all adapters */ @@ -957,6 +965,7 @@ fail: } return err; +#endif } #else /* BCMDBUS */ static int dhd_wifi_platform_load_usb(void) diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_msgbuf.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_msgbuf.c index 455f125a9687..bb56c1aa0cdc 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_msgbuf.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_msgbuf.c @@ -6023,7 +6023,7 @@ dhd_msgbuf_wait_ioctl_cmplt(dhd_pub_t *dhd, uint32 len, void *buf) goto out; } - timeleft = dhd_os_ioctl_resp_wait(dhd, (uint *)&prot->ioctl_received, false); + timeleft = dhd_os_ioctl_resp_wait(dhd, (uint *)&prot->ioctl_received); #ifdef DHD_RECOVER_TIMEOUT if (prot->ioctl_received == 0) { @@ -6064,10 +6064,11 @@ dhd_msgbuf_wait_ioctl_cmplt(dhd_pub_t *dhd, uint32 len, void *buf) if (intstatus) { DHD_ERROR(("%s: reschedule dhd_dpc, cnt=%d, intstatus=0x%x, intmask=0x%x\n", __FUNCTION__, cnt, intstatus, intmask)); + dhd->bus->intstatus = intstatus; dhd->bus->ipend = TRUE; dhd->bus->dpc_sched = TRUE; dhd_sched_dpc(dhd); - timeleft = dhd_os_ioctl_resp_wait(dhd, &prot->ioctl_received, true); + timeleft = dhd_os_ioctl_resp_wait(dhd, &prot->ioctl_received); } } } else { diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_pcie.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_pcie.c index a785fe52be96..3d302287f854 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_pcie.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_pcie.c @@ -1628,36 +1628,6 @@ dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh, return ret; } -void -dhd_set_path_params(struct dhd_bus *bus) -{ - /* External conf takes precedence if specified */ - dhd_conf_preinit(bus->dhd); - - if (bus->dhd->clm_path[0] == '\0') { - dhd_conf_set_path(bus->dhd, "clm.blob", bus->dhd->clm_path, bus->fw_path); - } - dhd_conf_set_clm_name_by_chip(bus->dhd, bus->dhd->clm_path); - if (bus->dhd->conf_path[0] == '\0') { - dhd_conf_set_path(bus->dhd, "config.txt", bus->dhd->conf_path, bus->nv_path); - } -#ifdef CONFIG_PATH_AUTO_SELECT - dhd_conf_set_conf_name_by_chip(bus->dhd, bus->dhd->conf_path); -#endif - - dhd_conf_read_config(bus->dhd, bus->dhd->conf_path); - - dhd_conf_set_fw_name_by_chip(bus->dhd, bus->fw_path); - dhd_conf_set_nv_name_by_chip(bus->dhd, bus->nv_path); - dhd_conf_set_clm_name_by_chip(bus->dhd, bus->dhd->clm_path); - - printf("Final fw_path=%s\n", bus->fw_path); - printf("Final nv_path=%s\n", bus->nv_path); - printf("Final clm_path=%s\n", bus->dhd->clm_path); - printf("Final conf_path=%s\n", bus->dhd->conf_path); - -} - void dhd_set_bus_params(struct dhd_bus *bus) { @@ -1709,7 +1679,7 @@ dhdpcie_download_firmware(struct dhd_bus *bus, osl_t *osh) DHD_OS_WAKE_LOCK(bus->dhd); - dhd_set_path_params(bus); + dhd_conf_set_path_params(bus->dhd, NULL, bus->fw_path, bus->nv_path); dhd_set_bus_params(bus); ret = _dhdpcie_download_firmware(bus); @@ -2920,7 +2890,8 @@ dhd_bus_schedule_queue(struct dhd_bus *bus, uint16 flow_id, bool txs) } while ((txp = dhd_flow_queue_dequeue(bus->dhd, queue)) != NULL) { - PKTORPHAN(txp, bus->dhd->conf->tsq); + if (bus->dhd->conf->orphan_move <= 1) + PKTORPHAN(txp, bus->dhd->conf->tsq); /* * Modifying the packet length caused P2P cert failures. diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_pcie_linux.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_pcie_linux.c index ecaed3e93558..928c72ba182b 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_pcie_linux.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_pcie_linux.c @@ -139,7 +139,7 @@ struct pcos_info { dhdpcie_info_t *pc; spinlock_t lock; wait_queue_head_t intr_wait_queue; - struct timer_list tuning_timer; + timer_list_compat_t tuning_timer; int tuning_timer_exp; atomic_t timer_enab; struct tasklet_struct tuning_tasklet; @@ -570,7 +570,7 @@ static int dhdpcie_suspend_dev(struct pci_dev *dev) DHD_ERROR(("%s: pci_set_power_state error %d\n", __FUNCTION__, ret)); } - dev->state_saved = FALSE; +// dev->state_saved = FALSE; return ret; } @@ -607,7 +607,7 @@ static int dhdpcie_resume_dev(struct pci_dev *dev) pci_load_and_free_saved_state(dev, &pch->state); #endif /* OEM_ANDROID && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */ DHD_TRACE_HW4(("%s: Enter\n", __FUNCTION__)); - dev->state_saved = TRUE; +// dev->state_saved = TRUE; pci_restore_state(dev); err = pci_enable_device(dev); if (err) { @@ -884,11 +884,13 @@ dhdpcie_bus_unregister(void) int __devinit dhdpcie_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { + int err = 0; DHD_MUTEX_LOCK(); if (dhdpcie_chipmatch (pdev->vendor, pdev->device)) { DHD_ERROR(("%s: chipmatch failed!!\n", __FUNCTION__)); - return -ENODEV; + err = -ENODEV; + goto exit; } printf("PCI_PROBE: bus %X, slot %X,vendor %X, device %X" "(good PCI location)\n", pdev->bus->number, @@ -896,7 +898,8 @@ dhdpcie_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (dhdpcie_init (pdev)) { DHD_ERROR(("%s: PCIe Enumeration failed\n", __FUNCTION__)); - return -ENODEV; + err = -ENODEV; + goto exit; } #ifdef BCMPCIE_DISABLE_ASYNC_SUSPEND @@ -905,8 +908,10 @@ dhdpcie_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) #endif /* BCMPCIE_DISABLE_ASYNC_SUSPEND */ DHD_TRACE(("%s: PCIe Enumeration done!!\n", __FUNCTION__)); + +exit: DHD_MUTEX_UNLOCK(); - return 0; + return err; } int @@ -1203,7 +1208,8 @@ void dhdpcie_linkdown_cb(struct_pcie_notify *noti) } } -#endif /* CONFIG_ARCH_MSM || (EXYNOS_PCIE_LINKDOWN_RECOVERY && +#endif +/* CONFIG_ARCH_MSM || (EXYNOS_PCIE_LINKDOWN_RECOVERY && * (CONFIG_SOC_EXYNOS8890 || CONFIG_SOC_EXYNOS8895)) */ #endif /* SUPPORT_LINKDOWN_RECOVERY */ @@ -1541,7 +1547,7 @@ dhdpcie_enable_irq(dhd_bus_t *bus) bool dhdpcie_irq_enabled(dhd_bus_t *bus) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) struct irq_desc *desc = irq_to_desc(bus->dev->irq); /* depth will be zero, if enabled */ if (!desc->depth) { diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_pno.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_pno.c index 570e75ec8167..e095d6035ac8 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_pno.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_pno.c @@ -186,7 +186,7 @@ dhd_is_legacy_pno_enabled(dhd_pub_t *dhd) #ifdef GSCAN_SUPPORT static uint64 -convert_fw_rel_time_to_systime(struct timespec *ts, uint32 fw_ts_ms) +convert_fw_rel_time_to_systime(struct osl_timespec *ts, uint32 fw_ts_ms) { return ((uint64)(TIMESPEC_TO_US(*ts)) - (uint64)(fw_ts_ms * 1000)); } @@ -2566,7 +2566,7 @@ _dhd_pno_get_gscan_batch_from_fw(dhd_pub_t *dhd) uint8 *nAPs_per_scan = NULL; uint8 num_scans_in_cur_iter; uint16 count; - struct timespec tm_spec; + struct osl_timespec tm_spec; NULL_CHECK(dhd, "dhd is NULL\n", err); NULL_CHECK(dhd->pno_state, "pno_state is NULL", err); @@ -2626,7 +2626,7 @@ _dhd_pno_get_gscan_batch_from_fw(dhd_pub_t *dhd) __FUNCTION__, err)); goto exit_mutex_unlock; } - get_monotonic_boottime(&tm_spec); + osl_get_monotonic_boottime(&tm_spec); DHD_PNO(("ver %d, status : %d, count %d\n", plbestnet->version, plbestnet->status, plbestnet->count)); if (plbestnet->version != PFN_SCANRESULT_VERSION) { @@ -3672,7 +3672,7 @@ dhd_process_full_gscan_result(dhd_pub_t *dhd, const void *data, uint32 len, int u32 bi_length = 0; uint8 channel; uint32 mem_needed; - struct timespec ts; + struct osl_timespec ts; u32 bi_ie_length = 0; u32 bi_ie_offset = 0; @@ -3734,7 +3734,7 @@ dhd_process_full_gscan_result(dhd_pub_t *dhd, const void *data, uint32 len, int result->fixed.rssi = (int32) bi->RSSI; result->fixed.rtt = 0; result->fixed.rtt_sd = 0; - get_monotonic_boottime(&ts); + osl_get_monotonic_boottime(&ts); result->fixed.ts = (uint64) TIMESPEC_TO_US(ts); result->fixed.beacon_period = dtoh16(bi->beacon_period); result->fixed.capability = dtoh16(bi->capability); @@ -3843,7 +3843,7 @@ dhd_handle_hotlist_scan_evt(dhd_pub_t *dhd, const void *event_data, wl_pfn_net_info_v2_t *plnetinfo; gscan_results_cache_t *gscan_hotlist_cache; int malloc_size = 0, i, total = 0; - struct timespec tm_spec; + struct osl_timespec tm_spec; gscan_params = &(_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS].params_gscan); @@ -3853,7 +3853,7 @@ dhd_handle_hotlist_scan_evt(dhd_pub_t *dhd, const void *event_data, return ptr; } - get_monotonic_boottime(&tm_spec); + osl_get_monotonic_boottime(&tm_spec); malloc_size = sizeof(gscan_results_cache_t) + ((results->count - 1) * sizeof(wifi_gscan_result_t)); gscan_hotlist_cache = (gscan_results_cache_t *) kmalloc(malloc_size, GFP_KERNEL); diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_rtt.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_rtt.c index 67a86e022fdd..603e35cedb09 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_rtt.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_rtt.c @@ -1611,7 +1611,7 @@ dhd_rtt_convert_results_to_host(rtt_report_t *rtt_report, uint8 *p_data, uint16 wl_proxd_session_state_t session_state; wl_proxd_status_t proxd_status; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) - struct timespec ts; + struct osl_timespec ts; #endif /* LINUX_VER >= 2.6.39 */ uint32 ratespec; uint32 avg_dist; @@ -1708,7 +1708,7 @@ dhd_rtt_convert_results_to_host(rtt_report_t *rtt_report, uint8 *p_data, uint16 /* time stamp */ /* get the time elapsed from boot time */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) - get_monotonic_boottime(&ts); + osl_get_monotonic_boottime(&ts); rtt_report->ts = (uint64)TIMESPEC_TO_US(ts); #endif /* LINUX_VER >= 2.6.39 */ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_sdio.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_sdio.c index 84fa6e91608c..7933a0973a29 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_sdio.c @@ -193,7 +193,7 @@ extern unsigned int system_hw_rev; /* Device console log buffer state */ #define CONSOLE_LINE_MAX 192 -#define CONSOLE_BUFFER_MAX 2024 +#define CONSOLE_BUFFER_MAX 8192 typedef struct dhd_console { uint count; /* Poll interval msec counter */ uint log_addr; /* Log struct address (fixed) */ @@ -350,6 +350,10 @@ typedef struct dhd_bus { bool usebufpool; int32 txinrx_thres; /* num of in-queued pkts */ int32 dotxinrx; /* tx first in dhdsdio_readframes */ +#ifdef BCMSDIO_RXLIM_POST + bool rxlim_en; + uint32 rxlim_addr; +#endif /* BCMSDIO_RXLIM_POST */ #ifdef SDTEST /* external loopback */ bool ext_loop; @@ -1904,6 +1908,7 @@ void dhdsdio_reset_bt_use_count(struct dhd_bus *bus) } #endif /* BT_OVER_SDIO */ +#ifdef USE_DYNAMIC_F2_BLKSIZE int dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size) { int func_blk_size = function_num; @@ -1919,7 +1924,7 @@ int dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size) } if (result != block_size) { - DHD_ERROR(("%s: F%d Block size set from %d to %d\n", + DHD_TRACE_HW4(("%s: F%d Block size set from %d to %d\n", __FUNCTION__, function_num, result, block_size)); func_blk_size = function_num << 16 | block_size; bcmerr = dhd_bus_iovar_op(dhd, "sd_blocksize", NULL, @@ -1932,6 +1937,7 @@ int dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size) return BCME_OK; } +#endif /* USE_DYNAMIC_F2_BLKSIZE */ #if defined(OOB_INTR_ONLY) || defined(FORCE_WOWLAN) void @@ -1995,7 +2001,7 @@ dhd_bus_txdata(struct dhd_bus *bus, void *pkt) prec = PRIO2PREC((PKTPRIO(pkt) & PRIOMASK)); /* move from dhdsdio_sendfromq(), try to orphan skb early */ - if (bus->dhd->conf->orphan_move) + if (bus->dhd->conf->orphan_move == 1) PKTORPHAN(pkt, bus->dhd->conf->tsq); /* Check for existing queue, current flow-control, pending event, or pending clock */ @@ -2858,6 +2864,11 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) #endif /* CUSTOMER_HW4_DEBUG */ DHD_ERROR(("%s: ctrl_frame_stat == TRUE txcnt_timeout=%d\n", __FUNCTION__, bus->dhd->txcnt_timeout)); +#ifdef BCMSDIO_RXLIM_POST + DHD_ERROR(("%s: rxlim_en=%d, rxlim enable=%d, rxlim_addr=%d\n", + __FUNCTION__, + bus->dhd->conf->rxlim_en, bus->rxlim_en, bus->rxlim_addr)); +#endif /* BCMSDIO_RXLIM_POST */ } #ifdef DHD_FW_COREDUMP /* Collect socram dump */ @@ -2937,7 +2948,7 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen) return -EIO; /* Wait until control frame is available */ - timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen, false); + timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen); dhd_os_sdlock(bus->dhd); rxlen = bus->rxlen; @@ -2958,7 +2969,7 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen) dhd_sched_dpc(bus->dhd); /* Wait until control frame is available */ - timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen, true); + timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen); dhd_os_sdlock(bus->dhd); rxlen = bus->rxlen; @@ -3505,6 +3516,21 @@ dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh) sh->console_addr = ltoh32(sh->console_addr); sh->msgtrace_addr = ltoh32(sh->msgtrace_addr); +#ifdef BCMSDIO_RXLIM_POST + if (sh->flags & SDPCM_SHARED_RXLIM_POST) { + if (bus->dhd->conf->rxlim_en) + bus->rxlim_en = !!sh->msgtrace_addr; + bus->rxlim_addr = sh->msgtrace_addr; + DHD_INFO(("%s: rxlim_en=%d, rxlim enable=%d, rxlim_addr=%d\n", + __FUNCTION__, + bus->dhd->conf->rxlim_en, bus->rxlim_en, bus->rxlim_addr)); + sh->flags &= ~SDPCM_SHARED_RXLIM_POST; + } else { + bus->rxlim_en = 0; + DHD_INFO(("%s: FW has no rx limit post support\n", __FUNCTION__)); + } +#endif /* BCMSDIO_RXLIM_POST */ + if ((sh->flags & SDPCM_SHARED_VERSION_MASK) == 3 && SDPCM_SHARED_VERSION == 1) return BCME_OK; @@ -5039,6 +5065,9 @@ dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex) uint8 ready, enable; int err, ret = 0; uint8 saveclk; +#if defined(SDIO_ISR_THREAD) + int intr_extn; +#endif DHD_TRACE(("%s: Enter\n", __FUNCTION__)); @@ -5098,6 +5127,15 @@ dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex) DHD_ERROR(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n", __FUNCTION__, enable, ready, tmo.elapsed)); +#if defined(SDIO_ISR_THREAD) + if (dhdp->conf->intr_extn) { + intr_extn = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTR_EXTN, NULL); + if (intr_extn & 0x1) { + intr_extn |= 0x2; + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTR_EXTN, intr_extn, NULL); + } + } +#endif /* If F2 successfully enabled, set core and enable interrupts */ if (ready == enable) { @@ -5589,7 +5627,7 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) /* Check window for sanity */ if ((uint8)(txmax - bus->tx_seq) > 0x70) { - DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", + DHD_INFO(("%s: got unlikely tx max %d with tx_seq %d\n", __FUNCTION__, txmax, bus->tx_seq)); txmax = bus->tx_max; } @@ -6092,7 +6130,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) /* Check window for sanity */ if ((uint8)(txmax - bus->tx_seq) > 0x70) { - DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", + DHD_INFO(("%s: got unlikely tx max %d with tx_seq %d\n", __FUNCTION__, txmax, bus->tx_seq)); txmax = bus->tx_max; } @@ -6249,7 +6287,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) /* Check window for sanity */ if ((uint8)(txmax - bus->tx_seq) > 0x70) { - DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", + DHD_INFO(("%s: got unlikely tx max %d with tx_seq %d\n", __FUNCTION__, txmax, bus->tx_seq)); txmax = bus->tx_max; } @@ -6776,6 +6814,19 @@ clkwait: } #endif /* defined(OOB_INTR_ONLY) && !defined(HW_OOB) */ +#ifdef BCMSDIO_RXLIM_POST + if (!DATAOK(bus) && bus->rxlim_en) { + uint8 rxlim = 0; + if (0 == dhdsdio_membytes(bus, FALSE, bus->rxlim_addr, (uint8 *)&rxlim, 1)) { + if (bus->tx_max != rxlim) { + DHD_INFO(("%s: bus->tx_max/rxlim=%d/%d\n", __FUNCTION__, + bus->tx_max, rxlim)); + bus->tx_max = rxlim; + } + } + } +#endif /* BCMSDIO_RXLIM_POST */ + #ifdef PROP_TXSTATUS dhd_wlfc_commit_packets(bus->dhd, (f_commitpkt_t)dhd_bus_txdata, (void *)bus, NULL, FALSE); #endif @@ -6917,7 +6968,7 @@ dhdsdio_isr(void *arg) dhd_bus_t *bus = (dhd_bus_t*)arg; bcmsdh_info_t *sdh; - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + DHD_INTR(("%s: Enter\n", __FUNCTION__)); if (!bus) { DHD_ERROR(("%s : bus is null pointer , exit \n", __FUNCTION__)); @@ -6930,8 +6981,6 @@ dhdsdio_isr(void *arg) return; } - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - /* Count the interrupt call */ bus->intrcount++; bus->ipend = TRUE; @@ -7568,6 +7617,13 @@ dhd_bus_console_in(dhd_pub_t *dhdp, uchar *msg, uint msglen) if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0) goto done; + if (!DATAOK(bus)) { + DHD_CTL(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d, pktq_len %d\n", + __FUNCTION__, bus->tx_max, bus->tx_seq, pktq_len(&bus->txq))); + rv = BCME_NOTREADY; + goto done; + } + /* Bump dongle by sending an empty packet on the event channel. * sdpcm_sendup (RX) checks for virtual console input. */ @@ -8313,38 +8369,6 @@ dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh, return ret; } -void -dhd_set_path_params(struct dhd_bus *bus) -{ - /* External conf takes precedence if specified */ - dhd_conf_preinit(bus->dhd); - - if (bus->dhd->conf_path[0] == '\0') { - dhd_conf_set_path(bus->dhd, "config.txt", bus->dhd->conf_path, bus->nv_path); - } - if (bus->dhd->clm_path[0] == '\0') { - dhd_conf_set_path(bus->dhd, "clm.blob", bus->dhd->clm_path, bus->fw_path); - } -#ifdef CONFIG_PATH_AUTO_SELECT - dhd_conf_set_conf_name_by_chip(bus->dhd, bus->dhd->conf_path); -#endif - - dhd_conf_read_config(bus->dhd, bus->dhd->conf_path); - - dhd_conf_set_fw_name_by_chip(bus->dhd, bus->fw_path); - dhd_conf_set_nv_name_by_chip(bus->dhd, bus->nv_path); - dhd_conf_set_clm_name_by_chip(bus->dhd, bus->dhd->clm_path); - - dhd_conf_set_fw_name_by_mac(bus->dhd, bus->sdh, bus->fw_path); - dhd_conf_set_nv_name_by_mac(bus->dhd, bus->sdh, bus->nv_path); - - printf("Final fw_path=%s\n", bus->fw_path); - printf("Final nv_path=%s\n", bus->nv_path); - printf("Final clm_path=%s\n", bus->dhd->clm_path); - printf("Final conf_path=%s\n", bus->dhd->conf_path); - -} - void dhd_set_bus_params(struct dhd_bus *bus) { @@ -8382,7 +8406,7 @@ dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh) /* Download the firmware */ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); - dhd_set_path_params(bus); + dhd_conf_set_path_params(bus->dhd, bus->sdh, bus->fw_path, bus->nv_path); dhd_set_bus_params(bus); ret = _dhdsdio_download_firmware(bus); @@ -10075,3 +10099,31 @@ dhd_bus_get_bus_wake(dhd_pub_t *dhd) return bcmsdh_set_get_wake(dhd->bus->sdh, 0); } #endif /* DHD_WAKE_STATUS */ + +int +dhd_bus_sleep(dhd_pub_t *dhdp, bool sleep, uint32 *intstatus) +{ + dhd_bus_t *bus = dhdp->bus; + uint32 retry = 0; + int ret = 0; + + if (bus) { + dhd_os_sdlock(dhdp); + BUS_WAKE(bus); + R_SDREG(*intstatus, &bus->regs->intstatus, retry); + if (sleep) { + if (SLPAUTO_ENAB(bus)) { + ret = dhdsdio_bussleep(bus, sleep); + if (ret != BCME_BUSY) + dhd_os_wd_timer(bus->dhd, 0); + } else + dhdsdio_clkctl(bus, CLK_NONE, FALSE); + } + dhd_os_sdunlock(dhdp); + } else { + DHD_ERROR(("bus is NULL\n")); + ret = -1; + } + + return ret; +} \ No newline at end of file diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_static_buf.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_static_buf.c index 56605d336208..ade49e070dbb 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_static_buf.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/dhd_static_buf.c @@ -36,7 +36,7 @@ enum dhd_prealloc_index { DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX = 16, DHD_PREALLOC_DHD_PKTLOG_DUMP_BUF = 17, DHD_PREALLOC_STAT_REPORT_BUF = 18, - DHD_PREALLOC_WL_ESCAN_INFO = 19, + DHD_PREALLOC_WL_ESCAN = 19, DHD_PREALLOC_FW_VERBOSE_RING = 20, DHD_PREALLOC_FW_EVENT_RING = 21, DHD_PREALLOC_DHD_EVENT_RING = 22, @@ -55,7 +55,7 @@ enum dhd_prealloc_index { #define DHD_PREALLOC_DHD_INFO_SIZE (32 * 1024) #define DHD_PREALLOC_MEMDUMP_RAM_SIZE (810 * 1024) #define DHD_PREALLOC_DHD_WLFC_HANGER_SIZE (73 * 1024) -#define DHD_PREALLOC_WL_ESCAN_INFO_SIZE (66 * 1024) +#define DHD_PREALLOC_WL_ESCAN_SIZE (70 * 1024) #ifdef CONFIG_64BIT #define DHD_PREALLOC_IF_FLOW_LKUP_SIZE (20 * 1024 * 2) #else @@ -192,10 +192,10 @@ void *dhd_wlan_mem_prealloc(int section, unsigned long size) } return wlan_static_dhd_wlfc_hanger_buf; } - if (section == DHD_PREALLOC_WL_ESCAN_INFO) { - if (size > DHD_PREALLOC_WL_ESCAN_INFO_SIZE) { - pr_err("request DHD_PREALLOC_WL_ESCAN_INFO_SIZE(%lu) > %d\n", - size, DHD_PREALLOC_WL_ESCAN_INFO_SIZE); + if (section == DHD_PREALLOC_WL_ESCAN) { + if (size > DHD_PREALLOC_WL_ESCAN_SIZE) { + pr_err("request DHD_PREALLOC_WL_ESCAN_SIZE(%lu) > %d\n", + size, DHD_PREALLOC_WL_ESCAN_SIZE); return NULL; } @@ -344,11 +344,11 @@ static int dhd_init_wlan_mem(void) pr_err("%s: sectoin %d, size=%d\n", __func__, DHD_PREALLOC_DHD_WLFC_HANGER, DHD_PREALLOC_DHD_WLFC_HANGER_SIZE); - wlan_static_wl_escan_info_buf = kmalloc(DHD_PREALLOC_WL_ESCAN_INFO_SIZE, GFP_KERNEL); + wlan_static_wl_escan_info_buf = kmalloc(DHD_PREALLOC_WL_ESCAN_SIZE, GFP_KERNEL); if (!wlan_static_wl_escan_info_buf) goto err_mem_alloc; pr_err("%s: sectoin %d, size=%d\n", __func__, - DHD_PREALLOC_WL_ESCAN_INFO, DHD_PREALLOC_WL_ESCAN_INFO_SIZE); + DHD_PREALLOC_WL_ESCAN, DHD_PREALLOC_WL_ESCAN_SIZE); wlan_static_fw_verbose_ring_buf = kmalloc(FW_VERBOSE_RING_SIZE, GFP_KERNEL); if (!wlan_static_fw_verbose_ring_buf) @@ -417,7 +417,7 @@ err_mem_alloc: if (wlan_static_wl_escan_info_buf) kfree(wlan_static_wl_escan_info_buf); - + #ifdef BCMDHD_PCIE if (wlan_static_fw_verbose_ring_buf) kfree(wlan_static_fw_verbose_ring_buf); @@ -513,7 +513,7 @@ dhd_static_buf_exit(void) if (wlan_static_wl_escan_info_buf) kfree(wlan_static_wl_escan_info_buf); - + #ifdef BCMDHD_PCIE if (wlan_static_fw_verbose_ring_buf) kfree(wlan_static_fw_verbose_ring_buf); diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/802.11.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/802.11.h index 2d7650ae9bbd..f2847ecbe74b 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/802.11.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/802.11.h @@ -4353,6 +4353,8 @@ typedef struct vht_features_ie_hdr vht_features_ie_hdr_t; #define RSN_AKM_SHA256_1X 5 /* SHA256 key derivation, using 802.1X */ #define RSN_AKM_SHA256_PSK 6 /* SHA256 key derivation, using Pre-shared Key */ #define RSN_AKM_TPK 7 /* TPK(TDLS Peer Key) handshake */ +#define RSN_AKM_SAE_PSK 8 /* AKM for SAE with 4-way handshake */ +#define RSN_AKM_SAE_FBT 9 /* AKM for SAE with FBT */ #define RSN_AKM_FILS_SHA256 14 /* SHA256 key derivation, using FILS */ #define RSN_AKM_FILS_SHA384 15 /* SHA384 key derivation, using FILS */ @@ -4395,6 +4397,10 @@ typedef struct vht_features_ie_hdr vht_features_ie_hdr_t; #define WCN_OUI "\x00\x50\xf2" /* WCN OUI */ #define WCN_TYPE 4 /* WCN type */ +#ifdef BCMWAPI_WPI +#define SMS4_KEY_LEN 16 +#define SMS4_WPI_CBC_MAC_LEN 16 +#endif /* 802.11r protocol definitions */ @@ -4473,6 +4479,13 @@ typedef struct dot11_ft_rrb_frame dot11_ft_rrb_frame_t; #define BSSID_INVALID "\x00\x00\x00\x00\x00\x00" #define BSSID_BROADCAST "\xFF\xFF\xFF\xFF\xFF\xFF" +#ifdef BCMWAPI_WAI +#define WAPI_IE_MIN_LEN 20 /* WAPI IE min length */ +#define WAPI_VERSION 1 /* WAPI version */ +#define WAPI_VERSION_LEN 2 /* WAPI version length */ +#define WAPI_OUI "\x00\x14\x72" /* WAPI OUI */ +#define WAPI_OUI_LEN DOT11_OUI_LEN /* WAPI OUI length */ +#endif /* BCMWAPI_WAI */ /* ************* WMM Parameter definitions. ************* */ #define WMM_OUI "\x00\x50\xF2" /* WNN OUI */ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/bcmip.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/bcmip.h index e5bb0ac66c59..47781a25a96f 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/bcmip.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/bcmip.h @@ -130,6 +130,21 @@ BWL_PRE_PACKED_STRUCT struct ipv4_hdr { uint8 dst_ip[IPV4_ADDR_LEN]; /* Destination IP Address */ } BWL_POST_PACKED_STRUCT; +#define HTYPE_ETHERNET 1 /* htype for ethernet */ +#define ARP_OPC_REQUEST 1 /* ARP request */ +#define ARP_OPC_REPLY 2 /* ARP reply */ +BWL_PRE_PACKED_STRUCT struct bcmarp { + uint16 htype; /* Header type (1 = ethernet) */ + uint16 ptype; /* Protocol type (0x800 = IP) */ + uint8 hlen; /* Hardware address length (Eth = 6) */ + uint8 plen; /* Protocol address length (IP = 4) */ + uint16 oper; /* ARP_OPC_... */ + uint8 src_eth[ETHER_ADDR_LEN]; /* Source hardware address */ + uint8 src_ip[IPV4_ADDR_LEN]; /* Source protocol address (not aligned) */ + uint8 dst_eth[ETHER_ADDR_LEN]; /* Destination hardware address */ + uint8 dst_ip[IPV4_ADDR_LEN]; /* Destination protocol address */ +} BWL_POST_PACKED_STRUCT; + /* IPV6 field offsets */ #define IPV6_PAYLOAD_LEN_OFFSET 4 /* payload length offset */ #define IPV6_NEXT_HDR_OFFSET 6 /* next header/protocol offset */ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/bcmsdpcm.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/bcmsdpcm.h index 6230047f4f3a..5b9c51b3a125 100755 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/bcmsdpcm.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/bcmsdpcm.h @@ -283,6 +283,7 @@ typedef volatile struct { #define SDPCM_SHARED_SET_BRPT 0x1000 #define SDPCM_SHARED_PENDING_BRPT 0x2000 #define SDPCM_SHARED_FATAL_LOGBUF_VALID 0x100000 +#define SDPCM_SHARED_RXLIM_POST 0x4000 typedef struct { uint32 flags; diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/brcm_nl80211.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/brcm_nl80211.h index 84bfddabffdd..cca207bdde2e 100755 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/brcm_nl80211.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/brcm_nl80211.h @@ -35,9 +35,13 @@ #define OUI_GOOGLE 0x001A11 enum wl_vendor_subcmd { - BRCM_VENDOR_SCMD_UNSPEC, - BRCM_VENDOR_SCMD_PRIV_STR, - BRCM_VENDOR_SCMD_BCM_STR + BRCM_VENDOR_SCMD_UNSPEC = 0, + BRCM_VENDOR_SCMD_PRIV_STR = 1, + BRCM_VENDOR_SCMD_BCM_STR = 2, + BRCM_VENDOR_SCMD_BCM_PSK = 3, + BRCM_VENDOR_SCMD_SET_PMK = 4, + BRCM_VENDOR_SCMD_GET_FEATURES = 5, + BRCM_VENDOR_SCMD_MAX = 6 }; diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/dhdioctl.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/dhdioctl.h index 8a139dcc1c1b..dd32fdb551e1 100755 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/dhdioctl.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/dhdioctl.h @@ -113,6 +113,12 @@ enum { #define DHD_IW_VAL 0x20000 #define DHD_CFG_VAL 0x40000 #define DHD_CONFIG_VAL 0x80000 +#define DUMP_EAPOL_VAL 0x0001 +#define DUMP_ARP_VAL 0x0002 +#define DUMP_DHCP_VAL 0x0004 +#define DUMP_ICMP_VAL 0x0008 +#define DUMP_DNS_VAL 0x0010 +#define DUMP_TRX_VAL 0x0080 #ifdef SDTEST /* For pktgen iovar */ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/epivers.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/epivers.h index f3fe5e9f4629..304da24d2d38 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/epivers.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/epivers.h @@ -46,6 +46,6 @@ #define EPI_VERSION_DEV 1.579.77.41 /* Driver Version String, ASCII, 32 chars max */ -#define EPI_VERSION_STR "1.579.77.41.10 (r)" +#define EPI_VERSION_STR "1.579.77.41.22 (r-20191105-2)(20191120-1)" #endif /* _epivers_h_ */ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/linux_osl.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/linux_osl.h index b40ec111c08b..dbe208a06f92 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/linux_osl.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/linux_osl.h @@ -1159,4 +1159,12 @@ extern void osl_timer_update(osl_t *osh, osl_timer_t *t, uint32 ms, bool periodi extern bool osl_timer_del(osl_t *osh, osl_timer_t *t); #endif +typedef struct osl_timespec { + __kernel_time_t tv_sec; /* seconds */ + __kernel_suseconds_t tv_usec; /* microseconds */ + long tv_nsec; /* nanoseconds */ +} osl_timespec_t; +extern void osl_do_gettimeofday(struct osl_timespec *ts); +extern void osl_get_monotonic_boottime(struct osl_timespec *ts); + #endif /* _linux_osl_h_ */ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/linuxver.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/linuxver.h index 36cba287ddbe..d51fbac19479 100755 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/linuxver.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/linuxver.h @@ -347,6 +347,42 @@ static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size, #endif /* DMA mapping */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) + +typedef struct timer_list timer_list_compat_t; + +#define init_timer_compat(timer_compat, cb, priv) \ + init_timer(timer_compat); \ + (timer_compat)->data = (ulong)priv; \ + (timer_compat)->function = cb +#define timer_set_private(timer_compat, priv) (timer_compat)->data = (ulong)priv +#define timer_expires(timer_compat) (timer_compat)->expires + +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) */ + +typedef struct timer_list_compat { + struct timer_list timer; + void *arg; + void (*callback)(ulong arg); +} timer_list_compat_t; + +extern void timer_cb_compat(struct timer_list *tl); + +#define init_timer_compat(timer_compat, cb, priv) \ + (timer_compat)->arg = priv; \ + (timer_compat)->callback = cb; \ + timer_setup(&(timer_compat)->timer, timer_cb_compat, 0); +#define timer_set_private(timer_compat, priv) (timer_compat)->arg = priv +#define timer_expires(timer_compat) (timer_compat)->timer.expires + +#define del_timer(t) del_timer(&((t)->timer)) +#define del_timer_sync(t) del_timer_sync(&((t)->timer)) +#define timer_pending(t) timer_pending(&((t)->timer)) +#define add_timer(t) add_timer(&((t)->timer)) +#define mod_timer(t, j) mod_timer(&((t)->timer), j) + +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0) */ + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 43)) #define dev_kfree_skb_any(a) dev_kfree_skb(a) @@ -765,6 +801,7 @@ not match our unaligned address for < 2.6.24 #endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)) +#include static inline struct inode *file_inode(const struct file *f) { return f->f_dentry->d_inode; diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/wlioctl.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/wlioctl.h index da8392dc9b0f..444cb0021d5b 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/wlioctl.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/wlioctl.h @@ -1081,6 +1081,8 @@ typedef struct wl_wsec_key { #define WSEC_MIN_PSK_LEN 8 #define WSEC_MAX_PSK_LEN 64 +/* Max length of supported passphrases for SAE */ +#define WSEC_MAX_PASSPHRASE_LEN 256u /** Flag for key material needing passhash'ing */ #define WSEC_PASSPHRASE (1<<0) @@ -1092,6 +1094,23 @@ typedef struct wsec_pmk { uint8 key[WSEC_MAX_PSK_LEN]; /**< PMK material */ } wsec_pmk_t; +#define WL_AUTH_EVENT_DATA_V1 0x1 + +/* tlv ids for auth event */ +#define WL_AUTH_PMK_TLV_ID 1 +#define WL_AUTH_PMKID_TLV_ID 2 +/* AUTH event data +* pmk and pmkid in case of SAE auth +* xtlvs will be 32 bit alligned +*/ +typedef struct wl_auth_event { + uint16 version; + uint16 length; + uint8 xtlvs[]; +} wl_auth_event_t; + +#define WL_AUTH_EVENT_FIXED_LEN_V1 OFFSETOF(wl_auth_event_t, xtlvs) + typedef struct _pmkid { struct ether_addr BSSID; uint8 PMKID[WPA2_PMKID_LEN]; @@ -6521,6 +6540,7 @@ typedef struct wlc_btc_stats { #define LOGRRC_FIX_LEN 8 #define IOBUF_ALLOWED_NUM_OF_LOGREC(type, len) ((len - LOGRRC_FIX_LEN)/sizeof(type)) +#ifdef BCMWAPI_WAI /* BCMWAPI_WAI */ #define IV_LEN 16 struct wapi_sta_msg_t @@ -6534,7 +6554,7 @@ typedef struct wlc_btc_stats { uint8 gsn[IV_LEN]; uint8 wie[256]; }; -/* #endif BCMWAPI_WAI */ +#endif /* BCMWAPI_WAI */ /* chanim acs record */ typedef struct { uint8 valid; diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/wlioctl_defs.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/wlioctl_defs.h index 8038588d58e4..85e33b995d6f 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/wlioctl_defs.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/wlioctl_defs.h @@ -441,15 +441,40 @@ #define AES_ENABLED 0x0004 #define WSEC_SWFLAG 0x0008 #define SES_OW_ENABLED 0x0040 /* to go into transition mode without setting wep */ +#ifdef BCMWAPI_WPI +#define SMS4_ENABLED 0x0100 +#endif /* BCMWAPI_WPI */ #define WSEC_WEP_ENABLED(wsec) ((wsec) & WEP_ENABLED) #define WSEC_TKIP_ENABLED(wsec) ((wsec) & TKIP_ENABLED) #define WSEC_AES_ENABLED(wsec) ((wsec) & AES_ENABLED) +#ifdef BCMCCX +#define WSEC_CKIP_KP_ENABLED(wsec) ((wsec) & CKIP_KP_ENABLED) +#define WSEC_CKIP_MIC_ENABLED(wsec) ((wsec) & CKIP_MIC_ENABLED) +#define WSEC_CKIP_ENABLED(wsec) ((wsec) & (CKIP_KP_ENABLED|CKIP_MIC_ENABLED)) + +#ifdef BCMWAPI_WPI +#define WSEC_ENABLED(wsec) \ + ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED | CKIP_KP_ENABLED | \ + CKIP_MIC_ENABLED | SMS4_ENABLED)) +#else /* BCMWAPI_WPI */ +#define WSEC_ENABLED(wsec) \ + ((wsec) & \ + (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED | CKIP_KP_ENABLED | CKIP_MIC_ENABLED)) +#endif /* BCMWAPI_WPI */ +#else /* defined BCMCCX */ +#ifdef BCMWAPI_WPI +#define WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED | SMS4_ENABLED)) +#else /* BCMWAPI_WPI */ #define WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED)) +#endif /* BCMWAPI_WPI */ +#endif /* BCMCCX */ #define WSEC_SES_OW_ENABLED(wsec) ((wsec) & SES_OW_ENABLED) - +#ifdef BCMWAPI_WAI +#define WSEC_SMS4_ENABLED(wsec) ((wsec) & SMS4_ENABLED) +#endif /* BCMWAPI_WAI */ /* Following macros are not used any more. Just kept here to * avoid build issue in BISON/CARIBOU branch @@ -472,10 +497,17 @@ #define WPA2_AUTH_PSK 0x0080 /* Pre-shared key */ #define BRCM_AUTH_PSK 0x0100 /* BRCM specific PSK */ #define BRCM_AUTH_DPT 0x0200 /* DPT PSK without group keys */ +#if defined(BCMWAPI_WAI) || defined(BCMWAPI_WPI) +#define WPA_AUTH_WAPI 0x0400 +#define WAPI_AUTH_NONE WPA_AUTH_NONE /* none (IBSS) */ +#define WAPI_AUTH_UNSPECIFIED 0x0400 /* over AS */ +#define WAPI_AUTH_PSK 0x0800 /* Pre-shared key */ +#endif /* BCMWAPI_WAI || BCMWAPI_WPI */ #define WPA2_AUTH_1X_SHA256 0x1000 /* 1X with SHA256 key derivation */ #define WPA2_AUTH_TPK 0x2000 /* TDLS Peer Key */ #define WPA2_AUTH_FT 0x4000 /* Fast Transition. */ #define WPA2_AUTH_PSK_SHA256 0x8000 /* PSK with SHA256 key derivation */ +#define WPA3_AUTH_SAE_PSK 0x40000 /* SAE with 4-way handshake */ /* WPA2_AUTH_SHA256 not used anymore. Just kept here to avoid build issue in DINGO */ #define WPA2_AUTH_SHA256 0x8000 #define WPA_AUTH_PFN_ANY 0xffffffff /* for PFN, match only ssid */ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/wpa.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/wpa.h index f681ece53dff..fbb9c29e68ff 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/wpa.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/include/wpa.h @@ -128,6 +128,12 @@ typedef BWL_PRE_PACKED_STRUCT struct #define WPA_CIPHER_AES_GCM 8 /* AES (GCM) */ #define WPA_CIPHER_AES_GCM256 9 /* AES (GCM256) */ +#ifdef BCMWAPI_WAI +#define WAPI_CIPHER_NONE WPA_CIPHER_NONE +#define WAPI_CIPHER_SMS4 11 + +#define WAPI_CSE_WPI_SMS4 1 +#endif /* BCMWAPI_WAI */ #define IS_WPA_CIPHER(cipher) ((cipher) == WPA_CIPHER_NONE || \ (cipher) == WPA_CIPHER_WEP_40 || \ @@ -139,6 +145,17 @@ typedef BWL_PRE_PACKED_STRUCT struct (cipher) == WPA_CIPHER_AES_GCM256 || \ (cipher) == WPA_CIPHER_TPK) +#ifdef BCMWAPI_WAI +#define IS_WAPI_CIPHER(cipher) ((cipher) == WAPI_CIPHER_NONE || \ + (cipher) == WAPI_CSE_WPI_SMS4) + +/* convert WAPI_CSE_WPI_XXX to WAPI_CIPHER_XXX */ +#define WAPI_CSE_WPI_2_CIPHER(cse) ((cse) == WAPI_CSE_WPI_SMS4 ? \ + WAPI_CIPHER_SMS4 : WAPI_CIPHER_NONE) + +#define WAPI_CIPHER_2_CSE_WPI(cipher) ((cipher) == WAPI_CIPHER_SMS4 ? \ + WAPI_CSE_WPI_SMS4 : WAPI_CIPHER_NONE) +#endif /* BCMWAPI_WAI */ /* WPA TKIP countermeasures parameters */ #define WPA_TKIP_CM_DETECT 60 /* multiple MIC failure window (seconds) */ @@ -180,6 +197,19 @@ typedef BWL_PRE_PACKED_STRUCT struct #define WPA2_PMKID_COUNT_LEN 2 +#ifdef BCMWAPI_WAI +#define WAPI_CAP_PREAUTH RSN_CAP_PREAUTH + +/* Other WAI definition */ +#define WAPI_WAI_REQUEST 0x00F1 +#define WAPI_UNICAST_REKEY 0x00F2 +#define WAPI_STA_AGING 0x00F3 +#define WAPI_MUTIL_REKEY 0x00F4 +#define WAPI_STA_STATS 0x00F5 + +#define WAPI_USK_REKEY_COUNT 0x4000000 /* 0xA00000 */ +#define WAPI_MSK_REKEY_COUNT 0x4000000 /* 0xA00000 */ +#endif /* BCMWAPI_WAI */ /* This marks the end of a packed structure section. */ #include diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/linux_osl.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/linux_osl.c index ee07bd325532..54142a7db846 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/linux_osl.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/linux_osl.c @@ -48,6 +48,11 @@ #include #include #include +#include +#include +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 8, 0)) +#include +#endif #ifdef BCM_SECURE_DMA @@ -538,7 +543,7 @@ int osl_static_mem_init(osl_t *osh, void *adapter) #ifdef CONFIG_DHD_USE_STATIC_BUF if (!bcm_static_buf && adapter) { if (!(bcm_static_buf = (bcm_static_buf_t *)wifi_platform_prealloc(adapter, - 3, STATIC_BUF_SIZE + STATIC_BUF_TOTAL_LEN))) { + DHD_PREALLOC_OSL_BUF, STATIC_BUF_SIZE + STATIC_BUF_TOTAL_LEN))) { printk("can not alloc static buf!\n"); bcm_static_skb = NULL; ASSERT(osh->magic == OS_HANDLE_MAGIC); @@ -557,7 +562,7 @@ int osl_static_mem_init(osl_t *osh, void *adapter) int i; void *skb_buff_ptr = 0; bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048); - skb_buff_ptr = wifi_platform_prealloc(adapter, 4, 0); + skb_buff_ptr = wifi_platform_prealloc(adapter, DHD_PREALLOC_SKB_BUF, 0); if (!skb_buff_ptr) { printk("cannot alloc static buf!\n"); bcm_static_buf = NULL; @@ -1953,10 +1958,10 @@ osl_sleep(uint ms) uint64 osl_sysuptime_us(void) { - struct timeval tv; + struct osl_timespec tv; uint64 usec; - do_gettimeofday(&tv); + osl_do_gettimeofday(&tv); /* tv_usec content is fraction of a second */ usec = (uint64)tv.tv_sec * 1000000ul + tv.tv_usec; return usec; @@ -2693,6 +2698,15 @@ osl_pkt_orphan_partial(struct sk_buff *skb, int tsq) /* timer apis */ /* Note: All timer api's are thread unsafe and should be protected with locks by caller */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) +void +timer_cb_compat(struct timer_list *tl) +{ + timer_list_compat_t *t = container_of(tl, timer_list_compat_t, timer); + t->callback((ulong)t->arg); +} +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) */ + #ifdef REPORT_FATAL_TIMEOUTS osl_timer_t * osl_timer_init(osl_t *osh, const char *name, void (*fn)(void *arg), void *arg) @@ -2779,3 +2793,39 @@ osl_timer_del(osl_t *osh, osl_timer_t *t) return (TRUE); } #endif + +void +osl_do_gettimeofday(struct osl_timespec *ts) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) + struct timespec curtime; +#else + struct timeval curtime; +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) + getnstimeofday(&curtime); + ts->tv_nsec = curtime.tv_nsec; + ts->tv_usec = curtime.tv_nsec / 1000; +#else + do_gettimeofday(&curtime); + ts->tv_usec = curtime.tv_usec; + ts->tv_nsec = curtime.tv_usec * 1000; +#endif + ts->tv_sec = curtime.tv_sec; +} + +void +osl_get_monotonic_boottime(struct osl_timespec *ts) +{ + struct timespec curtime; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) + curtime = ktime_to_timespec(ktime_get_boottime()); +#else + get_monotonic_boottime(&curtime); +#endif + ts->tv_sec = curtime.tv_sec; + ts->tv_nsec = curtime.tv_nsec; + ts->tv_usec = curtime.tv_nsec / 1000; +} \ No newline at end of file diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android.c index bce45a7441fd..9c4bcb3ab21b 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android.c @@ -66,6 +66,9 @@ #if defined(STAT_REPORT) #include #endif /* STAT_REPORT */ +#ifdef WL_ESCAN +#include +#endif #ifndef WL_CFG80211 #define htod32(i) i @@ -76,7 +79,29 @@ #define dtohchanspec(i) i #endif -uint android_msg_level = ANDROID_ERROR_LEVEL; +uint android_msg_level = ANDROID_ERROR_LEVEL | ANDROID_MSG_LEVEL; + +#define ANDROID_ERROR_MSG(x, args...) \ + do { \ + if (android_msg_level & ANDROID_ERROR_LEVEL) { \ + printk(KERN_ERR "[dhd] ANDROID-ERROR) " x, ## args); \ + } \ + } while (0) +#define ANDROID_TRACE_MSG(x, args...) \ + do { \ + if (android_msg_level & ANDROID_TRACE_LEVEL) { \ + printk(KERN_INFO "[dhd] ANDROID-TRACE) " x, ## args); \ + } \ + } while (0) +#define ANDROID_INFO_MSG(x, args...) \ + do { \ + if (android_msg_level & ANDROID_INFO_LEVEL) { \ + printk(KERN_INFO "[dhd] ANDROID-INFO) " x, ## args); \ + } \ + } while (0) +#define ANDROID_ERROR(x) ANDROID_ERROR_MSG x +#define ANDROID_TRACE(x) ANDROID_TRACE_MSG x +#define ANDROID_INFO(x) ANDROID_INFO_MSG x /* * Android private command strings, PLEASE define new private commands here @@ -104,7 +129,7 @@ uint android_msg_level = ANDROID_ERROR_LEVEL; #define CMD_SETBAND "SETBAND" #define CMD_GETBAND "GETBAND" #define CMD_COUNTRY "COUNTRY" -#ifdef WLMESH +#ifdef WLMESH_CFG80211 #define CMD_SAE_SET_PASSWORD "SAE_SET_PASSWORD" #define CMD_SET_RSDB_MODE "RSDB_MODE" #endif @@ -126,6 +151,9 @@ uint android_msg_level = ANDROID_ERROR_LEVEL; #define CMD_ULB_MODE "ULB_MODE" #define CMD_ULB_BW "ULB_BW" #endif /* WL11ULB */ +#ifdef WLFBT +#define CMD_GET_FTKEY "GET_FTKEY" +#endif #if defined(WL_SUPPORT_AUTO_CHANNEL) #define CMD_GET_BEST_CHANNELS "GET_BEST_CHANNELS" @@ -1565,9 +1593,8 @@ int wl_android_wifi_on(struct net_device *dev) return -EINVAL; } - printf("%s in 1\n", __FUNCTION__); dhd_net_if_lock(dev); - printf("%s in 2: g_wifi_on=%d\n", __FUNCTION__, g_wifi_on); + WL_MSG(dev->name, "in g_wifi_on=%d\n", g_wifi_on); if (!g_wifi_on) { do { if (!dhd_net_wifi_platform_set_power(dev, TRUE, WIFI_TURNON_DELAY)) { @@ -1612,7 +1639,7 @@ int wl_android_wifi_on(struct net_device *dev) } exit: - printf("%s: Success\n", __FUNCTION__); + WL_MSG(dev->name, "Success\n"); dhd_net_if_unlock(dev); return ret; @@ -1623,7 +1650,7 @@ err: dhd_net_bus_suspend(dev); #endif /* BCMSDIO */ dhd_net_wifi_platform_set_power(dev, FALSE, WIFI_TURNOFF_DELAY); - printf("%s: Failed\n", __FUNCTION__); + WL_MSG(dev->name, "Failed\n"); dhd_net_if_unlock(dev); return ret; #endif /* BCMSDIO || BCMDBUS */ @@ -1638,7 +1665,6 @@ int wl_android_wifi_off(struct net_device *dev, bool on_failure) return -EINVAL; } - printf("%s in 1\n", __FUNCTION__); #if defined(BCMPCIE) && defined(DHD_DEBUG_UART) ret = dhd_debug_uart_is_running(dev); if (ret) { @@ -1647,7 +1673,7 @@ int wl_android_wifi_off(struct net_device *dev, bool on_failure) } #endif /* BCMPCIE && DHD_DEBUG_UART */ dhd_net_if_lock(dev); - printf("%s in 2: g_wifi_on=%d, on_failure=%d\n", __FUNCTION__, g_wifi_on, on_failure); + WL_MSG(dev->name, "in g_wifi_on=%d, on_failure=%d\n", g_wifi_on, on_failure); if (g_wifi_on || on_failure) { #if defined(BCMSDIO) || defined(BCMPCIE) || defined(BCMDBUS) ret = dhd_net_bus_devreset(dev, TRUE); @@ -1658,7 +1684,7 @@ int wl_android_wifi_off(struct net_device *dev, bool on_failure) dhd_net_wifi_platform_set_power(dev, FALSE, WIFI_TURNOFF_DELAY); g_wifi_on = FALSE; } - printf("%s out\n", __FUNCTION__); + WL_MSG(dev->name, "out\n"); dhd_net_if_unlock(dev); return ret; @@ -2024,7 +2050,7 @@ wl_android_natoe_subcmd_enable(struct net_device *dev, const wl_natoe_sub_cmd_t int ret = BCME_OK; wl_natoe_ioc_t *natoe_ioc; char *pcmd = command; - gfp_t kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; + uint16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ; uint16 buflen = WL_NATOE_IOC_BUFSZ; bcm_xtlv_t *pxtlv = NULL; @@ -2102,7 +2128,7 @@ wl_android_natoe_subcmd_config_ips(struct net_device *dev, wl_natoe_ioc_t *natoe_ioc; char *pcmd = command; char *str; - gfp_t kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; + uint16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ; uint16 buflen = WL_NATOE_IOC_BUFSZ; bcm_xtlv_t *pxtlv = NULL; @@ -2222,7 +2248,7 @@ wl_android_natoe_subcmd_config_ports(struct net_device *dev, wl_natoe_ioc_t *natoe_ioc; char *pcmd = command; char *str; - gfp_t kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; + uint16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ; uint16 buflen = WL_NATOE_IOC_BUFSZ; bcm_xtlv_t *pxtlv = NULL; @@ -2320,7 +2346,7 @@ wl_android_natoe_subcmd_dbg_stats(struct net_device *dev, const wl_natoe_sub_cmd int ret = BCME_OK; wl_natoe_ioc_t *natoe_ioc; char *pcmd = command; - gfp_t kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; + uint16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_DBG_STATS_BUFSZ; uint16 buflen = WL_NATOE_DBG_STATS_BUFSZ; bcm_xtlv_t *pxtlv = NULL; @@ -2396,7 +2422,7 @@ wl_android_natoe_subcmd_tbl_cnt(struct net_device *dev, const wl_natoe_sub_cmd_t int ret = BCME_OK; wl_natoe_ioc_t *natoe_ioc; char *pcmd = command; - gfp_t kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; + uint16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ; uint16 buflen = WL_NATOE_IOC_BUFSZ; bcm_xtlv_t *pxtlv = NULL; @@ -2481,6 +2507,74 @@ exit: #define APCS_MAX_RETRY 10 #define APCS_DEFAULT_2G_CH 1 #define APCS_DEFAULT_5G_CH 149 + +#ifdef WL_ESCAN +static int +wl_android_escan_autochannel(struct net_device *dev, uint32 band) +{ + struct dhd_pub *dhd = dhd_get_pub(dev); + wlc_ssid_t ssid; + struct wl_escan_info *escan = NULL; + int ret = 0, retry = 0, retry_max, retry_interval = 250, channel = 0, up = 1; +#ifdef WL_CFG80211 + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); +#endif + + escan = dhd->escan; + if (dhd) { + retry_max = WL_ESCAN_TIMER_INTERVAL_MS/retry_interval; + memset(&ssid, 0, sizeof(ssid)); + ret = wldev_ioctl_get(dev, WLC_GET_UP, &up, sizeof(s32)); + if (ret < 0 || up == 0) { + ret = wldev_ioctl_set(dev, WLC_UP, &up, sizeof(s32)); + } + retry = retry_max; + while (retry--) { +#ifdef WL_CFG80211 + if (wl_get_drv_status_all(cfg, SCANNING) || + escan->escan_state == ESCAN_STATE_SCANING) +#else + if (escan->escan_state == ESCAN_STATE_SCANING) +#endif + { + ANDROID_INFO(("Scanning %d tried, ret = %d\n", + (retry_max - retry), ret)); + } else { + escan->autochannel = 1; + ret = wl_escan_set_scan(dev, dhd, &ssid, 0, TRUE); + if (!ret) + break; + } + OSL_SLEEP(retry_interval); + } + if ((retry == 0) || (ret < 0)) + goto done; + retry = retry_max; + while (retry--) { + if (escan->escan_state == ESCAN_STATE_IDLE) { + if (band == WLC_BAND_5G) + channel = escan->best_5g_ch; + else + channel = escan->best_2g_ch; + WL_MSG(dev->name, "selected channel = %d\n", channel); + goto done; + } + ANDROID_INFO(("escan_state=%d, %d tried, ret = %d\n", + escan->escan_state, (retry_max - retry), ret)); + OSL_SLEEP(retry_interval); + } + if ((retry == 0) || (ret < 0)) + goto done; + } + +done: + if (escan) + escan->autochannel = 0; + + return channel; +} +#endif /* WL_ESCAN */ + static int wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str, char* command, int total_len) @@ -2491,18 +2585,16 @@ wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str, int ret = 0; int spect = 0; u8 *reqbuf = NULL; - uint32 band = WLC_BAND_2G; + uint32 band = WLC_BAND_2G, sta_band = WLC_BAND_2G; uint32 buf_size; - char *pos = command; - int band_new, band_cur = 0; if (cmd_str) { ANDROID_INFO(("Command: %s len:%d \n", cmd_str, (int)strlen(cmd_str))); - if (strncmp(cmd_str, APCS_BAND_AUTO, strlen(APCS_BAND_AUTO)) == 0) { + if (strnicmp(cmd_str, APCS_BAND_AUTO, strlen(APCS_BAND_AUTO)) == 0) { band = WLC_BAND_AUTO; - } else if (strncmp(cmd_str, APCS_BAND_5G, strlen(APCS_BAND_5G)) == 0) { + } else if (strnicmp(cmd_str, APCS_BAND_5G, strlen(APCS_BAND_5G)) == 0) { band = WLC_BAND_5G; - } else if (strncmp(cmd_str, APCS_BAND_2G, strlen(APCS_BAND_2G)) == 0) { + } else if (strnicmp(cmd_str, APCS_BAND_2G, strlen(APCS_BAND_2G)) == 0) { band = WLC_BAND_2G; } else { /* @@ -2514,22 +2606,55 @@ wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str, (channel == APCS_BAND_2G_LEGACY2)) { band = WLC_BAND_2G; } else { - ANDROID_ERROR(("%s: Invalid argument\n", __FUNCTION__)); + ANDROID_ERROR(("Invalid argument\n")); return -EINVAL; } } } else { /* If no argument is provided, default to 2G */ - ANDROID_ERROR(("%s: No argument given default to 2.4G scan\n", __FUNCTION__)); + ANDROID_ERROR(("No argument given default to 2.4G scan\n")); band = WLC_BAND_2G; } - ANDROID_INFO(("%s : HAPD_AUTO_CHANNEL = %d, band=%d \n", __FUNCTION__, channel, band)); + ANDROID_INFO(("HAPD_AUTO_CHANNEL = %d, band=%d \n", channel, band)); - ret = wldev_ioctl_set(dev, WLC_GET_BAND, &band_cur, sizeof(band_cur)); + /* If STA is connected, return is STA channel, else ACS can be issued, + * set spect to 0 and proceed with ACS + */ + channel = wl_cfg80211_get_sta_channel(dev); + if (channel) { + sta_band = WL_GET_BAND(channel); + switch (sta_band) { + case (WL_CHANSPEC_BAND_5G): { + if (band == WLC_BAND_2G || band == WLC_BAND_AUTO) { + channel = APCS_DEFAULT_2G_CH; + } + break; + } + case (WL_CHANSPEC_BAND_2G): { + if (band == WLC_BAND_5G) { + channel = APCS_DEFAULT_5G_CH; + } + break; + } + default: + /* Intentional fall through to use same sta channel for softap */ + break; + } + WL_MSG(dev->name, "band=%d, sta_band=%d, channel=%d\n", band, sta_band, channel); + goto done2; + } + +#ifdef WL_ESCAN + channel = wl_android_escan_autochannel(dev, band); + if (channel) + goto done2; + else + goto done; +#endif /* WL_ESCAN */ if ((ret = wldev_ioctl_get(dev, WLC_GET_SPECT_MANAGMENT, &spect, sizeof(spect))) < 0) { - ANDROID_ERROR(("%s: ACS: error getting the spect\n", __FUNCTION__)); + ANDROID_ERROR(("ACS: error getting the spect\n")); goto done; } @@ -2551,19 +2676,15 @@ wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str, reqbuf = kzalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL); if (reqbuf == NULL) { - ANDROID_ERROR(("%s: failed to allocate chanspec buffer\n", __FUNCTION__)); + ANDROID_ERROR(("failed to allocate chanspec buffer\n")); return -ENOMEM; } if (band == WLC_BAND_AUTO) { - ANDROID_INFO(("%s: ACS full channel scan \n", __func__)); + ANDROID_INFO(("ACS full channel scan \n")); reqbuf[0] = htod32(0); } else if (band == WLC_BAND_5G) { - band_new = band_cur==WLC_BAND_2G ? band_cur : WLC_BAND_5G; - ret = wldev_ioctl_set(dev, WLC_SET_BAND, &band_new, sizeof(band_new)); - if (ret < 0) - WL_ERR(("WLC_SET_BAND error %d\n", ret)); - ANDROID_INFO(("%s: ACS 5G band scan \n", __func__)); + ANDROID_INFO(("ACS 5G band scan \n")); if ((ret = wl_cfg80211_get_chanspecs_5g(dev, reqbuf, CHANSPEC_BUF_SIZE)) < 0) { ANDROID_ERROR(("ACS 5g chanspec retreival failed! \n")); goto done; @@ -2573,7 +2694,7 @@ wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str, * If channel argument is not provided/ argument 20 is provided, * Restrict channel to 2GHz, 20MHz BW, No SB */ - ANDROID_INFO(("%s: ACS 2G band scan \n", __func__)); + ANDROID_INFO(("ACS 2G band scan \n")); if ((ret = wl_cfg80211_get_chanspecs_2g(dev, reqbuf, CHANSPEC_BUF_SIZE)) < 0) { ANDROID_ERROR(("ACS 2g chanspec retreival failed! \n")); goto done; @@ -2583,12 +2704,11 @@ wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str, goto done2; } - buf_size = CHANSPEC_BUF_SIZE; + buf_size = (band == WLC_BAND_AUTO) ? sizeof(int) : CHANSPEC_BUF_SIZE; ret = wldev_ioctl_set(dev, WLC_START_CHANNEL_SEL, (void *)reqbuf, buf_size); if (ret < 0) { - ANDROID_ERROR(("%s: can't start auto channel scan, err = %d\n", - __FUNCTION__, ret)); + ANDROID_ERROR(("can't start auto channel scan, err = %d\n", ret)); channel = 0; goto done; } @@ -2614,18 +2734,6 @@ wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str, chosen = dtoh32(chosen); } - if ((ret == 0) && (dtoh32(chosen) != 0)) { - uint chip; - chip = dhd_conf_get_chip(dhd_get_pub(dev)); - if (chip != BCM43143_CHIP_ID) { - u32 chanspec = 0; - chanspec = wl_chspec_driver_to_host(chosen); - ANDROID_INFO(("%s: selected chanspec = 0x%x\n", __FUNCTION__, chanspec)); - chosen = wf_chspec_ctlchan(chanspec); - ANDROID_INFO(("%s: selected chosen = 0x%x\n", __FUNCTION__, chosen)); - } - } - if (chosen) { int chosen_band; int apcs_band; @@ -2640,15 +2748,12 @@ wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str, #endif /* D11AC_IOTYPES */ apcs_band = (band == WLC_BAND_AUTO) ? WLC_BAND_2G : band; chosen_band = (channel <= CH_MAX_2G_CHANNEL) ? WLC_BAND_2G : WLC_BAND_5G; - if (band == WLC_BAND_AUTO) { - printf("%s: selected channel = %d\n", __FUNCTION__, channel); - break; - } else if (apcs_band == chosen_band) { - printf("%s: selected channel = %d\n", __FUNCTION__, channel); + if (apcs_band == chosen_band) { + WL_MSG(dev->name, "selected channel = %d\n", channel); break; } } - ANDROID_INFO(("%s: %d tried, ret = %d, chosen = 0x%x\n", __FUNCTION__, + ANDROID_INFO(("%d tried, ret = %d, chosen = 0x%x\n", (APCS_MAX_RETRY - retry), ret, chosen)); OSL_SLEEP(250); } @@ -2661,16 +2766,12 @@ done: } else { channel = APCS_DEFAULT_2G_CH; } - ANDROID_ERROR(("%s: ACS failed." - " Fall back to default channel (%d) \n", __FUNCTION__, channel)); + ANDROID_ERROR(("ACS failed. Fall back to default channel (%d) \n", channel)); } done2: - ret = wldev_ioctl_set(dev, WLC_SET_BAND, &band_cur, sizeof(band_cur)); - if (ret < 0) - WL_ERR(("WLC_SET_BAND error %d\n", ret)); if (spect > 0) { if ((ret = wl_cfg80211_set_spect(dev, spect) < 0)) { - ANDROID_ERROR(("%s: ACS: error while setting spect\n", __FUNCTION__)); + ANDROID_ERROR(("ACS: error while setting spect\n")); } } @@ -2679,12 +2780,8 @@ done2: } if (channel) { - if (channel < 15) - pos += snprintf(pos, total_len, "2g="); - else - pos += snprintf(pos, total_len, "5g="); - pos += snprintf(pos, total_len, "%d", channel); - ANDROID_INFO(("%s: command result is %s \n", __FUNCTION__, command)); + snprintf(command, 4, "%d", channel); + ANDROID_INFO(("command result is %s \n", command)); return strlen(command); } else { return ret; @@ -3322,6 +3419,7 @@ wl_android_set_ulb_bw(struct net_device *dev, char *command, int total_len) return wl_cfg80211_set_ulb_bw(dev, bw, ifname); } #endif /* WL11ULB */ + static int wl_android_set_miracast(struct net_device *dev, char *command, int total_len) { @@ -3423,6 +3521,7 @@ resume: } #endif +#ifdef WL_RELMCAST #define NETLINK_OXYGEN 30 #define AIBSS_BEACON_TIMEOUT 10 @@ -3508,7 +3607,7 @@ wl_netlink_send_msg(int pid, int type, int seq, const void *data, size_t size) nlmsg_failure: return ret; } - +#endif /* WL_RELMCAST */ int wl_keep_alive_set(struct net_device *dev, char* extra, int total_len) { @@ -4226,7 +4325,7 @@ wl_android_make_hang_with_reason(struct net_device *dev, const char *string_num) #endif /* DHD_HANG_SEND_UP_TEST */ #ifdef WL_CFG80211 -#ifdef WLMESH +#ifdef WLMESH_CFG80211 static int wl_android_set_rsdb_mode(struct net_device *dev, char *command, int total_len) { @@ -4746,8 +4845,8 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) command[0] = '\0'; } if (bytes_written >= priv_cmd.total_len) { - ANDROID_ERROR(("%s: err. bytes_written:%d >= buf_size:%d \n", - __FUNCTION__, bytes_written, buf_size)); + ANDROID_ERROR(("%s: err. bytes_written:%d >= total_len:%d, buf_size:%d\n", + __FUNCTION__, bytes_written, priv_cmd.total_len, buf_size)); ret = BCME_BUFTOOSHORT; goto exit; } @@ -4957,7 +5056,7 @@ wl_handle_private_cmd(struct net_device *net, char *command, u32 cmd_len) bytes_written = wl_android_get_p2p_dev_addr(net, command, priv_cmd.total_len); } #ifdef WL_CFG80211 -#ifdef WLMESH +#ifdef WLMESH_CFG80211 else if (strnicmp(command, CMD_SAE_SET_PASSWORD, strlen(CMD_SAE_SET_PASSWORD)) == 0) { int skip = strlen(CMD_SAE_SET_PASSWORD) + 1; bytes_written = wl_cfg80211_set_sae_password(net, command + skip, @@ -5007,6 +5106,11 @@ wl_handle_private_cmd(struct net_device *net, char *command, u32 cmd_len) bytes_written = wl_cfg80211_set_wps_p2p_ie(net, command + skip, priv_cmd.total_len - skip, *(command + skip - 2) - '0'); } +#ifdef WLFBT + else if (strnicmp(command, CMD_GET_FTKEY, strlen(CMD_GET_FTKEY)) == 0) { + bytes_written = wl_cfg80211_get_fbt_key(net, command, priv_cmd.total_len); + } +#endif /* WLFBT */ #endif /* WL_CFG80211 */ #if defined(WL_SUPPORT_AUTO_CHANNEL) else if (strnicmp(command, CMD_GET_BEST_CHANNELS, @@ -5409,7 +5513,7 @@ int wl_android_init(void) { int ret = 0; -#ifdef ENABLE_INSMOD_NO_FW_LOAD +#if defined(ENABLE_INSMOD_NO_FW_LOAD) || defined(BUS_POWER_RESTORE) dhd_download_fw_on_driverload = FALSE; #endif /* ENABLE_INSMOD_NO_FW_LOAD */ if (!iface_name[0]) { @@ -5417,7 +5521,9 @@ int wl_android_init(void) bcm_strncpy_s(iface_name, IFNAMSIZ, "wlan", IFNAMSIZ); } +#ifdef WL_RELMCAST wl_netlink_init(); +#endif /* WL_RELMCAST */ return ret; } @@ -5427,7 +5533,9 @@ int wl_android_exit(void) int ret = 0; struct io_cfg *cur, *q; +#ifdef WL_RELMCAST wl_netlink_deinit(); +#endif #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android.h index 710380e4af92..55afc81500d1 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android.h @@ -66,37 +66,17 @@ typedef struct _compat_android_wifi_priv_cmd { */ /* message levels */ -#define ANDROID_ERROR_LEVEL 0x0001 -#define ANDROID_TRACE_LEVEL 0x0002 -#define ANDROID_INFO_LEVEL 0x0004 -#define ANDROID_EVENT_LEVEL 0x0008 +#define ANDROID_ERROR_LEVEL (1 << 0) +#define ANDROID_TRACE_LEVEL (1 << 1) +#define ANDROID_INFO_LEVEL (1 << 2) +#define ANDROID_SCAN_LEVEL (1 << 3) +#define ANDROID_DBG_LEVEL (1 << 4) +#define ANDROID_MSG_LEVEL (1 << 0) -#define ANDROID_ERROR(x) \ +#define WL_MSG(name, arg1, args...) \ do { \ - if (android_msg_level & ANDROID_ERROR_LEVEL) { \ - printk(KERN_ERR "ANDROID-ERROR) "); \ - printk x; \ - } \ - } while (0) -#define ANDROID_TRACE(x) \ - do { \ - if (android_msg_level & ANDROID_TRACE_LEVEL) { \ - printk(KERN_ERR "ANDROID-TRACE) "); \ - printk x; \ - } \ - } while (0) -#define ANDROID_INFO(x) \ - do { \ - if (android_msg_level & ANDROID_INFO_LEVEL) { \ - printk(KERN_ERR "ANDROID-INFO) "); \ - printk x; \ - } \ - } while (0) -#define ANDROID_EVENT(x) \ - do { \ - if (android_msg_level & ANDROID_EVENT_LEVEL) { \ - printk(KERN_ERR "ANDROID-EVENT) "); \ - printk x; \ + if (android_msg_level & ANDROID_MSG_LEVEL) { \ + printk(KERN_ERR "[dhd-%s] %s : " arg1, name, __func__, ## args); \ } \ } while (0) @@ -117,23 +97,69 @@ s32 wl_netlink_send_msg(int pid, int type, int seq, const void *data, size_t siz int wl_ext_iapsta_attach_netdev(struct net_device *net, int ifidx, uint8 bssidx); int wl_ext_iapsta_attach_name(struct net_device *net, int ifidx); int wl_ext_iapsta_dettach_netdev(struct net_device *net, int ifidx); -u32 wl_ext_iapsta_update_channel(struct net_device *dev, u32 channel); +u32 wl_ext_iapsta_update_channel(dhd_pub_t *dhd, struct net_device *dev, u32 channel); int wl_ext_iapsta_alive_preinit(struct net_device *dev); int wl_ext_iapsta_alive_postinit(struct net_device *dev); -int wl_ext_iapsta_event(struct net_device *dev, wl_event_msg_t *e, void* data); int wl_ext_iapsta_attach(dhd_pub_t *pub); void wl_ext_iapsta_dettach(dhd_pub_t *pub); +bool wl_ext_check_mesh_creating(struct net_device *net); +#ifdef WL_CFG80211 +void wl_ext_iapsta_update_iftype(struct net_device *net, int ifidx, int wl_iftype); +#endif extern int op_mode; #endif +typedef struct bcol_gtk_para { + int enable; + int ptk_len; + char ptk[64]; + char replay[8]; +} bcol_gtk_para_t; +#if defined(WL_EXT_IAPSTA) || defined(USE_IW) +typedef enum WL_EVENT_PRIO { + PRIO_EVENT_IAPSTA, + PRIO_EVENT_ESCAN, + PRIO_EVENT_WEXT +}wl_event_prio_t; +s32 wl_ext_event_attach(struct net_device *dev, dhd_pub_t *dhdp); +void wl_ext_event_dettach(dhd_pub_t *dhdp); +int wl_ext_event_attach_netdev(struct net_device *net, int ifidx, uint8 bssidx); +int wl_ext_event_dettach_netdev(struct net_device *net, int ifidx); +int wl_ext_event_register(struct net_device *dev, dhd_pub_t *dhd, + uint32 event, void *cb_func, void *data, wl_event_prio_t prio); +void wl_ext_event_deregister(struct net_device *dev, dhd_pub_t *dhd, + uint32 event, void *cb_func); +void wl_ext_event_send(void *params, const wl_event_msg_t * e, void *data); +#endif int wl_android_ext_priv_cmd(struct net_device *net, char *command, int total_len, int *bytes_written); +void wl_ext_get_sec(struct net_device *dev, int ifmode, char *sec, int total_len); +bool wl_ext_check_scan(struct net_device *dev, dhd_pub_t *dhdp); +#if defined(WL_CFG80211) || defined(WL_ESCAN) +void wl_ext_user_sync(struct dhd_pub *dhd, int ifidx, bool lock); +bool wl_ext_event_complete(struct dhd_pub *dhd, int ifidx); +#endif +enum wl_ext_status { + WL_EXT_STATUS_DISCONNECTING = 0, + WL_EXT_STATUS_DISCONNECTED, + WL_EXT_STATUS_SCAN, + WL_EXT_STATUS_CONNECTING, + WL_EXT_STATUS_CONNECTED, + WL_EXT_STATUS_ADD_KEY, + WL_EXT_STATUS_AP_ENABLED, + WL_EXT_STATUS_DELETE_STA, + WL_EXT_STATUS_STA_DISCONNECTED, + WL_EXT_STATUS_STA_CONNECTED, + WL_EXT_STATUS_AP_DISABLED +}; typedef struct wl_conn_info { uint8 bssidx; wlc_ssid_t ssid; struct ether_addr bssid; uint16 channel; } wl_conn_info_t; +#if defined(WL_WIRELESS_EXT) s32 wl_ext_connect(struct net_device *dev, wl_conn_info_t *conn_info); +#endif /* defined(WL_WIRELESS_EXT) */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) #define strnicmp(str1, str2, len) strncasecmp((str1), (str2), (len)) #endif @@ -154,6 +180,8 @@ s32 wl_ext_connect(struct net_device *dev, wl_conn_info_t *conn_info); * restrict max number to 10 as maximum cmd string size is 255 */ #define MAX_NUM_MAC_FILT 10 +#define WL_GET_BAND(ch) (((uint)(ch) <= CH_MAX_2G_CHANNEL) ? \ + WLC_BAND_2G : WLC_BAND_5G) int wl_android_set_ap_mac_list(struct net_device *dev, int macmode, struct maclist *maclist); @@ -189,7 +217,7 @@ extern int g_wifi_on; typedef struct wl_rssi_cache { struct wl_rssi_cache *next; int dirty; - struct timeval tv; + struct osl_timespec tv; struct ether_addr BSSID; int16 RSSI[RSSIAVG_LEN]; } wl_rssi_cache_t; @@ -225,7 +253,7 @@ int wl_update_rssi_offset(struct net_device *net, int rssi); typedef struct wl_bss_cache { struct wl_bss_cache *next; int dirty; - struct timeval tv; + struct osl_timespec tv; wl_scan_results_t results; } wl_bss_cache_t; diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android_ext.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android_ext.c index 1049663326bc..d84eab9e3f7d 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android_ext.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_android_ext.c @@ -16,7 +16,7 @@ #include #if defined(WL_WIRELESS_EXT) #include -#endif +#endif /* WL_WIRELESS_EXT */ #include #include #include @@ -27,10 +27,35 @@ #include #ifdef WL_CFG80211 #include -#endif +#endif /* WL_CFG80211 */ #ifdef WL_ESCAN #include -#endif +#endif /* WL_ESCAN */ + +#define AEXT_ERROR(name, arg1, args...) \ + do { \ + if (android_msg_level & ANDROID_ERROR_LEVEL) { \ + printk(KERN_ERR "[dhd-%s] AEXT-ERROR) %s : " arg1, name, __func__, ## args); \ + } \ + } while (0) +#define AEXT_TRACE(name, arg1, args...) \ + do { \ + if (android_msg_level & ANDROID_TRACE_LEVEL) { \ + printk(KERN_ERR "[dhd-%s] AEXT-TRACE) %s : " arg1, name, __func__, ## args); \ + } \ + } while (0) +#define AEXT_INFO(name, arg1, args...) \ + do { \ + if (android_msg_level & ANDROID_INFO_LEVEL) { \ + printk(KERN_ERR "[dhd-%s] AEXT-INFO) %s : " arg1, name, __func__, ## args); \ + } \ + } while (0) +#define AEXT_DBG(name, arg1, args...) \ + do { \ + if (android_msg_level & ANDROID_DBG_LEVEL) { \ + printk(KERN_ERR "[dhd-%s] AEXT-DBG) %s : " arg1, name, __func__, ## args); \ + } \ + } while (0) #ifndef WL_CFG80211 #define htod32(i) i @@ -44,7 +69,7 @@ #define WL_SCAN_JOIN_PROBE_INTERVAL_MS 20 #define WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS 320 #define WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS 400 -#endif +#endif /* WL_CFG80211 */ #define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) #ifndef IW_CUSTOM_MAX @@ -54,7 +79,6 @@ #define CMD_CHANNEL "CHANNEL" #define CMD_CHANNELS "CHANNELS" #define CMD_ROAM_TRIGGER "ROAM_TRIGGER" -#define CMD_KEEP_ALIVE "KEEP_ALIVE" #define CMD_PM "PM" #define CMD_MONITOR "MONITOR" #define CMD_SET_SUSPEND_BCN_LI_DTIM "SET_SUSPEND_BCN_LI_DTIM" @@ -75,104 +99,25 @@ #include extern int disable_proptx; #endif /* PROP_TXSTATUS_VSDB */ -#endif -#endif -#ifdef IDHCP -#define CMD_DHCPC_ENABLE "DHCPC_ENABLE" -#define CMD_DHCPC_DUMP "DHCPC_DUMP" -#endif +#endif /* PROP_TXSTATUS */ +#endif /* WL_EXT_IAPSTA */ #define CMD_AUTOCHANNEL "AUTOCHANNEL" #define CMD_WL "WL" -int wl_ext_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set) -{ - int ret; - - ret = wldev_ioctl(dev, cmd, arg, len, set); - if (ret) - ANDROID_ERROR(("%s: cmd=%d ret=%d\n", __FUNCTION__, cmd, ret)); - return ret; -} - -int wl_ext_iovar_getint(struct net_device *dev, s8 *iovar, s32 *val) -{ - int ret; - - ret = wldev_iovar_getint(dev, iovar, val); - if (ret) - ANDROID_ERROR(("%s: iovar=%s, ret=%d\n", __FUNCTION__, iovar, ret)); - - return ret; -} - -int wl_ext_iovar_setint(struct net_device *dev, s8 *iovar, s32 val) -{ - int ret; - - ret = wldev_iovar_setint(dev, iovar, val); - if (ret) - ANDROID_ERROR(("%s: iovar=%s, ret=%d\n", __FUNCTION__, iovar, ret)); - - return ret; -} - -int wl_ext_iovar_getbuf(struct net_device *dev, s8 *iovar_name, - void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync) -{ - int ret; - - ret = wldev_iovar_getbuf(dev, iovar_name, param, paramlen, buf, buflen, buf_sync); - if (ret != 0) - ANDROID_ERROR(("%s: iovar=%s, ret=%d\n", __FUNCTION__, iovar_name, ret)); - - return ret; -} - -int wl_ext_iovar_setbuf(struct net_device *dev, s8 *iovar_name, - void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync) -{ - int ret; - - ret = wldev_iovar_setbuf(dev, iovar_name, param, paramlen, buf, buflen, buf_sync); - if (ret != 0) - ANDROID_ERROR(("%s: iovar=%s, ret=%d\n", __FUNCTION__, iovar_name, ret)); - - return ret; -} - -static int wl_ext_iovar_setbuf_bsscfg(struct net_device *dev, s8 *iovar_name, - void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, - struct mutex* buf_sync) -{ - int ret; - - ret = wldev_iovar_setbuf_bsscfg(dev, iovar_name, param, paramlen, - buf, buflen, bsscfg_idx, buf_sync); - if (ret < 0) - ANDROID_ERROR(("%s: iovar_name=%s ret=%d\n", __FUNCTION__, iovar_name, ret)); - - return ret; -} - #ifdef WL_EXT_IAPSTA -typedef enum IF_STATE { - IF_STATE_INIT = 1, - IF_STATE_DISALBE, - IF_STATE_ENABLE -} if_state_t; - typedef enum APSTAMODE { ISTAONLY_MODE = 1, - IAPONLY_MODE, - IAPSTA_MODE, - IDUALAP_MODE, - ISTAAPAP_MODE, - IMESHONLY_MODE, - IMESHSTA_MODE, - IMESHAP_MODE, - IMESHAPSTA_MODE, - IMESHAPAP_MODE, - IGOSTA_MODE + IAPONLY_MODE = 2, + ISTAAP_MODE = 3, + ISTAGO_MODE = 4, + ISTASTA_MODE = 5, + IDUALAP_MODE = 6, + ISTAAPAP_MODE = 7, + IMESHONLY_MODE = 8, + ISTAMESH_MODE = 9, + IMESHAP_MODE = 10, + ISTAAPMESH_MODE = 11, + IMESHAPAP_MODE = 12 } apstamode_t; typedef enum IFMODE { @@ -217,12 +162,12 @@ typedef enum WL_PRIO { PRIO_AP, PRIO_MESH, PRIO_STA -}wl_prio_t; +} wl_prio_t; typedef struct wl_if_info { struct net_device *dev; - if_state_t ifstate; ifmode_t ifmode; + unsigned long status; char prefix; wl_prio_t prio; int ifidx; @@ -237,6 +182,10 @@ typedef struct wl_if_info { authmode_t amode; encmode_t emode; char key[100]; +#if defined(WLMESH) && defined(WL_ESCAN) + struct wl_escan_info *escan; + timer_list_compat_t delay_scan; +#endif /* WLMESH && WL_ESCAN */ } wl_if_info_t; #define CSA_FW_BIT (1<<0) @@ -247,28 +196,178 @@ typedef struct wl_apsta_params { struct dhd_pub *dhd; int ioctl_ver; bool init; - bool rsdb; + int rsdb; bool vsdb; uint csa; apstamode_t apstamode; - bool netif_change; wait_queue_head_t netif_change_event; + struct mutex usr_sync; +#if defined(WLMESH) && defined(WL_ESCAN) + int macs; + struct wl_mesh_params mesh_info; +#endif /* WLMESH && WL_ESCAN */ } wl_apsta_params_t; -static int wl_ext_enable_iface(struct net_device *dev, char *ifname); -#endif +#define MAX_AP_LINK_WAIT_TIME 3000 +#define MAX_STA_LINK_WAIT_TIME 15000 +enum wifi_isam_status { + ISAM_STATUS_IF_ADDING = 0, + ISAM_STATUS_IF_READY, + ISAM_STATUS_STA_CONNECTING, + ISAM_STATUS_STA_CONNECTED, + ISAM_STATUS_AP_CREATING, + ISAM_STATUS_AP_CREATED +}; + +#define wl_get_isam_status(cur_if, stat) \ + (test_bit(ISAM_STATUS_ ## stat, &(cur_if)->status)) +#define wl_set_isam_status(cur_if, stat) \ + (set_bit(ISAM_STATUS_ ## stat, &(cur_if)->status)) +#define wl_clr_isam_status(cur_if, stat) \ + (clear_bit(ISAM_STATUS_ ## stat, &(cur_if)->status)) +#define wl_chg_isam_status(cur_if, stat) \ + (change_bit(ISAM_STATUS_ ## stat, &(cur_if)->status)) + +static int wl_ext_enable_iface(struct net_device *dev, char *ifname, int wait_up); +static int wl_ext_disable_iface(struct net_device *dev, char *ifname); +#if defined(WLMESH) && defined(WL_ESCAN) +static int wl_mesh_escan_attach(dhd_pub_t *dhd, struct wl_if_info *cur_if); +#endif /* WLMESH && WL_ESCAN */ +#endif /* WL_EXT_IAPSTA */ + +#ifdef IDHCP +typedef struct dhcpc_parameter { + uint32 ip_addr; + uint32 ip_serv; + uint32 lease_time; +} dhcpc_para_t; +#endif /* IDHCP */ + +#ifdef WL_EXT_WOWL +#define WL_WOWL_TCPFIN (1 << 26) +typedef struct wl_wowl_pattern2 { + char cmd[4]; + wl_wowl_pattern_t wowl_pattern; +} wl_wowl_pattern2_t; +#endif /* WL_EXT_WOWL */ + +#ifdef WL_EXT_TCPKA +typedef struct tcpka_conn { + uint32 sess_id; + struct ether_addr dst_mac; /* Destinition Mac */ + struct ipv4_addr src_ip; /* Sorce IP */ + struct ipv4_addr dst_ip; /* Destinition IP */ + uint16 ipid; /* Ip Identification */ + uint16 srcport; /* Source Port Address */ + uint16 dstport; /* Destination Port Address */ + uint32 seq; /* TCP Sequence Number */ + uint32 ack; /* TCP Ack Number */ + uint16 tcpwin; /* TCP window */ + uint32 tsval; /* Timestamp Value */ + uint32 tsecr; /* Timestamp Echo Reply */ + uint32 len; /* last packet payload len */ + uint32 ka_payload_len; /* keep alive payload length */ + uint8 ka_payload[1]; /* keep alive payload */ +} tcpka_conn_t; + +typedef struct tcpka_conn_sess { + uint32 sess_id; /* session id */ + uint32 flag; /* enable/disable flag */ + wl_mtcpkeep_alive_timers_pkt_t tcpka_timers; +} tcpka_conn_sess_t; + +typedef struct tcpka_conn_info { + uint32 ipid; + uint32 seq; + uint32 ack; +} tcpka_conn_sess_info_t; +#endif /* WL_EXT_TCPKA */ + +static int wl_ext_wl_iovar(struct net_device *dev, char *command, int total_len); + +static int +wl_ext_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set) +{ + int ret; + + ret = wldev_ioctl(dev, cmd, arg, len, set); + if (ret) + AEXT_ERROR(dev->name, "cmd=%d, ret=%d\n", cmd, ret); + return ret; +} + +static int +wl_ext_iovar_getint(struct net_device *dev, s8 *iovar, s32 *val) +{ + int ret; + + ret = wldev_iovar_getint(dev, iovar, val); + if (ret) + AEXT_ERROR(dev->name, "iovar=%s, ret=%d\n", iovar, ret); + + return ret; +} + +static int +wl_ext_iovar_setint(struct net_device *dev, s8 *iovar, s32 val) +{ + int ret; + + ret = wldev_iovar_setint(dev, iovar, val); + if (ret) + AEXT_ERROR(dev->name, "iovar=%s, ret=%d\n", iovar, ret); + + return ret; +} + +static int +wl_ext_iovar_getbuf(struct net_device *dev, s8 *iovar_name, + void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync) +{ + int ret; + + ret = wldev_iovar_getbuf(dev, iovar_name, param, paramlen, buf, buflen, buf_sync); + if (ret != 0) + AEXT_ERROR(dev->name, "iovar=%s, ret=%d\n", iovar_name, ret); + + return ret; +} + +static int +wl_ext_iovar_setbuf(struct net_device *dev, s8 *iovar_name, + void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync) +{ + int ret; + + ret = wldev_iovar_setbuf(dev, iovar_name, param, paramlen, buf, buflen, buf_sync); + if (ret != 0) + AEXT_ERROR(dev->name, "iovar=%s, ret=%d\n", iovar_name, ret); + + return ret; +} + +static int +wl_ext_iovar_setbuf_bsscfg(struct net_device *dev, s8 *iovar_name, + void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, + struct mutex* buf_sync) +{ + int ret; + + ret = wldev_iovar_setbuf_bsscfg(dev, iovar_name, param, paramlen, + buf, buflen, bsscfg_idx, buf_sync); + if (ret < 0) + AEXT_ERROR(dev->name, "iovar=%s, ret=%d\n", iovar_name, ret); + + return ret; +} -/* Return a legacy chanspec given a new chanspec - * Returns INVCHANSPEC on error - */ static chanspec_t wl_ext_chspec_to_legacy(chanspec_t chspec) { chanspec_t lchspec; if (wf_chspec_malformed(chspec)) { - ANDROID_ERROR(("wl_ext_chspec_to_legacy: input chanspec (0x%04X) malformed\n", - chspec)); + AEXT_ERROR("wlan", "input chanspec (0x%04X) malformed\n", chspec); return INVCHANSPEC; } @@ -296,20 +395,15 @@ wl_ext_chspec_to_legacy(chanspec_t chspec) } else { /* cannot express the bandwidth */ char chanbuf[CHANSPEC_STR_LEN]; - ANDROID_ERROR(( - "wl_ext_chspec_to_legacy: unable to convert chanspec %s (0x%04X) " - "to pre-11ac format\n", - wf_chspec_ntoa(chspec, chanbuf), chspec)); + AEXT_ERROR("wlan", "unable to convert chanspec %s (0x%04X) " + "to pre-11ac format\n", + wf_chspec_ntoa(chspec, chanbuf), chspec); return INVCHANSPEC; } return lchspec; } -/* given a chanspec value, do the endian and chanspec version conversion to - * a chanspec_t value - * Returns INVCHANSPEC on error - */ static chanspec_t wl_ext_chspec_host_to_driver(int ioctl_ver, chanspec_t chanspec) { @@ -353,9 +447,6 @@ wl_ext_ch_to_chanspec(int ioctl_ver, int ch, join_params->params.chanspec_num = htod32(join_params->params.chanspec_num); - ANDROID_TRACE(("join_params->params.chanspec_list[0]= %X, %d channels\n", - join_params->params.chanspec_list[0], - join_params->params.chanspec_num)); } } @@ -388,8 +479,7 @@ wl_ext_chspec_from_legacy(chanspec_t legacy_chspec) } if (wf_chspec_malformed(chspec)) { - ANDROID_ERROR(("wl_ext_chspec_from_legacy: output chanspec (0x%04X) malformed\n", - chspec)); + AEXT_ERROR("wlan", "output chanspec (0x%04X) malformed\n", chspec); return INVCHANSPEC; } @@ -406,7 +496,107 @@ wl_ext_chspec_driver_to_host(int ioctl_ver, chanspec_t chanspec) return chanspec; } +#endif /* WL_EXT_IAPSTA || WL_CFG80211 || WL_ESCAN */ + +bool +wl_ext_check_scan(struct net_device *dev, dhd_pub_t *dhdp) +{ +#ifdef WL_CFG80211 + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); +#endif /* WL_CFG80211 */ +#ifdef WL_ESCAN + struct wl_escan_info *escan = dhdp->escan; +#endif /* WL_ESCAN */ + +#ifdef WL_CFG80211 + if (wl_get_drv_status_all(cfg, SCANNING)) { + AEXT_ERROR(dev->name, "cfg80211 scanning...\n"); + return TRUE; + } +#endif /* WL_CFG80211 */ + +#ifdef WL_ESCAN + if (escan->escan_state == ESCAN_STATE_SCANING) { + AEXT_ERROR(dev->name, "escan scanning...\n"); + return TRUE; + } +#endif /* WL_ESCAN */ + + return FALSE; +} + +#if defined(WL_CFG80211) || defined(WL_ESCAN) +void +wl_ext_user_sync(struct dhd_pub *dhd, int ifidx, bool lock) +{ + struct net_device *dev = dhd_idx2net(dhd, ifidx); +#ifdef WL_CFG80211 + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); +#endif /* WL_CFG80211 */ +#ifdef WL_ESCAN + struct wl_escan_info *escan = dhd->escan; +#endif /* WL_ESCAN */ + + AEXT_INFO(dev->name, "lock=%d\n", lock); + + if (lock) { +#if defined(WL_CFG80211) + mutex_lock(&cfg->usr_sync); #endif +#if defined(WL_ESCAN) + mutex_lock(&escan->usr_sync); +#endif + } else { +#if defined(WL_CFG80211) + mutex_unlock(&cfg->usr_sync); +#endif +#if defined(WL_ESCAN) + mutex_unlock(&escan->usr_sync); +#endif + } +} + +bool +wl_ext_event_complete(struct dhd_pub *dhd, int ifidx) +{ + struct net_device *dev = dhd_idx2net(dhd, ifidx); +#ifdef WL_CFG80211 + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); +#endif /* WL_CFG80211 */ +#ifdef WL_ESCAN + struct wl_escan_info *escan = dhd->escan; +#endif /* WL_ESCAN */ + bool complete = TRUE; + +#ifdef WL_CFG80211 + if (wl_get_drv_status_all(cfg, SCANNING)) { + AEXT_INFO(dev->name, "SCANNING\n"); + complete = FALSE; + } + if (wl_get_drv_status_all(cfg, CONNECTING)) { + AEXT_INFO(dev->name, "CONNECTING\n"); + complete = FALSE; + } + if (wl_get_drv_status_all(cfg, DISCONNECTING)) { + AEXT_INFO(dev->name, "DISCONNECTING\n"); + complete = FALSE; + } +#endif /* WL_CFG80211 */ +#ifdef WL_ESCAN + if (escan->escan_state == ESCAN_STATE_SCANING) { + AEXT_INFO(dev->name, "ESCAN_STATE_SCANING\n"); + complete = FALSE; + } +#endif /* WL_ESCAN */ + if (dhd->conf->eapol_status >= EAPOL_STATUS_4WAY_START && + dhd->conf->eapol_status < EAPOL_STATUS_4WAY_DONE) { + AEXT_INFO(dev->name, "4-WAY handshaking\n"); + complete = FALSE; + } + + return complete; +} +#endif /* WL_CFG80211 && WL_ESCAN */ static int wl_ext_get_ioctl_ver(struct net_device *dev, int *ioctl_ver) @@ -421,8 +611,8 @@ wl_ext_get_ioctl_ver(struct net_device *dev, int *ioctl_ver) } val = dtoh32(val); if (val != WLC_IOCTL_VERSION && val != 1) { - ANDROID_ERROR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n", - val, WLC_IOCTL_VERSION)); + AEXT_ERROR(dev->name, "Version mismatch, please upgrade. Got %d, expected %d or 1\n", + val, WLC_IOCTL_VERSION); return BCME_VERSION; } *ioctl_ver = val; @@ -458,7 +648,7 @@ wl_ext_set_chanspec(struct net_device *dev, int ioctl_ver, iovar_buf, WLC_IOCTL_SMLEN, NULL); if (err) { if (err != BCME_UNSUPPORTED) { - ANDROID_ERROR(("bw_cap failed, %d\n", err)); + AEXT_ERROR(dev->name, "bw_cap failed, %d\n", err); return err; } else { err = wl_ext_iovar_getint(dev, "mimo_bw_cap", &bw_cap); @@ -487,16 +677,13 @@ set_channel: if (bw == WL_CHANSPEC_BW_80) goto change_bw; wl_ext_ioctl(dev, WLC_SET_CHANNEL, &_chan, sizeof(_chan), 1); - printf("%s: channel %d\n", __FUNCTION__, _chan); + WL_MSG(dev->name, "channel %d\n", _chan); } else if (err) { - ANDROID_ERROR(("%s: failed to set chanspec error %d\n", - __FUNCTION__, err)); + AEXT_ERROR(dev->name, "failed to set chanspec error %d\n", err); } else - printf("%s: %s channel %d, 0x%x\n", __FUNCTION__, - dev->name, channel, chspec); + WL_MSG(dev->name, "channel %d, 0x%x\n", channel, chspec); } else { - ANDROID_ERROR(("%s: failed to convert host chanspec to fw chanspec\n", - __FUNCTION__)); + AEXT_ERROR(dev->name, "failed to convert host chanspec to fw chanspec\n"); err = BCME_ERROR; } } else { @@ -509,7 +696,7 @@ change_bw: bw = 0; if (bw) goto set_channel; - ANDROID_ERROR(("%s: Invalid chanspec 0x%x\n", __FUNCTION__, chspec)); + AEXT_ERROR(dev->name, "Invalid chanspec 0x%x\n", chspec); err = BCME_ERROR; } *ret_chspec = fw_chspec; @@ -517,7 +704,7 @@ change_bw: return err; } -int +static int wl_ext_channel(struct net_device *dev, char* command, int total_len) { int ret; @@ -527,7 +714,7 @@ wl_ext_channel(struct net_device *dev, char* command, int total_len) chanspec_t fw_chspec; int ioctl_ver = 0; - ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command)); + AEXT_TRACE(dev->name, "cmd %s", command); sscanf(command, "%*s %d", &channel); @@ -537,12 +724,12 @@ wl_ext_channel(struct net_device *dev, char* command, int total_len) } else { if (!(ret = wl_ext_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t), FALSE))) { - ANDROID_TRACE(("hw_channel %d\n", ci.hw_channel)); - ANDROID_TRACE(("target_channel %d\n", ci.target_channel)); - ANDROID_TRACE(("scan_channel %d\n", ci.scan_channel)); + AEXT_TRACE(dev->name, "hw_channel %d\n", ci.hw_channel); + AEXT_TRACE(dev->name, "target_channel %d\n", ci.target_channel); + AEXT_TRACE(dev->name, "scan_channel %d\n", ci.scan_channel); bytes_written = snprintf(command, sizeof(channel_info_t)+2, "channel %d", ci.hw_channel); - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); + AEXT_TRACE(dev->name, "command result is %s\n", command); ret = bytes_written; } } @@ -550,7 +737,7 @@ wl_ext_channel(struct net_device *dev, char* command, int total_len) return ret; } -int +static int wl_ext_channels(struct net_device *dev, char* command, int total_len) { int ret, i; @@ -558,7 +745,7 @@ wl_ext_channels(struct net_device *dev, char* command, int total_len) u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)]; wl_uint32_list_t *list; - ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command)); + AEXT_TRACE(dev->name, "cmd %s", command); memset(valid_chan_list, 0, sizeof(valid_chan_list)); list = (wl_uint32_list_t *)(void *) valid_chan_list; @@ -566,22 +753,21 @@ wl_ext_channels(struct net_device *dev, char* command, int total_len) ret = wl_ext_ioctl(dev, WLC_GET_VALID_CHANNELS, valid_chan_list, sizeof(valid_chan_list), 0); if (ret<0) { - ANDROID_ERROR(("%s: get channels failed with %d\n", __FUNCTION__, ret)); + AEXT_ERROR(dev->name, "get channels failed with %d\n", ret); } else { bytes_written = snprintf(command, total_len, "channels"); for (i = 0; i < dtoh32(list->count); i++) { bytes_written += snprintf(command+bytes_written, total_len, " %d", dtoh32(list->element[i])); - printf("%d ", dtoh32(list->element[i])); } - printf("\n"); + AEXT_TRACE(dev->name, "command result is %s\n", command); ret = bytes_written; } return ret; } -int +static int wl_ext_roam_trigger(struct net_device *dev, char* command, int total_len) { int ret = 0; @@ -608,7 +794,7 @@ wl_ext_roam_trigger(struct net_device *dev, char* command, int total_len) if (!ret) trigger[1] = roam_trigger[0]; - ANDROID_TRACE(("roam_trigger %d %d\n", trigger[0], trigger[1])); + AEXT_TRACE(dev->name, "roam_trigger %d %d\n", trigger[0], trigger[1]); bytes_written = snprintf(command, total_len, "%d %d", trigger[0], trigger[1]); ret = bytes_written; } @@ -617,102 +803,13 @@ wl_ext_roam_trigger(struct net_device *dev, char* command, int total_len) } static int -wl_ext_pattern_atoh(char *src, char *dst) -{ - int i; - if (strncmp(src, "0x", 2) != 0 && - strncmp(src, "0X", 2) != 0) { - ANDROID_ERROR(("Mask invalid format. Needs to start with 0x\n")); - return -1; - } - src = src + 2; /* Skip past 0x */ - if (strlen(src) % 2 != 0) { - DHD_ERROR(("Mask invalid format. Needs to be of even length\n")); - return -1; - } - for (i = 0; *src != '\0'; i++) { - char num[3]; - bcm_strncpy_s(num, sizeof(num), src, 2); - num[2] = '\0'; - dst[i] = (uint8)strtoul(num, NULL, 16); - src += 2; - } - return i; -} - -int -wl_ext_keep_alive(struct net_device *dev, char *command, int total_len) -{ - wl_mkeep_alive_pkt_t *mkeep_alive_pktp; - int ret = -1, i; - int id, period=-1, len_bytes=0, buf_len=0; - char data[200]="\0"; - char buf[WLC_IOCTL_SMLEN]="\0", iovar_buf[WLC_IOCTL_SMLEN]="\0"; - int bytes_written = -1; - - ANDROID_TRACE(("%s: command = %s\n", __FUNCTION__, command)); - sscanf(command, "%*s %d %d %s", &id, &period, data); - ANDROID_TRACE(("%s: id=%d, period=%d, data=%s\n", __FUNCTION__, id, period, data)); - - if (period >= 0) { - mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *)buf; - mkeep_alive_pktp->version = htod16(WL_MKEEP_ALIVE_VERSION); - mkeep_alive_pktp->length = htod16(WL_MKEEP_ALIVE_FIXED_LEN); - mkeep_alive_pktp->keep_alive_id = id; - buf_len += WL_MKEEP_ALIVE_FIXED_LEN; - mkeep_alive_pktp->period_msec = period; - if (strlen(data)) { - len_bytes = wl_ext_pattern_atoh(data, (char *) mkeep_alive_pktp->data); - buf_len += len_bytes; - } - mkeep_alive_pktp->len_bytes = htod16(len_bytes); - - ret = wl_ext_iovar_setbuf(dev, "mkeep_alive", buf, buf_len, - iovar_buf, sizeof(iovar_buf), NULL); - } else { - if (id < 0) - id = 0; - ret = wl_ext_iovar_getbuf(dev, "mkeep_alive", &id, sizeof(id), buf, - sizeof(buf), NULL); - if (ret) { - goto exit; - } else { - mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *) buf; - printf("Id :%d\n" - "Period (msec) :%d\n" - "Length :%d\n" - "Packet :0x", - mkeep_alive_pktp->keep_alive_id, - dtoh32(mkeep_alive_pktp->period_msec), - dtoh16(mkeep_alive_pktp->len_bytes)); - for (i=0; ilen_bytes; i++) { - printf("%02x", mkeep_alive_pktp->data[i]); - } - printf("\n"); - } - bytes_written = snprintf(command, total_len, "mkeep_alive_period_msec %d ", - dtoh32(mkeep_alive_pktp->period_msec)); - bytes_written += snprintf(command+bytes_written, total_len, "0x"); - for (i=0; ilen_bytes; i++) { - bytes_written += snprintf(command+bytes_written, total_len, "%x", - mkeep_alive_pktp->data[i]); - } - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); - ret = bytes_written; - } - -exit: - return ret; -} - -int wl_ext_pm(struct net_device *dev, char *command, int total_len) { int pm=-1, ret = -1; char *pm_local; int bytes_written=-1; - ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command)); + AEXT_TRACE(dev->name, "cmd %s", command); sscanf(command, "%*s %d", &pm); @@ -721,7 +818,7 @@ wl_ext_pm(struct net_device *dev, char *command, int total_len) } else { ret = wl_ext_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm), 0); if (!ret) { - ANDROID_TRACE(("%s: PM = %d\n", __func__, pm)); + AEXT_TRACE(dev->name, "PM = %d", pm); if (pm == PM_OFF) pm_local = "PM_OFF"; else if(pm == PM_MAX) @@ -733,7 +830,7 @@ wl_ext_pm(struct net_device *dev, char *command, int total_len) pm_local = "Invalid"; } bytes_written = snprintf(command, total_len, "PM %s", pm_local); - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); + AEXT_TRACE(dev->name, "command result is %s\n", command); ret = bytes_written; } } @@ -744,7 +841,7 @@ wl_ext_pm(struct net_device *dev, char *command, int total_len) static int wl_ext_monitor(struct net_device *dev, char *command, int total_len) { - int val, ret = -1; + int val = -1, ret = -1; int bytes_written=-1; sscanf(command, "%*s %d", &val); @@ -754,9 +851,9 @@ wl_ext_monitor(struct net_device *dev, char *command, int total_len) } else { ret = wl_ext_ioctl(dev, WLC_GET_MONITOR, &val, sizeof(val), 0); if (!ret) { - ANDROID_TRACE(("%s: monitor = %d\n", __FUNCTION__, val)); + AEXT_TRACE(dev->name, "monitor = %d\n", val); bytes_written = snprintf(command, total_len, "monitor %d", val); - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); + AEXT_TRACE(dev->name, "command result is %s\n", command); ret = bytes_written; } } @@ -767,18 +864,31 @@ wl_ext_monitor(struct net_device *dev, char *command, int total_len) s32 wl_ext_connect(struct net_device *dev, struct wl_conn_info *conn_info) { - wl_extjoin_params_t *ext_join_params; + struct dhd_pub *dhd = dhd_get_pub(dev); + wl_extjoin_params_t *ext_join_params = NULL; struct wl_join_params join_params; size_t join_params_size; s32 err = 0; u32 chan_cnt = 0; - s8 iovar_buf[WLC_IOCTL_SMLEN]; + s8 *iovar_buf = NULL; int ioctl_ver = 0; + char sec[32]; + + wl_ext_get_ioctl_ver(dev, &ioctl_ver); + + if (dhd->conf->chip == BCM43362_CHIP_ID) + goto set_ssid; if (conn_info->channel) { chan_cnt = 1; } + iovar_buf = kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL); + if (iovar_buf == NULL) { + err = -ENOMEM; + goto exit; + } + /* * Join with specific BSSID and cached SSID * If SSID is zero join based on BSSID only @@ -790,7 +900,6 @@ wl_ext_connect(struct net_device *dev, struct wl_conn_info *conn_info) err = -ENOMEM; goto exit; } - wl_ext_get_ioctl_ver(dev, &ioctl_ver); ext_join_params->ssid.SSID_len = min((uint32)sizeof(ext_join_params->ssid.SSID), conn_info->ssid.SSID_len); memcpy(&ext_join_params->ssid.SSID, conn_info->ssid.SSID, ext_join_params->ssid.SSID_len); @@ -827,20 +936,20 @@ wl_ext_connect(struct net_device *dev, struct wl_conn_info *conn_info) } ext_join_params->assoc.chanspec_num = htod32(ext_join_params->assoc.chanspec_num); + wl_ext_get_sec(dev, 0, sec, sizeof(sec)); + WL_MSG(dev->name, + "Connecting with %pM channel (%d) ssid \"%s\", len (%d), sec=%s\n\n", + &ext_join_params->assoc.bssid, conn_info->channel, + ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len, sec); err = wl_ext_iovar_setbuf_bsscfg(dev, "join", ext_join_params, - join_params_size, iovar_buf, WLC_IOCTL_SMLEN, conn_info->bssidx, NULL); + join_params_size, iovar_buf, WLC_IOCTL_MAXLEN, conn_info->bssidx, NULL); - printf("Connecting with " MACDBG " channel (%d) ssid \"%s\", len (%d)\n\n", - MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)), conn_info->channel, - ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len); - - kfree(ext_join_params); if (err) { if (err == BCME_UNSUPPORTED) { - ANDROID_TRACE(("join iovar is not supported\n")); + AEXT_TRACE(dev->name, "join iovar is not supported\n"); goto set_ssid; } else { - ANDROID_ERROR(("error (%d)\n", err)); + AEXT_ERROR(dev->name, "error (%d)\n", err); goto exit; } } else @@ -859,19 +968,158 @@ set_ssid: memcpy(&join_params.params.bssid, ðer_bcast, ETH_ALEN); wl_ext_ch_to_chanspec(ioctl_ver, conn_info->channel, &join_params, &join_params_size); - ANDROID_TRACE(("join_param_size %zu\n", join_params_size)); + AEXT_TRACE(dev->name, "join_param_size %zu\n", join_params_size); if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) { - ANDROID_INFO(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID, - join_params.ssid.SSID_len)); + AEXT_INFO(dev->name, "ssid \"%s\", len (%d)\n", join_params.ssid.SSID, + join_params.ssid.SSID_len); } - err = wl_ext_ioctl(dev, WLC_SET_SSID, &join_params,join_params_size, 1); + wl_ext_get_sec(dev, 0, sec, sizeof(sec)); + WL_MSG(dev->name, + "Connecting with %pM channel (%d) ssid \"%s\", len (%d), sec=%s\n\n", + &join_params.params.bssid, conn_info->channel, + join_params.ssid.SSID, join_params.ssid.SSID_len, sec); + err = wl_ext_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, 1); exit: + if (iovar_buf) + kfree(iovar_buf); + if (ext_join_params) + kfree(ext_join_params); return err; } +void +wl_ext_get_sec(struct net_device *dev, int ifmode, char *sec, int total_len) +{ + int auth=-1, wpa_auth=-1, wsec=0, mfp=0; + int bytes_written=0; + + memset(sec, 0, total_len); + wl_ext_iovar_getint(dev, "auth", &auth); + wl_ext_iovar_getint(dev, "wpa_auth", &wpa_auth); + wl_ext_iovar_getint(dev, "wsec", &wsec); + wldev_iovar_getint(dev, "mfp", &mfp); + + if (ifmode == IMESH_MODE) { + if (auth == WL_AUTH_OPEN_SYSTEM && wpa_auth == WPA_AUTH_DISABLED) { + bytes_written += snprintf(sec+bytes_written, total_len, "open"); + } else if (auth == WL_AUTH_OPEN_SYSTEM && wpa_auth == WPA2_AUTH_PSK) { + bytes_written += snprintf(sec+bytes_written, total_len, "sae"); + } else { + bytes_written += snprintf(sec+bytes_written, total_len, "unknown"); + } + } else { + if (auth == WL_AUTH_OPEN_SYSTEM && wpa_auth == WPA_AUTH_DISABLED) { + bytes_written += snprintf(sec+bytes_written, total_len, "open"); + } else if (auth == WL_AUTH_SHARED_KEY && wpa_auth == WPA_AUTH_DISABLED) { + bytes_written += snprintf(sec+bytes_written, total_len, "shared"); + } else if (auth == WL_AUTH_OPEN_SYSTEM && wpa_auth == WPA_AUTH_PSK) { + bytes_written += snprintf(sec+bytes_written, total_len, "wpapsk"); + } else if (auth == WL_AUTH_OPEN_SYSTEM && wpa_auth == WPA2_AUTH_PSK) { + bytes_written += snprintf(sec+bytes_written, total_len, "wpa2psk"); + } else if (auth == WL_AUTH_OPEN_SYSTEM && + wpa_auth == (WPA_AUTH_PSK|WPA2_AUTH_PSK)) { + bytes_written += snprintf(sec+bytes_written, total_len, "wpawpa2psk"); + } else if (auth == WL_AUTH_OPEN_SHARED && wpa_auth == WPA3_AUTH_SAE_PSK) { + bytes_written += snprintf(sec+bytes_written, total_len, "wpa3"); + } else { + bytes_written += snprintf(sec+bytes_written, total_len, "(%d/%d)", + auth, wpa_auth); + } + } + + if (mfp == WL_MFP_CAPABLE) { + bytes_written += snprintf(sec+bytes_written, total_len, "/mfpc"); + } else if (mfp == WL_MFP_REQUIRED) { + bytes_written += snprintf(sec+bytes_written, total_len, "/mfpr"); + } + + if (ifmode == IMESH_MODE) { + if (wsec == 0) { + bytes_written += snprintf(sec+bytes_written, total_len, "/none"); + } else { + bytes_written += snprintf(sec+bytes_written, total_len, "/sae"); + } + } else { + if (wsec == 0) { + bytes_written += snprintf(sec+bytes_written, total_len, "/none"); + } else if (wsec == WEP_ENABLED) { + bytes_written += snprintf(sec+bytes_written, total_len, "/wep"); + } else if (wsec == TKIP_ENABLED || wsec == (TKIP_ENABLED|WSEC_SWFLAG)) { + bytes_written += snprintf(sec+bytes_written, total_len, "/tkip"); + } else if (wsec == AES_ENABLED || wsec == (AES_ENABLED|WSEC_SWFLAG)) { + bytes_written += snprintf(sec+bytes_written, total_len, "/aes"); + } else if (wsec == (TKIP_ENABLED|AES_ENABLED) || + wsec == (TKIP_ENABLED|AES_ENABLED|WSEC_SWFLAG)) { + bytes_written += snprintf(sec+bytes_written, total_len, "/tkipaes"); + } else { + bytes_written += snprintf(sec+bytes_written, total_len, "/%d", wsec); + } + } +} + +#if defined(SENDPROB) || (defined(WLMESH) && defined(WL_ESCAN)) +static int +wl_ext_add_del_ie(struct net_device *dev, uint pktflag, char *ie_data, const char* add_del_cmd) +{ + vndr_ie_setbuf_t *vndr_ie = NULL; + char iovar_buf[WLC_IOCTL_SMLEN]="\0"; + int ie_data_len = 0, tot_len = 0, iecount; + int err = -1; + + if (!strlen(ie_data)) { + AEXT_ERROR(dev->name, "wrong ie %s\n", ie_data); + goto exit; + } + + tot_len = (int)(sizeof(vndr_ie_setbuf_t) + ((strlen(ie_data)-2)/2)); + vndr_ie = (vndr_ie_setbuf_t *) kzalloc(tot_len, GFP_KERNEL); + if (!vndr_ie) { + AEXT_ERROR(dev->name, "IE memory alloc failed\n"); + err = -ENOMEM; + goto exit; + } + + /* Copy the vndr_ie SET command ("add"/"del") to the buffer */ + strncpy(vndr_ie->cmd, add_del_cmd, VNDR_IE_CMD_LEN - 1); + vndr_ie->cmd[VNDR_IE_CMD_LEN - 1] = '\0'; + + /* Set the IE count - the buffer contains only 1 IE */ + iecount = htod32(1); + memcpy((void *)&vndr_ie->vndr_ie_buffer.iecount, &iecount, sizeof(s32)); + + /* Set packet flag to indicate that BEACON's will contain this IE */ + pktflag = htod32(pktflag); + memcpy((void *)&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].pktflag, &pktflag, + sizeof(u32)); + + /* Set the IE ID */ + vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = (uchar)DOT11_MNG_VS_ID; + + /* Set the IE LEN */ + vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len = (strlen(ie_data)-2)/2; + + /* Set the IE OUI and DATA */ + ie_data_len = wl_pattern_atoh(ie_data, + (char *)vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui); + if (ie_data_len <= 0) { + AEXT_ERROR(dev->name, "wrong ie_data_len %d\n", (int)strlen(ie_data)-2); + goto exit; + } + + err = wl_ext_iovar_setbuf(dev, "vndr_ie", vndr_ie, tot_len, iovar_buf, + sizeof(iovar_buf), NULL); + +exit: + if (vndr_ie) { + kfree(vndr_ie); + } + return err; +} +#endif /* SENDPROB || (WLMESH && WL_ESCAN) */ + #ifdef WL_EXT_IAPSTA static int wl_ext_parse_wep(char *key, struct wl_wsec_key *wsec_key) @@ -951,98 +1199,37 @@ wl_ext_set_bgnmode(struct wl_if_info *cur_if) wl_ext_iovar_setint(dev, "nmode", 0); val = 0; wl_ext_ioctl(dev, WLC_SET_GMODE, &val, sizeof(val), 1); - ANDROID_TRACE(("%s: Network mode: B only\n", __FUNCTION__)); + AEXT_TRACE(dev->name, "Network mode: B only\n"); } else if (bgnmode == IEEE80211G) { wl_ext_iovar_setint(dev, "nmode", 0); val = 2; wl_ext_ioctl(dev, WLC_SET_GMODE, &val, sizeof(val), 1); - ANDROID_TRACE(("%s: Network mode: G only\n", __FUNCTION__)); + AEXT_TRACE(dev->name, "Network mode: G only\n"); } else if (bgnmode == IEEE80211BG) { wl_ext_iovar_setint(dev, "nmode", 0); val = 1; wl_ext_ioctl(dev, WLC_SET_GMODE, &val, sizeof(val), 1); - ANDROID_TRACE(("%s: Network mode: B/G mixed\n", __FUNCTION__)); + AEXT_TRACE(dev->name, "Network mode: B/G mixed\n"); } else if (bgnmode == IEEE80211BGN) { wl_ext_iovar_setint(dev, "nmode", 0); wl_ext_iovar_setint(dev, "nmode", 1); wl_ext_iovar_setint(dev, "vhtmode", 0); val = 1; wl_ext_ioctl(dev, WLC_SET_GMODE, &val, sizeof(val), 1); - ANDROID_TRACE(("%s: Network mode: B/G/N mixed\n", __FUNCTION__)); + AEXT_TRACE(dev->name, "Network mode: B/G/N mixed\n"); } else if (bgnmode == IEEE80211BGNAC) { wl_ext_iovar_setint(dev, "nmode", 0); wl_ext_iovar_setint(dev, "nmode", 1); wl_ext_iovar_setint(dev, "vhtmode", 1); val = 1; wl_ext_ioctl(dev, WLC_SET_GMODE, &val, sizeof(val), 1); - ANDROID_TRACE(("%s: Network mode: B/G/N/AC mixed\n", __FUNCTION__)); + AEXT_TRACE(dev->name, "Network mode: B/G/N/AC mixed\n"); } wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); return 0; } -static void -wl_ext_get_amode(struct wl_if_info *cur_if, char *amode) -{ - struct net_device *dev = cur_if->dev; - int auth=-1, wpa_auth=-1; - - wl_ext_iovar_getint(dev, "auth", &auth); - wl_ext_iovar_getint(dev, "wpa_auth", &wpa_auth); - -#ifdef WLMESH - if (cur_if->ifmode == IMESH_MODE) { - if (auth == 0 && wpa_auth == 0) { - strcpy(amode, "open"); - } else if (auth == 0 && wpa_auth == 128) { - strcpy(amode, "sae"); - } - } else -#endif - if (auth == 0 && wpa_auth == 0) { - strcpy(amode, "open"); - } else if (auth == 1 && wpa_auth == 0) { - strcpy(amode, "shared"); - } else if (auth == 0 && wpa_auth == 4) { - strcpy(amode, "wpapsk"); - } else if (auth == 0 && wpa_auth == 128) { - strcpy(amode, "wpa2psk"); - } else if (auth == 0 && wpa_auth == 132) { - strcpy(amode, "wpawpa2psk"); - } -} - -static void -wl_ext_get_emode(struct wl_if_info *cur_if, char *emode) -{ - struct net_device *dev = cur_if->dev; - int wsec=0; - - wl_ext_iovar_getint(dev, "wsec", &wsec); - -#ifdef WLMESH - if (cur_if->ifmode == IMESH_MODE) { - if (wsec == 0) { - strcpy(emode, "none"); - } else { - strcpy(emode, "sae"); - } - } else -#endif - if (wsec == 0) { - strcpy(emode, "none"); - } else if (wsec == 1) { - strcpy(emode, "wep"); - } else if (wsec == 2 || wsec == 10) { - strcpy(emode, "tkip"); - } else if (wsec == 4 || wsec == 12) { - strcpy(emode, "aes"); - } else if (wsec == 6 || wsec == 14) { - strcpy(emode, "tkipaes"); - } -} - static int wl_ext_set_amode(struct wl_if_info *cur_if) { @@ -1055,41 +1242,41 @@ wl_ext_set_amode(struct wl_if_info *cur_if) if (amode == AUTH_SAE) { auth = 0; wpa_auth = 128; - ANDROID_INFO(("%s: Authentication: SAE\n", __FUNCTION__)); + AEXT_INFO(dev->name, "SAE\n"); } else { auth = 0; wpa_auth = 0; - ANDROID_INFO(("%s: Authentication: Open System\n", __FUNCTION__)); + AEXT_INFO(dev->name, "Open System\n"); } } else -#endif +#endif /* WLMESH */ if (amode == AUTH_OPEN) { auth = 0; wpa_auth = 0; - ANDROID_INFO(("%s: Authentication: Open System\n", __FUNCTION__)); + AEXT_INFO(dev->name, "Open System\n"); } else if (amode == AUTH_SHARED) { auth = 1; wpa_auth = 0; - ANDROID_INFO(("%s: Authentication: Shared Key\n", __FUNCTION__)); + AEXT_INFO(dev->name, "Shared Key\n"); } else if (amode == AUTH_WPAPSK) { auth = 0; wpa_auth = 4; - ANDROID_INFO(("%s: Authentication: WPA-PSK\n", __FUNCTION__)); + AEXT_INFO(dev->name, "WPA-PSK\n"); } else if (amode == AUTH_WPA2PSK) { auth = 0; wpa_auth = 128; - ANDROID_INFO(("%s: Authentication: WPA2-PSK\n", __FUNCTION__)); + AEXT_INFO(dev->name, "WPA2-PSK\n"); } else if (amode == AUTH_WPAWPA2PSK) { auth = 0; wpa_auth = 132; - ANDROID_INFO(("%s: Authentication: WPA/WPA2-PSK\n", __FUNCTION__)); + AEXT_INFO(dev->name, "WPA/WPA2-PSK\n"); } #ifdef WLMESH if (cur_if->ifmode == IMESH_MODE) { s32 val = WL_BSSTYPE_MESH; wl_ext_ioctl(dev, WLC_SET_INFRA, &val, sizeof(val), 1); } else -#endif +#endif /* WLMESH */ if (cur_if->ifmode == ISTA_MODE) { s32 val = WL_BSSTYPE_INFRA; wl_ext_ioctl(dev, WLC_SET_INFRA, &val, sizeof(val), 1); @@ -1102,7 +1289,8 @@ wl_ext_set_amode(struct wl_if_info *cur_if) } static int -wl_ext_set_emode(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if) +wl_ext_set_emode(struct wl_apsta_params *apsta_params, + struct wl_if_info *cur_if) { struct net_device *dev = cur_if->dev; int wsec=0; @@ -1111,7 +1299,7 @@ wl_ext_set_emode(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if authmode_t amode = cur_if->amode; encmode_t emode = cur_if->emode; char *key = cur_if->key; - struct dhd_pub *dhd = dhd_get_pub(dev); + struct dhd_pub *dhd = apsta_params->dhd; memset(&wsec_key, 0, sizeof(wsec_key)); memset(&psk, 0, sizeof(psk)); @@ -1120,45 +1308,39 @@ wl_ext_set_emode(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if if (cur_if->ifmode == IMESH_MODE) { if (amode == AUTH_SAE) { wsec = 4; - ANDROID_INFO(("%s: Encryption: AES\n", __FUNCTION__)); } else { wsec = 0; - ANDROID_INFO(("%s: Encryption: No securiy\n", __FUNCTION__)); } } else -#endif +#endif /* WLMESH */ if (emode == ENC_NONE) { wsec = 0; - ANDROID_INFO(("%s: Encryption: No securiy\n", __FUNCTION__)); + AEXT_INFO(dev->name, "No securiy\n"); } else if (emode == ENC_WEP) { wsec = 1; wl_ext_parse_wep(key, &wsec_key); - ANDROID_INFO(("%s: Encryption: WEP\n", __FUNCTION__)); - ANDROID_INFO(("%s: Key: \"%s\"\n", __FUNCTION__, wsec_key.data)); + AEXT_INFO(dev->name, "WEP key \"%s\"\n", wsec_key.data); } else if (emode == ENC_TKIP) { wsec = 2; psk.key_len = strlen(key); psk.flags = WSEC_PASSPHRASE; memcpy(psk.key, key, strlen(key)); - ANDROID_INFO(("%s: Encryption: TKIP\n", __FUNCTION__)); - ANDROID_INFO(("%s: Key: \"%s\"\n", __FUNCTION__, psk.key)); + AEXT_INFO(dev->name, "TKIP key \"%s\"\n", psk.key); } else if (emode == ENC_AES || amode == AUTH_SAE) { wsec = 4; psk.key_len = strlen(key); psk.flags = WSEC_PASSPHRASE; memcpy(psk.key, key, strlen(key)); - ANDROID_INFO(("%s: Encryption: AES\n", __FUNCTION__)); - ANDROID_INFO(("%s: Key: \"%s\"\n", __FUNCTION__, psk.key)); + AEXT_INFO(dev->name, "AES key \"%s\"\n", psk.key); } else if (emode == ENC_TKIPAES) { wsec = 6; psk.key_len = strlen(key); psk.flags = WSEC_PASSPHRASE; memcpy(psk.key, key, strlen(key)); - ANDROID_INFO(("%s: Encryption: TKIP/AES\n", __FUNCTION__)); - ANDROID_INFO(("%s: Key: \"%s\"\n", __FUNCTION__, psk.key)); + AEXT_INFO(dev->name, "TKIP/AES key \"%s\"\n", psk.key); } if (dhd->conf->chip == BCM43430_CHIP_ID && cur_if->ifidx > 0 && wsec >= 2 && - apsta_params->apstamode == IAPSTA_MODE) { + apsta_params->apstamode == ISTAAP_MODE) { wsec |= 0x8; // terence 20180628: fix me, this is a workaround } @@ -1168,26 +1350,42 @@ wl_ext_set_emode(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if if (cur_if->ifmode == IMESH_MODE) { if (amode == AUTH_SAE) { s8 iovar_buf[WLC_IOCTL_SMLEN]; - ANDROID_INFO(("%s: Key: \"%s\"\n", __FUNCTION__, key)); + AEXT_INFO(dev->name, "SAE key \"%s\"\n", key); wl_ext_iovar_setint(dev, "mesh_auth_proto", 1); wl_ext_iovar_setint(dev, "mfp", WL_MFP_REQUIRED); wl_ext_iovar_setbuf(dev, "sae_password", key, strlen(key), iovar_buf, WLC_IOCTL_SMLEN, NULL); } else { + AEXT_INFO(dev->name, "No securiy\n"); wl_ext_iovar_setint(dev, "mesh_auth_proto", 0); wl_ext_iovar_setint(dev, "mfp", WL_MFP_NONE); } } else -#endif +#endif /* WLMESH */ if (emode == ENC_WEP) { wl_ext_ioctl(dev, WLC_SET_KEY, &wsec_key, sizeof(wsec_key), 1); } else if (emode == ENC_TKIP || emode == ENC_AES || emode == ENC_TKIPAES) { - if (dev) { - if (cur_if->ifmode == ISTA_MODE) - wl_ext_iovar_setint(dev, "sup_wpa", 1); - wl_ext_ioctl(dev, WLC_SET_WSEC_PMK, &psk, sizeof(psk), 1); - } else { - ANDROID_ERROR(("%s: apdev is null\n", __FUNCTION__)); + if (cur_if->ifmode == ISTA_MODE) + wl_ext_iovar_setint(dev, "sup_wpa", 1); + wl_ext_ioctl(dev, WLC_SET_WSEC_PMK, &psk, sizeof(psk), 1); + } + + return 0; +} + +static u32 +wl_ext_get_chanspec(struct wl_apsta_params *apsta_params, + struct net_device *dev) +{ + int ret = 0; + struct ether_addr bssid; + u32 chanspec = 0; + + ret = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), 0); + if (ret != BCME_NOTASSOCIATED && memcmp(ðer_null, &bssid, ETHER_ADDR_LEN)) { + if (wl_ext_iovar_getint(dev, "chanspec", (s32 *)&chanspec) == BCME_OK) { + chanspec = wl_ext_chspec_driver_to_host(apsta_params->ioctl_ver, chanspec); + return chanspec; } } @@ -1201,15 +1399,13 @@ wl_ext_get_chan(struct wl_apsta_params *apsta_params, struct net_device *dev) uint16 chan = 0, ctl_chan; struct ether_addr bssid; u32 chanspec = 0; - - ret = wl_ext_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), 0); + + ret = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), 0); if (ret != BCME_NOTASSOCIATED && memcmp(ðer_null, &bssid, ETHER_ADDR_LEN)) { if (wl_ext_iovar_getint(dev, "chanspec", (s32 *)&chanspec) == BCME_OK) { chanspec = wl_ext_chspec_driver_to_host(apsta_params->ioctl_ver, chanspec); ctl_chan = wf_chspec_ctlchan(chanspec); chan = (u16)(ctl_chan & 0x00FF); - ANDROID_INFO(("%s: cur_chan=%d(0x%x)\n", __FUNCTION__, - chan, chanspec)); return chan; } } @@ -1218,7 +1414,7 @@ wl_ext_get_chan(struct wl_apsta_params *apsta_params, struct net_device *dev) } static chanspec_t -wl_ext_get_chanspec(struct wl_apsta_params *apsta_params, +wl_ext_chan_to_chanspec(struct wl_apsta_params *apsta_params, struct net_device *dev, uint16 channel) { s32 _chan = channel; @@ -1245,7 +1441,7 @@ wl_ext_get_chanspec(struct wl_apsta_params *apsta_params, iovar_buf, WLC_IOCTL_SMLEN, NULL); if (err) { if (err != BCME_UNSUPPORTED) { - ANDROID_ERROR(("bw_cap failed, %d\n", err)); + AEXT_ERROR(dev->name, "bw_cap failed, %d\n", err); return err; } else { err = wl_ext_iovar_getint(dev, "mimo_bw_cap", &bw_cap); @@ -1269,8 +1465,7 @@ set_channel: if (wf_chspec_valid(chspec)) { fw_chspec = wl_ext_chspec_host_to_driver(apsta_params->ioctl_ver, chspec); if (fw_chspec == INVCHANSPEC) { - ANDROID_ERROR(("%s: failed to convert host chanspec to fw chanspec\n", - __FUNCTION__)); + AEXT_ERROR(dev->name, "failed to convert host chanspec to fw chanspec\n"); fw_chspec = 0; } } else { @@ -1282,23 +1477,109 @@ set_channel: bw = 0; if (bw) goto set_channel; - ANDROID_ERROR(("%s: Invalid chanspec 0x%x\n", __FUNCTION__, chspec)); + AEXT_ERROR(dev->name, "Invalid chanspec 0x%x\n", chspec); err = BCME_ERROR; } return fw_chspec; } +static bool +wl_ext_dfs_chan(struct wl_apsta_params *apsta_params, struct net_device *dev, + uint16 chan) +{ + u32 channel = chan; + s32 err = BCME_OK; + bool dfs = FALSE; + + if (chan <= CH_MAX_2G_CHANNEL) + return FALSE; + + channel |= WL_CHANSPEC_BAND_5G; + channel |= WL_CHANSPEC_BW_20; + channel = wl_ext_chspec_host_to_driver(apsta_params->ioctl_ver, channel); + err = wl_ext_iovar_getint(dev, "per_chan_info", &channel); + if (!err) { + if (channel & WL_CHAN_PASSIVE) { + dfs = TRUE; + } + } + + return dfs; +} + static void wl_ext_wait_netif_change(struct wl_apsta_params *apsta_params, - bool need_rtnl_unlock) + struct wl_if_info *cur_if) { - if (need_rtnl_unlock) - rtnl_unlock(); + rtnl_unlock(); wait_event_interruptible_timeout(apsta_params->netif_change_event, - apsta_params->netif_change, msecs_to_jiffies(1500)); - if (need_rtnl_unlock) - rtnl_lock(); + wl_get_isam_status(cur_if, IF_READY), + msecs_to_jiffies(MAX_AP_LINK_WAIT_TIME)); + rtnl_lock(); +} + +bool +wl_ext_check_mesh_creating(struct net_device *net) +{ + struct dhd_pub *dhd = dhd_get_pub(net); + struct wl_apsta_params *apsta_params = dhd->iapsta_params; + struct wl_if_info *cur_if; + int i; + + if (apsta_params) { + for (i=0; iif_info[i]; + if (cur_if->ifmode==IMESH_MODE && wl_get_isam_status(cur_if, IF_ADDING)) + return TRUE; + } + } + return FALSE; +} + +bool +wl_ext_check_other_enabling(struct wl_apsta_params *apsta_params, + struct wl_if_info *cur_if) +{ + struct wl_if_info *tmp_if; + bool enabling = FALSE; + u32 timeout = 1; + int i; + + for (i=0; iif_info[i]; + if (tmp_if->dev && tmp_if->dev != cur_if->dev) { + if (tmp_if->ifmode == ISTA_MODE) + enabling = wl_get_isam_status(tmp_if, STA_CONNECTING); + else if (tmp_if->ifmode == IAP_MODE || tmp_if->ifmode == IMESH_MODE) + enabling = wl_get_isam_status(tmp_if, AP_CREATING); + if (enabling) + WL_MSG(cur_if->ifname, "waiting for %s[%c] enabling...\n", + tmp_if->ifname, tmp_if->prefix); + if (enabling && tmp_if->ifmode == ISTA_MODE) { + timeout = wait_event_interruptible_timeout( + apsta_params->netif_change_event, + !wl_get_isam_status(tmp_if, STA_CONNECTING), + msecs_to_jiffies(MAX_STA_LINK_WAIT_TIME)); + } else if (enabling && + (tmp_if->ifmode == IAP_MODE || tmp_if->ifmode == IMESH_MODE)) { + timeout = wait_event_interruptible_timeout( + apsta_params->netif_change_event, + !wl_get_isam_status(tmp_if, AP_CREATING), + msecs_to_jiffies(MAX_STA_LINK_WAIT_TIME)); + } + if (tmp_if->ifmode == ISTA_MODE) + enabling = wl_get_isam_status(tmp_if, STA_CONNECTING); + else if (tmp_if->ifmode == IAP_MODE || tmp_if->ifmode == IMESH_MODE) + enabling = wl_get_isam_status(tmp_if, AP_CREATING); + if (timeout <= 0 || enabling) { + WL_MSG(cur_if->ifname, "%s[%c] is still enabling...\n", + tmp_if->ifname, tmp_if->prefix); + } + } + } + + return enabling; } static void @@ -1306,34 +1587,26 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para { struct dhd_pub *dhd; apstamode_t apstamode = apsta_params->apstamode; - wl_interface_create_t iface; struct wl_if_info *cur_if; - wlc_ssid_t ssid = { 0, {0} }; s8 iovar_buf[WLC_IOCTL_SMLEN]; - wl_country_t cspec = {{0}, 0, {0}}; - wl_p2p_if_t ifreq; s32 val = 0; - int i, dfs = 1; + int i, dfs = 1, disable_5g_band = 0; dhd = dhd_get_pub(dev); for (i=0; iif_info[i]; - if (i == 1 && !strlen(cur_if->ifname)) - strcpy(cur_if->ifname, "wlan1"); - if (i == 2 && !strlen(cur_if->ifname)) - strcpy(cur_if->ifname, "wlan2"); + if (i >= 1 && !strlen(cur_if->ifname)) + snprintf(cur_if->ifname, IFNAMSIZ, "wlan%d", i); if (cur_if->ifmode == ISTA_MODE) { cur_if->channel = 0; cur_if->maxassoc = -1; - cur_if->ifstate = IF_STATE_INIT; cur_if->prio = PRIO_STA; cur_if->prefix = 'S'; snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_sta"); } else if (cur_if->ifmode == IAP_MODE) { cur_if->channel = 1; cur_if->maxassoc = -1; - cur_if->ifstate = IF_STATE_INIT; cur_if->prio = PRIO_AP; cur_if->prefix = 'A'; snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_ap"); @@ -1342,46 +1615,51 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para } else if (cur_if->ifmode == IMESH_MODE) { cur_if->channel = 1; cur_if->maxassoc = -1; - cur_if->ifstate = IF_STATE_INIT; cur_if->prio = PRIO_MESH; cur_if->prefix = 'M'; snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_mesh"); dfs = 0; -#endif +#ifdef WL_ESCAN + if (i == 0 && apsta_params->macs) + wl_mesh_escan_attach(dhd, cur_if); +#endif /* WL_ESCAN */ +#endif /* WLMESH */ } } if (!dfs && !apsta_params->vsdb) { - dhd_conf_get_country(dhd, &cspec); - if (!dhd_conf_map_country_list(dhd, &cspec)) { - dhd_conf_set_country(dhd, &cspec); - dhd_bus_country_set(dev, &cspec, TRUE); - } wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); - wl_ext_iovar_setint(dev, "dfs_chan_disable", 1); + wl_ext_iovar_getint(dev, "disable_5g_band", &disable_5g_band); + disable_5g_band |= 0x6; + wl_ext_iovar_setint(dev, "disable_5g_band", disable_5g_band); wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); +#ifdef WL_CFG80211 + if (dhd->up) { + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); + wl_update_wiphybands(cfg, true); + } +#endif /* WL_CFG80211 */ } if (FW_SUPPORTED(dhd, rsdb)) { if (apstamode == IDUALAP_MODE) - apsta_params->rsdb = TRUE; + apsta_params->rsdb = -1; else if (apstamode == ISTAAPAP_MODE) - apsta_params->rsdb = FALSE; - if (apstamode == IDUALAP_MODE || apstamode == ISTAAPAP_MODE || - apstamode == IMESHONLY_MODE || apstamode == IMESHSTA_MODE || - apstamode == IMESHAP_MODE || apstamode == IMESHAPSTA_MODE || - apstamode == IMESHAPAP_MODE) { + apsta_params->rsdb = 0; + if (apstamode == ISTAAPAP_MODE || apstamode == IDUALAP_MODE || + apstamode == IMESHONLY_MODE || apstamode == ISTAMESH_MODE || + apstamode == IMESHAP_MODE || apstamode == ISTAAPMESH_MODE || + apstamode == IMESHAPAP_MODE) { wl_config_t rsdb_mode_cfg = {0, 0}; - if (apsta_params->rsdb) - rsdb_mode_cfg.config = 1; - printf("%s: set rsdb_mode %d\n", __FUNCTION__, rsdb_mode_cfg.config); + rsdb_mode_cfg.config = apsta_params->rsdb; + AEXT_INFO(dev->name, "set rsdb_mode %d\n", rsdb_mode_cfg.config); wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); wl_ext_iovar_setbuf(dev, "rsdb_mode", &rsdb_mode_cfg, sizeof(rsdb_mode_cfg), iovar_buf, sizeof(iovar_buf), NULL); wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); } } else { - apsta_params->rsdb = FALSE; + apsta_params->rsdb = 0; } if (apstamode == ISTAONLY_MODE) { @@ -1402,7 +1680,7 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para wl_ext_ioctl(dev, WLC_SET_AP, &val, sizeof(val), 1); #ifdef PROP_TXSTATUS_VSDB #if defined(BCMSDIO) - if (!FW_SUPPORTED(dhd, rsdb) && !disable_proptx) { + if (!(FW_SUPPORTED(dhd, rsdb)) && !disable_proptx) { bool enabled; dhd_wlfc_get_enable(dhd, &enabled); if (!enabled) { @@ -1410,26 +1688,21 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); } } -#endif +#endif /* BCMSDIO */ #endif /* PROP_TXSTATUS_VSDB */ } - else if (apstamode == IAPSTA_MODE) { + else if (apstamode == ISTAAP_MODE) { wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); wl_ext_iovar_setint(dev, "mpc", 0); wl_ext_iovar_setint(dev, "apsta", 1); wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); - apsta_params->netif_change = FALSE; - if (FW_SUPPORTED(dhd, rsdb)) { - bzero(&iface, sizeof(wl_interface_create_t)); - iface.ver = WL_INTERFACE_CREATE_VER; - iface.flags = WL_INTERFACE_CREATE_AP; - wl_ext_iovar_getbuf(dev, "interface_create", &iface, - sizeof(iface), iovar_buf, WLC_IOCTL_SMLEN, NULL); - } else { - wl_ext_iovar_setbuf_bsscfg(dev, "ssid", &ssid, sizeof(ssid), - iovar_buf, WLC_IOCTL_SMLEN, 1, NULL); - } - wl_ext_wait_netif_change(apsta_params, TRUE); + } + else if (apstamode == ISTAGO_MODE) { + wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); + wl_ext_iovar_setint(dev, "apsta", 1); + wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); + } + else if (apstamode == ISTASTA_MODE) { } else if (apstamode == IDUALAP_MODE) { wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); @@ -1445,146 +1718,146 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); val = 1; wl_ext_ioctl(dev, WLC_SET_AP, &val, sizeof(val), 1); - bzero(&iface, sizeof(wl_interface_create_t)); - iface.ver = WL_INTERFACE_CREATE_VER; - iface.flags = WL_INTERFACE_CREATE_AP; - apsta_params->netif_change = FALSE; - wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface), - iovar_buf, WLC_IOCTL_SMLEN, NULL); - wl_ext_wait_netif_change(apsta_params, TRUE); } else if (apstamode == ISTAAPAP_MODE) { - u8 rand_bytes[2] = {0, }; - get_random_bytes(&rand_bytes, sizeof(rand_bytes)); wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); wl_ext_iovar_setint(dev, "mpc", 0); wl_ext_iovar_setint(dev, "mbss", 1); wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); // don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off - bzero(&iface, sizeof(wl_interface_create_t)); - iface.ver = WL_INTERFACE_CREATE_VER; - iface.flags = WL_INTERFACE_CREATE_AP | WL_INTERFACE_MAC_USE; - memcpy(&iface.mac_addr, dev->dev_addr, ETHER_ADDR_LEN); - iface.mac_addr.octet[0] |= 0x02; - iface.mac_addr.octet[5] += 0x01; - memcpy(&iface.mac_addr.octet[3], rand_bytes, sizeof(rand_bytes)); - apsta_params->netif_change = FALSE; - wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface), - iovar_buf, WLC_IOCTL_SMLEN, NULL); - wl_ext_wait_netif_change(apsta_params, TRUE); - bzero(&iface, sizeof(wl_interface_create_t)); - iface.ver = WL_INTERFACE_CREATE_VER; - iface.flags = WL_INTERFACE_CREATE_AP | WL_INTERFACE_MAC_USE; - memcpy(&iface.mac_addr, dev->dev_addr, ETHER_ADDR_LEN); - iface.mac_addr.octet[0] |= 0x02; - iface.mac_addr.octet[5] += 0x02; - memcpy(&iface.mac_addr.octet[3], rand_bytes, sizeof(rand_bytes)); - apsta_params->netif_change = FALSE; - wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface), - iovar_buf, WLC_IOCTL_SMLEN, NULL); - wl_ext_wait_netif_change(apsta_params, TRUE); } #ifdef WLMESH - else if (apstamode == IMESHONLY_MODE) { + else if (apstamode == IMESHONLY_MODE || apstamode == ISTAMESH_MODE || + apstamode == IMESHAP_MODE || apstamode == ISTAAPMESH_MODE || + apstamode == IMESHAPAP_MODE) { int pm = 0; wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); wl_ext_iovar_setint(dev, "mpc", 0); - wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls - wl_ext_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), 1); - wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); - // don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off - } - else if (apstamode == IMESHSTA_MODE) { - wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); - wl_ext_iovar_setint(dev, "mpc", 0); - wl_ext_iovar_setint(dev, "mbcn", 1); - wl_ext_iovar_setint(dev, "apsta", 1); - wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); - bzero(&iface, sizeof(wl_interface_create_t)); - iface.ver = WL_INTERFACE_CREATE_VER; - iface.flags = WL_INTERFACE_CREATE_STA; - apsta_params->netif_change = FALSE; - wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface), - iovar_buf, WLC_IOCTL_SMLEN, NULL); - wl_ext_wait_netif_change(apsta_params, TRUE); - } - else if (apstamode == IMESHAP_MODE) { - wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); - wl_ext_iovar_setint(dev, "mpc", 0); - wl_ext_iovar_setint(dev, "mbcn", 1); + if (apstamode == IMESHONLY_MODE) + wl_ext_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), 1); + else + wl_ext_iovar_setint(dev, "mbcn", 1); wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); // don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off - bzero(&iface, sizeof(wl_interface_create_t)); - iface.ver = WL_INTERFACE_CREATE_VER; - iface.flags = WL_INTERFACE_CREATE_AP; - apsta_params->netif_change = FALSE; - wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface), - iovar_buf, WLC_IOCTL_SMLEN, NULL); - wl_ext_wait_netif_change(apsta_params, TRUE); - } - else if (apstamode == IMESHAPSTA_MODE) { - wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); - wl_ext_iovar_setint(dev, "mpc", 0); - wl_ext_iovar_setint(dev, "mbcn", 1); - wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls - wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); - // don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off - bzero(&iface, sizeof(wl_interface_create_t)); - iface.ver = WL_INTERFACE_CREATE_VER; - iface.flags = WL_INTERFACE_CREATE_AP; - apsta_params->netif_change = FALSE; - wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface), - iovar_buf, WLC_IOCTL_SMLEN, NULL); - wl_ext_wait_netif_change(apsta_params, TRUE); - bzero(&iface, sizeof(wl_interface_create_t)); - iface.ver = WL_INTERFACE_CREATE_VER; - iface.flags = WL_INTERFACE_CREATE_STA; - apsta_params->netif_change = FALSE; - wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface), - iovar_buf, WLC_IOCTL_SMLEN, NULL); - wl_ext_wait_netif_change(apsta_params, TRUE); - } - else if (apstamode == IMESHAPAP_MODE) { - wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); - wl_ext_iovar_setint(dev, "mpc", 0); - wl_ext_iovar_setint(dev, "mbcn", 1); - wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls - wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); - // don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off - bzero(&iface, sizeof(wl_interface_create_t)); - iface.ver = WL_INTERFACE_CREATE_VER; - iface.flags = WL_INTERFACE_CREATE_AP; - apsta_params->netif_change = FALSE; - wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface), - iovar_buf, WLC_IOCTL_SMLEN, NULL); - wl_ext_wait_netif_change(apsta_params, TRUE); - bzero(&iface, sizeof(wl_interface_create_t)); - iface.ver = WL_INTERFACE_CREATE_VER; - iface.flags = WL_INTERFACE_CREATE_AP; - apsta_params->netif_change = FALSE; - wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface), - iovar_buf, WLC_IOCTL_SMLEN, NULL); - wl_ext_wait_netif_change(apsta_params, TRUE); - } -#endif - else if (apstamode == IGOSTA_MODE) { - wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); - wl_ext_iovar_setint(dev, "apsta", 1); - wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); - bzero(&ifreq, sizeof(wl_p2p_if_t)); - ifreq.type = htod32(WL_P2P_IF_GO); - apsta_params->netif_change = FALSE; - wl_ext_iovar_setbuf(dev, "p2p_ifadd", &ifreq, sizeof(ifreq), - iovar_buf, WLC_IOCTL_SMLEN, NULL); - wl_ext_wait_netif_change(apsta_params, TRUE); } +#endif /* WLMESH */ wl_ext_get_ioctl_ver(dev, &apsta_params->ioctl_ver); apsta_params->init = TRUE; - printf("%s: apstamode=%d\n", __FUNCTION__, apstamode); + WL_MSG(dev->name, "apstamode=%d\n", apstamode); +} + +static void +wl_ext_interface_create(struct net_device *dev, struct wl_apsta_params *apsta_params, + struct wl_if_info *cur_if, int iftype, u8 *addr) +{ + wl_interface_create_t iface; + u8 iovar_buf[WLC_IOCTL_SMLEN]; + + bzero(&iface, sizeof(iface)); + if (addr) { + iftype |= WL_INTERFACE_MAC_USE; + } + iface.ver = WL_INTERFACE_CREATE_VER; + iface.flags = iftype; + if (addr) { + memcpy(&iface.mac_addr.octet, addr, ETH_ALEN); + } + wl_set_isam_status(cur_if, IF_ADDING); + wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface), + iovar_buf, WLC_IOCTL_SMLEN, NULL); + wl_ext_wait_netif_change(apsta_params, cur_if); +} + +static void +wl_ext_iapsta_intf_add(struct net_device *dev, struct wl_apsta_params *apsta_params) +{ + struct dhd_pub *dhd; + apstamode_t apstamode = apsta_params->apstamode; + struct wl_if_info *cur_if; + wlc_ssid_t ssid = { 0, {0} }; + s8 iovar_buf[WLC_IOCTL_SMLEN]; + wl_p2p_if_t ifreq; + struct ether_addr mac_addr; + + dhd = dhd_get_pub(dev); + bzero(&mac_addr, sizeof(mac_addr)); + + if (apstamode == ISTAAP_MODE) { + cur_if = &apsta_params->if_info[IF_VIF]; + if (FW_SUPPORTED(dhd, rsdb)) { + wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL); + } else { + wl_set_isam_status(cur_if, IF_ADDING); + wl_ext_iovar_setbuf_bsscfg(dev, "ssid", &ssid, sizeof(ssid), + iovar_buf, WLC_IOCTL_SMLEN, 1, NULL); + wl_ext_wait_netif_change(apsta_params, cur_if); + } + } + else if (apstamode == ISTAGO_MODE) { + bzero(&ifreq, sizeof(wl_p2p_if_t)); + ifreq.type = htod32(WL_P2P_IF_GO); + cur_if = &apsta_params->if_info[IF_VIF]; + wl_set_isam_status(cur_if, IF_ADDING); + wl_ext_iovar_setbuf(dev, "p2p_ifadd", &ifreq, sizeof(ifreq), + iovar_buf, WLC_IOCTL_SMLEN, NULL); + wl_ext_wait_netif_change(apsta_params, cur_if); + } + else if (apstamode == ISTASTA_MODE) { + cur_if = &apsta_params->if_info[IF_VIF]; + memcpy(&mac_addr, dev->dev_addr, ETHER_ADDR_LEN); + mac_addr.octet[0] |= 0x02; + wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_STA, + (u8*)&mac_addr); + } + else if (apstamode == IDUALAP_MODE) { + cur_if = &apsta_params->if_info[IF_VIF]; + wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL); + } + else if (apstamode == ISTAAPAP_MODE) { + u8 rand_bytes[2] = {0, }; + get_random_bytes(&rand_bytes, sizeof(rand_bytes)); + cur_if = &apsta_params->if_info[IF_VIF]; + memcpy(&mac_addr, dev->dev_addr, ETHER_ADDR_LEN); + mac_addr.octet[0] |= 0x02; + mac_addr.octet[5] += 0x01; + memcpy(&mac_addr.octet[3], rand_bytes, sizeof(rand_bytes)); + wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, + (u8*)&mac_addr); + cur_if = &apsta_params->if_info[IF_VIF2]; + memcpy(&mac_addr, dev->dev_addr, ETHER_ADDR_LEN); + mac_addr.octet[0] |= 0x02; + mac_addr.octet[5] += 0x02; + memcpy(&mac_addr.octet[3], rand_bytes, sizeof(rand_bytes)); + wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, + (u8*)&mac_addr); + } +#ifdef WLMESH + else if (apstamode == ISTAMESH_MODE) { + cur_if = &apsta_params->if_info[IF_VIF]; + wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_STA, NULL); + } + else if (apstamode == IMESHAP_MODE) { + cur_if = &apsta_params->if_info[IF_VIF]; + wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL); + } + else if (apstamode == ISTAAPMESH_MODE) { + cur_if = &apsta_params->if_info[IF_VIF]; + wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL); + cur_if = &apsta_params->if_info[IF_VIF2]; + wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_STA, NULL); + } + else if (apstamode == IMESHAPAP_MODE) { + cur_if = &apsta_params->if_info[IF_VIF]; + wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL); + cur_if = &apsta_params->if_info[IF_VIF2]; + wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL); + } +#endif /* WLMESH */ + } static int @@ -1596,11 +1869,10 @@ wl_ext_isam_init(struct net_device *dev, char *command, int total_len) int i; if (apsta_params->init) { - ANDROID_ERROR(("%s: don't init twice\n", __FUNCTION__)); + AEXT_ERROR(dev->name, "don't init twice\n"); return -1; } - - ANDROID_TRACE(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len)); + AEXT_TRACE(dev->name, "command=%s, len=%d\n", command, total_len); pick_tmp = command; param = bcmstrtok(&pick_tmp, " ", 0); // skip iapsta_init @@ -1615,45 +1887,44 @@ wl_ext_isam_init(struct net_device *dev, char *command, int total_len) } else if (!strcmp(pick_tmp2, "ap")) { apsta_params->apstamode = IAPONLY_MODE; } else if (!strcmp(pick_tmp2, "sta-ap")) { - apsta_params->apstamode = IAPSTA_MODE; + apsta_params->apstamode = ISTAAP_MODE; + } else if (!strcmp(pick_tmp2, "sta-sta")) { + apsta_params->apstamode = ISTASTA_MODE; + apsta_params->vsdb = TRUE; } else if (!strcmp(pick_tmp2, "ap-ap")) { apsta_params->apstamode = IDUALAP_MODE; } else if (!strcmp(pick_tmp2, "sta-ap-ap")) { apsta_params->apstamode = ISTAAPAP_MODE; -#ifdef WLMESH - } else if (!strcmp(pick_tmp2, "mesh")) { - apsta_params->apstamode = IMESHONLY_MODE; - } else if (!strcmp(pick_tmp2, "mesh-sta") || - !strcmp(pick_tmp2, "sta-mesh")) { - apsta_params->apstamode = IMESHSTA_MODE; - } else if (!strcmp(pick_tmp2, "mesh-ap") || - !strcmp(pick_tmp2, "ap-mesh")) { - apsta_params->apstamode = IMESHAP_MODE; - } else if (!strcmp(pick_tmp2, "mesh-ap-sta") || - !strcmp(pick_tmp2, "sta-ap-mesh") || - !strcmp(pick_tmp2, "sta-mesh-ap")) { - apsta_params->apstamode = IMESHAPSTA_MODE; - } else if (!strcmp(pick_tmp2, "mesh-ap-ap") || - !strcmp(pick_tmp2, "ap-ap-mesh")) { - apsta_params->apstamode = IMESHAPAP_MODE; -#endif } else if (!strcmp(pick_tmp2, "apsta")) { - apsta_params->apstamode = IAPSTA_MODE; + apsta_params->apstamode = ISTAAP_MODE; apsta_params->if_info[IF_PIF].ifmode = ISTA_MODE; apsta_params->if_info[IF_VIF].ifmode = IAP_MODE; } else if (!strcmp(pick_tmp2, "dualap")) { apsta_params->apstamode = IDUALAP_MODE; apsta_params->if_info[IF_PIF].ifmode = IAP_MODE; apsta_params->if_info[IF_VIF].ifmode = IAP_MODE; - } else if (!strcmp(pick_tmp2, "gosta")) { + } else if (!strcmp(pick_tmp2, "sta-go") || + !strcmp(pick_tmp2, "gosta")) { if (!FW_SUPPORTED(dhd, p2p)) { return -1; } - apsta_params->apstamode = IGOSTA_MODE; + apsta_params->apstamode = ISTAGO_MODE; apsta_params->if_info[IF_PIF].ifmode = ISTA_MODE; apsta_params->if_info[IF_VIF].ifmode = IAP_MODE; +#ifdef WLMESH + } else if (!strcmp(pick_tmp2, "mesh")) { + apsta_params->apstamode = IMESHONLY_MODE; + } else if (!strcmp(pick_tmp2, "sta-mesh")) { + apsta_params->apstamode = ISTAMESH_MODE; + } else if (!strcmp(pick_tmp2, "sta-ap-mesh")) { + apsta_params->apstamode = ISTAAPMESH_MODE; + } else if (!strcmp(pick_tmp2, "mesh-ap")) { + apsta_params->apstamode = IMESHAP_MODE; + } else if (!strcmp(pick_tmp2, "mesh-ap-ap")) { + apsta_params->apstamode = IMESHAPAP_MODE; +#endif /* WLMESH */ } else { - ANDROID_ERROR(("%s: mode [sta|ap|sta-ap|ap-ap]\n", __FUNCTION__)); + AEXT_ERROR(dev->name, "mode [sta|ap|sta-ap|ap-ap]\n"); return -1; } pch = bcmstrtok(&pick_tmp2, " -", 0); @@ -1665,12 +1936,12 @@ wl_ext_isam_init(struct net_device *dev, char *command, int total_len) #ifdef WLMESH else if (!strcmp(pch, "mesh")) { if (dhd->conf->fw_type != FW_TYPE_MESH) { - ANDROID_ERROR(("%s: wrong fw type\n", __FUNCTION__)); + AEXT_ERROR(dev->name, "wrong fw type\n"); return -1; } apsta_params->if_info[i].ifmode = IMESH_MODE; } -#endif +#endif /* WLMESH */ pch = bcmstrtok(&pick_tmp2, " -", 0); } } @@ -1678,14 +1949,7 @@ wl_ext_isam_init(struct net_device *dev, char *command, int total_len) else if (!strcmp(param, "rsdb")) { pch = bcmstrtok(&pick_tmp, " ", 0); if (pch) { - if (!strcmp(pch, "y")) { - apsta_params->rsdb = TRUE; - } else if (!strcmp(pch, "n")) { - apsta_params->rsdb = FALSE; - } else { - ANDROID_ERROR(("%s: rsdb [y|n]\n", __FUNCTION__)); - return -1; - } + apsta_params->rsdb = (int)simple_strtol(pch, NULL, 0); } } else if (!strcmp(param, "vsdb")) { pch = bcmstrtok(&pick_tmp, " ", 0); @@ -1695,7 +1959,7 @@ wl_ext_isam_init(struct net_device *dev, char *command, int total_len) } else if (!strcmp(pch, "n")) { apsta_params->vsdb = FALSE; } else { - ANDROID_ERROR(("%s: vsdb [y|n]\n", __FUNCTION__)); + AEXT_ERROR(dev->name, "vsdb [y|n]\n"); return -1; } } @@ -1704,6 +1968,13 @@ wl_ext_isam_init(struct net_device *dev, char *command, int total_len) if (pch) { apsta_params->csa = (int)simple_strtol(pch, NULL, 0); } +#if defined(WLMESH) && defined(WL_ESCAN) + } else if (!strcmp(param, "macs")) { + pch = bcmstrtok(&pick_tmp, " ", 0); + if (pch) { + apsta_params->macs = (int)simple_strtol(pch, NULL, 0); + } +#endif /* WLMESH && WL_ESCAN */ } else if (!strcmp(param, "ifname")) { pch = NULL; pick_tmp2 = bcmstrtok(&pick_tmp, " ", 0); @@ -1718,7 +1989,7 @@ wl_ext_isam_init(struct net_device *dev, char *command, int total_len) if (pch) strcpy(apsta_params->if_info[IF_VIF].ifname, pch); else { - ANDROID_ERROR(("%s: vifname [wlan1]\n", __FUNCTION__)); + AEXT_ERROR(dev->name, "vifname [wlan1]\n"); return -1; } } @@ -1726,11 +1997,12 @@ wl_ext_isam_init(struct net_device *dev, char *command, int total_len) } if (apsta_params->apstamode == 0) { - ANDROID_ERROR(("%s: mode [sta|ap|sta-ap|ap-ap]\n", __FUNCTION__)); + AEXT_ERROR(dev->name, "mode [sta|ap|sta-ap|ap-ap]\n"); return -1; } wl_ext_iapsta_preinit(dev, apsta_params); + wl_ext_iapsta_intf_add(dev, apsta_params); return 0; } @@ -1856,7 +2128,7 @@ wl_ext_parse_config(struct wl_if_info *cur_if, char *command, char **pick_next) else if (!strcmp(pick_tmp, "bgnac")) cur_if->bgnmode = IEEE80211BGNAC; else { - ANDROID_ERROR(("%s: bgnmode [b|g|bg|bgn|bgnac]\n", __FUNCTION__)); + AEXT_ERROR(cur_if->dev->name, "bgnmode [b|g|bg|bgn|bgnac]\n"); return -1; } } else if (!strcmp(row->name, " hidden ")) { @@ -1865,7 +2137,7 @@ wl_ext_parse_config(struct wl_if_info *cur_if, char *command, char **pick_next) else if (!strcmp(pick_tmp, "y")) cur_if->hidden = 1; else { - ANDROID_ERROR(("%s: hidden [y|n]\n", __FUNCTION__)); + AEXT_ERROR(cur_if->dev->name, "hidden [y|n]\n"); return -1; } } else if (!strcmp(row->name, " maxassoc ")) { @@ -1886,8 +2158,7 @@ wl_ext_parse_config(struct wl_if_info *cur_if, char *command, char **pick_next) else if (!strcmp(pick_tmp, "sae")) cur_if->amode = AUTH_SAE; else { - ANDROID_ERROR(("%s: amode [open|shared|wpapsk|wpa2psk|wpawpa2psk]\n", - __FUNCTION__)); + AEXT_ERROR(cur_if->dev->name, "amode [open|shared|wpapsk|wpa2psk|wpawpa2psk]\n"); return -1; } } else if (!strcmp(row->name, " emode ")) { @@ -1902,8 +2173,7 @@ wl_ext_parse_config(struct wl_if_info *cur_if, char *command, char **pick_next) else if (!strcmp(pick_tmp, "tkipaes")) cur_if->emode = ENC_TKIPAES; else { - ANDROID_ERROR(("%s: emode [none|wep|tkip|aes|tkipaes]\n", - __FUNCTION__)); + AEXT_ERROR(cur_if->dev->name, "emode [none|wep|tkip|aes|tkipaes]\n"); return -1; } } else if (!strcmp(row->name, " key ")) { @@ -1929,18 +2199,20 @@ wl_ext_iapsta_config(struct net_device *dev, char *command, int total_len) char *pch, *pch2, *pick_tmp, *pick_next=NULL, *param; struct wl_apsta_params *apsta_params = dhd->iapsta_params; char ifname[IFNAMSIZ+1]; - struct wl_if_info *cur_if = NULL; + struct wl_if_info *cur_if = NULL, *tmp_if = NULL; if (!apsta_params->init) { - ANDROID_ERROR(("%s: please init first\n", __FUNCTION__)); + AEXT_ERROR(dev->name, "please init first\n"); return -1; } - ANDROID_TRACE(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len)); + AEXT_TRACE(dev->name, "command=%s, len=%d\n", command, total_len); pick_tmp = command; param = bcmstrtok(&pick_tmp, " ", 0); // skip iapsta_config + mutex_lock(&apsta_params->usr_sync); + while (pick_tmp != NULL) { memset(ifname, 0, IFNAMSIZ+1); if (!strncmp(pick_tmp, "ifname ", strlen("ifname "))) { @@ -1949,87 +2221,62 @@ wl_ext_iapsta_config(struct net_device *dev, char *command, int total_len) if (pch && pch2) { strncpy(ifname, pch, pch2-pch); } else { - ANDROID_ERROR(("%s: ifname [wlanX]\n", __FUNCTION__)); - return -1; + AEXT_ERROR(dev->name, "ifname [wlanX]\n"); + ret = -1; + break; } for (i=0; iif_info[i].dev && - !strcmp(apsta_params->if_info[i].dev->name, ifname)) { - cur_if = &apsta_params->if_info[i]; + tmp_if = &apsta_params->if_info[i]; + if (tmp_if->dev && !strcmp(tmp_if->dev->name, ifname)) { + cur_if = tmp_if; break; } } if (!cur_if) { - ANDROID_ERROR(("%s: wrong ifname=%s in apstamode=%d\n", - __FUNCTION__, ifname, apsta_params->apstamode)); - return -1; + AEXT_ERROR(dev->name, "wrong ifname=%s in apstamode=%d\n", + ifname, apsta_params->apstamode); + ret = -1; + break; } ret = wl_ext_parse_config(cur_if, pick_tmp, &pick_next); if (ret) - return -1; + break; pick_tmp = pick_next; } else { - ANDROID_ERROR(("%s: first arg must be ifname\n", __FUNCTION__)); - return -1; + AEXT_ERROR(dev->name, "first arg must be ifname\n"); + ret = -1; + break; } } - return 0; + mutex_unlock(&apsta_params->usr_sync); + + return ret; } static int -wl_ext_isam_status(struct net_device *dev, char *command, int total_len) +wl_ext_assoclist(struct net_device *dev, char *data, char *command, + int total_len) { - struct dhd_pub *dhd = dhd_get_pub(dev); - struct wl_apsta_params *apsta_params = dhd->iapsta_params; - int i; - bool now_if; - struct wl_if_info *tmp_if; - uint16 chan = 0; - wlc_ssid_t ssid = { 0, {0} }; - char amode[16], emode[16]; - int bytes_written=0; + int ret = 0, i, maxassoc = 0, bytes_written = 0; + char mac_buf[MAX_NUM_OF_ASSOCLIST * + sizeof(struct ether_addr) + sizeof(uint)] = {0}; + struct maclist *assoc_maclist = (struct maclist *)mac_buf; - if (apsta_params->init == FALSE) { - return 0; + assoc_maclist->count = htod32(MAX_NUM_OF_ASSOCLIST); + ret = wl_ext_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, sizeof(mac_buf), 0); + if (ret) + return -1; + maxassoc = dtoh32(assoc_maclist->count); + bytes_written += snprintf(command+bytes_written, total_len, + "%2s: %12s", + "no", "------addr------"); + for (i=0; iea[i]); } - ANDROID_INFO(("****************************\n")); - ANDROID_INFO(("%s: apstamode=%d\n", __FUNCTION__, apsta_params->apstamode)); - for (i=0; iif_info[i]; - if (dev == tmp_if->dev) - now_if = TRUE; - if (tmp_if->dev) { - chan = wl_ext_get_chan(apsta_params, tmp_if->dev); - if (chan) { - wl_ext_ioctl(tmp_if->dev, WLC_GET_SSID, &ssid, sizeof(ssid), 0); - wl_ext_get_amode(tmp_if, amode); - wl_ext_get_emode(tmp_if, emode); - ANDROID_INFO(("%s[%c-%c%s]: chan %3d, amode %s, emode %s, SSID \"%s\"\n", - tmp_if->ifname, tmp_if->prefix, chan?'E':'D', - now_if?"*":" ", chan, amode, emode, ssid.SSID)); - if (command) - bytes_written += snprintf(command+bytes_written, total_len, - "%s[%c-%c%s]: chan %3d, amode %s, emode %s, SSID \"%s\"\n", - tmp_if->ifname, tmp_if->prefix, chan?'E':'D', - now_if?"*":" ", chan, amode, emode, ssid.SSID); - } else { - ANDROID_INFO(("%s[%c-%c%s]:\n", - tmp_if->ifname, tmp_if->prefix, chan?'E':'D', now_if?"*":" ")); - if (command) - bytes_written += snprintf(command+bytes_written, total_len, "%s[%c-%c%s]:\n", - tmp_if->ifname, tmp_if->prefix, chan?'E':'D', now_if?"*":" "); - } - } - } - ANDROID_INFO(("****************************\n")); - return bytes_written; } @@ -2047,7 +2294,7 @@ wl_mesh_print_peer_info(mesh_peer_info_ext_t *mpi_ext, " %5s : %4s : %4s : %11s : %4s", "no", "------addr------ ", "l.aid", "state", "p.aid", "mppid", "llid", "plid", "entry_state", "rssi"); - for (count = 0; count < peer_results_count; count++) { + for (count=0; count < peer_results_count; count++) { if (mpi_ext->entry_state != MESH_SELF_PEER_ENTRY_STATE_TIMEDOUT) { bytes_written += snprintf(command+bytes_written, total_len, "\n%2d: %pM : 0x%4x : %6s : 0x%4x :" @@ -2064,18 +2311,37 @@ wl_mesh_print_peer_info(mesh_peer_info_ext_t *mpi_ext, mpi_ext->rssi); } else { bytes_written += snprintf(command+bytes_written, total_len, - "\n%d: %pM : %6s : %5s : %6s :" + "\n%2d: %pM : %6s : %5s : %6s :" " %5s : %4s : %4s : %11s : %4s", - count, &mpi_ext->ea, " NA ", " NA ", " NA ", + count, &mpi_ext->ea, " NA ", " NA ", " NA ", " NA ", " NA ", " NA ", " TIMEDOUT ", " NA "); } mpi_ext++; } - ANDROID_INFO(("\n%s\n", command)); return bytes_written; } +static int +wl_mesh_get_peer_results(struct net_device *dev, char *buf, int len) +{ + int indata, inlen; + mesh_peer_info_dump_t *peer_results; + int ret; + + memset(buf, 0, len); + peer_results = (mesh_peer_info_dump_t *)buf; + indata = htod32(len); + inlen = 4; + ret = wl_ext_iovar_getbuf(dev, "mesh_peer_status", &indata, inlen, buf, len, NULL); + if (!ret) { + peer_results = (mesh_peer_info_dump_t *)buf; + ret = peer_results->count; + } + + return ret; +} + static int wl_ext_mesh_peer_status(struct net_device *dev, char *data, char *command, int total_len) @@ -2084,50 +2350,505 @@ wl_ext_mesh_peer_status(struct net_device *dev, char *data, char *command, struct wl_apsta_params *apsta_params = dhd->iapsta_params; int i; struct wl_if_info *cur_if; - int bytes_written = -1; - int indata, inlen; - char *dump_buf; mesh_peer_info_dump_t *peer_results; mesh_peer_info_ext_t *mpi_ext; - - if (apsta_params->init == FALSE) { - ANDROID_ERROR(("%s: please init first\n", __FUNCTION__)); - return -1; - } + char *peer_buf = NULL; + int peer_len = WLC_IOCTL_MAXLEN; + int dump_written = 0, ret; if (!data) { - dump_buf = kmalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL); - if (dump_buf == NULL) { - ANDROID_ERROR(("Failed to allocate buffer of %d bytes\n", WLC_IOCTL_MAXLEN)); + peer_buf = kmalloc(peer_len, GFP_KERNEL); + if (peer_buf == NULL) { + AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n", + peer_len); return -1; } - memset(dump_buf, 0, WLC_IOCTL_MAXLEN); - for (i=0; iif_info[i]; - if (dev == cur_if->dev && cur_if->ifmode == IMESH_MODE) { - peer_results = (mesh_peer_info_dump_t *)dump_buf; - indata = htod32(WLC_IOCTL_MAXLEN); - inlen = 4; - bytes_written = wl_ext_iovar_getbuf(dev, "mesh_peer_status", - &indata, inlen, dump_buf, WLC_IOCTL_MAXLEN, NULL); - if (!bytes_written) { - peer_results = (mesh_peer_info_dump_t *)dump_buf; + if (cur_if && dev == cur_if->dev && cur_if->ifmode == IMESH_MODE) { + memset(peer_buf, 0, peer_len); + ret = wl_mesh_get_peer_results(dev, peer_buf, peer_len); + if (ret >= 0) { + peer_results = (mesh_peer_info_dump_t *)peer_buf; mpi_ext = (mesh_peer_info_ext_t *)peer_results->mpi_ext; - bytes_written = wl_mesh_print_peer_info(mpi_ext, peer_results->count, - command, total_len); + dump_written += wl_mesh_print_peer_info(mpi_ext, + peer_results->count, command+dump_written, + total_len-dump_written); } - } else if (dev == cur_if->dev) { - ANDROID_ERROR(("%s: %s[%c] is not mesh interface\n", - __FUNCTION__, cur_if->ifname, cur_if->prefix)); + } else if (cur_if && dev == cur_if->dev) { + AEXT_ERROR(dev->name, "[%s][%c] is not mesh interface\n", + cur_if->ifname, cur_if->prefix); } } - kfree(dump_buf); } - - return bytes_written; + + if (peer_buf) + kfree(peer_buf); + return dump_written; +} + +#ifdef WL_ESCAN +#define WL_MESH_DELAY_SCAN_MS 3000 +static void +wl_mesh_timer(unsigned long data) +{ + wl_event_msg_t msg; + struct wl_if_info *mesh_if = (struct wl_if_info *)data; + struct dhd_pub *dhd; + + if (!mesh_if) { + AEXT_ERROR("wlan", "mesh_if is not ready\n"); + return; + } + + if (!mesh_if->dev) { + AEXT_ERROR("wlan", "ifidx %d is not ready\n", mesh_if->ifidx); + return; + } + dhd = dhd_get_pub(mesh_if->dev); + + bzero(&msg, sizeof(wl_event_msg_t)); + AEXT_TRACE(mesh_if->dev->name, "timer expired\n"); + + msg.ifidx = mesh_if->ifidx; + msg.event_type = hton32(WLC_E_RESERVED); + msg.reason = 0xFFFFFFFF; + wl_ext_event_send(dhd->event_params, &msg, NULL); +} + +static void +wl_mesh_set_timer(struct wl_if_info *mesh_if, uint timeout) +{ + AEXT_TRACE(mesh_if->dev->name, "timeout=%d\n", timeout); + + if (timer_pending(&mesh_if->delay_scan)) + del_timer_sync(&mesh_if->delay_scan); + + if (timeout) { + if (timer_pending(&mesh_if->delay_scan)) + del_timer_sync(&mesh_if->delay_scan); + mod_timer(&mesh_if->delay_scan, jiffies + msecs_to_jiffies(timeout)); + } +} + +static struct wl_if_info * +wl_ext_if_enabled(struct wl_apsta_params *apsta_params, ifmode_t ifmode) +{ + struct wl_if_info *tmp_if, *target_if = NULL; + int i; + + for (i=0; iif_info[i]; + if (tmp_if && tmp_if->ifmode == ifmode && + wl_get_isam_status(tmp_if, IF_READY)) { + if (wl_ext_get_chan(apsta_params, tmp_if->dev)) { + target_if = tmp_if; + break; + } + } + } + + return target_if; +} + +static int +wl_mesh_clear_vndr_ie(struct net_device *dev, uchar *oui) +{ + char *vndr_ie_buf = NULL; + vndr_ie_setbuf_t *vndr_ie = NULL; + ie_getbuf_t vndr_ie_tmp; + char *iovar_buf = NULL; + int err = -1, i; + vndr_ie_buf_t *vndr_ie_dump = NULL; + uchar *iebuf; + vndr_ie_info_t *ie_info; + vndr_ie_t *ie; + + vndr_ie_buf = kzalloc(WLC_IOCTL_SMLEN, GFP_KERNEL); + if (!vndr_ie_buf) { + AEXT_ERROR(dev->name, "IE memory alloc failed\n"); + err = -ENOMEM; + goto exit; + } + + iovar_buf = kzalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL); + if (!iovar_buf) { + AEXT_ERROR(dev->name, "iovar_buf alloc failed\n"); + err = -ENOMEM; + goto exit; + } + + memset(iovar_buf, 0, WLC_IOCTL_MEDLEN); + vndr_ie_tmp.pktflag = (uint32) -1; + vndr_ie_tmp.id = (uint8) DOT11_MNG_PROPR_ID; + err = wl_ext_iovar_getbuf(dev, "vndr_ie", &vndr_ie_tmp, sizeof(vndr_ie_tmp), + iovar_buf, WLC_IOCTL_MEDLEN, NULL); + if (err) + goto exit; + + vndr_ie_dump = (vndr_ie_buf_t *)iovar_buf; + if (!vndr_ie_dump->iecount) + goto exit; + + iebuf = (uchar *)&vndr_ie_dump->vndr_ie_list[0]; + for (i=0; iiecount; i++) { + ie_info = (vndr_ie_info_t *) iebuf; + ie = &ie_info->vndr_ie_data; + if (memcmp(ie->oui, oui, 3)) + memset(ie->oui, 0, 3); + iebuf += sizeof(uint32) + ie->len + VNDR_IE_HDR_LEN; + } + + vndr_ie = (vndr_ie_setbuf_t *) vndr_ie_buf; + strncpy(vndr_ie->cmd, "del", VNDR_IE_CMD_LEN - 1); + vndr_ie->cmd[VNDR_IE_CMD_LEN - 1] = '\0'; + memcpy(&vndr_ie->vndr_ie_buffer, vndr_ie_dump, WLC_IOCTL_SMLEN-VNDR_IE_CMD_LEN-1); + + memset(iovar_buf, 0, WLC_IOCTL_MEDLEN); + err = wl_ext_iovar_setbuf(dev, "vndr_ie", vndr_ie, WLC_IOCTL_SMLEN, iovar_buf, + WLC_IOCTL_MEDLEN, NULL); + +exit: + if (vndr_ie) { + kfree(vndr_ie); + } + if (iovar_buf) { + kfree(iovar_buf); + } + return err; +} + +static int +wl_mesh_clear_mesh_info(struct wl_apsta_params *apsta_params, + struct wl_if_info *mesh_if, bool scan) +{ + struct wl_mesh_params *mesh_info = &apsta_params->mesh_info; + uchar mesh_oui[]={0x00, 0x22, 0xf4}; + int ret; + + AEXT_TRACE(mesh_if->dev->name, "Enter\n"); + + ret = wl_mesh_clear_vndr_ie(mesh_if->dev, mesh_oui); + memset(mesh_info, 0, sizeof(struct wl_mesh_params)); + if (scan) { + mesh_info->scan_channel = wl_ext_get_chan(apsta_params, mesh_if->dev); + wl_mesh_set_timer(mesh_if, 100); + } + + return ret; +} + +static int +wl_mesh_update_vndr_ie(struct wl_apsta_params *apsta_params, + struct wl_if_info *mesh_if) +{ + struct wl_mesh_params *mesh_info = &apsta_params->mesh_info; + char vndr_ie[64]; + uchar mesh_oui[]={0x00, 0x22, 0xf4}; + int bytes_written = 0; + int ret; + + wl_mesh_clear_vndr_ie(mesh_if->dev, mesh_oui); + + bytes_written += snprintf(vndr_ie+bytes_written, sizeof(vndr_ie), + "0x%02x%02x%02x", mesh_oui[0], mesh_oui[1], mesh_oui[2]); + + bytes_written += snprintf(vndr_ie+bytes_written, sizeof(vndr_ie), + "%02d%02d%02x%02x%02x%02x%02x%02x", MESH_INFO_MASTER_BSSID, ETHER_ADDR_LEN, + ((u8 *)(&mesh_info->master_bssid))[0], ((u8 *)(&mesh_info->master_bssid))[1], + ((u8 *)(&mesh_info->master_bssid))[2], ((u8 *)(&mesh_info->master_bssid))[3], + ((u8 *)(&mesh_info->master_bssid))[4], ((u8 *)(&mesh_info->master_bssid))[5]); + + bytes_written += snprintf(vndr_ie+bytes_written, sizeof(vndr_ie), + "%02x%02x%02x", MESH_INFO_MASTER_CHANNEL, 1, mesh_info->master_channel); + + bytes_written += snprintf(vndr_ie+bytes_written, sizeof(vndr_ie), + "%02x%02x%02x", MESH_INFO_HOP_CNT, 1, mesh_info->hop_cnt); + + bytes_written += snprintf(vndr_ie+bytes_written, sizeof(vndr_ie), + "%02d%02d%02x%02x%02x%02x%02x%02x", MESH_INFO_PEER_BSSID, ETHER_ADDR_LEN, + ((u8 *)(&mesh_info->peer_bssid))[0], ((u8 *)(&mesh_info->peer_bssid))[1], + ((u8 *)(&mesh_info->peer_bssid))[2], ((u8 *)(&mesh_info->peer_bssid))[3], + ((u8 *)(&mesh_info->peer_bssid))[4], ((u8 *)(&mesh_info->peer_bssid))[5]); + + ret = wl_ext_add_del_ie(mesh_if->dev, VNDR_IE_BEACON_FLAG|VNDR_IE_PRBRSP_FLAG, + vndr_ie, "add"); + if (!ret) { + AEXT_INFO(mesh_if->dev->name, "mbssid=%pM, mchannel=%d, hop=%d, pbssid=%pM\n", + &mesh_info->master_bssid, mesh_info->master_channel, mesh_info->hop_cnt, + &mesh_info->peer_bssid); + } + + return ret; +} + +static bool +wl_mesh_update_master_info(struct wl_apsta_params *apsta_params, + struct wl_if_info *mesh_if) +{ + struct wl_mesh_params *mesh_info = &apsta_params->mesh_info; + struct wl_if_info *sta_if = NULL; + bool updated = FALSE; + + sta_if = wl_ext_if_enabled(apsta_params, ISTA_MODE); + if (sta_if) { + wldev_ioctl(mesh_if->dev, WLC_GET_BSSID, &mesh_info->master_bssid, + ETHER_ADDR_LEN, 0); + mesh_info->master_channel = wl_ext_get_chan(apsta_params, mesh_if->dev); + mesh_info->hop_cnt = 1; + memcpy(&mesh_info->peer_bssid, &mesh_info->master_bssid, ETHER_ADDR_LEN); + wl_mesh_update_vndr_ie(apsta_params, mesh_if); + updated = TRUE; + } + + return updated; +} + +static uint +wl_mesh_update_mesh_info(struct wl_apsta_params *apsta_params, + struct wl_if_info *mesh_if) +{ + struct wl_mesh_params *mesh_info = &apsta_params->mesh_info, peer_mesh_info; + uint32 count = 0; + char *dump_buf = NULL; + mesh_peer_info_dump_t *peer_results; + mesh_peer_info_ext_t *mpi_ext; + struct ether_addr bssid; + bool updated = FALSE; + uint16 cur_chan; + + dump_buf = kmalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL); + if (dump_buf == NULL) { + AEXT_ERROR(mesh_if->dev->name, "Failed to allocate buffer of %d bytes\n", + WLC_IOCTL_MAXLEN); + return FALSE; + } + count = wl_mesh_get_peer_results(mesh_if->dev, dump_buf, WLC_IOCTL_MAXLEN); + if (count > 0) { + memset(&bssid, 0 , ETHER_ADDR_LEN); + wldev_ioctl(mesh_if->dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, 0); + peer_results = (mesh_peer_info_dump_t *)dump_buf; + mpi_ext = (mesh_peer_info_ext_t *)peer_results->mpi_ext; + for (count = 0; count < peer_results->count; count++) { + if (mpi_ext->entry_state != MESH_SELF_PEER_ENTRY_STATE_TIMEDOUT && + mpi_ext->peer_info.state == MESH_PEERING_ESTAB) { + memset(&peer_mesh_info, 0 , sizeof(struct wl_mesh_params)); + wl_escan_mesh_info(mesh_if->dev, mesh_if->escan, + &mpi_ext->ea, &peer_mesh_info); + if ((memcmp(&peer_mesh_info.peer_bssid, &bssid, ETHER_ADDR_LEN)) && + peer_mesh_info.hop_cnt && (mesh_info->hop_cnt == 0 || + peer_mesh_info.hop_cnt <= mesh_info->hop_cnt)) { + memcpy(&mesh_info->master_bssid, &peer_mesh_info.master_bssid, + ETHER_ADDR_LEN); + mesh_info->master_channel = peer_mesh_info.master_channel; + mesh_info->hop_cnt = peer_mesh_info.hop_cnt+1; + memcpy(&mesh_info->peer_bssid, &mpi_ext->ea, ETHER_ADDR_LEN); + mesh_info->channel = peer_mesh_info.channel; + updated = TRUE; + } + } + mpi_ext++; + } + if (updated) + wl_mesh_update_vndr_ie(apsta_params, mesh_if); + } + + if (!mesh_info->hop_cnt) { + wlc_ssid_t cur_ssid; + char sec[32]; + bool sae = FALSE; + memset(&peer_mesh_info, 0, sizeof(struct wl_mesh_params)); + wl_ext_ioctl(mesh_if->dev, WLC_GET_SSID, &cur_ssid, sizeof(cur_ssid), 0); + wl_ext_get_sec(mesh_if->dev, mesh_if->ifmode, sec, sizeof(sec)); + if (strnicmp(sec, "sae/sae", strlen("sae/sae")) == 0) + sae = TRUE; + cur_chan = wl_ext_get_chan(apsta_params, mesh_if->dev); + wl_escan_mesh_peer(mesh_if->dev, mesh_if->escan, &cur_ssid, cur_chan, + sae, &peer_mesh_info); + + if (peer_mesh_info.hop_cnt && peer_mesh_info.channel && + (cur_chan != peer_mesh_info.channel)) { + WL_MSG(mesh_if->ifname, "moving channel %d -> %d\n", + cur_chan, peer_mesh_info.channel); + wl_ext_disable_iface(mesh_if->dev, mesh_if->ifname); + mesh_if->channel = peer_mesh_info.channel; + wl_ext_enable_iface(mesh_if->dev, mesh_if->ifname, 500); + } + } + + if (dump_buf) + kfree(dump_buf); + return mesh_info->hop_cnt; +} + +static void +wl_mesh_event_handler( struct wl_apsta_params *apsta_params, + struct wl_if_info *mesh_if, const wl_event_msg_t *e, void *data) +{ + struct wl_mesh_params *mesh_info = &apsta_params->mesh_info; + uint32 event_type = ntoh32(e->event_type); + uint32 status = ntoh32(e->status); + uint32 reason = ntoh32(e->reason); + wlc_ssid_t ssid; + int ret; + + if (wl_get_isam_status(mesh_if, AP_CREATED) && + ((event_type == WLC_E_SET_SSID && status == WLC_E_STATUS_SUCCESS) || + (event_type == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS && + reason == WLC_E_REASON_INITIAL_ASSOC))) { + if (!wl_mesh_update_master_info(apsta_params, mesh_if)) { + mesh_info->scan_channel = wl_ext_get_chan(apsta_params, mesh_if->dev); + wl_mesh_set_timer(mesh_if, WL_MESH_DELAY_SCAN_MS); + } + } + else if ((event_type == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS) || + (event_type == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS && + reason == WLC_E_REASON_DEAUTH)) { + wl_mesh_clear_mesh_info(apsta_params, mesh_if, FALSE); + } + else if (wl_get_isam_status(mesh_if, AP_CREATED) && + (event_type == WLC_E_ASSOC_IND || event_type == WLC_E_REASSOC_IND) && + reason == DOT11_SC_SUCCESS) { + mesh_info->scan_channel = wl_ext_get_chan(apsta_params, mesh_if->dev); + wl_mesh_set_timer(mesh_if, 100); + } + else if (event_type == WLC_E_DISASSOC_IND || event_type == WLC_E_DEAUTH_IND || + (event_type == WLC_E_DEAUTH && reason != DOT11_RC_RESERVED)) { + if (!memcmp(&mesh_info->peer_bssid, &e->addr, ETHER_ADDR_LEN)) + wl_mesh_clear_mesh_info(apsta_params, mesh_if, TRUE); + } + else if (wl_get_isam_status(mesh_if, AP_CREATED) && + event_type == WLC_E_RESERVED && reason == 0xFFFFFFFF) { + if (!wl_mesh_update_master_info(apsta_params, mesh_if)) { + wl_ext_ioctl(mesh_if->dev, WLC_GET_SSID, &ssid, sizeof(ssid), 0); + ret = wl_escan_set_scan(mesh_if->dev, apsta_params->dhd, &ssid, + mesh_info->scan_channel, FALSE); + if (ret) + wl_mesh_set_timer(mesh_if, WL_MESH_DELAY_SCAN_MS); + } + } + else if (wl_get_isam_status(mesh_if, AP_CREATED) && + ((event_type == WLC_E_ESCAN_RESULT && status == WLC_E_STATUS_SUCCESS) || + (event_type == WLC_E_ESCAN_RESULT && + (status == WLC_E_STATUS_ABORT || status == WLC_E_STATUS_NEWSCAN || + status == WLC_E_STATUS_11HQUIET || status == WLC_E_STATUS_CS_ABORT || + status == WLC_E_STATUS_NEWASSOC || status == WLC_E_STATUS_TIMEOUT)))) { + if (!wl_mesh_update_master_info(apsta_params, mesh_if)) { + if (!wl_mesh_update_mesh_info(apsta_params, mesh_if)) { + mesh_info->scan_channel = 0; + wl_mesh_set_timer(mesh_if, WL_MESH_DELAY_SCAN_MS); + } + } + } +} + +static void +wl_mesh_escan_detach(dhd_pub_t *dhd, struct wl_if_info *mesh_if) +{ + AEXT_TRACE(mesh_if->dev->name, "Enter\n"); + + del_timer_sync(&mesh_if->delay_scan); + + if (mesh_if->escan) { + mesh_if->escan = NULL; + } +} + +static int +wl_mesh_escan_attach(dhd_pub_t *dhd, struct wl_if_info *mesh_if) +{ + AEXT_TRACE(mesh_if->dev->name, "Enter\n"); + + mesh_if->escan = dhd->escan; + init_timer_compat(&mesh_if->delay_scan, wl_mesh_timer, mesh_if); + + return 0; +} +#endif /* WL_ESCAN */ +#endif /* WLMESH */ + +static int +wl_ext_isam_status(struct net_device *dev, char *command, int total_len) +{ + struct dhd_pub *dhd = dhd_get_pub(dev); + struct wl_apsta_params *apsta_params = dhd->iapsta_params; + int i; + bool now_if; + struct wl_if_info *tmp_if; + uint16 chan = 0; + wlc_ssid_t ssid = { 0, {0} }; + struct ether_addr bssid; + scb_val_t scb_val; + char sec[32]; + u32 chanspec = 0; + char *dump_buf = NULL; + int dump_len = WLC_IOCTL_MEDLEN; + int dump_written = 0; + + if (command || android_msg_level & ANDROID_INFO_LEVEL) { + if (command) { + dump_buf = command; + dump_len = total_len; + } else { + dump_buf = kmalloc(dump_len, GFP_KERNEL); + if (dump_buf == NULL) { + AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n", + dump_len); + return -1; + } + } + dump_written += snprintf(dump_buf+dump_written, dump_len, + "apstamode=%d", apsta_params->apstamode); + for (i=0; iif_info[i]; + if (dev == tmp_if->dev) + now_if = TRUE; + if (tmp_if->dev) { + chan = wl_ext_get_chan(apsta_params, tmp_if->dev); + if (chan) { + wl_ext_ioctl(tmp_if->dev, WLC_GET_SSID, &ssid, sizeof(ssid), 0); + wldev_ioctl(tmp_if->dev, WLC_GET_BSSID, &bssid, sizeof(bssid), 0); + wldev_ioctl(tmp_if->dev, WLC_GET_RSSI, &scb_val, + sizeof(scb_val_t), 0); + chanspec = wl_ext_get_chanspec(apsta_params, tmp_if->dev); + wl_ext_get_sec(tmp_if->dev, tmp_if->ifmode, sec, sizeof(sec)); + dump_written += snprintf(dump_buf+dump_written, dump_len, + "\n[dhd-%s][%c-%c%s]: bssid=%pM, chan=%3d(0x%x), " + "rssi=%3d, sec=%-15s, SSID=\"%s\"", + tmp_if->ifname, tmp_if->prefix, chan?'E':'D', + now_if?"*":" ", &bssid, chan, chanspec, + dtoh32(scb_val.val), sec, ssid.SSID); + if (tmp_if->ifmode == IAP_MODE) { + dump_written += snprintf(dump_buf+dump_written, dump_len, "\n"); + dump_written += wl_ext_assoclist(tmp_if->dev, NULL, + dump_buf+dump_written, dump_len-dump_written); + } +#ifdef WLMESH + else if (tmp_if->ifmode == IMESH_MODE) { + dump_written += snprintf(dump_buf+dump_written, dump_len, "\n"); + dump_written += wl_ext_mesh_peer_status(tmp_if->dev, NULL, + dump_buf+dump_written, dump_len-dump_written); + } +#endif /* WLMESH */ + } else { + dump_written += snprintf(dump_buf+dump_written, dump_len, + "\n[dhd-%s][%c-%c%s]:", + tmp_if->ifname, tmp_if->prefix, chan?'E':'D', + now_if?"*":" "); + } + } + } + AEXT_INFO(dev->name, "%s\n", dump_buf); + } + + if (!command && dump_buf) + kfree(dump_buf); + return dump_written; } -#endif static int wl_ext_if_down(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if) @@ -2140,7 +2861,7 @@ wl_ext_if_down(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if) } bss_setbuf; apstamode_t apstamode = apsta_params->apstamode; - printf("%s: %s[%c] Turning off\n", __FUNCTION__, cur_if->ifname, cur_if->prefix); + WL_MSG(cur_if->ifname, "[%c] Turning off...\n", cur_if->prefix); if (cur_if->ifmode == ISTA_MODE) { wl_ext_ioctl(cur_if->dev, WLC_DISASSOC, NULL, 0, 1); @@ -2158,6 +2879,7 @@ wl_ext_if_down(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if) wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf), iovar_buf, WLC_IOCTL_SMLEN, NULL); } + wl_clr_isam_status(cur_if, AP_CREATED); return 0; } @@ -2172,24 +2894,28 @@ wl_ext_if_up(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if) } bss_setbuf; apstamode_t apstamode = apsta_params->apstamode; chanspec_t fw_chspec; + u32 timeout; + wlc_ssid_t ssid = { 0, {0} }; + uint16 chan = 0; if (cur_if->ifmode != IAP_MODE) { - ANDROID_ERROR(("%s: Wrong ifmode on %s[%c]\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix)); + AEXT_ERROR(cur_if->ifname, "Wrong ifmode\n"); return 0; } - if (cur_if->channel >= 52 && cur_if->channel <= 148) { - printf("%s: %s[%c] skip DFS channel %d\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix, cur_if->channel); + if (wl_ext_dfs_chan(apsta_params, cur_if->dev, cur_if->channel)) { + WL_MSG(cur_if->ifname, "[%c] skip DFS channel %d\n", + cur_if->prefix, cur_if->channel); return 0; } - printf("%s: %s[%c] Turning on\n", __FUNCTION__, cur_if->ifname, cur_if->prefix); + WL_MSG(cur_if->ifname, "[%c] Turning on...\n", cur_if->prefix); wl_ext_set_chanspec(cur_if->dev, apsta_params->ioctl_ver, cur_if->channel, &fw_chspec); + wl_clr_isam_status(cur_if, AP_CREATED); + wl_set_isam_status(cur_if, AP_CREATING); if (apstamode == IAPONLY_MODE) { wl_ext_ioctl(cur_if->dev, WLC_UP, NULL, 0, 1); } else { @@ -2199,17 +2925,31 @@ wl_ext_if_up(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if) sizeof(bss_setbuf), iovar_buf, WLC_IOCTL_SMLEN, NULL); } - OSL_SLEEP(500); + timeout = wait_event_interruptible_timeout(apsta_params->netif_change_event, + wl_get_isam_status(cur_if, AP_CREATED), + msecs_to_jiffies(MAX_AP_LINK_WAIT_TIME)); + if (timeout <= 0 || !wl_get_isam_status(cur_if, AP_CREATED)) { + wl_ext_if_down(apsta_params, cur_if); + WL_MSG(cur_if->ifname, "[%c] failed to up with SSID: \"%s\"\n", + cur_if->prefix, cur_if->ssid); + } else { + wl_ext_ioctl(cur_if->dev, WLC_GET_SSID, &ssid, sizeof(ssid), 0); + chan = wl_ext_get_chan(apsta_params, cur_if->dev); + WL_MSG(cur_if->ifname, "[%c] enabled with SSID: \"%s\" on channel %d\n", + cur_if->prefix, ssid.SSID, chan); + } + wl_clr_isam_status(cur_if, AP_CREATING); + wl_ext_isam_status(cur_if->dev, NULL, 0); return 0; } static int -wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len) +wl_ext_disable_iface(struct net_device *dev, char *ifname) { struct dhd_pub *dhd = dhd_get_pub(dev); - char *pch, *pick_tmp, *param; + int i; s8 iovar_buf[WLC_IOCTL_SMLEN]; wlc_ssid_t ssid = { 0, {0} }; scb_val_t scbval; @@ -2219,46 +2959,22 @@ wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len) } bss_setbuf; struct wl_apsta_params *apsta_params = dhd->iapsta_params; apstamode_t apstamode = apsta_params->apstamode; - char ifname[IFNAMSIZ+1]; - struct wl_if_info *cur_if = NULL; - int i; - - if (!apsta_params->init) { - ANDROID_ERROR(("%s: please init first\n", __FUNCTION__)); - return -1; - } - - ANDROID_TRACE(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len)); - - pick_tmp = command; - param = bcmstrtok(&pick_tmp, " ", 0); // skip iapsta_disable - param = bcmstrtok(&pick_tmp, " ", 0); - while (param != NULL) { - if (!strcmp(param, "ifname")) { - pch = bcmstrtok(&pick_tmp, " ", 0); - if (pch) - strcpy(ifname, pch); - else { - ANDROID_ERROR(("%s: ifname [wlanX]\n", __FUNCTION__)); - return -1; - } - } - param = bcmstrtok(&pick_tmp, " ", 0); - } + struct wl_if_info *cur_if = NULL, *tmp_if = NULL; for (i=0; iif_info[i].dev && - !strcmp(apsta_params->if_info[i].dev->name, ifname)) { - cur_if = &apsta_params->if_info[i]; + tmp_if = &apsta_params->if_info[i]; + if (tmp_if->dev && !strcmp(tmp_if->dev->name, ifname)) { + cur_if = tmp_if; break; } } if (!cur_if) { - ANDROID_ERROR(("%s: wrong ifname=%s or dev not ready\n", __FUNCTION__, ifname)); + AEXT_ERROR(dev->name, "wrong ifname=%s or dev not ready\n", ifname); return -1; } - printf("%s: %s[%c] Disabling\n", __FUNCTION__, ifname, cur_if->prefix); + mutex_lock(&apsta_params->usr_sync); + WL_MSG(ifname, "[%c] Disabling...\n", cur_if->prefix); if (cur_if->ifmode == ISTA_MODE) { wl_ext_ioctl(cur_if->dev, WLC_DISASSOC, NULL, 0, 1); @@ -2272,7 +2988,7 @@ wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len) wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); wl_ext_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1); // reset ssid wl_ext_iovar_setint(dev, "mpc", 1); - } else if ((apstamode==IAPSTA_MODE || apstamode==IGOSTA_MODE) && + } else if ((apstamode==ISTAAP_MODE || apstamode==ISTAGO_MODE) && cur_if->ifmode == IAP_MODE) { bss_setbuf.cfg = 0xffffffff; bss_setbuf.val = htod32(0); @@ -2293,7 +3009,7 @@ wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len) dhd_wlfc_deinit(dhd); } } -#endif +#endif /* BCMSDIO */ #endif /* PROP_TXSTATUS_VSDB */ } else if (apstamode == IDUALAP_MODE) { @@ -2302,42 +3018,94 @@ wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len) wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf), iovar_buf, WLC_IOCTL_SMLEN, NULL); #ifdef WLMESH - } else if (apstamode == IMESHSTA_MODE || apstamode == IMESHAP_MODE || - apstamode == IMESHAPSTA_MODE || apstamode == IMESHAPAP_MODE || + } else if (apstamode == ISTAMESH_MODE || apstamode == IMESHAP_MODE || + apstamode == ISTAAPMESH_MODE || apstamode == IMESHAPAP_MODE || apstamode == ISTAAPAP_MODE) { bss_setbuf.cfg = 0xffffffff; bss_setbuf.val = htod32(0); wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf), iovar_buf, WLC_IOCTL_SMLEN, NULL); -#endif +#endif /* WLMESH */ + } +#ifdef WLMESH + if ((cur_if->ifmode == IMESH_MODE) && + (apstamode == ISTAMESH_MODE || apstamode == IMESHAP_MODE || + apstamode == ISTAAPMESH_MODE || apstamode == IMESHAPAP_MODE)) { + int scan_assoc_time = DHD_SCAN_ASSOC_ACTIVE_TIME; + for (i=0; iif_info[i]; + if (tmp_if->dev && tmp_if->ifmode == ISTA_MODE) { + wl_ext_ioctl(tmp_if->dev, WLC_SET_SCAN_CHANNEL_TIME, + &scan_assoc_time, sizeof(scan_assoc_time), 1); + } + } + } +#endif /* WLMESH */ + + wl_clr_isam_status(cur_if, AP_CREATED); + + WL_MSG(ifname, "[%c] Exit\n", cur_if->prefix); + mutex_unlock(&apsta_params->usr_sync); + return 0; +} + +static int +wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len) +{ + int ret = 0; + char *pch, *pick_tmp, *param; + char ifname[IFNAMSIZ+1]; + + AEXT_TRACE(dev->name, "command=%s, len=%d\n", command, total_len); + + pick_tmp = command; + param = bcmstrtok(&pick_tmp, " ", 0); // skip iapsta_disable + param = bcmstrtok(&pick_tmp, " ", 0); + while (param != NULL) { + if (!strcmp(param, "ifname")) { + pch = bcmstrtok(&pick_tmp, " ", 0); + if (pch) { + strcpy(ifname, pch); + ret = wl_ext_disable_iface(dev, ifname); + if (ret) + return ret; + } + else { + AEXT_ERROR(dev->name, "ifname [wlanX]\n"); + return -1; + } + } + param = bcmstrtok(&pick_tmp, " ", 0); } - cur_if->ifstate = IF_STATE_DISALBE; + return ret; +} - printf("%s: %s[%c] disabled\n", __FUNCTION__, ifname, cur_if->prefix); - - return 0; +static bool +wl_ext_diff_band(uint16 chan1, uint16 chan2) +{ + if ((chan1 <= CH_MAX_2G_CHANNEL && chan2 > CH_MAX_2G_CHANNEL) || + (chan1 > CH_MAX_2G_CHANNEL && chan2 <= CH_MAX_2G_CHANNEL)) { + return TRUE; + } + return FALSE; } static uint16 wl_ext_get_vsdb_chan(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if, struct wl_if_info *target_if) { - uint16 target_chan = 0, cur_chan = cur_if->channel, cur_working_chan = 0; + uint16 target_chan = 0, cur_chan = cur_if->channel; target_chan = wl_ext_get_chan(apsta_params, target_if->dev); if (target_chan) { - ANDROID_INFO(("%s: cur_chan=%d, target_chan=%d\n", __FUNCTION__, - cur_chan, target_chan)); - if ((cur_chan <= CH_MAX_2G_CHANNEL && target_chan > CH_MAX_2G_CHANNEL) || - (cur_chan > CH_MAX_2G_CHANNEL && target_chan <= CH_MAX_2G_CHANNEL)) { - if (!FW_SUPPORTED(apsta_params->dhd, rsdb) || !apsta_params->rsdb) + AEXT_INFO(cur_if->ifname, "cur_chan=%d, target_chan=%d\n", + cur_chan, target_chan); + if (wl_ext_diff_band(cur_chan, target_chan)) { + if (!apsta_params->rsdb) return target_chan; - cur_working_chan = wl_ext_get_chan(apsta_params, cur_if->dev); - if (cur_working_chan) - return cur_working_chan; } else { - if (target_chan != cur_chan) + if (cur_chan != target_chan) return target_chan; } } @@ -2346,35 +3114,71 @@ wl_ext_get_vsdb_chan(struct wl_apsta_params *apsta_params, } static int -wl_ext_triger_csa(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if) +wl_ext_rsdb_core_conflict(struct wl_apsta_params *apsta_params, + struct wl_if_info *cur_if) +{ + struct wl_if_info *tmp_if; + uint16 cur_chan, tmp_chan; + int i; + + if (apsta_params->rsdb) { + cur_chan = wl_ext_get_chan(apsta_params, cur_if->dev); + for (i=0; iif_info[i]; + if (tmp_if != cur_if && wl_get_isam_status(tmp_if, IF_READY) && + tmp_if->prio > cur_if->prio) { + tmp_chan = wl_ext_get_chan(apsta_params, tmp_if->dev); + if (!tmp_chan) + continue; + if (wl_ext_diff_band(cur_chan, tmp_chan) && + wl_ext_diff_band(cur_chan, cur_if->channel)) + return TRUE; + else if (!wl_ext_diff_band(cur_chan, tmp_chan) && + wl_ext_diff_band(cur_chan, cur_if->channel)) + return TRUE; + } + } + } + return FALSE; +} + +static int +wl_ext_trigger_csa(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if) { s8 iovar_buf[WLC_IOCTL_SMLEN]; + bool core_conflict = FALSE; if (apsta_params->csa & CSA_DRV_BIT && (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE)) { if (!cur_if->channel) { - printf("%s: %s[%c] skip channel %d\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix, cur_if->channel); - } else if (cur_if->channel >= 52 && cur_if->channel <= 148) { - printf("%s: %s[%c] skip DFS channel %d\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix, cur_if->channel); + WL_MSG(cur_if->ifname, "[%c] skip channel %d\n", + cur_if->prefix, cur_if->channel); + } else if (wl_ext_dfs_chan(apsta_params, cur_if->dev, cur_if->channel)) { + WL_MSG(cur_if->ifname, "[%c] skip DFS channel %d\n", + cur_if->prefix, cur_if->channel); wl_ext_if_down(apsta_params, cur_if); } else { wl_chan_switch_t csa_arg; memset(&csa_arg, 0, sizeof(csa_arg)); csa_arg.mode = 1; csa_arg.count = 3; - csa_arg.chspec = wl_ext_get_chanspec(apsta_params, cur_if->dev, + csa_arg.chspec = wl_ext_chan_to_chanspec(apsta_params, cur_if->dev, cur_if->channel); - if (csa_arg.chspec) { - printf("%s: Trigger CSA to channel %d(0x%x)\n", __FUNCTION__, - cur_if->channel, csa_arg.chspec); + core_conflict = wl_ext_rsdb_core_conflict(apsta_params, cur_if); + if (core_conflict) { + WL_MSG(cur_if->ifname, "[%c] Skip CSA due to rsdb core conflict\n", + cur_if->prefix); + } else if (csa_arg.chspec) { + WL_MSG(cur_if->ifname, "[%c] Trigger CSA to channel %d(0x%x)\n", + cur_if->prefix, cur_if->channel, csa_arg.chspec); + wl_set_isam_status(cur_if, AP_CREATING); wl_ext_iovar_setbuf(cur_if->dev, "csa", &csa_arg, sizeof(csa_arg), iovar_buf, sizeof(iovar_buf), NULL); OSL_SLEEP(500); + wl_clr_isam_status(cur_if, AP_CREATING); wl_ext_isam_status(cur_if->dev, NULL, 0); } else { - printf("%s: fail to get chanspec\n", __FUNCTION__); + AEXT_ERROR(cur_if->ifname, "fail to get chanspec\n"); } } } @@ -2400,7 +3204,7 @@ wl_ext_move_cur_channel(struct wl_apsta_params *apsta_params, max_prio = cur_if->prio; for (i=0; iif_info[i]; - if (tmp_if->ifstate >= IF_STATE_INIT && cur_if != tmp_if && + if (cur_if != tmp_if && wl_get_isam_status(tmp_if, IF_READY) && tmp_if->prio > max_prio) { tmp_chan = wl_ext_get_vsdb_chan(apsta_params, cur_if, tmp_if); if (tmp_chan) { @@ -2410,18 +3214,25 @@ wl_ext_move_cur_channel(struct wl_apsta_params *apsta_params, } } } - if (target_chan) { - printf("%s: %s[%c] channel=%d => %s[%c] channel=%d\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix, cur_if->channel, - target_if->ifname, target_if->prefix, target_chan); - cur_if->channel = target_chan; + tmp_chan = wl_ext_get_chan(apsta_params, cur_if->dev); + if (apsta_params->rsdb && tmp_chan && + wl_ext_diff_band(tmp_chan, target_chan)) { + WL_MSG(cur_if->ifname, "[%c] keep on current channel %d\n", + cur_if->prefix, tmp_chan); + cur_if->channel = 0; + } else { + WL_MSG(cur_if->ifname, "[%c] channel=%d => %s[%c] channel=%d\n", + cur_if->prefix, cur_if->channel, + target_if->ifname, target_if->prefix, target_chan); + cur_if->channel = target_chan; + } } exit: if ((cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) && - (cur_if->channel >= 52 && cur_if->channel <= 148)) { - printf("%s: %s[%c] skip DFS channel %d\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix, cur_if->channel); + wl_ext_dfs_chan(apsta_params, cur_if->dev, cur_if->channel)) { + WL_MSG(cur_if->ifname, "[%c] skip DFS channel %d\n", + cur_if->prefix, cur_if->channel); cur_if->channel = 0; } @@ -2445,7 +3256,7 @@ wl_ext_move_other_channel(struct wl_apsta_params *apsta_params, cur_prio = cur_if->prio; for (i=0; iif_info[i]; - if (tmp_if->ifstate >= IF_STATE_INIT && cur_if != tmp_if && + if (cur_if != tmp_if && wl_get_isam_status(tmp_if, IF_READY) && tmp_if->prio >= max_prio && tmp_if->prio <= cur_prio) { tmp_chan = wl_ext_get_vsdb_chan(apsta_params, cur_if, tmp_if); if (tmp_chan) { @@ -2457,29 +3268,29 @@ wl_ext_move_other_channel(struct wl_apsta_params *apsta_params, } if (target_if) { - printf("%s: %s channel=%d => %s channel=%d\n", __FUNCTION__, - target_if->ifname, target_chan, cur_if->ifname, cur_if->channel); + WL_MSG(target_if->ifname, "channel=%d => %s channel=%d\n", + target_chan, cur_if->ifname, cur_if->channel); target_if->channel = cur_if->channel; if (apsta_params->csa == 0) { wl_ext_if_down(apsta_params, target_if); wl_ext_move_other_channel(apsta_params, dev, target_if); if (target_if->ifmode == ISTA_MODE || target_if->ifmode == IMESH_MODE) { - wl_ext_enable_iface(target_if->dev, target_if->ifname); + wl_ext_enable_iface(target_if->dev, target_if->ifname, 0); } else if (target_if->ifmode == IAP_MODE) { wl_ext_if_up(apsta_params, target_if); } } else { - wl_ext_triger_csa(apsta_params, target_if); + wl_ext_trigger_csa(apsta_params, target_if); } } } static int -wl_ext_enable_iface(struct net_device *dev, char *ifname) +wl_ext_enable_iface(struct net_device *dev, char *ifname, int wait_up) { struct dhd_pub *dhd = dhd_get_pub(dev); - int i; + int i, ret = 0; s8 iovar_buf[WLC_IOCTL_SMLEN]; wlc_ssid_t ssid = { 0, {0} }; chanspec_t fw_chspec; @@ -2489,38 +3300,53 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) } bss_setbuf; struct wl_apsta_params *apsta_params = dhd->iapsta_params; apstamode_t apstamode = apsta_params->apstamode; - struct wl_if_info *cur_if = NULL; + struct wl_if_info *cur_if = NULL, *tmp_if = NULL; uint16 cur_chan; struct wl_conn_info conn_info; + u32 timeout; for (i=0; iif_info[i].dev && - !strcmp(apsta_params->if_info[i].dev->name, ifname)) { - cur_if = &apsta_params->if_info[i]; + tmp_if = &apsta_params->if_info[i]; + if (tmp_if->dev && !strcmp(tmp_if->dev->name, ifname)) { + cur_if = tmp_if; break; } } if (!cur_if) { - ANDROID_ERROR(("%s: wrong ifname=%s or dev not ready\n", __FUNCTION__, ifname)); + AEXT_ERROR(dev->name, "wrong ifname=%s or dev not ready\n", ifname); return -1; } - printf("%s: %s[%c] Enabling\n", __FUNCTION__, ifname, cur_if->prefix); + mutex_lock(&apsta_params->usr_sync); + + if (cur_if->ifmode == ISTA_MODE) { + wl_set_isam_status(cur_if, STA_CONNECTING); + } else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) { + wl_set_isam_status(cur_if, AP_CREATING); + } wl_ext_isam_status(cur_if->dev, NULL, 0); + WL_MSG(ifname, "[%c] Enabling...\n", cur_if->prefix); + + wl_ext_check_other_enabling(apsta_params, cur_if); wl_ext_move_cur_channel(apsta_params, dev, cur_if); if (!cur_if->channel && cur_if->ifmode != ISTA_MODE) { - return 0; + goto exit; } cur_chan = wl_ext_get_chan(apsta_params, cur_if->dev); if (cur_chan) { - ANDROID_INFO(("%s: Associated!\n", __FUNCTION__)); + AEXT_INFO(cur_if->ifname, "Associated\n"); if (cur_chan != cur_if->channel) { - wl_ext_triger_csa(apsta_params, cur_if); + wl_ext_trigger_csa(apsta_params, cur_if); } - return 0; + goto exit; + } + if (cur_if->ifmode == ISTA_MODE) { + wl_clr_isam_status(cur_if, STA_CONNECTED); + } else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) { + wl_clr_isam_status(cur_if, AP_CREATED); } wl_ext_move_other_channel(apsta_params, dev, cur_if); @@ -2535,9 +3361,9 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) memcpy(ssid.SSID, cur_if->ssid, ssid.SSID_len); if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) { wl_ext_iovar_setint(dev, "mpc", 0); - if (apstamode == IAPONLY_MODE) { + if (apstamode == IAPONLY_MODE || apstamode == IMESHONLY_MODE) { wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); - } else if (apstamode==IAPSTA_MODE || apstamode==IGOSTA_MODE) { + } else if (apstamode==ISTAAP_MODE || apstamode==ISTAGO_MODE) { wl_ext_iovar_setbuf_bsscfg(cur_if->dev, "ssid", &ssid, sizeof(ssid), iovar_buf, WLC_IOCTL_SMLEN, cur_if->bssidx, NULL); } @@ -2566,7 +3392,7 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) cur_if->channel = cur_chan; #else cur_if->channel = 1; -#endif +#endif /* WL_CFG80211 */ } wl_ext_set_chanspec(cur_if->dev, apsta_params->ioctl_ver, cur_if->channel, &fw_chspec); @@ -2589,8 +3415,8 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) if (cur_if->hidden > 0) { wl_ext_ioctl(cur_if->dev, WLC_SET_CLOSED, &cur_if->hidden, sizeof(cur_if->hidden), 1); - printf("%s: Broadcast SSID: %s\n", __FUNCTION__, - cur_if->hidden ? "OFF":"ON"); + WL_MSG(ifname, "[%c] Broadcast SSID: %s\n", + cur_if->prefix, cur_if->hidden ? "OFF":"ON"); } } @@ -2599,7 +3425,7 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) } else if (apstamode == IAPONLY_MODE) { wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1); wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); - } else if (apstamode == IAPSTA_MODE || apstamode == IGOSTA_MODE) { + } else if (apstamode == ISTAAP_MODE || apstamode == ISTAGO_MODE) { if (cur_if->ifmode == ISTA_MODE) { wl_ext_connect(cur_if->dev, &conn_info); } else { @@ -2618,7 +3444,7 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) #endif /* ARP_OFFLOAD_SUPPORT */ #ifdef PROP_TXSTATUS_VSDB #if defined(BCMSDIO) - if (!FW_SUPPORTED(dhd, rsdb) && !disable_proptx) { + if (!(FW_SUPPORTED(dhd, rsdb)) && !disable_proptx) { bool enabled; dhd_wlfc_get_enable(dhd, &enabled); if (!enabled) { @@ -2626,7 +3452,7 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); } } -#endif +#endif /* BCMSDIO */ #endif /* PROP_TXSTATUS_VSDB */ } } @@ -2638,12 +3464,12 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) } else if (cur_if->ifmode == IAP_MODE) { wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1); } else { - printf("%s: wrong ifmode %d\n", __FUNCTION__, cur_if->ifmode); + AEXT_ERROR(cur_if->ifname, "wrong ifmode %d\n", cur_if->ifmode); } #ifdef WLMESH } else if (apstamode == IMESHONLY_MODE || - apstamode == IMESHSTA_MODE || apstamode == IMESHAP_MODE || - apstamode == IMESHAPSTA_MODE || apstamode == IMESHAPAP_MODE) { + apstamode == ISTAMESH_MODE || apstamode == IMESHAP_MODE || + apstamode == ISTAAPMESH_MODE || apstamode == IMESHAPAP_MODE) { if (cur_if->ifmode == ISTA_MODE) { wl_ext_connect(cur_if->dev, &conn_info); } else if (cur_if->ifmode == IAP_MODE) { @@ -2658,36 +3484,59 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) join_params.params.chanspec_num = 1; wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &join_params, sizeof(join_params), 1); } else { - printf("%s: wrong ifmode %d\n", __FUNCTION__, cur_if->ifmode); + AEXT_ERROR(cur_if->ifname, "wrong ifmode %d\n", cur_if->ifmode); + } +#endif /* WLMESH */ + } + + if (wait_up) { + OSL_SLEEP(wait_up); + } else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) { + timeout = wait_event_interruptible_timeout(apsta_params->netif_change_event, + wl_get_isam_status(cur_if, AP_CREATED), + msecs_to_jiffies(MAX_AP_LINK_WAIT_TIME)); + if (timeout <= 0 || !wl_get_isam_status(cur_if, AP_CREATED)) { + wl_ext_disable_iface(dev, cur_if->ifname); + WL_MSG(ifname, "[%c] failed to enable with SSID: \"%s\"\n", + cur_if->prefix, cur_if->ssid); + ret = -1; + } + } + + if (wl_get_isam_status(cur_if, AP_CREATED) && + (cur_if->ifmode == IMESH_MODE || cur_if->ifmode == IAP_MODE) && + (apstamode == ISTAAP_MODE || apstamode == ISTAAPAP_MODE || + apstamode == ISTAMESH_MODE || apstamode == IMESHAP_MODE || + apstamode == ISTAAPMESH_MODE || apstamode == IMESHAPAP_MODE)) { + int scan_assoc_time = 80; + for (i=0; iif_info[i]; + if (tmp_if->dev && tmp_if->ifmode == ISTA_MODE) { + wl_ext_ioctl(tmp_if->dev, WLC_SET_SCAN_CHANNEL_TIME, + &scan_assoc_time, sizeof(scan_assoc_time), 1); + } } -#endif } - OSL_SLEEP(500); - printf("%s: %s[%c] enabled with SSID: \"%s\"\n", __FUNCTION__, - ifname, cur_if->prefix, cur_if->ssid); wl_ext_isam_status(cur_if->dev, NULL, 0); - cur_if->ifstate = IF_STATE_ENABLE; - - return 0; +exit: + if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) { + wl_clr_isam_status(cur_if, AP_CREATING); + } + WL_MSG(ifname, "[%c] Exit\n", cur_if->prefix); + mutex_unlock(&apsta_params->usr_sync); + return ret; } static int wl_ext_iapsta_enable(struct net_device *dev, char *command, int total_len) { - struct dhd_pub *dhd = dhd_get_pub(dev); int ret = 0; char *pch, *pick_tmp, *param; - struct wl_apsta_params *apsta_params = dhd->iapsta_params; char ifname[IFNAMSIZ+1]; - if (!apsta_params->init) { - ANDROID_ERROR(("%s: please init first\n", __FUNCTION__)); - return -1; - } - - ANDROID_TRACE(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len)); + AEXT_TRACE(dev->name, "command=%s, len=%d\n", command, total_len); pick_tmp = command; param = bcmstrtok(&pick_tmp, " ", 0); // skip iapsta_enable @@ -2697,11 +3546,11 @@ wl_ext_iapsta_enable(struct net_device *dev, char *command, int total_len) pch = bcmstrtok(&pick_tmp, " ", 0); if (pch) { strcpy(ifname, pch); - ret = wl_ext_enable_iface(dev, ifname); + ret = wl_ext_enable_iface(dev, ifname, 0); if (ret) return ret; } else { - ANDROID_ERROR(("%s: ifname [wlanX]\n", __FUNCTION__)); + AEXT_ERROR(dev->name, "ifname [wlanX]\n"); return -1; } } @@ -2716,47 +3565,13 @@ wl_ext_iapsta_alive_preinit(struct net_device *dev) { struct dhd_pub *dhd = dhd_get_pub(dev); struct wl_apsta_params *apsta_params = dhd->iapsta_params; - struct wl_if_info *cur_if; - int i; if (apsta_params->init == TRUE) { - ANDROID_ERROR(("%s: don't init twice\n", __FUNCTION__)); + AEXT_ERROR(dev->name, "don't init twice\n"); return -1; } - ANDROID_TRACE(("%s: Enter\n", __FUNCTION__)); - - for (i=0; iif_info[i]; - if (i == 1 && !strlen(cur_if->ifname)) - strcpy(cur_if->ifname, "wlan1"); - if (i == 2 && !strlen(cur_if->ifname)) - strcpy(cur_if->ifname, "wlan2"); - if (cur_if->ifmode == ISTA_MODE) { - cur_if->channel = 0; - cur_if->maxassoc = -1; - cur_if->ifstate = IF_STATE_INIT; - cur_if->prio = PRIO_STA; - cur_if->prefix = 'S'; - snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_sta"); - } else if (cur_if->ifmode == IAP_MODE) { - cur_if->channel = 1; - cur_if->maxassoc = -1; - cur_if->ifstate = IF_STATE_INIT; - cur_if->prio = PRIO_AP; - cur_if->prefix = 'A'; - snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_ap"); -#ifdef WLMESH - } else if (cur_if->ifmode == IMESH_MODE) { - cur_if->channel = 1; - cur_if->maxassoc = -1; - cur_if->ifstate = IF_STATE_INIT; - cur_if->prio = PRIO_MESH; - cur_if->prefix = 'M'; - snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_mesh"); -#endif - } - } + AEXT_TRACE(dev->name, "Enter\n"); apsta_params->init = TRUE; @@ -2767,8 +3582,10 @@ int wl_ext_iapsta_alive_postinit(struct net_device *dev) { struct dhd_pub *dhd = dhd_get_pub(dev); - s32 apsta = 0; struct wl_apsta_params *apsta_params = dhd->iapsta_params; + s32 apsta = 0; + struct wl_if_info *cur_if; + int i; wl_ext_iovar_getint(dev, "apsta", &apsta); if (apsta == 1) { @@ -2780,154 +3597,175 @@ wl_ext_iapsta_alive_postinit(struct net_device *dev) apsta_params->if_info[IF_PIF].ifmode = IAP_MODE; op_mode = DHD_FLAG_HOSTAP_MODE; } - // fix me: how to check it's IAPSTA_MODE or IDUALAP_MODE? + // fix me: how to check it's ISTAAP_MODE or IDUALAP_MODE? wl_ext_get_ioctl_ver(dev, &apsta_params->ioctl_ver); - printf("%s: apstamode=%d\n", __FUNCTION__, apsta_params->apstamode); + WL_MSG(dev->name, "apstamode=%d\n", apsta_params->apstamode); + + for (i=0; iif_info[i]; + if (i == 1 && !strlen(cur_if->ifname)) + strcpy(cur_if->ifname, "wlan1"); + if (i == 2 && !strlen(cur_if->ifname)) + strcpy(cur_if->ifname, "wlan2"); + if (cur_if->ifmode == ISTA_MODE) { + cur_if->channel = 0; + cur_if->maxassoc = -1; + wl_set_isam_status(cur_if, IF_READY); + cur_if->prio = PRIO_STA; + cur_if->prefix = 'S'; + snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_sta"); + } else if (cur_if->ifmode == IAP_MODE) { + cur_if->channel = 1; + cur_if->maxassoc = -1; + wl_set_isam_status(cur_if, IF_READY); + cur_if->prio = PRIO_AP; + cur_if->prefix = 'A'; + snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_ap"); +#ifdef WLMESH + } else if (cur_if->ifmode == IMESH_MODE) { + cur_if->channel = 1; + cur_if->maxassoc = -1; + wl_set_isam_status(cur_if, IF_READY); + cur_if->prio = PRIO_MESH; + cur_if->prefix = 'M'; + snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_mesh"); +#endif /* WLMESH */ + } + } return op_mode; } -#if defined(WL_WIRELESS_EXT) -static bool -wl_ext_conn_status_str(uint32 event_type, - uint32 status, uint32 reason, char* stringBuf, uint buflen) -{ - int i; - - typedef struct conn_fail_event_map_t { - uint32 inEvent; /* input: event type to match */ - uint32 inStatus; /* input: event status code to match */ - uint32 inReason; /* input: event reason code to match */ - } conn_fail_event_map_t; - - /* Map of WLC_E events to connection failure strings */ -# define WL_IW_DONT_CARE 9999 - const conn_fail_event_map_t event_map [] = { - /* inEvent inStatus inReason */ - {WLC_E_LINK, WL_IW_DONT_CARE, WL_IW_DONT_CARE}, - {WLC_E_DEAUTH, WL_IW_DONT_CARE, WL_IW_DONT_CARE}, - {WLC_E_DEAUTH_IND, WL_IW_DONT_CARE, WL_IW_DONT_CARE}, - {WLC_E_DISASSOC, WL_IW_DONT_CARE, WL_IW_DONT_CARE}, - {WLC_E_DISASSOC_IND, WL_IW_DONT_CARE, WL_IW_DONT_CARE}, - {WLC_E_OVERLAY_REQ, WL_IW_DONT_CARE, WL_IW_DONT_CARE}, - {WLC_E_ASSOC_IND, WL_IW_DONT_CARE, DOT11_SC_SUCCESS}, - {WLC_E_REASSOC_IND, WL_IW_DONT_CARE, DOT11_SC_SUCCESS}, - }; - - /* Search the event map table for a matching event */ - for (i = 0; i < sizeof(event_map)/sizeof(event_map[0]); i++) { - const conn_fail_event_map_t* row = &event_map[i]; - if (row->inEvent == event_type && - (row->inStatus == status || row->inStatus == WL_IW_DONT_CARE) && - (row->inReason == reason || row->inReason == WL_IW_DONT_CARE)) { - memset(stringBuf, 0, buflen); - snprintf(stringBuf, buflen, "isam_event event=%d reason=%d", - event_type, reason); - return TRUE; - } - } - - return FALSE; -} -#endif /* WL_WIRELESS_EXT */ - int -wl_ext_iapsta_event(struct net_device *dev, wl_event_msg_t *e, void* data) +wl_ext_iapsta_event(struct net_device *dev, + struct wl_apsta_params *apsta_params, wl_event_msg_t *e, void* data) { - struct dhd_pub *dhd = dhd_get_pub(dev); - struct wl_apsta_params *apsta_params = dhd->iapsta_params; - struct wl_if_info *cur_if = NULL; + struct wl_if_info *cur_if = NULL, *tmp_if = NULL; +#if defined(WLMESH) && defined(WL_ESCAN) + struct wl_if_info *mesh_if = NULL; +#endif /* WLMESH && WL_ESCAN */ int i; -#if defined(WL_WIRELESS_EXT) - char extra[IW_CUSTOM_MAX + 1]; - union iwreq_data wrqu; -#endif uint32 event_type = ntoh32(e->event_type); uint32 status = ntoh32(e->status); uint32 reason = ntoh32(e->reason); uint16 flags = ntoh16(e->flags); - if (!apsta_params->init) { - ANDROID_TRACE(("%s: please init first\n", __FUNCTION__)); - return -1; - } - for (i=0; iif_info[i].ifidx == e->ifidx) { - cur_if = &apsta_params->if_info[i]; + tmp_if = &apsta_params->if_info[i]; + if (tmp_if->dev == dev) { + cur_if = tmp_if; break; } } +#if defined(WLMESH) && defined(WL_ESCAN) + for (i=0; iif_info[i]; + if (tmp_if->dev && tmp_if->ifmode == IMESH_MODE) { + mesh_if = tmp_if; + break; + } + } +#endif /* WLMESH && WL_ESCAN */ if (!cur_if || !cur_if->dev) { - ANDROID_ERROR(("%s: %s ifidx %d is not ready\n", __FUNCTION__, - dev->name, e->ifidx)); + AEXT_DBG(dev->name, "ifidx %d is not ready\n", e->ifidx); return -1; } if (cur_if->ifmode == ISTA_MODE) { if (event_type == WLC_E_LINK) { if (!(flags & WLC_EVENT_MSG_LINK)) { - printf("%s: %s[%c] Link Down with %pM\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix, &e->addr); + WL_MSG(cur_if->ifname, + "[%c] Link down with %pM, %s(%d), reason %d\n", + cur_if->prefix, &e->addr, bcmevent_get_name(event_type), + event_type, reason); + wl_clr_isam_status(cur_if, STA_CONNECTED); +#if defined(WLMESH) && defined(WL_ESCAN) + if (mesh_if && apsta_params->macs) + wl_mesh_clear_mesh_info(apsta_params, mesh_if, TRUE); +#endif /* WLMESH && WL_ESCAN */ } else { - printf("%s: %s[%c] Link UP with %pM\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix, &e->addr); + WL_MSG(cur_if->ifname, "[%c] Link UP with %pM\n", + cur_if->prefix, &e->addr); + wl_set_isam_status(cur_if, STA_CONNECTED); +#if defined(WLMESH) && defined(WL_ESCAN) + if (mesh_if && apsta_params->macs) + wl_mesh_update_master_info(apsta_params, mesh_if); +#endif /* WLMESH && WL_ESCAN */ } + wl_clr_isam_status(cur_if, STA_CONNECTING); + wake_up_interruptible(&apsta_params->netif_change_event); + } else if (event_type == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS) { + WL_MSG(cur_if->ifname, + "connect failed event=%d, reason=%d, status=%d\n", + event_type, reason, status); + wl_clr_isam_status(cur_if, STA_CONNECTING); + wake_up_interruptible(&apsta_params->netif_change_event); +#if defined(WLMESH) && defined(WL_ESCAN) + if (mesh_if && apsta_params->macs) + wl_mesh_clear_mesh_info(apsta_params, mesh_if, TRUE); +#endif /* WLMESH && WL_ESCAN */ + } else if (event_type == WLC_E_DEAUTH || event_type == WLC_E_DEAUTH_IND || + event_type == WLC_E_DISASSOC || event_type == WLC_E_DISASSOC_IND) { + WL_MSG(cur_if->ifname, "[%c] Link down with %pM, %s(%d), reason %d\n", + cur_if->prefix, &e->addr, bcmevent_get_name(event_type), + event_type, reason); +#if defined(WLMESH) && defined(WL_ESCAN) + if (mesh_if && apsta_params->macs) + wl_mesh_clear_mesh_info(apsta_params, mesh_if, TRUE); +#endif /* WLMESH && WL_ESCAN */ } } else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) { if ((event_type == WLC_E_SET_SSID && status == WLC_E_STATUS_SUCCESS) || (event_type == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS && reason == WLC_E_REASON_INITIAL_ASSOC)) { - printf("%s: %s[%c] Link up\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix); - } else if ((event_type == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS) || + if (wl_get_isam_status(cur_if, AP_CREATING)) { + WL_MSG(cur_if->ifname, "[%c] Link up (etype=%d)\n", + cur_if->prefix, event_type); + wl_set_isam_status(cur_if, AP_CREATED); + wake_up_interruptible(&apsta_params->netif_change_event); + } else { + wl_set_isam_status(cur_if, AP_CREATED); + WL_MSG(cur_if->ifname, "[%c] Link up w/o creating? (etype=%d)\n", + cur_if->prefix, event_type); + } + } + else if ((event_type == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS) || (event_type == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS && reason == WLC_E_REASON_DEAUTH)) { - printf("%s: %s[%c] Link down\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix); + wl_clr_isam_status(cur_if, AP_CREATED); + WL_MSG(cur_if->ifname, "[%c] Link down, reason=%d\n", + cur_if->prefix, reason); } else if ((event_type == WLC_E_ASSOC_IND || event_type == WLC_E_REASSOC_IND) && reason == DOT11_SC_SUCCESS) { - printf("%s: %s[%c] connected device %pM\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix, &e->addr); - } else if (event_type == WLC_E_DISASSOC_IND) { - printf("%s: %s[%c] disassociated device %pM\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix, &e->addr); - } else if (event_type == WLC_E_DEAUTH_IND || - (event_type == WLC_E_DEAUTH && reason != DOT11_RC_RESERVED)) { - printf("%s: %s[%c] deauthenticated device %pM\n", __FUNCTION__, - cur_if->ifname, cur_if->prefix, &e->addr); + WL_MSG(cur_if->ifname, "[%c] connected device %pM\n", + cur_if->prefix, &e->addr); + wl_ext_isam_status(cur_if->dev, NULL, 0); } - } - -#if defined(WL_WIRELESS_EXT) - memset(extra, 0, sizeof(extra)); - memset(&wrqu, 0, sizeof(wrqu)); - memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN); - wrqu.addr.sa_family = ARPHRD_ETHER; - if (wl_ext_conn_status_str(event_type, status, reason, extra, sizeof(extra))) { - wrqu.data.length = strlen(extra); - wireless_send_event(cur_if->dev, IWEVCUSTOM, &wrqu, extra); - ANDROID_EVENT(("%s: %s[%c] event=%d, status=%d, reason=%d, flags=%d sent up\n", - __FUNCTION__, cur_if->ifname, cur_if->prefix, event_type, status, - reason, flags)); - } else -#endif /* WL_WIRELESS_EXT */ - { - ANDROID_EVENT(("%s: %s[%c] event=%d, status=%d, reason=%d, flags=%d\n", - __FUNCTION__, cur_if->ifname, cur_if->prefix, event_type, status, - reason, flags)); + else if (event_type == WLC_E_DISASSOC_IND || + event_type == WLC_E_DEAUTH_IND || + (event_type == WLC_E_DEAUTH && reason != DOT11_RC_RESERVED)) { + WL_MSG(cur_if->ifname, + "[%c] disconnected device %pM, %s(%d), reason=%d\n", + cur_if->prefix, &e->addr, bcmevent_get_name(event_type), + event_type, reason); + wl_ext_isam_status(cur_if->dev, NULL, 0); + } +#if defined(WLMESH) && defined(WL_ESCAN) + if (cur_if->ifmode == IMESH_MODE && apsta_params->macs) + wl_mesh_event_handler(apsta_params, cur_if, e, data); +#endif /* WLMESH && WL_ESCAN */ } return 0; } u32 -wl_ext_iapsta_update_channel(struct net_device *dev, u32 channel) +wl_ext_iapsta_update_channel(dhd_pub_t *dhd, struct net_device *dev, + u32 channel) { - struct dhd_pub *dhd = dhd_get_pub(dev); struct wl_apsta_params *apsta_params = dhd->iapsta_params; struct wl_if_info *cur_if = NULL, *tmp_if = NULL; int i; @@ -2941,6 +3779,8 @@ wl_ext_iapsta_update_channel(struct net_device *dev, u32 channel) } if (cur_if) { + if (cur_if->ifmode == ISTA_MODE) + wl_set_isam_status(cur_if, STA_CONNECTING); wl_ext_isam_status(cur_if->dev, NULL, 0); cur_if->channel = channel; channel = wl_ext_move_cur_channel(apsta_params, @@ -2953,6 +3793,76 @@ wl_ext_iapsta_update_channel(struct net_device *dev, u32 channel) return channel; } +#ifdef WL_CFG80211 +void +wl_ext_iapsta_update_iftype(struct net_device *net, int ifidx, int wl_iftype) +{ + struct dhd_pub *dhd = dhd_get_pub(net); + struct wl_apsta_params *apsta_params = dhd->iapsta_params; + struct wl_if_info *cur_if = NULL; + + AEXT_TRACE(net->name, "ifidx=%d, wl_iftype=%d\n", ifidx, wl_iftype); + + if (ifidx < MAX_IF_NUM) { + cur_if = &apsta_params->if_info[ifidx]; + } + + if (cur_if) { + if (wl_iftype == WLC_E_IF_ROLE_STA) { + cur_if->ifmode = ISTA_MODE; + cur_if->prio = PRIO_STA; + cur_if->prefix = 'S'; + } else if (wl_iftype == WLC_E_IF_ROLE_AP) { + cur_if->ifmode = IAP_MODE; + cur_if->prio = PRIO_AP; + cur_if->prefix = 'A'; + } + } +} +#endif /* WL_CFG80211 */ + +static void +wl_ext_iapsta_postinit(struct net_device *net, struct wl_if_info *cur_if) +{ + struct dhd_pub *dhd = dhd_get_pub(net); + struct wl_apsta_params *apsta_params = dhd->iapsta_params; + int pm; + + AEXT_TRACE(cur_if->ifname, "ifidx=%d\n", cur_if->ifidx); + if (cur_if->ifidx == 0) { + apsta_params->csa |= CSA_FW_BIT; + if (dhd->conf->chip == BCM4359_CHIP_ID) { + if (dhd->conf->fw_type == FW_TYPE_MESH) + apsta_params->rsdb = 1; + else + apsta_params->rsdb = -1; + } else { + apsta_params->rsdb = 0; + } + if (dhd->conf->fw_type == FW_TYPE_MESH) { + apsta_params->csa |= (CSA_FW_BIT | CSA_DRV_BIT); + } + } else { + if (cur_if->ifmode == ISTA_MODE) { + wl_ext_iovar_setint(cur_if->dev, "roam_off", dhd->conf->roam_off); + wl_ext_iovar_setint(cur_if->dev, "bcn_timeout", dhd->conf->bcn_timeout); + if (dhd->conf->pm >= 0) + pm = dhd->conf->pm; + else + pm = PM_FAST; + wl_ext_ioctl(cur_if->dev, WLC_SET_PM, &pm, sizeof(pm), 1); + wl_ext_iovar_setint(cur_if->dev, "assoc_retry_max", 30); + } +#ifdef WLMESH + else if (cur_if->ifmode == IMESH_MODE) { + pm = 0; + wl_ext_ioctl(cur_if->dev, WLC_SET_PM, &pm, sizeof(pm), 1); + } +#endif /* WLMESH */ + } + +} + int wl_ext_iapsta_attach_name(struct net_device *net, int ifidx) { @@ -2960,19 +3870,19 @@ wl_ext_iapsta_attach_name(struct net_device *net, int ifidx) struct wl_apsta_params *apsta_params = dhd->iapsta_params; struct wl_if_info *cur_if = NULL; - ANDROID_TRACE(("%s: ifidx=%d, %s\n", __FUNCTION__, ifidx, net->name)); + AEXT_TRACE(net->name, "ifidx=%d\n", ifidx); if (ifidx < MAX_IF_NUM) { cur_if = &apsta_params->if_info[ifidx]; } if (ifidx == 0) { - if (dhd->conf->fw_type == FW_TYPE_MESH) { - apsta_params->rsdb = TRUE; - apsta_params->csa = CSA_FW_BIT | CSA_DRV_BIT; - } strcpy(cur_if->ifname, net->name); - } else if (cur_if && cur_if->ifstate == IF_STATE_INIT) { + wl_ext_iapsta_postinit(net, cur_if); + wl_set_isam_status(cur_if, IF_READY); + } else if (cur_if && wl_get_isam_status(cur_if, IF_ADDING)) { strcpy(cur_if->ifname, net->name); - apsta_params->netif_change = TRUE; + wl_ext_iapsta_postinit(net, cur_if); + wl_clr_isam_status(cur_if, IF_ADDING); + wl_set_isam_status(cur_if, IF_READY); wake_up_interruptible(&apsta_params->netif_change_event); } @@ -2986,7 +3896,7 @@ wl_ext_iapsta_attach_netdev(struct net_device *net, int ifidx, uint8 bssidx) struct wl_apsta_params *apsta_params = dhd->iapsta_params; struct wl_if_info *cur_if = NULL, *primary_if; - printf("%s: ifidx=%d, bssidx=%d\n", __FUNCTION__, ifidx, bssidx); + AEXT_TRACE(net->name, "ifidx=%d, bssidx=%d\n", ifidx, bssidx); if (ifidx < MAX_IF_NUM) { cur_if = &apsta_params->if_info[ifidx]; } @@ -2997,19 +3907,28 @@ wl_ext_iapsta_attach_netdev(struct net_device *net, int ifidx, uint8 bssidx) cur_if->dev = net; cur_if->ifidx = ifidx; cur_if->bssidx = bssidx; + cur_if->ifmode = ISTA_MODE; + cur_if->prio = PRIO_STA; + cur_if->prefix = 'S'; + wl_ext_event_register(net, dhd, WLC_E_LAST, wl_ext_iapsta_event, + apsta_params, PRIO_EVENT_IAPSTA); strcpy(cur_if->ifname, net->name); init_waitqueue_head(&apsta_params->netif_change_event); - } else if (cur_if && cur_if->ifstate == IF_STATE_INIT) { + mutex_init(&apsta_params->usr_sync); + } else if (cur_if && wl_get_isam_status(cur_if, IF_ADDING)) { primary_if = &apsta_params->if_info[IF_PIF]; cur_if->dev = net; cur_if->ifidx = ifidx; cur_if->bssidx = bssidx; + wl_ext_event_register(net, dhd, WLC_E_LAST, wl_ext_iapsta_event, + apsta_params, PRIO_EVENT_IAPSTA); if (strlen(cur_if->ifname)) { memset(net->name, 0, sizeof(IFNAMSIZ)); strcpy(net->name, cur_if->ifname); net->name[IFNAMSIZ-1] = '\0'; } - if (apsta_params->apstamode != ISTAAPAP_MODE) { + if (apsta_params->apstamode != ISTAAPAP_MODE && + apsta_params->apstamode != ISTASTA_MODE) { memcpy(net->dev_addr, primary_if->dev->dev_addr, ETHER_ADDR_LEN); net->dev_addr[0] |= 0x02; if (ifidx >= 2) { @@ -3018,15 +3937,11 @@ wl_ext_iapsta_attach_netdev(struct net_device *net, int ifidx, uint8 bssidx) net->dev_addr[5] += (ifidx-1); } } - if (cur_if->ifmode == ISTA_MODE) { - wl_ext_iovar_setint(net, "roam_off", dhd->conf->roam_off); - wl_ext_iovar_setint(net, "bcn_timeout", dhd->conf->bcn_timeout); -#ifdef WLMESH - } else if (cur_if->ifmode == IMESH_MODE) { - int pm = 0; - wl_ext_ioctl(net, WLC_SET_PM, &pm, sizeof(pm), 1); -#endif +#if defined(WLMESH) && defined(WL_ESCAN) + if (cur_if->ifmode == IMESH_MODE && apsta_params->macs) { + wl_mesh_escan_attach(dhd, cur_if); } +#endif /* WLMESH && WL_ESCAN */ } return 0; @@ -3042,27 +3957,40 @@ wl_ext_iapsta_dettach_netdev(struct net_device *net, int ifidx) if (!apsta_params) return 0; - printf("%s: ifidx=%d\n", __FUNCTION__, ifidx); + AEXT_TRACE(net->name, "ifidx=%d\n", ifidx); if (ifidx < MAX_IF_NUM) { cur_if = &apsta_params->if_info[ifidx]; } if (ifidx == 0) { + wl_ext_event_deregister(net, dhd, WLC_E_LAST, wl_ext_iapsta_event); +#if defined(WLMESH) && defined(WL_ESCAN) + if (cur_if->ifmode == IMESH_MODE && apsta_params->macs) { + wl_mesh_escan_detach(dhd, cur_if); + } +#endif /* WLMESH && WL_ESCAN */ memset(apsta_params, 0, sizeof(struct wl_apsta_params)); - } else if (cur_if && cur_if->ifstate >= IF_STATE_INIT) { + } else if (cur_if && wl_get_isam_status(cur_if, IF_READY)) { + wl_ext_event_deregister(net, dhd, WLC_E_LAST, wl_ext_iapsta_event); +#if defined(WLMESH) && defined(WL_ESCAN) + if (cur_if->ifmode == IMESH_MODE && apsta_params->macs) { + wl_mesh_escan_detach(dhd, cur_if); + } +#endif /* WLMESH && WL_ESCAN */ memset(cur_if, 0, sizeof(struct wl_if_info)); } return 0; } -int wl_ext_iapsta_attach(dhd_pub_t *pub) +int +wl_ext_iapsta_attach(dhd_pub_t *pub) { struct wl_apsta_params *iapsta_params; iapsta_params = kzalloc(sizeof(struct wl_apsta_params), GFP_KERNEL); if (unlikely(!iapsta_params)) { - printf("%s: Could not allocate apsta_params\n", __FUNCTION__); + AEXT_ERROR("wlan", "Could not allocate apsta_params\n"); return -ENOMEM; } pub->iapsta_params = (void *)iapsta_params; @@ -3070,100 +3998,319 @@ int wl_ext_iapsta_attach(dhd_pub_t *pub) return 0; } -void wl_ext_iapsta_dettach(dhd_pub_t *pub) +void +wl_ext_iapsta_dettach(dhd_pub_t *pub) { if (pub->iapsta_params) { kfree(pub->iapsta_params); pub->iapsta_params = NULL; } } -#endif +#endif /* WL_EXT_IAPSTA */ #ifdef IDHCP -int -wl_ext_ip_dump(int ip, char *buf) -{ - unsigned char bytes[4]; - int bytes_written=-1; - - bytes[0] = ip & 0xFF; - bytes[1] = (ip >> 8) & 0xFF; - bytes[2] = (ip >> 16) & 0xFF; - bytes[3] = (ip >> 24) & 0xFF; - bytes_written = sprintf(buf, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]); - - return bytes_written; -} - /* -terence 20170215: -dhd_priv dhcpc_dump ifname [wlan0|wlan1] -dhd_priv dhcpc_enable [0|1] +terence 20190409: +dhd_priv wl dhcpc_dump +dhd_priv wl dhcpc_param */ -int -wl_ext_dhcpc_enable(struct net_device *dev, char *command, int total_len) -{ - int enable = -1, ret = -1; - int bytes_written = -1; - - ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command)); - - sscanf(command, "%*s %d", &enable); - - if (enable >= 0) - ret = wl_ext_iovar_setint(dev, "dhcpc_enable", enable); - else { - ret = wl_ext_iovar_getint(dev, "dhcpc_enable", &enable); - if (!ret) { - bytes_written = snprintf(command, total_len, "%d", enable); - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); - ret = bytes_written; - } - } - - return ret; -} - -int -wl_ext_dhcpc_dump(struct net_device *dev, char *command, int total_len) +static int +wl_ext_dhcpc_dump(struct net_device *dev, char *data, char *command, + int total_len) { int ret = 0; int bytes_written = 0; uint32 ip_addr; char buf[20]=""; - ret = wl_ext_iovar_getint(dev, "dhcpc_ip_addr", &ip_addr); - if (!ret) { - wl_ext_ip_dump(ip_addr, buf); - bytes_written += snprintf(command+bytes_written, total_len, "ipaddr %s ", buf); + if (!data) { + ret = wl_ext_iovar_getint(dev, "dhcpc_ip_addr", &ip_addr); + if (!ret) { + bcm_ip_ntoa((struct ipv4_addr *)&ip_addr, buf); + bytes_written += snprintf(command+bytes_written, total_len, + "ipaddr %s ", buf); + } + + ret = wl_ext_iovar_getint(dev, "dhcpc_ip_mask", &ip_addr); + if (!ret) { + bcm_ip_ntoa((struct ipv4_addr *)&ip_addr, buf); + bytes_written += snprintf(command+bytes_written, total_len, + "mask %s ", buf); + } + + ret = wl_ext_iovar_getint(dev, "dhcpc_ip_gateway", &ip_addr); + if (!ret) { + bcm_ip_ntoa((struct ipv4_addr *)&ip_addr, buf); + bytes_written += snprintf(command+bytes_written, total_len, + "gw %s ", buf); + } + + ret = wl_ext_iovar_getint(dev, "dhcpc_ip_dnsserv", &ip_addr); + if (!ret) { + bcm_ip_ntoa((struct ipv4_addr *)&ip_addr, buf); + bytes_written += snprintf(command+bytes_written, total_len, + "dnsserv %s ", buf); + } + + if (!bytes_written) + bytes_written = -1; + + AEXT_TRACE(dev->name, "command result is %s\n", command); } - ret = wl_ext_iovar_getint(dev, "dhcpc_ip_mask", &ip_addr); - if (!ret) { - wl_ext_ip_dump(ip_addr, buf); - bytes_written += snprintf(command+bytes_written, total_len, "mask %s ", buf); - } - - ret = wl_ext_iovar_getint(dev, "dhcpc_ip_gateway", &ip_addr); - if (!ret) { - wl_ext_ip_dump(ip_addr, buf); - bytes_written += snprintf(command+bytes_written, total_len, "gw %s ", buf); - } - - ret = wl_ext_iovar_getint(dev, "dhcpc_ip_dnsserv", &ip_addr); - if (!ret) { - wl_ext_ip_dump(ip_addr, buf); - bytes_written += snprintf(command+bytes_written, total_len, "dnsserv %s ", buf); - } - - if (!bytes_written) - bytes_written = -1; - - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); - return bytes_written; } -#endif + +int +wl_ext_dhcpc_param(struct net_device *dev, char *data, char *command, + int total_len) +{ + int ret = -1, bytes_written = 0; + char ip_addr_str[20]="", ip_serv_str[20]=""; + struct dhcpc_parameter dhcpc_param; + uint32 ip_addr, ip_serv, lease_time; + char iovar_buf[WLC_IOCTL_SMLEN]="\0"; + + if (data) { + AEXT_TRACE(dev->name, "cmd %s", command); + sscanf(data, "%s %s %d", ip_addr_str, ip_serv_str, &lease_time); + AEXT_TRACE(dev->name, "ip_addr = %s, ip_serv = %s, lease_time = %d", + ip_addr_str, ip_serv_str, lease_time); + + memset(&dhcpc_param, 0, sizeof(struct dhcpc_parameter)); + if (!bcm_atoipv4(ip_addr_str, (struct ipv4_addr *)&ip_addr)) { + AEXT_ERROR(dev->name, "wrong ip_addr_str %s\n", ip_addr_str); + ret = -1; + goto exit; + } + dhcpc_param.ip_addr = ip_addr; + + if (!bcm_atoipv4(ip_addr_str, (struct ipv4_addr *)&ip_serv)) { + AEXT_ERROR(dev->name, "wrong ip_addr_str %s\n", ip_addr_str); + ret = -1; + goto exit; + } + dhcpc_param.ip_serv = ip_serv; + dhcpc_param.lease_time = lease_time; + ret = wl_ext_iovar_setbuf(dev, "dhcpc_param", &dhcpc_param, + sizeof(struct dhcpc_parameter), iovar_buf, sizeof(iovar_buf), NULL); + } else { + ret = wl_ext_iovar_getbuf(dev, "dhcpc_param", &dhcpc_param, + sizeof(struct dhcpc_parameter), iovar_buf, WLC_IOCTL_SMLEN, NULL); + if (!ret) { + bcm_ip_ntoa((struct ipv4_addr *)&dhcpc_param.ip_addr, ip_addr_str); + bytes_written += snprintf(command + bytes_written, total_len, + "ip_addr %s\n", ip_addr_str); + bcm_ip_ntoa((struct ipv4_addr *)&dhcpc_param.ip_serv, ip_serv_str); + bytes_written += snprintf(command + bytes_written, total_len, + "ip_serv %s\n", ip_serv_str); + bytes_written += snprintf(command + bytes_written, total_len, + "lease_time %d\n", dhcpc_param.lease_time); + AEXT_TRACE(dev->name, "command result is %s\n", command); + ret = bytes_written; + } + } + + exit: + return ret; +} +#endif /* IDHCP */ + +int +wl_ext_mkeep_alive(struct net_device *dev, char *data, char *command, + int total_len) +{ + struct dhd_pub *dhd = dhd_get_pub(dev); + wl_mkeep_alive_pkt_t *mkeep_alive_pktp; + int ret = -1, i, ifidx, id, period=-1; + char *packet = NULL, *buf = NULL; + int bytes_written = 0; + + if (data) { + buf = kmalloc(total_len, GFP_KERNEL); + if (buf == NULL) { + AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n", WLC_IOCTL_SMLEN); + goto exit; + } + packet = kmalloc(total_len, GFP_KERNEL); + if (packet == NULL) { + AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n", WLC_IOCTL_SMLEN); + goto exit; + } + AEXT_TRACE(dev->name, "cmd %s", command); + sscanf(data, "%d %d %s", &id, &period, packet); + AEXT_TRACE(dev->name, "id=%d, period=%d, packet=%s", id, period, packet); + if (period >= 0) { + ifidx = dhd_net2idx(dhd->info, dev); + ret = dhd_conf_mkeep_alive(dhd, ifidx, id, period, packet, FALSE); + } else { + if (id < 0) + id = 0; + ret = wl_ext_iovar_getbuf(dev, "mkeep_alive", &id, sizeof(id), buf, + total_len, NULL); + if (!ret) { + mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *) buf; + bytes_written += snprintf(command+bytes_written, total_len, + "Id :%d\n" + "Period (msec) :%d\n" + "Length :%d\n" + "Packet :0x", + mkeep_alive_pktp->keep_alive_id, + dtoh32(mkeep_alive_pktp->period_msec), + dtoh16(mkeep_alive_pktp->len_bytes)); + for (i=0; ilen_bytes; i++) { + bytes_written += snprintf(command+bytes_written, total_len, + "%02x", mkeep_alive_pktp->data[i]); + } + AEXT_TRACE(dev->name, "command result is %s\n", command); + ret = bytes_written; + } + } + } + +exit: + if (buf) + kfree(buf); + if (packet) + kfree(packet); + return ret; +} + +#ifdef WL_EXT_TCPKA +static int +wl_ext_tcpka_conn_add(struct net_device *dev, char *data, char *command, + int total_len) +{ + int ret = 0; + s8 iovar_buf[WLC_IOCTL_SMLEN]; + tcpka_conn_t *tcpka = NULL; + uint32 sess_id = 0, ipid = 0, srcport = 0, dstport = 0, seq = 0, ack = 0, + tcpwin = 0, tsval = 0, tsecr = 0, len = 0, ka_payload_len = 0; + char dst_mac[ETHER_ADDR_STR_LEN], src_ip[IPV4_ADDR_STR_LEN], + dst_ip[IPV4_ADDR_STR_LEN], ka_payload[32]; + + if (data) { + memset(dst_mac, 0, sizeof(dst_mac)); + memset(src_ip, 0, sizeof(src_ip)); + memset(dst_ip, 0, sizeof(dst_ip)); + memset(ka_payload, 0, sizeof(ka_payload)); + sscanf(data, "%d %s %s %s %d %d %d %u %u %d %u %u %u %u %32s", + &sess_id, dst_mac, src_ip, dst_ip, &ipid, &srcport, &dstport, &seq, + &ack, &tcpwin, &tsval, &tsecr, &len, &ka_payload_len, ka_payload); + + tcpka = kmalloc(sizeof(struct tcpka_conn) + ka_payload_len, GFP_KERNEL); + if (tcpka == NULL) { + AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n", + sizeof(struct tcpka_conn) + ka_payload_len); + goto exit; + } + memset(tcpka, 0, sizeof(struct tcpka_conn) + ka_payload_len); + + tcpka->sess_id = sess_id; + if (!(ret = bcm_ether_atoe(dst_mac, &tcpka->dst_mac))) { + AEXT_ERROR(dev->name, "mac parsing err addr=%s\n", dst_mac); + goto exit; + } + if (!bcm_atoipv4(src_ip, &tcpka->src_ip)) { + AEXT_ERROR(dev->name, "src_ip parsing err ip=%s\n", src_ip); + goto exit; + } + if (!bcm_atoipv4(dst_ip, &tcpka->dst_ip)) { + AEXT_ERROR(dev->name, "dst_ip parsing err ip=%s\n", dst_ip); + goto exit; + } + tcpka->ipid = ipid; + tcpka->srcport = srcport; + tcpka->dstport = dstport; + tcpka->seq = seq; + tcpka->ack = ack; + tcpka->tcpwin = tcpwin; + tcpka->tsval = tsval; + tcpka->tsecr = tsecr; + tcpka->len = len; + tcpka->ka_payload_len = ka_payload_len; + strncpy(tcpka->ka_payload, ka_payload, ka_payload_len); + + AEXT_INFO(dev->name, + "tcpka_conn_add %d %pM %pM %pM %d %d %d %u %u %d %u %u %u %u \"%s\"\n", + tcpka->sess_id, &tcpka->dst_mac, &tcpka->src_ip, &tcpka->dst_ip, + tcpka->ipid, tcpka->srcport, tcpka->dstport, tcpka->seq, + tcpka->ack, tcpka->tcpwin, tcpka->tsval, tcpka->tsecr, + tcpka->len, tcpka->ka_payload_len, tcpka->ka_payload); + + ret = wl_ext_iovar_setbuf(dev, "tcpka_conn_add", (char *)tcpka, + (sizeof(tcpka_conn_t) + tcpka->ka_payload_len - 1), + iovar_buf, sizeof(iovar_buf), NULL); + } + +exit: + if (tcpka) + kfree(tcpka); + return ret; +} + +static int +wl_ext_tcpka_conn_enable(struct net_device *dev, char *data, char *command, + int total_len) +{ + s8 iovar_buf[WLC_IOCTL_SMLEN]; + tcpka_conn_sess_t tcpka_conn; + int ret; + uint32 sess_id = 0, flag, interval = 0, retry_interval = 0, retry_count = 0; + + if (data) { + sscanf(data, "%d %d %d %d %d", + &sess_id, &flag, &interval, &retry_interval, &retry_count); + tcpka_conn.sess_id = sess_id; + tcpka_conn.flag = flag; + if (tcpka_conn.flag) { + tcpka_conn.tcpka_timers.interval = interval; + tcpka_conn.tcpka_timers.retry_interval = retry_interval; + tcpka_conn.tcpka_timers.retry_count = retry_count; + } else { + tcpka_conn.tcpka_timers.interval = 0; + tcpka_conn.tcpka_timers.retry_interval = 0; + tcpka_conn.tcpka_timers.retry_count = 0; + } + + AEXT_INFO(dev->name, "tcpka_conn_enable %d %d %d %d %d\n", + tcpka_conn.sess_id, tcpka_conn.flag, + tcpka_conn.tcpka_timers.interval, + tcpka_conn.tcpka_timers.retry_interval, + tcpka_conn.tcpka_timers.retry_count); + + ret = wl_ext_iovar_setbuf(dev, "tcpka_conn_enable", (char *)&tcpka_conn, + sizeof(tcpka_conn_sess_t), iovar_buf, sizeof(iovar_buf), NULL); + } + + return ret; +} + +static int +wl_ext_tcpka_conn_info(struct net_device *dev, char *data, char *command, + int total_len) +{ + s8 iovar_buf[WLC_IOCTL_SMLEN]; + tcpka_conn_sess_info_t *info = NULL; + uint32 sess_id = 0; + int ret = 0; + + if (data) { + sscanf(data, "%d", &sess_id); + AEXT_INFO(dev->name, "tcpka_conn_sess_info %d\n", sess_id); + ret = wl_ext_iovar_getbuf(dev, "tcpka_conn_sess_info", (char *)&sess_id, + sizeof(uint32), iovar_buf, sizeof(iovar_buf), NULL); + if (!ret) { + info = (tcpka_conn_sess_info_t *) iovar_buf; + ret = snprintf(command, total_len, "id=%d, ipid=%d, seq=%u, ack=%u", + sess_id, info->ipid, info->seq, info->ack); + AEXT_INFO(dev->name, "%s\n", command); + } + } + + return ret; +} +#endif /* WL_EXT_TCPKA */ static int wl_ext_rsdb_mode(struct net_device *dev, char *data, char *command, @@ -3173,27 +4320,758 @@ wl_ext_rsdb_mode(struct net_device *dev, char *data, char *command, wl_config_t rsdb_mode_cfg = {1, 0}, *rsdb_p; int ret = 0; - ANDROID_TRACE(("%s: Enter\n", __FUNCTION__)); - if (data) { rsdb_mode_cfg.config = (int)simple_strtol(data, NULL, 0); ret = wl_ext_iovar_setbuf(dev, "rsdb_mode", (char *)&rsdb_mode_cfg, sizeof(rsdb_mode_cfg), iovar_buf, WLC_IOCTL_SMLEN, NULL); - printf("%s: rsdb_mode %d\n", __FUNCTION__, rsdb_mode_cfg.config); + AEXT_INFO(dev->name, "rsdb_mode %d\n", rsdb_mode_cfg.config); } else { ret = wl_ext_iovar_getbuf(dev, "rsdb_mode", NULL, 0, iovar_buf, WLC_IOCTL_SMLEN, NULL); if (!ret) { rsdb_p = (wl_config_t *) iovar_buf; ret = snprintf(command, total_len, "%d", rsdb_p->config); - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, - command)); + AEXT_TRACE(dev->name, "command result is %s\n", command); } } return ret; } +static int +wl_ext_recal(struct net_device *dev, char *data, char *command, + int total_len) +{ + int ret = 0, i, nchan, nssid = 0; + int params_size = WL_SCAN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(uint16); + wl_scan_params_t *params = NULL; + int ioctl_ver; + char *p; + + AEXT_TRACE(dev->name, "Enter\n"); + + if (data) { + params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t); + params = (wl_scan_params_t *) kzalloc(params_size, GFP_KERNEL); + if (params == NULL) { + ret = -ENOMEM; + goto exit; + } + memset(params, 0, params_size); + + wl_ext_get_ioctl_ver(dev, &ioctl_ver); + + memcpy(¶ms->bssid, ðer_bcast, ETHER_ADDR_LEN); + params->bss_type = DOT11_BSSTYPE_ANY; + params->scan_type = 0; + params->nprobes = -1; + params->active_time = -1; + params->passive_time = -1; + params->home_time = -1; + params->channel_num = 0; + + params->scan_type |= WL_SCANFLAGS_PASSIVE; + nchan = 2; + params->channel_list[0] = wf_channel2chspec(1, WL_CHANSPEC_BW_20); + params->channel_list[1] = wf_channel2chspec(2, WL_CHANSPEC_BW_20); + + params->nprobes = htod32(params->nprobes); + params->active_time = htod32(params->active_time); + params->passive_time = htod32(params->passive_time); + params->home_time = htod32(params->home_time); + + for (i = 0; i < nchan; i++) { + wl_ext_chspec_host_to_driver(ioctl_ver, params->channel_list[i]); + } + + p = (char*)params->channel_list + nchan * sizeof(uint16); + + params->channel_num = htod32((nssid << WL_SCAN_PARAMS_NSSID_SHIFT) | + (nchan & WL_SCAN_PARAMS_COUNT_MASK)); + params_size = p - (char*)params + nssid * sizeof(wlc_ssid_t); + + AEXT_INFO(dev->name, "recal\n"); + ret = wl_ext_ioctl(dev, WLC_SCAN, params, params_size, 1); + } + +exit: + if (params) + kfree(params); + return ret; +} + +static s32 +wl_ext_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add) +{ + s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; + s8 eventmask[WL_EVENTING_MASK_LEN]; + s32 err = 0; + + if (!ndev) + return -ENODEV; + + /* Setup event_msgs */ + err = wldev_iovar_getbuf(ndev, "event_msgs", NULL, 0, iovbuf, sizeof(iovbuf), NULL); + if (unlikely(err)) { + AEXT_ERROR(ndev->name, "Get event_msgs error (%d)\n", err); + goto eventmsg_out; + } + memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN); + if (add) { + setbit(eventmask, event); + } else { + clrbit(eventmask, event); + } + err = wldev_iovar_setbuf(ndev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, + sizeof(iovbuf), NULL); + if (unlikely(err)) { + AEXT_ERROR(ndev->name, "Set event_msgs error (%d)\n", err); + goto eventmsg_out; + } + +eventmsg_out: + return err; +} + +static int +wl_ext_event_msg(struct net_device *dev, char *data, + char *command, int total_len) +{ + s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; + s8 eventmask[WL_EVENTING_MASK_LEN]; + int i, bytes_written = 0, add = -1; + uint event; + char *vbuf; + bool skipzeros; + + /* dhd_priv wl event_msg [offset] [1/0, 1 for add, 0 for remove] */ + /* dhd_priv wl event_msg 40 1 */ + if (data) { + AEXT_TRACE(dev->name, "data = %s\n", data); + sscanf(data, "%d %d", &event, &add); + /* Setup event_msgs */ + bytes_written = wldev_iovar_getbuf(dev, "event_msgs", NULL, 0, iovbuf, + sizeof(iovbuf), NULL); + if (unlikely(bytes_written)) { + AEXT_ERROR(dev->name, "Get event_msgs error (%d)\n", bytes_written); + goto eventmsg_out; + } + memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN); + if (add == -1) { + if (isset(eventmask, event)) + bytes_written += snprintf(command+bytes_written, total_len, "1"); + else + bytes_written += snprintf(command+bytes_written, total_len, "0"); + AEXT_INFO(dev->name, "%s\n", command); + goto eventmsg_out; + } + bytes_written = wl_ext_add_remove_eventmsg(dev, event, add); + } + else { + /* Setup event_msgs */ + bytes_written = wldev_iovar_getbuf(dev, "event_msgs", NULL, 0, iovbuf, + sizeof(iovbuf), NULL); + if (bytes_written) { + AEXT_ERROR(dev->name, "Get event_msgs error (%d)\n", bytes_written); + goto eventmsg_out; + } + vbuf = (char *)iovbuf; + bytes_written += snprintf(command+bytes_written, total_len, "0x"); + for (i = (sizeof(eventmask) - 1); i >= 0; i--) { + if (vbuf[i] || (i == 0)) + skipzeros = FALSE; + if (skipzeros) + continue; + bytes_written += snprintf(command+bytes_written, total_len, + "%02x", vbuf[i] & 0xff); + } + AEXT_INFO(dev->name, "%s\n", command); + } + +eventmsg_out: + return bytes_written; +} + +#ifdef PKT_FILTER_SUPPORT +extern void dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg); +extern void dhd_pktfilter_offload_delete(dhd_pub_t *dhd, int id); +extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode); +static int +wl_ext_pkt_filter_add(struct net_device *dev, char *data, char *command, + int total_len) +{ + struct dhd_pub *dhd = dhd_get_pub(dev); + int i, filter_id, new_id = 0, cnt; + conf_pkt_filter_add_t *filter_add = &dhd->conf->pkt_filter_add; + char **pktfilter = dhd->pktfilter; + int err = 0; + + if (data) { + AEXT_TRACE(dev->name, "data = %s\n", data); + + new_id = simple_strtol(data, NULL, 10); + if (new_id <= 0) { + AEXT_ERROR(dev->name, "wrong id %d\n", new_id); + return -1; + } + + cnt = dhd->pktfilter_count; + for (i=0; iname, "filter id %d already in list\n", filter_id); + return -1; + } + } + + cnt = filter_add->count; + if (cnt >= DHD_CONF_FILTER_MAX) { + AEXT_ERROR(dev->name, "not enough filter\n"); + return -1; + } + for (i=0; ifilter[i], NULL, 10); + if (new_id == filter_id) { + AEXT_ERROR(dev->name, "filter id %d already in list\n", filter_id); + return -1; + } + } + + strcpy(&filter_add->filter[cnt][0], data); + dhd->pktfilter[dhd->pktfilter_count] = filter_add->filter[cnt]; + filter_add->count++; + dhd->pktfilter_count++; + + dhd_pktfilter_offload_set(dhd, data); + AEXT_INFO(dev->name, "filter id %d added\n", new_id); + } + + return err; +} + +static int +wl_ext_pkt_filter_delete(struct net_device *dev, char *data, char *command, + int total_len) +{ + struct dhd_pub *dhd = dhd_get_pub(dev); + int i, j, filter_id, cnt; + char **pktfilter = dhd->pktfilter; + conf_pkt_filter_add_t *filter_add = &dhd->conf->pkt_filter_add; + bool in_filter = FALSE; + int id, err = 0; + + if (data) { + AEXT_TRACE(dev->name, "data = %s\n", data); + id = (int)simple_strtol(data, NULL, 0); + + cnt = filter_add->count; + for (i=0; ifilter[i], NULL, 10); + if (id == filter_id) { + in_filter = TRUE; + memset(filter_add->filter[i], 0, PKT_FILTER_LEN); + for (j=i; j<(cnt-1); j++) { + strcpy(filter_add->filter[j], filter_add->filter[j+1]); + memset(filter_add->filter[j+1], 0, PKT_FILTER_LEN); + } + cnt--; + filter_add->count--; + dhd->pktfilter_count--; + } + } + + cnt = dhd->pktfilter_count; + for (i=0; iname, "filter id %d deleted\n", id); + } else { + AEXT_ERROR(dev->name, "filter id %d not in list\n", id); + err = -1; + } + } + + return err; +} + +static int +wl_ext_pkt_filter_enable(struct net_device *dev, char *data, char *command, + int total_len) +{ + struct dhd_pub *dhd = dhd_get_pub(dev); + int err = 0, id, enable; + int i, filter_id, cnt; + char **pktfilter = dhd->pktfilter; + bool in_filter = FALSE; + + /* dhd_priv wl pkt_filter_enable [id] [1/0] */ + /* dhd_priv wl pkt_filter_enable 141 1 */ + if (data) { + sscanf(data, "%d %d", &id, &enable); + + cnt = dhd->pktfilter_count; + for (i=0; ipktfilter[i], + enable, dhd_master_mode); + AEXT_INFO(dev->name, "filter id %d %s\n", id, enable?"enabled":"disabled"); + } else { + AEXT_ERROR(dev->name, "filter id %d not in list\n", id); + err = -1; + } + } + + return err; +} +#endif /* PKT_FILTER_SUPPORT */ + +#ifdef SENDPROB +static int +wl_ext_send_probreq(struct net_device *dev, char *data, char *command, + int total_len) +{ + int err = 0; + char addr_str[16], addr[6]; + char iovar_buf[WLC_IOCTL_SMLEN]="\0"; + char ie_data[WLC_IOCTL_SMLEN] = "\0"; + wl_probe_params_t params; + + /* dhd_priv wl send_probreq [dest. addr] [OUI+VAL] */ + /* dhd_priv wl send_probreq 0x00904c010203 0x00904c01020304050607 */ + if (data) { + AEXT_TRACE(dev->name, "data = %s\n", data); + sscanf(data, "%s %s", addr_str, ie_data); + AEXT_TRACE(dev->name, "addr=%s, ie=%s\n", addr_str, ie_data); + + if (strlen(addr_str) != 14) { + AEXT_ERROR(dev->name, "wrong addr %s\n", addr_str); + goto exit; + } + wl_pattern_atoh(addr_str, (char *) addr); + memset(¶ms, 0, sizeof(params)); + memcpy(¶ms.bssid, addr, ETHER_ADDR_LEN); + memcpy(¶ms.mac, addr, ETHER_ADDR_LEN); + + err = wl_ext_add_del_ie(dev, VNDR_IE_PRBREQ_FLAG, ie_data, "add"); + if (err) + goto exit; + err = wl_ext_iovar_setbuf(dev, "sendprb", (char *)¶ms, sizeof(params), + iovar_buf, sizeof(iovar_buf), NULL); + OSL_SLEEP(100); + wl_ext_add_del_ie(dev, VNDR_IE_PRBREQ_FLAG, ie_data, "del"); + } + +exit: + return err; +} + +static int +wl_ext_send_probresp(struct net_device *dev, char *data, char *command, + int total_len) +{ + int err = 0; + char addr_str[16], addr[6]; + char iovar_buf[WLC_IOCTL_SMLEN]="\0"; + char ie_data[WLC_IOCTL_SMLEN] = "\0"; + + /* dhd_priv wl send_probresp [dest. addr] [OUI+VAL] */ + /* dhd_priv wl send_probresp 0x00904c010203 0x00904c01020304050607 */ + if (data) { + AEXT_TRACE(dev->name, "data = %s\n", data); + sscanf(data, "%s %s", addr_str, ie_data); + AEXT_TRACE(dev->name, "addr=%s, ie=%s\n", addr_str, ie_data); + + if (strlen(addr_str) != 14) { + AEXT_ERROR(dev->name, "wrong addr %s\n", addr_str); + goto exit; + } + wl_pattern_atoh(addr_str, (char *) addr); + + err = wl_ext_add_del_ie(dev, VNDR_IE_PRBRSP_FLAG, ie_data, "add"); + if (err) + goto exit; + err = wl_ext_iovar_setbuf(dev, "send_probresp", addr, sizeof(addr), + iovar_buf, sizeof(iovar_buf), NULL); + OSL_SLEEP(100); + wl_ext_add_del_ie(dev, VNDR_IE_PRBRSP_FLAG, ie_data, "del"); + } + +exit: + return err; +} + +static int +wl_ext_recv_probreq(struct net_device *dev, char *data, char *command, + int total_len) +{ + int err = 0, enable = 0; + char cmd[32]; + struct dhd_pub *dhd = dhd_get_pub(dev); + + /* enable: + 1. dhd_priv wl 86 0 + 2. dhd_priv wl event_msg 44 1 + disable: + 1. dhd_priv wl 86 2; + 2. dhd_priv wl event_msg 44 0 + */ + if (data) { + AEXT_TRACE(dev->name, "data = %s\n", data); + sscanf(data, "%d", &enable); + if (enable) { + strcpy(cmd, "wl 86 0"); + err = wl_ext_wl_iovar(dev, cmd, total_len); + if (err) + goto exit; + strcpy(cmd, "wl event_msg 44 1"); + err = wl_ext_wl_iovar(dev, cmd, total_len); + if (err) + goto exit; + dhd->recv_probereq = TRUE; + } else { + if (dhd->conf->pm) + strcpy(cmd, "wl 86 2"); { + wl_ext_wl_iovar(dev, cmd, total_len); + } + strcpy(cmd, "wl event_msg 44 0"); + wl_ext_wl_iovar(dev, cmd, total_len); + dhd->recv_probereq = FALSE; + } + } + +exit: + return err; +} + +static int +wl_ext_recv_probresp(struct net_device *dev, char *data, char *command, + int total_len) +{ + int err = 0, enable = 0; + char cmd[32]; + + /* enable: + 1. dhd_priv wl pkt_filter_add 150 0 0 0 0xFF 0x50 + 2. dhd_priv wl pkt_filter_enable 150 1 + 3. dhd_priv wl mpc 0 + 4. dhd_priv wl 108 1 + disable: + 1. dhd_priv wl 108 0 + 2. dhd_priv wl mpc 1 + 3. dhd_priv wl pkt_filter_disable 150 0 + 4. dhd_priv pkt_filter_delete 150 + */ + if (data) { + AEXT_TRACE(dev->name, "data = %s\n", data); + sscanf(data, "%d", &enable); + if (enable) { + strcpy(cmd, "wl pkt_filter_add 150 0 0 0 0xFF 0x50"); + err = wl_ext_wl_iovar(dev, cmd, total_len); + if (err) + goto exit; + strcpy(cmd, "wl pkt_filter_enable 150 1"); + err = wl_ext_wl_iovar(dev, cmd, total_len); + if (err) + goto exit; + strcpy(cmd, "wl mpc 0"); + err = wl_ext_wl_iovar(dev, cmd, total_len); + if (err) + goto exit; + strcpy(cmd, "wl 108 1"); + err= wl_ext_wl_iovar(dev, cmd, total_len); + } else { + strcpy(cmd, "wl 108 0"); + wl_ext_wl_iovar(dev, cmd, total_len); + strcpy(cmd, "wl mpc 1"); + wl_ext_wl_iovar(dev, cmd, total_len); + strcpy(cmd, "wl pkt_filter_enable 150 0"); + wl_ext_wl_iovar(dev, cmd, total_len); + strcpy(cmd, "wl pkt_filter_delete 150"); + wl_ext_wl_iovar(dev, cmd, total_len); + } + } + +exit: + return err; +} +#endif /* SENDPROB */ + +static int +wl_ext_gtk_key_info(struct net_device *dev, char *data, char *command, int total_len) +{ + int err = 0; + char iovar_buf[WLC_IOCTL_SMLEN]="\0"; + gtk_keyinfo_t keyinfo; + bcol_gtk_para_t bcol_keyinfo; + + /* wl gtk_key_info [kck kek replay_ctr] */ + /* wl gtk_key_info 001122..FF001122..FF00000000000001 */ + if (data) { + memset(&keyinfo, 0, sizeof(keyinfo)); + memcpy(&keyinfo, data, RSN_KCK_LENGTH+RSN_KEK_LENGTH+RSN_REPLAY_LEN); + if (android_msg_level & ANDROID_INFO_LEVEL) { + prhex("kck", (uchar *)keyinfo.KCK, RSN_KCK_LENGTH); + prhex("kek", (uchar *)keyinfo.KEK, RSN_KEK_LENGTH); + prhex("replay_ctr", (uchar *)keyinfo.ReplayCounter, RSN_REPLAY_LEN); + } + + memset(&bcol_keyinfo, 0, sizeof(bcol_keyinfo)); + bcol_keyinfo.enable = 1; + bcol_keyinfo.ptk_len = 64; + memcpy(&bcol_keyinfo.ptk, data, RSN_KCK_LENGTH+RSN_KEK_LENGTH); + err = wl_ext_iovar_setbuf(dev, "bcol_gtk_rekey_ptk", &bcol_keyinfo, + sizeof(bcol_keyinfo), iovar_buf, sizeof(iovar_buf), NULL); + if (!err) { + goto exit; + } + + err = wl_ext_iovar_setbuf(dev, "gtk_key_info", &keyinfo, sizeof(keyinfo), + iovar_buf, sizeof(iovar_buf), NULL); + if (err) { + AEXT_ERROR(dev->name, "failed to set gtk_key_info\n"); + goto exit; + } + } + +exit: + return err; +} + +#ifdef WL_EXT_WOWL +static int +wl_ext_wowl_pattern(struct net_device *dev, char *data, char *command, + int total_len) +{ + s8 iovar_buf[WLC_IOCTL_SMLEN]; + uint buf_len = 0; + int offset; + char mask[128]="\0", pattern[128]="\0", add[4]="\0", + mask_tmp[128], *pmask_tmp; + uint32 masksize, patternsize, pad_len = 0; + wl_wowl_pattern2_t *wowl_pattern2 = NULL; + wl_wowl_pattern_t *wowl_pattern = NULL; + char *mask_and_pattern; + wl_wowl_pattern_list_t *list; + uint8 *ptr; + int ret = 0, i, j, v; + + if (data) { + sscanf(data, "%s %d %s %s", add, &offset, mask_tmp, pattern); + if (strcmp(add, "add") != 0 && strcmp(add, "clr") != 0) { + AEXT_ERROR(dev->name, "first arg should be add or clr\n"); + goto exit; + } + if (!strcmp(add, "clr")) { + AEXT_INFO(dev->name, "wowl_pattern clr\n"); + ret = wl_ext_iovar_setbuf(dev, "wowl_pattern", add, + sizeof(add), iovar_buf, sizeof(iovar_buf), NULL); + goto exit; + } + masksize = strlen(mask_tmp) -2; + AEXT_TRACE(dev->name, "0 mask_tmp=%s, masksize=%d\n", mask_tmp, masksize); + + // add pading + if (masksize % 16) + pad_len = (16 - masksize % 16); + for (i=0; iname, "1 mask_tmp=%s, masksize=%d\n", mask_tmp, masksize); + + // translate 0x00 to 0, others to 1 + j = 0; + pmask_tmp = &mask_tmp[2]; + for (i=0; iname, "2 mask_tmp=%s, masksize=%d\n", mask_tmp, masksize); + + // reorder per 8bits + pmask_tmp = &mask_tmp[2]; + for (i=0; iname, "3 mask_tmp=%s, masksize=%d\n", mask_tmp, masksize); + + // translate 8bits to 1byte + j = 0; v = 0; + pmask_tmp = &mask_tmp[2]; + strcpy(mask, "0x"); + for (i=0; iname, "4 mask=%s, masksize=%d\n", mask, masksize); + + patternsize = (strlen(pattern)-2)/2; + buf_len = sizeof(wl_wowl_pattern2_t) + patternsize + masksize; + wowl_pattern2 = kmalloc(buf_len, GFP_KERNEL); + if (wowl_pattern2 == NULL) { + AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n", buf_len); + goto exit; + } + memset(wowl_pattern2, 0, sizeof(wl_wowl_pattern2_t)); + + strncpy(wowl_pattern2->cmd, add, sizeof(add)); + wowl_pattern2->wowl_pattern.type = 0; + wowl_pattern2->wowl_pattern.offset = offset; + mask_and_pattern = (char*)wowl_pattern2 + sizeof(wl_wowl_pattern2_t); + + wowl_pattern2->wowl_pattern.masksize = masksize; + ret = wl_pattern_atoh(mask, mask_and_pattern); + if (ret == -1) { + AEXT_ERROR(dev->name, "rejecting mask=%s\n", mask); + goto exit; + } + + mask_and_pattern += wowl_pattern2->wowl_pattern.masksize; + wowl_pattern2->wowl_pattern.patternoffset = sizeof(wl_wowl_pattern_t) + + wowl_pattern2->wowl_pattern.masksize; + + wowl_pattern2->wowl_pattern.patternsize = patternsize; + ret = wl_pattern_atoh(pattern, mask_and_pattern); + if (ret == -1) { + AEXT_ERROR(dev->name, "rejecting pattern=%s\n", pattern); + goto exit; + } + + AEXT_INFO(dev->name, "%s %d %s %s\n", add, offset, mask, pattern); + + ret = wl_ext_iovar_setbuf(dev, "wowl_pattern", (char *)wowl_pattern2, + buf_len, iovar_buf, sizeof(iovar_buf), NULL); + } + else { + ret = wl_ext_iovar_getbuf(dev, "wowl_pattern", NULL, 0, + iovar_buf, sizeof(iovar_buf), NULL); + if (!ret) { + list = (wl_wowl_pattern_list_t *)iovar_buf; + ret = snprintf(command, total_len, "#of patterns :%d\n", list->count); + ptr = (uint8 *)list->pattern; + for (i=0; icount; i++) { + uint8 *pattern; + wowl_pattern = (wl_wowl_pattern_t *)ptr; + ret += snprintf(command+ret, total_len, + "Pattern %d:\n" + "ID :0x%x\n" + "Offset :%d\n" + "Masksize :%d\n" + "Mask :0x", + i+1, (uint32)wowl_pattern->id, wowl_pattern->offset, + wowl_pattern->masksize); + pattern = ((uint8 *)wowl_pattern + sizeof(wl_wowl_pattern_t)); + for (j = 0; j < wowl_pattern->masksize; j++) { + ret += snprintf(command+ret, total_len, "%02x", pattern[j]); + } + ret += snprintf(command+ret, total_len, "\n"); + ret += snprintf(command+ret, total_len, + "PatternSize:%d\n" + "Pattern :0x", + wowl_pattern->patternsize); + + pattern = ((uint8*)wowl_pattern + wowl_pattern->patternoffset); + for (j=0; jpatternsize; j++) + ret += snprintf(command+ret, total_len, "%02x", pattern[j]); + ret += snprintf(command+ret, total_len, "\n"); + ptr += (wowl_pattern->masksize + wowl_pattern->patternsize + + sizeof(wl_wowl_pattern_t)); + } + + AEXT_INFO(dev->name, "%s\n", command); + } + } + +exit: + if (wowl_pattern2) + kfree(wowl_pattern2); + return ret; +} + +static int +wl_ext_wowl_wakeind(struct net_device *dev, char *data, char *command, + int total_len) +{ + s8 iovar_buf[WLC_IOCTL_SMLEN]; + wl_wowl_wakeind_t *wake = NULL; + int ret = -1; + char clr[6]="\0"; + + if (data) { + sscanf(data, "%s", clr); + if (!strcmp(clr, "clear")) { + AEXT_INFO(dev->name, "wowl_wakeind clear\n"); + ret = wl_ext_iovar_setbuf(dev, "wowl_wakeind", clr, sizeof(clr), + iovar_buf, sizeof(iovar_buf), NULL); + } else { + AEXT_ERROR(dev->name, "first arg should be clear\n"); + } + } else { + ret = wl_ext_iovar_getbuf(dev, "wowl_wakeind", NULL, 0, + iovar_buf, sizeof(iovar_buf), NULL); + if (!ret) { + wake = (wl_wowl_wakeind_t *) iovar_buf; + ret = snprintf(command, total_len, "wakeind=0x%x", wake->ucode_wakeind); + if (wake->ucode_wakeind & WL_WOWL_MAGIC) + ret += snprintf(command+ret, total_len, " (MAGIC packet)"); + if (wake->ucode_wakeind & WL_WOWL_NET) + ret += snprintf(command+ret, total_len, " (Netpattern)"); + if (wake->ucode_wakeind & WL_WOWL_DIS) + ret += snprintf(command+ret, total_len, " (Disassoc/Deauth)"); + if (wake->ucode_wakeind & WL_WOWL_BCN) + ret += snprintf(command+ret, total_len, " (Loss of beacon)"); + if (wake->ucode_wakeind & WL_WOWL_TCPKEEP_TIME) + ret += snprintf(command+ret, total_len, " (TCPKA timeout)"); + if (wake->ucode_wakeind & WL_WOWL_TCPKEEP_DATA) + ret += snprintf(command+ret, total_len, " (TCPKA data)"); + if (wake->ucode_wakeind & WL_WOWL_TCPFIN) + ret += snprintf(command+ret, total_len, " (TCP FIN)"); + AEXT_INFO(dev->name, "%s\n", command); + } + } + + return ret; +} +#endif /* WL_EXT_WOWL */ + typedef int (wl_ext_tpl_parse_t)(struct net_device *dev, char *data, char *command, int total_len); @@ -3205,10 +5083,38 @@ typedef struct wl_ext_iovar_tpl_t { } wl_ext_iovar_tpl_t; const wl_ext_iovar_tpl_t wl_ext_iovar_tpl_list[] = { + {WLC_GET_VAR, WLC_SET_VAR, "event_msg", wl_ext_event_msg}, + {WLC_GET_VAR, WLC_SET_VAR, "gtk_key_info", wl_ext_gtk_key_info}, + {WLC_GET_VAR, WLC_SET_VAR, "recal", wl_ext_recal}, {WLC_GET_VAR, WLC_SET_VAR, "rsdb_mode", wl_ext_rsdb_mode}, -#ifdef WLMESH + {WLC_GET_VAR, WLC_SET_VAR, "mkeep_alive", wl_ext_mkeep_alive}, +#ifdef PKT_FILTER_SUPPORT + {WLC_GET_VAR, WLC_SET_VAR, "pkt_filter_add", wl_ext_pkt_filter_add}, + {WLC_GET_VAR, WLC_SET_VAR, "pkt_filter_delete", wl_ext_pkt_filter_delete}, + {WLC_GET_VAR, WLC_SET_VAR, "pkt_filter_enable", wl_ext_pkt_filter_enable}, +#endif /* PKT_FILTER_SUPPORT */ +#if defined(WL_EXT_IAPSTA) && defined(WLMESH) {WLC_GET_VAR, WLC_SET_VAR, "mesh_peer_status", wl_ext_mesh_peer_status}, -#endif +#endif /* WL_EXT_IAPSTA && WLMESH */ +#ifdef SENDPROB + {WLC_GET_VAR, WLC_SET_VAR, "send_probreq", wl_ext_send_probreq}, + {WLC_GET_VAR, WLC_SET_VAR, "send_probresp", wl_ext_send_probresp}, + {WLC_GET_VAR, WLC_SET_VAR, "recv_probreq", wl_ext_recv_probreq}, + {WLC_GET_VAR, WLC_SET_VAR, "recv_probresp", wl_ext_recv_probresp}, +#endif /* SENDPROB */ +#ifdef WL_EXT_TCPKA + {WLC_GET_VAR, WLC_SET_VAR, "tcpka_conn_add", wl_ext_tcpka_conn_add}, + {WLC_GET_VAR, WLC_SET_VAR, "tcpka_conn_enable", wl_ext_tcpka_conn_enable}, + {WLC_GET_VAR, WLC_SET_VAR, "tcpka_conn_sess_info", wl_ext_tcpka_conn_info}, +#endif /* WL_EXT_TCPKA */ +#ifdef WL_EXT_WOWL + {WLC_GET_VAR, WLC_SET_VAR, "wowl_pattern", wl_ext_wowl_pattern}, + {WLC_GET_VAR, WLC_SET_VAR, "wowl_wakeind", wl_ext_wowl_wakeind}, +#endif /* WL_EXT_WOWL */ +#ifdef IDHCP + {WLC_GET_VAR, WLC_SET_VAR, "dhcpc_dump", wl_ext_dhcpc_dump}, + {WLC_GET_VAR, WLC_SET_VAR, "dhcpc_param", wl_ext_dhcpc_param}, +#endif /* IDHCP */ }; /* @@ -3218,7 +5124,7 @@ Ex: dhd_priv wl [cmd] [val] dhd_priv wl mpc dhd_priv wl mpc 1 */ -int +static int wl_ext_wl_iovar(struct net_device *dev, char *command, int total_len) { int cmd, val, ret = -1, i; @@ -3227,7 +5133,7 @@ wl_ext_wl_iovar(struct net_device *dev, char *command, int total_len) const wl_ext_iovar_tpl_t *tpl = wl_ext_iovar_tpl_list; int tpl_count = ARRAY_SIZE(wl_ext_iovar_tpl_list); - ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command)); + AEXT_TRACE(dev->name, "cmd %s\n", command); pick_tmp = command; pch = bcmstrtok(&pick_tmp, " ", 0); // pick wl @@ -3243,7 +5149,7 @@ wl_ext_wl_iovar(struct net_device *dev, char *command, int total_len) if (cmd == 0) { strcpy(name, pch); } - data = bcmstrtok(&pick_tmp, " ", 0); // pick data + data = bcmstrtok(&pick_tmp, "", 0); // pick data if (data && cmd == 0) { cmd = WLC_SET_VAR; } else if (cmd == 0) { @@ -3260,28 +5166,26 @@ wl_ext_wl_iovar(struct net_device *dev, char *command, int total_len) } else { if (cmd == WLC_SET_VAR) { val = (int)simple_strtol(data, NULL, 0); - ANDROID_TRACE(("%s: set %s %d\n", __FUNCTION__, name, val)); + AEXT_INFO(dev->name, "set %s %d\n", name, val); ret = wl_ext_iovar_setint(dev, name, val); } else if (cmd == WLC_GET_VAR) { - ANDROID_TRACE(("%s: get %s\n", __FUNCTION__, name)); + AEXT_INFO(dev->name, "get %s\n", name); ret = wl_ext_iovar_getint(dev, name, &val); if (!ret) { bytes_written = snprintf(command, total_len, "%d", val); - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, - command)); + AEXT_INFO(dev->name, "command result is %s\n", command); ret = bytes_written; } } else if (data) { val = (int)simple_strtol(data, NULL, 0); - ANDROID_TRACE(("%s: set %d %d\n", __FUNCTION__, cmd, val)); + AEXT_INFO(dev->name, "set %d %d\n", cmd, val); ret = wl_ext_ioctl(dev, cmd, &val, sizeof(val), TRUE); } else { - ANDROID_TRACE(("%s: get %d\n", __FUNCTION__, cmd)); + AEXT_INFO(dev->name, "get %d\n", cmd); ret = wl_ext_ioctl(dev, cmd, &val, sizeof(val), FALSE); if (!ret) { bytes_written = snprintf(command, total_len, "%d", val); - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, - command)); + AEXT_INFO(dev->name, "command result is %s\n", command); ret = bytes_written; } } @@ -3291,7 +5195,8 @@ exit: return ret; } -int wl_android_ext_priv_cmd(struct net_device *net, char *command, +int +wl_android_ext_priv_cmd(struct net_device *net, char *command, int total_len, int *bytes_written) { int ret = 0; @@ -3305,9 +5210,6 @@ int wl_android_ext_priv_cmd(struct net_device *net, char *command, else if (strnicmp(command, CMD_ROAM_TRIGGER, strlen(CMD_ROAM_TRIGGER)) == 0) { *bytes_written = wl_ext_roam_trigger(net, command, total_len); } - else if (strnicmp(command, CMD_KEEP_ALIVE, strlen(CMD_KEEP_ALIVE)) == 0) { - *bytes_written = wl_ext_keep_alive(net, command, total_len); - } else if (strnicmp(command, CMD_PM, strlen(CMD_PM)) == 0) { *bytes_written = wl_ext_pm(net, command, total_len); } @@ -3320,52 +5222,36 @@ int wl_android_ext_priv_cmd(struct net_device *net, char *command, *bytes_written = net_os_set_suspend_bcn_li_dtim(net, bcn_li_dtim); } #ifdef WL_EXT_IAPSTA - else if (strnicmp(command, CMD_IAPSTA_INIT, strlen(CMD_IAPSTA_INIT)) == 0) { + else if (strnicmp(command, CMD_IAPSTA_INIT, strlen(CMD_IAPSTA_INIT)) == 0 || + strnicmp(command, CMD_ISAM_INIT, strlen(CMD_ISAM_INIT)) == 0) { *bytes_written = wl_ext_isam_init(net, command, total_len); } - else if (strnicmp(command, CMD_ISAM_INIT, strlen(CMD_ISAM_INIT)) == 0) { - *bytes_written = wl_ext_isam_init(net, command, total_len); - } - else if (strnicmp(command, CMD_IAPSTA_CONFIG, strlen(CMD_IAPSTA_CONFIG)) == 0) { + else if (strnicmp(command, CMD_IAPSTA_CONFIG, strlen(CMD_IAPSTA_CONFIG)) == 0 || + strnicmp(command, CMD_ISAM_CONFIG, strlen(CMD_ISAM_CONFIG)) == 0) { *bytes_written = wl_ext_iapsta_config(net, command, total_len); } - else if (strnicmp(command, CMD_ISAM_CONFIG, strlen(CMD_ISAM_CONFIG)) == 0) { - *bytes_written = wl_ext_iapsta_config(net, command, total_len); - } - else if (strnicmp(command, CMD_IAPSTA_ENABLE, strlen(CMD_IAPSTA_ENABLE)) == 0) { + else if (strnicmp(command, CMD_IAPSTA_ENABLE, strlen(CMD_IAPSTA_ENABLE)) == 0 || + strnicmp(command, CMD_ISAM_ENABLE, strlen(CMD_ISAM_ENABLE)) == 0) { *bytes_written = wl_ext_iapsta_enable(net, command, total_len); } - else if (strnicmp(command, CMD_ISAM_ENABLE, strlen(CMD_ISAM_ENABLE)) == 0) { - *bytes_written = wl_ext_iapsta_enable(net, command, total_len); - } - else if (strnicmp(command, CMD_IAPSTA_DISABLE, strlen(CMD_IAPSTA_DISABLE)) == 0) { - *bytes_written = wl_ext_iapsta_disable(net, command, total_len); - } - else if (strnicmp(command, CMD_ISAM_DISABLE, strlen(CMD_ISAM_DISABLE)) == 0) { + else if (strnicmp(command, CMD_IAPSTA_DISABLE, strlen(CMD_IAPSTA_DISABLE)) == 0 || + strnicmp(command, CMD_ISAM_DISABLE, strlen(CMD_ISAM_DISABLE)) == 0) { *bytes_written = wl_ext_iapsta_disable(net, command, total_len); } else if (strnicmp(command, CMD_ISAM_STATUS, strlen(CMD_ISAM_STATUS)) == 0) { *bytes_written = wl_ext_isam_status(net, command, total_len); } -#endif -#ifdef IDHCP - else if (strnicmp(command, CMD_DHCPC_ENABLE, strlen(CMD_DHCPC_ENABLE)) == 0) { - *bytes_written = wl_ext_dhcpc_enable(net, command, total_len); - } - else if (strnicmp(command, CMD_DHCPC_DUMP, strlen(CMD_DHCPC_DUMP)) == 0) { - *bytes_written = wl_ext_dhcpc_dump(net, command, total_len); - } -#endif +#endif /* WL_EXT_IAPSTA */ #ifdef WL_CFG80211 else if (strnicmp(command, CMD_AUTOCHANNEL, strlen(CMD_AUTOCHANNEL)) == 0) { *bytes_written = wl_cfg80211_autochannel(net, command, total_len); } -#endif -#ifdef WL_ESCAN +#endif /* WL_CFG80211 */ +#if defined(WL_WIRELESS_EXT) && defined(WL_ESCAN) else if (strnicmp(command, CMD_AUTOCHANNEL, strlen(CMD_AUTOCHANNEL)) == 0) { - *bytes_written = wl_escan_autochannel(net, command, total_len); + *bytes_written = wl_iw_autochannel(net, command, total_len); } -#endif +#endif /* WL_WIRELESS_EXT && WL_ESCAN */ else if (strnicmp(command, CMD_WL, strlen(CMD_WL)) == 0) { *bytes_written = wl_ext_wl_iovar(net, command, total_len); } @@ -3393,7 +5279,7 @@ wl_ext_get_distance(struct net_device *net, u32 band) sizeof(buf), NULL); if (err) { if (err != BCME_UNSUPPORTED) { - ANDROID_ERROR(("bw_cap failed, %d\n", err)); + AEXT_ERROR(net->name, "bw_cap failed, %d\n", err); return err; } else { err = wl_ext_iovar_getint(net, "mimo_bw_cap", &bw_cap); @@ -3417,7 +5303,7 @@ wl_ext_get_distance(struct net_device *net, u32 band) distance = 8; else distance = 16; - ANDROID_INFO(("%s: bw=0x%x, distance=%d\n", __FUNCTION__, bw, distance)); + AEXT_INFO(net->name, "bw=0x%x, distance=%d\n", bw, distance); return distance; } @@ -3428,7 +5314,7 @@ wl_ext_get_best_channel(struct net_device *net, wl_bss_cache_ctrl_t *bss_cache_ctrl, #else struct wl_scan_results *bss_list, -#endif +#endif /* BSSCACHE */ int ioctl_ver, int *best_2g_ch, int *best_5g_ch ) { @@ -3436,7 +5322,7 @@ wl_ext_get_best_channel(struct net_device *net, s32 i, j; #if defined(BSSCACHE) wl_bss_cache_t *node; -#endif +#endif /* BSSCACHE */ int b_band[CH_MAX_2G_CHANNEL]={0}, a_band1[4]={0}, a_band4[5]={0}; s32 cen_ch, distance, distance_2g, distance_5g, ch, min_ap=999; u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)]; @@ -3454,7 +5340,7 @@ wl_ext_get_best_channel(struct net_device *net, ret = wl_ext_ioctl(net, WLC_GET_VALID_CHANNELS, &valid_chan_list, sizeof(valid_chan_list), 0); if (ret<0) { - ANDROID_ERROR(("%s: get channels failed with %d\n", __FUNCTION__, ret)); + AEXT_ERROR(net->name, "get channels failed with %d\n", ret); return 0; } else { for (i = 0; i < dtoh32(list->count); i++) { @@ -3476,13 +5362,13 @@ wl_ext_get_best_channel(struct net_device *net, for (i=0; node && i<256; i++) #else for (i=0; i < bss_list->count; i++) -#endif +#endif /* BSSCACHE */ { #if defined(BSSCACHE) bi = node->results.bss_info; #else bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : bss_list->bss_info; -#endif +#endif /* BSSCACHE */ chanspec = wl_ext_chspec_driver_to_host(ioctl_ver, bi->chanspec); cen_ch = CHSPEC_CHANNEL(bi->chanspec); distance = 0; @@ -3517,7 +5403,7 @@ wl_ext_get_best_channel(struct net_device *net, } #if defined(BSSCACHE) node = node->next; -#endif +#endif /* BSSCACHE */ } *best_2g_ch = 0; @@ -3543,26 +5429,36 @@ wl_ext_get_best_channel(struct net_device *net, } } - if (android_msg_level&ANDROID_INFO_LEVEL) { - printf("%s: b_band: ", __FUNCTION__); + if (android_msg_level & ANDROID_INFO_LEVEL) { + struct bcmstrbuf strbuf; + char *tmp_buf = NULL; + tmp_buf = kmalloc(WLC_IOCTL_SMLEN, GFP_KERNEL); + if (tmp_buf == NULL) { + AEXT_ERROR(net->name, "Failed to allocate buffer of %d bytes\n", WLC_IOCTL_SMLEN); + goto exit; + } + bcm_binit(&strbuf, tmp_buf, WLC_IOCTL_SMLEN); for (j=0; jname, "\n%s", strbuf.origbuf); + if (tmp_buf) { + kfree(tmp_buf); + } } +exit: return 0; } -#endif +#endif /* WL_CFG80211 || WL_ESCAN */ #if defined(RSSIAVG) void @@ -3575,8 +5471,7 @@ wl_free_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl) node = *rssi_head; for (;node;) { - ANDROID_INFO(("%s: Free %d with BSSID %pM\n", - __FUNCTION__, i, &node->BSSID)); + AEXT_INFO("wlan", "Free %d with BSSID %pM\n", i, &node->BSSID); cur = node; node = cur->next; kfree(cur); @@ -3590,9 +5485,9 @@ wl_delete_dirty_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl) { wl_rssi_cache_t *node, *prev, **rssi_head; int i = -1, tmp = 0; - struct timeval now; + struct osl_timespec now; - do_gettimeofday(&now); + osl_do_gettimeofday(&now); rssi_head = &rssi_cache_ctrl->m_cache_head; node = *rssi_head; @@ -3607,8 +5502,7 @@ wl_delete_dirty_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl) tmp = 0; prev->next = node->next; } - ANDROID_INFO(("%s: Del %d with BSSID %pM\n", - __FUNCTION__, i, &node->BSSID)); + AEXT_INFO("wlan", "Del %d with BSSID %pM\n", i, &node->BSSID); kfree(node); if (tmp == 1) { node = *rssi_head; @@ -3643,8 +5537,7 @@ wl_delete_disconnected_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, tmp = 0; prev->next = node->next; } - ANDROID_INFO(("%s: Del %d with BSSID %pM\n", - __FUNCTION__, i, &node->BSSID)); + AEXT_INFO("wlan", "Del %d with BSSID %pM\n", i, &node->BSSID); kfree(node); if (tmp == 1) { node = *rssi_head; @@ -3682,36 +5575,37 @@ wl_update_connected_rssi_cache(struct net_device *net, int j, k=0; int rssi, error=0; struct ether_addr bssid; - struct timeval now, timeout; + struct osl_timespec now, timeout; scb_val_t scbval; if (!g_wifi_on) return 0; - error = wl_ext_ioctl(net, WLC_GET_BSSID, &bssid, sizeof(bssid), 0); + error = wldev_ioctl(net, WLC_GET_BSSID, &bssid, sizeof(bssid), 0); if (error == BCME_NOTASSOCIATED) { - ANDROID_INFO(("%s: Not Associated! res:%d\n", __FUNCTION__, error)); + AEXT_INFO("wlan", "Not Associated! res:%d\n", error); return 0; } if (error) { - ANDROID_ERROR(("Could not get bssid (%d)\n", error)); + AEXT_ERROR(net->name, "Could not get bssid (%d)\n", error); } error = wldev_get_rssi(net, &scbval); if (error) { - ANDROID_ERROR(("Could not get rssi (%d)\n", error)); + AEXT_ERROR(net->name, "Could not get rssi (%d)\n", error); return error; } rssi = scbval.val; - do_gettimeofday(&now); + osl_do_gettimeofday(&now); timeout.tv_sec = now.tv_sec + RSSICACHE_TIMEOUT; if (timeout.tv_sec < now.tv_sec) { /* * Integer overflow - assume long enough timeout to be assumed * to be infinite, i.e., the timeout would never happen. */ - ANDROID_TRACE(("%s: Too long timeout (secs=%d) to ever happen - now=%lu, timeout=%lu", - __FUNCTION__, RSSICACHE_TIMEOUT, now.tv_sec, timeout.tv_sec)); + AEXT_TRACE(net->name, + "Too long timeout (secs=%d) to ever happen - now=%lu, timeout=%lu\n", + RSSICACHE_TIMEOUT, now.tv_sec, timeout.tv_sec); } /* update RSSI */ @@ -3720,8 +5614,7 @@ wl_update_connected_rssi_cache(struct net_device *net, prev = NULL; for (;node;) { if (!memcmp(&node->BSSID, &bssid, ETHER_ADDR_LEN)) { - ANDROID_INFO(("%s: Update %d with BSSID %pM, RSSI=%d\n", - __FUNCTION__, k, &bssid, rssi)); + AEXT_INFO("wlan", "Update %d with BSSID %pM, RSSI=%d\n", k, &bssid, rssi); for (j=0; jRSSI[j] = node->RSSI[j+1]; node->RSSI[j] = rssi; @@ -3736,12 +5629,11 @@ wl_update_connected_rssi_cache(struct net_device *net, leaf = kmalloc(sizeof(wl_rssi_cache_t), GFP_KERNEL); if (!leaf) { - ANDROID_ERROR(("%s: Memory alloc failure %d\n", - __FUNCTION__, (int)sizeof(wl_rssi_cache_t))); + AEXT_ERROR(net->name, "Memory alloc failure %d\n", (int)sizeof(wl_rssi_cache_t)); return 0; } - ANDROID_INFO(("%s: Add %d with cached BSSID %pM, RSSI=%3d in the leaf\n", - __FUNCTION__, k, &bssid, rssi)); + AEXT_INFO(net->name, "Add %d with cached BSSID %pM, RSSI=%3d in the leaf\n", + k, &bssid, rssi); leaf->next = NULL; leaf->dirty = 0; @@ -3768,20 +5660,21 @@ wl_update_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, wl_rssi_cache_t *node, *prev, *leaf, **rssi_head; wl_bss_info_t *bi = NULL; int i, j, k; - struct timeval now, timeout; + struct osl_timespec now, timeout; if (!ss_list->count) return; - do_gettimeofday(&now); + osl_do_gettimeofday(&now); timeout.tv_sec = now.tv_sec + RSSICACHE_TIMEOUT; if (timeout.tv_sec < now.tv_sec) { /* * Integer overflow - assume long enough timeout to be assumed * to be infinite, i.e., the timeout would never happen. */ - ANDROID_TRACE(("%s: Too long timeout (secs=%d) to ever happen - now=%lu, timeout=%lu", - __FUNCTION__, RSSICACHE_TIMEOUT, now.tv_sec, timeout.tv_sec)); + AEXT_TRACE("wlan", + "Too long timeout (secs=%d) to ever happen - now=%lu, timeout=%lu\n", + RSSICACHE_TIMEOUT, now.tv_sec, timeout.tv_sec); } rssi_head = &rssi_cache_ctrl->m_cache_head; @@ -3794,8 +5687,8 @@ wl_update_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info; for (;node;) { if (!memcmp(&node->BSSID, &bi->BSSID, ETHER_ADDR_LEN)) { - ANDROID_INFO(("%s: Update %d with BSSID %pM, RSSI=%3d, SSID \"%s\"\n", - __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID)); + AEXT_INFO("wlan", "Update %d with BSSID %pM, RSSI=%3d, SSID \"%s\"\n", + k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID); for (j=0; jRSSI[j] = node->RSSI[j+1]; node->RSSI[j] = dtoh16(bi->RSSI); @@ -3813,12 +5706,12 @@ wl_update_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, leaf = kmalloc(sizeof(wl_rssi_cache_t), GFP_KERNEL); if (!leaf) { - ANDROID_ERROR(("%s: Memory alloc failure %d\n", - __FUNCTION__, (int)sizeof(wl_rssi_cache_t))); + AEXT_ERROR("wlan", "Memory alloc failure %d\n", + (int)sizeof(wl_rssi_cache_t)); return; } - ANDROID_INFO(("%s: Add %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\" in the leaf\n", - __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID)); + AEXT_INFO("wlan", "Add %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\" in the leaf\n", + k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID); leaf->next = NULL; leaf->dirty = 0; @@ -3856,12 +5749,11 @@ wl_get_avg_rssi(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, void *addr) } rssi = MIN(rssi, RSSI_MAXVAL); if (rssi == RSSI_MINVAL) { - ANDROID_ERROR(("%s: BSSID %pM does not in RSSI cache\n", - __FUNCTION__, addr)); + AEXT_ERROR("wlan", "BSSID %pM does not in RSSI cache\n", addr); } return (int16)rssi; } -#endif +#endif /* RSSIAVG */ #if defined(RSSIOFFSET) int @@ -3869,7 +5761,7 @@ wl_update_rssi_offset(struct net_device *net, int rssi) { #if defined(RSSIOFFSET_NEW) int j; -#endif +#endif /* RSSIOFFSET_NEW */ if (!g_wifi_on) return rssi; @@ -3882,10 +5774,10 @@ wl_update_rssi_offset(struct net_device *net, int rssi) rssi += j; #else rssi += RSSI_OFFSET; -#endif +#endif /* RSSIOFFSET_NEW */ return MIN(rssi, RSSI_MAXVAL); } -#endif +#endif /* RSSIOFFSET */ #if defined(BSSCACHE) void @@ -3894,14 +5786,14 @@ wl_free_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl) wl_bss_cache_t *node, *cur, **bss_head; int i=0; - ANDROID_TRACE(("%s called\n", __FUNCTION__)); + AEXT_TRACE("wlan", "called\n"); bss_head = &bss_cache_ctrl->m_cache_head; node = *bss_head; for (;node;) { - ANDROID_TRACE(("%s: Free %d with BSSID %pM\n", - __FUNCTION__, i, &node->results.bss_info->BSSID)); + AEXT_TRACE("wlan", "Free %d with BSSID %pM\n", + i, &node->results.bss_info->BSSID); cur = node; node = cur->next; kfree(cur); @@ -3915,9 +5807,9 @@ wl_delete_dirty_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl) { wl_bss_cache_t *node, *prev, **bss_head; int i = -1, tmp = 0; - struct timeval now; + struct osl_timespec now; - do_gettimeofday(&now); + osl_do_gettimeofday(&now); bss_head = &bss_cache_ctrl->m_cache_head; node = *bss_head; @@ -3932,9 +5824,9 @@ wl_delete_dirty_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl) tmp = 0; prev->next = node->next; } - ANDROID_TRACE(("%s: Del %d with BSSID %pM, RSSI=%3d, SSID \"%s\"\n", - __FUNCTION__, i, &node->results.bss_info->BSSID, - dtoh16(node->results.bss_info->RSSI), node->results.bss_info->SSID)); + AEXT_TRACE("wlan", "Del %d with BSSID %pM, RSSI=%3d, SSID \"%s\"\n", + i, &node->results.bss_info->BSSID, + dtoh16(node->results.bss_info->RSSI), node->results.bss_info->SSID); kfree(node); if (tmp == 1) { node = *bss_head; @@ -3969,9 +5861,9 @@ wl_delete_disconnected_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl, tmp = 0; prev->next = node->next; } - ANDROID_TRACE(("%s: Del %d with BSSID %pM, RSSI=%3d, SSID \"%s\"\n", - __FUNCTION__, i, &node->results.bss_info->BSSID, - dtoh16(node->results.bss_info->RSSI), node->results.bss_info->SSID)); + AEXT_TRACE("wlan", "Del %d with BSSID %pM, RSSI=%3d, SSID \"%s\"\n", + i, &node->results.bss_info->BSSID, + dtoh16(node->results.bss_info->RSSI), node->results.bss_info->SSID); kfree(node); if (tmp == 1) { node = *bss_head; @@ -4004,7 +5896,7 @@ wl_reset_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl) void dump_bss_cache( #if defined(RSSIAVG) wl_rssi_cache_ctrl_t *rssi_cache_ctrl, -#endif +#endif /* RSSIAVG */ wl_bss_cache_t *node) { int k = 0; @@ -4015,10 +5907,9 @@ void dump_bss_cache( rssi = wl_get_avg_rssi(rssi_cache_ctrl, &node->results.bss_info->BSSID); #else rssi = dtoh16(node->results.bss_info->RSSI); -#endif - ANDROID_TRACE(("%s: dump %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\"\n", - __FUNCTION__, k, &node->results.bss_info->BSSID, rssi, - node->results.bss_info->SSID)); +#endif /* RSSIAVG */ + AEXT_TRACE("wlan", "dump %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\"\n", + k, &node->results.bss_info->BSSID, rssi, node->results.bss_info->SSID); k++; node = node->next; } @@ -4028,7 +5919,7 @@ void wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl, #if defined(RSSIAVG) wl_rssi_cache_ctrl_t *rssi_cache_ctrl, -#endif +#endif /* RSSIAVG */ wl_scan_results_t *ss_list) { wl_bss_cache_t *node, *prev, *leaf, **bss_head; @@ -4036,21 +5927,22 @@ wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl, int i, k=0; #if defined(SORT_BSS_BY_RSSI) int16 rssi, rssi_node; -#endif - struct timeval now, timeout; +#endif /* SORT_BSS_BY_RSSI */ + struct osl_timespec now, timeout; if (!ss_list->count) return; - do_gettimeofday(&now); + osl_do_gettimeofday(&now); timeout.tv_sec = now.tv_sec + BSSCACHE_TIMEOUT; if (timeout.tv_sec < now.tv_sec) { /* * Integer overflow - assume long enough timeout to be assumed * to be infinite, i.e., the timeout would never happen. */ - ANDROID_TRACE(("%s: Too long timeout (secs=%d) to ever happen - now=%lu, timeout=%lu", - __FUNCTION__, BSSCACHE_TIMEOUT, now.tv_sec, timeout.tv_sec)); + AEXT_TRACE("wlan", + "Too long timeout (secs=%d) to ever happen - now=%lu, timeout=%lu\n", + BSSCACHE_TIMEOUT, now.tv_sec, timeout.tv_sec); } bss_head = &bss_cache_ctrl->m_cache_head; @@ -4075,18 +5967,20 @@ wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl, leaf = kmalloc(dtoh32(bi->length) + sizeof(wl_bss_cache_t), GFP_KERNEL); if (!leaf) { - ANDROID_ERROR(("%s: Memory alloc failure %d\n", __FUNCTION__, - dtoh32(bi->length) + (int)sizeof(wl_bss_cache_t))); + AEXT_ERROR("wlan", "Memory alloc failure %d\n", + dtoh32(bi->length) + (int)sizeof(wl_bss_cache_t)); return; } if (node) { kfree(node); node = NULL; - ANDROID_TRACE(("%s: Update %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\"\n", - __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID)); + AEXT_TRACE("wlan", + "Update %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\"\n", + k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID); } else - ANDROID_TRACE(("%s: Add %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\"\n", - __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID)); + AEXT_TRACE("wlan", + "Add %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\"\n", + k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID); memcpy(leaf->results.bss_info, bi, dtoh32(bi->length)); leaf->next = NULL; @@ -4105,14 +5999,14 @@ wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl, rssi = wl_get_avg_rssi(rssi_cache_ctrl, &leaf->results.bss_info->BSSID); #else rssi = dtoh16(leaf->results.bss_info->RSSI); -#endif +#endif /* RSSIAVG */ for (;node;) { #if defined(RSSIAVG) rssi_node = wl_get_avg_rssi(rssi_cache_ctrl, &node->results.bss_info->BSSID); #else rssi_node = dtoh16(node->results.bss_info->RSSI); -#endif +#endif /* RSSIAVG */ if (rssi > rssi_node) { leaf->next = node; if (node == *bss_head) @@ -4129,22 +6023,22 @@ wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl, #else leaf->next = *bss_head; *bss_head = leaf; -#endif +#endif /* SORT_BSS_BY_RSSI */ } } dump_bss_cache( #if defined(RSSIAVG) rssi_cache_ctrl, -#endif +#endif /* RSSIAVG */ *bss_head); } void wl_release_bss_cache_ctrl(wl_bss_cache_ctrl_t *bss_cache_ctrl) { - ANDROID_TRACE(("%s:\n", __FUNCTION__)); + AEXT_TRACE("wlan", "Enter\n"); wl_free_bss_cache(bss_cache_ctrl); } -#endif +#endif /* BSSCACHE */ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfg80211.c index 9705772cdf0b..19ddc5432251 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfg80211.c @@ -94,6 +94,9 @@ #ifdef RTT_SUPPORT #include #endif /* RTT_SUPPORT */ + +#define BRCM_SAE_VENDOR_EVENT_BUF_LEN 500 + #ifdef WL11U #endif /* WL11U */ @@ -101,8 +104,38 @@ #define DHD_SUPPORT_IF_CNTS #endif /* !DHD_UN_SUPPORT_IF_CNTS */ +#ifdef BCMWAPI_WPI +/* these items should evetually go into wireless.h of the linux system headfile dir */ +#ifndef IW_ENCODE_ALG_SM4 +#define IW_ENCODE_ALG_SM4 0x20 +#endif +#ifndef IW_AUTH_WAPI_ENABLED +#define IW_AUTH_WAPI_ENABLED 0x20 +#endif + +#ifndef IW_AUTH_WAPI_VERSION_1 +#define IW_AUTH_WAPI_VERSION_1 0x00000008 +#endif + +#ifndef IW_AUTH_CIPHER_SMS4 +#define IW_AUTH_CIPHER_SMS4 0x00000020 +#endif + +#ifndef IW_AUTH_KEY_MGMT_WAPI_PSK +#define IW_AUTH_KEY_MGMT_WAPI_PSK 4 +#endif + +#ifndef IW_AUTH_KEY_MGMT_WAPI_CERT +#define IW_AUTH_KEY_MGMT_WAPI_CERT 8 +#endif +#endif /* BCMWAPI_WPI */ + +#ifdef BCMWAPI_WPI +#define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED | SMS4_ENABLED)) +#else /* BCMWAPI_WPI */ #define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED)) +#endif /* BCMWAPI_WPI */ static struct device *cfg80211_parent_dev = NULL; #ifdef CUSTOMER_HW4_DEBUG @@ -513,14 +546,14 @@ static s32 wl_cfg80211_del_station(struct wiphy *wiphy, static s32 wl_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, u8* mac_addr); #endif -#ifdef WLMESH +#ifdef WLMESH_CFG80211 static s32 wl_cfg80211_join_mesh( struct wiphy *wiphy, struct net_device *dev, const struct mesh_config *conf, const struct mesh_setup *setup); static s32 wl_cfg80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev); -#endif /* WLMESH */ +#endif /* WLMESH_CFG80211 */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) static s32 wl_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev, const u8 *mac, struct station_parameters *params); @@ -730,6 +763,10 @@ static s32 wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme); static s32 wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme); +#ifdef BCMWAPI_WPI +static s32 wl_set_set_wapi_ie(struct net_device *dev, + struct cfg80211_connect_params *sme); +#endif static s32 wl_set_set_sharedkey(struct net_device *dev, struct cfg80211_connect_params *sme); static s32 wl_get_assoc_ies(struct bcm_cfg80211 *cfg, struct net_device *ndev); @@ -1047,6 +1084,12 @@ static const u32 __wl_cipher_suites[] = { */ WLAN_CIPHER_SUITE_AES_CMAC, #endif /* MFP */ +#ifdef BCMWAPI_WPI + WLAN_CIPHER_SUITE_SMS4, +#endif +#if defined(WLAN_CIPHER_SUITE_PMK) + WLAN_CIPHER_SUITE_PMK, +#endif }; #ifdef WL_SUPPORT_ACS @@ -1326,13 +1369,13 @@ wl_cfg80211_ether_atoe(const char *a, struct ether_addr *n) /* There isn't a lot of sense in it, but you can transmit anything you like */ static const struct ieee80211_txrx_stypes wl_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { -#ifdef WLMESH +#ifdef WLMESH_CFG80211 [NL80211_IFTYPE_MESH_POINT] = { .tx = 0xffff, .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | BIT(IEEE80211_STYPE_AUTH >> 4) }, -#endif /* WLMESH */ +#endif /* WLMESH_CFG80211 */ [NL80211_IFTYPE_ADHOC] = { .tx = 0xffff, .rx = BIT(IEEE80211_STYPE_ACTION >> 4) @@ -2231,18 +2274,18 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, switch (type) { case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_WDS: -#ifndef WLMESH +#ifndef WLMESH_CFG80211 case NL80211_IFTYPE_MESH_POINT: -#endif /* WLMESH */ +#endif /* WLMESH_CFG80211 */ ap = 1; WL_ERR(("type (%d) : currently we do not support this type\n", type)); break; -#ifdef WLMESH +#ifdef WLMESH_CFG80211 case NL80211_IFTYPE_MESH_POINT: infra_ibss = WL_BSSTYPE_MESH; break; -#endif /* WLMESH */ +#endif /* WLMESH_CFG80211 */ case NL80211_IFTYPE_ADHOC: mode = WL_MODE_IBSS; infra_ibss = 0; @@ -2319,8 +2362,8 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, } wlif_type = WL_P2P_IF_GO; - printf("%s: %s ap (%d), infra_ibss (%d), iftype (%d) conn_idx (%d)\n", - __FUNCTION__, ndev->name, ap, infra_ibss, type, conn_idx); + WL_MSG(ndev->name, "ap (%d), infra_ibss (%d), iftype (%d) conn_idx (%d)\n", + ap, infra_ibss, type, conn_idx); wl_set_p2p_status(cfg, IF_CHANGING); wl_clr_p2p_status(cfg, IF_CHANGED); wl_cfgp2p_ifchange(cfg, wl_to_p2p_bss_macaddr(cfg, conn_idx), @@ -2821,9 +2864,9 @@ wl_run_escan(struct bcm_cfg80211 *cfg, struct net_device *ndev, bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr); + WL_MSG(ndev->name, "LEGACY_SCAN sync ID: %d, bssidx: %d\n", params->sync_id, bssidx); err = wldev_iovar_setbuf(ndev, "escan", params, params_size, cfg->escan_ioctl_buf, WLC_IOCTL_MEDLEN, NULL); - printf("%s: LEGACY_SCAN sync ID: %d, bssidx: %d\n", __FUNCTION__, params->sync_id, bssidx); if (unlikely(err)) { if (err == BCME_EPERM) /* Scan Not permitted at this point of time */ @@ -2956,9 +2999,8 @@ exit: WL_ERR(("error (%d), cnt=%d\n", err, cnt)); // terence 20140111: send disassoc to firmware if (cnt >= 4) { - dev = bcmcfg_to_prmry_ndev(cfg); memset(&scbval, 0, sizeof(scb_val_t)); - wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true); + wldev_ioctl(ndev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true); WL_ERR(("Send disassoc to break the busy dev=%p\n", dev)); cnt = 0; } @@ -3700,7 +3742,7 @@ fail: } #endif /* WLAIBSS_MCHAN */ -#ifdef WLMESH +#ifdef WLMESH_CFG80211 s32 wl_cfg80211_interface_ops(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bsscfg_idx, @@ -4041,6 +4083,12 @@ cfg80211_to_wl_iftype(uint16 type, uint16 *role, uint16 *mode) *role = WLC_E_IF_ROLE_IBSS; *mode = WL_MODE_IBSS; break; +#ifdef WLMESH_CFG80211 + case NL80211_IFTYPE_MESH_POINT: + *role = WLC_E_IF_ROLE_AP; + *mode = WL_MODE_MESH; + break; +#endif default: WL_ERR(("Unknown interface type:0x%x\n", type)); return BCME_ERROR; @@ -4110,6 +4158,12 @@ wl_cfg80211_post_ifcreate(struct net_device *ndev, return NULL; } +#ifdef WL_EXT_IAPSTA + if (wl_ext_check_mesh_creating(ndev)) { + WL_MSG(ndev->name, "change iface_type to NL80211_IFTYPE_MESH_POINT\n"); + iface_type = NL80211_IFTYPE_MESH_POINT; + } +#endif if (cfg80211_to_wl_iftype(iface_type, &role, &mode) < 0) { /* Unsupported operating mode */ WL_ERR(("Unsupported operating mode \n")); @@ -4285,7 +4339,7 @@ wl_cfg80211_create_iface(struct wiphy *wiphy, wl_if_event_info *event = NULL; u8 addr[ETH_ALEN]; struct net_info *iter, *next; -#ifdef WLMESH +#ifdef WLMESH_CFG80211 u16 role = 0, mode = 0; #endif @@ -4389,7 +4443,7 @@ wl_cfg80211_create_iface(struct wiphy *wiphy, } event = &cfg->if_event_info; -#ifdef WLMESH +#ifdef WLMESH_CFG80211 cfg80211_to_wl_iftype(iface_type, &role, &mode); event->role = role; #endif @@ -4470,7 +4524,7 @@ exit: } #endif /* defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF) */ -#ifdef WLMESH +#ifdef WLMESH_CFG80211 s32 wl_cfg80211_set_sae_password(struct net_device *dev, char* buf, int len) { struct bcm_cfg80211 *cfg = wl_get_cfg(dev); @@ -4548,7 +4602,7 @@ static s32 wl_cfg80211_join_mesh( wldev_iovar_setint(dev, "wpa_auth", WPA2_AUTH_PSK); wldev_iovar_setint(dev, "wsec", AES_ENABLED); wldev_iovar_setint(dev, "mfp", WL_MFP_REQUIRED); - printf("%s: password=%s, len=%d\n", __FUNCTION__, + WL_MSG(dev->name, "password=%s, len=%d\n", cfg->sae_password, cfg->sae_password_len); wldev_iovar_setbuf(dev, "sae_password", cfg->sae_password, cfg->sae_password_len, cfg->ioctl_buf, WLC_IOCTL_MAXLEN, NULL); @@ -4619,7 +4673,7 @@ static s32 wl_cfg80211_leave_mesh( return err; } -#endif /* WLMESH */ +#endif /* WLMESH_CFG80211 */ static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, @@ -4879,6 +4933,13 @@ wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme) if (is_wps_conn(sme)) val = WPA_AUTH_DISABLED; +#ifdef BCMWAPI_WPI + if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) { + WL_DBG((" * wl_set_wpa_version, set wpa_auth" + " to WPA_AUTH_WAPI 0x400")); + val = WAPI_AUTH_PSK | WAPI_AUTH_UNSPECIFIED; + } +#endif WL_DBG(("setting wpa_auth to 0x%0x\n", val)); err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx); if (unlikely(err)) { @@ -4889,7 +4950,35 @@ wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme) sec->wpa_versions = sme->crypto.wpa_versions; return err; } + +#ifdef BCMWAPI_WPI +static s32 +wl_set_set_wapi_ie(struct net_device *dev, struct cfg80211_connect_params *sme) +{ + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); + s32 err = 0; + s32 bssidx; + if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) { + WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr)); + return BCME_ERROR; + } + + WL_DBG((" %s \n", __FUNCTION__)); + + if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) { + err = wldev_iovar_setbuf_bsscfg(dev, "wapiie", (void *)sme->ie, sme->ie_len, + cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync); + + if (unlikely(err)) { + WL_ERR(("===> set_wapi_ie Error (%d)\n", err)); + return err; + } + } else + WL_DBG((" * skip \n")); + return err; +} +#endif /* BCMWAPI_WPI */ static s32 wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme) @@ -4918,6 +5007,12 @@ wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme) val = WL_AUTH_OPEN_SHARED; WL_DBG(("automatic\n")); break; +#ifdef WL_SAE + case NL80211_AUTHTYPE_SAE: + val = WL_AUTH_OPEN_SHARED; + WL_DBG(("sae\n")); + break; +#endif /* WL_SAE */ default: val = 2; WL_ERR(("invalid auth type (%d)\n", sme->auth_type)); @@ -4944,6 +5039,9 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme) s32 err = 0; s32 wsec_val = 0; s32 bssidx; +#ifdef BCMWAPI_WPI + s32 val = 0; +#endif if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) { WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr)); @@ -4963,6 +5061,12 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme) case WLAN_CIPHER_SUITE_AES_CMAC: pval = AES_ENABLED; break; +#ifdef BCMWAPI_WPI + case WLAN_CIPHER_SUITE_SMS4: + val = SMS4_ENABLED; + pval = SMS4_ENABLED; + break; +#endif default: WL_ERR(("invalid cipher pairwise (%d)\n", sme->crypto.ciphers_pairwise[0])); @@ -4984,6 +5088,12 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme) case WLAN_CIPHER_SUITE_AES_CMAC: gval = AES_ENABLED; break; +#ifdef BCMWAPI_WPI + case WLAN_CIPHER_SUITE_SMS4: + val = SMS4_ENABLED; + gval = SMS4_ENABLED; + break; +#endif default: WL_ERR(("invalid cipher group (%d)\n", sme->crypto.cipher_group)); @@ -5000,12 +5110,21 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme) /* WPS-2.0 allows no security */ err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx); } else { +#ifdef BCMWAPI_WPI + if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_SMS4) { + WL_DBG((" NO, is_wps_conn, WAPI set to SMS4_ENABLED")); + err = wldev_iovar_setint_bsscfg(dev, "wsec", val, bssidx); + } else { +#endif WL_DBG((" NO, is_wps_conn, Set pval | gval to WSEC")); wsec_val = pval | gval; WL_DBG((" Set WSEC to fW 0x%x \n", wsec_val)); err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec_val, bssidx); +#ifdef BCMWAPI_WPI + } +#endif } if (unlikely(err)) { WL_ERR(("error (%d)\n", err)); @@ -5189,15 +5308,46 @@ wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme) break; #endif /* CUSTOMER_HW6 */ #endif /* MFP */ +#if defined(WLFBT) && defined(WLAN_AKM_SUITE_FT_8021X) + case WLAN_AKM_SUITE_FT_8021X: + val = WPA2_AUTH_UNSPECIFIED | WPA2_AUTH_FT; + break; +#endif +#if defined(WLFBT) && defined(WLAN_AKM_SUITE_FT_PSK) + case WLAN_AKM_SUITE_FT_PSK: + val = WPA2_AUTH_PSK | WPA2_AUTH_FT; + break; +#endif case WLAN_AKM_SUITE_PSK: val = WPA2_AUTH_PSK; break; +#ifdef WL_SAE + case WLAN_AKM_SUITE_SAE: + val = WPA3_AUTH_SAE_PSK; + break; +#endif /* WL_SAE */ default: WL_ERR(("invalid akm suite (0x%x)\n", sme->crypto.akm_suites[0])); return -EINVAL; } } +#ifdef BCMWAPI_WPI + else if (val & (WAPI_AUTH_PSK | WAPI_AUTH_UNSPECIFIED)) { + switch (sme->crypto.akm_suites[0]) { + case WLAN_AKM_SUITE_WAPI_CERT: + val = WAPI_AUTH_UNSPECIFIED; + break; + case WLAN_AKM_SUITE_WAPI_PSK: + val = WAPI_AUTH_PSK; + break; + default: + WL_ERR(("invalid cipher group (%d)\n", + sme->crypto.cipher_group)); + return -EINVAL; + } + } +#endif #ifdef MFP if ((err = wl_cfg80211_set_mfp(cfg, dev, sme)) < 0) { @@ -5241,9 +5391,17 @@ wl_set_set_sharedkey(struct net_device *dev, WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n", sec->wpa_versions, sec->cipher_pairwise)); if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 | +#ifdef BCMWAPI_WPI + NL80211_WPA_VERSION_2 | NL80211_WAPI_VERSION_1)) && +#else NL80211_WPA_VERSION_2)) && +#endif (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 | - WLAN_CIPHER_SUITE_WEP104))) +#ifdef BCMWAPI_WPI + WLAN_CIPHER_SUITE_WEP104 | WLAN_CIPHER_SUITE_SMS4))) +#else + WLAN_CIPHER_SUITE_WEP104))) +#endif { memset(&key, 0, sizeof(key)); key.len = (u32) sme->key_len; @@ -5261,6 +5419,11 @@ wl_set_set_sharedkey(struct net_device *dev, case WLAN_CIPHER_SUITE_WEP104: key.algo = CRYPTO_ALGO_WEP128; break; +#ifdef BCMWAPI_WPI + case WLAN_CIPHER_SUITE_SMS4: + key.algo = CRYPTO_ALGO_SMS4; + break; +#endif default: WL_ERR(("Invalid algorithm (%d)\n", sme->crypto.ciphers_pairwise[0])); @@ -5352,6 +5515,10 @@ int wl_cfg80211_cleanup_mismatch_status(struct net_device *dev, struct bcm_cfg80 if (wait_cnt == 0) { WL_ERR(("DISCONNECING clean up failed!\n")); + /* Clear DISCONNECTING driver status as we have made sufficient attempts + * for driver clean up. + */ + wl_clr_drv_status(cfg, DISCONNECTING, dev); return BCME_NOTREADY; } return BCME_OK; @@ -5381,6 +5548,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, #if (defined(BCM4359_CHIP) || !defined(ESCAN_RESULT_PATCH)) int wait_cnt; #endif + char sec[32]; WL_DBG(("In\n")); BCM_REFERENCE(dhdp); @@ -5553,8 +5721,16 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, WL_DBG(("No channel info from user space\n")); cfg->channel = 0; } - - +#ifdef BCMWAPI_WPI + WL_DBG(("1. enable wapi auth\n")); + if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) { + WL_DBG(("2. set wapi ie \n")); + err = wl_set_set_wapi_ie(dev, sme); + if (unlikely(err)) + goto exit; + } else + WL_DBG(("2. Not wapi ie \n")); +#endif WL_DBG(("3. set wpa version \n")); err = wl_set_wpa_version(dev, sme); @@ -5562,11 +5738,20 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, WL_ERR(("Invalid wpa_version\n")); goto exit; } +#ifdef BCMWAPI_WPI + if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) + WL_DBG(("4. WAPI Dont Set wl_set_auth_type\n")); + else { + WL_DBG(("4. wl_set_auth_type\n")); +#endif err = wl_set_auth_type(dev, sme); if (unlikely(err)) { WL_ERR(("Invalid auth type\n")); goto exit; } +#ifdef BCMWAPI_WPI + } +#endif err = wl_set_set_cipher(dev, sme); if (unlikely(err)) { @@ -5662,21 +5847,25 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, DHD_DISABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub); #endif /* BCMDONGLEHOST && CUSTOMER_HW2 */ #ifdef WL_EXT_IAPSTA - wl_ext_iapsta_update_channel(dev, cfg->channel); + wl_ext_iapsta_update_channel(dhdp, dev, cfg->channel); #endif + + wl_ext_get_sec(dev, 0, sec, sizeof(sec)); + if (cfg->rcc_enabled) { + WL_MSG(dev->name, "Connecting with " MACDBG " ssid \"%s\", len (%d), " + "sec=%s, with rcc channels\n\n", + MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)), + ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len, sec); + } else { + WL_MSG(dev->name, "Connecting with " MACDBG " ssid \"%s\", len (%d), " + "sec=%s, channel=%d\n\n", + MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)), + ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len, sec, + cfg->channel); + } err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size, cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync); - if (cfg->rcc_enabled) { - printf("Connecting with " MACDBG " ssid \"%s\", len (%d) with rcc channels \n\n", - MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)), - ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len); - } else { - printf("Connecting with " MACDBG " ssid \"%s\", len (%d) channel=%d\n\n", - MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)), - ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len, cfg->channel); - } - kfree(ext_join_params); if (err) { wl_clr_drv_status(cfg, CONNECTING, dev); @@ -5711,8 +5900,8 @@ set_ssid: WL_DBG(("join_param_size %zu\n", join_params_size)); if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) { - WL_INFORM(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID, - join_params.ssid.SSID_len)); + WL_MSG(dev->name, "ssid \"%s\", len (%d)\n", join_params.ssid.SSID, + join_params.ssid.SSID_len); } err = wldev_ioctl_set(dev, WLC_SET_SSID, &join_params, join_params_size); exit: @@ -5722,7 +5911,7 @@ exit: } if (!err) wl_cfg80211_check_in4way(cfg, dev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY, - WL_EXT_STATUS_CONNECTING, NULL); + WL_EXT_STATUS_CONNECTING, NULL); #ifdef WLTDLS /* disable TDLS if number of connected interfaces is >= 1 */ @@ -5762,7 +5951,8 @@ wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, s32 err = 0; u8 *curbssid; dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub); - WL_ERR(("Reason %d\n", reason_code)); + + WL_MSG(dev->name, "Reason %d\n", reason_code); RETURN_EIO_IF_NOT_UP(cfg); act = *(bool *) wl_read_prof(cfg, dev, WL_PROF_ACT); curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID); @@ -6007,6 +6197,12 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev, key.algo = CRYPTO_ALGO_AES_CCM; WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n")); break; +#ifdef BCMWAPI_WPI + case WLAN_CIPHER_SUITE_SMS4: + key.algo = CRYPTO_ALGO_SMS4; + WL_DBG(("WLAN_CIPHER_SUITE_SMS4\n")); + break; +#endif default: WL_ERR(("Invalid cipher (0x%x)\n", params->cipher)); return -EINVAL; @@ -6230,6 +6426,43 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, val = AES_ENABLED; WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n")); break; +#if defined(WLFBT) && defined(WLAN_CIPHER_SUITE_PMK) + case WLAN_CIPHER_SUITE_PMK: { + int j; + wsec_pmk_t pmk; + char keystring[WSEC_MAX_PSK_LEN + 1]; + char* charptr = keystring; + uint len; + struct wl_security *sec; + sec = wl_read_prof(cfg, dev, WL_PROF_SEC); + if (sec->wpa_auth == WLAN_AKM_SUITE_8021X) { + err = wldev_iovar_setbuf(dev, "okc_info_pmk", (void *)params->key, + WSEC_MAX_PSK_LEN / 2, keystring, sizeof(keystring), NULL); + if (err) { + /* could fail in case that 'okc' is not supported */ + WL_INFORM(("Setting 'okc_info_pmk' failed, err=%d\n", err)); + } + } + /* copy the raw hex key to the appropriate format */ + for (j = 0; j < (WSEC_MAX_PSK_LEN / 2); j++) { + charptr += snprintf(charptr, sizeof(keystring), "%02x", params->key[j]); + } + len = strlen(keystring); + pmk.key_len = htod16(len); + bcopy(keystring, pmk.key, len); + pmk.flags = htod16(WSEC_PASSPHRASE); + err = wldev_ioctl(dev, WLC_SET_WSEC_PMK, &pmk, sizeof(pmk), true); + if (err) + return err; + } break; +#endif /* WLFBT && WLAN_CIPHER_SUITE_PMK */ +#ifdef BCMWAPI_WPI + case WLAN_CIPHER_SUITE_SMS4: + key.algo = CRYPTO_ALGO_SMS4; + WL_DBG(("WLAN_CIPHER_SUITE_SMS4\n")); + val = SMS4_ENABLED; + break; +#endif /* BCMWAPI_WPI */ default: WL_ERR(("Invalid cipher (0x%x)\n", params->cipher)); return -EINVAL; @@ -6382,6 +6615,12 @@ wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev, params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n")); break; +#endif +#ifdef BCMWAPI_WPI + case SMS4_ENABLED: + params.cipher = WLAN_CIPHER_SUITE_SMS4; + WL_DBG(("WLAN_CIPHER_SUITE_SMS4\n")); + break; #endif default: WL_ERR(("Invalid algo (0x%x)\n", wsec)); @@ -6419,9 +6658,7 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, s32 rate; s32 err = 0; sta_info_t *sta; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) s8 eabuf[ETHER_ADDR_STR_LEN]; -#endif dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub); bool fw_assoc_state = FALSE; u32 dhd_assoc_state = 0; @@ -6448,10 +6685,10 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, sinfo->filled |= STA_INFO_BIT(INFO_CONNECTED_TIME); sinfo->connected_time = sta->in; } - WL_INFORM(("STA %s : idle time : %d sec, connected time :%d ms\n", - bcm_ether_ntoa((const struct ether_addr *)mac, eabuf), sinfo->inactive_time, - sta->idle * 1000)); #endif + WL_INFORM(("STA %s, flags 0x%x, idle time %ds, connected time %ds\n", + bcm_ether_ntoa((const struct ether_addr *)mac, eabuf), + sta->flags, sta->idle, sta->in)); } else if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_BSS || wl_get_mode_by_netdev(cfg, dev) == WL_MODE_IBSS) { get_pktcnt_t pktcnt; @@ -6597,8 +6834,8 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, (uint32)dtoh64(if_stats->txrunt) + (uint32)dtoh64(if_stats->txfail); } else { - WL_ERR(("%s: if_counters not supported ret=%d\n", - __FUNCTION__, err)); +// WL_ERR(("%s: if_counters not supported ret=%d\n", +// __FUNCTION__, err)); #endif /* DHD_SUPPORT_IF_CNTS */ err = wldev_ioctl_get(dev, WLC_GET_PKTCNTS, &pktcnt, @@ -6839,7 +7076,7 @@ wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list, struct net_device *primary_dev = bcmcfg_to_prmry_ndev(cfg); if (!pmk_list) { - printf("pmk_list is NULL\n"); + WL_MSG(dev->name, "pmk_list is NULL\n"); return -EINVAL; } /* pmk list is supported only for STA interface i.e. primary interface @@ -7064,7 +7301,7 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev, #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST if (wl_get_drv_status(cfg, SCANNING, ndev)) { - struct timer_list *_timer; + timer_list_compat_t *_timer; WL_DBG(("scan is running. go to fake listen state\n")); if (duration > LONG_LISTEN_TIME) { @@ -8062,17 +8299,17 @@ wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, } param = {0, 0}; struct bcm_cfg80211 *cfg = wiphy_priv(wiphy); #if defined(CUSTOM_SET_CPUCORE) || (defined(WL_VIRTUAL_APSTA) && \ - defined(APSTA_RESTRICTED_CHANNEL)) + defined(APSTA_RESTRICTED_CHANNEL)) || defined(WL_EXT_IAPSTA) dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub); #endif /* CUSTOM_SET_CPUCORE || (WL_VIRTUAL_APSTA && APSTA_RESTRICTED_CHANNEL) */ dev = ndev_to_wlc_ndev(dev, cfg); _chan = ieee80211_frequency_to_channel(chan->center_freq); #ifdef WL_EXT_IAPSTA - _chan = wl_ext_iapsta_update_channel(dev, _chan); + _chan = wl_ext_iapsta_update_channel(dhd, dev, _chan); #endif - printf("%s: netdev_ifidx(%d), chan_type(%d) target channel(%d) \n", - __FUNCTION__, dev->ifindex, channel_type, _chan); + WL_MSG(dev->name, "netdev_ifidx(%d), chan_type(%d) target channel(%d) \n", + dev->ifindex, channel_type, _chan); #if defined(WL_VIRTUAL_APSTA) && defined(APSTA_RESTRICTED_CHANNEL) @@ -8303,6 +8540,11 @@ wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx) case WPA_CIPHER_AES_CCM: gval = AES_ENABLED; break; +#ifdef BCMWAPI_WPI + case WAPI_CIPHER_SMS4: + gval = SMS4_ENABLED; + break; +#endif default: WL_ERR(("No Security Info\n")); break; @@ -8327,6 +8569,11 @@ wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx) case WPA_CIPHER_AES_CCM: pval = AES_ENABLED; break; +#ifdef BCMWAPI_WPI + case WAPI_CIPHER_SMS4: + pval = SMS4_ENABLED; + break; +#endif default: WL_ERR(("No Security Info\n")); } @@ -8357,6 +8604,12 @@ wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx) wpa_auth |= WPA2_AUTH_1X_SHA256; break; #endif /* MFP */ +#ifdef WL_SAE + case RSN_AKM_SAE_PSK: + case RSN_AKM_SAE_FBT: + wpa_auth |= WPA3_AUTH_SAE_PSK; + break; +#endif /* WL_SAE */ default: WL_ERR(("No Key Mgmt Info\n")); } @@ -9107,7 +9360,7 @@ wl_cfg80211_bcn_bringup_ap( s32 join_params_size = 0; s32 ap = 1; s32 wsec; -#ifdef WLMESH +#ifdef WLMESH_CFG80211 bool retried = false; #endif #ifdef SOFTAP_UAPSD_OFF @@ -9116,9 +9369,8 @@ wl_cfg80211_bcn_bringup_ap( s32 err = BCME_OK; s32 is_rsdb_supported = BCME_ERROR; u32 timeout; -#if defined(DHD_DEBUG) && defined(DHD_FW_COREDUMP) dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub); -#endif /* DHD_DEBUG && DHD_FW_COREDUMP */ + char sec[32]; is_rsdb_supported = DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_RSDB_MODE); if (is_rsdb_supported < 0) @@ -9139,6 +9391,8 @@ wl_cfg80211_bcn_bringup_ap( /* Do abort scan before creating GO */ wl_cfg80211_scan_abort(cfg); + wl_ext_get_sec(dev, 0, sec, sizeof(sec)); + WL_MSG(dev->name, "Creating AP/GO with sec=%s\n", sec); if (dev_role == NL80211_IFTYPE_P2P_GO) { is_bssup = wl_cfg80211_bss_isup(dev, bssidx); if (!is_bssup && (ies->wpa2_ie != NULL)) { @@ -9253,7 +9507,7 @@ wl_cfg80211_bcn_bringup_ap( } #endif /* MFP */ -#ifdef WLMESH +#ifdef WLMESH_CFG80211 ssid_retry: #endif memset(&join_params, 0, sizeof(join_params)); @@ -9288,7 +9542,7 @@ ssid_retry: timeout = wait_event_interruptible_timeout(cfg->netif_change_event, wl_get_drv_status(cfg, AP_CREATED, dev), msecs_to_jiffies(MAX_AP_LINK_WAIT_TIME)); if (timeout <= 0 || !wl_get_drv_status(cfg, AP_CREATED, dev)) { -#ifdef WLMESH +#ifdef WLMESH_CFG80211 if (!retried) { retried = true; WL_ERR(("Link up didn't come for AP interface. Try to set ssid again to recover it! \n")); @@ -9584,10 +9838,13 @@ wl_cfg80211_del_station( } else { #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */ #endif /* CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE */ + scb_val.val = DOT11_RC_DEAUTH_LEAVING; + WL_MSG(dev->name, "Disconnect STA %s scb_val.val %d\n", + bcm_ether_ntoa((const struct ether_addr *)mac_addr, eabuf), + scb_val.val); #ifndef BCMDBUS dhd_wait_pend8021x(dev); #endif /* !BCMDBUS */ - scb_val.val = DOT11_RC_DEAUTH_LEAVING; err = wldev_ioctl_set(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val, sizeof(scb_val_t)); if (err < 0) @@ -9597,9 +9854,6 @@ wl_cfg80211_del_station( } #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */ #endif /* CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE */ - printf("%s: Disconnect STA : %s scb_val.val %d\n", __FUNCTION__, - bcm_ether_ntoa((const struct ether_addr *)mac_addr, eabuf), - scb_val.val); if (num_associated > 0 && ETHER_ISBCAST(mac_addr)) wl_delay(400); @@ -9714,7 +9968,7 @@ wl_cfg80211_start_ap( s32 bssidx = 0; u32 dev_role = 0; dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub); -#ifdef WLMESH +#ifdef WLMESH_CFG80211 struct wl_join_params join_params; s32 join_params_size = 0; #endif @@ -9818,7 +10072,7 @@ wl_cfg80211_start_ap( // goto fail; } -#ifdef WLMESH +#ifdef WLMESH_CFG80211 OSL_SLEEP(1000); if ((dev_role == NL80211_IFTYPE_P2P_GO) || (dev_role == NL80211_IFTYPE_AP)) { memset(&join_params, 0, sizeof(join_params)); @@ -10233,6 +10487,8 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, /* Set GC/STA SCB expiry timings. */ if ((err = wl_cfg80211_set_scb_timings(cfg, dev))) { WL_ERR(("scb setting failed \n")); + if (err == BCME_UNSUPPORTED) + err = 0; // goto fail; } @@ -10764,10 +11020,10 @@ static struct cfg80211_ops wl_cfg80211_ops = { .change_station = wl_cfg80211_change_station, .mgmt_tx_cancel_wait = wl_cfg80211_mgmt_tx_cancel_wait, #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VERSION >= (3,2,0) */ -#ifdef WLMESH +#ifdef WLMESH_CFG80211 .join_mesh = wl_cfg80211_join_mesh, .leave_mesh = wl_cfg80211_leave_mesh, -#endif /* WLMESH */ +#endif /* WLMESH_CFG80211 */ #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) .tdls_mgmt = wl_cfg80211_tdls_mgmt, .tdls_oper = wl_cfg80211_tdls_oper, @@ -10796,7 +11052,7 @@ s32 wl_mode_to_nl80211_iftype(s32 mode) return NL80211_IFTYPE_ADHOC; case WL_MODE_AP: return NL80211_IFTYPE_AP; -#ifdef WLMESH +#ifdef WLMESH_CFG80211 case WL_MODE_MESH: return NL80211_IFTYPE_MESH_POINT; #endif @@ -10918,7 +11174,7 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */ #endif /* WL_SCHED_SCAN */ -#ifdef WLMESH +#ifdef WLMESH_CFG80211 wdev->wiphy->flags |= WIPHY_FLAG_MESH_AUTH; #endif wdev->wiphy->interface_modes = @@ -10934,9 +11190,9 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev #if defined(WL_CFG80211_P2P_DEV_IF) | BIT(NL80211_IFTYPE_P2P_DEVICE) #endif /* WL_CFG80211_P2P_DEV_IF */ -#ifdef WLMESH +#ifdef WLMESH_CFG80211 | BIT(NL80211_IFTYPE_MESH_POINT) -#endif /* WLMESH */ +#endif /* WLMESH_CFG80211 */ | BIT(NL80211_IFTYPE_AP); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \ @@ -11085,6 +11341,11 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev wdev->wiphy->flags &= ~WIPHY_FLAG_ENFORCE_COMBINATIONS; #endif +#ifdef WL_SAE + WL_ERR(("SAE support\n")); + wdev->wiphy->features |= NL80211_FEATURE_SAE; +#endif /* WL_SAE */ + return err; } @@ -11318,7 +11579,7 @@ static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, struct wl_bss_info *bi return -EINVAL; } channel = ieee80211_get_channel(wiphy, freq); - WL_SCAN(("BSSID %pM, channel %2d(%2d %sMHz), rssi %3d, capa 0x04%x, mgmt_type %d, " + WL_SCAN(("BSSID %pM, channel %3d(%3d %sMHz), rssi %3d, capa 0x04%x, mgmt_type %d, " "frame_len %d, SSID \"%s\"\n", &bi->BSSID, notif_bss_info->channel, CHSPEC_CHANNEL(chanspec), CHSPEC_IS20(chanspec)?"20": @@ -11336,8 +11597,8 @@ static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, struct wl_bss_info *bi signal = notif_bss_info->rssi * 100; if (!mgmt->u.probe_resp.timestamp) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) - struct timespec ts; - get_monotonic_boottime(&ts); + struct osl_timespec ts; + osl_get_monotonic_boottime(&ts); mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000) + ts.tv_nsec / 1000; #else @@ -11537,6 +11798,93 @@ static bool wl_is_nonetwork(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e) return false; } +#ifdef WL_SAE +static s32 +wl_cfg80211_event_sae_key(struct bcm_cfg80211 *cfg, struct net_device *ndev, + wl_sae_key_info_t *sae_key) +{ + struct sk_buff *skb; + gfp_t kflags; + struct wiphy *wiphy = bcmcfg_to_wiphy(cfg); + int err = BCME_OK; + + kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; +#if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \ + LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) + skb = cfg80211_vendor_event_alloc(wiphy, ndev_to_wdev(ndev), BRCM_SAE_VENDOR_EVENT_BUF_LEN, + BRCM_VENDOR_EVENT_SAE_KEY, kflags); +#else + skb = cfg80211_vendor_event_alloc(wiphy, BRCM_SAE_VENDOR_EVENT_BUF_LEN, + BRCM_VENDOR_EVENT_SAE_KEY, kflags); +#endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */ + /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */ + if (!skb) { + WL_ERR(("skb alloc failed")); + err = BCME_NOMEM; + goto done; + } + + WL_INFORM(("Received Sae Key event for "MACDBG" key length %x %x", + MAC2STRDBG(sae_key->peer_mac), sae_key->pmk_len, sae_key->pmkid_len)); + nla_put(skb, BRCM_SAE_KEY_ATTR_PEER_MAC, ETHER_ADDR_LEN, sae_key->peer_mac); + nla_put(skb, BRCM_SAE_KEY_ATTR_PMK, sae_key->pmk_len, sae_key->pmk); + nla_put(skb, BRCM_SAE_KEY_ATTR_PMKID, sae_key->pmkid_len, sae_key->pmkid); + cfg80211_vendor_event(skb, kflags); + +done: + return err; +} + +static s32 +wl_bss_handle_sae_auth(struct bcm_cfg80211 *cfg, struct net_device *ndev, + const wl_event_msg_t *event, void *data) +{ + int err = BCME_OK; + uint status = ntoh32(event->status); + wl_auth_event_t *auth_data; + wl_sae_key_info_t sae_key; + uint16 tlv_buf_len; + + if (status == WLC_E_STATUS_SUCCESS) { + auth_data = (wl_auth_event_t *)data; + if (auth_data->version != WL_AUTH_EVENT_DATA_V1) { + WL_ERR(("unknown auth event data version %x\n", + auth_data->version)); + err = BCME_VERSION; + goto done; + } + + tlv_buf_len = auth_data->length - WL_AUTH_EVENT_FIXED_LEN_V1; + + /* check if PMK info present */ + sae_key.pmk = bcm_get_data_from_xtlv_buf(auth_data->xtlvs, tlv_buf_len, + WL_AUTH_PMK_TLV_ID, &(sae_key.pmk_len), BCM_XTLV_OPTION_ALIGN32); + if (!sae_key.pmk || !sae_key.pmk_len) { + WL_ERR(("Mandatory PMK info not present")); + err = BCME_NOTFOUND; + goto done; + } + /* check if PMKID info present */ + sae_key.pmkid = bcm_get_data_from_xtlv_buf(auth_data->xtlvs, tlv_buf_len, + WL_AUTH_PMKID_TLV_ID, &(sae_key.pmkid_len), BCM_XTLV_OPTION_ALIGN32); + if (!sae_key.pmkid || !sae_key.pmkid_len) { + WL_ERR(("Mandatory PMKID info not present\n")); + err = BCME_NOTFOUND; + goto done; + } + memcpy(sae_key.peer_mac, event->addr.octet, ETHER_ADDR_LEN); + err = wl_cfg80211_event_sae_key(cfg, ndev, &sae_key); + if (err) { + WL_ERR(("Failed to event sae key info\n")); + } + } else { + WL_ERR(("sae auth status failure:%d\n", status)); + } +done: + return err; +} +#endif /* WL_SAE */ + /* The mainline kernel >= 3.2.0 has support for indicating new/del station * to AP/P2P GO via events. If this change is backported to kernel for which * this driver is being built, then define WL_CFG80211_STA_EVENT. You @@ -11568,7 +11916,6 @@ wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev, channel_info_t ci; #else struct station_info sinfo; - memset(&sinfo, 0, sizeof(sinfo)); #endif WL_DBG(("event %d status %d reason %d\n", event, ntoh32(e->status), reason)); @@ -11576,7 +11923,7 @@ wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev, if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS && wl_get_p2p_status(cfg, IF_DELETING) && (ndev != bcmcfg_to_prmry_ndev(cfg))) { wl_add_remove_eventmsg(ndev, WLC_E_PROBREQ_MSG, false); - WL_INFORM(("AP mode link down !! \n")); + WL_MSG(ndev->name, "AP mode link down !! \n"); complete(&cfg->iface_disable); return 0; } @@ -11586,7 +11933,7 @@ wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev, (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP)) { if (!wl_get_drv_status(cfg, AP_CREATED, ndev)) { /* AP/GO brought up successfull in firmware */ - printf("%s: ** AP/GO Link up event **\n", __FUNCTION__); + WL_MSG(ndev->name, "AP/GO Link up\n"); wl_set_drv_status(cfg, AP_CREATED, ndev); wake_up_interruptible(&cfg->netif_change_event); wl_cfg80211_check_in4way(cfg, ndev, 0, WL_EXT_STATUS_AP_ENABLED, NULL); @@ -11595,9 +11942,13 @@ wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev, } if (event == WLC_E_DISASSOC_IND || event == WLC_E_DEAUTH_IND || event == WLC_E_DEAUTH) { - printf("%s: event %s(%d) status %d reason %d\n", __FUNCTION__, + WL_MSG(ndev->name, "event %s(%d) status %d reason %d\n", bcmevent_get_name(event), event, ntoh32(e->status), reason); } +#ifdef WL_SAE + if (event == WLC_E_AUTH_IND) + wl_bss_handle_sae_auth(cfg, ndev, e, data); +#endif /* WL_SAE */ #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) WL_DBG(("Enter \n")); @@ -11609,7 +11960,7 @@ wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev, body = kzalloc(len, GFP_KERNEL); if (body == NULL) { - WL_ERR(("wl_notify_connect_status: Failed to allocate body\n")); + WL_ERR(("Failed to allocate body\n")); return WL_INVALID; } } @@ -11698,6 +12049,7 @@ exit: if (body) kfree(body); #else /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */ + memset(&sinfo, 0, sizeof(struct station_info)); sinfo.filled = 0; if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) && reason == DOT11_SC_SUCCESS) { @@ -11713,18 +12065,18 @@ exit: } sinfo.assoc_req_ies = data; sinfo.assoc_req_ies_len = len; - printf("%s: connected device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet)); + WL_MSG(ndev->name, "connected device "MACDBG"\n", MAC2STRDBG(e->addr.octet)); wl_cfg80211_check_in4way(cfg, ndev, DONT_DELETE_GC_AFTER_WPS, WL_EXT_STATUS_STA_CONNECTED, NULL); cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC); } else if (event == WLC_E_DISASSOC_IND) { - printf("%s: disassociated device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet)); + WL_MSG(ndev->name, "disassociated device "MACDBG"\n", MAC2STRDBG(e->addr.octet)); wl_cfg80211_check_in4way(cfg, ndev, DONT_DELETE_GC_AFTER_WPS, WL_EXT_STATUS_STA_DISCONNECTED, NULL); cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC); } else if ((event == WLC_E_DEAUTH_IND) || ((event == WLC_E_DEAUTH) && (reason != DOT11_RC_RESERVED))) { - printf("%s: deauthenticated device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet)); + WL_MSG(ndev->name, "deauthenticated device "MACDBG"\n", MAC2STRDBG(e->addr.octet)); wl_cfg80211_check_in4way(cfg, ndev, DONT_DELETE_GC_AFTER_WPS, WL_EXT_STATUS_STA_DISCONNECTED, NULL); cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC); @@ -11798,12 +12150,14 @@ s32 wl_cfg80211_get_connect_failed_status(struct net_device *dev, char* cmd, int static s32 wl_get_auth_assoc_status(struct bcm_cfg80211 *cfg, struct net_device *ndev, - const wl_event_msg_t *e) + const wl_event_msg_t *e, void *data) { u32 reason = ntoh32(e->reason); u32 event = ntoh32(e->event_type); + uint auth_type = ntoh32(e->auth_type); struct wl_security *sec = wl_read_prof(cfg, ndev, WL_PROF_SEC); - WL_DBG(("event type : %d, reason : %d\n", event, reason)); + + WL_DBG(("event type : %d, reason : %d, auth_type : %d\n", event, reason, auth_type)); #if defined(DHD_ENABLE_BIGDATA_LOGGING) memcpy(&cfg->event_auth_assoc, e, sizeof(wl_event_msg_t)); @@ -11816,7 +12170,12 @@ wl_get_auth_assoc_status(struct bcm_cfg80211 *cfg, struct net_device *ndev, switch (event) { case WLC_E_ASSOC: case WLC_E_AUTH: - sec->auth_assoc_res_status = reason; + sec->auth_assoc_res_status = reason; +#ifdef WL_SAE + if (event == WLC_E_AUTH && auth_type == DOT11_SAE) { + wl_bss_handle_sae_auth(cfg, ndev, e, data); + } +#endif /* WL_SAE */ default: break; } @@ -12172,6 +12531,185 @@ s32 wl_cfg80211_get_bss_info(struct net_device *dev, char* cmd, int total_len) #endif /* DHD_ENABLE_BIGDATA_LOGGING */ +#ifdef WLMESH_CFG80211 +static s32 +wl_notify_connect_status_mesh(struct bcm_cfg80211 *cfg, struct net_device *ndev, + const wl_event_msg_t *e, void *data) +{ + s32 err = 0; + u32 event = ntoh32(e->event_type); + u32 reason = ntoh32(e->reason); + u32 len = ntoh32(e->datalen); + u32 status = ntoh32(e->status); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) + bool isfree = false; + u8 *mgmt_frame; + u8 bsscfgidx = e->bsscfgidx; + s32 freq; + s32 channel; + u8 *body = NULL; + u16 fc = 0; + + struct ieee80211_supported_band *band; + struct ether_addr da; + struct ether_addr bssid; + struct wiphy *wiphy = bcmcfg_to_wiphy(cfg); + channel_info_t ci; +#else + struct station_info sinfo; +#endif + + WL_DBG(("event %d status %d reason %d\n", event, ntoh32(e->status), reason)); + /* if link down, bsscfg is disabled. */ + if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS && + (ndev != bcmcfg_to_prmry_ndev(cfg))) { + WL_MSG(ndev->name, "Mesh mode link down !! \n"); + return 0; + } + + if ((event == WLC_E_LINK) && (status == WLC_E_STATUS_SUCCESS) && + (reason == WLC_E_REASON_INITIAL_ASSOC)) { + /* AP/GO brought up successfull in firmware */ + WL_MSG(ndev->name, "Mesh Link up\n"); + return 0; + } + + if (event == WLC_E_DISASSOC_IND || event == WLC_E_DEAUTH_IND || event == WLC_E_DEAUTH) { + WL_MSG(ndev->name, "event %s(%d) status %d reason %d\n", + bcmevent_get_name(event), event, ntoh32(e->status), reason); + } + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) + WL_DBG(("Enter \n")); + if (!len && (event == WLC_E_DEAUTH)) { + len = 2; /* reason code field */ + data = &reason; + } + if (len) { + body = kzalloc(len, GFP_KERNEL); + + if (body == NULL) { + WL_ERR(("Failed to allocate body\n")); + return WL_INVALID; + } + } + memset(&bssid, 0, ETHER_ADDR_LEN); + WL_DBG(("Enter event %d ndev %p\n", event, ndev)); + if (wl_get_mode_by_netdev(cfg, ndev) == WL_INVALID) { + kfree(body); + return WL_INVALID; + } + if (len) + memcpy(body, data, len); + + wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr", + NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &cfg->ioctl_buf_sync); + memcpy(da.octet, cfg->ioctl_buf, ETHER_ADDR_LEN); + memset(&bssid, 0, sizeof(bssid)); + err = wldev_ioctl_get(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN); + switch (event) { + case WLC_E_ASSOC_IND: + fc = FC_ASSOC_REQ; + break; + case WLC_E_REASSOC_IND: + fc = FC_REASSOC_REQ; + break; + case WLC_E_DISASSOC_IND: + fc = FC_DISASSOC; + break; + case WLC_E_DEAUTH_IND: + fc = FC_DISASSOC; + break; + case WLC_E_DEAUTH: + fc = FC_DISASSOC; + break; + default: + fc = 0; + goto exit; + } + memset(&ci, 0, sizeof(ci)); + if ((err = wldev_ioctl_get(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci)))) { + kfree(body); + return err; + } + + channel = dtoh32(ci.hw_channel); + if (channel <= CH_MAX_2G_CHANNEL) + band = wiphy->bands[IEEE80211_BAND_2GHZ]; + else + band = wiphy->bands[IEEE80211_BAND_5GHZ]; + if (!band) { + WL_ERR(("No valid band\n")); + if (body) + kfree(body); + return -EINVAL; + } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) + freq = ieee80211_channel_to_frequency(channel); + (void)band->band; +#else + freq = ieee80211_channel_to_frequency(channel, band->band); +#endif + + err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid, + &mgmt_frame, &len, body); + if (err < 0) + goto exit; + isfree = true; + + if ((event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) || + (event == WLC_E_DISASSOC_IND) || + ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH))) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) + cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, 0); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) + cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, 0, GFP_ATOMIC); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \ + defined(WL_COMPAT_WIRELESS) + cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC); +#else + cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); +#endif + } + +exit: + if (isfree) + kfree(mgmt_frame); + if (body) + kfree(body); +#else /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */ + memset(&sinfo, 0, sizeof(struct station_info)); + sinfo.filled = 0; + if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) && + reason == DOT11_SC_SUCCESS) { + /* Linux ver >= 4.0 assoc_req_ies_len is used instead of + * STATION_INFO_ASSOC_REQ_IES flag + */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) + sinfo.filled = STA_INFO_BIT(INFO_ASSOC_REQ_IES); +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) */ + if (!data) { + WL_ERR(("No IEs present in ASSOC/REASSOC_IND")); + return -EINVAL; + } + sinfo.assoc_req_ies = data; + sinfo.assoc_req_ies_len = len; + WL_MSG(ndev->name, "connected device "MACDBG"\n", MAC2STRDBG(e->addr.octet)); + cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC); + } else if (event == WLC_E_DISASSOC_IND) { + WL_MSG(ndev->name, "disassociated device "MACDBG"\n", MAC2STRDBG(e->addr.octet)); + cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC); + } else if ((event == WLC_E_DEAUTH_IND) || + ((event == WLC_E_DEAUTH) && (reason != DOT11_RC_RESERVED))) { + WL_MSG(ndev->name, "deauthenticated device "MACDBG"\n", MAC2STRDBG(e->addr.octet)); + cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC); + } +#endif + return err; +} +#endif + static s32 wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data) @@ -12194,13 +12732,17 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) { err = wl_notify_connect_status_ap(cfg, ndev, e, data); +#ifdef WLMESH_CFG80211 + } else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_MESH) { + err = wl_notify_connect_status_mesh(cfg, ndev, e, data); +#endif } else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_IBSS) { err = wl_notify_connect_status_ibss(cfg, ndev, e, data); } else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_BSS) { - WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n", + WL_DBG(("event %d status : %d ndev %p\n", ntoh32(e->event_type), ntoh32(e->status), ndev)); if (event == WLC_E_ASSOC || event == WLC_E_AUTH) { - wl_get_auth_assoc_status(cfg, ndev, e); + wl_get_auth_assoc_status(cfg, ndev, e, data); return 0; } DHD_DISABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub); @@ -12225,7 +12767,7 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, #endif /* STAT_REPORT */ } - printf("wl_bss_connect_done succeeded with " + WL_MSG(ndev->name, "wl_bss_connect_done succeeded with " MACDBG " %s%s\n", MAC2STRDBG((const u8*)(&e->addr)), vndr_oui_num > 0 ? "vndr_oui: " : "", vndr_oui_num > 0 ? vndr_oui : ""); @@ -12340,7 +12882,7 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, /* WLAN_REASON_UNSPECIFIED is used for hang up event in Android */ reason = (reason == WLAN_REASON_UNSPECIFIED)? 0 : reason; - printf("link down if %s may call cfg80211_disconnected. " + WL_MSG(ndev->name, "link down if %s may call cfg80211_disconnected. " "event : %d, reason=%d from " MACDBG "\n", ndev->name, event, ntoh32(e->reason), MAC2STRDBG((const u8*)(&e->addr))); @@ -12444,15 +12986,13 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, wl_vndr_ies_clear_vendor_oui_list(cfg); } else if (wl_get_drv_status(cfg, CONNECTING, ndev)) { - printf("link down, during connecting\n"); + WL_MSG(ndev->name, "link down, during connecting\n"); /* Issue WLC_DISASSOC to prevent FW roam attempts */ err = wldev_ioctl_set(ndev, WLC_DISASSOC, NULL, 0); if (err < 0) { WL_ERR(("CONNECTING state, WLC_DISASSOC error %d\n", err)); err = 0; } - WL_INFORM(("Clear drv CONNECTING status\n")); - wl_clr_drv_status(cfg, CONNECTING, ndev); #ifdef ESCAN_RESULT_PATCH if ((memcmp(connect_req_bssid, broad_bssid, ETHER_ADDR_LEN) == 0) || (memcmp(&e->addr, broad_bssid, ETHER_ADDR_LEN) == 0) || @@ -12460,6 +13000,8 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, /* In case this event comes while associating another AP */ #endif /* ESCAN_RESULT_PATCH */ wl_bss_connect_done(cfg, ndev, e, data, false); + WL_INFORM(("Clear drv CONNECTING status\n")); + wl_clr_drv_status(cfg, CONNECTING, ndev); } wl_clr_drv_status(cfg, DISCONNECTING, ndev); wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY|WAIT_DISCONNECTED, @@ -12475,7 +13017,7 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, wl_cfg80211_tdls_config(cfg, TDLS_STATE_DISCONNECT, false); #endif /* WLTDLS */ } else if (wl_is_nonetwork(cfg, e)) { - printf("connect failed event=%d e->status %d e->reason %d \n", + WL_MSG(ndev->name, "connect failed event=%d e->status %d e->reason %d \n", event, (int)ntoh32(e->status), (int)ntoh32(e->reason)); wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY|WAIT_DISCONNECTED, WL_EXT_STATUS_DISCONNECTED, NULL); @@ -12504,8 +13046,8 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub); } else { - printf("wl_notify_connect_status : Invalid %s mode %d event %d status %d\n", - ndev->name, wl_get_mode_by_netdev(cfg, ndev), ntoh32(e->event_type), + WL_MSG(ndev->name, "Invalid mode %d event %d status %d\n", + wl_get_mode_by_netdev(cfg, ndev), ntoh32(e->event_type), ntoh32(e->status)); } return err; @@ -13095,10 +13637,7 @@ wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev, struct ieee80211_supported_band *band; struct ieee80211_channel *notify_channel = NULL; u32 freq; -#ifdef BCM4359_CHIP - struct channel_info ci; - u32 cur_channel; -#endif /* BCM4359_CHIP */ + u32 cur_channel, chanspec; #endif #if defined(WLADPS_SEAK_AP_WAR) || defined(WBTEXT) dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub); @@ -13106,6 +13645,11 @@ wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev, #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) struct cfg80211_roam_info roam_info = {}; #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */ +#ifdef WLFBT + uint32 data_len = 0; + if (data) + data_len = ntoh32(e->datalen); +#endif /* WLFBT */ #ifdef WLADPS_SEAK_AP_WAR BCM_REFERENCE(dhdp); @@ -13113,30 +13657,29 @@ wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev, curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID); channel = (u32 *)wl_read_prof(cfg, ndev, WL_PROF_CHAN); -#ifdef BCM4359_CHIP + /* Skip calling cfg80211_roamed If the channels are same and * the current bssid/last_roamed_bssid & the new bssid are same * Also clear timer roam_timeout. * Only used on BCM4359 devices. */ - memset(&ci, 0, sizeof(ci)); - if ((wldev_ioctl_get(ndev, WLC_GET_CHANNEL, &ci, - sizeof(ci))) < 0) { - WL_ERR(("Failed to get current channel !")); - return BCME_ERROR; + err = wldev_iovar_getint(ndev, "chanspec", (s32 *)&chanspec); + if (unlikely(err)) { + return err; } - cur_channel = dtoh32(ci.hw_channel); - if ((*channel == cur_channel) && ((memcmp(curbssid, &e->addr, - ETHER_ADDR_LEN) == 0) || (memcmp(&cfg->last_roamed_addr, - &e->addr, ETHER_ADDR_LEN) == 0))) { - WL_ERR(("BSS already present, Skipping roamed event to" + cur_channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(chanspec)); + WL_DBG(("%d=>%d, %pM(%pM)=>%pM\n", *channel, cur_channel, + curbssid, (const u8*)(&cfg->last_roamed_addr), (const u8*)(&e->addr))); + if ((*channel == cur_channel) && + ((memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) == 0) || + (memcmp(&cfg->last_roamed_addr, &e->addr, ETHER_ADDR_LEN) == 0))) { + WL_DBG(("BSS already present, Skipping roamed event to" " upper layer\n")); #ifdef DHD_LOSSLESS_ROAMING wl_del_roam_timeout(cfg); #endif /* DHD_LOSSLESS_ROAMING */ return err; } -#endif /* BCM4359_CHIP */ wl_get_assoc_ies(cfg, ndev); wl_update_prof(cfg, ndev, NULL, (const void *)(e->addr.octet), WL_PROF_BSSID); @@ -13154,6 +13697,15 @@ wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev, freq = ieee80211_channel_to_frequency(*channel, band->band); notify_channel = ieee80211_get_channel(wiphy, freq); #endif +#ifdef WLFBT + /* back up the given FBT key for the further supplicant request, + * currently not checking the FBT is enabled for current BSS in DHD, + * because the supplicant decides to take it or not. + */ + if (data && (data_len == FBT_KEYLEN)) { + memcpy(cfg->fbt_key, data, FBT_KEYLEN); + } +#endif /* WLFBT */ #ifdef WLADPS_SEAK_AP_WAR if ((dhdp->op_mode & DHD_FLAG_STA_MODE) && (!dhdp->disabled_adps)) { @@ -13166,7 +13718,7 @@ wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev, wl_set_adps_mode(cfg, ndev, enable_mode); } #endif /* WLADPS_SEAK_AP_WAR */ - printf("%s succeeded to " MACDBG " (ch:%d)\n", __FUNCTION__, + WL_MSG(ndev->name, "succeeded to " MACDBG " (ch:%d)\n", MAC2STRDBG((const u8*)(&e->addr)), *channel); wl_cfg80211_check_in4way(cfg, ndev, 0, WL_EXT_STATUS_CONNECTED, NULL); @@ -13341,7 +13893,12 @@ wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev, sec->auth_assoc_res_status = WLAN_STATUS_UNSPECIFIED_FAILURE; } if (completed) { + WL_INFORM(("Report connect result - connection succeeded\n")); wl_cfg80211_check_in4way(cfg, ndev, 0, WL_EXT_STATUS_CONNECTED, NULL); + } else { + WL_MSG(ndev->name, "Report connect result - connection failed\n"); + wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY|WAIT_DISCONNECTED, + WL_EXT_STATUS_DISCONNECTED, NULL); } cfg80211_connect_result(ndev, curbssid, @@ -13354,13 +13911,6 @@ wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev, sec->auth_assoc_res_status : WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL); - if (completed) { - WL_INFORM(("Report connect result - connection succeeded\n")); - } else { - WL_ERR(("Report connect result - connection failed\n")); - wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY|WAIT_DISCONNECTED, - WL_EXT_STATUS_DISCONNECTED, NULL); - } } #ifdef CONFIG_TCPACK_FASTTX if (wl_get_chan_isvht80(ndev, dhdp)) @@ -14331,7 +14881,9 @@ static void wl_init_event_handler(struct bcm_cfg80211 *cfg) #ifdef ENABLE_TEMP_THROTTLING cfg->evt_handler[WLC_E_TEMP_THROTTLE] = wl_check_rx_throttle_status; #endif /* ENABLE_TEMP_THROTTLING */ - +#ifdef WL_SAE + cfg->evt_handler[WLC_E_AUTH_IND] = wl_notify_connect_status; +#endif /* WL_SAE */ } #if defined(STATIC_WL_PRIV_STRUCT) @@ -14507,20 +15059,10 @@ void wl_terminate_event_handler(struct net_device *dev) } } -static void wl_scan_timeout( -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - struct timer_list *t -#else - unsigned long data -#endif -) +static void wl_scan_timeout(unsigned long data) { wl_event_msg_t msg; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - struct bcm_cfg80211 *cfg = from_timer(cfg, t, scan_timeout); -#else struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data; -#endif struct wireless_dev *wdev = NULL; struct net_device *ndev = NULL; struct wl_scan_results *bss_list; @@ -14601,19 +15143,9 @@ static void wl_del_roam_timeout(struct bcm_cfg80211 *cfg) } -static void wl_roam_timeout( -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - struct timer_list *t -#else - unsigned long data -#endif -) +static void wl_roam_timeout(unsigned long data) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - struct bcm_cfg80211 *cfg = from_timer(cfg, t, roam_timeout); -#else struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data; -#endif dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub); WL_ERR(("roam timer expired\n")); @@ -14846,6 +15378,7 @@ static s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg, if (p2p_is_on(cfg)) wl_clr_p2p_status(cfg, SCANNING); wl_clr_drv_status(cfg, SCANNING, dev); + wake_up_interruptible(&dhdp->conf->event_complete); spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags); out: @@ -15123,8 +15656,9 @@ static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, } if (!ndev || (!wl_get_drv_status(cfg, SCANNING, ndev) && !cfg->sched_scan_running)) { - WL_ERR(("escan is not ready ndev %p drv_status 0x%x e_type %d e_states %d\n", - ndev, wl_get_drv_status(cfg, SCANNING, ndev), + WL_ERR_RLMT(("escan is not ready. drv_scan_status 0x%x" + " e_type %d e_states %d\n", + wl_get_drv_status(cfg, SCANNING, ndev), ntoh32(e->event_type), ntoh32(e->status))); goto exit; } @@ -15232,7 +15766,7 @@ static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, remove_lower_rssi = TRUE; #endif /* ESCAN_BUF_OVERFLOW_MGMT */ - WL_SCAN(("%s("MACDBG") RSSI %d flags 0x%x length %d\n", bi->SSID, + WL_DBG(("%s("MACDBG") RSSI %d flags 0x%x length %d\n", bi->SSID, MAC2STRDBG(bi->BSSID.octet), bi->RSSI, bi->flags, bi->length)); for (i = 0; i < list->count; i++) { bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) @@ -15242,7 +15776,7 @@ static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, goto exit; } #ifdef ESCAN_BUF_OVERFLOW_MGMT - WL_SCAN(("%s("MACDBG"), i=%d bss: RSSI %d list->count %d\n", + WL_DBG(("%s("MACDBG"), i=%d bss: RSSI %d list->count %d\n", bss->SSID, MAC2STRDBG(bss->BSSID.octet), i, bss->RSSI, list->count)); @@ -15263,7 +15797,7 @@ static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, (bi->flags & WL_BSS_FLAGS_FROM_BEACON)) goto exit; - WL_SCAN(("%s("MACDBG"), i=%d prev: RSSI %d" + WL_DBG(("%s("MACDBG"), i=%d prev: RSSI %d" " flags 0x%x, new: RSSI %d flags 0x%x\n", bss->SSID, MAC2STRDBG(bi->BSSID.octet), i, bss->RSSI, bss->flags, bi->RSSI, bi->flags)); @@ -15273,7 +15807,7 @@ static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, /* preserve max RSSI if the measurements are * both on-channel or both off-channel */ - WL_SCAN(("%s("MACDBG"), same onchan" + WL_DBG(("%s("MACDBG"), same onchan" ", RSSI: prev %d new %d\n", bss->SSID, MAC2STRDBG(bi->BSSID.octet), bss->RSSI, bi->RSSI)); @@ -15283,7 +15817,7 @@ static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, /* preserve the on-channel rssi measurement * if the new measurement is off channel */ - WL_SCAN(("%s("MACDBG"), prev onchan" + WL_DBG(("%s("MACDBG"), prev onchan" ", RSSI: prev %d new %d\n", bss->SSID, MAC2STRDBG(bi->BSSID.octet), bss->RSSI, bi->RSSI)); @@ -15293,10 +15827,10 @@ static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, if (dtoh32(bss->length) != bi_length) { u32 prev_len = dtoh32(bss->length); - WL_SCAN(("bss info replacement" + WL_DBG(("bss info replacement" " is occured(bcast:%d->probresp%d)\n", bss->ie_length, bi->ie_length)); - WL_SCAN(("%s("MACDBG"), replacement!(%d -> %d)\n", + WL_DBG(("%s("MACDBG"), replacement!(%d -> %d)\n", bss->SSID, MAC2STRDBG(bi->BSSID.octet), prev_len, bi_length)); @@ -15372,7 +15906,7 @@ static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_COMPLETE); cfg->bss_list = wl_escan_get_buf(cfg, FALSE); if (!scan_req_match(cfg)) { - WL_SCAN(("SCAN COMPLETED: scanned AP count=%d\n", + WL_DBG(("SCAN COMPLETED: scanned AP count=%d\n", cfg->bss_list->count)); } wl_inform_bss(cfg); @@ -15560,7 +16094,7 @@ _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") 4 && __GNUC_MINOR__ >= 6)) _Pragma("GCC diagnostic pop") #endif - printf("%s concurrency is enabled\n", cfg->vsdb_mode ? "Multi Channel" : "Same Channel"); + WL_MSG("wlan", "%s concurrency is enabled\n", cfg->vsdb_mode ? "Multi Channel" : "Same Channel"); return; } @@ -15654,13 +16188,7 @@ static s32 wl_init_scan(struct bcm_cfg80211 *cfg) wl_escan_init_sync_id(cfg); /* Init scan_timeout timer */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - timer_setup(&cfg->scan_timeout, wl_scan_timeout, 0); -#else - init_timer(&cfg->scan_timeout); - cfg->scan_timeout.data = (unsigned long) cfg; - cfg->scan_timeout.function = wl_scan_timeout; -#endif + init_timer_compat(&cfg->scan_timeout, wl_scan_timeout, cfg); return err; } @@ -15671,13 +16199,7 @@ static s32 wl_init_roam_timeout(struct bcm_cfg80211 *cfg) int err = 0; /* Init roam timer */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - timer_setup(&cfg->roam_timeout, wl_roam_timeout, 0); -#else - init_timer(&cfg->roam_timeout); - cfg->roam_timeout.data = (unsigned long) cfg; - cfg->roam_timeout.function = wl_roam_timeout; -#endif + init_timer_compat(&cfg->roam_timeout, wl_roam_timeout, cfg); return err; } @@ -15754,11 +16276,9 @@ static void wl_deinit_priv(struct bcm_cfg80211 *cfg) wl_destroy_event_handler(cfg); wl_flush_eq(cfg); wl_link_down(cfg); - if (cfg->scan_timeout.function) - del_timer_sync(&cfg->scan_timeout); + del_timer_sync(&cfg->scan_timeout); #ifdef DHD_LOSSLESS_ROAMING - if (cfg->roam_timeout.function) - del_timer_sync(&cfg->roam_timeout); + del_timer_sync(&cfg->roam_timeout); #endif wl_deinit_priv_mem(cfg); if (wl_cfg80211_netdev_notifier_registered) { @@ -15840,8 +16360,7 @@ static s32 wl_cfg80211_attach_post(struct net_device *ndev) /* Update MAC addr for p2p0 interface here. */ memcpy(cfg->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN); cfg->p2p_net->dev_addr[0] |= 0x02; - printf("%s: p2p_dev_addr="MACDBG "\n", - cfg->p2p_net->name, + WL_MSG(cfg->p2p_net->name, "p2p_dev_addr="MACDBG "\n", MAC2STRDBG(cfg->p2p_net->dev_addr)); } else { WL_ERR(("p2p_net not yet populated." @@ -15900,7 +16419,7 @@ s32 wl_cfg80211_attach(struct net_device *ndev, void *context) kfree(wdev); return -ENOMEM; } -#ifdef WLMESH +#ifdef WLMESH_CFG80211 wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_MESH); #else wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS); @@ -16232,12 +16751,12 @@ static s32 wl_config_ifmode(struct bcm_cfg80211 *cfg, struct net_device *ndev, s mode = WL_MODE_BSS; infra = 1; break; -#ifdef WLMESH +#ifdef WLMESH_CFG80211 case NL80211_IFTYPE_MESH_POINT: mode = WL_MODE_MESH; infra = WL_BSSTYPE_MESH; break; -#endif /* WLMESH */ +#endif /* WLMESH_CFG80211 */ case NL80211_IFTYPE_AP: case NL80211_IFTYPE_P2P_GO: mode = WL_MODE_AP; @@ -17062,9 +17581,9 @@ s32 wl_cfg80211_up(struct net_device *net) return err; } } -#ifdef WLMESH +#ifdef WLMESH_CFG80211 cfg->wdev->wiphy->features |= NL80211_FEATURE_USERSPACE_MPM; -#endif /* WLMESH */ +#endif /* WLMESH_CFG80211 */ err = __wl_cfg80211_up(cfg); if (unlikely(err)) @@ -18130,7 +18649,7 @@ done: WL_ERR(("can't restore auto channel scan state, error = %d\n", ret)); } - printf("%s: %s\n", __FUNCTION__, cmd); + WL_MSG(ndev->name, "%s\n", cmd); return (pos - cmd); } @@ -18370,7 +18889,7 @@ int wl_cfg80211_do_driver_init(struct net_device *net) void wl_cfg80211_enable_trace(u32 level) { wl_dbg_level = level; - printf("%s: wl_dbg_level = 0x%x\n", __FUNCTION__, wl_dbg_level); + WL_MSG("wlan", "wl_dbg_level = 0x%x\n", wl_dbg_level); } #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \ @@ -19364,6 +19883,29 @@ wl_get_public_action(void *frame, u32 frame_len, u8 *ret_action) return BCME_OK; } +#ifdef WLFBT +int +wl_cfg80211_get_fbt_key(struct net_device *dev, uint8 *key, int total_len) +{ + struct bcm_cfg80211 * cfg = wl_get_cfg(dev); + int bytes_written = -1; + + if (total_len < FBT_KEYLEN) { + WL_ERR(("wl_cfg80211_get_fbt_key: Insufficient buffer \n")); + goto end; + } + if (cfg) { + memcpy(key, cfg->fbt_key, FBT_KEYLEN); + bytes_written = FBT_KEYLEN; + } else { + bzero(key, FBT_KEYLEN); + WL_ERR(("wl_cfg80211_get_fbt_key: Failed to copy KCK and KEK \n")); + } + prhex("KCK, KEK", (uchar *)key, FBT_KEYLEN); +end: + return bytes_written; +} +#endif /* WLFBT */ static int wl_cfg80211_delayed_roam(struct bcm_cfg80211 *cfg, struct net_device *ndev, @@ -20071,11 +20613,7 @@ struct wiphy *wiphy) #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) cfg80211_chandef_create(chandef, chan, chan_type); -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \ - \ - \ - \ - 0))) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0))) chaninfo->freq = freq; chaninfo->chan_type = chan_type; #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */ @@ -20088,16 +20626,12 @@ wl_cfg80211_ch_switch_notify(struct net_device *dev, uint16 chanspec, struct wip u32 freq; #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) struct cfg80211_chan_def chandef; -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \ - \ - \ - \ - 0))) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0))) struct chan_info chaninfo; #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */ if (!wiphy) { - printf("wiphy is null\n"); + WL_MSG(dev->name, "wiphy is null\n"); return; } #ifndef ALLOW_CHSW_EVT @@ -20125,7 +20659,8 @@ wl_cfg80211_ch_switch_notify(struct net_device *dev, uint16 chanspec, struct wip cfg80211_ch_switch_notify(dev, freq, chan_info.chan_type); #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */ - WL_ERR(("Channel switch notification for freq: %d chanspec: 0x%x\n", freq, chanspec)); + WL_MSG(dev->name, "Channel switch notification for freq: %d chanspec: 0x%x\n", + freq, chanspec); return; } #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */ @@ -20462,6 +20997,7 @@ wl_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev, struct bcm_cfg80211 *cfg = wiphy_priv(wiphy); s32 err = 0; gtk_keyinfo_t keyinfo; + bcol_gtk_para_t bcol_keyinfo; WL_DBG(("Enter\n")); if (data == NULL || cfg->p2p_net == dev) { @@ -20481,11 +21017,23 @@ wl_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev, bcopy(data->kek, keyinfo.KEK, RSN_KEK_LENGTH); bcopy(data->replay_ctr, keyinfo.ReplayCounter, RSN_REPLAY_LEN); + memset(&bcol_keyinfo, 0, sizeof(bcol_keyinfo)); + bcol_keyinfo.enable = 1; + bcol_keyinfo.ptk_len = 64; + memcpy(&bcol_keyinfo.ptk[0], data->kck, RSN_KCK_LENGTH); + memcpy(&bcol_keyinfo.ptk[RSN_KCK_LENGTH], data->kek, RSN_KEK_LENGTH); + err = wldev_iovar_setbuf(dev, "bcol_gtk_rekey_ptk", &bcol_keyinfo, + sizeof(bcol_keyinfo), cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync); + if (!err) { + return err; + } + if ((err = wldev_iovar_setbuf(dev, "gtk_key_info", &keyinfo, sizeof(keyinfo), cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync)) < 0) { WL_ERR(("seting gtk_key_info failed code=%d\n", err)); return err; } + WL_DBG(("Exit\n")); return err; } @@ -21735,7 +22283,7 @@ wl_cfg80211_autochannel(struct net_device *dev, char* command, int total_len) } else if (cfg->autochannel == 2) { bytes_written = snprintf(command, total_len, "2g=%d 5g=%d", cfg->best_2g_ch, cfg->best_5g_ch); - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); + WL_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); ret = bytes_written; } @@ -21749,15 +22297,23 @@ wl_cfg80211_check_in4way(struct bcm_cfg80211 *cfg, dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub); struct wl_security *sec; s32 bssidx = -1; - int ret = 0, cur_eapol_status; + int ret = 0, cur_eapol_status, ifidx; int max_wait_time, max_wait_cnt; + int suppressed = 0; mutex_lock(&cfg->in4way_sync); - WL_DBG(("status=%d, action=0x%x\n", status, action)); + action = action & dhdp->conf->in4way; + WL_DBG(("status=%d, action=0x%x, in4way=0x%x\n", status, action, dhdp->conf->in4way)); cur_eapol_status = dhdp->conf->eapol_status; switch (status) { case WL_EXT_STATUS_SCAN: + wldev_ioctl(dev, WLC_GET_SCANSUPPRESS, &suppressed, sizeof(int), false); + if (suppressed) { + WL_ERR(("scan suppressed\n")); + ret = -EBUSY; + break; + } if (action & NO_SCAN_IN4WAY) { if (cfg->handshaking > 0 && cfg->handshaking <= 3) { WL_ERR(("return -EBUSY cnt %d\n", cfg->handshaking)); @@ -21768,22 +22324,21 @@ wl_cfg80211_check_in4way(struct bcm_cfg80211 *cfg, } break; case WL_EXT_STATUS_DISCONNECTING: - if (cur_eapol_status >= EAPOL_STATUS_WPA_START && - cur_eapol_status < EAPOL_STATUS_WPA_END) { - ANDROID_ERROR(("%s: WPA failed at %d\n", __FUNCTION__, - cur_eapol_status)); + if (cur_eapol_status >= EAPOL_STATUS_4WAY_START && + cur_eapol_status < EAPOL_STATUS_4WAY_DONE) { + WL_ERR(("WPA failed at %d\n", cur_eapol_status)); dhdp->conf->eapol_status = EAPOL_STATUS_NONE; - } else if (cur_eapol_status >= EAPOL_STATUS_WPS_WSC_START && - cur_eapol_status < EAPOL_STATUS_WPS_DONE) { - ANDROID_ERROR(("%s: WPS failed at %d\n", __FUNCTION__, - cur_eapol_status)); + } else if (cur_eapol_status >= EAPOL_STATUS_WSC_START && + cur_eapol_status < EAPOL_STATUS_WSC_DONE) { + WL_ERR(("WPS failed at %d\n", cur_eapol_status)); dhdp->conf->eapol_status = EAPOL_STATUS_NONE; } if (action & (NO_SCAN_IN4WAY|NO_BTC_IN4WAY)) { if (cfg->handshaking) { - if (action & NO_BTC_IN4WAY) { - WL_TRACE(("status=%d, enable btc_mode\n", status)); - wldev_iovar_setint(dev, "btc_mode", 1); + if ((action & NO_BTC_IN4WAY) && cfg->btc_mode) { + WL_TRACE(("status=%d, restore btc_mode %d\n", + status, cfg->btc_mode)); + wldev_iovar_setint(dev, "btc_mode", cfg->btc_mode); } cfg->handshaking = 0; } @@ -21802,6 +22357,7 @@ wl_cfg80211_check_in4way(struct bcm_cfg80211 *cfg, mutex_lock(&cfg->in4way_sync); max_wait_cnt--; } + wake_up_interruptible(&dhdp->conf->event_complete); } break; case WL_EXT_STATUS_CONNECTING: @@ -21810,11 +22366,15 @@ wl_cfg80211_check_in4way(struct bcm_cfg80211 *cfg, sec = wl_read_prof(cfg, dev, WL_PROF_SEC); if ((sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) && bssidx == 0) { - dhdp->conf->eapol_status = EAPOL_STATUS_WPA_START; + dhdp->conf->eapol_status = EAPOL_STATUS_4WAY_START; cfg->handshaking = 1; if (action & NO_BTC_IN4WAY) { - WL_TRACE(("status=%d, disable btc_mode\n", status)); - wldev_iovar_setint(dev, "btc_mode", 0); + ret = wldev_iovar_getint(dev, "btc_mode", &cfg->btc_mode); + if (!ret && cfg->btc_mode) { + WL_TRACE(("status=%d, disable current btc_mode %d\n", + status, cfg->btc_mode)); + wldev_iovar_setint(dev, "btc_mode", 0); + } } } } @@ -21831,33 +22391,35 @@ wl_cfg80211_check_in4way(struct bcm_cfg80211 *cfg, mutex_lock(&cfg->in4way_sync); max_wait_cnt--; } + wake_up_interruptible(&dhdp->conf->event_complete); } break; case WL_EXT_STATUS_CONNECTED: - if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION) { - dhd_conf_set_wme(cfg->pub, 0); - dhd_conf_set_intiovar(cfg->pub, WLC_SET_VAR, "phy_oclscdenable", - cfg->pub->conf->phy_oclscdenable, 0, FALSE); + ifidx = dhd_net2idx(dhdp->info, dev); + if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION && ifidx >= 0) { + dhd_conf_set_wme(cfg->pub, ifidx, 0); + wake_up_interruptible(&dhdp->conf->event_complete); } else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) { dhd_conf_set_mchan_bw(cfg->pub, WL_P2P_IF_CLIENT, -1); } break; case WL_EXT_STATUS_DISCONNECTED: - if (cur_eapol_status >= EAPOL_STATUS_WPA_START && - cur_eapol_status < EAPOL_STATUS_WPA_END) { - ANDROID_ERROR(("%s: WPA failed at %d\n", __FUNCTION__, cur_eapol_status)); + if (cur_eapol_status >= EAPOL_STATUS_4WAY_START && + cur_eapol_status < EAPOL_STATUS_4WAY_DONE) { + WL_ERR(("WPA failed at %d\n", cur_eapol_status)); dhdp->conf->eapol_status = EAPOL_STATUS_NONE; - } else if (cur_eapol_status >= EAPOL_STATUS_WPS_WSC_START && - cur_eapol_status < EAPOL_STATUS_WPS_DONE) { - ANDROID_ERROR(("%s: WPS failed at %d\n", __FUNCTION__, cur_eapol_status)); + } else if (cur_eapol_status >= EAPOL_STATUS_WSC_START && + cur_eapol_status < EAPOL_STATUS_WSC_DONE) { + WL_ERR(("WPS failed at %d\n", cur_eapol_status)); dhdp->conf->eapol_status = EAPOL_STATUS_NONE; } if (action & (NO_SCAN_IN4WAY|NO_BTC_IN4WAY)) { if (cfg->handshaking) { - if (action & NO_BTC_IN4WAY) { - WL_TRACE(("status=%d, enable btc_mode\n", status)); - wldev_iovar_setint(dev, "btc_mode", 1); + if ((action & NO_BTC_IN4WAY) && cfg->btc_mode) { + WL_TRACE(("status=%d, restore btc_mode %d\n", + status, cfg->btc_mode)); + wldev_iovar_setint(dev, "btc_mode", cfg->btc_mode); } cfg->handshaking = 0; } @@ -21865,22 +22427,26 @@ wl_cfg80211_check_in4way(struct bcm_cfg80211 *cfg, if (action & WAIT_DISCONNECTED) { cfg->disconnected_jiffies = jiffies; } + wake_up_interruptible(&dhdp->conf->event_complete); break; case WL_EXT_STATUS_ADD_KEY: - dhdp->conf->eapol_status = EAPOL_STATUS_WPA_END; + dhdp->conf->eapol_status = EAPOL_STATUS_4WAY_DONE; if (action & (NO_SCAN_IN4WAY|NO_BTC_IN4WAY)) { if (cfg->handshaking) { - if (action & NO_BTC_IN4WAY) { - WL_TRACE(("status=%d, enable btc_mode\n", status)); - wldev_iovar_setint(dev, "btc_mode", 1); + if ((action & NO_BTC_IN4WAY) && cfg->btc_mode) { + WL_TRACE(("status=%d, restore btc_mode %d\n", + status, cfg->btc_mode)); + wldev_iovar_setint(dev, "btc_mode", cfg->btc_mode); } cfg->handshaking = 0; } } + wake_up_interruptible(&dhdp->conf->event_complete); break; case WL_EXT_STATUS_AP_ENABLED: - if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) { - dhd_conf_set_wme(cfg->pub, 1); + ifidx = dhd_net2idx(dhdp->info, dev); + if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP && ifidx >= 0) { + dhd_conf_set_wme(cfg->pub, ifidx, 1); } else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) { dhd_conf_set_mchan_bw(cfg->pub, WL_P2P_IF_GO, -1); @@ -21891,9 +22457,9 @@ wl_cfg80211_check_in4way(struct bcm_cfg80211 *cfg, (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO)) { u8* mac_addr = context; if (mac_addr && memcmp(ðer_bcast, mac_addr, ETHER_ADDR_LEN) && - cur_eapol_status == EAPOL_STATUS_WPS_DONE) { + cur_eapol_status == EAPOL_STATUS_WSC_DONE) { u32 timeout; - max_wait_time = dhdp->conf->max_wait_gc_time; + max_wait_time = 300; WL_TRACE(("status=%d, wps_done=%d, waiting %dms ...\n", status, cfg->wps_done, max_wait_time)); mutex_unlock(&cfg->in4way_sync); @@ -21916,7 +22482,7 @@ wl_cfg80211_check_in4way(struct bcm_cfg80211 *cfg, case WL_EXT_STATUS_STA_DISCONNECTED: if ((action & DONT_DELETE_GC_AFTER_WPS) && (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) && - cur_eapol_status == EAPOL_STATUS_WPS_DONE) { + cur_eapol_status == EAPOL_STATUS_WSC_DONE) { WL_TRACE(("status=%d, wps_done=%d => 0\n", status, cfg->wps_done)); cfg->wps_done = FALSE; } @@ -21924,7 +22490,7 @@ wl_cfg80211_check_in4way(struct bcm_cfg80211 *cfg, case WL_EXT_STATUS_STA_CONNECTED: if ((action & DONT_DELETE_GC_AFTER_WPS) && (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) && - cur_eapol_status == EAPOL_STATUS_WPS_DONE) { + cur_eapol_status == EAPOL_STATUS_WSC_DONE) { WL_TRACE(("status=%d, wps_done=%d => 1\n", status, cfg->wps_done)); cfg->wps_done = TRUE; wake_up_interruptible(&cfg->wps_done_event); diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfg80211.h index 48092808c45f..979bf22ae004 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfg80211.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfg80211.h @@ -52,6 +52,9 @@ struct bcm_cfg80211; struct wl_security; struct wl_ibss; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) +#undef WL_SAE +#endif // endif #define htod32(i) (i) #define htod16(i) (i) @@ -84,116 +87,135 @@ extern char *dhd_log_dump_get_timestamp(void); #define WL_DBG_LEVEL 0xFF #ifdef CUSTOMER_HW4_DEBUG -#define CFG80211_ERROR_TEXT "CFG80211-INFO2) " +#define CFG80211_ERROR_TEXT "[dhd] CFG80211-INFO2) " #else -#define CFG80211_ERROR_TEXT "CFG80211-ERROR) " +#define CFG80211_ERROR_TEXT "[dhd] CFG80211-ERROR) " #endif /* CUSTOMER_HW4_DEBUG */ #if defined(DHD_DEBUG) #ifdef DHD_LOG_DUMP -#define WL_ERR(args) \ +#define WL_ERR_MSG(x, args...) \ do { \ if (wl_dbg_level & WL_DBG_ERR) { \ - printk(KERN_INFO CFG80211_ERROR_TEXT "%s : ", __func__); \ - printk args; \ + printk(KERN_INFO CFG80211_ERROR_TEXT "%s : " x, __func__, ## args); \ DHD_LOG_DUMP_WRITE("[%s] %s: ", dhd_log_dump_get_timestamp(), __func__); \ - DHD_LOG_DUMP_WRITE args; \ + DHD_LOG_DUMP_WRITE(x, ## args); \ } \ } while (0) #define WL_ERR_MEM(args) \ do { \ if (wl_dbg_level & WL_DBG_ERR) { \ DHD_LOG_DUMP_WRITE("[%s] %s: ", dhd_log_dump_get_timestamp(), __func__); \ - DHD_LOG_DUMP_WRITE args; \ + DHD_LOG_DUMP_WRITE(x, ## args); \ } \ } while (0) -#define WL_ERR_EX(args) \ +#define WL_ERR_EX_MSG(x, args...) \ do { \ if (wl_dbg_level & WL_DBG_ERR) { \ - printk(KERN_INFO CFG80211_ERROR_TEXT "%s : ", __func__); \ - printk args; \ - DHD_LOG_DUMP_WRITE_EX("[%s] %s: ", dhd_log_dump_get_timestamp(), __func__); \ - DHD_LOG_DUMP_WRITE_EX args; \ + printk(KERN_INFO CFG80211_ERROR_TEXT "%s : " x, __func__, ## args); \ + DHD_LOG_DUMP_WRITE_EX("[%s] %s: ", dhd_log_dump_get_timestamp(), __func__); \ + DHD_LOG_DUMP_WRITE_EX(x, ## args); \ } \ } while (0) +#define WL_ERR(x) WL_ERR_MSG x +#define WL_ERR_EX(args) WL_ERR_EX_MSG(args) #else -#define WL_ERR(args) \ +#define WL_ERR_MSG(x, args...) \ do { \ if (wl_dbg_level & WL_DBG_ERR) { \ - printk(KERN_INFO CFG80211_ERROR_TEXT "%s : ", __func__); \ - printk args; \ - } \ + printk(KERN_INFO CFG80211_ERROR_TEXT "%s : " x, __func__, ## args); \ + } \ } while (0) +#define WL_ERR(x) WL_ERR_MSG x #define WL_ERR_MEM(args) WL_ERR(args) #define WL_ERR_EX(args) WL_ERR(args) #endif /* DHD_LOG_DUMP */ #else /* defined(DHD_DEBUG) */ -#define WL_ERR(args) \ +#define WL_ERR_MSG(x, args...) \ do { \ if ((wl_dbg_level & WL_DBG_ERR) && net_ratelimit()) { \ - printk(KERN_INFO CFG80211_ERROR_TEXT "%s : ", __func__); \ - printk args; \ - } \ + printk(KERN_INFO CFG80211_ERROR_TEXT "%s : " x, __func__, ## args); \ + } \ } while (0) +#define WL_ERR(x) WL_ERR_MSG x #define WL_ERR_MEM(args) WL_ERR(args) #define WL_ERR_EX(args) WL_ERR(args) #endif /* defined(DHD_DEBUG) */ +#define WL_PRINT_RATE_LIMIT_PERIOD 4000000000u /* 4s in units of ns */ +#define WL_ERR_RLMT(args) \ +do { \ + if (wl_dbg_level & WL_DBG_ERR) { \ + static uint64 __err_ts = 0; \ + static uint32 __err_cnt = 0; \ + uint64 __cur_ts = 0; \ + __cur_ts = local_clock(); \ + if (__err_ts == 0 || (__cur_ts > __err_ts && \ + (__cur_ts - __err_ts > WL_PRINT_RATE_LIMIT_PERIOD))) { \ + __err_ts = __cur_ts; \ + WL_ERR(args); \ + WL_ERR(("[Repeats %u times]\n", __err_cnt)); \ + __err_cnt = 0; \ + } else { \ + ++__err_cnt; \ + } \ + } \ +} while (0) + #ifdef WL_INFORM #undef WL_INFORM #endif -#define WL_INFORM(args) \ +#define WL_INFORM_MSG(x, args...) \ do { \ if (wl_dbg_level & WL_DBG_INFO) { \ - printk(KERN_INFO "CFG80211-INFO) %s : ", __func__); \ - printk args; \ - } \ + printk(KERN_INFO "[dhd] CFG80211-INFO) %s : " x, __func__, ## args); \ + } \ } while (0) - +#define WL_INFORM(x) WL_INFORM_MSG x #ifdef WL_SCAN #undef WL_SCAN #endif -#define WL_SCAN(args) \ +#define WL_SCAN_MSG(x, args...) \ do { \ if (wl_dbg_level & WL_DBG_SCAN) { \ - printk(KERN_INFO "CFG80211-SCAN) %s :", __func__); \ - printk args; \ + printk(KERN_INFO "[dhd] CFG80211-SCAN) %s :" x, __func__, ## args); \ } \ } while (0) +#define WL_SCAN(x) WL_SCAN_MSG x #ifdef WL_TRACE #undef WL_TRACE #endif -#define WL_TRACE(args) \ +#define WL_TRACE_MSG(x, args...) \ do { \ if (wl_dbg_level & WL_DBG_TRACE) { \ - printk(KERN_INFO "CFG80211-TRACE) %s :", __func__); \ - printk args; \ + printk(KERN_INFO "[dhd] CFG80211-TRACE) %s :" x, __func__, ## args); \ } \ } while (0) +#define WL_TRACE(x) WL_TRACE_MSG x #ifdef WL_TRACE_HW4 #undef WL_TRACE_HW4 #endif #ifdef CUSTOMER_HW4_DEBUG -#define WL_TRACE_HW4(args) \ +#define WL_TRACE_HW4_MSG(x, args...) \ do { \ if (wl_dbg_level & WL_DBG_ERR) { \ - printk(KERN_INFO "CFG80211-TRACE) %s : ", __func__); \ - printk args; \ - } \ + printk(KERN_INFO "[dhd] CFG80211-TRACE) %s : " x, __func__, ## args); \ + } \ } while (0) +#define WL_TRACE_HW4(x) WL_TRACE_HW4_MSG x #else #define WL_TRACE_HW4 WL_TRACE #endif /* CUSTOMER_HW4_DEBUG */ #if (WL_DBG_LEVEL > 0) -#define WL_DBG(args) \ +#define WL_DBG_MSG(x, args...) \ do { \ if (wl_dbg_level & WL_DBG_DBG) { \ - printk(KERN_INFO "CFG80211-DEBUG) %s :", __func__); \ - printk args; \ + printk(KERN_INFO "[dhd] CFG80211-DEBUG) %s :" x, __func__, ## args); \ } \ } while (0) +#define WL_DBG(x) WL_DBG_MSG x #else /* !(WL_DBG_LEVEL > 0) */ #define WL_DBG(args) #endif /* (WL_DBG_LEVEL > 0) */ @@ -207,8 +229,8 @@ do { \ #define IEEE80211_NUM_BANDS NUM_NL80211_BANDS #endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) -#ifdef WLMESH -#undef WLMESH +#ifdef WLMESH_CFG80211 +#undef WLMESH_CFG80211 #endif #endif @@ -341,26 +363,12 @@ enum wl_status { WL_STATUS_NESTED_CONNECT }; -enum wl_ext_status { - WL_EXT_STATUS_DISCONNECTING = 0, - WL_EXT_STATUS_DISCONNECTED, - WL_EXT_STATUS_SCAN, - WL_EXT_STATUS_CONNECTING, - WL_EXT_STATUS_CONNECTED, - WL_EXT_STATUS_ADD_KEY, - WL_EXT_STATUS_AP_ENABLED, - WL_EXT_STATUS_DELETE_STA, - WL_EXT_STATUS_STA_DISCONNECTED, - WL_EXT_STATUS_STA_CONNECTED, - WL_EXT_STATUS_AP_DISABLED -}; - /* wi-fi mode */ enum wl_mode { WL_MODE_BSS, WL_MODE_IBSS, WL_MODE_AP, -#ifdef WLMESH +#ifdef WLMESH_CFG80211 WL_MODE_MESH #endif }; @@ -631,6 +639,9 @@ typedef struct { /* Max length of Interworking element */ #define IW_IES_MAX_BUF_LEN 9 #endif +#ifdef WLFBT +#define FBT_KEYLEN 32 +#endif #define MAX_EVENT_BUF_NUM 16 typedef struct wl_eventmsg_buf { u16 num; @@ -783,7 +794,7 @@ struct bcm_cfg80211 { struct p2p_info *p2p; bool p2p_supported; void *btcoex_info; - struct timer_list scan_timeout; /* Timer for catch scan event timeout */ + timer_list_compat_t scan_timeout; /* Timer for catch scan event timeout */ #if defined(P2P_IE_MISSING_FIX) bool p2p_prb_noti; #endif @@ -797,7 +808,7 @@ struct bcm_cfg80211 { bool sched_scan_running; /* scheduled scan req status */ struct cfg80211_sched_scan_request *sched_scan_req; /* scheduled scan req */ bool scan_suppressed; - struct timer_list scan_supp_timer; + timer_list_compat_t scan_supp_timer; struct work_struct wlan_work; struct mutex event_sync; /* maily for up/down synchronization */ bool disable_roam_event; @@ -817,6 +828,9 @@ struct bcm_cfg80211 { bcm_struct_cfgdev *ibss_cfgdev; /* For AIBSS */ #endif /* WLAIBSS_MCHAN */ bool bss_pending_op; /* indicate where there is a pending IF operation */ +#ifdef WLFBT + uint8 fbt_key[FBT_KEYLEN]; +#endif int roam_offload; #ifdef WL_CFG80211_P2P_DEV_IF bool down_disc_if; @@ -847,7 +861,7 @@ struct bcm_cfg80211 { bool random_mac_enabled; #endif /* SUPPORT_RANDOM_MAC_SCAN */ #ifdef DHD_LOSSLESS_ROAMING - struct timer_list roam_timeout; /* Timer for catch roam timeout */ + timer_list_compat_t roam_timeout; /* Timer for catch roam timeout */ #endif uint16 escan_sync_id_cntr; #ifdef WLTDLS @@ -869,10 +883,10 @@ struct bcm_cfg80211 { #ifdef STAT_REPORT void *stat_report_info; #endif -#ifdef WLMESH +#ifdef WLMESH_CFG80211 char sae_password[SAE_MAX_PASSWD_LEN]; uint sae_password_len; -#endif /* WLMESH */ +#endif /* WLMESH_CFG80211 */ #if defined(RSSIAVG) wl_rssi_cache_ctrl_t g_rssi_cache_ctrl; wl_rssi_cache_ctrl_t g_connected_rssi_cache_ctrl; @@ -886,12 +900,23 @@ struct bcm_cfg80211 { int best_2g_ch; int best_5g_ch; uint handshaking; + int btc_mode; bool wps_done; wait_queue_head_t wps_done_event; struct mutex in4way_sync; ulong disconnected_jiffies; }; +#ifdef WL_SAE +typedef struct wl_sae_key_info { + uint8 peer_mac[ETHER_ADDR_LEN]; + uint16 pmk_len; + uint16 pmkid_len; + const uint8 *pmk; + const uint8 *pmkid; +} wl_sae_key_info_t; +#endif /* WL_SAE */ + #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \ 4 && __GNUC_MINOR__ >= 6)) #define GCC_DIAGNOSTIC_PUSH() \ @@ -1447,7 +1472,20 @@ wl_get_netinfo_by_wdev(struct bcm_cfg80211 *cfg, struct wireless_dev *wdev) (!_sme->crypto.n_ciphers_pairwise) && \ (!_sme->crypto.cipher_group)) +#ifdef WLFBT +#if defined(WLAN_AKM_SUITE_FT_8021X) && defined(WLAN_AKM_SUITE_FT_PSK) +#define IS_AKM_SUITE_FT(sec) (sec->wpa_auth == WLAN_AKM_SUITE_FT_8021X || \ + sec->wpa_auth == WLAN_AKM_SUITE_FT_PSK) +#elif defined(WLAN_AKM_SUITE_FT_8021X) +#define IS_AKM_SUITE_FT(sec) (sec->wpa_auth == WLAN_AKM_SUITE_FT_8021X) +#elif defined(WLAN_AKM_SUITE_FT_PSK) +#define IS_AKM_SUITE_FT(sec) (sec->wpa_auth == WLAN_AKM_SUITE_FT_PSK) +#else #define IS_AKM_SUITE_FT(sec) ({BCM_REFERENCE(sec); FALSE;}) +#endif /* WLAN_AKM_SUITE_FT_8021X && WLAN_AKM_SUITE_FT_PSK */ +#else +#define IS_AKM_SUITE_FT(sec) ({BCM_REFERENCE(sec); FALSE;}) +#endif /* WLFBT */ #define IS_AKM_SUITE_CCKM(sec) ({BCM_REFERENCE(sec); FALSE;}) @@ -1504,7 +1542,7 @@ extern s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len extern s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len); extern s32 wl_cfg80211_set_p2p_ecsa(struct net_device *net, char* buf, int len); extern s32 wl_cfg80211_increase_p2p_bw(struct net_device *net, char* buf, int len); -#ifdef WLMESH +#ifdef WLMESH_CFG80211 extern s32 wl_cfg80211_set_sae_password(struct net_device *net, char* buf, int len); #endif #ifdef WL11ULB @@ -1586,6 +1624,9 @@ extern int wl_cfg80211_set_mgmt_vndr_ies(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, s32 bssidx, s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len); +#ifdef WLFBT +extern int wl_cfg80211_get_fbt_key(struct net_device *dev, uint8 *key, int total_len); +#endif /* Action frame specific functions */ extern u8 wl_get_action_category(void *frame, u32 frame_len); diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfg_btcoex.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfg_btcoex.c index 6d62b3a40f09..4f1200229620 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfg_btcoex.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfg_btcoex.c @@ -45,7 +45,7 @@ extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, #endif struct btcoex_info { - struct timer_list timer; + timer_list_compat_t timer; u32 timer_ms; u32 timer_on; u32 ts_dhcp_start; /* ms ts ecord time stats */ @@ -294,19 +294,9 @@ wl_cfg80211_bt_setflag(struct net_device *dev, bool set) #endif } -static void wl_cfg80211_bt_timerfunc( -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - struct timer_list *t -#else - unsigned long data -#endif -) +static void wl_cfg80211_bt_timerfunc(ulong data) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - struct btcoex_info *bt_local = from_timer(bt_local, t, timer); -#else struct btcoex_info *bt_local = (struct btcoex_info *)data; -#endif WL_TRACE(("Enter\n")); bt_local->timer_on = 0; schedule_work(&bt_local->work); @@ -403,13 +393,7 @@ void* wl_cfg80211_btcoex_init(struct net_device *ndev) btco_inf->ts_dhcp_ok = 0; /* Set up timer for BT */ btco_inf->timer_ms = 10; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - timer_setup(&btco_inf->timer, wl_cfg80211_bt_timerfunc, 0); -#else - init_timer(&btco_inf->timer); - btco_inf->timer.data = (ulong)btco_inf; - btco_inf->timer.function = wl_cfg80211_bt_timerfunc; -#endif + init_timer_compat(&btco_inf->timer, wl_cfg80211_bt_timerfunc, btco_inf); btco_inf->dev = ndev; @@ -506,7 +490,8 @@ int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, dhd_pub_t *dhd, char *co btco_inf->bt_state = BT_DHCP_START; btco_inf->timer_on = 1; - mod_timer(&btco_inf->timer, btco_inf->timer.expires); + mod_timer(&btco_inf->timer, + timer_expires(&btco_inf->timer)); WL_TRACE(("enable BT DHCP Timer\n")); } } diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfgp2p.c index 69f7a050cd14..861a3a1cbbcc 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfgp2p.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfgp2p.c @@ -334,9 +334,6 @@ wl_cfgp2p_init_priv(struct bcm_cfg80211 *cfg) return -ENOMEM; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - cfg->p2p->cfg = cfg; -#endif wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY) = bcmcfg_to_prmry_ndev(cfg); wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_PRIMARY) = 0; wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) = NULL; @@ -1389,21 +1386,10 @@ wl_cfgp2p_listen_complete(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, * so lets do it from thread context. */ void -wl_cfgp2p_listen_expired( -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - struct timer_list *t -#else - ulong data -#endif -) +wl_cfgp2p_listen_expired(unsigned long data) { wl_event_msg_t msg; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - struct p2p_info *p2p = from_timer(p2p, t, listen_timer); - struct bcm_cfg80211 *cfg = p2p->cfg; -#else struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *) data; -#endif struct net_device *ndev; CFGP2P_DBG((" Enter\n")); @@ -1469,7 +1455,7 @@ wl_cfgp2p_discover_listen(struct bcm_cfg80211 *cfg, s32 channel, u32 duration_ms { #define EXTRA_DELAY_TIME 100 s32 ret = BCME_OK; - struct timer_list *_timer; + timer_list_compat_t *_timer; s32 extra_delay; struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg); diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfgp2p.h index ca930acc6553..2099a6020a61 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfgp2p.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfgp2p.h @@ -71,16 +71,13 @@ struct p2p_bss { }; struct p2p_info { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - struct bcm_cfg80211 *cfg; -#endif bool on; /**< p2p on/off switch */ bool scan; int16 search_state; s8 vir_ifname[IFNAMSIZ]; unsigned long status; struct p2p_bss bss[P2PAPI_BSSCFG_MAX]; - struct timer_list listen_timer; + timer_list_compat_t listen_timer; wl_p2p_sched_t noa; wl_p2p_ops_t ops; wlc_ssid_t ssid; @@ -186,23 +183,13 @@ enum wl_cfgp2p_status { printk args; \ } \ } while (0) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) + #define INIT_TIMER(timer, func, duration, extra_delay) \ do { \ - timer_setup(timer, func, 0); \ - timer->expires = jiffies + msecs_to_jiffies(duration + extra_delay); \ + init_timer_compat(timer, func, cfg); \ + timer_expires(timer) = jiffies + msecs_to_jiffies(duration + extra_delay); \ add_timer(timer); \ } while (0); -#else -#define INIT_TIMER(timer, func, duration, extra_delay) \ - do { \ - init_timer(timer); \ - timer->function = func; \ - timer->expires = jiffies + msecs_to_jiffies(duration + extra_delay); \ - timer->data = (unsigned long) cfg; \ - add_timer(timer); \ - } while (0); -#endif #if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 0, 8)) #ifdef WL_SUPPORT_BACKPORTED_KPATCHES @@ -257,13 +244,7 @@ enum wl_cfgp2p_status { #define P2P_ECSA_CNT 50 extern void -wl_cfgp2p_listen_expired( -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - struct timer_list *t -#else - ulong data -#endif -); +wl_cfgp2p_listen_expired(ulong data); extern bool wl_cfgp2p_is_pub_action(void *frame, u32 frame_len); extern bool diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfgvendor.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfgvendor.c index 88a588854fe2..4cd741e0e1ec 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfgvendor.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfgvendor.c @@ -2080,6 +2080,53 @@ wl_cfgvendor_get_ndev(struct bcm_cfg80211 *cfg, struct wireless_dev *wdev, return ndev; } +#ifdef WL_SAE +static int +wl_cfgvendor_set_sae_password(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int len) +{ + int err = BCME_OK; + struct net_device *net = wdev->netdev; + struct bcm_cfg80211 *cfg = wl_get_cfg(net); + wsec_pmk_t pmk; + s32 bssidx; + + /* clear the content of pmk structure before usage */ + (void)memset(&pmk, 0x0, sizeof(wsec_pmk_t)); + + if ((bssidx = wl_get_bssidx_by_wdev(cfg, net->ieee80211_ptr)) < 0) { + WL_ERR(("Find p2p index from wdev(%p) failed\n", net->ieee80211_ptr)); + return BCME_ERROR; + } + + if ((len < WSEC_MIN_PSK_LEN) || (len >= WSEC_MAX_PASSPHRASE_LEN)) { + WL_ERR(("Invalid passphrase length %d..should be >= 8 and < 256\n", + len)); + err = BCME_BADLEN; + goto done; + } + /* Set AUTH to SAE */ + err = wldev_iovar_setint_bsscfg(net, "wpa_auth", WPA3_AUTH_SAE_PSK, bssidx); + if (unlikely(err)) { + WL_ERR(("could not set wpa_auth (0x%x)\n", err)); + goto done; + } + pmk.key_len = htod16(len); + bcopy((const u8*)data, pmk.key, len); + pmk.flags = htod16(WSEC_PASSPHRASE); + + err = wldev_ioctl_set(net, WLC_SET_WSEC_PMK, &pmk, sizeof(pmk)); + if (err) { + WL_ERR(("\n failed to set pmk %d\n", err)); + goto done; + } else { + WL_INFORM(("sae passphrase set successfully\n")); + } +done: + return err; +} +#endif /* WL_SAE */ + /* Max length for the reply buffer. For BRCM_ATTR_DRIVER_CMD, the reply * would be a formatted string and reply buf would be the size of the * string. @@ -3212,6 +3259,16 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, .doit = wl_cfgvendor_priv_bcm_handler }, +#ifdef WL_SAE + { + { + .vendor_id = OUI_BRCM, + .subcmd = BRCM_VENDOR_SCMD_BCM_PSK + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = wl_cfgvendor_set_sae_password + }, +#endif /* WL_SAE */ #ifdef GSCAN_SUPPORT { { @@ -3612,40 +3669,45 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { static const struct nl80211_vendor_cmd_info wl_vendor_events [] = { { OUI_BRCM, BRCM_VENDOR_EVENT_UNSPEC }, { OUI_BRCM, BRCM_VENDOR_EVENT_PRIV_STR }, -#ifdef GSCAN_SUPPORT { OUI_GOOGLE, GOOGLE_GSCAN_SIGNIFICANT_EVENT }, { OUI_GOOGLE, GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT }, { OUI_GOOGLE, GOOGLE_GSCAN_BATCH_SCAN_EVENT }, { OUI_GOOGLE, GOOGLE_SCAN_FULL_RESULTS_EVENT }, -#endif /* GSCAN_SUPPORT */ -#ifdef RTT_SUPPORT { OUI_GOOGLE, GOOGLE_RTT_COMPLETE_EVENT }, -#endif /* RTT_SUPPORT */ -#ifdef GSCAN_SUPPORT { OUI_GOOGLE, GOOGLE_SCAN_COMPLETE_EVENT }, { OUI_GOOGLE, GOOGLE_GSCAN_GEOFENCE_LOST_EVENT }, { OUI_GOOGLE, GOOGLE_SCAN_EPNO_EVENT }, -#endif /* GSCAN_SUPPORT */ { OUI_GOOGLE, GOOGLE_DEBUG_RING_EVENT }, { OUI_GOOGLE, GOOGLE_FW_DUMP_EVENT }, -#ifdef GSCAN_SUPPORT { OUI_GOOGLE, GOOGLE_PNO_HOTSPOT_FOUND_EVENT }, -#endif /* GSCAN_SUPPORT */ { OUI_GOOGLE, GOOGLE_RSSI_MONITOR_EVENT }, { OUI_GOOGLE, GOOGLE_MKEEP_ALIVE_EVENT }, { OUI_GOOGLE, GOOGLE_NAN_EVENT_ENABLED}, { OUI_GOOGLE, GOOGLE_NAN_EVENT_DISABLED}, - { OUI_GOOGLE, GOOGLE_NAN_EVENT_PUBLISH_TERMINATED}, { OUI_GOOGLE, GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH}, - { OUI_GOOGLE, GOOGLE_NAN_EVENT_SUBSCRIBE_UNMATCH}, + { OUI_GOOGLE, GOOGLE_NAN_EVENT_REPLIED}, + { OUI_GOOGLE, GOOGLE_NAN_EVENT_PUBLISH_TERMINATED}, { OUI_GOOGLE, GOOGLE_NAN_EVENT_SUBSCRIBE_TERMINATED}, { OUI_GOOGLE, GOOGLE_NAN_EVENT_DE_EVENT}, { OUI_GOOGLE, GOOGLE_NAN_EVENT_FOLLOWUP}, + { OUI_GOOGLE, GOOGLE_NAN_EVENT_TRANSMIT_FOLLOWUP_IND}, + { OUI_GOOGLE, GOOGLE_NAN_EVENT_DATA_REQUEST}, + { OUI_GOOGLE, GOOGLE_NAN_EVENT_DATA_CONFIRMATION}, + { OUI_GOOGLE, GOOGLE_NAN_EVENT_DATA_END}, + { OUI_GOOGLE, GOOGLE_NAN_EVENT_BEACON}, + { OUI_GOOGLE, GOOGLE_NAN_EVENT_SDF}, { OUI_GOOGLE, GOOGLE_NAN_EVENT_TCA}, -#ifdef NAN_DP - { OUI_GOOGLE, GOOGLE_NAN_EVENT_DATA_PATH_OPEN}, -#endif /* NAN_DP */ - { OUI_GOOGLE, GOOGLE_NAN_EVENT_UNKNOWN} + { OUI_GOOGLE, GOOGLE_NAN_EVENT_SUBSCRIBE_UNMATCH}, + { OUI_GOOGLE, GOOGLE_NAN_EVENT_UNKNOWN}, + { OUI_GOOGLE, GOOGLE_ROAM_EVENT_START}, + { OUI_BRCM, BRCM_VENDOR_EVENT_HANGED}, + { OUI_BRCM, BRCM_VENDOR_EVENT_SAE_KEY}, + { OUI_BRCM, BRCM_VENDOR_EVENT_BEACON_RECV}, + { OUI_BRCM, BRCM_VENDOR_EVENT_PORT_AUTHORIZED}, + { OUI_GOOGLE, GOOGLE_FILE_DUMP_EVENT }, + { OUI_BRCM, BRCM_VENDOR_EVENT_CU}, + { OUI_BRCM, BRCM_VENDOR_EVENT_WIPS}, + { OUI_GOOGLE, NAN_ASYNC_RESPONSE_DISABLED} }; int wl_cfgvendor_attach(struct wiphy *wiphy, dhd_pub_t *dhd) diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfgvendor.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfgvendor.h index 8933548f8058..fa7dd523a3ea 100755 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfgvendor.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfgvendor.h @@ -359,6 +359,12 @@ enum wifi_rssi_monitor_attr { RSSI_MONITOR_ATTRIBUTE_START }; +enum wifi_sae_key_attr { + BRCM_SAE_KEY_ATTR_PEER_MAC, + BRCM_SAE_KEY_ATTR_PMK, + BRCM_SAE_KEY_ATTR_PMKID +}; + enum debug_attributes { DEBUG_ATTRIBUTE_GET_DRIVER, DEBUG_ATTRIBUTE_GET_FW, @@ -395,38 +401,53 @@ enum apf_attributes { }; typedef enum wl_vendor_event { - BRCM_VENDOR_EVENT_UNSPEC, - BRCM_VENDOR_EVENT_PRIV_STR, - GOOGLE_GSCAN_SIGNIFICANT_EVENT, - GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT, - GOOGLE_GSCAN_BATCH_SCAN_EVENT, - GOOGLE_SCAN_FULL_RESULTS_EVENT, - GOOGLE_RTT_COMPLETE_EVENT, - GOOGLE_SCAN_COMPLETE_EVENT, - GOOGLE_GSCAN_GEOFENCE_LOST_EVENT, - GOOGLE_SCAN_EPNO_EVENT, - GOOGLE_DEBUG_RING_EVENT, - GOOGLE_FW_DUMP_EVENT, - GOOGLE_PNO_HOTSPOT_FOUND_EVENT, - GOOGLE_RSSI_MONITOR_EVENT, - GOOGLE_MKEEP_ALIVE_EVENT, + BRCM_VENDOR_EVENT_UNSPEC = 0, + BRCM_VENDOR_EVENT_PRIV_STR = 1, + GOOGLE_GSCAN_SIGNIFICANT_EVENT = 2, + GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT = 3, + GOOGLE_GSCAN_BATCH_SCAN_EVENT = 4, + GOOGLE_SCAN_FULL_RESULTS_EVENT = 5, + GOOGLE_RTT_COMPLETE_EVENT = 6, + GOOGLE_SCAN_COMPLETE_EVENT = 7, + GOOGLE_GSCAN_GEOFENCE_LOST_EVENT = 8, + GOOGLE_SCAN_EPNO_EVENT = 9, + GOOGLE_DEBUG_RING_EVENT = 10, + GOOGLE_FW_DUMP_EVENT = 11, + GOOGLE_PNO_HOTSPOT_FOUND_EVENT = 12, + GOOGLE_RSSI_MONITOR_EVENT = 13, + GOOGLE_MKEEP_ALIVE_EVENT = 14, + /* * BRCM specific events should be placed after * the Generic events so that enums don't mismatch * between the DHD and HAL */ - GOOGLE_NAN_EVENT_ENABLED = 150, - GOOGLE_NAN_EVENT_DISABLED, - GOOGLE_NAN_EVENT_PUBLISH_TERMINATED, - GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH, - GOOGLE_NAN_EVENT_SUBSCRIBE_UNMATCH, - GOOGLE_NAN_EVENT_SUBSCRIBE_TERMINATED, - GOOGLE_NAN_EVENT_DE_EVENT, - GOOGLE_NAN_EVENT_FOLLOWUP, - GOOGLE_NAN_EVENT_TCA, - GOOGLE_NAN_EVENT_DATA_IF_ADD, - GOOGLE_NAN_EVENT_DATA_PATH_OPEN, - GOOGLE_NAN_EVENT_UNKNOWN + GOOGLE_NAN_EVENT_ENABLED = 15, + GOOGLE_NAN_EVENT_DISABLED = 16, + GOOGLE_NAN_EVENT_SUBSCRIBE_MATCH = 17, + GOOGLE_NAN_EVENT_REPLIED = 18, + GOOGLE_NAN_EVENT_PUBLISH_TERMINATED = 19, + GOOGLE_NAN_EVENT_SUBSCRIBE_TERMINATED = 20, + GOOGLE_NAN_EVENT_DE_EVENT = 21, + GOOGLE_NAN_EVENT_FOLLOWUP = 22, + GOOGLE_NAN_EVENT_TRANSMIT_FOLLOWUP_IND = 23, + GOOGLE_NAN_EVENT_DATA_REQUEST = 24, + GOOGLE_NAN_EVENT_DATA_CONFIRMATION = 25, + GOOGLE_NAN_EVENT_DATA_END = 26, + GOOGLE_NAN_EVENT_BEACON = 27, + GOOGLE_NAN_EVENT_SDF = 28, + GOOGLE_NAN_EVENT_TCA = 29, + GOOGLE_NAN_EVENT_SUBSCRIBE_UNMATCH = 30, + GOOGLE_NAN_EVENT_UNKNOWN = 31, + GOOGLE_ROAM_EVENT_START = 32, + BRCM_VENDOR_EVENT_HANGED = 33, + BRCM_VENDOR_EVENT_SAE_KEY = 34, + BRCM_VENDOR_EVENT_BEACON_RECV = 35, + BRCM_VENDOR_EVENT_PORT_AUTHORIZED = 36, + GOOGLE_FILE_DUMP_EVENT = 37, + BRCM_VENDOR_EVENT_CU = 38, + BRCM_VENDOR_EVENT_WIPS = 39, + NAN_ASYNC_RESPONSE_DISABLED = 40 } wl_vendor_event_t; enum andr_wifi_attr { diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.c index 05546127541d..23577579c230 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.c @@ -1,49 +1,34 @@ /* SPDX-License-Identifier: GPL-2.0 */ #if defined(WL_ESCAN) - -#include -#include -#include -#include -#include - -#include #include -#include - #include #include - -#include #include -#include #include #include -/* message levels */ -#define ESCAN_ERROR_LEVEL 0x0001 -#define ESCAN_SCAN_LEVEL 0x0002 -#define ESCAN_TRACE_LEVEL 0x0004 - -#define ESCAN_ERROR(x) \ +#define ESCAN_ERROR(name, arg1, args...) \ do { \ - if (iw_msg_level & ESCAN_ERROR_LEVEL) { \ - printf(KERN_ERR "ESCAN-ERROR) %s : ", __func__); \ - printf x; \ + if (android_msg_level & ANDROID_ERROR_LEVEL) { \ + printk(KERN_ERR "[dhd-%s] ESCAN-ERROR) %s : " arg1, name, __func__, ## args); \ } \ } while (0) -#define ESCAN_SCAN(x) \ +#define ESCAN_TRACE(name, arg1, args...) \ do { \ - if (iw_msg_level & ESCAN_SCAN_LEVEL) { \ - printf(KERN_ERR "ESCAN-SCAN) %s : ", __func__); \ - printf x; \ + if (android_msg_level & ANDROID_TRACE_LEVEL) { \ + printk(KERN_ERR "[dhd-%s] ESCAN-TRACE) %s : " arg1, name, __func__, ## args); \ } \ } while (0) -#define ESCAN_TRACE(x) \ +#define ESCAN_SCAN(name, arg1, args...) \ do { \ - if (iw_msg_level & ESCAN_TRACE_LEVEL) { \ - printf(KERN_ERR "ESCAN-TRACE) %s : ", __func__); \ - printf x; \ + if (android_msg_level & ANDROID_SCAN_LEVEL) { \ + printk(KERN_ERR "[dhd-%s] ESCAN-SCAN) %s : " arg1, name, __func__, ## args); \ + } \ + } while (0) +#define ESCAN_DBG(name, arg1, args...) \ + do { \ + if (android_msg_level & ANDROID_DBG_LEVEL) { \ + printk(KERN_ERR "[dhd-%s] ESCAN-DBG) %s : " arg1, name, __func__, ## args); \ } \ } while (0) @@ -103,8 +88,8 @@ wl_chspec_from_legacy(chanspec_t legacy_chspec) } if (wf_chspec_malformed(chspec)) { - ESCAN_ERROR(("wl_chspec_from_legacy: output chanspec (0x%04X) malformed\n", - chspec)); + ESCAN_ERROR("wlan", "wl_chspec_from_legacy: output chanspec (0x%04X) malformed\n", + chspec); return INVCHANSPEC; } @@ -120,8 +105,8 @@ wl_chspec_to_legacy(chanspec_t chspec) chanspec_t lchspec; if (wf_chspec_malformed(chspec)) { - ESCAN_ERROR(("wl_chspec_to_legacy: input chanspec (0x%04X) malformed\n", - chspec)); + ESCAN_ERROR("wlan", "wl_chspec_to_legacy: input chanspec (0x%04X) malformed\n", + chspec); return INVCHANSPEC; } @@ -149,10 +134,9 @@ wl_chspec_to_legacy(chanspec_t chspec) } else { /* cannot express the bandwidth */ char chanbuf[CHANSPEC_STR_LEN]; - ESCAN_ERROR(( - "wl_chspec_to_legacy: unable to convert chanspec %s (0x%04X) " - "to pre-11ac format\n", - wf_chspec_ntoa(chspec, chanbuf), chspec)); + ESCAN_ERROR("wlan", "wl_chspec_to_legacy: unable to convert chanspec %s " + "(0x%04X) to pre-11ac format\n", + wf_chspec_ntoa(chspec, chanbuf), chspec); return INVCHANSPEC; } @@ -197,7 +181,7 @@ wl_chspec_host_to_driver(int ioctl_ver, chanspec_t chanspec) * Returns INVCHANSPEC on error */ static chanspec_t -wl_ch_host_to_driver(int ioctl_ver, s32 bssidx, u16 channel) +wl_ch_host_to_driver(int ioctl_ver, u16 channel) { chanspec_t chanspec; @@ -215,233 +199,15 @@ wl_ch_host_to_driver(int ioctl_ver, s32 bssidx, u16 channel) return wl_chspec_host_to_driver(ioctl_ver, chanspec); } -static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss) +static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, + struct wl_bss_info *bss) { return bss = bss ? (struct wl_bss_info *)((uintptr) bss + dtoh32(bss->length)) : list->bss_info; } -#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] - -static int -rssi_to_qual(int rssi) -{ - if (rssi <= WL_IW_RSSI_NO_SIGNAL) - return 0; - else if (rssi <= WL_IW_RSSI_VERY_LOW) - return 1; - else if (rssi <= WL_IW_RSSI_LOW) - return 2; - else if (rssi <= WL_IW_RSSI_GOOD) - return 3; - else if (rssi <= WL_IW_RSSI_VERY_GOOD) - return 4; - else - return 5; -} - -#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \ - 4 && __GNUC_MINOR__ >= 6)) -#define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \ -_Pragma("GCC diagnostic push") \ -_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \ -(entry) = list_first_entry((ptr), type, member); \ -_Pragma("GCC diagnostic pop") \ - -#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \ -_Pragma("GCC diagnostic push") \ -_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \ -entry = container_of((ptr), type, member); \ -_Pragma("GCC diagnostic pop") \ - -#else -#define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \ -(entry) = list_first_entry((ptr), type, member); \ - -#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \ -entry = container_of((ptr), type, member); \ - -#endif /* STRICT_GCC_WARNINGS */ - -static unsigned long wl_lock_eq(struct wl_escan_info *escan) -{ - unsigned long flags; - - spin_lock_irqsave(&escan->eq_lock, flags); - return flags; -} - -static void wl_unlock_eq(struct wl_escan_info *escan, unsigned long flags) -{ - spin_unlock_irqrestore(&escan->eq_lock, flags); -} - -static void wl_init_eq(struct wl_escan_info *escan) -{ - spin_lock_init(&escan->eq_lock); - INIT_LIST_HEAD(&escan->eq_list); -} - -static void wl_flush_eq(struct wl_escan_info *escan) -{ - struct escan_event_q *e; - unsigned long flags; - - flags = wl_lock_eq(escan); - while (!list_empty_careful(&escan->eq_list)) { - BCM_SET_LIST_FIRST_ENTRY(e, &escan->eq_list, struct escan_event_q, eq_list); - list_del(&e->eq_list); - kfree(e); - } - wl_unlock_eq(escan, flags); -} - -static struct escan_event_q *wl_deq_event(struct wl_escan_info *escan) -{ - struct escan_event_q *e = NULL; - unsigned long flags; - - flags = wl_lock_eq(escan); - if (likely(!list_empty(&escan->eq_list))) { - BCM_SET_LIST_FIRST_ENTRY(e, &escan->eq_list, struct escan_event_q, eq_list); - list_del(&e->eq_list); - } - wl_unlock_eq(escan, flags); - - return e; -} - -/* - * push event to tail of the queue - */ - static s32 -wl_enq_event(struct wl_escan_info *escan, struct net_device *ndev, u32 event, - const wl_event_msg_t *msg, void *data) -{ - struct escan_event_q *e; - s32 err = 0; - uint32 evtq_size; - uint32 data_len; - unsigned long flags; - gfp_t aflags; - - data_len = 0; - if (data) - data_len = ntoh32(msg->datalen); - evtq_size = sizeof(struct escan_event_q) + data_len; - aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; - e = kzalloc(evtq_size, aflags); - if (unlikely(!e)) { - ESCAN_ERROR(("event alloc failed\n")); - return -ENOMEM; - } - e->etype = event; - memcpy(&e->emsg, msg, sizeof(wl_event_msg_t)); - if (data) - memcpy(e->edata, data, data_len); - flags = wl_lock_eq(escan); - list_add_tail(&e->eq_list, &escan->eq_list); - wl_unlock_eq(escan, flags); - - return err; -} - -static void wl_put_event(struct escan_event_q *e) -{ - kfree(e); -} - -static void wl_wakeup_event(struct wl_escan_info *escan) -{ - dhd_pub_t *dhd = (dhd_pub_t *)(escan->pub); - - if (dhd->up && (escan->event_tsk.thr_pid >= 0)) { - up(&escan->event_tsk.sema); - } -} - -static s32 wl_escan_event_handler(void *data) -{ - struct wl_escan_info *escan = NULL; - struct escan_event_q *e; - tsk_ctl_t *tsk = (tsk_ctl_t *)data; - - escan = (struct wl_escan_info *)tsk->parent; - - printf("tsk Enter, tsk = 0x%p\n", tsk); - - while (down_interruptible (&tsk->sema) == 0) { - SMP_RD_BARRIER_DEPENDS(); - if (tsk->terminated) { - break; - } - while (escan && (e = wl_deq_event(escan))) { - ESCAN_TRACE(("dev=%p, event type (%d), ifidx: %d bssidx: %d \n", - escan->dev, e->etype, e->emsg.ifidx, e->emsg.bsscfgidx)); - - if (e->emsg.ifidx > WL_MAX_IFS) { - ESCAN_ERROR(("Event ifidx not in range. val:%d \n", e->emsg.ifidx)); - goto fail; - } - - if (escan->dev && escan->evt_handler[e->etype]) { - dhd_pub_t *dhd = (struct dhd_pub *)(escan->pub); - if (dhd->busstate == DHD_BUS_DOWN) { - ESCAN_ERROR((": BUS is DOWN.\n")); - } else { - escan->evt_handler[e->etype](escan, &e->emsg, e->edata); - } - } else { - ESCAN_TRACE(("Unknown Event (%d): ignoring\n", e->etype)); - } -fail: - wl_put_event(e); - DHD_EVENT_WAKE_UNLOCK(escan->pub); - } - } - printf("%s: was terminated\n", __FUNCTION__); - complete_and_exit(&tsk->completed, 0); - return 0; -} - -void -wl_escan_event(struct net_device *dev, const wl_event_msg_t * e, void *data) -{ - struct dhd_pub *dhd = dhd_get_pub(dev); - struct wl_escan_info *escan = dhd->escan; - u32 event_type = ntoh32(e->event_type); - - if (!escan || !escan->dev) { - return; - } - - if (escan->event_tsk.thr_pid == -1) { - ESCAN_ERROR(("Event handler is not created\n")); - return; - } - - if (escan == NULL) { - ESCAN_ERROR(("Stale event ignored\n")); - return; - } - - if (event_type == WLC_E_PFN_NET_FOUND) { - ESCAN_TRACE(("PNOEVENT: PNO_NET_FOUND\n")); - } - else if (event_type == WLC_E_PFN_NET_LOST) { - ESCAN_TRACE(("PNOEVENT: PNO_NET_LOST\n")); - } - - DHD_EVENT_WAKE_LOCK(escan->pub); - if (likely(!wl_enq_event(escan, dev, event_type, e, data))) { - wl_wakeup_event(escan); - } else { - DHD_EVENT_WAKE_UNLOCK(escan->pub); - } -} - -static s32 wl_escan_inform_bss(struct wl_escan_info *escan) +wl_escan_inform_bss(struct net_device *dev, struct wl_escan_info *escan) { struct wl_scan_results *bss_list; s32 err = 0; @@ -451,11 +217,15 @@ static s32 wl_escan_inform_bss(struct wl_escan_info *escan) bss_list = escan->bss_list; + ESCAN_SCAN(dev->name, "scanned AP count (%d)\n", bss_list->count); + /* Delete disconnected cache */ #if defined(BSSCACHE) - wl_delete_disconnected_bss_cache(&escan->g_bss_cache_ctrl, (u8*)&escan->disconnected_bssid); + wl_delete_disconnected_bss_cache(&escan->g_bss_cache_ctrl, + (u8*)&escan->disconnected_bssid); #if defined(RSSIAVG) - wl_delete_disconnected_rssi_cache(&escan->g_rssi_cache_ctrl, (u8*)&escan->disconnected_bssid); + wl_delete_disconnected_rssi_cache(&escan->g_rssi_cache_ctrl, + (u8*)&escan->disconnected_bssid); #endif #endif @@ -463,7 +233,7 @@ static s32 wl_escan_inform_bss(struct wl_escan_info *escan) #if defined(RSSIAVG) wl_update_rssi_cache(&escan->g_rssi_cache_ctrl, bss_list); if (!in_atomic()) - wl_update_connected_rssi_cache(escan->dev, &escan->g_rssi_cache_ctrl, &rssi); + wl_update_connected_rssi_cache(dev, &escan->g_rssi_cache_ctrl, &rssi); #endif #if defined(BSSCACHE) wl_update_bss_cache(&escan->g_bss_cache_ctrl, @@ -482,27 +252,24 @@ static s32 wl_escan_inform_bss(struct wl_escan_info *escan) wl_delete_dirty_bss_cache(&escan->g_bss_cache_ctrl); wl_reset_bss_cache(&escan->g_bss_cache_ctrl); if (escan->autochannel) - wl_ext_get_best_channel(escan->dev, &escan->g_bss_cache_ctrl, + wl_ext_get_best_channel(dev, &escan->g_bss_cache_ctrl, escan->ioctl_ver &escan->best_2g_ch, &escan->best_5g_ch); #else if (escan->autochannel) - wl_ext_get_best_channel(escan->dev, bss_list, escan->ioctl_ver, + wl_ext_get_best_channel(dev, bss_list, escan->ioctl_ver, &escan->best_2g_ch, &escan->best_5g_ch); #endif - ESCAN_TRACE(("scanned AP count (%d)\n", bss_list->count)); - return err; } static wl_scan_params_t * -wl_escan_alloc_params(struct wl_escan_info *escan, int channel, - int nprobes, int *out_params_size) +wl_escan_alloc_params(struct net_device *dev, struct wl_escan_info *escan, + int channel, int nprobes, int *out_params_size) { wl_scan_params_t *params; int params_size; int num_chans; - int bssidx = 0; *out_params_size = 0; @@ -510,7 +277,7 @@ wl_escan_alloc_params(struct wl_escan_info *escan, int channel, params_size = WL_SCAN_PARAMS_FIXED_SIZE + 1 * sizeof(uint16); params = (wl_scan_params_t*) kzalloc(params_size, GFP_KERNEL); if (params == NULL) { - ESCAN_ERROR(("mem alloc failed (%d bytes)\n", params_size)); + ESCAN_ERROR(dev->name, "mem alloc failed (%d bytes)\n", params_size); return params; } memset(params, 0, params_size); @@ -528,7 +295,7 @@ wl_escan_alloc_params(struct wl_escan_info *escan, int channel, if (channel == -1) params->channel_list[0] = htodchanspec(channel); else - params->channel_list[0] = wl_ch_host_to_driver(escan->ioctl_ver, bssidx, channel); + params->channel_list[0] = wl_ch_host_to_driver(escan->ioctl_ver, channel); /* Our scan params have 1 channel and 0 ssids */ params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) | @@ -538,78 +305,83 @@ wl_escan_alloc_params(struct wl_escan_info *escan, int channel, return params; } -static void wl_escan_abort(struct wl_escan_info *escan) +static void +wl_escan_abort(struct net_device *dev, struct wl_escan_info *escan) { wl_scan_params_t *params = NULL; s32 params_size = 0; s32 err = BCME_OK; if (!in_atomic()) { /* Our scan params only need space for 1 channel and 0 ssids */ - params = wl_escan_alloc_params(escan, -1, 0, ¶ms_size); + params = wl_escan_alloc_params(dev, escan, -1, 0, ¶ms_size); if (params == NULL) { - ESCAN_ERROR(("scan params allocation failed \n")); + ESCAN_ERROR(dev->name, "scan params allocation failed \n"); err = -ENOMEM; } else { /* Do a scan abort to stop the driver's scan engine */ - err = wldev_ioctl(escan->dev, WLC_SCAN, params, params_size, true); + err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true); if (err < 0) { - ESCAN_ERROR(("scan abort failed \n")); + ESCAN_ERROR(dev->name, "scan abort failed \n"); } kfree(params); } } } -static s32 wl_notify_escan_complete(struct wl_escan_info *escan, bool fw_abort) +static s32 +wl_escan_notify_complete(struct net_device *dev, + struct wl_escan_info *escan, bool fw_abort) { s32 err = BCME_OK; +#if defined(WL_WIRELESS_EXT) int cmd = 0; #if WIRELESS_EXT > 13 union iwreq_data wrqu; char extra[IW_CUSTOM_MAX + 1]; - - memset(extra, 0, sizeof(extra)); #endif +#endif + struct dhd_pub *dhd = dhd_get_pub(dev); - ESCAN_TRACE(("Enter\n")); + ESCAN_TRACE(dev->name, "Enter\n"); - if (!escan || !escan->dev) { - ESCAN_ERROR(("escan or dev is null\n")); - err = BCME_ERROR; - goto out; - } if (fw_abort && !in_atomic()) - wl_escan_abort(escan); + wl_escan_abort(dev, escan); if (timer_pending(&escan->scan_timeout)) del_timer_sync(&escan->scan_timeout); + #if defined(ESCAN_RESULT_PATCH) escan->bss_list = wl_escan_get_buf(escan); - wl_escan_inform_bss(escan); + wl_escan_inform_bss(dev, escan); #endif /* ESCAN_RESULT_PATCH */ + escan->escan_state = ESCAN_STATE_IDLE; + wake_up_interruptible(&dhd->conf->event_complete); + +#if defined(WL_WIRELESS_EXT) #if WIRELESS_EXT > 13 #if WIRELESS_EXT > 14 cmd = SIOCGIWSCAN; #endif - ESCAN_TRACE(("event WLC_E_SCAN_COMPLETE\n")); // terence 20150224: fix "wlan0: (WE) : Wireless Event too big (65306)" memset(&wrqu, 0, sizeof(wrqu)); + memset(extra, 0, sizeof(extra)); if (cmd) { if (cmd == SIOCGIWSCAN) { - wireless_send_event(escan->dev, cmd, &wrqu, NULL); + wireless_send_event(dev, cmd, &wrqu, NULL); } else - wireless_send_event(escan->dev, cmd, &wrqu, extra); + wireless_send_event(dev, cmd, &wrqu, extra); } +#endif #endif -out: return err; } #ifdef ESCAN_BUF_OVERFLOW_MGMT static void -wl_cfg80211_find_removal_candidate(wl_bss_info_t *bss, removal_element_t *candidate) +wl_escan_find_removal_candidate(struct wl_escan_info *escan, + wl_bss_info_t *bss, removal_element_t *candidate) { int idx; for (idx = 0; idx < BUF_OVERFLOW_MGMT_COUNT; idx++) { @@ -627,8 +399,8 @@ wl_cfg80211_find_removal_candidate(wl_bss_info_t *bss, removal_element_t *candid } static void -wl_cfg80211_remove_lowRSSI_info(wl_scan_results_t *list, removal_element_t *candidate, - wl_bss_info_t *bi) +wl_escan_remove_lowRSSI_info(struct net_device *dev, struct wl_escan_info *escan, + wl_scan_results_t *list, removal_element_t *candidate, wl_bss_info_t *bi) { int idx1, idx2; int total_delete_len = 0; @@ -644,8 +416,8 @@ wl_cfg80211_remove_lowRSSI_info(wl_scan_results_t *list, removal_element_t *cand candidate[idx1].RSSI == bss->RSSI && candidate[idx1].length == dtoh32(bss->length)) { u32 delete_len = dtoh32(bss->length); - ESCAN_TRACE(("delete scan info of " MACDBG " to add new AP\n", - MAC2STRDBG(bss->BSSID.octet))); + ESCAN_DBG(dev->name, + "delete scan info of %pM to add new AP\n", &bss->BSSID); if (idx2 < list->count -1) { memmove((u8 *)bss, (u8 *)bss + delete_len, list->buflen - cur_len - delete_len); @@ -665,7 +437,8 @@ wl_cfg80211_remove_lowRSSI_info(wl_scan_results_t *list, removal_element_t *cand } #endif /* ESCAN_BUF_OVERFLOW_MGMT */ -static s32 wl_escan_handler(struct wl_escan_info *escan, +static s32 +wl_escan_handler(struct net_device *dev, struct wl_escan_info *escan, const wl_event_msg_t *e, void *data) { s32 err = BCME_OK; @@ -678,41 +451,44 @@ static s32 wl_escan_handler(struct wl_escan_info *escan, u32 i; u16 channel; - ESCAN_TRACE(("enter event type : %d, status : %d \n", - ntoh32(e->event_type), ntoh32(e->status))); - mutex_lock(&escan->usr_sync); escan_result = (wl_escan_result_t *)data; if (escan->escan_state != ESCAN_STATE_SCANING) { - ESCAN_TRACE(("Not my scan\n")); + ESCAN_DBG(dev->name, "Not my scan\n"); goto exit; } + ESCAN_DBG(dev->name, "enter event type : %d, status : %d \n", + ntoh32(e->event_type), ntoh32(e->status)); + if (status == WLC_E_STATUS_PARTIAL) { - ESCAN_TRACE(("WLC_E_STATUS_PARTIAL \n")); + ESCAN_DBG(dev->name, "WLC_E_STATUS_PARTIAL \n"); if (!escan_result) { - ESCAN_ERROR(("Invalid escan result (NULL pointer)\n")); + ESCAN_ERROR(dev->name, "Invalid escan result (NULL pointer)\n"); goto exit; } if (dtoh16(escan_result->bss_count) != 1) { - ESCAN_ERROR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count)); + ESCAN_ERROR(dev->name, "Invalid bss_count %d: ignoring\n", + escan_result->bss_count); goto exit; } bi = escan_result->bss_info; if (!bi) { - ESCAN_ERROR(("Invalid escan bss info (NULL pointer)\n")); + ESCAN_ERROR(dev->name, "Invalid escan bss info (NULL pointer)\n"); goto exit; } bi_length = dtoh32(bi->length); if (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE)) { - ESCAN_ERROR(("Invalid bss_info length %d: ignoring\n", bi_length)); + ESCAN_ERROR(dev->name, "Invalid bss_info length %d: ignoring\n", + bi_length); goto exit; } /* +++++ terence 20130524: skip invalid bss */ channel = - bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec)); + bi->ctl_ch ? bi->ctl_ch : + CHSPEC_CHANNEL(wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec)); if (!dhd_conf_match_channel(escan->pub, channel)) goto exit; /* ----- terence 20130524: skip invalid bss */ @@ -732,24 +508,24 @@ static s32 wl_escan_handler(struct wl_escan_info *escan, remove_lower_rssi = TRUE; #endif /* ESCAN_BUF_OVERFLOW_MGMT */ - ESCAN_TRACE(("%s("MACDBG") RSSI %d flags 0x%x length %d\n", bi->SSID, - MAC2STRDBG(bi->BSSID.octet), bi->RSSI, bi->flags, bi->length)); + ESCAN_DBG(dev->name, "%s(%pM) RSSI %d flags 0x%x length %d\n", + bi->SSID, &bi->BSSID, bi->RSSI, bi->flags, bi->length); for (i = 0; i < list->count; i++) { bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) : list->bss_info; #ifdef ESCAN_BUF_OVERFLOW_MGMT - ESCAN_TRACE(("%s("MACDBG"), i=%d bss: RSSI %d list->count %d\n", - bss->SSID, MAC2STRDBG(bss->BSSID.octet), - i, bss->RSSI, list->count)); + ESCAN_DBG(dev->name, + "%s(%pM), i=%d bss: RSSI %d list->count %d\n", + bss->SSID, &bss->BSSID, i, bss->RSSI, list->count); if (remove_lower_rssi) - wl_cfg80211_find_removal_candidate(bss, candidate); + wl_escan_find_removal_candidate(escan, bss, candidate); #endif /* ESCAN_BUF_OVERFLOW_MGMT */ if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) && - (CHSPEC_BAND(wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec)) - == CHSPEC_BAND(wl_chspec_driver_to_host(escan->ioctl_ver, bss->chanspec))) && - bi->SSID_len == bss->SSID_len && - !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) { + (CHSPEC_BAND(wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec)) + == CHSPEC_BAND(wl_chspec_driver_to_host(escan->ioctl_ver, bss->chanspec))) && + bi->SSID_len == bss->SSID_len && + !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) { /* do not allow beacon data to update *the data recd from a probe response @@ -758,47 +534,46 @@ static s32 wl_escan_handler(struct wl_escan_info *escan, (bi->flags & WL_BSS_FLAGS_FROM_BEACON)) goto exit; - ESCAN_TRACE(("%s("MACDBG"), i=%d prev: RSSI %d" - " flags 0x%x, new: RSSI %d flags 0x%x\n", - bss->SSID, MAC2STRDBG(bi->BSSID.octet), i, - bss->RSSI, bss->flags, bi->RSSI, bi->flags)); + ESCAN_DBG(dev->name, + "%s(%pM), i=%d prev: RSSI %d flags 0x%x, " + "new: RSSI %d flags 0x%x\n", + bss->SSID, &bi->BSSID, i, bss->RSSI, bss->flags, + bi->RSSI, bi->flags); if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) { /* preserve max RSSI if the measurements are * both on-channel or both off-channel */ - ESCAN_TRACE(("%s("MACDBG"), same onchan" - ", RSSI: prev %d new %d\n", - bss->SSID, MAC2STRDBG(bi->BSSID.octet), - bss->RSSI, bi->RSSI)); + ESCAN_DBG(dev->name, + "%s(%pM), same onchan, RSSI: prev %d new %d\n", + bss->SSID, &bi->BSSID, bss->RSSI, bi->RSSI); bi->RSSI = MAX(bss->RSSI, bi->RSSI); } else if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) && (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) { /* preserve the on-channel rssi measurement * if the new measurement is off channel */ - ESCAN_TRACE(("%s("MACDBG"), prev onchan" - ", RSSI: prev %d new %d\n", - bss->SSID, MAC2STRDBG(bi->BSSID.octet), - bss->RSSI, bi->RSSI)); + ESCAN_DBG(dev->name, + "%s(%pM), prev onchan, RSSI: prev %d new %d\n", + bss->SSID, &bi->BSSID, bss->RSSI, bi->RSSI); bi->RSSI = bss->RSSI; bi->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL; } if (dtoh32(bss->length) != bi_length) { u32 prev_len = dtoh32(bss->length); - ESCAN_TRACE(("bss info replacement" - " is occured(bcast:%d->probresp%d)\n", - bss->ie_length, bi->ie_length)); - ESCAN_TRACE(("%s("MACDBG"), replacement!(%d -> %d)\n", - bss->SSID, MAC2STRDBG(bi->BSSID.octet), - prev_len, bi_length)); + ESCAN_DBG(dev->name, + "bss info replacement occured(bcast:%d->probresp%d)\n", + bss->ie_length, bi->ie_length); + ESCAN_DBG(dev->name, + "%s(%pM), replacement!(%d -> %d)\n", + bss->SSID, &bi->BSSID, prev_len, bi_length); - if (list->buflen - prev_len + bi_length - > ESCAN_BUF_SIZE) { - ESCAN_ERROR(("Buffer is too small: keep the" - " previous result of this AP\n")); + if (list->buflen - prev_len + bi_length > ESCAN_BUF_SIZE) { + ESCAN_ERROR(dev->name, + "Buffer is too small: keep the previous result " + "of this AP\n"); /* Only update RSSI */ bss->RSSI = bi->RSSI; bss->flags |= (bi->flags @@ -823,23 +598,19 @@ static s32 wl_escan_handler(struct wl_escan_info *escan, } if (bi_length > ESCAN_BUF_SIZE - list->buflen) { #ifdef ESCAN_BUF_OVERFLOW_MGMT - wl_cfg80211_remove_lowRSSI_info(list, candidate, bi); + wl_escan_remove_lowRSSI_info(dev, escan, list, candidate, bi); if (bi_length > ESCAN_BUF_SIZE - list->buflen) { - ESCAN_TRACE(("RSSI(" MACDBG ") is too low(%d) to add Buffer\n", - MAC2STRDBG(bi->BSSID.octet), bi->RSSI)); + ESCAN_DBG(dev->name, + "RSSI(%pM) is too low(%d) to add Buffer\n", + &bi->BSSID, bi->RSSI); goto exit; } #else - ESCAN_ERROR(("Buffer is too small: ignoring\n")); + ESCAN_ERROR(dev->name, "Buffer is too small: ignoring\n"); goto exit; #endif /* ESCAN_BUF_OVERFLOW_MGMT */ } - if (strlen(bi->SSID) == 0) { // terence: fix for hidden SSID - ESCAN_SCAN(("Skip hidden SSID %pM\n", &bi->BSSID)); - goto exit; - } - memcpy(&(((char *)list)[list->buflen]), bi, bi_length); list->version = dtoh32(bi->version); list->buflen += bi_length; @@ -847,39 +618,32 @@ static s32 wl_escan_handler(struct wl_escan_info *escan, } } else if (status == WLC_E_STATUS_SUCCESS) { - escan->escan_state = ESCAN_STATE_IDLE; - ESCAN_TRACE(("ESCAN COMPLETED\n")); + ESCAN_DBG(dev->name, "ESCAN COMPLETED\n"); escan->bss_list = wl_escan_get_buf(escan); - ESCAN_TRACE(("SCAN COMPLETED: scanned AP count=%d\n", - escan->bss_list->count)); - wl_escan_inform_bss(escan); - wl_notify_escan_complete(escan, false); + ESCAN_DBG(dev->name, "SCAN COMPLETED: scanned AP count=%d\n", + escan->bss_list->count); + wl_escan_notify_complete(dev, escan, false); } else if ((status == WLC_E_STATUS_ABORT) || (status == WLC_E_STATUS_NEWSCAN) || (status == WLC_E_STATUS_11HQUIET) || (status == WLC_E_STATUS_CS_ABORT) || (status == WLC_E_STATUS_NEWASSOC)) { /* Handle all cases of scan abort */ - escan->escan_state = ESCAN_STATE_IDLE; - ESCAN_TRACE(("ESCAN ABORT reason: %d\n", status)); + ESCAN_DBG(dev->name, "ESCAN ABORT reason: %d\n", status); escan->bss_list = wl_escan_get_buf(escan); - ESCAN_TRACE(("SCAN ABORT: scanned AP count=%d\n", - escan->bss_list->count)); - wl_escan_inform_bss(escan); - wl_notify_escan_complete(escan, false); + ESCAN_DBG(dev->name, "SCAN ABORT: scanned AP count=%d\n", + escan->bss_list->count); + wl_escan_notify_complete(dev, escan, false); } else if (status == WLC_E_STATUS_TIMEOUT) { - ESCAN_ERROR(("WLC_E_STATUS_TIMEOUT\n")); - ESCAN_ERROR(("reason[0x%x]\n", e->reason)); + ESCAN_ERROR(dev->name, "WLC_E_STATUS_TIMEOUT\n"); + ESCAN_ERROR(dev->name, "reason[0x%x]\n", e->reason); if (e->reason == 0xFFFFFFFF) { - wl_notify_escan_complete(escan, true); + wl_escan_notify_complete(dev, escan, true); } - escan->escan_state = ESCAN_STATE_IDLE; } else { - ESCAN_ERROR(("unexpected Escan Event %d : abort\n", status)); - escan->escan_state = ESCAN_STATE_IDLE; + ESCAN_ERROR(dev->name, "unexpected Escan Event %d : abort\n", status); escan->bss_list = wl_escan_get_buf(escan); - ESCAN_TRACE(("SCAN ABORTED(UNEXPECTED): scanned AP count=%d\n", - escan->bss_list->count)); - wl_escan_inform_bss(escan); - wl_notify_escan_complete(escan, false); + ESCAN_DBG(dev->name, "SCAN ABORTED(UNEXPECTED): scanned AP count=%d\n", + escan->bss_list->count); + wl_escan_notify_complete(dev, escan, false); } exit: mutex_unlock(&escan->usr_sync); @@ -887,8 +651,8 @@ exit: } static int -wl_escan_prep(struct wl_escan_info *escan, wl_uint32_list_t *list, - wl_scan_params_t *params, wlc_ssid_t *ssid) +wl_escan_prep(struct net_device *dev, struct wl_escan_info *escan, + wl_uint32_list_t *list, wl_scan_params_t *params, wlc_ssid_t *ssid, bool bcast) { int err = 0; wl_scan_results_t *results; @@ -899,6 +663,7 @@ wl_escan_prep(struct wl_escan_info *escan, wl_uint32_list_t *list, u32 n_channels = 0; uint channel; chanspec_t chanspec; + u32 n_ssids; results = wl_escan_get_buf(escan); results->version = 0; @@ -925,7 +690,7 @@ wl_escan_prep(struct wl_escan_info *escan, wl_uint32_list_t *list, n_channels = dtoh32(list->count); /* Copy channel array if applicable */ - ESCAN_SCAN(("### List of channelspecs to scan ###\n")); + ESCAN_SCAN(dev->name, "### List of channelspecs to scan ###\n"); if (n_channels > 0) { for (i = 0; i < n_channels; i++) { channel = dtoh32(list->element[i]); @@ -933,7 +698,7 @@ wl_escan_prep(struct wl_escan_info *escan, wl_uint32_list_t *list, continue; chanspec = WL_CHANSPEC_BW_20; if (chanspec == INVCHANSPEC) { - ESCAN_ERROR(("Invalid chanspec! Skipping channel\n")); + ESCAN_ERROR(dev->name, "Invalid chanspec! Skipping channel\n"); continue; } if (channel <= CH_MAX_2G_CHANNEL) { @@ -944,48 +709,55 @@ wl_escan_prep(struct wl_escan_info *escan, wl_uint32_list_t *list, params->channel_list[j] = channel; params->channel_list[j] &= WL_CHANSPEC_CHAN_MASK; params->channel_list[j] |= chanspec; - ESCAN_SCAN(("Chan : %d, Channel spec: %x \n", - channel, params->channel_list[j])); + ESCAN_SCAN(dev->name, "Chan : %d, Channel spec: %x\n", + channel, params->channel_list[j]); params->channel_list[j] = wl_chspec_host_to_driver(escan->ioctl_ver, params->channel_list[j]); j++; } } else { - ESCAN_SCAN(("Scanning all channels\n")); + ESCAN_SCAN(dev->name, "Scanning all channels\n"); } if (ssid && ssid->SSID_len) { /* Copy ssid array if applicable */ - ESCAN_SCAN(("### List of SSIDs to scan ###\n")); + ESCAN_SCAN(dev->name, "### List of SSIDs to scan ###\n"); offset = offsetof(wl_scan_params_t, channel_list) + n_channels * sizeof(u16); offset = roundup(offset, sizeof(u32)); ptr = (char*)params + offset; - ESCAN_SCAN(("0: Broadcast scan\n")); - memset(&ssid_tmp, 0, sizeof(wlc_ssid_t)); - ssid_tmp.SSID_len = 0; - memcpy(ptr, &ssid_tmp, sizeof(wlc_ssid_t)); - ptr += sizeof(wlc_ssid_t); + if (bcast) { + n_ssids = 2; + ESCAN_SCAN(dev->name, "0: Broadcast scan\n"); + memset(&ssid_tmp, 0, sizeof(wlc_ssid_t)); + ssid_tmp.SSID_len = 0; + memcpy(ptr, &ssid_tmp, sizeof(wlc_ssid_t)); + ptr += sizeof(wlc_ssid_t); + } else { + n_ssids = 1; + } memset(&ssid_tmp, 0, sizeof(wlc_ssid_t)); ssid_tmp.SSID_len = ssid->SSID_len; memcpy(ssid_tmp.SSID, ssid->SSID, ssid->SSID_len); memcpy(ptr, &ssid_tmp, sizeof(wlc_ssid_t)); ptr += sizeof(wlc_ssid_t); - ESCAN_SCAN(("1: scan for %s size=%d\n", ssid_tmp.SSID, ssid_tmp.SSID_len)); + ESCAN_SCAN(dev->name, "1: scan for %s size=%d\n", + ssid_tmp.SSID, ssid_tmp.SSID_len); /* Adding mask to channel numbers */ params->channel_num = - htod32((2 << WL_SCAN_PARAMS_NSSID_SHIFT) | + htod32((n_ssids << WL_SCAN_PARAMS_NSSID_SHIFT) | (n_channels & WL_SCAN_PARAMS_COUNT_MASK)); } else { - ESCAN_SCAN(("Broadcast scan\n")); + ESCAN_SCAN(dev->name, "Broadcast scan\n"); } return err; } -static int wl_escan_reset(struct wl_escan_info *escan) +static int +wl_escan_reset(struct wl_escan_info *escan) { if (timer_pending(&escan->scan_timeout)) del_timer_sync(&escan->scan_timeout); @@ -994,130 +766,90 @@ static int wl_escan_reset(struct wl_escan_info *escan) return 0; } -static void wl_escan_timeout( -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - struct timer_list *t -#else - unsigned long data -#endif -) +static void +wl_escan_timeout(unsigned long data) { wl_event_msg_t msg; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - struct wl_escan_info *escan = from_timer(escan, t, scan_timeout); -#else struct wl_escan_info *escan = (struct wl_escan_info *)data; -#endif struct wl_scan_results *bss_list; struct wl_bss_info *bi = NULL; s32 i; u32 channel; - bss_list = wl_escan_get_buf(escan); - if (!bss_list) { - ESCAN_ERROR(("bss_list is null. Didn't receive any partial scan results\n")); - } else { - ESCAN_ERROR(("%s: scanned AP count (%d)\n", __FUNCTION__, bss_list->count)); - bi = next_bss(bss_list, bi); - for_each_bss(bss_list, bi, i) { - channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec)); - ESCAN_ERROR(("SSID :%s Channel :%d\n", bi->SSID, channel)); - } - } - if (!escan->dev) { - ESCAN_ERROR(("No dev present\n")); + ESCAN_ERROR("wlan", "No dev present\n"); return; } - bzero(&msg, sizeof(wl_event_msg_t)); - ESCAN_ERROR(("timer expired\n")); + bss_list = wl_escan_get_buf(escan); + if (!bss_list) { + ESCAN_ERROR(escan->dev->name, + "bss_list is null. Didn't receive any partial scan results\n"); + } else { + ESCAN_ERROR(escan->dev->name, "scanned AP count (%d)\n", bss_list->count); + bi = next_bss(bss_list, bi); + for_each_bss(bss_list, bi, i) { + channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(escan->ioctl_ver, + bi->chanspec)); + ESCAN_ERROR(escan->dev->name, "SSID :%s Channel :%d\n", bi->SSID, channel); + } + } + bzero(&msg, sizeof(wl_event_msg_t)); + ESCAN_ERROR(escan->dev->name, "timer expired\n"); + + msg.ifidx = dhd_net2idx(escan->pub->info, escan->dev); msg.event_type = hton32(WLC_E_ESCAN_RESULT); msg.status = hton32(WLC_E_STATUS_TIMEOUT); msg.reason = 0xFFFFFFFF; - wl_escan_event(escan->dev, &msg, NULL); - - // terence 20130729: workaround to fix out of memory in firmware -// if (dhd_conf_get_chip(dhd_get_pub(dev)) == BCM43362_CHIP_ID) { -// ESCAN_ERROR(("Send hang event\n")); -// net_os_send_hang_message(dev); -// } + wl_ext_event_send(escan->pub->event_params, &msg, NULL); } int -wl_escan_set_scan( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) +wl_escan_set_scan(struct net_device *dev, dhd_pub_t *dhdp, + wlc_ssid_t *ssid, uint16 channel, bool bcast) { - struct dhd_pub *dhd = dhd_get_pub(dev); - struct wl_escan_info *escan = dhd->escan; + struct wl_escan_info *escan = dhdp->escan; s32 err = BCME_OK; s32 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params)); wl_escan_params_t *params = NULL; scb_val_t scbval; static int cnt = 0; - wlc_ssid_t ssid; u32 n_channels = 0; wl_uint32_list_t *list; u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)]; - s32 val = 0; - ESCAN_TRACE(("Enter \n")); - - if (!escan) { - ESCAN_ERROR(("device is not ready\n")); - return -EIO; - } mutex_lock(&escan->usr_sync); - - if (!escan->ioctl_ver) { - val = 1; - if ((err = wldev_ioctl(dev, WLC_GET_VERSION, &val, sizeof(int), false) < 0)) { - ANDROID_ERROR(("WLC_GET_VERSION failed, err=%d\n", err)); - goto exit; - } - val = dtoh32(val); - if (val != WLC_IOCTL_VERSION && val != 1) { - ANDROID_ERROR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n", - val, WLC_IOCTL_VERSION)); - goto exit; - } - escan->ioctl_ver = val; - printf("%s: ioctl_ver=%d\n", __FUNCTION__, val); - } - - /* default Broadcast scan */ - memset(&ssid, 0, sizeof(ssid)); - -#if WIRELESS_EXT > 17 - /* check for given essid */ - if (wrqu->data.length == sizeof(struct iw_scan_req)) { - if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { - struct iw_scan_req *req = (struct iw_scan_req *)extra; - ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len); - memcpy(ssid.SSID, req->essid, ssid.SSID_len); - ssid.SSID_len = htod32(ssid.SSID_len); - } - } -#endif - if (escan->escan_state == ESCAN_STATE_SCANING) { - ESCAN_ERROR(("Scanning already\n")); + if (escan->escan_state == ESCAN_STATE_DOWN) { + ESCAN_ERROR(dev->name, "STATE is down\n"); + err = -EIO; goto exit; } + if (wl_ext_check_scan(dev, dhdp)) { + err = -EBUSY; + goto exit; + } + + ESCAN_TRACE(dev->name, "Enter \n"); + /* if scan request is not empty parse scan request paramters */ memset(valid_chan_list, 0, sizeof(valid_chan_list)); list = (wl_uint32_list_t *)(void *) valid_chan_list; - list->count = htod32(WL_NUMCHANNELS); - err = wldev_ioctl(escan->dev, WLC_GET_VALID_CHANNELS, valid_chan_list, sizeof(valid_chan_list), false); - if (err != 0) { - ESCAN_ERROR(("%s: get channels failed with %d\n", __FUNCTION__, err)); - goto exit; + + if (channel) { + list->count = htod32(1); + list->element[0] = htod32(channel); + } else { + list->count = htod32(WL_NUMCHANNELS); + err = wldev_ioctl(dev, WLC_GET_VALID_CHANNELS, valid_chan_list, + sizeof(valid_chan_list), false); + if (err != 0) { + ESCAN_ERROR(dev->name, "get channels failed with %d\n", err); + goto exit; + } } + n_channels = dtoh32(list->count); /* Allocate space for populating ssids in wl_escan_params_t struct */ if (dtoh32(list->count) % 2) @@ -1125,7 +857,7 @@ wl_escan_set_scan( params_size += sizeof(u16) * (n_channels + 1); else params_size += sizeof(u16) * n_channels; - if (ssid.SSID_len) { + if (ssid && ssid->SSID_len) { params_size += sizeof(struct wlc_ssid) * 2; } @@ -1134,62 +866,81 @@ wl_escan_set_scan( err = -ENOMEM; goto exit; } - wl_escan_prep(escan, list, ¶ms->params, &ssid); + wl_escan_prep(dev, escan, list, ¶ms->params, ssid, bcast); params->version = htod32(ESCAN_REQ_VERSION); params->action = htod16(WL_SCAN_ACTION_START); wl_escan_set_sync_id(params->sync_id); if (params_size + sizeof("escan") >= WLC_IOCTL_MEDLEN) { - ESCAN_ERROR(("ioctl buffer length not sufficient\n")); + ESCAN_ERROR(dev->name, "ioctl buffer length not sufficient\n"); kfree(params); err = -ENOMEM; goto exit; } params->params.scan_type = DOT11_SCANTYPE_ACTIVE; - ESCAN_TRACE(("Passive scan_type %d\n", params->params.scan_type)); + ESCAN_SCAN(dev->name, "Passive scan_type %d\n", params->params.scan_type); + WL_MSG(dev->name, "LEGACY_SCAN\n"); err = wldev_iovar_setbuf(dev, "escan", params, params_size, escan->escan_ioctl_buf, WLC_IOCTL_MEDLEN, NULL); - printf("%s: LEGACY_SCAN\n", __FUNCTION__); if (unlikely(err)) { if (err == BCME_EPERM) /* Scan Not permitted at this point of time */ - ESCAN_TRACE(("Escan not permitted at this time (%d)\n", err)); + ESCAN_TRACE(dev->name, "Escan not permitted at this time (%d)\n", err); else - ESCAN_ERROR(("Escan set error (%d)\n", err)); - wl_escan_reset(escan); + ESCAN_ERROR(dev->name, "Escan set error (%d)\n", err); } kfree(params); -exit: if (unlikely(err)) { /* Don't print Error incase of Scan suppress */ if ((err == BCME_EPERM)) - ESCAN_TRACE(("Escan failed: Scan Suppressed \n")); + ESCAN_TRACE(dev->name, "Escan failed: Scan Suppressed\n"); else { cnt++; - ESCAN_ERROR(("error (%d), cnt=%d\n", err, cnt)); + ESCAN_ERROR(dev->name, "error (%d), cnt=%d\n", err, cnt); // terence 20140111: send disassoc to firmware if (cnt >= 4) { memset(&scbval, 0, sizeof(scb_val_t)); wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true); - ESCAN_ERROR(("Send disassoc to break the busy dev=%p\n", dev)); + ESCAN_ERROR(dev->name, "Send disassoc to break the busy\n"); cnt = 0; } } } else { cnt = 0; + escan->dev = dev; + } +exit: + if (unlikely(err)) { + wl_escan_reset(escan); } mutex_unlock(&escan->usr_sync); return err; } -int -wl_escan_merge_scan_results(struct net_device *dev, struct iw_request_info *info, - char *extra, wl_bss_info_t *bi, int *len, int max_size) +#if defined(WL_WIRELESS_EXT) +static int +rssi_to_qual(int rssi) +{ + if (rssi <= WL_IW_RSSI_NO_SIGNAL) + return 0; + else if (rssi <= WL_IW_RSSI_VERY_LOW) + return 1; + else if (rssi <= WL_IW_RSSI_LOW) + return 2; + else if (rssi <= WL_IW_RSSI_GOOD) + return 3; + else if (rssi <= WL_IW_RSSI_VERY_GOOD) + return 4; + else + return 5; +} + +static int +wl_escan_merge_scan_results(struct net_device *dev, struct wl_escan_info *escan, + struct iw_request_info *info, char *extra, wl_bss_info_t *bi, int *len, int max_size) { - struct dhd_pub *dhd = dhd_get_pub(dev); - struct wl_escan_info *escan = dhd->escan; s32 err = BCME_OK; struct iw_event iwe; int j; @@ -1213,8 +964,8 @@ wl_escan_merge_scan_results(struct net_device *dev, struct iw_request_info *info rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL); #endif channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec)); - ESCAN_SCAN(("BSSID="MACSTR", channel=%d, RSSI=%d, SSID=\"%s\"\n", - MAC2STR(bi->BSSID.octet), channel, rssi, bi->SSID)); + ESCAN_SCAN(dev->name, "BSSID=%pM, channel=%3d, RSSI=%3d, SSID=\"%s\"\n", + &bi->BSSID, channel, rssi, bi->SSID); /* First entry must be the BSSID */ iwe.cmd = SIOCGIWAP; @@ -1289,18 +1040,17 @@ wl_escan_merge_scan_results(struct net_device *dev, struct iw_request_info *info } *len = event - extra; if (*len < 0) - ESCAN_ERROR(("==> Wrong size\n")); + ESCAN_ERROR(dev->name, "==> Wrong size\n"); exit: return err; } int -wl_escan_get_scan(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) +wl_escan_get_scan(struct net_device *dev, dhd_pub_t *dhdp, + struct iw_request_info *info, struct iw_point *dwrq, char *extra) { - struct dhd_pub *dhd = dhd_get_pub(dev); - struct wl_escan_info *escan = dhd->escan; + struct wl_escan_info *escan = dhdp->escan; s32 err = BCME_OK; int i = 0; int len_prep = 0, len_ret = 0; @@ -1313,43 +1063,50 @@ wl_escan_get_scan(struct net_device *dev, struct iw_request_info *info, char *buf = NULL; struct ether_addr cur_bssid; - ESCAN_TRACE(("%s: %s SIOCGIWSCAN, len=%d\n", __FUNCTION__, dev->name, dwrq->length)); - - if (!extra) + if (!extra) { + ESCAN_TRACE(dev->name, "extra is null\n"); return -EINVAL; + } mutex_lock(&escan->usr_sync); /* Check for scan in progress */ if (escan->escan_state == ESCAN_STATE_SCANING) { - ESCAN_TRACE(("%s: SIOCGIWSCAN GET still scanning\n", dev->name)); + ESCAN_DBG(dev->name, "SIOCGIWSCAN GET still scanning\n"); err = -EAGAIN; goto exit; } if (!escan->bss_list) { - ESCAN_ERROR(("%s: scan not ready\n", dev->name)); + ESCAN_ERROR(dev->name, "scan not ready\n"); err = -EAGAIN; goto exit; } + if (dev != escan->dev) { + ESCAN_ERROR(dev->name, "not my scan from %s\n", escan->dev->name); + err = -EINVAL; + goto exit; + } + + ESCAN_SCAN(dev->name, "SIOCGIWSCAN, len=%d\n", dwrq->length); err = wldev_ioctl(dev, WLC_GET_BSSID, &cur_bssid, sizeof(cur_bssid), false); if (err != BCME_NOTASSOCIATED && memcmp(ðer_null, &cur_bssid, ETHER_ADDR_LEN)) { // merge current connected bss buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_ATOMIC); if (!buf) { - ESCAN_ERROR(("buffer alloc failed.\n")); + ESCAN_ERROR(dev->name, "buffer alloc failed.\n"); err = BCME_NOMEM; goto exit; } *(u32 *)buf = htod32(WL_EXTRA_BUF_MAX); err = wldev_ioctl(dev, WLC_GET_BSS_INFO, buf, WL_EXTRA_BUF_MAX, false); if (unlikely(err)) { - ESCAN_ERROR(("Could not get bss info %d\n", err)); + ESCAN_ERROR(dev->name, "Could not get bss info %d\n", err); goto exit; } bi = (struct wl_bss_info *)(buf + 4); len_prep = 0; - err = wl_escan_merge_scan_results(dev, info, extra+len_ret, bi, + err = wl_escan_merge_scan_results(dev, escan, info, extra+len_ret, bi, &len_prep, buflen_from_user-len_ret); len_ret += len_prep; if (err) @@ -1371,14 +1128,14 @@ wl_escan_get_scan(struct net_device *dev, struct iw_request_info *info, bi = node->results.bss_info; #endif if (!memcmp(&bi->BSSID, &cur_bssid, ETHER_ADDR_LEN)) { - ESCAN_SCAN(("skip connected AP %pM\n", &cur_bssid)); + ESCAN_SCAN(dev->name, "skip connected AP %pM\n", &cur_bssid); #if defined(BSSCACHE) node = node->next; #endif continue; } len_prep = 0; - err = wl_escan_merge_scan_results(dev, info, extra+len_ret, bi, + err = wl_escan_merge_scan_results(dev, escan, info, extra+len_ret, bi, &len_prep, buflen_from_user-len_ret); len_ret += len_prep; if (err) @@ -1392,67 +1149,265 @@ wl_escan_get_scan(struct net_device *dev, struct iw_request_info *info, dwrq->length = len_ret; dwrq->flags = 0; /* todo */ + ESCAN_SCAN(dev->name, "scanned AP count (%d)\n", i); exit: kfree(buf); dwrq->length = len_ret; - ESCAN_SCAN(("scanned AP count (%d)\n", i)); + mutex_unlock(&escan->usr_sync); + return err; +} +#endif /* WL_WIRELESS_EXT */ + +#ifdef WLMESH +bool +wl_escan_meshid_ie(u8 *parse, u32 len, wlc_ssid_t *mesh_id) +{ + bcm_tlv_t *ie; + + if((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_MESH_ID)) != NULL) { + mesh_id->SSID_len = ie->len; + if (ie->len) { + strncpy(mesh_id->SSID, ie->data, ie->len); + } + return TRUE; + } + return FALSE; +} + +bool +wl_escan_rsn_ie(u8 *parse, u32 len) +{ + if (bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_RSN_ID)) { + return TRUE; + } + return FALSE; +} + +void +wl_escan_mesh_info_ie(u8 *parse, u32 len, struct wl_mesh_params *mesh_info) +{ + bcm_tlv_t *ie; + uchar mesh_oui[]={0x00, 0x22, 0xf4}; + int totl_len; + uint8 *pie; + + if((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID)) != NULL) { + totl_len = ie->len; + if (!memcmp(ie->data, &mesh_oui, sizeof(mesh_oui))) { + pie = ie->data + sizeof(mesh_oui); + ie = (bcm_tlv_t *)pie; + totl_len -= sizeof(mesh_oui); + while (totl_len > 2 && ie->len) { + if (ie->id == MESH_INFO_MASTER_BSSID && ie->len == ETHER_ADDR_LEN) { + memcpy(&mesh_info->master_bssid, ie->data, ETHER_ADDR_LEN); + } else if (ie->id == MESH_INFO_MASTER_CHANNEL) { + mesh_info->master_channel = ie->data[0]; + } else if (ie->id == MESH_INFO_HOP_CNT) { + mesh_info->hop_cnt = ie->data[0]; + } else if (ie->id == MESH_INFO_PEER_BSSID) { + memcpy(&mesh_info->peer_bssid, ie->data, ETHER_ADDR_LEN); + } + totl_len -= (ie->len + 2); + pie = ie->data + ie->len; + ie = (bcm_tlv_t *)pie; + } + } + } +} + +int +wl_escan_mesh_info(struct net_device *dev, struct wl_escan_info *escan, + struct ether_addr *peer_bssid, struct wl_mesh_params *mesh_info) +{ + s32 err = BCME_OK; + int i = 0; + wl_bss_info_t *bi = NULL; + struct wl_scan_results *bss_list; + int16 bi_rssi, bi_chan; + wlc_ssid_t bi_meshid; + bool is_mesh_peer = FALSE; + struct wl_mesh_params peer_mesh_info; + + mutex_lock(&escan->usr_sync); + + /* Check for scan in progress */ + if (escan->escan_state == ESCAN_STATE_SCANING) { + ESCAN_ERROR(dev->name, "SIOCGIWSCAN GET still scanning\n"); + err = -EAGAIN; + goto exit; + } + if (!escan->bss_list) { + ESCAN_ERROR(dev->name, "scan not ready\n"); + err = -EAGAIN; + goto exit; + } + if (dev != escan->dev) { + ESCAN_ERROR(dev->name, "not my scan from %s\n", escan->dev->name); + err = -EINVAL; + goto exit; + } + + bss_list = escan->bss_list; + bi = next_bss(bss_list, bi); + ESCAN_SCAN(dev->name, "scanned AP/Mesh count (%d)\n", bss_list->count); + for_each_bss(bss_list, bi, i) + { + memset(&bi_meshid, 0, sizeof(bi_meshid)); + is_mesh_peer = FALSE; + bi_chan = wf_chspec_ctlchan( + wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec)); + bi_rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL); + is_mesh_peer = wl_escan_meshid_ie(((u8*)bi)+bi->ie_offset, + bi->ie_length, &bi_meshid); + if (!(bi->capability & (DOT11_CAP_ESS|DOT11_CAP_IBSS)) && is_mesh_peer) { + bool bi_sae = FALSE, bss_found = FALSE; + if (!memcmp(peer_bssid, &bi->BSSID, ETHER_ADDR_LEN)) { + bi_sae = wl_escan_rsn_ie(((u8*)bi)+bi->ie_offset, bi->ie_length); + memset(&peer_mesh_info, 0, sizeof(peer_mesh_info)); + wl_escan_mesh_info_ie(((u8*)bi)+bi->ie_offset, bi->ie_length, + &peer_mesh_info); + if (peer_mesh_info.hop_cnt) { + memcpy(&mesh_info->master_bssid, &peer_mesh_info.master_bssid, + ETHER_ADDR_LEN); + mesh_info->master_channel = peer_mesh_info.master_channel; + mesh_info->hop_cnt = peer_mesh_info.hop_cnt; + memcpy(&mesh_info->peer_bssid, &peer_mesh_info.peer_bssid, + ETHER_ADDR_LEN); + mesh_info->channel = bi_chan; + bss_found = TRUE; + } + } + ESCAN_SCAN(dev->name, + "%s[Mesh] BSSID=%pM, channel=%d, RSSI=%d, sec=%s, " + "mbssid=%pM, mchannel=%d, hop=%d, pbssid=%pM, MeshID=\"%s\"\n", + bss_found?"*":" ", &bi->BSSID, bi_chan, bi_rssi, bi_sae?"SAE":"OPEN", + &peer_mesh_info.master_bssid, peer_mesh_info.master_channel, + peer_mesh_info.hop_cnt, &peer_mesh_info.peer_bssid, bi_meshid.SSID); + } + } + +exit: mutex_unlock(&escan->usr_sync); return err; } -s32 wl_escan_autochannel(struct net_device *dev, char* command, int total_len) +int +wl_escan_mesh_peer(struct net_device *dev, struct wl_escan_info *escan, + wlc_ssid_t *cur_ssid, uint16 cur_chan, bool sae, + struct wl_mesh_params *mesh_info) { - struct dhd_pub *dhd = dhd_get_pub(dev); - struct wl_escan_info *escan = dhd->escan; - int ret = 0; - int bytes_written = -1; + s32 err = BCME_OK; + int i = 0; + wl_bss_info_t *bi = NULL; + struct wl_scan_results *bss_list; + int16 bi_rssi, bi_chan, max_rssi = -100; + uint min_hop_cnt = 255; + wlc_ssid_t bi_meshid; + bool is_mesh_peer = FALSE, chan_matched = FALSE; + struct wl_mesh_params peer_mesh_info; - sscanf(command, "%*s %d", &escan->autochannel); + mutex_lock(&escan->usr_sync); - if (escan->autochannel == 0) { - escan->best_2g_ch = 0; - escan->best_5g_ch = 0; - } else if (escan->autochannel == 2) { - bytes_written = snprintf(command, total_len, "2g=%d 5g=%d", - escan->best_2g_ch, escan->best_5g_ch); - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); - ret = bytes_written; + /* Check for scan in progress */ + if (escan->escan_state == ESCAN_STATE_SCANING) { + ESCAN_ERROR(dev->name, "SIOCGIWSCAN GET still scanning\n"); + err = -EAGAIN; + goto exit; + } + if (!escan->bss_list) { + ESCAN_ERROR(dev->name, "scan not ready\n"); + err = -EAGAIN; + goto exit; + } + if (dev != escan->dev) { + ESCAN_ERROR(dev->name, "not my scan from %s\n", escan->dev->name); + err = -EINVAL; + goto exit; } - return ret; -} + bss_list = escan->bss_list; + bi = next_bss(bss_list, bi); + ESCAN_SCAN(dev->name, "scanned AP/Mesh count (%d)\n", bss_list->count); + for_each_bss(bss_list, bi, i) + { + memset(&bi_meshid, 0, sizeof(bi_meshid)); + is_mesh_peer = FALSE; + bi_chan = wf_chspec_ctlchan( + wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec)); + bi_rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL); + is_mesh_peer = wl_escan_meshid_ie(((u8*)bi)+bi->ie_offset, + bi->ie_length, &bi_meshid); + if (!(bi->capability & (DOT11_CAP_ESS|DOT11_CAP_IBSS)) && is_mesh_peer) { + bool meshid_matched = FALSE, sec_matched = FALSE, bi_sae = FALSE, + bss_found = FALSE; -static s32 wl_create_event_handler(struct wl_escan_info *escan) -{ - int ret = 0; - ESCAN_TRACE(("Enter \n")); + if (cur_ssid->SSID_len && cur_ssid->SSID_len == bi_meshid.SSID_len && + !memcmp(cur_ssid->SSID, bi_meshid.SSID, bi_meshid.SSID_len)) + meshid_matched = TRUE; - /* Do not use DHD in cfg driver */ - escan->event_tsk.thr_pid = -1; + bi_sae = wl_escan_rsn_ie(((u8*)bi)+bi->ie_offset, bi->ie_length); + if (bi_sae == sae) + sec_matched = TRUE; - PROC_START(wl_escan_event_handler, escan, &escan->event_tsk, 0, "wl_escan_handler"); - if (escan->event_tsk.thr_pid < 0) - ret = -ENOMEM; - return ret; -} + memset(&peer_mesh_info, 0, sizeof(peer_mesh_info)); + wl_escan_mesh_info_ie(((u8*)bi)+bi->ie_offset, bi->ie_length, + &peer_mesh_info); -static void wl_destroy_event_handler(struct wl_escan_info *escan) -{ - if (escan->event_tsk.thr_pid >= 0) - PROC_STOP(&escan->event_tsk); -} + if (meshid_matched && sec_matched && peer_mesh_info.hop_cnt && + (cur_chan == bi_chan)) { + if (peer_mesh_info.hop_cnt < min_hop_cnt) { + memcpy(&mesh_info->master_bssid, &peer_mesh_info.master_bssid, + ETHER_ADDR_LEN); + mesh_info->master_channel = peer_mesh_info.master_channel; + mesh_info->hop_cnt = peer_mesh_info.hop_cnt; + memcpy(&mesh_info->peer_bssid, &peer_mesh_info.peer_bssid, + ETHER_ADDR_LEN); + mesh_info->channel = bi_chan; + min_hop_cnt = peer_mesh_info.hop_cnt; + bss_found = TRUE; + chan_matched = TRUE; + } + } else if (meshid_matched && sec_matched && peer_mesh_info.hop_cnt && + (cur_chan != bi_chan) && !chan_matched) { + if (bi_rssi > max_rssi) { + memcpy(&mesh_info->master_bssid, &peer_mesh_info.master_bssid, + ETHER_ADDR_LEN); + mesh_info->master_channel = peer_mesh_info.master_channel; + mesh_info->hop_cnt = peer_mesh_info.hop_cnt; + memcpy(&mesh_info->peer_bssid, &peer_mesh_info.peer_bssid, + ETHER_ADDR_LEN); + mesh_info->channel = bi_chan; + max_rssi = bi_rssi; + bss_found = TRUE; + } + } -static void wl_escan_deinit(struct wl_escan_info *escan) -{ - printf("%s: Enter\n", __FUNCTION__); - if (!escan) { - ESCAN_ERROR(("device is not ready\n")); - return; + ESCAN_SCAN(dev->name, + "%s[Mesh] BSSID=%pM, channel=%d, RSSI=%d, sec=%s, " + "mbssid=%pM, mchannel=%d, hop=%d, pbssid=%pM, MeshID=\"%s\"\n", + bss_found?"*":" ", &bi->BSSID, bi_chan, bi_rssi, bi_sae?"SAE":"OPEN", + &peer_mesh_info.master_bssid, peer_mesh_info.master_channel, + peer_mesh_info.hop_cnt, &peer_mesh_info.peer_bssid, bi_meshid.SSID); + } else { + ESCAN_SCAN(dev->name, + "[AP] BSSID=%pM, channel=%d, RSSI=%d, SSID=\"%s\"\n", + &bi->BSSID, bi_chan, bi_rssi, bi->SSID); + } } - wl_destroy_event_handler(escan); - wl_flush_eq(escan); + +exit: + mutex_unlock(&escan->usr_sync); + return err; +} +#endif /* WLMESH */ + +static void +wl_escan_deinit(struct net_device *dev, struct wl_escan_info *escan) +{ + ESCAN_TRACE(dev->name, "Enter\n"); + del_timer_sync(&escan->scan_timeout); - escan->escan_state = ESCAN_STATE_IDLE; + escan->escan_state = ESCAN_STATE_DOWN; #if defined(RSSIAVG) wl_free_rssi_cache(&escan->g_rssi_cache_ctrl); @@ -1462,59 +1417,123 @@ static void wl_escan_deinit(struct wl_escan_info *escan) #endif } -static s32 wl_escan_init(struct wl_escan_info *escan) +static s32 +wl_escan_init(struct net_device *dev, struct wl_escan_info *escan) { - int err = 0; - - printf("%s: Enter\n", __FUNCTION__); - if (!escan) { - ESCAN_ERROR(("device is not ready\n")); - return -EIO; - } + ESCAN_TRACE(dev->name, "Enter\n"); /* Init scan_timeout timer */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - timer_setup(&escan->scan_timeout, wl_escan_timeout, 0); -#else - init_timer(&escan->scan_timeout); - escan->scan_timeout.data = (unsigned long) escan; - escan->scan_timeout.function = wl_escan_timeout; -#endif - - if (wl_create_event_handler(escan)) { - err = -ENOMEM; - goto err; - } - memset(escan->evt_handler, 0, sizeof(escan->evt_handler)); - - escan->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler; + init_timer_compat(&escan->scan_timeout, wl_escan_timeout, escan); escan->escan_state = ESCAN_STATE_IDLE; - mutex_init(&escan->usr_sync); - return 0; -err: - wl_escan_deinit(escan); - return err; } -void wl_escan_detach(dhd_pub_t *dhdp) +void +wl_escan_down(struct net_device *dev, dhd_pub_t *dhdp) { struct wl_escan_info *escan = dhdp->escan; - printf("%s: Enter\n", __FUNCTION__); - + ESCAN_TRACE(dev->name, "Enter\n"); if (!escan) { - ESCAN_ERROR(("device is not ready\n")); + ESCAN_ERROR(dev->name, "escan is NULL\n"); return; } - wl_escan_deinit(escan); + wl_escan_deinit(dev, escan); +} +int +wl_escan_up(struct net_device *dev, dhd_pub_t *dhdp) +{ + struct wl_escan_info *escan = dhdp->escan; + s32 val = 0; + int ret = -1; + + ESCAN_TRACE(dev->name, "Enter\n"); + if (!escan) { + ESCAN_ERROR(dev->name, "escan is NULL\n"); + return ret; + } + + ret = wl_escan_init(dev, escan); + if (ret) { + ESCAN_ERROR(dev->name, "wl_escan_init ret %d\n", ret); + return ret; + } + + if (!escan->ioctl_ver) { + val = 1; + if ((ret = wldev_ioctl(dev, WLC_GET_VERSION, &val, sizeof(int), false) < 0)) { + ESCAN_ERROR(dev->name, "WLC_GET_VERSION failed, ret=%d\n", ret); + return ret; + } + val = dtoh32(val); + if (val != WLC_IOCTL_VERSION && val != 1) { + ESCAN_ERROR(dev->name, + "Version mismatch, please upgrade. Got %d, expected %d or 1\n", + val, WLC_IOCTL_VERSION); + return ret; + } + escan->ioctl_ver = val; + } + + return 0; +} + +int +wl_escan_event_dettach(struct net_device *dev, dhd_pub_t *dhdp) +{ + struct wl_escan_info *escan = dhdp->escan; + int ret = -1; + + if (!escan) { + ESCAN_ERROR(dev->name, "escan is NULL\n"); + return ret; + } + + wl_ext_event_deregister(dev, dhdp, WLC_E_ESCAN_RESULT, wl_escan_handler); + + return 0; +} + +int +wl_escan_event_attach(struct net_device *dev, dhd_pub_t *dhdp) +{ + struct wl_escan_info *escan = dhdp->escan; + int ret = -1; + + if (!escan) { + ESCAN_ERROR(dev->name, "escan is NULL\n"); + return ret; + } + + ret = wl_ext_event_register(dev, dhdp, WLC_E_ESCAN_RESULT, wl_escan_handler, + escan, PRIO_EVENT_ESCAN); + if (ret) { + ESCAN_ERROR(dev->name, "wl_ext_event_register err %d\n", ret); + } + + return ret; +} + +void +wl_escan_detach(struct net_device *dev, dhd_pub_t *dhdp) +{ + struct wl_escan_info *escan = dhdp->escan; + + ESCAN_TRACE(dev->name, "Enter\n"); + + if (!escan) + return; + + wl_escan_deinit(dev, escan); if (escan->escan_ioctl_buf) { kfree(escan->escan_ioctl_buf); escan->escan_ioctl_buf = NULL; } + wl_ext_event_deregister(dev, dhdp, WLC_E_ESCAN_RESULT, wl_escan_handler); + DHD_OS_PREFREE(dhdp, escan, sizeof(struct wl_escan_info)); dhdp->escan = NULL; } @@ -1523,34 +1542,40 @@ int wl_escan_attach(struct net_device *dev, dhd_pub_t *dhdp) { struct wl_escan_info *escan = NULL; + int ret = 0; - printf("%s: Enter\n", __FUNCTION__); + ESCAN_TRACE(dev->name, "Enter\n"); - if (!dev) - return 0; - escan = (wl_escan_info_t *)DHD_OS_PREALLOC(dhdp, DHD_PREALLOC_WL_ESCAN_INFO, sizeof(struct wl_escan_info)); + escan = (struct wl_escan_info *)DHD_OS_PREALLOC(dhdp, + DHD_PREALLOC_WL_ESCAN, sizeof(struct wl_escan_info)); if (!escan) return -ENOMEM; - dhdp->escan = (void *)escan; memset(escan, 0, sizeof(struct wl_escan_info)); + dhdp->escan = escan; + /* we only care about main interface so save a global here */ - escan->dev = dev; escan->pub = dhdp; - escan->escan_state = ESCAN_STATE_IDLE; + escan->escan_state = ESCAN_STATE_DOWN; escan->escan_ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL); if (unlikely(!escan->escan_ioctl_buf)) { - ESCAN_ERROR(("Ioctl buf alloc failed\n")); - goto err ; + ESCAN_ERROR(dev->name, "Ioctl buf alloc failed\n"); + ret = -ENOMEM; + goto exit; } - wl_init_eq(escan); - wl_escan_init(escan); + ret = wl_escan_init(dev, escan); + if (ret) { + ESCAN_ERROR(dev->name, "wl_escan_init err %d\n", ret); + goto exit; + } + mutex_init(&escan->usr_sync); return 0; -err: - wl_escan_detach(dhdp); - return -ENOMEM; + +exit: + wl_escan_detach(dev, dhdp); + return ret; } #endif /* WL_ESCAN */ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.h index 5106069d1dab..474980f4554f 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_escan.h @@ -1,65 +1,30 @@ /* SPDX-License-Identifier: GPL-2.0 */ #ifndef _wl_escan_ #define _wl_escan_ - -#include +#include #include -#include -#include -#include - - -#ifdef DHD_MAX_IFS -#define WL_MAX_IFS DHD_MAX_IFS -#else -#define WL_MAX_IFS 16 -#endif #define ESCAN_BUF_SIZE (64 * 1024) #define WL_ESCAN_TIMER_INTERVAL_MS 10000 /* Scan timeout */ -/* event queue for cfg80211 main event */ -struct escan_event_q { - struct list_head eq_list; - u32 etype; - wl_event_msg_t emsg; - s8 edata[1]; -}; - -struct pmk_list { - pmkid_list_t pmkids; - pmkid_t foo[MAXPMKID - 1]; -}; - /* donlge escan state */ enum escan_state { + ESCAN_STATE_DOWN, ESCAN_STATE_IDLE, ESCAN_STATE_SCANING }; -struct wl_escan_info; - -typedef s32(*ESCAN_EVENT_HANDLER) (struct wl_escan_info *escan, - const wl_event_msg_t *e, void *data); - typedef struct wl_escan_info { struct net_device *dev; dhd_pub_t *pub; - struct timer_list scan_timeout; /* Timer for catch scan event timeout */ - int escan_state; + timer_list_compat_t scan_timeout; /* Timer for catch scan event timeout */ + int escan_state; int ioctl_ver; - - char ioctlbuf[WLC_IOCTL_SMLEN]; u8 escan_buf[ESCAN_BUF_SIZE]; struct wl_scan_results *bss_list; - struct wl_scan_results *scan_results; struct ether_addr disconnected_bssid; u8 *escan_ioctl_buf; - spinlock_t eq_lock; /* for event queue synchronization */ - struct list_head eq_list; /* used for event queue */ - tsk_ctl_t event_tsk; /* task of main event handler thread */ - ESCAN_EVENT_HANDLER evt_handler[WLC_E_LAST]; struct mutex usr_sync; /* maily for up/down synchronization */ int autochannel; int best_2g_ch; @@ -71,23 +36,43 @@ typedef struct wl_escan_info { #if defined(BSSCACHE) wl_bss_cache_ctrl_t g_bss_cache_ctrl; #endif - struct pmk_list pmk_list; - wl_conn_info_t conn_info; } wl_escan_info_t; -void wl_escan_event(struct net_device *dev, const wl_event_msg_t * e, void *data); +#if defined(WLMESH) +/* donlge escan state */ +enum mesh_info_id { + MESH_INFO_MASTER_BSSID = 1, + MESH_INFO_MASTER_CHANNEL, + MESH_INFO_HOP_CNT, + MESH_INFO_PEER_BSSID +}; -int wl_escan_set_scan( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -); -int wl_escan_get_scan(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra); -s32 wl_escan_autochannel(struct net_device *dev, char* command, int total_len); +typedef struct wl_mesh_params { + struct ether_addr master_bssid; + uint16 master_channel; + uint hop_cnt; + struct ether_addr peer_bssid; + uint16 channel; + uint16 scan_channel; +} wl_mesh_params_t; +int wl_escan_mesh_info(struct net_device *dev, + struct wl_escan_info *escan, struct ether_addr *peer_bssid, + struct wl_mesh_params *mesh_info); +int wl_escan_mesh_peer(struct net_device *dev, + struct wl_escan_info *escan, wlc_ssid_t *cur_ssid, uint16 cur_chan, bool sae, + struct wl_mesh_params *mesh_info); +#endif /* WLMESH */ + +int wl_escan_set_scan(struct net_device *dev, dhd_pub_t *dhdp, + wlc_ssid_t *ssid, uint16 channel, bool bcast); +int wl_escan_get_scan(struct net_device *dev, dhd_pub_t *dhdp, + struct iw_request_info *info, struct iw_point *dwrq, char *extra); int wl_escan_attach(struct net_device *dev, dhd_pub_t *dhdp); -void wl_escan_detach(dhd_pub_t *dhdp); +void wl_escan_detach(struct net_device *dev, dhd_pub_t *dhdp); +int wl_escan_event_attach(struct net_device *dev, dhd_pub_t *dhdp); +int wl_escan_event_dettach(struct net_device *dev, dhd_pub_t *dhdp); +int wl_escan_up(struct net_device *dev, dhd_pub_t *dhdp); +void wl_escan_down(struct net_device *dev, dhd_pub_t *dhdp); #endif /* _wl_escan_ */ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_event.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_event.c new file mode 100644 index 000000000000..c9e3d569dc4f --- /dev/null +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_event.c @@ -0,0 +1,504 @@ + +#if defined(WL_EXT_IAPSTA) || defined(USE_IW) +#include +#include +#include + +#define EVENT_ERROR(name, arg1, args...) \ + do { \ + if (android_msg_level & ANDROID_ERROR_LEVEL) { \ + printk(KERN_ERR "[dhd-%s] EVENT-ERROR) %s : " arg1, name, __func__, ## args); \ + } \ + } while (0) +#define EVENT_TRACE(name, arg1, args...) \ + do { \ + if (android_msg_level & ANDROID_TRACE_LEVEL) { \ + printk(KERN_ERR "[dhd-%s] EVENT-TRACE) %s : " arg1, name, __func__, ## args); \ + } \ + } while (0) +#define EVENT_DBG(name, arg1, args...) \ + do { \ + if (android_msg_level & ANDROID_DBG_LEVEL) { \ + printk(KERN_ERR "[dhd-%s] EVENT-DBG) %s : " arg1, name, __func__, ## args); \ + } \ + } while (0) + +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \ + 4 && __GNUC_MINOR__ >= 6)) +#define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \ +_Pragma("GCC diagnostic push") \ +_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \ +(entry) = list_first_entry((ptr), type, member); \ +_Pragma("GCC diagnostic pop") \ + +#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \ +_Pragma("GCC diagnostic push") \ +_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \ +entry = container_of((ptr), type, member); \ +_Pragma("GCC diagnostic pop") \ + +#else +#define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \ +(entry) = list_first_entry((ptr), type, member); \ + +#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \ +entry = container_of((ptr), type, member); \ + +#endif /* STRICT_GCC_WARNINGS */ + +#ifdef DHD_MAX_IFS +#define WL_MAX_IFS DHD_MAX_IFS +#else +#define WL_MAX_IFS 16 +#endif + +/* event queue for cfg80211 main event */ +struct wl_event_q { + struct list_head eq_list; + u32 etype; + wl_event_msg_t emsg; + s8 edata[1]; +}; + +typedef s32(*EXT_EVENT_HANDLER) (struct net_device *dev, void *cb_argu, + const wl_event_msg_t *e, void *data); + +typedef struct event_handler_list { + struct event_handler_list *next; + struct net_device *dev; + uint32 etype; + EXT_EVENT_HANDLER cb_func; + void *cb_argu; + wl_event_prio_t prio; +} event_handler_list_t; + +typedef struct event_handler_head { + event_handler_list_t *evt_head; +} event_handler_head_t; + +typedef struct wl_event_params { + dhd_pub_t *pub; + struct net_device *dev[WL_MAX_IFS]; + struct event_handler_head evt_head; + struct list_head eq_list; /* used for event queue */ + spinlock_t eq_lock; /* for event queue synchronization */ + struct workqueue_struct *event_workq; /* workqueue for event */ + struct work_struct event_work; /* work item for event */ + struct mutex event_sync; +} wl_event_params_t; + +static unsigned long +wl_ext_event_lock_eq(struct wl_event_params *event_params) +{ + unsigned long flags; + + spin_lock_irqsave(&event_params->eq_lock, flags); + return flags; +} + +static void +wl_ext_event_unlock_eq(struct wl_event_params *event_params, unsigned long flags) +{ + spin_unlock_irqrestore(&event_params->eq_lock, flags); +} + +static void +wl_ext_event_init_eq_lock(struct wl_event_params *event_params) +{ + spin_lock_init(&event_params->eq_lock); +} + +static void +wl_ext_event_init_eq(struct wl_event_params *event_params) +{ + wl_ext_event_init_eq_lock(event_params); + INIT_LIST_HEAD(&event_params->eq_list); +} + +static void +wl_ext_event_flush_eq(struct wl_event_params *event_params) +{ + struct wl_event_q *e; + unsigned long flags; + + flags = wl_ext_event_lock_eq(event_params); + while (!list_empty_careful(&event_params->eq_list)) { + BCM_SET_LIST_FIRST_ENTRY(e, &event_params->eq_list, struct wl_event_q, eq_list); + list_del(&e->eq_list); + kfree(e); + } + wl_ext_event_unlock_eq(event_params, flags); +} + +/* +* retrieve first queued event from head +*/ + +static struct wl_event_q * +wl_ext_event_deq_event(struct wl_event_params *event_params) +{ + struct wl_event_q *e = NULL; + unsigned long flags; + + flags = wl_ext_event_lock_eq(event_params); + if (likely(!list_empty(&event_params->eq_list))) { + BCM_SET_LIST_FIRST_ENTRY(e, &event_params->eq_list, struct wl_event_q, eq_list); + list_del(&e->eq_list); + } + wl_ext_event_unlock_eq(event_params, flags); + + return e; +} + +/* + * push event to tail of the queue + */ + +static s32 +wl_ext_event_enq_event(struct wl_event_params *event_params, u32 event, + const wl_event_msg_t *msg, void *data) +{ + struct wl_event_q *e; + s32 err = 0; + uint32 evtq_size; + uint32 data_len; + unsigned long flags; + gfp_t aflags; + + data_len = 0; + if (data) + data_len = ntoh32(msg->datalen); + evtq_size = sizeof(struct wl_event_q) + data_len; + aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; + e = kzalloc(evtq_size, aflags); + if (unlikely(!e)) { + EVENT_ERROR("wlan", "event alloc failed\n"); + return -ENOMEM; + } + e->etype = event; + memcpy(&e->emsg, msg, sizeof(wl_event_msg_t)); + if (data) + memcpy(e->edata, data, data_len); + flags = wl_ext_event_lock_eq(event_params); + list_add_tail(&e->eq_list, &event_params->eq_list); + wl_ext_event_unlock_eq(event_params, flags); + + return err; +} + +static void +wl_ext_event_put_event(struct wl_event_q *e) +{ + kfree(e); +} + +static void +wl_ext_event_handler(struct work_struct *work_data) +{ + struct wl_event_params *event_params = NULL; + struct wl_event_q *e; + struct net_device *dev = NULL; + struct event_handler_list *evt_node; + dhd_pub_t *dhd; + + BCM_SET_CONTAINER_OF(event_params, work_data, struct wl_event_params, event_work); + DHD_EVENT_WAKE_LOCK(event_params->pub); + while ((e = wl_ext_event_deq_event(event_params))) { + if (e->emsg.ifidx >= DHD_MAX_IFS) { + EVENT_ERROR("wlan", "ifidx=%d not in range\n", e->emsg.ifidx); + goto fail; + } + dev = event_params->dev[e->emsg.ifidx]; + if (!dev) { + EVENT_DBG("wlan", "ifidx=%d dev not ready\n", e->emsg.ifidx); + goto fail; + } + dhd = dhd_get_pub(dev); + if (e->etype > WLC_E_LAST) { + EVENT_TRACE(dev->name, "Unknown Event (%d): ignoring\n", e->etype); + goto fail; + } + if (dhd->busstate == DHD_BUS_DOWN) { + EVENT_ERROR(dev->name, "BUS is DOWN.\n"); + goto fail; + } + EVENT_DBG(dev->name, "event type (%d)\n", e->etype); + mutex_lock(&event_params->event_sync); + evt_node = event_params->evt_head.evt_head; + for (;evt_node;) { + if (evt_node->dev == dev && + (evt_node->etype == e->etype || evt_node->etype == WLC_E_LAST)) + evt_node->cb_func(dev, evt_node->cb_argu, &e->emsg, e->edata); + evt_node = evt_node->next; + } + mutex_unlock(&event_params->event_sync); +fail: + wl_ext_event_put_event(e); + } + DHD_EVENT_WAKE_UNLOCK(event_params->pub); +} + +void +wl_ext_event_send(void *params, const wl_event_msg_t * e, void *data) +{ + struct wl_event_params *event_params = params; + u32 event_type = ntoh32(e->event_type); + + if (event_params == NULL) { + EVENT_ERROR("wlan", "Stale event %d(%s) ignored\n", + event_type, bcmevent_get_name(event_type)); + return; + } + + if (event_params->event_workq == NULL) { + EVENT_ERROR("wlan", "Event handler is not created %d(%s)\n", + event_type, bcmevent_get_name(event_type)); + return; + } + + if (likely(!wl_ext_event_enq_event(event_params, event_type, e, data))) { + queue_work(event_params->event_workq, &event_params->event_work); + } +} + +static s32 +wl_ext_event_create_handler(struct wl_event_params *event_params) +{ + int ret = 0; + EVENT_TRACE("wlan", "Enter\n"); + + /* Allocate workqueue for event */ + if (!event_params->event_workq) { + event_params->event_workq = alloc_workqueue("ext_eventd", WQ_MEM_RECLAIM | WQ_HIGHPRI, 0); + } + + if (!event_params->event_workq) { + EVENT_ERROR("wlan", "event_workq alloc_workqueue failed\n"); + ret = -ENOMEM; + } else { + INIT_WORK(&event_params->event_work, wl_ext_event_handler); + } + return ret; +} + +static void +wl_ext_event_free(struct wl_event_params *event_params) +{ + struct event_handler_list *node, *cur, **evt_head; + + evt_head = &event_params->evt_head.evt_head; + node = *evt_head; + + for (;node;) { + EVENT_TRACE(node->dev->name, "Free etype=%d\n", node->etype); + cur = node; + node = cur->next; + kfree(cur); + } + *evt_head = NULL; +} + +static void +wl_ext_event_destroy_handler(struct wl_event_params *event_params) +{ + if (event_params && event_params->event_workq) { + cancel_work_sync(&event_params->event_work); + destroy_workqueue(event_params->event_workq); + event_params->event_workq = NULL; + } +} + +int +wl_ext_event_register(struct net_device *dev, dhd_pub_t *dhd, uint32 event, + void *cb_func, void *data, wl_event_prio_t prio) +{ + struct wl_event_params *event_params = dhd->event_params; + struct event_handler_list *node, *leaf, *node_prev, **evt_head; + int ret = 0; + + if (event_params) { + mutex_lock(&event_params->event_sync); + evt_head = &event_params->evt_head.evt_head; + node = *evt_head; + for (;node;) { + if (node->dev == dev && node->etype == event && node->cb_func == cb_func) { + EVENT_TRACE(dev->name, "skip event %d\n", event); + mutex_unlock(&event_params->event_sync); + return 0; + } + node = node->next; + } + leaf = kmalloc(sizeof(event_handler_list_t), GFP_KERNEL); + if (!leaf) { + EVENT_ERROR(dev->name, "Memory alloc failure %d for event %d\n", + (int)sizeof(event_handler_list_t), event); + mutex_unlock(&event_params->event_sync); + return -ENOMEM; + } + leaf->next = NULL; + leaf->dev = dev; + leaf->etype = event; + leaf->cb_func = cb_func; + leaf->cb_argu = data; + leaf->prio = prio; + if (*evt_head == NULL) { + *evt_head = leaf; + } else { + node = *evt_head; + node_prev = NULL; + for (;node;) { + if (node->prio <= prio) { + leaf->next = node; + if (node_prev) + node_prev->next = leaf; + else + *evt_head = leaf; + break; + } else if (node->next == NULL) { + node->next = leaf; + break; + } + node_prev = node; + node = node->next; + } + } + EVENT_TRACE(dev->name, "event %d registered\n", event); + mutex_unlock(&event_params->event_sync); + } else { + EVENT_ERROR(dev->name, "event_params not ready %d\n", event); + ret = -ENODEV; + } + + return ret; +} + +void +wl_ext_event_deregister(struct net_device *dev, dhd_pub_t *dhd, + uint32 event, void *cb_func) +{ + struct wl_event_params *event_params = dhd->event_params; + struct event_handler_list *node, *prev, **evt_head; + int tmp = 0; + + if (event_params) { + mutex_lock(&event_params->event_sync); + evt_head = &event_params->evt_head.evt_head; + node = *evt_head; + prev = node; + for (;node;) { + if (node->dev == dev && node->etype == event && node->cb_func == cb_func) { + if (node == *evt_head) { + tmp = 1; + *evt_head = node->next; + } else { + tmp = 0; + prev->next = node->next; + } + EVENT_TRACE(dev->name, "event %d deregistered\n", event); + kfree(node); + if (tmp == 1) { + node = *evt_head; + prev = node; + } else { + node = prev->next; + } + continue; + } + prev = node; + node = node->next; + } + mutex_unlock(&event_params->event_sync); + } else { + EVENT_ERROR(dev->name, "event_params not ready %d\n", event); + } +} + +static s32 +wl_ext_event_init_priv(struct wl_event_params *event_params) +{ + s32 err = 0; + + mutex_init(&event_params->event_sync); + wl_ext_event_init_eq(event_params); + if (wl_ext_event_create_handler(event_params)) + return -ENOMEM; + + return err; +} + +static void +wl_ext_event_deinit_priv(struct wl_event_params *event_params) +{ + wl_ext_event_destroy_handler(event_params); + wl_ext_event_flush_eq(event_params); + wl_ext_event_free(event_params); +} + +int +wl_ext_event_attach_netdev(struct net_device *net, int ifidx, uint8 bssidx) +{ + struct dhd_pub *dhd = dhd_get_pub(net); + struct wl_event_params *event_params = dhd->event_params; + + EVENT_TRACE(net->name, "ifidx=%d, bssidx=%d\n", ifidx, bssidx); + if (event_params && ifidx < WL_MAX_IFS) { + event_params->dev[ifidx] = net; + } + + return 0; +} + +int +wl_ext_event_dettach_netdev(struct net_device *net, int ifidx) +{ + struct dhd_pub *dhd = dhd_get_pub(net); + struct wl_event_params *event_params = dhd->event_params; + + EVENT_TRACE(net->name, "ifidx=%d\n", ifidx); + if (event_params && ifidx < WL_MAX_IFS) { + event_params->dev[ifidx] = NULL; + } + + return 0; +} + +s32 +wl_ext_event_attach(struct net_device *dev, dhd_pub_t *dhdp) +{ + struct wl_event_params *event_params = NULL; + s32 err = 0; + + event_params = kmalloc(sizeof(wl_event_params_t), GFP_KERNEL); + if (!event_params) { + EVENT_ERROR(dev->name, "Failed to allocate memory (%zu)\n", + sizeof(wl_event_params_t)); + return -ENOMEM; + } + dhdp->event_params = event_params; + memset(event_params, 0, sizeof(wl_event_params_t)); + event_params->pub = dhdp; + + err = wl_ext_event_init_priv(event_params); + if (err) { + EVENT_ERROR(dev->name, "Failed to wl_ext_event_init_priv (%d)\n", err); + goto ext_attach_out; + } + + return err; +ext_attach_out: + wl_ext_event_dettach(dhdp); + return err; +} + +void +wl_ext_event_dettach(dhd_pub_t *dhdp) +{ + struct wl_event_params *event_params = dhdp->event_params; + + if (event_params) { + wl_ext_event_deinit_priv(event_params); + kfree(event_params); + dhdp->event_params = NULL; + } +} +#endif diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_iw.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_iw.c index fc06441207ac..52067f536b95 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_iw.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_iw.c @@ -44,39 +44,70 @@ #ifdef WL_NAN #include #endif +#include #include #ifdef WL_ESCAN #include #endif #include -typedef const struct si_pub si_t; - -/* message levels */ -#define WL_ERROR_LEVEL 0x0001 -#define WL_SCAN_LEVEL 0x0002 -#define WL_ASSOC_LEVEL 0x0004 -#define WL_INFORM_LEVEL 0x0008 -#define WL_WSEC_LEVEL 0x0010 -#define WL_PNO_LEVEL 0x0020 -#define WL_COEX_LEVEL 0x0040 -#define WL_SOFTAP_LEVEL 0x0080 -#define WL_TRACE_LEVEL 0x0100 - uint iw_msg_level = WL_ERROR_LEVEL; -#define WL_ERROR(x) do {if (iw_msg_level & WL_ERROR_LEVEL) printf x;} while (0) -#define WL_SCAN(x) do {if (iw_msg_level & WL_SCAN_LEVEL) printf x;} while (0) -#define WL_ASSOC(x) do {if (iw_msg_level & WL_ASSOC_LEVEL) printf x;} while (0) -#define WL_INFORM(x) do {if (iw_msg_level & WL_INFORM_LEVEL) printf x;} while (0) -#define WL_WSEC(x) do {if (iw_msg_level & WL_WSEC_LEVEL) printf x;} while (0) -#define WL_PNO(x) do {if (iw_msg_level & WL_PNO_LEVEL) printf x;} while (0) -#define WL_COEX(x) do {if (iw_msg_level & WL_COEX_LEVEL) printf x;} while (0) -#define WL_SOFTAP(x) do {if (iw_msg_level & WL_SOFTAP_LEVEL) printf x;} while (0) -#define WL_TRACE(x) do {if (iw_msg_level & WL_TRACE_LEVEL) printf x;} while (0) +#define WL_ERROR_MSG(x, args...) \ + do { \ + if (iw_msg_level & WL_ERROR_LEVEL) { \ + printk(KERN_ERR "[dhd] WEXT-ERROR) %s : " x, __func__, ## args); \ + } \ + } while (0) +#define WL_TRACE_MSG(x, args...) \ + do { \ + if (iw_msg_level & WL_TRACE_LEVEL) { \ + printk(KERN_ERR "[dhd] WEXT-TRACE) %s : " x, __func__, ## args); \ + } \ + } while (0) +#define WL_SCAN_MSG(x, args...) \ + do { \ + if (iw_msg_level & WL_SCAN_LEVEL) { \ + printk(KERN_ERR "[dhd] WEXT-SCAN) %s : " x, __func__, ## args); \ + } \ + } while (0) +#define WL_WSEC_MSG(x, args...) \ + do { \ + if (iw_msg_level & WL_WSEC_LEVEL) { \ + printk(KERN_ERR "[dhd] WEXT-WSEC) %s : " x, __func__, ## args); \ + } \ + } while (0) +#define WL_ERROR(x) WL_ERROR_MSG x +#define WL_TRACE(x) WL_TRACE_MSG x +#define WL_SCAN(x) WL_SCAN_MSG x +#define WL_WSEC(x) WL_WSEC_MSG x + +#ifdef BCMWAPI_WPI +/* these items should evetually go into wireless.h of the linux system headfile dir */ +#ifndef IW_ENCODE_ALG_SM4 +#define IW_ENCODE_ALG_SM4 0x20 +#endif -#include +#ifndef IW_AUTH_WAPI_ENABLED +#define IW_AUTH_WAPI_ENABLED 0x20 +#endif +#ifndef IW_AUTH_WAPI_VERSION_1 +#define IW_AUTH_WAPI_VERSION_1 0x00000008 +#endif + +#ifndef IW_AUTH_CIPHER_SMS4 +#define IW_AUTH_CIPHER_SMS4 0x00000020 +#endif + +#ifndef IW_AUTH_KEY_MGMT_WAPI_PSK +#define IW_AUTH_KEY_MGMT_WAPI_PSK 4 +#endif + +#ifndef IW_AUTH_KEY_MGMT_WAPI_CERT +#define IW_AUTH_KEY_MGMT_WAPI_CERT 8 +#endif +#endif /* BCMWAPI_WPI */ /* Broadcom extensions to WEXT, linux upstream has obsoleted WEXT */ #ifndef IW_AUTH_KEY_MGMT_FT_802_1X @@ -161,14 +192,9 @@ typedef struct iscan_buf { char iscan_buf[WLC_IW_ISCAN_MAXLEN]; } iscan_buf_t; -struct pmk_list { - pmkid_list_t pmkids; - pmkid_t foo[MAXPMKID - 1]; -}; - typedef struct iscan_info { struct net_device *dev; - struct timer_list timer; + timer_list_compat_t timer; uint32 timer_ms; uint32 timer_on; int iscan_state; @@ -183,13 +209,28 @@ typedef struct iscan_info { struct semaphore sysioc_sem; struct completion sysioc_exited; char ioctlbuf[WLC_IOCTL_SMLEN]; - struct pmk_list pmk_list; - wl_conn_info_t conn_info; } iscan_info_t; static void wl_iw_timerfunc(ulong data); static void wl_iw_set_event_mask(struct net_device *dev); static int wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action); -#endif /* WL_ESCAN */ +#endif /* !WL_ESCAN */ + +struct pmk_list { + pmkid_list_t pmkids; + pmkid_t foo[MAXPMKID - 1]; +}; + +typedef struct wl_wext_info { + struct net_device *dev; + dhd_pub_t *dhd; + struct delayed_work pm_enable_work; + struct mutex pm_sync; + struct wl_conn_info conn_info; + struct pmk_list pmk_list; +#ifndef WL_ESCAN + struct iscan_info iscan; +#endif +} wl_wext_info_t; /* priv_link becomes netdev->priv and is the link between netdev and wlif struct */ typedef struct priv_link { @@ -473,35 +514,145 @@ wl_iw_set_pm( } #endif /* WIRELESS_EXT > 12 */ +#define WL_PM_ENABLE_TIMEOUT 10000 +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \ + 4 && __GNUC_MINOR__ >= 6)) +#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \ +_Pragma("GCC diagnostic push") \ +_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \ +entry = container_of((ptr), type, member); \ +_Pragma("GCC diagnostic pop") +#else +#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \ +entry = container_of((ptr), type, member); +#endif /* STRICT_GCC_WARNINGS */ + +void wl_ext_pm_work_handler(struct work_struct *work) +{ + struct wl_wext_info *wext_info; + s32 pm = PM_FAST; + dhd_pub_t *dhd; + int ret = 0; + + BCM_SET_CONTAINER_OF(wext_info, work, struct wl_wext_info, pm_enable_work.work); + + WL_TRACE(("%s: Enter\n", __FUNCTION__)); +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \ + 4 && __GNUC_MINOR__ >= 6)) +_Pragma("GCC diagnostic push") +_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#endif + + dhd = (dhd_pub_t *)(wext_info->dhd); + if (!dhd || !wext_info->dhd->up) { + WL_TRACE(("%s: dhd is null or not up\n", __FUNCTION__)); + return; + } + if (dhd_conf_get_pm(dhd) >= 0) + pm = dhd_conf_get_pm(dhd); + ret = dev_wlc_ioctl(wext_info->dev, WLC_SET_PM, &pm, sizeof(pm)); + if (ret) + WL_ERROR(("%s: WLC_SET_PM failed %d\n", __FUNCTION__, ret)); +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \ + 4 && __GNUC_MINOR__ >= 6)) +_Pragma("GCC diagnostic pop") +#endif + DHD_PM_WAKE_UNLOCK(wext_info->dhd); + +} + +void wl_ext_add_remove_pm_enable_work(struct wl_wext_info *wext_info, + bool add) +{ + u16 wq_duration = 0; + s32 pm = PM_OFF; + int ret = 0; + + if (wext_info == NULL || wext_info->dhd == NULL) + return; + + mutex_lock(&wext_info->pm_sync); + /* + * Make cancel and schedule work part mutually exclusive + * so that while cancelling, we are sure that there is no + * work getting scheduled. + */ + + if (delayed_work_pending(&wext_info->pm_enable_work)) { + cancel_delayed_work_sync(&wext_info->pm_enable_work); + DHD_PM_WAKE_UNLOCK(wext_info->dhd); + } + + if (add) { + wq_duration = (WL_PM_ENABLE_TIMEOUT); + } + + /* It should schedule work item only if driver is up */ + if (wq_duration && wext_info->dhd->up) { + if (dhd_conf_get_pm(wext_info->dhd) >= 0) + pm = dhd_conf_get_pm(wext_info->dhd); + ret = dev_wlc_ioctl(wext_info->dev, WLC_SET_PM, &pm, sizeof(pm)); + if (ret) + WL_ERROR(("%s: WLC_SET_PM failed %d\n", __FUNCTION__, ret)); + if (schedule_delayed_work(&wext_info->pm_enable_work, + msecs_to_jiffies((const unsigned int)wq_duration))) { + DHD_PM_WAKE_LOCK_TIMEOUT(wext_info->dhd, wq_duration); + } else { + WL_ERROR(("%s: Can't schedule pm work handler\n", __FUNCTION__)); + } + } + mutex_unlock(&wext_info->pm_sync); + +} + static void -wl_iw_check_handshake(struct net_device *dev, bool set) +wl_iw_update_connect_status(struct net_device *dev, enum wl_ext_status status) { #ifndef WL_CFG80211 struct dhd_pub *dhd = dhd_get_pub(dev); int cur_eapol_status = 0; int wpa_auth = 0; int error = -EINVAL; + wl_wext_info_t *wext_info = NULL; - if (dhd && dhd->conf) - cur_eapol_status = dhd->conf->eapol_status; + if (!dhd || !dhd->conf) + return; + wext_info = dhd->wext_info; + cur_eapol_status = dhd->conf->eapol_status; - if (set) { + if (status == WL_EXT_STATUS_CONNECTING) { + wl_ext_add_remove_pm_enable_work(wext_info, TRUE); if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &wpa_auth))) { - WL_ERROR(("%s: wpa_auth get error %d\n", __FUNCTION__, error)); + WL_ERROR(("wpa_auth get error %d\n", error)); return; } if (wpa_auth & (WPA_AUTH_PSK|WPA2_AUTH_PSK)) - dhd->conf->eapol_status = EAPOL_STATUS_WPA_START; + dhd->conf->eapol_status = EAPOL_STATUS_4WAY_START; else dhd->conf->eapol_status = EAPOL_STATUS_NONE; - } else { - if (cur_eapol_status >= EAPOL_STATUS_WPA_START && - cur_eapol_status < EAPOL_STATUS_WPA_END) { - WL_ERROR(("%s: WPA failed at %d\n", __FUNCTION__, cur_eapol_status)); + } else if (status == WL_EXT_STATUS_ADD_KEY) { + dhd->conf->eapol_status = EAPOL_STATUS_4WAY_DONE; + wake_up_interruptible(&dhd->conf->event_complete); + } else if (status == WL_EXT_STATUS_DISCONNECTING) { + wl_ext_add_remove_pm_enable_work(wext_info, FALSE); + if (cur_eapol_status >= EAPOL_STATUS_4WAY_START && + cur_eapol_status < EAPOL_STATUS_4WAY_DONE) { + WL_ERROR(("WPA failed at %d\n", cur_eapol_status)); dhd->conf->eapol_status = EAPOL_STATUS_NONE; - } else if (cur_eapol_status >= EAPOL_STATUS_WPS_WSC_START && - cur_eapol_status < EAPOL_STATUS_WPS_DONE) { - WL_ERROR(("%s: WPS failed at %d\n", __FUNCTION__, cur_eapol_status)); + } else if (cur_eapol_status >= EAPOL_STATUS_WSC_START && + cur_eapol_status < EAPOL_STATUS_WSC_DONE) { + WL_ERROR(("WPS failed at %d\n", cur_eapol_status)); + dhd->conf->eapol_status = EAPOL_STATUS_NONE; + } + } else if (status == WL_EXT_STATUS_DISCONNECTED) { + if (cur_eapol_status >= EAPOL_STATUS_4WAY_START && + cur_eapol_status < EAPOL_STATUS_4WAY_DONE) { + WL_ERROR(("WPA failed at %d\n", cur_eapol_status)); + dhd->conf->eapol_status = EAPOL_STATUS_NONE; + wake_up_interruptible(&dhd->conf->event_complete); + } else if (cur_eapol_status >= EAPOL_STATUS_WSC_START && + cur_eapol_status < EAPOL_STATUS_WSC_DONE) { + WL_ERROR(("WPS failed at %d\n", cur_eapol_status)); dhd->conf->eapol_status = EAPOL_STATUS_NONE; } } @@ -557,7 +708,7 @@ wl_iw_config_commit( bzero(&bssid, sizeof(struct sockaddr)); if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, &bssid, ETHER_ADDR_LEN))) { - WL_ERROR(("%s: WLC_REASSOC failed (%d)\n", __FUNCTION__, error)); + WL_ERROR(("WLC_REASSOC failed (%d)\n", error)); return error; } @@ -611,6 +762,12 @@ done: return 0; } +#define DHD_CHECK(dhd, dev) \ + if (!dhd) { \ + WL_ERROR (("[dhd-%s] %s: dhd is NULL\n", dev->name, __FUNCTION__)); \ + return -ENODEV; \ + } \ + static int wl_iw_set_freq( struct net_device *dev, @@ -622,22 +779,11 @@ wl_iw_set_freq( int error, chan; uint sf = 0; struct dhd_pub *dhd = dhd_get_pub(dev); - wl_conn_info_t *conn_info = NULL; -#ifdef WL_ESCAN - wl_escan_info_t *escan; - if (dhd && dhd->escan) { - escan = (wl_escan_info_t *)dhd->escan; - conn_info = &escan->conn_info; - } -#else - iscan_info_t *iscan; - if (dhd && dhd->iscan) { - iscan = (iscan_info_t *)dhd->iscan; - conn_info = &iscan->conn_info; - } -#endif + wl_wext_info_t *wext_info = NULL; WL_TRACE(("%s: SIOCSIWFREQ\n", dev->name)); + DHD_CHECK(dhd, dev); + wext_info = dhd->wext_info; /* Setting by channel number */ if (fwrq->e == 0 && fwrq->m < MAXCHANNEL) { @@ -661,12 +807,12 @@ wl_iw_set_freq( } chan = wf_mhz2channel(fwrq->m, sf); } - if (conn_info) - conn_info->channel = chan; - WL_ERROR(("%s: chan=%d\n", __FUNCTION__, chan)); + if (wext_info) + wext_info->conn_info.channel = chan; + WL_MSG(dev->name, "chan=%d\n", chan); chan = htod32(chan); if ((error = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &chan, sizeof(chan)))) { - WL_ERROR(("%s: WLC_SET_CHANNEL failed (%d).\n", __FUNCTION__, error)); + WL_ERROR(("WLC_SET_CHANNEL failed (%d).\n", error)); return error; } @@ -708,24 +854,16 @@ wl_iw_set_mode( { int infra = 0, ap = 0, error = 0; struct dhd_pub *dhd = dhd_get_pub(dev); - wl_conn_info_t *conn_info = NULL; -#ifdef WL_ESCAN - wl_escan_info_t *escan; - if (dhd && dhd->escan) { - escan = (wl_escan_info_t *)dhd->escan; - conn_info = &escan->conn_info; - } -#else - iscan_info_t *iscan; - if (dhd && dhd->iscan) { - iscan = (iscan_info_t *)dhd->iscan; - conn_info = &iscan->conn_info; - } -#endif + wl_wext_info_t *wext_info = NULL; WL_TRACE(("%s: SIOCSIWMODE\n", dev->name)); - if (conn_info) - memset(conn_info, 0, sizeof(wl_conn_info_t)); + DHD_CHECK(dhd, dev); + wext_info = dhd->wext_info; + if (wext_info) { + memset(&wext_info->conn_info.ssid, 0, sizeof(wlc_ssid_t)); + memset(&wext_info->conn_info.bssid, 0, sizeof(struct ether_addr)); + wext_info->conn_info.channel = 0; + } switch (*uwrq) { case IW_MODE_MASTER: @@ -1070,25 +1208,13 @@ wl_iw_set_wap( { int error = -EINVAL; struct dhd_pub *dhd = dhd_get_pub(dev); - wl_conn_info_t *conn_info = NULL; -#ifdef WL_ESCAN - wl_escan_info_t *escan; - if (dhd && dhd->escan) { - escan = (wl_escan_info_t *)dhd->escan; - conn_info = &escan->conn_info; - } -#else - iscan_info_t *iscan; - if (dhd && dhd->iscan) { - iscan = (iscan_info_t *)dhd->iscan; - conn_info = &iscan->conn_info; - } -#endif + wl_wext_info_t *wext_info = NULL; WL_TRACE(("%s: SIOCSIWAP\n", dev->name)); - + DHD_CHECK(dhd, dev); + wext_info = dhd->wext_info; if (awrq->sa_family != ARPHRD_ETHER) { - WL_ERROR(("%s: Invalid Header...sa_family\n", __FUNCTION__)); + WL_ERROR(("Invalid Header...sa_family\n")); return -EINVAL; } @@ -1096,30 +1222,30 @@ wl_iw_set_wap( if (ETHER_ISBCAST(awrq->sa_data) || ETHER_ISNULLADDR(awrq->sa_data)) { scb_val_t scbval; bzero(&scbval, sizeof(scb_val_t)); - WL_ERROR(("%s: WLC_DISASSOC\n", __FUNCTION__)); + WL_MSG(dev->name, "WLC_DISASSOC\n"); if ((error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)))) { - WL_ERROR(("%s: WLC_DISASSOC failed (%d).\n", __FUNCTION__, error)); + WL_ERROR(("WLC_DISASSOC failed (%d).\n", error)); } - wl_iw_check_handshake(dev, FALSE); + wl_iw_update_connect_status(dev, WL_EXT_STATUS_DISCONNECTING); return 0; } /* WL_ASSOC(("Assoc to %s\n", bcm_ether_ntoa((struct ether_addr *)&(awrq->sa_data), * eabuf))); */ /* Reassociate to the specified AP */ - if (conn_info) - memcpy(&conn_info->bssid, awrq->sa_data, ETHER_ADDR_LEN); - if (conn_info && conn_info->ssid.SSID_len) { - if ((error = wl_ext_connect(dev, conn_info))) + if (wext_info) + memcpy(&wext_info->conn_info.bssid, awrq->sa_data, ETHER_ADDR_LEN); + if (wext_info && wext_info->conn_info.ssid.SSID_len) { + if ((error = wl_ext_connect(dev, &wext_info->conn_info))) return error; } else { if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, awrq->sa_data, ETHER_ADDR_LEN))) { - WL_ERROR(("%s: WLC_REASSOC failed (%d).\n", __FUNCTION__, error)); + WL_ERROR(("WLC_REASSOC failed (%d).\n", error)); return error; } - WL_ERROR(("%s: join BSSID="MACSTR"\n", __FUNCTION__, MAC2STR((u8 *)awrq->sa_data))); + WL_MSG(dev->name, "join BSSID="MACSTR"\n", MAC2STR((u8 *)awrq->sa_data)); } - wl_iw_check_handshake(dev, TRUE); + wl_iw_update_connect_status(dev, WL_EXT_STATUS_CONNECTING); return 0; } @@ -1169,18 +1295,20 @@ wl_iw_mlme( if (mlme->cmd == IW_MLME_DISASSOC) { scbval.val = htod32(scbval.val); + WL_MSG(dev->name, "WLC_DISASSOC\n"); error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)); } else if (mlme->cmd == IW_MLME_DEAUTH) { scbval.val = htod32(scbval.val); + WL_MSG(dev->name, "WLC_SCB_DEAUTHENTICATE_FOR_REASON\n"); error = dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval, sizeof(scb_val_t)); } else { - WL_ERROR(("%s: Invalid ioctl data.\n", __FUNCTION__)); + WL_ERROR(("Invalid ioctl data.\n")); return error; } - wl_iw_check_handshake(dev, FALSE); + wl_iw_update_connect_status(dev, WL_EXT_STATUS_DISCONNECTING); return error; } @@ -1281,10 +1409,12 @@ wl_iw_iscan_get_aplist( int i; int16 rssi; struct dhd_pub *dhd = dhd_get_pub(dev); - if (dhd && dhd->iscan) - iscan = (iscan_info_t *)dhd->iscan; + wl_wext_info_t *wext_info = NULL; WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name)); + DHD_CHECK(dhd, dev); + wext_info = dhd->wext_info; + iscan = &wext_info->iscan; if (!extra) return -EINVAL; @@ -1372,6 +1502,7 @@ wl_iw_set_scan( return 0; } +#endif static int wl_iw_iscan_set_scan( @@ -1381,12 +1512,32 @@ wl_iw_iscan_set_scan( char *extra ) { - wlc_ssid_t ssid; struct dhd_pub *dhd = dhd_get_pub(dev); + wl_wext_info_t *wext_info = NULL; + wlc_ssid_t ssid; +#ifndef WL_ESCAN iscan_info_t *iscan; - if (dhd && dhd->iscan) - iscan = (iscan_info_t *)dhd->iscan; +#endif + DHD_CHECK(dhd, dev); + wext_info = dhd->wext_info; +#ifdef WL_ESCAN + /* default Broadcast scan */ + memset(&ssid, 0, sizeof(ssid)); +#if WIRELESS_EXT > 17 + /* check for given essid */ + if (wrqu->data.length == sizeof(struct iw_scan_req)) { + if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { + struct iw_scan_req *req = (struct iw_scan_req *)extra; + ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len); + memcpy(ssid.SSID, req->essid, ssid.SSID_len); + ssid.SSID_len = htod32(ssid.SSID_len); + } + } +#endif + return wl_escan_set_scan(dev, dhd, &ssid, 0, TRUE); +#else + iscan = &wext_info->iscan; WL_TRACE(("%s: SIOCSIWSCAN iscan=%p\n", dev->name, iscan)); /* use backup if our thread is not successful */ @@ -1424,8 +1575,8 @@ wl_iw_iscan_set_scan( iscan->timer_on = 1; return 0; +#endif } -#endif /* WL_ESCAN */ #if WIRELESS_EXT > 17 static bool @@ -1473,6 +1624,42 @@ ie_is_wps_ie(uint8 **wpsie, uint8 **tlvs, int *tlvs_len) } #endif /* WIRELESS_EXT > 17 */ +#ifdef BCMWAPI_WPI +static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, + size_t len, int uppercase) +{ + size_t i; + char *pos = buf, *end = buf + buf_size; + int ret; + if (buf_size == 0) + return 0; + for (i = 0; i < len; i++) { + ret = snprintf(pos, end - pos, uppercase ? "%02X" : "%02x", + data[i]); + if (ret < 0 || ret >= end - pos) { + end[-1] = '\0'; + return pos - buf; + } + pos += ret; + } + end[-1] = '\0'; + return pos - buf; +} + +/** + * wpa_snprintf_hex - Print data as a hex string into a buffer + * @buf: Memory area to use as the output buffer + * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) + * @data: Data to be printed + * @len: Length of data in bytes + * Returns: Number of bytes written + */ +static int +wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len) +{ + return _wpa_snprintf_hex(buf, buf_size, data, len, 0); +} +#endif /* BCMWAPI_WPI */ #ifndef WL_ESCAN static @@ -1484,6 +1671,10 @@ wl_iw_handle_scanresults_ies(char **event_p, char *end, #if WIRELESS_EXT > 17 struct iw_event iwe; char *event; +#ifdef BCMWAPI_WPI + char *buf; + int custom_event_len; +#endif event = *event_p; if (bi->ie_length) { @@ -1537,7 +1728,39 @@ wl_iw_handle_scanresults_ies(char **event_p, char *end, break; } } + +#ifdef BCMWAPI_WPI + ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); + ptr_len = bi->ie_length; + while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WAPI_ID))) { + WL_TRACE(("found a WAPI IE...\n")); +#ifdef WAPI_IE_USE_GENIE + iwe.cmd = IWEVGENIE; + iwe.u.data.length = ie->len + 2; + event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); +#else /* using CUSTOM event */ + iwe.cmd = IWEVCUSTOM; + custom_event_len = strlen("wapi_ie=") + 2*(ie->len + 2); + iwe.u.data.length = custom_event_len; + + buf = kmalloc(custom_event_len+1, GFP_KERNEL); + if (buf == NULL) + { + WL_ERROR(("malloc(%d) returned NULL...\n", custom_event_len)); + break; + } + + memcpy(buf, "wapi_ie=", 8); + wpa_snprintf_hex(buf + 8, 2+1, &(ie->id), 1); + wpa_snprintf_hex(buf + 10, 2+1, &(ie->len), 1); + wpa_snprintf_hex(buf + 12, 2*ie->len+1, ie->data, ie->len); + event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, buf); + kfree(buf); +#endif /* WAPI_IE_USE_GENIE */ + break; + } +#endif /* BCMWAPI_WPI */ *event_p = event; } @@ -1564,7 +1787,7 @@ wl_iw_get_scan( int16 rssi; int channel; - WL_TRACE(("%s: %s SIOCGIWSCAN\n", __FUNCTION__, dev->name)); + WL_TRACE(("%s SIOCGIWSCAN\n", dev->name)); if (!extra) return -EINVAL; @@ -1600,8 +1823,8 @@ wl_iw_get_scan( // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL); channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch; - WL_SCAN(("%s: BSSID="MACSTR", channel=%d, RSSI=%d, SSID=\"%s\"\n", - __FUNCTION__, MAC2STR(bi->BSSID.octet), channel, rssi, bi->SSID)); + WL_SCAN(("BSSID="MACSTR", channel=%d, RSSI=%d, SSID=\"%s\"\n", + MAC2STR(bi->BSSID.octet), channel, rssi, bi->SSID)); /* First entry must be the BSSID */ iwe.cmd = SIOCGIWAP; @@ -1674,6 +1897,7 @@ wl_iw_get_scan( return 0; } +#endif /* WL_ESCAN */ static int wl_iw_iscan_get_scan( @@ -1683,6 +1907,9 @@ wl_iw_iscan_get_scan( char *extra ) { + struct dhd_pub *dhd = dhd_get_pub(dev); + wl_wext_info_t *wext_info = NULL; +#ifndef WL_ESCAN wl_scan_results_t *list; struct iw_event iwe; wl_bss_info_t *bi = NULL; @@ -1692,17 +1919,21 @@ wl_iw_iscan_get_scan( iscan_buf_t * p_buf; int16 rssi; int channel; - struct dhd_pub *dhd = dhd_get_pub(dev); iscan_info_t *iscan; - if (dhd && dhd->iscan) - iscan = (iscan_info_t *)dhd->iscan; +#endif - WL_TRACE(("%s: %s SIOCGIWSCAN\n", __FUNCTION__, dev->name)); + DHD_CHECK(dhd, dev); + wext_info = dhd->wext_info; +#ifdef WL_ESCAN + return wl_escan_get_scan(dev, dhd, info, dwrq, extra); +#else + WL_TRACE(("%s SIOCGIWSCAN\n", dev->name)); if (!extra) return -EINVAL; /* use backup if our thread is not successful */ + iscan = &wext_info->iscan; if ((!iscan) || (iscan->sysioc_pid < 0)) { return wl_iw_get_scan(dev, info, dwrq, extra); } @@ -1737,8 +1968,8 @@ wl_iw_iscan_get_scan( // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL); channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch; - WL_SCAN(("%s: BSSID="MACSTR", channel=%d, RSSI=%d, SSID=\"%s\"\n", - __FUNCTION__, MAC2STR(bi->BSSID.octet), channel, rssi, bi->SSID)); + WL_SCAN(("BSSID="MACSTR", channel=%d, RSSI=%d, SSID=\"%s\"\n", + MAC2STR(bi->BSSID.octet), channel, rssi, bi->SSID)); /* First entry must be the BSSID */ iwe.cmd = SIOCGIWAP; @@ -1810,11 +2041,11 @@ wl_iw_iscan_get_scan( dwrq->length = event - extra; dwrq->flags = 0; /* todo */ - WL_SCAN(("%s: apcnt=%d\n", __FUNCTION__, apcnt)); + WL_SCAN(("apcnt=%d\n", apcnt)); return 0; +#endif } -#endif /* WL_ESCAN */ #endif /* WIRELESS_EXT > 13 */ @@ -1829,22 +2060,11 @@ wl_iw_set_essid( wlc_ssid_t ssid; int error; struct dhd_pub *dhd = dhd_get_pub(dev); - wl_conn_info_t *conn_info = NULL; -#ifdef WL_ESCAN - wl_escan_info_t *escan; - if (dhd && dhd->escan) { - escan = (wl_escan_info_t *)dhd->escan; - conn_info = &escan->conn_info; - } -#else - iscan_info_t *iscan; - if (dhd && dhd->iscan) { - iscan = (iscan_info_t *)dhd->iscan; - conn_info = &iscan->conn_info; - } -#endif + wl_wext_info_t *wext_info = NULL; WL_TRACE(("%s: SIOCSIWESSID\n", dev->name)); + DHD_CHECK(dhd, dev); + wext_info = dhd->wext_info; /* default Broadcast SSID */ memset(&ssid, 0, sizeof(ssid)); @@ -1857,32 +2077,32 @@ wl_iw_set_essid( memcpy(ssid.SSID, extra, ssid.SSID_len); ssid.SSID_len = htod32(ssid.SSID_len); - if (conn_info) { - memcpy(conn_info->ssid.SSID, ssid.SSID, ssid.SSID_len); - conn_info->ssid.SSID_len = ssid.SSID_len; + if (wext_info) { + memcpy(wext_info->conn_info.ssid.SSID, ssid.SSID, ssid.SSID_len); + wext_info->conn_info.ssid.SSID_len = ssid.SSID_len; } - if (conn_info && memcmp(ðer_null, &conn_info->bssid, ETHER_ADDR_LEN)) { - if ((error = wl_ext_connect(dev, conn_info))) + if (wext_info && memcmp(ðer_null, &wext_info->conn_info.bssid, ETHER_ADDR_LEN)) { + if ((error = wl_ext_connect(dev, &wext_info->conn_info))) return error; } else { if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid)))) { - WL_ERROR(("%s: WLC_SET_SSID failed (%d).\n", __FUNCTION__, error)); + WL_ERROR(("WLC_SET_SSID failed (%d).\n", error)); return error; } - WL_ERROR(("%s: join SSID=%s\n", __FUNCTION__, ssid.SSID)); + WL_MSG(dev->name, "join SSID=\"%s\"\n", ssid.SSID); } - wl_iw_check_handshake(dev, TRUE); + wl_iw_update_connect_status(dev, WL_EXT_STATUS_CONNECTING); } /* If essid null then it is "iwconfig essid off" command */ else { scb_val_t scbval; bzero(&scbval, sizeof(scb_val_t)); - WL_ERROR(("%s: WLC_DISASSOC\n", __FUNCTION__)); + WL_MSG(dev->name, "WLC_DISASSOC\n"); if ((error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)))) { - WL_ERROR(("%s: WLC_DISASSOC failed (%d).\n", __FUNCTION__, error)); + WL_ERROR(("WLC_DISASSOC failed (%d).\n", error)); return error; } - wl_iw_check_handshake(dev, FALSE); + wl_iw_update_connect_status(dev, WL_EXT_STATUS_DISCONNECTING); } return 0; } @@ -1904,7 +2124,7 @@ wl_iw_get_essid( return -EINVAL; if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid)))) { - WL_ERROR(("Error getting the SSID\n")); + WL_ERROR(("Error getting the SSID %d\n", error)); return error; } @@ -2512,6 +2732,21 @@ wl_iw_set_wpaie( char *extra ) { +#if defined(BCMWAPI_WPI) + uchar buf[WLC_IOCTL_SMLEN] = {0}; + uchar *p = buf; + int wapi_ie_size; + + WL_TRACE(("%s: SIOCSIWGENIE\n", dev->name)); + + if (extra[0] == DOT11_MNG_WAPI_ID) + { + wapi_ie_size = iwp->length; + memcpy(p, extra, iwp->length); + dev_wlc_bufvar_set(dev, "wapiie", buf, wapi_ie_size); + } + else +#endif dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length); return 0; @@ -2542,7 +2777,6 @@ wl_iw_set_encodeext( wl_wsec_key_t key; int error; struct iw_encode_ext *iwe; - struct dhd_pub *dhd = dhd_get_pub(dev); WL_TRACE(("%s: SIOCSIWENCODEEXT\n", dev->name)); @@ -2605,10 +2839,10 @@ wl_iw_set_encodeext( bcopy(keystring, pmk.key, len); pmk.flags = htod16(WSEC_PASSPHRASE); - WL_WSEC(("%s: set key %s\n", __FUNCTION__, keystring)); + WL_WSEC(("set key %s\n", keystring)); error = dev_wlc_ioctl(dev, WLC_SET_WSEC_PMK, &pmk, sizeof(pmk)); if (error) { - WL_ERROR(("%s: WLC_SET_WSEC_PMK error %d\n", __FUNCTION__, error)); + WL_ERROR(("WLC_SET_WSEC_PMK error %d\n", error)); return error; } } @@ -2658,6 +2892,14 @@ wl_iw_set_encodeext( case IW_ENCODE_ALG_CCMP: key.algo = CRYPTO_ALGO_AES_CCM; break; +#ifdef BCMWAPI_WPI + case IW_ENCODE_ALG_SM4: + key.algo = CRYPTO_ALGO_SMS4; + if (iwe->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + key.flags &= ~WL_PRIMARY_KEY; + } + break; +#endif default: break; } @@ -2668,8 +2910,7 @@ wl_iw_set_encodeext( error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key)); if (error) return error; - if (dhd && dhd->conf) - dhd->conf->eapol_status = EAPOL_STATUS_WPA_END; + wl_iw_update_connect_status(dev, WL_EXT_STATUS_ADD_KEY); } return 0; } @@ -2689,21 +2930,12 @@ wl_iw_set_pmksa( char eabuf[ETHER_ADDR_STR_LEN]; pmkid_t *pmkid_array = NULL; struct dhd_pub *dhd = dhd_get_pub(dev); -#ifdef WL_ESCAN - wl_escan_info_t *escan; - if (dhd && dhd->escan) { - escan = (wl_escan_info_t *)dhd->escan; - pmk_list = &escan->pmk_list; - } -#else - iscan_info_t *iscan; - if (dhd && dhd->iscan) { - iscan = (iscan_info_t *)dhd->iscan; - pmk_list = &iscan->pmk_list; - } -#endif + wl_wext_info_t *wext_info = NULL; WL_TRACE(("%s: SIOCSIWPMKSA\n", dev->name)); + DHD_CHECK(dhd, dev); + wext_info = dhd->wext_info; + pmk_list = &wext_info->pmk_list; if (pmk_list) pmkid_array = pmk_list->pmkids.pmkid; iwpmksa = (struct iw_pmksa *)extra; @@ -2770,7 +3002,6 @@ wl_iw_set_pmksa( WL_TRACE(("%02x ", pmkid_array[i].PMKID[j])); printf("\n"); } - WL_TRACE(("\n")); dev_wlc_bufvar_set(dev, "pmkid_info", (char *)pmk_list, sizeof(struct pmk_list)); return 0; } @@ -2820,7 +3051,11 @@ wl_iw_set_wpaauth( val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED; else if (paramval & IW_AUTH_WPA_VERSION_WPA2) val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED; - WL_TRACE(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val)); +#ifdef BCMWAPI_WPI + else if (paramval & IW_AUTH_WAPI_VERSION_1) + val = WAPI_AUTH_UNSPECIFIED; +#endif + WL_TRACE(("%d: setting wpa_auth to 0x%0x\n", __LINE__, val)); if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val))) return error; break; @@ -2837,10 +3072,10 @@ wl_iw_set_wpaauth( } if ((error = dev_wlc_intvar_get(dev, "wsec", &val))) { - WL_ERROR(("%s: wsec error %d\n", __FUNCTION__, error)); + WL_ERROR(("wsec error %d\n", error)); return error; } - WL_WSEC(("%s: get wsec=0x%x\n", __FUNCTION__, val)); + WL_WSEC(("get wsec=0x%x\n", val)); cipher_combined = iw->gwsec | iw->pwsec; val &= ~(WEP_ENABLED | TKIP_ENABLED | AES_ENABLED); @@ -2850,10 +3085,15 @@ wl_iw_set_wpaauth( val |= TKIP_ENABLED; if (cipher_combined & IW_AUTH_CIPHER_CCMP) val |= AES_ENABLED; +#ifdef BCMWAPI_WPI + val &= ~SMS4_ENABLED; + if (cipher_combined & IW_AUTH_CIPHER_SMS4) + val |= SMS4_ENABLED; +#endif if (iw->privacy_invoked && !val) { - WL_WSEC(("%s: %s: 'Privacy invoked' TRUE but clearing wsec, assuming " - "we're a WPS enrollee\n", dev->name, __FUNCTION__)); + WL_WSEC(("%s: 'Privacy invoked' TRUE but clearing wsec, assuming " + "we're a WPS enrollee\n", dev->name)); if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", TRUE))) { WL_WSEC(("Failed to set iovar is_WPS_enrollee\n")); return error; @@ -2865,9 +3105,9 @@ wl_iw_set_wpaauth( } } - WL_WSEC(("%s: set wsec=0x%x\n", __FUNCTION__, val)); + WL_WSEC(("set wsec=0x%x\n", val)); if ((error = dev_wlc_intvar_set(dev, "wsec", val))) { - WL_ERROR(("%s: wsec error %d\n", __FUNCTION__, error)); + WL_ERROR(("wsec error %d\n", error)); return error; } @@ -2875,17 +3115,17 @@ wl_iw_set_wpaauth( * handshake. */ if (dev_wlc_intvar_get(dev, "fbt_cap", &fbt_cap) == 0) { - WL_WSEC(("%s: get fbt_cap=0x%x\n", __FUNCTION__, fbt_cap)); + WL_WSEC(("get fbt_cap=0x%x\n", fbt_cap)); if (fbt_cap == WLC_FBT_CAP_DRV_4WAY_AND_REASSOC) { if ((paramid == IW_AUTH_CIPHER_PAIRWISE) && (val & AES_ENABLED)) { if ((error = dev_wlc_intvar_set(dev, "sup_wpa", 1))) { - WL_ERROR(("%s: sup_wpa 1 error %d\n", __FUNCTION__, error)); + WL_ERROR(("sup_wpa 1 error %d\n", error)); return error; } } else if (val == 0) { if ((error = dev_wlc_intvar_set(dev, "sup_wpa", 0))) { - WL_ERROR(("%s: sup_wpa 0 error %d\n", __FUNCTION__, error)); + WL_ERROR(("sup_wpa 0 error %d\n", error)); return error; } } @@ -2896,10 +3136,10 @@ wl_iw_set_wpaauth( case IW_AUTH_KEY_MGMT: if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val))) { - WL_ERROR(("%s: wpa_auth error %d\n", __FUNCTION__, error)); + WL_ERROR(("wpa_auth error %d\n", error)); return error; } - WL_WSEC(("%s: get wpa_auth to %d\n", __FUNCTION__, val)); + WL_WSEC(("get wpa_auth to %d\n", val)); if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) { if (paramval & (IW_AUTH_KEY_MGMT_FT_PSK | IW_AUTH_KEY_MGMT_PSK)) @@ -2917,7 +3157,11 @@ wl_iw_set_wpaauth( if (paramval & (IW_AUTH_KEY_MGMT_FT_802_1X | IW_AUTH_KEY_MGMT_FT_PSK)) val |= WPA2_AUTH_FT; } - WL_TRACE(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val)); +#ifdef BCMWAPI_WPI + if (paramval & (IW_AUTH_KEY_MGMT_WAPI_PSK | IW_AUTH_KEY_MGMT_WAPI_CERT)) + val = WAPI_AUTH_UNSPECIFIED; +#endif + WL_TRACE(("%d: setting wpa_auth to %d\n", __LINE__, val)); if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val))) return error; break; @@ -2928,7 +3172,7 @@ wl_iw_set_wpaauth( case IW_AUTH_80211_AUTH_ALG: /* open shared */ - WL_ERROR(("Setting the D11auth %d\n", paramval)); + WL_MSG(dev->name, "Setting the D11auth %d\n", paramval); if (paramval & IW_AUTH_ALG_OPEN_SYSTEM) val = 0; else if (paramval & IW_AUTH_ALG_SHARED_KEY) @@ -2942,7 +3186,7 @@ wl_iw_set_wpaauth( case IW_AUTH_WPA_ENABLED: if (paramval == 0) { val = 0; - WL_TRACE(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val)); + WL_TRACE(("%d: setting wpa_auth to %d\n", __LINE__, val)); error = dev_wlc_intvar_set(dev, "wpa_auth", val); return error; } @@ -2962,7 +3206,7 @@ wl_iw_set_wpaauth( #if WIRELESS_EXT > 17 case IW_AUTH_ROAMING_CONTROL: - WL_TRACE(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__)); + WL_TRACE(("IW_AUTH_ROAMING_CONTROL\n")); /* driver control or user space app control */ break; @@ -2999,6 +3243,29 @@ wl_iw_set_wpaauth( #endif /* WIRELESS_EXT > 17 */ +#ifdef BCMWAPI_WPI + + case IW_AUTH_WAPI_ENABLED: + if ((error = dev_wlc_intvar_get(dev, "wsec", &val))) + return error; + if (paramval) { + val |= SMS4_ENABLED; + if ((error = dev_wlc_intvar_set(dev, "wsec", val))) { + WL_ERROR(("setting wsec to 0x%0x returned error %d\n", + val, error)); + return error; + } + if ((error = dev_wlc_intvar_set(dev, "wpa_auth", WAPI_AUTH_UNSPECIFIED))) { + WL_ERROR(("setting wpa_auth(%d) returned %d\n", + WAPI_AUTH_UNSPECIFIED, + error)); + return error; + } + } + + break; + +#endif /* BCMWAPI_WPI */ default: break; @@ -3089,7 +3356,7 @@ wl_iw_get_wpaauth( #if WIRELESS_EXT > 17 case IW_AUTH_ROAMING_CONTROL: - WL_ERROR(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__)); + WL_ERROR(("IW_AUTH_ROAMING_CONTROL\n")); /* driver control or user space app control */ break; @@ -3139,13 +3406,8 @@ static const iw_handler wl_iw_handler[] = (iw_handler) wl_iw_iscan_get_aplist, /* SIOCGIWAPLIST */ #endif #if WIRELESS_EXT > 13 -#ifdef WL_ESCAN - (iw_handler) wl_escan_set_scan, /* SIOCSIWSCAN */ - (iw_handler) wl_escan_get_scan, /* SIOCGIWSCAN */ -#else (iw_handler) wl_iw_iscan_set_scan, /* SIOCSIWSCAN */ (iw_handler) wl_iw_iscan_get_scan, /* SIOCGIWSCAN */ -#endif #else /* WIRELESS_EXT > 13 */ (iw_handler) NULL, /* SIOCSIWSCAN */ (iw_handler) NULL, /* SIOCGIWSCAN */ @@ -3251,9 +3513,12 @@ wl_iw_ioctl( int max_tokens = 0, ret = 0; #ifndef WL_ESCAN struct dhd_pub *dhd = dhd_get_pub(dev); + wl_wext_info_t *wext_info = NULL; iscan_info_t *iscan; - if (dhd && dhd->iscan) - iscan = (iscan_info_t *)dhd->iscan; + + DHD_CHECK(dhd, dev); + wext_info = dhd->wext_info; + iscan = &wext_info->iscan; #endif if (cmd < SIOCIWFIRST || @@ -3449,7 +3714,8 @@ wl_iw_check_conn_fail(wl_event_msg_t *e, char* stringBuf, uint buflen) #endif /* IW_CUSTOM_MAX */ void -wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) +wl_iw_event(struct net_device *dev, struct wl_wext_info *wext_info, + wl_event_msg_t *e, void* data) { #if WIRELESS_EXT > 13 union iwreq_data wrqu; @@ -3461,10 +3727,7 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) uint32 status = ntoh32(e->status); uint32 reason = ntoh32(e->reason); #ifndef WL_ESCAN - struct dhd_pub *dhd = dhd_get_pub(dev); - iscan_info_t *iscan; - if (dhd && dhd->iscan) - iscan = (iscan_info_t *)dhd->iscan; + iscan_info_t *iscan = &wext_info->iscan; #endif memset(&wrqu, 0, sizeof(wrqu)); @@ -3483,25 +3746,32 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) case WLC_E_REASSOC_IND: cmd = IWEVREGISTERED; break; + case WLC_E_DEAUTH: + case WLC_E_DISASSOC: + wl_iw_update_connect_status(dev, WL_EXT_STATUS_DISCONNECTED); + WL_MSG(dev->name, "disconnected with "MACSTR", event %d, reason %d\n", + MAC2STR((u8 *)wrqu.addr.sa_data), event_type, reason); + break; case WLC_E_DEAUTH_IND: case WLC_E_DISASSOC_IND: cmd = SIOCGIWAP; - wrqu.data.length = strlen(extra); + WL_MSG(dev->name, "disconnected with "MACSTR", event %d, reason %d\n", + MAC2STR((u8 *)wrqu.addr.sa_data), event_type, reason); bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN); bzero(&extra, ETHER_ADDR_LEN); - wl_iw_check_handshake(dev, FALSE); + wl_iw_update_connect_status(dev, WL_EXT_STATUS_DISCONNECTED); break; case WLC_E_LINK: cmd = SIOCGIWAP; if (!(flags & WLC_EVENT_MSG_LINK)) { - printf("%s: Link Down with "MACSTR", reason=%d\n", __FUNCTION__, + WL_MSG(dev->name, "Link Down with "MACSTR", reason=%d\n", MAC2STR((u8 *)wrqu.addr.sa_data), reason); bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN); bzero(&extra, ETHER_ADDR_LEN); - wl_iw_check_handshake(dev, FALSE); + wl_iw_update_connect_status(dev, WL_EXT_STATUS_DISCONNECTED); } else { - printf("%s: Link UP with "MACSTR"\n", __FUNCTION__, + WL_MSG(dev->name, "Link UP with "MACSTR"\n", MAC2STR((u8 *)wrqu.addr.sa_data)); } break; @@ -3582,13 +3852,7 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) } #endif /* WIRELESS_EXT > 17 */ -#ifdef WL_ESCAN - case WLC_E_ESCAN_RESULT: - WL_TRACE(("event WLC_E_ESCAN_RESULT\n")); - wl_escan_event(dev, e, data); - break; -#else - +#ifndef WL_ESCAN case WLC_E_SCAN_COMPLETE: #if WIRELESS_EXT > 14 cmd = SIOCGIWSCAN; @@ -3687,7 +3951,7 @@ static int wl_iw_get_wireless_stats_cbfn(void *ctx, uint8 *data, uint16 type, ui break; } default: - WL_ERROR(("%s %d: Unsupported type %d\n", __FUNCTION__, __LINE__, type)); + WL_ERROR(("%d: Unsupported type %d\n", __LINE__, type)); break; } return res; @@ -3709,7 +3973,7 @@ int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstat phy_noise = 0; if ((res = dev_wlc_ioctl(dev, WLC_GET_PHY_NOISE, &phy_noise, sizeof(phy_noise)))) { - WL_ERROR(("%s: WLC_GET_PHY_NOISE error=%d\n", __FUNCTION__, res)); + WL_ERROR(("WLC_GET_PHY_NOISE error=%d\n", res)); goto done; } @@ -3718,7 +3982,7 @@ int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstat memset(&scb_val, 0, sizeof(scb_val)); if ((res = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t)))) { - WL_ERROR(("%s: WLC_GET_RSSI error=%d\n", __FUNCTION__, res)); + WL_ERROR(("WLC_GET_RSSI error=%d\n", res)); goto done; } @@ -3783,7 +4047,7 @@ int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstat memset(&revinfo, 0, sizeof(revinfo)); res = dev_wlc_ioctl(dev, WLC_GET_REVINFO, &revinfo, sizeof(revinfo)); if (res) { - WL_ERROR(("%s: WLC_GET_REVINFO failed %d\n", __FUNCTION__, res)); + WL_ERROR(("WLC_GET_REVINFO failed %d\n", res)); goto done; } corerev = dtoh32(revinfo.corerev); @@ -3792,7 +4056,7 @@ int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstat #ifdef WL_NAN res = wl_cntbuf_to_xtlv_format(NULL, cntinfo, MAX_WLIW_IOCTL_LEN, corerev); if (res) { - WL_ERROR(("%s: wl_cntbuf_to_xtlv_format failed %d\n", __FUNCTION__, res)); + WL_ERROR(("wl_cntbuf_to_xtlv_format failed %d\n", res)); goto done; } @@ -3814,19 +4078,9 @@ done: #ifndef WL_ESCAN static void -wl_iw_timerfunc( -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - struct timer_list *t -#else - unsigned long data -#endif -) +wl_iw_timerfunc(ulong data) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - iscan_info_t *iscan = from_timer(iscan, t, timer); -#else iscan_info_t *iscan = (iscan_info_t *)data; -#endif iscan->timer_on = 0; if (iscan->iscan_state != ISCAN_STATE_IDLE) { WL_TRACE(("timer trigger\n")); @@ -3977,7 +4231,7 @@ _iscan_sysioc_thread(void *data) uint32 status; iscan_info_t *iscan = (iscan_info_t *)data; - printf("%s: thread Enter\n", __FUNCTION__); + WL_MSG("wlan", "thread Enter\n"); DAEMONIZE("iscan_sysioc"); status = WL_SCAN_RESULTS_PARTIAL; @@ -4033,62 +4287,24 @@ _iscan_sysioc_thread(void *data) break; } } - printf("%s: was terminated\n", __FUNCTION__); + WL_MSG("wlan", "was terminated\n"); complete_and_exit(&iscan->sysioc_exited, 0); } +#endif /* !WL_ESCAN */ -int -wl_iw_attach(struct net_device *dev, dhd_pub_t *dhdp) -{ - iscan_info_t *iscan = NULL; - - printf("%s: Enter\n", __FUNCTION__); - - if (!dev) - return 0; - - iscan = kmalloc(sizeof(iscan_info_t), GFP_KERNEL); - if (!iscan) - return -ENOMEM; - dhdp->iscan = (void *)iscan; - memset(iscan, 0, sizeof(iscan_info_t)); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) - iscan->kthread = NULL; -#endif - iscan->sysioc_pid = -1; - /* we only care about main interface so save a global here */ - iscan->dev = dev; - iscan->iscan_state = ISCAN_STATE_IDLE; - - /* Set up the timer */ - iscan->timer_ms = 2000; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - timer_setup(&iscan->timer, wl_iw_timerfunc, 0); -#else - init_timer(&iscan->timer); - iscan->timer.data = (ulong)iscan; - iscan->timer.function = wl_iw_timerfunc; -#endif - - sema_init(&iscan->sysioc_sem, 0); - init_completion(&iscan->sysioc_exited); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) - iscan->kthread = kthread_run(_iscan_sysioc_thread, iscan, "iscan_sysioc"); - iscan->sysioc_pid = iscan->kthread->pid; -#else - iscan->sysioc_pid = kernel_thread(_iscan_sysioc_thread, iscan, 0); -#endif - if (iscan->sysioc_pid < 0) - return -ENOMEM; - return 0; -} - -void wl_iw_detach(dhd_pub_t *dhdp) +void +wl_iw_detach(struct net_device *dev, dhd_pub_t *dhdp) { + wl_wext_info_t *wext_info = dhdp->wext_info; +#ifndef WL_ESCAN iscan_buf_t *buf; - iscan_info_t *iscan = dhdp->iscan; - if (!iscan) + iscan_info_t *iscan; +#endif + if (!wext_info) return; + +#ifndef WL_ESCAN + iscan = &wext_info->iscan; if (iscan->sysioc_pid >= 0) { KILL_PROC(iscan->sysioc_pid, SIGTERM); wait_for_completion(&iscan->sysioc_exited); @@ -4099,9 +4315,135 @@ void wl_iw_detach(dhd_pub_t *dhdp) kfree(iscan->list_hdr); iscan->list_hdr = buf; } - kfree(iscan); - dhdp->iscan = NULL; +#endif + wl_ext_add_remove_pm_enable_work(wext_info, FALSE); + wl_ext_event_deregister(dev, dhdp, WLC_E_LAST, wl_iw_event); + if (wext_info) { + kfree(wext_info); + dhdp->wext_info = NULL; + } +} + +int +wl_iw_attach(struct net_device *dev, dhd_pub_t *dhdp) +{ + wl_wext_info_t *wext_info = NULL; + int ret = 0; +#ifndef WL_ESCAN + iscan_info_t *iscan = NULL; +#endif + + if (!dev) + return 0; + WL_TRACE(("Enter\n")); + + wext_info = (void *)kzalloc(sizeof(struct wl_wext_info), GFP_KERNEL); + if (!wext_info) + return -ENOMEM; + memset(wext_info, 0, sizeof(wl_wext_info_t)); + wext_info->dev = dev; + wext_info->dhd = dhdp; + wext_info->conn_info.bssidx = 0; + dhdp->wext_info = (void *)wext_info; + +#ifndef WL_ESCAN + iscan = &wext_info->iscan; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) + iscan->kthread = NULL; +#endif + iscan->sysioc_pid = -1; + /* we only care about main interface so save a global here */ + iscan->dev = dev; + iscan->iscan_state = ISCAN_STATE_IDLE; + + /* Set up the timer */ + iscan->timer_ms = 2000; + init_timer_compat(&iscan->timer, wl_iw_timerfunc, iscan); + + sema_init(&iscan->sysioc_sem, 0); + init_completion(&iscan->sysioc_exited); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) + iscan->kthread = kthread_run(_iscan_sysioc_thread, iscan, "iscan_sysioc"); + iscan->sysioc_pid = iscan->kthread->pid; +#else + iscan->sysioc_pid = kernel_thread(_iscan_sysioc_thread, iscan, 0); +#endif + if (iscan->sysioc_pid < 0) { + ret = -ENOMEM; + goto exit; + } +#endif + mutex_init(&wext_info->pm_sync); + INIT_DELAYED_WORK(&wext_info->pm_enable_work, wl_ext_pm_work_handler); + ret = wl_ext_event_register(dev, dhdp, WLC_E_LAST, wl_iw_event, dhdp->wext_info, + PRIO_EVENT_WEXT); + if (ret) { + WL_ERROR(("wl_ext_event_register err %d\n", ret)); + goto exit; + } + + return ret; +exit: + wl_iw_detach(dev, dhdp); + return ret; +} + +void +wl_iw_down(struct net_device *dev, dhd_pub_t *dhdp) +{ + wl_wext_info_t *wext_info = NULL; + + if (dhdp) { + wext_info = dhdp->wext_info; + } else { + WL_ERROR (("dhd is NULL\n")); + return; + } + wl_ext_add_remove_pm_enable_work(wext_info, FALSE); +} + +int +wl_iw_up(struct net_device *dev, dhd_pub_t *dhdp) +{ + wl_wext_info_t *wext_info = NULL; + int ret = 0; + + if (dhdp) { + wext_info = dhdp->wext_info; + } else { + WL_ERROR (("dhd is NULL\n")); + return -ENODEV; + } + + return ret; +} + +s32 +wl_iw_autochannel(struct net_device *dev, char* command, int total_len) +{ + struct dhd_pub *dhd = dhd_get_pub(dev); + wl_wext_info_t *wext_info = NULL; + int ret = 0; +#ifdef WL_ESCAN + int bytes_written = -1; +#endif + + DHD_CHECK(dhd, dev); + wext_info = dhd->wext_info; +#ifdef WL_ESCAN + sscanf(command, "%*s %d", &dhd->escan->autochannel); + if (dhd->escan->autochannel == 0) { + dhd->escan->best_2g_ch = 0; + dhd->escan->best_5g_ch = 0; + } else if (dhd->escan->autochannel == 2) { + bytes_written = snprintf(command, total_len, "2g=%d 5g=%d", + dhd->escan->best_2g_ch, dhd->escan->best_5g_ch); + WL_TRACE(("command result is %s\n", command)); + ret = bytes_written; + } +#endif + + return ret; } -#endif /* !WL_ESCAN */ #endif /* USE_IW */ diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_iw.h b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_iw.h index 0adba1b52b03..0fae6a8041ec 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_iw.h +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_iw.h @@ -109,7 +109,7 @@ typedef struct wl_iw { } wl_iw_t; struct wl_ctrl { - struct timer_list *timer; + timer_list_compat_t *timer; struct net_device *dev; long sysioc_pid; struct semaphore sysioc_sem; @@ -123,16 +123,24 @@ extern const struct iw_handler_def wl_iw_handler_def; #endif /* WIRELESS_EXT > 12 */ extern int wl_iw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -extern void wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data); extern int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats); int wl_iw_send_priv_event(struct net_device *dev, char *flag); #ifdef WL_ESCAN int wl_iw_handle_scanresults_ies(char **event_p, char *end, struct iw_request_info *info, wl_bss_info_t *bi); -#else -int wl_iw_attach(struct net_device *dev, dhd_pub_t *dhdp); -void wl_iw_detach(dhd_pub_t *dhdp); #endif +int wl_iw_attach(struct net_device *dev, dhd_pub_t *dhdp); +void wl_iw_detach(struct net_device *dev, dhd_pub_t *dhdp); +int wl_iw_up(struct net_device *dev, dhd_pub_t *dhdp); +void wl_iw_down(struct net_device *dev, dhd_pub_t *dhdp); +s32 wl_iw_autochannel(struct net_device *dev, char* command, int total_len); + +/* message levels */ +#define WL_ERROR_LEVEL (1 << 0) +#define WL_TRACE_LEVEL (1 << 1) +#define WL_INFO_LEVEL (1 << 2) +#define WL_SCAN_LEVEL (1 << 3) +#define WL_WSEC_LEVEL (1 << 4) #define CSCAN_COMMAND "CSCAN " #define CSCAN_TLV_PREFIX 'S' diff --git a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wldev_common.c b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wldev_common.c index 38b7117463ac..49df1a484aea 100644 --- a/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wldev_common.c +++ b/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wldev_common.c @@ -46,17 +46,17 @@ #define htodchanspec(i) (i) #define dtohchanspec(i) (i) -#define WLDEV_ERROR(args) \ - do { \ - printk(KERN_ERR "WLDEV-ERROR) "); \ - printk args; \ +#define WLDEV_ERROR_MSG(x, args...) \ + do { \ + printk(KERN_INFO "WLDEV-ERROR) " x, ## args); \ } while (0) +#define WLDEV_ERROR(x) WLDEV_ERROR_MSG x -#define WLDEV_INFO(args) \ - do { \ - printk(KERN_INFO "WLDEV-INFO) "); \ - printk args; \ +#define WLDEV_INFO_MSG(x, args...) \ + do { \ + printk(KERN_INFO "WLDEV-INFO) " x, ## args); \ } while (0) +#define WLDEV_INFO(x) WLDEV_INFO_MSG x extern int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd); @@ -479,7 +479,6 @@ int wldev_set_country( wl_country_t cspec = {{0}, 0, {0}}; wl_country_t cur_cspec = {{0}, 0, {0}}; /* current ccode */ scb_val_t scbval; - char smbuf[WLC_IOCTL_SMLEN]; #ifdef WL_CFG80211 struct wireless_dev *wdev = ndev_to_wdev(dev); struct wiphy *wiphy = wdev->wiphy; @@ -525,8 +524,7 @@ int wldev_set_country( } } - error = wldev_iovar_setbuf(dev, "country", &cspec, sizeof(cspec), - smbuf, sizeof(smbuf), NULL); + error = dhd_conf_set_country(dhd_get_pub(dev), &cspec); if (error < 0) { WLDEV_ERROR(("%s: set country for %s as %s rev %d failed\n", __FUNCTION__, country_code, cspec.ccode, cspec.rev));