diff options
-rw-r--r-- | core/interrupts.c | 105 | ||||
-rw-r--r-- | hw/npu.c | 21 | ||||
-rw-r--r-- | hw/p7ioc-phb.c | 21 | ||||
-rw-r--r-- | hw/p7ioc.c | 13 | ||||
-rw-r--r-- | hw/phb3.c | 37 | ||||
-rw-r--r-- | hw/phb4.c | 10 | ||||
-rw-r--r-- | hw/psi.c | 29 | ||||
-rw-r--r-- | include/interrupts.h | 23 |
8 files changed, 143 insertions, 116 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) } } + @@ -700,12 +700,10 @@ static int npu_isn_valid(struct npu *p, uint32_t isn) return true; } -static int64_t npu_lsi_get_xive(void *data, - uint32_t isn, - uint16_t *server, - uint8_t *prio) +static int64_t npu_lsi_get_xive(struct irq_source *is, uint32_t isn, + uint16_t *server, uint8_t *prio) { - struct npu *p = data; + struct npu *p = is->data; uint32_t irq = NPU_IRQ_NUM(isn); uint64_t lxive; @@ -724,12 +722,10 @@ static int64_t npu_lsi_get_xive(void *data, return OPAL_SUCCESS; } -static int64_t npu_lsi_set_xive(void *data, - uint32_t isn, - uint16_t server, - uint8_t prio) +static int64_t npu_lsi_set_xive(struct irq_source *is, uint32_t isn, + uint16_t server, uint8_t prio) { - struct npu *p = data; + struct npu *p = is->data; uint32_t irq = NPU_IRQ_NUM(isn); uint64_t lxive; @@ -754,9 +750,9 @@ static int64_t npu_lsi_set_xive(void *data, return OPAL_SUCCESS; } -static void npu_err_interrupt(void *data, uint32_t isn) +static void npu_err_interrupt(struct irq_source *is, uint32_t isn) { - struct npu *p = data; + struct npu *p = is->data; uint32_t irq = NPU_IRQ_NUM(isn); if (!npu_isn_valid(p, isn)) @@ -1888,3 +1884,4 @@ void probe_npu(void) dt_for_each_compatible(dt_root, np, "ibm,power8-npu-pciex") npu_create_phb(np); } + diff --git a/hw/p7ioc-phb.c b/hw/p7ioc-phb.c index 6f5a6ab..52ff952 100644 --- a/hw/p7ioc-phb.c +++ b/hw/p7ioc-phb.c @@ -2362,10 +2362,10 @@ static const struct phb_ops p7ioc_phb_ops = { }; /* p7ioc_phb_get_xive - Interrupt control from OPAL */ -static int64_t p7ioc_msi_get_xive(void *data, uint32_t isn, +static int64_t p7ioc_msi_get_xive(struct irq_source *is, uint32_t isn, uint16_t *server, uint8_t *prio) { - struct p7ioc_phb *p = data; + struct p7ioc_phb *p = is->data; uint32_t irq, fbuid = P7_IRQ_FBUID(isn); uint64_t xive; @@ -2382,10 +2382,10 @@ static int64_t p7ioc_msi_get_xive(void *data, uint32_t isn, } /* p7ioc_phb_set_xive - Interrupt control from OPAL */ -static int64_t p7ioc_msi_set_xive(void *data, uint32_t isn, +static int64_t p7ioc_msi_set_xive(struct irq_source *is, uint32_t isn, uint16_t server, uint8_t prio) { - struct p7ioc_phb *p = data; + struct p7ioc_phb *p = is->data; uint32_t irq, fbuid = P7_IRQ_FBUID(isn); uint64_t xive, m_server, m_prio; @@ -2422,10 +2422,10 @@ static int64_t p7ioc_msi_set_xive(void *data, uint32_t isn, } /* p7ioc_phb_get_xive - Interrupt control from OPAL */ -static int64_t p7ioc_lsi_get_xive(void *data, uint32_t isn, +static int64_t p7ioc_lsi_get_xive(struct irq_source *is, uint32_t isn, uint16_t *server, uint8_t *prio) { - struct p7ioc_phb *p = data; + struct p7ioc_phb *p = is->data; uint32_t irq = (isn & 0x7); uint32_t fbuid = P7_IRQ_FBUID(isn); uint64_t xive; @@ -2441,10 +2441,10 @@ static int64_t p7ioc_lsi_get_xive(void *data, uint32_t isn, } /* p7ioc_phb_set_xive - Interrupt control from OPAL */ -static int64_t p7ioc_lsi_set_xive(void *data, uint32_t isn, +static int64_t p7ioc_lsi_set_xive(struct irq_source *is, uint32_t isn, uint16_t server, uint8_t prio) { - struct p7ioc_phb *p = data; + struct p7ioc_phb *p = is->data; uint32_t irq = (isn & 0x7); uint32_t fbuid = P7_IRQ_FBUID(isn); uint64_t xive, m_server, m_prio; @@ -2481,9 +2481,9 @@ static int64_t p7ioc_lsi_set_xive(void *data, uint32_t isn, return OPAL_SUCCESS; } -static void p7ioc_phb_err_interrupt(void *data, uint32_t isn) +static void p7ioc_phb_err_interrupt(struct irq_source *is, uint32_t isn) { - struct p7ioc_phb *p = data; + struct p7ioc_phb *p = is->data; uint64_t peev0, peev1; PHBDBG(p, "Got interrupt 0x%04x\n", isn); @@ -3264,3 +3264,4 @@ void p7ioc_phb_reset(struct phb *phb) out_be64(ioc->regs + P7IOC_CIn_LEM_ERR_MASK_AND(ci_idx), 0); } + @@ -190,10 +190,10 @@ static const struct io_hub_ops p7ioc_hub_ops = { .reset = p7ioc_reset, }; -static int64_t p7ioc_rgc_get_xive(void *data, uint32_t isn, +static int64_t p7ioc_rgc_get_xive(struct irq_source *is, uint32_t isn, uint16_t *server, uint8_t *prio) { - struct p7ioc *ioc = data; + struct p7ioc *ioc = is->data; uint32_t irq = (isn & 0xf); uint32_t fbuid = P7_IRQ_FBUID(isn); uint64_t xive; @@ -208,10 +208,10 @@ static int64_t p7ioc_rgc_get_xive(void *data, uint32_t isn, return OPAL_SUCCESS; } -static int64_t p7ioc_rgc_set_xive(void *data, uint32_t isn, +static int64_t p7ioc_rgc_set_xive(struct irq_source *is, uint32_t isn, uint16_t server, uint8_t prio) { - struct p7ioc *ioc = data; + struct p7ioc *ioc = is->data; uint32_t irq = (isn & 0xf); uint32_t fbuid = P7_IRQ_FBUID(isn); uint64_t xive; @@ -566,9 +566,9 @@ static bool p7ioc_check_GEM(struct p7ioc *ioc) return false; } -static void p7ioc_rgc_interrupt(void *data, uint32_t isn) +static void p7ioc_rgc_interrupt(struct irq_source *is, uint32_t isn) { - struct p7ioc *ioc = data; + struct p7ioc *ioc = is->data; printf("Got RGC interrupt 0x%04x\n", isn); @@ -679,3 +679,4 @@ void probe_p7ioc(void) p7ioc_create_hub(np); } + @@ -1602,12 +1602,10 @@ static void phb3_read_phb_status(struct phb3 *p, } } -static int64_t phb3_msi_get_xive(void *data, - uint32_t isn, - uint16_t *server, - uint8_t *prio) +static int64_t phb3_msi_get_xive(struct irq_source *is, uint32_t isn, + uint16_t *server, uint8_t *prio) { - struct phb3 *p = data; + struct phb3 *p = is->data; uint32_t chip, index, irq; uint64_t ive; @@ -1631,12 +1629,10 @@ static int64_t phb3_msi_get_xive(void *data, return OPAL_SUCCESS; } -static int64_t phb3_msi_set_xive(void *data, - uint32_t isn, - uint16_t server, - uint8_t prio) +static int64_t phb3_msi_set_xive(struct irq_source *is, uint32_t isn, + uint16_t server, uint8_t prio) { - struct phb3 *p = data; + struct phb3 *p = is->data; uint32_t chip, index; uint64_t *cache, ive_num, data64, m_server, m_prio, ivc; uint32_t *ive; @@ -1716,12 +1712,10 @@ static int64_t phb3_msi_set_xive(void *data, return OPAL_SUCCESS; } -static int64_t phb3_lsi_get_xive(void *data, - uint32_t isn, - uint16_t *server, - uint8_t *prio) +static int64_t phb3_lsi_get_xive(struct irq_source *is, uint32_t isn, + uint16_t *server, uint8_t *prio) { - struct phb3 *p = data; + struct phb3 *p = is->data; uint32_t chip, index, irq; uint64_t lxive; @@ -1742,12 +1736,10 @@ static int64_t phb3_lsi_get_xive(void *data, return OPAL_SUCCESS; } -static int64_t phb3_lsi_set_xive(void *data, - uint32_t isn, - uint16_t server, - uint8_t prio) +static int64_t phb3_lsi_set_xive(struct irq_source *is, uint32_t isn, + uint16_t server, uint8_t prio) { - struct phb3 *p = data; + struct phb3 *p = is->data; uint32_t chip, index, irq, entry; uint64_t lxive; @@ -1785,9 +1777,9 @@ static int64_t phb3_lsi_set_xive(void *data, return OPAL_SUCCESS; } -static void phb3_err_interrupt(void *data, uint32_t isn) +static void phb3_err_interrupt(struct irq_source *is, uint32_t isn) { - struct phb3 *p = data; + struct phb3 *p = is->data; PHBDBG(p, "Got interrupt 0x%08x\n", isn); @@ -4733,3 +4725,4 @@ void probe_phb3(void) dt_for_each_compatible(dt_root, np, "ibm,power8-pciex") phb3_create(np); } + @@ -2991,7 +2991,7 @@ static bool phb4_calculate_windows(struct phb4 *p) } -static int64_t phb4_get_xive(void *data __unused, uint32_t isn, +static int64_t phb4_get_xive(struct irq_source *is __unused, uint32_t isn, uint16_t *server, uint8_t *prio) { uint32_t target_id; @@ -3003,10 +3003,10 @@ static int64_t phb4_get_xive(void *data __unused, uint32_t isn, return OPAL_PARAMETER; } -static int64_t phb4_set_xive(void *data, uint32_t isn, +static int64_t phb4_set_xive(struct irq_source *is, uint32_t isn, uint16_t server, uint8_t prio) { - struct phb4 *p = data; + struct phb4 *p = is->data; uint32_t idx = isn - p->base_msi; void *mmio_base; @@ -3027,9 +3027,9 @@ static int64_t phb4_set_xive(void *data, uint32_t isn, return OPAL_SUCCESS; } -static void phb4_eoi(void *data, uint32_t isn) +static void phb4_eoi(struct irq_source *is, uint32_t isn) { - struct phb4 *p = data; + struct phb4 *p = is->data; uint32_t idx = isn - p->base_msi; void *mmio_base; uint8_t eoi_val; @@ -343,9 +343,9 @@ bool psi_poll_fsp_interrupt(struct psi *psi) return !!(in_be64(psi->regs + PSIHB_CR) & PSIHB_CR_FSP_IRQ); } -static void psi_interrupt(void *data, uint32_t isn __unused) +static void psi_interrupt(struct irq_source *is, uint32_t isn __unused) { - struct psi *psi = data; + struct psi *psi = is->data; u64 val; val = in_be64(psi->regs + PSIHB_CR); @@ -395,10 +395,10 @@ static void psi_interrupt(void *data, uint32_t isn __unused) fsp_console_poll(NULL); } -static int64_t psi_p7_set_xive(void *data, uint32_t isn __unused, - uint16_t server, uint8_t priority) +static int64_t psi_p7_set_xive(struct irq_source *is, uint32_t isn __unused, + uint16_t server, uint8_t priority) { - struct psi *psi = data; + struct psi *psi = is->data; uint64_t xivr; if (!psi->working) @@ -414,10 +414,10 @@ static int64_t psi_p7_set_xive(void *data, uint32_t isn __unused, return OPAL_SUCCESS; } -static int64_t psi_p7_get_xive(void *data, uint32_t isn __unused, - uint16_t *server, uint8_t *priority) +static int64_t psi_p7_get_xive(struct irq_source *is, uint32_t isn __unused, + uint16_t *server, uint8_t *priority) { - struct psi *psi = data; + struct psi *psi = is->data; uint64_t xivr; if (!psi->working) @@ -432,10 +432,10 @@ static int64_t psi_p7_get_xive(void *data, uint32_t isn __unused, return OPAL_SUCCESS; } -static int64_t psi_p8_set_xive(void *data, uint32_t isn, - uint16_t server, uint8_t priority) +static int64_t psi_p8_set_xive(struct irq_source *is, uint32_t isn, + uint16_t server, uint8_t priority) { - struct psi *psi = data; + struct psi *psi = is->data; uint64_t xivr_p, xivr; switch(isn & 7) { @@ -471,10 +471,10 @@ static int64_t psi_p8_set_xive(void *data, uint32_t isn, return OPAL_SUCCESS; } -static int64_t psi_p8_get_xive(void *data, uint32_t isn __unused, - uint16_t *server, uint8_t *priority) +static int64_t psi_p8_get_xive(struct irq_source *is, uint32_t isn __unused, + uint16_t *server, uint8_t *priority) { - struct psi *psi = data; + struct psi *psi = is->data; uint64_t xivr_p, xivr; switch(isn & 7) { @@ -919,3 +919,4 @@ void psi_init(void) dt_for_each_compatible(dt_root, np, "ibm,psihb-x") psi_init_psihb(np); } + diff --git a/include/interrupts.h b/include/interrupts.h index daa9747..3fba9d9 100644 --- a/include/interrupts.h +++ b/include/interrupts.h @@ -256,6 +256,8 @@ uint32_t p8_irq_to_phb(uint32_t irq); * functions in this file (or the corresponding core/interrupts.c). */ +struct irq_source; + /* * IRQ sources register themselves here. If an "interrupts" callback * is provided, then all interrupts in that source will appear in @@ -266,18 +268,27 @@ uint32_t p8_irq_to_phb(uint32_t irq); * be used for XIVE interrupts coming from PHBs. */ struct irq_source_ops { - int64_t (*set_xive)(void *data, uint32_t isn, uint16_t server, - uint8_t priority); - int64_t (*get_xive)(void *data, uint32_t isn, uint16_t *server, - uint8_t *priority); - void (*interrupt)(void *data, uint32_t isn); + int64_t (*set_xive)(struct irq_source *is, uint32_t isn, + uint16_t server, uint8_t priority); + int64_t (*get_xive)(struct irq_source *is, uint32_t isn, + uint16_t *server, uint8_t *priority); + void (*interrupt)(struct irq_source *is, uint32_t isn); + void (*eoi)(struct irq_source *is, uint32_t isn); +}; - void (*eoi)(void *data, uint32_t isn); +struct irq_source { + uint32_t start; + uint32_t end; + const struct irq_source_ops *ops; + void *data; + struct list_node link; }; +extern void __register_irq_source(struct irq_source *is); extern void register_irq_source(const struct irq_source_ops *ops, void *data, uint32_t start, uint32_t count); extern void unregister_irq_source(uint32_t start, uint32_t count); +extern void adjust_irq_source(struct irq_source *is, uint32_t new_count); extern uint32_t get_psi_interrupt(uint32_t chip_id); |