diff options
| author | Rajeev Kumar <rajekuma@qca.qualcomm.com> | 2014-05-16 14:53:37 -0700 |
|---|---|---|
| committer | Pitani Venkata Rajesh Kumar <c_vpitan@qti.qualcomm.com> | 2014-05-20 19:38:24 +0530 |
| commit | fa27ecc4f447b70797f6f079bcdbb0e4d9502715 (patch) | |
| tree | 8afc2db8de7cb2f0b499227f1d9fd563327eca45 | |
| parent | d5c7613fcfa9faa60e49e235583a316d110861ed (diff) | |
qcacld: Fix of race condition leading to L2 errors
Fix of race condition between hif_pci_suspend and register
read from wlan_tasklet and sleep timer when PCIe link is
suspended and tis in D3 state.
Change-Id: I40037327a83e611865bb5d59ad7041200da30c77
CRs-Fixed: 665695
| -rw-r--r-- | CORE/SERVICES/HIF/PCIe/hif_pci.c | 6 | ||||
| -rw-r--r-- | CORE/SERVICES/HIF/PCIe/if_pci.c | 15 | ||||
| -rw-r--r-- | CORE/SERVICES/HIF/PCIe/if_pci.h | 1 |
3 files changed, 16 insertions, 6 deletions
diff --git a/CORE/SERVICES/HIF/PCIe/hif_pci.c b/CORE/SERVICES/HIF/PCIe/hif_pci.c index e4e739c54f3c..cf2e7f572e9a 100644 --- a/CORE/SERVICES/HIF/PCIe/hif_pci.c +++ b/CORE/SERVICES/HIF/PCIe/hif_pci.c @@ -2008,9 +2008,11 @@ HIF_sleep_entry(void *arg) idle_ms = adf_os_ticks_to_msecs(adf_os_ticks() - hif_state->sleep_ticks); if (idle_ms >= HIF_MIN_SLEEP_INACTIVITY_TIME_MS) { - A_PCI_WRITE32(pci_addr + PCIE_LOCAL_BASE_ADDRESS + + if (!adf_os_atomic_read(&sc->pci_link_suspended)) { + A_PCI_WRITE32(pci_addr + PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_RESET); - hif_state->fake_sleep = FALSE; + hif_state->fake_sleep = FALSE; + } } else { adf_os_timer_start(&hif_state->sleep_timer, HIF_SLEEP_INACTIVITY_TIMER_PERIOD_MS); diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.c b/CORE/SERVICES/HIF/PCIe/if_pci.c index 1d233a383994..747ed9bd3f61 100644 --- a/CORE/SERVICES/HIF/PCIe/if_pci.c +++ b/CORE/SERVICES/HIF/PCIe/if_pci.c @@ -613,7 +613,8 @@ wlan_tasklet(unsigned long data) } irq_handled: if (LEGACY_INTERRUPTS(sc) && (sc->ol_sc->target_status != - OL_TRGET_STATUS_RESET)) { + OL_TRGET_STATUS_RESET) && + (!adf_os_atomic_read(&sc->pci_link_suspended))) { if (sc->hif_init_done == TRUE) A_TARGET_ACCESS_BEGIN(hif_state->targid); @@ -882,6 +883,7 @@ again: adf_os_atomic_init(&sc->tasklet_from_intr); adf_os_atomic_init(&sc->wow_done); adf_os_atomic_init(&sc->ce_suspend); + adf_os_atomic_init(&sc->pci_link_suspended); init_waitqueue_head(&ol_sc->sc_osdev->event_queue); init_completion(&ol_sc->ramdump_event); @@ -1201,6 +1203,7 @@ again: adf_os_atomic_init(&sc->tasklet_from_intr); adf_os_atomic_init(&sc->wow_done); adf_os_atomic_init(&sc->ce_suspend); + adf_os_atomic_init(&sc->pci_link_suspended); init_waitqueue_head(&ol_sc->sc_osdev->event_queue); init_completion(&ol_sc->ramdump_event); @@ -1713,9 +1716,6 @@ hif_pci_suspend(struct pci_dev *pdev, pm_message_t state) msleep(10); } - /* Stop the HIF Sleep Timer */ - HIFCancelDeferredTargetSleep(sc->hif_device); - /*Disable PCIe interrupts*/ A_TARGET_ACCESS_BEGIN_RET(targid); A_PCI_WRITE32(sc->mem+(SOC_CORE_BASE_ADDRESS | PCIE_INTR_ENABLE_ADDRESS), 0); @@ -1727,6 +1727,11 @@ hif_pci_suspend(struct pci_dev *pdev, pm_message_t state) } A_TARGET_ACCESS_END_RET(targid); + /* Stop the HIF Sleep Timer */ + HIFCancelDeferredTargetSleep(sc->hif_device); + + adf_os_atomic_set(&sc->pci_link_suspended, 1); + pci_read_config_dword(pdev, OL_ATH_PCI_PM_CONTROL, &val); if ((val & 0x000000ff) != 0x3) { pci_save_state(pdev); @@ -1751,6 +1756,8 @@ hif_pci_resume(struct pci_dev *pdev) v_VOID_t * temp_module; u32 tmp; + adf_os_atomic_set(&sc->pci_link_suspended, 0); + /* Enable Legacy PCI line interrupts */ A_TARGET_ACCESS_BEGIN_RET(targid); A_PCI_WRITE32(sc->mem+(SOC_CORE_BASE_ADDRESS | PCIE_INTR_ENABLE_ADDRESS), diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.h b/CORE/SERVICES/HIF/PCIe/if_pci.h index 8114bc8b019b..a11ef830bea3 100644 --- a/CORE/SERVICES/HIF/PCIe/if_pci.h +++ b/CORE/SERVICES/HIF/PCIe/if_pci.h @@ -86,6 +86,7 @@ struct hif_pci_softc { atomic_t tasklet_from_intr; atomic_t wow_done; atomic_t ce_suspend; + atomic_t pci_link_suspended; bool hif_init_done; bool recovery; int htc_endpoint; |
