aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/pci/pci.c
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2010-10-22 11:42:02 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2010-10-22 11:42:02 +0000
commitba577448a2c9ea9bde8f575ddcc12fcbb16619df (patch)
tree08d66ccea5d75cbecdf6ac186b63d71e1ff6e002 /sys/dev/pci/pci.c
parent1c2b97e084b8cc025347d8a68397aa918c4154ee (diff)
Notes
Diffstat (limited to 'sys/dev/pci/pci.c')
-rw-r--r--sys/dev/pci/pci.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 533134274929..ef80f815d94b 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -182,6 +182,7 @@ struct pci_quirk {
int type;
#define PCI_QUIRK_MAP_REG 1 /* PCI map register in weird place */
#define PCI_QUIRK_DISABLE_MSI 2 /* MSI/MSI-X doesn't work */
+#define PCI_QUIRK_ENABLE_MSI_VM 3 /* Older chipset in VM where MSI works */
int arg1;
int arg2;
};
@@ -218,6 +219,12 @@ struct pci_quirk pci_quirks[] = {
*/
{ 0x74501022, PCI_QUIRK_DISABLE_MSI, 0, 0 },
+ /*
+ * Some virtualization environments emulate an older chipset
+ * but support MSI just fine. QEMU uses the Intel 82440.
+ */
+ { 0x12378086, PCI_QUIRK_ENABLE_MSI_VM, 0, 0 },
+
{ 0 }
};
@@ -1834,6 +1841,23 @@ pci_msi_device_blacklisted(device_t dev)
}
/*
+ * Returns true if a specified chipset supports MSI when it is
+ * emulated hardware in a virtual machine.
+ */
+static int
+pci_msi_vm_chipset(device_t dev)
+{
+ struct pci_quirk *q;
+
+ for (q = &pci_quirks[0]; q->devid; q++) {
+ if (q->devid == pci_get_devid(dev) &&
+ q->type == PCI_QUIRK_ENABLE_MSI_VM)
+ return (1);
+ }
+ return (0);
+}
+
+/*
* Determine if MSI is blacklisted globally on this sytem. Currently,
* we just check for blacklisted chipsets as represented by the
* host-PCI bridge at device 0:0:0. In the future, it may become
@@ -1849,8 +1873,14 @@ pci_msi_blacklisted(void)
return (0);
/* Blacklist all non-PCI-express and non-PCI-X chipsets. */
- if (!(pcie_chipset || pcix_chipset))
+ if (!(pcie_chipset || pcix_chipset)) {
+ if (vm_guest != VM_GUEST_NO) {
+ dev = pci_find_bsf(0, 0, 0);
+ if (dev != NULL)
+ return (pci_msi_vm_chipset(dev) == 0);
+ }
return (1);
+ }
dev = pci_find_bsf(0, 0, 0);
if (dev != NULL)