18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 28c2ecf20Sopenharmony_ci#ifndef _DRIVERS_VIRTIO_VIRTIO_PCI_COMMON_H 38c2ecf20Sopenharmony_ci#define _DRIVERS_VIRTIO_VIRTIO_PCI_COMMON_H 48c2ecf20Sopenharmony_ci/* 58c2ecf20Sopenharmony_ci * Virtio PCI driver - APIs for common functionality for all device versions 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * This module allows virtio devices to be used over a virtual PCI device. 88c2ecf20Sopenharmony_ci * This can be used with QEMU based VMMs like KVM or Xen. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Copyright IBM Corp. 2007 118c2ecf20Sopenharmony_ci * Copyright Red Hat, Inc. 2014 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * Authors: 148c2ecf20Sopenharmony_ci * Anthony Liguori <aliguori@us.ibm.com> 158c2ecf20Sopenharmony_ci * Rusty Russell <rusty@rustcorp.com.au> 168c2ecf20Sopenharmony_ci * Michael S. Tsirkin <mst@redhat.com> 178c2ecf20Sopenharmony_ci */ 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include <linux/module.h> 208c2ecf20Sopenharmony_ci#include <linux/list.h> 218c2ecf20Sopenharmony_ci#include <linux/pci.h> 228c2ecf20Sopenharmony_ci#include <linux/slab.h> 238c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 248c2ecf20Sopenharmony_ci#include <linux/virtio.h> 258c2ecf20Sopenharmony_ci#include <linux/virtio_config.h> 268c2ecf20Sopenharmony_ci#include <linux/virtio_ring.h> 278c2ecf20Sopenharmony_ci#include <linux/virtio_pci.h> 288c2ecf20Sopenharmony_ci#include <linux/highmem.h> 298c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistruct virtio_pci_vq_info { 328c2ecf20Sopenharmony_ci /* the actual virtqueue */ 338c2ecf20Sopenharmony_ci struct virtqueue *vq; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci /* the list node for the virtqueues list */ 368c2ecf20Sopenharmony_ci struct list_head node; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci /* MSI-X vector (or none) */ 398c2ecf20Sopenharmony_ci unsigned msix_vector; 408c2ecf20Sopenharmony_ci}; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* Our device structure */ 438c2ecf20Sopenharmony_cistruct virtio_pci_device { 448c2ecf20Sopenharmony_ci struct virtio_device vdev; 458c2ecf20Sopenharmony_ci struct pci_dev *pci_dev; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci /* In legacy mode, these two point to within ->legacy. */ 488c2ecf20Sopenharmony_ci /* Where to read and clear interrupt */ 498c2ecf20Sopenharmony_ci u8 __iomem *isr; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci /* Modern only fields */ 528c2ecf20Sopenharmony_ci /* The IO mapping for the PCI config space (non-legacy mode) */ 538c2ecf20Sopenharmony_ci struct virtio_pci_common_cfg __iomem *common; 548c2ecf20Sopenharmony_ci /* Device-specific data (non-legacy mode) */ 558c2ecf20Sopenharmony_ci void __iomem *device; 568c2ecf20Sopenharmony_ci /* Base of vq notifications (non-legacy mode). */ 578c2ecf20Sopenharmony_ci void __iomem *notify_base; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci /* So we can sanity-check accesses. */ 608c2ecf20Sopenharmony_ci size_t notify_len; 618c2ecf20Sopenharmony_ci size_t device_len; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci /* Capability for when we need to map notifications per-vq. */ 648c2ecf20Sopenharmony_ci int notify_map_cap; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci /* Multiply queue_notify_off by this value. (non-legacy mode). */ 678c2ecf20Sopenharmony_ci u32 notify_offset_multiplier; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci int modern_bars; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci /* Legacy only field */ 728c2ecf20Sopenharmony_ci /* the IO mapping for the PCI config space */ 738c2ecf20Sopenharmony_ci void __iomem *ioaddr; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci /* a list of queues so we can dispatch IRQs */ 768c2ecf20Sopenharmony_ci spinlock_t lock; 778c2ecf20Sopenharmony_ci struct list_head virtqueues; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci /* array of all queues for house-keeping */ 808c2ecf20Sopenharmony_ci struct virtio_pci_vq_info **vqs; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci /* MSI-X support */ 838c2ecf20Sopenharmony_ci int msix_enabled; 848c2ecf20Sopenharmony_ci int intx_enabled; 858c2ecf20Sopenharmony_ci cpumask_var_t *msix_affinity_masks; 868c2ecf20Sopenharmony_ci /* Name strings for interrupts. This size should be enough, 878c2ecf20Sopenharmony_ci * and I'm too lazy to allocate each name separately. */ 888c2ecf20Sopenharmony_ci char (*msix_names)[256]; 898c2ecf20Sopenharmony_ci /* Number of available vectors */ 908c2ecf20Sopenharmony_ci unsigned msix_vectors; 918c2ecf20Sopenharmony_ci /* Vectors allocated, excluding per-vq vectors if any */ 928c2ecf20Sopenharmony_ci unsigned msix_used_vectors; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci /* Whether we have vector per vq */ 958c2ecf20Sopenharmony_ci bool per_vq_vectors; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci struct virtqueue *(*setup_vq)(struct virtio_pci_device *vp_dev, 988c2ecf20Sopenharmony_ci struct virtio_pci_vq_info *info, 998c2ecf20Sopenharmony_ci unsigned idx, 1008c2ecf20Sopenharmony_ci void (*callback)(struct virtqueue *vq), 1018c2ecf20Sopenharmony_ci const char *name, 1028c2ecf20Sopenharmony_ci bool ctx, 1038c2ecf20Sopenharmony_ci u16 msix_vec); 1048c2ecf20Sopenharmony_ci void (*del_vq)(struct virtio_pci_vq_info *info); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci u16 (*config_vector)(struct virtio_pci_device *vp_dev, u16 vector); 1078c2ecf20Sopenharmony_ci}; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci/* Constants for MSI-X */ 1108c2ecf20Sopenharmony_ci/* Use first vector for configuration changes, second and the rest for 1118c2ecf20Sopenharmony_ci * virtqueues Thus, we need at least 2 vectors for MSI. */ 1128c2ecf20Sopenharmony_cienum { 1138c2ecf20Sopenharmony_ci VP_MSIX_CONFIG_VECTOR = 0, 1148c2ecf20Sopenharmony_ci VP_MSIX_VQ_VECTOR = 1, 1158c2ecf20Sopenharmony_ci}; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci/* Convert a generic virtio device to our structure */ 1188c2ecf20Sopenharmony_cistatic struct virtio_pci_device *to_vp_device(struct virtio_device *vdev) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci return container_of(vdev, struct virtio_pci_device, vdev); 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci/* wait for pending irq handlers */ 1248c2ecf20Sopenharmony_civoid vp_synchronize_vectors(struct virtio_device *vdev); 1258c2ecf20Sopenharmony_ci/* the notify function used when creating a virt queue */ 1268c2ecf20Sopenharmony_cibool vp_notify(struct virtqueue *vq); 1278c2ecf20Sopenharmony_ci/* the config->del_vqs() implementation */ 1288c2ecf20Sopenharmony_civoid vp_del_vqs(struct virtio_device *vdev); 1298c2ecf20Sopenharmony_ci/* the config->find_vqs() implementation */ 1308c2ecf20Sopenharmony_ciint vp_find_vqs(struct virtio_device *vdev, unsigned nvqs, 1318c2ecf20Sopenharmony_ci struct virtqueue *vqs[], vq_callback_t *callbacks[], 1328c2ecf20Sopenharmony_ci const char * const names[], const bool *ctx, 1338c2ecf20Sopenharmony_ci struct irq_affinity *desc); 1348c2ecf20Sopenharmony_ciconst char *vp_bus_name(struct virtio_device *vdev); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci/* Setup the affinity for a virtqueue: 1378c2ecf20Sopenharmony_ci * - force the affinity for per vq vector 1388c2ecf20Sopenharmony_ci * - OR over all affinities for shared MSI 1398c2ecf20Sopenharmony_ci * - ignore the affinity request if we're using INTX 1408c2ecf20Sopenharmony_ci */ 1418c2ecf20Sopenharmony_ciint vp_set_vq_affinity(struct virtqueue *vq, const struct cpumask *cpu_mask); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ciconst struct cpumask *vp_get_vq_affinity(struct virtio_device *vdev, int index); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_VIRTIO_PCI_LEGACY) 1468c2ecf20Sopenharmony_ciint virtio_pci_legacy_probe(struct virtio_pci_device *); 1478c2ecf20Sopenharmony_civoid virtio_pci_legacy_remove(struct virtio_pci_device *); 1488c2ecf20Sopenharmony_ci#else 1498c2ecf20Sopenharmony_cistatic inline int virtio_pci_legacy_probe(struct virtio_pci_device *vp_dev) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci return -ENODEV; 1528c2ecf20Sopenharmony_ci} 1538c2ecf20Sopenharmony_cistatic inline void virtio_pci_legacy_remove(struct virtio_pci_device *vp_dev) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci#endif 1578c2ecf20Sopenharmony_ciint virtio_pci_modern_probe(struct virtio_pci_device *); 1588c2ecf20Sopenharmony_civoid virtio_pci_modern_remove(struct virtio_pci_device *); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci#endif 161