summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGovind Singh <govinds@qti.qualcomm.com>2016-07-12 12:03:53 +0530
committerAnjaneedevi Kapparapu <akappa@codeaurora.org>2016-07-18 11:52:53 +0530
commit87bcbd647a93fed14bc843bb79c28c8e1e619f0a (patch)
tree918f2a68aef22b934bc0f70524b9be8bc4d6659e
parent1d292d761555c35a89586bf8d3adc8bdb6589ade (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.c2
-rw-r--r--CORE/SERVICES/HIF/PCIe/copy_engine_api.h5
-rw-r--r--CORE/SERVICES/HIF/PCIe/if_pci.c23
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) {};