Michael S. Tsirkin wrote:
> This implements optional MSI-X support in virtio_pci.
> MSI-X is used whenever the host supports at least 2 MSI-X
> vectors: 1 for configuration changes and 1 for virtqueues.
> Per-virtqueue vectors are allocated if enough vectors
> available.
>
> +static int vp_request_vectors(struct virtio_device *vdev, unsigned max_vqs)
> +{
> + struct virtio_pci_device *vp_dev = to_vp_device(vdev);
> + const char *name = dev_name(&vp_dev->vdev.dev);
> + unsigned i, v;
> + int err = -ENOMEM;
> + /* We want at most one vector per queue and one for config changes.
> + * Fallback to separate vectors for config and a shared for queues.
> + * Finally fall back to regular interrupts. */
> + int options[] = { max_vqs + 1, 2 };
> + int nvectors = max(options[0], options[1]);
> +
> + vp_dev->msix_entries = kmalloc(nvectors * sizeof *vp_dev->msix_entries,
> + GFP_KERNEL);
> + if (!vp_dev->msix_entries)
> + goto error_entries;
> + vp_dev->msix_names = kmalloc(nvectors * sizeof *vp_dev->msix_names,
> + GFP_KERNEL);
> + if (!vp_dev->msix_names)
> + goto error_names;
> +
> + for (i = 0; i < nvectors; ++i)
> + vp_dev->msix_entries[i].entry = i;
> +
> + err = vp_enable_msix(vp_dev->pci_dev, vp_dev->msix_entries,
> + options, ARRAY_SIZE(options));
> + if (err < 0) {
> + /* Can't allocate enough MSI-X vectors, use regular interrupt */
> + vp_dev->msix_vectors = 0;
> + err = request_irq(vp_dev->pci_dev->irq, vp_interrupt,
> + IRQF_SHARED, name, vp_dev);
> + if (err)
> + goto error_irq;
> + vp_dev->intx_enabled = 1;
> + } else {
> + vp_dev->msix_vectors = err;
> + vp_dev->msix_enabled = 1;
> +
> + /* Set the vector used for configuration */
> + v = vp_dev->msix_used_vectors;
> + snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names,
> + "%s-config", name);
> + err = request_irq(vp_dev->msix_entries[v].vector,
> + vp_config_changed, 0, vp_dev->msix_names[v],
> + vp_dev);
> + if (err)
> + goto error_irq;
> + ++vp_dev->msix_used_vectors;
> +
> + iowrite16(v, vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR);
> + /* Verify we had enough resources to assign the vector */
> + v = ioread16(vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR);
> + if (v == VIRTIO_MSI_NO_VECTOR) {
> + err = -EBUSY;
> + goto error_irq;
> + }
> + }
> +
> + if (vp_dev->msix_vectors && vp_dev->msix_vectors != max_vqs + 1) {
> + /* Shared vector for all VQs */
> + v = vp_dev->msix_used_vectors;
> + snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names,
> + "%s-virtqueues", name);
> + err = request_irq(vp_dev->msix_entries[v].vector,
> + vp_vring_interrupt, 0, vp_dev->msix_names[v],
> + vp_dev);
> + if (err)
> + goto error_irq;
> + ++vp_dev->msix_used_vectors;
> + }
> + return 0;
> +error_irq:
> + vp_free_vectors(vdev);
> + kfree(vp_dev->msix_names);
> +error_names:
> + kfree(vp_dev->msix_entries);
> +error_entries:
> + return err;
> +}
> +
> @@ -272,12 +412,43 @@ static struct virtqueue *vp_find_vq(struct
> virtio_device *vdev, unsigned index,
> vq->priv = info;
> info->vq = vq;
>
> + /* allocate per-vq vector if available and necessary */
> + if (callback && vp_dev->msix_used_vectors < vp_dev->msix_vectors) {
> + vector = vp_dev->msix_used_vectors;
> + snprintf(vp_dev->msix_names[vector], sizeof *vp_dev->msix_names,
> + "%s-%s", dev_name(&vp_dev->vdev.dev), name);
> + err = request_irq(vp_dev->msix_entries[vector].vector,
> + vring_interrupt, 0,
> + vp_dev->msix_names[vector], vq);
> + if (err)
> + goto out_request_irq;
> + info->vector = vector;
> + ++vp_dev->msix_used_vectors;
> + } else
> + vector = VP_MSIX_VQ_VECTOR;
> +
> + if (callback && vp_dev->msix_enabled) {
> + iowrite16(vector, vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR);
> + vector = ioread16(vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR);
> + if (vector == VIRTIO_MSI_NO_VECTOR) {
> + err = -EBUSY;
> + goto out_assign;
> + }
> + }
> +
>
I'm not sure I understand how the vq -> msi mapping works. Do we
actually support an arbitrary mapping, or just either linear or n:1?
I don't mind the driver being limited, but the device interface should
be flexible. We'll want to deal with limited vector availability soon.
--
Do not meddle in the internals of kernels, for they are subtle and quick to
panic.
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/virtualization