From e382ff88b977651ee5a6e401f498c565f6b40a3b Mon Sep 17 00:00:00 2001 From: Pramod Simha Date: Mon, 5 Jun 2017 18:09:26 -0700 Subject: [PATCH] qcacmn: Add RXDMA_DST ring support Setup & process the RXDMA_DST ring to handle error frames from RXDMA block. Pro-active fix to handle the WAR for the WBM stuck issue seen when sending RX_FLUSH command. Change-Id: Ibf56062da2cd9b5d447f1d43bbae5944426d88c8 CRs-Fixed: 2059870 --- dp/wifi3.0/dp_htt.c | 8 +++ dp/wifi3.0/dp_main.c | 24 +++++++ dp/wifi3.0/dp_rx.h | 5 ++ dp/wifi3.0/dp_rx_err.c | 158 +++++++++++++++++++++++++++++++++++++++++ dp/wifi3.0/dp_rx_mon.h | 3 + dp/wifi3.0/dp_types.h | 3 + 6 files changed, 201 insertions(+) diff --git a/dp/wifi3.0/dp_htt.c b/dp/wifi3.0/dp_htt.c index 695b0a6855..1459706972 100644 --- a/dp/wifi3.0/dp_htt.c +++ b/dp/wifi3.0/dp_htt.c @@ -316,6 +316,10 @@ int htt_srng_setup(void *htt_soc, int mac_id, void *hal_srng, htt_ring_id = HTT_RXDMA_MONITOR_DESC_RING; htt_ring_type = HTT_SW_TO_HW_RING; break; + case RXDMA_DST: + htt_ring_id = HTT_RXDMA_NON_MONITOR_DEST_RING; + htt_ring_type = HTT_HW_TO_SW_RING; + break; default: QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, @@ -544,6 +548,10 @@ int htt_h2t_rx_ring_cfg(void *htt_soc, int pdev_id, void *hal_srng, htt_ring_id = HTT_RXDMA_MONITOR_DESC_RING; htt_ring_type = HTT_SW_TO_HW_RING; break; + case RXDMA_DST: + htt_ring_id = HTT_RXDMA_NON_MONITOR_DEST_RING; + htt_ring_type = HTT_HW_TO_SW_RING; + break; default: QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index b6d0558d5e..e94aae0b37 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -330,6 +330,13 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget) dp_mon_process(soc, ring, budget); budget -= work_done; } + + if (int_ctx->rxdma2host_ring_mask & (1 << ring)) { + work_done = + dp_rxdma_err_process(soc, ring, budget); + budget -= work_done; + } + } qdf_lro_flush(int_ctx->lro_ctx); @@ -871,6 +878,7 @@ static void dp_hw_link_desc_pool_cleanup(struct dp_soc *soc) #define RXDMA_MONITOR_DST_RING_SIZE 1024 #define RXDMA_MONITOR_STATUS_RING_SIZE 1024 #define RXDMA_MONITOR_DESC_RING_SIZE 1024 +#define RXDMA_ERR_DST_RING_SIZE 1024 /* * dp_soc_cmn_setup() - Common SoC level initializion @@ -1301,6 +1309,13 @@ static struct cdp_pdev *dp_pdev_attach_wifi3(struct cdp_soc_t *txrx_soc, goto fail1; } + if (dp_srng_setup(soc, &pdev->rxdma_err_dst_ring, RXDMA_DST, 0, + pdev_id, RXDMA_ERR_DST_RING_SIZE)) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("dp_srng_setup failed for rxdma_mon_dst_ring")); + goto fail1; + } + /* Rx specific init */ if (dp_rx_pdev_attach(pdev)) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, @@ -1438,6 +1453,8 @@ static void dp_pdev_detach_wifi3(struct cdp_pdev *txrx_pdev, int force) dp_srng_cleanup(soc, &pdev->rxdma_mon_desc_ring, RXDMA_MONITOR_DESC, 0); + dp_srng_cleanup(soc, &pdev->rxdma_err_dst_ring, RXDMA_DST, 0); + soc->pdev_list[pdev->pdev_id] = NULL; soc->pdev_count--; wlan_cfg_pdev_detach(pdev->wlan_cfg_ctx); @@ -1633,6 +1650,10 @@ static void dp_rxdma_ring_config(struct dp_soc *soc) htt_srng_setup(soc->htt_handle, i, pdev->rxdma_mon_desc_ring.hal_srng, RXDMA_MONITOR_DESC); + + htt_srng_setup(soc->htt_handle, i, + pdev->rxdma_err_dst_ring.hal_srng, + RXDMA_DST); } } } @@ -1660,6 +1681,9 @@ static void dp_rxdma_ring_config(struct dp_soc *soc) htt_srng_setup(soc->htt_handle, i, pdev->rxdma_mon_desc_ring.hal_srng, RXDMA_MONITOR_DESC); + htt_srng_setup(soc->htt_handle, i, + pdev->rxdma_err_dst_ring.hal_srng, + RXDMA_DST); } } } diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index a2e8986f94..64253d2ba4 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/dp/wifi3.0/dp_rx.h @@ -582,4 +582,9 @@ QDF_STATUS dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id, QDF_STATUS dp_rx_link_desc_buf_return(struct dp_soc *soc, struct dp_srng *dp_rxdma_srng, void *buf_addr_info); + + +uint32_t +dp_rxdma_err_process(struct dp_soc *soc, uint32_t mac_id, + uint32_t quota); #endif /* _DP_RX_H */ diff --git a/dp/wifi3.0/dp_rx_err.c b/dp/wifi3.0/dp_rx_err.c index 09a0d7cc83..6a6d20ec75 100644 --- a/dp/wifi3.0/dp_rx_err.c +++ b/dp/wifi3.0/dp_rx_err.c @@ -813,3 +813,161 @@ done: return rx_bufs_reaped; /* Assume no scale factor for now */ } + +/** + * dp_rx_err_mpdu_pop() - extract the MSDU's from link descs + * + * @soc: core DP main context + * @mac_id: mac id which is one of 3 mac_ids + * @rxdma_dst_ring_desc: void pointer to monitor link descriptor buf addr info + * @head: head of descs list to be freed + * @tail: tail of decs list to be freed + + * Return: number of msdu in MPDU to be popped + */ +static inline uint32_t +dp_rx_err_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, + void *rxdma_dst_ring_desc, + union dp_rx_desc_list_elem_t **head, + union dp_rx_desc_list_elem_t **tail) +{ + void *rx_msdu_link_desc; + qdf_nbuf_t msdu; + qdf_nbuf_t last; + struct hal_rx_msdu_list msdu_list; + uint8_t num_msdus; + struct hal_buf_info buf_info; + void *p_buf_addr_info; + void *p_last_buf_addr_info; + uint32_t rx_bufs_used = 0; + uint32_t msdu_cnt; + uint32_t i; + bool mpdu_err; + + msdu = 0; + + last = NULL; + + hal_rx_reo_ent_buf_paddr_get(rxdma_dst_ring_desc, &buf_info, + &p_last_buf_addr_info, &msdu_cnt, &mpdu_err); + + do { + rx_msdu_link_desc = + dp_rx_cookie_2_link_desc_va(soc, &buf_info); + + qdf_assert(rx_msdu_link_desc); + + num_msdus = (msdu_cnt > HAL_RX_NUM_MSDU_DESC)? + HAL_RX_NUM_MSDU_DESC:msdu_cnt; + + hal_rx_msdu_list_get(rx_msdu_link_desc, &msdu_list, num_msdus); + + msdu_cnt -= num_msdus; + + for (i = 0; i < num_msdus; i++) { + struct dp_rx_desc *rx_desc = + dp_rx_cookie_2_va_rxdma_buf(soc, + msdu_list.sw_cookie[i]); + + qdf_assert(rx_desc); + msdu = rx_desc->nbuf; + + qdf_nbuf_unmap_single(soc->osdev, msdu, + QDF_DMA_FROM_DEVICE); + + QDF_TRACE(QDF_MODULE_ID_DP, + QDF_TRACE_LEVEL_DEBUG, + "[%s][%d] msdu_nbuf=%p \n", + __func__, __LINE__, msdu); + + qdf_nbuf_free(msdu); + rx_bufs_used++; + dp_rx_add_to_free_desc_list(head, + tail, rx_desc); + } + + hal_rx_mon_next_link_desc_get(rx_msdu_link_desc, &buf_info, + &p_buf_addr_info); + + dp_rx_link_desc_return(soc, p_last_buf_addr_info); + p_last_buf_addr_info = p_buf_addr_info; + + } while (buf_info.paddr && msdu_cnt); + + return rx_bufs_used; +} + +/** +* dp_rxdma_err_process() - RxDMA error processing functionality +* +* @soc: core txrx main contex +* @mac_id: mac id which is one of 3 mac_ids +* @hal_ring: opaque pointer to the HAL Rx Ring, which will be serviced +* @quota: No. of units (packets) that can be serviced in one shot. + +* Return: num of buffers processed +*/ +uint32_t +dp_rxdma_err_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota) +{ + struct dp_pdev *pdev = soc->pdev_list[mac_id]; + uint8_t pdev_id; + void *hal_soc; + void *rxdma_dst_ring_desc; + void *err_dst_srng; + union dp_rx_desc_list_elem_t *head = NULL; + union dp_rx_desc_list_elem_t *tail = NULL; + struct dp_srng *dp_rxdma_srng; + struct rx_desc_pool *rx_desc_pool; + uint32_t work_done = 0; + uint32_t rx_bufs_used = 0; + +#ifdef DP_INTR_POLL_BASED + if (!pdev) + return 0; +#endif + pdev_id = pdev->pdev_id; + err_dst_srng = pdev->rxdma_err_dst_ring.hal_srng; + + if (!err_dst_srng) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "%s %d : HAL Monitor Destination Ring Init \ + Failed -- %p\n", + __func__, __LINE__, err_dst_srng); + return 0; + } + + hal_soc = soc->hal_soc; + + qdf_assert(hal_soc); + + if (qdf_unlikely(hal_srng_access_start(hal_soc, err_dst_srng))) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + "%s %d : HAL Monitor Destination Ring Init \ + Failed -- %p\n", + __func__, __LINE__, err_dst_srng); + return 0; + } + + while (qdf_likely((rxdma_dst_ring_desc = + hal_srng_dst_get_next(hal_soc, err_dst_srng)) && quota--)) { + + rx_bufs_used += dp_rx_err_mpdu_pop(soc, mac_id, + rxdma_dst_ring_desc, + &head, &tail); + } + + hal_srng_access_end(hal_soc, err_dst_srng); + + if (rx_bufs_used) { + dp_rxdma_srng = &pdev->rx_refill_buf_ring; + rx_desc_pool = &soc->rx_desc_buf[mac_id]; + + dp_rx_buffers_replenish(soc, pdev_id, dp_rxdma_srng, + rx_desc_pool, rx_bufs_used, &head, &tail, + HAL_RX_BUF_RBM_SW3_BM); + work_done += rx_bufs_used; + } + + return work_done; +} diff --git a/dp/wifi3.0/dp_rx_mon.h b/dp/wifi3.0/dp_rx_mon.h index 7bf371760e..d3fc6fff96 100644 --- a/dp/wifi3.0/dp_rx_mon.h +++ b/dp/wifi3.0/dp_rx_mon.h @@ -48,4 +48,7 @@ QDF_STATUS dp_rx_pdev_mon_status_detach(struct dp_pdev *pdev); uint32_t dp_mon_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota); QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id, qdf_nbuf_t head_msdu, qdf_nbuf_t tail_msdu); + +uint32_t dp_rxdma_err_process(struct dp_soc *soc, uint32_t mac_id, + uint32_t quota); #endif diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 02e3637f31..d41875c5e0 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -723,6 +723,9 @@ struct dp_pdev { struct dp_srng rxdma_mon_desc_ring; + /* RXDMA error destination ring */ + struct dp_srng rxdma_err_dst_ring; + /* Link descriptor memory banks */ struct { void *base_vaddr_unaligned;