Prechádzať zdrojové kódy

qcacmn: Filter sched_scan channels when DNBS set

Filter channels passed to firmware for scheduled/offloaded scans,
when Do_Not_Break_Stream is set.

Change-Id: I36d434b9f7c25ff7de5ccb4d20a2ae41b2712662
CRs-Fixed: 2064380
Ajit Pal Singh 7 rokov pred
rodič
commit
890fc8d420
1 zmenil súbory, kde vykonal 65 pridanie a 4 odobranie
  1. 65 4
      os_if/linux/scan/src/wlan_cfg80211_scan.c

+ 65 - 4
os_if/linux/scan/src/wlan_cfg80211_scan.c

@@ -179,6 +179,49 @@ static QDF_STATUS wlan_cfg80211_is_pno_allowed(struct wlan_objmgr_vdev *vdev)
 		return QDF_STATUS_E_FAILURE;
 }
 
+#ifdef WLAN_POLICY_MGR_ENABLE
+static bool wlan_cfg80211_is_ap_go_present(struct wlan_objmgr_psoc *psoc)
+{
+	return policy_mgr_mode_specific_connection_count(psoc,
+							  QDF_SAP_MODE,
+							  NULL) ||
+		policy_mgr_mode_specific_connection_count(psoc,
+							  QDF_P2P_GO_MODE,
+							  NULL);
+}
+
+static QDF_STATUS wlan_cfg80211_is_chan_ok_for_dnbs(
+			struct wlan_objmgr_psoc *psoc,
+			u8 channel, bool *ok)
+{
+	QDF_STATUS status = policy_mgr_is_chan_ok_for_dnbs(psoc, channel, ok);
+
+	if (QDF_IS_STATUS_ERROR(status)) {
+		cfg80211_err("DNBS check failed");
+		return status;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+#else
+static bool wlan_cfg80211_is_ap_go_present(struct wlan_objmgr_psoc *psoc)
+{
+	return false;
+}
+
+static QDF_STATUS wlan_cfg80211_is_chan_ok_for_dnbs(
+			struct wlan_objmgr_psoc *psoc,
+			u8 channel,
+			bool *ok)
+{
+	if (!ok)
+		return QDF_STATUS_E_INVAL;
+
+	*ok = true;
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
 int wlan_cfg80211_sched_scan_start(struct wlan_objmgr_pdev *pdev,
 	struct net_device *dev,
 	struct cfg80211_sched_scan_request *request,
@@ -231,6 +274,10 @@ int wlan_cfg80211_sched_scan_start(struct wlan_objmgr_pdev *pdev,
 		return -ENOMEM;
 	}
 
+	wlan_pdev_obj_lock(pdev);
+	psoc = wlan_pdev_get_psoc(pdev);
+	wlan_pdev_obj_unlock(pdev);
+
 	req->networks_cnt = request->n_match_sets;
 	wlan_vdev_obj_lock(vdev);
 	req->vdev_id = wlan_vdev_get_id(vdev);
@@ -254,11 +301,29 @@ int wlan_cfg80211_sched_scan_start(struct wlan_objmgr_pdev *pdev,
 	if (request->n_channels) {
 		char chl[(request->n_channels * 5) + 1];
 		int len = 0;
+		bool ap_or_go_present = wlan_cfg80211_is_ap_go_present(psoc);
 
 		for (i = 0; i < request->n_channels; i++) {
 			channel = request->channels[i]->hw_value;
 			if (wlan_is_dsrc_channel(wlan_chan_to_freq(channel)))
 				continue;
+
+			if (ap_or_go_present) {
+				bool ok;
+
+				status =
+				wlan_cfg80211_is_chan_ok_for_dnbs(psoc,
+								  channel,
+								  &ok);
+				if (QDF_IS_STATUS_ERROR(status)) {
+					cfg80211_err("DNBS check failed");
+					qdf_mem_free(req);
+					ret = -EINVAL;
+					goto error;
+				}
+				if (!ok)
+					continue;
+			}
 			len += snprintf(chl + len, 5, "%d ", channel);
 			valid_ch[num_chan++] = wlan_chan_to_freq(channel);
 		}
@@ -348,9 +413,6 @@ int wlan_cfg80211_sched_scan_start(struct wlan_objmgr_pdev *pdev,
 		req->fast_scan_period, req->fast_scan_max_cycles,
 		req->slow_scan_period);
 
-	wlan_pdev_obj_lock(pdev);
-	psoc = wlan_pdev_get_psoc(pdev);
-	wlan_pdev_obj_unlock(pdev);
 	ucfg_scan_register_pno_cb(psoc,
 		wlan_cfg80211_pno_callback, NULL);
 	ucfg_scan_get_pno_def_params(vdev, req);
@@ -1061,7 +1123,6 @@ int wlan_cfg80211_scan(struct wlan_objmgr_pdev *pdev,
 					continue;
 			}
 #endif
-
 			len += snprintf(chl + len, 5, "%d ", channel);
 			req->scan_req.chan_list[num_chan] =
 				wlan_chan_to_freq(channel);