diff options
Diffstat (limited to 'drivers/net/wireless/ath/wil6210/pcie_bus.c')
-rw-r--r-- | drivers/net/wireless/ath/wil6210/pcie_bus.c | 53 |
1 files changed, 47 insertions, 6 deletions
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index 1e2e07b9d13d..d3fbfa28db62 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c @@ -15,7 +15,6 @@ */ #include <linux/module.h> -#include <linux/debugfs.h> #include <linux/pci.h> #include <linux/moduleparam.h> @@ -27,11 +26,22 @@ MODULE_PARM_DESC(use_msi, " Use MSI interrupt: " "0 - don't, 1 - (default) - single, or 3"); +static bool debug_fw; /* = false; */ +module_param(debug_fw, bool, S_IRUGO); +MODULE_PARM_DESC(debug_fw, " load driver if FW not ready. For FW debug"); + /* Bus ops */ 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); @@ -63,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; @@ -71,6 +87,8 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil) mutex_lock(&wil->mutex); rc = wil_reset(wil); mutex_unlock(&wil->mutex); + if (debug_fw) + rc = 0; if (rc) goto release_irq; @@ -104,10 +122,12 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) struct wil6210_priv *wil; struct device *dev = &pdev->dev; void __iomem *csr; + struct wil_board *board = (struct wil_board *)id->driver_data; int rc; /* check HW */ - dev_info(&pdev->dev, WIL_NAME " device found [%04x:%04x] (rev %x)\n", + dev_info(&pdev->dev, WIL_NAME + " \"%s\" device found [%04x:%04x] (rev %x)\n", board->name, (int)pdev->vendor, (int)pdev->device, (int)pdev->revision); if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) { @@ -119,9 +139,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); @@ -150,6 +177,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_drvdata(pdev, wil); wil->pdev = pdev; + wil->board = board; wil6210_clear_irq(wil); /* FW should raise IRQ when ready */ @@ -200,8 +228,21 @@ static void wil_pcie_remove(struct pci_dev *pdev) pci_disable_device(pdev); } -static DEFINE_PCI_DEVICE_TABLE(wil6210_pcie_ids) = { - { PCI_DEVICE(0x1ae9, 0x0301) }, +static const struct wil_board wil_board_marlon = { + .board = WIL_BOARD_MARLON, + .name = "marlon", +}; + +static const struct wil_board wil_board_sparrow = { + .board = WIL_BOARD_SPARROW, + .name = "sparrow", +}; + +static const struct pci_device_id wil6210_pcie_ids[] = { + { PCI_DEVICE(0x1ae9, 0x0301), + .driver_data = (kernel_ulong_t)&wil_board_marlon }, + { PCI_DEVICE(0x1ae9, 0x0310), + .driver_data = (kernel_ulong_t)&wil_board_sparrow }, { /* end: all zeroes */ }, }; MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids); |