qcacmn: do not process duplicate descriptor frame in RX
once in a while the HW is sending a descriptor which is already processed by host. This can be a potential HW issue, as a WAR we are not processing such duplicate descriptors instead increment a counter and continue with next descriptor. Change-Id: I6c9bc6a9fb4705b42284171a32855411aa5dd73f CRs-Fixed: 2338543
This commit is contained in:

committed by
nshrivas

parent
e88c0e8ffa
commit
eff377a1d3
@@ -6502,6 +6502,10 @@ dp_print_soc_rx_stats(struct dp_soc *soc)
|
||||
DP_PRINT_STATS("RX frag wait: %d", soc->stats.rx.rx_frag_wait);
|
||||
DP_PRINT_STATS("RX frag err: %d", soc->stats.rx.rx_frag_err);
|
||||
DP_PRINT_STATS("RX HP out_of_sync: %d", soc->stats.rx.hp_oos);
|
||||
DP_PRINT_STATS("RX DUP DESC: %d",
|
||||
soc->stats.rx.err.hal_reo_dest_dup);
|
||||
DP_PRINT_STATS("RX REL DUP DESC: %d",
|
||||
soc->stats.rx.err.hal_wbm_rel_dup);
|
||||
|
||||
for (i = 0; i < HAL_RXDMA_ERR_MAX; i++) {
|
||||
index += qdf_snprint(&rxdma_error[index],
|
||||
|
@@ -56,6 +56,28 @@ static inline bool dp_rx_check_ap_bridge(struct dp_vdev *vdev)
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* dp_rx_dump_info_and_assert() - dump RX Ring info and Rx Desc info
|
||||
*
|
||||
* @soc: core txrx main context
|
||||
* @hal_ring: opaque pointer to the HAL Rx Ring, which will be serviced
|
||||
* @ring_desc: opaque pointer to the RX ring descriptor
|
||||
* @rx_desc: host rs descriptor
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
void dp_rx_dump_info_and_assert(struct dp_soc *soc, void *hal_ring,
|
||||
void *ring_desc, struct dp_rx_desc *rx_desc)
|
||||
{
|
||||
void *hal_soc = soc->hal_soc;
|
||||
|
||||
dp_rx_desc_dump(rx_desc);
|
||||
hal_srng_dump_ring_desc(hal_soc, hal_ring, ring_desc);
|
||||
hal_srng_dump_ring(hal_soc, hal_ring);
|
||||
qdf_assert_always(rx_desc->in_use);
|
||||
}
|
||||
|
||||
/*
|
||||
* dp_rx_buffers_replenish() - replenish rxdma ring with rx nbufs
|
||||
* called during dp rx initialization
|
||||
@@ -1448,9 +1470,21 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring,
|
||||
rx_buf_cookie = HAL_RX_REO_BUF_COOKIE_GET(ring_desc);
|
||||
|
||||
rx_desc = dp_rx_cookie_2_va_rxdma_buf(soc, rx_buf_cookie);
|
||||
|
||||
|
||||
qdf_assert(rx_desc);
|
||||
|
||||
/*
|
||||
* this is a unlikely scenario where the host is reaping
|
||||
* a descriptor which it already reaped just a while ago
|
||||
* but is yet to replenish it back to HW.
|
||||
* In this case host will dump the last 128 descriptors
|
||||
* including the software descriptor rx_desc and assert.
|
||||
*/
|
||||
if (qdf_unlikely(!rx_desc->in_use)) {
|
||||
DP_STATS_INC(soc, rx.err.hal_reo_dest_dup, 1);
|
||||
dp_rx_dump_info_and_assert(soc, hal_ring,
|
||||
ring_desc, rx_desc);
|
||||
}
|
||||
|
||||
rx_bufs_reaped[rx_desc->pool_id]++;
|
||||
|
||||
/* TODO */
|
||||
|
@@ -846,6 +846,19 @@ static inline QDF_STATUS dp_rx_ast_set_active(struct dp_soc *soc, uint16_t sa_id
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* dp_rx_desc_dump() - dump the sw rx descriptor
|
||||
*
|
||||
* @rx_desc: sw rx descriptor
|
||||
*/
|
||||
static inline void dp_rx_desc_dump(struct dp_rx_desc *rx_desc)
|
||||
{
|
||||
QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL,
|
||||
"rx_desc->nbuf: %pK, rx_desc->cookie: %d, rx_desc->pool_id: %d, rx_desc->in_use: %d, rx_desc->unmapped: %d",
|
||||
rx_desc->nbuf, rx_desc->cookie, rx_desc->pool_id,
|
||||
rx_desc->in_use, rx_desc->unmapped);
|
||||
}
|
||||
|
||||
/*
|
||||
* check_qwrap_multicast_loopback() - Check if rx packet is a loopback packet.
|
||||
* In qwrap mode, packets originated from
|
||||
@@ -962,4 +975,7 @@ int dp_wds_rx_policy_check(uint8_t *rx_tlv_hdr, struct dp_vdev *vdev,
|
||||
qdf_nbuf_t
|
||||
dp_rx_nbuf_prepare(struct dp_soc *soc, struct dp_pdev *pdev);
|
||||
|
||||
void dp_rx_dump_info_and_assert(struct dp_soc *soc, void *hal_ring,
|
||||
void *ring_desc, struct dp_rx_desc *rx_desc);
|
||||
|
||||
#endif /* _DP_RX_H */
|
||||
|
@@ -1253,6 +1253,19 @@ dp_rx_wbm_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota)
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* this is a unlikely scenario where the host is reaping
|
||||
* a descriptor which it already reaped just a while ago
|
||||
* but is yet to replenish it back to HW.
|
||||
* In this case host will dump the last 128 descriptors
|
||||
* including the software descriptor rx_desc and assert.
|
||||
*/
|
||||
if (qdf_unlikely(!rx_desc->in_use)) {
|
||||
DP_STATS_INC(soc, rx.err.hal_wbm_rel_dup, 1);
|
||||
dp_rx_dump_info_and_assert(soc, hal_ring,
|
||||
ring_desc, rx_desc);
|
||||
}
|
||||
|
||||
nbuf = rx_desc->nbuf;
|
||||
qdf_nbuf_unmap_single(soc->osdev, nbuf, QDF_DMA_BIDIRECTIONAL);
|
||||
|
||||
|
@@ -617,6 +617,10 @@ struct dp_soc_stats {
|
||||
uint32_t reo_error[HAL_REO_ERR_MAX];
|
||||
/* HAL REO ERR Count */
|
||||
uint32_t hal_reo_error[MAX_REO_DEST_RINGS];
|
||||
/* HAL REO DEST Duplicate count */
|
||||
uint32_t hal_reo_dest_dup;
|
||||
/* HAL WBM RELEASE Duplicate count */
|
||||
uint32_t hal_wbm_rel_dup;
|
||||
} err;
|
||||
|
||||
/* packet count per core - per ring */
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for
|
||||
* any purpose with or without fee is hereby granted, provided that the
|
||||
@@ -1334,4 +1334,48 @@ static inline void hal_setup_link_idle_list(void *halsoc,
|
||||
num_entries);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* hal_srng_dump_ring_desc() - Dump ring descriptor info
|
||||
*
|
||||
* @hal_soc: Opaque HAL SOC handle
|
||||
* @hal_ring: Source ring pointer
|
||||
* @ring_desc: Opaque ring descriptor handle
|
||||
*/
|
||||
static inline void hal_srng_dump_ring_desc(struct hal_soc *hal, void *hal_ring,
|
||||
void *ring_desc)
|
||||
{
|
||||
struct hal_srng *srng = (struct hal_srng *)hal_ring;
|
||||
|
||||
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_FATAL,
|
||||
ring_desc, (srng->entry_size << 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* hal_srng_dump_ring() - Dump last 128 descs of the ring
|
||||
*
|
||||
* @hal_soc: Opaque HAL SOC handle
|
||||
* @hal_ring: Source ring pointer
|
||||
*/
|
||||
static inline void hal_srng_dump_ring(struct hal_soc *hal, void *hal_ring)
|
||||
{
|
||||
struct hal_srng *srng = (struct hal_srng *)hal_ring;
|
||||
uint32_t *desc;
|
||||
uint32_t tp, i;
|
||||
|
||||
tp = srng->u.dst_ring.tp;
|
||||
|
||||
for (i = 0; i < 128; i++) {
|
||||
if (!tp)
|
||||
tp = srng->ring_size;
|
||||
|
||||
desc = &srng->ring_base_vaddr[tp - srng->entry_size];
|
||||
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_DP,
|
||||
QDF_TRACE_LEVEL_FATAL,
|
||||
desc, (srng->entry_size << 2));
|
||||
|
||||
tp -= srng->entry_size;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _HAL_APIH_ */
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for
|
||||
* any purpose with or without fee is hereby granted, provided that the
|
||||
|
Reference in New Issue
Block a user