qcacld-3.0: Move SAP from dfs to non-dfs if sta is coming up
Currently STA will fail to start on 5G channel if SAP is up on dfs channel already. So moving SAP from dfs to non-dfs channel first to make sure STA connection can happen. Change-Id: I1761debdd33b0b60755f159d598fd3c9b080ceee CRs-Fixed: 3103726
This commit is contained in:

committed by
Madan Koyyalamudi

parent
acb33111a7
commit
bcf5bbcfb7
@@ -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 above
|
||||
@@ -49,6 +49,7 @@
|
||||
#include <wlan_mlme_twt_ucfg_api.h>
|
||||
#include "wlan_roam_debug.h"
|
||||
#include <wlan_hdd_regulatory.h>
|
||||
#include "wlan_hdd_hostapd.h"
|
||||
|
||||
bool hdd_cm_is_vdev_associated(struct hdd_adapter *adapter)
|
||||
{
|
||||
@@ -385,6 +386,189 @@ hdd_get_dot11mode_filter(struct hdd_context *hdd_ctx)
|
||||
return ALLOW_ALL;
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_get_sap_adapter_of_dfs - Get sap adapter on dfs channel
|
||||
* @hdd_ctx: HDD context
|
||||
*
|
||||
* This function is used to get the sap adapter on dfs channel.
|
||||
*
|
||||
* Return: pointer to adapter or null
|
||||
*/
|
||||
static struct hdd_adapter
|
||||
*hdd_get_sap_adapter_of_dfs(struct hdd_context *hdd_ctx)
|
||||
{
|
||||
struct hdd_adapter *adapter, *next_adapter = NULL;
|
||||
wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_ADAPTER;
|
||||
qdf_freq_t chan_freq = 0;
|
||||
|
||||
hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
|
||||
dbgid) {
|
||||
if (adapter->device_mode != QDF_SAP_MODE)
|
||||
goto loop_next;
|
||||
|
||||
/*
|
||||
* sap is not in started state and also not under doing CAC,
|
||||
* so it is fine to go ahead with sta.
|
||||
*/
|
||||
if (!test_bit(SOFTAP_BSS_STARTED, &(adapter)->event_flags) &&
|
||||
(hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
|
||||
goto loop_next;
|
||||
|
||||
chan_freq = wlan_get_operation_chan_freq_vdev_id(hdd_ctx->pdev,
|
||||
adapter->vdev_id);
|
||||
|
||||
if (chan_freq && wlan_reg_is_dfs_for_freq(hdd_ctx->pdev,
|
||||
chan_freq)) {
|
||||
hdd_adapter_dev_put_debug(adapter, dbgid);
|
||||
if (next_adapter)
|
||||
hdd_adapter_dev_put_debug(next_adapter, dbgid);
|
||||
|
||||
return adapter;
|
||||
}
|
||||
loop_next:
|
||||
hdd_adapter_dev_put_debug(adapter, dbgid);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_hdd_cm_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
|
||||
* @hdd_ctx: hdd_ctx
|
||||
* @req: connect req
|
||||
*
|
||||
* This routine will move SAP from dfs to non-dfs, if sta is coming up.
|
||||
*
|
||||
* Return: false if sta-sap conc is not allowed, else return true
|
||||
*/
|
||||
static
|
||||
bool wlan_hdd_cm_handle_sap_sta_dfs_conc(struct hdd_context *hdd_ctx,
|
||||
struct cfg80211_connect_params *req)
|
||||
{
|
||||
struct hdd_adapter *ap_adapter;
|
||||
struct hdd_ap_ctx *hdd_ap_ctx;
|
||||
struct hdd_hostapd_state *hostapd_state;
|
||||
QDF_STATUS status;
|
||||
qdf_freq_t ch_freq = 0;
|
||||
struct scan_filter *scan_filter;
|
||||
qdf_list_t *list = NULL;
|
||||
qdf_list_node_t *cur_lst = NULL;
|
||||
struct scan_cache_node *cur_node = NULL;
|
||||
|
||||
ap_adapter = hdd_get_sap_adapter_of_dfs(hdd_ctx);
|
||||
/* probably no dfs sap running, no handling required */
|
||||
if (!ap_adapter)
|
||||
return true;
|
||||
|
||||
/* if sap is currently doing CAC then don't allow sta to go further */
|
||||
if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
|
||||
hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* log and return error, if we allow STA to go through, we don't
|
||||
* know what is going to happen better stop sta connection
|
||||
*/
|
||||
hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
|
||||
if (!hdd_ap_ctx) {
|
||||
hdd_err("AP context not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (req->channel && req->channel->center_freq) {
|
||||
ch_freq = req->channel->center_freq;
|
||||
goto def_chan;
|
||||
}
|
||||
/*
|
||||
* find out by looking in to scan cache where sta is going to
|
||||
* connect by passing its ssid amd bssid.
|
||||
*/
|
||||
scan_filter = qdf_mem_malloc(sizeof(*scan_filter));
|
||||
if (!scan_filter)
|
||||
goto def_chan;
|
||||
|
||||
if (req->bssid) {
|
||||
scan_filter->num_of_bssid = 1;
|
||||
qdf_mem_copy(scan_filter->bssid_list[0].bytes, req->bssid,
|
||||
QDF_MAC_ADDR_SIZE);
|
||||
}
|
||||
scan_filter->num_of_ssid = 1;
|
||||
scan_filter->ssid_list[0].length =
|
||||
QDF_MIN(req->ssid_len, QDF_MAC_ADDR_SIZE);
|
||||
qdf_mem_copy(scan_filter->ssid_list[0].ssid, req->ssid,
|
||||
scan_filter->ssid_list[0].length);
|
||||
scan_filter->ignore_auth_enc_type = true;
|
||||
list = ucfg_scan_get_result(hdd_ctx->pdev, scan_filter);
|
||||
qdf_mem_free(scan_filter);
|
||||
|
||||
if (!list || (list && !qdf_list_size(list))) {
|
||||
hdd_debug("scan list empty");
|
||||
goto purge_list;
|
||||
}
|
||||
qdf_list_peek_front(list, &cur_lst);
|
||||
if (!cur_lst)
|
||||
goto purge_list;
|
||||
|
||||
cur_node = qdf_container_of(cur_lst, struct scan_cache_node, node);
|
||||
ch_freq = cur_node->entry->channel.chan_freq;
|
||||
purge_list:
|
||||
if (list)
|
||||
ucfg_scan_purge_results(list);
|
||||
def_chan:
|
||||
/*
|
||||
* If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
|
||||
* channels for roaming case.
|
||||
*/
|
||||
if (WLAN_REG_IS_24GHZ_CH_FREQ(ch_freq)) {
|
||||
hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* If channel is 0 or DFS or LTE unsafe then better to call pcl and
|
||||
* find out the best channel. If channel is non-dfs 5 GHz then
|
||||
* better move SAP to STA's channel to make scc, so we have room
|
||||
* for 3port MCC scenario.
|
||||
*/
|
||||
if (!ch_freq || wlan_reg_is_dfs_for_freq(hdd_ctx->pdev, ch_freq) ||
|
||||
!policy_mgr_is_safe_channel(hdd_ctx->psoc, ch_freq))
|
||||
ch_freq = policy_mgr_get_nondfs_preferred_channel(
|
||||
hdd_ctx->psoc, PM_SAP_MODE, true);
|
||||
|
||||
hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
|
||||
qdf_event_reset(&hostapd_state->qdf_event);
|
||||
wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, ap_adapter->vdev_id,
|
||||
CSA_REASON_STA_CONNECT_DFS_TO_NON_DFS);
|
||||
|
||||
status = wlansap_set_channel_change_with_csa(
|
||||
WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), ch_freq,
|
||||
hdd_ap_ctx->sap_config.ch_width_orig, false);
|
||||
|
||||
if (QDF_STATUS_SUCCESS != status) {
|
||||
hdd_err("Set channel with CSA IE failed, can't allow STA");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* wait here for SAP to finish the channel switch. When channel
|
||||
* switch happens, SAP sends few beacons with CSA_IE. After
|
||||
* successfully Transmission of those beacons, it will move its
|
||||
* state from started to disconnected and move to new channel.
|
||||
* once it moves to new channel, sap again moves its state
|
||||
* machine from disconnected to started and set this event.
|
||||
* wait for 10 secs to finish this.
|
||||
*/
|
||||
status = qdf_wait_for_event_completion(&hostapd_state->qdf_event,
|
||||
10000);
|
||||
if (!QDF_IS_STATUS_SUCCESS(status)) {
|
||||
hdd_err("wait for qdf_event failed, STA not allowed!!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int wlan_hdd_cm_connect(struct wiphy *wiphy,
|
||||
struct net_device *ndev,
|
||||
struct cfg80211_connect_params *req)
|
||||
@@ -427,6 +611,12 @@ int wlan_hdd_cm_connect(struct wiphy *wiphy,
|
||||
|
||||
hdd_reg_wait_for_country_change(hdd_ctx);
|
||||
|
||||
if (policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc) &&
|
||||
!wlan_hdd_cm_handle_sap_sta_dfs_conc(hdd_ctx, req)) {
|
||||
hdd_err("sap-sta conc will fail, can't allow sta");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
qdf_mem_zero(¶ms, sizeof(params));
|
||||
ucfg_blm_dump_black_list_ap(hdd_ctx->pdev);
|
||||
vdev = hdd_objmgr_get_vdev_by_user(adapter, WLAN_OSIF_CM_ID);
|
||||
|
Reference in New Issue
Block a user