Commit 079944e6 authored by Anthony Liguori's avatar Anthony Liguori
Browse files

Merge remote-tracking branch 'mst/tags/for_anthony' into staging



pci,virtio

This optimizes MSIX handling in virtio-pci.
Also included is pci express capability bugfix.

Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarAnthony Liguori <aliguori@us.ibm.com>

* mst/tags/for_anthony:
  virtio-pci: don't poll masked vectors
  msix: expose access to masked/pending state
  msi: add API to get notified about pending bit poll
  pcie: Fix bug in pcie_ext_cap_set_next
  virtio: make bindings typesafe
parents a97ff30e 89d62be9
Loading
Loading
Loading
Loading
+15 −4
Original line number Diff line number Diff line
@@ -65,7 +65,7 @@ static int msix_is_pending(PCIDevice *dev, int vector)
    return *msix_pending_byte(dev, vector) & msix_pending_mask(vector);
}

static void msix_set_pending(PCIDevice *dev, int vector)
void msix_set_pending(PCIDevice *dev, unsigned int vector)
{
    *msix_pending_byte(dev, vector) |= msix_pending_mask(vector);
}
@@ -75,13 +75,13 @@ static void msix_clr_pending(PCIDevice *dev, int vector)
    *msix_pending_byte(dev, vector) &= ~msix_pending_mask(vector);
}

static bool msix_vector_masked(PCIDevice *dev, int vector, bool fmask)
static bool msix_vector_masked(PCIDevice *dev, unsigned int vector, bool fmask)
{
    unsigned offset = vector * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL;
    return fmask || dev->msix_table[offset] & PCI_MSIX_ENTRY_CTRL_MASKBIT;
}

static bool msix_is_masked(PCIDevice *dev, int vector)
bool msix_is_masked(PCIDevice *dev, unsigned int vector)
{
    return msix_vector_masked(dev, vector, dev->msix_function_masked);
}
@@ -191,6 +191,11 @@ static uint64_t msix_pba_mmio_read(void *opaque, hwaddr addr,
                                   unsigned size)
{
    PCIDevice *dev = opaque;
    if (dev->msix_vector_poll_notifier) {
        unsigned vector_start = addr * 8;
        unsigned vector_end = MIN(addr + size * 8, dev->msix_entries_nr);
        dev->msix_vector_poll_notifier(dev, vector_start, vector_end);
    }

    return pci_get_long(dev->msix_pba + addr);
}
@@ -513,7 +518,8 @@ static void msix_unset_notifier_for_vector(PCIDevice *dev, unsigned int vector)

int msix_set_vector_notifiers(PCIDevice *dev,
                              MSIVectorUseNotifier use_notifier,
                              MSIVectorReleaseNotifier release_notifier)
                              MSIVectorReleaseNotifier release_notifier,
                              MSIVectorPollNotifier poll_notifier)
{
    int vector, ret;

@@ -521,6 +527,7 @@ int msix_set_vector_notifiers(PCIDevice *dev,

    dev->msix_vector_use_notifier = use_notifier;
    dev->msix_vector_release_notifier = release_notifier;
    dev->msix_vector_poll_notifier = poll_notifier;

    if ((dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] &
        (MSIX_ENABLE_MASK | MSIX_MASKALL_MASK)) == MSIX_ENABLE_MASK) {
@@ -531,6 +538,9 @@ int msix_set_vector_notifiers(PCIDevice *dev,
            }
        }
    }
    if (dev->msix_vector_poll_notifier) {
        dev->msix_vector_poll_notifier(dev, 0, dev->msix_entries_nr);
    }
    return 0;

undo:
@@ -557,4 +567,5 @@ void msix_unset_vector_notifiers(PCIDevice *dev)
    }
    dev->msix_vector_use_notifier = NULL;
    dev->msix_vector_release_notifier = NULL;
    dev->msix_vector_poll_notifier = NULL;
}
+5 −1
Original line number Diff line number Diff line
@@ -26,6 +26,9 @@ void msix_load(PCIDevice *dev, QEMUFile *f);
int msix_enabled(PCIDevice *dev);
int msix_present(PCIDevice *dev);

bool msix_is_masked(PCIDevice *dev, unsigned vector);
void msix_set_pending(PCIDevice *dev, unsigned vector);

int msix_vector_use(PCIDevice *dev, unsigned vector);
void msix_vector_unuse(PCIDevice *dev, unsigned vector);
void msix_unuse_all_vectors(PCIDevice *dev);
@@ -36,6 +39,7 @@ void msix_reset(PCIDevice *dev);

int msix_set_vector_notifiers(PCIDevice *dev,
                              MSIVectorUseNotifier use_notifier,
                              MSIVectorReleaseNotifier release_notifier);
                              MSIVectorReleaseNotifier release_notifier,
                              MSIVectorPollNotifier poll_notifier);
void msix_unset_vector_notifiers(PCIDevice *dev);
#endif
+4 −0
Original line number Diff line number Diff line
@@ -187,6 +187,9 @@ typedef void (*PCIINTxRoutingNotifier)(PCIDevice *dev);
typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector,
                                      MSIMessage msg);
typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector);
typedef void (*MSIVectorPollNotifier)(PCIDevice *dev,
                                      unsigned int vector_start,
                                      unsigned int vector_end);

struct PCIDevice {
    DeviceState qdev;
@@ -271,6 +274,7 @@ struct PCIDevice {
    /* MSI-X notifiers */
    MSIVectorUseNotifier msix_vector_use_notifier;
    MSIVectorReleaseNotifier msix_vector_release_notifier;
    MSIVectorPollNotifier msix_vector_poll_notifier;
};

void pci_register_bar(PCIDevice *pci_dev, int region_num,
+1 −1
Original line number Diff line number Diff line
@@ -494,7 +494,7 @@ uint16_t pcie_find_capability(PCIDevice *dev, uint16_t cap_id)

static void pcie_ext_cap_set_next(PCIDevice *dev, uint16_t pos, uint16_t next)
{
    uint16_t header = pci_get_long(dev->config + pos);
    uint32_t header = pci_get_long(dev->config + pos);
    assert(!(next & (PCI_EXT_CAP_ALIGN - 1)));
    header = (header & ~PCI_EXT_CAP_NEXT_MASK) |
        ((next << PCI_EXT_CAP_NEXT_SHIFT) & PCI_EXT_CAP_NEXT_MASK);
+19 −5
Original line number Diff line number Diff line
@@ -138,7 +138,7 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)

    bus->dev_offs += dev_len;

    virtio_bind_device(vdev, &virtio_s390_bindings, dev);
    virtio_bind_device(vdev, &virtio_s390_bindings, DEVICE(dev));
    dev->host_features = vdev->get_features(vdev, dev->host_features);
    s390_virtio_device_sync(dev);
    s390_virtio_reset_idx(dev);
@@ -364,18 +364,32 @@ VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem)
    return NULL;
}

static void virtio_s390_notify(void *opaque, uint16_t vector)
/* DeviceState to VirtIOS390Device. Note: used on datapath,
 * be careful and test performance if you change this.
 */
static inline VirtIOS390Device *to_virtio_s390_device_fast(DeviceState *d)
{
    return container_of(d, VirtIOS390Device, qdev);
}

/* DeviceState to VirtIOS390Device. TODO: use QOM. */
static inline VirtIOS390Device *to_virtio_s390_device(DeviceState *d)
{
    return container_of(d, VirtIOS390Device, qdev);
}

static void virtio_s390_notify(DeviceState *d, uint16_t vector)
{
    VirtIOS390Device *dev = (VirtIOS390Device*)opaque;
    VirtIOS390Device *dev = to_virtio_s390_device_fast(d);
    uint64_t token = s390_virtio_device_vq_token(dev, vector);
    S390CPU *cpu = s390_cpu_addr2state(0);

    s390_virtio_irq(cpu, 0, token);
}

static unsigned virtio_s390_get_features(void *opaque)
static unsigned virtio_s390_get_features(DeviceState *d)
{
    VirtIOS390Device *dev = (VirtIOS390Device*)opaque;
    VirtIOS390Device *dev = to_virtio_s390_device(d);
    return dev->host_features;
}

Loading