irqchip/loongson-pch-msi: Switch to MSI parent domains
Remove the global PCI/MSI irqdomain implementation and provide the required MSI parent functionality by filling in msi_parent_ops, so the PCI/MSI code can detect the new parent and setup per-device MSI domains. Signed-off-by: Huacai Chen <chenhuacai@loongson.cn> Signed-off-by: Tianyang Zhang <zhangtianyang@loongson.cn> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lore.kernel.org/all/20240815112608.26925-2-zhangtianyang@loongson.cn
This commit is contained in:
parent
e68ac2b488
commit
0b3af7591d
@ -685,6 +685,7 @@ config LOONGSON_PCH_MSI
|
|||||||
depends on PCI
|
depends on PCI
|
||||||
default MACH_LOONGSON64
|
default MACH_LOONGSON64
|
||||||
select IRQ_DOMAIN_HIERARCHY
|
select IRQ_DOMAIN_HIERARCHY
|
||||||
|
select IRQ_MSI_LIB
|
||||||
select PCI_MSI
|
select PCI_MSI
|
||||||
help
|
help
|
||||||
Support for the Loongson PCH MSI Controller.
|
Support for the Loongson PCH MSI Controller.
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
#include "irq-msi-lib.h"
|
||||||
|
|
||||||
static int nr_pics;
|
static int nr_pics;
|
||||||
|
|
||||||
struct pch_msi_data {
|
struct pch_msi_data {
|
||||||
@ -27,26 +29,6 @@ struct pch_msi_data {
|
|||||||
|
|
||||||
static struct fwnode_handle *pch_msi_handle[MAX_IO_PICS];
|
static struct fwnode_handle *pch_msi_handle[MAX_IO_PICS];
|
||||||
|
|
||||||
static void pch_msi_mask_msi_irq(struct irq_data *d)
|
|
||||||
{
|
|
||||||
pci_msi_mask_irq(d);
|
|
||||||
irq_chip_mask_parent(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pch_msi_unmask_msi_irq(struct irq_data *d)
|
|
||||||
{
|
|
||||||
irq_chip_unmask_parent(d);
|
|
||||||
pci_msi_unmask_irq(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct irq_chip pch_msi_irq_chip = {
|
|
||||||
.name = "PCH PCI MSI",
|
|
||||||
.irq_mask = pch_msi_mask_msi_irq,
|
|
||||||
.irq_unmask = pch_msi_unmask_msi_irq,
|
|
||||||
.irq_ack = irq_chip_ack_parent,
|
|
||||||
.irq_set_affinity = irq_chip_set_affinity_parent,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int pch_msi_allocate_hwirq(struct pch_msi_data *priv, int num_req)
|
static int pch_msi_allocate_hwirq(struct pch_msi_data *priv, int num_req)
|
||||||
{
|
{
|
||||||
int first;
|
int first;
|
||||||
@ -85,12 +67,6 @@ static void pch_msi_compose_msi_msg(struct irq_data *data,
|
|||||||
msg->data = data->hwirq;
|
msg->data = data->hwirq;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct msi_domain_info pch_msi_domain_info = {
|
|
||||||
.flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
|
|
||||||
MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX,
|
|
||||||
.chip = &pch_msi_irq_chip,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct irq_chip middle_irq_chip = {
|
static struct irq_chip middle_irq_chip = {
|
||||||
.name = "PCH MSI",
|
.name = "PCH MSI",
|
||||||
.irq_mask = irq_chip_mask_parent,
|
.irq_mask = irq_chip_mask_parent,
|
||||||
@ -155,13 +131,31 @@ static void pch_msi_middle_domain_free(struct irq_domain *domain,
|
|||||||
static const struct irq_domain_ops pch_msi_middle_domain_ops = {
|
static const struct irq_domain_ops pch_msi_middle_domain_ops = {
|
||||||
.alloc = pch_msi_middle_domain_alloc,
|
.alloc = pch_msi_middle_domain_alloc,
|
||||||
.free = pch_msi_middle_domain_free,
|
.free = pch_msi_middle_domain_free,
|
||||||
|
.select = msi_lib_irq_domain_select,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PCH_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \
|
||||||
|
MSI_FLAG_USE_DEF_CHIP_OPS | \
|
||||||
|
MSI_FLAG_PCI_MSI_MASK_PARENT)
|
||||||
|
|
||||||
|
#define PCH_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \
|
||||||
|
MSI_FLAG_PCI_MSIX | \
|
||||||
|
MSI_FLAG_MULTI_PCI_MSI)
|
||||||
|
|
||||||
|
static struct msi_parent_ops pch_msi_parent_ops = {
|
||||||
|
.required_flags = PCH_MSI_FLAGS_REQUIRED,
|
||||||
|
.supported_flags = PCH_MSI_FLAGS_SUPPORTED,
|
||||||
|
.bus_select_mask = MATCH_PCI_MSI,
|
||||||
|
.bus_select_token = DOMAIN_BUS_NEXUS,
|
||||||
|
.prefix = "PCH-",
|
||||||
|
.init_dev_msi_info = msi_lib_init_dev_msi_info,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int pch_msi_init_domains(struct pch_msi_data *priv,
|
static int pch_msi_init_domains(struct pch_msi_data *priv,
|
||||||
struct irq_domain *parent,
|
struct irq_domain *parent,
|
||||||
struct fwnode_handle *domain_handle)
|
struct fwnode_handle *domain_handle)
|
||||||
{
|
{
|
||||||
struct irq_domain *middle_domain, *msi_domain;
|
struct irq_domain *middle_domain;
|
||||||
|
|
||||||
middle_domain = irq_domain_create_hierarchy(parent, 0, priv->num_irqs,
|
middle_domain = irq_domain_create_hierarchy(parent, 0, priv->num_irqs,
|
||||||
domain_handle,
|
domain_handle,
|
||||||
@ -174,14 +168,8 @@ static int pch_msi_init_domains(struct pch_msi_data *priv,
|
|||||||
|
|
||||||
irq_domain_update_bus_token(middle_domain, DOMAIN_BUS_NEXUS);
|
irq_domain_update_bus_token(middle_domain, DOMAIN_BUS_NEXUS);
|
||||||
|
|
||||||
msi_domain = pci_msi_create_irq_domain(domain_handle,
|
middle_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT;
|
||||||
&pch_msi_domain_info,
|
middle_domain->msi_parent_ops = &pch_msi_parent_ops;
|
||||||
middle_domain);
|
|
||||||
if (!msi_domain) {
|
|
||||||
pr_err("Failed to create PCI MSI domain\n");
|
|
||||||
irq_domain_remove(middle_domain);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user