drivers/pci: epc add dma heap

The PCI inbound address space and the CPU cache need to maintain cache coherence

Signed-off-by: lipengfei28 <lipengfei28@xiaomi.com>
This commit is contained in:
lipengfei28 2025-07-25 10:48:12 +08:00 committed by Xiang Xiao
parent 50d94863f2
commit 4fa6d4b791
4 changed files with 179 additions and 11 deletions

View file

@ -30,6 +30,7 @@
#include <debug.h>
#include <nuttx/bits.h>
#include <nuttx/mm/mm.h>
#include <nuttx/kmalloc.h>
#include <nuttx/lib/math32.h>
#include <nuttx/pci/pci_epc.h>
@ -967,6 +968,8 @@ void pci_epc_bme_notify(FAR struct pci_epc_ctrl_s *epc)
* Input Parameters:
* name - EPC name strings
* priv - The epc priv data
* dma_addr - Used for inbound address
* dma_len - The dma memory len
* ops - Function pointers for performing EPC operations
*
* Returned Value:
@ -975,8 +978,8 @@ void pci_epc_bme_notify(FAR struct pci_epc_ctrl_s *epc)
****************************************************************************/
FAR struct pci_epc_ctrl_s *
pci_epc_create(FAR const char *name, FAR void *priv,
FAR const struct pci_epc_ops_s *ops)
pci_epc_create(FAR const char *name, FAR void *priv, FAR void *dma_addr,
size_t dma_len, FAR const struct pci_epc_ops_s *ops)
{
FAR struct pci_epc_ctrl_s *epc;
size_t len;
@ -993,6 +996,16 @@ pci_epc_create(FAR const char *name, FAR void *priv,
return NULL;
}
if (dma_addr != NULL && dma_len != 0)
{
epc->dmaheap = mm_initialize_pool("pci_dma", dma_addr, dma_len, NULL);
if (epc->dmaheap == NULL)
{
pcierr("Create DMA heap error \n");
goto free_epc;
}
}
epc->priv = priv;
memcpy(epc->name, name, len);
nxmutex_init(&epc->lock);
@ -1004,6 +1017,10 @@ pci_epc_create(FAR const char *name, FAR void *priv,
nxmutex_unlock(&g_pci_epc_lock);
return epc;
free_epc:
kmm_free(epc);
return NULL;
}
/****************************************************************************
@ -1036,3 +1053,92 @@ void pci_epc_destroy(FAR struct pci_epc_ctrl_s *epc)
nxmutex_destroy(&epc->lock);
kmm_free(epc);
}
/****************************************************************************
* Name: pci_epc_dma_alloc
*
* Description:
* This function is used to create a new endpoint controller (EPC) device.
*
* Invoke to destroy the PCI EPC device.
*
* Input Parameters:
* epc - The EPC device that has to be destroyed
* size - The dma memory size
*
* Returned Value:
* The point of dma memory if success, NULL if failed
*
****************************************************************************/
FAR void *pci_epc_dma_alloc(FAR struct pci_epc_ctrl_s *epc, size_t size)
{
if (epc->dmaheap != NULL)
{
return mm_malloc(epc->dmaheap, size);
}
else
{
return kmm_malloc(size);
}
}
/****************************************************************************
* Name: pci_epc_dma_memalign
*
* Description:
* This function is used to create a new endpoint controller (EPC) device.
*
* Invoke to destroy the PCI EPC device.
*
* Input Parameters:
* epc - The EPC device that has to be destroyed
* alignment - Alignment size
* size - The dma memory size
*
* Returned Value:
* The point of dma memory if success, NULL if failed
*
****************************************************************************/
FAR void *pci_epc_dma_memalign(FAR struct pci_epc_ctrl_s *epc,
size_t alignment, size_t size)
{
if (epc->dmaheap != NULL)
{
return mm_memalign(epc->dmaheap, alignment, size);
}
else
{
return kmm_memalign(alignment, size);
}
}
/****************************************************************************
* Name: pci_epc_dma_free
*
* Description:
* This function is used to create a new endpoint controller (EPC) device.
*
* Invoke to destroy the PCI EPC device.
*
* Input Parameters:
* epc - The EPC device that has to be destroyed
* mem - The dma memory need ed to be free
*
* Returned Value:
* None
*
****************************************************************************/
void pci_epc_dma_free(FAR struct pci_epc_ctrl_s *epc, FAR void *mem)
{
if (epc->dmaheap != NULL)
{
mm_free(epc->dmaheap, mem);
}
else
{
kmm_free(mem);
}
}

View file

@ -254,7 +254,7 @@ FAR void *pci_epf_alloc_space(FAR struct pci_epf_device_s *epf, int barno,
bar = epf->bar;
space = kmm_zalloc(size);
space = pci_epc_dma_memalign(epf->epc, align, size);
if (space == NULL)
{
pcierr("Failed to allocate mem space\n");

View file

@ -803,10 +803,10 @@ static int qemu_epc_probe(FAR struct pci_device_s *dev)
}
qep->pdev = dev;
epc = pci_epc_create("qemu_epc", qep, &g_qemu_epc_ops);
epc = pci_epc_create("qemu_epc", qep, NULL, 0, &g_qemu_epc_ops);
if (epc == NULL)
{
pcierr("Failed to create epc device\n");
pcierr("Failed to create qemu_epc device\n");
ret = -ENOMEM;
goto err_free_epc;
}

View file

@ -181,6 +181,7 @@ struct pci_epc_mem_s
* num_windows: Number of mem supported by device
* max_functions: Max number of functions that can be configured in this EPC
* node: The node of epc list
* dmaheap: The dma heap
* lock: Mutex to protect pci_epc ops
* funcno_map: Bitmap to manage physical function number
* priv: The private data
@ -195,6 +196,7 @@ struct pci_epc_ctrl_s
unsigned int num_windows;
uint8_t max_functions;
struct list_node node;
FAR struct mm_heap_s *dmaheap;
/* Mutex to protect against concurrent access of EP controller */
@ -714,9 +716,11 @@ void pci_epc_bme_notify(FAR struct pci_epc_ctrl_s *epc);
* Invoke to create a new EPC device and add it to pci_epc class.
*
* Input Parameters:
* name - EPC name strings
* priv - The epc priv data
* ops - Function pointers for performing EPC operations
* name - EPC name strings
* priv - The epc priv data
* dma_addr - Used for inbound address
* dma_len - The dma memory len
* ops - Function pointers for performing EPC operations
*
* Returned Value:
* Return struct pci_epc_ctrl_s * if success, NULL if failed.
@ -724,9 +728,8 @@ void pci_epc_bme_notify(FAR struct pci_epc_ctrl_s *epc);
****************************************************************************/
FAR struct pci_epc_ctrl_s *
pci_epc_create(FAR const char *name, FAR void *priv,
FAR const struct pci_epc_ops_s *ops);
pci_epc_create(FAR const char *name, FAR void *priv, FAR void *dma_addr,
size_t dma_len, FAR const struct pci_epc_ops_s *ops);
/****************************************************************************
* Name: pci_epc_destroy
*
@ -852,4 +855,63 @@ FAR void *pci_epc_mem_alloc_addr(FAR struct pci_epc_ctrl_s *epc,
void pci_epc_mem_free_addr(FAR struct pci_epc_ctrl_s *epc,
uintptr_t phys_addr, size_t size);
/****************************************************************************
* Name: pci_epc_dma_alloc
*
* Description:
* This function is used to create a new endpoint controller (EPC) device.
*
* Invoke to destroy the PCI EPC device.
*
* Input Parameters:
* epc - The EPC device that has to be destroyed
* size - The dma memory size
*
* Returned Value:
* The point of dma memory if success, NULL if failed
*
****************************************************************************/
FAR void *pci_epc_dma_alloc(FAR struct pci_epc_ctrl_s *epc, size_t size);
/****************************************************************************
* Name: pci_epc_dma_memalign
*
* Description:
* This function is used to create a new endpoint controller (EPC) device.
*
* Invoke to destroy the PCI EPC device.
*
* Input Parameters:
* epc - The EPC device that has to be destroyed
* alignment - Alignment size
* size - The dma memory size
*
* Returned Value:
* The point of dma memory if success, NULL if failed
*
****************************************************************************/
FAR void *pci_epc_dma_memalign(FAR struct pci_epc_ctrl_s *epc,
size_t alignment, size_t size);
/****************************************************************************
* Name: pci_epc_dma_free
*
* Description:
* This function is used to create a new endpoint controller (EPC) device.
*
* Invoke to destroy the PCI EPC device.
*
* Input Parameters:
* epc - The EPC device that has to be destroyed
* mem - The dma memory need ed to be free
*
* Returned Value:
* None
*
****************************************************************************/
void pci_epc_dma_free(FAR struct pci_epc_ctrl_s *epc, FAR void *mem);
#endif /* __INCLUDE_NUTTX_PCI_PCI_EPC_H */