| #ifndef _NETFRONT_H | |
| #define _NETFRONT_H | |
| /** @file | |
| * | |
| * Xen netfront driver | |
| * | |
| */ | |
| FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); | |
| FILE_SECBOOT ( PERMITTED ); | |
| #include <ipxe/xen.h> | |
| #include <xen/io/netif.h> | |
| /** Number of transmit ring entries */ | |
| #define NETFRONT_NUM_TX_DESC 16 | |
| /** Number of receive ring entries */ | |
| #define NETFRONT_NUM_RX_DESC 32 | |
| /** Receive ring fill level | |
| * | |
| * The xen-netback driver from kernels 3.18 to 4.2 inclusive have a | |
| * bug (CA-163395) which prevents packet reception if fewer than 18 | |
| * receive descriptors are available. This was fixed in upstream | |
| * kernel commit d5d4852 ("xen-netback: require fewer guest Rx slots | |
| * when not using GSO"). | |
| * | |
| * We provide 18 receive descriptors to avoid unpleasant silent | |
| * failures on these kernel versions. | |
| */ | |
| #define NETFRONT_RX_FILL 18 | |
| /** Grant reference indices */ | |
| enum netfront_ref_index { | |
| /** Transmit ring grant reference index */ | |
| NETFRONT_REF_TX_RING = 0, | |
| /** Transmit descriptor grant reference base index */ | |
| NETFRONT_REF_TX_BASE, | |
| /** Receive ring grant reference index */ | |
| NETFRONT_REF_RX_RING = ( NETFRONT_REF_TX_BASE + NETFRONT_NUM_TX_DESC ), | |
| /** Receive descriptor grant reference base index */ | |
| NETFRONT_REF_RX_BASE, | |
| /** Total number of grant references required */ | |
| NETFRONT_REF_COUNT = ( NETFRONT_REF_RX_BASE + NETFRONT_NUM_RX_DESC ) | |
| }; | |
| /** A netfront descriptor ring */ | |
| struct netfront_ring { | |
| /** Shared ring */ | |
| union { | |
| /** Transmit shared ring */ | |
| netif_tx_sring_t *tx; | |
| /** Receive shared ring */ | |
| netif_rx_sring_t *rx; | |
| /** Raw pointer */ | |
| void *raw; | |
| } sring; | |
| /** Shared ring grant reference key */ | |
| const char *ref_key; | |
| /** Shared ring grant reference */ | |
| grant_ref_t ref; | |
| /** Maximum number of used descriptors */ | |
| size_t count; | |
| /** I/O buffers, indexed by buffer ID */ | |
| struct io_buffer **iobufs; | |
| /** Grant references, indexed by buffer ID */ | |
| grant_ref_t *refs; | |
| /** Buffer ID ring */ | |
| uint8_t *ids; | |
| /** Buffer ID ring producer counter */ | |
| unsigned int id_prod; | |
| /** Buffer ID ring consumer counter */ | |
| unsigned int id_cons; | |
| }; | |
| /** | |
| * Initialise descriptor ring | |
| * | |
| * @v ring Descriptor ring | |
| * @v ref_key Shared ring grant reference key | |
| * @v ref Shared ring grant reference | |
| * @v count Maxium number of used descriptors | |
| * @v iobufs I/O buffers | |
| * @v refs I/O buffer grant references | |
| * @v ids Buffer IDs | |
| */ | |
| static inline __attribute__ (( always_inline )) void | |
| netfront_init_ring ( struct netfront_ring *ring, const char *ref_key, | |
| grant_ref_t ref, unsigned int count, | |
| struct io_buffer **iobufs, grant_ref_t *refs, | |
| uint8_t *ids ) { | |
| ring->ref_key = ref_key; | |
| ring->ref = ref; | |
| ring->count = count; | |
| ring->iobufs = iobufs; | |
| ring->refs = refs; | |
| ring->ids = ids; | |
| } | |
| /** | |
| * Calculate descriptor ring fill level | |
| * | |
| * @v ring Descriptor ring | |
| * @v fill Fill level | |
| */ | |
| static inline __attribute__ (( always_inline )) unsigned int | |
| netfront_ring_fill ( struct netfront_ring *ring ) { | |
| unsigned int fill_level; | |
| fill_level = ( ring->id_prod - ring->id_cons ); | |
| assert ( fill_level <= ring->count ); | |
| return fill_level; | |
| } | |
| /** | |
| * Calculate descriptor ring remaining space | |
| * | |
| * @v ring Descriptor ring | |
| * @v space Number of unused entries | |
| */ | |
| static inline __attribute__ (( always_inline )) unsigned int | |
| netfront_ring_space ( struct netfront_ring *ring ) { | |
| return ( ring->count - netfront_ring_fill ( ring ) ); | |
| } | |
| /** | |
| * Check whether or not descriptor ring is full | |
| * | |
| * @v ring Descriptor ring | |
| * @v is_full Ring is full | |
| */ | |
| static inline __attribute__ (( always_inline )) int | |
| netfront_ring_is_full ( struct netfront_ring *ring ) { | |
| return ( netfront_ring_fill ( ring ) >= ring->count ); | |
| } | |
| /** | |
| * Check whether or not descriptor ring is empty | |
| * | |
| * @v ring Descriptor ring | |
| * @v is_empty Ring is empty | |
| */ | |
| static inline __attribute__ (( always_inline )) int | |
| netfront_ring_is_empty ( struct netfront_ring *ring ) { | |
| return ( netfront_ring_fill ( ring ) == 0 ); | |
| } | |
| /** A netfront NIC */ | |
| struct netfront_nic { | |
| /** Xen device */ | |
| struct xen_device *xendev; | |
| /** Grant references */ | |
| grant_ref_t refs[NETFRONT_REF_COUNT]; | |
| /** Network device */ | |
| struct net_device *netdev; | |
| /** List of netfront NICs */ | |
| struct list_head list; | |
| /** Transmit ring */ | |
| struct netfront_ring tx; | |
| /** Transmit front ring */ | |
| netif_tx_front_ring_t tx_fring; | |
| /** Transmit I/O buffers */ | |
| struct io_buffer *tx_iobufs[NETFRONT_NUM_TX_DESC]; | |
| /** Transmit I/O buffer IDs */ | |
| uint8_t tx_ids[NETFRONT_NUM_TX_DESC]; | |
| /** Receive ring */ | |
| struct netfront_ring rx; | |
| /** Receive front ring */ | |
| netif_rx_front_ring_t rx_fring; | |
| /** Receive I/O buffers */ | |
| struct io_buffer *rx_iobufs[NETFRONT_NUM_RX_DESC]; | |
| /** Receive I/O buffer IDs */ | |
| uint8_t rx_ids[NETFRONT_NUM_RX_DESC]; | |
| /** Partial receive I/O buffer list */ | |
| struct list_head rx_partial; | |
| /** Event channel */ | |
| struct evtchn_send event; | |
| }; | |
| /** Transmit shared ring field */ | |
| #define tx_sring tx.sring.tx | |
| /** Receive shared ring field */ | |
| #define rx_sring rx.sring.rx | |
| #endif /* _NETFRONT_H */ |