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 >