summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>2014-02-03 11:17:33 +0530
committerPrakash Dhavali <pdhavali@qca.qualcomm.com>2014-02-04 00:02:39 -0800
commit987542b0d7801fdc28bb8dbedbe46740f62267ae (patch)
treece29a4bf9960a3a99c61b11e2fd695d1987371c0
parentd8b27ae6bbc04bae956ec14c31cac678308991aa (diff)
hif/ce: Fix potential infinite loop during Rx
It is possible to run into an infinite loop of CE Rx when doing more Rx completion. Have a threshold count (20) for more completion. Do not do anymore more Rx completion once we hit this threshold value. Change-Id: I35a892f90400f2462035d12ddf87ded4b4ba1d4c CRs-Fixed: 610472
-rw-r--r--CORE/SERVICES/HIF/PCIe/copy_engine.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/CORE/SERVICES/HIF/PCIe/copy_engine.c b/CORE/SERVICES/HIF/PCIe/copy_engine.c
index 243e84824563..78995a7a3cc3 100644
--- a/CORE/SERVICES/HIF/PCIe/copy_engine.c
+++ b/CORE/SERVICES/HIF/PCIe/copy_engine.c
@@ -842,6 +842,17 @@ CE_per_engine_servicereap(struct hif_pci_softc *sc, unsigned int CE_id)
}
#endif /*ATH_11AC_TXCOMPACT*/
+
+/*
+ * Number of times to check for any pending tx/rx completion on
+ * a copy engine, this count should be big enough. Once we hit
+ * this threashold we'll not check for any Tx/Rx comlpetion in same
+ * interrupt handling. Note that this threashold is only used for
+ * Rx interrupt processing, this can be used tor Tx as well if we
+ * suspect any infinite loop in checking for pending Tx completion.
+ */
+#define CE_TXRX_COMP_CHECK_THRESHOLD 20
+
/*
* Guts of interrupt handler for per-engine interrupts on a particular CE.
*
@@ -861,6 +872,7 @@ CE_per_engine_service(struct hif_pci_softc *sc, unsigned int CE_id)
unsigned int id;
unsigned int flags;
u_int32_t CE_int_status;
+ unsigned int more_comp_cnt = 0;
A_TARGET_ACCESS_BEGIN(targid);
@@ -966,7 +978,15 @@ more_watermarks:
* we find no more events to process.
*/
if (CE_state->recv_cb && CE_recv_entries_done_nolock(sc, CE_state)) {
- goto more_completions;
+ if (more_comp_cnt++ < CE_TXRX_COMP_CHECK_THRESHOLD) {
+ goto more_completions;
+ } else {
+ adf_os_print("%s:Potential infinite loop detected during Rx processing"
+ "nentries_mask:0x%x sw read_idx:0x%x hw read_idx:0x%x\n",
+ __func__, CE_state->dest_ring->nentries_mask,
+ CE_state->dest_ring->sw_index,
+ CE_DEST_RING_READ_IDX_GET(targid, CE_state->ctrl_addr));
+ }
}
if (CE_state->send_cb && CE_send_entries_done_nolock(sc, CE_state)) {