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

Koichiro Den den at valinux.co.jp
Mon Feb 16 17:39:05 PST 2026


On Mon, Feb 16, 2026 at 11:14:58AM -0500, Frank Li wrote:
> 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 <den at valinux.co.jp>
> > ---
> >  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.

Sounds reasonable. I was trying to keep the code minimal, but your suggestion
makes it more future-proof and avoids exposing PCI_EPF_DOORBELL_EMBEDDED details
to this consumer layer. I'll adjust this part accordingly.

THanks for the review,
Koichiro

> 
> 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
> >



More information about the Linux-rockchip mailing list