diff options
| author | Rajeev Kumar <rajekuma@qca.qualcomm.com> | 2014-03-28 16:53:32 -0700 |
|---|---|---|
| committer | Akash Patel <c_akashp@qca.qualcomm.com> | 2014-03-31 21:49:08 -0700 |
| commit | 71ed7846d47b733bb59e380d0da26d2d354ff603 (patch) | |
| tree | 74061da93504333d41832298cd93f41677d405eb | |
| parent | 9d4d6ac9be1b43d21f60849e772738d969bd1276 (diff) | |
qcacld: Reset SoC after wma_stop before vos_close
Following is theory behind this change:
1) Host driver has provided HTT RX ring buffers to target.
2) Target is doing DMA to these RX ring buffers over PCIe.
3) Driver unload is triggered from user space.
4) During unload wma_stop sends PDEV_SUSPEND command to
target but SoC is not immediately reset after it. SoC
reset is done at the end of driver unload after vos_close.
5) vos_close is called after step 4) and it calls htt_detach.
6) htt_detach is freeing the RX ring buffers which FW is still
holding.
7) Now DMA happens from target to a page in HLOS memory which is
already freed and this leads to HLOS memory corruption.
Change-Id: I7c2dded7bb171891e0ae60608e346d16be0a2b12
CRs-fixed: 640687
| -rw-r--r-- | CORE/SERVICES/HIF/PCIe/if_pci.c | 36 | ||||
| -rw-r--r-- | CORE/SERVICES/HIF/PCIe/if_pci.h | 3 | ||||
| -rw-r--r-- | CORE/VOSS/src/vos_api.c | 9 |
3 files changed, 29 insertions, 19 deletions
diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.c b/CORE/SERVICES/HIF/PCIe/if_pci.c index 35a15a43af38..53239381e722 100644 --- a/CORE/SERVICES/HIF/PCIe/if_pci.c +++ b/CORE/SERVICES/HIF/PCIe/if_pci.c @@ -1442,21 +1442,6 @@ hif_pci_remove(struct pci_dev *pdev) mem = (void __iomem *)sc->mem; -#if defined(CPU_WARM_RESET_WAR) - /* Currently CPU warm reset sequence is tested only for AR9888_REV2 - * Need to enable for AR9888_REV1 once CPU warm reset sequence is - * verified for AR9888_REV1 - */ - if (scn->target_version == AR9888_REV2_VERSION) { - hif_pci_device_warm_reset(sc); - } - else { - hif_pci_device_reset(sc); - } -#else - hif_pci_device_reset(sc); -#endif - pci_disable_msi(pdev); A_FREE(scn); A_FREE(sc->hif_device); @@ -1755,3 +1740,24 @@ void hif_disable_isr(void *ol_sc) /* Cancel the pending tasklet */ tasklet_kill(&hif_sc->intr_tq); } + +void hif_reset_soc(void *ol_sc) +{ + struct ol_softc *scn = (struct ol_softc *)ol_sc; + struct hif_pci_softc *sc = scn->hif_sc; + +#if defined(CPU_WARM_RESET_WAR) + /* Currently CPU warm reset sequence is tested only for AR9888_REV2 + * Need to enable for AR9888_REV1 once CPU warm reset sequence is + * verified for AR9888_REV1 + */ + if (scn->target_version == AR9888_REV2_VERSION) { + hif_pci_device_warm_reset(sc); + } + else { + hif_pci_device_reset(sc); + } +#else + hif_pci_device_reset(sc); +#endif +} diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.h b/CORE/SERVICES/HIF/PCIe/if_pci.h index f66142a35f66..b79bcdeadaf8 100644 --- a/CORE/SERVICES/HIF/PCIe/if_pci.h +++ b/CORE/SERVICES/HIF/PCIe/if_pci.h @@ -114,6 +114,9 @@ adf_os_size_t initBufferCount(adf_os_size_t maxSize); void hif_init_pdev_txrx_handle(void *ol_sc, void *txrx_handle); void hif_disable_isr(void *ol_sc); +/* Function to reset SoC*/ +void hif_reset_soc(void *ol_sc); + void hif_init_adf_ctx(adf_os_device_t adf_dev, void *ol_sc); #ifndef REMOVE_PKT_LOG diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c index 97cddeffc503..38903f05150f 100644 --- a/CORE/VOSS/src/vos_api.c +++ b/CORE/VOSS/src/vos_api.c @@ -1024,6 +1024,11 @@ VOS_STATUS vos_stop( v_CONTEXT_t vosContext ) } #endif +#ifndef QCA_WIFI_ISOC + hif_disable_isr(((VosContextType*)vosContext)->pHIFContext); + hif_reset_soc(((VosContextType*)vosContext)->pHIFContext); +#endif + /* SYS STOP will stop SME and MAC */ vosStatus = sysStop( vosContext); if (!VOS_IS_STATUS_SUCCESS(vosStatus)) @@ -1041,10 +1046,6 @@ VOS_STATUS vos_stop( v_CONTEXT_t vosContext ) VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); } -#ifndef QCA_WIFI_ISOC - hif_disable_isr(((VosContextType*)vosContext)->pHIFContext); -#endif - return VOS_STATUS_SUCCESS; } |
