diff options
| author | Houston Hoffman <hhoffman@qca.qualcomm.com> | 2015-08-13 13:44:28 -0700 |
|---|---|---|
| committer | Akash Patel <akashp@codeaurora.org> | 2015-08-14 17:20:23 -0700 |
| commit | fa3f17ead99d23e953da134fe3cc630062abbc30 (patch) | |
| tree | ade27f7d5ffb7c6992262143524b84f56b5fe87c | |
| parent | e4a734388b6239e50d8b09f9111def4cbcc460b6 (diff) | |
qcacld-2.0: protect hif_state in wlan_tasklet
If hif init is not done the suspend lock isn't guaranteed to be valid.
Change-Id: I330968e11f5e82a06ca7c35c7704fb71c5775fc7
CRs-Fixed: 890229
| -rw-r--r-- | CORE/SERVICES/HIF/PCIe/if_pci.c | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.c b/CORE/SERVICES/HIF/PCIe/if_pci.c index f6f3b701164d..4b95803c2fbb 100644 --- a/CORE/SERVICES/HIF/PCIe/if_pci.c +++ b/CORE/SERVICES/HIF/PCIe/if_pci.c @@ -695,8 +695,9 @@ wlan_tasklet(unsigned long data) struct hif_pci_softc *sc = (struct hif_pci_softc *) data; struct HIF_CE_state *hif_state = (struct HIF_CE_state *)sc->hif_device; volatile int tmp; + bool hif_init_done = sc->hif_init_done; - if (sc->hif_init_done == FALSE) { + if (hif_init_done == FALSE) { goto irq_handled; } @@ -726,12 +727,18 @@ wlan_tasklet(unsigned long data) return; } irq_handled: - adf_os_spin_lock_irqsave(&hif_state->suspend_lock); + /* use cached value for hif_init_done to prevent + * unlocking an unlocked spinlock if hif init finishes + * while this tasklet is running + */ + if (hif_init_done == TRUE) + adf_os_spin_lock_irqsave(&hif_state->suspend_lock); + if (LEGACY_INTERRUPTS(sc) && (sc->ol_sc->target_status != OL_TRGET_STATUS_RESET) && (!adf_os_atomic_read(&sc->pci_link_suspended))) { - if (sc->hif_init_done == TRUE) { + if (hif_init_done == TRUE) { if(HIFTargetSleepStateAdjust(hif_state->targid, FALSE, TRUE) < 0) { adf_os_spin_unlock_irqrestore(&hif_state->suspend_lock); return; @@ -744,14 +751,17 @@ irq_handled: /* IMPORTANT: this extra read transaction is required to flush the posted write buffer */ tmp = A_PCI_READ32(sc->mem+(SOC_CORE_BASE_ADDRESS | PCIE_INTR_ENABLE_ADDRESS)); - if (sc->hif_init_done == TRUE) { + if (hif_init_done == TRUE) { if(HIFTargetSleepStateAdjust(hif_state->targid, TRUE, FALSE) < 0) { adf_os_spin_unlock_irqrestore(&hif_state->suspend_lock); return; } } } - adf_os_spin_unlock_irqrestore(&hif_state->suspend_lock); + + if (hif_init_done == TRUE) + adf_os_spin_unlock_irqrestore(&hif_state->suspend_lock); + adf_os_atomic_set(&sc->ce_suspend, 1); } |
