mirror of https://github.com/ipxe/ipxe.git
[iobuf] Relax alignment requirement for small I/O buffers
iPXE currently aligns all I/O buffers on a 2kB boundary. This is overkill for transmitted packets, which are typically much smaller than 2kB. Align I/O buffers on their own size. This reduces the alignment requirement for small buffers, while preserving the guarantee that I/O buffers will never cross boundaries that might cause problems for some DMA engines. Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/598/head
parent
9a8c6b00d4
commit
a5c016d93e
|
@ -19,6 +19,7 @@
|
||||||
FILE_LICENCE ( GPL2_OR_LATER );
|
FILE_LICENCE ( GPL2_OR_LATER );
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <strings.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <ipxe/malloc.h>
|
#include <ipxe/malloc.h>
|
||||||
#include <ipxe/iobuf.h>
|
#include <ipxe/iobuf.h>
|
||||||
|
@ -40,18 +41,24 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||||
*/
|
*/
|
||||||
struct io_buffer * alloc_iob ( size_t len ) {
|
struct io_buffer * alloc_iob ( size_t len ) {
|
||||||
struct io_buffer *iobuf = NULL;
|
struct io_buffer *iobuf = NULL;
|
||||||
|
size_t align;
|
||||||
void *data;
|
void *data;
|
||||||
|
|
||||||
/* Pad to minimum length */
|
/* Pad to minimum length */
|
||||||
if ( len < IOB_ZLEN )
|
if ( len < IOB_ZLEN )
|
||||||
len = IOB_ZLEN;
|
len = IOB_ZLEN;
|
||||||
|
|
||||||
/* Align buffer length */
|
/* Align buffer length to ensure that struct io_buffer is aligned */
|
||||||
len = ( len + __alignof__ ( *iobuf ) - 1 ) &
|
len = ( len + __alignof__ ( *iobuf ) - 1 ) &
|
||||||
~( __alignof__ ( *iobuf ) - 1 );
|
~( __alignof__ ( *iobuf ) - 1 );
|
||||||
|
|
||||||
|
/* Align buffer on its own size to avoid potential problems
|
||||||
|
* with boundary-crossing DMA.
|
||||||
|
*/
|
||||||
|
align = ( 1 << fls ( len - 1 ) );
|
||||||
|
|
||||||
/* Allocate memory for buffer plus descriptor */
|
/* Allocate memory for buffer plus descriptor */
|
||||||
data = malloc_dma ( len + sizeof ( *iobuf ), IOB_ALIGN );
|
data = malloc_dma ( len + sizeof ( *iobuf ), align );
|
||||||
if ( ! data )
|
if ( ! data )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -61,6 +68,7 @@ struct io_buffer * alloc_iob ( size_t len ) {
|
||||||
return iobuf;
|
return iobuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Free I/O buffer
|
* Free I/O buffer
|
||||||
*
|
*
|
||||||
|
|
|
@ -13,17 +13,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ipxe/list.h>
|
#include <ipxe/list.h>
|
||||||
|
|
||||||
/**
|
|
||||||
* I/O buffer alignment
|
|
||||||
*
|
|
||||||
* I/O buffers allocated via alloc_iob() are guaranteed to be
|
|
||||||
* physically aligned to this boundary. Some cards cannot DMA across
|
|
||||||
* a 4kB boundary. With a standard Ethernet MTU, aligning to a 2kB
|
|
||||||
* boundary is sufficient to guarantee no 4kB boundary crossings. For
|
|
||||||
* a jumbo Ethernet MTU, a packet may be larger than 4kB anyway.
|
|
||||||
*/
|
|
||||||
#define IOB_ALIGN 2048
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minimum I/O buffer length
|
* Minimum I/O buffer length
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue