diff --git a/hif/src/ce/ce_internal.h b/hif/src/ce/ce_internal.h index 16443be878c9..7569d10a9c5a 100644 --- a/hif/src/ce/ce_internal.h +++ b/hif/src/ce/ce_internal.h @@ -438,6 +438,10 @@ enum hif_ce_event_type { NAPI_POLL_ENTER, NAPI_COMPLETE, NAPI_POLL_EXIT, + + HIF_RX_NBUF_ALLOC_FAILURE = 0x20, + HIF_RX_NBUF_MAP_FAILURE, + HIF_RX_NBUF_ENQUEUE_FAILURE, }; void ce_init_ce_desc_event_log(int ce_id, int size); diff --git a/hif/src/ce/ce_main.c b/hif/src/ce/ce_main.c index 58085bdad320..dd3b38c0143d 100644 --- a/hif/src/ce/ce_main.c +++ b/hif/src/ce/ce_main.c @@ -1721,6 +1721,34 @@ void hif_dump_pipe_debug_count(struct hif_softc *scn) } } +static void hif_post_recv_buffers_failure(struct HIF_CE_pipe_info *pipe_info, + void *nbuf, uint32_t *error_cnt, + enum hif_ce_event_type failure_type, + const char *failure_type_string) +{ + int bufs_needed_tmp = atomic_inc_return(&pipe_info->recv_bufs_needed); + struct CE_state *CE_state = (struct CE_state *)pipe_info->ce_hdl; + struct hif_softc *scn = HIF_GET_SOFTC(pipe_info->HIF_CE_state); + int ce_id = CE_state->id; + uint32_t error_cnt_tmp; + + qdf_spin_lock_bh(&pipe_info->recv_bufs_needed_lock); + error_cnt_tmp = ++(*error_cnt); + qdf_spin_unlock_bh(&pipe_info->recv_bufs_needed_lock); + HIF_ERROR("%s: pipe_num %d, needed %d, err_cnt = %u, fail_type = %s", + __func__, pipe_info->pipe_num, bufs_needed_tmp, error_cnt_tmp, + failure_type_string); + hif_record_ce_desc_event(scn, ce_id, failure_type, + NULL, nbuf, bufs_needed_tmp); + /* if we fail to allocate the last buffer for an rx pipe, + * there is no trigger to refill the ce and we will + * eventually crash + */ + if (bufs_needed_tmp == CE_state->dest_ring->nentries - 1) + QDF_ASSERT(0); +} + + static int hif_post_recv_buffers_for_pipe(struct HIF_CE_pipe_info *pipe_info) { struct CE_handle *ce_hdl; @@ -1748,16 +1776,10 @@ static int hif_post_recv_buffers_for_pipe(struct HIF_CE_pipe_info *pipe_info) nbuf = qdf_nbuf_alloc(scn->qdf_dev, buf_sz, 0, 4, false); if (!nbuf) { - qdf_spin_lock_bh(&pipe_info->recv_bufs_needed_lock); - pipe_info->nbuf_alloc_err_count++; - qdf_spin_unlock_bh( - &pipe_info->recv_bufs_needed_lock); - HIF_ERROR( - "%s buf alloc error [%d] needed %d, nbuf_alloc_err_count = %u", - __func__, pipe_info->pipe_num, - atomic_read(&pipe_info->recv_bufs_needed), - pipe_info->nbuf_alloc_err_count); - atomic_inc(&pipe_info->recv_bufs_needed); + hif_post_recv_buffers_failure(pipe_info, nbuf, + &pipe_info->nbuf_alloc_err_count, + HIF_RX_NBUF_ALLOC_FAILURE, + "HIF_RX_NBUF_ALLOC_FAILURE"); return 1; } @@ -1771,16 +1793,11 @@ static int hif_post_recv_buffers_for_pipe(struct HIF_CE_pipe_info *pipe_info) QDF_DMA_FROM_DEVICE); if (unlikely(ret != QDF_STATUS_SUCCESS)) { - qdf_spin_lock_bh(&pipe_info->recv_bufs_needed_lock); - pipe_info->nbuf_dma_err_count++; - qdf_spin_unlock_bh(&pipe_info->recv_bufs_needed_lock); - HIF_ERROR( - "%s buf alloc error [%d] needed %d, nbuf_dma_err_count = %u", - __func__, pipe_info->pipe_num, - atomic_read(&pipe_info->recv_bufs_needed), - pipe_info->nbuf_dma_err_count); + hif_post_recv_buffers_failure(pipe_info, nbuf, + &pipe_info->nbuf_dma_err_count, + HIF_RX_NBUF_MAP_FAILURE, + "HIF_RX_NBUF_MAP_FAILURE"); qdf_nbuf_free(nbuf); - atomic_inc(&pipe_info->recv_bufs_needed); return 1; } @@ -1790,18 +1807,14 @@ static int hif_post_recv_buffers_for_pipe(struct HIF_CE_pipe_info *pipe_info) buf_sz, DMA_FROM_DEVICE); status = ce_recv_buf_enqueue(ce_hdl, (void *)nbuf, CE_data); QDF_ASSERT(status == QDF_STATUS_SUCCESS); - if (status != EOK) { - qdf_spin_lock_bh(&pipe_info->recv_bufs_needed_lock); - pipe_info->nbuf_ce_enqueue_err_count++; - qdf_spin_unlock_bh(&pipe_info->recv_bufs_needed_lock); - HIF_ERROR( - "%s buf alloc error [%d] needed %d, nbuf_alloc_err_count = %u", - __func__, pipe_info->pipe_num, - atomic_read(&pipe_info->recv_bufs_needed), - pipe_info->nbuf_ce_enqueue_err_count); + if (unlikely(status != EOK)) { + hif_post_recv_buffers_failure(pipe_info, nbuf, + &pipe_info->nbuf_ce_enqueue_err_count, + HIF_RX_NBUF_ENQUEUE_FAILURE, + "HIF_RX_NBUF_ENQUEUE_FAILURE"); + qdf_nbuf_unmap_single(scn->qdf_dev, nbuf, QDF_DMA_FROM_DEVICE); - atomic_inc(&pipe_info->recv_bufs_needed); qdf_nbuf_free(nbuf); return 1; } @@ -1817,7 +1830,7 @@ static int hif_post_recv_buffers_for_pipe(struct HIF_CE_pipe_info *pipe_info) pipe_info->nbuf_dma_err_count - bufs_posted : 0; pipe_info->nbuf_ce_enqueue_err_count = (pipe_info->nbuf_ce_enqueue_err_count > bufs_posted) ? - pipe_info->nbuf_ce_enqueue_err_count - bufs_posted : 0; + pipe_info->nbuf_ce_enqueue_err_count - bufs_posted : 0; qdf_spin_unlock_bh(&pipe_info->recv_bufs_needed_lock);