Re: [PATCH v7 7/9] PCI: endpoint: pci-epf-vntb: Reuse pre-exposed doorbells and IRQ flags

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 <aZNCgkddVkDbtO_c@lizhi-Precision-Tower-5810>
On Mon, Feb 16, 2026 at 01:38:45AM +0900, Koichiro Den wrote:
> Support doorbell backends where the doorbell target is already exposed
> via a platform-owned fixed BAR mapping and/or where the doorbell IRQ
> must be requested with specific flags.
>
> When pci_epf_alloc_doorbell() provides db_msg[].bar/offset, reuse the
> pre-exposed BAR window and skip programming a new inbound mapping. Also
> honor db_msg[].irq_flags when requesting the doorbell IRQ.
>
> For embedded doorbells (e.g. interrupt-emulation), multiple doorbells
> may share a single address/data pair and a single Linux IRQ. Avoid
> requesting duplicate handlers by requesting only one IRQ in that case.
>
> Signed-off-by: Koichiro Den <[email protected]>
> ---
>  drivers/pci/endpoint/functions/pci-epf-vntb.c | 57 +++++++++++++++++--
>  1 file changed, 52 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c
> index 20efa27325f1..39ba4d6b7d8d 100644
> --- a/drivers/pci/endpoint/functions/pci-epf-vntb.c
> +++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c
> @@ -134,6 +134,11 @@ struct epf_ntb {
>  	u16 vntb_vid;
>
>  	bool linkup;
> +
> +	/*
> +	 * True when doorbells are interrupt-driven (MSI or embedded), false
> +	 * when polled.
> +	 */
>  	bool msi_doorbell;
>  	u32 spad_size;
>
> @@ -523,7 +528,7 @@ static int epf_ntb_db_bar_init_msi_doorbell(struct epf_ntb *ntb,
>  					    enum pci_barno barno)
>  {
>  	struct pci_epf *epf = ntb->epf;
> -	unsigned int req;
> +	unsigned int req, cnt;
>  	dma_addr_t low, high;
>  	struct msi_msg *msg;
>  	size_t sz;
> @@ -534,9 +539,29 @@ static int epf_ntb_db_bar_init_msi_doorbell(struct epf_ntb *ntb,
>  	if (ret)
>  		return ret;
>
> -	for (req = 0; req < ntb->db_count; req++) {
> +	/*
> +	 * The doorbell target may already be exposed by a platform-owned fixed
> +	 * BAR. In that case, we must reuse it and the requested db_bar must
> +	 * match.
> +	 */
> +	if (epf->db_msg[0].bar != NO_BAR && epf->db_msg[0].bar != barno) {
> +		ret = -EINVAL;
> +		goto err_free_doorbell;
> +	}
> +
> +	/*
> +	 * For PCI_EPF_DOORBELL_EMBEDDED, the backend may provide a single MMIO
> +	 * address/data pair and a single Linux IRQ even if multiple doorbells
> +	 * were requested. Avoid requesting duplicate handlers in that case.
> +	 */
> +	cnt = ntb->db_count;
> +	if (epf->db_msg[0].type == PCI_EPF_DOORBELL_EMBEDDED)
> +		cnt = 1;

Most SoC combine all DMA channel to one irqs. But it should be not
neccessary for SoC design. It is possible each DMA channel have dedicate
irq number. I suggest check irq, instead of type.

Frank
> +
> +	for (req = 0; req < cnt; req++) {
>  		ret = request_irq(epf->db_msg[req].virq, epf_ntb_doorbell_handler,
> -				  0, "pci_epf_vntb_db", ntb);
> +				  epf->db_msg[req].irq_flags, "pci_epf_vntb_db",
> +				  ntb);
>
>  		if (ret) {
>  			dev_err(&epf->dev,
> @@ -546,6 +571,22 @@ static int epf_ntb_db_bar_init_msi_doorbell(struct epf_ntb *ntb,
>  		}
>  	}
>
> +	if (epf->db_msg[0].bar != NO_BAR) {
> +		for (i = 0; i < ntb->db_count; i++) {
> +			msg = &epf->db_msg[i].msg;
> +
> +			if (epf->db_msg[i].bar != barno) {
> +				ret = -EINVAL;
> +				goto err_free_irq;
> +			}
> +
> +			ntb->reg->db_data[i] = msg->data;
> +			ntb->reg->db_offset[i] = epf->db_msg[i].offset;
> +		}
> +		goto out;
> +	}
> +
> +	/* Program inbound mapping for the doorbell */
>  	msg = &epf->db_msg[0].msg;
>
>  	high = 0;
> @@ -592,6 +633,7 @@ static int epf_ntb_db_bar_init_msi_doorbell(struct epf_ntb *ntb,
>  		ntb->reg->db_offset[i] = offset;
>  	}
>
> +out:
>  	ntb->reg->db_entry_size = 0;
>
>  	ntb->msi_doorbell = true;
> @@ -602,6 +644,7 @@ static int epf_ntb_db_bar_init_msi_doorbell(struct epf_ntb *ntb,
>  	while (req)
>  		free_irq(epf->db_msg[--req].virq, ntb);
>
> +err_free_doorbell:
>  	pci_epf_free_doorbell(ntb->epf);
>  	return ret;
>  }
> @@ -665,9 +708,13 @@ static void epf_ntb_db_bar_clear(struct epf_ntb *ntb)
>  	enum pci_barno barno;
>
>  	if (ntb->msi_doorbell) {
> -		int i;
> +		unsigned int cnt = ntb->db_count;
> +		unsigned int i;
>
> -		for (i = 0; i < ntb->db_count; i++)
> +		if (ntb->epf->db_msg[0].type == PCI_EPF_DOORBELL_EMBEDDED)
> +			cnt = 1;
> +
> +		for (i = 0; i < cnt; i++)
>  			free_irq(ntb->epf->db_msg[i].virq, ntb);
>  	}
>
> --
> 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.