]> rtime.felk.cvut.cz Git - jailhouse.git/blobdiff - hypervisor/arch/arm/irqchip.c
arm: Consolidate gic_irqchip to irqchip
[jailhouse.git] / hypervisor / arch / arm / irqchip.c
index 538bbc01f4f265f6d2a8c672e83ec1ddb0915e42..0b1193ccc7be57eeff0959e61b683707367939f1 100644 (file)
@@ -24,6 +24,8 @@
 /* AMBA's biosfood */
 #define AMBA_DEVICE    0xb105f00d
 
+extern struct irqchip_ops irqchip;
+
 void *gicd_base;
 unsigned long gicd_size;
 
@@ -32,7 +34,6 @@ unsigned long gicd_size;
  * per-cpu setup, which means that a bool must be set by the master CPU
  */
 static bool irqchip_is_init;
-static struct irqchip_ops irqchip;
 
 bool spi_in_cell(struct cell *cell, unsigned int spi)
 {
@@ -49,11 +50,12 @@ bool spi_in_cell(struct cell *cell, unsigned int spi)
        return spi_mask & (1 << (spi & 31));
 }
 
-void irqchip_set_pending(struct per_cpu *cpu_data, u16 irq_id, bool try_inject)
+void irqchip_set_pending(struct per_cpu *cpu_data, u16 irq_id)
 {
+       bool local_injection = (this_cpu_data() == cpu_data);
        unsigned int new_tail;
 
-       if (try_inject && irqchip.inject_irq(cpu_data, irq_id) != -EBUSY)
+       if (local_injection && irqchip.inject_irq(cpu_data, irq_id) != -EBUSY)
                return;
 
        spin_lock(&cpu_data->pending_irqs_lock);
@@ -72,6 +74,14 @@ void irqchip_set_pending(struct per_cpu *cpu_data, u16 irq_id, bool try_inject)
        }
 
        spin_unlock(&cpu_data->pending_irqs_lock);
+
+       /*
+        * The list registers are full, trigger maintenance interrupt if we are
+        * on the target CPU. In the other case, the caller will send a
+        * SGI_INJECT, and irqchip_inject_pending will take care.
+        */
+       if (local_injection)
+               irqchip.enable_maint_irq(true);
 }
 
 void irqchip_inject_pending(struct per_cpu *cpu_data)
@@ -118,20 +128,14 @@ int irqchip_send_sgi(struct sgi *sgi)
 
 int irqchip_cpu_init(struct per_cpu *cpu_data)
 {
-       if (irqchip.cpu_init)
-               return irqchip.cpu_init(cpu_data);
-
-       return 0;
+       return irqchip.cpu_init(cpu_data);
 }
 
 int irqchip_cpu_reset(struct per_cpu *cpu_data)
 {
        cpu_data->pending_irqs_head = cpu_data->pending_irqs_tail = 0;
 
-       if (irqchip.cpu_reset)
-               return irqchip.cpu_reset(cpu_data, false);
-
-       return 0;
+       return irqchip.cpu_reset(cpu_data, false);
 }
 
 void irqchip_cpu_shutdown(struct per_cpu *cpu_data)
@@ -141,8 +145,7 @@ void irqchip_cpu_shutdown(struct per_cpu *cpu_data)
         * it has been initialised: this function may be executed during the
         * setup phase.
         */
-       if (irqchip.cpu_reset)
-               irqchip.cpu_reset(cpu_data, true);
+       irqchip.cpu_reset(cpu_data, true);
 }
 
 static const struct jailhouse_irqchip *
@@ -187,9 +190,6 @@ void irqchip_root_cell_shrink(struct cell *cell)
        root_cell.arch.spis &= ~(cell->arch.spis);
 }
 
-/* Only the GIC is implemented */
-extern struct irqchip_ops gic_irqchip;
-
 int irqchip_init(void)
 {
        int i, err;
@@ -220,8 +220,9 @@ int irqchip_init(void)
        case 0x2:
        case 0x3:
        case 0x4:
-               memcpy(&irqchip, &gic_irqchip, sizeof(struct irqchip_ops));
                break;
+       default:
+               goto err_no_distributor;
        }
 
        if (irqchip.init) {
@@ -232,7 +233,7 @@ int irqchip_init(void)
        }
 
 err_no_distributor:
-       printk("GIC: no distributor found\n");
+       printk("GIC: no supported distributor found\n");
        arch_unmap_device(gicd_base, gicd_size);
 
        return -ENODEV;