Browse Source

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
Nirav Shah 5 years ago
parent
commit
942cdf64c5

+ 0 - 14
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

+ 15 - 1
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

+ 15 - 2
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

+ 15 - 1
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);
 }
 
 /**

+ 17 - 2
core/pld/src/pld_usb.c

@@ -25,6 +25,8 @@
 #include <linux/platform_device.h>
 #include <linux/err.h>
 #include <linux/list.h>
+#include "osif_psoc_sync.h"
+
 #ifdef CONFIG_PLD_USB_CNSS
 #include <net/cnss2.h>
 #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__);
 }