Просмотр исходного кода

qcacmn: add MLME changes for ML reconfig

1) add op flags to indicate Link removal in progress
2) update API to include link removal check for ML peer create
3) add API to check whether all link peers to be deleted.

CRs-Fixed: 3341256
Change-Id: I8fabd19d3321315eb13d874a7e9b2e93392a7886
Srinivas Pitla 2 лет назад
Родитель
Сommit
3bae1f975c

+ 6 - 0
umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h

@@ -227,6 +227,12 @@
  * Broadcast TWT element
  */
 #define WLAN_VDEV_OP_CU_CAT2                0x00100000
+  /* for mlo reconfig link removal functionality */
+#define WLAN_VDEV_OP_MLO_STOP_LINK_DEL      0x00200000
+  /* for mlo reconfig link add functionality */
+#define WLAN_VDEV_OP_MLO_LINK_ADD           0x00400000
+  /* for mlo reconfig link removal TBTT complete */
+#define WLAN_VDEV_OP_MLO_LINK_TBTT_COMPLETE 0x00800000
 
  /* CAPABILITY: IBSS available */
 #define WLAN_VDEV_C_IBSS                    0x00000001

+ 11 - 4
umac/mlme/vdev_mgr/dispatcher/src/wlan_vdev_mlme_api.c

@@ -235,10 +235,11 @@ QDF_STATUS wlan_vdev_is_mlo_peer_create_allowed(struct wlan_objmgr_vdev *vdev)
 	enum wlan_vdev_state substate;
 	bool acs_in_progress;
 	QDF_STATUS ret;
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
 
 	if (!vdev) {
 		mlme_err("vdev is null");
-		return QDF_STATUS_E_FAILURE;
+		return status;
 	}
 
 	state = wlan_vdev_mlme_get_state(vdev);
@@ -248,7 +249,7 @@ QDF_STATUS wlan_vdev_is_mlo_peer_create_allowed(struct wlan_objmgr_vdev *vdev)
 	ret = mlme_ext_hdl_get_acs_in_progress(vdev, &acs_in_progress);
 	if (ret != QDF_STATUS_SUCCESS) {
 		mlme_err("Unable to get ACS in progress status");
-		return QDF_STATUS_E_FAILURE;
+		return status;
 	}
 
 	if (!acs_in_progress)
@@ -256,9 +257,15 @@ QDF_STATUS wlan_vdev_is_mlo_peer_create_allowed(struct wlan_objmgr_vdev *vdev)
 		    ((state == WLAN_VDEV_S_SUSPEND) &&
 		     (substate == WLAN_VDEV_SS_SUSPEND_CSA_RESTART)) ||
 		    (state == WLAN_VDEV_S_DFS_CAC_WAIT))
-			return QDF_STATUS_SUCCESS;
+			status = QDF_STATUS_SUCCESS;
 
-	return QDF_STATUS_E_FAILURE;
+	/* with link rejection feature, this check can be removed */
+	if (wlan_vdev_mlme_op_flags_get(vdev, WLAN_VDEV_OP_MLO_STOP_LINK_DEL) ||
+	    wlan_vdev_mlme_op_flags_get(vdev,
+					WLAN_VDEV_OP_MLO_LINK_TBTT_COMPLETE))
+		status = QDF_STATUS_E_FAILURE;
+
+	return status;
 }
 
 QDF_STATUS wlan_vdev_is_restart_progress(struct wlan_objmgr_vdev *vdev)

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

@@ -59,6 +59,25 @@ void mlo_ap_get_vdev_list(struct wlan_objmgr_vdev *vdev,
 			  uint16_t *vdev_count,
 			  struct wlan_objmgr_vdev **wlan_vdev_list);
 
+/**
+ * mlo_ap_get_active_vdev_list() - get mlo vdev list
+ * @vdev: vdev pointer
+ * @vdev_count: vdev count
+ * @wlan_vdev_list: vdev list
+ *
+ * This API gets all active partner vdev's which have WLAN_VDEV_FEXT2_MLO bit
+ * set.
+ *
+ * It takes references for all vdev's with bit set in the list. Callers
+ * of this API should properly release references before destroying the
+ * list.
+ *
+ * Return: None
+ */
+void mlo_ap_get_active_vdev_list(struct wlan_objmgr_vdev *vdev,
+				 uint16_t *vdev_count,
+				 struct wlan_objmgr_vdev **wlan_vdev_list);
+
 /**
  * mlo_ap_get_partner_vdev_list_from_mld() - get partner vdev from MLD
  *                                           vdev_list without checking
@@ -531,4 +550,13 @@ QDF_STATUS mlo_peer_create_get_frm_buf(
 		struct wlan_mlo_peer_context *ml_peer,
 		struct peer_create_notif_s *peer_create,
 		qdf_nbuf_t frm_buf);
+
+/**
+ * wlan_mlo_ap_get_active_links() - Get number of active link VDEVs of MLD
+ * @vdev: vdev pointer
+ *
+ * Return: active vdev count.
+ */
+uint16_t wlan_mlo_ap_get_active_links(struct wlan_objmgr_vdev *vdev);
+
 #endif

+ 2 - 1
umac/mlo_mgr/inc/wlan_mlo_mgr_cmn.h

@@ -243,10 +243,11 @@ qdf_nbuf_t mlo_mlme_get_link_assoc_req(struct wlan_objmgr_peer *peer,
 /**
  * mlo_mlme_peer_deauth() - Initiate deauth on link peer
  * @peer: Object manager peer
+ * @is_disassoc: disassoc frame needs to be sent
  *
  * Return: void
  */
-void mlo_mlme_peer_deauth(struct wlan_objmgr_peer *peer);
+void mlo_mlme_peer_deauth(struct wlan_objmgr_peer *peer, uint8_t is_disassoc);
 
 #ifdef UMAC_MLO_AUTH_DEFER
 /**

+ 2 - 0
umac/mlo_mgr/inc/wlan_mlo_mgr_msgq.h

@@ -98,9 +98,11 @@ struct peer_discon_notify_s {
 /*
  * struct peer_deauth_notify_s - MLO partner peer deauth notification
  * @peer: Link peer on which Peer deauth to be sent
+ * @is_disassoc: flag indicates that disassoc frame needs to be sent
  */
 struct peer_deauth_notify_s {
 	struct wlan_objmgr_peer *peer;
+	uint8_t is_disassoc;
 };
 
 /*

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

@@ -186,12 +186,17 @@ void wlan_mlo_partner_peer_assoc_post(struct wlan_objmgr_peer *assoc_peer);
 /**
  * wlan_mlo_peer_deauth_init() - Initiate Deauth of MLO peer
  * @ml_peer: MLO peer
+ * @src_peer: Source peer, if this pointer is valid, send deauth on other link
+ * @is_disassoc: to indicate, whether Disassoc to be sent instead of deauth
  *
  * This function initiates deauth on MLO peer and its links peers
  *
  * Return: void
  */
-void wlan_mlo_peer_deauth_init(struct wlan_mlo_peer_context *ml_peer);
+void
+wlan_mlo_peer_deauth_init(struct wlan_mlo_peer_context *ml_peer,
+			  struct wlan_objmgr_peer *src_peer,
+			  uint8_t is_disassoc);
 
 /**
  * wlan_mlo_partner_peer_create_failed_notify() - Notify peer creation fail
@@ -580,4 +585,15 @@ mlo_peer_free_auth_param(struct mlpeer_auth_params *auth_params)
 {
 }
 #endif
+
+/**
+ * wlan_mlo_partner_peer_delete_is_allowed() - Checks MLO peer delete is allowed
+ * @src_peer: Link peer
+ *
+ * This function checks whether MLO peer can be deleted along with link peer
+ * delete in link removal cases
+ *
+ * Return: true, if MLO peer can be deleted
+ */
+bool wlan_mlo_partner_peer_delete_is_allowed(struct wlan_objmgr_peer *src_peer);
 #endif

+ 2 - 1
umac/mlo_mgr/inc/wlan_mlo_mgr_public_structs.h

@@ -817,7 +817,8 @@ struct mlo_mlme_ext_ops {
 	void (*mlo_mlme_ext_assoc_resp)(struct wlan_objmgr_peer *peer);
 	qdf_nbuf_t (*mlo_mlme_get_link_assoc_req)(struct wlan_objmgr_peer *peer,
 						  uint8_t link_ix);
-	void (*mlo_mlme_ext_deauth)(struct wlan_objmgr_peer *peer);
+	void (*mlo_mlme_ext_deauth)(struct wlan_objmgr_peer *peer,
+				    uint8_t is_disassoc);
 	QDF_STATUS (*mlo_mlme_ext_clone_security_param)(
 		    struct vdev_mlme_obj *vdev_mlme,
 		    struct wlan_cm_connect_req *req);

+ 66 - 10
umac/mlo_mgr/src/wlan_mlo_mgr_ap.c

@@ -135,6 +135,45 @@ void mlo_ap_get_vdev_list(struct wlan_objmgr_vdev *vdev,
 	mlo_dev_lock_release(dev_ctx);
 }
 
+void mlo_ap_get_active_vdev_list(struct wlan_objmgr_vdev *vdev,
+				 uint16_t *vdev_count,
+				 struct wlan_objmgr_vdev **wlan_vdev_list)
+{
+	struct wlan_mlo_dev_context *dev_ctx;
+	int i;
+	QDF_STATUS status;
+	struct wlan_objmgr_vdev *partner_vdev = NULL;
+
+	*vdev_count = 0;
+
+	if (!vdev || !vdev->mlo_dev_ctx) {
+		mlo_err("Invalid input");
+		return;
+	}
+
+	dev_ctx = vdev->mlo_dev_ctx;
+
+	mlo_dev_lock_acquire(dev_ctx);
+	*vdev_count = 0;
+	for (i = 0; i < QDF_ARRAY_SIZE(dev_ctx->wlan_vdev_list); i++) {
+		partner_vdev = dev_ctx->wlan_vdev_list[i];
+		if (partner_vdev &&
+		    wlan_vdev_mlme_is_mlo_ap(partner_vdev)) {
+			if (wlan_vdev_chan_config_valid(partner_vdev) !=
+						 QDF_STATUS_SUCCESS)
+				continue;
+
+			status = wlan_objmgr_vdev_try_get_ref(partner_vdev,
+							      WLAN_MLO_MGR_ID);
+			if (QDF_IS_STATUS_ERROR(status))
+				break;
+			wlan_vdev_list[*vdev_count] = partner_vdev;
+			(*vdev_count) += 1;
+		}
+	}
+	mlo_dev_lock_release(dev_ctx);
+}
+
 void mlo_ap_get_partner_vdev_list_from_mld(
 		struct wlan_objmgr_vdev *vdev,
 		uint16_t *vdev_count,
@@ -199,22 +238,15 @@ static QDF_STATUS mlo_ap_vdev_is_start_resp_rcvd(struct wlan_objmgr_vdev *vdev)
 	return QDF_STATUS_E_FAILURE;
 }
 
-/**
- * mlo_is_ap_vdev_up_allowed() - Is mlo ap allowed to come up
- * @vdev: vdev pointer
- *
- * Return: true if given ap is allowed to up, false otherwise.
- */
-static bool mlo_is_ap_vdev_up_allowed(struct wlan_objmgr_vdev *vdev)
+uint16_t wlan_mlo_ap_get_active_links(struct wlan_objmgr_vdev *vdev)
 {
 	uint16_t vdev_count = 0;
 	struct wlan_mlo_dev_context *dev_ctx;
 	int i;
-	bool up_allowed = false;
 
 	if (!vdev || !vdev->mlo_dev_ctx || !vdev->mlo_dev_ctx->ap_ctx) {
 		mlo_err("Invalid input");
-		return up_allowed;
+		return vdev_count;
 	}
 
 	dev_ctx = vdev->mlo_dev_ctx;
@@ -226,9 +258,33 @@ static bool mlo_is_ap_vdev_up_allowed(struct wlan_objmgr_vdev *vdev)
 			vdev_count++;
 	}
 
+	mlo_dev_lock_release(dev_ctx);
+
+	return vdev_count;
+}
+
+/**
+ * mlo_is_ap_vdev_up_allowed() - Is mlo ap allowed to come up
+ * @vdev: vdev pointer
+ *
+ * Return: true if given ap is allowed to up, false otherwise.
+ */
+static bool mlo_is_ap_vdev_up_allowed(struct wlan_objmgr_vdev *vdev)
+{
+	uint16_t vdev_count = 0;
+	bool up_allowed = false;
+	struct wlan_mlo_dev_context *dev_ctx;
+
+	if (!vdev) {
+		mlo_err("Invalid input");
+		return up_allowed;
+	}
+
+	dev_ctx = vdev->mlo_dev_ctx;
+
+	vdev_count = wlan_mlo_ap_get_active_links(vdev);
 	if (vdev_count == dev_ctx->ap_ctx->num_ml_vdevs)
 		up_allowed = true;
-	mlo_dev_lock_release(dev_ctx);
 
 	return up_allowed;
 }

+ 2 - 2
umac/mlo_mgr/src/wlan_mlo_mgr_cmn.c

@@ -259,7 +259,7 @@ qdf_nbuf_t mlo_mlme_get_link_assoc_req(struct wlan_objmgr_peer *peer,
 	return mlo_ctx->mlme_ops->mlo_mlme_get_link_assoc_req(peer, link_ix);
 }
 
-void mlo_mlme_peer_deauth(struct wlan_objmgr_peer *peer)
+void mlo_mlme_peer_deauth(struct wlan_objmgr_peer *peer, uint8_t is_disassoc)
 {
 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
 
@@ -267,7 +267,7 @@ void mlo_mlme_peer_deauth(struct wlan_objmgr_peer *peer)
 	    !mlo_ctx->mlme_ops->mlo_mlme_ext_deauth)
 		return;
 
-	mlo_ctx->mlme_ops->mlo_mlme_ext_deauth(peer);
+	mlo_ctx->mlme_ops->mlo_mlme_ext_deauth(peer, is_disassoc);
 }
 
 #ifdef UMAC_MLO_AUTH_DEFER

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

@@ -69,7 +69,8 @@ QDF_STATUS mlo_msgq_post(enum mlo_msg_type type,
 
 	case MLO_PEER_DEAUTH:
 		peer_deauth = (struct peer_deauth_notify_s *)payload;
-		mlo_mlme_peer_deauth(peer_deauth->peer);
+		mlo_mlme_peer_deauth(peer_deauth->peer,
+				     peer_deauth->is_disassoc);
 		wlan_objmgr_peer_release_ref(peer_deauth->peer,
 					     WLAN_MLO_MGR_ID);
 		break;
@@ -194,6 +195,7 @@ QDF_STATUS mlo_msgq_post(enum mlo_msg_type type,
 		peer_deauth = &msg->m.peer_deauth;
 		peer_deauth_l = (struct peer_deauth_notify_s *)payload;
 		peer_deauth->peer = peer_deauth_l->peer;
+		peer_deauth->is_disassoc = peer_deauth_l->is_disassoc;
 		break;
 
 	case MLO_PEER_PENDING_AUTH:

+ 51 - 12
umac/mlo_mgr/src/wlan_mlo_mgr_peer.c

@@ -120,12 +120,14 @@ static void mlo_link_peer_disconnect_notify(struct wlan_mlo_dev_context *ml_dev,
 }
 
 static void mlo_link_peer_deauth_init(struct wlan_mlo_dev_context *ml_dev,
-				      struct wlan_objmgr_peer *peer)
+				      struct wlan_objmgr_peer *peer,
+				      uint8_t is_disassoc)
 {
 	struct peer_deauth_notify_s peer_deauth;
 	QDF_STATUS status;
 
 	peer_deauth.peer = peer;
+	peer_deauth.is_disassoc = is_disassoc;
 	status = mlo_msgq_post(MLO_PEER_DEAUTH, ml_dev, &peer_deauth);
 	if (status != QDF_STATUS_SUCCESS)
 		wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
@@ -312,13 +314,16 @@ void wlan_mlo_partner_peer_assoc_post(struct wlan_objmgr_peer *assoc_peer)
 }
 
 void
-wlan_mlo_peer_deauth_init(struct wlan_mlo_peer_context *ml_peer)
+wlan_mlo_peer_deauth_init(struct wlan_mlo_peer_context *ml_peer,
+			  struct wlan_objmgr_peer *src_peer,
+			  uint8_t is_disassoc)
 {
 	struct wlan_mlo_dev_context *ml_dev;
 	struct wlan_objmgr_peer *link_peer;
 	struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS];
 	struct wlan_mlo_link_peer_entry *peer_entry;
 	uint16_t i;
+	uint8_t deauth_sent = 0;
 
 	if (!ml_peer)
 		return;
@@ -356,10 +361,15 @@ wlan_mlo_peer_deauth_init(struct wlan_mlo_peer_context *ml_peer)
 			continue;
 
 		/* Prepare and queue message */
-		if (i == 0)
-			mlo_link_peer_deauth_init(ml_dev, link_peers[i]);
-		else
+		/* skip sending deauth on src peer */
+		if ((deauth_sent) ||
+		    (src_peer && (src_peer == link_peers[i]))) {
 			mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]);
+		} else {
+			mlo_link_peer_deauth_init(ml_dev, link_peers[i],
+						  is_disassoc);
+			deauth_sent = 1;
+		}
 	}
 
 	return;
@@ -429,6 +439,10 @@ void wlan_mlo_partner_peer_disconnect_notify(struct wlan_objmgr_peer *src_peer)
 	if (!ml_peer)
 		return;
 
+	vdev = wlan_peer_get_vdev(src_peer);
+	if (!vdev)
+		return;
+
 	mlo_peer_lock_acquire(ml_peer);
 
 	if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) {
@@ -438,8 +452,7 @@ void wlan_mlo_partner_peer_disconnect_notify(struct wlan_objmgr_peer *src_peer)
 
 	ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED;
 
-	vdev = wlan_peer_get_vdev(src_peer);
-	if (!vdev || wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
+	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) {
 		mlo_peer_lock_release(ml_peer);
 		return;
 	}
@@ -672,11 +685,6 @@ static QDF_STATUS mlo_peer_detach_link_peer(
 
 	mlo_peer_lock_acquire(ml_peer);
 
-	if (ml_peer->mlpeer_state != ML_PEER_DISCONN_INITIATED) {
-		mlo_peer_lock_release(ml_peer);
-		return status;
-	}
-
 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
 		peer_entry = &ml_peer->peer_list[i];
 		if (!peer_entry->link_peer)
@@ -1317,4 +1325,35 @@ QDF_STATUS mlo_peer_link_auth_defer(struct wlan_mlo_peer_context *ml_peer,
 
 	return status;
 }
+
+bool wlan_mlo_partner_peer_delete_is_allowed(struct wlan_objmgr_peer *src_peer)
+{
+	struct wlan_objmgr_vdev *vdev = NULL;
+	struct wlan_mlo_peer_context *ml_peer;
+
+	vdev = wlan_peer_get_vdev(src_peer);
+	if (!vdev)
+		return false;
+
+	ml_peer = src_peer->mlo_peer_ctx;
+	if (!wlan_peer_is_mlo(src_peer) || !ml_peer)
+		return false;
+
+	if (wlan_vdev_mlme_op_flags_get(vdev, WLAN_VDEV_OP_MLO_STOP_LINK_DEL) ||
+	    wlan_vdev_mlme_op_flags_get(vdev,
+					WLAN_VDEV_OP_MLO_LINK_TBTT_COMPLETE)) {
+		/* Single LINK MLO connection */
+		if (ml_peer->link_peer_cnt == 1)
+			return false;
+		/*
+		 * If this link is primary TQM, then delete MLO connection till
+		 * primary umac migration is implemented
+		 */
+		if (wlan_mlo_peer_get_primary_peer_link_id(src_peer) !=
+			wlan_vdev_get_link_id(vdev))
+			return false;
+	}
+
+	return true;
+}
 #endif