summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPixelBot AutoMerger <android-nexus-securitybot@system.gserviceaccount.com>2023-06-18 18:44:40 -0700
committerSecurityBot <android-nexus-securitybot@system.gserviceaccount.com>2023-06-18 18:44:40 -0700
commit1979a5d83d62d6f2ad739635113f6345f4ee0641 (patch)
treede00bc01862f267eccbcf6630b6e0db22586c02a
parent63cd8e2d4b30f04cbe37772915821195c0676703 (diff)
parent4bb757afacc81de1645e009485fcd65e154c5950 (diff)
downloadbcm4398-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--Kbuild2
-rw-r--r--dhd.h1
-rw-r--r--dhd_common.c12
-rw-r--r--dhd_linux.c32
-rw-r--r--dhd_pcie.c37
-rw-r--r--wl_cfg80211.c83
-rw-r--r--wl_cfg80211.h11
-rw-r--r--wl_cfgnan.c21
-rw-r--r--wl_cfgscan.c118
-rw-r--r--wl_cfgscan.h5
-rw-r--r--wl_cfgvif.c73
-rw-r--r--wl_cfgvif.h4
12 files changed, 308 insertions, 91 deletions
diff --git a/Kbuild b/Kbuild
index 3236619..c9f4363 100644
--- a/Kbuild
+++ b/Kbuild
@@ -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
diff --git a/dhd.h b/dhd.h
index 1b8e280..259de31 100644
--- a/dhd.h
+++ b/dhd.h
@@ -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",
diff --git a/dhd_pcie.c b/dhd_pcie.c
index 74fecb2..eafb4ae 100644
--- a/dhd_pcie.c
+++ b/dhd_pcie.c
@@ -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_ */