static int vfio_msi_enable(struct vfio_pci_device *vdev, int nvec, bool msix)
{
struct pci_dev *pdev = vdev->pdev;
+ unsigned int flag = msix ? PCI_IRQ_MSIX : PCI_IRQ_MSI;
int ret;
if (!is_irq_none(vdev))
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;
- }
+ /* return the number of supported vectors if we can't get all: */
+ ret = pci_alloc_irq_vectors(pdev, 1, nvec, flag);
+ if (ret < nvec) {
+ if (ret > 0)
+ pci_free_irq_vectors(pdev);
+ kfree(vdev->ctx);
+ return ret;
}
vdev->num_ctx = nvec;
if (vector < 0 || vector >= vdev->num_ctx)
return -EINVAL;
- irq = msix ? vdev->msix[vector].vector : pdev->irq + vector;
+ irq = pci_irq_vector(pdev, vector);
if (vdev->ctx[vector].trigger) {
free_irq(irq, vdev->ctx[vector].trigger);
vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix);
- if (msix) {
- pci_disable_msix(vdev->pdev);
- kfree(vdev->msix);
- } else
- pci_disable_msi(pdev);
+ pci_free_irq_vectors(pdev);
/*
* Both disable paths above use pci_intx_for_msi() to clear DisINTx