Re: [PATCH 09/15] PCI: endpoint: Add pci-ep-dma helper for exported DMA ABI v1
Koichiro Den <[email protected]>
| Newsgroups | org.kernel.vger.dmaengine,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pci |
|---|---|
| Message-ID | <3ef3b7wdwpf364teperxcjc2leycxwke77cejjfzd5w4pnbmik@vlcbizvbxv4m> |
On Fri, Mar 13, 2026 at 01:49:59AM +0900, Koichiro Den wrote: > Add a generic helper that packages controller-owned DMA resources into a > peer-visible BAR slice described by exported DMA ABI v1. > > pci_epf_alloc_dma() queries EPC auxiliary resources, delegates the > requested DMA read channels, builds an ABI header in coherent memory, > and assembles the BAR region list covering the header, controller > register window, and per-channel descriptor windows. If the controller > control window is not already BAR-backed, map it into the exported slice > so the peer still sees a self-contained layout. > > The first ABI is designed based on the DesignWare unrolled eDMA model, > but it is intended to be vendor-neutral. It exports delegated READ > channels only, which are the channels the host uses to send data from > host memory into the endpoint. > > Signed-off-by: Koichiro Den <[email protected]> > --- > drivers/pci/endpoint/Makefile | 2 +- > drivers/pci/endpoint/pci-ep-dma.c | 342 ++++++++++++++++++++++++++++++ > include/linux/pci-ep-dma.h | 130 ++++++++++++ > 3 files changed, 473 insertions(+), 1 deletion(-) > create mode 100644 drivers/pci/endpoint/pci-ep-dma.c > create mode 100644 include/linux/pci-ep-dma.h > > diff --git a/drivers/pci/endpoint/Makefile b/drivers/pci/endpoint/Makefile > index b4869d52053a..94824f3ed5a1 100644 > --- a/drivers/pci/endpoint/Makefile > +++ b/drivers/pci/endpoint/Makefile > @@ -5,5 +5,5 @@ > > obj-$(CONFIG_PCI_ENDPOINT_CONFIGFS) += pci-ep-cfs.o > obj-$(CONFIG_PCI_ENDPOINT) += pci-epc-core.o pci-epf-core.o\ > - pci-epc-mem.o functions/ > + pci-epc-mem.o pci-ep-dma.o functions/ > obj-$(CONFIG_PCI_ENDPOINT_MSI_DOORBELL) += pci-ep-msi.o > diff --git a/drivers/pci/endpoint/pci-ep-dma.c b/drivers/pci/endpoint/pci-ep-dma.c > new file mode 100644 > index 000000000000..2a996f9b1424 > --- /dev/null > +++ b/drivers/pci/endpoint/pci-ep-dma.c ---[snip]--- > diff --git a/include/linux/pci-ep-dma.h b/include/linux/pci-ep-dma.h > new file mode 100644 > index 000000000000..0ef6f9eb8593 > --- /dev/null > +++ b/include/linux/pci-ep-dma.h Hi Mani, (Cc: Frank, Niklas) Perhaps it's time to reincarnate this series, with much of it reworked. Following the discussion here: https://lore.kernel.org/r/fg7cma2ccvdgjgcref7qa4q7ocvvume5dteekedikszebkq7rd@uhrjfp3nmmwh/ I am now thinking of dropping the generic pci-ep-dma helper and include/linux/pci-ep-dma.h altogether, as I understand the direction is to keep the DMA export within the vNTB/ntb_hw_epf path *as much as possible*. The old wire layout was consumed by pci-epf-vntb.c, ntb_hw_epf.c, and dw-edma-aux.c (see patch 13). That is why I put pci-ep-dma.h under include/linux/. For the rework, I am thinking ntb_hw_epf should decode it and pass only the resulting resources to dw-edma-aux. This keeps the wire format between pci-epf-vntb and ntb_hw_epf. At that point, defining the same small layout in both files might even be preferable to adding another shared header in include/linux/. Mani, does this direction look acceptable to you? I would also appreciate your view on the linked discussion when you have a chance. Best regards, Koichiro > @@ -0,0 +1,130 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Generic exported DMA helper for PCI endpoint functions > + */ > + > +#ifndef __LINUX_PCI_EP_DMA_H > +#define __LINUX_PCI_EP_DMA_H > + > +#include <linux/dma-mapping.h> > +#include <linux/pci-epf.h> > + > +#define PCI_EP_DMA_MAGIC 0x4d445045 /* "EPDM" */ > +#define PCI_EP_DMA_MAX_CHANS 8 > +#define PCI_EP_DMA_MAX_REGIONS (2 + PCI_EP_DMA_MAX_CHANS) > + > +enum pci_ep_dma_abi { > + PCI_EP_DMA_ABI_NONE = 0, > + PCI_EP_DMA_ABI_V1 = 1, > +}; > + > +/** > + * struct pci_ep_dma_locator - peer-visible location of an exported DMA slice > + * @abi: exported-DMA ABI identifier from &enum pci_ep_dma_abi > + * @bar: BAR number that carries the exported slice > + * @flags: ABI-specific locator flags, reserved for future use in v1 > + * @offset: BAR-relative start offset of the exported slice > + * @size: total size of the exported slice in bytes > + */ > +struct pci_ep_dma_locator { > + u8 abi; > + u8 bar; > + u16 flags; > + u32 offset; > + u32 size; > +}; > + > +/** > + * struct pci_ep_dma_region - one physical region mapped into the exported slice > + * @offset: BAR-relative start offset of the region within the exported slice > + * @phys_addr: DMA address to program into the EPC BAR mapping > + * @size: mapped size in bytes > + */ > +struct pci_ep_dma_region { > + u32 offset; > + dma_addr_t phys_addr; > + size_t size; > +}; > + > +/** > + * struct pci_ep_dma_chan_info - per-channel descriptor metadata in ABI v1 > + * @desc_bar: BAR number that exposes the descriptor window > + * @desc_offset: BAR-relative start offset of the descriptor window > + * @desc_size: descriptor window size in bytes > + * @desc_phys_addr: physical/DMA address used for the EPC-side BAR mapping > + */ > +struct pci_ep_dma_chan_info { > + __le32 desc_bar; > + __le32 desc_offset; > + __le32 desc_size; > + __le64 desc_phys_addr; > +}; > + > +/** > + * struct pci_ep_dma_hdr_v1 - exported DMA header format, version 1 > + * @magic: fixed signature, must be %PCI_EP_DMA_MAGIC > + * @version: header version, must be 1 for this structure > + * @hdr_size: size of the populated header structure in bytes > + * @total_size: total exported-slice size starting at &struct pci_ep_dma_locator.offset > + * @ctrl_bar: BAR that exposes the live DMA control registers > + * @ctrl_offset: BAR-relative start offset of the control-register window > + * @ctrl_size: size of the control-register window in bytes > + * @irq_count: number of IRQ vectors reserved for the exported DMA provider > + * @num_chans: number of valid entries in @chans > + * @chans: per-channel descriptor metadata > + * > + * Exported DMA ABI v1 lays out the peer-visible slice as: > + * > + * [header][controller window?][descriptor window 0]...[descriptor window N] > + * > + * The controller window is optional in that slice. When the live register > + * block is already exposed through another BAR, @ctrl_bar/@ctrl_offset point at > + * that BAR directly and no controller subrange is embedded in the exported > + * slice. > + * > + * @chans[] describes a dense prefix of the remote hardware READ-channel > + * space, ordered by remote hardware READ-channel index starting at 0. A > + * consumer may map @chans[i] directly to remote READ channel i. > + */ > +struct pci_ep_dma_hdr_v1 { > + __le32 magic; > + __le16 version; > + __le16 hdr_size; > + __le32 total_size; > + __le32 ctrl_bar; > + __le32 ctrl_offset; > + __le32 ctrl_size; > + __le32 irq_count; > + __le32 num_chans; > + struct pci_ep_dma_chan_info chans[PCI_EP_DMA_MAX_CHANS]; > +}; > + > +struct pci_ep_dma { > + struct pci_epf *epf; > + enum pci_barno bar; > + void *hdr_virt; > + dma_addr_t hdr_phys; > + size_t hdr_alloc_size; > + struct pci_ep_dma_locator loc; > + unsigned int num_regions; > + u32 num_chans; > + struct pci_ep_dma_region regions[PCI_EP_DMA_MAX_REGIONS]; > + dma_addr_t ctrl_map_addr; > + size_t ctrl_map_size; > + int delegated_chan_ids[PCI_EP_DMA_MAX_CHANS]; > + u8 delegated_num_chans; > +}; > + > +struct pci_ep_dma *pci_epf_alloc_dma(struct pci_epf *epf, enum pci_barno bar, > + u32 offset, u32 req_chans); > +void pci_epf_free_dma(struct pci_ep_dma *dma); > + > +const struct pci_ep_dma_locator * > +pci_epf_get_dma_locator(const struct pci_ep_dma *dma); > + > +unsigned int pci_epf_get_dma_region_count(const struct pci_ep_dma *dma); > + > +const struct pci_ep_dma_region * > +pci_epf_get_dma_regions(const struct pci_ep_dma *dma); > + > +#endif /* __LINUX_PCI_EP_DMA_H */ > -- > 2.51.0 >