Containing the following patches: ACPI/MPAM: Adapt to Arm's MPAM ACPI table version 2 ACPI / PPTT: Find PPTT processor node by cache id ACPICA: ACPI 6.4: PPTT: add new version of subtable type 1 ACPICA: Add support for Arm's MPAM ACPI table version 2
303 lines
9.0 KiB
Diff
303 lines
9.0 KiB
Diff
From c366e5ecb88cf89495a82a26274e682fb45631ab Mon Sep 17 00:00:00 2001
|
|
From: Yu Liao <liaoyu15@huawei.com>
|
|
Date: Fri, 9 Jun 2023 13:06:52 +0800
|
|
Subject: [PATCH openEuler-20.03-LTS-SP4 4/4] ACPI/MPAM: Adapt to Arm's MPAM ACPI
|
|
table version 2
|
|
|
|
openeuler inclusion
|
|
category: feature
|
|
bugzilla: https://gitee.com/openeuler/kernel/issues/I77UDW
|
|
CVE: NA
|
|
|
|
--------------------------------
|
|
|
|
Support ACPI for MPAM 2.0 [1]. Compatible with MPAM ACPI 1.0 by reading
|
|
ACPI revision.
|
|
|
|
[1] https://developer.arm.com/documentation/den0065/latest
|
|
|
|
Signed-off-by: Yu Liao <liaoyu15@huawei.com>
|
|
---
|
|
arch/arm64/kernel/mpam/mpam_device.c | 2 +-
|
|
drivers/acpi/arm64/Makefile | 2 +-
|
|
drivers/acpi/arm64/mpam.c | 21 +++-
|
|
drivers/acpi/arm64/mpam_v2.c | 175 +++++++++++++++++++++++++++
|
|
include/linux/arm_mpam.h | 2 +-
|
|
5 files changed, 195 insertions(+), 7 deletions(-)
|
|
create mode 100644 drivers/acpi/arm64/mpam_v2.c
|
|
|
|
diff --git a/arch/arm64/kernel/mpam/mpam_device.c b/arch/arm64/kernel/mpam/mpam_device.c
|
|
index b77cea2673c0..1003716efc09 100644
|
|
--- a/arch/arm64/kernel/mpam/mpam_device.c
|
|
+++ b/arch/arm64/kernel/mpam/mpam_device.c
|
|
@@ -1873,7 +1873,7 @@ static int __init arm_mpam_driver_init(void)
|
|
if (acpi_disabled)
|
|
return platform_driver_register(&arm_mpam_driver);
|
|
else
|
|
- return acpi_mpam_parse();
|
|
+ return acpi_mpam_parse_version();
|
|
}
|
|
|
|
/*
|
|
diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
|
|
index 81408ce40506..4ba0486dac6b 100644
|
|
--- a/drivers/acpi/arm64/Makefile
|
|
+++ b/drivers/acpi/arm64/Makefile
|
|
@@ -1,3 +1,3 @@
|
|
obj-$(CONFIG_ACPI_IORT) += iort.o
|
|
obj-$(CONFIG_ACPI_GTDT) += gtdt.o
|
|
-obj-$(CONFIG_ACPI_MPAM) += mpam.o
|
|
+obj-$(CONFIG_ACPI_MPAM) += mpam.o mpam_v2.o
|
|
diff --git a/drivers/acpi/arm64/mpam.c b/drivers/acpi/arm64/mpam.c
|
|
index 6f4572193eb2..7b92cab79cf1 100644
|
|
--- a/drivers/acpi/arm64/mpam.c
|
|
+++ b/drivers/acpi/arm64/mpam.c
|
|
@@ -32,6 +32,8 @@
|
|
#include <linux/nodemask.h>
|
|
#include <linux/arm_mpam.h>
|
|
|
|
+extern int __init acpi_mpam_parse_table_v2(struct acpi_table_header *table,
|
|
+ struct acpi_table_header *pptt);
|
|
/**
|
|
* acpi_mpam_label_cache_component_id() - Recursivly find @min_physid
|
|
* for all leaf CPUs below @cpu_node, use numa node id of @min_cpu_node
|
|
@@ -40,7 +42,7 @@
|
|
* @cpu_node: The point in the toplogy to start the walk
|
|
* @component_id: The id labels the structure mpam_node cache
|
|
*/
|
|
-static int
|
|
+int
|
|
acpi_mpam_label_cache_component_id(struct acpi_table_header *table_hdr,
|
|
struct acpi_pptt_processor *cpu_node,
|
|
u32 *component_id)
|
|
@@ -213,11 +215,11 @@ static int __init acpi_mpam_parse_table(struct acpi_table_header *table,
|
|
return ret;
|
|
}
|
|
|
|
-int __init acpi_mpam_parse(void)
|
|
+int __init acpi_mpam_parse_version(void)
|
|
{
|
|
struct acpi_table_header *mpam, *pptt;
|
|
acpi_status status;
|
|
- int ret;
|
|
+ int ret = -EINVAL;
|
|
|
|
if (!cpus_have_const_cap(ARM64_HAS_MPAM))
|
|
return 0;
|
|
@@ -234,7 +236,18 @@ int __init acpi_mpam_parse(void)
|
|
if (ACPI_FAILURE(status))
|
|
pptt = NULL;
|
|
|
|
- ret = acpi_mpam_parse_table(mpam, pptt);
|
|
+ /*
|
|
+ * The BIOS of Kunpeng 920 supports MPAM ACPI 1.0, but the ACPI
|
|
+ * revision is wrongly written as 1, so distinguished by
|
|
+ * oem_table_id here.
|
|
+ */
|
|
+ if (mpam->revision == 0 || strncmp(mpam->oem_table_id, "HIP08", 5) == 0)
|
|
+ ret = acpi_mpam_parse_table(mpam, pptt);
|
|
+ else if (mpam->revision == 1)
|
|
+ ret = acpi_mpam_parse_table_v2(mpam, pptt);
|
|
+ else
|
|
+ pr_err("unsupported MPAM ACPI version: %u\n", mpam->revision);
|
|
+
|
|
acpi_put_table(pptt);
|
|
acpi_put_table(mpam);
|
|
|
|
diff --git a/drivers/acpi/arm64/mpam_v2.c b/drivers/acpi/arm64/mpam_v2.c
|
|
new file mode 100644
|
|
index 000000000000..a3888a5da695
|
|
--- /dev/null
|
|
+++ b/drivers/acpi/arm64/mpam_v2.c
|
|
@@ -0,0 +1,175 @@
|
|
+// SPDX-License-Identifier: GPL-2.0+
|
|
+/*
|
|
+ * Common code for ARM v8 MPAM ACPI 2.0
|
|
+ *
|
|
+ * Copyright (C) 2019-2022 Huawei Technologies Co., Ltd
|
|
+ *
|
|
+ * Author: Yu Liao <liaoyu15@huawei.com>
|
|
+ *
|
|
+ * Code was partially borrowed from http://www.linux-arm.org/git?p=
|
|
+ * linux-jm.git;a=commit;h=10fe7d6363ae96b25f584d4a91f9d0f2fd5faf3b.
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or modify it
|
|
+ * under the terms and conditions of the GNU General Public License,
|
|
+ * version 2, as published by the Free Software Foundation.
|
|
+ *
|
|
+ * This program is distributed in the hope it will be useful, but WITHOUT
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
+ * more details.
|
|
+ *
|
|
+ */
|
|
+
|
|
+/* Parse the MPAM ACPI table feeding the discovered nodes into the driver */
|
|
+#define pr_fmt(fmt) "ACPI MPAM: " fmt
|
|
+
|
|
+#include <linux/acpi.h>
|
|
+#include <acpi/processor.h>
|
|
+#include <linux/cpu.h>
|
|
+#include <linux/cpumask.h>
|
|
+#include <linux/cacheinfo.h>
|
|
+#include <linux/string.h>
|
|
+#include <linux/nodemask.h>
|
|
+#include <linux/arm_mpam.h>
|
|
+
|
|
+extern int
|
|
+acpi_mpam_label_cache_component_id(struct acpi_table_header *table_hdr,
|
|
+ struct acpi_pptt_processor *cpu_node,
|
|
+ u32 *component_id);
|
|
+
|
|
+static int __init acpi_mpam_parse_cache_v2(struct acpi_mpam_msc_node *msc,
|
|
+ struct acpi_table_header *pptt)
|
|
+{
|
|
+ int ret = 0;
|
|
+ int level;
|
|
+ u32 component_id;
|
|
+ struct mpam_device *dev;
|
|
+ struct cacheinfo *ci;
|
|
+ struct acpi_pptt_processor *pptt_cpu_node;
|
|
+ struct acpi_mpam_resource_node *resources;
|
|
+
|
|
+ resources = (struct acpi_mpam_resource_node *)(msc + 1);
|
|
+
|
|
+ pptt_cpu_node = find_acpi_processor_node_from_cache_id(resources->locator.cache_locator.cache_reference);
|
|
+ if (!pptt_cpu_node) {
|
|
+ pr_err("Failed to find processor cpu node\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ ret = acpi_mpam_label_cache_component_id(pptt, pptt_cpu_node,
|
|
+ &component_id);
|
|
+ if (ret) {
|
|
+ pr_err("Failed to label cache component id\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ cpus_read_lock();
|
|
+ ci = cacheinfo_shared_cpu_map_search(pptt_cpu_node);
|
|
+ if (!ci) {
|
|
+ pr_err_once("No CPU has cache with PPTT reference %#llx",
|
|
+ resources->locator.cache_locator.cache_reference);
|
|
+ pr_err_once("All CPUs must be online to probe mpam.\n");
|
|
+ cpus_read_unlock();
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ level = ci->level;
|
|
+ ci = NULL;
|
|
+ cpus_read_unlock();
|
|
+
|
|
+ /*
|
|
+ * Possible we can get cpu-affinity in next MPAM ACPI version,
|
|
+ * now we have to set it to NULL and use default possible_aff-
|
|
+ * inity.
|
|
+ */
|
|
+ dev = mpam_device_create_cache(level, component_id, NULL,
|
|
+ msc->base_address);
|
|
+ if (IS_ERR(dev)) {
|
|
+ pr_err("Failed to create cache node\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ return mpam_register_device_irq(dev,
|
|
+ msc->overflow_interrupt, msc->overflow_interrupt_flags,
|
|
+ msc->error_interrupt, msc->error_interrupt_flags);
|
|
+}
|
|
+
|
|
+static int __init acpi_mpam_parse_memory_v2(struct acpi_mpam_msc_node *msc)
|
|
+{
|
|
+ u32 component_id;
|
|
+ struct mpam_device *dev;
|
|
+ struct acpi_mpam_resource_node *resources;
|
|
+
|
|
+ resources = (struct acpi_mpam_resource_node *)(msc + 1);
|
|
+
|
|
+ component_id = acpi_map_pxm_to_node(resources->locator.memory_locator.proximity_domain);
|
|
+ if (component_id == NUMA_NO_NODE)
|
|
+ component_id = 0;
|
|
+
|
|
+ dev = mpam_device_create_memory(component_id, msc->base_address);
|
|
+ if (IS_ERR(dev)) {
|
|
+ pr_err("Failed to create memory node\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ return mpam_register_device_irq(dev,
|
|
+ msc->overflow_interrupt, msc->overflow_interrupt_flags,
|
|
+ msc->error_interrupt, msc->error_interrupt_flags);
|
|
+}
|
|
+
|
|
+int __init acpi_mpam_parse_table_v2(struct acpi_table_header *table,
|
|
+ struct acpi_table_header *pptt)
|
|
+{
|
|
+ char *table_offset = (char *)(table + 1);
|
|
+ char *table_end = (char *)table + table->length;
|
|
+ struct acpi_mpam_msc_node *node_hdr;
|
|
+ struct acpi_mpam_resource_node *resources;
|
|
+ int ret = 0;
|
|
+
|
|
+ ret = mpam_discovery_start();
|
|
+
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ node_hdr = (struct acpi_mpam_msc_node *)table_offset;
|
|
+ resources = (struct acpi_mpam_resource_node *)(node_hdr + 1);
|
|
+
|
|
+ while (table_offset < table_end) {
|
|
+ switch (resources->locator_type) {
|
|
+
|
|
+ case ACPI_MPAM_LOCATION_TYPE_PROCESSOR_CACHE:
|
|
+ ret = acpi_mpam_parse_cache_v2(node_hdr, pptt);
|
|
+ break;
|
|
+ case ACPI_MPAM_LOCATION_TYPE_MEMORY:
|
|
+ ret = acpi_mpam_parse_memory_v2(node_hdr);
|
|
+ break;
|
|
+ default:
|
|
+ pr_warn_once("Unknown node type %u offset %ld.",
|
|
+ (resources->locator_type),
|
|
+ (table_offset-(char *)table));
|
|
+ /* fall through */
|
|
+ case ACPI_MPAM_LOCATION_TYPE_SMMU:
|
|
+ /* not yet supported */
|
|
+ /* fall through */
|
|
+ case ACPI_MPAM_TYPE_UNKNOWN:
|
|
+ break;
|
|
+ }
|
|
+ if (ret)
|
|
+ break;
|
|
+
|
|
+ table_offset += node_hdr->length;
|
|
+ node_hdr = (struct acpi_mpam_msc_node *)table_offset;
|
|
+ resources = (struct acpi_mpam_resource_node *)(node_hdr + 1);
|
|
+ }
|
|
+
|
|
+ if (ret) {
|
|
+ pr_err("discovery failed: %d\n", ret);
|
|
+ mpam_discovery_failed();
|
|
+ } else {
|
|
+ ret = mpam_discovery_complete();
|
|
+ if (!ret)
|
|
+ pr_info("Successfully init mpam by ACPI.\n");
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
diff --git a/include/linux/arm_mpam.h b/include/linux/arm_mpam.h
|
|
index eed95ba06a5d..9bdca6cd3cc9 100644
|
|
--- a/include/linux/arm_mpam.h
|
|
+++ b/include/linux/arm_mpam.h
|
|
@@ -116,6 +116,6 @@ static inline int mpam_register_device_irq(struct mpam_device *dev,
|
|
return ret;
|
|
}
|
|
|
|
-int __init acpi_mpam_parse(void);
|
|
+int __init acpi_mpam_parse_version(void);
|
|
|
|
#endif
|
|
--
|
|
2.25.1
|
|
|