Browse Source

[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>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
a5c016d93e
2 changed files with 13 additions and 16 deletions
  1. 13
    5
      src/core/iobuf.c
  2. 0
    11
      src/include/ipxe/iobuf.h

+ 13
- 5
src/core/iobuf.c View File

19
 FILE_LICENCE ( GPL2_OR_LATER );
19
 FILE_LICENCE ( GPL2_OR_LATER );
20
 
20
 
21
 #include <stdint.h>
21
 #include <stdint.h>
22
+#include <strings.h>
22
 #include <errno.h>
23
 #include <errno.h>
23
 #include <ipxe/malloc.h>
24
 #include <ipxe/malloc.h>
24
 #include <ipxe/iobuf.h>
25
 #include <ipxe/iobuf.h>
40
  */
41
  */
41
 struct io_buffer * alloc_iob ( size_t len ) {
42
 struct io_buffer * alloc_iob ( size_t len ) {
42
 	struct io_buffer *iobuf = NULL;
43
 	struct io_buffer *iobuf = NULL;
44
+	size_t align;
43
 	void *data;
45
 	void *data;
44
 
46
 
45
 	/* Pad to minimum length */
47
 	/* Pad to minimum length */
46
 	if ( len < IOB_ZLEN )
48
 	if ( len < IOB_ZLEN )
47
 		len = IOB_ZLEN;
49
 		len = IOB_ZLEN;
48
 
50
 
49
-	/* Align buffer length */
50
-	len = ( len + __alignof__( *iobuf ) - 1 ) &
51
-		~( __alignof__( *iobuf ) - 1 );
52
-	
51
+	/* Align buffer length to ensure that struct io_buffer is aligned */
52
+	len = ( len + __alignof__ ( *iobuf ) - 1 ) &
53
+		~( __alignof__ ( *iobuf ) - 1 );
54
+
55
+	/* Align buffer on its own size to avoid potential problems
56
+	 * with boundary-crossing DMA.
57
+	 */
58
+	align = ( 1 << fls ( len - 1 ) );
59
+
53
 	/* Allocate memory for buffer plus descriptor */
60
 	/* Allocate memory for buffer plus descriptor */
54
-	data = malloc_dma ( len + sizeof ( *iobuf ), IOB_ALIGN );
61
+	data = malloc_dma ( len + sizeof ( *iobuf ), align );
55
 	if ( ! data )
62
 	if ( ! data )
56
 		return NULL;
63
 		return NULL;
57
 
64
 
61
 	return iobuf;
68
 	return iobuf;
62
 }
69
 }
63
 
70
 
71
+
64
 /**
72
 /**
65
  * Free I/O buffer
73
  * Free I/O buffer
66
  *
74
  *

+ 0
- 11
src/include/ipxe/iobuf.h View File

13
 #include <assert.h>
13
 #include <assert.h>
14
 #include <ipxe/list.h>
14
 #include <ipxe/list.h>
15
 
15
 
16
-/**
17
- * I/O buffer alignment
18
- *
19
- * I/O buffers allocated via alloc_iob() are guaranteed to be
20
- * physically aligned to this boundary.  Some cards cannot DMA across
21
- * a 4kB boundary.  With a standard Ethernet MTU, aligning to a 2kB
22
- * boundary is sufficient to guarantee no 4kB boundary crossings.  For
23
- * a jumbo Ethernet MTU, a packet may be larger than 4kB anyway.
24
- */
25
-#define IOB_ALIGN 2048
26
-
27
 /**
16
 /**
28
  * Minimum I/O buffer length
17
  * Minimum I/O buffer length
29
  *
18
  *

Loading…
Cancel
Save