Преглед изворни кода

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
Houston Hoffman пре 8 година
родитељ
комит
c0c00a2c46
2 измењених фајлова са 47 додато и 30 уклоњено
  1. 4 0
      hif/src/ce/ce_internal.h
  2. 43 30
      hif/src/ce/ce_main.c

+ 4 - 0
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);

+ 43 - 30
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);