From patchwork Fri Jun 24 22:47:49 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Herrenschmidt X-Patchwork-Id: 640483 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3rbtr165jFz9s9N for ; Sat, 25 Jun 2016 08:52:01 +1000 (AEST) Received: from ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3rbtr15KYnzDqwd for ; Sat, 25 Jun 2016 08:52:01 +1000 (AEST) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from gate.crashing.org (gate.crashing.org [63.228.1.57]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3rbtnF4mMczDqn5 for ; Sat, 25 Jun 2016 08:49:37 +1000 (AEST) Received: from pasglop.au.ibm.com (localhost.localdomain [127.0.0.1]) by gate.crashing.org (8.14.1/8.13.8) with ESMTP id u5OMm2N1022384; Fri, 24 Jun 2016 17:49:14 -0500 From: Benjamin Herrenschmidt To: skiboot@lists.ozlabs.org Date: Sat, 25 Jun 2016 08:47:49 +1000 Message-Id: <1466808476-32690-26-git-send-email-benh@kernel.crashing.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1466808476-32690-1-git-send-email-benh@kernel.crashing.org> References: <1466808476-32690-1-git-send-email-benh@kernel.crashing.org> Subject: [Skiboot] [PATCH 26/33] interrupts: Expose irq_source and change prototypes of all ops X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" 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 --- core/interrupts.c | 105 +++++++++++++++++++++++++++++++-------------------- hw/npu.c | 21 +++++------ hw/p7ioc-phb.c | 21 ++++++----- hw/p7ioc.c | 13 ++++--- hw/phb3.c | 37 ++++++++---------- hw/phb4.c | 10 ++--- hw/psi.c | 29 +++++++------- include/interrupts.h | 24 +++++++++--- 8 files changed, 144 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) } } + diff --git a/hw/npu.c b/hw/npu.c index 34b4f26..7944f9a 100644 --- a/hw/npu.c +++ b/hw/npu.c @@ -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)) @@ -1898,3 +1894,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); } + diff --git a/hw/p7ioc.c b/hw/p7ioc.c index 85a0a51..db758bb 100644 --- a/hw/p7ioc.c +++ b/hw/p7ioc.c @@ -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); @@ -678,3 +678,4 @@ void probe_p7ioc(void) p7ioc_create_hub(np); } + diff --git a/hw/phb3.c b/hw/phb3.c index 8e4c544..4d0b683 100644 --- a/hw/phb3.c +++ b/hw/phb3.c @@ -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); } + diff --git a/hw/phb4.c b/hw/phb4.c index cf5742b..e0fb266 100644 --- a/hw/phb4.c +++ b/hw/phb4.c @@ -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; diff --git a/hw/psi.c b/hw/psi.c index 0823ec8..b02863e 100644 --- a/hw/psi.c +++ b/hw/psi.c @@ -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 0380c59..9926d72 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); @@ -299,3 +310,4 @@ extern bool irq_source_eoi(uint32_t isn); #endif /* __INTERRUPTS_H */ +