From patchwork Mon Aug 18 13:40:49 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Thompson X-Patchwork-Id: 35498 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-qa0-f72.google.com (mail-qa0-f72.google.com [209.85.216.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 34AF620676 for ; Mon, 18 Aug 2014 13:41:19 +0000 (UTC) Received: by mail-qa0-f72.google.com with SMTP id cm18sf15212002qab.7 for ; Mon, 18 Aug 2014 06:41:19 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=jvDJMUwC8eNBsbFkMKsYqrbqekkeO+l+ms/INEOn9GM=; b=j4cyfVK622KiVPDrRCTezRRyHtBzeczqAYbnXJp0zR/jQc+6/aNaqh3F1oVSBr0BeI TEUDrcc3fBXwCqA/RauSG+EuGgwSOh0d9xLFypMF6sL3UyGDmKUtRxrGS+BjeP7QfFsX 01DaOhKeLX2/qu4Cc8Jnctqesudt2QeihAQdP8s+fJv4zVnwCe5v8paxKK2GgqJLHOoi gIn8Khc/nT+DWRdTQKQAcYzzaYzEZsCr1CkjL/mz9Y4xuAWeT3M2AYjOQ8UyaE+Ag5RE pKPZEp8iV9Qw9Mn76RXM3z1PutBzDItXrJOvLky2Tqv4LhswfcASZvfC7g1nydNrr/kS Z0og== X-Gm-Message-State: ALoCoQmpkX9bvsWdPy3MfZu/c2LuC/qDdyxXhkct7f9/vy3qoSSHJAwjqgHIpUGbr2mUAe+u2Yu5 X-Received: by 10.236.108.172 with SMTP id q32mr6138736yhg.0.1408369279076; Mon, 18 Aug 2014 06:41:19 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.27.176 with SMTP id 45ls2338151qgx.16.gmail; Mon, 18 Aug 2014 06:41:19 -0700 (PDT) X-Received: by 10.52.51.203 with SMTP id m11mr148242vdo.72.1408369278960; Mon, 18 Aug 2014 06:41:18 -0700 (PDT) Received: from mail-vc0-f176.google.com (mail-vc0-f176.google.com [209.85.220.176]) by mx.google.com with ESMTPS id l3si7122072vdc.59.2014.08.18.06.41.18 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 18 Aug 2014 06:41:18 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.176 as permitted sender) client-ip=209.85.220.176; Received: by mail-vc0-f176.google.com with SMTP id id10so5624531vcb.7 for ; Mon, 18 Aug 2014 06:41:18 -0700 (PDT) X-Received: by 10.221.5.137 with SMTP id og9mr25187195vcb.18.1408369278848; Mon, 18 Aug 2014 06:41:18 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.221.37.5 with SMTP id tc5csp153383vcb; Mon, 18 Aug 2014 06:41:18 -0700 (PDT) X-Received: by 10.194.92.244 with SMTP id cp20mr2686468wjb.135.1408369277633; Mon, 18 Aug 2014 06:41:17 -0700 (PDT) Received: from mail-wi0-f181.google.com (mail-wi0-f181.google.com [209.85.212.181]) by mx.google.com with ESMTPS id s7si16882510wib.69.2014.08.18.06.41.17 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 18 Aug 2014 06:41:17 -0700 (PDT) Received-SPF: pass (google.com: domain of daniel.thompson@linaro.org designates 209.85.212.181 as permitted sender) client-ip=209.85.212.181; Received: by mail-wi0-f181.google.com with SMTP id bs8so3670389wib.2 for ; Mon, 18 Aug 2014 06:41:17 -0700 (PDT) X-Received: by 10.180.35.134 with SMTP id h6mr42340021wij.0.1408369276998; Mon, 18 Aug 2014 06:41:16 -0700 (PDT) Received: from sundance.lan (cpc4-aztw19-0-0-cust157.18-1.cable.virginm.net. [82.33.25.158]) by mx.google.com with ESMTPSA id y6sm6351438wia.0.2014.08.18.06.41.15 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 18 Aug 2014 06:41:15 -0700 (PDT) From: Daniel Thompson To: Russell King Cc: Daniel Thompson , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kgdb-bugreport@lists.sourceforge.net, patches@linaro.org, linaro-kernel@lists.linaro.org, John Stultz , Anton Vorontsov , Colin Cross , kernel-team@android.com, Rob Herring , Linus Walleij , Ben Dooks , Catalin Marinas , Dave Martin , Fabio Estevam , Frederic Weisbecker , Nicolas Pitre Subject: [PATCH v9 01/16] arm: fiq: Add callbacks to manage FIQ routings Date: Mon, 18 Aug 2014 14:40:49 +0100 Message-Id: <1408369264-14242-2-git-send-email-daniel.thompson@linaro.org> X-Mailer: git-send-email 1.9.3 In-Reply-To: <1408369264-14242-1-git-send-email-daniel.thompson@linaro.org> References: <1404979427-12943-1-git-send-email-daniel.thompson@linaro.org> <1408369264-14242-1-git-send-email-daniel.thompson@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: daniel.thompson@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.176 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Currently enable_fiq/disable_fiq use a simple offset to convert an IRQ virq into a FIQ virq. This is too inflexible for multi-platform kernels and makes runtime error checking impossible. We solve this by introducing a flexible mapping that allows interrupt controllers that support FIQ to register those mappings. This, in turn, makes it much possible for drivers in DT kernels to install FIQ handlers without knowing anything about the interrupt controller. Signed-off-by: Daniel Thompson Acked-by: Nicolas Pitre Cc: Russell King Cc: Fabio Estevam --- arch/arm/include/asm/fiq.h | 8 ++++ arch/arm/kernel/fiq.c | 103 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/fiq.h b/arch/arm/include/asm/fiq.h index d493d0b..ed44528 100644 --- a/arch/arm/include/asm/fiq.h +++ b/arch/arm/include/asm/fiq.h @@ -16,8 +16,14 @@ #ifndef __ASM_FIQ_H #define __ASM_FIQ_H +#include #include +struct fiq_chip { + void (*fiq_enable)(struct irq_data *data); + void (*fiq_disable)(struct irq_data *data); +}; + struct fiq_handler { struct fiq_handler *next; /* Name @@ -38,6 +44,8 @@ extern void release_fiq(struct fiq_handler *f); extern void set_fiq_handler(void *start, unsigned int length); extern void enable_fiq(int fiq); extern void disable_fiq(int fiq); +extern bool has_fiq(int fiq); +extern void fiq_register_mapping(int irq, struct fiq_chip *chip); /* helpers defined in fiqasm.S: */ extern void __set_fiq_regs(unsigned long const *regs); diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index 918875d..5d831cf 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c @@ -40,6 +40,9 @@ #include #include #include +#include +#include +#include #include #include @@ -52,7 +55,15 @@ (unsigned)&vector_fiq_offset; \ }) +struct fiq_data { + struct fiq_chip *fiq_chip; + struct irq_data *irq_data; +}; + static unsigned long no_fiq_insn; +static int fiq_start = -1; +static RADIX_TREE(fiq_data_tree, GFP_KERNEL); +static DEFINE_MUTEX(fiq_data_mutex); /* Default reacquire function * - we always relinquish FIQ control @@ -127,18 +138,65 @@ void release_fiq(struct fiq_handler *f) while (current_fiq->fiq_op(current_fiq->dev_id, 0)); } -static int fiq_start; +static struct fiq_data *lookup_fiq_data(int fiq) +{ + struct fiq_data *data; + + rcu_read_lock(); + data = radix_tree_lookup(&fiq_data_tree, fiq); + rcu_read_unlock(); + + return data; +} void enable_fiq(int fiq) { + struct fiq_data *data = lookup_fiq_data(fiq); + + if (data) { + if (data->fiq_chip->fiq_enable) + data->fiq_chip->fiq_enable(data->irq_data); + enable_irq(fiq); + return; + } + + if (WARN_ON(fiq_start == -1)) + return; + enable_irq(fiq + fiq_start); } void disable_fiq(int fiq) { + struct fiq_data *data = lookup_fiq_data(fiq); + + if (data) { + if (data->fiq_chip->fiq_disable) + data->fiq_chip->fiq_disable(data->irq_data); + disable_irq(fiq); + return; + } + + if (WARN_ON(fiq_start == -1)) + return; + disable_irq(fiq + fiq_start); } +bool has_fiq(int fiq) +{ + struct fiq_data *data = lookup_fiq_data(fiq); + + if (data) + return true; + + if (fiq_start == -1) + return false; + + return fiq >= fiq_start; +} +EXPORT_SYMBOL(has_fiq); + EXPORT_SYMBOL(set_fiq_handler); EXPORT_SYMBOL(__set_fiq_regs); /* defined in fiqasm.S */ EXPORT_SYMBOL(__get_fiq_regs); /* defined in fiqasm.S */ @@ -147,9 +205,50 @@ EXPORT_SYMBOL(release_fiq); EXPORT_SYMBOL(enable_fiq); EXPORT_SYMBOL(disable_fiq); +/* + * Add a mapping from a Linux irq to the fiq data. + */ +void fiq_register_mapping(int irq, struct fiq_chip *chip) +{ + struct fiq_data *fiq_data = NULL; + int res; + + /* fiq_register_mapping can't be mixed with init_FIQ */ + BUG_ON(fiq_start != -1); + + fiq_data = kmalloc(sizeof(*fiq_data), GFP_KERNEL); + if (!fiq_data) + goto err; + + fiq_data->fiq_chip = chip; + fiq_data->irq_data = irq_get_irq_data(irq); + BUG_ON(!fiq_data->irq_data); + + mutex_lock(&fiq_data_mutex); + res = radix_tree_insert(&fiq_data_tree, irq, fiq_data); + mutex_unlock(&fiq_data_mutex); + if (res) + goto err; + + return; + +err: + kfree(fiq_data); + pr_err("fiq: Cannot register mapping %d\n", irq); +} + +/* + * Set the offset between normal IRQs and their FIQ shadows. + */ void __init init_FIQ(int start) { + fiq_start = start; +} + +static int __init init_default_fiq_handler(void) +{ unsigned offset = FIQ_OFFSET; no_fiq_insn = *(unsigned long *)(0xffff0000 + offset); - fiq_start = start; + return 0; } +pure_initcall(init_default_fiq_handler);