irqchip: GICv3: Convert to domain hierarchy

In order to start supporting stacked domains, convert the GICv3
code base to the new domain hierarchy framework, which mostly
amounts to supporting the new alloc/free callbacks.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Link: https://lkml.kernel.org/r/1416839720-18400-3-git-send-email-marc.zyngier@arm.com
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
This commit is contained in:
Marc Zyngier 2014-11-24 14:35:09 +00:00 committed by Jason Cooper
parent be091d468a
commit 443acc4f37
2 changed files with 38 additions and 5 deletions

View File

@ -14,6 +14,7 @@ config ARM_GIC_V3
bool bool
select IRQ_DOMAIN select IRQ_DOMAIN
select MULTI_IRQ_HANDLER select MULTI_IRQ_HANDLER
select IRQ_DOMAIN_HIERARCHY
config ARM_NVIC config ARM_NVIC
bool bool

View File

@ -594,14 +594,14 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
/* PPIs */ /* PPIs */
if (hw < 32) { if (hw < 32) {
irq_set_percpu_devid(irq); irq_set_percpu_devid(irq);
irq_set_chip_and_handler(irq, &gic_chip, irq_domain_set_info(d, irq, hw, &gic_chip, d->host_data,
handle_percpu_devid_irq); handle_percpu_devid_irq, NULL, NULL);
set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN); set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
} }
/* SPIs */ /* SPIs */
if (hw >= 32 && hw < gic_data.irq_nr) { if (hw >= 32 && hw < gic_data.irq_nr) {
irq_set_chip_and_handler(irq, &gic_chip, irq_domain_set_info(d, irq, hw, &gic_chip, d->host_data,
handle_fasteoi_irq); handle_fasteoi_irq, NULL, NULL);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
} }
irq_set_chip_data(irq, d->host_data); irq_set_chip_data(irq, d->host_data);
@ -633,9 +633,41 @@ static int gic_irq_domain_xlate(struct irq_domain *d,
return 0; return 0;
} }
static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
unsigned int nr_irqs, void *arg)
{
int i, ret;
irq_hw_number_t hwirq;
unsigned int type = IRQ_TYPE_NONE;
struct of_phandle_args *irq_data = arg;
ret = gic_irq_domain_xlate(domain, irq_data->np, irq_data->args,
irq_data->args_count, &hwirq, &type);
if (ret)
return ret;
for (i = 0; i < nr_irqs; i++)
gic_irq_domain_map(domain, virq + i, hwirq + i);
return 0;
}
static void gic_irq_domain_free(struct irq_domain *domain, unsigned int virq,
unsigned int nr_irqs)
{
int i;
for (i = 0; i < nr_irqs; i++) {
struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);
irq_set_handler(virq + i, NULL);
irq_domain_reset_irq_data(d);
}
}
static const struct irq_domain_ops gic_irq_domain_ops = { static const struct irq_domain_ops gic_irq_domain_ops = {
.map = gic_irq_domain_map,
.xlate = gic_irq_domain_xlate, .xlate = gic_irq_domain_xlate,
.alloc = gic_irq_domain_alloc,
.free = gic_irq_domain_free,
}; };
static int __init gic_of_init(struct device_node *node, struct device_node *parent) static int __init gic_of_init(struct device_node *node, struct device_node *parent)