Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 #ifndef _DRIVERS_VIRTIO_VIRTIO_PCI_COMMON_H
0003 #define _DRIVERS_VIRTIO_VIRTIO_PCI_COMMON_H
0004 /*
0005  * Virtio PCI driver - APIs for common functionality for all device versions
0006  *
0007  * This module allows virtio devices to be used over a virtual PCI device.
0008  * This can be used with QEMU based VMMs like KVM or Xen.
0009  *
0010  * Copyright IBM Corp. 2007
0011  * Copyright Red Hat, Inc. 2014
0012  *
0013  * Authors:
0014  *  Anthony Liguori  <aliguori@us.ibm.com>
0015  *  Rusty Russell <rusty@rustcorp.com.au>
0016  *  Michael S. Tsirkin <mst@redhat.com>
0017  */
0018 
0019 #include <linux/module.h>
0020 #include <linux/list.h>
0021 #include <linux/pci.h>
0022 #include <linux/slab.h>
0023 #include <linux/interrupt.h>
0024 #include <linux/virtio.h>
0025 #include <linux/virtio_config.h>
0026 #include <linux/virtio_ring.h>
0027 #include <linux/virtio_pci.h>
0028 #include <linux/virtio_pci_legacy.h>
0029 #include <linux/virtio_pci_modern.h>
0030 #include <linux/highmem.h>
0031 #include <linux/spinlock.h>
0032 
0033 struct virtio_pci_vq_info {
0034     /* the actual virtqueue */
0035     struct virtqueue *vq;
0036 
0037     /* the list node for the virtqueues list */
0038     struct list_head node;
0039 
0040     /* MSI-X vector (or none) */
0041     unsigned int msix_vector;
0042 };
0043 
0044 /* Our device structure */
0045 struct virtio_pci_device {
0046     struct virtio_device vdev;
0047     struct pci_dev *pci_dev;
0048     struct virtio_pci_legacy_device ldev;
0049     struct virtio_pci_modern_device mdev;
0050 
0051     bool is_legacy;
0052 
0053     /* Where to read and clear interrupt */
0054     u8 __iomem *isr;
0055 
0056     /* a list of queues so we can dispatch IRQs */
0057     spinlock_t lock;
0058     struct list_head virtqueues;
0059 
0060     /* array of all queues for house-keeping */
0061     struct virtio_pci_vq_info **vqs;
0062 
0063     /* MSI-X support */
0064     int msix_enabled;
0065     int intx_enabled;
0066     cpumask_var_t *msix_affinity_masks;
0067     /* Name strings for interrupts. This size should be enough,
0068      * and I'm too lazy to allocate each name separately. */
0069     char (*msix_names)[256];
0070     /* Number of available vectors */
0071     unsigned int msix_vectors;
0072     /* Vectors allocated, excluding per-vq vectors if any */
0073     unsigned int msix_used_vectors;
0074 
0075     /* Whether we have vector per vq */
0076     bool per_vq_vectors;
0077 
0078     struct virtqueue *(*setup_vq)(struct virtio_pci_device *vp_dev,
0079                       struct virtio_pci_vq_info *info,
0080                       unsigned int idx,
0081                       void (*callback)(struct virtqueue *vq),
0082                       const char *name,
0083                       bool ctx,
0084                       u16 msix_vec);
0085     void (*del_vq)(struct virtio_pci_vq_info *info);
0086 
0087     u16 (*config_vector)(struct virtio_pci_device *vp_dev, u16 vector);
0088 };
0089 
0090 /* Constants for MSI-X */
0091 /* Use first vector for configuration changes, second and the rest for
0092  * virtqueues Thus, we need at least 2 vectors for MSI. */
0093 enum {
0094     VP_MSIX_CONFIG_VECTOR = 0,
0095     VP_MSIX_VQ_VECTOR = 1,
0096 };
0097 
0098 /* Convert a generic virtio device to our structure */
0099 static struct virtio_pci_device *to_vp_device(struct virtio_device *vdev)
0100 {
0101     return container_of(vdev, struct virtio_pci_device, vdev);
0102 }
0103 
0104 /* wait for pending irq handlers */
0105 void vp_synchronize_vectors(struct virtio_device *vdev);
0106 /* the notify function used when creating a virt queue */
0107 bool vp_notify(struct virtqueue *vq);
0108 /* the config->del_vqs() implementation */
0109 void vp_del_vqs(struct virtio_device *vdev);
0110 /* the config->find_vqs() implementation */
0111 int vp_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
0112         struct virtqueue *vqs[], vq_callback_t *callbacks[],
0113         const char * const names[], const bool *ctx,
0114         struct irq_affinity *desc);
0115 const char *vp_bus_name(struct virtio_device *vdev);
0116 
0117 /* Setup the affinity for a virtqueue:
0118  * - force the affinity for per vq vector
0119  * - OR over all affinities for shared MSI
0120  * - ignore the affinity request if we're using INTX
0121  */
0122 int vp_set_vq_affinity(struct virtqueue *vq, const struct cpumask *cpu_mask);
0123 
0124 const struct cpumask *vp_get_vq_affinity(struct virtio_device *vdev, int index);
0125 
0126 #if IS_ENABLED(CONFIG_VIRTIO_PCI_LEGACY)
0127 int virtio_pci_legacy_probe(struct virtio_pci_device *);
0128 void virtio_pci_legacy_remove(struct virtio_pci_device *);
0129 #else
0130 static inline int virtio_pci_legacy_probe(struct virtio_pci_device *vp_dev)
0131 {
0132     return -ENODEV;
0133 }
0134 static inline void virtio_pci_legacy_remove(struct virtio_pci_device *vp_dev)
0135 {
0136 }
0137 #endif
0138 int virtio_pci_modern_probe(struct virtio_pci_device *);
0139 void virtio_pci_modern_remove(struct virtio_pci_device *);
0140 
0141 #endif