From patchwork Mon Jun 27 05:12:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Holland X-Patchwork-Id: 12896203 X-Patchwork-Delegate: geert@linux-m68k.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AA5A5CCA473 for ; Mon, 27 Jun 2022 05:13:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231875AbiF0FNF (ORCPT ); Mon, 27 Jun 2022 01:13:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48638 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231834AbiF0FNE (ORCPT ); Mon, 27 Jun 2022 01:13:04 -0400 Received: from out2-smtp.messagingengine.com (out2-smtp.messagingengine.com [66.111.4.26]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F3A592BFB; Sun, 26 Jun 2022 22:13:03 -0700 (PDT) Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailout.nyi.internal (Postfix) with ESMTP id 6232E5C00FC; Mon, 27 Jun 2022 01:13:03 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute5.internal (MEProxy); Mon, 27 Jun 2022 01:13:03 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sholland.org; h= cc:cc:content-transfer-encoding:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:sender :subject:subject:to:to; s=fm3; t=1656306783; x=1656393183; bh=wU N1+m3amFs/T9ggw9lR4TovIgER88ljJACClYd7QvQ=; b=sCz5atL50hK3HMkou7 /8S5XZ9Lxxjv7Xamb+JGuNJx/yoLPAerpL4OMbtCSlDjvR8GIFxWGxW/ibKnH7nt CqgYU/iBARbAbYB2gvxtZ2q+3tYiwMTE+DGTN8aWeXOq9dfnekeuXk4F+gQ8eDAe y41PjBKNPAWNvjMJp5uzC4p7CNccoCQtkOesbQqYz7FPa3hh+Jid9V58eV+4B1yo fWLjDkNmTcmQCTCXflGeTceUvQhp90xIFrGzdDD9Jc3tt4b5WH5lGKYb1Pi4yCj1 /B9p8Xlvtp8ZnIXw9g12PKvaBdhrfX26ZVZSXQnEzXmo1Ms1nZ32HNjgYOMm4s4l aoLA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm2; t=1656306783; x=1656393183; bh=wUN1+m3amFs/T 9ggw9lR4TovIgER88ljJACClYd7QvQ=; b=qR2M9a1en554dFn8nonZS6Q8PRYA3 lDRpt59G8c5nTn/RgNKquOYVqcEZbTLrkbZrm6BRaaxrByWBbKnmnj5WJq+D+jLj kdr5jskydzlbnE1naKVjy8U/u7bFm7SlIcwRq4G12k8ej3eoLVIjLa2Y3qqMFDlM wYETmzNh6I9EfwHdD6rM4Dqh8GCUmTYhbtPMQ2ezY52HLsJqqDxPfxQwfytRUxuQ WAzc1aKVeKAfQ1i3shKOIFFIscfWzcGoVD3bD0qDNzmixco1axgdaxmL5ItIMW8D ZoSjs0ynNG7IcItT6yNk1P+o4xZgbhX2M73/Q6ILCPqIaZ0xJ9uLpREHQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedrudeggedgkeelucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhgggfestdekredtredttdenucfhrhhomhepufgrmhhu vghlucfjohhllhgrnhguuceoshgrmhhuvghlsehshhholhhlrghnugdrohhrgheqnecugg ftrfgrthhtvghrnhepudekteeuudehtdelteevgfduvddvjefhfedulefgudevgeeghefg udefiedtveetnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrh homhepshgrmhhuvghlsehshhholhhlrghnugdrohhrgh X-ME-Proxy: Feedback-ID: i0ad843c9:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 27 Jun 2022 01:13:02 -0400 (EDT) From: Samuel Holland To: Lad Prabhakar , Prabhakar , Marc Zyngier , Sagar Kadam , Paul Walmsley , Palmer Dabbelt Cc: linux-renesas-soc@vger.kernel.org, Guo Ren , Geert Uytterhoeven , Thomas Gleixner , Biju Das , Samuel Holland , Albert Ou , Krzysztof Kozlowski , Rob Herring , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org Subject: [PATCH v1 3/3] irqchip/sifive-plic: Fix T-HEAD PLIC edge trigger handling Date: Mon, 27 Jun 2022 00:12:57 -0500 Message-Id: <20220627051257.38543-4-samuel@sholland.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220627051257.38543-1-samuel@sholland.org> References: <20220627051257.38543-1-samuel@sholland.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org The T-HEAD PLIC ignores additional edges seen while an edge-triggered interrupt is being handled. Because of this behavior, the driver needs to complete edge-triggered interrupts in the .irq_ack callback before handling them, instead of in the .irq_eoi callback afterward. Otherwise, it could miss some interrupts. Co-developed-by: Lad Prabhakar Signed-off-by: Lad Prabhakar Signed-off-by: Samuel Holland --- Changes in v1: - Use a flag for enabling the changes instead of a variant ID - Use handle_edge_irq instead of handle_fasteoi_ack_irq - Do not set the handler name, as RISC-V selects GENERIC_IRQ_SHOW_LEVEL drivers/irqchip/irq-sifive-plic.c | 76 +++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 5 deletions(-) diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c index 90515865af08..462a93b4b088 100644 --- a/drivers/irqchip/irq-sifive-plic.c +++ b/drivers/irqchip/irq-sifive-plic.c @@ -69,6 +69,7 @@ struct plic_priv { struct cpumask lmask; struct irq_domain *irqdomain; void __iomem *regs; + bool needs_edge_handling; }; struct plic_handler { @@ -86,6 +87,9 @@ static int plic_parent_irq __ro_after_init; static bool plic_cpuhp_setup_done __ro_after_init; static DEFINE_PER_CPU(struct plic_handler, plic_handlers); +static struct irq_chip plic_edge_chip; +static struct irq_chip plic_chip; + static void __plic_toggle(void __iomem *enable_base, int hwirq, int enable) { u32 __iomem *reg = enable_base + (hwirq / 32) * sizeof(u32); @@ -181,6 +185,40 @@ static void plic_irq_eoi(struct irq_data *d) } } +static int plic_irq_set_type(struct irq_data *d, unsigned int flow_type) +{ + struct plic_priv *priv = irq_data_get_irq_chip_data(d); + + if (!priv->needs_edge_handling) + return IRQ_SET_MASK_OK_NOCOPY; + + switch (flow_type) { + case IRQ_TYPE_EDGE_RISING: + irq_set_chip_handler_name_locked(d, &plic_edge_chip, + handle_edge_irq, NULL); + break; + case IRQ_TYPE_LEVEL_HIGH: + irq_set_chip_handler_name_locked(d, &plic_chip, + handle_fasteoi_irq, NULL); + break; + default: + return -EINVAL; + } + + return IRQ_SET_MASK_OK; +} + +static struct irq_chip plic_edge_chip = { + .name = "PLIC", + .irq_ack = plic_irq_eoi, + .irq_mask = plic_irq_mask, + .irq_unmask = plic_irq_unmask, +#ifdef CONFIG_SMP + .irq_set_affinity = plic_set_affinity, +#endif + .irq_set_type = plic_irq_set_type, +}; + static struct irq_chip plic_chip = { .name = "PLIC", .irq_mask = plic_irq_mask, @@ -189,8 +227,22 @@ static struct irq_chip plic_chip = { #ifdef CONFIG_SMP .irq_set_affinity = plic_set_affinity, #endif + .irq_set_type = plic_irq_set_type, }; +static int plic_irq_domain_translate(struct irq_domain *d, + struct irq_fwspec *fwspec, + unsigned long *hwirq, + unsigned int *type) +{ + struct plic_priv *priv = d->host_data; + + if (priv->needs_edge_handling) + return irq_domain_translate_twocell(d, fwspec, hwirq, type); + else + return irq_domain_translate_onecell(d, fwspec, hwirq, type); +} + static int plic_irqdomain_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hwirq) { @@ -211,7 +263,7 @@ static int plic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, unsigned int type; struct irq_fwspec *fwspec = arg; - ret = irq_domain_translate_onecell(domain, fwspec, &hwirq, &type); + ret = plic_irq_domain_translate(domain, fwspec, &hwirq, &type); if (ret) return ret; @@ -225,7 +277,7 @@ static int plic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, } static const struct irq_domain_ops plic_irqdomain_ops = { - .translate = irq_domain_translate_onecell, + .translate = plic_irq_domain_translate, .alloc = plic_irq_domain_alloc, .free = irq_domain_free_irqs_top, }; @@ -286,8 +338,9 @@ static int plic_starting_cpu(unsigned int cpu) return 0; } -static int __init plic_init(struct device_node *node, - struct device_node *parent) +static int __init __plic_init(struct device_node *node, + struct device_node *parent, + bool needs_edge_handling) { int error = 0, nr_contexts, nr_handlers = 0, i; u32 nr_irqs; @@ -298,6 +351,8 @@ static int __init plic_init(struct device_node *node, if (!priv) return -ENOMEM; + priv->needs_edge_handling = needs_edge_handling; + priv->regs = of_iomap(node, 0); if (WARN_ON(!priv->regs)) { error = -EIO; @@ -415,6 +470,17 @@ static int __init plic_init(struct device_node *node, return error; } +static int __init plic_init(struct device_node *node, + struct device_node *parent) +{ + return __plic_init(node, parent, false); +} IRQCHIP_DECLARE(sifive_plic, "sifive,plic-1.0.0", plic_init); IRQCHIP_DECLARE(riscv_plic0, "riscv,plic0", plic_init); /* for legacy systems */ -IRQCHIP_DECLARE(thead_c900_plic, "thead,c900-plic", plic_init); /* for firmware driver */ + +static int __init plic_edge_init(struct device_node *node, + struct device_node *parent) +{ + return __plic_init(node, parent, true); +} +IRQCHIP_DECLARE(thead_c900_plic, "thead,c900-plic", plic_edge_init);