Merge d1bd8e66e9 on remote branch

Change-Id: I2c0d004cc51d0ce7b262875f00c34c6a98c01cb3
This commit is contained in:
Linux Build Service Account 2022-09-06 14:50:48 -07:00
commit 342f6e18c1
38 changed files with 793 additions and 187 deletions

View file

@ -750,14 +750,10 @@ QDF_STATUS if_mgr_validate_candidate(struct wlan_objmgr_vdev *vdev,
* Do not allow STA to connect on 6Ghz or indoor channel for non dbs
* hardware if SAP and skip_6g_and_indoor_freq_scan ini are present
*/
if (wlan_scan_cfg_skip_6g_and_indoor_freq(psoc) &&
!policy_mgr_is_hw_dbs_capable(psoc) &&
(WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_freq) ||
wlan_reg_is_freq_indoor(pdev, chan_freq)) &&
op_mode == QDF_STA_MODE &&
policy_mgr_mode_specific_connection_count(
psoc, PM_SAP_MODE, NULL)) {
ifmgr_debug("STA connection not allowed on bssid: "QDF_MAC_ADDR_FMT" with freq: %d (6Ghz or indoor(%d)), as SAP is present",
if (op_mode == QDF_STA_MODE &&
!policy_mgr_is_sta_chan_valid_for_connect_and_roam(pdev,
chan_freq)) {
ifmgr_debug("STA connection not allowed on bssid: "QDF_MAC_ADDR_FMT" with freq: %d (6Ghz or indoor(%d)), as not valid for connection",
QDF_MAC_ADDR_REF(candidate_info->peer_addr.bytes),
chan_freq,
wlan_reg_is_freq_indoor(pdev, chan_freq));

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2022 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
@ -3729,4 +3730,16 @@ bool policy_mgr_is_sta_mon_concurrency(struct wlan_objmgr_psoc *psoc);
*
*/
QDF_STATUS policy_mgr_check_mon_concurrency(struct wlan_objmgr_psoc *psoc);
/**
* policy_mgr_is_sta_chan_valid_for_connect_and_roam - Check if given
* channel is valid for STA connection/roam pcl channels
* @pdev: pdev
* @freq: frequency
*
* Return: true if channel is valid else false
*/
bool policy_mgr_is_sta_chan_valid_for_connect_and_roam(
struct wlan_objmgr_pdev *pdev,
qdf_freq_t freq);
#endif /* __WLAN_POLICY_MGR_API_H */

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2022 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

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2022 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

View file

@ -35,6 +35,7 @@
#include "wlan_utility.h"
#include "wlan_mlme_ucfg_api.h"
#include "csr_neighbor_roam.h"
#include "wlan_scan_api.h"
/**
* first_connection_pcl_table - table which provides PCL for the
@ -2755,3 +2756,34 @@ QDF_STATUS policy_mgr_filter_passive_ch(struct wlan_objmgr_pdev *pdev,
return QDF_STATUS_SUCCESS;
}
bool policy_mgr_is_sta_chan_valid_for_connect_and_roam(
struct wlan_objmgr_pdev *pdev,
qdf_freq_t freq)
{
struct wlan_objmgr_psoc *psoc;
uint32_t sap_count;
bool skip_6g_and_indoor_freq;
psoc = wlan_pdev_get_psoc(pdev);
if (!psoc)
return true;
skip_6g_and_indoor_freq =
wlan_scan_cfg_skip_6g_and_indoor_freq(psoc);
sap_count =
policy_mgr_mode_specific_connection_count(psoc, PM_SAP_MODE,
NULL);
/*
* Do not allow STA to connect/roam on 6Ghz or indoor channel for
* non-dbs hardware if SAP is present and skip_6g_and_indoor_freq_scan
* ini is enabled
*/
if (skip_6g_and_indoor_freq && sap_count &&
!policy_mgr_is_hw_dbs_capable(psoc) &&
(WLAN_REG_IS_6GHZ_CHAN_FREQ(freq) ||
wlan_reg_is_freq_indoor(pdev, freq)))
return false;
return true;
}

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2022 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
@ -385,6 +386,12 @@ QDF_STATUS ucfg_send_big_data_stats_request(struct wlan_objmgr_vdev *vdev,
{
return QDF_STATUS_SUCCESS;
}
static inline void
ucfg_mc_cp_stats_get_tx_power(struct wlan_objmgr_vdev *vdev,
int *dbm)
{}
#endif /* QCA_SUPPORT_CP_STATS */
#endif /* __WLAN_CP_STATS_MC_UCFG_API_H__ */

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2022 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
@ -292,7 +293,7 @@
* enable_pending_list_req - Sets Pending channel List Req.
* @Min: 0
* @Max: 1
* @Default: 0
* @Default: 1
*
* This option enables/disables SCAN_CHAN_LIST_CMDID channel list command to FW
* till the current scan is complete.
@ -307,7 +308,7 @@
*/
#define CFG_ENABLE_PENDING_CHAN_LIST_REQ CFG_INI_BOOL( \
"enable_pending_list_req", \
0, \
1, \
"Enable Pending list req")
/*

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2021-2022 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
@ -63,6 +63,8 @@ struct pkt_capture_cb_context {
* @ppdu_stats_q: list used for storing smu related ppdu stats
* @lock_q: spinlock for ppdu_stats q
* @tx_nss: nss of tx data packets received from ppdu stats
* @last_freq: Last connected freq
* @curr_freq: current connected freq
*/
struct pkt_capture_vdev_priv {
struct wlan_objmgr_vdev *vdev;
@ -74,6 +76,8 @@ struct pkt_capture_vdev_priv {
qdf_list_t ppdu_stats_q;
qdf_spinlock_t lock_q;
uint8_t tx_nss;
qdf_freq_t last_freq;
qdf_freq_t curr_freq;
};
/**

View file

@ -1467,10 +1467,6 @@ void pkt_capture_datapkt_process(
if (QDF_IS_STATUS_ERROR(ret))
goto drop_rx_buf;
pkt = pkt_capture_alloc_mon_pkt(vdev);
if (!pkt)
goto drop_rx_buf;
switch (type) {
case TXRX_PROCESS_TYPE_DATA_RX:
callback = pkt_capture_rx_data_cb;
@ -1480,7 +1476,14 @@ void pkt_capture_datapkt_process(
callback = pkt_capture_tx_data_cb;
break;
default:
return;
pkt_capture_vdev_put_ref(vdev);
goto drop_rx_buf;
}
pkt = pkt_capture_alloc_mon_pkt(vdev);
if (!pkt) {
pkt_capture_vdev_put_ref(vdev);
goto drop_rx_buf;
}
pkt->callback = callback;

View file

@ -268,7 +268,7 @@ pkt_capture_process_tx_data(void *soc, void *log_data, u_int16_t vdev_id,
{
struct dp_soc *psoc = soc;
uint8_t tid = 0;
uint8_t bssid[QDF_MAC_ADDR_SIZE];
uint8_t bssid[QDF_MAC_ADDR_SIZE] = {0};
struct pkt_capture_tx_hdr_elem_t *ptr_pktcapture_hdr;
struct pkt_capture_tx_hdr_elem_t pktcapture_hdr = {0};
struct hal_tx_completion_status tx_comp_status = {0};
@ -482,7 +482,7 @@ pkt_capture_is_frame_filter_set(qdf_nbuf_t buf,
void pkt_capture_callback(void *soc, enum WDI_EVENT event, void *log_data,
u_int16_t peer_id, uint32_t status)
{
uint8_t bssid[QDF_MAC_ADDR_SIZE];
uint8_t bssid[QDF_MAC_ADDR_SIZE] = {0};
struct wlan_objmgr_vdev *vdev;
struct pkt_capture_vdev_priv *vdev_priv;
struct pkt_capture_frame_filter *frame_filter;
@ -754,6 +754,8 @@ pkt_capture_register_callbacks(struct wlan_objmgr_vdev *vdev,
target_if_pkt_capture_register_rx_ops(&psoc_priv->rx_ops);
pkt_capture_wdi_event_subscribe(psoc);
pkt_capture_record_channel(vdev);
vdev_priv->curr_freq = vdev->vdev_mlme.des_chan->ch_freq;
vdev_priv->last_freq = vdev_priv->curr_freq;
status = tgt_pkt_capture_register_ev_handler(vdev);
if (QDF_IS_STATUS_ERROR(status))

View file

@ -594,6 +594,7 @@ pkt_capture_mgmt_rx_data_cb(struct wlan_objmgr_psoc *psoc,
buf_len + RESERVE_BYTES, 4),
RESERVE_BYTES, 4, false);
if (!nbuf) {
pkt_capture_vdev_put_ref(vdev);
qdf_nbuf_free(wbuf);
return QDF_STATUS_E_FAILURE;
}

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2022 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
@ -25,6 +26,7 @@
#include "wlan_mgmt_txrx_utils_api.h"
#include "cdp_txrx_ctrl.h"
#include "cfg_ucfg_api.h"
#include "wlan_mgmt_txrx_utils_api.h"
void pkt_capture_mon(struct pkt_capture_cb_context *cb_ctx, qdf_nbuf_t msdu,
struct wlan_objmgr_vdev *vdev, uint16_t ch_freq)
@ -35,6 +37,9 @@ void pkt_capture_mon(struct pkt_capture_cb_context *cb_ctx, qdf_nbuf_t msdu,
void *soc = cds_get_context(QDF_MODULE_ID_SOC);
struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
cdp_config_param_type val;
uint16_t status;
tSirMacAuthFrameBody *auth;
struct pkt_capture_vdev_priv *vdev_priv;
rthdr = (struct radiotap_header *)qdf_nbuf_data(msdu);
rtlen = rthdr->it_len;
@ -42,17 +47,79 @@ void pkt_capture_mon(struct pkt_capture_cb_context *cb_ctx, qdf_nbuf_t msdu,
type = (wh)->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
sub_type = (wh)->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
vdev_priv = pkt_capture_vdev_get_priv(vdev);
if (!vdev_priv) {
pkt_capture_err("packet capture vdev priv is NULL");
return;
}
/*
* Update channel only if successful AUTH Resp is received.
* This is done so that EAPOL M1 data frame have correct
* channel
*/
if ((type == IEEE80211_FC0_TYPE_MGT) &&
(sub_type == MGMT_SUBTYPE_AUTH)) {
uint8_t chan = wlan_freq_to_chan(ch_freq);
val.cdp_pdev_param_monitor_chan = chan;
cdp_txrx_set_pdev_param(soc, wlan_objmgr_pdev_get_pdev_id(pdev),
auth = (tSirMacAuthFrameBody *)(qdf_nbuf_data(msdu) + rtlen +
sizeof(tSirMacMgmtHdr));
if (auth->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_2 ||
auth->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_4) {
if (auth->authStatusCode == STATUS_SUCCESS) {
val.cdp_pdev_param_monitor_chan = chan;
cdp_txrx_set_pdev_param(
soc, wlan_objmgr_pdev_get_pdev_id(pdev),
CDP_MONITOR_CHANNEL, val);
val.cdp_pdev_param_mon_freq = ch_freq;
cdp_txrx_set_pdev_param(soc, wlan_objmgr_pdev_get_pdev_id(pdev),
val.cdp_pdev_param_mon_freq = ch_freq;
cdp_txrx_set_pdev_param(
soc, wlan_objmgr_pdev_get_pdev_id(pdev),
CDP_MONITOR_FREQUENCY, val);
}
}
}
/*
* Update channel to last connected channel in case of assoc/reassoc
* response failure and save current chan in case of success
*/
if ((type == IEEE80211_FC0_TYPE_MGT) &&
((sub_type == MGMT_SUBTYPE_ASSOC_RESP) ||
(sub_type == MGMT_SUBTYPE_REASSOC_RESP))) {
if (qdf_nbuf_len(msdu) < (rtlen + sizeof(tSirMacMgmtHdr) +
SIR_MAC_ASSOC_RSP_STATUS_CODE_OFFSET)) {
pkt_capture_err("Packet length is less than expected");
qdf_nbuf_free(msdu);
return;
}
status = (uint16_t)(*(qdf_nbuf_data(msdu) + rtlen +
sizeof(tSirMacMgmtHdr) +
SIR_MAC_ASSOC_RSP_STATUS_CODE_OFFSET));
if (status == STATUS_SUCCESS) {
vdev_priv->last_freq = vdev_priv->curr_freq;
vdev_priv->curr_freq = ch_freq;
} else {
uint8_t chan_num;
chan_num = wlan_reg_freq_to_chan(pdev,
vdev_priv->last_freq);
val.cdp_pdev_param_monitor_chan = chan_num;
cdp_txrx_set_pdev_param(
soc, wlan_objmgr_pdev_get_pdev_id(pdev),
CDP_MONITOR_CHANNEL, val);
val.cdp_pdev_param_mon_freq = vdev_priv->last_freq;
cdp_txrx_set_pdev_param(
soc, wlan_objmgr_pdev_get_pdev_id(pdev),
CDP_MONITOR_FREQUENCY, val);
vdev_priv->curr_freq = vdev_priv->last_freq;
}
}
if (cb_ctx->mon_cb(cb_ctx->mon_ctx, msdu) != QDF_STATUS_SUCCESS) {

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 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 above
@ -62,9 +63,11 @@ wlan_cm_roam_send_set_vdev_pcl(struct wlan_objmgr_psoc *psoc,
struct fw_scan_channels *freq_list;
struct wlan_objmgr_vdev *vdev;
struct wmi_pcl_chan_weights *weights;
struct wlan_objmgr_pdev *pdev;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
uint32_t band_capability;
uint16_t i;
bool is_channel_allowed;
/*
* If vdev_id is WLAN_UMAC_VDEV_ID_MAX, then PDEV pcl command
@ -85,6 +88,13 @@ wlan_cm_roam_send_set_vdev_pcl(struct wlan_objmgr_psoc *psoc,
return status;
}
pdev = wlan_vdev_get_pdev(vdev);
if (!pdev) {
mlme_err("pdev object is NULL");
status = QDF_STATUS_E_FAILURE;
return status;
}
roam_tx_ops = wlan_cm_roam_get_tx_ops_from_vdev(vdev);
if (!roam_tx_ops || !roam_tx_ops->send_vdev_set_pcl_cmd) {
mlme_err("send_vdev_set_pcl_cmd is NULL");
@ -133,6 +143,13 @@ wlan_cm_roam_send_set_vdev_pcl(struct wlan_objmgr_psoc *psoc,
!WLAN_REG_IS_24GHZ_CH_FREQ(weights->saved_chan_list[i]))
weights->weighed_valid_list[i] =
WEIGHT_OF_DISALLOWED_CHANNELS;
is_channel_allowed =
policy_mgr_is_sta_chan_valid_for_connect_and_roam(
pdev, weights->saved_chan_list[i]);
if (!is_channel_allowed)
weights->weighed_valid_list[i] =
WEIGHT_OF_DISALLOWED_CHANNELS;
}
if (QDF_IS_STATUS_ERROR(status)) {

View file

@ -958,10 +958,13 @@ QDF_STATUS cds_dp_open(struct wlan_objmgr_psoc *psoc)
cds_debug("CDS successfully Opened");
if (cdp_cfg_get(gp_cds_context->dp_soc, cfg_dp_force_gro_enable))
hdd_ctx->dp_agg_param.force_gro_enable = true;
if (cdp_cfg_get(gp_cds_context->dp_soc, cfg_dp_tc_based_dyn_gro_enable))
hdd_ctx->dp_agg_param.tc_based_dyn_gro = true;
else
hdd_ctx->dp_agg_param.force_gro_enable = false;
hdd_ctx->dp_agg_param.tc_based_dyn_gro = false;
hdd_ctx->dp_agg_param.tc_ingress_prio =
cdp_cfg_get(gp_cds_context->dp_soc, cfg_dp_tc_ingress_prio);
return 0;

View file

@ -1198,6 +1198,20 @@ struct rcpi_info {
struct hdd_context;
#ifdef WLAN_FEATURE_DYNAMIC_RX_AGGREGATION
/**
* enum qdisc_filter_status - QDISC filter status
* @QDISC_FILTER_RTNL_LOCK_FAIL: rtnl lock acquire failed
* @QDISC_FILTER_PRIO_MATCH: qdisc filter with priority match
* @QDISC_FILTER_PRIO_MISMATCH: no filter match with configured priority
*/
enum qdisc_filter_status {
QDISC_FILTER_RTNL_LOCK_FAIL,
QDISC_FILTER_PRIO_MATCH,
QDISC_FILTER_PRIO_MISMATCH,
};
#endif
/**
* struct hdd_adapter - hdd vdev/net_device context
* @vdev: object manager vdev context
@ -1532,7 +1546,7 @@ struct hdd_adapter {
void *cookie;
bool response_expected;
#endif
uint8_t gro_disallowed[DP_MAX_RX_THREADS];
qdf_atomic_t gro_disallowed;
uint8_t gro_flushed[DP_MAX_RX_THREADS];
bool handle_feature_update;
/* Indicate if TSO and checksum offload features are enabled or not */
@ -1865,7 +1879,8 @@ struct hdd_adapter_ops_history {
* @country_change_work: work for updating vdev when country changes
* @rx_aggregation: rx aggregation enable or disable state
* @gro_force_flush: gro force flushed indication flag
* @force_gro_enable: force GRO enable or disable flag
* @tc_based_dyn_gro: TC based dynamic GRO enable/disable flag
* @tc_ingress_prio: TC ingress priority
* @current_pcie_gen_speed: current pcie gen speed
* @pm_qos_req: pm_qos request for all cpu cores
* @qos_cpu_mask: voted cpu core mask
@ -2206,7 +2221,8 @@ struct hdd_context {
struct {
qdf_atomic_t rx_aggregation;
uint8_t gro_force_flush[DP_MAX_RX_THREADS];
bool force_gro_enable;
bool tc_based_dyn_gro;
uint32_t tc_ingress_prio;
} dp_agg_param;
int current_pcie_gen_speed;
qdf_workqueue_t *adapter_ops_wq;

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2022 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

View file

@ -15714,7 +15714,8 @@ __wlan_hdd_cfg80211_set_monitor_mode(struct wiphy *wiphy,
return -EPERM;
}
if (!ucfg_pkt_capture_get_mode(hdd_ctx->psoc))
if (!ucfg_pkt_capture_get_mode(hdd_ctx->psoc) ||
!hdd_is_pkt_capture_mon_enable(adapter))
return -EPERM;
errno = hdd_validate_adapter(adapter);
@ -17433,12 +17434,15 @@ static void wlan_hdd_update_lfr_wiphy(struct hdd_context *hdd_ctx)
bool fast_transition_enabled;
bool lfr_enabled;
bool ese_enabled;
bool roam_offload;
ucfg_mlme_is_fast_transition_enabled(hdd_ctx->psoc,
&fast_transition_enabled);
ucfg_mlme_is_lfr_enabled(hdd_ctx->psoc, &lfr_enabled);
ucfg_mlme_is_ese_enabled(hdd_ctx->psoc, &ese_enabled);
if (fast_transition_enabled || lfr_enabled || ese_enabled)
ucfg_mlme_get_roaming_offload(hdd_ctx->psoc, &roam_offload);
if (fast_transition_enabled || lfr_enabled || ese_enabled ||
roam_offload)
hdd_ctx->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
}
#else
@ -17446,11 +17450,13 @@ static void wlan_hdd_update_lfr_wiphy(struct hdd_context *hdd_ctx)
{
bool fast_transition_enabled;
bool lfr_enabled;
bool roam_offload;
ucfg_mlme_is_fast_transition_enabled(hdd_ctx->psoc,
&fast_transition_enabled);
ucfg_mlme_is_lfr_enabled(hdd_ctx->psoc, &lfr_enabled);
if (fast_transition_enabled || lfr_enabled)
ucfg_mlme_get_roaming_offload(hdd_ctx->psoc, &roam_offload);
if (fast_transition_enabled || lfr_enabled || roam_offload)
hdd_ctx->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
}
#endif

View file

@ -754,7 +754,6 @@ static int __hdd_soc_recovery_reinit(struct device *dev,
}
hdd_soc_load_unlock(dev);
hdd_start_complete(0);
return 0;
@ -811,6 +810,7 @@ static int hdd_soc_recovery_reinit(struct device *dev,
osif_psoc_sync_trans_stop(psoc_sync);
hdd_start_complete(0);
return errno;
}

View file

@ -198,6 +198,9 @@
#include <cdp_txrx_ctrl.h>
#include "qdf_lock.h"
#include "wlan_hdd_thermal.h"
#ifdef WLAN_FEATURE_DYNAMIC_RX_AGGREGATION
#include <net/pkt_cls.h>
#endif
#ifdef MODULE
#ifdef WLAN_WEAR_CHIPSET
@ -6996,6 +6999,7 @@ struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx, uint8_t sessio
qdf_event_create(&adapter->peer_cleanup_done);
hdd_sta_info_init(&adapter->sta_info_list);
hdd_sta_info_init(&adapter->cache_sta_info_list);
qdf_atomic_init(&adapter->gro_disallowed);
for (i = 0; i < NET_DEV_HOLD_ID_MAX; i++)
qdf_atomic_init(
@ -10574,6 +10578,168 @@ void hdd_send_mscs_action_frame(struct hdd_context *hdd_ctx,
}
#endif
#ifdef WLAN_FEATURE_DYNAMIC_RX_AGGREGATION
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
static enum qdisc_filter_status
__hdd_check_for_prio_filter_in_clsact_qdisc(struct tcf_block *block,
uint32_t prio)
{
struct tcf_chain *chain;
struct tcf_proto *tp;
struct tcf_proto *tp_next;
enum qdisc_filter_status ret = QDISC_FILTER_PRIO_MISMATCH;
if (!rtnl_trylock())
return QDISC_FILTER_RTNL_LOCK_FAIL;
mutex_lock(&block->lock);
list_for_each_entry(chain, &block->chain_list, list) {
mutex_lock(&chain->filter_chain_lock);
tp = tcf_chain_dereference(chain->filter_chain, chain);
while (tp) {
tp_next = rcu_dereference_protected(tp->next, 1);
if (tp->prio == (prio << 16)) {
ret = QDISC_FILTER_PRIO_MATCH;
break;
}
tp = tp_next;
}
mutex_unlock(&chain->filter_chain_lock);
if (ret == QDISC_FILTER_PRIO_MATCH)
break;
}
mutex_unlock(&block->lock);
rtnl_unlock();
return ret;
}
#else
static enum qdisc_filter_status
__hdd_check_for_prio_filter_in_clsact_qdisc(struct tcf_block *block,
uint32_t prio)
{
struct tcf_chain *chain;
struct tcf_proto *tp;
enum qdisc_filter_status ret = QDISC_FILTER_PRIO_MISMATCH;
if (!rtnl_trylock())
return QDISC_FILTER_RTNL_LOCK_FAIL;
list_for_each_entry(chain, &block->chain_list, list) {
for (tp = rtnl_dereference(chain->filter_chain); tp;
tp = rtnl_dereference(tp->next)) {
if (tp->prio == (prio << 16))
ret = QDISC_FILTER_PRIO_MATCH;
}
}
rtnl_unlock();
return ret;
}
#endif
/**
* hdd_check_for_prio_filter_in_clsact_qdisc() - Check if priority 3 filter
* is configured in the ingress clsact qdisc
* @qdisc: pointer to clsact qdisc
*
* Return: true if priority 3 filter is present else false
*/
static enum qdisc_filter_status
hdd_check_for_prio_filter_in_clsact_qdisc(struct Qdisc *qdisc, uint32_t prio)
{
const struct Qdisc_class_ops *cops;
struct tcf_block *ingress_block;
cops = qdisc->ops->cl_ops;
if (qdf_unlikely(!cops || !cops->tcf_block))
return QDISC_FILTER_PRIO_MISMATCH;
ingress_block = cops->tcf_block(qdisc, TC_H_MIN_INGRESS, NULL);
if (qdf_unlikely(!ingress_block))
return QDISC_FILTER_PRIO_MISMATCH;
return __hdd_check_for_prio_filter_in_clsact_qdisc(ingress_block, prio);
}
/**
* hdd_rx_check_qdisc_for_adapter() - Check if any ingress qdisc is configured
* for given adapter
* @adapter: pointer to HDD adapter context
* @rx_ctx_id: Rx context id
*
* The function checks if ingress qdisc is registered for a given
* net device.
*
* Return: None
*/
static void
hdd_rx_check_qdisc_for_adapter(struct hdd_adapter *adapter)
{
struct hdd_context *hdd_ctx = adapter->hdd_ctx;
struct netdev_queue *ingress_q;
struct Qdisc *ingress_qdisc;
bool disable_gro = false;
enum qdisc_filter_status ret;
if (!adapter->dev->ingress_queue)
goto reset_wl;
rcu_read_lock();
ingress_q = rcu_dereference(adapter->dev->ingress_queue);
if (qdf_unlikely(!ingress_q))
goto reset;
ingress_qdisc = rcu_dereference(ingress_q->qdisc);
if (qdf_unlikely(!ingress_qdisc))
goto reset;
if (qdf_str_eq(ingress_qdisc->ops->id, "ingress")) {
disable_gro = true;
} else if (qdf_str_eq(ingress_qdisc->ops->id, "clsact")) {
ret = hdd_check_for_prio_filter_in_clsact_qdisc(ingress_qdisc,
hdd_ctx->dp_agg_param.tc_ingress_prio);
if (ret == QDISC_FILTER_RTNL_LOCK_FAIL) {
rcu_read_unlock();
return;
} else if (ret == QDISC_FILTER_PRIO_MISMATCH) {
goto reset;
}
disable_gro = true;
}
if (disable_gro) {
rcu_read_unlock();
if (qdf_likely(qdf_atomic_read(&adapter->gro_disallowed)))
return;
hdd_debug("ingress qdisc/filter configured disable GRO");
qdf_atomic_set(&adapter->gro_disallowed, 1);
return;
}
reset:
rcu_read_unlock();
reset_wl:
if (qdf_unlikely(qdf_atomic_read(&adapter->gro_disallowed))) {
hdd_debug("ingress qdisc/filter removed enable GRO");
qdf_atomic_set(&adapter->gro_disallowed, 0);
}
}
#else
static inline void
hdd_rx_check_qdisc_for_adapter(struct hdd_adapter *adapter)
{
}
#endif
static void __hdd_bus_bw_work_handler(struct hdd_context *hdd_ctx)
{
struct hdd_adapter *adapter = NULL, *next_adapter = NULL,
@ -10630,6 +10796,9 @@ static void __hdd_bus_bw_work_handler(struct hdd_context *hdd_ctx)
continue;
}
if (hdd_ctx->dp_agg_param.tc_based_dyn_gro)
hdd_rx_check_qdisc_for_adapter(adapter);
tx_packets += HDD_BW_GET_DIFF(adapter->stats.tx_packets,
adapter->prev_tx_packets);
rx_packets += HDD_BW_GET_DIFF(adapter->stats.rx_packets,
@ -11759,6 +11928,7 @@ static void hdd_init_channel_avoidance(struct hdd_context *hdd_ctx)
{
uint16_t unsafe_channel_count;
int index;
qdf_freq_t *unsafe_freq_list;
pld_get_wlan_unsafe_channel(hdd_ctx->parent_dev,
hdd_ctx->unsafe_channel_list,
@ -11771,16 +11941,25 @@ static void hdd_init_channel_avoidance(struct hdd_context *hdd_ctx)
unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
(uint16_t)NUM_CHANNELS);
unsafe_freq_list = qdf_mem_malloc(
unsafe_channel_count * sizeof(*unsafe_freq_list));
if (!unsafe_freq_list)
return;
for (index = 0; index < unsafe_channel_count; index++) {
hdd_debug("channel frequency %d is not safe",
hdd_ctx->unsafe_channel_list[index]);
unsafe_freq_list[index] =
(qdf_freq_t)hdd_ctx->unsafe_channel_list[index];
}
ucfg_policy_mgr_init_chan_avoidance(
hdd_ctx->psoc,
(qdf_freq_t *)hdd_ctx->unsafe_channel_list,
hdd_ctx->unsafe_channel_count);
unsafe_freq_list,
unsafe_channel_count);
qdf_mem_free(unsafe_freq_list);
}
static void hdd_lte_coex_restart_sap(struct hdd_adapter *adapter,
@ -16627,6 +16806,36 @@ void hdd_init_start_completion(void)
INIT_COMPLETION(wlan_start_comp);
}
#if defined CFG80211_USER_HINT_CELL_BASE_SELF_MANAGED || \
(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0))
static void hdd_inform_wifi_on(void)
{
int ret;
struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
struct osif_psoc_sync *psoc_sync;
hdd_nofl_debug("inform regdomain for wifi on");
ret = wlan_hdd_validate_context(hdd_ctx);
if (ret)
return;
if (!wlan_hdd_validate_modules_state(hdd_ctx))
return;
if (!hdd_ctx->wiphy)
return;
ret = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy), &psoc_sync);
if (ret)
return;
if (hdd_ctx->wiphy->registered)
hdd_send_wiphy_regd_sync_event(hdd_ctx);
osif_psoc_sync_op_stop(psoc_sync);
}
#else
static void hdd_inform_wifi_on(void)
{
}
#endif
static ssize_t wlan_hdd_state_ctrl_param_write(struct file *filp,
const char __user *user_buf,
size_t count,
@ -16638,6 +16847,7 @@ static ssize_t wlan_hdd_state_ctrl_param_write(struct file *filp,
int ret;
unsigned long rc;
struct hdd_context *hdd_ctx;
bool turning_on = false;
if (copy_from_user(buf, user_buf, 3)) {
pr_err("Failed to read buffer\n");
@ -16645,13 +16855,15 @@ static ssize_t wlan_hdd_state_ctrl_param_write(struct file *filp,
}
if (strncmp(buf, wlan_off_str, strlen(wlan_off_str)) == 0) {
pr_debug("Wifi turning off from UI\n");
hdd_info("Wifi turning off from UI\n");
hdd_inform_wifi_off();
goto exit;
}
if (strncmp(buf, wlan_on_str, strlen(wlan_on_str)) == 0)
pr_info("Wifi Turning On from UI\n");
if (strncmp(buf, wlan_on_str, strlen(wlan_on_str)) == 0) {
hdd_info("Wifi Turning On from UI\n");
turning_on = true;
}
if (strncmp(buf, wlan_on_str, strlen(wlan_on_str)) != 0) {
pr_err("Invalid value received from framework");
@ -16675,8 +16887,10 @@ static ssize_t wlan_hdd_state_ctrl_param_write(struct file *filp,
hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
if (hdd_ctx)
hdd_psoc_idle_timer_stop(hdd_ctx);
exit:
if (turning_on)
hdd_inform_wifi_on();
return count;
}

View file

@ -88,6 +88,7 @@
#include "wlan_hdd_object_manager.h"
#include <linux/igmp.h>
#include "qdf_types.h"
#include <wlan_cp_stats_mc_ucfg_api.h>
/* Preprocessor definitions and constants */
#ifdef QCA_WIFI_NAPIER_EMULATION
#define HDD_SSR_BRING_UP_TIME 3000000
@ -2916,6 +2917,7 @@ static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy,
int status;
struct hdd_station_ctx *sta_ctx;
static bool is_rate_limited;
struct wlan_objmgr_vdev *vdev;
hdd_enter_dev(ndev);
@ -2967,7 +2969,13 @@ static int __wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy,
is_rate_limited) {
hdd_debug("Modules not enabled/rate limited, use cached stats");
/* Send cached data to upperlayer*/
*dbm = adapter->hdd_stats.class_a_stat.max_pwr;
vdev = hdd_objmgr_get_vdev(adapter);
if (!vdev) {
hdd_err("vdev is NULL");
return -EINVAL;
}
ucfg_mc_cp_stats_get_tx_power(vdev, dbm);
hdd_objmgr_put_vdev(vdev);
return 0;
}

View file

@ -2728,22 +2728,25 @@ static int hdd_twt_pause_session(struct hdd_adapter *adapter,
qdf_mem_copy(params.peer_macaddr, hdd_sta_ctx->conn_info.bssid.bytes,
QDF_MAC_ADDR_SIZE);
params.vdev_id = adapter->vdev_id;
params.dialog_id = 0;
ret = wlan_cfg80211_nla_parse_nested(tb,
if (twt_param_attr) {
ret = wlan_cfg80211_nla_parse_nested(tb,
QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX,
twt_param_attr,
qca_wlan_vendor_twt_add_dialog_policy);
if (ret) {
hdd_debug("command parsing failed");
return ret;
}
if (ret) {
hdd_debug("command parsing failed");
return ret;
}
id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID;
if (tb[id]) {
params.dialog_id = nla_get_u8(tb[id]);
id = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID;
if (tb[id])
params.dialog_id = nla_get_u8(tb[id]);
else
hdd_debug("TWT: FLOW_ID not specified. set to zero");
} else {
params.dialog_id = 0;
hdd_debug("TWT: FLOW_ID not specified. set to zero");
hdd_debug("TWT param not present. flow id set to zero");
}
status = hdd_twt_check_all_twt_support(adapter->hdd_ctx->psoc,
@ -3877,7 +3880,8 @@ static int hdd_twt_configure(struct hdd_adapter *adapter,
twt_param_attr = tb[id];
if (!twt_param_attr &&
twt_oper != QCA_WLAN_TWT_GET_CAPABILITIES) {
twt_oper != QCA_WLAN_TWT_GET_CAPABILITIES &&
twt_oper != QCA_WLAN_TWT_SUSPEND) {
hdd_err("TWT parameters NOT specified");
return -EINVAL;
}

View file

@ -1678,8 +1678,10 @@ static QDF_STATUS hdd_gro_rx_bh_disable(struct hdd_adapter *adapter,
gro_result_t gro_ret;
uint32_t rx_aggregation;
uint8_t rx_ctx_id = QDF_NBUF_CB_RX_CTX_ID(skb);
int32_t gro_disallowed;
rx_aggregation = qdf_atomic_read(&hdd_ctx->dp_agg_param.rx_aggregation);
gro_disallowed = qdf_atomic_read(&adapter->gro_disallowed);
skb_set_hash(skb, QDF_NBUF_CB_RX_FLOW_ID(skb), PKT_HASH_TYPE_L4);
@ -1687,7 +1689,7 @@ static QDF_STATUS hdd_gro_rx_bh_disable(struct hdd_adapter *adapter,
gro_ret = napi_gro_receive(napi_to_use, skb);
if (hdd_get_current_throughput_level(hdd_ctx) == PLD_BUS_WIDTH_IDLE ||
!rx_aggregation || adapter->gro_disallowed[rx_ctx_id]) {
!rx_aggregation || gro_disallowed) {
if (HDD_IS_EXTRA_GRO_FLUSH_NECESSARY(gro_ret)) {
adapter->hdd_stats.tx_rx_stats.
rx_gro_low_tput_flush++;
@ -1696,7 +1698,7 @@ static QDF_STATUS hdd_gro_rx_bh_disable(struct hdd_adapter *adapter,
}
if (!rx_aggregation)
hdd_ctx->dp_agg_param.gro_force_flush[rx_ctx_id] = 1;
if (adapter->gro_disallowed[rx_ctx_id])
if (gro_disallowed)
adapter->gro_flushed[rx_ctx_id] = 1;
}
local_bh_enable();
@ -2153,6 +2155,7 @@ QDF_STATUS hdd_rx_deliver_to_stack(struct hdd_adapter *adapter,
}
#else
#ifdef WLAN_FEATURE_DYNAMIC_RX_AGGREGATION
#if defined(WLAN_SUPPORT_RX_FISA)
/**
* hdd_set_fisa_disallowed_for_vdev() - Set fisa disallowed bit for a vdev
@ -2179,97 +2182,6 @@ void hdd_set_fisa_disallowed_for_vdev(ol_txrx_soc_handle soc, uint8_t vdev_id,
}
#endif
#ifdef WLAN_FEATURE_DYNAMIC_RX_AGGREGATION
/**
* hdd_is_chain_list_non_empty_for_clsact_qdisc() - Check if chain_list in
* ingress block is non-empty for a clsact qdisc.
* @qdisc: pointer to clsact qdisc
*
* Return: true if chain_list is not empty else false
*/
static bool
hdd_is_chain_list_non_empty_for_clsact_qdisc(struct Qdisc *qdisc)
{
const struct Qdisc_class_ops *cops;
struct tcf_block *ingress_block;
cops = qdisc->ops->cl_ops;
if (qdf_unlikely(!cops || !cops->tcf_block))
return false;
ingress_block = cops->tcf_block(qdisc, TC_H_MIN_INGRESS, NULL);
if (qdf_unlikely(!ingress_block))
return false;
if (list_empty(&ingress_block->chain_list))
return false;
else
return true;
}
/**
* hdd_rx_check_qdisc_for_adapter() - Check if any ingress qdisc is configured
* for given adapter
* @adapter: pointer to HDD adapter context
* @rx_ctx_id: Rx context id
*
* The function checks if ingress qdisc is registered for a given
* net device.
*
* Return: None
*/
static void
hdd_rx_check_qdisc_for_adapter(struct hdd_adapter *adapter, uint8_t rx_ctx_id)
{
ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC);
struct netdev_queue *ingress_q;
struct Qdisc *ingress_qdisc;
if (qdf_unlikely(!soc))
return;
if (!adapter->dev->ingress_queue)
goto reset_wl;
rcu_read_lock();
ingress_q = rcu_dereference(adapter->dev->ingress_queue);
if (qdf_unlikely(!ingress_q))
goto reset;
ingress_qdisc = rcu_dereference(ingress_q->qdisc);
if (qdf_unlikely(!ingress_qdisc))
goto reset;
if (!(qdf_str_eq(ingress_qdisc->ops->id, "ingress") ||
(qdf_str_eq(ingress_qdisc->ops->id, "clsact") &&
hdd_is_chain_list_non_empty_for_clsact_qdisc(ingress_qdisc))))
goto reset;
rcu_read_unlock();
if (qdf_likely(adapter->gro_disallowed[rx_ctx_id]))
return;
hdd_debug("ingress qdisc/filter configured disable GRO");
adapter->gro_disallowed[rx_ctx_id] = 1;
hdd_set_fisa_disallowed_for_vdev(soc, adapter->vdev_id, rx_ctx_id, 1);
return;
reset:
rcu_read_unlock();
reset_wl:
if (qdf_unlikely(adapter->gro_disallowed[rx_ctx_id])) {
hdd_debug("ingress qdisc/filter removed enable GRO");
hdd_set_fisa_disallowed_for_vdev(soc, adapter->vdev_id,
rx_ctx_id, 0);
adapter->gro_disallowed[rx_ctx_id] = 0;
adapter->gro_flushed[rx_ctx_id] = 0;
}
}
QDF_STATUS hdd_rx_deliver_to_stack(struct hdd_adapter *adapter,
struct sk_buff *skb)
{
@ -2278,15 +2190,25 @@ QDF_STATUS hdd_rx_deliver_to_stack(struct hdd_adapter *adapter,
int netif_status;
bool skb_receive_offload_ok = false;
uint8_t rx_ctx_id = QDF_NBUF_CB_RX_CTX_ID(skb);
if (!hdd_ctx->dp_agg_param.force_gro_enable)
/* rx_ctx_id is already verified for out-of-range */
hdd_rx_check_qdisc_for_adapter(adapter, rx_ctx_id);
ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC);
if (QDF_NBUF_CB_RX_TCP_PROTO(skb) &&
!QDF_NBUF_CB_RX_PEER_CACHED_FRM(skb))
skb_receive_offload_ok = true;
if (qdf_atomic_read(&adapter->gro_disallowed) == 0 &&
adapter->gro_flushed[rx_ctx_id] != 0) {
if (qdf_likely(soc))
hdd_set_fisa_disallowed_for_vdev(soc, adapter->vdev_id,
rx_ctx_id, 0);
adapter->gro_flushed[rx_ctx_id] = 0;
} else if (qdf_atomic_read(&adapter->gro_disallowed) &&
adapter->gro_flushed[rx_ctx_id] == 0) {
if (qdf_likely(soc))
hdd_set_fisa_disallowed_for_vdev(soc, adapter->vdev_id,
rx_ctx_id, 1);
}
if (skb_receive_offload_ok && hdd_ctx->receive_offload_cb &&
!hdd_ctx->dp_agg_param.gro_force_flush[rx_ctx_id] &&
!adapter->gro_flushed[rx_ctx_id] &&

View file

@ -32,9 +32,9 @@
#define QWLAN_VERSION_MAJOR 2
#define QWLAN_VERSION_MINOR 0
#define QWLAN_VERSION_PATCH 8
#define QWLAN_VERSION_EXTRA "J"
#define QWLAN_VERSION_BUILD 30
#define QWLAN_VERSION_EXTRA ""
#define QWLAN_VERSION_BUILD 31
#define QWLAN_VERSIONSTR "2.0.8.30J"
#define QWLAN_VERSIONSTR "2.0.8.31"
#endif /* QWLAN_VERSION_H */

View file

@ -482,6 +482,9 @@ struct sme_ready_req {
uint16_t deauth_disassoc_frame_len,
uint16_t reason_code);
csr_roam_pmkid_req_fn_t csr_roam_pmkid_req_cb;
QDF_STATUS (*csr_roam_candidate_event_cb)(struct mac_context *mac,
uint8_t *frame,
uint32_t len);
};
/**
@ -2929,6 +2932,18 @@ struct roam_offload_synch_ind {
enum wlan_phymode phy_mode; /*phy mode sent by fw */
};
/*
* struct roam_scan_candidate_frame Roam candidate scan entry
* vdev_id : vdev id
* frame_len : Length of the beacon/probe rsp frame
* frame : Pointer to the frame
*/
struct roam_scan_candidate_frame {
uint8_t vdev_id;
uint32_t frame_length;
uint8_t *frame;
};
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
struct handoff_failure_ind {
uint8_t vdev_id;

View file

@ -1356,7 +1356,8 @@ void pe_register_callbacks_with_wma(struct mac_context *mac,
ready_req->csr_roam_auth_event_handle_cb,
ready_req->pe_roam_synch_cb,
ready_req->pe_disconnect_cb,
ready_req->csr_roam_pmkid_req_cb);
ready_req->csr_roam_pmkid_req_cb,
ready_req->csr_roam_candidate_event_cb);
if (status != QDF_STATUS_SUCCESS)
pe_err("Registering roaming callbacks with WMA failed");
}

View file

@ -1552,7 +1552,7 @@ static void lim_process_delba_req(struct mac_context *mac_ctx, uint8_t *rx_pkt_i
body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_INFO,
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
body_ptr, frame_len);
delba_req = qdf_mem_malloc(sizeof(*delba_req));
@ -1576,7 +1576,7 @@ static void lim_process_delba_req(struct mac_context *mac_ctx, uint8_t *rx_pkt_i
delba_req->delba_param_set.tid, delba_req->Reason.code);
if (QDF_STATUS_SUCCESS != qdf_status)
pe_err("Failed to process delba request");
pe_err_rl("Failed to process delba request");
error:
qdf_mem_free(delba_req);

View file

@ -2081,6 +2081,12 @@ void lim_calculate_tpc(struct mac_context *mac,
session->ch_width);
}
if (num_pwr_levels > MAX_NUM_PWR_LEVELS) {
pe_debug("reset num_pwr_levels %d to MAX_NUM_PWR_LEVELS %d",
num_pwr_levels, MAX_NUM_PWR_LEVELS);
num_pwr_levels = MAX_NUM_PWR_LEVELS;
}
ch_params.ch_width = CH_WIDTH_20MHZ;
for (i = 0; i < num_pwr_levels; i++) {

View file

@ -105,6 +105,12 @@ typedef enum {
#define MAX_WAIT_FOR_BCN_TX_COMPLETE 4000
#define MAX_WAKELOCK_FOR_CSA 5000
#ifdef WLAN_FEATURE_11BE
#define MAX_NUM_PWR_LEVELS 16
#else
#define MAX_NUM_PWR_LEVELS 8
#endif
#ifdef WLAN_FEATURE_11W
typedef union uPmfSaQueryTimerId {
struct {

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2022 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
@ -364,52 +365,51 @@ uint32_t lim_send_probe_rsp_template_to_hal(struct mac_context *mac,
* @timestamp_offset: return for the offset of the timestamp field
* @time_value_offset: return for the time_value field in the TA IE
*
* Return: the length of the buffer.
* Return: the length of the buffer on success and error code on failure.
*/
int sch_gen_timing_advert_frame(struct mac_context *mac_ctx, tSirMacAddr self_addr,
uint8_t **buf, uint32_t *timestamp_offset, uint32_t *time_value_offset)
{
tDot11fTimingAdvertisementFrame frame;
tDot11fTimingAdvertisementFrame frame = {};
uint32_t payload_size, buf_size;
int status;
QDF_STATUS status;
uint32_t ret;
struct qdf_mac_addr wildcard_bssid = {
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
};
qdf_mem_zero((uint8_t *)&frame, sizeof(tDot11fTimingAdvertisementFrame));
/* Populate the TA fields */
status = populate_dot11f_timing_advert_frame(mac_ctx, &frame);
if (status) {
if (!QDF_IS_STATUS_SUCCESS(status)) {
pe_err("Error populating TA frame %x", status);
return status;
return qdf_status_to_os_return(status);
}
status = dot11f_get_packed_timing_advertisement_frame_size(mac_ctx,
ret = dot11f_get_packed_timing_advertisement_frame_size(mac_ctx,
&frame, &payload_size);
if (DOT11F_FAILED(status)) {
pe_err("Error getting packed frame size %x", status);
return status;
} else if (DOT11F_WARNED(status)) {
pe_warn("Warning getting packed frame size");
if (DOT11F_FAILED(ret)) {
pe_err("Error getting packed frame size %x", ret);
return -EINVAL;
}
if (DOT11F_WARNED(ret))
pe_warn("Warning getting packed frame size");
buf_size = sizeof(tSirMacMgmtHdr) + payload_size;
*buf = qdf_mem_malloc(buf_size);
if (!*buf)
return QDF_STATUS_E_FAILURE;
return -ENOMEM;
payload_size = 0;
status = dot11f_pack_timing_advertisement_frame(mac_ctx, &frame,
ret = dot11f_pack_timing_advertisement_frame(mac_ctx, &frame,
*buf + sizeof(tSirMacMgmtHdr), buf_size -
sizeof(tSirMacMgmtHdr), &payload_size);
pe_err("TA payload size2 = %d", payload_size);
if (DOT11F_FAILED(status)) {
pe_err("Error packing frame %x", status);
pe_debug("TA payload size2 = %d", payload_size);
if (DOT11F_FAILED(ret)) {
pe_err("Error packing frame %x", ret);
goto fail;
} else if (DOT11F_WARNED(status)) {
pe_warn("Warning packing frame");
}
if (DOT11F_WARNED(ret))
pe_warn("Warning packing frame");
lim_populate_mac_header(mac_ctx, *buf, SIR_MAC_MGMT_FRAME,
SIR_MAC_MGMT_TIME_ADVERT, wildcard_bssid.bytes, self_addr);
@ -436,7 +436,7 @@ int sch_gen_timing_advert_frame(struct mac_context *mac_ctx, tSirMacAddr self_ad
return payload_size + sizeof(tSirMacMgmtHdr);
fail:
if (*buf)
qdf_mem_free(*buf);
return status;
qdf_mem_free(*buf);
*buf = NULL;
return -EINVAL;
}

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2022 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
@ -380,6 +381,7 @@ QDF_STATUS
csr_process_roam_pmkid_req_callback(struct mac_context *mac_ctx,
uint8_t vdev_id,
struct roam_pmkid_req_event *roam_bsslist);
#else
static inline QDF_STATUS
csr_roam_pmkid_req_callback(uint8_t vdev_id,
@ -388,7 +390,9 @@ csr_roam_pmkid_req_callback(uint8_t vdev_id,
return QDF_STATUS_SUCCESS;
}
#endif /* WLAN_FEATURE_FIPS */
QDF_STATUS
csr_roam_candidate_event_handle_callback(struct mac_context *mac_ctx,
uint8_t *frame, uint32_t len);
#else
static inline QDF_STATUS csr_roam_synch_callback(struct mac_context *mac,
struct roam_offload_synch_ind *roam_synch_data,
@ -420,6 +424,13 @@ csr_roam_pmkid_req_callback(uint8_t vdev_id,
{
return QDF_STATUS_E_NOSUPPORT;
}
QDF_STATUS
csr_roam_candidate_event_handle_callback(struct mac_context *mac_ctx,
uint8_t *frame, uint32_t len)
{
return QDF_STATUS_SUCCESS;
}
#endif
void csr_neighbor_roam_state_transition(struct mac_context *mac_ctx,
uint8_t newstate, uint8_t session);

View file

@ -1185,6 +1185,8 @@ QDF_STATUS sme_hdd_ready_ind(mac_handle_t mac_handle)
msg->csr_roam_auth_event_handle_cb =
csr_roam_auth_offload_callback;
msg->csr_roam_pmkid_req_cb = csr_roam_pmkid_req_callback;
msg->csr_roam_candidate_event_cb =
csr_roam_candidate_event_handle_callback;
status = u_mac_post_ctrl_msg(mac_handle, (tSirMbMsg *)msg);
if (QDF_IS_STATUS_ERROR(status)) {
@ -8669,7 +8671,7 @@ void sme_get_command_q_status(mac_handle_t mac_handle)
* @timestamp_offset: return for the offset of the timestamp field
* @time_value_offset: return for the time_value field in the TA IE
*
* Return: the length of the buffer.
* Return: the length of the buffer on success and error code on failure.
*/
int sme_ocb_gen_timing_advert_frame(mac_handle_t mac_handle,
tSirMacAddr self_addr, uint8_t **buf,

View file

@ -5028,10 +5028,16 @@ QDF_STATUS csr_roam_stop_network(struct mac_context *mac, uint32_t sessionId,
ssid_match = csr_is_ssid_equal(
mac, pSession->pConnectBssDesc,
bss_desc, pIes);
if (bss_desc && !ssid_match)
status = csr_roam_issue_disassociate(mac,
sessionId, substate, false);
else if (bss_desc)
if (bss_desc && !ssid_match) {
csr_roam_issue_disassociate(mac,
sessionId, substate,
false);
status = QDF_STATUS_E_FAILURE;
qdf_mem_free(pBssConfig);
return status;
} else if (bss_desc) {
/*
* In an infra & going to an infra network with
* the same SSID. This calls for a reassoc seq.
@ -5042,6 +5048,7 @@ QDF_STATUS csr_roam_stop_network(struct mac_context *mac, uint32_t sessionId,
mac, sessionId, roam_profile,
bss_desc, pBssConfig, pIes,
false);
}
} else if (bss_desc || CSR_IS_INFRA_AP(roam_profile)) {
/*
* Not in Infra. We can go ahead and set
@ -15706,6 +15713,17 @@ QDF_STATUS csr_send_join_req_msg(struct mac_context *mac, uint32_t sessionId,
bss_freq,
mac->mlme_cfg->ht_caps.
ht_cap_info.adv_coding_cap);
if (pProfile->csrPersona == QDF_STA_MODE) {
if (pSession->ht_config.ht_sgi20)
pSession->ht_config.ht_sgi20 =
pIes->HTCaps.shortGI20MHz;
if (pSession->ht_config.ht_sgi40)
pSession->ht_config.ht_sgi40 =
pIes->HTCaps.shortGI40MHz;
}
csr_join_req->ht_config = pSession->ht_config;
csr_join_req->vht_config = pSession->vht_config;
sme_debug("ht capability 0x%x VHT capability 0x%x",
@ -21938,6 +21956,128 @@ csr_roam_auth_offload_callback(struct mac_context *mac_ctx,
return status;
}
static
void csr_inform_bcn_probe(struct mac_context *mac_ctx,
uint8_t *frame, uint32_t len,
qdf_freq_t freq)
{
qdf_nbuf_t buf;
uint8_t *data, i;
struct mgmt_rx_event_params rx_param = {0};
struct wlan_frame_hdr *hdr;
enum mgmt_frame_type frm_type = MGMT_BEACON;
hdr = (struct wlan_frame_hdr *)frame;
if ((hdr->i_fc[0] & QDF_IEEE80211_FC0_SUBTYPE_MASK) ==
MGMT_SUBTYPE_PROBE_RESP)
frm_type = MGMT_PROBE_RESP;
rx_param.pdev_id = 0;
rx_param.chan_freq = freq;
/* Real RSSI will be filled after roam sync */
rx_param.rssi = 0;
/* Set all per chain rssi as invalid */
for (i = 0; i < WLAN_MGMT_TXRX_HOST_MAX_ANTENNA; i++)
rx_param.rssi_ctl[i] = WLAN_INVALID_PER_CHAIN_RSSI;
buf = qdf_nbuf_alloc(NULL, qdf_roundup(len, 4), 0, 4, false);
if (!buf)
return;
qdf_nbuf_put_tail(buf, len);
qdf_nbuf_set_protocol(buf, ETH_P_CONTROL);
data = qdf_nbuf_data(buf);
qdf_mem_copy(data, frame, len);
/* buf will be freed by scan module in error or success case */
wlan_scan_process_bcn_probe_rx_sync(wlan_pdev_get_psoc(mac_ctx->pdev),
buf, &rx_param, frm_type);
}
QDF_STATUS
csr_roam_candidate_event_handle_callback(struct mac_context *mac_ctx,
uint8_t *frame, uint32_t len)
{
uint32_t ie_offset, ie_len;
uint8_t *ie_ptr = NULL;
uint8_t *extracted_ie = NULL;
uint8_t primary_channel, band;
qdf_freq_t op_freq;
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_MLME, QDF_TRACE_LEVEL_DEBUG,
frame, len);
/* Fixed parameters offset */
ie_offset = sizeof(struct wlan_frame_hdr) + SIR_MAC_B_PR_SSID_OFFSET;
if (len <= ie_offset) {
mlme_err("Invalid frame length");
return QDF_STATUS_E_FAILURE;
}
ie_ptr = frame + ie_offset;
ie_len = len - ie_offset;
/* For 2.4GHz,5GHz get channel from DS IE */
extracted_ie = (uint8_t *)wlan_get_ie_ptr_from_eid(WLAN_ELEMID_DSPARMS,
ie_ptr, ie_len);
if (extracted_ie && extracted_ie[0] == WLAN_ELEMID_DSPARMS &&
extracted_ie[1] == WLAN_DS_PARAM_IE_MAX_LEN) {
band = BIT(REG_BAND_2G) | BIT(REG_BAND_5G);
primary_channel = *(extracted_ie + 2);
sme_debug("Extracted primary channel from DS : %d",
primary_channel);
goto update_beacon;
}
/* For HT, VHT and non-6GHz HE, get channel from HTINFO IE */
extracted_ie = (uint8_t *)
wlan_get_ie_ptr_from_eid(WLAN_ELEMID_HTINFO_ANA,
ie_ptr, ie_len);
if (extracted_ie && extracted_ie[0] == WLAN_ELEMID_HTINFO_ANA &&
extracted_ie[1] == sizeof(struct wlan_ie_htinfo_cmn)) {
band = BIT(REG_BAND_2G) | BIT(REG_BAND_5G);
primary_channel =
((struct wlan_ie_htinfo *)extracted_ie)->
hi_ie.hi_ctrlchannel;
sme_debug("Extracted primary channel from HT INFO : %d",
primary_channel);
goto update_beacon;
}
/* For 6GHz, get channel from HE OP IE */
extracted_ie = (uint8_t *)
wlan_get_ext_ie_ptr_from_ext_id(WLAN_HEOP_OUI_TYPE,
(uint8_t)
WLAN_HEOP_OUI_SIZE,
ie_ptr, ie_len);
if (extracted_ie &&
!qdf_mem_cmp(&extracted_ie[2], WLAN_HEOP_OUI_TYPE,
WLAN_HEOP_OUI_SIZE) &&
extracted_ie[1] <= WLAN_MAX_HEOP_IE_LEN) {
band = BIT(REG_BAND_6G);
primary_channel = util_scan_get_6g_oper_channel(extracted_ie);
sme_debug("Extracted primary channel from HE OP : %d",
primary_channel);
if (primary_channel)
goto update_beacon;
}
mlme_err("Primary channel was not found in the candidate scan entry");
return QDF_STATUS_E_FAILURE;
update_beacon:
op_freq = wlan_reg_chan_band_to_freq(mac_ctx->pdev,
primary_channel, band);
sme_debug("Roaming candidate frequency : %d", op_freq);
csr_inform_bcn_probe(mac_ctx, frame, len, op_freq);
return QDF_STATUS_SUCCESS;
}
#endif
QDF_STATUS csr_update_owe_info(struct mac_context *mac,

View file

@ -1012,6 +1012,9 @@ typedef struct {
uint16_t reason_code);
QDF_STATUS (*csr_roam_pmkid_req_cb)(uint8_t vdev_id,
struct roam_pmkid_req_event *bss_list);
QDF_STATUS (*csr_roam_candidate_event_cb)(struct mac_context *mac,
uint8_t *frame,
uint32_t len);
qdf_wake_lock_t wmi_cmd_rsp_wake_lock;
qdf_runtime_lock_t wmi_cmd_rsp_runtime_lock;
qdf_runtime_lock_t sap_prevent_runtime_pm_lock;

View file

@ -312,6 +312,17 @@ void wma_report_real_time_roam_stats(struct wlan_objmgr_psoc *psoc,
enum roam_rt_stats_type events,
struct mlme_roam_debug_info *roam_info,
uint32_t value, uint32_t reason);
/**
* wma_roam_candidate_frame_event_handler - Handles wma roam frame event id
* @handle: wma_handle
* @event: event data
* @len: length of the data
*
*Return: Success or Failure status
*/
int wma_roam_candidate_frame_event_handler(void *handle, uint8_t *event,
uint32_t len);
#else
static inline int wma_mlme_roam_synch_event_handler_cb(void *handle,
uint8_t *event,

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2021-2022 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
@ -738,7 +738,10 @@ QDF_STATUS wma_register_roaming_callbacks(
uint8_t *deauth_disassoc_frame,
uint16_t deauth_disassoc_frame_len,
uint16_t reason_code),
csr_roam_pmkid_req_fn_t csr_roam_pmkid_req_cb);
csr_roam_pmkid_req_fn_t csr_roam_pmkid_req_cb,
QDF_STATUS (*csr_roam_candidate_event_cb)(struct mac_context *mac,
uint8_t *frame,
uint32_t len));
#else
static inline QDF_STATUS wma_register_roaming_callbacks(
csr_roam_synch_fn_t csr_roam_synch_cb,
@ -752,7 +755,10 @@ static inline QDF_STATUS wma_register_roaming_callbacks(
uint8_t *deauth_disassoc_frame,
uint16_t deauth_disassoc_frame_len,
uint16_t reason_code),
csr_roam_pmkid_req_fn_t csr_roam_pmkid_req_cb)
csr_roam_pmkid_req_fn_t csr_roam_pmkid_req_cb,
QDF_STATUS (*csr_roam_candidate_event_cb)(struct mac_context *mac,
uint8_t *frame,
uint32_t len))
{
return QDF_STATUS_E_NOSUPPORT;
}

View file

@ -3413,6 +3413,11 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc,
wma_roam_vdev_disconnect_event_handler,
WMA_RX_SERIALIZER_CTX);
wmi_unified_register_event_handler(wma_handle->wmi_handle,
wmi_roam_frame_event_id,
wma_roam_candidate_frame_event_handler,
WMA_RX_SERIALIZER_CTX);
#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
wmi_unified_register_event_handler(wma_handle->wmi_handle,
wmi_rssi_breach_event_id,
@ -9296,6 +9301,7 @@ QDF_STATUS wma_send_set_pcl_cmd(tp_wma_handle wma_handle,
{
uint32_t i;
QDF_STATUS status;
bool is_channel_allowed;
if (!wma_handle) {
wma_err("WMA handle is NULL. Cannot issue command");
@ -9338,6 +9344,14 @@ QDF_STATUS wma_send_set_pcl_cmd(tp_wma_handle wma_handle,
msg->chan_weights.saved_chan_list[i]))
msg->chan_weights.weighed_valid_list[i] =
WEIGHT_OF_DISALLOWED_CHANNELS;
is_channel_allowed =
policy_mgr_is_sta_chan_valid_for_connect_and_roam(
wma_handle->pdev,
msg->chan_weights.saved_chan_list[i]);
if (!is_channel_allowed)
msg->chan_weights.weighed_valid_list[i] =
WEIGHT_OF_DISALLOWED_CHANNELS;
}
if (!QDF_IS_STATUS_SUCCESS(status)) {

View file

@ -3699,6 +3699,8 @@ QDF_STATUS wma_de_register_mgmt_frm_client(void)
* @pe_roam_synch_cb: PE roam synch callback routine pointer
* @csr_roam_auth_event_handle_cb: CSR callback routine pointer
* @csr_roam_pmkid_req_cb: CSR roam pmkid callback routine pointer
* @csr_roam_candidate_event_handle_cb: CSR roam candidate callback
* routine pointer
*
* Register the SME and PE callback routines with WMA for
* handling roaming
@ -3716,7 +3718,9 @@ QDF_STATUS wma_register_roaming_callbacks(
uint8_t *deauth_disassoc_frame,
uint16_t deauth_disassoc_frame_len,
uint16_t reason_code),
csr_roam_pmkid_req_fn_t csr_roam_pmkid_req_cb)
csr_roam_pmkid_req_fn_t csr_roam_pmkid_req_cb,
QDF_STATUS (*csr_roam_candidate_event_cb)(struct mac_context *mac,
uint8_t *frame, uint32_t len))
{
tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
@ -3729,6 +3733,8 @@ QDF_STATUS wma_register_roaming_callbacks(
wma->csr_roam_auth_event_handle_cb = csr_roam_auth_event_handle_cb;
wma->pe_roam_synch_cb = pe_roam_synch_cb;
wma->pe_disconnect_cb = pe_disconnect_cb;
wma->csr_roam_candidate_event_cb =
csr_roam_candidate_event_cb;
wma_debug("Registered roam synch callbacks with WMA successfully");
wma->csr_roam_pmkid_req_cb = csr_roam_pmkid_req_cb;

View file

@ -2611,6 +2611,72 @@ int wma_roam_stats_event_handler(WMA_HANDLE handle, uint8_t *event,
err:
return -EINVAL;
}
int wma_roam_candidate_frame_event_handler(void *handle, uint8_t *event,
uint32_t len)
{
tp_wma_handle wma = (tp_wma_handle) handle;
WMI_ROAM_FRAME_EVENTID_param_tlvs *param_buf = NULL;
wmi_roam_frame_event_fixed_param *frame_params = NULL;
struct roam_scan_candidate_frame *data;
struct mac_context *mac_ctx;
QDF_STATUS status;
if (!event || !len) {
wma_err("Empty roam candidate frame event");
return QDF_STATUS_E_FAILURE;
}
param_buf = (WMI_ROAM_FRAME_EVENTID_param_tlvs *)event;
if (!param_buf) {
wma_err("Received null buf from target");
return -EINVAL;
}
frame_params =
(wmi_roam_frame_event_fixed_param *)param_buf->fixed_param;
if (!wma_is_vdev_valid(frame_params->vdev_id)) {
wma_err("Invalid vdev id %d", frame_params->vdev_id);
return QDF_STATUS_E_FAILURE;
}
if (frame_params->frame_length > param_buf->num_frame) {
wma_err("Invalid frame length %d expected : %d",
frame_params->frame_length,
param_buf->num_frame);
return QDF_STATUS_E_FAILURE;
}
if (!param_buf->frame) {
wmi_err("Frame pointer is Null");
return QDF_STATUS_E_FAILURE;
}
mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
if (!mac_ctx) {
wma_err("NULL mac ptr");
QDF_ASSERT(0);
return -EINVAL;
}
data = qdf_mem_malloc(sizeof(*data));
if (!data)
return -ENOMEM;
data->vdev_id = frame_params->vdev_id;
data->frame_length = frame_params->frame_length;
data->frame = (uint8_t *)param_buf->frame;
status = wma->csr_roam_candidate_event_cb(mac_ctx, data->frame,
data->frame_length);
qdf_mem_free(data);
return QDF_STATUS_SUCCESS;
}
#endif
/**