|
|
1.1 root 1: /*
2: * (c) Copyright 2010 Stefan Hajnoczi <[email protected]>
3: *
4: * based on the Etherboot virtio-net driver
5: *
6: * (c) Copyright 2008 Bull S.A.S.
7: *
8: * Author: Laurent Vivier <[email protected]>
9: *
10: * some parts from Linux Virtio PCI driver
11: *
12: * Copyright IBM Corp. 2007
13: * Authors: Anthony Liguori <[email protected]>
14: *
15: * some parts from Linux Virtio Ring
16: *
17: * Copyright Rusty Russell IBM Corporation 2007
18: *
19: * This work is licensed under the terms of the GNU GPL, version 2 or later.
20: * See the COPYING file in the top-level directory.
21: */
22:
23: FILE_LICENCE ( GPL2_OR_LATER );
24:
25: #include <errno.h>
26: #include <stdlib.h>
27: #include <ipxe/list.h>
28: #include <ipxe/iobuf.h>
29: #include <ipxe/netdevice.h>
30: #include <ipxe/pci.h>
31: #include <ipxe/if_ether.h>
32: #include <ipxe/ethernet.h>
33: #include <ipxe/virtio-ring.h>
34: #include <ipxe/virtio-pci.h>
35: #include "virtio-net.h"
36:
37: /*
38: * Virtio network device driver
39: *
40: * Specification:
41: * http://ozlabs.org/~rusty/virtio-spec/
42: *
43: * The virtio network device is supported by Linux virtualization software
44: * including QEMU/KVM and lguest. This driver supports the virtio over PCI
45: * transport; virtual machines have one virtio-net PCI adapter per NIC.
46: *
47: * Virtio-net is different from hardware NICs because virtio devices
48: * communicate with the hypervisor via virtqueues, not traditional descriptor
49: * rings. Virtqueues are unordered queues, they support add_buf() and
50: * get_buf() operations. To transmit a packet, the driver has to add the
51: * packet buffer onto the virtqueue. To receive a packet, the driver must
52: * first add an empty buffer to the virtqueue and then get the filled packet
53: * buffer on completion.
54: *
55: * Virtqueues are an abstraction that is commonly implemented using the vring
56: * descriptor ring layout. The vring is the actual shared memory structure
57: * that allows the virtual machine to communicate buffers with the hypervisor.
58: * Because the vring layout is optimized for flexibility and performance rather
59: * than space, it is heavy-weight and allocated like traditional descriptor
60: * rings in the open() function of the driver and not in probe().
61: *
62: * There is no true interrupt enable/disable. Virtqueues have callback
63: * enable/disable flags but these are only hints. The hypervisor may still
64: * raise an interrupt. Nevertheless, this driver disables callbacks in the
65: * hopes of avoiding interrupts.
66: */
67:
68: /* Driver types are declared here so virtio-net.h can be easily synced with its
69: * Linux source.
70: */
71:
72: /* Virtqueue indicies */
73: enum {
74: RX_INDEX = 0,
75: TX_INDEX,
76: QUEUE_NB
77: };
78:
79: enum {
80: /** Max number of pending rx packets */
81: NUM_RX_BUF = 8,
82:
83: /** Max Ethernet frame length, including FCS and VLAN tag */
84: RX_BUF_SIZE = 1522,
85: };
86:
87: struct virtnet_nic {
88: /** Base pio register address */
89: unsigned long ioaddr;
90:
91: /** RX/TX virtqueues */
92: struct vring_virtqueue *virtqueue;
93:
94: /** RX packets handed to the NIC waiting to be filled in */
95: struct list_head rx_iobufs;
96:
97: /** Pending rx packet count */
98: unsigned int rx_num_iobufs;
99:
100: /** Virtio net packet header, we only need one */
101: struct virtio_net_hdr empty_header;
102: };
103:
104: /** Add an iobuf to a virtqueue
105: *
106: * @v netdev Network device
107: * @v vq_idx Virtqueue index (RX_INDEX or TX_INDEX)
108: * @v iobuf I/O buffer
109: *
110: * The virtqueue is kicked after the iobuf has been added.
111: */
112: static void virtnet_enqueue_iob ( struct net_device *netdev,
113: int vq_idx, struct io_buffer *iobuf ) {
114: struct virtnet_nic *virtnet = netdev->priv;
115: struct vring_virtqueue *vq = &virtnet->virtqueue[vq_idx];
116: unsigned int out = ( vq_idx == TX_INDEX ) ? 2 : 0;
117: unsigned int in = ( vq_idx == TX_INDEX ) ? 0 : 2;
118: struct vring_list list[] = {
119: {
120: /* Share a single zeroed virtio net header between all
121: * rx and tx packets. This works because this driver
122: * does not use any advanced features so none of the
123: * header fields get used.
124: */
125: .addr = ( char* ) &virtnet->empty_header,
126: .length = sizeof ( virtnet->empty_header ),
127: },
128: {
129: .addr = ( char* ) iobuf->data,
130: .length = iob_len ( iobuf ),
131: },
132: };
133:
134: DBGC ( virtnet, "VIRTIO-NET %p enqueuing iobuf %p on vq %d\n",
135: virtnet, iobuf, vq_idx );
136:
137: vring_add_buf ( vq, list, out, in, iobuf, 0 );
138: vring_kick ( virtnet->ioaddr, vq, 1 );
139: }
140:
141: /** Try to keep rx virtqueue filled with iobufs
142: *
143: * @v netdev Network device
144: */
145: static void virtnet_refill_rx_virtqueue ( struct net_device *netdev ) {
146: struct virtnet_nic *virtnet = netdev->priv;
147:
148: while ( virtnet->rx_num_iobufs < NUM_RX_BUF ) {
149: struct io_buffer *iobuf;
150:
151: /* Try to allocate a buffer, stop for now if out of memory */
152: iobuf = alloc_iob ( RX_BUF_SIZE );
153: if ( ! iobuf )
154: break;
155:
156: /* Keep track of iobuf so close() can free it */
157: list_add ( &iobuf->list, &virtnet->rx_iobufs );
158:
159: /* Mark packet length until we know the actual size */
160: iob_put ( iobuf, RX_BUF_SIZE );
161:
162: virtnet_enqueue_iob ( netdev, RX_INDEX, iobuf );
163: virtnet->rx_num_iobufs++;
164: }
165: }
166:
167: /** Open network device
168: *
169: * @v netdev Network device
170: * @ret rc Return status code
171: */
172: static int virtnet_open ( struct net_device *netdev ) {
173: struct virtnet_nic *virtnet = netdev->priv;
174: unsigned long ioaddr = virtnet->ioaddr;
175: u32 features;
176: int i;
177:
178: /* Reset for sanity */
179: vp_reset ( ioaddr );
180:
181: /* Allocate virtqueues */
182: virtnet->virtqueue = zalloc ( QUEUE_NB *
183: sizeof ( *virtnet->virtqueue ) );
184: if ( ! virtnet->virtqueue )
185: return -ENOMEM;
186:
187: /* Initialize rx/tx virtqueues */
188: for ( i = 0; i < QUEUE_NB; i++ ) {
189: if ( vp_find_vq ( ioaddr, i, &virtnet->virtqueue[i] ) == -1 ) {
190: DBGC ( virtnet, "VIRTIO-NET %p cannot register queue %d\n",
191: virtnet, i );
192: free ( virtnet->virtqueue );
193: virtnet->virtqueue = NULL;
194: return -ENOENT;
195: }
196: }
197:
198: /* Initialize rx packets */
199: INIT_LIST_HEAD ( &virtnet->rx_iobufs );
200: virtnet->rx_num_iobufs = 0;
201: virtnet_refill_rx_virtqueue ( netdev );
202:
203: /* Disable interrupts before starting */
204: netdev_irq ( netdev, 0 );
205:
206: /* Driver is ready */
207: features = vp_get_features ( ioaddr );
208: vp_set_features ( ioaddr, features & ( 1 << VIRTIO_NET_F_MAC ) );
209: vp_set_status ( ioaddr, VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK );
210: return 0;
211: }
212:
213: /** Close network device
214: *
215: * @v netdev Network device
216: */
217: static void virtnet_close ( struct net_device *netdev ) {
218: struct virtnet_nic *virtnet = netdev->priv;
219: struct io_buffer *iobuf;
220: struct io_buffer *next_iobuf;
221:
222: vp_reset ( virtnet->ioaddr );
223:
224: /* Virtqueues can be freed now that NIC is reset */
225: free ( virtnet->virtqueue );
226: virtnet->virtqueue = NULL;
227:
228: /* Free rx iobufs */
229: list_for_each_entry_safe ( iobuf, next_iobuf, &virtnet->rx_iobufs, list ) {
230: free_iob ( iobuf );
231: }
232: INIT_LIST_HEAD ( &virtnet->rx_iobufs );
233: virtnet->rx_num_iobufs = 0;
234: }
235:
236: /** Transmit packet
237: *
238: * @v netdev Network device
239: * @v iobuf I/O buffer
240: * @ret rc Return status code
241: */
242: static int virtnet_transmit ( struct net_device *netdev,
243: struct io_buffer *iobuf ) {
244: virtnet_enqueue_iob ( netdev, TX_INDEX, iobuf );
245: return 0;
246: }
247:
248: /** Complete packet transmission
249: *
250: * @v netdev Network device
251: */
252: static void virtnet_process_tx_packets ( struct net_device *netdev ) {
253: struct virtnet_nic *virtnet = netdev->priv;
254: struct vring_virtqueue *tx_vq = &virtnet->virtqueue[TX_INDEX];
255:
256: while ( vring_more_used ( tx_vq ) ) {
257: struct io_buffer *iobuf = vring_get_buf ( tx_vq, NULL );
258:
259: DBGC ( virtnet, "VIRTIO-NET %p tx complete iobuf %p\n",
260: virtnet, iobuf );
261:
262: netdev_tx_complete ( netdev, iobuf );
263: }
264: }
265:
266: /** Complete packet reception
267: *
268: * @v netdev Network device
269: */
270: static void virtnet_process_rx_packets ( struct net_device *netdev ) {
271: struct virtnet_nic *virtnet = netdev->priv;
272: struct vring_virtqueue *rx_vq = &virtnet->virtqueue[RX_INDEX];
273:
274: while ( vring_more_used ( rx_vq ) ) {
275: unsigned int len;
276: struct io_buffer *iobuf = vring_get_buf ( rx_vq, &len );
277:
278: /* Release ownership of iobuf */
279: list_del ( &iobuf->list );
280: virtnet->rx_num_iobufs--;
281:
282: /* Update iobuf length */
283: iob_unput ( iobuf, RX_BUF_SIZE );
284: iob_put ( iobuf, len - sizeof ( struct virtio_net_hdr ) );
285:
286: DBGC ( virtnet, "VIRTIO-NET %p rx complete iobuf %p len %zd\n",
287: virtnet, iobuf, iob_len ( iobuf ) );
288:
289: /* Pass completed packet to the network stack */
290: netdev_rx ( netdev, iobuf );
291: }
292:
293: virtnet_refill_rx_virtqueue ( netdev );
294: }
295:
296: /** Poll for completed and received packets
297: *
298: * @v netdev Network device
299: */
300: static void virtnet_poll ( struct net_device *netdev ) {
301: struct virtnet_nic *virtnet = netdev->priv;
302:
303: /* Acknowledge interrupt. This is necessary for UNDI operation and
304: * interrupts that are raised despite VRING_AVAIL_F_NO_INTERRUPT being
305: * set (that flag is just a hint and the hypervisor not not have to
306: * honor it).
307: */
308: vp_get_isr ( virtnet->ioaddr );
309:
310: virtnet_process_tx_packets ( netdev );
311: virtnet_process_rx_packets ( netdev );
312: }
313:
314: /** Enable or disable interrupts
315: *
316: * @v netdev Network device
317: * @v enable Interrupts should be enabled
318: */
319: static void virtnet_irq ( struct net_device *netdev, int enable ) {
320: struct virtnet_nic *virtnet = netdev->priv;
321: int i;
322:
323: for ( i = 0; i < QUEUE_NB; i++ ) {
324: if ( enable )
325: vring_enable_cb ( &virtnet->virtqueue[i] );
326: else
327: vring_disable_cb ( &virtnet->virtqueue[i] );
328: }
329: }
330:
331: /** virtio-net device operations */
332: static struct net_device_operations virtnet_operations = {
333: .open = virtnet_open,
334: .close = virtnet_close,
335: .transmit = virtnet_transmit,
336: .poll = virtnet_poll,
337: .irq = virtnet_irq,
338: };
339:
340: /**
341: * Probe PCI device
342: *
343: * @v pci PCI device
344: * @v id PCI ID
345: * @ret rc Return status code
346: */
347: static int virtnet_probe ( struct pci_device *pci ) {
348: unsigned long ioaddr = pci->ioaddr;
349: struct net_device *netdev;
350: struct virtnet_nic *virtnet;
351: u32 features;
352: int rc;
353:
354: /* Allocate and hook up net device */
355: netdev = alloc_etherdev ( sizeof ( *virtnet ) );
356: if ( ! netdev )
357: return -ENOMEM;
358: netdev_init ( netdev, &virtnet_operations );
359: virtnet = netdev->priv;
360: virtnet->ioaddr = ioaddr;
361: pci_set_drvdata ( pci, netdev );
362: netdev->dev = &pci->dev;
363:
364: DBGC ( virtnet, "VIRTIO-NET %p busaddr=%s ioaddr=%#lx irq=%d\n",
365: virtnet, pci->dev.name, ioaddr, pci->irq );
366:
367: /* Enable PCI bus master and reset NIC */
368: adjust_pci_device ( pci );
369: vp_reset ( ioaddr );
370:
371: /* Load MAC address */
372: features = vp_get_features ( ioaddr );
373: if ( features & ( 1 << VIRTIO_NET_F_MAC ) ) {
374: vp_get ( ioaddr, offsetof ( struct virtio_net_config, mac ),
375: netdev->hw_addr, ETH_ALEN );
376: DBGC ( virtnet, "VIRTIO-NET %p mac=%s\n", virtnet,
377: eth_ntoa ( netdev->hw_addr ) );
378: }
379:
380: /* Register network device */
381: if ( ( rc = register_netdev ( netdev ) ) != 0 )
382: goto err_register_netdev;
383:
384: /* Mark link as up, control virtqueue is not used */
385: netdev_link_up ( netdev );
386:
387: return 0;
388:
389: unregister_netdev ( netdev );
390: err_register_netdev:
391: vp_reset ( ioaddr );
392: netdev_nullify ( netdev );
393: netdev_put ( netdev );
394: return rc;
395: }
396:
397: /**
398: * Remove device
399: *
400: * @v pci PCI device
401: */
402: static void virtnet_remove ( struct pci_device *pci ) {
403: struct net_device *netdev = pci_get_drvdata ( pci );
404:
405: unregister_netdev ( netdev );
406: netdev_nullify ( netdev );
407: netdev_put ( netdev );
408: }
409:
410: static struct pci_device_id virtnet_nics[] = {
411: PCI_ROM(0x1af4, 0x1000, "virtio-net", "Virtio Network Interface", 0),
412: };
413:
414: struct pci_driver virtnet_driver __pci_driver = {
415: .ids = virtnet_nics,
416: .id_count = ( sizeof ( virtnet_nics ) / sizeof ( virtnet_nics[0] ) ),
417: .probe = virtnet_probe,
418: .remove = virtnet_remove,
419: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.