Message ID | 20230404182037.863533-9-sunilvl@ventanamicro.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp78508vqo; Tue, 4 Apr 2023 11:25:24 -0700 (PDT) X-Google-Smtp-Source: AKy350aCnuBmyzw+hyNF5SGBFnrwAp7HMkp63cfj5dC6itHo7O1rZuAzu7ERIG9G9z3YdbruFQfW X-Received: by 2002:a17:90b:4a4b:b0:23d:1fc0:dd1f with SMTP id lb11-20020a17090b4a4b00b0023d1fc0dd1fmr3559127pjb.38.1680632724368; Tue, 04 Apr 2023 11:25:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680632724; cv=none; d=google.com; s=arc-20160816; b=SiuHvgz3wVTDay0iEWtAtQzhPxMwT3qVhVRgCaHIrWUExVUbRjzCfWBxs6vMYvzEXG FXwNf6wVS7uwHk0rzXERyAbFr0OBtijHyCcp4eB55eSL+Qb8a1+Zhsc2pq9QQLHJ2Y5a n72bKvXOZ3PVozUe/aHqtV7xkLYHyAdhF23SIA8YPHcMMPupdMZVCCkbi3gjvIWnAslY EK1TsA9F8cZSl34ZPa9ygyVo5lThpfpZixUvpMV5T9QKfuB9TAyJhnX1kHjBl25Pl4BM yjMYgexajqcF1RiO9LdXmGvjMgA6a0WpnNFyvqBn0ZNkRW9g57cW+mDKZyxJPRoFu9lu zlKw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=sK3yofAaBPCm3lmjxfNqOeEWtEi7+pbDB/M30NYTLb4=; b=0mAOHbf6B9Lbmb47rikvwAiYfuc9cPqCj41MExIVfQbssIN2grUhaFbNPd7sxTnJfT i8fu7lPqmVDBVW4TbPvDXAd25mFe1LSjeAxruyRt01j0WFBeP82rFXSf0mm1bL6upQv6 XUeHSzEfrM0ZVQ621McBBK5t0XqVHs7ZQ7C/LXTpIadBOBmmH2l+gkbnoiStklLucUM8 phSmn/k66Koj8bSO6uXr86D+U529YYfVgRZ4XCQE2iwPEyWsdibShl9hR/dOS5wVwLxy /yz45AEUlwT3LrDScaYAtlCRBN1AWkmRlBriO6mzSr2/4ODQS8s4Af2ahWNm2McuzOZs 1q+A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ventanamicro.com header.s=google header.b=JtyGYEmj; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id x4-20020a17090a9dc400b00232f57260c1si2084297pjv.1.2023.04.04.11.25.11; Tue, 04 Apr 2023 11:25:24 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@ventanamicro.com header.s=google header.b=JtyGYEmj; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236276AbjDDSXF (ORCPT <rfc822;a1648639935@gmail.com> + 99 others); Tue, 4 Apr 2023 14:23:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39592 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236479AbjDDSV6 (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Tue, 4 Apr 2023 14:21:58 -0400 Received: from mail-pg1-x535.google.com (mail-pg1-x535.google.com [IPv6:2607:f8b0:4864:20::535]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 952E35FC1 for <linux-kernel@vger.kernel.org>; Tue, 4 Apr 2023 11:21:43 -0700 (PDT) Received: by mail-pg1-x535.google.com with SMTP id l184so11108418pgd.11 for <linux-kernel@vger.kernel.org>; Tue, 04 Apr 2023 11:21:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ventanamicro.com; s=google; t=1680632503; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=sK3yofAaBPCm3lmjxfNqOeEWtEi7+pbDB/M30NYTLb4=; b=JtyGYEmj3+3zXeCs5rBdEDlUNt6swvT2m0XrsA3IxnpAIAobJbh35p79poWYW0Y6DK /NatfbFv1zcZu5PtRqFFn7Bsw50dOsX/WRlTS4Oqgzyz+qtXNFGqVS6tgUfG6Givx9N2 In/h+M3U6bNqy0rDKS7kJWHaCI5EgCPUJNoXaIZ+nQXKmfIoVE/uQZXVwLXSHJ2+wPSL sTJBuz6w8MHN0b+gl3Jp/kbsanaFYKHbb2MfHz4Hz/y/V++YkTeXD74E3tw48NW9w1gJ PSRM3VIJgLuJlkFRrz3GJC+HXFj0K9F/uZhGuFYR1Vkg91JK/xEqUbHtTgfzxNX2/ciU pUHg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680632503; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=sK3yofAaBPCm3lmjxfNqOeEWtEi7+pbDB/M30NYTLb4=; b=KujdI53LKJ58oHU60odrrvUZFgS9IdTj9U7YM+z7vWNIRgp4ri6ME/Ryaw5IqZ63Pe BdCUeEPu/8PuUI09sCMPp/1Yr9f05sTWvV2Cm6kmwisEaXoyzqrf1H2PwmMVC3OZSM+z ihMoX4a7+83iUE4DchCpQdwBeG8yuGcT8F91MXrZ2RSC2p0R0u/f3pRQgJ5hcJSw5nZc zKIt/Mg20K/38l+Q2jmaZdgxQ3C967434tyTXDHgsfirWv+WDZJsqQJmk9rELoUxicWI SmLEBIgIpv8Ud4IyZs16PjrMGiJvzJ9imcBr+cpi3nAAQr9aQ4Igb6baw8P+zrsXoe+v KUdg== X-Gm-Message-State: AAQBX9fmerbCAqKTKIDm0XKH1wDTqN0NrEeVvmowO4w6G2sz3O3TpBBY yEshvi0NnwDUI8V+WJwsnCOxfQ== X-Received: by 2002:aa7:9793:0:b0:626:658:c998 with SMTP id o19-20020aa79793000000b006260658c998mr3204222pfp.10.1680632502984; Tue, 04 Apr 2023 11:21:42 -0700 (PDT) Received: from localhost.localdomain ([106.51.184.50]) by smtp.gmail.com with ESMTPSA id o12-20020a056a001bcc00b0062dcf5c01f9sm9018524pfw.36.2023.04.04.11.21.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 04 Apr 2023 11:21:42 -0700 (PDT) From: Sunil V L <sunilvl@ventanamicro.com> To: linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org, linux-acpi@vger.kernel.org, linux-crypto@vger.kernel.org, platform-driver-x86@vger.kernel.org, llvm@lists.linux.dev Cc: Jonathan Corbet <corbet@lwn.net>, Paul Walmsley <paul.walmsley@sifive.com>, Palmer Dabbelt <palmer@dabbelt.com>, Albert Ou <aou@eecs.berkeley.edu>, Len Brown <lenb@kernel.org>, Daniel Lezcano <daniel.lezcano@linaro.org>, Thomas Gleixner <tglx@linutronix.de>, Weili Qian <qianweili@huawei.com>, Zhou Wang <wangzhou1@hisilicon.com>, Herbert Xu <herbert@gondor.apana.org.au>, Marc Zyngier <maz@kernel.org>, Maximilian Luz <luzmaximilian@gmail.com>, Hans de Goede <hdegoede@redhat.com>, Mark Gross <markgross@kernel.org>, Nathan Chancellor <nathan@kernel.org>, Nick Desaulniers <ndesaulniers@google.com>, Tom Rix <trix@redhat.com>, "Rafael J . Wysocki" <rafael@kernel.org>, "David S . Miller" <davem@davemloft.net>, Sunil V L <sunilvl@ventanamicro.com>, "Rafael J . Wysocki" <rafael.j.wysocki@intel.com> Subject: [PATCH V4 08/23] RISC-V: ACPI: Cache and retrieve the RINTC structure Date: Tue, 4 Apr 2023 23:50:22 +0530 Message-Id: <20230404182037.863533-9-sunilvl@ventanamicro.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230404182037.863533-1-sunilvl@ventanamicro.com> References: <20230404182037.863533-1-sunilvl@ventanamicro.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762271139292771558?= X-GMAIL-MSGID: =?utf-8?q?1762271139292771558?= |
Series |
Add basic ACPI support for RISC-V
|
|
Commit Message
Sunil V L
April 4, 2023, 6:20 p.m. UTC
RINTC structures in the MADT provide mapping between the hartid and the CPU. This is required many times even at run time like cpuinfo. So, instead of parsing the ACPI table every time, cache the RINTC structures and provide a function to get the correct RINTC structure for a given cpu. Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> --- arch/riscv/include/asm/acpi.h | 2 ++ arch/riscv/kernel/acpi.c | 60 +++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+)
Comments
On Tue, Apr 04, 2023 at 11:50:22PM +0530, Sunil V L wrote: > RINTC structures in the MADT provide mapping between the hartid > and the CPU. This is required many times even at run time like > cpuinfo. So, instead of parsing the ACPI table every time, cache > the RINTC structures and provide a function to get the correct > RINTC structure for a given cpu. > > Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> > Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > --- > arch/riscv/include/asm/acpi.h | 2 ++ > arch/riscv/kernel/acpi.c | 60 +++++++++++++++++++++++++++++++++++ > 2 files changed, 62 insertions(+) > > diff --git a/arch/riscv/include/asm/acpi.h b/arch/riscv/include/asm/acpi.h > index 9be52b6ffae1..1606dce8992e 100644 > --- a/arch/riscv/include/asm/acpi.h > +++ b/arch/riscv/include/asm/acpi.h > @@ -59,6 +59,8 @@ static inline bool acpi_has_cpu_in_madt(void) > > static inline void arch_fix_phys_package_id(int num, u32 slot) { } > > +struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu); > +u32 get_acpi_id_for_cpu(int cpu); > #endif /* CONFIG_ACPI */ > > #endif /*_ASM_ACPI_H*/ > diff --git a/arch/riscv/kernel/acpi.c b/arch/riscv/kernel/acpi.c > index 81d448c41714..40ab55309c70 100644 > --- a/arch/riscv/kernel/acpi.c > +++ b/arch/riscv/kernel/acpi.c > @@ -24,6 +24,66 @@ EXPORT_SYMBOL(acpi_disabled); > int acpi_pci_disabled = 1; /* skip ACPI PCI scan and IRQ initialization */ > EXPORT_SYMBOL(acpi_pci_disabled); > > +static struct acpi_madt_rintc cpu_madt_rintc[NR_CPUS]; > + > +static int acpi_parse_madt_rintc(union acpi_subtable_headers *header, const unsigned long end) > +{ > + struct acpi_madt_rintc *rintc = (struct acpi_madt_rintc *)header; > + int cpuid; > + > + if (!(rintc->flags & ACPI_MADT_ENABLED)) > + return 0; > + > + cpuid = riscv_hartid_to_cpuid(rintc->hart_id); > + /* > + * When CONFIG_SMP is disabled, mapping won't be created for > + * all cpus. > + * CPUs more than NR_CPUS, will be ignored. > + */ > + if (cpuid >= 0 && cpuid < NR_CPUS) > + cpu_madt_rintc[cpuid] = *rintc; > + > + return 0; > +} > + > +static int acpi_init_rintc_array(void) > +{ > + if (acpi_table_parse_madt(ACPI_MADT_TYPE_RINTC, acpi_parse_madt_rintc, 0) > 0) Does this not return an actual ERRNO? Naïvely following the call chain, it looks like it should do. If it does, why not return that instead of always returning -ENODEV? > + return 0; > + > + return -ENODEV; > +} > + > +/* > + * Instead of parsing (and freeing) the ACPI table, cache > + * the RINTC structures since they are frequently used > + * like in cpuinfo. > + */ > +struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu) > +{ > + static bool rintc_init_done; > + > + if (!rintc_init_done) { > + if (acpi_init_rintc_array()) { > + pr_err("No valid RINTC entries exist\n"); > + return NULL; > + } > + > + rintc_init_done = true; > + } > + > + return &cpu_madt_rintc[cpu]; > +} > + > +u32 get_acpi_id_for_cpu(int cpu) > +{ > + struct acpi_madt_rintc *rintc = acpi_cpu_get_madt_rintc(cpu); > + > + BUG_ON(!rintc); > + > + return rintc->uid; > +} > + > /* > * __acpi_map_table() will be called before paging_init(), so early_ioremap() > * or early_memremap() should be called here to for ACPI table mapping. > -- > 2.34.1 > > > _______________________________________________ > linux-riscv mailing list > linux-riscv@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-riscv
On Tue, Apr 04, 2023 at 11:50:22PM +0530, Sunil V L wrote: > RINTC structures in the MADT provide mapping between the hartid > and the CPU. This is required many times even at run time like > cpuinfo. So, instead of parsing the ACPI table every time, cache > the RINTC structures and provide a function to get the correct > RINTC structure for a given cpu. > > Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> > Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > --- > arch/riscv/include/asm/acpi.h | 2 ++ > arch/riscv/kernel/acpi.c | 60 +++++++++++++++++++++++++++++++++++ > 2 files changed, 62 insertions(+) > > diff --git a/arch/riscv/include/asm/acpi.h b/arch/riscv/include/asm/acpi.h > index 9be52b6ffae1..1606dce8992e 100644 > --- a/arch/riscv/include/asm/acpi.h > +++ b/arch/riscv/include/asm/acpi.h > @@ -59,6 +59,8 @@ static inline bool acpi_has_cpu_in_madt(void) > > static inline void arch_fix_phys_package_id(int num, u32 slot) { } > > +struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu); > +u32 get_acpi_id_for_cpu(int cpu); > #endif /* CONFIG_ACPI */ > > #endif /*_ASM_ACPI_H*/ > diff --git a/arch/riscv/kernel/acpi.c b/arch/riscv/kernel/acpi.c > index 81d448c41714..40ab55309c70 100644 > --- a/arch/riscv/kernel/acpi.c > +++ b/arch/riscv/kernel/acpi.c > @@ -24,6 +24,66 @@ EXPORT_SYMBOL(acpi_disabled); > int acpi_pci_disabled = 1; /* skip ACPI PCI scan and IRQ initialization */ > EXPORT_SYMBOL(acpi_pci_disabled); > > +static struct acpi_madt_rintc cpu_madt_rintc[NR_CPUS]; > + > +static int acpi_parse_madt_rintc(union acpi_subtable_headers *header, const unsigned long end) > +{ > + struct acpi_madt_rintc *rintc = (struct acpi_madt_rintc *)header; > + int cpuid; > + > + if (!(rintc->flags & ACPI_MADT_ENABLED)) > + return 0; > + > + cpuid = riscv_hartid_to_cpuid(rintc->hart_id); > + /* > + * When CONFIG_SMP is disabled, mapping won't be created for > + * all cpus. > + * CPUs more than NR_CPUS, will be ignored. > + */ > + if (cpuid >= 0 && cpuid < NR_CPUS) > + cpu_madt_rintc[cpuid] = *rintc; > + > + return 0; > +} > + > +static int acpi_init_rintc_array(void) > +{ > + if (acpi_table_parse_madt(ACPI_MADT_TYPE_RINTC, acpi_parse_madt_rintc, 0) > 0) > + return 0; > + > + return -ENODEV; As Conor pointed out, the errors could be propagated from acpi_table_parse_madt(), which could reduce this function to return acpi_table_parse_madt(ACPI_MADT_TYPE_RINTC, acpi_parse_madt_rintc, 0); where the '< 0' check would be in the caller below. That sounds good to me, but then I'd take that a step further and just drop this helper altogether. > +} > + > +/* > + * Instead of parsing (and freeing) the ACPI table, cache > + * the RINTC structures since they are frequently used > + * like in cpuinfo. ^ extra space > + */ > +struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu) > +{ > + static bool rintc_init_done; > + > + if (!rintc_init_done) { > + if (acpi_init_rintc_array()) { > + pr_err("No valid RINTC entries exist\n"); > + return NULL; > + } > + > + rintc_init_done = true; > + } > + > + return &cpu_madt_rintc[cpu]; > +} > + > +u32 get_acpi_id_for_cpu(int cpu) > +{ > + struct acpi_madt_rintc *rintc = acpi_cpu_get_madt_rintc(cpu); > + > + BUG_ON(!rintc); > + > + return rintc->uid; > +} > + > /* > * __acpi_map_table() will be called before paging_init(), so early_ioremap() > * or early_memremap() should be called here to for ACPI table mapping. > -- > 2.34.1 > Otherwise, Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Thanks, drew
On Wed, Apr 05, 2023 at 05:17:48PM +0200, Andrew Jones wrote: > On Tue, Apr 04, 2023 at 11:50:22PM +0530, Sunil V L wrote: > > RINTC structures in the MADT provide mapping between the hartid > > and the CPU. This is required many times even at run time like > > cpuinfo. So, instead of parsing the ACPI table every time, cache > > the RINTC structures and provide a function to get the correct > > RINTC structure for a given cpu. > > > > Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> > > Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > --- > > arch/riscv/include/asm/acpi.h | 2 ++ > > arch/riscv/kernel/acpi.c | 60 +++++++++++++++++++++++++++++++++++ > > 2 files changed, 62 insertions(+) > > > > diff --git a/arch/riscv/include/asm/acpi.h b/arch/riscv/include/asm/acpi.h > > index 9be52b6ffae1..1606dce8992e 100644 > > --- a/arch/riscv/include/asm/acpi.h > > +++ b/arch/riscv/include/asm/acpi.h > > @@ -59,6 +59,8 @@ static inline bool acpi_has_cpu_in_madt(void) > > > > static inline void arch_fix_phys_package_id(int num, u32 slot) { } > > > > +struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu); > > +u32 get_acpi_id_for_cpu(int cpu); > > #endif /* CONFIG_ACPI */ > > > > #endif /*_ASM_ACPI_H*/ > > diff --git a/arch/riscv/kernel/acpi.c b/arch/riscv/kernel/acpi.c > > index 81d448c41714..40ab55309c70 100644 > > --- a/arch/riscv/kernel/acpi.c > > +++ b/arch/riscv/kernel/acpi.c > > @@ -24,6 +24,66 @@ EXPORT_SYMBOL(acpi_disabled); > > int acpi_pci_disabled = 1; /* skip ACPI PCI scan and IRQ initialization */ > > EXPORT_SYMBOL(acpi_pci_disabled); > > > > +static struct acpi_madt_rintc cpu_madt_rintc[NR_CPUS]; > > + > > +static int acpi_parse_madt_rintc(union acpi_subtable_headers *header, const unsigned long end) > > +{ > > + struct acpi_madt_rintc *rintc = (struct acpi_madt_rintc *)header; > > + int cpuid; > > + > > + if (!(rintc->flags & ACPI_MADT_ENABLED)) > > + return 0; > > + > > + cpuid = riscv_hartid_to_cpuid(rintc->hart_id); > > + /* > > + * When CONFIG_SMP is disabled, mapping won't be created for > > + * all cpus. > > + * CPUs more than NR_CPUS, will be ignored. > > + */ > > + if (cpuid >= 0 && cpuid < NR_CPUS) > > + cpu_madt_rintc[cpuid] = *rintc; > > + > > + return 0; > > +} > > + > > +static int acpi_init_rintc_array(void) > > +{ > > + if (acpi_table_parse_madt(ACPI_MADT_TYPE_RINTC, acpi_parse_madt_rintc, 0) > 0) > > + return 0; > > + > > + return -ENODEV; > > As Conor pointed out, the errors could be propagated from > acpi_table_parse_madt(), which could reduce this function to > > return acpi_table_parse_madt(ACPI_MADT_TYPE_RINTC, acpi_parse_madt_rintc, 0); > > where the '< 0' check would be in the caller below. That sounds good to > me, but then I'd take that a step further and just drop this helper > altogether. > Thanks, Conor, Drew. I used similar to how others have used acpi_table_parse_madt(). But your suggestion makes sense. Will remove the wrapper function also. Thanks, Sunil
On Tue, 04 Apr 2023 11:20:22 PDT (-0700), sunilvl@ventanamicro.com wrote: > RINTC structures in the MADT provide mapping between the hartid > and the CPU. This is required many times even at run time like > cpuinfo. So, instead of parsing the ACPI table every time, cache > the RINTC structures and provide a function to get the correct > RINTC structure for a given cpu. > > Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> > Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > --- > arch/riscv/include/asm/acpi.h | 2 ++ > arch/riscv/kernel/acpi.c | 60 +++++++++++++++++++++++++++++++++++ > 2 files changed, 62 insertions(+) > > diff --git a/arch/riscv/include/asm/acpi.h b/arch/riscv/include/asm/acpi.h > index 9be52b6ffae1..1606dce8992e 100644 > --- a/arch/riscv/include/asm/acpi.h > +++ b/arch/riscv/include/asm/acpi.h > @@ -59,6 +59,8 @@ static inline bool acpi_has_cpu_in_madt(void) > > static inline void arch_fix_phys_package_id(int num, u32 slot) { } > > +struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu); > +u32 get_acpi_id_for_cpu(int cpu); > #endif /* CONFIG_ACPI */ > > #endif /*_ASM_ACPI_H*/ > diff --git a/arch/riscv/kernel/acpi.c b/arch/riscv/kernel/acpi.c > index 81d448c41714..40ab55309c70 100644 > --- a/arch/riscv/kernel/acpi.c > +++ b/arch/riscv/kernel/acpi.c > @@ -24,6 +24,66 @@ EXPORT_SYMBOL(acpi_disabled); > int acpi_pci_disabled = 1; /* skip ACPI PCI scan and IRQ initialization */ > EXPORT_SYMBOL(acpi_pci_disabled); > > +static struct acpi_madt_rintc cpu_madt_rintc[NR_CPUS]; > + > +static int acpi_parse_madt_rintc(union acpi_subtable_headers *header, const unsigned long end) > +{ > + struct acpi_madt_rintc *rintc = (struct acpi_madt_rintc *)header; > + int cpuid; > + > + if (!(rintc->flags & ACPI_MADT_ENABLED)) > + return 0; > + > + cpuid = riscv_hartid_to_cpuid(rintc->hart_id); Unless I'm missing something, this races with CPUs coming online. Maybe that's a rare enough case we don't care, but I think we'd also just have simpler logic if we fixed it... > + /* > + * When CONFIG_SMP is disabled, mapping won't be created for > + * all cpus. > + * CPUs more than NR_CPUS, will be ignored. > + */ > + if (cpuid >= 0 && cpuid < NR_CPUS) > + cpu_madt_rintc[cpuid] = *rintc; > + > + return 0; > +} > + > +static int acpi_init_rintc_array(void) > +{ > + if (acpi_table_parse_madt(ACPI_MADT_TYPE_RINTC, acpi_parse_madt_rintc, 0) > 0) > + return 0; > + > + return -ENODEV; > +} > + > +/* > + * Instead of parsing (and freeing) the ACPI table, cache > + * the RINTC structures since they are frequently used > + * like in cpuinfo. > + */ > +struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu) > +{ > + static bool rintc_init_done; ... basically just get rid of this global variable, and instead have a if (!&cpu_madt_rintc[cpu]) ... parse ... return &cpu_madt_rintc[cpu]; that'd probably let us get rid of a handful of these helpers too, as now it's just a call to the parsing bits. > + > + if (!rintc_init_done) { > + if (acpi_init_rintc_array()) { > + pr_err("No valid RINTC entries exist\n"); > + return NULL; > + } > + > + rintc_init_done = true; > + } > + > + return &cpu_madt_rintc[cpu]; > +} > + > +u32 get_acpi_id_for_cpu(int cpu) > +{ > + struct acpi_madt_rintc *rintc = acpi_cpu_get_madt_rintc(cpu); > + > + BUG_ON(!rintc); We should have some better error reporting here. It looks like all the callerss of get_acpi_id_for_cpu() are tolerant of a nonsense ID being returned, so maybe we just pr_warn() something users can understand and then return -1 or something? > + > + return rintc->uid; > +} > + > /* > * __acpi_map_table() will be called before paging_init(), so early_ioremap() > * or early_memremap() should be called here to for ACPI table mapping.
Hi Palmer, On Wed, Apr 26, 2023 at 11:45:00AM -0700, Palmer Dabbelt wrote: > On Tue, 04 Apr 2023 11:20:22 PDT (-0700), sunilvl@ventanamicro.com wrote: > > RINTC structures in the MADT provide mapping between the hartid > > and the CPU. This is required many times even at run time like > > cpuinfo. So, instead of parsing the ACPI table every time, cache > > the RINTC structures and provide a function to get the correct > > RINTC structure for a given cpu. > > > > Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> > > Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > --- > > arch/riscv/include/asm/acpi.h | 2 ++ > > arch/riscv/kernel/acpi.c | 60 +++++++++++++++++++++++++++++++++++ > > 2 files changed, 62 insertions(+) > > > > diff --git a/arch/riscv/include/asm/acpi.h b/arch/riscv/include/asm/acpi.h > > index 9be52b6ffae1..1606dce8992e 100644 > > --- a/arch/riscv/include/asm/acpi.h > > +++ b/arch/riscv/include/asm/acpi.h > > @@ -59,6 +59,8 @@ static inline bool acpi_has_cpu_in_madt(void) > > > > static inline void arch_fix_phys_package_id(int num, u32 slot) { } > > > > +struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu); > > +u32 get_acpi_id_for_cpu(int cpu); > > #endif /* CONFIG_ACPI */ > > > > #endif /*_ASM_ACPI_H*/ > > diff --git a/arch/riscv/kernel/acpi.c b/arch/riscv/kernel/acpi.c > > index 81d448c41714..40ab55309c70 100644 > > --- a/arch/riscv/kernel/acpi.c > > +++ b/arch/riscv/kernel/acpi.c > > @@ -24,6 +24,66 @@ EXPORT_SYMBOL(acpi_disabled); > > int acpi_pci_disabled = 1; /* skip ACPI PCI scan and IRQ initialization */ > > EXPORT_SYMBOL(acpi_pci_disabled); > > > > +static struct acpi_madt_rintc cpu_madt_rintc[NR_CPUS]; > > + > > +static int acpi_parse_madt_rintc(union acpi_subtable_headers *header, const unsigned long end) > > +{ > > + struct acpi_madt_rintc *rintc = (struct acpi_madt_rintc *)header; > > + int cpuid; > > + > > + if (!(rintc->flags & ACPI_MADT_ENABLED)) > > + return 0; > > + > > + cpuid = riscv_hartid_to_cpuid(rintc->hart_id); > > Unless I'm missing something, this races with CPUs coming online. Maybe > that's a rare enough case we don't care, but I think we'd also just have > simpler logic if we fixed it... > This depend only on cpuid_to_hartid_map filled up. I wish I could initialize this RINTC mapping in setup_smp() itself like ARM64. But in RISC-V, this file smpboot.c gets built only when CONFIG_SMP is enabled. Hence, we need to initialize this array outside of setup_smp(). I can update the code to initialize this from setup_arch() immediately after setup_smp() if ACPI is enabled. That should avoid the global variable check also. Let me know if you prefer this. > > + /* > > + * When CONFIG_SMP is disabled, mapping won't be created for > > + * all cpus. > > + * CPUs more than NR_CPUS, will be ignored. > > + */ > > + if (cpuid >= 0 && cpuid < NR_CPUS) > > + cpu_madt_rintc[cpuid] = *rintc; > > + > > + return 0; > > +} > > + > > +static int acpi_init_rintc_array(void) > > +{ > > + if (acpi_table_parse_madt(ACPI_MADT_TYPE_RINTC, acpi_parse_madt_rintc, 0) > 0) > > + return 0; > > + > > + return -ENODEV; > > +} > > + > > +/* > > + * Instead of parsing (and freeing) the ACPI table, cache > > + * the RINTC structures since they are frequently used > > + * like in cpuinfo. > > + */ > > +struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu) > > +{ > > + static bool rintc_init_done; > > ... basically just get rid of this global variable, and instead have a > > if (!&cpu_madt_rintc[cpu]) > ... parse ... > return &cpu_madt_rintc[cpu]; > > that'd probably let us get rid of a handful of these helpers too, as now > it's just a call to the parsing bits. > I am afraid this (!&cpu_madt_rintc[cpu]) check won't work since we are not caching the RINTC pointers but actual contents itself. So, the address is always valid. However, as per Drew's earlier feedback I am going to reduce one helper. I am planning to send the next version of this patch once 6.4 rc1 is available since the ACPICA patches are merged now. > > + > > + if (!rintc_init_done) { > > + if (acpi_init_rintc_array()) { > > + pr_err("No valid RINTC entries exist\n"); > > + return NULL; > > + } > > + > > + rintc_init_done = true; > > + } > > + > > + return &cpu_madt_rintc[cpu]; > > +} > > + > > +u32 get_acpi_id_for_cpu(int cpu) > > +{ > > + struct acpi_madt_rintc *rintc = acpi_cpu_get_madt_rintc(cpu); > > + > > + BUG_ON(!rintc); > > We should have some better error reporting here. It looks like all the > callerss of get_acpi_id_for_cpu() are tolerant of a nonsense ID being > returned, so maybe we just pr_warn() something users can understand and then > return -1 or something? > RINTC is mandatory for ACPI systems. Also, all 32bit values are valid for UID. So, there is no bogus value we can return. Actually, I just realized this check is redundant. It will never be NULL since it is a static array. So, we can just get rid of the BUG. Thanks! Sunil
On Thu, Apr 27, 2023 at 02:52:50PM +0530, Sunil V L wrote: > Hi Palmer, > > On Wed, Apr 26, 2023 at 11:45:00AM -0700, Palmer Dabbelt wrote: > > On Tue, 04 Apr 2023 11:20:22 PDT (-0700), sunilvl@ventanamicro.com wrote: > > > RINTC structures in the MADT provide mapping between the hartid > > > and the CPU. This is required many times even at run time like > > > cpuinfo. So, instead of parsing the ACPI table every time, cache > > > the RINTC structures and provide a function to get the correct > > > RINTC structure for a given cpu. > > > > > > Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> > > > Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > > --- > > > arch/riscv/include/asm/acpi.h | 2 ++ > > > arch/riscv/kernel/acpi.c | 60 +++++++++++++++++++++++++++++++++++ > > > 2 files changed, 62 insertions(+) > > > > > > diff --git a/arch/riscv/include/asm/acpi.h b/arch/riscv/include/asm/acpi.h > > > index 9be52b6ffae1..1606dce8992e 100644 > > > --- a/arch/riscv/include/asm/acpi.h > > > +++ b/arch/riscv/include/asm/acpi.h > > > @@ -59,6 +59,8 @@ static inline bool acpi_has_cpu_in_madt(void) > > > > > > static inline void arch_fix_phys_package_id(int num, u32 slot) { } > > > > > > +struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu); > > > +u32 get_acpi_id_for_cpu(int cpu); > > > #endif /* CONFIG_ACPI */ > > > > > > #endif /*_ASM_ACPI_H*/ > > > diff --git a/arch/riscv/kernel/acpi.c b/arch/riscv/kernel/acpi.c > > > index 81d448c41714..40ab55309c70 100644 > > > --- a/arch/riscv/kernel/acpi.c > > > +++ b/arch/riscv/kernel/acpi.c > > > @@ -24,6 +24,66 @@ EXPORT_SYMBOL(acpi_disabled); > > > int acpi_pci_disabled = 1; /* skip ACPI PCI scan and IRQ initialization */ > > > EXPORT_SYMBOL(acpi_pci_disabled); > > > > > > +static struct acpi_madt_rintc cpu_madt_rintc[NR_CPUS]; > > > + > > > +static int acpi_parse_madt_rintc(union acpi_subtable_headers *header, const unsigned long end) > > > +{ > > > + struct acpi_madt_rintc *rintc = (struct acpi_madt_rintc *)header; > > > + int cpuid; > > > + > > > + if (!(rintc->flags & ACPI_MADT_ENABLED)) > > > + return 0; > > > + > > > + cpuid = riscv_hartid_to_cpuid(rintc->hart_id); > > > > Unless I'm missing something, this races with CPUs coming online. Maybe > > that's a rare enough case we don't care, but I think we'd also just have > > simpler logic if we fixed it... > > > This depend only on cpuid_to_hartid_map filled up. I wish I could > initialize this RINTC mapping in setup_smp() itself like ARM64. But in > RISC-V, this file smpboot.c gets built only when CONFIG_SMP is enabled. > Hence, we need to initialize this array outside of setup_smp(). > > I can update the code to initialize this from setup_arch() immediately > after setup_smp() if ACPI is enabled. That should avoid the global > variable check also. Let me know if you prefer this. > > > > + /* > > > + * When CONFIG_SMP is disabled, mapping won't be created for > > > + * all cpus. > > > + * CPUs more than NR_CPUS, will be ignored. > > > + */ > > > + if (cpuid >= 0 && cpuid < NR_CPUS) > > > + cpu_madt_rintc[cpuid] = *rintc; > > > + > > > + return 0; > > > +} > > > + > > > +static int acpi_init_rintc_array(void) > > > +{ > > > + if (acpi_table_parse_madt(ACPI_MADT_TYPE_RINTC, acpi_parse_madt_rintc, 0) > 0) > > > + return 0; > > > + > > > + return -ENODEV; > > > +} > > > + > > > +/* > > > + * Instead of parsing (and freeing) the ACPI table, cache > > > + * the RINTC structures since they are frequently used > > > + * like in cpuinfo. > > > + */ > > > +struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu) > > > +{ > > > + static bool rintc_init_done; > > > > ... basically just get rid of this global variable, and instead have a > > > > if (!&cpu_madt_rintc[cpu]) > > ... parse ... > > return &cpu_madt_rintc[cpu]; > > > > that'd probably let us get rid of a handful of these helpers too, as now > > it's just a call to the parsing bits. > > > I am afraid this (!&cpu_madt_rintc[cpu]) check won't work since we are > not caching the RINTC pointers but actual contents itself. So, the > address is always valid. However, as per Drew's earlier feedback I am > going to reduce one helper. I am planning to send the next version of > this patch once 6.4 rc1 is available since the ACPICA patches are merged > now. > > > > + > > > + if (!rintc_init_done) { > > > + if (acpi_init_rintc_array()) { > > > + pr_err("No valid RINTC entries exist\n"); > > > + return NULL; > > > + } > > > + > > > + rintc_init_done = true; > > > + } > > > + > > > + return &cpu_madt_rintc[cpu]; > > > +} > > > + > > > +u32 get_acpi_id_for_cpu(int cpu) > > > +{ > > > + struct acpi_madt_rintc *rintc = acpi_cpu_get_madt_rintc(cpu); > > > + > > > + BUG_ON(!rintc); > > > > We should have some better error reporting here. It looks like all the > > callerss of get_acpi_id_for_cpu() are tolerant of a nonsense ID being > > returned, so maybe we just pr_warn() something users can understand and then > > return -1 or something? > > > > RINTC is mandatory for ACPI systems. Also, all 32bit values are valid > for UID. So, there is no bogus value we can return. > > Actually, I just realized this check is redundant. It will never be NULL > since it is a static array. So, we can just get rid of the BUG. It can be NULL on the first call of acpi_cpu_get_madt_rintc(), which is a good time to BUG if there's isn't an RINTC. Thanks, drew
On Thu, Apr 27, 2023 at 12:25:42PM +0200, Andrew Jones wrote: > On Thu, Apr 27, 2023 at 02:52:50PM +0530, Sunil V L wrote: > > Hi Palmer, > > > > On Wed, Apr 26, 2023 at 11:45:00AM -0700, Palmer Dabbelt wrote: > > > On Tue, 04 Apr 2023 11:20:22 PDT (-0700), sunilvl@ventanamicro.com wrote: > > > > RINTC structures in the MADT provide mapping between the hartid > > > > and the CPU. This is required many times even at run time like > > > > cpuinfo. So, instead of parsing the ACPI table every time, cache > > > > the RINTC structures and provide a function to get the correct > > > > RINTC structure for a given cpu. > > > > > > > > Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> > > > > Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > > > --- > > > > arch/riscv/include/asm/acpi.h | 2 ++ > > > > arch/riscv/kernel/acpi.c | 60 +++++++++++++++++++++++++++++++++++ > > > > 2 files changed, 62 insertions(+) > > > > > > > > diff --git a/arch/riscv/include/asm/acpi.h b/arch/riscv/include/asm/acpi.h > > > > index 9be52b6ffae1..1606dce8992e 100644 > > > > --- a/arch/riscv/include/asm/acpi.h > > > > +++ b/arch/riscv/include/asm/acpi.h > > > > @@ -59,6 +59,8 @@ static inline bool acpi_has_cpu_in_madt(void) > > > > > > > > static inline void arch_fix_phys_package_id(int num, u32 slot) { } > > > > > > > > +struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu); > > > > +u32 get_acpi_id_for_cpu(int cpu); > > > > #endif /* CONFIG_ACPI */ > > > > > > > > #endif /*_ASM_ACPI_H*/ > > > > diff --git a/arch/riscv/kernel/acpi.c b/arch/riscv/kernel/acpi.c > > > > index 81d448c41714..40ab55309c70 100644 > > > > --- a/arch/riscv/kernel/acpi.c > > > > +++ b/arch/riscv/kernel/acpi.c > > > > @@ -24,6 +24,66 @@ EXPORT_SYMBOL(acpi_disabled); > > > > int acpi_pci_disabled = 1; /* skip ACPI PCI scan and IRQ initialization */ > > > > EXPORT_SYMBOL(acpi_pci_disabled); > > > > > > > > +static struct acpi_madt_rintc cpu_madt_rintc[NR_CPUS]; > > > > + > > > > +static int acpi_parse_madt_rintc(union acpi_subtable_headers *header, const unsigned long end) > > > > +{ > > > > + struct acpi_madt_rintc *rintc = (struct acpi_madt_rintc *)header; > > > > + int cpuid; > > > > + > > > > + if (!(rintc->flags & ACPI_MADT_ENABLED)) > > > > + return 0; > > > > + > > > > + cpuid = riscv_hartid_to_cpuid(rintc->hart_id); > > > > > > Unless I'm missing something, this races with CPUs coming online. Maybe > > > that's a rare enough case we don't care, but I think we'd also just have > > > simpler logic if we fixed it... > > > > > This depend only on cpuid_to_hartid_map filled up. I wish I could > > initialize this RINTC mapping in setup_smp() itself like ARM64. But in > > RISC-V, this file smpboot.c gets built only when CONFIG_SMP is enabled. > > Hence, we need to initialize this array outside of setup_smp(). > > > > I can update the code to initialize this from setup_arch() immediately > > after setup_smp() if ACPI is enabled. That should avoid the global > > variable check also. Let me know if you prefer this. > > > > > > + /* > > > > + * When CONFIG_SMP is disabled, mapping won't be created for > > > > + * all cpus. > > > > + * CPUs more than NR_CPUS, will be ignored. > > > > + */ > > > > + if (cpuid >= 0 && cpuid < NR_CPUS) > > > > + cpu_madt_rintc[cpuid] = *rintc; > > > > + > > > > + return 0; > > > > +} > > > > + > > > > +static int acpi_init_rintc_array(void) > > > > +{ > > > > + if (acpi_table_parse_madt(ACPI_MADT_TYPE_RINTC, acpi_parse_madt_rintc, 0) > 0) > > > > + return 0; > > > > + > > > > + return -ENODEV; > > > > +} > > > > + > > > > +/* > > > > + * Instead of parsing (and freeing) the ACPI table, cache > > > > + * the RINTC structures since they are frequently used > > > > + * like in cpuinfo. > > > > + */ > > > > +struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu) > > > > +{ > > > > + static bool rintc_init_done; > > > > > > ... basically just get rid of this global variable, and instead have a > > > > > > if (!&cpu_madt_rintc[cpu]) > > > ... parse ... > > > return &cpu_madt_rintc[cpu]; > > > > > > that'd probably let us get rid of a handful of these helpers too, as now > > > it's just a call to the parsing bits. > > > > > I am afraid this (!&cpu_madt_rintc[cpu]) check won't work since we are > > not caching the RINTC pointers but actual contents itself. So, the > > address is always valid. However, as per Drew's earlier feedback I am > > going to reduce one helper. I am planning to send the next version of > > this patch once 6.4 rc1 is available since the ACPICA patches are merged > > now. > > > > > > + > > > > + if (!rintc_init_done) { > > > > + if (acpi_init_rintc_array()) { > > > > + pr_err("No valid RINTC entries exist\n"); > > > > + return NULL; > > > > + } > > > > + > > > > + rintc_init_done = true; > > > > + } > > > > + > > > > + return &cpu_madt_rintc[cpu]; > > > > +} > > > > + > > > > +u32 get_acpi_id_for_cpu(int cpu) > > > > +{ > > > > + struct acpi_madt_rintc *rintc = acpi_cpu_get_madt_rintc(cpu); > > > > + > > > > + BUG_ON(!rintc); > > > > > > We should have some better error reporting here. It looks like all the > > > callerss of get_acpi_id_for_cpu() are tolerant of a nonsense ID being > > > returned, so maybe we just pr_warn() something users can understand and then > > > return -1 or something? > > > > > > > RINTC is mandatory for ACPI systems. Also, all 32bit values are valid > > for UID. So, there is no bogus value we can return. > > > > Actually, I just realized this check is redundant. It will never be NULL > > since it is a static array. So, we can just get rid of the BUG. > > It can be NULL on the first call of acpi_cpu_get_madt_rintc(), which is > a good time to BUG if there's isn't an RINTC. > Sorry, I mean if we change the initialization to get called from setup_arch, then we can get rid of this check along with global variable check, correct? Thanks, Sunil
On Thu, Apr 27, 2023 at 04:22:56PM +0530, Sunil V L wrote: > On Thu, Apr 27, 2023 at 12:25:42PM +0200, Andrew Jones wrote: > > On Thu, Apr 27, 2023 at 02:52:50PM +0530, Sunil V L wrote: > > > Hi Palmer, > > > > > > On Wed, Apr 26, 2023 at 11:45:00AM -0700, Palmer Dabbelt wrote: > > > > On Tue, 04 Apr 2023 11:20:22 PDT (-0700), sunilvl@ventanamicro.com wrote: > > > > > RINTC structures in the MADT provide mapping between the hartid > > > > > and the CPU. This is required many times even at run time like > > > > > cpuinfo. So, instead of parsing the ACPI table every time, cache > > > > > the RINTC structures and provide a function to get the correct > > > > > RINTC structure for a given cpu. > > > > > > > > > > Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> > > > > > Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > > > > --- > > > > > arch/riscv/include/asm/acpi.h | 2 ++ > > > > > arch/riscv/kernel/acpi.c | 60 +++++++++++++++++++++++++++++++++++ > > > > > 2 files changed, 62 insertions(+) > > > > > > > > > > diff --git a/arch/riscv/include/asm/acpi.h b/arch/riscv/include/asm/acpi.h > > > > > index 9be52b6ffae1..1606dce8992e 100644 > > > > > --- a/arch/riscv/include/asm/acpi.h > > > > > +++ b/arch/riscv/include/asm/acpi.h > > > > > @@ -59,6 +59,8 @@ static inline bool acpi_has_cpu_in_madt(void) > > > > > > > > > > static inline void arch_fix_phys_package_id(int num, u32 slot) { } > > > > > > > > > > +struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu); > > > > > +u32 get_acpi_id_for_cpu(int cpu); > > > > > #endif /* CONFIG_ACPI */ > > > > > > > > > > #endif /*_ASM_ACPI_H*/ > > > > > diff --git a/arch/riscv/kernel/acpi.c b/arch/riscv/kernel/acpi.c > > > > > index 81d448c41714..40ab55309c70 100644 > > > > > --- a/arch/riscv/kernel/acpi.c > > > > > +++ b/arch/riscv/kernel/acpi.c > > > > > @@ -24,6 +24,66 @@ EXPORT_SYMBOL(acpi_disabled); > > > > > int acpi_pci_disabled = 1; /* skip ACPI PCI scan and IRQ initialization */ > > > > > EXPORT_SYMBOL(acpi_pci_disabled); > > > > > > > > > > +static struct acpi_madt_rintc cpu_madt_rintc[NR_CPUS]; > > > > > + > > > > > +static int acpi_parse_madt_rintc(union acpi_subtable_headers *header, const unsigned long end) > > > > > +{ > > > > > + struct acpi_madt_rintc *rintc = (struct acpi_madt_rintc *)header; > > > > > + int cpuid; > > > > > + > > > > > + if (!(rintc->flags & ACPI_MADT_ENABLED)) > > > > > + return 0; > > > > > + > > > > > + cpuid = riscv_hartid_to_cpuid(rintc->hart_id); > > > > > > > > Unless I'm missing something, this races with CPUs coming online. Maybe > > > > that's a rare enough case we don't care, but I think we'd also just have > > > > simpler logic if we fixed it... > > > > > > > This depend only on cpuid_to_hartid_map filled up. I wish I could > > > initialize this RINTC mapping in setup_smp() itself like ARM64. But in > > > RISC-V, this file smpboot.c gets built only when CONFIG_SMP is enabled. > > > Hence, we need to initialize this array outside of setup_smp(). > > > > > > I can update the code to initialize this from setup_arch() immediately > > > after setup_smp() if ACPI is enabled. That should avoid the global > > > variable check also. Let me know if you prefer this. > > > > > > > > + /* > > > > > + * When CONFIG_SMP is disabled, mapping won't be created for > > > > > + * all cpus. > > > > > + * CPUs more than NR_CPUS, will be ignored. > > > > > + */ > > > > > + if (cpuid >= 0 && cpuid < NR_CPUS) > > > > > + cpu_madt_rintc[cpuid] = *rintc; > > > > > + > > > > > + return 0; > > > > > +} > > > > > + > > > > > +static int acpi_init_rintc_array(void) > > > > > +{ > > > > > + if (acpi_table_parse_madt(ACPI_MADT_TYPE_RINTC, acpi_parse_madt_rintc, 0) > 0) > > > > > + return 0; > > > > > + > > > > > + return -ENODEV; > > > > > +} > > > > > + > > > > > +/* > > > > > + * Instead of parsing (and freeing) the ACPI table, cache > > > > > + * the RINTC structures since they are frequently used > > > > > + * like in cpuinfo. > > > > > + */ > > > > > +struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu) > > > > > +{ > > > > > + static bool rintc_init_done; > > > > > > > > ... basically just get rid of this global variable, and instead have a > > > > > > > > if (!&cpu_madt_rintc[cpu]) > > > > ... parse ... > > > > return &cpu_madt_rintc[cpu]; > > > > > > > > that'd probably let us get rid of a handful of these helpers too, as now > > > > it's just a call to the parsing bits. > > > > > > > I am afraid this (!&cpu_madt_rintc[cpu]) check won't work since we are > > > not caching the RINTC pointers but actual contents itself. So, the > > > address is always valid. However, as per Drew's earlier feedback I am > > > going to reduce one helper. I am planning to send the next version of > > > this patch once 6.4 rc1 is available since the ACPICA patches are merged > > > now. > > > > > > > > + > > > > > + if (!rintc_init_done) { > > > > > + if (acpi_init_rintc_array()) { > > > > > + pr_err("No valid RINTC entries exist\n"); > > > > > + return NULL; > > > > > + } > > > > > + > > > > > + rintc_init_done = true; > > > > > + } > > > > > + > > > > > + return &cpu_madt_rintc[cpu]; > > > > > +} > > > > > + > > > > > +u32 get_acpi_id_for_cpu(int cpu) > > > > > +{ > > > > > + struct acpi_madt_rintc *rintc = acpi_cpu_get_madt_rintc(cpu); > > > > > + > > > > > + BUG_ON(!rintc); > > > > > > > > We should have some better error reporting here. It looks like all the > > > > callerss of get_acpi_id_for_cpu() are tolerant of a nonsense ID being > > > > returned, so maybe we just pr_warn() something users can understand and then > > > > return -1 or something? > > > > > > > > > > RINTC is mandatory for ACPI systems. Also, all 32bit values are valid > > > for UID. So, there is no bogus value we can return. > > > > > > Actually, I just realized this check is redundant. It will never be NULL > > > since it is a static array. So, we can just get rid of the BUG. > > > > It can be NULL on the first call of acpi_cpu_get_madt_rintc(), which is > > a good time to BUG if there's isn't an RINTC. > > > Sorry, I mean if we change the initialization to get called from > setup_arch, then we can get rid of this check along with global variable > check, correct? Sounds good to me, but now I think we're pushing the question of whether to BUG or not on a missing RINTC to that new init function, because otherwise we'll still end up in get_acpi_id_for_cpu() eventually with or without a valid rintc from which we get the uid (and the uid has no specified bogus value). Thanks, drew
diff --git a/arch/riscv/include/asm/acpi.h b/arch/riscv/include/asm/acpi.h index 9be52b6ffae1..1606dce8992e 100644 --- a/arch/riscv/include/asm/acpi.h +++ b/arch/riscv/include/asm/acpi.h @@ -59,6 +59,8 @@ static inline bool acpi_has_cpu_in_madt(void) static inline void arch_fix_phys_package_id(int num, u32 slot) { } +struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu); +u32 get_acpi_id_for_cpu(int cpu); #endif /* CONFIG_ACPI */ #endif /*_ASM_ACPI_H*/ diff --git a/arch/riscv/kernel/acpi.c b/arch/riscv/kernel/acpi.c index 81d448c41714..40ab55309c70 100644 --- a/arch/riscv/kernel/acpi.c +++ b/arch/riscv/kernel/acpi.c @@ -24,6 +24,66 @@ EXPORT_SYMBOL(acpi_disabled); int acpi_pci_disabled = 1; /* skip ACPI PCI scan and IRQ initialization */ EXPORT_SYMBOL(acpi_pci_disabled); +static struct acpi_madt_rintc cpu_madt_rintc[NR_CPUS]; + +static int acpi_parse_madt_rintc(union acpi_subtable_headers *header, const unsigned long end) +{ + struct acpi_madt_rintc *rintc = (struct acpi_madt_rintc *)header; + int cpuid; + + if (!(rintc->flags & ACPI_MADT_ENABLED)) + return 0; + + cpuid = riscv_hartid_to_cpuid(rintc->hart_id); + /* + * When CONFIG_SMP is disabled, mapping won't be created for + * all cpus. + * CPUs more than NR_CPUS, will be ignored. + */ + if (cpuid >= 0 && cpuid < NR_CPUS) + cpu_madt_rintc[cpuid] = *rintc; + + return 0; +} + +static int acpi_init_rintc_array(void) +{ + if (acpi_table_parse_madt(ACPI_MADT_TYPE_RINTC, acpi_parse_madt_rintc, 0) > 0) + return 0; + + return -ENODEV; +} + +/* + * Instead of parsing (and freeing) the ACPI table, cache + * the RINTC structures since they are frequently used + * like in cpuinfo. + */ +struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu) +{ + static bool rintc_init_done; + + if (!rintc_init_done) { + if (acpi_init_rintc_array()) { + pr_err("No valid RINTC entries exist\n"); + return NULL; + } + + rintc_init_done = true; + } + + return &cpu_madt_rintc[cpu]; +} + +u32 get_acpi_id_for_cpu(int cpu) +{ + struct acpi_madt_rintc *rintc = acpi_cpu_get_madt_rintc(cpu); + + BUG_ON(!rintc); + + return rintc->uid; +} + /* * __acpi_map_table() will be called before paging_init(), so early_ioremap() * or early_memremap() should be called here to for ACPI table mapping.