Annotation of qemu/roms/ipxe/src/drivers/net/virtio-net.c, revision 1.1.1.1

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: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.