summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKomal Seelam <kseelam@qti.qualcomm.com>2016-08-10 14:46:36 +0530
committerAnjaneedevi Kapparapu <akappa@codeaurora.org>2016-08-11 17:37:23 +0530
commit291bf43cfba55f4494c2fc312dae47afe85c1dd3 (patch)
treee7d3d2e8dcc39467036f84899bd92485e156c4cf
parent37864a495b1c9770eac35bc84be613cd5dfb8514 (diff)
qcacld-2.0: Prevent NOC/Link Access in resume when Link is down
PCIe link training failure will not be indicated to cnss client driver as a link down indication. In System/Runtime PM resume callbacks, client driver will access the target registers results in L2 errors. Fix it by ensuring the PCIe link resume training is completed by reading config space device-id. Change-Id: I8be902330215cf3c8cb0700e6f0da5b69e274c96 CRs-Fixed: 1052965
-rw-r--r--CORE/SERVICES/HIF/PCIe/if_pci.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.c b/CORE/SERVICES/HIF/PCIe/if_pci.c
index 20e2e4835ad2..c792f1ec3d7e 100644
--- a/CORE/SERVICES/HIF/PCIe/if_pci.c
+++ b/CORE/SERVICES/HIF/PCIe/if_pci.c
@@ -2873,6 +2873,39 @@ static int hif_pci_suspend(struct pci_dev *pdev, pm_message_t state)
return ret;
}
+/**
+ * __hif_check_link_status() - API to check if PCIe link is active/not
+ *
+ * @pdev: PCIe device structure
+ *
+ * API reads the PCIe config space to verify if PCIe link training is
+ * successful or not.
+ *
+ * Return: Success/Failure
+ */
+static int __hif_check_link_status(struct pci_dev *pdev)
+{
+ uint16_t dev_id;
+ struct hif_pci_softc *sc = pci_get_drvdata(pdev);
+
+ if (!sc) {
+ pr_err("%s: HIF Bus Context is Invalid\n", __func__);
+ return -EINVAL;
+ }
+
+ pci_read_config_word(sc->pdev, PCI_DEVICE_ID, &dev_id);
+
+ if (dev_id == sc->devid)
+ return 0;
+
+ pr_err("%s: Invalid PCIe Config Space; PCIe link down dev_id:0x%04x\n",
+ __func__, dev_id);
+ sc->recovery = true;
+ vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, TRUE);
+ vos_wlan_pci_link_down();
+ return -EACCES;
+}
+
static int
__hif_pci_resume(struct pci_dev *pdev, bool runtime_pm)
{
@@ -2889,6 +2922,10 @@ __hif_pci_resume(struct pci_dev *pdev, bool runtime_pm)
if (vos_is_logp_in_progress(VOS_MODULE_ID_HIF, NULL))
return err;
+ err = __hif_check_link_status(pdev);
+ if (err)
+ return err;
+
adf_os_atomic_set(&sc->pci_link_suspended, 0);
adf_os_atomic_set(&sc->wow_done, 0);