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
This commit is contained in:
Nirav Shah 2019-09-25 00:02:54 +05:30 • committed by nshrivas
commit 942cdf64c5
5 changed files with 62 additions and 20 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);
}
/**

View file

@ -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__);
}