iPXE
virtio-net.c File Reference
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <ipxe/list.h>
#include <ipxe/iobuf.h>
#include <ipxe/netdevice.h>
#include <ipxe/pci.h>
#include <ipxe/dma.h>
#include <ipxe/if_ether.h>
#include <ipxe/ethernet.h>
#include <ipxe/virtio-pci.h>
#include <ipxe/virtio-ring.h>
#include "virtio-net.h"

Go to the source code of this file.

Data Structures

struct  virtnet_nic

Macros

#define NUM_RX_BUF   8
 Max number of pending rx packets.

Enumerations

enum  { RX_INDEX = 0 , TX_INDEX , QUEUE_NB }

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static void virtnet_enqueue_iob (struct net_device *netdev, int vq_idx, struct io_buffer *iobuf)
 Add an iobuf to a virtqueue.
static void virtnet_refill_rx_virtqueue (struct net_device *netdev)
 Try to keep rx virtqueue filled with iobufs.
static void virtnet_free_virtqueues (struct net_device *netdev)
 Helper to free all virtqueue memory.
static int virtnet_open_legacy (struct net_device *netdev)
 Open network device, legacy virtio 0.9.5.
static int virtnet_open_modern (struct net_device *netdev)
 Open network device, modern virtio 1.0.
static int virtnet_open (struct net_device *netdev)
 Open network device.
static void virtnet_close (struct net_device *netdev)
 Close network device.
static int virtnet_transmit (struct net_device *netdev, struct io_buffer *iobuf)
 Transmit packet.
static void virtnet_process_tx_packets (struct net_device *netdev)
 Complete packet transmission.
static void virtnet_process_rx_packets (struct net_device *netdev)
 Complete packet reception.
static void virtnet_poll (struct net_device *netdev)
 Poll for completed and received packets.
static void virtnet_irq (struct net_device *netdev, int enable)
 Enable or disable interrupts.
static int virtnet_probe_legacy (struct pci_device *pci)
 Probe PCI device, legacy virtio 0.9.5.
static int virtnet_probe_modern (struct pci_device *pci, int *found_dev)
 Probe PCI device, modern virtio 1.0.
static int virtnet_probe (struct pci_device *pci)
 Probe PCI device.
static void virtnet_remove (struct pci_device *pci)
 Remove device.

Variables

static struct net_device_operations virtnet_operations
 virtio-net device operations
static struct pci_device_id virtnet_nics []
struct pci_driver virtnet_driver __pci_driver

Macro Definition Documentation

◆ NUM_RX_BUF

#define NUM_RX_BUF   8

Max number of pending rx packets.

Definition at line 82 of file virtio-net.c.

Referenced by virtnet_refill_rx_virtqueue().

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
RX_INDEX 
TX_INDEX 
QUEUE_NB 

Definition at line 75 of file virtio-net.c.

75 {
76 RX_INDEX = 0,
79};
@ QUEUE_NB
Definition virtio-net.c:78
@ TX_INDEX
Definition virtio-net.c:77
@ RX_INDEX
Definition virtio-net.c:76

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ virtnet_enqueue_iob()

void virtnet_enqueue_iob ( struct net_device * netdev,
int vq_idx,
struct io_buffer * iobuf )
static

Add an iobuf to a virtqueue.

Parameters
netdevNetwork device
vq_idxVirtqueue index (RX_INDEX or TX_INDEX)
iobufI/O buffer

The virtqueue is kicked after the iobuf has been added.

Definition at line 116 of file virtio-net.c.

117 {
118 struct virtnet_nic *virtnet = netdev->priv;
119 struct vring_virtqueue *vq = &virtnet->virtqueue[vq_idx];
121 unsigned int out = ( vq_idx == TX_INDEX ) ? 2 : 0;
122 unsigned int in = ( vq_idx == TX_INDEX ) ? 0 : 2;
123 size_t header_len = ( virtnet->virtio_version ?
124 sizeof ( *header ) : sizeof ( header->legacy ) );
125 struct vring_list list[] = {
126 {
127 /* Share a single zeroed virtio net header between all
128 * packets in a ring. This works because this driver
129 * does not use any advanced features so none of the
130 * header fields get used.
131 *
132 * Some host implementations (notably Google Compute
133 * Platform) are known to unconditionally write back
134 * to header->flags for received packets. Work around
135 * this by using separate RX and TX headers.
136 */
137 .addr = dma ( &vq->map, header ),
138 .length = header_len,
139 },
140 {
141 .addr = iob_dma ( iobuf ),
142 .length = iob_len ( iobuf ),
143 },
144 };
145
146 DBGC2 ( virtnet, "VIRTIO-NET %p enqueuing iobuf %p on vq %d\n",
147 virtnet, iobuf, vq_idx );
148
149 vring_add_buf ( vq, list, out, in, iobuf, 0 );
150 vring_kick ( virtnet->virtio_version ? &virtnet->vdev : NULL,
151 virtnet->ioaddr, vq, 1 );
152}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
__be32 in[4]
Definition CIB_PRM.h:7
__be32 out[4]
Definition CIB_PRM.h:8
struct ena_llq_option header
Header locations.
Definition ena.h:5
static struct net_device * netdev
Definition gdbudp.c:53
#define DBGC2(...)
Definition compiler.h:522
static __always_inline physaddr_t iob_dma(struct io_buffer *iobuf)
Get I/O buffer DMA address.
Definition iobuf.h:268
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
physaddr_t dma(struct dma_mapping *map, void *addr)
Get DMA address from virtual address.
struct virtio_pci_modern_device vdev
Virtio 1.0 device data.
Definition virtio-net.c:92
unsigned long ioaddr
Base pio register address.
Definition virtio-net.c:86
int virtio_version
0 for legacy, 1 for virtio 1.0
Definition virtio-net.c:89
struct vring_virtqueue * virtqueue
RX/TX virtqueues.
Definition virtio-net.c:95
struct virtio_net_hdr_modern * empty_header
Definition virtio-ring.h:85
struct dma_mapping map
Definition virtio-ring.h:79
void vring_kick(struct virtio_pci_modern_device *vdev, unsigned int ioaddr, struct vring_virtqueue *vq, int num_added)
void vring_add_buf(struct vring_virtqueue *vq, struct vring_list list[], unsigned int out, unsigned int in, void *opaque, int num_added)
Definition virtio-ring.c:86

References DBGC2, dma(), vring_virtqueue::empty_header, header, in, virtnet_nic::ioaddr, iob_dma(), iob_len(), vring_virtqueue::map, netdev, NULL, out, TX_INDEX, virtnet_nic::vdev, virtnet_nic::virtio_version, virtnet_nic::virtqueue, vring_add_buf(), and vring_kick().

Referenced by virtnet_refill_rx_virtqueue(), and virtnet_transmit().

◆ virtnet_refill_rx_virtqueue()

void virtnet_refill_rx_virtqueue ( struct net_device * netdev)
static

Try to keep rx virtqueue filled with iobufs.

Parameters
netdevNetwork device

Definition at line 158 of file virtio-net.c.

158 {
159 struct virtnet_nic *virtnet = netdev->priv;
160 size_t len = ( netdev->max_pkt_len + 4 /* VLAN */ );
161
162 while ( virtnet->rx_num_iobufs < NUM_RX_BUF ) {
163 struct io_buffer *iobuf;
164
165 /* Try to allocate a buffer, stop for now if out of memory */
166 iobuf = alloc_rx_iob ( len, virtnet->dma );
167 if ( ! iobuf )
168 break;
169
170 /* Keep track of iobuf so close() can free it */
171 list_add ( &iobuf->list, &virtnet->rx_iobufs );
172
173 /* Mark packet length until we know the actual size */
174 iob_put ( iobuf, len );
175
177 virtnet->rx_num_iobufs++;
178 }
179}
ring len
Length.
Definition dwmac.h:226
struct io_buffer * alloc_rx_iob(size_t len, struct dma_device *dma)
Allocate and map I/O buffer for receive DMA.
Definition iobuf.c:188
#define iob_put(iobuf, len)
Definition iobuf.h:125
#define list_add(new, head)
Add a new entry to the head of a list.
Definition list.h:70
A persistent I/O buffer.
Definition iobuf.h:38
struct list_head list
List of which this buffer is a member.
Definition iobuf.h:45
struct list_head rx_iobufs
RX packets handed to the NIC waiting to be filled in.
Definition virtio-net.c:98
struct dma_device * dma
DMA device.
Definition virtio-net.c:104
unsigned int rx_num_iobufs
Pending rx packet count.
Definition virtio-net.c:101
static void virtnet_enqueue_iob(struct net_device *netdev, int vq_idx, struct io_buffer *iobuf)
Add an iobuf to a virtqueue.
Definition virtio-net.c:116
#define NUM_RX_BUF
Max number of pending rx packets.
Definition virtio-net.c:82

References alloc_rx_iob(), virtnet_nic::dma, iob_put, len, io_buffer::list, list_add, netdev, NUM_RX_BUF, RX_INDEX, virtnet_nic::rx_iobufs, virtnet_nic::rx_num_iobufs, and virtnet_enqueue_iob().

Referenced by virtnet_open_legacy(), virtnet_open_modern(), and virtnet_process_rx_packets().

◆ virtnet_free_virtqueues()

void virtnet_free_virtqueues ( struct net_device * netdev)
static

Helper to free all virtqueue memory.

Parameters
netdevNetwork device

Definition at line 185 of file virtio-net.c.

185 {
186 struct virtnet_nic *virtnet = netdev->priv;
187 int i;
188
189 for ( i = 0; i < QUEUE_NB; i++ ) {
191 vp_free_vq ( &virtnet->virtqueue[i] );
192 }
193
194 free ( virtnet->virtqueue );
195 virtnet->virtqueue = NULL;
196}
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
struct virtio_pci_region notification
Definition virtio-ring.h:88
void vp_free_vq(struct vring_virtqueue *vq)
Definition virtio-pci.c:48
void virtio_pci_unmap_capability(struct virtio_pci_region *region)
Definition virtio-pci.c:346

References free, netdev, vring_virtqueue::notification, NULL, QUEUE_NB, virtio_pci_unmap_capability(), virtnet_nic::virtqueue, and vp_free_vq().

Referenced by virtnet_close(), virtnet_open_legacy(), and virtnet_open_modern().

◆ virtnet_open_legacy()

int virtnet_open_legacy ( struct net_device * netdev)
static

Open network device, legacy virtio 0.9.5.

Parameters
netdevNetwork device
Return values
rcReturn status code

Definition at line 203 of file virtio-net.c.

203 {
204 struct virtnet_nic *virtnet = netdev->priv;
205 unsigned long ioaddr = virtnet->ioaddr;
207 int i;
208
209 /* Reset for sanity */
210 vp_reset ( ioaddr );
211
212 /* Allocate virtqueues */
213 virtnet->virtqueue = zalloc ( QUEUE_NB *
214 sizeof ( *virtnet->virtqueue ) );
215 if ( ! virtnet->virtqueue )
216 return -ENOMEM;
217
218 /* Initialize rx/tx virtqueues */
219 for ( i = 0; i < QUEUE_NB; i++ ) {
220 if ( vp_find_vq ( ioaddr, i, &virtnet->virtqueue[i], virtnet->dma,
221 sizeof ( struct virtio_net_hdr_modern ) ) == -1 ) {
222 DBGC ( virtnet, "VIRTIO-NET %p cannot register queue %d\n",
223 virtnet, i );
225 return -ENOENT;
226 }
227 }
228
229 /* Initialize rx packets */
230 INIT_LIST_HEAD ( &virtnet->rx_iobufs );
231 virtnet->rx_num_iobufs = 0;
233
234 /* Disable interrupts before starting */
235 netdev_irq ( netdev, 0 );
236
237 /* Driver is ready */
240 ( 1 << VIRTIO_NET_F_MTU ) ) );
242 return 0;
243}
static unsigned long ioaddr
Definition davicom.c:129
uint32_t features
Supported features.
Definition ena.h:5
#define DBGC(...)
Definition compiler.h:505
#define ENOENT
No such file or directory.
Definition errno.h:515
#define ENOMEM
Not enough space.
Definition errno.h:535
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition list.h:46
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
void netdev_irq(struct net_device *netdev, int enable)
Enable or disable interrupts.
Definition netdevice.c:971
#define u32
Definition vga.h:21
static void virtnet_refill_rx_virtqueue(struct net_device *netdev)
Try to keep rx virtqueue filled with iobufs.
Definition virtio-net.c:158
static void virtnet_free_virtqueues(struct net_device *netdev)
Helper to free all virtqueue memory.
Definition virtio-net.c:185
#define VIRTIO_NET_F_MTU
Definition virtio-net.h:7
#define VIRTIO_NET_F_MAC
Definition virtio-net.h:8
int vp_find_vq(unsigned int ioaddr, int queue_index, struct vring_virtqueue *vq, struct dma_device *dma_dev, size_t header_size)
Definition virtio-pci.c:58
static u32 vp_get_features(unsigned int ioaddr)
Definition virtio-pci.h:140
static void vp_set_features(unsigned int ioaddr, u32 features)
Definition virtio-pci.h:145
static void vp_reset(unsigned int ioaddr)
Definition virtio-pci.h:177
static void vp_set_status(unsigned int ioaddr, u8 status)
Definition virtio-pci.h:165
#define VIRTIO_CONFIG_S_DRIVER
Definition virtio-ring.h:11
#define VIRTIO_CONFIG_S_DRIVER_OK
Definition virtio-ring.h:13

References DBGC, virtnet_nic::dma, ENOENT, ENOMEM, features, INIT_LIST_HEAD, ioaddr, virtnet_nic::ioaddr, netdev, netdev_irq(), QUEUE_NB, virtnet_nic::rx_iobufs, virtnet_nic::rx_num_iobufs, u32, VIRTIO_CONFIG_S_DRIVER, VIRTIO_CONFIG_S_DRIVER_OK, VIRTIO_NET_F_MAC, VIRTIO_NET_F_MTU, virtnet_free_virtqueues(), virtnet_refill_rx_virtqueue(), virtnet_nic::virtqueue, vp_find_vq(), vp_get_features(), vp_reset(), vp_set_features(), vp_set_status(), and zalloc().

Referenced by virtnet_open().

◆ virtnet_open_modern()

int virtnet_open_modern ( struct net_device * netdev)
static

Open network device, modern virtio 1.0.

Parameters
netdevNetwork device
Return values
rcReturn status code

Definition at line 250 of file virtio-net.c.

250 {
251 struct virtnet_nic *virtnet = netdev->priv;
253 u8 status;
254
255 /* Negotiate features */
256 features = vpm_get_features ( &virtnet->vdev );
257 if ( ! ( features & VIRTIO_F_VERSION_1 ) ) {
259 return -EINVAL;
260 }
261 vpm_set_features ( &virtnet->vdev, features & (
262 ( 1ULL << VIRTIO_NET_F_MAC ) |
263 ( 1ULL << VIRTIO_NET_F_MTU ) |
264 ( 1ULL << VIRTIO_F_VERSION_1 ) |
265 ( 1ULL << VIRTIO_F_ANY_LAYOUT ) |
266 ( 1ULL << VIRTIO_F_IOMMU_PLATFORM ) ) );
268
269 status = vpm_get_status ( &virtnet->vdev );
270 if ( ! ( status & VIRTIO_CONFIG_S_FEATURES_OK ) ) {
271 DBGC ( virtnet, "VIRTIO-NET %p device didn't accept features\n",
272 virtnet );
274 return -EINVAL;
275 }
276
277 /* Allocate virtqueues */
278 virtnet->virtqueue = zalloc ( QUEUE_NB *
279 sizeof ( *virtnet->virtqueue ) );
280 if ( ! virtnet->virtqueue ) {
282 return -ENOMEM;
283 }
284
285 /* Initialize rx/tx virtqueues */
286 if ( vpm_find_vqs ( &virtnet->vdev, QUEUE_NB, virtnet->virtqueue,
287 virtnet->dma, sizeof ( struct virtio_net_hdr_modern ) ) ) {
288 DBGC ( virtnet, "VIRTIO-NET %p cannot register queues\n",
289 virtnet );
292 return -ENOENT;
293 }
294
295 /* Disable interrupts before starting */
296 netdev_irq ( netdev, 0 );
297
299
300 /* Initialize rx packets */
301 INIT_LIST_HEAD ( &virtnet->rx_iobufs );
302 virtnet->rx_num_iobufs = 0;
304 return 0;
305}
uint8_t status
Status.
Definition ena.h:5
#define EINVAL
Invalid argument.
Definition errno.h:429
#define u8
Definition igbvf_osdep.h:40
uint64_t u64
Definition stdint.h:26
int vpm_find_vqs(struct virtio_pci_modern_device *vdev, unsigned nvqs, struct vring_virtqueue *vqs, struct dma_device *dma_dev, size_t header_size)
Definition virtio-pci.c:360
static void vpm_add_status(struct virtio_pci_modern_device *vdev, u8 status)
Definition virtio-pci.h:253
static void vpm_set_features(struct virtio_pci_modern_device *vdev, u64 features)
Definition virtio-pci.h:273
static u64 vpm_get_features(struct virtio_pci_modern_device *vdev)
Definition virtio-pci.h:261
static u8 vpm_get_status(struct virtio_pci_modern_device *vdev)
Definition virtio-pci.h:248
#define VIRTIO_F_IOMMU_PLATFORM
Definition virtio-ring.h:24
#define VIRTIO_CONFIG_S_FEATURES_OK
Definition virtio-ring.h:15
#define VIRTIO_F_ANY_LAYOUT
Definition virtio-ring.h:21
#define VIRTIO_CONFIG_S_FAILED
Definition virtio-ring.h:17
#define VIRTIO_F_VERSION_1
Definition virtio-ring.h:23

References DBGC, virtnet_nic::dma, EINVAL, ENOENT, ENOMEM, features, INIT_LIST_HEAD, netdev, netdev_irq(), QUEUE_NB, virtnet_nic::rx_iobufs, virtnet_nic::rx_num_iobufs, status, u8, virtnet_nic::vdev, VIRTIO_CONFIG_S_DRIVER_OK, VIRTIO_CONFIG_S_FAILED, VIRTIO_CONFIG_S_FEATURES_OK, VIRTIO_F_ANY_LAYOUT, VIRTIO_F_IOMMU_PLATFORM, VIRTIO_F_VERSION_1, VIRTIO_NET_F_MAC, VIRTIO_NET_F_MTU, virtnet_free_virtqueues(), virtnet_refill_rx_virtqueue(), virtnet_nic::virtqueue, vpm_add_status(), vpm_find_vqs(), vpm_get_features(), vpm_get_status(), vpm_set_features(), and zalloc().

Referenced by virtnet_open().

◆ virtnet_open()

int virtnet_open ( struct net_device * netdev)
static

Open network device.

Parameters
netdevNetwork device
Return values
rcReturn status code

Definition at line 312 of file virtio-net.c.

312 {
313 struct virtnet_nic *virtnet = netdev->priv;
314
315 if ( virtnet->virtio_version ) {
316 return virtnet_open_modern ( netdev );
317 } else {
318 return virtnet_open_legacy ( netdev );
319 }
320}
static int virtnet_open_legacy(struct net_device *netdev)
Open network device, legacy virtio 0.9.5.
Definition virtio-net.c:203
static int virtnet_open_modern(struct net_device *netdev)
Open network device, modern virtio 1.0.
Definition virtio-net.c:250

References netdev, virtnet_nic::virtio_version, virtnet_open_legacy(), and virtnet_open_modern().

◆ virtnet_close()

void virtnet_close ( struct net_device * netdev)
static

Close network device.

Parameters
netdevNetwork device

Definition at line 326 of file virtio-net.c.

326 {
327 struct virtnet_nic *virtnet = netdev->priv;
328 struct io_buffer *iobuf;
329 struct io_buffer *next_iobuf;
330
331 if ( virtnet->virtio_version ) {
332 vpm_reset ( &virtnet->vdev );
333 } else {
334 vp_reset ( virtnet->ioaddr );
335 }
336
337 /* Virtqueues can be freed now that NIC is reset */
339
340 /* Free rx iobufs */
341 list_for_each_entry_safe ( iobuf, next_iobuf, &virtnet->rx_iobufs, list ) {
342 free_rx_iob ( iobuf );
343 }
344 INIT_LIST_HEAD ( &virtnet->rx_iobufs );
345 virtnet->rx_num_iobufs = 0;
346}
void free_rx_iob(struct io_buffer *iobuf)
Unmap and free I/O buffer for receive DMA.
Definition iobuf.c:215
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition list.h:459
static void vpm_reset(struct virtio_pci_modern_device *vdev)
Definition virtio-pci.h:241

References free_rx_iob(), INIT_LIST_HEAD, virtnet_nic::ioaddr, io_buffer::list, list_for_each_entry_safe, netdev, virtnet_nic::rx_iobufs, virtnet_nic::rx_num_iobufs, virtnet_nic::vdev, virtnet_nic::virtio_version, virtnet_free_virtqueues(), vp_reset(), and vpm_reset().

◆ virtnet_transmit()

int virtnet_transmit ( struct net_device * netdev,
struct io_buffer * iobuf )
static

Transmit packet.

Parameters
netdevNetwork device
iobufI/O buffer
Return values
rcReturn status code

Definition at line 354 of file virtio-net.c.

355 {
357 return 0;
358}

References netdev, TX_INDEX, and virtnet_enqueue_iob().

◆ virtnet_process_tx_packets()

void virtnet_process_tx_packets ( struct net_device * netdev)
static

Complete packet transmission.

Parameters
netdevNetwork device

Definition at line 364 of file virtio-net.c.

364 {
365 struct virtnet_nic *virtnet = netdev->priv;
366 struct vring_virtqueue *tx_vq = &virtnet->virtqueue[TX_INDEX];
367
368 while ( vring_more_used ( tx_vq ) ) {
369 struct io_buffer *iobuf = vring_get_buf ( tx_vq, NULL );
370
371 DBGC2 ( virtnet, "VIRTIO-NET %p tx complete iobuf %p\n",
372 virtnet, iobuf );
373
374 netdev_tx_complete ( netdev, iobuf );
375 }
376}
static void netdev_tx_complete(struct net_device *netdev, struct io_buffer *iobuf)
Complete network transmission.
Definition netdevice.h:767
void * vring_get_buf(struct vring_virtqueue *vq, unsigned int *len)
Definition virtio-ring.c:62
static int vring_more_used(struct vring_virtqueue *vq)

References DBGC2, netdev, netdev_tx_complete(), NULL, TX_INDEX, virtnet_nic::virtqueue, vring_get_buf(), and vring_more_used().

Referenced by virtnet_poll().

◆ virtnet_process_rx_packets()

void virtnet_process_rx_packets ( struct net_device * netdev)
static

Complete packet reception.

Parameters
netdevNetwork device

Definition at line 382 of file virtio-net.c.

382 {
383 struct virtnet_nic *virtnet = netdev->priv;
384 struct vring_virtqueue *rx_vq = &virtnet->virtqueue[RX_INDEX];
385
386 while ( vring_more_used ( rx_vq ) ) {
387 unsigned int len;
388 struct io_buffer *iobuf = vring_get_buf ( rx_vq, &len );
389
390 /* Release ownership of iobuf */
391 list_del ( &iobuf->list );
392 virtnet->rx_num_iobufs--;
393
394 /* Update iobuf length */
395 iob_unput ( iobuf, iob_len ( iobuf ) );
396 iob_put ( iobuf, len - sizeof ( struct virtio_net_hdr ) );
397
398 DBGC2 ( virtnet, "VIRTIO-NET %p rx complete iobuf %p len %zd\n",
399 virtnet, iobuf, iob_len ( iobuf ) );
400
401 /* Pass completed packet to the network stack */
402 netdev_rx ( netdev, iobuf );
403 }
404
406}
#define iob_unput(iobuf, len)
Definition iobuf.h:140
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
void netdev_rx(struct net_device *netdev, struct io_buffer *iobuf)
Add packet to receive queue.
Definition netdevice.c:549

References DBGC2, iob_len(), iob_put, iob_unput, len, io_buffer::list, list_del, netdev, netdev_rx(), RX_INDEX, virtnet_nic::rx_num_iobufs, virtnet_refill_rx_virtqueue(), virtnet_nic::virtqueue, vring_get_buf(), and vring_more_used().

Referenced by virtnet_poll().

◆ virtnet_poll()

void virtnet_poll ( struct net_device * netdev)
static

Poll for completed and received packets.

Parameters
netdevNetwork device

Definition at line 412 of file virtio-net.c.

412 {
413 struct virtnet_nic *virtnet = netdev->priv;
414
415 /* Acknowledge interrupt. This is necessary for UNDI operation and
416 * interrupts that are raised despite VRING_AVAIL_F_NO_INTERRUPT being
417 * set (that flag is just a hint and the hypervisor does not have to
418 * honor it).
419 */
420 if ( virtnet->virtio_version ) {
421 vpm_get_isr ( &virtnet->vdev );
422 } else {
423 vp_get_isr ( virtnet->ioaddr );
424 }
425
428}
static void virtnet_process_rx_packets(struct net_device *netdev)
Complete packet reception.
Definition virtio-net.c:382
static void virtnet_process_tx_packets(struct net_device *netdev)
Complete packet transmission.
Definition virtio-net.c:364
static u8 vp_get_isr(unsigned int ioaddr)
Definition virtio-pci.h:172
static u8 vpm_get_isr(struct virtio_pci_modern_device *vdev)
Definition virtio-pci.h:295

References virtnet_nic::ioaddr, netdev, virtnet_nic::vdev, virtnet_nic::virtio_version, virtnet_process_rx_packets(), virtnet_process_tx_packets(), vp_get_isr(), and vpm_get_isr().

◆ virtnet_irq()

void virtnet_irq ( struct net_device * netdev,
int enable )
static

Enable or disable interrupts.

Parameters
netdevNetwork device
enableInterrupts should be enabled

Definition at line 435 of file virtio-net.c.

435 {
436 struct virtnet_nic *virtnet = netdev->priv;
437 int i;
438
439 for ( i = 0; i < QUEUE_NB; i++ ) {
440 if ( enable )
441 vring_enable_cb ( &virtnet->virtqueue[i] );
442 else
443 vring_disable_cb ( &virtnet->virtqueue[i] );
444 }
445}
static void vring_disable_cb(struct vring_virtqueue *vq)
static void vring_enable_cb(struct vring_virtqueue *vq)

References netdev, QUEUE_NB, virtnet_nic::virtqueue, vring_disable_cb(), and vring_enable_cb().

◆ virtnet_probe_legacy()

int virtnet_probe_legacy ( struct pci_device * pci)
static

Probe PCI device, legacy virtio 0.9.5.

Parameters
pciPCI device
Return values
rcReturn status code

Definition at line 462 of file virtio-net.c.

462 {
463 unsigned long ioaddr = pci->ioaddr;
464 struct net_device *netdev;
465 struct virtnet_nic *virtnet;
467 u16 mtu;
468 int rc;
469
470 /* Allocate and hook up net device */
471 netdev = alloc_etherdev ( sizeof ( *virtnet ) );
472 if ( ! netdev )
473 return -ENOMEM;
475 virtnet = netdev->priv;
476 virtnet->ioaddr = ioaddr;
477 pci_set_drvdata ( pci, netdev );
478 netdev->dev = &pci->dev;
479
480 DBGC ( virtnet, "VIRTIO-NET %p busaddr=%s ioaddr=%#lx irq=%d\n",
481 virtnet, pci->dev.name, ioaddr, pci->irq );
482
483 /* Enable PCI bus master and reset NIC */
484 adjust_pci_device ( pci );
485
486 /* Configure DMA */
487 virtnet->dma = &pci->dma;
488 dma_set_mask_64bit ( virtnet->dma );
489 netdev->dma = virtnet->dma;
490
491 vp_reset ( ioaddr );
492
493 /* Load MAC address and MTU */
495 if ( features & ( 1 << VIRTIO_NET_F_MAC ) ) {
497 netdev->hw_addr, ETH_ALEN );
498 DBGC ( virtnet, "VIRTIO-NET %p mac=%s\n", virtnet,
499 eth_ntoa ( netdev->hw_addr ) );
500 }
501 if ( features & ( 1ULL << VIRTIO_NET_F_MTU ) ) {
503 &mtu, sizeof ( mtu ) );
504 DBGC ( virtnet, "VIRTIO-NET %p mtu=%d\n", virtnet, mtu );
505 netdev->max_pkt_len = ( mtu + ETH_HLEN );
506 netdev->mtu = mtu;
507 }
508
509 /* Register network device */
510 if ( ( rc = register_netdev ( netdev ) ) != 0 )
511 goto err_register_netdev;
512
513 /* Mark link as up, control virtqueue is not used */
515
516 return 0;
517
519err_register_netdev:
520 vp_reset ( ioaddr );
522 netdev_put ( netdev );
523 return rc;
524}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
uint32_t mtu
Maximum MTU.
Definition ena.h:17
uint8_t mac[ETH_ALEN]
MAC address.
Definition ena.h:13
struct net_device * alloc_etherdev(size_t priv_size)
Allocate Ethernet device.
Definition ethernet.c:265
const char * eth_ntoa(const void *ll_addr)
Transcribe Ethernet address.
Definition ethernet.c:176
#define ETH_ALEN
Definition if_ether.h:9
#define ETH_HLEN
Definition if_ether.h:10
static __always_inline void dma_set_mask_64bit(struct dma_device *dma)
Set 64-bit addressable space mask.
Definition dma.h:467
void unregister_netdev(struct net_device *netdev)
Unregister network device.
Definition netdevice.c:942
int register_netdev(struct net_device *netdev)
Register network device.
Definition netdevice.c:760
static void netdev_link_up(struct net_device *netdev)
Mark network device as having link up.
Definition netdevice.h:789
static void netdev_init(struct net_device *netdev, struct net_device_operations *op)
Initialise a network device.
Definition netdevice.h:519
static void netdev_nullify(struct net_device *netdev)
Stop using a network device.
Definition netdevice.h:532
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition netdevice.h:576
void adjust_pci_device(struct pci_device *pci)
Enable PCI device.
Definition pci.c:241
static void pci_set_drvdata(struct pci_device *pci, void *priv)
Set PCI driver-private data.
Definition pci.h:366
#define offsetof(type, field)
Get offset of a field within a structure.
Definition stddef.h:25
char name[40]
Name.
Definition device.h:79
A network device.
Definition netdevice.h:353
unsigned long ioaddr
I/O address.
Definition pci.h:226
uint8_t irq
Interrupt number.
Definition pci.h:234
struct device dev
Generic device.
Definition pci.h:213
struct dma_device dma
DMA device.
Definition pci.h:215
#define u16
Definition vga.h:20
static struct net_device_operations virtnet_operations
virtio-net device operations
Definition virtio-net.c:448
static void vp_get(unsigned int ioaddr, unsigned offset, void *buf, unsigned len)
Definition virtio-pci.h:150

References adjust_pci_device(), alloc_etherdev(), DBGC, pci_device::dev, pci_device::dma, virtnet_nic::dma, dma_set_mask_64bit(), ENOMEM, ETH_ALEN, ETH_HLEN, eth_ntoa(), features, ioaddr, pci_device::ioaddr, virtnet_nic::ioaddr, pci_device::irq, mac, mtu, device::name, netdev, netdev_init(), netdev_link_up(), netdev_nullify(), netdev_put(), offsetof, pci_set_drvdata(), rc, register_netdev(), u16, u32, unregister_netdev(), VIRTIO_NET_F_MAC, VIRTIO_NET_F_MTU, virtnet_operations, vp_get(), vp_get_features(), and vp_reset().

Referenced by virtnet_probe().

◆ virtnet_probe_modern()

int virtnet_probe_modern ( struct pci_device * pci,
int * found_dev )
static

Probe PCI device, modern virtio 1.0.

Parameters
pciPCI device
found_devSet to non-zero if modern device was found (probe may still fail)
Return values
rcReturn status code

Definition at line 533 of file virtio-net.c.

533 {
534 struct net_device *netdev;
535 struct virtnet_nic *virtnet;
537 u16 mtu;
538 int rc, common, isr, notify, config, device;
539
541 if ( ! common ) {
542 DBG ( "Common virtio capability not found!\n" );
543 return -ENODEV;
544 }
545 *found_dev = 1;
546
550 if ( ! isr || ! notify || ! config ) {
551 DBG ( "Missing virtio capabilities %i/%i/%i/%i\n",
552 common, isr, notify, config );
553 return -EINVAL;
554 }
556
557 /* Allocate and hook up net device */
558 netdev = alloc_etherdev ( sizeof ( *virtnet ) );
559 if ( ! netdev )
560 return -ENOMEM;
562 virtnet = netdev->priv;
563
564 pci_set_drvdata ( pci, netdev );
565 netdev->dev = &pci->dev;
566
567 DBGC ( virtnet, "VIRTIO-NET modern %p busaddr=%s irq=%d\n",
568 virtnet, pci->dev.name, pci->irq );
569
570 virtnet->vdev.pci = pci;
572 sizeof ( struct virtio_pci_common_cfg ), 4,
573 0, sizeof ( struct virtio_pci_common_cfg ),
574 &virtnet->vdev.common );
575 if ( rc )
576 goto err_map_common;
577
578 rc = virtio_pci_map_capability ( pci, isr, sizeof ( u8 ), 1,
579 0, 1,
580 &virtnet->vdev.isr );
581 if ( rc )
582 goto err_map_isr;
583
584 virtnet->vdev.notify_cap_pos = notify;
585 virtnet->vdev.cfg_cap_pos = config;
586
587 /* Map the device capability */
588 if ( device ) {
590 0, 4, 0, sizeof ( struct virtio_net_config ),
591 &virtnet->vdev.device );
592 if ( rc )
593 goto err_map_device;
594 }
595
596 /* Enable the PCI device */
597 adjust_pci_device ( pci );
598
599 /* Configure DMA */
600 virtnet->dma = &pci->dma;
601 dma_set_mask_64bit ( virtnet->dma );
602 netdev->dma = virtnet->dma;
603
604 /* Reset the device and set initial status bits */
605 vpm_reset ( &virtnet->vdev );
608
609 /* Load MAC address and MTU */
610 if ( device ) {
611 features = vpm_get_features ( &virtnet->vdev );
612 if ( features & ( 1ULL << VIRTIO_NET_F_MAC ) ) {
613 vpm_get ( &virtnet->vdev,
614 offsetof ( struct virtio_net_config, mac ),
615 netdev->hw_addr, ETH_ALEN );
616 DBGC ( virtnet, "VIRTIO-NET %p mac=%s\n", virtnet,
617 eth_ntoa ( netdev->hw_addr ) );
618 }
619 if ( features & ( 1ULL << VIRTIO_NET_F_MTU ) ) {
620 vpm_get ( &virtnet->vdev,
621 offsetof ( struct virtio_net_config, mtu ),
622 &mtu, sizeof ( mtu ) );
623 DBGC ( virtnet, "VIRTIO-NET %p mtu=%d\n", virtnet,
624 mtu );
625 netdev->max_pkt_len = ( mtu + ETH_HLEN );
626 }
627 }
628
629 /* We need a valid MAC address */
630 if ( ! is_valid_ether_addr ( netdev->hw_addr ) ) {
631 rc = -EADDRNOTAVAIL;
632 goto err_mac_address;
633 }
634
635 /* Register network device */
636 if ( ( rc = register_netdev ( netdev ) ) != 0 )
637 goto err_register_netdev;
638
639 /* Mark link as up, control virtqueue is not used */
641
642 virtnet->virtio_version = 1;
643 return 0;
644
646err_register_netdev:
647err_mac_address:
648 vpm_reset ( &virtnet->vdev );
650 netdev_put ( netdev );
652err_map_device:
654err_map_isr:
656err_map_common:
657 return rc;
658}
static int is_valid_ether_addr(const void *addr)
Check if Ethernet address is valid.
Definition ethernet.h:78
#define DBG(...)
Print a debugging message.
Definition compiler.h:498
#define EADDRNOTAVAIL
Address not available.
Definition errno.h:309
#define ENODEV
No such device.
Definition errno.h:510
struct ib_cm_common common
Definition ib_mad.h:0
@ isr
Definition sis900.h:26
A hardware device.
Definition device.h:77
struct virtio_pci_region isr
Definition virtio-pci.h:134
struct virtio_pci_region device
Definition virtio-pci.h:131
struct pci_device * pci
Definition virtio-pci.h:122
struct virtio_pci_region common
Definition virtio-pci.h:128
int virtio_pci_map_capability(struct pci_device *pci, int cap, size_t minlen, u32 align, u32 start, u32 size, struct virtio_pci_region *region)
Definition virtio-pci.c:276
int virtio_pci_find_capability(struct pci_device *pci, uint8_t cfg_type)
Definition virtio-pci.c:250
#define VIRTIO_PCI_CAP_PCI_CFG
Definition virtio-pci.h:47
#define VIRTIO_PCI_CAP_DEVICE_CFG
Definition virtio-pci.h:46
#define VIRTIO_PCI_CAP_ISR_CFG
Definition virtio-pci.h:45
static void vpm_get(struct virtio_pci_modern_device *vdev, unsigned offset, void *buf, unsigned len)
Definition virtio-pci.h:285
#define VIRTIO_PCI_CAP_NOTIFY_CFG
Definition virtio-pci.h:44
#define VIRTIO_PCI_CAP_COMMON_CFG
Definition virtio-pci.h:43
#define VIRTIO_CONFIG_S_ACKNOWLEDGE
Definition virtio-ring.h:9

References adjust_pci_device(), alloc_etherdev(), virtio_pci_modern_device::cfg_cap_pos, common, virtio_pci_modern_device::common, DBG, DBGC, pci_device::dev, virtio_pci_modern_device::device, pci_device::dma, virtnet_nic::dma, dma_set_mask_64bit(), EADDRNOTAVAIL, EINVAL, ENODEV, ENOMEM, ETH_ALEN, ETH_HLEN, eth_ntoa(), features, pci_device::irq, is_valid_ether_addr(), isr, virtio_pci_modern_device::isr, mac, mtu, device::name, netdev, netdev_init(), netdev_link_up(), netdev_nullify(), netdev_put(), virtio_pci_modern_device::notify_cap_pos, offsetof, virtio_pci_modern_device::pci, pci_set_drvdata(), rc, register_netdev(), u16, u8, unregister_netdev(), virtnet_nic::vdev, VIRTIO_CONFIG_S_ACKNOWLEDGE, VIRTIO_CONFIG_S_DRIVER, VIRTIO_NET_F_MAC, VIRTIO_NET_F_MTU, VIRTIO_PCI_CAP_COMMON_CFG, VIRTIO_PCI_CAP_DEVICE_CFG, VIRTIO_PCI_CAP_ISR_CFG, VIRTIO_PCI_CAP_NOTIFY_CFG, VIRTIO_PCI_CAP_PCI_CFG, virtio_pci_find_capability(), virtio_pci_map_capability(), virtio_pci_unmap_capability(), virtnet_nic::virtio_version, virtnet_operations, vpm_add_status(), vpm_get(), vpm_get_features(), and vpm_reset().

Referenced by virtnet_probe().

◆ virtnet_probe()

int virtnet_probe ( struct pci_device * pci)
static

Probe PCI device.

Parameters
pciPCI device
Return values
rcReturn status code

Definition at line 666 of file virtio-net.c.

666 {
667 int found_modern = 0;
668 int rc = virtnet_probe_modern ( pci, &found_modern );
669 if ( ! found_modern && pci->device < 0x1040 ) {
670 /* fall back to the legacy probe */
671 rc = virtnet_probe_legacy ( pci );
672 }
673 return rc;
674}
uint16_t device
Device ID.
Definition pci.h:230
static int virtnet_probe_legacy(struct pci_device *pci)
Probe PCI device, legacy virtio 0.9.5.
Definition virtio-net.c:462
static int virtnet_probe_modern(struct pci_device *pci, int *found_dev)
Probe PCI device, modern virtio 1.0.
Definition virtio-net.c:533

References pci_device::device, rc, virtnet_probe_legacy(), and virtnet_probe_modern().

◆ virtnet_remove()

void virtnet_remove ( struct pci_device * pci)
static

Remove device.

Parameters
pciPCI device

Definition at line 681 of file virtio-net.c.

681 {
682 struct net_device *netdev = pci_get_drvdata ( pci );
683 struct virtnet_nic *virtnet = netdev->priv;
684
688
691 netdev_put ( netdev );
692}
static void * pci_get_drvdata(struct pci_device *pci)
Get PCI driver-private data.
Definition pci.h:376

References virtio_pci_modern_device::common, virtio_pci_modern_device::device, virtio_pci_modern_device::isr, netdev, netdev_nullify(), netdev_put(), pci_get_drvdata(), unregister_netdev(), virtnet_nic::vdev, and virtio_pci_unmap_capability().

Variable Documentation

◆ virtnet_operations

struct net_device_operations virtnet_operations
static
Initial value:
= {
.open = virtnet_open,
.close = virtnet_close,
.transmit = virtnet_transmit,
.poll = virtnet_poll,
.irq = virtnet_irq,
}
static int virtnet_transmit(struct net_device *netdev, struct io_buffer *iobuf)
Transmit packet.
Definition virtio-net.c:354
static void virtnet_close(struct net_device *netdev)
Close network device.
Definition virtio-net.c:326
static void virtnet_irq(struct net_device *netdev, int enable)
Enable or disable interrupts.
Definition virtio-net.c:435
static void virtnet_poll(struct net_device *netdev)
Poll for completed and received packets.
Definition virtio-net.c:412
static int virtnet_open(struct net_device *netdev)
Open network device.
Definition virtio-net.c:312

virtio-net device operations

Definition at line 448 of file virtio-net.c.

448 {
449 .open = virtnet_open,
450 .close = virtnet_close,
451 .transmit = virtnet_transmit,
452 .poll = virtnet_poll,
453 .irq = virtnet_irq,
454};

Referenced by virtnet_probe_legacy(), and virtnet_probe_modern().

◆ virtnet_nics

struct pci_device_id virtnet_nics[]
static
Initial value:
= {
PCI_ROM(0x1af4, 0x1000, "virtio-net", "Virtio Network Interface", 0),
PCI_ROM(0x1af4, 0x1041, "virtio-net", "Virtio Network Interface 1.0", 0),
}
#define PCI_ROM(_vendor, _device, _name, _description, _data)
Definition pci.h:308

Definition at line 694 of file virtio-net.c.

694 {
695PCI_ROM(0x1af4, 0x1000, "virtio-net", "Virtio Network Interface", 0),
696PCI_ROM(0x1af4, 0x1041, "virtio-net", "Virtio Network Interface 1.0", 0),
697};

◆ __pci_driver

struct pci_driver virtnet_driver __pci_driver
Initial value:
= {
.ids = virtnet_nics,
.id_count = ( sizeof ( virtnet_nics ) / sizeof ( virtnet_nics[0] ) ),
.probe = virtnet_probe,
}
static int virtnet_probe(struct pci_device *pci)
Probe PCI device.
Definition virtio-net.c:666
static struct pci_device_id virtnet_nics[]
Definition virtio-net.c:694
static void virtnet_remove(struct pci_device *pci)
Remove device.
Definition virtio-net.c:681
static struct xen_remove_from_physmap * remove
Definition xenmem.h:40

Definition at line 699 of file virtio-net.c.

699 {
700 .ids = virtnet_nics,
701 .id_count = ( sizeof ( virtnet_nics ) / sizeof ( virtnet_nics[0] ) ),
702 .probe = virtnet_probe,
704};