aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/interrupts.c22
-rw-r--r--hw/xive.c10
-rw-r--r--hw/xive2.c10
-rw-r--r--include/interrupts.h1
4 files changed, 38 insertions, 5 deletions
diff --git a/core/interrupts.c b/core/interrupts.c
index 35571f2..03a37b2 100644
--- a/core/interrupts.c
+++ b/core/interrupts.c
@@ -199,6 +199,21 @@ uint32_t get_ics_phandle(void)
abort();
}
+static bool source_has_opal_interrupts(struct irq_source *is)
+{
+ /* check with the source first */
+ if (is->ops->has_opal_interrupts)
+ return is->ops->has_opal_interrupts(is);
+ /*
+ * Default case: to handle an interrupt in opal, a source
+ * needs at least an attribute callback to declare it and a
+ * handler
+ */
+ if (!is->ops->interrupt || !is->ops->attributes)
+ return false;
+ return true;
+}
+
void add_opal_interrupts(void)
{
struct irq_source *is;
@@ -214,11 +229,8 @@ void add_opal_interrupts(void)
lock(&irq_lock);
list_for_each(&irq_sources, is, link) {
- /*
- * Don't even consider sources that don't have an interrupts
- * callback or don't have an attributes one.
- */
- if (!is->ops->interrupt || !is->ops->attributes)
+
+ if (!source_has_opal_interrupts(is))
continue;
for (isn = is->start; isn < is->end; isn++) {
uint64_t attr = is->ops->attributes(is, isn);
diff --git a/hw/xive.c b/hw/xive.c
index 6055276..bf711ad 100644
--- a/hw/xive.c
+++ b/hw/xive.c
@@ -2520,6 +2520,15 @@ void xive_source_mask(struct irq_source *is, uint32_t isn)
xive_update_irq_mask(s, isn - s->esb_base, true);
}
+static bool xive_has_opal_interrupts(struct irq_source *is)
+{
+ struct xive_src *s = container_of(is, struct xive_src, is);
+
+ if (!s->orig_ops || !s->orig_ops->attributes || !s->orig_ops->interrupt)
+ return false;
+ return true;
+}
+
static const struct irq_source_ops xive_irq_source_ops = {
.get_xive = xive_source_get_xive,
.set_xive = xive_source_set_xive,
@@ -2527,6 +2536,7 @@ static const struct irq_source_ops xive_irq_source_ops = {
.interrupt = xive_source_interrupt,
.attributes = xive_source_attributes,
.name = xive_source_name,
+ .has_opal_interrupts = xive_has_opal_interrupts,
};
static void __xive_register_source(struct xive *x, struct xive_src *s,
diff --git a/hw/xive2.c b/hw/xive2.c
index 8e2a1f2..d20e3c5 100644
--- a/hw/xive2.c
+++ b/hw/xive2.c
@@ -2644,10 +2644,20 @@ void xive2_source_mask(struct irq_source *is, uint32_t isn)
xive_update_irq_mask(s, isn - s->esb_base, true);
}
+static bool xive_has_opal_interrupts(struct irq_source *is)
+{
+ struct xive_src *s = container_of(is, struct xive_src, is);
+
+ if (!s->orig_ops || !s->orig_ops->attributes || !s->orig_ops->interrupt)
+ return false;
+ return true;
+}
+
static const struct irq_source_ops xive_irq_source_ops = {
.interrupt = xive_source_interrupt,
.attributes = xive_source_attributes,
.name = xive_source_name,
+ .has_opal_interrupts = xive_has_opal_interrupts,
};
static void __xive_register_source(struct xive *x, struct xive_src *s,
diff --git a/include/interrupts.h b/include/interrupts.h
index 7ffcc6c..6958fa6 100644
--- a/include/interrupts.h
+++ b/include/interrupts.h
@@ -153,6 +153,7 @@ struct irq_source_ops {
void (*interrupt)(struct irq_source *is, uint32_t isn);
void (*eoi)(struct irq_source *is, uint32_t isn);
char *(*name)(struct irq_source *is, uint32_t isn);
+ bool (*has_opal_interrupts)(struct irq_source *is);
};
struct irq_source {