From: jiabin.chen Date: Tue, 9 May 2023 05:17:21 +0000 (+0800) Subject: wifi: update driver for 62x8 not use bcmdl tool [1/2] X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=2a839cb3569c5ed97f0afe993305c7276355b762;p=GitHub%2FLineageOS%2FG12%2Fandroid_hardware_amlogic_kernel-modules_dhd-driver.git wifi: update driver for 62x8 not use bcmdl tool [1/2] PD#SWPL-122237 Problem: need del bcmdl and then 62x8 not work Solution: update driver and open CONFIG_BCMDHD_NO_POWER_OFF := y Verify: sc2-ah212 Change-Id: Ic3110283b0738a9c4627f3ea5172b2420959baf4 Signed-off-by: jiabin.chen --- diff --git a/bcmdhd.101.10.361.x/Makefile b/bcmdhd.101.10.361.x/Makefile index 42393f4..8f8e8e5 100755 --- a/bcmdhd.101.10.361.x/Makefile +++ b/bcmdhd.101.10.361.x/Makefile @@ -98,7 +98,6 @@ ifneq ($(CONFIG_CFG80211),) DHDCFLAGS += -DVSDB -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST DHDCFLAGS += -DWLTDLS -DMIRACAST_AMPDU_SIZE=8 # DHDCFLAGS += -DHOSTAPD_BW_SUPPORT -# DHDCFLAGS += -DHOSTAPD_EID_EXTENSION_SUPPORT DHDCFLAGS += -DWL_VIRTUAL_APSTA -DSTA_MGMT DHDCFLAGS += -DPNO_SUPPORT -DEXPLICIT_DISCIF_CLEANUP DHDCFLAGS += -DDHD_USE_SCAN_WAKELOCK @@ -106,13 +105,14 @@ ifneq ($(CONFIG_CFG80211),) DHDCFLAGS += -DWL_IFACE_MGMT DHDCFLAGS += -DSUPPORT_RSSI_SUM_REPORT DHDCFLAGS += -DWLFBT -DWL_GCMP_SUPPORT -DWL_OWE - DHDCFLAGS += -DROAM_CHANNEL_CACHE -DDHD_LOSSLESS_ROAMING -DWL_ROAM_WAR -# DHDCFLAGS += -DVNDR_IE_WAR -DGET_FW_IE_DATA + DHDCFLAGS += -DROAM_CHANNEL_CACHE -DDHD_LOSSLESS_ROAMING # DHDCFLAGS += -DWL_CFGVENDOR_SEND_HANG_EVENT DHDCFLAGS += -DGTK_OFFLOAD_SUPPORT - DHDCFLAGS += -DRESTART_AP_WAR - DHDCFLAGS += -DWL_STATIC_IF + DHDCFLAGS += -DWL_STATIC_IF #-DDHD_MAX_STATIC_IFS=2 DHDCFLAGS += -DWL_CLIENT_SAE + DHDCFLAGS += -DCONNECT_INFO_WAR -DWL_ROAM_WAR + DHDCFLAGS += -DVNDR_IE_WAR + DHDCFLAGS += -DRESTART_AP_WAR -DRXF0OVFL_REINIT_WAR endif #BCMDHD_SDIO @@ -123,7 +123,8 @@ DHDCFLAGS += -DBCMSDIO -DMMC_SDIO_ABORT -DUSE_SDIOFIFO_IOVAR -DBCMLXSDMMC \ -DBCMSDIOH_TXGLOM -DBCMSDIOH_TXGLOM_EXT -DBCMSDIOH_STATIC_COPY_BUF \ -DRXFRAME_THREAD -DDHDENABLE_TAILPAD -DSUPPORT_P2P_GO_PS \ -DBCMSDIO_RXLIM_POST -DBCMSDIO_TXSEQ_SYNC -DCONSOLE_DPC \ - -DBCMSDIO_INTSTATUS_WAR -DMMC_SW_RESET -DMMC_HW_RESET + -DBCMSDIO_INTSTATUS_WAR +DHDCFLAGS += -DMMC_HW_RESET -DMMC_SW_RESET #-DBUS_POWER_RESTORE ifeq ($(CONFIG_BCMDHD_OOB),y) DHDCFLAGS += -DOOB_INTR_ONLY -DCUSTOMER_OOB -DHW_OOB ifeq ($(CONFIG_BCMDHD_DISABLE_WOWLAN),y) @@ -254,6 +255,7 @@ ifeq ($(CONFIG_BCMDHD_DEBUG),y) DHDCFLAGS += -DPKT_STATICS DHDCFLAGS += -DKSO_DEBUG # DHDCFLAGS += -DDHD_PKTDUMP_TOFW +# DHDCFLAGS += -DDHD_DUMP_FILE_WRITE_FROM_KERNEL endif # For Debug2 @@ -402,9 +404,9 @@ ifeq ($(CONFIG_BCMDHD_REQUEST_FW),y) else DHDCFLAGS += -DDHD_SUPPORT_VFS_CALL ifeq ($(CONFIG_BCMDHD_FW_PATH),) - DHDCFLAGS += -DCONFIG_BCMDHD_FW_PATH="\"/system/etc/firmware/fw_bcmdhd.bin\"" - DHDCFLAGS += -DCONFIG_BCMDHD_NVRAM_PATH="\"/system/etc/firmware/nvram.txt\"" - DHDCFLAGS += -DCONFIG_BCMDHD_CLM_PATH="\"/system/etc/firmware/clm_bcmdhd.blob\"" + DHDCFLAGS += -DCONFIG_BCMDHD_FW_PATH="\"/vendor/etc/firmware/fw_bcmdhd.bin\"" + DHDCFLAGS += -DCONFIG_BCMDHD_NVRAM_PATH="\"/vendor/etc/firmware/nvram.txt\"" + DHDCFLAGS += -DCONFIG_BCMDHD_CLM_PATH="\"/vendor/etc/firmware/clm_bcmdhd.blob\"" endif endif @@ -421,7 +423,12 @@ else endif DHDCFLAGS += -DSTATIC_WL_PRIV_STRUCT -DENHANCED_STATIC_BUF DHDCFLAGS += -DCONFIG_DHD_USE_STATIC_BUF +ifneq ($(filter -DDHD_LOG_DUMP, $(DHDCFLAGS)),) + DHDCFLAGS += -DDHD_USE_STATIC_MEMDUMP +endif +ifneq ($(filter -DDHD_FW_COREDUMP, $(DHDCFLAGS)),) DHDCFLAGS += -DDHD_USE_STATIC_MEMDUMP +endif ifneq ($(CONFIG_BCMDHD_PCIE),) DHDCFLAGS += -DDHD_USE_STATIC_CTRLBUF endif diff --git a/bcmdhd.101.10.361.x/bcmevent.c b/bcmdhd.101.10.361.x/bcmevent.c index 61009d3..2039769 100755 --- a/bcmdhd.101.10.361.x/bcmevent.c +++ b/bcmdhd.101.10.361.x/bcmevent.c @@ -243,6 +243,24 @@ static const bcmevent_name_str_t bcmevent_names[] = { #ifdef WL_TWT BCMEVENT_NAME(WLC_E_TWT), #endif /* WL_TWT */ + BCMEVENT_NAME(WLC_E_AMT), + BCMEVENT_NAME(WLC_E_ROAM_SCAN_RESULT), +#if defined(XRAPI) + BCMEVENT_NAME(WLC_E_XR_SOFTAP_PSMODE), +#endif /* XRAPI */ +#ifdef WL_SIB_COEX + BCMEVENT_NAME(WLC_E_SIB), +#endif /* WL_SIB_COEX */ + BCMEVENT_NAME(WLC_E_MSCS), + BCMEVENT_NAME(WLC_E_RXDMA_RECOVERY_ATMPT), +#ifdef WL_SCHED_SCAN + BCMEVENT_NAME(WLC_E_PFN_PARTIAL_RESULT), +#endif /* WL_SCHED_SCAN */ + BCMEVENT_NAME(WLC_E_MLO_LINK_INFO), + BCMEVENT_NAME(WLC_E_C2C), + BCMEVENT_NAME(WLC_E_BCN_TSF), + BCMEVENT_NAME(WLC_E_OWE_INFO), + BCMEVENT_NAME(WLC_E_ULMU_DISABLED_REASON_UPD), }; const char *bcmevent_get_name(uint event_type) diff --git a/bcmdhd.101.10.361.x/bcmsdh_sdmmc.c b/bcmdhd.101.10.361.x/bcmsdh_sdmmc.c index a1dcf33..d4b6878 100755 --- a/bcmdhd.101.10.361.x/bcmsdh_sdmmc.c +++ b/bcmdhd.101.10.361.x/bcmsdh_sdmmc.c @@ -82,7 +82,7 @@ static void IRQHandler(struct sdio_func *func); static void IRQHandlerF2(struct sdio_func *func); #endif /* !defined(OOB_INTR_ONLY) */ static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr); -#if defined(ENABLE_INSMOD_NO_FW_LOAD) && !defined(BUS_POWER_RESTORE) +#if defined(ENABLE_INSMOD_NO_FW_LOAD) #if defined(MMC_SW_RESET) && LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0) extern int mmc_sw_reset(struct mmc_card *card); @@ -95,6 +95,10 @@ extern int mmc_hw_reset(struct mmc_card *card); #else extern int mmc_hw_reset(struct mmc_host *host); #endif +#elif defined(BUS_POWER_RESTORE) && \ +LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) +#undef MMC_SW_RESET +#undef MMC_HW_RESET #else extern int sdio_reset_comm(struct mmc_card *card); #endif @@ -1787,7 +1791,7 @@ sdioh_sdmmc_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, int regsiz } #endif /* NOTUSED */ -#if defined(ENABLE_INSMOD_NO_FW_LOAD) && !defined(BUS_POWER_RESTORE) +#if defined(ENABLE_INSMOD_NO_FW_LOAD) static int sdio_sw_reset(sdioh_info_t *sd) { struct mmc_card *card = sd->func[0]->card; @@ -1818,6 +1822,10 @@ static int sdio_sw_reset(sdioh_info_t *sd) err = mmc_hw_reset(card->host); #endif sdio_release_host(sd->func[0]); +#elif defined(BUS_POWER_RESTORE) && \ +LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) + printf("%s: call mmc_power_restore_host\n", __FUNCTION__); + mmc_power_restore_host(card->host); #else /* sdio_reset_comm */ err = sdio_reset_comm(card); @@ -1856,7 +1864,7 @@ sdioh_start(sdioh_info_t *sd, int stage) 2.6.27. The implementation prior to that is buggy, and needs broadcom's patch for it */ -#if defined(ENABLE_INSMOD_NO_FW_LOAD) && !defined(BUS_POWER_RESTORE) +#if defined(ENABLE_INSMOD_NO_FW_LOAD) if ((ret = sdio_sw_reset(sd))) { sd_err(("%s Failed, error = %d\n", __FUNCTION__, ret)); return ret; @@ -1955,6 +1963,16 @@ sdioh_stop(sdioh_info_t *sd) else sd_err(("%s Failed\n", __FUNCTION__)); #endif /* defined(OEM_ANDROID) */ +#if !defined(MMC_SW_RESET) && !defined(MMC_HW_RESET) +#if defined(BUS_POWER_RESTORE) && \ +LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) + if (sd->func[0]) { + struct mmc_card *card = sd->func[0]->card; + printf("%s: call mmc_power_save_host\n", __FUNCTION__); + mmc_power_save_host(card->host); + } +#endif +#endif #if !defined(OOB_INTR_ONLY) sdio_claim_host_unlock_local(sd); #endif diff --git a/bcmdhd.101.10.361.x/dbus.c b/bcmdhd.101.10.361.x/dbus.c index d15b758..40a4b8c 100755 --- a/bcmdhd.101.10.361.x/dbus.c +++ b/bcmdhd.101.10.361.x/dbus.c @@ -2913,7 +2913,7 @@ dbus_resume(void *context) if (bus->dhd->up == FALSE) { return BCME_OK; } - + dlneeded = dbus_dlneeded(bus); if (dlneeded == 0) { ret = dbus_up(bus); diff --git a/bcmdhd.101.10.361.x/dhd_cdc.c b/bcmdhd.101.10.361.x/dhd_cdc.c index a81d49f..8a4bf27 100755 --- a/bcmdhd.101.10.361.x/dhd_cdc.c +++ b/bcmdhd.101.10.361.x/dhd_cdc.c @@ -775,6 +775,7 @@ dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reord cur_pkt = *pkt; *pkt = NULL; + *pkt_count = 0; ptr = dhd->reorder_bufs[flow_id]; if (flags & WLHOST_REORDERDATA_DEL_FLOW) { @@ -784,10 +785,12 @@ dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reord __FUNCTION__, flow_id)); if (ptr == NULL) { - DHD_REORDER(("%s: received flags to cleanup, but no flow (%d) yet\n", + DHD_ERROR(("%s: received flags to cleanup, but no flow (%d) yet\n", __FUNCTION__, flow_id)); - *pkt_count = 1; - *pkt = cur_pkt; + if (cur_pkt) { + *pkt_count = 1; + *pkt = cur_pkt; + } return 0; } @@ -795,16 +798,22 @@ dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reord ptr->exp_idx, ptr->exp_idx); /* set it to the last packet */ if (plast) { - PKTSETNEXT(dhd->osh, plast, cur_pkt); - cnt++; + if (cur_pkt) { + PKTSETNEXT(dhd->osh, plast, cur_pkt); + cnt++; + } } else { if (cnt != 0) { DHD_ERROR(("%s: del flow: something fishy, pending packets %d\n", __FUNCTION__, cnt)); } - *pkt = cur_pkt; - cnt = 1; + if (cur_pkt) { + *pkt = cur_pkt; + cnt = 1; + } else { + cnt = 0; + } } buf_size += ((ptr->max_idx + 1) * sizeof(void *)); MFREE(dhd->osh, ptr, buf_size); @@ -825,7 +834,10 @@ dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reord ptr = (struct reorder_info *)MALLOC(dhd->osh, buf_size_alloc); if (ptr == NULL) { DHD_ERROR(("%s: Malloc failed to alloc buffer\n", __FUNCTION__)); - *pkt_count = 1; + if (cur_pkt) { + *pkt = cur_pkt; + *pkt_count = 1; + } return 0; } bzero(ptr, buf_size_alloc); @@ -847,6 +859,17 @@ dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reord ptr->p[ptr->cur_idx] = cur_pkt; ptr->pend_pkts++; *pkt_count = cnt; + /* Corner case: wrong BA WSIZE make 'cur < exp' with FLUSH */ + if ((ptr->cur_idx < ptr->exp_idx) || + (WLHOST_REORDERDATA_FLUSH_ALL & flags)) { + cur_idx = ptr->cur_idx; + exp_idx = ptr->exp_idx; + dhd_get_hostreorder_pkts(dhd->osh, ptr, pkt, &cnt, &plast, + cur_idx, exp_idx); + *pkt_count = cnt; + DHD_ERROR(("%s: *Warning, new+flush, out=%d, pending=%d\n", + __FUNCTION__, cnt, ptr->pend_pkts)); + } } else if (flags & WLHOST_REORDERDATA_CURIDX_VALID) { cur_idx = reorder_info_buf[WLHOST_REORDERDATA_CURIDX_OFFSET]; @@ -874,7 +897,7 @@ dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reord DHD_REORDER(("%s: got the right one now, cur_idx is %d\n", __FUNCTION__, cur_idx)); if (ptr->p[cur_idx] != NULL) { - DHD_REORDER(("%s: Error buffer pending..free it\n", + DHD_ERROR(("%s: Error buffer pending..free it\n", __FUNCTION__)); PKTFREE(dhd->osh, ptr->p[cur_idx], TRUE); ptr->p[cur_idx] = NULL; @@ -919,7 +942,9 @@ dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reord PKTSETNEXT(dhd->osh, plast, cur_pkt); else *pkt = cur_pkt; - cnt++; + if (cur_pkt) { + cnt++; + } } else { ptr->p[cur_idx] = cur_pkt; @@ -947,7 +972,9 @@ dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reord PKTSETNEXT(dhd->osh, plast, cur_pkt); else *pkt = cur_pkt; - cnt++; + if (cur_pkt) { + cnt++; + } *pkt_count = cnt; /* set the new expected idx */ ptr->exp_idx = exp_idx; diff --git a/bcmdhd.101.10.361.x/dhd_common.c b/bcmdhd.101.10.361.x/dhd_common.c index 2c465d3..680b791 100755 --- a/bcmdhd.101.10.361.x/dhd_common.c +++ b/bcmdhd.101.10.361.x/dhd_common.c @@ -5159,6 +5159,13 @@ wl_show_host_event(dhd_pub_t *dhd_pub, wl_event_msg_t *event, void *event_data, DHD_EVENT(("MACEVENT: %s, type:%d\n", event_name, reason)); break; #endif /* WL_TWT */ + case WLC_E_COUNTRY_CODE_CHANGED: + DHD_EVENT(("MACEVENT: %s: Country code changed to %s\n", event_name, + (char*)event_data)); + break; + case WLC_E_OWE_INFO: + DHD_EVENT(("MACEVENT: %s, MAC %s type:%d\n", event_name, eabuf, reason)); + break; default: DHD_EVENT(("MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d\n", event_name, event_type, eabuf, (int)status, (int)reason, diff --git a/bcmdhd.101.10.361.x/dhd_config.c b/bcmdhd.101.10.361.x/dhd_config.c index a91aecc..4df7ca3 100755 --- a/bcmdhd.101.10.361.x/dhd_config.c +++ b/bcmdhd.101.10.361.x/dhd_config.c @@ -565,6 +565,29 @@ dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, char *nv_path) } } #endif + +bool +dhd_conf_legacy_otp_chip(dhd_pub_t *dhd) +{ + uint chip; + + chip = dhd->conf->chip; + + if (chip == BCM43362_CHIP_ID || chip == BCM4330_CHIP_ID || + chip == BCM4334_CHIP_ID || chip == BCM43340_CHIP_ID || + chip == BCM43341_CHIP_ID || chip == BCM4324_CHIP_ID || + chip == BCM4335_CHIP_ID || chip == BCM4339_CHIP_ID || + chip == BCM4354_CHIP_ID || chip == BCM4356_CHIP_ID || + chip == BCM4371_CHIP_ID || + chip == BCM43430_CHIP_ID || + chip == BCM4345_CHIP_ID || chip == BCM43454_CHIP_ID || + chip == BCM4359_CHIP_ID || chip == BCM43012_CHIP_ID || + chip == BCM43751_CHIP_ID || chip == BCM43752_CHIP_ID) { + return true; + } + + return false; +} #endif #ifdef BCMPCIE @@ -867,7 +890,7 @@ dhd_conf_get_module_name(dhd_pub_t *dhd, int ag_type) #endif const chip_name_map_t *row_chip = NULL; char *name = NULL; - + #if defined(BCMPCIE) && defined(UPDATE_MODULE_NAME) row_module = dhd_conf_match_module(dhd); if (row_module && strlen(row_module->module_name)) { @@ -1635,13 +1658,20 @@ dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec) return bcmerror; } -int +static int dhd_conf_set_country(dhd_pub_t *dhd, wl_country_t *cspec) { int bcmerror = -1; + struct net_device *net; + int bytes_written = 0; + char event_msg[32]; memset(&dhd->dhd_cspec, 0, sizeof(wl_country_t)); + net = dhd_idx2net(dhd, 0); + snprintf(event_msg, sizeof(event_msg), "wl event_msg %d 0", WLC_E_COUNTRY_CODE_CHANGED); + wl_android_ext_priv_cmd(net, event_msg, 0, &bytes_written); + CONFIG_MSG("set country %s, revision %d\n", cspec->ccode, cspec->rev); bcmerror = dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "country", (char *)cspec, sizeof(wl_country_t), FALSE); @@ -1649,6 +1679,9 @@ dhd_conf_set_country(dhd_pub_t *dhd, wl_country_t *cspec) CONFIG_MSG("Country code: %s (%s/%d)\n", cspec->country_abbrev, cspec->ccode, cspec->rev); + snprintf(event_msg, sizeof(event_msg), "wl event_msg %d 1", WLC_E_COUNTRY_CODE_CHANGED); + wl_android_ext_priv_cmd(net, event_msg, 0, &bytes_written); + return bcmerror; } @@ -1911,7 +1944,7 @@ dhd_conf_country(dhd_pub_t *dhd, char *cmd, char *buf) strlcpy(cspec.country_abbrev, buf, WL_CCODE_LEN + 1); strlcpy(cspec.ccode, buf, WL_CCODE_LEN + 1); dhd_conf_map_country_list(dhd, &cspec); - if (!memcmp(&cspec.ccode, &cur_cspec.ccode, WL_CCODE_LEN + 1) && + if (!memcmp(&cspec.ccode, &cur_cspec.ccode, WL_CCODE_LEN) && (cspec.rev == cur_cspec.rev)) { CONFIG_MSG("country code = %s/%d is already configured\n", cspec.ccode, cspec.rev); @@ -1927,6 +1960,33 @@ dhd_conf_country(dhd_pub_t *dhd, char *cmd, char *buf) return err; } +int +dhd_conf_autocountry(dhd_pub_t *dhd, char *cmd, char *buf) +{ + struct net_device *net; + int bytes_written = 0; + char event_msg[32]; + int enable = 0; + + if (buf) { + sscanf(buf, "%d", &enable); + } + + net = dhd_idx2net(dhd, 0); + snprintf(event_msg, sizeof(event_msg), "wl event_msg %d 0", WLC_E_COUNTRY_CODE_CHANGED); + wl_android_ext_priv_cmd(net, event_msg, 0, &bytes_written); + + CONFIG_MSG("autocountry %d\n", enable); + dhd_conf_set_intiovar(dhd, 0, WLC_SET_VAR, "autocountry", enable, 0, FALSE); + + snprintf(event_msg, sizeof(event_msg), "wl event_msg %d 1", WLC_E_COUNTRY_CODE_CHANGED); + wl_android_ext_priv_cmd(net, event_msg, 0, &bytes_written); + + dhd_conf_country(dhd, "country", dhd->conf->cspec.country_abbrev); + + return 0; +} + typedef int (tpl_parse_t)(dhd_pub_t *dhd, char *name, char *buf); typedef struct iovar_tpl_t { @@ -1943,6 +2003,7 @@ const iovar_tpl_t iovar_tpl_list[] = { {WLC_SET_VAR, "scanmac", dhd_conf_scan_mac}, #endif {WLC_SET_VAR, "country", dhd_conf_country}, + {WLC_SET_VAR, "autocountry", dhd_conf_autocountry}, }; static int iovar_tpl_parse(const iovar_tpl_t *tpl, int tpl_count, @@ -4673,11 +4734,7 @@ dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path) goto err; } -#ifdef DHD_LINUX_STD_FW_API - memblock_len = MAXSZ_CONFIG; -#else memblock_len = MAXSZ_CONFIG; -#endif /* DHD_LINUX_STD_FW_API */ pick = MALLOC(dhd->osh, MAXSZ_BUF); if (!pick) { @@ -5050,7 +5107,6 @@ dhd_conf_postinit_ioctls(dhd_pub_t *dhd) dhd_conf_set_intiovar(dhd, 0, WLC_SET_SRL, "WLC_SET_SRL", conf->srl, 0, FALSE); dhd_conf_set_intiovar(dhd, 0, WLC_SET_LRL, "WLC_SET_LRL", conf->lrl, 0, FALSE); dhd_conf_set_bw_cap(dhd); - dhd_conf_set_roam(dhd, 0); #if defined(BCMPCIE) dhd_conf_set_intiovar(dhd, 0, WLC_SET_VAR, "bus:deepsleep_disable", @@ -5112,6 +5168,7 @@ dhd_conf_postinit_ioctls(dhd_pub_t *dhd) } } #endif /* WLEASYMESH */ +#if defined(BCMSDIO) || defined(BCMPCIE) #if defined(BCMSDIO) if (conf->devid == BCM43751_CHIP_ID) #elif defined(BCMPCIE) @@ -5123,6 +5180,7 @@ dhd_conf_postinit_ioctls(dhd_pub_t *dhd) dhd_conf_set_wl_cmd(dhd, he_features, TRUE); } } +#endif #ifdef UPDATE_MODULE_NAME dhd_conf_compat_func(dhd); #endif @@ -5330,7 +5388,8 @@ dhd_conf_preinit(dhd_pub_t *dhd) conf->in4way = STA_NO_SCAN_IN4WAY | STA_WAIT_DISCONNECTED | AP_WAIT_STA_RECONNECT; if (conf->chip == BCM43752_CHIP_ID) - conf->war = SET_CHAN_INCONN | FW_REINIT_INCSA | FW_REINIT_EMPTY_SCAN; + conf->war = SET_CHAN_INCONN | FW_REINIT_INCSA | FW_REINIT_EMPTY_SCAN | + FW_REINIT_RXF0OVFL; else conf->war = 0; #ifdef P2P_AP_CONCURRENT diff --git a/bcmdhd.101.10.361.x/dhd_config.h b/bcmdhd.101.10.361.x/dhd_config.h index 522d760..e33e8c7 100755 --- a/bcmdhd.101.10.361.x/dhd_config.h +++ b/bcmdhd.101.10.361.x/dhd_config.h @@ -125,7 +125,8 @@ enum war_flags { FW_REINIT_INCSA = (1 << (1)), FW_REINIT_EMPTY_SCAN = (1 << (2)), P2P_AP_MAC_CONFLICT = (1 << (3)), - RESEND_EAPOL_PKT = (1 << (4)) + RESEND_EAPOL_PKT = (1 << (4)), + FW_REINIT_RXF0OVFL = (1 << (5)) }; enum in4way_flags { @@ -170,26 +171,27 @@ enum conn_state { CONN_STATE_AUTH_SAE_M2 = 3, CONN_STATE_AUTH_SAE_M3 = 4, CONN_STATE_AUTH_SAE_M4 = 5, - CONN_STATE_REQID = 6, - CONN_STATE_RSPID = 7, - CONN_STATE_WSC_START = 8, - CONN_STATE_WPS_M1 = 9, - CONN_STATE_WPS_M2 = 10, - CONN_STATE_WPS_M3 = 11, - CONN_STATE_WPS_M4 = 12, - CONN_STATE_WPS_M5 = 13, - CONN_STATE_WPS_M6 = 14, - CONN_STATE_WPS_M7 = 15, - CONN_STATE_WPS_M8 = 16, - CONN_STATE_WSC_DONE = 17, - CONN_STATE_4WAY_M1 = 18, - CONN_STATE_4WAY_M2 = 19, - CONN_STATE_4WAY_M3 = 20, - CONN_STATE_4WAY_M4 = 21, - CONN_STATE_ADD_KEY = 22, - CONN_STATE_CONNECTED = 23, - CONN_STATE_GROUPKEY_M1 = 24, - CONN_STATE_GROUPKEY_M2 = 25, + CONN_STATE_ASSOCIATED = 6, + CONN_STATE_REQID = 7, + CONN_STATE_RSPID = 8, + CONN_STATE_WSC_START = 9, + CONN_STATE_WPS_M1 = 10, + CONN_STATE_WPS_M2 = 11, + CONN_STATE_WPS_M3 = 12, + CONN_STATE_WPS_M4 = 13, + CONN_STATE_WPS_M5 = 14, + CONN_STATE_WPS_M6 = 15, + CONN_STATE_WPS_M7 = 16, + CONN_STATE_WPS_M8 = 17, + CONN_STATE_WSC_DONE = 18, + CONN_STATE_4WAY_M1 = 19, + CONN_STATE_4WAY_M2 = 20, + CONN_STATE_4WAY_M3 = 21, + CONN_STATE_4WAY_M4 = 22, + CONN_STATE_ADD_KEY = 23, + CONN_STATE_CONNECTED = 24, + CONN_STATE_GROUPKEY_M1 = 25, + CONN_STATE_GROUPKEY_M2 = 26, }; enum enq_pkt_type { @@ -401,6 +403,7 @@ void dhd_conf_get_otp(dhd_pub_t *dhd, bcmsdh_info_t *sdh, si_t *sih); 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); +bool dhd_conf_legacy_otp_chip(dhd_pub_t *dhd); #endif #ifdef BCMPCIE int dhd_conf_get_otp(dhd_pub_t *dhd, si_t *sih); @@ -450,9 +453,7 @@ void dhd_conf_tput_monitor(dhd_pub_t *dhd); uint dhd_conf_get_insuspend(dhd_pub_t *dhd, uint mask); int dhd_conf_set_suspend_resume(dhd_pub_t *dhd, int suspend); void dhd_conf_postinit_ioctls(dhd_pub_t *dhd); -#ifdef WL_STATIC_IF void dhd_conf_preinit_ioctls_sta(dhd_pub_t *dhd, int ifidx); -#endif /* WL_STATIC_IF */ int dhd_conf_preinit(dhd_pub_t *dhd); int dhd_conf_reset(dhd_pub_t *dhd); int dhd_conf_attach(dhd_pub_t *dhd); diff --git a/bcmdhd.101.10.361.x/dhd_debug.c b/bcmdhd.101.10.361.x/dhd_debug.c index 6ab2326..2a40a53 100755 --- a/bcmdhd.101.10.361.x/dhd_debug.c +++ b/bcmdhd.101.10.361.x/dhd_debug.c @@ -321,11 +321,11 @@ dhd_dbg_msgtrace_msg_parser(void *event_data) */ while (*data != '\0' && (s = strstr(data, "\n")) != NULL) { *s = '\0'; - DHD_FWLOG(("[FWLOG] %s\n", data)); + printf("[FWLOG] %s\n", data); data = s+1; } if (*data) - DHD_FWLOG(("[FWLOG] %s", data)); + printf("[FWLOG] %s", data); } #ifdef SHOW_LOGTRACE #define DATA_UNIT_FOR_LOG_CNT 4 diff --git a/bcmdhd.101.10.361.x/dhd_gpio.c b/bcmdhd.101.10.361.x/dhd_gpio.c index 594afbb..211e7a0 100755 --- a/bcmdhd.101.10.361.x/dhd_gpio.c +++ b/bcmdhd.101.10.361.x/dhd_gpio.c @@ -9,18 +9,7 @@ #include #endif -#if defined(BUS_POWER_RESTORE) && defined(BCMSDIO) -#include -#include -#include -#include -#endif /* defined(BUS_POWER_RESTORE) && defined(BCMSDIO) */ - #ifdef CONFIG_DHD_USE_STATIC_BUF -#ifdef DHD_STATIC_IN_DRIVER -extern int dhd_static_buf_init(void); -extern void dhd_static_buf_exit(void); -#endif /* DHD_STATIC_IN_DRIVER */ #if defined(BCMDHD_MDRIVER) && !defined(DHD_STATIC_IN_DRIVER) extern void *bcmdhd_mem_prealloc(uint bus_type, int index, int section, unsigned long size); @@ -105,15 +94,7 @@ dhd_wlan_set_power(int on, wifi_adapter_info_t *adapter) #endif #endif #ifdef BUS_POWER_RESTORE -#ifdef BCMSDIO -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) - if (adapter->sdio_func && adapter->sdio_func->card && adapter->sdio_func->card->host) { - mdelay(100); - printf("======== mmc_power_restore_host! ========\n"); - mmc_power_restore_host(adapter->sdio_func->card->host); - } -#endif -#elif defined(BCMPCIE) +#ifdef BCMPCIE if (adapter->pci_dev) { mdelay(100); printf("======== pci_set_power_state PCI_D0! ========\n"); @@ -131,14 +112,7 @@ dhd_wlan_set_power(int on, wifi_adapter_info_t *adapter) /* Lets customer power to get stable */ } else { #ifdef BUS_POWER_RESTORE -#ifdef BCMSDIO -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) - if (adapter->sdio_func && adapter->sdio_func->card && adapter->sdio_func->card->host) { - printf("======== mmc_power_save_host! ========\n"); - mmc_power_save_host(adapter->sdio_func->card->host); - } -#endif -#elif defined(BCMPCIE) +#ifdef BCMPCIE if (adapter->pci_dev) { printf("======== pci_set_power_state PCI_D3hot! ========\n"); pci_save_state(adapter->pci_dev); @@ -186,7 +160,6 @@ dhd_wlan_set_carddetect(int present) { int err = 0; -#if !defined(BUS_POWER_RESTORE) if (present) { #if defined(BCMSDIO) printf("======== Card detection to detect SDIO card! ========\n"); @@ -217,7 +190,6 @@ dhd_wlan_set_carddetect(int present) #endif #endif } -#endif /* BUS_POWER_RESTORE */ return err; } @@ -225,7 +197,7 @@ dhd_wlan_set_carddetect(int present) static int dhd_wlan_get_mac_addr(unsigned char *buf, int ifidx) { - int err = 0; + int err = -1; if (ifidx == 1) { #ifdef EXAMPLE_GET_MAC @@ -476,13 +448,13 @@ dhd_wlan_deinit_gpio(wifi_adapter_info_t *adapter) if (gpio_wl_reg_on >= 0) { printf("%s: gpio_free(WL_REG_ON %d)\n", __FUNCTION__, gpio_wl_reg_on); gpio_free(gpio_wl_reg_on); - gpio_wl_reg_on = -1; + adapter->gpio_wl_reg_on = -1; } #ifdef CUSTOMER_OOB if (gpio_wl_host_wake >= 0) { printf("%s: gpio_free(WL_HOST_WAKE %d)\n", __FUNCTION__, gpio_wl_host_wake); gpio_free(gpio_wl_host_wake); - gpio_wl_host_wake = -1; + adapter->gpio_wl_host_wake = -1; } #endif /* CUSTOMER_OOB */ } @@ -538,10 +510,6 @@ dhd_wlan_init_plat_data(wifi_adapter_info_t *adapter) if (err) goto exit; -#ifdef DHD_STATIC_IN_DRIVER - err = dhd_static_buf_init(); -#endif - exit: return err; } @@ -549,8 +517,5 @@ exit: void dhd_wlan_deinit_plat_data(wifi_adapter_info_t *adapter) { -#ifdef DHD_STATIC_IN_DRIVER - dhd_static_buf_exit(); -#endif dhd_wlan_deinit_gpio(adapter); } diff --git a/bcmdhd.101.10.361.x/dhd_linux.c b/bcmdhd.101.10.361.x/dhd_linux.c index 4160930..e54223c 100755 --- a/bcmdhd.101.10.361.x/dhd_linux.c +++ b/bcmdhd.101.10.361.x/dhd_linux.c @@ -624,6 +624,10 @@ static void dhd_natoe_ct_event_hanlder(void *handle, void *event_info, u8 event) static void dhd_natoe_ct_ioctl_handler(void *handle, void *event_info, uint8 event); #endif /* WL_NATOE */ +#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_STATIC_IN_DRIVER) +extern int dhd_static_buf_init(void); +extern void dhd_static_buf_exit(void); +#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_STATIC_IN_DRIVER */ #ifdef DHD_UPDATE_INTF_MAC static void dhd_ifupdate_event_handler(void *handle, void *event_info, u8 event); #endif /* DHD_UPDATE_INTF_MAC */ @@ -8686,7 +8690,7 @@ static void dhd_rollback_cpu_freq(dhd_info_t *dhd) static int dhd_ioctl_entry_wrapper(struct net_device *net, struct ifreq *ifr, #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)) - void __user *data, + void __user *data, #endif /* LINUX_VERSION_CODE > KERNEL_VERSION(5, 15, 0) */ int cmd) { @@ -9494,8 +9498,13 @@ dhd_open(struct net_device *net) if (dhd->rx_napi_netdev == NULL) { dhd->rx_napi_netdev = dhd->iflist[ifidx]->net; memset(&dhd->rx_napi_struct, 0, sizeof(struct napi_struct)); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) + netif_napi_add(dhd->rx_napi_netdev, &dhd->rx_napi_struct, + dhd_napi_poll); +#else netif_napi_add(dhd->rx_napi_netdev, &dhd->rx_napi_struct, dhd_napi_poll, dhd_napi_weight); +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)) */ DHD_INFO(("%s napi<%p> enabled ifp->net<%p,%s> dhd_napi_weight: %d\n", __FUNCTION__, &dhd->rx_napi_struct, net, net->name, dhd_napi_weight)); @@ -14651,10 +14660,10 @@ dhd_legacy_preinit_ioctls(dhd_pub_t *dhd) uint32 apsta = 0; int ap_mode = 1; #endif /* (defined(AP) || defined(WLP2P)) && !defined(SOFTAP_AND_GC) */ -#ifdef GET_CUSTOM_MAC_ENABLE struct ether_addr ea_addr; char hw_ether[62]; -#endif /* GET_CUSTOM_MAC_ENABLE */ + dhd_if_t *ifp = dhd->info->iflist[0]; + bool set_mac = FALSE; #ifdef OKC_SUPPORT uint32 okc = 1; #endif @@ -14846,19 +14855,26 @@ dhd_legacy_preinit_ioctls(dhd_pub_t *dhd) } #endif /* EVENT_LOG_RATE_HC */ -#ifdef GET_CUSTOM_MAC_ENABLE memset(hw_ether, 0, sizeof(hw_ether)); - ret = wifi_platform_get_mac_addr(dhd->info->adapter, hw_ether, 0); -#ifdef GET_CUSTOM_MAC_FROM_CONFIG - if (!memcmp(ðer_null, &dhd->conf->hw_ether, ETHER_ADDR_LEN)) { - ret = 0; - } else -#endif - if (!ret) { - memset(buf, 0, sizeof(buf)); + if (ifp->set_macaddress) { + memcpy(hw_ether, ifp->mac_addr, ETHER_ADDR_LEN); + set_mac = TRUE; + } +#ifdef GET_CUSTOM_MAC_ENABLE #ifdef GET_CUSTOM_MAC_FROM_CONFIG + else if (!memcmp(ðer_null, &dhd->conf->hw_ether, ETHER_ADDR_LEN)) { + set_mac = TRUE; memcpy(hw_ether, &dhd->conf->hw_ether, sizeof(dhd->conf->hw_ether)); + } #endif + else { + ret = wifi_platform_get_mac_addr(dhd->info->adapter, hw_ether, 0); + if (!ret) + set_mac = TRUE; + } +#endif /* GET_CUSTOM_MAC_ENABLE */ + if (set_mac) { + memset(buf, 0, sizeof(buf)); bcopy(hw_ether, ea_addr.octet, sizeof(struct ether_addr)); bcm_mkiovar("cur_etheraddr", (void *)&ea_addr, ETHER_ADDR_LEN, buf, sizeof(buf)); ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0); @@ -14874,7 +14890,9 @@ dhd_legacy_preinit_ioctls(dhd_pub_t *dhd) goto done; } } - } else { + } +#ifdef GET_CUSTOM_MAC_ENABLE + else { DHD_ERROR(("%s: can't get custom MAC address, ret=%d\n", __FUNCTION__, ret)); ret = BCME_NOTUP; goto done; @@ -15652,6 +15670,7 @@ dhd_legacy_preinit_ioctls(dhd_pub_t *dhd) // setbit(mask, WLC_E_TXFAIL); // terence 20181106: remove unnecessary event #endif setbit(mask, WLC_E_JOIN_START); + setbit(mask, WLC_E_OWE_INFO); // setbit(mask, WLC_E_SCAN_COMPLETE); // terence 20150628: remove redundant event #ifdef DHD_DEBUG setbit(mask, WLC_E_SCAN_CONFIRM_IND); @@ -17800,6 +17819,9 @@ dhd_module_cleanup(void) wifi_teardown_dt(); #endif #endif +#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_STATIC_IN_DRIVER) + dhd_static_buf_exit(); +#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_STATIC_IN_DRIVER */ printf("%s: Exit\n", __FUNCTION__); } @@ -17828,6 +17850,12 @@ _dhd_module_init(void) PRINTF_SYSTEM_TIME, __FUNCTION__, dhd_version); if (ANDROID_VERSION > 0) printf("ANDROID_VERSION = %d\n", ANDROID_VERSION); +#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_STATIC_IN_DRIVER) + err = dhd_static_buf_init(); + if (err) { + goto exit; + } +#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_STATIC_IN_DRIVER */ #ifdef CUSTOMER_HW_AMLOGIC #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)) if (wifi_setup_dt()) { @@ -17900,6 +17928,11 @@ _dhd_module_init(void) } } +#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_STATIC_IN_DRIVER) +exit: + if (err) + dhd_static_buf_exit(); +#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_STATIC_IN_DRIVER */ printf("%s: Exit err=%d\n", __FUNCTION__, err); return err; } @@ -21682,10 +21715,10 @@ dhd_os_check_wakelock_all(dhd_pub_t *pub) lock_active = (l1 || l2 || l3 || l4 || l5 || l6 || l7 || l8 || l9 || l10); /* Indicate to the Host to avoid going to suspend if internal locks are up */ + DHD_ERROR(("%s wakelock c-%d wl-%d wd-%d rx-%d " + "ctl-%d intr-%d scan-%d evt-%d, pm-%d, txfl-%d nan-%d\n", + __FUNCTION__, c, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10)); if (lock_active) { - DHD_ERROR(("%s wakelock c-%d wl-%d wd-%d rx-%d " - "ctl-%d intr-%d scan-%d evt-%d, pm-%d, txfl-%d nan-%d\n", - __FUNCTION__, c, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10)); return 1; } #elif defined(BCMSDIO) @@ -25504,7 +25537,9 @@ void custom_xps_map_clear(struct net_device *net) DHD_INFO(("%s : Entered.\n", __FUNCTION__)); rcu_read_lock(); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0)) + dev_maps = rcu_dereference(net->xps_maps[XPS_CPUS]); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) dev_maps = rcu_dereference(net->xps_cpus_map); #else dev_maps = rcu_dereference(net->xps_maps); @@ -25512,7 +25547,9 @@ void custom_xps_map_clear(struct net_device *net) rcu_read_unlock(); if (dev_maps) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0)) + RCU_INIT_POINTER(net->xps_maps[XPS_CPUS], NULL); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) RCU_INIT_POINTER(net->xps_cpus_map, NULL); #else RCU_INIT_POINTER(net->xps_maps, NULL); diff --git a/bcmdhd.101.10.361.x/dhd_linux_platdev.c b/bcmdhd.101.10.361.x/dhd_linux_platdev.c index afecfa9..8d65e48 100755 --- a/bcmdhd.101.10.361.x/dhd_linux_platdev.c +++ b/bcmdhd.101.10.361.x/dhd_linux_platdev.c @@ -128,7 +128,7 @@ wifi_adapter_info_t* dhd_wifi_platform_attach_adapter(uint32 bus_type, if ((adapter->bus_type == -1 || adapter->bus_type == bus_type) && (adapter->bus_num == -1 || adapter->bus_num == bus_num) && (adapter->slot_num == -1 || adapter->slot_num == slot_num) -#if defined(ENABLE_INSMOD_NO_FW_LOAD) +#if defined(ENABLE_INSMOD_NO_FW_LOAD) && !defined(ENABLE_INSMOD_NO_POWER_OFF) && (wifi_chk_adapter_status(adapter, status)) #endif ) { @@ -1024,7 +1024,7 @@ static int dhd_wifi_platform_load_usb(void) int i; #endif -#if !defined(DHD_PRELOAD) +#if !defined(DHD_PRELOAD) && !defined(ENABLE_INSMOD_NO_POWER_OFF) /* power down all adapters */ for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) { adapter = &dhd_wifi_platdata->adapters[i]; diff --git a/bcmdhd.101.10.361.x/dhd_msgbuf.c b/bcmdhd.101.10.361.x/dhd_msgbuf.c index 1b6b7ce..c9c70c2 100755 --- a/bcmdhd.101.10.361.x/dhd_msgbuf.c +++ b/bcmdhd.101.10.361.x/dhd_msgbuf.c @@ -7429,6 +7429,7 @@ dhd_prot_ioctcmplt_process(dhd_pub_t *dhd, void *msg) #ifdef REPORT_FATAL_TIMEOUTS uint16 dhd_xt_id; #endif + int ret = 0; /* Check for ioctl timeout induce flag, which is set by firing * dhd iovar to induce IOCTL timeout. If flag is set, @@ -7521,11 +7522,18 @@ dhd_prot_ioctcmplt_process(dhd_pub_t *dhd, void *msg) pkt_id, xt_id, prot->ioctl_status, prot->ioctl_resplen)); if (prot->ioctl_resplen > 0) { + uint16 copy_len = MIN(prot->ioctl_resplen, prot->retbuf.len); #ifndef IOCTLRESP_USE_CONSTMEM - bcopy(PKTDATA(dhd->osh, pkt), prot->retbuf.va, prot->ioctl_resplen); + ret = memcpy_s(prot->retbuf.va, prot->retbuf.len, PKTDATA(dhd->osh, pkt), copy_len); #else - bcopy(pkt, prot->retbuf.va, prot->ioctl_resplen); + ret = memcpy_s(prot->retbuf.va, prot->retbuf.len, pkt, copy_len); #endif /* !IOCTLRESP_USE_CONSTMEM */ + if (ret) { + DHD_ERROR(("memcpy failed:%d, destsz:%d, n:%u\n", + ret, prot->retbuf.len, copy_len)); + dhd_wakeup_ioctl_event(dhd, IOCTL_RETURN_ON_ERROR); + goto exit; + } } /* wake up any dhd_os_ioctl_resp_wait() */ diff --git a/bcmdhd.101.10.361.x/dhd_pcie.c b/bcmdhd.101.10.361.x/dhd_pcie.c index c5f687a..ee82a99 100755 --- a/bcmdhd.101.10.361.x/dhd_pcie.c +++ b/bcmdhd.101.10.361.x/dhd_pcie.c @@ -4378,11 +4378,7 @@ dhdpcie_download_nvram(struct dhd_bus *bus) } else { nvram_uefi_exists = TRUE; } -#ifdef DHD_LINUX_STD_FW_API - memblock_len = len; -#else memblock_len = MAX_NVRAMBUF_SIZE; -#endif /* DHD_LINUX_STD_FW_API */ DHD_ERROR(("%s: dhd_get_download_buffer len %d\n", __FUNCTION__, len)); diff --git a/bcmdhd.101.10.361.x/dhd_pcie_linux.c b/bcmdhd.101.10.361.x/dhd_pcie_linux.c index 0e681ad..071308b 100755 --- a/bcmdhd.101.10.361.x/dhd_pcie_linux.c +++ b/bcmdhd.101.10.361.x/dhd_pcie_linux.c @@ -889,6 +889,9 @@ static int dhdpcie_pci_resume_early(struct pci_dev *pdev) if (!bus) { return ret; } + if (bus->dhd->busstate == DHD_BUS_DOWN) { + return ret; + } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 9)) /* On fc30 (linux ver 5.0.9), @@ -2871,7 +2874,7 @@ void dhdpcie_oob_intr_set(dhd_bus_t *bus, bool enable) static irqreturn_t wlan_oob_irq_isr(int irq, void *data) { dhd_bus_t *bus = (dhd_bus_t *)data; - DHD_TRACE(("%s: IRQ ISR\n", __FUNCTION__)); + DHD_INTR(("%s: IRQ ISR\n", __FUNCTION__)); bus->last_oob_irq_isr_time = OSL_LOCALTIME_NS(); return IRQ_WAKE_THREAD; } @@ -2883,10 +2886,10 @@ static irqreturn_t wlan_oob_irq(int irq, void *data) bus = (dhd_bus_t *)data; dhdpcie_oob_intr_set(bus, FALSE); #ifdef DHD_USE_PCIE_OOB_THREADED_IRQ - DHD_TRACE(("%s: IRQ Thread\n", __FUNCTION__)); + DHD_INTR(("%s: IRQ Thread\n", __FUNCTION__)); bus->last_oob_irq_thr_time = OSL_LOCALTIME_NS(); #else - DHD_TRACE(("%s: IRQ ISR\n", __FUNCTION__)); + DHD_INTR(("%s: IRQ ISR\n", __FUNCTION__)); bus->last_oob_irq_isr_time = OSL_LOCALTIME_NS(); #endif /* DHD_USE_PCIE_OOB_THREADED_IRQ */ diff --git a/bcmdhd.101.10.361.x/dhd_sdio.c b/bcmdhd.101.10.361.x/dhd_sdio.c index bda7b2c..9fb997a 100755 --- a/bcmdhd.101.10.361.x/dhd_sdio.c +++ b/bcmdhd.101.10.361.x/dhd_sdio.c @@ -2686,14 +2686,14 @@ static int dhdsdio_txpkt_preprocess(dhd_bus_t *bus, void *pkt, int chan, int txs real_pad = pkt_len - act_len; if (PKTTAILROOM(osh, pkt) < real_pad) { - DHD_INFO(("%s : insufficient tailroom %d for %d real_pad\n", + DHD_INFO(("%s : insufficient tailroom %d for %d real_pad\n", __func__, (int)PKTTAILROOM(osh, pkt), real_pad)); if (PKTPADTAILROOM(osh, pkt, real_pad)) { DHD_ERROR(("CHK1: padding error size %d\n", real_pad)); } else frame = (uint8 *)PKTDATA(osh, pkt); } - } else + } else #endif { swhdr_offset += SDPCM_HWEXT_LEN; @@ -6553,7 +6553,7 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) /* Check window for sanity */ if ((uint8)(txmax - bus->tx_seq) > 0x70) { - DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", + DHD_INFO(("%s: got unlikely tx max %d with tx_seq %d\n", __FUNCTION__, txmax, bus->tx_seq)); txmax = bus->tx_max; } @@ -7159,7 +7159,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) txmax = bus->tx_seq + 2; } else { #endif /* BCMSPI */ - DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", + DHD_INFO(("%s: got unlikely tx max %d with tx_seq %d\n", __FUNCTION__, txmax, bus->tx_seq)); txmax = bus->tx_max; #ifdef BCMSPI @@ -7327,7 +7327,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) /* Check window for sanity */ if ((uint8)(txmax - bus->tx_seq) > 0x70) { - DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", + DHD_INFO(("%s: got unlikely tx max %d with tx_seq %d\n", __FUNCTION__, txmax, bus->tx_seq)); txmax = bus->tx_max; } @@ -9009,11 +9009,6 @@ dhd_dump_cis(uint fn, uint8 *cis) DHD_INFO(("Function %d CIS:\n", fn)); for (tdata = byte = 0; byte < SBSDIO_CIS_SIZE_LIMIT; byte++) { - if ((byte % 16) == 0) - DHD_INFO((" ")); - DHD_INFO(("%02x ", cis[byte])); - if ((byte % 16) == 15) - DHD_INFO(("\n")); if (!tdata--) { tag = cis[byte]; if (tag == 0xff) @@ -9022,12 +9017,9 @@ dhd_dump_cis(uint fn, uint8 *cis) tdata = 0; else if ((byte + 1) < SBSDIO_CIS_SIZE_LIMIT) tdata = cis[byte + 1] + 1; - else - DHD_INFO(("]")); } } - if ((byte % 16) != 15) - DHD_INFO(("\n")); + prhex(NULL, (const u8 *) cis, byte+1); } #endif /* DHD_DEBUG */ @@ -9253,10 +9245,15 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, /* if firmware path present try to download and bring up bus */ bus->dhd->hang_report = TRUE; -#if 0 // terence 20150325: fix for WPA/WPA2 4-way handshake fail in hostapd + +#if defined(BCMDHD_MODULAR) && defined(INSMOD_FW_LOAD) + if (1) +#else #if defined(LINUX) || defined(linux) - if (dhd_download_fw_on_driverload) { + if (!dhd_conf_legacy_otp_chip(bus->dhd)) #endif /* LINUX || linux */ +#endif + { if ((ret = dhd_bus_start(bus->dhd)) != 0) { DHD_ERROR(("%s: dhd_bus_start failed\n", __FUNCTION__)); #if !defined(OEM_ANDROID) @@ -9275,7 +9272,6 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, bus->dhd->mac.octet[2] = 0x4C; } #endif /* LINUX || linux */ -#endif #if defined(BT_OVER_SDIO) /* At this point Regulators are turned on and iconditionaly sdio bus is started * based upon dhd_download_fw_on_driverload check, so @@ -10684,11 +10680,7 @@ dhdsdio_download_nvram(struct dhd_bus *bus) if (bcmerror != BCME_OK) goto err; -#ifdef DHD_LINUX_STD_FW_API memblock_len = MAX_NVRAMBUF_SIZE; -#else - memblock_len = MAX_NVRAMBUF_SIZE; -#endif /* DHD_LINUX_STD_FW_API */ if (len > 0 && len < MAX_NVRAMBUF_SIZE) { bufp = (char *)memblock; diff --git a/bcmdhd.101.10.361.x/dhd_static_buf.c b/bcmdhd.101.10.361.x/dhd_static_buf.c index 9bc63bf..b565b90 100755 --- a/bcmdhd.101.10.361.x/dhd_static_buf.c +++ b/bcmdhd.101.10.361.x/dhd_static_buf.c @@ -13,7 +13,7 @@ #include #include -#define DHD_STATIC_VERSION_STR "101.10.361.28 (wlan=r892223-20221018-1)" +#define DHD_STATIC_VERSION_STR "101.10.361.31 (wlan=r892223-20230427-1)" #define STATIC_ERROR_LEVEL BIT(0) #define STATIC_TRACE_LEVEL BIT(1) #define STATIC_MSG_LEVEL BIT(0) @@ -38,17 +38,16 @@ do { \ } \ } while (0) -#ifdef DHD_STATIC_IN_DRIVER -#if ANDROID_VERSION > 0 -#define CONFIG_BCMDHD_VTS { : = y} -#define CONFIG_BCMDHD_DEBUG { : = y} -#endif -#else +#ifndef DHD_STATIC_IN_DRIVER +#ifndef BCMSDIO #define BCMSDIO +#endif +#ifndef BCMPCIE #define BCMPCIE -//#define BCMDBUS -#define CONFIG_BCMDHD_VTS { : = y} -#define CONFIG_BCMDHD_DEBUG { : = y} +#endif +#ifndef BCMDBUS +#define BCMDBUS +#endif #define DHD_USE_STATIC_MEMDUMP { : = y} //#define BCMDHD_UNUSE_MEM #endif @@ -75,9 +74,9 @@ enum dhd_prealloc_index { DHD_PREALLOC_IF_FLOW_LKUP = 9, #endif /* BCMPCIE */ DHD_PREALLOC_MEMDUMP_BUF = 10, -#if defined(CONFIG_BCMDHD_VTS) || defined(CONFIG_BCMDHD_DEBUG) +#if defined(DHD_USE_STATIC_MEMDUMP) || defined(BCMDBUS) DHD_PREALLOC_MEMDUMP_RAM = 11, -#endif /* CONFIG_BCMDHD_VTS | CONFIG_BCMDHD_DEBUG */ +#endif /* DHD_USE_STATIC_MEMDUMP | BCMDBUS */ #if defined(BCMSDIO) || defined(BCMDBUS) DHD_PREALLOC_DHD_WLFC_HANGER = 12, #endif /* BCMSDIO | BCMDBUS */ @@ -112,10 +111,8 @@ enum dhd_prealloc_index { #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 (43 * 1024) -#if defined(CONFIG_BCMDHD_VTS) || defined(CONFIG_BCMDHD_DEBUG) +#define DHD_PREALLOC_DHD_INFO_SIZE (44 * 1024) #define DHD_PREALLOC_MEMDUMP_RAM_SIZE (1290 * 1024) -#endif /* CONFIG_BCMDHD_VTS | CONFIG_BCMDHD_DEBUG */ #define DHD_PREALLOC_DHD_WLFC_HANGER_SIZE (73 * 1024) #ifdef DHD_USE_STATIC_MEMDUMP #define DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE \ @@ -268,7 +265,7 @@ void *bcmdhd_mem_prealloc(int section, unsigned long size) return wlan_static_if_flow_lkup[index]; } #endif /* BCMPCIE */ -#if defined(CONFIG_BCMDHD_VTS) || defined(CONFIG_BCMDHD_DEBUG) +#if defined(DHD_USE_STATIC_MEMDUMP) || defined(BCMDBUS) if (section == DHD_PREALLOC_MEMDUMP_RAM) { if (size > DHD_PREALLOC_MEMDUMP_RAM_SIZE) { DHD_STATIC_ERROR("request DHD_PREALLOC_MEMDUMP_RAM(%lu) > %d\n", @@ -277,7 +274,7 @@ void *bcmdhd_mem_prealloc(int section, unsigned long size) } return wlan_static_dhd_memdump_ram_buf[index]; } -#endif /* CONFIG_BCMDHD_VTS | CONFIG_BCMDHD_DEBUG */ +#endif /* DHD_USE_STATIC_MEMDUMP | BCMDBUS */ #if defined(BCMSDIO) || defined(BCMDBUS) if (section == DHD_PREALLOC_DHD_WLFC_HANGER) { if (size > DHD_PREALLOC_DHD_WLFC_HANGER_SIZE) { @@ -384,9 +381,9 @@ dhd_deinit_wlan_mem(int index) #ifdef BCMPCIE kfree(wlan_static_if_flow_lkup[index]); #endif /* BCMPCIE */ -#if defined(CONFIG_BCMDHD_VTS) || defined(CONFIG_BCMDHD_DEBUG) +#if defined(DHD_USE_STATIC_MEMDUMP) || defined(BCMDBUS) kfree(wlan_static_dhd_memdump_ram_buf[index]); -#endif /* CONFIG_BCMDHD_VTS | CONFIG_BCMDHD_DEBUG */ +#endif /* DHD_USE_STATIC_MEMDUMP | BCMDBUS */ #if defined(BCMSDIO) || defined(BCMDBUS) kfree(wlan_static_dhd_wlfc_hanger_buf[index]); #endif /* BCMSDIO | BCMDBUS */ @@ -517,14 +514,14 @@ dhd_init_wlan_mem(int index, unsigned int buf_level) #endif /* BCMPCIE */ } -#if defined(CONFIG_BCMDHD_VTS) || defined(CONFIG_BCMDHD_DEBUG) +#if defined(DHD_USE_STATIC_MEMDUMP) || defined(BCMDBUS) wlan_static_dhd_memdump_ram_buf[index] = kmalloc(DHD_PREALLOC_MEMDUMP_RAM_SIZE, GFP_KERNEL); if (!wlan_static_dhd_memdump_ram_buf[index]) goto err_mem_alloc; size += DHD_PREALLOC_MEMDUMP_RAM_SIZE; DHD_STATIC_TRACE("section %d, size=%d\n", DHD_PREALLOC_MEMDUMP_RAM, DHD_PREALLOC_MEMDUMP_RAM_SIZE); -#endif /* CONFIG_BCMDHD_VTS | CONFIG_BCMDHD_DEBUG */ +#endif /* DHD_USE_STATIC_MEMDUMP | BCMDBUS */ if (buf_level > 0) { #if defined(BCMSDIO) || defined(BCMDBUS) @@ -625,10 +622,12 @@ bcmdhd_init_wlan_mem(unsigned int all_buf) break; } +#ifndef DHD_STATIC_IN_DRIVER if (ret) { for (i = 0; i < MAX_NUM_ADAPTERS; i++) dhd_deinit_wlan_mem(i); } +#endif return ret; } diff --git a/bcmdhd.101.10.361.x/include/bcmevent.h b/bcmdhd.101.10.361.x/include/bcmevent.h index a2fbbd6..6b70c0f 100755 --- a/bcmdhd.101.10.361.x/include/bcmevent.h +++ b/bcmdhd.101.10.361.x/include/bcmevent.h @@ -314,9 +314,21 @@ typedef union bcm_event_msg_u { #define WLC_E_PFN_SCAN_ALLGONE_EXT 193 /* last found PFN network gets lost. */ #define WLC_E_AUTH_START 194 /* notify upper layer to start auth */ #define WLC_E_TWT 195 /* TWT event */ -#define WLC_E_LAST 196 /* highest val + 1 for range checking */ -#if (WLC_E_LAST > 196) -#error "WLC_E_LAST: Invalid value for last event; must be <= 196." +#define WLC_E_AMT 196 /* Address Management Table (AMT) */ +#define WLC_E_ROAM_SCAN_RESULT 197 /* roam/reassoc scan result event */ + +#define WLC_E_MSCS 200 /* MSCS success/failure events */ +#define WLC_E_RXDMA_RECOVERY_ATMPT 201 /* RXDMA Recovery Attempted Event */ +#define WLC_E_PFN_PARTIAL_RESULT 202 +#define WLC_E_MLO_LINK_INFO 203 /* 11be MLO link information */ +#define WLC_E_C2C 204 /* Client to client (C2C) for 6GHz TX */ +#define WLC_E_BCN_TSF 205 /* Report Beacon TSF */ +#define WLC_E_OWE_INFO 206 /* OWE Information */ +#define WLC_E_ULMU_DISABLED_REASON_UPD 207 /* OMI ULMU disable reason code update */ +#define WLC_E_AMSDU_RX_WAKEUP 208 /* When amsdu deagg SM is stuck in D3 condition */ +#define WLC_E_LAST 209 /* highest val + 1 for range checking */ +#if (WLC_E_LAST > 209) +#error "WLC_E_LAST: Invalid value for last event; must be <= 209." #endif /* WLC_E_LAST */ /* define an API for getting the string name of an event */ diff --git a/bcmdhd.101.10.361.x/include/epivers.h b/bcmdhd.101.10.361.x/include/epivers.h index d09f7e2..2061770 100755 --- a/bcmdhd.101.10.361.x/include/epivers.h +++ b/bcmdhd.101.10.361.x/include/epivers.h @@ -45,7 +45,7 @@ #elif (defined (BCMDBG_ASSERT) && !defined (BCMDBG_ASSERT_DISABLED)) #define EPI_VERSION_STR "101.10.361 (wlan=r892223 ASSRT)" #else -#define EPI_VERSION_STR "101.10.361.28 (wlan=r892223-20221202-3)" +#define EPI_VERSION_STR "101.10.361.32 (wlan=r892223-20230508-1)" #endif /* BCMINTERNAL */ #endif /* _epivers_h_ */ diff --git a/bcmdhd.101.10.361.x/include/wlioctl.h b/bcmdhd.101.10.361.x/include/wlioctl.h index 72c9d9f..18263e6 100755 --- a/bcmdhd.101.10.361.x/include/wlioctl.h +++ b/bcmdhd.101.10.361.x/include/wlioctl.h @@ -23538,6 +23538,18 @@ typedef struct wl_filter_ie_iov_v1 { uint8 tlvs[]; /* variable data (zero in for list ,clearall) */ } wl_filter_ie_iov_v1_t; +#define WL_ASSOC_RESP_PARAMS_V1 (1u) +typedef struct wl_assoc_resp_params_v1 { + uint16 version; /* Structure version */ + uint16 len; /* Total length of the structure */ + uint16 fixed_length; /* Total length of fixed fields */ + uint8 mac_addr[ETHER_ADDR_LEN]; /* peer MAC address */ + uint8 resp_ie_len; /* Assoc_resp IE's length */ + uint8 pad; /* Pad for alignment */ + uint16 status; /* AREQ status code from Host */ + uint8 ies[]; /* Variable data (resp_ies) */ +} wl_assoc_resp_params_v1_t; + /* Event aggregation config */ #define EVENT_AGGR_CFG_VERSION 1 #define EVENT_AGGR_DISABLED 0x0 diff --git a/bcmdhd.101.10.361.x/wl_android.c b/bcmdhd.101.10.361.x/wl_android.c index ec37154..b108fca 100755 --- a/bcmdhd.101.10.361.x/wl_android.c +++ b/bcmdhd.101.10.361.x/wl_android.c @@ -4945,22 +4945,19 @@ int wl_android_wifi_on(struct net_device *dev) #endif /* BCMSDIO */ ret = dhd_dev_init_ioctl(dev); if (ret < 0) { - goto retry_bus; + goto retry_power; } #endif /* BCMSDIO || BCMDBUS */ if (ret == 0) { break; } -#if defined(BCMSDIO) || defined(BCMDBUS) -retry_bus: -#ifdef BCMSDIO - dhd_net_bus_suspend(dev); -#endif /* BCMSDIO */ -#endif /* BCMSDIO || BCMDBUS */ retry_power: ANDROID_ERROR(("failed to power up wifi chip, retry again (%d left) **\n\n", retry)); dhd_net_bus_devreset(dev, TRUE); +#ifdef BCMSDIO + dhd_net_bus_suspend(dev); +#endif /* BCMSDIO */ dhd_net_wifi_platform_set_power(dev, FALSE, WIFI_TURNOFF_DELAY); #ifdef WBRC /* Inform BT reset which will internally wait till BT reset is done */ @@ -6830,6 +6827,14 @@ wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str, goto done2; } + chosen = wl_ext_autochannel(dev, ACS_DRV_BIT, band); + channel = wf_chspec_ctlchan(chosen); + if (channel) { + acs_band = CHSPEC_BAND(channel); + goto done2; + } else + goto done; + /* If AP is started on wlan0 iface, * do not issue any iovar to fw and choose default ACS channel for softap */ @@ -6840,14 +6845,6 @@ wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str, } } - chosen = wl_ext_autochannel(dev, ACS_DRV_BIT, band); - channel = wf_chspec_ctlchan(chosen); - if (channel) { - acs_band = CHSPEC_BAND(channel); - goto done2; - } else - goto done; - ret = wldev_ioctl_get(dev, WLC_GET_SPECT_MANAGMENT, &spect, sizeof(spect)); if (ret) { ANDROID_ERROR(("ACS: error getting the spect, ret=%d\n", ret)); @@ -13064,7 +13061,7 @@ int wl_android_init(void) #ifdef ENABLE_INSMOD_NO_POWER_OFF dhd_download_fw_on_driverload = TRUE; -#elif defined(ENABLE_INSMOD_NO_FW_LOAD) || defined(BUS_POWER_RESTORE) +#elif defined(ENABLE_INSMOD_NO_FW_LOAD) dhd_download_fw_on_driverload = FALSE; #endif /* ENABLE_INSMOD_NO_FW_LOAD */ if (!iface_name[0]) { diff --git a/bcmdhd.101.10.361.x/wl_android_ext.c b/bcmdhd.101.10.361.x/wl_android_ext.c index 3a4a553..54d8546 100755 --- a/bcmdhd.101.10.361.x/wl_android_ext.c +++ b/bcmdhd.101.10.361.x/wl_android_ext.c @@ -185,6 +185,7 @@ const auth_name_map_t auth_name_map[] = { {WL_AUTH_OPEN_SYSTEM, 0x20|WPA2_AUTH_PSK_SHA256|WPA2_AUTH_PSK, "wpa3/psk/sha256"}, {WL_AUTH_SAE_KEY, 0x20|WPA2_AUTH_PSK_SHA256|WPA2_AUTH_PSK, "wpa3sae/psk/sha256"}, {WL_AUTH_OPEN_SYSTEM, WPA3_AUTH_OWE, "owe"}, + {WL_AUTH_OPEN_SYSTEM, BRCM_AUTH_DPT, "owe"}, }; typedef struct wsec_name_map_t { @@ -2143,7 +2144,7 @@ wl_ext_recv_probresp(struct net_device *dev, char *data, char *command, /* enable: 1. dhd_priv wl pkt_filter_add 150 0 0 0 0xFF 0x50 - 2. dhd_priv wl pkt_filter_enable 150 1 + 2. dhd_priv wl pkt_filter_enable 150 1 3. dhd_priv wl mpc 0 4. dhd_priv wl 108 1 disable: @@ -2454,27 +2455,43 @@ wl_ext_wowl_wakeind(struct net_device *dev, char *data, char *command, typedef struct notify_payload { int index; int len; - char payload[128]; + char payload[256]; } 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]; + s8 *iovar_buf = NULL; notify_payload_t notify, *pnotify = NULL; - int i, ret = 0, bytes_written = 0; - char frame_str[WLC_IOCTL_SMLEN+3]; + int i, ret = 0, bytes_written = 0, len; + char *frame_str = NULL; if (data) { + iovar_buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL); + if (iovar_buf == NULL) { + AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n", WLC_IOCTL_MEDLEN); + goto exit; + } + memset(iovar_buf, 0, WLC_IOCTL_MEDLEN); + frame_str = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL); + if (frame_str == NULL) { + AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n", WLC_IOCTL_MEDLEN); + goto exit; + } + memset(frame_str, 0, WLC_IOCTL_MEDLEN); 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)) { + len = strlen(frame_str); + if (len > sizeof(notify.payload)) { + AEXT_ERROR(dev->name, "playload size %d > %d\n", len, sizeof(notify.payload)); + goto exit; + } + if (len) { notify.len = wl_pattern_atoh(frame_str, notify.payload); if (notify.len == -1) { AEXT_ERROR(dev->name, "rejecting pattern=%s\n", frame_str); @@ -2506,6 +2523,10 @@ wl_ext_gpio_notify(struct net_device *dev, char *data, char *command, } exit: + if (iovar_buf) + kfree(iovar_buf); + if (frame_str) + kfree(frame_str); return ret; } #endif /* WL_GPIO_NOTIFY */ @@ -2827,7 +2848,7 @@ wl_ext_conf_iovar(struct net_device *dev, char *command, int total_len) goto exit; strncpy(name, pch, sizeof(name)); - + data = bcmstrtok(&pick_tmp, "", 0); // pick data if (!strcmp(name, "pm")) { diff --git a/bcmdhd.101.10.361.x/wl_cfg80211.c b/bcmdhd.101.10.361.x/wl_cfg80211.c index 030fa44..f623aed 100755 --- a/bcmdhd.101.10.361.x/wl_cfg80211.c +++ b/bcmdhd.101.10.361.x/wl_cfg80211.c @@ -475,23 +475,23 @@ static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm); #endif /* WL_CFG80211_P2P_DEV_IF */ static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev, -#if defined(CFG80211_BKPORT_MLO) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(CFG80211_BKPORT_MLO) int link_id, #endif u8 key_idx, bool unicast, bool multicast); static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, -#if defined(CFG80211_BKPORT_MLO) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(CFG80211_BKPORT_MLO) int link_id, #endif u8 key_idx, bool pairwise, const u8 *mac_addr, struct key_params *params); static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev, -#if defined(CFG80211_BKPORT_MLO) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(CFG80211_BKPORT_MLO) int link_id, #endif u8 key_idx, bool pairwise, const u8 *mac_addr); static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev, -#if defined(CFG80211_BKPORT_MLO) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(CFG80211_BKPORT_MLO) int link_id, #endif u8 key_idx, bool pairwise, const u8 *mac_addr, @@ -499,7 +499,7 @@ static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev, struct key_params *params)); static s32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy, struct net_device *dev, -#if defined(CFG80211_BKPORT_MLO) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(CFG80211_BKPORT_MLO) int link_id, #endif u8 key_idx); @@ -572,6 +572,10 @@ static int wl_cfg80211_set_pmk(struct wiphy *wiphy, struct net_device *dev, static int wl_cfg80211_del_pmk(struct wiphy *wiphy, struct net_device *dev, const u8 *aa); #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)) +static int wl_cfg80211_update_owe_info(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_update_owe_info *oweinfo); +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) */ /* * event & event Q handlers for cfg80211 interfaces @@ -6087,6 +6091,47 @@ wl_config_assoc_params(struct bcm_cfg80211 *cfg, struct net_device *dev, return ret; } +static s32 +wl_ext_get_scan_rssi(struct bcm_cfg80211 *cfg, u8 *bssid) +{ + wl_scan_results_t *bss_list; + wl_bss_info_t *bi = NULL; + s32 i, rssi = 0; + + mutex_lock(&cfg->scan_sync); + bss_list = cfg->bss_list; + bi = next_bss(bss_list, bi); + for_each_bss(bss_list, bi, i) { + if (!memcmp(&bi->BSSID, bssid, ETHER_ADDR_LEN)) + rssi = dtoh32(bi->RSSI); + } + mutex_unlock(&cfg->scan_sync); + + return rssi; +} + +#ifdef CONNECT_INFO_WAR +static chanspec_t +wl_ext_get_scan_chanspec(struct bcm_cfg80211 *cfg, u8 *bssid) +{ + wl_scan_results_t *bss_list; + wl_bss_info_t *bi = NULL; + chanspec_t chanspec = 0; + s32 i; + + mutex_lock(&cfg->scan_sync); + bss_list = cfg->bss_list; + bi = next_bss(bss_list, bi); + for_each_bss(bss_list, bi, i) { + if (!memcmp(&bi->BSSID, bssid, ETHER_ADDR_LEN)) + chanspec = wl_chspec_driver_to_host(bi->chanspec); + } + mutex_unlock(&cfg->scan_sync); + + return chanspec; +} +#endif /* CONNECT_INFO_WAR */ + static s32 wl_handle_assoc_hints(struct bcm_cfg80211 *cfg, struct net_device *dev, struct cfg80211_connect_params *sme, wlcfg_assoc_info_t *info) @@ -6094,7 +6139,10 @@ wl_handle_assoc_hints(struct bcm_cfg80211 *cfg, struct net_device *dev, #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) bool skip_hints = false; #endif /* KERNEL >= 3.15 */ - chanspec_t chspec; +#ifdef CONNECT_INFO_WAR + chanspec_t scan_chspec; +#endif /* CONNECT_INFO_WAR */ + chanspec_t chspec = 0; if (!sme || !info) { WL_ERR(("wrong args\n")); @@ -6119,8 +6167,18 @@ wl_handle_assoc_hints(struct bcm_cfg80211 *cfg, struct net_device *dev, /* Use user space requested BSSID and channel */ info->targeted_join = true; (void)memcpy_s(info->bssid, ETH_ALEN, sme->bssid, ETH_ALEN); - if (sme->channel && ((chspec = - wl_freq_to_chanspec(sme->channel->center_freq)) != INVCHANSPEC)) { + if (sme->channel) { + chspec = wl_freq_to_chanspec(sme->channel->center_freq); + } +#ifdef CONNECT_INFO_WAR + scan_chspec = wl_ext_get_scan_chanspec(cfg, info->bssid); + if (scan_chspec && (scan_chspec != chspec)) { + WL_MSG(dev->name, "replace chspec 0x%x to previous scan chanspec 0x%x\n", + chspec, scan_chspec); + chspec = scan_chspec; + } +#endif /* CONNECT_INFO_WAR */ + if (chspec && (chspec != INVCHANSPEC)) { info->chan_cnt = 1; info->chanspecs[0] = chspec; /* Skip p2p connection on 6G */ @@ -6192,7 +6250,11 @@ wl_sync_fw_assoc_states(struct bcm_cfg80211 *cfg, s32 err = BCME_OK; u8 bssid[ETH_ALEN]; - if (wl_get_drv_status(cfg, CONNECTED, dev) && wl_reassoc_support) { + if (wl_get_drv_status(cfg, CONNECTED, dev) && wl_reassoc_support +#ifdef WL_EXT_IAPSTA + && wl_ext_sta_connected(dev) +#endif /* WL_EXT_IAPSTA */ + ) { /* ROAM case */ info->reassoc = true; } else { @@ -6269,25 +6331,6 @@ wl_pkt_mon_start(struct bcm_cfg80211 *cfg, struct net_device *dev) } #endif /* DBG_PKT_MON && BCMDONGLEHOST */ -static s32 -wl_ext_get_rssi(struct bcm_cfg80211 *cfg, u8 *bssid) -{ - wl_scan_results_t *bss_list; - wl_bss_info_t *bi = NULL; - s32 i, rssi = 0; - - mutex_lock(&cfg->scan_sync); - bss_list = cfg->bss_list; - bi = next_bss(bss_list, bi); - for_each_bss(bss_list, bi, i) { - if (!memcmp(&bi->BSSID, bssid, ETHER_ADDR_LEN)) - rssi = dtoh32(bi->RSSI); - } - mutex_unlock(&cfg->scan_sync); - - return rssi; -} - void wl_conn_debug_info(struct bcm_cfg80211 *cfg, struct net_device *dev, wlcfg_assoc_info_t *info) { @@ -6304,7 +6347,7 @@ wl_conn_debug_info(struct bcm_cfg80211 *cfg, struct net_device *dev, wlcfg_assoc return; } - target_rssi = wl_ext_get_rssi(cfg, info->bssid); + target_rssi = wl_ext_get_scan_rssi(cfg, info->bssid); wl_ext_get_sec(dev, 0, sec_info, sizeof(sec_info), TRUE); if (info->reassoc) { memset(&scb_val, 0, sizeof(scb_val_t)); @@ -6451,6 +6494,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, s32 err = BCME_OK; struct bcm_cfg80211 *cfg = wiphy_priv(wiphy); wlcfg_assoc_info_t assoc_info; + chanspec_t scan_chspec = 1; WL_DBG(("Enter len=%zu\n", sme->ie_len)); RETURN_EIO_IF_NOT_UP(cfg); @@ -6496,10 +6540,20 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, goto fail; } - err = wl_get_assoc_channels(cfg, dev, &assoc_info); - if (unlikely(err)) { - WL_ERR(("get assoc channels failed\n")); - goto fail; +#ifdef CONNECT_INFO_WAR + if (!ETHER_ISBCAST(assoc_info.bssid)) { + scan_chspec = wl_ext_get_scan_chanspec(cfg, assoc_info.bssid); + } + if(!scan_chspec) + WL_MSG(dev->name, "BSSID %pM not in previous scan results\n", + assoc_info.bssid); +#endif /* CONNECT_INFO_WAR */ + if (scan_chspec) { + err = wl_get_assoc_channels(cfg, dev, &assoc_info); + if (unlikely(err)) { + WL_ERR(("get assoc channels failed\n")); + goto fail; + } } err = wl_config_assoc_ies(cfg, dev, sme, &assoc_info); @@ -6803,7 +6857,7 @@ wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm) static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev, -#if defined(CFG80211_BKPORT_MLO) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(CFG80211_BKPORT_MLO) int link_id, #endif u8 key_idx, bool unicast, bool multicast) @@ -7017,7 +7071,7 @@ wl_cfg80211_block_arp(struct net_device *dev, int enable) static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, -#if defined(CFG80211_BKPORT_MLO) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(CFG80211_BKPORT_MLO) int link_id, #endif u8 key_idx, bool pairwise, const u8 *mac_addr, @@ -7219,7 +7273,7 @@ exit: static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev, -#if defined(CFG80211_BKPORT_MLO) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(CFG80211_BKPORT_MLO) int link_id, #endif u8 key_idx, bool pairwise, const u8 *mac_addr) @@ -7285,7 +7339,7 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev, /* NOTE : this function cannot work as is and is never called */ static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev, -#if defined(CFG80211_BKPORT_MLO) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(CFG80211_BKPORT_MLO) int link_id, #endif u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie, @@ -7363,7 +7417,7 @@ wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev, static s32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy, struct net_device *dev, -#if defined(CFG80211_BKPORT_MLO) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) || defined(CFG80211_BKPORT_MLO) int link_id, #endif u8 key_idx) @@ -7421,7 +7475,7 @@ wl_cfg80211_get_rssi(struct net_device *dev, struct bcm_cfg80211 *cfg, s32 *rssi /* Query RSSI sum across antennas */ bzero(&rssi_ant_mimo, sizeof(rssi_ant_mimo)); err = wl_get_rssi_per_ant(dev, dev->name, NULL, &rssi_ant_mimo); - if (err) { + if (err && err != BCME_UNSUPPORTED) { WL_ERR(("Could not get rssi sum (%d)\n", err)); /* set rssi to zero and do not return error, * because iovar phy_rssi_ant could return BCME_UNSUPPORTED @@ -7429,9 +7483,10 @@ wl_cfg80211_get_rssi(struct net_device *dev, struct bcm_cfg80211 *cfg, s32 *rssi */ err = BCME_OK; } else { - cfg->rssi_sum_report = TRUE; if ((*rssi = rssi_ant_mimo.rssi_sum) >= 0) { *rssi = 0; + } else { + cfg->rssi_sum_report = TRUE; } } #endif /* SUPPORT_RSSI_SUM_REPORT */ @@ -7825,9 +7880,9 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, (void)memset_s(&rssi_ant_mimo, sizeof(rssi_ant_mimo), 0, sizeof(rssi_ant_mimo)); err = wl_get_rssi_per_ant(dev, dev->name, NULL, &rssi_ant_mimo); - if (err) { + if (err && err != BCME_UNSUPPORTED) { WL_ERR(("Could not get rssi sum (%d)\n", err)); - } else { + } else if (!err) { chains = 0; for (cnt = 0; cnt < rssi_ant_mimo.count; cnt++) { sinfo->chain_signal[cnt] = rssi_ant_mimo.rssi_ant[cnt]; @@ -10234,7 +10289,7 @@ exit: return err; } -static int wl_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev, +static int wl_cfg80211_dump_survey_ap(struct wiphy *wiphy, struct net_device *ndev, int idx, struct survey_info *info) { struct bcm_cfg80211 *cfg = wiphy_priv(wiphy); @@ -10350,7 +10405,82 @@ exit: } #endif /* WL_SUPPORT_ACS */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) +/** + * A connected STA typically cannot afford to go off-channel to collect + * all form of stats like an AP sounding the air before going up, hence + * a dedicated interface. And NL only uses that for the noise field of + * wpa_cli's signal_poll. + */ +static int wl_cfg80211_dump_survey_sta(struct wiphy *wiphy, struct net_device *ndev, + int idx, struct survey_info *info) +{ + struct bcm_cfg80211 *cfg = wiphy_priv(wiphy); + u16 wl_iftype = 0; + u16 wl_mode = 0; + chanspec_t *chanspec = NULL; + s32 freq = 0; + struct ieee80211_channel *channel = NULL; + int err, noise, retry; + + if (cfg80211_to_wl_iftype(ndev->ieee80211_ptr->iftype, &wl_iftype, &wl_mode) < 0) { + return -ENOENT; + } + + if (wl_iftype != WL_IF_TYPE_STA || + !wl_get_drv_status(cfg, CONNECTED, ndev) || + idx != 0) { + return -ENOENT; + } + chanspec = (chanspec_t *)wl_read_prof(cfg, ndev, WL_PROF_CHAN); + if (chanspec && (*chanspec) && (*chanspec != INVCHANNEL)) { + freq = wl_channel_to_frequency(wf_chspec_ctlchan(*chanspec), CHSPEC_BAND(*chanspec)); + channel = ieee80211_get_channel(wiphy, freq); + } else { + return -ENOENT; + } + + /* Get noise value */ + retry = IOCTL_RETRY_COUNT; + while (retry--) { + noise = 0; + err = wldev_ioctl_get(ndev, WLC_GET_PHY_NOISE, &noise, + sizeof(noise)); + if (err >= 0) { + break; + } + WL_DBG(("attempt = %d, err = %d, \n", + (IOCTL_RETRY_COUNT - retry), err)); + } + + if (retry <= 0) { + WL_ERR(("Get Phy Noise failed, error = %d\n", err)); + noise = CHAN_NOISE_DUMMY; + } + + memset_s(info, sizeof(struct survey_info), 0, sizeof(struct survey_info)); + info->channel = channel; + info->noise = noise; + info->filled = SURVEY_INFO_NOISE_DBM ; + + return 0; +} + +static int wl_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev, + int idx, struct survey_info *info) +{ +#ifdef WL_SUPPORT_ACS + struct bcm_cfg80211 *cfg = wiphy_priv(wiphy); + dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub); + if ((dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) { + return wl_cfg80211_dump_survey_ap(wiphy, ndev, idx, info); + } else +#endif /* WL_SUPPORT_ACS */ + { + return wl_cfg80211_dump_survey_sta(wiphy, ndev, idx, info); + } +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) static int wl_cfg80211_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev, #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 2) || defined(CFG80211_BKPORT_MLO) @@ -10445,9 +10575,7 @@ static struct cfg80211_ops wl_cfg80211_ops = { .tdls_mgmt = wl_cfg80211_tdls_mgmt, .tdls_oper = wl_cfg80211_tdls_oper, #endif /* LINUX_VERSION > VERSION(3, 2, 0) || WL_COMPAT_WIRELESS */ -#ifdef WL_SUPPORT_ACS .dump_survey = wl_cfg80211_dump_survey, -#endif /* WL_SUPPORT_ACS */ #ifdef WL_CFG80211_ACL .set_mac_acl = wl_cfg80211_set_mac_acl, #endif /* WL_CFG80211_ACL */ @@ -10475,7 +10603,10 @@ static struct cfg80211_ops wl_cfg80211_ops = { .update_ft_ies = wl_cfg80211_update_ft_ies, #endif /* WLFBT */ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION (3, 6, 0) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)) + .update_owe_info = wl_cfg80211_update_owe_info, +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0) .get_channel = wl_cfg80211_get_channel, #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION (3, 6, 0) */ }; @@ -13317,7 +13448,7 @@ wl_check_pmstatus(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, /* Query RSSI sum across antennas */ memset(&rssi_ant_mimo, 0, sizeof(rssi_ant_mimo)); err = wl_get_rssi_per_ant(ndev, ndev->name, NULL, &rssi_ant_mimo); - if (err) { + if (err && err != BCME_UNSUPPORTED) { WL_ERR(("Could not get rssi sum (%d)\n", err)); } rssi = rssi_ant_mimo.rssi_sum; @@ -14847,11 +14978,9 @@ static s32 wl_cfg80211_ccode_evt_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *event, void *data) { - dhd_pub_t *dhd = cfg->pub; s32 err = 0; struct wiphy *wiphy = bcmcfg_to_wiphy(cfg); char country_str[WLC_CNTRY_BUF_SZ] = { 0 }; - struct net_device *dev = bcmcfg_to_prmry_ndev(cfg); if (strlcpy(country_str, data, WL_CCODE_LEN + 1) >= WLC_CNTRY_BUF_SZ) { return -EINVAL; @@ -14859,12 +14988,11 @@ wl_cfg80211_ccode_evt_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgde if (strncmp(cfg->country, country_str, WL_CCODE_LEN) == 0) { /* If country code is updated from command context, skip wiphy update */ - WL_MSG(dev->name, "No change in country (%s)\n", country_str); + WL_DBG_MEM(("No change in country (%s)\n", country_str)); return BCME_OK; } - WL_MSG(dev->name, "Updating new country %s\n", country_str); - dhd_conf_country(dhd, "country", country_str); + WL_INFORM_MEM(("Updating new country %s\n", country_str)); /* Indicate to upper layer for regdom change */ err = wl_update_wiphybands(cfg, true); @@ -14924,6 +15052,7 @@ static void wl_init_event_handler(struct bcm_cfg80211 *cfg) cfg->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status; cfg->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status; cfg->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status; + cfg->evt_handler[WLC_E_OWE_INFO] = wl_notify_connect_status; cfg->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status; cfg->evt_handler[WLC_E_ROAM] = wl_notify_roaming_status; cfg->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status; @@ -19676,6 +19805,21 @@ wl_cfg80211_filter_vndr_ext_id(const vndr_ie_t *vndrie) WL_DBG(("%s:SKIP ADDING FILS HLP EXTN ID\n", __func__)); return true; } +#ifdef WL_CAP_OCE_STA + if (vndrie->oui[0] == FILS_EXTID_MNG_REQ_PARAMS) { + /* Skip adding fils FILS_MAX_CHANNEL_TIME, its already done in FW */ + WL_DBG(("%s:SKIP ADDING FILS MNG REQ PARAMS \n", __func__)); + return true; + } +#endif /* WL_CAP_OCE_STA */ + if ((vndrie->oui[0] == EXT_MNG_HE_CAP_ID) || + (vndrie->oui[0] == EXT_MNG_HE_OP_ID)) { + /* Skip adding HE Capabilities ie and HE operation IE + */ + WL_DBG(("%s:SKIP ADDING HE EXTN ID\n", __func__)); + return true; + } + return false; } @@ -19699,12 +19843,7 @@ wl_cfg80211_parse_vndr_ies(const u8 *parse, u32 len, while (ie) { if (count >= MAX_VNDR_IE_NUMBER) break; -#ifdef HOSTAPD_EID_EXTENSION_SUPPORT - if (ie->id == DOT11_MNG_VS_ID || (ie->id == DOT11_MNG_ID_EXT_ID)) -#else - if (ie->id == DOT11_MNG_VS_ID) -#endif - { + if (ie->id == DOT11_MNG_VS_ID || (ie->id == DOT11_MNG_ID_EXT_ID)) { vndrie = (const vndr_ie_t *) ie; if (ie->id == DOT11_MNG_ID_EXT_ID) { /* len should be bigger than sizeof ID extn field at least */ @@ -20514,6 +20653,62 @@ static int wl_cfg80211_del_pmk(struct wiphy *wiphy, struct net_device *dev, } #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)) +static int wl_cfg80211_update_owe_info(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_update_owe_info *oweinfo) +{ + int err = 0; + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); + dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub); + wl_assoc_resp_params_v1_t *assoc_resp_params; + uint8 resp_buf[AP_OWE_IOCTL_BUF_SIZE]; + uint8 *p_resp_ies_tlv = NULL; + uint16 assoc_params_iovsize; + + WL_DBG(("%s: Enter\n", __func__)); + assoc_params_iovsize = AP_OWE_ASSOC_RESP_PARAMS_BUFSZ + + OFFSETOF(wl_assoc_resp_params_v1_t, ies); + assoc_resp_params = (wl_assoc_resp_params_v1_t *)MALLOCZ(dhdp->osh, assoc_params_iovsize); + + if (assoc_resp_params == NULL) { + WL_ERR(("error: failed to allocate %d bytes of memory\n", assoc_params_iovsize)); + return BCME_ERROR; + } + /* setup assoc_resp_params iovar */ + assoc_resp_params->version = WL_ASSOC_RESP_PARAMS_V1; + assoc_resp_params->len = assoc_params_iovsize; + assoc_resp_params->fixed_length = OFFSETOF(wl_assoc_resp_params_v1_t, ies); + /* setup TLVs */ + p_resp_ies_tlv = (uint8 *)&assoc_resp_params->ies[0]; + + if (wl_dbg_level & WL_DBG_DBG) { + if (oweinfo) { + prhex("supplicant MAC", oweinfo->peer, ETHER_ADDR_LEN); + prhex("supplicant generated OWE IE", oweinfo->ie, oweinfo->ie_len); + } + } + + if (oweinfo->ie_len > AP_OWE_ASSOC_RESP_PARAMS_BUFSZ) { + WL_ERR(("no resp ies buffer left\n")); + err = -EINVAL; + goto exit; + } + (void)memcpy_s(assoc_resp_params->mac_addr, ETHER_ADDR_LEN, + oweinfo->peer, ETHER_ADDR_LEN); + (void)memcpy_s(p_resp_ies_tlv, AP_OWE_ASSOC_RESP_PARAMS_BUFSZ, + oweinfo->ie, oweinfo->ie_len); + assoc_resp_params->resp_ie_len = oweinfo->ie_len; + assoc_resp_params->status = oweinfo->status; + err = wldev_iovar_setbuf(dev, "assoc_resp_params", assoc_resp_params, + assoc_params_iovsize, resp_buf, AP_OWE_IOCTL_BUF_SIZE, NULL); + if (err) { + WL_DBG(("ap_assoc_resp_params failed, err=%d\n", err)); + } +exit: + return err; +} +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) */ + u64 wl_cfg80211_get_new_roc_id(struct bcm_cfg80211 *cfg) { @@ -20905,8 +21100,8 @@ wl_get_rssi_per_ant(struct net_device *dev, char *ifname, char *peer_mac, void * WL_ERR(("Failed to get rssi info, err=%d\n", err)); } else { memcpy(get_param, iobuf, sizeof(wl_rssi_ant_mimo_t)); - if (get_param->count == 0) { - WL_ERR(("Not supported on this chip\n")); + if (get_param->count == 0 || get_param->rssi_sum >= 0) { + WL_INFORM(("Not supported on this chip\n")); err = BCME_UNSUPPORTED; } } diff --git a/bcmdhd.101.10.361.x/wl_cfg80211.h b/bcmdhd.101.10.361.x/wl_cfg80211.h index 35ab3af..d05482b 100755 --- a/bcmdhd.101.10.361.x/wl_cfg80211.h +++ b/bcmdhd.101.10.361.x/wl_cfg80211.h @@ -2849,10 +2849,11 @@ extern int wl_get_public_action(void *frame, u32 frame_len, u8 *ret_action); struct net_device *wl_cfg80211_get_remain_on_channel_ndev(struct bcm_cfg80211 *cfg); #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ -#ifdef WL_SUPPORT_ACS -#define ACS_MSRMNT_DELAY 1000 /* dump_obss delay in ms */ #define IOCTL_RETRY_COUNT 5 #define CHAN_NOISE_DUMMY -80 + +#ifdef WL_SUPPORT_ACS +#define ACS_MSRMNT_DELAY 1000 /* dump_obss delay in ms */ #define OBSS_TOKEN_IDX 15 #define IBSS_TOKEN_IDX 15 #define TX_TOKEN_IDX 14 diff --git a/bcmdhd.101.10.361.x/wl_cfgscan.c b/bcmdhd.101.10.361.x/wl_cfgscan.c index 606f327..85eb430 100755 --- a/bcmdhd.101.10.361.x/wl_cfgscan.c +++ b/bcmdhd.101.10.361.x/wl_cfgscan.c @@ -580,7 +580,7 @@ s32 wl_inform_bss_cache(struct bcm_cfg80211 *cfg) } } - cnt = i; + cnt = i; node = cfg->g_bss_cache_ctrl.m_cache_head; WL_SCAN(("cached AP count (%d)\n", wl_bss_cache_size(&cfg->g_bss_cache_ctrl))); for (i=cnt; node && iosh, reply, CHANINFO_LIST_BUF_SIZE); reply = dhd_pno_get_gscan(dhdp, DHD_PNO_GET_CHANNEL_LIST, &band, &reply_len); if (!reply) { @@ -6949,7 +6950,7 @@ static int wl_cfgvendor_lstats_get_info(struct wiphy *wiphy, pwrstats = (wl_pwrstats_t *) iovar_buf; if (dtoh16(pwrstats->version) != WL_PWRSTATS_VERSION) { - WL_ERR(("PWRSTATS Version mismatch\n")); + WL_ERR(("PWRSTATS Version mismatch %d\n", dtoh16(pwrstats->version))); err = BCME_ERROR; goto exit; } @@ -10115,7 +10116,9 @@ const struct nla_policy andr_dbg_policy[DEBUG_ATTRIBUTE_MAX] = { [DEBUG_ATTRIBUTE_LOG_MIN_DATA_SIZE] = { .type = NLA_U32 }, [DEBUG_ATTRIBUTE_FW_DUMP_LEN] = { .type = NLA_U32 }, [DEBUG_ATTRIBUTE_FW_DUMP_DATA] = { .type = NLA_U64 }, +#if (ANDROID_VERSION >= 11) [DEBUG_ATTRIBUTE_FW_ERR_CODE] = { .type = NLA_U32 }, +#endif [DEBUG_ATTRIBUTE_RING_DATA] = { .type = NLA_BINARY }, [DEBUG_ATTRIBUTE_RING_STATUS] = { .type = NLA_BINARY }, [DEBUG_ATTRIBUTE_RING_NUM] = { .type = NLA_U32 }, diff --git a/bcmdhd.101.10.361.x/wl_cfgvendor.h b/bcmdhd.101.10.361.x/wl_cfgvendor.h index c66c6d5..5c78e2f 100755 --- a/bcmdhd.101.10.361.x/wl_cfgvendor.h +++ b/bcmdhd.101.10.361.x/wl_cfgvendor.h @@ -108,6 +108,9 @@ typedef enum wifi_error { #define CFG80211_VENDOR_CMD_REPLY_SKB_SZ 100 #define CFG80211_VENDOR_EVT_SKB_SZ 2048 +#define AP_OWE_IOCTL_BUF_SIZE 1024u +#define AP_OWE_ASSOC_RESP_PARAMS_BUFSZ 512u + #define SUPP_SAE_PWE_LOOP 0x00 #define SUPP_SAE_PWE_H2E 0x01 #define SUPP_SAE_PWE_TRANS 0x02 diff --git a/bcmdhd.101.10.361.x/wl_cfgvif.c b/bcmdhd.101.10.361.x/wl_cfgvif.c index 0af2e0f..12ce31c 100755 --- a/bcmdhd.101.10.361.x/wl_cfgvif.c +++ b/bcmdhd.101.10.361.x/wl_cfgvif.c @@ -1615,8 +1615,8 @@ wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, #endif chspec = wl_freq_to_chanspec(center_freq); - WL_MSG(dev->name, "netdev_ifidx(%d) chan_width(%d) target channel(%s-%d %sMHz)\n", - dev->ifindex, width, CHSPEC2BANDSTR(chspec), + WL_MSG(dev->name, "netdev_ifidx(%d) target channel(%s-%d %sMHz)\n", + dev->ifindex, CHSPEC2BANDSTR(chspec), CHSPEC_CHANNEL(chspec), WLCWIDTH2STR(band_width)); #ifdef WL_P2P_6G @@ -2053,6 +2053,11 @@ wl_validate_wpa2ie(struct net_device *dev, const bcm_tlv_t *wpa2ie, s32 bssidx) break; #endif /* WL_SAE || WL_CLIENT_SAE */ #endif /* MFP */ +#if defined(WL_OWE) && (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)) + case RSN_AKM_OWE: + wpa_auth |= WPA3_AUTH_OWE; + break; +#endif /* WL_OWE && LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) */ default: WL_ERR(("No Key Mgmt Info\n")); } @@ -2062,6 +2067,29 @@ wl_validate_wpa2ie(struct net_device *dev, const bcm_tlv_t *wpa2ie, s32 bssidx) rsn_cap[0] = *(const u8 *)&mgmt->list[suite_count]; rsn_cap[1] = *((const u8 *)&mgmt->list[suite_count] + 1); + if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) { + int wpa_cap = 0, fw_wpa_cap = 0; + + err = wldev_iovar_getint_bsscfg(dev, "wpa_cap", &fw_wpa_cap, bssidx); + if (err < 0) { + WL_ERR(("get wpa_cap error %d\n", err)); + return err; + } + + /* set FW wpa_cap to sync RSN Capabilities */ + wpa_cap = rsn_cap[1] << 8 | rsn_cap[0]; + WL_INFORM(("rsn_cap 0x%02x 0x%02x, wpa_cap = 0x%04x, fw_wpa_cap = 0x%4x\n", + wpa_cap, rsn_cap[1], rsn_cap[0], fw_wpa_cap)); + + if ((wpa_cap&RSN_CAP_PREAUTH) != (fw_wpa_cap&RSN_CAP_PREAUTH)) { + err = wldev_iovar_setint_bsscfg(dev, "wpa_cap", wpa_cap, bssidx); + if (err < 0) { + WL_ERR(("wpa_cap error %d\n", err)); + return BCME_ERROR; + } + } + } + if (rsn_cap[0] & (RSN_CAP_16_REPLAY_CNTRS << RSN_CAP_PTK_REPLAY_CNTR_SHIFT)) { wme_bss_disable = 0; } else { @@ -3019,7 +3047,9 @@ wl_cfg80211_bcn_bringup_ap( uint32 wme_apsd = 0; #endif /* SOFTAP_UAPSD_OFF */ s32 err = BCME_OK; +#ifdef BCM4343X_WAR dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub); +#endif s32 is_rsdb_supported = BCME_ERROR; char sec[64]; @@ -3173,6 +3203,7 @@ wl_cfg80211_bcn_bringup_ap( WL_ERR(("Could not get wsec %d\n", err)); goto exit; } +#ifdef BCM4343X_WAR if (dhd->conf->chip == BCM43430_CHIP_ID && bssidx > 0 && (wsec & (TKIP_ENABLED|AES_ENABLED))) { struct net_device *primary_ndev = bcmcfg_to_prmry_ndev(cfg); @@ -3193,6 +3224,7 @@ wl_cfg80211_bcn_bringup_ap( wldev_ioctl_set(primary_ndev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)); } } +#endif if ((wsec == WEP_ENABLED) && cfg->wep_key.len) { WL_DBG(("Applying buffered WEP KEY \n")); err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &cfg->wep_key, @@ -4518,6 +4550,9 @@ wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev, #if defined(WL_CFG80211_STA_EVENT) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) struct station_info sinfo; #endif /* (LINUX_VERSION >= VERSION(3,2,0)) || !WL_CFG80211_STA_EVENT */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)) + struct cfg80211_update_owe_info owe_info; +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) */ #ifdef BIGDATA_SOFTAP dhd_pub_t *dhdp; #endif /* BIGDATA_SOFTAP */ @@ -4661,6 +4696,23 @@ wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev, } #endif /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)) + else if (event == WLC_E_OWE_INFO) { + if (!data) { + WL_ERR(("No DH-IEs present in ASSOC/REASSOC_IND")); + return -EINVAL; + } + if (wl_dbg_level & WL_DBG_DBG) { + prhex("FW-OWEIE ", (uint8 *)data, len); + } + eacopy(e->addr.octet, owe_info.peer); + owe_info.ie = data; + owe_info.ie_len = len; + WL_INFORM_MEM(("Recieved owe_info. Mac addr" MACDBG "\n", + MAC2STRDBG((const u8*)(&e->addr)))); + cfg80211_update_owe_info_event(ndev, &owe_info, GFP_ATOMIC); + } +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) */ return err; } @@ -5144,6 +5196,7 @@ wl_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *cfgdev, } #endif /* WL_CFG80211_ACL */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) int wl_chspec_chandef(chanspec_t chanspec, struct cfg80211_chan_def *chandef, struct wiphy *wiphy) { @@ -5254,7 +5307,6 @@ int wl_chspec_chandef(chanspec_t chanspec, return 0; } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) void wl_cfg80211_ch_switch_notify(struct net_device *dev, uint16 chanspec, struct wiphy *wiphy) { diff --git a/bcmdhd.101.10.361.x/wl_cfgvif.h b/bcmdhd.101.10.361.x/wl_cfgvif.h index a81df9f..c949c10 100755 --- a/bcmdhd.101.10.361.x/wl_cfgvif.h +++ b/bcmdhd.101.10.361.x/wl_cfgvif.h @@ -263,6 +263,8 @@ extern bool wl_cfg80211_is_tdls_tunneled_frame(void *frame, u32 frame_len); extern void wl_restore_ap_bw(struct bcm_cfg80211 *cfg); #endif /* SUPPORT_AP_BWCTRL */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) extern int wl_chspec_chandef(chanspec_t chanspec, struct cfg80211_chan_def *chandef, struct wiphy *wiphy); +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))) */ #endif /* _wl_cfgvif_h_ */ diff --git a/bcmdhd.101.10.361.x/wl_iapsta.c b/bcmdhd.101.10.361.x/wl_iapsta.c index 06053e6..f6a5424 100755 --- a/bcmdhd.101.10.361.x/wl_iapsta.c +++ b/bcmdhd.101.10.361.x/wl_iapsta.c @@ -645,8 +645,10 @@ static int wl_ext_set_emode(struct wl_if_info *cur_if) { struct net_device *dev = cur_if->dev; +#ifdef BCM4343X_WAR struct dhd_pub *dhd = dhd_get_pub(dev); struct wl_apsta_params *apsta_params = dhd->iapsta_params; +#endif struct wl_wsec_key wsec_key; wsec_pmk_t psk; authmode_t amode = cur_if->amode; @@ -692,10 +694,12 @@ wl_ext_set_emode(struct wl_if_info *cur_if) memcpy(psk.key, key, strlen(key)); IAPSTA_INFO(dev->name, "TKIP/AES key \"%s\"\n", psk.key); } +#ifdef BCM4343X_WAR if (dhd->conf->chip == BCM43430_CHIP_ID && cur_if->ifidx > 0 && wsec >= 2 && apsta_params->apstamode == ISTAAP_MODE) { wsec |= WSEC_SWFLAG; // terence 20180628: fix me, this is a workaround } +#endif wl_ext_iovar_setint(dev, "wsec", wsec); @@ -772,7 +776,7 @@ wl_ext_get_chan(struct net_device *dev, struct wl_chan_info *chan_info) { uint16 chan = 0, ctl_chan; u32 chanspec = 0; - + chanspec = wl_ext_get_chanspec(dev, chan_info); if (chanspec) { ctl_chan = wf_chspec_ctlchan(chanspec); @@ -988,6 +992,10 @@ wl_ext_connect_timeout(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct wl_if_info *cur_if; +#if defined(WL_EXT_RECONNECT) && defined(WL_CFG80211) + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); + u8 *curbssid = NULL; +#endif /* WL_CFG80211 */ if (!dev) { IAPSTA_ERROR("wlan", "dev is not ready\n"); @@ -1000,6 +1008,9 @@ wl_ext_connect_timeout(unsigned long data) #if defined(WL_EXT_RECONNECT) && defined(WL_CFG80211) cur_if->assoc_info.reassoc = 0; + curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID); + if (curbssid) + (void)memcpy_s(&cur_if->bssid, ETH_ALEN, curbssid, ETH_ALEN); #endif /* WL_EXT_RECONNECT && WL_CFG80211 */ IAPSTA_ERROR(dev->name, "timer expired\n"); wl_ext_send_event_msg(dev, WLC_E_SET_SSID, WLC_E_STATUS_NO_NETWORKS, WLC_E_STATUS_SUCCESS); @@ -2126,6 +2137,21 @@ wl_ext_move_other_channel(struct wl_apsta_params *apsta_params, } } + if (target_if) { + // skip move target_if while there is other interface's prio is higher than cur_if + max_prio = cur_if->prio; + for (i=0; iif_info[i]; + if (target_if != tmp_if && wl_get_isam_status(tmp_if, IF_READY) && + tmp_if->prio > max_prio) { + if (wl_ext_same_chan(&target_if->chan_info, &tmp_if->chan_info)) { + target_if = NULL; + break; + } + } + } + } + if (target_if) { WL_MSG(target_if->ifname, "channel=%s-%d => %s channel=%s-%d\n", WLCBAND2STR(target_if->chan_info.band), target_chan, @@ -2261,6 +2287,29 @@ wl_ext_sta_handshaking(struct net_device *dev) return connecting; } +bool +wl_ext_sta_connected(struct net_device *dev) +{ + struct wl_if_info *cur_if = NULL; + bool connected = FALSE; + int state; + + cur_if = wl_get_cur_if(dev); + if (!cur_if) + return FALSE; + + if (cur_if->ifmode != ISTA_MODE && cur_if->ifmode != IGC_MODE) + return FALSE; + + state = cur_if->conn_state; + if (state >= CONN_STATE_CONNECTED) { + connected = TRUE; + IAPSTA_TRACE(dev->name, "conn_state %d\n", state); + } + + return connected; +} + #ifdef DHD_LOSSLESS_ROAMING int wl_ext_any_sta_handshaking(struct dhd_pub *dhd) @@ -2434,14 +2483,31 @@ wl_ext_iapsta_restart_master(struct net_device *dev) { dhd_pub_t *dhd = dhd_get_pub(dev); struct wl_apsta_params *apsta_params = dhd->iapsta_params; - struct wl_if_info *ap_if = NULL; + struct wl_if_info *ap_if = NULL, *tmp_if = NULL; + struct wl_chan_info chan_info; + int i; if (apsta_params->radar) return; ap_if = wl_ext_get_dfs_master_if(apsta_params); + if (!ap_if) + return; + + for (i=0; iif_info[i]; + if (tmp_if && tmp_if->ifmode == ISTA_MODE && + wl_get_isam_status(tmp_if, IF_READY)) { + memset(&chan_info, 0, sizeof(struct wl_chan_info)); + wl_ext_get_chan(tmp_if->dev, &chan_info); + if (wl_ext_same_chan(&chan_info, &tmp_if->chan_info)) { + return; + } + } + } if (ap_if) { uint16 chan_2g, chan_5g; + WL_MSG(tmp_if->ifname, "move DFS channel interface\n"); wl_ext_if_down(apsta_params, ap_if); wl_ext_iapsta_restart_master(dev); wl_ext_get_default_chan(ap_if->dev, &chan_2g, &chan_5g, TRUE); @@ -2454,6 +2520,8 @@ wl_ext_iapsta_restart_master(struct net_device *dev) if (ap_if->chan_info.chan) { wl_ext_move_cur_channel(apsta_params, ap_if); wl_ext_if_up(apsta_params, ap_if, FALSE, 0); + } else { + WL_MSG(tmp_if->ifname, "no preferred channel\n"); } } } @@ -2469,7 +2537,7 @@ wl_ext_if_reenabled(struct wl_apsta_params *apsta_params, ifmode_t ifmode, u32 c if (tmp_if && tmp_if->ifmode == ifmode && wl_get_isam_status(tmp_if, IF_READY)) { if (wl_ext_get_chan(tmp_if->dev, &tmp_if->chan_info) == channel) { - WL_MSG(tmp_if->ifname, "re-enable channel %d\n", channel); + WL_MSG(tmp_if->ifname, "re-enable channel %d\n", channel); if (ifmode == IAP_MODE) { wl_ext_if_down(apsta_params, tmp_if); wl_ext_if_up(apsta_params, tmp_if, FALSE, 0); @@ -2519,8 +2587,8 @@ wl_ext_iapsta_update_channel(struct net_device *dev, u32 chanspec) if (cur_if->ifmode == ISTA_MODE) { if (conf->war & SET_CHAN_INCONN && chan_info->chan) { chanspec_t fw_chspec; - IAPSTA_INFO(dev->name, "set channel %d\n", chan_info->chan); - wl_ext_set_chanspec(cur_if->dev, chan_info, &fw_chspec); + IAPSTA_INFO(dev->name, "set channel %d\n", chan_info->chan); + wl_ext_set_chanspec(cur_if->dev, chan_info, &fw_chspec); } wl_set_isam_status(cur_if, STA_CONNECTING); } @@ -2789,6 +2857,11 @@ wl_ext_connect_retry(struct net_device *dev, wl_event_msg_t *e) connecting = wl_ext_sta_connecting(dev); handshaking = wl_ext_sta_handshaking(dev); + if (cur_if->conn_state == CONN_STATE_ASSOCIATED) { + WL_MSG(dev->name, "skip connect retry due to no 4-way M1 received\n"); + return BCME_BADADDR; + } + mutex_unlock(&apsta_params->in4way_sync); mutex_lock(&cfg->connect_sync); @@ -2827,9 +2900,11 @@ wl_ext_connect_retry(struct net_device *dev, wl_event_msg_t *e) if (associated) { bzero(&cfg->last_roamed_addr, ETHER_ADDR_LEN); wl_cfg80211_disassoc(dev, WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT); + OSL_SLEEP(50); // wait WLC_E_DISASSOC } if (wl_handle_join(cfg, dev, assoc_info)) goto exit; + wl_ext_update_conn_state(dhd, cur_if->ifidx, CONN_STATE_CONNECTING); if (assoc_info->chan_cnt == 0) max_wait_time = STA_CONNECT_FULL_CHAN_TIMEOUT; else @@ -3984,6 +4059,7 @@ wl_ext_in4way_sync_sta(dhd_pub_t *dhd, struct wl_if_info *cur_if, #endif /* BTC_WAR */ max_wait_time = 0; } else { + wl_ext_update_conn_state(dhd, cur_if->ifidx, CONN_STATE_ASSOCIATED); max_wait_time = STA_4WAY_TIMEOUT; } #if defined(WL_EXT_RECONNECT) && defined(WL_CFG80211) @@ -4001,8 +4077,10 @@ wl_ext_in4way_sync_sta(dhd_pub_t *dhd, struct wl_if_info *cur_if, case WL_EXT_STATUS_ROAMED: wl_ext_iovar_getint(dev, "wpa_auth", &wpa_auth); if ((wpa_auth >= WPA_AUTH_UNSPECIFIED) && !(wpa_auth & WPA2_AUTH_FT)) { - wl_timer_mod(dhd, &cur_if->connect_timer, STA_CONNECT_TIMEOUT); - osl_do_gettimeofday(sta_conn_ts); + if (cur_if->conn_state >= CONN_STATE_CONNECTED) { + wl_timer_mod(dhd, &cur_if->connect_timer, STA_CONNECT_TIMEOUT); + osl_do_gettimeofday(sta_conn_ts); + } wl_ext_update_conn_state(dhd, cur_if->ifidx, CONN_STATE_CONNECTING); #ifdef BTC_WAR wl_ext_btc_config(cur_if->dev, TRUE); @@ -4275,7 +4353,7 @@ wl_ext_update_extsae_4way(struct net_device *dev, else conn_state = CONN_STATE_AUTH_SAE_M1; } else if (auth_seq == 2) { - if (tx) + if (tx) conn_state = CONN_STATE_AUTH_SAE_M4; else conn_state = CONN_STATE_AUTH_SAE_M3; @@ -5269,6 +5347,10 @@ wl_ext_rxf0ovfl_reinit_handler(struct wl_if_info *cur_if, const wl_event_msg_t * int ret = 0; bool reinit = FALSE; + if (!(dhd->conf->war & FW_REINIT_RXF0OVFL)) { + return; + } + if ((cur_if->ifmode == ISTA_MODE) && (etype == WLC_E_LINK) && (flags & WLC_EVENT_MSG_LINK)) { // Link up @@ -5342,6 +5424,7 @@ wl_ext_iapsta_link(struct wl_if_info *cur_if, } else { WL_MSG(cur_if->ifname, "[%c] Link UP with %pM\n", cur_if->prefix, &e->addr); + wl_ext_isam_status(cur_if->dev, NULL, 0); #ifdef SET_CARRIER wl_ext_net_setcarrier(cur_if, TRUE, FALSE); #endif /* SET_CARRIER */ @@ -5382,11 +5465,13 @@ wl_ext_iapsta_link(struct wl_if_info *cur_if, WL_MSG(cur_if->ifname, "[%c] Link up (etype=%d)\n", cur_if->prefix, event_type); wl_set_isam_status(cur_if, AP_CREATED); + wl_ext_isam_status(cur_if->dev, NULL, 0); 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); + wl_ext_isam_status(cur_if->dev, NULL, 0); } #ifdef SET_CARRIER wl_ext_net_setcarrier(cur_if, TRUE, FALSE); @@ -5426,6 +5511,23 @@ wl_ext_iapsta_link(struct wl_if_info *cur_if, } } +static void +wl_ext_iapsta_ccode(struct wl_if_info *cur_if, + const wl_event_msg_t *e, void *data) +{ + struct dhd_pub *dhd = dhd_get_pub(cur_if->dev); + uint32 event_type = ntoh32(e->event_type); + char country_str[WLC_CNTRY_BUF_SZ] = { 0 }; + + if (event_type == WLC_E_COUNTRY_CODE_CHANGED) { + if (strlcpy(country_str, data, WL_CCODE_LEN + 1) >= WLC_CNTRY_BUF_SZ) { + return; + } + WL_MSG(cur_if->ifname, "Updating new country %s\n", country_str); + dhd_conf_country(dhd, "country", country_str); + } +} + void wl_ext_iapsta_event(struct net_device *dev, void *argu, const wl_event_msg_t *e, void *data) @@ -5443,6 +5545,7 @@ wl_ext_iapsta_event(struct net_device *dev, void *argu, } wl_ext_iapsta_link(cur_if, e, data); + wl_ext_iapsta_ccode(cur_if, e, data); #ifdef TPUT_MONITOR if (dhd->conf->tput_monitor_ms) wl_tput_monitor_handler(cur_if, e, data); @@ -5718,7 +5821,7 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para if (FW_SUPPORTED(dhd, rsdb)) { if (apstamode == IDUALAP_MODE) - apsta_params->rsdb = -1; + apsta_params->rsdb = 1; else if (apstamode == ISTAAPAP_MODE) apsta_params->rsdb = 0; if (apstamode == ISTAAPAP_MODE || apstamode == IDUALAP_MODE || @@ -6720,7 +6823,6 @@ wl_ext_iapsta_postinit(struct net_device *net, struct wl_if_info *cur_if) { struct dhd_pub *dhd = dhd_get_pub(net); struct wl_apsta_params *apsta_params = dhd->iapsta_params; - int pm; IAPSTA_TRACE(cur_if->ifname, "ifidx=%d\n", cur_if->ifidx); if (cur_if->ifidx == 0) { @@ -6741,14 +6843,7 @@ wl_ext_iapsta_postinit(struct net_device *net, struct wl_if_info *cur_if) wl_ext_add_del_ie(net, VNDR_IE_ASSOCREQ_FLAG, dhd->conf->vndr_ie_assocreq, "add"); } else { if (cur_if->ifmode == ISTA_MODE) { - wl_ext_iovar_setint(cur_if->dev, "roam_off", dhd->conf->roam_off); - wl_ext_iovar_setint(cur_if->dev, "bcn_timeout", dhd->conf->bcn_timeout); - if (dhd->conf->pm >= 0) - pm = dhd->conf->pm; - else - pm = PM_FAST; - wl_ext_ioctl(cur_if->dev, WLC_SET_PM, &pm, sizeof(pm), 1); - wl_ext_iovar_setint(cur_if->dev, "assoc_retry_max", 10); + dhd_conf_preinit_ioctls_sta(dhd, cur_if->ifidx); } #ifdef WLMESH else if (cur_if->ifmode == IMESH_MODE) { diff --git a/bcmdhd.101.10.361.x/wl_iapsta.h b/bcmdhd.101.10.361.x/wl_iapsta.h index f88c6e7..26eb7e7 100755 --- a/bcmdhd.101.10.361.x/wl_iapsta.h +++ b/bcmdhd.101.10.361.x/wl_iapsta.h @@ -58,6 +58,7 @@ int wl_ext_iapsta_config(struct net_device *dev, char *command, int total_len); void wl_ext_add_remove_pm_enable_work(struct net_device *dev, bool add); bool wl_ext_iapsta_other_if_enabled(struct net_device *net); bool wl_ext_sta_connecting(struct net_device *dev); +bool wl_ext_sta_connected(struct net_device *dev); void wl_ext_get_chan_str(struct net_device *dev, char *chan_str, int total_len); #ifdef DHD_LOSSLESS_ROAMING int wl_ext_any_sta_handshaking(struct dhd_pub *dhd); diff --git a/bcmdhd.101.10.361.x/wl_timer.c b/bcmdhd.101.10.361.x/wl_timer.c index e9ea4d8..0255acd 100755 --- a/bcmdhd.101.10.361.x/wl_timer.c +++ b/bcmdhd.101.10.361.x/wl_timer.c @@ -1,611 +1,611 @@ -#include -#ifdef WL_TIMER - -#define TIMER_ERROR(name, arg1, args...) \ - do { \ - if (android_msg_level & ANDROID_ERROR_LEVEL) { \ - printf("[%s] TIMER-ERROR) %s : " arg1, name, __func__, ## args); \ - } \ - } while (0) -#define TIMER_TRACE(name, arg1, args...) \ - do { \ - if (android_msg_level & ANDROID_TRACE_LEVEL) { \ - printf("[%s] TIMER-TRACE) %s : " arg1, name, __func__, ## args); \ - } \ - } while (0) - -#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \ - 4 && __GNUC_MINOR__ >= 6)) -#define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \ -_Pragma("GCC diagnostic push") \ -_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \ -(entry) = list_first_entry((ptr), type, member); \ -_Pragma("GCC diagnostic pop") \ - -#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \ -_Pragma("GCC diagnostic push") \ -_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \ -entry = container_of((ptr), type, member); \ -_Pragma("GCC diagnostic pop") \ - -#else -#define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \ -(entry) = list_first_entry((ptr), type, member); \ - -#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \ -entry = container_of((ptr), type, member); \ - -#endif /* STRICT_GCC_WARNINGS */ - -typedef void(*FUNC_HANDLER) (void *cb_argu); - -struct wl_func_q { - struct list_head eq_list; - FUNC_HANDLER cb_func; - void *cb_argu; -}; - -typedef void(*TIMER_HANDLER) (void *cb_argu); - -typedef struct timer_handler_list { - struct list_head list; - struct net_device *net; - timer_list_compat_t *timer; - TIMER_HANDLER cb_func; - void *cb_argu; - uint tmo_ms; - ulong tmo_jiffies; -} timer_handler_list_t; - -typedef struct wl_timer_params { - dhd_pub_t *pub; - struct list_head timer_list; - struct list_head eq_list; - timer_list_compat_t timer; - spinlock_t eq_lock; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) - struct workqueue_struct *timer_workq; - struct work_struct timer_work; - struct workqueue_struct *func_workq; - struct work_struct func_work; -#else - tsk_ctl_t thr_timer_ctl; - tsk_ctl_t thr_func_ctl; -#endif -} wl_timer_params_t; - -static unsigned long -wl_func_lock_eq(struct wl_timer_params *timer_params) -{ - unsigned long flags; - - spin_lock_irqsave(&timer_params->eq_lock, flags); - return flags; -} - -static void -wl_func_unlock_eq(struct wl_timer_params *timer_params, unsigned long flags) -{ - spin_unlock_irqrestore(&timer_params->eq_lock, flags); -} - -static void -wl_func_init_eq_lock(struct wl_timer_params *timer_params) -{ - spin_lock_init(&timer_params->eq_lock); -} - -static void -wl_func_init_eq(struct wl_timer_params *timer_params) -{ - wl_func_init_eq_lock(timer_params); - INIT_LIST_HEAD(&timer_params->eq_list); -} - -static void -wl_func_flush_eq(struct wl_timer_params *timer_params) -{ - struct wl_func_q *e; - unsigned long flags; - - flags = wl_func_lock_eq(timer_params); - while (!list_empty_careful(&timer_params->eq_list)) { - BCM_SET_LIST_FIRST_ENTRY(e, &timer_params->eq_list, struct wl_func_q, eq_list); - list_del(&e->eq_list); - kfree(e); - } - wl_func_unlock_eq(timer_params, flags); -} - -static struct wl_func_q * -wl_func_deq(struct wl_timer_params *timer_params) -{ - struct wl_func_q *e = NULL; - unsigned long flags; - - flags = wl_func_lock_eq(timer_params); - if (likely(!list_empty(&timer_params->eq_list))) { - BCM_SET_LIST_FIRST_ENTRY(e, &timer_params->eq_list, struct wl_func_q, eq_list); - list_del(&e->eq_list); - } - wl_func_unlock_eq(timer_params, flags); - - return e; -} - -static s32 -wl_func_enq(struct wl_timer_params *timer_params, - void *cb_func, void *cb_argu) -{ - struct wl_func_q *e; - s32 err = 0; - uint32 funcq_size; - unsigned long flags; - gfp_t aflags; - - funcq_size = sizeof(struct wl_func_q); - aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; - e = kzalloc(funcq_size, aflags); - if (unlikely(!e)) { - TIMER_ERROR("wlan", "funcq_size alloc failed %d\n", funcq_size); - return -ENOMEM; - } - e->cb_func = cb_func; - e->cb_argu = cb_argu; - flags = wl_func_lock_eq(timer_params); - list_add_tail(&e->eq_list, &timer_params->eq_list); - wl_func_unlock_eq(timer_params, flags); - - return err; -} - -static void -wl_func_put(struct wl_func_q *e) -{ - kfree(e); -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) -static void wl_func_handler(struct work_struct *data); -#define WL_FUNC_HANDLER() static void wl_func_handler(struct work_struct *data) -#else -static int wl_func_handler(void *data); -#define WL_FUNC_HANDLER() static int wl_func_handler(void *data) -#endif - -WL_FUNC_HANDLER() -{ - struct wl_timer_params *timer_params = NULL; - struct wl_func_q *e; - struct net_device *net = NULL; - dhd_pub_t *dhd; - unsigned long flags = 0; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)) - tsk_ctl_t *tsk = (tsk_ctl_t *)data; - timer_params = (struct wl_timer_params *)tsk->parent; -#else - BCM_SET_CONTAINER_OF(timer_params, data, struct wl_timer_params, func_work); -#endif - - dhd = timer_params->pub; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)) - while (1) { - if (down_interruptible(&tsk->sema) == 0) { - SMP_RD_BARRIER_DEPENDS(); - if (tsk->terminated) { - break; - } -#endif - DHD_EVENT_WAKE_LOCK(dhd); - while ((e = wl_func_deq(timer_params))) { - DHD_GENERAL_LOCK(dhd, flags); - if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhd)) { - TIMER_ERROR(net->name, "BUS is DOWN.\n"); - DHD_GENERAL_UNLOCK(dhd, flags); - goto fail; - } - DHD_GENERAL_UNLOCK(dhd, flags); - e->cb_func(e->cb_argu); -fail: - wl_func_put(e); - } - DHD_EVENT_WAKE_UNLOCK(dhd); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)) - } else { - break; - } - } - complete_and_exit(&tsk->completed, 0); -#endif -} - -void -wl_func_send(void *params, void *cb_func, void *cb_argu) -{ - struct wl_timer_params *timer_params = params; - - if (timer_params == NULL) { - TIMER_ERROR("wlan", "Stale ignored\n"); - return; - } - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) - if (timer_params->func_workq == NULL) { - TIMER_ERROR("wlan", "Event handler is not created\n"); - return; - } -#endif - - if (likely(!wl_func_enq(timer_params, cb_func, cb_argu))) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) - queue_work(timer_params->func_workq, &timer_params->func_work); -#else - if (timer_params->thr_func_ctl.thr_pid >= 0) { - up(&timer_params->thr_func_ctl.sema); - } -#endif - } -} - -static s32 -wl_func_create_handler(struct wl_timer_params *timer_params) -{ - int ret = 0; - TIMER_TRACE("wlan", "Enter\n"); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) - if (!timer_params->func_workq) { - timer_params->func_workq = alloc_workqueue("timer_funcd", - WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_UNBOUND, 0); - } - if (!timer_params->func_workq) { - TIMER_ERROR("wlan", "func_workq alloc_workqueue failed\n"); - ret = -ENOMEM; - } else { - INIT_WORK(&timer_params->func_work, wl_func_handler); - } -#else - PROC_START(wl_func_handler, timer_params, &timer_params->thr_func_ctl, 0, "timer_funcd"); - if (timer_params->thr_func_ctl.thr_pid < 0) { - ret = -ENOMEM; - } -#endif - - return ret; -} - -static void -wl_func_destroy_handler(struct wl_timer_params *timer_params) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) - if (timer_params && timer_params->func_workq) { - cancel_work_sync(&timer_params->func_work); - destroy_workqueue(timer_params->func_workq); - timer_params->func_workq = NULL; - } -#else - if (timer_params->thr_func_ctl.thr_pid >= 0) { - PROC_STOP(&timer_params->thr_func_ctl); - } -#endif -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) -static void wl_timer_handler(struct work_struct *data); -#define WL_TIMER_HANDLER() static void wl_timer_handler(struct work_struct *data) -#else -static int wl_timer_handler(void *data); -#define WL_TIMER_HANDLER() static int wl_timer_handler(void *data) -#endif - -WL_TIMER_HANDLER() -{ - struct wl_timer_params *timer_params = NULL; - struct timer_handler_list *node, *next; - dhd_pub_t *dhd; - unsigned long flags = 0; - unsigned long cur_jiffies, diff_jiffies, min_jiffies = 0; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)) - tsk_ctl_t *tsk = (tsk_ctl_t *)data; - timer_params = (struct wl_timer_params *)tsk->parent; -#else - BCM_SET_CONTAINER_OF(timer_params, data, struct wl_timer_params, timer_work); -#endif - - dhd = timer_params->pub; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)) - while (1) { - if (down_interruptible(&tsk->sema) == 0) { - SMP_RD_BARRIER_DEPENDS(); - if (tsk->terminated) { - break; - } -#endif - DHD_EVENT_WAKE_LOCK(dhd); - DHD_GENERAL_LOCK(dhd, flags); - if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhd)) { - TIMER_ERROR("wlan", "BUS is DOWN.\n"); - DHD_GENERAL_UNLOCK(dhd, flags); - goto exit; - } - DHD_GENERAL_UNLOCK(dhd, flags); - cur_jiffies = jiffies; - list_for_each_entry_safe(node, next, &timer_params->timer_list, list) { - if (node->tmo_ms) { - if (time_after(cur_jiffies, node->tmo_jiffies)) { - wl_func_send(timer_params, node->cb_func, node->cb_argu); - node->tmo_ms = 0; - } else { - diff_jiffies = node->tmo_jiffies - cur_jiffies; - if (min_jiffies == 0) - min_jiffies = diff_jiffies; - else if (diff_jiffies < min_jiffies) - min_jiffies = diff_jiffies; - } - } - } - if (min_jiffies) - mod_timer(&timer_params->timer, jiffies + min_jiffies); -exit: - DHD_EVENT_WAKE_UNLOCK(dhd); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)) - } else { - break; - } - } - complete_and_exit(&tsk->completed, 0); -#endif -} - -void -wl_timer_kick_handler(wl_timer_params_t *timer_params) -{ - if (timer_params == NULL) { - TIMER_ERROR("wlan", "timer_params not ready\n"); - return; - } - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) - if (timer_params->timer_workq == NULL) { - TIMER_ERROR("wlan", "timer handler is not created\n"); - return; - } - queue_work(timer_params->timer_workq, &timer_params->timer_work); -#else - if (timer_params->thr_timer_ctl.thr_pid >= 0) { - up(&timer_params->thr_timer_ctl.sema); - } -#endif -} - -static void -wl_timer_timeout(unsigned long data) -{ - struct wl_timer_params *timer_params = (struct wl_timer_params *)data; - - if (!timer_params) { - TIMER_ERROR("wlan", "timer_params is not ready\n"); - return; - } - - TIMER_TRACE("wlan", "timer expired\n"); - wl_timer_kick_handler(timer_params); -} - -static s32 -wl_timer_create_handler(struct wl_timer_params *timer_params) -{ - int ret = 0; - - TIMER_TRACE("wlan", "Enter\n"); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) - if (!timer_params->timer_workq) { - timer_params->timer_workq = alloc_workqueue("timerd", - WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_UNBOUND, 0); - } - if (!timer_params->timer_workq) { - TIMER_ERROR("wlan", "timer_workq alloc_workqueue failed\n"); - ret = -ENOMEM; - } else { - INIT_WORK(&timer_params->timer_work, wl_timer_handler); - } -#else - PROC_START(wl_timer_handler, timer_params, &timer_params->thr_timer_ctl, 0, "timerd"); - if (timer_params->thr_timer_ctl.thr_pid < 0) { - ret = -ENOMEM; - } -#endif - - return ret; -} - -static void -wl_timer_destroy_handler(struct wl_timer_params *timer_params) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) - if (timer_params && timer_params->timer_workq) { - cancel_work_sync(&timer_params->timer_work); - destroy_workqueue(timer_params->timer_workq); - timer_params->timer_workq = NULL; - } -#else - if (timer_params->thr_timer_ctl.thr_pid >= 0) { - PROC_STOP(&timer_params->thr_timer_ctl); - } -#endif -} - -static void -wl_timer_free(struct wl_timer_params *timer_params) -{ - timer_handler_list_t *node, *next; - - list_for_each_entry_safe(node, next, &timer_params->timer_list, list) { - TIMER_TRACE(node->net->name, "Free timer\n"); - list_del(&node->list); - kfree(node); - } -} - -void -wl_timer_mod(dhd_pub_t *dhd, timer_list_compat_t *timer, uint32 tmo_ms) -{ - wl_timer_params_t *timer_params = dhd->timer_params; - timer_handler_list_t *node, *next; - bool found = FALSE; - - list_for_each_entry_safe(node, next, &timer_params->timer_list, list) { - if (node->timer == timer) { - node->tmo_ms = tmo_ms; - if (tmo_ms) { - TIMER_TRACE(node->net->name, "update timer %dms\n", tmo_ms); - node->tmo_jiffies = jiffies + msecs_to_jiffies(tmo_ms); - wl_timer_kick_handler(timer_params); - } - found = TRUE; - break; - } - } - if (!found) - TIMER_ERROR("wlan", "timer not found\n"); -} - -void -wl_timer_register(struct net_device *net, timer_list_compat_t *timer, void *cb_func) -{ - dhd_pub_t *dhd = dhd_get_pub(net); - wl_timer_params_t *timer_params = dhd->timer_params; - timer_handler_list_t *node, *next, *leaf; - - list_for_each_entry_safe(node, next, &timer_params->timer_list, list) { - if (node->timer == timer) { - TIMER_TRACE(net->name, "timer already registered\n"); - return; - } - } - - leaf = kmalloc(sizeof(timer_handler_list_t), GFP_KERNEL); - if (!leaf) { - TIMER_ERROR(net->name, "Memory alloc failure %d\n", - (int)sizeof(timer_handler_list_t)); - return; - } - memset(leaf, 0, sizeof(timer_handler_list_t)); - leaf->net = net; - leaf->timer = timer; - leaf->cb_func = cb_func; - leaf->cb_argu = net; - TIMER_ERROR(net->name, "timer registered tmo=%d\n", leaf->tmo_ms); - list_add_tail(&leaf->list, &timer_params->timer_list); - - return; -} - -void -wl_timer_deregister(struct net_device *net, timer_list_compat_t *timer) -{ - dhd_pub_t *dhd = dhd_get_pub(net); - wl_timer_params_t *timer_params = dhd->timer_params; - timer_handler_list_t *node, *next; - - list_for_each_entry_safe(node, next, &timer_params->timer_list, list) { - if (node->timer == timer) { - TIMER_TRACE(net->name, "timer deregistered\n"); - list_del(&node->list); - kfree(node); - } - } - return; -} - -static s32 -wl_timer_init_priv(struct wl_timer_params *timer_params) -{ - s32 err = 0; - - INIT_LIST_HEAD(&timer_params->timer_list); - if (wl_timer_create_handler(timer_params)) - return -ENOMEM; - wl_func_init_eq(timer_params); - if (wl_func_create_handler(timer_params)) - return -ENOMEM; - - return err; -} - -static void -wl_timer_deinit_priv(struct wl_timer_params *timer_params) -{ - wl_timer_free(timer_params); - wl_func_destroy_handler(timer_params); - wl_func_flush_eq(timer_params); - wl_timer_destroy_handler(timer_params); -} - -void -wl_timer_dettach(dhd_pub_t *dhdp) -{ - struct wl_timer_params *timer_params = dhdp->timer_params; - - if (timer_params) { - if (timer_pending(&timer_params->timer)) - del_timer_sync(&timer_params->timer); - wl_timer_deinit_priv(timer_params); - kfree(timer_params); - dhdp->timer_params = NULL; - } -} - -s32 -wl_timer_attach(struct net_device *net) -{ - struct dhd_pub *dhdp = dhd_get_pub(net); - struct wl_timer_params *timer_params = NULL; - s32 err = 0; - - timer_params = kmalloc(sizeof(wl_timer_params_t), GFP_KERNEL); - if (!timer_params) { - TIMER_ERROR(net->name, "Failed to allocate memory (%zu)\n", - sizeof(wl_timer_params_t)); - return -ENOMEM; - } - dhdp->timer_params = timer_params; - memset(timer_params, 0, sizeof(wl_timer_params_t)); - timer_params->pub = dhdp; - - err = wl_timer_init_priv(timer_params); - if (err) { - TIMER_ERROR(net->name, "Failed to wl_timer_init_priv (%d)\n", err); - goto exit; - } - init_timer_compat(&timer_params->timer, wl_timer_timeout, timer_params); - -exit: - if (err) - wl_timer_dettach(dhdp); - return err; -} -#else -void -wl_timer_mod(dhd_pub_t *dhd, timer_list_compat_t *timer, uint32 tmo_ms) -{ - if (timer_pending(timer)) - del_timer_sync(timer); - if (tmo_ms) - mod_timer(timer, jiffies + msecs_to_jiffies(tmo_ms)); -} - -void -wl_timer_register(struct net_device *net, timer_list_compat_t *timer, void *cb_func) -{ - init_timer_compat(timer, cb_func, net); -} - -void -wl_timer_deregister(struct net_device *net, timer_list_compat_t *timer) -{ - if (timer_pending(timer)) - del_timer_sync(timer); -} -#endif +#include +#ifdef WL_TIMER + +#define TIMER_ERROR(name, arg1, args...) \ + do { \ + if (android_msg_level & ANDROID_ERROR_LEVEL) { \ + printf("[%s] TIMER-ERROR) %s : " arg1, name, __func__, ## args); \ + } \ + } while (0) +#define TIMER_TRACE(name, arg1, args...) \ + do { \ + if (android_msg_level & ANDROID_TRACE_LEVEL) { \ + printf("[%s] TIMER-TRACE) %s : " arg1, name, __func__, ## args); \ + } \ + } while (0) + +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \ + 4 && __GNUC_MINOR__ >= 6)) +#define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \ +_Pragma("GCC diagnostic push") \ +_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \ +(entry) = list_first_entry((ptr), type, member); \ +_Pragma("GCC diagnostic pop") \ + +#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \ +_Pragma("GCC diagnostic push") \ +_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \ +entry = container_of((ptr), type, member); \ +_Pragma("GCC diagnostic pop") \ + +#else +#define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \ +(entry) = list_first_entry((ptr), type, member); \ + +#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \ +entry = container_of((ptr), type, member); \ + +#endif /* STRICT_GCC_WARNINGS */ + +typedef void(*FUNC_HANDLER) (void *cb_argu); + +struct wl_func_q { + struct list_head eq_list; + FUNC_HANDLER cb_func; + void *cb_argu; +}; + +typedef void(*TIMER_HANDLER) (void *cb_argu); + +typedef struct timer_handler_list { + struct list_head list; + struct net_device *net; + timer_list_compat_t *timer; + TIMER_HANDLER cb_func; + void *cb_argu; + uint tmo_ms; + ulong tmo_jiffies; +} timer_handler_list_t; + +typedef struct wl_timer_params { + dhd_pub_t *pub; + struct list_head timer_list; + struct list_head eq_list; + timer_list_compat_t timer; + spinlock_t eq_lock; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) + struct workqueue_struct *timer_workq; + struct work_struct timer_work; + struct workqueue_struct *func_workq; + struct work_struct func_work; +#else + tsk_ctl_t thr_timer_ctl; + tsk_ctl_t thr_func_ctl; +#endif +} wl_timer_params_t; + +static unsigned long +wl_func_lock_eq(struct wl_timer_params *timer_params) +{ + unsigned long flags; + + spin_lock_irqsave(&timer_params->eq_lock, flags); + return flags; +} + +static void +wl_func_unlock_eq(struct wl_timer_params *timer_params, unsigned long flags) +{ + spin_unlock_irqrestore(&timer_params->eq_lock, flags); +} + +static void +wl_func_init_eq_lock(struct wl_timer_params *timer_params) +{ + spin_lock_init(&timer_params->eq_lock); +} + +static void +wl_func_init_eq(struct wl_timer_params *timer_params) +{ + wl_func_init_eq_lock(timer_params); + INIT_LIST_HEAD(&timer_params->eq_list); +} + +static void +wl_func_flush_eq(struct wl_timer_params *timer_params) +{ + struct wl_func_q *e; + unsigned long flags; + + flags = wl_func_lock_eq(timer_params); + while (!list_empty_careful(&timer_params->eq_list)) { + BCM_SET_LIST_FIRST_ENTRY(e, &timer_params->eq_list, struct wl_func_q, eq_list); + list_del(&e->eq_list); + kfree(e); + } + wl_func_unlock_eq(timer_params, flags); +} + +static struct wl_func_q * +wl_func_deq(struct wl_timer_params *timer_params) +{ + struct wl_func_q *e = NULL; + unsigned long flags; + + flags = wl_func_lock_eq(timer_params); + if (likely(!list_empty(&timer_params->eq_list))) { + BCM_SET_LIST_FIRST_ENTRY(e, &timer_params->eq_list, struct wl_func_q, eq_list); + list_del(&e->eq_list); + } + wl_func_unlock_eq(timer_params, flags); + + return e; +} + +static s32 +wl_func_enq(struct wl_timer_params *timer_params, + void *cb_func, void *cb_argu) +{ + struct wl_func_q *e; + s32 err = 0; + uint32 funcq_size; + unsigned long flags; + gfp_t aflags; + + funcq_size = sizeof(struct wl_func_q); + aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; + e = kzalloc(funcq_size, aflags); + if (unlikely(!e)) { + TIMER_ERROR("wlan", "funcq_size alloc failed %d\n", funcq_size); + return -ENOMEM; + } + e->cb_func = cb_func; + e->cb_argu = cb_argu; + flags = wl_func_lock_eq(timer_params); + list_add_tail(&e->eq_list, &timer_params->eq_list); + wl_func_unlock_eq(timer_params, flags); + + return err; +} + +static void +wl_func_put(struct wl_func_q *e) +{ + kfree(e); +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) +static void wl_func_handler(struct work_struct *data); +#define WL_FUNC_HANDLER() static void wl_func_handler(struct work_struct *data) +#else +static int wl_func_handler(void *data); +#define WL_FUNC_HANDLER() static int wl_func_handler(void *data) +#endif + +WL_FUNC_HANDLER() +{ + struct wl_timer_params *timer_params = NULL; + struct wl_func_q *e; + struct net_device *net = NULL; + dhd_pub_t *dhd; + unsigned long flags = 0; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)) + tsk_ctl_t *tsk = (tsk_ctl_t *)data; + timer_params = (struct wl_timer_params *)tsk->parent; +#else + BCM_SET_CONTAINER_OF(timer_params, data, struct wl_timer_params, func_work); +#endif + + dhd = timer_params->pub; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)) + while (1) { + if (down_interruptible(&tsk->sema) == 0) { + SMP_RD_BARRIER_DEPENDS(); + if (tsk->terminated) { + break; + } +#endif + DHD_EVENT_WAKE_LOCK(dhd); + while ((e = wl_func_deq(timer_params))) { + DHD_GENERAL_LOCK(dhd, flags); + if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhd)) { + TIMER_ERROR(net->name, "BUS is DOWN.\n"); + DHD_GENERAL_UNLOCK(dhd, flags); + goto fail; + } + DHD_GENERAL_UNLOCK(dhd, flags); + e->cb_func(e->cb_argu); +fail: + wl_func_put(e); + } + DHD_EVENT_WAKE_UNLOCK(dhd); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)) + } else { + break; + } + } + complete_and_exit(&tsk->completed, 0); +#endif +} + +void +wl_func_send(void *params, void *cb_func, void *cb_argu) +{ + struct wl_timer_params *timer_params = params; + + if (timer_params == NULL) { + TIMER_ERROR("wlan", "Stale ignored\n"); + return; + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) + if (timer_params->func_workq == NULL) { + TIMER_ERROR("wlan", "Event handler is not created\n"); + return; + } +#endif + + if (likely(!wl_func_enq(timer_params, cb_func, cb_argu))) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) + queue_work(timer_params->func_workq, &timer_params->func_work); +#else + if (timer_params->thr_func_ctl.thr_pid >= 0) { + up(&timer_params->thr_func_ctl.sema); + } +#endif + } +} + +static s32 +wl_func_create_handler(struct wl_timer_params *timer_params) +{ + int ret = 0; + TIMER_TRACE("wlan", "Enter\n"); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) + if (!timer_params->func_workq) { + timer_params->func_workq = alloc_workqueue("timer_funcd", + WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_UNBOUND, 0); + } + if (!timer_params->func_workq) { + TIMER_ERROR("wlan", "func_workq alloc_workqueue failed\n"); + ret = -ENOMEM; + } else { + INIT_WORK(&timer_params->func_work, wl_func_handler); + } +#else + PROC_START(wl_func_handler, timer_params, &timer_params->thr_func_ctl, 0, "timer_funcd"); + if (timer_params->thr_func_ctl.thr_pid < 0) { + ret = -ENOMEM; + } +#endif + + return ret; +} + +static void +wl_func_destroy_handler(struct wl_timer_params *timer_params) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) + if (timer_params && timer_params->func_workq) { + cancel_work_sync(&timer_params->func_work); + destroy_workqueue(timer_params->func_workq); + timer_params->func_workq = NULL; + } +#else + if (timer_params->thr_func_ctl.thr_pid >= 0) { + PROC_STOP(&timer_params->thr_func_ctl); + } +#endif +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) +static void wl_timer_handler(struct work_struct *data); +#define WL_TIMER_HANDLER() static void wl_timer_handler(struct work_struct *data) +#else +static int wl_timer_handler(void *data); +#define WL_TIMER_HANDLER() static int wl_timer_handler(void *data) +#endif + +WL_TIMER_HANDLER() +{ + struct wl_timer_params *timer_params = NULL; + struct timer_handler_list *node, *next; + dhd_pub_t *dhd; + unsigned long flags = 0; + unsigned long cur_jiffies, diff_jiffies, min_jiffies = 0; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)) + tsk_ctl_t *tsk = (tsk_ctl_t *)data; + timer_params = (struct wl_timer_params *)tsk->parent; +#else + BCM_SET_CONTAINER_OF(timer_params, data, struct wl_timer_params, timer_work); +#endif + + dhd = timer_params->pub; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)) + while (1) { + if (down_interruptible(&tsk->sema) == 0) { + SMP_RD_BARRIER_DEPENDS(); + if (tsk->terminated) { + break; + } +#endif + DHD_EVENT_WAKE_LOCK(dhd); + DHD_GENERAL_LOCK(dhd, flags); + if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhd)) { + TIMER_ERROR("wlan", "BUS is DOWN.\n"); + DHD_GENERAL_UNLOCK(dhd, flags); + goto exit; + } + DHD_GENERAL_UNLOCK(dhd, flags); + cur_jiffies = jiffies; + list_for_each_entry_safe(node, next, &timer_params->timer_list, list) { + if (node->tmo_ms) { + if (time_after(cur_jiffies, node->tmo_jiffies)) { + wl_func_send(timer_params, node->cb_func, node->cb_argu); + node->tmo_ms = 0; + } else { + diff_jiffies = node->tmo_jiffies - cur_jiffies; + if (min_jiffies == 0) + min_jiffies = diff_jiffies; + else if (diff_jiffies < min_jiffies) + min_jiffies = diff_jiffies; + } + } + } + if (min_jiffies) + mod_timer(&timer_params->timer, jiffies + min_jiffies); +exit: + DHD_EVENT_WAKE_UNLOCK(dhd); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)) + } else { + break; + } + } + complete_and_exit(&tsk->completed, 0); +#endif +} + +void +wl_timer_kick_handler(wl_timer_params_t *timer_params) +{ + if (timer_params == NULL) { + TIMER_ERROR("wlan", "timer_params not ready\n"); + return; + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) + if (timer_params->timer_workq == NULL) { + TIMER_ERROR("wlan", "timer handler is not created\n"); + return; + } + queue_work(timer_params->timer_workq, &timer_params->timer_work); +#else + if (timer_params->thr_timer_ctl.thr_pid >= 0) { + up(&timer_params->thr_timer_ctl.sema); + } +#endif +} + +static void +wl_timer_timeout(unsigned long data) +{ + struct wl_timer_params *timer_params = (struct wl_timer_params *)data; + + if (!timer_params) { + TIMER_ERROR("wlan", "timer_params is not ready\n"); + return; + } + + TIMER_TRACE("wlan", "timer expired\n"); + wl_timer_kick_handler(timer_params); +} + +static s32 +wl_timer_create_handler(struct wl_timer_params *timer_params) +{ + int ret = 0; + + TIMER_TRACE("wlan", "Enter\n"); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) + if (!timer_params->timer_workq) { + timer_params->timer_workq = alloc_workqueue("timerd", + WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_UNBOUND, 0); + } + if (!timer_params->timer_workq) { + TIMER_ERROR("wlan", "timer_workq alloc_workqueue failed\n"); + ret = -ENOMEM; + } else { + INIT_WORK(&timer_params->timer_work, wl_timer_handler); + } +#else + PROC_START(wl_timer_handler, timer_params, &timer_params->thr_timer_ctl, 0, "timerd"); + if (timer_params->thr_timer_ctl.thr_pid < 0) { + ret = -ENOMEM; + } +#endif + + return ret; +} + +static void +wl_timer_destroy_handler(struct wl_timer_params *timer_params) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) + if (timer_params && timer_params->timer_workq) { + cancel_work_sync(&timer_params->timer_work); + destroy_workqueue(timer_params->timer_workq); + timer_params->timer_workq = NULL; + } +#else + if (timer_params->thr_timer_ctl.thr_pid >= 0) { + PROC_STOP(&timer_params->thr_timer_ctl); + } +#endif +} + +static void +wl_timer_free(struct wl_timer_params *timer_params) +{ + timer_handler_list_t *node, *next; + + list_for_each_entry_safe(node, next, &timer_params->timer_list, list) { + TIMER_TRACE(node->net->name, "Free timer\n"); + list_del(&node->list); + kfree(node); + } +} + +void +wl_timer_mod(dhd_pub_t *dhd, timer_list_compat_t *timer, uint32 tmo_ms) +{ + wl_timer_params_t *timer_params = dhd->timer_params; + timer_handler_list_t *node, *next; + bool found = FALSE; + + list_for_each_entry_safe(node, next, &timer_params->timer_list, list) { + if (node->timer == timer) { + node->tmo_ms = tmo_ms; + if (tmo_ms) { + TIMER_TRACE(node->net->name, "update timer %dms\n", tmo_ms); + node->tmo_jiffies = jiffies + msecs_to_jiffies(tmo_ms); + wl_timer_kick_handler(timer_params); + } + found = TRUE; + break; + } + } + if (!found) + TIMER_ERROR("wlan", "timer not found\n"); +} + +void +wl_timer_register(struct net_device *net, timer_list_compat_t *timer, void *cb_func) +{ + dhd_pub_t *dhd = dhd_get_pub(net); + wl_timer_params_t *timer_params = dhd->timer_params; + timer_handler_list_t *node, *next, *leaf; + + list_for_each_entry_safe(node, next, &timer_params->timer_list, list) { + if (node->timer == timer) { + TIMER_TRACE(net->name, "timer already registered\n"); + return; + } + } + + leaf = kmalloc(sizeof(timer_handler_list_t), GFP_KERNEL); + if (!leaf) { + TIMER_ERROR(net->name, "Memory alloc failure %d\n", + (int)sizeof(timer_handler_list_t)); + return; + } + memset(leaf, 0, sizeof(timer_handler_list_t)); + leaf->net = net; + leaf->timer = timer; + leaf->cb_func = cb_func; + leaf->cb_argu = net; + TIMER_ERROR(net->name, "timer registered tmo=%d\n", leaf->tmo_ms); + list_add_tail(&leaf->list, &timer_params->timer_list); + + return; +} + +void +wl_timer_deregister(struct net_device *net, timer_list_compat_t *timer) +{ + dhd_pub_t *dhd = dhd_get_pub(net); + wl_timer_params_t *timer_params = dhd->timer_params; + timer_handler_list_t *node, *next; + + list_for_each_entry_safe(node, next, &timer_params->timer_list, list) { + if (node->timer == timer) { + TIMER_TRACE(net->name, "timer deregistered\n"); + list_del(&node->list); + kfree(node); + } + } + return; +} + +static s32 +wl_timer_init_priv(struct wl_timer_params *timer_params) +{ + s32 err = 0; + + INIT_LIST_HEAD(&timer_params->timer_list); + if (wl_timer_create_handler(timer_params)) + return -ENOMEM; + wl_func_init_eq(timer_params); + if (wl_func_create_handler(timer_params)) + return -ENOMEM; + + return err; +} + +static void +wl_timer_deinit_priv(struct wl_timer_params *timer_params) +{ + wl_timer_free(timer_params); + wl_func_destroy_handler(timer_params); + wl_func_flush_eq(timer_params); + wl_timer_destroy_handler(timer_params); +} + +void +wl_timer_dettach(dhd_pub_t *dhdp) +{ + struct wl_timer_params *timer_params = dhdp->timer_params; + + if (timer_params) { + if (timer_pending(&timer_params->timer)) + del_timer_sync(&timer_params->timer); + wl_timer_deinit_priv(timer_params); + kfree(timer_params); + dhdp->timer_params = NULL; + } +} + +s32 +wl_timer_attach(struct net_device *net) +{ + struct dhd_pub *dhdp = dhd_get_pub(net); + struct wl_timer_params *timer_params = NULL; + s32 err = 0; + + timer_params = kmalloc(sizeof(wl_timer_params_t), GFP_KERNEL); + if (!timer_params) { + TIMER_ERROR(net->name, "Failed to allocate memory (%zu)\n", + sizeof(wl_timer_params_t)); + return -ENOMEM; + } + dhdp->timer_params = timer_params; + memset(timer_params, 0, sizeof(wl_timer_params_t)); + timer_params->pub = dhdp; + + err = wl_timer_init_priv(timer_params); + if (err) { + TIMER_ERROR(net->name, "Failed to wl_timer_init_priv (%d)\n", err); + goto exit; + } + init_timer_compat(&timer_params->timer, wl_timer_timeout, timer_params); + +exit: + if (err) + wl_timer_dettach(dhdp); + return err; +} +#else +void +wl_timer_mod(dhd_pub_t *dhd, timer_list_compat_t *timer, uint32 tmo_ms) +{ + if (timer_pending(timer)) + del_timer_sync(timer); + if (tmo_ms) + mod_timer(timer, jiffies + msecs_to_jiffies(tmo_ms)); +} + +void +wl_timer_register(struct net_device *net, timer_list_compat_t *timer, void *cb_func) +{ + init_timer_compat(timer, cb_func, net); +} + +void +wl_timer_deregister(struct net_device *net, timer_list_compat_t *timer) +{ + if (timer_pending(timer)) + del_timer_sync(timer); +} +#endif diff --git a/bcmdhd.101.10.361.x/wl_timer.h b/bcmdhd.101.10.361.x/wl_timer.h index 97997f4..6b43384 100755 --- a/bcmdhd.101.10.361.x/wl_timer.h +++ b/bcmdhd.101.10.361.x/wl_timer.h @@ -1,8 +1,8 @@ -#ifndef _wl_timer_ -#define _wl_timer_ -s32 wl_timer_attach(struct net_device *net); -void wl_timer_dettach(dhd_pub_t *dhdp); -void wl_timer_register(struct net_device *net, timer_list_compat_t *timer, void *cb_func); -void wl_timer_deregister(struct net_device *net, timer_list_compat_t *timer); -void wl_timer_mod(dhd_pub_t *dhd, timer_list_compat_t *timer, uint32 tmo_ms); -#endif +#ifndef _wl_timer_ +#define _wl_timer_ +s32 wl_timer_attach(struct net_device *net); +void wl_timer_dettach(dhd_pub_t *dhdp); +void wl_timer_register(struct net_device *net, timer_list_compat_t *timer, void *cb_func); +void wl_timer_deregister(struct net_device *net, timer_list_compat_t *timer); +void wl_timer_mod(dhd_pub_t *dhd, timer_list_compat_t *timer, uint32 tmo_ms); +#endif