15f4c9760SMichael S. Tsirkin #ifndef _DRIVERS_VIRTIO_VIRTIO_PCI_COMMON_H 25f4c9760SMichael S. Tsirkin #define _DRIVERS_VIRTIO_VIRTIO_PCI_COMMON_H 35f4c9760SMichael S. Tsirkin /* 45f4c9760SMichael S. Tsirkin * Virtio PCI driver - APIs for common functionality for all device versions 55f4c9760SMichael S. Tsirkin * 65f4c9760SMichael S. Tsirkin * This module allows virtio devices to be used over a virtual PCI device. 75f4c9760SMichael S. Tsirkin * This can be used with QEMU based VMMs like KVM or Xen. 85f4c9760SMichael S. Tsirkin * 95f4c9760SMichael S. Tsirkin * Copyright IBM Corp. 2007 105f4c9760SMichael S. Tsirkin * Copyright Red Hat, Inc. 2014 115f4c9760SMichael S. Tsirkin * 125f4c9760SMichael S. Tsirkin * Authors: 135f4c9760SMichael S. Tsirkin * Anthony Liguori <aliguori@us.ibm.com> 145f4c9760SMichael S. Tsirkin * Rusty Russell <rusty@rustcorp.com.au> 155f4c9760SMichael S. Tsirkin * Michael S. Tsirkin <mst@redhat.com> 165f4c9760SMichael S. Tsirkin * 175f4c9760SMichael S. Tsirkin * This work is licensed under the terms of the GNU GPL, version 2 or later. 185f4c9760SMichael S. Tsirkin * See the COPYING file in the top-level directory. 195f4c9760SMichael S. Tsirkin * 205f4c9760SMichael S. Tsirkin */ 215f4c9760SMichael S. Tsirkin 225f4c9760SMichael S. Tsirkin #include <linux/module.h> 235f4c9760SMichael S. Tsirkin #include <linux/list.h> 245f4c9760SMichael S. Tsirkin #include <linux/pci.h> 255f4c9760SMichael S. Tsirkin #include <linux/slab.h> 265f4c9760SMichael S. Tsirkin #include <linux/interrupt.h> 275f4c9760SMichael S. Tsirkin #include <linux/virtio.h> 285f4c9760SMichael S. Tsirkin #include <linux/virtio_config.h> 295f4c9760SMichael S. Tsirkin #include <linux/virtio_ring.h> 305f4c9760SMichael S. Tsirkin #include <linux/virtio_pci.h> 315f4c9760SMichael S. Tsirkin #include <linux/highmem.h> 325f4c9760SMichael S. Tsirkin #include <linux/spinlock.h> 335f4c9760SMichael S. Tsirkin 34*0a9b3f47SMichael S. Tsirkin struct virtio_pci_vq_info { 35*0a9b3f47SMichael S. Tsirkin /* the actual virtqueue */ 36*0a9b3f47SMichael S. Tsirkin struct virtqueue *vq; 37*0a9b3f47SMichael S. Tsirkin 38*0a9b3f47SMichael S. Tsirkin /* the list node for the virtqueues list */ 39*0a9b3f47SMichael S. Tsirkin struct list_head node; 40*0a9b3f47SMichael S. Tsirkin 41*0a9b3f47SMichael S. Tsirkin /* MSI-X vector (or none) */ 42*0a9b3f47SMichael S. Tsirkin unsigned msix_vector; 43*0a9b3f47SMichael S. Tsirkin }; 44*0a9b3f47SMichael S. Tsirkin 455f4c9760SMichael S. Tsirkin /* Our device structure */ 465f4c9760SMichael S. Tsirkin struct virtio_pci_device { 475f4c9760SMichael S. Tsirkin struct virtio_device vdev; 485f4c9760SMichael S. Tsirkin struct pci_dev *pci_dev; 495f4c9760SMichael S. Tsirkin 501fcf0512SMichael S. Tsirkin /* In legacy mode, these two point to within ->legacy. */ 511fcf0512SMichael S. Tsirkin /* Where to read and clear interrupt */ 521fcf0512SMichael S. Tsirkin u8 __iomem *isr; 531fcf0512SMichael S. Tsirkin 541fcf0512SMichael S. Tsirkin /* Modern only fields */ 551fcf0512SMichael S. Tsirkin /* The IO mapping for the PCI config space (non-legacy mode) */ 561fcf0512SMichael S. Tsirkin struct virtio_pci_common_cfg __iomem *common; 571fcf0512SMichael S. Tsirkin /* Device-specific data (non-legacy mode) */ 581fcf0512SMichael S. Tsirkin void __iomem *device; 593909213cSMichael S. Tsirkin /* Base of vq notifications (non-legacy mode). */ 603909213cSMichael S. Tsirkin void __iomem *notify_base; 611fcf0512SMichael S. Tsirkin 621fcf0512SMichael S. Tsirkin /* So we can sanity-check accesses. */ 633909213cSMichael S. Tsirkin size_t notify_len; 641fcf0512SMichael S. Tsirkin size_t device_len; 651fcf0512SMichael S. Tsirkin 661fcf0512SMichael S. Tsirkin /* Capability for when we need to map notifications per-vq. */ 671fcf0512SMichael S. Tsirkin int notify_map_cap; 681fcf0512SMichael S. Tsirkin 691fcf0512SMichael S. Tsirkin /* Multiply queue_notify_off by this value. (non-legacy mode). */ 701fcf0512SMichael S. Tsirkin u32 notify_offset_multiplier; 711fcf0512SMichael S. Tsirkin 7259a5b0f7SGerd Hoffmann int modern_bars; 7359a5b0f7SGerd Hoffmann 741fcf0512SMichael S. Tsirkin /* Legacy only field */ 755f4c9760SMichael S. Tsirkin /* the IO mapping for the PCI config space */ 765f4c9760SMichael S. Tsirkin void __iomem *ioaddr; 775f4c9760SMichael S. Tsirkin 78*0a9b3f47SMichael S. Tsirkin /* a list of queues so we can dispatch IRQs */ 79*0a9b3f47SMichael S. Tsirkin spinlock_t lock; 80*0a9b3f47SMichael S. Tsirkin struct list_head virtqueues; 81*0a9b3f47SMichael S. Tsirkin 82*0a9b3f47SMichael S. Tsirkin /* array of all queues for house-keeping */ 83*0a9b3f47SMichael S. Tsirkin struct virtio_pci_vq_info **vqs; 84*0a9b3f47SMichael S. Tsirkin 852008c154SMichael S. Tsirkin /* MSI-X support */ 862008c154SMichael S. Tsirkin int msix_enabled; 870b0f9dc5SMichael S. Tsirkin int intx_enabled; 885f4c9760SMichael S. Tsirkin cpumask_var_t *msix_affinity_masks; 895f4c9760SMichael S. Tsirkin /* Name strings for interrupts. This size should be enough, 905f4c9760SMichael S. Tsirkin * and I'm too lazy to allocate each name separately. */ 915f4c9760SMichael S. Tsirkin char (*msix_names)[256]; 920b0f9dc5SMichael S. Tsirkin /* Number of available vectors */ 930b0f9dc5SMichael S. Tsirkin unsigned msix_vectors; 940b0f9dc5SMichael S. Tsirkin /* Vectors allocated, excluding per-vq vectors if any */ 950b0f9dc5SMichael S. Tsirkin unsigned msix_used_vectors; 960b0f9dc5SMichael S. Tsirkin 97*0a9b3f47SMichael S. Tsirkin /* Whether we have vector per vq */ 98*0a9b3f47SMichael S. Tsirkin bool per_vq_vectors; 995f4c9760SMichael S. Tsirkin 1005f4c9760SMichael S. Tsirkin struct virtqueue *(*setup_vq)(struct virtio_pci_device *vp_dev, 101*0a9b3f47SMichael S. Tsirkin struct virtio_pci_vq_info *info, 1025f4c9760SMichael S. Tsirkin unsigned idx, 1035f4c9760SMichael S. Tsirkin void (*callback)(struct virtqueue *vq), 1045f4c9760SMichael S. Tsirkin const char *name, 1055f4c9760SMichael S. Tsirkin u16 msix_vec); 106*0a9b3f47SMichael S. Tsirkin void (*del_vq)(struct virtio_pci_vq_info *info); 1075f4c9760SMichael S. Tsirkin 1085f4c9760SMichael S. Tsirkin u16 (*config_vector)(struct virtio_pci_device *vp_dev, u16 vector); 1095f4c9760SMichael S. Tsirkin }; 1105f4c9760SMichael S. Tsirkin 1110b0f9dc5SMichael S. Tsirkin /* Constants for MSI-X */ 1120b0f9dc5SMichael S. Tsirkin /* Use first vector for configuration changes, second and the rest for 1130b0f9dc5SMichael S. Tsirkin * virtqueues Thus, we need at least 2 vectors for MSI. */ 1140b0f9dc5SMichael S. Tsirkin enum { 1150b0f9dc5SMichael S. Tsirkin VP_MSIX_CONFIG_VECTOR = 0, 1160b0f9dc5SMichael S. Tsirkin VP_MSIX_VQ_VECTOR = 1, 1170b0f9dc5SMichael S. Tsirkin }; 1180b0f9dc5SMichael S. Tsirkin 1195f4c9760SMichael S. Tsirkin /* Convert a generic virtio device to our structure */ 1205f4c9760SMichael S. Tsirkin static struct virtio_pci_device *to_vp_device(struct virtio_device *vdev) 1215f4c9760SMichael S. Tsirkin { 1225f4c9760SMichael S. Tsirkin return container_of(vdev, struct virtio_pci_device, vdev); 1235f4c9760SMichael S. Tsirkin } 1245f4c9760SMichael S. Tsirkin 1255f4c9760SMichael S. Tsirkin /* wait for pending irq handlers */ 1265f4c9760SMichael S. Tsirkin void vp_synchronize_vectors(struct virtio_device *vdev); 1275f4c9760SMichael S. Tsirkin /* the notify function used when creating a virt queue */ 1285f4c9760SMichael S. Tsirkin bool vp_notify(struct virtqueue *vq); 1295f4c9760SMichael S. Tsirkin /* the config->del_vqs() implementation */ 1305f4c9760SMichael S. Tsirkin void vp_del_vqs(struct virtio_device *vdev); 1315f4c9760SMichael S. Tsirkin /* the config->find_vqs() implementation */ 1325f4c9760SMichael S. Tsirkin int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs, 133fb5e31d9SChristoph Hellwig struct virtqueue *vqs[], vq_callback_t *callbacks[], 134fb5e31d9SChristoph Hellwig const char * const names[], struct irq_affinity *desc); 1355f4c9760SMichael S. Tsirkin const char *vp_bus_name(struct virtio_device *vdev); 1365f4c9760SMichael S. Tsirkin 1375f4c9760SMichael S. Tsirkin /* Setup the affinity for a virtqueue: 1385f4c9760SMichael S. Tsirkin * - force the affinity for per vq vector 1395f4c9760SMichael S. Tsirkin * - OR over all affinities for shared MSI 1405f4c9760SMichael S. Tsirkin * - ignore the affinity request if we're using INTX 1415f4c9760SMichael S. Tsirkin */ 1425f4c9760SMichael S. Tsirkin int vp_set_vq_affinity(struct virtqueue *vq, int cpu); 1435f4c9760SMichael S. Tsirkin 144bbaba479SChristoph Hellwig const struct cpumask *vp_get_vq_affinity(struct virtio_device *vdev, int index); 145bbaba479SChristoph Hellwig 14646506da5SMichael S. Tsirkin #if IS_ENABLED(CONFIG_VIRTIO_PCI_LEGACY) 147ff31d2e2SMichael S. Tsirkin int virtio_pci_legacy_probe(struct virtio_pci_device *); 148ff31d2e2SMichael S. Tsirkin void virtio_pci_legacy_remove(struct virtio_pci_device *); 14946506da5SMichael S. Tsirkin #else 15046506da5SMichael S. Tsirkin static inline int virtio_pci_legacy_probe(struct virtio_pci_device *vp_dev) 15146506da5SMichael S. Tsirkin { 15246506da5SMichael S. Tsirkin return -ENODEV; 15346506da5SMichael S. Tsirkin } 15446506da5SMichael S. Tsirkin static inline void virtio_pci_legacy_remove(struct virtio_pci_device *vp_dev) 15546506da5SMichael S. Tsirkin { 15646506da5SMichael S. Tsirkin } 15746506da5SMichael S. Tsirkin #endif 1581fcf0512SMichael S. Tsirkin int virtio_pci_modern_probe(struct virtio_pci_device *); 1591fcf0512SMichael S. Tsirkin void virtio_pci_modern_remove(struct virtio_pci_device *); 1605f4c9760SMichael S. Tsirkin 1615f4c9760SMichael S. Tsirkin #endif 162