qcacmn: add fix to send ppdu in sequential order

logic of holding ppdu info list is modified to store it
in sequential order.

Change-Id: I179e76f4bb1663e141e48df5f274ac5fd1b81bbc
This commit is contained in:
nobelj
2020-07-14 00:37:29 -07:00
committed by snandini
parent 94c430da4a
commit 4dd08941dd
6 changed files with 240 additions and 47 deletions

View File

@@ -1718,6 +1718,7 @@ struct cdp_cfr_rcc_stats {
* @tx_ppdu_proc: stats counter for tx ppdu processed * @tx_ppdu_proc: stats counter for tx ppdu processed
* @ack_ba_comes_twice: stats counter for ack_ba_comes twice * @ack_ba_comes_twice: stats counter for ack_ba_comes twice
* @ppdu_drop: stats counter for ppdu_desc drop once threshold reached * @ppdu_drop: stats counter for ppdu_desc drop once threshold reached
* @ppdu_wrap_drop: stats counter for ppdu desc drop on wrap around
*/ */
struct cdp_pdev_stats { struct cdp_pdev_stats {
struct { struct {
@@ -1784,6 +1785,7 @@ struct cdp_pdev_stats {
uint64_t tx_ppdu_proc; uint64_t tx_ppdu_proc;
uint64_t ack_ba_comes_twice; uint64_t ack_ba_comes_twice;
uint64_t ppdu_drop; uint64_t ppdu_drop;
uint64_t ppdu_wrap_drop;
struct { struct {
uint64_t num_bufs_consumed; uint64_t num_bufs_consumed;

View File

@@ -2705,10 +2705,6 @@ static void dp_process_ppdu_stats_user_cmpltn_common_tlv(
ppdu_desc->rts_failure = ppdu_desc->rts_failure =
HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_RTS_FAILURE_GET(*tag_buf); HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_RTS_FAILURE_GET(*tag_buf);
/*
* on mpdu success, increase compltn_common_tlv counter
*/
if (ppdu_user_desc->mpdu_success)
ppdu_info->compltn_common_tlv++; ppdu_info->compltn_common_tlv++;
/* /*
@@ -3014,7 +3010,7 @@ dp_process_ppdu_stats_user_compltn_flush_tlv(struct dp_pdev *pdev,
peer = dp_peer_find_by_id(pdev->soc, peer_id); peer = dp_peer_find_by_id(pdev->soc, peer_id);
if (!peer) if (!peer)
return; goto add_ppdu_to_sched_list;
if (ppdu_desc->drop_reason == HTT_FLUSH_EXCESS_RETRIES) { if (ppdu_desc->drop_reason == HTT_FLUSH_EXCESS_RETRIES) {
DP_STATS_INC(peer, DP_STATS_INC(peer,
@@ -3023,6 +3019,14 @@ dp_process_ppdu_stats_user_compltn_flush_tlv(struct dp_pdev *pdev,
} }
dp_peer_unref_del_find_by_id(peer); dp_peer_unref_del_find_by_id(peer);
add_ppdu_to_sched_list:
ppdu_info->done = 1;
TAILQ_REMOVE(&pdev->ppdu_info_list, ppdu_info, ppdu_info_list_elem);
pdev->list_depth--;
TAILQ_INSERT_TAIL(&pdev->sched_comp_ppdu_list, ppdu_info,
ppdu_info_list_elem);
pdev->sched_comp_list_depth++;
} }
/** /**
@@ -3156,6 +3160,11 @@ dp_process_ppdu_stats_sch_cmd_status_tlv(struct dp_pdev *pdev,
} }
} }
TAILQ_REMOVE(&pdev->ppdu_info_list, ppdu_info, ppdu_info_list_elem);
pdev->list_depth--;
TAILQ_INSERT_TAIL(&pdev->sched_comp_ppdu_list, ppdu_info,
ppdu_info_list_elem);
pdev->sched_comp_list_depth++;
} }
#ifndef WLAN_TX_PKT_CAPTURE_ENH #ifndef WLAN_TX_PKT_CAPTURE_ENH
@@ -3509,47 +3518,105 @@ static
void dp_ppdu_desc_deliver(struct dp_pdev *pdev, void dp_ppdu_desc_deliver(struct dp_pdev *pdev,
struct ppdu_info *ppdu_info) struct ppdu_info *ppdu_info)
{ {
struct ppdu_info *s_ppdu_info = NULL;
struct ppdu_info *ppdu_info_next = NULL;
struct cdp_tx_completion_ppdu *ppdu_desc = NULL; struct cdp_tx_completion_ppdu *ppdu_desc = NULL;
qdf_nbuf_t nbuf; qdf_nbuf_t nbuf;
uint32_t time_delta = 0;
bool starved = 0;
bool matched = 0;
bool recv_ack_ba_done = 0;
ppdu_desc = (struct cdp_tx_completion_ppdu *) if (ppdu_info->tlv_bitmap &
qdf_nbuf_data(ppdu_info->nbuf); (1 << HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV) &&
ppdu_info->done)
recv_ack_ba_done = 1;
dp_ppdu_desc_user_stats_update(pdev, ppdu_info); pdev->last_sched_cmdid = ppdu_info->sched_cmdid;
/* s_ppdu_info = TAILQ_FIRST(&pdev->sched_comp_ppdu_list);
* Remove from the list
*/
TAILQ_REMOVE(&pdev->ppdu_info_list, ppdu_info, ppdu_info_list_elem);
nbuf = ppdu_info->nbuf;
pdev->list_depth--;
qdf_mem_free(ppdu_info);
TAILQ_FOREACH_SAFE(s_ppdu_info, &pdev->sched_comp_ppdu_list,
ppdu_info_list_elem, ppdu_info_next) {
if (s_ppdu_info->tsf_l32 > ppdu_info->tsf_l32)
time_delta = (MAX_TSF_32 - s_ppdu_info->tsf_l32) +
ppdu_info->tsf_l32;
else
time_delta = ppdu_info->tsf_l32 - s_ppdu_info->tsf_l32;
if (!s_ppdu_info->done && !recv_ack_ba_done) {
if (time_delta < MAX_SCHED_STARVE) {
qdf_err("pdev[%d] ppdu_id[%d] sched_cmdid[%d] TLV_B[0x%x] TSF[%u] D[%d]",
pdev->pdev_id,
s_ppdu_info->ppdu_id,
s_ppdu_info->sched_cmdid,
s_ppdu_info->tlv_bitmap,
s_ppdu_info->tsf_l32,
s_ppdu_info->done);
break;
}
starved = 1;
}
pdev->delivered_sched_cmdid = s_ppdu_info->sched_cmdid;
TAILQ_REMOVE(&pdev->sched_comp_ppdu_list, s_ppdu_info,
ppdu_info_list_elem);
pdev->sched_comp_list_depth--;
nbuf = s_ppdu_info->nbuf;
qdf_assert_always(nbuf); qdf_assert_always(nbuf);
ppdu_desc = (struct cdp_tx_completion_ppdu *) ppdu_desc = (struct cdp_tx_completion_ppdu *)
qdf_nbuf_data(nbuf); qdf_nbuf_data(nbuf);
ppdu_desc->tlv_bitmap = s_ppdu_info->tlv_bitmap;
if (starved) {
qdf_err("ppdu starved fc[0x%x] h_ftype[%d] tlv_bitmap[0x%x] cs[%d]\n",
ppdu_desc->frame_ctrl,
ppdu_desc->htt_frame_type,
ppdu_desc->tlv_bitmap,
ppdu_desc->user[0].completion_status);
starved = 0;
}
if (ppdu_info->ppdu_id == s_ppdu_info->ppdu_id &&
ppdu_info->sched_cmdid == s_ppdu_info->sched_cmdid)
matched = 1;
dp_ppdu_desc_user_stats_update(pdev, s_ppdu_info);
qdf_mem_free(s_ppdu_info);
/** /**
* Deliver PPDU stats only for valid (acked) data frames if * Deliver PPDU stats only for valid (acked) data
* sniffer mode is not enabled. * frames if sniffer mode is not enabled.
* If sniffer mode is enabled, PPDU stats for all frames * If sniffer mode is enabled, PPDU stats
* including mgmt/control frames should be delivered to upper layer * for all frames including mgmt/control
* frames should be delivered to upper layer
*/ */
if (pdev->tx_sniffer_enable || pdev->mcopy_mode) { if (pdev->tx_sniffer_enable || pdev->mcopy_mode) {
dp_wdi_event_handler(WDI_EVENT_TX_PPDU_DESC, pdev->soc,
nbuf, HTT_INVALID_PEER,
WDI_NO_VAL, pdev->pdev_id);
} else {
if (ppdu_desc->num_mpdu != 0 && ppdu_desc->num_users != 0 &&
ppdu_desc->frame_ctrl & HTT_FRAMECTRL_DATATYPE) {
dp_wdi_event_handler(WDI_EVENT_TX_PPDU_DESC, dp_wdi_event_handler(WDI_EVENT_TX_PPDU_DESC,
pdev->soc, nbuf, HTT_INVALID_PEER, pdev->soc,
WDI_NO_VAL, pdev->pdev_id); nbuf, HTT_INVALID_PEER,
} else WDI_NO_VAL,
pdev->pdev_id);
} else {
if (ppdu_desc->num_mpdu != 0 &&
ppdu_desc->num_users != 0 &&
ppdu_desc->frame_ctrl &
HTT_FRAMECTRL_DATATYPE) {
dp_wdi_event_handler(WDI_EVENT_TX_PPDU_DESC,
pdev->soc,
nbuf, HTT_INVALID_PEER,
WDI_NO_VAL,
pdev->pdev_id);
} else {
qdf_nbuf_free(nbuf); qdf_nbuf_free(nbuf);
} }
}
if (matched)
break;
}
return; return;
} }
@@ -3561,26 +3628,100 @@ void dp_ppdu_desc_deliver(struct dp_pdev *pdev,
* @pdev: DP pdev handle * @pdev: DP pdev handle
* @ppdu_id: PPDU unique identifier * @ppdu_id: PPDU unique identifier
* @tlv_type: TLV type received * @tlv_type: TLV type received
* @tsf_l32: timestamp received along with ppdu stats indication header
* @max_users: Maximum user for that particular ppdu
* *
* return: ppdu_info per ppdu tlv structure * return: ppdu_info per ppdu tlv structure
*/ */
static static
struct ppdu_info *dp_get_ppdu_desc(struct dp_pdev *pdev, uint32_t ppdu_id, struct ppdu_info *dp_get_ppdu_desc(struct dp_pdev *pdev, uint32_t ppdu_id,
uint8_t tlv_type, uint8_t max_users) uint8_t tlv_type, uint32_t tsf_l32,
uint8_t max_users)
{ {
struct ppdu_info *ppdu_info = NULL; struct ppdu_info *ppdu_info = NULL;
struct ppdu_info *s_ppdu_info = NULL;
struct ppdu_info *ppdu_info_next = NULL;
struct cdp_tx_completion_ppdu *ppdu_desc = NULL; struct cdp_tx_completion_ppdu *ppdu_desc = NULL;
uint32_t size = 0; uint32_t size = 0;
struct cdp_tx_completion_ppdu *tmp_ppdu_desc = NULL;
struct cdp_tx_completion_ppdu_user *tmp_user;
uint32_t time_delta;
/* /*
* Find ppdu_id node exists or not * Find ppdu_id node exists or not
*/ */
TAILQ_FOREACH(ppdu_info, &pdev->ppdu_info_list, ppdu_info_list_elem) { TAILQ_FOREACH_SAFE(ppdu_info, &pdev->ppdu_info_list,
ppdu_info_list_elem, ppdu_info_next) {
if (ppdu_info && (ppdu_info->ppdu_id == ppdu_id)) { if (ppdu_info && (ppdu_info->ppdu_id == ppdu_id)) {
if (ppdu_info->tsf_l32 > tsf_l32)
time_delta = (MAX_TSF_32 -
ppdu_info->tsf_l32) + tsf_l32;
else
time_delta = tsf_l32 - ppdu_info->tsf_l32;
if (time_delta > WRAP_DROP_TSF_DELTA) {
TAILQ_REMOVE(&pdev->ppdu_info_list,
ppdu_info, ppdu_info_list_elem);
pdev->list_depth--;
pdev->stats.ppdu_wrap_drop++;
tmp_ppdu_desc =
(struct cdp_tx_completion_ppdu *)
qdf_nbuf_data(ppdu_info->nbuf);
tmp_user = &tmp_ppdu_desc->user[0];
QDF_TRACE(QDF_MODULE_ID_TX_CAPTURE,
QDF_TRACE_LEVEL_INFO_MED,
"S_PID [%d] S_TSF[%u] TLV_BITMAP[0x%x] [CMPLTN - %d ACK_BA - %d] CS[%d] - R_PID[%d] R_TSF[%u] R_TLV_TAG[0x%x]\n",
ppdu_info->ppdu_id,
ppdu_info->tsf_l32,
ppdu_info->tlv_bitmap,
tmp_user->completion_status,
ppdu_info->compltn_common_tlv,
ppdu_info->ack_ba_tlv,
ppdu_id, tsf_l32, tlv_type);
qdf_nbuf_free(ppdu_info->nbuf);
ppdu_info->nbuf = NULL;
qdf_mem_free(ppdu_info);
} else {
break; break;
} }
} }
}
/*
* check if it is ack ba tlv and if it is not there in ppdu info
* list then check it in sched completion ppdu list
*/
if (!ppdu_info &&
tlv_type == HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV) {
TAILQ_FOREACH(s_ppdu_info,
&pdev->sched_comp_ppdu_list,
ppdu_info_list_elem) {
if (s_ppdu_info && (s_ppdu_info->ppdu_id == ppdu_id)) {
if (s_ppdu_info->tsf_l32 > tsf_l32)
time_delta = (MAX_TSF_32 -
s_ppdu_info->tsf_l32) +
tsf_l32;
else
time_delta = tsf_l32 -
s_ppdu_info->tsf_l32;
if (time_delta < WRAP_DROP_TSF_DELTA) {
ppdu_info = s_ppdu_info;
break;
}
} else {
/*
* ACK BA STATUS TLV comes sequential order
* if we received ack ba status tlv for second
* ppdu and first ppdu is still waiting for
* ACK BA STATUS TLV. Based on fw comment
* we won't receive it tlv later. So we can
* set ppdu info done.
*/
if (s_ppdu_info)
s_ppdu_info->done = 1;
}
}
}
if (ppdu_info) { if (ppdu_info) {
if (ppdu_info->tlv_bitmap & (1 << tlv_type)) { if (ppdu_info->tlv_bitmap & (1 << tlv_type)) {
@@ -3663,7 +3804,7 @@ struct ppdu_info *dp_get_ppdu_desc(struct dp_pdev *pdev, uint32_t ppdu_id,
} }
ppdu_info->ppdu_desc->max_users = max_users; ppdu_info->ppdu_desc->max_users = max_users;
ppdu_info->tsf_l32 = tsf_l32;
/** /**
* No lock is needed because all PPDU TLVs are processed in * No lock is needed because all PPDU TLVs are processed in
* same context and this list is updated in same context * same context and this list is updated in same context
@@ -3693,6 +3834,7 @@ static struct ppdu_info *dp_htt_process_tlv(struct dp_pdev *pdev,
struct ppdu_info *ppdu_info = NULL; struct ppdu_info *ppdu_info = NULL;
struct cdp_tx_completion_ppdu *ppdu_desc = NULL; struct cdp_tx_completion_ppdu *ppdu_desc = NULL;
uint8_t max_users = CDP_MU_MAX_USERS; uint8_t max_users = CDP_MU_MAX_USERS;
uint32_t tsf_l32;
uint32_t *msg_word = (uint32_t *) qdf_nbuf_data(htt_t2h_msg); uint32_t *msg_word = (uint32_t *) qdf_nbuf_data(htt_t2h_msg);
@@ -3701,8 +3843,10 @@ static struct ppdu_info *dp_htt_process_tlv(struct dp_pdev *pdev,
msg_word = msg_word + 1; msg_word = msg_word + 1;
ppdu_id = HTT_T2H_PPDU_STATS_PPDU_ID_GET(*msg_word); ppdu_id = HTT_T2H_PPDU_STATS_PPDU_ID_GET(*msg_word);
msg_word = msg_word + 3; msg_word = msg_word + 1;
tsf_l32 = (uint32_t)(*msg_word);
msg_word = msg_word + 2;
while (length > 0) { while (length > 0) {
tlv_buf = (uint8_t *)msg_word; tlv_buf = (uint8_t *)msg_word;
tlv_type = HTT_STATS_TLV_TAG_GET(*msg_word); tlv_type = HTT_STATS_TLV_TAG_GET(*msg_word);
@@ -3744,7 +3888,8 @@ static struct ppdu_info *dp_htt_process_tlv(struct dp_pdev *pdev,
max_users = 1; max_users = 1;
} }
ppdu_info = dp_get_ppdu_desc(pdev, ppdu_id, tlv_type, max_users); ppdu_info = dp_get_ppdu_desc(pdev, ppdu_id, tlv_type,
tsf_l32, max_users);
if (!ppdu_info) if (!ppdu_info)
return NULL; return NULL;
@@ -3804,9 +3949,21 @@ static struct ppdu_info *dp_htt_process_tlv(struct dp_pdev *pdev,
if (ppdu_desc->frame_type != CDP_PPDU_FTYPE_CTRL && if (ppdu_desc->frame_type != CDP_PPDU_FTYPE_CTRL &&
ppdu_desc->htt_frame_type != HTT_STATS_FTYPE_SGEN_QOS_NULL) { ppdu_desc->htt_frame_type != HTT_STATS_FTYPE_SGEN_QOS_NULL) {
/* /*
* successful mpdu count should match with both tlv * most of the time bar frame will have duplicate ack ba
* status tlv
*/ */
if (ppdu_info->compltn_common_tlv != ppdu_info->ack_ba_tlv) if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_BAR &&
(ppdu_info->compltn_common_tlv != ppdu_info->ack_ba_tlv))
return NULL;
/*
* For data frame, compltn common tlv should match ack ba status
* tlv and completion status. Reason we are checking first user
* for ofdma, completion seen at next MU BAR frm, for mimo
* only for first user completion will be immediate.
*/
if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_DATA &&
(ppdu_desc->user[0].completion_status == 0 &&
(ppdu_info->compltn_common_tlv != ppdu_info->ack_ba_tlv)))
return NULL; return NULL;
} }
@@ -3822,8 +3979,10 @@ static struct ppdu_info *dp_htt_process_tlv(struct dp_pdev *pdev,
(ppdu_info->tlv_bitmap & (ppdu_info->tlv_bitmap &
(1 << HTT_PPDU_STATS_SCH_CMD_STATUS_TLV))) || (1 << HTT_PPDU_STATS_SCH_CMD_STATUS_TLV))) ||
(ppdu_info->tlv_bitmap & (ppdu_info->tlv_bitmap &
(1 << HTT_PPDU_STATS_USR_COMPLTN_FLUSH_TLV))) (1 << HTT_PPDU_STATS_USR_COMPLTN_FLUSH_TLV))) {
ppdu_info->done = 1;
return ppdu_info; return ppdu_info;
}
return NULL; return NULL;
} }

View File

@@ -137,6 +137,10 @@ void htt_htc_pkt_pool_free(struct htt_soc *soc);
#define HTT_GET_STATS_CMN_INDEX(index) \ #define HTT_GET_STATS_CMN_INDEX(index) \
HTT_PPDU_STATS_COMMON_TLV_##index##_OFFSET HTT_PPDU_STATS_COMMON_TLV_##index##_OFFSET
#define MAX_SCHED_STARVE 100000
#define WRAP_DROP_TSF_DELTA 10000
#define MAX_TSF_32 0xFFFFFFFF
/** /**
* enum dp_full_mon_config - enum to enable/disable full monitor mode * enum dp_full_mon_config - enum to enable/disable full monitor mode
* *

View File

@@ -4044,6 +4044,17 @@ static void dp_htt_ppdu_stats_detach(struct dp_pdev *pdev)
qdf_assert_always(ppdu_info->nbuf); qdf_assert_always(ppdu_info->nbuf);
qdf_nbuf_free(ppdu_info->nbuf); qdf_nbuf_free(ppdu_info->nbuf);
qdf_mem_free(ppdu_info); qdf_mem_free(ppdu_info);
pdev->list_depth--;
}
TAILQ_FOREACH_SAFE(ppdu_info, &pdev->sched_comp_ppdu_list,
ppdu_info_list_elem, ppdu_info_next) {
if (!ppdu_info)
break;
qdf_assert_always(ppdu_info->nbuf);
qdf_nbuf_free(ppdu_info->nbuf);
qdf_mem_free(ppdu_info);
pdev->sched_comp_list_depth--;
} }
if (pdev->ppdu_tlv_buf) if (pdev->ppdu_tlv_buf)
@@ -12709,6 +12720,7 @@ static inline QDF_STATUS dp_pdev_init(struct cdp_soc_t *txrx_soc,
* initialize ppdu tlv list * initialize ppdu tlv list
*/ */
TAILQ_INIT(&pdev->ppdu_info_list); TAILQ_INIT(&pdev->ppdu_info_list);
TAILQ_INIT(&pdev->sched_comp_ppdu_list);
pdev->tlv_count = 0; pdev->tlv_count = 0;
pdev->list_depth = 0; pdev->list_depth = 0;

View File

@@ -6293,12 +6293,21 @@ dp_print_pdev_tx_stats(struct dp_pdev *pdev)
} }
DP_PRINT_STATS("BA not received for delayed_ba: %d", DP_PRINT_STATS("BA not received for delayed_ba: %d",
pdev->stats.cdp_delayed_ba_not_recev); pdev->stats.cdp_delayed_ba_not_recev);
DP_PRINT_STATS("ppdu info schedule completion list depth: %d",
pdev->sched_comp_list_depth);
DP_PRINT_STATS("cur sched cmdid: %d", pdev->last_sched_cmdid);
DP_PRINT_STATS("delivered sched cmdid: %d",
pdev->delivered_sched_cmdid);
DP_PRINT_STATS("ppdu info list depth: %d",
pdev->list_depth);
DP_PRINT_STATS("tx_ppdu_proc: %llu", DP_PRINT_STATS("tx_ppdu_proc: %llu",
pdev->stats.tx_ppdu_proc); pdev->stats.tx_ppdu_proc);
DP_PRINT_STATS("ack ba comes twice: %llu", DP_PRINT_STATS("ack ba comes twice: %llu",
pdev->stats.ack_ba_comes_twice); pdev->stats.ack_ba_comes_twice);
DP_PRINT_STATS("ppdu dropped because of incomplete tlv: %llu", DP_PRINT_STATS("ppdu dropped because of incomplete tlv: %llu",
pdev->stats.ppdu_drop); pdev->stats.ppdu_drop);
DP_PRINT_STATS("ppdu dropped because of wrap around: %llu",
pdev->stats.ppdu_wrap_drop);
for (i = 0; i < CDP_WDI_NUM_EVENTS; i++) { for (i = 0; i < CDP_WDI_NUM_EVENTS; i++) {
if (!pdev->stats.wdi_event[i]) if (!pdev->stats.wdi_event[i])

View File

@@ -1540,6 +1540,7 @@ struct ppdu_info {
uint32_t ppdu_id; uint32_t ppdu_id;
uint32_t sched_cmdid; uint32_t sched_cmdid;
uint32_t max_ppdu_id; uint32_t max_ppdu_id;
uint32_t tsf_l32;
uint16_t tlv_bitmap; uint16_t tlv_bitmap;
uint16_t last_tlv_cnt; uint16_t last_tlv_cnt;
uint16_t last_user:8, uint16_t last_user:8,
@@ -1558,6 +1559,7 @@ struct ppdu_info {
#endif #endif
uint8_t compltn_common_tlv; uint8_t compltn_common_tlv;
uint8_t ack_ba_tlv; uint8_t ack_ba_tlv;
bool done;
}; };
/** /**
@@ -1870,6 +1872,11 @@ struct dp_pdev {
#endif #endif
/* list of ppdu tlvs */ /* list of ppdu tlvs */
TAILQ_HEAD(, ppdu_info) ppdu_info_list; TAILQ_HEAD(, ppdu_info) ppdu_info_list;
TAILQ_HEAD(, ppdu_info) sched_comp_ppdu_list;
uint32_t sched_comp_list_depth;
uint16_t delivered_sched_cmdid;
uint16_t last_sched_cmdid;
uint32_t tlv_count; uint32_t tlv_count;
uint32_t list_depth; uint32_t list_depth;
uint32_t ppdu_id; uint32_t ppdu_id;