diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 118c892579..eafeaacb0c 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -2787,7 +2787,7 @@ static void dp_reo_frag_dst_set(struct dp_soc *soc, uint8_t *frag_dst_ring) switch (offload_radio) { case dp_nss_cfg_default: - *frag_dst_ring = HAL_SRNG_REO_EXCEPTION; + *frag_dst_ring = REO_REMAP_TCL; break; case dp_nss_cfg_first_radio: /* @@ -3169,6 +3169,8 @@ out: hal_reo_setup(soc->hal_soc, &reo_params); + hal_reo_set_err_dst_remap(soc->hal_soc); + qdf_atomic_set(&soc->cmn_init_done, 1); dp_soc_wds_attach(soc); diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index b38c7d6aa9..4055b008fc 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -1676,25 +1676,6 @@ static inline bool dp_rx_enable_eol_data_check(struct dp_soc *soc) #endif /* WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT */ -/** - * dp_is_special_data() - check is the pkt special like eapol, dhcp, etc - * - * @nbuf: pkt skb pointer - * - * Return: true if matched, false if not - */ -static inline -bool dp_is_special_data(qdf_nbuf_t nbuf) -{ - if (qdf_nbuf_is_ipv4_arp_pkt(nbuf) || - qdf_nbuf_is_ipv4_dhcp_pkt(nbuf) || - qdf_nbuf_is_ipv4_eapol_pkt(nbuf) || - qdf_nbuf_is_ipv6_dhcp_pkt(nbuf)) - return true; - else - return false; -} - #ifdef DP_RX_PKT_NO_PEER_DELIVER /** * dp_rx_deliver_to_stack_no_peer() - try deliver rx data even if @@ -1718,6 +1699,8 @@ void dp_rx_deliver_to_stack_no_peer(struct dp_soc *soc, qdf_nbuf_t nbuf) uint16_t msdu_len = 0; uint32_t pkt_len = 0; uint8_t *rx_tlv_hdr; + uint32_t frame_mask = FRAME_MASK_IPV4_ARP | FRAME_MASK_IPV4_DHCP | + FRAME_MASK_IPV4_EAPOL | FRAME_MASK_IPV6_DHCP; peer_id = QDF_NBUF_CB_RX_PEER_ID(nbuf); if (peer_id > soc->max_peers) @@ -1728,30 +1711,28 @@ void dp_rx_deliver_to_stack_no_peer(struct dp_soc *soc, qdf_nbuf_t nbuf) if (!vdev || vdev->delete.pending || !vdev->osif_rx) goto deliver_fail; + if (qdf_unlikely(qdf_nbuf_is_frag(nbuf))) + goto deliver_fail; + rx_tlv_hdr = qdf_nbuf_data(nbuf); l2_hdr_offset = hal_rx_msdu_end_l3_hdr_padding_get(soc->hal_soc, rx_tlv_hdr); msdu_len = QDF_NBUF_CB_RX_PKT_LEN(nbuf); pkt_len = msdu_len + l2_hdr_offset + RX_PKT_TLVS_LEN; + QDF_NBUF_CB_RX_NUM_ELEMENTS_IN_LIST(nbuf) = 1; - if (qdf_unlikely(qdf_nbuf_is_frag(nbuf))) { - qdf_nbuf_pull_head(nbuf, RX_PKT_TLVS_LEN); - } else { - qdf_nbuf_set_pktlen(nbuf, pkt_len); - qdf_nbuf_pull_head(nbuf, - RX_PKT_TLVS_LEN + - l2_hdr_offset); + qdf_nbuf_set_pktlen(nbuf, pkt_len); + qdf_nbuf_pull_head(nbuf, + RX_PKT_TLVS_LEN + + l2_hdr_offset); + + if (dp_rx_is_special_frame(nbuf, frame_mask)) { + vdev->osif_rx(vdev->osif_vdev, nbuf); + DP_STATS_INC(soc, rx.err.pkt_delivered_no_peer, 1); + return; } - /* only allow special frames */ - if (!dp_is_special_data(nbuf)) - goto deliver_fail; - - vdev->osif_rx(vdev->osif_vdev, nbuf); - DP_STATS_INC(soc, rx.err.pkt_delivered_no_peer, 1); - return; - deliver_fail: DP_STATS_INC_PKT(soc, rx.err.rx_invalid_peer, 1, QDF_NBUF_CB_RX_PKT_LEN(nbuf)); @@ -2790,3 +2771,36 @@ dp_rx_nbuf_prepare(struct dp_soc *soc, struct dp_pdev *pdev) return nbuf; } + +#ifdef DP_RX_SPECIAL_FRAME_NEED +bool dp_rx_deliver_special_frame(struct dp_soc *soc, struct dp_peer *peer, + qdf_nbuf_t nbuf, uint32_t frame_mask) +{ + uint32_t l2_hdr_offset = 0; + uint16_t msdu_len = 0; + uint32_t pkt_len = 0; + uint8_t *rx_tlv_hdr; + + if (qdf_unlikely(qdf_nbuf_is_frag(nbuf))) + return false; + + rx_tlv_hdr = qdf_nbuf_data(nbuf); + l2_hdr_offset = + hal_rx_msdu_end_l3_hdr_padding_get(soc->hal_soc, rx_tlv_hdr); + + msdu_len = QDF_NBUF_CB_RX_PKT_LEN(nbuf); + pkt_len = msdu_len + l2_hdr_offset + RX_PKT_TLVS_LEN; + QDF_NBUF_CB_RX_NUM_ELEMENTS_IN_LIST(nbuf) = 1; + + qdf_nbuf_set_pktlen(nbuf, pkt_len); + dp_rx_skip_tlvs(nbuf, l2_hdr_offset); + + if (dp_rx_is_special_frame(nbuf, frame_mask)) { + dp_rx_deliver_to_stack(soc, peer->vdev, peer, + nbuf, NULL); + return true; + } + + return false; +} +#endif diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index 7cfebb335b..fb2d94c474 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/dp/wifi3.0/dp_rx.h @@ -132,6 +132,69 @@ struct dp_rx_desc { (((_cookie) & RX_DESC_COOKIE_INDEX_MASK) >> \ RX_DESC_COOKIE_INDEX_SHIFT) +#define FRAME_MASK_IPV4_ARP 1 +#define FRAME_MASK_IPV4_DHCP 2 +#define FRAME_MASK_IPV4_EAPOL 4 +#define FRAME_MASK_IPV6_DHCP 8 + +#ifdef DP_RX_SPECIAL_FRAME_NEED +/** + * dp_rx_is_special_frame() - check is RX frame special needed + * + * @nbuf: RX skb pointer + * @frame_mask: the mask for speical frame needed + * + * Check is RX frame wanted matched with mask + * + * Return: true - special frame needed, false - no + */ +static inline +bool dp_rx_is_special_frame(qdf_nbuf_t nbuf, uint32_t frame_mask) +{ + if (((frame_mask & FRAME_MASK_IPV4_ARP) && + qdf_nbuf_is_ipv4_arp_pkt(nbuf)) || + ((frame_mask & FRAME_MASK_IPV4_DHCP) && + qdf_nbuf_is_ipv4_dhcp_pkt(nbuf)) || + ((frame_mask & FRAME_MASK_IPV4_EAPOL) && + qdf_nbuf_is_ipv4_eapol_pkt(nbuf)) || + ((frame_mask & FRAME_MASK_IPV6_DHCP) && + qdf_nbuf_is_ipv6_dhcp_pkt(nbuf))) + return true; + + return false; +} + +/** + * dp_rx_deliver_special_frame() - Deliver the RX special frame to stack + * if matches mask + * + * @soc: Datapath soc handler + * @peer: pointer to DP peer + * @nbuf: pointer to the skb of RX frame + * @frame_mask: the mask for speical frame needed + * + * note: Msdu_len must have been stored in QDF_NBUF_CB_RX_PKT_LEN(nbuf) and + * single nbuf is expected. + * + * return: true - nbuf has been delivered to stack, false - not. + */ +bool dp_rx_deliver_special_frame(struct dp_soc *soc, struct dp_peer *peer, + qdf_nbuf_t nbuf, uint32_t frame_mask); +#else +static inline +bool dp_rx_is_special_frame(qdf_nbuf_t nbuf, uint32_t frame_mask) +{ + return false; +} + +static inline +bool dp_rx_deliver_special_frame(struct dp_soc *soc, struct dp_peer *peer, + qdf_nbuf_t nbuf, uint32_t frame_mask) +{ + return false; +} +#endif + /* DOC: Offset to obtain LLC hdr * * In the case of Wifi parse error diff --git a/dp/wifi3.0/dp_rx_err.c b/dp/wifi3.0/dp_rx_err.c index ffab7261af..21a5c90873 100644 --- a/dp/wifi3.0/dp_rx_err.c +++ b/dp/wifi3.0/dp_rx_err.c @@ -379,32 +379,163 @@ dp_rx_pn_error_handle(struct dp_soc *soc, hal_ring_desc_t ring_desc, } /** - * dp_rx_2k_jump_handle() - Handles Sequence Number Jump by 2K + * dp_rx_oor_handle() - Handles the msdu which is OOR error + * + * @soc: core txrx main context + * @nbuf: pointer to msdu skb + * @peer_id: dp peer ID + * + * This function process the msdu delivered from REO2TCL + * ring with error type OOR + * + * Return: None + */ +static void +dp_rx_oor_handle(struct dp_soc *soc, + qdf_nbuf_t nbuf, + uint16_t peer_id) +{ + uint32_t frame_mask = FRAME_MASK_IPV4_ARP | FRAME_MASK_IPV4_DHCP | + FRAME_MASK_IPV4_EAPOL | FRAME_MASK_IPV6_DHCP; + struct dp_peer *peer = NULL; + + peer = dp_peer_find_by_id(soc, peer_id); + if (!peer) { + dp_info_rl("peer not found"); + goto free_nbuf; + } + + if (dp_rx_deliver_special_frame(soc, peer, nbuf, frame_mask)) { + DP_STATS_INC(soc, rx.err.reo_err_oor_to_stack, 1); + dp_peer_unref_del_find_by_id(peer); + return; + } + +free_nbuf: + if (peer) + dp_peer_unref_del_find_by_id(peer); + + DP_STATS_INC(soc, rx.err.reo_err_oor_drop, 1); + qdf_nbuf_free(nbuf); +} + +/** + * dp_rx_reo_err_entry_process() - Handles for REO error entry processing * * @soc: core txrx main context * @ring_desc: opaque pointer to the REO error ring descriptor - * @mpdu_desc_info: MPDU descriptor information from ring descriptor - * @head: head of the local descriptor free-list - * @tail: tail of the local descriptor free-list - * @quota: No. of units (packets) that can be serviced in one shot. + * @mpdu_desc_info: pointer to mpdu level description info + * @link_desc_va: pointer to msdu_link_desc virtual address + * @err_code: reo erro code fetched from ring entry * - * This function implements the error handling when sequence number - * of the MPDU jumps suddenly by 2K.Today there are 2 cases that - * need to be handled: - * A) CSN (Current Sequence Number) = Last Valid SN (LSN) + 2K - * B) CSN = LSN + 2K, but falls within a "BA sized window" of the SSN - * For case A) the protocol stack is invoked to generate DELBA/DEAUTH frame - * For case B), the frame is normally dropped, no more action is taken + * Function to handle msdus fetched from msdu link desc, currently + * only support 2K jump, OOR error. * - * Return: uint32_t: No. of elements processed + * Return: msdu count processed. */ static uint32_t -dp_rx_2k_jump_handle(struct dp_soc *soc, hal_ring_desc_t ring_desc, - struct hal_rx_mpdu_desc_info *mpdu_desc_info, - uint8_t *mac_id, uint32_t quota) +dp_rx_reo_err_entry_process(struct dp_soc *soc, + void *ring_desc, + struct hal_rx_mpdu_desc_info *mpdu_desc_info, + void *link_desc_va, + enum hal_reo_error_code err_code) { - return dp_rx_msdus_drop(soc, ring_desc, mpdu_desc_info, - mac_id, quota); + uint32_t rx_bufs_used = 0; + struct dp_pdev *pdev; + int i; + uint8_t *rx_tlv_hdr; + uint32_t tid = DP_MAX_TIDS; + uint16_t peer_id; + struct dp_rx_desc *rx_desc; + qdf_nbuf_t nbuf; + struct hal_buf_info buf_info; + struct hal_rx_msdu_list msdu_list; + uint16_t num_msdus; + struct buffer_addr_info cur_link_desc_addr_info = { 0 }; + struct buffer_addr_info next_link_desc_addr_info = { 0 }; + /* First field in REO Dst ring Desc is buffer_addr_info */ + void *buf_addr_info = ring_desc; + + peer_id = DP_PEER_METADATA_PEER_ID_GET( + mpdu_desc_info->peer_meta_data); + +more_msdu_link_desc: + hal_rx_msdu_list_get(soc->hal_soc, link_desc_va, &msdu_list, + &num_msdus); + for (i = 0; i < num_msdus; i++) { + rx_desc = dp_rx_cookie_2_va_rxdma_buf( + soc, + msdu_list.sw_cookie[i]); + + qdf_assert_always(rx_desc); + + /* all buffers from a MSDU link belong to same pdev */ + pdev = dp_get_pdev_for_lmac_id(soc, rx_desc->pool_id); + + nbuf = rx_desc->nbuf; + qdf_nbuf_unmap_single(soc->osdev, + nbuf, QDF_DMA_FROM_DEVICE); + + rx_tlv_hdr = qdf_nbuf_data(nbuf); + QDF_NBUF_CB_RX_PKT_LEN(nbuf) = msdu_list.msdu_info[i].msdu_len; + + switch (err_code) { + case HAL_REO_ERR_REGULAR_FRAME_2K_JUMP: + /* + * only first msdu, mpdu start description tlv valid? + * and use it for following msdu. + */ + if (hal_rx_msdu_end_first_msdu_get(soc->hal_soc, + rx_tlv_hdr)) + tid = hal_rx_mpdu_start_tid_get(soc->hal_soc, + rx_tlv_hdr); + + dp_2k_jump_handle(soc, nbuf, rx_tlv_hdr, + peer_id, tid); + break; + + case HAL_REO_ERR_REGULAR_FRAME_OOR: + dp_rx_oor_handle(soc, nbuf, peer_id); + break; + default: + dp_err_rl("Non-support error code %d", err_code); + qdf_nbuf_free(nbuf); + } + + dp_rx_add_to_free_desc_list(&pdev->free_list_head, + &pdev->free_list_tail, rx_desc); + rx_bufs_used++; + } + + if (rx_bufs_used < mpdu_desc_info->msdu_count) { + hal_rx_get_next_msdu_link_desc_buf_addr_info( + link_desc_va, + &next_link_desc_addr_info); + + if (hal_rx_is_buf_addr_info_valid( + &next_link_desc_addr_info)) { + dp_rx_link_desc_return_by_addr( + soc, + buf_addr_info, + HAL_BM_ACTION_PUT_IN_IDLE_LIST); + + hal_rx_buffer_addr_info_get_paddr( + &next_link_desc_addr_info, + &buf_info); + link_desc_va = + dp_rx_cookie_2_link_desc_va(soc, &buf_info); + cur_link_desc_addr_info = next_link_desc_addr_info; + buf_addr_info = &cur_link_desc_addr_info; + + goto more_msdu_link_desc; + } + } + + dp_rx_link_desc_return_by_addr(soc, buf_addr_info, + HAL_BM_ACTION_PUT_IN_IDLE_LIST); + QDF_BUG(rx_bufs_used == mpdu_desc_info->msdu_count); + + return rx_bufs_used; } #ifdef DP_INVALID_PEER_ASSERT @@ -574,58 +705,62 @@ dp_2k_jump_handle(struct dp_soc *soc, uint16_t peer_id, uint8_t tid) { - uint32_t ppdu_id; struct dp_peer *peer = NULL; struct dp_rx_tid *rx_tid = NULL; + uint32_t frame_mask = FRAME_MASK_IPV4_ARP; peer = dp_peer_find_by_id(soc, peer_id); - if (!peer || peer->delete_in_progress) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "peer not found"); + if (!peer) { + dp_info_rl("peer not found"); goto free_nbuf; } - rx_tid = &peer->rx_tid[tid]; - if (qdf_unlikely(!rx_tid)) { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "rx_tid is NULL!!"); - goto free_nbuf; - } - qdf_spin_lock_bh(&rx_tid->tid_lock); - ppdu_id = hal_rx_attn_phy_ppdu_id_get(rx_tlv_hdr); - /* - * If BA session is created and a non-aggregate packet is - * landing here then the issue is with sequence number mismatch. - * Proceed with delba even in that case - */ - if (rx_tid->ppdu_id_2k != ppdu_id && - rx_tid->ba_status != DP_RX_BA_ACTIVE) { - rx_tid->ppdu_id_2k = ppdu_id; - qdf_spin_unlock_bh(&rx_tid->tid_lock); - goto free_nbuf; + if (tid >= DP_MAX_TIDS) { + dp_info_rl("invalid tid"); + goto nbuf_deliver; } + + rx_tid = &peer->rx_tid[tid]; + qdf_spin_lock_bh(&rx_tid->tid_lock); + + /* only if BA session is active, allow send Delba */ + if (rx_tid->ba_status != DP_RX_BA_ACTIVE) { + qdf_spin_unlock_bh(&rx_tid->tid_lock); + goto nbuf_deliver; + } + if (!rx_tid->delba_tx_status) { rx_tid->delba_tx_retry++; rx_tid->delba_tx_status = 1; rx_tid->delba_rcode = IEEE80211_REASON_QOS_SETUP_REQUIRED; qdf_spin_unlock_bh(&rx_tid->tid_lock); - if (soc->cdp_soc.ol_ops->send_delba) + if (soc->cdp_soc.ol_ops->send_delba) { + DP_STATS_INC(soc, rx.err.rx_2k_jump_delba_sent, 1); soc->cdp_soc.ol_ops->send_delba( peer->vdev->pdev->soc->ctrl_psoc, peer->vdev->vdev_id, peer->mac_addr.raw, tid, rx_tid->delba_rcode); + } } else { qdf_spin_unlock_bh(&rx_tid->tid_lock); } +nbuf_deliver: + if (dp_rx_deliver_special_frame(soc, peer, nbuf, frame_mask)) { + DP_STATS_INC(soc, rx.err.rx_2k_jump_to_stack, 1); + dp_peer_unref_del_find_by_id(peer); + return; + } + free_nbuf: if (peer) dp_peer_unref_del_find_by_id(peer); + + DP_STATS_INC(soc, rx.err.rx_2k_jump_drop, 1); qdf_nbuf_free(nbuf); - return; } #if defined(QCA_WIFI_QCA6390) || defined(QCA_WIFI_QCA6490) || \ @@ -1371,9 +1506,33 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, if (dp_pdev) DP_STATS_INC(dp_pdev, err.reo_error, 1); - count = dp_rx_2k_jump_handle(soc, - ring_desc, &mpdu_desc_info, - &mac_id, quota); + count = dp_rx_reo_err_entry_process( + soc, + ring_desc, + &mpdu_desc_info, + link_desc_va, + HAL_REO_ERR_REGULAR_FRAME_2K_JUMP); + + rx_bufs_reaped[mac_id] += count; + continue; + } + + if (hal_rx_reo_is_oor_error(ring_desc)) { + DP_STATS_INC( + soc, + rx.err. + reo_error[HAL_REO_ERR_REGULAR_FRAME_OOR], + 1); + /* increment @pdev level */ + dp_pdev = dp_get_pdev_for_lmac_id(soc, mac_id); + if (dp_pdev) + DP_STATS_INC(dp_pdev, err.reo_error, 1); + count = dp_rx_reo_err_entry_process( + soc, + ring_desc, + &mpdu_desc_info, + link_desc_va, + HAL_REO_ERR_REGULAR_FRAME_OOR); rx_bufs_reaped[mac_id] += count; continue; @@ -1707,7 +1866,12 @@ done: tid = hal_rx_mpdu_start_tid_get(hal_soc, rx_tlv_hdr); } - dp_2k_jump_handle(soc, nbuf, rx_tlv_hdr, + QDF_NBUF_CB_RX_PKT_LEN(nbuf) = + hal_rx_msdu_start_msdu_len_get( + rx_tlv_hdr); + nbuf->next = NULL; + dp_2k_jump_handle(soc, nbuf, + rx_tlv_hdr, peer_id, tid); nbuf = next; if (peer) diff --git a/dp/wifi3.0/dp_stats.c b/dp/wifi3.0/dp_stats.c index 819bca6f33..21c93849d8 100644 --- a/dp/wifi3.0/dp_stats.c +++ b/dp/wifi3.0/dp_stats.c @@ -5574,6 +5574,16 @@ void dp_txrx_path_stats(struct dp_soc *soc) pdev->soc->stats.rx.err.pkt_delivered_no_peer); DP_PRINT_STATS("RX invalid cookie: %d", soc->stats.rx.err.invalid_cookie); + DP_PRINT_STATS("2k jump delba sent: %u", + pdev->soc->stats.rx.err.rx_2k_jump_delba_sent); + DP_PRINT_STATS("2k jump msdu to stack: %u", + pdev->soc->stats.rx.err.rx_2k_jump_to_stack); + DP_PRINT_STATS("2k jump msdu drop: %u", + pdev->soc->stats.rx.err.rx_2k_jump_drop); + DP_PRINT_STATS("REO err oor msdu to stack %u", + pdev->soc->stats.rx.err.reo_err_oor_to_stack); + DP_PRINT_STATS("REO err oor msdu drop: %u", + pdev->soc->stats.rx.err.reo_err_oor_drop); DP_PRINT_STATS("Reo Statistics"); DP_PRINT_STATS("near_full: %u ", soc->stats.rx.near_full); @@ -6088,6 +6098,21 @@ dp_print_soc_rx_stats(struct dp_soc *soc) DP_PRINT_STATS("RX wait completed msdu break: %d", soc->stats.rx.msdu_scatter_wait_break); + DP_PRINT_STATS("2k jump delba sent: %d", + soc->stats.rx.err.rx_2k_jump_delba_sent); + + DP_PRINT_STATS("2k jump msdu to stack: %d", + soc->stats.rx.err.rx_2k_jump_to_stack); + + DP_PRINT_STATS("2k jump msdu drop: %d", + soc->stats.rx.err.rx_2k_jump_drop); + + DP_PRINT_STATS("REO err oor msdu to stack %d", + soc->stats.rx.err.reo_err_oor_to_stack); + + DP_PRINT_STATS("REO err oor msdu drop: %d", + soc->stats.rx.err.reo_err_oor_drop); + for (i = 0; i < HAL_RXDMA_ERR_MAX; i++) { index += qdf_snprint(&rxdma_error[index], DP_RXDMA_ERR_LENGTH - index, diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 0adbc768c1..7859862628 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -795,6 +795,16 @@ struct dp_soc_stats { uint32_t scatter_msdu; /* RX msdu drop count due to invalid cookie */ uint32_t invalid_cookie; + /* Delba sent count due to RX 2k jump */ + uint32_t rx_2k_jump_delba_sent; + /* RX 2k jump msdu indicated to stack count */ + uint32_t rx_2k_jump_to_stack; + /* RX 2k jump msdu dropped count */ + uint32_t rx_2k_jump_drop; + /* REO OOR msdu drop count */ + uint32_t reo_err_oor_drop; + /* REO OOR msdu indicated to stack count */ + uint32_t reo_err_oor_to_stack; } err; /* packet count per core - per ring */ diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index 9cf5a9bd4f..36e7a7c728 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -815,6 +815,15 @@ extern void *hal_srng_setup(void *hal_soc, int ring_type, int ring_num, #define REO_REMAP_FW 6 #define REO_REMAP_UNUSED 7 +/* + * Macro to access HWIO_REO_R0_ERROR_DESTINATION_RING_CTRL_IX_0 + * to map destination to rings + */ +#define HAL_REO_ERR_REMAP_IX0(_VALUE, _OFFSET) \ + ((_VALUE) << \ + (HWIO_REO_R0_ERROR_DESTINATION_MAPPING_IX_0_ERROR_ ## \ + DESTINATION_RING_ ## _OFFSET ## _SHFT)) + /* * Macro to access HWIO_REO_R0_DESTINATION_RING_CTRL_IX_0 * to map destination to rings @@ -2052,4 +2061,20 @@ hal_rx_sw_mon_desc_info_get(struct hal_soc *hal, { return hal->ops->hal_rx_sw_mon_desc_info_get(ring_desc, desc_info); } + +/** + * hal_reo_set_err_dst_remap() - Set REO error destination ring remap + * register value. + * + * @hal_soc_hdl: Opaque HAL soc handle + * + * Return: None + */ +static inline void hal_reo_set_err_dst_remap(hal_soc_handle_t hal_soc_hdl) +{ + struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl; + + if (hal_soc->ops->hal_reo_set_err_dst_remap) + hal_soc->ops->hal_reo_set_err_dst_remap(hal_soc); +} #endif /* _HAL_APIH_ */ diff --git a/hal/wifi3.0/hal_generic_api.h b/hal/wifi3.0/hal_generic_api.h index 51df36560f..4e8713696a 100644 --- a/hal/wifi3.0/hal_generic_api.h +++ b/hal/wifi3.0/hal_generic_api.h @@ -1630,7 +1630,6 @@ static void hal_reo_setup_generic(struct hal_soc *soc, SEQ_WCSS_UMAC_REO_REG_OFFSET))); } - /* TODO: Check if the following registers shoould be setup by host: * AGING_CONTROL * HIGH_MEMORY_THRESHOLD diff --git a/hal/wifi3.0/hal_internal.h b/hal/wifi3.0/hal_internal.h index 213a41c9c9..0da2824157 100644 --- a/hal/wifi3.0/hal_internal.h +++ b/hal/wifi3.0/hal_internal.h @@ -469,6 +469,7 @@ struct hal_hw_txrx_ops { uint32_t num_entries); qdf_iomem_t (*hal_get_window_address)(struct hal_soc *hal_soc, qdf_iomem_t addr); + void (*hal_reo_set_err_dst_remap)(void *hal_soc); /* tx */ void (*hal_tx_desc_set_dscp_tid_table_id)(void *desc, uint8_t id); diff --git a/hal/wifi3.0/hal_rx.h b/hal/wifi3.0/hal_rx.h index dd97a75fc3..dce357375b 100644 --- a/hal/wifi3.0/hal_rx.h +++ b/hal/wifi3.0/hal_rx.h @@ -2121,6 +2121,22 @@ static inline bool hal_rx_reo_is_2k_jump(hal_ring_desc_t rx_desc) true : false; } +/** + * hal_rx_reo_is_oor_error() - Indicate if this error was caused by OOR + * + * @ring_desc: opaque pointer used by HAL to get the REO destination entry + * + * Return: true: error caused by OOR, false: other error + */ +static inline bool hal_rx_reo_is_oor_error(void *rx_desc) +{ + struct reo_destination_ring *reo_desc = + (struct reo_destination_ring *)rx_desc; + + return (HAL_RX_REO_ERROR_GET(reo_desc) == + HAL_REO_ERR_REGULAR_FRAME_OOR) ? true : false; +} + #define HAL_WBM_RELEASE_RING_DESC_LEN_DWORDS (NUM_OF_DWORDS_WBM_RELEASE_RING) /** * hal_dump_wbm_rel_desc() - dump wbm release descriptor @@ -3656,4 +3672,63 @@ hal_rx_mpdu_start_tlv_tag_valid(hal_soc_handle_t hal_soc_hdl, return hal->ops->hal_rx_mpdu_start_tlv_tag_valid(rx_tlv_hdr); } + +/** + * hal_rx_buffer_addr_info_get_paddr(): get paddr/sw_cookie from + * structure + * @buf_addr_info: pointer to structure + * @buf_info: structure to return the buffer information including + * paddr/cookie + * + * return: None + */ +static inline +void hal_rx_buffer_addr_info_get_paddr(void *buf_addr_info, + struct hal_buf_info *buf_info) +{ + buf_info->paddr = + (HAL_RX_BUFFER_ADDR_31_0_GET(buf_addr_info) | + ((uint64_t)(HAL_RX_BUFFER_ADDR_39_32_GET(buf_addr_info)) << 32)); + + buf_info->sw_cookie = HAL_RX_BUF_COOKIE_GET(buf_addr_info); +} + +/** + * hal_rx_get_next_msdu_link_desc_buf_addr_info(): get next msdu link desc + * buffer addr info + * @link_desc_va: pointer to current msdu link Desc + * @next_addr_info: buffer to save next msdu link Desc buffer addr info + * + * return: None + */ +static inline +void hal_rx_get_next_msdu_link_desc_buf_addr_info( + void *link_desc_va, + struct buffer_addr_info *next_addr_info) +{ + struct rx_msdu_link *msdu_link = link_desc_va; + + if (!msdu_link) { + qdf_mem_zero(next_addr_info, + sizeof(struct buffer_addr_info)); + return; + } + + *next_addr_info = msdu_link->next_msdu_link_desc_addr_info; +} + +/** + * hal_rx_is_buf_addr_info_valid(): check is the buf_addr_info valid + * + * @buf_addr_info: pointer to buf_addr_info structure + * + * return: true: has valid paddr, false: not. + */ +static inline +bool hal_rx_is_buf_addr_info_valid( + struct buffer_addr_info *buf_addr_info) +{ + return (HAL_RX_BUFFER_ADDR_31_0_GET(buf_addr_info) == 0) ? + false : true; +} #endif /* _HAL_RX_H */ diff --git a/hal/wifi3.0/qca5018/hal_5018.c b/hal/wifi3.0/qca5018/hal_5018.c index 6e806512d5..620124ff23 100644 --- a/hal/wifi3.0/qca5018/hal_5018.c +++ b/hal/wifi3.0/qca5018/hal_5018.c @@ -1352,6 +1352,7 @@ struct hal_hw_txrx_ops qca5018_hal_hw_txrx_ops = { hal_reo_setup_generic, hal_setup_link_idle_list_generic, hal_get_window_address_5018, + NULL, /* tx */ hal_tx_desc_set_dscp_tid_table_id_5018, diff --git a/hal/wifi3.0/qca6290/hal_6290.c b/hal/wifi3.0/qca6290/hal_6290.c index 9ae88ecea0..798995b5f2 100644 --- a/hal/wifi3.0/qca6290/hal_6290.c +++ b/hal/wifi3.0/qca6290/hal_6290.c @@ -1000,6 +1000,7 @@ struct hal_hw_txrx_ops qca6290_hal_hw_txrx_ops = { hal_reo_setup_generic, hal_setup_link_idle_list_generic, hal_get_window_address_6290, + NULL, /* tx */ hal_tx_desc_set_dscp_tid_table_id_6290, diff --git a/hal/wifi3.0/qca6390/hal_6390.c b/hal/wifi3.0/qca6390/hal_6390.c index 1c83dc4fa5..ba967d6b21 100644 --- a/hal/wifi3.0/qca6390/hal_6390.c +++ b/hal/wifi3.0/qca6390/hal_6390.c @@ -988,6 +988,44 @@ static inline qdf_iomem_t hal_get_window_address_6390(struct hal_soc *hal_soc, return addr; } +/** + * hal_reo_set_err_dst_remap_6390(): Function to set REO error destination + * ring remap register + * @hal_soc: Pointer to hal_soc + * + * Return: none. + */ +static void +hal_reo_set_err_dst_remap_6390(void *hal_soc) +{ + /* + * Set REO error 2k jump (error code 5) / OOR (error code 7) + * frame routed to REO2TCL ring. + */ + uint32_t dst_remap_ix0 = + HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 0) | + HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 1) | + HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 2) | + 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, 7) | + HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 8) | + HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 9); + + HAL_REG_WRITE(hal_soc, + HWIO_REO_R0_ERROR_DESTINATION_MAPPING_IX_0_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + dst_remap_ix0); + + hal_info("HWIO_REO_R0_ERROR_DESTINATION_MAPPING_IX_0 0x%x", + HAL_REG_READ( + hal_soc, + HWIO_REO_R0_ERROR_DESTINATION_MAPPING_IX_0_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET))); +} + struct hal_hw_txrx_ops qca6390_hal_hw_txrx_ops = { /* init and setup */ hal_srng_dst_hw_init_generic, @@ -996,6 +1034,7 @@ struct hal_hw_txrx_ops qca6390_hal_hw_txrx_ops = { hal_reo_setup_generic, hal_setup_link_idle_list_generic, hal_get_window_address_6390, + hal_reo_set_err_dst_remap_6390, /* tx */ hal_tx_desc_set_dscp_tid_table_id_6390, diff --git a/hal/wifi3.0/qca6490/hal_6490.c b/hal/wifi3.0/qca6490/hal_6490.c index 49c4a23d84..93aebbcde6 100644 --- a/hal/wifi3.0/qca6490/hal_6490.c +++ b/hal/wifi3.0/qca6490/hal_6490.c @@ -1411,6 +1411,42 @@ bool hal_rx_get_fisa_timeout_6490(uint8_t *buf) return HAL_RX_TLV_GET_FISA_TIMEOUT(buf); } +/** + * hal_reo_set_err_dst_remap_6490(): Function to set REO error destination + * ring remap register + * @hal_soc: Pointer to hal_soc + * + * Return: none. + */ +static void +hal_reo_set_err_dst_remap_6490(void *hal_soc) +{ + /* + * Set REO error 2k jump (error code 5) / OOR (error code 7) + * frame routed to REO2TCL ring. + */ + uint32_t dst_remap_ix0 = + HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 0) | + HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 1) | + HAL_REO_ERR_REMAP_IX0(REO_REMAP_RELEASE, 2) | + 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, 7); + + HAL_REG_WRITE(hal_soc, + HWIO_REO_R0_ERROR_DESTINATION_MAPPING_IX_0_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET), + dst_remap_ix0); + + hal_info("HWIO_REO_R0_ERROR_DESTINATION_MAPPING_IX_0 0x%x", + HAL_REG_READ( + hal_soc, + HWIO_REO_R0_ERROR_DESTINATION_MAPPING_IX_0_ADDR( + SEQ_WCSS_UMAC_REO_REG_OFFSET))); +} + struct hal_hw_txrx_ops qca6490_hal_hw_txrx_ops = { /* init and setup */ hal_srng_dst_hw_init_generic, @@ -1419,6 +1455,7 @@ struct hal_hw_txrx_ops qca6490_hal_hw_txrx_ops = { hal_reo_setup_generic, hal_setup_link_idle_list_generic, hal_get_window_address_6490, + hal_reo_set_err_dst_remap_6490, /* tx */ hal_tx_desc_set_dscp_tid_table_id_6490, diff --git a/hal/wifi3.0/qca6750/hal_6750.c b/hal/wifi3.0/qca6750/hal_6750.c index 51706d8905..25cd1e95d6 100644 --- a/hal/wifi3.0/qca6750/hal_6750.c +++ b/hal/wifi3.0/qca6750/hal_6750.c @@ -1330,6 +1330,7 @@ struct hal_hw_txrx_ops qca6750_hal_hw_txrx_ops = { hal_reo_setup_generic, hal_setup_link_idle_list_generic, hal_get_window_address_6750, + NULL, /* tx */ hal_tx_desc_set_dscp_tid_table_id_6750, diff --git a/hal/wifi3.0/qca8074v1/hal_8074v1.c b/hal/wifi3.0/qca8074v1/hal_8074v1.c index 680dfa9485..70182b2543 100644 --- a/hal/wifi3.0/qca8074v1/hal_8074v1.c +++ b/hal/wifi3.0/qca8074v1/hal_8074v1.c @@ -1021,6 +1021,7 @@ struct hal_hw_txrx_ops qca8074_hal_hw_txrx_ops = { hal_reo_setup_generic, hal_setup_link_idle_list_generic, hal_get_window_address_8074, + NULL, /* tx */ hal_tx_desc_set_dscp_tid_table_id_8074, diff --git a/hal/wifi3.0/qca8074v2/hal_8074v2.c b/hal/wifi3.0/qca8074v2/hal_8074v2.c index 25a917c164..216dc67555 100644 --- a/hal/wifi3.0/qca8074v2/hal_8074v2.c +++ b/hal/wifi3.0/qca8074v2/hal_8074v2.c @@ -1018,6 +1018,7 @@ struct hal_hw_txrx_ops qca8074v2_hal_hw_txrx_ops = { hal_reo_setup_generic, hal_setup_link_idle_list_generic, hal_get_window_address_8074v2, + NULL, /* tx */ hal_tx_desc_set_dscp_tid_table_id_8074v2, diff --git a/hal/wifi3.0/qcn9000/hal_9000.c b/hal/wifi3.0/qcn9000/hal_9000.c index 6c70db09bc..9fb24edc0d 100644 --- a/hal/wifi3.0/qcn9000/hal_9000.c +++ b/hal/wifi3.0/qcn9000/hal_9000.c @@ -1473,6 +1473,7 @@ struct hal_hw_txrx_ops qcn9000_hal_hw_txrx_ops = { hal_reo_setup_generic, hal_setup_link_idle_list_generic, hal_get_window_address_9000, + NULL, /* tx */ hal_tx_desc_set_dscp_tid_table_id_9000,