* [PATCH 0/2] PCI: endpoint: BAR subrange mapping support
@ 2026-01-05 8:02 Koichiro Den
2026-01-05 8:02 ` [PATCH 1/2] PCI: endpoint: Add " Koichiro Den
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Koichiro Den @ 2026-01-05 8:02 UTC (permalink / raw)
To: jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas
Cc: Frank.Li, linux-pci, linux-kernel
This series proposes support for mapping subranges within a PCIe endpoint
BAR and enables controllers to program inbound address translation for
those subranges.
The first patch introduces generic BAR subrange mapping support in the
PCI endpoint core. The second patch adds an implementation for the
DesignWare PCIe endpoint controller using Address Match Mode IB iATU.
This series is a spin-off from a larger RFC series posted earlier:
https://lore.kernel.org/all/20251217151609.3162665-4-den@valinux.co.jp/
Base:
git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git
branch: controller/dwc
commit: 68ac85fb42cf ("PCI: dwc: Use cfg0_base as iMSI-RX target address
to support 32-bit MSI devices")
Thank you for reviewing,
Koichiro Den (2):
PCI: endpoint: Add BAR subrange mapping support
PCI: dwc: ep: Support BAR subrange inbound mapping via address-match
iATU
.../pci/controller/dwc/pcie-designware-ep.c | 198 ++++++++++++++++--
drivers/pci/controller/dwc/pcie-designware.h | 2 +
include/linux/pci-epf.h | 26 +++
3 files changed, 214 insertions(+), 12 deletions(-)
--
2.51.0
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH 1/2] PCI: endpoint: Add BAR subrange mapping support 2026-01-05 8:02 [PATCH 0/2] PCI: endpoint: BAR subrange mapping support Koichiro Den @ 2026-01-05 8:02 ` Koichiro Den 2026-01-05 8:02 ` [PATCH 2/2] PCI: dwc: ep: Support BAR subrange inbound mapping via address-match iATU Koichiro Den 2026-01-05 16:55 ` [PATCH 0/2] PCI: endpoint: BAR subrange mapping support Niklas Cassel 2 siblings, 0 replies; 10+ messages in thread From: Koichiro Den @ 2026-01-05 8:02 UTC (permalink / raw) To: jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas Cc: Frank.Li, linux-pci, linux-kernel Extend the PCI endpoint core to support mapping subranges within a BAR. Introduce a new 'submap' field and a 'use_submap' flag in struct pci_epf_bar so an endpoint function driver can request inbound mappings that cover only a portion of a BAR. This provides the generic infrastructure needed to map multiple logical regions into a single BAR at different offsets, without assuming a controller-specific inbound address translation mechanism. No controller-specific implementation is added in this commit. Signed-off-by: Koichiro Den <den@valinux.co.jp> --- include/linux/pci-epf.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/include/linux/pci-epf.h b/include/linux/pci-epf.h index 48f68c4dcfa5..164768db85f6 100644 --- a/include/linux/pci-epf.h +++ b/include/linux/pci-epf.h @@ -110,6 +110,24 @@ struct pci_epf_driver { #define to_pci_epf_driver(drv) container_of_const((drv), struct pci_epf_driver, driver) +/** + * struct pci_epf_bar_submap - represents a BAR subrange for inbound mapping + * @phys_addr: physical address that should be mapped to the BAR subrange + * @size: the size of the subrange to be mapped + * @offset: The byte offset from the BAR base + * + * When pci_epf_bar.use_submap is set, an EPF driver may describe multiple + * independent mappings within a single BAR. An EPC driver can use these + * descriptors to set up the required address translation (e.g. multiple + * inbound iATU regions) without requiring the whole BAR to be mapped at + * once. + */ +struct pci_epf_bar_submap { + dma_addr_t phys_addr; + size_t size; + size_t offset; +}; + /** * struct pci_epf_bar - represents the BAR of EPF device * @phys_addr: physical address that should be mapped to the BAR @@ -119,6 +137,9 @@ struct pci_epf_driver { * requirement * @barno: BAR number * @flags: flags that are set for the BAR + * @use_submap: set true to request subrange mappings within this BAR + * @num_submap: number of entries in @submap + * @submap: array of subrange descriptors allocated by the caller */ struct pci_epf_bar { dma_addr_t phys_addr; @@ -127,6 +148,11 @@ struct pci_epf_bar { size_t mem_size; enum pci_barno barno; int flags; + + /* Optional sub-range mapping */ + bool use_submap; + int num_submap; + struct pci_epf_bar_submap *submap; }; /** -- 2.51.0 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/2] PCI: dwc: ep: Support BAR subrange inbound mapping via address-match iATU 2026-01-05 8:02 [PATCH 0/2] PCI: endpoint: BAR subrange mapping support Koichiro Den 2026-01-05 8:02 ` [PATCH 1/2] PCI: endpoint: Add " Koichiro Den @ 2026-01-05 8:02 ` Koichiro Den 2026-01-05 16:55 ` [PATCH 0/2] PCI: endpoint: BAR subrange mapping support Niklas Cassel 2 siblings, 0 replies; 10+ messages in thread From: Koichiro Den @ 2026-01-05 8:02 UTC (permalink / raw) To: jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas Cc: Frank.Li, linux-pci, linux-kernel Extend dw_pcie_ep_set_bar() to support inbound mappings for BAR subranges using Address Match Mode IB iATU. Refactor the existing BAR-match helper into dw_pcie_ep_ib_atu_bar() and introduce dw_pcie_ep_ib_atu_addr() for address-match mode. When an endpoint function requests subrange mapping via pci_epf_bar.submap, the DesignWare PCIe endpoint controller programs an inbound iATU entry that matches only the specified address range within the BAR. This builds on the generic BAR subrange mapping support added in the PCI endpoint core. Signed-off-by: Koichiro Den <den@valinux.co.jp> --- .../pci/controller/dwc/pcie-designware-ep.c | 198 ++++++++++++++++-- drivers/pci/controller/dwc/pcie-designware.h | 2 + 2 files changed, 188 insertions(+), 12 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c index 1195d401df19..d1e50e9989ed 100644 --- a/drivers/pci/controller/dwc/pcie-designware-ep.c +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c @@ -139,9 +139,10 @@ static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no, u8 vfunc_no, return 0; } -static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no, int type, - dma_addr_t parent_bus_addr, enum pci_barno bar, - size_t size) +/* Bar match mode */ +static int dw_pcie_ep_ib_atu_bar(struct dw_pcie_ep *ep, u8 func_no, int type, + dma_addr_t parent_bus_addr, enum pci_barno bar, + size_t size) { int ret; u32 free_win; @@ -174,6 +175,151 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no, int type, return 0; } +struct dw_pcie_ib_map { + struct list_head list; + enum pci_barno bar; + u64 pci_addr; + u64 parent_bus_addr; + u64 size; + u32 index; +}; + +static struct dw_pcie_ib_map * +dw_pcie_ep_find_ib_map(struct dw_pcie_ep *ep, enum pci_barno bar, u64 pci_addr) +{ + struct dw_pcie_ib_map *m; + + list_for_each_entry(m, &ep->ib_map_list, list) { + if (m->bar == bar && m->pci_addr == pci_addr) + return m; + } + + return NULL; +} + +static u64 dw_pcie_ep_read_bar_assigned(struct dw_pcie_ep *ep, u8 func_no, + enum pci_barno bar, int flags) +{ + u32 reg = PCI_BASE_ADDRESS_0 + (4 * bar); + u32 lo, hi; + u64 addr; + + lo = dw_pcie_ep_readl_dbi(ep, func_no, reg); + + if (flags & PCI_BASE_ADDRESS_SPACE) + return lo & PCI_BASE_ADDRESS_IO_MASK; + + addr = lo & PCI_BASE_ADDRESS_MEM_MASK; + if (!(flags & PCI_BASE_ADDRESS_MEM_TYPE_64)) + return addr; + + hi = dw_pcie_ep_readl_dbi(ep, func_no, reg + 4); + return addr | ((u64)hi << 32); +} + +/* Address match mode */ +static int dw_pcie_ep_ib_atu_addr(struct dw_pcie_ep *ep, u8 func_no, int type, + struct pci_epf_bar *epf_bar) +{ + struct pci_epf_bar_submap *submap = epf_bar->submap; + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + enum pci_barno bar = epf_bar->barno; + struct dw_pcie_ib_map *m, *new; + struct device *dev = pci->dev; + u64 pci_addr, parent_bus_addr; + u64 size, off, base; + unsigned long flags; + int free_win, ret; + u32 i; + + if (!epf_bar->num_submap) + return 0; + + if (!submap) + return -EINVAL; + + base = dw_pcie_ep_read_bar_assigned(ep, func_no, bar, epf_bar->flags); + if (!base) { + dev_err(dev, + "BAR%u not assigned, cannot set up sub-range mappings\n", + bar); + return -EINVAL; + } + + for (i = 0; i < epf_bar->num_submap; i++) { + off = submap[i].offset; + size = submap[i].size; + parent_bus_addr = submap[i].phys_addr; + + if (!size) + continue; + + if (off > (~0ULL) - base) + return -EINVAL; + + pci_addr = base + off; + + new = devm_kzalloc(dev, sizeof(*new), GFP_KERNEL); + if (!new) + return -ENOMEM; + + spin_lock_irqsave(&ep->ib_map_lock, flags); + m = dw_pcie_ep_find_ib_map(ep, bar, pci_addr); + if (m) { + if (m->parent_bus_addr == parent_bus_addr && + m->size == size) { + spin_unlock_irqrestore(&ep->ib_map_lock, flags); + devm_kfree(dev, new); + continue; + } + + ret = dw_pcie_prog_inbound_atu(pci, m->index, type, + parent_bus_addr, pci_addr, + size); + if (!ret) { + m->parent_bus_addr = parent_bus_addr; + m->size = size; + } + spin_unlock_irqrestore(&ep->ib_map_lock, flags); + devm_kfree(dev, new); + if (ret) + return ret; + continue; + } + + free_win = find_first_zero_bit(ep->ib_window_map, + pci->num_ib_windows); + if (free_win >= pci->num_ib_windows) { + spin_unlock_irqrestore(&ep->ib_map_lock, flags); + devm_kfree(dev, new); + return -ENOSPC; + } + set_bit(free_win, ep->ib_window_map); + + new->bar = bar; + new->index = free_win; + new->pci_addr = pci_addr; + new->parent_bus_addr = parent_bus_addr; + new->size = size; + list_add_tail(&new->list, &ep->ib_map_list); + + spin_unlock_irqrestore(&ep->ib_map_lock, flags); + + ret = dw_pcie_prog_inbound_atu(pci, free_win, type, + parent_bus_addr, pci_addr, size); + if (ret) { + spin_lock_irqsave(&ep->ib_map_lock, flags); + list_del(&new->list); + clear_bit(free_win, ep->ib_window_map); + spin_unlock_irqrestore(&ep->ib_map_lock, flags); + devm_kfree(dev, new); + return ret; + } + } + + return 0; +} + static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, struct dw_pcie_ob_atu_cfg *atu) { @@ -204,17 +350,35 @@ static void dw_pcie_ep_clear_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no, struct dw_pcie_ep *ep = epc_get_drvdata(epc); struct dw_pcie *pci = to_dw_pcie_from_ep(ep); enum pci_barno bar = epf_bar->barno; - u32 atu_index = ep->bar_to_atu[bar] - 1; + struct dw_pcie_ib_map *m, *tmp; + struct device *dev = pci->dev; + u32 atu_index; - if (!ep->bar_to_atu[bar]) + if (!ep->epf_bar[bar]) return; __dw_pcie_ep_reset_bar(pci, func_no, bar, epf_bar->flags); - dw_pcie_disable_atu(pci, PCIE_ATU_REGION_DIR_IB, atu_index); - clear_bit(atu_index, ep->ib_window_map); + /* BAR match iATU */ + if (ep->bar_to_atu[bar]) { + atu_index = ep->bar_to_atu[bar] - 1; + dw_pcie_disable_atu(pci, PCIE_ATU_REGION_DIR_IB, atu_index); + clear_bit(atu_index, ep->ib_window_map); + ep->bar_to_atu[bar] = 0; + } + + /* Address match iATU */ + guard(spinlock_irqsave)(&ep->ib_map_lock); + list_for_each_entry_safe(m, tmp, &ep->ib_map_list, list) { + if (m->bar != bar) + continue; + dw_pcie_disable_atu(pci, PCIE_ATU_REGION_DIR_IB, m->index); + clear_bit(m->index, ep->ib_window_map); + list_del(&m->list); + devm_kfree(dev, m); + } + ep->epf_bar[bar] = NULL; - ep->bar_to_atu[bar] = 0; } static unsigned int dw_pcie_ep_get_rebar_offset(struct dw_pcie *pci, @@ -364,10 +528,14 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no, /* * We can only dynamically change a BAR if the new BAR size and * BAR flags do not differ from the existing configuration. + * When 'use_submap' is set and the intention is to create + * sub-range mappings perhaps incrementally, epf_bar->size + * does not mean anything so no need to validate it. */ if (ep->epf_bar[bar]->barno != bar || - ep->epf_bar[bar]->size != size || - ep->epf_bar[bar]->flags != flags) + ep->epf_bar[bar]->flags != flags || + ep->epf_bar[bar]->use_submap != epf_bar->use_submap || + (!epf_bar->use_submap && ep->epf_bar[bar]->size != size)) return -EINVAL; /* @@ -408,8 +576,12 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no, else type = PCIE_ATU_TYPE_IO; - ret = dw_pcie_ep_inbound_atu(ep, func_no, type, epf_bar->phys_addr, bar, - size); + if (epf_bar->use_submap) + ret = dw_pcie_ep_ib_atu_addr(ep, func_no, type, epf_bar); + else + ret = dw_pcie_ep_ib_atu_bar(ep, func_no, type, + epf_bar->phys_addr, bar, size); + if (ret) return ret; @@ -1120,6 +1292,8 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep) struct device *dev = pci->dev; INIT_LIST_HEAD(&ep->func_list); + INIT_LIST_HEAD(&ep->ib_map_list); + spin_lock_init(&ep->ib_map_lock); ep->msi_iatu_mapped = false; ep->msi_msg_addr = 0; ep->msi_map_size = 0; diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index f87c67a7a482..1ebe8a9ee139 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -479,6 +479,8 @@ struct dw_pcie_ep { phys_addr_t *outbound_addr; unsigned long *ib_window_map; unsigned long *ob_window_map; + struct list_head ib_map_list; + spinlock_t ib_map_lock; void __iomem *msi_mem; phys_addr_t msi_mem_phys; struct pci_epf_bar *epf_bar[PCI_STD_NUM_BARS]; -- 2.51.0 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 0/2] PCI: endpoint: BAR subrange mapping support 2026-01-05 8:02 [PATCH 0/2] PCI: endpoint: BAR subrange mapping support Koichiro Den 2026-01-05 8:02 ` [PATCH 1/2] PCI: endpoint: Add " Koichiro Den 2026-01-05 8:02 ` [PATCH 2/2] PCI: dwc: ep: Support BAR subrange inbound mapping via address-match iATU Koichiro Den @ 2026-01-05 16:55 ` Niklas Cassel 2026-01-06 1:52 ` Koichiro Den 2 siblings, 1 reply; 10+ messages in thread From: Niklas Cassel @ 2026-01-05 16:55 UTC (permalink / raw) To: Koichiro Den Cc: jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas, Frank.Li, linux-pci, linux-kernel Hello Koichiro, On Mon, Jan 05, 2026 at 05:02:12PM +0900, Koichiro Den wrote: > This series proposes support for mapping subranges within a PCIe endpoint > BAR and enables controllers to program inbound address translation for > those subranges. > > The first patch introduces generic BAR subrange mapping support in the > PCI endpoint core. The second patch adds an implementation for the > DesignWare PCIe endpoint controller using Address Match Mode IB iATU. > > This series is a spin-off from a larger RFC series posted earlier: > https://lore.kernel.org/all/20251217151609.3162665-4-den@valinux.co.jp/ > > Base: > git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git > branch: controller/dwc > commit: 68ac85fb42cf ("PCI: dwc: Use cfg0_base as iMSI-RX target address > to support 32-bit MSI devices") > > Thank you for reviewing, > > Koichiro Den (2): > PCI: endpoint: Add BAR subrange mapping support > PCI: dwc: ep: Support BAR subrange inbound mapping via address-match > iATU I have nothing against this feature, but the big question here is: where is the user? Usually, we don't add a new feature without having a single user of said feature. One thing that I would like to see though: stricter verification of the pci_epf_bar_submap array. For DWC, we know that the minimum size that an iATU can map is stored in: (struct dw_pcie *pci) pci->region_align. Thus, each element in the pci_epf_bar_submap array has to have a size that is a multiple of pci->region_align. I don't see that you ever verify this anywhere. You should also verify that the sum of all the sizes in the pci_epf_bar_submap array adds up to exactly pci_epf_bar->size. Also, we currently have code in dw_pcie_prog_inbound_atu() that verifies that the physical memory address is aligned to the size of the BAR, as that is a requirement in BAR match mode, see: 129f6af747b2 ("PCI: dwc: ep: Add 'address' alignment to 'size' check in dw_pcie_prog_ep_inbound_atu()") This is not a requirement in address match mode, so you probably don't want to do that check in address match mode. (You will want to keep the check that the physical memory address is aligned to pci->region_align though.) Kind regards, Niklas ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/2] PCI: endpoint: BAR subrange mapping support 2026-01-05 16:55 ` [PATCH 0/2] PCI: endpoint: BAR subrange mapping support Niklas Cassel @ 2026-01-06 1:52 ` Koichiro Den 2026-01-06 3:09 ` Koichiro Den 2026-01-06 9:30 ` Niklas Cassel 0 siblings, 2 replies; 10+ messages in thread From: Koichiro Den @ 2026-01-06 1:52 UTC (permalink / raw) To: Niklas Cassel Cc: jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas, Frank.Li, linux-pci, linux-kernel On Mon, Jan 05, 2026 at 05:55:30PM +0100, Niklas Cassel wrote: > Hello Koichiro, > > On Mon, Jan 05, 2026 at 05:02:12PM +0900, Koichiro Den wrote: > > This series proposes support for mapping subranges within a PCIe endpoint > > BAR and enables controllers to program inbound address translation for > > those subranges. > > > > The first patch introduces generic BAR subrange mapping support in the > > PCI endpoint core. The second patch adds an implementation for the > > DesignWare PCIe endpoint controller using Address Match Mode IB iATU. > > > > This series is a spin-off from a larger RFC series posted earlier: > > https://lore.kernel.org/all/20251217151609.3162665-4-den@valinux.co.jp/ > > > > Base: > > git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git > > branch: controller/dwc > > commit: 68ac85fb42cf ("PCI: dwc: Use cfg0_base as iMSI-RX target address > > to support 32-bit MSI devices") > > > > Thank you for reviewing, > > > > Koichiro Den (2): > > PCI: endpoint: Add BAR subrange mapping support > > PCI: dwc: ep: Support BAR subrange inbound mapping via address-match > > iATU > > I have nothing against this feature, but the big question here is: > where is the user? > > Usually, we don't add a new feature without having a single user of said > feature. > The first user will likely be Remote eDMA-backed NTB transport. An RFC series, https://lore.kernel.org/all/20251217151609.3162665-4-den@valinux.co.jp/ referenced in the cover letter relies on Address Match Mode support. In that sense, this split series is prerequisite work, and if this gets acked, I will post another patch series that utilizes this in the NTB code. At least for Renesas R-Car S4, where 64-bit BAR0/BAR2 and 32-bit BAR4 are available, exposing the eDMA regsister and LL regions to the host requires at least two mappings (one for register and another for a contiguous LL memory). Address Match Mode allows a flexible and extensible layout for the required regions. > > One thing that I would like to see though: > stricter verification of the pci_epf_bar_submap array. > > For DWC, we know that the minimum size that an iATU can map is stored in: > (struct dw_pcie *pci) pci->region_align. > > Thus, each element in the pci_epf_bar_submap array has to have a size that > is a multiple of pci->region_align. > > I don't see that you ever verify this anywhere. I missed it, will add the check. > > You should also verify that the sum of all the sizes in the pci_epf_bar_submap > array adds up to exactly pci_epf_bar->size. I didn't think this was a requirement. I experimented with it just now, and seems to me that no harm is caused even if the sum of the submap sizes is less than the BAR size. Could you point me to any description of this requirement in the databook if available? > > Also, we currently have code in dw_pcie_prog_inbound_atu() that verifies > that the physical memory address is aligned to the size of the BAR, as that > is a requirement in BAR match mode, see: > 129f6af747b2 ("PCI: dwc: ep: Add 'address' alignment to 'size' check in dw_pcie_prog_ep_inbound_atu()") > > This is not a requirement in address match mode, so you probably don't > want to do that check in address match mode. > (You will want to keep the check that the physical memory address is > aligned to pci->region_align though.) With this series, the call graph would change as follows: -> dw_pcie_ep_set_bar() # For BAR Match Mode: -> dw_pcie_ep_ib_atu_bar() -> dw_pcie_prog_ep_inbound_atu() # For Address Match Mode: -> dw_pcie_ep_ib_atu_addr() -> dw_pcie_prog_inbound_atu() and the size check that was introduced in the commit 129f6af747b2 should not run for Address Match Mode in any case. Thank you for the review! Koichiro > > > Kind regards, > Niklas ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/2] PCI: endpoint: BAR subrange mapping support 2026-01-06 1:52 ` Koichiro Den @ 2026-01-06 3:09 ` Koichiro Den 2026-01-06 9:16 ` Niklas Cassel 2026-01-06 9:30 ` Niklas Cassel 1 sibling, 1 reply; 10+ messages in thread From: Koichiro Den @ 2026-01-06 3:09 UTC (permalink / raw) To: Niklas Cassel Cc: jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas, Frank.Li, linux-pci, linux-kernel On Tue, Jan 06, 2026 at 10:52:54AM +0900, Koichiro Den wrote: > On Mon, Jan 05, 2026 at 05:55:30PM +0100, Niklas Cassel wrote: > > Hello Koichiro, > > > > On Mon, Jan 05, 2026 at 05:02:12PM +0900, Koichiro Den wrote: > > > This series proposes support for mapping subranges within a PCIe endpoint > > > BAR and enables controllers to program inbound address translation for > > > those subranges. > > > > > > The first patch introduces generic BAR subrange mapping support in the > > > PCI endpoint core. The second patch adds an implementation for the > > > DesignWare PCIe endpoint controller using Address Match Mode IB iATU. > > > > > > This series is a spin-off from a larger RFC series posted earlier: > > > https://lore.kernel.org/all/20251217151609.3162665-4-den@valinux.co.jp/ > > > > > > Base: > > > git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git > > > branch: controller/dwc > > > commit: 68ac85fb42cf ("PCI: dwc: Use cfg0_base as iMSI-RX target address > > > to support 32-bit MSI devices") > > > > > > Thank you for reviewing, > > > > > > Koichiro Den (2): > > > PCI: endpoint: Add BAR subrange mapping support > > > PCI: dwc: ep: Support BAR subrange inbound mapping via address-match > > > iATU > > > > I have nothing against this feature, but the big question here is: > > where is the user? > > > > Usually, we don't add a new feature without having a single user of said > > feature. > > > > The first user will likely be Remote eDMA-backed NTB transport. An RFC > series, > https://lore.kernel.org/all/20251217151609.3162665-4-den@valinux.co.jp/ > referenced in the cover letter relies on Address Match Mode support. > In that sense, this split series is prerequisite work, and if this gets > acked, I will post another patch series that utilizes this in the NTB code. > > At least for Renesas R-Car S4, where 64-bit BAR0/BAR2 and 32-bit BAR4 are > available, exposing the eDMA regsister and LL regions to the host requires > at least two mappings (one for register and another for a contiguous LL > memory). Address Match Mode allows a flexible and extensible layout for the > required regions. > > > > > One thing that I would like to see though: > > stricter verification of the pci_epf_bar_submap array. > > > > For DWC, we know that the minimum size that an iATU can map is stored in: > > (struct dw_pcie *pci) pci->region_align. > > > > Thus, each element in the pci_epf_bar_submap array has to have a size that > > is a multiple of pci->region_align. > > > > I don't see that you ever verify this anywhere. > > I missed it, will add the check. My reply above was wrong, the region_align-related validation is already handled in dw_pcie_prog_inbound_atu(). I don't think we need to duplicate the same check at (A) (see below) in dw_pcie_ep_ib_atu_addr(), and would prefer to keep the code simple as possible since this is not a fast path. (The below is the code with this series applied) /* Address match mode */ static int dw_pcie_ep_ib_atu_addr(struct dw_pcie_ep *ep, u8 func_no, int type, struct pci_epf_bar *epf_bar) { [...] for (i = 0; i < epf_bar->num_submap; i++) { off = submap[i].offset; size = submap[i].size; parent_bus_addr = submap[i].phys_addr; if (!size) continue; # (A) [...] ret = dw_pcie_prog_inbound_atu(pci, free_win, type, parent_bus_addr, pci_addr, size); # (B) if (ret) { spin_lock_irqsave(&ep->ib_map_lock, flags); list_del(&new->list); clear_bit(free_win, ep->ib_window_map); spin_unlock_irqrestore(&ep->ib_map_lock, flags); devm_kfree(dev, new); return ret; Kind regards, Koichiro > > > > > You should also verify that the sum of all the sizes in the pci_epf_bar_submap > > array adds up to exactly pci_epf_bar->size. > > I didn't think this was a requirement. I experimented with it just now, and > seems to me that no harm is caused even if the sum of the submap sizes is > less than the BAR size. Could you point me to any description of this > requirement in the databook if available? > > > > > Also, we currently have code in dw_pcie_prog_inbound_atu() that verifies > > that the physical memory address is aligned to the size of the BAR, as that > > is a requirement in BAR match mode, see: > > 129f6af747b2 ("PCI: dwc: ep: Add 'address' alignment to 'size' check in dw_pcie_prog_ep_inbound_atu()") > > > > This is not a requirement in address match mode, so you probably don't > > want to do that check in address match mode. > > (You will want to keep the check that the physical memory address is > > aligned to pci->region_align though.) > > With this series, the call graph would change as follows: > > -> dw_pcie_ep_set_bar() > # For BAR Match Mode: > -> dw_pcie_ep_ib_atu_bar() > -> dw_pcie_prog_ep_inbound_atu() > # For Address Match Mode: > -> dw_pcie_ep_ib_atu_addr() > -> dw_pcie_prog_inbound_atu() > > and the size check that was introduced in the commit 129f6af747b2 should > not run for Address Match Mode in any case. > > Thank you for the review! > Koichiro > > > > > > > Kind regards, > > Niklas ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/2] PCI: endpoint: BAR subrange mapping support 2026-01-06 3:09 ` Koichiro Den @ 2026-01-06 9:16 ` Niklas Cassel 2026-01-06 12:39 ` Koichiro Den 0 siblings, 1 reply; 10+ messages in thread From: Niklas Cassel @ 2026-01-06 9:16 UTC (permalink / raw) To: Koichiro Den Cc: jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas, Frank.Li, linux-pci, linux-kernel On Tue, Jan 06, 2026 at 12:09:24PM +0900, Koichiro Den wrote: > On Tue, Jan 06, 2026 at 10:52:54AM +0900, Koichiro Den wrote: > > On Mon, Jan 05, 2026 at 05:55:30PM +0100, Niklas Cassel wrote: > > > Hello Koichiro, > > > > > > On Mon, Jan 05, 2026 at 05:02:12PM +0900, Koichiro Den wrote: > > > > This series proposes support for mapping subranges within a PCIe endpoint > > > > BAR and enables controllers to program inbound address translation for > > > > those subranges. > > > > > > > > The first patch introduces generic BAR subrange mapping support in the > > > > PCI endpoint core. The second patch adds an implementation for the > > > > DesignWare PCIe endpoint controller using Address Match Mode IB iATU. > > > > > > > > This series is a spin-off from a larger RFC series posted earlier: > > > > https://lore.kernel.org/all/20251217151609.3162665-4-den@valinux.co.jp/ > > > > > > > > Base: > > > > git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git > > > > branch: controller/dwc > > > > commit: 68ac85fb42cf ("PCI: dwc: Use cfg0_base as iMSI-RX target address > > > > to support 32-bit MSI devices") > > > > > > > > Thank you for reviewing, > > > > > > > > Koichiro Den (2): > > > > PCI: endpoint: Add BAR subrange mapping support > > > > PCI: dwc: ep: Support BAR subrange inbound mapping via address-match > > > > iATU > > > > > > I have nothing against this feature, but the big question here is: > > > where is the user? > > > > > > Usually, we don't add a new feature without having a single user of said > > > feature. > > > > > > > The first user will likely be Remote eDMA-backed NTB transport. An RFC > > series, > > https://lore.kernel.org/all/20251217151609.3162665-4-den@valinux.co.jp/ > > referenced in the cover letter relies on Address Match Mode support. > > In that sense, this split series is prerequisite work, and if this gets > > acked, I will post another patch series that utilizes this in the NTB code. > > > > At least for Renesas R-Car S4, where 64-bit BAR0/BAR2 and 32-bit BAR4 are > > available, exposing the eDMA regsister and LL regions to the host requires > > at least two mappings (one for register and another for a contiguous LL > > memory). Address Match Mode allows a flexible and extensible layout for the > > required regions. > > > > > > > > One thing that I would like to see though: > > > stricter verification of the pci_epf_bar_submap array. > > > > > > For DWC, we know that the minimum size that an iATU can map is stored in: > > > (struct dw_pcie *pci) pci->region_align. > > > > > > Thus, each element in the pci_epf_bar_submap array has to have a size that > > > is a multiple of pci->region_align. > > > > > > I don't see that you ever verify this anywhere. > > > > I missed it, will add the check. > > My reply above was wrong, the region_align-related validation is already > handled in dw_pcie_prog_inbound_atu(). I don't think we need to duplicate > the same check at (A) (see below) in dw_pcie_ep_ib_atu_addr(), and would > prefer to keep the code simple as possible since this is not a fast path. The region align check in dw_pcie_prog_inbound_atu() validates that the addresses (pci_addr and parent_bus_addr) are aligned to region_align (min iATU size). You also need to check that the size of the region mapped is aligned to region_align (min iATU size). Kind regards, Niklas ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/2] PCI: endpoint: BAR subrange mapping support 2026-01-06 9:16 ` Niklas Cassel @ 2026-01-06 12:39 ` Koichiro Den 0 siblings, 0 replies; 10+ messages in thread From: Koichiro Den @ 2026-01-06 12:39 UTC (permalink / raw) To: Niklas Cassel Cc: jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas, Frank.Li, linux-pci, linux-kernel On Tue, Jan 06, 2026 at 10:16:15AM +0100, Niklas Cassel wrote: > On Tue, Jan 06, 2026 at 12:09:24PM +0900, Koichiro Den wrote: > > On Tue, Jan 06, 2026 at 10:52:54AM +0900, Koichiro Den wrote: > > > On Mon, Jan 05, 2026 at 05:55:30PM +0100, Niklas Cassel wrote: > > > > Hello Koichiro, > > > > > > > > On Mon, Jan 05, 2026 at 05:02:12PM +0900, Koichiro Den wrote: > > > > > This series proposes support for mapping subranges within a PCIe endpoint > > > > > BAR and enables controllers to program inbound address translation for > > > > > those subranges. > > > > > > > > > > The first patch introduces generic BAR subrange mapping support in the > > > > > PCI endpoint core. The second patch adds an implementation for the > > > > > DesignWare PCIe endpoint controller using Address Match Mode IB iATU. > > > > > > > > > > This series is a spin-off from a larger RFC series posted earlier: > > > > > https://lore.kernel.org/all/20251217151609.3162665-4-den@valinux.co.jp/ > > > > > > > > > > Base: > > > > > git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git > > > > > branch: controller/dwc > > > > > commit: 68ac85fb42cf ("PCI: dwc: Use cfg0_base as iMSI-RX target address > > > > > to support 32-bit MSI devices") > > > > > > > > > > Thank you for reviewing, > > > > > > > > > > Koichiro Den (2): > > > > > PCI: endpoint: Add BAR subrange mapping support > > > > > PCI: dwc: ep: Support BAR subrange inbound mapping via address-match > > > > > iATU > > > > > > > > I have nothing against this feature, but the big question here is: > > > > where is the user? > > > > > > > > Usually, we don't add a new feature without having a single user of said > > > > feature. > > > > > > > > > > The first user will likely be Remote eDMA-backed NTB transport. An RFC > > > series, > > > https://lore.kernel.org/all/20251217151609.3162665-4-den@valinux.co.jp/ > > > referenced in the cover letter relies on Address Match Mode support. > > > In that sense, this split series is prerequisite work, and if this gets > > > acked, I will post another patch series that utilizes this in the NTB code. > > > > > > At least for Renesas R-Car S4, where 64-bit BAR0/BAR2 and 32-bit BAR4 are > > > available, exposing the eDMA regsister and LL regions to the host requires > > > at least two mappings (one for register and another for a contiguous LL > > > memory). Address Match Mode allows a flexible and extensible layout for the > > > required regions. > > > > > > > > > > > One thing that I would like to see though: > > > > stricter verification of the pci_epf_bar_submap array. > > > > > > > > For DWC, we know that the minimum size that an iATU can map is stored in: > > > > (struct dw_pcie *pci) pci->region_align. > > > > > > > > Thus, each element in the pci_epf_bar_submap array has to have a size that > > > > is a multiple of pci->region_align. > > > > > > > > I don't see that you ever verify this anywhere. > > > > > > I missed it, will add the check. > > > > My reply above was wrong, the region_align-related validation is already > > handled in dw_pcie_prog_inbound_atu(). I don't think we need to duplicate > > the same check at (A) (see below) in dw_pcie_ep_ib_atu_addr(), and would > > prefer to keep the code simple as possible since this is not a fast path. > > The region align check in dw_pcie_prog_inbound_atu() validates that the > addresses (pci_addr and parent_bus_addr) are aligned to region_align > (min iATU size). > > You also need to check that the size of the region mapped is aligned to > region_align (min iATU size). You're right, thanks for pointing that out. Koichiro > > > Kind regards, > Niklas ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/2] PCI: endpoint: BAR subrange mapping support 2026-01-06 1:52 ` Koichiro Den 2026-01-06 3:09 ` Koichiro Den @ 2026-01-06 9:30 ` Niklas Cassel 2026-01-06 12:32 ` Koichiro Den 1 sibling, 1 reply; 10+ messages in thread From: Niklas Cassel @ 2026-01-06 9:30 UTC (permalink / raw) To: Koichiro Den Cc: jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas, Frank.Li, linux-pci, linux-kernel On Tue, Jan 06, 2026 at 10:52:54AM +0900, Koichiro Den wrote: > On Mon, Jan 05, 2026 at 05:55:30PM +0100, Niklas Cassel wrote: > > > > You should also verify that the sum of all the sizes in the pci_epf_bar_submap > > array adds up to exactly pci_epf_bar->size. > > I didn't think this was a requirement. I experimented with it just now, and > seems to me that no harm is caused even if the sum of the submap sizes is > less than the BAR size. Could you point me to any description of this > requirement in the databook if available? 3.10.7 Inbound Features "Without address translation, your application address is passed from the TLPs directly through the application interface." Thus, when there is not an explicit translation, the DWC controller passes through a transaction untranslated. Sure, if there is no physical memory or IO registers at the physical address corresponding to the PCI address trying to be accessed, no harm done. But because of the potential security implications, I think it is good to ensure that the whole PCI address range of the BAR has a physical mapping. Kind regards, Niklas ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 0/2] PCI: endpoint: BAR subrange mapping support 2026-01-06 9:30 ` Niklas Cassel @ 2026-01-06 12:32 ` Koichiro Den 0 siblings, 0 replies; 10+ messages in thread From: Koichiro Den @ 2026-01-06 12:32 UTC (permalink / raw) To: Niklas Cassel Cc: jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas, Frank.Li, linux-pci, linux-kernel On Tue, Jan 06, 2026 at 10:30:40AM +0100, Niklas Cassel wrote: > On Tue, Jan 06, 2026 at 10:52:54AM +0900, Koichiro Den wrote: > > On Mon, Jan 05, 2026 at 05:55:30PM +0100, Niklas Cassel wrote: > > > > > > You should also verify that the sum of all the sizes in the pci_epf_bar_submap > > > array adds up to exactly pci_epf_bar->size. > > > > I didn't think this was a requirement. I experimented with it just now, and > > seems to me that no harm is caused even if the sum of the submap sizes is > > less than the BAR size. Could you point me to any description of this > > requirement in the databook if available? > > 3.10.7 Inbound Features > "Without address translation, your application address is passed from the > TLPs directly through the application interface." > > > Thus, when there is not an explicit translation, the DWC controller passes > through a transaction untranslated. I see your point now. Thanks for the clarification. > > Sure, if there is no physical memory or IO registers at the physical address > corresponding to the PCI address trying to be accessed, no harm done. > > But because of the potential security implications, I think it is good to > ensure that the whole PCI address range of the BAR has a physical mapping. That makes sense. This (v1) series implicitly allows incremental iATU programming via multiple dw_pcie_ep_set_bar() invocations with incrementally added submaps, but if we want to prohibit any holes, it seems reasonable to make the API contract stricter such that the caller must prepare all sub-range mappings up front, and a one-shot API call should either map the whole BAR or fail altogether (all-or-nothing). Kind regards, Koichiro > > > Kind regards, > Niklas ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-01-06 12:39 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-01-05 8:02 [PATCH 0/2] PCI: endpoint: BAR subrange mapping support Koichiro Den 2026-01-05 8:02 ` [PATCH 1/2] PCI: endpoint: Add " Koichiro Den 2026-01-05 8:02 ` [PATCH 2/2] PCI: dwc: ep: Support BAR subrange inbound mapping via address-match iATU Koichiro Den 2026-01-05 16:55 ` [PATCH 0/2] PCI: endpoint: BAR subrange mapping support Niklas Cassel 2026-01-06 1:52 ` Koichiro Den 2026-01-06 3:09 ` Koichiro Den 2026-01-06 9:16 ` Niklas Cassel 2026-01-06 12:39 ` Koichiro Den 2026-01-06 9:30 ` Niklas Cassel 2026-01-06 12:32 ` Koichiro Den
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox