summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);