diff --git a/dp/inc/cdp_txrx_cmn_struct.h b/dp/inc/cdp_txrx_cmn_struct.h index 3deded7e2370..197ece62d030 100644 --- a/dp/inc/cdp_txrx_cmn_struct.h +++ b/dp/inc/cdp_txrx_cmn_struct.h @@ -991,6 +991,8 @@ struct cdp_pdev_stats { uint32_t map_err; /* x86 failures */ uint32_t x86_fail; + /* low threshold interrupts */ + uint32_t low_thresh_intrs; } replenish; /* Rx Raw Packets */ diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index a52c9172f612..480727188b3b 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -339,8 +339,11 @@ static int dp_srng_calculate_msi_group(struct dp_soc *soc, grp_mask = &soc->wlan_cfg_ctx->int_rxdma2host_ring_mask[0]; break; - case RXDMA_MONITOR_BUF: case RXDMA_BUF: + grp_mask = &soc->wlan_cfg_ctx->int_host2rxdma_ring_mask[0]; + break; + + case RXDMA_MONITOR_BUF: /* TODO: support low_thresh interrupt */ return -QDF_STATUS_E_NOENT; break; @@ -490,6 +493,7 @@ static int dp_srng_setup(struct dp_soc *soc, struct dp_srng *srng, num_entries = (num_entries > max_entries) ? max_entries : num_entries; srng->hal_srng = NULL; srng->alloc_size = (num_entries * entry_size) + ring_base_align - 1; + srng->num_entries = num_entries; srng->base_vaddr_unaligned = qdf_mem_alloc_consistent( soc->osdev, soc->osdev->dev, srng->alloc_size, &(srng->base_paddr_unaligned)); @@ -608,6 +612,7 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget) uint8_t rx_wbm_rel_mask = int_ctx->rx_wbm_rel_ring_mask; uint8_t reo_status_mask = int_ctx->reo_status_ring_mask; uint32_t remaining_quota = dp_budget; + struct dp_pdev *pdev = NULL; /* Process Tx completion interrupts first to return back buffers */ while (tx_mask) { @@ -689,11 +694,14 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget) /* Process LMAC interrupts */ for (ring = 0 ; ring < MAX_PDEV_CNT; ring++) { - if (soc->pdev_list[ring] == NULL) + pdev = soc->pdev_list[ring]; + if (pdev == NULL) continue; if (int_ctx->rx_mon_ring_mask & (1 << ring)) { work_done = dp_mon_process(soc, ring, remaining_quota); budget -= work_done; + if (budget <= 0) + goto budget_done; remaining_quota = budget; } @@ -701,6 +709,22 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget) work_done = dp_rxdma_err_process(soc, ring, remaining_quota); budget -= work_done; + if (budget <= 0) + goto budget_done; + remaining_quota = budget; + } + + if (int_ctx->host2rxdma_ring_mask & (1 << ring)) { + union dp_rx_desc_list_elem_t *desc_list = NULL; + union dp_rx_desc_list_elem_t *tail = NULL; + struct dp_srng *rx_refill_buf_ring = + &pdev->rx_refill_buf_ring; + + DP_STATS_INC(pdev, replenish.low_thresh_intrs, 1); + dp_rx_buffers_replenish(soc, ring, + rx_refill_buf_ring, + &soc->rx_desc_buf[ring], 0, + &desc_list, &tail, HAL_RX_BUF_RBM_SW3_BM); } } @@ -758,6 +782,7 @@ static QDF_STATUS dp_soc_interrupt_attach_poll(void *txrx_soc) soc->intr_ctx[i].rx_wbm_rel_ring_mask = 0x1; soc->intr_ctx[i].reo_status_ring_mask = 0x1; soc->intr_ctx[i].rxdma2host_ring_mask = 0x1; + soc->intr_ctx[i].host2rxdma_ring_mask = 0x1; soc->intr_ctx[i].soc = soc; soc->intr_ctx[i].lro_ctx = qdf_lro_init(); } @@ -825,6 +850,8 @@ static void dp_soc_interrupt_map_calculate_integrated(struct dp_soc *soc, soc->wlan_cfg_ctx, intr_ctx_num); int rxdma2host_ring_mask = wlan_cfg_get_rxdma2host_ring_mask( soc->wlan_cfg_ctx, intr_ctx_num); + int host2rxdma_ring_mask = wlan_cfg_get_host2rxdma_ring_mask( + soc->wlan_cfg_ctx, intr_ctx_num); for (j = 0; j < HIF_MAX_GRP_IRQ; j++) { @@ -844,6 +871,12 @@ static void dp_soc_interrupt_map_calculate_integrated(struct dp_soc *soc, wlan_cfg_get_hw_mac_idx(soc->wlan_cfg_ctx, j); } + if (host2rxdma_ring_mask & (1 << j)) { + irq_id_map[num_irq++] = + host2rxdma_host_buf_ring_mac1 - + wlan_cfg_get_hw_mac_idx(soc->wlan_cfg_ctx, j); + } + if (rx_mon_mask & (1 << j)) { irq_id_map[num_irq++] = ppdu_end_interrupts_mac1 - @@ -953,6 +986,9 @@ static QDF_STATUS dp_soc_interrupt_attach(void *txrx_soc) wlan_cfg_get_reo_status_ring_mask(soc->wlan_cfg_ctx, i); int rxdma2host_ring_mask = wlan_cfg_get_rxdma2host_ring_mask(soc->wlan_cfg_ctx, i); + int host2rxdma_ring_mask = + wlan_cfg_get_host2rxdma_ring_mask(soc->wlan_cfg_ctx, i); + soc->intr_ctx[i].dp_intr_id = i; soc->intr_ctx[i].tx_ring_mask = tx_mask; @@ -960,6 +996,7 @@ static QDF_STATUS dp_soc_interrupt_attach(void *txrx_soc) soc->intr_ctx[i].rx_mon_ring_mask = rx_mon_mask; soc->intr_ctx[i].rx_err_ring_mask = rx_err_ring_mask; soc->intr_ctx[i].rxdma2host_ring_mask = rxdma2host_ring_mask; + soc->intr_ctx[i].host2rxdma_ring_mask = host2rxdma_ring_mask; soc->intr_ctx[i].rx_wbm_rel_ring_mask = rx_wbm_rel_ring_mask; soc->intr_ctx[i].reo_status_ring_mask = reo_status_ring_mask; @@ -1015,6 +1052,7 @@ static void dp_soc_interrupt_detach(void *txrx_soc) soc->intr_ctx[i].rx_wbm_rel_ring_mask = 0; soc->intr_ctx[i].reo_status_ring_mask = 0; soc->intr_ctx[i].rxdma2host_ring_mask = 0; + soc->intr_ctx[i].host2rxdma_ring_mask = 0; qdf_lro_deinit(soc->intr_ctx[i].lro_ctx); } @@ -1344,7 +1382,7 @@ static void dp_hw_link_desc_pool_cleanup(struct dp_soc *soc) #define REO_CMD_RING_SIZE 32 #define REO_STATUS_RING_SIZE 32 #define RXDMA_BUF_RING_SIZE 1024 -#define RXDMA_REFILL_RING_SIZE 2048 +#define RXDMA_REFILL_RING_SIZE 4096 #define RXDMA_MONITOR_BUF_RING_SIZE 4096 #define RXDMA_MONITOR_DST_RING_SIZE 2048 #define RXDMA_MONITOR_STATUS_RING_SIZE 1024 @@ -1489,6 +1527,7 @@ static uint8_t dp_soc_ring_if_nss_offloaded(struct dp_soc *soc, enum hal_ring_ty switch (ring_type) { case WBM2SW_RELEASE: case REO_DST: + case RXDMA_BUF: status = ((nss_config) & (1 << ring_num)); break; default: @@ -1530,7 +1569,7 @@ static void dp_soc_reset_intr_mask(struct dp_soc *soc) group_number = dp_srng_find_ring_in_mask(j, grp_mask); if (group_number < 0) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - FL("ring not part of an group; ring_type: %d,ring_num %d"), + FL("ring not part of any group; ring_type: %d,ring_num %d"), WBM2SW_RELEASE, j); return; } @@ -1565,7 +1604,7 @@ static void dp_soc_reset_intr_mask(struct dp_soc *soc) group_number = dp_srng_find_ring_in_mask(j, grp_mask); if (group_number < 0) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - FL("ring not part of an group; ring_type: %d,ring_num %d"), + FL("ring not part of any group; ring_type: %d,ring_num %d"), REO_DST, j); return; } @@ -1579,6 +1618,40 @@ static void dp_soc_reset_intr_mask(struct dp_soc *soc) */ wlan_cfg_set_rx_ring_mask(soc->wlan_cfg_ctx, group_number, mask); } + + /* + * group mask for Rx buffer refill ring + */ + grp_mask = &soc->wlan_cfg_ctx->int_host2rxdma_ring_mask[0]; + + /* loop and reset the mask for only offloaded ring */ + for (j = 0; j < MAX_PDEV_CNT; j++) { + if (!dp_soc_ring_if_nss_offloaded(soc, RXDMA_BUF, j)) { + continue; + } + + /* + * Group number corresponding to rx offloaded ring. + */ + group_number = dp_srng_find_ring_in_mask(j, grp_mask); + if (group_number < 0) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + FL("ring not part of any group; ring_type: %d,ring_num %d"), + REO_DST, j); + return; + } + + /* set the interrupt mask for offloaded ring */ + mask = wlan_cfg_get_host2rxdma_ring_mask(soc->wlan_cfg_ctx, + group_number); + mask &= (~(1 << j)); + + /* + * set the interrupt mask to zero for rx offloaded radio. + */ + wlan_cfg_set_host2rxdma_ring_mask(soc->wlan_cfg_ctx, + group_number, mask); + } } #ifdef IPA_OFFLOAD @@ -3857,6 +3930,8 @@ dp_print_pdev_rx_stats(struct dp_pdev *pdev) pdev->stats.replenish.pkts.bytes); DP_PRINT_STATS(" Buffers Added To Freelist = %d", pdev->stats.buf_freelist); + DP_PRINT_STATS(" Low threshold intr = %d", + pdev->stats.replenish.low_thresh_intrs); DP_PRINT_STATS("Dropped:"); DP_PRINT_STATS(" msdu_not_done = %d", pdev->stats.dropped.msdu_not_done); diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 7b139ad31117..d088a965eca3 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -107,6 +107,29 @@ QDF_STATUS dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id, QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, "requested %d buffers for replenish", num_req_buffers); + hal_srng_access_start(dp_soc->hal_soc, rxdma_srng); + num_entries_avail = hal_srng_src_num_avail(dp_soc->hal_soc, + rxdma_srng, + sync_hw_ptr); + + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, + "no of availble entries in rxdma ring: %d", + num_entries_avail); + + if (!(*desc_list) && (num_entries_avail > + ((dp_rxdma_srng->num_entries * 3) / 4))) { + num_req_buffers = num_entries_avail; + } else if (num_entries_avail < num_req_buffers) { + num_desc_to_free = num_req_buffers - num_entries_avail; + num_req_buffers = num_entries_avail; + } + + if (qdf_unlikely(!num_req_buffers)) { + num_desc_to_free = num_req_buffers; + hal_srng_access_end(dp_soc->hal_soc, rxdma_srng); + goto free_descs; + } + /* * if desc_list is NULL, allocate the descs from freelist */ @@ -122,6 +145,7 @@ QDF_STATUS dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id, "no free rx_descs in freelist"); DP_STATS_INC(dp_pdev, err.desc_alloc_fail, num_req_buffers); + hal_srng_access_end(dp_soc->hal_soc, rxdma_srng); return QDF_STATUS_E_NOMEM; } @@ -130,19 +154,6 @@ QDF_STATUS dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id, num_req_buffers = num_alloc_desc; } - hal_srng_access_start(dp_soc->hal_soc, rxdma_srng); - num_entries_avail = hal_srng_src_num_avail(dp_soc->hal_soc, - rxdma_srng, - sync_hw_ptr); - - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, - "no of availble entries in rxdma ring: %d", - num_entries_avail); - - if (num_entries_avail < num_req_buffers) { - num_desc_to_free = num_req_buffers - num_entries_avail; - num_req_buffers = num_entries_avail; - } count = 0; @@ -208,10 +219,11 @@ QDF_STATUS dp_rx_buffers_replenish(struct dp_soc *dp_soc, uint32_t mac_id, QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, "%d rx desc added back to free list", num_desc_to_free); - DP_STATS_INC(dp_pdev, buf_freelist, num_desc_to_free); DP_STATS_INC_PKT(dp_pdev, replenish.pkts, num_req_buffers, (RX_BUFFER_SIZE * num_req_buffers)); +free_descs: + DP_STATS_INC(dp_pdev, buf_freelist, num_desc_to_free); /* * add any available free desc back to the free list */ @@ -1449,7 +1461,7 @@ dp_rx_pdev_attach(struct dp_pdev *pdev) /* For Rx buffers, WBM release ring is SW RING 3,for all pdev's */ dp_rxdma_srng = &pdev->rx_refill_buf_ring; dp_rx_buffers_replenish(soc, pdev_id, dp_rxdma_srng, rx_desc_pool, - rxdma_entries, &desc_list, &tail, HAL_RX_BUF_RBM_SW3_BM); + 0, &desc_list, &tail, HAL_RX_BUF_RBM_SW3_BM); return QDF_STATUS_SUCCESS; } diff --git a/dp/wifi3.0/dp_rx_desc.c b/dp/wifi3.0/dp_rx_desc.c index 621c0f78c771..b91dbae4a0fd 100644 --- a/dp/wifi3.0/dp_rx_desc.c +++ b/dp/wifi3.0/dp_rx_desc.c @@ -126,6 +126,7 @@ uint16_t dp_rx_get_free_desc_list(struct dp_soc *soc, uint32_t pool_id, return count; } } + (*tail)->next = NULL; qdf_spin_unlock_bh(&soc->rx_desc_mutex[pool_id]); return count; } @@ -152,7 +153,7 @@ void dp_rx_add_desc_list_to_free_list(struct dp_soc *soc, temp_list = rx_desc_pool->freelist; - qdf_print( + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG, "temp_list: %pK, *local_desc_list: %pK, *tail: %pK (*tail)->next: %pK\n", temp_list, *local_desc_list, *tail, (*tail)->next); rx_desc_pool->freelist = *local_desc_list; diff --git a/dp/wifi3.0/dp_rx_err.c b/dp/wifi3.0/dp_rx_err.c index a77ef50c1182..0045eb601936 100644 --- a/dp/wifi3.0/dp_rx_err.c +++ b/dp/wifi3.0/dp_rx_err.c @@ -992,7 +992,7 @@ dp_rx_wbm_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota) default: QDF_TRACE(QDF_MODULE_ID_DP, - QDF_TRACE_LEVEL_ERROR, + QDF_TRACE_LEVEL_DEBUG, "REO error %d detected", reo_error_code); } @@ -1029,13 +1029,13 @@ dp_rx_wbm_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota) case HAL_RXDMA_ERR_DECRYPT: QDF_TRACE(QDF_MODULE_ID_DP, - QDF_TRACE_LEVEL_ERROR, + QDF_TRACE_LEVEL_DEBUG, "Packet received with Decrypt error"); break; default: QDF_TRACE(QDF_MODULE_ID_DP, - QDF_TRACE_LEVEL_ERROR, + QDF_TRACE_LEVEL_DEBUG, "RXDMA error %d", rxdma_error_code); } diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 2a56d63fd7f5..1eeb42280deb 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -358,6 +358,7 @@ struct dp_srng { qdf_dma_addr_t base_paddr_unaligned; uint32_t alloc_size; int irq; + uint32_t num_entries; }; struct dp_rx_reorder_array_elem { @@ -427,6 +428,7 @@ struct dp_intr { uint8_t rx_wbm_rel_ring_mask; /* WBM2SW Rx Release Ring */ uint8_t reo_status_ring_mask; /* REO command response ring */ uint8_t rxdma2host_ring_mask; /* RXDMA to host destination ring */ + uint8_t host2rxdma_ring_mask; /* Host to RXDMA buffer ring */ struct dp_soc *soc; /* Reference to SoC structure , to get DMA ring handles */ qdf_lro_ctx_t lro_ctx; diff --git a/wlan_cfg/wlan_cfg.c b/wlan_cfg/wlan_cfg.c index 511945c604b3..ae124c27a849 100644 --- a/wlan_cfg/wlan_cfg.c +++ b/wlan_cfg/wlan_cfg.c @@ -77,7 +77,7 @@ /* Interrupt Mitigation - Timer threshold in us */ #define WLAN_CFG_INT_TIMER_THRESHOLD_TX 1000 #define WLAN_CFG_INT_TIMER_THRESHOLD_RX 500 -#define WLAN_CFG_INT_TIMER_THRESHOLD_OTHER 8 +#define WLAN_CFG_INT_TIMER_THRESHOLD_OTHER 1000 #define WLAN_CFG_TX_RING_SIZE 512 @@ -159,6 +159,11 @@ #define WLAN_CFG_RXDMA2HOST_RING_MASK_2 0x4 #define WLAN_CFG_RXDMA2HOST_RING_MASK_3 0x0 +#define WLAN_CFG_HOST2RXDMA_RING_MASK_0 0x1 +#define WLAN_CFG_HOST2RXDMA_RING_MASK_1 0x2 +#define WLAN_CFG_HOST2RXDMA_RING_MASK_2 0x4 +#define WLAN_CFG_HOST2RXDMA_RING_MASK_3 0x0 + #define WLAN_CFG_DP_TX_NUM_POOLS 3 /* Change this to a lower value to enforce scattered idle list mode */ #define WLAN_CFG_MAX_ALLOC_SIZE (2 << 20) @@ -254,6 +259,12 @@ static const int rxdma2host_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { WLAN_CFG_RXDMA2HOST_RING_MASK_2, WLAN_CFG_RXDMA2HOST_RING_MASK_3}; +static const int host2rxdma_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS] = { + WLAN_CFG_HOST2RXDMA_RING_MASK_0, + WLAN_CFG_HOST2RXDMA_RING_MASK_1, + WLAN_CFG_HOST2RXDMA_RING_MASK_2, + WLAN_CFG_HOST2RXDMA_RING_MASK_3}; + /** * struct wlan_cfg_dp_pdev_ctxt - Configuration parameters for pdev (radio) * @rx_dma_buf_ring_size - Size of RxDMA buffer ring @@ -322,6 +333,8 @@ struct wlan_cfg_dp_soc_ctxt *wlan_cfg_soc_attach() reo_status_ring_mask[i]; wlan_cfg_ctx->int_rxdma2host_ring_mask[i] = rxdma2host_ring_mask[i]; + wlan_cfg_ctx->int_host2rxdma_ring_mask[i] = + host2rxdma_ring_mask[i]; } /* This is default mapping and can be overridden by HW config @@ -404,6 +417,18 @@ int wlan_cfg_get_rxdma2host_ring_mask(struct wlan_cfg_dp_soc_ctxt *cfg, return cfg->int_rxdma2host_ring_mask[context]; } +void wlan_cfg_set_host2rxdma_ring_mask(struct wlan_cfg_dp_soc_ctxt *cfg, + int context, int mask) +{ + cfg->int_host2rxdma_ring_mask[context] = mask; +} + +int wlan_cfg_get_host2rxdma_ring_mask(struct wlan_cfg_dp_soc_ctxt *cfg, + int context) +{ + return cfg->int_host2rxdma_ring_mask[context]; +} + void wlan_cfg_set_hw_macid(struct wlan_cfg_dp_soc_ctxt *cfg, int pdev_idx, int hw_macid) { diff --git a/wlan_cfg/wlan_cfg.h b/wlan_cfg/wlan_cfg.h index d28c301ff4b5..01bb228c8758 100644 --- a/wlan_cfg/wlan_cfg.h +++ b/wlan_cfg/wlan_cfg.h @@ -128,6 +128,7 @@ struct wlan_cfg_dp_soc_ctxt { int int_rx_wbm_rel_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS]; int int_reo_status_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS]; int int_rxdma2host_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS]; + int int_host2rxdma_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS]; int hw_macid[MAX_PDEV_CNT]; int base_hw_macid; bool lro_enabled; @@ -268,6 +269,27 @@ void wlan_cfg_set_rxdma2host_ring_mask(struct wlan_cfg_dp_soc_ctxt *cfg, int wlan_cfg_get_rxdma2host_ring_mask(struct wlan_cfg_dp_soc_ctxt *cfg, int context); +/** + * wlan_cfg_set_host2rxdma_ring_mask() - Set host2rxdma ring interrupt mask + * for the given interrupt context + * @wlan_cfg_ctx - Configuration Handle + * @context - Numerical ID identifying the Interrupt/NAPI context + * + */ +void wlan_cfg_set_host2rxdma_ring_mask(struct wlan_cfg_dp_soc_ctxt *cfg, + int context, int mask); + +/** + * wlan_cfg_get_host2rxdma_ring_mask() - Return host2rxdma ring interrupt mask + * mapped to an interrupt context + * @wlan_cfg_ctx - Configuration Handle + * @context - Numerical ID identifying the Interrupt/NAPI context + * + * Return: int_host2rxdma_ring_mask[context] + */ +int wlan_cfg_get_host2rxdma_ring_mask(struct wlan_cfg_dp_soc_ctxt *cfg, + int context); + /** * wlan_cfg_set_hw_macid() - Set HW MAC Id for the given PDEV index *