From adb5a919a12ff4c6fb5fe43a8c613bd0ceca1934 Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Wed, 23 Nov 2016 10:02:56 +0530 Subject: qcacld-2.0: Do not process the packets if hw read_idx is invalid When SSR is injected on PCIE using iwpriv wlan0 crash_inject 7 0, fw brings down the PCIE link. PCIE root complex detects link down and notifies the link_down ops to the cnss platform driver. Platform driver link down ops disables the interrupts and then schedules the recovery. If rx data path is active, current running tasklet relies on HW index to calculate the ring delta. As hw index is 0xFFFFFFFF due to linkdown and host identifies this condition as infinity loop due to recursive tasklet design for interrupt mitigation and asserts. To fix the problem do not process the packets recursively if hw read_idx is invalid. Change-Id: Ieb170edb3ea6741b158db4aa9fd61b2ed0070fc7 CRs-Fixed: 1089360 --- CORE/SERVICES/HIF/PCIe/copy_engine.c | 11 +++++++++-- CORE/SERVICES/HIF/PCIe/copy_engine_internal.h | 3 ++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CORE/SERVICES/HIF/PCIe/copy_engine.c b/CORE/SERVICES/HIF/PCIe/copy_engine.c index 9619e93d07f3..e7831136ffff 100644 --- a/CORE/SERVICES/HIF/PCIe/copy_engine.c +++ b/CORE/SERVICES/HIF/PCIe/copy_engine.c @@ -1043,20 +1043,27 @@ static inline bool ce_is_valid_entries(struct hif_pci_softc *sc, { bool status; A_target_id_t targid = TARGID(sc); + unsigned int hw_index = + CE_DEST_RING_READ_IDX_GET(targid, ce_state->ctrl_addr); /* check if difference between hw index and read index is with in * nentries_mask limit. */ - if (ring_delta < ce_state->dest_ring->nentries_mask) { + if ((ring_delta < ce_state->dest_ring->nentries_mask) && + (hw_index != CE_HW_INDEX_LINK_DOWN)) { adf_os_print("%s: spent more time during rx proceesing for CE%d, allow other CE to process Rx packet.\n", __func__, ce_state->id); status = true; + } else if (hw_index == CE_HW_INDEX_LINK_DOWN) { + status = false; + adf_os_print("%s: hw index is invalid due to link down \n", __func__); } else { adf_os_print("%s:Potential infinite loop detected during rx processing for CE%d\n", - __func__, ce_state->id); + __func__, ce_state->id); VOS_BUG(0); status = false; } + adf_os_print("nentries_mask:0x%x sw read_idx:0x%x hw read_idx:0x%x ring_delta:0x%x\n", ce_state->dest_ring->nentries_mask, ce_state->dest_ring->sw_index, diff --git a/CORE/SERVICES/HIF/PCIe/copy_engine_internal.h b/CORE/SERVICES/HIF/PCIe/copy_engine_internal.h index 65d505e43210..08db7ca11f6e 100644 --- a/CORE/SERVICES/HIF/PCIe/copy_engine_internal.h +++ b/CORE/SERVICES/HIF/PCIe/copy_engine_internal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2013, 2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -216,6 +216,7 @@ struct CE_sendlist_s { #define CDC_WAR_MAGIC_STR 0xceef0000 #define CDC_WAR_DATA_CE 4 +#define CE_HW_INDEX_LINK_DOWN 0xFFFFFFFF /* Additional internal-only CE_send flags */ #define CE_SEND_FLAG_GATHER 0x00010000 /* Use Gather */ -- cgit v1.2.3