Subject: Re: [PATCH v5 3/3] PCI: dwc: ep: Support BAR subrange inbound mapping via Address Match Mode iATU

From: Niklas Cassel <[email-masked]>
Date: Thu, 8 Jan 2026 21:55:27 +0100

Hello Koichiro,

On Fri, Jan 09, 2026 at 02:24:03AM +0900, Koichiro Den wrote:

(snip)

> +/* 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;
> +	struct dw_pcie_ib_map *new;
> +	u64 size, off, base;
> +	unsigned long flags;
> +	int free_win, ret;
> +	unsigned int i;
> +
> +	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;
> +	}

Sorry for giving additional review comments.

But there is one thing that I might not be so obvious for someone just
reading this source. How is this API supposed to be used in practice?

Most DWC-based controllers are not hotplug capable.

That means that we must boot the EP, create the EPF symlink in configfs,
and start link training by writing to configfs, before starting the host.

dw_pcie_ep_ib_atu_addr() reads the PCI address that the host has assigned
to the BAR, and returns an error if the host has not already assigned a
PCI addres to the BAR.

Does that mean that the usage of this API will be something like:

1) set_bar() ## using BAR match mode, since BAR match mode can write
   the BAR mask to define a BAR size, so that the host can assign a
   PCI address to the BAR.

2) start() ## start link

3) link up

4) wait for some special command, perhaps NTB_EPF_COMMAND
CMD_CONFIGURE_DOORBELL or NTB_EPF_COMMAND CMD_CONFIGURE_MW

5) set_bar() ## using Address match mode. Because address match mode
   requires that the host has assigned a PCI address to the BAR, we
   can only change the mapping for a BAR after the host has assigned
   PCI addresses for all bars.

Perhaps you should add some text to:
Documentation/PCI/endpoint/pci-endpoint.rst

Because right now the documentation for pci_epc_set_bar() says:

   The PCI endpoint function driver should use pci_epc_set_bar() to configure
   the Base Address Register in order for the host to assign PCI addr space.
   Register space of the function driver is usually configured
   using this API.

So it is obviously meant to be called *before* the host assigns a PCI
address for the BAR. Now with submap ranges, it appears that it has to
be called *after* the host assigned a PCI address for the BAR.

So I can only assume that you will call set_bar() twice.
Once with BAR match mode, and then a second time with address map mode.

It might be obvious to you, but I think it makes sense to also have some
kind of documentation for this feature.

Kind regards,
Niklas