From e28d968b5ad644d39e458255509fa07e6cf17590 Mon Sep 17 00:00:00 2001 From: Rakesh Pillai Date: Mon, 12 Apr 2021 06:27:43 -0700 Subject: [PATCH] qcacmn: BAR frame handling for 2K-jump and & OOR error Currently the detection of whether a frame arriving on the rx-error ring is done via the flags in the ring descriptor. For targets which support providing previous PN in the rx-error ring descriptor, the flags indicating BAR frame will not be present in the ring descriptor. Add BAR frame check and handling in the OOR and 2K-jump frame processing handlers. Change-Id: Iaba763559a84f1c1f6a193e01945124f08c506f2 CRs-Fixed: 2965086 --- dp/wifi3.0/dp_rx_err.c | 194 +++++++++++++++++++++++------------------ 1 file changed, 109 insertions(+), 85 deletions(-) diff --git a/dp/wifi3.0/dp_rx_err.c b/dp/wifi3.0/dp_rx_err.c index b8ae8dd205..740ee227c7 100644 --- a/dp/wifi3.0/dp_rx_err.c +++ b/dp/wifi3.0/dp_rx_err.c @@ -536,6 +536,107 @@ dp_rx_err_nbuf_pn_check(struct dp_soc *soc, hal_ring_desc_t ring_desc, return QDF_STATUS_E_FAILURE; } +static +void dp_rx_err_handle_bar(struct dp_soc *soc, + struct dp_peer *peer, + qdf_nbuf_t nbuf) +{ + uint8_t *rx_tlv_hdr; + unsigned char type, subtype; + uint16_t start_seq_num; + uint32_t tid; + QDF_STATUS status; + struct ieee80211_frame_bar *bar; + + /* + * 1. Is this a BAR frame. If not Discard it. + * 2. If it is, get the peer id, tid, ssn + * 2a Do a tid update + */ + + rx_tlv_hdr = qdf_nbuf_data(nbuf); + bar = (struct ieee80211_frame_bar *)(rx_tlv_hdr + soc->rx_pkt_tlv_size); + + type = bar->i_fc[0] & IEEE80211_FC0_TYPE_MASK; + subtype = bar->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; + + if (!(type == IEEE80211_FC0_TYPE_CTL && + subtype == QDF_IEEE80211_FC0_SUBTYPE_BAR)) { + dp_err_rl("Not a BAR frame!"); + return; + } + + tid = hal_rx_mpdu_start_tid_get(soc->hal_soc, rx_tlv_hdr); + qdf_assert_always(tid < DP_MAX_TIDS); + + start_seq_num = le16toh(bar->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT; + + dp_info_rl("tid %u window_size %u start_seq_num %u", + tid, peer->rx_tid[tid].ba_win_size, start_seq_num); + + status = dp_rx_tid_update_wifi3(peer, tid, + peer->rx_tid[tid].ba_win_size, + start_seq_num); + if (status != QDF_STATUS_SUCCESS) { + dp_err_rl("failed to handle bar frame update rx tid"); + DP_STATS_INC(soc, rx.err.bar_handle_fail_count, 1); + } else { + DP_STATS_INC(soc, rx.err.ssn_update_count, 1); + } +} + +/** + * _dp_rx_bar_frame_handle(): Core of the BAR frame handling + * @soc: Datapath SoC handle + * @nbuf: packet being processed + * @mpdu_desc_info: mpdu desc info for the current packet + * @tid: tid on which the packet arrived + * @err_status: Flag to indicate if REO encountered an error while routing this + * frame + * @error_code: REO error code + * + * Return: None + */ +static void +_dp_rx_bar_frame_handle(struct dp_soc *soc, qdf_nbuf_t nbuf, + struct hal_rx_mpdu_desc_info *mpdu_desc_info, + uint32_t tid, uint8_t err_status, uint32_t error_code) +{ + uint16_t peer_id; + struct dp_peer *peer; + + peer_id = DP_PEER_METADATA_PEER_ID_GET(mpdu_desc_info->peer_meta_data); + peer = dp_peer_get_ref_by_id(soc, peer_id, DP_MOD_ID_RX_ERR); + if (!peer) + return; + + dp_info("BAR frame: peer = " QDF_MAC_ADDR_FMT + " peer_id = %d" + " tid = %u" + " SSN = %d" + " error status = %d", + QDF_MAC_ADDR_REF(peer->mac_addr.raw), + peer->peer_id, + tid, + mpdu_desc_info->mpdu_seq, + err_status); + + if (err_status == HAL_REO_ERROR_DETECTED) { + switch (error_code) { + case HAL_REO_ERR_BAR_FRAME_2K_JUMP: + /* fallthrough */ + case HAL_REO_ERR_BAR_FRAME_OOR: + dp_rx_err_handle_bar(soc, peer, nbuf); + DP_STATS_INC(soc, rx.err.reo_error[error_code], 1); + break; + default: + DP_STATS_INC(soc, rx.bar_frame, 1); + } + } + + dp_peer_unref_delete(peer, DP_MOD_ID_RX_ERR); +} + /** * dp_rx_reo_err_entry_process() - Handles for REO error entry processing * @@ -656,6 +757,12 @@ more_msdu_link_desc: mpdu_desc_info); peer_id = DP_PEER_METADATA_PEER_ID_GET( mpdu_desc_info->peer_meta_data); + + if (mpdu_desc_info->bar_frame) + _dp_rx_bar_frame_handle(soc, nbuf, + mpdu_desc_info, tid, + HAL_REO_ERROR_DETECTED, + err_code); } switch (err_code) { @@ -830,55 +937,6 @@ dp_rx_chain_msdus(struct dp_soc *soc, qdf_nbuf_t nbuf, return mpdu_done; } -static -void dp_rx_err_handle_bar(struct dp_soc *soc, - struct dp_peer *peer, - qdf_nbuf_t nbuf) -{ - uint8_t *rx_tlv_hdr; - unsigned char type, subtype; - uint16_t start_seq_num; - uint32_t tid; - QDF_STATUS status; - struct ieee80211_frame_bar *bar; - - /* - * 1. Is this a BAR frame. If not Discard it. - * 2. If it is, get the peer id, tid, ssn - * 2a Do a tid update - */ - - rx_tlv_hdr = qdf_nbuf_data(nbuf); - bar = (struct ieee80211_frame_bar *)(rx_tlv_hdr + soc->rx_pkt_tlv_size); - - type = bar->i_fc[0] & IEEE80211_FC0_TYPE_MASK; - subtype = bar->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; - - if (!(type == IEEE80211_FC0_TYPE_CTL && - subtype == QDF_IEEE80211_FC0_SUBTYPE_BAR)) { - dp_err_rl("Not a BAR frame!"); - return; - } - - tid = hal_rx_mpdu_start_tid_get(soc->hal_soc, rx_tlv_hdr); - qdf_assert_always(tid < DP_MAX_TIDS); - - start_seq_num = le16toh(bar->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT; - - dp_info_rl("tid %u window_size %u start_seq_num %u", - tid, peer->rx_tid[tid].ba_win_size, start_seq_num); - - status = dp_rx_tid_update_wifi3(peer, tid, - peer->rx_tid[tid].ba_win_size, - start_seq_num); - if (status != QDF_STATUS_SUCCESS) { - dp_err_rl("failed to handle bar frame update rx tid"); - DP_STATS_INC(soc, rx.err.bar_handle_fail_count, 1); - } else { - DP_STATS_INC(soc, rx.err.ssn_update_count, 1); - } -} - /** * dp_rx_bar_frame_handle() - Function to handle err BAR frames * @soc: core DP main context @@ -904,9 +962,7 @@ dp_rx_bar_frame_handle(struct dp_soc *soc, { qdf_nbuf_t nbuf; struct dp_pdev *pdev; - struct dp_peer *peer; struct rx_desc_pool *rx_desc_pool; - uint16_t peer_id; uint8_t *rx_tlv_hdr; uint32_t tid; @@ -922,44 +978,12 @@ dp_rx_bar_frame_handle(struct dp_soc *soc, rx_desc->unmapped = 1; dp_ipa_rx_buf_smmu_mapping_unlock(soc); rx_tlv_hdr = qdf_nbuf_data(nbuf); - peer_id = - hal_rx_mpdu_start_sw_peer_id_get(soc->hal_soc, - rx_tlv_hdr); - peer = dp_peer_get_ref_by_id(soc, peer_id, - DP_MOD_ID_RX_ERR); tid = hal_rx_mpdu_start_tid_get(soc->hal_soc, rx_tlv_hdr); pdev = dp_get_pdev_for_lmac_id(soc, rx_desc->pool_id); - if (!peer) - goto next; - - dp_info("BAR frame: peer = "QDF_MAC_ADDR_FMT - " peer_id = %d" - " tid = %u" - " SSN = %d" - " error code = %d", - QDF_MAC_ADDR_REF(peer->mac_addr.raw), - peer->peer_id, - tid, - mpdu_desc_info->mpdu_seq, - err_code); - - if (err_status == HAL_REO_ERROR_DETECTED) { - switch (err_code) { - case HAL_REO_ERR_BAR_FRAME_2K_JUMP: - /* fallthrough */ - case HAL_REO_ERR_BAR_FRAME_OOR: - dp_rx_err_handle_bar(soc, peer, nbuf); - DP_STATS_INC(soc, rx.err.reo_error[err_code], 1); - break; - default: - DP_STATS_INC(soc, rx.bar_frame, 1); - } - } - - dp_peer_unref_delete(peer, DP_MOD_ID_RX_ERR); -next: + _dp_rx_bar_frame_handle(soc, nbuf, mpdu_desc_info, tid, err_status, + err_code); dp_rx_link_desc_return(soc, ring_desc, HAL_BM_ACTION_PUT_IN_IDLE_LIST); dp_rx_buffer_pool_nbuf_free(soc, rx_desc->nbuf,