diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2016-07-07 11:50:05 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2016-07-13 17:06:24 +1000 |
commit | 24cd81df5b0bf584a0d382b84f45099db46aa727 (patch) | |
tree | f53317c37af8c0f18a205f00e2e4dafd5fac004f /core/interrupts.c | |
parent | 1d5643c568f444c52e914013bc090ea55469cf49 (diff) | |
download | skiboot-24cd81df5b0bf584a0d382b84f45099db46aa727.zip skiboot-24cd81df5b0bf584a0d382b84f45099db46aa727.tar.gz skiboot-24cd81df5b0bf584a0d382b84f45099db46aa727.tar.bz2 |
interrupts: Expose irq_source and change prototypes of all ops
This makes irq_source public, and change all irq_source_ops to take
the source pointer as a first argument (they can still dig the void *
data out of that).
This will allow us to embed/wrap it for XIVE later on.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'core/interrupts.c')
-rw-r--r-- | core/interrupts.c | 105 |
1 files changed, 64 insertions, 41 deletions
diff --git a/core/interrupts.c b/core/interrupts.c index 7109fae..f93ce7b 100644 --- a/core/interrupts.c +++ b/core/interrupts.c @@ -31,32 +31,15 @@ #define ICP_CPPR 0x4 /* 8-bit access */ #define ICP_MFRR 0xc /* 8-bit access */ -struct irq_source { - uint32_t start; - uint32_t end; - const struct irq_source_ops *ops; - void *data; - struct list_node link; -}; - static LIST_HEAD(irq_sources); static struct lock irq_lock = LOCK_UNLOCKED; -void register_irq_source(const struct irq_source_ops *ops, void *data, - uint32_t start, uint32_t count) +void __register_irq_source(struct irq_source *is) { - struct irq_source *is, *is1; - - is = zalloc(sizeof(struct irq_source)); - assert(is); - is->start = start; - is->end = start + count; - is->ops = ops; - is->data = data; + struct irq_source *is1; - prlog(PR_DEBUG, "IRQ: Registering %04x..%04x ops @%p (data %p) %s\n", - start, start + count - 1, ops, data, - ops->interrupt ? "[Internal]" : "[OS]"); + prlog(PR_DEBUG, "IRQ: Registering %04x..%04x ops @%p (data %p)\n", + is->start, is->end - 1, is->ops, is->data); lock(&irq_lock); list_for_each(&irq_sources, is1, link) { @@ -72,6 +55,21 @@ void register_irq_source(const struct irq_source_ops *ops, void *data, unlock(&irq_lock); } +void register_irq_source(const struct irq_source_ops *ops, void *data, + uint32_t start, uint32_t count) +{ + struct irq_source *is; + + is = zalloc(sizeof(struct irq_source)); + assert(is); + is->start = start; + is->end = start + count; + is->ops = ops; + is->data = data; + + __register_irq_source(is); +} + void unregister_irq_source(uint32_t start, uint32_t count) { struct irq_source *is; @@ -99,6 +97,46 @@ void unregister_irq_source(uint32_t start, uint32_t count) assert(0); } +static struct irq_source *irq_find_source(uint32_t isn) +{ + struct irq_source *is; + + lock(&irq_lock); + list_for_each(&irq_sources, is, link) { + if (isn >= is->start && isn < is->end) { + unlock(&irq_lock); + return is; + } + } + unlock(&irq_lock); + + return NULL; +} + +void adjust_irq_source(struct irq_source *is, uint32_t new_count) +{ + struct irq_source *is1; + uint32_t new_end = is->start + new_count; + + prlog(PR_DEBUG, "IRQ: Adjusting %04x..%04x to %04x..%04x\n", + is->start, is->end - 1, is->start, new_end - 1); + + lock(&irq_lock); + list_for_each(&irq_sources, is1, link) { + if (is1 == is) + continue; + if (new_end > is1->start && is->start < is1->end) { + prerror("adjust IRQ source overlap !\n"); + prerror(" new: %x..%x old: %x..%x\n", + is->start, new_end - 1, + is1->start, is1->end - 1); + assert(0); + } + } + is->end = new_end; + unlock(&irq_lock); +} + /* * This takes a 6-bit chip id and returns a 20 bit value representing * the PSI interrupt. This includes all the fields above, ie, is a @@ -341,22 +379,6 @@ uint32_t p8_irq_to_phb(uint32_t irq) return p8_irq_to_block(irq) - P8_IRQ_BLOCK_PHB_BASE; } -static struct irq_source *irq_find_source(uint32_t isn) -{ - struct irq_source *is; - - lock(&irq_lock); - list_for_each(&irq_sources, is, link) { - if (isn >= is->start && isn < is->end) { - unlock(&irq_lock); - return is; - } - } - unlock(&irq_lock); - - return NULL; -} - bool irq_source_eoi(uint32_t isn) { struct irq_source *is = irq_find_source(isn); @@ -364,7 +386,7 @@ bool irq_source_eoi(uint32_t isn) if (!is || !is->ops->eoi) return false; - is->ops->eoi(is->data, isn); + is->ops->eoi(is, isn); return true; } @@ -375,7 +397,7 @@ static int64_t opal_set_xive(uint32_t isn, uint16_t server, uint8_t priority) if (!is || !is->ops->set_xive) return OPAL_PARAMETER; - return is->ops->set_xive(is->data, isn, server, priority); + return is->ops->set_xive(is, isn, server, priority); } opal_call(OPAL_SET_XIVE, opal_set_xive, 3); @@ -386,7 +408,7 @@ static int64_t opal_get_xive(uint32_t isn, uint16_t *server, uint8_t *priority) if (!is || !is->ops->get_xive) return OPAL_PARAMETER; - return is->ops->get_xive(is->data, isn, server, priority); + return is->ops->get_xive(is, isn, server, priority); } opal_call(OPAL_GET_XIVE, opal_get_xive, 3); @@ -402,7 +424,7 @@ static int64_t opal_handle_interrupt(uint32_t isn, __be64 *outstanding_event_mas } /* Run it */ - is->ops->interrupt(is->data, isn); + is->ops->interrupt(is, isn); /* Check timers if SLW timer isn't working */ if (!slw_timer_ok()) @@ -440,3 +462,4 @@ void init_interrupts(void) } } + |