Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 : : #ifndef _DRIVERS_VIRTIO_VIRTIO_PCI_COMMON_H 3 : : #define _DRIVERS_VIRTIO_VIRTIO_PCI_COMMON_H 4 : : /* 5 : : * Virtio PCI driver - APIs for common functionality for all device versions 6 : : * 7 : : * This module allows virtio devices to be used over a virtual PCI device. 8 : : * This can be used with QEMU based VMMs like KVM or Xen. 9 : : * 10 : : * Copyright IBM Corp. 2007 11 : : * Copyright Red Hat, Inc. 2014 12 : : * 13 : : * Authors: 14 : : * Anthony Liguori <aliguori@us.ibm.com> 15 : : * Rusty Russell <rusty@rustcorp.com.au> 16 : : * Michael S. Tsirkin <mst@redhat.com> 17 : : */ 18 : : 19 : : #include <linux/module.h> 20 : : #include <linux/list.h> 21 : : #include <linux/pci.h> 22 : : #include <linux/slab.h> 23 : : #include <linux/interrupt.h> 24 : : #include <linux/virtio.h> 25 : : #include <linux/virtio_config.h> 26 : : #include <linux/virtio_ring.h> 27 : : #include <linux/virtio_pci.h> 28 : : #include <linux/highmem.h> 29 : : #include <linux/spinlock.h> 30 : : 31 : : struct virtio_pci_vq_info { 32 : : /* the actual virtqueue */ 33 : : struct virtqueue *vq; 34 : : 35 : : /* the list node for the virtqueues list */ 36 : : struct list_head node; 37 : : 38 : : /* MSI-X vector (or none) */ 39 : : unsigned msix_vector; 40 : : }; 41 : : 42 : : /* Our device structure */ 43 : : struct virtio_pci_device { 44 : : struct virtio_device vdev; 45 : : struct pci_dev *pci_dev; 46 : : 47 : : /* In legacy mode, these two point to within ->legacy. */ 48 : : /* Where to read and clear interrupt */ 49 : : u8 __iomem *isr; 50 : : 51 : : /* Modern only fields */ 52 : : /* The IO mapping for the PCI config space (non-legacy mode) */ 53 : : struct virtio_pci_common_cfg __iomem *common; 54 : : /* Device-specific data (non-legacy mode) */ 55 : : void __iomem *device; 56 : : /* Base of vq notifications (non-legacy mode). */ 57 : : void __iomem *notify_base; 58 : : 59 : : /* So we can sanity-check accesses. */ 60 : : size_t notify_len; 61 : : size_t device_len; 62 : : 63 : : /* Capability for when we need to map notifications per-vq. */ 64 : : int notify_map_cap; 65 : : 66 : : /* Multiply queue_notify_off by this value. (non-legacy mode). */ 67 : : u32 notify_offset_multiplier; 68 : : 69 : : int modern_bars; 70 : : 71 : : /* Legacy only field */ 72 : : /* the IO mapping for the PCI config space */ 73 : : void __iomem *ioaddr; 74 : : 75 : : /* a list of queues so we can dispatch IRQs */ 76 : : spinlock_t lock; 77 : : struct list_head virtqueues; 78 : : 79 : : /* array of all queues for house-keeping */ 80 : : struct virtio_pci_vq_info **vqs; 81 : : 82 : : /* MSI-X support */ 83 : : int msix_enabled; 84 : : int intx_enabled; 85 : : cpumask_var_t *msix_affinity_masks; 86 : : /* Name strings for interrupts. This size should be enough, 87 : : * and I'm too lazy to allocate each name separately. */ 88 : : char (*msix_names)[256]; 89 : : /* Number of available vectors */ 90 : : unsigned msix_vectors; 91 : : /* Vectors allocated, excluding per-vq vectors if any */ 92 : : unsigned msix_used_vectors; 93 : : 94 : : /* Whether we have vector per vq */ 95 : : bool per_vq_vectors; 96 : : 97 : : struct virtqueue *(*setup_vq)(struct virtio_pci_device *vp_dev, 98 : : struct virtio_pci_vq_info *info, 99 : : unsigned idx, 100 : : void (*callback)(struct virtqueue *vq), 101 : : const char *name, 102 : : bool ctx, 103 : : u16 msix_vec); 104 : : void (*del_vq)(struct virtio_pci_vq_info *info); 105 : : 106 : : u16 (*config_vector)(struct virtio_pci_device *vp_dev, u16 vector); 107 : : }; 108 : : 109 : : /* Constants for MSI-X */ 110 : : /* Use first vector for configuration changes, second and the rest for 111 : : * virtqueues Thus, we need at least 2 vectors for MSI. */ 112 : : enum { 113 : : VP_MSIX_CONFIG_VECTOR = 0, 114 : : VP_MSIX_VQ_VECTOR = 1, 115 : : }; 116 : : 117 : : /* Convert a generic virtio device to our structure */ 118 : 0 : static struct virtio_pci_device *to_vp_device(struct virtio_device *vdev) 119 : : { 120 [ # # # # : 0 : return container_of(vdev, struct virtio_pci_device, vdev); # # # # # # ] 121 : : } 122 : : 123 : : /* wait for pending irq handlers */ 124 : : void vp_synchronize_vectors(struct virtio_device *vdev); 125 : : /* the notify function used when creating a virt queue */ 126 : : bool vp_notify(struct virtqueue *vq); 127 : : /* the config->del_vqs() implementation */ 128 : : void vp_del_vqs(struct virtio_device *vdev); 129 : : /* the config->find_vqs() implementation */ 130 : : int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs, 131 : : struct virtqueue *vqs[], vq_callback_t *callbacks[], 132 : : const char * const names[], const bool *ctx, 133 : : struct irq_affinity *desc); 134 : : const char *vp_bus_name(struct virtio_device *vdev); 135 : : 136 : : /* Setup the affinity for a virtqueue: 137 : : * - force the affinity for per vq vector 138 : : * - OR over all affinities for shared MSI 139 : : * - ignore the affinity request if we're using INTX 140 : : */ 141 : : int vp_set_vq_affinity(struct virtqueue *vq, const struct cpumask *cpu_mask); 142 : : 143 : : const struct cpumask *vp_get_vq_affinity(struct virtio_device *vdev, int index); 144 : : 145 : : #if IS_ENABLED(CONFIG_VIRTIO_PCI_LEGACY) 146 : : int virtio_pci_legacy_probe(struct virtio_pci_device *); 147 : : void virtio_pci_legacy_remove(struct virtio_pci_device *); 148 : : #else 149 : : static inline int virtio_pci_legacy_probe(struct virtio_pci_device *vp_dev) 150 : : { 151 : : return -ENODEV; 152 : : } 153 : : static inline void virtio_pci_legacy_remove(struct virtio_pci_device *vp_dev) 154 : : { 155 : : } 156 : : #endif 157 : : int virtio_pci_modern_probe(struct virtio_pci_device *); 158 : : void virtio_pci_modern_remove(struct virtio_pci_device *); 159 : : 160 : : #endif