* [PATCH v8 1/5] PCI: endpoint: Add dynamic_inbound_mapping EPC feature
2026-01-15 8:49 [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support Koichiro Den
@ 2026-01-15 8:49 ` Koichiro Den
2026-01-15 8:49 ` [PATCH v8 2/5] PCI: endpoint: Add BAR subrange mapping support Koichiro Den
` (4 subsequent siblings)
5 siblings, 0 replies; 29+ messages in thread
From: Koichiro Den @ 2026-01-15 8:49 UTC (permalink / raw)
To: jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas, cassel
Cc: vigneshr, s-vadapalli, hongxing.zhu, l.stach, shawnguo, s.hauer,
kernel, festevam, minghuan.Lian, mingkai.hu, roy.zang,
jesper.nilsson, heiko, srikanth.thokala, marek.vasut+renesas,
yoshihiro.shimoda.uh, geert+renesas, magnus.damm, christian.bruel,
mcoquelin.stm32, alexandre.torgue, thierry.reding, jonathanh,
hayashi.kunihiko, mhiramat, kishon, jirislaby, rongqianfeng,
18255117159, shawn.lin, nicolas.frattaroli, linux.amoon, vidyas,
Frank.Li, linux-omap, linux-pci, linux-arm-kernel, linux-kernel,
imx, linuxppc-dev, linux-arm-kernel, linux-rockchip,
linux-arm-msm, linux-renesas-soc, linux-stm32, linux-tegra
Introduce a new EPC feature bit (dynamic_inbound_mapping) that indicates
whether an Endpoint Controller can update the inbound address
translation for a BAR without requiring the EPF driver to clear/reset
the BAR first.
Endpoint Function drivers (e.g. vNTB) can use this information to decide
whether it really is safe to call pci_epc_set_bar() multiple times to
update inbound mappings for the BAR.
Suggested-by: Niklas Cassel <cassel@kernel.org>
Reviewed-by: Niklas Cassel <cassel@kernel.org>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
include/linux/pci-epc.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
index 4286bfdbfdfa..4c8516756c56 100644
--- a/include/linux/pci-epc.h
+++ b/include/linux/pci-epc.h
@@ -223,6 +223,10 @@ struct pci_epc_bar_desc {
/**
* struct pci_epc_features - features supported by a EPC device per function
* @linkup_notifier: indicate if the EPC device can notify EPF driver on link up
+ * @dynamic_inbound_mapping: indicate if the EPC device supports updating
+ * inbound mappings for an already configured BAR
+ * (i.e. allow calling pci_epc_set_bar() again
+ * without first calling pci_epc_clear_bar())
* @msi_capable: indicate if the endpoint function has MSI capability
* @msix_capable: indicate if the endpoint function has MSI-X capability
* @intx_capable: indicate if the endpoint can raise INTx interrupts
@@ -231,6 +235,7 @@ struct pci_epc_bar_desc {
*/
struct pci_epc_features {
unsigned int linkup_notifier : 1;
+ unsigned int dynamic_inbound_mapping : 1;
unsigned int msi_capable : 1;
unsigned int msix_capable : 1;
unsigned int intx_capable : 1;
--
2.51.0
^ permalink raw reply related [flat|nested] 29+ messages in thread* [PATCH v8 2/5] PCI: endpoint: Add BAR subrange mapping support
2026-01-15 8:49 [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support Koichiro Den
2026-01-15 8:49 ` [PATCH v8 1/5] PCI: endpoint: Add dynamic_inbound_mapping EPC feature Koichiro Den
@ 2026-01-15 8:49 ` Koichiro Den
2026-01-15 14:52 ` Frank Li
2026-01-15 8:49 ` [PATCH v8 3/5] PCI: dwc: Advertise dynamic inbound " Koichiro Den
` (3 subsequent siblings)
5 siblings, 1 reply; 29+ messages in thread
From: Koichiro Den @ 2026-01-15 8:49 UTC (permalink / raw)
To: jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas, cassel
Cc: vigneshr, s-vadapalli, hongxing.zhu, l.stach, shawnguo, s.hauer,
kernel, festevam, minghuan.Lian, mingkai.hu, roy.zang,
jesper.nilsson, heiko, srikanth.thokala, marek.vasut+renesas,
yoshihiro.shimoda.uh, geert+renesas, magnus.damm, christian.bruel,
mcoquelin.stm32, alexandre.torgue, thierry.reding, jonathanh,
hayashi.kunihiko, mhiramat, kishon, jirislaby, rongqianfeng,
18255117159, shawn.lin, nicolas.frattaroli, linux.amoon, vidyas,
Frank.Li, linux-omap, linux-pci, linux-arm-kernel, linux-kernel,
imx, linuxppc-dev, linux-arm-kernel, linux-rockchip,
linux-arm-msm, linux-renesas-soc, linux-stm32, linux-tegra
Extend the PCI endpoint core to support mapping subranges within a BAR.
Add an optional 'submap' field in struct pci_epf_bar so an endpoint
function driver can request inbound mappings that fully cover the BAR.
Introduce a new EPC feature bit, subrange_mapping, and reject submap
requests from pci_epc_set_bar() unless the controller advertises both
subrange_mapping and dynamic_inbound_mapping features.
The submap array describes the complete BAR layout (no overlaps and no
gaps are allowed to avoid exposing untranslated address ranges). 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.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/pci/endpoint/pci-epc-core.c | 8 ++++++++
include/linux/pci-epc.h | 4 ++++
include/linux/pci-epf.h | 27 +++++++++++++++++++++++++++
3 files changed, 39 insertions(+)
diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c
index ca7f19cc973a..068155819c57 100644
--- a/drivers/pci/endpoint/pci-epc-core.c
+++ b/drivers/pci/endpoint/pci-epc-core.c
@@ -596,6 +596,14 @@ int pci_epc_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
if (!epc_features)
return -EINVAL;
+ if (epf_bar->num_submap && !epf_bar->submap)
+ return -EINVAL;
+
+ if (epf_bar->num_submap &&
+ !(epc_features->dynamic_inbound_mapping &&
+ epc_features->subrange_mapping))
+ return -EINVAL;
+
if (epc_features->bar[bar].type == BAR_RESIZABLE &&
(epf_bar->size < SZ_1M || (u64)epf_bar->size > (SZ_128G * 1024)))
return -EINVAL;
diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
index 4c8516756c56..c021c7af175f 100644
--- a/include/linux/pci-epc.h
+++ b/include/linux/pci-epc.h
@@ -227,6 +227,9 @@ struct pci_epc_bar_desc {
* inbound mappings for an already configured BAR
* (i.e. allow calling pci_epc_set_bar() again
* without first calling pci_epc_clear_bar())
+ * @subrange_mapping: indicate if the EPC device can map inbound subranges for a
+ * BAR. This feature depends on @dynamic_inbound_mapping
+ * feature.
* @msi_capable: indicate if the endpoint function has MSI capability
* @msix_capable: indicate if the endpoint function has MSI-X capability
* @intx_capable: indicate if the endpoint can raise INTx interrupts
@@ -236,6 +239,7 @@ struct pci_epc_bar_desc {
struct pci_epc_features {
unsigned int linkup_notifier : 1;
unsigned int dynamic_inbound_mapping : 1;
+ unsigned int subrange_mapping : 1;
unsigned int msi_capable : 1;
unsigned int msix_capable : 1;
unsigned int intx_capable : 1;
diff --git a/include/linux/pci-epf.h b/include/linux/pci-epf.h
index 48f68c4dcfa5..46f817da6e24 100644
--- a/include/linux/pci-epf.h
+++ b/include/linux/pci-epf.h
@@ -110,6 +110,26 @@ struct pci_epf_driver {
#define to_pci_epf_driver(drv) container_of_const((drv), struct pci_epf_driver, driver)
+/**
+ * struct pci_epf_bar_submap - BAR subrange for inbound mapping
+ * @phys_addr: target physical/DMA address for this subrange
+ * @size: the size of the subrange to be mapped
+ *
+ * When pci_epf_bar.num_submap is >0, pci_epf_bar.submap describes the
+ * complete BAR layout. This allows an EPC driver to program multiple
+ * inbound translation windows for a single BAR when supported by the
+ * controller. The array order defines the BAR layout (submap[0] at offset
+ * 0, and each immediately follows the previous one).
+ *
+ * Note that the subranges:
+ * - must be non-overlapping
+ * - must exactly cover the BAR (i.e. no holes)
+ */
+struct pci_epf_bar_submap {
+ dma_addr_t phys_addr;
+ size_t size;
+};
+
/**
* struct pci_epf_bar - represents the BAR of EPF device
* @phys_addr: physical address that should be mapped to the BAR
@@ -119,6 +139,9 @@ struct pci_epf_driver {
* requirement
* @barno: BAR number
* @flags: flags that are set for the BAR
+ * @num_submap: number of entries in @submap
+ * @submap: array of subrange descriptors allocated by the caller. See
+ * struct pci_epf_bar_submap for the restrictions in detail.
*/
struct pci_epf_bar {
dma_addr_t phys_addr;
@@ -127,6 +150,10 @@ struct pci_epf_bar {
size_t mem_size;
enum pci_barno barno;
int flags;
+
+ /* Optional sub-range mapping */
+ unsigned int num_submap;
+ struct pci_epf_bar_submap *submap;
};
/**
--
2.51.0
^ permalink raw reply related [flat|nested] 29+ messages in thread* Re: [PATCH v8 2/5] PCI: endpoint: Add BAR subrange mapping support
2026-01-15 8:49 ` [PATCH v8 2/5] PCI: endpoint: Add BAR subrange mapping support Koichiro Den
@ 2026-01-15 14:52 ` Frank Li
2026-01-15 15:21 ` Niklas Cassel
2026-01-19 8:42 ` Koichiro Den
0 siblings, 2 replies; 29+ messages in thread
From: Frank Li @ 2026-01-15 14:52 UTC (permalink / raw)
To: Koichiro Den
Cc: jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas, cassel,
vigneshr, s-vadapalli, hongxing.zhu, l.stach, shawnguo, s.hauer,
kernel, festevam, minghuan.Lian, mingkai.hu, roy.zang,
jesper.nilsson, heiko, srikanth.thokala, marek.vasut+renesas,
yoshihiro.shimoda.uh, geert+renesas, magnus.damm, christian.bruel,
mcoquelin.stm32, alexandre.torgue, thierry.reding, jonathanh,
hayashi.kunihiko, mhiramat, kishon, jirislaby, rongqianfeng,
18255117159, shawn.lin, nicolas.frattaroli, linux.amoon, vidyas,
linux-omap, linux-pci, linux-arm-kernel, linux-kernel, imx,
linuxppc-dev, linux-arm-kernel, linux-rockchip, linux-arm-msm,
linux-renesas-soc, linux-stm32, linux-tegra
On Thu, Jan 15, 2026 at 05:49:25PM +0900, Koichiro Den wrote:
> Extend the PCI endpoint core to support mapping subranges within a BAR.
> Add an optional 'submap' field in struct pci_epf_bar so an endpoint
> function driver can request inbound mappings that fully cover the BAR.
>
> Introduce a new EPC feature bit, subrange_mapping, and reject submap
> requests from pci_epc_set_bar() unless the controller advertises both
> subrange_mapping and dynamic_inbound_mapping features.
>
> The submap array describes the complete BAR layout (no overlaps and no
> gaps are allowed to avoid exposing untranslated address ranges). 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.
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
> drivers/pci/endpoint/pci-epc-core.c | 8 ++++++++
> include/linux/pci-epc.h | 4 ++++
> include/linux/pci-epf.h | 27 +++++++++++++++++++++++++++
> 3 files changed, 39 insertions(+)
>
> diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c
> index ca7f19cc973a..068155819c57 100644
> --- a/drivers/pci/endpoint/pci-epc-core.c
> +++ b/drivers/pci/endpoint/pci-epc-core.c
> @@ -596,6 +596,14 @@ int pci_epc_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
> if (!epc_features)
> return -EINVAL;
>
> + if (epf_bar->num_submap && !epf_bar->submap)
> + return -EINVAL;
> +
> + if (epf_bar->num_submap &&
> + !(epc_features->dynamic_inbound_mapping &&
> + epc_features->subrange_mapping))
> + return -EINVAL;
> +
> if (epc_features->bar[bar].type == BAR_RESIZABLE &&
> (epf_bar->size < SZ_1M || (u64)epf_bar->size > (SZ_128G * 1024)))
> return -EINVAL;
> diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
> index 4c8516756c56..c021c7af175f 100644
> --- a/include/linux/pci-epc.h
> +++ b/include/linux/pci-epc.h
> @@ -227,6 +227,9 @@ struct pci_epc_bar_desc {
> * inbound mappings for an already configured BAR
> * (i.e. allow calling pci_epc_set_bar() again
> * without first calling pci_epc_clear_bar())
> + * @subrange_mapping: indicate if the EPC device can map inbound subranges for a
> + * BAR. This feature depends on @dynamic_inbound_mapping
> + * feature.
> * @msi_capable: indicate if the endpoint function has MSI capability
> * @msix_capable: indicate if the endpoint function has MSI-X capability
> * @intx_capable: indicate if the endpoint can raise INTx interrupts
> @@ -236,6 +239,7 @@ struct pci_epc_bar_desc {
> struct pci_epc_features {
> unsigned int linkup_notifier : 1;
> unsigned int dynamic_inbound_mapping : 1;
> + unsigned int subrange_mapping : 1;
> unsigned int msi_capable : 1;
> unsigned int msix_capable : 1;
> unsigned int intx_capable : 1;
> diff --git a/include/linux/pci-epf.h b/include/linux/pci-epf.h
> index 48f68c4dcfa5..46f817da6e24 100644
> --- a/include/linux/pci-epf.h
> +++ b/include/linux/pci-epf.h
> @@ -110,6 +110,26 @@ struct pci_epf_driver {
>
> #define to_pci_epf_driver(drv) container_of_const((drv), struct pci_epf_driver, driver)
>
> +/**
> + * struct pci_epf_bar_submap - BAR subrange for inbound mapping
> + * @phys_addr: target physical/DMA address for this subrange
> + * @size: the size of the subrange to be mapped
> + *
> + * When pci_epf_bar.num_submap is >0, pci_epf_bar.submap describes the
> + * complete BAR layout. This allows an EPC driver to program multiple
> + * inbound translation windows for a single BAR when supported by the
> + * controller. The array order defines the BAR layout (submap[0] at offset
> + * 0, and each immediately follows the previous one).
> + *
> + * Note that the subranges:
> + * - must be non-overlapping
> + * - must exactly cover the BAR (i.e. no holes)
It is impossible after use 'size'. It can be removed.
> + */
> +struct pci_epf_bar_submap {
> + dma_addr_t phys_addr;
> + size_t size;
> +};
> +
> /**
> * struct pci_epf_bar - represents the BAR of EPF device
> * @phys_addr: physical address that should be mapped to the BAR
> @@ -119,6 +139,9 @@ struct pci_epf_driver {
> * requirement
> * @barno: BAR number
> * @flags: flags that are set for the BAR
> + * @num_submap: number of entries in @submap
> + * @submap: array of subrange descriptors allocated by the caller. See
> + * struct pci_epf_bar_submap for the restrictions in detail.
> */
> struct pci_epf_bar {
> dma_addr_t phys_addr;
> @@ -127,6 +150,10 @@ struct pci_epf_bar {
> size_t mem_size;
> enum pci_barno barno;
> int flags;
> +
> + /* Optional sub-range mapping */
> + unsigned int num_submap;
> + struct pci_epf_bar_submap *submap;
struct pci_epf_bar_submap submap[] __counted_by(num_submap);
Not sure if use this simplify alloc/free.
Frank
> };
>
> /**
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 29+ messages in thread* Re: [PATCH v8 2/5] PCI: endpoint: Add BAR subrange mapping support
2026-01-15 14:52 ` Frank Li
@ 2026-01-15 15:21 ` Niklas Cassel
2026-01-15 19:44 ` Frank Li
2026-01-19 8:42 ` Koichiro Den
1 sibling, 1 reply; 29+ messages in thread
From: Niklas Cassel @ 2026-01-15 15:21 UTC (permalink / raw)
To: Frank Li
Cc: Koichiro Den, jingoohan1, mani, lpieralisi, kwilczynski, robh,
bhelgaas, vigneshr, s-vadapalli, hongxing.zhu, l.stach, shawnguo,
s.hauer, kernel, festevam, minghuan.Lian, mingkai.hu, roy.zang,
jesper.nilsson, heiko, srikanth.thokala, marek.vasut+renesas,
yoshihiro.shimoda.uh, geert+renesas, magnus.damm, christian.bruel,
mcoquelin.stm32, alexandre.torgue, thierry.reding, jonathanh,
hayashi.kunihiko, mhiramat, kishon, jirislaby, rongqianfeng,
18255117159, shawn.lin, nicolas.frattaroli, linux.amoon, vidyas,
linux-omap, linux-pci, linux-arm-kernel, linux-kernel, imx,
linuxppc-dev, linux-arm-kernel, linux-rockchip, linux-arm-msm,
linux-renesas-soc, linux-stm32, linux-tegra
On Thu, Jan 15, 2026 at 09:52:58AM -0500, Frank Li wrote:
> > @@ -127,6 +150,10 @@ struct pci_epf_bar {
> > size_t mem_size;
> > enum pci_barno barno;
> > int flags;
> > +
> > + /* Optional sub-range mapping */
> > + unsigned int num_submap;
> > + struct pci_epf_bar_submap *submap;
>
> struct pci_epf_bar_submap submap[] __counted_by(num_submap);
>
> Not sure if use this simplify alloc/free.
Your suggestion changes the submap from a pointer to a flexible array
member.
A flexible array member must always be last in the struct,
and you can only have one flexible array member per struct.
Additionally, using a flexible array member requires the struct to
always be allocated on the heap. You can't allocate a struct with a
flexible array member on the stack.
So I'm not sure that if your suggestion is something we want.
Kind regards,
Niklas
^ permalink raw reply [flat|nested] 29+ messages in thread* Re: [PATCH v8 2/5] PCI: endpoint: Add BAR subrange mapping support
2026-01-15 15:21 ` Niklas Cassel
@ 2026-01-15 19:44 ` Frank Li
0 siblings, 0 replies; 29+ messages in thread
From: Frank Li @ 2026-01-15 19:44 UTC (permalink / raw)
To: Niklas Cassel
Cc: Koichiro Den, jingoohan1, mani, lpieralisi, kwilczynski, robh,
bhelgaas, vigneshr, s-vadapalli, hongxing.zhu, l.stach, shawnguo,
s.hauer, kernel, festevam, minghuan.Lian, mingkai.hu, roy.zang,
jesper.nilsson, heiko, srikanth.thokala, marek.vasut+renesas,
yoshihiro.shimoda.uh, geert+renesas, magnus.damm, christian.bruel,
mcoquelin.stm32, alexandre.torgue, thierry.reding, jonathanh,
hayashi.kunihiko, mhiramat, kishon, jirislaby, rongqianfeng,
18255117159, shawn.lin, nicolas.frattaroli, linux.amoon, vidyas,
linux-omap, linux-pci, linux-arm-kernel, linux-kernel, imx,
linuxppc-dev, linux-arm-kernel, linux-rockchip, linux-arm-msm,
linux-renesas-soc, linux-stm32, linux-tegra
On Thu, Jan 15, 2026 at 04:21:21PM +0100, Niklas Cassel wrote:
> On Thu, Jan 15, 2026 at 09:52:58AM -0500, Frank Li wrote:
> > > @@ -127,6 +150,10 @@ struct pci_epf_bar {
> > > size_t mem_size;
> > > enum pci_barno barno;
> > > int flags;
> > > +
> > > + /* Optional sub-range mapping */
> > > + unsigned int num_submap;
> > > + struct pci_epf_bar_submap *submap;
> >
> > struct pci_epf_bar_submap submap[] __counted_by(num_submap);
> >
> > Not sure if use this simplify alloc/free.
>
> Your suggestion changes the submap from a pointer to a flexible array
> member.
>
> A flexible array member must always be last in the struct,
> and you can only have one flexible array member per struct.
>
> Additionally, using a flexible array member requires the struct to
> always be allocated on the heap. You can't allocate a struct with a
> flexible array member on the stack.
>
> So I'm not sure that if your suggestion is something we want.
Yes, forget my comments if not fit.
Frank
>
>
> Kind regards,
> Niklas
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v8 2/5] PCI: endpoint: Add BAR subrange mapping support
2026-01-15 14:52 ` Frank Li
2026-01-15 15:21 ` Niklas Cassel
@ 2026-01-19 8:42 ` Koichiro Den
1 sibling, 0 replies; 29+ messages in thread
From: Koichiro Den @ 2026-01-19 8:42 UTC (permalink / raw)
To: Frank Li
Cc: jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas, cassel,
vigneshr, s-vadapalli, hongxing.zhu, l.stach, shawnguo, s.hauer,
kernel, festevam, minghuan.Lian, mingkai.hu, roy.zang,
jesper.nilsson, heiko, srikanth.thokala, marek.vasut+renesas,
yoshihiro.shimoda.uh, geert+renesas, magnus.damm, christian.bruel,
mcoquelin.stm32, alexandre.torgue, thierry.reding, jonathanh,
hayashi.kunihiko, mhiramat, kishon, jirislaby, rongqianfeng,
18255117159, shawn.lin, nicolas.frattaroli, linux.amoon, vidyas,
linux-omap, linux-pci, linux-arm-kernel, linux-kernel, imx,
linuxppc-dev, linux-arm-kernel, linux-rockchip, linux-arm-msm,
linux-renesas-soc, linux-stm32, linux-tegra
On Thu, Jan 15, 2026 at 09:52:58AM -0500, Frank Li wrote:
> On Thu, Jan 15, 2026 at 05:49:25PM +0900, Koichiro Den wrote:
> > Extend the PCI endpoint core to support mapping subranges within a BAR.
> > Add an optional 'submap' field in struct pci_epf_bar so an endpoint
> > function driver can request inbound mappings that fully cover the BAR.
> >
> > Introduce a new EPC feature bit, subrange_mapping, and reject submap
> > requests from pci_epc_set_bar() unless the controller advertises both
> > subrange_mapping and dynamic_inbound_mapping features.
> >
> > The submap array describes the complete BAR layout (no overlaps and no
> > gaps are allowed to avoid exposing untranslated address ranges). 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.
> >
> > Signed-off-by: Koichiro Den <den@valinux.co.jp>
> > ---
> > drivers/pci/endpoint/pci-epc-core.c | 8 ++++++++
> > include/linux/pci-epc.h | 4 ++++
> > include/linux/pci-epf.h | 27 +++++++++++++++++++++++++++
> > 3 files changed, 39 insertions(+)
> >
> > diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c
> > index ca7f19cc973a..068155819c57 100644
> > --- a/drivers/pci/endpoint/pci-epc-core.c
> > +++ b/drivers/pci/endpoint/pci-epc-core.c
> > @@ -596,6 +596,14 @@ int pci_epc_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
> > if (!epc_features)
> > return -EINVAL;
> >
> > + if (epf_bar->num_submap && !epf_bar->submap)
> > + return -EINVAL;
> > +
> > + if (epf_bar->num_submap &&
> > + !(epc_features->dynamic_inbound_mapping &&
> > + epc_features->subrange_mapping))
> > + return -EINVAL;
> > +
> > if (epc_features->bar[bar].type == BAR_RESIZABLE &&
> > (epf_bar->size < SZ_1M || (u64)epf_bar->size > (SZ_128G * 1024)))
> > return -EINVAL;
> > diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
> > index 4c8516756c56..c021c7af175f 100644
> > --- a/include/linux/pci-epc.h
> > +++ b/include/linux/pci-epc.h
> > @@ -227,6 +227,9 @@ struct pci_epc_bar_desc {
> > * inbound mappings for an already configured BAR
> > * (i.e. allow calling pci_epc_set_bar() again
> > * without first calling pci_epc_clear_bar())
> > + * @subrange_mapping: indicate if the EPC device can map inbound subranges for a
> > + * BAR. This feature depends on @dynamic_inbound_mapping
> > + * feature.
> > * @msi_capable: indicate if the endpoint function has MSI capability
> > * @msix_capable: indicate if the endpoint function has MSI-X capability
> > * @intx_capable: indicate if the endpoint can raise INTx interrupts
> > @@ -236,6 +239,7 @@ struct pci_epc_bar_desc {
> > struct pci_epc_features {
> > unsigned int linkup_notifier : 1;
> > unsigned int dynamic_inbound_mapping : 1;
> > + unsigned int subrange_mapping : 1;
> > unsigned int msi_capable : 1;
> > unsigned int msix_capable : 1;
> > unsigned int intx_capable : 1;
> > diff --git a/include/linux/pci-epf.h b/include/linux/pci-epf.h
> > index 48f68c4dcfa5..46f817da6e24 100644
> > --- a/include/linux/pci-epf.h
> > +++ b/include/linux/pci-epf.h
> > @@ -110,6 +110,26 @@ struct pci_epf_driver {
> >
> > #define to_pci_epf_driver(drv) container_of_const((drv), struct pci_epf_driver, driver)
> >
> > +/**
> > + * struct pci_epf_bar_submap - BAR subrange for inbound mapping
> > + * @phys_addr: target physical/DMA address for this subrange
> > + * @size: the size of the subrange to be mapped
> > + *
> > + * When pci_epf_bar.num_submap is >0, pci_epf_bar.submap describes the
> > + * complete BAR layout. This allows an EPC driver to program multiple
> > + * inbound translation windows for a single BAR when supported by the
> > + * controller. The array order defines the BAR layout (submap[0] at offset
> > + * 0, and each immediately follows the previous one).
> > + *
> > + * Note that the subranges:
> > + * - must be non-overlapping
> > + * - must exactly cover the BAR (i.e. no holes)
>
> It is impossible after use 'size'. It can be removed.
Agreed, those notes (ie non-overlapping/no holes) are redundant now.
Thanks for pointing it out. I'll drop them.
Koichiro
>
> > + */
> > +struct pci_epf_bar_submap {
> > + dma_addr_t phys_addr;
> > + size_t size;
> > +};
> > +
> > /**
> > * struct pci_epf_bar - represents the BAR of EPF device
> > * @phys_addr: physical address that should be mapped to the BAR
> > @@ -119,6 +139,9 @@ struct pci_epf_driver {
> > * requirement
> > * @barno: BAR number
> > * @flags: flags that are set for the BAR
> > + * @num_submap: number of entries in @submap
> > + * @submap: array of subrange descriptors allocated by the caller. See
> > + * struct pci_epf_bar_submap for the restrictions in detail.
> > */
> > struct pci_epf_bar {
> > dma_addr_t phys_addr;
> > @@ -127,6 +150,10 @@ struct pci_epf_bar {
> > size_t mem_size;
> > enum pci_barno barno;
> > int flags;
> > +
> > + /* Optional sub-range mapping */
> > + unsigned int num_submap;
> > + struct pci_epf_bar_submap *submap;
>
> struct pci_epf_bar_submap submap[] __counted_by(num_submap);
>
> Not sure if use this simplify alloc/free.
>
> Frank
> > };
> >
> > /**
> > --
> > 2.51.0
> >
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v8 3/5] PCI: dwc: Advertise dynamic inbound mapping support
2026-01-15 8:49 [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support Koichiro Den
2026-01-15 8:49 ` [PATCH v8 1/5] PCI: endpoint: Add dynamic_inbound_mapping EPC feature Koichiro Den
2026-01-15 8:49 ` [PATCH v8 2/5] PCI: endpoint: Add BAR subrange mapping support Koichiro Den
@ 2026-01-15 8:49 ` Koichiro Den
2026-01-15 14:54 ` Frank Li
2026-01-15 8:49 ` [PATCH v8 4/5] PCI: dwc: ep: Support BAR subrange inbound mapping via Address Match Mode iATU Koichiro Den
` (2 subsequent siblings)
5 siblings, 1 reply; 29+ messages in thread
From: Koichiro Den @ 2026-01-15 8:49 UTC (permalink / raw)
To: jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas, cassel
Cc: vigneshr, s-vadapalli, hongxing.zhu, l.stach, shawnguo, s.hauer,
kernel, festevam, minghuan.Lian, mingkai.hu, roy.zang,
jesper.nilsson, heiko, srikanth.thokala, marek.vasut+renesas,
yoshihiro.shimoda.uh, geert+renesas, magnus.damm, christian.bruel,
mcoquelin.stm32, alexandre.torgue, thierry.reding, jonathanh,
hayashi.kunihiko, mhiramat, kishon, jirislaby, rongqianfeng,
18255117159, shawn.lin, nicolas.frattaroli, linux.amoon, vidyas,
Frank.Li, linux-omap, linux-pci, linux-arm-kernel, linux-kernel,
imx, linuxppc-dev, linux-arm-kernel, linux-rockchip,
linux-arm-msm, linux-renesas-soc, linux-stm32, linux-tegra
The DesignWare EP core has supported updating the inbound iATU mapping
for an already configured BAR (i.e. allowing pci_epc_set_bar() to be
called again without a prior pci_epc_clear_bar()) since commit
4284c88fff0e ("PCI: designware-ep: Allow pci_epc_set_bar() update
inbound map address").
Now that this capability is exposed via the dynamic_inbound_mapping EPC
feature bit, set it for DWC-based EP glue drivers using a common
initializer macro to avoid duplicating the same flag in each driver.
Note that pci-layerscape-ep.c is untouched. It currently constructs the
feature struct dynamically in ls_pcie_ep_init(). Once converted to a
static feature definition, it will use DWC_EPC_COMMON_FEATURES as well.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/pci/controller/dwc/pci-dra7xx.c | 1 +
drivers/pci/controller/dwc/pci-imx6.c | 3 +++
drivers/pci/controller/dwc/pci-keystone.c | 1 +
drivers/pci/controller/dwc/pcie-artpec6.c | 1 +
drivers/pci/controller/dwc/pcie-designware-plat.c | 1 +
drivers/pci/controller/dwc/pcie-designware.h | 3 +++
drivers/pci/controller/dwc/pcie-dw-rockchip.c | 2 ++
drivers/pci/controller/dwc/pcie-keembay.c | 1 +
drivers/pci/controller/dwc/pcie-qcom-ep.c | 1 +
drivers/pci/controller/dwc/pcie-rcar-gen4.c | 1 +
drivers/pci/controller/dwc/pcie-stm32-ep.c | 1 +
drivers/pci/controller/dwc/pcie-tegra194.c | 1 +
drivers/pci/controller/dwc/pcie-uniphier-ep.c | 2 ++
13 files changed, 19 insertions(+)
diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c
index 01cfd9aeb0b8..d5d26229063f 100644
--- a/drivers/pci/controller/dwc/pci-dra7xx.c
+++ b/drivers/pci/controller/dwc/pci-dra7xx.c
@@ -424,6 +424,7 @@ static int dra7xx_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
}
static const struct pci_epc_features dra7xx_pcie_epc_features = {
+ DWC_EPC_COMMON_FEATURES,
.linkup_notifier = true,
.msi_capable = true,
};
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 4668fc9648bf..f28e335bbbfa 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -1387,6 +1387,7 @@ static int imx_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
}
static const struct pci_epc_features imx8m_pcie_epc_features = {
+ DWC_EPC_COMMON_FEATURES,
.msi_capable = true,
.bar[BAR_1] = { .type = BAR_RESERVED, },
.bar[BAR_3] = { .type = BAR_RESERVED, },
@@ -1396,6 +1397,7 @@ static const struct pci_epc_features imx8m_pcie_epc_features = {
};
static const struct pci_epc_features imx8q_pcie_epc_features = {
+ DWC_EPC_COMMON_FEATURES,
.msi_capable = true,
.bar[BAR_1] = { .type = BAR_RESERVED, },
.bar[BAR_3] = { .type = BAR_RESERVED, },
@@ -1416,6 +1418,7 @@ static const struct pci_epc_features imx8q_pcie_epc_features = {
* BAR5 | Enable | 32-bit | 64 KB | Programmable Size
*/
static const struct pci_epc_features imx95_pcie_epc_features = {
+ DWC_EPC_COMMON_FEATURES,
.msi_capable = true,
.bar[BAR_1] = { .type = BAR_FIXED, .fixed_size = SZ_64K, },
.align = SZ_4K,
diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index f86d9111f863..20fa4dadb82a 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -930,6 +930,7 @@ static int ks_pcie_am654_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
}
static const struct pci_epc_features ks_pcie_am654_epc_features = {
+ DWC_EPC_COMMON_FEATURES,
.msi_capable = true,
.msix_capable = true,
.bar[BAR_0] = { .type = BAR_RESERVED, },
diff --git a/drivers/pci/controller/dwc/pcie-artpec6.c b/drivers/pci/controller/dwc/pcie-artpec6.c
index f4a136ee2daf..e994b75986c3 100644
--- a/drivers/pci/controller/dwc/pcie-artpec6.c
+++ b/drivers/pci/controller/dwc/pcie-artpec6.c
@@ -370,6 +370,7 @@ static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
}
static const struct pci_epc_features artpec6_pcie_epc_features = {
+ DWC_EPC_COMMON_FEATURES,
.msi_capable = true,
};
diff --git a/drivers/pci/controller/dwc/pcie-designware-plat.c b/drivers/pci/controller/dwc/pcie-designware-plat.c
index 12f41886c65d..8530746ec5cb 100644
--- a/drivers/pci/controller/dwc/pcie-designware-plat.c
+++ b/drivers/pci/controller/dwc/pcie-designware-plat.c
@@ -61,6 +61,7 @@ static int dw_plat_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
}
static const struct pci_epc_features dw_plat_pcie_epc_features = {
+ DWC_EPC_COMMON_FEATURES,
.msi_capable = true,
.msix_capable = true,
};
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index f87c67a7a482..4df0cc44faab 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -305,6 +305,9 @@
/* Default eDMA LLP memory size */
#define DMA_LLP_MEM_SIZE PAGE_SIZE
+/* Common struct pci_epc_feature bits among DWC EP glue drivers */
+#define DWC_EPC_COMMON_FEATURES .dynamic_inbound_mapping = true
+
struct dw_pcie;
struct dw_pcie_rp;
struct dw_pcie_ep;
diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
index 352f513ebf03..f985a934a137 100644
--- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
+++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
@@ -384,6 +384,7 @@ static int rockchip_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
}
static const struct pci_epc_features rockchip_pcie_epc_features_rk3568 = {
+ DWC_EPC_COMMON_FEATURES,
.linkup_notifier = true,
.msi_capable = true,
.msix_capable = true,
@@ -404,6 +405,7 @@ static const struct pci_epc_features rockchip_pcie_epc_features_rk3568 = {
* BARs) would be overwritten, resulting in (all other BARs) no longer working.
*/
static const struct pci_epc_features rockchip_pcie_epc_features_rk3588 = {
+ DWC_EPC_COMMON_FEATURES,
.linkup_notifier = true,
.msi_capable = true,
.msix_capable = true,
diff --git a/drivers/pci/controller/dwc/pcie-keembay.c b/drivers/pci/controller/dwc/pcie-keembay.c
index 60e74ac782af..2666a9c3d67e 100644
--- a/drivers/pci/controller/dwc/pcie-keembay.c
+++ b/drivers/pci/controller/dwc/pcie-keembay.c
@@ -309,6 +309,7 @@ static int keembay_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
}
static const struct pci_epc_features keembay_pcie_epc_features = {
+ DWC_EPC_COMMON_FEATURES,
.msi_capable = true,
.msix_capable = true,
.bar[BAR_0] = { .only_64bit = true, },
diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c b/drivers/pci/controller/dwc/pcie-qcom-ep.c
index f1bc0ac81a92..5e990c7a5879 100644
--- a/drivers/pci/controller/dwc/pcie-qcom-ep.c
+++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c
@@ -820,6 +820,7 @@ static void qcom_pcie_ep_init_debugfs(struct qcom_pcie_ep *pcie_ep)
}
static const struct pci_epc_features qcom_pcie_epc_features = {
+ DWC_EPC_COMMON_FEATURES,
.linkup_notifier = true,
.msi_capable = true,
.align = SZ_4K,
diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
index 80778917d2dd..a6912e85e4dd 100644
--- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
+++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
@@ -420,6 +420,7 @@ static int rcar_gen4_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
}
static const struct pci_epc_features rcar_gen4_pcie_epc_features = {
+ DWC_EPC_COMMON_FEATURES,
.msi_capable = true,
.bar[BAR_1] = { .type = BAR_RESERVED, },
.bar[BAR_3] = { .type = BAR_RESERVED, },
diff --git a/drivers/pci/controller/dwc/pcie-stm32-ep.c b/drivers/pci/controller/dwc/pcie-stm32-ep.c
index 2cecf32d2b0f..c1944b40ce02 100644
--- a/drivers/pci/controller/dwc/pcie-stm32-ep.c
+++ b/drivers/pci/controller/dwc/pcie-stm32-ep.c
@@ -70,6 +70,7 @@ static int stm32_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
}
static const struct pci_epc_features stm32_pcie_epc_features = {
+ DWC_EPC_COMMON_FEATURES,
.msi_capable = true,
.align = SZ_64K,
};
diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
index 0ddeef70726d..06571d806ab3 100644
--- a/drivers/pci/controller/dwc/pcie-tegra194.c
+++ b/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -1988,6 +1988,7 @@ static int tegra_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
}
static const struct pci_epc_features tegra_pcie_epc_features = {
+ DWC_EPC_COMMON_FEATURES,
.linkup_notifier = true,
.msi_capable = true,
.bar[BAR_0] = { .type = BAR_FIXED, .fixed_size = SZ_1M,
diff --git a/drivers/pci/controller/dwc/pcie-uniphier-ep.c b/drivers/pci/controller/dwc/pcie-uniphier-ep.c
index d6e73811216e..d52753060970 100644
--- a/drivers/pci/controller/dwc/pcie-uniphier-ep.c
+++ b/drivers/pci/controller/dwc/pcie-uniphier-ep.c
@@ -420,6 +420,7 @@ static const struct uniphier_pcie_ep_soc_data uniphier_pro5_data = {
.init = uniphier_pcie_pro5_init_ep,
.wait = NULL,
.features = {
+ DWC_EPC_COMMON_FEATURES,
.linkup_notifier = false,
.msi_capable = true,
.msix_capable = false,
@@ -438,6 +439,7 @@ static const struct uniphier_pcie_ep_soc_data uniphier_nx1_data = {
.init = uniphier_pcie_nx1_init_ep,
.wait = uniphier_pcie_nx1_wait_ep,
.features = {
+ DWC_EPC_COMMON_FEATURES,
.linkup_notifier = false,
.msi_capable = true,
.msix_capable = false,
--
2.51.0
^ permalink raw reply related [flat|nested] 29+ messages in thread* Re: [PATCH v8 3/5] PCI: dwc: Advertise dynamic inbound mapping support
2026-01-15 8:49 ` [PATCH v8 3/5] PCI: dwc: Advertise dynamic inbound " Koichiro Den
@ 2026-01-15 14:54 ` Frank Li
0 siblings, 0 replies; 29+ messages in thread
From: Frank Li @ 2026-01-15 14:54 UTC (permalink / raw)
To: Koichiro Den
Cc: jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas, cassel,
vigneshr, s-vadapalli, hongxing.zhu, l.stach, shawnguo, s.hauer,
kernel, festevam, minghuan.Lian, mingkai.hu, roy.zang,
jesper.nilsson, heiko, srikanth.thokala, marek.vasut+renesas,
yoshihiro.shimoda.uh, geert+renesas, magnus.damm, christian.bruel,
mcoquelin.stm32, alexandre.torgue, thierry.reding, jonathanh,
hayashi.kunihiko, mhiramat, kishon, jirislaby, rongqianfeng,
18255117159, shawn.lin, nicolas.frattaroli, linux.amoon, vidyas,
linux-omap, linux-pci, linux-arm-kernel, linux-kernel, imx,
linuxppc-dev, linux-arm-kernel, linux-rockchip, linux-arm-msm,
linux-renesas-soc, linux-stm32, linux-tegra
On Thu, Jan 15, 2026 at 05:49:26PM +0900, Koichiro Den wrote:
> The DesignWare EP core has supported updating the inbound iATU mapping
> for an already configured BAR (i.e. allowing pci_epc_set_bar() to be
> called again without a prior pci_epc_clear_bar()) since commit
> 4284c88fff0e ("PCI: designware-ep: Allow pci_epc_set_bar() update
> inbound map address").
>
> Now that this capability is exposed via the dynamic_inbound_mapping EPC
> feature bit, set it for DWC-based EP glue drivers using a common
> initializer macro to avoid duplicating the same flag in each driver.
>
> Note that pci-layerscape-ep.c is untouched. It currently constructs the
> feature struct dynamically in ls_pcie_ep_init(). Once converted to a
> static feature definition, it will use DWC_EPC_COMMON_FEATURES as well.
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/pci/controller/dwc/pci-dra7xx.c | 1 +
> drivers/pci/controller/dwc/pci-imx6.c | 3 +++
> drivers/pci/controller/dwc/pci-keystone.c | 1 +
> drivers/pci/controller/dwc/pcie-artpec6.c | 1 +
> drivers/pci/controller/dwc/pcie-designware-plat.c | 1 +
> drivers/pci/controller/dwc/pcie-designware.h | 3 +++
> drivers/pci/controller/dwc/pcie-dw-rockchip.c | 2 ++
> drivers/pci/controller/dwc/pcie-keembay.c | 1 +
> drivers/pci/controller/dwc/pcie-qcom-ep.c | 1 +
> drivers/pci/controller/dwc/pcie-rcar-gen4.c | 1 +
> drivers/pci/controller/dwc/pcie-stm32-ep.c | 1 +
> drivers/pci/controller/dwc/pcie-tegra194.c | 1 +
> drivers/pci/controller/dwc/pcie-uniphier-ep.c | 2 ++
> 13 files changed, 19 insertions(+)
>
> diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c
> index 01cfd9aeb0b8..d5d26229063f 100644
> --- a/drivers/pci/controller/dwc/pci-dra7xx.c
> +++ b/drivers/pci/controller/dwc/pci-dra7xx.c
> @@ -424,6 +424,7 @@ static int dra7xx_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
> }
>
> static const struct pci_epc_features dra7xx_pcie_epc_features = {
> + DWC_EPC_COMMON_FEATURES,
> .linkup_notifier = true,
> .msi_capable = true,
> };
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
> index 4668fc9648bf..f28e335bbbfa 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -1387,6 +1387,7 @@ static int imx_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
> }
>
> static const struct pci_epc_features imx8m_pcie_epc_features = {
> + DWC_EPC_COMMON_FEATURES,
> .msi_capable = true,
> .bar[BAR_1] = { .type = BAR_RESERVED, },
> .bar[BAR_3] = { .type = BAR_RESERVED, },
> @@ -1396,6 +1397,7 @@ static const struct pci_epc_features imx8m_pcie_epc_features = {
> };
>
> static const struct pci_epc_features imx8q_pcie_epc_features = {
> + DWC_EPC_COMMON_FEATURES,
> .msi_capable = true,
> .bar[BAR_1] = { .type = BAR_RESERVED, },
> .bar[BAR_3] = { .type = BAR_RESERVED, },
> @@ -1416,6 +1418,7 @@ static const struct pci_epc_features imx8q_pcie_epc_features = {
> * BAR5 | Enable | 32-bit | 64 KB | Programmable Size
> */
> static const struct pci_epc_features imx95_pcie_epc_features = {
> + DWC_EPC_COMMON_FEATURES,
> .msi_capable = true,
> .bar[BAR_1] = { .type = BAR_FIXED, .fixed_size = SZ_64K, },
> .align = SZ_4K,
> diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
> index f86d9111f863..20fa4dadb82a 100644
> --- a/drivers/pci/controller/dwc/pci-keystone.c
> +++ b/drivers/pci/controller/dwc/pci-keystone.c
> @@ -930,6 +930,7 @@ static int ks_pcie_am654_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
> }
>
> static const struct pci_epc_features ks_pcie_am654_epc_features = {
> + DWC_EPC_COMMON_FEATURES,
> .msi_capable = true,
> .msix_capable = true,
> .bar[BAR_0] = { .type = BAR_RESERVED, },
> diff --git a/drivers/pci/controller/dwc/pcie-artpec6.c b/drivers/pci/controller/dwc/pcie-artpec6.c
> index f4a136ee2daf..e994b75986c3 100644
> --- a/drivers/pci/controller/dwc/pcie-artpec6.c
> +++ b/drivers/pci/controller/dwc/pcie-artpec6.c
> @@ -370,6 +370,7 @@ static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
> }
>
> static const struct pci_epc_features artpec6_pcie_epc_features = {
> + DWC_EPC_COMMON_FEATURES,
> .msi_capable = true,
> };
>
> diff --git a/drivers/pci/controller/dwc/pcie-designware-plat.c b/drivers/pci/controller/dwc/pcie-designware-plat.c
> index 12f41886c65d..8530746ec5cb 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-plat.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-plat.c
> @@ -61,6 +61,7 @@ static int dw_plat_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
> }
>
> static const struct pci_epc_features dw_plat_pcie_epc_features = {
> + DWC_EPC_COMMON_FEATURES,
> .msi_capable = true,
> .msix_capable = true,
> };
> diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
> index f87c67a7a482..4df0cc44faab 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.h
> +++ b/drivers/pci/controller/dwc/pcie-designware.h
> @@ -305,6 +305,9 @@
> /* Default eDMA LLP memory size */
> #define DMA_LLP_MEM_SIZE PAGE_SIZE
>
> +/* Common struct pci_epc_feature bits among DWC EP glue drivers */
> +#define DWC_EPC_COMMON_FEATURES .dynamic_inbound_mapping = true
> +
> struct dw_pcie;
> struct dw_pcie_rp;
> struct dw_pcie_ep;
> diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> index 352f513ebf03..f985a934a137 100644
> --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> @@ -384,6 +384,7 @@ static int rockchip_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
> }
>
> static const struct pci_epc_features rockchip_pcie_epc_features_rk3568 = {
> + DWC_EPC_COMMON_FEATURES,
> .linkup_notifier = true,
> .msi_capable = true,
> .msix_capable = true,
> @@ -404,6 +405,7 @@ static const struct pci_epc_features rockchip_pcie_epc_features_rk3568 = {
> * BARs) would be overwritten, resulting in (all other BARs) no longer working.
> */
> static const struct pci_epc_features rockchip_pcie_epc_features_rk3588 = {
> + DWC_EPC_COMMON_FEATURES,
> .linkup_notifier = true,
> .msi_capable = true,
> .msix_capable = true,
> diff --git a/drivers/pci/controller/dwc/pcie-keembay.c b/drivers/pci/controller/dwc/pcie-keembay.c
> index 60e74ac782af..2666a9c3d67e 100644
> --- a/drivers/pci/controller/dwc/pcie-keembay.c
> +++ b/drivers/pci/controller/dwc/pcie-keembay.c
> @@ -309,6 +309,7 @@ static int keembay_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
> }
>
> static const struct pci_epc_features keembay_pcie_epc_features = {
> + DWC_EPC_COMMON_FEATURES,
> .msi_capable = true,
> .msix_capable = true,
> .bar[BAR_0] = { .only_64bit = true, },
> diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c b/drivers/pci/controller/dwc/pcie-qcom-ep.c
> index f1bc0ac81a92..5e990c7a5879 100644
> --- a/drivers/pci/controller/dwc/pcie-qcom-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c
> @@ -820,6 +820,7 @@ static void qcom_pcie_ep_init_debugfs(struct qcom_pcie_ep *pcie_ep)
> }
>
> static const struct pci_epc_features qcom_pcie_epc_features = {
> + DWC_EPC_COMMON_FEATURES,
> .linkup_notifier = true,
> .msi_capable = true,
> .align = SZ_4K,
> diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> index 80778917d2dd..a6912e85e4dd 100644
> --- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> +++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c
> @@ -420,6 +420,7 @@ static int rcar_gen4_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
> }
>
> static const struct pci_epc_features rcar_gen4_pcie_epc_features = {
> + DWC_EPC_COMMON_FEATURES,
> .msi_capable = true,
> .bar[BAR_1] = { .type = BAR_RESERVED, },
> .bar[BAR_3] = { .type = BAR_RESERVED, },
> diff --git a/drivers/pci/controller/dwc/pcie-stm32-ep.c b/drivers/pci/controller/dwc/pcie-stm32-ep.c
> index 2cecf32d2b0f..c1944b40ce02 100644
> --- a/drivers/pci/controller/dwc/pcie-stm32-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-stm32-ep.c
> @@ -70,6 +70,7 @@ static int stm32_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
> }
>
> static const struct pci_epc_features stm32_pcie_epc_features = {
> + DWC_EPC_COMMON_FEATURES,
> .msi_capable = true,
> .align = SZ_64K,
> };
> diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c
> index 0ddeef70726d..06571d806ab3 100644
> --- a/drivers/pci/controller/dwc/pcie-tegra194.c
> +++ b/drivers/pci/controller/dwc/pcie-tegra194.c
> @@ -1988,6 +1988,7 @@ static int tegra_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
> }
>
> static const struct pci_epc_features tegra_pcie_epc_features = {
> + DWC_EPC_COMMON_FEATURES,
> .linkup_notifier = true,
> .msi_capable = true,
> .bar[BAR_0] = { .type = BAR_FIXED, .fixed_size = SZ_1M,
> diff --git a/drivers/pci/controller/dwc/pcie-uniphier-ep.c b/drivers/pci/controller/dwc/pcie-uniphier-ep.c
> index d6e73811216e..d52753060970 100644
> --- a/drivers/pci/controller/dwc/pcie-uniphier-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-uniphier-ep.c
> @@ -420,6 +420,7 @@ static const struct uniphier_pcie_ep_soc_data uniphier_pro5_data = {
> .init = uniphier_pcie_pro5_init_ep,
> .wait = NULL,
> .features = {
> + DWC_EPC_COMMON_FEATURES,
> .linkup_notifier = false,
> .msi_capable = true,
> .msix_capable = false,
> @@ -438,6 +439,7 @@ static const struct uniphier_pcie_ep_soc_data uniphier_nx1_data = {
> .init = uniphier_pcie_nx1_init_ep,
> .wait = uniphier_pcie_nx1_wait_ep,
> .features = {
> + DWC_EPC_COMMON_FEATURES,
> .linkup_notifier = false,
> .msi_capable = true,
> .msix_capable = false,
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v8 4/5] PCI: dwc: ep: Support BAR subrange inbound mapping via Address Match Mode iATU
2026-01-15 8:49 [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support Koichiro Den
` (2 preceding siblings ...)
2026-01-15 8:49 ` [PATCH v8 3/5] PCI: dwc: Advertise dynamic inbound " Koichiro Den
@ 2026-01-15 8:49 ` Koichiro Den
2026-01-15 15:22 ` Frank Li
2026-01-15 8:49 ` [PATCH v8 5/5] Documentation: PCI: endpoint: Clarify pci_epc_set_bar() usage Koichiro Den
2026-01-19 13:00 ` [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support Koichiro Den
5 siblings, 1 reply; 29+ messages in thread
From: Koichiro Den @ 2026-01-15 8:49 UTC (permalink / raw)
To: jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas, cassel
Cc: vigneshr, s-vadapalli, hongxing.zhu, l.stach, shawnguo, s.hauer,
kernel, festevam, minghuan.Lian, mingkai.hu, roy.zang,
jesper.nilsson, heiko, srikanth.thokala, marek.vasut+renesas,
yoshihiro.shimoda.uh, geert+renesas, magnus.damm, christian.bruel,
mcoquelin.stm32, alexandre.torgue, thierry.reding, jonathanh,
hayashi.kunihiko, mhiramat, kishon, jirislaby, rongqianfeng,
18255117159, shawn.lin, nicolas.frattaroli, linux.amoon, vidyas,
Frank.Li, linux-omap, linux-pci, linux-arm-kernel, linux-kernel,
imx, linuxppc-dev, linux-arm-kernel, linux-rockchip,
linux-arm-msm, linux-renesas-soc, linux-stm32, linux-tegra
Extend dw_pcie_ep_set_bar() to support inbound mappings for BAR
subranges using Address Match Mode IB iATU when pci_epf_bar.num_submap
is non-zero.
Rename 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
num_submap is non-zero, read the assigned BAR base address and program
one inbound iATU window per subrange. Validate the submap array before
programming:
- each subrange is aligned to pci->region_align
- subranges cover the whole BAR (no gaps and no overlaps)
- subranges are sorted in ascending order by offset
Track Address Match Mode mappings and tear them down on clear_bar() and
on set_bar() error paths to avoid leaving half-programmed state or
untranslated BAR holes.
Advertise this capability by extending the common feature bit
initializer macro (DWC_EPC_COMMON_FEATURES).
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
.../pci/controller/dwc/pcie-designware-ep.c | 203 +++++++++++++++++-
drivers/pci/controller/dwc/pcie-designware.h | 7 +-
2 files changed, 199 insertions(+), 11 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 1195d401df19..904c90f16a0b 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 inbound iATU mapping */
+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,179 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no, int type,
return 0;
}
+static void dw_pcie_ep_clear_ib_maps(struct dw_pcie_ep *ep, enum pci_barno bar)
+{
+ struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+ struct device *dev = pci->dev;
+ unsigned int i, num;
+ u32 atu_index;
+ u32 *indexes;
+
+ /* Tear down the BAR Match Mode mapping, if any. */
+ 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;
+ }
+
+ /* Tear down all Address Match Mode mappings, if any. */
+ indexes = ep->ib_atu_indexes[bar];
+ num = ep->num_ib_atu_indexes[bar];
+ ep->ib_atu_indexes[bar] = NULL;
+ ep->num_ib_atu_indexes[bar] = 0;
+ if (!indexes)
+ return;
+ for (i = 0; i < num; i++) {
+ dw_pcie_disable_atu(pci, PCIE_ATU_REGION_DIR_IB, indexes[i]);
+ clear_bit(indexes[i], ep->ib_window_map);
+ }
+ devm_kfree(dev, indexes);
+}
+
+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);
+}
+
+static int dw_pcie_ep_validate_submap(struct dw_pcie_ep *ep,
+ const struct pci_epf_bar_submap *submap,
+ unsigned int num_submap, size_t bar_size)
+{
+ struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+ u32 align = pci->region_align;
+ size_t off = 0;
+ unsigned int i;
+ size_t size;
+
+ if (!align || !IS_ALIGNED(bar_size, align))
+ return -EINVAL;
+
+ /*
+ * The submap array order defines the BAR layout (submap[0] starts
+ * at offset 0 and each entry immediately follows the previous
+ * one). Here, validate that it forms a strict, gapless
+ * decomposition of the BAR:
+ * - each entry has a non-zero size
+ * - sizes, implicit offsets and phys_addr are aligned to
+ * pci->region_align
+ * - each entry lies within the BAR range
+ * - the entries exactly cover the whole BAR
+ *
+ * Note: dw_pcie_prog_inbound_atu() also checks alignment for the
+ * PCI address and the target phys_addr, but validating up-front
+ * avoids partially programming iATU windows in vain.
+ */
+ for (i = 0; i < num_submap; i++) {
+ size = submap[i].size;
+
+ if (!size)
+ return -EINVAL;
+
+ if (!IS_ALIGNED(size, align) || !IS_ALIGNED(off, align))
+ return -EINVAL;
+
+ if (!IS_ALIGNED(submap[i].phys_addr, align))
+ return -EINVAL;
+
+ if (off > bar_size || size > bar_size - off)
+ return -EINVAL;
+
+ off += size;
+ }
+ if (off != bar_size)
+ return -EINVAL;
+
+ return 0;
+}
+
+/* Address Match Mode inbound iATU mapping */
+static int dw_pcie_ep_ib_atu_addr(struct dw_pcie_ep *ep, u8 func_no, int type,
+ const struct pci_epf_bar *epf_bar)
+{
+ const 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 device *dev = pci->dev;
+ u64 pci_addr, parent_bus_addr;
+ u64 size, base, off = 0;
+ int free_win, ret;
+ unsigned int i;
+ u32 *indexes;
+
+ if (!epf_bar->num_submap || !submap || !epf_bar->size)
+ return -EINVAL;
+
+ ret = dw_pcie_ep_validate_submap(ep, submap, epf_bar->num_submap,
+ epf_bar->size);
+ if (ret)
+ return ret;
+
+ 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;
+ }
+
+ indexes = devm_kcalloc(dev, epf_bar->num_submap, sizeof(*indexes),
+ GFP_KERNEL);
+ if (!indexes)
+ return -ENOMEM;
+
+ ep->ib_atu_indexes[bar] = indexes;
+ ep->num_ib_atu_indexes[bar] = 0;
+
+ for (i = 0; i < epf_bar->num_submap; i++) {
+ size = submap[i].size;
+ parent_bus_addr = submap[i].phys_addr;
+
+ if (off > (~0ULL) - base) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ pci_addr = base + off;
+ off += size;
+
+ free_win = find_first_zero_bit(ep->ib_window_map,
+ pci->num_ib_windows);
+ if (free_win >= pci->num_ib_windows) {
+ ret = -ENOSPC;
+ goto err;
+ }
+
+ ret = dw_pcie_prog_inbound_atu(pci, free_win, type,
+ parent_bus_addr, pci_addr, size);
+ if (ret)
+ goto err;
+
+ set_bit(free_win, ep->ib_window_map);
+ indexes[i] = free_win;
+ ep->num_ib_atu_indexes[bar] = i + 1;
+ }
+ return 0;
+err:
+ dw_pcie_ep_clear_ib_maps(ep, bar);
+ return ret;
+}
+
static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep,
struct dw_pcie_ob_atu_cfg *atu)
{
@@ -204,17 +378,15 @@ 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;
- 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);
+ dw_pcie_ep_clear_ib_maps(ep, bar);
+
ep->epf_bar[bar] = NULL;
- ep->bar_to_atu[bar] = 0;
}
static unsigned int dw_pcie_ep_get_rebar_offset(struct dw_pcie *pci,
@@ -370,6 +542,13 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
ep->epf_bar[bar]->flags != flags)
return -EINVAL;
+ /*
+ * When dynamically changing a BAR, tear down any existing
+ * mappings before re-programming.
+ */
+ if (ep->epf_bar[bar]->num_submap || epf_bar->num_submap)
+ dw_pcie_ep_clear_ib_maps(ep, bar);
+
/*
* When dynamically changing a BAR, skip writing the BAR reg, as
* that would clear the BAR's PCI address assigned by the host.
@@ -408,8 +587,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->num_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;
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index 4df0cc44faab..b74f5014faf6 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -306,7 +306,8 @@
#define DMA_LLP_MEM_SIZE PAGE_SIZE
/* Common struct pci_epc_feature bits among DWC EP glue drivers */
-#define DWC_EPC_COMMON_FEATURES .dynamic_inbound_mapping = true
+#define DWC_EPC_COMMON_FEATURES .dynamic_inbound_mapping = true, \
+ .subrange_mapping = true
struct dw_pcie;
struct dw_pcie_rp;
@@ -486,6 +487,10 @@ struct dw_pcie_ep {
phys_addr_t msi_mem_phys;
struct pci_epf_bar *epf_bar[PCI_STD_NUM_BARS];
+ /* Only for Address Match Mode inbound iATU */
+ u32 *ib_atu_indexes[PCI_STD_NUM_BARS];
+ unsigned int num_ib_atu_indexes[PCI_STD_NUM_BARS];
+
/* MSI outbound iATU state */
bool msi_iatu_mapped;
u64 msi_msg_addr;
--
2.51.0
^ permalink raw reply related [flat|nested] 29+ messages in thread* Re: [PATCH v8 4/5] PCI: dwc: ep: Support BAR subrange inbound mapping via Address Match Mode iATU
2026-01-15 8:49 ` [PATCH v8 4/5] PCI: dwc: ep: Support BAR subrange inbound mapping via Address Match Mode iATU Koichiro Den
@ 2026-01-15 15:22 ` Frank Li
0 siblings, 0 replies; 29+ messages in thread
From: Frank Li @ 2026-01-15 15:22 UTC (permalink / raw)
To: Koichiro Den
Cc: jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas, cassel,
vigneshr, s-vadapalli, hongxing.zhu, l.stach, shawnguo, s.hauer,
kernel, festevam, minghuan.Lian, mingkai.hu, roy.zang,
jesper.nilsson, heiko, srikanth.thokala, marek.vasut+renesas,
yoshihiro.shimoda.uh, geert+renesas, magnus.damm, christian.bruel,
mcoquelin.stm32, alexandre.torgue, thierry.reding, jonathanh,
hayashi.kunihiko, mhiramat, kishon, jirislaby, rongqianfeng,
18255117159, shawn.lin, nicolas.frattaroli, linux.amoon, vidyas,
linux-omap, linux-pci, linux-arm-kernel, linux-kernel, imx,
linuxppc-dev, linux-arm-kernel, linux-rockchip, linux-arm-msm,
linux-renesas-soc, linux-stm32, linux-tegra
On Thu, Jan 15, 2026 at 05:49:27PM +0900, Koichiro Den wrote:
> Extend dw_pcie_ep_set_bar() to support inbound mappings for BAR
> subranges using Address Match Mode IB iATU when pci_epf_bar.num_submap
> is non-zero.
>
> Rename 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
> num_submap is non-zero, read the assigned BAR base address and program
> one inbound iATU window per subrange. Validate the submap array before
> programming:
> - each subrange is aligned to pci->region_align
> - subranges cover the whole BAR (no gaps and no overlaps)
> - subranges are sorted in ascending order by offset
>
> Track Address Match Mode mappings and tear them down on clear_bar() and
> on set_bar() error paths to avoid leaving half-programmed state or
> untranslated BAR holes.
>
> Advertise this capability by extending the common feature bit
> initializer macro (DWC_EPC_COMMON_FEATURES).
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> ---
> .../pci/controller/dwc/pcie-designware-ep.c | 203 +++++++++++++++++-
> drivers/pci/controller/dwc/pcie-designware.h | 7 +-
> 2 files changed, 199 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
> index 1195d401df19..904c90f16a0b 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 inbound iATU mapping */
> +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,179 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, u8 func_no, int type,
> return 0;
> }
>
> +static void dw_pcie_ep_clear_ib_maps(struct dw_pcie_ep *ep, enum pci_barno bar)
> +{
> + struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> + struct device *dev = pci->dev;
> + unsigned int i, num;
> + u32 atu_index;
> + u32 *indexes;
> +
> + /* Tear down the BAR Match Mode mapping, if any. */
> + 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;
> + }
> +
> + /* Tear down all Address Match Mode mappings, if any. */
> + indexes = ep->ib_atu_indexes[bar];
> + num = ep->num_ib_atu_indexes[bar];
> + ep->ib_atu_indexes[bar] = NULL;
> + ep->num_ib_atu_indexes[bar] = 0;
> + if (!indexes)
> + return;
> + for (i = 0; i < num; i++) {
> + dw_pcie_disable_atu(pci, PCIE_ATU_REGION_DIR_IB, indexes[i]);
> + clear_bit(indexes[i], ep->ib_window_map);
> + }
> + devm_kfree(dev, indexes);
> +}
> +
> +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);
> +}
> +
> +static int dw_pcie_ep_validate_submap(struct dw_pcie_ep *ep,
> + const struct pci_epf_bar_submap *submap,
> + unsigned int num_submap, size_t bar_size)
> +{
> + struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> + u32 align = pci->region_align;
> + size_t off = 0;
> + unsigned int i;
> + size_t size;
> +
> + if (!align || !IS_ALIGNED(bar_size, align))
> + return -EINVAL;
> +
> + /*
> + * The submap array order defines the BAR layout (submap[0] starts
> + * at offset 0 and each entry immediately follows the previous
> + * one). Here, validate that it forms a strict, gapless
> + * decomposition of the BAR:
> + * - each entry has a non-zero size
> + * - sizes, implicit offsets and phys_addr are aligned to
> + * pci->region_align
> + * - each entry lies within the BAR range
> + * - the entries exactly cover the whole BAR
> + *
> + * Note: dw_pcie_prog_inbound_atu() also checks alignment for the
> + * PCI address and the target phys_addr, but validating up-front
> + * avoids partially programming iATU windows in vain.
> + */
> + for (i = 0; i < num_submap; i++) {
> + size = submap[i].size;
> +
> + if (!size)
> + return -EINVAL;
> +
> + if (!IS_ALIGNED(size, align) || !IS_ALIGNED(off, align))
> + return -EINVAL;
> +
> + if (!IS_ALIGNED(submap[i].phys_addr, align))
> + return -EINVAL;
> +
> + if (off > bar_size || size > bar_size - off)
> + return -EINVAL;
> +
> + off += size;
> + }
> + if (off != bar_size)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> +/* Address Match Mode inbound iATU mapping */
> +static int dw_pcie_ep_ib_atu_addr(struct dw_pcie_ep *ep, u8 func_no, int type,
> + const struct pci_epf_bar *epf_bar)
> +{
> + const 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 device *dev = pci->dev;
> + u64 pci_addr, parent_bus_addr;
> + u64 size, base, off = 0;
> + int free_win, ret;
> + unsigned int i;
> + u32 *indexes;
> +
> + if (!epf_bar->num_submap || !submap || !epf_bar->size)
> + return -EINVAL;
> +
> + ret = dw_pcie_ep_validate_submap(ep, submap, epf_bar->num_submap,
> + epf_bar->size);
> + if (ret)
> + return ret;
> +
> + 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;
> + }
> +
> + indexes = devm_kcalloc(dev, epf_bar->num_submap, sizeof(*indexes),
> + GFP_KERNEL);
> + if (!indexes)
> + return -ENOMEM;
> +
> + ep->ib_atu_indexes[bar] = indexes;
> + ep->num_ib_atu_indexes[bar] = 0;
> +
> + for (i = 0; i < epf_bar->num_submap; i++) {
> + size = submap[i].size;
> + parent_bus_addr = submap[i].phys_addr;
> +
> + if (off > (~0ULL) - base) {
> + ret = -EINVAL;
> + goto err;
> + }
> +
> + pci_addr = base + off;
> + off += size;
> +
> + free_win = find_first_zero_bit(ep->ib_window_map,
> + pci->num_ib_windows);
> + if (free_win >= pci->num_ib_windows) {
> + ret = -ENOSPC;
> + goto err;
> + }
> +
> + ret = dw_pcie_prog_inbound_atu(pci, free_win, type,
> + parent_bus_addr, pci_addr, size);
> + if (ret)
> + goto err;
> +
> + set_bit(free_win, ep->ib_window_map);
> + indexes[i] = free_win;
> + ep->num_ib_atu_indexes[bar] = i + 1;
> + }
> + return 0;
> +err:
> + dw_pcie_ep_clear_ib_maps(ep, bar);
> + return ret;
> +}
> +
> static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep,
> struct dw_pcie_ob_atu_cfg *atu)
> {
> @@ -204,17 +378,15 @@ 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;
>
> - 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);
> + dw_pcie_ep_clear_ib_maps(ep, bar);
> +
> ep->epf_bar[bar] = NULL;
> - ep->bar_to_atu[bar] = 0;
> }
>
> static unsigned int dw_pcie_ep_get_rebar_offset(struct dw_pcie *pci,
> @@ -370,6 +542,13 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
> ep->epf_bar[bar]->flags != flags)
> return -EINVAL;
>
> + /*
> + * When dynamically changing a BAR, tear down any existing
> + * mappings before re-programming.
> + */
> + if (ep->epf_bar[bar]->num_submap || epf_bar->num_submap)
> + dw_pcie_ep_clear_ib_maps(ep, bar);
> +
> /*
> * When dynamically changing a BAR, skip writing the BAR reg, as
> * that would clear the BAR's PCI address assigned by the host.
> @@ -408,8 +587,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->num_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;
>
> diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
> index 4df0cc44faab..b74f5014faf6 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.h
> +++ b/drivers/pci/controller/dwc/pcie-designware.h
> @@ -306,7 +306,8 @@
> #define DMA_LLP_MEM_SIZE PAGE_SIZE
>
> /* Common struct pci_epc_feature bits among DWC EP glue drivers */
> -#define DWC_EPC_COMMON_FEATURES .dynamic_inbound_mapping = true
> +#define DWC_EPC_COMMON_FEATURES .dynamic_inbound_mapping = true, \
> + .subrange_mapping = true
>
> struct dw_pcie;
> struct dw_pcie_rp;
> @@ -486,6 +487,10 @@ struct dw_pcie_ep {
> phys_addr_t msi_mem_phys;
> struct pci_epf_bar *epf_bar[PCI_STD_NUM_BARS];
>
> + /* Only for Address Match Mode inbound iATU */
> + u32 *ib_atu_indexes[PCI_STD_NUM_BARS];
> + unsigned int num_ib_atu_indexes[PCI_STD_NUM_BARS];
> +
> /* MSI outbound iATU state */
> bool msi_iatu_mapped;
> u64 msi_msg_addr;
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH v8 5/5] Documentation: PCI: endpoint: Clarify pci_epc_set_bar() usage
2026-01-15 8:49 [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support Koichiro Den
` (3 preceding siblings ...)
2026-01-15 8:49 ` [PATCH v8 4/5] PCI: dwc: ep: Support BAR subrange inbound mapping via Address Match Mode iATU Koichiro Den
@ 2026-01-15 8:49 ` Koichiro Den
2026-01-15 15:23 ` Frank Li
2026-01-19 13:00 ` [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support Koichiro Den
5 siblings, 1 reply; 29+ messages in thread
From: Koichiro Den @ 2026-01-15 8:49 UTC (permalink / raw)
To: jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas, cassel
Cc: vigneshr, s-vadapalli, hongxing.zhu, l.stach, shawnguo, s.hauer,
kernel, festevam, minghuan.Lian, mingkai.hu, roy.zang,
jesper.nilsson, heiko, srikanth.thokala, marek.vasut+renesas,
yoshihiro.shimoda.uh, geert+renesas, magnus.damm, christian.bruel,
mcoquelin.stm32, alexandre.torgue, thierry.reding, jonathanh,
hayashi.kunihiko, mhiramat, kishon, jirislaby, rongqianfeng,
18255117159, shawn.lin, nicolas.frattaroli, linux.amoon, vidyas,
Frank.Li, linux-omap, linux-pci, linux-arm-kernel, linux-kernel,
imx, linuxppc-dev, linux-arm-kernel, linux-rockchip,
linux-arm-msm, linux-renesas-soc, linux-stm32, linux-tegra
The current documentation implies that pci_epc_set_bar() is only used
before the host enumerates the endpoint.
In practice, some Endpoint Controllers support calling pci_epc_set_bar()
multiple times for the same BAR (without clearing it) in order to update
inbound address translations after the host has programmed the BAR base
address, which some Endpoint Functions such as vNTB already rely on.
Add document text for that.
Also document the expected call flow for BAR subrange mapping
(pci_epf_bar.num_submap / pci_epf_bar.submap), which may require a
second pci_epc_set_bar() call after the host has programmed the BAR base
address.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
Documentation/PCI/endpoint/pci-endpoint.rst | 24 +++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/Documentation/PCI/endpoint/pci-endpoint.rst b/Documentation/PCI/endpoint/pci-endpoint.rst
index 0741c8cbd74e..4697377adeae 100644
--- a/Documentation/PCI/endpoint/pci-endpoint.rst
+++ b/Documentation/PCI/endpoint/pci-endpoint.rst
@@ -95,6 +95,30 @@ by the PCI endpoint function driver.
Register space of the function driver is usually configured
using this API.
+ Some endpoint controllers also support calling pci_epc_set_bar() again
+ for the same BAR (without calling pci_epc_clear_bar()) to update inbound
+ address translations after the host has programmed the BAR base address.
+ Endpoint function drivers can check this capability via the
+ dynamic_inbound_mapping EPC feature bit.
+
+ When pci_epf_bar.num_submap is non-zero, the endpoint function driver is
+ requesting BAR subrange mapping using pci_epf_bar.submap. This requires
+ the EPC to advertise support via the subrange_mapping EPC feature bit.
+
+ When an EPF driver wants to make use of the inbound subrange mapping
+ feature, it requires that the BAR base address has been programmed by
+ the host during enumeration. Thus, it needs to call pci_epc_set_bar()
+ twice for the same BAR (requires dynamic_inbound_mapping): first with
+ num_submap set to zero and configuring the BAR size, then after the PCIe
+ link is up and the host enumerates the endpoint and programs the BAR
+ base address, again with num_submap set to non-zero value.
+
+ Note that when making use of the inbound subrange mapping feature, the
+ EPF driver must not call pci_epc_clear_bar() between the two
+ pci_epc_set_bar() calls, because clearing the BAR can clear/disable the
+ BAR register or BAR decode on the endpoint while the host still expects
+ the assigned BAR address to remain valid.
+
* pci_epc_clear_bar()
The PCI endpoint function driver should use pci_epc_clear_bar() to reset
--
2.51.0
^ permalink raw reply related [flat|nested] 29+ messages in thread* Re: [PATCH v8 5/5] Documentation: PCI: endpoint: Clarify pci_epc_set_bar() usage
2026-01-15 8:49 ` [PATCH v8 5/5] Documentation: PCI: endpoint: Clarify pci_epc_set_bar() usage Koichiro Den
@ 2026-01-15 15:23 ` Frank Li
0 siblings, 0 replies; 29+ messages in thread
From: Frank Li @ 2026-01-15 15:23 UTC (permalink / raw)
To: Koichiro Den
Cc: jingoohan1, mani, lpieralisi, kwilczynski, robh, bhelgaas, cassel,
vigneshr, s-vadapalli, hongxing.zhu, l.stach, shawnguo, s.hauer,
kernel, festevam, minghuan.Lian, mingkai.hu, roy.zang,
jesper.nilsson, heiko, srikanth.thokala, marek.vasut+renesas,
yoshihiro.shimoda.uh, geert+renesas, magnus.damm, christian.bruel,
mcoquelin.stm32, alexandre.torgue, thierry.reding, jonathanh,
hayashi.kunihiko, mhiramat, kishon, jirislaby, rongqianfeng,
18255117159, shawn.lin, nicolas.frattaroli, linux.amoon, vidyas,
linux-omap, linux-pci, linux-arm-kernel, linux-kernel, imx,
linuxppc-dev, linux-arm-kernel, linux-rockchip, linux-arm-msm,
linux-renesas-soc, linux-stm32, linux-tegra
On Thu, Jan 15, 2026 at 05:49:28PM +0900, Koichiro Den wrote:
> The current documentation implies that pci_epc_set_bar() is only used
> before the host enumerates the endpoint.
>
> In practice, some Endpoint Controllers support calling pci_epc_set_bar()
> multiple times for the same BAR (without clearing it) in order to update
> inbound address translations after the host has programmed the BAR base
> address, which some Endpoint Functions such as vNTB already rely on.
> Add document text for that.
>
> Also document the expected call flow for BAR subrange mapping
> (pci_epf_bar.num_submap / pci_epf_bar.submap), which may require a
> second pci_epc_set_bar() call after the host has programmed the BAR base
> address.
>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> Documentation/PCI/endpoint/pci-endpoint.rst | 24 +++++++++++++++++++++
> 1 file changed, 24 insertions(+)
>
> diff --git a/Documentation/PCI/endpoint/pci-endpoint.rst b/Documentation/PCI/endpoint/pci-endpoint.rst
> index 0741c8cbd74e..4697377adeae 100644
> --- a/Documentation/PCI/endpoint/pci-endpoint.rst
> +++ b/Documentation/PCI/endpoint/pci-endpoint.rst
> @@ -95,6 +95,30 @@ by the PCI endpoint function driver.
> Register space of the function driver is usually configured
> using this API.
>
> + Some endpoint controllers also support calling pci_epc_set_bar() again
> + for the same BAR (without calling pci_epc_clear_bar()) to update inbound
> + address translations after the host has programmed the BAR base address.
> + Endpoint function drivers can check this capability via the
> + dynamic_inbound_mapping EPC feature bit.
> +
> + When pci_epf_bar.num_submap is non-zero, the endpoint function driver is
> + requesting BAR subrange mapping using pci_epf_bar.submap. This requires
> + the EPC to advertise support via the subrange_mapping EPC feature bit.
> +
> + When an EPF driver wants to make use of the inbound subrange mapping
> + feature, it requires that the BAR base address has been programmed by
> + the host during enumeration. Thus, it needs to call pci_epc_set_bar()
> + twice for the same BAR (requires dynamic_inbound_mapping): first with
> + num_submap set to zero and configuring the BAR size, then after the PCIe
> + link is up and the host enumerates the endpoint and programs the BAR
> + base address, again with num_submap set to non-zero value.
> +
> + Note that when making use of the inbound subrange mapping feature, the
> + EPF driver must not call pci_epc_clear_bar() between the two
> + pci_epc_set_bar() calls, because clearing the BAR can clear/disable the
> + BAR register or BAR decode on the endpoint while the host still expects
> + the assigned BAR address to remain valid.
> +
> * pci_epc_clear_bar()
>
> The PCI endpoint function driver should use pci_epc_clear_bar() to reset
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support
2026-01-15 8:49 [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support Koichiro Den
` (4 preceding siblings ...)
2026-01-15 8:49 ` [PATCH v8 5/5] Documentation: PCI: endpoint: Clarify pci_epc_set_bar() usage Koichiro Den
@ 2026-01-19 13:00 ` Koichiro Den
2026-01-21 15:38 ` Manivannan Sadhasivam
5 siblings, 1 reply; 29+ messages in thread
From: Koichiro Den @ 2026-01-19 13:00 UTC (permalink / raw)
To: mani, bhelgaas; +Cc: kwilczynski, cassel, frank.li, linux-pci, linux-kernel
On Thu, Jan 15, 2026 at 05:49:23PM +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.
>
> - Patch 1/5 introduces dynamic_inbound_mapping feature bit. This can be
> used as a safeguard to check whether a BAR can really be reconfigured
> without clearing/resetting it.
>
> - Patch 2/5 introduces generic BAR subrange mapping support in the PCI
> endpoint core.
>
> - Patch 3/5 advertises dynamic inbound mapping support via
> DWC_EPC_COMMON_FEATURES for all DWC-based glue drivers.
>
> - Patch 4/5 adds an implementation for the DesignWare PCIe endpoint
> controller using Address Match Mode IB iATU. It also advertises
> subrange_mapping support via DWC_EPC_COMMON_FEATURES.
>
> - Patch 5/5 updates a documentation for pci_epc_set_bar().
>
--(snip)--
> Koichiro Den (5):
> PCI: endpoint: Add dynamic_inbound_mapping EPC feature
> PCI: endpoint: Add BAR subrange mapping support
> PCI: dwc: Advertise dynamic inbound mapping support
> PCI: dwc: ep: Support BAR subrange inbound mapping via Address Match
> Mode iATU
> Documentation: PCI: endpoint: Clarify pci_epc_set_bar() usage
>
> Documentation/PCI/endpoint/pci-endpoint.rst | 24 +++
> drivers/pci/controller/dwc/pci-dra7xx.c | 1 +
> drivers/pci/controller/dwc/pci-imx6.c | 3 +
> drivers/pci/controller/dwc/pci-keystone.c | 1 +
> drivers/pci/controller/dwc/pcie-artpec6.c | 1 +
> .../pci/controller/dwc/pcie-designware-ep.c | 203 +++++++++++++++++-
> .../pci/controller/dwc/pcie-designware-plat.c | 1 +
> drivers/pci/controller/dwc/pcie-designware.h | 8 +
> drivers/pci/controller/dwc/pcie-dw-rockchip.c | 2 +
> drivers/pci/controller/dwc/pcie-keembay.c | 1 +
> drivers/pci/controller/dwc/pcie-qcom-ep.c | 1 +
> drivers/pci/controller/dwc/pcie-rcar-gen4.c | 1 +
> drivers/pci/controller/dwc/pcie-stm32-ep.c | 1 +
> drivers/pci/controller/dwc/pcie-tegra194.c | 1 +
> drivers/pci/controller/dwc/pcie-uniphier-ep.c | 2 +
> drivers/pci/endpoint/pci-epc-core.c | 8 +
> include/linux/pci-epc.h | 9 +
> include/linux/pci-epf.h | 27 +++
> 18 files changed, 285 insertions(+), 10 deletions(-)
Hi Mani, Bjorn,
Based on the feedback so far (thanks to Niklas and Frank), the design seems
to be converging. At this point, I would appreciate confirmation on the
following points before proceeding further.
1) Does the current (v8) approach for BAR subrange inbound mapping at the
EPC/core level look reasonable?
2) From a process perspective, does it make sense to continue this as a PCI
endpoint subsystem-led series, with the dwc-specific changes layered on
top, or would you prefer a different split or ownership?
Thanks,
Koichiro
>
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 29+ messages in thread* Re: [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support
2026-01-19 13:00 ` [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support Koichiro Den
@ 2026-01-21 15:38 ` Manivannan Sadhasivam
2026-01-22 1:52 ` Koichiro Den
0 siblings, 1 reply; 29+ messages in thread
From: Manivannan Sadhasivam @ 2026-01-21 15:38 UTC (permalink / raw)
To: Koichiro Den
Cc: bhelgaas, kwilczynski, cassel, frank.li, linux-pci, linux-kernel
On Mon, Jan 19, 2026 at 10:00:38PM +0900, Koichiro Den wrote:
> On Thu, Jan 15, 2026 at 05:49:23PM +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.
> >
> > - Patch 1/5 introduces dynamic_inbound_mapping feature bit. This can be
> > used as a safeguard to check whether a BAR can really be reconfigured
> > without clearing/resetting it.
> >
> > - Patch 2/5 introduces generic BAR subrange mapping support in the PCI
> > endpoint core.
> >
> > - Patch 3/5 advertises dynamic inbound mapping support via
> > DWC_EPC_COMMON_FEATURES for all DWC-based glue drivers.
> >
> > - Patch 4/5 adds an implementation for the DesignWare PCIe endpoint
> > controller using Address Match Mode IB iATU. It also advertises
> > subrange_mapping support via DWC_EPC_COMMON_FEATURES.
> >
> > - Patch 5/5 updates a documentation for pci_epc_set_bar().
> >
> --(snip)--
> > Koichiro Den (5):
> > PCI: endpoint: Add dynamic_inbound_mapping EPC feature
> > PCI: endpoint: Add BAR subrange mapping support
> > PCI: dwc: Advertise dynamic inbound mapping support
> > PCI: dwc: ep: Support BAR subrange inbound mapping via Address Match
> > Mode iATU
> > Documentation: PCI: endpoint: Clarify pci_epc_set_bar() usage
> >
> > Documentation/PCI/endpoint/pci-endpoint.rst | 24 +++
> > drivers/pci/controller/dwc/pci-dra7xx.c | 1 +
> > drivers/pci/controller/dwc/pci-imx6.c | 3 +
> > drivers/pci/controller/dwc/pci-keystone.c | 1 +
> > drivers/pci/controller/dwc/pcie-artpec6.c | 1 +
> > .../pci/controller/dwc/pcie-designware-ep.c | 203 +++++++++++++++++-
> > .../pci/controller/dwc/pcie-designware-plat.c | 1 +
> > drivers/pci/controller/dwc/pcie-designware.h | 8 +
> > drivers/pci/controller/dwc/pcie-dw-rockchip.c | 2 +
> > drivers/pci/controller/dwc/pcie-keembay.c | 1 +
> > drivers/pci/controller/dwc/pcie-qcom-ep.c | 1 +
> > drivers/pci/controller/dwc/pcie-rcar-gen4.c | 1 +
> > drivers/pci/controller/dwc/pcie-stm32-ep.c | 1 +
> > drivers/pci/controller/dwc/pcie-tegra194.c | 1 +
> > drivers/pci/controller/dwc/pcie-uniphier-ep.c | 2 +
> > drivers/pci/endpoint/pci-epc-core.c | 8 +
> > include/linux/pci-epc.h | 9 +
> > include/linux/pci-epf.h | 27 +++
> > 18 files changed, 285 insertions(+), 10 deletions(-)
>
> Hi Mani, Bjorn,
>
> Based on the feedback so far (thanks to Niklas and Frank), the design seems
> to be converging. At this point, I would appreciate confirmation on the
> following points before proceeding further.
>
> 1) Does the current (v8) approach for BAR subrange inbound mapping at the
> EPC/core level look reasonable?
>
In this series you didn't add a consumer of this subrange mapping, which I
believe is the epf-vntb driver [1]. Even so I don't see a justification of why
the BAR needs to be split into multiple subranges. Can you explain that?
> 2) From a process perspective, does it make sense to continue this as a PCI
> endpoint subsystem-led series, with the dwc-specific changes layered on
> top, or would you prefer a different split or ownership?
>
Is is OK to have both controller driver and endpoint changes in one series.
- Mani
[1] https://lore.kernel.org/linux-pci/20260118135440.1958279-14-den@valinux.co.jp
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support
2026-01-21 15:38 ` Manivannan Sadhasivam
@ 2026-01-22 1:52 ` Koichiro Den
2026-01-22 6:46 ` Manivannan Sadhasivam
2026-01-22 8:45 ` Niklas Cassel
0 siblings, 2 replies; 29+ messages in thread
From: Koichiro Den @ 2026-01-22 1:52 UTC (permalink / raw)
To: Manivannan Sadhasivam
Cc: bhelgaas, kwilczynski, cassel, frank.li, linux-pci, linux-kernel
On Wed, Jan 21, 2026 at 09:08:34PM +0530, Manivannan Sadhasivam wrote:
> On Mon, Jan 19, 2026 at 10:00:38PM +0900, Koichiro Den wrote:
> > On Thu, Jan 15, 2026 at 05:49:23PM +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.
> > >
> > > - Patch 1/5 introduces dynamic_inbound_mapping feature bit. This can be
> > > used as a safeguard to check whether a BAR can really be reconfigured
> > > without clearing/resetting it.
> > >
> > > - Patch 2/5 introduces generic BAR subrange mapping support in the PCI
> > > endpoint core.
> > >
> > > - Patch 3/5 advertises dynamic inbound mapping support via
> > > DWC_EPC_COMMON_FEATURES for all DWC-based glue drivers.
> > >
> > > - Patch 4/5 adds an implementation for the DesignWare PCIe endpoint
> > > controller using Address Match Mode IB iATU. It also advertises
> > > subrange_mapping support via DWC_EPC_COMMON_FEATURES.
> > >
> > > - Patch 5/5 updates a documentation for pci_epc_set_bar().
> > >
> > --(snip)--
> > > Koichiro Den (5):
> > > PCI: endpoint: Add dynamic_inbound_mapping EPC feature
> > > PCI: endpoint: Add BAR subrange mapping support
> > > PCI: dwc: Advertise dynamic inbound mapping support
> > > PCI: dwc: ep: Support BAR subrange inbound mapping via Address Match
> > > Mode iATU
> > > Documentation: PCI: endpoint: Clarify pci_epc_set_bar() usage
> > >
> > > Documentation/PCI/endpoint/pci-endpoint.rst | 24 +++
> > > drivers/pci/controller/dwc/pci-dra7xx.c | 1 +
> > > drivers/pci/controller/dwc/pci-imx6.c | 3 +
> > > drivers/pci/controller/dwc/pci-keystone.c | 1 +
> > > drivers/pci/controller/dwc/pcie-artpec6.c | 1 +
> > > .../pci/controller/dwc/pcie-designware-ep.c | 203 +++++++++++++++++-
> > > .../pci/controller/dwc/pcie-designware-plat.c | 1 +
> > > drivers/pci/controller/dwc/pcie-designware.h | 8 +
> > > drivers/pci/controller/dwc/pcie-dw-rockchip.c | 2 +
> > > drivers/pci/controller/dwc/pcie-keembay.c | 1 +
> > > drivers/pci/controller/dwc/pcie-qcom-ep.c | 1 +
> > > drivers/pci/controller/dwc/pcie-rcar-gen4.c | 1 +
> > > drivers/pci/controller/dwc/pcie-stm32-ep.c | 1 +
> > > drivers/pci/controller/dwc/pcie-tegra194.c | 1 +
> > > drivers/pci/controller/dwc/pcie-uniphier-ep.c | 2 +
> > > drivers/pci/endpoint/pci-epc-core.c | 8 +
> > > include/linux/pci-epc.h | 9 +
> > > include/linux/pci-epf.h | 27 +++
> > > 18 files changed, 285 insertions(+), 10 deletions(-)
> >
> > Hi Mani, Bjorn,
> >
> > Based on the feedback so far (thanks to Niklas and Frank), the design seems
> > to be converging. At this point, I would appreciate confirmation on the
> > following points before proceeding further.
> >
> > 1) Does the current (v8) approach for BAR subrange inbound mapping at the
> > EPC/core level look reasonable?
> >
Hi Mani,
Thanks for the question.
>
> In this series you didn't add a consumer of this subrange mapping, which I
> believe is the epf-vntb driver [1]. Even so I don't see a justification of why
> the BAR needs to be split into multiple subranges. Can you explain that?
Yes, the first consumer I have in mind is epf-vntb / remote eDMA-backed NTB
work referenced in [1].
The motivation for BAR subrange mapping is that some EP platforms
effectively have only two practically usable BARs, while needing multiple
logically independent inbound mapping.
For example, on Renesas R-Car Gen4 Spider, 64-bit BAR0 and BAR2 are the
only practically usable BARs, since BAR4 is only 256 bytes. epf-vntb
already needs two separate regions (config+spad and MW1 for the
data-plane), leaving no spare BAR. Adding ntb_msi requires yet another MW,
which simply does not fit unless an existing BAR is further divided.
In theory, some vNTB regions (e.g. config+spad and dynamically allocated
memory-backed MWs) could be tightly packed into a single physically
contiguous BAR region to barely make it work. However, it immediately makes
features mutually exclusive (e.g. ntb_msi / ntb_edma cannot coexist), and
the layout becomes extremely fragile.
Similarly, for remote eDMA-backed NTB transport, the host needs separate
inbound access to the eDMA register block and the LL regions, which are
distinct local address ranges. Without subrange mapping, the only choice is
unnatural layout (e.g. dedicating one BAR entirely to eDMA register block,
and another one to everything else that can be packed into a single locally
contiguous memory region), even when this is barely possible.
So while some cases might be made to work by aggressive packing, they are
already at the limit on platforms such as R-Car Spider. BAR subrange
mapping allows these features to be implemented in a straightforward,
loosely-coupled, and extensible way on platforms with severely constrained
BAR resources.
>
> > 2) From a process perspective, does it make sense to continue this as a PCI
> > endpoint subsystem-led series, with the dwc-specific changes layered on
> > top, or would you prefer a different split or ownership?
> >
>
> Is is OK to have both controller driver and endpoint changes in one series.
Understood, thank you.
Koichiro
>
> - Mani
>
> [1] https://lore.kernel.org/linux-pci/20260118135440.1958279-14-den@valinux.co.jp
>
> --
> மணிவண்ணன் சதாசிவம்
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support
2026-01-22 1:52 ` Koichiro Den
@ 2026-01-22 6:46 ` Manivannan Sadhasivam
2026-01-22 8:45 ` Niklas Cassel
1 sibling, 0 replies; 29+ messages in thread
From: Manivannan Sadhasivam @ 2026-01-22 6:46 UTC (permalink / raw)
To: Koichiro Den
Cc: bhelgaas, kwilczynski, cassel, frank.li, linux-pci, linux-kernel
On Thu, Jan 22, 2026 at 10:52:31AM +0900, Koichiro Den wrote:
> On Wed, Jan 21, 2026 at 09:08:34PM +0530, Manivannan Sadhasivam wrote:
> > On Mon, Jan 19, 2026 at 10:00:38PM +0900, Koichiro Den wrote:
> > > On Thu, Jan 15, 2026 at 05:49:23PM +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.
> > > >
> > > > - Patch 1/5 introduces dynamic_inbound_mapping feature bit. This can be
> > > > used as a safeguard to check whether a BAR can really be reconfigured
> > > > without clearing/resetting it.
> > > >
> > > > - Patch 2/5 introduces generic BAR subrange mapping support in the PCI
> > > > endpoint core.
> > > >
> > > > - Patch 3/5 advertises dynamic inbound mapping support via
> > > > DWC_EPC_COMMON_FEATURES for all DWC-based glue drivers.
> > > >
> > > > - Patch 4/5 adds an implementation for the DesignWare PCIe endpoint
> > > > controller using Address Match Mode IB iATU. It also advertises
> > > > subrange_mapping support via DWC_EPC_COMMON_FEATURES.
> > > >
> > > > - Patch 5/5 updates a documentation for pci_epc_set_bar().
> > > >
> > > --(snip)--
> > > > Koichiro Den (5):
> > > > PCI: endpoint: Add dynamic_inbound_mapping EPC feature
> > > > PCI: endpoint: Add BAR subrange mapping support
> > > > PCI: dwc: Advertise dynamic inbound mapping support
> > > > PCI: dwc: ep: Support BAR subrange inbound mapping via Address Match
> > > > Mode iATU
> > > > Documentation: PCI: endpoint: Clarify pci_epc_set_bar() usage
> > > >
> > > > Documentation/PCI/endpoint/pci-endpoint.rst | 24 +++
> > > > drivers/pci/controller/dwc/pci-dra7xx.c | 1 +
> > > > drivers/pci/controller/dwc/pci-imx6.c | 3 +
> > > > drivers/pci/controller/dwc/pci-keystone.c | 1 +
> > > > drivers/pci/controller/dwc/pcie-artpec6.c | 1 +
> > > > .../pci/controller/dwc/pcie-designware-ep.c | 203 +++++++++++++++++-
> > > > .../pci/controller/dwc/pcie-designware-plat.c | 1 +
> > > > drivers/pci/controller/dwc/pcie-designware.h | 8 +
> > > > drivers/pci/controller/dwc/pcie-dw-rockchip.c | 2 +
> > > > drivers/pci/controller/dwc/pcie-keembay.c | 1 +
> > > > drivers/pci/controller/dwc/pcie-qcom-ep.c | 1 +
> > > > drivers/pci/controller/dwc/pcie-rcar-gen4.c | 1 +
> > > > drivers/pci/controller/dwc/pcie-stm32-ep.c | 1 +
> > > > drivers/pci/controller/dwc/pcie-tegra194.c | 1 +
> > > > drivers/pci/controller/dwc/pcie-uniphier-ep.c | 2 +
> > > > drivers/pci/endpoint/pci-epc-core.c | 8 +
> > > > include/linux/pci-epc.h | 9 +
> > > > include/linux/pci-epf.h | 27 +++
> > > > 18 files changed, 285 insertions(+), 10 deletions(-)
> > >
> > > Hi Mani, Bjorn,
> > >
> > > Based on the feedback so far (thanks to Niklas and Frank), the design seems
> > > to be converging. At this point, I would appreciate confirmation on the
> > > following points before proceeding further.
> > >
> > > 1) Does the current (v8) approach for BAR subrange inbound mapping at the
> > > EPC/core level look reasonable?
> > >
>
> Hi Mani,
>
> Thanks for the question.
>
> >
> > In this series you didn't add a consumer of this subrange mapping, which I
> > believe is the epf-vntb driver [1]. Even so I don't see a justification of why
> > the BAR needs to be split into multiple subranges. Can you explain that?
>
> Yes, the first consumer I have in mind is epf-vntb / remote eDMA-backed NTB
> work referenced in [1].
>
> The motivation for BAR subrange mapping is that some EP platforms
> effectively have only two practically usable BARs, while needing multiple
> logically independent inbound mapping.
>
> For example, on Renesas R-Car Gen4 Spider, 64-bit BAR0 and BAR2 are the
> only practically usable BARs, since BAR4 is only 256 bytes. epf-vntb
> already needs two separate regions (config+spad and MW1 for the
> data-plane), leaving no spare BAR. Adding ntb_msi requires yet another MW,
> which simply does not fit unless an existing BAR is further divided.
>
> In theory, some vNTB regions (e.g. config+spad and dynamically allocated
> memory-backed MWs) could be tightly packed into a single physically
> contiguous BAR region to barely make it work. However, it immediately makes
> features mutually exclusive (e.g. ntb_msi / ntb_edma cannot coexist), and
> the layout becomes extremely fragile.
>
> Similarly, for remote eDMA-backed NTB transport, the host needs separate
> inbound access to the eDMA register block and the LL regions, which are
> distinct local address ranges. Without subrange mapping, the only choice is
> unnatural layout (e.g. dedicating one BAR entirely to eDMA register block,
> and another one to everything else that can be packed into a single locally
> contiguous memory region), even when this is barely possible.
>
> So while some cases might be made to work by aggressive packing, they are
> already at the limit on platforms such as R-Car Spider. BAR subrange
> mapping allows these features to be implemented in a straightforward,
> loosely-coupled, and extensible way on platforms with severely constrained
> BAR resources.
>
Thanks for the explanation, makes sense. When you respin this series, please
include it in cover letter and relevant commit message.
- Mani
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support
2026-01-22 1:52 ` Koichiro Den
2026-01-22 6:46 ` Manivannan Sadhasivam
@ 2026-01-22 8:45 ` Niklas Cassel
2026-01-22 14:02 ` Koichiro Den
1 sibling, 1 reply; 29+ messages in thread
From: Niklas Cassel @ 2026-01-22 8:45 UTC (permalink / raw)
To: Koichiro Den
Cc: Manivannan Sadhasivam, bhelgaas, kwilczynski, frank.li, linux-pci,
linux-kernel
Hello Koichiro,
On Thu, Jan 22, 2026 at 10:52:31AM +0900, Koichiro Den wrote:
> >
> > In this series you didn't add a consumer of this subrange mapping, which I
> > believe is the epf-vntb driver [1]. Even so I don't see a justification of why
> > the BAR needs to be split into multiple subranges. Can you explain that?
>
> Yes, the first consumer I have in mind is epf-vntb / remote eDMA-backed NTB
> work referenced in [1].
Another consumer in your RFC series is pci-epf-test, specifically:
[RFC PATCH v4 35/38] PCI: endpoint: pci-epf-test: Add pci_epf_test_next_free_bar() helper
[RFC PATCH v4 36/38] PCI: endpoint: pci-epf-test: Add remote eDMA-backed mode
[RFC PATCH v4 37/38] misc: pci_endpoint_test: Add remote eDMA transfer test mode
[RFC PATCH v4 38/38] selftests: pci_endpoint: Add remote eDMA transfer coverage
where the pci-epf-test exports the eDMA registers (using subranges) over a
BAR, and then in the host side driver, calls dw_edma_probe() on this subrange
and uses the host side driver to control the eDMA residing in the endpoint.
Most of your patches in [RFC PATCH v4 35/38] have NTB prefix.
Would it not be possible to simply include patches 35-38 in this series,
so we actually have a consumer, or do you need some other patches as well?
E.g., perhaps
[RFC PATCH v4 01/38] dmaengine: dw-edma: Export helper to get integrated register window
Would also be required?
Kind regards,
Niklas
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support
2026-01-22 8:45 ` Niklas Cassel
@ 2026-01-22 14:02 ` Koichiro Den
2026-01-22 15:17 ` Niklas Cassel
0 siblings, 1 reply; 29+ messages in thread
From: Koichiro Den @ 2026-01-22 14:02 UTC (permalink / raw)
To: Niklas Cassel
Cc: Manivannan Sadhasivam, bhelgaas, kwilczynski, frank.li, linux-pci,
linux-kernel
On Thu, Jan 22, 2026 at 09:45:13AM +0100, Niklas Cassel wrote:
> Hello Koichiro,
>
> On Thu, Jan 22, 2026 at 10:52:31AM +0900, Koichiro Den wrote:
> > >
> > > In this series you didn't add a consumer of this subrange mapping, which I
> > > believe is the epf-vntb driver [1]. Even so I don't see a justification of why
> > > the BAR needs to be split into multiple subranges. Can you explain that?
> >
> > Yes, the first consumer I have in mind is epf-vntb / remote eDMA-backed NTB
> > work referenced in [1].
>
> Another consumer in your RFC series is pci-epf-test, specifically:
> [RFC PATCH v4 35/38] PCI: endpoint: pci-epf-test: Add pci_epf_test_next_free_bar() helper
> [RFC PATCH v4 36/38] PCI: endpoint: pci-epf-test: Add remote eDMA-backed mode
> [RFC PATCH v4 37/38] misc: pci_endpoint_test: Add remote eDMA transfer test mode
> [RFC PATCH v4 38/38] selftests: pci_endpoint: Add remote eDMA transfer coverage
>
> where the pci-epf-test exports the eDMA registers (using subranges) over a
> BAR, and then in the host side driver, calls dw_edma_probe() on this subrange
> and uses the host side driver to control the eDMA residing in the endpoint.
>
> Most of your patches in [RFC PATCH v4 35/38] have NTB prefix.
>
> Would it not be possible to simply include patches 35-38 in this series,
> so we actually have a consumer, or do you need some other patches as well?
Sorry, I sent v9 just a few minutes after your email, without noticing it,
and then I was AFK for several hours.
>
> E.g., perhaps
> [RFC PATCH v4 01/38] dmaengine: dw-edma: Export helper to get integrated register window
>
> Would also be required?
Yes, please see the section "Patch layout" in:
https://lore.kernel.org/all/20260118135440.1958279-1-den@valinux.co.jp/
[...]
1. dw-edma / DesignWare EP helpers needed for remote embedded-DMA (export
register/LL windows, IRQ routing control, etc.)
Patch 01 : dmaengine: dw-edma: Export helper to get integrated register window
Patch 02 : dmaengine: dw-edma: Add per-channel interrupt routing control
Patch 03 : dmaengine: dw-edma: Poll completion when local IRQ handling is disabled
Patch 04 : dmaengine: dw-edma: Add notify-only channels support
Patch 05 : dmaengine: dw-edma: Add a helper to query linked-list region
Patches [RFC PATCH v4 01/38] through [RFC PATCH v4 05/38] are prerequisites
for the PCI test update, in addition to this "PCI: endpoint: BAR subrange
mapping support" series. Note that this series is described in "Kernel
base / dependencies" section of the large RFC series cover letter.
For this reason, those test cases cannot be included in this series.
Kind regards,
Koichiro
>
>
>
> Kind regards,
> Niklas
^ permalink raw reply [flat|nested] 29+ messages in thread* Re: [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support
2026-01-22 14:02 ` Koichiro Den
@ 2026-01-22 15:17 ` Niklas Cassel
2026-01-23 0:36 ` Koichiro Den
0 siblings, 1 reply; 29+ messages in thread
From: Niklas Cassel @ 2026-01-22 15:17 UTC (permalink / raw)
To: Koichiro Den
Cc: Manivannan Sadhasivam, bhelgaas, kwilczynski, frank.li, linux-pci,
linux-kernel
On Thu, Jan 22, 2026 at 11:02:42PM +0900, Koichiro Den wrote:
> On Thu, Jan 22, 2026 at 09:45:13AM +0100, Niklas Cassel wrote:
> > Hello Koichiro,
> >
> > On Thu, Jan 22, 2026 at 10:52:31AM +0900, Koichiro Den wrote:
> > > >
> > > > In this series you didn't add a consumer of this subrange mapping, which I
> > > > believe is the epf-vntb driver [1]. Even so I don't see a justification of why
> > > > the BAR needs to be split into multiple subranges. Can you explain that?
> > >
> > > Yes, the first consumer I have in mind is epf-vntb / remote eDMA-backed NTB
> > > work referenced in [1].
> >
> > Another consumer in your RFC series is pci-epf-test, specifically:
> > [RFC PATCH v4 35/38] PCI: endpoint: pci-epf-test: Add pci_epf_test_next_free_bar() helper
> > [RFC PATCH v4 36/38] PCI: endpoint: pci-epf-test: Add remote eDMA-backed mode
> > [RFC PATCH v4 37/38] misc: pci_endpoint_test: Add remote eDMA transfer test mode
> > [RFC PATCH v4 38/38] selftests: pci_endpoint: Add remote eDMA transfer coverage
> >
> > where the pci-epf-test exports the eDMA registers (using subranges) over a
> > BAR, and then in the host side driver, calls dw_edma_probe() on this subrange
> > and uses the host side driver to control the eDMA residing in the endpoint.
> >
> > Most of your patches in [RFC PATCH v4 35/38] have NTB prefix.
> >
> > Would it not be possible to simply include patches 35-38 in this series,
> > so we actually have a consumer, or do you need some other patches as well?
>
> Sorry, I sent v9 just a few minutes after your email, without noticing it,
> and then I was AFK for several hours.
>
> >
> > E.g., perhaps
> > [RFC PATCH v4 01/38] dmaengine: dw-edma: Export helper to get integrated register window
> >
> > Would also be required?
>
> Yes, please see the section "Patch layout" in:
> https://lore.kernel.org/all/20260118135440.1958279-1-den@valinux.co.jp/
>
> [...]
> 1. dw-edma / DesignWare EP helpers needed for remote embedded-DMA (export
> register/LL windows, IRQ routing control, etc.)
>
> Patch 01 : dmaengine: dw-edma: Export helper to get integrated register window
> Patch 02 : dmaengine: dw-edma: Add per-channel interrupt routing control
> Patch 03 : dmaengine: dw-edma: Poll completion when local IRQ handling is disabled
> Patch 04 : dmaengine: dw-edma: Add notify-only channels support
> Patch 05 : dmaengine: dw-edma: Add a helper to query linked-list region
>
> Patches [RFC PATCH v4 01/38] through [RFC PATCH v4 05/38] are prerequisites
> for the PCI test update, in addition to this "PCI: endpoint: BAR subrange
> mapping support" series. Note that this series is described in "Kernel
> base / dependencies" section of the large RFC series cover letter.
>
> For this reason, those test cases cannot be included in this series.
Ok, I assumed that some of those 5 patches were either eDMA optimizations
or things needed for NTB.
But if you need them even to just probe the eDMA driver on the host side
(using registers from the remote eDMA), then perhaps it is too much.
I was hoping that we could at least have a very simple test,
e.g. pci-endpoint-test only supporting READ or WRITE using remote eDMA.
At least then we would have a consumer part of this series.
pci-endpoint-test could have been further extended in a follow up series
if there were some eDMA driver patches that were needed for more complex
operations than a simple READ or WRITE using remote eDMA.
Kind regards,
Niklas
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support
2026-01-22 15:17 ` Niklas Cassel
@ 2026-01-23 0:36 ` Koichiro Den
2026-01-23 7:11 ` Koichiro Den
0 siblings, 1 reply; 29+ messages in thread
From: Koichiro Den @ 2026-01-23 0:36 UTC (permalink / raw)
To: Niklas Cassel
Cc: Manivannan Sadhasivam, bhelgaas, kwilczynski, frank.li, linux-pci,
linux-kernel
On Thu, Jan 22, 2026 at 04:17:51PM +0100, Niklas Cassel wrote:
> On Thu, Jan 22, 2026 at 11:02:42PM +0900, Koichiro Den wrote:
> > On Thu, Jan 22, 2026 at 09:45:13AM +0100, Niklas Cassel wrote:
> > > Hello Koichiro,
> > >
> > > On Thu, Jan 22, 2026 at 10:52:31AM +0900, Koichiro Den wrote:
> > > > >
> > > > > In this series you didn't add a consumer of this subrange mapping, which I
> > > > > believe is the epf-vntb driver [1]. Even so I don't see a justification of why
> > > > > the BAR needs to be split into multiple subranges. Can you explain that?
> > > >
> > > > Yes, the first consumer I have in mind is epf-vntb / remote eDMA-backed NTB
> > > > work referenced in [1].
> > >
> > > Another consumer in your RFC series is pci-epf-test, specifically:
> > > [RFC PATCH v4 35/38] PCI: endpoint: pci-epf-test: Add pci_epf_test_next_free_bar() helper
> > > [RFC PATCH v4 36/38] PCI: endpoint: pci-epf-test: Add remote eDMA-backed mode
> > > [RFC PATCH v4 37/38] misc: pci_endpoint_test: Add remote eDMA transfer test mode
> > > [RFC PATCH v4 38/38] selftests: pci_endpoint: Add remote eDMA transfer coverage
> > >
> > > where the pci-epf-test exports the eDMA registers (using subranges) over a
> > > BAR, and then in the host side driver, calls dw_edma_probe() on this subrange
> > > and uses the host side driver to control the eDMA residing in the endpoint.
> > >
> > > Most of your patches in [RFC PATCH v4 35/38] have NTB prefix.
> > >
> > > Would it not be possible to simply include patches 35-38 in this series,
> > > so we actually have a consumer, or do you need some other patches as well?
> >
> > Sorry, I sent v9 just a few minutes after your email, without noticing it,
> > and then I was AFK for several hours.
> >
> > >
> > > E.g., perhaps
> > > [RFC PATCH v4 01/38] dmaengine: dw-edma: Export helper to get integrated register window
> > >
> > > Would also be required?
> >
> > Yes, please see the section "Patch layout" in:
> > https://lore.kernel.org/all/20260118135440.1958279-1-den@valinux.co.jp/
> >
> > [...]
> > 1. dw-edma / DesignWare EP helpers needed for remote embedded-DMA (export
> > register/LL windows, IRQ routing control, etc.)
> >
> > Patch 01 : dmaengine: dw-edma: Export helper to get integrated register window
> > Patch 02 : dmaengine: dw-edma: Add per-channel interrupt routing control
> > Patch 03 : dmaengine: dw-edma: Poll completion when local IRQ handling is disabled
> > Patch 04 : dmaengine: dw-edma: Add notify-only channels support
> > Patch 05 : dmaengine: dw-edma: Add a helper to query linked-list region
> >
> > Patches [RFC PATCH v4 01/38] through [RFC PATCH v4 05/38] are prerequisites
> > for the PCI test update, in addition to this "PCI: endpoint: BAR subrange
> > mapping support" series. Note that this series is described in "Kernel
> > base / dependencies" section of the large RFC series cover letter.
> >
> > For this reason, those test cases cannot be included in this series.
>
> Ok, I assumed that some of those 5 patches were either eDMA optimizations
> or things needed for NTB.
>
> But if you need them even to just probe the eDMA driver on the host side
> (using registers from the remote eDMA), then perhaps it is too much.
>
> I was hoping that we could at least have a very simple test,
> e.g. pci-endpoint-test only supporting READ or WRITE using remote eDMA.
If we were to add a simple test in this series, I think it would be
something like BAR_SUBRANGE_TEST (beside BAR_TEST), which dynamically
triggers subrange mapping on the EP side if supported, and performs
read/write to those subranges. That would keep the test focused on
validating the subrange mapping functionality, and would not involve remote
eDMA. What do you think?
Koichiro
>
> At least then we would have a consumer part of this series.
>
> pci-endpoint-test could have been further extended in a follow up series
> if there were some eDMA driver patches that were needed for more complex
> operations than a simple READ or WRITE using remote eDMA.
>
>
> Kind regards,
> Niklas
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support
2026-01-23 0:36 ` Koichiro Den
@ 2026-01-23 7:11 ` Koichiro Den
2026-01-23 8:35 ` Niklas Cassel
0 siblings, 1 reply; 29+ messages in thread
From: Koichiro Den @ 2026-01-23 7:11 UTC (permalink / raw)
To: Niklas Cassel
Cc: Manivannan Sadhasivam, bhelgaas, kwilczynski, frank.li, linux-pci,
linux-kernel
On Fri, Jan 23, 2026 at 09:36:27AM +0900, Koichiro Den wrote:
> On Thu, Jan 22, 2026 at 04:17:51PM +0100, Niklas Cassel wrote:
> > On Thu, Jan 22, 2026 at 11:02:42PM +0900, Koichiro Den wrote:
> > > On Thu, Jan 22, 2026 at 09:45:13AM +0100, Niklas Cassel wrote:
> > > > Hello Koichiro,
> > > >
> > > > On Thu, Jan 22, 2026 at 10:52:31AM +0900, Koichiro Den wrote:
> > > > > >
> > > > > > In this series you didn't add a consumer of this subrange mapping, which I
> > > > > > believe is the epf-vntb driver [1]. Even so I don't see a justification of why
> > > > > > the BAR needs to be split into multiple subranges. Can you explain that?
> > > > >
> > > > > Yes, the first consumer I have in mind is epf-vntb / remote eDMA-backed NTB
> > > > > work referenced in [1].
> > > >
> > > > Another consumer in your RFC series is pci-epf-test, specifically:
> > > > [RFC PATCH v4 35/38] PCI: endpoint: pci-epf-test: Add pci_epf_test_next_free_bar() helper
> > > > [RFC PATCH v4 36/38] PCI: endpoint: pci-epf-test: Add remote eDMA-backed mode
> > > > [RFC PATCH v4 37/38] misc: pci_endpoint_test: Add remote eDMA transfer test mode
> > > > [RFC PATCH v4 38/38] selftests: pci_endpoint: Add remote eDMA transfer coverage
> > > >
> > > > where the pci-epf-test exports the eDMA registers (using subranges) over a
> > > > BAR, and then in the host side driver, calls dw_edma_probe() on this subrange
> > > > and uses the host side driver to control the eDMA residing in the endpoint.
> > > >
> > > > Most of your patches in [RFC PATCH v4 35/38] have NTB prefix.
> > > >
> > > > Would it not be possible to simply include patches 35-38 in this series,
> > > > so we actually have a consumer, or do you need some other patches as well?
> > >
> > > Sorry, I sent v9 just a few minutes after your email, without noticing it,
> > > and then I was AFK for several hours.
> > >
> > > >
> > > > E.g., perhaps
> > > > [RFC PATCH v4 01/38] dmaengine: dw-edma: Export helper to get integrated register window
> > > >
> > > > Would also be required?
> > >
> > > Yes, please see the section "Patch layout" in:
> > > https://lore.kernel.org/all/20260118135440.1958279-1-den@valinux.co.jp/
> > >
> > > [...]
> > > 1. dw-edma / DesignWare EP helpers needed for remote embedded-DMA (export
> > > register/LL windows, IRQ routing control, etc.)
> > >
> > > Patch 01 : dmaengine: dw-edma: Export helper to get integrated register window
> > > Patch 02 : dmaengine: dw-edma: Add per-channel interrupt routing control
> > > Patch 03 : dmaengine: dw-edma: Poll completion when local IRQ handling is disabled
> > > Patch 04 : dmaengine: dw-edma: Add notify-only channels support
> > > Patch 05 : dmaengine: dw-edma: Add a helper to query linked-list region
> > >
> > > Patches [RFC PATCH v4 01/38] through [RFC PATCH v4 05/38] are prerequisites
> > > for the PCI test update, in addition to this "PCI: endpoint: BAR subrange
> > > mapping support" series. Note that this series is described in "Kernel
> > > base / dependencies" section of the large RFC series cover letter.
> > >
> > > For this reason, those test cases cannot be included in this series.
> >
> > Ok, I assumed that some of those 5 patches were either eDMA optimizations
> > or things needed for NTB.
> >
> > But if you need them even to just probe the eDMA driver on the host side
> > (using registers from the remote eDMA), then perhaps it is too much.
> >
> > I was hoping that we could at least have a very simple test,
> > e.g. pci-endpoint-test only supporting READ or WRITE using remote eDMA.
>
> If we were to add a simple test in this series, I think it would be
> something like BAR_SUBRANGE_TEST (beside BAR_TEST), which dynamically
> triggers subrange mapping on the EP side if supported, and performs
> read/write to those subranges. That would keep the test focused on
> validating the subrange mapping functionality, and would not involve remote
> eDMA. What do you think?
One additional concern if we were to add a subrange mapping test is that
the EP-side pci-epf-test.c currently defines bar_size as follows:
static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
(see https://github.com/torvalds/linux/blob/v6.19-rc6/drivers/pci/endpoint/functions/pci-epf-test.c#L105)
The values 512 (BAR0/1) and 1024 (BAR2) are even smaller than the minimam
CX_ATU_MIN_REGION_SIZE (=4KB). This means that introducing
BAR_SUBRANGE_TEST would likely require one of the following:
(a). raising these hard-coded values
(b). reserving a dedicated BAR for the subrange mapping test
(c). limiting the testing to BAR3/4/5 if available (though, for
example, no BAR would pass the test on R-Car Spider which I'm
testing on, where BAR4 is fixed 256B).
I'm wondering whether there is a clean way to add a subrange mapping test
without significantly reshaping pci-epf-test.
Regards,
Koichiro
>
> Koichiro
>
> >
> > At least then we would have a consumer part of this series.
> >
> > pci-endpoint-test could have been further extended in a follow up series
> > if there were some eDMA driver patches that were needed for more complex
> > operations than a simple READ or WRITE using remote eDMA.
> >
> >
> > Kind regards,
> > Niklas
^ permalink raw reply [flat|nested] 29+ messages in thread* Re: [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support
2026-01-23 7:11 ` Koichiro Den
@ 2026-01-23 8:35 ` Niklas Cassel
2026-01-23 10:16 ` Niklas Cassel
` (2 more replies)
0 siblings, 3 replies; 29+ messages in thread
From: Niklas Cassel @ 2026-01-23 8:35 UTC (permalink / raw)
To: Koichiro Den
Cc: Manivannan Sadhasivam, bhelgaas, kwilczynski, frank.li, linux-pci,
linux-kernel
On Fri, Jan 23, 2026 at 04:11:08PM +0900, Koichiro Den wrote:
>
> One additional concern if we were to add a subrange mapping test is that
> the EP-side pci-epf-test.c currently defines bar_size as follows:
>
> static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
> (see https://github.com/torvalds/linux/blob/v6.19-rc6/drivers/pci/endpoint/functions/pci-epf-test.c#L105)
>
> The values 512 (BAR0/1) and 1024 (BAR2) are even smaller than the minimam
> CX_ATU_MIN_REGION_SIZE (=4KB). This means that introducing
> BAR_SUBRANGE_TEST would likely require one of the following:
>
> (a). raising these hard-coded values
> (b). reserving a dedicated BAR for the subrange mapping test
> (c). limiting the testing to BAR3/4/5 if available (though, for
> example, no BAR would pass the test on R-Car Spider which I'm
> testing on, where BAR4 is fixed 256B).
>
> I'm wondering whether there is a clean way to add a subrange mapping test
> without significantly reshaping pci-epf-test.
If you really want to implement a test, I suggest to look at:
pci_epf_test_enable_doorbell()
Which changes the address translation of a BAR dynamically.
pci_epf_test_disable_doorbell()
Which reverts back to the original translation.
pci_epf_test_enable_doorbell() simply does:
pci_epc_get_next_free_bar() to get a BAR, then writes the BAR
number in the in the pci-epf-test command registers, offset:
PCI_ENDPOINT_TEST_DB_BAR 0x34
(Which represent the offset in struct pci_epf_test, for
struct member db_bar)
However, the doorbells are most likely very small, so the chances
that reg->doorbell_offset will have a value that is smaller than
BAR size seems likely... but not guaranteed... and there is no
if (reg->doorbell_offset > epf->bar[bar].size)
goto err_doorbell_cleanup;
So it seems that this doorbell test just ignores the problem...
Frank, could you perhaps send a patch to add something like the above?
For your case... I guess we could bump the default sizes in pci-epf-test
if we want to. pci-epf-test already does:
if (epc_features->bar[bar].type == BAR_FIXED)
test_reg_size = epc_features->bar[bar].fixed_size;
else
test_reg_size = bar_size[bar];
So if there are fixed size BARs, that size will be respected, so I don't
think there should be any problem to increase the default sizes, if we
wanted to.
E.g. RK3588 has CX_ATU_MIN_REGION_SIZE 64k
So if we wanted to, a good number would be to have at least a few BARs of size
128k or larger (so there could be two submaps), since I assume that some other
DWC controllers might also have have 64k min alignment.
Having a test for this feature in pci-epf-test sounds really nice.
You could have even add a capability for this, see
pci_epf_test_set_capabilities().
if (epf_test->epc_features->subrange_mapping)
caps |= CAP_SUBRANGE_MAPPING;
Such that the host side driver (drivers/misc/pci_endpoint_test.c) could return
a distinct error code when this feature is not supported, such that
tools/testing/selftests/pci_endpoint/pci_endpoint_test.c could return SKIP when
that distinct error code is detected.
Kind regards,
Niklas
^ permalink raw reply [flat|nested] 29+ messages in thread* Re: [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support
2026-01-23 8:35 ` Niklas Cassel
@ 2026-01-23 10:16 ` Niklas Cassel
2026-01-23 14:08 ` Koichiro Den
2026-01-23 15:26 ` Niklas Cassel
2 siblings, 0 replies; 29+ messages in thread
From: Niklas Cassel @ 2026-01-23 10:16 UTC (permalink / raw)
To: Koichiro Den, frank.li
Cc: Manivannan Sadhasivam, bhelgaas, kwilczynski, linux-pci,
linux-kernel
On Fri, Jan 23, 2026 at 09:35:01AM +0100, Niklas Cassel wrote:
>
> pci_epf_test_enable_doorbell() simply does:
> pci_epc_get_next_free_bar() to get a BAR, then writes the BAR
> number in the in the pci-epf-test command registers, offset:
> PCI_ENDPOINT_TEST_DB_BAR 0x34
>
> However, the doorbells are most likely very small, so the chances
> that reg->doorbell_offset will have a value that is smaller than
> BAR size seems likely... but not guaranteed... and there is no
>
> if (reg->doorbell_offset > epf->bar[bar].size)
> goto err_doorbell_cleanup;
>
> So it seems that this doorbell test just ignores the problem...
>
> Frank, could you perhaps send a patch to add something like the above?
Frank, I guess the check would actually have to be something like:
if (reg->doorbell_offset + size of the doorbell > epf->bar[bar].size)
goto err_doorbell_cleanup;
Kind regards,
Niklas
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support
2026-01-23 8:35 ` Niklas Cassel
2026-01-23 10:16 ` Niklas Cassel
@ 2026-01-23 14:08 ` Koichiro Den
2026-01-23 14:57 ` Niklas Cassel
2026-01-23 15:26 ` Niklas Cassel
2 siblings, 1 reply; 29+ messages in thread
From: Koichiro Den @ 2026-01-23 14:08 UTC (permalink / raw)
To: Niklas Cassel
Cc: Manivannan Sadhasivam, bhelgaas, kwilczynski, frank.li, linux-pci,
linux-kernel
On Fri, Jan 23, 2026 at 09:35:01AM +0100, Niklas Cassel wrote:
> On Fri, Jan 23, 2026 at 04:11:08PM +0900, Koichiro Den wrote:
> >
> > One additional concern if we were to add a subrange mapping test is that
> > the EP-side pci-epf-test.c currently defines bar_size as follows:
> >
> > static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
> > (see https://github.com/torvalds/linux/blob/v6.19-rc6/drivers/pci/endpoint/functions/pci-epf-test.c#L105)
> >
> > The values 512 (BAR0/1) and 1024 (BAR2) are even smaller than the minimam
> > CX_ATU_MIN_REGION_SIZE (=4KB). This means that introducing
> > BAR_SUBRANGE_TEST would likely require one of the following:
> >
> > (a). raising these hard-coded values
> > (b). reserving a dedicated BAR for the subrange mapping test
> > (c). limiting the testing to BAR3/4/5 if available (though, for
> > example, no BAR would pass the test on R-Car Spider which I'm
> > testing on, where BAR4 is fixed 256B).
> >
> > I'm wondering whether there is a clean way to add a subrange mapping test
> > without significantly reshaping pci-epf-test.
>
> If you really want to implement a test, I suggest to look at:
Honestly, I hadn't thought of it until receiving your comment in this
thread, since [1] through [2] already cover the relevant testing. But on
second thought, that might be too heavy-weight, and instead adding just a
simple test for subrange mapping in this series, might suffice.
[1] https://lore.kernel.org/all/20260118135440.1958279-37-den@valinux.co.jp/
[2] https://lore.kernel.org/all/20260118135440.1958279-39-den@valinux.co.jp/
>
> pci_epf_test_enable_doorbell()
> Which changes the address translation of a BAR dynamically.
>
> pci_epf_test_disable_doorbell()
> Which reverts back to the original translation.
>
> pci_epf_test_enable_doorbell() simply does:
> pci_epc_get_next_free_bar() to get a BAR, then writes the BAR
> number in the in the pci-epf-test command registers, offset:
> PCI_ENDPOINT_TEST_DB_BAR 0x34
>
> (Which represent the offset in struct pci_epf_test, for
> struct member db_bar)
>
>
> However, the doorbells are most likely very small, so the chances
> that reg->doorbell_offset will have a value that is smaller than
> BAR size seems likely... but not guaranteed... and there is no
>
> if (reg->doorbell_offset > epf->bar[bar].size)
> goto err_doorbell_cleanup;
>
> So it seems that this doorbell test just ignores the problem...
>
> Frank, could you perhaps send a patch to add something like the above?
>
>
> For your case... I guess we could bump the default sizes in pci-epf-test
> if we want to. pci-epf-test already does:
>
> if (epc_features->bar[bar].type == BAR_FIXED)
> test_reg_size = epc_features->bar[bar].fixed_size;
> else
> test_reg_size = bar_size[bar];
>
> So if there are fixed size BARs, that size will be respected, so I don't
> think there should be any problem to increase the default sizes, if we
> wanted to.
>
> E.g. RK3588 has CX_ATU_MIN_REGION_SIZE 64k
>
> So if we wanted to, a good number would be to have at least a few BARs of size
> 128k or larger (so there could be two submaps), since I assume that some other
> DWC controllers might also have have 64k min alignment.
I'm not entirely sure whether it's really acceptable to bump the hard-coded
sizes for BAR0/1/2/3 (512, 512, 1024, 16384) to 128k, in other words,
whether there were any reasons behind choosing such small default numbers.
Let's see. I agree that 128k or larger should suffice for DWC-based
platforms (as you mentioned, testing with two submaps).
>
>
> Having a test for this feature in pci-epf-test sounds really nice.
> You could have even add a capability for this, see
> pci_epf_test_set_capabilities().
>
> if (epf_test->epc_features->subrange_mapping)
> caps |= CAP_SUBRANGE_MAPPING;
>
>
> Such that the host side driver (drivers/misc/pci_endpoint_test.c) could return
> a distinct error code when this feature is not supported, such that
> tools/testing/selftests/pci_endpoint/pci_endpoint_test.c could return SKIP when
> that distinct error code is detected.
That sounds nice.
Thanks,
Koichiro
>
>
> Kind regards,
> Niklas
^ permalink raw reply [flat|nested] 29+ messages in thread* Re: [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support
2026-01-23 14:08 ` Koichiro Den
@ 2026-01-23 14:57 ` Niklas Cassel
2026-01-26 14:26 ` Koichiro Den
0 siblings, 1 reply; 29+ messages in thread
From: Niklas Cassel @ 2026-01-23 14:57 UTC (permalink / raw)
To: Koichiro Den
Cc: Manivannan Sadhasivam, bhelgaas, kwilczynski, frank.li, linux-pci,
linux-kernel
On Fri, Jan 23, 2026 at 11:08:39PM +0900, Koichiro Den wrote:
> >
> > So if we wanted to, a good number would be to have at least a few BARs of size
> > 128k or larger (so there could be two submaps), since I assume that some other
> > DWC controllers might also have have 64k min alignment.
>
> I'm not entirely sure whether it's really acceptable to bump the hard-coded
> sizes for BAR0/1/2/3 (512, 512, 1024, 16384) to 128k, in other words,
> whether there were any reasons behind choosing such small default numbers.
> Let's see. I agree that 128k or larger should suffice for DWC-based
> platforms (as you mentioned, testing with two submaps).
When the PCI endpoint subsystem was created, most SoC were arm32, and many
of them had a very small PCIe aperture, like a few megabytes in total.
So if you were running two boards based on the same SoC, one as host and
one as endpoint, and perhaps you even had a PCIe switch on the host board,
you really did not want to have larger BARs than needed because it would
not fit inside the small address space dedicated to PCIe.
Additionally, the PCI endpoint subsystem allocates backing memory for
these BARs, some of these systems might have a very small amount of RAM.
However, I think that:
static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
512+512+1024+16384+131072+1048576 = 1 Mi + 146 Ki
Is still quite low...
When adding more and more features to the PCI endpoint subsystem,
these small BAR sizes will not be enough to evaluate new features.
E.g. for Resizable BARs, as per the PCIe specification, the minimum
possible size for a Resizable BAR is 1 MB.
I solved this by making sure that pci_epf_alloc_space() overrides
the requested size, to set it to 1MB, if BAR type is BAR_RESIZABLE:
https://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git/commit/?h=52132f3a63b33fd38ceef07392ed176db84d579f
If a few MB is too much for your host system, use a different host
system to test. (E.g. if you connect these arm32 boards to a PC,
and run pci_endpoint_test, larger BAR sizes would not be a problem,
assuming that the endpoint itself can allocate enough backing memory.)
So my suggestion is that we that we just bump the defaults...
I guess in worst case, if someone actually complains, I think a nice
solution would be do to like you are doing for vntb:
https://lore.kernel.org/linux-pci/20260118135440.1958279-34-den@valinux.co.jp/
i.e. pci-epf-test could have {barX_size} in configfs, one per BAR,
and then the user themselves could configure the BAR sizes that they
want to run pci-epf-test with, if the pci-epf-test default sizes are
not desirable, before starting the link. (Some tests like e.g. the
subrange mapping test should of course fail if there is not a single
BAR with BAR size larger than needed to test the feature.)
But if I were you, I would just bump the defaults, since the defaults
are currently overrided for BAR type FIXED_BAR and RESIZABLE_BAR anyway,
and just add the barX_size attributes in configfs if someone complains.
Kind regards,
Niklas
^ permalink raw reply [flat|nested] 29+ messages in thread* Re: [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support
2026-01-23 14:57 ` Niklas Cassel
@ 2026-01-26 14:26 ` Koichiro Den
2026-01-26 19:08 ` Niklas Cassel
0 siblings, 1 reply; 29+ messages in thread
From: Koichiro Den @ 2026-01-26 14:26 UTC (permalink / raw)
To: Niklas Cassel
Cc: Manivannan Sadhasivam, bhelgaas, kwilczynski, frank.li, linux-pci,
linux-kernel
On Fri, Jan 23, 2026 at 03:57:25PM +0100, Niklas Cassel wrote:
> On Fri, Jan 23, 2026 at 11:08:39PM +0900, Koichiro Den wrote:
> > >
> > > So if we wanted to, a good number would be to have at least a few BARs of size
> > > 128k or larger (so there could be two submaps), since I assume that some other
> > > DWC controllers might also have have 64k min alignment.
> >
> > I'm not entirely sure whether it's really acceptable to bump the hard-coded
> > sizes for BAR0/1/2/3 (512, 512, 1024, 16384) to 128k, in other words,
> > whether there were any reasons behind choosing such small default numbers.
> > Let's see. I agree that 128k or larger should suffice for DWC-based
> > platforms (as you mentioned, testing with two submaps).
>
> When the PCI endpoint subsystem was created, most SoC were arm32, and many
> of them had a very small PCIe aperture, like a few megabytes in total.
>
> So if you were running two boards based on the same SoC, one as host and
> one as endpoint, and perhaps you even had a PCIe switch on the host board,
> you really did not want to have larger BARs than needed because it would
> not fit inside the small address space dedicated to PCIe.
>
> Additionally, the PCI endpoint subsystem allocates backing memory for
> these BARs, some of these systems might have a very small amount of RAM.
>
> However, I think that:
> static size_t bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
>
> 512+512+1024+16384+131072+1048576 = 1 Mi + 146 Ki
>
> Is still quite low...
>
> When adding more and more features to the PCI endpoint subsystem,
> these small BAR sizes will not be enough to evaluate new features.
> E.g. for Resizable BARs, as per the PCIe specification, the minimum
> possible size for a Resizable BAR is 1 MB.
>
> I solved this by making sure that pci_epf_alloc_space() overrides
> the requested size, to set it to 1MB, if BAR type is BAR_RESIZABLE:
> https://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git/commit/?h=52132f3a63b33fd38ceef07392ed176db84d579f
>
> If a few MB is too much for your host system, use a different host
> system to test. (E.g. if you connect these arm32 boards to a PC,
> and run pci_endpoint_test, larger BAR sizes would not be a problem,
> assuming that the endpoint itself can allocate enough backing memory.)
>
> So my suggestion is that we that we just bump the defaults...
>
>
> I guess in worst case, if someone actually complains, I think a nice
> solution would be do to like you are doing for vntb:
> https://lore.kernel.org/linux-pci/20260118135440.1958279-34-den@valinux.co.jp/
>
> i.e. pci-epf-test could have {barX_size} in configfs, one per BAR,
> and then the user themselves could configure the BAR sizes that they
> want to run pci-epf-test with, if the pci-epf-test default sizes are
> not desirable, before starting the link. (Some tests like e.g. the
> subrange mapping test should of course fail if there is not a single
> BAR with BAR size larger than needed to test the feature.)
>
> But if I were you, I would just bump the defaults, since the defaults
> are currently overrided for BAR type FIXED_BAR and RESIZABLE_BAR anyway,
> and just add the barX_size attributes in configfs if someone complains.
That makes sense. I bumped the default sizes in v10, and if this turns out
to be a concern for some setups, I'll consider sending a patch to add such
configfs knobs. Thanks for sharing your thoughts.
(For forward reference, I sent v10 at:
https://lore.kernel.org/all/20260124145012.2794108-1-den@valinux.co.jp/)
Koichiro
>
>
> Kind regards,
> Niklas
^ permalink raw reply [flat|nested] 29+ messages in thread* Re: [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support
2026-01-26 14:26 ` Koichiro Den
@ 2026-01-26 19:08 ` Niklas Cassel
0 siblings, 0 replies; 29+ messages in thread
From: Niklas Cassel @ 2026-01-26 19:08 UTC (permalink / raw)
To: Koichiro Den
Cc: Manivannan Sadhasivam, bhelgaas, kwilczynski, frank.li, linux-pci,
linux-kernel
On Mon, Jan 26, 2026 at 11:26:53PM +0900, Koichiro Den wrote:
> On Fri, Jan 23, 2026 at 03:57:25PM +0100, Niklas Cassel wrote:
> >
> > I guess in worst case, if someone actually complains, I think a nice
> > solution would be do to like you are doing for vntb:
> > https://lore.kernel.org/linux-pci/20260118135440.1958279-34-den@valinux.co.jp/
> >
> > i.e. pci-epf-test could have {barX_size} in configfs, one per BAR,
> > and then the user themselves could configure the BAR sizes that they
> > want to run pci-epf-test with, if the pci-epf-test default sizes are
> > not desirable, before starting the link. (Some tests like e.g. the
> > subrange mapping test should of course fail if there is not a single
> > BAR with BAR size larger than needed to test the feature.)
> >
> > But if I were you, I would just bump the defaults, since the defaults
> > are currently overrided for BAR type FIXED_BAR and RESIZABLE_BAR anyway,
> > and just add the barX_size attributes in configfs if someone complains.
>
> That makes sense. I bumped the default sizes in v10, and if this turns out
> to be a concern for some setups, I'll consider sending a patch to add such
> configfs knobs. Thanks for sharing your thoughts.
FWIW, I think such configfs knobs are nice to have regardless of any new
features or not.
(I have personally changed the hardcoded values locally during testing many
times.)
So I decided to just send a patch that adds such configfs knobs:
https://lore.kernel.org/linux-pci/20260123180747.827357-2-cassel@kernel.org/
Kind regards,
Niklas
^ permalink raw reply [flat|nested] 29+ messages in thread
* Re: [PATCH v8 0/5] PCI: endpoint: BAR subrange mapping support
2026-01-23 8:35 ` Niklas Cassel
2026-01-23 10:16 ` Niklas Cassel
2026-01-23 14:08 ` Koichiro Den
@ 2026-01-23 15:26 ` Niklas Cassel
2 siblings, 0 replies; 29+ messages in thread
From: Niklas Cassel @ 2026-01-23 15:26 UTC (permalink / raw)
To: Koichiro Den
Cc: Manivannan Sadhasivam, bhelgaas, kwilczynski, frank.li, linux-pci,
linux-kernel
On Fri, Jan 23, 2026 at 09:35:01AM +0100, Niklas Cassel wrote:
> On Fri, Jan 23, 2026 at 04:11:08PM +0900, Koichiro Den wrote:
>
> pci_epf_test_enable_doorbell() simply does:
> pci_epc_get_next_free_bar() to get a BAR, then writes the BAR
> number in the in the pci-epf-test command registers, offset:
> PCI_ENDPOINT_TEST_DB_BAR 0x34
>
> (Which represent the offset in struct pci_epf_test, for
> struct member db_bar)
Correction: Which represents the offset in struct pci_epf_test_reg, for
struct member doorbell_bar.
Kind regards,
Niklas
^ permalink raw reply [flat|nested] 29+ messages in thread