qcacld-3.0: Support for handling of op class in xcsa action frame
qcacld-2.0 to qcacld-3.0 propagation
Add support to parse operating class from xcsa frame and select
channel bandwidth on basis of new operating class.
Change-Id: I33d794e77220ef82cca793767d459979eb940669
CRs-Fixed: 942104
diff --git a/core/cds/inc/cds_regdomain_common.h b/core/cds/inc/cds_regdomain_common.h
index 7feaf55..36c480b 100644
--- a/core/cds/inc/cds_regdomain_common.h
+++ b/core/cds/inc/cds_regdomain_common.h
@@ -2214,5 +2214,7 @@
uint16_t cds_regdm_get_opclass_from_channel(uint8_t *country, uint8_t channel,
uint8_t offset);
+uint16_t cds_regdm_get_chanwidth_from_opclass(uint8_t *country, uint8_t channel,
+ uint8_t opclass);
uint16_t cds_regdm_set_curr_opclasses(uint8_t num_classes, uint8_t *class);
uint16_t cds_regdm_get_curr_opclasses(uint8_t *num_classes, uint8_t *class);
diff --git a/core/cds/src/cds_regdomain.c b/core/cds/src/cds_regdomain.c
index 3a93529..e3c897c 100644
--- a/core/cds/src/cds_regdomain.c
+++ b/core/cds/src/cds_regdomain.c
@@ -622,6 +622,50 @@
return 0;
}
+/**
+ * cds_regdm_get_chanwidth_from_opclass() - return chan width based on opclass
+ * @country: country name
+ * @channel: operating channel
+ * @opclass: operating class
+ *
+ * Given a value of country, channel and opclass this API will return value of
+ * channel width.
+ *
+ * Return: channel width
+ *
+ */
+uint16_t cds_regdm_get_chanwidth_from_opclass(uint8_t *country,
+ uint8_t channel,
+ uint8_t opclass)
+{
+ regdm_op_class_map_t *class;
+ uint16_t i;
+
+ if (true == cdf_mem_compare(country, "US", 2))
+ class = us_op_class;
+ else if (true == cdf_mem_compare(country, "EU", 2))
+ class = euro_op_class;
+ else if (true == cdf_mem_compare(country, "JP", 2))
+ class = japan_op_class;
+ else
+ class = global_op_class;
+
+ while (class->op_class) {
+ if (opclass == class->op_class) {
+ for (i = 0;
+ (i < MAX_CHANNELS_PER_OPERATING_CLASS &&
+ class->channels[i]);
+ i++) {
+ if (channel == class->channels[i])
+ return class->ch_spacing;
+ }
+ }
+ class++;
+ }
+ return 0;
+}
+
+
/*
* Get operating class for a given channel
*/
diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c
index bde6cba..eee97ba 100644
--- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c
+++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c
@@ -55,6 +55,8 @@
#include "lim_session_utils.h"
#include "lim_types.h"
#include "sir_api.h"
+#include "cds_regdomain_common.h"
+#include "lim_send_messages.h"
static void lim_handle_join_rsp_status(tpAniSirGlobal mac_ctx,
tpPESession session_entry, tSirResultCodes result_code,
@@ -2010,6 +2012,9 @@
tpDphHashNode sta_ds = NULL;
uint8_t session_id;
uint16_t aid = 0;
+ uint16_t chan_space = 0;
+ int cb_mode = 0;
+
tLimWiderBWChannelSwitchInfo *chnl_switch_info = NULL;
if (!csa_params) {
@@ -2052,10 +2057,13 @@
eLIM_CHANNEL_SWITCH_PRIMARY_ONLY;
session_entry->gLimChannelSwitch.ch_width = CH_WIDTH_20MHZ;
+ session_entry->gLimChannelSwitch.ch_center_freq_seg0 = 0;
+ session_entry->gLimChannelSwitch.ch_center_freq_seg1 = 0;
+ chnl_switch_info =
+ &session_entry->gLimWiderBWChannelSwitch;
+
if (session_entry->vhtCapability &&
session_entry->htSupportedChannelWidthSet) {
- chnl_switch_info =
- &session_entry->gLimWiderBWChannelSwitch;
if (csa_params->ies_present_flag & lim_wbw_ie_present) {
chnl_switch_info->newChanWidth =
csa_params->new_ch_width;
@@ -2067,8 +2075,103 @@
eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
session_entry->gLimChannelSwitch.ch_width =
csa_params->new_ch_width + 1;
+ } else if (csa_params->ies_present_flag
+ & lim_xcsa_ie_present) {
+ chan_space =
+ cds_regdm_get_chanwidth_from_opclass(
+ mac_ctx->scan.countryCodeCurrent,
+ csa_params->channel,
+ csa_params->new_op_class);
+ session_entry->gLimChannelSwitch.state =
+ eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
+
+ if (chan_space == 80) {
+ chnl_switch_info->newChanWidth =
+ CH_WIDTH_80MHZ;
+ } else if (chan_space == 40) {
+ chnl_switch_info->newChanWidth =
+ CH_WIDTH_40MHZ;
+ } else {
+ chnl_switch_info->newChanWidth =
+ CH_WIDTH_20MHZ;
+ session_entry->gLimChannelSwitch.state =
+ eLIM_CHANNEL_SWITCH_PRIMARY_ONLY;
+ }
+
+ cb_mode = lim_select_cb_mode_for_sta(
+ session_entry,
+ csa_params->channel,
+ chan_space);
+
+ chnl_switch_info->newCenterChanFreq0 =
+ lim_get_center_channel(mac_ctx,
+ csa_params->channel,
+ cb_mode,
+ chnl_switch_info->newChanWidth);
+ /*
+ * This is not applicable for 20/40/80 MHz.
+ * Only used when we support 80+80 MHz operation.
+ * In case of 80+80 MHz, this parameter indicates
+ * center channel frequency index of 80 MHz
+ * channel offrequency segment 1.
+ */
+ chnl_switch_info->newCenterChanFreq1 = 0;
+
}
+ session_entry->gLimChannelSwitch.ch_center_freq_seg0 =
+ chnl_switch_info->newCenterChanFreq0;
+ session_entry->gLimChannelSwitch.ch_center_freq_seg1 =
+ chnl_switch_info->newCenterChanFreq1;
+ session_entry->gLimChannelSwitch.ch_width =
+ chnl_switch_info->newChanWidth;
+
} else if (session_entry->htSupportedChannelWidthSet) {
+ if (csa_params->ies_present_flag
+ & lim_xcsa_ie_present) {
+ chan_space =
+ cds_regdm_get_chanwidth_from_opclass(
+ mac_ctx->scan.countryCodeCurrent,
+ csa_params->channel,
+ csa_params->new_op_class);
+ session_entry->gLimChannelSwitch.state =
+ eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
+ if (chan_space == 40) {
+ session_entry->
+ gLimChannelSwitch.ch_width =
+ CH_WIDTH_40MHZ;
+ chnl_switch_info->newChanWidth =
+ CH_WIDTH_40MHZ;
+ cb_mode = lim_select_cb_mode_for_sta(
+ session_entry,
+ csa_params->channel,
+ chan_space);
+ if (cb_mode ==
+ PHY_DOUBLE_CHANNEL_LOW_PRIMARY) {
+ session_entry->
+ gLimChannelSwitch.
+ ch_center_freq_seg0 =
+ csa_params->channel + 2;
+ } else if (cb_mode ==
+ PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) {
+ session_entry->
+ gLimChannelSwitch.
+ ch_center_freq_seg0 =
+ csa_params->channel - 2;
+ }
+
+ } else {
+ session_entry->
+ gLimChannelSwitch.ch_width =
+ CH_WIDTH_20MHZ;
+ chnl_switch_info->newChanWidth =
+ CH_WIDTH_40MHZ;
+ session_entry->gLimChannelSwitch.state =
+ eLIM_CHANNEL_SWITCH_PRIMARY_ONLY;
+ }
+
+
+ }
+
if (csa_params->sec_chan_offset) {
session_entry->gLimChannelSwitch.ch_width =
CH_WIDTH_40MHZ;
diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h
index cd9d6a1..42a5eab 100644
--- a/core/mac/src/pe/lim/lim_utils.h
+++ b/core/mac/src/pe/lim/lim_utils.h
@@ -294,6 +294,59 @@
return false;
}
+/**
+ * lim_select_cb_mode_for_sta() - return cb_mode based on current session
+ * @session_entry: Session entry
+ * @channel: channel
+ * @chan_bw: channel bandwidth
+ *
+ * Given a value of channel and bandwidth this API will return the value of
+ * cb_mode on basis of channel, bandwidth ht/vht capabilities
+ *
+ * Return: cb_mode
+ *
+ */
+
+static inline int lim_select_cb_mode_for_sta(tpPESession session_entry,
+ uint8_t channel, uint8_t chan_bw)
+{
+ if (session_entry->vhtCapability && chan_bw) {
+ if (channel == 36 || channel == 52 || channel == 100 ||
+ channel == 116 || channel == 149) {
+ return PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1;
+ } else if (channel == 40 || channel == 56 || channel == 104 ||
+ channel == 120 || channel == 153) {
+ return PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1;
+ } else if (channel == 44 || channel == 60 || channel == 108 ||
+ channel == 124 || channel == 157) {
+ return PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH - 1;
+ } else if (channel == 48 || channel == 64 || channel == 112 ||
+ channel == 128 || channel == 161) {
+ return PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1;
+ } else if (channel == 165) {
+ return PHY_SINGLE_CHANNEL_CENTERED;
+ }
+ } else if (session_entry->htSupportedChannelWidthSet) {
+ if (channel == 40 || channel == 48 || channel == 56 ||
+ channel == 64 || channel == 104 || channel == 112 ||
+ channel == 120 || channel == 128 || channel == 136 ||
+ channel == 144 || channel == 153 || channel == 161) {
+ return PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
+ } else if (channel == 36 || channel == 44 || channel == 52 ||
+ channel == 60 || channel == 100 ||
+ channel == 108 || channel == 116 ||
+ channel == 124 || channel == 132 ||
+ channel == 140 || channel == 149 ||
+ channel == 157) {
+ return PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
+ } else if (channel == 165) {
+ return PHY_SINGLE_CHANNEL_CENTERED;
+ }
+ }
+ return PHY_SINGLE_CHANNEL_CENTERED;
+}
+
+
static inline int lim_select_cb_mode(tDphHashNode *pStaDs,
tpPESession psessionEntry, uint8_t channel,
uint8_t chan_bw)
diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h
index 63dd5e3..52e3139 100644
--- a/core/wma/inc/wma_if.h
+++ b/core/wma/inc/wma_if.h
@@ -940,6 +940,7 @@
uint8_t switchmode;
uint8_t sec_chan_offset;
uint8_t new_ch_width;
+ uint8_t new_op_class;
uint8_t new_ch_freq_seg1;
uint8_t new_ch_freq_seg2;
uint32_t ies_present_flag;
diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c
index ffe4771..f8f2736 100644
--- a/core/wma/src/wma_features.c
+++ b/core/wma/src/wma_features.c
@@ -1492,6 +1492,7 @@
(&csa_event->xcsa_ie[0]);
csa_offload_event->channel = xcsa_ie->newchannel;
csa_offload_event->switchmode = xcsa_ie->switchmode;
+ csa_offload_event->new_op_class = xcsa_ie->newClass;
} else {
WMA_LOGE("CSA Event error: No CSA IE present");
cdf_mem_free(csa_offload_event);