Browse Source

qcacmn: Add support for PNO scan in connected state

qcacld-2.0 to qcacmn propagation

Add changes to support PNO scan in connected state to find better Ap's
based on rssi threshold, band and rssi preference.

Change-Id: I0744297cc5269f0fe37613247c911102e293d8e9
CRs-Fixed: 2000342
Sreelakshmi Konamki 7 years ago
parent
commit
77dd1efb64

+ 31 - 38
os_if/linux/scan/src/wlan_cfg80211_scan.c

@@ -234,37 +234,6 @@ static void wlan_cfg80211_pno_callback(struct wlan_objmgr_vdev *vdev,
 	cfg80211_sched_scan_results(pdev_ospriv->wiphy);
 }
 
-/**
- * wlan_cfg80211_is_pno_allowed() -  Check if PNO is allowed
- * @vdev: vdev ptr
- *
- * The PNO Start request is coming from upper layers.
- * It is to be allowed only for Infra STA device type
- * and the link should be in a disconnected state.
- *
- * Return: Success if PNO is allowed, Failure otherwise.
- */
-static QDF_STATUS wlan_cfg80211_is_pno_allowed(struct wlan_objmgr_vdev *vdev)
-{
-	enum wlan_vdev_state state;
-	enum tQDF_ADAPTER_MODE vdev_opmode;
-	uint8_t vdev_id;
-
-	vdev_opmode = wlan_vdev_mlme_get_opmode(vdev);
-	state = wlan_vdev_mlme_get_state(vdev);
-	vdev_id = wlan_vdev_get_id(vdev);
-
-	cfg80211_notice("dev_mode=%d, state=%d vdev id %d",
-		vdev_opmode, state, vdev_id);
-
-	if ((vdev_opmode == QDF_STA_MODE) &&
-	   ((state == WLAN_VDEV_S_INIT) ||
-	   (state == WLAN_VDEV_S_STOP)))
-		return QDF_STATUS_SUCCESS;
-	else
-		return QDF_STATUS_E_FAILURE;
-}
-
 #ifdef WLAN_POLICY_MGR_ENABLE
 static bool wlan_cfg80211_is_ap_go_present(struct wlan_objmgr_psoc *psoc)
 {
@@ -354,6 +323,36 @@ static void wlan_pno_scan_rand_attr(struct wlan_objmgr_vdev *vdev,
 }
 #endif
 
+/**
+ * wlan_hdd_sched_scan_update_relative_rssi() - update CPNO params
+ * @pno_request: pointer to PNO scan request
+ * @request: Pointer to cfg80211 scheduled scan start request
+ *
+ * This function is used to update Connected PNO params sent by kernel
+ *
+ * Return: None
+ */
+#if defined(CFG80211_REPORT_BETTER_BSS_IN_SCHED_SCAN)
+static inline void wlan_hdd_sched_scan_update_relative_rssi(
+			struct pno_scan_req_params *pno_request,
+			struct cfg80211_sched_scan_request *request)
+{
+	pno_request->relative_rssi_set = request->relative_rssi_set;
+	pno_request->relative_rssi = request->relative_rssi;
+	if (NL80211_BAND_2GHZ == request->rssi_adjust.band)
+		pno_request->band_rssi_pref.band = WLAN_BAND_2_4_GHZ;
+	else if (NL80211_BAND_5GHZ == request->rssi_adjust.band)
+		pno_request->band_rssi_pref.band = WLAN_BAND_5_GHZ;
+	pno_request->band_rssi_pref.rssi = request->rssi_adjust.delta;
+}
+#else
+static inline void wlan_hdd_sched_scan_update_relative_rssi(
+			struct pno_scan_req_params *pno_request,
+			struct cfg80211_sched_scan_request *request)
+{
+}
+#endif
+
 int wlan_cfg80211_sched_scan_start(struct wlan_objmgr_pdev *pdev,
 	struct net_device *dev,
 	struct cfg80211_sched_scan_request *request,
@@ -374,13 +373,6 @@ int wlan_cfg80211_sched_scan_start(struct wlan_objmgr_pdev *pdev,
 		return -EIO;
 	}
 
-	status = wlan_cfg80211_is_pno_allowed(vdev);
-	if (QDF_IS_STATUS_ERROR(status)) {
-		cfg80211_err("pno is not allowed");
-		wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID);
-		return -ENOTSUPP;
-	}
-
 	if (ucfg_scan_get_pno_in_progress(vdev)) {
 		cfg80211_debug("pno is already in progress");
 		wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID);
@@ -544,6 +536,7 @@ int wlan_cfg80211_sched_scan_start(struct wlan_objmgr_pdev *pdev,
 	cfg80211_notice("Base scan interval: %d sec, scan cycles: %d, slow scan interval %d",
 		req->fast_scan_period, req->fast_scan_max_cycles,
 		req->slow_scan_period);
+	wlan_hdd_sched_scan_update_relative_rssi(req, request);
 
 	psoc = wlan_pdev_get_psoc(pdev);
 	ucfg_scan_register_pno_cb(psoc,

+ 18 - 0
umac/scan/dispatcher/inc/wlan_scan_public_structs.h

@@ -916,6 +916,17 @@ struct pno_nw_type {
 	int32_t rssi_thresh;
 };
 
+/**
+ * struct connected_pno_band_rssi_pref - BSS preference based on band
+ * and RSSI
+ * @band: band preference
+ * @rssi_pref: RSSI preference
+ */
+struct cpno_band_rssi_pref {
+	int8_t band;
+	int8_t rssi;
+};
+
 /**
  * struct pno_scan_req_params - PNO Scan request structure
  * @networks_cnt: Number of networks
@@ -937,6 +948,10 @@ struct pno_nw_type {
  * @networks_list: Preferred network list
  * @scan_random: scan randomization params
  * @ie_whitelist: probe req IE whitelist attrs
+ * @relative_rssi_set: Flag to check whether realtive_rssi is set or not
+ * @relative_rssi: Relative rssi threshold, used for connected pno
+ * @band_rssi_pref: Band and RSSI preference that can be given to one BSS
+ *     over the other BSS
  *
  * E.g.
  *	{ fast_scan_period=120, fast_scan_max_cycles=2,
@@ -961,6 +976,9 @@ struct pno_scan_req_params {
 	struct pno_nw_type networks_list[SCAN_PNO_MAX_SUPP_NETWORKS];
 	struct scan_random_attr scan_random;
 	struct probe_req_whitelist_attr ie_whitelist;
+	bool relative_rssi_set;
+	int8_t relative_rssi;
+	struct cpno_band_rssi_pref band_rssi_pref;
 };
 
 /**

+ 48 - 1
wmi/src/wmi_unified_tlv.c

@@ -7465,16 +7465,19 @@ static QDF_STATUS send_pno_start_cmd_tlv(wmi_unified_t wmi_handle,
 	uint8_t i;
 	int ret;
 	struct probe_req_whitelist_attr *ie_whitelist = &pno->ie_whitelist;
+	connected_nlo_rssi_params *nlo_relative_rssi;
+	connected_nlo_bss_band_rssi_pref *nlo_band_rssi;
 
 	/*
 	 * TLV place holder for array nlo_configured_parameters(nlo_list)
 	 * TLV place holder for array of uint32_t channel_list
 	 * TLV place holder for chnnl prediction cfg
 	 * TLV place holder for array of wmi_vendor_oui
+	 * TLV place holder for array of connected_nlo_bss_band_rssi_pref
 	 */
 	len = sizeof(*cmd) +
 		WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE +
-		WMI_TLV_HDR_SIZE;
+		WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE;
 
 	len += sizeof(uint32_t) * QDF_MIN(pno->networks_list[0].channel_cnt,
 					  WMI_NLO_MAX_CHAN);
@@ -7483,6 +7486,8 @@ static QDF_STATUS send_pno_start_cmd_tlv(wmi_unified_t wmi_handle,
 	len += sizeof(nlo_channel_prediction_cfg);
 	len += sizeof(enlo_candidate_score_params);
 	len += sizeof(wmi_vendor_oui) * ie_whitelist->num_vendor_oui;
+	len += sizeof(connected_nlo_rssi_params);
+	len += sizeof(connected_nlo_bss_band_rssi_pref);
 
 	buf = wmi_buf_alloc(wmi_handle, len);
 	if (!buf) {
@@ -7621,6 +7626,48 @@ static QDF_STATUS send_pno_start_cmd_tlv(wmi_unified_t wmi_handle,
 		buf_ptr += cmd->num_vendor_oui * sizeof(wmi_vendor_oui);
 	}
 
+	if (pno->relative_rssi_set)
+		cmd->flags |= WMI_NLO_CONFIG_ENABLE_CNLO_RSSI_CONFIG;
+
+	/*
+	 * Firmware calculation using connected PNO params:
+	 * New AP's RSSI >= (Connected AP's RSSI + relative_rssi +/- rssi_pref)
+	 * deduction of rssi_pref for chosen band_pref and
+	 * addition of rssi_pref for remaining bands (other than chosen band).
+	 */
+	nlo_relative_rssi = (connected_nlo_rssi_params *) buf_ptr;
+	WMITLV_SET_HDR(&nlo_relative_rssi->tlv_header,
+		WMITLV_TAG_STRUC_wmi_connected_nlo_rssi_params,
+		WMITLV_GET_STRUCT_TLVLEN(connected_nlo_rssi_params));
+	nlo_relative_rssi->relative_rssi = pno->relative_rssi;
+	WMI_LOGD("relative_rssi %d", nlo_relative_rssi->relative_rssi);
+	buf_ptr += sizeof(*nlo_relative_rssi);
+
+	/*
+	 * As of now Kernel and Host supports one band and rssi preference.
+	 * Firmware supports array of band and rssi preferences
+	 */
+	cmd->num_cnlo_band_pref = 1;
+	WMITLV_SET_HDR(buf_ptr,
+		WMITLV_TAG_ARRAY_STRUC,
+		cmd->num_cnlo_band_pref *
+		sizeof(connected_nlo_bss_band_rssi_pref));
+	buf_ptr += WMI_TLV_HDR_SIZE;
+
+	nlo_band_rssi = (connected_nlo_bss_band_rssi_pref *) buf_ptr;
+	for (i = 0; i < cmd->num_cnlo_band_pref; i++) {
+		WMITLV_SET_HDR(&nlo_band_rssi[i].tlv_header,
+			WMITLV_TAG_STRUC_wmi_connected_nlo_bss_band_rssi_pref,
+			WMITLV_GET_STRUCT_TLVLEN(
+				connected_nlo_bss_band_rssi_pref));
+		nlo_band_rssi[i].band = pno->band_rssi_pref.band;
+		nlo_band_rssi[i].rssi_pref = pno->band_rssi_pref.rssi;
+		WMI_LOGI("band_pref %d, rssi_pref %d",
+			nlo_band_rssi[i].band,
+			nlo_band_rssi[i].rssi_pref);
+	}
+	buf_ptr += cmd->num_cnlo_band_pref * sizeof(*nlo_band_rssi);
+
 	ret = wmi_unified_cmd_send(wmi_handle, buf, len,
 				   WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
 	if (ret) {