Jelajahi Sumber

qcacld-3.0: Add APIs to validate vendor ACS channel

If channel set is coming from external application, it could be
possible that it doesn't fall into valid channel criteria.

Add APIs to validate the channel.

Change-Id: I1aa855b64c7702418471111d59c92ebaebe8be49
CRs-Fixed: 1110061
Kapil Gupta 8 tahun lalu
induk
melakukan
94ca6f67f6

+ 15 - 3
core/hdd/inc/wlan_hdd_main.h

@@ -2059,9 +2059,6 @@ int hdd_enable_disable_ca_event(hdd_context_t *hddctx,
 				uint8_t set_value);
 void wlan_hdd_undo_acs(hdd_adapter_t *adapter);
 
-int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
-			uint32_t channel_count,
-			uint8_t *channel_list);
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0))
 static inline int
 hdd_wlan_nla_put_u64(struct sk_buff *skb, int attrtype, u64 value)
@@ -2087,4 +2084,19 @@ static inline int wlan_hdd_validate_session_id(u8 session_id)
 bool hdd_is_roaming_in_progress(void);
 void hdd_set_roaming_in_progress(bool value);
 
+/**
+ * wlan_hdd_sap_get_valid_channellist() - Get SAPs valid channel list
+ * @ap_adapter: adapter
+ * @channel_count: valid channel count
+ * @channel_list: valid channel list
+ *
+ * This API returns valid channel list for SAP after removing nol and
+ * channel which lies outside of configuration.
+ *
+ * Return: Zero on success, non-zero on failure
+ */
+int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
+				       uint32_t *channel_count,
+				       uint8_t *channel_list);
+
 #endif /* end #if !defined(WLAN_HDD_MAIN_H) */

+ 127 - 13
core/hdd/src/wlan_hdd_cfg80211.c

@@ -1389,6 +1389,29 @@ static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
 	return 0;
 }
 
+/**
+ * wlan_hdd_sap_get_nol() - Get SAPs NOL
+ * @ap_adapter: AP adapter
+ * @nol: Non-occupancy list
+ * @nol_len: Length of NOL
+ *
+ * Get the NOL for SAP
+ *
+ * Return: Zero on success, non-zero on failure
+ */
+static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
+				uint32_t *nol_len)
+{
+	QDF_STATUS ret;
+
+	ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
+				nol, nol_len);
+	if (QDF_IS_STATUS_ERROR(ret))
+		return -EINVAL;
+
+	return 0;
+}
+
 /**
  * hdd_update_reg_chan_info : This API contructs channel info
  * for all the given channel
@@ -6927,24 +6950,83 @@ static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
 }
 
 /**
- * wlan_hdd_sap_get_nol() - Get SAPs NOL
- * @ap_adapter: AP adapter
- * @nol: Non-occupancy list
- * @nol_len: Length of NOL
- *
- * Get the NOL for SAP
+ * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
+ * are in nol list from provided channel list
+ * @adapter: AP adapter
+ * @channel_count: channel count
+ * @channel_list: channel list
  *
- * Return: Zero on success, non-zero on failure
+ * Return: None
  */
-static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
-				uint32_t *nol_len)
+static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
+				      uint32_t *channel_count,
+				      uint8_t *channel_list)
 {
-	QDF_STATUS ret;
+	uint8_t i, j;
+	uint32_t nol_len = 0;
+	uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
+	uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
+	uint32_t chan_count;
+	bool found;
+	hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
 
-	ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
-				nol, nol_len);
-	if (QDF_IS_STATUS_ERROR(ret))
+	if (!hdd_ctx) {
+		hdd_err("hdd ctx not found");
+		*channel_count = 0;
+		return;
+	}
+
+	if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
+		hdd_err("invalid channel count %d", *channel_count);
+		return;
+	}
+
+	wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
+	if (nol_len == 0)
+		return;
+
+	qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
+	chan_count = *channel_count;
+	qdf_mem_zero(channel_list, chan_count);
+	*channel_count = 0;
+
+	for (i = 0 ; i < chan_count; i++) {
+		if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
+		    (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
+			continue;
+		found = false;
+		for (j = 0; j < nol_len; j++) {
+			if (tmp_chan_list[i] == nol[j]) {
+				found = true;
+				hdd_notice("skipped channel %d due to nol",
+						nol[j]);
+				break;
+			}
+		}
+		if (!found) {
+			channel_list[*channel_count] = tmp_chan_list[i];
+			*channel_count = *channel_count + 1;
+		}
+	}
+}
+
+int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
+				       uint32_t *channel_count,
+				       uint8_t *channel_list)
+{
+	tsap_Config_t *sap_config;
+
+	sap_config = &adapter->sessionCtx.ap.sapConfig;
+
+	qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
+		     sap_config->acs_cfg.ch_list_count);
+	*channel_count = sap_config->acs_cfg.ch_list_count;
+	wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
+
+	if (*channel_count == 0) {
+		hdd_err("no valid channel found");
 		return -EINVAL;
+	}
 
 	return 0;
 }
@@ -8188,6 +8270,38 @@ static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
 	return ret;
 }
 
+/**
+ *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
+ * @adapter: hdd adapter
+ * @channel: channel number
+ *
+ * return: QDF status based on success or failure
+ */
+static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
+						int channel, int chan_bw)
+{
+	if (QDF_STATUS_SUCCESS !=
+	    wlan_hdd_validate_operation_channel(adapter, channel))
+		return QDF_STATUS_E_FAILURE;
+	if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
+				channel,
+				PHY_SINGLE_CHANNEL_CENTERED))) {
+		hdd_notice("channel %d is in nol", channel);
+		return -EINVAL;
+	}
+
+	if ((wlansap_is_channel_leaking_in_nol(
+				WLAN_HDD_GET_SAP_CTX_PTR(adapter),
+				channel, chan_bw))) {
+		hdd_notice("channel %d is leaking in nol", channel);
+		return -EINVAL;
+	}
+
+	return 0;
+
+}
+
+
 /**
  * wlan_hdd_cfg80211_setband() - Wrapper to setband
  * @wiphy:    wiphy structure pointer

+ 23 - 0
core/sap/inc/sap_api.h

@@ -878,6 +878,29 @@ typedef QDF_STATUS (*tpWLAN_SAPEventCB)(tpSap_Event pSapEvent,
 					void *pUsrContext);
 uint8_t wlansap_get_state(void *p_cds_gctx);
 
+/**
+ * wlansap_is_channel_in_nol_list() - This API checks if channel is
+ * in nol list
+ * @ctx: context pointer
+ * @channel: channel
+ * @chanBondState: channel bonding state
+ *
+ * Return: True/False
+ */
+bool wlansap_is_channel_in_nol_list(void *p_cds_gctx, uint8_t channel_no,
+				    ePhyChanBondState chanBondState);
+/**
+ * wlansap_is_channel_leaking_in_nol() - This API checks if channel is leaking
+ * in nol list
+ * @ctx: context pointer
+ * @channel: channel
+ * @chan_bw: channel bandwidth
+ *
+ * Return: True/False
+ */
+bool wlansap_is_channel_leaking_in_nol(void *ctx, uint8_t channel,
+				       uint8_t chan_bw);
+
 QDF_STATUS wlansap_start_bss(void *p_cds_gctx,
 	 tpWLAN_SAPEventCB pSapEventCallback,
 	 tsap_Config_t *pConfig, void *pUsrContext);

+ 1 - 1
core/sap/src/sap_fsm.c

@@ -994,7 +994,7 @@ sap_find_target_channel_in_channel_matrix(ptSapContext sapContext,
  * Return: QDF_STATUS
  */
 
-static QDF_STATUS
+QDF_STATUS
 sap_mark_leaking_ch(ptSapContext sap_ctx,
 		enum phy_ch_width ch_width,
 		tSapDfsNolInfo *nol,

+ 22 - 1
core/sap/src/sap_internal.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -433,6 +433,27 @@ QDF_STATUS sap_open_session(tHalHandle hHal, ptSapContext sapContext,
 QDF_STATUS sap_close_session(tHalHandle hHal,
 			     ptSapContext sapContext,
 			     csr_roamSessionCloseCallback callback, bool valid);
+/**
+ * sap_mark_leaking_ch() - to mark channel leaking in to nol
+ * @sap_ctx: pointer to SAP context
+ * @ch_width: channel width
+ * @nol: nol info
+ * @temp_ch_lst_sz: the target channel list
+ * @temp_ch_lst: the target channel list
+ *
+ * This function removes the channels from temp channel list that
+ * (if selected as target channel) will cause leakage in one of
+ * the NOL channels
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+sap_mark_leaking_ch(ptSapContext sap_ctx,
+		enum phy_ch_width ch_width,
+		tSapDfsNolInfo *nol,
+		uint8_t temp_ch_lst_sz,
+		uint8_t *temp_ch_lst);
+
 #ifdef __cplusplus
 }
 #endif

+ 67 - 0
core/sap/src/sap_module.c

@@ -581,6 +581,73 @@ uint8_t wlansap_get_state(void *pCtx)
 	return pSapCtx->sapsMachine;
 }
 
+bool wlansap_is_channel_in_nol_list(void *p_cds_gctx,
+				    uint8_t channelNumber,
+				    ePhyChanBondState chanBondState)
+{
+	ptSapContext pSapCtx = NULL;
+
+	pSapCtx = CDS_GET_SAP_CB(p_cds_gctx);
+
+	if (!pSapCtx) {
+		QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH,
+			  "%s: Invalid SAP pointer from pCtx", __func__);
+		return QDF_STATUS_E_FAULT;
+	}
+
+	return sap_dfs_is_channel_in_nol_list(pSapCtx, channelNumber,
+					      chanBondState);
+}
+
+#ifdef WLAN_ENABLE_CHNL_MATRIX_RESTRICTION
+static QDF_STATUS wlansap_mark_leaking_channel(ptSapContext sap_ctx,
+		tSapDfsNolInfo *nol,
+		uint8_t *leakage_adjusted_lst,
+		uint8_t chan_bw)
+{
+
+	return sap_mark_leaking_ch(sap_ctx, chan_bw, nol, 1,
+			leakage_adjusted_lst);
+}
+#else
+static QDF_STATUS wlansap_mark_leaking_channel(ptSapContext sap_ctx,
+		tSapDfsNolInfo *nol,
+		uint8_t *leakage_adjusted_lst,
+		uint8_t chan_bw)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
+bool wlansap_is_channel_leaking_in_nol(void *ctx, uint8_t channel,
+		uint8_t chan_bw)
+{
+	ptSapContext sap_ctx = CDS_GET_SAP_CB(ctx);
+	tpAniSirGlobal mac_ctx;
+	uint8_t leakage_adjusted_lst[1];
+	void *handle = NULL;
+	tSapDfsNolInfo *nol;
+
+	leakage_adjusted_lst[0] = channel;
+	handle = CDS_GET_HAL_CB(sapContext->p_cds_gctx);
+	mac_ctx = PMAC_STRUCT(handle);
+	if (!mac_ctx) {
+		QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
+				"%s: Invalid mac pointer", __func__);
+		return QDF_STATUS_E_FAULT;
+	}
+	nol = mac_ctx->sap.SapDfsInfo.sapDfsChannelNolList;
+	QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
+			FL("sapdfs: Processing current chan against NOL."));
+	if (wlansap_mark_leaking_channel(sap_ctx, nol,
+			leakage_adjusted_lst, chan_bw) != QDF_STATUS_SUCCESS) {
+		return true;
+	}
+	if (leakage_adjusted_lst[0] == 0)
+		return true;
+	return false;
+}
+
 #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
 /*==========================================================================
    FUNCTION    wlansap_check_cc_intf