From patchwork Mon Jun 30 08:53:08 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Thompson X-Patchwork-Id: 32682 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ob0-f200.google.com (mail-ob0-f200.google.com [209.85.214.200]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id DAC30203F4 for ; Mon, 30 Jun 2014 08:58:16 +0000 (UTC) Received: by mail-ob0-f200.google.com with SMTP id wm4sf50015020obc.7 for ; Mon, 30 Jun 2014 01:58: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: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=Nrma1N9NArPUd+ivyFBAwng4npZ/ST0Rklamt/1tpVkP3dHOn/swk80lBiC4SIo3kg OrMVlgEYVjvgeyVLG6kIT+C9EEME44HEAM0MHiXntL2QwBH9ruX3B/VbtsxYNhssUKI3 xwXnkQ3A2eXB6oPZ+zAE+KDCCPrnXPVTS46I7w1T2VqkIkjYvE4KwCaNZ58SBuiCAkTE E7+Je4dhdzOlbY8MRahW8s1fGowErA5Lfx88YAcKRFzsGgSdWOJLBDTMFXsAH5u2paDv et9wQzotonrdswYzQ+odsRfYQ/TwUWjxUjQIgdBt7gDvLIZgDvc4NH/36I78lAsHxJDf bt9Q== X-Gm-Message-State: ALoCoQl69htKMrNr1bG40uYkEB6tG833koJYA7EnGK4j6nAZqTpAHK9aYasNeQTcs14ALaXF/Lax X-Received: by 10.50.98.69 with SMTP id eg5mr15564245igb.7.1404118696521; Mon, 30 Jun 2014 01:58:16 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.104.177 with SMTP id a46ls1417062qgf.7.gmail; Mon, 30 Jun 2014 01:58:16 -0700 (PDT) X-Received: by 10.52.159.226 with SMTP id xf2mr31110663vdb.14.1404118696396; Mon, 30 Jun 2014 01:58:16 -0700 (PDT) Received: from mail-vc0-f175.google.com (mail-vc0-f175.google.com [209.85.220.175]) by mx.google.com with ESMTPS id jg5si9741481vdb.70.2014.06.30.01.58.16 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 30 Jun 2014 01:58:16 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.175 as permitted sender) client-ip=209.85.220.175; Received: by mail-vc0-f175.google.com with SMTP id hy4so7217509vcb.20 for ; Mon, 30 Jun 2014 01:58:16 -0700 (PDT) X-Received: by 10.52.26.237 with SMTP id o13mr30808466vdg.1.1404118696295; Mon, 30 Jun 2014 01:58:16 -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 tc5csp120685vcb; Mon, 30 Jun 2014 01:58:15 -0700 (PDT) X-Received: by 10.194.92.177 with SMTP id cn17mr43619648wjb.71.1404118695205; Mon, 30 Jun 2014 01:58:15 -0700 (PDT) Received: from mail-we0-f179.google.com (mail-we0-f179.google.com [74.125.82.179]) by mx.google.com with ESMTPS id z17si9240191wiv.4.2014.06.30.01.58.14 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 30 Jun 2014 01:58:15 -0700 (PDT) Received-SPF: pass (google.com: domain of daniel.thompson@linaro.org designates 74.125.82.179 as permitted sender) client-ip=74.125.82.179; Received: by mail-we0-f179.google.com with SMTP id w62so7648545wes.24 for ; Mon, 30 Jun 2014 01:58:14 -0700 (PDT) X-Received: by 10.194.189.50 with SMTP id gf18mr43296894wjc.13.1404118694789; Mon, 30 Jun 2014 01:58:14 -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 l5sm28993317wif.22.2014.06.30.01.58.13 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 30 Jun 2014 01:58:14 -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 v7 1/4] arm: fiq: Add callbacks to manage FIQ routings Date: Mon, 30 Jun 2014 09:53:08 +0100 Message-Id: <1404118391-3850-2-git-send-email-daniel.thompson@linaro.org> X-Mailer: git-send-email 1.9.3 In-Reply-To: <1404118391-3850-1-git-send-email-daniel.thompson@linaro.org> References: <1403623097-1153-1-git-send-email-daniel.thompson@linaro.org> <1404118391-3850-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.175 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);