diff options
author | PixelBot AutoMerger <android-nexus-securitybot@system.gserviceaccount.com> | 2023-06-18 18:44:40 -0700 |
---|---|---|
committer | SecurityBot <android-nexus-securitybot@system.gserviceaccount.com> | 2023-06-18 18:44:40 -0700 |
commit | 1979a5d83d62d6f2ad739635113f6345f4ee0641 (patch) | |
tree | de00bc01862f267eccbcf6630b6e0db22586c02a | |
parent | 63cd8e2d4b30f04cbe37772915821195c0676703 (diff) | |
parent | 4bb757afacc81de1645e009485fcd65e154c5950 (diff) | |
download | bcm4398-1979a5d83d62d6f2ad739635113f6345f4ee0641.tar.gz |
Merge android14-gs-pixel-5.15-udc-d1 into android14-gs-pixel-5.15-udc-qpr1
SBMerger: 526756187
Change-Id: I39825c3e386f66cc1ae85d1480abcb4ceeb28f6a
Signed-off-by: SecurityBot <android-nexus-securitybot@system.gserviceaccount.com>
-rw-r--r-- | Kbuild | 2 | ||||
-rw-r--r-- | dhd.h | 1 | ||||
-rw-r--r-- | dhd_common.c | 12 | ||||
-rw-r--r-- | dhd_linux.c | 32 | ||||
-rw-r--r-- | dhd_pcie.c | 37 | ||||
-rw-r--r-- | wl_cfg80211.c | 83 | ||||
-rw-r--r-- | wl_cfg80211.h | 11 | ||||
-rw-r--r-- | wl_cfgnan.c | 21 | ||||
-rw-r--r-- | wl_cfgscan.c | 118 | ||||
-rw-r--r-- | wl_cfgscan.h | 5 | ||||
-rw-r--r-- | wl_cfgvif.c | 73 | ||||
-rw-r--r-- | wl_cfgvif.h | 4 |
12 files changed, 308 insertions, 91 deletions
@@ -352,6 +352,8 @@ ifneq ($(CONFIG_SOC_GOOGLE),) DHDCFLAGS += -DDHD_TREAT_D3ACKTO_AS_LINKDWN # Skip coredump for certain health check traps DHDCFLAGS += -DDHD_SKIP_COREDUMP_ON_HC + # Skip coredump for older chip revs + DHDCFLAGS += -DDHD_SKIP_COREDUMP_OLDER_CHIPS endif endif @@ -1848,6 +1848,7 @@ typedef struct dhd_pub { #ifdef EWP_EDL bool dongle_edl_support; dhd_dma_buf_t edl_ring_mem; + bool host_edl_mem_inited; #endif /* EWP_EDL */ #if defined(__linux__) struct mutex ndev_op_sync; diff --git a/dhd_common.c b/dhd_common.c index 2159183..f30d077 100644 --- a/dhd_common.c +++ b/dhd_common.c @@ -11297,10 +11297,13 @@ dhd_edl_mem_init(dhd_pub_t *dhd) bzero(&dhd->edl_ring_mem, sizeof(dhd->edl_ring_mem)); ret = dhd_dma_buf_alloc(dhd, &dhd->edl_ring_mem, DHD_EDL_RING_SIZE); if (ret != BCME_OK) { - DHD_ERROR(("%s: alloc of edl_ring_mem failed\n", - __FUNCTION__)); + DHD_ERROR(("%s: alloc of edl_ring_mem size(%u) failed \n", + __FUNCTION__, DHD_EDL_RING_SIZE)); + dhd->host_edl_mem_inited = FALSE; return BCME_ERROR; } + DHD_PRINT(("%s: EDL buffer allocated of size %u\n", __FUNCTION__, DHD_EDL_RING_SIZE)); + dhd->host_edl_mem_inited = TRUE; return BCME_OK; } @@ -11311,8 +11314,11 @@ dhd_edl_mem_init(dhd_pub_t *dhd) void dhd_edl_mem_deinit(dhd_pub_t *dhd) { - if (dhd->edl_ring_mem.va != NULL) + if (dhd->host_edl_mem_inited && dhd->edl_ring_mem.va) { dhd_dma_buf_free(dhd, &dhd->edl_ring_mem); + dhd->host_edl_mem_inited = FALSE; + DHD_PRINT(("%s: EDL buffer freed\n", __FUNCTION__)); + } } int diff --git a/dhd_linux.c b/dhd_linux.c index 72958a6..7b857ef 100644 --- a/dhd_linux.c +++ b/dhd_linux.c @@ -530,11 +530,6 @@ struct semaphore dhd_registration_sem; void dhd_generate_rand_mac_addr(struct ether_addr *ea_addr); -#ifdef EWP_EDL -int host_edl_support = TRUE; -module_param(host_edl_support, int, 0644); -#endif - /* deferred handlers */ static void dhd_ifadd_event_handler(void *handle, void *event_info, u8 event); static void dhd_ifdel_event_handler(void *handle, void *event_info, u8 event); @@ -9726,10 +9721,8 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) #endif /* DHD_SDTC_ETB_DUMP */ #ifdef EWP_EDL - if (host_edl_support) { - if (DHD_EDL_MEM_INIT(&dhd->pub) != BCME_OK) { - host_edl_support = FALSE; - } + if (DHD_EDL_MEM_INIT(&dhd->pub) != BCME_OK) { + DHD_ERROR(("%s: EDL memory allocation failed\n", __FUNCTION__)); } #endif /* EWP_EDL */ @@ -15119,10 +15112,7 @@ void dhd_detach(dhd_pub_t *dhdp) #endif #ifdef EWP_EDL - if (host_edl_support) { - DHD_EDL_MEM_DEINIT(dhdp); - host_edl_support = FALSE; - } + DHD_EDL_MEM_DEINIT(dhdp); #endif /* EWP_EDL */ #if defined(WLTDLS) && defined(PCIE_FULL_DONGLE) @@ -20167,14 +20157,26 @@ extern int dhd_collect_coredump(dhd_pub_t *dhdp, dhd_dump_t *dump); #ifdef DHD_SSSR_COREDUMP static bool -dhd_is_coredump_reqd(char *trapstr, uint str_len) +dhd_is_coredump_reqd(char *trapstr, uint str_len, dhd_pub_t *dhdp) { + uint16 chipid = dhd_get_chipid(dhdp->bus); + + BCM_REFERENCE(chipid); + #ifdef DHD_SKIP_COREDUMP_ON_HC if (trapstr && str_len && strnstr(trapstr, DHD_COREDUMP_IGNORE_TRAP_SIG, str_len)) { return FALSE; } #endif /* DHD_SKIP_COREDUMP_ON_HC */ + +#ifdef DHD_SKIP_COREDUMP_OLDER_CHIPS + /* customer ask to skip coredump collection for older chip revs */ + if (BCM4397_CHIP(chipid) && (dhd_get_chiprev(dhdp->bus) <= 2)) { + return FALSE; + } +#endif /* DHD_SKIP_COREDUMP_OLDER_CHIPS */ + return TRUE; } #endif /* DHD_SSSR_COREDUMP */ @@ -20391,7 +20393,7 @@ dhd_mem_dump(void *handle, void *event_info, u8 event) #ifdef DHD_SSSR_COREDUMP if (dhd_is_coredump_reqd(dhdp->memdump_str, - strnlen(dhdp->memdump_str, DHD_MEMDUMP_LONGSTR_LEN))) { + strnlen(dhdp->memdump_str, DHD_MEMDUMP_LONGSTR_LEN), dhdp)) { ret = dhd_collect_coredump(dhdp, dump); if (ret == BCME_ERROR) { DHD_ERROR(("%s: dhd_collect_coredump() failed.\n", @@ -189,10 +189,6 @@ int cc_wd_reset = FALSE; extern unsigned int system_rev; #endif /* SUPPORT_MULTIPLE_BOARD_REV */ -#ifdef EWP_EDL -extern int host_edl_support; -#endif - #ifdef BCMQT_HW extern int qt_dngl_timeout; #endif /* BCMQT_HW */ @@ -787,6 +783,7 @@ const bcm_iovar_t dhdpcie_iovars[] = { {NULL, 0, 0, 0, 0, 0 } }; +extern void exynos_pcie_d3_ack_timeout_set(bool val); #ifdef BCMQT_HW #define MAX_READ_TIMEOUT 200 * 1000 /* 200 ms in dongle time */ @@ -8889,7 +8886,19 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) if (bcmerror) { DHD_ERROR(("%s: dhd_bus_start: %d\n", __FUNCTION__, bcmerror)); - bcmerror = BCME_NOTUP; + /* NORESOURCE means oob irq init failed + * NOMEM means host memory alloc failed + * in these cases retain the error code + * so that caller can take decision based + * on it to not collect debug_dump + * Because in such a case prot_init etc would + * not have happened and iovars/ioctls to FW + * should be avoided. + */ + if ((bcmerror != BCME_NORESOURCE) && + (bcmerror != BCME_NOMEM)) { + bcmerror = BCME_NOTUP; + } goto done; } @@ -11355,11 +11364,11 @@ dhdpcie_bus_suspend(struct dhd_bus *bus, bool state) if ((bus->wait_for_d3_ack == 0) && (timeleft == 0)) { DHD_ERROR(("%s: Treating D3 ack timeout during" " suspend-resume as PCIe linkdown !\n", __FUNCTION__)); + exynos_pcie_d3_ack_timeout_set(1); bus->is_linkdown = 1; bus->d3ackto_as_linkdwn_cnt++; bus->dhd->hang_reason = HANG_REASON_PCIE_LINK_DOWN_RC_DETECT; dhd_os_send_hang_message(bus->dhd); - } #endif /* DHD_TREAT_D3ACKTO_AS_LINKDWN */ @@ -16460,9 +16469,16 @@ dhdpcie_readshared(dhd_bus_t *bus) (sh->flags2 & PCIE_SHARED2_HSCB) == PCIE_SHARED2_HSCB; #ifdef EWP_EDL - if (host_edl_support) { - bus->dhd->dongle_edl_support = (sh->flags2 & PCIE_SHARED2_EDL_RING) ? TRUE : FALSE; - DHD_PRINT(("Dongle EDL support: %u\n", bus->dhd->dongle_edl_support)); + bus->dhd->dongle_edl_support = (sh->flags2 & PCIE_SHARED2_EDL_RING) ? TRUE : FALSE; + DHD_PRINT(("host_edl_mem_inited:%u Dongle EDL support: %u\n", bus->dhd->host_edl_mem_inited, + bus->dhd->dongle_edl_support)); + if (bus->dhd->dongle_edl_support && !bus->dhd->host_edl_mem_inited) { + DHD_ERROR(("Dongle supports EDL but host allocation failed during module init\n")); + DHD_PRINT(("Retry Allocating EDL buffer\n")); + if (DHD_EDL_MEM_INIT(bus->dhd) != BCME_OK) { + DHD_ERROR(("EDL Alloc failed. Abort!!\n")); + return BCME_NOMEM; + } } #endif /* EWP_EDL */ @@ -17316,8 +17332,7 @@ int dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex) * reason, collect ewp init dumps */ if (ret == BCME_OK || ret == BCME_BADADDR || - ret == BCME_NOMEM || ret == BCME_DATA_NOTFOUND || - ret == BCME_UNSUPPORTED) { + ret == BCME_DATA_NOTFOUND || ret == BCME_UNSUPPORTED) { if (bus->api.fw_rev >= PCIE_SHARED_VERSION_9) { /* ewp hw new init sequence and ewp hw log collection * is supported only above ipc rev 9 diff --git a/wl_cfg80211.c b/wl_cfg80211.c index 75a2b19..42e58cd 100644 --- a/wl_cfg80211.c +++ b/wl_cfg80211.c @@ -16106,17 +16106,20 @@ static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, return BCME_NOMEM; } + if (!target_bssid) { #ifdef WL_MLO - WL_CFG_NET_LIST_SYNC_LOCK(&cfg->net_list_sync, flags); - mld_netinfo = _wl_get_netinfo_by_wdev(cfg, ndev->ieee80211_ptr); - if (mld_netinfo && mld_netinfo->mlinfo.num_links) { - /* copy for local use */ - (void)memcpy_s(&mlinfo, sizeof(mlinfo), &mld_netinfo->mlinfo, sizeof(mlinfo)); - ml_conn = TRUE; - num_links = mld_netinfo->mlinfo.num_links; - } - WL_CFG_NET_LIST_SYNC_UNLOCK(&cfg->net_list_sync, flags); + WL_CFG_NET_LIST_SYNC_LOCK(&cfg->net_list_sync, flags); + mld_netinfo = _wl_get_netinfo_by_wdev(cfg, ndev->ieee80211_ptr); + if (mld_netinfo && mld_netinfo->mlinfo.num_links) { + /* copy for local use */ + (void)memcpy_s(&mlinfo, sizeof(mlinfo), + &mld_netinfo->mlinfo, sizeof(mlinfo)); + ml_conn = TRUE; + num_links = mld_netinfo->mlinfo.num_links; + } + WL_CFG_NET_LIST_SYNC_UNLOCK(&cfg->net_list_sync, flags); #endif /* WL_MLO */ + } mutex_lock(&cfg->usr_sync); for (index = 0; index < num_links; index++) { @@ -16127,8 +16130,9 @@ static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, * instance as even FW does not have peer link addr populated. */ if (target_bssid) { - WL_INFORM_MEM(("Update bssinfo for target bssid\n")); curbssid = target_bssid; + WL_INFORM_MEM(("Update bssinfo for target bssid " MACDBG "\n", + MAC2STRDBG(curbssid))); } else if (ml_conn) { #ifdef WL_MLO linkinfo = &mlinfo.links[index]; @@ -16158,7 +16162,8 @@ static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, } bi = (wl_bss_info_v109_t *)(buf + 4); chspec = wl_chspec_driver_to_host(bi->chanspec); - WL_INFORM_MEM(("link_idx %d chanspec %x\n", link_idx, chspec)); + WL_INFORM_MEM(("chanspec:0x%x\n band:%d chan:%d", chspec, CHSPEC_BAND(chspec), + wf_chspec_ctlchan(wl_chspec_driver_to_host(chspec)))); /* chanspec queried for ASSOCIATED BSSID needs to be valid */ if (!(target_bssid) && !wf_chspec_valid(chspec)) { WL_ERR(("Invalid chanspec from get bss info %x\n", chspec)); @@ -19505,6 +19510,8 @@ static s32 wl_update_chan_param(struct net_device *dev, u32 cur_chspec, u32 chan channel = chaninfo; } + WL_TRACE(("channel:%d chaninfo:%x chspec:%x flags:%x\n", + cur_channel, channel, cur_chspec, band_chan->flags)); if (!err) { if (channel & WL_CHAN_RADAR) { #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)) @@ -19513,7 +19520,7 @@ static s32 wl_update_chan_param(struct net_device *dev, u32 cur_chspec, u32 chan #else band_chan->flags |= IEEE80211_CHAN_RADAR; #endif - WL_DBG(("DFS channel:%d chaninfo:%x chspec:%x flags:%x\n", + WL_TRACE(("DFS channel:%d chaninfo:%x chspec:%x flags:%x\n", cur_channel, channel, cur_chspec, band_chan->flags)); *dfs_radar_disabled = TRUE; } @@ -19527,7 +19534,7 @@ static s32 wl_update_chan_param(struct net_device *dev, u32 cur_chspec, u32 chan band_chan->flags |= IEEE80211_CHAN_NO_IR; #endif /* USE_INDOOR_CHAN_FLAG */ #endif /* LINUX_VER >= 5.4 */ - WL_DBG(("indoor channel:%d chaninfo:%x chspec:%x flags:%x\n", + WL_TRACE(("indoor channel:%d chaninfo:%x chspec:%x flags:%x\n", cur_channel, channel, cur_chspec, band_chan->flags)); } @@ -19538,6 +19545,8 @@ static s32 wl_update_chan_param(struct net_device *dev, u32 cur_chspec, u32 chan #else band_chan->flags |= IEEE80211_CHAN_NO_IR; #endif + WL_TRACE(("passive/restricted channel:%d chaninfo:%x chspec:%x flags:%x\n", + cur_channel, channel, cur_chspec, band_chan->flags)); } } else if (err == BCME_UNSUPPORTED) { @@ -26583,24 +26592,9 @@ wl_notify_start_auth(struct bcm_cfg80211 *cfg, goto fail; } -#ifdef WL_MLO - if (cfg->mlo.supported && !ETHER_ISNULLADDR(e->addr.octet) && - memcmp(evt_data->bssid.octet, e->addr.octet, ETH_ALEN)) { - /* For MLO cases, e->addr would carry MLD address and incase - * MLD is different from link address, a bss entry needs to - * be created so that the host accepts the SAE AUTH indication. - * Without this WAR, host will ignore the event since MLD is not - * known to host yet. This WAR to be removed once user space and - * kernel is ML aware. - */ - WL_INFORM_MEM(("[MLO] Create MLD bss entry\n")); - wl_update_bss_info(cfg, ndev, false, evt_data->bssid.octet); - } else -#endif /* WL_MLO */ - if (wl_get_drv_status(cfg, CONNECTED, ndev)) { - /* Make sure bss_info is updated in roam case */ - wl_update_bss_info(cfg, ndev, false, evt_data->bssid.octet); - } + WL_INFORM(("evt_data->addr: " MACDBG " e->addr: " MACDBG "\n", + MAC2STRDBG(evt_data->bssid.octet), MAC2STRDBG(e->addr.octet))); + wl_update_bss_info(cfg, ndev, false, evt_data->bssid.octet); ext_auth_param.ssid.ssid_len = MIN(evt_data->ssid.SSID_len, DOT11_MAX_SSID_LEN); if (ext_auth_param.ssid.ssid_len) { @@ -26608,12 +26602,35 @@ wl_notify_start_auth(struct bcm_cfg80211 *cfg, evt_data->ssid.SSID, ext_auth_param.ssid.ssid_len); } - (void)memcpy_s(&ext_auth_param.bssid, ETHER_ADDR_LEN, &e->addr, ETHER_ADDR_LEN); + /* + * For MLO cases, e->addr would carry MLD address and in case + * MLD is different from link address, a bss entry needs to + * be created for non-ml aware kernels so that the host accepts + * the SAE AUTH indication. Without this WAR, host will ignore + * the event since MLD is unknown to host yet. + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0)) || defined(WL_EXT_AUTH_BKPORT) + (void)memcpy_s(&ext_auth_param.mld_addr, ETHER_ADDR_LEN, e->addr.octet, ETHER_ADDR_LEN); + (void)memcpy_s(&ext_auth_param.bssid, + ETHER_ADDR_LEN, evt_data->bssid.octet, ETHER_ADDR_LEN); +#else + /* In non-ml aware kernels, use MLD address for auth ind for SAE PMK calc. */ + (void)memcpy_s(&ext_auth_param.bssid, ETHER_ADDR_LEN, e->addr.octet, ETHER_ADDR_LEN); + if (cfg->mlo.supported && !ETHER_ISNULLADDR(e->addr.octet) && + memcmp(evt_data->bssid.octet, e->addr.octet, ETH_ALEN)) { + /* report MLD address based bss for non ML aware external auth kernel I/F */ + if (wl_cfgvif_clone_bss_info(cfg, ndev, + evt_data->bssid.octet, (u8 *)e->addr.octet)) { + WL_ERR(("cfg80211_bss_info clone failed\n")); + /* fall through to attempt connection anyway */ + } + } +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0)) || defined(WL_EXT_AUTH_BKPORT) */ ext_auth_param.action = NL80211_EXTERNAL_AUTH_START; ext_auth_param.key_mgmt_suite = ntoh32(WLAN_AKM_SUITE_SAE_SHA256); WL_INFORM_MEM(("call cfg80211_external_auth_request, BSSID:"MACDBG"\n", - MAC2STRDBG(&e->addr))); + MAC2STRDBG(&ext_auth_param.bssid))); wl_cfg80211_wdev_lock(wdev); err = cfg80211_external_auth_request(ndev, &ext_auth_param, GFP_KERNEL); diff --git a/wl_cfg80211.h b/wl_cfg80211.h index eea7d29..d7fa09f 100644 --- a/wl_cfg80211.h +++ b/wl_cfg80211.h @@ -405,6 +405,17 @@ extern char *dhd_log_dump_get_timestamp(void); #define WL_GCMP #endif /* (LINUX_VERSION > KERNEL_VERSION(4, 0, 0) && WL_GCMP_SUPPORT */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) || \ + (defined(CONFIG_ARCH_MSM) && defined(CFG80211_DISCONNECTED_V2)) +#define CFG80211_GET_BSS(wiphy, channel, bssid, ssid, ssid_len) \ + cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len, \ + IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY); +#else +#define CFG80211_GET_BSS(wiphy, channel, bssid, ssid, ssid_len) \ + cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len, \ + WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) */ + #ifndef IBSS_COALESCE_ALLOWED #define IBSS_COALESCE_ALLOWED IBSS_COALESCE_DEFAULT #endif diff --git a/wl_cfgnan.c b/wl_cfgnan.c index 7137bd7..e8ef182 100644 --- a/wl_cfgnan.c +++ b/wl_cfgnan.c @@ -3312,7 +3312,6 @@ wl_cfgnan_start_handler(struct net_device *ndev, struct bcm_cfg80211 *cfg, uint8 resp_buf[NAN_IOCTL_BUF_SIZE]; int i; s32 timeout = 0; - nan_hal_capabilities_t capabilities; uint32 status; wl_nancfg_t *nancfg = cfg->nancfg; uint32 cfg_ctrl1_flags; @@ -3668,9 +3667,9 @@ wl_cfgnan_start_handler(struct net_device *ndev, struct bcm_cfg80211 *cfg, /* TODO: For now enabling NDPE by default as framework is not setting use_ndpe_attr * When (cmd_data->use_ndpe_attr) is set by framework, Add additional check for * (cmd_data->use_ndpe_attr) as below - * if (capabilities.ndpe_attr_supported && cmd_data->use_ndpe_attr) + * if (nancfg->capabilities.ndpe_attr_supported && cmd_data->use_ndpe_attr) */ - if (capabilities.ndpe_attr_supported) + if (nancfg->capabilities.ndpe_attr_supported) { cfg_ctrl2_flags1 |= WL_NAN_CTRL2_FLAG1_NDPE_CAP; nancfg->ndpe_enabled = true; @@ -6098,7 +6097,21 @@ wl_cfgnan_aligned_data_size_of_opt_dp_params(struct bcm_cfg80211 *cfg, uint16 *d *data_size += ALIGN_SIZE(cmd_data->scid.dlen + NAN_XTLV_ID_LEN_SIZE, 4); } - *data_size += ALIGN_SIZE(WL_NAN_SVC_HASH_LEN + NAN_XTLV_ID_LEN_SIZE, 4); + if (cmd_data->ndp_cfg.security_cfg) { + if ((cmd_data->svc_hash.dlen == WL_NAN_SVC_HASH_LEN) && (cmd_data->svc_hash.data)) { + *data_size += ALIGN_SIZE(WL_NAN_SVC_HASH_LEN + NAN_XTLV_ID_LEN_SIZE, 4); + } else { +#ifdef WL_NAN_DISC_CACHE + *data_size += ALIGN_SIZE(WL_NAN_SVC_HASH_LEN + NAN_XTLV_ID_LEN_SIZE, 4); +#endif /* WL_NAN_DISC_CACHE */ + } + } + + if (cmd_data->service_instance_id) { + /* Account for instance id */ + *data_size += ALIGN_SIZE(sizeof(wl_nan_instance_id_t) + NAN_XTLV_ID_LEN_SIZE, 4); + } + return ret; } diff --git a/wl_cfgscan.c b/wl_cfgscan.c index cb0b476..0587c6e 100644 --- a/wl_cfgscan.c +++ b/wl_cfgscan.c @@ -6522,6 +6522,17 @@ static int wl_cfgscan_acs_do_apcs(struct net_device *dev, if (parameter->scc_chspec) { chosen = parameter->scc_chspec; WL_INFORM_MEM(("sta connected case. chosen:0x%x\n", chosen)); + if ((CHSPEC_BAND(chosen) == WL_CHANSPEC_BAND_5G) && + ((CHSPEC_BW(chosen) == WL_CHANSPEC_BW_320) || + (CHSPEC_BW(chosen) == WL_CHANSPEC_BW_160))) { + /* max bw restricted to 80MHz */ + if (wl_cfgscan_get_bw_chspec((chanspec_t *)&chosen, WL_CHANSPEC_BW_80)) { + WL_ERR(("bw config failed for chosen chspec\n")); + chosen = INVCHANSPEC; + } + WL_DBG_MEM(("5G AP restricted to 80Mhz. chosen:0x%x\n", chosen)); + + } goto done2; } @@ -7147,6 +7158,8 @@ wl_acs_check_scc(struct bcm_cfg80211 *cfg, drv_acs_params_t *parameter, chanspec_t sta_chanspec, int qty, uint32 *pList) { bool scc = FALSE; + chanspec_t cur_chanspec = INVCHANSPEC; + s32 ret = 0; if (!(parameter->freq_bands & CHSPEC_TO_WLC_BAND(sta_chanspec))) { return scc; @@ -7179,9 +7192,31 @@ wl_acs_check_scc(struct bcm_cfg80211 *cfg, drv_acs_params_t *parameter, #endif /* DHD_ACS_CHECK_SCC_2G_ACTIVE_CH */ if (scc == TRUE) { - parameter->scc_chspec = sta_chanspec; - parameter->freq_bands = CHSPEC_TO_WLC_BAND(sta_chanspec); - WL_INFORM_MEM(("SCC case, ACS pick up STA chanspec:0x%x\n", sta_chanspec)); + cur_chanspec = sta_chanspec; + + WL_INFORM_MEM(("sta connected case. chosen:0x%x\n", cur_chanspec)); + if ((CHSPEC_BAND(cur_chanspec) == WL_CHANSPEC_BAND_5G) && + ((CHSPEC_BW(cur_chanspec) == WL_CHANSPEC_BW_320) || + (CHSPEC_BW(cur_chanspec) == WL_CHANSPEC_BW_160))) { + /* max bw restricted to 80MHz */ + if (wl_cfgscan_get_bw_chspec((chanspec_t *)&cur_chanspec, + WL_CHANSPEC_BW_80)) { + WL_ERR(("bw config failed for chosen chspec\n")); + cur_chanspec = INVCHANSPEC; + return FALSE; + } + WL_INFORM_MEM(("5G AP restricted to 80Mhz. chosen:0x%x\n", + cur_chanspec)); + } + ret = wl_filter_restricted_subbands(cfg, bcmcfg_to_prmry_ndev(cfg), &cur_chanspec); + if (ret || !wf_chspec_valid(cur_chanspec)) { + scc = FALSE; + } else { + parameter->scc_chspec = cur_chanspec; + parameter->freq_bands = CHSPEC_TO_WLC_BAND(parameter->scc_chspec); + WL_INFORM_MEM(("SCC case, ACS pick up STA chanspec:0x%x\n", + parameter->scc_chspec)); + } } return scc; } @@ -7575,10 +7610,11 @@ wl_is_channel_dynamic(struct bcm_cfg80211 *cfg, chanspec_t in_chspec) { u16 list_count; u8 *list = NULL; - int i; + int i, j; + u8 chan_array[MAX_20MHZ_CHANNELS] = {0}; u32 chaninfo = 0; chanspec_t chspec; - u32 freq, in_freq; + u32 in_chan_band; bool dyn_indoor = !!(cfg->dyn_chan_policy & DYN_CHAN_POLICY_INDOOR); bool dyn_dfs = !!(cfg->dyn_chan_policy & DYN_CHAN_POLICY_DFS); @@ -7590,8 +7626,10 @@ wl_is_channel_dynamic(struct bcm_cfg80211 *cfg, chanspec_t in_chspec) return -EINVAL; } - in_freq = wl_channel_to_frequency(wf_chspec_ctlchan((chanspec_t)in_chspec), - CHSPEC_BAND((chanspec_t)in_chspec)); + in_chan_band = CHSPEC_BAND(in_chspec); + WL_DBG(("dfs:%d indoor:%d chan_cnt:%d in_band:%d\n", + dyn_dfs, dyn_indoor, dtoh32(list_count), in_chan_band)); + wf_get_all_ext(in_chspec, chan_array); for (i = 0; i < dtoh32(list_count); i++) { chspec = (chanspec_t)dtoh32 (((wl_chanspec_list_v1_t *)list)->chspecs[i].chanspec); @@ -7599,20 +7637,31 @@ wl_is_channel_dynamic(struct bcm_cfg80211 *cfg, chanspec_t in_chspec) (((wl_chanspec_list_v1_t *)list)->chspecs[i].chaninfo); chspec = wl_chspec_driver_to_host(chspec); - INDOOR_DBG(("sta_chanspec:%x chspec:%x\n", in_chspec, chspec)); - freq = wl_channel_to_frequency(wf_chspec_ctlchan((chanspec_t)chspec), - CHSPEC_BAND((chanspec_t)chspec)); - /* compare incoming freq against current supported channel list flags */ - if (freq == in_freq) { - INDOOR_DBG(("chspec:%x chaninfo:%x indoor_p:%d dfs_p:%d indoor:%d " - "dfs:%d passive:%d\n", chspec, chaninfo, dyn_indoor, dyn_dfs, - ((chaninfo & WL_CHAN_INDOOR_ONLY) ? 1 : 0), - ((chaninfo & WL_CHAN_RADAR) ? 1 : 0), - ((chaninfo & WL_CHAN_PASSIVE) ? 1 : 0))); - if (((chaninfo & WL_CHAN_INDOOR_ONLY) && - (dyn_indoor)) || ((chaninfo & WL_CHAN_RADAR) && dyn_dfs)) { - WL_DBG(("indoor or RADAR channel\n")); - return TRUE; + if ((in_chan_band == CHSPEC_BAND(chspec)) && + (CHSPEC_BW(chspec) == WL_CHANSPEC_BW_20)) { + for (j = 0; j < MAX_20MHZ_CHANNELS; j++) { + if (!chan_array[j]) { + /* if there are no more subband channels, exit the loop */ + break; + } + WL_DBG(("sta_chanspec:%x chspec:%x channel:%d band:%d bw:%d\n", + in_chspec, chspec, chan_array[j], + CHSPEC_BAND(chspec), CHSPEC_BW(chspec))); + if (chan_array[j] == CHSPEC_CHANNEL(chspec)) { + /* if subband channel matches, check flags */ + WL_DBG(("overlapping chspec. chspec:%x chaninfo:%x\n", + chspec, chaninfo)); + if (((chaninfo & WL_CHAN_INDOOR_ONLY) && (dyn_indoor)) || + ((chaninfo & WL_CHAN_RADAR) && dyn_dfs)) { + WL_INFORM_MEM(("chspec:%x chaninfo:%x indr_p:%d" + "dfs_p:%d indoor:%d dfs:%d passive:%d\n", + chspec, chaninfo, dyn_indoor, dyn_dfs, + ((chaninfo & WL_CHAN_INDOOR_ONLY) ? 1 : 0), + ((chaninfo & WL_CHAN_RADAR) ? 1 : 0), + ((chaninfo & WL_CHAN_PASSIVE) ? 1 : 0))); + return TRUE; + } + } } } } @@ -7648,7 +7697,7 @@ wl_cfgscan_update_dynamic_channels(struct bcm_cfg80211 *cfg, /* MLO case, check for each link chanspec */ for (i = 0; i < MAX_MLO_LINK; i++) { perlink = &netinfo->mlinfo.links[i]; - WL_DBG_MEM(("check chan for indoor/radar:%x\n", perlink->chspec)); + WL_DBG(("check for indoor/radar:0x%x\n", perlink->chspec)); if (perlink->chspec && wl_is_channel_dynamic(cfg, perlink->chspec)) { dynamic_channel_found = TRUE; @@ -7657,7 +7706,7 @@ wl_cfgscan_update_dynamic_channels(struct bcm_cfg80211 *cfg, } } else { sta_chanspec = (chanspec_t *)wl_read_prof(cfg, ndev, WL_PROF_CHAN); - WL_DBG_MEM(("check sta channel for indoor/radar:%x\n", *sta_chanspec)); + WL_DBG(("check for indoor/radar:0x%x\n", *sta_chanspec)); if ((sta_chanspec) && (wl_is_channel_dynamic(cfg, *sta_chanspec))) { dynamic_channel_found = TRUE; } @@ -7691,3 +7740,26 @@ wl_cfgscan_update_dynamic_channels(struct bcm_cfg80211 *cfg, return err; } #endif /* WL_DYNAMIC_CHAN_POLICY */ + +s32 +wl_cfgscan_get_bw_chspec(chanspec_t *chspec, u32 bw) +{ + chanspec_t cur_chspec = *chspec; + +#ifdef WL_BW320MHZ + *chspec = wf_create_chspec_from_primary(wf_chspec_primary20_chan(cur_chspec), + bw, CHSPEC_BAND(cur_chspec), 0); +#else + *chspec = wf_create_chspec_from_primary(wf_chspec_primary20_chan(cur_chspec), + bw, CHSPEC_BAND(cur_chspec)); +#endif /* WL_BW320MHZ */ + if (!wf_chspec_valid(*chspec)) { + WL_ERR(("invalid chanspec\n")); + return BCME_ERROR; + } + + WL_INFORM_MEM(("cur_chspec:%x new_chspec:0x%x BW:%d chan:%d\n", + cur_chspec, *chspec, bw, + wf_chspec_primary20_chan(*chspec))); + return BCME_OK; +}
\ No newline at end of file diff --git a/wl_cfgscan.h b/wl_cfgscan.h index 811f58b..bbc69be 100644 --- a/wl_cfgscan.h +++ b/wl_cfgscan.h @@ -57,6 +57,9 @@ #define SCAN_PARAMS_VER_2 2u #define SCAN_PARAMS_VER_3 3u #define SCAN_PARAMS_VER_4 4u + +#define MAX_20MHZ_CHANNELS 16u + /* SCAN_PARAMS V3 and V2 have same size. so use V3 with appriate version param */ #define IS_SCAN_PARAMS_V3_V2(cfg) (((cfg->scan_params_ver == SCAN_PARAMS_VER_3) || \ (cfg->scan_params_ver == SCAN_PARAMS_VER_2)) ? TRUE : FALSE) @@ -244,4 +247,6 @@ extern bool wl_is_link_sleepable(struct bcm_cfg80211 *cfg, chanspec_t pri_chspec chanspec_t target_chspec); extern bool wl_cfgscan_chaninfo_restricted(struct bcm_cfg80211 *cfg, struct net_device *dev, u32 chan_info, chanspec_t chspec); +extern s32 +wl_cfgscan_get_bw_chspec(chanspec_t *chspec, u32 bw); #endif /* _wl_cfgscan_h_ */ diff --git a/wl_cfgvif.c b/wl_cfgvif.c index dfb33a0..d29df46 100644 --- a/wl_cfgvif.c +++ b/wl_cfgvif.c @@ -1854,7 +1854,6 @@ wl_get_lower_bw_chspec(chanspec_t *chspec) return BCME_OK; } -#define MAX_20MHZ_CHANNELS 16u static s32 wl_get_overlapping_chspecs(chanspec_t sel_chspec, wl_chanspec_attr_v1_t *overlap, u32 *arr_idx) @@ -1911,7 +1910,7 @@ wl_get_overlapping_chspecs(chanspec_t sel_chspec, return BCME_OK; } -static s32 +s32 wl_filter_restricted_subbands(struct bcm_cfg80211 *cfg, struct net_device *dev, chanspec_t *cur_chspec) { @@ -8981,3 +8980,73 @@ exit: WL_CFG_NET_LIST_SYNC_UNLOCK(&cfg->net_list_sync, flags); return found; } + +s32 +wl_cfgvif_clone_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, + u8 *src_bssid, u8 *target_bssid) +{ + struct cfg80211_bss *src_bss, *bss, *target_bss; + struct wiphy *wiphy; + s32 err = 0; + struct wlc_ssid *ssid; + u32 ftype; + + wiphy = bcmcfg_to_wiphy(cfg); + + if (!src_bssid || !target_bssid) { + WL_ERR(("invalid arg\n")); + return BCME_ERROR; + } + + ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID); + if (!ssid) { + WL_ERR(("connection ssid null\n")); + return BCME_ERROR; + } + + target_bss = CFG80211_GET_BSS(wiphy, NULL, target_bssid, + NULL, 0); + if (target_bss) { + /* Entry already present for target bssid */ + WL_INFORM(("target bss found for bssid" MACDBG "\n", + MAC2STRDBG(target_bssid))); + CFG80211_PUT_BSS(wiphy, target_bss); + return BCME_OK; + } + + src_bss = CFG80211_GET_BSS(wiphy, NULL, src_bssid, + ssid->SSID, ssid->SSID_len); + if (!src_bss) { + WL_ERR(("No src bss found for bssid" MACDBG "\n", + MAC2STRDBG(src_bssid))); + return BCME_ERROR; + } + + + if (!src_bss->ies || !src_bss->ies->len) { + WL_ERR(("empty bss ies\n")); + err = BCME_NOMEM; + goto exit; + } + + ftype = src_bss->proberesp_ies ? + CFG80211_BSS_FTYPE_PRESP : CFG80211_BSS_FTYPE_BEACON; + + /* use same info to create a clone with the target bssid */ + bss = cfg80211_inform_bss(wiphy, src_bss->channel, + ftype, target_bssid, src_bss->ies->tsf, src_bss->capability, + src_bss->beacon_interval, (const u8 *)src_bss->ies->data, src_bss->ies->len, + src_bss->signal, GFP_KERNEL); + if (!bss) { + WL_ERR(("cfg8011_inform_bss failed\n")); + err = BCME_NOMEM; + goto exit; + } + CFG80211_PUT_BSS(wiphy, bss); + + WL_INFORM_MEM(("bss entry created for address:" MACDBG " freq:%d\n", + MAC2STRDBG(target_bssid), src_bss->channel->center_freq)); +exit: + CFG80211_PUT_BSS(wiphy, src_bss); + return err; +} diff --git a/wl_cfgvif.h b/wl_cfgvif.h index 8332987..407b0cb 100644 --- a/wl_cfgvif.h +++ b/wl_cfgvif.h @@ -313,4 +313,8 @@ extern s32 wl_cfgvif_set_multi_link(struct bcm_cfg80211 *cfg, u8 enable); extern s32 wl_cfgvif_get_multilink_status(struct bcm_cfg80211 *cfg, struct net_device *dev, u8 *status); bool wl_cfgvif_bssid_match_found(struct bcm_cfg80211 *cfg, struct wireless_dev *wdev, u8 *mac_addr); +s32 wl_cfgvif_clone_bss_info(struct bcm_cfg80211 *cfg, + struct net_device *ndev, u8 *src_bssid, u8 *target_bssid); +extern s32 wl_filter_restricted_subbands(struct bcm_cfg80211 *cfg, struct net_device *dev, + chanspec_t *cur_chspec); #endif /* _wl_cfgvif_h_ */ |