|
@@ -32,31 +32,25 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
32
|
32
|
*/
|
33
|
33
|
|
34
|
34
|
/**
|
35
|
|
- * Allocate I/O buffer
|
|
35
|
+ * Allocate I/O buffer with specified alignment and offset
|
36
|
36
|
*
|
37
|
37
|
* @v len Required length of buffer
|
|
38
|
+ * @v align Physical alignment
|
|
39
|
+ * @v offset Offset from physical alignment
|
38
|
40
|
* @ret iobuf I/O buffer, or NULL if none available
|
39
|
41
|
*
|
40
|
|
- * The I/O buffer will be physically aligned to a multiple of
|
41
|
|
- * @c IOBUF_SIZE.
|
|
42
|
+ * @c align will be rounded up to the nearest power of two.
|
42
|
43
|
*/
|
43
|
|
-struct io_buffer * alloc_iob ( size_t len ) {
|
|
44
|
+struct io_buffer * alloc_iob_raw ( size_t len, size_t align, size_t offset ) {
|
44
|
45
|
struct io_buffer *iobuf;
|
45
|
|
- size_t align;
|
46
|
46
|
void *data;
|
47
|
47
|
|
48
|
|
- /* Pad to minimum length */
|
49
|
|
- if ( len < IOB_ZLEN )
|
50
|
|
- len = IOB_ZLEN;
|
51
|
|
-
|
52
|
48
|
/* Align buffer length to ensure that struct io_buffer is aligned */
|
53
|
49
|
len = ( len + __alignof__ ( *iobuf ) - 1 ) &
|
54
|
50
|
~( __alignof__ ( *iobuf ) - 1 );
|
55
|
51
|
|
56
|
|
- /* Align buffer on its own size to avoid potential problems
|
57
|
|
- * with boundary-crossing DMA.
|
58
|
|
- */
|
59
|
|
- align = ( 1 << fls ( len - 1 ) );
|
|
52
|
+ /* Round up alignment to the nearest power of two */
|
|
53
|
+ align = ( 1 << fls ( align - 1 ) );
|
60
|
54
|
|
61
|
55
|
/* Allocate buffer plus descriptor as a single unit, unless
|
62
|
56
|
* doing so will push the total size over the alignment
|
|
@@ -65,7 +59,8 @@ struct io_buffer * alloc_iob ( size_t len ) {
|
65
|
59
|
if ( ( len + sizeof ( *iobuf ) ) <= align ) {
|
66
|
60
|
|
67
|
61
|
/* Allocate memory for buffer plus descriptor */
|
68
|
|
- data = malloc_dma ( len + sizeof ( *iobuf ), align );
|
|
62
|
+ data = malloc_dma_offset ( len + sizeof ( *iobuf ), align,
|
|
63
|
+ offset );
|
69
|
64
|
if ( ! data )
|
70
|
65
|
return NULL;
|
71
|
66
|
iobuf = ( data + len );
|
|
@@ -73,7 +68,7 @@ struct io_buffer * alloc_iob ( size_t len ) {
|
73
|
68
|
} else {
|
74
|
69
|
|
75
|
70
|
/* Allocate memory for buffer */
|
76
|
|
- data = malloc_dma ( len, align );
|
|
71
|
+ data = malloc_dma_offset ( len, align, offset );
|
77
|
72
|
if ( ! data )
|
78
|
73
|
return NULL;
|
79
|
74
|
|
|
@@ -92,6 +87,26 @@ struct io_buffer * alloc_iob ( size_t len ) {
|
92
|
87
|
return iobuf;
|
93
|
88
|
}
|
94
|
89
|
|
|
90
|
+/**
|
|
91
|
+ * Allocate I/O buffer
|
|
92
|
+ *
|
|
93
|
+ * @v len Required length of buffer
|
|
94
|
+ * @ret iobuf I/O buffer, or NULL if none available
|
|
95
|
+ *
|
|
96
|
+ * The I/O buffer will be physically aligned on its own size (rounded
|
|
97
|
+ * up to the nearest power of two).
|
|
98
|
+ */
|
|
99
|
+struct io_buffer * alloc_iob ( size_t len ) {
|
|
100
|
+
|
|
101
|
+ /* Pad to minimum length */
|
|
102
|
+ if ( len < IOB_ZLEN )
|
|
103
|
+ len = IOB_ZLEN;
|
|
104
|
+
|
|
105
|
+ /* Align buffer on its own size to avoid potential problems
|
|
106
|
+ * with boundary-crossing DMA.
|
|
107
|
+ */
|
|
108
|
+ return alloc_iob_raw ( len, len, 0 );
|
|
109
|
+}
|
95
|
110
|
|
96
|
111
|
/**
|
97
|
112
|
* Free I/O buffer
|