Browse Source

qcacld-3.0: Validate update avoid frequency channel list

qcacld-2.0 to qcacld-3.0 propagation.

Validate the avoid frequency channel list of
QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY command and update the
driver's unsafe channel list with the channels received in the command.

Change-Id: I1a10e668bf6fe6dbb22f7f2f8aef929fc6e7fc65
CRs-Fixed: 2187477
Ashish Kumar Dhanotiya 7 years ago
parent
commit
4be2a7b2a4
2 changed files with 77 additions and 11 deletions
  1. 2 0
      core/cds/inc/cds_utils.h
  2. 75 11
      core/hdd/src/wlan_hdd_cfg80211.c

+ 2 - 0
core/cds/inc/cds_utils.h

@@ -56,10 +56,12 @@
 #define CDS_24_GHZ_BASE_FREQ   (2407)
 #define CDS_5_GHZ_BASE_FREQ    (5000)
 #define CDS_24_GHZ_CHANNEL_6   (6)
+#define CDS_24_GHZ_CHANNEL_1   (1)
 #define CDS_5_GHZ_CHANNEL_36   (36)
 #define CDS_24_GHZ_CHANNEL_14  (14)
 #define CDS_24_GHZ_CHANNEL_15  (15)
 #define CDS_24_GHZ_CHANNEL_27  (27)
+#define CDS_5_GHZ_CHANNEL_165  (165)
 #define CDS_5_GHZ_CHANNEL_170  (170)
 #define CDS_CHAN_SPACING_5MHZ  (5)
 #define CDS_CHAN_SPACING_20MHZ (20)

+ 75 - 11
core/hdd/src/wlan_hdd_cfg80211.c

@@ -10504,6 +10504,56 @@ static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
 }
 
 #ifdef FEATURE_WLAN_CH_AVOID
+
+static int hdd_validate_avoid_freq_chanlist(
+					struct hdd_context *hdd_ctx,
+					struct ch_avoid_ind_type *channel_list)
+{
+	unsigned int range_idx, ch_idx;
+	unsigned int unsafe_channel_index, unsafe_channel_count = 0;
+	bool ch_found = false;
+
+	unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
+				       (uint16_t)NUM_CHANNELS);
+
+	for (range_idx = 0; range_idx < channel_list->ch_avoid_range_cnt;
+					range_idx++) {
+		if ((channel_list->avoid_freq_range[range_idx].start_freq <
+		     CDS_24_GHZ_CHANNEL_1) ||
+		    (channel_list->avoid_freq_range[range_idx].end_freq >
+		     CDS_5_GHZ_CHANNEL_165) ||
+		    (channel_list->avoid_freq_range[range_idx].start_freq >
+		     channel_list->avoid_freq_range[range_idx].end_freq))
+			continue;
+
+		for (ch_idx = channel_list->
+				avoid_freq_range[range_idx].start_freq;
+		     ch_idx <= channel_list->
+					avoid_freq_range[range_idx].end_freq;
+		     ch_idx++) {
+			for (unsafe_channel_index = 0;
+			     unsafe_channel_index < unsafe_channel_count;
+			     unsafe_channel_index++) {
+				if (ch_idx ==
+					hdd_ctx->unsafe_channel_list[
+					unsafe_channel_index]) {
+					hdd_log(QDF_TRACE_LEVEL_INFO,
+						"Duplicate channel %d",
+						ch_idx);
+					ch_found = true;
+					break;
+				}
+			}
+			if (!ch_found) {
+				hdd_ctx->unsafe_channel_list[
+				unsafe_channel_count++] = ch_idx;
+			}
+			ch_found = false;
+		}
+	}
+	return unsafe_channel_count;
+}
+
 /**
  * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
  * is on unsafe channel.
@@ -10526,11 +10576,11 @@ __wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
 {
 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
 	int ret;
-	uint16_t unsafe_channel_count;
-	int unsafe_channel_index;
 	qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
 	uint16_t *local_unsafe_list;
-	uint16_t local_unsafe_list_count;
+	uint16_t unsafe_channel_index, local_unsafe_list_count;
+	struct ch_avoid_ind_type *channel_list;
+	enum tQDF_GLOBAL_CON_MODE curr_mode;
 
 	ENTER_DEV(wdev->netdev);
 
@@ -10538,15 +10588,24 @@ __wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
 		hdd_err("qdf_ctx is NULL");
 		return -EINVAL;
 	}
-
-	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
-		hdd_err("Command not allowed in FTM mode");
+	curr_mode = hdd_get_conparam();
+	if (QDF_GLOBAL_FTM_MODE == curr_mode ||
+	    QDF_GLOBAL_MONITOR_MODE == curr_mode) {
+		hdd_err("Command not allowed in FTM/MONITOR mode");
 		return -EINVAL;
 	}
 
 	ret = wlan_hdd_validate_context(hdd_ctx);
 	if (0 != ret)
 		return ret;
+
+	channel_list = (struct ch_avoid_ind_type *)data;
+	if (!channel_list) {
+		hdd_log(QDF_TRACE_LEVEL_ERROR,
+			"Avoid frequency channel list empty");
+		return -EINVAL;
+	}
+
 	ret = hdd_clone_local_unsafe_chan(hdd_ctx,
 					  &local_unsafe_list,
 					  &local_unsafe_list_count);
@@ -10559,13 +10618,18 @@ __wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
 			&(hdd_ctx->unsafe_channel_count),
 			sizeof(hdd_ctx->unsafe_channel_list));
 
-	unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
-			(uint16_t)NUM_CHANNELS);
+	hdd_ctx->unsafe_channel_count = hdd_validate_avoid_freq_chanlist(
+								hdd_ctx,
+								channel_list);
+
+	pld_set_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
+				    hdd_ctx->unsafe_channel_count);
+
 	for (unsafe_channel_index = 0;
-			unsafe_channel_index < unsafe_channel_count;
-			unsafe_channel_index++) {
+	     unsafe_channel_index < hdd_ctx->unsafe_channel_count;
+	     unsafe_channel_index++) {
 		hdd_debug("Channel %d is not safe",
-			hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
+			  hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
 	}
 	if (hdd_local_unsafe_channel_updated(hdd_ctx, local_unsafe_list,
 					     local_unsafe_list_count))