From patchwork Mon Oct 13 08:56:20 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Zyngier X-Patchwork-Id: 38643 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ee0-f69.google.com (mail-ee0-f69.google.com [74.125.83.69]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id D864920973 for ; Mon, 13 Oct 2014 08:56:34 +0000 (UTC) Received: by mail-ee0-f69.google.com with SMTP id b57sf566449eek.8 for ; Mon, 13 Oct 2014 01:56:34 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:message-id:date:from:user-agent :mime-version:to:cc:subject:references:in-reply-to:sender:precedence :list-id:x-original-sender:x-original-authentication-results :mailing-list:list-post:list-help:list-archive:list-unsubscribe :content-type:content-transfer-encoding; bh=rYCvrVtsP9jw7bZD1J6tB9A/zQA6GvgI3BXCHDrQln0=; b=CS0g9+ANMbig+ezrYwWYBB2/9ONyUIaMUMAdFUAw/9oytigPpjPgarQ9otnvuCPU3j wDEZe+TEFVO0uT1VddpeV10fzzy3yBRUznNZKGZQQHDDOBzZCb08PwJVF5JGhMkDGprU qACgJNyNfLarbHumg5sz6Lb2VKHWS8SNOS1e+9G+EFSg8e3SrIl/aa6t6vZ6Yy77SqW/ pbCi5dMXyTvzgr1gg/y+KEXNSxWFW0ypq8GMTg44W8kn8Un6SspJ4bKlEpsu+tIDdsaV ntg4aZ4ncOiSgrxiO8/NzCkR5SUns5sDWbR++eArWLvOrZJDPFduSe+eVqBY6SHuFE0o vQDQ== X-Gm-Message-State: ALoCoQmw9WP2Yjkpjo+Mcagfsd/D32gV2DhM+Wd39dqivgSzDc9xKwSNgsj/fLGbJjEbM5IT5zRj X-Received: by 10.152.6.9 with SMTP id w9mr82858law.7.1413190594027; Mon, 13 Oct 2014 01:56:34 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.44.169 with SMTP id f9ls443394lam.11.gmail; Mon, 13 Oct 2014 01:56:33 -0700 (PDT) X-Received: by 10.112.135.137 with SMTP id ps9mr22615051lbb.24.1413190593543; Mon, 13 Oct 2014 01:56:33 -0700 (PDT) Received: from mail-lb0-f177.google.com (mail-lb0-f177.google.com [209.85.217.177]) by mx.google.com with ESMTPS id ir4si21122792lac.116.2014.10.13.01.56.33 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 13 Oct 2014 01:56:33 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.177 as permitted sender) client-ip=209.85.217.177; Received: by mail-lb0-f177.google.com with SMTP id w7so5970941lbi.22 for ; Mon, 13 Oct 2014 01:56:33 -0700 (PDT) X-Received: by 10.152.19.195 with SMTP id h3mr22508471lae.71.1413190593411; Mon, 13 Oct 2014 01:56:33 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.84.229 with SMTP id c5csp176666lbz; Mon, 13 Oct 2014 01:56:32 -0700 (PDT) X-Received: by 10.70.94.104 with SMTP id db8mr2119541pdb.124.1413190591723; Mon, 13 Oct 2014 01:56:31 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id lz2si8978916pdb.43.2014.10.13.01.56.31 for ; Mon, 13 Oct 2014 01:56:31 -0700 (PDT) Received-SPF: none (google.com: linux-kernel-owner@vger.kernel.org does not designate permitted sender hosts) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753441AbaJMI43 (ORCPT + 27 others); Mon, 13 Oct 2014 04:56:29 -0400 Received: from service87.mimecast.com ([91.220.42.44]:52981 "EHLO service87.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753146AbaJMI4Z convert rfc822-to-8bit (ORCPT ); Mon, 13 Oct 2014 04:56:25 -0400 Received: from cam-owa1.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.21]) by service87.mimecast.com; Mon, 13 Oct 2014 09:56:22 +0100 Received: from [10.1.209.143] ([10.1.255.212]) by cam-owa1.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.3959); Mon, 13 Oct 2014 09:56:21 +0100 Message-ID: <543B93B4.3040404@arm.com> Date: Mon, 13 Oct 2014 09:56:20 +0100 From: Marc Zyngier User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130330 Thunderbird/17.0.5 MIME-Version: 1.0 To: "Joe.C" , Thomas Gleixner , Jiang Liu CC: "arm@kernel.org" , Rob Herring , Mark Rutland , "linux-arm-kernel@lists.infradead.org" , "srv_heupstream@mediatek.com" , "yingjoe.chen@gmail.com" , "hc.yen@mediatek.com" , "eddie.huang@mediatek.com" , "nathan.chung@mediatek.com" , "yh.chen@mediatek.com" , Sascha Hauer , Olof Johansson , Arnd Bergmann , Pawel Moll , Russell King , Jason Cooper , Benjamin Herrenschmidt , Santosh Shilimkar , Matt Porter , Marc Carino , Florian Fainelli , Sricharan R , Matthias Brugger , "grant.likely@linaro.org" , "devicetree@vger.kernel.org" , "linux-kernel@vger.kernel.org" Subject: Re: [PATCH v3 3/7] irqchip: gic: Support hierarchy irq domain. References: <1412864980-20273-1-git-send-email-yingjoe.chen@mediatek.com> <1412864980-20273-4-git-send-email-yingjoe.chen@mediatek.com> In-Reply-To: <1412864980-20273-4-git-send-email-yingjoe.chen@mediatek.com> X-Enigmail-Version: 1.4.6 X-OriginalArrivalTime: 13 Oct 2014 08:56:21.0699 (UTC) FILETIME=[8F771130:01CFE6C3] X-MC-Unique: 114101309562201501 Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: marc.zyngier@arm.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.177 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , On 09/10/14 15:29, Joe.C wrote: > From: "Joe.C" > > Add support to use gic as a parent for stacked irq domain. > > Signed-off-by: Joe.C > --- > drivers/irqchip/irq-gic.c | 56 ++++++++++++++++++++++++++++++++++++++++------- > 1 file changed, 48 insertions(+), 8 deletions(-) > > diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c > index dda6dbc..17f5aa6 100644 > --- a/drivers/irqchip/irq-gic.c > +++ b/drivers/irqchip/irq-gic.c > @@ -767,19 +767,17 @@ void __init gic_init_physaddr(struct device_node *node) > static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, > irq_hw_number_t hw) > { > + irq_domain_set_hwirq_and_chip(d, irq, hw, &gic_chip, d->host_data); > if (hw < 32) { > irq_set_percpu_devid(irq); > - irq_set_chip_and_handler(irq, &gic_chip, > - handle_percpu_devid_irq); > + irq_set_handler(irq, handle_percpu_devid_irq); > set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN); > } else { > - irq_set_chip_and_handler(irq, &gic_chip, > - handle_fasteoi_irq); > + irq_set_handler(irq, handle_fasteoi_irq); > set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); > > gic_routable_irq_domain_ops->map(d, irq, hw); > } > - irq_set_chip_data(irq, d->host_data); > return 0; > } > > @@ -795,8 +793,6 @@ static int gic_irq_domain_xlate(struct irq_domain *d, > { > unsigned long ret = 0; > > - if (d->of_node != controller) > - return -EINVAL; > if (intsize < 3) > return -EINVAL; > > @@ -839,6 +835,46 @@ static struct notifier_block gic_cpu_notifier = { > }; > #endif > > + > +#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY > +static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, > + unsigned int nr_irqs, void *arg) > +{ > + int i, ret; > + irq_hw_number_t hwirq; > + unsigned int type = IRQ_TYPE_NONE; > + struct of_phandle_args *irq_data = arg; > + > + ret = gic_irq_domain_xlate(domain, irq_data->np, irq_data->args, > + irq_data->args_count, &hwirq, &type); > + if (ret) > + return ret; > + > + for (i = 0; i < nr_irqs; i++) > + gic_irq_domain_map(domain, virq+i, hwirq+i); > + > + return 0; > +} > + > +static void gic_irq_domain_free(struct irq_domain *domain, unsigned int virq, > + unsigned int nr_irqs) > +{ > + int i; > + > + for (i = 0; i < nr_irqs; i++) { > + irq_set_handler(virq + i, NULL); > + irq_domain_set_hwirq_and_chip(domain, virq + i, 0, NULL, NULL); > + } > +} > + > +static const struct irq_domain_ops gic_irq_domain_hierarchy_ops = { > + .alloc = gic_irq_domain_alloc, > + .free = gic_irq_domain_free, > +}; > +#else > +#define gic_irq_domain_hierarchy_ops 0 > +#endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */ > + > static const struct irq_domain_ops gic_irq_domain_ops = { > .map = gic_irq_domain_map, > .unmap = gic_irq_domain_unmap, > @@ -952,7 +988,11 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, > > gic_irqs -= hwirq_base; /* calculate # of irqs to allocate */ > > - if (of_property_read_u32(node, "arm,routable-irqs", > + if (IS_ENABLED(CONFIG_IRQ_DOMAIN_HIERARCHY) && > + of_find_property(node, "arm,irq-domain-hierarchy", NULL)) > + gic->domain = irq_domain_add_linear(node, gic_irqs, > + &gic_irq_domain_hierarchy_ops, gic); > + else if (of_property_read_u32(node, "arm,routable-irqs", > &nr_routable_irqs)) { > irq_base = irq_alloc_descs(irq_start, 16, gic_irqs, > numa_node_id()); > So I've been playing with this over the weekend (with quite a few tweaks), and I'm hitting a not-so-nice effect of the automatic platform device creation from the device tree. What happens is the following: - Kernel starts - GIC gets initialized with a linear domain supporting hierarchy - per-cpu timers are up and running - platform devices get created from the device tree: - irq_of_parse_and_map() - irq_create_of_mapping() - irq_domain_alloc_irqs() Here, we start re-allocating interrupts that have already been allocated (the timer interrupts). This has a side effect of nuking the percpu_dev_id, and everything explodes on the next timer tick. Grmbl. The main issue here is that we have a single path that: - translates the interrupt from DT to HW - configures the interrupts and that we use it more than once. The non-hierarchy path works because the the "map" operation takes place only once, and virtual interrupts are allocated upfront. When we switch to this more dynamic way of doing things, the fact that the virqs only available at allocation time is screwing us up. I can see a way out of this, which would involve having a way of detecting that a hwirq has already been allocated (which requires having the xlate callback instantiated). Something like this (not even compile-tested): } Thoughts? M. diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index dd8d3ab..6a45821 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -479,6 +479,21 @@ unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data) } if (irq_domain_is_hierarchy(domain)) { + if (domain->ops->xlate) { + /* + * If we've already configured this interrupt, + * don't do it again, or hell will break loose. + */ + if (domain->ops->xlate(domain, irq_data->np, + irq_data->args, + irq_data->args_count, + &hwirq, &type)) + return 0; + + virq = irq_find_mapping(domain, hwirq); + if (virq) + return virq; + } virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, irq_data); return virq <= 0 ? 0 : virq;