From acef42a09cb9560537f4afbf29d7be6a85d0f07f Mon Sep 17 00:00:00 2001 From: Saket Jha Date: Thu, 15 Oct 2020 21:30:05 -0700 Subject: [PATCH] qcacmn: Add support to handle BAR frames in host Due to recent FW changes not filtering out BAR frames, redirect these frames to REO exception ring and handle as normal data packets. Change-Id: I4540929fddab14de57a23f6364fc916a70057cbe CRs-Fixed: 2795499 --- dp/wifi3.0/dp_rx_err.c | 115 +++++++++++++++++++++++++++--- dp/wifi3.0/dp_stats.c | 4 ++ dp/wifi3.0/dp_types.h | 2 + hal/wifi3.0/hal_api.h | 9 +++ hal/wifi3.0/hal_rx.h | 8 +++ hal/wifi3.0/qca6390/hal_6390.c | 4 +- hal/wifi3.0/qca6390/hal_6390_rx.h | 11 +++ hal/wifi3.0/qca6490/hal_6490.c | 22 +++++- hal/wifi3.0/qca6490/hal_6490_rx.h | 11 +++ 9 files changed, 173 insertions(+), 13 deletions(-) diff --git a/dp/wifi3.0/dp_rx_err.c b/dp/wifi3.0/dp_rx_err.c index 2b308a0b6d37..e7eebe8c5cbe 100644 --- a/dp/wifi3.0/dp_rx_err.c +++ b/dp/wifi3.0/dp_rx_err.c @@ -776,9 +776,9 @@ dp_rx_chain_msdus(struct dp_soc *soc, qdf_nbuf_t nbuf, } static -void dp_rx_wbm_err_handle_bar(struct dp_soc *soc, - struct dp_peer *peer, - qdf_nbuf_t nbuf) +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; @@ -817,6 +817,77 @@ void dp_rx_wbm_err_handle_bar(struct dp_soc *soc, start_seq_num); } +static void +dp_rx_bar_frame_handle(struct dp_soc *soc, + hal_ring_desc_t ring_desc, + struct dp_rx_desc *rx_desc, + struct hal_rx_mpdu_desc_info *mpdu_desc_info, + uint8_t error) +{ + 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; + + nbuf = rx_desc->nbuf; + rx_desc_pool = &soc->rx_desc_buf[rx_desc->pool_id]; + dp_ipa_handle_rx_buf_smmu_mapping(soc, nbuf, + rx_desc_pool->buf_size, + false); + qdf_nbuf_unmap_nbytes_single(soc->osdev, nbuf, + QDF_DMA_FROM_DEVICE, + rx_desc_pool->buf_size); + rx_desc->unmapped = 1; + 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 status = %d", + QDF_MAC_ADDR_REF(peer->mac_addr.raw), + peer->peer_id, + tid, + mpdu_desc_info->mpdu_seq, + error); + + switch (error) { + case HAL_REO_ERR_BAR_FRAME_2K_JUMP: + DP_STATS_INC(soc, + rx.err.reo_error[error], 1); + case HAL_REO_ERR_BAR_FRAME_OOR: + dp_rx_err_handle_bar(soc, peer, nbuf); + DP_STATS_INC(soc, + rx.err.reo_error[error], 1); + break; + default: + DP_STATS_INC(soc, rx.bar_frame, 1); + } + + dp_peer_unref_delete(peer, DP_MOD_ID_RX_ERR); +next: + dp_rx_link_desc_return(soc, ring_desc, + HAL_BM_ACTION_PUT_IN_IDLE_LIST); + dp_rx_add_to_free_desc_list(&pdev->free_list_head, + &pdev->free_list_tail, + rx_desc); + qdf_nbuf_free(nbuf); +} + /** * dp_2k_jump_handle() - Function to handle 2k jump exception * on WBM ring @@ -1614,9 +1685,14 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, error = HAL_RX_ERROR_STATUS_GET(ring_desc); - qdf_assert(error == HAL_REO_ERROR_DETECTED); - buf_type = HAL_RX_REO_BUF_TYPE_GET(ring_desc); + + /* Get the MPDU DESC info */ + hal_rx_mpdu_desc_info_get(ring_desc, &mpdu_desc_info); + + if (mpdu_desc_info.msdu_count == 0) + goto next_entry; + /* * For REO error ring, expect only MSDU LINK DESC */ @@ -1673,8 +1749,20 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, mac_id = rx_desc->pool_id; - /* Get the MPDU DESC info */ - hal_rx_mpdu_desc_info_get(ring_desc, &mpdu_desc_info); + if (mpdu_desc_info.bar_frame) { + qdf_assert_always(mpdu_desc_info.msdu_count == 1); + + dp_rx_bar_frame_handle(soc, + ring_desc, + rx_desc, + &mpdu_desc_info, + error); + + rx_bufs_reaped[mac_id] += 1; + goto next_entry; + } + + dp_info("Got pkt with REO ERROR: %d", error); if (mpdu_desc_info.mpdu_flags & HAL_MPDU_F_FRAGMENT) { /* @@ -1725,6 +1813,11 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, goto next_entry; } + /* + * Expect REO errors to be handled after this point + */ + qdf_assert_always(error == HAL_REO_ERROR_DETECTED); + if (hal_rx_reo_is_pn_error(ring_desc)) { /* TOD0 */ DP_STATS_INC(soc, @@ -1786,6 +1879,8 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, rx_bufs_reaped[mac_id] += count; goto next_entry; } + /* Assert if unexpected error type */ + qdf_assert_always(0); next_entry: dp_rx_link_cookie_invalidate(ring_desc); hal_srng_dst_get_next(hal_soc, hal_ring_hdl); @@ -2152,9 +2247,9 @@ done: case HAL_REO_ERR_BAR_FRAME_2K_JUMP: case HAL_REO_ERR_BAR_FRAME_OOR: if (peer) - dp_rx_wbm_err_handle_bar(soc, - peer, - nbuf); + dp_rx_err_handle_bar(soc, + peer, + nbuf); qdf_nbuf_free(nbuf); break; diff --git a/dp/wifi3.0/dp_stats.c b/dp/wifi3.0/dp_stats.c index ed195eb97fec..d4e4c01db232 100644 --- a/dp/wifi3.0/dp_stats.c +++ b/dp/wifi3.0/dp_stats.c @@ -6049,6 +6049,8 @@ void dp_txrx_path_stats(struct dp_soc *soc) DP_PRINT_STATS("hal ring access full fail: %u msdus", pdev->soc->stats.rx.err.hal_ring_access_full_fail); + DP_PRINT_STATS("Rx BAR frames:%d", soc->stats.rx.bar_frame); + for (error_code = 0; error_code < HAL_REO_ERR_MAX; error_code++) { if (!pdev->soc->stats.rx.err.reo_error[error_code]) @@ -6630,6 +6632,8 @@ dp_print_soc_rx_stats(struct dp_soc *soc) DP_PRINT_STATS("REO Error(0-14):%s", reo_error); DP_PRINT_STATS("REO CMD SEND FAIL: %d", soc->stats.rx.err.reo_cmd_send_fail); + + DP_PRINT_STATS("Rx BAR frames:%d", soc->stats.rx.bar_frame); } #ifdef FEATURE_TSO_STATS diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index a6e2edd6d293..bbb5ab91f98d 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -889,6 +889,8 @@ struct dp_soc_stats { uint32_t near_full; /* Break ring reaping as not all scattered msdu received */ uint32_t msdu_scatter_wait_break; + /* Number of bar frames received */ + uint32_t bar_frame; struct { /* Invalid RBM error count */ diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index 9b9e8159405e..dc220cd77ac6 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -1101,6 +1101,15 @@ extern void *hal_srng_setup(void *hal_soc, int ring_type, int ring_num, (HWIO_REO_R0_ERROR_DESTINATION_MAPPING_IX_0_ERROR_ ## \ DESTINATION_RING_ ## _OFFSET ## _SHFT)) +/* + * Macro to access HWIO_REO_R0_ERROR_DESTINATION_RING_CTRL_IX_1 + * to map destination to rings + */ +#define HAL_REO_ERR_REMAP_IX1(_VALUE, _OFFSET) \ + ((_VALUE) << \ + (HWIO_REO_R0_ERROR_DESTINATION_MAPPING_IX_1_ERROR_ ## \ + DESTINATION_RING_ ## _OFFSET ## _SHFT)) + /* * Macro to access HWIO_REO_R0_DESTINATION_RING_CTRL_IX_0 * to map destination to rings diff --git a/hal/wifi3.0/hal_rx.h b/hal/wifi3.0/hal_rx.h index 70448db8bdfe..3392c2a7f0c4 100644 --- a/hal/wifi3.0/hal_rx.h +++ b/hal/wifi3.0/hal_rx.h @@ -186,12 +186,14 @@ enum hal_rx_msdu_desc_flags { * [2] AMPDU flag * [3] raw_ampdu * @peer_meta_data: Upper bits containing peer id, vdev id + * @bar_frame: indicates if received frame is a bar frame */ struct hal_rx_mpdu_desc_info { uint16_t msdu_count; uint16_t mpdu_seq; /* 12 bits for length */ uint32_t mpdu_flags; uint32_t peer_meta_data; /* sw progamed meta-data:MAC Id & peer Id */ + uint16_t bar_frame; }; /** @@ -427,6 +429,11 @@ enum hal_rx_ret_buf_manager { HAL_RX_MPDU_AMPDU_FLAG_GET(mpdu_info_ptr) | \ HAL_RX_MPDU_RAW_MPDU_GET(mpdu_info_ptr)) +#define HAL_RX_MPDU_BAR_FRAME_GET(mpdu_info_ptr) \ + ((mpdu_info_ptr[RX_MPDU_DESC_INFO_0_BAR_FRAME_OFFSET >> 2] & \ + RX_MPDU_DESC_INFO_0_BAR_FRAME_MASK) >> \ + RX_MPDU_DESC_INFO_0_BAR_FRAME_LSB) + #define HAL_RX_MSDU_PKT_LENGTH_GET(msdu_info_ptr) \ (_HAL_MS((*_OFFSET_TO_WORD_PTR(msdu_info_ptr, \ @@ -558,6 +565,7 @@ static inline void hal_rx_mpdu_desc_info_get(void *desc_addr, mpdu_desc_info->mpdu_flags = HAL_RX_MPDU_FLAGS_GET(mpdu_info); mpdu_desc_info->peer_meta_data = HAL_RX_MPDU_DESC_PEER_META_DATA_GET(mpdu_info); + mpdu_desc_info->bar_frame = HAL_RX_MPDU_BAR_FRAME_GET(mpdu_info); } /* diff --git a/hal/wifi3.0/qca6390/hal_6390.c b/hal/wifi3.0/qca6390/hal_6390.c index 212a88285de9..c1696e8ca9cf 100644 --- a/hal/wifi3.0/qca6390/hal_6390.c +++ b/hal/wifi3.0/qca6390/hal_6390.c @@ -1027,9 +1027,9 @@ hal_reo_set_err_dst_remap_6390(void *hal_soc) HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 3) | HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 4) | HAL_REO_ERR_REMAP_IX0(REO_REMAP_TCL, 5) | - HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 6) | + HAL_REO_ERR_REMAP_IX0(REO_REMAP_TCL, 6) | HAL_REO_ERR_REMAP_IX0(REO_REMAP_TCL, 7) | - HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 8) | + HAL_REO_ERR_REMAP_IX0(REO_REMAP_TCL, 8) | HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 9); HAL_REG_WRITE(hal_soc, diff --git a/hal/wifi3.0/qca6390/hal_6390_rx.h b/hal/wifi3.0/qca6390/hal_6390_rx.h index 745f9a7eb9c0..095b9f8de03b 100644 --- a/hal/wifi3.0/qca6390/hal_6390_rx.h +++ b/hal/wifi3.0/qca6390/hal_6390_rx.h @@ -294,6 +294,17 @@ HWIO_REO_R0_GENERAL_ENABLE_ADDR( \ SEQ_WCSS_UMAC_REO_REG_OFFSET), \ (reg_val)); \ + reg_val = \ + HAL_REG_READ((soc), \ + HWIO_REO_R0_GENERAL_ENABLE_ADDR( \ + SEQ_WCSS_UMAC_REO_REG_OFFSET)); \ + reg_val &= \ + (~HWIO_REO_R0_GENERAL_ENABLE_BAR_DEST_RING_BMSK |\ + (REO_REMAP_TCL << HWIO_REO_R0_GENERAL_ENABLE_BAR_DEST_RING_SHFT)); \ + HAL_REG_WRITE((soc), \ + HWIO_REO_R0_GENERAL_ENABLE_ADDR( \ + SEQ_WCSS_UMAC_REO_REG_OFFSET), \ + (reg_val)); \ } while (0) #define HAL_RX_MSDU_DESC_INFO_GET(msdu_details_ptr) \ diff --git a/hal/wifi3.0/qca6490/hal_6490.c b/hal/wifi3.0/qca6490/hal_6490.c index cc9cebfc7a7a..b8f9766ddef5 100644 --- a/hal/wifi3.0/qca6490/hal_6490.c +++ b/hal/wifi3.0/qca6490/hal_6490.c @@ -1471,9 +1471,18 @@ hal_reo_set_err_dst_remap_6490(void *hal_soc) HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 3) | HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 4) | HAL_REO_ERR_REMAP_IX0(REO_REMAP_TCL, 5) | - HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 6) | + HAL_REO_ERR_REMAP_IX0(REO_REMAP_TCL, 6) | HAL_REO_ERR_REMAP_IX0(REO_REMAP_TCL, 7); + uint32_t dst_remap_ix1 = + HAL_REO_ERR_REMAP_IX1(REO_REMAP_RELEASE, 14) | + HAL_REO_ERR_REMAP_IX1(REO_REMAP_RELEASE, 13) | + HAL_REO_ERR_REMAP_IX1(REO_REMAP_RELEASE, 12) | + HAL_REO_ERR_REMAP_IX1(REO_REMAP_RELEASE, 11) | + HAL_REO_ERR_REMAP_IX1(REO_REMAP_RELEASE, 10) | + HAL_REO_ERR_REMAP_IX1(REO_REMAP_RELEASE, 9) | + HAL_REO_ERR_REMAP_IX1(REO_REMAP_TCL, 8); + HAL_REG_WRITE(hal_soc, HWIO_REO_R0_ERROR_DESTINATION_MAPPING_IX_0_ADDR( SEQ_WCSS_UMAC_REO_REG_OFFSET), @@ -1484,6 +1493,17 @@ hal_reo_set_err_dst_remap_6490(void *hal_soc) hal_soc, HWIO_REO_R0_ERROR_DESTINATION_MAPPING_IX_0_ADDR( SEQ_WCSS_UMAC_REO_REG_OFFSET))); + + HAL_REG_WRITE(hal_soc, + HWIO_REO_R0_ERROR_DESTINATION_MAPPING_IX_1_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + dst_remap_ix1); + + hal_info("HWIO_REO_R0_ERROR_DESTINATION_MAPPING_IX_1 0x%x", + HAL_REG_READ( + hal_soc, + HWIO_REO_R0_ERROR_DESTINATION_MAPPING_IX_1_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET))); } /** diff --git a/hal/wifi3.0/qca6490/hal_6490_rx.h b/hal/wifi3.0/qca6490/hal_6490_rx.h index 1d26d1be1717..8859e95eb02f 100644 --- a/hal/wifi3.0/qca6490/hal_6490_rx.h +++ b/hal/wifi3.0/qca6490/hal_6490_rx.h @@ -307,6 +307,17 @@ HWIO_REO_R0_MISC_CTL_ADDR( \ SEQ_WCSS_UMAC_REO_REG_OFFSET), \ (reg_val)); \ + reg_val = \ + HAL_REG_READ((soc), \ + HWIO_REO_R0_GENERAL_ENABLE_ADDR( \ + SEQ_WCSS_UMAC_REO_REG_OFFSET)); \ + reg_val &= \ + (~HWIO_REO_R0_GENERAL_ENABLE_BAR_DEST_RING_BMSK |\ + (REO_REMAP_TCL << HWIO_REO_R0_GENERAL_ENABLE_BAR_DEST_RING_SHFT)); \ + HAL_REG_WRITE((soc), \ + HWIO_REO_R0_GENERAL_ENABLE_ADDR( \ + SEQ_WCSS_UMAC_REO_REG_OFFSET), \ + (reg_val)); \ } while (0) #define HAL_RX_MSDU_DESC_INFO_GET(msdu_details_ptr) \