Prechádzať zdrojové kódy

qcacmn: update unsafe channel list for SAP for freq extcmd

Currently unsafe channel list updated from firmware using
"wmi_wlan_freq_avoid_event_id".

This change is to update unsafe channel list for vendor
QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_EXT which we receive from
userspace.

Change-Id: I57ff334e9cf47468c30bc6884a9ead0a65a92eab
CRs-Fixed: 3103275
Balaji Pothunoori 3 rokov pred
rodič
commit
7192d90810

+ 3 - 0
umac/regulatory/core/src/reg_build_chan_list.c

@@ -1659,6 +1659,9 @@ reg_modify_chan_list_for_avoid_chan_ext(struct wlan_regulatory_pdev_priv_obj
 	if (!psoc)
 		return;
 
+	if (reg_check_coex_unsafe_nb_user_prefer(psoc))
+		return;
+
 	psoc_priv_obj = reg_get_psoc_obj(psoc);
 	if (!psoc_priv_obj)
 		return;

+ 37 - 4
umac/regulatory/core/src/reg_callbacks.c

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2014-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
@@ -92,6 +93,7 @@ static void reg_call_chan_change_cbks(struct wlan_objmgr_psoc *psoc,
 	qdf_mem_free(cur_chan_list);
 }
 
+#ifdef FEATURE_WLAN_CH_AVOID_EXT
 /**
  * reg_alloc_and_fill_payload() - Alloc and fill payload structure.
  * @psoc: Pointer to global psoc structure.
@@ -114,17 +116,48 @@ static void reg_alloc_and_fill_payload(struct wlan_objmgr_psoc *psoc,
 	if (*payload) {
 		(*payload)->psoc = psoc;
 		(*payload)->pdev = pdev;
-		(*payload)->ch_avoid_ind = !!psoc_priv_obj->ch_avoid_ind;
-		qdf_mem_copy(&(*payload)->avoid_info.freq_list,
-			     &psoc_priv_obj->avoid_freq_list,
-			     sizeof(psoc_priv_obj->avoid_freq_list));
+		if (reg_check_coex_unsafe_nb_user_prefer(psoc)) {
+			(*payload)->ch_avoid_ind =
+				!!psoc_priv_obj->ch_avoid_ext_ind;
+			qdf_mem_copy(&(*payload)->avoid_info.freq_list,
+				     &psoc_priv_obj->avoid_freq_ext_list,
+				sizeof(psoc_priv_obj->avoid_freq_ext_list));
+			psoc_priv_obj->ch_avoid_ext_ind = false;
+		}
 		qdf_mem_copy(&(*payload)->avoid_info.chan_list,
 			     &psoc_priv_obj->unsafe_chan_list,
 			     sizeof(psoc_priv_obj->unsafe_chan_list));
+	}
+}
+#else
+static void reg_alloc_and_fill_payload(struct wlan_objmgr_psoc *psoc,
+				       struct wlan_objmgr_pdev *pdev,
+				       struct reg_sched_payload **payload)
+{
+	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
 
+	psoc_priv_obj = reg_get_psoc_obj(psoc);
+	if (!psoc_priv_obj) {
+		reg_err("reg psoc private obj is NULL");
+		*payload = NULL;
+		return;
+	}
+
+	*payload = qdf_mem_malloc(sizeof(**payload));
+	if (*payload) {
+		(*payload)->psoc = psoc;
+		(*payload)->pdev = pdev;
+		(*payload)->ch_avoid_ind = !!psoc_priv_obj->ch_avoid_ind;
+		qdf_mem_copy(&(*payload)->avoid_info.freq_list,
+			     &psoc_priv_obj->avoid_freq_list,
+			     sizeof(psoc_priv_obj->avoid_freq_list));
 		psoc_priv_obj->ch_avoid_ind = false;
 	}
+	qdf_mem_copy(&(*payload)->avoid_info.chan_list,
+		     &psoc_priv_obj->unsafe_chan_list,
+		     sizeof(psoc_priv_obj->unsafe_chan_list));
 }
+#endif
 
 /**
  * reg_chan_change_flush_cbk_sb() - Flush south bound channel change callbacks.

+ 8 - 2
umac/regulatory/core/src/reg_lte.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2014-2020 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
@@ -28,8 +28,8 @@
 #include "reg_services_public_struct.h"
 #include <wlan_objmgr_psoc_obj.h>
 #include <wlan_objmgr_pdev_obj.h>
-#include "reg_services_common.h"
 #include "reg_priv_objs.h"
+#include "reg_services_common.h"
 #include "reg_build_chan_list.h"
 #include "reg_callbacks.h"
 #include "reg_lte.h"
@@ -185,6 +185,12 @@ QDF_STATUS reg_process_ch_avoid_event(struct wlan_objmgr_psoc *psoc,
 		reg_err("reg psoc private obj is NULL");
 		return QDF_STATUS_E_FAILURE;
 	}
+
+	if (reg_check_coex_unsafe_nb_user_prefer(psoc)) {
+		reg_err("skipping LTE Coex unsafe channel change");
+		return QDF_STATUS_E_FAILURE;
+	}
+
 	if (CH_AVOID_RULE_DO_NOT_RESTART ==
 	    psoc_priv_obj->restart_beaconing) {
 		reg_debug("skipping all LTE Coex unsafe channel range");

+ 2 - 1
umac/regulatory/core/src/reg_priv_objs.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2017-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
@@ -178,6 +178,7 @@ struct wlan_regulatory_psoc_priv_obj {
 #ifdef FEATURE_WLAN_CH_AVOID_EXT
 	bool ch_avoid_ext_ind;
 	struct ch_avoid_ind_type avoid_freq_ext_list;
+	bool coex_unsafe_chan_nb_user_prefer;
 #endif
 };
 

+ 71 - 5
umac/regulatory/core/src/reg_services_common.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2014-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
@@ -6070,11 +6070,16 @@ reg_process_ch_avoid_freq_ext(struct wlan_objmgr_psoc *psoc,
 	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
 	uint8_t start_channel;
 	uint8_t end_channel;
+	int32_t txpower;
+	bool is_valid_txpower;
 	struct ch_avoid_freq_type *range;
 	enum channel_enum ch_loop;
 	enum channel_enum start_ch_idx;
 	enum channel_enum end_ch_idx;
 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
+	uint32_t len;
+	struct unsafe_ch_list *unsafe_ch_list;
+	bool coex_unsafe_nb_user_prefer;
 
 	pdev_priv_obj = reg_get_pdev_obj(pdev);
 
@@ -6088,15 +6093,23 @@ reg_process_ch_avoid_freq_ext(struct wlan_objmgr_psoc *psoc,
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	if (pdev_priv_obj->avoid_chan_ext_list.chan_cnt > 0) {
-		uint32_t len;
+	unsafe_ch_list = &psoc_priv_obj->unsafe_chan_list;
+	coex_unsafe_nb_user_prefer =
+		psoc_priv_obj->coex_unsafe_chan_nb_user_prefer;
 
+	if (pdev_priv_obj->avoid_chan_ext_list.chan_cnt > 0) {
 		len = sizeof(pdev_priv_obj->avoid_chan_ext_list.chan_freq_list);
 		pdev_priv_obj->avoid_chan_ext_list.chan_cnt = 0;
 		qdf_mem_zero(&pdev_priv_obj->avoid_chan_ext_list.chan_freq_list,
 			     len);
 	}
 
+	if (unsafe_ch_list->chan_cnt > 0) {
+		len = sizeof(unsafe_ch_list->chan_freq_list);
+		unsafe_ch_list->chan_cnt = 0;
+		qdf_mem_zero(unsafe_ch_list->chan_freq_list, len);
+	}
+
 	for (i = 0; i < psoc_priv_obj->avoid_freq_ext_list.ch_avoid_range_cnt;
 		i++) {
 		if (pdev_priv_obj->avoid_chan_ext_list.chan_cnt >=
@@ -6105,15 +6118,23 @@ reg_process_ch_avoid_freq_ext(struct wlan_objmgr_psoc *psoc,
 			break;
 		}
 
+		if (unsafe_ch_list->chan_cnt >= NUM_CHANNELS) {
+			reg_warn("LTE Coex unsafe channel list full");
+			break;
+		}
+
 		start_ch_idx = INVALID_CHANNEL;
 		end_ch_idx = INVALID_CHANNEL;
 		range = &psoc_priv_obj->avoid_freq_ext_list.avoid_freq_range[i];
 
 		start_channel = reg_freq_to_chan(pdev, range->start_freq);
 		end_channel = reg_freq_to_chan(pdev, range->end_freq);
-		reg_debug("start: freq %d, ch %d, end: freq %d, ch %d",
+		txpower = range->txpower;
+		is_valid_txpower = range->is_valid_txpower;
+
+		reg_debug("start: freq %d, ch %d, end: freq %d, ch %d txpower %d",
 			  range->start_freq, start_channel, range->end_freq,
-			  end_channel);
+			  end_channel, txpower);
 
 		/* do not process frequency bands that are not mapped to
 		 * predefined channels
@@ -6148,6 +6169,23 @@ reg_process_ch_avoid_freq_ext(struct wlan_objmgr_psoc *psoc,
 			[pdev_priv_obj->avoid_chan_ext_list.chan_cnt++] =
 			REG_CH_TO_FREQ(ch_loop);
 
+			if (coex_unsafe_nb_user_prefer) {
+				if (unsafe_ch_list->chan_cnt >=
+					NUM_CHANNELS) {
+					reg_warn("LTECoex unsafe ch list full");
+					break;
+				}
+				unsafe_ch_list->txpower[
+				unsafe_ch_list->chan_cnt] =
+					txpower;
+				unsafe_ch_list->is_valid_txpower[
+				unsafe_ch_list->chan_cnt] =
+					is_valid_txpower;
+				unsafe_ch_list->chan_freq_list[
+				unsafe_ch_list->chan_cnt++] =
+					REG_CH_TO_FREQ(ch_loop);
+			}
+
 			if (pdev_priv_obj->avoid_chan_ext_list.chan_cnt >=
 				NUM_CHANNELS) {
 				reg_debug("avoid freq ext list full");
@@ -6167,6 +6205,14 @@ reg_process_ch_avoid_freq_ext(struct wlan_objmgr_psoc *psoc,
 			range->start_freq = range->start_freq - HALF_20MHZ_BW;
 			range->end_freq = range->end_freq + HALF_20MHZ_BW;
 		}
+
+		for (ch_loop = 0; ch_loop <
+			unsafe_ch_list->chan_cnt; ch_loop++) {
+			if (ch_loop >= NUM_CHANNELS)
+				break;
+			reg_debug("Unsafe freq %d",
+				  unsafe_ch_list->chan_freq_list[ch_loop]);
+		}
 	}
 
 	return QDF_STATUS_SUCCESS;
@@ -6242,7 +6288,14 @@ reg_process_ch_avoid_ext_event(struct wlan_objmgr_psoc *psoc,
 			ch_avoid_event->avoid_freq_range[i].start_freq;
 		range->end_freq =
 			ch_avoid_event->avoid_freq_range[i].end_freq;
+		range->txpower =
+			ch_avoid_event->avoid_freq_range[i].txpower;
+		range->is_valid_txpower =
+			ch_avoid_event->avoid_freq_range[i].is_valid_txpower;
 	}
+
+	psoc_priv_obj->avoid_freq_ext_list.restriction_mask =
+		ch_avoid_event->restriction_mask;
 	psoc_priv_obj->avoid_freq_ext_list.ch_avoid_range_cnt =
 		ch_avoid_event->ch_avoid_range_cnt;
 
@@ -6264,6 +6317,19 @@ reg_process_ch_avoid_ext_event(struct wlan_objmgr_psoc *psoc,
 
 	return status;
 }
+
+bool reg_check_coex_unsafe_nb_user_prefer(struct wlan_objmgr_psoc *psoc)
+{
+	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
+
+	psoc_priv_obj = reg_get_psoc_obj(psoc);
+	if (!psoc_priv_obj) {
+		reg_err("reg psoc private obj is NULL");
+		return false;
+	}
+
+	return psoc_priv_obj->coex_unsafe_chan_nb_user_prefer;
+}
 #endif
 
 #if defined(CONFIG_AFC_SUPPORT) && defined(CONFIG_BAND_6GHZ)

+ 15 - 0
umac/regulatory/core/src/reg_services_common.h

@@ -1732,6 +1732,15 @@ bool reg_is_upper_6g_edge_ch_disabled(struct wlan_objmgr_psoc *psoc);
 QDF_STATUS
 reg_process_ch_avoid_ext_event(struct wlan_objmgr_psoc *psoc,
 			       struct ch_avoid_ind_type *ch_avoid_event);
+/**
+ * reg_check_coex_unsafe_nb_user_prefer() - get coex unsafe nb
+ * user prefer ini
+ * @psoc: pointer to psoc
+ *
+ * Return: bool
+ */
+
+bool reg_check_coex_unsafe_nb_user_prefer(struct wlan_objmgr_psoc *psoc);
 #else
 static inline QDF_STATUS
 reg_process_ch_avoid_ext_event(struct wlan_objmgr_psoc *psoc,
@@ -1739,6 +1748,12 @@ reg_process_ch_avoid_ext_event(struct wlan_objmgr_psoc *psoc,
 {
 	return QDF_STATUS_SUCCESS;
 }
+
+static inline
+bool reg_check_coex_unsafe_nb_user_prefer(struct wlan_objmgr_psoc *psoc)
+{
+	return false;
+}
 #endif
 
 #if defined(CONFIG_AFC_SUPPORT) && defined(CONFIG_BAND_6GHZ)

+ 22 - 1
umac/regulatory/core/src/reg_utils.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2014-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
@@ -375,6 +375,26 @@ reg_get_6g_power_type_for_ctry(struct wlan_objmgr_psoc *psoc,
 }
 #endif
 
+#ifdef FEATURE_WLAN_CH_AVOID_EXT
+static inline
+void reg_get_coex_unsafe_chan_nb_user_prefer(
+		struct wlan_regulatory_psoc_priv_obj
+		*psoc_priv_obj,
+		 struct reg_config_vars config_vars)
+{
+	psoc_priv_obj->coex_unsafe_chan_nb_user_prefer =
+		config_vars.coex_unsafe_chan_nb_user_prefer;
+}
+#else
+static inline
+void reg_get_coex_unsafe_chan_nb_user_prefer(
+		struct wlan_regulatory_psoc_priv_obj
+		*psoc_priv_obj,
+		struct reg_config_vars config_vars)
+{
+}
+#endif
+
 #ifdef CONFIG_CHAN_FREQ_API
 bool reg_is_passive_or_disable_for_freq(struct wlan_objmgr_pdev *pdev,
 					qdf_freq_t freq)
@@ -793,6 +813,7 @@ QDF_STATUS reg_set_config_vars(struct wlan_objmgr_psoc *psoc,
 		config_vars.enable_5dot9_ghz_chan_in_master_mode;
 	psoc_priv_obj->retain_nol_across_regdmn_update =
 		config_vars.retain_nol_across_regdmn_update;
+	reg_get_coex_unsafe_chan_nb_user_prefer(psoc_priv_obj, config_vars);
 
 	status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_REGULATORY_SB_ID);
 	if (QDF_IS_STATUS_ERROR(status)) {

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

@@ -48,7 +48,7 @@
 #define MAX_STA_VDEV_CNT 4
 #define INVALID_VDEV_ID 0xFF
 #define INVALID_CHANNEL_NUM 0x0
-#define CH_AVOID_MAX_RANGE   4
+#define CH_AVOID_MAX_RANGE   (NUM_5GHZ_CHANNELS + NUM_24GHZ_CHANNELS)
 #define REG_ALPHA2_LEN 2
 #define MAX_REG_RULES 10
 #define MAX_6G_REG_RULES 5
@@ -1391,6 +1391,8 @@ enum restart_beaconing_on_ch_avoid_rule {
  * @enable_5dot9_ghz_chan_in_master_mode: 5.9 GHz channel support in
  * master mode
  * @retain_nol_across_regdmn_update: Retain the NOL list across the regdomain.
+ * @coex_unsafe_chan_nb_user_prefer: Honor coex unsafe chan cmd from firmware or
+ * userspace
  */
 struct reg_config_vars {
 	uint32_t enable_11d_support;
@@ -1405,6 +1407,9 @@ struct reg_config_vars {
 	bool enable_11d_in_world_mode;
 	bool enable_5dot9_ghz_chan_in_master_mode;
 	bool retain_nol_across_regdmn_update;
+#ifdef FEATURE_WLAN_CH_AVOID_EXT
+	bool coex_unsafe_chan_nb_user_prefer;
+#endif
 };
 
 /**
@@ -1534,20 +1539,25 @@ struct cur_regdmn_info {
  * struct ch_avoid_freq_type
  * @start_freq: start freq
  * @end_freq: end freq
+ * @txpower: txpower
  */
 struct ch_avoid_freq_type {
 	qdf_freq_t start_freq;
 	qdf_freq_t end_freq;
+	int32_t txpower;
+	bool is_valid_txpower;
 };
 
 /**
  * struct ch_avoid_ind_type
  * @ch_avoid_range_cnt: count
  * @avoid_freq_range: avoid freq range array
+ * @restriction_mask: restriction mask to apply txpower
  */
 struct ch_avoid_ind_type {
 	uint32_t ch_avoid_range_cnt;
 	struct ch_avoid_freq_type avoid_freq_range[CH_AVOID_MAX_RANGE];
+	uint8_t restriction_mask;
 };
 
 /**
@@ -1558,6 +1568,8 @@ struct ch_avoid_ind_type {
 struct unsafe_ch_list {
 	uint16_t chan_cnt;
 	uint16_t chan_freq_list[NUM_CHANNELS];
+	int32_t txpower[NUM_CHANNELS];
+	bool is_valid_txpower[NUM_CHANNELS];
 };
 
 /**