wil6210: work around for platforms with broken INTx
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / ath / wil6210 / pcie_bus.c
index 05c1c9d6f9c229b9f47a995377d4fbe3418c1032..77b6272d93fb24c11e9d703549e03929f623c6ca 100644 (file)
@@ -35,6 +35,13 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil)
 {
        struct pci_dev *pdev = wil->pdev;
        int rc;
+       /* on platforms with buggy ACPI, pdev->msi_enabled may be set to
+        * allow pci_enable_device to work. This indicates INTx was not routed
+        * and only MSI should be used
+        */
+       int msi_only = pdev->msi_enabled;
+
+       pdev->msi_enabled = 0;
 
        pci_set_master(pdev);
 
@@ -66,6 +73,12 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil)
 
        wil->n_msi = use_msi;
 
+       if ((wil->n_msi == 0) && msi_only) {
+               wil_err(wil, "Interrupt pin not routed, unable to use INTx\n");
+               rc = -ENODEV;
+               goto stop_master;
+       }
+
        rc = wil6210_init_irq(wil, pdev->irq);
        if (rc)
                goto stop_master;
@@ -124,9 +137,16 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        rc = pci_enable_device(pdev);
        if (rc) {
-               dev_err(&pdev->dev, "pci_enable_device failed\n");
-               return -ENODEV;
+               dev_err(&pdev->dev,
+                       "pci_enable_device failed, retry with MSI only\n");
+               /* Work around for platforms that can't allocate IRQ:
+                * retry with MSI only
+                */
+               pdev->msi_enabled = 1;
+               rc = pci_enable_device(pdev);
        }
+       if (rc)
+               return -ENODEV;
        /* rollback to err_disable_pdev */
 
        rc = pci_request_region(pdev, 0, WIL_NAME);