Commit 957d8d1d authored by Stefan Hajnoczi's avatar Stefan Hajnoczi Committed by Michael S. Tsirkin
Browse files

libqos: add MSI-X callbacks to QVirtioPCIDevice



The MSI-X vectors are programmed differently in the VIRTIO 1.0 and
Legacy interfaces.  Introduce callbacks so different implementations can
be used depending on the interface version.

Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: default avatarSergio Lopez <slp@redhat.com>
Reviewed-by: default avatarThomas Huth <thuth@redhat.com>
Message-Id: <20191023100425.12168-13-stefanha@redhat.com>
Reviewed-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent 1e59a866
Loading
Loading
Loading
Loading
+28 −9
Original line number Diff line number Diff line
@@ -281,6 +281,31 @@ const QVirtioBus qvirtio_pci = {
    .virtqueue_kick = qvirtio_pci_virtqueue_kick,
};

static void qvirtio_pci_set_config_vector(QVirtioPCIDevice *d, uint16_t entry)
{
    uint16_t vector;

    qpci_io_writew(d->pdev, d->bar, VIRTIO_MSI_CONFIG_VECTOR, entry);
    vector = qpci_io_readw(d->pdev, d->bar, VIRTIO_MSI_CONFIG_VECTOR);
    g_assert_cmphex(vector, !=, VIRTIO_MSI_NO_VECTOR);
}

static void qvirtio_pci_set_queue_vector(QVirtioPCIDevice *d, uint16_t vq_idx,
                                         uint16_t entry)
{
    uint16_t vector;

    qvirtio_pci_queue_select(&d->vdev, vq_idx);
    qpci_io_writew(d->pdev, d->bar, VIRTIO_MSI_QUEUE_VECTOR, entry);
    vector = qpci_io_readw(d->pdev, d->bar, VIRTIO_MSI_QUEUE_VECTOR);
    g_assert_cmphex(vector, !=, VIRTIO_MSI_NO_VECTOR);
}

static const QVirtioPCIMSIXOps qvirtio_pci_msix_ops_legacy = {
    .set_config_vector = qvirtio_pci_set_config_vector,
    .set_queue_vector = qvirtio_pci_set_queue_vector,
};

void qvirtio_pci_device_enable(QVirtioPCIDevice *d)
{
    qpci_device_enable(d->pdev);
@@ -295,7 +320,6 @@ void qvirtio_pci_device_disable(QVirtioPCIDevice *d)
void qvirtqueue_pci_msix_setup(QVirtioPCIDevice *d, QVirtQueuePCI *vqpci,
                                        QGuestAllocator *alloc, uint16_t entry)
{
    uint16_t vector;
    uint32_t control;
    uint64_t off;

@@ -321,16 +345,12 @@ void qvirtqueue_pci_msix_setup(QVirtioPCIDevice *d, QVirtQueuePCI *vqpci,
                   off + PCI_MSIX_ENTRY_VECTOR_CTRL,
                   control & ~PCI_MSIX_ENTRY_CTRL_MASKBIT);

    qvirtio_pci_queue_select(&d->vdev, vqpci->vq.index);
    qpci_io_writew(d->pdev, d->bar, VIRTIO_MSI_QUEUE_VECTOR, entry);
    vector = qpci_io_readw(d->pdev, d->bar, VIRTIO_MSI_QUEUE_VECTOR);
    g_assert_cmphex(vector, !=, VIRTIO_MSI_NO_VECTOR);
    d->msix_ops->set_queue_vector(d, vqpci->vq.index, entry);
}

void qvirtio_pci_set_msix_configuration_vector(QVirtioPCIDevice *d,
                                        QGuestAllocator *alloc, uint16_t entry)
{
    uint16_t vector;
    uint32_t control;
    uint64_t off;

@@ -358,9 +378,7 @@ void qvirtio_pci_set_msix_configuration_vector(QVirtioPCIDevice *d,
                   off + PCI_MSIX_ENTRY_VECTOR_CTRL,
                   control & ~PCI_MSIX_ENTRY_CTRL_MASKBIT);

    qpci_io_writew(d->pdev, d->bar, VIRTIO_MSI_CONFIG_VECTOR, entry);
    vector = qpci_io_readw(d->pdev, d->bar, VIRTIO_MSI_CONFIG_VECTOR);
    g_assert_cmphex(vector, !=, VIRTIO_MSI_NO_VECTOR);
    d->msix_ops->set_config_vector(d, entry);
}

void qvirtio_pci_destructor(QOSGraphObject *obj)
@@ -383,6 +401,7 @@ static void qvirtio_pci_init_from_pcidev(QVirtioPCIDevice *dev, QPCIDevice *pci_
    dev->vdev.device_type = qpci_config_readw(pci_dev, PCI_SUBSYSTEM_ID);

    dev->config_msix_entry = -1;
    dev->msix_ops = &qvirtio_pci_msix_ops_legacy;

    dev->vdev.bus = &qvirtio_pci;
    dev->vdev.big_endian = qvirtio_pci_is_big_endian(dev);
+12 −0
Original line number Diff line number Diff line
@@ -14,16 +14,28 @@
#include "libqos/pci.h"
#include "libqos/qgraph.h"

typedef struct QVirtioPCIMSIXOps QVirtioPCIMSIXOps;

typedef struct QVirtioPCIDevice {
    QOSGraphObject obj;
    QVirtioDevice vdev;
    QPCIDevice *pdev;
    QPCIBar bar;
    const QVirtioPCIMSIXOps *msix_ops;
    uint16_t config_msix_entry;
    uint64_t config_msix_addr;
    uint32_t config_msix_data;
} QVirtioPCIDevice;

struct QVirtioPCIMSIXOps {
    /* Set the Configuration Vector for MSI-X */
    void (*set_config_vector)(QVirtioPCIDevice *d, uint16_t entry);

    /* Set the Queue Vector for MSI-X */
    void (*set_queue_vector)(QVirtioPCIDevice *d, uint16_t vq_idx,
                             uint16_t entry);
};

typedef struct QVirtQueuePCI {
    QVirtQueue vq;
    uint16_t msix_entry;