Browse Source

qcacld-3.0: Add candidate validation to the if_mgr

Add the API to validate the BSS before roaming to it. This API will check
if other vdevs are already connected to the BSS, if concurrency is allowed,
and if channel is allowed for the current HW mode.
Keep the new changes under the interface_mgr feature flag.

Change-Id: I280e95b0a30c08fe4037295330628b79d22acf5f
CRs-fixed: 2774543
Lincoln Tran 4 years ago
parent
commit
53f7903389

+ 29 - 0
components/cmn_services/interface_mgr/inc/wlan_if_mgr_roam.h

@@ -25,6 +25,7 @@
 #include "wlan_objmgr_pdev_obj.h"
 #include "wlan_objmgr_vdev_obj.h"
 #include "wlan_policy_mgr_api.h"
+#include "wlan_if_mgr_public_struct.h"
 #include "wlan_if_mgr_roam.h"
 
 /**
@@ -40,6 +41,19 @@ struct change_roam_state_arg {
 	uint8_t curr_vdev_id;
 };
 
+/**
+ * struct bssid_search_arg - Contains candidate validation arguments
+ * @peer_addr: MAC address of the BSS
+ * @vdev_id: virtual device ID
+ *
+ * This structure is used to pass the candidate validation information to the
+ * callback
+ */
+struct bssid_search_arg {
+	struct qdf_mac_addr peer_addr;
+	uint8_t vdev_id;
+};
+
 /**
  * if_mgr_enable_roaming() - interface manager enable roaming
  * @vdev: vdev object
@@ -106,4 +120,19 @@ QDF_STATUS if_mgr_enable_roaming_after_p2p_disconnect(
 				struct wlan_objmgr_pdev *pdev,
 				enum wlan_cm_rso_control_requestor requestor);
 
+/**
+ * if_mgr_validate_candidate() - validate candidate event handler
+ * @vdev: vdev object
+ * @event_data: Interface mgr event data
+ *
+ * This function will validate the candidate to see if it is a suitable option
+ * for roaming to.
+ *
+ * Context: It should run in thread context
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS if_mgr_validate_candidate(struct wlan_objmgr_vdev *vdev,
+				     struct if_mgr_event_data *event_data);
+
 #endif

+ 81 - 0
components/cmn_services/interface_mgr/src/wlan_if_mgr_roam.c

@@ -21,7 +21,9 @@
 #include "wlan_objmgr_pdev_obj.h"
 #include "wlan_objmgr_vdev_obj.h"
 #include "wlan_policy_mgr_api.h"
+#include "wlan_policy_mgr_i.h"
 #include "wlan_if_mgr_roam.h"
+#include "wlan_if_mgr_public_struct.h"
 #include "wlan_cm_roam_api.h"
 #include "wlan_if_mgr_main.h"
 #include "wlan_p2p_ucfg_api.h"
@@ -164,3 +166,82 @@ QDF_STATUS if_mgr_enable_roaming_after_p2p_disconnect(
 
 	return status;
 }
+
+static void if_mgr_get_vdev_id_from_bssid(struct wlan_objmgr_pdev *pdev,
+					  void *object, void *arg)
+{
+	struct bssid_search_arg *bssid_arg = arg;
+	struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object;
+	struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr;
+	struct wlan_objmgr_peer *peer = objmgr->bss_peer;
+
+	if (WLAN_ADDR_EQ(bssid_arg->peer_addr.bytes,
+			 wlan_peer_get_macaddr(peer)))
+		bssid_arg->vdev_id = wlan_vdev_get_id(vdev);
+}
+
+QDF_STATUS if_mgr_validate_candidate(struct wlan_objmgr_vdev *vdev,
+				     struct if_mgr_event_data *event_data)
+{
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_objmgr_pdev *pdev;
+	enum QDF_OPMODE op_mode;
+	enum policy_mgr_con_mode mode;
+	struct bssid_search_arg bssid_arg;
+	uint32_t chan_freq = event_data->validate_bss_info.chan_freq;
+
+	op_mode = wlan_vdev_mlme_get_opmode(vdev);
+
+	pdev = wlan_vdev_get_pdev(vdev);
+	if (!pdev)
+		return QDF_STATUS_E_FAILURE;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	if (!psoc)
+		return QDF_STATUS_E_FAILURE;
+
+	/*
+	 * Ignore the BSS if any other vdev is already connected to it.
+	 */
+	qdf_copy_macaddr(&bssid_arg.peer_addr,
+			 &event_data->validate_bss_info.peer_addr);
+	bssid_arg.vdev_id = WLAN_INVALID_VDEV_ID;
+	wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP,
+					  if_mgr_get_vdev_id_from_bssid,
+					  &bssid_arg, 0,
+					  WLAN_IF_MGR_ID);
+
+	if (bssid_arg.vdev_id != WLAN_INVALID_VDEV_ID) {
+		ifmgr_info("vdev_id %d already connected to "QDF_MAC_ADDR_FMT". select next bss for vdev_id %d",
+			   bssid_arg.vdev_id,
+			   QDF_MAC_ADDR_REF(bssid_arg.peer_addr.bytes),
+			   wlan_vdev_get_id(vdev));
+		return QDF_STATUS_E_INVAL;
+	}
+
+	/*
+	 * If concurrency enabled take the concurrent connected channel first.
+	 * Valid multichannel concurrent sessions exempted
+	 */
+	mode = policy_mgr_convert_device_mode_to_qdf_type(op_mode);
+	/* If concurrency is not allowed select next bss */
+	if (!policy_mgr_is_concurrency_allowed(psoc, mode, chan_freq,
+					       HW_MODE_20_MHZ)) {
+		ifmgr_info("Concurrency not allowed for this channel freq %d bssid "QDF_MAC_ADDR_FMT", selecting next",
+			   chan_freq, QDF_MAC_ADDR_REF(bssid_arg.peer_addr.bytes));
+		return QDF_STATUS_E_INVAL;
+	}
+
+	/*
+	 * check if channel is allowed for current hw mode, if not fetch
+	 * next BSS.
+	 */
+	if (!policy_mgr_is_hwmode_set_for_given_chnl(psoc, chan_freq)) {
+		ifmgr_info("HW mode isn't properly set, freq %d BSSID "QDF_MAC_ADDR_FMT,
+			   chan_freq,
+			   QDF_MAC_ADDR_REF(bssid_arg.peer_addr.bytes));
+		return QDF_STATUS_E_INVAL;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}

+ 39 - 3
core/sme/src/csr/csr_api_roam.c

@@ -75,6 +75,11 @@
 #include "wlan_psoc_mlme_api.h"
 #include "wlan_cm_roam_api.h"
 
+#ifdef WLAN_FEATURE_INTERFACE_MGR
+#include "wlan_if_mgr_public_struct.h"
+#include "wlan_if_mgr_ucfg_api.h"
+#endif
+
 #define RSN_AUTH_KEY_MGMT_SAE           WLAN_RSN_SEL(WLAN_AKM_SAE)
 #define MAX_PWR_FCC_CHAN_12 8
 #define MAX_PWR_FCC_CHAN_13 2
@@ -5367,14 +5372,20 @@ static bool csr_roam_select_bss(struct mac_context *mac_ctx,
 		enum csr_join_state *roam_state,
 		struct scan_result_list *bss_list)
 {
-	uint32_t conc_freq = 0, chan_freq, temp_vdev_id;
+	uint32_t conc_freq = 0, chan_freq;
 	bool status = false;
 	struct tag_csrscan_result *scan_result = NULL;
 	tCsrScanResultInfo *result = NULL;
 	enum QDF_OPMODE op_mode;
 	struct wlan_objmgr_vdev *vdev;
-	enum policy_mgr_con_mode mode;
 	QDF_STATUS qdf_status;
+#ifdef WLAN_FEATURE_INTERFACE_MGR
+	struct if_mgr_event_data event_data;
+	struct validate_bss_data candidate_info;
+#else
+	uint32_t temp_vdev_id;
+	enum policy_mgr_con_mode mode;
+#endif
 
 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(mac_ctx->pdev,
 						    vdev_id,
@@ -5397,6 +5408,31 @@ static bool csr_roam_select_bss(struct mac_context *mac_ctx,
 		 * sessions exempted
 		 */
 		result = &scan_result->Result;
+		chan_freq = result->BssDescriptor.chan_freq;
+
+	/*
+	 * Following code will be cleaned once the interface manager
+	 * module is enabled.
+	 */
+#ifdef WLAN_FEATURE_INTERFACE_MGR
+		qdf_mem_copy(candidate_info.peer_addr.bytes,
+			result->BssDescriptor.bssId,
+			sizeof(tSirMacAddr));
+		candidate_info.chan_freq = result->BssDescriptor.chan_freq;
+		event_data.validate_bss_info = candidate_info;
+		qdf_status = ucfg_if_mgr_deliver_event(vdev,
+						WLAN_IF_MGR_EV_VALIDATE_CANDIDATE,
+						&event_data);
+
+		if (QDF_IS_STATUS_ERROR(qdf_status)) {
+			*roam_state = eCsrStopRoamingDueToConcurrency;
+			status = true;
+			*roam_bss_entry = csr_ll_next(&bss_list->List,
+						*roam_bss_entry,
+						LL_ACCESS_LOCK);
+			continue;
+		}
+#else
 		/*
 		 * Ignore the BSS if any other vdev is already connected
 		 * to it.
@@ -5417,7 +5453,6 @@ static bool csr_roam_select_bss(struct mac_context *mac_ctx,
 			continue;
 		}
 
-		chan_freq = result->BssDescriptor.chan_freq;
 		mode = policy_mgr_convert_device_mode_to_qdf_type(op_mode);
 		/* If concurrency is not allowed select next bss */
 		if (!policy_mgr_is_concurrency_allowed(mac_ctx->psoc,
@@ -5451,6 +5486,7 @@ static bool csr_roam_select_bss(struct mac_context *mac_ctx,
 						     LL_ACCESS_LOCK);
 			continue;
 		}
+#endif
 		if (policy_mgr_concurrent_open_sessions_running(mac_ctx->psoc)
 			&& !csr_is_valid_mc_concurrent_session(mac_ctx,
 					vdev_id, &result->BssDescriptor)) {