diff options
Diffstat (limited to 'src/drivers/net/netfront.h')
-rw-r--r-- | src/drivers/net/netfront.h | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/src/drivers/net/netfront.h b/src/drivers/net/netfront.h index 38fd0a77..c95ed264 100644 --- a/src/drivers/net/netfront.h +++ b/src/drivers/net/netfront.h @@ -16,7 +16,20 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #define NETFRONT_NUM_TX_DESC 16 /** Number of receive ring entries */ -#define NETFRONT_NUM_RX_DESC 8 +#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 { @@ -89,6 +102,21 @@ netfront_init_ring ( struct netfront_ring *ring, const char *ref_key, } /** + * 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; +} + +/** * Check whether or not descriptor ring is full * * @v ring Descriptor ring @@ -96,11 +124,8 @@ netfront_init_ring ( struct netfront_ring *ring, const char *ref_key, */ static inline __attribute__ (( always_inline )) int netfront_ring_is_full ( struct netfront_ring *ring ) { - unsigned int fill_level; - fill_level = ( ring->id_prod - ring->id_cons ); - assert ( fill_level <= ring->count ); - return ( fill_level >= ring->count ); + return ( netfront_ring_fill ( ring ) >= ring->count ); } /** @@ -112,7 +137,7 @@ netfront_ring_is_full ( struct netfront_ring *ring ) { static inline __attribute__ (( always_inline )) int netfront_ring_is_empty ( struct netfront_ring *ring ) { - return ( ring->id_prod == ring->id_cons ); + return ( netfront_ring_fill ( ring ) == 0 ); } /** A netfront NIC */ |