Browse Source

qcacmn: Do not update the NOL state of the channels

Currently driver sets the NOL state of the channels to false
on every regulatory updated, which indicates the channel is
not in NOL. Which may lead to some issues where the channel
is actually in NOL but host treats it as non-NOL channel.

Ideally NOL list should be maintained throughout the driver
lifetime and across the regulatory changes.

To address this issue add a logic to not update the NOL state
of the channels whenever the regulatory update is received.

Change-Id: I7487a24a349f5f6e06a058b4d07799c8e5ac2d40
CRs-Fixed: 2735137
Ashish Kumar Dhanotiya 5 years ago
parent
commit
2d6243e27e

+ 2 - 1
umac/regulatory/core/src/reg_build_chan_list.c

@@ -1141,7 +1141,8 @@ QDF_STATUS reg_process_master_chan_list(
 			REGULATORY_CHAN_DISABLED;
 		mas_chan_list[chan_enum].state =
 			CHANNEL_STATE_DISABLE;
-		mas_chan_list[chan_enum].nol_chan = false;
+		if (!soc_reg->retain_nol_across_regdmn_update)
+			mas_chan_list[chan_enum].nol_chan = false;
 	}
 
 	soc_reg->num_phy = regulat_info->num_phy;

+ 1 - 0
umac/regulatory/core/src/reg_priv_objs.c

@@ -95,6 +95,7 @@ QDF_STATUS wlan_regulatory_psoc_obj_created_notification(
 	soc_reg_obj->enable_11d_in_world_mode = false;
 	soc_reg_obj->five_dot_nine_ghz_supported = false;
 	soc_reg_obj->enable_5dot9_ghz_chan_in_master_mode = false;
+	soc_reg_obj->retain_nol_across_regdmn_update = false;
 
 	for (i = 0; i < MAX_STA_VDEV_CNT; i++)
 		soc_reg_obj->vdev_ids_11d[i] = INVALID_VDEV_ID;

+ 3 - 0
umac/regulatory/core/src/reg_priv_objs.h

@@ -99,6 +99,8 @@ struct chan_change_cbk_entry {
  *	(service bit WMI_SERVICE_5_DOT_9GHZ_SUPPORT)
  * @enable_5dot9_ghz_chan_in_master_mode: 5.9 GHz channel support in
  *	master mode (ini fcc_5dot9_ghz_chan_in_master_mode)
+ * @retain_nol_across_regdmn_update: Retain the NOL list across the regdomain
+ *	changes.
  */
 struct wlan_regulatory_psoc_priv_obj {
 	struct mas_chan_params mas_chan_params[PSOC_MAX_PHY_REG_CAP];
@@ -150,6 +152,7 @@ struct wlan_regulatory_psoc_priv_obj {
 	bool enable_11d_in_world_mode;
 	bool enable_5dot9_ghz_chan_in_master_mode;
 	qdf_spinlock_t cbk_list_lock;
+	bool retain_nol_across_regdmn_update;
 };
 
 /**

+ 46 - 1
umac/regulatory/core/src/reg_services_common.c

@@ -3657,13 +3657,54 @@ bool reg_is_dfs_for_freq(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq)
 	return chan_flags & REGULATORY_CHAN_RADAR;
 }
 
+#ifdef CONFIG_REG_CLIENT
+/**
+ * reg_get_psoc_mas_chan_list () - Get psoc master channel list
+ * @pdev: pointer to pdev object
+ * @psoc: pointer to psoc object
+ *
+ * Return: psoc master chanel list
+ */
+static struct regulatory_channel *reg_get_psoc_mas_chan_list(
+						struct wlan_objmgr_pdev *pdev,
+						struct wlan_objmgr_psoc *psoc)
+{
+	struct wlan_regulatory_psoc_priv_obj *soc_reg;
+	uint8_t pdev_id;
+	uint8_t phy_id;
+	struct wlan_lmac_if_reg_tx_ops *reg_tx_ops;
+
+	soc_reg = reg_get_psoc_obj(psoc);
+	if (!soc_reg) {
+		reg_err("reg psoc private obj is NULL");
+		return NULL;
+	}
+	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
+
+	reg_tx_ops = reg_get_psoc_tx_ops(psoc);
+	if (reg_tx_ops->get_phy_id_from_pdev_id)
+		reg_tx_ops->get_phy_id_from_pdev_id(psoc, pdev_id, &phy_id);
+	else
+		phy_id = pdev_id;
+
+	return soc_reg->mas_chan_params[phy_id].mas_chan_list;
+}
+#else
+static inline struct regulatory_channel *reg_get_psoc_mas_chan_list(
+						struct wlan_objmgr_pdev *pdev,
+						struct wlan_objmgr_psoc *psoc)
+{
+	return NULL;
+}
+#endif
+
 void reg_update_nol_ch_for_freq(struct wlan_objmgr_pdev *pdev,
 				uint16_t *chan_freq_list,
 				uint8_t num_chan,
 				bool nol_chan)
 {
 	enum channel_enum chan_enum;
-	struct regulatory_channel *mas_chan_list;
+	struct regulatory_channel *mas_chan_list, *psoc_mas_chan_list;
 	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
 	struct wlan_objmgr_psoc *psoc;
 	uint16_t i;
@@ -3681,6 +3722,8 @@ void reg_update_nol_ch_for_freq(struct wlan_objmgr_pdev *pdev,
 		return;
 	}
 
+	psoc_mas_chan_list = reg_get_psoc_mas_chan_list(pdev, psoc);
+
 	mas_chan_list = pdev_priv_obj->mas_chan_list;
 	for (i = 0; i < num_chan; i++) {
 		chan_enum = reg_get_chan_enum_for_freq(chan_freq_list[i]);
@@ -3690,6 +3733,8 @@ void reg_update_nol_ch_for_freq(struct wlan_objmgr_pdev *pdev,
 			continue;
 		}
 		mas_chan_list[chan_enum].nol_chan = nol_chan;
+		if (psoc_mas_chan_list)
+			psoc_mas_chan_list[chan_enum].nol_chan = nol_chan;
 	}
 
 	reg_compute_pdev_current_chan_list(pdev_priv_obj);

+ 2 - 0
umac/regulatory/core/src/reg_utils.c

@@ -796,6 +796,8 @@ QDF_STATUS reg_set_config_vars(struct wlan_objmgr_psoc *psoc,
 		config_vars.enable_11d_in_world_mode;
 	psoc_priv_obj->enable_5dot9_ghz_chan_in_master_mode =
 		config_vars.enable_5dot9_ghz_chan_in_master_mode;
+	psoc_priv_obj->retain_nol_across_regdmn_update =
+		config_vars.retain_nol_across_regdmn_update;
 
 	status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_REGULATORY_SB_ID);
 	if (QDF_IS_STATUS_ERROR(status)) {

+ 2 - 0
umac/regulatory/dispatcher/inc/reg_services_public_struct.h

@@ -980,6 +980,7 @@ enum restart_beaconing_on_ch_avoid_rule {
  * @enable_11d_in_world_mode: enable 11d in world mode
  * @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.
  */
 struct reg_config_vars {
 	uint32_t enable_11d_support;
@@ -993,6 +994,7 @@ struct reg_config_vars {
 	bool enable_srd_chan_in_master_mode;
 	bool enable_11d_in_world_mode;
 	bool enable_5dot9_ghz_chan_in_master_mode;
+	bool retain_nol_across_regdmn_update;
 };
 
 /**