From: Xingang Wang wangxingang5@huawei.com
ascend inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I4L735 CVE: NA
---------------------------------------------------
The process of MPAM device tree initialization is like this: arm_mpam_device_probe() // driver probe mpam_discovery_start() // start discover mpam devices [...] // find and add mpam devices mpam_discovery_complete() // trigger mpam_enable
When there are multiple mpam device nodes, the driver probe procedure will execute more than once. However, the mpam_discovery_start() and mpam_discovery_complete() should only run once. Besides, the start should run first, and the complete should run after all devices added.
So we reorganize the device tree structure, so that there will be only one mpam device parent nodes, and the probe procedure will only run once. We add the child node to represent the mpam devices, and traverse and add all mpam devices in the middle procedure of driver probe.
Signed-off-by: Xingang Wang wangxingang5@huawei.com Signed-off-by: Wang ShaoBo bobo.shaobowang@huawei.com Reviewed-by: Cheng Jian cj.chengjian@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/arm64/kernel/mpam/mpam_device.c | 59 +++++++++++++++------------- 1 file changed, 32 insertions(+), 27 deletions(-)
diff --git a/arch/arm64/kernel/mpam/mpam_device.c b/arch/arm64/kernel/mpam/mpam_device.c index f2cc6e9b2ed4..2aa9a3ab59f2 100644 --- a/arch/arm64/kernel/mpam/mpam_device.c +++ b/arch/arm64/kernel/mpam/mpam_device.c @@ -34,6 +34,7 @@ #include <linux/arm_mpam.h> #include <linux/of.h> #include <linux/of_platform.h> +#include <linux/of_address.h>
#include "mpam_resource.h" #include "mpam_device.h" @@ -1708,10 +1709,9 @@ static const struct of_device_id arm_mpam_of_device_ids[] = { { } };
-static int of_mpam_parse_irq(struct platform_device *pdev, +static int of_mpam_parse_irq(struct device_node *node, struct mpam_device *dev) { - struct device_node *node = pdev->dev.of_node; u32 overflow_interrupt, overflow_flags; u32 error_interrupt, error_interrupt_flags;
@@ -1726,12 +1726,12 @@ static int of_mpam_parse_irq(struct platform_device *pdev, error_interrupt, error_interrupt_flags); }
-static int of_mpam_parse_cache(struct platform_device *pdev) +static int of_mpam_parse_cache(struct platform_device *pdev, + struct device_node *node) { struct mpam_device *dev; - struct device_node *node = pdev->dev.of_node; int cache_level, cache_id; - struct resource *res; + u64 reg_value[2];
if (of_property_read_u32(node, "cache-level", &cache_level)) { dev_err(&pdev->dev, "missing cache level property\n"); @@ -1744,27 +1744,27 @@ static int of_mpam_parse_cache(struct platform_device *pdev) }
/* Base address */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { + if (of_property_read_u64_array(node, "reg", reg_value, 2)) { dev_err(&pdev->dev, "missing io resource property\n"); return -EINVAL; }
- dev = mpam_device_create_cache(cache_level, cache_id, NULL, res->start); + dev = mpam_device_create_cache(cache_level, cache_id, NULL, + reg_value[0]); if (IS_ERR(dev)) { dev_err(&pdev->dev, "Failed to create cache node\n"); return -EINVAL; }
- return of_mpam_parse_irq(pdev, dev); + return of_mpam_parse_irq(node, dev); }
-static int of_mpam_parse_memory(struct platform_device *pdev) +static int of_mpam_parse_memory(struct platform_device *pdev, + struct device_node *node) { struct mpam_device *dev; - struct device_node *node = pdev->dev.of_node; int numa_id; - struct resource *res; + u64 reg_value[2];
if (of_property_read_u32(node, "numa-node-id", &numa_id)) { dev_err(&pdev->dev, "missing numa node id property\n"); @@ -1772,40 +1772,35 @@ static int of_mpam_parse_memory(struct platform_device *pdev) }
/* Base address */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { + if (of_property_read_u64_array(node, "reg", reg_value, 2)) { dev_err(&pdev->dev, "missing io resource property\n"); return -EINVAL; }
- dev = mpam_device_create_memory(numa_id, res->start); + dev = mpam_device_create_memory(numa_id, reg_value[0]); if (IS_ERR(dev)) { dev_err(&pdev->dev, "Failed to create memory node\n"); return -EINVAL; }
- return of_mpam_parse_irq(pdev, dev); + return of_mpam_parse_irq(node, dev); }
-static int of_mpam_parse(struct platform_device *pdev) +static int of_mpam_add_child(struct platform_device *pdev, + struct device_node *node) { - 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"); + if (of_property_read_u32(node, "type", &type)) { + dev_err(&pdev->dev, "missing type property\n"); return -EINVAL; }
switch (type) { case MPAM_CLASS_CACHE: - return of_mpam_parse_cache(pdev); + return of_mpam_parse_cache(pdev, node); case MPAM_CLASS_MEMORY: - return of_mpam_parse_memory(pdev); + return of_mpam_parse_memory(pdev, node); default: pr_warn_once("Unknown node type %u.\n", type); return -EINVAL; @@ -1823,6 +1818,9 @@ static int of_mpam_parse(struct platform_device *pdev) static int arm_mpam_device_probe(struct platform_device *pdev) { int ret; + struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; + struct device_node *child = NULL;
if (!cpus_have_const_cap(ARM64_HAS_MPAM)) return 0; @@ -1830,11 +1828,18 @@ static int arm_mpam_device_probe(struct platform_device *pdev) if (!acpi_disabled || mpam_enabled != MPAM_ENABLE_OF) return 0;
+ if (!node || !of_match_node(arm_mpam_of_device_ids, pdev->dev.of_node)) + return -EINVAL; + ret = mpam_discovery_start(); if (ret) return ret;
- ret = of_mpam_parse(pdev); + for_each_available_child_of_node(node, child) { + ret = of_mpam_add_child(pdev, child); + if (ret) + break; + }
if (ret) { mpam_discovery_failed();