浏览代码

qcacmn: Add an API reg_get_center_channel in the Regulatory

In a SON WFA testcase, the QCA AP advertises the channel set in
operating class 128 as individual IEEE channel number (for eg. 36, 40,
44, 48 etc.) instead of center channel (for eg. 42, 58, 106 etc.) to
the third party AP.

As a result, the third party AP creates Front Haul VAPs in High Band
radio when the QCA AP is configured to Low Band, due to incorrect
channel set advertised to it.

To fix this issue, add an API reg_get_chan_or_chan_center to
calculate the center channel number for a 80MHz, 80_80 MHz and 160
MHz bandwidth channel, and use it to calculate the center channel
number within the channel set for a particular operating class in the
operating class table.

Change-Id: Idf7df70c8d01ed79b43d0ba21db7b07189f3f710
CRs-Fixed: 2612258
Hariharan Basuthkar 5 年之前
父节点
当前提交
a6a139298a

+ 68 - 7
umac/regulatory/core/src/reg_opclass.c

@@ -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
  * any purpose with or without fee is hereby granted, provided that the
@@ -619,6 +619,68 @@ reg_get_op_class_tbl_by_chan_map(const struct
 		*op_class_tbl = global_op_class;
 }
 
+/**
+ * reg_get_channel_cen - Calculate central channel in the channel set.
+ *
+ * @op_class_tbl - Pointer to op_class_tbl.
+ * @idx - Pointer to channel index.
+ * @num_channels - Number of channels.
+ * @center_chan - Pointer to center channel number
+ *
+ * Return : void
+ */
+static void reg_get_channel_cen(const struct
+				reg_dmn_op_class_map_t *op_class_tbl,
+				uint8_t *idx,
+				uint8_t num_channels,
+				uint8_t *center_chan)
+{
+	uint8_t i;
+	uint16_t new_chan = 0;
+
+	for (i = *idx; i < (*idx + num_channels); i++)
+		new_chan += op_class_tbl->channels[i];
+
+	new_chan = new_chan / num_channels;
+	*center_chan = new_chan;
+	*idx = *idx + num_channels;
+}
+
+/**
+ * reg_get_chan_or_chan_center - Calculate central channel in the channel set.
+ *
+ * @op_class_tbl - Pointer to op_class_tbl.
+ * @idx - Pointer to channel index.
+ *
+ * Return : Center channel number
+ */
+static uint8_t reg_get_chan_or_chan_center(const struct
+					   reg_dmn_op_class_map_t *op_class_tbl,
+					   uint8_t *idx)
+{
+	uint8_t center_chan;
+
+	if (((op_class_tbl->chan_spacing == BW_80_MHZ) &&
+	     (op_class_tbl->behav_limit == BIT(BEHAV_NONE))) ||
+	    ((op_class_tbl->chan_spacing == BW_80_MHZ) &&
+	     (op_class_tbl->behav_limit == BIT(BEHAV_BW80_PLUS)))) {
+		reg_get_channel_cen(op_class_tbl,
+				    idx,
+				    NUM_20_MHZ_CHAN_IN_80_MHZ_CHAN,
+				    &center_chan);
+	} else if (op_class_tbl->chan_spacing == BW_160_MHZ) {
+		reg_get_channel_cen(op_class_tbl,
+				    idx,
+				    NUM_20_MHZ_CHAN_IN_160_MHZ_CHAN,
+				    &center_chan);
+	} else {
+		center_chan = op_class_tbl->channels[*idx];
+		*idx = *idx + 1;
+	}
+
+	return center_chan;
+}
+
 /**
  * reg_get_channels_from_opclassmap()- Get channels from the opclass map
  * @pdev: Pointer to pdev
@@ -653,17 +715,16 @@ reg_get_channels_from_opclassmap(
 			reg_is_freq_present_in_cur_chan_list(pdev, search_freq);
 
 		if (!is_freq_present) {
-			reg_ap_cap[index].
-					non_sup_chan_list[n_unsup_chans++] =
-					op_class_tbl->channels[chan_idx];
+			reg_ap_cap[index].non_sup_chan_list[n_unsup_chans++] =
+				reg_get_chan_or_chan_center(op_class_tbl,
+							    &chan_idx);
 			reg_ap_cap[index].num_non_supported_chan++;
 		} else {
 			reg_ap_cap[index].sup_chan_list[n_sup_chans++] =
-					op_class_tbl->channels[chan_idx];
+				reg_get_chan_or_chan_center(op_class_tbl,
+							    &chan_idx);
 			reg_ap_cap[index].num_supported_chan++;
 		}
-
-		chan_idx++;
 	}
 
 	if (reg_ap_cap[index].num_supported_chan >= 1)

+ 3 - 1
umac/regulatory/core/src/reg_services_common.h

@@ -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
@@ -31,6 +31,8 @@
 #define FREQ_TO_CHAN_SCALE     5
 /* The distance between the 80Mhz center and the nearest 20Mhz channel */
 #define NEAREST_20MHZ_CHAN_FREQ_OFFSET     10
+#define NUM_20_MHZ_CHAN_IN_80_MHZ_CHAN     4
+#define NUM_20_MHZ_CHAN_IN_160_MHZ_CHAN    8
 
 #ifdef CONFIG_CHAN_NUM_API
 #define REG_MIN_24GHZ_CH_NUM channel_map[MIN_24GHZ_CHANNEL].chan_num

+ 4 - 1
umac/regulatory/dispatcher/inc/reg_services_public_struct.h

@@ -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
  * any purpose with or without fee is hereby granted, provided that the
@@ -61,6 +61,9 @@
 #define REGULATORY_PHYMODE_NO11AC    BIT(4)
 #define REGULATORY_PHYMODE_NO11AX    BIT(5)
 
+#define BW_80_MHZ     80
+#define BW_160_MHZ    160
+
 /**
  * enum dfs_reg - DFS region
  * @DFS_UNINIT_REGION: un-initialized region