diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 61e6362357..011b158f2e 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -4591,7 +4591,6 @@ static void dp_pdev_deinit(struct cdp_pdev *txrx_pdev, int force) dp_tx_ppdu_stats_detach(pdev); qdf_nbuf_free(pdev->sojourn_buf); - qdf_nbuf_queue_free(&pdev->rx_ppdu_buf_q); dp_cal_client_detach(&pdev->cal_client_ctx); @@ -7231,10 +7230,9 @@ QDF_STATUS dp_monitor_mode_ring_config(struct dp_soc *soc, uint8_t mac_for_pdev, static inline void dp_pdev_disable_mcopy_code(struct dp_pdev *pdev) { - pdev->mcopy_mode = 0; + pdev->mcopy_mode = M_COPY_DISABLED; pdev->monitor_configured = false; pdev->monitor_vdev = NULL; - qdf_nbuf_queue_free(&pdev->rx_ppdu_buf_q); } /** @@ -8236,7 +8234,6 @@ dp_config_debug_sniffer(struct dp_pdev *pdev, int val) } #endif /* FEATURE_PERPKT_INFO */ } - switch (val) { case 0: pdev->tx_sniffer_enable = 0; @@ -8274,13 +8271,14 @@ dp_config_debug_sniffer(struct dp_pdev *pdev, int val) DP_PPDU_STATS_CFG_SNIFFER, pdev->pdev_id); break; case 2: + case 4: if (pdev->monitor_vdev) { status = QDF_STATUS_E_RESOURCES; break; } #ifdef FEATURE_PERPKT_INFO - pdev->mcopy_mode = 1; + pdev->mcopy_mode = val; pdev->tx_sniffer_enable = 0; pdev->monitor_configured = true; diff --git a/dp/wifi3.0/dp_mon_filter.c b/dp/wifi3.0/dp_mon_filter.c index dff1b190da..22c2ed91a4 100644 --- a/dp/wifi3.0/dp_mon_filter.c +++ b/dp/wifi3.0/dp_mon_filter.c @@ -605,6 +605,7 @@ void dp_mon_filter_setup_mcopy_mode(struct dp_pdev *pdev) /* Setup the filter */ filter.tlv_filter.enable_mo = 1; filter.tlv_filter.packet_header = 1; + filter.tlv_filter.mpdu_end = 1; dp_mon_filter_show_filter(pdev, mode, &filter); srng_type = DP_MON_FILTER_SRNG_TYPE_RXDMA_MONITOR_STATUS; diff --git a/dp/wifi3.0/dp_rx_mon_status.c b/dp/wifi3.0/dp_rx_mon_status.c index 0078a3ceb4..3fe0240398 100644 --- a/dp/wifi3.0/dp_rx_mon_status.c +++ b/dp/wifi3.0/dp_rx_mon_status.c @@ -695,87 +695,14 @@ static void dp_rx_stats_update(struct dp_pdev *pdev, } #endif -/* - * dp_rx_get_fcs_ok_msdu() - get ppdu status buffer containing fcs_ok msdu - * @pdev: pdev object - * @ppdu_info: ppdu info object - * - * Return: nbuf - */ - -static inline qdf_nbuf_t -dp_rx_get_fcs_ok_msdu(struct dp_pdev *pdev, - struct hal_rx_ppdu_info *ppdu_info) -{ - uint16_t mpdu_fcs_ok; - qdf_nbuf_t status_nbuf = NULL; - unsigned long *fcs_ok_bitmap; - - if (qdf_unlikely(qdf_nbuf_is_queue_empty(&pdev->rx_ppdu_buf_q))) - return NULL; - - /* Obtain fcs_ok passed index from bitmap - * this index is used to get fcs passed first msdu payload - */ - - fcs_ok_bitmap = - (unsigned long *)&ppdu_info->com_info.mpdu_fcs_ok_bitmap[0]; - mpdu_fcs_ok = qdf_find_first_bit(fcs_ok_bitmap, - HAL_RX_MAX_MPDU); - - if (qdf_unlikely(mpdu_fcs_ok >= HAL_RX_MAX_MPDU)) - goto end; - - if (qdf_unlikely(!ppdu_info->ppdu_msdu_info[mpdu_fcs_ok].nbuf)) - goto end; - - /* Get status buffer by indexing mpdu_fcs_ok index - * containing first msdu payload with fcs passed - * and clone the buffer - */ - status_nbuf = ppdu_info->ppdu_msdu_info[mpdu_fcs_ok].nbuf; - ppdu_info->ppdu_msdu_info[mpdu_fcs_ok].nbuf = NULL; - - /* Take ref of status nbuf as this nbuf is to be - * freeed by upper layer. - */ - qdf_nbuf_ref(status_nbuf); - ppdu_info->fcs_ok_msdu_info.first_msdu_payload = - ppdu_info->ppdu_msdu_info[mpdu_fcs_ok].first_msdu_payload; - ppdu_info->fcs_ok_msdu_info.payload_len = - ppdu_info->ppdu_msdu_info[mpdu_fcs_ok].payload_len; - - -end: - /* Free the ppdu status buffer queue */ - qdf_nbuf_queue_free(&pdev->rx_ppdu_buf_q); - - qdf_mem_zero(&ppdu_info->ppdu_msdu_info, - (ppdu_info->com_info.mpdu_cnt_fcs_ok + - ppdu_info->com_info.mpdu_cnt_fcs_err) - * sizeof(struct hal_rx_msdu_payload_info)); - return status_nbuf; -} - -static inline void -dp_rx_handle_ppdu_status_buf(struct dp_pdev *pdev, - struct hal_rx_ppdu_info *ppdu_info, - qdf_nbuf_t status_nbuf) -{ - qdf_nbuf_t dropnbuf; - - if (qdf_nbuf_queue_len(&pdev->rx_ppdu_buf_q) > - HAL_RX_MAX_MPDU) { - dropnbuf = qdf_nbuf_queue_remove(&pdev->rx_ppdu_buf_q); - qdf_nbuf_free(dropnbuf); - } - qdf_nbuf_queue_add(&pdev->rx_ppdu_buf_q, status_nbuf); -} /** * dp_rx_handle_mcopy_mode() - Allocate and deliver first MSDU payload * @soc: core txrx main context - * @pdev: pdev strcuture + * @pdev: pdev structure * @ppdu_info: structure for rx ppdu ring + * @nbuf: QDF nbuf + * @fcs_ok_mpdu_cnt: fcs passsed mpdu index + * @deliver_frame: flag to deliver wdi event * * Return: QDF_STATUS_SUCCESS - If nbuf to be freed by caller * QDF_STATUS_E_ALREADY - If nbuf not to be freed by caller @@ -783,24 +710,25 @@ dp_rx_handle_ppdu_status_buf(struct dp_pdev *pdev, #ifdef FEATURE_PERPKT_INFO static inline QDF_STATUS dp_rx_handle_mcopy_mode(struct dp_soc *soc, struct dp_pdev *pdev, - struct hal_rx_ppdu_info *ppdu_info, qdf_nbuf_t nbuf) + struct hal_rx_ppdu_info *ppdu_info, qdf_nbuf_t nbuf, + uint8_t fcs_ok_mpdu_cnt, bool deliver_frame) { - uint8_t size = 0; + uint16_t size = 0; struct ieee80211_frame *wh; uint32_t *nbuf_data; - if (!ppdu_info->fcs_ok_msdu_info.first_msdu_payload) + if (!ppdu_info->ppdu_msdu_info[fcs_ok_mpdu_cnt].first_msdu_payload) return QDF_STATUS_SUCCESS; - if (pdev->m_copy_id.rx_ppdu_id == ppdu_info->com_info.ppdu_id) - return QDF_STATUS_SUCCESS; + /* For M_COPY mode only one msdu per ppdu is sent to upper layer*/ + if (pdev->mcopy_mode == M_COPY) { + if (pdev->m_copy_id.rx_ppdu_id == ppdu_info->com_info.ppdu_id) + return QDF_STATUS_SUCCESS; + } - pdev->m_copy_id.rx_ppdu_id = ppdu_info->com_info.ppdu_id; + wh = (struct ieee80211_frame *)(ppdu_info->ppdu_msdu_info[fcs_ok_mpdu_cnt].first_msdu_payload + 4); - wh = (struct ieee80211_frame *) - (ppdu_info->fcs_ok_msdu_info.first_msdu_payload + 4); - - size = (ppdu_info->fcs_ok_msdu_info.first_msdu_payload - + size = (ppdu_info->ppdu_msdu_info[fcs_ok_mpdu_cnt].first_msdu_payload - qdf_nbuf_data(nbuf)); if (qdf_nbuf_pull_head(nbuf, size) == NULL) @@ -813,25 +741,163 @@ dp_rx_handle_mcopy_mode(struct dp_soc *soc, struct dp_pdev *pdev, return QDF_STATUS_SUCCESS; } - ppdu_info->fcs_ok_msdu_info.first_msdu_payload = NULL; nbuf_data = (uint32_t *)qdf_nbuf_data(nbuf); *nbuf_data = pdev->ppdu_info.com_info.ppdu_id; /* only retain RX MSDU payload in the skb */ - qdf_nbuf_trim_tail(nbuf, qdf_nbuf_len(nbuf) - - ppdu_info->fcs_ok_msdu_info.payload_len); - dp_wdi_event_handler(WDI_EVENT_RX_DATA, soc, - nbuf, HTT_INVALID_PEER, WDI_NO_VAL, pdev->pdev_id); + qdf_nbuf_trim_tail(nbuf, qdf_nbuf_len(nbuf) - ppdu_info->ppdu_msdu_info[fcs_ok_mpdu_cnt].payload_len); + if (deliver_frame) { + pdev->m_copy_id.rx_ppdu_id = ppdu_info->com_info.ppdu_id; + dp_wdi_event_handler(WDI_EVENT_RX_DATA, soc, + nbuf, HTT_INVALID_PEER, + WDI_NO_VAL, pdev->pdev_id); + } return QDF_STATUS_E_ALREADY; } #else static inline QDF_STATUS dp_rx_handle_mcopy_mode(struct dp_soc *soc, struct dp_pdev *pdev, - struct hal_rx_ppdu_info *ppdu_info, qdf_nbuf_t nbuf) + struct hal_rx_ppdu_info *ppdu_info, qdf_nbuf_t nbuf, + uint8_t fcs_ok_cnt, bool deliver_frame) { return QDF_STATUS_SUCCESS; } #endif +/** + * dp_rx_mcopy_handle_last_mpdu() - cache and delive last MPDU header in a + * status buffer if MPDU end tlv is received in different buffer + * @soc: core txrx main context + * @pdev: pdev structure + * @ppdu_info: structure for rx ppdu ring + * @status_nbuf: QDF nbuf + * + * Return: void + */ +#ifdef FEATURE_PERPKT_INFO +static inline void +dp_rx_mcopy_handle_last_mpdu(struct dp_soc *soc, struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info, + qdf_nbuf_t status_nbuf) +{ + QDF_STATUS mcopy_status; + qdf_nbuf_t nbuf_clone = NULL; + /* If the MPDU end tlv and RX header are received in different buffers, + * process the RX header based on fcs status. + */ + if (pdev->mcopy_status_nbuf) { + /* For M_COPY mode only one msdu per ppdu is sent to upper layer*/ + if (pdev->mcopy_mode == M_COPY) { + if (pdev->m_copy_id.rx_ppdu_id == + ppdu_info->com_info.ppdu_id) + goto end1; + } + + if (ppdu_info->is_fcs_passed) { + nbuf_clone = qdf_nbuf_clone(pdev->mcopy_status_nbuf); + if (!nbuf_clone) { + QDF_TRACE(QDF_MODULE_ID_TXRX, + QDF_TRACE_LEVEL_ERROR, + "Failed to clone nbuf", + __func__, __LINE__); + goto end1; + } + + pdev->m_copy_id.rx_ppdu_id = ppdu_info->com_info.ppdu_id; + dp_wdi_event_handler(WDI_EVENT_RX_DATA, soc, + nbuf_clone, + HTT_INVALID_PEER, + WDI_NO_VAL, pdev->pdev_id); + ppdu_info->is_fcs_passed = false; + } +end1: + qdf_nbuf_free(pdev->mcopy_status_nbuf); + pdev->mcopy_status_nbuf = NULL; + } + + /* If the MPDU end tlv and RX header are received in different buffers, + * preserve the RX header as the fcs status will be received in MPDU + * end tlv in next buffer. So, cache the buffer to be processd in next + * iteration + */ + if ((ppdu_info->fcs_ok_cnt + ppdu_info->fcs_err_cnt) != + ppdu_info->com_info.mpdu_cnt) { + pdev->mcopy_status_nbuf = qdf_nbuf_clone(status_nbuf); + if (pdev->mcopy_status_nbuf) { + mcopy_status = dp_rx_handle_mcopy_mode( + soc, pdev, + ppdu_info, + pdev->mcopy_status_nbuf, + ppdu_info->fcs_ok_cnt, + false); + if (mcopy_status == QDF_STATUS_SUCCESS) { + qdf_nbuf_free(pdev->mcopy_status_nbuf); + pdev->mcopy_status_nbuf = NULL; + } + } + } +} +#else +static inline void +dp_rx_mcopy_handle_last_mpdu(struct dp_soc *soc, struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info, + qdf_nbuf_t status_nbuf) +{ +} +#endif + +/** + * dp_rx_mcopy_process_ppdu_info() - update mcopy ppdu info + * @ppdu_info: structure for rx ppdu ring + * @tlv_status: processed TLV status + * + * Return: void + */ +#ifdef FEATURE_PERPKT_INFO +static inline void +dp_rx_mcopy_process_ppdu_info(struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info, + uint32_t tlv_status) +{ + if (!pdev->mcopy_mode) + return; + + /* The fcs status is received in MPDU end tlv. If the RX header + * and its MPDU end tlv are received in different status buffer then + * to process that header ppdu_info->is_fcs_passed is used. + * If end tlv is received in next status buffer then com_info.mpdu_cnt + * will be 0 at the time of receiving MPDU end tlv and we update the + * is_fcs_passed flag based on ppdu_info->fcs_err. + */ + if (tlv_status != HAL_TLV_STATUS_MPDU_END) + return; + + if (!ppdu_info->fcs_err) { + if (ppdu_info->fcs_ok_cnt > + HAL_RX_MAX_MPDU_H_PER_STATUS_BUFFER) { + dp_err("No. of MPDUs(%d) per status buff exceeded", + ppdu_info->fcs_ok_cnt); + return; + } + if (ppdu_info->com_info.mpdu_cnt) + ppdu_info->fcs_ok_cnt++; + else + ppdu_info->is_fcs_passed = true; + } else { + if (ppdu_info->com_info.mpdu_cnt) + ppdu_info->fcs_err_cnt++; + else + ppdu_info->is_fcs_passed = false; + } +} +#else +static inline void +dp_rx_mcopy_process_ppdu_info(struct dp_pdev *pdev, + struct hal_rx_ppdu_info *ppdu_info, + uint32_t tlv_status) +{ +} +#endif + #ifdef FEATURE_PERPKT_INFO static inline void dp_rx_process_mcopy_mode(struct dp_soc *soc, struct dp_pdev *pdev, @@ -840,36 +906,50 @@ dp_rx_process_mcopy_mode(struct dp_soc *soc, struct dp_pdev *pdev, qdf_nbuf_t status_nbuf) { QDF_STATUS mcopy_status; + qdf_nbuf_t nbuf_clone = NULL; + uint8_t fcs_ok_mpdu_cnt = 0; - if (qdf_unlikely(!ppdu_info->com_info.mpdu_cnt)) { - qdf_nbuf_free(status_nbuf); - return; - } - /* Add buffers to queue until we receive - * HAL_TLV_STATUS_PPDU_DONE - */ - dp_rx_handle_ppdu_status_buf(pdev, ppdu_info, status_nbuf); + dp_rx_mcopy_handle_last_mpdu(soc, pdev, ppdu_info, status_nbuf); - /* If tlv_status is PPDU_DONE, process rx_ppdu_buf_q - * and devliver fcs_ok msdu buffer - */ - if (tlv_status == HAL_TLV_STATUS_PPDU_DONE) { - if (qdf_unlikely(ppdu_info->com_info.mpdu_cnt != - (ppdu_info->com_info.mpdu_cnt_fcs_ok + - ppdu_info->com_info.mpdu_cnt_fcs_err))) { - qdf_nbuf_queue_free(&pdev->rx_ppdu_buf_q); - return; - } - /* Get rx ppdu status buffer having fcs ok msdu */ - status_nbuf = dp_rx_get_fcs_ok_msdu(pdev, ppdu_info); - if (status_nbuf) { - mcopy_status = dp_rx_handle_mcopy_mode(soc, pdev, - ppdu_info, - status_nbuf); - if (mcopy_status == QDF_STATUS_SUCCESS) - qdf_nbuf_free(status_nbuf); + if (qdf_unlikely(!ppdu_info->com_info.mpdu_cnt)) + goto end; + + if (qdf_unlikely(!ppdu_info->fcs_ok_cnt)) + goto end; + + /* For M_COPY mode only one msdu per ppdu is sent to upper layer*/ + if (pdev->mcopy_mode == M_COPY) + ppdu_info->fcs_ok_cnt = 1; + + while (fcs_ok_mpdu_cnt < ppdu_info->fcs_ok_cnt) { + nbuf_clone = qdf_nbuf_clone(status_nbuf); + if (!nbuf_clone) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "Failed to clone nbuf", + __func__, __LINE__); + goto end; } + + mcopy_status = dp_rx_handle_mcopy_mode(soc, pdev, + ppdu_info, + nbuf_clone, + fcs_ok_mpdu_cnt, + true); + + if (mcopy_status == QDF_STATUS_SUCCESS) + qdf_nbuf_free(nbuf_clone); + + fcs_ok_mpdu_cnt++; } +end: + qdf_nbuf_free(status_nbuf); + ppdu_info->fcs_ok_cnt = 0; + ppdu_info->fcs_err_cnt = 0; + ppdu_info->com_info.mpdu_cnt = 0; + qdf_mem_zero(&ppdu_info->ppdu_msdu_info, + HAL_RX_MAX_MPDU_H_PER_STATUS_BUFFER + * sizeof(struct hal_rx_msdu_payload_info)); + } #else static inline void @@ -1534,6 +1614,10 @@ dp_rx_mon_status_process_tlv(struct dp_soc *soc, uint32_t mac_id, status_nbuf, ppdu_info, &nbuf_used); + dp_rx_mcopy_process_ppdu_info(pdev, + ppdu_info, + tlv_status); + rx_tlv = hal_rx_status_get_next_tlv(rx_tlv); if ((rx_tlv - rx_tlv_start) >= @@ -2103,7 +2187,6 @@ dp_rx_pdev_mon_status_attach(struct dp_pdev *pdev, int ring_id) { return status; qdf_nbuf_queue_init(&pdev->rx_status_q); - qdf_nbuf_queue_init(&pdev->rx_ppdu_buf_q); pdev->mon_ppdu_status = DP_PPDU_STATUS_START; diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 0b3c13ab75..55488a4350 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -123,6 +123,15 @@ enum rx_pktlog_mode { }; #endif +/* enum m_copy_mode - Available mcopy mode + * + */ +enum m_copy_mode { + M_COPY_DISABLED = 0, + M_COPY = 2, + M_COPY_EXTENDED = 4, +}; + struct msdu_list { qdf_nbuf_t head; qdf_nbuf_t tail; @@ -1735,7 +1744,7 @@ struct dp_pdev { bool tx_sniffer_enable; /* mirror copy mode */ - bool mcopy_mode; + enum m_copy_mode mcopy_mode; bool cfr_rcc_mode; bool enable_reap_timer_non_pkt; bool bpr_enable; @@ -1845,10 +1854,6 @@ struct dp_pdev { uint32_t *ppdu_tlv_buf; /* Buffer to hold HTT ppdu stats TLVs*/ - /* nbuf queue to maintain rx ppdu status buffer - * belonging to one ppdu - */ - qdf_nbuf_queue_t rx_ppdu_buf_q; #ifdef WLAN_SUPPORT_RX_FLOW_TAG /** * Pointer to DP Flow FST at SOC level if @@ -1877,6 +1882,7 @@ struct dp_pdev { */ struct hal_rx_mon_desc_info *mon_desc; #endif + qdf_nbuf_t mcopy_status_nbuf; }; struct dp_peer; diff --git a/hal/wifi3.0/hal_api_mon.h b/hal/wifi3.0/hal_api_mon.h index c70bac38e4..a0569d8e64 100644 --- a/hal/wifi3.0/hal_api_mon.h +++ b/hal/wifi3.0/hal_api_mon.h @@ -161,6 +161,7 @@ /* Max MPDUs per status buffer */ #define HAL_RX_MAX_MPDU 256 #define HAL_RX_NUM_WORDS_PER_PPDU_BITMAP (HAL_RX_MAX_MPDU >> 5) +#define HAL_RX_MAX_MPDU_H_PER_STATUS_BUFFER 16 /* Max pilot count */ #define HAL_RX_MAX_SU_EVM_COUNT 32 @@ -476,12 +477,10 @@ struct hal_rx_ppdu_common_info { * struct hal_rx_msdu_payload_info - msdu payload info * @first_msdu_payload: pointer to first msdu payload * @payload_len: payload len - * @nbuf: status network buffer to which msdu belongs to */ struct hal_rx_msdu_payload_info { uint8_t *first_msdu_payload; uint32_t payload_len; - qdf_nbuf_t nbuf; }; /** @@ -630,8 +629,14 @@ struct hal_rx_ppdu_info { /* Id to indicate how to process mpdu */ uint8_t sw_frame_group_id; struct hal_rx_ppdu_msdu_info rx_msdu_info[HAL_MAX_UL_MU_USERS]; - /* first msdu payload for all mpdus in ppdu */ - struct hal_rx_msdu_payload_info ppdu_msdu_info[HAL_RX_MAX_MPDU]; + /* fcs passed mpdu count in rx monitor status buffer */ + uint8_t fcs_ok_cnt; + /* fcs error mpdu count in rx monitor status buffer */ + uint8_t fcs_err_cnt; + /* MPDU FCS passed */ + bool is_fcs_passed; + /* first msdu payload for all mpdus in rx monitor status buffer */ + struct hal_rx_msdu_payload_info ppdu_msdu_info[HAL_RX_MAX_MPDU_H_PER_STATUS_BUFFER]; /* evm info */ struct hal_rx_su_evm_info evm_info; /** diff --git a/hal/wifi3.0/hal_generic_api.h b/hal/wifi3.0/hal_generic_api.h index 308944e14f..2d8a0b33c3 100644 --- a/hal/wifi3.0/hal_generic_api.h +++ b/hal/wifi3.0/hal_generic_api.h @@ -1513,19 +1513,20 @@ hal_rx_status_get_tlv_info_generic(void *rx_tlv_hdr, void *ppduinfo, case WIFIRX_HEADER_E: { struct hal_rx_ppdu_common_info *com_info = &ppdu_info->com_info; - uint16_t mpdu_cnt = com_info->mpdu_cnt; - if (mpdu_cnt >= HAL_RX_MAX_MPDU) { - hal_alert("Number of MPDUs per PPDU exceeded"); + if (ppdu_info->fcs_ok_cnt >= + HAL_RX_MAX_MPDU_H_PER_STATUS_BUFFER) { + hal_err("Number of MPDUs(%d) per status buff exceeded", + ppdu_info->fcs_ok_cnt); break; } + /* Update first_msdu_payload for every mpdu and increment * com_info->mpdu_cnt for every WIFIRX_HEADER_E TLV */ - ppdu_info->ppdu_msdu_info[mpdu_cnt].first_msdu_payload = + ppdu_info->ppdu_msdu_info[ppdu_info->fcs_ok_cnt].first_msdu_payload = rx_tlv; - ppdu_info->ppdu_msdu_info[mpdu_cnt].payload_len = tlv_len; - ppdu_info->ppdu_msdu_info[mpdu_cnt].nbuf = nbuf; + ppdu_info->ppdu_msdu_info[ppdu_info->fcs_ok_cnt].payload_len = tlv_len; ppdu_info->msdu_info.first_msdu_payload = rx_tlv; ppdu_info->msdu_info.payload_len = tlv_len; ppdu_info->user_id = user_id;