From patchwork Sat Jan 30 14:07:10 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frederic Barrat X-Patchwork-Id: 575988 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 6E0E914032B for ; Sun, 31 Jan 2016 01:15:26 +1100 (AEDT) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 51E821A0BE2 for ; Sun, 31 Jan 2016 01:15:26 +1100 (AEDT) X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Received: from e06smtp10.uk.ibm.com (e06smtp10.uk.ibm.com [195.75.94.106]) (using TLSv1 with cipher CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4E15A1A003C for ; Sun, 31 Jan 2016 01:07:31 +1100 (AEDT) Received: from localhost by e06smtp10.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Sat, 30 Jan 2016 14:07:29 -0000 Received: from d06dlp01.portsmouth.uk.ibm.com (9.149.20.13) by e06smtp10.uk.ibm.com (192.168.101.140) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Sat, 30 Jan 2016 14:07:27 -0000 X-IBM-Helo: d06dlp01.portsmouth.uk.ibm.com X-IBM-MailFrom: fbarrat@linux.vnet.ibm.com X-IBM-RcptTo: linuxppc-dev@lists.ozlabs.org Received: from b06cxnps4076.portsmouth.uk.ibm.com (d06relay13.portsmouth.uk.ibm.com [9.149.109.198]) by d06dlp01.portsmouth.uk.ibm.com (Postfix) with ESMTP id AA83B17D8056 for ; Sat, 30 Jan 2016 14:07:36 +0000 (GMT) Received: from d06av07.portsmouth.uk.ibm.com (d06av07.portsmouth.uk.ibm.com [9.149.37.248]) by b06cxnps4076.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id u0UE7QUc2556308 for ; Sat, 30 Jan 2016 14:07:26 GMT Received: from d06av07.portsmouth.uk.ibm.com (localhost [127.0.0.1]) by d06av07.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id u0UE7QYP031075 for ; Sat, 30 Jan 2016 09:07:26 -0500 Received: from borneo.ibm.com (icon-9-167-233-193.megacenter.de.ibm.com [9.167.233.193]) by d06av07.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id u0UE7JPm030968; Sat, 30 Jan 2016 09:07:25 -0500 From: Frederic Barrat To: imunsie@au1.ibm.com, michael.neuling@au1.ibm.com, linuxppc-dev@lists.ozlabs.org Subject: [PATCH v2 07/16] cxl: IRQ allocation for guests Date: Sat, 30 Jan 2016 15:07:10 +0100 Message-Id: <1454162839-24407-8-git-send-email-fbarrat@linux.vnet.ibm.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1454162839-24407-1-git-send-email-fbarrat@linux.vnet.ibm.com> References: <1454162839-24407-1-git-send-email-fbarrat@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16013014-0041-0000-0000-0000071B3554 X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" The PSL interrupt is not going to be multiplexed in a guest, so an interrupt will be allocated for it for each context. It will still be the first interrupt found in the first interrupt range, but is treated almost like any other AFU interrupt when creating/deleting the context. Only the handler is different. Rework the code so that the range 0 is treated like the other ranges. Co-authored-by: Christophe Lombard Signed-off-by: Frederic Barrat Signed-off-by: Christophe Lombard --- drivers/misc/cxl/irq.c | 69 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 14 deletions(-) diff --git a/drivers/misc/cxl/irq.c b/drivers/misc/cxl/irq.c index 5033869..9e78094 100644 --- a/drivers/misc/cxl/irq.c +++ b/drivers/misc/cxl/irq.c @@ -19,6 +19,13 @@ #include "cxl.h" #include "trace.h" +static int afu_irq_range_start(void) +{ + if (cpu_has_feature(CPU_FTR_HVMODE)) + return 1; + return 0; +} + static irqreturn_t schedule_cxl_fault(struct cxl_context *ctx, u64 dsisr, u64 dar) { ctx->dsisr = dsisr; @@ -117,11 +124,23 @@ static irqreturn_t cxl_irq_afu(int irq, void *data) { struct cxl_context *ctx = data; irq_hw_number_t hwirq = irqd_to_hwirq(irq_get_irq_data(irq)); - int irq_off, afu_irq = 1; + int irq_off, afu_irq = 0; __u16 range; int r; - for (r = 1; r < CXL_IRQ_RANGES; r++) { + /* + * Look for the interrupt number. + * On bare-metal, we know the range 0 only contains the PSL + * interrupt so, we could start counting at range 1 and initialize + * afu_irq at 1. + * In a guest, range 0 also contains AFU interrupts, so it must + * be counted for, but we initialize afu_irq at 0 to take into + * account the PSL interrupt. + * + * For code-readability, it just seems easier to go over all + * the ranges. + */ + for (r = 0; r < CXL_IRQ_RANGES; r++) { irq_off = hwirq - ctx->irqs.offset[r]; range = ctx->irqs.range[r]; if (irq_off >= 0 && irq_off < range) { @@ -131,7 +150,7 @@ static irqreturn_t cxl_irq_afu(int irq, void *data) afu_irq += range; } if (unlikely(r >= CXL_IRQ_RANGES)) { - WARN(1, "Recieved AFU IRQ out of range for pe %i (virq %i hwirq %lx)\n", + WARN(1, "Received AFU IRQ out of range for pe %i (virq %i hwirq %lx)\n", ctx->pe, irq, hwirq); return IRQ_HANDLED; } @@ -141,7 +160,7 @@ static irqreturn_t cxl_irq_afu(int irq, void *data) afu_irq, ctx->pe, irq, hwirq); if (unlikely(!ctx->irq_bitmap)) { - WARN(1, "Recieved AFU IRQ for context with no IRQ bitmap\n"); + WARN(1, "Received AFU IRQ for context with no IRQ bitmap\n"); return IRQ_HANDLED; } spin_lock(&ctx->lock); @@ -227,17 +246,33 @@ int afu_allocate_irqs(struct cxl_context *ctx, u32 count) { int rc, r, i, j = 1; struct cxl_irq_name *irq_name; + int alloc_count; + + /* + * In native mode, range 0 is reserved for the multiplexed + * PSL interrupt. It has been allocated when the AFU was initialized. + * + * In a guest, the PSL interrupt is not mutliplexed, but per-context, + * and is the first interrupt from range 0. It still needs to be + * allocated, so bump the count by one. + */ + if (cpu_has_feature(CPU_FTR_HVMODE)) + alloc_count = count; + else + alloc_count = count + 1; /* Initialize the list head to hold irq names */ INIT_LIST_HEAD(&ctx->irq_names); if ((rc = cxl_ops->alloc_irq_ranges(&ctx->irqs, ctx->afu->adapter, - count))) + alloc_count))) return rc; - /* Multiplexed PSL Interrupt */ - ctx->irqs.offset[0] = ctx->afu->psl_hwirq; - ctx->irqs.range[0] = 1; + if (cpu_has_feature(CPU_FTR_HVMODE)) { + /* Multiplexed PSL Interrupt */ + ctx->irqs.offset[0] = ctx->afu->psl_hwirq; + ctx->irqs.range[0] = 1; + } ctx->irq_count = count; ctx->irq_bitmap = kcalloc(BITS_TO_LONGS(count), @@ -249,7 +284,7 @@ int afu_allocate_irqs(struct cxl_context *ctx, u32 count) * Allocate names first. If any fail, bail out before allocating * actual hardware IRQs. */ - for (r = 1; r < CXL_IRQ_RANGES; r++) { + for (r = afu_irq_range_start(); r < CXL_IRQ_RANGES; r++) { for (i = 0; i < ctx->irqs.range[r]; i++) { irq_name = kmalloc(sizeof(struct cxl_irq_name), GFP_KERNEL); @@ -279,15 +314,21 @@ static void afu_register_hwirqs(struct cxl_context *ctx) { irq_hw_number_t hwirq; struct cxl_irq_name *irq_name; - int r,i; + int r, i; + irqreturn_t (*handler)(int irq, void *data); /* We've allocated all memory now, so let's do the irq allocations */ irq_name = list_first_entry(&ctx->irq_names, struct cxl_irq_name, list); - for (r = 1; r < CXL_IRQ_RANGES; r++) { + for (r = afu_irq_range_start(); r < CXL_IRQ_RANGES; r++) { hwirq = ctx->irqs.offset[r]; for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) { - cxl_map_irq(ctx->afu->adapter, hwirq, - cxl_irq_afu, ctx, irq_name->name); + if (r == 0 && i == 0) + /* PSL interrupt, only for guest */ + handler = cxl_ops->psl_interrupt; + else + handler = cxl_irq_afu; + cxl_map_irq(ctx->afu->adapter, hwirq, handler, ctx, + irq_name->name); irq_name = list_next_entry(irq_name, list); } } @@ -311,7 +352,7 @@ void afu_release_irqs(struct cxl_context *ctx, void *cookie) unsigned int virq; int r, i; - for (r = 1; r < CXL_IRQ_RANGES; r++) { + for (r = afu_irq_range_start(); r < CXL_IRQ_RANGES; r++) { hwirq = ctx->irqs.offset[r]; for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) { virq = irq_find_mapping(NULL, hwirq);