From patchwork Tue Sep 2 13:00:35 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Thompson X-Patchwork-Id: 4825301 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 81CB3C0338 for ; Tue, 2 Sep 2014 13:06:03 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id BBA02201BB for ; Tue, 2 Sep 2014 13:05:57 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 6E38820170 for ; Tue, 2 Sep 2014 13:05:56 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1XOniU-00088L-Ut; Tue, 02 Sep 2014 13:01:46 +0000 Received: from mail-wg0-f46.google.com ([74.125.82.46]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1XOniN-00084G-33 for linux-arm-kernel@lists.infradead.org; Tue, 02 Sep 2014 13:01:40 +0000 Received: by mail-wg0-f46.google.com with SMTP id x13so6818284wgg.29 for ; Tue, 02 Sep 2014 06:01:16 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=jvDJMUwC8eNBsbFkMKsYqrbqekkeO+l+ms/INEOn9GM=; b=VfjJvA8lVoJnPkr+ML+1CpRENHnv60dvPn88Cf/pMPxPW+Sv3DYDZcaDcA1rMrJE57 b3+K5IPQBrvE5zuU+fjPrc0arB/iFO6dWjCRNKNn4YNT9CUMlwrcCrSmLhYpJ+Ko/2jY FloY4AIywZd5AzqM9fh9b0BZ+0xom5v6Mr3kSPfdeoCl2ZZJwN++aVPM+/n95CgjWarM l0Y+jnxe/VKXvAVu5OjuGBC1r6SLlwGbtE/nsN9uiYpZ1KOKXFbjPo4DqX1H+2SRCmmB TeMvJ3s53W5eS2IyV17rdvJfXb4OX1w8KXOv2VoD20B2Kr7juNRk+55No7bKutJKf56y sEVA== X-Gm-Message-State: ALoCoQkL1ID6XSWTRQrh7kpoGLoI8aiBXV/TXAPywAA1w3Y7MwHAZrDnddHE+jVnt8pZqCux3aUC X-Received: by 10.194.5.162 with SMTP id t2mr2938173wjt.97.1409662876514; Tue, 02 Sep 2014 06:01: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 ec2sm34928892wib.19.2014.09.02.06.01.14 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 02 Sep 2014 06:01:15 -0700 (PDT) From: Daniel Thompson To: Russell King Subject: [PATCH v11 01/19] arm: fiq: Add callbacks to manage FIQ routings Date: Tue, 2 Sep 2014 14:00:35 +0100 Message-Id: <1409662853-29313-2-git-send-email-daniel.thompson@linaro.org> X-Mailer: git-send-email 1.9.3 In-Reply-To: <1409662853-29313-1-git-send-email-daniel.thompson@linaro.org> References: <1408466769-20004-1-git-send-email-daniel.thompson@linaro.org> <1409662853-29313-1-git-send-email-daniel.thompson@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140902_060139_444081_6104C447 X-CRM114-Status: GOOD ( 19.02 ) X-Spam-Score: -0.7 (/) Cc: Daniel Thompson , linaro-kernel@lists.linaro.org, Catalin Marinas , patches@linaro.org, kgdb-bugreport@lists.sourceforge.net, Linus Walleij , Nicolas Pitre , linux-kernel@vger.kernel.org, Frederic Weisbecker , Anton Vorontsov , Ben Dooks , John Stultz , Fabio Estevam , Colin Cross , kernel-team@android.com, Dave Martin , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-3.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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);