From 291bf43cfba55f4494c2fc312dae47afe85c1dd3 Mon Sep 17 00:00:00 2001 From: Komal Seelam Date: Wed, 10 Aug 2016 14:46:36 +0530 Subject: 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 --- CORE/SERVICES/HIF/PCIe/if_pci.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) 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); -- cgit v1.2.3