diff --git a/Kbuild b/Kbuild index 945fa0c5d160..8ea27fbefa71 100644 --- a/Kbuild +++ b/Kbuild @@ -3649,7 +3649,7 @@ ccflags-y += -DWLAN_PDEV_MAX_VDEVS=$(CONFIG_WLAN_PDEV_MAX_VDEVS) CONFIG_WLAN_PSOC_MAX_VDEVS ?= $(CONFIG_WLAN_MAX_VDEVS) ccflags-y += -DWLAN_PSOC_MAX_VDEVS=$(CONFIG_WLAN_PSOC_MAX_VDEVS) -CONFIG_MAX_SCAN_CACHE_SIZE ?= 300 +CONFIG_MAX_SCAN_CACHE_SIZE ?= 500 ccflags-y += -DMAX_SCAN_CACHE_SIZE=$(CONFIG_MAX_SCAN_CACHE_SIZE) CONFIG_SCAN_MAX_REST_TIME ?= 0 ccflags-y += -DSCAN_MAX_REST_TIME=$(CONFIG_SCAN_MAX_REST_TIME) diff --git a/components/pkt_capture/core/src/wlan_pkt_capture_main.c b/components/pkt_capture/core/src/wlan_pkt_capture_main.c index 72b08322e3fc..27081aa1c9a6 100644 --- a/components/pkt_capture/core/src/wlan_pkt_capture_main.c +++ b/components/pkt_capture/core/src/wlan_pkt_capture_main.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -125,8 +125,8 @@ static void pkt_capture_wdi_event_unsubscribe(struct wlan_objmgr_psoc *psoc) WDI_EVENT_PKT_CAPTURE_OFFLOAD_TX_DATA); /* unsubscribe for rx data no peer packets */ - cdp_wdi_event_sub(soc, pdev_id, &PKT_CAPTURE_RX_NO_PEER_SUBSCRIBER, - WDI_EVENT_PKT_CAPTURE_RX_DATA_NO_PEER); + cdp_wdi_event_unsub(soc, pdev_id, &PKT_CAPTURE_RX_NO_PEER_SUBSCRIBER, + WDI_EVENT_PKT_CAPTURE_RX_DATA_NO_PEER); /* unsubscribing for rx data packets */ cdp_wdi_event_unsub(soc, pdev_id, &PKT_CAPTURE_RX_SUBSCRIBER, diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index bc93b02a6359..1bc03e75936e 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -7237,6 +7237,8 @@ const struct nla_policy wlan_hdd_wifi_config_policy[ [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS] = {.type = NLA_U8 }, [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS] = {.type = NLA_U8 }, [QCA_WLAN_VENDOR_ATTR_CONFIG_FT_OVER_DS] = {.type = NLA_U8 }, + [QCA_WLAN_VENDOR_ATTR_CONFIG_WFC_STATE] = { + .type = NLA_U8 }, }; static const struct nla_policy @@ -9017,6 +9019,38 @@ static int hdd_set_nss(struct hdd_adapter *adapter, return ret; } +/** + * hdd_set_wfc_state() - Set wfc state + * @adapter: hdd adapter + * @attr: pointer to nla attr + * + * Return: 0 on success, negative on failure + */ +static int hdd_set_wfc_state(struct hdd_adapter *adapter, + const struct nlattr *attr) +{ + uint8_t cfg_val; + enum pld_wfc_mode set_val; + struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + int errno; + + errno = wlan_hdd_validate_context(hdd_ctx); + if (errno) + return errno; + + cfg_val = nla_get_u8(attr); + + hdd_debug_rl("set wfc state %d", cfg_val); + if (cfg_val == 0) + set_val = PLD_WFC_MODE_OFF; + else if (cfg_val == 1) + set_val = PLD_WFC_MODE_ON; + else + return -EINVAL; + + return pld_set_wfc_mode(hdd_ctx->parent_dev, set_val); +} + /** * typedef independent_setter_fn - independent attribute handler * @adapter: The adapter being configured @@ -9129,6 +9163,8 @@ static const struct independent_setters independent_setters[] = { hdd_config_udp_qos_upgrade_threshold}, {QCA_WLAN_VENDOR_ATTR_CONFIG_FT_OVER_DS, hdd_set_ft_over_ds}, + {QCA_WLAN_VENDOR_ATTR_CONFIG_WFC_STATE, + hdd_set_wfc_state}, }; #ifdef WLAN_FEATURE_ELNA @@ -19714,7 +19750,8 @@ static int wlan_hdd_cfg80211_connect_start(struct hdd_adapter *adapter, const u8 *ssid, size_t ssid_len, const u8 *bssid, const u8 *bssid_hint, uint32_t oper_freq, - enum nl80211_chan_width ch_width) + enum nl80211_chan_width ch_width, + uint32_t ch_freq_hint) { int status = 0; QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; @@ -19907,6 +19944,8 @@ static int wlan_hdd_cfg80211_connect_start(struct hdd_adapter *adapter, roam_profile->ChannelInfo.numOfChannels = 0; } + roam_profile->freq_hint = ch_freq_hint; + if (wlan_hdd_cfg80211_check_pmf_valid(roam_profile)) { status = -EINVAL; goto conn_failure; @@ -21723,6 +21762,7 @@ static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy, #endif struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev); struct hdd_context *hdd_ctx; + uint32_t ch_freq_hint = 0; hdd_enter(); @@ -21838,11 +21878,15 @@ static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy, else ch_freq = 0; + if (req->channel_hint) + ch_freq_hint = req->channel_hint->center_freq; + wlan_hdd_check_ht20_ht40_ind(hdd_ctx, adapter, req); status = wlan_hdd_cfg80211_connect_start(adapter, req->ssid, req->ssid_len, req->bssid, - bssid_hint, ch_freq, 0); + bssid_hint, ch_freq, 0, + ch_freq_hint); if (status) { wlan_hdd_cfg80211_clear_privacy(adapter); hdd_err("connect failed"); diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 1030046ff134..6bfdee44a536 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -6507,12 +6507,15 @@ static int drv_cmd_set_channel_switch(struct hdd_adapter *adapter, return status; } - if ((chan_bw != 20) && (chan_bw != 40) && (chan_bw != 80)) { + if ((chan_bw != 20) && (chan_bw != 40) && (chan_bw != 80) && + (chan_bw != 160)) { hdd_err("BW %d is not allowed for CHANNEL_SWITCH", chan_bw); return -EINVAL; } - if (chan_bw == 80) + if (chan_bw == 160) + width = CH_WIDTH_160MHZ; + else if (chan_bw == 80) width = CH_WIDTH_80MHZ; else if (chan_bw == 40) width = CH_WIDTH_40MHZ; diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index b4f765c974c8..f98127f70dcc 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 2 #define QWLAN_VERSION_MINOR 0 #define QWLAN_VERSION_PATCH 8 -#define QWLAN_VERSION_EXTRA "B" +#define QWLAN_VERSION_EXTRA "L" #define QWLAN_VERSION_BUILD 32 -#define QWLAN_VERSIONSTR "2.0.8.32B" +#define QWLAN_VERSIONSTR "2.0.8.32L" #endif /* QWLAN_VERSION_H */ diff --git a/core/mac/inc/sir_mac_prot_def.h b/core/mac/inc/sir_mac_prot_def.h index f124b5fb4be4..8927b19557e7 100644 --- a/core/mac/inc/sir_mac_prot_def.h +++ b/core/mac/inc/sir_mac_prot_def.h @@ -347,9 +347,11 @@ #define SIR_MAC_BAD_HTC_HE_VENDOR_OUI2 "\x00\x50\xF2\x12" #define SIR_MAC_BAD_HTC_HE_VENDOR_OUI_LEN 4 -/* Maximum allowable size of a beacon and probe rsp frame */ -#define SIR_MAX_BEACON_SIZE 512 +/* Maximum allowable size of a beacon,probe rsp and fils discovery frame */ +#define SIR_MAX_BEACON_SIZE 512 #define SIR_MAX_PROBE_RESP_SIZE 512 +#define SIR_MAX_FD_TMPL_SIZE 512 + /* / Frame control field format (2 bytes) */ typedef struct sSirMacFrameCtl { diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 81ced02ff3af..1fec33b2ddbd 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -2138,7 +2138,9 @@ void lim_calculate_tpc(struct mac_context *mac, if (mlme_obj->reg_tpc_obj.ap_constraint_power) { local_constraint = mlme_obj->reg_tpc_obj.ap_constraint_power; - reg_max = mlme_obj->reg_tpc_obj.reg_max[i]; + pe_debug("local constraint: %d" + "power constraint absolute: %d", + local_constraint, is_pwr_constraint_absolute); if (is_pwr_constraint_absolute) max_tx_power = QDF_MIN(reg_max, local_constraint); diff --git a/core/mac/src/pe/sch/sch_api.c b/core/mac/src/pe/sch/sch_api.c index 7b51fae0dcca..104855636a9b 100644 --- a/core/mac/src/pe/sch/sch_api.c +++ b/core/mac/src/pe/sch/sch_api.c @@ -47,6 +47,398 @@ #include "wma_types.h" +#include +#include +#include + +/* Fils Dicovery Frame */ +/** + * struct fd_action_header - FILS Discovery Action frame header + * @action_header: WLAN Action frame header + * @fd_frame_cntl: FILS Disovery Frame Control + * @timestamp: Time stamp + * @bcn_interval: Beacon Interval + * @elem: variable len sub element fields + */ +struct fd_action_header { + struct action_frm_hdr action_header; + uint16_t fd_frame_cntl; + uint8_t timestamp[WLAN_TIMESTAMP_LEN]; + uint16_t bcn_interval; + uint8_t elem[]; +} qdf_packed; + +/** + * struct tpe_ie - Transmit Power Enevolpe IE + * @tpe_header: WLAN IE Header + * @max_tx_pwr_count: Maximum Transmit Power Count + * @max_tx_pwr_interpret: Maximum Transmit Power Interpretation + * @max_tx_pwr_category: Maximum Transmit Power category + * @tx_pwr_info: Transmit power Information + * @elem: variable len sub element fields + */ +struct tpe_ie { + struct ie_header tpe_header; + union { + struct { + uint8_t max_tx_pwr_count:3; + uint8_t max_tx_pwr_interpret:3; + uint8_t max_tx_pwr_category:2; + }; + uint8_t tx_pwr_info; + }; + uint8_t elem[]; +} qdf_packed; + +/** + * lim_populate_fd_capability() - populate the capability field in the + * fils discovery template + * @pe_session: pointer to pe session + * @cur_phymode: current phymode + * @fd_cap: pointer to fils discovery capability array + * + * Return: void + */ +static void lim_populate_fd_capability(struct pe_session *pe_session, + enum wlan_phymode cur_phymode, + uint8_t *fd_cap) +{ + /* Setting ESS and Privacy bits */ + fd_cap[0] |= ((!WLAN_FD_CAP_ESS_ENABLE << WLAN_FD_CAP_ESS_S) | + ((pe_session->privacy) << WLAN_FD_CAP_PRIVACY_S)); + + /* Channel Width Selection */ + switch (pe_session->ch_width) { + case CH_WIDTH_20MHZ: + fd_cap[0] |= (WLAN_FD_CHWIDTH_20 << WLAN_FD_CAP_BSS_CHWIDTH_S); + break; + case CH_WIDTH_40MHZ: + fd_cap[0] |= (WLAN_FD_CHWIDTH_40 << WLAN_FD_CAP_BSS_CHWIDTH_S); + break; + case CH_WIDTH_80MHZ: + fd_cap[0] |= (WLAN_FD_CHWIDTH_80 << WLAN_FD_CAP_BSS_CHWIDTH_S); + break; + case CH_WIDTH_160MHZ: + case CH_WIDTH_80P80MHZ: + fd_cap[0] |= (WLAN_FD_CHWIDTH_160_80_80 << + WLAN_FD_CAP_BSS_CHWIDTH_S); + break; + default: + pe_err("channel width : %d is not supported", pe_session->ch_width); + break; + } + + /* Max Num of Spatial Steam */ + switch (pe_session->nss) { + case WLAN_FD_CAP_NSS_MODE_1: + case WLAN_FD_CAP_NSS_MODE_2: + fd_cap[0] |= ((pe_session->nss - 1) << WLAN_FD_CAP_NSS_S); + break; + case WLAN_FD_CAP_NSS_MODE_3: + case WLAN_FD_CAP_NSS_MODE_4: + case WLAN_FD_CAP_NSS_MODE_5: + case WLAN_FD_CAP_NSS_MODE_6: + case WLAN_FD_CAP_NSS_MODE_7: + case WLAN_FD_CAP_NSS_MODE_8: + fd_cap[0] |= (WLAN_FD_CAP_NSS_GTE_5 << WLAN_FD_CAP_NSS_S); + break; + default: + pe_err("NSS value: %d is not supported", pe_session->nss); + break; + } + + /* Set PHY index */ + switch (cur_phymode) { + case WLAN_PHYMODE_11AXA_HE20: + case WLAN_PHYMODE_11AXG_HE20: + case WLAN_PHYMODE_11AXA_HE40: + case WLAN_PHYMODE_11AXG_HE40: + case WLAN_PHYMODE_11AXG_HE40PLUS: + case WLAN_PHYMODE_11AXG_HE40MINUS: + case WLAN_PHYMODE_11AXA_HE80: + case WLAN_PHYMODE_11AXA_HE160: + case WLAN_PHYMODE_11AXA_HE80_80: + fd_cap[1] |= (WLAN_FD_CAP_PHY_INDEX_HE << + WLAN_FD_CAP_PHY_INDEX_S); + break; + case WLAN_PHYMODE_11AC_VHT20: + case WLAN_PHYMODE_11AC_VHT40: + case WLAN_PHYMODE_11AC_VHT80: + case WLAN_PHYMODE_11AC_VHT160: + case WLAN_PHYMODE_11AC_VHT80_80: + fd_cap[1] |= (WLAN_FD_CAP_PHY_INDEX_VHT << + WLAN_FD_CAP_PHY_INDEX_S); + break; + case WLAN_PHYMODE_11NA_HT20: + case WLAN_PHYMODE_11NG_HT20: + case WLAN_PHYMODE_11NG_HT40PLUS: + case WLAN_PHYMODE_11NG_HT40MINUS: + case WLAN_PHYMODE_11NG_HT40: + case WLAN_PHYMODE_11NA_HT40: + fd_cap[1] |= (WLAN_FD_CAP_PHY_INDEX_HT << + WLAN_FD_CAP_PHY_INDEX_S); + break; + default: + pe_err("Phymode : %d is not supported", cur_phymode); + break; + } + + /* FILS Min Rate */ + fd_cap[1] |= (WLAN_FD_CAP_MIN_RATE << WLAN_FD_CAP_MIN_RATE_S); +} + +/** + * lim_populate_fd_tmpl_frame() - populate the fils discovery frame + * @mac: pointer to mac structure + * @frm: pointer to fils discovery frame + * @pe_session:pointer to pe session + * @frame_size: pointer to fils discovery frame size + * + * return: success: QDF_STATUS_SUCCESS failure: QDF_STATUS_E_FAILURE + */ +static QDF_STATUS lim_populate_fd_tmpl_frame(struct mac_context *mac, + struct pe_session *pe_session, + uint8_t *frm, uint32_t *frame_size) +{ + uint16_t fd_cntl_subfield = 0; + struct fd_action_header *fd_header; + struct wlan_objmgr_vdev *vdev; + uint8_t fd_cap[WLAN_FD_CAP_LEN] = {0}; + uint8_t length = 0; + uint8_t ssid_len = 0, ssid[WLAN_SSID_MAX_LEN + 1] = {0}; + uint32_t shortssid; + uint16_t chwidth = pe_session->ch_width; + qdf_freq_t cur_chan_freq = pe_session->curr_op_freq; + struct wlan_channel *des_chan; + enum wlan_phymode cur_phymode; + uint16_t tpe_num = 0; + tDot11fIEtransmit_power_env tpe[WLAN_MAX_NUM_TPE_IE]; + struct tpe_ie *tpe_ie; + uint8_t i, idx; + tSirMacMgmtHdr *mac_hdr; + struct qdf_mac_addr broadcast_mac_addr = QDF_MAC_ADDR_BCAST_INIT; + + pe_debug("FD TMPL freq: %d chWidth: %d", cur_chan_freq, chwidth); + + vdev = pe_session->vdev; + if (!vdev) { + pe_err("VDEV is NULL"); + return QDF_STATUS_E_FAILURE; + } + + des_chan = wlan_vdev_mlme_get_des_chan(vdev); + if (!des_chan) { + pe_err("des_chan is NULL"); + return QDF_STATUS_E_FAILURE; + } + + cur_phymode = des_chan->ch_phymode; + + lim_populate_mac_header(mac, frm, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, broadcast_mac_addr.bytes, + pe_session->self_mac_addr); + mac_hdr = (tpSirMacMgmtHdr)frm; + sir_copy_mac_addr(mac_hdr->bssId, pe_session->bssId); + frm += sizeof(*mac_hdr); + *frame_size = sizeof(*mac_hdr); + + /* filling fd header */ + fd_header = (struct fd_action_header *)frm; + fd_header->action_header.action_category = ACTION_CATEGORY_PUBLIC; + fd_header->action_header.action_code = WLAN_ACTION_FILS_DISCOVERY; + + /* + * FILS DIscovery Frame Control Subfield - 2 byte + * Enable Short SSID + * When the Short SSID Indicator subfield is equal to 1, + * the SSID Length subfield is equal to 3 + */ + fd_cntl_subfield = WLAN_FD_SSID_LEN_PRES(WLAN_FD_FRAMECNTL_SHORTSSID_LEN); + fd_cntl_subfield |= WLAN_FD_FRAMECNTL_SHORTSSID; + + if (wlan_reg_is_6ghz_chan_freq(cur_chan_freq)) { + fd_cntl_subfield |= WLAN_FD_FRAMECNTL_CAP; + pe_debug("FD Capability Present"); + length = WLAN_FD_CAP_LEN; + } + + /* For 80+80 set Channel center freq segment 1 */ + if (IS_WLAN_PHYMODE_160MHZ(cur_phymode)) { + fd_cntl_subfield |= WLAN_FD_FRAMECNTL_CH_CENTERFREQ; + pe_debug("Center frequenceny Present"); + length += 1; + } + + /* Update the length field */ + /*Indicates length from FD cap to Mobility Domain */ + if (length) + fd_cntl_subfield |= WLAN_FD_FRAMECNTL_LEN_PRES; + + /* FD Control - 2 bytes */ + fd_header->fd_frame_cntl = qdf_cpu_to_le16(fd_cntl_subfield); + + /* Timestamp - 8 bytes */ + qdf_mem_zero(fd_header->timestamp, sizeof(fd_header->timestamp)); + + /* Beacon Interval - 2 bytes */ + fd_header->bcn_interval = + qdf_cpu_to_le16(pe_session->beaconParams.beaconInterval); + + *frame_size += sizeof(*fd_header); + + /* Variable length data */ + frm = &fd_header->elem[0]; + + /* Short SSID - 4 bytes */ + wlan_vdev_mlme_get_ssid(vdev, ssid, &ssid_len); + shortssid = wlan_construct_shortssid(ssid, ssid_len); + *(uint32_t *)frm = qdf_cpu_to_le32(shortssid); + frm += 4; + *frame_size += 4; + pe_debug("Category:%02x Action:%02x fd_cntl:%02x bcn_intvl:%02x short ssid:%02x frame_size:%02x", + fd_header->action_header.action_category, + fd_header->action_header.action_code, fd_cntl_subfield, + fd_header->bcn_interval, shortssid, *frame_size); + + /* Length - 1 byte */ + if (length) { + *frm = length; + pe_debug("length: %d", length); + frm++; + *frame_size += length + 1; + } + + /* FD Capabilities - 2 bytes */ + if (WLAN_FD_IS_CAP_PRESENT(fd_cntl_subfield)) { + lim_populate_fd_capability(pe_session, cur_phymode, &fd_cap[0]); + qdf_mem_copy(frm, fd_cap, WLAN_FD_CAP_LEN); + frm += WLAN_FD_CAP_LEN; + pe_debug("fd_cap: %02x %02x", fd_cap[0], fd_cap[1]); + } + + /* Channel Center Freq Segment 1 - 1 byte */ + if (WLAN_FD_IS_FRAMECNTL_CH_CENTERFREQ(fd_cntl_subfield)) { + /* spec has seg0 and seg1 naming while we use seg1 and seg2 */ + *frm = des_chan->ch_freq_seg1; + frm++; + pe_debug("ch_center_freq: %02x", des_chan->ch_freq_seg1); + } + + /* Add TPE IE */ + if ((wlan_reg_is_6ghz_chan_freq(cur_chan_freq)) || + (pe_session->vhtCapability)) { + populate_dot11f_tx_power_env(mac, &tpe[0], chwidth, + cur_chan_freq, &tpe_num, false); + pe_debug("tpe_num: %02x", tpe_num); + if (tpe_num > WLAN_MAX_NUM_TPE_IE) { + pe_err("tpe_num %d greater than max size", tpe_num); + return QDF_STATUS_E_FAILURE; + } + + for (idx = 0; idx < tpe_num; idx++) { + /* filling tpe_header header */ + tpe_ie = (struct tpe_ie *)frm; + tpe_ie->tpe_header.ie_id = WLAN_ELEMID_VHT_TX_PWR_ENVLP; + + if (tpe[idx].num_tx_power > WLAN_MAX_NUM_TPE_IE) { + pe_err("num_tx_power %d greater than max num", + tpe[idx].num_tx_power); + return QDF_STATUS_E_FAILURE; + } + + /* +1 for including tx power info */ + tpe_ie->tpe_header.ie_len = tpe[idx].num_tx_power + 1; + + if (tpe_ie->tpe_header.ie_len < WLAN_TPE_IE_MIN_LEN || + tpe_ie->tpe_header.ie_len > WLAN_TPE_IE_MAX_LEN) { + pe_err("tpe length %d less than min len or greater than max len", + tpe_ie->tpe_header.ie_len); + return QDF_STATUS_E_FAILURE; + } + + tpe_ie->max_tx_pwr_count = tpe[idx].max_tx_pwr_count; + tpe_ie->max_tx_pwr_interpret = + tpe[idx].max_tx_pwr_interpret; + tpe_ie->max_tx_pwr_category = + tpe[idx].max_tx_pwr_category; + pe_debug("tx_pwr_info: %02x", tpe_ie->tx_pwr_info); + frm = &tpe_ie->elem[0]; + + for (i = 0; i < tpe[idx].num_tx_power; i++) { + *frm = tpe[idx].tx_power[i]; + pe_debug("tx_pwr[%d]: %02x", i, *frm); + frm++; + } + + /* +2 for including element id and length */ + *frame_size += tpe_ie->tpe_header.ie_len + 2; + } + } + + return QDF_STATUS_SUCCESS; +} + +/** + * lim_send_fils_discovery_template() - send fils discovery template to + * target_if + * @mac: pointer to mac structure + * @pe_session:pe session + * + * return: status + */ +static QDF_STATUS lim_send_fils_discovery_template(struct mac_context *mac, + struct pe_session *pe_session) +{ + struct fils_discovery_tmpl_params *fd_params; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + uint32_t n_bytes = sizeof(*fd_params); + + fd_params = qdf_mem_malloc(n_bytes); + + if (!fd_params) + return QDF_STATUS_E_NOMEM; + + fd_params->vdev_id = pe_session->vdev_id; + + fd_params->frm = qdf_mem_malloc(SIR_MAX_FD_TMPL_SIZE); + if (!(fd_params->frm)) { + qdf_mem_free(fd_params); + return QDF_STATUS_E_NOMEM; + } + + status = lim_populate_fd_tmpl_frame(mac, pe_session, fd_params->frm, + &n_bytes); + + if (QDF_IS_STATUS_ERROR(status)) { + pe_err("FAIL bytes %d retcode[%X]", n_bytes, status); + goto memfree; + } + + pe_debug("Fils Discovery template created successfully %d", n_bytes); + + QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR, + fd_params->frm, n_bytes); + + fd_params->tmpl_len = n_bytes; + fd_params->tmpl_len_aligned = roundup(fd_params->tmpl_len, + sizeof(uint32_t)); + + /* Sending data to wmi layer via target_if */ + status = target_if_vdev_mgr_send_fd_tmpl(pe_session->vdev, + fd_params); + if (QDF_IS_STATUS_ERROR(status)) { + pe_err("FAIL bytes %d retcode[%X]", n_bytes, status); + } else { + pe_debug("Fils Discovery tmpl msg posted to HAL of bytes %d", + n_bytes); + } + +memfree: + qdf_mem_free(fd_params->frm); + qdf_mem_free(fd_params); + return status; +} + QDF_STATUS sch_send_beacon_req(struct mac_context *mac, uint8_t *beaconPayload, uint16_t size, struct pe_session *pe_session, enum sir_bcn_update_reason reason) @@ -66,6 +458,11 @@ QDF_STATUS sch_send_beacon_req(struct mac_context *mac, uint8_t *beaconPayload, if (QDF_STATUS_SUCCESS != retCode) pe_err("FAILED to send probe response template with retCode %d", retCode); + /*Fils Discovery Template */ + retCode = lim_send_fils_discovery_template(mac, pe_session); + if (QDF_STATUS_SUCCESS != retCode) + pe_err("FAILED to send fils discovery template retCode %d", + retCode); } beaconParams = qdf_mem_malloc(sizeof(tSendbeaconParams)); diff --git a/core/pld/inc/pld_common.h b/core/pld/inc/pld_common.h index 772007805899..27b6447cea4e 100644 --- a/core/pld/inc/pld_common.h +++ b/core/pld/inc/pld_common.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -133,6 +133,16 @@ enum pld_platform_cap_flag { PLD_HAS_DRV_SUPPORT = 0x04, }; +/** + * enum pld_wfc_mode - WFC Mode + * @PLD_WFC_MODE_OFF: WFC Inactive + * @PLD_WFC_MODE_ON: WFC Active + */ +enum pld_wfc_mode { + PLD_WFC_MODE_OFF, + PLD_WFC_MODE_ON, +}; + /** * struct pld_platform_cap - platform capabilities * @cap_flag: capabilities flag @@ -946,6 +956,15 @@ int pld_thermal_register(struct device *dev, unsigned long state, int mon_id); */ void pld_thermal_unregister(struct device *dev, int mon_id); +/** + * pld_set_wfc_mode() - Sent WFC mode to FW via platform driver + * @dev: The device structure + * @wfc_mode: WFC Modes (0 => Inactive, 1 => Active) + * + * Return: Error code on error + */ +int pld_set_wfc_mode(struct device *dev, enum pld_wfc_mode wfc_mode); + /** * pld_bus_width_type_to_str() - Helper function to convert PLD bandwidth level * to string diff --git a/core/pld/src/pld_common.c b/core/pld/src/pld_common.c index b756a115bb98..a75c8c20adad 100644 --- a/core/pld/src/pld_common.c +++ b/core/pld/src/pld_common.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -3154,6 +3154,32 @@ void pld_thermal_unregister(struct device *dev, int mon_id) } } +int pld_set_wfc_mode(struct device *dev, enum pld_wfc_mode wfc_mode) +{ + int errno = -ENOTSUPP; + enum pld_bus_type type; + + type = pld_get_bus_type(dev); + switch (type) { + case PLD_BUS_TYPE_SDIO: + case PLD_BUS_TYPE_USB: + case PLD_BUS_TYPE_SNOC: + case PLD_BUS_TYPE_IPCI_FW_SIM: + case PLD_BUS_TYPE_SNOC_FW_SIM: + case PLD_BUS_TYPE_IPCI: + case PLD_BUS_TYPE_PCIE_FW_SIM: + break; + case PLD_BUS_TYPE_PCIE: + errno = pld_pcie_set_wfc_mode(dev, wfc_mode); + break; + default: + pr_err("Invalid device type %d\n", type); + break; + } + + return errno; +} + const char *pld_bus_width_type_to_str(enum pld_bus_width_type level) { switch (level) { diff --git a/core/pld/src/pld_pcie.c b/core/pld/src/pld_pcie.c index 8132f4f42069..e04f9a904397 100644 --- a/core/pld/src/pld_pcie.c +++ b/core/pld/src/pld_pcie.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -940,5 +941,30 @@ void pld_pcie_device_self_recovery(struct device *dev, } cnss_self_recovery(dev, cnss_reason); } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) +int pld_pcie_set_wfc_mode(struct device *dev, + enum pld_wfc_mode wfc_mode) +{ + struct cnss_wfc_cfg cfg; + int ret; + + switch (wfc_mode) { + case PLD_WFC_MODE_OFF: + cfg.mode = CNSS_WFC_MODE_OFF; + break; + case PLD_WFC_MODE_ON: + cfg.mode = CNSS_WFC_MODE_ON; + break; + default: + ret = -EINVAL; + goto out; + } + + ret = cnss_set_wfc_mode(dev, cfg); +out: + return ret; +} +#endif #endif #endif diff --git a/core/pld/src/pld_pcie.h b/core/pld/src/pld_pcie.h index 07ed2933cf7b..607367c0c887 100644 --- a/core/pld/src/pld_pcie.h +++ b/core/pld/src/pld_pcie.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -404,7 +405,24 @@ static inline bool pld_pcie_platform_driver_support(void) { return false; } + +static inline int pld_pcie_set_wfc_mode(struct device *dev, + enum pld_wfc_mode wfc_mode) +{ + return 0; +} #else +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) +int pld_pcie_set_wfc_mode(struct device *dev, + enum pld_wfc_mode wfc_mode); +#else +static inline int pld_pcie_set_wfc_mode(struct device *dev, + enum pld_wfc_mode wfc_mode) +{ + return 0; +} +#endif + int pld_pcie_get_fw_files_for_target(struct device *dev, struct pld_fw_files *pfw_files, u32 target_type, u32 target_version); diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index 133896da4386..d2b522974b6b 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -662,6 +663,7 @@ struct csr_roam_profile { tCsrKeys Keys; tCsrChannelInfo ChannelInfo; uint32_t op_freq; + uint32_t freq_hint; struct ch_params ch_params; /* If this is 0, SME will fill in for caller. */ uint16_t beaconInterval; diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 854b6c35a72e..0b75b2e3a1e8 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -8711,35 +8711,60 @@ bool is_disconnect_pending(struct mac_context *pmac, uint8_t vdev_id) return disconnect_cmd_exist; } -bool is_disconnect_pending_on_other_vdev(struct mac_context *pmac, - uint8_t vdev_id) +bool is_any_other_vdev_connecting_disconnecting(struct mac_context *pmac, + uint8_t vdev_id) { tListElem *entry = NULL; tListElem *next_entry = NULL; tSmeCmd *command = NULL; - bool disconnect_cmd_exist = false; + bool is_pending_cmd = false; + enum QDF_OPMODE opmode; entry = csr_nonscan_pending_ll_peek_head(pmac, LL_ACCESS_NOLOCK); while (entry) { next_entry = csr_nonscan_pending_ll_next(pmac, entry, LL_ACCESS_NOLOCK); command = GET_BASE_ADDR(entry, tSmeCmd, Link); - /* - * check if any other vdev NB disconnect or SB disconnect - * (eSmeCommandWmStatusChange) is pending - */ - if (command && (CSR_IS_DISCONNECT_COMMAND(command) || - command->command == eSmeCommandWmStatusChange) && - command->vdev_id != vdev_id) { - sme_debug("disconnect is pending on vdev:%d, cmd:%d", - command->vdev_id, command->command); - disconnect_cmd_exist = true; - break; + if (!command) { + entry = next_entry; + continue; } + + opmode = wlan_get_opmode_from_vdev_id(pmac->pdev, + command->vdev_id); + + if (opmode == QDF_STA_MODE || opmode == QDF_P2P_CLIENT_MODE) { + /* + * check if any other vdev NB disconnect or SB + * disconnect (eSmeCommandWmStatusChange) is pending + */ + if ((CSR_IS_DISCONNECT_COMMAND(command) || + command->command == eSmeCommandWmStatusChange) && + command->vdev_id != vdev_id) { + sme_debug("disconnect is pending on vdev:%d, cmd:%d", + command->vdev_id, command->command); + is_pending_cmd = true; + break; + } + } + + if (opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE) { + /* Check if START/STOP AP OP is in progress */ + if ((command->command == eSmeCommandRoam && + (command->u.roamCmd.roamReason == eCsrStopBss || + command->u.roamCmd.roamReason == eCsrHddIssued))) { + sme_debug("vdev ops pending on vdev_id:%d, cmd:%d, reason:%d", + command->vdev_id, command->command, + command->u.roamCmd.roamReason); + is_pending_cmd = true; + break; + } + } + entry = next_entry; } - return disconnect_cmd_exist; + return is_pending_cmd; } #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD) @@ -8861,7 +8886,7 @@ static void csr_roam_join_rsp_processor(struct mac_context *mac, struct csr_roam_connectedinfo *prev_connect_info; struct wlan_crypto_pmksa *pmksa; uint32_t len = 0, roamId = 0, reason_code = 0; - bool is_dis_pending, is_dis_pending_on_other_vdev; + bool is_dis_pending, is_vdev_ops_pending_on_other_vdev; bool use_same_bss = false; uint8_t max_retry_count = 1; bool retry_same_bss = false; @@ -8965,8 +8990,8 @@ static void csr_roam_join_rsp_processor(struct mac_context *mac, reason_code); is_dis_pending = is_disconnect_pending(mac, session_ptr->sessionId); - is_dis_pending_on_other_vdev = - is_disconnect_pending_on_other_vdev(mac, + is_vdev_ops_pending_on_other_vdev = + is_any_other_vdev_connecting_disconnecting(mac, session_ptr->sessionId); is_time_allowed = csr_is_time_allowed_for_connect_attempt(pCommand, @@ -8976,7 +9001,7 @@ static void csr_roam_join_rsp_processor(struct mac_context *mac, * if userspace has issued disconnection or we have reached mac tries or * max time, driver should not continue for next connection. */ - if (is_dis_pending || is_dis_pending_on_other_vdev || !is_time_allowed || + if (is_dis_pending || is_vdev_ops_pending_on_other_vdev || !is_time_allowed || session_ptr->join_bssid_count >= CSR_MAX_BSSID_COUNT) attempt_next_bss = false; @@ -9092,8 +9117,8 @@ static void csr_roam_join_rsp_processor(struct mac_context *mac, if (is_dis_pending) sme_err("disconnect is pending, complete roam"); - if (is_dis_pending_on_other_vdev) - sme_err("disconnect is pending on other vdev, complete roam"); + if (is_vdev_ops_pending_on_other_vdev) + sme_err("vdev ops is pending on other vdev, complete roam"); if (!is_time_allowed) sme_err("time can exceed the active timeout for connection attempt"); diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index 2a499ca3dcaf..e98e39512c71 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -1395,6 +1395,15 @@ QDF_STATUS csr_scan_for_ssid(struct mac_context *mac_ctx, uint32_t session_id, req->scan_req.chan_list.num_chan = num_chan; } + /* Add freq hint for scan for ssid */ + if (!num_chan && profile->freq_hint && + csr_roam_is_valid_channel(mac_ctx, profile->freq_hint)) { + sme_debug("add freq hint %d", profile->freq_hint); + req->scan_req.chan_list.chan[0].freq = + profile->freq_hint; + req->scan_req.chan_list.num_chan = 1; + } + /* Extend it for multiple SSID */ if (profile->SSIDs.numOfSSIDs) { if (profile->SSIDs.SSIDList[0].SSID.length > WLAN_SSID_MAX_LEN) { diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h index b873e2aa8692..d9f9d701cc4c 100644 --- a/core/sme/src/csr/csr_inside_api.h +++ b/core/sme/src/csr/csr_inside_api.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -984,15 +985,15 @@ bool is_disconnect_pending(struct mac_context *mac_ctx, uint8_t sessionid); /** - * is_disconnect_pending_on_other_vdev() - To check whether a disconnect req - * is pending on any other vdev or not + * is_any_other_vdev_connecting_disconnecting() - To check whether any other + * vdev is in waiting for vdev operations (connect/disconnect or start/stop AP) * @mac_tx: mac context * @sessionid: session id * * Return true if disconnect is pending on any other vdev */ -bool is_disconnect_pending_on_other_vdev(struct mac_context *mac_ctx, - uint8_t sessionid); +bool is_any_other_vdev_connecting_disconnecting(struct mac_context *mac_ctx, + uint8_t sessionid); QDF_STATUS csr_roam_prepare_bss_config_from_profile(struct mac_context *mac_ctx, diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index cfa317853883..409c88336202 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -3730,6 +3730,7 @@ static int wma_group_num_bss_to_scan_id(const u_int8_t *cmd_param_info, struct extscan_cached_scan_results *t_cached_result; struct extscan_cached_scan_result *t_scan_id_grp; int i, j; + uint32_t total_scan_num_results = 0; tSirWifiScanResult *ap; param_buf = (WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *) @@ -3740,16 +3741,19 @@ static int wma_group_num_bss_to_scan_id(const u_int8_t *cmd_param_info, t_cached_result = cached_result; t_scan_id_grp = &t_cached_result->result[0]; - if ((t_cached_result->num_scan_ids * - QDF_MIN(t_scan_id_grp->num_results, - param_buf->num_bssid_list)) > param_buf->num_bssid_list) { - wma_err("num_scan_ids %d, num_results %d num_bssid_list %d", - t_cached_result->num_scan_ids, - t_scan_id_grp->num_results, - param_buf->num_bssid_list); + for (i = 0; i < t_cached_result->num_scan_ids; i++) { + total_scan_num_results += t_scan_id_grp->num_results; + t_scan_id_grp++; + } + + if (total_scan_num_results > param_buf->num_bssid_list) { + wma_err("total_scan_num_results %d, num_bssid_list %d", + total_scan_num_results, + param_buf->num_bssid_list); return -EINVAL; } + t_scan_id_grp = &t_cached_result->result[0]; wma_debug("num_scan_ids:%d", t_cached_result->num_scan_ids); for (i = 0; i < t_cached_result->num_scan_ids; i++) { @@ -3760,8 +3764,7 @@ static int wma_group_num_bss_to_scan_id(const u_int8_t *cmd_param_info, return -ENOMEM; ap = &t_scan_id_grp->ap[0]; - for (j = 0; j < QDF_MIN(t_scan_id_grp->num_results, - param_buf->num_bssid_list); j++) { + for (j = 0; j < t_scan_id_grp->num_results; j++) { ap->channel = src_hotlist->channel; ap->ts = WMA_MSEC_TO_USEC(src_rssi->tstamp); ap->rtt = src_hotlist->rtt;