From: Xingang Wang wangxingang5@huawei.com
ascend inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I4L735 CVE: NA
---------------------------------------------------
For now, only ACPI boot is supported for the arm64 mpam init. This introduce device tree support, treat the mpam device as a platform device, add a platform driver and use of interface to parse the dts node. Add a common init function to call the device tree or ACPI init procedure, according to whether ACPI is disabled and the boot arguments.
Signed-off-by: Xingang Wang wangxingang5@huawei.com Reviewed-by: Wang ShaoBo bobo.shaobowang@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/arm64/kernel/mpam/mpam_device.c | 170 ++++++++++++++++++++++++++ arch/arm64/kernel/mpam/mpam_resctrl.c | 2 + drivers/acpi/arm64/mpam.c | 6 - include/linux/arm_mpam.h | 3 + 4 files changed, 175 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/kernel/mpam/mpam_device.c b/arch/arm64/kernel/mpam/mpam_device.c index e887d32c8451..85b5c415fdc2 100644 --- a/arch/arm64/kernel/mpam/mpam_device.c +++ b/arch/arm64/kernel/mpam/mpam_device.c @@ -32,6 +32,8 @@ #include <linux/cpu.h> #include <linux/cacheinfo.h> #include <linux/arm_mpam.h> +#include <linux/of.h> +#include <linux/of_platform.h>
#include "mpam_resource.h" #include "mpam_device.h" @@ -1698,3 +1700,171 @@ void mpam_component_get_config(struct mpam_component *comp, { mpam_component_get_config_local(comp, args, result); } + +#define ARM_MPAM_PDEV_NAME "arm-mpam" + +static const struct of_device_id arm_mpam_of_device_ids[] = { + {.compatible = "arm,mpam"}, + { } +}; + +static int of_mpam_parse_irq(struct platform_device *pdev, + struct mpam_device *dev) +{ + struct device_node *node = pdev->dev.of_node; + u32 overflow_interrupt, overflow_flags; + u32 error_interrupt, error_interrupt_flags; + + of_property_read_u32(node, "overflow-interrupt", &overflow_interrupt); + of_property_read_u32(node, "overflow-flags", &overflow_flags); + of_property_read_u32(node, "error-interrupt", &error_interrupt); + of_property_read_u32(node, "error-interrupt-flags", + &error_interrupt_flags); + + return mpam_register_device_irq(dev, + overflow_interrupt, overflow_flags, + error_interrupt, error_interrupt_flags); +} + +static int of_mpam_parse_cache(struct platform_device *pdev) +{ + struct mpam_device *dev; + struct device_node *node = pdev->dev.of_node; + int cache_level, cache_id; + struct resource *res; + + if (of_property_read_u32(node, "cache-level", &cache_level)) { + dev_err(&pdev->dev, "missing cache level property\n"); + return -EINVAL; + } + + if (of_property_read_u32(node, "cache-id", &cache_id)) { + dev_err(&pdev->dev, "missing cache id property\n"); + return -EINVAL; + } + + /* Base address */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "missing io resource property\n"); + return -EINVAL; + } + + dev = mpam_device_create_cache(cache_level, cache_id, NULL, res->start); + if (IS_ERR(dev)) { + dev_err(&pdev->dev, "Failed to create cache node\n"); + return -EINVAL; + } + + return of_mpam_parse_irq(pdev, dev); +} + +static int of_mpam_parse_memory(struct platform_device *pdev) +{ + struct mpam_device *dev; + struct device_node *node = pdev->dev.of_node; + int numa_id; + struct resource *res; + + if (of_property_read_u32(node, "numa-node-id", &numa_id)) { + dev_err(&pdev->dev, "missing numa node id property\n"); + return -EINVAL; + } + + /* Base address */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "missing io resource property\n"); + return -EINVAL; + } + + dev = mpam_device_create_memory(numa_id, res->start); + if (IS_ERR(dev)) { + dev_err(&pdev->dev, "Failed to create memory node\n"); + return -EINVAL; + } + + return of_mpam_parse_irq(pdev, dev); +} + +static int of_mpam_parse(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; + enum mpam_class_types type; + + if (!node || !of_match_node(arm_mpam_of_device_ids, pdev->dev.of_node)) + return -EINVAL; + + if (of_property_read_u32(dev->of_node, "type", &type)) { + dev_err(dev, "missing type property\n"); + return -EINVAL; + } + + switch (type) { + case MPAM_CLASS_CACHE: + return of_mpam_parse_cache(pdev); + case MPAM_CLASS_MEMORY: + return of_mpam_parse_memory(pdev); + default: + pr_warn_once("Unknown node type %u.\n", type); + return -EINVAL; + /* fall through */ + case MPAM_CLASS_SMMU: + /* not yet supported */ + /* fall through */ + case MPAM_CLASS_UNKNOWN: + break; + } + + return 0; +} + +static int arm_mpam_device_probe(struct platform_device *pdev) +{ + int ret; + + if (!cpus_have_const_cap(ARM64_HAS_MPAM)) + return 0; + + if (!acpi_disabled || mpam_enabled != MPAM_ENABLE_OF) + return 0; + + ret = mpam_discovery_start(); + if (ret) + return ret; + + ret = of_mpam_parse(pdev); + + if (ret) { + mpam_discovery_failed(); + } else { + ret = mpam_discovery_complete(); + if (!ret) + pr_info("Successfully init mpam by DT.\n"); + } + + return ret; +} + +static struct platform_driver arm_mpam_driver = { + .driver = { + .name = ARM_MPAM_PDEV_NAME, + .of_match_table = arm_mpam_of_device_ids, + }, + .probe = arm_mpam_device_probe, +}; + +static int __init arm_mpam_driver_init(void) +{ + if (acpi_disabled) + return platform_driver_register(&arm_mpam_driver); + else + return acpi_mpam_parse(); +} + +/* + * We want to run after cacheinfo_sysfs_init() has caused the cacheinfo + * structures to be populated. That runs as a device_initcall. + */ +device_initcall_sync(arm_mpam_driver_init); diff --git a/arch/arm64/kernel/mpam/mpam_resctrl.c b/arch/arm64/kernel/mpam/mpam_resctrl.c index 86752a7a71a8..53789acaae20 100644 --- a/arch/arm64/kernel/mpam/mpam_resctrl.c +++ b/arch/arm64/kernel/mpam/mpam_resctrl.c @@ -2162,6 +2162,8 @@ static int __init mpam_setup(char *str) { if (!strcmp(str, "=acpi")) mpam_enabled = MPAM_ENABLE_ACPI; + else if (!strcmp(str, "=of")) + mpam_enabled = MPAM_ENABLE_OF;
return 1; } diff --git a/drivers/acpi/arm64/mpam.c b/drivers/acpi/arm64/mpam.c index 51419473f63b..6f4572193eb2 100644 --- a/drivers/acpi/arm64/mpam.c +++ b/drivers/acpi/arm64/mpam.c @@ -240,9 +240,3 @@ int __init acpi_mpam_parse(void)
return ret; } - -/* - * We want to run after cacheinfo_sysfs_init() has caused the cacheinfo - * structures to be populated. That runs as a device_initcall. - */ -device_initcall_sync(acpi_mpam_parse); diff --git a/include/linux/arm_mpam.h b/include/linux/arm_mpam.h index d32c553ae473..01498a5c06ba 100644 --- a/include/linux/arm_mpam.h +++ b/include/linux/arm_mpam.h @@ -61,6 +61,7 @@ void mpam_discovery_failed(void); enum mpam_enable_type { MPAM_ENABLE_DENIED = 0, MPAM_ENABLE_ACPI, + MPAM_ENABLE_OF, };
extern enum mpam_enable_type mpam_enabled; @@ -115,4 +116,6 @@ static inline int mpam_register_device_irq(struct mpam_device *dev, return ret; }
+int __init acpi_mpam_parse(void); + #endif