Revision 89d62be9 hw/virtio-pci.c

b/hw/virtio-pci.c
508 508
        }
509 509
        return ret;
510 510
    }
511

  
512
    virtio_queue_set_guest_notifier_fd_handler(vq, true, true);
513 511
    return 0;
514 512
}
515 513

  
......
528 526
    if (--irqfd->users == 0) {
529 527
        kvm_irqchip_release_virq(kvm_state, irqfd->virq);
530 528
    }
531

  
532
    virtio_queue_set_guest_notifier_fd_handler(vq, true, false);
533 529
}
534 530

  
535 531
static int kvm_virtio_pci_vector_use(PCIDevice *dev, unsigned vector,
......
580 576
    }
581 577
}
582 578

  
583
static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign)
579
static void kvm_virtio_pci_vector_poll(PCIDevice *dev,
580
                                       unsigned int vector_start,
581
                                       unsigned int vector_end)
582
{
583
    VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
584
    VirtIODevice *vdev = proxy->vdev;
585
    int queue_no;
586
    unsigned int vector;
587
    EventNotifier *notifier;
588
    VirtQueue *vq;
589

  
590
    for (queue_no = 0; queue_no < VIRTIO_PCI_QUEUE_MAX; queue_no++) {
591
        if (!virtio_queue_get_num(vdev, queue_no)) {
592
            break;
593
        }
594
        vector = virtio_queue_vector(vdev, queue_no);
595
        if (vector < vector_start || vector >= vector_end ||
596
            !msix_is_masked(dev, vector)) {
597
            continue;
598
        }
599
        vq = virtio_get_queue(vdev, queue_no);
600
        notifier = virtio_queue_get_guest_notifier(vq);
601
        if (event_notifier_test_and_clear(notifier)) {
602
            msix_set_pending(dev, vector);
603
        }
604
    }
605
}
606

  
607
static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign,
608
                                         bool with_irqfd)
584 609
{
585 610
    VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
586 611
    VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
......
591 616
        if (r < 0) {
592 617
            return r;
593 618
        }
594
        virtio_queue_set_guest_notifier_fd_handler(vq, true, false);
619
        virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd);
595 620
    } else {
596
        virtio_queue_set_guest_notifier_fd_handler(vq, false, false);
621
        virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);
597 622
        event_notifier_cleanup(notifier);
598 623
    }
599 624

  
......
611 636
    VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
612 637
    VirtIODevice *vdev = proxy->vdev;
613 638
    int r, n;
639
    bool with_irqfd = msix_enabled(&proxy->pci_dev) &&
640
        kvm_msi_via_irqfd_enabled();
614 641

  
615 642
    /* Must unset vector notifier while guest notifier is still assigned */
616
    if (kvm_msi_via_irqfd_enabled() && !assign) {
643
    if (proxy->vector_irqfd && !assign) {
617 644
        msix_unset_vector_notifiers(&proxy->pci_dev);
618 645
        g_free(proxy->vector_irqfd);
619 646
        proxy->vector_irqfd = NULL;
......
624 651
            break;
625 652
        }
626 653

  
627
        r = virtio_pci_set_guest_notifier(d, n, assign);
654
        r = virtio_pci_set_guest_notifier(d, n, assign,
655
                                          kvm_msi_via_irqfd_enabled());
628 656
        if (r < 0) {
629 657
            goto assign_error;
630 658
        }
631 659
    }
632 660

  
633 661
    /* Must set vector notifier after guest notifier has been assigned */
634
    if (kvm_msi_via_irqfd_enabled() && assign) {
662
    if (with_irqfd && assign) {
635 663
        proxy->vector_irqfd =
636 664
            g_malloc0(sizeof(*proxy->vector_irqfd) *
637 665
                      msix_nr_vectors_allocated(&proxy->pci_dev));
638 666
        r = msix_set_vector_notifiers(&proxy->pci_dev,
639 667
                                      kvm_virtio_pci_vector_use,
640 668
                                      kvm_virtio_pci_vector_release,
641
                                      NULL);
669
                                      kvm_virtio_pci_vector_poll);
642 670
        if (r < 0) {
643 671
            goto assign_error;
644 672
        }
......
650 678
    /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */
651 679
    assert(assign);
652 680
    while (--n >= 0) {
653
        virtio_pci_set_guest_notifier(d, n, !assign);
681
        virtio_pci_set_guest_notifier(d, n, !assign, with_irqfd);
654 682
    }
655 683
    return r;
656 684
}

Also available in: Unified diff