[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v3 16/25] arm: irq



From: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>

A simple do_IRQ and request_irq implementation for ARM.

Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxx>
---
 xen/arch/arm/irq.c          |  179 +++++++++++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/irq.h   |   30 +++++++
 xen/include/asm-arm/setup.h |    2 +
 xen/include/xen/irq.h       |   13 +++
 4 files changed, 224 insertions(+), 0 deletions(-)
 create mode 100644 xen/arch/arm/irq.c
 create mode 100644 xen/include/asm-arm/irq.h

diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
new file mode 100644
index 0000000..5663762
--- /dev/null
+++ b/xen/arch/arm/irq.c
@@ -0,0 +1,179 @@
+/*
+ * xen/arch/arm/irq.c
+ *
+ * ARM Interrupt support
+ *
+ * Ian Campbell <ian.campbell@xxxxxxxxxx>
+ * Copyright (c) 2011 Citrix Systems.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <xen/config.h>
+#include <xen/lib.h>
+#include <xen/spinlock.h>
+#include <xen/irq.h>
+#include <xen/init.h>
+#include <xen/errno.h>
+#include <xen/sched.h>
+
+#include "gic.h"
+
+static void enable_none(struct irq_desc *irq) { }
+static unsigned int startup_none(struct irq_desc *irq) { return 0; }
+static void disable_none(struct irq_desc *irq) { }
+static void ack_none(struct irq_desc *irq)
+{
+    printk("unexpected IRQ trap at irq %02x\n", irq->irq);
+}
+
+#define shutdown_none   disable_none
+#define end_none        enable_none
+
+hw_irq_controller no_irq_type = {
+    .typename = "none",
+    .startup = startup_none,
+    .shutdown = shutdown_none,
+    .enable = enable_none,
+    .disable = disable_none,
+    .ack = ack_none,
+    .end = end_none
+};
+
+int __init arch_init_one_irq_desc(struct irq_desc *desc)
+{
+       return 0;
+}
+
+
+static int __init init_irq_data(void)
+{
+    int irq;
+
+    for (irq = 0; irq < NR_IRQS; irq++) {
+        struct irq_desc *desc = irq_to_desc(irq);
+        init_one_irq_desc(desc);
+        desc->irq = irq;
+        desc->action  = NULL;
+    }
+    return 0;
+}
+
+void __init init_IRQ(void)
+{
+    BUG_ON(init_irq_data() < 0);
+}
+
+int __init request_irq(unsigned int irq,
+        void (*handler)(int, void *, struct cpu_user_regs *),
+        unsigned long irqflags, const char * devname, void *dev_id)
+{
+    struct irqaction *action;
+    int retval;
+
+    /*
+     * Sanity-check: shared interrupts must pass in a real dev-ID,
+     * otherwise we'll have trouble later trying to figure out
+     * which interrupt is which (messes up the interrupt freeing
+     * logic etc).
+     */
+    if (irq >= nr_irqs)
+        return -EINVAL;
+    if (!handler)
+        return -EINVAL;
+
+    action = xmalloc(struct irqaction);
+    if (!action)
+        return -ENOMEM;
+
+    action->handler = handler;
+    action->name = devname;
+    action->dev_id = dev_id;
+    action->free_on_release = 1;
+
+    retval = setup_irq(irq, action);
+    if (retval)
+        xfree(action);
+
+    return retval;
+}
+
+/* Dispatch an interrupt */
+void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, int is_fiq)
+{
+    struct irq_desc *desc = irq_to_desc(irq);
+    struct irqaction *action = desc->action;
+
+    /* TODO: perfc_incr(irqs); */
+
+    /* TODO: this_cpu(irq_count)++; */
+
+    irq_enter();
+
+    spin_lock(&desc->lock);
+    desc->handler->ack(desc);
+
+    if ( action == NULL )
+    {
+        printk("Unknown %s %#3.3x\n",
+               is_fiq ? "FIQ" : "IRQ", irq);
+        goto out;
+    }
+
+    if ( desc->status & IRQ_GUEST )
+    {
+        struct domain *d = action->dev_id;
+
+        desc->handler->end(desc);
+
+        desc->status |= IRQ_INPROGRESS;
+
+        /* XXX: inject irq into the guest */
+        goto out_no_end;
+    }
+
+    desc->status |= IRQ_PENDING;
+
+    /*
+     * Since we set PENDING, if another processor is handling a different
+     * instance of this same irq, the other processor will take care of it.
+     */
+    if ( desc->status & (IRQ_DISABLED | IRQ_INPROGRESS) )
+        goto out;
+
+    desc->status |= IRQ_INPROGRESS;
+
+    action = desc->action;
+    while ( desc->status & IRQ_PENDING )
+    {
+        desc->status &= ~IRQ_PENDING;
+        spin_unlock_irq(&desc->lock);
+        action->handler(irq, action->dev_id, regs);
+        spin_lock_irq(&desc->lock);
+    }
+
+    desc->status &= ~IRQ_INPROGRESS;
+
+out:
+    desc->handler->end(desc);
+out_no_end:
+    spin_unlock(&desc->lock);
+    irq_exit();
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h
new file mode 100644
index 0000000..8e65a2e
--- /dev/null
+++ b/xen/include/asm-arm/irq.h
@@ -0,0 +1,30 @@
+#ifndef _ASM_HW_IRQ_H
+#define _ASM_HW_IRQ_H
+
+#include <xen/config.h>
+
+#define NR_VECTORS 256 /* XXX */
+
+typedef struct {
+    DECLARE_BITMAP(_bits,NR_VECTORS);
+} vmask_t;
+
+struct arch_pirq
+{
+};
+
+struct irq_cfg {
+#define arch_irq_desc irq_cfg
+};
+
+void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, int is_fiq);
+
+#endif /* _ASM_HW_IRQ_H */
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
index 1dc3f97..2041f06 100644
--- a/xen/include/asm-arm/setup.h
+++ b/xen/include/asm-arm/setup.h
@@ -7,6 +7,8 @@ void arch_get_xen_caps(xen_capabilities_info_t *info);
 
 int construct_dom0(struct domain *d);
 
+void init_IRQ(void);
+
 #endif
 /*
  * Local variables:
diff --git a/xen/include/xen/irq.h b/xen/include/xen/irq.h
index a2a90e1..5a711cc 100644
--- a/xen/include/xen/irq.h
+++ b/xen/include/xen/irq.h
@@ -107,6 +107,19 @@ extern irq_desc_t irq_desc[NR_VECTORS];
 
 #define request_irq(irq, handler, irqflags, devname, devid) \
     request_irq_vector(irq_to_vector(irq), handler, irqflags, devname, devid)
+
+#elif defined(__arm__)
+
+#define NR_IRQS                1024
+#define nr_irqs NR_IRQS
+extern irq_desc_t irq_desc[NR_IRQS];
+
+extern int setup_irq(unsigned int irq, struct irqaction *);
+extern void release_irq(unsigned int irq);
+extern int request_irq(unsigned int irq,
+               void (*handler)(int, void *, struct cpu_user_regs *),
+               unsigned long irqflags, const char * devname, void *dev_id);
+
 #else
 extern int setup_irq(unsigned int irq, struct irqaction *);
 extern void release_irq(unsigned int irq);
-- 
1.7.2.5


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.