virtio: provide a method to get the IRQ affinity mask for a virtqueue
authorChristoph Hellwig <hch@lst.de>
Sun, 5 Feb 2017 17:15:23 +0000 (18:15 +0100)
committerMichael S. Tsirkin <mst@redhat.com>
Mon, 27 Feb 2017 18:54:05 +0000 (20:54 +0200)
This basically passed up the pci_irq_get_affinity information through
virtio through an optional get_vq_affinity method.  It is only implemented
by the PCI backend for now, and only when we use per-virtqueue IRQs.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
drivers/virtio/virtio_pci_common.c
drivers/virtio/virtio_pci_common.h
drivers/virtio/virtio_pci_legacy.c
drivers/virtio/virtio_pci_modern.c
include/linux/virtio_config.h

index 7902e920fc73fab609a528bd7ea3b3d24acb358c..df548a6fb844f701d65301503d998a05e6d19703 100644 (file)
@@ -361,6 +361,17 @@ int vp_set_vq_affinity(struct virtqueue *vq, int cpu)
        return 0;
 }
 
+const struct cpumask *vp_get_vq_affinity(struct virtio_device *vdev, int index)
+{
+       struct virtio_pci_device *vp_dev = to_vp_device(vdev);
+       unsigned int *map = vp_dev->msix_vector_map;
+
+       if (!map || map[index] == VIRTIO_MSI_NO_VECTOR)
+               return NULL;
+
+       return pci_irq_get_affinity(vp_dev->pci_dev, map[index]);
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int virtio_pci_freeze(struct device *dev)
 {
index a6ad9ec6baefd0092e7d6f32a30fff053220a3b5..ac8c9d7889646ab3cc28bb51accd0d3840d5a34f 100644 (file)
@@ -108,6 +108,8 @@ const char *vp_bus_name(struct virtio_device *vdev);
  */
 int vp_set_vq_affinity(struct virtqueue *vq, int cpu);
 
+const struct cpumask *vp_get_vq_affinity(struct virtio_device *vdev, int index);
+
 #if IS_ENABLED(CONFIG_VIRTIO_PCI_LEGACY)
 int virtio_pci_legacy_probe(struct virtio_pci_device *);
 void virtio_pci_legacy_remove(struct virtio_pci_device *);
index 2ab6aee51bf6fd5fe38123303b38c7b63c758778..f7362c5fe18a96a902bc81138b8ea796e03e79d9 100644 (file)
@@ -190,6 +190,7 @@ static const struct virtio_config_ops virtio_pci_config_ops = {
        .finalize_features = vp_finalize_features,
        .bus_name       = vp_bus_name,
        .set_vq_affinity = vp_set_vq_affinity,
+       .get_vq_affinity = vp_get_vq_affinity,
 };
 
 /* the PCI probing function */
index a7a0981e441ce080a91421298155f36f95b1256e..7bc3004b840ef3e3dabb5c2e24af8a935f552eba 100644 (file)
@@ -437,6 +437,7 @@ static const struct virtio_config_ops virtio_pci_config_nodev_ops = {
        .finalize_features = vp_finalize_features,
        .bus_name       = vp_bus_name,
        .set_vq_affinity = vp_set_vq_affinity,
+       .get_vq_affinity = vp_get_vq_affinity,
 };
 
 static const struct virtio_config_ops virtio_pci_config_ops = {
@@ -452,6 +453,7 @@ static const struct virtio_config_ops virtio_pci_config_ops = {
        .finalize_features = vp_finalize_features,
        .bus_name       = vp_bus_name,
        .set_vq_affinity = vp_set_vq_affinity,
+       .get_vq_affinity = vp_get_vq_affinity,
 };
 
 /**
index 2ebe506fe41aea8287781407bc6a40a6f49b4a28..8355bab175e1d8fb27ac9e0860465ba8afc36076 100644 (file)
@@ -58,6 +58,7 @@ struct irq_affinity;
  *      This returns a pointer to the bus name a la pci_name from which
  *      the caller can then copy.
  * @set_vq_affinity: set the affinity for a virtqueue.
+ * @get_vq_affinity: get the affinity for a virtqueue (optional).
  */
 typedef void vq_callback_t(struct virtqueue *);
 struct virtio_config_ops {
@@ -77,6 +78,8 @@ struct virtio_config_ops {
        int (*finalize_features)(struct virtio_device *vdev);
        const char *(*bus_name)(struct virtio_device *vdev);
        int (*set_vq_affinity)(struct virtqueue *vq, int cpu);
+       const struct cpumask *(*get_vq_affinity)(struct virtio_device *vdev,
+                       int index);
 };
 
 /* If driver didn't advertise the feature, it will never appear. */