diff options
| author | Zhang Qian <zhangq@codeaurora.org> | 2017-09-14 18:22:25 +0800 |
|---|---|---|
| committer | snandini <snandini@codeaurora.org> | 2017-09-20 03:44:07 -0700 |
| commit | d727ca2e0c254f94b892de5738c5e1b127744b44 (patch) | |
| tree | 27c3efb5abba1d1b5ce34b27017ebd32475a10f4 | |
| parent | 39f5ef3bf21cb021ac50ba4d5fde32515017a001 (diff) | |
qcacld-2.0: Trigger SSR once CE hw_index is wrong
After PCIe resume, host would get invalid hw_index. The invalid
hw_index will introduce infinite loop. SSR will be triggered for
such a case.
Change-Id: I81349098366689b329ae081b849dce8b022ae55c
CRs-Fixed: 2089240
| -rw-r--r-- | CORE/SERVICES/HIF/PCIe/copy_engine.c | 49 | ||||
| -rw-r--r-- | CORE/SERVICES/HIF/PCIe/copy_engine_api.h | 9 | ||||
| -rw-r--r-- | CORE/SERVICES/HIF/PCIe/hif_pci.c | 19 |
3 files changed, 69 insertions, 8 deletions
diff --git a/CORE/SERVICES/HIF/PCIe/copy_engine.c b/CORE/SERVICES/HIF/PCIe/copy_engine.c index e7831136ffff..ebece13f3e05 100644 --- a/CORE/SERVICES/HIF/PCIe/copy_engine.c +++ b/CORE/SERVICES/HIF/PCIe/copy_engine.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014,2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014,2016-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -68,6 +68,48 @@ enum hif_ce_event_type { HIF_TX_DESC_COMPLETION, }; +static struct hif_pci_softc *hif_sc = NULL; +/** + * target_reset_work_handler() - Work queue handler to reset target + * @sc: work queue handle + */ +void target_reset_work_handler(struct work_struct *sc) +{ + if (hif_sc) + vos_device_crashed(hif_sc->dev); +} + +static DECLARE_WORK(target_reset_work, target_reset_work_handler); + +/** + * ce_target_reset() - Trigger SSR + * @sc: hif layer handle + * + * Once hw error is hit, SSR would be triggered. + */ +void ce_target_reset(struct hif_pci_softc *sc) +{ + hif_sc = sc; + adf_os_warn(1); + adf_os_print("Trigger SSR.\n"); + schedule_work(&target_reset_work); +} + +/** + * ce_idx_invalid() - check whether a CE index is valid + * @ring: ring handle + * @idx: CE idx + */ +static bool ce_idx_invalid(struct CE_ring_state *ring, unsigned int idx) +{ + if (ring->nentries <= idx) { + adf_os_print("hw index %d is not correct.\n", idx); + return TRUE; + } else { + return FALSE; + } +} + #ifdef CONFIG_SLUB_DEBUG_ON /** @@ -831,6 +873,9 @@ CE_completed_send_next_nolock(struct CE_state *CE_state, A_TARGET_ACCESS_BEGIN_RET(targid); src_ring->hw_index = CE_SRC_RING_READ_IDX_GET(targid, ctrl_addr); A_TARGET_ACCESS_END_RET(targid); + + if (ce_idx_invalid(src_ring, src_ring->hw_index)) + return status; } read_index = src_ring->hw_index; @@ -1060,7 +1105,7 @@ static inline bool ce_is_valid_entries(struct hif_pci_softc *sc, } else { adf_os_print("%s:Potential infinite loop detected during rx processing for CE%d\n", __func__, ce_state->id); - VOS_BUG(0); + ce_target_reset(sc); status = false; } diff --git a/CORE/SERVICES/HIF/PCIe/copy_engine_api.h b/CORE/SERVICES/HIF/PCIe/copy_engine_api.h index d69641540ab1..e48fd63bc11d 100644 --- a/CORE/SERVICES/HIF/PCIe/copy_engine_api.h +++ b/CORE/SERVICES/HIF/PCIe/copy_engine_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014, 2016-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -376,6 +376,13 @@ bool CE_get_rx_pending(struct hif_pci_softc *sc); int get_next_record_index(atomic_t *table_index, int array_size); +/** + * ce_target_reset() - Trigger SSR + * @sc: hif layer handle + * + * Once hw error is hit, SSR would be triggered. + */ +void ce_target_reset(struct hif_pci_softc *sc); /* CE_attr.flags values */ #define CE_ATTR_NO_SNOOP 0x01 /* Use NonSnooping PCIe accesses? */ diff --git a/CORE/SERVICES/HIF/PCIe/hif_pci.c b/CORE/SERVICES/HIF/PCIe/hif_pci.c index 3f1bee7ab62d..bfcb639e94ed 100644 --- a/CORE/SERVICES/HIF/PCIe/hif_pci.c +++ b/CORE/SERVICES/HIF/PCIe/hif_pci.c @@ -467,7 +467,7 @@ HIF_PCI_CE_send_done(struct CE_handle *copyeng, void *ce_context, void *transfer "pipe_num:%d num_send_allowed:%d pipe_info:0x%p sw_index:%d hw_index:%d nbytes:%d\n", pipe_info->pipe_num, pipe_info->num_sends_allowed, pipe_info, sw_idx, hw_idx, nbytes)); - ASSERT(0); + ce_target_reset(hif_state->sc); break; } pipe_info->completion_freeq_head = compl_state->next; @@ -538,7 +538,10 @@ HIF_PCI_CE_recv_data(struct CE_handle *copyeng, void *ce_context, void *transfer hif_pm_runtime_mark_last_busy(sc->dev); adf_os_spin_lock(&pipe_info->completion_freeq_lock); compl_state = pipe_info->completion_freeq_head; - ASSERT(compl_state != NULL); + + if (!compl_state) + ce_target_reset(sc); + pipe_info->completion_freeq_head = compl_state->next; adf_os_spin_unlock(&pipe_info->completion_freeq_lock); @@ -2862,9 +2865,15 @@ HIFTargetSleepStateAdjust(A_target_id_t targid, hif_msm_pcie_debug_info(sc); if (!sc->ol_sc->enable_self_recovery) VOS_BUG(0); - sc->recovery = true; - vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, TRUE); - vos_wlan_pci_link_down(); + + if (!vos_is_logp_in_progress(VOS_MODULE_ID_VOSS, NULL)) { + sc->recovery = true; + vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, TRUE); + vos_wlan_pci_link_down(); + } else { + adf_os_print("%s- %d: SSR is in progress!!!!\n", + __func__, __LINE__); + } return -EACCES; } |
