iPXE - Open Source Boot Firmware

[virtio-net] Fix kick/wait logic
[mirror/etherboot.git] / src / drivers / net / virtio-net.c
1 /* virtio-net.c - etherboot driver for virtio network 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  *  some parts from Linux Virtio Ring
13  *
14  *  Copyright Rusty Russell IBM Corporation 2007
15  *
16  * This work is licensed under the terms of the GNU GPL, version 2 or later.
17  * See the COPYING file in the top-level directory.
18  *
19  *
20  */
21
22 #include "etherboot.h"
23 #include "pci.h"
24 #include "nic.h"
25 #include "timer.h"
26 #include "virtio-ring.h"
27 #include "virtio-pci.h"
28 #include "virtio-net.h"
29
30 #define BUG() do { \
31    printf("BUG: failure at %s:%d/%s()!\n", \
32           __FILE__, __LINE__, __FUNCTION__); \
33    while(1); \
34 } while (0)
35 #define BUG_ON(condition) do { if (condition) BUG(); } while (0)
36
37 /* Ethernet header */
38
39 struct eth_hdr {
40    unsigned char dst_addr[ETH_ALEN];
41    unsigned char src_addr[ETH_ALEN];
42    unsigned short type;
43 };
44
45 struct eth_frame {
46    struct eth_hdr hdr;
47    unsigned char data[ETH_FRAME_LEN];
48 };
49
50 typedef unsigned char virtio_queue_t[PAGE_MASK + vring_size(MAX_QUEUE_NUM)];
51
52 /* TX: virtio header and eth buffer */
53
54 static struct virtio_net_hdr tx_virtio_hdr;
55 static struct eth_frame tx_eth_frame;
56
57 /* RX: virtio headers and buffers */
58
59 #define RX_BUF_NB  6
60 static struct virtio_net_hdr rx_hdr[RX_BUF_NB];
61 static unsigned char rx_buffer[RX_BUF_NB][ETH_FRAME_LEN];
62
63 /* virtio queues and vrings */
64
65 enum {
66    RX_INDEX = 0,
67    TX_INDEX,
68    QUEUE_NB
69 };
70
71 static virtio_queue_t queue[QUEUE_NB];
72 static struct vring vring[QUEUE_NB];
73 static u16 free_head[QUEUE_NB];
74 static u16 last_used_idx[QUEUE_NB];
75 static u16 vdata[QUEUE_NB][MAX_QUEUE_NUM];
76
77 /*
78  * Virtio PCI interface
79  *
80  */
81
82 static int vp_find_vq(struct nic *nic, int queue_index)
83 {
84    struct vring * vr = &vring[queue_index];
85    u16 num;
86
87    /* select the queue */
88
89    outw(queue_index, nic->ioaddr + VIRTIO_PCI_QUEUE_SEL);
90
91    /* check if the queue is available */
92
93    num = inw(nic->ioaddr + VIRTIO_PCI_QUEUE_NUM);
94    if (!num) {
95            printf("ERROR: queue size is 0\n");
96            return -1;
97    }
98
99    if (num > MAX_QUEUE_NUM) {
100            printf("ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM);
101            return -1;
102    }
103
104    /* check if the queue is already active */
105
106    if (inl(nic->ioaddr + VIRTIO_PCI_QUEUE_PFN)) {
107            printf("ERROR: queue already active\n");
108            return -1;
109    }
110
111    /* initialize the queue */
112
113    vring_init(vr, num, (unsigned char*)&queue[queue_index]);
114
115    /* activate the queue
116     *
117     * NOTE: vr->desc is initialized by vring_init()
118     */
119
120    outl((unsigned long)virt_to_phys(vr->desc) >> PAGE_SHIFT,
121         nic->ioaddr + VIRTIO_PCI_QUEUE_PFN);
122
123    return num;
124 }
125
126 /*
127  * Virtual ring management
128  *
129  */
130
131 static void vring_enable_cb(int queue_index)
132 {
133    vring[queue_index].avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT;
134 }
135
136 static void vring_disable_cb(int queue_index)
137 {
138    vring[queue_index].avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
139 }
140
141 /*
142  * vring_free
143  *
144  * put at the begin of the free list the current desc[head]
145  */
146
147 static void vring_detach(int queue_index, unsigned int head)
148 {
149    struct vring *vr = &vring[queue_index];
150         unsigned int i;
151
152         /* find end of given descriptor */
153
154    i = head;
155    while (vr->desc[i].flags & VRING_DESC_F_NEXT)
156            i = vr->desc[i].next;
157
158    /* link it with free list and point to it */
159
160    vr->desc[i].next = free_head[queue_index];
161    wmb();
162    free_head[queue_index] = head;
163 }
164
165 /*
166  * vring_more_used
167  *
168  * is there some used buffers ?
169  *
170  */
171
172 static inline int vring_more_used(int queue_index)
173 {
174    wmb();
175    return last_used_idx[queue_index] != vring[queue_index].used->idx;
176 }
177
178 /*
179  * vring_get_buf
180  *
181  * get a buffer from the used list
182  *
183  */
184
185 static int vring_get_buf(int queue_index, unsigned int *len)
186 {
187    struct vring *vr = &vring[queue_index];
188    struct vring_used_elem *elem;
189    u32 id;
190    int ret;
191
192    BUG_ON(!vring_more_used(queue_index));
193
194    elem = &vr->used->ring[last_used_idx[queue_index] % vr->num];
195    wmb();
196    id = elem->id;
197    if (len != NULL)
198            *len = elem->len;
199
200    ret = vdata[queue_index][id];
201
202    vring_detach(queue_index, id);
203
204    last_used_idx[queue_index]++;
205
206    return ret;
207 }
208
209 static void vring_add_buf(int queue_index, int index, int num_added)
210 {
211    struct vring *vr = &vring[queue_index];
212    int i, avail, head;
213
214    BUG_ON(queue_index >= QUEUE_NB);
215
216    head = free_head[queue_index];
217    i = head;
218
219    if (queue_index == TX_INDEX) {
220
221            BUG_ON(index != 0);
222
223            /* add header into vring */
224
225            vr->desc[i].flags = VRING_DESC_F_NEXT;
226            vr->desc[i].addr = (u64)virt_to_phys(&tx_virtio_hdr);
227            vr->desc[i].len = sizeof(struct virtio_net_hdr);
228            i = vr->desc[i].next;
229
230            /* add frame buffer into vring */
231
232            vr->desc[i].flags = 0;
233            vr->desc[i].addr = (u64)virt_to_phys(&tx_eth_frame);
234            vr->desc[i].len = ETH_FRAME_LEN;
235            i = vr->desc[i].next;
236
237    } else if (queue_index == RX_INDEX) {
238
239            BUG_ON(index >= RX_BUF_NB);
240
241            /* add header into vring */
242
243            vr->desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE;
244            vr->desc[i].addr = (u64)virt_to_phys(&rx_hdr[index]);
245            vr->desc[i].len = sizeof(struct virtio_net_hdr);
246            i = vr->desc[i].next;
247
248            /* add frame buffer into vring */
249
250            vr->desc[i].flags = VRING_DESC_F_WRITE;
251            vr->desc[i].addr = (u64)virt_to_phys(&rx_buffer[index]);
252            vr->desc[i].len = ETH_FRAME_LEN;
253            i = vr->desc[i].next;
254    }
255
256    free_head[queue_index] = i;
257
258    vdata[queue_index][head] = index;
259
260    avail = (vr->avail->idx + num_added) % vr->num;
261    vr->avail->ring[avail] = head;
262    wmb();
263 }
264
265 static void vring_kick(struct nic *nic, int queue_index, int num_added)
266 {
267    struct vring *vr = &vring[queue_index];
268
269    wmb();
270    vr->avail->idx += num_added;
271
272    mb();
273    if (!(vr->used->flags & VRING_USED_F_NO_NOTIFY))
274            vp_notify(nic, queue_index);
275 }
276
277 /*
278  * virtnet_disable
279  *
280  * Turn off ethernet interface
281  *
282  */
283
284 static void virtnet_disable(struct dev *dev)
285 {
286    int i;
287    struct nic *nic = (struct nic *)dev;
288
289    for (i = 0; i < QUEUE_NB; i++) {
290            vring_disable_cb(i);
291            vp_del_vq(nic, i);
292    }
293    vp_reset(nic);
294 }
295
296 /*
297  * virtnet_poll
298  *
299  * Wait for a frame
300  *
301  * return true if there is a packet ready to read
302  *
303  * nic->packet should contain data on return
304  * nic->packetlen should contain length of data
305  *
306  */
307 static int virtnet_poll(struct nic *nic, int retrieve)
308 {
309    unsigned int len;
310    u16 token;
311    struct virtio_net_hdr *hdr;
312
313    if (!vring_more_used(RX_INDEX))
314            return 0;
315
316    if (!retrieve)
317            return 1;
318
319    token = vring_get_buf(RX_INDEX, &len);
320
321    BUG_ON(len > sizeof(struct virtio_net_hdr) + ETH_FRAME_LEN);
322
323    hdr = &rx_hdr[token];   /* FIXME: check flags */
324    len -= sizeof(struct virtio_net_hdr);
325
326         nic->packetlen = len;
327    memcpy(nic->packet, (char *)rx_buffer[token], nic->packetlen);
328
329    /* add buffer to desc */
330
331    vring_add_buf(RX_INDEX, token, 0);
332    vring_kick(nic, RX_INDEX, 1);
333
334    return 1;
335 }
336
337 /*
338  *
339  * virtnet_transmit
340  *
341  * Transmit a frame
342  *
343  */
344
345 static void virtnet_transmit(struct nic *nic, const char *destaddr,
346         unsigned int type, unsigned int len, const char *data)
347 {
348    /*
349     * from http://www.etherboot.org/wiki/dev/devmanual :
350     *     "You do not need more than one transmit buffer."
351     */
352
353    /* FIXME: initialize header according to vp_get_features() */
354
355    tx_virtio_hdr.flags = 0;
356    tx_virtio_hdr.csum_offset = 0;
357    tx_virtio_hdr.csum_start = 0;
358    tx_virtio_hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE;
359    tx_virtio_hdr.gso_size = 0;
360    tx_virtio_hdr.hdr_len = 0;
361
362    /* add ethernet frame into vring */
363
364    BUG_ON(len > sizeof(tx_eth_frame.data));
365
366    memcpy(tx_eth_frame.hdr.dst_addr, destaddr, ETH_ALEN);
367    memcpy(tx_eth_frame.hdr.src_addr, nic->node_addr, ETH_ALEN);
368    tx_eth_frame.hdr.type = htons(type);
369    memcpy(tx_eth_frame.data, data, len);
370
371    vring_add_buf(TX_INDEX, 0, 0);
372
373    vring_kick(nic, TX_INDEX, 1);
374
375    /*
376     * http://www.etherboot.org/wiki/dev/devmanual
377     *
378     *   "You should ensure the packet is fully transmitted
379     *    before returning from this routine"
380     */
381
382    while (!vring_more_used(TX_INDEX)) {
383            mb();
384            udelay(10);
385            poll_interruptions();
386    }
387
388    /* free desc */
389
390    (void)vring_get_buf(TX_INDEX, NULL);
391 }
392
393 static void virtnet_irq(struct nic *nic __unused, irq_action_t action)
394 {
395    switch ( action ) {
396    case DISABLE :
397            vring_disable_cb(RX_INDEX);
398            vring_disable_cb(TX_INDEX);
399            break;
400    case ENABLE :
401            vring_enable_cb(RX_INDEX);
402            vring_enable_cb(TX_INDEX);
403            break;
404    case FORCE :
405            break;
406    }
407 }
408
409 static void provide_buffers(struct nic *nic)
410 {
411    int i;
412
413    for (i = 0; i < RX_BUF_NB; i++)
414            vring_add_buf(RX_INDEX, i, i);
415
416    /* nofify */
417
418    vring_kick(nic, RX_INDEX, i);
419 }
420
421 /*
422  * virtnet_probe
423  *
424  * Look for a virtio network adapter
425  *
426  */
427
428 static int virtnet_probe(struct dev *dev, struct pci_device *pci)
429 {
430    struct nic *nic = (struct nic *)dev;
431    u32 features;
432    int i;
433
434    /* Mask the bit that says "this is an io addr" */
435
436    nic->ioaddr = pci->ioaddr & ~3;
437
438    /* Copy IRQ from PCI information */
439
440    nic->irqno = pci->irq;
441
442    printf("I/O address 0x%08x, IRQ #%d\n", nic->ioaddr, nic->irqno);
443
444    adjust_pci_device(pci);
445
446    vp_reset(nic);
447
448    features = vp_get_features(nic);
449    if (features & (1 << VIRTIO_NET_F_MAC)) {
450            vp_get(nic, offsetof(struct virtio_net_config, mac),
451                   nic->node_addr, ETH_ALEN);
452            printf("MAC address %!\n", nic->node_addr);
453    }
454
455    /* initialize emit/receive queue */
456
457    for (i = 0; i < QUEUE_NB; i++) {
458            free_head[i] = 0;
459            last_used_idx[i] = 0;
460            memset((char*)&queue[i], 0, sizeof(queue[i]));
461            if (vp_find_vq(nic, i) == -1)
462                    printf("Cannot register queue #%d\n", i);
463    }
464
465    /* provide some receive buffers */
466
467     provide_buffers(nic);
468
469    /* define NIC interface */
470
471    dev->disable = virtnet_disable;
472    nic->poll = virtnet_poll;
473    nic->transmit = virtnet_transmit;
474    nic->irq = virtnet_irq;
475
476    /* driver is ready */
477
478    vp_set_features(nic, features & (1 << VIRTIO_NET_F_MAC));
479    vp_set_status(nic, VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK);
480
481    return 1;
482 }
483
484 static struct pci_id virtnet_nics[] = {
485 PCI_ROM(0x1af4, 0x1000, "virtio-net",              "Virtio Network Interface"),
486 };
487
488 static struct pci_driver virtnet_driver __pci_driver = {
489    .type     = NIC_DRIVER,
490    .name     = "VIRTIO-NET",
491    .probe    = virtnet_probe,
492    .ids      = virtnet_nics,
493    .id_count = sizeof(virtnet_nics)/sizeof(virtnet_nics[0]),
494    .class    = 0,
495 };