From 7b0e27336e9a73ba53012535507e430bf2c77542 Mon Sep 17 00:00:00 2001 From: nobelj Date: Fri, 31 May 2019 00:19:07 -0700 Subject: [PATCH] qcacmn: Fix OFDMA stats counter user info with delayed ba stats are stored and stats are updated later on receiving BAR. Change-Id: I574dd94d5a7db2160953b5d5d302eff18f4f8648 --- dp/inc/cdp_txrx_cmn_struct.h | 55 ++++++ dp/inc/cdp_txrx_stats_struct.h | 57 ++++++- dp/wifi3.0/dp_htt.c | 303 ++++++++++++++++++++++++++++++--- dp/wifi3.0/dp_internal.h | 32 ++++ dp/wifi3.0/dp_main.c | 2 + dp/wifi3.0/dp_peer.c | 26 +++ dp/wifi3.0/dp_stats.c | 28 +-- dp/wifi3.0/dp_types.h | 14 +- 8 files changed, 481 insertions(+), 36 deletions(-) diff --git a/dp/inc/cdp_txrx_cmn_struct.h b/dp/inc/cdp_txrx_cmn_struct.h index 90c17afcc4..8dc063e9b9 100644 --- a/dp/inc/cdp_txrx_cmn_struct.h +++ b/dp/inc/cdp_txrx_cmn_struct.h @@ -1151,6 +1151,57 @@ struct cdp_tx_sojourn_stats { struct cdp_stats_cookie *cookie; }; +/** + * struct cdp_delayed_tx_completion_ppdu_user - Delayed Tx PPDU completion + * per-user information + * @frame_ctrl: frame control field in 802.11 header + * @qos_ctrl: QoS control field in 802.11 header + * @mpdu_tried: number of mpdus tried + * @ltf_size: ltf_size + * @stbc: stbc + * @he_re: he_re (range extension) + * @txbf: txbf + * @bw: Transmission bandwidth + * + * + * + * + * @nss: NSS 1,2, ...8 + * @mcs: MCS index + * @preamble: preamble + * @gi: guard interval 800/400/1600/3200 ns + * @dcm: dcm + * @ldpc: ldpc + * @ru_start: RU start index + * @ru_tones: RU tones length + * @is_mcast: MCAST or UCAST + * @user_pos: user position + * @mu_group_id: mu group id + */ +struct cdp_delayed_tx_completion_ppdu_user { + uint32_t frame_ctrl:16, + qos_ctrl:16; + uint32_t mpdu_tried_ucast:16, + mpdu_tried_mcast:16; + uint32_t ltf_size:2, + stbc:1, + he_re:1, + txbf:4, + bw:4, + nss:4, + mcs:4, + preamble:4, + gi:4, + dcm:1, + ldpc:1, + delayed_ba:1; + uint16_t ru_start; + uint16_t ru_tones; + bool is_mcast; + uint32_t user_pos; + uint32_t mu_group_id; +}; + /** * struct cdp_tx_completion_ppdu_user - Tx PPDU completion per-user information * @completion_status: completion status - OK/Filter/Abort/Timeout @@ -1354,6 +1405,7 @@ struct cdp_tx_indication_info { * @ppdu_id: PPDU Id * @ppdu_seq_id: ppdu sequence id for sojourn stats * @vdev_id: VAP Id + * @bar_num_users: BA response user count, based on completion common TLV * @num_users: Number of users * @num_mpdu: Number of MPDUs in PPDU * @num_msdu: Number of MSDUs in PPDU @@ -1365,6 +1417,7 @@ struct cdp_tx_indication_info { * @ppdu_start_timestamp: TSF at PPDU start * @ppdu_end_timestamp: TSF at PPDU end * @ack_timestamp: TSF at the reception of ACK + * @delayed_ba: Delayed ba flag * @user: per-User stats (array of per-user structures) * @mpdu_q: queue of mpdu in a ppdu */ @@ -1372,6 +1425,7 @@ struct cdp_tx_completion_ppdu { uint32_t ppdu_id; uint32_t ppdu_seq_id; uint16_t vdev_id; + uint16_t bar_num_users; uint32_t num_users; uint8_t last_usr_index; uint32_t num_mpdu:9, @@ -1385,6 +1439,7 @@ struct cdp_tx_completion_ppdu { uint32_t ppdu_start_timestamp; uint32_t ppdu_end_timestamp; uint32_t ack_timestamp; + bool delayed_ba; struct cdp_tx_completion_ppdu_user user[CDP_MU_MAX_USERS]; qdf_nbuf_queue_t mpdu_q; }; diff --git a/dp/inc/cdp_txrx_stats_struct.h b/dp/inc/cdp_txrx_stats_struct.h index e6eaca6a84..6cb31b7a80 100644 --- a/dp/inc/cdp_txrx_stats_struct.h +++ b/dp/inc/cdp_txrx_stats_struct.h @@ -127,6 +127,39 @@ (((nssb) & CDP_TXRX_RATECODE_NSS_MASK) << CDP_TXRX_RATECODE_NSS_LSB) | \ (((premb) & CDP_TXRX_RATECODE_PREM_MASK) << CDP_TXRX_RATECODE_PREM_LSB)) +/* + * cdp_tx_transmit_type: Transmit type index + * SU: SU Transmit type index + * MU_MIMO: MU_MIMO Transmit type index + * MU_OFDMA: MU_OFDMA Transmit type index + * MU_MIMO_OFDMA: MU MIMO OFDMA Transmit type index + */ +enum cdp_tx_transmit_type { + SU = 0, + MU_MIMO, + MU_OFDMA, + MU_MIMO_OFDMA, +}; + +/* + * cdp_ru_index: Different RU index + * + * RU_26_INDEX : 26-tone Resource Unit index + * RU_52_INDEX : 52-tone Resource Unit index + * RU_106_INDEX: 106-tone Resource Unit index + * RU_242_INDEX: 242-tone Resource Unit index + * RU_484_INDEX: 484-tone Resource Unit index + * RU_996_INDEX: 996-tone Resource Unit index + */ +enum cdp_ru_index { + RU_26_INDEX = 0, + RU_52_INDEX, + RU_106_INDEX, + RU_242_INDEX, + RU_484_INDEX, + RU_996_INDEX, +}; + /* Different Packet Types */ enum cdp_packet_type { DOT11_A = 0, @@ -383,6 +416,19 @@ struct cdp_pkt_type { uint32_t mcs_count[MAX_MCS]; }; +/* struct cdp_tx_pkt_info - tx packet info + * num_msdu - successful msdu + * num_mpdu - successful mpdu from compltn common + * mpdu_tried - mpdu tried + * + * tx packet info counter field for mpdu success/tried and msdu + */ +struct cdp_tx_pkt_info { + uint32_t num_msdu; + uint32_t num_mpdu; + uint32_t mpdu_tried; +}; + /* struct cdp_tx_stats - tx stats * @cdp_pkt_info comp_pkt: Pkt Info for which completions were received * @cdp_pkt_info ucast: Unicast Packet Count @@ -452,11 +498,11 @@ struct cdp_pkt_type { * @failed_retry_count: packets failed due to retry above 802.11 retry limit * @retry_count: packets successfully send after one or more retry * @multiple_retry_count: packets successfully sent after more than one retry - * @transmit_type: tx transmit type + * @transmit_type: pkt info for tx transmit type * @mu_group_id: mumimo mu group id * @ru_start: RU start index * @ru_tones: RU tones size - * @ru_loc: RU location 26/ 52/ 106/ 242/ 484 counter + * @ru_loc: pkt info for RU location 26/ 52/ 106/ 242/ 484 counter * @num_ppdu_cookie_valid : Number of comp received with valid ppdu cookie */ struct cdp_tx_stats { @@ -538,11 +584,12 @@ struct cdp_tx_stats { uint32_t multiple_retry_count; uint32_t last_tx_rate_used; - uint32_t transmit_type[MAX_TRANSMIT_TYPES]; + struct cdp_tx_pkt_info transmit_type[MAX_TRANSMIT_TYPES]; uint32_t mu_group_id[MAX_MU_GROUP_ID]; uint32_t ru_start; uint32_t ru_tones; - uint32_t ru_loc[MAX_RU_LOCATIONS]; + struct cdp_tx_pkt_info ru_loc[MAX_RU_LOCATIONS]; + uint32_t num_ppdu_cookie_valid; }; @@ -1248,6 +1295,7 @@ struct cdp_htt_rx_pdev_stats { * @tx_comp_histogram: Number of Tx completions per interrupt * @rx_ind_histogram: Number of Rx ring descriptors reaped per interrupt * @ppdu_stats_counter: ppdu stats counter + * @cdp_delayed_ba_not_recev: counter for delayed ba not received * @htt_tx_pdev_stats: htt pdev stats for tx * @htt_rx_pdev_stats: htt pdev stats for rx */ @@ -1293,6 +1341,7 @@ struct cdp_pdev_stats { struct cdp_hist_tx_comp tx_comp_histogram; struct cdp_hist_rx_ind rx_ind_histogram; uint64_t ppdu_stats_counter[CDP_PPDU_STATS_MAX_TAG]; + uint32_t cdp_delayed_ba_not_recev; struct cdp_htt_tx_pdev_stats htt_tx_pdev_stats; struct cdp_htt_rx_pdev_stats htt_rx_pdev_stats; diff --git a/dp/wifi3.0/dp_htt.c b/dp/wifi3.0/dp_htt.c index 349aca11f4..cbb4ccd650 100644 --- a/dp/wifi3.0/dp_htt.c +++ b/dp/wifi3.0/dp_htt.c @@ -66,6 +66,108 @@ dp_htt_get_ppdu_sniffer_ampdu_tlv_bitmap(uint32_t bitmap) } #ifdef FEATURE_PERPKT_INFO +/* + * dp_peer_copy_delay_stats() - copy ppdu stats to peer delayed stats. + * @peer: Datapath peer handle + * @ppdu: PPDU Descriptor + * + * Return: None + * + * on Tx data frame, we may get delayed ba set + * in htt_ppdu_stats_user_common_tlv. which mean we get Block Ack(BA) after we + * request Block Ack Request(BAR). Successful msdu is received only after Block + * Ack. To populate peer stats we need successful msdu(data frame). + * So we hold the Tx data stats on delayed_ba for stats update. + */ +static inline void +dp_peer_copy_delay_stats(struct dp_peer *peer, + struct cdp_tx_completion_ppdu_user *ppdu) +{ + struct dp_pdev *pdev; + struct dp_vdev *vdev; + + if (peer->last_delayed_ba) { + QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, + "BA not yet recv for prev delayed ppdu[%d]\n", + peer->last_delayed_ba_ppduid); + vdev = peer->vdev; + if (vdev) { + pdev = vdev->pdev; + pdev->stats.cdp_delayed_ba_not_recev++; + } + } + + peer->delayed_ba_ppdu_stats.ltf_size = ppdu->ltf_size; + peer->delayed_ba_ppdu_stats.stbc = ppdu->stbc; + peer->delayed_ba_ppdu_stats.he_re = ppdu->he_re; + peer->delayed_ba_ppdu_stats.txbf = ppdu->txbf; + peer->delayed_ba_ppdu_stats.bw = ppdu->bw; + peer->delayed_ba_ppdu_stats.nss = ppdu->nss; + peer->delayed_ba_ppdu_stats.preamble = ppdu->preamble; + peer->delayed_ba_ppdu_stats.gi = ppdu->gi; + peer->delayed_ba_ppdu_stats.dcm = ppdu->dcm; + peer->delayed_ba_ppdu_stats.ldpc = ppdu->ldpc; + peer->delayed_ba_ppdu_stats.dcm = ppdu->dcm; + peer->delayed_ba_ppdu_stats.mpdu_tried_ucast = ppdu->mpdu_tried_ucast; + peer->delayed_ba_ppdu_stats.mpdu_tried_mcast = ppdu->mpdu_tried_mcast; + peer->delayed_ba_ppdu_stats.frame_ctrl = ppdu->frame_ctrl; + peer->delayed_ba_ppdu_stats.qos_ctrl = ppdu->qos_ctrl; + peer->delayed_ba_ppdu_stats.dcm = ppdu->dcm; + + peer->delayed_ba_ppdu_stats.ru_start = ppdu->ru_start; + peer->delayed_ba_ppdu_stats.ru_tones = ppdu->ru_tones; + peer->delayed_ba_ppdu_stats.is_mcast = ppdu->is_mcast; + + peer->delayed_ba_ppdu_stats.user_pos = ppdu->user_pos; + peer->delayed_ba_ppdu_stats.mu_group_id = ppdu->mu_group_id; + + peer->last_delayed_ba = true; +} + +/* + * dp_peer_copy_stats_to_bar() - copy delayed stats to ppdu stats. + * @peer: Datapath peer handle + * @ppdu: PPDU Descriptor + * + * Return: None + * + * For Tx BAR, PPDU stats TLV include Block Ack info. PPDU info + * from Tx BAR frame not required to populate peer stats. + * But we need successful MPDU and MSDU to update previous + * transmitted Tx data frame. Overwrite ppdu stats with the previous + * stored ppdu stats. + */ +static void +dp_peer_copy_stats_to_bar(struct dp_peer *peer, + struct cdp_tx_completion_ppdu_user *ppdu) +{ + ppdu->ltf_size = peer->delayed_ba_ppdu_stats.ltf_size; + ppdu->stbc = peer->delayed_ba_ppdu_stats.stbc; + ppdu->he_re = peer->delayed_ba_ppdu_stats.he_re; + ppdu->txbf = peer->delayed_ba_ppdu_stats.txbf; + ppdu->bw = peer->delayed_ba_ppdu_stats.bw; + ppdu->nss = peer->delayed_ba_ppdu_stats.nss; + ppdu->preamble = peer->delayed_ba_ppdu_stats.preamble; + ppdu->gi = peer->delayed_ba_ppdu_stats.gi; + ppdu->dcm = peer->delayed_ba_ppdu_stats.dcm; + ppdu->ldpc = peer->delayed_ba_ppdu_stats.ldpc; + ppdu->dcm = peer->delayed_ba_ppdu_stats.dcm; + ppdu->mpdu_tried_ucast = peer->delayed_ba_ppdu_stats.mpdu_tried_ucast; + ppdu->mpdu_tried_mcast = peer->delayed_ba_ppdu_stats.mpdu_tried_mcast; + ppdu->frame_ctrl = peer->delayed_ba_ppdu_stats.frame_ctrl; + ppdu->qos_ctrl = peer->delayed_ba_ppdu_stats.qos_ctrl; + ppdu->dcm = peer->delayed_ba_ppdu_stats.dcm; + + ppdu->ru_start = peer->delayed_ba_ppdu_stats.ru_start; + ppdu->ru_tones = peer->delayed_ba_ppdu_stats.ru_tones; + ppdu->is_mcast = peer->delayed_ba_ppdu_stats.is_mcast; + + ppdu->user_pos = peer->delayed_ba_ppdu_stats.user_pos; + ppdu->mu_group_id = peer->delayed_ba_ppdu_stats.mu_group_id; + + peer->last_delayed_ba = false; +} + /* * dp_tx_rate_stats_update() - Update rate per-peer statistics * @peer: Datapath peer handle @@ -139,10 +241,14 @@ dp_tx_stats_update(struct dp_soc *soc, struct dp_peer *peer, struct dp_pdev *pdev = peer->vdev->pdev; uint8_t preamble, mcs; uint16_t num_msdu; + uint16_t num_mpdu; + uint16_t mpdu_tried; preamble = ppdu->preamble; mcs = ppdu->mcs; num_msdu = ppdu->num_msdu; + num_mpdu = ppdu->mpdu_success; + mpdu_tried = ppdu->mpdu_tried_ucast + ppdu->mpdu_tried_mcast; /* If the peer statistics are already processed as part of * per-MSDU completion handler, do not process these again in per-PPDU @@ -176,27 +282,63 @@ dp_tx_stats_update(struct dp_soc *soc, struct dp_peer *peer, DP_STATS_UPD(peer, tx.ru_start, ppdu->ru_start); switch (ppdu->ru_tones) { case RU_26: - DP_STATS_INC(peer, tx.ru_loc[0], num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_26_INDEX].num_msdu, + num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_26_INDEX].num_mpdu, + num_mpdu); + DP_STATS_INC(peer, tx.ru_loc[RU_26_INDEX].mpdu_tried, + mpdu_tried); break; case RU_52: - DP_STATS_INC(peer, tx.ru_loc[1], num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_52_INDEX].num_msdu, + num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_52_INDEX].num_mpdu, + num_mpdu); + DP_STATS_INC(peer, tx.ru_loc[RU_52_INDEX].mpdu_tried, + mpdu_tried); break; case RU_106: - DP_STATS_INC(peer, tx.ru_loc[2], num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_106_INDEX].num_msdu, + num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_106_INDEX].num_mpdu, + num_mpdu); + DP_STATS_INC(peer, tx.ru_loc[RU_106_INDEX].mpdu_tried, + mpdu_tried); break; case RU_242: - DP_STATS_INC(peer, tx.ru_loc[3], num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_242_INDEX].num_msdu, + num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_242_INDEX].num_mpdu, + num_mpdu); + DP_STATS_INC(peer, tx.ru_loc[RU_242_INDEX].mpdu_tried, + mpdu_tried); break; case RU_484: - DP_STATS_INC(peer, tx.ru_loc[4], num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_484_INDEX].num_msdu, + num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_484_INDEX].num_mpdu, + num_mpdu); + DP_STATS_INC(peer, tx.ru_loc[RU_484_INDEX].mpdu_tried, + mpdu_tried); break; case RU_996: - DP_STATS_INC(peer, tx.ru_loc[5], num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_996_INDEX].num_msdu, + num_msdu); + DP_STATS_INC(peer, tx.ru_loc[RU_996_INDEX].num_mpdu, + num_mpdu); + DP_STATS_INC(peer, tx.ru_loc[RU_996_INDEX].mpdu_tried, + mpdu_tried); break; } } - DP_STATS_INC(peer, tx.transmit_type[ppdu->ppdu_type], num_msdu); + DP_STATS_INC(peer, tx.transmit_type[ppdu->ppdu_type].num_msdu, + num_msdu); + DP_STATS_INC(peer, tx.transmit_type[ppdu->ppdu_type].num_mpdu, + num_mpdu); + DP_STATS_INC(peer, tx.transmit_type[ppdu->ppdu_type].mpdu_tried, + mpdu_tried); + DP_STATS_INC_PKT(peer, tx.comp_pkt, num_msdu, (ppdu->success_bytes + ppdu->retry_bytes + ppdu->failed_bytes)); @@ -1948,6 +2090,7 @@ static void dp_process_ppdu_stats_user_common_tlv( if (HTT_PPDU_STATS_USER_COMMON_TLV_DELAYED_BA_GET(*tag_buf)) { ppdu_user_desc->delayed_ba = 1; + ppdu_desc->delayed_ba = 1; } if (HTT_PPDU_STATS_USER_COMMON_TLV_MCAST_GET(*tag_buf)) { @@ -1968,11 +2111,8 @@ static void dp_process_ppdu_stats_user_common_tlv( HTT_PPDU_STATS_USER_COMMON_TLV_FRAME_CTRL_GET(*tag_buf); ppdu_desc->frame_ctrl = ppdu_user_desc->frame_ctrl; - if (ppdu_user_desc->delayed_ba) { + if (ppdu_user_desc->delayed_ba) ppdu_user_desc->mpdu_success = 0; - ppdu_user_desc->mpdu_tried_mcast = 0; - ppdu_user_desc->mpdu_tried_ucast = 0; - } tag_buf += 3; @@ -2244,6 +2384,19 @@ static void dp_process_ppdu_stats_user_cmpltn_common_tlv( HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_IS_AMPDU_GET(*tag_buf); ppdu_info->is_ampdu = ppdu_user_desc->is_ampdu; + /* + * increase successful mpdu counter from + * htt_ppdu_stats_user_cmpltn_common_tlv + */ + ppdu_info->mpdu_compltn_common_tlv += ppdu_user_desc->mpdu_success; + + /* + * MU BAR may send request to n users but we may received ack only from + * m users. To have count of number of users respond back, we have a + * separate counter bar_num_users per PPDU that get increment for every + * htt_ppdu_stats_user_cmpltn_common_tlv + */ + ppdu_desc->bar_num_users++; } /* @@ -2372,6 +2525,8 @@ static void dp_process_ppdu_stats_user_compltn_ack_ba_status_tlv( tag_buf += 2; ppdu_user_desc->success_bytes = *tag_buf; + /* increase successful mpdu counter */ + ppdu_info->mpdu_ack_ba_tlv += ppdu_user_desc->num_mpdu; } /* @@ -2683,6 +2838,7 @@ dp_ppdu_desc_user_stats_update(struct dp_pdev *pdev, uint32_t tlv_bitmap_expected; uint32_t tlv_bitmap_default; uint16_t i; + uint32_t num_users; ppdu_desc = (struct cdp_tx_completion_ppdu *) qdf_nbuf_data(ppdu_info->nbuf); @@ -2699,7 +2855,15 @@ dp_ppdu_desc_user_stats_update(struct dp_pdev *pdev, } tlv_bitmap_default = tlv_bitmap_expected; - for (i = 0; i < ppdu_desc->num_users; i++) { + + if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_BAR) { + num_users = ppdu_desc->bar_num_users; + ppdu_desc->num_users = ppdu_desc->bar_num_users; + } else { + num_users = ppdu_desc->num_users; + } + + for (i = 0; i < num_users; i++) { ppdu_desc->num_mpdu += ppdu_desc->user[i].num_mpdu; ppdu_desc->num_msdu += ppdu_desc->user[i].num_msdu; @@ -2717,17 +2881,31 @@ dp_ppdu_desc_user_stats_update(struct dp_pdev *pdev, HTT_PPDU_STATS_USER_STATUS_OK) tlv_bitmap_expected = tlv_bitmap_expected & 0xFF; - if (ppdu_info->tlv_bitmap != tlv_bitmap_expected) { + /* + * different frame like DATA, BAR or CTRL has different + * tlv bitmap expected. Apart from ACK_BA_STATUS TLV, we + * receive other tlv in-order/sequential from fw. + * Since ACK_BA_STATUS TLV come from Hardware it is + * asynchronous So we need to depend on some tlv to confirm + * all tlv is received for a ppdu. + * So we depend on both HTT_PPDU_STATS_COMMON_TLV and + * ACK_BA_STATUS_TLV. + */ + if (!(ppdu_info->tlv_bitmap & + (1 << HTT_PPDU_STATS_COMMON_TLV)) || + !(ppdu_info->tlv_bitmap & + (1 << HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV))) { dp_peer_unref_del_find_by_id(peer); continue; } + /** * Update tx stats for data frames having Qos as well as * non-Qos data tid */ if ((ppdu_desc->user[i].tid < CDP_DATA_TID_MAX || (ppdu_desc->user[i].tid == CDP_DATA_NON_QOS_TID)) && - (ppdu_desc->frame_type == CDP_PPDU_FTYPE_DATA)) { + (ppdu_desc->frame_type != CDP_PPDU_FTYPE_CTRL)) { dp_tx_stats_update(pdev->soc, peer, &ppdu_desc->user[i], @@ -2839,6 +3017,15 @@ struct ppdu_info *dp_get_ppdu_desc(struct dp_pdev *pdev, uint32_t ppdu_id, (1 << HTT_PPDU_STATS_SCH_CMD_STATUS_TLV))) return ppdu_info; + /** + * apart from ACK BA STATUS TLV rest all comes in order + * so if tlv type not ACK BA STATUS TLV we can deliver + * ppdu_info + */ + if (tlv_type == + HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV) + return ppdu_info; + dp_ppdu_desc_deliver(pdev, ppdu_info); } else { return ppdu_info; @@ -2913,6 +3100,8 @@ static struct ppdu_info *dp_htt_process_tlv(struct dp_pdev *pdev, uint8_t *tlv_buf; struct ppdu_info *ppdu_info = NULL; struct cdp_tx_completion_ppdu *ppdu_desc = NULL; + struct dp_peer *peer; + uint32_t i = 0; uint32_t *msg_word = (uint32_t *) qdf_nbuf_data(htt_t2h_msg); @@ -2977,13 +3166,6 @@ static struct ppdu_info *dp_htt_process_tlv(struct dp_pdev *pdev, tlv_bitmap_expected = HTT_PPDU_DEFAULT_TLV_BITMAP; - ppdu_desc = ppdu_info->ppdu_desc; - if (ppdu_desc && - ppdu_desc->user[ppdu_desc->last_usr_index].completion_status != - HTT_PPDU_STATS_USER_STATUS_OK) { - tlv_bitmap_expected = tlv_bitmap_expected & 0xFF; - } - if (pdev->tx_sniffer_enable || pdev->mcopy_mode) { if (ppdu_info->is_ampdu) tlv_bitmap_expected = @@ -2991,6 +3173,85 @@ static struct ppdu_info *dp_htt_process_tlv(struct dp_pdev *pdev, ppdu_info->tlv_bitmap); } + ppdu_desc = ppdu_info->ppdu_desc; + + if (!ppdu_desc) + return NULL; + + if (ppdu_desc->user[ppdu_desc->last_usr_index].completion_status != + HTT_PPDU_STATS_USER_STATUS_OK) { + tlv_bitmap_expected = tlv_bitmap_expected & 0xFF; + } + + if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_DATA && + (ppdu_info->tlv_bitmap & (1 << HTT_PPDU_STATS_COMMON_TLV)) && + ppdu_desc->delayed_ba) { + for (i = 0; i < ppdu_desc->num_users; i++) { + uint32_t ppdu_id; + + ppdu_id = ppdu_desc->ppdu_id; + peer = dp_peer_find_by_id(pdev->soc, + ppdu_desc->user[i].peer_id); + /** + * This check is to make sure peer is not deleted + * after processing the TLVs. + */ + if (!peer) + continue; + + /** + * save delayed ba user info + */ + if (ppdu_desc->user[i].delayed_ba) { + dp_peer_copy_delay_stats(peer, + &ppdu_desc->user[i]); + peer->last_delayed_ba_ppduid = ppdu_id; + } + dp_peer_unref_del_find_by_id(peer); + } + } + + /* + * when frame type is BAR and STATS_COMMON_TLV is set + * copy the store peer delayed info to BAR status + */ + if (ppdu_desc->frame_type == CDP_PPDU_FTYPE_BAR && + (ppdu_info->tlv_bitmap & (1 << HTT_PPDU_STATS_COMMON_TLV))) { + for (i = 0; i < ppdu_desc->bar_num_users; i++) { + peer = dp_peer_find_by_id(pdev->soc, + ppdu_desc->user[i].peer_id); + /** + * This check is to make sure peer is not deleted + * after processing the TLVs. + */ + if (!peer) + continue; + + if (peer->last_delayed_ba) { + dp_peer_copy_stats_to_bar(peer, + &ppdu_desc->user[i]); + } + dp_peer_unref_del_find_by_id(peer); + } + } + + /* + * for frame type DATA and BAR, we update stats based on MSDU, + * successful msdu and mpdu are populate from ACK BA STATUS TLV + * which comes out of order. successful mpdu also populated from + * COMPLTN COMMON TLV which comes in order. for every ppdu_info + * we store successful mpdu from both tlv and compare before delivering + * to make sure we received ACK BA STATUS TLV. + */ + if (ppdu_desc->frame_type != CDP_PPDU_FTYPE_CTRL) { + /* + * successful mpdu count should match with both tlv + */ + if (ppdu_info->mpdu_compltn_common_tlv != + ppdu_info->mpdu_ack_ba_tlv) + return NULL; + } + /** * Once all the TLVs for a given PPDU has been processed, * return PPDU status to be delivered to higher layer diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index b42741a1ad..21df93eeaa 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -63,6 +63,21 @@ (1 << HTT_PPDU_STATS_USR_COMPLTN_COMMON_TLV) | \ (1 << HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV) +/** + * Bitmap of HTT PPDU delayed ba TLV types for Default mode + */ +#define HTT_PPDU_DELAYED_BA_TLV_BITMAP \ + (1 << HTT_PPDU_STATS_COMMON_TLV) | \ + (1 << HTT_PPDU_STATS_USR_COMMON_TLV) | \ + (1 << HTT_PPDU_STATS_USR_RATE_TLV) + +/** + * Bitmap of HTT PPDU TLV types for Delayed BA + */ +#define HTT_PPDU_STATUS_TLV_BITMAP \ + (1 << HTT_PPDU_STATS_COMMON_TLV) | \ + (1 << HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV) + /** * Bitmap of HTT PPDU TLV types for Sniffer mode bitmap 64 */ @@ -739,6 +754,23 @@ extern void dp_peer_find_detach(struct dp_soc *soc); extern void dp_peer_find_hash_add(struct dp_soc *soc, struct dp_peer *peer); extern void dp_peer_find_hash_remove(struct dp_soc *soc, struct dp_peer *peer); extern void dp_peer_find_hash_erase(struct dp_soc *soc); + +/* + * dp_peer_ppdu_delayed_ba_init() Initialize ppdu in peer + * @peer: Datapath peer + * + * return: void + */ +void dp_peer_ppdu_delayed_ba_init(struct dp_peer *peer); + +/* + * dp_peer_ppdu_delayed_ba_cleanup() free ppdu allocated in peer + * @peer: Datapath peer + * + * return: void + */ +void dp_peer_ppdu_delayed_ba_cleanup(struct dp_peer *peer); + extern void dp_peer_rx_init(struct dp_pdev *pdev, struct dp_peer *peer); void dp_peer_tx_init(struct dp_pdev *pdev, struct dp_peer *peer); extern void dp_peer_cleanup(struct dp_vdev *vdev, struct dp_peer *peer); diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 76777c9c13..26ca66c8db 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -5392,6 +5392,8 @@ static void dp_peer_setup_wifi3(struct cdp_vdev *vdev_hdl, void *peer_hdl) dp_peer_rx_init(pdev, peer); dp_peer_tx_init(pdev, peer); + dp_peer_ppdu_delayed_ba_init(peer); + return; } diff --git a/dp/wifi3.0/dp_peer.c b/dp/wifi3.0/dp_peer.c index d58b2a35b0..9692f711ba 100644 --- a/dp/wifi3.0/dp_peer.c +++ b/dp/wifi3.0/dp_peer.c @@ -2299,6 +2299,32 @@ void dp_peer_rx_cleanup(struct dp_vdev *vdev, struct dp_peer *peer) qdf_spinlock_destroy(&peer->rx_tid[tid].tid_lock); } +#ifdef FEATURE_PERPKT_INFO +/* + * dp_peer_ppdu_delayed_ba_init() Initialize ppdu in peer + * @peer: Datapath peer + * + * return: void + */ +void dp_peer_ppdu_delayed_ba_init(struct dp_peer *peer) +{ + qdf_mem_zero(&peer->delayed_ba_ppdu_stats, + sizeof(struct cdp_delayed_tx_completion_ppdu_user)); + peer->last_delayed_ba = false; + peer->last_delayed_ba_ppduid = 0; +} +#else +/* + * dp_peer_ppdu_delayed_ba_init() Initialize ppdu in peer + * @peer: Datapath peer + * + * return: void + */ +void dp_peer_ppdu_delayed_ba_init(struct dp_peer *peer) +{ +} +#endif + /* * dp_peer_cleanup() – Cleanup peer information * @vdev: Datapath vdev diff --git a/dp/wifi3.0/dp_stats.c b/dp/wifi3.0/dp_stats.c index 2cc9f02a4e..56a955ae0b 100644 --- a/dp/wifi3.0/dp_stats.c +++ b/dp/wifi3.0/dp_stats.c @@ -4864,10 +4864,10 @@ void dp_print_peer_stats(struct dp_peer *peer) DP_PRINT_STATS("Transmit Type :"); DP_PRINT_STATS("SU %d, MU_MIMO %d, MU_OFDMA %d, MU_MIMO_OFDMA %d", - peer->stats.tx.transmit_type[0], - peer->stats.tx.transmit_type[1], - peer->stats.tx.transmit_type[2], - peer->stats.tx.transmit_type[3]); + peer->stats.tx.transmit_type[SU].num_msdu, + peer->stats.tx.transmit_type[MU_MIMO].num_msdu, + peer->stats.tx.transmit_type[MU_OFDMA].num_msdu, + peer->stats.tx.transmit_type[MU_MIMO_OFDMA].num_msdu); for (i = 0; i < MAX_MU_GROUP_ID;) { index = 0; @@ -4887,12 +4887,18 @@ void dp_print_peer_stats(struct dp_peer *peer) DP_PRINT_STATS("Last Packet RU index [%d], Size [%d]", peer->stats.tx.ru_start, peer->stats.tx.ru_tones); DP_PRINT_STATS("RU Locations RU[26 52 106 242 484 996]:"); - DP_PRINT_STATS("RU_26: %d", peer->stats.tx.ru_loc[0]); - DP_PRINT_STATS("RU 52: %d", peer->stats.tx.ru_loc[1]); - DP_PRINT_STATS("RU 106: %d", peer->stats.tx.ru_loc[2]); - DP_PRINT_STATS("RU 242: %d", peer->stats.tx.ru_loc[3]); - DP_PRINT_STATS("RU 484: %d", peer->stats.tx.ru_loc[4]); - DP_PRINT_STATS("RU 996: %d", peer->stats.tx.ru_loc[5]); + DP_PRINT_STATS("RU_26: %d", + peer->stats.tx.ru_loc[RU_26_INDEX].num_msdu); + DP_PRINT_STATS("RU 52: %d", + peer->stats.tx.ru_loc[RU_52_INDEX].num_msdu); + DP_PRINT_STATS("RU 106: %d", + peer->stats.tx.ru_loc[RU_106_INDEX].num_msdu); + DP_PRINT_STATS("RU 242: %d", + peer->stats.tx.ru_loc[RU_242_INDEX].num_msdu); + DP_PRINT_STATS("RU 484: %d", + peer->stats.tx.ru_loc[RU_484_INDEX].num_msdu); + DP_PRINT_STATS("RU 996: %d", + peer->stats.tx.ru_loc[RU_996_INDEX].num_msdu); DP_PRINT_STATS("Aggregation:"); DP_PRINT_STATS("Number of Msdu's Part of Amsdu = %d", @@ -5354,6 +5360,8 @@ dp_print_pdev_tx_stats(struct dp_pdev *pdev) DP_PRINT_STATS(" Tag[%d] = %llu", index, pdev->stats.ppdu_stats_counter[index]); } + DP_PRINT_STATS("BA not received for delayed_ba: %d", + pdev->stats.cdp_delayed_ba_not_recev); DP_PRINT_STATS("tx_ppdu_proc: %llu\n", pdev->tx_ppdu_proc); diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 8b1eb7f6ef..2796253638 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -1211,8 +1211,10 @@ struct dp_neighbour_peer { * @is_ampdu - set if Ampdu aggregate * @nbuf - ppdu descriptor payload * @ppdu_desc - ppdu descriptor - * @ppdu_info_list_elem - linked list of ppdu tlvs + * @ppdu_info_list_elem - linked list of ppdu tlvs * @ppdu_info_queue_elem - Singly linked list (queue) of ppdu tlvs + * @mpdu_compltn_common_tlv - Successful MPDU counter from COMPLTN COMMON tlv + * @mpdu_ack_ba_tlv - Successful MPDU from ACK BA tlv */ struct ppdu_info { uint32_t ppdu_id; @@ -1234,6 +1236,8 @@ struct ppdu_info { #else TAILQ_ENTRY(ppdu_info) ppdu_info_list_elem; #endif + uint16_t mpdu_compltn_common_tlv; + uint16_t mpdu_ack_ba_tlv; }; /** @@ -1960,6 +1964,14 @@ struct dp_peer { qdf_atomic_t flush_in_progress; struct dp_peer_cached_bufq bufq_info; #endif +#ifdef FEATURE_PERPKT_INFO + /* delayed ba ppdu stats handling */ + struct cdp_delayed_tx_completion_ppdu_user delayed_ba_ppdu_stats; + /* delayed ba flag */ + bool last_delayed_ba; + /* delayed ba ppdu id */ + uint32_t last_delayed_ba_ppduid; +#endif }; /*