Parcourir la source

[virtio] Split virtio-net.c into several files.

Signed-off-by: Laurent Vivier <Laurent.Vivier@bull.net>
tags/v0.9.6
Laurent Vivier il y a 15 ans
Parent
révision
b48f37e69a

+ 64
- 0
src/drivers/bus/virtio-pci.c Voir le fichier

@@ -0,0 +1,64 @@
1
+/* virtio-pci.c - pci interface for virtio interface
2
+ *
3
+ * (c) Copyright 2008 Bull S.A.S.
4
+ *
5
+ *  Author: Laurent Vivier <Laurent.Vivier@bull.net>
6
+ *
7
+ * some parts from Linux Virtio PCI driver
8
+ *
9
+ *  Copyright IBM Corp. 2007
10
+ *  Authors: Anthony Liguori  <aliguori@us.ibm.com>
11
+ *
12
+ */
13
+
14
+#include "etherboot.h"
15
+#include "gpxe/io.h"
16
+#include "gpxe/virtio-ring.h"
17
+#include "gpxe/virtio-pci.h"
18
+
19
+int vp_find_vq(unsigned int ioaddr, int queue_index,
20
+               struct vring_virtqueue *vq)
21
+{
22
+   struct vring * vr = &vq->vring;
23
+   u16 num;
24
+
25
+   /* select the queue */
26
+
27
+   outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL);
28
+
29
+   /* check if the queue is available */
30
+
31
+   num = inw(ioaddr + VIRTIO_PCI_QUEUE_NUM);
32
+   if (!num) {
33
+           printf("ERROR: queue size is 0\n");
34
+           return -1;
35
+   }
36
+
37
+   if (num > MAX_QUEUE_NUM) {
38
+           printf("ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM);
39
+           return -1;
40
+   }
41
+
42
+   /* check if the queue is already active */
43
+
44
+   if (inl(ioaddr + VIRTIO_PCI_QUEUE_PFN)) {
45
+           printf("ERROR: queue already active\n");
46
+           return -1;
47
+   }
48
+
49
+   vq->queue_index = queue_index;
50
+
51
+   /* initialize the queue */
52
+
53
+   vring_init(vr, num, (unsigned char*)&vq->queue);
54
+
55
+   /* activate the queue
56
+    *
57
+    * NOTE: vr->desc is initialized by vring_init()
58
+    */
59
+
60
+   outl((unsigned long)virt_to_phys(vr->desc) >> PAGE_SHIFT,
61
+        ioaddr + VIRTIO_PCI_QUEUE_PFN);
62
+
63
+   return num;
64
+}

+ 134
- 0
src/drivers/bus/virtio-ring.c Voir le fichier

@@ -0,0 +1,134 @@
1
+/* virtio-pci.c - virtio ring management
2
+ *
3
+ * (c) Copyright 2008 Bull S.A.S.
4
+ *
5
+ *  Author: Laurent Vivier <Laurent.Vivier@bull.net>
6
+ *
7
+ *  some parts from Linux Virtio Ring
8
+ *
9
+ *  Copyright Rusty Russell IBM Corporation 2007
10
+ *
11
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
12
+ * See the COPYING file in the top-level directory.
13
+ *
14
+ *
15
+ */
16
+
17
+#include "etherboot.h"
18
+#include "gpxe/io.h"
19
+#include "gpxe/virtio-ring.h"
20
+#include "gpxe/virtio-pci.h"
21
+
22
+#define BUG() do { \
23
+   printf("BUG: failure at %s:%d/%s()!\n", \
24
+          __FILE__, __LINE__, __FUNCTION__); \
25
+   while(1); \
26
+} while (0)
27
+#define BUG_ON(condition) do { if (condition) BUG(); } while (0)
28
+
29
+/*
30
+ * vring_free
31
+ *
32
+ * put at the begin of the free list the current desc[head]
33
+ */
34
+
35
+void vring_detach(struct vring_virtqueue *vq, unsigned int head)
36
+{
37
+   struct vring *vr = &vq->vring;
38
+   unsigned int i;
39
+
40
+   /* find end of given descriptor */
41
+
42
+   i = head;
43
+   while (vr->desc[i].flags & VRING_DESC_F_NEXT)
44
+           i = vr->desc[i].next;
45
+
46
+   /* link it with free list and point to it */
47
+
48
+   vr->desc[i].next = vq->free_head;
49
+   wmb();
50
+   vq->free_head = head;
51
+}
52
+
53
+/*
54
+ * vring_get_buf
55
+ *
56
+ * get a buffer from the used list
57
+ *
58
+ */
59
+
60
+int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len)
61
+{
62
+   struct vring *vr = &vq->vring;
63
+   struct vring_used_elem *elem;
64
+   u32 id;
65
+   int ret;
66
+
67
+   BUG_ON(!vring_more_used(vq));
68
+
69
+   elem = &vr->used->ring[vq->last_used_idx % vr->num];
70
+   wmb();
71
+   id = elem->id;
72
+   if (len != NULL)
73
+           *len = elem->len;
74
+
75
+   ret = vq->vdata[id];
76
+
77
+   vring_detach(vq, id);
78
+
79
+   vq->last_used_idx++;
80
+
81
+   return ret;
82
+}
83
+
84
+void vring_add_buf(struct vring_virtqueue *vq,
85
+		   struct vring_list list[],
86
+		   unsigned int out, unsigned int in,
87
+		   int index, int num_added)
88
+{
89
+   struct vring *vr = &vq->vring;
90
+   int i, avail, head, prev;
91
+
92
+   BUG_ON(out + in == 0);
93
+
94
+   prev = 0;
95
+   head = vq->free_head;
96
+   for (i = head; out; i = vr->desc[i].next, out--) {
97
+
98
+           vr->desc[i].flags = VRING_DESC_F_NEXT;
99
+           vr->desc[i].addr = (u64)virt_to_phys(list->addr);
100
+           vr->desc[i].len = list->length;
101
+           prev = i;
102
+           list++;
103
+   }
104
+   for ( ; in; i = vr->desc[i].next, in--) {
105
+
106
+           vr->desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE;
107
+           vr->desc[i].addr = (u64)virt_to_phys(list->addr);
108
+           vr->desc[i].len = list->length;
109
+           prev = i;
110
+           list++;
111
+   }
112
+   vr->desc[prev].flags &= ~VRING_DESC_F_NEXT;
113
+
114
+   vq->free_head = i;
115
+
116
+   vq->vdata[head] = index;
117
+
118
+   avail = (vr->avail->idx + num_added) % vr->num;
119
+   vr->avail->ring[avail] = head;
120
+   wmb();
121
+}
122
+
123
+void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added)
124
+{
125
+   struct vring *vr = &vq->vring;
126
+
127
+   wmb();
128
+   vr->avail->idx += num_added;
129
+
130
+   mb();
131
+   if (!(vr->used->flags & VRING_USED_F_NO_NOTIFY))
132
+           vp_notify(ioaddr, vq->queue_index);
133
+}
134
+

+ 3
- 202
src/drivers/net/virtio-net.c Voir le fichier

@@ -45,8 +45,6 @@ struct eth_frame {
45 45
    unsigned char data[ETH_FRAME_LEN];
46 46
 };
47 47
 
48
-typedef unsigned char virtio_queue_t[PAGE_MASK + vring_size(MAX_QUEUE_NUM)];
49
-
50 48
 /* TX: virtio header and eth buffer */
51 49
 
52 50
 static struct virtio_net_hdr tx_virtio_hdr;
@@ -66,205 +64,8 @@ enum {
66 64
    QUEUE_NB
67 65
 };
68 66
 
69
-struct vring_virtqueue {
70
-   virtio_queue_t queue;
71
-   struct vring vring;
72
-   u16 free_head;
73
-   u16 last_used_idx;
74
-   u16 vdata[MAX_QUEUE_NUM];
75
-   /* PCI */
76
-   int queue_index;
77
-};
78
-
79 67
 static struct vring_virtqueue virtqueue[QUEUE_NB];
80 68
 
81
-/*
82
- * Virtio PCI interface
83
- *
84
- */
85
-
86
-static int vp_find_vq(unsigned int ioaddr, int queue_index,
87
-                      struct vring_virtqueue *vq)
88
-{
89
-   struct vring * vr = &vq->vring;
90
-   u16 num;
91
-
92
-   /* select the queue */
93
-
94
-   outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL);
95
-
96
-   /* check if the queue is available */
97
-
98
-   num = inw(ioaddr + VIRTIO_PCI_QUEUE_NUM);
99
-   if (!num) {
100
-           printf("ERROR: queue size is 0\n");
101
-           return -1;
102
-   }
103
-
104
-   if (num > MAX_QUEUE_NUM) {
105
-           printf("ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM);
106
-           return -1;
107
-   }
108
-
109
-   /* check if the queue is already active */
110
-
111
-   if (inl(ioaddr + VIRTIO_PCI_QUEUE_PFN)) {
112
-           printf("ERROR: queue already active\n");
113
-           return -1;
114
-   }
115
-
116
-   vq->queue_index = queue_index;
117
-
118
-   /* initialize the queue */
119
-
120
-   vring_init(vr, num, (unsigned char*)&vq->queue);
121
-
122
-   /* activate the queue
123
-    *
124
-    * NOTE: vr->desc is initialized by vring_init()
125
-    */
126
-
127
-   outl((unsigned long)virt_to_phys(vr->desc) >> PAGE_SHIFT,
128
-        ioaddr + VIRTIO_PCI_QUEUE_PFN);
129
-
130
-   return num;
131
-}
132
-
133
-/*
134
- * Virtual ring management
135
- *
136
- */
137
-
138
-static void vring_enable_cb(struct vring_virtqueue *vq)
139
-{
140
-   vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT;
141
-}
142
-
143
-static void vring_disable_cb(struct vring_virtqueue *vq)
144
-{
145
-   vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
146
-}
147
-
148
-/*
149
- * vring_free
150
- *
151
- * put at the begin of the free list the current desc[head]
152
- */
153
-
154
-static void vring_detach(struct vring_virtqueue *vq, unsigned int head)
155
-{
156
-   struct vring *vr = &vq->vring;
157
-   unsigned int i;
158
-
159
-   /* find end of given descriptor */
160
-
161
-   i = head;
162
-   while (vr->desc[i].flags & VRING_DESC_F_NEXT)
163
-           i = vr->desc[i].next;
164
-
165
-   /* link it with free list and point to it */
166
-
167
-   vr->desc[i].next = vq->free_head;
168
-   wmb();
169
-   vq->free_head = head;
170
-}
171
-
172
-/*
173
- * vring_more_used
174
- *
175
- * is there some used buffers ?
176
- *
177
- */
178
-
179
-static inline int vring_more_used(struct vring_virtqueue *vq)
180
-{
181
-   wmb();
182
-   return vq->last_used_idx != vq->vring.used->idx;
183
-}
184
-
185
-/*
186
- * vring_get_buf
187
- *
188
- * get a buffer from the used list
189
- *
190
- */
191
-
192
-static int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len)
193
-{
194
-   struct vring *vr = &vq->vring;
195
-   struct vring_used_elem *elem;
196
-   u32 id;
197
-   int ret;
198
-
199
-   BUG_ON(!vring_more_used(vq));
200
-
201
-   elem = &vr->used->ring[vq->last_used_idx % vr->num];
202
-   wmb();
203
-   id = elem->id;
204
-   if (len != NULL)
205
-           *len = elem->len;
206
-
207
-   ret = vq->vdata[id];
208
-
209
-   vring_detach(vq, id);
210
-
211
-   vq->last_used_idx++;
212
-
213
-   return ret;
214
-}
215
-
216
-static void vring_add_buf(struct vring_virtqueue *vq,
217
-			  struct vring_list list[],
218
-			  unsigned int out, unsigned int in,
219
-			  int index, int num_added)
220
-{
221
-   struct vring *vr = &vq->vring;
222
-   int i, avail, head, prev;
223
-
224
-   BUG_ON(out + in == 0);
225
-
226
-   prev = 0;
227
-   head = vq->free_head;
228
-   for (i = head; out; i = vr->desc[i].next, out--) {
229
-
230
-           vr->desc[i].flags = VRING_DESC_F_NEXT;
231
-           vr->desc[i].addr = (u64)virt_to_phys(list->addr);
232
-           vr->desc[i].len = list->length;
233
-           prev = i;
234
-           list++;
235
-   }
236
-   for ( ; in; i = vr->desc[i].next, in--) {
237
-
238
-           vr->desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE;
239
-           vr->desc[i].addr = (u64)virt_to_phys(list->addr);
240
-           vr->desc[i].len = list->length;
241
-           prev = i;
242
-           list++;
243
-   }
244
-   vr->desc[prev].flags &= ~VRING_DESC_F_NEXT;
245
-
246
-   vq->free_head = i;
247
-
248
-   vq->vdata[head] = index;
249
-
250
-   avail = (vr->avail->idx + num_added) % vr->num;
251
-   vr->avail->ring[avail] = head;
252
-   wmb();
253
-}
254
-
255
-static void vring_kick(struct nic *nic, struct vring_virtqueue *vq,
256
-                       int num_added)
257
-{
258
-   struct vring *vr = &vq->vring;
259
-
260
-   wmb();
261
-   vr->avail->idx += num_added;
262
-
263
-   mb();
264
-   if (!(vr->used->flags & VRING_USED_F_NO_NOTIFY))
265
-           vp_notify(nic->ioaddr, vq->queue_index);
266
-}
267
-
268 69
 /*
269 70
  * virtnet_disable
270 71
  *
@@ -325,7 +126,7 @@ static int virtnet_poll(struct nic *nic, int retrieve)
325 126
    list[1].length = ETH_FRAME_LEN;
326 127
 
327 128
    vring_add_buf(&virtqueue[RX_INDEX], list, 0, 2, token, 0);
328
-   vring_kick(nic, &virtqueue[RX_INDEX], 1);
129
+   vring_kick(nic->ioaddr, &virtqueue[RX_INDEX], 1);
329 130
 
330 131
    return 1;
331 132
 }
@@ -373,7 +174,7 @@ static void virtnet_transmit(struct nic *nic, const char *destaddr,
373 174
 
374 175
    vring_add_buf(&virtqueue[TX_INDEX], list, 2, 0, 0, 0);
375 176
 
376
-   vring_kick(nic, &virtqueue[TX_INDEX], 1);
177
+   vring_kick(nic->ioaddr, &virtqueue[TX_INDEX], 1);
377 178
 
378 179
    /*
379 180
     * http://www.etherboot.org/wiki/dev/devmanual
@@ -423,7 +224,7 @@ static void provide_buffers(struct nic *nic)
423 224
 
424 225
    /* nofify */
425 226
 
426
-   vring_kick(nic, &virtqueue[RX_INDEX], i);
227
+   vring_kick(nic->ioaddr, &virtqueue[RX_INDEX], i);
427 228
 }
428 229
 
429 230
 static struct nic_operations virtnet_operations = {

+ 3
- 0
src/include/gpxe/virtio-pci.h Voir le fichier

@@ -91,4 +91,7 @@ static inline void vp_del_vq(unsigned int ioaddr, int queue_index)
91 91
 
92 92
    outl(0, ioaddr + VIRTIO_PCI_QUEUE_PFN);
93 93
 }
94
+
95
+int vp_find_vq(unsigned int ioaddr, int queue_index,
96
+               struct vring_virtqueue *vq);
94 97
 #endif /* _VIRTIO_PCI_H_ */

+ 48
- 5
src/include/gpxe/virtio-ring.h Voir le fichier

@@ -58,6 +58,24 @@ struct vring {
58 58
    struct vring_used *used;
59 59
 };
60 60
 
61
+#define vring_size(num) \
62
+   (((((sizeof(struct vring_desc) * num) + \
63
+      (sizeof(struct vring_avail) + sizeof(u16) * num)) \
64
+         + PAGE_MASK) & ~PAGE_MASK) + \
65
+         (sizeof(struct vring_used) + sizeof(struct vring_used_elem) * num))
66
+
67
+typedef unsigned char virtio_queue_t[PAGE_MASK + vring_size(MAX_QUEUE_NUM)];
68
+
69
+struct vring_virtqueue {
70
+   virtio_queue_t queue;
71
+   struct vring vring;
72
+   u16 free_head;
73
+   u16 last_used_idx;
74
+   u16 vdata[MAX_QUEUE_NUM];
75
+   /* PCI */
76
+   int queue_index;
77
+};
78
+
61 79
 struct vring_list {
62 80
   char *addr;
63 81
   unsigned int length;
@@ -90,10 +108,35 @@ static inline void vring_init(struct vring *vr,
90 108
    vr->desc[i].next = 0;
91 109
 }
92 110
 
93
-#define vring_size(num) \
94
-   (((((sizeof(struct vring_desc) * num) + \
95
-      (sizeof(struct vring_avail) + sizeof(u16) * num)) \
96
-         + PAGE_MASK) & ~PAGE_MASK) + \
97
-         (sizeof(struct vring_used) + sizeof(struct vring_used_elem) * num))
111
+static inline void vring_enable_cb(struct vring_virtqueue *vq)
112
+{
113
+   vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT;
114
+}
115
+
116
+static inline void vring_disable_cb(struct vring_virtqueue *vq)
117
+{
118
+   vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
119
+}
120
+
121
+
122
+/*
123
+ * vring_more_used
124
+ *
125
+ * is there some used buffers ?
126
+ *
127
+ */
128
+
129
+static inline int vring_more_used(struct vring_virtqueue *vq)
130
+{
131
+   wmb();
132
+   return vq->last_used_idx != vq->vring.used->idx;
133
+}
134
+
135
+void vring_detach(struct vring_virtqueue *vq, unsigned int head);
136
+int vring_get_buf(struct vring_virtqueue *vq, unsigned int *len);
137
+void vring_add_buf(struct vring_virtqueue *vq, struct vring_list list[],
138
+                   unsigned int out, unsigned int in,
139
+                   int index, int num_added);
140
+void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added);
98 141
 
99 142
 #endif /* _VIRTIO_RING_H_ */

Chargement…
Annuler
Enregistrer