aboutsummaryrefslogtreecommitdiffstats
path: root/src/drivers/bus/virtio-pci.c
diff options
context:
space:
mode:
authorAaron Young <Aaron.Young@oracle.com>2021-10-27 16:05:43 -0700
committerMichael Brown <mcb30@ipxe.org>2021-10-28 13:19:30 +0100
commitf24a2794e1b527e45efbbcad1c272f176f3d9df0 (patch)
tree1bb4cc38e3e7059259fe37f3a7716a864f55eb13 /src/drivers/bus/virtio-pci.c
parent2265a65191d76ce367913a61c97752ab88ab1a59 (diff)
downloadipxe-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.c45
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));