wcnss: Invoke PIL only after completing intialization
Delay PIL operation until all data structures used by WCNSS SMD
interrupt handler are initialized. There could be a race condition
where the SMD interrupt handler is called even before the WCNSS
trigger function is completed.
Change-Id: I6d83e7a67ebb3e7b6efe2b3fbfc2708cca355916
CRs-Fixed: 496402
Signed-off-by: Sameer Thalappil <sameert@codeaurora.org>
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index e8b8fc2..f5b666f 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -675,7 +675,7 @@
static int __devinit
wcnss_wlan_ctrl_probe(struct platform_device *pdev)
{
- if (!penv)
+ if (!penv || !penv->triggered)
return -ENODEV;
penv->smd_channel_ready = 1;
@@ -730,7 +730,7 @@
{
int ret = 0;
- if (!penv)
+ if (!penv || !penv->triggered)
return -ENODEV;
ret = smd_named_open_on_edge(WCNSS_CTRL_CHANNEL, SMD_APPS_WCNSS,
@@ -1573,15 +1573,6 @@
goto fail_power;
}
- /* trigger initialization of the WCNSS */
- penv->pil = subsystem_get(WCNSS_PIL_DEVICE);
- if (IS_ERR(penv->pil)) {
- dev_err(&pdev->dev, "Peripheral Loader failed on WCNSS.\n");
- ret = PTR_ERR(penv->pil);
- penv->pil = NULL;
- goto fail_pil;
- }
-
/* allocate resources */
penv->mmio_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"wcnss_mmio");
@@ -1613,7 +1604,7 @@
if (!penv->msm_wcnss_base) {
ret = -ENOMEM;
pr_err("%s: ioremap wcnss physical failed\n", __func__);
- goto fail_wake;
+ goto fail_ioremap;
}
if (wcnss_hardware_type() == WCNSS_RIVA_HW) {
@@ -1621,20 +1612,20 @@
if (!penv->riva_ccu_base) {
ret = -ENOMEM;
pr_err("%s: ioremap wcnss physical failed\n", __func__);
- goto fail_ioremap;
+ goto fail_ioremap2;
}
} else {
penv->pronto_a2xb_base = ioremap(MSM_PRONTO_A2XB_BASE, SZ_512);
if (!penv->pronto_a2xb_base) {
ret = -ENOMEM;
pr_err("%s: ioremap wcnss physical failed\n", __func__);
- goto fail_ioremap;
+ goto fail_ioremap2;
}
penv->pronto_ccpu_base = ioremap(MSM_PRONTO_CCPU_BASE, SZ_512);
if (!penv->pronto_ccpu_base) {
ret = -ENOMEM;
pr_err("%s: ioremap wcnss physical failed\n", __func__);
- goto fail_ioremap2;
+ goto fail_ioremap3;
}
/* for reset FIQ */
res = platform_get_resource_byname(penv->pdev,
@@ -1642,31 +1633,45 @@
if (!res) {
dev_err(&pdev->dev, "insufficient irq mem resources\n");
ret = -ENOENT;
- goto fail_ioremap3;
+ goto fail_ioremap4;
}
penv->fiq_reg = ioremap_nocache(res->start, resource_size(res));
if (!penv->fiq_reg) {
pr_err("wcnss: %s: ioremap_nocache() failed fiq_reg addr:%pr\n",
__func__, &res->start);
ret = -ENOMEM;
- goto fail_ioremap3;
+ goto fail_ioremap4;
}
}
+ /* trigger initialization of the WCNSS */
+ penv->pil = subsystem_get(WCNSS_PIL_DEVICE);
+ if (IS_ERR(penv->pil)) {
+ dev_err(&pdev->dev, "Peripheral Loader failed on WCNSS.\n");
+ ret = PTR_ERR(penv->pil);
+ penv->pil = NULL;
+ goto fail_pil;
+ }
+
return 0;
+fail_pil:
+ if (penv->riva_ccu_base)
+ iounmap(penv->riva_ccu_base);
+ if (penv->fiq_reg)
+ iounmap(penv->fiq_reg);
+fail_ioremap4:
+ if (penv->pronto_ccpu_base)
+ iounmap(penv->pronto_ccpu_base);
fail_ioremap3:
- iounmap(penv->pronto_ccpu_base);
+ if (penv->pronto_a2xb_base)
+ iounmap(penv->pronto_a2xb_base);
fail_ioremap2:
- iounmap(penv->pronto_a2xb_base);
+ if (penv->msm_wcnss_base)
+ iounmap(penv->msm_wcnss_base);
fail_ioremap:
- iounmap(penv->msm_wcnss_base);
-fail_wake:
wake_lock_destroy(&penv->wcnss_wake_lock);
fail_res:
- if (penv->pil)
- subsystem_put(penv->pil);
-fail_pil:
wcnss_wlan_power(&pdev->dev, &penv->wlan_config,
WCNSS_WLAN_SWITCH_OFF);
fail_power: