diff --git a/src/core/iobuf.c b/src/core/iobuf.c index d776d606..3dfaf18c 100644 --- a/src/core/iobuf.c +++ b/src/core/iobuf.c @@ -19,6 +19,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include +#include #include #include #include @@ -40,18 +41,24 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ struct io_buffer * alloc_iob ( size_t len ) { struct io_buffer *iobuf = NULL; + size_t align; void *data; /* Pad to minimum length */ if ( len < IOB_ZLEN ) len = IOB_ZLEN; - /* Align buffer length */ - len = ( len + __alignof__( *iobuf ) - 1 ) & - ~( __alignof__( *iobuf ) - 1 ); - + /* Align buffer length to ensure that struct io_buffer is aligned */ + len = ( len + __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 */ - data = malloc_dma ( len + sizeof ( *iobuf ), IOB_ALIGN ); + data = malloc_dma ( len + sizeof ( *iobuf ), align ); if ( ! data ) return NULL; @@ -61,6 +68,7 @@ struct io_buffer * alloc_iob ( size_t len ) { return iobuf; } + /** * Free I/O buffer * diff --git a/src/include/ipxe/iobuf.h b/src/include/ipxe/iobuf.h index 82c8b889..8134ae76 100644 --- a/src/include/ipxe/iobuf.h +++ b/src/include/ipxe/iobuf.h @@ -13,17 +13,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include -/** - * 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 *