Browse Source

qcacmn: Support HW Tx completion delay and Tx enqueue stats

- Add support to compute HW Tx completion delay on WKK
- Define arch op to calculate delay

Change-Id: I82567cc781e90fe01dc5a0edfffacd4cde73f652
CRs-Fixed: 3220911
Ripan Deuri 3 years ago
parent
commit
fc7daffbd0

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

@@ -1779,6 +1779,7 @@ void dp_initialize_arch_ops_be(struct dp_arch_ops *arch_ops)
 					dp_peer_rx_reorder_queue_setup_be;
 	arch_ops->txrx_print_peer_stats = dp_print_peer_txrx_stats_be;
 	arch_ops->dp_find_peer_by_destmac = dp_find_peer_by_destmac_be;
+	arch_ops->dp_tx_compute_hw_delay = dp_tx_compute_tx_delay_be;
 	dp_init_near_full_arch_ops_be(arch_ops);
 	arch_ops->get_rx_hash_key = dp_get_rx_hash_key_be;
 }

+ 95 - 0
dp/wifi3.0/be/dp_be_tx.c

@@ -549,6 +549,20 @@ void dp_sawf_config_be(struct dp_soc *soc, uint32_t *hal_tx_desc_cached,
 		       uint16_t *fw_metadata, qdf_nbuf_t nbuf)
 {
 }
+
+static inline
+QDF_STATUS dp_sawf_tx_enqueue_peer_stats(struct dp_soc *soc,
+					 struct dp_tx_desc_s *tx_desc)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline
+QDF_STATUS dp_sawf_tx_enqueue_fail_peer_stats(struct dp_soc *soc,
+					      struct dp_tx_desc_s *tx_desc)
+{
+	return QDF_STATUS_SUCCESS;
+}
 #endif
 
 QDF_STATUS
@@ -594,6 +608,7 @@ dp_tx_hw_enqueue_be(struct dp_soc *soc, struct dp_vdev *vdev,
 	if (dp_sawf_tag_valid_get(tx_desc->nbuf)) {
 		dp_sawf_config_be(soc, hal_tx_desc_cached,
 				  &fw_metadata, tx_desc->nbuf);
+		dp_sawf_tx_enqueue_peer_stats(soc, tx_desc);
 	}
 
 	hal_tx_desc_set_buf_addr_be(soc->hal_soc, hal_tx_desc_cached,
@@ -644,6 +659,7 @@ dp_tx_hw_enqueue_be(struct dp_soc *soc, struct dp_vdev *vdev,
 		dp_err("HAL RING Access Failed -- %pK", hal_ring_hdl);
 		DP_STATS_INC(soc, tx.tcl_ring_full[ring_id], 1);
 		DP_STATS_INC(vdev, tx_i.dropped.enqueue_fail, 1);
+		dp_sawf_tx_enqueue_fail_peer_stats(soc, tx_desc);
 		return status;
 	}
 
@@ -652,6 +668,7 @@ dp_tx_hw_enqueue_be(struct dp_soc *soc, struct dp_vdev *vdev,
 		dp_verbose_debug("TCL ring full ring_id:%d", ring_id);
 		DP_STATS_INC(soc, tx.tcl_ring_full[ring_id], 1);
 		DP_STATS_INC(vdev, tx_i.dropped.enqueue_fail, 1);
+		dp_sawf_tx_enqueue_fail_peer_stats(soc, tx_desc);
 		goto ring_access_fail;
 	}
 
@@ -942,3 +959,81 @@ uint32_t dp_tx_comp_nf_handler(struct dp_intr *int_ctx, struct dp_soc *soc,
 	return work_done;
 }
 #endif
+
+#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) && \
+	defined(CONFIG_SAWF)
+#define PPDUID_GET_HW_LINK_ID(PPDU_ID, LINK_ID_OFFSET, LINK_ID_BITS) \
+	(((PPDU_ID) >> (LINK_ID_OFFSET)) & ((1 << (LINK_ID_BITS)) - 1))
+
+#define HW_TX_DELAY_MAX                       0x1000000
+#define TX_COMPL_SHIFT_BUFFER_TIMESTAMP_US    10
+#define HW_TX_DELAY_MASK                      0x1FFFFFFF
+#define TX_COMPL_BUFFER_TSTAMP_US(TSTAMP) \
+	(((TSTAMP) << TX_COMPL_SHIFT_BUFFER_TIMESTAMP_US) & \
+	 HW_TX_DELAY_MASK)
+
+static inline
+QDF_STATUS dp_mlo_compute_hw_delay_us(struct dp_soc *soc,
+				      struct dp_vdev *vdev,
+				      struct hal_tx_completion_status *ts,
+				      uint32_t *delay_us)
+{
+	uint32_t ppdu_id;
+	uint8_t link_id_offset, link_id_bits;
+	uint8_t hw_link_id;
+	uint32_t msdu_tqm_enqueue_tstamp_us, final_msdu_tqm_enqueue_tstamp_us;
+	uint32_t msdu_compl_tsf_tstamp_us, final_msdu_compl_tsf_tstamp_us;
+	uint32_t delay;
+	int32_t delta_tsf2, delta_tqm;
+
+	if (!ts->valid)
+		return QDF_STATUS_E_INVAL;
+
+	link_id_offset = soc->link_id_offset;
+	link_id_bits = soc->link_id_bits;
+	ppdu_id = ts->ppdu_id;
+	hw_link_id = PPDUID_GET_HW_LINK_ID(ppdu_id, link_id_offset,
+					   link_id_bits);
+
+	msdu_tqm_enqueue_tstamp_us =
+		TX_COMPL_BUFFER_TSTAMP_US(ts->buffer_timestamp);
+	msdu_compl_tsf_tstamp_us = ts->tsf;
+
+	delta_tsf2 = dp_mlo_get_delta_tsf2_wrt_mlo_offset(soc, hw_link_id);
+	delta_tqm = dp_mlo_get_delta_tqm_wrt_mlo_offset(soc);
+
+	final_msdu_tqm_enqueue_tstamp_us = (msdu_tqm_enqueue_tstamp_us +
+			delta_tqm) & HW_TX_DELAY_MASK;
+
+	final_msdu_compl_tsf_tstamp_us = (msdu_compl_tsf_tstamp_us +
+			delta_tsf2) & HW_TX_DELAY_MASK;
+
+	delay = (final_msdu_compl_tsf_tstamp_us -
+		final_msdu_tqm_enqueue_tstamp_us) & HW_TX_DELAY_MASK;
+
+	if (delay > HW_TX_DELAY_MAX)
+		return QDF_STATUS_E_FAILURE;
+
+	if (delay_us)
+		*delay_us = delay;
+
+	return QDF_STATUS_SUCCESS;
+}
+#else
+static inline
+QDF_STATUS dp_mlo_compute_hw_delay_us(struct dp_soc *soc,
+				      struct dp_vdev *vdev,
+				      struct hal_tx_completion_status *ts,
+				      uint32_t *delay_us)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
+QDF_STATUS dp_tx_compute_tx_delay_be(struct dp_soc *soc,
+				     struct dp_vdev *vdev,
+				     struct hal_tx_completion_status *ts,
+				     uint32_t *delay_us)
+{
+	return dp_mlo_compute_hw_delay_us(soc, vdev, ts, delay_us);
+}

+ 14 - 0
dp/wifi3.0/be/dp_be_tx.h

@@ -226,4 +226,18 @@ uint32_t dp_tx_comp_nf_handler(struct dp_intr *int_ctx, struct dp_soc *soc,
 	return 0;
 }
 #endif /* WLAN_FEATURE_NEAR_FULL_IRQ */
+
+/**
+ * dp_tx_compute_tx_delay_be() - Compute HW Tx completion delay
+ * @soc: Handle to DP Soc structure
+ * @vdev: vdev
+ * @ts: Tx completion status
+ * @delay_us: Delay to be calculated in microseconds
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS dp_tx_compute_tx_delay_be(struct dp_soc *soc,
+				     struct dp_vdev *vdev,
+				     struct hal_tx_completion_status *ts,
+				     uint32_t *delay_us);
 #endif

+ 5 - 0
dp/wifi3.0/dp_types.h

@@ -1863,6 +1863,11 @@ struct dp_arch_ops {
 	struct dp_peer *(*dp_find_peer_by_destmac)(struct dp_soc *soc,
 						   uint8_t *dest_mac_addr,
 						   uint8_t vdev_id);
+	QDF_STATUS
+	(*dp_tx_compute_hw_delay)(struct dp_soc *soc,
+				  struct dp_vdev *vdev,
+				  struct hal_tx_completion_status *ts,
+				  uint32_t *delay_us);
 };
 
 /**

+ 1 - 0
dp/wifi3.0/li/dp_li.c

@@ -607,6 +607,7 @@ void dp_initialize_arch_ops_li(struct dp_arch_ops *arch_ops)
 	arch_ops->dp_peer_rx_reorder_queue_setup =
 					dp_peer_rx_reorder_queue_setup_li;
 	arch_ops->dp_find_peer_by_destmac = dp_find_peer_by_destmac_li;
+	arch_ops->dp_tx_compute_hw_delay = dp_tx_compute_tx_delay_li;
 }
 
 #ifdef QCA_DP_TX_HW_SW_NBUF_DESC_PREFETCH

+ 26 - 0
dp/wifi3.0/li/dp_li_tx.c

@@ -368,6 +368,15 @@ void dp_sawf_config_li(struct dp_soc *soc, uint32_t *hal_tx_desc_cached,
 	hal_tx_desc_set_search_index_li(soc->hal_soc, hal_tx_desc_cached,
 					search_index);
 }
+
+static inline
+QDF_STATUS dp_tx_compute_hw_delay_li(struct dp_soc *soc,
+				     struct dp_vdev *vdev,
+				     struct hal_tx_completion_status *ts,
+				     uint32_t *delay_us)
+{
+	return dp_tx_compute_hw_delay_us(ts, vdev->delta_tsf, delay_us);
+}
 #else
 static inline
 void dp_sawf_config_li(struct dp_soc *soc, uint32_t *hal_tx_desc_cached,
@@ -376,6 +385,15 @@ void dp_sawf_config_li(struct dp_soc *soc, uint32_t *hal_tx_desc_cached,
 {
 }
 
+static inline
+QDF_STATUS dp_tx_compute_hw_delay_li(struct dp_soc *soc,
+				     struct dp_vdev *vdev,
+				     struct hal_tx_completion_status *ts,
+				     uint32_t *delay_us)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
 #define dp_sawf_tx_enqueue_peer_stats(soc, tx_desc)
 #define dp_sawf_tx_enqueue_fail_peer_stats(soc, tx_desc)
 #endif
@@ -554,3 +572,11 @@ void dp_tx_desc_pool_deinit_li(struct dp_soc *soc,
 			       uint8_t pool_id)
 {
 }
+
+QDF_STATUS dp_tx_compute_tx_delay_li(struct dp_soc *soc,
+				     struct dp_vdev *vdev,
+				     struct hal_tx_completion_status *ts,
+				     uint32_t *delay_us)
+{
+	return dp_tx_compute_hw_delay_li(soc, vdev, ts, delay_us);
+}

+ 14 - 0
dp/wifi3.0/li/dp_li_tx.h

@@ -93,4 +93,18 @@ QDF_STATUS dp_tx_desc_pool_init_li(struct dp_soc *soc,
 void dp_tx_desc_pool_deinit_li(struct dp_soc *soc,
 			       struct dp_tx_desc_pool_s *tx_desc_pool,
 			       uint8_t pool_id);
+
+/**
+ * dp_tx_compute_tx_delay_li() - Compute HW Tx completion delay
+ * @soc: Handle to DP Soc structure
+ * @vdev: vdev
+ * @ts: Tx completion status
+ * @delay_us: Delay to be calculated in microseconds
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS dp_tx_compute_tx_delay_li(struct dp_soc *soc,
+				     struct dp_vdev *vdev,
+				     struct hal_tx_completion_status *ts,
+				     uint32_t *delay_us);
 #endif