x86, devicetree, irq: Use common mechanism to support irqdomain

Now the ioapic driver provides a common interface to create irqdomain,
so replace the private implementation.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Michal Simek <monstr@monstr.eu>
Cc: Tony Lindgren <tony@atomide.com>
Link: http://lkml.kernel.org/r/1402302011-23642-29-git-send-email-jiang.liu@linux.intel.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
Jiang Liu 2014-06-09 16:19:57 +08:00 committed by Thomas Gleixner
parent 1b5d3e00d4
commit facd8fdb25
3 changed files with 73 additions and 154 deletions

View File

@ -26,12 +26,10 @@
extern int of_ioapic;
extern u64 initial_dtb;
extern void add_dtb(u64 data);
extern void x86_add_irq_domains(void);
void x86_of_pci_init(void);
void x86_dtb_init(void);
#else
static inline void add_dtb(u64 data) { }
static inline void x86_add_irq_domains(void) { }
static inline void x86_of_pci_init(void) { }
static inline void x86_dtb_init(void) { }
#define of_ioapic 0

View File

@ -166,10 +166,82 @@ static void __init dtb_lapic_setup(void)
#ifdef CONFIG_X86_IO_APIC
static unsigned int ioapic_id;
struct of_ioapic_type {
u32 out_type;
u32 trigger;
u32 polarity;
};
static struct of_ioapic_type of_ioapic_type[] =
{
{
.out_type = IRQ_TYPE_EDGE_RISING,
.trigger = IOAPIC_EDGE,
.polarity = 1,
},
{
.out_type = IRQ_TYPE_LEVEL_LOW,
.trigger = IOAPIC_LEVEL,
.polarity = 0,
},
{
.out_type = IRQ_TYPE_LEVEL_HIGH,
.trigger = IOAPIC_LEVEL,
.polarity = 1,
},
{
.out_type = IRQ_TYPE_EDGE_FALLING,
.trigger = IOAPIC_EDGE,
.polarity = 0,
},
};
static int ioapic_xlate(struct irq_domain *domain,
struct device_node *controller,
const u32 *intspec, u32 intsize,
irq_hw_number_t *out_hwirq, u32 *out_type)
{
struct io_apic_irq_attr attr;
struct of_ioapic_type *it;
u32 line, idx;
int rc;
if (WARN_ON(intsize < 2))
return -EINVAL;
line = intspec[0];
if (intspec[1] >= ARRAY_SIZE(of_ioapic_type))
return -EINVAL;
it = &of_ioapic_type[intspec[1]];
idx = (u32)(long)domain->host_data;
set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);
rc = io_apic_setup_irq_pin_once(irq_find_mapping(domain, line),
cpu_to_node(0), &attr);
if (rc)
return rc;
*out_hwirq = line;
*out_type = it->out_type;
return 0;
}
const struct irq_domain_ops ioapic_irq_domain_ops = {
.xlate = ioapic_xlate,
};
static void __init dtb_add_ioapic(struct device_node *dn)
{
struct resource r;
int ret;
struct ioapic_domain_cfg cfg = {
.type = IOAPIC_DOMAIN_DYNAMIC,
.ops = &ioapic_irq_domain_ops,
.dev = dn,
};
ret = of_address_to_resource(dn, 0, &r);
if (ret) {
@ -177,7 +249,7 @@ static void __init dtb_add_ioapic(struct device_node *dn)
dn->full_name);
return;
}
mp_register_ioapic(++ioapic_id, r.start, gsi_top, NULL);
mp_register_ioapic(++ioapic_id, r.start, gsi_top, &cfg);
}
static void __init dtb_ioapic_setup(void)
@ -239,148 +311,3 @@ void __init x86_dtb_init(void)
dtb_setup_hpet();
dtb_apic_setup();
}
#ifdef CONFIG_X86_IO_APIC
struct of_ioapic_type {
u32 out_type;
u32 trigger;
u32 polarity;
};
static struct of_ioapic_type of_ioapic_type[] =
{
{
.out_type = IRQ_TYPE_EDGE_RISING,
.trigger = IOAPIC_EDGE,
.polarity = 1,
},
{
.out_type = IRQ_TYPE_LEVEL_LOW,
.trigger = IOAPIC_LEVEL,
.polarity = 0,
},
{
.out_type = IRQ_TYPE_LEVEL_HIGH,
.trigger = IOAPIC_LEVEL,
.polarity = 1,
},
{
.out_type = IRQ_TYPE_EDGE_FALLING,
.trigger = IOAPIC_EDGE,
.polarity = 0,
},
};
static int ioapic_xlate(struct irq_domain *domain,
struct device_node *controller,
const u32 *intspec, u32 intsize,
irq_hw_number_t *out_hwirq, u32 *out_type)
{
struct io_apic_irq_attr attr;
struct of_ioapic_type *it;
u32 line, idx;
int rc;
if (WARN_ON(intsize < 2))
return -EINVAL;
line = intspec[0];
if (intspec[1] >= ARRAY_SIZE(of_ioapic_type))
return -EINVAL;
it = &of_ioapic_type[intspec[1]];
idx = (u32) domain->host_data;
set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);
rc = io_apic_setup_irq_pin_once(irq_find_mapping(domain, line),
cpu_to_node(0), &attr);
if (rc)
return rc;
*out_hwirq = line;
*out_type = it->out_type;
return 0;
}
const struct irq_domain_ops ioapic_irq_domain_ops = {
.xlate = ioapic_xlate,
};
static void dt_add_ioapic_domain(unsigned int ioapic_num,
struct device_node *np)
{
struct irq_domain *id;
struct mp_ioapic_gsi *gsi_cfg;
int ret;
int num, legacy_irqs = nr_legacy_irqs();
gsi_cfg = mp_ioapic_gsi_routing(ioapic_num);
num = gsi_cfg->gsi_end - gsi_cfg->gsi_base + 1;
id = irq_domain_add_linear(np, num, &ioapic_irq_domain_ops,
(void *)ioapic_num);
BUG_ON(!id);
if (gsi_cfg->gsi_base == 0) {
/*
* The first nr_legacy_irqs() irq descs are allocated in
* early_irq_init() and need just a mapping. The
* remaining irqs need both. All of them are preallocated
* and assigned so we can keep the 1:1 mapping which the ioapic
* is having.
*/
irq_domain_associate_many(id, 0, 0, legacy_irqs);
if (num > legacy_irqs) {
ret = irq_create_strict_mappings(id, legacy_irqs,
legacy_irqs, num - legacy_irqs);
if (ret)
pr_err("Error creating mapping for the "
"remaining IRQs: %d\n", ret);
}
irq_set_default_host(id);
} else {
ret = irq_create_strict_mappings(id, gsi_cfg->gsi_base, 0, num);
if (ret)
pr_err("Error creating IRQ mapping: %d\n", ret);
}
}
static void __init ioapic_add_ofnode(struct device_node *np)
{
struct resource r;
int i, ret;
ret = of_address_to_resource(np, 0, &r);
if (ret) {
printk(KERN_ERR "Failed to obtain address for %s\n",
np->full_name);
return;
}
for (i = 0; i < nr_ioapics; i++) {
if (r.start == mpc_ioapic_addr(i)) {
dt_add_ioapic_domain(i, np);
return;
}
}
printk(KERN_ERR "IOxAPIC at %s is not registered.\n", np->full_name);
}
void __init x86_add_irq_domains(void)
{
struct device_node *dp;
if (!of_have_populated_dt())
return;
for_each_node_with_property(dp, "interrupt-controller") {
if (of_device_is_compatible(dp, "intel,ce4100-ioapic"))
ioapic_add_ofnode(dp);
}
}
#else
void __init x86_add_irq_domains(void) { }
#endif

View File

@ -86,12 +86,6 @@ void __init init_IRQ(void)
{
int i;
/*
* We probably need a better place for this, but it works for
* now ...
*/
x86_add_irq_domains();
/*
* On cpu 0, Assign IRQ0_VECTOR..IRQ15_VECTOR's to IRQ 0..15.
* If these IRQ's are handled by legacy interrupt-controllers like PIC,