Received: by 2002:a25:6193:0:0:0:0:0 with SMTP id v141csp1788603ybb; Sun, 29 Mar 2020 13:27:17 -0700 (PDT) X-Google-Smtp-Source: ADFU+vt76vKZX6YUxuZ4lyCVuhPPDjSKvGioFkk6gyyaz8pUsO8U6JcTx3qSfxuJv4+7ssS75oba X-Received: by 2002:a9d:1b6d:: with SMTP id l100mr6391897otl.70.1585513636752; Sun, 29 Mar 2020 13:27:16 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1585513636; cv=none; d=google.com; s=arc-20160816; b=K5JGGmRz+ZcEUkTbeadgkZAaz5Cs6ouf8BiymAQ9reJol+0FTRLs4PDjXaX0cwD3tR kE9wYixMtqgzNHzQbV75mR0hjLeUfzwJKFSZwIvfvTbb45n6vmkVLEVurpYihm9gVTQh sM98qiNbPzFPDT769QwQjxGcq3WX3i5CWSPzMW9QkQ8F5Le07hqJUC+FKM5GU8SqGNVA Pjd/IcNOaT+Ap1DyHGNB+qU7h6nRAhm0422voFVZRkR3r7veBBQVvOnZZzu33D/g2NVZ Z3ch92ETKZjgTNXLQmbgCXYojGc5wntMAN+jn2A6AlG3rQWPJ3XOddqvseK/55kCK4AN cBNg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding :robot-unsubscribe:robot-id:message-id:mime-version:references :in-reply-to:cc:subject:to:reply-to:from:date; bh=or1TbYJSLgDKyLHkA2p+2m5yeUnl3Dakf6Rs+zLdJO0=; b=l4Tu0Y1GBlkk2JLgWXSrRC9ug/m6UAp3cE5h44v9bMoc/DyEXMcLYlua6MUqy+uQ54 2fLNaN7J+0moyQbXFcD6LfiwAkX3VZIXEeQzmUH+g3UTNBUW1VGgWDn4bXo0XNLJilCo YKP7sFO4TyEH0QWJpoEIxPHTqf26ahNwUp+ZpAAULvo+0USXlE5QFUDhEH+95Ds1sOcB Ztf0UZD96SzHqG28cA3U7KMNtMnN00QJdHLrh8HGz9+0aakNMylgUPvBlDaWi+ws/e1F YHdaD+vrGbL1Znd2K4xqo+FYAHLUFrgGr38YEadw2LL7CjGky6fsoyqD/TGQTi4SiXGI yOug== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id w6si4719060oig.171.2020.03.29.13.27.04; Sun, 29 Mar 2020 13:27:16 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728956AbgC2U0j (ORCPT + 99 others); Sun, 29 Mar 2020 16:26:39 -0400 Received: from Galois.linutronix.de ([193.142.43.55]:57074 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728916AbgC2U0e (ORCPT ); Sun, 29 Mar 2020 16:26:34 -0400 Received: from [5.158.153.53] (helo=tip-bot2.lab.linutronix.de) by Galois.linutronix.de with esmtpsa (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1jIeVq-0001Ug-W1; Sun, 29 Mar 2020 22:26:31 +0200 Received: from [127.0.1.1] (localhost [IPv6:::1]) by tip-bot2.lab.linutronix.de (Postfix) with ESMTP id 9635A1C070D; Sun, 29 Mar 2020 22:26:21 +0200 (CEST) Date: Sun, 29 Mar 2020 20:26:21 -0000 From: "tip-bot2 for Atish Patra" Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: irq/core] irqchip/sifive-plic: Add support for multiple PLICs Cc: Atish Patra , Marc Zyngier , Anup Patel , x86 , LKML In-Reply-To: <20200302231146.15530-3-atish.patra@wdc.com> References: <20200302231146.15530-3-atish.patra@wdc.com> MIME-Version: 1.0 Message-ID: <158551358111.28353.4832719273444577850.tip-bot2@tip-bot2> X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Linutronix-Spam-Score: -1.0 X-Linutronix-Spam-Level: - X-Linutronix-Spam-Status: No , -1.0 points, 5.0 required, ALL_TRUSTED=-1,SHORTCIRCUIT=-0.0001 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The following commit has been merged into the irq/core branch of tip: Commit-ID: f1ad1133b18f2aed3f6923cdb62b63da230accfd Gitweb: https://git.kernel.org/tip/f1ad1133b18f2aed3f6923cdb62b63da230accfd Author: Atish Patra AuthorDate: Mon, 02 Mar 2020 15:11:46 -08:00 Committer: Marc Zyngier CommitterDate: Mon, 16 Mar 2020 15:48:54 irqchip/sifive-plic: Add support for multiple PLICs Current, PLIC driver can support only 1 PLIC on the board. However, there can be multiple PLICs present on a two socket systems in RISC-V. Modify the driver so that each PLIC handler can have a information about individual PLIC registers and an irqdomain associated with it. Tested on two socket RISC-V system based on VCU118 FPGA connected via OmniXtend protocol. Signed-off-by: Atish Patra Signed-off-by: Marc Zyngier Reviewed-by: Anup Patel Link: https://lore.kernel.org/r/20200302231146.15530-3-atish.patra@wdc.com --- drivers/irqchip/irq-sifive-plic.c | 81 ++++++++++++++++++------------ 1 file changed, 51 insertions(+), 30 deletions(-) diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c index 7c7f373..c34fb3a 100644 --- a/drivers/irqchip/irq-sifive-plic.c +++ b/drivers/irqchip/irq-sifive-plic.c @@ -59,7 +59,11 @@ #define PLIC_DISABLE_THRESHOLD 0xf #define PLIC_ENABLE_THRESHOLD 0 -static void __iomem *plic_regs; +struct plic_priv { + struct cpumask lmask; + struct irq_domain *irqdomain; + void __iomem *regs; +}; struct plic_handler { bool present; @@ -70,6 +74,7 @@ struct plic_handler { */ raw_spinlock_t enable_lock; void __iomem *enable_base; + struct plic_priv *priv; }; static DEFINE_PER_CPU(struct plic_handler, plic_handlers); @@ -88,31 +93,40 @@ static inline void plic_toggle(struct plic_handler *handler, } static inline void plic_irq_toggle(const struct cpumask *mask, - int hwirq, int enable) + struct irq_data *d, int enable) { int cpu; + struct plic_priv *priv = irq_get_chip_data(d->irq); - writel(enable, plic_regs + PRIORITY_BASE + hwirq * PRIORITY_PER_ID); + writel(enable, priv->regs + PRIORITY_BASE + d->hwirq * PRIORITY_PER_ID); for_each_cpu(cpu, mask) { struct plic_handler *handler = per_cpu_ptr(&plic_handlers, cpu); - if (handler->present) - plic_toggle(handler, hwirq, enable); + if (handler->present && + cpumask_test_cpu(cpu, &handler->priv->lmask)) + plic_toggle(handler, d->hwirq, enable); } } static void plic_irq_unmask(struct irq_data *d) { - unsigned int cpu = cpumask_any_and(irq_data_get_affinity_mask(d), - cpu_online_mask); + struct cpumask amask; + unsigned int cpu; + struct plic_priv *priv = irq_get_chip_data(d->irq); + + cpumask_and(&amask, &priv->lmask, cpu_online_mask); + cpu = cpumask_any_and(irq_data_get_affinity_mask(d), + &amask); if (WARN_ON_ONCE(cpu >= nr_cpu_ids)) return; - plic_irq_toggle(cpumask_of(cpu), d->hwirq, 1); + plic_irq_toggle(cpumask_of(cpu), d, 1); } static void plic_irq_mask(struct irq_data *d) { - plic_irq_toggle(cpu_possible_mask, d->hwirq, 0); + struct plic_priv *priv = irq_get_chip_data(d->irq); + + plic_irq_toggle(&priv->lmask, d, 0); } #ifdef CONFIG_SMP @@ -120,17 +134,21 @@ static int plic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, bool force) { unsigned int cpu; + struct cpumask amask; + struct plic_priv *priv = irq_get_chip_data(d->irq); + + cpumask_and(&amask, &priv->lmask, mask_val); if (force) - cpu = cpumask_first(mask_val); + cpu = cpumask_first(&amask); else - cpu = cpumask_any_and(mask_val, cpu_online_mask); + cpu = cpumask_any_and(&amask, cpu_online_mask); if (cpu >= nr_cpu_ids) return -EINVAL; - plic_irq_toggle(cpu_possible_mask, d->hwirq, 0); - plic_irq_toggle(cpumask_of(cpu), d->hwirq, 1); + plic_irq_toggle(&priv->lmask, d, 0); + plic_irq_toggle(cpumask_of(cpu), d, 1); irq_data_update_effective_affinity(d, cpumask_of(cpu)); @@ -191,8 +209,6 @@ static const struct irq_domain_ops plic_irqdomain_ops = { .free = irq_domain_free_irqs_top, }; -static struct irq_domain *plic_irqdomain; - /* * Handling an interrupt is a two-step process: first you claim the interrupt * by reading the claim register, then you complete the interrupt by writing @@ -209,7 +225,7 @@ static void plic_handle_irq(struct pt_regs *regs) csr_clear(CSR_IE, IE_EIE); while ((hwirq = readl(claim))) { - int irq = irq_find_mapping(plic_irqdomain, hwirq); + int irq = irq_find_mapping(handler->priv->irqdomain, hwirq); if (unlikely(irq <= 0)) pr_warn_ratelimited("can't find mapping for hwirq %lu\n", @@ -265,15 +281,17 @@ static int __init plic_init(struct device_node *node, { int error = 0, nr_contexts, nr_handlers = 0, i; u32 nr_irqs; + struct plic_priv *priv; - if (plic_regs) { - pr_warn("PLIC already present.\n"); - return -ENXIO; - } + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; - plic_regs = of_iomap(node, 0); - if (WARN_ON(!plic_regs)) - return -EIO; + priv->regs = of_iomap(node, 0); + if (WARN_ON(!priv->regs)) { + error = -EIO; + goto out_free_priv; + } error = -EINVAL; of_property_read_u32(node, "riscv,ndev", &nr_irqs); @@ -287,9 +305,9 @@ static int __init plic_init(struct device_node *node, goto out_iounmap; error = -ENOMEM; - plic_irqdomain = irq_domain_add_linear(node, nr_irqs + 1, - &plic_irqdomain_ops, NULL); - if (WARN_ON(!plic_irqdomain)) + priv->irqdomain = irq_domain_add_linear(node, nr_irqs + 1, + &plic_irqdomain_ops, priv); + if (WARN_ON(!priv->irqdomain)) goto out_iounmap; for (i = 0; i < nr_contexts; i++) { @@ -334,13 +352,14 @@ static int __init plic_init(struct device_node *node, goto done; } + cpumask_set_cpu(cpu, &priv->lmask); handler->present = true; handler->hart_base = - plic_regs + CONTEXT_BASE + i * CONTEXT_PER_HART; + priv->regs + CONTEXT_BASE + i * CONTEXT_PER_HART; raw_spin_lock_init(&handler->enable_lock); handler->enable_base = - plic_regs + ENABLE_BASE + i * ENABLE_PER_HART; - + priv->regs + ENABLE_BASE + i * ENABLE_PER_HART; + handler->priv = priv; done: for (hwirq = 1; hwirq <= nr_irqs; hwirq++) plic_toggle(handler, hwirq, 0); @@ -356,7 +375,9 @@ done: return 0; out_iounmap: - iounmap(plic_regs); + iounmap(priv->regs); +out_free_priv: + kfree(priv); return error; }