diff options
author | Aaron Young <Aaron.Young@oracle.com> | 2021-10-27 16:05:43 -0700 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2021-10-28 13:19:30 +0100 |
commit | f24a2794e1b527e45efbbcad1c272f176f3d9df0 (patch) | |
tree | 1bb4cc38e3e7059259fe37f3a7716a864f55eb13 /src/drivers/bus/virtio-pci.c | |
parent | 2265a65191d76ce367913a61c97752ab88ab1a59 (diff) | |
download | ipxe-f24a2794e1b527e45efbbcad1c272f176f3d9df0.tar.gz |
[virtio] Update driver to use DMA API
Signed-off-by: Aaron Young <aaron.young@oracle.com>
Diffstat (limited to 'src/drivers/bus/virtio-pci.c')
-rw-r--r-- | src/drivers/bus/virtio-pci.c | 45 |
1 files changed, 30 insertions, 15 deletions
diff --git a/src/drivers/bus/virtio-pci.c b/src/drivers/bus/virtio-pci.c index 5d2d62750..8b34c7277 100644 --- a/src/drivers/bus/virtio-pci.c +++ b/src/drivers/bus/virtio-pci.c @@ -17,37 +17,47 @@ #include "ipxe/io.h" #include "ipxe/iomap.h" #include "ipxe/pci.h" +#include "ipxe/dma.h" #include "ipxe/reboot.h" #include "ipxe/virtio-pci.h" #include "ipxe/virtio-ring.h" -static int vp_alloc_vq(struct vring_virtqueue *vq, u16 num) +static int vp_alloc_vq(struct vring_virtqueue *vq, u16 num, size_t header_size) { - size_t queue_size = PAGE_MASK + vring_size(num); + size_t ring_size = PAGE_MASK + vring_size(num); size_t vdata_size = num * sizeof(void *); + size_t queue_size = ring_size + vdata_size + header_size; - vq->queue = zalloc(queue_size + vdata_size); + vq->queue = dma_alloc(vq->dma, &vq->map, queue_size, queue_size); if (!vq->queue) { return -ENOMEM; } + memset ( vq->queue, 0, queue_size ); + vq->queue_size = queue_size; + /* vdata immediately follows the ring */ - vq->vdata = (void **)(vq->queue + queue_size); + vq->vdata = (void **)(vq->queue + ring_size); + + /* empty header immediately follows vdata */ + vq->empty_header = (struct virtio_net_hdr_modern *)(vq->queue + ring_size + vdata_size); return 0; } void vp_free_vq(struct vring_virtqueue *vq) { - if (vq->queue) { - free(vq->queue); + if (vq->queue && vq->queue_size) { + dma_free(&vq->map, vq->queue, vq->queue_size); vq->queue = NULL; vq->vdata = NULL; + vq->queue_size = 0; } } int vp_find_vq(unsigned int ioaddr, int queue_index, - struct vring_virtqueue *vq) + struct vring_virtqueue *vq, struct dma_device *dma_dev, + size_t header_size) { struct vring * vr = &vq->vring; u16 num; @@ -73,9 +83,10 @@ int vp_find_vq(unsigned int ioaddr, int queue_index, } vq->queue_index = queue_index; + vq->dma = dma_dev; /* initialize the queue */ - rc = vp_alloc_vq(vq, num); + rc = vp_alloc_vq(vq, num, header_size); if (rc) { DBG("VIRTIO-PCI ERROR: failed to allocate queue memory\n"); return rc; @@ -87,8 +98,7 @@ int vp_find_vq(unsigned int ioaddr, int queue_index, * NOTE: vr->desc is initialized by vring_init() */ - outl((unsigned long)virt_to_phys(vr->desc) >> PAGE_SHIFT, - ioaddr + VIRTIO_PCI_QUEUE_PFN); + outl(dma(&vq->map, vr->desc) >> PAGE_SHIFT, ioaddr + VIRTIO_PCI_QUEUE_PFN); return num; } @@ -348,7 +358,8 @@ void vpm_notify(struct virtio_pci_modern_device *vdev, } int vpm_find_vqs(struct virtio_pci_modern_device *vdev, - unsigned nvqs, struct vring_virtqueue *vqs) + unsigned nvqs, struct vring_virtqueue *vqs, + struct dma_device *dma_dev, size_t header_size) { unsigned i; struct vring_virtqueue *vq; @@ -392,11 +403,12 @@ int vpm_find_vqs(struct virtio_pci_modern_device *vdev, vq = &vqs[i]; vq->queue_index = i; + vq->dma = dma_dev; /* get offset of notification word for this vq */ off = vpm_ioread16(vdev, &vdev->common, COMMON_OFFSET(queue_notify_off)); - err = vp_alloc_vq(vq, size); + err = vp_alloc_vq(vq, size, header_size); if (err) { DBG("VIRTIO-PCI %p: failed to allocate queue memory\n", vdev); return err; @@ -406,13 +418,16 @@ int vpm_find_vqs(struct virtio_pci_modern_device *vdev, /* activate the queue */ vpm_iowrite16(vdev, &vdev->common, size, COMMON_OFFSET(queue_size)); - vpm_iowrite64(vdev, &vdev->common, virt_to_phys(vq->vring.desc), + vpm_iowrite64(vdev, &vdev->common, + dma(&vq->map, vq->vring.desc), COMMON_OFFSET(queue_desc_lo), COMMON_OFFSET(queue_desc_hi)); - vpm_iowrite64(vdev, &vdev->common, virt_to_phys(vq->vring.avail), + vpm_iowrite64(vdev, &vdev->common, + dma(&vq->map, vq->vring.avail), COMMON_OFFSET(queue_avail_lo), COMMON_OFFSET(queue_avail_hi)); - vpm_iowrite64(vdev, &vdev->common, virt_to_phys(vq->vring.used), + vpm_iowrite64(vdev, &vdev->common, + dma(&vq->map, vq->vring.used), COMMON_OFFSET(queue_used_lo), COMMON_OFFSET(queue_used_hi)); |