blob: dca3ff1c519e47b9ae861f8b13ed218b03b11c20 [file] [log] [blame]
#ifndef _NETFRONT_H
#define _NETFRONT_H
/** @file
*
* Xen netfront driver
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#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];
/** 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 */