From: Koichiro Den Date: Tue, 14 Apr 2026 14:15:12 +0000 (+0900) Subject: PCI: endpoint: pci-epf-vntb: Reuse pre-exposed doorbells and IRQ flags X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=0c3f82a584082a0d2e09b65e0a2e9cdcf9046d0d;p=thirdparty%2Flinux.git PCI: endpoint: pci-epf-vntb: Reuse pre-exposed doorbells and IRQ flags 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. Make pci-epf-vntb work with platform-defined or embedded doorbell backends without exposing backend-specific details to the consumer layer. Signed-off-by: Koichiro Den Signed-off-by: Manivannan Sadhasivam Signed-off-by: Bjorn Helgaas Tested-by: Niklas Cassel Reviewed-by: Frank Li Link: https://patch.msgid.link/20260414141514.1341429-6-den@valinux.co.jp --- diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c index 2256c3062b1ae..b493a300da4dc 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_duplicated(const struct pci_epf *epf, unsigned int idx) +{ + unsigned int i; + + for (i = 0; i < idx; i++) + if (epf->db_msg[i].virq == epf->db_msg[idx].virq) + return true; + + return false; +} + 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_duplicated(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_duplicated(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_duplicated(ntb->epf, i)) + continue; free_irq(ntb->epf->db_msg[i].virq, ntb); + } } if (ntb->epf->db_msg)