Re: [PATCH v7 5/9] PCI: dwc: ep: Expose integrated eDMA resources via EPC aux-resource API

Frank Li <[email protected]>
Newsgroups dev.linux.lists.ntb,org.infradead.lists.linux-arm-kernel,org.infradead.lists.linux-rockchip,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pci
Message-ID <aZM_rCBkIzEztT1Q@lizhi-Precision-Tower-5810>
On Mon, Feb 16, 2026 at 01:38:43AM +0900, Koichiro Den wrote:
> Implement the EPC aux-resource API for DesignWare endpoint controllers
> with integrated eDMA.
>
> Report:
>   - DMA controller MMIO window (PCI_EPC_AUX_DMA_CTRL_MMIO)
>   - interrupt-emulation doorbell register (PCI_EPC_AUX_DOORBELL_MMIO),
>     including its Linux IRQ
>   - per-channel LL descriptor regions (PCI_EPC_AUX_DMA_CHAN_DESC)
>
> If the DMA controller MMIO window is already exposed via a
> platform-owned fixed BAR subregion, also provide the BAR number and
> offset so EPF drivers can reuse it without reprogramming the BAR.
>
> Signed-off-by: Koichiro Den <[email protected]>
> ---
Reviewed-by: Frank Li <[email protected]>
>  .../pci/controller/dwc/pcie-designware-ep.c   | 149 ++++++++++++++++++
>  1 file changed, 149 insertions(+)
>
> diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
> index 7e7844ff0f7e..ffd2797b7b81 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> @@ -808,6 +808,154 @@ dw_pcie_ep_get_features(struct pci_epc *epc, u8 func_no, u8 vfunc_no)
>  	return ep->ops->get_features(ep);
>  }
>
> +static const struct pci_epc_bar_rsvd_region *
> +dw_pcie_ep_find_bar_rsvd_region(struct dw_pcie_ep *ep,
> +				enum pci_epc_bar_rsvd_region_type type,
> +				enum pci_barno *bar,
> +				resource_size_t *bar_offset)
> +{
> +	const struct pci_epc_features *features;
> +	const struct pci_epc_bar_desc *bar_desc;
> +	const struct pci_epc_bar_rsvd_region *r;
> +	int i, j;
> +
> +	if (!ep->ops->get_features)
> +		return NULL;
> +
> +	features = ep->ops->get_features(ep);
> +	if (!features)
> +		return NULL;
> +
> +	for (i = BAR_0; i <= BAR_5; i++) {
> +		bar_desc = &features->bar[i];
> +
> +		if (!bar_desc->nr_rsvd_regions || !bar_desc->rsvd_regions)
> +			continue;
> +
> +		for (j = 0; j < bar_desc->nr_rsvd_regions; j++) {
> +			r = &bar_desc->rsvd_regions[j];
> +
> +			if (r->type != type)
> +				continue;
> +
> +			if (bar)
> +				*bar = i;
> +			if (bar_offset)
> +				*bar_offset = r->offset;
> +			return r;
> +		}
> +	}
> +
> +	return NULL;
> +}
> +
> +static int
> +dw_pcie_ep_get_aux_resources(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
> +			     struct pci_epc_aux_resource *resources,
> +			     int num_resources)
> +{
> +	struct dw_pcie_ep *ep = epc_get_drvdata(epc);
> +	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> +	const struct pci_epc_bar_rsvd_region *rsvd;
> +	struct dw_edma_chip *edma = &pci->edma;
> +	enum pci_barno dma_ctrl_bar = NO_BAR;
> +	int ll_cnt = 0, needed, idx = 0;
> +	resource_size_t db_offset = edma->db_offset;
> +	resource_size_t dma_ctrl_bar_offset = 0;
> +	resource_size_t dma_reg_size;
> +	unsigned int i;
> +
> +	if (!pci->edma_reg_size)
> +		return 0;
> +
> +	dma_reg_size = pci->edma_reg_size;
> +
> +	for (i = 0; i < edma->ll_wr_cnt; i++)
> +		if (edma->ll_region_wr[i].sz)
> +			ll_cnt++;
> +
> +	for (i = 0; i < edma->ll_rd_cnt; i++)
> +		if (edma->ll_region_rd[i].sz)
> +			ll_cnt++;
> +
> +	needed = 1 + ll_cnt + (db_offset != ~0 ? 1 : 0);
> +
> +	/* Count query mode */
> +	if (!resources || !num_resources)
> +		return needed;
> +
> +	if (num_resources < needed)
> +		return -ENOSPC;
> +
> +	rsvd = dw_pcie_ep_find_bar_rsvd_region(ep,
> +					       PCI_EPC_BAR_RSVD_DMA_CTRL_MMIO,
> +					       &dma_ctrl_bar,
> +					       &dma_ctrl_bar_offset);
> +	if (rsvd && rsvd->size < dma_reg_size)
> +		dma_reg_size = rsvd->size;
> +
> +	/* DMA register block */
> +	resources[idx++] = (struct pci_epc_aux_resource) {
> +		.type = PCI_EPC_AUX_DMA_CTRL_MMIO,
> +		.phys_addr = pci->edma_reg_phys,
> +		.size = dma_reg_size,
> +		.bar = dma_ctrl_bar,
> +		.bar_offset = dma_ctrl_bar_offset,
> +	};
> +
> +	/*
> +	 * For interrupt-emulation doorbells, report a standalone resource
> +	 * instead of bundling it into the DMA controller MMIO resource.
> +	 */
> +	if (db_offset != ~0) {
> +		if (dma_reg_size < sizeof(u32) ||
> +		    db_offset > dma_reg_size - sizeof(u32))
> +			return -EINVAL;
> +
> +		resources[idx++] = (struct pci_epc_aux_resource) {
> +			.type = PCI_EPC_AUX_DOORBELL_MMIO,
> +			.phys_addr = pci->edma_reg_phys + db_offset,
> +			.size = sizeof(u32),
> +			.bar = dma_ctrl_bar,
> +			.bar_offset = dma_ctrl_bar != NO_BAR ?
> +					dma_ctrl_bar_offset + db_offset : 0,
> +			.u.db_mmio = {
> +				.irq = edma->db_irq,
> +			},
> +		};
> +	}
> +
> +	/* One LL region per write channel */
> +	for (i = 0; i < edma->ll_wr_cnt; i++) {
> +		if (!edma->ll_region_wr[i].sz)
> +			continue;
> +
> +		resources[idx++] = (struct pci_epc_aux_resource) {
> +			.type = PCI_EPC_AUX_DMA_CHAN_DESC,
> +			.phys_addr = edma->ll_region_wr[i].paddr,
> +			.size = edma->ll_region_wr[i].sz,
> +			.bar = NO_BAR,
> +			.bar_offset = 0,
> +		};
> +	}
> +
> +	/* One LL region per read channel */
> +	for (i = 0; i < edma->ll_rd_cnt; i++) {
> +		if (!edma->ll_region_rd[i].sz)
> +			continue;
> +
> +		resources[idx++] = (struct pci_epc_aux_resource) {
> +			.type = PCI_EPC_AUX_DMA_CHAN_DESC,
> +			.phys_addr = edma->ll_region_rd[i].paddr,
> +			.size = edma->ll_region_rd[i].sz,
> +			.bar = NO_BAR,
> +			.bar_offset = 0,
> +		};
> +	}
> +
> +	return idx;
> +}
> +
>  static const struct pci_epc_ops epc_ops = {
>  	.write_header		= dw_pcie_ep_write_header,
>  	.set_bar		= dw_pcie_ep_set_bar,
> @@ -823,6 +971,7 @@ static const struct pci_epc_ops epc_ops = {
>  	.start			= dw_pcie_ep_start,
>  	.stop			= dw_pcie_ep_stop,
>  	.get_features		= dw_pcie_ep_get_features,
> +	.get_aux_resources	= dw_pcie_ep_get_aux_resources,
>  };
>
>  /**
> --
> 2.51.0
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.