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;
    int rc;

    /* check HW */
    dev_info(&pdev->dev, WIL_NAME " device found [%04x:%04x] (rev %x)\n",
             (int)pdev->vendor, (int)pdev->device, (int)pdev->revision);

    if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) {
        dev_err(&pdev->dev, "Not " WIL_NAME "? "
                "BAR0 size is %lu while expecting %lu\n",
                (ulong)pci_resource_len(pdev, 0), WIL6210_MEM_SIZE);
        return -ENODEV;
    }

    rc = pci_enable_device(pdev);
    if (rc) {
        dev_err(&pdev->dev, "pci_enable_device failed\n");
        return -ENODEV;
    }
    /* rollback to err_disable_pdev */

    rc = pci_request_region(pdev, 0, WIL_NAME);
    if (rc) {
        dev_err(&pdev->dev, "pci_request_region failed\n");
        goto err_disable_pdev;
    }
    /* rollback to err_release_reg */

    csr = pci_ioremap_bar(pdev, 0);
    if (!csr) {
        dev_err(&pdev->dev, "pci_ioremap_bar failed\n");
        rc = -ENODEV;
        goto err_release_reg;
    }
    /* rollback to err_iounmap */
    dev_info(&pdev->dev, "CSR at %pR -> %p\n", &pdev->resource[0], csr);

    wil = wil_if_alloc(dev, csr);
    if (IS_ERR(wil)) {
        rc = (int)PTR_ERR(wil);
        dev_err(dev, "wil_if_alloc failed: %d\n", rc);
        goto err_iounmap;
    }
    /* rollback to if_free */

    pci_set_drvdata(pdev, wil);
    wil->pdev = pdev;

    wil6210_clear_irq(wil);
    /* FW should raise IRQ when ready */
    rc = wil_if_pcie_enable(wil);
    if (rc) {
        wil_err(wil, "Enable device failed\n");
        goto if_free;
    }
    /* rollback to bus_disable */

    rc = wil_if_add(wil);
    if (rc) {
        wil_err(wil, "wil_if_add failed: %d\n", rc);
        goto bus_disable;
    }

    wil6210_debugfs_init(wil);

    /* check FW is alive */
    wmi_echo(wil);

    return 0;

bus_disable:
    wil_if_pcie_disable(wil);
if_free:
    wil_if_free(wil);
err_iounmap:
    pci_iounmap(pdev, csr);
err_release_reg:
    pci_release_region(pdev, 0);
err_disable_pdev:
    pci_disable_device(pdev);

    return rc;
}
Esempio n. 2
0
static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
	struct wil6210_priv *wil;
	struct device *dev = &pdev->dev;
	int rc;
	const struct wil_platform_rops rops = {
		.ramdump = wil_platform_rop_ramdump,
		.fw_recovery = wil_platform_rop_fw_recovery,
	};

	/* check HW */
	dev_info(&pdev->dev, WIL_NAME
		 " device found [%04x:%04x] (rev %x)\n",
		 (int)pdev->vendor, (int)pdev->device, (int)pdev->revision);

	if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) {
		dev_err(&pdev->dev, "Not " WIL_NAME "? "
			"BAR0 size is %lu while expecting %lu\n",
			(ulong)pci_resource_len(pdev, 0), WIL6210_MEM_SIZE);
		return -ENODEV;
	}

	wil = wil_if_alloc(dev);
	if (IS_ERR(wil)) {
		rc = (int)PTR_ERR(wil);
		dev_err(dev, "wil_if_alloc failed: %d\n", rc);
		return rc;
	}
	wil->pdev = pdev;
	pci_set_drvdata(pdev, wil);
	/* rollback to if_free */

	wil->platform_handle =
		wil_platform_init(&pdev->dev, &wil->platform_ops, &rops, wil);
	if (!wil->platform_handle) {
		rc = -ENODEV;
		wil_err(wil, "wil_platform_init failed\n");
		goto if_free;
	}
	/* rollback to err_plat */

	rc = pci_enable_device(pdev);
	if (rc) {
		wil_err(wil,
			"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) {
		wil_err(wil,
			"pci_enable_device failed, even with MSI only\n");
		goto err_plat;
	}
	/* rollback to err_disable_pdev */

	rc = pci_request_region(pdev, 0, WIL_NAME);
	if (rc) {
		wil_err(wil, "pci_request_region failed\n");
		goto err_disable_pdev;
	}
	/* rollback to err_release_reg */

	wil->csr = pci_ioremap_bar(pdev, 0);
	if (!wil->csr) {
		wil_err(wil, "pci_ioremap_bar failed\n");
		rc = -ENODEV;
		goto err_release_reg;
	}
	/* rollback to err_iounmap */
	wil_info(wil, "CSR at %pR -> 0x%p\n", &pdev->resource[0], wil->csr);

	wil_set_capabilities(wil);
	wil6210_clear_irq(wil);

	/* FW should raise IRQ when ready */
	rc = wil_if_pcie_enable(wil);
	if (rc) {
		wil_err(wil, "Enable device failed\n");
		goto err_iounmap;
	}
	/* rollback to bus_disable */

	rc = wil_if_add(wil);
	if (rc) {
		wil_err(wil, "wil_if_add failed: %d\n", rc);
		goto bus_disable;
	}

#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
	wil->pm_notify.notifier_call = wil6210_pm_notify;
	rc = register_pm_notifier(&wil->pm_notify);
	if (rc)
		/* Do not fail the driver initialization, as suspend can
		 * be prevented in a later phase if needed
		 */
		wil_err(wil, "register_pm_notifier failed: %d\n", rc);
#endif /* CONFIG_PM_SLEEP */
#endif /* CONFIG_PM */

	wil6210_debugfs_init(wil);


	return 0;

bus_disable:
	wil_if_pcie_disable(wil);
err_iounmap:
	pci_iounmap(pdev, wil->csr);
err_release_reg:
	pci_release_region(pdev, 0);
err_disable_pdev:
	pci_disable_device(pdev);
err_plat:
	if (wil->platform_ops.uninit)
		wil->platform_ops.uninit(wil->platform_handle);
if_free:
	wil_if_free(wil);

	return rc;
}