Commit 1fcf0512 authored by Michael S. Tsirkin's avatar Michael S. Tsirkin Committed by Rusty Russell

virtio_pci: modern driver

Lightly tested against qemu.

One thing *not* implemented here is separate mappings
for descriptor/avail/used rings. That's nice to have,
will be done later after we have core support.

This also exposes the PCI layout to userspace, and
adds macros for PCI layout offsets:

QEMU wants it, so why not?  Trust, but verify.
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Michael S. Tsirkin's avatarMichael S. Tsirkin <mst@redhat.com>
parent 71d70c26
obj-$(CONFIG_VIRTIO) += virtio.o virtio_ring.o
obj-$(CONFIG_VIRTIO_MMIO) += virtio_mmio.o
obj-$(CONFIG_VIRTIO_PCI) += virtio_pci.o
virtio_pci-y := virtio_pci_legacy.o virtio_pci_common.o
virtio_pci-y := virtio_pci_modern.o virtio_pci_legacy.o virtio_pci_common.o
obj-$(CONFIG_VIRTIO_BALLOON) += virtio_balloon.o
......@@ -505,7 +505,9 @@ static int virtio_pci_probe(struct pci_dev *pci_dev,
if (rc)
goto err_request_regions;
rc = virtio_pci_legacy_probe(vp_dev);
rc = virtio_pci_modern_probe(vp_dev);
if (rc == -ENODEV)
rc = virtio_pci_legacy_probe(vp_dev);
if (rc)
goto err_probe;
......@@ -518,7 +520,10 @@ static int virtio_pci_probe(struct pci_dev *pci_dev,
return 0;
err_register:
virtio_pci_legacy_remove(vp_dev);
if (vp_dev->ioaddr)
virtio_pci_legacy_remove(vp_dev);
else
virtio_pci_modern_remove(vp_dev);
err_probe:
pci_release_regions(pci_dev);
err_request_regions:
......@@ -534,7 +539,10 @@ static void virtio_pci_remove(struct pci_dev *pci_dev)
unregister_virtio_device(&vp_dev->vdev);
virtio_pci_legacy_remove(pci_dev);
if (vp_dev->ioaddr)
virtio_pci_legacy_remove(vp_dev);
else
virtio_pci_modern_remove(vp_dev);
pci_release_regions(pci_dev);
pci_disable_device(pci_dev);
......
......@@ -53,12 +53,29 @@ struct virtio_pci_device {
struct virtio_device vdev;
struct pci_dev *pci_dev;
/* In legacy mode, these two point to within ->legacy. */
/* Where to read and clear interrupt */
u8 __iomem *isr;
/* Modern only fields */
/* The IO mapping for the PCI config space (non-legacy mode) */
struct virtio_pci_common_cfg __iomem *common;
/* Device-specific data (non-legacy mode) */
void __iomem *device;
/* So we can sanity-check accesses. */
size_t device_len;
/* Capability for when we need to map notifications per-vq. */
int notify_map_cap;
/* Multiply queue_notify_off by this value. (non-legacy mode). */
u32 notify_offset_multiplier;
/* Legacy only field */
/* the IO mapping for the PCI config space */
void __iomem *ioaddr;
/* the IO mapping for ISR operation */
void __iomem *isr;
/* a list of queues so we can dispatch IRQs */
spinlock_t lock;
struct list_head virtqueues;
......@@ -129,5 +146,7 @@ int vp_set_vq_affinity(struct virtqueue *vq, int cpu);
int virtio_pci_legacy_probe(struct virtio_pci_device *);
void virtio_pci_legacy_remove(struct virtio_pci_device *);
int virtio_pci_modern_probe(struct virtio_pci_device *);
void virtio_pci_modern_remove(struct virtio_pci_device *);
#endif
This diff is collapsed.
......@@ -117,10 +117,11 @@ struct virtio_pci_cap {
__u8 cap_vndr; /* Generic PCI field: PCI_CAP_ID_VNDR */
__u8 cap_next; /* Generic PCI field: next ptr. */
__u8 cap_len; /* Generic PCI field: capability length */
__u8 type_and_bar; /* Upper 3 bits: bar.
* Lower 3 is VIRTIO_PCI_CAP_*_CFG. */
__u8 cfg_type; /* Identifies the structure. */
__u8 bar; /* Where to find it. */
__u8 padding[3]; /* Pad to full dword. */
__le32 offset; /* Offset within bar. */
__le32 length; /* Length. */
__le32 length; /* Length of the structure, in bytes. */
};
#define VIRTIO_PCI_CAP_BAR_SHIFT 5
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment