Re: [PATCH v8 6/9] PCI: endpoint: pci-ep-msi: Refactor doorbell allocation for new backends
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 | <aZSantK-I2pFAJ9d@lizhi-Precision-Tower-5810> |
On Tue, Feb 17, 2026 at 05:05:58PM +0900, Koichiro Den wrote: > Prepare pci-ep-msi for non-MSI doorbell backends. > > Factor MSI doorbell allocation into a helper and extend struct > pci_epf_doorbell_msg with: > > - irq_flags: required IRQ request flags (e.g. IRQF_SHARED for some > backends) > - type: doorbell backend type > - bar/offset: pre-exposed doorbell target location, if any > > Initialize these fields for the existing MSI-backed doorbell > implementation. > > Also add PCI_EPF_DOORBELL_EMBEDDED type, which is to be implemented in a > follow-up patch. > > No functional changes. > > Signed-off-by: Koichiro Den <[email protected]> > --- Reviewed-by: Frank Li <[email protected]> > Changes since v7: > - Switch to designated initializer and rely on implicit > zero-initialization. > > drivers/pci/endpoint/pci-ep-msi.c | 54 ++++++++++++++++++++++--------- > include/linux/pci-epf.h | 23 +++++++++++-- > 2 files changed, 60 insertions(+), 17 deletions(-) > > diff --git a/drivers/pci/endpoint/pci-ep-msi.c b/drivers/pci/endpoint/pci-ep-msi.c > index ad8a81d6ad77..50badffa9d72 100644 > --- a/drivers/pci/endpoint/pci-ep-msi.c > +++ b/drivers/pci/endpoint/pci-ep-msi.c > @@ -8,6 +8,7 @@ > > #include <linux/device.h> > #include <linux/export.h> > +#include <linux/interrupt.h> > #include <linux/irqdomain.h> > #include <linux/module.h> > #include <linux/msi.h> > @@ -35,23 +36,13 @@ static void pci_epf_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg) > pci_epc_put(epc); > } > > -int pci_epf_alloc_doorbell(struct pci_epf *epf, u16 num_db) > +static int pci_epf_alloc_doorbell_msi(struct pci_epf *epf, u16 num_db) > { > - struct pci_epc *epc = epf->epc; > + struct pci_epf_doorbell_msg *msg; > struct device *dev = &epf->dev; > + struct pci_epc *epc = epf->epc; > struct irq_domain *domain; > - void *msg; > - int ret; > - int i; > - > - /* TODO: Multi-EPF support */ > - if (list_first_entry_or_null(&epc->pci_epf, struct pci_epf, list) != epf) { > - dev_err(dev, "MSI doorbell doesn't support multiple EPF\n"); > - return -EINVAL; > - } > - > - if (epf->db_msg) > - return -EBUSY; > + int ret, i; > > domain = of_msi_map_get_device_domain(epc->dev.parent, 0, > DOMAIN_BUS_PLATFORM_MSI); > @@ -74,6 +65,12 @@ int pci_epf_alloc_doorbell(struct pci_epf *epf, u16 num_db) > if (!msg) > return -ENOMEM; > > + for (i = 0; i < num_db; i++) > + msg[i] = (struct pci_epf_doorbell_msg) { > + .type = PCI_EPF_DOORBELL_MSI, > + .bar = NO_BAR, > + }; > + > epf->num_db = num_db; > epf->db_msg = msg; > > @@ -90,13 +87,40 @@ int pci_epf_alloc_doorbell(struct pci_epf *epf, u16 num_db) > for (i = 0; i < num_db; i++) > epf->db_msg[i].virq = msi_get_virq(epc->dev.parent, i); > > + return 0; > +} > + > +int pci_epf_alloc_doorbell(struct pci_epf *epf, u16 num_db) > +{ > + struct pci_epc *epc = epf->epc; > + 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; > + > + dev_err(dev, "Failed to allocate doorbell: %d\n", ret); > return ret; > } > EXPORT_SYMBOL_GPL(pci_epf_alloc_doorbell); > > void pci_epf_free_doorbell(struct pci_epf *epf) > { > - platform_device_msi_free_irqs_all(epf->epc->dev.parent); > + if (!epf->db_msg) > + return; > + > + if (epf->db_msg[0].type == PCI_EPF_DOORBELL_MSI) > + platform_device_msi_free_irqs_all(epf->epc->dev.parent); > > kfree(epf->db_msg); > epf->db_msg = NULL; > diff --git a/include/linux/pci-epf.h b/include/linux/pci-epf.h > index 7737a7c03260..cd747447a1ea 100644 > --- a/include/linux/pci-epf.h > +++ b/include/linux/pci-epf.h > @@ -152,14 +152,33 @@ struct pci_epf_bar { > struct pci_epf_bar_submap *submap; > }; > > +enum pci_epf_doorbell_type { > + PCI_EPF_DOORBELL_MSI = 0, > + PCI_EPF_DOORBELL_EMBEDDED, > +}; > + > /** > * struct pci_epf_doorbell_msg - represents doorbell message > - * @msg: MSI message > - * @virq: IRQ number of this doorbell MSI message > + * @msg: Doorbell address/data pair to be mapped into BAR space. > + * For MSI-backed doorbells this is the MSI message, while for > + * "embedded" doorbells this represents an MMIO write that asserts > + * an interrupt on the EP side. > + * @virq: IRQ number of this doorbell message > + * @irq_flags: Required flags for request_irq()/request_threaded_irq(). > + * Callers may OR-in additional flags (e.g. IRQF_ONESHOT). > + * @type: Doorbell type. > + * @bar: BAR number where the doorbell target is already exposed to the RC > + * (NO_BAR if not) > + * @offset: offset within @bar for the doorbell target (valid iff > + * @bar != NO_BAR) > */ > struct pci_epf_doorbell_msg { > struct msi_msg msg; > int virq; > + unsigned long irq_flags; > + enum pci_epf_doorbell_type type; > + enum pci_barno bar; > + resource_size_t offset; > }; > > /** > -- > 2.51.0 >