[PATCH 3/3] PCI: endpoint: pci-ep-msi: Let non-first EPFs use embedded doorbells
Koichiro Den <[email protected]> Wed, 29 Jul 2026 02:23:06 +0900
| Newsgroups | dev.linux.lists.ntb,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pci |
|---|---|
| Message-ID | <[email protected]> |
pci_epf_alloc_doorbell() rejects every EPF that is not the first one attached to the EPC because the MSI-backed path can populate doorbell messages only for that EPF. This also prevents non-first EPFs from using the embedded doorbell backend. Keep the MSI-backed path limited to the first attached EPF. Let non-first EPFs skip it and try the embedded doorbell directly. The embedded IRQ is exclusive, so a second embedded user fails to request the IRQ instead of receiving another EPF's notifications. Signed-off-by: Koichiro Den <[email protected]> --- drivers/pci/endpoint/pci-ep-msi.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/drivers/pci/endpoint/pci-ep-msi.c b/drivers/pci/endpoint/pci-ep-msi.c index a123a189b4e6..5ea7eef9794f 100644 --- a/drivers/pci/endpoint/pci-ep-msi.c +++ b/drivers/pci/endpoint/pci-ep-msi.c @@ -199,28 +199,31 @@ static int pci_epf_alloc_doorbell_msi(struct pci_epf *epf, u16 num_db) int pci_epf_alloc_doorbell(struct pci_epf *epf, u16 num_db) { struct pci_epc *epc = epf->epc; + struct pci_epf *first_epf; struct device *dev = &epf->dev; int ret; - /* TODO: Multi-EPF support */ - if (list_first_entry_or_null(&epc->pci_epf, struct pci_epf, list) != epf) { - dev_err(dev, "Doorbell doesn't support multiple EPF\n"); - return -EINVAL; - } - if (epf->db_msg) return -EBUSY; - ret = pci_epf_alloc_doorbell_msi(epf, num_db); - if (!ret) - return 0; - /* - * Fall back to embedded doorbell only when platform MSI is unavailable - * for this EPC. + * The MSI-backed doorbell path currently targets the first EPF attached + * to the EPC. Let non-first EPFs try the embedded doorbell instead. */ - if (ret != -ENODEV) - return ret; + first_epf = list_first_entry_or_null(&epc->pci_epf, struct pci_epf, + list); + if (first_epf == epf) { + ret = pci_epf_alloc_doorbell_msi(epf, num_db); + if (!ret) + return 0; + + /* + * Fall back to embedded doorbell only when platform MSI is + * unavailable for this EPC. + */ + if (ret != -ENODEV) + return ret; + } ret = pci_epf_alloc_doorbell_embedded(epf, num_db); if (ret) { -- 2.51.0