|
@@ -21,11 +21,37 @@
|
21
|
21
|
#include "ipxe/virtio-pci.h"
|
22
|
22
|
#include "ipxe/virtio-ring.h"
|
23
|
23
|
|
|
24
|
+static int vp_alloc_vq(struct vring_virtqueue *vq, u16 num)
|
|
25
|
+{
|
|
26
|
+ size_t queue_size = PAGE_MASK + vring_size(num);
|
|
27
|
+ size_t vdata_size = num * sizeof(void *);
|
|
28
|
+
|
|
29
|
+ vq->queue = zalloc(queue_size + vdata_size);
|
|
30
|
+ if (!vq->queue) {
|
|
31
|
+ return -ENOMEM;
|
|
32
|
+ }
|
|
33
|
+
|
|
34
|
+ /* vdata immediately follows the ring */
|
|
35
|
+ vq->vdata = (void **)(vq->queue + queue_size);
|
|
36
|
+
|
|
37
|
+ return 0;
|
|
38
|
+}
|
|
39
|
+
|
|
40
|
+void vp_free_vq(struct vring_virtqueue *vq)
|
|
41
|
+{
|
|
42
|
+ if (vq->queue) {
|
|
43
|
+ free(vq->queue);
|
|
44
|
+ vq->queue = NULL;
|
|
45
|
+ vq->vdata = NULL;
|
|
46
|
+ }
|
|
47
|
+}
|
|
48
|
+
|
24
|
49
|
int vp_find_vq(unsigned int ioaddr, int queue_index,
|
25
|
50
|
struct vring_virtqueue *vq)
|
26
|
51
|
{
|
27
|
52
|
struct vring * vr = &vq->vring;
|
28
|
53
|
u16 num;
|
|
54
|
+ int rc;
|
29
|
55
|
|
30
|
56
|
/* select the queue */
|
31
|
57
|
|
|
@@ -39,11 +65,6 @@ int vp_find_vq(unsigned int ioaddr, int queue_index,
|
39
|
65
|
return -1;
|
40
|
66
|
}
|
41
|
67
|
|
42
|
|
- if (num > MAX_QUEUE_NUM) {
|
43
|
|
- DBG("VIRTIO-PCI ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM);
|
44
|
|
- return -1;
|
45
|
|
- }
|
46
|
|
-
|
47
|
68
|
/* check if the queue is already active */
|
48
|
69
|
|
49
|
70
|
if (inl(ioaddr + VIRTIO_PCI_QUEUE_PFN)) {
|
|
@@ -54,8 +75,12 @@ int vp_find_vq(unsigned int ioaddr, int queue_index,
|
54
|
75
|
vq->queue_index = queue_index;
|
55
|
76
|
|
56
|
77
|
/* initialize the queue */
|
57
|
|
-
|
58
|
|
- vring_init(vr, num, (unsigned char*)&vq->queue);
|
|
78
|
+ rc = vp_alloc_vq(vq, num);
|
|
79
|
+ if (rc) {
|
|
80
|
+ DBG("VIRTIO-PCI ERROR: failed to allocate queue memory\n");
|
|
81
|
+ return rc;
|
|
82
|
+ }
|
|
83
|
+ vring_init(vr, num, vq->queue);
|
59
|
84
|
|
60
|
85
|
/* activate the queue
|
61
|
86
|
*
|
|
@@ -354,7 +379,7 @@ int vpm_find_vqs(struct virtio_pci_modern_device *vdev,
|
354
|
379
|
return -ENOENT;
|
355
|
380
|
|
356
|
381
|
if (size & (size - 1)) {
|
357
|
|
- DBG("VIRTIO-PCI %p: bad queue size %d", vdev, size);
|
|
382
|
+ DBG("VIRTIO-PCI %p: bad queue size %d\n", vdev, size);
|
358
|
383
|
return -EINVAL;
|
359
|
384
|
}
|
360
|
385
|
|
|
@@ -371,7 +396,12 @@ int vpm_find_vqs(struct virtio_pci_modern_device *vdev,
|
371
|
396
|
/* get offset of notification word for this vq */
|
372
|
397
|
off = vpm_ioread16(vdev, &vdev->common, COMMON_OFFSET(queue_notify_off));
|
373
|
398
|
|
374
|
|
- vring_init(&vq->vring, size, (unsigned char *)vq->queue);
|
|
399
|
+ err = vp_alloc_vq(vq, size);
|
|
400
|
+ if (err) {
|
|
401
|
+ DBG("VIRTIO-PCI %p: failed to allocate queue memory\n", vdev);
|
|
402
|
+ return err;
|
|
403
|
+ }
|
|
404
|
+ vring_init(&vq->vring, size, vq->queue);
|
375
|
405
|
|
376
|
406
|
/* activate the queue */
|
377
|
407
|
vpm_iowrite16(vdev, &vdev->common, size, COMMON_OFFSET(queue_size));
|