From patchwork Fri Jul 10 10:45:10 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Hanjun Guo X-Patchwork-Id: 51025 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wi0-f198.google.com (mail-wi0-f198.google.com [209.85.212.198]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 1352A2290A for ; Fri, 10 Jul 2015 10:46:17 +0000 (UTC) Received: by wizo10 with SMTP id o10sf3780459wiz.0 for ; Fri, 10 Jul 2015 03:46: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:delivered-to:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-type :content-transfer-encoding:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=iDJQIdyxPwPSzB8WR6mslisLer0Zv4OM5RtSSvrO5GA=; b=HzPeHWJP0KpbHFKpY1ilAkCab7JvNHqrbJllOz/uCgfBPMWa60rlGUsGDJFm7csxxY XRKUvBFqhMWsiLYf08+Hnf+RdMg8H28ceIOfnwPRIWur8qvVgiYBDlfGEDZYRVkLZ0IE lvoboik5vOzk3BcUzKSuX2J7roc3BbBgc8xnGtk+tqp2vW7BHEBd5CtbkPG13+O83CUP zx5qTcr8kH/DXoZQk0Ho4LnVtYkoc0ftRI/WzeSgZrGJtw0VrujNR66qghg1/a16XCwn SJ18ukHZCj3HDKjFAjcZ0woR2aGpAJD4dolJlRtlaJSdkmQat1yJL73rwh6VAnk0j8hH 5d5g== X-Gm-Message-State: ALoCoQlovF7wOAzOkgIzUMR5PW53bq6Bq6sjooklRu0272MSvHyJt0AqwYQZFGivQ6aS/Z0lDg4o X-Received: by 10.194.179.42 with SMTP id dd10mr10529459wjc.7.1436525176395; Fri, 10 Jul 2015 03:46:16 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.88.99 with SMTP id bf3ls1218079lab.21.gmail; Fri, 10 Jul 2015 03:46:16 -0700 (PDT) X-Received: by 10.112.77.103 with SMTP id r7mr18897118lbw.63.1436525176229; Fri, 10 Jul 2015 03:46:16 -0700 (PDT) Received: from mail-lb0-f173.google.com (mail-lb0-f173.google.com. [209.85.217.173]) by mx.google.com with ESMTPS id j10si7325187lbv.162.2015.07.10.03.46.15 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 10 Jul 2015 03:46:15 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.173 as permitted sender) client-ip=209.85.217.173; Received: by lbbpo10 with SMTP id po10so90285417lbb.3 for ; Fri, 10 Jul 2015 03:46:15 -0700 (PDT) X-Received: by 10.152.6.69 with SMTP id y5mr19149813lay.72.1436525175763; Fri, 10 Jul 2015 03:46:15 -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.108.230 with SMTP id hn6csp1287909lbb; Fri, 10 Jul 2015 03:46:14 -0700 (PDT) X-Received: by 10.66.136.39 with SMTP id px7mr40771055pab.141.1436525173486; Fri, 10 Jul 2015 03:46:13 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id ps1si13274315pbb.236.2015.07.10.03.46.12; Fri, 10 Jul 2015 03:46:13 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-acpi-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754285AbbGJKqK (ORCPT + 6 others); Fri, 10 Jul 2015 06:46:10 -0400 Received: from mail-pa0-f42.google.com ([209.85.220.42]:35278 "EHLO mail-pa0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754193AbbGJKqA (ORCPT ); Fri, 10 Jul 2015 06:46:00 -0400 Received: by pactm7 with SMTP id tm7so166726939pac.2 for ; Fri, 10 Jul 2015 03:45:59 -0700 (PDT) X-Received: by 10.66.228.73 with SMTP id sg9mr41275644pac.88.1436525159724; Fri, 10 Jul 2015 03:45:59 -0700 (PDT) Received: from localhost (211-79-127-12.veetime.com. [211.79.127.12]) by smtp.googlemail.com with ESMTPSA id i5sm9131090pat.42.2015.07.10.03.45.57 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Fri, 10 Jul 2015 03:45:58 -0700 (PDT) From: Hanjun Guo To: Marc Zyngier , Jason Cooper , Will Deacon , Catalin Marinas , "Rafael J. Wysocki" Cc: Thomas Gleixner , Jiang Liu , Lorenzo Pieralisi , Arnd Bergmann , Tomasz Nowicki , Grant Likely , Mark Brown , Wei Huang , linux-arm-kernel@lists.infradead.org, linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, linaro-acpi@lists.linaro.org, Hanjun Guo Subject: [PATCH v3 4/8] irqchip / gic: Add stacked irqdomain support for ACPI based GICv2 init Date: Fri, 10 Jul 2015 18:45:10 +0800 Message-Id: <1436525114-14425-5-git-send-email-hanjun.guo@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1436525114-14425-1-git-send-email-hanjun.guo@linaro.org> References: <1436525114-14425-1-git-send-email-hanjun.guo@linaro.org> MIME-Version: 1.0 Sender: linux-acpi-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: hanjun.guo@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.217.173 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: , For now, ACPI based GICv2 is using the irq_default_domain as the ACPI core domain which is not scalable, also we don't support stacked irq domains in ACPI, this patch is trying to implement that. Firstly, we need to find the irqdomain with GSI, because we use different model of mapping interrupt with device in ACPI than DT, in DT, we using the interrupt parent property to get the device node of irqchip for devices, that's why we need the matching function that match the device node with the one associated with the irqdomain. But for ACPI, we only can get the GSI which the device is using, no interrupt parent will be specified, then we need a mechanism to find GSI's (also the device's) irqdomain to make the code scalable. Thanks to the usage of GSI, it is a flat hwirq number which is unique in the system, then we can get its associated irq domain by matching the GSI supported by this irqchip (see drawings below), then we can live without the token pointer matching the interrupt controller as DT did. ------------ ---> gsi_base0 | | | | irqdomain <----| irqchip 0 | | | | | |____________| ---> gsi_end0 ------------ ---> gsi_base1 (probably gsi_end0+1) | | | | irqdomain <----| irqchip 1 | | | | | |____________| ---> gsi_end1 ..... if a device is using GSI n, then we can find GSI's irqdomain by matching gsi_base <= n <= gsi_end. For GIC, we only have one GICD, but the above model still valid. GICD structure in ACPI MADT defines System Vector Base in the GICD entry, which means the global system interrupt number where this GIC Distributor’s interrupt inputs start, then we can get the hwirq numbers supported by reading the register, so we can explictly get the GSI's associated irqdomain if the GSI is within the range of hwirq supported by this GICD. Secondly, pass the GSI as the arg for domain's ops alloc() function when register the GSI, then we can take advantage of stacked irqdomains. Signed-off-by: Hanjun Guo --- drivers/acpi/gsi.c | 78 ++++++++++++++++++++++++++++++++++++++--------- drivers/irqchip/irq-gic.c | 37 +++++++++++++--------- include/linux/acpi.h | 5 +++ 3 files changed, 90 insertions(+), 30 deletions(-) diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c index 38208f2..ba7de7f 100644 --- a/drivers/acpi/gsi.c +++ b/drivers/acpi/gsi.c @@ -3,6 +3,7 @@ * * Copyright (C) 2015 ARM Ltd. * Author: Lorenzo Pieralisi + * Hanjun Guo for stacked irqdomains support * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -14,6 +15,54 @@ enum acpi_irq_model_id acpi_irq_model; +struct gsi_cfg_data { + struct list_head list; + u32 gsi_base; + u32 gsi_end; + struct irq_domain *domain; +}; + +static LIST_HEAD(gsi_cfg_data_list); +static DEFINE_MUTEX(gsi_mutex); + +/* Init the gsi cfg data which is called by irqchip drivers */ +int gsi_cfg_data_add(struct irq_domain *domain, u32 gsi_base, u32 gsi_end) +{ + struct gsi_cfg_data *data; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->domain = domain; + data->gsi_base = gsi_base; + data->gsi_end = gsi_end; + + mutex_lock(&gsi_mutex); + list_add(&data->list, &gsi_cfg_data_list); + mutex_unlock(&gsi_mutex); + + return 0; +} + +/* Find irqdomain with GSI (hwirq number) */ +static struct irq_domain *acpi_find_irqdomain(u32 gsi) +{ + struct gsi_cfg_data *data; + struct irq_domain *domain = NULL; + + mutex_lock(&gsi_mutex); + list_for_each_entry(data, &gsi_cfg_data_list, list) { + if (gsi >= data->gsi_base && gsi <= data->gsi_end) { + domain = data->domain; + break; + } + } + mutex_unlock(&gsi_mutex); + + return domain; +} + static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity) { switch (polarity) { @@ -45,12 +94,9 @@ static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity) */ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) { - /* - * Only default domain is supported at present, always find - * the mapping corresponding to default domain by passing NULL - * as irq_domain parameter - */ - *irq = irq_find_mapping(NULL, gsi); + struct irq_domain *domain = acpi_find_irqdomain(gsi); + + *irq = irq_find_mapping(domain, gsi); /* * *irq == 0 means no mapping, that should * be reported as a failure @@ -72,16 +118,17 @@ EXPORT_SYMBOL_GPL(acpi_gsi_to_irq); int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) { - unsigned int irq; + int irq; unsigned int irq_type = acpi_gsi_get_irq_type(trigger, polarity); + struct irq_domain *domain = acpi_find_irqdomain(gsi); - /* - * There is no way at present to look-up the IRQ domain on ACPI, - * hence always create mapping referring to the default domain - * by passing NULL as irq_domain parameter - */ - irq = irq_create_mapping(NULL, gsi); - if (!irq) + irq = irq_find_mapping(domain, gsi); + if (irq > 0) + return irq; + + /* pass gsi as the hwirq num and get it in the domain's alloc() ops */ + irq = irq_domain_alloc_irqs(domain, 1, dev_to_node(dev), &gsi); + if (irq <= 0) return -EINVAL; /* Set irq type if specified and different than the current one */ @@ -98,7 +145,8 @@ EXPORT_SYMBOL_GPL(acpi_register_gsi); */ void acpi_unregister_gsi(u32 gsi) { - int irq = irq_find_mapping(NULL, gsi); + struct irq_domain *domain = acpi_find_irqdomain(gsi); + int irq = irq_find_mapping(domain, gsi); irq_dispose_mapping(irq); } diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 58a7112..39c1b0d 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -852,15 +852,22 @@ static struct notifier_block gic_cpu_notifier = { static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs, void *arg) { - int i, ret; + int i; 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; + if (acpi_disabled) { /* DT case */ + int ret; + 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; + } else { /* ACPI case */ + hwirq = (irq_hw_number_t)*(u32 *)arg; + } for (i = 0; i < nr_irqs; i++) gic_irq_domain_map(domain, virq + i, hwirq + i); @@ -946,11 +953,11 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, gic_irqs = 1020; gic->gic_irqs = gic_irqs; - if (node) { /* DT case */ + if (node || !acpi_disabled) { /* DT or ACPI case */ gic->domain = irq_domain_add_linear(node, gic_irqs, &gic_irq_domain_hierarchy_ops, gic); - } else { /* Non-DT case */ + } else { /* Non-DT and Non-ACPI case */ /* * For primary GICs, skip over SGIs. * For secondary GICs, skip over PPIs, too. @@ -1044,6 +1051,7 @@ IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init); #ifdef CONFIG_ACPI static phys_addr_t dist_phy_base, cpu_phy_base __initdata; +static u32 gsi_base __initdata; static int __init gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header, @@ -1082,6 +1090,7 @@ gic_acpi_parse_madt_distributor(struct acpi_subtable_header *header, if (BAD_MADT_ENTRY(dist, end)) return -EINVAL; + gsi_base = dist->global_irq_base; dist_phy_base = dist->base_address; return 0; } @@ -1131,13 +1140,11 @@ gic_v2_acpi_init(struct acpi_table_header *table) return -ENOMEM; } - /* - * Initialize zero GIC instance (no multi-GIC support). Also, set GIC - * as default IRQ domain to allow for GSI registration and GSI to IRQ - * number translation (see acpi_register_gsi() and acpi_gsi_to_irq()). - */ gic_init_bases(0, -1, dist_base, cpu_base, 0, NULL); - irq_set_default_host(gic_data[0].domain); + + /* since we have only one GICD, we can safely use gic_data[0] here */ + gsi_cfg_data_add(gic_data[0].domain, gsi_base, + gsi_base + gic_data[0].gic_irqs); acpi_irq_model = ACPI_IRQ_MODEL_GIC; return 0; diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 7b058f0..6e84714 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -204,6 +204,11 @@ extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity); */ void acpi_unregister_gsi (u32 gsi); +#ifdef CONFIG_ACPI_GENERIC_GSI +struct irq_domain; +int gsi_cfg_data_add(struct irq_domain *domain, u32 gsi_base, u32 gsi_end); +#endif + struct pci_dev; int acpi_pci_irq_enable (struct pci_dev *dev);