1f33f5fe2SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
25f4c9760SMichael S. Tsirkin #ifndef _DRIVERS_VIRTIO_VIRTIO_PCI_COMMON_H
35f4c9760SMichael S. Tsirkin #define _DRIVERS_VIRTIO_VIRTIO_PCI_COMMON_H
45f4c9760SMichael S. Tsirkin /*
55f4c9760SMichael S. Tsirkin * Virtio PCI driver - APIs for common functionality for all device versions
65f4c9760SMichael S. Tsirkin *
75f4c9760SMichael S. Tsirkin * This module allows virtio devices to be used over a virtual PCI device.
85f4c9760SMichael S. Tsirkin * This can be used with QEMU based VMMs like KVM or Xen.
95f4c9760SMichael S. Tsirkin *
105f4c9760SMichael S. Tsirkin * Copyright IBM Corp. 2007
115f4c9760SMichael S. Tsirkin * Copyright Red Hat, Inc. 2014
125f4c9760SMichael S. Tsirkin *
135f4c9760SMichael S. Tsirkin * Authors:
145f4c9760SMichael S. Tsirkin * Anthony Liguori <aliguori@us.ibm.com>
155f4c9760SMichael S. Tsirkin * Rusty Russell <rusty@rustcorp.com.au>
165f4c9760SMichael S. Tsirkin * Michael S. Tsirkin <mst@redhat.com>
175f4c9760SMichael S. Tsirkin */
185f4c9760SMichael S. Tsirkin
195f4c9760SMichael S. Tsirkin #include <linux/module.h>
205f4c9760SMichael S. Tsirkin #include <linux/list.h>
215f4c9760SMichael S. Tsirkin #include <linux/pci.h>
225f4c9760SMichael S. Tsirkin #include <linux/slab.h>
235f4c9760SMichael S. Tsirkin #include <linux/interrupt.h>
245f4c9760SMichael S. Tsirkin #include <linux/virtio.h>
255f4c9760SMichael S. Tsirkin #include <linux/virtio_config.h>
265f4c9760SMichael S. Tsirkin #include <linux/virtio_ring.h>
275f4c9760SMichael S. Tsirkin #include <linux/virtio_pci.h>
28d89c8169SWu Zongyong #include <linux/virtio_pci_legacy.h>
29fd502729SJason Wang #include <linux/virtio_pci_modern.h>
305f4c9760SMichael S. Tsirkin #include <linux/highmem.h>
315f4c9760SMichael S. Tsirkin #include <linux/spinlock.h>
3292792ac7SFeng Liu #include <linux/mutex.h>
335f4c9760SMichael S. Tsirkin
340a9b3f47SMichael S. Tsirkin struct virtio_pci_vq_info {
350a9b3f47SMichael S. Tsirkin /* the actual virtqueue */
360a9b3f47SMichael S. Tsirkin struct virtqueue *vq;
370a9b3f47SMichael S. Tsirkin
3806909a44SJiri Pirko /* the list node for the virtqueues or slow_virtqueues list */
390a9b3f47SMichael S. Tsirkin struct list_head node;
400a9b3f47SMichael S. Tsirkin
410a9b3f47SMichael S. Tsirkin /* MSI-X vector (or none) */
4231532340SSolomon Tan unsigned int msix_vector;
430a9b3f47SMichael S. Tsirkin };
440a9b3f47SMichael S. Tsirkin
45fd27ef6bSFeng Liu struct virtio_pci_admin_vq {
46fd27ef6bSFeng Liu /* Virtqueue info associated with this admin queue. */
47af22bbe1SJiri Pirko struct virtio_pci_vq_info *info;
484c3b54afSJiri Pirko /* Protects virtqueue access. */
494c3b54afSJiri Pirko spinlock_t lock;
50f51e146fSYishai Hadas u64 supported_cmds;
51fd27ef6bSFeng Liu /* Name of the admin queue: avq.$vq_index. */
52fd27ef6bSFeng Liu char name[10];
53fd27ef6bSFeng Liu u16 vq_index;
54fd27ef6bSFeng Liu };
55fd27ef6bSFeng Liu
56b5d58094SJason Wang /* Our device structure */
57b5d58094SJason Wang struct virtio_pci_device {
58b5d58094SJason Wang struct virtio_device vdev;
59b5d58094SJason Wang struct pci_dev *pci_dev;
604f0fc225SFeng Liu union {
61d89c8169SWu Zongyong struct virtio_pci_legacy_device ldev;
62b5d58094SJason Wang struct virtio_pci_modern_device mdev;
634f0fc225SFeng Liu };
64d89c8169SWu Zongyong bool is_legacy;
65d89c8169SWu Zongyong
66b5d58094SJason Wang /* Where to read and clear interrupt */
67b5d58094SJason Wang u8 __iomem *isr;
68b5d58094SJason Wang
6906909a44SJiri Pirko /* Lists of queues and potentially slow path queues
7006909a44SJiri Pirko * so we can dispatch IRQs.
7106909a44SJiri Pirko */
720a9b3f47SMichael S. Tsirkin spinlock_t lock;
730a9b3f47SMichael S. Tsirkin struct list_head virtqueues;
7406909a44SJiri Pirko struct list_head slow_virtqueues;
750a9b3f47SMichael S. Tsirkin
76fd27ef6bSFeng Liu /* Array of all virtqueues reported in the
77fd27ef6bSFeng Liu * PCI common config num_queues field
78fd27ef6bSFeng Liu */
790a9b3f47SMichael S. Tsirkin struct virtio_pci_vq_info **vqs;
800a9b3f47SMichael S. Tsirkin
81fd27ef6bSFeng Liu struct virtio_pci_admin_vq admin_vq;
82fd27ef6bSFeng Liu
832008c154SMichael S. Tsirkin /* MSI-X support */
842008c154SMichael S. Tsirkin int msix_enabled;
850b0f9dc5SMichael S. Tsirkin int intx_enabled;
865f4c9760SMichael S. Tsirkin cpumask_var_t *msix_affinity_masks;
875f4c9760SMichael S. Tsirkin /* Name strings for interrupts. This size should be enough,
885f4c9760SMichael S. Tsirkin * and I'm too lazy to allocate each name separately. */
895f4c9760SMichael S. Tsirkin char (*msix_names)[256];
900b0f9dc5SMichael S. Tsirkin /* Number of available vectors */
9131532340SSolomon Tan unsigned int msix_vectors;
920b0f9dc5SMichael S. Tsirkin /* Vectors allocated, excluding per-vq vectors if any */
9331532340SSolomon Tan unsigned int msix_used_vectors;
940b0f9dc5SMichael S. Tsirkin
950a9b3f47SMichael S. Tsirkin /* Whether we have vector per vq */
960a9b3f47SMichael S. Tsirkin bool per_vq_vectors;
975f4c9760SMichael S. Tsirkin
985f4c9760SMichael S. Tsirkin struct virtqueue *(*setup_vq)(struct virtio_pci_device *vp_dev,
990a9b3f47SMichael S. Tsirkin struct virtio_pci_vq_info *info,
10031532340SSolomon Tan unsigned int idx,
1015f4c9760SMichael S. Tsirkin void (*callback)(struct virtqueue *vq),
1025f4c9760SMichael S. Tsirkin const char *name,
103f94682ddSMichael S. Tsirkin bool ctx,
1045f4c9760SMichael S. Tsirkin u16 msix_vec);
1050a9b3f47SMichael S. Tsirkin void (*del_vq)(struct virtio_pci_vq_info *info);
1065f4c9760SMichael S. Tsirkin
1075f4c9760SMichael S. Tsirkin u16 (*config_vector)(struct virtio_pci_device *vp_dev, u16 vector);
108af22bbe1SJiri Pirko int (*avq_index)(struct virtio_device *vdev, u16 *index, u16 *num);
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 */
to_vp_device(struct virtio_device * vdev)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
125eb4cecb4SJason Wang /* wait for pending irq handlers */
126eb4cecb4SJason Wang 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 */
13231532340SSolomon Tan int vp_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
133ad9a1257SJiri Pirko struct virtqueue *vqs[], struct virtqueue_info vqs_info[],
134f94682ddSMichael S. Tsirkin 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 */
14219e226e8SCaleb Raitto int vp_set_vq_affinity(struct virtqueue *vq, const struct cpumask *cpu_mask);
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
virtio_pci_legacy_probe(struct virtio_pci_device * vp_dev)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 }
virtio_pci_legacy_remove(struct virtio_pci_device * vp_dev)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
161c3fc3e09SYishai Hadas struct virtio_device *virtio_pci_vf_get_pf_dev(struct pci_dev *pdev);
162c3fc3e09SYishai Hadas
163f51e146fSYishai Hadas #define VIRTIO_LEGACY_ADMIN_CMD_BITMAP \
164f51e146fSYishai Hadas (BIT_ULL(VIRTIO_ADMIN_CMD_LEGACY_COMMON_CFG_WRITE) | \
165f51e146fSYishai Hadas BIT_ULL(VIRTIO_ADMIN_CMD_LEGACY_COMMON_CFG_READ) | \
166f51e146fSYishai Hadas BIT_ULL(VIRTIO_ADMIN_CMD_LEGACY_DEV_CFG_WRITE) | \
167f51e146fSYishai Hadas BIT_ULL(VIRTIO_ADMIN_CMD_LEGACY_DEV_CFG_READ) | \
168f51e146fSYishai Hadas BIT_ULL(VIRTIO_ADMIN_CMD_LEGACY_NOTIFY_INFO))
169f51e146fSYishai Hadas
170f51e146fSYishai Hadas /* Unlike modern drivers which support hardware virtio devices, legacy drivers
171f51e146fSYishai Hadas * assume software-based devices: e.g. they don't use proper memory barriers
172f51e146fSYishai Hadas * on ARM, use big endian on PPC, etc. X86 drivers are mostly ok though, more
173f51e146fSYishai Hadas * or less by chance. For now, only support legacy IO on X86.
174f51e146fSYishai Hadas */
175f51e146fSYishai Hadas #ifdef CONFIG_VIRTIO_PCI_ADMIN_LEGACY
176f51e146fSYishai Hadas #define VIRTIO_ADMIN_CMD_BITMAP VIRTIO_LEGACY_ADMIN_CMD_BITMAP
177f51e146fSYishai Hadas #else
178f51e146fSYishai Hadas #define VIRTIO_ADMIN_CMD_BITMAP 0
179f51e146fSYishai Hadas #endif
180f51e146fSYishai Hadas
181*97ee04feSFeng Liu bool vp_is_avq(struct virtio_device *vdev, unsigned int index);
1824c3b54afSJiri Pirko void vp_modern_avq_done(struct virtqueue *vq);
18392792ac7SFeng Liu int vp_modern_admin_cmd_exec(struct virtio_device *vdev,
18492792ac7SFeng Liu struct virtio_admin_cmd *cmd);
18592792ac7SFeng Liu
1865f4c9760SMichael S. Tsirkin #endif
187