diff options
-rw-r--r-- | drivers/vfio/pci/vfio_pci.c | 8 | ||||
-rw-r--r-- | drivers/vfio/pci/vfio_pci_config.c | 27 |
2 files changed, 33 insertions, 2 deletions
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index cddb453a1ba5..50cdedfca9fe 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c | |||
@@ -434,10 +434,14 @@ static int vfio_pci_get_irq_count(struct vfio_pci_device *vdev, int irq_type) | |||
434 | { | 434 | { |
435 | if (irq_type == VFIO_PCI_INTX_IRQ_INDEX) { | 435 | if (irq_type == VFIO_PCI_INTX_IRQ_INDEX) { |
436 | u8 pin; | 436 | u8 pin; |
437 | |||
438 | if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || | ||
439 | vdev->nointx || vdev->pdev->is_virtfn) | ||
440 | return 0; | ||
441 | |||
437 | pci_read_config_byte(vdev->pdev, PCI_INTERRUPT_PIN, &pin); | 442 | pci_read_config_byte(vdev->pdev, PCI_INTERRUPT_PIN, &pin); |
438 | if (IS_ENABLED(CONFIG_VFIO_PCI_INTX) && !vdev->nointx && pin) | ||
439 | return 1; | ||
440 | 443 | ||
444 | return pin ? 1 : 0; | ||
441 | } else if (irq_type == VFIO_PCI_MSI_IRQ_INDEX) { | 445 | } else if (irq_type == VFIO_PCI_MSI_IRQ_INDEX) { |
442 | u8 pos; | 446 | u8 pos; |
443 | u16 flags; | 447 | u16 flags; |
diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c index 62023b4a373b..423ea1f98441 100644 --- a/drivers/vfio/pci/vfio_pci_config.c +++ b/drivers/vfio/pci/vfio_pci_config.c | |||
@@ -1612,6 +1612,15 @@ static int vfio_ecap_init(struct vfio_pci_device *vdev) | |||
1612 | } | 1612 | } |
1613 | 1613 | ||
1614 | /* | 1614 | /* |
1615 | * Nag about hardware bugs, hopefully to have vendors fix them, but at least | ||
1616 | * to collect a list of dependencies for the VF INTx pin quirk below. | ||
1617 | */ | ||
1618 | static const struct pci_device_id known_bogus_vf_intx_pin[] = { | ||
1619 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x270c) }, | ||
1620 | {} | ||
1621 | }; | ||
1622 | |||
1623 | /* | ||
1615 | * For each device we allocate a pci_config_map that indicates the | 1624 | * For each device we allocate a pci_config_map that indicates the |
1616 | * capability occupying each dword and thus the struct perm_bits we | 1625 | * capability occupying each dword and thus the struct perm_bits we |
1617 | * use for read and write. We also allocate a virtualized config | 1626 | * use for read and write. We also allocate a virtualized config |
@@ -1676,6 +1685,24 @@ int vfio_config_init(struct vfio_pci_device *vdev) | |||
1676 | if (pdev->is_virtfn) { | 1685 | if (pdev->is_virtfn) { |
1677 | *(__le16 *)&vconfig[PCI_VENDOR_ID] = cpu_to_le16(pdev->vendor); | 1686 | *(__le16 *)&vconfig[PCI_VENDOR_ID] = cpu_to_le16(pdev->vendor); |
1678 | *(__le16 *)&vconfig[PCI_DEVICE_ID] = cpu_to_le16(pdev->device); | 1687 | *(__le16 *)&vconfig[PCI_DEVICE_ID] = cpu_to_le16(pdev->device); |
1688 | |||
1689 | /* | ||
1690 | * Per SR-IOV spec rev 1.1, 3.4.1.18 the interrupt pin register | ||
1691 | * does not apply to VFs and VFs must implement this register | ||
1692 | * as read-only with value zero. Userspace is not readily able | ||
1693 | * to identify whether a device is a VF and thus that the pin | ||
1694 | * definition on the device is bogus should it violate this | ||
1695 | * requirement. We already virtualize the pin register for | ||
1696 | * other purposes, so we simply need to replace the bogus value | ||
1697 | * and consider VFs when we determine INTx IRQ count. | ||
1698 | */ | ||
1699 | if (vconfig[PCI_INTERRUPT_PIN] && | ||
1700 | !pci_match_id(known_bogus_vf_intx_pin, pdev)) | ||
1701 | pci_warn(pdev, | ||
1702 | "Hardware bug: VF reports bogus INTx pin %d\n", | ||
1703 | vconfig[PCI_INTERRUPT_PIN]); | ||
1704 | |||
1705 | vconfig[PCI_INTERRUPT_PIN] = 0; /* Gratuitous for good VFs */ | ||
1679 | } | 1706 | } |
1680 | 1707 | ||
1681 | if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || vdev->nointx) | 1708 | if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || vdev->nointx) |