Эх сурвалжийг харах

qcacmn: Add support to get usable channels for NAN

Fetch usable channels for NAN iface mode from policy manager
or reg current channel list based on filter mask and
Update res msg channel list.

Change-Id: Ifa4ad4c7c8479f4a0ecc7dbe101f6507ff1525dc
CRs-Fixed: 2949340
sheenam monga 4 жил өмнө
parent
commit
ef4a346a73

+ 141 - 40
umac/regulatory/core/src/reg_services_common.c

@@ -35,7 +35,10 @@
 #include "reg_build_chan_list.h"
 #include <wlan_objmgr_pdev_obj.h>
 #include <target_if.h>
+#ifdef WLAN_FEATURE_GET_USABLE_CHAN_LIST
 #include "wlan_mlme_ucfg_api.h"
+#include "wlan_nan_api.h"
+#endif
 
 const struct chan_map *channel_map;
 #ifdef CONFIG_CHAN_NUM_API
@@ -3324,6 +3327,7 @@ is_freq_present_in_resp_list(uint32_t pcl_ch,
  * @pcl_ch: pcl channel
  * @len: calculated pcl len
  * @iface_mode_mask: interface type
+ * @band_mask: requested band mask
  * @count: no of usable channels
  *
  * Return: void
@@ -3332,7 +3336,8 @@ static void
 reg_update_usable_chan_resp(struct wlan_objmgr_pdev *pdev,
 			    struct get_usable_chan_res_params *res_msg,
 			    uint32_t *pcl_ch, uint32_t len,
-			    uint32_t iface_mode_mask, int *count)
+			    uint32_t iface_mode_mask,
+			    uint32_t band_mask, int *count)
 {
 	int i;
 	struct ch_params ch_params = {0};
@@ -3348,6 +3353,10 @@ reg_update_usable_chan_resp(struct wlan_objmgr_pdev *pdev,
 			res_msg[i].iface_mode_mask |= 1 << iface_mode_mask;
 			continue;
 		}
+
+		if (!(band_mask & 1 << wlan_reg_freq_to_band(pcl_ch[i])))
+			continue;
+
 		ch_params.ch_width = CH_WIDTH_MAX;
 		reg_set_channel_params_for_freq(
 				pdev,
@@ -3375,6 +3384,7 @@ reg_update_usable_chan_resp(struct wlan_objmgr_pdev *pdev,
  * @res_msg: Response msg
  * @policy_mgr_con_mode: policy mgr mode
  * @iftype: interface type
+ * @band_mask: requested band mask
  * @count: no of usable channels
  *
  * Return: qdf status
@@ -3384,31 +3394,54 @@ reg_update_conn_chan_list(struct wlan_objmgr_pdev *pdev,
 			  struct get_usable_chan_res_params *res_msg,
 			  enum policy_mgr_con_mode mode,
 			  uint32_t iftype,
+			  uint32_t band_mask,
 			  uint32_t *count)
 {
-	uint32_t pcl_ch[NUM_CHANNELS] = {0};
-	uint8_t weight_list[NUM_CHANNELS] = {0};
+	uint32_t *pcl_ch;
+	uint8_t *weight_list;
 	uint32_t len;
 	uint32_t weight_len;
 	struct wlan_objmgr_psoc *psoc;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
+	pcl_ch = qdf_mem_malloc(NUM_CHANNELS *
+			sizeof(uint32_t));
+
+	if (!pcl_ch) {
+		reg_err("pcl_ch invalid");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	weight_list = qdf_mem_malloc(NUM_CHANNELS *
+			sizeof(uint8_t));
+
+	if (!weight_list) {
+		reg_err("weight_list invalid");
+		qdf_mem_free(pcl_ch);
+		return QDF_STATUS_E_FAILURE;
+	}
+
 	psoc = wlan_pdev_get_psoc(pdev);
 	if (!psoc) {
 		reg_err("invalid psoc");
-		return QDF_STATUS_E_FAILURE;
+		status = QDF_STATUS_E_FAILURE;
+		goto err;
 	}
 
-	len = QDF_ARRAY_SIZE(pcl_ch);
-	weight_len = QDF_ARRAY_SIZE(weight_list);
+	len = NUM_CHANNELS;
+	weight_len = NUM_CHANNELS;
 
 	status = policy_mgr_get_pcl(psoc, mode, pcl_ch, &len,
 				    weight_list, weight_len);
 	if (QDF_IS_STATUS_ERROR(status)) {
 		reg_err("get pcl failed for mode: %d", mode);
-		return status;
+		goto err;
 	}
-	reg_update_usable_chan_resp(pdev, res_msg, pcl_ch, len, iftype, count);
+	reg_update_usable_chan_resp(pdev, res_msg, pcl_ch, len,
+				    iftype, band_mask, count);
+err:
+	qdf_mem_free(pcl_ch);
+	qdf_mem_free(weight_list);
 	return status;
 }
 
@@ -3434,22 +3467,30 @@ reg_get_usable_channel_con_filter(struct wlan_objmgr_pdev *pdev,
 	if (req_msg.iface_mode_mask & 1 << IFTYPE_AP) {
 		status =
 		reg_update_conn_chan_list(pdev, res_msg, PM_SAP_MODE,
-					  IFTYPE_AP, count);
+					  IFTYPE_AP, req_msg.band_mask, count);
 	}
 	if (req_msg.iface_mode_mask & 1 << IFTYPE_STATION) {
 		status =
 		reg_update_conn_chan_list(pdev, res_msg, PM_STA_MODE,
-					  IFTYPE_STATION, count);
+					  IFTYPE_STATION, req_msg.band_mask,
+					  count);
 	}
 	if (req_msg.iface_mode_mask & 1 << IFTYPE_P2P_GO) {
 		status =
 		reg_update_conn_chan_list(pdev, res_msg, PM_P2P_GO_MODE,
-					  IFTYPE_P2P_GO, count);
+					  IFTYPE_P2P_GO, req_msg.band_mask,
+					  count);
 	}
 	if (req_msg.iface_mode_mask & 1 << IFTYPE_P2P_CLIENT) {
 		status =
 		reg_update_conn_chan_list(pdev, res_msg, PM_P2P_CLIENT_MODE,
-					  IFTYPE_P2P_CLIENT, count);
+					  IFTYPE_P2P_CLIENT, req_msg.band_mask,
+					  count);
+	}
+	if (req_msg.iface_mode_mask & 1 << IFTYPE_NAN) {
+		status =
+		reg_update_conn_chan_list(pdev, res_msg, PM_NAN_DISC_MODE,
+					  IFTYPE_NAN, req_msg.band_mask, count);
 	}
 	return status;
 }
@@ -3471,7 +3512,8 @@ reg_remove_freq(struct get_usable_chan_res_params *res_msg,
 }
 
 /**
- * reg_skip_invalid_chan_for_sap_p2p_go() - Remove invalid freq for SAP & P2PGO
+ * reg_skip_invalid_chan_freq() - Remove invalid freq for SAP, P2P GO
+ *				  and NAN
  * @pdev: Pointer to pdev
  * @res_msg: Response msg
  * @count: no of usable channels
@@ -3480,17 +3522,16 @@ reg_remove_freq(struct get_usable_chan_res_params *res_msg,
  * Return: qdf status
  */
 static QDF_STATUS
-reg_skip_invalid_chan_for_sap_p2p_go(struct wlan_objmgr_pdev *pdev,
-				     struct get_usable_chan_res_params *res_msg,
-				     uint32_t *no_usable_channels,
-				     uint32_t iface_mode_mask)
+reg_skip_invalid_chan_freq(struct wlan_objmgr_pdev *pdev,
+			   struct get_usable_chan_res_params *res_msg,
+			   uint32_t *no_usable_channels,
+			   uint32_t iface_mode_mask)
 {
 	uint32_t chan_enum, iface_mode = 0;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 	bool include_indoor_channel;
 	uint8_t enable_srd_chan, srd_mask = 0;
 	struct wlan_objmgr_psoc *psoc;
-
 	psoc = wlan_pdev_get_psoc(pdev);
 	if (!psoc) {
 		reg_err("invalid psoc");
@@ -3518,27 +3559,42 @@ reg_skip_invalid_chan_for_sap_p2p_go(struct wlan_objmgr_pdev *pdev,
 		} else if (iface_mode_mask & (1 << IFTYPE_P2P_GO)) {
 			srd_mask = 2;
 			iface_mode = 1 << IFTYPE_P2P_GO;
+		} else if (iface_mode_mask & (1 << IFTYPE_NAN)) {
+			iface_mode = 1 << IFTYPE_NAN;
 		} else {
 			break;
 		}
 		for (chan_enum = 0; chan_enum < *no_usable_channels;
 		     chan_enum++) {
-			if (wlan_reg_is_freq_indoor(
-					pdev, res_msg[chan_enum].freq) &&
-					!include_indoor_channel) {
-				res_msg[chan_enum].iface_mode_mask &=
+			if (iface_mode_mask & (1 << IFTYPE_NAN)) {
+				if (res_msg[chan_enum].state ==
+				    CHANNEL_STATE_DISABLE ||
+				    !wlan_is_nan_allowed_on_freq(pdev,
+				    res_msg[chan_enum].freq))
+					res_msg[chan_enum].iface_mode_mask &=
 						~(iface_mode);
 				if (!res_msg[chan_enum].iface_mode_mask)
 					reg_remove_freq(res_msg, chan_enum);
-			}
-
-			if (!(enable_srd_chan & srd_mask) &&
-			    reg_is_etsi13_srd_chan(
+			} else {
+				if (wlan_reg_is_freq_indoor(
+					pdev, res_msg[chan_enum].freq) &&
+					!include_indoor_channel) {
+					res_msg[chan_enum].iface_mode_mask &=
+							~(iface_mode);
+					if (!res_msg[chan_enum].iface_mode_mask)
+						reg_remove_freq(res_msg,
+								chan_enum);
+				}
+
+				if (!(enable_srd_chan & srd_mask) &&
+				    reg_is_etsi13_srd_chan_for_freq(
 					pdev, res_msg[chan_enum].freq)) {
-				res_msg[chan_enum].iface_mode_mask &=
-					~(iface_mode);
-				if (!res_msg[chan_enum].iface_mode_mask)
-					reg_remove_freq(res_msg, chan_enum);
+					res_msg[chan_enum].iface_mode_mask &=
+						~(iface_mode);
+					if (!res_msg[chan_enum].iface_mode_mask)
+						reg_remove_freq(res_msg,
+								chan_enum);
+				}
 			}
 		}
 
@@ -3568,8 +3624,8 @@ reg_get_usable_channel_no_filter(struct wlan_objmgr_pdev *pdev,
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
 	status =
-	reg_skip_invalid_chan_for_sap_p2p_go(pdev, res_msg,
-					     count, req_msg.iface_mode_mask);
+	reg_skip_invalid_chan_freq(pdev, res_msg,
+				   count, req_msg.iface_mode_mask);
 	return status;
 }
 
@@ -3624,13 +3680,35 @@ reg_get_usable_channel_coex_filter(struct wlan_objmgr_pdev *pdev,
 		index++;
 	}
 	if (req_msg.iface_mode_mask & 1 << IFTYPE_AP ||
-	    req_msg.iface_mode_mask & 1 << IFTYPE_P2P_GO)
+	    req_msg.iface_mode_mask & 1 << IFTYPE_P2P_GO ||
+	    req_msg.iface_mode_mask & 1 << IFTYPE_NAN)
 		status =
-		reg_skip_invalid_chan_for_sap_p2p_go(pdev, res_msg, count,
-						     req_msg.iface_mode_mask);
+		reg_skip_invalid_chan_freq(pdev, res_msg, count,
+					   req_msg.iface_mode_mask);
 	return status;
 }
 
+/**
+ * reg_calculate_mode_mask() - calculate valid mode mask
+ * @iface_mode_mask: interface mode mask
+ *
+ * Return: Valid mode mask
+ */
+static uint32_t
+reg_calculate_mode_mask(uint32_t iface_mode_mask)
+{
+	int mode_mask = 0;
+
+	mode_mask = (iface_mode_mask & 1 << IFTYPE_STATION) |
+		    (iface_mode_mask & 1 << IFTYPE_AP) |
+		    (iface_mode_mask & 1 << IFTYPE_P2P_GO) |
+		    (iface_mode_mask & 1 << IFTYPE_P2P_CLIENT) |
+		    (iface_mode_mask & 1 << IFTYPE_P2P_DEVICE) |
+		    (iface_mode_mask & 1 << IFTYPE_NAN);
+
+	return mode_mask;
+}
+
 /**
  * reg_add_usable_channel_to_resp() - Add usable channels to resp structure
  * @pdev: Pointer to pdev
@@ -3639,9 +3717,9 @@ reg_get_usable_channel_coex_filter(struct wlan_objmgr_pdev *pdev,
  * @chan_list: reg channel list
  * @count: no of usable channels
  *
- * Return: void
+ * Return: qdf status
  */
-static void
+static QDF_STATUS
 reg_add_usable_channel_to_resp(struct wlan_objmgr_pdev *pdev,
 			       struct get_usable_chan_res_params *res_msg,
 			       uint32_t iface_mode_mask,
@@ -3650,6 +3728,7 @@ reg_add_usable_channel_to_resp(struct wlan_objmgr_pdev *pdev,
 {
 	enum channel_enum chan_enum;
 	struct ch_params ch_params = {0};
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
 	for (chan_enum = 0; chan_enum < *count; chan_enum++) {
 		ch_params.ch_width = CH_WIDTH_MAX;
@@ -3659,8 +3738,14 @@ reg_add_usable_channel_to_resp(struct wlan_objmgr_pdev *pdev,
 				chan_list[chan_enum].max_bw, &ch_params);
 
 		res_msg[chan_enum].freq = chan_list[chan_enum].center_freq;
-		res_msg[chan_enum].iface_mode_mask = iface_mode_mask;
+		res_msg[chan_enum].iface_mode_mask =
+				reg_calculate_mode_mask(iface_mode_mask);
+		if (!res_msg[chan_enum].iface_mode_mask) {
+			reg_err("invalid iface mask");
+			return QDF_STATUS_E_FAILURE;
+		}
 		res_msg[chan_enum].bw = chan_list[chan_enum].max_bw;
+		res_msg[chan_enum].state = chan_list[chan_enum].state;
 		if (ch_params.center_freq_seg0)
 			res_msg[chan_enum].seg0_freq =
 					ch_params.center_freq_seg0;
@@ -3668,6 +3753,8 @@ reg_add_usable_channel_to_resp(struct wlan_objmgr_pdev *pdev,
 			res_msg[chan_enum].seg1_freq =
 					ch_params.center_freq_seg1;
 	}
+
+	return status;
 }
 
 QDF_STATUS
@@ -3676,19 +3763,31 @@ wlan_reg_get_usable_channel(struct wlan_objmgr_pdev *pdev,
 			    struct get_usable_chan_res_params *res_msg,
 			    uint32_t *usable_channels)
 {
-	struct regulatory_channel chan_list[NUM_CHANNELS];
+	struct regulatory_channel *chan_list;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
+	chan_list = qdf_mem_malloc(NUM_CHANNELS *
+			sizeof(*chan_list));
+
+	if (!chan_list) {
+		reg_err("chan_list invalid");
+		return QDF_STATUS_E_FAILURE;
+	}
+
 	if ((req_msg.filter_mask & 1 << FILTER_CELLULAR_COEX) ||
 	    (!(req_msg.filter_mask & 1 << FILTER_CELLULAR_COEX) &&
 	     !(req_msg.filter_mask & 1 << FILTER_WLAN_CONCURRENCY))) {
 		*usable_channels = reg_get_band_channel_list(pdev,
 							     req_msg.band_mask,
 							     chan_list);
-
+		status =
 		reg_add_usable_channel_to_resp(pdev, res_msg,
 					       req_msg.iface_mode_mask,
 					       chan_list, usable_channels);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			qdf_mem_free(chan_list);
+			return status;
+		}
 	}
 
 	if (req_msg.filter_mask & 1 << FILTER_CELLULAR_COEX)
@@ -3706,7 +3805,9 @@ wlan_reg_get_usable_channel(struct wlan_objmgr_pdev *pdev,
 		status =
 		reg_get_usable_channel_no_filter(pdev, req_msg, res_msg,
 						 chan_list, usable_channels);
+	reg_debug("usable chan count is %d", *usable_channels);
 
+	qdf_mem_free(chan_list);
 	return status;
 }
 #endif

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

@@ -822,8 +822,9 @@ enum country_src {
  *      and therefore can't be created in the normal ways, use the
  *      %NL80211_CMD_START_P2P_DEVICE and %NL80211_CMD_STOP_P2P_DEVICE
  *      commands to create and destroy one
- * @NL80211_IF_TYPE_OCB: Outside Context of a BSS
+ * @IF_TYPE_OCB: Outside Context of a BSS
  *      This mode corresponds to the MIB variable dot11OCBActivated=true
+ * @IF_TYPE_NAN: NAN mode
  * @IFTYPE_MAX: highest interface type number currently defined
  * @NUM_IFTYPES: number of defined interface types
  *
@@ -844,6 +845,7 @@ enum iftype {
 	IFTYPE_P2P_GO,
 	IFTYPE_P2P_DEVICE,
 	IFTYPE_OCB,
+	IFTYPE_NAN,
 
 	/* keep last */
 	NUM_IFTYPES,
@@ -866,6 +868,7 @@ enum usable_channels_filter {
  * seg0_freq : seg0 freq
  * seg1_freq: seg1 freq
  * bw : bandwidth
+ * state: channel state
  * iface_mode_mask: interface mode mask
  **/
 struct get_usable_chan_res_params {
@@ -874,6 +877,7 @@ struct get_usable_chan_res_params {
 	uint32_t seg1_freq;
 	uint32_t bw;
 	uint32_t iface_mode_mask;
+	enum channel_state state;
 };
 
 /**