From 3910ce8e87fb55d14a2a8d7f90aa34b6a04f3db4 Mon Sep 17 00:00:00 2001 From: Liang Ji Date: Tue, 30 Jun 2020 21:07:22 +0800 Subject: [PATCH] update dhd to 100.10.545.11 [1/1] PD#SWPL-28928 Problem: cmd: iw --debug phy0 interface add test type managed failed on adt3 Solution: update dhd Driver: 100.10.545.11 (r826445-20200610-1) Verify: deadpool + R Signed-off-by: Liang Ji Change-Id: I0073b34edacdb0fe69a6a0517b9be7e782afa572 --- bcmdhd.100.10.315.x/Makefile | 93 +- bcmdhd.100.10.315.x/bcmsdh_linux.c | 25 +- bcmdhd.100.10.315.x/bcmsdh_sdmmc.c | 19 +- bcmdhd.100.10.315.x/bcmstdlib_s.c | 2 +- bcmdhd.100.10.315.x/bcmutils.c | 4 +- bcmdhd.100.10.315.x/dbus.c | 2 +- bcmdhd.100.10.315.x/dhd.h | 21 +- bcmdhd.100.10.315.x/dhd_bus.h | 3 + bcmdhd.100.10.315.x/dhd_ccode.c | 234 ++ bcmdhd.100.10.315.x/dhd_common.c | 23 +- bcmdhd.100.10.315.x/dhd_config.c | 958 ++++-- bcmdhd.100.10.315.x/dhd_config.h | 43 +- bcmdhd.100.10.315.x/dhd_csi.c | 220 ++ bcmdhd.100.10.315.x/dhd_csi.h | 77 + bcmdhd.100.10.315.x/dhd_custom_gpio.c | 2 +- bcmdhd.100.10.315.x/dhd_gpio.c | 46 +- bcmdhd.100.10.315.x/dhd_linux.c | 256 +- bcmdhd.100.10.315.x/dhd_linux.h | 8 +- bcmdhd.100.10.315.x/dhd_linux_exportfs.c | 39 +- bcmdhd.100.10.315.x/dhd_linux_pktdump.c | 230 +- bcmdhd.100.10.315.x/dhd_linux_platdev.c | 12 +- bcmdhd.100.10.315.x/dhd_msgbuf.c | 8 +- bcmdhd.100.10.315.x/dhd_pcie.c | 5 +- bcmdhd.100.10.315.x/dhd_pcie_linux.c | 14 +- bcmdhd.100.10.315.x/dhd_pno.c | 2 +- bcmdhd.100.10.315.x/dhd_sdio.c | 142 +- bcmdhd.100.10.315.x/dhd_static_buf.c | 1049 ++++--- bcmdhd.100.10.315.x/dhd_wlfc.c | 39 + bcmdhd.100.10.315.x/dhd_wlfc.h | 7 + bcmdhd.100.10.315.x/include/bcmdevs.h | 20 +- bcmdhd.100.10.315.x/include/bcmevent.h | 7 + bcmdhd.100.10.315.x/include/dhdioctl.h | 6 + bcmdhd.100.10.315.x/include/epivers.h | 2 +- bcmdhd.100.10.315.x/include/linux_osl.h | 10 +- bcmdhd.100.10.315.x/include/wlioctl.h | 7 + bcmdhd.100.10.315.x/include/wlioctl_defs.h | 4 +- bcmdhd.100.10.315.x/linux_osl.c | 22 +- bcmdhd.100.10.315.x/siutils.c | 2 +- bcmdhd.100.10.315.x/wl_android.c | 98 +- bcmdhd.100.10.315.x/wl_android.h | 49 +- bcmdhd.100.10.315.x/wl_android_ext.c | 3193 +++++++++++++++----- bcmdhd.100.10.315.x/wl_cfg80211.c | 968 +++++- bcmdhd.100.10.315.x/wl_cfg80211.h | 29 +- bcmdhd.100.10.315.x/wl_cfgp2p.c | 10 +- bcmdhd.100.10.315.x/wl_cfgp2p.h | 65 +- bcmdhd.100.10.315.x/wl_cfgscan.c | 7 +- bcmdhd.100.10.315.x/wl_cfgvendor.c | 225 ++ bcmdhd.100.10.315.x/wl_escan.c | 335 +- bcmdhd.100.10.315.x/wl_escan.h | 33 +- bcmdhd.100.10.315.x/wl_event.c | 10 +- bcmdhd.100.10.315.x/wl_iw.c | 127 +- bcmdhd.100.10.315.x/wl_iw.h | 6 +- bcmdhd.100.10.315.x/wldev_common.c | 16 +- 53 files changed, 6614 insertions(+), 2220 deletions(-) create mode 100644 bcmdhd.100.10.315.x/dhd_ccode.c create mode 100644 bcmdhd.100.10.315.x/dhd_csi.c create mode 100644 bcmdhd.100.10.315.x/dhd_csi.h diff --git a/bcmdhd.100.10.315.x/Makefile b/bcmdhd.100.10.315.x/Makefile index 88d5475..8461a5b 100644 --- a/bcmdhd.100.10.315.x/Makefile +++ b/bcmdhd.100.10.315.x/Makefile @@ -9,7 +9,11 @@ endif ifeq ($(CONFIG_BCMDHD_SDIO),y) MODULE_NAME := dhd else +ifeq ($(CONFIG_BCMDHD_USB),y) MODULE_NAME := bcmdhd +else +MODULE_NAME := dhdpci +endif endif #CONFIG_BCMDHD := m #CONFIG_BCMDHD_SDIO := y @@ -34,9 +38,9 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \ -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT -DSUPPORT_PM2_ONLY \ -DKEEP_ALIVE -DPKT_FILTER_SUPPORT -DDHDTCPACK_SUPPRESS \ -DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT \ - -DMULTIPLE_SUPPLICANT -DTSQ_MULTIPLIER -DMFP \ + -DMULTIPLE_SUPPLICANT -DTSQ_MULTIPLIER -DMFP -DDHD_8021X_DUMP \ -DPOWERUP_MAX_RETRY=0 -DIFACE_HANG_FORCE_DEV_CLOSE -DWAIT_DEQUEUE \ - -DWL_EXT_IAPSTA -DWL_ESCAN \ + -DWL_EXT_IAPSTA -DWL_ESCAN -DCCODE_LIST \ -DENABLE_INSMOD_NO_FW_LOAD \ -I$(src) -I$(src)/include @@ -46,15 +50,39 @@ DHDOFILES = aiutils.o siutils.o sbutils.o bcmutils.o bcmwifi_channels.o \ bcmevent.o hndpmu.o linux_osl.o wldev_common.o wl_android.o \ dhd_debug_linux.o dhd_debug.o dhd_mschdbg.o dhd_dbg_ring.o \ hnd_pktq.o hnd_pktpool.o bcmxtlv.o linux_pkt.o bcmstdlib_s.o frag.o \ - dhd_linux_exportfs.o dhd_linux_pktdump.o \ - dhd_config.o wl_event.o wl_android_ext.o wl_escan.o + dhd_linux_exportfs.o dhd_linux_pktdump.o \ + dhd_config.o dhd_ccode.o wl_event.o wl_android_ext.o wl_escan.o + +ifneq ($(CONFIG_WIRELESS_EXT),) + DHDOFILES += wl_iw.o + DHDCFLAGS += -DSOFTAP -DWL_WIRELESS_EXT -DUSE_IW +endif +ifneq ($(CONFIG_CFG80211),) + DHDOFILES += wl_cfg80211.o wl_cfgscan.o wl_cfgp2p.o + DHDOFILES += wl_linux_mon.o wl_cfg_btcoex.o wl_cfgvendor.o + DHDOFILES += dhd_cfg80211.o + DHDCFLAGS += -DWL_CFG80211 -DWLP2P -DWL_CFG80211_STA_EVENT + DHDCFLAGS += -DWL_IFACE_COMB_NUM_CHANNELS + DHDCFLAGS += -DCUSTOM_PNO_EVENT_LOCK_xTIME=10 + DHDCFLAGS += -DWL_SUPPORT_AUTO_CHANNEL + DHDCFLAGS += -DWL_SUPPORT_BACKPORTED_KPATCHES + DHDCFLAGS += -DESCAN_RESULT_PATCH -DESCAN_BUF_OVERFLOW_MGMT + 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 += -DDHD_USE_SCAN_WAKELOCK + DHDCFLAGS += -DWL_STATIC_IF +# DHDCFLAGS += -DWL_SAE +endif #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 \ - -DBCMSDIO_RXLIM_POST + -DDHDENABLE_TAILPAD -DSUPPORT_P2P_GO_PS \ + -DBCMSDIO_RXLIM_POST -DCONSOLE_DPC ifeq ($(CONFIG_BCMDHD_OOB),y) DHDCFLAGS += -DOOB_INTR_ONLY -DCUSTOMER_OOB -DHW_OOB ifeq ($(CONFIG_BCMDHD_DISABLE_WOWLAN),y) @@ -73,9 +101,19 @@ 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 DHDCFLAGS += -DDHD_PKTID_AUDIT_ENABLED +ifeq ($(CONFIG_BCMDHD_OOB),y) + DHDCFLAGS += -DCUSTOMER_OOB -DBCMPCIE_OOB_HOST_WAKE +endif ifneq ($(CONFIG_PCI_MSI),) - DHDCFLAGS += -DDHD_USE_MSI + DHDCFLAGS += -DDHD_MSI_SUPPORT endif +DHDCFLAGS += -DDHD_LB_TXP_DEFAULT_ENAB +DHDCFLAGS += -DSET_RPS_CPUS -DSET_XPS_CPUS +DHDCFLAGS += -DCUSTOM_TCPACK_SUPP_RATIO=15 +DHDCFLAGS += -DCUSTOM_TCPACK_DELAY_TIME=10 +DHDCFLAGS += -DDHDTCPACK_SUPPRESS +DHDCFLAGS += -DDHD_DISABLE_ASPM + DHDOFILES += dhd_pcie.o dhd_pcie_linux.o pcie_core.o dhd_flowring.o \ dhd_msgbuf.o dhd_linux_lb.o endif @@ -99,7 +137,7 @@ ifneq ($(CONFIG_BCMDHD_USB),) DHDCFLAGS += -DPROP_TXSTATUS endif ifneq ($(CONFIG_BCMDHD_SDIO),) - DHDCFLAGS += -DPROP_TXSTATUS + DHDCFLAGS += -DPROP_TXSTATUS -DPROPTX_MAXCOUNT endif ifneq ($(CONFIG_CFG80211),) DHDCFLAGS += -DPROP_TXSTATUS_VSDB @@ -145,13 +183,19 @@ ifneq ($(CONFIG_BCMDHD_PCIE),) endif DHDCFLAGS += -DDHD_UPDATE_INTF_MAC DHDCFLAGS :=$(filter-out -DDHD_FW_COREDUMP,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DSET_RANDOM_MAC_SOFTAP,$(DHDCFLAGS)) + DHDCFLAGS :=$(filter-out -DWL_STATIC_IF,$(DHDCFLAGS)) endif ifeq ($(CONFIG_WL_EASYMESH),y) DHDCFLAGS :=$(filter-out -DDHD_FW_COREDUMP,$(DHDCFLAGS)) DHDCFLAGS :=$(filter-out -DDHD_LOG_DUMP,$(DHDCFLAGS)) -DHDCFLAGS += -DWLEASYMESH -DWL_STATIC_IF -DWLDWDS -DFOURADDR_AUTO_BRG + DHDCFLAGS += -DWLEASYMESH -DWL_STATIC_IF -DWLDWDS -DFOURADDR_AUTO_BRG +endif + +#CSI_SUPPORT +ifneq ($(CONFIG_CSI_SUPPORT),) + DHDCFLAGS += -DCSI_SUPPORT + DHDOFILES += dhd_csi.o endif obj-$(CONFIG_BCMDHD) += $(MODULE_NAME).o @@ -165,6 +209,13 @@ else DHDCFLAGS += -DCUSTOMER_HW -DDHD_OF_SUPPORT endif DHDCFLAGS += -DCUSTOMER_HW_AMLOGIC + +# for config custom MAC +# DHDCFLAGS += -DGET_CUSTOM_MAC_ENABLE -DCUSTOM_MULTI_MAC +# if also need config AP MAC +# DHDCFLAGS += -DCUSTOM_AP_MAC +# + # DHDCFLAGS += -DBCMWAPI_WPI -DBCMWAPI_WAI endif @@ -175,30 +226,10 @@ endif ifeq ($(CONFIG_DHD_USE_STATIC_BUF),y) # obj-m += dhd_static_buf.o DHDCFLAGS += -DSTATIC_WL_PRIV_STRUCT -DENHANCED_STATIC_BUF - DHDCFLAGS += -DDHD_USE_STATIC_MEMDUMP -DCONFIG_DHD_USE_STATIC_BUF + DHDCFLAGS += -DCONFIG_DHD_USE_STATIC_BUF + DHDCFLAGS += -DDHD_USE_STATIC_MEMDUMP endif -ifneq ($(CONFIG_WIRELESS_EXT),) - DHDOFILES += wl_iw.o - DHDCFLAGS += -DSOFTAP -DWL_WIRELESS_EXT -DUSE_IW -endif -ifneq ($(CONFIG_CFG80211),) - DHDOFILES += wl_cfg80211.o wl_cfgscan.o wl_cfgp2p.o - DHDOFILES += wl_linux_mon.o wl_cfg_btcoex.o wl_cfgvendor.o - DHDOFILES += dhd_cfg80211.o - DHDCFLAGS += -DWL_CFG80211 -DWLP2P -DWL_CFG80211_STA_EVENT - DHDCFLAGS += -DWL_IFACE_COMB_NUM_CHANNELS - DHDCFLAGS += -DCUSTOM_PNO_EVENT_LOCK_xTIME=10 - DHDCFLAGS += -DWL_SUPPORT_AUTO_CHANNEL - DHDCFLAGS += -DWL_SUPPORT_BACKPORTED_KPATCHES - DHDCFLAGS += -DESCAN_RESULT_PATCH -DESCAN_BUF_OVERFLOW_MGMT - 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 += -DDHD_USE_SCAN_WAKELOCK - DHDCFLAGS += -DWL_STATIC_IF -endif EXTRA_CFLAGS = $(DHDCFLAGS) ifeq ($(CONFIG_BCMDHD),m) EXTRA_LDFLAGS += --strip-debug diff --git a/bcmdhd.100.10.315.x/bcmsdh_linux.c b/bcmdhd.100.10.315.x/bcmsdh_linux.c index ed61189..54b0543 100644 --- a/bcmdhd.100.10.315.x/bcmsdh_linux.c +++ b/bcmdhd.100.10.315.x/bcmsdh_linux.c @@ -81,6 +81,7 @@ typedef struct bcmsdh_os_info { } bcmsdh_os_info_t; /* debugging macros */ +#define SDLX_ERR(x) printf x #define SDLX_MSG(x) printf x /** @@ -143,12 +144,12 @@ void* bcmsdh_probe(osl_t *osh, void *dev, void *sdioh, void *adapter_info, uint bcmsdh = bcmsdh_attach(osh, sdioh, ®s); if (bcmsdh == NULL) { - SDLX_MSG(("%s: bcmsdh_attach failed\n", __FUNCTION__)); + SDLX_ERR(("%s: bcmsdh_attach failed\n", __FUNCTION__)); goto err; } bcmsdh_osinfo = MALLOC(osh, sizeof(bcmsdh_os_info_t)); if (bcmsdh_osinfo == NULL) { - SDLX_MSG(("%s: failed to allocate bcmsdh_os_info_t\n", __FUNCTION__)); + SDLX_ERR(("%s: failed to allocate bcmsdh_os_info_t\n", __FUNCTION__)); goto err; } bzero((char *)bcmsdh_osinfo, sizeof(bcmsdh_os_info_t)); @@ -168,7 +169,7 @@ void* bcmsdh_probe(osl_t *osh, void *dev, void *sdioh, void *adapter_info, uint bcmsdh_osinfo->oob_irq_num = wifi_platform_get_irq_number(adapter_info, &bcmsdh_osinfo->oob_irq_flags); if (bcmsdh_osinfo->oob_irq_num < 0) { - SDLX_MSG(("%s: Host OOB irq is not defined\n", __FUNCTION__)); + SDLX_ERR(("%s: Host OOB irq is not defined\n", __FUNCTION__)); goto err; } #endif /* defined(BCMLXSDMMC) */ @@ -179,7 +180,7 @@ void* bcmsdh_probe(osl_t *osh, void *dev, void *sdioh, void *adapter_info, uint bcmsdh_osinfo->context = drvinfo.probe((vendevid >> 16), (vendevid & 0xFFFF), bus_num, slot_num, 0, bus_type, (void *)regs, osh, bcmsdh); if (bcmsdh_osinfo->context == NULL) { - SDLX_MSG(("%s: device attach failed\n", __FUNCTION__)); + SDLX_ERR(("%s: device attach failed\n", __FUNCTION__)); goto err; } @@ -282,7 +283,7 @@ bcmsdh_register(bcmsdh_driver_t *driver) SDLX_MSG(("%s: register client driver\n", __FUNCTION__)); error = bcmsdh_register_client_driver(); if (error) - SDLX_MSG(("%s: failed %d\n", __FUNCTION__, error)); + SDLX_ERR(("%s: failed %d\n", __FUNCTION__, error)); return error; } @@ -362,15 +363,15 @@ int bcmsdh_oob_intr_register(bcmsdh_info_t *bcmsdh, bcmsdh_cb_fn_t oob_irq_handl bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt; if (bcmsdh_osinfo->oob_irq_registered) { - SDLX_MSG(("%s: irq is already registered\n", __FUNCTION__)); + SDLX_ERR(("%s: irq is already registered\n", __FUNCTION__)); return -EBUSY; } #ifdef HW_OOB - printf("%s: HW_OOB irq=%d flags=0x%X\n", __FUNCTION__, - (int)bcmsdh_osinfo->oob_irq_num, (int)bcmsdh_osinfo->oob_irq_flags); + SDLX_MSG(("%s: HW_OOB irq=%d flags=0x%X\n", __FUNCTION__, + (int)bcmsdh_osinfo->oob_irq_num, (int)bcmsdh_osinfo->oob_irq_flags)); #else - printf("%s: SW_OOB irq=%d flags=0x%X\n", __FUNCTION__, - (int)bcmsdh_osinfo->oob_irq_num, (int)bcmsdh_osinfo->oob_irq_flags); + SDLX_MSG(("%s: SW_OOB irq=%d flags=0x%X\n", __FUNCTION__, + (int)bcmsdh_osinfo->oob_irq_num, (int)bcmsdh_osinfo->oob_irq_flags)); #endif bcmsdh_osinfo->oob_irq_handler = oob_irq_handler; bcmsdh_osinfo->oob_irq_handler_context = oob_irq_handler_context; @@ -379,7 +380,7 @@ int bcmsdh_oob_intr_register(bcmsdh_info_t *bcmsdh, bcmsdh_cb_fn_t oob_irq_handl err = request_irq(bcmsdh_osinfo->oob_irq_num, wlan_oob_irq, bcmsdh_osinfo->oob_irq_flags, "bcmsdh_sdmmc", bcmsdh); if (err) { - SDLX_MSG(("%s: request_irq failed with %d\n", __FUNCTION__, err)); + SDLX_ERR(("%s: request_irq failed with %d\n", __FUNCTION__, err)); bcmsdh_osinfo->oob_irq_enabled = FALSE; bcmsdh_osinfo->oob_irq_registered = FALSE; return err; @@ -394,7 +395,7 @@ int bcmsdh_oob_intr_register(bcmsdh_info_t *bcmsdh, bcmsdh_cb_fn_t oob_irq_handl #endif /* CONFIG_ARCH_RHEA || CONFIG_ARCH_CAPRI */ err = enable_irq_wake(bcmsdh_osinfo->oob_irq_num); if (err) - SDLX_MSG(("%s: enable_irq_wake failed with %d\n", __FUNCTION__, err)); + SDLX_ERR(("%s: enable_irq_wake failed with %d\n", __FUNCTION__, err)); else bcmsdh_osinfo->oob_irq_wake_enabled = TRUE; #if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) diff --git a/bcmdhd.100.10.315.x/bcmsdh_sdmmc.c b/bcmdhd.100.10.315.x/bcmsdh_sdmmc.c index 89b2c9f..aa9a36b 100644 --- a/bcmdhd.100.10.315.x/bcmsdh_sdmmc.c +++ b/bcmdhd.100.10.315.x/bcmsdh_sdmmc.c @@ -1180,6 +1180,9 @@ sdioh_request_packet_chain(sdioh_info_t *sd, uint fix_inc, uint write, uint func * a restriction on max tx/glom count (based on host->max_segs). */ if (sg_count >= ARRAYSIZE(sd->sg_list)) { + sd_err(("%s: sg list entries(%u) exceed limit(%zu)," + " sd blk_size=%u\n", + __FUNCTION__, sg_count, (size_t)ARRAYSIZE(sd->sg_list), blk_size)); return (SDIOH_API_RC_FAIL); } pdata += pkt_offset; @@ -1274,21 +1277,13 @@ txglomfail: pkt_len += blk_size - (pkt_len % blk_size); if ((write) && (!fifo)) - err_ret = sdio_memcpy_toio( - sd->func[func], - addr, buf, pkt_len); + err_ret = sdio_memcpy_toio(sd->func[func], addr, buf, pkt_len); else if (write) - err_ret = sdio_memcpy_toio( - sd->func[func], - addr, buf, pkt_len); + err_ret = sdio_memcpy_toio(sd->func[func], addr, buf, pkt_len); else if (fifo) - err_ret = sdio_readsb( - sd->func[func], - buf, addr, pkt_len); + err_ret = sdio_readsb(sd->func[func], buf, addr, pkt_len); else - err_ret = sdio_memcpy_fromio( - sd->func[func], - buf, addr, pkt_len); + err_ret = sdio_memcpy_fromio(sd->func[func], buf, addr, pkt_len); if (err_ret) sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=%d\n", diff --git a/bcmdhd.100.10.315.x/bcmstdlib_s.c b/bcmdhd.100.10.315.x/bcmstdlib_s.c index 42e74c1..05c3e48 100644 --- a/bcmdhd.100.10.315.x/bcmstdlib_s.c +++ b/bcmdhd.100.10.315.x/bcmstdlib_s.c @@ -185,7 +185,7 @@ exit: } #endif /* !__STDC_WANT_SECURE_LIB__ && !(__STDC_LIB_EXT1__ && __STDC_WANT_LIB_EXT1__) */ -#if !defined(FREEBSD) && !defined(BCM_USE_PLATFORM_STRLCPY) +#if 0 /** * strlcpy - Copy a %NUL terminated string into a sized buffer * @dest: Where to copy the string to diff --git a/bcmdhd.100.10.315.x/bcmutils.c b/bcmdhd.100.10.315.x/bcmutils.c index 3cdad7b..2e9253a 100644 --- a/bcmdhd.100.10.315.x/bcmutils.c +++ b/bcmdhd.100.10.315.x/bcmutils.c @@ -3179,7 +3179,7 @@ bcm_format_field(const bcm_bit_desc_ex_t *bd, uint32 flags, char* buf, int len) if ((flags & mask) == bit) { if (len > (int)strlen(name)) { slen = (int)strlen(name); - strncpy(buf, name, (size_t)slen+1); + strncpy(buf, name, (size_t)len); } break; } @@ -3222,7 +3222,7 @@ bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len) if (len <= slen) break; /* copy NULL char but don't count it */ - strncpy(p, name, (size_t)nlen + 1); + strncpy(p, name, (size_t)len); p += nlen; /* copy btwn flag space and NULL char */ if (flags != 0) diff --git a/bcmdhd.100.10.315.x/dbus.c b/bcmdhd.100.10.315.x/dbus.c index baacbfc..a62642e 100644 --- a/bcmdhd.100.10.315.x/dbus.c +++ b/bcmdhd.100.10.315.x/dbus.c @@ -2703,7 +2703,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_conf_set_path_params(bus->dhd, NULL, NULL, bus->fw_path, bus->nv_path); + dhd_conf_set_path_params(bus->dhd, bus->fw_path, bus->nv_path); } diff --git a/bcmdhd.100.10.315.x/dhd.h b/bcmdhd.100.10.315.x/dhd.h index 97b0598..f4a7f52 100644 --- a/bcmdhd.100.10.315.x/dhd.h +++ b/bcmdhd.100.10.315.x/dhd.h @@ -53,7 +53,9 @@ #if defined(CONFIG_HAS_WAKELOCK) #include #endif /* defined CONFIG_HAS_WAKELOCK */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) +#include +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) #include #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) */ /* The kernel threading is sdio-specific */ @@ -1387,6 +1389,10 @@ typedef struct dhd_pub { void *pktcnts; #endif /* DHD_PKTDUMP_ROAM */ bool disable_dtim_in_suspend; /* Disable set bcn_li_dtim in suspend */ +#ifdef CSI_SUPPORT + struct list_head csi_list; + int csi_count; +#endif /* CSI_SUPPORT */ char *clm_path; /* module_param: path to clm vars file */ char *conf_path; /* module_param: path to config vars file */ struct dhd_conf *conf; /* Bus module handle */ @@ -2358,6 +2364,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 */ @@ -2925,6 +2932,12 @@ extern void *dhd_pub_shim(dhd_pub_t *dhd_pub); void* dhd_get_fwdump_buf(dhd_pub_t *dhd_pub, uint32 length); #endif /* DHD_FW_COREDUMP */ +#if defined(SET_XPS_CPUS) +int dhd_xps_cpus_enable(struct net_device *net, int enable); +int custom_xps_map_set(struct net_device *net, char *buf, size_t len); +void custom_xps_map_clear(struct net_device *net); +#endif + #if defined(SET_RPS_CPUS) int dhd_rps_cpus_enable(struct net_device *net, int enable); int custom_rps_map_set(struct netdev_rx_queue *queue, char *buf, size_t len); @@ -2937,9 +2950,9 @@ void custom_rps_map_clear(struct netdev_rx_queue *queue); #define RPS_CPUS_MASK_IBSS "10" #define RPS_CPUS_WLAN_CORE_ID 4 #else -#define RPS_CPUS_MASK "6" -#define RPS_CPUS_MASK_P2P "6" -#define RPS_CPUS_MASK_IBSS "6" +#define RPS_CPUS_MASK "f" +#define RPS_CPUS_MASK_P2P "f" +#define RPS_CPUS_MASK_IBSS "f" #endif /* CONFIG_MACH_UNIVERSAL7420 || CONFIG_SOC_EXYNOS8890 */ #endif // endif diff --git a/bcmdhd.100.10.315.x/dhd_bus.h b/bcmdhd.100.10.315.x/dhd_bus.h index 72e9d91..d020783 100644 --- a/bcmdhd.100.10.315.x/dhd_bus.h +++ b/bcmdhd.100.10.315.x/dhd_bus.h @@ -96,6 +96,9 @@ extern bool dhd_bus_dev_pm_enabled(dhd_pub_t *dhdpub); /* Device console input function */ extern int dhd_bus_console_in(dhd_pub_t *dhd, uchar *msg, uint msglen); +#ifdef CONSOLE_DPC +extern int dhd_bus_txcons(dhd_pub_t *dhd, uchar *msg, uint msglen); +#endif /* Deferred processing for the bus, return TRUE requests reschedule */ extern bool dhd_bus_dpc(struct dhd_bus *bus); diff --git a/bcmdhd.100.10.315.x/dhd_ccode.c b/bcmdhd.100.10.315.x/dhd_ccode.c new file mode 100644 index 0000000..763e92d --- /dev/null +++ b/bcmdhd.100.10.315.x/dhd_ccode.c @@ -0,0 +1,234 @@ + +#ifdef CCODE_LIST +#ifdef CONFIG_COMPAT +#include +#endif /* COMFIG_COMPAT */ +#include +#include + +#ifdef BCMSDIO +#define CCODE_43438 +#define CCODE_43455C0 +#define CCODE_43456C5 +#endif +#if defined(BCMSDIO) || defined(BCMPCIE) +#define CCODE_4356A2 +#define CCODE_4359C0 +#endif +#ifdef BCMDBUS +#define CCODE_4358U +#endif + +#ifdef BCMSDIO +#ifdef CCODE_43438 +const char ccode_43438[] = "RU/13"; +#else +const char ccode_43438 = ""; +#endif + +#ifdef CCODE_43455C0 +const char ccode_43455c0[] = \ +"AE/6 AG/2 AI/1 AL/2 AS/12 AT/4 AU/6 AW/2 AZ/2 "\ +"BA/2 BD/1 BE/4 BG/4 BH/4 BM/12 BN/4 BR/2 BS/2 BY/3 "\ +"CA/2 CA/31 CH/4 CN/38 CO/17 CR/17 CY/4 CZ/4 "\ +"DE/3 DE/7 DK/4 "\ +"EC/21 EE/4 EG/13 ES/4 ET/2 "\ +"FI/4 FR/5 "\ +"GB/1 GB/6 GD/2 GF/2 GP/2 GR/4 GT/1 GU/30 "\ +"HK/2 HR/4 HU/4 "\ +"ID/1 IE/5 IL/14 IN/3 IS/4 IT/4 "\ +"JO/3 JP/45 JP/58 "\ +"KH/2 KR/45 KR/48 KR/49 KR/70 KR/71 KR/96 KW/5 KY/3 "\ +"LA/2 LB/5 LI/4 LK/1 LS/2 LT/4 LU/3 LV/4 "\ +"MA/2 MC/1 MD/2 ME/2 MK/2 MN/1 MQ/2 MR/2 MT/4 MU/2 MV/3 MW/1 MX/44 MY/3 "\ +"NI/2 NL/4 NO/4 NZ/4 "\ +"OM/4 "\ +"PA/17 PE/20 PH/5 PL/4 PR/38 PT/4 PY/2 "\ +"Q2/993 "\ +"RE/2 RO/4 RS/2 RU/13 "\ +"SE/4 SI/4 SK/4 SV/25 "\ +"TH/5 TN/1 TR/7 TT/3 TW/1 "\ +"UA/8 US/988 "\ +"VA/2 VE/3 VG/2 VN/4 "\ +"XZ/11 "\ +"YT/2 "\ +"ZA/6"; +#else +const char ccode_43455c0[] = ""; +#endif + +#ifdef CCODE_43456C5 +const char ccode_43456c5[] = \ +"AE/6 AG/2 AI/1 AL/2 AS/12 AT/4 AU/6 AW/2 AZ/2 "\ +"BA/2 BD/1 BE/4 BG/4 BH/4 BM/12 BN/4 BR/4 BS/2 BY/3 "\ +"CA/2 CH/4 CN/38 CO/17 CR/17 CY/4 CZ/4 "\ +"DE/7 DK/4 "\ +"EC/21 EE/4 EG/13 ES/4 ET/2 "\ +"FI/4 FR/5 "\ +"GB/6 GD/2 GF/2 GP/2 GR/4 GT/1 GU/30 "\ +"HK/2 HR/4 HU/4 "\ +"ID/1 IE/5 IL/14 IN/3 IS/4 IT/4 "\ +"JO/3 JP/58 "\ +"KH/2 KR/96 KW/5 KY/3 "\ +"LA/2 LB/5 LI/4 LK/1 LS/2 LT/4 LU/3 LV/4 "\ +"MA/2 MC/1 MD/2 ME/2 MK/2 MN/1 MQ/2 MR/2 MT/4 MU/2 MV/3 MW/1 MX/44 MY/3 "\ +"NI/2 NL/4 NO/4 NZ/4 "\ +"OM/4 "\ +"PA/17 PE/20 PH/5 PL/4 PR/38 PT/4 PY/2 "\ +"Q2/993 "\ +"RE/2 RO/4 RS/2 RU/13 "\ +"SE/4 SI/4 SK/4 SV/25 "\ +"TH/5 TN/1 TR/7 TT/3 TW/65 "\ +"UA/8 US/988 "\ +"VA/2 VE/3 VG/2 VN/4 "\ +"XZ/11 "\ +"YT/2 "\ +"ZA/6"; +#else +const char ccode_43456c5[] = ""; +#endif +#endif + +#ifdef CCODE_4356A2 +const char ccode_4356a2[] = \ +"AE/6 AG/2 AI/1 AL/2 AN/2 AR/21 AS/12 AT/4 AU/6 AW/2 AZ/2 "\ +"BA/2 BD/2 BE/4 BG/4 BH/4 BM/12 BN/4 BR/4 BS/2 BY/3 "\ +"CA/31 CH/4 CN/38 CO/17 CR/17 CY/4 CZ/4 "\ +"DE/7 DK/4 DZ/1 "\ +"EC/21 EE/4 ES/4 ET/2 "\ +"FI/4 FR/5 "\ +"GB/6 GD/2 GF/2 GP/2 GR/4 GT/1 GU/12 "\ +"HK/2 HR/4 HU/4 "\ +"ID/13 IE/5 IL/7 IN/28 IS/4 IT/4 "\ +"JO/3 JP/58 "\ +"KH/2 KR/57 KW/5 KY/3 "\ +"LA/2 LB/5 LI/4 LK/1 LS/2 LT/4 LU/3 LV/4 "\ +"MA/2 MC/1 MD/2 ME/2 MK/2 MN/1 MO/2 MR/2 MT/4 MQ/2 MU/2 MV/3 MW/1 MX/20 MY/16 "\ +"NI/2 NL/4 NO/4 NP/3 NZ/4 "\ +"OM/4 "\ +"PA/17 PE/20 PG/2 PH/5 PL/4 PR/20 PT/4 PY/2 "\ +"RE/2 RO/4 RS/2 RU/986 "\ +"SE/4 SG/4 SG/19 SI/4 SK/4 SN/2 SV/19 "\ +"TH/9 TN/1 TR/7 TT/3 TW/1 "\ +"UA/8 UG/2 US/1 UY/1 "\ +"VA/2 UA/16 VE/3 VG/2 VI/13 VN/4 "\ +"XZ/11 "\ +"YT/2 "\ +"ZM/2 "\ +"E0/32"; +#else +const char ccode_4356a2[] = ""; +#endif + +#ifdef CCODE_4359C0 +const char ccode_4359c0[] = \ +"AD/1 AE/6 AG/2 AI/1 AL/3 AS/12 AT/21 AU/6 AW/2 AZ/8 "\ +"BA/4 BD/1 BE/19 BG/18 BH/4 BM/12 BN/4 BR/2 BS/2 BY/3 "\ +"CN/38 CO/17 CR/17 CY/18 CZ/18 "\ +"DE/30 DK/19 "\ +"E0/32 EC/21 EE/18 EG/13 ES/21 ET/2 "\ +"FI/19 FR/21 "\ +"GB/996 GD/2 GE/1 GF/2 GP/2 GR/18 GT/1 GU/30 "\ +"HK/2 HR/18 HU/18 "\ +"ID/1 IE/21 IL/14 IN/3 IS/17 IT/20 "\ +"JO/3 JP/967 "\ +"KH/2 KR/70 KW/5 KY/3 "\ +"LA/2 LB/5 LI/17 LI/4 LK/1 LS/2 LT/18 LU/18 LV/18 "\ +"MA/2 MC/2 MD/3 ME/5 MK/4 MN/1 MQ/2 MR/2 MT/18 MU/2 MV/3 MW/1 MX/44 MY/3 "\ +"NI/2 NL/19 NO/18 NZ/4 "\ +"OM/4 "\ +"PA/17 PE/20 PH/5 PL/18 PR/38 PT/20 PY/2 "\ +"Q1/947 Q2/993 "\ +"RE/2 RO/18 RS/4 RU/986 "\ +"SE/19 SI/18 SK/18 SM/1 SV/25 "\ +"TH/5 TN/1 TR/18 TT/3 TW/1 "\ +"UA/16 US/988 "\ +"VA/3 VE/3 VG/2 VN/4 "\ +"XZ/11 "\ +"YT/2 "\ +"ZA/6"; +#else +const char ccode_4359c0[] = ""; +#endif + +#ifdef CCODE_4358U +const char ccode_4358u[] = \ +"BE/4 BR/4 CA/2 CH/4 CN/38 CY/4 DE/7 DK/4 ES/4 "\ +"FI/4 FR/5 GB/6 GR/4 HK/2 HU/4 IE/5 IL/7 IS/4 "\ +"IT/4 JP/72 KE/0 MY/3 NL/4 PT/4 SA/5 SE/4 SG/0 "\ +"SZ/0 TH/5 TR/7 TW/230 US/0 VN/4"; +#else +const char ccode_4358u[] = ""; +#endif + +typedef struct ccode_list_map_t { + uint chip; + uint chiprev; + const char *ccode_list; + const char *ccode_ww; +} ccode_list_map_t; + +extern const char ccode_43438[]; +extern const char ccode_43455c0[]; +extern const char ccode_43456c5[]; +extern const char ccode_4356a2[]; +extern const char ccode_4359c0[]; +extern const char ccode_4358u[]; + +const ccode_list_map_t ccode_list_map[] = { + /* ChipID Chiprev ccode */ +#ifdef BCMSDIO + {BCM43430_CHIP_ID, 0, ccode_43438, ""}, + {BCM43430_CHIP_ID, 1, ccode_43438, ""}, + {BCM4345_CHIP_ID, 6, ccode_43455c0, "XZ/11"}, + {BCM43454_CHIP_ID, 6, ccode_43455c0, "XZ/11"}, + {BCM4345_CHIP_ID, 9, ccode_43456c5, "XZ/11"}, + {BCM43454_CHIP_ID, 9, ccode_43456c5, "XZ/11"}, + {BCM4354_CHIP_ID, 2, ccode_4356a2, "XZ/11"}, + {BCM4356_CHIP_ID, 2, ccode_4356a2, "XZ/11"}, + {BCM4371_CHIP_ID, 2, ccode_4356a2, "XZ/11"}, + {BCM4359_CHIP_ID, 9, ccode_4359c0, "XZ/11"}, +#endif +#ifdef BCMPCIE + {BCM4354_CHIP_ID, 2, ccode_4356a2, "XZ/11"}, + {BCM4356_CHIP_ID, 2, ccode_4356a2, "XZ/11"}, + {BCM4359_CHIP_ID, 9, ccode_4359c0, "XZ/11"}, +#endif +#ifdef BCMDBUS + {BCM43569_CHIP_ID, 2, ccode_4358u, "XW/0"}, +#endif +}; + +int +dhd_ccode_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec) +{ + int bcmerror = -1, i; + uint chip = dhd->conf->chip, chiprev = dhd->conf->chiprev; + const char *ccode_list = NULL, *ccode_ww = NULL; + char *pch; + + for (i=0; ichip == chip && row->chiprev == chiprev) { + ccode_list = row->ccode_list; + ccode_ww = row->ccode_ww; + break; + } + } + + if (ccode_list) { + pch = strstr(ccode_list, cspec->ccode); + if (pch) { + cspec->rev = (int)simple_strtol(pch+strlen(cspec->ccode)+1, NULL, 0); + bcmerror = 0; + } + } + + if (bcmerror && ccode_ww && strlen(ccode_ww)>=4) { + memcpy(cspec->ccode, ccode_ww, 2); + cspec->rev = (int)simple_strtol(ccode_ww+3, NULL, 0); + } + + return bcmerror; +} +#endif diff --git a/bcmdhd.100.10.315.x/dhd_common.c b/bcmdhd.100.10.315.x/dhd_common.c index c5f62fb..813833d 100644 --- a/bcmdhd.100.10.315.x/dhd_common.c +++ b/bcmdhd.100.10.315.x/dhd_common.c @@ -113,7 +113,7 @@ #ifdef DHD_LOG_PRINT_RATE_LIMIT int log_print_threshold = 0; #endif /* DHD_LOG_PRINT_RATE_LIMIT */ -int dhd_msg_level = DHD_ERROR_VAL;// | DHD_FWLOG_VAL | DHD_EVENT_VAL +int dhd_msg_level = DHD_ERROR_VAL | DHD_FWLOG_VAL;// | DHD_EVENT_VAL /* For CUSTOMER_HW4 do not enable DHD_IOVAR_MEM_VAL by default */ // | DHD_PKT_MON_VAL; @@ -133,6 +133,10 @@ int dhd_msg_level = DHD_ERROR_VAL;// | DHD_FWLOG_VAL | DHD_EVENT_VAL #include #endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ +#ifdef CSI_SUPPORT +#include +#endif /* CSI_SUPPORT */ + #ifdef SOFTAP char fw_path2[MOD_PARAM_PATHLEN]; extern bool softap_enabled; @@ -1634,8 +1638,13 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch #if defined(DHD_DEBUG) case IOV_SVAL(IOV_CONS): - if (len > 0) + if (len > 0) { +#ifdef CONSOLE_DPC + bcmerror = dhd_bus_txcons(dhd_pub, arg, len - 1); +#else bcmerror = dhd_bus_console_in(dhd_pub, arg, len - 1); +#endif + } break; #endif /* DHD_DEBUG */ #endif /* !BCMDBUS */ @@ -3071,7 +3080,7 @@ wl_show_host_event(dhd_pub_t *dhd_pub, wl_event_msg_t *event, void *event_data, break; } default: - DHD_INFO(("MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d\n", + DHD_EVENT(("MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d\n", event_name, event_type, eabuf, (int)status, (int)reason, (int)auth_type)); break; @@ -3663,6 +3672,11 @@ wl_process_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, uint pktlen } break; #endif /* DHD_POST_EAPOL_M1_AFTER_ROAM_EVT */ +#if defined(CSI_SUPPORT) + case WLC_E_CSI: + dhd_csi_event_handler(dhd_pub, event, (void *)event_data); + break; +#endif /* CSI_SUPPORT */ case WLC_E_LINK: #ifdef PCIE_FULL_DONGLE if (dhd_update_interface_link_status(dhd_pub, (uint8)dhd_ifname2idx(dhd_pub->info, @@ -5068,6 +5082,8 @@ dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd, int *dtim_period, int *bcn_interval) } } + 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__, *bcn_interval, bcn_li_dtim, *dtim_period, CUSTOM_LISTEN_INTERVAL)); @@ -5120,7 +5136,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; diff --git a/bcmdhd.100.10.315.x/dhd_config.c b/bcmdhd.100.10.315.x/dhd_config.c index 3d33ea4..c308fd0 100644 --- a/bcmdhd.100.10.315.x/dhd_config.c +++ b/bcmdhd.100.10.315.x/dhd_config.c @@ -23,9 +23,10 @@ /* message levels */ #define CONFIG_ERROR_LEVEL (1 << 0) #define CONFIG_TRACE_LEVEL (1 << 1) -#define CONFIG_MSG_LEVEL (1 << 15) +#define CONFIG_MSG_LEVEL (1 << 0) uint config_msg_level = CONFIG_ERROR_LEVEL | CONFIG_MSG_LEVEL; +uint dump_msg_level = 0; #define CONFIG_MSG(x, args...) \ do { \ @@ -42,12 +43,12 @@ uint config_msg_level = CONFIG_ERROR_LEVEL | CONFIG_MSG_LEVEL; #define CONFIG_TRACE(x, args...) \ do { \ if (config_msg_level & CONFIG_TRACE_LEVEL) { \ - printk(KERN_ERR "[dhd] CONFIG-TRACE) %s : " x, __func__, ## args); \ + printk(KERN_INFO "[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 @@ -58,11 +59,9 @@ uint config_msg_level = CONFIG_ERROR_LEVEL | CONFIG_MSG_LEVEL; #define dtohchanspec(i) i #endif -#if defined(SUSPEND_EVENT) && defined(PROP_TXSTATUS) -#if defined(BCMSDIO) || defined(BCMDBUS) +#if defined(PROP_TXSTATUS) #include -#endif /* BCMSDIO || BCMDBUS */ -#endif /* SUSPEND_EVENT && PROP_TXSTATUS */ +#endif /* PROP_TXSTATUS */ #define MAX_EVENT_BUF_NUM 16 typedef struct eventmsg_buf { @@ -95,6 +94,7 @@ const cihp_name_map_t chip_name_map[] = { {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", ""}, @@ -133,6 +133,18 @@ const cihp_name_map_t chip_name_map[] = { #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) @@ -153,18 +165,6 @@ dhd_conf_free_mac_list(wl_mac_list_ctrl_t *mac_list) mac_list->count = 0; } -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; -} - #if defined(HW_OOB) || defined(FORCE_WOWLAN) void dhd_conf_set_hw_oob_intr(bcmsdh_info_t *sdh, struct si_pub *sih) @@ -185,73 +185,30 @@ dhd_conf_set_hw_oob_intr(bcmsdh_info_t *sdh, struct si_pub *sih) #endif #define SBSDIO_CIS_SIZE_LIMIT 0x200 -#define F0_BLOCK_SIZE 32 -int -dhd_conf_set_blksize(bcmsdh_info_t *sdh) -{ - int err = 0; - uint fn, numfn; - int32 blksize = 0, cur_blksize = 0; - uint8 cisd; - - numfn = bcmsdh_query_iofnum(sdh); - - for (fn = 0; fn <= numfn; fn++) { - if (!fn) - blksize = F0_BLOCK_SIZE; - else { - bcmsdh_cisaddr_read(sdh, fn, &cisd, 24); - blksize = cisd; - bcmsdh_cisaddr_read(sdh, fn, &cisd, 25); - blksize |= cisd << 8; - } -#ifdef CUSTOM_SDIO_F2_BLKSIZE - if (fn == 2 && blksize > CUSTOM_SDIO_F2_BLKSIZE) { - blksize = CUSTOM_SDIO_F2_BLKSIZE; - } -#endif - bcmsdh_iovar_op(sdh, "sd_blocksize", &fn, sizeof(int32), - &cur_blksize, sizeof(int32), FALSE); - if (cur_blksize != blksize) { - 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) { - CONFIG_ERROR("fail on get sd_blocksize"); - err = -1; - } - } - } - - return err; -} - -int -dhd_conf_get_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, si_t *sih, uint8 *mac) +void +dhd_conf_get_otp(dhd_pub_t *dhd, bcmsdh_info_t *sdh, si_t *sih) { int i, err = -1; - uint8 *ptr = 0; + uint8 *ptr = 0, *ptpl_code = NULL; unsigned char tpl_code, tpl_link='\0'; - uint8 header[3] = {0x80, 0x07, 0x19}; + uint8 mac_header[3] = {0x80, 0x07, 0x19}; uint8 *cis; if (!(cis = MALLOC(dhd->osh, SBSDIO_CIS_SIZE_LIMIT))) { 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("cis read err %d\n", err); MFREE(dhd->osh, cis, SBSDIO_CIS_SIZE_LIMIT); - return err; + return; } - err = -1; // reset err; ptr = cis; do { /* 0xff means we're done */ tpl_code = *ptr; + ptpl_code = ptr; ptr++; if (tpl_code == 0xff) break; @@ -266,35 +223,35 @@ dhd_conf_get_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, si_t *sih, uint8 *mac) if (tpl_link == 0xff) break; if (config_msg_level & CONFIG_TRACE_LEVEL) { - 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; iconf->otp_mac, ptr+1, 6); + } +#ifdef GET_OTP_MODULE_NAME + else if (tpl_code == 0x8e && *ptr == 0x41) { + int len = tpl_link - 1; + if (len <= sizeof(dhd->conf->module_name) - 1) { + strncpy(dhd->conf->module_name, ptr+1, len); + CONFIG_MSG("module_name=%s\n", dhd->conf->module_name); + } else { + CONFIG_ERROR("len is too long %d >= %d\n", + len, (int)sizeof(dhd->conf->module_name) - 1); + } + } +#endif ptr += tpl_link; } while (1); - if (tpl_code == 0x80 && tpl_link == 0x07 && *ptr == 0x19) { - /* Normal OTP */ - memcpy(mac, ptr+1, 6); - err = 0; - } else { + if (!memcmp(ðer_null, &dhd->conf->otp_mac, ETHER_ADDR_LEN)) { ptr = cis; /* Special OTP */ if (bcmsdh_reg_read(sdh, SI_ENUM_BASE(sih), 4) == 0x16044330) { for (i=0; iconf->otp_mac, ptr+3, 6); break; } ptr++; @@ -304,16 +261,13 @@ dhd_conf_get_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, si_t *sih, uint8 *mac) ASSERT(cis); MFREE(dhd->osh, cis, SBSDIO_CIS_SIZE_LIMIT); - - return err; } void -dhd_conf_set_fw_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, - si_t *sih, char *fw_path) +dhd_conf_set_fw_name_by_mac(dhd_pub_t *dhd, char *fw_path) { int i, j; - uint8 mac[6]={0}; + uint8 *mac = (uint8 *)&dhd->conf->otp_mac; int fw_num=0, mac_num=0; uint32 oui, nic; wl_mac_list_t *mac_list; @@ -326,10 +280,6 @@ dhd_conf_set_fw_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, if (!mac_list || !fw_num) return; - if (dhd_conf_get_mac(dhd, sdh, sih, mac)) { - CONFIG_ERROR("Can not read MAC address\n"); - return; - } oui = (mac[0] << 16) | (mac[1] << 8) | (mac[2]); nic = (mac[3] << 16) | (mac[4] << 8) | (mac[5]); @@ -390,11 +340,10 @@ dhd_conf_set_fw_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, } void -dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, - si_t *sih, char *nv_path) +dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, char *nv_path) { int i, j; - uint8 mac[6]={0}; + uint8 *mac = (uint8 *)&dhd->conf->otp_mac; int nv_num=0, mac_num=0; uint32 oui, nic; wl_mac_list_t *mac_list; @@ -406,10 +355,6 @@ dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, if (!mac_list || !nv_num) return; - if (dhd_conf_get_mac(dhd, sdh, sih, mac)) { - CONFIG_ERROR("Can not read MAC address\n"); - return; - } oui = (mac[0] << 16) | (mac[1] << 8) | (mac[2]); nic = (mac[3] << 16) | (mac[4] << 8) | (mac[5]); @@ -439,18 +384,37 @@ dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, #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("called\n"); - for (i=0; icspec[i]) { - CONFIG_TRACE("Free cspec %p\n", country_list->cspec[i]); - kfree(country_list->cspec[i]); - country_list->cspec[i] = NULL; - } + while (country) { + CONFIG_TRACE("Free cspec %s\n", country->cspec.country_abbrev); + conf->country_head = country->next; + kfree(country); + country = conf->country_head; + count++; + } + 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 @@ -475,7 +439,7 @@ dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path) } } #ifndef FW_PATH_AUTO_SELECT - return; + return DONT_CARE; #endif /* find out the last '/' */ @@ -610,10 +574,18 @@ dhd_conf_set_nv_name_by_chip(dhd_pub_t *dhd, char *nv_path, int ag_type) 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) && - strlen(row->module_name)) { - strcpy(name_ptr, "nvram_"); - strcat(name_ptr, row->module_name); + (row->ag_type == ag_type || row->ag_type == DONT_CARE)) { +#ifdef GET_OTP_MODULE_NAME + if (strlen(dhd->conf->module_name)) { + strcpy(name_ptr, "nvram_"); + strcat(name_ptr, dhd->conf->module_name); + } else +#endif + if (strlen(row->module_name)){ + strcpy(name_ptr, "nvram_"); + strcat(name_ptr, row->module_name); + } else + continue; #ifdef BCMUSBDEV_COMPOSITE strcat(name_ptr, "_cusb"); #endif @@ -698,8 +670,7 @@ dhd_conf_set_conf_name_by_chip(dhd_pub_t *dhd, char *conf_path) #endif void -dhd_conf_set_path_params(dhd_pub_t *dhd, void *sdh, void *sih, - char *fw_path, char *nv_path) +dhd_conf_set_path_params(dhd_pub_t *dhd, char *fw_path, char *nv_path) { int ag_type; @@ -722,8 +693,8 @@ dhd_conf_set_path_params(dhd_pub_t *dhd, void *sdh, void *sih, 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, (si_t *)sih, fw_path); - dhd_conf_set_nv_name_by_mac(dhd, (bcmsdh_info_t *)sdh, (si_t *)sih, nv_path); + dhd_conf_set_fw_name_by_mac(dhd, fw_path); + dhd_conf_set_nv_name_by_mac(dhd, nv_path); #endif CONFIG_MSG("Final fw_path=%s\n", fw_path); @@ -815,6 +786,196 @@ dhd_conf_get_iovar(dhd_pub_t *dhd, int ifidx, int cmd, char *name, return ret; } +static int +dhd_conf_rsdb_mode(dhd_pub_t *dhd, char *buf) +{ + wl_config_t rsdb_mode_cfg = {1, 0}; + + if (buf) { + rsdb_mode_cfg.config = (int)simple_strtol(buf, NULL, 0); + CONFIG_MSG("rsdb_mode %d\n", rsdb_mode_cfg.config); + dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "rsdb_mode", (char *)&rsdb_mode_cfg, + sizeof(rsdb_mode_cfg), TRUE); + } + + return 0; +} + +typedef struct sub_cmd_t { + char *name; + uint16 id; /* id for the dongle f/w switch/case */ + uint16 type; /* base type of argument IOVT_XXXX */ +} sub_cmd_t; + +/* wl he sub cmd list */ +static const sub_cmd_t he_cmd_list[] = { + {"enab", WL_HE_CMD_ENAB, IOVT_UINT8}, + {"features", WL_HE_CMD_FEATURES, IOVT_UINT32}, + {"bsscolor", WL_HE_CMD_BSSCOLOR, IOVT_UINT8}, + {"partialbsscolor", WL_HE_CMD_PARTIAL_BSSCOLOR, IOVT_UINT8}, + {"cap", WL_HE_CMD_CAP, IOVT_UINT8}, + {"staid", WL_HE_CMD_STAID, IOVT_UINT16}, + {"rtsdurthresh", WL_HE_CMD_RTSDURTHRESH, IOVT_UINT16}, + {"peduration", WL_HE_CMD_PEDURATION, IOVT_UINT8}, + {"testbed_mode", WL_HE_CMD_TESTBED_MODE, IOVT_UINT32}, + {"omi_ulmu_throttle", WL_HE_CMD_OMI_ULMU_THROTTLE, IOVT_UINT16}, + {"omi_dlmu_rr_mpf_map", WL_HE_CMD_OMI_DLMU_RSD_RCM_MPF_MAP, IOVT_UINT32}, + {"ulmu_disable_policy", WL_HE_CMD_ULMU_DISABLE_POLICY, IOVT_UINT8}, + {"sr_prohibit", WL_HE_CMD_SR_PROHIBIT, IOVT_UINT8}, +}; + +static uint +wl_he_iovt2len(uint iovt) +{ + switch (iovt) { + case IOVT_BOOL: + case IOVT_INT8: + case IOVT_UINT8: + return sizeof(uint8); + case IOVT_INT16: + case IOVT_UINT16: + return sizeof(uint16); + case IOVT_INT32: + case IOVT_UINT32: + return sizeof(uint32); + default: + /* ASSERT(0); */ + return 0; + } +} + +static int +dhd_conf_he_cmd(dhd_pub_t * dhd, char *buf) +{ + int ret = BCME_OK, i; + bcm_xtlv_t *pxtlv = NULL; + uint8 mybuf[128]; + uint16 he_id = -1, he_len = 0, mybuf_len = sizeof(mybuf); + uint32 he_val; + const sub_cmd_t *tpl = he_cmd_list; + char sub_cmd[32], he_val_str[10]; + + if (buf) { + sscanf(buf, "%s %s", sub_cmd, he_val_str); + } + + for (i=0; iname, sub_cmd)) { + he_id = tpl->id; + he_len = wl_he_iovt2len(tpl->type); + break; + } + } + if (he_id < 0) { + CONFIG_ERROR("No he id found for %s\n", sub_cmd); + return 0; + } + + pxtlv = (bcm_xtlv_t *)mybuf; + + if (strlen(he_val_str)) { + he_val = simple_strtol(he_val_str, NULL, 0); + ret = bcm_pack_xtlv_entry((uint8**)&pxtlv, &mybuf_len, he_id, + he_len, (uint8 *)&he_val, BCM_XTLV_OPTION_ALIGN32); + if (ret != BCME_OK) { + CONFIG_ERROR("failed to pack he enab, err: %s\n", bcmerrorstr(ret)); + return 0; + } + CONFIG_MSG("he %s 0x%x\n", sub_cmd, he_val); + dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "he", (char *)&mybuf, + sizeof(mybuf), TRUE); + } + + return 0; +} + +typedef int (tpl_parse_t)(dhd_pub_t *dhd, char *buf); + +typedef struct iovar_tpl_t { + int cmd; + char *name; + tpl_parse_t *parse; +} iovar_tpl_t; + +const iovar_tpl_t iovar_tpl_list[] = { + {WLC_SET_VAR, "rsdb_mode", dhd_conf_rsdb_mode}, + {WLC_SET_VAR, "he", dhd_conf_he_cmd}, +}; + +static int iovar_tpl_parse(const iovar_tpl_t *tpl, int tpl_count, + dhd_pub_t *dhd, int cmd, char *name, char *buf) +{ + int i, ret = 0; + + /* look for a matching code in the table */ + for (i = 0; i < tpl_count; i++, tpl++) { + if (tpl->cmd == cmd && !strcmp(tpl->name, name)) + break; + } + if (i < tpl_count && tpl->parse) { + ret = tpl->parse(dhd, buf); + } else { + ret = -1; + } + + return ret; +} + +bool +dhd_conf_set_wl_cmd(dhd_pub_t *dhd, char *data, bool down) +{ + int cmd, val, ret = 0, len; + char name[32], *pch, *pick_tmp, *pick_tmp2, *pdata = NULL; + + /* Process wl_preinit: + * wl_preinit=[cmd]=[val], [cmd]=[val] + * Ex: wl_preinit=86=0, mpc=0 + */ + + if (data == NULL) + return FALSE; + + len = strlen(data); + pdata = kmalloc(len+1, GFP_KERNEL); + if (pdata == NULL) { + CONFIG_ERROR("Failed to allocate buffer of %d bytes\n", len+1); + goto exit; + } + memset(pdata, 0, len+1); + strcpy(pdata, data); + + pick_tmp = pdata; + while (pick_tmp && (pick_tmp2 = bcmstrtok(&pick_tmp, ",", 0)) != NULL) { + pch = bcmstrtok(&pick_tmp2, "=", 0); + if (!pch) + break; + if (*pch == ' ') { + pch++; + } + memset(name, 0 , sizeof (name)); + cmd = (int)simple_strtol(pch, NULL, 0); + if (cmd == 0) { + cmd = WLC_SET_VAR; + strcpy(name, pch); + } + pch = bcmstrtok(&pick_tmp2, ",", 0); + if (!pch) { + break; + } + ret = iovar_tpl_parse(iovar_tpl_list, ARRAY_SIZE(iovar_tpl_list), + dhd, cmd, name, pch); + if (ret) { + val = (int)simple_strtol(pch, NULL, 0); + dhd_conf_set_intiovar(dhd, cmd, name, val, -1, down); + } + } + +exit: + if (pdata) + kfree(pdata); + return true; +} + int dhd_conf_get_band(dhd_pub_t *dhd) { @@ -845,25 +1006,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; - - for (i=0; icspec[i] != NULL) { - if (!strncmp("**", 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; - bcmerror = 0; - break; - } else 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; - bcmerror = 0; - break; - } + country_list_t *country = conf->country_head; + +#ifdef CCODE_LIST + bcmerror = dhd_ccode_map_country_list(dhd, cspec); +#endif + + 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) @@ -1073,7 +1237,7 @@ dhd_conf_set_bw_cap(dhd_pub_t *dhd) param.bw_cap = (uint)dhd->conf->bw_cap[0]; 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); + sizeof(param), TRUE); } if (dhd->conf->bw_cap[1] >= 0) { @@ -1082,7 +1246,7 @@ dhd_conf_set_bw_cap(dhd_pub_t *dhd) param.bw_cap = (uint)dhd->conf->bw_cap[1]; 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); + sizeof(param), TRUE); } } @@ -1226,18 +1390,19 @@ dhd_conf_set_wme(dhd_pub_t *dhd, int ifidx, 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; @@ -1370,6 +1535,24 @@ dhd_conf_check_hostsleep(dhd_pub_t *dhd, int cmd, void *buf, int len, goto exit; } } +#ifdef NO_POWER_SAVE + if (cmd == WLC_SET_PM) { + if (*(const u32*)buf != 0) { + CONFIG_TRACE("skip PM\n"); + *ret = BCME_OK; + goto exit; + } + } else if (cmd == WLC_SET_VAR) { + int cmd_len = strlen("mpc"); + if (!strncmp(buf, "mpc", cmd_len)) { + if (*((u32 *)((u8*)buf+cmd_len+1)) != 0) { + CONFIG_TRACE("skip mpc\n"); + *ret = BCME_OK; + goto exit; + } + } + } +#endif return 0; exit: @@ -1576,7 +1759,6 @@ dhd_conf_mkeep_alive(dhd_pub_t *dhd, int ifidx, int id, int period, wl_mkeep_alive_pkt_t *mkeep_alive_pktp; int ret = 0, len_bytes=0, buf_len=0; char *buf = NULL, *iovar_buf = NULL; - struct ether_addr bssid; uint8 *pdata; CONFIG_TRACE("id=%d, period=%d, packet=%s\n", id, period, packet); @@ -1597,17 +1779,11 @@ dhd_conf_mkeep_alive(dhd_pub_t *dhd, int ifidx, int id, int period, mkeep_alive_pktp->keep_alive_id = id; buf_len += WL_MKEEP_ALIVE_FIXED_LEN; mkeep_alive_pktp->period_msec = period; - if (strlen(packet)) { + 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); - } else { - memset(&bssid, 0, ETHER_ADDR_LEN); - ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, - FALSE, ifidx); - if (ret != BCME_NOTASSOCIATED && memcmp(ðer_null, &bssid, ETHER_ADDR_LEN)) - memcpy(mkeep_alive_pktp->data, &bssid, ETHER_ADDR_LEN); } ret = dhd_conf_get_iovar(dhd, ifidx, WLC_GET_VAR, "cur_etheraddr", iovar_buf, WLC_IOCTL_SMLEN); @@ -1658,11 +1834,18 @@ dhd_conf_set_garp(dhd_pub_t *dhd, int ifidx, uint32 ipa, bool enable) for (i=0; i>8)&0xff, (ipa>>16)&0xff, (ipa>>24)&0xff); + // Target Hardware Addr. + len += snprintf(packet+len, total_len, "ffffffffffff"); + // Target IP Addr. len += snprintf(packet+len, total_len, "%02x%02x%02x%02x", ipa&0xff, (ipa>>8)&0xff, (ipa>>16)&0xff, (ipa>>24)&0xff); - len += snprintf(packet+len, total_len, "ffffffffffffc0a80101000000000000000000000000000000000000"); + len += snprintf(packet+len, total_len, "000000000000000000000000000000000000"); } dhd_conf_mkeep_alive(dhd, ifidx, 0, dhd->conf->keep_alive_period, packet, TRUE); @@ -1707,6 +1890,7 @@ dhd_conf_set_suspend_event(dhd_pub_t *dhd, int suspend) struct net_device *net; #endif /* defined(WL_CFG80211) */ + CONFIG_TRACE("Enter\n"); if (suspend) { #ifdef PROP_TXSTATUS #if defined(BCMSDIO) || defined(BCMDBUS) @@ -1783,26 +1967,50 @@ dhd_conf_set_suspend_event(dhd_pub_t *dhd, int suspend) } #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) { - uint insuspend = 0; 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 insuspend = dhd_conf_get_insuspend(dhd, ALL_IN_SUSPEND); if (insuspend) - CONFIG_MSG("op_mode %d, suspend %d, suspended %d, insuspend 0x%x\n", - dhd->op_mode, suspend, conf->suspended, insuspend); + CONFIG_MSG("op_mode %d, suspend %d, suspended %d, insuspend 0x%x, suspend_mode=%d\n", + dhd->op_mode, suspend, conf->suspended, insuspend, conf->suspend_mode); - if (conf->suspended == suspend) { + if (conf->suspended == suspend || !dhd->up) { 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) { @@ -1810,14 +2018,36 @@ dhd_conf_set_suspend_resume(dhd_pub_t *dhd, int 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) + 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) + 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 (insuspend & NO_TXDATA_IN_SUSPEND) { - dhd_txflowcontrol(dhd, ALL_INTERFACES, ON); + 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); } + dhd_conf_set_wl_cmd(dhd, conf->wl_suspend, FALSE); #ifdef WL_EXT_WOWL if ((insuspend & WOWL_IN_SUSPEND) && dhd_master_mode) { dhd_conf_wowl_pattern(dhd, FALSE, "clr"); @@ -1828,10 +2058,18 @@ dhd_conf_set_suspend_resume(dhd_pub_t *dhd, int suspend) 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 { @@ -1846,21 +2084,40 @@ dhd_conf_set_suspend_resume(dhd_pub_t *dhd, int suspend) dhd_conf_wowl_pattern(dhd, FALSE, "clr"); } #endif + dhd_conf_set_wl_cmd(dhd, conf->wl_resume, FALSE); + 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) + 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 (insuspend & NO_TXDATA_IN_SUSPEND) { - dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF); + 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; } @@ -1919,7 +2176,7 @@ dhd_conf_get_disable_proptx(dhd_pub_t *dhd) #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; @@ -1972,6 +2229,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++; } @@ -2017,6 +2276,10 @@ dhd_conf_read_log_level(dhd_pub_t *dhd, char *full_param, uint len_param) dhd_msg_level = (int)simple_strtol(data, NULL, 0); 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); @@ -2162,6 +2425,7 @@ 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); @@ -2218,6 +2482,7 @@ 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); @@ -2277,6 +2542,7 @@ 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); @@ -2346,14 +2612,13 @@ 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) { struct dhd_conf *conf = dhd->conf; - conf_country_list_t *country_list = &conf->country_list; + 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; uint len_data = strlen(data); /* Process country_list: @@ -2373,6 +2638,7 @@ dhd_conf_read_country_list(dhd_pub_t *dhd, char *full_param, uint len_param) 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->cspec.rev = (int32)simple_strtol(pch, NULL, 10); count++; - country_list->cspec[i] = cspec; - CONFIG_TRACE("country_list abbrev=%s, ccode=%s, regrev=%d\n", - cspec->country_abbrev, cspec->ccode, cspec->rev); + 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); } @@ -2420,6 +2692,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: @@ -2427,51 +2700,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("wrong bw %d\n", 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) - CONFIG_MSG("mchan_bw=%d/%d/%d\n", 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 @@ -2531,6 +2818,10 @@ dhd_conf_read_pkt_filter(dhd_pub_t *dhd, char *full_param, uint len_param) 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("kmalloc failed\n"); } else { @@ -2806,6 +3097,12 @@ dhd_conf_read_pm_params(dhd_pub_t *dhd, char *full_param, uint len_param) conf->pm_in_suspend = (int)simple_strtol(data, NULL, 10); 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); + if (conf->suspend_mode == PM_NOTIFIER) + conf->insuspend |= (NO_TXDATA_IN_SUSPEND | NO_TXCTL_IN_SUSPEND); + } else if (!strncmp("suspend_bcn_li_dtim=", full_param, len_param)) { conf->suspend_bcn_li_dtim = (int)simple_strtol(data, NULL, 10); CONFIG_MSG("suspend_bcn_li_dtim = %d\n", conf->suspend_bcn_li_dtim); @@ -2992,6 +3289,10 @@ dhd_conf_read_others(dhd_pub_t *dhd, char *full_param, uint len_param) 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("kmalloc failed\n"); } else { @@ -3000,6 +3301,32 @@ dhd_conf_read_others(dhd_pub_t *dhd, char *full_param, uint len_param) CONFIG_MSG("wl_preinit = %s\n", conf->wl_preinit); } } + else if (!strncmp("wl_suspend=", full_param, len_param)) { + if (conf->wl_suspend) { + kfree(conf->wl_suspend); + conf->wl_suspend = NULL; + } + if (!(conf->wl_suspend = kmalloc(len_param+1, GFP_KERNEL))) { + CONFIG_ERROR("kmalloc failed\n"); + } else { + memset(conf->wl_suspend, 0, len_param+1); + strcpy(conf->wl_suspend, data); + CONFIG_MSG("wl_suspend = %s\n", conf->wl_suspend); + } + } + else if (!strncmp("wl_resume=", full_param, len_param)) { + if (conf->wl_resume) { + kfree(conf->wl_resume); + conf->wl_resume = NULL; + } + if (!(conf->wl_resume = kmalloc(len_param+1, GFP_KERNEL))) { + CONFIG_ERROR("kmalloc failed\n"); + } else { + memset(conf->wl_resume, 0, len_param+1); + strcpy(conf->wl_resume, data); + CONFIG_MSG("wl_resume = %s\n", conf->wl_resume); + } + } #ifdef GET_CUSTOM_MAC_FROM_CONFIG else if (!strncmp("mac=", full_param, len_param)) { if (!bcm_ether_atoe(data, &ea_addr)) { @@ -3024,6 +3351,16 @@ dhd_conf_read_others(dhd_pub_t *dhd, char *full_param, uint len_param) } } } +#endif +#ifdef PROPTX_MAXCOUNT + else if (!strncmp("proptx_maxcnt_2g=", full_param, len_param)) { + conf->proptx_maxcnt_2g = (int)simple_strtol(data, NULL, 0); + CONFIG_MSG("proptx_maxcnt_2g = 0x%x\n", conf->proptx_maxcnt_2g); + } + else if (!strncmp("proptx_maxcnt_5g=", full_param, len_param)) { + conf->proptx_maxcnt_5g = (int)simple_strtol(data, NULL, 0); + CONFIG_MSG("proptx_maxcnt_5g = 0x%x\n", conf->proptx_maxcnt_5g); + } #endif else return false; @@ -3035,16 +3372,16 @@ int dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path) { int bcmerror = -1, chip_match = -1; - uint len = 0, start_pos=0; - void * image = NULL; - char * memblock = NULL; + 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); } @@ -3078,7 +3415,10 @@ 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; @@ -3109,7 +3449,7 @@ dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path) #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; @@ -3226,99 +3566,15 @@ dhd_conf_set_txglom_params(dhd_pub_t *dhd, bool enable) } #endif -static int -dhd_conf_rsdb_mode(dhd_pub_t *dhd, char *buf) -{ - char *pch; - wl_config_t rsdb_mode_cfg = {1, 0}; - - pch = buf; - rsdb_mode_cfg.config = (int)simple_strtol(pch, NULL, 0); - - if (pch) { - dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "rsdb_mode", (char *)&rsdb_mode_cfg, - sizeof(rsdb_mode_cfg), TRUE); - CONFIG_MSG("rsdb_mode %d\n", rsdb_mode_cfg.config); - } - - return 0; -} - -typedef int (tpl_parse_t)(dhd_pub_t *dhd, char *buf); - -typedef struct iovar_tpl_t { - int cmd; - char *name; - tpl_parse_t *parse; -} iovar_tpl_t; - -const iovar_tpl_t iovar_tpl_list[] = { - {WLC_SET_VAR, "rsdb_mode", dhd_conf_rsdb_mode}, -}; - -static int iovar_tpl_parse(const iovar_tpl_t *tpl, int tpl_count, - dhd_pub_t *dhd, int cmd, char *name, char *buf) -{ - int i, ret = 0; - - /* look for a matching code in the table */ - for (i = 0; i < tpl_count; i++, tpl++) { - if (tpl->cmd == cmd && !strcmp(tpl->name, name)) - break; - } - if (i < tpl_count && tpl->parse) { - ret = tpl->parse(dhd, buf); - } else { - ret = -1; - } - - return ret; -} - -bool -dhd_conf_set_wl_preinit(dhd_pub_t *dhd, char *data) -{ - int cmd, val, ret = 0; - char name[32], *pch, *pick_tmp, *pick_tmp2; - - /* Process wl_preinit: - * wl_preinit=[cmd]=[val], [cmd]=[val] - * Ex: wl_preinit=86=0, mpc=0 - */ - pick_tmp = data; - while (pick_tmp && (pick_tmp2 = bcmstrtok(&pick_tmp, ",", 0)) != NULL) { - pch = bcmstrtok(&pick_tmp2, "=", 0); - if (!pch) - break; - if (*pch == ' ') { - pch++; - } - memset(name, 0 , sizeof (name)); - cmd = (int)simple_strtol(pch, NULL, 0); - if (cmd == 0) { - cmd = WLC_SET_VAR; - strcpy(name, pch); - } - pch = bcmstrtok(&pick_tmp2, ",", 0); - if (!pch) { - break; - } - ret = iovar_tpl_parse(iovar_tpl_list, ARRAY_SIZE(iovar_tpl_list), - dhd, cmd, name, pch); - if (ret) { - val = (int)simple_strtol(pch, NULL, 0); - dhd_conf_set_intiovar(dhd, cmd, name, val, -1, TRUE); - } - } - - return true; -} - void dhd_conf_postinit_ioctls(dhd_pub_t *dhd) { struct dhd_conf *conf = dhd->conf; - char wl_preinit[] = "assoc_retry_max=30"; + char wl_preinit[] = "assoc_retry_max=20"; +#ifdef NO_POWER_SAVE + char wl_no_power_save[] = "mpc=0, 86=0"; + dhd_conf_set_wl_cmd(dhd, wl_no_power_save, FALSE); +#endif dhd_conf_set_intiovar(dhd, WLC_UP, "WLC_UP", 0, 0, FALSE); dhd_conf_map_country_list(dhd, &conf->cspec); @@ -3358,25 +3614,26 @@ dhd_conf_postinit_ioctls(dhd_pub_t *dhd) dhd_conf_set_intiovar(dhd, WLC_SET_FAKEFRAG, "WLC_SET_FAKEFRAG", conf->frameburst, 0, FALSE); - dhd_conf_set_wl_preinit(dhd, wl_preinit); + dhd_conf_set_wl_cmd(dhd, wl_preinit, TRUE); #if defined(BCMSDIO) { char ampdu_mpdu[] = "ampdu_mpdu=16"; - dhd_conf_set_wl_preinit(dhd, ampdu_mpdu); + dhd_conf_set_wl_cmd(dhd, ampdu_mpdu, TRUE); } #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) { + conf->chip == BCM43569_CHIP_ID || + conf->chip == BCM43751_CHIP_ID || conf->chip == BCM43752_CHIP_ID) { dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "txbf", 1, 0, FALSE); } #if defined(WLEASYMESH) { char ezmesh[] = "mbss=1, rsdb_mode=0"; - dhd_conf_set_wl_preinit(dhd, ezmesh); + dhd_conf_set_wl_cmd(dhd, ezmesh, TRUE); } #endif - dhd_conf_set_wl_preinit(dhd, conf->wl_preinit); + dhd_conf_set_wl_cmd(dhd, conf->wl_preinit, TRUE); #ifndef WL_CFG80211 dhd_conf_set_intiovar(dhd, WLC_UP, "WLC_UP", 0, 0, FALSE); @@ -3388,16 +3645,16 @@ int dhd_conf_preinit(dhd_pub_t *dhd) { struct dhd_conf *conf = dhd->conf; - int i; 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; @@ -3406,7 +3663,14 @@ 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)); + if (conf->wl_suspend) { + kfree(conf->wl_suspend); + conf->wl_suspend = NULL; + } + if (conf->wl_resume) { + kfree(conf->wl_resume); + conf->wl_resume = NULL; + } conf->band = -1; memset(&conf->bw_cap, -1, sizeof(conf->bw_cap)); if (conf->chip == BCM43362_CHIP_ID || conf->chip == BCM4330_CHIP_ID) { @@ -3416,8 +3680,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 == BCM43751_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; @@ -3482,14 +3745,16 @@ dhd_conf_preinit(dhd_pub_t *dhd) conf->deepsleep = FALSE; conf->pm = -1; conf->pm_in_suspend = -1; + conf->insuspend = 0; + conf->suspend_mode = EARLY_SUSPEND; conf->suspend_bcn_li_dtim = -1; #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; + conf->insuspend |= (WOWL_IN_SUSPEND | NO_TXDATA_IN_SUSPEND); #endif + if (conf->suspend_mode == PM_NOTIFIER) + conf->insuspend |= (NO_TXDATA_IN_SUSPEND | NO_TXCTL_IN_SUSPEND); conf->suspended = FALSE; #ifdef SUSPEND_EVENT memset(&conf->resume_eventmask, 0, sizeof(conf->resume_eventmask)); @@ -3518,15 +3783,16 @@ dhd_conf_preinit(dhd_pub_t *dhd) #endif conf->pktprio8021x = -1; conf->ctrl_resched = 2; - conf->in4way = NO_SCAN_IN4WAY | WAIT_DISCONNECTED; + conf->in4way = NO_SCAN_IN4WAY | DONT_DELETE_GC_AFTER_WPS | WAIT_DISCONNECTED; +#ifdef PROPTX_MAXCOUNT + conf->proptx_maxcnt_2g = 46; + conf->proptx_maxcnt_5g = WL_TXSTATUS_FREERUNCTR_MASK; +#endif /* DYNAMIC_PROPTX_MAXCOUNT */ #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)); - } #ifdef CUSTOMER_HW_AMLOGIC dhd_slpauto = FALSE; #ifdef BCMSDIO @@ -3539,8 +3805,8 @@ dhd_conf_preinit(dhd_pub_t *dhd) 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 == BCM4359_CHIP_ID || conf->chip == BCM43751_CHIP_ID || - conf->chip == BCM43752_CHIP_ID) { + conf->chip == BCM4359_CHIP_ID || + conf->chip == BCM43751_CHIP_ID || conf->chip == BCM43752_CHIP_ID) { conf->intr_extn = TRUE; } #endif @@ -3595,6 +3861,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; } @@ -3602,21 +3869,32 @@ 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)); + if (conf->wl_suspend) { + kfree(conf->wl_suspend); + conf->wl_suspend = NULL; + } + if (conf->wl_resume) { + kfree(conf->wl_resume); + conf->wl_resume = NULL; + } + memset(conf, 0, sizeof(dhd_conf_t)); return 0; } @@ -3651,24 +3929,34 @@ fail: void dhd_conf_detach(dhd_pub_t *dhd) { - CONFIG_TRACE("Enter\n"); + 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)); + if (conf->wl_suspend) { + kfree(conf->wl_suspend); + conf->wl_suspend = NULL; + } + if (conf->wl_resume) { + kfree(conf->wl_resume); + conf->wl_resume = NULL; + } + MFREE(dhd->osh, conf, sizeof(dhd_conf_t)); } dhd->conf = NULL; } diff --git a/bcmdhd.100.10.315.x/dhd_config.h b/bcmdhd.100.10.315.x/dhd_config.h index 7902171..cdd76c4 100644 --- a/bcmdhd.100.10.315.x/dhd_config.h +++ b/bcmdhd.100.10.315.x/dhd_config.h @@ -86,16 +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 { - 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; @@ -119,6 +121,11 @@ enum in_suspend_flags { ALL_IN_SUSPEND = 0xFFFFFFFF, }; +enum in_suspend_mode { + EARLY_SUSPEND = 0, + PM_NOTIFIER = 1 +}; + enum eapol_status { EAPOL_STATUS_NONE = 0, EAPOL_STATUS_REQID = 1, @@ -146,13 +153,17 @@ enum eapol_status { typedef struct dhd_conf { uint chip; uint chiprev; +#ifdef GET_OTP_MODULE_NAME + char module_name[16]; +#endif + struct ether_addr otp_mac; 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; @@ -218,6 +229,7 @@ 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; @@ -244,8 +256,10 @@ typedef struct dhd_conf { char isam_enable[50]; #endif int ctrl_resched; - struct mchan_params mchan[MCHAN_MAX_NUM]; + mchan_params_t *mchan; char *wl_preinit; + char *wl_suspend; + char *wl_resume; int tsq; int orphan_move; uint eapol_status; @@ -256,24 +270,30 @@ typedef struct dhd_conf { #ifdef GET_CUSTOM_MAC_FROM_CONFIG char hw_ether[62]; #endif + wait_queue_head_t event_complete; +#ifdef PROPTX_MAXCOUNT + int proptx_maxcnt_2g; + int proptx_maxcnt_5g; +#endif /* DYNAMIC_PROPTX_MAXCOUNT */ } dhd_conf_t; #ifdef BCMSDIO -int dhd_conf_get_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, si_t *sih, uint8 *mac); +void dhd_conf_get_otp(dhd_pub_t *dhd, bcmsdh_info_t *sdh, si_t *sih); #if defined(HW_OOB) || defined(FORCE_WOWLAN) void dhd_conf_set_hw_oob_intr(bcmsdh_info_t *sdh, struct si_pub *sih); #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_path_params(dhd_pub_t *dhd, void *sdh, void *sih, - char *fw_path, char *nv_path); +void dhd_conf_set_path_params(dhd_pub_t *dhd, 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); +#ifdef CCODE_LIST +int dhd_ccode_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec); +#endif 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 ifidx, int mode); @@ -307,4 +327,7 @@ int dhd_conf_attach(dhd_pub_t *dhd); void dhd_conf_detach(dhd_pub_t *dhd); void *dhd_get_pub(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/bcmdhd.100.10.315.x/dhd_csi.c b/bcmdhd.100.10.315.x/dhd_csi.c new file mode 100644 index 0000000..dd1a068 --- /dev/null +++ b/bcmdhd.100.10.315.x/dhd_csi.c @@ -0,0 +1,220 @@ +/* + * Broadcom Dongle Host Driver (DHD) + * + * Copyright (C) 1999-2018, Broadcom. + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: dhd_csi.c 606280 2015-12-15 05:28:25Z $ + */ +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define NULL_CHECK(p, s, err) \ + do { \ + if (!(p)) { \ + printf("NULL POINTER (%s) : %s\n", __FUNCTION__, (s)); \ + err = BCME_ERROR; \ + return err; \ + } \ + } while (0) + +#define TIMESPEC_TO_US(ts) (((uint64)(ts).tv_sec * USEC_PER_SEC) + \ + (ts).tv_nsec / NSEC_PER_USEC) + +#define NULL_ADDR "\x00\x00\x00\x00\x00\x00" + +int +dhd_csi_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data) +{ + int ret = BCME_OK; + bool is_new = TRUE; + cfr_dump_data_t *p_event; + cfr_dump_list_t *ptr, *next, *new; + + NULL_CHECK(dhd, "dhd is NULL", ret); + + DHD_TRACE(("Enter %s\n", __FUNCTION__)); + + if (!event_data) { + DHD_ERROR(("%s: event_data is NULL\n", __FUNCTION__)); + return -EINVAL; + } + p_event = (cfr_dump_data_t *)event_data; + + /* check if this addr exist */ + if (!list_empty(&dhd->csi_list)) { + list_for_each_entry_safe(ptr, next, &dhd->csi_list, list) { + if (bcmp(&ptr->entry.header.peer_macaddr, &p_event->header.peer_macaddr, + ETHER_ADDR_LEN) == 0) { + int pos = 0, dump_len = 0, remain = 0; + is_new = FALSE; + DHD_INFO(("CSI data exist\n")); + if (p_event->header.status == 0) { + bcopy(&p_event->header, &ptr->entry.header, sizeof(cfr_dump_header_t)); + dump_len = p_event->header.cfr_dump_length; + if (dump_len < MAX_EVENT_SIZE) { + bcopy(&p_event->data, &ptr->entry.data, dump_len); + } else { + /* for big csi data */ + uint8 *p = (uint8 *)&ptr->entry.data; + remain = p_event->header.remain_length; + if (remain) { + pos = dump_len - remain - MAX_EVENT_SIZE; + p += pos; + bcopy(&p_event->data, p, MAX_EVENT_SIZE); + } + /* copy rest of csi data */ + else { + pos = dump_len - (dump_len % MAX_EVENT_SIZE); + p += pos; + bcopy(&p_event->data, p, (dump_len % MAX_EVENT_SIZE)); + } + } + return BCME_OK; + } + } + } + } + if (is_new) { + if (dhd->csi_count < MAX_CSI_NUM) { + new = (cfr_dump_list_t *)MALLOCZ(dhd->osh, sizeof(cfr_dump_list_t)); + if (!new){ + DHD_ERROR(("Malloc cfr dump list error\n")); + return BCME_NOMEM; + } + bcopy(&p_event->header, &new->entry.header, sizeof(cfr_dump_header_t)); + DHD_INFO(("New entry data size %d\n", p_event->header.cfr_dump_length)); + /* for big csi data */ + if (p_event->header.remain_length) { + DHD_TRACE(("remain %d\n", p_event->header.remain_length)); + bcopy(&p_event->data, &new->entry.data, MAX_EVENT_SIZE); + } + else + bcopy(&p_event->data, &new->entry.data, p_event->header.cfr_dump_length); + INIT_LIST_HEAD(&(new->list)); + list_add_tail(&(new->list), &dhd->csi_list); + dhd->csi_count++; + } + else { + DHD_TRACE(("Over maximum CSI Number 8. SKIP it.\n")); + } + } + return ret; +} + +int +dhd_csi_init(dhd_pub_t *dhd) +{ + int err = BCME_OK; + + NULL_CHECK(dhd, "dhd is NULL", err); + INIT_LIST_HEAD(&dhd->csi_list); + dhd->csi_count = 0; + + return err; +} + +int +dhd_csi_deinit(dhd_pub_t *dhd) +{ + int err = BCME_OK; + cfr_dump_list_t *ptr, *next; + + NULL_CHECK(dhd, "dhd is NULL", err); + + if (!list_empty(&dhd->csi_list)) { + list_for_each_entry_safe(ptr, next, &dhd->csi_list, list) { + list_del(&ptr->list); + MFREE(dhd->osh, ptr, sizeof(cfr_dump_list_t)); + } + } + return err; +} + +void +dhd_csi_clean_list(dhd_pub_t *dhd) +{ + cfr_dump_list_t *ptr, *next; + int num = 0; + + if (!dhd) { + DHD_ERROR(("NULL POINTER: %s\n", __FUNCTION__)); + return; + } + + if (!list_empty(&dhd->csi_list)) { + list_for_each_entry_safe(ptr, next, &dhd->csi_list, list) { + if (0 == ptr->entry.header.remain_length) { + list_del(&ptr->list); + num++; + MFREE(dhd->osh, ptr, sizeof(cfr_dump_list_t)); + } + } + } + dhd->csi_count = 0; + DHD_TRACE(("Clean up %d record\n", num)); +} + +int +dhd_csi_dump_list(dhd_pub_t *dhd, char *buf) +{ + int ret = BCME_OK; + cfr_dump_list_t *ptr, *next; + uint8 * pbuf = buf; + int num = 0; + int length = 0; + + NULL_CHECK(dhd, "dhd is NULL", ret); + + /* check if this addr exist */ + if (!list_empty(&dhd->csi_list)) { + list_for_each_entry_safe(ptr, next, &dhd->csi_list, list) { + if (ptr->entry.header.remain_length) { + DHD_ERROR(("data not ready %d\n", ptr->entry.header.remain_length)); + continue; + } + bcopy(&ptr->entry.header, pbuf, sizeof(cfr_dump_header_t)); + length += sizeof(cfr_dump_header_t); + pbuf += sizeof(cfr_dump_header_t); + DHD_TRACE(("Copy data size %d\n", ptr->entry.header.cfr_dump_length)); + bcopy(&ptr->entry.data, pbuf, ptr->entry.header.cfr_dump_length); + length += ptr->entry.header.cfr_dump_length; + pbuf += ptr->entry.header.cfr_dump_length; + num++; + } + } + DHD_TRACE(("dump %d record %d bytes\n", num, length)); + + return length; +} + diff --git a/bcmdhd.100.10.315.x/dhd_csi.h b/bcmdhd.100.10.315.x/dhd_csi.h new file mode 100644 index 0000000..bcc712c --- /dev/null +++ b/bcmdhd.100.10.315.x/dhd_csi.h @@ -0,0 +1,77 @@ +/* + * Broadcom Dongle Host Driver (DHD), CSI + * + * Copyright (C) 1999-2018, Broadcom. + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: dhd_csi.h 558438 2015-05-22 06:05:11Z $ + */ +#ifndef __DHD_CSI_H__ +#define __DHD_CSI_H__ + +/* Maxinum csi file dump size */ +#define MAX_CSI_FILESZ (32 * 1024) +/* Maxinum subcarrier number */ +#define MAXINUM_CFR_DATA 256 * 4 +#define CSI_DUMP_PATH "/sys/bcm-dhd/csi" +#define MAX_EVENT_SIZE 1400 +/* maximun csi number stored at dhd */ +#define MAX_CSI_NUM 8 + +typedef struct cfr_dump_header { + /* 0 - successful; 1 - Failed */ + uint8 status; + /* Peer MAC address */ + uint8 peer_macaddr[6]; + /* Number of Space Time Streams */ + uint8 sts; + /* Number of RX chain */ + uint8 num_rx; + /* Number of subcarrier */ + uint16 num_carrier; + /* Length of the CSI dump */ + uint32 cfr_dump_length; + /* remain unsend CSI data length */ + uint32 remain_length; + /* RSSI */ + int8 rssi; +} __attribute__((packed)) cfr_dump_header_t; + +typedef struct cfr_dump_data { + cfr_dump_header_t header; + uint32 data[MAXINUM_CFR_DATA]; +} cfr_dump_data_t; + +typedef struct { + struct list_head list; + cfr_dump_data_t entry; +} cfr_dump_list_t; + +int dhd_csi_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data); + +int dhd_csi_init(dhd_pub_t *dhd); + +int dhd_csi_deinit(dhd_pub_t *dhd); + +void dhd_csi_clean_list(dhd_pub_t *dhd); + +int dhd_csi_dump_list(dhd_pub_t *dhd, char *buf); +#endif /* __DHD_CSI_H__ */ + diff --git a/bcmdhd.100.10.315.x/dhd_custom_gpio.c b/bcmdhd.100.10.315.x/dhd_custom_gpio.c index 136d2a2..f3facfd 100644 --- a/bcmdhd.100.10.315.x/dhd_custom_gpio.c +++ b/bcmdhd.100.10.315.x/dhd_custom_gpio.c @@ -85,7 +85,7 @@ dhd_customer_gpio_wlan_ctrl(void *adapter, int onoff) return err; } -#ifdef GET_CUSTOM_MAC_ENABLE +#if 0 /* Function to get custom MAC address */ int dhd_custom_get_mac_address(void *adapter, unsigned char *buf) diff --git a/bcmdhd.100.10.315.x/dhd_gpio.c b/bcmdhd.100.10.315.x/dhd_gpio.c index 7b0e65d..fc8fd44 100644 --- a/bcmdhd.100.10.315.x/dhd_gpio.c +++ b/bcmdhd.100.10.315.x/dhd_gpio.c @@ -24,6 +24,7 @@ static int gpio_wl_host_wake = -1; // WL_HOST_WAKE is output pin of WLAN module #include extern int wifi_irq_trigger_level(void); extern u8 *wifi_get_mac(void); +extern u8 *wifi_get_ap_mac(void); #endif extern void sdio_reinit(void); extern void set_usb_bt_power(int is_power); @@ -177,18 +178,45 @@ static int dhd_wlan_set_carddetect(int present) return err; } -static int dhd_wlan_get_mac_addr(unsigned char *buf) +static int dhd_wlan_get_mac_addr(unsigned char *buf +#ifdef CUSTOM_MULTI_MAC + , char *name +#endif +) { int err = 0; - printf("======== %s ========\n", __FUNCTION__); -#ifdef EXAMPLE_GET_MAC - /* EXAMPLE code */ +#ifdef CUSTOM_MULTI_MAC + if (!strcmp("wlan1", name)) { +#ifdef CUSTOMER_HW_AMLOGIC +#ifdef CUSTOM_AP_MAC + bcopy((char *)wifi_get_ap_mac(), buf, sizeof(struct ether_addr)); + if (buf[0] == 0xff) { + printf("custom wifi ap mac is not set\n"); + err = -1; + } else + printf("custom wifi ap mac-addr: %02x:%02x:%02x:%02x:%02x:%02x\n", + buf[0], buf[1], buf[2], + buf[3], buf[4], buf[5]); +#else + err = -1; +#endif +#endif + } else +#endif /* CUSTOM_MULTI_MAC */ { - struct ether_addr ea_example = {{0x00, 0x11, 0x22, 0x33, 0x44, 0xFF}}; - bcopy((char *)&ea_example, buf, sizeof(struct ether_addr)); +#ifdef CUSTOMER_HW_AMLOGIC + bcopy((char *)wifi_get_mac(), buf, sizeof(struct ether_addr)); + if (buf[0] == 0xff) { + printf("custom wifi mac is not set\n"); + err = -1; + } else + printf("custom wifi mac-addr: %02x:%02x:%02x:%02x:%02x:%02x\n", + buf[0], buf[1], buf[2], + buf[3], buf[4], buf[5]); +#endif } -#endif /* EXAMPLE_GET_MAC */ + #ifdef EXAMPLE_GET_MAC_VER2 /* EXAMPLE code */ { @@ -204,6 +232,8 @@ static int dhd_wlan_get_mac_addr(unsigned char *buf) } #endif /* EXAMPLE_GET_MAC_VER2 */ + printf("======== %s err=%d ========\n", __FUNCTION__, err); + return err; } @@ -295,7 +325,7 @@ int dhd_wlan_init_gpio(void) #ifdef CUSTOMER_HW_AMLOGIC #if defined(BCMPCIE) printf("======== Card detection to detect PCIE card! ========\n"); - pci_remove_reinit(0x14e4, 0x43ec, 1); + //pci_remove_reinit(0x14e4, 0x449d, 1); #endif #endif diff --git a/bcmdhd.100.10.315.x/dhd_linux.c b/bcmdhd.100.10.315.x/dhd_linux.c index 9495648..54fa3ca 100644 --- a/bcmdhd.100.10.315.x/dhd_linux.c +++ b/bcmdhd.100.10.315.x/dhd_linux.c @@ -111,6 +111,10 @@ #include #endif // endif +#ifdef CSI_SUPPORT +#include +#endif /* CSI_SUPPORT */ + #ifdef CONFIG_COMPAT #include #endif // endif @@ -247,6 +251,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 @@ -874,18 +879,33 @@ 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) */ + if (dhdinfo->pub.conf->suspend_mode == PM_NOTIFIER) + dhd_conf_set_suspend_resume(&dhdinfo->pub, suspend); DHD_OS_WAKE_LOCK_RESTORE(&dhdinfo->pub); } else { + if (dhdinfo->pub.conf->suspend_mode == PM_NOTIFIER) + dhd_conf_set_suspend_resume(&dhdinfo->pub, suspend); +#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)) dhd_mmc_suspend = suspend; smp_mb(); +#endif return ret; } @@ -1810,7 +1830,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 */ /* wl_pkt_filter_enable_t enable_parm; */ int bcn_li_dtim = 0; /* Default bcn_li_dtim in resume mode is 0 */ int ret = 0; @@ -1822,7 +1844,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 = 1; @@ -1876,12 +1898,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 @@ -1890,10 +1906,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); +#endif /* SUPPORT_PM2_ONLY */ #ifdef PKT_FILTER_SUPPORT /* Enable packet filter, @@ -2110,8 +2126,11 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) DHD_ERROR(("failed to set intr_width (%d)\n", ret)); } #endif /* DYNAMIC_SWOOB_DURATION */ +#ifndef SUPPORT_PM2_ONLY + power_mode = PM_FAST; dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode), TRUE, 0); +#endif /* SUPPORT_PM2_ONLY */ #if defined(WL_CFG80211) && defined(WL_BCNRECV) ret = wl_android_bcnrecv_resume(dhd_linux_get_primary_netdev(dhd)); if (ret != BCME_OK) { @@ -2300,8 +2319,10 @@ static void dhd_early_suspend(struct early_suspend *h) struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend); DHD_TRACE_HW4(("%s: enter\n", __FUNCTION__)); - if (dhd) + if (dhd && dhd->pub.conf->suspend_mode == EARLY_SUSPEND) { dhd_suspend_resume_helper(dhd, 1, 0); + dhd_conf_set_suspend_resume(&dhd->pub, 1); + } } static void dhd_late_resume(struct early_suspend *h) @@ -2309,8 +2330,10 @@ static void dhd_late_resume(struct early_suspend *h) struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend); DHD_TRACE_HW4(("%s: enter\n", __FUNCTION__)); - if (dhd) + if (dhd && dhd->pub.conf->suspend_mode == EARLY_SUSPEND) { + dhd_conf_set_suspend_resume(&dhd->pub, 0); dhd_suspend_resume_helper(dhd, 0, 0); + } } #endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */ @@ -3565,6 +3588,8 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net) bcm_object_trace_opr(skb, BCM_OBJDBG_ADD_PKT, __FUNCTION__, __LINE__); + skb_orphan(skb); + /* re-align socket buffer if "skb->data" is odd address */ if (((unsigned long)(skb->data)) & 0x1) { unsigned char *data = skb->data; @@ -3824,13 +3849,13 @@ __dhd_txflowcontrol(dhd_pub_t *dhdp, struct net_device *net, bool state) netif_stop_queue(net); dhd_prot_update_pktid_txq_stop_cnt(dhdp); } else if (state == ON) { - DHD_ERROR(("%s: Netif Queue has already stopped\n", __FUNCTION__)); + DHD_INFO(("%s: Netif Queue has already stopped\n", __FUNCTION__)); } if ((state == OFF) && (dhdp->txoff == TRUE)) { netif_wake_queue(net); dhd_prot_update_pktid_txq_start_cnt(dhdp); } else if (state == OFF) { - DHD_ERROR(("%s: Netif Queue has already started\n", __FUNCTION__)); + DHD_INFO(("%s: Netif Queue has already started\n", __FUNCTION__)); } } @@ -4666,7 +4691,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) * logtrace_pkt_sendup is true */ if (event_type == WLC_E_TRACE) { - DHD_TRACE(("%s: WLC_E_TRACE\n", __FUNCTION__)); + DHD_EVENT(("%s: WLC_E_TRACE\n", __FUNCTION__)); dhd_event_logtrace_enqueue(dhdp, ifidx, pktbuf); continue; } @@ -4739,7 +4764,13 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) continue; } - if (dhdp->wl_event_enabled) { +#ifdef SENDPROB + if (dhdp->wl_event_enabled || + (dhdp->recv_probereq && (event.event_type == WLC_E_PROBREQ_MSG))) +#else + if (dhdp->wl_event_enabled) +#endif + { #ifdef DHD_USE_STATIC_CTRLBUF /* If event bufs are allocated via static buf pool * and wl events are enabled, make a copy, free the @@ -5503,8 +5534,8 @@ dhd_ethtool(dhd_info_t *dhd, void *uaddr) /* Copy out any request driver name */ if (copy_from_user(&info, uaddr, sizeof(info))) return -EFAULT; - strncpy(drvname, info.driver, sizeof(info.driver)); - drvname[sizeof(info.driver)-1] = '\0'; + strncpy(drvname, info.driver, sizeof(drvname) - 1); + drvname[sizeof(drvname) - 1] = '\0'; /* clear struct for return */ memset(&info, 0, sizeof(info)); @@ -6411,10 +6442,12 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) } } +#ifndef CONFIG_VTS_SUPPORT if (!capable(CAP_NET_ADMIN)) { bcmerror = BCME_EPERM; goto done; } +#endif /* Take backup of ioc.buf and restore later */ ioc_buf_user = ioc.buf; @@ -7213,6 +7246,17 @@ dhd_pri_open(struct net_device *net) /* Allow transmit calls */ netif_start_queue(net); DHD_ERROR(("[%s] tx queue started\n", net->name)); + +#if defined(SET_RPS_CPUS) + dhd_rps_cpus_enable(net, TRUE); + DHD_ERROR(("[%s] RPS started\n", net->name)); +#endif + +#if defined(SET_XPS_CPUS) + dhd_xps_cpus_enable(net, TRUE); + DHD_ERROR(("[%s] XPS started\n", net->name)); +#endif + return ret; } @@ -8433,7 +8477,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen #endif /* DHD_DEBUG */ #ifdef GET_CUSTOM_MAC_ENABLE - wifi_platform_get_mac_addr(dhd->adapter, hw_ether); + wifi_platform_get_mac_addr(dhd->adapter, hw_ether, iface_name); bcopy(hw_ether, dhd->pub.mac.octet, sizeof(struct ether_addr)); #endif /* GET_CUSTOM_MAC_ENABLE */ #ifdef CUSTOM_FORCE_NODFS_FLAG @@ -8492,7 +8536,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen len = strlen(if_name); ch = if_name[len - 1]; if ((ch > '9' || ch < '0') && (len < IFNAMSIZ - 2)) - strncat(if_name, "%d", 2); + strncat(if_name, "%d", IFNAMSIZ - len - 1); } /* Passing NULL to dngl_name to ensure host gets if_name in dngl_name member */ @@ -8911,6 +8955,10 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen dhd->dhd_state = dhd_state; dhd_found++; + +#ifdef CSI_SUPPORT + dhd_csi_init(&dhd->pub); +#endif /* CSI_SUPPORT */ #ifdef DHD_DUMP_MNGR dhd->pub.dump_file_manage = @@ -10072,7 +10120,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #ifdef GET_CUSTOM_MAC_ENABLE memset(hw_ether, 0, sizeof(hw_ether)); - ret = wifi_platform_get_mac_addr(dhd->info->adapter, hw_ether); + ret = wifi_platform_get_mac_addr(dhd->info->adapter, hw_ether, iface_name); #ifdef GET_CUSTOM_MAC_FROM_CONFIG if (!memcmp(ðer_null, &dhd->conf->hw_ether, ETHER_ADDR_LEN)) { ret = 0; @@ -10752,6 +10800,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #ifdef WL_ESCAN setbit(eventmask, WLC_E_ESCAN_RESULT); #endif /* WL_ESCAN */ +#ifdef CSI_SUPPORT + setbit(eventmask, WLC_E_CSI); +#endif /* CSI_SUPPORT */ #ifdef RTT_SUPPORT setbit(eventmask, WLC_E_PROXD); #endif /* RTT_SUPPORT */ @@ -10774,6 +10825,8 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) setbit(eventmask, WLC_E_TRACE); #else clrbit(eventmask, WLC_E_TRACE); + if (dhd->conf->chip == BCM43752_CHIP_ID) + setbit(eventmask, WLC_E_TRACE); #endif /* defined(SHOW_LOGTRACE) && defined(LOGTRACE_FROM_FILE) */ setbit(eventmask, WLC_E_CSA_COMPLETE_IND); @@ -10846,6 +10899,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #ifdef WL_MBO setbit(eventmask_msg->mask, WLC_E_MBO); #endif /* WL_MBO */ +#ifdef WL_CLIENT_SAE + setbit(eventmask_msg->mask, WLC_E_JOIN_START); +#endif /* WL_CLIENT_SAE */ #ifdef WL_BCNRECV setbit(eventmask_msg->mask, WLC_E_BCNRECV_ABORTED); #endif /* WL_BCNRECV */ @@ -11005,7 +11061,7 @@ 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 *ver_temp_buf = NULL, *ver_date_buf = NULL; int len; @@ -11045,11 +11101,13 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) /* query for 'wlc_ver' to get version info from firmware */ memset(&wlc_ver, 0, sizeof(wl_wlc_version_t)); - ret = dhd_iovar(dhd, 0, "wlc_ver", NULL, 0, (char *)&wlc_ver, + ret2 = dhd_iovar(dhd, 0, "wlc_ver", NULL, 0, (char *)&wlc_ver, sizeof(wl_wlc_version_t), FALSE); - if (ret < 0) - DHD_ERROR(("%s failed %d\n", __FUNCTION__, ret)); - else { + if (ret2 < 0) { + DHD_ERROR(("%s wlc_ver failed %d\n", __FUNCTION__, ret2)); + if (ret2 != BCME_UNSUPPORTED) + ret = ret2; + } else { dhd->wlc_ver_major = wlc_ver.wlc_ver_major; dhd->wlc_ver_minor = wlc_ver.wlc_ver_minor; } @@ -11835,17 +11893,9 @@ 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 - wl_ext_iapsta_attach_netdev(net, ifidx, ifp->bssidx); + wl_ext_iapsta_update_net_device(net, ifidx); #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__)); else @@ -11861,20 +11911,16 @@ 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); + wl_ext_event_attach_netdev(net, ifidx, ifp->bssidx); #ifdef WL_ESCAN - wl_escan_event_attach(net, dhdp); + wl_escan_event_attach(net, dhdp); #endif /* WL_ESCAN */ #ifdef WL_EXT_IAPSTA - 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_netdev(net, ifidx, ifp->bssidx); wl_ext_iapsta_attach_name(net, ifidx); #endif /* WL_EXT_IAPSTA */ +#endif /* WL_EXT_IAPSTA || USE_IW || WL_ESCAN */ printf("Register interface [%s] MAC: "MACDBG"\n\n", net->name, MAC2STRDBG(net->dev_addr)); @@ -11988,6 +12034,14 @@ void dhd_detach(dhd_pub_t *dhdp) if (dev) { rtnl_lock(); +#if defined(WL_CFG80211) && defined(WL_STATIC_IF) + if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) { + cfg = wl_get_cfg(dev); + if (cfg && cfg->static_ndev && (cfg->static_ndev->flags & IFF_UP)) { + dev_close(cfg->static_ndev); + } + } +#endif /* WL_CFG80211 && WL_STATIC_IF */ if (dev->flags & IFF_UP) { /* If IFF_UP is still up, it indicates that * "ifconfig wlan0 down" hasn't been called. @@ -12143,6 +12197,10 @@ void dhd_detach(dhd_pub_t *dhdp) MFREE(dhd->pub.osh, ifp, sizeof(*ifp)); dhd->iflist[0] = NULL; +#ifdef WL_CFG80211 + if (cfg && cfg->wdev) + cfg->wdev->netdev = NULL; +#endif } } @@ -12213,6 +12271,10 @@ void dhd_detach(dhd_pub_t *dhdp) } #endif /* DHD_LB */ +#ifdef CSI_SUPPORT + dhd_csi_deinit(dhdp); +#endif /* CSI_SUPPORT */ + #if defined(DNGL_AXI_ERROR_LOGGING) && defined(DHD_USE_WQ_FOR_DNGL_AXI_ERROR) cancel_work_sync(&dhd->axi_error_dispatcher_work); #endif /* DNGL_AXI_ERROR_LOGGING && DHD_USE_WQ_FOR_DNGL_AXI_ERROR */ @@ -13214,6 +13276,10 @@ dhd_get_wireless_stats(struct net_device *dev) return NULL; } + if (!(dev->flags & IFF_UP)) { + return NULL; + } + res = wl_iw_get_wireless_stats(dev, &dhd->iw.wstats); if (res == 0) @@ -13475,7 +13541,9 @@ int net_os_set_suspend(struct net_device *dev, int val, int force) int ret = 0; dhd_info_t *dhd = DHD_DEV_INFO(dev); - if (dhd) { + if (dhd && dhd->pub.conf->suspend_mode == EARLY_SUSPEND) { + if (!val) + dhd_conf_set_suspend_resume(&dhd->pub, val); #ifdef CONFIG_MACH_UNIVERSAL7420 #endif /* CONFIG_MACH_UNIVERSAL7420 */ #if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) @@ -13486,6 +13554,8 @@ int net_os_set_suspend(struct net_device *dev, int val, int force) #ifdef WL_CFG80211 wl_cfg80211_update_power_mode(dev); #endif // endif + if (val) + dhd_conf_set_suspend_resume(&dhd->pub, val); } return ret; } @@ -15480,7 +15550,7 @@ dhd_wait_pend8021x(struct net_device *dev) if (ntimes == 0) { atomic_set(&dhd->pend_8021x_cnt, 0); - DHD_ERROR(("%s: TIMEOUT\n", __FUNCTION__)); + WL_MSG(dev->name, "TIMEOUT\n"); } return pend; } @@ -18906,6 +18976,98 @@ int dhd_set_block_tdls_status(dhd_pub_t *dhdp, uint32 idx, int val) } #endif /* DHD_L2_FILTER */ +#if defined(SET_XPS_CPUS) +int dhd_xps_cpus_enable(struct net_device *net, int enable) +{ + dhd_info_t *dhd = DHD_DEV_INFO(net); + dhd_if_t *ifp; + int ifidx; + char * XPS_CPU_SETBUF; + + ifidx = dhd_net2idx(dhd, net); + if (ifidx == DHD_BAD_IF) { + DHD_ERROR(("%s bad ifidx\n", __FUNCTION__)); + return -ENODEV; + } + + if (ifidx == PRIMARY_INF) { + if (dhd->pub.op_mode == DHD_FLAG_IBSS_MODE) { + DHD_INFO(("%s : set for IBSS.\n", __FUNCTION__)); + XPS_CPU_SETBUF = RPS_CPUS_MASK_IBSS; + } else { + DHD_INFO(("%s : set for BSS.\n", __FUNCTION__)); + XPS_CPU_SETBUF = RPS_CPUS_MASK; + } + } else if (ifidx == VIRTUAL_INF) { + DHD_INFO(("%s : set for P2P.\n", __FUNCTION__)); + XPS_CPU_SETBUF = RPS_CPUS_MASK_P2P; + } else { + DHD_ERROR(("%s : Invalid index : %d.\n", __FUNCTION__, ifidx)); + return -EINVAL; + } + + ifp = dhd->iflist[ifidx]; + if (ifp) { + if (enable) { + DHD_INFO(("%s : set xps_cpus as [%s]\n", __FUNCTION__, XPS_CPU_SETBUF)); + custom_xps_map_set(ifp->net, XPS_CPU_SETBUF, strlen(XPS_CPU_SETBUF)); + } else { + custom_xps_map_clear(ifp->net); + } + } else { + DHD_ERROR(("%s : ifp is NULL!!\n", __FUNCTION__)); + return -ENODEV; + } + return BCME_OK; +} + +int custom_xps_map_set(struct net_device *net, char *buf, size_t len) +{ + cpumask_var_t mask; + int err; + + DHD_INFO(("%s : Entered.\n", __FUNCTION__)); + + if (!alloc_cpumask_var(&mask, GFP_KERNEL)) { + DHD_ERROR(("%s : alloc_cpumask_var fail.\n", __FUNCTION__)); + return -ENOMEM; + } + + err = bitmap_parse(buf, len, cpumask_bits(mask), nr_cpumask_bits); + if (err) { + free_cpumask_var(mask); + DHD_ERROR(("%s : bitmap_parse fail.\n", __FUNCTION__)); + return err; + } + + err = netif_set_xps_queue(net, mask, 0); + + free_cpumask_var(mask); + + if (0 == err) + DHD_ERROR(("%s : Done. mapping cpu\n", __FUNCTION__)); + + return err; +} + +void custom_xps_map_clear(struct net_device *net) +{ + struct xps_dev_maps *dev_maps; + + DHD_INFO(("%s : Entered.\n", __FUNCTION__)); + + rcu_read_lock(); + dev_maps = rcu_dereference(net->xps_maps); + rcu_read_unlock(); + + if (dev_maps) { + RCU_INIT_POINTER(net->xps_maps, NULL); + kfree_rcu(dev_maps, rcu); + DHD_INFO(("%s : xps_cpus map clear.\n", __FUNCTION__)); + } +} +#endif // endif + #if defined(SET_RPS_CPUS) int dhd_rps_cpus_enable(struct net_device *net, int enable) { @@ -19011,7 +19173,7 @@ int custom_rps_map_set(struct netdev_rx_queue *queue, char *buf, size_t len) } free_cpumask_var(mask); - DHD_INFO(("%s : Done. mapping cpu nummber : %d\n", __FUNCTION__, map->len)); + DHD_ERROR(("%s : Done. mapping cpu nummber : %d\n", __FUNCTION__, map->len)); return map->len; } diff --git a/bcmdhd.100.10.315.x/dhd_linux.h b/bcmdhd.100.10.315.x/dhd_linux.h index ae2b4e2..2f2097d 100644 --- a/bcmdhd.100.10.315.x/dhd_linux.h +++ b/bcmdhd.100.10.315.x/dhd_linux.h @@ -274,6 +274,7 @@ typedef struct wifi_adapter_info { #define WLAN_PLAT_NODFS_FLAG 0x01 #define WLAN_PLAT_AP_FLAG 0x02 +#if !defined(CONFIG_WIFI_CONTROL_FUNC) struct wifi_platform_data { #ifdef BUS_POWER_RESTORE int (*set_power)(int val, wifi_adapter_info_t *adapter); @@ -283,7 +284,11 @@ struct wifi_platform_data { int (*set_reset)(int val); int (*set_carddetect)(int val); void *(*mem_prealloc)(int section, unsigned long size); +#ifdef CUSTOM_MULTI_MAC + int (*get_mac_addr)(unsigned char *buf, char *name); +#else int (*get_mac_addr)(unsigned char *buf); +#endif #ifdef BCMSDIO int (*get_wake_irq)(void); #endif // endif @@ -293,6 +298,7 @@ struct wifi_platform_data { void *(*get_country_code)(char *ccode); #endif }; +#endif typedef struct bcmdhd_wifi_platdata { uint num_adapters; @@ -409,7 +415,7 @@ wifi_adapter_info_t* dhd_wifi_platform_get_adapter(uint32 bus_type, uint32 bus_n int wifi_platform_set_power(wifi_adapter_info_t *adapter, bool on, unsigned long msec); int wifi_platform_bus_enumerate(wifi_adapter_info_t *adapter, bool device_present); int wifi_platform_get_irq_number(wifi_adapter_info_t *adapter, unsigned long *irq_flags_ptr); -int wifi_platform_get_mac_addr(wifi_adapter_info_t *adapter, unsigned char *buf); +int wifi_platform_get_mac_addr(wifi_adapter_info_t *adapter, unsigned char *buf, char *name); #ifdef CUSTOM_COUNTRY_CODE void *wifi_platform_get_country_code(wifi_adapter_info_t *adapter, char *ccode, u32 flags); diff --git a/bcmdhd.100.10.315.x/dhd_linux_exportfs.c b/bcmdhd.100.10.315.x/dhd_linux_exportfs.c index 5e85bb3..fc9326d 100644 --- a/bcmdhd.100.10.315.x/dhd_linux_exportfs.c +++ b/bcmdhd.100.10.315.x/dhd_linux_exportfs.c @@ -36,6 +36,9 @@ #ifdef DHD_ADPS_BAM_EXPORT #include #endif // endif +#ifdef CSI_SUPPORT +#include +#endif /* CSI_SUPPORT */ #ifdef SHOW_LOGTRACE extern dhd_pub_t* g_dhd_pub; @@ -558,7 +561,7 @@ static struct dhd_attr dhd_attr_cntl_macaddr = #ifdef DHD_FW_COREDUMP -#define MEMDUMPINFO "/data/vendor/misc/wifi/.memdump.info" +#define MEMDUMPINFO "/data/misc/wifi/.memdump.info" uint32 get_mem_val_from_file(void) @@ -674,7 +677,7 @@ static struct dhd_attr dhd_attr_cntl_memdump = #endif /* DHD_FW_COREDUMP */ #ifdef BCMASSERT_LOG -#define ASSERTINFO "/data/vendor/misc/wifi/.assert.info" +#define ASSERTINFO "/data/misc/wifi/.assert.info" int get_assert_val_from_file(void) { @@ -1334,6 +1337,29 @@ static struct kobj_type dhd_cntl_file_ktype = { .default_attrs = control_file_attrs, }; +#ifdef CSI_SUPPORT +/* Function to show current ccode */ +static ssize_t read_csi_data(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) +{ + dhd_info_t *dhd = to_dhd(kobj); + int n = 0; + + n = dhd_csi_dump_list(&dhd->pub, buf); + DHD_INFO(("Dump data to file, size %d\n", n)); + dhd_csi_clean_list(&dhd->pub); + + return n; +} + +static struct bin_attribute dhd_attr_csi = { + .attr = { .name = "csi", + .mode = 0660, }, + .size = MAX_CSI_FILESZ, + .read = read_csi_data, +}; +#endif /* CSI_SUPPORT */ + /* Create a kobject and attach to sysfs interface */ int dhd_sysfs_init(dhd_info_t *dhd) { @@ -1358,6 +1384,15 @@ int dhd_sysfs_init(dhd_info_t *dhd) return ret; } +#ifdef CSI_SUPPORT + ret = sysfs_create_bin_file(&dhd->dhd_kobj, &dhd_attr_csi); + if (ret) { + DHD_ERROR(("%s: can't create %s\n", __FUNCTION__, dhd_attr_csi.attr.name)); + kobject_put(&dhd->dhd_kobj); + return ret; + } +#endif /* CSI_SUPPORT */ + /* * We are always responsible for sending the uevent that the kobject * was added to the system. diff --git a/bcmdhd.100.10.315.x/dhd_linux_pktdump.c b/bcmdhd.100.10.315.x/dhd_linux_pktdump.c index 254d696..aa68570 100644 --- a/bcmdhd.100.10.315.x/dhd_linux_pktdump.c +++ b/bcmdhd.100.10.315.x/dhd_linux_pktdump.c @@ -44,8 +44,8 @@ #include #include -#define DHD_PKTDUMP(arg) DHD_ERROR(arg) -#define DHD_PKTDUMP_MEM(arg) DHD_ERROR(arg) +#define DHD_PKTDUMP(arg) printk arg +#define DHD_PKTDUMP_MEM(arg) printk arg #define PACKED_STRUCT __attribute__ ((packed)) #define EAPOL_HDR_LEN 4 @@ -161,6 +161,7 @@ typedef struct pkt_cnt_log { #define PKT_CNT_RSN_VALID(rsn) \ (((rsn) > (PKT_CNT_RSN_INVALID)) && ((rsn) < (PKT_CNT_RSN_MAX))) +#ifdef DHD_PKTDUMP_ROAM static const char pkt_cnt_msg[][20] = { "INVALID", "ROAM_SUCCESS", @@ -168,6 +169,7 @@ static const char pkt_cnt_msg[][20] = { "CONNECT_SUCCESS", "INVALID" }; +#endif static const char tx_pktfate[][30] = { "TX_PKT_FATE_ACKED", /* 0: WLFC_CTL_PKTFLAG_DISCARD */ @@ -197,60 +199,78 @@ static const char tx_pktfate[][30] = { #define TX_FATE(fate) ((fate) ? (TX_FATE_STR(fate)) : "N/A") #define TX_FATE_ACKED(fate) ((fate) ? ((*fate) == (WLFC_CTL_PKTFLAG_DISCARD)) : (0)) -#define EAP_PRINT(str) \ +#define EAP_PRINT(x, args...) \ do { \ - if (tx) { \ - DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [TX]: " \ - str TXFATE_FMT "\n", ifname, \ - TX_PKTHASH(pkthash), TX_FATE(pktfate))); \ - } else { \ - DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [RX]: " \ - str "\n", ifname)); \ + if (dump_msg_level & DUMP_EAPOL_VAL) { \ + if (tx) { \ + DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [TX] : (%s) %s (%s)"TXFATE_FMT"\n", \ + ifname, ## args, \ + tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \ + TX_PKTHASH(pkthash), TX_FATE(pktfate))); \ + } else { \ + DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [RX] : (%s) %s (%s)\n", \ + ifname, ## args, \ + tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf)); \ + } \ } \ } while (0) -#define EAP_PRINT_REPLAY(str) \ +#define EAP_PRINT_REPLAY(x, args...) \ do { \ - if (tx) { \ - DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [TX]: " \ - str DBGREPLAY TXFATE_FMT "\n", ifname, \ - REPLAY_FMT(eap_key), TX_PKTHASH(pkthash), \ - TX_FATE(pktfate))); \ - } else { \ - DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [RX]: " \ - str DBGREPLAY "\n", ifname, \ - REPLAY_FMT(eap_key))); \ + if (dump_msg_level & DUMP_EAPOL_VAL) { \ + if (tx) { \ + DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [TX] : (%s) %s (%s)"DBGREPLAY TXFATE_FMT"\n", \ + ifname, ## args, \ + tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \ + REPLAY_FMT(eap_key), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \ + } else { \ + DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [RX] : (%s) %s (%s)"DBGREPLAY"\n", \ + ifname, ## args, \ + tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \ + REPLAY_FMT(eap_key))); \ + } \ } \ } while (0) -#define EAP_PRINT_OTHER(str) \ +#define EAP_PRINT_OTHER(x, args...) \ do { \ - if (tx) { \ - DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [TX]: " \ - str "ver %d, type %d" TXFATE_FMT "\n", ifname, \ - eapol_hdr->version, eapol_hdr->type, \ - TX_PKTHASH(pkthash), TX_FATE(pktfate))); \ - } else { \ - DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [RX]: " \ - str "ver %d, type %d\n", ifname, \ - eapol_hdr->version, eapol_hdr->type)); \ + if (dump_msg_level & DUMP_EAPOL_VAL) { \ + if (tx) { \ + DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [TX] : (%s) %s (%s) " \ + "ver %d, type %d"TXFATE_FMT"\n", \ + ifname, ## args, \ + tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \ + eapol_hdr->version, eapol_hdr->type, \ + TX_PKTHASH(pkthash), TX_FATE(pktfate))); \ + } else { \ + DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [RX] : (%s) %s (%s) " \ + "ver %d, type %d\n", \ + ifname, ## args, \ + tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \ + eapol_hdr->version, eapol_hdr->type)); \ + } \ } \ } while (0) -#define EAP_PRINT_OTHER_4WAY(str) \ +#define EAP_PRINT_OTHER_4WAY(x, args...) \ do { \ - if (tx) { \ - DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [TX]: " str \ - "ver %d type %d keytype %d keyinfo 0x%02X" \ - TXFATE_FMT "\n", ifname, eapol_hdr->version, \ - eapol_hdr->type, eap_key->type, \ - (uint32)hton16(eap_key->key_info), \ - TX_PKTHASH(pkthash), TX_FATE(pktfate))); \ - } else { \ - DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [RX]: " str \ - "ver %d type %d keytype %d keyinfo 0x%02X\n", \ - ifname, eapol_hdr->version, eapol_hdr->type, \ - eap_key->type, (uint32)hton16(eap_key->key_info))); \ + if (dump_msg_level & DUMP_EAPOL_VAL) { \ + if (tx) { \ + DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [TX] : (%s) %s (%s) " \ + "ver %d type %d keytype %d keyinfo 0x%02X"TXFATE_FMT"\n", \ + ifname, ## args, \ + tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \ + eapol_hdr->version, eapol_hdr->type, eap_key->type, \ + (uint32)hton16(eap_key->key_info), \ + TX_PKTHASH(pkthash), TX_FATE(pktfate))); \ + } else { \ + DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [RX] : (%s) %s (%s) " \ + "ver %d type %d keytype %d keyinfo 0x%02X\n", \ + ifname, ## args, \ + tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \ + eapol_hdr->version, eapol_hdr->type, eap_key->type, \ + (uint32)hton16(eap_key->key_info))); \ + } \ } \ } while (0) @@ -551,6 +571,8 @@ dhd_dump_wsc_message(dhd_pub_t *dhd, int ifidx, uint8 *pktdata, char *ifname; uint16 eap_len; bool cond; + char seabuf[ETHER_ADDR_STR_LEN]=""; + char deabuf[ETHER_ADDR_STR_LEN]=""; if (!pktdata) { DHD_ERROR(("%s: pktdata is NULL\n", __FUNCTION__)); @@ -562,6 +584,9 @@ dhd_dump_wsc_message(dhd_pub_t *dhd, int ifidx, uint8 *pktdata, return; } + bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf); + bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf); + eapol_hdr = (eapol_header_t *)pktdata; eap_hdr = (eap_header_fmt_t *)(eapol_hdr->body); if (eap_hdr->type != EAP_TYPE_EXP) { @@ -660,12 +685,17 @@ dhd_dump_eap_packet(dhd_pub_t *dhd, int ifidx, uint8 *pktdata, eap_header_fmt_t *eap_hdr; char *ifname; bool cond; + char seabuf[ETHER_ADDR_STR_LEN]=""; + char deabuf[ETHER_ADDR_STR_LEN]=""; if (!pktdata) { DHD_PKTDUMP(("%s: pktdata is NULL\n", __FUNCTION__)); return; } + bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf); + bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf); + eapol_hdr = (eapol_header_t *)pktdata; eap_hdr = (eap_header_fmt_t *)(eapol_hdr->body); ifname = dhd_ifname(dhd, ifidx); @@ -783,12 +813,17 @@ dhd_dump_eapol_4way_message(dhd_pub_t *dhd, int ifidx, uint8 *pktdata, bool tx, msg_eapol_t type; char *ifname; bool cond; + char seabuf[ETHER_ADDR_STR_LEN]=""; + char deabuf[ETHER_ADDR_STR_LEN]=""; if (!pktdata) { DHD_PKTDUMP(("%s: pktdata is NULL\n", __FUNCTION__)); return; } + bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf); + bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf); + type = dhd_is_4way_msg(pktdata); ifname = dhd_ifname(dhd, ifidx); eapol_hdr = (eapol_header_t *)pktdata; @@ -846,12 +881,17 @@ dhd_dump_eapol_message(dhd_pub_t *dhd, int ifidx, uint8 *pktdata, char *ifname; eapol_header_t *eapol_hdr = (eapol_header_t *)pktdata; bool cond; + char seabuf[ETHER_ADDR_STR_LEN]=""; + char deabuf[ETHER_ADDR_STR_LEN]=""; if (!pktdata) { DHD_ERROR(("%s: pktdata is NULL\n", __FUNCTION__)); return; } + bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf); + bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf); + eapol_hdr = (eapol_header_t *)pktdata; ifname = dhd_ifname(dhd, ifidx); cond = (tx && pktfate) ? FALSE : TRUE; @@ -891,12 +931,14 @@ dhd_dump_eapol_message(dhd_pub_t *dhd, int ifidx, uint8 *pktdata, #define DHCP_PRINT(str) \ do { \ if (tx) { \ - DHD_PKTDUMP(("[dhd-%s] "str " %s[%s] [TX] -" TXFATE_FMT "\n", \ - ifname, typestr, opstr, \ + DHD_PKTDUMP(("[dhd-%s] " str " %8s[%8s] [TX] : %s(%s) %s %s(%s)"TXFATE_FMT"\n", \ + ifname, typestr, opstr, tx?sabuf:dabuf, tx?seabuf:deabuf, \ + tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \ TX_PKTHASH(pkthash), TX_FATE(pktfate))); \ } else { \ - DHD_PKTDUMP(("[dhd-%s] "str" %s[%s] [RX]\n", \ - ifname, typestr, opstr)); \ + DHD_PKTDUMP(("[dhd-%s] " str " %8s[%8s] [RX] : %s(%s) %s %s(%s)\n", \ + ifname, typestr, opstr, tx?sabuf:dabuf, tx?seabuf:deabuf, \ + tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf)); \ } \ } while (0) @@ -944,6 +986,12 @@ dhd_dhcp_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, bool tx, int dhcp_type = 0, len, opt_len; char *ifname = NULL, *typestr = NULL, *opstr = NULL; bool cond; + 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 ((IPV4_HLEN(iph) < IPV4_HLEN_MIN) || @@ -964,6 +1012,10 @@ dhd_dhcp_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, bool tx, if (ntohs(iph->tot_len) < ntohs(b->udph.len) + sizeof(struct bcmudp_hdr)) { return; } + bcm_ip_ntoa((struct ipv4_addr *)iph->src_ip, sabuf); + bcm_ip_ntoa((struct ipv4_addr *)iph->dst_ip, dabuf); + bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf); + bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf); ifname = dhd_ifname(dhdp, ifidx); cond = (tx && pktfate) ? FALSE : TRUE; @@ -1008,7 +1060,7 @@ dhd_dhcp_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, bool tx, do { \ if (tx) { \ DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s) SEQNUM=%d" \ - TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \ + TXFATE_FMT"\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \ tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, seqnum, \ TX_PKTHASH(pkthash), TX_FATE(pktfate))); \ } else { \ @@ -1046,6 +1098,9 @@ dhd_icmp_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, bool tx, char seabuf[ETHER_ADDR_STR_LEN]=""; char deabuf[ETHER_ADDR_STR_LEN]=""; + if (!(dump_msg_level & DUMP_ICMP_VAL)) + return; + /* check IP header */ if ((IPV4_HLEN(iph) < IPV4_HLEN_MIN) || IP_VER(iph) != IP_VER_4 || @@ -1091,12 +1146,12 @@ dhd_icmp_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, bool tx, do { \ if (tx) { \ if (dump_enabled && pktfate && !TX_FATE_ACKED(pktfate)) { \ - DHD_PKTDUMP(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s)" TXFATE_FMT "\n", \ + DHD_PKTDUMP(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s)"TXFATE_FMT"\n", \ ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \ tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \ TX_PKTHASH(pkthash), TX_FATE(pktfate))); \ } else { \ - DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s)" TXFATE_FMT "\n", \ + DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s)"TXFATE_FMT"\n", \ ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \ tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \ TX_PKTHASH(pkthash), TX_FATE(pktfate))); \ @@ -1112,18 +1167,20 @@ dhd_icmp_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, bool tx, do { \ if (tx) { \ if (dump_enabled && pktfate && !TX_FATE_ACKED(pktfate)) { \ - DHD_PKTDUMP(("[dhd-%s] "str " [TX] op_code=%d" \ - TXFATE_FMT "\n", ifname, opcode, \ - TX_PKTHASH(pkthash), \ - TX_FATE(pktfate))); \ + DHD_PKTDUMP(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s) op_code=%d" \ + TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \ + tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, opcode, \ + TX_PKTHASH(pkthash), TX_FATE(pktfate))); \ } else { \ - DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] op_code=%d" \ - TXFATE_FMT "\n", ifname, opcode, \ + DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s) op_code=%d" \ + TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \ + tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, opcode, \ TX_PKTHASH(pkthash), TX_FATE(pktfate))); \ } \ } else { \ - DHD_PKTDUMP_MEM(("[dhd-%s] "str " [RX] op_code=%d\n", \ - ifname, opcode)); \ + DHD_PKTDUMP_MEM(("[dhd-%s] "str " [RX] : %s(%s) %s %s(%s) op_code=%d\n", \ + ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \ + tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, opcode)); \ } \ } while (0) @@ -1140,6 +1197,9 @@ dhd_arp_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, bool tx, 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 || @@ -1206,17 +1266,20 @@ static const char dns_opcode_types[][11] = { do { \ if (tx) { \ if (dump_enabled && pktfate && !TX_FATE_ACKED(pktfate)) { \ - DHD_PKTDUMP(("[dhd-%s] "str " [TX] ID:0x%04X OPCODE:%s" \ - TXFATE_FMT "\n", ifname, id, DNSOPCODE(opcode), \ - TX_PKTHASH(pkthash), TX_FATE(pktfate))); \ + DHD_PKTDUMP(("[dhd-%s] " str " [TX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s" \ + TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \ + tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \ + id, DNSOPCODE(opcode), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \ } else { \ - DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] ID:0x%04X OPCODE:%s" \ - TXFATE_FMT "\n", ifname, id, DNSOPCODE(opcode), \ - TX_PKTHASH(pkthash), TX_FATE(pktfate))); \ + DHD_PKTDUMP_MEM(("[dhd-%s] " str " [TX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s" \ + TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \ + tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \ + id, DNSOPCODE(opcode), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \ } \ } else { \ - DHD_PKTDUMP_MEM(("[dhd-%s] "str " [RX] ID:0x%04X OPCODE:%s\n", \ - ifname, id, DNSOPCODE(opcode))); \ + DHD_PKTDUMP_MEM(("[dhd-%s] " str " [RX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s\n", \ + ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, tx?"->":"<-", \ + tx?dabuf:sabuf, tx?deabuf:seabuf, id, DNSOPCODE(opcode))); \ } \ } while (0) @@ -1224,19 +1287,21 @@ static const char dns_opcode_types[][11] = { do { \ if (tx) { \ if (dump_enabled && pktfate && !TX_FATE_ACKED(pktfate)) { \ - DHD_PKTDUMP(("[dhd-%s] "str " [TX] ID:0x%04X OPCODE:%s RCODE:%d" \ - TXFATE_FMT "\n", ifname, id, DNSOPCODE(opcode), \ - GET_DNS_RCODE(flags), TX_PKTHASH(pkthash), \ - TX_FATE(pktfate))); \ + DHD_PKTDUMP(("[dhd-%s] " str " [TX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s RCODE:%d" \ + TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \ + tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, id, DNSOPCODE(opcode), \ + GET_DNS_RCODE(flags), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \ } else { \ - DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] ID:0x%04X OPCODE:%s RCODE:%d" \ - TXFATE_FMT "\n", ifname, id, DNSOPCODE(opcode), \ - GET_DNS_RCODE(flags), TX_PKTHASH(pkthash), \ - TX_FATE(pktfate))); \ + DHD_PKTDUMP_MEM(("[dhd-%s] " str " [TX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s RCODE:%d" \ + TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \ + tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, id, DNSOPCODE(opcode), \ + GET_DNS_RCODE(flags), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \ } \ } else { \ - DHD_PKTDUMP_MEM(("[dhd-%s] "str " [RX] ID:0x%04X OPCODE:%s RCODE:%d\n", \ - ifname, id, DNSOPCODE(opcode), GET_DNS_RCODE(flags))); \ + DHD_PKTDUMP_MEM(("[dhd-%s] " str " [RX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s RCODE:%d\n", \ + ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \ + tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \ + id, DNSOPCODE(opcode), GET_DNS_RCODE(flags))); \ } \ } while (0) @@ -1249,6 +1314,12 @@ dhd_dns_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, bool tx, uint16 flags, opcode, id; char *ifname; bool cond, dump_enabled; + char sabuf[20]="", dabuf[20]=""; + char seabuf[ETHER_ADDR_STR_LEN]=""; + char deabuf[ETHER_ADDR_STR_LEN]=""; + + if (!(dump_msg_level & DUMP_DNS_VAL)) + return; /* check IP header */ if ((IPV4_HLEN(iph) < IPV4_HLEN_MIN) || @@ -1275,6 +1346,10 @@ dhd_dns_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, bool tx, flags = hton16(dnsh->flags); opcode = GET_DNS_OPCODE(flags); id = hton16(dnsh->id); + bcm_ip_ntoa((struct ipv4_addr *)iph->src_ip, sabuf); + bcm_ip_ntoa((struct ipv4_addr *)iph->dst_ip, dabuf); + bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf); + bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf); if (GET_DNS_QR(flags)) { /* Response */ DHD_STATLOG_DATA(dhdp, ST(DNS_RESP), ifidx, tx, cond); @@ -1299,6 +1374,9 @@ dhd_trx_pkt_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, uint32 pktlen, bool uint16 protocol; char *pkttype = "UNKNOWN"; + if (!(dump_msg_level & DUMP_TRX_VAL)) + return; + if (!dhdp) { DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__)); return; diff --git a/bcmdhd.100.10.315.x/dhd_linux_platdev.c b/bcmdhd.100.10.315.x/dhd_linux_platdev.c index b483911..7ceaa40 100644 --- a/bcmdhd.100.10.315.x/dhd_linux_platdev.c +++ b/bcmdhd.100.10.315.x/dhd_linux_platdev.c @@ -282,7 +282,8 @@ int wifi_platform_bus_enumerate(wifi_adapter_info_t *adapter, bool device_presen } -int wifi_platform_get_mac_addr(wifi_adapter_info_t *adapter, unsigned char *buf) +int wifi_platform_get_mac_addr(wifi_adapter_info_t *adapter, unsigned char *buf, + char *name) { struct wifi_platform_data *plat_data; @@ -291,7 +292,11 @@ int wifi_platform_get_mac_addr(wifi_adapter_info_t *adapter, unsigned char *buf) return -EINVAL; plat_data = adapter->wifi_plat_data; if (plat_data->get_mac_addr) { +#ifdef CUSTOM_MULTI_MAC + return plat_data->get_mac_addr(buf, name); +#else return plat_data->get_mac_addr(buf); +#endif } return -EOPNOTSUPP; } @@ -339,8 +344,11 @@ static int wifi_plat_dev_drv_probe(struct platform_device *pdev) ASSERT(dhd_wifi_platdata != NULL); ASSERT(dhd_wifi_platdata->num_adapters == 1); adapter = &dhd_wifi_platdata->adapters[0]; +#if defined(CONFIG_WIFI_CONTROL_FUNC) + adapter->wifi_plat_data = (struct wifi_platform_data *)(pdev->dev.platform_data); +#else adapter->wifi_plat_data = (void *)&dhd_wlan_control; -// adapter->wifi_plat_data = (struct wifi_platform_data *)(pdev->dev.platform_data); +#endif resource = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcmdhd_wlan_irq"); if (resource == NULL) diff --git a/bcmdhd.100.10.315.x/dhd_msgbuf.c b/bcmdhd.100.10.315.x/dhd_msgbuf.c index 33ceb5a..41e8830 100644 --- a/bcmdhd.100.10.315.x/dhd_msgbuf.c +++ b/bcmdhd.100.10.315.x/dhd_msgbuf.c @@ -7575,7 +7575,6 @@ dhd_msgbuf_iovar_timeout_dump(dhd_pub_t *dhd) if (prot->curr_ioctl_cmd == WLC_SET_VAR || prot->curr_ioctl_cmd == WLC_GET_VAR) { char iovbuf[32]; - int i; int dump_size = 128; uint8 *ioctl_buf = (uint8 *)prot->ioctbuf.va; memset(iovbuf, 0, sizeof(iovbuf)); @@ -7585,12 +7584,7 @@ dhd_msgbuf_iovar_timeout_dump(dhd_pub_t *dhd) prot->curr_ioctl_cmd == WLC_SET_VAR ? "WLC_SET_VAR" : "WLC_GET_VAR", iovbuf)); DHD_ERROR(("========== START IOCTL REQBUF DUMP ==========\n")); - for (i = 0; i < dump_size; i++) { - DHD_ERROR(("%02X ", ioctl_buf[i])); - if ((i % 32) == 31) { - DHD_ERROR(("\n")); - } - } + prhex("ioctl_buf", (const u8 *) ioctl_buf, dump_size); DHD_ERROR(("\n========== END IOCTL REQBUF DUMP ==========\n")); } diff --git a/bcmdhd.100.10.315.x/dhd_pcie.c b/bcmdhd.100.10.315.x/dhd_pcie.c index de29e2d..ff69b13 100644 --- a/bcmdhd.100.10.315.x/dhd_pcie.c +++ b/bcmdhd.100.10.315.x/dhd_pcie.c @@ -605,13 +605,12 @@ dhd_bus_pcie_pwr_req_nolock(struct dhd_bus *bus) bool dhdpcie_chip_support_msi(dhd_bus_t *bus) { - DHD_ERROR(("%s: buscorerev=%d chipid=0x%x\n", + DHD_INFO(("%s: buscorerev=%d chipid=0x%x\n", __FUNCTION__, bus->sih->buscorerev, si_chipid(bus->sih))); if (bus->sih->buscorerev <= 14 || si_chipid(bus->sih) == BCM4375_CHIP_ID || si_chipid(bus->sih) == BCM4362_CHIP_ID || si_chipid(bus->sih) == BCM43751_CHIP_ID || - si_chipid(bus->sih) == BCM43752_CHIP_ID || si_chipid(bus->sih) == BCM4361_CHIP_ID || si_chipid(bus->sih) == BCM4359_CHIP_ID) { return FALSE; @@ -2807,7 +2806,7 @@ dhdpcie_download_firmware(struct dhd_bus *bus, osl_t *osh) DHD_OS_WAKE_LOCK(bus->dhd); - dhd_conf_set_path_params(bus->dhd, NULL, NULL, bus->fw_path, bus->nv_path); + dhd_conf_set_path_params(bus->dhd, bus->fw_path, bus->nv_path); dhd_set_bus_params(bus); ret = _dhdpcie_download_firmware(bus); diff --git a/bcmdhd.100.10.315.x/dhd_pcie_linux.c b/bcmdhd.100.10.315.x/dhd_pcie_linux.c index 08d3776..701f975 100644 --- a/bcmdhd.100.10.315.x/dhd_pcie_linux.c +++ b/bcmdhd.100.10.315.x/dhd_pcie_linux.c @@ -1498,6 +1498,11 @@ dhdpcie_request_irq(dhdpcie_info_t *dhdpcie_info) } } + if (bus->d2h_intr_method == PCIE_MSI) + printf("%s: MSI enabled\n", __FUNCTION__); + else + printf("%s: INTx enabled\n", __FUNCTION__); + if (request_irq(pdev->irq, dhdpcie_isr, IRQF_SHARED, dhdpcie_info->pciname, bus) < 0) { DHD_ERROR(("%s: request_irq() failed\n", __FUNCTION__)); @@ -1824,8 +1829,11 @@ int dhdpcie_init(struct pci_dev *pdev) if (bus->dev->bus) { /* self member of structure pci_bus is bridge device as seen by parent */ bus->rc_dev = bus->dev->bus->self; - DHD_ERROR(("%s: rc_dev from dev->bus->self (%x:%x) is %pK\n", __FUNCTION__, - bus->rc_dev->vendor, bus->rc_dev->device, bus->rc_dev)); + if (bus->rc_dev) + DHD_ERROR(("%s: rc_dev from dev->bus->self (%x:%x) is %pK\n", __FUNCTION__, + bus->rc_dev->vendor, bus->rc_dev->device, bus->rc_dev)); + else + DHD_ERROR(("%s: bus->dev->bus->self is NULL\n", __FUNCTION__)); } else { DHD_ERROR(("%s: unable to get rc_dev as dev->bus is NULL\n", __FUNCTION__)); } @@ -2541,7 +2549,7 @@ int dhdpcie_oob_intr_register(dhd_bus_t *bus) dhdpcie_osinfo->oob_irq_registered = TRUE; - return err; + return 0; } void dhdpcie_oob_intr_unregister(dhd_bus_t *bus) diff --git a/bcmdhd.100.10.315.x/dhd_pno.c b/bcmdhd.100.10.315.x/dhd_pno.c index 390fb81..6bb2fa4 100644 --- a/bcmdhd.100.10.315.x/dhd_pno.c +++ b/bcmdhd.100.10.315.x/dhd_pno.c @@ -3090,7 +3090,7 @@ _dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason) STATIC_ASSERT(sizeof(wl_pfn_net_info_v1_t) == sizeof(wl_pfn_net_info_v2_t)); STATIC_ASSERT(sizeof(wl_pfn_lnet_info_v1_t) == sizeof(wl_pfn_lnet_info_v2_t)); STATIC_ASSERT(sizeof(wl_pfn_subnet_info_v1_t) == sizeof(wl_pfn_subnet_info_v2_t)); - STATIC_ASSERT(OFFSETOF(wl_pfn_subnet_info_v1_t, SSID) == + ASSERT(OFFSETOF(wl_pfn_subnet_info_v1_t, SSID) == OFFSETOF(wl_pfn_subnet_info_v2_t, u.SSID)); DHD_PNO(("%s enter\n", __FUNCTION__)); diff --git a/bcmdhd.100.10.315.x/dhd_sdio.c b/bcmdhd.100.10.315.x/dhd_sdio.c index 46c55fe..b1281e0 100644 --- a/bcmdhd.100.10.315.x/dhd_sdio.c +++ b/bcmdhd.100.10.315.x/dhd_sdio.c @@ -449,6 +449,9 @@ typedef struct dhd_bus { uint txglomframes; /* Number of tx glom frames (superframes) */ uint txglompkts; /* Number of packets from tx glom frames */ uint8 *membuf; /* Buffer for dhdsdio_membytes */ +#ifdef CONSOLE_DPC + char cons_cmd[16]; +#endif } dhd_bus_t; /* @@ -7085,6 +7088,12 @@ clkwait: if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) dhdsdio_sendpendctl(bus); +#ifdef CONSOLE_DPC + else if (DATAOK(bus) && strlen(bus->cons_cmd) && (bus->clkstate == CLK_AVAIL) && + !bus->fcstate) { + dhd_bus_console_in(bus->dhd, bus->cons_cmd, strlen(bus->cons_cmd)); + } +#endif /* Send queued frames (limit 1 if rx may still be pending) */ else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate && @@ -7846,23 +7855,36 @@ dhd_bus_console_in(dhd_pub_t *dhdp, uchar *msg, uint msglen) int rv; void *pkt; - /* Address could be zero if CONSOLE := 0 in dongle Makefile */ - if (bus->console_addr == 0) - return BCME_UNSUPPORTED; - +#ifndef CONSOLE_DPC /* Exclusive bus access */ dhd_os_sdlock(bus->dhd); +#endif + + /* Address could be zero if CONSOLE := 0 in dongle Makefile */ + if (bus->console_addr == 0) { + rv = BCME_UNSUPPORTED; + goto exit; + } /* Don't allow input if dongle is in reset */ if (bus->dhd->dongle_reset) { - dhd_os_sdunlock(bus->dhd); - return BCME_NOTREADY; + rv = BCME_NOTREADY; + goto exit; + } + +#ifndef CONSOLE_DPC + 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_n_pkts_tot(&bus->txq))); + rv = BCME_NOTREADY; + goto exit; } /* Request clock to allow SDIO accesses */ BUS_WAKE(bus); /* No pend allowed since txpkt is called later, ht clk has to be on */ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); +#endif /* Zero cbuf_index */ addr = bus->console_addr + OFFSETOF(hnd_cons_t, cbuf_idx); @@ -7881,11 +7903,6 @@ 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)) { - rv = BCME_NOTREADY; - goto done; - } - /* Bump dongle by sending an empty packet on the event channel. * sdpcm_sendup (RX) checks for virtual console input. */ @@ -7893,18 +7910,72 @@ dhd_bus_console_in(dhd_pub_t *dhdp, uchar *msg, uint msglen) rv = dhdsdio_txpkt(bus, SDPCM_EVENT_CHANNEL, &pkt, 1, TRUE); done: +#ifndef CONSOLE_DPC if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched && NO_OTHER_ACTIVE_BUS_USER(bus)) { bus->activity = FALSE; dhdsdio_bussleep(bus, TRUE); dhdsdio_clkctl(bus, CLK_NONE, FALSE); } +#endif +exit: +#ifdef CONSOLE_DPC + memset(bus->cons_cmd, 0, sizeof(bus->cons_cmd)); +#else dhd_os_sdunlock(bus->dhd); - +#endif return rv; } +#ifdef CONSOLE_DPC +extern int +dhd_bus_txcons(dhd_pub_t *dhdp, uchar *msg, uint msglen) +{ + dhd_bus_t *bus = dhdp->bus; + int ret = BCME_OK; + + dhd_os_sdlock(bus->dhd); + + /* Address could be zero if CONSOLE := 0 in dongle Makefile */ + if (bus->console_addr == 0) { + ret = BCME_UNSUPPORTED; + goto exit; + } + + /* Don't allow input if dongle is in reset */ + if (bus->dhd->dongle_reset) { + ret = BCME_NOTREADY; + goto exit; + } + + if (msglen >= sizeof(bus->cons_cmd)) { + DHD_ERROR(("%s: \"%s\"(%d) too long\n", __FUNCTION__, msg, msglen)); + ret = BCME_BADARG; + goto exit; + } + + if (!strlen(bus->cons_cmd)) { + strncpy(bus->cons_cmd, msg, sizeof(bus->cons_cmd)); + DHD_CTL(("%s: \"%s\" delay send, tx_max %d, tx_seq %d, pktq_len %d\n", + __FUNCTION__, bus->cons_cmd, bus->tx_max, bus->tx_seq, pktq_n_pkts_tot(&bus->txq))); + if (!bus->dpc_sched) { + bus->dpc_sched = TRUE; + dhd_sched_dpc(bus->dhd); + } + } else { + DHD_CTL(("%s: \"%s\" is pending, tx_max %d, tx_seq %d, pktq_len %d\n", + __FUNCTION__, bus->cons_cmd, bus->tx_max, bus->tx_seq, pktq_n_pkts_tot(&bus->txq))); + ret = BCME_NOTREADY; + } + +exit: + dhd_os_sdunlock(bus->dhd); + + return ret; +} +#endif + #if defined(DHD_DEBUG) && !defined(BCMSDIOLITE) static void dhd_dump_cis(uint fn, uint8 *cis) @@ -7999,9 +8070,6 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, { int ret; dhd_bus_t *bus; -#ifdef GET_OTP_MAC_ENABLE - struct ether_addr ea_addr; -#endif DHD_MUTEX_LOCK(); @@ -8107,6 +8175,10 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, goto fail; } +#if defined(GET_OTP_MAC_ENABLE) || defined(GET_OTP_MODULE_NAME) + dhd_conf_get_otp(bus->dhd, sdh, bus->sih); +#endif + /* Allocate buffers */ if (!(dhdsdio_probe_malloc(bus, osh, sdh))) { DHD_ERROR(("%s: dhdsdio_probe_malloc failed\n", __FUNCTION__)); @@ -8165,10 +8237,8 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, #endif /* BT_OVER_SDIO */ #ifdef GET_OTP_MAC_ENABLE - if (dhd_conf_get_mac(bus->dhd, sdh, bus->sih, ea_addr.octet)) { - DHD_TRACE(("%s: Can not read MAC address\n", __FUNCTION__)); - } else - memcpy(bus->dhd->mac.octet, (void *)&ea_addr, ETHER_ADDR_LEN); + if (memcmp(ðer_null, &bus->dhd->conf->otp_mac, ETHER_ADDR_LEN)) + memcpy(bus->dhd->mac.octet, (void *)&bus->dhd->conf->otp_mac, ETHER_ADDR_LEN); #endif /* GET_CUSTOM_MAC_ENABLE */ /* Ok, have the per-port tell the stack we're open for business */ @@ -8697,12 +8767,12 @@ dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh) __FUNCTION__, bus->fw_path, bus->nv_path)); DHD_OS_WAKE_LOCK(bus->dhd); + dhd_conf_set_path_params(bus->dhd, bus->fw_path, bus->nv_path); + dhd_set_bus_params(bus); + /* Download the firmware */ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); - dhd_conf_set_path_params(bus->dhd, bus->sdh, bus->sih, bus->fw_path, bus->nv_path); - dhd_set_bus_params(bus); - ret = _dhdsdio_download_firmware(bus); dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); @@ -10479,3 +10549,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/bcmdhd.100.10.315.x/dhd_static_buf.c b/bcmdhd.100.10.315.x/dhd_static_buf.c index 77ad69b..fb68b01 100644 --- a/bcmdhd.100.10.315.x/dhd_static_buf.c +++ b/bcmdhd.100.10.315.x/dhd_static_buf.c @@ -1,464 +1,585 @@ -/* - * drivers/amlogic/wifi/dhd_static_buf.c - * - * Copyright (C) 2017 Amlogic, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - */ - -#define pr_fmt(fmt) "Wifi: %s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DHD_STATIC_VERSION_STR "100.10.545.3" - -#define BCMDHD_SDIO -#define BCMDHD_PCIE - -enum dhd_prealloc_index { - DHD_PREALLOC_PROT = 0, -#if defined(BCMDHD_SDIO) - DHD_PREALLOC_RXBUF = 1, - DHD_PREALLOC_DATABUF = 2, -#endif - DHD_PREALLOC_OSL_BUF = 3, - DHD_PREALLOC_SKB_BUF = 4, - DHD_PREALLOC_WIPHY_ESCAN0 = 5, - DHD_PREALLOC_WIPHY_ESCAN1 = 6, - DHD_PREALLOC_DHD_INFO = 7, - DHD_PREALLOC_DHD_WLFC_INFO = 8, -#ifdef BCMDHD_PCIE - DHD_PREALLOC_IF_FLOW_LKUP = 9, -#endif - DHD_PREALLOC_MEMDUMP_BUF = 10, - DHD_PREALLOC_MEMDUMP_RAM = 11, - DHD_PREALLOC_DHD_WLFC_HANGER = 12, - DHD_PREALLOC_PKTID_MAP = 13, - DHD_PREALLOC_PKTID_MAP_IOCTL = 14, - DHD_PREALLOC_DHD_LOG_DUMP_BUF = 15, - DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX = 16, - DHD_PREALLOC_DHD_PKTLOG_DUMP_BUF = 17, - DHD_PREALLOC_STAT_REPORT_BUF = 18, - DHD_PREALLOC_WL_WEXT_INFO = 19, - DHD_PREALLOC_FW_VERBOSE_RING = 20, - DHD_PREALLOC_FW_EVENT_RING = 21, - DHD_PREALLOC_DHD_EVENT_RING = 22, - DHD_PREALLOC_NAN_EVENT_RING = 23, - DHD_PREALLOC_MAX -}; - -#define STATIC_BUF_MAX_NUM 20 -#define STATIC_BUF_SIZE (PAGE_SIZE*2) - -#define DHD_PREALLOC_PROT_SIZE (16 * 1024) -#define DHD_PREALLOC_RXBUF_SIZE (24 * 1024) -#define DHD_PREALLOC_DATABUF_SIZE (64 * 1024) -#define DHD_PREALLOC_OSL_BUF_SIZE (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE) -#define DHD_PREALLOC_WIPHY_ESCAN0_SIZE (64 * 1024) -#define DHD_PREALLOC_DHD_INFO_SIZE (32 * 1024) -#define DHD_PREALLOC_MEMDUMP_RAM_SIZE (1290 * 1024) -#define DHD_PREALLOC_DHD_WLFC_HANGER_SIZE (73 * 1024) -#define DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE (1024 * 1024 * CUSTOM_LOG_DUMP_BUFSIZE_MB) -#define DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE (8 * 1024) -#define DHD_PREALLOC_WL_WEXT_INFO_SIZE (70 * 1024) -#ifdef CONFIG_64BIT -#define DHD_PREALLOC_IF_FLOW_LKUP_SIZE (20 * 1024 * 2) -#else -#define DHD_PREALLOC_IF_FLOW_LKUP_SIZE (20 * 1024) -#endif -#define FW_VERBOSE_RING_SIZE (256 * 1024) -#define FW_EVENT_RING_SIZE (64 * 1024) -#define DHD_EVENT_RING_SIZE (64 * 1024) -#define NAN_EVENT_RING_SIZE (64 * 1024) - -#if defined(CONFIG_64BIT) -#define WLAN_DHD_INFO_BUF_SIZE (24 * 1024) -#define WLAN_DHD_WLFC_BUF_SIZE (64 * 1024) -#define WLAN_DHD_IF_FLOW_LKUP_SIZE (64 * 1024) -#else -#define WLAN_DHD_INFO_BUF_SIZE (16 * 1024) -#define WLAN_DHD_WLFC_BUF_SIZE (64 * 1024) -#define WLAN_DHD_IF_FLOW_LKUP_SIZE (20 * 1024) -#endif /* CONFIG_64BIT */ -#define WLAN_DHD_MEMDUMP_SIZE (800 * 1024) - -#define DHD_SKB_1PAGE_BUFSIZE (PAGE_SIZE*1) -#define DHD_SKB_2PAGE_BUFSIZE (PAGE_SIZE*2) -#define DHD_SKB_4PAGE_BUFSIZE (PAGE_SIZE*4) - -#define DHD_SKB_1PAGE_BUF_NUM 8 -#define DHD_SKB_2PAGE_BUF_NUM 64 -#define DHD_SKB_4PAGE_BUF_NUM 1 - -/* The number is defined in linux_osl.c - * WLAN_SKB_1_2PAGE_BUF_NUM => STATIC_PKT_1_2PAGE_NUM - * WLAN_SKB_BUF_NUM => STATIC_PKT_MAX_NUM - */ -#define WLAN_SKB_1_2PAGE_BUF_NUM ((DHD_SKB_1PAGE_BUF_NUM) + \ - (DHD_SKB_2PAGE_BUF_NUM)) -#define WLAN_SKB_BUF_NUM ((WLAN_SKB_1_2PAGE_BUF_NUM) + (DHD_SKB_4PAGE_BUF_NUM)) - -void *wlan_static_prot; -void *wlan_static_rxbuf; -void *wlan_static_databuf; -void *wlan_static_osl_buf; -void *wlan_static_scan_buf0; -void *wlan_static_scan_buf1; -void *wlan_static_dhd_info_buf; -void *wlan_static_dhd_wlfc_info_buf; -void *wlan_static_if_flow_lkup; -void *wlan_static_dhd_memdump_ram_buf; -void *wlan_static_dhd_wlfc_hanger_buf; -void *wlan_static_dhd_log_dump_buf; -void *wlan_static_dhd_log_dump_buf_ex; -void *wlan_static_wl_escan_info_buf; -void *wlan_static_fw_verbose_ring_buf; -void *wlan_static_fw_event_ring_buf; -void *wlan_static_dhd_event_ring_buf; -void *wlan_static_nan_event_ring_buf; - -static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM]; - -void *bcmdhd_mem_prealloc(int section, unsigned long size) -{ - pr_info("sectoin %d, size %ld\n", section, size); - if (section == DHD_PREALLOC_PROT) - return wlan_static_prot; - -#if defined(BCMDHD_SDIO) - if (section == DHD_PREALLOC_RXBUF) - return wlan_static_rxbuf; - - if (section == DHD_PREALLOC_DATABUF) - return wlan_static_databuf; -#endif /* BCMDHD_SDIO */ - - if (section == DHD_PREALLOC_SKB_BUF) - return wlan_static_skb; - - if (section == DHD_PREALLOC_WIPHY_ESCAN0) - return wlan_static_scan_buf0; - - if (section == DHD_PREALLOC_WIPHY_ESCAN1) - return wlan_static_scan_buf1; - - if (section == DHD_PREALLOC_OSL_BUF) { - if (size > DHD_PREALLOC_OSL_BUF_SIZE) { - pr_err("request OSL_BUF(%lu) > %ld\n", - size, DHD_PREALLOC_OSL_BUF_SIZE); - return NULL; - } - return wlan_static_osl_buf; - } - - if (section == DHD_PREALLOC_DHD_INFO) { - if (size > DHD_PREALLOC_DHD_INFO_SIZE) { - pr_err("request DHD_INFO size(%lu) > %d\n", - size, DHD_PREALLOC_DHD_INFO_SIZE); - return NULL; - } - return wlan_static_dhd_info_buf; - } - if (section == DHD_PREALLOC_DHD_WLFC_INFO) { - if (size > WLAN_DHD_WLFC_BUF_SIZE) { - pr_err("request DHD_WLFC_INFO size(%lu) > %d\n", - size, WLAN_DHD_WLFC_BUF_SIZE); - return NULL; - } - return wlan_static_dhd_wlfc_info_buf; - } -#ifdef BCMDHD_PCIE - if (section == DHD_PREALLOC_IF_FLOW_LKUP) { - if (size > DHD_PREALLOC_IF_FLOW_LKUP_SIZE) { - pr_err("request DHD_IF_FLOW_LKUP size(%lu) > %d\n", - size, DHD_PREALLOC_IF_FLOW_LKUP_SIZE); - return NULL; - } - - return wlan_static_if_flow_lkup; - } -#endif /* BCMDHD_PCIE */ - if (section == DHD_PREALLOC_MEMDUMP_RAM) { - if (size > DHD_PREALLOC_MEMDUMP_RAM_SIZE) { - pr_err("request DHD_PREALLOC_MEMDUMP_RAM_SIZE(%lu) > %d\n", - size, DHD_PREALLOC_MEMDUMP_RAM_SIZE); - return NULL; - } - - return wlan_static_dhd_memdump_ram_buf; - } - if (section == DHD_PREALLOC_DHD_WLFC_HANGER) { - if (size > DHD_PREALLOC_DHD_WLFC_HANGER_SIZE) { - pr_err("request DHD_WLFC_HANGER size(%lu) > %d\n", - size, DHD_PREALLOC_DHD_WLFC_HANGER_SIZE); - return NULL; - } - return wlan_static_dhd_wlfc_hanger_buf; - } - if (section == DHD_PREALLOC_DHD_LOG_DUMP_BUF) { - if (size > DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE) { - pr_err("request DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE(%lu) > %d\n", - size, DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE); - return NULL; - } - - return wlan_static_dhd_log_dump_buf; - } - if (section == DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX) { - if (size > DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE) { - pr_err("request DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE(%lu) > %d\n", - size, DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE); - return NULL; - } - - return wlan_static_dhd_log_dump_buf_ex; - } - if (section == DHD_PREALLOC_WL_WEXT_INFO) { - if (size > DHD_PREALLOC_WL_WEXT_INFO_SIZE) { - pr_err("request DHD_PREALLOC_WL_WEXT_INFO_SIZE(%lu) > %d\n", - size, DHD_PREALLOC_WL_WEXT_INFO_SIZE); - return NULL; - } - - return wlan_static_wl_escan_info_buf; - } - if (section == DHD_PREALLOC_FW_VERBOSE_RING) { - if (size > FW_VERBOSE_RING_SIZE) { - pr_err("request DHD_PREALLOC_FW_VERBOSE_RING(%lu) > %d\n", - size, FW_VERBOSE_RING_SIZE); - return NULL; - } - - return wlan_static_fw_verbose_ring_buf; - } - if (section == DHD_PREALLOC_FW_EVENT_RING) { - if (size > FW_EVENT_RING_SIZE) { - pr_err("request DHD_PREALLOC_FW_EVENT_RING(%lu) > %d\n", - size, FW_EVENT_RING_SIZE); - return NULL; - } - - return wlan_static_fw_event_ring_buf; - } - if (section == DHD_PREALLOC_DHD_EVENT_RING) { - if (size > DHD_EVENT_RING_SIZE) { - pr_err("request DHD_PREALLOC_DHD_EVENT_RING(%lu) > %d\n", - size, DHD_EVENT_RING_SIZE); - return NULL; - } - - return wlan_static_dhd_event_ring_buf; - } - if (section == DHD_PREALLOC_NAN_EVENT_RING) { - if (size > NAN_EVENT_RING_SIZE) { - pr_err("request DHD_PREALLOC_NAN_EVENT_RING(%lu) > %d\n", - size, NAN_EVENT_RING_SIZE); - return NULL; - } - - return wlan_static_nan_event_ring_buf; - } - if ((section < 0) || (section > DHD_PREALLOC_MAX)) - pr_err("request section id(%d) is out of max index %d\n", - section, DHD_PREALLOC_MAX); - - pr_err("%s: failed to alloc section %d, size=%ld\n", - __func__, section, size); - - return NULL; -} -EXPORT_SYMBOL(bcmdhd_mem_prealloc); - -int bcmdhd_init_wlan_mem(void) -{ - int i; - int j; - pr_info("%s(): %s\n", __func__, DHD_STATIC_VERSION_STR); - - for (i = 0; i < DHD_SKB_1PAGE_BUF_NUM; i++) { - wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_1PAGE_BUFSIZE); - if (!wlan_static_skb[i]) - goto err_skb_alloc; - } - - for (i = DHD_SKB_1PAGE_BUF_NUM; i < WLAN_SKB_1_2PAGE_BUF_NUM; i++) { - wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_2PAGE_BUFSIZE); - if (!wlan_static_skb[i]) - goto err_skb_alloc; - } - -#if defined(BCMDHD_SDIO) - wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_4PAGE_BUFSIZE); - if (!wlan_static_skb[i]) - goto err_skb_alloc; -#endif /* BCMDHD_SDIO */ - - wlan_static_prot = kmalloc(DHD_PREALLOC_PROT_SIZE, GFP_KERNEL); - if (!wlan_static_prot) - goto err_mem_alloc; - -#if defined(BCMDHD_SDIO) - wlan_static_rxbuf = kmalloc(DHD_PREALLOC_RXBUF_SIZE, GFP_KERNEL); - if (!wlan_static_rxbuf) - goto err_mem_alloc; - - wlan_static_databuf = kmalloc(DHD_PREALLOC_DATABUF_SIZE, GFP_KERNEL); - if (!wlan_static_databuf) - goto err_mem_alloc; -#endif /* BCMDHD_SDIO */ - - wlan_static_osl_buf = kmalloc(DHD_PREALLOC_OSL_BUF_SIZE, GFP_KERNEL); - if (!wlan_static_osl_buf) - goto err_mem_alloc; - - wlan_static_scan_buf0 = kmalloc(DHD_PREALLOC_WIPHY_ESCAN0_SIZE, GFP_KERNEL); - if (!wlan_static_scan_buf0) - goto err_mem_alloc; - - wlan_static_dhd_info_buf = kmalloc(DHD_PREALLOC_DHD_INFO_SIZE, GFP_KERNEL); - if (!wlan_static_dhd_info_buf) - goto err_mem_alloc; - - wlan_static_dhd_wlfc_info_buf = kmalloc(WLAN_DHD_WLFC_BUF_SIZE, GFP_KERNEL); - if (!wlan_static_dhd_wlfc_info_buf) - goto err_mem_alloc; - -#ifdef BCMDHD_PCIE - wlan_static_if_flow_lkup = kmalloc(DHD_PREALLOC_IF_FLOW_LKUP_SIZE, GFP_KERNEL); - if (!wlan_static_if_flow_lkup) - goto err_mem_alloc; -#endif /* BCMDHD_PCIE */ - - wlan_static_dhd_memdump_ram_buf = kmalloc(DHD_PREALLOC_MEMDUMP_RAM_SIZE, GFP_KERNEL); - if (!wlan_static_dhd_memdump_ram_buf) - goto err_mem_alloc; - - wlan_static_dhd_wlfc_hanger_buf = kmalloc(DHD_PREALLOC_DHD_WLFC_HANGER_SIZE, GFP_KERNEL); - if (!wlan_static_dhd_wlfc_hanger_buf) - goto err_mem_alloc; - - wlan_static_dhd_log_dump_buf = kmalloc(DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE, GFP_KERNEL); - if (!wlan_static_dhd_log_dump_buf) - goto err_mem_alloc; - - wlan_static_dhd_log_dump_buf_ex = kmalloc(DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE, GFP_KERNEL); - if (!wlan_static_dhd_log_dump_buf_ex) - goto err_mem_alloc; - - wlan_static_wl_escan_info_buf = kmalloc(DHD_PREALLOC_WL_WEXT_INFO_SIZE, GFP_KERNEL); - if (!wlan_static_wl_escan_info_buf) - goto err_mem_alloc; - - wlan_static_fw_verbose_ring_buf = kmalloc(FW_VERBOSE_RING_SIZE, GFP_KERNEL); - if (!wlan_static_fw_verbose_ring_buf) - goto err_mem_alloc; - - wlan_static_fw_event_ring_buf = kmalloc(FW_EVENT_RING_SIZE, GFP_KERNEL); - if (!wlan_static_fw_event_ring_buf) - goto err_mem_alloc; - - wlan_static_dhd_event_ring_buf = kmalloc(DHD_EVENT_RING_SIZE, GFP_KERNEL); - if (!wlan_static_dhd_event_ring_buf) - goto err_mem_alloc; - - wlan_static_nan_event_ring_buf = kmalloc(NAN_EVENT_RING_SIZE, GFP_KERNEL); - if (!wlan_static_nan_event_ring_buf) - goto err_mem_alloc; - - pr_info("bcmdhd_init_wlan_mem prealloc ok\n"); - return 0; - -err_mem_alloc: - - if (wlan_static_prot) - kfree(wlan_static_prot); - -#if defined(BCMDHD_SDIO) - if (wlan_static_rxbuf) - kfree(wlan_static_rxbuf); - - if (wlan_static_databuf) - kfree(wlan_static_databuf); -#endif /* BCMDHD_SDIO */ - - if (wlan_static_osl_buf) - kfree(wlan_static_osl_buf); - - if (wlan_static_scan_buf0) - kfree(wlan_static_scan_buf0); - - if (wlan_static_scan_buf1) - kfree(wlan_static_scan_buf1); - - if (wlan_static_dhd_info_buf) - kfree(wlan_static_dhd_info_buf); - - if (wlan_static_dhd_wlfc_info_buf) - kfree(wlan_static_dhd_wlfc_info_buf); - -#ifdef BCMDHD_PCIE - if (wlan_static_if_flow_lkup) - kfree(wlan_static_if_flow_lkup); -#endif /* BCMDHD_PCIE */ - - if (wlan_static_dhd_memdump_ram_buf) - kfree(wlan_static_dhd_memdump_ram_buf); - - if (wlan_static_dhd_wlfc_hanger_buf) - kfree(wlan_static_dhd_wlfc_hanger_buf); - - if (wlan_static_dhd_log_dump_buf) - kfree(wlan_static_dhd_log_dump_buf); - - if (wlan_static_dhd_log_dump_buf_ex) - kfree(wlan_static_dhd_log_dump_buf_ex); - - 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); - - if (wlan_static_fw_event_ring_buf) - kfree(wlan_static_fw_event_ring_buf); - - if (wlan_static_dhd_event_ring_buf) - kfree(wlan_static_dhd_event_ring_buf); - - if (wlan_static_nan_event_ring_buf) - kfree(wlan_static_nan_event_ring_buf); -#endif /* BCMDHD_PCIE */ - - pr_err("%s: Failed to mem_alloc for WLAN\n", __func__); - - i = WLAN_SKB_BUF_NUM; - -err_skb_alloc: - pr_err("%s: Failed to skb_alloc for WLAN\n", __func__); - for (j = 0; j < i; j++) - dev_kfree_skb(wlan_static_skb[j]); - - return -ENOMEM; -} -EXPORT_SYMBOL(bcmdhd_init_wlan_mem); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("AMLOGIC"); -MODULE_DESCRIPTION("wifi device tree driver"); +#include +#include +#include +#include +#include +#include +#include + +#define DHD_STATIC_VERSION_STR "100.10.545.7 (r826445-20200110-2)" + +#define BCMDHD_SDIO +#define BCMDHD_PCIE + +enum dhd_prealloc_index { + DHD_PREALLOC_PROT = 0, +#if defined(BCMDHD_SDIO) + DHD_PREALLOC_RXBUF = 1, + DHD_PREALLOC_DATABUF = 2, +#endif + DHD_PREALLOC_OSL_BUF = 3, + DHD_PREALLOC_SKB_BUF = 4, + DHD_PREALLOC_WIPHY_ESCAN0 = 5, + DHD_PREALLOC_WIPHY_ESCAN1 = 6, + DHD_PREALLOC_DHD_INFO = 7, + DHD_PREALLOC_DHD_WLFC_INFO = 8, +#ifdef BCMDHD_PCIE + DHD_PREALLOC_IF_FLOW_LKUP = 9, +#endif + DHD_PREALLOC_MEMDUMP_BUF = 10, + DHD_PREALLOC_MEMDUMP_RAM = 11, + DHD_PREALLOC_DHD_WLFC_HANGER = 12, + DHD_PREALLOC_PKTID_MAP = 13, + DHD_PREALLOC_PKTID_MAP_IOCTL = 14, + DHD_PREALLOC_DHD_LOG_DUMP_BUF = 15, + 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 = 19, + DHD_PREALLOC_FW_VERBOSE_RING = 20, + DHD_PREALLOC_FW_EVENT_RING = 21, + DHD_PREALLOC_DHD_EVENT_RING = 22, + DHD_PREALLOC_NAN_EVENT_RING = 23, + DHD_PREALLOC_MAX +}; + +#define STATIC_BUF_MAX_NUM 20 +#define STATIC_BUF_SIZE (PAGE_SIZE*2) + +#ifndef CUSTOM_LOG_DUMP_BUFSIZE_MB +#define CUSTOM_LOG_DUMP_BUFSIZE_MB 4 /* DHD_LOG_DUMP_BUF_SIZE 4 MB static memory in kernel */ +#endif /* CUSTOM_LOG_DUMP_BUFSIZE_MB */ + +#define DHD_PREALLOC_PROT_SIZE (16 * 1024) +#define DHD_PREALLOC_RXBUF_SIZE (24 * 1024) +#define DHD_PREALLOC_DATABUF_SIZE (64 * 1024) +#define DHD_PREALLOC_OSL_BUF_SIZE (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE) +#define DHD_PREALLOC_WIPHY_ESCAN0_SIZE (64 * 1024) +#define DHD_PREALLOC_DHD_INFO_SIZE (32 * 1024) +#define DHD_PREALLOC_MEMDUMP_RAM_SIZE (1290 * 1024) +#define DHD_PREALLOC_DHD_WLFC_HANGER_SIZE (73 * 1024) +#define DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE (1024 * 1024 * CUSTOM_LOG_DUMP_BUFSIZE_MB) +#define DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE (8 * 1024) +#define DHD_PREALLOC_WL_ESCAN_SIZE (70 * 1024) +#ifdef CONFIG_64BIT +#define DHD_PREALLOC_IF_FLOW_LKUP_SIZE (20 * 1024 * 2) +#else +#define DHD_PREALLOC_IF_FLOW_LKUP_SIZE (20 * 1024) +#endif +#define FW_VERBOSE_RING_SIZE (256 * 1024) +#define FW_EVENT_RING_SIZE (64 * 1024) +#define DHD_EVENT_RING_SIZE (64 * 1024) +#define NAN_EVENT_RING_SIZE (64 * 1024) + +#if defined(CONFIG_64BIT) +#define WLAN_DHD_INFO_BUF_SIZE (24 * 1024) +#define WLAN_DHD_WLFC_BUF_SIZE (64 * 1024) +#define WLAN_DHD_IF_FLOW_LKUP_SIZE (64 * 1024) +#else +#define WLAN_DHD_INFO_BUF_SIZE (16 * 1024) +#define WLAN_DHD_WLFC_BUF_SIZE (64 * 1024) +#define WLAN_DHD_IF_FLOW_LKUP_SIZE (20 * 1024) +#endif /* CONFIG_64BIT */ +#define WLAN_DHD_MEMDUMP_SIZE (800 * 1024) + +#define DHD_SKB_1PAGE_BUFSIZE (PAGE_SIZE*1) +#define DHD_SKB_2PAGE_BUFSIZE (PAGE_SIZE*2) +#define DHD_SKB_4PAGE_BUFSIZE (PAGE_SIZE*4) + +#define DHD_SKB_1PAGE_BUF_NUM 8 +#ifdef BCMDHD_PCIE +#define DHD_SKB_2PAGE_BUF_NUM 64 +#elif defined(BCMDHD_SDIO) +#define DHD_SKB_2PAGE_BUF_NUM 8 +#endif +#define DHD_SKB_4PAGE_BUF_NUM 1 + +/* The number is defined in linux_osl.c + * WLAN_SKB_1_2PAGE_BUF_NUM => STATIC_PKT_1_2PAGE_NUM + * WLAN_SKB_BUF_NUM => STATIC_PKT_MAX_NUM + */ +#define WLAN_SKB_1_2PAGE_BUF_NUM ((DHD_SKB_1PAGE_BUF_NUM) + \ + (DHD_SKB_2PAGE_BUF_NUM)) +#define WLAN_SKB_BUF_NUM ((WLAN_SKB_1_2PAGE_BUF_NUM) + (DHD_SKB_4PAGE_BUF_NUM)) + +void *wlan_static_prot = NULL; +void *wlan_static_rxbuf = NULL; +void *wlan_static_databuf = NULL; +void *wlan_static_osl_buf = NULL; +void *wlan_static_scan_buf0 = NULL; +void *wlan_static_scan_buf1 = NULL; +void *wlan_static_dhd_info_buf = NULL; +void *wlan_static_dhd_wlfc_info_buf = NULL; +void *wlan_static_if_flow_lkup = NULL; +void *wlan_static_dhd_memdump_ram_buf = NULL; +void *wlan_static_dhd_wlfc_hanger_buf = NULL; +void *wlan_static_dhd_log_dump_buf = NULL; +void *wlan_static_dhd_log_dump_buf_ex = NULL; +void *wlan_static_wl_escan_info_buf = NULL; +void *wlan_static_fw_verbose_ring_buf = NULL; +void *wlan_static_fw_event_ring_buf = NULL; +void *wlan_static_dhd_event_ring_buf = NULL; +void *wlan_static_nan_event_ring_buf = NULL; + +static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM]; + +void *dhd_wlan_mem_prealloc(int section, unsigned long size) +{ + pr_err("%s: sectoin %d, %ld\n", __func__, section, size); + if (section == DHD_PREALLOC_PROT) + return wlan_static_prot; + +#if defined(BCMDHD_SDIO) + if (section == DHD_PREALLOC_RXBUF) + return wlan_static_rxbuf; + + if (section == DHD_PREALLOC_DATABUF) + return wlan_static_databuf; +#endif /* BCMDHD_SDIO */ + + if (section == DHD_PREALLOC_SKB_BUF) + return wlan_static_skb; + + if (section == DHD_PREALLOC_WIPHY_ESCAN0) + return wlan_static_scan_buf0; + + if (section == DHD_PREALLOC_WIPHY_ESCAN1) + return wlan_static_scan_buf1; + + if (section == DHD_PREALLOC_OSL_BUF) { + if (size > DHD_PREALLOC_OSL_BUF_SIZE) { + pr_err("request OSL_BUF(%lu) > %ld\n", + size, DHD_PREALLOC_OSL_BUF_SIZE); + return NULL; + } + return wlan_static_osl_buf; + } + + if (section == DHD_PREALLOC_DHD_INFO) { + if (size > DHD_PREALLOC_DHD_INFO_SIZE) { + pr_err("request DHD_INFO size(%lu) > %d\n", + size, DHD_PREALLOC_DHD_INFO_SIZE); + return NULL; + } + return wlan_static_dhd_info_buf; + } + if (section == DHD_PREALLOC_DHD_WLFC_INFO) { + if (size > WLAN_DHD_WLFC_BUF_SIZE) { + pr_err("request DHD_WLFC_INFO size(%lu) > %d\n", + size, WLAN_DHD_WLFC_BUF_SIZE); + return NULL; + } + return wlan_static_dhd_wlfc_info_buf; + } +#ifdef BCMDHD_PCIE + if (section == DHD_PREALLOC_IF_FLOW_LKUP) { + if (size > DHD_PREALLOC_IF_FLOW_LKUP_SIZE) { + pr_err("request DHD_IF_FLOW_LKUP size(%lu) > %d\n", + size, DHD_PREALLOC_IF_FLOW_LKUP_SIZE); + return NULL; + } + + return wlan_static_if_flow_lkup; + } +#endif /* BCMDHD_PCIE */ + if (section == DHD_PREALLOC_MEMDUMP_RAM) { + if (size > DHD_PREALLOC_MEMDUMP_RAM_SIZE) { + pr_err("request DHD_PREALLOC_MEMDUMP_RAM_SIZE(%lu) > %d\n", + size, DHD_PREALLOC_MEMDUMP_RAM_SIZE); + return NULL; + } + + return wlan_static_dhd_memdump_ram_buf; + } + if (section == DHD_PREALLOC_DHD_WLFC_HANGER) { + if (size > DHD_PREALLOC_DHD_WLFC_HANGER_SIZE) { + pr_err("request DHD_WLFC_HANGER size(%lu) > %d\n", + size, DHD_PREALLOC_DHD_WLFC_HANGER_SIZE); + return NULL; + } + return wlan_static_dhd_wlfc_hanger_buf; + } + if (section == DHD_PREALLOC_DHD_LOG_DUMP_BUF) { + if (size > DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE) { + pr_err("request DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE(%lu) > %d\n", + size, DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE); + return NULL; + } + + return wlan_static_dhd_log_dump_buf; + } + if (section == DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX) { + if (size > DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE) { + pr_err("request DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE(%lu) > %d\n", + size, DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE); + return NULL; + } + + return wlan_static_dhd_log_dump_buf_ex; + } + 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; + } + + return wlan_static_wl_escan_info_buf; + } + if (section == DHD_PREALLOC_FW_VERBOSE_RING) { + if (size > FW_VERBOSE_RING_SIZE) { + pr_err("request DHD_PREALLOC_FW_VERBOSE_RING(%lu) > %d\n", + size, FW_VERBOSE_RING_SIZE); + return NULL; + } + + return wlan_static_fw_verbose_ring_buf; + } + if (section == DHD_PREALLOC_FW_EVENT_RING) { + if (size > FW_EVENT_RING_SIZE) { + pr_err("request DHD_PREALLOC_FW_EVENT_RING(%lu) > %d\n", + size, FW_EVENT_RING_SIZE); + return NULL; + } + + return wlan_static_fw_event_ring_buf; + } + if (section == DHD_PREALLOC_DHD_EVENT_RING) { + if (size > DHD_EVENT_RING_SIZE) { + pr_err("request DHD_PREALLOC_DHD_EVENT_RING(%lu) > %d\n", + size, DHD_EVENT_RING_SIZE); + return NULL; + } + + return wlan_static_dhd_event_ring_buf; + } + if (section == DHD_PREALLOC_NAN_EVENT_RING) { + if (size > NAN_EVENT_RING_SIZE) { + pr_err("request DHD_PREALLOC_NAN_EVENT_RING(%lu) > %d\n", + size, NAN_EVENT_RING_SIZE); + return NULL; + } + + return wlan_static_nan_event_ring_buf; + } + if ((section < 0) || (section > DHD_PREALLOC_MAX)) + pr_err("request section id(%d) is out of max index %d\n", + section, DHD_PREALLOC_MAX); + + pr_err("%s: failed to alloc section %d, size=%ld\n", + __func__, section, size); + + return NULL; +} +EXPORT_SYMBOL(dhd_wlan_mem_prealloc); + +static int dhd_init_wlan_mem(void) +{ + int i; + int j; + printk(KERN_ERR "%s(): %s\n", __func__, DHD_STATIC_VERSION_STR); + + for (i = 0; i < DHD_SKB_1PAGE_BUF_NUM; i++) { + wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_1PAGE_BUFSIZE); + if (!wlan_static_skb[i]) { + goto err_skb_alloc; + } + pr_err("%s: sectoin %d skb[%d], size=%ld\n", __func__, + DHD_PREALLOC_SKB_BUF, i, DHD_SKB_1PAGE_BUFSIZE); + } + + for (i = DHD_SKB_1PAGE_BUF_NUM; i < WLAN_SKB_1_2PAGE_BUF_NUM; i++) { + wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_2PAGE_BUFSIZE); + if (!wlan_static_skb[i]) { + goto err_skb_alloc; + } + pr_err("%s: sectoin %d skb[%d], size=%ld\n", __func__, + DHD_PREALLOC_SKB_BUF, i, DHD_SKB_2PAGE_BUFSIZE); + } + +#if defined(BCMDHD_SDIO) + wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_4PAGE_BUFSIZE); + if (!wlan_static_skb[i]) + goto err_skb_alloc; + pr_err("%s: sectoin %d skb[%d], size=%ld\n", __func__, + DHD_PREALLOC_SKB_BUF, i, DHD_SKB_4PAGE_BUFSIZE); +#endif /* BCMDHD_SDIO */ + + wlan_static_prot = kmalloc(DHD_PREALLOC_PROT_SIZE, GFP_KERNEL); + if (!wlan_static_prot) + goto err_mem_alloc; + pr_err("%s: sectoin %d, size=%d\n", __func__, + DHD_PREALLOC_PROT, DHD_PREALLOC_PROT_SIZE); + +#if defined(BCMDHD_SDIO) + wlan_static_rxbuf = kmalloc(DHD_PREALLOC_RXBUF_SIZE, GFP_KERNEL); + if (!wlan_static_rxbuf) + goto err_mem_alloc; + pr_err("%s: sectoin %d, size=%d\n", __func__, + DHD_PREALLOC_RXBUF, DHD_PREALLOC_RXBUF_SIZE); + + wlan_static_databuf = kmalloc(DHD_PREALLOC_DATABUF_SIZE, GFP_KERNEL); + if (!wlan_static_databuf) + goto err_mem_alloc; + pr_err("%s: sectoin %d, size=%d\n", __func__, + DHD_PREALLOC_DATABUF, DHD_PREALLOC_DATABUF_SIZE); +#endif /* BCMDHD_SDIO */ + + wlan_static_osl_buf = kmalloc(DHD_PREALLOC_OSL_BUF_SIZE, GFP_KERNEL); + if (!wlan_static_osl_buf) + goto err_mem_alloc; + pr_err("%s: sectoin %d, size=%ld\n", __func__, + DHD_PREALLOC_OSL_BUF, DHD_PREALLOC_OSL_BUF_SIZE); + + wlan_static_scan_buf0 = kmalloc(DHD_PREALLOC_WIPHY_ESCAN0_SIZE, GFP_KERNEL); + if (!wlan_static_scan_buf0) + goto err_mem_alloc; + pr_err("%s: sectoin %d, size=%d\n", __func__, + DHD_PREALLOC_WIPHY_ESCAN0, DHD_PREALLOC_WIPHY_ESCAN0_SIZE); + + wlan_static_dhd_info_buf = kmalloc(DHD_PREALLOC_DHD_INFO_SIZE, GFP_KERNEL); + if (!wlan_static_dhd_info_buf) + goto err_mem_alloc; + pr_err("%s: sectoin %d, size=%d\n", __func__, + DHD_PREALLOC_DHD_INFO, DHD_PREALLOC_DHD_INFO_SIZE); + + wlan_static_dhd_wlfc_info_buf = kmalloc(WLAN_DHD_WLFC_BUF_SIZE, GFP_KERNEL); + if (!wlan_static_dhd_wlfc_info_buf) + goto err_mem_alloc; + pr_err("%s: sectoin %d, size=%d\n", __func__, + DHD_PREALLOC_DHD_WLFC_INFO, WLAN_DHD_WLFC_BUF_SIZE); + +#ifdef BCMDHD_PCIE + wlan_static_if_flow_lkup = kmalloc(DHD_PREALLOC_IF_FLOW_LKUP_SIZE, GFP_KERNEL); + if (!wlan_static_if_flow_lkup) + goto err_mem_alloc; + pr_err("%s: sectoin %d, size=%d\n", __func__, + DHD_PREALLOC_IF_FLOW_LKUP, DHD_PREALLOC_IF_FLOW_LKUP_SIZE); +#endif /* BCMDHD_PCIE */ + + wlan_static_dhd_memdump_ram_buf = kmalloc(DHD_PREALLOC_MEMDUMP_RAM_SIZE, GFP_KERNEL); + if (!wlan_static_dhd_memdump_ram_buf) + goto err_mem_alloc; + pr_err("%s: sectoin %d, size=%d\n", __func__, + DHD_PREALLOC_MEMDUMP_RAM, DHD_PREALLOC_MEMDUMP_RAM_SIZE); + + wlan_static_dhd_wlfc_hanger_buf = kmalloc(DHD_PREALLOC_DHD_WLFC_HANGER_SIZE, GFP_KERNEL); + if (!wlan_static_dhd_wlfc_hanger_buf) + goto err_mem_alloc; + pr_err("%s: sectoin %d, size=%d\n", __func__, + DHD_PREALLOC_DHD_WLFC_HANGER, DHD_PREALLOC_DHD_WLFC_HANGER_SIZE); + + wlan_static_dhd_log_dump_buf = kmalloc(DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE, GFP_KERNEL); + if (!wlan_static_dhd_log_dump_buf) + goto err_mem_alloc; + pr_err("%s: sectoin %d, size=%d\n", __func__, + DHD_PREALLOC_DHD_LOG_DUMP_BUF, DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE); + + wlan_static_dhd_log_dump_buf_ex = kmalloc(DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE, GFP_KERNEL); + if (!wlan_static_dhd_log_dump_buf_ex) + goto err_mem_alloc; + pr_err("%s: sectoin %d, size=%d\n", __func__, + DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX, DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE); + + 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, 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) + goto err_mem_alloc; + pr_err("%s: sectoin %d, size=%d\n", __func__, + DHD_PREALLOC_FW_VERBOSE_RING, FW_VERBOSE_RING_SIZE); + + wlan_static_fw_event_ring_buf = kmalloc(FW_EVENT_RING_SIZE, GFP_KERNEL); + if (!wlan_static_fw_event_ring_buf) + goto err_mem_alloc; + pr_err("%s: sectoin %d, size=%d\n", __func__, + DHD_PREALLOC_FW_EVENT_RING, FW_EVENT_RING_SIZE); + + wlan_static_dhd_event_ring_buf = kmalloc(DHD_EVENT_RING_SIZE, GFP_KERNEL); + if (!wlan_static_dhd_event_ring_buf) + goto err_mem_alloc; + pr_err("%s: sectoin %d, size=%d\n", __func__, + DHD_PREALLOC_DHD_EVENT_RING, DHD_EVENT_RING_SIZE); + + wlan_static_nan_event_ring_buf = kmalloc(NAN_EVENT_RING_SIZE, GFP_KERNEL); + if (!wlan_static_nan_event_ring_buf) + goto err_mem_alloc; + pr_err("%s: sectoin %d, size=%d\n", __func__, + DHD_PREALLOC_NAN_EVENT_RING, NAN_EVENT_RING_SIZE); + + return 0; + +err_mem_alloc: + + if (wlan_static_prot) + kfree(wlan_static_prot); + +#if defined(BCMDHD_SDIO) + if (wlan_static_rxbuf) + kfree(wlan_static_rxbuf); + + if (wlan_static_databuf) + kfree(wlan_static_databuf); +#endif /* BCMDHD_SDIO */ + + if (wlan_static_osl_buf) + kfree(wlan_static_osl_buf); + + if (wlan_static_scan_buf0) + kfree(wlan_static_scan_buf0); + + if (wlan_static_scan_buf1) + kfree(wlan_static_scan_buf1); + + if (wlan_static_dhd_info_buf) + kfree(wlan_static_dhd_info_buf); + + if (wlan_static_dhd_wlfc_info_buf) + kfree(wlan_static_dhd_wlfc_info_buf); + +#ifdef BCMDHD_PCIE + if (wlan_static_if_flow_lkup) + kfree(wlan_static_if_flow_lkup); +#endif /* BCMDHD_PCIE */ + + if (wlan_static_dhd_memdump_ram_buf) + kfree(wlan_static_dhd_memdump_ram_buf); + + if (wlan_static_dhd_wlfc_hanger_buf) + kfree(wlan_static_dhd_wlfc_hanger_buf); + + if (wlan_static_dhd_log_dump_buf) + kfree(wlan_static_dhd_log_dump_buf); + + if (wlan_static_dhd_log_dump_buf_ex) + kfree(wlan_static_dhd_log_dump_buf_ex); + + 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); + + if (wlan_static_fw_event_ring_buf) + kfree(wlan_static_fw_event_ring_buf); + + if (wlan_static_dhd_event_ring_buf) + kfree(wlan_static_dhd_event_ring_buf); + + if (wlan_static_nan_event_ring_buf) + kfree(wlan_static_nan_event_ring_buf); +#endif /* BCMDHD_PCIE */ + + pr_err("%s: Failed to mem_alloc for WLAN\n", __func__); + + i = WLAN_SKB_BUF_NUM; + +err_skb_alloc: + pr_err("%s: Failed to skb_alloc for WLAN\n", __func__); + for (j = 0; j < i; j++) + dev_kfree_skb(wlan_static_skb[j]); + + return -ENOMEM; +} + +static int __init +dhd_static_buf_init(void) +{ + dhd_init_wlan_mem(); + + return 0; +} + +static void __exit +dhd_static_buf_exit(void) +{ + int i; + + pr_err("%s()\n", __FUNCTION__); + + for (i = 0; i < DHD_SKB_1PAGE_BUF_NUM; i++) { + if (wlan_static_skb[i]) + dev_kfree_skb(wlan_static_skb[i]); + } + + for (i = DHD_SKB_1PAGE_BUF_NUM; i < WLAN_SKB_1_2PAGE_BUF_NUM; i++) { + if (wlan_static_skb[i]) + dev_kfree_skb(wlan_static_skb[i]); + } + +#if defined(BCMDHD_SDIO) + if (wlan_static_skb[i]) + dev_kfree_skb(wlan_static_skb[i]); +#endif /* BCMDHD_SDIO */ + + if (wlan_static_prot) + kfree(wlan_static_prot); + +#if defined(BCMDHD_SDIO) + if (wlan_static_rxbuf) + kfree(wlan_static_rxbuf); + + if (wlan_static_databuf) + kfree(wlan_static_databuf); +#endif /* BCMDHD_SDIO */ + + if (wlan_static_osl_buf) + kfree(wlan_static_osl_buf); + + if (wlan_static_scan_buf0) + kfree(wlan_static_scan_buf0); + + if (wlan_static_scan_buf1) + kfree(wlan_static_scan_buf1); + + if (wlan_static_dhd_info_buf) + kfree(wlan_static_dhd_info_buf); + + if (wlan_static_dhd_wlfc_info_buf) + kfree(wlan_static_dhd_wlfc_info_buf); + +#ifdef BCMDHD_PCIE + if (wlan_static_if_flow_lkup) + kfree(wlan_static_if_flow_lkup); +#endif /* BCMDHD_PCIE */ + + if (wlan_static_dhd_memdump_ram_buf) + kfree(wlan_static_dhd_memdump_ram_buf); + + if (wlan_static_dhd_wlfc_hanger_buf) + kfree(wlan_static_dhd_wlfc_hanger_buf); + + if (wlan_static_dhd_log_dump_buf) + kfree(wlan_static_dhd_log_dump_buf); + + if (wlan_static_dhd_log_dump_buf_ex) + kfree(wlan_static_dhd_log_dump_buf_ex); + + 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); + + if (wlan_static_fw_event_ring_buf) + kfree(wlan_static_fw_event_ring_buf); + + if (wlan_static_dhd_event_ring_buf) + kfree(wlan_static_dhd_event_ring_buf); + + if (wlan_static_nan_event_ring_buf) + kfree(wlan_static_nan_event_ring_buf); +#endif + + return; +} + +module_init(dhd_static_buf_init); + +module_exit(dhd_static_buf_exit); diff --git a/bcmdhd.100.10.315.x/dhd_wlfc.c b/bcmdhd.100.10.315.x/dhd_wlfc.c index a7f034e..a54ed81 100644 --- a/bcmdhd.100.10.315.x/dhd_wlfc.c +++ b/bcmdhd.100.10.315.x/dhd_wlfc.c @@ -41,6 +41,7 @@ #include #include +#include #ifdef PROP_TXSTATUS /* a form of flow control between host and dongle */ #include @@ -1322,6 +1323,9 @@ _dhd_wlfc_deque_delayedq(athost_wl_status_info_t* ctx, int prec, ASSERT(entry); if (entry->occupied && _dhd_wlfc_is_destination_open(ctx, entry, prec) && +#ifdef PROPTX_MAXCOUNT + (entry->transit_count < entry->transit_maxcount) && +#endif /* PROPTX_MAXCOUNT */ (entry->transit_count < WL_TXSTATUS_FREERUNCTR_MASK) && (!entry->suppressed)) { *ac_credit_spent = credit_spent; @@ -1828,6 +1832,9 @@ _dhd_wlfc_mac_entry_update(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* if (action == eWLFC_MAC_ENTRY_ACTION_ADD) { entry->suppressed = FALSE; entry->transit_count = 0; +#ifdef PROPTX_MAXCOUNT + entry->transit_maxcount = wl_ext_get_wlfc_maxcount(ctx->dhdp, ifid); +#endif /* PROPTX_MAXCOUNT */ entry->suppr_transit_count = 0; entry->onbus_pkts_count = 0; } @@ -4573,4 +4580,36 @@ int dhd_wlfc_set_rxpkt_chk(dhd_pub_t *dhd, int val) return BCME_OK; } +#ifdef PROPTX_MAXCOUNT +int dhd_wlfc_update_maxcount(dhd_pub_t *dhdp, uint8 ifid, int maxcount) +{ + athost_wl_status_info_t* ctx; + int rc = 0; + + if (dhdp == NULL) { + DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__)); + return BCME_BADARG; + } + + dhd_os_wlfc_block(dhdp); + + if (!dhdp->wlfc_state || (dhdp->proptxstatus_mode == WLFC_FCMODE_NONE)) { + rc = WLFC_UNSUPPORTED; + goto exit; + } + + if (ifid >= WLFC_MAX_IFNUM) { + DHD_ERROR(("%s: bad ifid\n", __FUNCTION__)); + rc = BCME_BADARG; + goto exit; + } + + ctx = (athost_wl_status_info_t*)dhdp->wlfc_state; + ctx->destination_entries.interfaces[ifid].transit_maxcount = maxcount; +exit: + dhd_os_wlfc_unblock(dhdp); + return rc; +} +#endif /* PROPTX_MAXCOUNT */ + #endif /* PROP_TXSTATUS */ diff --git a/bcmdhd.100.10.315.x/dhd_wlfc.h b/bcmdhd.100.10.315.x/dhd_wlfc.h index 88b0650..7ca1968 100644 --- a/bcmdhd.100.10.315.x/dhd_wlfc.h +++ b/bcmdhd.100.10.315.x/dhd_wlfc.h @@ -166,6 +166,10 @@ typedef struct wlfc_mac_descriptor { uint32 opened_ct; uint32 closed_ct; #endif // endif +#ifdef PROPTX_MAXCOUNT + /** Max Number of packets at dongle for this entry. */ + int transit_maxcount; +#endif /* PROPTX_MAXCOUNT */ struct wlfc_mac_descriptor* prev; struct wlfc_mac_descriptor* next; } wlfc_mac_descriptor_t; @@ -558,5 +562,8 @@ int dhd_wlfc_set_txstatus_ignore(dhd_pub_t *dhd, int val); int dhd_wlfc_get_rxpkt_chk(dhd_pub_t *dhd, int *val); int dhd_wlfc_set_rxpkt_chk(dhd_pub_t *dhd, int val); +#ifdef PROPTX_MAXCOUNT +int dhd_wlfc_update_maxcount(dhd_pub_t *dhdp, uint8 ifid, int maxcount); +#endif /* PROPTX_MAXCOUNT */ #endif /* __wlfc_host_driver_definitions_h__ */ diff --git a/bcmdhd.100.10.315.x/include/bcmdevs.h b/bcmdhd.100.10.315.x/include/bcmdevs.h index 247400d..edb9c40 100644 --- a/bcmdhd.100.10.315.x/include/bcmdevs.h +++ b/bcmdhd.100.10.315.x/include/bcmdevs.h @@ -276,12 +276,12 @@ #define BCM4362_D11AX_ID 0x4490 /* 4362 802.11ax dualband device */ #define BCM4362_D11AX2G_ID 0x4491 /* 4362 802.11ax 2.4G device */ #define BCM4362_D11AX5G_ID 0x4492 /* 4362 802.11ax 5G device */ -#define BCM43751_D11AX_ID 0x4490 /* 43751 802.11ax dualband device */ -#define BCM43751_D11AX2G_ID 0x4491 /* 43751 802.11ax 2.4G device */ -#define BCM43751_D11AX5G_ID 0x4492 /* 43751 802.11ax 5G device */ -#define BCM43752_D11AX_ID 0x4490 /* 43752 802.11ax dualband device */ -#define BCM43752_D11AX2G_ID 0x4491 /* 43752 802.11ax 2.4G device */ -#define BCM43752_D11AX5G_ID 0x4492 /* 43752 802.11ax 5G device */ +#define BCM43751_D11AX_ID 0x449a /* 43751 802.11ax dualband device */ +#define BCM43751_D11AX2G_ID 0x449b /* 43751 802.11ax 2.4G device */ +#define BCM43751_D11AX5G_ID 0x449c /* 43751 802.11ax 5G device */ +#define BCM43752_D11AX_ID 0x449d /* 43752 802.11ax dualband device */ +#define BCM43752_D11AX2G_ID 0x449e /* 43752 802.11ax 2.4G device */ +#define BCM43752_D11AX5G_ID 0x449f /* 43752 802.11ax 5G device */ #define BCM4364_D11AC_ID 0x4464 /* 4364 802.11ac dualband device */ #define BCM4364_D11AC2G_ID 0x446a /* 4364 802.11ac 2.4G device */ @@ -547,8 +547,12 @@ #define BCM4369_CHIP_GRPID BCM4369_CHIP_ID: \ case BCM4377_CHIP_ID -#define BCM4362_CHIP(chipid) (CHIPID(chipid) == BCM4362_CHIP_ID) -#define BCM4362_CHIP_GRPID BCM4362_CHIP_ID +#define BCM4362_CHIP(chipid) ((CHIPID(chipid) == BCM4362_CHIP_ID) || \ + (CHIPID(chipid) == BCM43751_CHIP_ID) || \ + (CHIPID(chipid) == BCM43752_CHIP_ID)) +#define BCM4362_CHIP_GRPID BCM4362_CHIP_ID: \ + case BCM43751_CHIP_ID: \ + case BCM43752_CHIP_ID #define BCM4365_CHIP_ID 0x4365 /* 4365 chipcommon chipid */ #define BCM4366_CHIP_ID 0x4366 /* 4366 chipcommon chipid */ diff --git a/bcmdhd.100.10.315.x/include/bcmevent.h b/bcmdhd.100.10.315.x/include/bcmevent.h index 1dbb7b5..97adab1 100644 --- a/bcmdhd.100.10.315.x/include/bcmevent.h +++ b/bcmdhd.100.10.315.x/include/bcmevent.h @@ -175,7 +175,11 @@ typedef union bcm_event_msg_u { #define WLC_E_ACTION_FRAME_COMPLETE 60 /* Action frame Tx complete */ #define WLC_E_PRE_ASSOC_IND 61 /* assoc request received */ #define WLC_E_PRE_REASSOC_IND 62 /* re-assoc request received */ +#ifdef CSI_SUPPORT +#define WLC_E_CSI 63 +#else #define WLC_E_CHANNEL_ADOPTED 63 +#endif /* CSI_SUPPORT */ #define WLC_E_AP_STARTED 64 /* AP started */ #define WLC_E_DFS_AP_STOP 65 /* AP stopped due to DFS */ #define WLC_E_DFS_AP_RESUME 66 /* AP resumed due to DFS */ @@ -591,6 +595,9 @@ typedef struct wl_event_data_natoe { #define WLC_E_IF_ROLE_WDS 2 /* WDS link */ #define WLC_E_IF_ROLE_P2P_GO 3 /* P2P Group Owner */ #define WLC_E_IF_ROLE_P2P_CLIENT 4 /* P2P Client */ +#ifdef WLMESH_CFG80211 +#define WLC_E_IF_ROLE_MESH 5 /* MESH */ +#endif /* WLMESH_CFG80211 */ #define WLC_E_IF_ROLE_IBSS 8 /* IBSS */ #define WLC_E_IF_ROLE_NAN 9 /* NAN */ diff --git a/bcmdhd.100.10.315.x/include/dhdioctl.h b/bcmdhd.100.10.315.x/include/dhdioctl.h index 8e74513..fa2675d 100644 --- a/bcmdhd.100.10.315.x/include/dhdioctl.h +++ b/bcmdhd.100.10.315.x/include/dhdioctl.h @@ -179,6 +179,12 @@ typedef 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/bcmdhd.100.10.315.x/include/epivers.h b/bcmdhd.100.10.315.x/include/epivers.h index 88c63db..db6ea09 100644 --- a/bcmdhd.100.10.315.x/include/epivers.h +++ b/bcmdhd.100.10.315.x/include/epivers.h @@ -46,6 +46,6 @@ #define EPI_VERSION_DEV 100.10.545 /* Driver Version String, ASCII, 32 chars max */ -#define EPI_VERSION_STR "100.10.545.4 (r826445-20190826-1) (amlogic-20190916-1)" +#define EPI_VERSION_STR "100.10.545.11 (r826445-20200610-1)" #endif /* _epivers_h_ */ diff --git a/bcmdhd.100.10.315.x/include/linux_osl.h b/bcmdhd.100.10.315.x/include/linux_osl.h index fd4384d..8d6fc34 100644 --- a/bcmdhd.100.10.315.x/include/linux_osl.h +++ b/bcmdhd.100.10.315.x/include/linux_osl.h @@ -340,7 +340,7 @@ extern uint64 osl_systztime_us(void); #define OSL_LOCALTIME_NS() osl_localtime_ns() #define OSL_GET_LOCALTIME(sec, usec) osl_get_localtime((sec), (usec)) #define OSL_SYSTZTIME_US() osl_systztime_us() -#define printf(fmt, args...) printk(fmt , ## args) +#define printf(fmt, args...) printk("[dhd] " fmt , ## args) #include /* for vsn/printf's */ #include /* for mem*, str* */ /* bcopy's: Linux kernel doesn't provide these (anymore) */ @@ -445,7 +445,11 @@ extern uint64 osl_systztime_us(void); /* map/unmap physical to virtual I/O */ #if !defined(CONFIG_MMC_MSM7X00A) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)) +#define REG_MAP(pa, size) ioremap((unsigned long)(pa), (unsigned long)(size)) +#else #define REG_MAP(pa, size) ioremap_nocache((unsigned long)(pa), (unsigned long)(size)) +#endif #else #define REG_MAP(pa, size) (void *)(0) #endif /* !defined(CONFIG_MMC_MSM7X00A */ @@ -617,7 +621,11 @@ extern unsigned long osl_spin_lock(void *lock); extern void osl_spin_unlock(void *lock, unsigned long flags); typedef struct osl_timespec { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)) + __kernel_old_time_t tv_sec; /* seconds */ +#else __kernel_time_t tv_sec; /* seconds */ +#endif __kernel_suseconds_t tv_usec; /* microseconds */ long tv_nsec; /* nanoseconds */ } osl_timespec_t; diff --git a/bcmdhd.100.10.315.x/include/wlioctl.h b/bcmdhd.100.10.315.x/include/wlioctl.h index 6dc718d..16aefaf 100644 --- a/bcmdhd.100.10.315.x/include/wlioctl.h +++ b/bcmdhd.100.10.315.x/include/wlioctl.h @@ -19890,6 +19890,13 @@ enum wl_sc_cmd { WL_SC_CMD_LAST }; +typedef struct wl_ext_auth_evt { + wlc_ssid_t ssid; + struct ether_addr bssid; + unsigned int key_mgmt_suite; + int status; +} wl_ext_auth_evt_t; + /* WBUS sub-command IDs for unit test */ #define WL_WBUS_INA_SLOT_START 0x01u /**< Inactive slot start sub command ID. */ #define WL_WBUS_INA_SLOT_STOP 0x02u /**< Inactive slot stop sub command ID. */ diff --git a/bcmdhd.100.10.315.x/include/wlioctl_defs.h b/bcmdhd.100.10.315.x/include/wlioctl_defs.h index aa73924..4f0ee1d 100644 --- a/bcmdhd.100.10.315.x/include/wlioctl_defs.h +++ b/bcmdhd.100.10.315.x/include/wlioctl_defs.h @@ -926,7 +926,8 @@ #define WLC_GET_RSSI_QDB 321 /* qdB portion of the RSSI */ #define WLC_DUMP_RATESET 322 #define WLC_ECHO 323 -#define WLC_LAST 324 /* The last ioctl. Also push this +#define WLC_SCB_AUTHENTICATE 325 +#define WLC_LAST 326 /* The last ioctl. Also push this * number when adding new ioctls */ /* @@ -998,6 +999,7 @@ #define WL_AUTH_OPEN_SYSTEM 0 /* d11 open authentication */ #define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */ #define WL_AUTH_OPEN_SHARED 2 /* try open, then shared if open failed w/rc 13 */ +#define WL_AUTH_SAE_KEY 3 /* d11 sae authentication */ #define WL_AUTH_FILS_SHARED 4 /* d11 fils shared key authentication */ #define WL_AUTH_FILS_SHARED_PFS 5 /* d11 fils shared key w/ pfs authentication */ #define WL_AUTH_FILS_PUBLIC 6 /* d11 fils public key authentication */ diff --git a/bcmdhd.100.10.315.x/linux_osl.c b/bcmdhd.100.10.315.x/linux_osl.c index 1e853cc..e48c0c8 100644 --- a/bcmdhd.100.10.315.x/linux_osl.c +++ b/bcmdhd.100.10.315.x/linux_osl.c @@ -1208,10 +1208,10 @@ osl_get_localtime(uint64 *sec, uint64 *usec) uint64 osl_systztime_us(void) { - struct timeval tv; + struct osl_timespec tv; uint64 tzusec; - do_gettimeofday(&tv); + osl_do_gettimeofday(&tv); /* apply timezone */ tzusec = (uint64)((tv.tv_sec - (sys_tz.tz_minuteswest * 60)) * USEC_PER_SEC); @@ -2064,13 +2064,19 @@ osl_dma_lock_init(osl_t *osh) void osl_do_gettimeofday(struct osl_timespec *ts) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) + struct timespec64 curtime; +#elif 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) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) + ktime_get_real_ts64(&curtime); + ts->tv_nsec = curtime.tv_nsec; + ts->tv_usec = curtime.tv_nsec / 1000; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) getnstimeofday(&curtime); ts->tv_nsec = curtime.tv_nsec; ts->tv_usec = curtime.tv_nsec / 1000; @@ -2085,9 +2091,15 @@ osl_do_gettimeofday(struct osl_timespec *ts) void osl_get_monotonic_boottime(struct osl_timespec *ts) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) + struct timespec64 curtime; +#else struct timespec curtime; +#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) + curtime = ktime_to_timespec64(ktime_get_boottime()); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) curtime = ktime_to_timespec(ktime_get_boottime()); #else get_monotonic_boottime(&curtime); diff --git a/bcmdhd.100.10.315.x/siutils.c b/bcmdhd.100.10.315.x/siutils.c index bfc245f..994430f 100644 --- a/bcmdhd.100.10.315.x/siutils.c +++ b/bcmdhd.100.10.315.x/siutils.c @@ -348,7 +348,7 @@ si_get_pmu_reg_addr(si_t *sih, uint32 offset) pmuaddr = SI_ENUM_BASE(sih) + offset; done: - printf("%s: addrRET: %x\n", __FUNCTION__, pmuaddr); + SI_MSG(("%s: addrRET: %x\n", __FUNCTION__, pmuaddr)); return pmuaddr; } diff --git a/bcmdhd.100.10.315.x/wl_android.c b/bcmdhd.100.10.315.x/wl_android.c index f914498..84a4667 100644 --- a/bcmdhd.100.10.315.x/wl_android.c +++ b/bcmdhd.100.10.315.x/wl_android.c @@ -2994,73 +2994,6 @@ extern int g_mhs_chan_for_cpcoex; #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, 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) @@ -3145,13 +3078,11 @@ wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str, goto done2; } -#ifdef WL_ESCAN - channel = wl_android_escan_autochannel(dev, band); + channel = wl_ext_autochannel(dev, ACS_FW_BIT|ACS_DRV_BIT, band); if (channel) goto done2; else goto done; -#endif /* WL_ESCAN */ ret = wldev_ioctl_get(dev, WLC_GET_SPECT_MANAGMENT, &spect, sizeof(spect)); if (ret) { @@ -3944,7 +3875,7 @@ wl_android_set_rps_cpus(struct net_device *dev, char *command) enable = command[strlen(CMD_RPSMODE) + 1] - '0'; error = dhd_rps_cpus_enable(dev, enable); -#if defined(DHDTCPACK_SUPPRESS) && defined(BCMPCIE) && defined(WL_CFG80211) +#if 0 //defined(DHDTCPACK_SUPPRESS) && defined(BCMPCIE) && defined(WL_CFG80211) if (!error) { void *dhdp = wl_cfg80211_get_dhdp(net); if (enable) { @@ -6512,6 +6443,7 @@ wl_android_set_wifi_on_flag(bool enable) #endif /* BT_OVER_SDIO */ #ifdef WL_STATIC_IF +#include struct net_device * wl_cfg80211_register_static_if(struct bcm_cfg80211 *cfg, u16 iftype, char *ifname) { @@ -6523,6 +6455,10 @@ wl_cfg80211_register_static_if(struct bcm_cfg80211 *cfg, u16 iftype, char *ifnam #ifdef DHD_USE_RANDMAC struct ether_addr ea_addr; #endif /* DHD_USE_RANDMAC */ +#ifdef CUSTOM_MULTI_MAC + char hw_ether[62]; + dhd_pub_t *dhd = cfg->pub; +#endif WL_INFORM_MEM(("[STATIC_IF] Enter (%s) iftype:%d\n", ifname, iftype)); @@ -6536,9 +6472,17 @@ wl_cfg80211_register_static_if(struct bcm_cfg80211 *cfg, u16 iftype, char *ifnam dhd_generate_mac_addr(&ea_addr); (void)memcpy_s(mac_addr, ETH_ALEN, ea_addr.octet, ETH_ALEN); #else +#if defined(CUSTOM_MULTI_MAC) + if (wifi_platform_get_mac_addr(dhd->info->adapter, hw_ether, "wlan1")) { +#endif /* Use primary mac with locally admin bit set */ (void)memcpy_s(mac_addr, ETH_ALEN, primary_ndev->dev_addr, ETH_ALEN); mac_addr[0] |= 0x02; +#if defined(CUSTOM_MULTI_MAC) + } else { + (void)memcpy_s(mac_addr, ETH_ALEN, hw_ether, ETH_ALEN); + } +#endif #endif /* DHD_USE_RANDMAC */ ndev = wl_cfg80211_allocate_if(cfg, ifidx, ifname, mac_addr, @@ -6601,6 +6545,10 @@ wl_cfg80211_static_if_open(struct net_device *net) struct net_device *primary_ndev = bcmcfg_to_prmry_ndev(cfg); u16 iftype = net->ieee80211_ptr ? net->ieee80211_ptr->iftype : 0; u16 wl_iftype, wl_mode; +#ifdef CUSTOM_MULTI_MAC + char hw_ether[62]; + dhd_pub_t *dhd = dhd_get_pub(net); +#endif WL_INFORM_MEM(("[STATIC_IF] dev_open ndev %p and wdev %p\n", net, net->ieee80211_ptr)); ASSERT(cfg->static_ndev == net); @@ -6612,7 +6560,15 @@ wl_cfg80211_static_if_open(struct net_device *net) #ifdef DHD_USE_RANDMAC wdev = wl_cfg80211_add_if(cfg, primary_ndev, wl_iftype, net->name, net->dev_addr); #else +#if defined(CUSTOM_MULTI_MAC) + if (wifi_platform_get_mac_addr(dhd->info->adapter, hw_ether, net->name)) { +#endif wdev = wl_cfg80211_add_if(cfg, primary_ndev, wl_iftype, net->name, NULL); +#if defined(CUSTOM_MULTI_MAC) + } else { + wdev = wl_cfg80211_add_if(cfg, primary_ndev, wl_iftype, net->name, hw_ether); + } +#endif #endif // endif if (!wdev) { ANDROID_ERROR(("[STATIC_IF] wdev is NULL, can't proceed")); diff --git a/bcmdhd.100.10.315.x/wl_android.h b/bcmdhd.100.10.315.x/wl_android.h index 3e989d2..f05470d 100644 --- a/bcmdhd.100.10.315.x/wl_android.h +++ b/bcmdhd.100.10.315.x/wl_android.h @@ -82,6 +82,29 @@ typedef struct _compat_android_wifi_priv_cmd { } \ } while (0) +#define WL_MSG_PRINT_RATE_LIMIT_PERIOD 1000000000u /* 1s in units of ns */ +#define WL_MSG_RLMT(name, cmp, size, arg1, args...) \ +do { \ + if (android_msg_level & ANDROID_MSG_LEVEL) { \ + static uint64 __err_ts = 0; \ + static uint32 __err_cnt = 0; \ + uint64 __cur_ts = 0; \ + static uint8 static_tmp[size]; \ + __cur_ts = local_clock(); \ + if (__err_ts == 0 || (__cur_ts > __err_ts && \ + (__cur_ts - __err_ts > WL_MSG_PRINT_RATE_LIMIT_PERIOD)) || \ + memcmp(&static_tmp, cmp, size)) { \ + __err_ts = __cur_ts; \ + memcpy(static_tmp, cmp, size); \ + printk(KERN_ERR "[dhd-%s] %s : [%u times] " arg1, \ + name, __func__, __err_cnt, ## args); \ + __err_cnt = 0; \ + } else { \ + ++__err_cnt; \ + } \ + } \ +} while (0) + /** * wl_android_init will be called from module init function (dhd_module_init now), similarly * wl_android_exit will be called from module exit function (dhd_module_cleanup now) @@ -97,17 +120,22 @@ int wl_handle_private_cmd(struct net_device *net, char *command, u32 cmd_len); 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(dhd_pub_t *dhd, struct net_device *dev, u32 channel); +int wl_ext_iapsta_update_net_device(struct net_device *net, int ifidx); +void wl_ext_add_remove_pm_enable_work(struct net_device *dev, bool add); +#ifdef PROPTX_MAXCOUNT +void wl_ext_update_wlfc_maxcount(struct dhd_pub *dhd); +int wl_ext_get_wlfc_maxcount(struct dhd_pub *dhd, int ifidx); +#endif /* PROPTX_MAXCOUNT */ int wl_ext_iapsta_alive_preinit(struct net_device *dev); int wl_ext_iapsta_alive_postinit(struct net_device *dev); 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 +u32 wl_ext_iapsta_update_channel(dhd_pub_t *dhd, struct net_device *dev, u32 channel); void wl_ext_iapsta_update_iftype(struct net_device *net, int ifidx, int wl_iftype); -#endif -#ifdef WL_STATIC_IF +bool wl_ext_iapsta_iftype_enabled(struct net_device *net, int wl_iftype); void wl_ext_iapsta_ifadding(struct net_device *net, int ifidx); +bool wl_ext_iapsta_mesh_creating(struct net_device *net); #endif extern int op_mode; #endif @@ -117,6 +145,8 @@ typedef struct bcol_gtk_para { char ptk[64]; char replay[8]; } bcol_gtk_para_t; +#define ACS_FW_BIT (1<<0) +#define ACS_DRV_BIT (1<<1) #if defined(WL_EXT_IAPSTA) || defined(USE_IW) typedef enum WL_EVENT_PRIO { PRIO_EVENT_IAPSTA, @@ -133,9 +163,18 @@ 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_ext_autochannel(struct net_device *dev, uint acs, uint32 band); 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 +#if defined(WL_CFG80211) +void wl_ext_bss_iovar_war(struct net_device *dev, s32 *val); +#endif enum wl_ext_status { WL_EXT_STATUS_DISCONNECTING = 0, WL_EXT_STATUS_DISCONNECTED, @@ -323,7 +362,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/bcmdhd.100.10.315.x/wl_android_ext.c b/bcmdhd.100.10.315.x/wl_android_ext.c index a1498ae..dde787c 100644 --- a/bcmdhd.100.10.315.x/wl_android_ext.c +++ b/bcmdhd.100.10.315.x/wl_android_ext.c @@ -16,7 +16,7 @@ #include #if defined(WL_WIRELESS_EXT) #include -#endif +#endif /* WL_WIRELESS_EXT */ #include #include #include @@ -27,7 +27,10 @@ #include #ifdef WL_CFG80211 #include -#endif +#endif /* WL_CFG80211 */ +#ifdef WL_ESCAN +#include +#endif /* WL_ESCAN */ #define AEXT_ERROR(name, arg1, args...) \ do { \ @@ -38,19 +41,19 @@ #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); \ + printk(KERN_INFO "[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); \ + printk(KERN_INFO "[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); \ + printk(KERN_INFO "[dhd-%s] AEXT-DBG) %s : " arg1, name, __func__, ## args); \ } \ } while (0) @@ -66,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 @@ -91,18 +94,21 @@ #define CMD_ISAM_ENABLE "ISAM_ENABLE" #define CMD_ISAM_DISABLE "ISAM_DISABLE" #define CMD_ISAM_STATUS "ISAM_STATUS" +#define CMD_ISAM_PEER_PATH "ISAM_PEER_PATH" +#define CMD_ISAM_PARAM "ISAM_PARAM" #ifdef PROP_TXSTATUS #ifdef PROP_TXSTATUS_VSDB #include extern int disable_proptx; #endif /* PROP_TXSTATUS_VSDB */ -#endif -#endif +#endif /* PROP_TXSTATUS */ +#endif /* WL_EXT_IAPSTA */ #define CMD_AUTOCHANNEL "AUTOCHANNEL" #define CMD_WL "WL" #ifdef WL_EXT_IAPSTA typedef enum APSTAMODE { + IUNKNOWN_MODE = 0, ISTAONLY_MODE = 1, IAPONLY_MODE = 2, ISTAAP_MODE = 3, @@ -120,6 +126,8 @@ typedef enum APSTAMODE { typedef enum IFMODE { ISTA_MODE = 1, IAP_MODE, + IGO_MODE, + IGC_MODE, IMESH_MODE } ifmode_t; @@ -179,6 +187,15 @@ 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 */ + struct delayed_work pm_enable_work; + struct mutex pm_sync; +#ifdef PROPTX_MAXCOUNT + int transit_maxcount; +#endif /* PROP_TXSTATUS_VSDB */ } wl_if_info_t; #define CSA_FW_BIT (1<<0) @@ -189,12 +206,18 @@ typedef struct wl_apsta_params { struct dhd_pub *dhd; int ioctl_ver; bool init; - bool rsdb; + int rsdb; bool vsdb; uint csa; + uint acs; + bool radar; apstamode_t apstamode; 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; #define MAX_AP_LINK_WAIT_TIME 3000 @@ -217,8 +240,12 @@ enum wifi_isam_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); -#endif +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 { @@ -226,7 +253,7 @@ typedef struct dhcpc_parameter { uint32 ip_serv; uint32 lease_time; } dhcpc_para_t; -#endif +#endif /* IDHCP */ #ifdef WL_EXT_WOWL #define WL_WOWL_TCPFIN (1 << 26) @@ -234,7 +261,7 @@ typedef struct wl_wowl_pattern2 { char cmd[4]; wl_wowl_pattern_t wowl_pattern; } wl_wowl_pattern2_t; -#endif +#endif /* WL_EXT_WOWL */ #ifdef WL_EXT_TCPKA typedef struct tcpka_conn { @@ -266,7 +293,7 @@ typedef struct tcpka_conn_info { uint32 seq; uint32 ack; } tcpka_conn_sess_info_t; -#endif +#endif /* WL_EXT_TCPKA */ static int wl_ext_wl_iovar(struct net_device *dev, char *command, int total_len); @@ -432,9 +459,6 @@ wl_ext_ch_to_chanspec(int ioctl_ver, int ch, join_params->params.chanspec_num = htod32(join_params->params.chanspec_num); - AEXT_ERROR("wlan", "join_params->params.chanspec_list[0]= %X, %d channels\n", - join_params->params.chanspec_list[0], - join_params->params.chanspec_num); } } @@ -484,7 +508,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) @@ -508,6 +632,38 @@ wl_ext_get_ioctl_ver(struct net_device *dev, int *ioctl_ver) return ret; } +void +wl_ext_bss_iovar_war(struct net_device *ndev, s32 *val) +{ + dhd_pub_t *dhd = dhd_get_pub(ndev); + uint chip; + bool need_war = false; + + chip = dhd_conf_get_chip(dhd); + + if (chip == BCM43362_CHIP_ID || chip == BCM4330_CHIP_ID || + chip == BCM43430_CHIP_ID || chip == BCM43012_CHIP_ID || + chip == BCM4345_CHIP_ID || chip == BCM4356_CHIP_ID || + chip == BCM4359_CHIP_ID) { + need_war = true; + } + + if (need_war) { + /* Few firmware branches have issues in bss iovar handling and + * that can't be changed since they are in production. + */ + if (*val == WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE) { + *val = WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE; + } else if (*val == WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE) { + *val = WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE; + } else { + /* Ignore for other bss enums */ + return; + } + AEXT_TRACE(ndev->name, "wl bss %d\n", *val); + } +} + static int wl_ext_set_chanspec(struct net_device *dev, int ioctl_ver, uint16 channel, chanspec_t *ret_chspec) @@ -564,7 +720,7 @@ set_channel: if ((err = wl_ext_iovar_setint(dev, "chanspec", fw_chspec)) == BCME_BADCHAN) { if (bw == WL_CHANSPEC_BW_80) goto change_bw; - wl_ext_ioctl(dev, WLC_SET_CHANNEL, &_chan, sizeof(_chan), 1); + err = wl_ext_ioctl(dev, WLC_SET_CHANNEL, &_chan, sizeof(_chan), 1); WL_MSG(dev->name, "channel %d\n", _chan); } else if (err) { AEXT_ERROR(dev->name, "failed to set chanspec error %d\n", err); @@ -762,6 +918,8 @@ wl_ext_connect(struct net_device *dev, struct wl_conn_info *conn_info) 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; @@ -786,7 +944,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); @@ -846,7 +1003,8 @@ set_ssid: memset(&join_params, 0, sizeof(join_params)); join_params_size = sizeof(join_params.ssid); - join_params.ssid.SSID_len = min((uint32)sizeof(join_params.ssid.SSID), conn_info->ssid.SSID_len); + join_params.ssid.SSID_len = min((uint32)sizeof(join_params.ssid.SSID), + conn_info->ssid.SSID_len); memcpy(&join_params.ssid.SSID, conn_info->ssid.SSID, join_params.ssid.SSID_len); join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len); if (memcmp(ðer_null, &conn_info->bssid, ETHER_ADDR_LEN)) @@ -866,9 +1024,13 @@ set_ssid: "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); + err = wl_ext_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, 1); exit: +#ifdef WL_EXT_IAPSTA + if (!err) + wl_ext_add_remove_pm_enable_work(dev, TRUE); +#endif /* WL_EXT_IAPSTA */ if (iovar_buf) kfree(iovar_buf); if (ext_join_params) @@ -880,65 +1042,296 @@ exit: void wl_ext_get_sec(struct net_device *dev, int ifmode, char *sec, int total_len) { - int auth=-1, wpa_auth=-1, wsec=0; + int auth=0, wpa_auth=0, 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 defined(WL_EXT_IAPSTA) && defined(WLMESH) +#ifdef WL_EXT_IAPSTA if (ifmode == IMESH_MODE) { - if (auth == 0 && wpa_auth == 0) { + if (auth == WL_AUTH_OPEN_SYSTEM && wpa_auth == WPA_AUTH_DISABLED) { bytes_written += snprintf(sec+bytes_written, total_len, "open"); - } else if (auth == 0 && wpa_auth == 128) { + } 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"); + bytes_written += snprintf(sec+bytes_written, total_len, "%d/0x%x", + auth, wpa_auth); } } else -#endif - if (auth == 0 && wpa_auth == 0) { - bytes_written += snprintf(sec+bytes_written, total_len, "open"); - } else if (auth == 1 && wpa_auth == 0) { - bytes_written += snprintf(sec+bytes_written, total_len, "shared"); - } else if (auth == 0 && wpa_auth == 4) { - bytes_written += snprintf(sec+bytes_written, total_len, "wpapsk"); - } else if (auth == 0 && wpa_auth == 128) { - bytes_written += snprintf(sec+bytes_written, total_len, "wpa2psk"); - } else if (auth == 0 && wpa_auth == 132) { - bytes_written += snprintf(sec+bytes_written, total_len, "wpawpa2psk"); +#endif /* WL_EXT_IAPSTA */ + { + 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_SHARED && wpa_auth == WPA3_AUTH_SAE_PSK) { + bytes_written += snprintf(sec+bytes_written, total_len, "wpa3"); + } else if ((auth == WL_AUTH_OPEN_SYSTEM || auth == WL_AUTH_SAE_KEY) && + wpa_auth == 0x20) { + bytes_written += snprintf(sec+bytes_written, total_len, "wpa3"); + } else { + bytes_written += snprintf(sec+bytes_written, total_len, "%d/0x%x", + auth, wpa_auth); + } + } + + if (mfp == WL_MFP_NONE) { + bytes_written += snprintf(sec+bytes_written, total_len, "/mfpn"); + } else 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"); } else { - bytes_written += snprintf(sec+bytes_written, total_len, "(%d/%d)", - auth, wpa_auth); + bytes_written += snprintf(sec+bytes_written, total_len, "/%d", mfp); } -#if defined(WL_EXT_IAPSTA) && defined(WLMESH) +#ifdef WL_EXT_IAPSTA if (ifmode == IMESH_MODE) { - if (wsec == 0) { + if (wsec == WSEC_NONE) { bytes_written += snprintf(sec+bytes_written, total_len, "/none"); } else { - bytes_written += snprintf(sec+bytes_written, total_len, "/sae"); + bytes_written += snprintf(sec+bytes_written, total_len, "/aes"); } } else -#endif - if (wsec == 0) { - bytes_written += snprintf(sec+bytes_written, total_len, "/none"); - } else if (wsec == 1) { - bytes_written += snprintf(sec+bytes_written, total_len, "/wep"); - } else if (wsec == 2 || wsec == 10) { - bytes_written += snprintf(sec+bytes_written, total_len, "/tkip"); - } else if (wsec == 4 || wsec == 12) { - bytes_written += snprintf(sec+bytes_written, total_len, "/aes"); - } else if (wsec == 6 || wsec == 14) { - bytes_written += snprintf(sec+bytes_written, total_len, "/tkipaes"); - } else { - bytes_written += snprintf(sec+bytes_written, total_len, "/%d", wsec); +#endif /* WL_EXT_IAPSTA */ + { + if (wsec == WSEC_NONE) { + 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|AES_ENABLED) || + wsec == (WSEC_SWFLAG|TKIP_ENABLED|AES_ENABLED)) { + bytes_written += snprintf(sec+bytes_written, total_len, "/tkipaes"); + } else if (wsec == TKIP_ENABLED || wsec == (WSEC_SWFLAG|TKIP_ENABLED)) { + bytes_written += snprintf(sec+bytes_written, total_len, "/tkip"); + } else if (wsec == AES_ENABLED || wsec == (WSEC_SWFLAG|AES_ENABLED)) { + bytes_written += snprintf(sec+bytes_written, total_len, "/aes"); + } else { + bytes_written += snprintf(sec+bytes_written, total_len, "/0x%x", wsec); + } + } + +} + +static bool +wl_ext_dfs_chan(uint16 chan) +{ + if (chan >= 52 && chan <= 144) + return TRUE; + return FALSE; +} + +static uint16 +wl_ext_get_default_chan(struct net_device *dev, + uint16 *chan_2g, uint16 *chan_5g, bool nodfs) +{ + struct dhd_pub *dhd = dhd_get_pub(dev); + uint16 chan_tmp = 0, chan = 0; + wl_uint32_list_t *list; + u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)]; + s32 ret = BCME_OK; + int i; + + *chan_2g = 0; + *chan_5g = 0; + memset(valid_chan_list, 0, sizeof(valid_chan_list)); + list = (wl_uint32_list_t *)(void *) valid_chan_list; + list->count = htod32(WL_NUMCHANNELS); + ret = wl_ext_ioctl(dev, WLC_GET_VALID_CHANNELS, valid_chan_list, + sizeof(valid_chan_list), 0); + if (ret == 0) { + for (i=0; icount); i++) { + chan_tmp = dtoh32(list->element[i]); + if (!dhd_conf_match_channel(dhd, chan_tmp)) + continue; + if (chan_tmp <= 13) { + *chan_2g = chan_tmp; + } else { + if (wl_ext_dfs_chan(chan_tmp) && nodfs) + continue; + else if (chan_tmp >= 36 && chan_tmp <= 161) + *chan_5g = chan_tmp; + } + } + } + + return chan; +} + +#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 +#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 */ + +static void +wl_ext_pm_work_handler(struct work_struct *work) +{ + struct wl_if_info *cur_if; + s32 pm = PM_FAST; + dhd_pub_t *dhd; + + BCM_SET_CONTAINER_OF(cur_if, work, struct wl_if_info, pm_enable_work.work); + + WL_TRACE(("%s: Enter\n", __FUNCTION__)); + + if (cur_if->dev == NULL) + return; + +#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_get_pub(cur_if->dev); + + if (!dhd || !dhd->up) { + AEXT_TRACE(cur_if->ifname, "dhd is null or not up\n"); + return; + } + if (dhd_conf_get_pm(dhd) >= 0) + pm = dhd_conf_get_pm(dhd); + wl_ext_ioctl(cur_if->dev, WLC_SET_PM, &pm, sizeof(pm), 1); +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \ + 4 && __GNUC_MINOR__ >= 6)) +_Pragma("GCC diagnostic pop") +#endif + DHD_PM_WAKE_UNLOCK(dhd); + +} + +void +wl_ext_add_remove_pm_enable_work(struct net_device *dev, bool add) +{ + dhd_pub_t *dhd = dhd_get_pub(dev); + struct wl_apsta_params *apsta_params = dhd->iapsta_params; + struct wl_if_info *cur_if = NULL, *tmp_if = NULL; + u16 wq_duration = 0; + s32 pm = PM_OFF; + int i; + + for (i=0; iif_info[i]; + if (tmp_if->dev && tmp_if->dev == dev) { + cur_if = tmp_if; + break; + } + } + + if (!cur_if) + return; + + mutex_lock(&cur_if->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(&cur_if->pm_enable_work)) { + cancel_delayed_work_sync(&cur_if->pm_enable_work); + DHD_PM_WAKE_UNLOCK(dhd); + } + + if (add) { + wq_duration = (WL_PM_ENABLE_TIMEOUT); + } + + /* It should schedule work item only if driver is up */ + if (dhd->up) { + if (dhd_conf_get_pm(dhd) >= 0) + pm = dhd_conf_get_pm(dhd); + wl_ext_ioctl(cur_if->dev, WLC_SET_PM, &pm, sizeof(pm), 1); + if (wq_duration) { + if (schedule_delayed_work(&cur_if->pm_enable_work, + msecs_to_jiffies((const unsigned int)wq_duration))) { + DHD_PM_WAKE_LOCK_TIMEOUT(dhd, wq_duration); + } else { + AEXT_ERROR(cur_if->ifname, "Can't schedule pm work handler\n"); + } + } + } + mutex_unlock(&cur_if->pm_sync); + +} + static int wl_ext_parse_wep(char *key, struct wl_wsec_key *wsec_key) { @@ -1058,35 +1451,35 @@ wl_ext_set_amode(struct wl_if_info *cur_if) #ifdef WLMESH if (cur_if->ifmode == IMESH_MODE) { if (amode == AUTH_SAE) { - auth = 0; - wpa_auth = 128; + auth = WL_AUTH_OPEN_SYSTEM; + wpa_auth = WPA2_AUTH_PSK; AEXT_INFO(dev->name, "SAE\n"); } else { - auth = 0; - wpa_auth = 0; + auth = WL_AUTH_OPEN_SYSTEM; + wpa_auth = WPA_AUTH_DISABLED; AEXT_INFO(dev->name, "Open System\n"); } } else -#endif +#endif /* WLMESH */ if (amode == AUTH_OPEN) { - auth = 0; - wpa_auth = 0; + auth = WL_AUTH_OPEN_SYSTEM; + wpa_auth = WPA_AUTH_DISABLED; AEXT_INFO(dev->name, "Open System\n"); } else if (amode == AUTH_SHARED) { - auth = 1; - wpa_auth = 0; + auth = WL_AUTH_SHARED_KEY; + wpa_auth = WPA_AUTH_DISABLED; AEXT_INFO(dev->name, "Shared Key\n"); } else if (amode == AUTH_WPAPSK) { - auth = 0; - wpa_auth = 4; + auth = WL_AUTH_OPEN_SYSTEM; + wpa_auth = WPA_AUTH_PSK; AEXT_INFO(dev->name, "WPA-PSK\n"); } else if (amode == AUTH_WPA2PSK) { - auth = 0; - wpa_auth = 128; + auth = WL_AUTH_OPEN_SYSTEM; + wpa_auth = WPA2_AUTH_PSK; AEXT_INFO(dev->name, "WPA2-PSK\n"); } else if (amode == AUTH_WPAWPA2PSK) { - auth = 0; - wpa_auth = 132; + auth = WL_AUTH_OPEN_SYSTEM; + wpa_auth = WPA2_AUTH_PSK | WPA_AUTH_PSK; AEXT_INFO(dev->name, "WPA/WPA2-PSK\n"); } #ifdef WLMESH @@ -1094,7 +1487,7 @@ wl_ext_set_amode(struct wl_if_info *cur_if) 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); @@ -1125,33 +1518,33 @@ wl_ext_set_emode(struct wl_apsta_params *apsta_params, #ifdef WLMESH if (cur_if->ifmode == IMESH_MODE) { if (amode == AUTH_SAE) { - wsec = 4; + wsec = AES_ENABLED; } else { - wsec = 0; + wsec = WSEC_NONE; } } else -#endif +#endif /* WLMESH */ if (emode == ENC_NONE) { - wsec = 0; + wsec = WSEC_NONE; AEXT_INFO(dev->name, "No securiy\n"); } else if (emode == ENC_WEP) { - wsec = 1; + wsec = WEP_ENABLED; wl_ext_parse_wep(key, &wsec_key); AEXT_INFO(dev->name, "WEP key \"%s\"\n", wsec_key.data); } else if (emode == ENC_TKIP) { - wsec = 2; + wsec = TKIP_ENABLED; psk.key_len = strlen(key); psk.flags = WSEC_PASSPHRASE; memcpy(psk.key, key, strlen(key)); AEXT_INFO(dev->name, "TKIP key \"%s\"\n", psk.key); } else if (emode == ENC_AES || amode == AUTH_SAE) { - wsec = 4; + wsec = AES_ENABLED; psk.key_len = strlen(key); psk.flags = WSEC_PASSPHRASE; memcpy(psk.key, key, strlen(key)); AEXT_INFO(dev->name, "AES key \"%s\"\n", psk.key); } else if (emode == ENC_TKIPAES) { - wsec = 6; + wsec = TKIP_ENABLED | AES_ENABLED; psk.key_len = strlen(key); psk.flags = WSEC_PASSPHRASE; memcpy(psk.key, key, strlen(key)); @@ -1159,7 +1552,7 @@ wl_ext_set_emode(struct wl_apsta_params *apsta_params, } if (dhd->conf->chip == BCM43430_CHIP_ID && cur_if->ifidx > 0 && wsec >= 2 && apsta_params->apstamode == ISTAAP_MODE) { - wsec |= 0x8; // terence 20180628: fix me, this is a workaround + wsec |= WSEC_SWFLAG; // terence 20180628: fix me, this is a workaround } wl_ext_iovar_setint(dev, "wsec", wsec); @@ -1168,7 +1561,7 @@ wl_ext_set_emode(struct wl_apsta_params *apsta_params, if (cur_if->ifmode == IMESH_MODE) { if (amode == AUTH_SAE) { s8 iovar_buf[WLC_IOCTL_SMLEN]; - AEXT_INFO(dev->name, "SAE key \"%s\"\n", key); + AEXT_INFO(dev->name, "AES 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), @@ -1179,7 +1572,7 @@ wl_ext_set_emode(struct wl_apsta_params *apsta_params, 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) { @@ -1303,103 +1696,270 @@ set_channel: } static bool -wl_ext_dfs_chan(struct wl_apsta_params *apsta_params, struct net_device *dev, - uint16 chan) +wl_ext_radar_detect(struct net_device *dev) { - u32 channel = chan; - s32 err = BCME_OK; - bool dfs = FALSE; - - if (chan <= CH_MAX_2G_CHANNEL) - return FALSE; + int ret = BCME_OK; + bool radar = FALSE; + s32 val = 0; - 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; - } + if ((ret = wldev_ioctl(dev, WLC_GET_RADAR, &val, sizeof(int), false) == 0)) { + radar = TRUE; } - return dfs; -} - -static void -wl_ext_wait_netif_change(struct wl_apsta_params *apsta_params, - struct wl_if_info *cur_if) -{ - rtnl_unlock(); - wait_event_interruptible_timeout(apsta_params->netif_change_event, - wl_get_isam_status(cur_if, IF_READY), - msecs_to_jiffies(MAX_AP_LINK_WAIT_TIME)); - rtnl_lock(); + return radar; } -bool -wl_ext_check_mesh_creating(struct net_device *net) +static struct wl_if_info * +wl_ext_if_enabled(struct wl_apsta_params *apsta_params, ifmode_t ifmode) { - struct dhd_pub *dhd = dhd_get_pub(net); - struct wl_apsta_params *apsta_params = dhd->iapsta_params; - struct wl_if_info *cur_if; + struct wl_if_info *tmp_if, *target_if = NULL; 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; + 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 FALSE; + + return target_if; } -bool -wl_ext_check_other_enabling(struct wl_apsta_params *apsta_params, - struct wl_if_info *cur_if) +#ifndef WL_STATIC_IF +s32 +wl_ext_add_del_bss(struct net_device *ndev, s32 bsscfg_idx, + int iftype, s32 del, u8 *addr) { - struct wl_if_info *tmp_if; - bool enabling = FALSE; - u32 timeout = 1; - int i; + s32 ret = BCME_OK; + s32 val = 0; + u8 ioctl_buf[WLC_IOCTL_SMLEN]; + struct { + s32 cfg; + s32 val; + struct ether_addr ea; + } bss_setbuf; - 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)); + AEXT_TRACE(ndev->name, "wl_iftype:%d del:%d \n", iftype, del); + + bzero(&bss_setbuf, sizeof(bss_setbuf)); + + /* AP=2, STA=3, up=1, down=0, val=-1 */ + if (del) { + val = WLC_AP_IOV_OP_DELETE; + } else if (iftype == WL_INTERFACE_CREATE_AP) { + /* Add/role change to AP Interface */ + AEXT_TRACE(ndev->name, "Adding AP Interface\n"); + val = WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE; + } else if (iftype == WL_INTERFACE_CREATE_STA) { + /* Add/role change to STA Interface */ + AEXT_TRACE(ndev->name, "Adding STA Interface\n"); + val = WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE; + } else { + AEXT_ERROR(ndev->name, "add_del_bss NOT supported for IFACE type:0x%x", iftype); + return -EINVAL; + } + + if (!del) { + wl_ext_bss_iovar_war(ndev, &val); + } + + bss_setbuf.cfg = htod32(bsscfg_idx); + bss_setbuf.val = htod32(val); + + if (addr) { + memcpy(&bss_setbuf.ea.octet, addr, ETH_ALEN); + } + + AEXT_INFO(ndev->name, "wl bss %d bssidx:%d\n", val, bsscfg_idx); + ret = wl_ext_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf), + ioctl_buf, WLC_IOCTL_SMLEN, NULL); + if (ret != 0) + WL_ERR(("'bss %d' failed with %d\n", val, ret)); + + return ret; +} + +static int +wl_ext_interface_ops(struct net_device *dev, + struct wl_apsta_params *apsta_params, int iftype, u8 *addr) +{ + s32 ret; + struct wl_interface_create_v2 iface; + wl_interface_create_v3_t iface_v3; + struct wl_interface_info_v1 *info; + wl_interface_info_v2_t *info_v2; + uint32 ifflags = 0; + bool use_iface_info_v2 = false; + u8 ioctl_buf[WLC_IOCTL_SMLEN]; + wl_wlc_version_t wlc_ver; + + /* Interface create */ + bzero(&iface, sizeof(iface)); + + if (addr) { + ifflags |= WL_INTERFACE_MAC_USE; + } + + ret = wldev_iovar_getbuf(dev, "wlc_ver", NULL, 0, + &wlc_ver, sizeof(wl_wlc_version_t), NULL); + if ((ret == BCME_OK) && (wlc_ver.wlc_ver_major >= 5)) { + ret = wldev_iovar_getbuf(dev, "interface_create", + &iface, sizeof(struct wl_interface_create_v2), + ioctl_buf, sizeof(ioctl_buf), NULL); + if ((ret == BCME_OK) && (*((uint32 *)ioctl_buf) == WL_INTERFACE_CREATE_VER_3)) { + use_iface_info_v2 = true; + bzero(&iface_v3, sizeof(wl_interface_create_v3_t)); + iface_v3.ver = WL_INTERFACE_CREATE_VER_3; + iface_v3.iftype = iftype; + iface_v3.flags = ifflags; + if (addr) { + memcpy(&iface_v3.mac_addr.octet, addr, ETH_ALEN); } - 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); + ret = wl_ext_iovar_getbuf(dev, "interface_create", + &iface_v3, sizeof(wl_interface_create_v3_t), + ioctl_buf, sizeof(ioctl_buf), NULL); + if (unlikely(ret)) { + WL_ERR(("Interface v3 create failed!! ret %d\n", ret)); + return ret; } } } - return enabling; + /* success case */ + if (use_iface_info_v2 == true) { + info_v2 = (wl_interface_info_v2_t *)ioctl_buf; + ret = info_v2->bsscfgidx; + } else { + /* Use v1 struct */ + iface.ver = WL_INTERFACE_CREATE_VER_2; + iface.iftype = iftype; + iface.flags = ifflags; + if (addr) { + memcpy(&iface.mac_addr.octet, addr, ETH_ALEN); + } + ret = wldev_iovar_getbuf(dev, "interface_create", + &iface, sizeof(struct wl_interface_create_v2), + ioctl_buf, sizeof(ioctl_buf), NULL); + if (ret == BCME_OK) { + info = (struct wl_interface_info_v1 *)ioctl_buf; + ret = info->bsscfgidx; + } + } + + AEXT_INFO(dev->name, "wl interface create success!! bssidx:%d \n", ret); + return ret; +} + +static void +wl_ext_wait_netif_change(struct wl_apsta_params *apsta_params, + struct wl_if_info *cur_if) +{ + rtnl_unlock(); + wait_event_interruptible_timeout(apsta_params->netif_change_event, + wl_get_isam_status(cur_if, IF_READY), + msecs_to_jiffies(MAX_AP_LINK_WAIT_TIME)); + rtnl_lock(); +} + +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) +{ + s32 ret; + + wl_set_isam_status(cur_if, IF_ADDING); + ret = wl_ext_interface_ops(dev, apsta_params, iftype, addr); + if (ret == BCME_UNSUPPORTED) { + wl_ext_add_del_bss(dev, 1, iftype, 0, addr); + } + 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; + 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]; + wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL); + } + 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 */ + +} +#endif /* WL_STATIC_IF */ + static void wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_params) { @@ -1408,7 +1968,7 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para struct wl_if_info *cur_if; s8 iovar_buf[WLC_IOCTL_SMLEN]; s32 val = 0; - int i, dfs = 1, disable_5g_band = 0; + int i; dhd = dhd_get_pub(dev); @@ -1428,7 +1988,6 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para cur_if->prio = PRIO_AP; cur_if->prefix = 'A'; snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_ap"); - dfs = 0; #ifdef WLMESH } else if (cur_if->ifmode == IMESH_MODE) { cur_if->channel = 1; @@ -1436,37 +1995,25 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para cur_if->prio = PRIO_MESH; cur_if->prefix = 'M'; snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_mesh"); - dfs = 0; -#endif - } - } - - if (!dfs && !apsta_params->vsdb) { - wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 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); +#ifdef WL_ESCAN + if (i == 0 && apsta_params->macs) + wl_mesh_escan_attach(dhd, cur_if); +#endif /* WL_ESCAN */ +#endif /* WLMESH */ } -#endif } 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 == ISTAAP_MODE || apstamode == ISTAAPAP_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; + 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, @@ -1474,7 +2021,7 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); } } else { - apsta_params->rsdb = FALSE; + apsta_params->rsdb = 0; } if (apstamode == ISTAONLY_MODE) { @@ -1503,7 +2050,7 @@ 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 == ISTAAP_MODE) { @@ -1557,122 +2104,45 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para 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 } -#endif +#endif /* WLMESH */ wl_ext_get_ioctl_ver(dev, &apsta_params->ioctl_ver); apsta_params->init = TRUE; - 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); + WL_MSG(dev->name, "apstamode=%d\n", apstamode); +} + +static int +wl_ext_isam_param(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 ret = -1; + char *pick_tmp, *data, *param; + int bytes_written=-1; + + AEXT_TRACE(dev->name, "command=%s, len=%d\n", command, total_len); + + pick_tmp = command; + param = bcmstrtok(&pick_tmp, " ", 0); // pick isam_param + param = bcmstrtok(&pick_tmp, " ", 0); // pick cmd + while (param != NULL) { + data = bcmstrtok(&pick_tmp, " ", 0); // pick data + if (!strcmp(param, "acs")) { + if (data) { + apsta_params->acs = simple_strtol(data, NULL, 0); + ret = 0; + } else { + bytes_written = snprintf(command, total_len, "%d", apsta_params->acs); + ret = bytes_written; + goto exit; + } + } + param = bcmstrtok(&pick_tmp, " ", 0); // pick cmd } -#endif +exit: + return ret; } static int @@ -1682,11 +2152,6 @@ wl_ext_isam_init(struct net_device *dev, char *command, int total_len) char *pch, *pick_tmp, *pick_tmp2, *param; struct wl_apsta_params *apsta_params = dhd->iapsta_params; int i; - -#ifdef WL_STATIC_IF - AEXT_ERROR(dev->name, "please remove WL_STATIC_IF from Makefile\n"); - return -1; -#endif if (apsta_params->init) { AEXT_ERROR(dev->name, "don't init twice\n"); @@ -1698,120 +2163,104 @@ wl_ext_isam_init(struct net_device *dev, char *command, int total_len) param = bcmstrtok(&pick_tmp, " ", 0); // skip iapsta_init param = bcmstrtok(&pick_tmp, " ", 0); while (param != NULL) { + pick_tmp2 = bcmstrtok(&pick_tmp, " ", 0); + if (!pick_tmp2) { + AEXT_ERROR(dev->name, "wrong param %s\n", param); + return -1; + } if (!strcmp(param, "mode")) { pch = NULL; - pick_tmp2 = bcmstrtok(&pick_tmp, " ", 0); - if (pick_tmp2) { - if (!strcmp(pick_tmp2, "sta")) { - apsta_params->apstamode = ISTAONLY_MODE; - } else if (!strcmp(pick_tmp2, "ap")) { - apsta_params->apstamode = IAPONLY_MODE; - } else if (!strcmp(pick_tmp2, "sta-ap")) { - 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; - } else if (!strcmp(pick_tmp2, "apsta")) { - 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, "sta-go") || - !strcmp(pick_tmp2, "gosta")) { - if (!FW_SUPPORTED(dhd, p2p)) { - return -1; - } - 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 - } else { - AEXT_ERROR(dev->name, "mode [sta|ap|sta-ap|ap-ap]\n"); + if (!strcmp(pick_tmp2, "sta")) { + apsta_params->apstamode = ISTAONLY_MODE; + } else if (!strcmp(pick_tmp2, "ap")) { + apsta_params->apstamode = IAPONLY_MODE; + } else if (!strcmp(pick_tmp2, "sta-ap")) { + 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; + } else if (!strcmp(pick_tmp2, "apsta")) { + 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, "sta-go") || + !strcmp(pick_tmp2, "gosta")) { + if (!FW_SUPPORTED(dhd, p2p)) { return -1; } - pch = bcmstrtok(&pick_tmp2, " -", 0); - for (i=0; iif_info[i].ifmode = ISTA_MODE; - else if (!strcmp(pch, "ap")) - apsta_params->if_info[i].ifmode = IAP_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(pch, "mesh")) { - if (dhd->conf->fw_type != FW_TYPE_MESH) { - AEXT_ERROR(dev->name, "wrong fw type\n"); - return -1; - } - apsta_params->if_info[i].ifmode = IMESH_MODE; + } 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 { + AEXT_ERROR(dev->name, "mode [sta|ap|sta-ap|ap-ap]\n"); + return -1; + } + pch = bcmstrtok(&pick_tmp2, " -", 0); + for (i=0; iif_info[i].ifmode = ISTA_MODE; + else if (!strcmp(pch, "ap")) + apsta_params->if_info[i].ifmode = IAP_MODE; +#ifdef WLMESH + else if (!strcmp(pch, "mesh")) { + if (dhd->conf->fw_type != FW_TYPE_MESH) { + AEXT_ERROR(dev->name, "wrong fw type\n"); + return -1; } -#endif - pch = bcmstrtok(&pick_tmp2, " -", 0); + apsta_params->if_info[i].ifmode = IMESH_MODE; } +#endif /* WLMESH */ + pch = bcmstrtok(&pick_tmp2, " -", 0); } } 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 { - AEXT_ERROR(dev->name, "rsdb [y|n]\n"); - return -1; - } - } + apsta_params->rsdb = (int)simple_strtol(pick_tmp2, NULL, 0); } else if (!strcmp(param, "vsdb")) { - pch = bcmstrtok(&pick_tmp, " ", 0); - if (pch) { - if (!strcmp(pch, "y")) { - apsta_params->vsdb = TRUE; - } else if (!strcmp(pch, "n")) { - apsta_params->vsdb = FALSE; - } else { - AEXT_ERROR(dev->name, "vsdb [y|n]\n"); - return -1; - } + if (!strcmp(pick_tmp2, "y")) { + apsta_params->vsdb = TRUE; + } else if (!strcmp(pick_tmp2, "n")) { + apsta_params->vsdb = FALSE; + } else { + AEXT_ERROR(dev->name, "vsdb [y|n]\n"); + return -1; } } else if (!strcmp(param, "csa")) { - pch = bcmstrtok(&pick_tmp, " ", 0); - if (pch) { - apsta_params->csa = (int)simple_strtol(pch, NULL, 0); - } + apsta_params->csa = (int)simple_strtol(pick_tmp2, NULL, 0); + } else if (!strcmp(param, "acs")) { + apsta_params->acs = (int)simple_strtol(pick_tmp2, NULL, 0); +#if defined(WLMESH) && defined(WL_ESCAN) + } else if (!strcmp(param, "macs")) { + apsta_params->macs = (int)simple_strtol(pick_tmp2, NULL, 0); +#endif /* WLMESH && WL_ESCAN */ } else if (!strcmp(param, "ifname")) { pch = NULL; - pick_tmp2 = bcmstrtok(&pick_tmp, " ", 0); - if (pick_tmp2) - pch = bcmstrtok(&pick_tmp2, " -", 0); + pch = bcmstrtok(&pick_tmp2, " -", 0); for (i=0; iif_info[i].ifname, pch); pch = bcmstrtok(&pick_tmp2, " -", 0); } } else if (!strcmp(param, "vifname")) { - pch = bcmstrtok(&pick_tmp, " ", 0); - if (pch) - strcpy(apsta_params->if_info[IF_VIF].ifname, pch); - else { - AEXT_ERROR(dev->name, "vifname [wlan1]\n"); - return -1; - } + strcpy(apsta_params->if_info[IF_VIF].ifname, pick_tmp2); } param = bcmstrtok(&pick_tmp, " ", 0); } @@ -1822,7 +2271,9 @@ wl_ext_isam_init(struct net_device *dev, char *command, int total_len) } wl_ext_iapsta_preinit(dev, apsta_params); +#ifndef WL_STATIC_IF wl_ext_iapsta_intf_add(dev, apsta_params); +#endif /* WL_STATIC_IF */ return 0; } @@ -2159,54 +2610,540 @@ wl_mesh_get_peer_results(struct net_device *dev, char *buf, int len) ret = peer_results->count; } - return ret; + return ret; +} + +static int +wl_ext_mesh_peer_status(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; + struct wl_if_info *cur_if; + mesh_peer_info_dump_t *peer_results; + mesh_peer_info_ext_t *mpi_ext; + char *peer_buf = NULL; + int peer_len = WLC_IOCTL_MAXLEN; + int dump_written = 0, ret; + + if (!data) { + 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; + } + for (i=0; iif_info[i]; + 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; + dump_written += wl_mesh_print_peer_info(mpi_ext, + peer_results->count, command+dump_written, + total_len-dump_written); + } + } 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); + } + } + } + + 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 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; + uchar mesh_oui[]={0x00, 0x22, 0xf4}; + int bytes_written = 0; + int ret = 0, i, vndr_ie_len; + uint8 *peer_bssid; + + wl_mesh_clear_vndr_ie(mesh_if->dev, mesh_oui); + + vndr_ie_len = WLC_IOCTL_MEDLEN; + vndr_ie = kmalloc(vndr_ie_len, GFP_KERNEL); + if (vndr_ie == NULL) { + AEXT_ERROR(mesh_if->dev->name, "Failed to allocate buffer of %d bytes\n", + WLC_IOCTL_MEDLEN); + ret = -1; + goto exit; + } + + bytes_written += snprintf(vndr_ie+bytes_written, vndr_ie_len, + "0x%02x%02x%02x", mesh_oui[0], mesh_oui[1], mesh_oui[2]); + + bytes_written += snprintf(vndr_ie+bytes_written, vndr_ie_len, + "%02x%02x%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, vndr_ie_len, + "%02x%02x%02x", MESH_INFO_MASTER_CHANNEL, 1, mesh_info->master_channel); + + bytes_written += snprintf(vndr_ie+bytes_written, vndr_ie_len, + "%02x%02x%02x", MESH_INFO_HOP_CNT, 1, mesh_info->hop_cnt); + + bytes_written += snprintf(vndr_ie+bytes_written, vndr_ie_len, + "%02x%02x", MESH_INFO_PEER_BSSID, mesh_info->hop_cnt*ETHER_ADDR_LEN); + for (i=0; ihop_cnt && ipeer_bssid[i]; + bytes_written += snprintf(vndr_ie+bytes_written, vndr_ie_len, + "%02x%02x%02x%02x%02x%02x", + peer_bssid[0], peer_bssid[1], peer_bssid[2], + peer_bssid[3], peer_bssid[4], 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); + } + +exit: + if (vndr_ie) + kfree(vndr_ie); + 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 = 0; + memset(mesh_info->peer_bssid, 0, MAX_HOP_LIST*ETHER_ADDR_LEN); + if (!wl_mesh_update_vndr_ie(apsta_params, mesh_if)) + updated = TRUE; + } + + return updated; +} + +static bool +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, bss_found = 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)); + bss_found = wl_escan_mesh_info(mesh_if->dev, mesh_if->escan, + &mpi_ext->ea, &peer_mesh_info); + if (bss_found && (mesh_info->master_channel == 0 || + peer_mesh_info.hop_cnt <= mesh_info->hop_cnt) && + memcmp(&peer_mesh_info.peer_bssid, &bssid, ETHER_ADDR_LEN)) { + 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; + memset(mesh_info->peer_bssid, 0, MAX_HOP_LIST*ETHER_ADDR_LEN); + memcpy(&mesh_info->peer_bssid, &mpi_ext->ea, ETHER_ADDR_LEN); + memcpy(&mesh_info->peer_bssid[1], peer_mesh_info.peer_bssid, + (MAX_HOP_LIST-1)*ETHER_ADDR_LEN); + updated = TRUE; + } + } + mpi_ext++; + } + if (updated) { + if (wl_mesh_update_vndr_ie(apsta_params, mesh_if)) { + AEXT_ERROR(mesh_if->dev->name, "update failed\n"); + mesh_info->master_channel = 0; + updated = FALSE; + goto exit; + } + } + } + + if (!mesh_info->master_channel) { + 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); + bss_found = wl_escan_mesh_peer(mesh_if->dev, mesh_if->escan, &cur_ssid, cur_chan, + sae, &peer_mesh_info); + + if (bss_found && peer_mesh_info.master_channel&& + (cur_chan != peer_mesh_info.master_channel)) { + WL_MSG(mesh_if->ifname, "moving channel %d -> %d\n", + cur_chan, peer_mesh_info.master_channel); + wl_ext_disable_iface(mesh_if->dev, mesh_if->ifname); + mesh_if->channel = peer_mesh_info.master_channel; + wl_ext_enable_iface(mesh_if->dev, mesh_if->ifname, 500); + } + } + +exit: + if (dump_buf) + kfree(dump_buf); + return updated; +} + +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; +} + +static uint +wl_mesh_update_peer_path(struct wl_if_info *mesh_if, char *command, + int total_len) +{ + struct wl_mesh_params peer_mesh_info; + uint32 count = 0; + char *dump_buf = NULL; + mesh_peer_info_dump_t *peer_results; + mesh_peer_info_ext_t *mpi_ext; + int bytes_written = 0, j, k; + bool bss_found = FALSE; + + 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) { + 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)); + bss_found = wl_escan_mesh_info(mesh_if->dev, mesh_if->escan, + &mpi_ext->ea, &peer_mesh_info); + if (bss_found) { + bytes_written += snprintf(command+bytes_written, total_len, + "\npeer=%pM, hop=%d", + &mpi_ext->ea, peer_mesh_info.hop_cnt); + for (j=1; jiapsta_params; + struct wl_mesh_params *mesh_info = &apsta_params->mesh_info; + struct wl_if_info *tmp_if; + uint16 chan = 0; + char *dump_buf = NULL; + int dump_len = WLC_IOCTL_MEDLEN; + int dump_written = 0; int i; - struct wl_if_info *cur_if; - mesh_peer_info_dump_t *peer_results; - mesh_peer_info_ext_t *mpi_ext; - char *peer_buf = NULL; - int peer_len = WLC_IOCTL_MAXLEN; - int dump_written = 0, ret; - if (!data) { - 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; + 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; + } } for (i=0; iif_info[i]; - 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; - dump_written += wl_mesh_print_peer_info(mpi_ext, - peer_results->count, command+dump_written, - total_len-dump_written); + tmp_if = &apsta_params->if_info[i]; + if (tmp_if->dev && tmp_if->ifmode == IMESH_MODE && apsta_params->macs) { + chan = wl_ext_get_chan(apsta_params, tmp_if->dev); + if (chan) { + dump_written += snprintf(dump_buf+dump_written, dump_len, + "[dhd-%s-%c] mbssid=%pM, mchan=%d, hop=%d, pbssid=%pM", + tmp_if->ifname, tmp_if->prefix, &mesh_info->master_bssid, + mesh_info->master_channel, mesh_info->hop_cnt, + &mesh_info->peer_bssid); + dump_written += wl_mesh_update_peer_path(tmp_if, + dump_buf+dump_written, dump_len-dump_written); } - } 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); } } + AEXT_INFO(dev->name, "%s\n", dump_buf); } - if (peer_buf) - kfree(peer_buf); + if (!command && dump_buf) + kfree(dump_buf); return dump_written; } -#endif +#endif /* WL_ESCAN */ +#endif /* WLMESH */ static int wl_ext_isam_status(struct net_device *dev, char *command, int total_len) @@ -2214,7 +3151,6 @@ 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} }; @@ -2241,13 +3177,10 @@ wl_ext_isam_status(struct net_device *dev, char *command, int total_len) 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) { @@ -2258,10 +3191,12 @@ wl_ext_isam_status(struct net_device *dev, char *command, int total_len) 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), " + "\n[dhd-%s-%c]: bssid=%pM, chan=%3d(0x%x %sMHz), " "rssi=%3d, sec=%-15s, SSID=\"%s\"", - tmp_if->ifname, tmp_if->prefix, chan?'E':'D', - now_if?"*":" ", &bssid, chan, chanspec, + tmp_if->ifname, tmp_if->prefix, &bssid, chan, chanspec, + CHSPEC_IS20(chanspec)?"20": + CHSPEC_IS40(chanspec)?"40": + CHSPEC_IS80(chanspec)?"80":"160", dtoh32(scb_val.val), sec, ssid.SSID); if (tmp_if->ifmode == IAP_MODE) { dump_written += snprintf(dump_buf+dump_written, dump_len, "\n"); @@ -2274,12 +3209,10 @@ wl_ext_isam_status(struct net_device *dev, char *command, int total_len) dump_written += wl_ext_mesh_peer_status(tmp_if->dev, NULL, dump_buf+dump_written, dump_len-dump_written); } -#endif +#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?"*":" "); + "\n[dhd-%s-%c]:", tmp_if->ifname, tmp_if->prefix); } } } @@ -2291,6 +3224,15 @@ wl_ext_isam_status(struct net_device *dev, char *command, int total_len) return dump_written; } +static bool +wl_ext_master_if(struct wl_if_info *cur_if) +{ + if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) + return TRUE; + else + return FALSE; +} + static int wl_ext_if_down(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if) { @@ -2344,10 +3286,13 @@ wl_ext_if_up(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if) return 0; } - if (wl_ext_dfs_chan(apsta_params, cur_if->dev, cur_if->channel)) { + if (wl_ext_dfs_chan(cur_if->channel) && !apsta_params->radar) { WL_MSG(cur_if->ifname, "[%c] skip DFS channel %d\n", cur_if->prefix, cur_if->channel); return 0; + } else if (!cur_if->channel) { + WL_MSG(cur_if->ifname, "[%c] no valid channel\n", cur_if->prefix); + return 0; } WL_MSG(cur_if->ifname, "[%c] Turning on...\n", cur_if->prefix); @@ -2419,6 +3364,7 @@ wl_ext_disable_iface(struct net_device *dev, char *ifname) if (cur_if->ifmode == ISTA_MODE) { wl_ext_ioctl(cur_if->dev, WLC_DISASSOC, NULL, 0, 1); + wl_ext_add_remove_pm_enable_work(dev, FALSE); } else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) { // deauthenticate all STA first memcpy(scbval.ea.octet, ðer_bcast, ETHER_ADDR_LEN); @@ -2450,38 +3396,33 @@ wl_ext_disable_iface(struct net_device *dev, char *ifname) dhd_wlfc_deinit(dhd); } } -#endif +#endif /* BCMSDIO */ #endif /* PROP_TXSTATUS_VSDB */ } - else if (apstamode == IDUALAP_MODE) { + else if (apstamode == IDUALAP_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); #ifdef WLMESH } else if (apstamode == ISTAMESH_MODE || apstamode == IMESHAP_MODE || - apstamode == ISTAAPMESH_MODE || apstamode == IMESHAPAP_MODE || - apstamode == ISTAAPAP_MODE) { + apstamode == ISTAAPMESH_MODE || apstamode == IMESHAPAP_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 - } -#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); + if (cur_if->ifmode == IMESH_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 */ } -#endif wl_clr_isam_status(cur_if, AP_CREATED); @@ -2532,6 +3473,34 @@ wl_ext_diff_band(uint16 chan1, uint16 chan2) return FALSE; } +static uint16 +wl_ext_same_band(struct wl_apsta_params *apsta_params, + struct wl_if_info *cur_if, bool nodfs) +{ + struct wl_if_info *tmp_if; + uint16 tmp_chan, target_chan = 0; + wl_prio_t max_prio; + int i; + + // find the max prio + max_prio = cur_if->prio; + for (i=0; iif_info[i]; + if (cur_if != tmp_if && wl_get_isam_status(tmp_if, IF_READY) && + tmp_if->prio > max_prio) { + tmp_chan = wl_ext_get_chan(apsta_params, tmp_if->dev); + if (wl_ext_dfs_chan(tmp_chan) && nodfs) + continue; + if (tmp_chan && !wl_ext_diff_band(cur_if->channel, tmp_chan)) { + target_chan = tmp_chan; + max_prio = tmp_if->prio; + } + } + } + + return target_chan; +} + 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) @@ -2589,12 +3558,10 @@ wl_ext_trigger_csa(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_ 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 (wl_ext_master_if(cur_if) && (apsta_params->csa & CSA_DRV_BIT)) { if (!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] no valid channel\n", cur_if->prefix); + } else if (wl_ext_dfs_chan(cur_if->channel) && !apsta_params->radar) { 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); @@ -2627,9 +3594,139 @@ wl_ext_trigger_csa(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_ return 0; } +static void +wl_ext_move_cur_dfs_channel(struct wl_apsta_params *apsta_params, + struct wl_if_info *cur_if) +{ + uint16 other_chan = 0, cur_chan = cur_if->channel; + uint16 chan_2g = 0, chan_5g = 0; + uint32 auto_band = WLC_BAND_2G; + + if (wl_ext_master_if(cur_if) && wl_ext_dfs_chan(cur_if->channel) && + !apsta_params->radar) { + + wl_ext_get_default_chan(cur_if->dev, &chan_2g, &chan_5g, TRUE); + if (!chan_2g && !chan_5g) { + cur_if->channel = 0; + WL_MSG(cur_if->ifname, "[%c] no valid channel\n", cur_if->prefix); + return; + } + + if (apsta_params->vsdb) { + if (chan_5g) { + cur_if->channel = chan_5g; + auto_band = WLC_BAND_5G; + other_chan = wl_ext_same_band(apsta_params, cur_if, TRUE); + } else { + cur_if->channel = chan_2g; + auto_band = WLC_BAND_2G; + other_chan = wl_ext_same_band(apsta_params, cur_if, TRUE); + } + if (!other_chan) { + other_chan = wl_ext_autochannel(cur_if->dev, ACS_FW_BIT|ACS_DRV_BIT, + auto_band); + } + if (other_chan) + cur_if->channel = other_chan; + } else if (apsta_params->rsdb) { + if (chan_5g) { + cur_if->channel = chan_5g; + auto_band = WLC_BAND_5G; + other_chan = wl_ext_same_band(apsta_params, cur_if, FALSE); + if (wl_ext_dfs_chan(other_chan) && chan_2g) { + cur_if->channel = chan_2g; + auto_band = WLC_BAND_2G; + other_chan = wl_ext_same_band(apsta_params, cur_if, TRUE); + } + } else { + cur_if->channel = chan_2g; + auto_band = WLC_BAND_2G; + other_chan = wl_ext_same_band(apsta_params, cur_if, TRUE); + } + if (!other_chan) { + other_chan = wl_ext_autochannel(cur_if->dev, ACS_FW_BIT|ACS_DRV_BIT, + auto_band); + } + if (other_chan) + cur_if->channel = other_chan; + } else { + cur_if->channel = chan_5g; + auto_band = WLC_BAND_5G; + other_chan = wl_ext_same_band(apsta_params, cur_if, FALSE); + if (wl_ext_dfs_chan(other_chan)) { + cur_if->channel = 0; + } + else if (!other_chan) { + other_chan = wl_ext_autochannel(cur_if->dev, ACS_FW_BIT|ACS_DRV_BIT, + auto_band); + } + if (other_chan) + cur_if->channel = other_chan; + } + WL_MSG(cur_if->ifname, "[%c] move channel %d => %d\n", + cur_if->prefix, cur_chan, cur_if->channel); + } +} + +static void +wl_ext_move_other_dfs_channel(struct wl_apsta_params *apsta_params, + struct wl_if_info *cur_if) +{ + uint16 other_chan = 0, cur_chan = cur_if->channel; + uint16 chan_2g = 0, chan_5g = 0; + uint32 auto_band = WLC_BAND_2G; + + if (wl_ext_master_if(cur_if) && wl_ext_dfs_chan(cur_if->channel) && + !apsta_params->radar) { + + wl_ext_get_default_chan(cur_if->dev, &chan_2g, &chan_5g, TRUE); + if (!chan_2g && !chan_5g) { + cur_if->channel = 0; + WL_MSG(cur_if->ifname, "[%c] no valid channel\n", cur_if->prefix); + return; + } + + if (apsta_params->vsdb) { + if (chan_5g) { + cur_if->channel = chan_5g; + auto_band = WLC_BAND_5G; + other_chan = wl_ext_same_band(apsta_params, cur_if, TRUE); + } else { + cur_if->channel = chan_2g; + auto_band = WLC_BAND_2G; + other_chan = wl_ext_same_band(apsta_params, cur_if, TRUE); + } + if (!other_chan) { + other_chan = wl_ext_autochannel(cur_if->dev, ACS_FW_BIT|ACS_DRV_BIT, + auto_band); + } + if (other_chan) + cur_if->channel = other_chan; + } else if (apsta_params->rsdb) { + if (chan_2g) { + cur_if->channel = chan_2g; + auto_band = WLC_BAND_2G; + other_chan = wl_ext_same_band(apsta_params, cur_if, TRUE); + if (!other_chan) { + other_chan = wl_ext_autochannel(cur_if->dev, ACS_FW_BIT|ACS_DRV_BIT, + auto_band); + } + } else { + cur_if->channel = 0; + } + if (other_chan) + cur_if->channel = other_chan; + } else { + cur_if->channel = 0; + } + WL_MSG(cur_if->ifname, "[%c] move channel %d => %d\n", + cur_if->prefix, cur_chan, cur_if->channel); + } +} + static uint16 wl_ext_move_cur_channel(struct wl_apsta_params *apsta_params, - struct net_device *dev, struct wl_if_info *cur_if) + struct wl_if_info *cur_if) { struct wl_if_info *tmp_if, *target_if = NULL; uint16 tmp_chan, target_chan = 0; @@ -2655,6 +3752,7 @@ wl_ext_move_cur_channel(struct wl_apsta_params *apsta_params, } } } + if (target_chan) { tmp_chan = wl_ext_get_chan(apsta_params, cur_if->dev); if (apsta_params->rsdb && tmp_chan && @@ -2669,20 +3767,16 @@ wl_ext_move_cur_channel(struct wl_apsta_params *apsta_params, cur_if->channel = target_chan; } } + exit: - if ((cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) && - 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; - } + wl_ext_move_cur_dfs_channel(apsta_params, cur_if); return cur_if->channel; } static void wl_ext_move_other_channel(struct wl_apsta_params *apsta_params, - struct net_device *dev, struct wl_if_info *cur_if) + struct wl_if_info *cur_if) { struct wl_if_info *tmp_if, *target_if=NULL; uint16 tmp_chan, target_chan = 0; @@ -2712,11 +3806,12 @@ wl_ext_move_other_channel(struct wl_apsta_params *apsta_params, 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; + wl_ext_move_other_dfs_channel(apsta_params, target_if); if (apsta_params->csa == 0) { wl_ext_if_down(apsta_params, target_if); - wl_ext_move_other_channel(apsta_params, dev, target_if); + wl_ext_move_other_channel(apsta_params, cur_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); } @@ -2727,8 +3822,53 @@ wl_ext_move_other_channel(struct wl_apsta_params *apsta_params, } +static bool +wl_ext_wait_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 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, ret = 0; @@ -2769,10 +3909,29 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) 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_wait_other_enabling(apsta_params, cur_if); + + if (wl_ext_master_if(cur_if) && apsta_params->acs) { + uint16 chan_2g, chan_5g; + uint auto_band; + auto_band = WL_GET_BAND(cur_if->channel); + wl_ext_get_default_chan(cur_if->dev, &chan_2g, &chan_5g, TRUE); + if ((chan_2g && auto_band == WLC_BAND_2G) || + (chan_5g && auto_band == WLC_BAND_5G)) { + cur_if->channel = wl_ext_autochannel(cur_if->dev, apsta_params->acs, + auto_band); + } else { + AEXT_ERROR(ifname, "invalid channel\n"); + ret = -1; + goto exit; + } + } + + wl_ext_move_cur_channel(apsta_params, cur_if); - wl_ext_move_cur_channel(apsta_params, dev, cur_if); - if (!cur_if->channel && cur_if->ifmode != ISTA_MODE) { + if (wl_ext_master_if(cur_if) && !cur_if->channel) { + AEXT_ERROR(ifname, "skip channel 0\n"); + ret = -1; goto exit; } @@ -2790,7 +3949,7 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) wl_clr_isam_status(cur_if, AP_CREATED); } - wl_ext_move_other_channel(apsta_params, dev, cur_if); + wl_ext_move_other_channel(apsta_params, cur_if); if (cur_if->ifidx > 0) { wl_ext_iovar_setbuf(cur_if->dev, "cur_etheraddr", (u8 *)cur_if->dev->dev_addr, @@ -2810,33 +3969,15 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) } } - if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) { + if (wl_ext_master_if(cur_if)) { wl_ext_set_bgnmode(cur_if); if (!cur_if->channel) { -#ifdef WL_CFG80211 - char *pick_tmp, *param; - char cmd[128]; - uint16 cur_chan; - cur_chan = 1; - snprintf(cmd, 128, "get_best_channels"); - wl_cfg80211_get_best_channels(dev, cmd, strlen(cmd)); - pick_tmp = cmd; - param = bcmstrtok(&pick_tmp, " ", 0); - while (param != NULL) { - if (!strnicmp(param, "2g=", strlen("2g="))) { - cur_chan = (int)simple_strtol(param+strlen("2g="), NULL, 10); - } else if (!strnicmp(param, "5g=", strlen("5g="))) { - cur_chan = (int)simple_strtol(param+strlen("5g="), NULL, 10); - } - param = bcmstrtok(&pick_tmp, " ", 0); - } - cur_if->channel = cur_chan; -#else cur_if->channel = 1; -#endif } - wl_ext_set_chanspec(cur_if->dev, apsta_params->ioctl_ver, cur_if->channel, - &fw_chspec); + ret = wl_ext_set_chanspec(cur_if->dev, apsta_params->ioctl_ver, + cur_if->channel, &fw_chspec); + if (ret) + goto exit; } wl_ext_set_amode(cur_if); @@ -2870,7 +4011,7 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) if (cur_if->ifmode == ISTA_MODE) { wl_ext_connect(cur_if->dev, &conn_info); } else { - if (apsta_params->rsdb) { + if (FW_SUPPORTED(dhd, rsdb)) { wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1); } else { bss_setbuf.cfg = htod32(cur_if->bssidx); @@ -2893,7 +4034,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 */ } } @@ -2927,14 +4068,17 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname) } else { AEXT_ERROR(cur_if->ifname, "wrong ifmode %d\n", cur_if->ifmode); } -#endif +#endif /* WLMESH */ } - if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) { + 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)) { + mutex_unlock(&apsta_params->usr_sync); 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); @@ -2963,7 +4107,7 @@ 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); + WL_MSG(ifname, "[%c] Exit ret=%d\n", cur_if->prefix, ret); mutex_unlock(&apsta_params->usr_sync); return ret; } @@ -2985,7 +4129,7 @@ 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 { @@ -2999,88 +4143,91 @@ wl_ext_iapsta_enable(struct net_device *dev, char *command, int total_len) return ret; } +#ifdef PROPTX_MAXCOUNT int -wl_ext_iapsta_alive_preinit(struct net_device *dev) +wl_ext_get_wlfc_maxcount(struct dhd_pub *dhd, int ifidx) { - struct dhd_pub *dhd = dhd_get_pub(dev); struct wl_apsta_params *apsta_params = dhd->iapsta_params; + struct wl_if_info *tmp_if, *cur_if = NULL; + int i, maxcount = WL_TXSTATUS_FREERUNCTR_MASK; - if (apsta_params->init == TRUE) { - AEXT_ERROR(dev->name, "don't init twice\n"); - return -1; - } - - AEXT_TRACE(dev->name, "Enter\n"); - - apsta_params->init = TRUE; - - return 0; -} - -int -wl_ext_iapsta_alive_postinit(struct net_device *dev) -{ - struct dhd_pub *dhd = dhd_get_pub(dev); - struct wl_apsta_params *apsta_params = dhd->iapsta_params; - s32 apsta = 0; - struct wl_if_info *cur_if; - int i; + if (!apsta_params->rsdb) + return maxcount; - wl_ext_iovar_getint(dev, "apsta", &apsta); - if (apsta == 1) { - apsta_params->apstamode = ISTAONLY_MODE; - apsta_params->if_info[IF_PIF].ifmode = ISTA_MODE; - op_mode = DHD_FLAG_STA_MODE; - } else { - apsta_params->apstamode = IAPONLY_MODE; - apsta_params->if_info[IF_PIF].ifmode = IAP_MODE; - op_mode = DHD_FLAG_HOSTAP_MODE; + for (i=0; iif_info[i]; + if (tmp_if->dev && tmp_if->ifidx == ifidx) { + cur_if = tmp_if; + maxcount = cur_if->transit_maxcount; + } } - // fix me: how to check it's ISTAAP_MODE or IDUALAP_MODE? - wl_ext_get_ioctl_ver(dev, &apsta_params->ioctl_ver); - WL_MSG(dev->name, "apstamode=%d\n", apsta_params->apstamode); + if (cur_if) + AEXT_INFO(cur_if->ifname, "update maxcount %d\n", maxcount); + else + AEXT_INFO("wlan", "update maxcount %d for ifidx %d\n", maxcount, ifidx); + return maxcount; +} + +void +wl_ext_update_wlfc_maxcount(struct dhd_pub *dhd) +{ + struct wl_apsta_params *apsta_params = dhd->iapsta_params; + struct wl_if_info *tmp_if; + bool band_5g = FALSE; + uint16 chan = 0; + int i, ret; + + if (!apsta_params->rsdb) + return; 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 + tmp_if = &apsta_params->if_info[i]; + if (tmp_if->dev) { + chan = wl_ext_get_chan(apsta_params, tmp_if->dev); + if (chan > CH_MAX_2G_CHANNEL) { + tmp_if->transit_maxcount = dhd->conf->proptx_maxcnt_5g; + ret = dhd_wlfc_update_maxcount(dhd, tmp_if->ifidx, + tmp_if->transit_maxcount); + if (ret == 0) + AEXT_INFO(tmp_if->ifname, "updated maxcount %d\n", + tmp_if->transit_maxcount); + band_5g = TRUE; + } } } - return op_mode; + for (i=0; iif_info[i]; + if (tmp_if->dev) { + chan = wl_ext_get_chan(apsta_params, tmp_if->dev); + if ((chan == 0) || (chan <= CH_MAX_2G_CHANNEL && chan >= CH_MIN_2G_CHANNEL)) { + if (chan == 0) { + tmp_if->transit_maxcount = WL_TXSTATUS_FREERUNCTR_MASK; + } else if (band_5g) { + tmp_if->transit_maxcount = dhd->conf->proptx_maxcnt_2g; + } else { + tmp_if->transit_maxcount = dhd->conf->proptx_maxcnt_5g; + } + ret = dhd_wlfc_update_maxcount(dhd, tmp_if->ifidx, + tmp_if->transit_maxcount); + if (ret == 0) + AEXT_INFO(tmp_if->ifname, "updated maxcount %d\n", + tmp_if->transit_maxcount); + } + } + } } +#endif /* PROPTX_MAXCOUNT */ -int +static int wl_ext_iapsta_event(struct net_device *dev, struct wl_apsta_params *apsta_params, wl_event_msg_t *e, void* data) { 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; uint32 event_type = ntoh32(e->event_type); uint32 status = ntoh32(e->status); @@ -3094,12 +4241,21 @@ wl_ext_iapsta_event(struct net_device *dev, 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) { AEXT_DBG(dev->name, "ifidx %d is not ready\n", e->ifidx); return -1; } - if (cur_if->ifmode == ISTA_MODE) { + if (cur_if->ifmode == ISTA_MODE || cur_if->ifmode == IGC_MODE) { if (event_type == WLC_E_LINK) { if (!(flags & WLC_EVENT_MSG_LINK)) { WL_MSG(cur_if->ifname, @@ -3107,24 +4263,46 @@ wl_ext_iapsta_event(struct net_device *dev, 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 { 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); +#ifdef PROPTX_MAXCOUNT + wl_ext_update_wlfc_maxcount(apsta_params->dhd); +#endif /* PROPTX_MAXCOUNT */ } 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 */ +#ifdef PROPTX_MAXCOUNT + wl_ext_update_wlfc_maxcount(apsta_params->dhd); +#endif /* PROPTX_MAXCOUNT */ } 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) { @@ -3137,35 +4315,49 @@ wl_ext_iapsta_event(struct net_device *dev, 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) || +#ifdef PROPTX_MAXCOUNT + wl_ext_update_wlfc_maxcount(apsta_params->dhd); +#endif /* PROPTX_MAXCOUNT */ + } + 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_clr_isam_status(cur_if, AP_CREATED); WL_MSG(cur_if->ifname, "[%c] Link down, reason=%d\n", cur_if->prefix, reason); +#ifdef PROPTX_MAXCOUNT + wl_ext_update_wlfc_maxcount(apsta_params->dhd); +#endif /* PROPTX_MAXCOUNT */ } else if ((event_type == WLC_E_ASSOC_IND || event_type == WLC_E_REASSOC_IND) && reason == DOT11_SC_SUCCESS) { WL_MSG(cur_if->ifname, "[%c] connected device %pM\n", cur_if->prefix, &e->addr); wl_ext_isam_status(cur_if->dev, NULL, 0); - } else if (event_type == WLC_E_DISASSOC_IND || + } + 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, + WL_MSG_RLMT(cur_if->ifname, &e->addr, ETHER_ADDR_LEN, "[%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; } +#ifdef WL_CFG80211 u32 wl_ext_iapsta_update_channel(dhd_pub_t *dhd, struct net_device *dev, u32 channel) @@ -3183,21 +4375,46 @@ wl_ext_iapsta_update_channel(dhd_pub_t *dhd, struct net_device *dev, } 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, - apsta_params->if_info[IF_PIF].dev, cur_if); + if (wl_ext_master_if(cur_if) && apsta_params->acs) { + uint auto_band = WL_GET_BAND(channel); + cur_if->channel = wl_ext_autochannel(cur_if->dev, apsta_params->acs, + auto_band); + } + channel = wl_ext_move_cur_channel(apsta_params, cur_if); if (channel) - wl_ext_move_other_channel(apsta_params, - apsta_params->if_info[IF_PIF].dev, cur_if); + wl_ext_move_other_channel(apsta_params, cur_if); + if (cur_if->ifmode == ISTA_MODE) + wl_set_isam_status(cur_if, STA_CONNECTING); } return channel; } -#ifdef WL_CFG80211 +static int +wl_ext_iftype_to_ifmode(struct net_device *net, int wl_iftype, ifmode_t *ifmode) +{ + switch (wl_iftype) { + case WL_IF_TYPE_STA: + *ifmode = ISTA_MODE; + break; + case WL_IF_TYPE_AP: + *ifmode = IAP_MODE; + break; + case WL_IF_TYPE_P2P_GO: + *ifmode = IGO_MODE; + break; + case WL_IF_TYPE_P2P_GC: + *ifmode = IGC_MODE; + break; + default: + AEXT_ERROR(net->name, "Unknown interface wl_iftype:0x%x\n", wl_iftype); + return BCME_ERROR; + } + return BCME_OK; +} + void wl_ext_iapsta_update_iftype(struct net_device *net, int ifidx, int wl_iftype) { @@ -3216,16 +4433,25 @@ wl_ext_iapsta_update_iftype(struct net_device *net, int ifidx, int wl_iftype) cur_if->ifmode = ISTA_MODE; cur_if->prio = PRIO_STA; cur_if->prefix = 'S'; - } else if (wl_iftype == WL_IF_TYPE_AP) { + } else if (wl_iftype == WL_IF_TYPE_AP && cur_if->ifmode != IMESH_MODE) { cur_if->ifmode = IAP_MODE; cur_if->prio = PRIO_AP; cur_if->prefix = 'A'; + } else if (wl_iftype == WL_IF_TYPE_P2P_GO) { + cur_if->ifmode = IGO_MODE; + cur_if->prio = PRIO_AP; + cur_if->prefix = 'P'; + apsta_params->vsdb = TRUE; + } else if (wl_iftype == WL_IF_TYPE_P2P_GC) { + cur_if->ifmode = IGC_MODE; + cur_if->prio = PRIO_STA; + cur_if->prefix = 'P'; + apsta_params->vsdb = TRUE; + wl_ext_iovar_setint(cur_if->dev, "assoc_retry_max", 3); } } } -#endif -#ifdef WL_STATIC_IF void wl_ext_iapsta_ifadding(struct net_device *net, int ifidx) { @@ -3239,7 +4465,144 @@ wl_ext_iapsta_ifadding(struct net_device *net, int ifidx) wl_set_isam_status(cur_if, IF_ADDING); } } -#endif + +bool +wl_ext_iapsta_iftype_enabled(struct net_device *net, 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; + ifmode_t ifmode = 0; + + wl_ext_iftype_to_ifmode(net, wl_iftype, &ifmode); + cur_if = wl_ext_if_enabled(apsta_params, ifmode); + if (cur_if) + return TRUE; + + return FALSE; +} + +bool +wl_ext_iapsta_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; +} +#endif /* WL_CFG80211 */ + +int +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; + + if (apsta_params->init == TRUE) { + AEXT_ERROR(dev->name, "don't init twice\n"); + return -1; + } + + AEXT_TRACE(dev->name, "Enter\n"); + + apsta_params->init = TRUE; + + return 0; +} + +int +wl_ext_iapsta_alive_postinit(struct net_device *dev) +{ + struct dhd_pub *dhd = dhd_get_pub(dev); + struct wl_apsta_params *apsta_params = dhd->iapsta_params; + s32 apsta = 0, ap = 0; + struct wl_if_info *cur_if; + int i; + + wl_ext_iovar_getint(dev, "apsta", &apsta); + wl_ext_ioctl(dev, WLC_GET_AP, &ap, sizeof(ap), 0); + if (apsta == 1 || ap == 0) { + apsta_params->apstamode = ISTAONLY_MODE; + apsta_params->if_info[IF_PIF].ifmode = ISTA_MODE; + op_mode = DHD_FLAG_STA_MODE; + } else { + apsta_params->apstamode = IAPONLY_MODE; + apsta_params->if_info[IF_PIF].ifmode = IAP_MODE; + op_mode = DHD_FLAG_HOSTAP_MODE; + } + // fix me: how to check it's ISTAAP_MODE or IDUALAP_MODE? + + wl_ext_get_ioctl_ver(dev, &apsta_params->ioctl_ver); + 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; +} + +static int +wl_ext_iapsta_get_rsdb(struct net_device *net, struct dhd_pub *dhd) +{ + s8 iovar_buf[WLC_IOCTL_SMLEN]; + wl_config_t *rsdb_p; + int ret = 0, rsdb = 0; + + if (dhd->conf->chip == BCM4359_CHIP_ID) { + ret = wldev_iovar_getbuf(net, "rsdb_mode", NULL, 0, + iovar_buf, WLC_IOCTL_SMLEN, NULL); + if (!ret) { + if (dhd->conf->fw_type == FW_TYPE_MESH) { + rsdb = 1; + } else { + rsdb_p = (wl_config_t *) iovar_buf; + rsdb = rsdb_p->config; + } + } + } + + AEXT_INFO(net->name, "rsdb_mode=%d\n", rsdb); + + return rsdb; +} static void wl_ext_iapsta_postinit(struct net_device *net, struct wl_if_info *cur_if) @@ -3250,10 +4613,11 @@ wl_ext_iapsta_postinit(struct net_device *net, struct wl_if_info *cur_if) 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) { - apsta_params->rsdb = TRUE; - } + apsta_params->rsdb = wl_ext_iapsta_get_rsdb(net, dhd); + apsta_params->vsdb = FALSE; + apsta_params->csa = 0; + apsta_params->acs = 0; + apsta_params->radar = wl_ext_radar_detect(net); if (dhd->conf->fw_type == FW_TYPE_MESH) { apsta_params->csa |= (CSA_FW_BIT | CSA_DRV_BIT); } @@ -3266,15 +4630,18 @@ wl_ext_iapsta_postinit(struct net_device *net, struct wl_if_info *cur_if) 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); + wl_ext_iovar_setint(cur_if->dev, "assoc_retry_max", 20); } #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 +#endif /* WLMESH */ } +#ifdef PROPTX_MAXCOUNT + wl_ext_update_wlfc_maxcount(dhd); +#endif /* PROPTX_MAXCOUNT */ } @@ -3300,7 +4667,43 @@ wl_ext_iapsta_attach_name(struct net_device *net, int ifidx) wl_set_isam_status(cur_if, IF_READY); #ifndef WL_STATIC_IF wake_up_interruptible(&apsta_params->netif_change_event); -#endif +#endif /* WL_STATIC_IF */ + } + + return 0; +} + +int +wl_ext_iapsta_update_net_device(struct net_device *net, int ifidx) +{ + struct dhd_pub *dhd = dhd_get_pub(net); + struct wl_apsta_params *apsta_params = dhd->iapsta_params; + struct wl_if_info *cur_if = NULL, *primary_if; + + AEXT_TRACE(net->name, "ifidx=%d\n", ifidx); + if (ifidx < MAX_IF_NUM) { + cur_if = &apsta_params->if_info[ifidx]; + } + if (cur_if && wl_get_isam_status(cur_if, IF_ADDING)) { + primary_if = &apsta_params->if_info[IF_PIF]; + if (strlen(cur_if->ifname)) { + memset(net->name, 0, sizeof(IFNAMSIZ)); + strcpy(net->name, cur_if->ifname); + net->name[IFNAMSIZ-1] = '\0'; + } +#ifndef WL_STATIC_IF + if (apsta_params->apstamode != IUNKNOWN_MODE && + 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) { + net->dev_addr[4] ^= 0x80; + net->dev_addr[4] += ifidx; + net->dev_addr[5] += (ifidx-1); + } + } +#endif /* WL_STATIC_IF */ } return 0; @@ -3320,7 +4723,6 @@ wl_ext_iapsta_attach_netdev(struct net_device *net, int ifidx, uint8 bssidx) if (ifidx == 0) { memset(apsta_params, 0, sizeof(struct wl_apsta_params)); apsta_params->dhd = dhd; - apsta_params->vsdb = FALSE; cur_if->dev = net; cur_if->ifidx = ifidx; cur_if->bssidx = bssidx; @@ -3332,30 +4734,22 @@ wl_ext_iapsta_attach_netdev(struct net_device *net, int ifidx, uint8 bssidx) strcpy(cur_if->ifname, net->name); init_waitqueue_head(&apsta_params->netif_change_event); mutex_init(&apsta_params->usr_sync); + mutex_init(&cur_if->pm_sync); + INIT_DELAYED_WORK(&cur_if->pm_enable_work, wl_ext_pm_work_handler); } 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'; - } -#ifndef WL_STATIC_IF - 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) { - net->dev_addr[4] ^= 0x80; - net->dev_addr[4] += ifidx; - net->dev_addr[5] += (ifidx-1); - } + 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 defined(WLMESH) && defined(WL_ESCAN) + if (cur_if->ifmode == IMESH_MODE && apsta_params->macs) { + wl_mesh_escan_attach(dhd, cur_if); } -#endif +#endif /* WLMESH && WL_ESCAN */ + mutex_init(&cur_if->pm_sync); + INIT_DELAYED_WORK(&cur_if->pm_enable_work, wl_ext_pm_work_handler); } return 0; @@ -3377,10 +4771,23 @@ wl_ext_iapsta_dettach_netdev(struct net_device *net, int ifidx) } if (ifidx == 0) { + wl_ext_add_remove_pm_enable_work(net, FALSE); 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 && wl_get_isam_status(cur_if, IF_READY)) { + } else if (cur_if && (wl_get_isam_status(cur_if, IF_READY) || + wl_get_isam_status(cur_if, IF_ADDING))) { + wl_ext_add_remove_pm_enable_work(net, FALSE); 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)); } @@ -3410,7 +4817,7 @@ wl_ext_iapsta_dettach(dhd_pub_t *pub) pub->iapsta_params = NULL; } } -#endif +#endif /* WL_EXT_IAPSTA */ #ifdef IDHCP /* @@ -3518,7 +4925,7 @@ wl_ext_dhcpc_param(struct net_device *dev, char *data, char *command, exit: return ret; } -#endif +#endif /* IDHCP */ int wl_ext_mkeep_alive(struct net_device *dev, char *data, char *command, @@ -3536,7 +4943,7 @@ wl_ext_mkeep_alive(struct net_device *dev, char *data, char *command, AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n", WLC_IOCTL_SMLEN); goto exit; } - packet = kmalloc(total_len, GFP_KERNEL); + packet = kmalloc(WLC_IOCTL_SMLEN, GFP_KERNEL); if (packet == NULL) { AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n", WLC_IOCTL_SMLEN); goto exit; @@ -3551,7 +4958,7 @@ wl_ext_mkeep_alive(struct net_device *dev, char *data, char *command, if (id < 0) id = 0; ret = wl_ext_iovar_getbuf(dev, "mkeep_alive", &id, sizeof(id), buf, - sizeof(buf), NULL); + total_len, NULL); if (!ret) { mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *) buf; bytes_written += snprintf(command+bytes_written, total_len, @@ -3598,10 +5005,11 @@ wl_ext_tcpka_conn_add(struct net_device *dev, char *data, char *command, 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", + sscanf(data, "%d %s %s %s %d %d %d %u %u %d %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); + &ack, &tcpwin, &tsval, &tsecr, &len, ka_payload); + ka_payload_len = strlen(ka_payload) / 2; 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", @@ -3632,8 +5040,12 @@ wl_ext_tcpka_conn_add(struct net_device *dev, char *data, char *command, tcpka->tsval = tsval; tcpka->tsecr = tsecr; tcpka->len = len; + ka_payload_len = wl_pattern_atoh(ka_payload, (char *)tcpka->ka_payload); + if (ka_payload_len == -1) { + AEXT_ERROR(dev->name,"rejecting ka_payload=%s\n", ka_payload); + goto exit; + } 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", @@ -3659,7 +5071,7 @@ wl_ext_tcpka_conn_enable(struct net_device *dev, char *data, char *command, { s8 iovar_buf[WLC_IOCTL_SMLEN]; tcpka_conn_sess_t tcpka_conn; - int ret; + int ret = 0; uint32 sess_id = 0, flag, interval = 0, retry_interval = 0, retry_count = 0; if (data) { @@ -3697,7 +5109,7 @@ wl_ext_tcpka_conn_info(struct net_device *dev, char *data, char *command, s8 iovar_buf[WLC_IOCTL_SMLEN]; tcpka_conn_sess_info_t *info = NULL; uint32 sess_id = 0; - int ret = 0; + int ret = 0, bytes_written = 0; if (data) { sscanf(data, "%d", &sess_id); @@ -3706,15 +5118,20 @@ wl_ext_tcpka_conn_info(struct net_device *dev, char *data, char *command, 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", + bytes_written += snprintf(command+bytes_written, total_len, + "id :%d\n" + "ipid :%d\n" + "seq :%u\n" + "ack :%u", sess_id, info->ipid, info->seq, info->ack); AEXT_INFO(dev->name, "%s\n", command); + ret = bytes_written; } } return ret; } -#endif +#endif /* WL_EXT_TCPKA */ static int wl_ext_rsdb_mode(struct net_device *dev, char *data, char *command, @@ -4047,67 +5464,9 @@ wl_ext_pkt_filter_enable(struct net_device *dev, char *data, char *command, return err; } -#endif +#endif /* PKT_FILTER_SUPPORT */ #ifdef SENDPROB -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", 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; -} - static int wl_ext_send_probreq(struct net_device *dev, char *data, char *command, int total_len) @@ -4276,7 +5635,7 @@ wl_ext_recv_probresp(struct net_device *dev, char *data, char *command, exit: return err; } -#endif +#endif /* SENDPROB */ static int wl_ext_gtk_key_info(struct net_device *dev, char *data, char *command, int total_len) @@ -4532,7 +5891,182 @@ wl_ext_wowl_wakeind(struct net_device *dev, char *data, char *command, return ret; } -#endif +#endif /* WL_EXT_WOWL */ + +#ifdef WL_GPIO_NOTIFY +typedef struct notify_payload { + int index; + int len; + char payload[128]; +} notify_payload_t; + +static int +wl_ext_gpio_notify(struct net_device *dev, char *data, char *command, + int total_len) +{ + s8 iovar_buf[WLC_IOCTL_SMLEN]; + notify_payload_t notify, *pnotify = NULL; + int i, ret = 0, bytes_written = 0; + char frame_str[WLC_IOCTL_SMLEN+3]; + + if (data) { + memset(¬ify, 0, sizeof(notify)); + memset(frame_str, 0, sizeof(frame_str)); + sscanf(data, "%d %s", ¬ify.index, frame_str); + + if (notify.index < 0) + notify.index = 0; + + if (strlen(frame_str)) { + notify.len = wl_pattern_atoh(frame_str, notify.payload); + if (notify.len == -1) { + AEXT_ERROR(dev->name, "rejecting pattern=%s\n", frame_str); + goto exit; + } + AEXT_INFO(dev->name, "index=%d, len=%d\n", notify.index, notify.len); + if (android_msg_level & ANDROID_INFO_LEVEL) + prhex("payload", (uchar *)notify.payload, notify.len); + ret = wl_ext_iovar_setbuf(dev, "bcol_gpio_noti", (char *)¬ify, + sizeof(notify), iovar_buf, WLC_IOCTL_SMLEN, NULL); + } else { + AEXT_INFO(dev->name, "index=%d\n", notify.index); + ret = wl_ext_iovar_getbuf(dev, "bcol_gpio_noti", ¬ify.index, + sizeof(notify.index), iovar_buf, sizeof(iovar_buf), NULL); + if (!ret) { + pnotify = (notify_payload_t *)iovar_buf; + bytes_written += snprintf(command+bytes_written, total_len, + "Id :%d\n" + "Packet :0x", + pnotify->index); + for (i=0; ilen; i++) { + bytes_written += snprintf(command+bytes_written, total_len, + "%02x", pnotify->payload[i]); + } + AEXT_TRACE(dev->name, "command result is\n%s\n", command); + ret = bytes_written; + } + } + } + +exit: + return ret; +} +#endif /* WL_GPIO_NOTIFY */ + +#ifdef CSI_SUPPORT +typedef struct csi_config { + /* Peer device mac address. */ + struct ether_addr addr; + /* BW to be used in the measurements. This needs to be supported both by the */ + /* device itself and the peer. */ + uint32 bw; + /* Time interval between measurements (units: 1 ms). */ + uint32 period; + /* CSI method */ + uint32 method; +} csi_config_t; + +typedef struct csi_list { + uint32 cnt; + csi_config_t configs[1]; +} csi_list_t; + +static int +wl_ether_atoe(const char *a, struct ether_addr *n) +{ + char *c = NULL; + int i = 0; + + memset(n, 0, ETHER_ADDR_LEN); + for (;;) { + n->octet[i++] = (uint8)strtoul(a, &c, 16); + if (!*c++ || i == ETHER_ADDR_LEN) + break; + a = c; + } + return (i == ETHER_ADDR_LEN); +} + +static int +wl_ext_csi(struct net_device *dev, char *data, char *command, int total_len) +{ + csi_config_t csi, *csip; + csi_list_t *csi_list; + int ret = -1, period=-1, i; + char mac[32], *buf = NULL; + struct ether_addr ea; + int bytes_written = 0; + + buf = kmalloc(WLC_IOCTL_SMLEN, GFP_KERNEL); + if (buf == NULL) { + AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n", WLC_IOCTL_SMLEN); + goto exit; + } + memset(buf, 0, WLC_IOCTL_SMLEN); + + if (data) { + sscanf(data, "%s %d", mac, &period); + ret = wl_ether_atoe(mac, &ea); + if (!ret) { + AEXT_ERROR(dev->name, "rejecting mac=%s, ret=%d\n", mac, ret); + goto exit; + } + AEXT_TRACE(dev->name, "mac=%pM, period=%d", &ea, period); + if (period > 0) { + memset(&csi, 0, sizeof(csi_config_t)); + bcopy(&ea, &csi.addr, ETHER_ADDR_LEN); + csi.period = period; + ret = wl_ext_iovar_setbuf(dev, "csi", (char *)&csi, sizeof(csi), + buf, WLC_IOCTL_SMLEN, NULL); + } else if (period == 0) { + memset(&csi, 0, sizeof(csi_config_t)); + bcopy(&ea, &csi.addr, ETHER_ADDR_LEN); + ret = wl_ext_iovar_setbuf(dev, "csi_del", (char *)&csi, sizeof(csi), + buf, WLC_IOCTL_SMLEN, NULL); + } else { + ret = wl_ext_iovar_getbuf(dev, "csi", &ea, ETHER_ADDR_LEN, buf, + WLC_IOCTL_SMLEN, NULL); + if (!ret) { + csip = (csi_config_t *) buf; + /* Dump all lists */ + bytes_written += snprintf(command+bytes_written, total_len, + "Mac :%pM\n" + "Period :%d\n" + "BW :%d\n" + "Method :%d\n", + &csip->addr, csip->period, csip->bw, csip->method); + AEXT_TRACE(dev->name, "command result is %s\n", command); + ret = bytes_written; + } + } + } + else { + ret = wl_ext_iovar_getbuf(dev, "csi_list", NULL, 0, buf, WLC_IOCTL_SMLEN, NULL); + if (!ret) { + csi_list = (csi_list_t *)buf; + bytes_written += snprintf(command+bytes_written, total_len, + "Total number :%d\n", csi_list->cnt); + for (i=0; icnt; i++) { + csip = &csi_list->configs[i]; + bytes_written += snprintf(command+bytes_written, total_len, + "Idx :%d\n" + "Mac :%pM\n" + "Period :%d\n" + "BW :%d\n" + "Method :%d\n\n", + i+1, &csip->addr, csip->period, csip->bw, csip->method); + } + AEXT_TRACE(dev->name, "command result is %s\n", command); + ret = bytes_written; + } + } + +exit: + if (buf) + kfree(buf); + return ret; +} +#endif /* CSI_SUPPORT */ typedef int (wl_ext_tpl_parse_t)(struct net_device *dev, char *data, char *command, int total_len); @@ -4554,29 +6088,35 @@ const wl_ext_iovar_tpl_t wl_ext_iovar_tpl_list[] = { {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 +#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 +#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 +#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 +#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 +#endif /* IDHCP */ +#ifdef WL_GPIO_NOTIFY + {WLC_GET_VAR, WLC_SET_VAR, "bcol_gpio_noti", wl_ext_gpio_notify}, +#endif /* WL_GPIO_NOTIFY */ +#ifdef CSI_SUPPORT + {WLC_GET_VAR, WLC_SET_VAR, "csi", wl_ext_csi}, +#endif /* CSI_SUPPORT */ }; /* @@ -4703,17 +6243,25 @@ wl_android_ext_priv_cmd(struct net_device *net, char *command, else if (strnicmp(command, CMD_ISAM_STATUS, strlen(CMD_ISAM_STATUS)) == 0) { *bytes_written = wl_ext_isam_status(net, command, total_len); } -#endif + else if (strnicmp(command, CMD_ISAM_PARAM, strlen(CMD_ISAM_PARAM)) == 0) { + *bytes_written = wl_ext_isam_param(net, command, total_len); + } +#if defined(WLMESH) && defined(WL_ESCAN) + else if (strnicmp(command, CMD_ISAM_PEER_PATH, strlen(CMD_ISAM_PEER_PATH)) == 0) { + *bytes_written = wl_ext_isam_peer_path(net, command, total_len); + } +#endif /* WLMESH && WL_ESCAN */ +#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 +#endif /* WL_CFG80211 */ #if defined(WL_WIRELESS_EXT) && defined(WL_ESCAN) else if (strnicmp(command, CMD_AUTOCHANNEL, strlen(CMD_AUTOCHANNEL)) == 0) { *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); } @@ -4776,7 +6324,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 ) { @@ -4784,13 +6332,14 @@ 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)]; wl_uint32_list_t *list; int ret; chanspec_t chanspec; + struct dhd_pub *dhd = dhd_get_pub(net); memset(b_band, -1, sizeof(b_band)); memset(a_band1, -1, sizeof(a_band1)); @@ -4807,6 +6356,8 @@ wl_ext_get_best_channel(struct net_device *net, } else { for (i = 0; i < dtoh32(list->count); i++) { ch = dtoh32(list->element[i]); + if (!dhd_conf_match_channel(dhd, ch)) + continue; if (ch < CH_MAX_2G_CHANNEL) b_band[ch-1] = 0; else if (ch <= 48) @@ -4824,13 +6375,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; @@ -4847,7 +6398,7 @@ wl_ext_get_best_channel(struct net_device *net, distance += distance_2g; for (j=0; j= 0 && abs(cen_ch-(1+j)) <= distance) - b_band[j] += 1; + b_band[j] += 1; } } else { distance += distance_5g; @@ -4865,7 +6416,7 @@ wl_ext_get_best_channel(struct net_device *net, } #if defined(BSSCACHE) node = node->next; -#endif +#endif /* BSSCACHE */ } *best_2g_ch = 0; @@ -4920,8 +6471,234 @@ wl_ext_get_best_channel(struct net_device *net, exit: return 0; } +#endif /* WL_CFG80211 || WL_ESCAN */ + +#ifdef WL_CFG80211 +#define APCS_MAX_RETRY 10 +static int +wl_ext_fw_apcs(struct net_device *dev, uint32 band) +{ + int channel = 0, chosen = 0, retry = 0, ret = 0, spect = 0; + u8 *reqbuf = NULL; + uint32 buf_size; + + ret = wldev_ioctl_get(dev, WLC_GET_SPECT_MANAGMENT, &spect, sizeof(spect)); + if (ret) { + AEXT_ERROR(dev->name, "ACS: error getting the spect, ret=%d\n", ret); + goto done; + } + + if (spect > 0) { + ret = wl_cfg80211_set_spect(dev, 0); + if (ret < 0) { + AEXT_ERROR(dev->name, "ACS: error while setting spect, ret=%d\n", ret); + goto done; + } + } + + reqbuf = kmalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL); + if (reqbuf == NULL) { + AEXT_ERROR(dev->name, "failed to allocate chanspec buffer\n"); + goto done; + } + memset(reqbuf, 0, CHANSPEC_BUF_SIZE); + + if (band == WLC_BAND_AUTO) { + AEXT_INFO(dev->name, "ACS full channel scan \n"); + reqbuf[0] = htod32(0); + } else if (band == WLC_BAND_5G) { + AEXT_INFO(dev->name, "ACS 5G band scan \n"); + if ((ret = wl_cfg80211_get_chanspecs_5g(dev, reqbuf, CHANSPEC_BUF_SIZE)) < 0) { + AEXT_ERROR(dev->name, "ACS 5g chanspec retreival failed! \n"); + goto done; + } + } else if (band == WLC_BAND_2G) { + /* + * If channel argument is not provided/ argument 20 is provided, + * Restrict channel to 2GHz, 20MHz BW, No SB + */ + AEXT_INFO(dev->name, "ACS 2G band scan \n"); + if ((ret = wl_cfg80211_get_chanspecs_2g(dev, reqbuf, CHANSPEC_BUF_SIZE)) < 0) { + AEXT_ERROR(dev->name, "ACS 2g chanspec retreival failed! \n"); + goto done; + } + } else { + AEXT_ERROR(dev->name, "ACS: No band chosen\n"); + goto done; + } + + 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) { + AEXT_ERROR(dev->name, "can't start auto channel scan, err = %d\n", ret); + channel = 0; + goto done; + } + + /* Wait for auto channel selection, max 3000 ms */ + if ((band == WLC_BAND_2G) || (band == WLC_BAND_5G)) { + OSL_SLEEP(500); + } else { + /* + * Full channel scan at the minimum takes 1.2secs + * even with parallel scan. max wait time: 3500ms + */ + OSL_SLEEP(1000); + } + + retry = APCS_MAX_RETRY; + while (retry--) { + ret = wldev_ioctl_get(dev, WLC_GET_CHANNEL_SEL, &chosen, + sizeof(chosen)); + if (ret < 0) { + chosen = 0; + } else { + chosen = dtoh32(chosen); + } + + if (chosen) { + int chosen_band; + int apcs_band; +#ifdef D11AC_IOTYPES + if (wl_cfg80211_get_ioctl_version() == 1) { + channel = LCHSPEC_CHANNEL((chanspec_t)chosen); + } else { + channel = CHSPEC_CHANNEL((chanspec_t)chosen); + } +#else + channel = CHSPEC_CHANNEL((chanspec_t)chosen); +#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 (apcs_band == chosen_band) { + WL_MSG(dev->name, "selected channel = %d\n", channel); + break; + } + } + AEXT_INFO(dev->name, "%d tried, ret = %d, chosen = 0x%x\n", + (APCS_MAX_RETRY - retry), ret, chosen); + OSL_SLEEP(250); + } + +done: + if (spect > 0) { + if ((ret = wl_cfg80211_set_spect(dev, spect) < 0)) { + AEXT_ERROR(dev->name, "ACS: error while setting spect\n"); + } + } + + if (reqbuf) { + kfree(reqbuf); + } + + return channel; +} +#endif /* WL_CFG80211 */ + +#ifdef WL_ESCAN +int +wl_ext_drv_apcs(struct net_device *dev, uint32 band) +{ + int ret = 0, channel = 0; + struct dhd_pub *dhd = dhd_get_pub(dev); + struct wl_escan_info *escan = NULL; + int retry = 0, retry_max, retry_interval = 250, up = 1; +#ifdef WL_CFG80211 + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); +#endif /* WL_CFG80211 */ + + escan = dhd->escan; + if (dhd) { + retry_max = WL_ESCAN_TIMER_INTERVAL_MS/retry_interval; + 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--) { + if (escan->escan_state == ESCAN_STATE_SCANING +#ifdef WL_CFG80211 + || wl_get_drv_status_all(cfg, SCANNING) +#endif + ) + { + AEXT_INFO(dev->name, "Scanning %d tried, ret = %d\n", + (retry_max - retry), ret); + } else { + escan->autochannel = 1; + ret = wl_escan_set_scan(dev, dhd, NULL, 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; + } + AEXT_INFO(dev->name, "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 */ + +int +wl_ext_autochannel(struct net_device *dev, uint acs, uint32 band) +{ + int channel = 0; + uint16 chan_2g, chan_5g; + + AEXT_INFO(dev->name, "acs=0x%x, band=%d \n", acs, band); + +#ifdef WL_CFG80211 + if (acs & ACS_FW_BIT) { + int ret = 0; + ret = wldev_ioctl_get(dev, WLC_GET_CHANNEL_SEL, &channel, sizeof(channel)); + channel = 0; + if (ret != BCME_UNSUPPORTED) + channel = wl_ext_fw_apcs(dev, band); + if (channel) + return channel; + } #endif +#ifdef WL_ESCAN + if (acs & ACS_DRV_BIT) + channel = wl_ext_drv_apcs(dev, band); +#endif /* WL_ESCAN */ + + if (channel == 0) { + wl_ext_get_default_chan(dev, &chan_2g, &chan_5g, TRUE); + if (band == WLC_BAND_5G) { + channel = chan_5g; + } else { + channel = chan_2g; + } + AEXT_ERROR(dev->name, "ACS failed. Fall back to default channel (%d) \n", channel); + } + + return channel; +} + #if defined(RSSIAVG) void wl_free_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl) @@ -5215,7 +6992,7 @@ wl_get_avg_rssi(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, void *addr) } return (int16)rssi; } -#endif +#endif /* RSSIAVG */ #if defined(RSSIOFFSET) int @@ -5223,7 +7000,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; @@ -5236,10 +7013,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 @@ -5358,7 +7135,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; @@ -5369,7 +7146,7 @@ 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 +#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++; @@ -5381,7 +7158,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; @@ -5389,7 +7166,7 @@ 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 +#endif /* SORT_BSS_BY_RSSI */ struct osl_timespec now, timeout; if (!ss_list->count) @@ -5461,14 +7238,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) @@ -5485,13 +7262,13 @@ 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); } @@ -5501,6 +7278,6 @@ wl_release_bss_cache_ctrl(wl_bss_cache_ctrl_t *bss_cache_ctrl) AEXT_TRACE("wlan", "Enter\n"); wl_free_bss_cache(bss_cache_ctrl); } -#endif +#endif /* BSSCACHE */ diff --git a/bcmdhd.100.10.315.x/wl_cfg80211.c b/bcmdhd.100.10.315.x/wl_cfg80211.c index 7a58237..b7427b3 100644 --- a/bcmdhd.100.10.315.x/wl_cfg80211.c +++ b/bcmdhd.100.10.315.x/wl_cfg80211.c @@ -554,6 +554,9 @@ static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_pmksa *pmksa); static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev); +#ifdef WL_CLIENT_SAE +static bool wl_is_pmkid_available(struct net_device *dev, const u8 *bssid); +#endif /* WL_CLIENT_SAE */ #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || defined(WL_COMPAT_WIRELESS) #if (defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)) || (LINUX_VERSION_CODE < \ KERNEL_VERSION(3, 16, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) @@ -680,6 +683,15 @@ wl_mbo_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data); #endif /* WL_MBO */ +#ifdef WL_CLIENT_SAE +static s32 wl_notify_connect_status_bss(struct bcm_cfg80211 *cfg, struct net_device *ndev, + const wl_event_msg_t *e, void *data); +static s32 wl_notify_start_auth(struct bcm_cfg80211 *cfg, + bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data); +static s32 wl_cfg80211_external_auth(struct wiphy *wiphy, + struct net_device *dev, struct cfg80211_external_auth_params *ext_auth); +#endif /* WL_CLIENT_SAE */ + /* * register/deregister parent device */ @@ -747,6 +759,14 @@ static int wl_cfg80211_get_rsn_capa(const bcm_tlv_t *wpa2ie, const u8** rsn_cap) static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev, dhd_pub_t *data); static void wl_free_wdev(struct bcm_cfg80211 *cfg); +#ifdef CONFIG_CFG80211_INTERNAL_REGDB +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 11)) +static int +#else +static void +#endif /* kernel version < 3.10.11 */ +wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request); +#endif /* CONFIG_CFG80211_INTERNAL_REGDB */ static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, wl_bss_info_t *bi, bool update_ssid); static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, bool update_ssid); @@ -1417,6 +1437,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_CFG80211 + [NL80211_IFTYPE_MESH_POINT] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) + }, +#endif /* WLMESH_CFG80211 */ [NL80211_IFTYPE_ADHOC] = { .tx = 0xffff, .rx = BIT(IEEE80211_STYPE_ACTION >> 4) @@ -1425,6 +1452,9 @@ wl_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { .tx = 0xffff, .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) +#ifdef WL_CLIENT_SAE + | BIT(IEEE80211_STYPE_AUTH >> 4) +#endif /* WL_CLIENT_SAE */ }, [NL80211_IFTYPE_AP] = { .tx = 0xffff, @@ -4110,77 +4140,6 @@ exit: return ret; } -bool -wl_customer6_legacy_chip_check(struct bcm_cfg80211 *cfg, - struct net_device *ndev) -{ - u32 chipnum; - wlc_rev_info_t revinfo; - int ret; - - /* Get the device rev info */ - memset(&revinfo, 0, sizeof(revinfo)); - ret = wldev_ioctl_get(ndev, WLC_GET_REVINFO, &revinfo, sizeof(revinfo)); - if (ret < 0) { - WL_ERR(("%s: GET revinfo FAILED. ret:%d\n", __FUNCTION__, ret)); - ASSERT(0); - return false; - } - - WL_DBG(("%s: GET_REVINFO device 0x%x, vendor 0x%x, chipnum 0x%x\n", __FUNCTION__, - dtoh32(revinfo.deviceid), dtoh32(revinfo.vendorid), dtoh32(revinfo.chipnum))); - chipnum = revinfo.chipnum; - if ((chipnum == BCM4350_CHIP_ID) || (chipnum == BCM4355_CHIP_ID) || - (chipnum == BCM4345_CHIP_ID) || (chipnum == BCM43430_CHIP_ID) || - (chipnum == BCM43362_CHIP_ID) || (chipnum == BCM43012_CHIP_ID) || - (chipnum == BCM4356_CHIP_ID)) { - /* WAR required */ - return true; - } - - return false; -} - -void -wl_bss_iovar_war(struct bcm_cfg80211 *cfg, - struct net_device *ndev, s32 *val) -{ - u32 chipnum; - wlc_rev_info_t revinfo; - int ret; - bool need_war = false; - - /* Get the device rev info */ - memset(&revinfo, 0, sizeof(revinfo)); - ret = wldev_ioctl_get(ndev, WLC_GET_REVINFO, &revinfo, sizeof(revinfo)); - if (ret < 0) { - WL_ERR(("%s: GET revinfo FAILED. ret:%d\n", __FUNCTION__, ret)); - } else { - WL_DBG(("%s: GET_REVINFO device 0x%x, vendor 0x%x, chipnum 0x%x\n", __FUNCTION__, - dtoh32(revinfo.deviceid), dtoh32(revinfo.vendorid), dtoh32(revinfo.chipnum))); - chipnum = revinfo.chipnum; - if ((chipnum == BCM4359_CHIP_ID) || (chipnum == BCM43596_CHIP_ID)) { - /* WAR required */ - need_war = true; - } - } - - if (wl_customer6_legacy_chip_check(cfg, ndev) || need_war) { - /* Few firmware branches have issues in bss iovar handling and - * that can't be changed since they are in production. - */ - if (*val == WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE) { - *val = WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE; - } else if (*val == WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE) { - *val = WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE; - } else { - /* Ignore for other bss enums */ - return; - } - WL_DBG(("wl bss %d\n", *val)); - } -} - s32 wl_cfg80211_add_del_bss(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bsscfg_idx, @@ -4216,7 +4175,7 @@ wl_cfg80211_add_del_bss(struct bcm_cfg80211 *cfg, } if (!del) { - wl_bss_iovar_war(cfg, ndev, &val); + wl_ext_bss_iovar_war(ndev, &val); } bss_setbuf.cfg = htod32(bsscfg_idx); @@ -4226,7 +4185,7 @@ wl_cfg80211_add_del_bss(struct bcm_cfg80211 *cfg, memcpy(&bss_setbuf.ea.octet, addr, ETH_ALEN); } - WL_INFORM_MEM(("wl bss %d bssidx:%d iface:%s \n", val, bsscfg_idx, ndev->name)); + WL_MSG(ndev->name, "wl bss %d bssidx:%d\n", val, bsscfg_idx); ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync); if (ret != 0) @@ -4307,6 +4266,11 @@ wl_iftype_to_mode(wl_iftype_t iftype) case WL_IF_TYPE_IBSS: mode = WL_MODE_IBSS; break; +#ifdef WLMESH_CFG80211 + case WL_IF_TYPE_MESH: + mode = WL_MODE_MESH; + break; +#endif /* WLMESH_CFG80211 */ default: WL_ERR(("Unsupported type:%d\n", iftype)); break; @@ -4353,6 +4317,12 @@ cfg80211_to_wl_iftype(uint16 type, uint16 *role, uint16 *mode) *mode = WL_MODE_NAN; break; #endif // endif +#ifdef WLMESH_CFG80211 + case NL80211_IFTYPE_MESH_POINT: + *role = WLC_E_IF_ROLE_AP; + *mode = WL_MODE_MESH; + break; +#endif /* WLMESH_CFG80211 */ default: WL_ERR(("Unknown interface type:0x%x\n", type)); return BCME_ERROR; @@ -4402,6 +4372,12 @@ wl_role_to_cfg80211_type(uint16 role, uint16 *wl_iftype, uint16 *mode) *mode = WL_MODE_AP; return NL80211_IFTYPE_AP; #endif +#ifdef WLMESH_CFG80211 + case WLC_E_IF_ROLE_MESH: + *wl_iftype = WL_IF_TYPE_MESH; + *mode = WL_MODE_MESH; + return NL80211_IFTYPE_MESH_POINT; +#endif /* WLMESH_CFG80211 */ default: WL_ERR(("Unknown interface role:0x%x. Forcing type station\n", role)); @@ -4444,6 +4420,13 @@ wl_cfg80211_post_ifcreate(struct net_device *ndev, return NULL; } +#if defined(WLMESH_CFG80211) && defined(WL_EXT_IAPSTA) + if (wl_ext_iapsta_mesh_creating(ndev)) { + event->role = WLC_E_IF_ROLE_MESH; + WL_MSG(ndev->name, "change role to WLC_E_IF_ROLE_MESH\n"); + } +#endif /* WLMESH_CFG80211 && WL_EXT_IAPSTA */ + iface_type = wl_role_to_cfg80211_type(event->role, &wl_iftype, &mode); if (iface_type < 0) { /* Unknown iface type */ @@ -4451,13 +4434,6 @@ 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 - WL_DBG(("mac_ptr:%p name:%s role:%d nl80211_iftype:%d " MACDBG "\n", addr, name, event->role, iface_type, MAC2STRDBG(event->mac))); if (!name) { @@ -4484,9 +4460,6 @@ wl_cfg80211_post_ifcreate(struct net_device *ndev, return NULL; } wdev = new_ndev->ieee80211_ptr; -#ifdef WL_EXT_IAPSTA - wl_ext_iapsta_update_iftype(new_ndev, event->ifidx, wl_iftype); -#endif } else #endif /* WL_STATIC_IF */ { @@ -4521,6 +4494,9 @@ wl_cfg80211_post_ifcreate(struct net_device *ndev, SET_NETDEV_DEV(new_ndev, wiphy_dev(wdev->wiphy)); memcpy(new_ndev->dev_addr, addr, ETH_ALEN); +#ifdef WL_EXT_IAPSTA + wl_ext_iapsta_ifadding(new_ndev, event->ifidx); +#endif /* WL_EXT_IAPSTA */ if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev, rtnl_lock_reqd) != BCME_OK) { WL_ERR(("IFACE register failed \n")); @@ -4550,6 +4526,9 @@ wl_cfg80211_post_ifcreate(struct net_device *ndev, if (mode == WL_MODE_AP) { wl_set_drv_status(cfg, AP_CREATING, new_ndev); } +#ifdef WL_EXT_IAPSTA + wl_ext_iapsta_update_iftype(new_ndev, event->ifidx, wl_iftype); +#endif WL_INFORM_MEM(("Network Interface (%s) registered with host." " cfg_iftype:%d wl_role:%d " MACDBG "\n", @@ -5345,6 +5324,19 @@ wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme) val = WL_AUTH_FILS_PUBLIC; break; #endif /* WL_FILS */ +#ifdef WL_CLIENT_SAE + case NL80211_AUTHTYPE_SAE: + if (!wl_is_pmkid_available(dev, sme->bssid)) { + val = WL_AUTH_SAE_KEY; + } else { + /* Fw will choose right auth type + * dynamically based on PMKID availability + */ + val = WL_AUTH_OPEN_SHARED; + } + WL_DBG(("sae auth type %d\n", val)); + break; +#endif /* WL_CLIENT_SAE */ default: val = 2; WL_ERR(("invalid auth type (%d)\n", sme->auth_type)); @@ -5362,6 +5354,28 @@ wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme) return err; } +#ifdef WL_CLIENT_SAE +static bool +wl_is_pmkid_available(struct net_device *dev, const u8 *bssid) +{ + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); + int i; + int npmkids = (cfg->pmk_list->pmkids.length - sizeof(uint16)*2) / sizeof(pmkid_v2_t); + + /* check the bssid is null or not */ + if (!bssid) return FALSE; + + for (i = 0; i < npmkids; i++) { + if (!memcmp(bssid, &cfg->pmk_list->pmkids.pmkid[i].bssid, ETHER_ADDR_LEN)) { + WL_DBG(("FOUND PMKID\n")); + return TRUE; + } + } + WL_ERR(("PMKID NOT FOUND\n")); + return FALSE; +} +#endif /* WL_CLIENT_SAE */ + static u32 wl_rsn_cipher_wsec_algo_lookup(uint32 cipher) { @@ -5535,9 +5549,7 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme) return err; } #ifdef WL_GCMP - if (wl_set_wsec_info_algos(dev, algos, mask)) { - WL_ERR(("set wsec_info error (%d)\n", err)); - } + wl_set_wsec_info_algos(dev, algos, mask); #endif /* WL_GCMP */ sec = wl_read_prof(cfg, dev, WL_PROF_SEC); sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0]; @@ -5580,10 +5592,12 @@ wl_set_wsec_info_algos(struct net_device *dev, uint32 algos, uint32 mask) tlv_data_len = sizeof(tlv_data); err = memcpy_s(tlv_data, sizeof(tlv_data), &algos, sizeof(algos)); if (err) { + WL_ERR(("memcpy_s algos error (%d)\n", err)); goto exit; } err = memcpy_s(tlv_data + sizeof(algos), sizeof(mask), &mask, sizeof(mask)); if (err) { + WL_ERR(("memcpy_s mask error (%d)\n", err)); goto exit; } bcm_xtlv_pack_xtlv(wsec_info_tlv, WL_WSEC_INFO_BSS_ALGOS, tlv_data_len, tlv_data, 0); @@ -5942,9 +5956,6 @@ wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme) #ifdef WL_OWE case WLAN_AKM_SUITE_OWE: #endif /* WL_OWE */ -#ifdef WL_SAE - case WLAN_AKM_SUITE_SAE: -#endif /* WL_SAE */ case WLAN_AKM_SUITE_FT_8021X_SHA384: val = wl_rsn_akm_wpa_auth_lookup(sme->crypto.akm_suites[0]); break; @@ -5954,6 +5965,11 @@ wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme) case WLAN_AKM_SUITE_FT_FILS_SHA384: val = WPA2_AUTH_FILS_SHA384 | WPA2_AUTH_FT; break; +#if defined(WL_SAE) || defined(WL_CLIENT_SAE) + case WLAN_AKM_SUITE_SAE: + val = WPA3_AUTH_SAE_PSK; + break; +#endif /* WL_SAE || WL_CLIENT_SAE */ default: WL_ERR(("invalid akm suite (0x%x)\n", sme->crypto.akm_suites[0])); @@ -6829,10 +6845,10 @@ wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, s32 bssidx = 0; dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub); - 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); + WL_MSG(dev->name, "Reason %d, act %d\n", reason_code, act); BCM_REFERENCE(dhdp); DHD_STATLOG_CTRL(dhdp, ST(DISASSOC_START), @@ -8388,7 +8404,7 @@ wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev, if (pmksa->pmk_len) { if (memcpy_s(&cfg->pmk_list->pmkids.pmkid[i].pmk, PMK_LEN_MAX, pmksa->pmk, pmksa->pmk_len)) { - WL_ERR(("invalid pmk len = %lu", pmksa->pmk_len)); + WL_ERR(("invalid pmk len = %zu", pmksa->pmk_len)); } else { cfg->pmk_list->pmkids.pmkid[i].pmk_len = pmksa->pmk_len; } @@ -9638,7 +9654,39 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev, wl_cfg80211_cancel_scan(cfg); #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ } +#ifdef WL_CLIENT_SAE + else if (ieee80211_is_auth(mgmt->frame_control)) { + int err = 0; + wl_assoc_mgr_cmd_t *cmd; + char *ambuf = NULL; + int param_len; + ack = true; + if ((dev == bcmcfg_to_prmry_ndev(cfg)) && cfg->p2p) { + bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE); + } + param_len = sizeof(wl_assoc_mgr_cmd_t) + len; + ambuf = MALLOCZ(cfg->osh, param_len); + if (ambuf == NULL) { + WL_ERR(("unable to allocate frame\n")); + return -ENOMEM; + } + cmd = (wl_assoc_mgr_cmd_t*)ambuf; + cmd->version = WL_ASSOC_MGR_CURRENT_VERSION; + cmd->length = len; + cmd->cmd = WL_ASSOC_MGR_CMD_SEND_AUTH; + memcpy(&cmd->params, buf, len); + err = wldev_iovar_setbuf(dev, "assoc_mgr_cmd", ambuf, param_len, + cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync); + if (unlikely(err)) { + WL_ERR(("Failed to send auth(%d)\n", err)); + ack = false; + } + MFREE(cfg->osh, ambuf, param_len); + cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, ack, GFP_KERNEL); + goto exit; + } +#endif /* WL_CLIENT_SAE */ } else { WL_ERR(("Driver only allows MGMT packet type\n")); goto exit; @@ -9824,7 +9872,10 @@ wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, 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(dhd, dev, _chan); + if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) { + wl_ext_iapsta_update_iftype(dev, dhd_net2idx(dhd->info, dev), WL_IF_TYPE_AP); + _chan = wl_ext_iapsta_update_channel(dhd, dev, _chan); + } #endif WL_MSG(dev->name, "netdev_ifidx(%d), chan_type(%d) target channel(%d) \n", dev->ifindex, channel_type, _chan); @@ -10924,9 +10975,6 @@ wl_cfg80211_set_ap_role( } if (!ap) { -#ifdef WLEASYMESH - WL_ERR(("ap should not be 0\n")); -#endif /* AP mode switch not supported. Try setting up AP explicitly */ err = wldev_iovar_getint(dev, "apsta", (s32 *)&apsta); if (unlikely(err)) { @@ -10934,9 +10982,6 @@ wl_cfg80211_set_ap_role( return err; } if (apsta == 0) { -#ifdef WLEASYMESH - WL_ERR(("apsta should not be 0\n")); -#endif /* If apsta is not set, set it */ /* Check for any connected interfaces before wl down */ @@ -11044,9 +11089,9 @@ 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) { + wl_ext_get_sec(dev, 0, sec, sizeof(sec)); + WL_MSG(dev->name, "Creating GO with sec=%s\n", sec); is_bssup = wl_cfg80211_bss_isup(dev, bssidx); if (!is_bssup && (ies->wpa2_ie != NULL)) { @@ -11136,8 +11181,9 @@ wl_cfg80211_bcn_bringup_ap( WL_ERR(("Could not get wsec %d\n", err)); goto exit; } - if (dhdp->conf->chip == BCM43430_CHIP_ID && bssidx > 0 && wsec >= 2) { - wsec |= 0x8; // terence 20180628: fix me, this is a workaround + if (dhdp->conf->chip == BCM43430_CHIP_ID && bssidx > 0 && + (wsec & (TKIP_ENABLED|AES_ENABLED))) { + wsec |= WSEC_SWFLAG; // terence 20180628: fix me, this is a workaround err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx); if (err < 0) { WL_ERR(("wsec error %d\n", err)); @@ -11182,6 +11228,8 @@ wl_cfg80211_bcn_bringup_ap( join_params.ssid.SSID_len); join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len); + wl_ext_get_sec(dev, 0, sec, sizeof(sec)); + WL_MSG(dev->name, "Creating AP with sec=%s\n", sec); /* create softap */ if ((err = wldev_ioctl_set(dev, WLC_SET_SSID, &join_params, join_params_size)) != 0) { @@ -11620,18 +11668,17 @@ wl_cfg80211_del_station( } else #endif /* WL_WPS_SYNC */ { - + scb_val.val = DOT11_RC_DEAUTH_LEAVING; + WL_MSG(dev->name, "Disconnect STA : " MACDBG " scb_val.val %d\n", + MAC2STRDBG(bcm_ether_ntoa((const struct ether_addr *)mac_addr, + eabuf)), scb_val.val); /* need to guarantee EAP-Failure send out before deauth */ dhd_wait_pend8021x(dev); - 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) { WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON err %d\n", err)); } - WL_MSG(dev->name, "Disconnect STA : " MACDBG " scb_val.val %d\n", - MAC2STRDBG(bcm_ether_ntoa((const struct ether_addr *)mac_addr, - eabuf)), scb_val.val); } #ifdef CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) @@ -11795,6 +11842,9 @@ wl_cfg80211_start_ap( if (err) { WL_ERR(("Disabling NDO Failed %d\n", err)); } +#ifdef WL_EXT_IAPSTA + wl_ext_iapsta_update_iftype(dev, dhd_net2idx(dhd->info, dev), WL_IF_TYPE_AP); +#endif /* WL_EXT_IAPSTA */ #ifdef PKT_FILTER_SUPPORT /* Disable packet filter */ if (dhd->early_suspended) { @@ -11929,6 +11979,9 @@ fail: wl_flush_fw_log_buffer(dev, FW_LOGSET_MASK_ALL); wl_cfg80211_stop_ap(wiphy, dev); if (dev_role == NL80211_IFTYPE_AP) { +#ifdef WL_EXT_IAPSTA + if (!wl_ext_iapsta_iftype_enabled(dev, WL_IF_TYPE_AP)) { +#endif /* WL_EXT_IAPSTA */ dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE; #ifdef PKT_FILTER_SUPPORT /* Enable packet filter */ @@ -11950,6 +12003,9 @@ fail: #ifdef DISABLE_WL_FRAMEBURST_SOFTAP wl_cfg80211_set_frameburst(cfg, TRUE); #endif /* DISABLE_WL_FRAMEBURST_SOFTAP */ +#ifdef WL_EXT_IAPSTA + } +#endif /* WL_EXT_IAPSTA */ } #ifdef WLTDLS if (bssidx == 0) { @@ -12090,8 +12146,14 @@ exit: #endif /* WLTDLS */ if (dev_role == NL80211_IFTYPE_AP) { +#ifdef WL_EXT_IAPSTA + if (!wl_ext_iapsta_iftype_enabled(dev, WL_IF_TYPE_AP)) { +#endif /* WL_EXT_IAPSTA */ /* clear the AP mode */ dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE; +#ifdef WL_EXT_IAPSTA + } +#endif /* WL_EXT_IAPSTA */ } return err; } @@ -12342,8 +12404,14 @@ fail: if (err) { WL_ERR(("ADD/SET beacon failed\n")); if (dev_role == NL80211_IFTYPE_AP) { +#ifdef WL_EXT_IAPSTA + if (!wl_ext_iapsta_iftype_enabled(dev, WL_IF_TYPE_AP)) { +#endif /* WL_EXT_IAPSTA */ /* clear the AP mode */ dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE; +#ifdef WL_EXT_IAPSTA + } +#endif /* WL_EXT_IAPSTA */ } } return err; @@ -12397,8 +12465,14 @@ wl_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) wl_cfg80211_clear_per_bss_ies(cfg, dev->ieee80211_ptr); if (wdev->iftype == NL80211_IFTYPE_AP) { +#ifdef WL_EXT_IAPSTA + if (!wl_ext_iapsta_iftype_enabled(dev, WL_IF_TYPE_AP)) { +#endif /* WL_EXT_IAPSTA */ /* clear the AP mode */ dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE; +#ifdef WL_EXT_IAPSTA + } +#endif /* WL_EXT_IAPSTA */ } return 0; @@ -12693,6 +12767,9 @@ static struct cfg80211_ops wl_cfg80211_ops = { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) .channel_switch = wl_cfg80211_channel_switch, #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) */ +#ifdef WL_CLIENT_SAE + .external_auth = wl_cfg80211_external_auth, +#endif /* WL_CLIENT_SAE */ }; s32 wl_mode_to_nl80211_iftype(s32 mode) @@ -12706,6 +12783,10 @@ s32 wl_mode_to_nl80211_iftype(s32 mode) return NL80211_IFTYPE_ADHOC; case WL_MODE_AP: return NL80211_IFTYPE_AP; +#ifdef WLMESH_CFG80211 + case WL_MODE_MESH: + return NL80211_IFTYPE_MESH_POINT; +#endif /* WLMESH_CFG80211 */ default: return NL80211_IFTYPE_UNSPECIFIED; } @@ -12741,6 +12822,61 @@ wl_cfg80211_set_country_code(struct net_device *net, char *country_code, return ret; } +#ifdef CONFIG_CFG80211_INTERNAL_REGDB +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)) +#define WL_CFG80211_REG_NOTIFIER() static int wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) +#else +#define WL_CFG80211_REG_NOTIFIER() static void wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) +#endif /* kernel version < 3.9.0 */ +#endif + +#ifdef CONFIG_CFG80211_INTERNAL_REGDB +WL_CFG80211_REG_NOTIFIER() +{ + struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)wiphy_priv(wiphy); + int ret = 0; + int revinfo = -1; + + if (!request || !cfg) { + WL_ERR(("Invalid arg\n")); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 11)) + return -EINVAL; +#else + return; +#endif /* kernel version < 3.10.11 */ + } + + WL_DBG(("ccode: %c%c Initiator: %d\n", + request->alpha2[0], request->alpha2[1], request->initiator)); + + /* We support only REGDOM_SET_BY_USER as of now */ + if ((request->initiator != NL80211_REGDOM_SET_BY_USER) && + (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)) { + WL_ERR(("reg_notifier for intiator:%d not supported : set default\n", + request->initiator)); + /* in case of no supported country by regdb + lets driver setup platform default Locale + */ + } + + WL_ERR(("Set country code %c%c from %s\n", + request->alpha2[0], request->alpha2[1], + ((request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) ? " 11d AP" : "User"))); + + if ((ret = wldev_set_country(bcmcfg_to_prmry_ndev(cfg), request->alpha2, + false, (request->initiator == NL80211_REGDOM_SET_BY_USER ? true : false), + revinfo)) < 0) { + WL_ERR(("set country Failed :%d\n", ret)); + } + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 11)) + return ret; +#else + return; +#endif /* kernel version < 3.10.11 */ +} +#endif /* CONFIG_CFG80211_INTERNAL_REGDB */ + #ifdef CONFIG_PM #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) static const struct wiphy_wowlan_support brcm_wowlan_support = { @@ -12807,6 +12943,9 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; #endif /* LINUX_VER < 4.12 */ #endif /* WL_SCHED_SCAN */ +#ifdef WLMESH_CFG80211 + wdev->wiphy->flags |= WIPHY_FLAG_MESH_AUTH; +#endif /* WLMESH_CFG80211 */ wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) @@ -12820,6 +12959,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_CFG80211 + | BIT(NL80211_IFTYPE_MESH_POINT) +#endif /* WLMESH_CFG80211 */ | BIT(NL80211_IFTYPE_AP); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \ @@ -12958,7 +13100,7 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev wiphy_ext_feature_set(wdev->wiphy, NL80211_EXT_FEATURE_FILS_SK_OFFLOAD); #endif /* WL_FILS */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) wdev->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; wdev->wiphy->max_num_csa_counters = WL_MAX_NUM_CSA_COUNTERS; #endif /* LINUX_VERSION_CODE > KERNEL_VERSION(3, 12, 0) */ @@ -12975,9 +13117,9 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev wdev->wiphy->flags &= ~WIPHY_FLAG_ENFORCE_COMBINATIONS; #endif // endif -#ifdef WL_SAE - wdev->wiphy->features |= NL80211_FEATURE_SAE; -#endif /* WL_SAE */ +#if defined(WL_SAE) || defined(WL_CLIENT_SAE) + wdev->wiphy->features |= NL80211_FEATURE_SAE; +#endif /* WL_SAE || WL_CLIENT_SAE */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)) && defined(BCMSUP_4WAY_HANDSHAKE) if (FW_SUPPORTED(dhd, idsup)) { err = wiphy_ext_feature_set(wdev->wiphy, @@ -13032,7 +13174,11 @@ static void wl_free_wdev(struct bcm_cfg80211 *cfg) wl_delete_all_netinfo(cfg); if (wiphy) { + if (wdev->netdev) + wdev->netdev->ieee80211_ptr = NULL; + wdev->netdev = NULL; MFREE(cfg->osh, wdev, sizeof(*wdev)); + cfg->wdev = NULL; wiphy_free(wiphy); } @@ -13041,21 +13187,13 @@ static void wl_free_wdev(struct bcm_cfg80211 *cfg) */ } -s32 wl_inform_bss(struct bcm_cfg80211 *cfg) +#if defined(BSSCACHE) || defined(RSSIAVG) +void wl_cfg80211_update_bss_cache(struct bcm_cfg80211 *cfg) { - struct wl_scan_results *bss_list; - wl_bss_info_t *bi = NULL; /* must be initialized */ - s32 err = 0; - s32 i; - struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg); #if defined(RSSIAVG) int rssi; #endif -#if defined(BSSCACHE) - wl_bss_cache_t *node; -#endif - - bss_list = cfg->bss_list; + struct wl_scan_results *bss_list = cfg->bss_list; /* Free cache in p2p scanning*/ if (p2p_is_on(cfg) && p2p_scan(cfg)) { @@ -13069,9 +13207,11 @@ s32 wl_inform_bss(struct bcm_cfg80211 *cfg) /* Delete disconnected cache */ #if defined(BSSCACHE) - wl_delete_disconnected_bss_cache(&cfg->g_bss_cache_ctrl, (u8*)&cfg->disconnected_bssid); + wl_delete_disconnected_bss_cache(&cfg->g_bss_cache_ctrl, + (u8*)&cfg->disconnected_bssid); #if defined(RSSIAVG) - wl_delete_disconnected_rssi_cache(&cfg->g_rssi_cache_ctrl, (u8*)&cfg->disconnected_bssid); + wl_delete_disconnected_rssi_cache(&cfg->g_rssi_cache_ctrl, + (u8*)&cfg->disconnected_bssid); #endif if (cfg->p2p_disconnected == 0) memset(&cfg->disconnected_bssid, 0, ETHER_ADDR_LEN); @@ -13101,7 +13241,21 @@ s32 wl_inform_bss(struct bcm_cfg80211 *cfg) wl_reset_bss_cache(&cfg->g_bss_cache_ctrl); #endif +} +#endif + +#if defined(BSSCACHE) +s32 wl_inform_bss_cache(struct bcm_cfg80211 *cfg) +{ + struct wl_scan_results *bss_list = cfg->bss_list; + wl_bss_info_t *bi = NULL; /* must be initialized */ + s32 err = 0; + s32 i; + struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg); #if defined(BSSCACHE) + wl_bss_cache_t *node; +#endif + if (cfg->p2p_disconnected > 0) { // terence 20130703: Fix for wrong group_capab (timing issue) wl_delete_disconnected_bss_cache(&cfg->g_bss_cache_ctrl, (u8*)&cfg->disconnected_bssid); @@ -13119,7 +13273,29 @@ s32 wl_inform_bss(struct bcm_cfg80211 *cfg) if (cfg->autochannel) wl_ext_get_best_channel(ndev, &cfg->g_bss_cache_ctrl, ioctl_version, &cfg->best_2g_ch, &cfg->best_5g_ch); + + return err; +} +#endif + +s32 wl_inform_bss(struct bcm_cfg80211 *cfg) +{ +#if !defined(BSSCACHE) + struct wl_scan_results *bss_list; + wl_bss_info_t *bi = NULL; /* must be initialized */ + s32 i; + struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg); +#endif + s32 err = 0; + +#if defined(BSSCACHE) || defined(RSSIAVG) + wl_cfg80211_update_bss_cache(cfg); +#endif + +#if defined(BSSCACHE) + err = wl_inform_bss_cache(cfg); #else + bss_list = cfg->bss_list; WL_SCAN(("scanned AP count (%d)\n", bss_list->count)); #ifdef ESCAN_CHANNEL_CACHE reset_roam_cache(cfg); @@ -13127,8 +13303,11 @@ s32 wl_inform_bss(struct bcm_cfg80211 *cfg) preempt_disable(); bi = next_bss(bss_list, bi); for_each_bss(bss_list, bi, i) { - if (cfg->p2p_disconnected > 0 && !memcmp(&bi->BSSID, &cfg->disconnected_bssid, ETHER_ADDR_LEN)) + if (cfg->p2p_disconnected > 0 && + !memcmp(&bi->BSSID, &cfg->disconnected_bssid, ETHER_ADDR_LEN)) { + WL_SCAN(("Skip %pM\n", &bi->BSSID)); continue; + } #ifdef ESCAN_CHANNEL_CACHE add_roam_cache(cfg, bi); #endif /* ESCAN_CHANNEL_CACHE */ @@ -13146,7 +13325,7 @@ s32 wl_inform_bss(struct bcm_cfg80211 *cfg) if (cfg->p2p_disconnected > 0) { // terence 20130703: Fix for wrong group_capab (timing issue) cfg->p2p_disconnected++; - if (cfg->p2p_disconnected >= REPEATED_SCAN_RESULT_CNT+1) { + if (cfg->p2p_disconnected >= 2) { cfg->p2p_disconnected = 0; memset(&cfg->disconnected_bssid, 0, ETHER_ADDR_LEN); } @@ -13626,8 +13805,9 @@ 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) { - WL_MSG(ndev->name, "event %s(%d) status %d reason %d\n", - bcmevent_get_name(event), event, ntoh32(e->status), reason); + WL_MSG_RLMT(ndev->name, &e->addr, ETHER_ADDR_LEN, + "event %s(%d) status %d reason %d\n", + bcmevent_get_name(event), event, ntoh32(e->status), reason); } #if !defined(WL_CFG80211_STA_EVENT) && !defined(WL_COMPAT_WIRELESS) && \ @@ -13759,8 +13939,8 @@ exit: } else if ((event == WLC_E_DEAUTH_IND) || ((event == WLC_E_DEAUTH) && (reason != DOT11_RC_RESERVED)) || (event == WLC_E_DISASSOC_IND)) { - WL_MSG(ndev->name, "del sta event for "MACDBG "\n", - MAC2STRDBG(e->addr.octet)); + WL_MSG_RLMT(ndev->name, &e->addr, ETHER_ADDR_LEN, + "del sta event for "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); @@ -13772,37 +13952,248 @@ exit: return err; } +#ifdef WL_CLIENT_SAE static s32 -wl_notify_connect_status_ibss(struct bcm_cfg80211 *cfg, struct net_device *ndev, +wl_notify_start_auth(struct bcm_cfg80211 *cfg, + bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data) +{ + struct cfg80211_external_auth_params ext_auth_param; + struct net_device *ndev = cfgdev_to_wlc_ndev(cfgdev, cfg); + u32 datalen = be32_to_cpu(e->datalen); + wl_ext_auth_evt_t *evt_data = (wl_ext_auth_evt_t *)data; + wl_assoc_mgr_cmd_t cmd; + int err; + + WL_DBG(("Enter\n")); + + if (!datalen || !data) + return BCME_ERROR; + + ext_auth_param.ssid.ssid_len = MIN(evt_data->ssid.SSID_len, DOT11_MAX_SSID_LEN); + if (ext_auth_param.ssid.ssid_len) + memcpy(&ext_auth_param.ssid.ssid, evt_data->ssid.SSID, + ext_auth_param.ssid.ssid_len); + + memcpy(&ext_auth_param.bssid, &evt_data->bssid, ETHER_ADDR_LEN); + ext_auth_param.action = NL80211_EXTERNAL_AUTH_START; + ext_auth_param.key_mgmt_suite = ntoh32(WLAN_AKM_SUITE_SAE_SHA256); + + WL_MSG(ndev->name, "BSSID: "MACDBG"\n", MAC2STRDBG(&evt_data->bssid)); + + cfg80211_external_auth_request(ndev, &ext_auth_param, GFP_KERNEL); + + cmd.version = WL_ASSOC_MGR_CURRENT_VERSION; + cmd.length = sizeof(cmd); + cmd.cmd = WL_ASSOC_MGR_CMD_PAUSE_ON_EVT; + cmd.params = WL_ASSOC_MGR_PARAMS_PAUSE_EVENT_AUTH_RESP; + err = wldev_iovar_setbuf(ndev, "assoc_mgr_cmd", (void *)&cmd, sizeof(cmd), + cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync); + if (unlikely(err)) { + WL_ERR(("Failed to pause assoc(%d)\n", err)); + } + + return BCME_OK; +} + +static s32 +wl_notify_connect_status_bss(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); - u16 flags = ntoh16(e->flags); - u32 status = ntoh32(e->status); - bool active; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) - struct ieee80211_channel *channel = NULL; + u32 reason = ntoh32(e->reason); + u32 len = ntoh32(e->datalen); + u32 status = ntoh32(e->status); + + bool isfree = false; + u8 *mgmt_frame; + u8 bsscfgidx = e->bsscfgidx; + s32 freq; + s32 channel; + u8 *body = NULL; + u16 fc = 0, rssi = 0; + bcm_struct_cfgdev *cfgdev = ndev_to_cfgdev(ndev); + + struct ieee80211_supported_band *band; + struct ether_addr da; + struct ether_addr bssid; struct wiphy *wiphy = bcmcfg_to_wiphy(cfg); - u32 chanspec, chan; - u32 freq, band; -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */ + channel_info_t ci; - if (event == WLC_E_JOIN) { - WL_INFORM_MEM(("[%s] joined in IBSS network\n", ndev->name)); + WL_DBG(("event %d status %d reason %d\n", event, status, reason)); + + if (event == WLC_E_AUTH) { + struct wl_security *sec; + sec = wl_read_prof(cfg, ndev, WL_PROF_SEC); + + if (!(sec->auth_type == NL80211_AUTHTYPE_SAE)) { + WL_DBG(("Abort AUTH processing due to NOT SAE\n")); + return 0; + } else { + if (status != WLC_E_STATUS_SUCCESS && !len) { + WL_ERR(("SAE AUTH FAIL EVENT\n")); + wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY|WAIT_DISCONNECTED, + WL_EXT_STATUS_DISCONNECTED, NULL); + return 0; + } + } } - if (event == WLC_E_START) { - WL_INFORM_MEM(("[%s] started IBSS network\n", ndev->name)); + + if (!len && (event == WLC_E_DEAUTH)) { + len = 2; /* reason code field */ + data = &reason; } - if (event == WLC_E_JOIN || event == WLC_E_START || - (event == WLC_E_LINK && (flags == WLC_EVENT_MSG_LINK))) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) - err = wldev_iovar_getint(ndev, "chanspec", (s32 *)&chanspec); - if (unlikely(err)) { - WL_ERR(("Could not get chanspec %d\n", err)); - return err; - } - chan = wf_chspec_ctlchan(wl_chspec_driver_to_host(chanspec)); + + if (len) { + body = kzalloc(len, GFP_KERNEL); + if (body == NULL) { + WL_ERR(("wl_notify_connect_status: Failed to allocate body\n")); + return WL_INVALID; + } + } + + memset(&bssid, 0, ETHER_ADDR_LEN); + 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); + err = wldev_ioctl_get(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN); + /* Use e->addr as bssid for Sta case , before association completed */ + if (err == BCME_NOTASSOCIATED) + memcpy(&bssid, &e->addr, 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; + case WLC_E_AUTH: + fc = FC_AUTH; + break; + default: + fc = 0; + goto exit; + } + 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(cfg, 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) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) + cfg80211_rx_mgmt(cfgdev, freq, rssi, mgmt_frame, len, 0); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) + cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC); +#else + cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); +#endif + } else if (event == WLC_E_DISASSOC_IND) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) + cfg80211_rx_mgmt(cfgdev, freq, rssi, mgmt_frame, len, 0); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) + cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC); +#else + cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); +#endif + } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) + cfg80211_rx_mgmt(cfgdev, freq, rssi, mgmt_frame, len, 0); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) + cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC); +#else + cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); +#endif + } else if (event == WLC_E_AUTH) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) + cfg80211_rx_mgmt(cfgdev, freq, rssi, mgmt_frame, len, 0); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) + 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); + return err; +} +#endif /* WL_CLIENT_SAE */ + +static s32 +wl_notify_connect_status_ibss(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); + u16 flags = ntoh16(e->flags); + u32 status = ntoh32(e->status); + bool active; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) + struct ieee80211_channel *channel = NULL; + struct wiphy *wiphy = bcmcfg_to_wiphy(cfg); + u32 chanspec, chan; + u32 freq, band; +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */ + + if (event == WLC_E_JOIN) { + WL_INFORM_MEM(("[%s] joined in IBSS network\n", ndev->name)); + } + if (event == WLC_E_START) { + WL_INFORM_MEM(("[%s] started IBSS network\n", ndev->name)); + } + if (event == WLC_E_JOIN || event == WLC_E_START || + (event == WLC_E_LINK && (flags == WLC_EVENT_MSG_LINK))) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) + err = wldev_iovar_getint(ndev, "chanspec", (s32 *)&chanspec); + if (unlikely(err)) { + WL_ERR(("Could not get chanspec %d\n", err)); + return err; + } + chan = wf_chspec_ctlchan(wl_chspec_driver_to_host(chanspec)); band = (chan <= CH_MAX_2G_CHANNEL) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; freq = ieee80211_channel_to_frequency(chan, band); channel = ieee80211_get_channel(wiphy, freq); @@ -13980,6 +14371,193 @@ wl_cache_assoc_resp_ies(struct bcm_cfg80211 *cfg, struct net_device *ndev, } } +#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 !defined(WL_CFG80211_STA_EVENT) && !defined(WL_COMPAT_WIRELESS) && \ + (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) + bool isfree = false; + u8 *mgmt_frame; + u8 bsscfgidx = e->bsscfgidx; + s32 freq; + s32 channel; + u8 *body = NULL; + u16 fc = 0; + u32 body_len = 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; + u8 ioctl_buf[WLC_IOCTL_SMLEN]; +#else + struct station_info sinfo; +#endif /* (LINUX_VERSION < VERSION(3,2,0)) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */ + + WL_INFORM_MEM(("[%s] Mode Mesh. Event:%d status:%d reason:%d\n", + ndev->name, 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 !defined(WL_CFG80211_STA_EVENT) && !defined(WL_COMPAT_WIRELESS) && \ + (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) + WL_DBG(("Enter \n")); + if (!len && (event == WLC_E_DEAUTH)) { + len = 2; /* reason code field */ + data = &reason; + } + if (len) { + body = (u8 *)MALLOCZ(cfg->osh, len); + if (body == NULL) { + WL_ERR(("Failed to allocate body\n")); + return WL_INVALID; + } + } + bzero(&bssid, ETHER_ADDR_LEN); + WL_DBG(("Enter event %d ndev %p\n", event, ndev)); + if (wl_get_mode_by_netdev(cfg, ndev) == WL_INVALID) { + MFREE(cfg->osh, body, len); + return WL_INVALID; + } + if (len) + memcpy(body, data, len); + + wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr", + NULL, 0, ioctl_buf, sizeof(ioctl_buf), bsscfgidx, NULL); + memcpy(da.octet, ioctl_buf, ETHER_ADDR_LEN); + bzero(&bssid, 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; + } + bzero(&ci, sizeof(ci)); + if ((err = wldev_ioctl_get(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci)))) { + MFREE(cfg->osh, body, len); + 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) { + MFREE(cfg->osh, body, len); + } + return -EINVAL; + } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) && !defined(WL_COMPAT_WIRELESS) + freq = ieee80211_channel_to_frequency(channel); + (void)band->band; +#else + freq = ieee80211_channel_to_frequency(channel, band->band); +#endif // endif + body_len = len; + err = wl_frame_get_mgmt(cfg, 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 /* LINUX_VERSION >= VERSION(3, 18,0) || WL_COMPAT_WIRELESS */ + } + +exit: + if (isfree) { + MFREE(cfg->osh, mgmt_frame, len); + } + if (body) { + MFREE(cfg->osh, body, body_len); + } +#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, "new sta event for "MACDBG "\n", + MAC2STRDBG(e->addr.octet)); + cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC); + } else if ((event == WLC_E_DEAUTH_IND) || + ((event == WLC_E_DEAUTH) && (reason != DOT11_RC_RESERVED)) || + (event == WLC_E_DISASSOC_IND)) { + WL_MSG(ndev->name, "del sta event for "MACDBG "\n", + MAC2STRDBG(e->addr.octet)); + cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC); + } +#endif /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */ + return err; +} +#endif /* WLMESH_CFG80211 */ + static s32 wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data) @@ -14025,6 +14603,10 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, ntoh32(e->status), ntoh32(e->reason))); if (mode == WL_MODE_AP) { err = wl_notify_connect_status_ap(cfg, ndev, e, data); +#ifdef WLMESH_CFG80211 + } else if (mode == WL_MODE_MESH) { + err = wl_notify_connect_status_mesh(cfg, ndev, e, data); +#endif /* WLMESH_CFG80211 */ } else if (mode == WL_MODE_IBSS) { err = wl_notify_connect_status_ibss(cfg, ndev, e, data); } else if (mode == WL_MODE_BSS) { @@ -14041,6 +14623,10 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, " connect state. Ignore\n")); return BCME_OK; } +#ifdef WL_CLIENT_SAE + if (event == WLC_E_AUTH) + wl_notify_connect_status_bss(cfg, ndev, e, data); +#endif /* WL_CLIENT_SAE */ if (event == WLC_E_ASSOC || event == WLC_E_AUTH) { wl_get_auth_assoc_status(cfg, ndev, e, data); @@ -14286,7 +14872,8 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, dhd_dev_set_rssi_monitor_cfg(bcmcfg_to_prmry_ndev(cfg), FALSE, 0, 0); #endif /* RSSI_MONITOR_SUPPORT */ - if (!memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) { + if (dhdp->conf->eapol_status == EAPOL_STATUS_4WAY_DONE && + !memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) { // terence 20130703: Fix for wrong group_capab (timing issue) cfg->p2p_disconnected = 1; } @@ -15158,7 +15745,7 @@ wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev, 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" + WL_DBG(("BSS already present, Skipping roamed event to" " upper layer\n")); goto fail; } @@ -15499,6 +16086,14 @@ wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev, completed = false; sec->auth_assoc_res_status = WLAN_STATUS_UNSPECIFIED_FAILURE; } + if (completed) { + WL_MSG(ndev->name, "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); + } #ifdef WL_FILS if ((sec->auth_type == DOT11_FILS_SKEY_PFS)||(sec->auth_type == DOT11_FILS_SKEY)) { wl_get_fils_connect_params(cfg, ndev); @@ -15551,15 +16146,6 @@ wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev, WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL); } - if (completed) { - WL_MSG(ndev->name, "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); - } } else { WL_INFORM_MEM(("[%s] Ignore event:%d. drv status" " connecting:%x. connected:%d\n", @@ -16233,8 +16819,43 @@ static void wl_init_event_handler(struct bcm_cfg80211 *cfg) #ifdef WL_CHAN_UTIL cfg->evt_handler[WLC_E_BSS_LOAD] = wl_cfg80211_bssload_report_event_handler; #endif /* WL_CHAN_UTIL */ +#ifdef WL_CLIENT_SAE + cfg->evt_handler[WLC_E_JOIN_START] = wl_notify_start_auth; +#endif /* WL_CLIENT_SAE */ } +#ifdef WL_CLIENT_SAE +/** Called by the cfg80211 framework */ +static s32 +wl_cfg80211_external_auth(struct wiphy *wiphy, + struct net_device *ndev, struct cfg80211_external_auth_params *ext_auth_param) +{ + int err = 0; + struct bcm_cfg80211 *cfg = wiphy_priv(wiphy); + wl_assoc_mgr_cmd_t cmd; + + WL_DBG(("Enter\n")); + + if (!ext_auth_param || + ETHER_ISNULLADDR(ext_auth_param->bssid)) { + WL_ERR(("Invalid wl_cfg80211_external_auth param\n")); + return -EINVAL; + } + + cmd.version = WL_ASSOC_MGR_CURRENT_VERSION; + cmd.length = sizeof(cmd); + cmd.cmd = WL_ASSOC_MGR_CMD_PAUSE_ON_EVT; + cmd.params = WL_ASSOC_MGR_PARAMS_EVENT_NONE; + err = wldev_iovar_setbuf(ndev, "assoc_mgr_cmd", (void *)&cmd, sizeof(cmd), cfg->ioctl_buf, + WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync); + if (unlikely(err)) { + WL_ERR(("Failed to pause assoc(%d)\n", err)); + } + + return err; +} +#endif /* WL_CLIENT_SAE */ + #if defined(STATIC_WL_PRIV_STRUCT) static int wl_init_escan_result_buf(struct bcm_cfg80211 *cfg) @@ -17173,7 +17794,11 @@ s32 wl_cfg80211_attach(struct net_device *ndev, void *context) MFREE(dhd->osh, wdev, sizeof(*wdev)); return -ENOMEM; } +#ifdef WLMESH_CFG80211 + wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_MESH); +#else wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS); +#endif cfg = wiphy_priv(wdev->wiphy); cfg->wdev = wdev; cfg->pub = context; @@ -17224,6 +17849,10 @@ s32 wl_cfg80211_attach(struct net_device *ndev, void *context) goto cfg80211_attach_out; #endif // endif +#ifdef CONFIG_CFG80211_INTERNAL_REGDB + wdev->wiphy->reg_notifier = wl_cfg80211_reg_notifier; +#endif /* CONFIG_CFG80211_INTERNAL_REGDB */ + #if defined(WL_ENABLE_P2P_IF) err = wl_cfg80211_attach_p2p(cfg); if (err) @@ -17620,6 +18249,11 @@ static s32 wl_config_infra(struct bcm_cfg80211 *cfg, struct net_device *ndev, u1 /* Intentional fall through */ infra = 1; break; +#ifdef WLMESH_CFG80211 + case NL80211_IFTYPE_MESH_POINT: + infra = WL_BSSTYPE_MESH; + break; +#endif /* WLMESH_CFG80211 */ case WL_IF_TYPE_MONITOR: case WL_IF_TYPE_NAN: /* Intentionall fall through */ @@ -18528,6 +19162,9 @@ s32 wl_cfg80211_up(struct net_device *net) return err; } } +#ifdef WLMESH_CFG80211 + cfg->wdev->wiphy->features |= NL80211_FEATURE_USERSPACE_MPM; +#endif /* WLMESH_CFG80211 */ #if defined(BCMSUP_4WAY_HANDSHAKE) if (dhd->fw_4way_handshake) { /* This is a hacky method to indicate fw 4WHS support and @@ -24203,6 +24840,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: @@ -24236,12 +24874,14 @@ 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: 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); @@ -24270,6 +24910,7 @@ 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_4WAY_DONE; @@ -24283,6 +24924,7 @@ wl_cfg80211_check_in4way(struct bcm_cfg80211 *cfg, cfg->handshaking = 0; } } + wake_up_interruptible(&dhdp->conf->event_complete); break; case WL_EXT_STATUS_AP_ENABLED: ifidx = dhd_net2idx(dhdp->info, dev); diff --git a/bcmdhd.100.10.315.x/wl_cfg80211.h b/bcmdhd.100.10.315.x/wl_cfg80211.h index 7c9f86a..0aefc1c 100644 --- a/bcmdhd.100.10.315.x/wl_cfg80211.h +++ b/bcmdhd.100.10.315.x/wl_cfg80211.h @@ -74,9 +74,24 @@ struct bcm_cfg80211; struct wl_security; struct wl_ibss; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) && !defined(WL_SAE)) -#define WL_SAE -#endif // endif +#if !defined(WL_CLIENT_SAE) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) +#define WL_CLIENT_SAE +#endif +#if defined(WL_SAE) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)) +#error "Can not support WL_SAE befor kernel 3.14" +#endif +#if defined(WL_CLIENT_SAE) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)) +#error "Can not support WL_CLIENT_SAE before kernel 4.17" +#endif +#if defined(WL_CLIENT_SAE) && defined(WL_SAE) +#error "WL_SAE is for dongle-offload and WL_CLIENT_SAE is for wpa_supplicant. Please choose one." +#endif + +#if defined(WL_CLIENT_SAE) +#ifndef WL_ASSOC_MGR_CMD_SEND_AUTH +#define WL_ASSOC_MGR_CMD_SEND_AUTH 3 +#endif /* WL_ASSOC_MGR_CMD_SEND_AUTH */ +#endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) && !defined(WL_SCAN_TYPE)) #define WL_SCAN_TYPE @@ -382,6 +397,8 @@ do { \ #define WLAN_AKM_SUITE_FT_PSK 0x000FAC04 #endif /* WLAN_AKM_SUITE_FT_PSK */ +#define WLAN_AKM_SUITE_SAE_SHA256 0x000FAC08 + #ifndef WLAN_AKM_SUITE_8021X_SUITE_B #define WLAN_AKM_SUITE_8021X_SUITE_B 0x000FAC0B #define WLAN_AKM_SUITE_8021X_SUITE_B_192 0x000FAC0C @@ -507,6 +524,9 @@ enum wl_status { typedef enum wl_iftype { WL_IF_TYPE_STA = 0, WL_IF_TYPE_AP = 1, +#ifdef WLMESH_CFG80211 + WL_IF_TYPE_MESH = 2, +#endif /* WLMESH_CFG80211 */ WL_IF_TYPE_NAN_NMI = 3, WL_IF_TYPE_NAN = 4, WL_IF_TYPE_P2P_GO = 5, @@ -534,6 +554,9 @@ enum wl_mode { WL_MODE_IBSS = 1, WL_MODE_AP = 2, WL_MODE_NAN = 4, +#ifdef WLMESH_CFG80211 + WL_MODE_MESH = 5, +#endif /* WLMESH_CFG80211 */ WL_MODE_MAX }; diff --git a/bcmdhd.100.10.315.x/wl_cfgp2p.c b/bcmdhd.100.10.315.x/wl_cfgp2p.c index 9889132..edcedc6 100644 --- a/bcmdhd.100.10.315.x/wl_cfgp2p.c +++ b/bcmdhd.100.10.315.x/wl_cfgp2p.c @@ -459,7 +459,7 @@ wl_cfgp2p_ifadd(struct bcm_cfg80211 *cfg, struct ether_addr *mac, u8 if_type, err = wldev_iovar_setbuf(ndev, "p2p_ifadd", &ifreq, sizeof(ifreq), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync); if (unlikely(err < 0)) { - printk("'cfg p2p_ifadd' error %d\n", err); + CFGP2P_ERR(("'cfg p2p_ifadd' error %d\n", err)); return err; } @@ -482,7 +482,7 @@ wl_cfgp2p_ifdisable(struct bcm_cfg80211 *cfg, struct ether_addr *mac) ret = wldev_iovar_setbuf(netdev, "p2p_ifdis", mac, sizeof(*mac), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync); if (unlikely(ret < 0)) { - printk("'cfg p2p_ifdis' error %d\n", ret); + CFGP2P_ERR(("'cfg p2p_ifdis' error %d\n", ret)); } return ret; } @@ -506,7 +506,7 @@ wl_cfgp2p_ifdel(struct bcm_cfg80211 *cfg, struct ether_addr *mac) ret = wldev_iovar_setbuf(netdev, "p2p_ifdel", mac, sizeof(*mac), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync); if (unlikely(ret < 0)) { - printk("'cfg p2p_ifdel' error %d\n", ret); + CFGP2P_ERR(("'cfg p2p_ifdel' error %d\n", ret)); } #ifdef WL_DISABLE_HE_P2P if ((bssidx = wl_get_bssidx_by_wdev(cfg, netdev->ieee80211_ptr)) < 0) { @@ -551,7 +551,7 @@ wl_cfgp2p_ifchange(struct bcm_cfg80211 *cfg, struct ether_addr *mac, u8 if_type, err = wldev_iovar_setbuf(netdev, "p2p_ifupd", &ifreq, sizeof(ifreq), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync); if (unlikely(err < 0)) { - printk("'cfg p2p_ifupd' error %d\n", err); + CFGP2P_ERR(("'cfg p2p_ifupd' error %d\n", err)); } else if (if_type == WL_P2P_IF_GO) { cfg->p2p->p2p_go_count++; } @@ -2403,7 +2403,7 @@ wl_cfgp2p_register_ndev(struct bcm_cfg80211 *cfg) cfg->p2p_wdev = wdev; cfg->p2p_net = net; - printk("%s: P2P Interface Registered\n", net->name); + WL_MSG(net->name, "P2P Interface Registered\n"); return ret; } diff --git a/bcmdhd.100.10.315.x/wl_cfgp2p.h b/bcmdhd.100.10.315.x/wl_cfgp2p.h index 128ab5b..f4186ae 100644 --- a/bcmdhd.100.10.315.x/wl_cfgp2p.h +++ b/bcmdhd.100.10.315.x/wl_cfgp2p.h @@ -134,70 +134,67 @@ enum wl_cfgp2p_status { /* dword align allocation */ #define WLC_IOCTL_MAXLEN 8192 -#define CFGP2P_ERROR_TEXT "CFGP2P-ERROR) " +#define CFGP2P_ERROR_TEXT "[dhd] CFGP2P-ERROR) " #ifdef DHD_LOG_DUMP -#define CFGP2P_ERR(args) \ - do { \ - if (wl_dbg_level & WL_DBG_ERR) { \ - printk(KERN_INFO CFGP2P_ERROR_TEXT "%s : ", __func__); \ - printk args; \ - DHD_LOG_DUMP_WRITE("[%s] %s: ", \ - dhd_log_dump_get_timestamp(), __func__); \ - DHD_LOG_DUMP_WRITE args; \ - } \ +#define CFGP2P_ERR_MSG(x, args...) \ + do { \ + if (wl_dbg_level & WL_DBG_ERR) { \ + printk(KERN_INFO CFGP2P_ERROR_TEXT "%s : " x, __func__, ## args); \ + DHD_LOG_DUMP_WRITE("[%s] %s: ", dhd_log_dump_get_timestamp(), __func__); \ + DHD_LOG_DUMP_WRITE(x, ## args); \ + } \ } while (0) -#define CFGP2P_INFO(args) \ +#define CFGP2P_ERR(x) CFGP2P_ERR_MSG x +#define CFGP2P_INFO_MSG(x, args...) \ do { \ if (wl_dbg_level & WL_DBG_INFO) { \ - printk(KERN_INFO "CFGP2P-INFO) %s : ", __func__); \ - printk args; \ - DHD_LOG_DUMP_WRITE("[%s] %s: ", \ - dhd_log_dump_get_timestamp(), __func__); \ - DHD_LOG_DUMP_WRITE args; \ + printk(KERN_INFO "[dhd] CFGP2P-INFO) %s : " x, __func__, ## args); \ + DHD_LOG_DUMP_WRITE("[%s] %s: ", dhd_log_dump_get_timestamp(), __func__); \ + DHD_LOG_DUMP_WRITE(x, ## args); \ } \ } while (0) -#define CFGP2P_ACTION(args) \ +#define CFGP2P_INFO(x) CFGP2P_INFO_MSG x +#define CFGP2P_ACTION_MSG(x, args...) \ do { \ if (wl_dbg_level & WL_DBG_P2P_ACTION) { \ - printk(KERN_DEBUG "CFGP2P-ACTION) %s :", __func__); \ - printk args; \ - DHD_LOG_DUMP_WRITE("[%s] %s: ", \ - dhd_log_dump_get_timestamp(), __func__); \ - DHD_LOG_DUMP_WRITE args; \ + printk(KERN_INFO "[dhd] CFGP2P-ACTION) %s :" x, __func__, ## args); \ + DHD_LOG_DUMP_WRITE("[%s] %s: ", dhd_log_dump_get_timestamp(), __func__); \ + DHD_LOG_DUMP_WRITE(x, ## args); \ } \ } while (0) +#define CFGP2P_ACTION(x) CFGP2P_ACTION_MSG x #else -#define CFGP2P_ERR(args) \ +#define CFGP2P_ERR_MSG(x, args...) \ do { \ if (wl_dbg_level & WL_DBG_ERR) { \ - printk(KERN_INFO CFGP2P_ERROR_TEXT "%s : ", __func__); \ - printk args; \ + printk(KERN_INFO CFGP2P_ERROR_TEXT "%s : " x, __func__, ## args); \ } \ } while (0) -#define CFGP2P_INFO(args) \ +#define CFGP2P_ERR(x) CFGP2P_ERR_MSG x +#define CFGP2P_INFO_MSG(x, args...) \ do { \ if (wl_dbg_level & WL_DBG_INFO) { \ - printk(KERN_INFO "CFGP2P-INFO) %s : ", __func__); \ - printk args; \ + printk(KERN_INFO "[dhd] CFGP2P-INFO) %s : " x, __func__, ## args); \ } \ } while (0) -#define CFGP2P_ACTION(args) \ +#define CFGP2P_INFO(x) CFGP2P_INFO_MSG x +#define CFGP2P_ACTION_MSG(x, args...) \ do { \ if (wl_dbg_level & WL_DBG_P2P_ACTION) { \ - printk(KERN_INFO "CFGP2P-ACTION) %s :", __func__); \ - printk args; \ + printk(KERN_INFO "[dhd] CFGP2P-ACTION) %s :" x, __func__, ## args); \ } \ } while (0) +#define CFGP2P_ACTION(x) CFGP2P_ACTION_MSG x #endif /* DHD_LOG_DUMP */ -#define CFGP2P_DBG(args) \ +#define CFGP2P_DBG_MSG(x, args...) \ do { \ if (wl_dbg_level & WL_DBG_DBG) { \ - printk(KERN_INFO "CFGP2P-DEBUG) %s :", __func__); \ - printk args; \ + printk(KERN_INFO "[dhd] CFGP2P-DEBUG) %s :" x, __func__, ## args); \ } \ } while (0) +#define CFGP2P_DBG(x) CFGP2P_DBG_MSG x #define INIT_TIMER(timer, func, duration, extra_delay) \ do { \ diff --git a/bcmdhd.100.10.315.x/wl_cfgscan.c b/bcmdhd.100.10.315.x/wl_cfgscan.c index dcaebe5..7ab8712 100644 --- a/bcmdhd.100.10.315.x/wl_cfgscan.c +++ b/bcmdhd.100.10.315.x/wl_cfgscan.c @@ -1890,7 +1890,7 @@ wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, return -ENODEV; } } - err = wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY, + err = wl_cfg80211_check_in4way(cfg, ndev_to_wlc_ndev(ndev, cfg), NO_SCAN_IN4WAY, WL_EXT_STATUS_SCAN, NULL); if (err) return err; @@ -2068,7 +2068,7 @@ s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg, #if defined(ESCAN_RESULT_PATCH) if (likely(cfg->scan_request)) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) - if (aborted && p2p_scan(cfg) && + if (aborted && cfg->p2p && p2p_scan(cfg) && (cfg->scan_request->flags & NL80211_SCAN_FLAG_FLUSH)) { WL_ERR(("scan list is changed")); cfg->bss_list = wl_escan_get_buf(cfg, !aborted); @@ -2106,6 +2106,7 @@ 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); DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub)); DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)(cfg->pub)); @@ -2730,12 +2731,12 @@ static void wl_scan_timeout(unsigned long data) dhdp->memdump_type = DUMP_TYPE_SCAN_TIMEOUT; dhd_bus_mem_dump(dhdp); } +#endif /* DHD_FW_COREDUMP */ /* * For the memdump sanity, blocking bus transactions for a while * Keeping it TRUE causes the sequential private cmd error */ dhdp->scan_timeout_occurred = FALSE; -#endif /* DHD_FW_COREDUMP */ msg.event_type = hton32(WLC_E_ESCAN_RESULT); msg.status = hton32(WLC_E_STATUS_TIMEOUT); msg.reason = 0xFFFFFFFF; diff --git a/bcmdhd.100.10.315.x/wl_cfgvendor.c b/bcmdhd.100.10.315.x/wl_cfgvendor.c index 1cafa06..157bb80 100644 --- a/bcmdhd.100.10.315.x/wl_cfgvendor.c +++ b/bcmdhd.100.10.315.x/wl_cfgvendor.c @@ -6685,6 +6685,14 @@ wl_cfgvendor_dbg_get_mem_dump(struct wiphy *wiphy, } } if (buf_len > 0 && user_buf) { +#if 0 + mem_buf = vmalloc(buf_len); + if (!mem_buf) { + WL_ERR(("failed to allocate mem_buf with size : %d\n", buf_len)); + ret = BCME_NOMEM; + goto exit; + } +#endif ret = dhd_os_get_socram_dump(bcmcfg_to_prmry_ndev(cfg), &mem_buf, &buf_len); if (ret) { WL_ERR(("failed to get_socram_dump : %d\n", ret)); @@ -6736,6 +6744,7 @@ wl_cfgvendor_dbg_get_mem_dump(struct wiphy *wiphy, } free_mem: +// vfree(mem_buf); /* Free skb memory */ if (skb) { kfree_skb(skb); @@ -7803,6 +7812,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = BRCM_VENDOR_SCMD_PRIV_STR }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_priv_string_handler }, #ifdef BCM_PRIV_CMD_SUPPORT @@ -7812,6 +7824,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = BRCM_VENDOR_SCMD_BCM_STR }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_priv_bcm_handler }, #endif /* BCM_PRIV_CMD_SUPPORT */ @@ -7822,6 +7837,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = BRCM_VENDOR_SCMD_BCM_PSK }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_set_sae_password }, #endif /* WL_SAE */ @@ -7832,6 +7850,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = GSCAN_SUBCMD_GET_CAPABILITIES }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_gscan_get_capabilities }, { @@ -7840,6 +7861,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = GSCAN_SUBCMD_SET_CONFIG }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_set_scan_cfg }, { @@ -7848,6 +7872,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = GSCAN_SUBCMD_SET_SCAN_CONFIG }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_set_batch_scan_cfg }, { @@ -7856,6 +7883,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = GSCAN_SUBCMD_ENABLE_GSCAN }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_initiate_gscan }, { @@ -7864,6 +7894,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_enable_full_scan_result }, { @@ -7872,6 +7905,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = GSCAN_SUBCMD_SET_HOTLIST }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_hotlist_cfg }, { @@ -7880,6 +7916,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = GSCAN_SUBCMD_GET_SCAN_RESULTS }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_gscan_get_batch_results }, #endif /* GSCAN_SUPPORT */ @@ -7890,6 +7929,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = GSCAN_SUBCMD_GET_CHANNEL_LIST }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_gscan_get_channel_list }, #endif /* GSCAN_SUPPORT || DHD_GET_VALID_CHANNELS */ @@ -7900,6 +7942,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = RTT_SUBCMD_SET_CONFIG }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_rtt_set_config }, { @@ -7908,6 +7953,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = RTT_SUBCMD_CANCEL_CONFIG }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_rtt_cancel_config }, { @@ -7916,6 +7964,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = RTT_SUBCMD_GETCAPABILITY }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_rtt_get_capability }, { @@ -7924,6 +7975,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = RTT_SUBCMD_GETAVAILCHANNEL }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_rtt_get_responder_info }, { @@ -7932,6 +7986,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = RTT_SUBCMD_SET_RESPONDER }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_rtt_set_responder }, { @@ -7940,6 +7997,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = RTT_SUBCMD_CANCEL_RESPONDER }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_rtt_cancel_responder }, #endif /* RTT_SUPPORT */ @@ -7949,6 +8009,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = ANDR_WIFI_SUBCMD_GET_FEATURE_SET }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_get_feature_set }, { @@ -7957,6 +8020,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = ANDR_WIFI_SUBCMD_GET_FEATURE_SET_MATRIX }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_get_feature_set_matrix }, { @@ -7965,6 +8031,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = ANDR_WIFI_RANDOM_MAC_OUI }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_set_rand_mac_oui }, #ifdef CUSTOM_FORCE_NODFS_FLAG @@ -7974,6 +8043,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = ANDR_WIFI_NODFS_CHANNELS }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_set_nodfs_flag }, #endif /* CUSTOM_FORCE_NODFS_FLAG */ @@ -7983,6 +8055,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = ANDR_WIFI_SET_COUNTRY }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_set_country }, #ifdef LINKSTAT_SUPPORT @@ -7992,6 +8067,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = LSTATS_SUBCMD_GET_INFO }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_lstats_get_info }, #endif /* LINKSTAT_SUPPORT */ @@ -8003,6 +8081,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = GSCAN_SUBCMD_SET_EPNO_SSID }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_epno_cfg }, @@ -8012,6 +8093,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = WIFI_SUBCMD_SET_LAZY_ROAM_PARAMS }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_set_lazy_roam_cfg }, @@ -8021,6 +8105,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = WIFI_SUBCMD_ENABLE_LAZY_ROAM }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_enable_lazy_roam }, @@ -8030,6 +8117,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = WIFI_SUBCMD_SET_BSSID_PREF }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_set_bssid_pref }, @@ -8041,6 +8131,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = WIFI_SUBCMD_SET_SSID_WHITELIST }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_set_ssid_whitelist }, @@ -8050,6 +8143,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = WIFI_SUBCMD_SET_BSSID_BLACKLIST }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_set_bssid_blacklist }, #endif /* GSCAN_SUPPORT || ROAMEXP_SUPPORT */ @@ -8060,6 +8156,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = WIFI_SUBCMD_FW_ROAM_POLICY }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_set_fw_roaming_state }, { @@ -8068,6 +8167,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = WIFI_SUBCMD_ROAM_CAPABILITY }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_fw_roam_get_capability }, #endif /* ROAMEXP_SUPPORT */ @@ -8077,6 +8179,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = DEBUG_GET_VER }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_dbg_get_version }, #ifdef DHD_LOG_DUMP @@ -8086,6 +8191,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = DEBUG_GET_FILE_DUMP_BUF }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_dbg_file_dump }, #endif /* DHD_LOG_DUMP */ @@ -8097,6 +8205,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = DEBUG_TRIGGER_MEM_DUMP }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_dbg_trigger_mem_dump }, { @@ -8105,6 +8216,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = DEBUG_GET_MEM_DUMP }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_dbg_get_mem_dump }, { @@ -8113,6 +8227,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = DEBUG_START_LOGGING }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_dbg_start_logging }, { @@ -8121,6 +8238,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = DEBUG_RESET_LOGGING }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_dbg_reset_logging }, { @@ -8129,6 +8249,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = DEBUG_GET_RING_STATUS }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_dbg_get_ring_status }, { @@ -8137,6 +8260,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = DEBUG_GET_RING_DATA }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_dbg_get_ring_data }, #endif /* DEBUGABILITY */ @@ -8146,6 +8272,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = DEBUG_GET_FEATURE }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_dbg_get_feature }, #ifdef DBG_PKT_MON @@ -8155,6 +8284,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = DEBUG_START_PKT_FATE_MONITORING }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_dbg_start_pkt_fate_monitoring }, { @@ -8163,6 +8295,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = DEBUG_GET_TX_PKT_FATES }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_dbg_get_tx_pkt_fates }, { @@ -8171,6 +8306,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = DEBUG_GET_RX_PKT_FATES }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_dbg_get_rx_pkt_fates }, #endif /* DBG_PKT_MON */ @@ -8181,6 +8319,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_start_mkeep_alive }, { @@ -8189,6 +8330,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_stop_mkeep_alive }, #endif /* KEEP_ALIVE */ @@ -8199,6 +8343,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = NAN_WIFI_SUBCMD_ENABLE }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_nan_start_handler }, { @@ -8207,6 +8354,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = NAN_WIFI_SUBCMD_DISABLE }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_nan_stop_handler }, { @@ -8215,6 +8365,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = NAN_WIFI_SUBCMD_CONFIG }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_nan_config_handler }, { @@ -8223,6 +8376,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = NAN_WIFI_SUBCMD_REQUEST_PUBLISH }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_nan_req_publish }, { @@ -8231,6 +8387,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = NAN_WIFI_SUBCMD_REQUEST_SUBSCRIBE }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_nan_req_subscribe }, { @@ -8239,6 +8398,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = NAN_WIFI_SUBCMD_CANCEL_PUBLISH }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_nan_cancel_publish }, { @@ -8247,6 +8409,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = NAN_WIFI_SUBCMD_CANCEL_SUBSCRIBE }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_nan_cancel_subscribe }, { @@ -8255,6 +8420,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = NAN_WIFI_SUBCMD_TRANSMIT }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_nan_transmit }, { @@ -8263,6 +8431,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = NAN_WIFI_SUBCMD_GET_CAPABILITIES }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_nan_get_capablities }, @@ -8272,6 +8443,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = NAN_WIFI_SUBCMD_DATA_PATH_IFACE_CREATE }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_nan_data_path_iface_create }, { @@ -8280,6 +8454,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = NAN_WIFI_SUBCMD_DATA_PATH_IFACE_DELETE }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_nan_data_path_iface_delete }, { @@ -8288,6 +8465,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = NAN_WIFI_SUBCMD_DATA_PATH_REQUEST }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_nan_data_path_request }, { @@ -8296,6 +8476,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = NAN_WIFI_SUBCMD_DATA_PATH_RESPONSE }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_nan_data_path_response }, { @@ -8304,6 +8487,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = NAN_WIFI_SUBCMD_DATA_PATH_END }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_nan_data_path_end }, #ifdef WL_NAN_DISC_CACHE @@ -8313,6 +8499,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = NAN_WIFI_SUBCMD_DATA_PATH_SEC_INFO }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_nan_data_path_sec_info }, #endif /* WL_NAN_DISC_CACHE */ @@ -8322,6 +8511,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = NAN_WIFI_SUBCMD_VERSION_INFO }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_nan_version_info }, #endif /* WL_NAN */ @@ -8332,6 +8524,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = APF_SUBCMD_GET_CAPABILITIES }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_apf_get_capabilities }, @@ -8341,6 +8536,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = APF_SUBCMD_SET_FILTER }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_apf_set_filter }, #endif /* PKT_FILTER_SUPPORT && APF */ @@ -8351,6 +8549,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = WIFI_SUBCMD_CONFIG_ND_OFFLOAD }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_configure_nd_offload }, #endif /* NDO_CONFIG_SUPPORT */ @@ -8361,6 +8562,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = WIFI_SUBCMD_SET_RSSI_MONITOR }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_set_rssi_monitor }, #endif /* RSSI_MONITOR_SUPPORT */ @@ -8371,6 +8575,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = DEBUG_GET_WAKE_REASON_STATS }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_get_wake_reason_stats }, #endif /* DHD_WAKE_STATUS */ @@ -8381,6 +8588,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = WIFI_SUBCMD_CONFIG_TCPACK_SUP }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_set_tcpack_sup_mode }, #endif /* DHDTCPACK_SUPPRESS */ @@ -8391,6 +8601,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = BRCM_VENDOR_SCMD_SET_PMK }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_set_pmk }, #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) */ @@ -8400,6 +8613,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = BRCM_VENDOR_SCMD_GET_FEATURES }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_get_driver_feature }, #if defined(WL_CFG80211) && defined(DHD_FILE_DUMP_EVENT) @@ -8409,6 +8625,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = DEBUG_FILE_DUMP_DONE_IND }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_notify_dump_completion }, #endif /* WL_CFG80211 && DHD_FILE_DUMP_EVENT */ @@ -8419,6 +8638,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = DEBUG_SET_HAL_START }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_set_hal_started }, { @@ -8427,6 +8649,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { .subcmd = DEBUG_SET_HAL_STOP }, .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)) + .policy = VENDOR_CMD_RAW_DATA, +#endif .doit = wl_cfgvendor_stop_hal } #endif /* WL_CFG80211 */ diff --git a/bcmdhd.100.10.315.x/wl_escan.c b/bcmdhd.100.10.315.x/wl_escan.c index 82d5c5b..2775379 100644 --- a/bcmdhd.100.10.315.x/wl_escan.c +++ b/bcmdhd.100.10.315.x/wl_escan.c @@ -16,19 +16,19 @@ #define ESCAN_TRACE(name, arg1, args...) \ do { \ if (android_msg_level & ANDROID_TRACE_LEVEL) { \ - printk(KERN_ERR "[dhd-%s] ESCAN-TRACE) %s : " arg1, name, __func__, ## args); \ + printk(KERN_INFO "[dhd-%s] ESCAN-TRACE) %s : " arg1, name, __func__, ## args); \ } \ } while (0) #define ESCAN_SCAN(name, arg1, args...) \ do { \ if (android_msg_level & ANDROID_SCAN_LEVEL) { \ - printk(KERN_ERR "[dhd-%s] ESCAN-SCAN) %s : " arg1, name, __func__, ## args); \ + printk(KERN_INFO "[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); \ + printk(KERN_INFO "[dhd-%s] ESCAN-DBG) %s : " arg1, name, __func__, ## args); \ } \ } while (0) @@ -181,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; @@ -206,6 +206,7 @@ static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, (struct wl_bss_info *)((uintptr) bss + dtoh32(bss->length)) : list->bss_info; } +#if defined(ESCAN_RESULT_PATCH) static s32 wl_escan_inform_bss(struct net_device *dev, struct wl_escan_info *escan) { @@ -253,7 +254,7 @@ wl_escan_inform_bss(struct net_device *dev, struct wl_escan_info *escan) wl_reset_bss_cache(&escan->g_bss_cache_ctrl); if (escan->autochannel) wl_ext_get_best_channel(dev, &escan->g_bss_cache_ctrl, - escan->ioctl_ver &escan->best_2g_ch, &escan->best_5g_ch); + escan->ioctl_ver, &escan->best_2g_ch, &escan->best_5g_ch); #else if (escan->autochannel) wl_ext_get_best_channel(dev, bss_list, escan->ioctl_ver, @@ -262,6 +263,7 @@ wl_escan_inform_bss(struct net_device *dev, struct wl_escan_info *escan) return err; } +#endif /* ESCAN_RESULT_PATCH */ static wl_scan_params_t * wl_escan_alloc_params(struct net_device *dev, struct wl_escan_info *escan, @@ -270,7 +272,6 @@ wl_escan_alloc_params(struct net_device *dev, struct wl_escan_info *escan, wl_scan_params_t *params; int params_size; int num_chans; - int bssidx = 0; *out_params_size = 0; @@ -296,7 +297,7 @@ wl_escan_alloc_params(struct net_device *dev, struct wl_escan_info *escan, 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) | @@ -341,6 +342,7 @@ wl_escan_notify_complete(struct net_device *dev, char extra[IW_CUSTOM_MAX + 1]; #endif #endif + struct dhd_pub *dhd = dhd_get_pub(dev); ESCAN_TRACE(dev->name, "Enter\n"); @@ -349,11 +351,15 @@ wl_escan_notify_complete(struct net_device *dev, 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(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 @@ -433,8 +439,8 @@ wl_escan_remove_lowRSSI_info(struct net_device *dev, struct wl_escan_info *escan } #endif /* ESCAN_BUF_OVERFLOW_MGMT */ -s32 -wl_escan_handler2(struct net_device *dev, 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; @@ -618,9 +624,7 @@ wl_escan_handler2(struct net_device *dev, struct wl_escan_info *escan, escan->bss_list = wl_escan_get_buf(escan); ESCAN_DBG(dev->name, "SCAN COMPLETED: scanned AP count=%d\n", escan->bss_list->count); - wl_escan_inform_bss(dev, escan); wl_escan_notify_complete(dev, escan, false); - escan->escan_state = ESCAN_STATE_IDLE; } 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)) { @@ -629,24 +633,19 @@ wl_escan_handler2(struct net_device *dev, struct wl_escan_info *escan, escan->bss_list = wl_escan_get_buf(escan); ESCAN_DBG(dev->name, "SCAN ABORT: scanned AP count=%d\n", escan->bss_list->count); - wl_escan_inform_bss(dev, escan); wl_escan_notify_complete(dev, escan, false); - escan->escan_state = ESCAN_STATE_IDLE; } else if (status == WLC_E_STATUS_TIMEOUT) { ESCAN_ERROR(dev->name, "WLC_E_STATUS_TIMEOUT\n"); ESCAN_ERROR(dev->name, "reason[0x%x]\n", e->reason); if (e->reason == 0xFFFFFFFF) { wl_escan_notify_complete(dev, escan, true); } - escan->escan_state = ESCAN_STATE_IDLE; } else { ESCAN_ERROR(dev->name, "unexpected Escan Event %d : abort\n", status); escan->bss_list = wl_escan_get_buf(escan); ESCAN_DBG(dev->name, "SCAN ABORTED(UNEXPECTED): scanned AP count=%d\n", escan->bss_list->count); - wl_escan_inform_bss(dev, escan); wl_escan_notify_complete(dev, escan, false); - escan->escan_state = ESCAN_STATE_IDLE; } exit: mutex_unlock(&escan->usr_sync); @@ -801,6 +800,7 @@ wl_escan_timeout(unsigned long data) 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; @@ -809,7 +809,7 @@ wl_escan_timeout(unsigned long data) int wl_escan_set_scan(struct net_device *dev, dhd_pub_t *dhdp, - wlc_ssid_t *ssid, bool bcast) + wlc_ssid_t *ssid, uint16 channel, bool bcast) { struct wl_escan_info *escan = dhdp->escan; s32 err = BCME_OK; @@ -824,11 +824,12 @@ wl_escan_set_scan(struct net_device *dev, dhd_pub_t *dhdp, mutex_lock(&escan->usr_sync); if (escan->escan_state == ESCAN_STATE_DOWN) { ESCAN_ERROR(dev->name, "STATE is down\n"); - err = -EIO; + err = -EINVAL; goto exit2; } - if (escan->escan_state == ESCAN_STATE_SCANING) { - ESCAN_ERROR(dev->name, "Scanning already\n"); + + if (wl_ext_check_scan(dev, dhdp)) { + err = -EBUSY; goto exit; } @@ -837,13 +838,20 @@ wl_escan_set_scan(struct net_device *dev, dhd_pub_t *dhdp, /* 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(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; + + 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) @@ -883,14 +891,12 @@ wl_escan_set_scan(struct net_device *dev, dhd_pub_t *dhdp, ESCAN_TRACE(dev->name, "Escan not permitted at this time (%d)\n", err); else ESCAN_ERROR(dev->name, "Escan set error (%d)\n", err); - wl_escan_reset(escan); } kfree(params); -exit: if (unlikely(err)) { /* Don't print Error incase of Scan suppress */ - if ((err == BCME_EPERM)) + if (err == BCME_EPERM) ESCAN_TRACE(dev->name, "Escan failed: Scan Suppressed\n"); else { cnt++; @@ -907,6 +913,10 @@ exit: cnt = 0; escan->dev = dev; } +exit: + if (unlikely(err)) { + wl_escan_reset(escan); + } exit2: mutex_unlock(&escan->usr_sync); return err; @@ -940,6 +950,7 @@ wl_escan_merge_scan_results(struct net_device *dev, struct wl_escan_info *escan, char *event = extra, *end = extra + max_size - WE_ADD_EVENT_FIX, *value; int16 rssi; int channel; + chanspec_t chanspec; /* overflow check cover fields before wpa IEs */ if (event + ETHER_ADDR_LEN + bi->SSID_len + IW_EV_UINT_LEN + IW_EV_FREQ_LEN + @@ -956,9 +967,14 @@ wl_escan_merge_scan_results(struct net_device *dev, struct wl_escan_info *escan, // 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); #endif - channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec)); - ESCAN_SCAN(dev->name, "BSSID=%pM, channel=%3d, RSSI=%3d, SSID=\"%s\"\n", - &bi->BSSID, channel, rssi, bi->SSID); + chanspec = wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec); + channel = wf_chspec_ctlchan(chanspec); + ESCAN_SCAN(dev->name, "BSSID %pM, channel %3d(%3d %sMHz), rssi %3d, SSID \"%s\"\n", + &bi->BSSID, channel, CHSPEC_CHANNEL(chanspec), + CHSPEC_IS20(chanspec)?"20": + CHSPEC_IS40(chanspec)?"40": + CHSPEC_IS80(chanspec)?"80":"160", + rssi, bi->SSID); /* First entry must be the BSSID */ iwe.cmd = SIOCGIWAP; @@ -1055,6 +1071,7 @@ wl_escan_get_scan(struct net_device *dev, dhd_pub_t *dhdp, #endif char *buf = NULL; struct ether_addr cur_bssid; + u8 ioctl_buf[WLC_IOCTL_SMLEN]; if (!extra) { ESCAN_TRACE(dev->name, "extra is null\n"); @@ -1082,8 +1099,11 @@ wl_escan_get_scan(struct net_device *dev, dhd_pub_t *dhdp, ESCAN_SCAN(dev->name, "SIOCGIWSCAN, len=%d\n", dwrq->length); + wldev_iovar_getbuf(dev, "cur_etheraddr", NULL, 0, ioctl_buf, WLC_IOCTL_SMLEN, NULL); 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)) { + if (err != BCME_NOTASSOCIATED && + memcmp(ðer_null, &cur_bssid, ETHER_ADDR_LEN) && + memcmp(ioctl_buf, &cur_bssid, ETHER_ADDR_LEN)) { // merge current connected bss buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_ATOMIC); if (!buf) { @@ -1149,7 +1169,248 @@ exit: mutex_unlock(&escan->usr_sync); return err; } -#endif +#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; +} + +bool +wl_escan_mesh_info_ie(struct net_device *dev, 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; + uint max_len; + bool found = FALSE; + + memset(mesh_info, 0, sizeof(struct wl_mesh_params)); + 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]; + found = TRUE; + } else if (ie->id == MESH_INFO_HOP_CNT) { + mesh_info->hop_cnt = ie->data[0]; + } else if (ie->id == MESH_INFO_PEER_BSSID) { + max_len = min(MAX_HOP_LIST*ETHER_ADDR_LEN, (int)ie->len); + memcpy(mesh_info->peer_bssid, ie->data, max_len); + } + totl_len -= (ie->len + 2); + pie = ie->data + ie->len; + ie = (bcm_tlv_t *)pie; + } + } + } + + return found; +} + +bool +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 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, found = 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"); + goto exit; + } + if (!escan->bss_list) { + ESCAN_ERROR(dev->name, "scan not ready\n"); + goto exit; + } + if (dev != escan->dev) { + ESCAN_ERROR(dev->name, "not my scan from %s\n", escan->dev->name); + 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, prefer = FALSE; + if (!memcmp(peer_bssid, &bi->BSSID, ETHER_ADDR_LEN)) { + bi_sae = wl_escan_rsn_ie(((u8*)bi)+bi->ie_offset, bi->ie_length); + bss_found = wl_escan_mesh_info_ie(dev, ((u8*)bi)+bi->ie_offset, + bi->ie_length, &peer_mesh_info); + if (bss_found) { + 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, + sizeof(peer_mesh_info.peer_bssid)); + prefer = TRUE; + 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", + prefer?"*":" ", &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 found; +} + +bool +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) +{ + 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, found = 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"); + goto exit; + } + if (!escan->bss_list) { + ESCAN_ERROR(dev->name, "scan not ready\n"); + goto exit; + } + if (dev != escan->dev) { + ESCAN_ERROR(dev->name, "not my scan from %s\n", escan->dev->name); + 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 meshid_matched = FALSE, sec_matched = FALSE, bi_sae = FALSE, + bss_found = FALSE, prefer = FALSE; + + 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; + + bi_sae = wl_escan_rsn_ie(((u8*)bi)+bi->ie_offset, bi->ie_length); + if (bi_sae == sae) + sec_matched = TRUE; + + bss_found = wl_escan_mesh_info_ie(dev, ((u8*)bi)+bi->ie_offset, bi->ie_length, + &peer_mesh_info); + if (meshid_matched && sec_matched && bss_found && + (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, + sizeof(peer_mesh_info.peer_bssid)); + min_hop_cnt = peer_mesh_info.hop_cnt; + prefer = TRUE; + chan_matched = TRUE; + found = TRUE; + } + } + else if (meshid_matched && sec_matched && bss_found && + (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, + sizeof(peer_mesh_info.peer_bssid)); + max_rssi = bi_rssi; + prefer = TRUE; + 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", + prefer?"*":" ", &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); + } + } + +exit: + mutex_unlock(&escan->usr_sync); + return found; +} +#endif /* WLMESH */ static void wl_escan_deinit(struct net_device *dev, struct wl_escan_info *escan) @@ -1242,7 +1503,7 @@ wl_escan_event_dettach(struct net_device *dev, dhd_pub_t *dhdp) return ret; } - wl_ext_event_deregister(dev, dhdp, WLC_E_ESCAN_RESULT, wl_escan_handler2); + wl_ext_event_deregister(dev, dhdp, WLC_E_ESCAN_RESULT, wl_escan_handler); return 0; } @@ -1258,7 +1519,7 @@ wl_escan_event_attach(struct net_device *dev, dhd_pub_t *dhdp) return ret; } - ret = wl_ext_event_register(dev, dhdp, WLC_E_ESCAN_RESULT, wl_escan_handler2, + 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); @@ -1282,7 +1543,7 @@ wl_escan_detach(struct net_device *dev, dhd_pub_t *dhdp) kfree(escan->escan_ioctl_buf); escan->escan_ioctl_buf = NULL; } - wl_ext_event_deregister(dev, dhdp, WLC_E_ESCAN_RESULT, wl_escan_handler2); + 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; diff --git a/bcmdhd.100.10.315.x/wl_escan.h b/bcmdhd.100.10.315.x/wl_escan.h index f31ccea..080f333 100644 --- a/bcmdhd.100.10.315.x/wl_escan.h +++ b/bcmdhd.100.10.315.x/wl_escan.h @@ -1,6 +1,7 @@ #ifndef _wl_escan_ #define _wl_escan_ +#include #include #define ESCAN_BUF_SIZE (64 * 1024) @@ -17,14 +18,14 @@ enum escan_state { typedef struct wl_escan_info { struct net_device *dev; dhd_pub_t *pub; - struct timer_list scan_timeout; /* Timer for catch scan event timeout */ + timer_list_compat_t scan_timeout; /* Timer for catch scan event timeout */ int escan_state; int ioctl_ver; u8 escan_buf[ESCAN_BUF_SIZE]; struct wl_scan_results *bss_list; struct ether_addr disconnected_bssid; u8 *escan_ioctl_buf; - struct mutex usr_sync; /* maily for up/down synchronization */ + struct mutex usr_sync; /* maily for up/down synchronization */ int autochannel; int best_2g_ch; int best_5g_ch; @@ -37,12 +38,34 @@ typedef struct wl_escan_info { #endif } wl_escan_info_t; +#if defined(WLMESH) +enum mesh_info_id { + MESH_INFO_MASTER_BSSID = 1, + MESH_INFO_MASTER_CHANNEL, + MESH_INFO_HOP_CNT, + MESH_INFO_PEER_BSSID +}; + +#define MAX_HOP_LIST 10 +typedef struct wl_mesh_params { + struct ether_addr master_bssid; + uint16 master_channel; + uint hop_cnt; + struct ether_addr peer_bssid[MAX_HOP_LIST]; + uint16 scan_channel; +} wl_mesh_params_t; +bool wl_escan_mesh_info(struct net_device *dev, + struct wl_escan_info *escan, struct ether_addr *peer_bssid, + struct wl_mesh_params *mesh_info); +bool 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, bool bcast); + 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); -s32 wl_escan_handler2(struct net_device *dev, struct wl_escan_info *escan, - const wl_event_msg_t *e, void *data); int wl_escan_attach(struct net_device *dev, 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); diff --git a/bcmdhd.100.10.315.x/wl_event.c b/bcmdhd.100.10.315.x/wl_event.c index c9e3d56..5f75d65 100644 --- a/bcmdhd.100.10.315.x/wl_event.c +++ b/bcmdhd.100.10.315.x/wl_event.c @@ -13,13 +13,13 @@ #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); \ + printk(KERN_INFO "[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); \ + printk(KERN_INFO "[dhd-%s] EVENT-DBG) %s : " arg1, name, __func__, ## args); \ } \ } while (0) @@ -200,6 +200,7 @@ wl_ext_event_handler(struct work_struct *work_data) struct net_device *dev = NULL; struct event_handler_list *evt_node; dhd_pub_t *dhd; + unsigned long flags = 0; BCM_SET_CONTAINER_OF(event_params, work_data, struct wl_event_params, event_work); DHD_EVENT_WAKE_LOCK(event_params->pub); @@ -218,10 +219,13 @@ wl_ext_event_handler(struct work_struct *work_data) EVENT_TRACE(dev->name, "Unknown Event (%d): ignoring\n", e->etype); goto fail; } - if (dhd->busstate == DHD_BUS_DOWN) { + DHD_GENERAL_LOCK(dhd, flags); + if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhd)) { EVENT_ERROR(dev->name, "BUS is DOWN.\n"); + DHD_GENERAL_UNLOCK(dhd, flags); goto fail; } + DHD_GENERAL_UNLOCK(dhd, flags); EVENT_DBG(dev->name, "event type (%d)\n", e->etype); mutex_lock(&event_params->event_sync); evt_node = event_params->evt_head.evt_head; diff --git a/bcmdhd.100.10.315.x/wl_iw.c b/bcmdhd.100.10.315.x/wl_iw.c index f02173b..4f926c7 100644 --- a/bcmdhd.100.10.315.x/wl_iw.c +++ b/bcmdhd.100.10.315.x/wl_iw.c @@ -62,19 +62,19 @@ uint iw_msg_level = WL_ERROR_LEVEL; #define WL_TRACE_MSG(x, args...) \ do { \ if (iw_msg_level & WL_TRACE_LEVEL) { \ - printk(KERN_ERR "[dhd] WEXT-TRACE) %s : " x, __func__, ## args); \ + printk(KERN_INFO "[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); \ + printk(KERN_INFO "[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); \ + printk(KERN_INFO "[dhd] WEXT-WSEC) %s : " x, __func__, ## args); \ } \ } while (0) #define WL_ERROR(x) WL_ERROR_MSG x @@ -194,7 +194,7 @@ typedef struct iscan_buf { 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; @@ -514,97 +514,6 @@ 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_update_connect_status(struct net_device *dev, enum wl_ext_status status) { @@ -621,7 +530,9 @@ wl_iw_update_connect_status(struct net_device *dev, enum wl_ext_status status) cur_eapol_status = dhd->conf->eapol_status; if (status == WL_EXT_STATUS_CONNECTING) { - wl_ext_add_remove_pm_enable_work(wext_info, TRUE); +#ifdef WL_EXT_IAPSTA + wl_ext_add_remove_pm_enable_work(dev, TRUE); +#endif /* WL_EXT_IAPSTA */ if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &wpa_auth))) { WL_ERROR(("wpa_auth get error %d\n", error)); return; @@ -632,8 +543,11 @@ wl_iw_update_connect_status(struct net_device *dev, enum wl_ext_status status) dhd->conf->eapol_status = EAPOL_STATUS_NONE; } 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); +#ifdef WL_EXT_IAPSTA + wl_ext_add_remove_pm_enable_work(dev, FALSE); +#endif /* WL_EXT_IAPSTA */ 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)); @@ -648,6 +562,7 @@ wl_iw_update_connect_status(struct net_device *dev, enum wl_ext_status status) 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)); @@ -1533,7 +1448,7 @@ wl_iw_iscan_set_scan( } } #endif - return wl_escan_set_scan(dev, dhd, &ssid, TRUE); + 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)); @@ -3747,7 +3662,8 @@ wl_iw_event(struct net_device *dev, struct wl_wext_info *wext_info, 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", + WL_MSG_RLMT(dev->name, &e->addr, ETHER_ADDR_LEN, + "disconnected with "MACSTR", event %d, reason %d\n", MAC2STR((u8 *)wrqu.addr.sa_data), event_type, reason); break; case WLC_E_DEAUTH_IND: @@ -3971,7 +3887,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(("WLC_GET_PHY_NOISE error=%d\n", res)); + WL_TRACE(("WLC_GET_PHY_NOISE error=%d\n", res)); goto done; } @@ -3980,7 +3896,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(("WLC_GET_RSSI error=%d\n", res)); + WL_TRACE(("WLC_GET_RSSI error=%d\n", res)); goto done; } @@ -4076,10 +3992,9 @@ done: #ifndef WL_ESCAN static void -wl_iw_timerfunc(unsigned long data) +wl_iw_timerfunc(ulong data) { iscan_info_t *iscan = (iscan_info_t *)data; - iscan->timer_on = 0; if (iscan->iscan_state != ISCAN_STATE_IDLE) { WL_TRACE(("timer trigger\n")); @@ -4315,7 +4230,6 @@ wl_iw_detach(struct net_device *dev, dhd_pub_t *dhdp) iscan->list_hdr = buf; } #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); @@ -4357,7 +4271,7 @@ wl_iw_attach(struct net_device *dev, dhd_pub_t *dhdp) /* Set up the timer */ iscan->timer_ms = 2000; - init_timer_compat(&iscan->scan_timeout, wl_iw_timerfunc, iscan); + init_timer_compat(&iscan->timer, wl_iw_timerfunc, iscan); sema_init(&iscan->sysioc_sem, 0); init_completion(&iscan->sysioc_exited); @@ -4372,8 +4286,6 @@ wl_iw_attach(struct net_device *dev, dhd_pub_t *dhdp) 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) { @@ -4398,7 +4310,6 @@ wl_iw_down(struct net_device *dev, dhd_pub_t *dhdp) WL_ERROR (("dhd is NULL\n")); return; } - wl_ext_add_remove_pm_enable_work(wext_info, FALSE); } int diff --git a/bcmdhd.100.10.315.x/wl_iw.h b/bcmdhd.100.10.315.x/wl_iw.h index 44745e9..31d5811 100644 --- a/bcmdhd.100.10.315.x/wl_iw.h +++ b/bcmdhd.100.10.315.x/wl_iw.h @@ -38,6 +38,10 @@ #include #include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) +#define get_ds() (KERNEL_DS) +#endif + #define WL_SCAN_PARAMS_SSID_MAX 10 #define GET_SSID "SSID=" #define GET_CHANNEL "CH=" @@ -109,7 +113,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; diff --git a/bcmdhd.100.10.315.x/wldev_common.c b/bcmdhd.100.10.315.x/wldev_common.c index 7d89a9e..4181b28 100644 --- a/bcmdhd.100.10.315.x/wldev_common.c +++ b/bcmdhd.100.10.315.x/wldev_common.c @@ -47,17 +47,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 "[dhd] 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 "[dhd] 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); -- 2.20.1