static int vfio_msi_enable(struct vfio_pci_device *vdev, int nvec, bool msix) { struct pci_dev *pdev = vdev->pdev; int ret; if (!is_irq_none(vdev)) return -EINVAL; vdev->ctx = kzalloc(nvec * sizeof(struct vfio_pci_irq_ctx), GFP_KERNEL); if (!vdev->ctx) return -ENOMEM; if (msix) { int i; vdev->msix = kzalloc(nvec * sizeof(struct msix_entry), GFP_KERNEL); if (!vdev->msix) { kfree(vdev->ctx); return -ENOMEM; } for (i = 0; i < nvec; i++) vdev->msix[i].entry = i; ret = pci_enable_msix_range(pdev, vdev->msix, 1, nvec); if (ret < nvec) { if (ret > 0) pci_disable_msix(pdev); kfree(vdev->msix); kfree(vdev->ctx); return ret; } } else { ret = pci_enable_msi_range(pdev, 1, nvec); if (ret < nvec) { if (ret > 0) pci_disable_msi(pdev); kfree(vdev->ctx); return ret; } } vdev->num_ctx = nvec; vdev->irq_type = msix ? VFIO_PCI_MSIX_IRQ_INDEX : VFIO_PCI_MSI_IRQ_INDEX; if (!msix) { /* * Compute the virtual hardware field for max msi vectors - * it is the log base 2 of the number of vectors. */ vdev->msi_qmax = fls(nvec * 2 - 1) - 1; } return 0; }
/* Bus ops */ static int wil_if_pcie_enable(struct wil6210_priv *wil) { struct pci_dev *pdev = wil->pdev; int rc; pci_set_master(pdev); /* * how many MSI interrupts to request? */ switch (use_msi) { case 3: case 1: wil_dbg_misc(wil, "Setup %d MSI interrupts\n", use_msi); break; case 0: wil_dbg_misc(wil, "MSI interrupts disabled, use INTx\n"); break; default: wil_err(wil, "Invalid use_msi=%d, default to 1\n", use_msi); use_msi = 1; } if (use_msi == 3 && pci_enable_msi_range(pdev, 3, 3) < 0) { wil_err(wil, "3 MSI mode failed, try 1 MSI\n"); use_msi = 1; } if (use_msi == 1 && pci_enable_msi(pdev)) { wil_err(wil, "pci_enable_msi failed, use INTx\n"); use_msi = 0; } wil->n_msi = use_msi; rc = wil6210_init_irq(wil, pdev->irq); if (rc) goto stop_master; /* need reset here to obtain MAC */ mutex_lock(&wil->mutex); rc = wil_reset(wil); mutex_unlock(&wil->mutex); if (rc) goto release_irq; return 0; release_irq: wil6210_fini_irq(wil, pdev->irq); /* safe to call if no MSI */ pci_disable_msi(pdev); stop_master: pci_clear_master(pdev); return rc; }
/* 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; wil_dbg_misc(wil, "%s()\n", __func__); pdev->msi_enabled = 0; pci_set_master(pdev); /* * how many MSI interrupts to request? */ switch (use_msi) { case 3: case 1: wil_dbg_misc(wil, "Setup %d MSI interrupts\n", use_msi); break; case 0: wil_dbg_misc(wil, "MSI interrupts disabled, use INTx\n"); break; default: wil_err(wil, "Invalid use_msi=%d, default to 1\n", use_msi); use_msi = 1; } if (use_msi == 3 && pci_enable_msi_range(pdev, 3, 3) < 0) { wil_err(wil, "3 MSI mode failed, try 1 MSI\n"); use_msi = 1; } if (use_msi == 1 && pci_enable_msi(pdev)) { wil_err(wil, "pci_enable_msi failed, use INTx\n"); use_msi = 0; } 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; /* need reset here to obtain MAC */ mutex_lock(&wil->mutex); rc = wil_reset(wil); mutex_unlock(&wil->mutex); if (debug_fw) rc = 0; if (rc) goto release_irq; return 0; release_irq: wil6210_fini_irq(wil, pdev->irq); /* safe to call if no MSI */ pci_disable_msi(pdev); stop_master: pci_clear_master(pdev); return rc; }