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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
    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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
    PCIDevice *pdev = PCI_DEVICE(s);
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    if (!pdev->msix_vector_use_notifier) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    msix_unset_vector_notifiers(pdev);
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < s->peers[s->vm_id].nb_eventfds; i++) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue