Re: [PATCH v8 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 | <tflsioixiwtcoq7dfnfhllcmtimh5xlfmhzc34vw5gb3kqukvn@nka53jttuyec> |
On Tue, Feb 17, 2026 at 11:54:29AM -0500, Frank Li wrote: > On Tue, Feb 17, 2026 at 05:05:59PM +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. > > > > Multiple doorbells may share the same Linux IRQ. Avoid duplicate > > request_irq() calls by requesting each unique virq once. > > > > This makes pci-epf-vntb work with platform-defined or embedded doorbell > > Nit: Make pci-epf-vntb work with ... > > > backends without exposing backend-specific details to the consumer > > layer. > > > > Signed-off-by: Koichiro Den <[email protected]> > > --- > > Changes since v7: > > - Deduplicate request_irq()/free_irq() calls based on virq (shared > > IRQ) rather than doorbell type. > > > > drivers/pci/endpoint/functions/pci-epf-vntb.c | 61 ++++++++++++++++++- > > 1 file changed, 58 insertions(+), 3 deletions(-) > > > > diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c > > index 52cf442ca1d9..b1e8414c4e43 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; > > > > @@ -517,6 +522,17 @@ static int epf_ntb_configure_interrupt(struct epf_ntb *ntb) > > return 0; > > } > > > > +static bool epf_ntb_db_irq_is_first(const struct pci_epf *epf, unsigned int idx) > > epf_ntb_db_irq_is_duplicated() look better, below 'if' needn't ! Agreed. I'll rename it and update the usage in the next revision. Thanks for the review, Koichiro > > Frank > > > +{ > > + unsigned int i; > > + > > + for (i = 0; i < idx; i++) > > + if (epf->db_msg[i].virq == epf->db_msg[idx].virq) > > + return false; > > + > > + return true; > > +} > > + > > static int epf_ntb_db_bar_init_msi_doorbell(struct epf_ntb *ntb, > > struct pci_epf_bar *db_bar, > > const struct pci_epc_features *epc_features, > > @@ -533,9 +549,24 @@ static int epf_ntb_db_bar_init_msi_doorbell(struct epf_ntb *ntb, > > if (ret) > > return ret; > > > > + /* > > + * 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 (req = 0; req < ntb->db_count; req++) { > > + /* Avoid requesting duplicate handlers */ > > + if (!epf_ntb_db_irq_is_first(epf, req)) > > + continue; > > + > > 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, > > @@ -545,6 +576,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; > > @@ -591,6 +638,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; > > @@ -598,9 +646,13 @@ static int epf_ntb_db_bar_init_msi_doorbell(struct epf_ntb *ntb, > > return 0; > > > > err_free_irq: > > - for (req--; req >= 0; req--) > > + for (req--; req >= 0; req--) { > > + if (!epf_ntb_db_irq_is_first(epf, req)) > > + continue; > > free_irq(epf->db_msg[req].virq, ntb); > > + } > > > > +err_free_doorbell: > > pci_epf_free_doorbell(ntb->epf); > > return ret; > > } > > @@ -666,8 +718,11 @@ static void epf_ntb_db_bar_clear(struct epf_ntb *ntb) > > if (ntb->msi_doorbell) { > > int i; > > > > - for (i = 0; i < ntb->db_count; i++) > > + for (i = 0; i < ntb->db_count; i++) { > > + if (!epf_ntb_db_irq_is_first(ntb->epf, i)) > > + continue; > > free_irq(ntb->epf->db_msg[i].virq, ntb); > > + } > > } > > > > if (ntb->epf->db_msg) > > -- > > 2.51.0 > >