diff options
| author | Govind Singh <govinds@qti.qualcomm.com> | 2016-07-12 12:03:53 +0530 |
|---|---|---|
| committer | Anjaneedevi Kapparapu <akappa@codeaurora.org> | 2016-07-18 11:52:53 +0530 |
| commit | 87bcbd647a93fed14bc843bb79c28c8e1e619f0a (patch) | |
| tree | 918f2a68aef22b934bc0f70524b9be8bc4d6659e | |
| parent | 1d292d761555c35a89586bf8d3adc8bdb6589ade (diff) | |
qcacld-2.0: fix corruption of irq history buffer index
There is a race condition between irq history type
HIF_SUSPEND_AFTER_WOW and HIF_IRQ, this is corrupting
the irq history buffer index.
Fix the race condition by using atomic index counter.
Change-Id: I61e42d28a9eb242e13cc73cdab8efb52e1574cb6
CRs-Fixed: 1039967
| -rw-r--r-- | CORE/SERVICES/HIF/PCIe/copy_engine.c | 2 | ||||
| -rw-r--r-- | CORE/SERVICES/HIF/PCIe/copy_engine_api.h | 5 | ||||
| -rw-r--r-- | CORE/SERVICES/HIF/PCIe/if_pci.c | 23 |
3 files changed, 16 insertions, 14 deletions
diff --git a/CORE/SERVICES/HIF/PCIe/copy_engine.c b/CORE/SERVICES/HIF/PCIe/copy_engine.c index 1ec4cae236f6..9619e93d07f3 100644 --- a/CORE/SERVICES/HIF/PCIe/copy_engine.c +++ b/CORE/SERVICES/HIF/PCIe/copy_engine.c @@ -104,7 +104,7 @@ static void CE_init_ce_desc_event_log(int ce_id, int size); * trying to access the array, full locking of the recording process would * be needed to have sane logging. */ -static int get_next_record_index(adf_os_atomic_t *table_index, int array_size) +int get_next_record_index(adf_os_atomic_t *table_index, int array_size) { int record_index = adf_os_atomic_inc_return(table_index); if (record_index == array_size) diff --git a/CORE/SERVICES/HIF/PCIe/copy_engine_api.h b/CORE/SERVICES/HIF/PCIe/copy_engine_api.h index 7e03a5f28574..d69641540ab1 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 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014, 2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -374,6 +374,9 @@ void CE_enable_any_copy_compl_intr_nolock(struct hif_pci_softc *sc); /* API to check if any of the copy engine pipes has pending frames for prcoessing */ bool CE_get_rx_pending(struct hif_pci_softc *sc); +int get_next_record_index(atomic_t *table_index, int array_size); + + /* CE_attr.flags values */ #define CE_ATTR_NO_SNOOP 0x01 /* Use NonSnooping PCIe accesses? */ #define CE_ATTR_BYTE_SWAP_DATA 0x02 /* Byte swap data words */ diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.c b/CORE/SERVICES/HIF/PCIe/if_pci.c index af339871abad..0e8edec7b286 100644 --- a/CORE/SERVICES/HIF/PCIe/if_pci.c +++ b/CORE/SERVICES/HIF/PCIe/if_pci.c @@ -154,7 +154,7 @@ typedef struct { } hif_irq_history; #define HIF_IRQ_HISTORY_MAX 1024 -A_UINT32 g_hif_irq_history_idx = 0; +adf_os_atomic_t g_hif_irq_history_idx = 0; hif_irq_history hif_irq_history_buffer[HIF_IRQ_HISTORY_MAX]; void hif_irq_record(hif_irq_type type, struct hif_pci_softc *sc) @@ -162,36 +162,35 @@ void hif_irq_record(hif_irq_type type, struct hif_pci_softc *sc) struct HIF_CE_state *hif_state = (struct HIF_CE_state *)sc->hif_device; A_target_id_t targid = hif_state->targid; - if (HIF_IRQ_HISTORY_MAX <= g_hif_irq_history_idx) - g_hif_irq_history_idx = 0; + int record_index = get_next_record_index( + &g_hif_irq_history_idx, HIF_IRQ_HISTORY_MAX); if (HIFTargetSleepStateAdjust(hif_state->targid, FALSE, TRUE) < 0) { - adf_os_mem_zero(&hif_irq_history_buffer[g_hif_irq_history_idx], + adf_os_mem_zero(&hif_irq_history_buffer[record_index], sizeof(hif_irq_history)); goto out; } - hif_irq_history_buffer[g_hif_irq_history_idx].irq_summary = + hif_irq_history_buffer[record_index].irq_summary = CE_INTERRUPT_SUMMARY(targid); - hif_irq_history_buffer[g_hif_irq_history_idx].fw_indicator = + hif_irq_history_buffer[record_index].fw_indicator = A_TARGET_READ(targid, hif_state->fw_indicator_address); - hif_irq_history_buffer[g_hif_irq_history_idx].irq_enable = + hif_irq_history_buffer[record_index].irq_enable = A_PCI_READ32(sc->mem + SOC_CORE_BASE_ADDRESS + PCIE_INTR_ENABLE_ADDRESS); - hif_irq_history_buffer[g_hif_irq_history_idx].irq_cause = + hif_irq_history_buffer[record_index].irq_cause = A_PCI_READ32(sc->mem + SOC_CORE_BASE_ADDRESS + PCIE_INTR_CAUSE_ADDRESS); - hif_irq_history_buffer[g_hif_irq_history_idx].irq_clear = + hif_irq_history_buffer[record_index].irq_clear = A_PCI_READ32(sc->mem + SOC_CORE_BASE_ADDRESS + PCIE_INTR_CLR_ADDRESS); HIFTargetSleepStateAdjust(hif_state->targid, TRUE, FALSE); out: - hif_irq_history_buffer[g_hif_irq_history_idx].type = type; - hif_irq_history_buffer[g_hif_irq_history_idx].time = adf_get_boottime(); + hif_irq_history_buffer[record_index].type = type; + hif_irq_history_buffer[record_index].time = adf_get_boottime(); - g_hif_irq_history_idx++; } #else void hif_irq_record(hif_irq_type type, struct hif_pci_softc *sc) {}; |
