summaryrefslogtreecommitdiff
path: root/CORE/VOSS/src
diff options
context:
space:
mode:
authorAbhishek Singh <absingh@qti.qualcomm.com>2016-04-19 18:19:05 +0530
committerAnjaneedevi Kapparapu <akappa@codeaurora.org>2016-05-05 19:46:01 +0530
commit67feb105617bce80d39a8e8ddc29859199e3abed (patch)
treea0be1a777ac245db3026a015212d7006c58b14e3 /CORE/VOSS/src
parent81a514f926cff5ea60de03b866422d67b463fc5b (diff)
qcacld-2.0: Set wlan phy mode in OEM channel info response
Calculate and add wlan phy mode for each channel in OEM channel info response. Also send ANI_MSG_PEER_STATUS_IND indication for STA mode when STA gets connected. Change-Id: I91363e90698cabda72028135eb7fe9adeb1fbc86 CRs-Fixed: 1007004
Diffstat (limited to 'CORE/VOSS/src')
-rw-r--r--CORE/VOSS/src/vos_nvitem.c365
1 files changed, 365 insertions, 0 deletions
diff --git a/CORE/VOSS/src/vos_nvitem.c b/CORE/VOSS/src/vos_nvitem.c
index 493b1397eb1e..82afaeb14140 100644
--- a/CORE/VOSS/src/vos_nvitem.c
+++ b/CORE/VOSS/src/vos_nvitem.c
@@ -118,6 +118,48 @@ static v_BOOL_t init_by_reg_core = VOS_FALSE;
#define WORLD_SKU_MASK 0x00F0
#define WORLD_SKU_PREFIX 0x0060
+/**
+ * struct bonded_chan
+ * @start_ch: start channel
+ * @end_ch: end channel
+ */
+struct bonded_chan {
+ uint16_t start_ch;
+ uint16_t end_ch;
+};
+
+static const struct bonded_chan bonded_chan_40mhz_array[] = {
+ {36, 40},
+ {44, 48},
+ {52, 56},
+ {60, 64},
+ {100, 104},
+ {108, 112},
+ {116, 120},
+ {124, 128},
+ {132, 136},
+ {140, 144},
+ {149, 153},
+ {157, 161}
+};
+
+static const struct bonded_chan bonded_chan_80mhz_array[] = {
+ {36, 48},
+ {52, 64},
+ {100, 112},
+ {116, 128},
+ {132, 144},
+ {149, 161}
+};
+
+static const enum phy_ch_width next_lower_bw[] = {
+ [CH_WIDTH_80MHZ] = CH_WIDTH_40MHZ,
+ [CH_WIDTH_40MHZ] = CH_WIDTH_20MHZ,
+ [CH_WIDTH_20MHZ] = CH_WIDTH_10MHZ,
+ [CH_WIDTH_10MHZ] = CH_WIDTH_5MHZ,
+ [CH_WIDTH_5MHZ] = CH_WIDTH_INVALID
+};
+
static const struct ieee80211_regdomain vos_world_regdom_60_61_62 = {
.n_reg_rules = 6,
.alpha2 = "00",
@@ -494,6 +536,13 @@ const tRfChannelProps rfChannels[NUM_RF_CHANNELS] =
{ 5815, 163, NUM_RF_SUBBANDS}, //RF_CHAN_BOND_163,
};
+#define VOS_IS_CHANNEL_5GHZ(chan_num) \
+ ((chan_num >= rfChannels[RF_CHAN_36].channelNum) && \
+ (chan_num <= rfChannels[RF_CHAN_184].channelNum))
+#define VOS_IS_CHANNEL_24GHZ(chan_num) \
+ ((chan_num >= rfChannels[RF_CHAN_1].channelNum) && \
+ (chan_num <= rfChannels[RF_CHAN_14].channelNum))
+
extern const sHalNv nvDefaults;
const sRegulatoryChannel * regChannels = nvDefaults.tables.regDomains[0].channels;
@@ -707,6 +756,322 @@ VOS_STATUS vos_nv_close(void)
return VOS_STATUS_SUCCESS;
}
+/**
+ * vos_search_5g_bonded_chan_array() - get ptr to bonded channel
+ * @oper_ch: operating channel number
+ * @bonded_chan_ar: bonded channel array
+ * @bonded_chan_ptr_ptr: bonded channel ptr ptr
+ *
+ * Return: eNVChannelEnabledType
+ */
+static eNVChannelEnabledType vos_search_5g_bonded_chan_array(
+ uint32_t oper_chan, const struct bonded_chan bonded_chan_ar[],
+ uint16_t array_size, const struct bonded_chan
+ **bonded_chan_ptr_ptr)
+{
+ int i;
+ uint8_t chan_num;
+ const struct bonded_chan *bonded_chan_ptr = NULL;
+ eNVChannelEnabledType chan_state = NV_CHANNEL_INVALID;
+ eNVChannelEnabledType temp_chan_state;
+
+ for (i = 0; i < array_size; i++) {
+ if ((oper_chan >= bonded_chan_ar[i].start_ch) &&
+ (oper_chan <= bonded_chan_ar[i].end_ch)) {
+ bonded_chan_ptr = &(bonded_chan_ar[i]);
+ break;
+ }
+ }
+
+ if (NULL == bonded_chan_ptr)
+ return chan_state;
+
+ *bonded_chan_ptr_ptr = bonded_chan_ptr;
+ chan_num = bonded_chan_ptr->start_ch;
+ while (chan_num <= bonded_chan_ptr->end_ch) {
+ temp_chan_state = vos_nv_getChannelEnabledState(chan_num);
+ if (temp_chan_state < chan_state)
+ chan_state = temp_chan_state;
+ chan_num = chan_num + 4;
+ }
+
+ return chan_state;
+}
+
+/**
+ * vos_search_5g_bonded_channel() - get the 5G bonded channel state
+ * @chan_num: channel number
+ * @ch_width: channel width
+ * @bonded_chan_ptr_ptr: bonded channel ptr ptr
+ *
+ * Return: channel state
+ */
+static eNVChannelEnabledType vos_search_5g_bonded_channel(uint32_t chan_num,
+ enum phy_ch_width ch_width,
+ const struct bonded_chan
+ **bonded_chan_ptr_ptr)
+{
+
+ if (CH_WIDTH_80MHZ == ch_width)
+ return vos_search_5g_bonded_chan_array(chan_num,
+ bonded_chan_80mhz_array,
+ ARRAY_SIZE(bonded_chan_80mhz_array),
+ bonded_chan_ptr_ptr);
+ else if (CH_WIDTH_40MHZ == ch_width)
+ return vos_search_5g_bonded_chan_array(chan_num,
+ bonded_chan_40mhz_array,
+ ARRAY_SIZE(bonded_chan_40mhz_array),
+ bonded_chan_ptr_ptr);
+ else
+ return vos_nv_getChannelEnabledState(chan_num);
+}
+
+/**
+ * vos_get_5g_bonded_channel_state() - get the 5G bonded channel state
+ * @chan_num: channel number
+ * @ch_width: channel width
+ *
+ * Return: channel state
+ */
+eNVChannelEnabledType vos_get_5g_bonded_channel_state(
+ uint16_t chan_num,
+ enum phy_ch_width ch_width,
+ const struct bonded_chan *bonded_chan_ptr)
+{
+ bool bw_enabled = false;
+ uint32_t flags;
+
+ if (CH_WIDTH_80MHZ < ch_width)
+ return NV_CHANNEL_INVALID;
+
+ flags = vos_nv_get_channel_flags(chan_num);
+
+ if (CH_WIDTH_5MHZ == ch_width) {
+ bw_enabled = true;
+ } else if (CH_WIDTH_10MHZ == ch_width) {
+ bw_enabled = !(flags &
+ IEEE80211_CHAN_NO_10MHZ);
+ } else if (CH_WIDTH_20MHZ == ch_width) {
+ bw_enabled = !(flags &
+ IEEE80211_CHAN_NO_20MHZ);
+ } else if (CH_WIDTH_40MHZ == ch_width) {
+ if (chan_num == bonded_chan_ptr->start_ch)
+ bw_enabled =
+ !(flags & IEEE80211_CHAN_NO_HT40PLUS);
+ else
+ bw_enabled =
+ !(flags & IEEE80211_CHAN_NO_HT40MINUS);
+ } else if (CH_WIDTH_80MHZ == ch_width) {
+ bw_enabled = !(flags &
+ IEEE80211_CHAN_NO_80MHZ);
+ }
+
+ if (bw_enabled)
+ return NV_CHANNEL_ENABLE;
+ else
+ return NV_CHANNEL_DISABLE;
+}
+
+/**
+ * vos_set_sec_chan_offset_vht80() - set sec channel offset for vht80
+ * @oper_ch: operating channel
+ * @center_chan: center channel for operating channel
+ * @ch_params: channel parameters
+ *
+ * Return: void
+ */
+static inline void vos_set_sec_chan_offset_vht80(uint16_t oper_ch,
+ uint16_t center_chan, struct ch_params_s *ch_params)
+{
+ if ((oper_ch + 2 ) == center_chan)
+ ch_params->sec_ch_offset =
+ PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW;
+ else if ((oper_ch + 6 ) == center_chan)
+ ch_params->sec_ch_offset =
+ PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW;
+ else if ((oper_ch - 2 ) == center_chan)
+ ch_params->sec_ch_offset =
+ PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH;
+ else if ((oper_ch - 6 ) == center_chan)
+ ch_params->sec_ch_offset =
+ PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH;
+}
+
+/**
+ * vos_set_5g_channel_params() - set the 5G bonded channel parameters
+ * @oper_ch: operating channel
+ * @ch_params: channel parameters
+ *
+ * Return: void
+ */
+static void vos_set_5g_channel_params(uint16_t oper_ch,
+ struct ch_params_s *ch_params)
+{
+ eNVChannelEnabledType chan_state = NV_CHANNEL_ENABLE;
+ const struct bonded_chan *bonded_chan_ptr;
+ uint16_t center_chan;
+
+ if (CH_WIDTH_MAX <= ch_params->ch_width)
+ ch_params->ch_width = CH_WIDTH_80MHZ;
+
+ while (ch_params->ch_width < CH_WIDTH_INVALID) {
+ chan_state = vos_search_5g_bonded_channel(oper_ch,
+ ch_params->ch_width, &bonded_chan_ptr);
+ if (((NV_CHANNEL_ENABLE != chan_state) &&
+ (NV_CHANNEL_DFS != chan_state)))
+ goto next;
+
+ chan_state = vos_get_5g_bonded_channel_state(oper_ch,
+ ch_params->ch_width, bonded_chan_ptr);
+ if (((NV_CHANNEL_ENABLE != chan_state) &&
+ (NV_CHANNEL_DFS != chan_state)))
+ goto next;
+
+ if (CH_WIDTH_20MHZ >= ch_params->ch_width) {
+ ch_params->sec_ch_offset
+ = PHY_SINGLE_CHANNEL_CENTERED;
+ break;
+ } else if (CH_WIDTH_40MHZ == ch_params->ch_width) {
+ if (oper_ch == bonded_chan_ptr->start_ch)
+ ch_params->sec_ch_offset =
+ PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
+ else
+ ch_params->sec_ch_offset =
+ PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
+ }
+
+ center_chan = (bonded_chan_ptr->start_ch +
+ bonded_chan_ptr->end_ch) / 2;
+ ch_params->center_freq_seg0 =
+ vos_chan_to_freq(center_chan);
+
+ if (CH_WIDTH_80MHZ == ch_params->ch_width)
+ vos_set_sec_chan_offset_vht80(oper_ch,
+ center_chan, ch_params);
+
+ break;
+next:
+ ch_params->ch_width = next_lower_bw[ch_params->ch_width];
+ }
+}
+
+/**
+ * vos_get_2g_bonded_channel_state() - get the 2G bonded channel state
+ * @oper_ch: operating channel
+ * @ch_width: channel width
+ * @sec_ch: secondary channel
+ *
+ * Return: channel state
+ */
+eNVChannelEnabledType vos_get_2g_bonded_channel_state(uint16_t oper_ch,
+ enum phy_ch_width ch_width,
+ uint16_t sec_ch)
+{
+ eNVChannelEnabledType chan_state;
+ bool bw_enabled = false;
+ uint32_t flags;
+ bool ht_40_plus = false;
+
+ if (CH_WIDTH_40MHZ < ch_width)
+ return NV_CHANNEL_INVALID;
+
+ if (CH_WIDTH_40MHZ == ch_width) {
+ if ((sec_ch + 4 != oper_ch) &&
+ (oper_ch + 4 != sec_ch))
+ return NV_CHANNEL_INVALID;
+ ht_40_plus = (oper_ch < sec_ch)? true : false;
+ }
+
+ chan_state = vos_nv_getChannelEnabledState(oper_ch);
+ if ((NV_CHANNEL_INVALID == chan_state) ||
+ (NV_CHANNEL_DISABLE == chan_state))
+ return chan_state;
+
+ flags = vos_nv_get_channel_flags(oper_ch);
+
+ if (CH_WIDTH_5MHZ == ch_width) {
+ bw_enabled = true;
+ } else if (CH_WIDTH_10MHZ == ch_width) {
+ bw_enabled = !(flags &
+ IEEE80211_CHAN_NO_10MHZ);
+ } else if (CH_WIDTH_20MHZ == ch_width) {
+ bw_enabled = !(flags &
+ IEEE80211_CHAN_NO_20MHZ);
+ } else if (CH_WIDTH_40MHZ == ch_width) {
+ if (ht_40_plus)
+ bw_enabled =
+ !(flags & IEEE80211_CHAN_NO_HT40PLUS);
+ else
+ bw_enabled =
+ !(flags & IEEE80211_CHAN_NO_HT40MINUS);
+ }
+
+ if (bw_enabled)
+ return chan_state;
+ else
+ return NV_CHANNEL_DISABLE;
+}
+
+/**
+ * vos_set_2g_channel_params() - set the 2.4G bonded channel parameters
+ * @oper_ch: operating channel
+ * @ch_params: channel parameters
+ * @sec_ch_2g: 2.4G secondary channel
+ *
+ * Return: void
+ */
+static void vos_set_2g_channel_params(uint16_t oper_ch,
+ struct ch_params_s *ch_params,
+ uint16_t sec_ch_2g)
+{
+ eNVChannelEnabledType chan_state = NV_CHANNEL_ENABLE;
+
+ if (CH_WIDTH_MAX <= ch_params->ch_width)
+ ch_params->ch_width = CH_WIDTH_40MHZ;
+
+ while (ch_params->ch_width < CH_WIDTH_INVALID) {
+ chan_state = vos_get_2g_bonded_channel_state(oper_ch,
+ ch_params->ch_width,
+ sec_ch_2g);
+ if (NV_CHANNEL_ENABLE == chan_state) {
+ if (CH_WIDTH_40MHZ == ch_params->ch_width) {
+ if (oper_ch < sec_ch_2g)
+ ch_params->sec_ch_offset =
+ PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
+ else
+ ch_params->sec_ch_offset =
+ PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
+ ch_params->center_freq_seg0 =
+ vos_chan_to_freq(
+ (oper_ch + sec_ch_2g) / 2);
+ } else {
+ ch_params->sec_ch_offset =
+ PHY_SINGLE_CHANNEL_CENTERED;
+ }
+ break;
+ }
+
+ ch_params->ch_width = next_lower_bw[ch_params->ch_width];
+ }
+}
+
+/**
+ * vos_set_channel_params() - set the bonded channel parameters
+ * @oper_ch: operating channel
+ * @sec_ch_2g: 2.4G secondary channel
+ * @ch_params: chanel parameters
+ *
+ * Return: void
+ */
+void vos_set_channel_params(uint16_t oper_ch, uint16_t sec_ch_2g,
+ struct ch_params_s *ch_params)
+{
+ if (VOS_IS_CHANNEL_5GHZ(oper_ch))
+ vos_set_5g_channel_params(oper_ch, ch_params);
+ else if (VOS_IS_CHANNEL_24GHZ(oper_ch))
+ vos_set_2g_channel_params(oper_ch, ch_params, sec_ch_2g);
+}
+
/**------------------------------------------------------------------------
\brief vos_nv_getSupportedCountryCode() - get the list of supported
country codes