diff --git a/components/pkt_capture/core/inc/wlan_pkt_capture_data_txrx.h b/components/pkt_capture/core/inc/wlan_pkt_capture_data_txrx.h index f7511902a2..e7f51beda5 100644 --- a/components/pkt_capture/core/inc/wlan_pkt_capture_data_txrx.h +++ b/components/pkt_capture/core/inc/wlan_pkt_capture_data_txrx.h @@ -188,6 +188,17 @@ struct pkt_capture_tx_hdr_elem_t { uint16_t seqno; }; +/** + * pkt_capture_ppdu_stats_q_node - node structure to be enqueued + * in ppdu_stats_q + * @node: list node + * @buf: buffer data received from ppdu_stats + */ +struct pkt_capture_ppdu_stats_q_node { + qdf_list_node_t node; + uint32_t buf[]; +}; + /** * pkt_capture_tx_get_txcomplete_data_hdr() - extract Tx data hdr from Tx * completion for pkt capture mode diff --git a/components/pkt_capture/core/inc/wlan_pkt_capture_priv.h b/components/pkt_capture/core/inc/wlan_pkt_capture_priv.h index d48d0c4b20..6de315b58f 100644 --- a/components/pkt_capture/core/inc/wlan_pkt_capture_priv.h +++ b/components/pkt_capture/core/inc/wlan_pkt_capture_priv.h @@ -59,6 +59,8 @@ struct pkt_capture_cb_context { * @rx_ops: rx ops * @tx_ops: tx ops * @rx_avg_rssi: avg rssi of rx data packets + * @ppdu_stats_q: list used for storing smu related ppdu stats + * @lock_q: spinlock for ppdu_stats q */ struct pkt_capture_vdev_priv { struct wlan_objmgr_vdev *vdev; @@ -67,6 +69,8 @@ struct pkt_capture_vdev_priv { struct wlan_pkt_capture_rx_ops rx_ops; struct wlan_pkt_capture_tx_ops tx_ops; int32_t rx_avg_rssi; + qdf_list_t ppdu_stats_q; + qdf_spinlock_t lock_q; }; /** diff --git a/components/pkt_capture/core/src/wlan_pkt_capture_main.c b/components/pkt_capture/core/src/wlan_pkt_capture_main.c index 56d37a038e..13984f7513 100644 --- a/components/pkt_capture/core/src/wlan_pkt_capture_main.c +++ b/components/pkt_capture/core/src/wlan_pkt_capture_main.c @@ -23,6 +23,7 @@ #ifdef WLAN_FEATURE_PKT_CAPTURE_V2 #include +#include "htt_ppdu_stats.h" #endif #include "wlan_pkt_capture_main.h" #include "cfg_ucfg_api.h" @@ -40,6 +41,7 @@ wdi_event_subscribe PKT_CAPTURE_TX_SUBSCRIBER; wdi_event_subscribe PKT_CAPTURE_RX_SUBSCRIBER; wdi_event_subscribe PKT_CAPTURE_RX_NO_PEER_SUBSCRIBER; wdi_event_subscribe PKT_CAPTURE_OFFLOAD_TX_SUBSCRIBER; +wdi_event_subscribe PKT_CAPTURE_PPDU_STATS_SUBSCRIBER; /** * pkt_capture_wdi_event_subscribe() - Subscribe pkt capture callbacks @@ -89,6 +91,16 @@ static void pkt_capture_wdi_event_subscribe(struct wlan_objmgr_psoc *psoc) cdp_wdi_event_sub(soc, pdev_id, &PKT_CAPTURE_OFFLOAD_TX_SUBSCRIBER, WDI_EVENT_PKT_CAPTURE_OFFLOAD_TX_DATA); + + /* subscribe for packet capture mode related ppdu stats */ + PKT_CAPTURE_PPDU_STATS_SUBSCRIBER.callback = + pkt_capture_callback; + + PKT_CAPTURE_PPDU_STATS_SUBSCRIBER.context = + wlan_psoc_get_dp_handle(psoc); + + cdp_wdi_event_sub(soc, pdev_id, &PKT_CAPTURE_PPDU_STATS_SUBSCRIBER, + WDI_EVENT_PKT_CAPTURE_PPDU_STATS); } /** @@ -117,6 +129,10 @@ static void pkt_capture_wdi_event_unsubscribe(struct wlan_objmgr_psoc *psoc) /* unsubscribing for offload tx data packets */ cdp_wdi_event_unsub(soc, pdev_id, &PKT_CAPTURE_OFFLOAD_TX_SUBSCRIBER, WDI_EVENT_PKT_CAPTURE_OFFLOAD_TX_DATA); + + /* unsubscribe ppdu smu stats */ + cdp_wdi_event_unsub(soc, pdev_id, &PKT_CAPTURE_PPDU_STATS_SUBSCRIBER, + WDI_EVENT_PKT_CAPTURE_PPDU_STATS); } enum pkt_capture_mode @@ -140,6 +156,7 @@ pkt_capture_get_pktcap_mode_v2() } #define RX_OFFLOAD_PKT 1 +#define PPDU_STATS_Q_MAX_SIZE 500 static void pkt_capture_process_rx_data_no_peer(void *soc, uint16_t vdev_id, uint8_t *bssid, @@ -181,6 +198,57 @@ pkt_capture_process_rx_data_no_peer(void *soc, uint16_t vdev_id, uint8_t *bssid, bssid, psoc, 0); } +static void +pkt_capture_process_ppdu_stats(void *log_data) +{ + struct wlan_objmgr_vdev *vdev; + struct pkt_capture_vdev_priv *vdev_priv; + struct pkt_capture_ppdu_stats_q_node *q_node; + htt_ppdu_stats_for_smu_tlv *smu; + uint32_t stats_len; + + vdev = pkt_capture_get_vdev(); + if (qdf_unlikely(!vdev)) + return; + + vdev_priv = pkt_capture_vdev_get_priv(vdev); + if (qdf_unlikely(!vdev_priv)) + return; + + smu = (htt_ppdu_stats_for_smu_tlv *)log_data; + + qdf_spin_lock(&vdev_priv->lock_q); + if (qdf_list_size(&vdev_priv->ppdu_stats_q) < + PPDU_STATS_Q_MAX_SIZE) { + /* + * win size indicates the size of block ack bitmap, currently + * we support only 256 bit ba bitmap. + */ + if (smu->win_size > 8) { + qdf_spin_unlock(&vdev_priv->lock_q); + pkt_capture_err("win size %d > 8 not supported\n", + smu->win_size); + return; + } + + stats_len = sizeof(htt_ppdu_stats_for_smu_tlv) + + smu->win_size * sizeof(uint32_t); + + q_node = qdf_mem_malloc(sizeof(*q_node) + stats_len); + if (!q_node) { + qdf_spin_unlock(&vdev_priv->lock_q); + pkt_capture_err("stats node and buf allocation fail\n"); + return; + } + + qdf_mem_copy(q_node->buf, log_data, stats_len); + /* Insert received ppdu stats in queue */ + qdf_list_insert_back(&vdev_priv->ppdu_stats_q, + &q_node->node); + } + qdf_spin_unlock(&vdev_priv->lock_q); +} + void pkt_capture_callback(void *soc, enum WDI_EVENT event, void *log_data, u_int16_t vdev_id, uint32_t status) { @@ -380,8 +448,13 @@ void pkt_capture_callback(void *soc, enum WDI_EVENT event, void *log_data, pkt_capture_offload_deliver_indication_handler( log_data, vdev_id, bssid, soc); + break; } + case WDI_EVENT_PKT_CAPTURE_PPDU_STATS: + pkt_capture_process_ppdu_stats(log_data); + break; + default: break; } @@ -763,6 +836,9 @@ pkt_capture_vdev_create_notification(struct wlan_objmgr_vdev *vdev, void *arg) pkt_capture_err("Failed to open mon thread"); goto open_mon_thread_fail; } + qdf_spinlock_create(&vdev_priv->lock_q); + qdf_list_create(&vdev_priv->ppdu_stats_q, PPDU_STATS_Q_MAX_SIZE); + return status; open_mon_thread_fail: @@ -784,6 +860,8 @@ QDF_STATUS pkt_capture_vdev_destroy_notification(struct wlan_objmgr_vdev *vdev, void *arg) { struct pkt_capture_vdev_priv *vdev_priv; + struct pkt_capture_ppdu_stats_q_node *stats_node; + qdf_list_node_t *node; QDF_STATUS status; if ((wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE) || @@ -796,6 +874,15 @@ pkt_capture_vdev_destroy_notification(struct wlan_objmgr_vdev *vdev, void *arg) return QDF_STATUS_E_FAILURE; } + while (qdf_list_remove_front(&vdev_priv->ppdu_stats_q, &node) + == QDF_STATUS_SUCCESS) { + stats_node = qdf_container_of( + node, struct pkt_capture_ppdu_stats_q_node, node); + qdf_mem_free(stats_node); + } + qdf_list_destroy(&vdev_priv->ppdu_stats_q); + qdf_spinlock_destroy(&vdev_priv->lock_q); + status = wlan_objmgr_vdev_component_obj_detach( vdev, WLAN_UMAC_COMP_PKT_CAPTURE, @@ -806,6 +893,7 @@ pkt_capture_vdev_destroy_notification(struct wlan_objmgr_vdev *vdev, void *arg) pkt_capture_close_mon_thread(vdev_priv->mon_ctx); pkt_capture_mon_context_destroy(vdev_priv); pkt_capture_callback_ctx_destroy(vdev_priv); + qdf_mem_free(vdev_priv); gp_pkt_capture_vdev = NULL; return status;