mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 10:09:10 +02:00
PCI: endpoint: pci-ep-msi: Refactor doorbell allocation for new backends
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 <den@valinux.co.jp>
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Tested-by: Niklas Cassel <cassel@kernel.org>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20260414141514.1341429-5-den@valinux.co.jp
This commit is contained in:
parent
ec2075cfc6
commit
a3a079e5c5
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user