@@ -249,30 +249,20 @@ static void gic_set_irq_properties(unsigned int irq, bool_t level,
spin_unlock(&gic.lock);
}
-/* Program the GIC to route an interrupt */
-static int gic_route_irq(unsigned int irq, bool_t level,
- const cpumask_t *cpu_mask, unsigned int priority)
+/* Program the GIC to route an interrupt to the host (i.e. Xen)
+ * - needs to be called with desc.lock held
+ */
+void gic_route_irq_to_xen(struct irq_desc *desc, bool_t level,
+ const cpumask_t *cpu_mask, unsigned int priority)
{
- struct irq_desc *desc = irq_to_desc(irq);
- unsigned long flags;
-
ASSERT(priority <= 0xff); /* Only 8 bits of priority */
- ASSERT(irq < gic.lines); /* Can't route interrupts that don't exist */
-
- if ( desc->action != NULL )
- return -EBUSY;
-
- spin_lock_irqsave(&desc->lock, flags);
-
- /* Disable interrupt */
- desc->handler->shutdown(desc);
+ ASSERT(desc->irq < gic.lines);/* Can't route interrupts that don't exist */
+ ASSERT(desc->status & IRQ_DISABLED);
+ ASSERT(spin_is_locked(&desc->lock));
desc->handler = &gic_host_irq_type;
- gic_set_irq_properties(irq, level, cpu_mask, priority);
-
- spin_unlock_irqrestore(&desc->lock, flags);
- return 0;
+ gic_set_irq_properties(desc->irq, level, cpu_mask, priority);
}
/* Program the GIC to route an interrupt to a guest
@@ -296,17 +286,6 @@ void gic_route_irq_to_guest(struct domain *d, struct irq_desc *desc,
p->desc = desc;
}
-/* Program the GIC to route an interrupt with a dt_irq */
-void gic_route_dt_irq(const struct dt_irq *irq, const cpumask_t *cpu_mask,
- unsigned int priority)
-{
- bool_t level;
-
- level = dt_irq_is_level_triggered(irq);
-
- gic_route_irq(irq->irq, level, cpu_mask, priority);
-}
-
static void __init gic_dist_init(void)
{
uint32_t type;
@@ -560,30 +539,6 @@ void gic_disable_cpu(void)
spin_unlock(&gic.lock);
}
-void gic_route_ppis(void)
-{
- /* GIC maintenance */
- gic_route_dt_irq(&gic.maintenance, cpumask_of(smp_processor_id()),
- GIC_PRI_IRQ);
- /* Route timer interrupt */
- route_timer_interrupt();
-}
-
-void gic_route_spis(void)
-{
- int seridx;
- const struct dt_irq *irq;
-
- for ( seridx = 0; seridx <= SERHND_IDX; seridx++ )
- {
- if ( (irq = serial_dt_irq(seridx)) == NULL )
- continue;
-
- gic_route_dt_irq(irq, cpumask_of(smp_processor_id()),
- GIC_PRI_IRQ);
- }
-}
-
static inline void gic_set_lr(int lr, struct pending_irq *p,
unsigned int state)
{
@@ -250,15 +250,37 @@ int setup_dt_irq(const struct dt_irq *irq, struct irqaction *new)
int rc;
unsigned long flags;
struct irq_desc *desc;
+ bool_t disabled;
desc = irq_to_desc(irq->irq);
spin_lock_irqsave(&desc->lock, flags);
+
+ disabled = (desc->action == NULL);
+
rc = __setup_irq(desc, new);
+ if ( rc )
+ goto err;
- if ( !rc )
+ /* First time the IRQ is setup */
+ if ( disabled )
+ {
+ bool_t level;
+
+ level = dt_irq_is_level_triggered(irq);
+ /* It's fine to use smp_processor_id() because:
+ * For PPI: irq_desc is banked
+ * For SPI: we don't care for now which CPU will receive the
+ * interrupt
+ * TODO: Handle case where SPI is setup on different CPU than
+ * the targeted CPU and the priority.
+ */
+ gic_route_irq_to_xen(desc, level, cpumask_of(smp_processor_id()),
+ GIC_PRI_IRQ);
desc->handler->startup(desc);
+ }
+err:
spin_unlock_irqrestore(&desc->lock, flags);
return rc;
@@ -719,8 +719,6 @@ void __init start_xen(unsigned long boot_phys_offset,
init_IRQ();
- gic_route_ppis();
- gic_route_spis();
xsm_dt_init();
init_maintenance_interrupt();
@@ -287,8 +287,6 @@ void __cpuinit start_secondary(unsigned long boot_phys_offset,
init_secondary_IRQ();
- gic_route_ppis();
-
init_maintenance_interrupt();
init_timer_interrupt();
@@ -218,17 +218,6 @@ static void vtimer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
vgic_vcpu_inject_irq(current, current->arch.virt_timer.irq, 1);
}
-/* Route timer's IRQ on this CPU */
-void __cpuinit route_timer_interrupt(void)
-{
- gic_route_dt_irq(&timer_irq[TIMER_PHYS_NONSECURE_PPI],
- cpumask_of(smp_processor_id()), GIC_PRI_IRQ);
- gic_route_dt_irq(&timer_irq[TIMER_HYP_PPI],
- cpumask_of(smp_processor_id()), GIC_PRI_IRQ);
- gic_route_dt_irq(&timer_irq[TIMER_VIRT_PPI],
- cpumask_of(smp_processor_id()), GIC_PRI_IRQ);
-}
-
/* Set up the timer interrupt on this CPU */
void __cpuinit init_timer_interrupt(void)
{
@@ -167,15 +167,13 @@ extern void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq,int virtual);
extern void vgic_clear_pending_irqs(struct vcpu *v);
extern struct pending_irq *irq_to_pending(struct vcpu *v, unsigned int irq);
-/* Program the GIC to route an interrupt with a dt_irq */
-extern void gic_route_dt_irq(const struct dt_irq *irq,
- const cpumask_t *cpu_mask,
- unsigned int priority);
+/* Program the GIC to route an interrupt */
+extern void gic_route_irq_to_xen(struct irq_desc *desc, bool_t level,
+ const cpumask_t *cpu_mask,
+ unsigned int priority);
extern void gic_route_irq_to_guest(struct domain *, struct irq_desc *desc,
bool_t level, const cpumask_t *cpu_mask,
unsigned int priority);
-extern void gic_route_ppis(void);
-extern void gic_route_spis(void);
extern void gic_inject(void);
extern void gic_clear_pending_irqs(struct vcpu *v);
@@ -25,9 +25,6 @@ enum timer_ppi
/* Get one of the timer IRQ number */
unsigned int timer_get_irq(enum timer_ppi ppi);
-/* Route timer's IRQ on this CPU */
-extern void __cpuinit route_timer_interrupt(void);
-
/* Set up the timer interrupt on this CPU */
extern void __cpuinit init_timer_interrupt(void);