Bläddra i källkod

qcacmn: Support HW Tx delay for MLO

Add delta_tqm, delta_tsf2 and mlo timestamp offset for BE.
These offsets are used to calculate hardware Tx completion delay.
delta_tsf2 and delta_tqm are updated during init. mlo timestamp
offset is updated whenever target sends the update event.

Also, adding CDP ops to set the offsets.

Change-Id: I55665982798c3a795481fa96c023bb851ea17476
CRs-Fixed: 3220906
Ripan Deuri 3 år sedan
förälder
incheckning
b8fadd7061

+ 47 - 1
dp/inc/cdp_txrx_mlo.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 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
@@ -107,4 +107,50 @@ static inline void cdp_mlo_setup_complete(ol_txrx_soc_handle soc,
 
 	soc->ops->mlo_ops->mlo_setup_complete(mlo_ctx);
 }
+
+/*
+ * cdp_mlo_update_delta_tsf2 - Update delta_tsf2
+ * @soc: soc handle
+ * @pdev_id: pdev id
+ * @delta_tsf2: delta_tsf2
+ *
+ * return: none
+ */
+static inline void cdp_mlo_update_delta_tsf2(ol_txrx_soc_handle soc,
+					     uint8_t pdev_id,
+					     uint64_t delta_tsf2)
+{
+	if (!soc || !soc->ops) {
+		QDF_BUG(0);
+		return;
+	}
+
+	if (!soc->ops->mlo_ops ||
+	    !soc->ops->mlo_ops->mlo_update_delta_tsf2)
+		return;
+
+	soc->ops->mlo_ops->mlo_update_delta_tsf2(soc, pdev_id, delta_tsf2);
+}
+
+/*
+ * cdp_mlo_update_delta_tqm - Update delta_tqm
+ * @soc: soc handle
+ * @delta_tqm: delta_tqm
+ *
+ * return: none
+ */
+static inline void cdp_mlo_update_delta_tqm(ol_txrx_soc_handle soc,
+					    uint64_t delta_tqm)
+{
+	if (!soc || !soc->ops) {
+		QDF_BUG(0);
+		return;
+	}
+
+	if (!soc->ops->mlo_ops ||
+	    !soc->ops->mlo_ops->mlo_update_delta_tqm)
+		return;
+
+	soc->ops->mlo_ops->mlo_update_delta_tqm(soc, delta_tqm);
+}
 #endif /*_CDP_TXRX_MLO_H_*/

+ 10 - 0
dp/inc/cdp_txrx_ops.h

@@ -141,6 +141,9 @@ enum cdp_peer_txq_flush_policy {
  * @mlo_soc_setup: setup DP mlo for SOC
  * @mlo_soc_teardown: teardown DP mlo for SOC
  * @mlo_setup_complete: indication to DP that all SOCs mlo is setup
+ * @mlo_update_delta_tsf2: update delta tsf2 for link
+ * @mlo_update_delta_tqm: update delta tqm for SOC
+ * @mlo_update_mlo_ts_offset: update MLO timestamp offset for SOC
  */
 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
 struct cdp_mlo_ops {
@@ -152,6 +155,13 @@ struct cdp_mlo_ops {
 					   int8_t *vdev_ids, uint8_t num_vdevs,
 					   uint8_t vdev_id);
 	void (*mlo_setup_complete)(struct cdp_mlo_ctxt *mlo_ctxt);
+	void (*mlo_update_delta_tsf2)(struct cdp_soc_t *soc_hdl,
+				      uint8_t pdev_id,
+				      uint64_t delta_tsf2);
+	void (*mlo_update_delta_tqm)(struct cdp_soc_t *soc_hdl,
+				     uint64_t delta_tqm);
+	void (*mlo_update_mlo_ts_offset)(struct cdp_soc_t *soc_hdl,
+					 uint64_t offset);
 };
 #endif
 

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

@@ -687,11 +687,15 @@ static QDF_STATUS dp_pdev_attach_be(struct dp_pdev *pdev,
 				    struct cdp_pdev_attach_params *params)
 {
 	dp_pdev_mlo_fill_params(pdev, params);
+	dp_mlo_update_link_to_pdev_map(pdev->soc, pdev);
+
 	return QDF_STATUS_SUCCESS;
 }
 
 static QDF_STATUS dp_pdev_detach_be(struct dp_pdev *pdev)
 {
+	dp_mlo_update_link_to_pdev_unmap(pdev->soc, pdev);
+
 	return QDF_STATUS_SUCCESS;
 }
 

+ 16 - 0
dp/wifi3.0/be/dp_be.h

@@ -223,6 +223,8 @@ struct dp_ppe_vp_profile {
  * @mlo_enabled: Flag to indicate MLO is enabled or not
  * @mlo_chip_id: MLO chip_id
  * @ml_ctxt: pointer to global ml_context
+ * @delta_tqm: delta_tqm
+ * @mlo_tstamp_offset: mlo timestamp offset
  * @mld_peer_hash: peer hash table for ML peers
  *           Associated peer with this MAC address)
  * @mld_peer_hash_lock: lock to protect mld_peer_hash
@@ -259,6 +261,8 @@ struct dp_soc_be {
 	uint8_t mlo_enabled;
 	uint8_t mlo_chip_id;
 	struct dp_mlo_ctxt *ml_ctxt;
+	uint64_t delta_tqm;
+	uint64_t mlo_tstamp_offset;
 #else
 	/* Protect mld peer hash table */
 	DP_MUTEX_TYPE mld_peer_hash_lock;
@@ -280,11 +284,13 @@ struct dp_soc_be {
  * @pdev: dp pdev structure
  * @monitor_pdev_be: BE specific monitor object
  * @mlo_link_id: MLO link id for PDEV
+ * @delta_tsf2: delta_tsf2
  */
 struct dp_pdev_be {
 	struct dp_pdev pdev;
 #ifdef WLAN_MLO_MULTI_CHIP
 	uint8_t mlo_link_id;
+	uint64_t delta_tsf2;
 #endif
 };
 
@@ -770,6 +776,16 @@ void dp_pdev_mlo_fill_params(struct dp_pdev *pdev,
 			     struct cdp_pdev_attach_params *params)
 {
 }
+
+static inline
+void dp_mlo_update_link_to_pdev_map(struct dp_soc *soc, struct dp_pdev *pdev)
+{
+}
+
+static inline
+void dp_mlo_update_link_to_pdev_unmap(struct dp_soc *soc, struct dp_pdev *pdev)
+{
+}
 #endif
 
 /*

+ 145 - 0
dp/wifi3.0/be/mlo/dp_mlo.c

@@ -381,11 +381,51 @@ static void dp_mlo_setup_complete(struct cdp_mlo_ctxt *cdp_ml_ctxt)
 	}
 }
 
+static void dp_mlo_update_delta_tsf2(struct cdp_soc_t *soc_hdl,
+				     uint8_t pdev_id, uint64_t delta_tsf2)
+{
+	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
+	struct dp_pdev *pdev;
+	struct dp_pdev_be *be_pdev;
+
+	pdev = dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc,
+						  pdev_id);
+	if (!pdev) {
+		dp_err("pdev is NULL for pdev_id %u", pdev_id);
+		return;
+	}
+
+	be_pdev = dp_get_be_pdev_from_dp_pdev(pdev);
+
+	be_pdev->delta_tsf2 = delta_tsf2;
+}
+
+static void dp_mlo_update_delta_tqm(struct cdp_soc_t *soc_hdl,
+				    uint64_t delta_tqm)
+{
+	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
+	struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
+
+	be_soc->delta_tqm = delta_tqm;
+}
+
+static void dp_mlo_update_mlo_ts_offset(struct cdp_soc_t *soc_hdl,
+					uint64_t offset)
+{
+	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
+	struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
+
+	be_soc->mlo_tstamp_offset = offset;
+}
+
 static struct cdp_mlo_ops dp_mlo_ops = {
 	.mlo_soc_setup = dp_mlo_soc_setup,
 	.mlo_soc_teardown = dp_mlo_soc_teardown,
 	.update_mlo_ptnr_list = dp_update_mlo_ptnr_list,
 	.mlo_setup_complete = dp_mlo_setup_complete,
+	.mlo_update_delta_tsf2 = dp_mlo_update_delta_tsf2,
+	.mlo_update_delta_tqm = dp_mlo_update_delta_tqm,
+	.mlo_update_mlo_ts_offset = dp_mlo_update_mlo_ts_offset,
 };
 
 void dp_soc_mlo_fill_params(struct dp_soc *soc,
@@ -404,6 +444,57 @@ void dp_soc_mlo_fill_params(struct dp_soc *soc,
 	soc->cdp_soc.ops->mlo_ops = &dp_mlo_ops;
 }
 
+void dp_mlo_update_link_to_pdev_map(struct dp_soc *soc, struct dp_pdev *pdev)
+{
+	struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
+	struct dp_pdev_be *be_pdev = dp_get_be_pdev_from_dp_pdev(pdev);
+	struct dp_mlo_ctxt *ml_ctxt = be_soc->ml_ctxt;
+	uint8_t link_id;
+
+	if (!be_soc->mlo_enabled)
+		return;
+
+	if (!ml_ctxt)
+		return;
+
+	link_id = be_pdev->mlo_link_id;
+
+	if (link_id < WLAN_MAX_MLO_CHIPS * WLAN_MAX_MLO_LINKS_PER_SOC) {
+		if (!ml_ctxt->link_to_pdev_map[link_id])
+			ml_ctxt->link_to_pdev_map[link_id] = be_pdev;
+		else
+			dp_alert("Attempt to update existing map for link %u",
+				 link_id);
+	}
+}
+
+void dp_mlo_update_link_to_pdev_unmap(struct dp_soc *soc, struct dp_pdev *pdev)
+{
+	struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
+	struct dp_pdev_be *be_pdev = dp_get_be_pdev_from_dp_pdev(pdev);
+	struct dp_mlo_ctxt *ml_ctxt = be_soc->ml_ctxt;
+	uint8_t link_id;
+
+	if (!be_soc->mlo_enabled)
+		return;
+
+	if (!ml_ctxt)
+		return;
+
+	link_id = be_pdev->mlo_link_id;
+
+	if (link_id < WLAN_MAX_MLO_CHIPS * WLAN_MAX_MLO_LINKS_PER_SOC)
+		ml_ctxt->link_to_pdev_map[link_id] = NULL;
+}
+
+static struct dp_pdev_be *
+dp_mlo_get_be_pdev_from_link_id(struct dp_mlo_ctxt *ml_ctxt, uint8_t link_id)
+{
+	if (link_id < WLAN_MAX_MLO_CHIPS * WLAN_MAX_MLO_LINKS_PER_SOC)
+		return ml_ctxt->link_to_pdev_map[link_id];
+	return NULL;
+}
+
 void dp_pdev_mlo_fill_params(struct dp_pdev *pdev,
 			     struct cdp_pdev_attach_params *params)
 {
@@ -655,3 +746,57 @@ struct dp_vdev *dp_mlo_get_mcast_primary_vdev(struct dp_soc_be *be_soc,
 
 qdf_export_symbol(dp_mlo_get_mcast_primary_vdev);
 #endif
+
+static inline uint64_t dp_mlo_get_mlo_ts_offset(struct dp_pdev_be *be_pdev)
+{
+	struct dp_soc *soc;
+	struct dp_pdev *pdev;
+	struct dp_soc_be *be_soc;
+	uint32_t mlo_offset;
+
+	pdev = &be_pdev->pdev;
+	soc = pdev->soc;
+	be_soc = dp_get_be_soc_from_dp_soc(soc);
+
+	mlo_offset = be_soc->mlo_tstamp_offset;
+
+	return mlo_offset;
+}
+
+int32_t dp_mlo_get_delta_tsf2_wrt_mlo_offset(struct dp_soc *soc,
+					     uint8_t hw_link_id)
+{
+	struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
+	struct dp_mlo_ctxt *ml_ctxt = be_soc->ml_ctxt;
+	struct dp_pdev_be *be_pdev;
+	int32_t delta_tsf2_mlo_offset;
+	int32_t mlo_offset, delta_tsf2;
+
+	if (!ml_ctxt)
+		return 0;
+
+	be_pdev = dp_mlo_get_be_pdev_from_link_id(ml_ctxt, hw_link_id);
+	if (!be_pdev)
+		return 0;
+
+	mlo_offset = dp_mlo_get_mlo_ts_offset(be_pdev);
+	delta_tsf2 = be_pdev->delta_tsf2;
+
+	delta_tsf2_mlo_offset = mlo_offset - delta_tsf2;
+
+	return delta_tsf2_mlo_offset;
+}
+
+int32_t dp_mlo_get_delta_tqm_wrt_mlo_offset(struct dp_soc *soc)
+{
+	struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc);
+	int32_t delta_tqm_mlo_offset;
+	int32_t mlo_offset, delta_tqm;
+
+	mlo_offset = be_soc->mlo_tstamp_offset;
+	delta_tqm = be_soc->delta_tqm;
+
+	delta_tqm_mlo_offset = mlo_offset - delta_tqm;
+
+	return delta_tqm_mlo_offset;
+}

+ 41 - 0
dp/wifi3.0/be/mlo/dp_mlo.h

@@ -38,6 +38,7 @@
  * @mld_peer_hash: peer hash table for ML peers
  *           Associated peer with this MAC address)
  * @mld_peer_hash_lock: lock to protect mld_peer_hash
+ * @link_to_pdev_map: link to pdev mapping
  */
 struct dp_mlo_ctxt {
 	struct cdp_ctrl_mlo_mgr *ctrl_ctxt;
@@ -53,6 +54,8 @@ struct dp_mlo_ctxt {
 	qdf_spinlock_t mld_peer_hash_lock;
 	uint32_t toeplitz_hash_ipv4[LRO_IPV4_SEED_ARR_SZ];
 	uint32_t toeplitz_hash_ipv6[LRO_IPV6_SEED_ARR_SZ];
+	struct dp_pdev_be *link_to_pdev_map[WLAN_MAX_MLO_CHIPS *
+		WLAN_MAX_MLO_LINKS_PER_SOC];
 };
 
 /**
@@ -110,4 +113,42 @@ dp_mlo_get_soc_ref_by_chip_id(struct dp_mlo_ctxt *ml_ctxt, uint8_t chip_id);
  */
 void dp_mlo_get_rx_hash_key(struct dp_soc *soc,
 			    struct cdp_lro_hash_config *lro_hash);
+
+/**
+ * dp_mlo_update_link_to_pdev_map : map link-id to pdev mapping
+ * @soc: DP SOC
+ * @pdev: DP PDEV
+ *
+ * Return: none
+ */
+void dp_mlo_update_link_to_pdev_map(struct dp_soc *soc, struct dp_pdev *pdev);
+
+/**
+ * dp_mlo_update_link_to_pdev_unmap : unmap link-id to pdev mapping
+ * @soc: DP SOC
+ * @pdev: DP PDEV
+ *
+ * Return: none
+ */
+void dp_mlo_update_link_to_pdev_unmap(struct dp_soc *soc, struct dp_pdev *pdev);
+
+/**
+ * dp_mlo_get_delta_tsf2_wrt_mlo_offset() - Get delta between mlo timestamp
+ *                                          offset and delta tsf2
+ * @soc: DP SOC
+ * @hw_link_id: link id
+ *
+ * Return: int32_t
+ */
+int32_t dp_mlo_get_delta_tsf2_wrt_mlo_offset(struct dp_soc *soc,
+					     uint8_t hw_link_id);
+
+/**
+ * dp_mlo_get_delta_tqm_wrt_mlo_offset() - Get delta between mlo timestamp
+ *                                         offset and delta tqm
+ * @soc: DP SOC
+ *
+ * Return: int32_t
+ */
+int32_t dp_mlo_get_delta_tqm_wrt_mlo_offset(struct dp_soc *soc);
 #endif /* __DP_MLO_H */

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

@@ -2943,6 +2943,21 @@ dp_offload_ind_handler(struct htt_soc *soc, uint32_t *msg_word)
 #endif
 
 #ifdef WLAN_FEATURE_11BE_MLO
+#ifdef WLAN_MLO_MULTI_CHIP
+static inline void dp_update_mlo_ts_offset(struct dp_soc *soc,
+					   uint32_t ts_lo, uint32_t ts_hi)
+{
+	uint64_t mlo_offset;
+
+	mlo_offset = ((uint64_t)(ts_hi) << 32 | ts_lo);
+	soc->cdp_soc.ops->mlo_ops->mlo_update_mlo_ts_offset
+		((struct cdp_soc_t *)soc, mlo_offset);
+}
+#else
+static inline void dp_update_mlo_ts_offset(struct dp_soc *soc,
+					   uint32_t ts_lo, uint32_t ts_hi)
+{}
+#endif
 static void dp_htt_mlo_peer_map_handler(struct htt_soc *soc,
 					uint32_t *msg_word)
 {
@@ -3097,6 +3112,10 @@ dp_rx_mlo_timestamp_ind_handler(struct dp_soc *soc,
 		     pdev->timestamp.mlo_offset_hi_us);
 
 	qdf_spin_unlock_bh(&soc->htt_stats.lock);
+
+	dp_update_mlo_ts_offset(soc,
+				pdev->timestamp.mlo_offset_lo_us,
+				pdev->timestamp.mlo_offset_hi_us);
 }
 #else
 static void dp_htt_mlo_peer_map_handler(struct htt_soc *soc,

+ 3 - 0
dp/wifi3.0/dp_main.c

@@ -5722,6 +5722,7 @@ static QDF_STATUS dp_pdev_detach_wifi3(struct cdp_soc_t *psoc, uint8_t pdev_id,
 				       int force)
 {
 	struct dp_pdev *pdev;
+	struct dp_soc *soc = (struct dp_soc *)psoc;
 
 	pdev = dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)psoc,
 						  pdev_id);
@@ -5732,6 +5733,8 @@ static QDF_STATUS dp_pdev_detach_wifi3(struct cdp_soc_t *psoc, uint8_t pdev_id,
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	soc->arch_ops.txrx_pdev_detach(pdev);
+
 	dp_pdev_detach((struct cdp_pdev *)pdev, force);
 	return QDF_STATUS_SUCCESS;
 }