mm/iob: Support alloc IOB via malloc
Support the network interface card driver to receive zero copies of packets and send and receive giant frame packets, allowing drivers to initialize the DMA buffer to the iob structure, and we can apply for IOB with large memory Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
This commit is contained in:
parent
00d208baf6
commit
b934555fd1
@ -88,12 +88,18 @@
|
||||
# define IOB_QEMPTY(q) ((q)->qh_head == NULL)
|
||||
#endif
|
||||
|
||||
#define IOB_BUFSIZE(p) CONFIG_IOB_BUFSIZE
|
||||
#ifdef CONFIG_IOB_ALLOC
|
||||
# define IOB_BUFSIZE(p) ((p)->io_bufsize)
|
||||
#else
|
||||
# define IOB_BUFSIZE(p) CONFIG_IOB_BUFSIZE
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
typedef CODE void (*iob_free_cb_t)(FAR void *data);
|
||||
|
||||
/* Represents one I/O buffer. A packet is contained by one or more I/O
|
||||
* buffers in a chain. The io_pktlen is only valid for the I/O buffer at
|
||||
* the head of the chain.
|
||||
@ -107,16 +113,24 @@ struct iob_s
|
||||
|
||||
/* Payload */
|
||||
|
||||
#if CONFIG_IOB_BUFSIZE < 256
|
||||
#if CONFIG_IOB_BUFSIZE < 256 && !defined(CONFIG_IOB_ALLOC)
|
||||
uint8_t io_len; /* Length of the data in the entry */
|
||||
uint8_t io_offset; /* Data begins at this offset */
|
||||
#else
|
||||
uint16_t io_len; /* Length of the data in the entry */
|
||||
uint16_t io_offset; /* Data begins at this offset */
|
||||
# ifdef CONFIG_IOB_ALLOC
|
||||
uint16_t io_bufsize; /* Total length of the data buffer */
|
||||
# endif
|
||||
#endif
|
||||
unsigned int io_pktlen; /* Total length of the packet */
|
||||
|
||||
uint8_t io_data[CONFIG_IOB_BUFSIZE];
|
||||
#ifdef CONFIG_IOB_ALLOC
|
||||
iob_free_cb_t io_free; /* Custom free callback */
|
||||
FAR uint8_t *io_data;
|
||||
#else
|
||||
uint8_t io_data[CONFIG_IOB_BUFSIZE];
|
||||
#endif
|
||||
};
|
||||
|
||||
#if CONFIG_IOB_NCHAINS > 0
|
||||
@ -205,6 +219,53 @@ FAR struct iob_s *iob_alloc(bool throttled);
|
||||
|
||||
FAR struct iob_s *iob_tryalloc(bool throttled);
|
||||
|
||||
#ifdef CONFIG_IOB_ALLOC
|
||||
/****************************************************************************
|
||||
* Name: iob_alloc_dynamic
|
||||
*
|
||||
* Description:
|
||||
* Allocate an I/O buffer and playload from heap
|
||||
*
|
||||
* Input Parameters:
|
||||
* size - The size of the io_data that is allocated.
|
||||
*
|
||||
* +---------+
|
||||
* | IOB |
|
||||
* | io_data |--+
|
||||
* | buffer |<-+
|
||||
* +---------+
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct iob_s *iob_alloc_dynamic(uint16_t size);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: iob_alloc_with_data
|
||||
*
|
||||
* Description:
|
||||
* Allocate an I/O buffer from heap and attach the external payload
|
||||
*
|
||||
* Input Parameters:
|
||||
* data - Make io_data point to a specific address, the caller is
|
||||
* responsible for the memory management. The caller should
|
||||
* ensure that the memory is not freed before the iob is freed.
|
||||
*
|
||||
* +---------+ +-->+--------+
|
||||
* | IOB | | | data |
|
||||
* | io_data |--+ +--------+
|
||||
* +---------+
|
||||
*
|
||||
* size - The size of the data parameter
|
||||
* free_cb - Notify the caller when the iob is freed. The caller can
|
||||
* perform additional operations on the data before it is freed.
|
||||
* The free_cb is called when the iob is freed.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct iob_s *iob_alloc_with_data(FAR void *data, uint16_t size,
|
||||
iob_free_cb_t free_cb);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: iob_navail
|
||||
*
|
||||
|
@ -103,6 +103,12 @@ config IOB_NOTIFIER_DIV
|
||||
a notification will be sent only when there are a multiple of 4 IOBs
|
||||
available.
|
||||
|
||||
config IOB_ALLOC
|
||||
bool "Dynamic I/O buffer allocation"
|
||||
default n
|
||||
---help---
|
||||
This option will enable dynamic I/O buffer allocation
|
||||
|
||||
config IOB_DEBUG
|
||||
bool "Force I/O buffer debug"
|
||||
default n
|
||||
|
@ -39,6 +39,8 @@
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define ROUNDUP(x, y) (((x) + (y) - 1) / (y) * (y))
|
||||
|
||||
#if defined(CONFIG_DEBUG_FEATURES) && defined(CONFIG_IOB_DEBUG)
|
||||
# define ioberr _err
|
||||
# define iobwarn _warn
|
||||
|
@ -30,6 +30,9 @@
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/sched.h>
|
||||
#ifdef CONFIG_IOB_ALLOC
|
||||
# include <nuttx/kmalloc.h>
|
||||
#endif
|
||||
#include <nuttx/mm/iob.h>
|
||||
|
||||
#include "iob.h"
|
||||
@ -197,6 +200,23 @@ static FAR struct iob_s *iob_allocwait(bool throttled, unsigned int timeout)
|
||||
return iob;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IOB_ALLOC
|
||||
/****************************************************************************
|
||||
* Name: iob_free_dynamic
|
||||
*
|
||||
* Description:
|
||||
* Dummy free callback function, do nothing.
|
||||
*
|
||||
* Input Parameters:
|
||||
* data -
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void iob_free_dynamic(FAR void *data)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -329,3 +349,91 @@ FAR struct iob_s *iob_tryalloc(bool throttled)
|
||||
spin_unlock_irqrestore(&g_iob_lock, flags);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IOB_ALLOC
|
||||
|
||||
/****************************************************************************
|
||||
* Name: iob_alloc_dynamic
|
||||
*
|
||||
* Description:
|
||||
* Allocate an I/O buffer and playload from heap
|
||||
*
|
||||
* Input Parameters:
|
||||
* size - The size of the io_data that is allocated.
|
||||
*
|
||||
* +---------+
|
||||
* | IOB |
|
||||
* | io_data |--+
|
||||
* | buffer |<-+
|
||||
* +---------+
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct iob_s *iob_alloc_dynamic(uint16_t size)
|
||||
{
|
||||
FAR struct iob_s *iob;
|
||||
size_t alignsize;
|
||||
|
||||
alignsize = ROUNDUP(sizeof(struct iob_s), CONFIG_IOB_ALIGNMENT) + size;
|
||||
|
||||
iob = kmm_memalign(CONFIG_IOB_ALIGNMENT, alignsize);
|
||||
if (iob)
|
||||
{
|
||||
iob->io_flink = NULL; /* Not in a chain */
|
||||
iob->io_len = 0; /* Length of the data in the entry */
|
||||
iob->io_offset = 0; /* Offset to the beginning of data */
|
||||
iob->io_bufsize = size; /* Total length of the iob buffer */
|
||||
iob->io_pktlen = 0; /* Total length of the packet */
|
||||
iob->io_free = iob_free_dynamic; /* Customer free callback */
|
||||
iob->io_data = (FAR uint8_t *)ROUNDUP((uintptr_t)(iob + 1),
|
||||
CONFIG_IOB_ALIGNMENT);
|
||||
}
|
||||
|
||||
return iob;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: iob_alloc_with_data
|
||||
*
|
||||
* Description:
|
||||
* Allocate an I/O buffer from heap and attach the external payload
|
||||
*
|
||||
* Input Parameters:
|
||||
* data - Make io_data point to a specific address, the caller is
|
||||
* responsible for the memory management. The caller should
|
||||
* ensure that the memory is not freed before the iob is freed.
|
||||
*
|
||||
* +---------+ +-->+--------+
|
||||
* | IOB | | | data |
|
||||
* | io_data |--+ +--------+
|
||||
* +---------+
|
||||
*
|
||||
* size - The size of the data parameter
|
||||
* free_cb - Notify the caller when the iob is freed. The caller can
|
||||
* perform additional operations on the data before it is freed.
|
||||
* The free_cb is called when the iob is freed.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct iob_s *iob_alloc_with_data(FAR void *data, uint16_t size,
|
||||
iob_free_cb_t free_cb)
|
||||
{
|
||||
FAR struct iob_s *iob;
|
||||
|
||||
DEBUGASSERT(free_cb != NULL);
|
||||
|
||||
iob = kmm_malloc(sizeof(struct iob_s));
|
||||
if (iob)
|
||||
{
|
||||
iob->io_flink = NULL; /* Not in a chain */
|
||||
iob->io_len = 0; /* Length of the data in the entry */
|
||||
iob->io_offset = 0; /* Offset to the beginning of data */
|
||||
iob->io_bufsize = size; /* Total length of the iob buffer */
|
||||
iob->io_pktlen = 0; /* Total length of the packet */
|
||||
iob->io_free = free_cb; /* Customer free callback */
|
||||
iob->io_data = data;
|
||||
}
|
||||
|
||||
return iob;
|
||||
}
|
||||
#endif
|
||||
|
@ -30,6 +30,9 @@
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#ifdef CONFIG_IOB_ALLOC
|
||||
# include <nuttx/kmalloc.h>
|
||||
#endif
|
||||
#include <nuttx/mm/iob.h>
|
||||
|
||||
#include "iob.h"
|
||||
@ -112,6 +115,15 @@ FAR struct iob_s *iob_free(FAR struct iob_s *iob)
|
||||
next, next->io_pktlen, next->io_len);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IOB_ALLOC
|
||||
if (iob->io_free != NULL)
|
||||
{
|
||||
iob->io_free(iob->io_data);
|
||||
kmm_free(iob);
|
||||
return next;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Free the I/O buffer by adding it to the head of the free or the
|
||||
* committed list. We don't know what context we are called from so
|
||||
* we use extreme measures to protect the free list: We disable
|
||||
|
@ -34,11 +34,15 @@
|
||||
* 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)
|
||||
#ifdef CONFIG_IOB_ALLOC
|
||||
# define IOB_ALIGN_SIZE ROUNDUP(sizeof(struct iob_s) + CONFIG_IOB_BUFSIZE, \
|
||||
CONFIG_IOB_ALIGNMENT)
|
||||
#else
|
||||
# define IOB_ALIGN_SIZE ROUNDUP(sizeof(struct iob_s), CONFIG_IOB_ALIGNMENT)
|
||||
#endif
|
||||
|
||||
#define IOB_BUFFER_SIZE (IOB_ALIGN_SIZE * CONFIG_IOB_NBUFFERS + \
|
||||
CONFIG_IOB_ALIGNMENT - 1)
|
||||
|
||||
@ -138,8 +142,12 @@ void iob_initialize(void)
|
||||
|
||||
/* Add the pre-allocate I/O buffer to the head of the free list */
|
||||
|
||||
iob->io_flink = g_iob_freelist;
|
||||
g_iob_freelist = iob;
|
||||
iob->io_flink = g_iob_freelist;
|
||||
#ifdef CONFIG_IOB_ALLOC
|
||||
iob->io_bufsize = CONFIG_IOB_BUFSIZE;
|
||||
iob->io_data = (FAR uint8_t *)(iob + 1);
|
||||
#endif
|
||||
g_iob_freelist = iob;
|
||||
}
|
||||
|
||||
#if CONFIG_IOB_NCHAINS > 0
|
||||
|
@ -49,9 +49,9 @@ int iob_update_pktlen(FAR struct iob_s *iob, unsigned int pktlen,
|
||||
{
|
||||
FAR struct iob_s *penultimate;
|
||||
FAR struct iob_s *next;
|
||||
uint16_t offset = 0;
|
||||
int remain = pktlen;
|
||||
int ninqueue = 0;
|
||||
int nrequire;
|
||||
int nrequire = 0;
|
||||
uint16_t len;
|
||||
|
||||
/* The data offset must be less than CONFIG_IOB_BUFSIZE */
|
||||
@ -67,19 +67,28 @@ int iob_update_pktlen(FAR struct iob_s *iob, unsigned int pktlen,
|
||||
while (next != NULL)
|
||||
{
|
||||
ninqueue++;
|
||||
offset += next->io_offset;
|
||||
penultimate = next;
|
||||
if (remain > 0)
|
||||
{
|
||||
nrequire++;
|
||||
remain -= IOB_BUFSIZE(next) - next->io_offset;
|
||||
}
|
||||
|
||||
next = next->io_flink;
|
||||
}
|
||||
|
||||
/* Trim inqueue entries if needed */
|
||||
if (remain > 0)
|
||||
{
|
||||
nrequire += (remain + CONFIG_IOB_BUFSIZE - 1) / CONFIG_IOB_BUFSIZE;
|
||||
}
|
||||
|
||||
nrequire = (pktlen + offset + IOB_BUFSIZE(iob) - 1) / IOB_BUFSIZE(iob);
|
||||
if (nrequire == 0)
|
||||
{
|
||||
nrequire = 1;
|
||||
}
|
||||
|
||||
/* Trim inqueue entries if needed */
|
||||
|
||||
if (nrequire < ninqueue)
|
||||
{
|
||||
/* Loop until complete the trim */
|
||||
|
Loading…
Reference in New Issue
Block a user