Browse Source

qcacmn: Add APIs to create bridge peer

Add APIs to create bridge peer. Register call
back for the same to handle bridge peer
creation.

CRs-Fixed: 3416877
Change-Id: I51d8f023576c93121e42d54243721edbf705e6b4
Shreedhar Parande 2 years ago
parent
commit
60919a5e84

+ 16 - 0
umac/mlo_mgr/inc/wlan_mlo_mgr_ap.h

@@ -463,6 +463,22 @@ void mlo_peer_assign_primary_umac(
 		struct wlan_mlo_peer_context *ml_peer,
 		struct wlan_mlo_link_peer_entry *peer_entry);
 
+#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
+/**
+ * mlo_peer_overwrite_primary_umac() - Overwrite Primary UMAC config
+ * @psoc_id: PSOC ID
+ * @ml_peer: MLO peer object
+ *
+ * This function overwrites previous primary UMAC configuration
+ * with given PSOC.
+ *
+ * Return: QDF_STATUS_SUCCESS if it overwrites successfully.
+ * QDF_STATUS_E_FAILURE otherwise.
+ */
+QDF_STATUS mlo_peer_overwrite_primary_umac(uint8_t psoc_id,
+					   struct wlan_mlo_peer_context *ml_peer);
+#endif
+
 /**
  * mlo_peer_allocate_primary_umac() - Allocate Primary UMAC
  * @ml_dev: MLO DEV context

+ 14 - 0
umac/mlo_mgr/inc/wlan_mlo_mgr_cmn.h

@@ -198,6 +198,20 @@ void mlo_mlme_peer_create(struct wlan_objmgr_vdev *vdev,
 			  struct qdf_mac_addr *addr,
 			  qdf_nbuf_t frm_buf);
 
+/**
+ * mlo_mlme_bridge_peer_create() - Create mlo bridge peer
+ * @vdev: Object manager vdev
+ * @ml_peer: MLO peer context
+ * @addr: Peer addr
+ * @frm_buf: Frame buffer for IE processing
+ *
+ * Return: void
+ */
+void mlo_mlme_bridge_peer_create(struct wlan_objmgr_vdev *vdev,
+				 struct wlan_mlo_peer_context *ml_peer,
+				 struct qdf_mac_addr *addr,
+				 qdf_nbuf_t frm_buf);
+
 /**
  * mlo_mlme_peer_assoc() - Send ML Peer assoc
  * @peer: Object manager peer

+ 3 - 1
umac/mlo_mgr/inc/wlan_mlo_mgr_msgq.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -47,6 +47,7 @@ struct ctxt_switch_mgr {
  * @MLO_PEER_DISCONNECT:  Partner peer Disconnect
  * @MLO_PEER_DEAUTH:  Initiate Deauth for ML connection
  * @MLO_PEER_PENDING_AUTH:  Initiate process of pending auth
+ * @MLO_BRIDGE_PEER_CREATE:   Bridge peer create
  */
 enum mlo_msg_type {
 	MLO_PEER_CREATE,
@@ -55,6 +56,7 @@ enum mlo_msg_type {
 	MLO_PEER_DISCONNECT,
 	MLO_PEER_DEAUTH,
 	MLO_PEER_PENDING_AUTH,
+	MLO_BRIDGE_PEER_CREATE,
 };
 
 /*

+ 1 - 0
umac/mlo_mgr/inc/wlan_mlo_mgr_peer.h

@@ -24,6 +24,7 @@
 #include "wlan_objmgr_peer_obj.h"
 
 #define WLAN_LINK_ID_INVALID    0xff
+#define WLAN_NUM_TWO_LINK_PSOC  2
 
 /**
  * mlo_peer_create - Initiatiate peer create on secondary link(s)

+ 5 - 0
umac/mlo_mgr/inc/wlan_mlo_mgr_public_structs.h

@@ -726,6 +726,7 @@ struct mlo_tgt_partner_info {
  * @mlo_mlme_ext_validate_conn_req: Callback to validate connect request
  * @mlo_mlme_ext_create_link_vdev: Callback to create link vdev for ML STA
  * @mlo_mlme_ext_peer_create: Callback to create link peer
+ * @mlo_mlme_ext_bridge_peer_create: Callback to create bridge peer
  * @mlo_mlme_ext_peer_assoc: Callback to initiate peer assoc
  * @mlo_mlme_ext_peer_assoc_fail: Callback to notify peer assoc failure
  * @mlo_mlme_ext_peer_delete: Callback to initiate link peer delete
@@ -746,6 +747,10 @@ struct mlo_mlme_ext_ops {
 					struct wlan_mlo_peer_context *ml_peer,
 					struct qdf_mac_addr *addr,
 					qdf_nbuf_t frm_buf);
+	QDF_STATUS (*mlo_mlme_ext_bridge_peer_create)(struct wlan_objmgr_vdev *vdev,
+					struct wlan_mlo_peer_context *ml_peer,
+					struct qdf_mac_addr *addr,
+					qdf_nbuf_t frm_buf);
 	void (*mlo_mlme_ext_peer_assoc)(struct wlan_objmgr_peer *peer);
 	void (*mlo_mlme_ext_peer_assoc_fail)(struct wlan_objmgr_peer *peer);
 	void (*mlo_mlme_ext_peer_delete)(struct wlan_objmgr_peer *peer);

+ 15 - 0
umac/mlo_mgr/src/wlan_mlo_mgr_cmn.c

@@ -203,6 +203,21 @@ void mlo_mlme_peer_create(struct wlan_objmgr_vdev *vdev,
 						    addr, frm_buf);
 }
 
+void mlo_mlme_bridge_peer_create(struct wlan_objmgr_vdev *vdev,
+				 struct wlan_mlo_peer_context *ml_peer,
+				 struct qdf_mac_addr *addr,
+				 qdf_nbuf_t frm_buf)
+{
+	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
+
+	if (!mlo_ctx || !mlo_ctx->mlme_ops ||
+	    !mlo_ctx->mlme_ops->mlo_mlme_ext_bridge_peer_create)
+		return;
+
+	mlo_ctx->mlme_ops->mlo_mlme_ext_bridge_peer_create(vdev, ml_peer,
+							   addr, frm_buf);
+}
+
 void mlo_mlme_peer_assoc(struct wlan_objmgr_peer *peer)
 {
 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();

+ 40 - 1
umac/mlo_mgr/src/wlan_mlo_mgr_msgq.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -46,6 +46,18 @@ QDF_STATUS mlo_msgq_post(enum mlo_msg_type type,
 					     WLAN_MLO_MGR_ID);
 		break;
 
+	case MLO_BRIDGE_PEER_CREATE:
+		peer_create = (struct peer_create_notif_s *)payload;
+
+		mlo_mlme_bridge_peer_create(peer_create->vdev_link,
+					    peer_create->ml_peer,
+					    &peer_create->addr,
+					    peer_create->frm_buf);
+		wlan_mlo_peer_release_ref(peer_create->ml_peer);
+		wlan_objmgr_vdev_release_ref(peer_create->vdev_link,
+					     WLAN_MLO_MGR_ID);
+		break;
+
 	case MLO_PEER_ASSOC:
 		peer_assoc = (struct peer_assoc_notify_s *)payload;
 		mlo_mlme_peer_assoc(peer_assoc->peer);
@@ -173,6 +185,15 @@ QDF_STATUS mlo_msgq_post(enum mlo_msg_type type,
 		qdf_copy_macaddr(&peer_create->addr, &peer_create_l->addr);
 		break;
 
+	case MLO_BRIDGE_PEER_CREATE:
+		peer_create = &msg->m.peer_create;
+		peer_create_l = (struct peer_create_notif_s *)payload;
+		peer_create->frm_buf = peer_create_l->frm_buf;
+		peer_create->ml_peer = peer_create_l->ml_peer;
+		peer_create->vdev_link = peer_create_l->vdev_link;
+		qdf_copy_macaddr(&peer_create->addr, &peer_create_l->addr);
+		break;
+
 	case MLO_PEER_ASSOC:
 		peer_assoc = &msg->m.peer_assoc;
 		peer_assoc_l = (struct peer_assoc_notify_s *)payload;
@@ -239,6 +260,17 @@ static void mlo_msgq_msg_process_hdlr(struct mlo_ctxt_switch_msg_s *msg)
 					     WLAN_MLO_MGR_ID);
 		break;
 
+	case MLO_BRIDGE_PEER_CREATE:
+		peer_create = &msg->m.peer_create;
+		mlo_mlme_bridge_peer_create(peer_create->vdev_link,
+					    peer_create->ml_peer,
+					    &peer_create->addr,
+					    peer_create->frm_buf);
+		wlan_mlo_peer_release_ref(peer_create->ml_peer);
+		wlan_objmgr_vdev_release_ref(peer_create->vdev_link,
+					     WLAN_MLO_MGR_ID);
+		break;
+
 	case MLO_PEER_ASSOC:
 		peer_assoc = &msg->m.peer_assoc;
 		mlo_mlme_peer_assoc(peer_assoc->peer);
@@ -297,6 +329,13 @@ static void mlo_msgq_msg_flush_hdlr(struct mlo_ctxt_switch_msg_s *msg)
 					     WLAN_MLO_MGR_ID);
 		break;
 
+	case MLO_BRIDGE_PEER_CREATE:
+		peer_create = &msg->m.peer_create;
+		wlan_mlo_peer_release_ref(peer_create->ml_peer);
+		wlan_objmgr_vdev_release_ref(peer_create->vdev_link,
+					     WLAN_MLO_MGR_ID);
+		break;
+
 	case MLO_PEER_ASSOC:
 		peer_assoc = &msg->m.peer_assoc;
 		wlan_objmgr_peer_release_ref(peer_assoc->peer,

+ 170 - 0
umac/mlo_mgr/src/wlan_mlo_mgr_peer.c

@@ -24,6 +24,7 @@
 #include "wlan_mlo_mgr_peer.h"
 #include "wlan_mlo_mgr_ap.h"
 #include "wlan_crypto_global_api.h"
+#include "wlan_mlo_mgr_setup.h"
 
 static void mlo_partner_peer_create_post(struct wlan_mlo_dev_context *ml_dev,
 					 struct wlan_objmgr_vdev *vdev_link,
@@ -831,6 +832,165 @@ wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer,
 {}
 #endif /* WLAN_FEATURE_11BE */
 
+#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
+static struct wlan_objmgr_vdev*
+mlo_get_primary_umac_vdev(struct wlan_mlo_dev_context *ml_dev,
+			  uint8_t psoc_id)
+{
+	uint8_t i;
+	struct wlan_objmgr_vdev *link_vdev;
+
+	if (WLAN_OBJMGR_MAX_DEVICES <= psoc_id)
+		return NULL;
+
+	if (!ml_dev)
+		return NULL;
+
+	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
+		link_vdev = ml_dev->wlan_vdev_list[i];
+		if (!link_vdev)
+			continue;
+		if (psoc_id == wlan_vdev_get_psoc_id(link_vdev))
+			return link_vdev;
+	}
+
+	return NULL;
+}
+
+static
+QDF_STATUS mlo_bridge_peer_create_post(struct wlan_mlo_dev_context *ml_dev,
+				       struct wlan_mlo_peer_context *ml_peer,
+				       uint8_t psoc_id)
+{
+	struct peer_create_notif_s peer_create;
+	struct wlan_objmgr_vdev *vdev_link;
+	QDF_STATUS status;
+
+	vdev_link = mlo_get_primary_umac_vdev(ml_dev, psoc_id);
+
+	if (!vdev_link) {
+		mlo_err("VDEV derivation in unsuccessful");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (wlan_objmgr_vdev_try_get_ref(vdev_link, WLAN_MLO_MGR_ID) !=
+							QDF_STATUS_SUCCESS) {
+		mlo_err("VDEV is not in created state");
+		return QDF_STATUS_E_FAILURE;
+	}
+	peer_create.vdev_link = vdev_link;
+	wlan_mlo_peer_get_ref(ml_peer);
+	peer_create.ml_peer = ml_peer;
+
+	qdf_copy_macaddr(&peer_create.addr,
+			 &ml_peer->peer_mld_addr);
+
+	peer_create.frm_buf = NULL;
+
+	status = mlo_msgq_post(MLO_BRIDGE_PEER_CREATE, ml_dev, &peer_create);
+	if (status != QDF_STATUS_SUCCESS) {
+		wlan_mlo_peer_release_ref(ml_peer);
+		wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID);
+	}
+
+	return status;
+}
+
+static QDF_STATUS
+wlan_mlo_check_and_create_bridge_peer(struct wlan_objmgr_vdev *vdev,
+				      struct wlan_mlo_peer_context *ml_peer,
+				      struct wlan_objmgr_vdev *link_vdevs[],
+				      uint8_t num_partner_links)
+{
+	struct wlan_mlo_dev_context *ml_dev;
+	struct wlan_objmgr_vdev *ml_vdev;
+	uint8_t psoc_ids[WLAN_NUM_TWO_LINK_PSOC];
+	uint8_t comp_psoc_id, i, is_adjacent;
+	uint8_t bridge_peer_psoc_id = WLAN_OBJMGR_MAX_DEVICES;
+	QDF_STATUS status;
+
+	if (wlan_vdev_mlme_get_opmode(vdev) != QDF_SAP_MODE)
+		return QDF_STATUS_SUCCESS;
+
+	/* Return from here for 3 link association */
+	if (WLAN_NUM_TWO_LINK_PSOC != num_partner_links)
+		return QDF_STATUS_SUCCESS;
+
+	ml_dev = vdev->mlo_dev_ctx;
+	if (!ml_dev)
+		return QDF_STATUS_E_FAILURE;
+
+	for (i = 0; i < WLAN_NUM_TWO_LINK_PSOC; i++)
+		psoc_ids[i] = wlan_vdev_get_psoc_id(link_vdevs[i]);
+
+	status = mlo_chip_adjacent(psoc_ids[0], psoc_ids[1],
+				   &is_adjacent);
+	if (QDF_STATUS_SUCCESS != status) {
+		mlo_err("Unable to get chip adjacency for " QDF_MAC_ADDR_FMT ", psoc_0 %u, psoc_1 %u",
+			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
+			psoc_ids[0], psoc_ids[1]);
+		return status;
+	}
+	if (is_adjacent)
+		return QDF_STATUS_SUCCESS;
+	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
+		ml_vdev = ml_dev->wlan_vdev_list[i];
+		if (!ml_vdev)
+			continue;
+		comp_psoc_id = wlan_vdev_get_psoc_id(ml_vdev);
+		if ((comp_psoc_id != psoc_ids[0]) &&
+		    (comp_psoc_id != psoc_ids[1])) {
+			bridge_peer_psoc_id = comp_psoc_id;
+			break;
+		}
+	}
+
+	if (bridge_peer_psoc_id >= WLAN_OBJMGR_MAX_DEVICES) {
+		mlo_err("Invalid psoc or psoc not found for " QDF_MAC_ADDR_FMT " psoc %u",
+			ether_sprintf(ml_peer->peer_mld_addr.bytes),
+			bridge_peer_psoc_id);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	/* Check if derived psoc is adjecent to both links */
+	for (i = 0; i < WLAN_NUM_TWO_LINK_PSOC; i++) {
+		status = mlo_chip_adjacent(psoc_ids[i], bridge_peer_psoc_id,
+					   &is_adjacent);
+		if (QDF_STATUS_SUCCESS != status) {
+			mlo_err("Unable to get chip adjacency for " QDF_MAC_ADDR_FMT ", psoc_0 %u, psoc_1 %u",
+				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
+				psoc_ids[i], bridge_peer_psoc_id);
+			return status;
+		}
+		if (!is_adjacent) {
+			mlo_err("Derived psoc is not adjecent to one of the links for " QDF_MAC_ADDR_FMT ", psoc_0 %u, psoc_1 %u psoc_2 %u",
+				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
+				psoc_ids[0], psoc_ids[1], bridge_peer_psoc_id);
+			return QDF_STATUS_E_FAILURE;
+		}
+	}
+
+	/* Assign bridge peer PSOC as primary UMAC */
+	mlo_peer_overwrite_primary_umac(bridge_peer_psoc_id, ml_peer);
+	mlo_debug("Creating bridge peer for " QDF_MAC_ADDR_FMT " on psoc %u, is_adjacent %u",
+		  QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
+		  bridge_peer_psoc_id, is_adjacent);
+	/* Create bridge peer */
+	status = mlo_bridge_peer_create_post(ml_dev, ml_peer,
+					     bridge_peer_psoc_id);
+	return status;
+}
+#else
+static QDF_STATUS
+wlan_mlo_check_and_create_bridge_peer(struct wlan_objmgr_vdev *vdev,
+				      struct wlan_mlo_peer_context *ml_peer,
+				      struct wlan_objmgr_vdev *link_vdevs[],
+				      uint8_t num_partner_links)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
 QDF_STATUS wlan_mlo_peer_create(struct wlan_objmgr_vdev *vdev,
 				struct wlan_objmgr_peer *link_peer,
 				struct mlo_partner_info *ml_info,
@@ -1043,6 +1203,16 @@ QDF_STATUS wlan_mlo_peer_create(struct wlan_objmgr_vdev *vdev,
 			mlo_partner_peer_create_post(ml_dev, vdev_link,
 						     ml_peer, frm_buf, ml_info);
 		}
+		status = wlan_mlo_check_and_create_bridge_peer(vdev, ml_peer,
+							       link_vdevs,
+							       ml_info->num_partner_links);
+		if (QDF_STATUS_SUCCESS != status) {
+			mlo_err("MLD ID %d: Bridge peer creation failed",
+				ml_dev->mld_id);
+			mlo_dev_release_link_vdevs(link_vdevs);
+			wlan_mlo_peer_release_ref(ml_peer);
+			return QDF_STATUS_E_FAILURE;
+		}
 	}
 	mlo_dev_release_link_vdevs(link_vdevs);
 

+ 16 - 0
umac/mlo_mgr/src/wlan_mlo_mgr_primary_umac.c

@@ -424,6 +424,22 @@ static QDF_STATUS mlo_set_3_link_primary_umac(
 }
 #endif
 
+#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
+QDF_STATUS mlo_peer_overwrite_primary_umac(uint8_t psoc_id,
+					   struct wlan_mlo_peer_context *ml_peer)
+{
+	if (psoc_id >= WLAN_OBJMGR_MAX_DEVICES)
+		return QDF_STATUS_E_FAILURE;
+	if (!ml_peer)
+		return QDF_STATUS_E_FAILURE;
+
+	ml_peer->primary_umac_psoc_id = psoc_id;
+	mlo_peer_assign_primary_umac(ml_peer, &ml_peer->peer_list[0]);
+
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
 QDF_STATUS mlo_peer_allocate_primary_umac(
 		struct wlan_mlo_dev_context *ml_dev,
 		struct wlan_mlo_peer_context *ml_peer,