mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-11 03:24:58 -06:00
hw/usb/hcd-xhci-pci: Adds property for disabling mapping in IRQ mode
This change addresses an edge case that trips up macOS guest drivers for PCI based XHCI controllers. The guest driver would attempt to schedule events to XHCI event rings 1 and 2 even when using PCI pin-based interrupts. Interrupts would therefore be dropped, and events only handled on timeout. So, in addition to disabling interrupter mapping if numintrs is 1, a callback is added to xhci to check whether interrupter mapping should be enabled. The PCI XHCI device type now provides an implementation of this callback if the new "conditional-intr-mapping" property is enabled. (default: disabled) When enabled, interrupter mapping is only enabled when MSI-X or MSI is active. This means that when using pin-based interrupts, events are only submitted to interrupter 0 regardless of selected target. This allows the macOS guest drivers to work with the device in those configurations. Signed-off-by: Phil Dennis-Jordan <phil@philjordan.eu> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2705 Message-ID: <20241227121336.25838-6-phil@philjordan.eu> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
This commit is contained in:
parent
ee241d79bb
commit
9422a5acf2
4 changed files with 32 additions and 1 deletions
|
@ -82,6 +82,21 @@ static bool xhci_pci_intr_raise(XHCIState *xhci, int n, bool level)
|
||||||
return false;
|
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)
|
static void xhci_pci_reset(DeviceState *dev)
|
||||||
{
|
{
|
||||||
XHCIPciState *s = XHCI_PCI(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);
|
object_property_set_link(OBJECT(&s->xhci), "host", OBJECT(s), NULL);
|
||||||
s->xhci.intr_update = xhci_pci_intr_update;
|
s->xhci.intr_update = xhci_pci_intr_update;
|
||||||
s->xhci.intr_raise = xhci_pci_intr_raise;
|
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)) {
|
if (!qdev_realize(DEVICE(&s->xhci), NULL, errp)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -201,6 +219,8 @@ static void xhci_instance_init(Object *obj)
|
||||||
static const Property xhci_pci_properties[] = {
|
static const Property xhci_pci_properties[] = {
|
||||||
DEFINE_PROP_ON_OFF_AUTO("msi", XHCIPciState, msi, ON_OFF_AUTO_AUTO),
|
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_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)
|
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->exit = usb_xhci_pci_exit;
|
||||||
k->class_id = PCI_CLASS_SERIAL_USB;
|
k->class_id = PCI_CLASS_SERIAL_USB;
|
||||||
device_class_set_props(dc, xhci_pci_properties);
|
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 = {
|
static const TypeInfo xhci_pci_info = {
|
||||||
|
|
|
@ -40,6 +40,7 @@ typedef struct XHCIPciState {
|
||||||
XHCIState xhci;
|
XHCIState xhci;
|
||||||
OnOffAuto msi;
|
OnOffAuto msi;
|
||||||
OnOffAuto msix;
|
OnOffAuto msix;
|
||||||
|
bool conditional_intr_mapping;
|
||||||
} XHCIPciState;
|
} XHCIPciState;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -644,7 +644,8 @@ static void xhci_event(XHCIState *xhci, XHCIEvent *event, int v)
|
||||||
dma_addr_t erdp;
|
dma_addr_t erdp;
|
||||||
unsigned int dp_idx;
|
unsigned int dp_idx;
|
||||||
|
|
||||||
if (xhci->numintrs == 1) {
|
if (xhci->numintrs == 1 ||
|
||||||
|
(xhci->intr_mapping_supported && !xhci->intr_mapping_supported(xhci))) {
|
||||||
v = 0;
|
v = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -193,6 +193,11 @@ typedef struct XHCIState {
|
||||||
uint32_t max_pstreams_mask;
|
uint32_t max_pstreams_mask;
|
||||||
void (*intr_update)(XHCIState *s, int n, bool enable);
|
void (*intr_update)(XHCIState *s, int n, bool enable);
|
||||||
bool (*intr_raise)(XHCIState *s, int n, bool level);
|
bool (*intr_raise)(XHCIState *s, int n, bool level);
|
||||||
|
/*
|
||||||
|
* Callback for special-casing interrupter mapping support. NULL for most
|
||||||
|
* implementations, for defaulting to enabled mapping unless numintrs == 1.
|
||||||
|
*/
|
||||||
|
bool (*intr_mapping_supported)(XHCIState *s);
|
||||||
DeviceState *hostOpaque;
|
DeviceState *hostOpaque;
|
||||||
|
|
||||||
/* Operational Registers */
|
/* Operational Registers */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue