Browse Source

qcacmn: Add support to send regulatory sync event

Add support to send regulatory rules info in regulatory sync
event to user space for self managed regulatory when regulatory
info is updated.

Change-Id: Iac8704598fd181e47cb023405dfe592c4c93f51b
CRs-Fixed: 2242701
Kiran Kumar Lokere 7 years ago
parent
commit
76da7996ae

+ 3 - 0
os_if/linux/qca_vendor.h

@@ -2971,6 +2971,8 @@ enum qca_wlan_vendor_attr_nd_offload {
  *	QCA_WLAN_VENDOR_FEATURE_OCE_AP, the userspace shall assume that
  *	this Device may not support all OCE AP functionalities but can support
  *	only OCE STA-CFON functionalities.
+ * @QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY: Device supports self
+ *	managed regulatory.
  */
 enum qca_wlan_vendor_features {
 	QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD = 0,
@@ -2980,6 +2982,7 @@ enum qca_wlan_vendor_features {
 	QCA_WLAN_VENDOR_FEATURE_OCE_STA = 4,
 	QCA_WLAN_VENDOR_FEATURE_OCE_AP = 5,
 	QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON = 6,
+	QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY = 7,
 	/* Additional features need to be added above this */
 	NUM_QCA_WLAN_VENDOR_FEATURES
 };

+ 1 - 0
umac/regulatory/core/src/reg_priv.h

@@ -108,6 +108,7 @@ struct wlan_regulatory_pdev_priv_obj {
 	struct ch_avoid_ind_type freq_avoid_list;
 	bool force_ssc_disable_indoor_channel;
 	bool sap_state;
+	struct reg_rule_info reg_rules;
 };
 
 #endif

+ 93 - 2
umac/regulatory/core/src/reg_services.c

@@ -2496,7 +2496,7 @@ skip_ch_avoid_ind:
 		qdf_spin_unlock_bh(&psoc_priv_obj->cbk_list_lock);
 		if (callback != NULL)
 			callback(psoc, pdev, cur_chan_list, avoid_freq_ind,
-					cbk_list[ctr].arg);
+				 cbk_list[ctr].arg);
 	}
 	qdf_mem_free(cur_chan_list);
 	if (avoid_freq_ind)
@@ -2745,6 +2745,44 @@ static QDF_STATUS reg_sched_11d_msg(struct wlan_objmgr_psoc *psoc)
 }
 #endif
 
+void reg_reset_reg_rules(struct reg_rule_info *reg_rules)
+{
+	if (reg_rules->reg_rules_ptr)
+		qdf_mem_free(reg_rules->reg_rules_ptr);
+	qdf_mem_zero(reg_rules, sizeof(*reg_rules));
+}
+
+static void reg_save_reg_rules_to_pdev(struct reg_rule_info *psoc_reg_rules,
+				       struct wlan_regulatory_pdev_priv_obj
+				       *pdev_priv_obj)
+{
+	uint32_t reg_rule_len;
+	struct reg_rule_info *pdev_reg_rules;
+
+	pdev_reg_rules = &pdev_priv_obj->reg_rules;
+	reg_reset_reg_rules(pdev_reg_rules);
+	pdev_reg_rules->num_of_reg_rules = psoc_reg_rules->num_of_reg_rules;
+	if (!pdev_reg_rules->num_of_reg_rules) {
+		reg_debug("no reg rules in psoc");
+		return;
+	}
+	reg_rule_len = pdev_reg_rules->num_of_reg_rules *
+		       sizeof(struct cur_reg_rule);
+	pdev_reg_rules->reg_rules_ptr = qdf_mem_malloc(reg_rule_len);
+	if (!pdev_reg_rules->reg_rules_ptr) {
+		reg_err("mem alloc failed for pdev reg rules");
+		return;
+	}
+	qdf_mem_copy(pdev_reg_rules->reg_rules_ptr,
+		     psoc_reg_rules->reg_rules_ptr,
+		     reg_rule_len);
+	qdf_mem_copy(pdev_reg_rules->alpha2, pdev_priv_obj->current_country,
+		     REG_ALPHA2_LEN + 1);
+	pdev_reg_rules->dfs_region = pdev_priv_obj->dfs_region;
+	reg_debug("num pdev reg rules saved %d",
+		  pdev_reg_rules->num_of_reg_rules);
+}
+
 static void reg_propagate_mas_chan_list_to_pdev(struct wlan_objmgr_psoc *psoc,
 						void *object, void *arg)
 {
@@ -2754,6 +2792,7 @@ static void reg_propagate_mas_chan_list_to_pdev(struct wlan_objmgr_psoc *psoc,
 	enum direction *dir = arg;
 	uint32_t pdev_id;
 	struct wlan_lmac_if_reg_tx_ops *reg_tx_ops;
+	struct reg_rule_info *psoc_reg_rules;
 
 	psoc_priv_obj = (struct wlan_regulatory_psoc_priv_obj *)
 		wlan_objmgr_psoc_get_comp_private_obj(psoc,
@@ -2774,7 +2813,8 @@ static void reg_propagate_mas_chan_list_to_pdev(struct wlan_objmgr_psoc *psoc,
 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
 	reg_init_pdev_mas_chan_list(pdev_priv_obj,
 		      &psoc_priv_obj->mas_chan_params[pdev_id]);
-
+	psoc_reg_rules = &psoc_priv_obj->mas_chan_params[pdev_id].reg_rules;
+	reg_save_reg_rules_to_pdev(psoc_reg_rules, pdev_priv_obj);
 	reg_compute_pdev_current_chan_list(pdev_priv_obj);
 
 	reg_tx_ops = reg_get_psoc_tx_ops(psoc);
@@ -2832,6 +2872,7 @@ QDF_STATUS reg_process_master_chan_list(struct cur_regulatory_info
 	uint8_t phy_id;
 	struct wlan_objmgr_pdev *pdev;
 	struct wlan_lmac_if_reg_tx_ops *tx_ops;
+	struct reg_rule_info *reg_rules;
 
 	reg_debug("process reg master chan list");
 
@@ -2918,6 +2959,30 @@ QDF_STATUS reg_process_master_chan_list(struct cur_regulatory_info
 	reg_update_max_bw_per_rule(num_5g_reg_rules,
 			       reg_rule_5g, max_bw_5g);
 
+	reg_rules = &soc_reg->mas_chan_params[phy_id].reg_rules;
+	reg_reset_reg_rules(reg_rules);
+
+	reg_rules->num_of_reg_rules = num_5g_reg_rules + num_2g_reg_rules;
+
+	if (reg_rules->num_of_reg_rules) {
+		reg_rules->reg_rules_ptr =
+			qdf_mem_malloc(reg_rules->num_of_reg_rules *
+					sizeof(struct cur_reg_rule));
+		if (!reg_rules->reg_rules_ptr) {
+			reg_err("mem alloc failed for reg_rules");
+		} else {
+			if (num_2g_reg_rules)
+				qdf_mem_copy(reg_rules->reg_rules_ptr,
+					     reg_rule_2g, num_2g_reg_rules *
+					     sizeof(struct cur_reg_rule));
+			if (num_5g_reg_rules)
+				qdf_mem_copy(reg_rules->reg_rules_ptr +
+					     num_2g_reg_rules, reg_rule_5g,
+					     num_5g_reg_rules *
+					     sizeof(struct cur_reg_rule));
+		}
+	}
+
 	if (num_5g_reg_rules != 0)
 		reg_do_auto_bw_correction(num_5g_reg_rules,
 				      reg_rule_5g, max_bw_5g);
@@ -2979,6 +3044,7 @@ QDF_STATUS reg_process_master_chan_list(struct cur_regulatory_info
 	if (pdev != NULL) {
 		reg_propagate_mas_chan_list_to_pdev(psoc, pdev, &dir);
 		wlan_objmgr_pdev_release_ref(pdev, dbg_id);
+		reg_reset_reg_rules(reg_rules);
 	}
 
 	return QDF_STATUS_SUCCESS;
@@ -3277,6 +3343,7 @@ QDF_STATUS wlan_regulatory_pdev_obj_created_notification(
 	uint32_t range_2g_low, range_2g_high;
 	uint32_t range_5g_low, range_5g_high;
 	QDF_STATUS status;
+	struct reg_rule_info *psoc_reg_rules;
 
 	pdev_priv_obj = qdf_mem_malloc(sizeof(*pdev_priv_obj));
 	if (NULL == pdev_priv_obj) {
@@ -3343,6 +3410,11 @@ QDF_STATUS wlan_regulatory_pdev_obj_created_notification(
 
 	reg_compute_pdev_current_chan_list(pdev_priv_obj);
 
+	psoc_reg_rules = &psoc_priv_obj->mas_chan_params[pdev_id].reg_rules;
+	reg_save_reg_rules_to_pdev(psoc_reg_rules, pdev_priv_obj);
+
+	reg_reset_reg_rules(psoc_reg_rules);
+
 	status = wlan_objmgr_pdev_component_obj_attach(pdev,
 						     WLAN_UMAC_COMP_REGULATORY,
 						     pdev_priv_obj,
@@ -3377,6 +3449,7 @@ QDF_STATUS wlan_regulatory_pdev_obj_destroyed_notification(
 
 	reg_debug("reg pdev obj deleted with status %d", status);
 
+	reg_reset_reg_rules(&pdev_priv_obj->reg_rules);
 	qdf_mem_free(pdev_priv_obj);
 
 	return status;
@@ -3900,6 +3973,24 @@ QDF_STATUS reg_program_default_cc(struct wlan_objmgr_pdev *pdev,
 	return QDF_STATUS_SUCCESS;
 }
 
+struct reg_rule_info *reg_get_regd_rules(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
+
+	if (!pdev) {
+		reg_err("pdev is NULL");
+		return NULL;
+	}
+	pdev_priv_obj = reg_get_pdev_obj(pdev);
+
+	if (!pdev_priv_obj) {
+		reg_err("pdev priv obj is NULL");
+		return NULL;
+	}
+
+	return &pdev_priv_obj->reg_rules;
+}
+
 QDF_STATUS reg_program_chan_list(struct wlan_objmgr_pdev *pdev,
 				 struct cc_regdmn_s *rd)
 {

+ 16 - 0
umac/regulatory/core/src/reg_services.h

@@ -344,6 +344,22 @@ void reg_program_mas_chan_list(struct wlan_objmgr_psoc *psoc,
 			       uint8_t *alpha2,
 			       enum dfs_reg dfs_region);
 
+/**
+ * reg_get_regd_rules() - provides the reg domain rules info
+ * @pdev: pdev pointer
+ *
+ * Return: reg_rule_info pointer
+ */
+struct reg_rule_info *reg_get_regd_rules(struct wlan_objmgr_pdev *pdev);
+
+/**
+ * reg_reset_reg_rules() - provides the reg domain rules info
+ * @reg_rules: reg rules pointer
+ *
+ * Return: None
+ */
+void reg_reset_reg_rules(struct reg_rule_info *reg_rules);
+
 QDF_STATUS reg_program_default_cc(struct wlan_objmgr_pdev *pdev,
 				  uint16_t regdmn);
 

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

@@ -735,6 +735,20 @@ struct cur_regulatory_info {
 	struct cur_reg_rule *reg_rules_5g_ptr;
 };
 
+/**
+ * struct reg_rule_info
+ * @alpha2: alpha2 of reg rules
+ * @dfs_region: dfs region
+ * @num_of_reg_rules: number of reg rules
+ * @reg_rules_ptr: regulatory rules pointer
+ */
+struct reg_rule_info {
+	uint8_t alpha2[REG_ALPHA2_LEN + 1];
+	enum dfs_reg dfs_region;
+	uint8_t num_of_reg_rules;
+	struct cur_reg_rule *reg_rules_ptr;
+};
+
 /**
  * enum band_info
  * @BAND_ALL:all bands
@@ -828,6 +842,7 @@ enum direction {
  * @def_country_code: default country code
  * @reg_dmn_pair: reg domain pair
  * @ctry_code: country code
+ * @reg_rules: regulatory rules
  */
 struct mas_chan_params {
 	enum dfs_reg dfs_region;
@@ -839,6 +854,7 @@ struct mas_chan_params {
 	uint16_t def_country_code;
 	uint16_t reg_dmn_pair;
 	uint16_t ctry_code;
+	struct reg_rule_info reg_rules;
 };
 
 /**

+ 8 - 0
umac/regulatory/dispatcher/inc/wlan_reg_ucfg_api.h

@@ -219,6 +219,14 @@ void ucfg_reg_program_mas_chan_list(struct wlan_objmgr_psoc *psoc,
 				    uint8_t *alpha2,
 				    enum dfs_reg dfs_region);
 
+/**
+ * ucfg_reg_get_regd_rules() - provides the reg domain rules info pointer
+ * @pdev: pdev ptr
+ *
+ * Return: reg_rule_info pointer
+ */
+struct reg_rule_info *ucfg_reg_get_regd_rules(struct wlan_objmgr_pdev *pdev);
+
 /**
  * ucfg_reg_register_chan_change_callback () - add chan change cbk
  * @psoc: psoc ptr

+ 11 - 0
umac/regulatory/dispatcher/src/wlan_reg_services_api.c

@@ -377,6 +377,8 @@ QDF_STATUS regulatory_psoc_open(struct wlan_objmgr_psoc *psoc)
 QDF_STATUS regulatory_psoc_close(struct wlan_objmgr_psoc *psoc)
 {
 	struct wlan_lmac_if_reg_tx_ops *tx_ops;
+	struct wlan_regulatory_psoc_priv_obj *soc_reg;
+	uint8_t i;
 
 	tx_ops = reg_get_psoc_tx_ops(psoc);
 	if (tx_ops->unregister_11d_new_cc_handler)
@@ -386,6 +388,15 @@ QDF_STATUS regulatory_psoc_close(struct wlan_objmgr_psoc *psoc)
 	if (tx_ops->unregister_ch_avoid_event_handler)
 		tx_ops->unregister_ch_avoid_event_handler(psoc, NULL);
 
+	soc_reg = reg_get_psoc_obj(psoc);
+
+	if (!soc_reg) {
+		reg_err("reg psoc private obj is NULL");
+		return QDF_STATUS_E_FAULT;
+	}
+	for (i = 0; i < PSOC_MAX_PHY_REG_CAP; i++)
+		reg_reset_reg_rules(&soc_reg->mas_chan_params[i].reg_rules);
+
 	return QDF_STATUS_SUCCESS;
 }
 

+ 5 - 0
umac/regulatory/dispatcher/src/wlan_reg_ucfg_api.c

@@ -82,6 +82,11 @@ void ucfg_reg_program_mas_chan_list(struct wlan_objmgr_psoc *psoc,
 	reg_program_mas_chan_list(psoc, reg_channels, alpha2, dfs_region);
 }
 
+struct reg_rule_info *ucfg_reg_get_regd_rules(struct wlan_objmgr_pdev *pdev)
+{
+	return reg_get_regd_rules(pdev);
+}
+
 QDF_STATUS ucfg_reg_program_default_cc(struct wlan_objmgr_pdev *pdev,
 				       uint16_t regdmn)
 {