From 942cdf64c5a356312e4b1212f34847ae060979a5 Mon Sep 17 00:00:00 2001 From: Nirav Shah Date: Wed, 25 Sep 2019 00:02:54 +0530 Subject: [PATCH] qcacld-3.0: Protect pld_del_dev function as part of psoc trans Protect pld_del_dev function as part of psoc transaction to avoid race condition with pld_deinit. Change-Id: I3180801308b9a5e85822fb8d8bc04a9ecb42b347 CRs-Fixed: 2530822 --- core/hdd/src/wlan_hdd_driver_ops.c | 14 -------------- core/pld/src/pld_pcie.c | 16 +++++++++++++++- core/pld/src/pld_sdio.c | 17 +++++++++++++++-- core/pld/src/pld_snoc.c | 16 +++++++++++++++- core/pld/src/pld_usb.c | 19 +++++++++++++++++-- 5 files changed, 62 insertions(+), 20 deletions(-) diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index 3d023912c1fe..513052967d0b 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -673,21 +673,7 @@ static void __hdd_soc_remove(struct device *dev) */ static void hdd_soc_remove(struct device *dev) { - struct osif_psoc_sync *psoc_sync; - int errno; - - /* by design, this will fail to lookup if we never probed the SoC */ - errno = osif_psoc_sync_trans_start_wait(dev, &psoc_sync); - if (errno) - return; - - osif_psoc_sync_unregister(dev); - osif_psoc_sync_wait_for_ops(psoc_sync); - __hdd_soc_remove(dev); - - osif_psoc_sync_trans_stop(psoc_sync); - osif_psoc_sync_destroy(psoc_sync); } #ifdef FEATURE_WLAN_DIAG_SUPPORT diff --git a/core/pld/src/pld_pcie.c b/core/pld/src/pld_pcie.c index 52e4e45b1c5d..c6b272c52ca3 100644 --- a/core/pld/src/pld_pcie.c +++ b/core/pld/src/pld_pcie.c @@ -28,6 +28,7 @@ #include "pld_internal.h" #include "pld_pcie.h" +#include "osif_psoc_sync.h" #ifdef CONFIG_PCI @@ -82,15 +83,28 @@ out: static void pld_pcie_remove(struct pci_dev *pdev) { struct pld_context *pld_context; + int errno; + struct osif_psoc_sync *psoc_sync; + + errno = osif_psoc_sync_trans_start_wait(&pdev->dev, &psoc_sync); + if (errno) + return; + + osif_psoc_sync_unregister(&pdev->dev); + osif_psoc_sync_wait_for_ops(psoc_sync); pld_context = pld_get_global_context(); if (!pld_context) - return; + goto out; pld_context->ops->remove(&pdev->dev, PLD_BUS_TYPE_PCIE); pld_del_dev(pld_context, &pdev->dev); + +out: + osif_psoc_sync_trans_stop(psoc_sync); + osif_psoc_sync_destroy(psoc_sync); } #ifdef CONFIG_PLD_PCIE_CNSS diff --git a/core/pld/src/pld_sdio.c b/core/pld/src/pld_sdio.c index a95a3c5683b6..49b5e569455a 100644 --- a/core/pld/src/pld_sdio.c +++ b/core/pld/src/pld_sdio.c @@ -32,7 +32,7 @@ #include "pld_common.h" #include "pld_internal.h" #include "pld_sdio.h" - +#include "osif_psoc_sync.h" #ifdef CONFIG_SDIO /* SDIO manufacturer ID and Codes */ @@ -112,14 +112,27 @@ static void pld_sdio_remove(struct sdio_func *sdio_func) { struct pld_context *pld_context; struct device *dev = &sdio_func->dev; + int errno; + struct osif_psoc_sync *psoc_sync; + + errno = osif_psoc_sync_trans_start_wait(dev, &psoc_sync); + if (errno) + return; + + osif_psoc_sync_unregister(dev); + osif_psoc_sync_wait_for_ops(psoc_sync); pld_context = pld_get_global_context(); if (!pld_context) - return; + goto out; pld_context->ops->remove(dev, PLD_BUS_TYPE_SDIO); pld_del_dev(pld_context, dev); + +out: + osif_psoc_sync_trans_stop(psoc_sync); + osif_psoc_sync_destroy(psoc_sync); } #ifdef CONFIG_PLD_SDIO_CNSS diff --git a/core/pld/src/pld_snoc.c b/core/pld/src/pld_snoc.c index 775d235cfee0..df9b160eee19 100644 --- a/core/pld/src/pld_snoc.c +++ b/core/pld/src/pld_snoc.c @@ -27,6 +27,7 @@ #include "pld_internal.h" #include "pld_snoc.h" +#include "osif_psoc_sync.h" #ifdef CONFIG_PLD_SNOC_ICNSS /** @@ -72,15 +73,28 @@ out: static void pld_snoc_remove(struct device *dev) { struct pld_context *pld_context; + int errno; + struct osif_psoc_sync *psoc_sync; + + errno = osif_psoc_sync_trans_start_wait(dev, &psoc_sync); + if (errno) + return; + + osif_psoc_sync_unregister(dev); + osif_psoc_sync_wait_for_ops(psoc_sync); pld_context = pld_get_global_context(); if (!pld_context) - return; + goto out; pld_context->ops->remove(dev, PLD_BUS_TYPE_SNOC); pld_del_dev(pld_context, dev); + +out: + osif_psoc_sync_trans_stop(psoc_sync); + osif_psoc_sync_destroy(psoc_sync); } /** diff --git a/core/pld/src/pld_usb.c b/core/pld/src/pld_usb.c index fbb870fe0dcc..2f91f9c5cd99 100644 --- a/core/pld/src/pld_usb.c +++ b/core/pld/src/pld_usb.c @@ -25,6 +25,8 @@ #include #include #include +#include "osif_psoc_sync.h" + #ifdef CONFIG_PLD_USB_CNSS #include #endif @@ -87,15 +89,24 @@ static void pld_usb_remove(struct usb_interface *interface) { struct usb_device *pdev = interface_to_usbdev(interface); struct pld_context *pld_context; + int errno; + struct osif_psoc_sync *psoc_sync; + + errno = osif_psoc_sync_trans_start_wait(&pdev->dev, &psoc_sync); + if (errno) + return; + + osif_psoc_sync_unregister(&pdev->dev); + osif_psoc_sync_wait_for_ops(psoc_sync); pld_context = pld_get_global_context(); if (!pld_context) - return; + goto out; if (atomic_read(&pld_usb_reg_done) != true) { pr_info("%s: already de-registered!\n", __func__); - return; + goto out; } pld_context->ops->remove(&pdev->dev, PLD_BUS_TYPE_USB); @@ -103,6 +114,10 @@ static void pld_usb_remove(struct usb_interface *interface) pld_del_dev(pld_context, &pdev->dev); atomic_set(&pld_usb_reg_done, false); +out: + osif_psoc_sync_trans_stop(psoc_sync); + osif_psoc_sync_destroy(psoc_sync); + pr_info("%s: done!\n", __func__); }