aboutsummaryrefslogtreecommitdiff
path: root/hw/usb/hcd-xhci-pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/usb/hcd-xhci-pci.c')
-rw-r--r--hw/usb/hcd-xhci-pci.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/hw/usb/hcd-xhci-pci.c b/hw/usb/hcd-xhci-pci.c
index 49642aa..d908eb7 100644
--- a/hw/usb/hcd-xhci-pci.c
+++ b/hw/usb/hcd-xhci-pci.c
@@ -82,6 +82,21 @@ static bool xhci_pci_intr_raise(XHCIState *xhci, int n, bool level)
return false;
}
+static bool xhci_pci_intr_mapping_conditional(XHCIState *xhci)
+{
+ XHCIPciState *s = container_of(xhci, XHCIPciState, xhci);
+ PCIDevice *pci_dev = PCI_DEVICE(s);
+
+ /*
+ * Implementation of the "conditional-intr-mapping" property, which only
+ * enables interrupter mapping if MSI or MSI-X is available and active.
+ * Forces all events onto interrupter/event ring 0 in pin-based IRQ mode.
+ * Provides compatibility with macOS guests on machine types where MSI(-X)
+ * is not available.
+ */
+ return msix_enabled(pci_dev) || msi_enabled(pci_dev);
+}
+
static void xhci_pci_reset(DeviceState *dev)
{
XHCIPciState *s = XHCI_PCI(dev);
@@ -119,6 +134,9 @@ static void usb_xhci_pci_realize(struct PCIDevice *dev, Error **errp)
object_property_set_link(OBJECT(&s->xhci), "host", OBJECT(s), NULL);
s->xhci.intr_update = xhci_pci_intr_update;
s->xhci.intr_raise = xhci_pci_intr_raise;
+ if (s->conditional_intr_mapping) {
+ s->xhci.intr_mapping_supported = xhci_pci_intr_mapping_conditional;
+ }
if (!qdev_realize(DEVICE(&s->xhci), NULL, errp)) {
return;
}
@@ -201,6 +219,8 @@ static void xhci_instance_init(Object *obj)
static const Property xhci_pci_properties[] = {
DEFINE_PROP_ON_OFF_AUTO("msi", XHCIPciState, msi, ON_OFF_AUTO_AUTO),
DEFINE_PROP_ON_OFF_AUTO("msix", XHCIPciState, msix, ON_OFF_AUTO_AUTO),
+ DEFINE_PROP_BOOL("conditional-intr-mapping", XHCIPciState,
+ conditional_intr_mapping, false),
};
static void xhci_class_init(ObjectClass *klass, void *data)
@@ -215,6 +235,10 @@ static void xhci_class_init(ObjectClass *klass, void *data)
k->exit = usb_xhci_pci_exit;
k->class_id = PCI_CLASS_SERIAL_USB;
device_class_set_props(dc, xhci_pci_properties);
+ object_class_property_set_description(klass, "conditional-intr-mapping",
+ "When true, disables interrupter mapping for pin-based IRQ mode. "
+ "Intended to be used with guest drivers with questionable behaviour, "
+ "such as macOS's.");
}
static const TypeInfo xhci_pci_info = {