qcacld-3.0: Configure TDLS off channel mode when band switches

Disable TDLS off channel if 2g or 5g is disabled, restore TDLS off
channel configure when all bands are enabled.

Change-Id: Iabfdcdbf84e4a6313ad04e381b70e21c871d66c2
CRs-Fixed: 2595303
This commit is contained in:
bings
2019-12-31 18:24:21 +08:00
committed by nshrivas
parent a71b36fc0a
commit 059c4a06c2
10 changed files with 209 additions and 19 deletions

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
* *
* Permission to use, copy, modify, and/or distribute this software for * Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the * any purpose with or without fee is hereby granted, provided that the
@@ -1074,6 +1074,15 @@ int tdls_set_tdls_offchannelmode(struct wlan_objmgr_vdev *vdev,
tdls_debug("oper_class:%d", tdls_debug("oper_class:%d",
chan_switch_params.oper_class); chan_switch_params.oper_class);
} }
} else if (conn_peer->off_channel_capable &&
conn_peer->pref_off_chan_num) {
chan_switch_params.tdls_off_ch =
conn_peer->pref_off_chan_num;
chan_switch_params.oper_class =
tdls_get_opclass_from_bandwidth(
tdls_soc, conn_peer->pref_off_chan_num,
tdls_soc->tdls_configs.tdls_pre_off_chan_bw,
&chan_switch_params.tdls_off_ch_bw_offset);
} else { } else {
tdls_err("TDLS off-channel parameters are not set yet!!!"); tdls_err("TDLS off-channel parameters are not set yet!!!");
return -EINVAL; return -EINVAL;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
* *
* Permission to use, copy, modify, and/or distribute this software for * Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the * any purpose with or without fee is hereby granted, provided that the
@@ -1806,26 +1806,32 @@ void tdls_scan_serialization_comp_info_cb(struct wlan_objmgr_vdev *vdev,
uint8_t tdls_get_opclass_from_bandwidth(struct tdls_soc_priv_obj *soc_obj, uint8_t tdls_get_opclass_from_bandwidth(struct tdls_soc_priv_obj *soc_obj,
uint8_t channel, uint8_t bw_offset) uint8_t channel, uint8_t bw_offset,
uint8_t *reg_bw_offset)
{ {
uint8_t opclass; uint8_t opclass;
if (bw_offset & (1 << BW_80_OFFSET_BIT)) { if (bw_offset & (1 << BW_80_OFFSET_BIT)) {
opclass = tdls_find_opclass(soc_obj->soc, opclass = tdls_find_opclass(soc_obj->soc,
channel, BW80); channel, BW80);
*reg_bw_offset = BW80;
} else if (bw_offset & (1 << BW_40_OFFSET_BIT)) { } else if (bw_offset & (1 << BW_40_OFFSET_BIT)) {
opclass = tdls_find_opclass(soc_obj->soc, opclass = tdls_find_opclass(soc_obj->soc,
channel, BW40_LOW_PRIMARY); channel, BW40_LOW_PRIMARY);
*reg_bw_offset = BW40_LOW_PRIMARY;
if (!opclass) { if (!opclass) {
opclass = tdls_find_opclass(soc_obj->soc, opclass = tdls_find_opclass(soc_obj->soc,
channel, BW40_HIGH_PRIMARY); channel, BW40_HIGH_PRIMARY);
*reg_bw_offset = BW40_HIGH_PRIMARY;
} }
} else if (bw_offset & (1 << BW_20_OFFSET_BIT)) { } else if (bw_offset & (1 << BW_20_OFFSET_BIT)) {
opclass = tdls_find_opclass(soc_obj->soc, opclass = tdls_find_opclass(soc_obj->soc,
channel, BW20); channel, BW20);
*reg_bw_offset = BW20;
} else { } else {
opclass = tdls_find_opclass(soc_obj->soc, opclass = tdls_find_opclass(soc_obj->soc,
channel, BWALL); channel, BWALL);
*reg_bw_offset = BWALL;
} }
return opclass; return opclass;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
* *
* Permission to use, copy, modify, and/or distribute this software for * Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the * any purpose with or without fee is hereby granted, provided that the
@@ -751,11 +751,13 @@ QDF_STATUS tdls_delete_all_peers_indication(struct wlan_objmgr_psoc *psoc,
* @soc_obj: tdls soc object. * @soc_obj: tdls soc object.
* @channel: Channel number. * @channel: Channel number.
* @bw_offset: Bandwidth offset. * @bw_offset: Bandwidth offset.
* @reg_bw_offset: enum offset_t type bandwidth
* *
* To return the opclas. * To return the opclas.
* *
* Return: opclass * Return: opclass
*/ */
uint8_t tdls_get_opclass_from_bandwidth(struct tdls_soc_priv_obj *soc_obj, uint8_t tdls_get_opclass_from_bandwidth(struct tdls_soc_priv_obj *soc_obj,
uint8_t channel, uint8_t bw_offset); uint8_t channel, uint8_t bw_offset,
uint8_t *reg_bw_offset);
#endif #endif

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
* *
* Permission to use, copy, modify, and/or distribute this software for * Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the * any purpose with or without fee is hereby granted, provided that the
@@ -161,6 +161,7 @@ static struct tdls_peer *tdls_add_peer(struct tdls_vdev_priv_obj *vdev_obj,
struct tdls_soc_priv_obj *soc_obj; struct tdls_soc_priv_obj *soc_obj;
uint8_t key = 0; uint8_t key = 0;
qdf_list_t *head; qdf_list_t *head;
uint8_t reg_bw_offset;
peer = qdf_mem_malloc(sizeof(*peer)); peer = qdf_mem_malloc(sizeof(*peer));
if (!peer) { if (!peer) {
@@ -183,9 +184,10 @@ static struct tdls_peer *tdls_add_peer(struct tdls_vdev_priv_obj *vdev_obj,
peer->pref_off_chan_num = peer->pref_off_chan_num =
soc_obj->tdls_configs.tdls_pre_off_chan_num; soc_obj->tdls_configs.tdls_pre_off_chan_num;
peer->op_class_for_pref_off_chan = peer->op_class_for_pref_off_chan =
tdls_get_opclass_from_bandwidth(soc_obj, tdls_get_opclass_from_bandwidth(
peer->pref_off_chan_num, soc_obj, peer->pref_off_chan_num,
soc_obj->tdls_configs.tdls_pre_off_chan_bw); soc_obj->tdls_configs.tdls_pre_off_chan_bw,
&reg_bw_offset);
peer->valid_entry = false; peer->valid_entry = false;
@@ -748,6 +750,7 @@ QDF_STATUS tdls_reset_peer(struct tdls_vdev_priv_obj *vdev_obj,
struct tdls_soc_priv_obj *soc_obj; struct tdls_soc_priv_obj *soc_obj;
struct tdls_peer *curr_peer; struct tdls_peer *curr_peer;
struct tdls_user_config *config; struct tdls_user_config *config;
uint8_t reg_bw_offset;
soc_obj = wlan_vdev_get_tdls_soc_obj(vdev_obj->vdev); soc_obj = wlan_vdev_get_tdls_soc_obj(vdev_obj->vdev);
if (!soc_obj) { if (!soc_obj) {
@@ -765,9 +768,10 @@ QDF_STATUS tdls_reset_peer(struct tdls_vdev_priv_obj *vdev_obj,
config = &soc_obj->tdls_configs; config = &soc_obj->tdls_configs;
curr_peer->pref_off_chan_num = config->tdls_pre_off_chan_num; curr_peer->pref_off_chan_num = config->tdls_pre_off_chan_num;
curr_peer->op_class_for_pref_off_chan = curr_peer->op_class_for_pref_off_chan =
tdls_get_opclass_from_bandwidth(soc_obj, tdls_get_opclass_from_bandwidth(
curr_peer->pref_off_chan_num, soc_obj, curr_peer->pref_off_chan_num,
soc_obj->tdls_configs.tdls_pre_off_chan_bw); soc_obj->tdls_configs.tdls_pre_off_chan_bw,
&reg_bw_offset);
} }
tdls_set_peer_link_status(curr_peer, TDLS_LINK_IDLE, tdls_set_peer_link_status(curr_peer, TDLS_LINK_IDLE,

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018 The Linux Foundation. All rights reserved. * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
* *
* Permission to use, copy, modify, and/or distribute this software for * Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the * any purpose with or without fee is hereby granted, provided that the
@@ -137,6 +137,35 @@ QDF_STATUS
cfg_tdls_set_off_channel_enable(struct wlan_objmgr_psoc *psoc, cfg_tdls_set_off_channel_enable(struct wlan_objmgr_psoc *psoc,
bool val); bool val);
/**
* cfg_tdls_get_off_channel_enable_orig() - get tdls off channel enable orig
* @psoc: pointer to psoc object
* @val: pointer to tdls off channel enable
*
* This function gets tdls off channel enable orig
*/
QDF_STATUS
cfg_tdls_get_off_channel_enable_orig(struct wlan_objmgr_psoc *psoc,
bool *val);
/**
* cfg_tdls_restore_off_channel_enable() - set tdls off channel enable to
* tdls_off_chan_enable_orig
* @psoc: pointer to psoc object
*
* Return: NULL
*/
void cfg_tdls_restore_off_channel_enable(struct wlan_objmgr_psoc *psoc);
/**
* cfg_tdls_store_off_channel_enable() - save tdls off channel enable to
* tdls_off_chan_enable_orig
* @psoc: pointer to psoc object
*
* Return: NULL
*/
void cfg_tdls_store_off_channel_enable(struct wlan_objmgr_psoc *psoc);
/** /**
* cfg_tdls_get_wmm_mode_enable() - get tdls wmm mode enable * cfg_tdls_get_wmm_mode_enable() - get tdls wmm mode enable
* @psoc: pointer to psoc object * @psoc: pointer to psoc object

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
* *
* Permission to use, copy, modify, and/or distribute this software for * Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the * any purpose with or without fee is hereby granted, provided that the
@@ -461,6 +461,7 @@ enum tdls_feature_bit {
* @tdls_vdev_nss_5g: tdls NSS setting for 5G band * @tdls_vdev_nss_5g: tdls NSS setting for 5G band
* @tdls_buffer_sta_enable: tdls buffer station enable * @tdls_buffer_sta_enable: tdls buffer station enable
* @tdls_off_chan_enable: tdls off channel enable * @tdls_off_chan_enable: tdls off channel enable
* @tdls_off_chan_enable_orig: original tdls off channel enable
* @tdls_wmm_mode_enable: tdls wmm mode enable * @tdls_wmm_mode_enable: tdls wmm mode enable
* @tdls_external_control: tdls external control enable * @tdls_external_control: tdls external control enable
* @tdls_implicit_trigger_enable: tdls implicit trigger enable * @tdls_implicit_trigger_enable: tdls implicit trigger enable
@@ -492,6 +493,7 @@ struct tdls_user_config {
uint8_t tdls_vdev_nss_5g; uint8_t tdls_vdev_nss_5g;
bool tdls_buffer_sta_enable; bool tdls_buffer_sta_enable;
bool tdls_off_chan_enable; bool tdls_off_chan_enable;
bool tdls_off_chan_enable_orig;
bool tdls_wmm_mode_enable; bool tdls_wmm_mode_enable;
bool tdls_external_control; bool tdls_external_control;
bool tdls_implicit_trigger_enable; bool tdls_implicit_trigger_enable;
@@ -929,7 +931,7 @@ struct tdls_peer_update_state {
struct tdls_channel_switch_params { struct tdls_channel_switch_params {
uint32_t vdev_id; uint32_t vdev_id;
uint8_t peer_mac_addr[QDF_MAC_ADDR_SIZE]; uint8_t peer_mac_addr[QDF_MAC_ADDR_SIZE];
uint16_t tdls_off_ch_bw_offset; uint8_t tdls_off_ch_bw_offset;
uint8_t tdls_off_ch; uint8_t tdls_off_ch;
uint8_t tdls_sw_mode; uint8_t tdls_sw_mode;
uint8_t oper_class; uint8_t oper_class;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018 The Linux Foundation. All rights reserved. * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
* *
* Permission to use, copy, modify, and/or distribute this software for * Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the * any purpose with or without fee is hereby granted, provided that the
@@ -201,6 +201,53 @@ cfg_tdls_set_off_channel_enable(struct wlan_objmgr_psoc *psoc,
return QDF_STATUS_SUCCESS; return QDF_STATUS_SUCCESS;
} }
QDF_STATUS
cfg_tdls_get_off_channel_enable_orig(struct wlan_objmgr_psoc *psoc,
bool *val)
{
struct tdls_soc_priv_obj *soc_obj;
soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
if (!soc_obj) {
*val = false;
tdls_err("tdls soc null");
return QDF_STATUS_E_INVAL;
}
*val = soc_obj->tdls_configs.tdls_off_chan_enable_orig;
return QDF_STATUS_SUCCESS;
}
void cfg_tdls_store_off_channel_enable(struct wlan_objmgr_psoc *psoc)
{
struct tdls_soc_priv_obj *soc_obj;
soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
if (!soc_obj) {
tdls_err("tdls soc null");
return;
}
soc_obj->tdls_configs.tdls_off_chan_enable_orig =
soc_obj->tdls_configs.tdls_off_chan_enable;
}
void cfg_tdls_restore_off_channel_enable(struct wlan_objmgr_psoc *psoc)
{
struct tdls_soc_priv_obj *soc_obj;
soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
if (!soc_obj) {
tdls_err("tdls soc null");
return;
}
soc_obj->tdls_configs.tdls_off_chan_enable =
soc_obj->tdls_configs.tdls_off_chan_enable_orig;
soc_obj->tdls_configs.tdls_off_chan_enable_orig = false;
}
QDF_STATUS QDF_STATUS
cfg_tdls_get_wmm_mode_enable(struct wlan_objmgr_psoc *psoc, cfg_tdls_get_wmm_mode_enable(struct wlan_objmgr_psoc *psoc,
bool *val) bool *val)

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
* *
* Permission to use, copy, modify, and/or distribute this software for * Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the * any purpose with or without fee is hereby granted, provided that the
@@ -173,6 +173,16 @@ QDF_STATUS hdd_tdls_deregister_peer(void *userdata, uint32_t vdev_id,
*/ */
void hdd_init_tdls_config(struct tdls_start_params *tdls_cfg); void hdd_init_tdls_config(struct tdls_start_params *tdls_cfg);
/**
* hdd_config_tdls_with_band_switch() - configure tdls when band changes
* Disable tdls offchmode if only one of
* bands is supported
* Enable tdls offchmode if all band enable
* @hdd_ctx: Pointer to the HDD context
*
* Return: none
*/
void hdd_config_tdls_with_band_switch(struct hdd_context *hdd_ctx);
#else #else
static inline int wlan_hdd_tdls_antenna_switch(struct hdd_context *hdd_ctx, static inline int wlan_hdd_tdls_antenna_switch(struct hdd_context *hdd_ctx,
@@ -208,5 +218,9 @@ static inline void hdd_init_tdls_config(struct tdls_start_params *tdls_cfg)
{ {
} }
static inline void hdd_config_tdls_with_band_switch(struct hdd_context *hdd_ctx)
{
}
#endif /* End of FEATURE_WLAN_TDLS */ #endif /* End of FEATURE_WLAN_TDLS */
#endif /* __HDD_TDLS_H */ #endif /* __HDD_TDLS_H */

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. * Copyright (c) 2014-2020 The Linux Foundation. All rights reserved.
* *
* Permission to use, copy, modify, and/or distribute this software for * Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the * any purpose with or without fee is hereby granted, provided that the
@@ -1454,6 +1454,8 @@ static void hdd_regulatory_dyn_cbk(struct wlan_objmgr_psoc *psoc,
hdd_ch_avoid_ind(hdd_ctx, &avoid_freq_ind->chan_list, hdd_ch_avoid_ind(hdd_ctx, &avoid_freq_ind->chan_list,
&avoid_freq_ind->freq_list); &avoid_freq_ind->freq_list);
} else { } else {
hdd_config_tdls_with_band_switch(hdd_ctx);
sme_generic_change_country_code(hdd_ctx->mac_handle, sme_generic_change_country_code(hdd_ctx->mac_handle,
hdd_ctx->reg.alpha2); hdd_ctx->reg.alpha2);
/*Check whether need restart SAP/P2p Go*/ /*Check whether need restart SAP/P2p Go*/

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
* *
* Permission to use, copy, modify, and/or distribute this software for * Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the * any purpose with or without fee is hereby granted, provided that the
@@ -43,6 +43,7 @@
#include <qca_vendor.h> #include <qca_vendor.h>
#include "wlan_tdls_cfg_api.h" #include "wlan_tdls_cfg_api.h"
#include "wlan_hdd_object_manager.h" #include "wlan_hdd_object_manager.h"
#include <wlan_reg_ucfg_api.h>
/** /**
* enum qca_wlan_vendor_tdls_trigger_mode_hdd_map: Maps the user space TDLS * enum qca_wlan_vendor_tdls_trigger_mode_hdd_map: Maps the user space TDLS
@@ -767,6 +768,18 @@ int hdd_set_tdls_offchannelmode(struct hdd_context *hdd_ctx,
{ {
struct wlan_objmgr_vdev *vdev; struct wlan_objmgr_vdev *vdev;
QDF_STATUS status = QDF_STATUS_E_FAILURE; QDF_STATUS status = QDF_STATUS_E_FAILURE;
bool tdls_off_ch;
if (cfg_tdls_get_off_channel_enable(
hdd_ctx->psoc, &tdls_off_ch) !=
QDF_STATUS_SUCCESS) {
hdd_err("cfg get tdls off ch failed");
return qdf_status_to_os_return(status);
}
if (!tdls_off_ch) {
hdd_debug("tdls off ch is false, do nothing");
return qdf_status_to_os_return(status);
}
if (hdd_ctx->tdls_umac_comp_active) { if (hdd_ctx->tdls_umac_comp_active) {
vdev = hdd_objmgr_get_vdev(adapter); vdev = hdd_objmgr_get_vdev(adapter);
@@ -881,3 +894,65 @@ void hdd_init_tdls_config(struct tdls_start_params *tdls_cfg)
tdls_cfg->tdls_del_sta_req = eWNI_SME_TDLS_DEL_STA_REQ; tdls_cfg->tdls_del_sta_req = eWNI_SME_TDLS_DEL_STA_REQ;
tdls_cfg->tdls_update_peer_state = WMA_UPDATE_TDLS_PEER_STATE; tdls_cfg->tdls_update_peer_state = WMA_UPDATE_TDLS_PEER_STATE;
} }
void hdd_config_tdls_with_band_switch(struct hdd_context *hdd_ctx)
{
struct wlan_objmgr_vdev *tdls_obj_vdev;
int offchmode;
enum band_info current_band;
bool tdls_off_ch;
if (!hdd_ctx) {
hdd_err("Invalid hdd_ctx");
return;
}
if (ucfg_reg_get_curr_band(hdd_ctx->pdev, &current_band) !=
QDF_STATUS_SUCCESS) {
hdd_err("Failed to get current band config");
return;
}
/**
* If all bands are supported, in below condition off channel enable
* orig is false and nothing is need to do
* 1. band switch does not happen.
* 2. band switch happens and it already restores
* 3. tdls off channel is disabled by default.
* If 2g or 5g is not supported. Disable tdls off channel only when
* tdls off channel is enabled currently.
*/
if (current_band == BAND_ALL) {
if (cfg_tdls_get_off_channel_enable_orig(
hdd_ctx->psoc, &tdls_off_ch) !=
QDF_STATUS_SUCCESS) {
hdd_err("cfg get tdls off ch orig failed");
return;
}
if (!tdls_off_ch) {
hdd_debug("tdls off ch orig is false, do nothing");
return;
}
offchmode = ENABLE_CHANSWITCH;
cfg_tdls_restore_off_channel_enable(hdd_ctx->psoc);
} else {
if (cfg_tdls_get_off_channel_enable(
hdd_ctx->psoc, &tdls_off_ch) !=
QDF_STATUS_SUCCESS) {
hdd_err("cfg get tdls off ch failed");
return;
}
if (!tdls_off_ch) {
hdd_debug("tdls off ch is false, do nothing");
return;
}
offchmode = DISABLE_CHANSWITCH;
cfg_tdls_store_off_channel_enable(hdd_ctx->psoc);
cfg_tdls_set_off_channel_enable(hdd_ctx->psoc, false);
}
tdls_obj_vdev = ucfg_get_tdls_vdev(hdd_ctx->psoc, WLAN_TDLS_NB_ID);
if (tdls_obj_vdev) {
ucfg_set_tdls_offchan_mode(tdls_obj_vdev, offchmode);
wlan_objmgr_vdev_release_ref(tdls_obj_vdev, WLAN_TDLS_NB_ID);
}
}