This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push: new 4fa6d4b791 drivers/pci: epc add dma heap 4fa6d4b791 is described below commit 4fa6d4b7912c7d44d47bfc63c8ba9c549c10633c Author: lipengfei28 <lipengfe...@xiaomi.com> AuthorDate: Fri Jul 25 10:48:12 2025 +0800 drivers/pci: epc add dma heap The PCI inbound address space and the CPU cache need to maintain cache coherence Signed-off-by: lipengfei28 <lipengfe...@xiaomi.com> --- drivers/pci/pci_epc.c | 110 +++++++++++++++++++++++++++++++++++++++++++- drivers/pci/pci_epf.c | 2 +- drivers/pci/pci_qemu_epc.c | 4 +- include/nuttx/pci/pci_epc.h | 74 ++++++++++++++++++++++++++--- 4 files changed, 179 insertions(+), 11 deletions(-) diff --git a/drivers/pci/pci_epc.c b/drivers/pci/pci_epc.c index 20f6ea8135..8d11480d64 100644 --- a/drivers/pci/pci_epc.c +++ b/drivers/pci/pci_epc.c @@ -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); + } +} diff --git a/drivers/pci/pci_epf.c b/drivers/pci/pci_epf.c index ddb3e1002b..b16e269d30 100644 --- a/drivers/pci/pci_epf.c +++ b/drivers/pci/pci_epf.c @@ -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"); diff --git a/drivers/pci/pci_qemu_epc.c b/drivers/pci/pci_qemu_epc.c index 39221741fd..f2d2924920 100644 --- a/drivers/pci/pci_qemu_epc.c +++ b/drivers/pci/pci_qemu_epc.c @@ -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; } diff --git a/include/nuttx/pci/pci_epc.h b/include/nuttx/pci/pci_epc.h index 1330b57f16..0f317f352f 100644 --- a/include/nuttx/pci/pci_epc.h +++ b/include/nuttx/pci/pci_epc.h @@ -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 */