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
Dieser Commit ist enthalten in:

committet von
Madan Koyyalamudi

Ursprung
c3dc016a8c
Commit
c9bcf7e494
@@ -440,6 +440,7 @@ struct dp_srng *dp_get_rxdma_ring(struct dp_pdev *pdev, int lmac_id)
|
||||
* 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
|
||||
|
@@ -48,6 +48,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 */
|
||||
|
||||
#ifdef FEATURE_MEC
|
||||
bool dp_rx_mcast_echo_check(struct dp_soc *soc,
|
||||
struct dp_peer *peer,
|
||||
@@ -913,10 +918,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);
|
||||
}
|
||||
|
||||
#endif /* QCA_HOST_MODE_WIFI_DISABLED */
|
||||
@@ -1669,6 +1675,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;
|
||||
struct dp_rx_desc *rx_desc;
|
||||
struct hal_buf_info hbi;
|
||||
struct dp_pdev *pdev;
|
||||
|
||||
hal_rx_reo_buf_paddr_get(soc->hal_soc, ring_desc, &hbi);
|
||||
|
||||
rx_desc = dp_rx_cookie_2_va_rxdma_buf(soc, hbi.sw_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;
|
||||
|
||||
dp_rx_err_ring_record_entry(soc, hbi.paddr,
|
||||
hbi.sw_cookie,
|
||||
hal_rx_ret_buf_manager_get(soc->hal_soc,
|
||||
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)
|
||||
@@ -1732,9 +1851,17 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
|
||||
goto next_entry;
|
||||
|
||||
/*
|
||||
* For REO error ring, expect only MSDU LINK DESC
|
||||
* For REO error ring, only MSDU LINK DESC is expected.
|
||||
* Handle HAL_RX_REO_MSDU_BUF_ADDR_TYPE exception case.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
hal_rx_buf_cookie_rbm_get(hal_soc, (uint32_t *)ring_desc,
|
||||
&hbi);
|
||||
|
@@ -1023,6 +1023,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 */
|
||||
@@ -1801,6 +1805,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;
|
||||
|
@@ -1393,6 +1393,7 @@ enum qdf_suspend_type {
|
||||
* @QDF_SUSPEND_NO_CREDIT: host lack of credit after suspend
|
||||
* @QCA_HANG_BUS_FAILURE: Bus failure
|
||||
* @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,
|
||||
@@ -1420,6 +1421,7 @@ enum qdf_hang_reason {
|
||||
QDF_SUSPEND_NO_CREDIT,
|
||||
QCA_HANG_BUS_FAILURE,
|
||||
QDF_TASKLET_CREDIT_LATENCY_DETECT,
|
||||
QDF_RX_REG_PKT_ROUTE_ERR,
|
||||
};
|
||||
|
||||
/**
|
||||
|
In neuem Issue referenzieren
Einen Benutzer sperren