qcacmn: Improve recv buffer refill failure logging

Make it easier to identify when nbuf allocation starvation
in hif is the root cause for a crash, by adding events to
the hif_ce_desc_history buffer.

Change-Id: Id3b919f17ee79770f5fa81b389f9a28a0670cfa2
CRs-Fixed: 2011015
This commit is contained in:
Houston Hoffman 2017-02-24 17:37:46 -08:00 • committed by Sandeep Puligilla
commit c0c00a2c46
2 changed files with 47 additions and 30 deletions

View file

@ -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);

View file

@ -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);