[v5,5/8] irq: Add a new irq device that allows the ORing of lines
diff mbox

Message ID 42ce627289b3f8976eaba62951224233e4d1e5cf.1469514677.git.alistair@alistair23.me
State New
Headers show

Commit Message

Alistair Francis July 26, 2016, 2:37 p.m. UTC
Signed-off-by: Alistair Francis <alistair@alistair23.me>
---

 hw/core/irq.c    | 44 ++++++++++++++++++++++++++++++++++++++++++++
 include/hw/irq.h | 13 +++++++++++++
 2 files changed, 57 insertions(+)

Comments

Peter Maydell July 26, 2016, 3 p.m. UTC | #1
On 26 July 2016 at 15:37, Alistair Francis <alistair23@gmail.com> wrote:
> Signed-off-by: Alistair Francis <alistair@alistair23.me>
> ---
>
>  hw/core/irq.c    | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  include/hw/irq.h | 13 +++++++++++++
>  2 files changed, 57 insertions(+)
>
> diff --git a/hw/core/irq.c b/hw/core/irq.c
> index 49ff2e6..73b18b4 100644
> --- a/hw/core/irq.c
> +++ b/hw/core/irq.c
> @@ -27,6 +27,7 @@
>  #include "qom/object.h"
>
>  #define IRQ(obj) OBJECT_CHECK(struct IRQState, (obj), TYPE_IRQ)
> +#define OR_IRQ(obj) OBJECT_CHECK(struct OrIRQState, (obj), TYPE_OR_IRQ)
>
>  struct IRQState {
>      Object parent_obj;
> @@ -36,6 +37,15 @@ struct IRQState {
>      int n;
>  };
>
> +struct OrIRQState {
> +    Object parent_obj;
> +
> +    qemu_irq in_irq;
> +    qemu_irq *out_irqs;
> +    int *levels;

The data in the memory pointed to by 'levels' is state, and you
need to migrate it somehow. (Otherwise you'll give the wrong
results the next time an input changes following a migration.)

thanks
-- PMM
Alistair Francis Aug. 1, 2016, 2:21 a.m. UTC | #2
On Tue, Jul 26, 2016 at 8:00 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 26 July 2016 at 15:37, Alistair Francis <alistair23@gmail.com> wrote:
>> Signed-off-by: Alistair Francis <alistair@alistair23.me>
>> ---
>>
>>  hw/core/irq.c    | 44 ++++++++++++++++++++++++++++++++++++++++++++
>>  include/hw/irq.h | 13 +++++++++++++
>>  2 files changed, 57 insertions(+)
>>
>> diff --git a/hw/core/irq.c b/hw/core/irq.c
>> index 49ff2e6..73b18b4 100644
>> --- a/hw/core/irq.c
>> +++ b/hw/core/irq.c
>> @@ -27,6 +27,7 @@
>>  #include "qom/object.h"
>>
>>  #define IRQ(obj) OBJECT_CHECK(struct IRQState, (obj), TYPE_IRQ)
>> +#define OR_IRQ(obj) OBJECT_CHECK(struct OrIRQState, (obj), TYPE_OR_IRQ)
>>
>>  struct IRQState {
>>      Object parent_obj;
>> @@ -36,6 +37,15 @@ struct IRQState {
>>      int n;
>>  };
>>
>> +struct OrIRQState {
>> +    Object parent_obj;
>> +
>> +    qemu_irq in_irq;
>> +    qemu_irq *out_irqs;
>> +    int *levels;
>
> The data in the memory pointed to by 'levels' is state, and you
> need to migrate it somehow. (Otherwise you'll give the wrong
> results the next time an input changes following a migration.)

A simple vmstate should be enough for that right?

Thanks,

Alistair

>
> thanks
> -- PMM
>

Patch
diff mbox

diff --git a/hw/core/irq.c b/hw/core/irq.c
index 49ff2e6..73b18b4 100644
--- a/hw/core/irq.c
+++ b/hw/core/irq.c
@@ -27,6 +27,7 @@ 
 #include "qom/object.h"
 
 #define IRQ(obj) OBJECT_CHECK(struct IRQState, (obj), TYPE_IRQ)
+#define OR_IRQ(obj) OBJECT_CHECK(struct OrIRQState, (obj), TYPE_OR_IRQ)
 
 struct IRQState {
     Object parent_obj;
@@ -36,6 +37,15 @@  struct IRQState {
     int n;
 };
 
+struct OrIRQState {
+    Object parent_obj;
+
+    qemu_irq in_irq;
+    qemu_irq *out_irqs;
+    int *levels;
+    int n;
+};
+
 void qemu_set_irq(qemu_irq irq, int level)
 {
     if (!irq)
@@ -77,6 +87,33 @@  qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n)
     return irq;
 }
 
+static void or_irq_handler(void *opaque, int n, int level)
+{
+    qemu_or_irq or_irq = (qemu_or_irq) opaque;
+    int or_level = 0;
+    int i;
+
+    or_irq->levels[n] = level;
+
+    for (i = 0; i < or_irq->n; i++) {
+        or_level |= or_irq->levels[i];
+    }
+
+    qemu_set_irq(or_irq->in_irq, or_level);
+}
+
+qemu_irq *qemu_allocate_or_irqs(qemu_irq in_irq, int n)
+{
+    qemu_or_irq or_irq = OR_IRQ(object_new(TYPE_OR_IRQ));
+
+    or_irq->out_irqs = qemu_allocate_irqs(or_irq_handler, or_irq, n);
+    or_irq->in_irq = in_irq;
+    or_irq->levels = g_new(int, n);
+    or_irq->n = n;
+
+    return or_irq->out_irqs;
+}
+
 void qemu_free_irqs(qemu_irq *s, int n)
 {
     int i;
@@ -151,9 +188,16 @@  static const TypeInfo irq_type_info = {
    .instance_size = sizeof(struct IRQState),
 };
 
+static const TypeInfo or_irq_type_info = {
+   .name = TYPE_OR_IRQ,
+   .parent = TYPE_OBJECT,
+   .instance_size = sizeof(struct OrIRQState),
+};
+
 static void irq_register_types(void)
 {
     type_register_static(&irq_type_info);
+    type_register_static(&or_irq_type_info);
 }
 
 type_init(irq_register_types)
diff --git a/include/hw/irq.h b/include/hw/irq.h
index 4c4c2ea..aeb7eb7 100644
--- a/include/hw/irq.h
+++ b/include/hw/irq.h
@@ -4,8 +4,10 @@ 
 /* Generic IRQ/GPIO pin infrastructure.  */
 
 #define TYPE_IRQ "irq"
+#define TYPE_OR_IRQ "or-irq"
 
 typedef struct IRQState *qemu_irq;
+typedef struct OrIRQState *qemu_or_irq;
 
 typedef void (*qemu_irq_handler)(void *opaque, int n, int level);
 
@@ -38,6 +40,17 @@  qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n);
  */
 qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n);
 
+/*
+ * qemu_allocate_or_irqs
+ * @in_irq: An input IRQ. It will be the result of the @out_irqs ORed together
+ * @n: The number of interrupt lines that should be ORed together
+ *
+ * returns: An array of interrupts that should be ORed together
+ *
+ * OR all of the interrupts returned in the array into a single @in_irq.
+ */
+qemu_irq *qemu_allocate_or_irqs(qemu_irq in_irq, int n);
+
 /* Extends an Array of IRQs. Old IRQs have their handlers and opaque data
  * preserved. New IRQs are assigned the argument handler and opaque data.
  */