mirror of https://github.com/xqemu/xqemu.git
ivshmem: Improve MSI irqfd error handling
Adds a rollback path to ivshmem_enable_irqfd() and fixes ivshmem_disable_irqfd() to bail if irqfd has not been enabled. To reproduce, run: ivshmem-server -n 0 and QEMU with: -device ivshmem-doorbell,chardev=iv -chardev socket,path=/tmp/ivshmem_socket,id=iv then load, unload, and load again the Windows driver, at the time of writing available at: https://github.com/virtio-win/kvm-guest-drivers-windows/tree/master/ivshmem The issue is believed to have been masked by other guest drivers, notably Linux ones, not enabling MSI-X on the device. Signed-off-by: Ladi Prosek <lprosek@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> Message-Id: <20171211072110.9058-4-lprosek@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
089fd80376
commit
0b88dd9420
|
@ -785,29 +785,6 @@ static int ivshmem_setup_interrupts(IVShmemState *s, Error **errp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ivshmem_enable_irqfd(IVShmemState *s)
|
|
||||||
{
|
|
||||||
PCIDevice *pdev = PCI_DEVICE(s);
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < s->peers[s->vm_id].nb_eventfds; i++) {
|
|
||||||
Error *err = NULL;
|
|
||||||
|
|
||||||
ivshmem_add_kvm_msi_virq(s, i, &err);
|
|
||||||
if (err) {
|
|
||||||
error_report_err(err);
|
|
||||||
/* TODO do we need to handle the error? */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msix_set_vector_notifiers(pdev,
|
|
||||||
ivshmem_vector_unmask,
|
|
||||||
ivshmem_vector_mask,
|
|
||||||
ivshmem_vector_poll)) {
|
|
||||||
error_report("ivshmem: msix_set_vector_notifiers failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ivshmem_remove_kvm_msi_virq(IVShmemState *s, int vector)
|
static void ivshmem_remove_kvm_msi_virq(IVShmemState *s, int vector)
|
||||||
{
|
{
|
||||||
IVSHMEM_DPRINTF("ivshmem_remove_kvm_msi_virq vector:%d\n", vector);
|
IVSHMEM_DPRINTF("ivshmem_remove_kvm_msi_virq vector:%d\n", vector);
|
||||||
|
@ -822,11 +799,45 @@ static void ivshmem_remove_kvm_msi_virq(IVShmemState *s, int vector)
|
||||||
s->msi_vectors[vector].pdev = NULL;
|
s->msi_vectors[vector].pdev = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ivshmem_enable_irqfd(IVShmemState *s)
|
||||||
|
{
|
||||||
|
PCIDevice *pdev = PCI_DEVICE(s);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < s->peers[s->vm_id].nb_eventfds; i++) {
|
||||||
|
Error *err = NULL;
|
||||||
|
|
||||||
|
ivshmem_add_kvm_msi_virq(s, i, &err);
|
||||||
|
if (err) {
|
||||||
|
error_report_err(err);
|
||||||
|
goto undo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msix_set_vector_notifiers(pdev,
|
||||||
|
ivshmem_vector_unmask,
|
||||||
|
ivshmem_vector_mask,
|
||||||
|
ivshmem_vector_poll)) {
|
||||||
|
error_report("ivshmem: msix_set_vector_notifiers failed");
|
||||||
|
goto undo;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
undo:
|
||||||
|
while (--i >= 0) {
|
||||||
|
ivshmem_remove_kvm_msi_virq(s, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void ivshmem_disable_irqfd(IVShmemState *s)
|
static void ivshmem_disable_irqfd(IVShmemState *s)
|
||||||
{
|
{
|
||||||
PCIDevice *pdev = PCI_DEVICE(s);
|
PCIDevice *pdev = PCI_DEVICE(s);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (!pdev->msix_vector_use_notifier) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
msix_unset_vector_notifiers(pdev);
|
msix_unset_vector_notifiers(pdev);
|
||||||
|
|
||||||
for (i = 0; i < s->peers[s->vm_id].nb_eventfds; i++) {
|
for (i = 0; i < s->peers[s->vm_id].nb_eventfds; i++) {
|
||||||
|
|
Loading…
Reference in New Issue