Browse Source

qcacld-3.0: Update HDD link info with connected BSS info

Notify OSIF/HDD on successful connection to ML-BSS with all
links information part of association.

In each link's corresponding link info struct in HDD adapter,
update basic information of that link which contain following:
   a) IEEE link id.
   b) Link BSSID.
   c) Self link address.
   c) Current VDEV ID for that link.

As VDEV is not present for the standby link, we will use
self MAC address to identify the initial placeholder of that
link info to update IEEE link ID and BSSID.

Reset the IEEE link ID on disconnect/start adapter so that
stale values are not matched during search.

Don't reset connection info's BSSID if it is due to link switch.

Change-Id: I291f87072a2064bcee092819fbfb00a3803b9376
CRs-Fixed: 3557623
Vinod Kumar Pirla 1 year ago
parent
commit
073e5ee38c

+ 4 - 0
core/hdd/inc/wlan_hdd_assoc.h

@@ -155,6 +155,7 @@ struct hdd_conn_flag {
  * @max_tx_bitrate: Max tx bitrate supported by the AP
  * to which currently sta is connected.
  * @prev_ap_bcn_ie: ap beacon IE information to which sta is currently connected
+ * @ieee_link_id: AP Link Id valid for MLO connection
  */
 struct hdd_connection_info {
 	eConnectionState conn_state;
@@ -195,6 +196,9 @@ struct hdd_connection_info {
 	enum phy_ch_width ch_width;
 	struct rate_info max_tx_bitrate;
 	struct element_info prev_ap_bcn_ie;
+#ifdef WLAN_FEATURE_11BE_MLO
+	int32_t ieee_link_id;
+#endif
 };
 
 /* Forward declarations */

+ 24 - 0
core/hdd/inc/wlan_hdd_main.h

@@ -2833,6 +2833,21 @@ struct hdd_adapter *hdd_adapter_get_by_reference(struct hdd_context *hdd_ctx,
  */
 void hdd_adapter_put(struct hdd_adapter *adapter);
 
+/**
+ * hdd_get_link_info_by_link_addr() - Get the link info pointer where
+ * the link address matches.
+ * @hdd_ctx: HDD context pointer
+ * @link_addr: Link address to search
+ *
+ * In the given @adapter search for @link_addr in each entry of link_info
+ * array, and return the matching link_info pointer.
+ *
+ * Return: NULL / Valid link info pointer
+ */
+struct wlan_hdd_link_info *
+hdd_get_link_info_by_link_addr(struct hdd_context *hdd_ctx,
+			       struct qdf_mac_addr *link_addr);
+
 struct hdd_adapter *hdd_get_adapter_by_macaddr(struct hdd_context *hdd_ctx,
 					       tSirMacAddr mac_addr);
 
@@ -4048,6 +4063,15 @@ hdd_adapter_get_link_mac_addr(struct wlan_hdd_link_info *link_info);
  */
 QDF_STATUS hdd_adapter_check_duplicate_session(struct hdd_adapter *adapter);
 
+/**
+ * hdd_adapter_reset_station_ctx() - Resets station context with appropriate
+ * initial value.
+ * @adapter: HDD adapter
+ *
+ * Return: void
+ */
+void hdd_adapter_reset_station_ctx(struct hdd_adapter *adapter);
+
 /**
  * hdd_start_station_adapter()- Start the Station Adapter
  * @adapter: HDD adapter

+ 43 - 0
core/hdd/inc/wlan_hdd_mlo.h

@@ -327,12 +327,55 @@ int wlan_hdd_cfg80211_process_ml_link_state(struct wiphy *wiphy,
 QDF_STATUS hdd_derive_link_address_from_mld(struct qdf_mac_addr *mld_addr,
 					    struct qdf_mac_addr *link_addr_list,
 					    uint8_t max_idx);
+
+#ifdef WLAN_HDD_MULTI_VDEV_SINGLE_NDEV
+/**
+ * hdd_mlo_mgr_register_osif_ops() - Register OSIF ops with global MLO manager
+ * for callback to notify.
+ *
+ * The @ops contain callback functions which are triggered to update OSIF about
+ * necessary events from MLO manager.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS hdd_mlo_mgr_register_osif_ops(void);
+
+/**
+ * hdd_mlo_mgr_unregister_osif_ops() - Deregister OSIF ops with
+ * global MLO manager
+ *
+ * Deregister the calbacks registered with global MLO manager for OSIF
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS hdd_mlo_mgr_unregister_osif_ops(void);
+#else
+static inline QDF_STATUS hdd_mlo_mgr_register_osif_ops(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline QDF_STATUS hdd_mlo_mgr_unregister_osif_ops(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
 #else
 static inline void
 hdd_adapter_set_ml_adapter(struct hdd_adapter *adapter)
 {
 }
 
+static inline QDF_STATUS hdd_mlo_mgr_register_osif_ops(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline QDF_STATUS hdd_mlo_mgr_unregister_osif_ops(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
 static inline
 void hdd_mlo_t2lm_register_callback(struct wlan_objmgr_vdev *vdev)
 {

+ 63 - 2
core/hdd/src/wlan_hdd_cm_api.h

@@ -255,13 +255,13 @@ __hdd_cm_disconnect_handler_pre_user_update(struct wlan_hdd_link_info *link_info
 /**
  * __hdd_cm_disconnect_handler_post_user_update() - Handle disconnect indication
  * after updating to user space
- * @adapter: Pointer to adapter
+ * @link_info: Link info pointer in HDD adapter
  * @vdev: vdev ptr
  *
  * Return: None
  */
 void
-__hdd_cm_disconnect_handler_post_user_update(struct hdd_adapter *adapter,
+__hdd_cm_disconnect_handler_post_user_update(struct wlan_hdd_link_info *link_info,
 					     struct wlan_objmgr_vdev *vdev);
 
 /**
@@ -379,4 +379,65 @@ QDF_STATUS
 hdd_cm_get_scan_ie_params(struct wlan_objmgr_vdev *vdev,
 			  struct element_info *scan_ie,
 			  enum dot11_mode_filter *dot11mode_filter);
+
+#ifdef WLAN_FEATURE_11BE_MLO
+/**
+ * hdd_cm_save_connected_links_info() - Update connection info to station
+ * context.
+ * @self_mac: Self MAC address.
+ * @bssid: BSSID of link.
+ * @link_id: IEEE link id.
+ *
+ * It searches for link info pointer matching with @self_mac and updates
+ * the BSSID and link ID fields in station context's connection info.
+ * This will help to retrieve the link information using IEEE link ID or
+ * BSSID thereafter.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS hdd_cm_save_connected_links_info(struct qdf_mac_addr *self_mac,
+					    struct qdf_mac_addr *bssid,
+					    int32_t link_id);
+
+/**
+ * hdd_cm_set_ieee_link_id() - Set IEEE link ID in station context conn info.
+ * @link_info: Link info pointer in HDD adapter
+ * @link_id: IEEE link ID
+ *
+ * Sets IEEE link ID in connection info of @link_info's station context.
+ *
+ * Return: void
+ */
+void
+hdd_cm_set_ieee_link_id(struct wlan_hdd_link_info *link_info, uint8_t link_id);
+
+/**
+ * hdd_cm_clear_ieee_link_id() - Clear IEEE link ID in station context
+ * conn info.
+ * @link_info: Link info pointer in HDD adapter
+ *
+ * Clear IEEE link ID in connection info of @link_info's station context.
+ *
+ * Return: void
+ */
+void hdd_cm_clear_ieee_link_id(struct wlan_hdd_link_info *link_info);
+#else
+static inline void
+hdd_cm_set_ieee_link_id(struct wlan_hdd_link_info *link_info, uint8_t link_id)
+{
+}
+
+static inline void
+hdd_cm_clear_ieee_link_id(struct wlan_hdd_link_info *link_info)
+{
+}
+
+static inline
+QDF_STATUS hdd_cm_save_connected_links_info(struct qdf_mac_addr *self_mac,
+					    struct qdf_mac_addr *bssid,
+					    int32_t link_id)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif /* WLAN_FEATURE_11BE_MLO */
 #endif /* __WLAN_HDD_CM_API_H */

+ 57 - 1
core/hdd/src/wlan_hdd_cm_connect.c

@@ -327,6 +327,53 @@ void hdd_cm_save_connect_status(struct wlan_hdd_link_info *link_info,
 	hdd_sta_ctx->cache_conn_info.assoc_status_code = reason_code;
 }
 
+#ifdef WLAN_FEATURE_11BE_MLO
+QDF_STATUS hdd_cm_save_connected_links_info(struct qdf_mac_addr *self_mac,
+					    struct qdf_mac_addr *bssid,
+					    int32_t link_id)
+{
+	struct hdd_context *hdd_ctx;
+	struct wlan_hdd_link_info *link_info;
+	struct hdd_station_ctx *sta_ctx;
+
+	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+	if (!hdd_ctx) {
+		hdd_err("HDD context NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	link_info = hdd_get_link_info_by_link_addr(hdd_ctx, self_mac);
+	if (!link_info) {
+		hdd_err("No link info with MAC: " QDF_MAC_ADDR_FMT,
+			QDF_MAC_ADDR_REF(self_mac->bytes));
+		return QDF_STATUS_E_INVAL;
+	}
+
+	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
+	hdd_cm_set_ieee_link_id(link_info, link_id);
+	qdf_copy_macaddr(&sta_ctx->conn_info.bssid, bssid);
+	return QDF_STATUS_SUCCESS;
+}
+
+void
+hdd_cm_set_ieee_link_id(struct wlan_hdd_link_info *link_info, uint8_t link_id)
+{
+	struct hdd_station_ctx *sta_ctx =
+				WLAN_HDD_GET_STATION_CTX_PTR(link_info);
+
+	sta_ctx->conn_info.ieee_link_id = link_id;
+}
+
+void
+hdd_cm_clear_ieee_link_id(struct wlan_hdd_link_info *link_info)
+{
+	struct hdd_station_ctx *sta_ctx =
+				WLAN_HDD_GET_STATION_CTX_PTR(link_info);
+
+	sta_ctx->conn_info.ieee_link_id = WLAN_INVALID_LINK_ID;
+}
+#endif
+
 #ifdef FEATURE_WLAN_WAPI
 static bool hdd_cm_is_wapi_sta(enum csr_akm_type auth_type)
 {
@@ -888,6 +935,8 @@ hdd_cm_connect_failure_pre_user_update(struct wlan_objmgr_vdev *vdev,
 	struct hdd_station_ctx *hdd_sta_ctx;
 	uint32_t time_buffer_size;
 	struct wlan_hdd_link_info *link_info;
+	bool is_link_switch =
+			wlan_vdev_mlme_is_mlo_link_switch_in_progress(vdev);
 
 	if (!hdd_ctx) {
 		hdd_err("hdd_ctx is NULL");
@@ -906,7 +955,14 @@ hdd_cm_connect_failure_pre_user_update(struct wlan_objmgr_vdev *vdev,
 	qdf_mem_zero(hdd_sta_ctx->conn_info.connect_time, time_buffer_size);
 	hdd_init_scan_reject_params(hdd_ctx);
 	hdd_cm_save_connect_status(link_info, rsp->status_code);
-	hdd_conn_remove_connect_info(hdd_sta_ctx);
+	if (!is_link_switch) {
+		/* For link switch connection failure, do not clear existing
+		 * connection info in OSIF.
+		 */
+		hdd_conn_remove_connect_info(hdd_sta_ctx);
+		hdd_adapter_reset_station_ctx(adapter);
+	}
+
 	ucfg_dp_remove_conn_info(vdev);
 	hdd_cm_update_rssi_snr_by_bssid(link_info);
 	hdd_cm_rec_connect_info(rsp);

+ 23 - 14
core/hdd/src/wlan_hdd_cm_disconnect.c

@@ -165,36 +165,39 @@ __hdd_cm_disconnect_handler_pre_user_update(struct wlan_hdd_link_info *link_info
 	hdd_place_marker(adapter, "DISCONNECTED", NULL);
 }
 
-void __hdd_cm_disconnect_handler_post_user_update(struct hdd_adapter *adapter,
-						  struct wlan_objmgr_vdev *vdev)
+void
+__hdd_cm_disconnect_handler_post_user_update(struct wlan_hdd_link_info *link_info,
+					     struct wlan_objmgr_vdev *vdev)
 {
+	struct hdd_adapter *adapter = link_info->adapter;
 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
 	struct hdd_station_ctx *sta_ctx;
 	mac_handle_t mac_handle;
 	struct hdd_adapter *link_adapter;
 	struct hdd_station_ctx *link_sta_ctx;
+	bool is_link_switch =
+			wlan_vdev_mlme_is_mlo_link_switch_in_progress(vdev);
 
 	mac_handle = hdd_ctx->mac_handle;
-	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
+	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
 
 	/* update P2P connection status */
 	ucfg_p2p_status_disconnect(vdev);
-	hdd_cfr_disconnect(adapter->deflink->vdev);
+	hdd_cfr_disconnect(vdev);
 
 	hdd_wmm_adapter_clear(adapter);
 	ucfg_cm_ft_reset(vdev);
-	ucfg_cm_reset_key(hdd_ctx->pdev, adapter->deflink->vdev_id);
+	ucfg_cm_reset_key(hdd_ctx->pdev, link_info->vdev_id);
 	hdd_clear_roam_profile_ie(adapter);
 
 	if (adapter->device_mode == QDF_STA_MODE)
 		wlan_crypto_reset_vdev_params(vdev);
 
 	hdd_remove_beacon_filter(adapter);
-	if (sme_is_beacon_report_started(mac_handle,
-					 adapter->deflink->vdev_id)) {
+	if (sme_is_beacon_report_started(mac_handle, link_info->vdev_id)) {
 		hdd_debug("Sending beacon pause indication to userspace");
 		hdd_beacon_recv_pause_indication((hdd_handle_t)hdd_ctx,
-						 adapter->deflink->vdev_id,
+						 link_info->vdev_id,
 						 SCAN_EVENT_TYPE_MAX, true);
 	}
 
@@ -208,13 +211,20 @@ void __hdd_cm_disconnect_handler_post_user_update(struct hdd_adapter *adapter,
 			hdd_conn_remove_connect_info(link_sta_ctx);
 		}
 	}
-	/* Clear saved connection information in HDD */
-	hdd_conn_remove_connect_info(sta_ctx);
+
+	if (!is_link_switch) {
+		/* Clear saved connection information in HDD */
+		hdd_conn_remove_connect_info(sta_ctx);
+		/* Reset the IEEE link ID to invalid when disconnect is not
+		 * due to link switch.
+		 */
+		hdd_adapter_reset_station_ctx(adapter);
+	}
 
 	ucfg_dp_remove_conn_info(vdev);
 
 	/* Setting the RTS profile to original value */
-	if (sme_cli_set_command(adapter->deflink->vdev_id,
+	if (sme_cli_set_command(link_info->vdev_id,
 				wmi_vdev_param_enable_rtscts,
 				cfg_get(hdd_ctx->psoc,
 					CFG_ENABLE_FW_RTS_PROFILE),
@@ -226,8 +236,7 @@ void __hdd_cm_disconnect_handler_post_user_update(struct hdd_adapter *adapter,
 
 	if ((QDF_STA_MODE == adapter->device_mode) ||
 	    (QDF_P2P_CLIENT_MODE == adapter->device_mode)) {
-		sme_ps_disable_auto_ps_timer(mac_handle,
-					     adapter->deflink->vdev_id);
+		sme_ps_disable_auto_ps_timer(mac_handle, link_info->vdev_id);
 		adapter->send_mode_change = true;
 	}
 	wlan_hdd_clear_link_layer_stats(adapter);
@@ -568,7 +577,7 @@ hdd_cm_disconnect_complete_post_user_update(struct wlan_objmgr_vdev *vdev,
 	 */
 	hdd_cm_restore_ch_width(vdev, adapter);
 	hdd_cm_set_default_wlm_mode(adapter);
-	__hdd_cm_disconnect_handler_post_user_update(adapter, vdev);
+	__hdd_cm_disconnect_handler_post_user_update(link_info, vdev);
 	wlan_twt_concurrency_update(hdd_ctx);
 	hdd_cm_reset_udp_qos_upgrade_config(adapter);
 

+ 56 - 3
core/hdd/src/wlan_hdd_main.c

@@ -10265,6 +10265,35 @@ struct hdd_adapter *hdd_get_adapter_by_macaddr(struct hdd_context *hdd_ctx,
 
 	return NULL;
 }
+
+struct wlan_hdd_link_info *
+hdd_get_link_info_by_link_addr(struct hdd_context *hdd_ctx,
+			       struct qdf_mac_addr *link_addr)
+{
+	struct wlan_hdd_link_info *link_info;
+	struct hdd_adapter *adapter, *next_adapter = NULL;
+	wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_ADAPTER_BY_MACADDR;
+
+	if (!link_addr || qdf_is_macaddr_zero(link_addr))
+		return NULL;
+
+	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
+					   dbgid) {
+		hdd_adapter_for_each_link_info(adapter, link_info) {
+			if (qdf_is_macaddr_equal(link_addr,
+						 &link_info->link_addr)) {
+				hdd_adapter_dev_put_debug(adapter, dbgid);
+				if (next_adapter)
+					hdd_adapter_dev_put_debug(next_adapter,
+								  dbgid);
+				return link_info;
+			}
+		}
+		hdd_adapter_dev_put_debug(adapter, dbgid);
+	}
+
+	return NULL;
+}
 #else
 struct hdd_adapter *hdd_get_adapter_by_macaddr(struct hdd_context *hdd_ctx,
 					       tSirMacAddr mac_addr)
@@ -10296,6 +10325,13 @@ struct hdd_adapter *hdd_get_adapter_by_macaddr(struct hdd_context *hdd_ctx,
 
 	return NULL;
 }
+
+struct wlan_hdd_link_info *
+hdd_get_link_info_by_link_addr(struct hdd_context *hdd_ctx,
+			       struct qdf_mac_addr *link_addr)
+{
+	return NULL;
+}
 #endif
 
 struct wlan_hdd_link_info *
@@ -14197,7 +14233,7 @@ QDF_STATUS hdd_adapter_fill_link_address(struct hdd_adapter *adapter)
 	int i = 0;
 	QDF_STATUS status;
 	enum QDF_OPMODE opmode = adapter->device_mode;
-	struct qdf_mac_addr link_addrs[WLAN_MAX_MLD] = {0};
+	struct qdf_mac_addr link_addrs[WLAN_MAX_ML_BSS_LINKS] = {0};
 	struct wlan_hdd_link_info *link_info;
 
 	if (opmode != QDF_STA_MODE && opmode != QDF_SAP_MODE)
@@ -14214,11 +14250,11 @@ QDF_STATUS hdd_adapter_fill_link_address(struct hdd_adapter *adapter)
 
 	status = hdd_derive_link_address_from_mld(&adapter->mac_addr,
 						  &link_addrs[0],
-						  WLAN_MAX_MLD);
+						  WLAN_MAX_ML_BSS_LINKS);
 	if (QDF_IS_STATUS_ERROR(status))
 		return status;
 
-	hdd_adapter_for_each_active_link_info(adapter, link_info)
+	hdd_adapter_for_each_link_info(adapter, link_info)
 		qdf_copy_macaddr(&link_info->link_addr, &link_addrs[i++]);
 
 	return status;
@@ -14282,6 +14318,14 @@ static void hdd_restore_info_for_ssr(struct hdd_adapter *adapter)
 	}
 }
 
+void hdd_adapter_reset_station_ctx(struct hdd_adapter *adapter)
+{
+	struct wlan_hdd_link_info *link_info;
+
+	hdd_adapter_for_each_link_info(adapter, link_info)
+		hdd_cm_clear_ieee_link_id(link_info);
+}
+
 int hdd_start_station_adapter(struct hdd_adapter *adapter)
 {
 	QDF_STATUS status;
@@ -14326,6 +14370,8 @@ int hdd_start_station_adapter(struct hdd_adapter *adapter)
 		}
 	}
 
+	hdd_adapter_reset_station_ctx(adapter);
+
 	hdd_register_wext(adapter->dev);
 	hdd_set_netdev_flags(adapter);
 
@@ -18672,8 +18718,14 @@ static QDF_STATUS hdd_component_init(void)
 	if (QDF_IS_STATUS_ERROR(status))
 		goto ll_sap_deinit;
 
+	status = hdd_mlo_mgr_register_osif_ops();
+	if (QDF_IS_STATUS_ERROR(status))
+		goto afc_deinit;
+
 	return QDF_STATUS_SUCCESS;
 
+afc_deinit:
+	ucfg_afc_deinit();
 ll_sap_deinit:
 	ucfg_ll_sap_deinit();
 qmi_deinit:
@@ -18728,6 +18780,7 @@ mlme_global_deinit:
 static void hdd_component_deinit(void)
 {
 	/* deinitialize non-converged components */
+	hdd_mlo_mgr_unregister_osif_ops();
 	ucfg_afc_deinit();
 	ucfg_ll_sap_deinit();
 	ucfg_qmi_deinit();

+ 18 - 0
core/hdd/src/wlan_hdd_mlo.c

@@ -250,6 +250,24 @@ void hdd_adapter_set_ml_adapter(struct hdd_adapter *adapter)
 {
 	adapter->mlo_adapter_info.is_ml_adapter = true;
 }
+
+static struct mlo_osif_ext_ops mlo_osif_ops = {
+	.mlo_mgr_osif_update_bss_info = hdd_cm_save_connected_links_info,
+};
+
+QDF_STATUS hdd_mlo_mgr_register_osif_ops(void)
+{
+	struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
+
+	return wlan_mlo_mgr_register_osif_ext_ops(mlo_mgr_ctx, &mlo_osif_ops);
+}
+
+QDF_STATUS hdd_mlo_mgr_unregister_osif_ops(void)
+{
+	struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
+
+	return wlan_mlo_mgr_unregister_osif_ext_ops(mlo_mgr_ctx);
+}
 #endif
 
 void hdd_mlo_t2lm_register_callback(struct wlan_objmgr_vdev *vdev)