qcacmn: Add MCL/SAP DCS process after AFC event update
When AFC event come and update 6 GHz SP channels' state and power attribution, SAP which already started on 5 GHz or 6 GHz channel can move in or out from SP channel, which has higher tx power limit. SAP target channel/bandwidth is decided by ACS channel select callback register to SAP module, which will take channel max tx power limit into account. After target channel/bandwidth determined, SAPs move to same target channel/bandwidth with eCSA process. If violate any concurrency limitation, AFC DCS process should abort. Add AFC component id and reference id. Change-Id: Iba6933a30c0957eabf549fd6c8442bed547e8152 CRs-Fixed: 3204172
This commit is contained in:
parent
051821c54f
commit
dc9e47060f
@ -34,6 +34,9 @@
|
||||
#include <target_if_reg_lte.h>
|
||||
#include <wlan_reg_ucfg_api.h>
|
||||
#include <wlan_utility.h>
|
||||
#ifdef CONFIG_REG_CLIENT
|
||||
#include <wlan_dcs_tgt_api.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* get_chan_list_cc_event_id() - Get chan_list_cc event i
|
||||
@ -849,11 +852,19 @@ static void target_if_register_afc_event_handler(
|
||||
tgt_if_regulatory_unregister_afc_event_handler;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_REG_CLIENT
|
||||
static void target_if_register_acs_trigger_for_afc
|
||||
(struct wlan_lmac_if_reg_tx_ops *reg_ops)
|
||||
{
|
||||
reg_ops->trigger_acs_for_afc = tgt_afc_trigger_dcs;
|
||||
}
|
||||
#else
|
||||
static void target_if_register_acs_trigger_for_afc
|
||||
(struct wlan_lmac_if_reg_tx_ops *reg_ops)
|
||||
{
|
||||
reg_ops->trigger_acs_for_afc = NULL;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
static void target_if_register_afc_event_handler(
|
||||
struct wlan_lmac_if_reg_tx_ops *reg_ops)
|
||||
|
@ -297,6 +297,7 @@
|
||||
* @WLAN_COMP_DP: DP component
|
||||
* @WLAN_UMAC_COMP_COAP: Constrained Application Protocol component
|
||||
* @WLAN_UMAC_COMP_QMI: QMI component
|
||||
* @WLAN_UMAC_COMP_AFC: AFC component
|
||||
* @WLAN_UMAC_COMP_ID_MAX: Maximum components in UMAC
|
||||
*
|
||||
* This id is static.
|
||||
@ -353,6 +354,7 @@ enum wlan_umac_comp_id {
|
||||
WLAN_COMP_TELEMETRY_AGENT = 47,
|
||||
WLAN_UMAC_COMP_COAP = 48,
|
||||
WLAN_UMAC_COMP_QMI = 49,
|
||||
WLAN_UMAC_COMP_AFC = 50,
|
||||
WLAN_UMAC_COMP_ID_MAX,
|
||||
};
|
||||
|
||||
|
@ -291,6 +291,7 @@ typedef void (*wlan_objmgr_peer_status_handler)(
|
||||
* @WLAN_COAP_ID: Constrained Application Protocol reference id
|
||||
* @WLAN_SAWF_ID: Service Aware Wifi reference id
|
||||
* @WLAN_QMI_ID: QMI component id
|
||||
* @WLAN_AFC_ID: AFC reference id
|
||||
* @WLAN_REF_ID_MAX: Max id used to generate ref count tracking array
|
||||
*/
|
||||
/* New value added to the enum must also be reflected in function
|
||||
@ -400,6 +401,7 @@ typedef enum {
|
||||
WLAN_COAP_ID = 99,
|
||||
WLAN_SAWF_ID = 100,
|
||||
WLAN_QMI_ID = 101,
|
||||
WLAN_AFC_ID = 102,
|
||||
WLAN_REF_ID_MAX,
|
||||
} wlan_objmgr_ref_dbgid;
|
||||
|
||||
@ -513,7 +515,8 @@ static inline const char *string_from_dbgid(wlan_objmgr_ref_dbgid id)
|
||||
"WLAN_DP_ID",
|
||||
"WLAN_COAP_ID",
|
||||
"WLAN_SAWF_ID",
|
||||
"WLAN_QMI_ID"
|
||||
"WLAN_QMI_ID",
|
||||
"WLAN_AFC_ID"
|
||||
};
|
||||
|
||||
if (id >= WLAN_REF_ID_MAX)
|
||||
|
@ -31,6 +31,7 @@
|
||||
#ifdef WLAN_POLICY_MGR_ENABLE
|
||||
#include "wlan_policy_mgr_api.h"
|
||||
#endif
|
||||
#include <wlan_reg_services_api.h>
|
||||
|
||||
struct dcs_pdev_priv_obj *
|
||||
wlan_dcs_get_pdev_private_obj(struct wlan_objmgr_psoc *psoc, uint32_t pdev_id)
|
||||
@ -1371,6 +1372,485 @@ wlan_dcs_awgn_process(struct wlan_objmgr_psoc *psoc, uint8_t pdev_id,
|
||||
wlan_objmgr_pdev_release_ref(pdev, WLAN_DCS_ID);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AFC_SUPPORT
|
||||
/**
|
||||
* wlan_dcs_afc_sel_chan() - Select SAP new channel/bandwidth when AFC updated
|
||||
* @psoc: pointer to soc
|
||||
* @vdev_id: vdev id
|
||||
* @cur_freq: current channel frequency
|
||||
* @cur_bw: current channel bandwidth
|
||||
* @pref_bw: pointer to bandwidth of prefer to switch to when input, and target
|
||||
* bandwidth decided to switch to
|
||||
*
|
||||
* Return: target channel frequency to switch to
|
||||
*/
|
||||
static qdf_freq_t wlan_dcs_afc_sel_chan(struct wlan_objmgr_psoc *psoc,
|
||||
uint32_t vdev_id,
|
||||
qdf_freq_t cur_freq,
|
||||
enum phy_ch_width cur_bw,
|
||||
enum phy_ch_width *pref_bw)
|
||||
{
|
||||
struct dcs_psoc_priv_obj *dcs_psoc_priv;
|
||||
dcs_afc_select_chan_cb afc_sel_chan_cb;
|
||||
|
||||
if (!psoc)
|
||||
return 0;
|
||||
|
||||
dcs_psoc_priv = wlan_objmgr_psoc_get_comp_private_obj(
|
||||
psoc,
|
||||
WLAN_UMAC_COMP_DCS);
|
||||
if (!dcs_psoc_priv)
|
||||
return 0;
|
||||
|
||||
afc_sel_chan_cb = dcs_psoc_priv->afc_sel_chan_cbk.cbk;
|
||||
if (!afc_sel_chan_cb)
|
||||
return 0;
|
||||
|
||||
return afc_sel_chan_cb(dcs_psoc_priv->afc_sel_chan_cbk.arg,
|
||||
vdev_id, cur_freq, cur_bw, pref_bw);
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_dcs_afc_get_conn_info() - Iterate function to get connection channel
|
||||
* information of every vdev
|
||||
* @pdev: pointer to pdev
|
||||
* @object: pointer to iteration object
|
||||
* @arg: pointer to iteration argument
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static void
|
||||
wlan_dcs_afc_get_conn_info(struct wlan_objmgr_pdev *pdev,
|
||||
void *object, void *arg)
|
||||
{
|
||||
struct wlan_objmgr_vdev *vdev = object;
|
||||
struct wlan_dcs_conn_info *conn_info = arg;
|
||||
enum QDF_OPMODE op_mode;
|
||||
struct wlan_channel *chan;
|
||||
uint8_t vdev_id;
|
||||
|
||||
if (!vdev || !pdev || !conn_info)
|
||||
return;
|
||||
|
||||
if (conn_info->exit_condition)
|
||||
return;
|
||||
|
||||
if (wlan_vdev_mlme_is_active(vdev) != QDF_STATUS_SUCCESS)
|
||||
return;
|
||||
|
||||
vdev_id = wlan_vdev_get_id(vdev);
|
||||
op_mode = wlan_vdev_mlme_get_opmode(vdev);
|
||||
chan = wlan_vdev_get_active_channel(vdev);
|
||||
if (!chan)
|
||||
return;
|
||||
|
||||
switch (op_mode) {
|
||||
case QDF_STA_MODE:
|
||||
if (conn_info->sta_cnt >= WLAN_DCS_MAX_STA_NUM) {
|
||||
dcs_debug("too many STAs");
|
||||
conn_info->exit_condition = true;
|
||||
break;
|
||||
}
|
||||
conn_info->sta[conn_info->sta_cnt].freq = chan->ch_freq;
|
||||
conn_info->sta[conn_info->sta_cnt].bw = chan->ch_width;
|
||||
conn_info->sta[conn_info->sta_cnt].vdev_id = vdev_id;
|
||||
conn_info->sta_cnt++;
|
||||
break;
|
||||
case QDF_SAP_MODE:
|
||||
if (WLAN_REG_IS_5GHZ_CH_FREQ(chan->ch_freq)) {
|
||||
if (conn_info->sap_5ghz_cnt >= WLAN_DCS_MAX_SAP_NUM) {
|
||||
dcs_debug("too many 5 GHz SAPs");
|
||||
conn_info->exit_condition = true;
|
||||
}
|
||||
conn_info->sap_5ghz[conn_info->sap_5ghz_cnt].freq =
|
||||
chan->ch_freq;
|
||||
conn_info->sap_5ghz[conn_info->sap_5ghz_cnt].bw =
|
||||
chan->ch_width;
|
||||
conn_info->sap_5ghz[conn_info->sap_5ghz_cnt].vdev_id =
|
||||
vdev_id;
|
||||
conn_info->sap_5ghz_cnt++;
|
||||
} else if (WLAN_REG_IS_6GHZ_CHAN_FREQ(chan->ch_freq)) {
|
||||
if (conn_info->sap_6ghz_cnt >= WLAN_DCS_MAX_SAP_NUM) {
|
||||
dcs_debug("too many 6 GHz SAPs");
|
||||
conn_info->exit_condition = true;
|
||||
}
|
||||
conn_info->sap_6ghz[conn_info->sap_6ghz_cnt].freq =
|
||||
chan->ch_freq;
|
||||
conn_info->sap_6ghz[conn_info->sap_6ghz_cnt].bw =
|
||||
chan->ch_width;
|
||||
conn_info->sap_6ghz[conn_info->sap_6ghz_cnt].vdev_id =
|
||||
vdev_id;
|
||||
conn_info->sap_6ghz_cnt++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dcs_debug("not support op mode %d", op_mode);
|
||||
conn_info->exit_condition = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_dcs_afc_reduce_bw() - Get target bandwidth with fixed channel frequency
|
||||
* @pdev: pointer to pdev
|
||||
* @freq: channel frequency which is fixed because SCC with STA
|
||||
* @input_bw: SAP current channel bandwidth
|
||||
*
|
||||
* This function check every sub 20 MHz channel state which update by AFC, and
|
||||
* reduce channel bandwidth if sub channel is disable.
|
||||
*
|
||||
* Return: Reduced channel bandwidth
|
||||
*/
|
||||
static enum phy_ch_width wlan_dcs_afc_reduce_bw(struct wlan_objmgr_pdev *pdev,
|
||||
qdf_freq_t freq,
|
||||
enum phy_ch_width input_bw)
|
||||
{
|
||||
const struct bonded_channel_freq *bonded_chan_ptr = NULL;
|
||||
enum channel_state state;
|
||||
qdf_freq_t start_freq;
|
||||
bool find;
|
||||
|
||||
if (input_bw <= CH_WIDTH_20MHZ)
|
||||
return input_bw;
|
||||
|
||||
while (input_bw > CH_WIDTH_20MHZ) {
|
||||
state = wlan_reg_get_5g_bonded_channel_and_state_for_freq(
|
||||
pdev, freq, input_bw, &bonded_chan_ptr);
|
||||
if (state != CHANNEL_STATE_ENABLE) {
|
||||
input_bw = wlan_reg_get_next_lower_bandwidth(input_bw);
|
||||
continue;
|
||||
}
|
||||
find = false;
|
||||
start_freq = bonded_chan_ptr->start_freq;
|
||||
while (start_freq <= bonded_chan_ptr->end_freq) {
|
||||
if (wlan_reg_is_disable_in_secondary_list_for_freq(
|
||||
pdev, start_freq)) {
|
||||
find = true;
|
||||
break;
|
||||
}
|
||||
start_freq += 20;
|
||||
}
|
||||
if (find)
|
||||
input_bw = wlan_reg_get_next_lower_bandwidth(input_bw);
|
||||
else
|
||||
return input_bw;
|
||||
}
|
||||
return input_bw;
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_sap_update_tpc_on_channel() - Update vdev channel TPC parameters and
|
||||
* send TPC command
|
||||
* @pdev: pointer to pdev
|
||||
* @vdev_id: vdev id
|
||||
* @freq: SAP 6 GHz channel frequency
|
||||
* @bw: SAP 6 GHz channel bandwidth
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static void
|
||||
wlan_sap_update_tpc_on_channel(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
|
||||
qdf_freq_t freq, enum phy_ch_width bw)
|
||||
{
|
||||
struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
|
||||
struct wlan_lmac_if_reg_tx_ops *tx_ops;
|
||||
struct vdev_mlme_obj *mlme_obj;
|
||||
struct wlan_objmgr_vdev *vdev;
|
||||
struct reg_tpc_power_info *tpc;
|
||||
bool is_psd;
|
||||
uint32_t i;
|
||||
uint16_t tx_power;
|
||||
int16_t psd_eirp;
|
||||
enum reg_6g_ap_type power_type;
|
||||
|
||||
if (!wlan_reg_is_ext_tpc_supported(psoc))
|
||||
return;
|
||||
|
||||
if (wlan_reg_decide_6ghz_power_within_bw_for_freq(
|
||||
pdev, freq, bw, &is_psd, &tx_power, &psd_eirp, &power_type) !=
|
||||
QDF_STATUS_SUCCESS)
|
||||
return;
|
||||
|
||||
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, WLAN_DCS_ID);
|
||||
if (!vdev)
|
||||
return;
|
||||
|
||||
tx_ops = wlan_reg_get_tx_ops(psoc);
|
||||
|
||||
mlme_obj = wlan_vdev_mlme_get_cmpt_obj(vdev);
|
||||
if (!mlme_obj) {
|
||||
dcs_err("vdev mlme obj is NULL");
|
||||
goto release_vdev;
|
||||
}
|
||||
|
||||
tpc = &mlme_obj->reg_tpc_obj;
|
||||
if (tpc->is_psd_power != is_psd) {
|
||||
dcs_debug("psd flag changed");
|
||||
goto release_vdev;
|
||||
}
|
||||
tpc->eirp_power = tx_power;
|
||||
tpc->power_type_6g = power_type;
|
||||
for (i = 0; i < tpc->num_pwr_levels; i++) {
|
||||
if (is_psd)
|
||||
tpc->chan_power_info[i].tx_power = (uint8_t)psd_eirp;
|
||||
else
|
||||
tpc->chan_power_info[i].tx_power = (uint8_t)tx_power;
|
||||
}
|
||||
|
||||
dcs_debug("6 GHz pwr type %d, is psd %d, pwr %d, psd %d, num pwr %d",
|
||||
power_type, is_psd, tx_power, psd_eirp, tpc->num_pwr_levels);
|
||||
|
||||
if (tx_ops->set_tpc_power)
|
||||
tx_ops->set_tpc_power(psoc, vdev_id, tpc);
|
||||
|
||||
release_vdev:
|
||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_DCS_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_dcs_afc_sap_dcs_with_sta() - SAP channel switch when coexist with STA
|
||||
* @pdev: pointer to pdev handle
|
||||
* @conn_info: pointer to connection context of AFC DCS
|
||||
*
|
||||
* This function update TPC or restart SAP if doing SCC on 6 GHz with STA
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static void
|
||||
wlan_dcs_afc_sap_dcs_with_sta(struct wlan_objmgr_pdev *pdev,
|
||||
struct wlan_dcs_conn_info *conn_info)
|
||||
{
|
||||
uint32_t i;
|
||||
qdf_freq_t target_freq = conn_info->sta[0].freq;
|
||||
enum phy_ch_width target_bw = CH_WIDTH_20MHZ;
|
||||
struct wlan_objmgr_vdev *vdev;
|
||||
|
||||
if (!WLAN_REG_IS_6GHZ_CHAN_FREQ(conn_info->sta[0].freq))
|
||||
return;
|
||||
|
||||
for (i = 0; i < conn_info->sap_6ghz_cnt; i++) {
|
||||
if (conn_info->sap_6ghz[i].freq ==
|
||||
conn_info->sta[0].freq) {
|
||||
/*
|
||||
* sta operate under control of ap, if stop sap,
|
||||
* cannot start by itself, so just update tpc as sta,
|
||||
* if tx power is minimum of SCC tpc commands, no
|
||||
* need to update sap tpc command.
|
||||
* assume sta will move to safe channel by ap and
|
||||
* sap can move channel accordingly.
|
||||
*/
|
||||
if (wlan_reg_is_disable_in_secondary_list_for_freq(
|
||||
pdev, conn_info->sta[0].freq))
|
||||
continue;
|
||||
|
||||
target_bw = wlan_dcs_afc_reduce_bw(
|
||||
pdev,
|
||||
conn_info->sap_6ghz[i].freq,
|
||||
conn_info->sap_6ghz[i].bw);
|
||||
|
||||
if (target_bw == conn_info->sap_6ghz[i].bw) {
|
||||
wlan_sap_update_tpc_on_channel(
|
||||
pdev,
|
||||
conn_info->sap_6ghz[i].vdev_id,
|
||||
conn_info->sap_6ghz[i].freq,
|
||||
target_bw);
|
||||
continue;
|
||||
}
|
||||
|
||||
vdev = wlan_objmgr_get_vdev_by_id_from_pdev(
|
||||
pdev,
|
||||
conn_info->sap_6ghz[i].vdev_id,
|
||||
WLAN_DCS_ID);
|
||||
if (!vdev)
|
||||
continue;
|
||||
|
||||
/* tpc update once csa complete */
|
||||
wlan_dcs_switch_chan(vdev, target_freq, target_bw);
|
||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_DCS_ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WLAN_POLICY_MGR_ENABLE
|
||||
/**
|
||||
* wlan_dcs_afc_6ghz_capable() - API to check SAP configure is able to operate
|
||||
* on 6 GHz
|
||||
* @psoc: pointer to SOC
|
||||
* @vdev_id: vdev id
|
||||
*
|
||||
* Return: Return true if SAP is able to operate on 6 GHz
|
||||
*/
|
||||
static inline bool
|
||||
wlan_dcs_afc_6ghz_capable(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
|
||||
{
|
||||
return policy_mgr_get_ap_6ghz_capable(psoc, vdev_id, NULL);
|
||||
}
|
||||
#else
|
||||
static inline bool
|
||||
wlan_dcs_afc_6ghz_capable(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* wlan_dcs_afc_5ghz6ghz_sap_dcs() - SAP on 5 GHz or 6 GHz channel to do
|
||||
* channel switch.
|
||||
* @pdev: pointer to pdev handle
|
||||
* @conn_info: pointer to connection context for AFC DCS
|
||||
*
|
||||
* This function is trigger by AFC event and 6 GHz channels' state has been
|
||||
* updated, restart SAP to SP channel if possible, gain better performance.
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static void
|
||||
wlan_dcs_afc_5ghz6ghz_sap_dcs(struct wlan_objmgr_pdev *pdev,
|
||||
struct wlan_dcs_conn_info *conn_info)
|
||||
{
|
||||
uint32_t i;
|
||||
struct wlan_objmgr_vdev *vdev;
|
||||
uint8_t max_bw_vdev_id;
|
||||
qdf_freq_t max_bw_freq, target_freq;
|
||||
enum phy_ch_width max_bw = CH_WIDTH_20MHZ;
|
||||
enum phy_ch_width pref_bw;
|
||||
|
||||
if (conn_info->sap_5ghz_cnt) {
|
||||
max_bw = conn_info->sap_5ghz[0].bw;
|
||||
max_bw_vdev_id = conn_info->sap_5ghz[0].vdev_id;
|
||||
max_bw_freq = conn_info->sap_5ghz[0].freq;
|
||||
for (i = 1; i < conn_info->sap_5ghz_cnt; i++) {
|
||||
if (conn_info->sap_5ghz[i].bw > max_bw) {
|
||||
max_bw = conn_info->sap_5ghz[i].bw;
|
||||
max_bw_vdev_id = conn_info->sap_5ghz[i].vdev_id;
|
||||
max_bw_freq = conn_info->sap_5ghz[i].freq;
|
||||
}
|
||||
}
|
||||
} else if (conn_info->sap_6ghz_cnt) {
|
||||
max_bw = conn_info->sap_6ghz[0].bw;
|
||||
max_bw_vdev_id = conn_info->sap_6ghz[0].vdev_id;
|
||||
max_bw_freq = conn_info->sap_6ghz[0].freq;
|
||||
for (i = 1; i < conn_info->sap_6ghz_cnt; i++) {
|
||||
if (conn_info->sap_6ghz[i].bw > max_bw) {
|
||||
max_bw = conn_info->sap_6ghz[i].bw;
|
||||
max_bw_vdev_id = conn_info->sap_6ghz[i].vdev_id;
|
||||
max_bw_freq = conn_info->sap_6ghz[i].freq;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* After several AFC event update, if maximum bandwidth shrink to
|
||||
* 20 MHz, set prefer bandwidth to pre-defined value like 80 MHz,
|
||||
* so it can expand bandwidth and gain better performance.
|
||||
*/
|
||||
if (max_bw == CH_WIDTH_20MHZ)
|
||||
pref_bw = WLAN_DCS_AFC_PREFER_BW;
|
||||
else
|
||||
pref_bw = max_bw;
|
||||
|
||||
target_freq = wlan_dcs_afc_sel_chan(
|
||||
wlan_pdev_get_psoc(pdev),
|
||||
max_bw_vdev_id,
|
||||
max_bw_freq, max_bw, &pref_bw);
|
||||
|
||||
if (!target_freq)
|
||||
return;
|
||||
|
||||
if (WLAN_REG_IS_6GHZ_CHAN_FREQ(target_freq) &&
|
||||
conn_info->sap_5ghz_cnt) {
|
||||
for (i = 0; i < conn_info->sap_5ghz_cnt; i++) {
|
||||
if (!wlan_dcs_afc_6ghz_capable(
|
||||
wlan_pdev_get_psoc(pdev),
|
||||
conn_info->sap_5ghz[i].vdev_id)) {
|
||||
dcs_debug("vdev %d has no 6 GHz capability",
|
||||
conn_info->sap_5ghz[i].vdev_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (conn_info->sap_5ghz_cnt) {
|
||||
for (i = 0; i < conn_info->sap_5ghz_cnt; i++) {
|
||||
if (target_freq == conn_info->sap_5ghz[i].freq &&
|
||||
pref_bw == conn_info->sap_5ghz[i].bw)
|
||||
continue;
|
||||
vdev = wlan_objmgr_get_vdev_by_id_from_pdev(
|
||||
pdev,
|
||||
conn_info->sap_5ghz[i].vdev_id,
|
||||
WLAN_DCS_ID);
|
||||
if (!vdev)
|
||||
continue;
|
||||
|
||||
wlan_dcs_switch_chan(vdev, target_freq, pref_bw);
|
||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_DCS_ID);
|
||||
}
|
||||
} else if (conn_info->sap_6ghz_cnt) {
|
||||
for (i = 0; i < conn_info->sap_6ghz_cnt; i++) {
|
||||
if (target_freq == conn_info->sap_6ghz[i].freq &&
|
||||
pref_bw == conn_info->sap_6ghz[i].bw)
|
||||
continue;
|
||||
vdev = wlan_objmgr_get_vdev_by_id_from_pdev(
|
||||
pdev,
|
||||
conn_info->sap_6ghz[i].vdev_id,
|
||||
WLAN_DCS_ID);
|
||||
if (!vdev)
|
||||
continue;
|
||||
|
||||
wlan_dcs_switch_chan(vdev, target_freq, pref_bw);
|
||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_DCS_ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* wlan_dcs_afc_process() - Dynamic SAP channel switch after AFC update
|
||||
* @psoc: psoc handle
|
||||
* @pdev_id: pdev id
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static void
|
||||
wlan_dcs_afc_process(struct wlan_objmgr_psoc *psoc, uint8_t pdev_id)
|
||||
{
|
||||
struct wlan_objmgr_pdev *pdev;
|
||||
struct wlan_dcs_conn_info conn_info = {0};
|
||||
|
||||
pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, WLAN_DCS_ID);
|
||||
if (!pdev) {
|
||||
dcs_err("Invalid pdev id %d", pdev_id);
|
||||
return;
|
||||
}
|
||||
|
||||
wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
|
||||
wlan_dcs_afc_get_conn_info,
|
||||
&conn_info, 0, WLAN_DCS_ID);
|
||||
if (conn_info.exit_condition)
|
||||
goto pdev_release;
|
||||
|
||||
if ((conn_info.sap_5ghz_cnt && conn_info.sap_6ghz_cnt) ||
|
||||
(!conn_info.sap_5ghz_cnt && !conn_info.sap_6ghz_cnt)) {
|
||||
dcs_debug("NA for %d 5 GHz SAP, %d 6 GHz SAP",
|
||||
conn_info.sap_5ghz_cnt, conn_info.sap_6ghz_cnt);
|
||||
goto pdev_release;
|
||||
}
|
||||
|
||||
if (conn_info.sta_cnt &&
|
||||
!WLAN_REG_IS_24GHZ_CH_FREQ(conn_info.sta[0].freq))
|
||||
wlan_dcs_afc_sap_dcs_with_sta(pdev, &conn_info);
|
||||
else
|
||||
wlan_dcs_afc_5ghz6ghz_sap_dcs(pdev, &conn_info);
|
||||
|
||||
pdev_release:
|
||||
wlan_objmgr_pdev_release_ref(pdev, WLAN_DCS_ID);
|
||||
}
|
||||
#else
|
||||
static inline void
|
||||
wlan_dcs_afc_process(struct wlan_objmgr_psoc *psoc, uint8_t pdev_id) {}
|
||||
#endif
|
||||
|
||||
QDF_STATUS
|
||||
wlan_dcs_process(struct wlan_objmgr_psoc *psoc,
|
||||
struct wlan_host_dcs_event *event)
|
||||
@ -1427,6 +1907,9 @@ wlan_dcs_process(struct wlan_objmgr_psoc *psoc,
|
||||
wlan_dcs_awgn_process(psoc, event->dcs_param.pdev_id,
|
||||
&event->awgn_info);
|
||||
break;
|
||||
case WLAN_HOST_DCS_AFC:
|
||||
wlan_dcs_afc_process(psoc, event->dcs_param.pdev_id);
|
||||
break;
|
||||
default:
|
||||
dcs_err("unidentified interference type reported");
|
||||
break;
|
||||
|
@ -144,6 +144,52 @@ struct psoc_dcs_cbk {
|
||||
void *arg;
|
||||
};
|
||||
|
||||
#define WLAN_DCS_MAX_STA_NUM 1
|
||||
#define WLAN_DCS_MAX_SAP_NUM 2
|
||||
#define WLAN_DCS_AFC_PREFER_BW CH_WIDTH_80MHZ
|
||||
|
||||
/**
|
||||
* struct connection_chan_info - define connection channel information
|
||||
* @freq: channel frequency
|
||||
* @bw: channel bandwidth
|
||||
* @vdev_id: connection vdev id
|
||||
*/
|
||||
struct connection_chan_info {
|
||||
qdf_freq_t freq;
|
||||
enum phy_ch_width bw;
|
||||
uint8_t vdev_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wlan_dcs_conn_info - define arguments list for DCS when AFC updated
|
||||
* @sta_cnt: station count
|
||||
* @sap_5ghz_cnt: 5 GHz sap count
|
||||
* @sap_6ghz_cnt: 6 GHz sap count
|
||||
* @sta: connection info of station
|
||||
* @sap_5ghz: connection info of 5 GHz sap
|
||||
* @sap_6ghz: connection info of 6 GHz sap
|
||||
* @exit_condition: flag to exit iteration immediately
|
||||
*/
|
||||
struct wlan_dcs_conn_info {
|
||||
uint8_t sta_cnt;
|
||||
uint8_t sap_5ghz_cnt;
|
||||
uint8_t sap_6ghz_cnt;
|
||||
struct connection_chan_info sta[WLAN_DCS_MAX_STA_NUM];
|
||||
struct connection_chan_info sap_5ghz[WLAN_DCS_MAX_SAP_NUM];
|
||||
struct connection_chan_info sap_6ghz[WLAN_DCS_MAX_SAP_NUM];
|
||||
bool exit_condition;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dcs_afc_select_chan_cbk - define sap afc select channel callback
|
||||
* @cbk: callback
|
||||
* @arg: argument supply by register
|
||||
*/
|
||||
struct dcs_afc_select_chan_cbk {
|
||||
dcs_afc_select_chan_cb cbk;
|
||||
void *arg;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dcs_pdev_priv_obj - define dcs pdev priv
|
||||
* @dcs_host_params: dcs host configuration parameter
|
||||
@ -218,11 +264,13 @@ enum wlan_dcs_chan_seg {
|
||||
* @dcs_pdev_priv: dcs pdev priv
|
||||
* @dcs_cbk: dcs callback
|
||||
* @switch_chan_cb: callback for switching channel
|
||||
* @afc_sel_chan_cbk: callback for afc channel selection
|
||||
*/
|
||||
struct dcs_psoc_priv_obj {
|
||||
struct dcs_pdev_priv_obj dcs_pdev_priv[WLAN_DCS_MAX_PDEVS];
|
||||
struct psoc_dcs_cbk dcs_cbk;
|
||||
dcs_switch_chan_cb switch_chan_cb;
|
||||
struct dcs_afc_select_chan_cbk afc_sel_chan_cbk;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -28,12 +28,14 @@
|
||||
* @WLAN_HOST_DCS_CWIM: continuous wave interference
|
||||
* @WLAN_HOST_DCS_WLANIM: wlan interference stats
|
||||
* @WLAN_HOST_DCS_AWGNIM: additive white Gaussian noise (awgn) interference
|
||||
* @WLAN_HOST_DCS_AFC: AFC data update 6 GHz SP channels
|
||||
*/
|
||||
enum wlan_host_dcs_type {
|
||||
WLAN_HOST_DCS_NONE = 0, /* 0x0 */
|
||||
WLAN_HOST_DCS_CWIM = BIT(0), /* 0x1 */
|
||||
WLAN_HOST_DCS_WLANIM = BIT(1), /* 0x2 */
|
||||
WLAN_HOST_DCS_AWGNIM = BIT(2), /* 0x4 */
|
||||
WLAN_HOST_DCS_AFC = BIT(3), /* 0x8 */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 above
|
||||
@ -36,5 +37,13 @@
|
||||
*/
|
||||
QDF_STATUS tgt_dcs_process_event(struct wlan_objmgr_psoc *psoc,
|
||||
struct wlan_host_dcs_event *event);
|
||||
|
||||
#ifdef CONFIG_AFC_SUPPORT
|
||||
/**
|
||||
* tgt_afc_trigger_dcs() - AFC event DCS process
|
||||
* @pdev: pointer to pdev object
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS tgt_afc_trigger_dcs(struct wlan_objmgr_pdev *pdev);
|
||||
#endif
|
||||
#endif /* __WLAN_DCS_TGT_API_H__ */
|
||||
|
@ -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 above
|
||||
@ -49,6 +49,21 @@ typedef QDF_STATUS (*dcs_switch_chan_cb)(struct wlan_objmgr_vdev *vdev,
|
||||
qdf_freq_t tgt_freq,
|
||||
enum phy_ch_width tgt_width);
|
||||
|
||||
/**
|
||||
* typedef dcs_afc_select_chan_cb() - DCS callback for AFC channel selection
|
||||
* @arg: pointer to argument
|
||||
* @vdev_id: vdev id
|
||||
* @cur_freq: current channel frequency
|
||||
* @cur_bw: current channel bandwidth
|
||||
* @pref_bw: pointer to bandwidth of prefer bandwidth when input, and target
|
||||
* bandwidth switch to when output
|
||||
*/
|
||||
typedef qdf_freq_t (*dcs_afc_select_chan_cb)(void *arg,
|
||||
uint32_t vdev_id,
|
||||
qdf_freq_t cur_freq,
|
||||
enum phy_ch_width cur_bw,
|
||||
enum phy_ch_width *pref_bw);
|
||||
|
||||
#ifdef DCS_INTERFERENCE_DETECTION
|
||||
/**
|
||||
* ucfg_dcs_register_cb() - API to register dcs callback
|
||||
@ -90,6 +105,18 @@ void ucfg_dcs_register_user_cb(struct wlan_objmgr_psoc *psoc,
|
||||
QDF_STATUS ucfg_dcs_register_awgn_cb(struct wlan_objmgr_psoc *psoc,
|
||||
dcs_switch_chan_cb cb);
|
||||
|
||||
/**
|
||||
* ucfg_dcs_register_afc_sel_chan_cb() - API to register SAP channel selection
|
||||
* callback for AFC DCS
|
||||
* @psoc: pointer to psoc object
|
||||
* @cb: dcs user callback to be registered
|
||||
* @arg: argument
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS ucfg_dcs_register_afc_sel_chan_cb(struct wlan_objmgr_psoc *psoc,
|
||||
dcs_afc_select_chan_cb cb,
|
||||
void *arg);
|
||||
/**
|
||||
* ucfg_wlan_dcs_cmd(): API to send dcs command
|
||||
* @psoc: pointer to psoc object
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 above
|
||||
@ -28,3 +29,25 @@ QDF_STATUS tgt_dcs_process_event(struct wlan_objmgr_psoc *psoc,
|
||||
{
|
||||
return wlan_dcs_process(psoc, event);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_AFC_SUPPORT
|
||||
QDF_STATUS tgt_afc_trigger_dcs(struct wlan_objmgr_pdev *pdev)
|
||||
{
|
||||
struct wlan_objmgr_psoc *psoc;
|
||||
struct wlan_host_dcs_event *event;
|
||||
QDF_STATUS status;
|
||||
|
||||
psoc = wlan_pdev_get_psoc(pdev);
|
||||
|
||||
event = qdf_mem_malloc(sizeof(*event));
|
||||
if (!event)
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
|
||||
event->dcs_param.interference_type = WLAN_HOST_DCS_AFC;
|
||||
event->dcs_param.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
|
||||
status = wlan_dcs_process(psoc, event);
|
||||
|
||||
qdf_mem_free(event);
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 above
|
||||
@ -77,6 +78,24 @@ QDF_STATUS ucfg_dcs_register_awgn_cb(struct wlan_objmgr_psoc *psoc,
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QDF_STATUS ucfg_dcs_register_afc_sel_chan_cb(struct wlan_objmgr_psoc *psoc,
|
||||
dcs_afc_select_chan_cb cb,
|
||||
void *arg)
|
||||
{
|
||||
struct dcs_psoc_priv_obj *dcs_psoc_priv;
|
||||
|
||||
dcs_psoc_priv =
|
||||
wlan_objmgr_psoc_get_comp_private_obj(psoc, WLAN_UMAC_COMP_DCS);
|
||||
if (!dcs_psoc_priv) {
|
||||
dcs_err("dcs psoc private object is null");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
dcs_psoc_priv->afc_sel_chan_cbk.cbk = cb;
|
||||
dcs_psoc_priv->afc_sel_chan_cbk.arg = arg;
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QDF_STATUS
|
||||
ucfg_wlan_dcs_cmd(struct wlan_objmgr_psoc *psoc,
|
||||
uint32_t mac_id,
|
||||
|
Loading…
Reference in New Issue
Block a user