Преглед изворни кода

qcacmn: Add support to calculate uplink delay

Add support to calculate uplink delay on a per vdev basis.
The delay calculated excludes bus delays, where packet
enqueueing time and complete time are fetched from HW release
ring.

Change-Id: I4bbcbf28b197f7a87cb822a841f1f957ebcf063b
CRs-Fixed: 2958833
Jia Ding пре 4 година
родитељ
комит
9304c2d00e
6 измењених фајлова са 277 додато и 1 уклоњено
  1. 82 0
      dp/inc/cdp_txrx_ctrl.h
  2. 11 0
      dp/inc/cdp_txrx_ops.h
  3. 5 0
      dp/wifi3.0/dp_main.c
  4. 133 0
      dp/wifi3.0/dp_tx.c
  5. 35 0
      dp/wifi3.0/dp_tx.h
  6. 11 1
      dp/wifi3.0/dp_types.h

+ 82 - 0
dp/inc/cdp_txrx_ctrl.h

@@ -1284,4 +1284,86 @@ void cdp_txrx_peer_flush_frags(ol_txrx_soc_handle soc, uint8_t vdev_id,
 	return soc->ops->ctrl_ops->txrx_peer_flush_frags(soc, vdev_id,
 							 peer_mac);
 }
+
+#ifdef WLAN_FEATURE_TSF_UPLINK_DELAY
+/**
+ * cdp_set_delta_tsf() - wrapper function to set delta_tsf
+ * @soc: SOC TXRX handle
+ * @vdev_id: vdev id
+ * @delta_tsf: difference between TSF clock and qtimer
+ *
+ * Return: None
+ */
+static inline void cdp_set_delta_tsf(ol_txrx_soc_handle soc, uint8_t vdev_id,
+				     uint32_t delta_tsf)
+{
+	if (!soc || !soc->ops) {
+		dp_cdp_err("Invalid instance");
+		QDF_BUG(0);
+		return;
+	}
+
+	if (!soc->ops->ctrl_ops ||
+	    !soc->ops->ctrl_ops->txrx_set_delta_tsf)
+		return;
+
+	soc->ops->ctrl_ops->txrx_set_delta_tsf(soc, vdev_id, delta_tsf);
+}
+
+/**
+ * cdp_set_tsf_ul_delay_report() - Enable or disable reporting uplink delay
+ * @soc: SOC TXRX handle
+ * @vdev_id: vdev id
+ * @enable: true to enable and false to disable
+ *
+ * Return: QDF_STATUS
+ */
+static inline QDF_STATUS cdp_set_tsf_ul_delay_report(ol_txrx_soc_handle soc,
+						     uint8_t vdev_id,
+						     bool enable)
+{
+	if (!soc || !soc->ops) {
+		dp_cdp_err("Invalid SOC instance");
+		QDF_BUG(0);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (!soc->ops->ctrl_ops ||
+	    !soc->ops->ctrl_ops->txrx_set_tsf_ul_delay_report)
+		return QDF_STATUS_E_FAILURE;
+
+	return soc->ops->ctrl_ops->txrx_set_tsf_ul_delay_report(soc, vdev_id,
+								enable);
+}
+
+/**
+ * cdp_get_uplink_delay() - Get uplink delay value
+ * @soc: SOC TXRX handle
+ * @vdev_id: vdev id
+ * @val: pointer to save uplink delay value
+ *
+ * Return: QDF_STATUS
+ */
+static inline QDF_STATUS cdp_get_uplink_delay(ol_txrx_soc_handle soc,
+					      uint32_t vdev_id, uint32_t *val)
+{
+	if (!soc || !soc->ops) {
+		dp_cdp_err("Invalid SOC instance");
+		QDF_BUG(0);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (!val) {
+		dp_cdp_err("Invalid params val");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (!soc->ops->ctrl_ops ||
+	    !soc->ops->ctrl_ops->txrx_get_uplink_delay)
+		return QDF_STATUS_E_FAILURE;
+
+	return soc->ops->ctrl_ops->txrx_get_uplink_delay(soc, vdev_id, val);
+}
+#endif /* WLAN_FEATURE_TSF_UPLINK_DELAY */
+
 #endif /* _CDP_TXRX_CTRL_H_ */

+ 11 - 0
dp/inc/cdp_txrx_ops.h

@@ -813,6 +813,17 @@ struct cdp_ctrl_ops {
 						int8_t vdev_id);
 
 #endif
+
+#ifdef WLAN_FEATURE_TSF_UPLINK_DELAY
+	void (*txrx_set_delta_tsf)(struct cdp_soc_t *soc, uint8_t vdev_id,
+				   uint32_t delta_tsf);
+	QDF_STATUS (*txrx_set_tsf_ul_delay_report)(struct cdp_soc_t *soc,
+						   uint8_t vdev_id,
+						   bool enable);
+	QDF_STATUS (*txrx_get_uplink_delay)(struct cdp_soc_t *soc,
+					    uint8_t vdev_id,
+					    uint32_t *val);
+#endif
 };
 
 struct cdp_me_ops {

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

@@ -12471,6 +12471,11 @@ static struct cdp_ctrl_ops dp_ops_ctrl = {
 	.txrx_update_peer_pkt_capture_params =
 		 dp_peer_update_pkt_capture_params,
 #endif /* WLAN_TX_PKT_CAPTURE_ENH || WLAN_RX_PKT_CAPTURE_ENH */
+#ifdef WLAN_FEATURE_TSF_UPLINK_DELAY
+	.txrx_set_delta_tsf = dp_set_delta_tsf,
+	.txrx_set_tsf_ul_delay_report = dp_set_tsf_ul_delay_report,
+	.txrx_get_uplink_delay = dp_get_uplink_delay,
+#endif
 };
 
 static struct cdp_me_ops dp_ops_me = {

+ 133 - 0
dp/wifi3.0/dp_tx.c

@@ -3991,6 +3991,138 @@ void dp_tx_update_connectivity_stats(struct dp_soc *soc,
 }
 #endif
 
+#ifdef WLAN_FEATURE_TSF_UPLINK_DELAY
+void dp_set_delta_tsf(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
+		      uint32_t delta_tsf)
+{
+	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
+	struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id,
+						     DP_MOD_ID_CDP);
+
+	if (!vdev) {
+		dp_err_rl("vdev %d does not exist", vdev_id);
+		return;
+	}
+
+	vdev->delta_tsf = delta_tsf;
+	dp_debug("vdev id %u delta_tsf %u", vdev_id, delta_tsf);
+
+	dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP);
+}
+
+QDF_STATUS dp_set_tsf_ul_delay_report(struct cdp_soc_t *soc_hdl,
+				      uint8_t vdev_id, bool enable)
+{
+	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
+	struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id,
+						     DP_MOD_ID_CDP);
+
+	if (!vdev) {
+		dp_err_rl("vdev %d does not exist", vdev_id);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	qdf_atomic_set(&vdev->ul_delay_report, enable);
+
+	dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS dp_get_uplink_delay(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
+			       uint32_t *val)
+{
+	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
+	struct dp_vdev *vdev;
+	uint32_t delay_accum;
+	uint32_t pkts_accum;
+
+	vdev = dp_vdev_get_ref_by_id(soc, vdev_id, DP_MOD_ID_CDP);
+	if (!vdev) {
+		dp_err_rl("vdev %d does not exist", vdev_id);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (!qdf_atomic_read(&vdev->ul_delay_report)) {
+		dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	/* Average uplink delay based on current accumulated values */
+	delay_accum = qdf_atomic_read(&vdev->ul_delay_accum);
+	pkts_accum = qdf_atomic_read(&vdev->ul_pkts_accum);
+
+	*val = delay_accum / pkts_accum;
+	dp_debug("uplink_delay %u delay_accum %u pkts_accum %u", *val,
+		 delay_accum, pkts_accum);
+
+	/* Reset accumulated values to 0 */
+	qdf_atomic_set(&vdev->ul_delay_accum, 0);
+	qdf_atomic_set(&vdev->ul_pkts_accum, 0);
+
+	dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+static void dp_tx_update_uplink_delay(struct dp_soc *soc, struct dp_vdev *vdev,
+				      struct hal_tx_completion_status *ts)
+{
+	uint32_t buffer_ts;
+	uint32_t delta_tsf;
+	uint32_t ul_delay;
+
+	/* Tx_rate_stats_info_valid is 0 and tsf is invalid then */
+	if (!ts->valid)
+		return;
+
+	if (qdf_unlikely(!vdev)) {
+		dp_info_rl("vdev is null or delete in progrss");
+		return;
+	}
+
+	if (!qdf_atomic_read(&vdev->ul_delay_report))
+		return;
+
+	delta_tsf = vdev->delta_tsf;
+
+	/* buffer_timestamp is in units of 1024 us and is [31:13] of
+	 * WBM_RELEASE_RING_4. After left shift 10 bits, it's
+	 * valid up to 29 bits.
+	 */
+	buffer_ts = ts->buffer_timestamp << 10;
+
+	ul_delay = ts->tsf - buffer_ts - delta_tsf;
+	ul_delay &= 0x1FFFFFFF; /* mask 29 BITS */
+	if (ul_delay > 0x1000000) {
+		dp_info_rl("----------------------\n"
+			   "Tx completion status:\n"
+			   "----------------------\n"
+			   "release_src = %d\n"
+			   "ppdu_id = 0x%x\n"
+			   "release_reason = %d\n"
+			   "tsf = %u (0x%x)\n"
+			   "buffer_timestamp = %u (0x%x)\n"
+			   "delta_tsf = %u (0x%x)\n",
+			   ts->release_src, ts->ppdu_id, ts->status,
+			   ts->tsf, ts->tsf, ts->buffer_timestamp,
+			   ts->buffer_timestamp, delta_tsf, delta_tsf);
+		return;
+	}
+
+	ul_delay /= 1000; /* in unit of ms */
+
+	qdf_atomic_add(ul_delay, &vdev->ul_delay_accum);
+	qdf_atomic_inc(&vdev->ul_pkts_accum);
+}
+#else /* !WLAN_FEATURE_TSF_UPLINK_DELAY */
+static inline
+void dp_tx_update_uplink_delay(struct dp_soc *soc, struct dp_vdev *vdev,
+			       struct hal_tx_completion_status *ts)
+{
+}
+#endif /* WLAN_FEATURE_TSF_UPLINK_DELAY */
+
 /**
  * dp_tx_comp_process_tx_status() - Parse and Dump Tx completion status info
  * @soc: DP soc handle
@@ -4069,6 +4201,7 @@ void dp_tx_comp_process_tx_status(struct dp_soc *soc,
 	vdev = peer->vdev;
 
 	dp_tx_update_connectivity_stats(soc, vdev, tx_desc, ts->status);
+	dp_tx_update_uplink_delay(soc, vdev, ts);
 
 	/* Update per-packet stats for mesh mode */
 	if (qdf_unlikely(vdev->mesh_vdev) &&

+ 35 - 0
dp/wifi3.0/dp_tx.h

@@ -771,4 +771,39 @@ dp_tx_hw_desc_update_evt(uint8_t *hal_tx_desc_cached,
 }
 #endif
 
+#ifdef WLAN_FEATURE_TSF_UPLINK_DELAY
+/**
+ * dp_set_delta_tsf() - Set delta_tsf to dp_soc structure
+ * @soc_hdl: cdp soc pointer
+ * @vdev_id: vdev id
+ * @delta_tsf: difference between TSF clock and qtimer
+ *
+ * Return: None
+ */
+void dp_set_delta_tsf(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
+		      uint32_t delta_tsf);
+
+/**
+ * dp_set_tsf_report_ul_delay() - Enable or disable reporting uplink delay
+ * @soc_hdl: cdp soc pointer
+ * @vdev_id: vdev id
+ * @enable: true to enable and false to disable
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS dp_set_tsf_ul_delay_report(struct cdp_soc_t *soc_hdl,
+				      uint8_t vdev_id, bool enable);
+
+/**
+ * dp_get_uplink_delay() - Get uplink delay value
+ * @soc_hdl: cdp soc pointer
+ * @vdev_id: vdev id
+ * @val: pointer to save uplink delay value
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS dp_get_uplink_delay(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
+			       uint32_t *val);
+#endif /* WLAN_FEATURE_TSF_UPLINK_TSF */
+
 #endif

+ 11 - 1
dp/wifi3.0/dp_types.h

@@ -3032,8 +3032,18 @@ struct dp_vdev {
 		uint8_t latency_tid;
 	} mesh_tid_latency_config;
 #endif
-};
 
+#ifdef WLAN_FEATURE_TSF_UPLINK_DELAY
+	/* Indicate if uplink delay report is enabled or not */
+	qdf_atomic_t ul_delay_report;
+	/* Delta between TQM clock and TSF clock */
+	uint32_t delta_tsf;
+	/* accumulative delay for every TX completion */
+	qdf_atomic_t ul_delay_accum;
+	/* accumulative number of packets delay has accumulated */
+	qdf_atomic_t ul_pkts_accum;
+#endif /* WLAN_FEATURE_TSF_UPLINK_DELAY */
+};
 
 enum {
 	dp_sec_mcast = 0,