提交 6a2cb7bc 编写于 作者: Y Yu Liao

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/latestSigned-off-by: NYu Liao <liaoyu15@huawei.com>
上级 534ad2fc
......@@ -1865,7 +1865,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();
}
/*
......
# SPDX-License-Identifier: GPL-2.0-only
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
......@@ -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)
......@@ -187,10 +189,10 @@ static int __init acpi_mpam_parse_table(struct acpi_table_header *table,
pr_warn_once("Unknown node type %u offset %ld.",
node_hdr->type,
(table_offset-(char *)table));
/* fall through */
fallthrough;
case ACPI_MPAM_TYPE_SMMU:
/* not yet supported */
/* fall through */
fallthrough;
case ACPI_MPAM_TYPE_UNKNOWN:
break;
}
......@@ -213,7 +215,7 @@ 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;
......@@ -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);
......
// 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));
fallthrough;
case ACPI_MPAM_LOCATION_TYPE_SMMU:
/* not yet supported */
fallthrough;
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;
}
......@@ -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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册