|
@@ -2807,6 +2807,17 @@ static void dp_enable_verbose_debug(struct dp_soc *soc)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+#ifdef WLAN_FEATURE_STATS_EXT
|
|
|
+static inline void dp_create_ext_stats_event(struct dp_soc *soc)
|
|
|
+{
|
|
|
+ qdf_event_create(&soc->rx_hw_stats_event);
|
|
|
+}
|
|
|
+#else
|
|
|
+static inline void dp_create_ext_stats_event(struct dp_soc *soc)
|
|
|
+{
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
/*
|
|
|
* dp_soc_cmn_setup() - Common SoC level initializion
|
|
|
* @soc: Datapath SOC handle
|
|
@@ -3055,6 +3066,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc)
|
|
|
wlan_cfg_get_defrag_timeout_check(soc_cfg_ctx);
|
|
|
qdf_spinlock_create(&soc->rx.defrag.defrag_lock);
|
|
|
|
|
|
+ dp_create_ext_stats_event(soc);
|
|
|
out:
|
|
|
/*
|
|
|
* set the fragment destination ring
|
|
@@ -5302,6 +5314,26 @@ static inline void dp_peer_rx_bufq_resources_init(struct dp_peer *peer)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+#ifdef WLAN_FEATURE_STATS_EXT
|
|
|
+/*
|
|
|
+ * dp_set_ignore_reo_status_cb() - set ignore reo status cb flag
|
|
|
+ * @soc: dp soc handle
|
|
|
+ * @flag: flag to set or reset
|
|
|
+ *
|
|
|
+ * Return: None
|
|
|
+ */
|
|
|
+static inline void dp_set_ignore_reo_status_cb(struct dp_soc *soc,
|
|
|
+ bool flag)
|
|
|
+{
|
|
|
+ soc->ignore_reo_status_cb = flag;
|
|
|
+}
|
|
|
+#else
|
|
|
+static inline void dp_set_ignore_reo_status_cb(struct dp_soc *soc,
|
|
|
+ bool flag)
|
|
|
+{
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
/*
|
|
|
* dp_peer_create_wifi3() - attach txrx peer
|
|
|
* @soc_hdl: Datapath soc handle
|
|
@@ -5458,6 +5490,12 @@ static void *dp_peer_create_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
|
|
|
vdev->vap_self_peer = peer;
|
|
|
}
|
|
|
|
|
|
+ if (wlan_op_mode_sta == vdev->opmode &&
|
|
|
+ qdf_mem_cmp(peer->mac_addr.raw, vdev->mac_addr.raw,
|
|
|
+ QDF_MAC_ADDR_SIZE) != 0) {
|
|
|
+ dp_set_ignore_reo_status_cb(soc, false);
|
|
|
+ }
|
|
|
+
|
|
|
for (i = 0; i < DP_MAX_TIDS; i++)
|
|
|
qdf_spinlock_create(&peer->rx_tid[i].tid_lock);
|
|
|
|
|
@@ -6244,6 +6282,12 @@ static QDF_STATUS dp_peer_delete_wifi3(struct cdp_soc_t *soc, uint8_t vdev_id,
|
|
|
qdf_spinlock_destroy(&peer->peer_info_lock);
|
|
|
dp_peer_multipass_list_remove(peer);
|
|
|
|
|
|
+ if (wlan_op_mode_sta == peer->vdev->opmode &&
|
|
|
+ qdf_mem_cmp(peer->mac_addr.raw, peer->vdev->mac_addr.raw,
|
|
|
+ QDF_MAC_ADDR_SIZE) != 0) {
|
|
|
+ dp_set_ignore_reo_status_cb(peer->vdev->pdev->soc, true);
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* Remove the reference added during peer_attach.
|
|
|
* The peer will still be left allocated until the
|
|
@@ -9983,6 +10027,125 @@ dp_txrx_post_data_stall_event(struct cdp_soc_t *soc_hdl,
|
|
|
}
|
|
|
#endif /* WLAN_SUPPORT_DATA_STALL */
|
|
|
|
|
|
+#ifdef WLAN_FEATURE_STATS_EXT
|
|
|
+/* rx hw stats event wait timeout in ms */
|
|
|
+#define DP_REO_STATUS_STATS_TIMEOUT 1000
|
|
|
+/**
|
|
|
+ * dp_txrx_ext_stats_request - request dp txrx extended stats request
|
|
|
+ * @soc_hdl: soc handle
|
|
|
+ * @pdev_id: pdev id
|
|
|
+ * @req: stats request
|
|
|
+ *
|
|
|
+ * Return: QDF_STATUS
|
|
|
+ */
|
|
|
+static QDF_STATUS
|
|
|
+dp_txrx_ext_stats_request(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
|
|
|
+ struct cdp_txrx_ext_stats *req)
|
|
|
+{
|
|
|
+ struct dp_soc *soc = (struct dp_soc *)soc_hdl;
|
|
|
+ struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
|
|
|
+
|
|
|
+ if (!pdev) {
|
|
|
+ dp_err("pdev is null");
|
|
|
+ return QDF_STATUS_E_INVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ dp_aggregate_pdev_stats(pdev);
|
|
|
+
|
|
|
+ req->tx_msdu_enqueue = pdev->stats.tx_i.processed.num;
|
|
|
+ req->tx_msdu_overflow = pdev->stats.tx_i.dropped.ring_full;
|
|
|
+ req->rx_mpdu_received = soc->ext_stats.rx_mpdu_received;
|
|
|
+ req->rx_mpdu_delivered = soc->ext_stats.rx_mpdu_received;
|
|
|
+ req->rx_mpdu_missed = soc->ext_stats.rx_mpdu_missed;
|
|
|
+ req->rx_mpdu_error = soc->stats.rx.err_ring_pkts -
|
|
|
+ soc->stats.rx.rx_frags;
|
|
|
+
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * dp_rx_hw_stats_cb - request rx hw stats response callback
|
|
|
+ * @soc: soc handle
|
|
|
+ * @cb_ctxt: callback context
|
|
|
+ * @reo_status: reo command response status
|
|
|
+ *
|
|
|
+ * Return: None
|
|
|
+ */
|
|
|
+static void dp_rx_hw_stats_cb(struct dp_soc *soc, void *cb_ctxt,
|
|
|
+ union hal_reo_status *reo_status)
|
|
|
+{
|
|
|
+ struct dp_rx_tid *rx_tid = (struct dp_rx_tid *)cb_ctxt;
|
|
|
+ struct hal_reo_queue_status *queue_status = &reo_status->queue_status;
|
|
|
+
|
|
|
+ if (soc->ignore_reo_status_cb) {
|
|
|
+ qdf_event_set(&soc->rx_hw_stats_event);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (queue_status->header.status != HAL_REO_CMD_SUCCESS) {
|
|
|
+ dp_info("REO stats failure %d for TID %d",
|
|
|
+ queue_status->header.status, rx_tid->tid);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ soc->ext_stats.rx_mpdu_received += queue_status->mpdu_frms_cnt;
|
|
|
+ soc->ext_stats.rx_mpdu_missed += queue_status->late_recv_mpdu_cnt;
|
|
|
+
|
|
|
+ if (rx_tid->tid == (DP_MAX_TIDS - 1))
|
|
|
+ qdf_event_set(&soc->rx_hw_stats_event);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * dp_request_rx_hw_stats - request rx hardware stats
|
|
|
+ * @soc_hdl: soc handle
|
|
|
+ * @vdev_id: vdev id
|
|
|
+ *
|
|
|
+ * Return: None
|
|
|
+ */
|
|
|
+static void
|
|
|
+dp_request_rx_hw_stats(struct cdp_soc_t *soc_hdl, uint8_t vdev_id)
|
|
|
+{
|
|
|
+ struct dp_soc *soc = (struct dp_soc *)soc_hdl;
|
|
|
+ struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id);
|
|
|
+ struct dp_peer *peer;
|
|
|
+
|
|
|
+ if (!vdev) {
|
|
|
+ dp_err("vdev is null");
|
|
|
+ qdf_event_set(&soc->rx_hw_stats_event);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ peer = vdev->vap_bss_peer;
|
|
|
+
|
|
|
+ if (!peer || peer->delete_in_progress) {
|
|
|
+ dp_err("Peer deletion in progress");
|
|
|
+ qdf_event_set(&soc->rx_hw_stats_event);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ qdf_event_reset(&soc->rx_hw_stats_event);
|
|
|
+ dp_peer_rxtid_stats(peer, dp_rx_hw_stats_cb, NULL);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * dp_wait_for_ext_rx_stats - wait for rx reo status for rx stats
|
|
|
+ * @soc_hdl: cdp opaque soc handle
|
|
|
+ *
|
|
|
+ * Return: status
|
|
|
+ */
|
|
|
+static QDF_STATUS
|
|
|
+dp_wait_for_ext_rx_stats(struct cdp_soc_t *soc_hdl)
|
|
|
+{
|
|
|
+ struct dp_soc *soc = (struct dp_soc *)soc_hdl;
|
|
|
+ QDF_STATUS status;
|
|
|
+
|
|
|
+ status = qdf_wait_single_event(&soc->rx_hw_stats_event,
|
|
|
+ DP_REO_STATUS_STATS_TIMEOUT);
|
|
|
+
|
|
|
+ return status;
|
|
|
+}
|
|
|
+#endif /* WLAN_FEATURE_STATS_EXT */
|
|
|
+
|
|
|
#ifdef DP_PEER_EXTENDED_API
|
|
|
static struct cdp_misc_ops dp_ops_misc = {
|
|
|
#ifdef FEATURE_WLAN_TDLS
|
|
@@ -10002,6 +10165,12 @@ static struct cdp_misc_ops dp_ops_misc = {
|
|
|
.txrx_data_stall_cb_deregister = dp_deregister_data_stall_detect_cb,
|
|
|
.txrx_post_data_stall_event = dp_txrx_post_data_stall_event,
|
|
|
#endif
|
|
|
+
|
|
|
+#ifdef WLAN_FEATURE_STATS_EXT
|
|
|
+ .txrx_ext_stats_request = dp_txrx_ext_stats_request,
|
|
|
+ .request_rx_hw_stats = dp_request_rx_hw_stats,
|
|
|
+ .wait_for_ext_rx_stats = dp_wait_for_ext_rx_stats,
|
|
|
+#endif
|
|
|
};
|
|
|
#endif
|
|
|
|