From mboxrd@z Thu Jan 1 00:00:00 1970 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3F1A4C61DA4 for ; Thu, 9 Feb 2023 08:07:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Subject:Cc:To:From:Message-ID:Date:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=q1tyQZvtoLwq5K/0vFaLfcylPpZTBzUIq19TArkupAY=; b=gxRsjn8M/FfujF UOsn2eXB9+S1KhX2XsJ5cKs2sPk97EsFzXYF/wVegGvJDdaWzlwSQHdmhNzaVIGkpmLa2+1sTFzNv UlxpCdP4HCGAy331kYaKjzGwWSAVPhh09/dX9eH5bZMRFknTYcArTGu7Qm62R6qmh5qmzwCS+tesr Qf3eTrZdsOtjwYjuzJzZzjJ2XlJdayHYgDdXXHqBf7yNH2LFSbLqWgSHen3LXRdkpTS8wuXzLEC3K 9jX6iG3E/l+7VhyleiAtHTJWACn7e3LG4SF1+r3WwnIsoF7wuX2riK12c6FfXVNezQNCHXGT4sR3P szgNt+5QxmhYilf2DJnw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1pQ1xs-000VxR-Cw; Thu, 09 Feb 2023 08:07:32 +0000 Received: from ams.source.kernel.org ([2604:1380:4601:e00::1]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1pQ1xo-000Vwo-01 for linux-riscv@lists.infradead.org; Thu, 09 Feb 2023 08:07:30 +0000 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 28D14B81FF4; Thu, 9 Feb 2023 08:07:26 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id B9EA6C433EF; Thu, 9 Feb 2023 08:07:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1675930044; bh=+cixDLgbEuQ9XxFlWqxES+2DSULudenrzv2VNUtX5sA=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=LKsd+1QACuU5cXRjQ6wtdNhZewKdCbzpTYglFjBqRty3qRFX8NwRvOrIpM5wx14On rclifDe7TKJ6bBHbp4kud4PsxDUIuHhcM8nRBgexTWV7oyQmOrdYl8AUwOW/hfCgfm DZKD4d3Rb2q86h9hlMm7ifSgqLx/2P9FPm73HyEMRT8XsJ2YhLw9Tiacbep9pv7F9h SqD466zbjjzjStYSV5bhQprfzumFRdFXViaHhkqZy0rHNC7IhOkr4Zp/mOjgqoP6sa KcBDldPNPrgzsy3CJ4r5pHkrZslejyxnfTLaT2QICFIdSbwIuhwBZnRWno9nGCGQ0K QsSh9gwrfDtPQ== Received: from ip-185-104-136-29.ptr.icomera.net ([185.104.136.29] helo=wait-a-minute.misterjones.org) by disco-boy.misterjones.org with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1pQ1xi-008uHn-72; Thu, 09 Feb 2023 08:07:22 +0000 Date: Thu, 09 Feb 2023 08:07:05 +0000 Message-ID: <874jrv1cuu.wl-maz@kernel.org> From: Marc Zyngier To: Mason Huo Cc: Thomas Gleixner , Palmer Dabbelt , Paul Walmsley , , , Ley Foon Tan , Sia Jee Heng Subject: Re: [PATCH v2] irqchip/irq-sifive-plic: Add syscore callbacks for hibernation In-Reply-To: <20230209034322.69943-1-mason.huo@starfivetech.com> References: <20230209034322.69943-1-mason.huo@starfivetech.com> User-Agent: Wanderlust/2.15.9 (Almost Unreal) SEMI-EPG/1.14.7 (Harue) FLIM-LB/1.14.9 (=?UTF-8?B?R29qxY0=?=) APEL-LB/10.8 EasyPG/1.0.0 Emacs/27.1 (x86_64-pc-linux-gnu) MULE/6.0 (HANACHIRUSATO) MIME-Version: 1.0 (generated by SEMI-EPG 1.14.7 - "Harue") X-SA-Exim-Connect-IP: 185.104.136.29 X-SA-Exim-Rcpt-To: mason.huo@starfivetech.com, tglx@linutronix.de, palmer@dabbelt.com, paul.walmsley@sifive.com, linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org, leyfoon.tan@starfivetech.com, jeeheng.sia@starfivetech.com X-SA-Exim-Mail-From: maz@kernel.org X-SA-Exim-Scanned: No (on disco-boy.misterjones.org); SAEximRunCond expanded to false X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230209_000728_361662_C5DA5931 X-CRM114-Status: GOOD ( 35.52 ) X-BeenThere: linux-riscv@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-riscv" Errors-To: linux-riscv-bounces+linux-riscv=archiver.kernel.org@lists.infradead.org On Thu, 09 Feb 2023 03:43:22 +0000, Mason Huo wrote: > > The priority and enable registers of plic will be reset > during hibernation power cycle in poweroff mode, > add the syscore callbacks to save/restore those registers. > > Signed-off-by: Mason Huo > Reviewed-by: Ley Foon Tan > Reviewed-by: Sia Jee Heng > --- > drivers/irqchip/irq-sifive-plic.c | 94 ++++++++++++++++++++++++++++++- > 1 file changed, 92 insertions(+), 2 deletions(-) > > diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c > index ff47bd0dec45..4683e49d90ad 100644 > --- a/drivers/irqchip/irq-sifive-plic.c > +++ b/drivers/irqchip/irq-sifive-plic.c > @@ -17,6 +17,7 @@ > #include > #include > #include > +#include > #include > > /* > @@ -67,6 +68,8 @@ struct plic_priv { > struct irq_domain *irqdomain; > void __iomem *regs; > unsigned long plic_quirks; > + unsigned int nr_irqs; > + unsigned long *priority_reg; This isn't a pointer to registers. This is a save area for the values. Please fix the naming. > }; > > struct plic_handler { > @@ -78,11 +81,13 @@ struct plic_handler { > */ > raw_spinlock_t enable_lock; > void __iomem *enable_base; > + u32 *enable_reg; Same thing here. > struct plic_priv *priv; > }; > 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 plic_priv *priv_data; > > static int plic_irq_set_type(struct irq_data *d, unsigned int type); > > @@ -229,6 +234,68 @@ static int plic_irq_set_type(struct irq_data *d, unsigned int type) > return IRQ_SET_MASK_OK; > } > > +static int plic_irq_suspend(void) > +{ > + unsigned int i, cpu; > + u32 __iomem *reg; > + > + for (i = 0; i < priv_data->nr_irqs; i++) > + if (readl(priv_data->regs + PRIORITY_BASE + i * PRIORITY_PER_ID)) > + __set_bit(i, priv_data->priority_reg); > + else > + __clear_bit(i, priv_data->priority_reg); > + > + for_each_cpu(cpu, cpu_present_mask) { > + struct plic_handler *handler = per_cpu_ptr(&plic_handlers, cpu); > + > + if (!handler->present) > + continue; > + > + raw_spin_lock(&handler->enable_lock); > + for (i = 0; i < DIV_ROUND_UP(priv_data->nr_irqs, 32); i++) { > + reg = handler->enable_base + i * sizeof(u32); > + handler->enable_reg[i] = readl(reg); > + } > + raw_spin_unlock(&handler->enable_lock); > + } > + > + return 0; > +} > + > +static void plic_irq_resume(void) > +{ > + unsigned int i, cpu; > + u32 __iomem *reg; > + > + for (i = 0; i < priv_data->nr_irqs; i++) > + writel(test_bit(i, priv_data->priority_reg), > + priv_data->regs + PRIORITY_BASE + i * PRIORITY_PER_ID); I suggest you write the priority value instead of the result of test_bit(). Yes, they are the same for now. They may change in the future. > + > + for_each_cpu(cpu, cpu_present_mask) { > + struct plic_handler *handler = per_cpu_ptr(&plic_handlers, cpu); > + > + if (!handler->present) > + continue; > + > + raw_spin_lock(&handler->enable_lock); > + for (i = 0; i < DIV_ROUND_UP(priv_data->nr_irqs, 32); i++) { > + reg = handler->enable_base + i * sizeof(u32); > + writel(handler->enable_reg[i], reg); > + } > + raw_spin_unlock(&handler->enable_lock); > + } > +} > + > +static struct syscore_ops plic_irq_syscore_ops = { > + .suspend = plic_irq_suspend, > + .resume = plic_irq_resume, > +}; > + > +static void plic_irq_pm_init(void) > +{ > + register_syscore_ops(&plic_irq_syscore_ops); > +} I think we can live without this single line helper. > + > static int plic_irqdomain_map(struct irq_domain *d, unsigned int irq, > irq_hw_number_t hwirq) > { > @@ -345,12 +412,14 @@ static int __init __plic_init(struct device_node *node, > u32 nr_irqs; > struct plic_priv *priv; > struct plic_handler *handler; > + unsigned int cpu; > > priv = kzalloc(sizeof(*priv), GFP_KERNEL); > if (!priv) > return -ENOMEM; > > priv->plic_quirks = plic_quirks; > + priv_data = priv; And what happens if you have more than a single PLIC in the system, as described in [1]? You also already have this pointer in each per-CPU handler structure. Why do you need a global one? > > priv->regs = of_iomap(node, 0); > if (WARN_ON(!priv->regs)) { > @@ -363,15 +432,23 @@ static int __init __plic_init(struct device_node *node, > if (WARN_ON(!nr_irqs)) > goto out_iounmap; > > + priv->nr_irqs = nr_irqs; > + > + priv->priority_reg = kcalloc(DIV_ROUND_UP(nr_irqs, > + sizeof(unsigned long) * 8), > + sizeof(unsigned long), GFP_KERNEL); Is this trying to be a substitute to bitmap_alloc()? > + if (!priv->priority_reg) > + goto out_free_priority_reg; > + > nr_contexts = of_irq_count(node); > if (WARN_ON(!nr_contexts)) > - goto out_iounmap; > + goto out_free_priority_reg; > > error = -ENOMEM; > priv->irqdomain = irq_domain_add_linear(node, nr_irqs + 1, > &plic_irqdomain_ops, priv); > if (WARN_ON(!priv->irqdomain)) > - goto out_iounmap; > + goto out_free_priority_reg; > > for (i = 0; i < nr_contexts; i++) { > struct of_phandle_args parent; > @@ -441,6 +518,11 @@ static int __init __plic_init(struct device_node *node, > handler->enable_base = priv->regs + CONTEXT_ENABLE_BASE + > i * CONTEXT_ENABLE_SIZE; > handler->priv = priv; > + > + handler->enable_reg = kcalloc(DIV_ROUND_UP(nr_irqs, 32), > + 32, GFP_KERNEL); nit: either you write this on a single line, or you align the second line with the opening bracket of the previous one. > + if (!handler->enable_reg) > + goto out_free_enable_reg; > done: > for (hwirq = 1; hwirq <= nr_irqs; hwirq++) { > plic_toggle(handler, hwirq, 0); > @@ -461,11 +543,19 @@ static int __init __plic_init(struct device_node *node, > plic_starting_cpu, plic_dying_cpu); > plic_cpuhp_setup_done = true; > } > + plic_irq_pm_init(); > > pr_info("%pOFP: mapped %d interrupts with %d handlers for" > " %d contexts.\n", node, nr_irqs, nr_handlers, nr_contexts); > return 0; > > +out_free_enable_reg: > + for_each_cpu(cpu, cpu_present_mask) { > + handler = per_cpu_ptr(&plic_handlers, cpu); > + kfree(handler->enable_reg); > + } > +out_free_priority_reg: > + kfree(priv->priority_reg); > out_iounmap: > iounmap(priv->regs); > out_free_priv: M. [1] https://patchwork.kernel.org/project/linux-riscv/patch/20200302231146.15530-3-atish.patra@wdc.com/ -- Without deviation from the norm, progress is not possible. _______________________________________________ linux-riscv mailing list linux-riscv@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-riscv From mboxrd@z Thu Jan 1 00:00:00 1970 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 5138BC05027 for ; Thu, 9 Feb 2023 08:07:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229557AbjBIIHc (ORCPT ); Thu, 9 Feb 2023 03:07:32 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60960 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229447AbjBIIH3 (ORCPT ); Thu, 9 Feb 2023 03:07:29 -0500 Received: from sin.source.kernel.org (sin.source.kernel.org [145.40.73.55]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 816F41F489 for ; Thu, 9 Feb 2023 00:07:28 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sin.source.kernel.org (Postfix) with ESMTPS id DF283CE229B for ; Thu, 9 Feb 2023 08:07:26 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id B9EA6C433EF; Thu, 9 Feb 2023 08:07:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1675930044; bh=+cixDLgbEuQ9XxFlWqxES+2DSULudenrzv2VNUtX5sA=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=LKsd+1QACuU5cXRjQ6wtdNhZewKdCbzpTYglFjBqRty3qRFX8NwRvOrIpM5wx14On rclifDe7TKJ6bBHbp4kud4PsxDUIuHhcM8nRBgexTWV7oyQmOrdYl8AUwOW/hfCgfm DZKD4d3Rb2q86h9hlMm7ifSgqLx/2P9FPm73HyEMRT8XsJ2YhLw9Tiacbep9pv7F9h SqD466zbjjzjStYSV5bhQprfzumFRdFXViaHhkqZy0rHNC7IhOkr4Zp/mOjgqoP6sa KcBDldPNPrgzsy3CJ4r5pHkrZslejyxnfTLaT2QICFIdSbwIuhwBZnRWno9nGCGQ0K QsSh9gwrfDtPQ== Received: from ip-185-104-136-29.ptr.icomera.net ([185.104.136.29] helo=wait-a-minute.misterjones.org) by disco-boy.misterjones.org with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1pQ1xi-008uHn-72; Thu, 09 Feb 2023 08:07:22 +0000 Date: Thu, 09 Feb 2023 08:07:05 +0000 Message-ID: <874jrv1cuu.wl-maz@kernel.org> From: Marc Zyngier To: Mason Huo Cc: Thomas Gleixner , Palmer Dabbelt , Paul Walmsley , , , Ley Foon Tan , Sia Jee Heng Subject: Re: [PATCH v2] irqchip/irq-sifive-plic: Add syscore callbacks for hibernation In-Reply-To: <20230209034322.69943-1-mason.huo@starfivetech.com> References: <20230209034322.69943-1-mason.huo@starfivetech.com> User-Agent: Wanderlust/2.15.9 (Almost Unreal) SEMI-EPG/1.14.7 (Harue) FLIM-LB/1.14.9 (=?UTF-8?B?R29qxY0=?=) APEL-LB/10.8 EasyPG/1.0.0 Emacs/27.1 (x86_64-pc-linux-gnu) MULE/6.0 (HANACHIRUSATO) MIME-Version: 1.0 (generated by SEMI-EPG 1.14.7 - "Harue") Content-Type: text/plain; charset=US-ASCII X-SA-Exim-Connect-IP: 185.104.136.29 X-SA-Exim-Rcpt-To: mason.huo@starfivetech.com, tglx@linutronix.de, palmer@dabbelt.com, paul.walmsley@sifive.com, linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org, leyfoon.tan@starfivetech.com, jeeheng.sia@starfivetech.com X-SA-Exim-Mail-From: maz@kernel.org X-SA-Exim-Scanned: No (on disco-boy.misterjones.org); SAEximRunCond expanded to false Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, 09 Feb 2023 03:43:22 +0000, Mason Huo wrote: > > The priority and enable registers of plic will be reset > during hibernation power cycle in poweroff mode, > add the syscore callbacks to save/restore those registers. > > Signed-off-by: Mason Huo > Reviewed-by: Ley Foon Tan > Reviewed-by: Sia Jee Heng > --- > drivers/irqchip/irq-sifive-plic.c | 94 ++++++++++++++++++++++++++++++- > 1 file changed, 92 insertions(+), 2 deletions(-) > > diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c > index ff47bd0dec45..4683e49d90ad 100644 > --- a/drivers/irqchip/irq-sifive-plic.c > +++ b/drivers/irqchip/irq-sifive-plic.c > @@ -17,6 +17,7 @@ > #include > #include > #include > +#include > #include > > /* > @@ -67,6 +68,8 @@ struct plic_priv { > struct irq_domain *irqdomain; > void __iomem *regs; > unsigned long plic_quirks; > + unsigned int nr_irqs; > + unsigned long *priority_reg; This isn't a pointer to registers. This is a save area for the values. Please fix the naming. > }; > > struct plic_handler { > @@ -78,11 +81,13 @@ struct plic_handler { > */ > raw_spinlock_t enable_lock; > void __iomem *enable_base; > + u32 *enable_reg; Same thing here. > struct plic_priv *priv; > }; > 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 plic_priv *priv_data; > > static int plic_irq_set_type(struct irq_data *d, unsigned int type); > > @@ -229,6 +234,68 @@ static int plic_irq_set_type(struct irq_data *d, unsigned int type) > return IRQ_SET_MASK_OK; > } > > +static int plic_irq_suspend(void) > +{ > + unsigned int i, cpu; > + u32 __iomem *reg; > + > + for (i = 0; i < priv_data->nr_irqs; i++) > + if (readl(priv_data->regs + PRIORITY_BASE + i * PRIORITY_PER_ID)) > + __set_bit(i, priv_data->priority_reg); > + else > + __clear_bit(i, priv_data->priority_reg); > + > + for_each_cpu(cpu, cpu_present_mask) { > + struct plic_handler *handler = per_cpu_ptr(&plic_handlers, cpu); > + > + if (!handler->present) > + continue; > + > + raw_spin_lock(&handler->enable_lock); > + for (i = 0; i < DIV_ROUND_UP(priv_data->nr_irqs, 32); i++) { > + reg = handler->enable_base + i * sizeof(u32); > + handler->enable_reg[i] = readl(reg); > + } > + raw_spin_unlock(&handler->enable_lock); > + } > + > + return 0; > +} > + > +static void plic_irq_resume(void) > +{ > + unsigned int i, cpu; > + u32 __iomem *reg; > + > + for (i = 0; i < priv_data->nr_irqs; i++) > + writel(test_bit(i, priv_data->priority_reg), > + priv_data->regs + PRIORITY_BASE + i * PRIORITY_PER_ID); I suggest you write the priority value instead of the result of test_bit(). Yes, they are the same for now. They may change in the future. > + > + for_each_cpu(cpu, cpu_present_mask) { > + struct plic_handler *handler = per_cpu_ptr(&plic_handlers, cpu); > + > + if (!handler->present) > + continue; > + > + raw_spin_lock(&handler->enable_lock); > + for (i = 0; i < DIV_ROUND_UP(priv_data->nr_irqs, 32); i++) { > + reg = handler->enable_base + i * sizeof(u32); > + writel(handler->enable_reg[i], reg); > + } > + raw_spin_unlock(&handler->enable_lock); > + } > +} > + > +static struct syscore_ops plic_irq_syscore_ops = { > + .suspend = plic_irq_suspend, > + .resume = plic_irq_resume, > +}; > + > +static void plic_irq_pm_init(void) > +{ > + register_syscore_ops(&plic_irq_syscore_ops); > +} I think we can live without this single line helper. > + > static int plic_irqdomain_map(struct irq_domain *d, unsigned int irq, > irq_hw_number_t hwirq) > { > @@ -345,12 +412,14 @@ static int __init __plic_init(struct device_node *node, > u32 nr_irqs; > struct plic_priv *priv; > struct plic_handler *handler; > + unsigned int cpu; > > priv = kzalloc(sizeof(*priv), GFP_KERNEL); > if (!priv) > return -ENOMEM; > > priv->plic_quirks = plic_quirks; > + priv_data = priv; And what happens if you have more than a single PLIC in the system, as described in [1]? You also already have this pointer in each per-CPU handler structure. Why do you need a global one? > > priv->regs = of_iomap(node, 0); > if (WARN_ON(!priv->regs)) { > @@ -363,15 +432,23 @@ static int __init __plic_init(struct device_node *node, > if (WARN_ON(!nr_irqs)) > goto out_iounmap; > > + priv->nr_irqs = nr_irqs; > + > + priv->priority_reg = kcalloc(DIV_ROUND_UP(nr_irqs, > + sizeof(unsigned long) * 8), > + sizeof(unsigned long), GFP_KERNEL); Is this trying to be a substitute to bitmap_alloc()? > + if (!priv->priority_reg) > + goto out_free_priority_reg; > + > nr_contexts = of_irq_count(node); > if (WARN_ON(!nr_contexts)) > - goto out_iounmap; > + goto out_free_priority_reg; > > error = -ENOMEM; > priv->irqdomain = irq_domain_add_linear(node, nr_irqs + 1, > &plic_irqdomain_ops, priv); > if (WARN_ON(!priv->irqdomain)) > - goto out_iounmap; > + goto out_free_priority_reg; > > for (i = 0; i < nr_contexts; i++) { > struct of_phandle_args parent; > @@ -441,6 +518,11 @@ static int __init __plic_init(struct device_node *node, > handler->enable_base = priv->regs + CONTEXT_ENABLE_BASE + > i * CONTEXT_ENABLE_SIZE; > handler->priv = priv; > + > + handler->enable_reg = kcalloc(DIV_ROUND_UP(nr_irqs, 32), > + 32, GFP_KERNEL); nit: either you write this on a single line, or you align the second line with the opening bracket of the previous one. > + if (!handler->enable_reg) > + goto out_free_enable_reg; > done: > for (hwirq = 1; hwirq <= nr_irqs; hwirq++) { > plic_toggle(handler, hwirq, 0); > @@ -461,11 +543,19 @@ static int __init __plic_init(struct device_node *node, > plic_starting_cpu, plic_dying_cpu); > plic_cpuhp_setup_done = true; > } > + plic_irq_pm_init(); > > pr_info("%pOFP: mapped %d interrupts with %d handlers for" > " %d contexts.\n", node, nr_irqs, nr_handlers, nr_contexts); > return 0; > > +out_free_enable_reg: > + for_each_cpu(cpu, cpu_present_mask) { > + handler = per_cpu_ptr(&plic_handlers, cpu); > + kfree(handler->enable_reg); > + } > +out_free_priority_reg: > + kfree(priv->priority_reg); > out_iounmap: > iounmap(priv->regs); > out_free_priv: M. [1] https://patchwork.kernel.org/project/linux-riscv/patch/20200302231146.15530-3-atish.patra@wdc.com/ -- Without deviation from the norm, progress is not possible.