* [PATCH v3 0/5] PCI: endpoint: Expose endpoint DMA resources (part 2/3)
@ 2026-06-20 17:04 Koichiro Den
2026-06-20 17:04 ` [PATCH v3 1/5] PCI: endpoint: Define endpoint DMA BAR metadata format Koichiro Den
` (4 more replies)
0 siblings, 5 replies; 11+ messages in thread
From: Koichiro Den @ 2026-06-20 17:04 UTC (permalink / raw)
To: Jingoo Han, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Bjorn Helgaas,
Kishon Vijay Abraham I, Frank Li, Niklas Cassel
Cc: Marek Vasut, Yoshihiro Shimoda, linux-kernel, linux-pci
Hi,
This is v3, part 2 of three series for PCI endpoint DMA.
The three series are:
* part 1: dmaengine: dw-edma: Prepare for PCI EP DMA
* part 2: PCI: endpoint: Expose endpoint DMA resources
* part 3: PCI: endpoint: Add PCI DMA endpoint function
This series adds the PCI endpoint-side pieces used by the endpoint DMA
function. It defines the BAR metadata format, extends EPC auxiliary
resources with DMA-specific resource descriptions, adds EPC operations to
delegate and reclaim DMA channels, and teaches the DesignWare endpoint
controller to publish and delegate its integrated DMA resources.
The metadata lives in a normal endpoint BAR, not in PCI config space. This
keeps discovery independent from controller-specific writable extended
capability storage.
Dependencies
============
This series depends on part 1:
[PATCH v3 00/13] dmaengine: dw-edma: Prepare for PCI EP DMA (part 1/3)
https://lore.kernel.org/dmaengine/20260620170040.3756043-1-den@valinux.co.jp/
---
Changelog
=========
Changes in v3:
- Decouple logical DMA channel metadata from descriptor memory resources.
Logical channels now refer to descriptor memory by resource ID instead
of embedding descriptor metadata in each channel resource. (Sashiko)
- Replace the v2 DMAengine filter-callback metadata with EPC-level DMA
channel delegation/reclaim operations, keeping DMAengine provider details
out of generic EPC resource metadata.
- Add the DesignWare EPC backend for DMA channel delegation.
- Limit DesignWare endpoint DMA resource exposure to linked-list channels
until non-LL metadata and host-side parsing are added.
- Suppress DesignWare DMA auxiliary resources when the local DW eDMA
provider is not available.
- Reject VF DMA resource and delegation requests because the DWC
eDMA/HDMA register window exposed to the Root Complex is PF-only.
Changes in v2:
- Follow the part 1/3 v2 channel-claim model: EPC DMA resources now
carry DMAengine filter information instead of raw DMA channel
pointers. (Sashiko)
- Update the DesignWare endpoint resource provider accordingly. (Sashiko)
v2: https://lore.kernel.org/linux-pci/20260525063129.3316894-1-den@valinux.co.jp/
v1: https://lore.kernel.org/linux-pci/20260521063405.2842644-1-den@valinux.co.jp/
Best regards,
Koichiro
Koichiro Den (5):
PCI: endpoint: Define endpoint DMA BAR metadata format
PCI: endpoint: Add DMA auxiliary resource metadata
PCI: endpoint: Add API to delegate EPC DMA channels to the host
PCI: dwc: Expose endpoint DMA resources
PCI: dwc: Implement endpoint DMA channel delegation
MAINTAINERS | 1 +
.../pci/controller/dwc/pcie-designware-ep.c | 192 +++++++++++++++++-
drivers/pci/endpoint/pci-epc-core.c | 100 +++++++++
include/linux/pci-ep-dma.h | 163 +++++++++++++++
include/linux/pci-epc.h | 61 ++++++
5 files changed, 512 insertions(+), 5 deletions(-)
create mode 100644 include/linux/pci-ep-dma.h
--
2.51.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v3 1/5] PCI: endpoint: Define endpoint DMA BAR metadata format
2026-06-20 17:04 [PATCH v3 0/5] PCI: endpoint: Expose endpoint DMA resources (part 2/3) Koichiro Den
@ 2026-06-20 17:04 ` Koichiro Den
2026-06-20 17:10 ` sashiko-bot
2026-06-20 17:04 ` [PATCH v3 2/5] PCI: endpoint: Add DMA auxiliary resource metadata Koichiro Den
` (3 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Koichiro Den @ 2026-06-20 17:04 UTC (permalink / raw)
To: Jingoo Han, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Bjorn Helgaas,
Kishon Vijay Abraham I, Frank Li, Niklas Cassel
Cc: Marek Vasut, Yoshihiro Shimoda, linux-kernel, linux-pci
Define the BAR-resident metadata format used by endpoint functions that
expose an endpoint-integrated DMA controller to the host.
A VSEC-based discovery scheme would be a natural fit, and existing
dw-edma-pcie providers such as Synopsys EDDA and AMD (Xilinx) MDB/CPM6
already use VSECs for DMA discovery. However, some endpoint controllers
cannot provide enough writable configuration-space storage for a
complete, controller-defined payload. Keep the extensible metadata in a
BAR instead, where the endpoint function controls the layout and size.
The format describes the DMA register window, exported channel counts,
descriptor windows, optional auxiliary windows, endpoint-local descriptor
and auxiliary DMA addresses, and a ready bit that tells the host when the
described BAR windows are usable. Channel entries keep the auxiliary
window optional so layouts that need a separate data or auxiliary aperture
can describe it without a format bump.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
Changes in v3:
- Update commit message to describe the AMD (Xilinx) CPM6 match
present in the new base.
MAINTAINERS | 1 +
include/linux/pci-ep-dma.h | 163 +++++++++++++++++++++++++++++++++++++
2 files changed, 164 insertions(+)
create mode 100644 include/linux/pci-ep-dma.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 895a87b571c3..ff6f7d2595d9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20802,6 +20802,7 @@ F: Documentation/PCI/endpoint/*
F: Documentation/misc-devices/pci-endpoint-test.rst
F: drivers/misc/pci_endpoint_test.c
F: drivers/pci/endpoint/
+F: include/linux/pci-ep-dma.h
F: tools/testing/selftests/pci_endpoint/
PCI ENHANCED ERROR HANDLING (EEH) FOR POWERPC
diff --git a/include/linux/pci-ep-dma.h b/include/linux/pci-ep-dma.h
new file mode 100644
index 000000000000..c5fd7aab2101
--- /dev/null
+++ b/include/linux/pci-ep-dma.h
@@ -0,0 +1,163 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LINUX_PCI_EP_DMA_H
+#define __LINUX_PCI_EP_DMA_H
+
+#include <linux/bits.h>
+
+/*
+ * BAR metadata format used by PCI endpoint functions that expose an
+ * endpoint-integrated DMA controller to a PCI host.
+ *
+ * Offsets are relative to the beginning of the metadata blob. Multi-byte
+ * fields are little-endian. The blob is normally placed at offset 0 of a
+ * function BAR selected by the endpoint function and discovered by the host
+ * driver using device-specific policy. Other data in the same BAR, such as a
+ * standard MSI-X table or PBA, is outside this metadata format.
+ *
+ * 31 0
+ * +---------------------------------------------------------------+
+ * +0x000 | metadata magic |
+ * +---------------------------------------------------------------+
+ * 31 16 15 8 7 0
+ * +-------------------------------+---------------+---------------+
+ * +0x004 | metadata length | reserved | revision |
+ * +-------------------------------+---------------+---------------+
+ * 31 30 29 27 26 19 18 11 10 3 2 0
+ * +--+--+--------+--------------+--------------+--------------+---+
+ * +0x008 |R |H |reserved| ch entry size| RD count | WR count |BAR|
+ * +--+--+--------+--------------+--------------+--------------+---+
+ * +0x00c | register window offset[31:0] |
+ * +---------------------------------------------------------------+
+ * +0x010 | register window offset[63:32] |
+ * +---------------------------------------------------------------+
+ * 31 16 15 8 7 0
+ * +-------------------------------+---------------+---------------+
+ * +0x014 | reserved | layout data | layout |
+ * +-------------------------------+---------------+---------------+
+ * +0x018 | register window size |
+ * +---------------------------------------------------------------+
+ * +0x01c | write table |
+ * | ( channel table entries #0 ~ #N ) |
+ * +---------------------------------------------------------------+
+ * | read table |
+ * | ( channel table entries #0 ~ #N ) |
+ * +---------------------------------------------------------------+
+ *
+ * metadata magic: PCI_EP_DMA_METADATA_MAGIC.
+ * metadata length: byte size of the whole metadata blob.
+ * revision: metadata format revision.
+ * R: ready bit. Set when all BAR windows described by this metadata
+ * have been programmed and can be used by the host.
+ * H: host-request bit. Set by the host driver after it has found this
+ * metadata. The endpoint may use this as the trigger to program
+ * DMA window BAR subrange mappings.
+ * ch entry size: byte stride between consecutive channel table
+ * entries. Revision 1 requires at least
+ * PCI_EP_DMA_METADATA_CH_ENTRY_SIZE bytes.
+ * RD count: number of exposed RC-to-endpoint DMA read channels and
+ * read channel-table entries.
+ * WR count: number of exposed endpoint-to-RC DMA write channels and
+ * write channel-table entries.
+ * BAR: BAR that contains the DMA controller register window.
+ * register window offset: BAR-local byte offset of the DMA controller
+ * register window in BAR.
+ * register window size: DMA controller register window size in bytes.
+ * layout: DMA controller register layout identifier.
+ * layout data: layout-specific data. For
+ * PCI_EP_DMA_METADATA_REG_LAYOUT_DW_EDMA this is the
+ * DesignWare eDMA/HDMA map format.
+ * write table: starts at PCI_EP_DMA_METADATA_HDR_LEN if write channel
+ * count is non-zero.
+ * read table: starts at PCI_EP_DMA_METADATA_HDR_LEN plus the write
+ * table size if read channel count is non-zero.
+ *
+ *
+ * Channel table entry:
+ *
+ * 31 17 16 15 14 12 11 10 8 7 0
+ * +--------------------+--+--+-------+--+--------+----------------+
+ * +0x000 | reserved |A |rs|aux BAR|rs|desc BAR|hardware channel|
+ * +--------------------+--+--+-------+--+--------+----------------+
+ * +0x004 | descriptor window BAR offset[31:0] |
+ * +---------------------------------------------------------------+
+ * +0x008 | descriptor window BAR offset[63:32] |
+ * +---------------------------------------------------------------+
+ * +0x00c | descriptor window size |
+ * +---------------------------------------------------------------+
+ * +0x010 | descriptor DMA address[31:0] |
+ * +---------------------------------------------------------------+
+ * +0x014 | descriptor DMA address[63:32] |
+ * +---------------------------------------------------------------+
+ * +0x018 | auxiliary window BAR offset[31:0] |
+ * +---------------------------------------------------------------+
+ * +0x01c | auxiliary window BAR offset[63:32] |
+ * +---------------------------------------------------------------+
+ * +0x020 | auxiliary window size |
+ * +---------------------------------------------------------------+
+ * +0x024 | auxiliary DMA address[31:0] |
+ * +---------------------------------------------------------------+
+ * +0x028 | auxiliary DMA address[63:32] |
+ * +---------------------------------------------------------------+
+ *
+ * A: auxiliary-window-valid bit. If clear, aux BAR and auxiliary
+ * window fields are ignored.
+ * aux BAR: BAR that contains the optional auxiliary window.
+ * desc BAR: BAR that contains the descriptor window.
+ * hardware channel: DMA controller's hardware channel number.
+ * Revision 1 entries are currently consumed in dense
+ * 0-based order.
+ * descriptor window BAR offset: BAR-local byte offset of the
+ * descriptor window in desc BAR.
+ * descriptor window size: descriptor window size in bytes.
+ * descriptor DMA address: endpoint-local address used by the DMA
+ * controller to fetch descriptors.
+ * auxiliary window BAR offset: BAR-local byte offset of the auxiliary
+ * window in aux BAR.
+ * auxiliary window size: auxiliary window size in bytes.
+ * auxiliary DMA address: endpoint-local address corresponding to the
+ * auxiliary window.
+ */
+#define PCI_EP_DMA_METADATA_MAGIC 0x4d444550 /* "PEDM" */
+#define PCI_EP_DMA_METADATA_REV 0x1
+
+#define PCI_EP_DMA_METADATA_HDR_LEN 0x1c
+
+#define PCI_EP_DMA_METADATA_HDR 0x04
+#define PCI_EP_DMA_METADATA_HDR_REV GENMASK(7, 0)
+#define PCI_EP_DMA_METADATA_HDR_LEN_FIELD GENMASK(31, 16)
+
+#define PCI_EP_DMA_METADATA_CTRL 0x08
+#define PCI_EP_DMA_METADATA_CTRL_REG_BAR GENMASK(2, 0)
+#define PCI_EP_DMA_METADATA_CTRL_WR_CH_COUNT GENMASK(10, 3)
+#define PCI_EP_DMA_METADATA_CTRL_RD_CH_COUNT GENMASK(18, 11)
+#define PCI_EP_DMA_METADATA_CTRL_CH_ENTRY_SIZE GENMASK(26, 19)
+#define PCI_EP_DMA_METADATA_CTRL_HOST_REQ BIT(30)
+#define PCI_EP_DMA_METADATA_CTRL_READY BIT(31)
+
+#define PCI_EP_DMA_METADATA_REG_OFF_LO 0x0c
+#define PCI_EP_DMA_METADATA_REG_OFF_HI 0x10
+#define PCI_EP_DMA_METADATA_REG_LAYOUT 0x14
+#define PCI_EP_DMA_METADATA_REG_LAYOUT_ID GENMASK(7, 0)
+#define PCI_EP_DMA_METADATA_REG_LAYOUT_DATA GENMASK(15, 8)
+#define PCI_EP_DMA_METADATA_REG_SIZE 0x18
+
+#define PCI_EP_DMA_METADATA_REG_LAYOUT_DW_EDMA 0x1
+
+#define PCI_EP_DMA_METADATA_CH_ENTRY_SIZE 0x2c
+#define PCI_EP_DMA_METADATA_CH_CTRL 0x00
+#define PCI_EP_DMA_METADATA_CH_CTRL_HW_CH GENMASK(7, 0)
+#define PCI_EP_DMA_METADATA_CH_CTRL_DESC_BAR GENMASK(10, 8)
+#define PCI_EP_DMA_METADATA_CH_CTRL_AUX_BAR GENMASK(14, 12)
+#define PCI_EP_DMA_METADATA_CH_CTRL_AUX_VALID BIT(16)
+#define PCI_EP_DMA_METADATA_CH_DESC_OFF_LO 0x04
+#define PCI_EP_DMA_METADATA_CH_DESC_OFF_HI 0x08
+#define PCI_EP_DMA_METADATA_CH_DESC_SIZE 0x0c
+#define PCI_EP_DMA_METADATA_CH_DESC_ADDR_LO 0x10
+#define PCI_EP_DMA_METADATA_CH_DESC_ADDR_HI 0x14
+#define PCI_EP_DMA_METADATA_CH_AUX_OFF_LO 0x18
+#define PCI_EP_DMA_METADATA_CH_AUX_OFF_HI 0x1c
+#define PCI_EP_DMA_METADATA_CH_AUX_SIZE 0x20
+#define PCI_EP_DMA_METADATA_CH_AUX_ADDR_LO 0x24
+#define PCI_EP_DMA_METADATA_CH_AUX_ADDR_HI 0x28
+
+#endif /* __LINUX_PCI_EP_DMA_H */
--
2.51.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 2/5] PCI: endpoint: Add DMA auxiliary resource metadata
2026-06-20 17:04 [PATCH v3 0/5] PCI: endpoint: Expose endpoint DMA resources (part 2/3) Koichiro Den
2026-06-20 17:04 ` [PATCH v3 1/5] PCI: endpoint: Define endpoint DMA BAR metadata format Koichiro Den
@ 2026-06-20 17:04 ` Koichiro Den
2026-06-20 17:09 ` sashiko-bot
2026-06-20 17:04 ` [PATCH v3 3/5] PCI: endpoint: Add API to delegate EPC DMA channels to the host Koichiro Den
` (2 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Koichiro Den @ 2026-06-20 17:04 UTC (permalink / raw)
To: Jingoo Han, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Bjorn Helgaas,
Kishon Vijay Abraham I, Frank Li, Niklas Cassel
Cc: Marek Vasut, Yoshihiro Shimoda, linux-kernel, linux-pci
Extend EPC auxiliary resource metadata so endpoint functions can
discover controller-owned DMA registers, logical DMA channels, and
descriptor memory.
The DMA metadata is intentionally generic at the EPC layer. A backend
reports the register layout, channel counts, logical channel resources,
and descriptor memory resources. Logical channels carry hardware channel
numbers and refer to descriptor memory by ID; reserving or delegating
those channels is handled by separate EPC operations so resource metadata
stays independent of any backend-specific DMA provider. Descriptor memory
is identified separately so one memory resource can be shared by multiple
channels.
For DesignWare controllers, reg_layout_data carries the eDMA/HDMA map
format so a consumer can distinguish legacy, unroll, HDMA compatible,
and HDMA native register layouts without making the EPC API itself
DesignWare-specific.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
Changes in v3:
- Decouple logical DMA channels from descriptor memory resources (Sashiko).
- Add an explicit unknown DMA register layout value (Sashiko).
- Drop DMAengine filter callbacks from the generic EPC DMA channel
metadata.
- Keep DMA channel metadata provider-independent; channel delegation is
handled by a separate EPC API.
include/linux/pci-epc.h | 47 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
index f247cf9bcf1a..b86d46411065 100644
--- a/include/linux/pci-epc.h
+++ b/include/linux/pci-epc.h
@@ -11,6 +11,7 @@
#include <linux/pci-epf.h>
+struct device;
struct pci_epc;
enum pci_epc_interface_type {
@@ -65,6 +66,9 @@ struct pci_epc_map {
* enum pci_epc_aux_resource_type - auxiliary resource type identifiers
* @PCI_EPC_AUX_DOORBELL_MMIO: Doorbell MMIO, that might be outside the DMA
* controller register window
+ * @PCI_EPC_AUX_DMA_CTRL_MMIO: DMA controller MMIO register window
+ * @PCI_EPC_AUX_DMA_CHAN: Logical DMA channel
+ * @PCI_EPC_AUX_DMA_DESC_MEM: DMA descriptor memory
*
* EPC backends may expose auxiliary blocks (e.g. DMA engines) by mapping their
* register windows and descriptor memories into BAR space. This enum
@@ -72,6 +76,29 @@ struct pci_epc_map {
*/
enum pci_epc_aux_resource_type {
PCI_EPC_AUX_DOORBELL_MMIO,
+ PCI_EPC_AUX_DMA_CTRL_MMIO,
+ PCI_EPC_AUX_DMA_CHAN,
+ PCI_EPC_AUX_DMA_DESC_MEM,
+};
+
+/**
+ * enum pci_epc_aux_dma_reg_layout - DMA controller register layout
+ * @PCI_EPC_AUX_DMA_REG_LAYOUT_UNKNOWN: unknown or uninitialized layout
+ * @PCI_EPC_AUX_DMA_REG_LAYOUT_DW_EDMA: Synopsys DesignWare eDMA/HDMA layout
+ */
+enum pci_epc_aux_dma_reg_layout {
+ PCI_EPC_AUX_DMA_REG_LAYOUT_UNKNOWN = 0,
+ PCI_EPC_AUX_DMA_REG_LAYOUT_DW_EDMA,
+};
+
+/**
+ * enum pci_epc_aux_dma_dir - DMA channel direction relative to the endpoint
+ * @PCI_EPC_AUX_DMA_EP_TO_RC: channel moves data from endpoint to root complex
+ * @PCI_EPC_AUX_DMA_RC_TO_EP: channel moves data from root complex to endpoint
+ */
+enum pci_epc_aux_dma_dir {
+ PCI_EPC_AUX_DMA_EP_TO_RC,
+ PCI_EPC_AUX_DMA_RC_TO_EP,
};
/**
@@ -99,6 +126,26 @@ struct pci_epc_aux_resource {
int irq; /* IRQ number for the doorbell handler */
u32 data; /* write value to ring the doorbell */
} db_mmio;
+
+ /* PCI_EPC_AUX_DMA_CTRL_MMIO */
+ struct {
+ enum pci_epc_aux_dma_reg_layout reg_layout;
+ u32 reg_layout_data;
+ u16 ep_to_rc_ch_cnt;
+ u16 rc_to_ep_ch_cnt;
+ } dma_ctrl;
+
+ /* PCI_EPC_AUX_DMA_CHAN */
+ struct {
+ enum pci_epc_aux_dma_dir dir;
+ u16 hw_ch;
+ u16 desc_mem_id;
+ } dma_chan;
+
+ /* PCI_EPC_AUX_DMA_DESC_MEM */
+ struct {
+ u16 id;
+ } dma_desc;
} u;
};
--
2.51.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 3/5] PCI: endpoint: Add API to delegate EPC DMA channels to the host
2026-06-20 17:04 [PATCH v3 0/5] PCI: endpoint: Expose endpoint DMA resources (part 2/3) Koichiro Den
2026-06-20 17:04 ` [PATCH v3 1/5] PCI: endpoint: Define endpoint DMA BAR metadata format Koichiro Den
2026-06-20 17:04 ` [PATCH v3 2/5] PCI: endpoint: Add DMA auxiliary resource metadata Koichiro Den
@ 2026-06-20 17:04 ` Koichiro Den
2026-06-20 17:26 ` sashiko-bot
2026-06-20 17:04 ` [PATCH v3 4/5] PCI: dwc: Expose endpoint DMA resources Koichiro Den
2026-06-20 17:04 ` [PATCH v3 5/5] PCI: dwc: Implement endpoint DMA channel delegation Koichiro Den
4 siblings, 1 reply; 11+ messages in thread
From: Koichiro Den @ 2026-06-20 17:04 UTC (permalink / raw)
To: Jingoo Han, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Bjorn Helgaas,
Kishon Vijay Abraham I, Frank Li, Niklas Cassel
Cc: Marek Vasut, Yoshihiro Shimoda, linux-kernel, linux-pci
Some endpoint functions expose an EPC-integrated DMA controller to the
host. The endpoint function should not need to know the backend-specific
mechanism used to reserve a channel locally and hand its programming
interface to the host.
Add pci_epc_delegate_dma_chan() and pci_epc_reclaim_dma_chan().
Add matching EPC operations. The public API returns an opaque handle, while
the EPC backend keeps any private channel state. This lets generic endpoint
functions delegate channels without depending on a specific DMAengine
provider.
Let reclaim callers tell the backend whether the channel may have been
exposed to host programming and therefore needs to be quiesced before local
ownership is restored. Bind failure paths that only unwind local
reservations can skip that backend quiesce step.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
Changes in v3:
- New patch. Introduce EPC-level DMA channel delegation to replace
v2's DMAengine filter-callback metadata path for generic endpoint
functions.
- Let reclaim callers skip backend quiesce for delegated channels that
were never exposed to host programming.
drivers/pci/endpoint/pci-epc-core.c | 100 ++++++++++++++++++++++++++++
include/linux/pci-epc.h | 14 ++++
2 files changed, 114 insertions(+)
diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c
index 831b40458dcd..0f71c4633ee5 100644
--- a/drivers/pci/endpoint/pci-epc-core.c
+++ b/drivers/pci/endpoint/pci-epc-core.c
@@ -18,6 +18,13 @@ static const struct class pci_epc_class = {
.name = "pci_epc",
};
+struct pci_epc_dma_chan {
+ struct pci_epc *epc;
+ u8 func_no;
+ u8 vfunc_no;
+ void *data;
+};
+
static void devm_pci_epc_release(struct device *dev, void *res)
{
struct pci_epc *epc = *(struct pci_epc **)res;
@@ -236,6 +243,99 @@ int pci_epc_get_aux_resources(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
}
EXPORT_SYMBOL_GPL(pci_epc_get_aux_resources);
+/**
+ * pci_epc_delegate_dma_chan() - delegate an EPC-owned DMA channel to the host
+ * @epc: EPC device
+ * @func_no: function number
+ * @vfunc_no: virtual function number
+ * @dir: DMA channel direction relative to the endpoint
+ * @hw_ch: hardware channel number
+ * @chan: output delegated-channel handle
+ *
+ * Some EPC backends integrate DMA channels that can be exposed to the host.
+ * This helper asks the backend to reserve the specified channel locally and
+ * place it in a state where the host driver may program it through the exposed
+ * register window.
+ *
+ * Return: 0 on success, -EOPNOTSUPP if the backend does not support DMA channel
+ * delegation, or another -errno on failure.
+ */
+int pci_epc_delegate_dma_chan(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
+ enum pci_epc_aux_dma_dir dir, u16 hw_ch,
+ struct pci_epc_dma_chan **chan)
+{
+ struct pci_epc_dma_chan *epc_chan;
+ void *data = NULL;
+ int ret;
+
+ if (!chan)
+ return -EINVAL;
+ *chan = NULL;
+
+ if (!epc || !epc->ops)
+ return -EINVAL;
+
+ if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
+ return -EINVAL;
+
+ if (dir != PCI_EPC_AUX_DMA_EP_TO_RC &&
+ dir != PCI_EPC_AUX_DMA_RC_TO_EP)
+ return -EINVAL;
+
+ if (!epc->ops->delegate_dma_chan || !epc->ops->reclaim_dma_chan)
+ return -EOPNOTSUPP;
+
+ epc_chan = kzalloc_obj(*epc_chan, GFP_KERNEL);
+ if (!epc_chan)
+ return -ENOMEM;
+
+ mutex_lock(&epc->lock);
+ ret = epc->ops->delegate_dma_chan(epc, func_no, vfunc_no, dir, hw_ch,
+ &data);
+ mutex_unlock(&epc->lock);
+ if (ret) {
+ kfree(epc_chan);
+ return ret;
+ }
+
+ epc_chan->epc = epc;
+ epc_chan->func_no = func_no;
+ epc_chan->vfunc_no = vfunc_no;
+ epc_chan->data = data;
+ *chan = epc_chan;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pci_epc_delegate_dma_chan);
+
+/**
+ * pci_epc_reclaim_dma_chan() - reclaim a delegated EPC-owned DMA channel
+ * @chan: delegated-channel handle returned by pci_epc_delegate_dma_chan()
+ * @quiesce: quiesce the channel before reclaiming it
+ *
+ * Reclaim a channel previously delegated to the host. Set @quiesce for channels
+ * that may have been exposed to host programming. Bind failure paths that are
+ * unwinding local reservations before exposure may leave it clear.
+ */
+void pci_epc_reclaim_dma_chan(struct pci_epc_dma_chan *chan, bool quiesce)
+{
+ struct pci_epc *epc;
+
+ if (!chan)
+ return;
+
+ epc = chan->epc;
+ if (epc && epc->ops && epc->ops->reclaim_dma_chan) {
+ mutex_lock(&epc->lock);
+ epc->ops->reclaim_dma_chan(epc, chan->func_no, chan->vfunc_no,
+ chan->data, quiesce);
+ mutex_unlock(&epc->lock);
+ }
+
+ kfree(chan);
+}
+EXPORT_SYMBOL_GPL(pci_epc_reclaim_dma_chan);
+
/**
* pci_epc_stop() - stop the PCI link
* @epc: the link of the EPC device that has to be stopped
diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
index b86d46411065..84b37d7eb124 100644
--- a/include/linux/pci-epc.h
+++ b/include/linux/pci-epc.h
@@ -13,6 +13,7 @@
struct device;
struct pci_epc;
+struct pci_epc_dma_chan;
enum pci_epc_interface_type {
UNKNOWN_INTERFACE = -1,
@@ -175,6 +176,10 @@ struct pci_epc_aux_resource {
* @get_aux_resources_count: ops to get the number of controller-owned
* auxiliary resources
* @get_aux_resources: ops to retrieve controller-owned auxiliary resources
+ * @delegate_dma_chan: ops to delegate a controller-owned DMA channel to the
+ * host
+ * @reclaim_dma_chan: ops to reclaim a previously delegated DMA channel.
+ * The callback quiesces the channel when requested.
* @owner: the module owner containing the ops
*/
struct pci_epc_ops {
@@ -211,6 +216,11 @@ struct pci_epc_ops {
int (*get_aux_resources)(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
struct pci_epc_aux_resource *resources,
int num_resources);
+ int (*delegate_dma_chan)(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
+ enum pci_epc_aux_dma_dir dir, u16 hw_ch,
+ void **data);
+ void (*reclaim_dma_chan)(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
+ void *data, bool quiesce);
struct module *owner;
};
@@ -444,6 +454,10 @@ int pci_epc_get_aux_resources_count(struct pci_epc *epc, u8 func_no,
int pci_epc_get_aux_resources(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
struct pci_epc_aux_resource *resources,
int num_resources);
+int pci_epc_delegate_dma_chan(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
+ enum pci_epc_aux_dma_dir dir, u16 hw_ch,
+ struct pci_epc_dma_chan **chan);
+void pci_epc_reclaim_dma_chan(struct pci_epc_dma_chan *chan, bool quiesce);
enum pci_barno
pci_epc_get_first_free_bar(const struct pci_epc_features *epc_features);
enum pci_barno pci_epc_get_next_free_bar(const struct pci_epc_features
--
2.51.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 4/5] PCI: dwc: Expose endpoint DMA resources
2026-06-20 17:04 [PATCH v3 0/5] PCI: endpoint: Expose endpoint DMA resources (part 2/3) Koichiro Den
` (2 preceding siblings ...)
2026-06-20 17:04 ` [PATCH v3 3/5] PCI: endpoint: Add API to delegate EPC DMA channels to the host Koichiro Den
@ 2026-06-20 17:04 ` Koichiro Den
2026-06-20 17:14 ` sashiko-bot
2026-06-20 17:04 ` [PATCH v3 5/5] PCI: dwc: Implement endpoint DMA channel delegation Koichiro Den
4 siblings, 1 reply; 11+ messages in thread
From: Koichiro Den @ 2026-06-20 17:04 UTC (permalink / raw)
To: Jingoo Han, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Bjorn Helgaas,
Kishon Vijay Abraham I, Frank Li, Niklas Cassel
Cc: Marek Vasut, Yoshihiro Shimoda, linux-kernel, linux-pci
Expose the DesignWare endpoint-integrated eDMA register window, logical
DMA channels, and linked-list descriptor memories through the EPC
auxiliary resource API. This lets endpoint functions decide which
channels to publish to the host.
When the DMA register window is already visible through a reserved BAR
region, report its BAR and offset. Otherwise report it as a normal
physical resource so an endpoint function can map it. DMA channel
resources carry hardware channel selectors and refer to linked-list
descriptor memory by ID.
Expose DMA resources only after the local DW eDMA provider has been
registered, and only expose channels whose linked-list descriptor memory
is available. DWC non-LL exposure needs a metadata ABI and host parser
extension, so leave it unsupported for now. Reject VF auxiliary resource
queries because the RC-programmable DWC eDMA/HDMA register window is
assigned to a PF BAR only.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
Changes in v3:
- Report logical DMA channels separately from descriptor memory
resources (Sashiko).
- Use channel-referenced descriptor memory resource IDs instead of
embedding descriptor metadata in channel resources (Sashiko).
- Stop exporting DMAengine filter callbacks through EPC auxiliary
resource metadata.
- Suppress DMA aux resources when the local DW eDMA provider is
unavailable.
- Keep DWC exposure limited to linked-list channels until non-LL
metadata and host parsing are added.
- Reject VF resource queries because the DWC eDMA/HDMA register window
is PF-only.
.../pci/controller/dwc/pcie-designware-ep.c | 120 +++++++++++++++++-
1 file changed, 115 insertions(+), 5 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 7d2794945704..770cd7efe699 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -858,6 +858,26 @@ dw_pcie_ep_find_bar_rsvd_region(struct dw_pcie_ep *ep,
return NULL;
}
+static int dw_pcie_ep_check_edma_ll_regions(struct dw_edma_region *region,
+ u16 count)
+{
+ unsigned int i;
+
+ for (i = 0; i < count; i++) {
+ if (region[i].sz)
+ continue;
+
+ /*
+ * To-Do: Add non-LL support to the endpoint DMA metadata ABI
+ * and host parser before exposing channels without descriptor
+ * memory.
+ */
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
static int
dw_pcie_ep_get_aux_resources_count(struct pci_epc *epc, u8 func_no,
u8 vfunc_no)
@@ -865,14 +885,35 @@ dw_pcie_ep_get_aux_resources_count(struct pci_epc *epc, u8 func_no,
struct dw_pcie_ep *ep = epc_get_drvdata(epc);
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
struct dw_edma_chip *edma = &pci->edma;
+ int ret;
+ int count = 1;
- if (!pci->edma_reg_size)
+ if (!pci->edma_reg_size || !edma->dw)
return 0;
- if (edma->db_offset == ~0)
- return 0;
+ /*
+ * DWC eDMA/HDMA register windows exposed to the Root Complex are
+ * assigned to a PF BAR and cannot be assigned to a VF BAR.
+ */
+ if (vfunc_no)
+ return -EOPNOTSUPP;
- return 1;
+ ret = dw_pcie_ep_check_edma_ll_regions(edma->ll_region_wr,
+ edma->ll_wr_cnt);
+ if (ret)
+ return ret;
+
+ ret = dw_pcie_ep_check_edma_ll_regions(edma->ll_region_rd,
+ edma->ll_rd_cnt);
+ if (ret)
+ return ret;
+
+ count += 2 * (edma->ll_wr_cnt + edma->ll_rd_cnt);
+
+ if (edma->db_offset != ~0)
+ count++;
+
+ return count;
}
static int
@@ -888,6 +929,7 @@ dw_pcie_ep_get_aux_resources(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
resource_size_t db_offset = edma->db_offset;
resource_size_t dma_ctrl_bar_offset = 0;
resource_size_t dma_reg_size;
+ unsigned int i;
int count;
count = dw_pcie_ep_get_aux_resources_count(epc, func_no, vfunc_no);
@@ -909,6 +951,74 @@ dw_pcie_ep_get_aux_resources(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
if (rsvd && rsvd->size < dma_reg_size)
dma_reg_size = rsvd->size;
+ count = 0;
+ resources[count++] = (struct pci_epc_aux_resource) {
+ .type = PCI_EPC_AUX_DMA_CTRL_MMIO,
+ .phys_addr = pci->edma_reg_phys,
+ .size = dma_reg_size,
+ .bar = dma_ctrl_bar,
+ .bar_offset = dma_ctrl_bar != NO_BAR ? dma_ctrl_bar_offset : 0,
+ .u.dma_ctrl = {
+ .reg_layout = PCI_EPC_AUX_DMA_REG_LAYOUT_DW_EDMA,
+ .reg_layout_data = edma->mf,
+ .ep_to_rc_ch_cnt = edma->ll_wr_cnt,
+ .rc_to_ep_ch_cnt = edma->ll_rd_cnt,
+ },
+ };
+
+ for (i = 0; i < edma->ll_wr_cnt; i++) {
+ struct dw_edma_region *ll = &edma->ll_region_wr[i];
+ u16 desc_mem_id = i;
+
+ resources[count++] = (struct pci_epc_aux_resource) {
+ .type = PCI_EPC_AUX_DMA_CHAN,
+ .bar = NO_BAR,
+ .u.dma_chan = {
+ .dir = PCI_EPC_AUX_DMA_EP_TO_RC,
+ .hw_ch = i,
+ .desc_mem_id = desc_mem_id,
+ },
+ };
+
+ resources[count++] = (struct pci_epc_aux_resource) {
+ .type = PCI_EPC_AUX_DMA_DESC_MEM,
+ .phys_addr = ll->paddr,
+ .size = ll->sz,
+ .bar = NO_BAR,
+ .u.dma_desc = {
+ .id = desc_mem_id,
+ },
+ };
+ }
+
+ for (i = 0; i < edma->ll_rd_cnt; i++) {
+ struct dw_edma_region *ll = &edma->ll_region_rd[i];
+ u16 desc_mem_id = edma->ll_wr_cnt + i;
+
+ resources[count++] = (struct pci_epc_aux_resource) {
+ .type = PCI_EPC_AUX_DMA_CHAN,
+ .bar = NO_BAR,
+ .u.dma_chan = {
+ .dir = PCI_EPC_AUX_DMA_RC_TO_EP,
+ .hw_ch = i,
+ .desc_mem_id = desc_mem_id,
+ },
+ };
+
+ resources[count++] = (struct pci_epc_aux_resource) {
+ .type = PCI_EPC_AUX_DMA_DESC_MEM,
+ .phys_addr = ll->paddr,
+ .size = ll->sz,
+ .bar = NO_BAR,
+ .u.dma_desc = {
+ .id = desc_mem_id,
+ },
+ };
+ }
+
+ if (db_offset == ~0)
+ return 0;
+
/*
* For interrupt-emulation doorbells, report a standalone resource
* instead of bundling it into the DMA controller MMIO resource.
@@ -917,7 +1027,7 @@ dw_pcie_ep_get_aux_resources(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
sizeof(u32), dma_reg_size))
return -EINVAL;
- resources[0] = (struct pci_epc_aux_resource) {
+ resources[count] = (struct pci_epc_aux_resource) {
.type = PCI_EPC_AUX_DOORBELL_MMIO,
.phys_addr = pci->edma_reg_phys + db_offset,
.size = sizeof(u32),
--
2.51.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v3 5/5] PCI: dwc: Implement endpoint DMA channel delegation
2026-06-20 17:04 [PATCH v3 0/5] PCI: endpoint: Expose endpoint DMA resources (part 2/3) Koichiro Den
` (3 preceding siblings ...)
2026-06-20 17:04 ` [PATCH v3 4/5] PCI: dwc: Expose endpoint DMA resources Koichiro Den
@ 2026-06-20 17:04 ` Koichiro Den
2026-06-20 17:16 ` sashiko-bot
4 siblings, 1 reply; 11+ messages in thread
From: Koichiro Den @ 2026-06-20 17:04 UTC (permalink / raw)
To: Jingoo Han, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Bjorn Helgaas,
Kishon Vijay Abraham I, Frank Li, Niklas Cassel
Cc: Marek Vasut, Yoshihiro Shimoda, linux-kernel, linux-pci
Implement the EPC DMA channel delegation operations for DesignWare
endpoint controllers. The DWC backend uses the local DesignWare eDMA
provider to reserve the requested hardware channel and returns it as an
opaque EPC DMA channel handle to generic endpoint functions.
Validate the requested direction and hardware channel against the
linked-list channel counts before delegation.
Limit endpoint DMA resource exposure and channel delegation to PF0.
DWC eDMA/HDMA can generate DMA requests with a programmable function
number, but dw-edma does not program it yet. Reject PF1+ requests so
delegated DMA channels do not issue TLPs with the default requester
function number when the endpoint function is PF1+.
Reject VF requests because the RC-programmable DWC eDMA/HDMA register
window is assigned to a PF BAR only.
Reclaim releases the delegated local channel through the DesignWare eDMA
provider, which returns it to endpoint ownership. Propagate the EPC
quiesce request so bind failure paths can release unexposed reservations
without touching DMA engine state.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
Changes in v3:
- New patch. Implement the DWC backend for EPC DMA channel delegation,
replacing the v2 DMAengine filter-callback metadata path.
.../pci/controller/dwc/pcie-designware-ep.c | 84 +++++++++++++++++--
1 file changed, 78 insertions(+), 6 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 770cd7efe699..ebf3db4386b4 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -878,6 +878,26 @@ static int dw_pcie_ep_check_edma_ll_regions(struct dw_edma_region *region,
return 0;
}
+static int dw_pcie_ep_check_edma_func(u8 func_no, u8 vfunc_no)
+{
+ /*
+ * The DWC endpoint databook says it is not possible to assign the
+ * DMA/HDMA registers to any Virtual Function.
+ */
+ if (vfunc_no)
+ return -EOPNOTSUPP;
+
+ /*
+ * To-Do: Supporting PF1+ needs dw-edma core support to carry the
+ * endpoint function number into channel setup and program the eDMA/HDMA
+ * requester-ID registers.
+ */
+ if (func_no)
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
static int
dw_pcie_ep_get_aux_resources_count(struct pci_epc *epc, u8 func_no,
u8 vfunc_no)
@@ -891,12 +911,9 @@ dw_pcie_ep_get_aux_resources_count(struct pci_epc *epc, u8 func_no,
if (!pci->edma_reg_size || !edma->dw)
return 0;
- /*
- * DWC eDMA/HDMA register windows exposed to the Root Complex are
- * assigned to a PF BAR and cannot be assigned to a VF BAR.
- */
- if (vfunc_no)
- return -EOPNOTSUPP;
+ ret = dw_pcie_ep_check_edma_func(func_no, vfunc_no);
+ if (ret)
+ return ret;
ret = dw_pcie_ep_check_edma_ll_regions(edma->ll_region_wr,
edma->ll_wr_cnt);
@@ -1043,6 +1060,59 @@ dw_pcie_ep_get_aux_resources(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
return 0;
}
+static int dw_pcie_ep_delegate_dma_chan(struct pci_epc *epc, u8 func_no,
+ u8 vfunc_no,
+ enum pci_epc_aux_dma_dir dir, u16 hw_ch,
+ void **data)
+{
+ struct dw_pcie_ep *ep = epc_get_drvdata(epc);
+ struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+ struct dw_edma_chip *edma = &pci->edma;
+ struct dma_chan *chan;
+ int ret;
+ bool write;
+
+ if (!data)
+ return -EINVAL;
+ *data = NULL;
+
+ ret = dw_pcie_ep_check_edma_func(func_no, vfunc_no);
+ if (ret)
+ return ret;
+
+ if (!edma->dw)
+ return -ENODEV;
+
+ switch (dir) {
+ case PCI_EPC_AUX_DMA_EP_TO_RC:
+ if (hw_ch >= edma->ll_wr_cnt)
+ return -EINVAL;
+ write = true;
+ break;
+ case PCI_EPC_AUX_DMA_RC_TO_EP:
+ if (hw_ch >= edma->ll_rd_cnt)
+ return -EINVAL;
+ write = false;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ chan = dw_edma_request_delegated_chan(edma->dev, write, hw_ch);
+ if (!chan)
+ return -EBUSY;
+
+ *data = chan;
+
+ return 0;
+}
+
+static void dw_pcie_ep_reclaim_dma_chan(struct pci_epc *epc, u8 func_no,
+ u8 vfunc_no, void *data, bool quiesce)
+{
+ dw_edma_release_delegated_chan(data, quiesce);
+}
+
static const struct pci_epc_ops epc_ops = {
.write_header = dw_pcie_ep_write_header,
.set_bar = dw_pcie_ep_set_bar,
@@ -1060,6 +1130,8 @@ static const struct pci_epc_ops epc_ops = {
.get_features = dw_pcie_ep_get_features,
.get_aux_resources_count = dw_pcie_ep_get_aux_resources_count,
.get_aux_resources = dw_pcie_ep_get_aux_resources,
+ .delegate_dma_chan = dw_pcie_ep_delegate_dma_chan,
+ .reclaim_dma_chan = dw_pcie_ep_reclaim_dma_chan,
};
/**
--
2.51.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v3 2/5] PCI: endpoint: Add DMA auxiliary resource metadata
2026-06-20 17:04 ` [PATCH v3 2/5] PCI: endpoint: Add DMA auxiliary resource metadata Koichiro Den
@ 2026-06-20 17:09 ` sashiko-bot
0 siblings, 0 replies; 11+ messages in thread
From: sashiko-bot @ 2026-06-20 17:09 UTC (permalink / raw)
To: Koichiro Den; +Cc: linux-pci
> Extend EPC auxiliary resource metadata so endpoint functions can
> discover controller-owned DMA registers, logical DMA channels, and
> descriptor memory.
>
> The DMA metadata is intentionally generic at the EPC layer. A backend
> reports the register layout, channel counts, logical channel resources,
> and descriptor memory resources. Logical channels carry hardware channel
> numbers and refer to descriptor memory by ID; reserving or delegating
> those channels is handled by separate EPC operations so resource metadata
> stays independent of any backend-specific DMA provider. Descriptor memory
> is identified separately so one memory resource can be shared by multiple
> channels.
>
> For DesignWare controllers, reg_layout_data carries the eDMA/HDMA map
> format so a consumer can distinguish legacy, unroll, HDMA compatible,
> and HDMA native register layouts without making the EPC API itself
> DesignWare-specific.
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260620170438.3756593-1-den@valinux.co.jp?part=2
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/5] PCI: endpoint: Define endpoint DMA BAR metadata format
2026-06-20 17:04 ` [PATCH v3 1/5] PCI: endpoint: Define endpoint DMA BAR metadata format Koichiro Den
@ 2026-06-20 17:10 ` sashiko-bot
0 siblings, 0 replies; 11+ messages in thread
From: sashiko-bot @ 2026-06-20 17:10 UTC (permalink / raw)
To: Koichiro Den; +Cc: linux-pci
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The endpoint DMA BAR metadata format contains an inherent limit mismatch between the `metadata length` field and the maximum possible size of the tables it describes.
--
commit 8e3a71eaeea3ed7cc589bce08e6fd2a630ca1075
Author: Koichiro Den <den@valinux.co.jp>
PCI: endpoint: Define endpoint DMA BAR metadata format
This commit defines a BAR-resident metadata format for endpoint functions
that expose an endpoint-integrated DMA controller to a PCI host.
> diff --git a/include/linux/pci-ep-dma.h b/include/linux/pci-ep-dma.h
> new file mode 100644
> index 0000000000000..c5fd7aab2101f
> --- /dev/null
> +++ b/include/linux/pci-ep-dma.h
[ ... ]
> +#define PCI_EP_DMA_METADATA_HDR_LEN 0x1c
> +
> +#define PCI_EP_DMA_METADATA_HDR 0x04
> +#define PCI_EP_DMA_METADATA_HDR_REV GENMASK(7, 0)
> +#define PCI_EP_DMA_METADATA_HDR_LEN_FIELD GENMASK(31, 16)
> +
> +#define PCI_EP_DMA_METADATA_CTRL 0x08
> +#define PCI_EP_DMA_METADATA_CTRL_REG_BAR GENMASK(2, 0)
> +#define PCI_EP_DMA_METADATA_CTRL_WR_CH_COUNT GENMASK(10, 3)
> +#define PCI_EP_DMA_METADATA_CTRL_RD_CH_COUNT GENMASK(18, 11)
> +#define PCI_EP_DMA_METADATA_CTRL_CH_ENTRY_SIZE GENMASK(26, 19)
[Severity: Medium]
Could this layout result in the total computed size exceeding the 16-bit
length field capacity?
The PCI_EP_DMA_METADATA_HDR_LEN_FIELD defines a 16-bit metadata length
field (maximum 65,535 bytes). However, the format also specifies an 8-bit
write channel count (up to 255), an 8-bit read channel count (up to 255),
and an 8-bit channel entry size (up to 255 bytes).
If an endpoint were to specify these maximum values, the total computed size
could reach 130,078 bytes (a 28 byte header plus 510 channels at 255 bytes
each). This exceeds the maximum value that the 16-bit metadata length
field can represent.
Would this ABI inconsistency allow a malicious endpoint to craft a payload
where the table bounds exceed the reported length, potentially leading to
out-of-bounds reads in future host drivers if they map memory based on the
length but iterate using the channel counts?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260620170438.3756593-1-den@valinux.co.jp?part=1
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 4/5] PCI: dwc: Expose endpoint DMA resources
2026-06-20 17:04 ` [PATCH v3 4/5] PCI: dwc: Expose endpoint DMA resources Koichiro Den
@ 2026-06-20 17:14 ` sashiko-bot
0 siblings, 0 replies; 11+ messages in thread
From: sashiko-bot @ 2026-06-20 17:14 UTC (permalink / raw)
To: Koichiro Den; +Cc: linux-pci
> Expose the DesignWare endpoint-integrated eDMA register window, logical
> DMA channels, and linked-list descriptor memories through the EPC
> auxiliary resource API. This lets endpoint functions decide which
> channels to publish to the host.
>
> When the DMA register window is already visible through a reserved BAR
> region, report its BAR and offset. Otherwise report it as a normal
> physical resource so an endpoint function can map it. DMA channel
> resources carry hardware channel selectors and refer to linked-list
> descriptor memory by ID.
>
> Expose DMA resources only after the local DW eDMA provider has been
> registered, and only expose channels whose linked-list descriptor memory
> is available. DWC non-LL exposure needs a metadata ABI and host parser
> extension, so leave it unsupported for now. Reject VF auxiliary resource
> queries because the RC-programmable DWC eDMA/HDMA register window is
> assigned to a PF BAR only.
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260620170438.3756593-1-den@valinux.co.jp?part=4
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 5/5] PCI: dwc: Implement endpoint DMA channel delegation
2026-06-20 17:04 ` [PATCH v3 5/5] PCI: dwc: Implement endpoint DMA channel delegation Koichiro Den
@ 2026-06-20 17:16 ` sashiko-bot
0 siblings, 0 replies; 11+ messages in thread
From: sashiko-bot @ 2026-06-20 17:16 UTC (permalink / raw)
To: Koichiro Den; +Cc: linux-pci
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Calls to undeclared and undefined functions `dw_edma_request_delegated_chan` and `dw_edma_release_delegated_chan` will cause compilation and linking failures.
--
commit e55470d381c0b56d92a5e22c376824161b53e132
Author: Koichiro Den <den@valinux.co.jp>
PCI: dwc: Implement endpoint DMA channel delegation
This commit implements the EPC DMA channel delegation operations for
DesignWare endpoint controllers. It uses the local eDMA provider to reserve
hardware channels and returns them as opaque handles, limiting delegation
to PF0 and handling reclamation.
> diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
> --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
[ ... ]
> +static int dw_pcie_ep_delegate_dma_chan(struct pci_epc *epc, u8 func_no,
> + u8 vfunc_no,
> + enum pci_epc_aux_dma_dir dir, u16 hw_ch,
> + void **data)
> +{
[ ... ]
> + switch (dir) {
> + case PCI_EPC_AUX_DMA_EP_TO_RC:
> + if (hw_ch >= edma->ll_wr_cnt)
> + return -EINVAL;
> + write = true;
> + break;
> + case PCI_EPC_AUX_DMA_RC_TO_EP:
> + if (hw_ch >= edma->ll_rd_cnt)
> + return -EINVAL;
> + write = false;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + chan = dw_edma_request_delegated_chan(edma->dev, write, hw_ch);
[Severity: Low]
Are the definitions for dw_edma_request_delegated_chan() missing from this
commit? Calling undeclared and undefined functions in
dw_pcie_ep_delegate_dma_chan() will result in compilation and linking
failures.
> + if (!chan)
> + return -EBUSY;
> +
> + *data = chan;
> +
> + return 0;
> +}
> +
> +static void dw_pcie_ep_reclaim_dma_chan(struct pci_epc *epc, u8 func_no,
> + u8 vfunc_no, void *data, bool quiesce)
> +{
> + dw_edma_release_delegated_chan(data, quiesce);
[Severity: Low]
Does this code also rely on an undefined function? Like the request function
above, dw_edma_release_delegated_chan() appears to be undeclared in the
kernel tree at this point, which will break the build.
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260620170438.3756593-1-den@valinux.co.jp?part=5
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v3 3/5] PCI: endpoint: Add API to delegate EPC DMA channels to the host
2026-06-20 17:04 ` [PATCH v3 3/5] PCI: endpoint: Add API to delegate EPC DMA channels to the host Koichiro Den
@ 2026-06-20 17:26 ` sashiko-bot
0 siblings, 0 replies; 11+ messages in thread
From: sashiko-bot @ 2026-06-20 17:26 UTC (permalink / raw)
To: Koichiro Den; +Cc: linux-pci
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Error pointer dereference in `pci_epc_delegate_dma_chan` due to incorrect validation order.
--
commit b5fefb01d3a350b55650bc026830cacbecfcc978
Author: Koichiro Den <den@valinux.co.jp>
PCI: endpoint: Add API to delegate EPC DMA channels to the host
This commit adds pci_epc_delegate_dma_chan() and pci_epc_reclaim_dma_chan()
to allow generic endpoint functions to delegate integrated DMA channels to
the host. It introduces matching EPC operations and uses an opaque handle
for channel state management to avoid backend-specific dependencies.
> diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c
> index 831b40458dcd8..0f71c4633ee54 100644
> --- a/drivers/pci/endpoint/pci-epc-core.c
> +++ b/drivers/pci/endpoint/pci-epc-core.c
[ ... ]
> @@ -236,6 +243,99 @@ int pci_epc_get_aux_resources(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
> }
> EXPORT_SYMBOL_GPL(pci_epc_get_aux_resources);
>
> +/**
> + * pci_epc_delegate_dma_chan() - delegate an EPC-owned DMA channel to the host
[ ... ]
> +int pci_epc_delegate_dma_chan(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
> + enum pci_epc_aux_dma_dir dir, u16 hw_ch,
> + struct pci_epc_dma_chan **chan)
> +{
> + struct pci_epc_dma_chan *epc_chan;
> + void *data = NULL;
> + int ret;
> +
> + if (!chan)
> + return -EINVAL;
> + *chan = NULL;
> +
> + if (!epc || !epc->ops)
> + return -EINVAL;
[Severity: High]
If a caller passes an error pointer for epc, will the !epc->ops check
trigger a crash?
Functions like pci_epc_get() return ERR_PTR(-EINVAL) on failure rather
than NULL. If epc is an error pointer, the !epc check evaluates to false,
causing execution to proceed to the !epc->ops check. Dereferencing epc->ops
on an error pointer will trigger a kernel crash.
> +
> + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
> + return -EINVAL;
The subsequent call to pci_epc_function_is_valid() internally uses
IS_ERR_OR_NULL(epc) to safely handle error pointers, but placing the ops
dereference before it circumvents this safety.
Would it be better to move the pci_epc_function_is_valid() check before
dereferencing epc->ops, or explicitly check IS_ERR_OR_NULL(epc) first?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260620170438.3756593-1-den@valinux.co.jp?part=3
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-06-20 17:26 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-20 17:04 [PATCH v3 0/5] PCI: endpoint: Expose endpoint DMA resources (part 2/3) Koichiro Den
2026-06-20 17:04 ` [PATCH v3 1/5] PCI: endpoint: Define endpoint DMA BAR metadata format Koichiro Den
2026-06-20 17:10 ` sashiko-bot
2026-06-20 17:04 ` [PATCH v3 2/5] PCI: endpoint: Add DMA auxiliary resource metadata Koichiro Den
2026-06-20 17:09 ` sashiko-bot
2026-06-20 17:04 ` [PATCH v3 3/5] PCI: endpoint: Add API to delegate EPC DMA channels to the host Koichiro Den
2026-06-20 17:26 ` sashiko-bot
2026-06-20 17:04 ` [PATCH v3 4/5] PCI: dwc: Expose endpoint DMA resources Koichiro Den
2026-06-20 17:14 ` sashiko-bot
2026-06-20 17:04 ` [PATCH v3 5/5] PCI: dwc: Implement endpoint DMA channel delegation Koichiro Den
2026-06-20 17:16 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox