Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit be9f588e authored by Mohit Khanna's avatar Mohit Khanna Committed by Madan Koyyalamudi
Browse files

qcacmn: Handle BUF_ADDR ring desc in dp_rx_err

Currently dp_rx_err_process expects ring descriptor to be only
LINK_DESC_TYPE. In certain cases BUF_ADDR_TYPE ring descriptor is
observed in reo_exception ring. Add logic to handle the same.

Change-Id: I5baecc3f8eafc0830672b91bc9d9607b568a6cda
CRs-Fixed: 2954653
parent 5fb54e2e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -426,6 +426,7 @@ static inline void dp_wds_ext_peer_init(struct dp_peer *peer)
 * 2.4GHz band uses lmac_id = 1
 * 5GHz/6GHz band uses lmac_id=0
 */
#define DP_INVALID_LMAC_ID	(-1)
#define DP_MON_INVALID_LMAC_ID	(-1)
#define DP_MON_2G_LMAC_ID	1
#define DP_MON_5G_LMAC_ID	0
+128 −2
Original line number Diff line number Diff line
@@ -36,6 +36,11 @@
/* Max buffer in invalid peer SG list*/
#define DP_MAX_INVALID_BUFFERS 10

/* Max regular Rx packet routing error */
#define DP_MAX_REG_RX_ROUTING_ERRS_THRESHOLD 20
#define DP_MAX_REG_RX_ROUTING_ERRS_IN_TIMEOUT 10
#define DP_RX_ERR_ROUTE_TIMEOUT_US (5 * 1000 * 1000) /* micro seconds */

/**
 * dp_rx_mcast_echo_check() - check if the mcast pkt is a loop
 *			      back on same vap or a different vap.
@@ -905,10 +910,11 @@ dp_rx_bar_frame_handle(struct dp_soc *soc,
next:
	dp_rx_link_desc_return(soc, ring_desc,
			       HAL_BM_ACTION_PUT_IN_IDLE_LIST);
	dp_rx_buffer_pool_nbuf_free(soc, rx_desc->nbuf,
				    rx_desc->pool_id);
	dp_rx_add_to_free_desc_list(&pdev->free_list_head,
				    &pdev->free_list_tail,
				    rx_desc);
	qdf_nbuf_free(nbuf);
}

/**
@@ -1653,6 +1659,119 @@ dp_rx_err_ring_record_entry(struct dp_soc *soc, uint64_t paddr,
}
#endif

#ifdef HANDLE_RX_REROUTE_ERR
static int dp_rx_err_handle_msdu_buf(struct dp_soc *soc,
				     hal_ring_desc_t ring_desc)
{
	int lmac_id = DP_INVALID_LMAC_ID;
	uint32_t cookie = 0;
	struct dp_rx_desc *rx_desc = NULL;
	struct hal_buf_info hbi;
	struct dp_pdev *pdev;

	cookie = HAL_RX_REO_BUF_COOKIE_GET(ring_desc);
	rx_desc = dp_rx_cookie_2_va_rxdma_buf(soc, cookie);

	/* sanity */
	if (!rx_desc) {
		DP_STATS_INC(soc, rx.err.reo_err_msdu_buf_invalid_cookie, 1);
		goto assert_return;
	}

	if (!rx_desc->nbuf)
		goto assert_return;

	hal_rx_reo_buf_paddr_get(ring_desc, &hbi);
	dp_rx_err_ring_record_entry(soc, hbi.paddr,
				    hbi.sw_cookie,
				    hal_rx_ret_buf_manager_get(ring_desc));
	if (hbi.paddr != qdf_nbuf_get_frag_paddr(rx_desc->nbuf, 0)) {
		DP_STATS_INC(soc, rx.err.nbuf_sanity_fail, 1);
		rx_desc->in_err_state = 1;
		goto assert_return;
	}

	/* After this point the rx_desc and nbuf are valid */
	dp_ipa_rx_buf_smmu_mapping_lock(soc);
	qdf_assert_always(rx_desc->unmapped);
	dp_ipa_handle_rx_buf_smmu_mapping(soc,
					  rx_desc->nbuf,
					  RX_DATA_BUFFER_SIZE,
					  false);
	qdf_nbuf_unmap_nbytes_single(soc->osdev,
				     rx_desc->nbuf,
				     QDF_DMA_FROM_DEVICE,
				     RX_DATA_BUFFER_SIZE);
	rx_desc->unmapped = 1;
	dp_ipa_rx_buf_smmu_mapping_unlock(soc);
	dp_rx_buffer_pool_nbuf_free(soc, rx_desc->nbuf,
				    rx_desc->pool_id);

	pdev = dp_get_pdev_for_lmac_id(soc, rx_desc->pool_id);
	lmac_id = rx_desc->pool_id;
	dp_rx_add_to_free_desc_list(&pdev->free_list_head,
				    &pdev->free_list_tail,
				    rx_desc);
	return lmac_id;

assert_return:
	qdf_assert(0);
	return lmac_id;
}

static int dp_rx_err_exception(struct dp_soc *soc, hal_ring_desc_t ring_desc)
{
	int ret;
	uint64_t cur_time_stamp;

	DP_STATS_INC(soc, rx.err.reo_err_msdu_buf_rcved, 1);

	/* Recover if overall error count exceeds threshold */
	if (soc->stats.rx.err.reo_err_msdu_buf_rcved >
	    DP_MAX_REG_RX_ROUTING_ERRS_THRESHOLD) {
		dp_err("pkt threshold breached! reo_err_msdu_buf_rcved %u first err pkt time_stamp %llu",
		       soc->stats.rx.err.reo_err_msdu_buf_rcved,
		       soc->rx_route_err_start_pkt_ts);
		qdf_trigger_self_recovery(NULL, QDF_RX_REG_PKT_ROUTE_ERR);
	}

	cur_time_stamp = qdf_get_log_timestamp_usecs();
	if (!soc->rx_route_err_start_pkt_ts)
		soc->rx_route_err_start_pkt_ts = cur_time_stamp;

	/* Recover if threshold number of packets received in threshold time */
	if ((cur_time_stamp - soc->rx_route_err_start_pkt_ts) >
						DP_RX_ERR_ROUTE_TIMEOUT_US) {
		soc->rx_route_err_start_pkt_ts = cur_time_stamp;

		if (soc->rx_route_err_in_window >
		    DP_MAX_REG_RX_ROUTING_ERRS_IN_TIMEOUT) {
			qdf_trigger_self_recovery(NULL,
						  QDF_RX_REG_PKT_ROUTE_ERR);
			dp_err("rate threshold breached! reo_err_msdu_buf_rcved %u first err pkt time_stamp %llu",
			       soc->stats.rx.err.reo_err_msdu_buf_rcved,
			       soc->rx_route_err_start_pkt_ts);
		} else {
			soc->rx_route_err_in_window = 1;
		}
	} else {
		soc->rx_route_err_in_window++;
	}

	ret = dp_rx_err_handle_msdu_buf(soc, ring_desc);

	return ret;
}
#else /* HANDLE_RX_REROUTE_ERR */

static int dp_rx_err_exception(struct dp_soc *soc, hal_ring_desc_t ring_desc)
{
	qdf_assert_always(0);

	return DP_INVALID_LMAC_ID;
}
#endif /* HANDLE_RX_REROUTE_ERR */

uint32_t
dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
		  hal_ring_handle_t hal_ring_hdl, uint32_t quota)
@@ -1718,7 +1837,14 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
		/*
		 * For REO error ring, expect only MSDU LINK DESC
		 */
		qdf_assert_always(buf_type == HAL_RX_REO_MSDU_LINK_DESC_TYPE);
		if (qdf_unlikely(buf_type != HAL_RX_REO_MSDU_LINK_DESC_TYPE)) {
			int lmac_id;

			lmac_id = dp_rx_err_exception(soc, ring_desc);
			if (lmac_id >= 0)
				rx_bufs_reaped[lmac_id] += 1;
			goto next_entry;
		}

		cookie = HAL_RX_REO_BUF_COOKIE_GET(ring_desc);
		/*
+10 −0
Original line number Diff line number Diff line
@@ -1006,6 +1006,10 @@ struct dp_soc_stats {
			uint32_t rx_2k_jump_to_stack;
			/* RX 2k jump msdu dropped count */
			uint32_t rx_2k_jump_drop;
			/* REO ERR msdu buffer received */
			uint32_t reo_err_msdu_buf_rcved;
			/* REO ERR msdu buffer with invalid coookie received */
			uint32_t reo_err_msdu_buf_invalid_cookie;
			/* REO OOR msdu drop count */
			uint32_t reo_err_oor_drop;
			/* REO OOR msdu indicated to stack count */
@@ -1669,6 +1673,12 @@ struct dp_soc {
	/* SoC level data path statistics */
	struct dp_soc_stats stats;

	/* timestamp to keep track of msdu buffers received on reo err ring */
	uint64_t rx_route_err_start_pkt_ts;

	/* Num RX Route err in a given window to keep track of rate of errors */
	uint32_t rx_route_err_in_window;

	/* Enable processing of Tx completion status words */
	bool process_tx_status;
	bool process_rx_status;
+2 −0
Original line number Diff line number Diff line
@@ -1352,6 +1352,7 @@ enum qdf_suspend_type {
 * @QDF_HAL_REG_WRITE_FAILURE: HAL register writing failures
 * @QDF_SUSPEND_NO_CREDIT: host lack of credit after suspend
 * @QDF_TASKLET_CREDIT_LATENCY_DETECT: tasklet or credit latency happened
 * @QDF_RX_REG_PKT_ROUTE_ERR: MSDU buf errors exceed thresh in REO err path
 */
enum qdf_hang_reason {
	QDF_REASON_UNSPECIFIED,
@@ -1378,6 +1379,7 @@ enum qdf_hang_reason {
	QDF_HAL_REG_WRITE_FAILURE,
	QDF_SUSPEND_NO_CREDIT,
	QDF_TASKLET_CREDIT_LATENCY_DETECT,
	QDF_RX_REG_PKT_ROUTE_ERR,
};

/**