Add alloc_iob() and free_iob(). (Direct search-and-replace
authorMichael Brown <mcb30@etherboot.org>
Fri, 18 May 2007 14:45:16 +0000 (14:45 +0000)
committerMichael Brown <mcb30@etherboot.org>
Fri, 18 May 2007 14:45:16 +0000 (14:45 +0000)
equivalents for alloc_pkb() and free_pkb(), which will be retired in
due course).

src/core/iobuf.c [new file with mode: 0644]
src/include/gpxe/iobuf.h

diff --git a/src/core/iobuf.c b/src/core/iobuf.c
new file mode 100644 (file)
index 0000000..d04ede5
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdint.h>
+#include <gpxe/malloc.h>
+#include <gpxe/iobuf.h>
+
+/** @file
+ *
+ * I/O buffers
+ *
+ */
+
+/**
+ * Allocate I/O buffer
+ *
+ * @v len      Required length of buffer
+ * @ret iobuf  I/O buffer, or NULL if none available
+ *
+ * The I/O buffer will be physically aligned to a multiple of
+ * @c IOBUF_SIZE.
+ */
+struct io_buffer * alloc_iob ( size_t len ) {
+       struct io_buffer *iobuf = NULL;
+       void *data;
+
+       /* Pad to minimum length */
+       if ( len < IOB_ZLEN )
+               len = IOB_ZLEN;
+
+       /* Align buffer length */
+       len = ( len + __alignof__( *iobuf ) - 1 ) &
+               ~( __alignof__( *iobuf ) - 1 );
+       
+       /* Allocate memory for buffer plus descriptor */
+       data = malloc_dma ( len + sizeof ( *iobuf ), IOB_ALIGN );
+       if ( ! data )
+               return NULL;
+
+       iobuf = ( struct io_buffer * ) ( data + len );
+       iobuf->head = iobuf->data = iobuf->tail = data;
+       iobuf->end = iobuf;
+       return iobuf;
+}
+
+/**
+ * Free I/O buffer
+ *
+ * @v iobuf    I/O buffer
+ */
+void free_iob ( struct io_buffer *iobuf ) {
+       if ( iobuf ) {
+               assert ( iobuf->head <= iobuf->data );
+               assert ( iobuf->data <= iobuf->tail );
+               assert ( iobuf->tail <= iobuf->end );
+               free_dma ( iobuf->head,
+                          ( iobuf->end - iobuf->head ) + sizeof ( *iobuf ) );
+       }
+}
index cf99050..b5de6a5 100644 (file)
 #include <assert.h>
 #include <gpxe/list.h>
 
 #include <assert.h>
 #include <gpxe/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
+ *
+ * alloc_iob() will round up the allocated length to this size if
+ * necessary.  This is used on behalf of hardware that is not capable
+ * of auto-padding.
+ */
+#define IOB_ZLEN 64
+
 /**
  * A persistent I/O buffer
  *
 /**
  * A persistent I/O buffer
  *
@@ -40,109 +60,109 @@ struct io_buffer {
 /**
  * Reserve space at start of I/O buffer
  *
 /**
  * Reserve space at start of I/O buffer
  *
- * @v iob      I/O buffer
+ * @v iobuf    I/O buffer
  * @v len      Length to reserve
  * @ret data   Pointer to new start of buffer
  */
  * @v len      Length to reserve
  * @ret data   Pointer to new start of buffer
  */
-static inline void * iob_reserve ( struct io_buffer *iob, size_t len ) {
-       iob->data += len;
-       iob->tail += len;
-       assert ( iob->tail <= iob->end );
-       return iob->data;
+static inline void * iob_reserve ( struct io_buffer *iobuf, size_t len ) {
+       iobuf->data += len;
+       iobuf->tail += len;
+       assert ( iobuf->tail <= iobuf->end );
+       return iobuf->data;
 }
 
 /**
  * Add data to start of I/O buffer
  *
 }
 
 /**
  * Add data to start of I/O buffer
  *
- * @v iob      I/O buffer
+ * @v iobuf    I/O buffer
  * @v len      Length to add
  * @ret data   Pointer to new start of buffer
  */
  * @v len      Length to add
  * @ret data   Pointer to new start of buffer
  */
-static inline void * iob_push ( struct io_buffer *iob, size_t len ) {
-       iob->data -= len;
-       assert ( iob->data >= iob->head );
-       return iob->data;
+static inline void * iob_push ( struct io_buffer *iobuf, size_t len ) {
+       iobuf->data -= len;
+       assert ( iobuf->data >= iobuf->head );
+       return iobuf->data;
 }
 
 /**
  * Remove data from start of I/O buffer
  *
 }
 
 /**
  * Remove data from start of I/O buffer
  *
- * @v iob      I/O buffer
+ * @v iobuf    I/O buffer
  * @v len      Length to remove
  * @ret data   Pointer to new start of buffer
  */
  * @v len      Length to remove
  * @ret data   Pointer to new start of buffer
  */
-static inline void * iob_pull ( struct io_buffer *iob, size_t len ) {
-       iob->data += len;
-       assert ( iob->data <= iob->tail );
-       return iob->data;
+static inline void * iob_pull ( struct io_buffer *iobuf, size_t len ) {
+       iobuf->data += len;
+       assert ( iobuf->data <= iobuf->tail );
+       return iobuf->data;
 }
 
 /**
  * Add data to end of I/O buffer
  *
 }
 
 /**
  * Add data to end of I/O buffer
  *
- * @v iob      I/O buffer
+ * @v iobuf    I/O buffer
  * @v len      Length to add
  * @ret data   Pointer to newly added space
  */
  * @v len      Length to add
  * @ret data   Pointer to newly added space
  */
-static inline void * iob_put ( struct io_buffer *iob, size_t len ) {
-       void *old_tail = iob->tail;
-       iob->tail += len;
-       assert ( iob->tail <= iob->end );
+static inline void * iob_put ( struct io_buffer *iobuf, size_t len ) {
+       void *old_tail = iobuf->tail;
+       iobuf->tail += len;
+       assert ( iobuf->tail <= iobuf->end );
        return old_tail;
 }
 
 /**
  * Remove data from end of I/O buffer
  *
        return old_tail;
 }
 
 /**
  * Remove data from end of I/O buffer
  *
- * @v iob      I/O buffer
+ * @v iobuf    I/O buffer
  * @v len      Length to remove
  */
  * @v len      Length to remove
  */
-static inline void iob_unput ( struct io_buffer *iob, size_t len ) {
-       iob->tail -= len;
-       assert ( iob->tail >= iob->data );
+static inline void iob_unput ( struct io_buffer *iobuf, size_t len ) {
+       iobuf->tail -= len;
+       assert ( iobuf->tail >= iobuf->data );
 }
 
 /**
  * Empty an I/O buffer
  *
 }
 
 /**
  * Empty an I/O buffer
  *
- * @v iob      I/O buffer
+ * @v iobuf    I/O buffer
  */
  */
-static inline void iob_empty ( struct io_buffer *iob ) {
-       iob->tail = iob->data;
+static inline void iob_empty ( struct io_buffer *iobuf ) {
+       iobuf->tail = iobuf->data;
 }
 
 /**
  * Calculate length of data in an I/O buffer
  *
 }
 
 /**
  * Calculate length of data in an I/O buffer
  *
- * @v iob      I/O buffer
+ * @v iobuf    I/O buffer
  * @ret len    Length of data in buffer
  */
  * @ret len    Length of data in buffer
  */
-static inline size_t iob_len ( struct io_buffer *iob ) {
-       return ( iob->tail - iob->data );
+static inline size_t iob_len ( struct io_buffer *iobuf ) {
+       return ( iobuf->tail - iobuf->data );
 }
 
 /**
  * Calculate available space at start of an I/O buffer
  *
 }
 
 /**
  * Calculate available space at start of an I/O buffer
  *
- * @v iob      I/O buffer
+ * @v iobuf    I/O buffer
  * @ret len    Length of data available at start of buffer
  */
  * @ret len    Length of data available at start of buffer
  */
-static inline size_t iob_headroom ( struct io_buffer *iob ) {
-       return ( iob->data - iob->head );
+static inline size_t iob_headroom ( struct io_buffer *iobuf ) {
+       return ( iobuf->data - iobuf->head );
 }
 
 /**
  * Calculate available space at end of an I/O buffer
  *
 }
 
 /**
  * Calculate available space at end of an I/O buffer
  *
- * @v iob      I/O buffer
+ * @v iobuf    I/O buffer
  * @ret len    Length of data available at end of buffer
  */
  * @ret len    Length of data available at end of buffer
  */
-static inline size_t iob_tailroom ( struct io_buffer *iob ) {
-       return ( iob->end - iob->tail );
+static inline size_t iob_tailroom ( struct io_buffer *iobuf ) {
+       return ( iobuf->end - iobuf->tail );
 }
 
 extern struct io_buffer * alloc_iob ( size_t len );
 }
 
 extern struct io_buffer * alloc_iob ( size_t len );
-extern void free_iob ( struct io_buffer *iob );
-extern void iob_pad ( struct io_buffer *iob, size_t min_len );
+extern void free_iob ( struct io_buffer *iobuf );
+extern void iob_pad ( struct io_buffer *iobuf, size_t min_len );
 
 #endif /* _GPXE_IOBUF_H */
 
 #endif /* _GPXE_IOBUF_H */