diff --git a/include/nuttx/mm/iob.h b/include/nuttx/mm/iob.h index 68224a5221..4a93ea6050 100644 --- a/include/nuttx/mm/iob.h +++ b/include/nuttx/mm/iob.h @@ -70,6 +70,22 @@ # error CONFIG_IOB_NBUFFERS <= CONFIG_IOB_THROTTLE #endif +/* Default config of alignment and head padding size */ + +#if !defined(CONFIG_IOB_ALIGNMENT) +# define CONFIG_IOB_ALIGNMENT 1 +#endif + +#if !defined(CONFIG_IOB_HEADSIZE) +# define CONFIG_IOB_HEADSIZE 0 +#endif + +/* For backward compatibility when not using iob header padding */ + +#if CONFIG_IOB_HEADSIZE == 0 +# define io_head io_data +#endif + /* IOB helpers */ #define IOB_DATA(p) (&(p)->io_data[(p)->io_offset]) @@ -108,6 +124,9 @@ struct iob_s #endif unsigned int io_pktlen; /* Total length of the packet */ +#if CONFIG_IOB_HEADSIZE > 0 + uint8_t io_head[CONFIG_IOB_HEADSIZE]; +#endif uint8_t io_data[CONFIG_IOB_BUFSIZE]; }; diff --git a/mm/iob/Kconfig b/mm/iob/Kconfig index 85dc43fb9b..ecab1b9da2 100644 --- a/mm/iob/Kconfig +++ b/mm/iob/Kconfig @@ -32,6 +32,20 @@ config IOB_BUFSIZE chain. This setting determines the data payload each preallocated I/O buffer. +config IOB_HEADSIZE + int "Head size of each I/O buffer" + default 0 + ---help--- + This setting determines the reserved size in front of the payload + buffer in each I/O buffer. + +config IOB_ALIGNMENT + int "Alignment size of each I/O buffer" + default 1 + ---help--- + The member io_head of all I/O buffers is aligned to the value + specified by this configuration. + config IOB_NCHAINS int "Number of pre-allocated I/O buffer chain heads" default 0 if !NET_READAHEAD diff --git a/mm/iob/iob_initialize.c b/mm/iob/iob_initialize.c index af76cdc226..24a458f412 100644 --- a/mm/iob/iob_initialize.c +++ b/mm/iob/iob_initialize.c @@ -30,14 +30,32 @@ #include "iob.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ROUNDUP(x, y) (((x) + (y) - 1) / (y) * (y)) + +/* Fix the I/O Buffer size with specified alignment size */ + +#define IOB_ALIGN_SIZE ROUNDUP(sizeof(struct iob_s), CONFIG_IOB_ALIGNMENT) +#define IOB_BUFFER_SIZE (IOB_ALIGN_SIZE * CONFIG_IOB_NBUFFERS + \ + CONFIG_IOB_ALIGNMENT - 1) + /**************************************************************************** * Private Data ****************************************************************************/ -/* This is a pool of pre-allocated I/O buffers */ +/* Following raw buffer will be divided into iob_s instances, the initial + * procedure will ensure that the member io_head of each iob_s is aligned + * to the CONFIG_IOB_ALIGNMENT memory boundary. + */ + +static uint8_t g_iob_buffer[IOB_BUFFER_SIZE]; -static struct iob_s g_iob_pool[CONFIG_IOB_NBUFFERS]; #if CONFIG_IOB_NCHAINS > 0 +/* This is a pool of pre-allocated iob_qentry_s buffers */ + static struct iob_qentry_s g_iob_qpool[CONFIG_IOB_NCHAINS]; #endif @@ -95,12 +113,22 @@ sem_t g_qentry_sem = SEM_INITIALIZER(CONFIG_IOB_NCHAINS); void iob_initialize(void) { int i; + uintptr_t buf; - /* Add each I/O buffer to the free list */ + /* Get a start address which plus offsetof(struct iob_s, io_head) is + * aligned to the CONFIG_IOB_ALIGNMENT memory boundary + */ + + buf = ROUNDUP((uintptr_t)g_iob_buffer + offsetof(struct iob_s, io_head), + CONFIG_IOB_ALIGNMENT) - offsetof(struct iob_s, io_head); + + /* Get I/O buffer instance from the start address and add each I/O buffer + * to the free list + */ for (i = 0; i < CONFIG_IOB_NBUFFERS; i++) { - FAR struct iob_s *iob = &g_iob_pool[i]; + FAR struct iob_s *iob = (FAR struct iob_s *)(buf + i * IOB_ALIGN_SIZE); /* Add the pre-allocate I/O buffer to the head of the free list */