wifi: update driver for 62x8 not use bcmdl tool [1/2]
authorjiabin.chen <jiabin.chen@amlogic.com>
Tue, 9 May 2023 05:17:21 +0000 (13:17 +0800)
committerBruno Martins <bgcngm@gmail.com>
Thu, 25 Apr 2024 17:39:34 +0000 (18:39 +0100)
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 <jiabin.chen@amlogic.com>
33 files changed:
bcmdhd.101.10.361.x/Makefile
bcmdhd.101.10.361.x/bcmevent.c
bcmdhd.101.10.361.x/bcmsdh_sdmmc.c
bcmdhd.101.10.361.x/dbus.c
bcmdhd.101.10.361.x/dhd_cdc.c
bcmdhd.101.10.361.x/dhd_common.c
bcmdhd.101.10.361.x/dhd_config.c
bcmdhd.101.10.361.x/dhd_config.h
bcmdhd.101.10.361.x/dhd_debug.c
bcmdhd.101.10.361.x/dhd_gpio.c
bcmdhd.101.10.361.x/dhd_linux.c
bcmdhd.101.10.361.x/dhd_linux_platdev.c
bcmdhd.101.10.361.x/dhd_msgbuf.c
bcmdhd.101.10.361.x/dhd_pcie.c
bcmdhd.101.10.361.x/dhd_pcie_linux.c
bcmdhd.101.10.361.x/dhd_sdio.c
bcmdhd.101.10.361.x/dhd_static_buf.c
bcmdhd.101.10.361.x/include/bcmevent.h
bcmdhd.101.10.361.x/include/epivers.h
bcmdhd.101.10.361.x/include/wlioctl.h
bcmdhd.101.10.361.x/wl_android.c
bcmdhd.101.10.361.x/wl_android_ext.c
bcmdhd.101.10.361.x/wl_cfg80211.c
bcmdhd.101.10.361.x/wl_cfg80211.h
bcmdhd.101.10.361.x/wl_cfgscan.c
bcmdhd.101.10.361.x/wl_cfgvendor.c
bcmdhd.101.10.361.x/wl_cfgvendor.h
bcmdhd.101.10.361.x/wl_cfgvif.c
bcmdhd.101.10.361.x/wl_cfgvif.h
bcmdhd.101.10.361.x/wl_iapsta.c
bcmdhd.101.10.361.x/wl_iapsta.h
bcmdhd.101.10.361.x/wl_timer.c
bcmdhd.101.10.361.x/wl_timer.h

index 42393f44e01750e133c1a2d5ddcab4ec2bd6655e..8f8e8e5543235ceefad18493b0940a639e78a90e 100755 (executable)
@@ -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
index 61009d32fb3cc22e8730aa9d60ff1b8fe5c886e6..20397699253cced4d1ff3940948ca9600cef5204 100755 (executable)
@@ -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)
index a1dcf333cda0f9b75e4d532da3747138da13ccca..d4b6878d306396af8df06d4a7b22bbc418a825af 100755 (executable)
@@ -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
index d15b758d2687c9f2a68c56dd5cde4b48d841a6e3..40a4b8c4f70c18e4eca63a258be0a7d8b72c4b1a 100755 (executable)
@@ -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);
index a81d49fc8c90036ecfe6cbb309272fc9bd4ce839..8a4bf27e24115c0fd630fadba32420b88f936040 100755 (executable)
@@ -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;
index 2c465d3aa782320cbfdf6300718073b69aa4a50d..680b791df97214a20c9286e8a91c2a22ba4219f5 100755 (executable)
@@ -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,
index a91aecc57ab4450465ded16748d5796a57895598..4df7ca30557f68ddbb63122ff5f01b8c223f7d96 100755 (executable)
@@ -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
index 522d760631808da9b36290533224ac77bdcf687a..e33e8c78b9930728372b3517a22310e1a40efc4a 100755 (executable)
@@ -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);
index 6ab232699f896e96ac68f6c7680f6b96734d287f..2a40a53f0890c488f56d8a3f35a26330184f306c 100755 (executable)
@@ -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
index 594afbb0155892083eaa7451c90eca52e4dfe658..211e7a0dfd80825596cd54fe4611d597e6337012 100755 (executable)
@@ -9,18 +9,7 @@
 #include <linux/platform_device.h>
 #endif
 
-#if defined(BUS_POWER_RESTORE) && defined(BCMSDIO)
-#include <linux/mmc/core.h>
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/sdio_func.h>
-#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);
 }
index 41609301fd31ae5e4e9ddcc8d79155820bb9755c..e54223c388278fac4cee041090bfe481d261ebc7 100755 (executable)
@@ -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(&ether_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(&ether_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);
index afecfa9a985b387eae431401dca356888ce5d90a..8d65e48f4f9c2a6a2c36c7f81663cd990382d48f 100755 (executable)
@@ -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];
index 1b6b7ceaaef27834d5407e9b1b721c47cd2b8630..c9c70c2415b4fa7edb17b00c9a78437108bf7378 100755 (executable)
@@ -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() */
index c5f687a5f4f36e65e4860be7bf51d58185e8486d..ee82a99c5051be16ac4b139873127de9ec4c0641 100755 (executable)
@@ -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));
 
index 0e681adcb1e33e2135b4aaeab08dff8f3486dbbd..071308b8fb2e9ed931acc4f213d87ac059279cbd 100755 (executable)
@@ -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 */
 
index bda7b2c06e15c96cdd613e3be72f225fca7850ce..9fb997a5eb026d1e76a5d2766f9e3db59daf96e8 100755 (executable)
@@ -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;
index 9bc63bfd5dd80ba0224e841be908eb7ae864c729..b565b905216e7d50403a8931c3526e345e3a31a8 100755 (executable)
@@ -13,7 +13,7 @@
 #include <linux/amlogic/wlan_plat.h>
 #include <linux/amlogic/dhd_buf.h>
 
-#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;
 }
index a2fbbd63d6747b909c7fcfef97441e6779d5c91f..6b70c0fb1b44248f29dab04cb1be73d12189d040 100755 (executable)
@@ -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 */
index d09f7e26a243da9ad67c87c7a2f51b34dc42d1f0..20617705a4f889af403d0cfc8e131eae3a09c139 100755 (executable)
@@ -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_ */
index 72c9d9fb67c5a4a99ad2ad61b4bd05b7891ea24a..18263e69c2214512fef2c2ff4df2e21b14dea34a 100755 (executable)
@@ -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
index ec37154b69f41eb305c2220cea761730d8f0ddcb..b108fcab53b89e204b79582c46faf5715ba6c7ce 100755 (executable)
@@ -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]) {
index 3a4a553f39e95a97af8de0382b5dc75b9d3ffc86..54d85464bddcbd1b5aee3ba421118c8c9ee51996 100755 (executable)
@@ -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(&notify, 0, sizeof(notify));
-               memset(frame_str, 0, sizeof(frame_str));
                sscanf(data, "%d %s", &notify.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")) {
index 030fa4451d9d2e0e0bd30ff9b0f39bf4d906558f..f623aed0c4da7d40d52d8abfb688b51806ba6260 100755 (executable)
@@ -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;
                }
        }
index 35ab3aff453e504eb60d14bab0b799527e38a30d..d05482b99c14e948a10bc86e954b54b620914fbc 100755 (executable)
@@ -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
index 606f32767ce8061cd353b068a4e3884b468f007e..85eb430c68d937ca7bd037afddec5b7e926dcdc5 100755 (executable)
@@ -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 && i<WL_AP_MAX; i++) {
@@ -4384,7 +4384,7 @@ wl_cfgscan_update_v3_schedscan_results(struct bcm_cfg80211 *cfg, struct net_devi
                        err = wl_cfgp2p_discover_enable_search(cfg, false);
                        if (unlikely(err)) {
                                wl_clr_drv_status(cfg, SCANNING, ndev);
-                               return err;
+                               goto out_err;
                        }
                        p2p_scan(cfg) = false;
                }
@@ -5033,7 +5033,8 @@ wl_cfgscan_cancel_listen_on_channel(struct bcm_cfg80211 *cfg, bool notify_user)
        }
 
        /* abort scan listen */
-       _wl_cfgscan_cancel_scan(cfg);
+       /* change _wl_cfgscan_cancel_scan() to wl_cfgscan_scan_abort() to fix DPP connection issue on Android 12 */
+       wl_cfgscan_scan_abort(cfg);
 
        if (notify_user) {
                wl_cfgscan_notify_listen_complete(cfg);
index efba80fb5bd62ace6119b0a3948a90277ca9ef30..71c16f8f1c9d4fd8a6511cefa83304bb9620c5fe 100755 (executable)
@@ -1262,6 +1262,7 @@ wl_cfgvendor_gscan_get_channel_list(struct wiphy *wiphy,
        } else if (err == BCME_OK) {
                reply_len = (num_channels * sizeof(uint32));
        } else if (err == BCME_UNSUPPORTED) {
+               MFREE(cfg->osh, 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 },
index c66c6d5db952964d2984e5f0efe7ad40e169b799..5c78e2f6090670d47622f796dc24c26ab05757d3 100755 (executable)
@@ -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
index 0af2e0ffc284f7da01db960255755dd7cdf26cd2..12ce31cc3f9ae29af9ab7e6f7b5e67c41ed716a3 100755 (executable)
@@ -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)
 {
index a81df9fb9f1742336a35fcd9965a645719f5e15f..c949c10edfdc725fea1b0eb0eb561cca9b01e380 100755 (executable)
@@ -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_ */
index 06053e6d1a7cc102fa78421f5c3e681da3390509..f6a5424793abe2d1edc706148466382858627378 100755 (executable)
@@ -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; i<MAX_IF_NUM; i++) {
+                       tmp_if = &apsta_params->if_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; i<MAX_IF_NUM; i++) {
+               tmp_if = &apsta_params->if_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) {
index f88c6e7581f79d6e204795cb2022836350d689b4..26eb7e7d0da8729419e2a9cd262956e9b86de4b5 100755 (executable)
@@ -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);
index e9ea4d8cd92f01187fcb6a1b00e35f6e256355dd..0255acd55fbd25cc0d90be518ffc312b137f40b9 100755 (executable)
-#include <wl_android.h>\r
-#ifdef WL_TIMER\r
-\r
-#define TIMER_ERROR(name, arg1, args...) \\r
-       do { \\r
-               if (android_msg_level & ANDROID_ERROR_LEVEL) { \\r
-                       printf("[%s] TIMER-ERROR) %s : " arg1, name, __func__, ## args); \\r
-               } \\r
-       } while (0)\r
-#define TIMER_TRACE(name, arg1, args...) \\r
-       do { \\r
-               if (android_msg_level & ANDROID_TRACE_LEVEL) { \\r
-                       printf("[%s] TIMER-TRACE) %s : " arg1, name, __func__, ## args); \\r
-               } \\r
-       } while (0)\r
-\r
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \\r
-       4 && __GNUC_MINOR__ >= 6))\r
-#define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \\r
-_Pragma("GCC diagnostic push") \\r
-_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \\r
-(entry) = list_first_entry((ptr), type, member); \\r
-_Pragma("GCC diagnostic pop") \\r
-\r
-#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \\r
-_Pragma("GCC diagnostic push") \\r
-_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \\r
-entry = container_of((ptr), type, member); \\r
-_Pragma("GCC diagnostic pop") \\r
-\r
-#else\r
-#define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \\r
-(entry) = list_first_entry((ptr), type, member); \\r
-\r
-#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \\r
-entry = container_of((ptr), type, member); \\r
-\r
-#endif /* STRICT_GCC_WARNINGS */\r
-\r
-typedef void(*FUNC_HANDLER) (void *cb_argu);\r
-\r
-struct wl_func_q {\r
-       struct list_head eq_list;\r
-       FUNC_HANDLER cb_func;\r
-       void *cb_argu;\r
-};\r
-\r
-typedef void(*TIMER_HANDLER) (void *cb_argu);\r
-\r
-typedef struct timer_handler_list {\r
-       struct list_head list;\r
-       struct net_device *net;\r
-       timer_list_compat_t *timer;\r
-       TIMER_HANDLER cb_func;\r
-       void *cb_argu;\r
-       uint tmo_ms;\r
-       ulong tmo_jiffies;\r
-} timer_handler_list_t;\r
-\r
-typedef struct wl_timer_params {\r
-       dhd_pub_t *pub;\r
-       struct list_head timer_list;\r
-       struct list_head eq_list;\r
-       timer_list_compat_t timer;\r
-       spinlock_t eq_lock;\r
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
-       struct workqueue_struct *timer_workq;\r
-       struct work_struct timer_work;\r
-       struct workqueue_struct *func_workq;\r
-       struct work_struct func_work;\r
-#else\r
-       tsk_ctl_t thr_timer_ctl;\r
-       tsk_ctl_t thr_func_ctl;\r
-#endif\r
-} wl_timer_params_t;\r
-\r
-static unsigned long\r
-wl_func_lock_eq(struct wl_timer_params *timer_params)\r
-{\r
-       unsigned long flags;\r
-\r
-       spin_lock_irqsave(&timer_params->eq_lock, flags);\r
-       return flags;\r
-}\r
-\r
-static void\r
-wl_func_unlock_eq(struct wl_timer_params *timer_params, unsigned long flags)\r
-{\r
-       spin_unlock_irqrestore(&timer_params->eq_lock, flags);\r
-}\r
-\r
-static void\r
-wl_func_init_eq_lock(struct wl_timer_params *timer_params)\r
-{\r
-       spin_lock_init(&timer_params->eq_lock);\r
-}\r
-\r
-static void\r
-wl_func_init_eq(struct wl_timer_params *timer_params)\r
-{\r
-       wl_func_init_eq_lock(timer_params);\r
-       INIT_LIST_HEAD(&timer_params->eq_list);\r
-}\r
-\r
-static void\r
-wl_func_flush_eq(struct wl_timer_params *timer_params)\r
-{\r
-       struct wl_func_q *e;\r
-       unsigned long flags;\r
-\r
-       flags = wl_func_lock_eq(timer_params);\r
-       while (!list_empty_careful(&timer_params->eq_list)) {\r
-               BCM_SET_LIST_FIRST_ENTRY(e, &timer_params->eq_list, struct wl_func_q, eq_list);\r
-               list_del(&e->eq_list);\r
-               kfree(e);\r
-       }\r
-       wl_func_unlock_eq(timer_params, flags);\r
-}\r
-\r
-static struct wl_func_q *\r
-wl_func_deq(struct wl_timer_params *timer_params)\r
-{\r
-       struct wl_func_q *e = NULL;\r
-       unsigned long flags;\r
-\r
-       flags = wl_func_lock_eq(timer_params);\r
-       if (likely(!list_empty(&timer_params->eq_list))) {\r
-               BCM_SET_LIST_FIRST_ENTRY(e, &timer_params->eq_list, struct wl_func_q, eq_list);\r
-               list_del(&e->eq_list);\r
-       }\r
-       wl_func_unlock_eq(timer_params, flags);\r
-\r
-       return e;\r
-}\r
-\r
-static s32\r
-wl_func_enq(struct wl_timer_params *timer_params,\r
-       void *cb_func, void *cb_argu)\r
-{\r
-       struct wl_func_q *e;\r
-       s32 err = 0;\r
-       uint32 funcq_size;\r
-       unsigned long flags;\r
-       gfp_t aflags;\r
-\r
-       funcq_size = sizeof(struct wl_func_q);\r
-       aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;\r
-       e = kzalloc(funcq_size, aflags);\r
-       if (unlikely(!e)) {\r
-               TIMER_ERROR("wlan", "funcq_size alloc failed %d\n", funcq_size);\r
-               return -ENOMEM;\r
-       }\r
-       e->cb_func = cb_func;\r
-       e->cb_argu = cb_argu;\r
-       flags = wl_func_lock_eq(timer_params);\r
-       list_add_tail(&e->eq_list, &timer_params->eq_list);\r
-       wl_func_unlock_eq(timer_params, flags);\r
-\r
-       return err;\r
-}\r
-\r
-static void\r
-wl_func_put(struct wl_func_q *e)\r
-{\r
-       kfree(e);\r
-}\r
-\r
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
-static void wl_func_handler(struct work_struct *data);\r
-#define WL_FUNC_HANDLER() static void wl_func_handler(struct work_struct *data)\r
-#else\r
-static int wl_func_handler(void *data);\r
-#define WL_FUNC_HANDLER() static int wl_func_handler(void *data)\r
-#endif\r
-\r
-WL_FUNC_HANDLER()\r
-{\r
-       struct wl_timer_params *timer_params = NULL;\r
-       struct wl_func_q *e;\r
-       struct net_device *net = NULL;\r
-       dhd_pub_t *dhd;\r
-       unsigned long flags = 0;\r
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))\r
-       tsk_ctl_t *tsk = (tsk_ctl_t *)data;\r
-       timer_params = (struct wl_timer_params *)tsk->parent;\r
-#else\r
-       BCM_SET_CONTAINER_OF(timer_params, data, struct wl_timer_params, func_work);\r
-#endif\r
-\r
-       dhd = timer_params->pub;\r
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))\r
-       while (1) {\r
-       if (down_interruptible(&tsk->sema) == 0) {\r
-               SMP_RD_BARRIER_DEPENDS();\r
-               if (tsk->terminated) {\r
-                       break;\r
-               }\r
-#endif\r
-       DHD_EVENT_WAKE_LOCK(dhd);\r
-       while ((e = wl_func_deq(timer_params))) {\r
-               DHD_GENERAL_LOCK(dhd, flags);\r
-               if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhd)) {\r
-                       TIMER_ERROR(net->name, "BUS is DOWN.\n");\r
-                       DHD_GENERAL_UNLOCK(dhd, flags);\r
-                       goto fail;\r
-               }\r
-               DHD_GENERAL_UNLOCK(dhd, flags);\r
-               e->cb_func(e->cb_argu);\r
-fail:\r
-               wl_func_put(e);\r
-       }\r
-       DHD_EVENT_WAKE_UNLOCK(dhd);\r
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))\r
-       } else {\r
-               break;\r
-       }\r
-       }\r
-       complete_and_exit(&tsk->completed, 0);\r
-#endif\r
-}\r
-\r
-void\r
-wl_func_send(void *params, void *cb_func, void *cb_argu)\r
-{\r
-       struct wl_timer_params *timer_params = params;\r
-\r
-       if (timer_params == NULL) {\r
-               TIMER_ERROR("wlan", "Stale ignored\n");\r
-               return;\r
-       }\r
-\r
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
-       if (timer_params->func_workq == NULL) {\r
-               TIMER_ERROR("wlan", "Event handler is not created\n");\r
-               return;\r
-       }\r
-#endif\r
-\r
-       if (likely(!wl_func_enq(timer_params, cb_func, cb_argu))) {\r
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
-               queue_work(timer_params->func_workq, &timer_params->func_work);\r
-#else\r
-               if (timer_params->thr_func_ctl.thr_pid >= 0) {\r
-                       up(&timer_params->thr_func_ctl.sema);\r
-               }\r
-#endif\r
-       }\r
-}\r
-\r
-static s32\r
-wl_func_create_handler(struct wl_timer_params *timer_params)\r
-{\r
-       int ret = 0;\r
-       TIMER_TRACE("wlan", "Enter\n");\r
-\r
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
-       if (!timer_params->func_workq) {\r
-               timer_params->func_workq = alloc_workqueue("timer_funcd",\r
-                       WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_UNBOUND, 0);\r
-       }\r
-       if (!timer_params->func_workq) {\r
-               TIMER_ERROR("wlan", "func_workq alloc_workqueue failed\n");\r
-               ret = -ENOMEM;\r
-       } else {\r
-               INIT_WORK(&timer_params->func_work, wl_func_handler);\r
-       }\r
-#else\r
-       PROC_START(wl_func_handler, timer_params, &timer_params->thr_func_ctl, 0, "timer_funcd");\r
-       if (timer_params->thr_func_ctl.thr_pid < 0) {\r
-               ret = -ENOMEM;\r
-       }\r
-#endif\r
-\r
-       return ret;\r
-}\r
-\r
-static void\r
-wl_func_destroy_handler(struct wl_timer_params *timer_params)\r
-{\r
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
-       if (timer_params && timer_params->func_workq) {\r
-               cancel_work_sync(&timer_params->func_work);\r
-               destroy_workqueue(timer_params->func_workq);\r
-               timer_params->func_workq = NULL;\r
-       }\r
-#else\r
-       if (timer_params->thr_func_ctl.thr_pid >= 0) {\r
-               PROC_STOP(&timer_params->thr_func_ctl);\r
-       }\r
-#endif\r
-}\r
-\r
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
-static void wl_timer_handler(struct work_struct *data);\r
-#define WL_TIMER_HANDLER() static void wl_timer_handler(struct work_struct *data)\r
-#else\r
-static int wl_timer_handler(void *data);\r
-#define WL_TIMER_HANDLER() static int wl_timer_handler(void *data)\r
-#endif\r
-\r
-WL_TIMER_HANDLER()\r
-{\r
-       struct wl_timer_params *timer_params = NULL;\r
-       struct timer_handler_list *node, *next;\r
-       dhd_pub_t *dhd;\r
-       unsigned long flags = 0;\r
-       unsigned long cur_jiffies, diff_jiffies, min_jiffies = 0;\r
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))\r
-       tsk_ctl_t *tsk = (tsk_ctl_t *)data;\r
-       timer_params = (struct wl_timer_params *)tsk->parent;\r
-#else\r
-       BCM_SET_CONTAINER_OF(timer_params, data, struct wl_timer_params, timer_work);\r
-#endif\r
-\r
-       dhd = timer_params->pub;\r
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))\r
-       while (1) {\r
-       if (down_interruptible(&tsk->sema) == 0) {\r
-               SMP_RD_BARRIER_DEPENDS();\r
-               if (tsk->terminated) {\r
-                       break;\r
-               }\r
-#endif\r
-       DHD_EVENT_WAKE_LOCK(dhd);\r
-       DHD_GENERAL_LOCK(dhd, flags);\r
-       if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhd)) {\r
-               TIMER_ERROR("wlan", "BUS is DOWN.\n");\r
-               DHD_GENERAL_UNLOCK(dhd, flags);\r
-               goto exit;\r
-       }\r
-       DHD_GENERAL_UNLOCK(dhd, flags);\r
-       cur_jiffies = jiffies;\r
-       list_for_each_entry_safe(node, next, &timer_params->timer_list, list) {\r
-               if (node->tmo_ms) {\r
-                       if (time_after(cur_jiffies, node->tmo_jiffies)) {\r
-                               wl_func_send(timer_params, node->cb_func, node->cb_argu);\r
-                               node->tmo_ms = 0;\r
-                       } else {\r
-                               diff_jiffies = node->tmo_jiffies - cur_jiffies;\r
-                               if (min_jiffies == 0)\r
-                                       min_jiffies = diff_jiffies;\r
-                               else if (diff_jiffies < min_jiffies)\r
-                                       min_jiffies = diff_jiffies;\r
-                       }\r
-               }\r
-       }\r
-       if (min_jiffies)\r
-               mod_timer(&timer_params->timer, jiffies + min_jiffies);\r
-exit:\r
-       DHD_EVENT_WAKE_UNLOCK(dhd);\r
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))\r
-       } else {\r
-               break;\r
-       }\r
-       }\r
-       complete_and_exit(&tsk->completed, 0);\r
-#endif\r
-}\r
-\r
-void\r
-wl_timer_kick_handler(wl_timer_params_t *timer_params)\r
-{\r
-       if (timer_params == NULL) {\r
-               TIMER_ERROR("wlan", "timer_params not ready\n");\r
-               return;\r
-       }\r
-\r
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
-       if (timer_params->timer_workq == NULL) {\r
-               TIMER_ERROR("wlan", "timer handler is not created\n");\r
-               return;\r
-       }\r
-       queue_work(timer_params->timer_workq, &timer_params->timer_work);\r
-#else\r
-       if (timer_params->thr_timer_ctl.thr_pid >= 0) {\r
-               up(&timer_params->thr_timer_ctl.sema);\r
-       }\r
-#endif\r
-}\r
-\r
-static void\r
-wl_timer_timeout(unsigned long data)\r
-{\r
-       struct wl_timer_params *timer_params = (struct wl_timer_params *)data;\r
-\r
-       if (!timer_params) {\r
-               TIMER_ERROR("wlan", "timer_params is not ready\n");\r
-               return;\r
-       }\r
-\r
-       TIMER_TRACE("wlan", "timer expired\n");\r
-       wl_timer_kick_handler(timer_params);\r
-}\r
-\r
-static s32\r
-wl_timer_create_handler(struct wl_timer_params *timer_params)\r
-{\r
-       int ret = 0;\r
-\r
-       TIMER_TRACE("wlan", "Enter\n");\r
-       \r
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
-       if (!timer_params->timer_workq) {\r
-               timer_params->timer_workq = alloc_workqueue("timerd",\r
-                       WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_UNBOUND, 0);\r
-       }\r
-       if (!timer_params->timer_workq) {\r
-               TIMER_ERROR("wlan", "timer_workq alloc_workqueue failed\n");\r
-               ret = -ENOMEM;\r
-       } else {\r
-               INIT_WORK(&timer_params->timer_work, wl_timer_handler);\r
-       }\r
-#else\r
-       PROC_START(wl_timer_handler, timer_params, &timer_params->thr_timer_ctl, 0, "timerd");\r
-       if (timer_params->thr_timer_ctl.thr_pid < 0) {\r
-               ret = -ENOMEM;\r
-       }\r
-#endif\r
-\r
-       return ret;\r
-}\r
-\r
-static void\r
-wl_timer_destroy_handler(struct wl_timer_params *timer_params)\r
-{\r
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
-       if (timer_params && timer_params->timer_workq) {\r
-               cancel_work_sync(&timer_params->timer_work);\r
-               destroy_workqueue(timer_params->timer_workq);\r
-               timer_params->timer_workq = NULL;\r
-       }\r
-#else\r
-       if (timer_params->thr_timer_ctl.thr_pid >= 0) {\r
-               PROC_STOP(&timer_params->thr_timer_ctl);\r
-       }\r
-#endif\r
-}\r
-\r
-static void\r
-wl_timer_free(struct wl_timer_params *timer_params)\r
-{\r
-       timer_handler_list_t *node, *next;\r
-\r
-       list_for_each_entry_safe(node, next, &timer_params->timer_list, list) {\r
-               TIMER_TRACE(node->net->name, "Free timer\n");\r
-               list_del(&node->list);\r
-               kfree(node);\r
-       }\r
-}\r
-\r
-void\r
-wl_timer_mod(dhd_pub_t *dhd, timer_list_compat_t *timer, uint32 tmo_ms)\r
-{\r
-       wl_timer_params_t *timer_params = dhd->timer_params;\r
-       timer_handler_list_t *node, *next;\r
-       bool found = FALSE;\r
-\r
-       list_for_each_entry_safe(node, next, &timer_params->timer_list, list) {\r
-               if (node->timer == timer) {\r
-                       node->tmo_ms = tmo_ms;\r
-                       if (tmo_ms) {\r
-                               TIMER_TRACE(node->net->name, "update timer %dms\n", tmo_ms);\r
-                               node->tmo_jiffies = jiffies + msecs_to_jiffies(tmo_ms);\r
-                               wl_timer_kick_handler(timer_params);\r
-                       }\r
-                       found = TRUE;\r
-                       break;\r
-               }\r
-       }\r
-       if (!found)\r
-               TIMER_ERROR("wlan", "timer not found\n");\r
-}\r
-\r
-void\r
-wl_timer_register(struct net_device *net, timer_list_compat_t *timer, void *cb_func)\r
-{\r
-       dhd_pub_t *dhd = dhd_get_pub(net);\r
-       wl_timer_params_t *timer_params = dhd->timer_params;\r
-       timer_handler_list_t *node, *next, *leaf;\r
-\r
-       list_for_each_entry_safe(node, next, &timer_params->timer_list, list) {\r
-               if (node->timer == timer) {\r
-                       TIMER_TRACE(net->name, "timer already registered\n");\r
-                       return;\r
-               }\r
-       }\r
-\r
-       leaf = kmalloc(sizeof(timer_handler_list_t), GFP_KERNEL);\r
-       if (!leaf) {\r
-               TIMER_ERROR(net->name, "Memory alloc failure %d\n",\r
-                       (int)sizeof(timer_handler_list_t));\r
-               return;\r
-       }\r
-       memset(leaf, 0, sizeof(timer_handler_list_t));\r
-       leaf->net = net;\r
-       leaf->timer = timer;\r
-       leaf->cb_func = cb_func;\r
-       leaf->cb_argu = net;\r
-       TIMER_ERROR(net->name, "timer registered tmo=%d\n", leaf->tmo_ms);\r
-       list_add_tail(&leaf->list, &timer_params->timer_list);\r
-\r
-       return;\r
-}\r
-\r
-void\r
-wl_timer_deregister(struct net_device *net, timer_list_compat_t *timer)\r
-{\r
-       dhd_pub_t *dhd = dhd_get_pub(net);\r
-       wl_timer_params_t *timer_params = dhd->timer_params;\r
-       timer_handler_list_t *node, *next;\r
-\r
-       list_for_each_entry_safe(node, next, &timer_params->timer_list, list) {\r
-               if (node->timer == timer) {\r
-                       TIMER_TRACE(net->name, "timer deregistered\n");\r
-                       list_del(&node->list);\r
-                       kfree(node);\r
-               }\r
-       }\r
-       return;\r
-}\r
-\r
-static s32\r
-wl_timer_init_priv(struct wl_timer_params *timer_params)\r
-{\r
-       s32 err = 0;\r
-\r
-       INIT_LIST_HEAD(&timer_params->timer_list);\r
-       if (wl_timer_create_handler(timer_params))\r
-               return -ENOMEM;\r
-       wl_func_init_eq(timer_params);\r
-       if (wl_func_create_handler(timer_params))\r
-               return -ENOMEM;\r
-\r
-       return err;\r
-}\r
-\r
-static void\r
-wl_timer_deinit_priv(struct wl_timer_params *timer_params)\r
-{\r
-       wl_timer_free(timer_params);\r
-       wl_func_destroy_handler(timer_params);\r
-       wl_func_flush_eq(timer_params);\r
-       wl_timer_destroy_handler(timer_params);\r
-}\r
-\r
-void\r
-wl_timer_dettach(dhd_pub_t *dhdp)\r
-{\r
-       struct wl_timer_params *timer_params = dhdp->timer_params;\r
-\r
-       if (timer_params) {\r
-               if (timer_pending(&timer_params->timer))\r
-                       del_timer_sync(&timer_params->timer);\r
-               wl_timer_deinit_priv(timer_params);\r
-               kfree(timer_params);\r
-               dhdp->timer_params = NULL;\r
-       }\r
-}\r
-\r
-s32\r
-wl_timer_attach(struct net_device *net)\r
-{\r
-       struct dhd_pub *dhdp = dhd_get_pub(net);\r
-       struct wl_timer_params *timer_params = NULL;\r
-       s32 err = 0;\r
-\r
-       timer_params = kmalloc(sizeof(wl_timer_params_t), GFP_KERNEL);\r
-       if (!timer_params) {\r
-               TIMER_ERROR(net->name, "Failed to allocate memory (%zu)\n",\r
-                       sizeof(wl_timer_params_t));\r
-               return -ENOMEM;\r
-       }\r
-       dhdp->timer_params = timer_params;\r
-       memset(timer_params, 0, sizeof(wl_timer_params_t));\r
-       timer_params->pub = dhdp;\r
-\r
-       err = wl_timer_init_priv(timer_params);\r
-       if (err) {\r
-               TIMER_ERROR(net->name, "Failed to wl_timer_init_priv (%d)\n", err);\r
-               goto exit;\r
-       }\r
-       init_timer_compat(&timer_params->timer, wl_timer_timeout, timer_params);\r
-\r
-exit:\r
-       if (err)\r
-               wl_timer_dettach(dhdp);\r
-       return err;\r
-}\r
-#else\r
-void\r
-wl_timer_mod(dhd_pub_t *dhd, timer_list_compat_t *timer, uint32 tmo_ms)\r
-{\r
-       if (timer_pending(timer))\r
-               del_timer_sync(timer);\r
-       if (tmo_ms)\r
-               mod_timer(timer, jiffies + msecs_to_jiffies(tmo_ms));\r
-}\r
-\r
-void\r
-wl_timer_register(struct net_device *net, timer_list_compat_t *timer, void *cb_func)\r
-{\r
-       init_timer_compat(timer, cb_func, net);\r
-}\r
-\r
-void\r
-wl_timer_deregister(struct net_device *net, timer_list_compat_t *timer)\r
-{\r
-       if (timer_pending(timer))\r
-               del_timer_sync(timer);\r
-}\r
-#endif\r
+#include <wl_android.h>
+#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
index 97997f4975188ed6feb53a91a548b3fe71bfbd44..6b43384682b768f9c44218edd32ac46b00db12db 100755 (executable)
@@ -1,8 +1,8 @@
-#ifndef _wl_timer_\r
-#define _wl_timer_\r
-s32 wl_timer_attach(struct net_device *net);\r
-void wl_timer_dettach(dhd_pub_t *dhdp);\r
-void wl_timer_register(struct net_device *net, timer_list_compat_t *timer, void *cb_func);\r
-void wl_timer_deregister(struct net_device *net, timer_list_compat_t *timer);\r
-void wl_timer_mod(dhd_pub_t *dhd, timer_list_compat_t *timer, uint32 tmo_ms);\r
-#endif\r
+#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