Re: [PATCH v7 7/9] PCI: endpoint: pci-epf-vntb: Reuse pre-exposed doorbells and IRQ flags
Koichiro Den <[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 | <6yjsrg55aqnxvdotyhjalx5uwytizjxsh3xk44smdm3f46zyc6@zwk25sgezz5n> |
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 <[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. 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 > >