浏览代码

qcacmn: Add support for primary TQM migration

Add support for primary TQM migration.

Change-Id: Ifd62eb7e731bbd9e86c462642fd2e20d50d5495a
CRs-Fixed: 3410900
Neha Bisht 2 年之前
父节点
当前提交
80ee0f60c6

+ 5 - 0
dp/inc/cdp_txrx_ops.h

@@ -1464,6 +1464,11 @@ struct ol_if_ops {
 				   qdf_nbuf_t nbuf,
 				   qdf_nbuf_t nbuf,
 				   uint16_t hdr_space);
 				   uint16_t hdr_space);
 
 
+#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
+	void (*update_primary_link)(struct cdp_ctrl_objmgr_psoc *psoc,
+				    uint8_t *mac_addr);
+#endif
+
 	uint8_t (*freq_to_channel)(struct cdp_ctrl_objmgr_psoc *psoc,
 	uint8_t (*freq_to_channel)(struct cdp_ctrl_objmgr_psoc *psoc,
 				   uint8_t pdev_id, uint16_t freq);
 				   uint8_t pdev_id, uint16_t freq);
 
 

+ 211 - 0
dp/wifi3.0/be/dp_be.c

@@ -2763,3 +2763,214 @@ void dp_initialize_arch_ops_be(struct dp_arch_ops *arch_ops)
 	dp_initialize_arch_ops_be_ipa(arch_ops);
 	dp_initialize_arch_ops_be_ipa(arch_ops);
 	dp_initialize_arch_ops_be_single_dev(arch_ops);
 	dp_initialize_arch_ops_be_single_dev(arch_ops);
 }
 }
+
+#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
+static void
+dp_primary_link_migration(struct dp_soc *soc, void *cb_ctxt,
+			  union hal_reo_status *reo_status)
+{
+	struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
+	struct dp_mlo_ctxt *dp_mlo = be_soc->ml_ctxt;
+	struct dp_soc *pr_soc = NULL;
+	struct dp_peer_info *pr_peer_info = (struct dp_peer_info *)cb_ctxt;
+	struct dp_peer *new_primary_peer = NULL;
+	struct dp_peer *mld_peer = NULL;
+	uint8_t primary_vdev_id;
+	struct cdp_txrx_peer_params_update params = {0};
+
+	pr_soc = dp_mlo_get_soc_ref_by_chip_id(dp_mlo, pr_peer_info->chip_id);
+	if (!pr_soc) {
+		dp_htt_err("Invalid soc");
+		qdf_mem_free(pr_peer_info);
+		return;
+	}
+
+	new_primary_peer = pr_soc->peer_id_to_obj_map[
+				pr_peer_info->primary_peer_id];
+
+	mld_peer = DP_GET_MLD_PEER_FROM_PEER(new_primary_peer);
+	if (!mld_peer) {
+		dp_htt_err("Invalid peer");
+		qdf_mem_free(pr_peer_info);
+		return;
+	}
+
+	new_primary_peer->primary_link = 1;
+
+	if (pr_soc && pr_soc->cdp_soc.ol_ops->update_primary_link)
+		pr_soc->cdp_soc.ol_ops->update_primary_link(pr_soc->ctrl_psoc,
+						new_primary_peer->mac_addr.raw);
+
+	primary_vdev_id = new_primary_peer->vdev->vdev_id;
+
+	dp_vdev_unref_delete(soc, mld_peer->vdev, DP_MOD_ID_CHILD);
+	mld_peer->vdev = dp_vdev_get_ref_by_id(pr_soc, primary_vdev_id,
+			 DP_MOD_ID_CHILD);
+	mld_peer->txrx_peer->vdev = mld_peer->vdev;
+
+	params.osif_vdev = (void *)new_primary_peer->vdev->osif_vdev;
+	params.peer_mac = new_primary_peer->mac_addr.raw;
+	params.chip_id = pr_peer_info->chip_id;
+	params.pdev_id = new_primary_peer->vdev->pdev->pdev_id;
+
+	if (new_primary_peer->vdev->opmode == wlan_op_mode_sta) {
+		dp_wdi_event_handler(
+				WDI_EVENT_STA_PRIMARY_UMAC_UPDATE,
+				pr_soc, (void *)&params,
+				new_primary_peer->peer_id,
+				WDI_NO_VAL, params.pdev_id);
+	} else {
+		dp_wdi_event_handler(
+				WDI_EVENT_PEER_PRIMARY_UMAC_UPDATE,
+				pr_soc, (void *)&params,
+				new_primary_peer->peer_id,
+				WDI_NO_VAL, params.pdev_id);
+	}
+	qdf_mem_free(pr_peer_info);
+}
+
+QDF_STATUS dp_htt_reo_migration(struct dp_soc *soc, uint16_t peer_id,
+				uint16_t ml_peer_id, uint16_t vdev_id,
+				uint8_t pdev_id, uint8_t chip_id)
+{
+	struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
+	struct dp_mlo_ctxt *dp_mlo = be_soc->ml_ctxt;
+	uint16_t mld_peer_id = dp_gen_ml_peer_id(soc, ml_peer_id);
+	struct dp_soc *pr_soc = NULL;
+	struct dp_soc *current_pr_soc = NULL;
+	struct hal_reo_cmd_params params;
+	struct dp_rx_tid *rx_tid;
+	struct dp_peer *pr_peer = NULL;
+	struct dp_peer *mld_peer = NULL;
+	struct dp_soc *mld_soc = NULL;
+	struct dp_peer *current_pr_peer = NULL;
+	struct dp_peer_info *peer_info;
+	struct dp_vdev_be *be_vdev;
+	struct cdp_ds_vp_params vp_params = {0};
+	struct cdp_soc_t *cdp_soc;
+	struct dp_soc_be *be_soc_mld = NULL;
+	struct dp_ppe_vp_profile *ppe_vp_profile;
+	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
+	uint16_t src_info;
+	QDF_STATUS status;
+
+	if (!dp_mlo) {
+		dp_htt_err("Invalid dp_mlo ctxt");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	pr_soc = dp_mlo_get_soc_ref_by_chip_id(dp_mlo, chip_id);
+	if (!pr_soc) {
+		dp_htt_err("Invalid soc");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	pr_peer = pr_soc->peer_id_to_obj_map[peer_id];
+	if (!pr_peer || !(IS_MLO_DP_LINK_PEER(pr_peer))) {
+		dp_htt_err("Invalid peer");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	mld_peer = DP_GET_MLD_PEER_FROM_PEER(pr_peer);
+
+	if (!mld_peer || (mld_peer->peer_id != mld_peer_id)) {
+		dp_htt_err("Invalid mld peer");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	current_pr_peer = dp_get_primary_link_peer_by_id(
+						pr_soc,
+						mld_peer->peer_id,
+						DP_MOD_ID_HTT);
+	if (!current_pr_peer || (current_pr_peer == pr_peer)) {
+		dp_htt_err("Invalid peer");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	be_vdev = dp_get_be_vdev_from_dp_vdev(pr_peer->vdev);
+	if (!be_vdev) {
+		dp_htt_err("Invalid be vdev");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	mld_soc = mld_peer->vdev->pdev->soc;
+	cdp_soc = &mld_soc->cdp_soc;
+	/*
+	 * Extract the VP profile from the VAP
+	 */
+	if (!cdp_soc->ol_ops->get_ppeds_profile_info_for_vap) {
+		dp_err("%pK: Register get ppeds profile info first\n", cdp_soc);
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	/*
+	 * Check if PPE DS routing is enabled on the associated vap.
+	 */
+	qdf_status = cdp_soc->ol_ops->get_ppeds_profile_info_for_vap(
+							mld_soc->ctrl_psoc,
+							pr_peer->vdev->vdev_id,
+							&vp_params);
+	if (qdf_status == QDF_STATUS_E_NULL_VALUE) {
+		dp_err("%pK: Could not find ppeds profile info \n", be_vdev);
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+	/* Check if PPE DS routing is enabled on
+	 * the associated vap.
+	 */
+	if (vp_params.ppe_vp_type != PPE_VP_USER_TYPE_DS)
+		return qdf_status;
+
+	be_soc_mld = dp_get_be_soc_from_dp_soc(mld_soc);
+	ppe_vp_profile = &be_soc_mld->ppe_vp_profile[
+				vp_params.ppe_vp_profile_idx];
+	src_info = ppe_vp_profile->vp_num;
+
+	current_pr_soc = current_pr_peer->vdev->pdev->soc;
+	/* Making existing primary peer as non primary */
+	current_pr_peer->primary_link = 0;
+	dp_peer_unref_delete(current_pr_peer, DP_MOD_ID_HTT);
+
+	dp_peer_rx_reo_shared_qaddr_delete(current_pr_soc, mld_peer);
+
+	peer_info = qdf_mem_malloc(sizeof(struct dp_peer_info));
+	if (!peer_info) {
+		dp_htt_err("Malloc failed");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	peer_info->primary_peer_id = peer_id;
+	peer_info->chip_id = chip_id;
+
+	qdf_mem_zero(&params, sizeof(params));
+
+	rx_tid = &mld_peer->rx_tid[0];
+	params.std.need_status = 1;
+	params.std.addr_lo = rx_tid->hw_qdesc_paddr & 0xffffffff;
+	params.std.addr_hi = (uint64_t)(rx_tid->hw_qdesc_paddr) >> 32;
+	params.u.fl_cache_params.flush_no_inval = 0;
+	params.u.fl_cache_params.flush_entire_cache = 1;
+	status = dp_reo_send_cmd(current_pr_soc, CMD_FLUSH_CACHE, &params,
+				 dp_primary_link_migration,
+				 (void *)peer_info);
+
+	if (status != QDF_STATUS_SUCCESS) {
+		dp_htt_err("Reo flush failed");
+		qdf_mem_free(peer_info);
+		dp_h2t_ptqm_migration_msg_send(pr_soc, vdev_id, pdev_id,
+					       chip_id, peer_id, ml_peer_id,
+					       src_info, QDF_STATUS_E_FAILURE);
+	}
+
+	qdf_mem_zero(&params, sizeof(params));
+	params.std.need_status = 0;
+	params.std.addr_lo = rx_tid->hw_qdesc_paddr & 0xffffffff;
+	params.std.addr_hi = (uint64_t)(rx_tid->hw_qdesc_paddr) >> 32;
+	params.u.unblk_cache_params.type = UNBLOCK_CACHE;
+	dp_reo_send_cmd(current_pr_soc, CMD_UNBLOCK_CACHE, &params, NULL, NULL);
+
+	dp_h2t_ptqm_migration_msg_send(pr_soc, vdev_id, pdev_id,
+				       chip_id, peer_id, ml_peer_id,
+				       src_info, QDF_STATUS_SUCCESS);
+	return QDF_STATUS_SUCCESS;
+}
+#endif

+ 143 - 0
dp/wifi3.0/dp_htt.c

@@ -2404,6 +2404,105 @@ dp_pktlog_msg_handler(struct htt_soc *soc,
 }
 }
 #endif
 #endif
 
 
+#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
+QDF_STATUS
+dp_h2t_ptqm_migration_msg_send(struct dp_soc *dp_soc, uint16_t vdev_id,
+			       uint8_t pdev_id,
+			       uint8_t chip_id, uint16_t peer_id,
+			       uint16_t ml_peer_id, uint16_t src_info,
+			       QDF_STATUS status)
+{
+	struct htt_soc *soc = dp_soc->htt_handle;
+	struct dp_htt_htc_pkt *pkt;
+	uint8_t *htt_logger_bufp;
+	qdf_nbuf_t msg;
+	uint32_t *msg_word;
+	QDF_STATUS ret = QDF_STATUS_SUCCESS;
+
+	msg = qdf_nbuf_alloc(
+			soc->osdev,
+			HTT_MSG_BUF_SIZE(HTT_H2T_REO_MIGRATION_RESP_MSG_SZ),
+			HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE);
+
+	if (!msg)
+		return QDF_STATUS_E_NOMEM;
+
+	/*
+	 * Set the length of the message.
+	 * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
+	 * separately during the below call to qdf_nbuf_push_head.
+	 * The contribution from the HTC header is added separately inside HTC.
+	 */
+	if (qdf_nbuf_put_tail(msg, HTT_H2T_REO_MIGRATION_RESP_MSG_SZ)
+			      == NULL) {
+		dp_htt_err("Failed to expand head for"
+			   "HTT_H2T_MSG_TYPE_PRIMARY_LINK_PEER_MIGRATE_RESP");
+		qdf_nbuf_free(msg);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	msg_word = (uint32_t *)qdf_nbuf_data(msg);
+	memset(msg_word, 0, HTT_H2T_REO_MIGRATION_RESP_MSG_SZ);
+
+	qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
+	htt_logger_bufp = (uint8_t *)msg_word;
+	*msg_word = 0;
+	HTT_H2T_MSG_TYPE_SET(*msg_word,
+			     HTT_H2T_MSG_TYPE_PRIMARY_LINK_PEER_MIGRATE_RESP);
+	HTT_H2T_PRIMARY_LINK_PEER_MIGRATE_PDEV_ID_SET(*msg_word, pdev_id);
+	HTT_H2T_PRIMARY_LINK_PEER_MIGRATE_CHIP_ID_SET(*msg_word, chip_id);
+	HTT_H2T_PRIMARY_LINK_PEER_MIGRATE_VDEV_ID_SET(*msg_word, vdev_id);
+
+	/* word 1 */
+	msg_word++;
+	*msg_word = 0;
+	HTT_H2T_PRIMARY_LINK_PEER_MIGRATE_SW_LINK_PEER_ID_SET(*msg_word,
+							      peer_id);
+	HTT_H2T_PRIMARY_LINK_PEER_MIGRATE_ML_PEER_ID_SET(*msg_word,
+							 ml_peer_id);
+
+	/* word 1 */
+	msg_word++;
+	*msg_word = 0;
+	HTT_H2T_PRIMARY_LINK_PEER_MIGRATE_SRCINFO_SET(*msg_word,
+						      src_info);
+	HTT_H2T_PRIMARY_LINK_PEER_MIGRATE_STATUS_SET(*msg_word,
+						     status);
+
+	pkt = htt_htc_pkt_alloc(soc);
+	if (!pkt) {
+		dp_htt_err("Fail to allocate dp_htt_htc_pkt buffer");
+		qdf_nbuf_free(msg);
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	pkt->soc_ctxt = NULL;
+
+	/* macro to set packet parameters for TX */
+	SET_HTC_PACKET_INFO_TX(
+			&pkt->htc_pkt,
+			dp_htt_h2t_send_complete_free_netbuf,
+			qdf_nbuf_data(msg),
+			qdf_nbuf_len(msg),
+			soc->htc_endpoint,
+			HTC_TX_PACKET_TAG_RUNTIME_PUT);
+
+	SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
+
+	ret = DP_HTT_SEND_HTC_PKT(
+			soc, pkt,
+			HTT_H2T_MSG_TYPE_PRIMARY_LINK_PEER_MIGRATE_RESP,
+			htt_logger_bufp);
+
+	if (ret != QDF_STATUS_SUCCESS) {
+		qdf_nbuf_free(msg);
+		htt_htc_pkt_free(soc, pkt);
+	}
+
+	return ret;
+}
+#endif
+
 #ifdef QCA_VDEV_STATS_HW_OFFLOAD_SUPPORT
 #ifdef QCA_VDEV_STATS_HW_OFFLOAD_SUPPORT
 /**
 /**
  * dp_vdev_txrx_hw_stats_handler - Handle vdev stats received from FW
  * dp_vdev_txrx_hw_stats_handler - Handle vdev stats received from FW
@@ -3226,6 +3325,40 @@ static void dp_htt_mlo_peer_map_handler(struct htt_soc *soc,
 				   mlo_flow_info, mlo_link_info);
 				   mlo_flow_info, mlo_link_info);
 }
 }
 
 
+#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
+static void dp_htt_t2h_primary_link_migration(struct htt_soc *soc,
+					      uint32_t *msg_word)
+{
+	u_int16_t peer_id;
+	u_int16_t ml_peer_id;
+	u_int16_t vdev_id;
+	u_int8_t pdev_id;
+	u_int8_t chip_id;
+
+	vdev_id = HTT_T2H_PRIMARY_LINK_PEER_MIGRATE_VDEV_ID_GET(
+			*msg_word);
+	pdev_id = HTT_T2H_PRIMARY_LINK_PEER_MIGRATE_PDEV_ID_GET(
+			*msg_word);
+	chip_id = HTT_T2H_PRIMARY_LINK_PEER_MIGRATE_CHIP_ID_GET(
+			*msg_word);
+	ml_peer_id = HTT_T2H_PRIMARY_LINK_PEER_MIGRATE_ML_PEER_ID_GET(
+			*(msg_word + 1));
+	peer_id = HTT_T2H_PRIMARY_LINK_PEER_MIGRATE_SW_LINK_PEER_ID_GET(
+			*(msg_word + 1));
+
+	dp_htt_info("HTT_T2H_MSG_TYPE_PRIMARY_PEER_MIGRATE_IND msg"
+		    "for peer id %d vdev id %d", peer_id, vdev_id);
+
+	dp_htt_reo_migration(soc->dp_soc, peer_id, ml_peer_id,
+			vdev_id, pdev_id, chip_id);
+}
+#else
+static void dp_htt_t2h_primary_link_migration(struct htt_soc *soc,
+					      uint32_t *msg_word)
+{
+}
+#endif
+
 static void dp_htt_mlo_peer_unmap_handler(struct htt_soc *soc,
 static void dp_htt_mlo_peer_unmap_handler(struct htt_soc *soc,
 					  uint32_t *msg_word)
 					  uint32_t *msg_word)
 {
 {
@@ -3319,6 +3452,11 @@ dp_rx_mlo_timestamp_ind_handler(void *soc_handle,
 {
 {
 	qdf_assert_always(0);
 	qdf_assert_always(0);
 }
 }
+
+static void dp_htt_t2h_primary_link_migration(struct htt_soc *soc,
+					      uint32_t *msg_word)
+{
+}
 #endif
 #endif
 
 
 /**
 /**
@@ -3884,6 +4022,11 @@ void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt)
 
 
 		break;
 		break;
 	}
 	}
+	case HTT_T2H_MSG_TYPE_PRIMARY_LINK_PEER_MIGRATE_IND:
+	{
+		dp_htt_t2h_primary_link_migration(soc, msg_word);
+		break;
+	}
 	case HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP:
 	case HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP:
 	{
 	{
 		dp_htt_mlo_peer_map_handler(soc, msg_word);
 		dp_htt_mlo_peer_map_handler(soc, msg_word);

+ 47 - 0
dp/wifi3.0/dp_htt.h

@@ -1199,4 +1199,51 @@ dp_htt_get_mon_htt_ring_id(struct dp_soc *soc,
 QDF_STATUS htt_h2t_rx_cce_super_rule_setup(struct htt_soc *htt_soc,
 QDF_STATUS htt_h2t_rx_cce_super_rule_setup(struct htt_soc *htt_soc,
 					   void *flt_params);
 					   void *flt_params);
 #endif
 #endif
+
+#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
+/**
+ * struct dp_peer_info - Primary Peer information
+ * @primary_peer_id: Primary peer id
+ * @chip_id: Chip id of primary peer
+ */
+struct dp_peer_info {
+	uint16_t primary_peer_id;
+	uint8_t chip_id;
+};
+
+/**
+ * dp_h2t_ptqm_migration_msg_send() - Send H2T PTQM message to FW
+ * @dp_soc: DP SOC handle
+ * @vdev_id: Vdev id of primary peer
+ * @pdev_id: Pdev id of primary peer
+ * @chip_id: Chip id of primary peer
+ * @peer_id: Peer id of primary peer
+ * @ml_peer_id: Peer id of MLD peer
+ * @src_info: source info for DS
+ * @status: success or failure status of PTQM migration
+ *
+ * Return: Success when HTT message is sent, error on failure
+ */
+QDF_STATUS
+dp_h2t_ptqm_migration_msg_send(struct dp_soc *dp_soc, uint16_t vdev_id,
+			       uint8_t pdev_id,
+			       uint8_t chip_id, uint16_t peer_id,
+			       uint16_t ml_peer_id, uint16_t src_info,
+			       QDF_STATUS status);
+
+/**
+ * dp_htt_reo_migration() - Reo migration API
+ * @soc: DP SOC handle
+ * @peer_id: Peer id of primary peer
+ * @ml_peer_id: Peer id of MLD peer
+ * @vdev_id: Vdev id of primary peer
+ * @pdev_id: Pdev id of primary peer
+ * @chip_id: Chip id of primary peer
+ *
+ * Return: Success if migration completes, error on failure
+ */
+QDF_STATUS dp_htt_reo_migration(struct dp_soc *soc, uint16_t peer_id,
+				uint16_t ml_peer_id, uint16_t vdev_id,
+				uint8_t pdev_id, uint8_t chip_id);
+#endif
 #endif /* _DP_HTT_H_ */
 #endif /* _DP_HTT_H_ */

+ 2 - 4
dp/wifi3.0/dp_peer.c

@@ -2704,14 +2704,12 @@ static inline struct dp_peer *dp_peer_find_add_id(struct dp_soc *soc,
 
 
 #ifdef WLAN_FEATURE_11BE_MLO
 #ifdef WLAN_FEATURE_11BE_MLO
 #ifdef DP_USE_REDUCED_PEER_ID_FIELD_WIDTH
 #ifdef DP_USE_REDUCED_PEER_ID_FIELD_WIDTH
-static inline uint16_t dp_gen_ml_peer_id(struct dp_soc *soc,
-					 uint16_t peer_id)
+uint16_t dp_gen_ml_peer_id(struct dp_soc *soc, uint16_t peer_id)
 {
 {
 	return ((peer_id & soc->peer_id_mask) | (1 << soc->peer_id_shift));
 	return ((peer_id & soc->peer_id_mask) | (1 << soc->peer_id_shift));
 }
 }
 #else
 #else
-static inline uint16_t dp_gen_ml_peer_id(struct dp_soc *soc,
-					 uint16_t peer_id)
+uint16_t dp_gen_ml_peer_id(struct dp_soc *soc, uint16_t peer_id)
 {
 {
 	return (peer_id | (1 << HTT_RX_PEER_META_DATA_V1_ML_PEER_VALID_S));
 	return (peer_id | (1 << HTT_RX_PEER_META_DATA_V1_ML_PEER_VALID_S));
 }
 }

+ 10 - 0
dp/wifi3.0/dp_peer.h

@@ -2462,4 +2462,14 @@ static inline void dp_peer_rx_reo_shared_qaddr_delete(struct dp_soc *soc,
  * Return: True for WDS ext peer, false otherwise
  * Return: True for WDS ext peer, false otherwise
  */
  */
 bool dp_peer_check_wds_ext_peer(struct dp_peer *peer);
 bool dp_peer_check_wds_ext_peer(struct dp_peer *peer);
+
+/**
+ * dp_gen_ml_peer_id() - Generate MLD peer id for DP
+ *
+ * @soc: DP soc context
+ * @peer_id: mld peer id
+ *
+ * Return: DP MLD peer id
+ */
+uint16_t dp_gen_ml_peer_id(struct dp_soc *soc, uint16_t peer_id);
 #endif /* _DP_PEER_H_ */
 #endif /* _DP_PEER_H_ */

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

@@ -649,4 +649,16 @@ mlo_peer_free_auth_param(struct mlpeer_auth_params *auth_params)
  * Return: true, if MLO peer can be deleted
  * Return: true, if MLO peer can be deleted
  */
  */
 bool wlan_mlo_partner_peer_delete_is_allowed(struct wlan_objmgr_peer *src_peer);
 bool wlan_mlo_partner_peer_delete_is_allowed(struct wlan_objmgr_peer *src_peer);
+
+#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
+/**
+ * wlan_objmgr_mlo_update_primary_info() - Update is_primary flag
+ * @peer: new primary link peer object
+ *
+ * API to update is_primary flag in peer list
+ *
+ * Return: void
+ */
+void wlan_objmgr_mlo_update_primary_info(struct wlan_objmgr_peer *peer);
+#endif
 #endif
 #endif

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

@@ -1611,3 +1611,29 @@ bool wlan_mlo_partner_peer_delete_is_allowed(struct wlan_objmgr_peer *src_peer)
 	return true;
 	return true;
 }
 }
 #endif
 #endif
+
+#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
+void wlan_objmgr_mlo_update_primary_info(struct wlan_objmgr_peer *peer)
+{
+	struct wlan_mlo_peer_context *ml_peer = NULL;
+	struct wlan_mlo_link_peer_entry *peer_ent_iter;
+	uint8_t i;
+
+	ml_peer = peer->mlo_peer_ctx;
+
+	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
+		peer_ent_iter = &ml_peer->peer_list[i];
+
+		if (!peer_ent_iter->link_peer)
+			continue;
+
+		if (peer_ent_iter->is_primary)
+			peer_ent_iter->is_primary = false;
+
+		if (peer_ent_iter->link_peer == peer)
+			peer_ent_iter->is_primary = true;
+	}
+}
+
+qdf_export_symbol(wlan_objmgr_mlo_update_primary_info);
+#endif