diff --git a/kernel.spec b/kernel.spec index b7c794a..acf822f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -32,7 +32,7 @@ Name: kernel Version: 4.19.90 -Release: %{hulkrelease}.0230 +Release: %{hulkrelease}.0231 Summary: Linux Kernel License: GPLv2 URL: http://www.kernel.org/ @@ -832,6 +832,63 @@ fi %changelog +* Wed Nov 1 2023 hongrongxuan - 4.19.90-2311.1.0.0231 +- perf/smmuv3: Add MODULE_ALIAS for module auto loading +- perf/smmuv3: Enable HiSilicon Erratum 162001900 quirk for HIP08/09 +- perf/smmuv3: Enable HiSilicon Erratum 162001800 quirk +- Revert "perf/smmuv3_pmu: Enable HiSilicon Erratum 162001800 quirk" +- drivers/perf: hisi: add NULL check for name +- drivers/perf: hisi: Remove redundant initialized of pmu->name +- drivers/perf: hisi: Extract initialization of "cpa_pmu->pmu" +- drivers/perf: hisi: Simplify the parameters of hisi_pmu_init() +- drivers/perf: hisi: Advertise the PERF_PMU_CAP_NO_EXCLUDE capability +- perf: hisi: Extract hisi_pmu_init +- perf: hisi: Add configs for PMU isolation +- perf: hisi: Fix read sccl_id and ccl_id error in TSV200 +- drivers/perf: fixed kabi broken for SLLC and PA PMU +- drivers/perf: fixed the issue that the kabi value changed +- drivers/perf: hisi: Don't migrate perf to the CPU going to teardown +- drivers/perf: hisi: Add TLP filter support +- docs: perf: Fix PMU instance name of hisi-pcie-pmu +- docs: fix 'make htmldocs' warning in perf +- docs: perf: Address some html build warnings +- docs: perf: Add description for HiSilicon PCIe PMU driver +- docs: perf: Add new description on HiSilicon uncore PMU v2 +- docs: perf: move to the admin-guide +- drivers/perf: hisi: Fix some event id for hisi-pcie-pmu +- drivers/perf: hisi: Add Support for CPA PMU +- driver/perf: hisi: fix kabi broken for struct hisi_pmu +- drivers/perf: hisi: Associate PMUs in SICL with CPUs online +- drivers/perf: hisi: Add driver for HiSilicon PCIe PMU +- PCI: Add pci_dev_id() helper +- perf: hisi: Fix unexpected modifications in hisi_uncore_l3c_pmu.c +- perf: hisi: Add support for HiSilicon SoC LPDDRC PMU +- perf: hisi: Add support for HiSilicon SoC L3T PMU +- perf: hisi: Fix read sccl_id and ccl_id error in some platform +- perf: hisi: Make irq shared +- drivers/perf: hisi: Fix data source control +- perf/hisi: Use irq_set_affinity() +- drivers/perf: hisi: Add support for HiSilicon PA PMU driver +- drivers/perf: hisi: Add support for HiSilicon SLLC PMU driver +- drivers/perf: hisi: Update DDRC PMU for programmable counter +- drivers/perf: hisi: Add new functions for HHA PMU +- drivers/perf: hisi: Add new functions for L3C PMU +- drivers/perf: hisi: Add PMU version for uncore PMU drivers. +- drivers/perf: hisi: Refactor code for more uncore PMUs +- drivers/perf: hisi: Remove unnecessary check of counter index +- drivers/perf: hisi: Add identifier sysfs file +- perf: hisi: use devm_platform_ioremap_resource() to simplify code +- drivers: provide devm_platform_ioremap_resource() +- For drivers that do not support context exclusion let's advertise the PERF_PMU_CAP_NO_EXCLUDE capability. This ensures that perf will prevent us from handling events where any exclusion flags are set. Let's also remove the now unnecessary check for exclusion flags. +- drivers/perf: Fix kernel panic when rmmod PMU modules during perf sampling +- docs: perf: convert to ReST +- Revert "perf: hisi: remove duplicated code" +- Revert "drivers/perf: Fix kernel panic when rmmod PMU modules during perf sampling" +- Revert "perf: hisi: Add support for HiSilicon SoC PMU driver dt probe" +- Revert "perf: hisi: Add support for HiSilicon SoC LPDDRC PMU driver" +- Revert "perf: hisi: Add support for HiSilicon SoC L3T PMU driver" +- Revert "perf: hisi: Fix compile error if defined MODULE" + * Wed Nov 1 2023 Luo Shengwei - 4.19.90-2311.1.0.0230 - !2609 Fix CVE-2023-5717 - !2588 [openEuler-1.0-LTS] Add Phytium Display Engine support. diff --git a/patches/0042-Revert-perf-hisi-Fix-compile-error-if-defined-MODULE.patch b/patches/0042-Revert-perf-hisi-Fix-compile-error-if-defined-MODULE.patch new file mode 100644 index 0000000..acc3439 --- /dev/null +++ b/patches/0042-Revert-perf-hisi-Fix-compile-error-if-defined-MODULE.patch @@ -0,0 +1,37 @@ +From 6f28c899df9750b13fdc86b9b3bb80d46aa89c8d Mon Sep 17 00:00:00 2001 +From: hongrongxuan +Date: Wed, 25 Oct 2023 14:58:04 +0800 +Subject: [PATCH 01/55] Revert "perf: hisi: Fix compile error if defined + MODULE" + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +-------------------------------------------------------------- + +This reverts commit f00917fa81207962a5455e1084c90aff36b3a6ae. + +This bugfix fixed in higher verison in L3t pmu driver, inclusion it later. + +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c +index ca395252ccc3..8f8b211788e0 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c +@@ -241,7 +241,7 @@ static int hisi_lpddrc_pmu_init_irq(struct hisi_pmu *lpddrc_pmu, + static const struct of_device_id lpddrc_of_match[] = { + { .compatible = "hisilicon,lpddrc-pmu", }, + {}, +-}; ++} + MODULE_DEVICE_TABLE(of, lpddrc_of_match); + + static int hisi_lpddrc_pmu_init_data(struct platform_device *pdev, +-- +2.27.0 + diff --git a/patches/0043-Revert-perf-hisi-Add-support-for-HiSilicon-SoC-L3T-P.patch b/patches/0043-Revert-perf-hisi-Add-support-for-HiSilicon-SoC-L3T-P.patch new file mode 100644 index 0000000..498efa1 --- /dev/null +++ b/patches/0043-Revert-perf-hisi-Add-support-for-HiSilicon-SoC-L3T-P.patch @@ -0,0 +1,480 @@ +From 7cd21a232cb93ea0598386c028c88e1931946887 Mon Sep 17 00:00:00 2001 +From: hongrongxuan +Date: Wed, 25 Oct 2023 15:03:16 +0800 +Subject: [PATCH 02/55] Revert "perf: hisi: Add support for HiSilicon SoC L3T + PMU driver" + +driver inclusion +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +------------------------------------------------------------ + +This reverts commit 72ed85332d7704ab91afe3f14ab95b39fca17e97. + +Now, revert it, then we will inclusion the newer version of L3T PMU +driver. + +Signed-off-by: hongrongxuan + + Conflicts: + drivers/perf/hisilicon/Makefile +--- + drivers/perf/hisilicon/Makefile | 7 +- + drivers/perf/hisilicon/hisi_uncore_l3t_pmu.c | 432 ------------------- + 2 files changed, 1 insertion(+), 438 deletions(-) + delete mode 100644 drivers/perf/hisilicon/hisi_uncore_l3t_pmu.c + +diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile +index 63942ae6b167..3651f18260e5 100644 +--- a/drivers/perf/hisilicon/Makefile ++++ b/drivers/perf/hisilicon/Makefile +@@ -1,6 +1 @@ +-obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o \ +- hisi_uncore_l3c_pmu.o \ +- hisi_uncore_hha_pmu.o \ +- hisi_uncore_ddrc_pmu.o \ +- hisi_uncore_lpddrc_pmu.o \ +- hisi_uncore_l3t_pmu.o ++obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_lpddrc_pmu.o +diff --git a/drivers/perf/hisilicon/hisi_uncore_l3t_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3t_pmu.c +deleted file mode 100644 +index bd4e600e0c32..000000000000 +--- a/drivers/perf/hisilicon/hisi_uncore_l3t_pmu.c ++++ /dev/null +@@ -1,432 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/* +- * HiSilicon SoC L3T uncore Hardware event counters support +- * +- * Copyright (C) 2021 Hisilicon Limited +- * Author: Fang Lijun +- * Anurup M +- * Shaokun Zhang +- * +- * This code is based on the uncore PMUs like arm-cci and arm-ccn. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. +- */ +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "hisi_uncore_pmu.h" +- +-/* L3T register definition */ +-#define L3T_PERF_CTRL 0x0408 +-#define L3T_INT_MASK 0x0800 +-#define L3T_INT_STATUS 0x0808 +-#define L3T_INT_CLEAR 0x080c +-#define L3T_EVENT_CTRL 0x1c00 +-#define L3T_EVENT_TYPE0 0x1d00 +-/* +- * Each counter is 48-bits and [48:63] are reserved +- * which are Read-As-Zero and Writes-Ignored. +- */ +-#define L3T_CNTR0_LOWER 0x1e00 +- +-/* L3T has 8-counters */ +-#define L3T_NR_COUNTERS 0x8 +- +-#define L3T_PERF_CTRL_EN 0x20000 +-#define L3T_EVTYPE_NONE 0xff +- +-/* +- * Select the counter register offset using the counter index +- */ +-static u32 hisi_l3t_pmu_get_counter_offset(u32 cntr_idx) +-{ +- return (L3T_CNTR0_LOWER + (cntr_idx * 8)); +-} +- +-static u64 hisi_l3t_pmu_read_counter(struct hisi_pmu *l3t_pmu, +- struct hw_perf_event *hwc) +-{ +- u32 idx = hwc->idx; +- +- if (!hisi_uncore_pmu_counter_valid(l3t_pmu, idx)) { +- dev_err(l3t_pmu->dev, "Unsupported event index:%d!\n", idx); +- return 0; +- } +- +- /* Read 64-bits and the upper 16 bits are RAZ */ +- return readq(l3t_pmu->base + hisi_l3t_pmu_get_counter_offset(idx)); +-} +- +-static void hisi_l3t_pmu_write_counter(struct hisi_pmu *l3t_pmu, +- struct hw_perf_event *hwc, u64 val) +-{ +- u32 idx = hwc->idx; +- +- if (!hisi_uncore_pmu_counter_valid(l3t_pmu, idx)) { +- dev_err(l3t_pmu->dev, "Unsupported event index:%d!\n", idx); +- return; +- } +- +- /* Write 64-bits and the upper 16 bits are WI */ +- writeq(val, l3t_pmu->base + hisi_l3t_pmu_get_counter_offset(idx)); +-} +- +-static void hisi_l3t_pmu_write_evtype(struct hisi_pmu *l3t_pmu, int idx, +- u32 type) +-{ +- u32 reg, reg_idx, shift, val; +- +- /* +- * Select the appropriate event select register(L3T_EVENT_TYPE0/1). +- * There are 2 event select registers for the 8 hardware counters. +- * Event code is 8-bits and for the former 4 hardware counters, +- * L3T_EVENT_TYPE0 is chosen. For the latter 4 hardware counters, +- * L3T_EVENT_TYPE1 is chosen. +- */ +- reg = L3T_EVENT_TYPE0 + (idx / 4) * 4; +- reg_idx = idx % 4; +- shift = 8 * reg_idx; +- +- /* Write event code to L3T_EVENT_TYPEx Register */ +- val = readl(l3t_pmu->base + reg); +- val &= ~(L3T_EVTYPE_NONE << shift); +- val |= (type << shift); +- writel(val, l3t_pmu->base + reg); +-} +- +-static void hisi_l3t_pmu_start_counters(struct hisi_pmu *l3t_pmu) +-{ +- u32 val; +- +- /* +- * Set perf_enable bit in L3T_PERF_CTRL register to start counting +- * for all enabled counters. +- */ +- val = readl(l3t_pmu->base + L3T_PERF_CTRL); +- val |= L3T_PERF_CTRL_EN; +- writel(val, l3t_pmu->base + L3T_PERF_CTRL); +-} +- +-static void hisi_l3t_pmu_stop_counters(struct hisi_pmu *l3t_pmu) +-{ +- u32 val; +- +- /* +- * Clear perf_enable bit in L3T_PERF_CTRL register to stop counting +- * for all enabled counters. +- */ +- val = readl(l3t_pmu->base + L3T_PERF_CTRL); +- val &= ~(L3T_PERF_CTRL_EN); +- writel(val, l3t_pmu->base + L3T_PERF_CTRL); +-} +- +-static void hisi_l3t_pmu_enable_counter(struct hisi_pmu *l3t_pmu, +- struct hw_perf_event *hwc) +-{ +- u32 val; +- +- /* Enable counter index in L3T_EVENT_CTRL register */ +- val = readl(l3t_pmu->base + L3T_EVENT_CTRL); +- val |= (1 << hwc->idx); +- writel(val, l3t_pmu->base + L3T_EVENT_CTRL); +-} +- +-static void hisi_l3t_pmu_disable_counter(struct hisi_pmu *l3t_pmu, +- struct hw_perf_event *hwc) +-{ +- u32 val; +- +- /* Clear counter index in L3T_EVENT_CTRL register */ +- val = readl(l3t_pmu->base + L3T_EVENT_CTRL); +- val &= ~(1 << hwc->idx); +- writel(val, l3t_pmu->base + L3T_EVENT_CTRL); +-} +- +-static void hisi_l3t_pmu_enable_counter_int(struct hisi_pmu *l3t_pmu, +- struct hw_perf_event *hwc) +-{ +- u32 val; +- +- val = readl(l3t_pmu->base + L3T_INT_MASK); +- /* Write 0 to enable interrupt */ +- val &= ~(1 << hwc->idx); +- writel(val, l3t_pmu->base + L3T_INT_MASK); +-} +- +-static void hisi_l3t_pmu_disable_counter_int(struct hisi_pmu *l3t_pmu, +- struct hw_perf_event *hwc) +-{ +- u32 val; +- +- val = readl(l3t_pmu->base + L3T_INT_MASK); +- /* Write 1 to mask interrupt */ +- val |= (1 << hwc->idx); +- writel(val, l3t_pmu->base + L3T_INT_MASK); +-} +- +-static irqreturn_t hisi_l3t_pmu_isr(int irq, void *dev_id) +-{ +- struct hisi_pmu *l3t_pmu = dev_id; +- struct perf_event *event; +- unsigned long overflown; +- int idx; +- +- /* Read L3T_INT_STATUS register */ +- overflown = readl(l3t_pmu->base + L3T_INT_STATUS); +- if (!overflown) +- return IRQ_NONE; +- +- /* +- * Find the counter index which overflowed if the bit was set +- * and handle it. +- */ +- for_each_set_bit(idx, &overflown, L3T_NR_COUNTERS) { +- /* Write 1 to clear the IRQ status flag */ +- writel((1 << idx), l3t_pmu->base + L3T_INT_CLEAR); +- +- /* Get the corresponding event struct */ +- event = l3t_pmu->pmu_events.hw_events[idx]; +- if (!event) +- continue; +- +- hisi_uncore_pmu_event_update(event); +- hisi_uncore_pmu_set_event_period(event); +- } +- +- return IRQ_HANDLED; +-} +- +-static int hisi_l3t_pmu_init_irq(struct hisi_pmu *l3t_pmu, +- struct platform_device *pdev) +-{ +- int irq, ret; +- +- /* Read and init IRQ */ +- irq = platform_get_irq(pdev, 0); +- if (irq < 0) { +- dev_err(&pdev->dev, "L3T PMU get irq fail; irq:%d\n", irq); +- return irq; +- } +- +- ret = devm_request_irq(&pdev->dev, irq, hisi_l3t_pmu_isr, +- IRQF_NOBALANCING | IRQF_NO_THREAD | IRQF_SHARED, +- dev_name(&pdev->dev), l3t_pmu); +- if (ret < 0) { +- dev_err(&pdev->dev, +- "Fail to request IRQ:%d ret:%d\n", irq, ret); +- return ret; +- } +- +- l3t_pmu->irq = irq; +- +- return 0; +-} +- +-static const struct of_device_id l3t_of_match[] = { +- { .compatible = "hisilicon,l3t-pmu", }, +- {}, +-}; +-MODULE_DEVICE_TABLE(of, l3t_of_match); +- +-static int hisi_l3t_pmu_init_data(struct platform_device *pdev, +- struct hisi_pmu *l3t_pmu) +-{ +- struct resource *res; +- +- /* +- * Use the SCCL_ID and CCL_ID to identify the L3T PMU, while +- * SCCL_ID is in MPIDR[aff2] and CCL_ID is in MPIDR[aff1]. +- */ +- if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id", +- &l3t_pmu->sccl_id)) { +- dev_err(&pdev->dev, "Can not read l3t sccl-id!\n"); +- return -EINVAL; +- } +- +- if (device_property_read_u32(&pdev->dev, "hisilicon,ccl-id", +- &l3t_pmu->ccl_id)) { +- dev_err(&pdev->dev, "Can not read l3t ccl-id!\n"); +- return -EINVAL; +- } +- +- if (device_property_read_u32(&pdev->dev, "hisilicon,index-id", +- &l3t_pmu->index_id)) { +- dev_err(&pdev->dev, "Can not read l3t index-id!\n"); +- return -EINVAL; +- } +- +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- l3t_pmu->base = devm_ioremap_resource(&pdev->dev, res); +- if (IS_ERR(l3t_pmu->base)) { +- dev_err(&pdev->dev, "ioremap failed for l3t_pmu resource\n"); +- return PTR_ERR(l3t_pmu->base); +- } +- +- return 0; +-} +- +-static struct attribute *hisi_l3t_pmu_format_attr[] = { +- HISI_PMU_FORMAT_ATTR(event, "config:0-7"), +- NULL, +-}; +- +-static const struct attribute_group hisi_l3t_pmu_format_group = { +- .name = "format", +- .attrs = hisi_l3t_pmu_format_attr, +-}; +- +-static struct attribute *hisi_l3t_pmu_events_attr[] = { +- HISI_PMU_EVENT_ATTR(rd_cpipe, 0x00), +- HISI_PMU_EVENT_ATTR(wr_cpipe, 0x01), +- HISI_PMU_EVENT_ATTR(rd_hit_cpipe, 0x02), +- HISI_PMU_EVENT_ATTR(wr_hit_cpipe, 0x03), +- HISI_PMU_EVENT_ATTR(victim_num, 0x04), +- HISI_PMU_EVENT_ATTR(rd_spipe, 0x20), +- HISI_PMU_EVENT_ATTR(wr_spipe, 0x21), +- HISI_PMU_EVENT_ATTR(rd_hit_spipe, 0x22), +- HISI_PMU_EVENT_ATTR(wr_hit_spipe, 0x23), +- HISI_PMU_EVENT_ATTR(back_invalid, 0x29), +- HISI_PMU_EVENT_ATTR(retry_cpu, 0x40), +- HISI_PMU_EVENT_ATTR(retry_ring, 0x41), +- HISI_PMU_EVENT_ATTR(prefetch_drop, 0x42), +- NULL, +-}; +- +-static const struct attribute_group hisi_l3t_pmu_events_group = { +- .name = "events", +- .attrs = hisi_l3t_pmu_events_attr, +-}; +- +-static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL); +- +-static struct attribute *hisi_l3t_pmu_cpumask_attrs[] = { +- &dev_attr_cpumask.attr, +- NULL, +-}; +- +-static const struct attribute_group hisi_l3t_pmu_cpumask_attr_group = { +- .attrs = hisi_l3t_pmu_cpumask_attrs, +-}; +- +-static const struct attribute_group *hisi_l3t_pmu_attr_groups[] = { +- &hisi_l3t_pmu_format_group, +- &hisi_l3t_pmu_events_group, +- &hisi_l3t_pmu_cpumask_attr_group, +- NULL, +-}; +- +-static const struct hisi_uncore_ops hisi_uncore_l3t_ops = { +- .write_evtype = hisi_l3t_pmu_write_evtype, +- .get_event_idx = hisi_uncore_pmu_get_event_idx, +- .start_counters = hisi_l3t_pmu_start_counters, +- .stop_counters = hisi_l3t_pmu_stop_counters, +- .enable_counter = hisi_l3t_pmu_enable_counter, +- .disable_counter = hisi_l3t_pmu_disable_counter, +- .enable_counter_int = hisi_l3t_pmu_enable_counter_int, +- .disable_counter_int = hisi_l3t_pmu_disable_counter_int, +- .write_counter = hisi_l3t_pmu_write_counter, +- .read_counter = hisi_l3t_pmu_read_counter, +-}; +- +-static int hisi_l3t_pmu_dev_probe(struct platform_device *pdev, +- struct hisi_pmu *l3t_pmu) +-{ +- int ret; +- +- ret = hisi_l3t_pmu_init_data(pdev, l3t_pmu); +- if (ret) +- return ret; +- +- ret = hisi_l3t_pmu_init_irq(l3t_pmu, pdev); +- if (ret) +- return ret; +- +- l3t_pmu->num_counters = L3T_NR_COUNTERS; +- l3t_pmu->counter_bits = 48; +- l3t_pmu->ops = &hisi_uncore_l3t_ops; +- l3t_pmu->dev = &pdev->dev; +- l3t_pmu->on_cpu = -1; +- l3t_pmu->check_event = 0x59; +- +- return 0; +-} +- +-static int hisi_l3t_pmu_probe(struct platform_device *pdev) +-{ +- struct hisi_pmu *l3t_pmu; +- char *name; +- int ret; +- +- l3t_pmu = devm_kzalloc(&pdev->dev, sizeof(*l3t_pmu), GFP_KERNEL); +- if (!l3t_pmu) +- return -ENOMEM; +- +- platform_set_drvdata(pdev, l3t_pmu); +- +- ret = hisi_l3t_pmu_dev_probe(pdev, l3t_pmu); +- if (ret) +- return ret; +- +- name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_l3t%u", +- l3t_pmu->sccl_id, l3t_pmu->index_id); +- HISI_INIT_PMU(&l3t_pmu->pmu, name, hisi_l3t_pmu_attr_groups); +- +- ret = perf_pmu_register(&l3t_pmu->pmu, name, -1); +- if (ret) { +- dev_err(l3t_pmu->dev, "L3T PMU register failed!\n"); +- return ret; +- } +- +- /* Pick one core to use for cpumask attributes */ +- cpumask_set_cpu(smp_processor_id(), &l3t_pmu->associated_cpus); +- +- l3t_pmu->on_cpu = cpumask_first(&l3t_pmu->associated_cpus); +- if (l3t_pmu->on_cpu >= nr_cpu_ids) +- return -EINVAL; +- +- return 0; +-} +- +-static int hisi_l3t_pmu_remove(struct platform_device *pdev) +-{ +- struct hisi_pmu *l3t_pmu = platform_get_drvdata(pdev); +- +- perf_pmu_unregister(&l3t_pmu->pmu); +- +- return 0; +-} +- +-static struct platform_driver hisi_l3t_pmu_driver = { +- .driver = { +- .name = "hisi_l3t_pmu", +- .of_match_table = of_match_ptr(l3t_of_match), +- }, +- .probe = hisi_l3t_pmu_probe, +- .remove = hisi_l3t_pmu_remove, +-}; +- +-static int __init hisi_l3t_pmu_module_init(void) +-{ +- return platform_driver_register(&hisi_l3t_pmu_driver); +-} +-module_init(hisi_l3t_pmu_module_init); +- +-static void __exit hisi_l3t_pmu_module_exit(void) +-{ +- platform_driver_unregister(&hisi_l3t_pmu_driver); +-} +-module_exit(hisi_l3t_pmu_module_exit); +- +-MODULE_DESCRIPTION("HiSilicon SoC L3T uncore PMU driver"); +-MODULE_LICENSE("GPL v2"); +-MODULE_AUTHOR("HUAWEI TECHNOLOGIES CO., LTD."); +-MODULE_AUTHOR("Fang Lijun "); +-- +2.27.0 + diff --git a/patches/0044-Revert-perf-hisi-Add-support-for-HiSilicon-SoC-LPDDR.patch b/patches/0044-Revert-perf-hisi-Add-support-for-HiSilicon-SoC-LPDDR.patch new file mode 100644 index 0000000..8473d66 --- /dev/null +++ b/patches/0044-Revert-perf-hisi-Add-support-for-HiSilicon-SoC-LPDDR.patch @@ -0,0 +1,469 @@ +From a42c8f603e8d0aa7d67023014604d919227581dd Mon Sep 17 00:00:00 2001 +From: hongrongxuan +Date: Wed, 25 Oct 2023 15:04:16 +0800 +Subject: [PATCH 03/55] Revert "perf: hisi: Add support for HiSilicon SoC + LPDDRC PMU driver" + +driver inclusion +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +------------------------------------------------------------- + +This reverts commit be4e2dae37269ece33d54f906323b00208a569b0. + +Now, revert it, then we will inclusion the newer version of LPDRRC PMU +driver. + +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/Makefile | 2 +- + .../perf/hisilicon/hisi_uncore_lpddrc_pmu.c | 429 ------------------ + 2 files changed, 1 insertion(+), 430 deletions(-) + delete mode 100644 drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c + +diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile +index 3651f18260e5..2621d51ae87a 100644 +--- a/drivers/perf/hisilicon/Makefile ++++ b/drivers/perf/hisilicon/Makefile +@@ -1 +1 @@ +-obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_lpddrc_pmu.o ++obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o +diff --git a/drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c +deleted file mode 100644 +index 8f8b211788e0..000000000000 +--- a/drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c ++++ /dev/null +@@ -1,429 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/* +- * HiSilicon SoC LPDDRC uncore Hardware event counters support +- * +- * Copyright (C) 2021 Hisilicon Limited +- * Author: Fang Lijun +- * Shaokun Zhang +- * Anurup M +- * +- * This code is based on the uncore PMUs like arm-cci and arm-ccn. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. +- */ +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "hisi_uncore_pmu.h" +- +-/* LPDDRC register definition */ +-#define LPDDRC_PERF_CTRL 0x4930 +-#define LPDDRC_FLUX_WR 0x4948 +-#define LPDDRC_FLUX_RD 0x494c +-#define LPDDRC_FLUX_WCMD 0x4950 +-#define LPDDRC_FLUX_RCMD 0x4954 +-#define LPDDRC_PRE_CMD 0x4984 +-#define LPDDRC_ACT_CMD 0x4988 +-#define LPDDRC_RNK_CHG 0x4990 +-#define LPDDRC_RW_CHG 0x4994 +-#define LPDDRC_EVENT_CTRL 0x4d60 +-#define LPDDRC_INT_MASK 0x6c8 +-#define LPDDRC_INT_STATUS 0x6cc +-#define LPDDRC_INT_CLEAR 0x6d0 +- +-/* LPDDRC has 8-counters */ +-#define LPDDRC_NR_COUNTERS 0x8 +-#define LPDDRC_PERF_CTRL_EN 0x1 +- +-/* +- * For LPDDRC PMU, there are eight-events and every event has been mapped +- * to fixed-purpose counters which register offset is not consistent. +- * Therefore there is no write event type and we assume that event +- * code (0 to 7) is equal to counter index in PMU driver. +- */ +-#define GET_LPDDRC_EVENTID(hwc) (hwc->config_base & 0x7) +- +-static const u32 lpddrc_reg_off[] = { +- LPDDRC_FLUX_WR, LPDDRC_FLUX_RD, LPDDRC_FLUX_WCMD, LPDDRC_FLUX_RCMD, +- LPDDRC_PRE_CMD, LPDDRC_ACT_CMD, LPDDRC_RNK_CHG, LPDDRC_RW_CHG +-}; +- +-/* +- * Select the counter register offset using the counter index. +- * In LPDDRC there are no programmable counter, the count +- * is readed form the statistics counter register itself. +- */ +-static u32 hisi_lpddrc_pmu_get_counter_offset(int cntr_idx) +-{ +- return lpddrc_reg_off[cntr_idx]; +-} +- +-static u64 hisi_lpddrc_pmu_read_counter(struct hisi_pmu *lpddrc_pmu, +- struct hw_perf_event *hwc) +-{ +- /* Use event code as counter index */ +- u32 idx = GET_LPDDRC_EVENTID(hwc); +- +- if (!hisi_uncore_pmu_counter_valid(lpddrc_pmu, idx)) { +- dev_err(lpddrc_pmu->dev, "Unsupported event index:%d!\n", idx); +- return 0; +- } +- +- return readl(lpddrc_pmu->base + hisi_lpddrc_pmu_get_counter_offset(idx)); +-} +- +-/* +- * For LPDDRC PMU, event counter should be reset when start counters, +- * reset the prev_count by software, because the counter register was RO. +- */ +-static void hisi_lpddrc_pmu_write_counter(struct hisi_pmu *lpddrc_pmu, +- struct hw_perf_event *hwc, u64 val) +-{ +- local64_set(&hwc->prev_count, 0); +-} +- +-/* +- * For LPDDRC PMU, event has been mapped to fixed-purpose counter by hardware, +- * so there is no need to write event type. +- */ +-static void hisi_lpddrc_pmu_write_evtype(struct hisi_pmu *hha_pmu, int idx, +- u32 type) +-{ +-} +- +-static void hisi_lpddrc_pmu_start_counters(struct hisi_pmu *lpddrc_pmu) +-{ +- u32 val; +- +- /* Set perf_enable in LPDDRC_PERF_CTRL to start event counting */ +- val = readl(lpddrc_pmu->base + LPDDRC_PERF_CTRL); +- val |= LPDDRC_PERF_CTRL_EN; +- writel(val, lpddrc_pmu->base + LPDDRC_PERF_CTRL); +-} +- +-static void hisi_lpddrc_pmu_stop_counters(struct hisi_pmu *lpddrc_pmu) +-{ +- u32 val; +- +- /* Clear perf_enable in LPDDRC_PERF_CTRL to stop event counting */ +- val = readl(lpddrc_pmu->base + LPDDRC_PERF_CTRL); +- val &= ~LPDDRC_PERF_CTRL_EN; +- writel(val, lpddrc_pmu->base + LPDDRC_PERF_CTRL); +-} +- +-static void hisi_lpddrc_pmu_enable_counter(struct hisi_pmu *lpddrc_pmu, +- struct hw_perf_event *hwc) +-{ +- u32 val; +- +- /* Set counter index(event code) in LPDDRC_EVENT_CTRL register */ +- val = readl(lpddrc_pmu->base + LPDDRC_EVENT_CTRL); +- val |= (1 << GET_LPDDRC_EVENTID(hwc)); +- writel(val, lpddrc_pmu->base + LPDDRC_EVENT_CTRL); +-} +- +-static void hisi_lpddrc_pmu_disable_counter(struct hisi_pmu *lpddrc_pmu, +- struct hw_perf_event *hwc) +-{ +- u32 val; +- +- /* Clear counter index(event code) in LPDDRC_EVENT_CTRL register */ +- val = readl(lpddrc_pmu->base + LPDDRC_EVENT_CTRL); +- val &= ~(1 << GET_LPDDRC_EVENTID(hwc)); +- writel(val, lpddrc_pmu->base + LPDDRC_EVENT_CTRL); +-} +- +-static int hisi_lpddrc_pmu_get_event_idx(struct perf_event *event) +-{ +- struct hisi_pmu *lpddrc_pmu = to_hisi_pmu(event->pmu); +- unsigned long *used_mask = lpddrc_pmu->pmu_events.used_mask; +- struct hw_perf_event *hwc = &event->hw; +- /* For LPDDRC PMU, we use event code as counter index */ +- int idx = GET_LPDDRC_EVENTID(hwc); +- +- if (test_bit(idx, used_mask)) +- return -EAGAIN; +- +- set_bit(idx, used_mask); +- +- return idx; +-} +- +-static void hisi_lpddrc_pmu_enable_counter_int(struct hisi_pmu *lpddrc_pmu, +- struct hw_perf_event *hwc) +-{ +- u32 val; +- +- /* Write 0 to enable interrupt */ +- val = readl(lpddrc_pmu->base + LPDDRC_INT_MASK); +- val &= ~(1 << GET_LPDDRC_EVENTID(hwc)); +- writel(val, lpddrc_pmu->base + LPDDRC_INT_MASK); +-} +- +-static void hisi_lpddrc_pmu_disable_counter_int(struct hisi_pmu *lpddrc_pmu, +- struct hw_perf_event *hwc) +-{ +- u32 val; +- +- /* Write 1 to mask interrupt */ +- val = readl(lpddrc_pmu->base + LPDDRC_INT_MASK); +- val |= (1 << GET_LPDDRC_EVENTID(hwc)); +- writel(val, lpddrc_pmu->base + LPDDRC_INT_MASK); +-} +- +-static irqreturn_t hisi_lpddrc_pmu_isr(int irq, void *dev_id) +-{ +- struct hisi_pmu *lpddrc_pmu = dev_id; +- struct perf_event *event; +- unsigned long overflown; +- int idx; +- +- /* Read the LPDDRC_INT_STATUS register */ +- overflown = readl(lpddrc_pmu->base + LPDDRC_INT_STATUS); +- if (!overflown) +- return IRQ_NONE; +- +- /* +- * Find the counter index which overflowed if the bit was set +- * and handle it +- */ +- for_each_set_bit(idx, &overflown, LPDDRC_NR_COUNTERS) { +- /* Write 1 to clear the IRQ status flag */ +- writel((1 << idx), lpddrc_pmu->base + LPDDRC_INT_CLEAR); +- +- /* Get the corresponding event struct */ +- event = lpddrc_pmu->pmu_events.hw_events[idx]; +- if (!event) +- continue; +- +- hisi_uncore_pmu_event_update(event); +- hisi_uncore_pmu_set_event_period(event); +- } +- +- return IRQ_HANDLED; +-} +- +-static int hisi_lpddrc_pmu_init_irq(struct hisi_pmu *lpddrc_pmu, +- struct platform_device *pdev) +-{ +- int irq, ret; +- +- /* Read and init IRQ */ +- irq = platform_get_irq(pdev, 0); +- if (irq < 0) { +- dev_err(&pdev->dev, "LPDDRC PMU get irq fail; irq:%d\n", irq); +- return irq; +- } +- +- ret = devm_request_irq(&pdev->dev, irq, hisi_lpddrc_pmu_isr, +- IRQF_NOBALANCING | IRQF_NO_THREAD | IRQF_SHARED, +- dev_name(&pdev->dev), lpddrc_pmu); +- if (ret < 0) { +- dev_err(&pdev->dev, +- "Fail to request IRQ:%d ret:%d\n", irq, ret); +- return ret; +- } +- +- lpddrc_pmu->irq = irq; +- +- return 0; +-} +- +-static const struct of_device_id lpddrc_of_match[] = { +- { .compatible = "hisilicon,lpddrc-pmu", }, +- {}, +-} +-MODULE_DEVICE_TABLE(of, lpddrc_of_match); +- +-static int hisi_lpddrc_pmu_init_data(struct platform_device *pdev, +- struct hisi_pmu *lpddrc_pmu) +-{ +- struct resource *res; +- +- /* +- * Use the SCCL_ID and LPDDRC channel ID to identify the +- * LPDDRC PMU, while SCCL_ID is in MPIDR[aff2]. +- */ +- if (device_property_read_u32(&pdev->dev, "hisilicon,ch-id", +- &lpddrc_pmu->index_id)) { +- dev_err(&pdev->dev, "Can not read lpddrc channel-id!\n"); +- return -EINVAL; +- } +- +- if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id", +- &lpddrc_pmu->sccl_id)) { +- dev_err(&pdev->dev, "Can not read lpddrc sccl-id!\n"); +- return -EINVAL; +- } +- /* LPDDRC PMUs only share the same SCCL */ +- lpddrc_pmu->ccl_id = -1; +- +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- lpddrc_pmu->base = devm_ioremap_resource(&pdev->dev, res); +- if (IS_ERR(lpddrc_pmu->base)) { +- dev_err(&pdev->dev, "ioremap failed for lpddrc_pmu resource\n"); +- return PTR_ERR(lpddrc_pmu->base); +- } +- +- return 0; +-} +- +-static struct attribute *hisi_lpddrc_pmu_format_attr[] = { +- HISI_PMU_FORMAT_ATTR(event, "config:0-4"), +- NULL, +-}; +- +-static const struct attribute_group hisi_lpddrc_pmu_format_group = { +- .name = "format", +- .attrs = hisi_lpddrc_pmu_format_attr, +-}; +- +-static struct attribute *hisi_lpddrc_pmu_events_attr[] = { +- HISI_PMU_EVENT_ATTR(flux_wr, 0x00), +- HISI_PMU_EVENT_ATTR(flux_rd, 0x01), +- HISI_PMU_EVENT_ATTR(flux_wcmd, 0x02), +- HISI_PMU_EVENT_ATTR(flux_rcmd, 0x03), +- HISI_PMU_EVENT_ATTR(pre_cmd, 0x04), +- HISI_PMU_EVENT_ATTR(act_cmd, 0x05), +- HISI_PMU_EVENT_ATTR(rnk_chg, 0x06), +- HISI_PMU_EVENT_ATTR(rw_chg, 0x07), +- NULL, +-}; +- +-static const struct attribute_group hisi_lpddrc_pmu_events_group = { +- .name = "events", +- .attrs = hisi_lpddrc_pmu_events_attr, +-}; +- +-static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL); +- +-static struct attribute *hisi_lpddrc_pmu_cpumask_attrs[] = { +- &dev_attr_cpumask.attr, +- NULL, +-}; +- +-static const struct attribute_group hisi_lpddrc_pmu_cpumask_attr_group = { +- .attrs = hisi_lpddrc_pmu_cpumask_attrs, +-}; +- +-static const struct attribute_group *hisi_lpddrc_pmu_attr_groups[] = { +- &hisi_lpddrc_pmu_format_group, +- &hisi_lpddrc_pmu_events_group, +- &hisi_lpddrc_pmu_cpumask_attr_group, +- NULL, +-}; +- +-static const struct hisi_uncore_ops hisi_uncore_lpddrc_ops = { +- .write_evtype = hisi_lpddrc_pmu_write_evtype, +- .get_event_idx = hisi_lpddrc_pmu_get_event_idx, +- .start_counters = hisi_lpddrc_pmu_start_counters, +- .stop_counters = hisi_lpddrc_pmu_stop_counters, +- .enable_counter = hisi_lpddrc_pmu_enable_counter, +- .disable_counter = hisi_lpddrc_pmu_disable_counter, +- .enable_counter_int = hisi_lpddrc_pmu_enable_counter_int, +- .disable_counter_int = hisi_lpddrc_pmu_disable_counter_int, +- .write_counter = hisi_lpddrc_pmu_write_counter, +- .read_counter = hisi_lpddrc_pmu_read_counter, +-}; +- +-static int hisi_lpddrc_pmu_dev_probe(struct platform_device *pdev, +- struct hisi_pmu *lpddrc_pmu) +-{ +- int ret; +- +- ret = hisi_lpddrc_pmu_init_data(pdev, lpddrc_pmu); +- if (ret) +- return ret; +- +- ret = hisi_lpddrc_pmu_init_irq(lpddrc_pmu, pdev); +- if (ret) +- return ret; +- +- lpddrc_pmu->num_counters = LPDDRC_NR_COUNTERS; +- lpddrc_pmu->counter_bits = 32; +- lpddrc_pmu->ops = &hisi_uncore_lpddrc_ops; +- lpddrc_pmu->dev = &pdev->dev; +- lpddrc_pmu->on_cpu = -1; +- lpddrc_pmu->check_event = 7; +- +- return 0; +-} +- +-static int hisi_lpddrc_pmu_probe(struct platform_device *pdev) +-{ +- struct hisi_pmu *lpddrc_pmu; +- char *name; +- int ret; +- +- lpddrc_pmu = devm_kzalloc(&pdev->dev, sizeof(*lpddrc_pmu), GFP_KERNEL); +- if (!lpddrc_pmu) +- return -ENOMEM; +- +- platform_set_drvdata(pdev, lpddrc_pmu); +- +- ret = hisi_lpddrc_pmu_dev_probe(pdev, lpddrc_pmu); +- if (ret) +- return ret; +- +- name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_lpddrc%u", +- lpddrc_pmu->sccl_id, lpddrc_pmu->index_id); +- HISI_INIT_PMU(&lpddrc_pmu->pmu, name, hisi_lpddrc_pmu_attr_groups); +- ret = perf_pmu_register(&lpddrc_pmu->pmu, name, -1); +- if (ret) { +- dev_err(lpddrc_pmu->dev, "LPDDRC PMU register failed!\n"); +- return ret; +- } +- +- /* Pick one core to use for cpumask attributes */ +- cpumask_set_cpu(smp_processor_id(), &lpddrc_pmu->associated_cpus); +- +- lpddrc_pmu->on_cpu = cpumask_first(&lpddrc_pmu->associated_cpus); +- if (lpddrc_pmu->on_cpu >= nr_cpu_ids) +- return -EINVAL; +- +- return 0; +-} +- +-static int hisi_lpddrc_pmu_remove(struct platform_device *pdev) +-{ +- struct hisi_pmu *lpddrc_pmu = platform_get_drvdata(pdev); +- +- perf_pmu_unregister(&lpddrc_pmu->pmu); +- +- return 0; +-} +- +-static struct platform_driver hisi_lpddrc_pmu_driver = { +- .driver = { +- .name = "hisi_lpddrc_pmu", +- .of_match_table = lpddrc_of_match, +- }, +- .probe = hisi_lpddrc_pmu_probe, +- .remove = hisi_lpddrc_pmu_remove, +-}; +- +-static int __init hisi_lpddrc_pmu_module_init(void) +-{ +- return platform_driver_register(&hisi_lpddrc_pmu_driver); +-} +-module_init(hisi_lpddrc_pmu_module_init); +- +-static void __exit hisi_lpddrc_pmu_module_exit(void) +-{ +- platform_driver_unregister(&hisi_lpddrc_pmu_driver); +-} +-module_exit(hisi_lpddrc_pmu_module_exit); +- +-MODULE_DESCRIPTION("HiSilicon SoC LPDDRC uncore PMU driver"); +-MODULE_LICENSE("GPL v2"); +-MODULE_AUTHOR("Fang Lijun "); +-MODULE_AUTHOR("HUAWEI TECHNOLOGIES CO., LTD."); +-- +2.27.0 + diff --git a/patches/0045-Revert-perf-hisi-Add-support-for-HiSilicon-SoC-PMU-d.patch b/patches/0045-Revert-perf-hisi-Add-support-for-HiSilicon-SoC-PMU-d.patch new file mode 100644 index 0000000..38e1d8c --- /dev/null +++ b/patches/0045-Revert-perf-hisi-Add-support-for-HiSilicon-SoC-PMU-d.patch @@ -0,0 +1,142 @@ +From 368cbff964ef136c493a3f06b88ff7e35454073d Mon Sep 17 00:00:00 2001 +From: hongrongxuan +Date: Wed, 25 Oct 2023 15:21:52 +0800 +Subject: [PATCH 04/55] Revert "perf: hisi: Add support for HiSilicon SoC PMU + driver dt probe" + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +----------------------------------------------------------------- + +This reverts commit 31067ca7ca856eee32857bdc618e89d3b9a3261a. + +In newer version of PMU drivers that we will inclusion them later, +the acpi_evaluate_integer was removed, so this problem is gone. + +Signed-off-by: hongrongxuan + + Conflicts: + drivers/perf/Kconfig +--- + drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 1 - + drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 23 ++++--------------- + drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 20 +++------------- + 3 files changed, 7 insertions(+), 37 deletions(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +index 8d1c48bc9812..f2a144ba3724 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +@@ -17,7 +17,6 @@ + #include + #include + #include +-#include + #include + #include + +diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +index 52286739c8b9..540f664463a8 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +@@ -17,7 +17,6 @@ + #include + #include + #include +-#include + #include + #include + +@@ -236,34 +235,20 @@ static const struct acpi_device_id hisi_hha_pmu_acpi_match[] = { + }; + MODULE_DEVICE_TABLE(acpi, hisi_hha_pmu_acpi_match); + +-#ifdef CONFIG_ACPI +-static int hisi_hha_pmu_init_index(struct platform_device *pdev, ++static int hisi_hha_pmu_init_data(struct platform_device *pdev, + struct hisi_pmu *hha_pmu) + { +- acpi_status status; + unsigned long long id; ++ struct resource *res; ++ acpi_status status; + + status = acpi_evaluate_integer(ACPI_HANDLE(&pdev->dev), +- "_UID", NULL, &id); ++ "_UID", NULL, &id); + if (ACPI_FAILURE(status)) + return -EINVAL; + + hha_pmu->index_id = id; + +- return 0; +-} +-#endif +- +-static int hisi_hha_pmu_init_data(struct platform_device *pdev, +- struct hisi_pmu *hha_pmu) +-{ +- struct resource *res; +- +-#ifdef CONFIG_ACPI +- if (hisi_hha_pmu_init_index(pdev, hha_pmu)) +- dev_info(&pdev->dev, "Can not init index id by acpi!\n"); +-#endif +- + /* + * Use SCCL_ID and UID to identify the HHA PMU, while + * SCCL_ID is in MPIDR[aff2]. +diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +index 0e766cea4a11..117edd114445 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +@@ -17,7 +17,6 @@ + #include + #include + #include +-#include + #include + #include + +@@ -235,33 +234,20 @@ static const struct acpi_device_id hisi_l3c_pmu_acpi_match[] = { + }; + MODULE_DEVICE_TABLE(acpi, hisi_l3c_pmu_acpi_match); + +-#ifdef CONFIG_ACPI +-static int hisi_l3c_pmu_init_index(struct platform_device *pdev, ++static int hisi_l3c_pmu_init_data(struct platform_device *pdev, + struct hisi_pmu *l3c_pmu) + { + unsigned long long id; ++ struct resource *res; + acpi_status status; + + status = acpi_evaluate_integer(ACPI_HANDLE(&pdev->dev), +- "_UID", NULL, &id); ++ "_UID", NULL, &id); + if (ACPI_FAILURE(status)) + return -EINVAL; + + l3c_pmu->index_id = id; + +- return 0; +-} +-#endif +- +-static int hisi_l3c_pmu_init_data(struct platform_device *pdev, +- struct hisi_pmu *l3c_pmu) +-{ +- struct resource *res; +- +-#ifdef CONFIG_ACPI +- if (hisi_l3c_pmu_init_index(pdev, l3c_pmu)) +- dev_info(&pdev->dev, "Can not init index id by acpi!"); +-#endif + /* + * Use the SCCL_ID and CCL_ID to identify the L3C PMU, while + * SCCL_ID is in MPIDR[aff2] and CCL_ID is in MPIDR[aff1]. +-- +2.27.0 + diff --git a/patches/0046-Revert-drivers-perf-Fix-kernel-panic-when-rmmod-PMU-.patch b/patches/0046-Revert-drivers-perf-Fix-kernel-panic-when-rmmod-PMU-.patch new file mode 100644 index 0000000..4d365cf --- /dev/null +++ b/patches/0046-Revert-drivers-perf-Fix-kernel-panic-when-rmmod-PMU-.patch @@ -0,0 +1,36 @@ +From 05df62b6b7f9e92e9f25b8a0bcd5c99c4ae02165 Mon Sep 17 00:00:00 2001 +From: hongrongxuan +Date: Wed, 25 Oct 2023 15:26:10 +0800 +Subject: [PATCH 05/55] Revert "drivers/perf: Fix kernel panic when rmmod PMU + modules during perf sampling" + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +-------------------------------------------------------------- + +This reverts commit 525a3927062f89be41f1b23ae33ad0638c13bf8e. + +revert it, and inclusion the upstream version later. + +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_pmu.h | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h +index 129896662cf2..8445ee581e46 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h +@@ -105,7 +105,6 @@ static inline void HISI_INIT_PMU(struct pmu *pmu, const char *name, + const struct attribute_group **attr_groups) + { + pmu->name = name; +- pmu->module = THIS_MODULE; + pmu->task_ctx_nr = perf_invalid_context; + pmu->event_init = hisi_uncore_pmu_event_init; + pmu->pmu_enable = hisi_uncore_pmu_enable; +-- +2.27.0 + diff --git a/patches/0047-Revert-perf-hisi-remove-duplicated-code.patch b/patches/0047-Revert-perf-hisi-remove-duplicated-code.patch new file mode 100644 index 0000000..f3a607e --- /dev/null +++ b/patches/0047-Revert-perf-hisi-remove-duplicated-code.patch @@ -0,0 +1,129 @@ +From 41ea05f9ac69e7cbae775862e5c3e0dad2e1e4ca Mon Sep 17 00:00:00 2001 +From: hongrongxuan +Date: Wed, 25 Oct 2023 15:26:31 +0800 +Subject: [PATCH 06/55] Revert "perf: hisi: remove duplicated code" + +driver inclusion +category: cleanup +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +---------------------------------------------------------- + +This reverts commit de1ea4e7f5209c7f84965c38bf37287c11db02dc. + +revert it, and inclusion the newer version of commit c38992d67c15(perf: hisi: Extract hisi_pmu_init) later. + +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 15 ++++++++++++++- + drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 15 ++++++++++++++- + drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 14 +++++++++++++- + drivers/perf/hisilicon/hisi_uncore_pmu.h | 17 ----------------- + 4 files changed, 41 insertions(+), 20 deletions(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +index f2a144ba3724..b3488ae1f2b8 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +@@ -384,7 +384,20 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev) + + name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_ddrc%u", + ddrc_pmu->sccl_id, ddrc_pmu->index_id); +- HISI_INIT_PMU(&ddrc_pmu->pmu, name, hisi_ddrc_pmu_attr_groups); ++ ddrc_pmu->pmu = (struct pmu) { ++ .name = name, ++ .task_ctx_nr = perf_invalid_context, ++ .event_init = hisi_uncore_pmu_event_init, ++ .pmu_enable = hisi_uncore_pmu_enable, ++ .pmu_disable = hisi_uncore_pmu_disable, ++ .add = hisi_uncore_pmu_add, ++ .del = hisi_uncore_pmu_del, ++ .start = hisi_uncore_pmu_start, ++ .stop = hisi_uncore_pmu_stop, ++ .read = hisi_uncore_pmu_read, ++ .attr_groups = hisi_ddrc_pmu_attr_groups, ++ }; ++ + ret = perf_pmu_register(&ddrc_pmu->pmu, name, -1); + if (ret) { + dev_err(ddrc_pmu->dev, "DDRC PMU register failed!\n"); +diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +index 540f664463a8..f0215d50d84d 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +@@ -395,7 +395,20 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev) + + name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_hha%u", + hha_pmu->sccl_id, hha_pmu->index_id); +- HISI_INIT_PMU(&hha_pmu->pmu, name, hisi_hha_pmu_attr_groups); ++ hha_pmu->pmu = (struct pmu) { ++ .name = name, ++ .task_ctx_nr = perf_invalid_context, ++ .event_init = hisi_uncore_pmu_event_init, ++ .pmu_enable = hisi_uncore_pmu_enable, ++ .pmu_disable = hisi_uncore_pmu_disable, ++ .add = hisi_uncore_pmu_add, ++ .del = hisi_uncore_pmu_del, ++ .start = hisi_uncore_pmu_start, ++ .stop = hisi_uncore_pmu_stop, ++ .read = hisi_uncore_pmu_read, ++ .attr_groups = hisi_hha_pmu_attr_groups, ++ }; ++ + ret = perf_pmu_register(&hha_pmu->pmu, name, -1); + if (ret) { + dev_err(hha_pmu->dev, "HHA PMU register failed!\n"); +diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +index 117edd114445..11563e29d983 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +@@ -385,7 +385,19 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev) + + name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_l3c%u", + l3c_pmu->sccl_id, l3c_pmu->index_id); +- HISI_INIT_PMU(&l3c_pmu->pmu, name, hisi_l3c_pmu_attr_groups); ++ l3c_pmu->pmu = (struct pmu) { ++ .name = name, ++ .task_ctx_nr = perf_invalid_context, ++ .event_init = hisi_uncore_pmu_event_init, ++ .pmu_enable = hisi_uncore_pmu_enable, ++ .pmu_disable = hisi_uncore_pmu_disable, ++ .add = hisi_uncore_pmu_add, ++ .del = hisi_uncore_pmu_del, ++ .start = hisi_uncore_pmu_start, ++ .stop = hisi_uncore_pmu_stop, ++ .read = hisi_uncore_pmu_read, ++ .attr_groups = hisi_l3c_pmu_attr_groups, ++ }; + + ret = perf_pmu_register(&l3c_pmu->pmu, name, -1); + if (ret) { +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h +index 8445ee581e46..8f2f2fc5dde4 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h +@@ -100,21 +100,4 @@ ssize_t hisi_cpumask_sysfs_show(struct device *dev, + struct device_attribute *attr, char *buf); + int hisi_uncore_pmu_online_cpu(unsigned int cpu, struct hlist_node *node); + int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node); +- +-static inline void HISI_INIT_PMU(struct pmu *pmu, const char *name, +- const struct attribute_group **attr_groups) +-{ +- pmu->name = name; +- pmu->task_ctx_nr = perf_invalid_context; +- pmu->event_init = hisi_uncore_pmu_event_init; +- pmu->pmu_enable = hisi_uncore_pmu_enable; +- pmu->pmu_disable = hisi_uncore_pmu_disable; +- pmu->add = hisi_uncore_pmu_add; +- pmu->del = hisi_uncore_pmu_del; +- pmu->start = hisi_uncore_pmu_start; +- pmu->stop = hisi_uncore_pmu_stop; +- pmu->read = hisi_uncore_pmu_read; +- pmu->attr_groups = attr_groups; +-} +- + #endif /* __HISI_UNCORE_PMU_H__ */ +-- +2.27.0 + diff --git a/patches/0048-docs-perf-convert-to-ReST.patch b/patches/0048-docs-perf-convert-to-ReST.patch new file mode 100644 index 0000000..90ee59e --- /dev/null +++ b/patches/0048-docs-perf-convert-to-ReST.patch @@ -0,0 +1,315 @@ +From 926642e8644c860c77141b8251767e1485c6427c Mon Sep 17 00:00:00 2001 +From: Mauro Carvalho Chehab +Date: Thu, 18 Apr 2019 17:35:40 -0300 +Subject: [PATCH 07/55] docs: perf: convert to ReST + +mainline inclusion +from mainline-v5.3-rc1 +commit 6baec31591cee0f2f6d446abb81c828499a6ed23 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6baec31591cee0f2f6d446abb81c828499a6ed23 + +--------------------------------------------------------------------- + +Rename the perf documentation files to ReST, add an +index for them and adjust in order to produce a nice html +output via the Sphinx build system. + +At its new index.rst, let's add a :orphan: while this is not linked to +the main index.rst file, in order to avoid build warnings. + +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: hongrongxuan +--- + .../perf/{arm-ccn.txt => arm-ccn.rst} | 18 +++++---- + .../perf/{arm_dsu_pmu.txt => arm_dsu_pmu.rst} | 5 ++- + .../perf/{hisi-pmu.txt => hisi-pmu.rst} | 37 +++++++++++-------- + Documentation/perf/index.rst | 16 ++++++++ + .../perf/{qcom_l2_pmu.txt => qcom_l2_pmu.rst} | 3 +- + .../perf/{qcom_l3_pmu.txt => qcom_l3_pmu.rst} | 3 +- + .../perf/{xgene-pmu.txt => xgene-pmu.rst} | 3 +- + MAINTAINERS | 4 +- + drivers/perf/qcom_l3_pmu.c | 2 +- + 9 files changed, 60 insertions(+), 31 deletions(-) + rename Documentation/perf/{arm-ccn.txt => arm-ccn.rst} (86%) + rename Documentation/perf/{arm_dsu_pmu.txt => arm_dsu_pmu.rst} (92%) + rename Documentation/perf/{hisi-pmu.txt => hisi-pmu.rst} (73%) + create mode 100644 Documentation/perf/index.rst + rename Documentation/perf/{qcom_l2_pmu.txt => qcom_l2_pmu.rst} (94%) + rename Documentation/perf/{qcom_l3_pmu.txt => qcom_l3_pmu.rst} (93%) + rename Documentation/perf/{xgene-pmu.txt => xgene-pmu.rst} (96%) + +diff --git a/Documentation/perf/arm-ccn.txt b/Documentation/perf/arm-ccn.rst +similarity index 86% +rename from Documentation/perf/arm-ccn.txt +rename to Documentation/perf/arm-ccn.rst +index 15cdb7bc57c3..832b0c64023a 100644 +--- a/Documentation/perf/arm-ccn.txt ++++ b/Documentation/perf/arm-ccn.rst +@@ -1,3 +1,4 @@ ++========================== + ARM Cache Coherent Network + ========================== + +@@ -29,6 +30,7 @@ Crosspoint watchpoint-based events (special "event" value 0xfe) + require "xp" and "vc" as as above plus "port" (device port index), + "dir" (transmit/receive direction), comparator values ("cmp_l" + and "cmp_h") and "mask", being index of the comparator mask. ++ + Masks are defined separately from the event description + (due to limited number of the config values) in the "cmp_mask" + directory, with first 8 configurable by user and additional +@@ -44,16 +46,16 @@ request the events on this processor (if not, the perf_event->cpu value + will be overwritten anyway). In case of this processor being offlined, + the events are migrated to another one and the attribute is updated. + +-Example of perf tool use: ++Example of perf tool use:: + +-/ # perf list | grep ccn +- ccn/cycles/ [Kernel PMU event] +-<...> +- ccn/xp_valid_flit,xp=?,port=?,vc=?,dir=?/ [Kernel PMU event] +-<...> ++ / # perf list | grep ccn ++ ccn/cycles/ [Kernel PMU event] ++ <...> ++ ccn/xp_valid_flit,xp=?,port=?,vc=?,dir=?/ [Kernel PMU event] ++ <...> + +-/ # perf stat -a -e ccn/cycles/,ccn/xp_valid_flit,xp=1,port=0,vc=1,dir=1/ \ +- sleep 1 ++ / # perf stat -a -e ccn/cycles/,ccn/xp_valid_flit,xp=1,port=0,vc=1,dir=1/ \ ++ sleep 1 + + The driver does not support sampling, therefore "perf record" will + not work. Per-task (without "-a") perf sessions are not supported. +diff --git a/Documentation/perf/arm_dsu_pmu.txt b/Documentation/perf/arm_dsu_pmu.rst +similarity index 92% +rename from Documentation/perf/arm_dsu_pmu.txt +rename to Documentation/perf/arm_dsu_pmu.rst +index d611e15f5add..7fd34db75d13 100644 +--- a/Documentation/perf/arm_dsu_pmu.txt ++++ b/Documentation/perf/arm_dsu_pmu.rst +@@ -1,3 +1,4 @@ ++================================== + ARM DynamIQ Shared Unit (DSU) PMU + ================================== + +@@ -13,7 +14,7 @@ PMU doesn't support process specific events and cannot be used in sampling mode. + The DSU provides a bitmap for a subset of implemented events via hardware + registers. There is no way for the driver to determine if the other events + are available or not. Hence the driver exposes only those events advertised +-by the DSU, in "events" directory under : ++by the DSU, in "events" directory under:: + + /sys/bus/event_sources/devices/arm_dsu_/ + +@@ -23,6 +24,6 @@ and use the raw event code for the unlisted events. + The driver also exposes the CPUs connected to the DSU instance in "associated_cpus". + + +-e.g usage : ++e.g usage:: + + perf stat -a -e arm_dsu_0/cycles/ +diff --git a/Documentation/perf/hisi-pmu.txt b/Documentation/perf/hisi-pmu.rst +similarity index 73% +rename from Documentation/perf/hisi-pmu.txt +rename to Documentation/perf/hisi-pmu.rst +index 267a028b2741..404a5c3d9d00 100644 +--- a/Documentation/perf/hisi-pmu.txt ++++ b/Documentation/perf/hisi-pmu.rst +@@ -1,5 +1,7 @@ ++====================================================== + HiSilicon SoC uncore Performance Monitoring Unit (PMU) + ====================================================== ++ + The HiSilicon SoC chip includes various independent system device PMUs + such as L3 cache (L3C), Hydra Home Agent (HHA) and DDRC. These PMUs are + independent and have hardware logic to gather statistics and performance +@@ -11,11 +13,13 @@ called Super CPU cluster (SCCL) and is made up of 6 CCLs. Each SCCL has + two HHAs (0 - 1) and four DDRCs (0 - 3), respectively. + + HiSilicon SoC uncore PMU driver +---------------------------------------- ++------------------------------- ++ + Each device PMU has separate registers for event counting, control and + interrupt, and the PMU driver shall register perf PMU drivers like L3C, + HHA and DDRC etc. The available events and configuration options shall +-be described in the sysfs, see : ++be described in the sysfs, see: ++ + /sys/devices/hisi_sccl{X}_/, or + /sys/bus/event_source/devices/hisi_sccl{X}_. + The "perf list" command shall list the available events from sysfs. +@@ -24,27 +28,30 @@ Each L3C, HHA and DDRC is registered as a separate PMU with perf. The PMU + name will appear in event listing as hisi_sccl_module. + where "sccl-id" is the identifier of the SCCL and "index-id" is the index of + module. ++ + e.g. hisi_sccl3_l3c0/rd_hit_cpipe is READ_HIT_CPIPE event of L3C index #0 in + SCCL ID #3. ++ + e.g. hisi_sccl1_hha0/rx_operations is RX_OPERATIONS event of HHA index #0 in + SCCL ID #1. + + The driver also provides a "cpumask" sysfs attribute, which shows the CPU core + ID used to count the uncore PMU event. + +-Example usage of perf: +-$# perf list +-hisi_sccl3_l3c0/rd_hit_cpipe/ [kernel PMU event] +------------------------------------------- +-hisi_sccl3_l3c0/wr_hit_cpipe/ [kernel PMU event] +------------------------------------------- +-hisi_sccl1_l3c0/rd_hit_cpipe/ [kernel PMU event] +------------------------------------------- +-hisi_sccl1_l3c0/wr_hit_cpipe/ [kernel PMU event] +------------------------------------------- +- +-$# perf stat -a -e hisi_sccl3_l3c0/rd_hit_cpipe/ sleep 5 +-$# perf stat -a -e hisi_sccl3_l3c0/config=0x02/ sleep 5 ++Example usage of perf:: ++ ++ $# perf list ++ hisi_sccl3_l3c0/rd_hit_cpipe/ [kernel PMU event] ++ ------------------------------------------ ++ hisi_sccl3_l3c0/wr_hit_cpipe/ [kernel PMU event] ++ ------------------------------------------ ++ hisi_sccl1_l3c0/rd_hit_cpipe/ [kernel PMU event] ++ ------------------------------------------ ++ hisi_sccl1_l3c0/wr_hit_cpipe/ [kernel PMU event] ++ ------------------------------------------ ++ ++ $# perf stat -a -e hisi_sccl3_l3c0/rd_hit_cpipe/ sleep 5 ++ $# perf stat -a -e hisi_sccl3_l3c0/config=0x02/ sleep 5 + + The current driver does not support sampling. So "perf record" is unsupported. + Also attach to a task is unsupported as the events are all uncore. +diff --git a/Documentation/perf/index.rst b/Documentation/perf/index.rst +new file mode 100644 +index 000000000000..4bf848e27f26 +--- /dev/null ++++ b/Documentation/perf/index.rst +@@ -0,0 +1,16 @@ ++:orphan: ++ ++=========================== ++Performance monitor support ++=========================== ++ ++.. toctree:: ++ :maxdepth: 1 ++ ++ hisi-pmu ++ qcom_l2_pmu ++ qcom_l3_pmu ++ arm-ccn ++ xgene-pmu ++ arm_dsu_pmu ++ thunderx2-pmu +diff --git a/Documentation/perf/qcom_l2_pmu.txt b/Documentation/perf/qcom_l2_pmu.rst +similarity index 94% +rename from Documentation/perf/qcom_l2_pmu.txt +rename to Documentation/perf/qcom_l2_pmu.rst +index b25b97659ab9..c130178a4a55 100644 +--- a/Documentation/perf/qcom_l2_pmu.txt ++++ b/Documentation/perf/qcom_l2_pmu.rst +@@ -1,3 +1,4 @@ ++===================================================================== + Qualcomm Technologies Level-2 Cache Performance Monitoring Unit (PMU) + ===================================================================== + +@@ -28,7 +29,7 @@ The driver provides a "cpumask" sysfs attribute which contains a mask + consisting of one CPU per cluster which will be used to handle all the PMU + events on that cluster. + +-Examples for use with perf: ++Examples for use with perf:: + + perf stat -e l2cache_0/config=0x001/,l2cache_0/config=0x042/ -a sleep 1 + +diff --git a/Documentation/perf/qcom_l3_pmu.txt b/Documentation/perf/qcom_l3_pmu.rst +similarity index 93% +rename from Documentation/perf/qcom_l3_pmu.txt +rename to Documentation/perf/qcom_l3_pmu.rst +index 96b3a9444a0d..a3d014a46bfd 100644 +--- a/Documentation/perf/qcom_l3_pmu.txt ++++ b/Documentation/perf/qcom_l3_pmu.rst +@@ -1,3 +1,4 @@ ++=========================================================================== + Qualcomm Datacenter Technologies L3 Cache Performance Monitoring Unit (PMU) + =========================================================================== + +@@ -17,7 +18,7 @@ The hardware implements 32bit event counters and has a flat 8bit event space + exposed via the "event" format attribute. In addition to the 32bit physical + counters the driver supports virtual 64bit hardware counters by using hardware + counter chaining. This feature is exposed via the "lc" (long counter) format +-flag. E.g.: ++flag. E.g.:: + + perf stat -e l3cache_0_0/read-miss,lc/ + +diff --git a/Documentation/perf/xgene-pmu.txt b/Documentation/perf/xgene-pmu.rst +similarity index 96% +rename from Documentation/perf/xgene-pmu.txt +rename to Documentation/perf/xgene-pmu.rst +index d7cff4454e5b..644f8ed89152 100644 +--- a/Documentation/perf/xgene-pmu.txt ++++ b/Documentation/perf/xgene-pmu.rst +@@ -1,3 +1,4 @@ ++================================================ + APM X-Gene SoC Performance Monitoring Unit (PMU) + ================================================ + +@@ -33,7 +34,7 @@ each PMU, please refer to APM X-Gene User Manual. + Each perf driver also provides a "cpumask" sysfs attribute, which contains a + single CPU ID of the processor which will be used to handle all the PMU events. + +-Example for perf tool use: ++Example for perf tool use:: + + / # perf list | grep -e l3c -e iob -e mcb -e mc + l3c0/ackq-full/ [Kernel PMU event] +diff --git a/MAINTAINERS b/MAINTAINERS +index 5d0b782c973c..0b2a68401b0e 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -1040,7 +1040,7 @@ APPLIED MICRO (APM) X-GENE SOC PMU + M: Tai Nguyen + S: Supported + F: drivers/perf/xgene_pmu.c +-F: Documentation/perf/xgene-pmu.txt ++F: Documentation/perf/xgene-pmu.rst + F: Documentation/devicetree/bindings/perf/apm-xgene-pmu.txt + + APTINA CAMERA SENSOR PLL +@@ -6663,7 +6663,7 @@ M: Shaokun Zhang + W: http://www.hisilicon.com + S: Supported + F: drivers/perf/hisilicon +-F: Documentation/perf/hisi-pmu.txt ++F: Documentation/perf/hisi-pmu.rst + + HISILICON PTT DRIVER + M: Yicong Yang +diff --git a/drivers/perf/qcom_l3_pmu.c b/drivers/perf/qcom_l3_pmu.c +index b349e7bf4dd9..cc88dc92577e 100644 +--- a/drivers/perf/qcom_l3_pmu.c ++++ b/drivers/perf/qcom_l3_pmu.c +@@ -7,7 +7,7 @@ + * the slices. User space needs to aggregate to individual counts to provide + * a global picture. + * +- * See Documentation/perf/qcom_l3_pmu.txt for more details. ++ * See Documentation/perf/qcom_l3_pmu.rst for more details. + * + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * +-- +2.27.0 + diff --git a/patches/0049-drivers-perf-Fix-kernel-panic-when-rmmod-PMU-modules.patch b/patches/0049-drivers-perf-Fix-kernel-panic-when-rmmod-PMU-modules.patch new file mode 100644 index 0000000..bed37d1 --- /dev/null +++ b/patches/0049-drivers-perf-Fix-kernel-panic-when-rmmod-PMU-modules.patch @@ -0,0 +1,113 @@ +From 7901f6e0c3c188badd67a49ba546df8da2f0a123 Mon Sep 17 00:00:00 2001 +From: Qi Liu +Date: Thu, 16 Jul 2020 17:19:25 +0800 +Subject: [PATCH 08/55] drivers/perf: Fix kernel panic when rmmod PMU modules + during perf sampling + +mainline inclusion +from mainline-v5.8-rc1 +commit bdc5c744c7b6457d18a95c26769dad0e7f480a08 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bdc5c744c7b6457d18a95c26769dad0e7f480a08 + +---------------------------------------------------------------------- + +When users try to remove PMU modules during perf sampling, kernel panic +will happen because the pmu->read() is a NULL pointer here. + +INFO on HiSilicon hip08 platform as follow: +pc : hisi_uncore_pmu_event_update+0x30/0xa4 [hisi_uncore_pmu] +lr : hisi_uncore_pmu_read+0x20/0x2c [hisi_uncore_pmu] +sp : ffff800010103e90 +x29: ffff800010103e90 x28: ffff0027db0c0e40 +x27: ffffa29a76f129d8 x26: ffffa29a77ceb000 +x25: ffffa29a773a5000 x24: ffffa29a77392000 +x23: ffffddffe5943f08 x22: ffff002784285960 +x21: ffff002784285800 x20: ffff0027d2e76c80 +x19: ffff0027842859e0 x18: ffff80003498bcc8 +x17: ffffa29a76afe910 x16: ffffa29a7583f530 +x15: 16151a1512061a1e x14: 0000000000000000 +x13: ffffa29a76f1e238 x12: 0000000000000001 +x11: 0000000000000400 x10: 00000000000009f0 +x9 : ffff8000107b3e70 x8 : ffff0027db0c1890 +x7 : ffffa29a773a7000 x6 : 00000007f5131013 +x5 : 00000007f5131013 x4 : 09f257d417c00000 +x3 : 00000002187bd7ce x2 : ffffa29a38f0f0d8 +x1 : ffffa29a38eae268 x0 : ffff0027d2e76c80 +Call trace: +hisi_uncore_pmu_event_update+0x30/0xa4 [hisi_uncore_pmu] +hisi_uncore_pmu_read+0x20/0x2c [hisi_uncore_pmu] +__perf_event_read+0x1a0/0x1f8 +flush_smp_call_function_queue+0xa0/0x160 +generic_smp_call_function_single_interrupt+0x18/0x20 +handle_IPI+0x31c/0x4dc +gic_handle_irq+0x2c8/0x310 +el1_irq+0xcc/0x180 +arch_cpu_idle+0x4c/0x20c +default_idle_call+0x20/0x30 +do_idle+0x1b4/0x270 +cpu_startup_entry+0x28/0x30 +secondary_start_kernel+0x1a4/0x1fc + +To solve the above issue, current module should be registered to kernel, +so that try_module_get() can be invoked when perf sampling starts. This +adds the reference counting of module and could prevent users from removing +modules during sampling. + +Reported-by: Haifeng Wang +Signed-off-by: Qi Liu +Reviewed-by: John Garry +Link: https://lore.kernel.org/r/1594891165-8228-1-git-send-email-liuqi115@huawei.com +Signed-off-by: Will Deacon +Signed-off-by: hongrongxuan + + Conflicts: + drivers/perf/fsl_imx8_ddr_perf.c + drivers/perf/arm_smmuv3_pmu.c +--- + drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 1 + + drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 1 + + drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 1 + + 3 files changed, 3 insertions(+) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +index b3488ae1f2b8..620fa1345150 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +@@ -386,6 +386,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev) + ddrc_pmu->sccl_id, ddrc_pmu->index_id); + ddrc_pmu->pmu = (struct pmu) { + .name = name, ++ .module = THIS_MODULE, + .task_ctx_nr = perf_invalid_context, + .event_init = hisi_uncore_pmu_event_init, + .pmu_enable = hisi_uncore_pmu_enable, +diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +index f0215d50d84d..33a0da941be2 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +@@ -397,6 +397,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev) + hha_pmu->sccl_id, hha_pmu->index_id); + hha_pmu->pmu = (struct pmu) { + .name = name, ++ .module = THIS_MODULE, + .task_ctx_nr = perf_invalid_context, + .event_init = hisi_uncore_pmu_event_init, + .pmu_enable = hisi_uncore_pmu_enable, +diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +index 11563e29d983..92485f00dcc8 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +@@ -387,6 +387,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev) + l3c_pmu->sccl_id, l3c_pmu->index_id); + l3c_pmu->pmu = (struct pmu) { + .name = name, ++ .module = THIS_MODULE, + .task_ctx_nr = perf_invalid_context, + .event_init = hisi_uncore_pmu_event_init, + .pmu_enable = hisi_uncore_pmu_enable, +-- +2.27.0 + diff --git a/patches/0050-For-drivers-that-do-not-support-context-exclusion-le.patch b/patches/0050-For-drivers-that-do-not-support-context-exclusion-le.patch new file mode 100644 index 0000000..d844698 --- /dev/null +++ b/patches/0050-For-drivers-that-do-not-support-context-exclusion-le.patch @@ -0,0 +1,194 @@ +From 6d7245609c516aae8719e8d27b737337635ad8c3 Mon Sep 17 00:00:00 2001 +From: Andrew Murray +Date: Thu, 10 Jan 2019 13:53:29 +0000 +Subject: [PATCH 09/55] For drivers that do not support context exclusion let's + advertise the PERF_PMU_CAP_NO_EXCLUDE capability. This ensures that perf will + prevent us from handling events where any exclusion flags are set. Let's also + remove the now unnecessary check for exclusion flags. + +mainline inclusion +from mainline-v5.1-rc1 +commit 306563985819ed2af9df0a26ae368ed12cf28f41 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?=306563985819ed2af9df0a26ae368ed12cf28f41 + +-------------------------------------------------------------------- + +Signed-off-by: Andrew Murray +Signed-off-by: Peter Zijlstra (Intel) +Acked-by: Will Deacon +Cc: Arnaldo Carvalho de Melo +Cc: Benjamin Herrenschmidt +Cc: Borislav Petkov +Cc: Ivan Kokshaysky +Cc: Linus Torvalds +Cc: Mark Rutland +Cc: Matt Turner +Cc: Michael Ellerman +Cc: Paul Mackerras +Cc: Peter Zijlstra +Cc: Richard Henderson +Cc: Russell King +Cc: Sascha Hauer +Cc: Shawn Guo +Cc: Thomas Gleixner +Cc: linux-arm-kernel@lists.infradead.org +Cc: linuxppc-dev@lists.ozlabs.org +Cc: robin.murphy@arm.com +Cc: suzuki.poulose@arm.com +Link: https://lkml.kernel.org/r/1547128414-50693-8-git-send-email-andrew.murray@arm.com +Signed-off-by: Ingo Molnar +Signed-off-by: hongrongxuan + + Conflicts: + drivers/perf/thunderx2_pmu.c +--- + drivers/perf/arm-cci.c | 10 +--------- + drivers/perf/arm-ccn.c | 6 ++---- + drivers/perf/arm_dsu_pmu.c | 9 ++------- + drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 1 + + drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 1 + + drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 1 + + drivers/perf/hisilicon/hisi_uncore_pmu.c | 9 --------- + 7 files changed, 8 insertions(+), 29 deletions(-) + +diff --git a/drivers/perf/arm-cci.c b/drivers/perf/arm-cci.c +index 3bbc853dc12f..aca4570f78a8 100644 +--- a/drivers/perf/arm-cci.c ++++ b/drivers/perf/arm-cci.c +@@ -1327,15 +1327,6 @@ static int cci_pmu_event_init(struct perf_event *event) + if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK) + return -EOPNOTSUPP; + +- /* We have no filtering of any kind */ +- if (event->attr.exclude_user || +- event->attr.exclude_kernel || +- event->attr.exclude_hv || +- event->attr.exclude_idle || +- event->attr.exclude_host || +- event->attr.exclude_guest) +- return -EINVAL; +- + /* + * Following the example set by other "uncore" PMUs, we accept any CPU + * and rewrite its affinity dynamically rather than having perf core +@@ -1433,6 +1424,7 @@ static int cci_pmu_init(struct cci_pmu *cci_pmu, struct platform_device *pdev) + .stop = cci_pmu_stop, + .read = pmu_read, + .attr_groups = pmu_attr_groups, ++ .capabilities = PERF_PMU_CAP_NO_EXCLUDE, + }; + + cci_pmu->plat_device = pdev; +diff --git a/drivers/perf/arm-ccn.c b/drivers/perf/arm-ccn.c +index e4e06d2fbe29..e13ff765b362 100644 +--- a/drivers/perf/arm-ccn.c ++++ b/drivers/perf/arm-ccn.c +@@ -741,10 +741,7 @@ static int arm_ccn_pmu_event_init(struct perf_event *event) + return -EOPNOTSUPP; + } + +- if (has_branch_stack(event) || event->attr.exclude_user || +- event->attr.exclude_kernel || event->attr.exclude_hv || +- event->attr.exclude_idle || event->attr.exclude_host || +- event->attr.exclude_guest) { ++ if (has_branch_stack(event)) { + dev_dbg(ccn->dev, "Can't exclude execution levels!\n"); + return -EINVAL; + } +@@ -1290,6 +1287,7 @@ static int arm_ccn_pmu_init(struct arm_ccn *ccn) + .read = arm_ccn_pmu_event_read, + .pmu_enable = arm_ccn_pmu_enable, + .pmu_disable = arm_ccn_pmu_disable, ++ .capabilities = PERF_PMU_CAP_NO_EXCLUDE, + }; + + /* No overflow interrupt? Have to use a timer instead. */ +diff --git a/drivers/perf/arm_dsu_pmu.c b/drivers/perf/arm_dsu_pmu.c +index f1cb7a910394..87573eaa7fdd 100644 +--- a/drivers/perf/arm_dsu_pmu.c ++++ b/drivers/perf/arm_dsu_pmu.c +@@ -562,13 +562,7 @@ static int dsu_pmu_event_init(struct perf_event *event) + return -EINVAL; + } + +- if (has_branch_stack(event) || +- event->attr.exclude_user || +- event->attr.exclude_kernel || +- event->attr.exclude_hv || +- event->attr.exclude_idle || +- event->attr.exclude_host || +- event->attr.exclude_guest) { ++ if (has_branch_stack(event)) { + dev_dbg(dsu_pmu->pmu.dev, "Can't support filtering\n"); + return -EINVAL; + } +@@ -735,6 +729,7 @@ static int dsu_pmu_device_probe(struct platform_device *pdev) + .read = dsu_pmu_read, + + .attr_groups = dsu_pmu_attr_groups, ++ .capabilities = PERF_PMU_CAP_NO_EXCLUDE, + }; + + rc = perf_pmu_register(&dsu_pmu->pmu, name, -1); +diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +index 620fa1345150..4bab34504425 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +@@ -397,6 +397,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev) + .stop = hisi_uncore_pmu_stop, + .read = hisi_uncore_pmu_read, + .attr_groups = hisi_ddrc_pmu_attr_groups, ++ .capabilities = PERF_PMU_CAP_NO_EXCLUDE, + }; + + ret = perf_pmu_register(&ddrc_pmu->pmu, name, -1); +diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +index 33a0da941be2..53711b945551 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +@@ -408,6 +408,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev) + .stop = hisi_uncore_pmu_stop, + .read = hisi_uncore_pmu_read, + .attr_groups = hisi_hha_pmu_attr_groups, ++ .capabilities = PERF_PMU_CAP_NO_EXCLUDE, + }; + + ret = perf_pmu_register(&hha_pmu->pmu, name, -1); +diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +index 92485f00dcc8..171cf74405b3 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +@@ -398,6 +398,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev) + .stop = hisi_uncore_pmu_stop, + .read = hisi_uncore_pmu_read, + .attr_groups = hisi_l3c_pmu_attr_groups, ++ .capabilities = PERF_PMU_CAP_NO_EXCLUDE, + }; + + ret = perf_pmu_register(&l3c_pmu->pmu, name, -1); +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c +index 53f623ac4cc6..50b654a13305 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c +@@ -148,15 +148,6 @@ int hisi_uncore_pmu_event_init(struct perf_event *event) + if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK) + return -EOPNOTSUPP; + +- /* counters do not have these bits */ +- if (event->attr.exclude_user || +- event->attr.exclude_kernel || +- event->attr.exclude_host || +- event->attr.exclude_guest || +- event->attr.exclude_hv || +- event->attr.exclude_idle) +- return -EINVAL; +- + /* + * The uncore counters not specific to any CPU, so cannot + * support per-task +-- +2.27.0 + diff --git a/patches/0051-drivers-provide-devm_platform_ioremap_resource.patch b/patches/0051-drivers-provide-devm_platform_ioremap_resource.patch new file mode 100644 index 0000000..835c760 --- /dev/null +++ b/patches/0051-drivers-provide-devm_platform_ioremap_resource.patch @@ -0,0 +1,78 @@ +From 9adb641d4a64e0ed52ba63ea401a9858efe8976d Mon Sep 17 00:00:00 2001 +From: Bartosz Golaszewski +Date: Wed, 20 Feb 2019 11:12:39 +0000 +Subject: [PATCH 10/55] drivers: provide devm_platform_ioremap_resource() + +mainline inclusion +from mainline-v5.1-rc1 +commit 306563985819ed2af9df0a26ae368ed12cf28f41 +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=306563985819ed2af9df0a26ae368ed12cf28f41 + +------------------------------------------------------------------- + +There are currently 1200+ instances of using platform_get_resource() +and devm_ioremap_resource() together in the kernel tree. + +This patch wraps these two calls in a single helper. Thanks to that +we don't have to declare a local variable for struct resource * and can +omit the redundant argument for resource type. We also have one +function call less. + +Signed-off-by: Bartosz Golaszewski +Acked-by: Greg Kroah-Hartman +Reviewed-by: Andy Shevchenko +Signed-off-by: Linus Walleij +Signed-off-by: hongrongxuan +--- + drivers/base/platform.c | 18 ++++++++++++++++++ + include/linux/platform_device.h | 3 +++ + 2 files changed, 21 insertions(+) + +diff --git a/drivers/base/platform.c b/drivers/base/platform.c +index be8c82cc4445..23ec70ef6897 100644 +--- a/drivers/base/platform.c ++++ b/drivers/base/platform.c +@@ -80,6 +80,24 @@ struct resource *platform_get_resource(struct platform_device *dev, + } + EXPORT_SYMBOL_GPL(platform_get_resource); + ++/** ++ * devm_platform_ioremap_resource - call devm_ioremap_resource() for a platform ++ * device ++ * ++ * @pdev: platform device to use both for memory resource lookup as well as ++ * resource managemend ++ * @index: resource index ++ */ ++void __iomem *devm_platform_ioremap_resource(struct platform_device *pdev, ++ unsigned int index) ++{ ++ struct resource *res; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, index); ++ return devm_ioremap_resource(&pdev->dev, res); ++} ++EXPORT_SYMBOL_GPL(devm_platform_ioremap_resource); ++ + /** + * platform_get_irq - get an IRQ for a device + * @dev: platform device +diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h +index 1a9f38f27f65..9e5c98fcea8c 100644 +--- a/include/linux/platform_device.h ++++ b/include/linux/platform_device.h +@@ -51,6 +51,9 @@ extern struct device platform_bus; + extern void arch_setup_pdev_archdata(struct platform_device *); + extern struct resource *platform_get_resource(struct platform_device *, + unsigned int, unsigned int); ++extern void __iomem * ++devm_platform_ioremap_resource(struct platform_device *pdev, ++ unsigned int index); + extern int platform_get_irq(struct platform_device *, unsigned int); + extern int platform_irq_count(struct platform_device *); + extern struct resource *platform_get_resource_byname(struct platform_device *, +-- +2.27.0 + diff --git a/patches/0052-perf-hisi-use-devm_platform_ioremap_resource-to-simp.patch b/patches/0052-perf-hisi-use-devm_platform_ioremap_resource-to-simp.patch new file mode 100644 index 0000000..c38d249 --- /dev/null +++ b/patches/0052-perf-hisi-use-devm_platform_ioremap_resource-to-simp.patch @@ -0,0 +1,97 @@ +From ce76ffbdbb8cf7dcdc4bbd2988971202f4ab7e0f Mon Sep 17 00:00:00 2001 +From: YueHaibing +Date: Fri, 6 Sep 2019 22:36:44 +0800 +Subject: [PATCH 11/55] perf: hisi: use devm_platform_ioremap_resource() to + simplify code + +mainline inclusion +from mainline-v5.5-rc1 +commit 42c184ade43a79d36f50a0b3394b3326633f53f5 +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=42c184ade43a79d36f50a0b3394b3326633f53f5 + +--------------------------------------------------------------- + +Use devm_platform_ioremap_resource() to simplify the code a bit. +This is detected by coccinelle. + +Signed-off-by: YueHaibing +Signed-off-by: Will Deacon +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 5 +---- + drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 4 +--- + drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 4 +--- + 3 files changed, 3 insertions(+), 10 deletions(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +index 4bab34504425..5d9dd4078994 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +@@ -248,8 +248,6 @@ MODULE_DEVICE_TABLE(acpi, hisi_ddrc_pmu_acpi_match); + static int hisi_ddrc_pmu_init_data(struct platform_device *pdev, + struct hisi_pmu *ddrc_pmu) + { +- struct resource *res; +- + /* + * Use the SCCL_ID and DDRC channel ID to identify the + * DDRC PMU, while SCCL_ID is in MPIDR[aff2]. +@@ -268,8 +266,7 @@ static int hisi_ddrc_pmu_init_data(struct platform_device *pdev, + /* DDRC PMUs only share the same SCCL */ + ddrc_pmu->ccl_id = -1; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- ddrc_pmu->base = devm_ioremap_resource(&pdev->dev, res); ++ ddrc_pmu->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(ddrc_pmu->base)) { + dev_err(&pdev->dev, "ioremap failed for ddrc_pmu resource\n"); + return PTR_ERR(ddrc_pmu->base); +diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +index 53711b945551..d3c517325a3f 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +@@ -239,7 +239,6 @@ static int hisi_hha_pmu_init_data(struct platform_device *pdev, + struct hisi_pmu *hha_pmu) + { + unsigned long long id; +- struct resource *res; + acpi_status status; + + status = acpi_evaluate_integer(ACPI_HANDLE(&pdev->dev), +@@ -261,8 +260,7 @@ static int hisi_hha_pmu_init_data(struct platform_device *pdev, + /* HHA PMUs only share the same SCCL */ + hha_pmu->ccl_id = -1; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- hha_pmu->base = devm_ioremap_resource(&pdev->dev, res); ++ hha_pmu->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(hha_pmu->base)) { + dev_err(&pdev->dev, "ioremap failed for hha_pmu resource\n"); + return PTR_ERR(hha_pmu->base); +diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +index 171cf74405b3..cbbf73ea66e6 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +@@ -238,7 +238,6 @@ static int hisi_l3c_pmu_init_data(struct platform_device *pdev, + struct hisi_pmu *l3c_pmu) + { + unsigned long long id; +- struct resource *res; + acpi_status status; + + status = acpi_evaluate_integer(ACPI_HANDLE(&pdev->dev), +@@ -264,8 +263,7 @@ static int hisi_l3c_pmu_init_data(struct platform_device *pdev, + return -EINVAL; + } + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- l3c_pmu->base = devm_ioremap_resource(&pdev->dev, res); ++ l3c_pmu->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(l3c_pmu->base)) { + dev_err(&pdev->dev, "ioremap failed for l3c_pmu resource\n"); + return PTR_ERR(l3c_pmu->base); +-- +2.27.0 + diff --git a/patches/0053-drivers-perf-hisi-Add-identifier-sysfs-file.patch b/patches/0053-drivers-perf-hisi-Add-identifier-sysfs-file.patch new file mode 100644 index 0000000..ad5ca3f --- /dev/null +++ b/patches/0053-drivers-perf-hisi-Add-identifier-sysfs-file.patch @@ -0,0 +1,218 @@ +From 7da4fb60563da82f9b482af152909d29818b5d9e Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Fri, 30 Jul 2021 15:43:58 +0800 +Subject: [PATCH 12/55] drivers/perf: hisi: Add identifier sysfs file + +mainline inclusion +from mainline-v5.10-rc3 +commit ac4511c9364c9a6390e8585cdd4596103bca16eb +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M +CVE: NA +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ac4511c9364c9a6390e8585cdd4596103bca16eb + +------------------------------------------------------------------------ + +To allow userspace to identify the specific implementation of the device, +add an "identifier" sysfs file. + +Encoding is as follows (same for all uncore drivers): +hi1620: 0x0 +hi1630: 0x30 + +Signed-off-by: John Garry +Link: https://lore.kernel.org/r/1602149181-237415-2-git-send-email-john.garry@huawei.com +Signed-off-by: Will Deacon +Reviewed-by: Shaokun Zhang +Signed-off-by: Zheng Zengkai +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 16 ++++++++++++++++ + drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 16 ++++++++++++++++ + drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 16 ++++++++++++++++ + drivers/perf/hisilicon/hisi_uncore_pmu.c | 10 ++++++++++ + drivers/perf/hisilicon/hisi_uncore_pmu.h | 7 +++++++ + 5 files changed, 65 insertions(+) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +index 5d9dd4078994..a88c7d840d38 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +@@ -36,6 +36,7 @@ + #define DDRC_INT_MASK 0x6c8 + #define DDRC_INT_STATUS 0x6cc + #define DDRC_INT_CLEAR 0x6d0 ++#define DDRC_VERSION 0x710 + + /* DDRC has 8-counters */ + #define DDRC_NR_COUNTERS 0x8 +@@ -272,6 +273,8 @@ static int hisi_ddrc_pmu_init_data(struct platform_device *pdev, + return PTR_ERR(ddrc_pmu->base); + } + ++ ddrc_pmu->identifier = readl(ddrc_pmu->base + DDRC_VERSION); ++ + return 0; + } + +@@ -313,10 +316,23 @@ static const struct attribute_group hisi_ddrc_pmu_cpumask_attr_group = { + .attrs = hisi_ddrc_pmu_cpumask_attrs, + }; + ++static struct device_attribute hisi_ddrc_pmu_identifier_attr = ++ __ATTR(identifier, 0444, hisi_uncore_pmu_identifier_attr_show, NULL); ++ ++static struct attribute *hisi_ddrc_pmu_identifier_attrs[] = { ++ &hisi_ddrc_pmu_identifier_attr.attr, ++ NULL ++}; ++ ++static struct attribute_group hisi_ddrc_pmu_identifier_group = { ++ .attrs = hisi_ddrc_pmu_identifier_attrs, ++}; ++ + static const struct attribute_group *hisi_ddrc_pmu_attr_groups[] = { + &hisi_ddrc_pmu_format_group, + &hisi_ddrc_pmu_events_group, + &hisi_ddrc_pmu_cpumask_attr_group, ++ &hisi_ddrc_pmu_identifier_group, + NULL, + }; + +diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +index d3c517325a3f..1e0138bbe6e7 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +@@ -26,6 +26,7 @@ + #define HHA_INT_MASK 0x0804 + #define HHA_INT_STATUS 0x0808 + #define HHA_INT_CLEAR 0x080C ++#define HHA_VERSION 0x1cf0 + #define HHA_PERF_CTRL 0x1E00 + #define HHA_EVENT_CTRL 0x1E04 + #define HHA_EVENT_TYPE0 0x1E80 +@@ -266,6 +267,8 @@ static int hisi_hha_pmu_init_data(struct platform_device *pdev, + return PTR_ERR(hha_pmu->base); + } + ++ hha_pmu->identifier = readl(hha_pmu->base + HHA_VERSION); ++ + return 0; + } + +@@ -325,10 +328,23 @@ static const struct attribute_group hisi_hha_pmu_cpumask_attr_group = { + .attrs = hisi_hha_pmu_cpumask_attrs, + }; + ++static struct device_attribute hisi_hha_pmu_identifier_attr = ++ __ATTR(identifier, 0444, hisi_uncore_pmu_identifier_attr_show, NULL); ++ ++static struct attribute *hisi_hha_pmu_identifier_attrs[] = { ++ &hisi_hha_pmu_identifier_attr.attr, ++ NULL ++}; ++ ++static struct attribute_group hisi_hha_pmu_identifier_group = { ++ .attrs = hisi_hha_pmu_identifier_attrs, ++}; ++ + static const struct attribute_group *hisi_hha_pmu_attr_groups[] = { + &hisi_hha_pmu_format_group, + &hisi_hha_pmu_events_group, + &hisi_hha_pmu_cpumask_attr_group, ++ &hisi_hha_pmu_identifier_group, + NULL, + }; + +diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +index cbbf73ea66e6..1707ae551ece 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +@@ -28,6 +28,7 @@ + #define L3C_INT_STATUS 0x0808 + #define L3C_INT_CLEAR 0x080c + #define L3C_EVENT_CTRL 0x1c00 ++#define L3C_VERSION 0x1cf0 + #define L3C_EVENT_TYPE0 0x1d00 + /* + * Each counter is 48-bits and [48:63] are reserved +@@ -269,6 +270,8 @@ static int hisi_l3c_pmu_init_data(struct platform_device *pdev, + return PTR_ERR(l3c_pmu->base); + } + ++ l3c_pmu->identifier = readl(l3c_pmu->base + L3C_VERSION); ++ + return 0; + } + +@@ -315,10 +318,23 @@ static const struct attribute_group hisi_l3c_pmu_cpumask_attr_group = { + .attrs = hisi_l3c_pmu_cpumask_attrs, + }; + ++static struct device_attribute hisi_l3c_pmu_identifier_attr = ++ __ATTR(identifier, 0444, hisi_uncore_pmu_identifier_attr_show, NULL); ++ ++static struct attribute *hisi_l3c_pmu_identifier_attrs[] = { ++ &hisi_l3c_pmu_identifier_attr.attr, ++ NULL ++}; ++ ++static struct attribute_group hisi_l3c_pmu_identifier_group = { ++ .attrs = hisi_l3c_pmu_identifier_attrs, ++}; ++ + static const struct attribute_group *hisi_l3c_pmu_attr_groups[] = { + &hisi_l3c_pmu_format_group, + &hisi_l3c_pmu_events_group, + &hisi_l3c_pmu_cpumask_attr_group, ++ &hisi_l3c_pmu_identifier_group, + NULL, + }; + +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c +index 50b654a13305..f6a992da24bf 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c +@@ -122,6 +122,16 @@ int hisi_uncore_pmu_get_event_idx(struct perf_event *event) + } + EXPORT_SYMBOL_GPL(hisi_uncore_pmu_get_event_idx); + ++ssize_t hisi_uncore_pmu_identifier_attr_show(struct device *dev, ++ struct device_attribute *attr, ++ char *page) ++{ ++ struct hisi_pmu *hisi_pmu = to_hisi_pmu(dev_get_drvdata(dev)); ++ ++ return snprintf(page, PAGE_SIZE, "0x%08x\n", hisi_pmu->identifier); ++} ++EXPORT_SYMBOL_GPL(hisi_uncore_pmu_identifier_attr_show); ++ + static void hisi_uncore_pmu_clear_event_idx(struct hisi_pmu *hisi_pmu, int idx) + { + if (!hisi_uncore_pmu_counter_valid(hisi_pmu, idx)) { +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h +index 8f2f2fc5dde4..098a8f6dc7ee 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h +@@ -78,6 +78,7 @@ struct hisi_pmu { + int counter_bits; + /* check event code range */ + int check_event; ++ u32 identifier; + }; + + int hisi_uncore_pmu_counter_valid(struct hisi_pmu *hisi_pmu, int idx); +@@ -100,4 +101,10 @@ ssize_t hisi_cpumask_sysfs_show(struct device *dev, + struct device_attribute *attr, char *buf); + int hisi_uncore_pmu_online_cpu(unsigned int cpu, struct hlist_node *node); + int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node); ++ ++ssize_t hisi_uncore_pmu_identifier_attr_show(struct device *dev, ++ struct device_attribute *attr, ++ char *page); ++ ++ + #endif /* __HISI_UNCORE_PMU_H__ */ +-- +2.27.0 + diff --git a/patches/0054-drivers-perf-hisi-Remove-unnecessary-check-of-counte.patch b/patches/0054-drivers-perf-hisi-Remove-unnecessary-check-of-counte.patch new file mode 100644 index 0000000..202363d --- /dev/null +++ b/patches/0054-drivers-perf-hisi-Remove-unnecessary-check-of-counte.patch @@ -0,0 +1,193 @@ +From 34861133469cfd5c5851f7f4ab05e3d3af1dd13a Mon Sep 17 00:00:00 2001 +From: Shaokun Zhang +Date: Fri, 30 Jul 2021 15:44:02 +0800 +Subject: [PATCH 13/55] drivers/perf: hisi: Remove unnecessary check of counter + index + +mainline inclusion +from mainline-v5.12-rc3 +commit 4e4cb8ca48bd68c00df67c10ff867016abb7391f +category: cleanup +bugzilla: 175148 +CVE: NA +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4e4cb8ca48bd68c00df67c10ff867016abb7391f + +------------------------------------------------------------------------ + +The sanity check for counter index has been done in the function +hisi_uncore_pmu_get_event_idx, so remove the redundant interface +hisi_uncore_pmu_counter_valid() and sanity check. + +Cc: Mark Rutland +Cc: Will Deacon +Cc: John Garry +Cc: Jonathan Cameron +Co-developed-by: Qi Liu +Signed-off-by: Qi Liu +Signed-off-by: Shaokun Zhang +Link: https://lore.kernel.org/r/1615186237-22263-2-git-send-email-zhangshaokun@hisilicon.com +Signed-off-by: Will Deacon +Reviewed-by: Shaokun Zhang +Signed-off-by: Zheng Zengkai +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 20 +++---------------- + drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 18 ++--------------- + drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 18 ++--------------- + drivers/perf/hisilicon/hisi_uncore_pmu.c | 11 ---------- + drivers/perf/hisilicon/hisi_uncore_pmu.h | 1 - + 5 files changed, 7 insertions(+), 61 deletions(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +index a88c7d840d38..bcb2c2d66b7f 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +@@ -68,29 +68,15 @@ static u32 hisi_ddrc_pmu_get_counter_offset(int cntr_idx) + static u64 hisi_ddrc_pmu_read_counter(struct hisi_pmu *ddrc_pmu, + struct hw_perf_event *hwc) + { +- /* Use event code as counter index */ +- u32 idx = GET_DDRC_EVENTID(hwc); +- +- if (!hisi_uncore_pmu_counter_valid(ddrc_pmu, idx)) { +- dev_err(ddrc_pmu->dev, "Unsupported event index:%d!\n", idx); +- return 0; +- } +- +- return readl(ddrc_pmu->base + hisi_ddrc_pmu_get_counter_offset(idx)); ++ return readl(ddrc_pmu->base + ++ hisi_ddrc_pmu_get_counter_offset(hwc->idx)); + } + + static void hisi_ddrc_pmu_write_counter(struct hisi_pmu *ddrc_pmu, + struct hw_perf_event *hwc, u64 val) + { +- u32 idx = GET_DDRC_EVENTID(hwc); +- +- if (!hisi_uncore_pmu_counter_valid(ddrc_pmu, idx)) { +- dev_err(ddrc_pmu->dev, "Unsupported event index:%d!\n", idx); +- return; +- } +- + writel((u32)val, +- ddrc_pmu->base + hisi_ddrc_pmu_get_counter_offset(idx)); ++ ddrc_pmu->base + hisi_ddrc_pmu_get_counter_offset(hwc->idx)); + } + + /* +diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +index 1e0138bbe6e7..de1766342b4e 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +@@ -54,29 +54,15 @@ static u32 hisi_hha_pmu_get_counter_offset(u32 cntr_idx) + static u64 hisi_hha_pmu_read_counter(struct hisi_pmu *hha_pmu, + struct hw_perf_event *hwc) + { +- u32 idx = hwc->idx; +- +- if (!hisi_uncore_pmu_counter_valid(hha_pmu, idx)) { +- dev_err(hha_pmu->dev, "Unsupported event index:%d!\n", idx); +- return 0; +- } +- + /* Read 64 bits and like L3C, top 16 bits are RAZ */ +- return readq(hha_pmu->base + hisi_hha_pmu_get_counter_offset(idx)); ++ return readq(hha_pmu->base + hisi_hha_pmu_get_counter_offset(hwc->idx)); + } + + static void hisi_hha_pmu_write_counter(struct hisi_pmu *hha_pmu, + struct hw_perf_event *hwc, u64 val) + { +- u32 idx = hwc->idx; +- +- if (!hisi_uncore_pmu_counter_valid(hha_pmu, idx)) { +- dev_err(hha_pmu->dev, "Unsupported event index:%d!\n", idx); +- return; +- } +- + /* Write 64 bits and like L3C, top 16 bits are WI */ +- writeq(val, hha_pmu->base + hisi_hha_pmu_get_counter_offset(idx)); ++ writeq(val, hha_pmu->base + hisi_hha_pmu_get_counter_offset(hwc->idx)); + } + + static void hisi_hha_pmu_write_evtype(struct hisi_pmu *hha_pmu, int idx, +diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +index 1707ae551ece..c4afeaaaa3a4 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +@@ -53,29 +53,15 @@ static u32 hisi_l3c_pmu_get_counter_offset(u32 cntr_idx) + static u64 hisi_l3c_pmu_read_counter(struct hisi_pmu *l3c_pmu, + struct hw_perf_event *hwc) + { +- u32 idx = hwc->idx; +- +- if (!hisi_uncore_pmu_counter_valid(l3c_pmu, idx)) { +- dev_err(l3c_pmu->dev, "Unsupported event index:%d!\n", idx); +- return 0; +- } +- + /* Read 64-bits and the upper 16 bits are RAZ */ +- return readq(l3c_pmu->base + hisi_l3c_pmu_get_counter_offset(idx)); ++ return readq(l3c_pmu->base + hisi_l3c_pmu_get_counter_offset(hwc->idx)); + } + + static void hisi_l3c_pmu_write_counter(struct hisi_pmu *l3c_pmu, + struct hw_perf_event *hwc, u64 val) + { +- u32 idx = hwc->idx; +- +- if (!hisi_uncore_pmu_counter_valid(l3c_pmu, idx)) { +- dev_err(l3c_pmu->dev, "Unsupported event index:%d!\n", idx); +- return; +- } +- + /* Write 64-bits and the upper 16 bits are WI */ +- writeq(val, l3c_pmu->base + hisi_l3c_pmu_get_counter_offset(idx)); ++ writeq(val, l3c_pmu->base + hisi_l3c_pmu_get_counter_offset(hwc->idx)); + } + + static void hisi_l3c_pmu_write_evtype(struct hisi_pmu *l3c_pmu, int idx, +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c +index f6a992da24bf..9ebdb76dd3a4 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c +@@ -99,12 +99,6 @@ static bool hisi_validate_event_group(struct perf_event *event) + return counters <= hisi_pmu->num_counters; + } + +-int hisi_uncore_pmu_counter_valid(struct hisi_pmu *hisi_pmu, int idx) +-{ +- return idx >= 0 && idx < hisi_pmu->num_counters; +-} +-EXPORT_SYMBOL_GPL(hisi_uncore_pmu_counter_valid); +- + int hisi_uncore_pmu_get_event_idx(struct perf_event *event) + { + struct hisi_pmu *hisi_pmu = to_hisi_pmu(event->pmu); +@@ -134,11 +128,6 @@ EXPORT_SYMBOL_GPL(hisi_uncore_pmu_identifier_attr_show); + + static void hisi_uncore_pmu_clear_event_idx(struct hisi_pmu *hisi_pmu, int idx) + { +- if (!hisi_uncore_pmu_counter_valid(hisi_pmu, idx)) { +- dev_err(hisi_pmu->dev, "Unsupported event index:%d!\n", idx); +- return; +- } +- + clear_bit(idx, hisi_pmu->pmu_events.used_mask); + } + +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h +index 098a8f6dc7ee..d71a6c86b282 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h +@@ -81,7 +81,6 @@ struct hisi_pmu { + u32 identifier; + }; + +-int hisi_uncore_pmu_counter_valid(struct hisi_pmu *hisi_pmu, int idx); + int hisi_uncore_pmu_get_event_idx(struct perf_event *event); + void hisi_uncore_pmu_read(struct perf_event *event); + int hisi_uncore_pmu_add(struct perf_event *event, int flags); +-- +2.27.0 + diff --git a/patches/0055-drivers-perf-hisi-Refactor-code-for-more-uncore-PMUs.patch b/patches/0055-drivers-perf-hisi-Refactor-code-for-more-uncore-PMUs.patch new file mode 100644 index 0000000..61f6a74 --- /dev/null +++ b/patches/0055-drivers-perf-hisi-Refactor-code-for-more-uncore-PMUs.patch @@ -0,0 +1,448 @@ +From 990f0977794c7bc3a78dbea66e3b5e276eccaad4 Mon Sep 17 00:00:00 2001 +From: Shaokun Zhang +Date: Fri, 30 Jul 2021 15:44:03 +0800 +Subject: [PATCH 14/55] drivers/perf: hisi: Refactor code for more uncore PMUs + +mainline inclusion +from mainline-v5.12-rc3 +commit baff06c315a146a6943b4fcabb4fe4fa36167413 +category: cleanup +bugzilla: 175148 +CVE: NA +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=baff06c315a146a6943b4fcabb4fe4fa36167413 + +------------------------------------------------------------------------ + +On HiSilicon uncore PMU drivers, interrupt handling function and interrupt +registration function are very similar in differents PMU modules. Let's +refactor the frame. + +Two new callbacks are added for the HW accessors: + +* hisi_uncore_ops::get_int_status returns a bitmap of events which + have overflowed and raised an interrupt + +* hisi_uncore_ops::clear_int_status clears the overflow status for a + specific event + +These callback functions are used by a common IRQ handler, +hisi_uncore_pmu_isr(). + +One more function hisi_uncore_pmu_init_irq() is added to replace each +PMU initialization IRQ interface and simplify the code. + +Cc: Mark Rutland +Cc: Will Deacon +Cc: John Garry +Cc: Jonathan Cameron +Reviewed-by: John Garry +Co-developed-by: Qi Liu +Signed-off-by: Qi Liu +Signed-off-by: Shaokun Zhang +Link: https://lore.kernel.org/r/1615186237-22263-3-git-send-email-zhangshaokun@hisilicon.com +Signed-off-by: Will Deacon +Reviewed-by: Shaokun Zhang +Signed-off-by: Zheng Zengkai +Signed-off-by: hongrongxuan + + Conflicts: + drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c + drivers/perf/hisilicon/hisi_uncore_hha_pmu.c + drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +--- + drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 61 +++---------------- + drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 61 +++---------------- + drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 61 +++---------------- + drivers/perf/hisilicon/hisi_uncore_pmu.c | 54 ++++++++++++++++ + drivers/perf/hisilicon/hisi_uncore_pmu.h | 6 +- + 5 files changed, 80 insertions(+), 163 deletions(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +index bcb2c2d66b7f..a03e3f8058b3 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +@@ -17,7 +17,6 @@ + #include + #include + #include +-#include + #include + + #include "hisi_uncore_pmu.h" +@@ -168,62 +167,14 @@ static void hisi_ddrc_pmu_disable_counter_int(struct hisi_pmu *ddrc_pmu, + writel(val, ddrc_pmu->base + DDRC_INT_MASK); + } + +-static irqreturn_t hisi_ddrc_pmu_isr(int irq, void *dev_id) ++static u32 hisi_ddrc_pmu_get_int_status(struct hisi_pmu *ddrc_pmu) + { +- struct hisi_pmu *ddrc_pmu = dev_id; +- struct perf_event *event; +- unsigned long overflown; +- int idx; +- +- /* Read the DDRC_INT_STATUS register */ +- overflown = readl(ddrc_pmu->base + DDRC_INT_STATUS); +- if (!overflown) +- return IRQ_NONE; +- +- /* +- * Find the counter index which overflowed if the bit was set +- * and handle it +- */ +- for_each_set_bit(idx, &overflown, DDRC_NR_COUNTERS) { +- /* Write 1 to clear the IRQ status flag */ +- writel((1 << idx), ddrc_pmu->base + DDRC_INT_CLEAR); +- +- /* Get the corresponding event struct */ +- event = ddrc_pmu->pmu_events.hw_events[idx]; +- if (!event) +- continue; +- +- hisi_uncore_pmu_event_update(event); +- hisi_uncore_pmu_set_event_period(event); +- } +- +- return IRQ_HANDLED; ++ return readl(ddrc_pmu->base + DDRC_INT_STATUS); + } + +-static int hisi_ddrc_pmu_init_irq(struct hisi_pmu *ddrc_pmu, +- struct platform_device *pdev) ++static void hisi_ddrc_pmu_clear_int_status(struct hisi_pmu *ddrc_pmu, int idx) + { +- int irq, ret; +- +- /* Read and init IRQ */ +- irq = platform_get_irq(pdev, 0); +- if (irq < 0) { +- dev_err(&pdev->dev, "DDRC PMU get irq fail; irq:%d\n", irq); +- return irq; +- } +- +- ret = devm_request_irq(&pdev->dev, irq, hisi_ddrc_pmu_isr, +- IRQF_NOBALANCING | IRQF_NO_THREAD, +- dev_name(&pdev->dev), ddrc_pmu); +- if (ret < 0) { +- dev_err(&pdev->dev, +- "Fail to request IRQ:%d ret:%d\n", irq, ret); +- return ret; +- } +- +- ddrc_pmu->irq = irq; +- +- return 0; ++ writel(1 << idx, ddrc_pmu->base + DDRC_INT_CLEAR); + } + + static const struct acpi_device_id hisi_ddrc_pmu_acpi_match[] = { +@@ -333,6 +284,8 @@ static const struct hisi_uncore_ops hisi_uncore_ddrc_ops = { + .disable_counter_int = hisi_ddrc_pmu_disable_counter_int, + .write_counter = hisi_ddrc_pmu_write_counter, + .read_counter = hisi_ddrc_pmu_read_counter, ++ .get_int_status = hisi_ddrc_pmu_get_int_status, ++ .clear_int_status = hisi_ddrc_pmu_clear_int_status, + }; + + static int hisi_ddrc_pmu_dev_probe(struct platform_device *pdev, +@@ -344,7 +297,7 @@ static int hisi_ddrc_pmu_dev_probe(struct platform_device *pdev, + if (ret) + return ret; + +- ret = hisi_ddrc_pmu_init_irq(ddrc_pmu, pdev); ++ ret = hisi_uncore_pmu_init_irq(ddrc_pmu, pdev); + if (ret) + return ret; + +diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +index de1766342b4e..536d1f637fa7 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +@@ -17,7 +17,6 @@ + #include + #include + #include +-#include + #include + + #include "hisi_uncore_pmu.h" +@@ -158,62 +157,14 @@ static void hisi_hha_pmu_disable_counter_int(struct hisi_pmu *hha_pmu, + writel(val, hha_pmu->base + HHA_INT_MASK); + } + +-static irqreturn_t hisi_hha_pmu_isr(int irq, void *dev_id) ++static u32 hisi_hha_pmu_get_int_status(struct hisi_pmu *hha_pmu) + { +- struct hisi_pmu *hha_pmu = dev_id; +- struct perf_event *event; +- unsigned long overflown; +- int idx; +- +- /* Read HHA_INT_STATUS register */ +- overflown = readl(hha_pmu->base + HHA_INT_STATUS); +- if (!overflown) +- return IRQ_NONE; +- +- /* +- * Find the counter index which overflowed if the bit was set +- * and handle it +- */ +- for_each_set_bit(idx, &overflown, HHA_NR_COUNTERS) { +- /* Write 1 to clear the IRQ status flag */ +- writel((1 << idx), hha_pmu->base + HHA_INT_CLEAR); +- +- /* Get the corresponding event struct */ +- event = hha_pmu->pmu_events.hw_events[idx]; +- if (!event) +- continue; +- +- hisi_uncore_pmu_event_update(event); +- hisi_uncore_pmu_set_event_period(event); +- } +- +- return IRQ_HANDLED; ++ return readl(hha_pmu->base + HHA_INT_STATUS); + } + +-static int hisi_hha_pmu_init_irq(struct hisi_pmu *hha_pmu, +- struct platform_device *pdev) ++static void hisi_hha_pmu_clear_int_status(struct hisi_pmu *hha_pmu, int idx) + { +- int irq, ret; +- +- /* Read and init IRQ */ +- irq = platform_get_irq(pdev, 0); +- if (irq < 0) { +- dev_err(&pdev->dev, "HHA PMU get irq fail; irq:%d\n", irq); +- return irq; +- } +- +- ret = devm_request_irq(&pdev->dev, irq, hisi_hha_pmu_isr, +- IRQF_NOBALANCING | IRQF_NO_THREAD, +- dev_name(&pdev->dev), hha_pmu); +- if (ret < 0) { +- dev_err(&pdev->dev, +- "Fail to request IRQ:%d ret:%d\n", irq, ret); +- return ret; +- } +- +- hha_pmu->irq = irq; +- +- return 0; ++ writel(1 << idx, hha_pmu->base + HHA_INT_CLEAR); + } + + static const struct acpi_device_id hisi_hha_pmu_acpi_match[] = { +@@ -345,6 +296,8 @@ static const struct hisi_uncore_ops hisi_uncore_hha_ops = { + .disable_counter_int = hisi_hha_pmu_disable_counter_int, + .write_counter = hisi_hha_pmu_write_counter, + .read_counter = hisi_hha_pmu_read_counter, ++ .get_int_status = hisi_hha_pmu_get_int_status, ++ .clear_int_status = hisi_hha_pmu_clear_int_status, + }; + + static int hisi_hha_pmu_dev_probe(struct platform_device *pdev, +@@ -356,7 +309,7 @@ static int hisi_hha_pmu_dev_probe(struct platform_device *pdev, + if (ret) + return ret; + +- ret = hisi_hha_pmu_init_irq(hha_pmu, pdev); ++ ret = hisi_uncore_pmu_init_irq(hha_pmu, pdev); + if (ret) + return ret; + +diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +index c4afeaaaa3a4..5256e4ce3384 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +@@ -17,7 +17,6 @@ + #include + #include + #include +-#include + #include + + #include "hisi_uncore_pmu.h" +@@ -157,62 +156,14 @@ static void hisi_l3c_pmu_disable_counter_int(struct hisi_pmu *l3c_pmu, + writel(val, l3c_pmu->base + L3C_INT_MASK); + } + +-static irqreturn_t hisi_l3c_pmu_isr(int irq, void *dev_id) ++static u32 hisi_l3c_pmu_get_int_status(struct hisi_pmu *l3c_pmu) + { +- struct hisi_pmu *l3c_pmu = dev_id; +- struct perf_event *event; +- unsigned long overflown; +- int idx; +- +- /* Read L3C_INT_STATUS register */ +- overflown = readl(l3c_pmu->base + L3C_INT_STATUS); +- if (!overflown) +- return IRQ_NONE; +- +- /* +- * Find the counter index which overflowed if the bit was set +- * and handle it. +- */ +- for_each_set_bit(idx, &overflown, L3C_NR_COUNTERS) { +- /* Write 1 to clear the IRQ status flag */ +- writel((1 << idx), l3c_pmu->base + L3C_INT_CLEAR); +- +- /* Get the corresponding event struct */ +- event = l3c_pmu->pmu_events.hw_events[idx]; +- if (!event) +- continue; +- +- hisi_uncore_pmu_event_update(event); +- hisi_uncore_pmu_set_event_period(event); +- } +- +- return IRQ_HANDLED; ++ return readl(l3c_pmu->base + L3C_INT_STATUS); + } + +-static int hisi_l3c_pmu_init_irq(struct hisi_pmu *l3c_pmu, +- struct platform_device *pdev) ++static void hisi_l3c_pmu_clear_int_status(struct hisi_pmu *l3c_pmu, int idx) + { +- int irq, ret; +- +- /* Read and init IRQ */ +- irq = platform_get_irq(pdev, 0); +- if (irq < 0) { +- dev_err(&pdev->dev, "L3C PMU get irq fail; irq:%d\n", irq); +- return irq; +- } +- +- ret = devm_request_irq(&pdev->dev, irq, hisi_l3c_pmu_isr, +- IRQF_NOBALANCING | IRQF_NO_THREAD, +- dev_name(&pdev->dev), l3c_pmu); +- if (ret < 0) { +- dev_err(&pdev->dev, +- "Fail to request IRQ:%d ret:%d\n", irq, ret); +- return ret; +- } +- +- l3c_pmu->irq = irq; +- +- return 0; ++ writel(1 << idx, l3c_pmu->base + L3C_INT_CLEAR); + } + + static const struct acpi_device_id hisi_l3c_pmu_acpi_match[] = { +@@ -335,6 +286,8 @@ static const struct hisi_uncore_ops hisi_uncore_l3c_ops = { + .disable_counter_int = hisi_l3c_pmu_disable_counter_int, + .write_counter = hisi_l3c_pmu_write_counter, + .read_counter = hisi_l3c_pmu_read_counter, ++ .get_int_status = hisi_l3c_pmu_get_int_status, ++ .clear_int_status = hisi_l3c_pmu_clear_int_status, + }; + + static int hisi_l3c_pmu_dev_probe(struct platform_device *pdev, +@@ -346,7 +299,7 @@ static int hisi_l3c_pmu_dev_probe(struct platform_device *pdev, + if (ret) + return ret; + +- ret = hisi_l3c_pmu_init_irq(l3c_pmu, pdev); ++ ret = hisi_uncore_pmu_init_irq(l3c_pmu, pdev); + if (ret) + return ret; + +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c +index 9ebdb76dd3a4..53ac9f062c0f 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c +@@ -131,6 +131,60 @@ static void hisi_uncore_pmu_clear_event_idx(struct hisi_pmu *hisi_pmu, int idx) + clear_bit(idx, hisi_pmu->pmu_events.used_mask); + } + ++static irqreturn_t hisi_uncore_pmu_isr(int irq, void *data) ++{ ++ struct hisi_pmu *hisi_pmu = data; ++ struct perf_event *event; ++ unsigned long overflown; ++ int idx; ++ ++ overflown = hisi_pmu->ops->get_int_status(hisi_pmu); ++ if (!overflown) ++ return IRQ_NONE; ++ ++ /* ++ * Find the counter index which overflowed if the bit was set ++ * and handle it. ++ */ ++ for_each_set_bit(idx, &overflown, hisi_pmu->num_counters) { ++ /* Write 1 to clear the IRQ status flag */ ++ hisi_pmu->ops->clear_int_status(hisi_pmu, idx); ++ /* Get the corresponding event struct */ ++ event = hisi_pmu->pmu_events.hw_events[idx]; ++ if (!event) ++ continue; ++ ++ hisi_uncore_pmu_event_update(event); ++ hisi_uncore_pmu_set_event_period(event); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++int hisi_uncore_pmu_init_irq(struct hisi_pmu *hisi_pmu, ++ struct platform_device *pdev) ++{ ++ int irq, ret; ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) ++ return irq; ++ ++ ret = devm_request_irq(&pdev->dev, irq, hisi_uncore_pmu_isr, ++ IRQF_NOBALANCING | IRQF_NO_THREAD, ++ dev_name(&pdev->dev), hisi_pmu); ++ if (ret < 0) { ++ dev_err(&pdev->dev, ++ "Fail to request IRQ: %d ret: %d.\n", irq, ret); ++ return ret; ++ } ++ ++ hisi_pmu->irq = irq; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(hisi_uncore_pmu_init_irq); ++ + int hisi_uncore_pmu_event_init(struct perf_event *event) + { + struct hw_perf_event *hwc = &event->hw; +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h +index d71a6c86b282..3336723e8cf6 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + + #undef pr_fmt +@@ -50,6 +51,8 @@ struct hisi_uncore_ops { + void (*disable_counter_int)(struct hisi_pmu *, struct hw_perf_event *); + void (*start_counters)(struct hisi_pmu *); + void (*stop_counters)(struct hisi_pmu *); ++ u32 (*get_int_status)(struct hisi_pmu *hisi_pmu); ++ void (*clear_int_status)(struct hisi_pmu *hisi_pmu, int idx); + }; + + struct hisi_pmu_hwevents { +@@ -104,6 +107,7 @@ int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node); + ssize_t hisi_uncore_pmu_identifier_attr_show(struct device *dev, + struct device_attribute *attr, + char *page); +- ++int hisi_uncore_pmu_init_irq(struct hisi_pmu *hisi_pmu, ++ struct platform_device *pdev); + + #endif /* __HISI_UNCORE_PMU_H__ */ +-- +2.27.0 + diff --git a/patches/0056-drivers-perf-hisi-Add-PMU-version-for-uncore-PMU-dri.patch b/patches/0056-drivers-perf-hisi-Add-PMU-version-for-uncore-PMU-dri.patch new file mode 100644 index 0000000..a29c997 --- /dev/null +++ b/patches/0056-drivers-perf-hisi-Add-PMU-version-for-uncore-PMU-dri.patch @@ -0,0 +1,448 @@ +From 3d5c7ff8c993e8f570d32755ba43ae17e02b007e Mon Sep 17 00:00:00 2001 +From: Shaokun Zhang +Date: Fri, 30 Jul 2021 15:44:04 +0800 +Subject: [PATCH 15/55] drivers/perf: hisi: Add PMU version for uncore PMU + drivers. + +mainline inclusion +from mainline-v5.12-rc3 +commit 3da582df575c3b2910e09e0445c27c3ebc8096e5 +category: feature +bugzilla: 175148 +CVE: NA +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3da582df575c3b2910e09e0445c27c3ebc8096e5 + +------------------------------------------------------------------------ + +For HiSilicon uncore PMU, more versions are supported and some variables +shall be added suffix to distinguish the version which are prepared for +the new drivers. + +Cc: Mark Rutland +Cc: Will Deacon +Cc: John Garry +Cc: Jonathan Cameron +Acked-by: Mark Rutland +Reviewed-by: John Garry +Co-developed-by: Qi Liu +Signed-off-by: Qi Liu +Signed-off-by: Shaokun Zhang +Link: https://lore.kernel.org/r/1615186237-22263-4-git-send-email-zhangshaokun@hisilicon.com +Signed-off-by: Will Deacon +Reviewed-by: Shaokun Zhang +Signed-off-by: Zheng Zengkai +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 96 ++++++++++--------- + drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 27 +++--- + drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 23 ++--- + 3 files changed, 75 insertions(+), 71 deletions(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +index a03e3f8058b3..1d1c8e9f417e 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +@@ -39,7 +39,8 @@ + + /* DDRC has 8-counters */ + #define DDRC_NR_COUNTERS 0x8 +-#define DDRC_PERF_CTRL_EN 0x2 ++#define DDRC_V1_PERF_CTRL_EN 0x2 ++#define DDRC_V1_NR_EVENTS 0x7 + + /* + * For DDRC PMU, there are eight-events and every event has been mapped +@@ -56,26 +57,26 @@ static const u32 ddrc_reg_off[] = { + + /* + * Select the counter register offset using the counter index. +- * In DDRC there are no programmable counter, the count +- * is readed form the statistics counter register itself. ++ * In PMU v1, there are no programmable counter, the count ++ * is read form the statistics counter register itself. + */ +-static u32 hisi_ddrc_pmu_get_counter_offset(int cntr_idx) ++static u32 hisi_ddrc_pmu_v1_get_counter_offset(int cntr_idx) + { + return ddrc_reg_off[cntr_idx]; + } + +-static u64 hisi_ddrc_pmu_read_counter(struct hisi_pmu *ddrc_pmu, ++static u64 hisi_ddrc_pmu_v1_read_counter(struct hisi_pmu *ddrc_pmu, + struct hw_perf_event *hwc) + { + return readl(ddrc_pmu->base + +- hisi_ddrc_pmu_get_counter_offset(hwc->idx)); ++ hisi_ddrc_pmu_v1_get_counter_offset(hwc->idx)); + } + +-static void hisi_ddrc_pmu_write_counter(struct hisi_pmu *ddrc_pmu, ++static void hisi_ddrc_pmu_v1_write_counter(struct hisi_pmu *ddrc_pmu, + struct hw_perf_event *hwc, u64 val) + { + writel((u32)val, +- ddrc_pmu->base + hisi_ddrc_pmu_get_counter_offset(hwc->idx)); ++ ddrc_pmu->base + hisi_ddrc_pmu_v1_get_counter_offset(hwc->idx)); + } + + /* +@@ -87,28 +88,28 @@ static void hisi_ddrc_pmu_write_evtype(struct hisi_pmu *hha_pmu, int idx, + { + } + +-static void hisi_ddrc_pmu_start_counters(struct hisi_pmu *ddrc_pmu) ++static void hisi_ddrc_pmu_v1_start_counters(struct hisi_pmu *ddrc_pmu) + { + u32 val; + + /* Set perf_enable in DDRC_PERF_CTRL to start event counting */ + val = readl(ddrc_pmu->base + DDRC_PERF_CTRL); +- val |= DDRC_PERF_CTRL_EN; ++ val |= DDRC_V1_PERF_CTRL_EN; + writel(val, ddrc_pmu->base + DDRC_PERF_CTRL); + } + +-static void hisi_ddrc_pmu_stop_counters(struct hisi_pmu *ddrc_pmu) ++static void hisi_ddrc_pmu_v1_stop_counters(struct hisi_pmu *ddrc_pmu) + { + u32 val; + + /* Clear perf_enable in DDRC_PERF_CTRL to stop event counting */ + val = readl(ddrc_pmu->base + DDRC_PERF_CTRL); +- val &= ~DDRC_PERF_CTRL_EN; ++ val &= ~DDRC_V1_PERF_CTRL_EN; + writel(val, ddrc_pmu->base + DDRC_PERF_CTRL); + } + +-static void hisi_ddrc_pmu_enable_counter(struct hisi_pmu *ddrc_pmu, +- struct hw_perf_event *hwc) ++static void hisi_ddrc_pmu_v1_enable_counter(struct hisi_pmu *ddrc_pmu, ++ struct hw_perf_event *hwc) + { + u32 val; + +@@ -118,8 +119,8 @@ static void hisi_ddrc_pmu_enable_counter(struct hisi_pmu *ddrc_pmu, + writel(val, ddrc_pmu->base + DDRC_EVENT_CTRL); + } + +-static void hisi_ddrc_pmu_disable_counter(struct hisi_pmu *ddrc_pmu, +- struct hw_perf_event *hwc) ++static void hisi_ddrc_pmu_v1_disable_counter(struct hisi_pmu *ddrc_pmu, ++ struct hw_perf_event *hwc) + { + u32 val; + +@@ -129,7 +130,7 @@ static void hisi_ddrc_pmu_disable_counter(struct hisi_pmu *ddrc_pmu, + writel(val, ddrc_pmu->base + DDRC_EVENT_CTRL); + } + +-static int hisi_ddrc_pmu_get_event_idx(struct perf_event *event) ++static int hisi_ddrc_pmu_v1_get_event_idx(struct perf_event *event) + { + struct hisi_pmu *ddrc_pmu = to_hisi_pmu(event->pmu); + unsigned long *used_mask = ddrc_pmu->pmu_events.used_mask; +@@ -145,8 +146,8 @@ static int hisi_ddrc_pmu_get_event_idx(struct perf_event *event) + return idx; + } + +-static void hisi_ddrc_pmu_enable_counter_int(struct hisi_pmu *ddrc_pmu, +- struct hw_perf_event *hwc) ++static void hisi_ddrc_pmu_v1_enable_counter_int(struct hisi_pmu *ddrc_pmu, ++ struct hw_perf_event *hwc) + { + u32 val; + +@@ -156,8 +157,8 @@ static void hisi_ddrc_pmu_enable_counter_int(struct hisi_pmu *ddrc_pmu, + writel(val, ddrc_pmu->base + DDRC_INT_MASK); + } + +-static void hisi_ddrc_pmu_disable_counter_int(struct hisi_pmu *ddrc_pmu, +- struct hw_perf_event *hwc) ++static void hisi_ddrc_pmu_v1_disable_counter_int(struct hisi_pmu *ddrc_pmu, ++ struct hw_perf_event *hwc) + { + u32 val; + +@@ -167,12 +168,13 @@ static void hisi_ddrc_pmu_disable_counter_int(struct hisi_pmu *ddrc_pmu, + writel(val, ddrc_pmu->base + DDRC_INT_MASK); + } + +-static u32 hisi_ddrc_pmu_get_int_status(struct hisi_pmu *ddrc_pmu) ++static u32 hisi_ddrc_pmu_v1_get_int_status(struct hisi_pmu *ddrc_pmu) + { + return readl(ddrc_pmu->base + DDRC_INT_STATUS); + } + +-static void hisi_ddrc_pmu_clear_int_status(struct hisi_pmu *ddrc_pmu, int idx) ++static void hisi_ddrc_pmu_v1_clear_int_status(struct hisi_pmu *ddrc_pmu, ++ int idx) + { + writel(1 << idx, ddrc_pmu->base + DDRC_INT_CLEAR); + } +@@ -215,17 +217,17 @@ static int hisi_ddrc_pmu_init_data(struct platform_device *pdev, + return 0; + } + +-static struct attribute *hisi_ddrc_pmu_format_attr[] = { ++static struct attribute *hisi_ddrc_pmu_v1_format_attr[] = { + HISI_PMU_FORMAT_ATTR(event, "config:0-4"), + NULL, + }; + +-static const struct attribute_group hisi_ddrc_pmu_format_group = { ++static const struct attribute_group hisi_ddrc_pmu_v1_format_group = { + .name = "format", +- .attrs = hisi_ddrc_pmu_format_attr, ++ .attrs = hisi_ddrc_pmu_v1_format_attr, + }; + +-static struct attribute *hisi_ddrc_pmu_events_attr[] = { ++static struct attribute *hisi_ddrc_pmu_v1_events_attr[] = { + HISI_PMU_EVENT_ATTR(flux_wr, 0x00), + HISI_PMU_EVENT_ATTR(flux_rd, 0x01), + HISI_PMU_EVENT_ATTR(flux_wcmd, 0x02), +@@ -237,9 +239,9 @@ static struct attribute *hisi_ddrc_pmu_events_attr[] = { + NULL, + }; + +-static const struct attribute_group hisi_ddrc_pmu_events_group = { ++static const struct attribute_group hisi_ddrc_pmu_v1_events_group = { + .name = "events", +- .attrs = hisi_ddrc_pmu_events_attr, ++ .attrs = hisi_ddrc_pmu_v1_events_attr, + }; + + static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL); +@@ -265,27 +267,27 @@ static struct attribute_group hisi_ddrc_pmu_identifier_group = { + .attrs = hisi_ddrc_pmu_identifier_attrs, + }; + +-static const struct attribute_group *hisi_ddrc_pmu_attr_groups[] = { +- &hisi_ddrc_pmu_format_group, +- &hisi_ddrc_pmu_events_group, ++static const struct attribute_group *hisi_ddrc_pmu_v1_attr_groups[] = { ++ &hisi_ddrc_pmu_v1_format_group, ++ &hisi_ddrc_pmu_v1_events_group, + &hisi_ddrc_pmu_cpumask_attr_group, + &hisi_ddrc_pmu_identifier_group, + NULL, + }; + +-static const struct hisi_uncore_ops hisi_uncore_ddrc_ops = { ++static const struct hisi_uncore_ops hisi_uncore_ddrc_v1_ops = { + .write_evtype = hisi_ddrc_pmu_write_evtype, +- .get_event_idx = hisi_ddrc_pmu_get_event_idx, +- .start_counters = hisi_ddrc_pmu_start_counters, +- .stop_counters = hisi_ddrc_pmu_stop_counters, +- .enable_counter = hisi_ddrc_pmu_enable_counter, +- .disable_counter = hisi_ddrc_pmu_disable_counter, +- .enable_counter_int = hisi_ddrc_pmu_enable_counter_int, +- .disable_counter_int = hisi_ddrc_pmu_disable_counter_int, +- .write_counter = hisi_ddrc_pmu_write_counter, +- .read_counter = hisi_ddrc_pmu_read_counter, +- .get_int_status = hisi_ddrc_pmu_get_int_status, +- .clear_int_status = hisi_ddrc_pmu_clear_int_status, ++ .get_event_idx = hisi_ddrc_pmu_v1_get_event_idx, ++ .start_counters = hisi_ddrc_pmu_v1_start_counters, ++ .stop_counters = hisi_ddrc_pmu_v1_stop_counters, ++ .enable_counter = hisi_ddrc_pmu_v1_enable_counter, ++ .disable_counter = hisi_ddrc_pmu_v1_disable_counter, ++ .enable_counter_int = hisi_ddrc_pmu_v1_enable_counter_int, ++ .disable_counter_int = hisi_ddrc_pmu_v1_disable_counter_int, ++ .write_counter = hisi_ddrc_pmu_v1_write_counter, ++ .read_counter = hisi_ddrc_pmu_v1_read_counter, ++ .get_int_status = hisi_ddrc_pmu_v1_get_int_status, ++ .clear_int_status = hisi_ddrc_pmu_v1_clear_int_status, + }; + + static int hisi_ddrc_pmu_dev_probe(struct platform_device *pdev, +@@ -303,10 +305,10 @@ static int hisi_ddrc_pmu_dev_probe(struct platform_device *pdev, + + ddrc_pmu->num_counters = DDRC_NR_COUNTERS; + ddrc_pmu->counter_bits = 32; +- ddrc_pmu->ops = &hisi_uncore_ddrc_ops; ++ ddrc_pmu->ops = &hisi_uncore_ddrc_v1_ops; + ddrc_pmu->dev = &pdev->dev; + ddrc_pmu->on_cpu = -1; +- ddrc_pmu->check_event = 7; ++ ddrc_pmu->check_event = DDRC_V1_NR_EVENTS; + + return 0; + } +@@ -348,7 +350,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev) + .start = hisi_uncore_pmu_start, + .stop = hisi_uncore_pmu_stop, + .read = hisi_uncore_pmu_read, +- .attr_groups = hisi_ddrc_pmu_attr_groups, ++ .attr_groups = hisi_ddrc_pmu_v1_attr_groups, + .capabilities = PERF_PMU_CAP_NO_EXCLUDE, + }; + +diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +index 536d1f637fa7..7941900ea667 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +@@ -36,10 +36,11 @@ + #define HHA_CNT0_LOWER 0x1F00 + + /* HHA has 16-counters */ +-#define HHA_NR_COUNTERS 0x10 ++#define HHA_V1_NR_COUNTERS 0x10 + + #define HHA_PERF_CTRL_EN 0x1 + #define HHA_EVTYPE_NONE 0xff ++#define HHA_V1_NR_EVENT 0x65 + + /* + * Select the counter register offset using the counter index +@@ -209,17 +210,17 @@ static int hisi_hha_pmu_init_data(struct platform_device *pdev, + return 0; + } + +-static struct attribute *hisi_hha_pmu_format_attr[] = { ++static struct attribute *hisi_hha_pmu_v1_format_attr[] = { + HISI_PMU_FORMAT_ATTR(event, "config:0-7"), + NULL, + }; + +-static const struct attribute_group hisi_hha_pmu_format_group = { ++static const struct attribute_group hisi_hha_pmu_v1_format_group = { + .name = "format", +- .attrs = hisi_hha_pmu_format_attr, ++ .attrs = hisi_hha_pmu_v1_format_attr, + }; + +-static struct attribute *hisi_hha_pmu_events_attr[] = { ++static struct attribute *hisi_hha_pmu_v1_events_attr[] = { + HISI_PMU_EVENT_ATTR(rx_ops_num, 0x00), + HISI_PMU_EVENT_ATTR(rx_outer, 0x01), + HISI_PMU_EVENT_ATTR(rx_sccl, 0x02), +@@ -249,9 +250,9 @@ static struct attribute *hisi_hha_pmu_events_attr[] = { + NULL, + }; + +-static const struct attribute_group hisi_hha_pmu_events_group = { ++static const struct attribute_group hisi_hha_pmu_v1_events_group = { + .name = "events", +- .attrs = hisi_hha_pmu_events_attr, ++ .attrs = hisi_hha_pmu_v1_events_attr, + }; + + static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL); +@@ -277,9 +278,9 @@ static struct attribute_group hisi_hha_pmu_identifier_group = { + .attrs = hisi_hha_pmu_identifier_attrs, + }; + +-static const struct attribute_group *hisi_hha_pmu_attr_groups[] = { +- &hisi_hha_pmu_format_group, +- &hisi_hha_pmu_events_group, ++static const struct attribute_group *hisi_hha_pmu_v1_attr_groups[] = { ++ &hisi_hha_pmu_v1_format_group, ++ &hisi_hha_pmu_v1_events_group, + &hisi_hha_pmu_cpumask_attr_group, + &hisi_hha_pmu_identifier_group, + NULL, +@@ -313,12 +314,12 @@ static int hisi_hha_pmu_dev_probe(struct platform_device *pdev, + if (ret) + return ret; + +- hha_pmu->num_counters = HHA_NR_COUNTERS; ++ hha_pmu->num_counters = HHA_V1_NR_COUNTERS; + hha_pmu->counter_bits = 48; + hha_pmu->ops = &hisi_uncore_hha_ops; + hha_pmu->dev = &pdev->dev; + hha_pmu->on_cpu = -1; +- hha_pmu->check_event = 0x65; ++ hha_pmu->check_event = HHA_V1_NR_EVENT; + + return 0; + } +@@ -360,7 +361,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev) + .start = hisi_uncore_pmu_start, + .stop = hisi_uncore_pmu_stop, + .read = hisi_uncore_pmu_read, +- .attr_groups = hisi_hha_pmu_attr_groups, ++ .attr_groups = hisi_hha_pmu_v1_attr_groups, + .capabilities = PERF_PMU_CAP_NO_EXCLUDE, + }; + +diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +index 5256e4ce3384..5a4975e64368 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +@@ -40,6 +40,7 @@ + + #define L3C_PERF_CTRL_EN 0x10000 + #define L3C_EVTYPE_NONE 0xff ++#define L3C_V1_NR_EVENTS 0x59 + + /* + * Select the counter register offset using the counter index +@@ -212,17 +213,17 @@ static int hisi_l3c_pmu_init_data(struct platform_device *pdev, + return 0; + } + +-static struct attribute *hisi_l3c_pmu_format_attr[] = { ++static struct attribute *hisi_l3c_pmu_v1_format_attr[] = { + HISI_PMU_FORMAT_ATTR(event, "config:0-7"), + NULL, + }; + +-static const struct attribute_group hisi_l3c_pmu_format_group = { ++static const struct attribute_group hisi_l3c_pmu_v1_format_group = { + .name = "format", +- .attrs = hisi_l3c_pmu_format_attr, ++ .attrs = hisi_l3c_pmu_v1_format_attr, + }; + +-static struct attribute *hisi_l3c_pmu_events_attr[] = { ++static struct attribute *hisi_l3c_pmu_v1_events_attr[] = { + HISI_PMU_EVENT_ATTR(rd_cpipe, 0x00), + HISI_PMU_EVENT_ATTR(wr_cpipe, 0x01), + HISI_PMU_EVENT_ATTR(rd_hit_cpipe, 0x02), +@@ -239,9 +240,9 @@ static struct attribute *hisi_l3c_pmu_events_attr[] = { + NULL, + }; + +-static const struct attribute_group hisi_l3c_pmu_events_group = { ++static const struct attribute_group hisi_l3c_pmu_v1_events_group = { + .name = "events", +- .attrs = hisi_l3c_pmu_events_attr, ++ .attrs = hisi_l3c_pmu_v1_events_attr, + }; + + static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL); +@@ -267,9 +268,9 @@ static struct attribute_group hisi_l3c_pmu_identifier_group = { + .attrs = hisi_l3c_pmu_identifier_attrs, + }; + +-static const struct attribute_group *hisi_l3c_pmu_attr_groups[] = { +- &hisi_l3c_pmu_format_group, +- &hisi_l3c_pmu_events_group, ++static const struct attribute_group *hisi_l3c_pmu_v1_attr_groups[] = { ++ &hisi_l3c_pmu_v1_format_group, ++ &hisi_l3c_pmu_v1_events_group, + &hisi_l3c_pmu_cpumask_attr_group, + &hisi_l3c_pmu_identifier_group, + NULL, +@@ -308,7 +309,7 @@ static int hisi_l3c_pmu_dev_probe(struct platform_device *pdev, + l3c_pmu->ops = &hisi_uncore_l3c_ops; + l3c_pmu->dev = &pdev->dev; + l3c_pmu->on_cpu = -1; +- l3c_pmu->check_event = 0x59; ++ l3c_pmu->check_event = L3C_V1_NR_EVENTS; + + return 0; + } +@@ -350,7 +351,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev) + .start = hisi_uncore_pmu_start, + .stop = hisi_uncore_pmu_stop, + .read = hisi_uncore_pmu_read, +- .attr_groups = hisi_l3c_pmu_attr_groups, ++ .attr_groups = hisi_l3c_pmu_v1_attr_groups, + .capabilities = PERF_PMU_CAP_NO_EXCLUDE, + }; + +-- +2.27.0 + diff --git a/patches/0057-drivers-perf-hisi-Add-new-functions-for-L3C-PMU.patch b/patches/0057-drivers-perf-hisi-Add-new-functions-for-L3C-PMU.patch new file mode 100644 index 0000000..16132e3 --- /dev/null +++ b/patches/0057-drivers-perf-hisi-Add-new-functions-for-L3C-PMU.patch @@ -0,0 +1,505 @@ +From d4d47e781c088759005a0a6dc4e843a8bfeb5bdd Mon Sep 17 00:00:00 2001 +From: Shaokun Zhang +Date: Fri, 30 Jul 2021 15:44:05 +0800 +Subject: [PATCH 16/55] drivers/perf: hisi: Add new functions for L3C PMU + +mainline inclusion +from mainline-v5.12-rc3 +commit 486a7f46b966a825484808d4edf53bbe02698fb3 +category: feature +bugzilla: 175148 +CVE: NA +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=486a7f46b966a825484808d4edf53bbe02698fb3 + +------------------------------------------------------------------------ + +On HiSilicon Hip09 platform, some new functions are enhanced on L3C PMU: + +* tt_req: it is the abbreviation of tracetag request and allows user to +count only read/write/atomic operations. tt_req is 3-bit and details are +listed in the hisi-pmu document. +$# perf stat -a -e hisi_sccl3_l3c0/config=0x02,tt_req=0x4/ sleep 5 + +* tt_core: it is the abbreviation of tracetag core and allows user to +filter by core/thread within the cluster, it is a 8-bit bitmap that each +bit represents the corresponding core/thread in this L3C. +$# perf stat -a -e hisi_sccl3_l3c0/config=0x02,tt_core=0xf/ sleep 5 + +* datasrc_cfg: it is the abbreviation of data source configuration and +allows user to check where the data comes from, such as: from local DDR, +cross-die DDR or cross-socket DDR. Its is 5-bit and represents different +data source in the SoC. +$# perf stat -a -e hisi_sccl3_l3c0/dat_access,datasrc_cfg=0xe/ sleep 5 + +* datasrc_skt: it is the abbreviation of data source from another socket +and is used in the multi-chips, if user wants to check the cross-socket +datat source, it shall be added in perf command. Only one bit is used to +control this. +$# perf stat -a -e hisi_sccl3_l3c0/dat_access,datasrc_cfg=0x10,datasrc_skt=1/ sleep 5 + +Cc: Mark Rutland +Cc: Will Deacon +Cc: John Garry +Cc: Jonathan Cameron +Reviewed-by: John Garry +Co-developed-by: Qi Liu +Signed-off-by: Qi Liu +Signed-off-by: Shaokun Zhang +Link: https://lore.kernel.org/r/1615186237-22263-5-git-send-email-zhangshaokun@hisilicon.com +Signed-off-by: Will Deacon +Reviewed-by: Shaokun Zhang +Signed-off-by: Zheng Zengkai +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 259 +++++++++++++++++-- + drivers/perf/hisilicon/hisi_uncore_pmu.c | 8 +- + drivers/perf/hisilicon/hisi_uncore_pmu.h | 11 + + 3 files changed, 258 insertions(+), 20 deletions(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +index 5a4975e64368..87ca2a9ca8c5 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +@@ -26,12 +26,17 @@ + #define L3C_INT_MASK 0x0800 + #define L3C_INT_STATUS 0x0808 + #define L3C_INT_CLEAR 0x080c ++#define L3C_CORE_CTRL 0x1b04 ++#define L3C_TRACETAG_CTRL 0x1b20 ++#define L3C_DATSRC_TYPE 0x1b48 ++#define L3C_DATSRC_CTRL 0x1bf0 + #define L3C_EVENT_CTRL 0x1c00 + #define L3C_VERSION 0x1cf0 + #define L3C_EVENT_TYPE0 0x1d00 + /* +- * Each counter is 48-bits and [48:63] are reserved +- * which are Read-As-Zero and Writes-Ignored. ++ * If the HW version only supports a 48-bit counter, then ++ * bits [63:48] are reserved, which are Read-As-Zero and ++ * Writes-Ignored. + */ + #define L3C_CNTR0_LOWER 0x1e00 + +@@ -39,8 +44,186 @@ + #define L3C_NR_COUNTERS 0x8 + + #define L3C_PERF_CTRL_EN 0x10000 ++#define L3C_TRACETAG_EN BIT(31) ++#define L3C_TRACETAG_REQ_SHIFT 7 ++#define L3C_TRACETAG_MARK_EN BIT(0) ++#define L3C_TRACETAG_REQ_EN (L3C_TRACETAG_MARK_EN | BIT(2)) ++#define L3C_TRACETAG_CORE_EN (L3C_TRACETAG_MARK_EN | BIT(3)) ++#define L3C_CORE_EN BIT(20) ++#define L3C_COER_NONE 0x0 ++#define L3C_DATSRC_MASK 0xFF ++#define L3C_DATSRC_SKT_EN BIT(23) ++#define L3C_DATSRC_NONE 0x0 + #define L3C_EVTYPE_NONE 0xff + #define L3C_V1_NR_EVENTS 0x59 ++#define L3C_V2_NR_EVENTS 0xFF ++ ++HISI_PMU_EVENT_ATTR_EXTRACTOR(tt_core, config1, 7, 0); ++HISI_PMU_EVENT_ATTR_EXTRACTOR(tt_req, config1, 10, 8); ++HISI_PMU_EVENT_ATTR_EXTRACTOR(datasrc_cfg, config1, 15, 11); ++HISI_PMU_EVENT_ATTR_EXTRACTOR(datasrc_skt, config1, 16, 16); ++ ++static void hisi_l3c_pmu_config_req_tracetag(struct perf_event *event) ++{ ++ struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu); ++ u32 tt_req = hisi_get_tt_req(event); ++ ++ if (tt_req) { ++ u32 val; ++ ++ /* Set request-type for tracetag */ ++ val = readl(l3c_pmu->base + L3C_TRACETAG_CTRL); ++ val |= tt_req << L3C_TRACETAG_REQ_SHIFT; ++ val |= L3C_TRACETAG_REQ_EN; ++ writel(val, l3c_pmu->base + L3C_TRACETAG_CTRL); ++ ++ /* Enable request-tracetag statistics */ ++ val = readl(l3c_pmu->base + L3C_PERF_CTRL); ++ val |= L3C_TRACETAG_EN; ++ writel(val, l3c_pmu->base + L3C_PERF_CTRL); ++ } ++} ++ ++static void hisi_l3c_pmu_clear_req_tracetag(struct perf_event *event) ++{ ++ struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu); ++ u32 tt_req = hisi_get_tt_req(event); ++ ++ if (tt_req) { ++ u32 val; ++ ++ /* Clear request-type */ ++ val = readl(l3c_pmu->base + L3C_TRACETAG_CTRL); ++ val &= ~(tt_req << L3C_TRACETAG_REQ_SHIFT); ++ val &= ~L3C_TRACETAG_REQ_EN; ++ writel(val, l3c_pmu->base + L3C_TRACETAG_CTRL); ++ ++ /* Disable request-tracetag statistics */ ++ val = readl(l3c_pmu->base + L3C_PERF_CTRL); ++ val &= ~L3C_TRACETAG_EN; ++ writel(val, l3c_pmu->base + L3C_PERF_CTRL); ++ } ++} ++ ++static void hisi_l3c_pmu_write_ds(struct perf_event *event, u32 ds_cfg) ++{ ++ struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu); ++ struct hw_perf_event *hwc = &event->hw; ++ u32 reg, reg_idx, shift, val; ++ int idx = hwc->idx; ++ ++ /* ++ * Select the appropriate datasource register(L3C_DATSRC_TYPE0/1). ++ * There are 2 datasource ctrl register for the 8 hardware counters. ++ * Datasrc is 8-bits and for the former 4 hardware counters, ++ * L3C_DATSRC_TYPE0 is chosen. For the latter 4 hardware counters, ++ * L3C_DATSRC_TYPE1 is chosen. ++ */ ++ reg = L3C_DATSRC_TYPE + (idx / 4) * 4; ++ reg_idx = idx % 4; ++ shift = 8 * reg_idx; ++ ++ val = readl(l3c_pmu->base + reg); ++ val &= ~(L3C_DATSRC_MASK << shift); ++ val |= ds_cfg << shift; ++ writel(val, l3c_pmu->base + reg); ++} ++ ++static void hisi_l3c_pmu_config_ds(struct perf_event *event) ++{ ++ struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu); ++ u32 ds_cfg = hisi_get_datasrc_cfg(event); ++ u32 ds_skt = hisi_get_datasrc_skt(event); ++ ++ if (ds_cfg) ++ hisi_l3c_pmu_write_ds(event, ds_cfg); ++ ++ if (ds_skt) { ++ u32 val; ++ ++ val = readl(l3c_pmu->base + L3C_DATSRC_CTRL); ++ val |= L3C_DATSRC_SKT_EN; ++ writel(val, l3c_pmu->base + L3C_DATSRC_CTRL); ++ } ++} ++ ++static void hisi_l3c_pmu_clear_ds(struct perf_event *event) ++{ ++ struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu); ++ u32 ds_cfg = hisi_get_datasrc_cfg(event); ++ u32 ds_skt = hisi_get_datasrc_skt(event); ++ ++ if (ds_cfg) ++ hisi_l3c_pmu_write_ds(event, L3C_DATSRC_NONE); ++ ++ if (ds_skt) { ++ u32 val; ++ ++ val = readl(l3c_pmu->base + L3C_DATSRC_CTRL); ++ val &= ~L3C_DATSRC_SKT_EN; ++ writel(val, l3c_pmu->base + L3C_DATSRC_CTRL); ++ } ++} ++ ++static void hisi_l3c_pmu_config_core_tracetag(struct perf_event *event) ++{ ++ struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu); ++ u32 core = hisi_get_tt_core(event); ++ ++ if (core) { ++ u32 val; ++ ++ /* Config and enable core information */ ++ writel(core, l3c_pmu->base + L3C_CORE_CTRL); ++ val = readl(l3c_pmu->base + L3C_PERF_CTRL); ++ val |= L3C_CORE_EN; ++ writel(val, l3c_pmu->base + L3C_PERF_CTRL); ++ ++ /* Enable core-tracetag statistics */ ++ val = readl(l3c_pmu->base + L3C_TRACETAG_CTRL); ++ val |= L3C_TRACETAG_CORE_EN; ++ writel(val, l3c_pmu->base + L3C_TRACETAG_CTRL); ++ } ++} ++ ++static void hisi_l3c_pmu_clear_core_tracetag(struct perf_event *event) ++{ ++ struct hisi_pmu *l3c_pmu = to_hisi_pmu(event->pmu); ++ u32 core = hisi_get_tt_core(event); ++ ++ if (core) { ++ u32 val; ++ ++ /* Clear core information */ ++ writel(L3C_COER_NONE, l3c_pmu->base + L3C_CORE_CTRL); ++ val = readl(l3c_pmu->base + L3C_PERF_CTRL); ++ val &= ~L3C_CORE_EN; ++ writel(val, l3c_pmu->base + L3C_PERF_CTRL); ++ ++ /* Disable core-tracetag statistics */ ++ val = readl(l3c_pmu->base + L3C_TRACETAG_CTRL); ++ val &= ~L3C_TRACETAG_CORE_EN; ++ writel(val, l3c_pmu->base + L3C_TRACETAG_CTRL); ++ } ++} ++ ++static void hisi_l3c_pmu_enable_filter(struct perf_event *event) ++{ ++ if (event->attr.config1 != 0x0) { ++ hisi_l3c_pmu_config_req_tracetag(event); ++ hisi_l3c_pmu_config_core_tracetag(event); ++ hisi_l3c_pmu_config_ds(event); ++ } ++} ++ ++static void hisi_l3c_pmu_disable_filter(struct perf_event *event) ++{ ++ if (event->attr.config1 != 0x0) { ++ hisi_l3c_pmu_clear_ds(event); ++ hisi_l3c_pmu_clear_core_tracetag(event); ++ hisi_l3c_pmu_clear_req_tracetag(event); ++ } ++} + + /* + * Select the counter register offset using the counter index +@@ -53,14 +236,12 @@ static u32 hisi_l3c_pmu_get_counter_offset(u32 cntr_idx) + static u64 hisi_l3c_pmu_read_counter(struct hisi_pmu *l3c_pmu, + struct hw_perf_event *hwc) + { +- /* Read 64-bits and the upper 16 bits are RAZ */ + return readq(l3c_pmu->base + hisi_l3c_pmu_get_counter_offset(hwc->idx)); + } + + static void hisi_l3c_pmu_write_counter(struct hisi_pmu *l3c_pmu, + struct hw_perf_event *hwc, u64 val) + { +- /* Write 64-bits and the upper 16 bits are WI */ + writeq(val, l3c_pmu->base + hisi_l3c_pmu_get_counter_offset(hwc->idx)); + } + +@@ -169,23 +350,14 @@ static void hisi_l3c_pmu_clear_int_status(struct hisi_pmu *l3c_pmu, int idx) + + static const struct acpi_device_id hisi_l3c_pmu_acpi_match[] = { + { "HISI0213", }, +- {}, ++ { "HISI0214", }, ++ {} + }; + MODULE_DEVICE_TABLE(acpi, hisi_l3c_pmu_acpi_match); + + static int hisi_l3c_pmu_init_data(struct platform_device *pdev, + struct hisi_pmu *l3c_pmu) + { +- unsigned long long id; +- acpi_status status; +- +- status = acpi_evaluate_integer(ACPI_HANDLE(&pdev->dev), +- "_UID", NULL, &id); +- if (ACPI_FAILURE(status)) +- return -EINVAL; +- +- l3c_pmu->index_id = id; +- + /* + * Use the SCCL_ID and CCL_ID to identify the L3C PMU, while + * SCCL_ID is in MPIDR[aff2] and CCL_ID is in MPIDR[aff1]. +@@ -223,6 +395,20 @@ static const struct attribute_group hisi_l3c_pmu_v1_format_group = { + .attrs = hisi_l3c_pmu_v1_format_attr, + }; + ++static struct attribute *hisi_l3c_pmu_v2_format_attr[] = { ++ HISI_PMU_FORMAT_ATTR(event, "config:0-7"), ++ HISI_PMU_FORMAT_ATTR(tt_core, "config1:0-7"), ++ HISI_PMU_FORMAT_ATTR(tt_req, "config1:8-10"), ++ HISI_PMU_FORMAT_ATTR(datasrc_cfg, "config1:11-15"), ++ HISI_PMU_FORMAT_ATTR(datasrc_skt, "config1:16"), ++ NULL ++}; ++ ++static const struct attribute_group hisi_l3c_pmu_v2_format_group = { ++ .name = "format", ++ .attrs = hisi_l3c_pmu_v2_format_attr, ++}; ++ + static struct attribute *hisi_l3c_pmu_v1_events_attr[] = { + HISI_PMU_EVENT_ATTR(rd_cpipe, 0x00), + HISI_PMU_EVENT_ATTR(wr_cpipe, 0x01), +@@ -245,6 +431,19 @@ static const struct attribute_group hisi_l3c_pmu_v1_events_group = { + .attrs = hisi_l3c_pmu_v1_events_attr, + }; + ++static struct attribute *hisi_l3c_pmu_v2_events_attr[] = { ++ HISI_PMU_EVENT_ATTR(l3c_hit, 0x48), ++ HISI_PMU_EVENT_ATTR(cycles, 0x7f), ++ HISI_PMU_EVENT_ATTR(l3c_ref, 0xb8), ++ HISI_PMU_EVENT_ATTR(dat_access, 0xb9), ++ NULL ++}; ++ ++static const struct attribute_group hisi_l3c_pmu_v2_events_group = { ++ .name = "events", ++ .attrs = hisi_l3c_pmu_v2_events_attr, ++}; ++ + static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL); + + static struct attribute *hisi_l3c_pmu_cpumask_attrs[] = { +@@ -276,6 +475,14 @@ static const struct attribute_group *hisi_l3c_pmu_v1_attr_groups[] = { + NULL, + }; + ++static const struct attribute_group *hisi_l3c_pmu_v2_attr_groups[] = { ++ &hisi_l3c_pmu_v2_format_group, ++ &hisi_l3c_pmu_v2_events_group, ++ &hisi_l3c_pmu_cpumask_attr_group, ++ &hisi_l3c_pmu_identifier_group, ++ NULL ++}; ++ + static const struct hisi_uncore_ops hisi_uncore_l3c_ops = { + .write_evtype = hisi_l3c_pmu_write_evtype, + .get_event_idx = hisi_uncore_pmu_get_event_idx, +@@ -289,6 +496,8 @@ static const struct hisi_uncore_ops hisi_uncore_l3c_ops = { + .read_counter = hisi_l3c_pmu_read_counter, + .get_int_status = hisi_l3c_pmu_get_int_status, + .clear_int_status = hisi_l3c_pmu_clear_int_status, ++ .enable_filter = hisi_l3c_pmu_enable_filter, ++ .disable_filter = hisi_l3c_pmu_disable_filter, + }; + + static int hisi_l3c_pmu_dev_probe(struct platform_device *pdev, +@@ -304,12 +513,20 @@ static int hisi_l3c_pmu_dev_probe(struct platform_device *pdev, + if (ret) + return ret; + ++ if (l3c_pmu->identifier >= HISI_PMU_V2) { ++ l3c_pmu->counter_bits = 64; ++ l3c_pmu->check_event = L3C_V2_NR_EVENTS; ++ l3c_pmu->pmu_events.attr_groups = hisi_l3c_pmu_v2_attr_groups; ++ } else { ++ l3c_pmu->counter_bits = 48; ++ l3c_pmu->check_event = L3C_V1_NR_EVENTS; ++ l3c_pmu->pmu_events.attr_groups = hisi_l3c_pmu_v1_attr_groups; ++ } ++ + l3c_pmu->num_counters = L3C_NR_COUNTERS; +- l3c_pmu->counter_bits = 48; + l3c_pmu->ops = &hisi_uncore_l3c_ops; + l3c_pmu->dev = &pdev->dev; + l3c_pmu->on_cpu = -1; +- l3c_pmu->check_event = L3C_V1_NR_EVENTS; + + return 0; + } +@@ -337,8 +554,12 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev) + return ret; + } + ++ /* ++ * CCL_ID is used to identify the L3C in the same SCCL which was ++ * used _UID by mistake. ++ */ + name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_l3c%u", +- l3c_pmu->sccl_id, l3c_pmu->index_id); ++ l3c_pmu->sccl_id, l3c_pmu->ccl_id); + l3c_pmu->pmu = (struct pmu) { + .name = name, + .module = THIS_MODULE, +@@ -351,7 +572,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev) + .start = hisi_uncore_pmu_start, + .stop = hisi_uncore_pmu_stop, + .read = hisi_uncore_pmu_read, +- .attr_groups = hisi_l3c_pmu_v1_attr_groups, ++ .attr_groups = l3c_pmu->pmu_events.attr_groups, + .capabilities = PERF_PMU_CAP_NO_EXCLUDE, + }; + +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c +index 53ac9f062c0f..c0f221e39aff 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c +@@ -24,7 +24,7 @@ + #include "hisi_uncore_pmu.h" + + #define HISI_GET_EVENTID(ev) (ev->hw.config_base & 0xff) +-#define HISI_MAX_PERIOD(nr) (BIT_ULL(nr) - 1) ++#define HISI_MAX_PERIOD(nr) (GENMASK_ULL((nr) - 1, 0)) + + /* + * PMU format attributes +@@ -248,6 +248,9 @@ static void hisi_uncore_pmu_enable_event(struct perf_event *event) + hisi_pmu->ops->write_evtype(hisi_pmu, hwc->idx, + HISI_GET_EVENTID(event)); + ++ if (hisi_pmu->ops->enable_filter) ++ hisi_pmu->ops->enable_filter(event); ++ + hisi_pmu->ops->enable_counter_int(hisi_pmu, hwc); + hisi_pmu->ops->enable_counter(hisi_pmu, hwc); + } +@@ -262,6 +265,9 @@ static void hisi_uncore_pmu_disable_event(struct perf_event *event) + + hisi_pmu->ops->disable_counter(hisi_pmu, hwc); + hisi_pmu->ops->disable_counter_int(hisi_pmu, hwc); ++ ++ if (hisi_pmu->ops->disable_filter) ++ hisi_pmu->ops->disable_filter(event); + } + + void hisi_uncore_pmu_set_event_period(struct perf_event *event) +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h +index 3336723e8cf6..1147dbd25344 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h +@@ -14,6 +14,7 @@ + #ifndef __HISI_UNCORE_PMU_H__ + #define __HISI_UNCORE_PMU_H__ + ++#include + #include + #include + #include +@@ -25,6 +26,7 @@ + #undef pr_fmt + #define pr_fmt(fmt) "hisi_pmu: " fmt + ++#define HISI_PMU_V2 0x30 + #define HISI_MAX_COUNTERS 0x10 + #define to_hisi_pmu(p) (container_of(p, struct hisi_pmu, pmu)) + +@@ -38,6 +40,12 @@ + #define HISI_PMU_EVENT_ATTR(_name, _config) \ + HISI_PMU_ATTR(_name, hisi_event_sysfs_show, (unsigned long)_config) + ++#define HISI_PMU_EVENT_ATTR_EXTRACTOR(name, config, hi, lo) \ ++ static inline u32 hisi_get_##name(struct perf_event *event) \ ++ { \ ++ return FIELD_GET(GENMASK_ULL(hi, lo), event->attr.config); \ ++ } ++ + struct hisi_pmu; + + struct hisi_uncore_ops { +@@ -53,11 +61,14 @@ struct hisi_uncore_ops { + void (*stop_counters)(struct hisi_pmu *); + u32 (*get_int_status)(struct hisi_pmu *hisi_pmu); + void (*clear_int_status)(struct hisi_pmu *hisi_pmu, int idx); ++ void (*enable_filter)(struct perf_event *event); ++ void (*disable_filter)(struct perf_event *event); + }; + + struct hisi_pmu_hwevents { + struct perf_event *hw_events[HISI_MAX_COUNTERS]; + DECLARE_BITMAP(used_mask, HISI_MAX_COUNTERS); ++ const struct attribute_group **attr_groups; + }; + + /* Generic pmu struct for different pmu types */ +-- +2.27.0 + diff --git a/patches/0058-drivers-perf-hisi-Add-new-functions-for-HHA-PMU.patch b/patches/0058-drivers-perf-hisi-Add-new-functions-for-HHA-PMU.patch new file mode 100644 index 0000000..72991e0 --- /dev/null +++ b/patches/0058-drivers-perf-hisi-Add-new-functions-for-HHA-PMU.patch @@ -0,0 +1,340 @@ +From 77e91e65e043b7cec81e193b005ead3183316bb6 Mon Sep 17 00:00:00 2001 +From: Shaokun Zhang +Date: Fri, 30 Jul 2021 15:44:06 +0800 +Subject: [PATCH 17/55] drivers/perf: hisi: Add new functions for HHA PMU + +mainline inclusion +from mainline-v5.12-rc3 +commit 932f6a99f9b0c6b7039a5e2ce961009a8dc8c07c +category: feature +bugzilla: 175148 +CVE: NA +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=932f6a99f9b0c6b7039a5e2ce961009a8dc8c07c + +------------------------------------------------------------------------ + +On HiSilicon Hip09 platform, some new functions are also supported on +HHA PMU. + +* tracetag_en: it is the abbreviation of tracetag enable and allows user +to count events according to tt_req or tt_core set in L3C PMU. + +* datasrc_skt: it is the abbreviation of data source from another +socket and it is used in the multi-chips. It's the same as L3C PMU. + +* srcid_cmd & srcid_msk: pair of the fields are used to filter +statistics that come from the specific CCL/ICL by the configuration. +These are the abbreviation of source ID command and mask. The source +ID is 11-bit and detailed descriptions are documented in +Documentation/admin-guide/perf/hisi-pmu.rst. + +Cc: Mark Rutland +Cc: Will Deacon +Cc: John Garry +Cc: Jonathan Cameron +Reviewed-by: John Garry +Co-developed-by: Qi Liu +Signed-off-by: Qi Liu +Signed-off-by: Shaokun Zhang +Link: https://lore.kernel.org/r/1615186237-22263-6-git-send-email-zhangshaokun@hisilicon.com +Signed-off-by: Will Deacon +Reviewed-by: Shaokun Zhang +Signed-off-by: Zheng Zengkai +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 203 +++++++++++++++++-- + 1 file changed, 188 insertions(+), 15 deletions(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +index 7941900ea667..a7e1749fc3e4 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +@@ -28,19 +28,136 @@ + #define HHA_VERSION 0x1cf0 + #define HHA_PERF_CTRL 0x1E00 + #define HHA_EVENT_CTRL 0x1E04 ++#define HHA_SRCID_CTRL 0x1E08 ++#define HHA_DATSRC_CTRL 0x1BF0 + #define HHA_EVENT_TYPE0 0x1E80 + /* +- * Each counter is 48-bits and [48:63] are reserved +- * which are Read-As-Zero and Writes-Ignored. ++ * If the HW version only supports a 48-bit counter, then ++ * bits [63:48] are reserved, which are Read-As-Zero and ++ * Writes-Ignored. + */ + #define HHA_CNT0_LOWER 0x1F00 + +-/* HHA has 16-counters */ ++/* HHA PMU v1 has 16 counters and v2 only has 8 counters */ + #define HHA_V1_NR_COUNTERS 0x10 ++#define HHA_V2_NR_COUNTERS 0x8 + + #define HHA_PERF_CTRL_EN 0x1 ++#define HHA_TRACETAG_EN BIT(31) ++#define HHA_SRCID_EN BIT(2) ++#define HHA_SRCID_CMD_SHIFT 6 ++#define HHA_SRCID_MSK_SHIFT 20 ++#define HHA_SRCID_CMD GENMASK(16, 6) ++#define HHA_SRCID_MSK GENMASK(30, 20) ++#define HHA_DATSRC_SKT_EN BIT(23) + #define HHA_EVTYPE_NONE 0xff + #define HHA_V1_NR_EVENT 0x65 ++#define HHA_V2_NR_EVENT 0xCE ++ ++HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_cmd, config1, 10, 0); ++HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_msk, config1, 21, 11); ++HISI_PMU_EVENT_ATTR_EXTRACTOR(tracetag_en, config1, 22, 22); ++HISI_PMU_EVENT_ATTR_EXTRACTOR(datasrc_skt, config1, 23, 23); ++ ++static void hisi_hha_pmu_enable_tracetag(struct perf_event *event) ++{ ++ struct hisi_pmu *hha_pmu = to_hisi_pmu(event->pmu); ++ u32 tt_en = hisi_get_tracetag_en(event); ++ ++ if (tt_en) { ++ u32 val; ++ ++ val = readl(hha_pmu->base + HHA_SRCID_CTRL); ++ val |= HHA_TRACETAG_EN; ++ writel(val, hha_pmu->base + HHA_SRCID_CTRL); ++ } ++} ++ ++static void hisi_hha_pmu_clear_tracetag(struct perf_event *event) ++{ ++ struct hisi_pmu *hha_pmu = to_hisi_pmu(event->pmu); ++ u32 val; ++ ++ val = readl(hha_pmu->base + HHA_SRCID_CTRL); ++ val &= ~HHA_TRACETAG_EN; ++ writel(val, hha_pmu->base + HHA_SRCID_CTRL); ++} ++ ++static void hisi_hha_pmu_config_ds(struct perf_event *event) ++{ ++ struct hisi_pmu *hha_pmu = to_hisi_pmu(event->pmu); ++ u32 ds_skt = hisi_get_datasrc_skt(event); ++ ++ if (ds_skt) { ++ u32 val; ++ ++ val = readl(hha_pmu->base + HHA_DATSRC_CTRL); ++ val |= HHA_DATSRC_SKT_EN; ++ writel(ds_skt, hha_pmu->base + HHA_DATSRC_CTRL); ++ } ++} ++ ++static void hisi_hha_pmu_clear_ds(struct perf_event *event) ++{ ++ struct hisi_pmu *hha_pmu = to_hisi_pmu(event->pmu); ++ u32 ds_skt = hisi_get_datasrc_skt(event); ++ ++ if (ds_skt) { ++ u32 val; ++ ++ val = readl(hha_pmu->base + HHA_DATSRC_CTRL); ++ val &= ~HHA_DATSRC_SKT_EN; ++ writel(ds_skt, hha_pmu->base + HHA_DATSRC_CTRL); ++ } ++} ++ ++static void hisi_hha_pmu_config_srcid(struct perf_event *event) ++{ ++ struct hisi_pmu *hha_pmu = to_hisi_pmu(event->pmu); ++ u32 cmd = hisi_get_srcid_cmd(event); ++ ++ if (cmd) { ++ u32 val, msk; ++ ++ msk = hisi_get_srcid_msk(event); ++ val = readl(hha_pmu->base + HHA_SRCID_CTRL); ++ val |= HHA_SRCID_EN | (cmd << HHA_SRCID_CMD_SHIFT) | ++ (msk << HHA_SRCID_MSK_SHIFT); ++ writel(val, hha_pmu->base + HHA_SRCID_CTRL); ++ } ++} ++ ++static void hisi_hha_pmu_disable_srcid(struct perf_event *event) ++{ ++ struct hisi_pmu *hha_pmu = to_hisi_pmu(event->pmu); ++ u32 cmd = hisi_get_srcid_cmd(event); ++ ++ if (cmd) { ++ u32 val; ++ ++ val = readl(hha_pmu->base + HHA_SRCID_CTRL); ++ val &= ~(HHA_SRCID_EN | HHA_SRCID_MSK | HHA_SRCID_CMD); ++ writel(val, hha_pmu->base + HHA_SRCID_CTRL); ++ } ++} ++ ++static void hisi_hha_pmu_enable_filter(struct perf_event *event) ++{ ++ if (event->attr.config1 != 0x0) { ++ hisi_hha_pmu_enable_tracetag(event); ++ hisi_hha_pmu_config_ds(event); ++ hisi_hha_pmu_config_srcid(event); ++ } ++} ++ ++static void hisi_hha_pmu_disable_filter(struct perf_event *event) ++{ ++ if (event->attr.config1 != 0x0) { ++ hisi_hha_pmu_disable_srcid(event); ++ hisi_hha_pmu_clear_ds(event); ++ hisi_hha_pmu_clear_tracetag(event); ++ } ++} + + /* + * Select the counter register offset using the counter index +@@ -170,7 +287,8 @@ static void hisi_hha_pmu_clear_int_status(struct hisi_pmu *hha_pmu, int idx) + + static const struct acpi_device_id hisi_hha_pmu_acpi_match[] = { + { "HISI0243", }, +- {}, ++ { "HISI0244", }, ++ {} + }; + MODULE_DEVICE_TABLE(acpi, hisi_hha_pmu_acpi_match); + +@@ -180,13 +298,6 @@ static int hisi_hha_pmu_init_data(struct platform_device *pdev, + unsigned long long id; + acpi_status status; + +- status = acpi_evaluate_integer(ACPI_HANDLE(&pdev->dev), +- "_UID", NULL, &id); +- if (ACPI_FAILURE(status)) +- return -EINVAL; +- +- hha_pmu->index_id = id; +- + /* + * Use SCCL_ID and UID to identify the HHA PMU, while + * SCCL_ID is in MPIDR[aff2]. +@@ -196,6 +307,22 @@ static int hisi_hha_pmu_init_data(struct platform_device *pdev, + dev_err(&pdev->dev, "Can not read hha sccl-id!\n"); + return -EINVAL; + } ++ ++ /* ++ * Early versions of BIOS support _UID by mistake, so we support ++ * both "hisilicon, idx-id" as preference, if available. ++ */ ++ if (device_property_read_u32(&pdev->dev, "hisilicon,idx-id", ++ &hha_pmu->index_id)) { ++ status = acpi_evaluate_integer(ACPI_HANDLE(&pdev->dev), ++ "_UID", NULL, &id); ++ if (ACPI_FAILURE(status)) { ++ dev_err(&pdev->dev, "Cannot read idx-id!\n"); ++ return -EINVAL; ++ } ++ ++ hha_pmu->index_id = id; ++ } + /* HHA PMUs only share the same SCCL */ + hha_pmu->ccl_id = -1; + +@@ -220,6 +347,20 @@ static const struct attribute_group hisi_hha_pmu_v1_format_group = { + .attrs = hisi_hha_pmu_v1_format_attr, + }; + ++static struct attribute *hisi_hha_pmu_v2_format_attr[] = { ++ HISI_PMU_FORMAT_ATTR(event, "config:0-7"), ++ HISI_PMU_FORMAT_ATTR(srcid_cmd, "config1:0-10"), ++ HISI_PMU_FORMAT_ATTR(srcid_msk, "config1:11-21"), ++ HISI_PMU_FORMAT_ATTR(tracetag_en, "config1:22"), ++ HISI_PMU_FORMAT_ATTR(datasrc_skt, "config1:23"), ++ NULL ++}; ++ ++static const struct attribute_group hisi_hha_pmu_v2_format_group = { ++ .name = "format", ++ .attrs = hisi_hha_pmu_v2_format_attr, ++}; ++ + static struct attribute *hisi_hha_pmu_v1_events_attr[] = { + HISI_PMU_EVENT_ATTR(rx_ops_num, 0x00), + HISI_PMU_EVENT_ATTR(rx_outer, 0x01), +@@ -255,6 +396,20 @@ static const struct attribute_group hisi_hha_pmu_v1_events_group = { + .attrs = hisi_hha_pmu_v1_events_attr, + }; + ++static struct attribute *hisi_hha_pmu_v2_events_attr[] = { ++ HISI_PMU_EVENT_ATTR(rx_ops_num, 0x00), ++ HISI_PMU_EVENT_ATTR(rx_outer, 0x01), ++ HISI_PMU_EVENT_ATTR(rx_sccl, 0x02), ++ HISI_PMU_EVENT_ATTR(hha_retry, 0x2e), ++ HISI_PMU_EVENT_ATTR(cycles, 0x55), ++ NULL ++}; ++ ++static const struct attribute_group hisi_hha_pmu_v2_events_group = { ++ .name = "events", ++ .attrs = hisi_hha_pmu_v2_events_attr, ++}; ++ + static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL); + + static struct attribute *hisi_hha_pmu_cpumask_attrs[] = { +@@ -286,6 +441,14 @@ static const struct attribute_group *hisi_hha_pmu_v1_attr_groups[] = { + NULL, + }; + ++static const struct attribute_group *hisi_hha_pmu_v2_attr_groups[] = { ++ &hisi_hha_pmu_v2_format_group, ++ &hisi_hha_pmu_v2_events_group, ++ &hisi_hha_pmu_cpumask_attr_group, ++ &hisi_hha_pmu_identifier_group, ++ NULL ++}; ++ + static const struct hisi_uncore_ops hisi_uncore_hha_ops = { + .write_evtype = hisi_hha_pmu_write_evtype, + .get_event_idx = hisi_uncore_pmu_get_event_idx, +@@ -299,6 +462,8 @@ static const struct hisi_uncore_ops hisi_uncore_hha_ops = { + .read_counter = hisi_hha_pmu_read_counter, + .get_int_status = hisi_hha_pmu_get_int_status, + .clear_int_status = hisi_hha_pmu_clear_int_status, ++ .enable_filter = hisi_hha_pmu_enable_filter, ++ .disable_filter = hisi_hha_pmu_disable_filter, + }; + + static int hisi_hha_pmu_dev_probe(struct platform_device *pdev, +@@ -314,12 +479,20 @@ static int hisi_hha_pmu_dev_probe(struct platform_device *pdev, + if (ret) + return ret; + +- hha_pmu->num_counters = HHA_V1_NR_COUNTERS; +- hha_pmu->counter_bits = 48; ++ if (hha_pmu->identifier >= HISI_PMU_V2) { ++ hha_pmu->counter_bits = 64; ++ hha_pmu->check_event = HHA_V2_NR_EVENT; ++ hha_pmu->pmu_events.attr_groups = hisi_hha_pmu_v2_attr_groups; ++ hha_pmu->num_counters = HHA_V2_NR_COUNTERS; ++ } else { ++ hha_pmu->counter_bits = 48; ++ hha_pmu->check_event = HHA_V1_NR_EVENT; ++ hha_pmu->pmu_events.attr_groups = hisi_hha_pmu_v1_attr_groups; ++ hha_pmu->num_counters = HHA_V1_NR_COUNTERS; ++ } + hha_pmu->ops = &hisi_uncore_hha_ops; + hha_pmu->dev = &pdev->dev; + hha_pmu->on_cpu = -1; +- hha_pmu->check_event = HHA_V1_NR_EVENT; + + return 0; + } +@@ -361,7 +534,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev) + .start = hisi_uncore_pmu_start, + .stop = hisi_uncore_pmu_stop, + .read = hisi_uncore_pmu_read, +- .attr_groups = hisi_hha_pmu_v1_attr_groups, ++ .attr_groups = hha_pmu->pmu_events.attr_groups, + .capabilities = PERF_PMU_CAP_NO_EXCLUDE, + }; + +-- +2.27.0 + diff --git a/patches/0059-drivers-perf-hisi-Update-DDRC-PMU-for-programmable-c.patch b/patches/0059-drivers-perf-hisi-Update-DDRC-PMU-for-programmable-c.patch new file mode 100644 index 0000000..255d8bc --- /dev/null +++ b/patches/0059-drivers-perf-hisi-Update-DDRC-PMU-for-programmable-c.patch @@ -0,0 +1,400 @@ +From c00401895e634812a41f81e20223244782e503a8 Mon Sep 17 00:00:00 2001 +From: Shaokun Zhang +Date: Fri, 30 Jul 2021 15:44:07 +0800 +Subject: [PATCH 18/55] drivers/perf: hisi: Update DDRC PMU for programmable + counter + +mainline inclusion +from mainline-v5.12-rc3 +commit cce03e702c9f26a43b16c51bf03029911feab692 +category: feature +bugzilla: 175148 +CVE: NA +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cce03e702c9f26a43b16c51bf03029911feab692 + +------------------------------------------------------------------------ + +DDRC PMU's events are useful for performance profiling, but the events +are limited and counter is fixed. On HiSilicon Hip09 platform, PMU +counters are the programmable and more events are supported. Let's +add the DDRC PMU v2 driver. + +Bandwidth events are exposed directly in driver and some more events +will listed in JSON file later. + +Cc: Mark Rutland +Cc: Will Deacon +Cc: John Garry +Cc: Jonathan Cameron +Reviewed-by: John Garry +Co-developed-by: Qi Liu +Signed-off-by: Qi Liu +Signed-off-by: Shaokun Zhang +Link: https://lore.kernel.org/r/1615186237-22263-7-git-send-email-zhangshaokun@hisilicon.com +Signed-off-by: Will Deacon +Reviewed-by: Shaokun Zhang +Signed-off-by: Zheng Zengkai +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 207 ++++++++++++++++-- + drivers/perf/hisilicon/hisi_uncore_pmu.h | 2 + + 2 files changed, 196 insertions(+), 13 deletions(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +index 1d1c8e9f417e..af5f8c16eab1 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +@@ -21,7 +21,7 @@ + + #include "hisi_uncore_pmu.h" + +-/* DDRC register definition */ ++/* DDRC register definition in v1 */ + #define DDRC_PERF_CTRL 0x010 + #define DDRC_FLUX_WR 0x380 + #define DDRC_FLUX_RD 0x384 +@@ -37,13 +37,24 @@ + #define DDRC_INT_CLEAR 0x6d0 + #define DDRC_VERSION 0x710 + ++/* DDRC register definition in v2 */ ++#define DDRC_V2_INT_MASK 0x528 ++#define DDRC_V2_INT_STATUS 0x52c ++#define DDRC_V2_INT_CLEAR 0x530 ++#define DDRC_V2_EVENT_CNT 0xe00 ++#define DDRC_V2_EVENT_CTRL 0xe70 ++#define DDRC_V2_EVENT_TYPE 0xe74 ++#define DDRC_V2_PERF_CTRL 0xeA0 ++ + /* DDRC has 8-counters */ + #define DDRC_NR_COUNTERS 0x8 + #define DDRC_V1_PERF_CTRL_EN 0x2 ++#define DDRC_V2_PERF_CTRL_EN 0x1 + #define DDRC_V1_NR_EVENTS 0x7 ++#define DDRC_V2_NR_EVENTS 0x90 + + /* +- * For DDRC PMU, there are eight-events and every event has been mapped ++ * For PMU v1, there are eight-events and every event has been mapped + * to fixed-purpose counters which register offset is not consistent. + * Therefore there is no write event type and we assume that event + * code (0 to 7) is equal to counter index in PMU driver. +@@ -65,6 +76,11 @@ static u32 hisi_ddrc_pmu_v1_get_counter_offset(int cntr_idx) + return ddrc_reg_off[cntr_idx]; + } + ++static u32 hisi_ddrc_pmu_v2_get_counter_offset(int cntr_idx) ++{ ++ return DDRC_V2_EVENT_CNT + cntr_idx * 8; ++} ++ + static u64 hisi_ddrc_pmu_v1_read_counter(struct hisi_pmu *ddrc_pmu, + struct hw_perf_event *hwc) + { +@@ -79,13 +95,34 @@ static void hisi_ddrc_pmu_v1_write_counter(struct hisi_pmu *ddrc_pmu, + ddrc_pmu->base + hisi_ddrc_pmu_v1_get_counter_offset(hwc->idx)); + } + ++static u64 hisi_ddrc_pmu_v2_read_counter(struct hisi_pmu *ddrc_pmu, ++ struct hw_perf_event *hwc) ++{ ++ return readq(ddrc_pmu->base + ++ hisi_ddrc_pmu_v2_get_counter_offset(hwc->idx)); ++} ++ ++static void hisi_ddrc_pmu_v2_write_counter(struct hisi_pmu *ddrc_pmu, ++ struct hw_perf_event *hwc, u64 val) ++{ ++ writeq(val, ++ ddrc_pmu->base + hisi_ddrc_pmu_v2_get_counter_offset(hwc->idx)); ++} ++ + /* +- * For DDRC PMU, event has been mapped to fixed-purpose counter by hardware, +- * so there is no need to write event type. ++ * For DDRC PMU v1, event has been mapped to fixed-purpose counter by hardware, ++ * so there is no need to write event type, while it is programmable counter in ++ * PMU v2. + */ + static void hisi_ddrc_pmu_write_evtype(struct hisi_pmu *hha_pmu, int idx, + u32 type) + { ++ u32 offset; ++ ++ if (hha_pmu->identifier >= HISI_PMU_V2) { ++ offset = DDRC_V2_EVENT_TYPE + 4 * idx; ++ writel(type, hha_pmu->base + offset); ++ } + } + + static void hisi_ddrc_pmu_v1_start_counters(struct hisi_pmu *ddrc_pmu) +@@ -146,6 +183,49 @@ static int hisi_ddrc_pmu_v1_get_event_idx(struct perf_event *event) + return idx; + } + ++static int hisi_ddrc_pmu_v2_get_event_idx(struct perf_event *event) ++{ ++ return hisi_uncore_pmu_get_event_idx(event); ++} ++ ++static void hisi_ddrc_pmu_v2_start_counters(struct hisi_pmu *ddrc_pmu) ++{ ++ u32 val; ++ ++ val = readl(ddrc_pmu->base + DDRC_V2_PERF_CTRL); ++ val |= DDRC_V2_PERF_CTRL_EN; ++ writel(val, ddrc_pmu->base + DDRC_V2_PERF_CTRL); ++} ++ ++static void hisi_ddrc_pmu_v2_stop_counters(struct hisi_pmu *ddrc_pmu) ++{ ++ u32 val; ++ ++ val = readl(ddrc_pmu->base + DDRC_V2_PERF_CTRL); ++ val &= ~DDRC_V2_PERF_CTRL_EN; ++ writel(val, ddrc_pmu->base + DDRC_V2_PERF_CTRL); ++} ++ ++static void hisi_ddrc_pmu_v2_enable_counter(struct hisi_pmu *ddrc_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ val = readl(ddrc_pmu->base + DDRC_V2_EVENT_CTRL); ++ val |= 1 << hwc->idx; ++ writel(val, ddrc_pmu->base + DDRC_V2_EVENT_CTRL); ++} ++ ++static void hisi_ddrc_pmu_v2_disable_counter(struct hisi_pmu *ddrc_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ val = readl(ddrc_pmu->base + DDRC_V2_EVENT_CTRL); ++ val &= ~(1 << hwc->idx); ++ writel(val, ddrc_pmu->base + DDRC_V2_EVENT_CTRL); ++} ++ + static void hisi_ddrc_pmu_v1_enable_counter_int(struct hisi_pmu *ddrc_pmu, + struct hw_perf_event *hwc) + { +@@ -153,7 +233,7 @@ static void hisi_ddrc_pmu_v1_enable_counter_int(struct hisi_pmu *ddrc_pmu, + + /* Write 0 to enable interrupt */ + val = readl(ddrc_pmu->base + DDRC_INT_MASK); +- val &= ~(1 << GET_DDRC_EVENTID(hwc)); ++ val &= ~(1 << hwc->idx); + writel(val, ddrc_pmu->base + DDRC_INT_MASK); + } + +@@ -164,10 +244,30 @@ static void hisi_ddrc_pmu_v1_disable_counter_int(struct hisi_pmu *ddrc_pmu, + + /* Write 1 to mask interrupt */ + val = readl(ddrc_pmu->base + DDRC_INT_MASK); +- val |= (1 << GET_DDRC_EVENTID(hwc)); ++ val |= 1 << hwc->idx; + writel(val, ddrc_pmu->base + DDRC_INT_MASK); + } + ++static void hisi_ddrc_pmu_v2_enable_counter_int(struct hisi_pmu *ddrc_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ val = readl(ddrc_pmu->base + DDRC_V2_INT_MASK); ++ val &= ~(1 << hwc->idx); ++ writel(val, ddrc_pmu->base + DDRC_V2_INT_MASK); ++} ++ ++static void hisi_ddrc_pmu_v2_disable_counter_int(struct hisi_pmu *ddrc_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ val = readl(ddrc_pmu->base + DDRC_V2_INT_MASK); ++ val |= 1 << hwc->idx; ++ writel(val, ddrc_pmu->base + DDRC_V2_INT_MASK); ++} ++ + static u32 hisi_ddrc_pmu_v1_get_int_status(struct hisi_pmu *ddrc_pmu) + { + return readl(ddrc_pmu->base + DDRC_INT_STATUS); +@@ -179,9 +279,21 @@ static void hisi_ddrc_pmu_v1_clear_int_status(struct hisi_pmu *ddrc_pmu, + writel(1 << idx, ddrc_pmu->base + DDRC_INT_CLEAR); + } + ++static u32 hisi_ddrc_pmu_v2_get_int_status(struct hisi_pmu *ddrc_pmu) ++{ ++ return readl(ddrc_pmu->base + DDRC_V2_INT_STATUS); ++} ++ ++static void hisi_ddrc_pmu_v2_clear_int_status(struct hisi_pmu *ddrc_pmu, ++ int idx) ++{ ++ writel(1 << idx, ddrc_pmu->base + DDRC_V2_INT_CLEAR); ++} ++ + static const struct acpi_device_id hisi_ddrc_pmu_acpi_match[] = { + { "HISI0233", }, +- {}, ++ { "HISI0234", }, ++ {} + }; + MODULE_DEVICE_TABLE(acpi, hisi_ddrc_pmu_acpi_match); + +@@ -213,6 +325,13 @@ static int hisi_ddrc_pmu_init_data(struct platform_device *pdev, + } + + ddrc_pmu->identifier = readl(ddrc_pmu->base + DDRC_VERSION); ++ if (ddrc_pmu->identifier >= HISI_PMU_V2) { ++ if (device_property_read_u32(&pdev->dev, "hisilicon,sub-id", ++ &ddrc_pmu->sub_id)) { ++ dev_err(&pdev->dev, "Can not read sub-id!\n"); ++ return -EINVAL; ++ } ++ } + + return 0; + } +@@ -227,6 +346,16 @@ static const struct attribute_group hisi_ddrc_pmu_v1_format_group = { + .attrs = hisi_ddrc_pmu_v1_format_attr, + }; + ++static struct attribute *hisi_ddrc_pmu_v2_format_attr[] = { ++ HISI_PMU_FORMAT_ATTR(event, "config:0-7"), ++ NULL ++}; ++ ++static const struct attribute_group hisi_ddrc_pmu_v2_format_group = { ++ .name = "format", ++ .attrs = hisi_ddrc_pmu_v2_format_attr, ++}; ++ + static struct attribute *hisi_ddrc_pmu_v1_events_attr[] = { + HISI_PMU_EVENT_ATTR(flux_wr, 0x00), + HISI_PMU_EVENT_ATTR(flux_rd, 0x01), +@@ -244,6 +373,18 @@ static const struct attribute_group hisi_ddrc_pmu_v1_events_group = { + .attrs = hisi_ddrc_pmu_v1_events_attr, + }; + ++static struct attribute *hisi_ddrc_pmu_v2_events_attr[] = { ++ HISI_PMU_EVENT_ATTR(cycles, 0x00), ++ HISI_PMU_EVENT_ATTR(flux_wr, 0x83), ++ HISI_PMU_EVENT_ATTR(flux_rd, 0x84), ++ NULL ++}; ++ ++static const struct attribute_group hisi_ddrc_pmu_v2_events_group = { ++ .name = "events", ++ .attrs = hisi_ddrc_pmu_v2_events_attr, ++}; ++ + static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL); + + static struct attribute *hisi_ddrc_pmu_cpumask_attrs[] = { +@@ -275,6 +416,14 @@ static const struct attribute_group *hisi_ddrc_pmu_v1_attr_groups[] = { + NULL, + }; + ++static const struct attribute_group *hisi_ddrc_pmu_v2_attr_groups[] = { ++ &hisi_ddrc_pmu_v2_format_group, ++ &hisi_ddrc_pmu_v2_events_group, ++ &hisi_ddrc_pmu_cpumask_attr_group, ++ &hisi_ddrc_pmu_identifier_group, ++ NULL ++}; ++ + static const struct hisi_uncore_ops hisi_uncore_ddrc_v1_ops = { + .write_evtype = hisi_ddrc_pmu_write_evtype, + .get_event_idx = hisi_ddrc_pmu_v1_get_event_idx, +@@ -290,6 +439,21 @@ static const struct hisi_uncore_ops hisi_uncore_ddrc_v1_ops = { + .clear_int_status = hisi_ddrc_pmu_v1_clear_int_status, + }; + ++static const struct hisi_uncore_ops hisi_uncore_ddrc_v2_ops = { ++ .write_evtype = hisi_ddrc_pmu_write_evtype, ++ .get_event_idx = hisi_ddrc_pmu_v2_get_event_idx, ++ .start_counters = hisi_ddrc_pmu_v2_start_counters, ++ .stop_counters = hisi_ddrc_pmu_v2_stop_counters, ++ .enable_counter = hisi_ddrc_pmu_v2_enable_counter, ++ .disable_counter = hisi_ddrc_pmu_v2_disable_counter, ++ .enable_counter_int = hisi_ddrc_pmu_v2_enable_counter_int, ++ .disable_counter_int = hisi_ddrc_pmu_v2_disable_counter_int, ++ .write_counter = hisi_ddrc_pmu_v2_write_counter, ++ .read_counter = hisi_ddrc_pmu_v2_read_counter, ++ .get_int_status = hisi_ddrc_pmu_v2_get_int_status, ++ .clear_int_status = hisi_ddrc_pmu_v2_clear_int_status, ++}; ++ + static int hisi_ddrc_pmu_dev_probe(struct platform_device *pdev, + struct hisi_pmu *ddrc_pmu) + { +@@ -303,12 +467,21 @@ static int hisi_ddrc_pmu_dev_probe(struct platform_device *pdev, + if (ret) + return ret; + ++ if (ddrc_pmu->identifier >= HISI_PMU_V2) { ++ ddrc_pmu->counter_bits = 48; ++ ddrc_pmu->check_event = DDRC_V2_NR_EVENTS; ++ ddrc_pmu->pmu_events.attr_groups = hisi_ddrc_pmu_v2_attr_groups; ++ ddrc_pmu->ops = &hisi_uncore_ddrc_v2_ops; ++ } else { ++ ddrc_pmu->counter_bits = 32; ++ ddrc_pmu->check_event = DDRC_V1_NR_EVENTS; ++ ddrc_pmu->pmu_events.attr_groups = hisi_ddrc_pmu_v1_attr_groups; ++ ddrc_pmu->ops = &hisi_uncore_ddrc_v1_ops; ++ } ++ + ddrc_pmu->num_counters = DDRC_NR_COUNTERS; +- ddrc_pmu->counter_bits = 32; +- ddrc_pmu->ops = &hisi_uncore_ddrc_v1_ops; + ddrc_pmu->dev = &pdev->dev; + ddrc_pmu->on_cpu = -1; +- ddrc_pmu->check_event = DDRC_V1_NR_EVENTS; + + return 0; + } +@@ -336,8 +509,16 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev) + return ret; + } + +- name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_ddrc%u", +- ddrc_pmu->sccl_id, ddrc_pmu->index_id); ++ if (ddrc_pmu->identifier >= HISI_PMU_V2) ++ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, ++ "hisi_sccl%u_ddrc%u_%u", ++ ddrc_pmu->sccl_id, ddrc_pmu->index_id, ++ ddrc_pmu->sub_id); ++ else ++ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, ++ "hisi_sccl%u_ddrc%u", ddrc_pmu->sccl_id, ++ ddrc_pmu->index_id); ++ + ddrc_pmu->pmu = (struct pmu) { + .name = name, + .module = THIS_MODULE, +@@ -350,7 +531,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev) + .start = hisi_uncore_pmu_start, + .stop = hisi_uncore_pmu_stop, + .read = hisi_uncore_pmu_read, +- .attr_groups = hisi_ddrc_pmu_v1_attr_groups, ++ .attr_groups = ddrc_pmu->pmu_events.attr_groups, + .capabilities = PERF_PMU_CAP_NO_EXCLUDE, + }; + +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h +index 1147dbd25344..de6aa17a1355 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h +@@ -88,6 +88,8 @@ struct hisi_pmu { + void __iomem *base; + /* the ID of the PMU modules */ + u32 index_id; ++ /* For DDRC PMU v2: each DDRC has more than one DMC */ ++ u32 sub_id; + int num_counters; + int counter_bits; + /* check event code range */ +-- +2.27.0 + diff --git a/patches/0060-drivers-perf-hisi-Add-support-for-HiSilicon-SLLC-PMU.patch b/patches/0060-drivers-perf-hisi-Add-support-for-HiSilicon-SLLC-PMU.patch new file mode 100644 index 0000000..7844bce --- /dev/null +++ b/patches/0060-drivers-perf-hisi-Add-support-for-HiSilicon-SLLC-PMU.patch @@ -0,0 +1,618 @@ +From 16c054f4640b9f7c21bb784ac54e1ea32ac65df0 Mon Sep 17 00:00:00 2001 +From: Shaokun Zhang +Date: Fri, 30 Jul 2021 15:44:08 +0800 +Subject: [PATCH 19/55] drivers/perf: hisi: Add support for HiSilicon SLLC PMU + driver + +mainline inclusion +from mainline-v5.12-rc3 +commit 3bf30882c3c7b6e376d9d6d04082c9aa2d2ac30a +category: feature +bugzilla: 175148 +CVE: NA +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3bf30882c3c7b6e376d9d6d04082c9aa2d2ac30a + +------------------------------------------------------------------------ + +HiSilicon's Hip09 is comprised by multi-dies that can be connected by SLLC +module (Skyros Link Layer Controller), its has separate PMU registers which +the driver can program it freely and interrupt is supported to handle +counter overflow. Let's support its driver under the framework of HiSilicon +uncore PMU driver. + +SLLC PMU supports the following filter functions: +* tracetag_en: allows user to count data according to tt_req or +tt_core set in L3C PMU. + +* srcid_cmd & srcid_msk: allows user to filter statistics that come from +specific CCL/ICL by configuration source ID. + +* tgtid_hi & tgtid_lo: it also supports event statistics that these +operations will go to the CCL/ICL by configuration target ID or +target ID range. It's the same as source ID with 11-bit width in +the SoC. More introduction is added in documentation: +Documentation/admin-guide/perf/hisi-pmu.rst + +Cc: Mark Rutland +Cc: Will Deacon +Cc: John Garry +Cc: Jonathan Cameron +Reviewed-by: John Garry +Co-developed-by: Qi Liu +Signed-off-by: Qi Liu +Signed-off-by: Shaokun Zhang +Link: https://lore.kernel.org/r/1615186237-22263-8-git-send-email-zhangshaokun@hisilicon.com +Signed-off-by: Will Deacon +Reviewed-by: Shaokun Zhang +Signed-off-by: Zheng Zengkai +Signed-off-by: hongrongxuan + + Conflicts: + drivers/perf/hisilicon/Makefile +--- + drivers/perf/hisilicon/Makefile | 4 +- + drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 530 ++++++++++++++++++ + include/linux/cpuhotplug.h | 1 + + 3 files changed, 534 insertions(+), 1 deletion(-) + create mode 100644 drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c + +diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile +index 2621d51ae87a..6600a9d45dd8 100644 +--- a/drivers/perf/hisilicon/Makefile ++++ b/drivers/perf/hisilicon/Makefile +@@ -1 +1,3 @@ +-obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o ++# SPDX-License-Identifier: GPL-2.0-only ++obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o \ ++ hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_sllc_pmu.o +diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c +new file mode 100644 +index 000000000000..46be312fa126 +--- /dev/null ++++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c +@@ -0,0 +1,530 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * HiSilicon SLLC uncore Hardware event counters support ++ * ++ * Copyright (C) 2020 Hisilicon Limited ++ * Author: Shaokun Zhang ++ * ++ * This code is based on the uncore PMUs like arm-cci and arm-ccn. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hisi_uncore_pmu.h" ++ ++/* SLLC register definition */ ++#define SLLC_INT_MASK 0x0814 ++#define SLLC_INT_STATUS 0x0818 ++#define SLLC_INT_CLEAR 0x081c ++#define SLLC_PERF_CTRL 0x1c00 ++#define SLLC_SRCID_CTRL 0x1c04 ++#define SLLC_TGTID_CTRL 0x1c08 ++#define SLLC_EVENT_CTRL 0x1c14 ++#define SLLC_EVENT_TYPE0 0x1c18 ++#define SLLC_VERSION 0x1cf0 ++#define SLLC_EVENT_CNT0_L 0x1d00 ++ ++#define SLLC_EVTYPE_MASK 0xff ++#define SLLC_PERF_CTRL_EN BIT(0) ++#define SLLC_FILT_EN BIT(1) ++#define SLLC_TRACETAG_EN BIT(2) ++#define SLLC_SRCID_EN BIT(4) ++#define SLLC_SRCID_NONE 0x0 ++#define SLLC_TGTID_EN BIT(5) ++#define SLLC_TGTID_NONE 0x0 ++#define SLLC_TGTID_MIN_SHIFT 1 ++#define SLLC_TGTID_MAX_SHIFT 12 ++#define SLLC_SRCID_CMD_SHIFT 1 ++#define SLLC_SRCID_MSK_SHIFT 12 ++#define SLLC_NR_EVENTS 0x80 ++ ++HISI_PMU_EVENT_ATTR_EXTRACTOR(tgtid_min, config1, 10, 0); ++HISI_PMU_EVENT_ATTR_EXTRACTOR(tgtid_max, config1, 21, 11); ++HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_cmd, config1, 32, 22); ++HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_msk, config1, 43, 33); ++HISI_PMU_EVENT_ATTR_EXTRACTOR(tracetag_en, config1, 44, 44); ++ ++static bool tgtid_is_valid(u32 max, u32 min) ++{ ++ return max > 0 && max >= min; ++} ++ ++static void hisi_sllc_pmu_enable_tracetag(struct perf_event *event) ++{ ++ struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu); ++ u32 tt_en = hisi_get_tracetag_en(event); ++ ++ if (tt_en) { ++ u32 val; ++ ++ val = readl(sllc_pmu->base + SLLC_PERF_CTRL); ++ val |= SLLC_TRACETAG_EN | SLLC_FILT_EN; ++ writel(val, sllc_pmu->base + SLLC_PERF_CTRL); ++ } ++} ++ ++static void hisi_sllc_pmu_disable_tracetag(struct perf_event *event) ++{ ++ struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu); ++ u32 tt_en = hisi_get_tracetag_en(event); ++ ++ if (tt_en) { ++ u32 val; ++ ++ val = readl(sllc_pmu->base + SLLC_PERF_CTRL); ++ val &= ~(SLLC_TRACETAG_EN | SLLC_FILT_EN); ++ writel(val, sllc_pmu->base + SLLC_PERF_CTRL); ++ } ++} ++ ++static void hisi_sllc_pmu_config_tgtid(struct perf_event *event) ++{ ++ struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu); ++ u32 min = hisi_get_tgtid_min(event); ++ u32 max = hisi_get_tgtid_max(event); ++ ++ if (tgtid_is_valid(max, min)) { ++ u32 val = (max << SLLC_TGTID_MAX_SHIFT) | (min << SLLC_TGTID_MIN_SHIFT); ++ ++ writel(val, sllc_pmu->base + SLLC_TGTID_CTRL); ++ /* Enable the tgtid */ ++ val = readl(sllc_pmu->base + SLLC_PERF_CTRL); ++ val |= SLLC_TGTID_EN | SLLC_FILT_EN; ++ writel(val, sllc_pmu->base + SLLC_PERF_CTRL); ++ } ++} ++ ++static void hisi_sllc_pmu_clear_tgtid(struct perf_event *event) ++{ ++ struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu); ++ u32 min = hisi_get_tgtid_min(event); ++ u32 max = hisi_get_tgtid_max(event); ++ ++ if (tgtid_is_valid(max, min)) { ++ u32 val; ++ ++ writel(SLLC_TGTID_NONE, sllc_pmu->base + SLLC_TGTID_CTRL); ++ /* Disable the tgtid */ ++ val = readl(sllc_pmu->base + SLLC_PERF_CTRL); ++ val &= ~(SLLC_TGTID_EN | SLLC_FILT_EN); ++ writel(val, sllc_pmu->base + SLLC_PERF_CTRL); ++ } ++} ++ ++static void hisi_sllc_pmu_config_srcid(struct perf_event *event) ++{ ++ struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu); ++ u32 cmd = hisi_get_srcid_cmd(event); ++ ++ if (cmd) { ++ u32 val, msk; ++ ++ msk = hisi_get_srcid_msk(event); ++ val = (cmd << SLLC_SRCID_CMD_SHIFT) | (msk << SLLC_SRCID_MSK_SHIFT); ++ writel(val, sllc_pmu->base + SLLC_SRCID_CTRL); ++ /* Enable the srcid */ ++ val = readl(sllc_pmu->base + SLLC_PERF_CTRL); ++ val |= SLLC_SRCID_EN | SLLC_FILT_EN; ++ writel(val, sllc_pmu->base + SLLC_PERF_CTRL); ++ } ++} ++ ++static void hisi_sllc_pmu_clear_srcid(struct perf_event *event) ++{ ++ struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu); ++ u32 cmd = hisi_get_srcid_cmd(event); ++ ++ if (cmd) { ++ u32 val; ++ ++ writel(SLLC_SRCID_NONE, sllc_pmu->base + SLLC_SRCID_CTRL); ++ /* Disable the srcid */ ++ val = readl(sllc_pmu->base + SLLC_PERF_CTRL); ++ val &= ~(SLLC_SRCID_EN | SLLC_FILT_EN); ++ writel(val, sllc_pmu->base + SLLC_PERF_CTRL); ++ } ++} ++ ++static void hisi_sllc_pmu_enable_filter(struct perf_event *event) ++{ ++ if (event->attr.config1 != 0x0) { ++ hisi_sllc_pmu_enable_tracetag(event); ++ hisi_sllc_pmu_config_srcid(event); ++ hisi_sllc_pmu_config_tgtid(event); ++ } ++} ++ ++static void hisi_sllc_pmu_clear_filter(struct perf_event *event) ++{ ++ if (event->attr.config1 != 0x0) { ++ hisi_sllc_pmu_disable_tracetag(event); ++ hisi_sllc_pmu_clear_srcid(event); ++ hisi_sllc_pmu_clear_tgtid(event); ++ } ++} ++ ++static u32 hisi_sllc_pmu_get_counter_offset(int idx) ++{ ++ return (SLLC_EVENT_CNT0_L + idx * 8); ++} ++ ++static u64 hisi_sllc_pmu_read_counter(struct hisi_pmu *sllc_pmu, ++ struct hw_perf_event *hwc) ++{ ++ return readq(sllc_pmu->base + ++ hisi_sllc_pmu_get_counter_offset(hwc->idx)); ++} ++ ++static void hisi_sllc_pmu_write_counter(struct hisi_pmu *sllc_pmu, ++ struct hw_perf_event *hwc, u64 val) ++{ ++ writeq(val, sllc_pmu->base + ++ hisi_sllc_pmu_get_counter_offset(hwc->idx)); ++} ++ ++static void hisi_sllc_pmu_write_evtype(struct hisi_pmu *sllc_pmu, int idx, ++ u32 type) ++{ ++ u32 reg, reg_idx, shift, val; ++ ++ /* ++ * Select the appropriate event select register(SLLC_EVENT_TYPE0/1). ++ * There are 2 event select registers for the 8 hardware counters. ++ * Event code is 8-bits and for the former 4 hardware counters, ++ * SLLC_EVENT_TYPE0 is chosen. For the latter 4 hardware counters, ++ * SLLC_EVENT_TYPE1 is chosen. ++ */ ++ reg = SLLC_EVENT_TYPE0 + (idx / 4) * 4; ++ reg_idx = idx % 4; ++ shift = 8 * reg_idx; ++ ++ /* Write event code to SLLC_EVENT_TYPEx Register */ ++ val = readl(sllc_pmu->base + reg); ++ val &= ~(SLLC_EVTYPE_MASK << shift); ++ val |= (type << shift); ++ writel(val, sllc_pmu->base + reg); ++} ++ ++static void hisi_sllc_pmu_start_counters(struct hisi_pmu *sllc_pmu) ++{ ++ u32 val; ++ ++ val = readl(sllc_pmu->base + SLLC_PERF_CTRL); ++ val |= SLLC_PERF_CTRL_EN; ++ writel(val, sllc_pmu->base + SLLC_PERF_CTRL); ++} ++ ++static void hisi_sllc_pmu_stop_counters(struct hisi_pmu *sllc_pmu) ++{ ++ u32 val; ++ ++ val = readl(sllc_pmu->base + SLLC_PERF_CTRL); ++ val &= ~(SLLC_PERF_CTRL_EN); ++ writel(val, sllc_pmu->base + SLLC_PERF_CTRL); ++} ++ ++static void hisi_sllc_pmu_enable_counter(struct hisi_pmu *sllc_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ val = readl(sllc_pmu->base + SLLC_EVENT_CTRL); ++ val |= 1 << hwc->idx; ++ writel(val, sllc_pmu->base + SLLC_EVENT_CTRL); ++} ++ ++static void hisi_sllc_pmu_disable_counter(struct hisi_pmu *sllc_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ val = readl(sllc_pmu->base + SLLC_EVENT_CTRL); ++ val &= ~(1 << hwc->idx); ++ writel(val, sllc_pmu->base + SLLC_EVENT_CTRL); ++} ++ ++static void hisi_sllc_pmu_enable_counter_int(struct hisi_pmu *sllc_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ val = readl(sllc_pmu->base + SLLC_INT_MASK); ++ /* Write 0 to enable interrupt */ ++ val &= ~(1 << hwc->idx); ++ writel(val, sllc_pmu->base + SLLC_INT_MASK); ++} ++ ++static void hisi_sllc_pmu_disable_counter_int(struct hisi_pmu *sllc_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ val = readl(sllc_pmu->base + SLLC_INT_MASK); ++ /* Write 1 to mask interrupt */ ++ val |= 1 << hwc->idx; ++ writel(val, sllc_pmu->base + SLLC_INT_MASK); ++} ++ ++static u32 hisi_sllc_pmu_get_int_status(struct hisi_pmu *sllc_pmu) ++{ ++ return readl(sllc_pmu->base + SLLC_INT_STATUS); ++} ++ ++static void hisi_sllc_pmu_clear_int_status(struct hisi_pmu *sllc_pmu, int idx) ++{ ++ writel(1 << idx, sllc_pmu->base + SLLC_INT_CLEAR); ++} ++ ++static const struct acpi_device_id hisi_sllc_pmu_acpi_match[] = { ++ { "HISI0263", }, ++ {} ++}; ++MODULE_DEVICE_TABLE(acpi, hisi_sllc_pmu_acpi_match); ++ ++static int hisi_sllc_pmu_init_data(struct platform_device *pdev, ++ struct hisi_pmu *sllc_pmu) ++{ ++ /* ++ * Use the SCCL_ID and the index ID to identify the SLLC PMU, ++ * while SCCL_ID is from MPIDR_EL1 by CPU. ++ */ ++ if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id", ++ &sllc_pmu->sccl_id)) { ++ dev_err(&pdev->dev, "Cannot read sccl-id!\n"); ++ return -EINVAL; ++ } ++ ++ if (device_property_read_u32(&pdev->dev, "hisilicon,idx-id", ++ &sllc_pmu->index_id)) { ++ dev_err(&pdev->dev, "Cannot read idx-id!\n"); ++ return -EINVAL; ++ } ++ ++ /* SLLC PMUs only share the same SCCL */ ++ sllc_pmu->ccl_id = -1; ++ ++ sllc_pmu->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(sllc_pmu->base)) { ++ dev_err(&pdev->dev, "ioremap failed for sllc_pmu resource.\n"); ++ return PTR_ERR(sllc_pmu->base); ++ } ++ ++ sllc_pmu->identifier = readl(sllc_pmu->base + SLLC_VERSION); ++ ++ return 0; ++} ++ ++static struct attribute *hisi_sllc_pmu_v2_format_attr[] = { ++ HISI_PMU_FORMAT_ATTR(event, "config:0-7"), ++ HISI_PMU_FORMAT_ATTR(tgtid_min, "config1:0-10"), ++ HISI_PMU_FORMAT_ATTR(tgtid_max, "config1:11-21"), ++ HISI_PMU_FORMAT_ATTR(srcid_cmd, "config1:22-32"), ++ HISI_PMU_FORMAT_ATTR(srcid_msk, "config1:33-43"), ++ HISI_PMU_FORMAT_ATTR(tracetag_en, "config1:44"), ++ NULL ++}; ++ ++static const struct attribute_group hisi_sllc_pmu_v2_format_group = { ++ .name = "format", ++ .attrs = hisi_sllc_pmu_v2_format_attr, ++}; ++ ++static struct attribute *hisi_sllc_pmu_v2_events_attr[] = { ++ HISI_PMU_EVENT_ATTR(rx_req, 0x30), ++ HISI_PMU_EVENT_ATTR(rx_data, 0x31), ++ HISI_PMU_EVENT_ATTR(tx_req, 0x34), ++ HISI_PMU_EVENT_ATTR(tx_data, 0x35), ++ HISI_PMU_EVENT_ATTR(cycles, 0x09), ++ NULL ++}; ++ ++static const struct attribute_group hisi_sllc_pmu_v2_events_group = { ++ .name = "events", ++ .attrs = hisi_sllc_pmu_v2_events_attr, ++}; ++ ++static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL); ++ ++static struct attribute *hisi_sllc_pmu_cpumask_attrs[] = { ++ &dev_attr_cpumask.attr, ++ NULL ++}; ++ ++static const struct attribute_group hisi_sllc_pmu_cpumask_attr_group = { ++ .attrs = hisi_sllc_pmu_cpumask_attrs, ++}; ++ ++static struct device_attribute hisi_sllc_pmu_identifier_attr = ++ __ATTR(identifier, 0444, hisi_uncore_pmu_identifier_attr_show, NULL); ++ ++static struct attribute *hisi_sllc_pmu_identifier_attrs[] = { ++ &hisi_sllc_pmu_identifier_attr.attr, ++ NULL ++}; ++ ++static struct attribute_group hisi_sllc_pmu_identifier_group = { ++ .attrs = hisi_sllc_pmu_identifier_attrs, ++}; ++ ++static const struct attribute_group *hisi_sllc_pmu_v2_attr_groups[] = { ++ &hisi_sllc_pmu_v2_format_group, ++ &hisi_sllc_pmu_v2_events_group, ++ &hisi_sllc_pmu_cpumask_attr_group, ++ &hisi_sllc_pmu_identifier_group, ++ NULL ++}; ++ ++static const struct hisi_uncore_ops hisi_uncore_sllc_ops = { ++ .write_evtype = hisi_sllc_pmu_write_evtype, ++ .get_event_idx = hisi_uncore_pmu_get_event_idx, ++ .start_counters = hisi_sllc_pmu_start_counters, ++ .stop_counters = hisi_sllc_pmu_stop_counters, ++ .enable_counter = hisi_sllc_pmu_enable_counter, ++ .disable_counter = hisi_sllc_pmu_disable_counter, ++ .enable_counter_int = hisi_sllc_pmu_enable_counter_int, ++ .disable_counter_int = hisi_sllc_pmu_disable_counter_int, ++ .write_counter = hisi_sllc_pmu_write_counter, ++ .read_counter = hisi_sllc_pmu_read_counter, ++ .get_int_status = hisi_sllc_pmu_get_int_status, ++ .clear_int_status = hisi_sllc_pmu_clear_int_status, ++ .enable_filter = hisi_sllc_pmu_enable_filter, ++ .disable_filter = hisi_sllc_pmu_clear_filter, ++}; ++ ++static int hisi_sllc_pmu_dev_probe(struct platform_device *pdev, ++ struct hisi_pmu *sllc_pmu) ++{ ++ int ret; ++ ++ ret = hisi_sllc_pmu_init_data(pdev, sllc_pmu); ++ if (ret) ++ return ret; ++ ++ ret = hisi_uncore_pmu_init_irq(sllc_pmu, pdev); ++ if (ret) ++ return ret; ++ ++ sllc_pmu->pmu_events.attr_groups = hisi_sllc_pmu_v2_attr_groups; ++ sllc_pmu->ops = &hisi_uncore_sllc_ops; ++ sllc_pmu->check_event = SLLC_NR_EVENTS; ++ sllc_pmu->counter_bits = 64; ++ sllc_pmu->num_counters = 8; ++ sllc_pmu->dev = &pdev->dev; ++ sllc_pmu->on_cpu = -1; ++ ++ return 0; ++} ++ ++static int hisi_sllc_pmu_probe(struct platform_device *pdev) ++{ ++ struct hisi_pmu *sllc_pmu; ++ char *name; ++ int ret; ++ ++ sllc_pmu = devm_kzalloc(&pdev->dev, sizeof(*sllc_pmu), GFP_KERNEL); ++ if (!sllc_pmu) ++ return -ENOMEM; ++ ++ ret = hisi_sllc_pmu_dev_probe(pdev, sllc_pmu); ++ if (ret) ++ return ret; ++ ++ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_sllc%u", ++ sllc_pmu->sccl_id, sllc_pmu->index_id); ++ if (!name) ++ return -ENOMEM; ++ ++ ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE, ++ &sllc_pmu->node); ++ if (ret) { ++ dev_err(&pdev->dev, "Error %d registering hotplug\n", ret); ++ return ret; ++ } ++ ++ sllc_pmu->pmu = (struct pmu) { ++ .module = THIS_MODULE, ++ .task_ctx_nr = perf_invalid_context, ++ .event_init = hisi_uncore_pmu_event_init, ++ .pmu_enable = hisi_uncore_pmu_enable, ++ .pmu_disable = hisi_uncore_pmu_disable, ++ .add = hisi_uncore_pmu_add, ++ .del = hisi_uncore_pmu_del, ++ .start = hisi_uncore_pmu_start, ++ .stop = hisi_uncore_pmu_stop, ++ .read = hisi_uncore_pmu_read, ++ .attr_groups = sllc_pmu->pmu_events.attr_groups, ++ .capabilities = PERF_PMU_CAP_NO_EXCLUDE, ++ }; ++ ++ ret = perf_pmu_register(&sllc_pmu->pmu, name, -1); ++ if (ret) { ++ dev_err(sllc_pmu->dev, "PMU register failed, ret = %d\n", ret); ++ cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE, ++ &sllc_pmu->node); ++ irq_set_affinity_hint(sllc_pmu->irq, NULL); ++ return ret; ++ } ++ ++ platform_set_drvdata(pdev, sllc_pmu); ++ ++ return ret; ++} ++ ++static int hisi_sllc_pmu_remove(struct platform_device *pdev) ++{ ++ struct hisi_pmu *sllc_pmu = platform_get_drvdata(pdev); ++ ++ perf_pmu_unregister(&sllc_pmu->pmu); ++ cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE, ++ &sllc_pmu->node); ++ irq_set_affinity_hint(sllc_pmu->irq, NULL); ++ ++ return 0; ++} ++ ++static struct platform_driver hisi_sllc_pmu_driver = { ++ .driver = { ++ .name = "hisi_sllc_pmu", ++ .acpi_match_table = hisi_sllc_pmu_acpi_match, ++ .suppress_bind_attrs = true, ++ }, ++ .probe = hisi_sllc_pmu_probe, ++ .remove = hisi_sllc_pmu_remove, ++}; ++ ++static int __init hisi_sllc_pmu_module_init(void) ++{ ++ int ret; ++ ++ ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE, ++ "AP_PERF_ARM_HISI_SLLC_ONLINE", ++ hisi_uncore_pmu_online_cpu, ++ hisi_uncore_pmu_offline_cpu); ++ if (ret) { ++ pr_err("SLLC PMU: cpuhp state setup failed, ret = %d\n", ret); ++ return ret; ++ } ++ ++ ret = platform_driver_register(&hisi_sllc_pmu_driver); ++ if (ret) ++ cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE); ++ ++ return ret; ++} ++module_init(hisi_sllc_pmu_module_init); ++ ++static void __exit hisi_sllc_pmu_module_exit(void) ++{ ++ platform_driver_unregister(&hisi_sllc_pmu_driver); ++ cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE); ++} ++module_exit(hisi_sllc_pmu_module_exit); ++ ++MODULE_DESCRIPTION("HiSilicon SLLC uncore PMU driver"); ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Shaokun Zhang "); ++MODULE_AUTHOR("Qi Liu "); +diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h +index d67c0035165c..b5c55a408a30 100644 +--- a/include/linux/cpuhotplug.h ++++ b/include/linux/cpuhotplug.h +@@ -161,6 +161,7 @@ enum cpuhp_state { + CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE, + CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE, + CPUHP_AP_PERF_ARM_HISI_L3_ONLINE, ++ CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE, + CPUHP_AP_PERF_ARM_L2X0_ONLINE, + CPUHP_AP_PERF_ARM_QCOM_L2_ONLINE, + CPUHP_AP_PERF_ARM_QCOM_L3_ONLINE, +-- +2.27.0 + diff --git a/patches/0061-drivers-perf-hisi-Add-support-for-HiSilicon-PA-PMU-d.patch b/patches/0061-drivers-perf-hisi-Add-support-for-HiSilicon-PA-PMU-d.patch new file mode 100644 index 0000000..e569c5b --- /dev/null +++ b/patches/0061-drivers-perf-hisi-Add-support-for-HiSilicon-PA-PMU-d.patch @@ -0,0 +1,584 @@ +From 71cf98350d1423660b390740a190ce8a98502c37 Mon Sep 17 00:00:00 2001 +From: Shaokun Zhang +Date: Fri, 30 Jul 2021 15:44:09 +0800 +Subject: [PATCH 20/55] drivers/perf: hisi: Add support for HiSilicon PA PMU + driver + +mainline inclusion +from mainline-v5.12-rc3 +commit a0ab25cd82eeb68bfa19a4d93a097521af5011b8 +category: feature +bugzilla: 175148 +CVE: NA +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a0ab25cd82eeb68bfa19a4d93a097521af5011b8 + +------------------------------------------------------------------------ + +On HiSilicon Hip09 platform, there is a PA (Protocol Adapter) module on +each chip SICL (Super I/O Cluster) which incorporates three Hydra interface +and facilitates the cache coherency between the dies on the chip. While PA +uncore PMU model is the same as other Hip09 PMU modules and many PMU events +are supported. Let's support the PMU driver using the HiSilicon uncore PMU +framework. + +PA PMU supports the following filter functions: +* tracetag_en: allows user to count events according to tt_req or +tt_core set in L3C PMU. It's the same as other PMUs. + +* srcid_cmd & srcid_msk: allows user to filter statistics that come from +specific CCL/ICL by configuration source ID. + +* tgtid_cmd & tgtid_msk: it is the similar function to srcid_cmd & +srcid_msk. Both are used to check where the data comes from or go to. + +Cc: Mark Rutland +Cc: Will Deacon +Cc: John Garry +Cc: Jonathan Cameron +Reviewed-by: John Garry +Co-developed-by: Qi Liu +Signed-off-by: Qi Liu +Signed-off-by: Shaokun Zhang +Link: https://lore.kernel.org/r/1615186237-22263-9-git-send-email-zhangshaokun@hisilicon.com +Signed-off-by: Will Deacon +Reviewed-by: Shaokun Zhang +Signed-off-by: Zheng Zengkai +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/Makefile | 3 +- + drivers/perf/hisilicon/hisi_uncore_pa_pmu.c | 500 ++++++++++++++++++++ + include/linux/cpuhotplug.h | 1 + + 3 files changed, 503 insertions(+), 1 deletion(-) + create mode 100644 drivers/perf/hisilicon/hisi_uncore_pa_pmu.c + +diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile +index 6600a9d45dd8..7643c9f93e36 100644 +--- a/drivers/perf/hisilicon/Makefile ++++ b/drivers/perf/hisilicon/Makefile +@@ -1,3 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0-only + obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o \ +- hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_sllc_pmu.o ++ hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_sllc_pmu.o \ ++ hisi_uncore_pa_pmu.o +diff --git a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c +new file mode 100644 +index 000000000000..5517a90552ec +--- /dev/null ++++ b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c +@@ -0,0 +1,500 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * HiSilicon PA uncore Hardware event counters support ++ * ++ * Copyright (C) 2020 HiSilicon Limited ++ * Author: Shaokun Zhang ++ * ++ * This code is based on the uncore PMUs like arm-cci and arm-ccn. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hisi_uncore_pmu.h" ++ ++/* PA register definition */ ++#define PA_PERF_CTRL 0x1c00 ++#define PA_EVENT_CTRL 0x1c04 ++#define PA_TT_CTRL 0x1c08 ++#define PA_TGTID_CTRL 0x1c14 ++#define PA_SRCID_CTRL 0x1c18 ++#define PA_INT_MASK 0x1c70 ++#define PA_INT_STATUS 0x1c78 ++#define PA_INT_CLEAR 0x1c7c ++#define PA_EVENT_TYPE0 0x1c80 ++#define PA_PMU_VERSION 0x1cf0 ++#define PA_EVENT_CNT0_L 0x1d00 ++ ++#define PA_EVTYPE_MASK 0xff ++#define PA_NR_COUNTERS 0x8 ++#define PA_PERF_CTRL_EN BIT(0) ++#define PA_TRACETAG_EN BIT(4) ++#define PA_TGTID_EN BIT(11) ++#define PA_SRCID_EN BIT(11) ++#define PA_TGTID_NONE 0 ++#define PA_SRCID_NONE 0 ++#define PA_TGTID_MSK_SHIFT 12 ++#define PA_SRCID_MSK_SHIFT 12 ++ ++HISI_PMU_EVENT_ATTR_EXTRACTOR(tgtid_cmd, config1, 10, 0); ++HISI_PMU_EVENT_ATTR_EXTRACTOR(tgtid_msk, config1, 21, 11); ++HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_cmd, config1, 32, 22); ++HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_msk, config1, 43, 33); ++HISI_PMU_EVENT_ATTR_EXTRACTOR(tracetag_en, config1, 44, 44); ++ ++static void hisi_pa_pmu_enable_tracetag(struct perf_event *event) ++{ ++ struct hisi_pmu *pa_pmu = to_hisi_pmu(event->pmu); ++ u32 tt_en = hisi_get_tracetag_en(event); ++ ++ if (tt_en) { ++ u32 val; ++ ++ val = readl(pa_pmu->base + PA_TT_CTRL); ++ val |= PA_TRACETAG_EN; ++ writel(val, pa_pmu->base + PA_TT_CTRL); ++ } ++} ++ ++static void hisi_pa_pmu_clear_tracetag(struct perf_event *event) ++{ ++ struct hisi_pmu *pa_pmu = to_hisi_pmu(event->pmu); ++ u32 tt_en = hisi_get_tracetag_en(event); ++ ++ if (tt_en) { ++ u32 val; ++ ++ val = readl(pa_pmu->base + PA_TT_CTRL); ++ val &= ~PA_TRACETAG_EN; ++ writel(val, pa_pmu->base + PA_TT_CTRL); ++ } ++} ++ ++static void hisi_pa_pmu_config_tgtid(struct perf_event *event) ++{ ++ struct hisi_pmu *pa_pmu = to_hisi_pmu(event->pmu); ++ u32 cmd = hisi_get_tgtid_cmd(event); ++ ++ if (cmd) { ++ u32 msk = hisi_get_tgtid_msk(event); ++ u32 val = cmd | PA_TGTID_EN | (msk << PA_TGTID_MSK_SHIFT); ++ ++ writel(val, pa_pmu->base + PA_TGTID_CTRL); ++ } ++} ++ ++static void hisi_pa_pmu_clear_tgtid(struct perf_event *event) ++{ ++ struct hisi_pmu *pa_pmu = to_hisi_pmu(event->pmu); ++ u32 cmd = hisi_get_tgtid_cmd(event); ++ ++ if (cmd) ++ writel(PA_TGTID_NONE, pa_pmu->base + PA_TGTID_CTRL); ++} ++ ++static void hisi_pa_pmu_config_srcid(struct perf_event *event) ++{ ++ struct hisi_pmu *pa_pmu = to_hisi_pmu(event->pmu); ++ u32 cmd = hisi_get_srcid_cmd(event); ++ ++ if (cmd) { ++ u32 msk = hisi_get_srcid_msk(event); ++ u32 val = cmd | PA_SRCID_EN | (msk << PA_SRCID_MSK_SHIFT); ++ ++ writel(val, pa_pmu->base + PA_SRCID_CTRL); ++ } ++} ++ ++static void hisi_pa_pmu_clear_srcid(struct perf_event *event) ++{ ++ struct hisi_pmu *pa_pmu = to_hisi_pmu(event->pmu); ++ u32 cmd = hisi_get_srcid_cmd(event); ++ ++ if (cmd) ++ writel(PA_SRCID_NONE, pa_pmu->base + PA_SRCID_CTRL); ++} ++ ++static void hisi_pa_pmu_enable_filter(struct perf_event *event) ++{ ++ if (event->attr.config1 != 0x0) { ++ hisi_pa_pmu_enable_tracetag(event); ++ hisi_pa_pmu_config_srcid(event); ++ hisi_pa_pmu_config_tgtid(event); ++ } ++} ++ ++static void hisi_pa_pmu_disable_filter(struct perf_event *event) ++{ ++ if (event->attr.config1 != 0x0) { ++ hisi_pa_pmu_clear_tgtid(event); ++ hisi_pa_pmu_clear_srcid(event); ++ hisi_pa_pmu_clear_tracetag(event); ++ } ++} ++ ++static u32 hisi_pa_pmu_get_counter_offset(int idx) ++{ ++ return (PA_EVENT_CNT0_L + idx * 8); ++} ++ ++static u64 hisi_pa_pmu_read_counter(struct hisi_pmu *pa_pmu, ++ struct hw_perf_event *hwc) ++{ ++ return readq(pa_pmu->base + hisi_pa_pmu_get_counter_offset(hwc->idx)); ++} ++ ++static void hisi_pa_pmu_write_counter(struct hisi_pmu *pa_pmu, ++ struct hw_perf_event *hwc, u64 val) ++{ ++ writeq(val, pa_pmu->base + hisi_pa_pmu_get_counter_offset(hwc->idx)); ++} ++ ++static void hisi_pa_pmu_write_evtype(struct hisi_pmu *pa_pmu, int idx, ++ u32 type) ++{ ++ u32 reg, reg_idx, shift, val; ++ ++ /* ++ * Select the appropriate event select register(PA_EVENT_TYPE0/1). ++ * There are 2 event select registers for the 8 hardware counters. ++ * Event code is 8-bits and for the former 4 hardware counters, ++ * PA_EVENT_TYPE0 is chosen. For the latter 4 hardware counters, ++ * PA_EVENT_TYPE1 is chosen. ++ */ ++ reg = PA_EVENT_TYPE0 + (idx / 4) * 4; ++ reg_idx = idx % 4; ++ shift = 8 * reg_idx; ++ ++ /* Write event code to pa_EVENT_TYPEx Register */ ++ val = readl(pa_pmu->base + reg); ++ val &= ~(PA_EVTYPE_MASK << shift); ++ val |= (type << shift); ++ writel(val, pa_pmu->base + reg); ++} ++ ++static void hisi_pa_pmu_start_counters(struct hisi_pmu *pa_pmu) ++{ ++ u32 val; ++ ++ val = readl(pa_pmu->base + PA_PERF_CTRL); ++ val |= PA_PERF_CTRL_EN; ++ writel(val, pa_pmu->base + PA_PERF_CTRL); ++} ++ ++static void hisi_pa_pmu_stop_counters(struct hisi_pmu *pa_pmu) ++{ ++ u32 val; ++ ++ val = readl(pa_pmu->base + PA_PERF_CTRL); ++ val &= ~(PA_PERF_CTRL_EN); ++ writel(val, pa_pmu->base + PA_PERF_CTRL); ++} ++ ++static void hisi_pa_pmu_enable_counter(struct hisi_pmu *pa_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ /* Enable counter index in PA_EVENT_CTRL register */ ++ val = readl(pa_pmu->base + PA_EVENT_CTRL); ++ val |= 1 << hwc->idx; ++ writel(val, pa_pmu->base + PA_EVENT_CTRL); ++} ++ ++static void hisi_pa_pmu_disable_counter(struct hisi_pmu *pa_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ /* Clear counter index in PA_EVENT_CTRL register */ ++ val = readl(pa_pmu->base + PA_EVENT_CTRL); ++ val &= ~(1 << hwc->idx); ++ writel(val, pa_pmu->base + PA_EVENT_CTRL); ++} ++ ++static void hisi_pa_pmu_enable_counter_int(struct hisi_pmu *pa_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ /* Write 0 to enable interrupt */ ++ val = readl(pa_pmu->base + PA_INT_MASK); ++ val &= ~(1 << hwc->idx); ++ writel(val, pa_pmu->base + PA_INT_MASK); ++} ++ ++static void hisi_pa_pmu_disable_counter_int(struct hisi_pmu *pa_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ /* Write 1 to mask interrupt */ ++ val = readl(pa_pmu->base + PA_INT_MASK); ++ val |= 1 << hwc->idx; ++ writel(val, pa_pmu->base + PA_INT_MASK); ++} ++ ++static u32 hisi_pa_pmu_get_int_status(struct hisi_pmu *pa_pmu) ++{ ++ return readl(pa_pmu->base + PA_INT_STATUS); ++} ++ ++static void hisi_pa_pmu_clear_int_status(struct hisi_pmu *pa_pmu, int idx) ++{ ++ writel(1 << idx, pa_pmu->base + PA_INT_CLEAR); ++} ++ ++static const struct acpi_device_id hisi_pa_pmu_acpi_match[] = { ++ { "HISI0273", }, ++ {} ++}; ++MODULE_DEVICE_TABLE(acpi, hisi_pa_pmu_acpi_match); ++ ++static int hisi_pa_pmu_init_data(struct platform_device *pdev, ++ struct hisi_pmu *pa_pmu) ++{ ++ /* ++ * Use the SCCL_ID and the index ID to identify the PA PMU, ++ * while SCCL_ID is the nearst SCCL_ID from this SICL and ++ * CPU core is chosen from this SCCL to manage this PMU. ++ */ ++ if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id", ++ &pa_pmu->sccl_id)) { ++ dev_err(&pdev->dev, "Cannot read sccl-id!\n"); ++ return -EINVAL; ++ } ++ ++ if (device_property_read_u32(&pdev->dev, "hisilicon,idx-id", ++ &pa_pmu->index_id)) { ++ dev_err(&pdev->dev, "Cannot read idx-id!\n"); ++ return -EINVAL; ++ } ++ ++ pa_pmu->ccl_id = -1; ++ ++ pa_pmu->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(pa_pmu->base)) { ++ dev_err(&pdev->dev, "ioremap failed for pa_pmu resource.\n"); ++ return PTR_ERR(pa_pmu->base); ++ } ++ ++ pa_pmu->identifier = readl(pa_pmu->base + PA_PMU_VERSION); ++ ++ return 0; ++} ++ ++static struct attribute *hisi_pa_pmu_v2_format_attr[] = { ++ HISI_PMU_FORMAT_ATTR(event, "config:0-7"), ++ HISI_PMU_FORMAT_ATTR(tgtid_cmd, "config1:0-10"), ++ HISI_PMU_FORMAT_ATTR(tgtid_msk, "config1:11-21"), ++ HISI_PMU_FORMAT_ATTR(srcid_cmd, "config1:22-32"), ++ HISI_PMU_FORMAT_ATTR(srcid_msk, "config1:33-43"), ++ HISI_PMU_FORMAT_ATTR(tracetag_en, "config1:44"), ++ NULL, ++}; ++ ++static const struct attribute_group hisi_pa_pmu_v2_format_group = { ++ .name = "format", ++ .attrs = hisi_pa_pmu_v2_format_attr, ++}; ++ ++static struct attribute *hisi_pa_pmu_v2_events_attr[] = { ++ HISI_PMU_EVENT_ATTR(rx_req, 0x40), ++ HISI_PMU_EVENT_ATTR(tx_req, 0x5c), ++ HISI_PMU_EVENT_ATTR(cycle, 0x78), ++ NULL ++}; ++ ++static const struct attribute_group hisi_pa_pmu_v2_events_group = { ++ .name = "events", ++ .attrs = hisi_pa_pmu_v2_events_attr, ++}; ++ ++static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL); ++ ++static struct attribute *hisi_pa_pmu_cpumask_attrs[] = { ++ &dev_attr_cpumask.attr, ++ NULL ++}; ++ ++static const struct attribute_group hisi_pa_pmu_cpumask_attr_group = { ++ .attrs = hisi_pa_pmu_cpumask_attrs, ++}; ++ ++static struct device_attribute hisi_pa_pmu_identifier_attr = ++ __ATTR(identifier, 0444, hisi_uncore_pmu_identifier_attr_show, NULL); ++ ++static struct attribute *hisi_pa_pmu_identifier_attrs[] = { ++ &hisi_pa_pmu_identifier_attr.attr, ++ NULL ++}; ++ ++static struct attribute_group hisi_pa_pmu_identifier_group = { ++ .attrs = hisi_pa_pmu_identifier_attrs, ++}; ++ ++static const struct attribute_group *hisi_pa_pmu_v2_attr_groups[] = { ++ &hisi_pa_pmu_v2_format_group, ++ &hisi_pa_pmu_v2_events_group, ++ &hisi_pa_pmu_cpumask_attr_group, ++ &hisi_pa_pmu_identifier_group, ++ NULL ++}; ++ ++static const struct hisi_uncore_ops hisi_uncore_pa_ops = { ++ .write_evtype = hisi_pa_pmu_write_evtype, ++ .get_event_idx = hisi_uncore_pmu_get_event_idx, ++ .start_counters = hisi_pa_pmu_start_counters, ++ .stop_counters = hisi_pa_pmu_stop_counters, ++ .enable_counter = hisi_pa_pmu_enable_counter, ++ .disable_counter = hisi_pa_pmu_disable_counter, ++ .enable_counter_int = hisi_pa_pmu_enable_counter_int, ++ .disable_counter_int = hisi_pa_pmu_disable_counter_int, ++ .write_counter = hisi_pa_pmu_write_counter, ++ .read_counter = hisi_pa_pmu_read_counter, ++ .get_int_status = hisi_pa_pmu_get_int_status, ++ .clear_int_status = hisi_pa_pmu_clear_int_status, ++ .enable_filter = hisi_pa_pmu_enable_filter, ++ .disable_filter = hisi_pa_pmu_disable_filter, ++}; ++ ++static int hisi_pa_pmu_dev_probe(struct platform_device *pdev, ++ struct hisi_pmu *pa_pmu) ++{ ++ int ret; ++ ++ ret = hisi_pa_pmu_init_data(pdev, pa_pmu); ++ if (ret) ++ return ret; ++ ++ ret = hisi_uncore_pmu_init_irq(pa_pmu, pdev); ++ if (ret) ++ return ret; ++ ++ pa_pmu->pmu_events.attr_groups = hisi_pa_pmu_v2_attr_groups; ++ pa_pmu->num_counters = PA_NR_COUNTERS; ++ pa_pmu->ops = &hisi_uncore_pa_ops; ++ pa_pmu->check_event = 0xB0; ++ pa_pmu->counter_bits = 64; ++ pa_pmu->dev = &pdev->dev; ++ pa_pmu->on_cpu = -1; ++ ++ return 0; ++} ++ ++static int hisi_pa_pmu_probe(struct platform_device *pdev) ++{ ++ struct hisi_pmu *pa_pmu; ++ char *name; ++ int ret; ++ ++ pa_pmu = devm_kzalloc(&pdev->dev, sizeof(*pa_pmu), GFP_KERNEL); ++ if (!pa_pmu) ++ return -ENOMEM; ++ ++ ret = hisi_pa_pmu_dev_probe(pdev, pa_pmu); ++ if (ret) ++ return ret; ++ /* ++ * PA is attached in SICL and the CPU core is chosen to manage this ++ * PMU which is the nearest SCCL, while its SCCL_ID is greater than ++ * one with the SICL_ID. ++ */ ++ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sicl%u_pa%u", ++ pa_pmu->sccl_id - 1, pa_pmu->index_id); ++ if (!name) ++ return -ENOMEM; ++ ++ ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE, ++ &pa_pmu->node); ++ if (ret) { ++ dev_err(&pdev->dev, "Error %d registering hotplug\n", ret); ++ return ret; ++ } ++ ++ pa_pmu->pmu = (struct pmu) { ++ .module = THIS_MODULE, ++ .task_ctx_nr = perf_invalid_context, ++ .event_init = hisi_uncore_pmu_event_init, ++ .pmu_enable = hisi_uncore_pmu_enable, ++ .pmu_disable = hisi_uncore_pmu_disable, ++ .add = hisi_uncore_pmu_add, ++ .del = hisi_uncore_pmu_del, ++ .start = hisi_uncore_pmu_start, ++ .stop = hisi_uncore_pmu_stop, ++ .read = hisi_uncore_pmu_read, ++ .attr_groups = pa_pmu->pmu_events.attr_groups, ++ .capabilities = PERF_PMU_CAP_NO_EXCLUDE, ++ }; ++ ++ ret = perf_pmu_register(&pa_pmu->pmu, name, -1); ++ if (ret) { ++ dev_err(pa_pmu->dev, "PMU register failed, ret = %d\n", ret); ++ cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE, ++ &pa_pmu->node); ++ irq_set_affinity_hint(pa_pmu->irq, NULL); ++ return ret; ++ } ++ ++ platform_set_drvdata(pdev, pa_pmu); ++ return ret; ++} ++ ++static int hisi_pa_pmu_remove(struct platform_device *pdev) ++{ ++ struct hisi_pmu *pa_pmu = platform_get_drvdata(pdev); ++ ++ perf_pmu_unregister(&pa_pmu->pmu); ++ cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE, ++ &pa_pmu->node); ++ irq_set_affinity_hint(pa_pmu->irq, NULL); ++ ++ return 0; ++} ++ ++static struct platform_driver hisi_pa_pmu_driver = { ++ .driver = { ++ .name = "hisi_pa_pmu", ++ .acpi_match_table = hisi_pa_pmu_acpi_match, ++ .suppress_bind_attrs = true, ++ }, ++ .probe = hisi_pa_pmu_probe, ++ .remove = hisi_pa_pmu_remove, ++}; ++ ++static int __init hisi_pa_pmu_module_init(void) ++{ ++ int ret; ++ ++ ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE, ++ "AP_PERF_ARM_HISI_PA_ONLINE", ++ hisi_uncore_pmu_online_cpu, ++ hisi_uncore_pmu_offline_cpu); ++ if (ret) { ++ pr_err("PA PMU: cpuhp state setup failed, ret = %d\n", ret); ++ return ret; ++ } ++ ++ ret = platform_driver_register(&hisi_pa_pmu_driver); ++ if (ret) ++ cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE); ++ ++ return ret; ++} ++module_init(hisi_pa_pmu_module_init); ++ ++static void __exit hisi_pa_pmu_module_exit(void) ++{ ++ platform_driver_unregister(&hisi_pa_pmu_driver); ++ cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE); ++} ++module_exit(hisi_pa_pmu_module_exit); ++ ++MODULE_DESCRIPTION("HiSilicon Protocol Adapter uncore PMU driver"); ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Shaokun Zhang "); ++MODULE_AUTHOR("Qi Liu "); +diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h +index b5c55a408a30..225b095a96db 100644 +--- a/include/linux/cpuhotplug.h ++++ b/include/linux/cpuhotplug.h +@@ -161,6 +161,7 @@ enum cpuhp_state { + CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE, + CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE, + CPUHP_AP_PERF_ARM_HISI_L3_ONLINE, ++ CPUHP_AP_PERF_ARM_HISI_PA_ONLINE, + CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE, + CPUHP_AP_PERF_ARM_L2X0_ONLINE, + CPUHP_AP_PERF_ARM_QCOM_L2_ONLINE, +-- +2.27.0 + diff --git a/patches/0062-perf-hisi-Use-irq_set_affinity.patch b/patches/0062-perf-hisi-Use-irq_set_affinity.patch new file mode 100644 index 0000000..588e684 --- /dev/null +++ b/patches/0062-perf-hisi-Use-irq_set_affinity.patch @@ -0,0 +1,181 @@ +From e0b763c0b1c8c96a04fd56f7be82d13903123b19 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner +Date: Fri, 30 Jul 2021 15:44:12 +0800 +Subject: [PATCH 21/55] perf/hisi: Use irq_set_affinity() + +mainline inclusion +from mainline-v5.13-rc3 +commit 77b06ddc04354293f746d0434f00700110d3392d +category: bugfix +bugzilla: 175148 +CVE: NA +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=77b06ddc04354293f746d0434f00700110d3392d + +------------------------------------------------------------------------ + +These drivers use irq_set_affinity_hint() to set the affinity for the PMU +interrupts, which relies on the undocumented side effect that this function +actually sets the affinity under the hood. + +Setting an hint is clearly not a guarantee and for these PMU interrupts an +affinity hint, which is supposed to guide userspace for setting affinity, +is beyond pointless, because the affinity of these interrupts cannot be +modified from user space. + +Aside of that the error checks are bogus because the only error which is +returned from irq_set_affinity_hint() is when there is no irq descriptor +for the interrupt number, but not when the affinity set fails. That's on +purpose because the hint can point to an offline CPU. + +Replace the mindless abuse with irq_set_affinity(). + +Signed-off-by: Thomas Gleixner +Cc: Shaokun Zhang +Cc: Will Deacon +Cc: Mark Rutland +Cc: linux-arm-kernel@lists.infradead.org +Acked-by: Mark Rutland +Link: https://lore.kernel.org/r/20210518093118.813375875@linutronix.de +Signed-off-by: Will Deacon +Reviewed-by: Shaokun Zhang +Signed-off-by: Zheng Zengkai +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 3 --- + drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 3 --- + drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 3 --- + drivers/perf/hisilicon/hisi_uncore_pa_pmu.c | 3 --- + drivers/perf/hisilicon/hisi_uncore_pmu.c | 4 ++-- + drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 3 --- + 6 files changed, 2 insertions(+), 17 deletions(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +index af5f8c16eab1..457ac6a1ad64 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +@@ -540,7 +540,6 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev) + dev_err(ddrc_pmu->dev, "DDRC PMU register failed!\n"); + cpuhp_state_remove_instance_nocalls( + CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE, &ddrc_pmu->node); +- irq_set_affinity_hint(ddrc_pmu->irq, NULL); + } + + return ret; +@@ -553,8 +552,6 @@ static int hisi_ddrc_pmu_remove(struct platform_device *pdev) + perf_pmu_unregister(&ddrc_pmu->pmu); + cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE, + &ddrc_pmu->node); +- irq_set_affinity_hint(ddrc_pmu->irq, NULL); +- + return 0; + } + +diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +index a7e1749fc3e4..89996b4d939f 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +@@ -543,7 +543,6 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev) + dev_err(hha_pmu->dev, "HHA PMU register failed!\n"); + cpuhp_state_remove_instance_nocalls( + CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE, &hha_pmu->node); +- irq_set_affinity_hint(hha_pmu->irq, NULL); + } + + return ret; +@@ -556,8 +555,6 @@ static int hisi_hha_pmu_remove(struct platform_device *pdev) + perf_pmu_unregister(&hha_pmu->pmu); + cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE, + &hha_pmu->node); +- irq_set_affinity_hint(hha_pmu->irq, NULL); +- + return 0; + } + +diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +index 87ca2a9ca8c5..d70a01587d72 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +@@ -581,7 +581,6 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev) + dev_err(l3c_pmu->dev, "L3C PMU register failed!\n"); + cpuhp_state_remove_instance_nocalls( + CPUHP_AP_PERF_ARM_HISI_L3_ONLINE, &l3c_pmu->node); +- irq_set_affinity_hint(l3c_pmu->irq, NULL); + } + + return ret; +@@ -594,8 +593,6 @@ static int hisi_l3c_pmu_remove(struct platform_device *pdev) + perf_pmu_unregister(&l3c_pmu->pmu); + cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE, + &l3c_pmu->node); +- irq_set_affinity_hint(l3c_pmu->irq, NULL); +- + return 0; + } + +diff --git a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c +index 5517a90552ec..390e59f4ef60 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c +@@ -436,7 +436,6 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev) + dev_err(pa_pmu->dev, "PMU register failed, ret = %d\n", ret); + cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE, + &pa_pmu->node); +- irq_set_affinity_hint(pa_pmu->irq, NULL); + return ret; + } + +@@ -451,8 +450,6 @@ static int hisi_pa_pmu_remove(struct platform_device *pdev) + perf_pmu_unregister(&pa_pmu->pmu); + cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE, + &pa_pmu->node); +- irq_set_affinity_hint(pa_pmu->irq, NULL); +- + return 0; + } + +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c +index c0f221e39aff..2758cab39a58 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c +@@ -491,7 +491,7 @@ int hisi_uncore_pmu_online_cpu(unsigned int cpu, struct hlist_node *node) + hisi_pmu->on_cpu = cpu; + + /* Overflow interrupt also should use the same CPU */ +- WARN_ON(irq_set_affinity_hint(hisi_pmu->irq, cpumask_of(cpu))); ++ WARN_ON(irq_set_affinity(hisi_pmu->irq, cpumask_of(cpu))); + + return 0; + } +@@ -524,7 +524,7 @@ int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node) + perf_pmu_migrate_context(&hisi_pmu->pmu, cpu, target); + /* Use this CPU for event counting */ + hisi_pmu->on_cpu = target; +- WARN_ON(irq_set_affinity_hint(hisi_pmu->irq, cpumask_of(target))); ++ WARN_ON(irq_set_affinity(hisi_pmu->irq, cpumask_of(target))); + + return 0; + } +diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c +index 46be312fa126..835ec3e2178f 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c +@@ -465,7 +465,6 @@ static int hisi_sllc_pmu_probe(struct platform_device *pdev) + dev_err(sllc_pmu->dev, "PMU register failed, ret = %d\n", ret); + cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE, + &sllc_pmu->node); +- irq_set_affinity_hint(sllc_pmu->irq, NULL); + return ret; + } + +@@ -481,8 +480,6 @@ static int hisi_sllc_pmu_remove(struct platform_device *pdev) + perf_pmu_unregister(&sllc_pmu->pmu); + cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE, + &sllc_pmu->node); +- irq_set_affinity_hint(sllc_pmu->irq, NULL); +- + return 0; + } + +-- +2.27.0 + diff --git a/patches/0063-drivers-perf-hisi-Fix-data-source-control.patch b/patches/0063-drivers-perf-hisi-Fix-data-source-control.patch new file mode 100644 index 0000000..751365d --- /dev/null +++ b/patches/0063-drivers-perf-hisi-Fix-data-source-control.patch @@ -0,0 +1,60 @@ +From 07451c781b0890dd194b0a53606250bed8f6ecbf Mon Sep 17 00:00:00 2001 +From: Shaokun Zhang +Date: Fri, 30 Jul 2021 15:44:13 +0800 +Subject: [PATCH 22/55] drivers/perf: hisi: Fix data source control + +mainline inclusion +from mainline-v5.13-rc3 +commit 814be609baae62aaa6c02fa6f3ad66cff32a6d15 +category: bugfix +bugzilla: 175148 +CVE: NA +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=814be609baae62aaa6c02fa6f3ad66cff32a6d15 + +------------------------------------------------------------------------ + +'Data source' is a new function for HHA PMU and config / clear +interface was wrong by mistake. 'HHA_DATSRC_CTRL' register is +mainly used for data source configuration, if we enable bit0 +as driver, it will go on count the event and we didn't check +it carefully. So fix the issue and do as the initial purpose. + +Fixes: 932f6a99f9b0 ("drivers/perf: hisi: Add new functions for HHA PMU") +Reported-by: kernel test robot +Cc: Will Deacon +Cc: Mark Rutland +Signed-off-by: Shaokun Zhang +Link: https://lore.kernel.org/r/1622709291-37996-1-git-send-email-zhangshaokun@hisilicon.com +Signed-off-by: Will Deacon +Reviewed-by: Shaokun Zhang +Signed-off-by: Zheng Zengkai +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +index 89996b4d939f..3b120fc55e01 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +@@ -93,7 +93,7 @@ static void hisi_hha_pmu_config_ds(struct perf_event *event) + + val = readl(hha_pmu->base + HHA_DATSRC_CTRL); + val |= HHA_DATSRC_SKT_EN; +- writel(ds_skt, hha_pmu->base + HHA_DATSRC_CTRL); ++ writel(val, hha_pmu->base + HHA_DATSRC_CTRL); + } + } + +@@ -107,7 +107,7 @@ static void hisi_hha_pmu_clear_ds(struct perf_event *event) + + val = readl(hha_pmu->base + HHA_DATSRC_CTRL); + val &= ~HHA_DATSRC_SKT_EN; +- writel(ds_skt, hha_pmu->base + HHA_DATSRC_CTRL); ++ writel(val, hha_pmu->base + HHA_DATSRC_CTRL); + } + } + +-- +2.27.0 + diff --git a/patches/0064-perf-hisi-Make-irq-shared.patch b/patches/0064-perf-hisi-Make-irq-shared.patch new file mode 100644 index 0000000..c2036c9 --- /dev/null +++ b/patches/0064-perf-hisi-Make-irq-shared.patch @@ -0,0 +1,44 @@ +From d6ffa958e5f2fd9eff8cec5b41817e9bdec94f5e Mon Sep 17 00:00:00 2001 +From: Chen Jun +Date: Thu, 19 May 2022 20:09:48 +0800 +Subject: [PATCH 23/55] perf: hisi: Make irq shared + +hulk inclusion +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I584X2 +CVE: NA + +-------------------------------- + +On some platforms, there are some error: +genirq: Flags mismatch irq 23. 00010804 (xxx) vs. 00010804 (xxx) + +The reason is that there are more than one pmu nodes witch uses the same +irq number. + +Add IROF_SHARED when devm_request_irq + +Signed-off-by: Chen Jun +Reviewed-by: Weilong Chen +Signed-off-by: Zheng Zengkai +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_pmu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c +index 2758cab39a58..eceff43c89f7 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c +@@ -171,7 +171,7 @@ int hisi_uncore_pmu_init_irq(struct hisi_pmu *hisi_pmu, + return irq; + + ret = devm_request_irq(&pdev->dev, irq, hisi_uncore_pmu_isr, +- IRQF_NOBALANCING | IRQF_NO_THREAD, ++ IRQF_NOBALANCING | IRQF_NO_THREAD | IRQF_SHARED, + dev_name(&pdev->dev), hisi_pmu); + if (ret < 0) { + dev_err(&pdev->dev, +-- +2.27.0 + diff --git a/patches/0065-perf-hisi-Fix-read-sccl_id-and-ccl_id-error-in-some-.patch b/patches/0065-perf-hisi-Fix-read-sccl_id-and-ccl_id-error-in-some-.patch new file mode 100644 index 0000000..ce3d41b --- /dev/null +++ b/patches/0065-perf-hisi-Fix-read-sccl_id-and-ccl_id-error-in-some-.patch @@ -0,0 +1,57 @@ +From 52b22aa2df42650d15ff80d32c827a55e6907a49 Mon Sep 17 00:00:00 2001 +From: Chen Jun +Date: Thu, 19 May 2022 20:09:49 +0800 +Subject: [PATCH 24/55] perf: hisi: Fix read sccl_id and ccl_id error in some + platform + +hulk inclusion +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I584X2 +CVE: NA + +-------------------------------- + +Some platforms with TSV200 or CORTEX_A55, sccl and ccl are keep in +aff2 if mt. + +Signed-off-by: Chen Jun +Reviewed-by: Weilong Chen +Signed-off-by: Zheng Zengkai +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_pmu.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c +index eceff43c89f7..4a781c2e1992 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c +@@ -437,12 +437,19 @@ static void hisi_read_sccl_and_ccl_id(int *scclp, int *cclp) + bool mt = mpidr & MPIDR_MT_BITMASK; + int sccl, ccl; + +- if (mt && read_cpuid_part_number() == HISI_CPU_PART_TSV110) { +- sccl = aff2 >> 3; +- ccl = aff2 & 0x7; +- } else if (mt) { +- sccl = aff3; +- ccl = aff2; ++ if (mt) { ++ switch (read_cpuid_part_number()) { ++ case HISI_CPU_PART_TSV110: ++ case HISI_CPU_PART_TSV200: ++ case ARM_CPU_PART_CORTEX_A55: ++ sccl = aff2 >> 3; ++ ccl = aff2 & 0x7; ++ break; ++ default: ++ sccl = aff3; ++ ccl = aff2; ++ break; ++ } + } else { + sccl = aff2; + ccl = aff1; +-- +2.27.0 + diff --git a/patches/0066-perf-hisi-Add-support-for-HiSilicon-SoC-L3T-PMU.patch b/patches/0066-perf-hisi-Add-support-for-HiSilicon-SoC-L3T-PMU.patch new file mode 100644 index 0000000..e6e310f --- /dev/null +++ b/patches/0066-perf-hisi-Add-support-for-HiSilicon-SoC-L3T-PMU.patch @@ -0,0 +1,461 @@ +From 88223b8764dabcbfde85e37927fbd12100957f22 Mon Sep 17 00:00:00 2001 +From: Chen Jun +Date: Thu, 19 May 2022 20:09:50 +0800 +Subject: [PATCH 25/55] perf: hisi: Add support for HiSilicon SoC L3T PMU + +hulk inclusion +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I584X2 +CVE: NA + +-------------------------------- + +Add support for HiSilicon SoC L3T PMU + +Signed-off-by: Chen Jun +Reviewed-by: Weilong Chen +Signed-off-by: Zheng Zengkai +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/Makefile | 3 +- + drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 2 +- + drivers/perf/hisilicon/hisi_uncore_l3t_pmu.c | 403 +++++++++++++++++++ + 3 files changed, 406 insertions(+), 2 deletions(-) + create mode 100644 drivers/perf/hisilicon/hisi_uncore_l3t_pmu.c + +diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile +index 7643c9f93e36..18abcb612216 100644 +--- a/drivers/perf/hisilicon/Makefile ++++ b/drivers/perf/hisilicon/Makefile +@@ -1,4 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0-only + obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o \ + hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_sllc_pmu.o \ +- hisi_uncore_pa_pmu.o ++ hisi_uncore_pa_pmu.o \ ++ hisi_uncore_l3t_pmu.o +diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +index d70a01587d72..bb39b44761a5 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +@@ -611,7 +611,7 @@ static int __init hisi_l3c_pmu_module_init(void) + int ret; + + ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE, +- "AP_PERF_ARM_HISI_L3_ONLINE", ++ "AP_PERF_ARM_HISI_L3T_ONLINE", + hisi_uncore_pmu_online_cpu, + hisi_uncore_pmu_offline_cpu); + if (ret) { +diff --git a/drivers/perf/hisilicon/hisi_uncore_l3t_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3t_pmu.c +new file mode 100644 +index 000000000000..f414dc1736aa +--- /dev/null ++++ b/drivers/perf/hisilicon/hisi_uncore_l3t_pmu.c +@@ -0,0 +1,403 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * HiSilicon SoC L3T uncore Hardware event counters support ++ * ++ * Copyright (C) 2017 Hisilicon Limited ++ * Author: Anurup M ++ * Shaokun Zhang ++ * ++ * This code is based on the uncore PMUs like arm-cci and arm-ccn. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hisi_uncore_pmu.h" ++ ++/* L3T register definition */ ++#define L3T_PERF_CTRL 0x0408 ++#define L3T_INT_MASK 0x0800 ++#define L3T_INT_STATUS 0x0808 ++#define L3T_INT_CLEAR 0x080c ++#define L3T_EVENT_CTRL 0x1c00 ++#define L3T_VERSION 0x1cf0 ++#define L3T_EVENT_TYPE0 0x1d00 ++/* ++ * If the HW version only supports a 48-bit counter, then ++ * bits [63:48] are reserved, which are Read-As-Zero and ++ * Writes-Ignored. ++ */ ++#define L3T_CNTR0_LOWER 0x1e00 ++ ++/* L3T has 8-counters */ ++#define L3T_NR_COUNTERS 0x8 ++ ++#define L3T_PERF_CTRL_EN 0x20000 ++#define L3T_EVTYPE_NONE 0xff ++#define L3T_NR_EVENTS 0x59 ++ ++/* ++ * Select the counter register offset using the counter index ++ */ ++static u32 hisi_l3t_pmu_get_counter_offset(int cntr_idx) ++{ ++ return (L3T_CNTR0_LOWER + (cntr_idx * 8)); ++} ++ ++static u64 hisi_l3t_pmu_read_counter(struct hisi_pmu *l3t_pmu, ++ struct hw_perf_event *hwc) ++{ ++ return readq(l3t_pmu->base + hisi_l3t_pmu_get_counter_offset(hwc->idx)); ++} ++ ++static void hisi_l3t_pmu_write_counter(struct hisi_pmu *l3t_pmu, ++ struct hw_perf_event *hwc, u64 val) ++{ ++ writeq(val, l3t_pmu->base + hisi_l3t_pmu_get_counter_offset(hwc->idx)); ++} ++ ++static void hisi_l3t_pmu_write_evtype(struct hisi_pmu *l3t_pmu, int idx, ++ u32 type) ++{ ++ u32 reg, reg_idx, shift, val; ++ ++ /* ++ * Select the appropriate event select register(L3T_EVENT_TYPE0/1). ++ * There are 2 event select registers for the 8 hardware counters. ++ * Event code is 8-bits and for the former 4 hardware counters, ++ * L3T_EVENT_TYPE0 is chosen. For the latter 4 hardware counters, ++ * L3T_EVENT_TYPE1 is chosen. ++ */ ++ reg = L3T_EVENT_TYPE0 + (idx / 4) * 4; ++ reg_idx = idx % 4; ++ shift = 8 * reg_idx; ++ ++ /* Write event code to L3T_EVENT_TYPEx Register */ ++ val = readl(l3t_pmu->base + reg); ++ val &= ~(L3T_EVTYPE_NONE << shift); ++ val |= (type << shift); ++ writel(val, l3t_pmu->base + reg); ++} ++ ++static void hisi_l3t_pmu_start_counters(struct hisi_pmu *l3t_pmu) ++{ ++ u32 val; ++ ++ /* ++ * Set perf_enable bit in L3T_PERF_CTRL register to start counting ++ * for all enabled counters. ++ */ ++ val = readl(l3t_pmu->base + L3T_PERF_CTRL); ++ val |= L3T_PERF_CTRL_EN; ++ writel(val, l3t_pmu->base + L3T_PERF_CTRL); ++} ++ ++static void hisi_l3t_pmu_stop_counters(struct hisi_pmu *l3t_pmu) ++{ ++ u32 val; ++ ++ /* ++ * Clear perf_enable bit in L3T_PERF_CTRL register to stop counting ++ * for all enabled counters. ++ */ ++ val = readl(l3t_pmu->base + L3T_PERF_CTRL); ++ val &= ~(L3T_PERF_CTRL_EN); ++ writel(val, l3t_pmu->base + L3T_PERF_CTRL); ++} ++ ++static void hisi_l3t_pmu_enable_counter(struct hisi_pmu *l3t_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ /* Enable counter index in L3T_EVENT_CTRL register */ ++ val = readl(l3t_pmu->base + L3T_EVENT_CTRL); ++ val |= (1 << hwc->idx); ++ writel(val, l3t_pmu->base + L3T_EVENT_CTRL); ++} ++ ++static void hisi_l3t_pmu_disable_counter(struct hisi_pmu *l3t_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ /* Clear counter index in L3T_EVENT_CTRL register */ ++ val = readl(l3t_pmu->base + L3T_EVENT_CTRL); ++ val &= ~(1 << hwc->idx); ++ writel(val, l3t_pmu->base + L3T_EVENT_CTRL); ++} ++ ++static void hisi_l3t_pmu_enable_counter_int(struct hisi_pmu *l3t_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ val = readl(l3t_pmu->base + L3T_INT_MASK); ++ /* Write 0 to enable interrupt */ ++ val &= ~(1 << hwc->idx); ++ writel(val, l3t_pmu->base + L3T_INT_MASK); ++} ++ ++static void hisi_l3t_pmu_disable_counter_int(struct hisi_pmu *l3t_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ val = readl(l3t_pmu->base + L3T_INT_MASK); ++ /* Write 1 to mask interrupt */ ++ val |= (1 << hwc->idx); ++ writel(val, l3t_pmu->base + L3T_INT_MASK); ++} ++ ++static u32 hisi_l3t_pmu_get_int_status(struct hisi_pmu *l3t_pmu) ++{ ++ return readl(l3t_pmu->base + L3T_INT_STATUS); ++} ++ ++static void hisi_l3t_pmu_clear_int_status(struct hisi_pmu *l3t_pmu, int idx) ++{ ++ writel(1 << idx, l3t_pmu->base + L3T_INT_CLEAR); ++} ++ ++static const struct acpi_device_id hisi_l3t_pmu_acpi_match[] = { ++ {} ++}; ++MODULE_DEVICE_TABLE(acpi, hisi_l3t_pmu_acpi_match); ++ ++static const struct of_device_id l3t_of_match[] = { ++ { .compatible = "hisilicon,l3t-pmu", }, ++ {}, ++}; ++ ++static int hisi_l3t_pmu_init_data(struct platform_device *pdev, ++ struct hisi_pmu *l3t_pmu) ++{ ++ /* ++ * Use the SCCL_ID and CCL_ID to identify the L3T PMU, while ++ * SCCL_ID is in MPIDR[aff2] and CCL_ID is in MPIDR[aff1]. ++ */ ++ if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id", ++ &l3t_pmu->sccl_id)) { ++ dev_err(&pdev->dev, "Can not read l3t sccl-id!\n"); ++ return -EINVAL; ++ } ++ ++ if (device_property_read_u32(&pdev->dev, "hisilicon,ccl-id", ++ &l3t_pmu->ccl_id)) { ++ dev_err(&pdev->dev, "Can not read l3t ccl-id!\n"); ++ return -EINVAL; ++ } ++ ++ l3t_pmu->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(l3t_pmu->base)) { ++ dev_err(&pdev->dev, "ioremap failed for l3t_pmu resource\n"); ++ return PTR_ERR(l3t_pmu->base); ++ } ++ ++ l3t_pmu->identifier = readl(l3t_pmu->base + L3T_VERSION); ++ ++ return 0; ++} ++ ++static struct attribute *hisi_l3t_pmu_v1_format_attr[] = { ++ HISI_PMU_FORMAT_ATTR(event, "config:0-7"), ++ NULL, ++}; ++ ++static const struct attribute_group hisi_l3t_pmu_v1_format_group = { ++ .name = "format", ++ .attrs = hisi_l3t_pmu_v1_format_attr, ++}; ++ ++static struct attribute *hisi_l3t_pmu_v1_events_attr[] = { ++ HISI_PMU_EVENT_ATTR(rd_cpipe, 0x00), ++ HISI_PMU_EVENT_ATTR(wr_cpipe, 0x01), ++ HISI_PMU_EVENT_ATTR(rd_hit_cpipe, 0x02), ++ HISI_PMU_EVENT_ATTR(wr_hit_cpipe, 0x03), ++ HISI_PMU_EVENT_ATTR(victim_num, 0x04), ++ HISI_PMU_EVENT_ATTR(rd_spipe, 0x20), ++ HISI_PMU_EVENT_ATTR(wr_spipe, 0x21), ++ HISI_PMU_EVENT_ATTR(rd_hit_spipe, 0x22), ++ HISI_PMU_EVENT_ATTR(wr_hit_spipe, 0x23), ++ HISI_PMU_EVENT_ATTR(back_invalid, 0x29), ++ HISI_PMU_EVENT_ATTR(retry_cpu, 0x40), ++ HISI_PMU_EVENT_ATTR(retry_ring, 0x41), ++ HISI_PMU_EVENT_ATTR(prefetch_drop, 0x42), ++ NULL, ++}; ++ ++static const struct attribute_group hisi_l3t_pmu_v1_events_group = { ++ .name = "events", ++ .attrs = hisi_l3t_pmu_v1_events_attr, ++}; ++ ++static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL); ++ ++static struct attribute *hisi_l3t_pmu_cpumask_attrs[] = { ++ &dev_attr_cpumask.attr, ++ NULL, ++}; ++ ++static const struct attribute_group hisi_l3t_pmu_cpumask_attr_group = { ++ .attrs = hisi_l3t_pmu_cpumask_attrs, ++}; ++ ++static struct device_attribute hisi_l3t_pmu_identifier_attr = ++ __ATTR(identifier, 0444, hisi_uncore_pmu_identifier_attr_show, NULL); ++ ++static struct attribute *hisi_l3t_pmu_identifier_attrs[] = { ++ &hisi_l3t_pmu_identifier_attr.attr, ++ NULL ++}; ++ ++static struct attribute_group hisi_l3t_pmu_identifier_group = { ++ .attrs = hisi_l3t_pmu_identifier_attrs, ++}; ++ ++static const struct attribute_group *hisi_l3t_pmu_v1_attr_groups[] = { ++ &hisi_l3t_pmu_v1_format_group, ++ &hisi_l3t_pmu_v1_events_group, ++ &hisi_l3t_pmu_cpumask_attr_group, ++ &hisi_l3t_pmu_identifier_group, ++ NULL, ++}; ++ ++static const struct hisi_uncore_ops hisi_uncore_l3t_ops = { ++ .write_evtype = hisi_l3t_pmu_write_evtype, ++ .get_event_idx = hisi_uncore_pmu_get_event_idx, ++ .start_counters = hisi_l3t_pmu_start_counters, ++ .stop_counters = hisi_l3t_pmu_stop_counters, ++ .enable_counter = hisi_l3t_pmu_enable_counter, ++ .disable_counter = hisi_l3t_pmu_disable_counter, ++ .enable_counter_int = hisi_l3t_pmu_enable_counter_int, ++ .disable_counter_int = hisi_l3t_pmu_disable_counter_int, ++ .write_counter = hisi_l3t_pmu_write_counter, ++ .read_counter = hisi_l3t_pmu_read_counter, ++ .get_int_status = hisi_l3t_pmu_get_int_status, ++ .clear_int_status = hisi_l3t_pmu_clear_int_status, ++}; ++ ++static int hisi_l3t_pmu_dev_probe(struct platform_device *pdev, ++ struct hisi_pmu *l3t_pmu) ++{ ++ int ret; ++ ++ ret = hisi_l3t_pmu_init_data(pdev, l3t_pmu); ++ if (ret) ++ return ret; ++ ++ ret = hisi_uncore_pmu_init_irq(l3t_pmu, pdev); ++ if (ret) ++ return ret; ++ ++ l3t_pmu->counter_bits = 48; ++ l3t_pmu->check_event = L3T_NR_EVENTS; ++ l3t_pmu->pmu_events.attr_groups = hisi_l3t_pmu_v1_attr_groups; ++ ++ l3t_pmu->num_counters = L3T_NR_COUNTERS; ++ l3t_pmu->ops = &hisi_uncore_l3t_ops; ++ l3t_pmu->dev = &pdev->dev; ++ l3t_pmu->on_cpu = -1; ++ ++ return 0; ++} ++ ++static int hisi_l3t_pmu_probe(struct platform_device *pdev) ++{ ++ struct hisi_pmu *l3t_pmu; ++ char *name; ++ int ret; ++ ++ l3t_pmu = devm_kzalloc(&pdev->dev, sizeof(*l3t_pmu), GFP_KERNEL); ++ if (!l3t_pmu) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, l3t_pmu); ++ ++ ret = hisi_l3t_pmu_dev_probe(pdev, l3t_pmu); ++ if (ret) ++ return ret; ++ ++ if (device_property_read_u32(&pdev->dev, "hisilicon,index-id", &l3t_pmu->index_id)) { ++ dev_err(&pdev->dev, "Can not read l3t index-id!\n"); ++ return -EINVAL; ++ } ++ ++ /* ++ * CCL_ID is used to identify the L3T in the same SCCL which was ++ * used _UID by mistake. ++ */ ++ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_l3t%u", ++ l3t_pmu->sccl_id, l3t_pmu->index_id); ++ l3t_pmu->pmu = (struct pmu) { ++ .name = name, ++ .module = THIS_MODULE, ++ .task_ctx_nr = perf_invalid_context, ++ .event_init = hisi_uncore_pmu_event_init, ++ .pmu_enable = hisi_uncore_pmu_enable, ++ .pmu_disable = hisi_uncore_pmu_disable, ++ .add = hisi_uncore_pmu_add, ++ .del = hisi_uncore_pmu_del, ++ .start = hisi_uncore_pmu_start, ++ .stop = hisi_uncore_pmu_stop, ++ .read = hisi_uncore_pmu_read, ++ .attr_groups = l3t_pmu->pmu_events.attr_groups, ++ .capabilities = PERF_PMU_CAP_NO_EXCLUDE, ++ }; ++ ++ /* Pick one core to use for cpumask attributes */ ++ cpumask_set_cpu(smp_processor_id(), &l3t_pmu->associated_cpus); ++ ++ l3t_pmu->on_cpu = cpumask_first(&l3t_pmu->associated_cpus); ++ if (l3t_pmu->on_cpu >= nr_cpu_ids) ++ return -EINVAL; ++ ++ ret = perf_pmu_register(&l3t_pmu->pmu, name, -1); ++ ++ return ret; ++} ++ ++static int hisi_l3t_pmu_remove(struct platform_device *pdev) ++{ ++ struct hisi_pmu *l3t_pmu = platform_get_drvdata(pdev); ++ ++ perf_pmu_unregister(&l3t_pmu->pmu); ++ ++ return 0; ++} ++ ++static struct platform_driver hisi_l3t_pmu_driver = { ++ .driver = { ++ .name = "hisi_l3t_pmu", ++ .acpi_match_table = ACPI_PTR(hisi_l3t_pmu_acpi_match), ++ .of_match_table = l3t_of_match, ++ .suppress_bind_attrs = true, ++ }, ++ .probe = hisi_l3t_pmu_probe, ++ .remove = hisi_l3t_pmu_remove, ++}; ++ ++static int __init hisi_l3t_pmu_module_init(void) ++{ ++ int ret; ++ ++ ret = platform_driver_register(&hisi_l3t_pmu_driver); ++ ++ return ret; ++} ++module_init(hisi_l3t_pmu_module_init); ++ ++static void __exit hisi_l3t_pmu_module_exit(void) ++{ ++ platform_driver_unregister(&hisi_l3t_pmu_driver); ++} ++module_exit(hisi_l3t_pmu_module_exit); ++ ++MODULE_DESCRIPTION("HiSilicon SoC L3T uncore PMU driver"); ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Anurup M "); ++MODULE_AUTHOR("Shaokun Zhang "); +-- +2.27.0 + diff --git a/patches/0067-perf-hisi-Add-support-for-HiSilicon-SoC-LPDDRC-PMU.patch b/patches/0067-perf-hisi-Add-support-for-HiSilicon-SoC-LPDDRC-PMU.patch new file mode 100644 index 0000000..f8eaacc --- /dev/null +++ b/patches/0067-perf-hisi-Add-support-for-HiSilicon-SoC-LPDDRC-PMU.patch @@ -0,0 +1,452 @@ +From f61fd1d5a4ff1adaae0626f0a99fc38e82efde55 Mon Sep 17 00:00:00 2001 +From: Chen Jun +Date: Thu, 19 May 2022 20:09:51 +0800 +Subject: [PATCH 26/55] perf: hisi: Add support for HiSilicon SoC LPDDRC PMU + +hulk inclusion +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I584X2 +CVE: NA + +-------------------------------- + +Add support for HiSilicon SoC LPDDRC PMU + +Signed-off-by: Chen Jun +Reviewed-by: Weilong Chen +Signed-off-by: Zheng Zengkai +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/Makefile | 3 +- + .../perf/hisilicon/hisi_uncore_lpddrc_pmu.c | 408 ++++++++++++++++++ + 2 files changed, 410 insertions(+), 1 deletion(-) + create mode 100644 drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c + +diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile +index 18abcb612216..22e384cdfd53 100644 +--- a/drivers/perf/hisilicon/Makefile ++++ b/drivers/perf/hisilicon/Makefile +@@ -2,4 +2,5 @@ + obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o \ + hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_sllc_pmu.o \ + hisi_uncore_pa_pmu.o \ +- hisi_uncore_l3t_pmu.o ++ hisi_uncore_l3t_pmu.o \ ++ hisi_uncore_lpddrc_pmu.o +diff --git a/drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c +new file mode 100644 +index 000000000000..03a4bb1a9948 +--- /dev/null ++++ b/drivers/perf/hisilicon/hisi_uncore_lpddrc_pmu.c +@@ -0,0 +1,408 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * HiSilicon SoC LPDDRC uncore Hardware event counters support ++ * ++ * Copyright (C) 2017 Hisilicon Limited ++ * Author: Shaokun Zhang ++ * Anurup M ++ * ++ * This code is based on the uncore PMUs like arm-cci and arm-ccn. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hisi_uncore_pmu.h" ++ ++/* LPDDRC register definition in v1 */ ++#define LPDDRC_PERF_CTRL 0x4930 ++#define LPDDRC_FLUX_WR 0x4948 ++#define LPDDRC_FLUX_RD 0x494c ++#define LPDDRC_FLUX_WCMD 0x4950 ++#define LPDDRC_FLUX_RCMD 0x4954 ++#define LPDDRC_PRE_CMD 0x4984 ++#define LPDDRC_ACT_CMD 0x4988 ++#define LPDDRC_RNK_CHG 0x4990 ++#define LPDDRC_RW_CHG 0x4994 ++#define LPDDRC_EVENT_CTRL 0x4d60 ++#define LPDDRC_INT_MASK 0x6c8 ++#define LPDDRC_INT_STATUS 0x6cc ++#define LPDDRC_INT_CLEAR 0x6d0 ++#define LPDDRC_VERSION 0x710 ++ ++#define LPDDRC_NR_COUNTERS 0x8 ++#define LPDDRC_V1_PERF_CTRL_EN 0x1 ++#define LPDDRC_V1_NR_EVENTS 0x7 ++ ++/* ++ * For PMU v1, there are eight-events and every event has been mapped ++ * to fixed-purpose counters which register offset is not consistent. ++ * Therefore there is no write event type and we assume that event ++ * code (0 to 7) is equal to counter index in PMU driver. ++ */ ++#define GET_LPDDRC_EVENTID(hwc) (hwc->config_base & 0x7) ++ ++static const u32 lpddrc_reg_off[] = { ++ LPDDRC_FLUX_WR, LPDDRC_FLUX_RD, LPDDRC_FLUX_WCMD, LPDDRC_FLUX_RCMD, ++ LPDDRC_PRE_CMD, LPDDRC_ACT_CMD, LPDDRC_RNK_CHG, LPDDRC_RW_CHG ++}; ++ ++/* ++ * Select the counter register offset using the counter index. ++ * In PMU v1, there are no programmable counter, the count ++ * is read form the statistics counter register itself. ++ */ ++static u32 hisi_lpddrc_pmu_v1_get_counter_offset(int cntr_idx) ++{ ++ return lpddrc_reg_off[cntr_idx]; ++} ++ ++static u64 hisi_lpddrc_pmu_v1_read_counter(struct hisi_pmu *lpddrc_pmu, ++ struct hw_perf_event *hwc) ++{ ++ return readl(lpddrc_pmu->base + ++ hisi_lpddrc_pmu_v1_get_counter_offset(hwc->idx)); ++} ++ ++/* ++ * For LPDDRC PMU, event counter should be reset when start counters, ++ * reset the prev_count by software, because the counter register was RO. ++ */ ++static void hisi_lpddrc_pmu_v1_write_counter(struct hisi_pmu *lpddrc_pmu, ++ struct hw_perf_event *hwc, u64 val) ++{ ++ local64_set(&hwc->prev_count, 0); ++} ++ ++/* ++ * For LPDDRC PMU v1, event has been mapped to fixed-purpose counter by hardware, ++ * so there is no need to write event type, while it is programmable counter in ++ * PMU v2. ++ */ ++static void hisi_lpddrc_pmu_write_evtype(struct hisi_pmu *hha_pmu, int idx, ++ u32 type) ++{ ++} ++ ++static void hisi_lpddrc_pmu_v1_start_counters(struct hisi_pmu *lpddrc_pmu) ++{ ++ u32 val; ++ ++ /* Set perf_enable in LPDDRC_PERF_CTRL to start event counting */ ++ val = readl(lpddrc_pmu->base + LPDDRC_PERF_CTRL); ++ val |= LPDDRC_V1_PERF_CTRL_EN; ++ writel(val, lpddrc_pmu->base + LPDDRC_PERF_CTRL); ++} ++ ++static void hisi_lpddrc_pmu_v1_stop_counters(struct hisi_pmu *lpddrc_pmu) ++{ ++ u32 val; ++ ++ /* Clear perf_enable in LPDDRC_PERF_CTRL to stop event counting */ ++ val = readl(lpddrc_pmu->base + LPDDRC_PERF_CTRL); ++ val &= ~LPDDRC_V1_PERF_CTRL_EN; ++ writel(val, lpddrc_pmu->base + LPDDRC_PERF_CTRL); ++} ++ ++static void hisi_lpddrc_pmu_v1_enable_counter(struct hisi_pmu *lpddrc_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ /* Set counter index(event code) in LPDDRC_EVENT_CTRL register */ ++ val = readl(lpddrc_pmu->base + LPDDRC_EVENT_CTRL); ++ val |= (1 << GET_LPDDRC_EVENTID(hwc)); ++ writel(val, lpddrc_pmu->base + LPDDRC_EVENT_CTRL); ++} ++ ++static void hisi_lpddrc_pmu_v1_disable_counter(struct hisi_pmu *lpddrc_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ /* Clear counter index(event code) in LPDDRC_EVENT_CTRL register */ ++ val = readl(lpddrc_pmu->base + LPDDRC_EVENT_CTRL); ++ val &= ~(1 << GET_LPDDRC_EVENTID(hwc)); ++ writel(val, lpddrc_pmu->base + LPDDRC_EVENT_CTRL); ++} ++ ++static int hisi_lpddrc_pmu_v1_get_event_idx(struct perf_event *event) ++{ ++ struct hisi_pmu *lpddrc_pmu = to_hisi_pmu(event->pmu); ++ unsigned long *used_mask = lpddrc_pmu->pmu_events.used_mask; ++ struct hw_perf_event *hwc = &event->hw; ++ /* For LPDDRC PMU, we use event code as counter index */ ++ int idx = GET_LPDDRC_EVENTID(hwc); ++ ++ if (test_bit(idx, used_mask)) ++ return -EAGAIN; ++ ++ set_bit(idx, used_mask); ++ ++ return idx; ++} ++ ++static void hisi_lpddrc_pmu_v1_enable_counter_int(struct hisi_pmu *lpddrc_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ /* Write 0 to enable interrupt */ ++ val = readl(lpddrc_pmu->base + LPDDRC_INT_MASK); ++ val &= ~(1 << hwc->idx); ++ writel(val, lpddrc_pmu->base + LPDDRC_INT_MASK); ++} ++ ++static void hisi_lpddrc_pmu_v1_disable_counter_int(struct hisi_pmu *lpddrc_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ /* Write 1 to mask interrupt */ ++ val = readl(lpddrc_pmu->base + LPDDRC_INT_MASK); ++ val |= 1 << hwc->idx; ++ writel(val, lpddrc_pmu->base + LPDDRC_INT_MASK); ++} ++ ++static u32 hisi_lpddrc_pmu_v1_get_int_status(struct hisi_pmu *lpddrc_pmu) ++{ ++ return readl(lpddrc_pmu->base + LPDDRC_INT_STATUS); ++} ++ ++static void hisi_lpddrc_pmu_v1_clear_int_status(struct hisi_pmu *lpddrc_pmu, ++ int idx) ++{ ++ writel(1 << idx, lpddrc_pmu->base + LPDDRC_INT_CLEAR); ++} ++ ++static const struct acpi_device_id hisi_lpddrc_pmu_acpi_match[] = { ++ {} ++}; ++MODULE_DEVICE_TABLE(acpi, hisi_lpddrc_pmu_acpi_match); ++ ++static const struct of_device_id lpddrc_of_match[] = { ++ { .compatible = "hisilicon,lpddrc-pmu", }, ++ {}, ++}; ++ ++static int hisi_lpddrc_pmu_init_data(struct platform_device *pdev, ++ struct hisi_pmu *lpddrc_pmu) ++{ ++ /* ++ * Use the SCCL_ID and LPDDRC channel ID to identify the ++ * LPDDRC PMU, while SCCL_ID is in MPIDR[aff2]. ++ */ ++ if (device_property_read_u32(&pdev->dev, "hisilicon,ch-id", ++ &lpddrc_pmu->index_id)) { ++ dev_err(&pdev->dev, "Can not read lpddrc channel-id!\n"); ++ return -EINVAL; ++ } ++ ++ if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id", ++ &lpddrc_pmu->sccl_id)) { ++ dev_err(&pdev->dev, "Can not read lpddrc sccl-id!\n"); ++ return -EINVAL; ++ } ++ /* LPDDRC PMUs only share the same SCCL */ ++ lpddrc_pmu->ccl_id = -1; ++ ++ lpddrc_pmu->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(lpddrc_pmu->base)) { ++ dev_err(&pdev->dev, "ioremap failed for lpddrc_pmu resource\n"); ++ return PTR_ERR(lpddrc_pmu->base); ++ } ++ ++ lpddrc_pmu->identifier = readl(lpddrc_pmu->base + LPDDRC_VERSION); ++ ++ return 0; ++} ++ ++static struct attribute *hisi_lpddrc_pmu_v1_format_attr[] = { ++ HISI_PMU_FORMAT_ATTR(event, "config:0-4"), ++ NULL, ++}; ++ ++static const struct attribute_group hisi_lpddrc_pmu_v1_format_group = { ++ .name = "format", ++ .attrs = hisi_lpddrc_pmu_v1_format_attr, ++}; ++ ++static struct attribute *hisi_lpddrc_pmu_v1_events_attr[] = { ++ HISI_PMU_EVENT_ATTR(flux_wr, 0x00), ++ HISI_PMU_EVENT_ATTR(flux_rd, 0x01), ++ HISI_PMU_EVENT_ATTR(flux_wcmd, 0x02), ++ HISI_PMU_EVENT_ATTR(flux_rcmd, 0x03), ++ HISI_PMU_EVENT_ATTR(pre_cmd, 0x04), ++ HISI_PMU_EVENT_ATTR(act_cmd, 0x05), ++ HISI_PMU_EVENT_ATTR(rnk_chg, 0x06), ++ HISI_PMU_EVENT_ATTR(rw_chg, 0x07), ++ NULL, ++}; ++ ++static const struct attribute_group hisi_lpddrc_pmu_v1_events_group = { ++ .name = "events", ++ .attrs = hisi_lpddrc_pmu_v1_events_attr, ++}; ++ ++static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL); ++ ++static struct attribute *hisi_lpddrc_pmu_cpumask_attrs[] = { ++ &dev_attr_cpumask.attr, ++ NULL, ++}; ++ ++static const struct attribute_group hisi_lpddrc_pmu_cpumask_attr_group = { ++ .attrs = hisi_lpddrc_pmu_cpumask_attrs, ++}; ++ ++static struct device_attribute hisi_lpddrc_pmu_identifier_attr = ++ __ATTR(identifier, 0444, hisi_uncore_pmu_identifier_attr_show, NULL); ++ ++static struct attribute *hisi_lpddrc_pmu_identifier_attrs[] = { ++ &hisi_lpddrc_pmu_identifier_attr.attr, ++ NULL ++}; ++ ++static struct attribute_group hisi_lpddrc_pmu_identifier_group = { ++ .attrs = hisi_lpddrc_pmu_identifier_attrs, ++}; ++ ++static const struct attribute_group *hisi_lpddrc_pmu_v1_attr_groups[] = { ++ &hisi_lpddrc_pmu_v1_format_group, ++ &hisi_lpddrc_pmu_v1_events_group, ++ &hisi_lpddrc_pmu_cpumask_attr_group, ++ &hisi_lpddrc_pmu_identifier_group, ++ NULL, ++}; ++ ++static const struct hisi_uncore_ops hisi_uncore_lpddrc_v1_ops = { ++ .write_evtype = hisi_lpddrc_pmu_write_evtype, ++ .get_event_idx = hisi_lpddrc_pmu_v1_get_event_idx, ++ .start_counters = hisi_lpddrc_pmu_v1_start_counters, ++ .stop_counters = hisi_lpddrc_pmu_v1_stop_counters, ++ .enable_counter = hisi_lpddrc_pmu_v1_enable_counter, ++ .disable_counter = hisi_lpddrc_pmu_v1_disable_counter, ++ .enable_counter_int = hisi_lpddrc_pmu_v1_enable_counter_int, ++ .disable_counter_int = hisi_lpddrc_pmu_v1_disable_counter_int, ++ .write_counter = hisi_lpddrc_pmu_v1_write_counter, ++ .read_counter = hisi_lpddrc_pmu_v1_read_counter, ++ .get_int_status = hisi_lpddrc_pmu_v1_get_int_status, ++ .clear_int_status = hisi_lpddrc_pmu_v1_clear_int_status, ++}; ++ ++static int hisi_lpddrc_pmu_dev_probe(struct platform_device *pdev, ++ struct hisi_pmu *lpddrc_pmu) ++{ ++ int ret; ++ ++ ret = hisi_lpddrc_pmu_init_data(pdev, lpddrc_pmu); ++ if (ret) ++ return ret; ++ ++ ret = hisi_uncore_pmu_init_irq(lpddrc_pmu, pdev); ++ if (ret) ++ return ret; ++ ++ lpddrc_pmu->counter_bits = 32; ++ lpddrc_pmu->check_event = LPDDRC_V1_NR_EVENTS; ++ lpddrc_pmu->pmu_events.attr_groups = hisi_lpddrc_pmu_v1_attr_groups; ++ lpddrc_pmu->ops = &hisi_uncore_lpddrc_v1_ops; ++ ++ lpddrc_pmu->num_counters = LPDDRC_NR_COUNTERS; ++ lpddrc_pmu->dev = &pdev->dev; ++ lpddrc_pmu->on_cpu = -1; ++ ++ return 0; ++} ++ ++static int hisi_lpddrc_pmu_probe(struct platform_device *pdev) ++{ ++ struct hisi_pmu *lpddrc_pmu; ++ char *name; ++ int ret; ++ ++ lpddrc_pmu = devm_kzalloc(&pdev->dev, sizeof(*lpddrc_pmu), GFP_KERNEL); ++ if (!lpddrc_pmu) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, lpddrc_pmu); ++ ++ ret = hisi_lpddrc_pmu_dev_probe(pdev, lpddrc_pmu); ++ if (ret) ++ return ret; ++ ++ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, ++ "hisi_sccl%u_lpddrc%u", lpddrc_pmu->sccl_id, ++ lpddrc_pmu->index_id); ++ ++ lpddrc_pmu->pmu = (struct pmu) { ++ .name = name, ++ .module = THIS_MODULE, ++ .task_ctx_nr = perf_invalid_context, ++ .event_init = hisi_uncore_pmu_event_init, ++ .pmu_enable = hisi_uncore_pmu_enable, ++ .pmu_disable = hisi_uncore_pmu_disable, ++ .add = hisi_uncore_pmu_add, ++ .del = hisi_uncore_pmu_del, ++ .start = hisi_uncore_pmu_start, ++ .stop = hisi_uncore_pmu_stop, ++ .read = hisi_uncore_pmu_read, ++ .attr_groups = lpddrc_pmu->pmu_events.attr_groups, ++ .capabilities = PERF_PMU_CAP_NO_EXCLUDE, ++ }; ++ ++ /* Pick one core to use for cpumask attributes */ ++ cpumask_set_cpu(smp_processor_id(), &lpddrc_pmu->associated_cpus); ++ ++ lpddrc_pmu->on_cpu = cpumask_first(&lpddrc_pmu->associated_cpus); ++ if (lpddrc_pmu->on_cpu >= nr_cpu_ids) ++ return -EINVAL; ++ ++ ret = perf_pmu_register(&lpddrc_pmu->pmu, name, -1); ++ ++ return ret; ++} ++ ++static int hisi_lpddrc_pmu_remove(struct platform_device *pdev) ++{ ++ struct hisi_pmu *lpddrc_pmu = platform_get_drvdata(pdev); ++ ++ perf_pmu_unregister(&lpddrc_pmu->pmu); ++ return 0; ++} ++ ++static struct platform_driver hisi_lpddrc_pmu_driver = { ++ .driver = { ++ .name = "hisi_lpddrc_pmu", ++ .acpi_match_table = ACPI_PTR(hisi_lpddrc_pmu_acpi_match), ++ .of_match_table = lpddrc_of_match, ++ .suppress_bind_attrs = true, ++ }, ++ .probe = hisi_lpddrc_pmu_probe, ++ .remove = hisi_lpddrc_pmu_remove, ++}; ++ ++static int __init hisi_lpddrc_pmu_module_init(void) ++{ ++ int ret; ++ ++ ret = platform_driver_register(&hisi_lpddrc_pmu_driver); ++ ++ return ret; ++} ++module_init(hisi_lpddrc_pmu_module_init); ++ ++static void __exit hisi_lpddrc_pmu_module_exit(void) ++{ ++ platform_driver_unregister(&hisi_lpddrc_pmu_driver); ++} ++module_exit(hisi_lpddrc_pmu_module_exit); ++ ++MODULE_DESCRIPTION("HiSilicon SoC LPDDRC uncore PMU driver"); ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Shaokun Zhang "); ++MODULE_AUTHOR("Anurup M "); +-- +2.27.0 + diff --git a/patches/0068-perf-hisi-Fix-unexpected-modifications-in-hisi_uncor.patch b/patches/0068-perf-hisi-Fix-unexpected-modifications-in-hisi_uncor.patch new file mode 100644 index 0000000..c199c0d --- /dev/null +++ b/patches/0068-perf-hisi-Fix-unexpected-modifications-in-hisi_uncor.patch @@ -0,0 +1,41 @@ +From 91e203d62a15728846824029f1eb18fa8eb03aeb Mon Sep 17 00:00:00 2001 +From: Chen Jun +Date: Mon, 23 May 2022 21:18:33 +0800 +Subject: [PATCH 27/55] perf: hisi: Fix unexpected modifications in + hisi_uncore_l3c_pmu.c + +hulk inclusion +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I584X2 +CVE: NA + +-------------------------------- + +the name passed to cpuhp_setup_state_multi in hisi_uncore_l3c_pmu.c was +modification unexpected. + +Fixes: 744d0990ad13 ("perf: hisi: Add support for HiSilicon SoC L3TPMU") +Signed-off-by: Chen Jun +Reviewed-by: Weilong Chen +Signed-off-by: Zheng Zengkai +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +index bb39b44761a5..d70a01587d72 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +@@ -611,7 +611,7 @@ static int __init hisi_l3c_pmu_module_init(void) + int ret; + + ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE, +- "AP_PERF_ARM_HISI_L3T_ONLINE", ++ "AP_PERF_ARM_HISI_L3_ONLINE", + hisi_uncore_pmu_online_cpu, + hisi_uncore_pmu_offline_cpu); + if (ret) { +-- +2.27.0 + diff --git a/patches/0069-PCI-Add-pci_dev_id-helper.patch b/patches/0069-PCI-Add-pci_dev_id-helper.patch new file mode 100644 index 0000000..8eeeb9c --- /dev/null +++ b/patches/0069-PCI-Add-pci_dev_id-helper.patch @@ -0,0 +1,114 @@ +From 5fe54aa034e28dc979d147c3cf4a2ae25c529ff7 Mon Sep 17 00:00:00 2001 +From: Heiner Kallweit +Date: Wed, 24 Apr 2019 21:11:58 +0200 +Subject: [PATCH 28/55] PCI: Add pci_dev_id() helper + +mainline inclusion +from mainline-v5.2-rc1 +commit 4e544bac8267f65a0bf06aed1bde9964da4812ed +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4e544bac8267f65a0bf06aed1bde9964da4812ed + +---------------------------------------------------------------- + +In several places in the kernel we find PCI_DEVID used like this: + + PCI_DEVID(dev->bus->number, dev->devfn) + +Add a "pci_dev_id(struct pci_dev *dev)" helper to simplify callers. + +Signed-off-by: Heiner Kallweit +Signed-off-by: Bjorn Helgaas +Signed-off-by: hongrongxuan +--- + drivers/pci/msi.c | 6 +++--- + drivers/pci/search.c | 10 +++------- + include/linux/pci.h | 5 +++++ + 3 files changed, 11 insertions(+), 10 deletions(-) + +diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c +index bf560dcf8dd4..8138f67123a1 100644 +--- a/drivers/pci/msi.c ++++ b/drivers/pci/msi.c +@@ -1385,7 +1385,7 @@ irq_hw_number_t pci_msi_domain_calc_hwirq(struct pci_dev *dev, + struct msi_desc *desc) + { + return (irq_hw_number_t)desc->msi_attrib.entry_nr | +- PCI_DEVID(dev->bus->number, dev->devfn) << 11 | ++ pci_dev_id(dev) << 11 | + (pci_domain_nr(dev->bus) & 0xFFFFFFFF) << 27; + } + +@@ -1555,7 +1555,7 @@ static int get_msi_id_cb(struct pci_dev *pdev, u16 alias, void *data) + u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev) + { + struct device_node *of_node; +- u32 rid = PCI_DEVID(pdev->bus->number, pdev->devfn); ++ u32 rid = pci_dev_id(pdev); + + pci_for_each_dma_alias(pdev, get_msi_id_cb, &rid); + +@@ -1578,7 +1578,7 @@ u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev) + struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev) + { + struct irq_domain *dom; +- u32 rid = PCI_DEVID(pdev->bus->number, pdev->devfn); ++ u32 rid = pci_dev_id(pdev); + + pci_for_each_dma_alias(pdev, get_msi_id_cb, &rid); + dom = of_msi_map_get_device_domain(&pdev->dev, rid); +diff --git a/drivers/pci/search.c b/drivers/pci/search.c +index 2b5f720862d3..5c7922612733 100644 +--- a/drivers/pci/search.c ++++ b/drivers/pci/search.c +@@ -33,7 +33,7 @@ int pci_for_each_dma_alias(struct pci_dev *pdev, + struct pci_bus *bus; + int ret; + +- ret = fn(pdev, PCI_DEVID(pdev->bus->number, pdev->devfn), data); ++ ret = fn(pdev, pci_dev_id(pdev), data); + if (ret) + return ret; + +@@ -88,9 +88,7 @@ int pci_for_each_dma_alias(struct pci_dev *pdev, + return ret; + continue; + case PCI_EXP_TYPE_PCIE_BRIDGE: +- ret = fn(tmp, +- PCI_DEVID(tmp->bus->number, +- tmp->devfn), data); ++ ret = fn(tmp, pci_dev_id(tmp), data); + if (ret) + return ret; + continue; +@@ -101,9 +99,7 @@ int pci_for_each_dma_alias(struct pci_dev *pdev, + PCI_DEVID(tmp->subordinate->number, + PCI_DEVFN(0, 0)), data); + else +- ret = fn(tmp, +- PCI_DEVID(tmp->bus->number, +- tmp->devfn), data); ++ ret = fn(tmp, pci_dev_id(tmp), data); + if (ret) + return ret; + } +diff --git a/include/linux/pci.h b/include/linux/pci.h +index bc49349fcc53..bfc26f8d5552 100644 +--- a/include/linux/pci.h ++++ b/include/linux/pci.h +@@ -633,6 +633,11 @@ struct pci_bus { + + #define to_pci_bus(n) container_of(n, struct pci_bus, dev) + ++static inline u16 pci_dev_id(struct pci_dev *dev) ++{ ++ return PCI_DEVID(dev->bus->number, dev->devfn); ++} ++ + /* + * Returns true if the PCI bus is root (behind host-PCI bridge), + * false otherwise +-- +2.27.0 + diff --git a/patches/0070-drivers-perf-hisi-Add-driver-for-HiSilicon-PCIe-PMU.patch b/patches/0070-drivers-perf-hisi-Add-driver-for-HiSilicon-PCIe-PMU.patch new file mode 100644 index 0000000..bc6eaf8 --- /dev/null +++ b/patches/0070-drivers-perf-hisi-Add-driver-for-HiSilicon-PCIe-PMU.patch @@ -0,0 +1,1103 @@ +From 67e9f6f7130ec835cb534be5bf37b3b18af3eec5 Mon Sep 17 00:00:00 2001 +From: Qi Liu +Date: Tue, 9 Aug 2022 23:06:41 +0800 +Subject: [PATCH 29/55] drivers/perf: hisi: Add driver for HiSilicon PCIe PMU +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +mainline inclusion +from mainline-v5.17-rc1 +commit 8404b0fbc7fbd42e5c5d28cdedd450e70829c77a +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I5AZ87 +CVE: NA + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8404b0fbc7fb + +-------------------------------------------------------------------------- + +PCIe PMU Root Complex Integrated End Point(RCiEP) device is supported +to sample bandwidth, latency, buffer occupation etc. + +Each PMU RCiEP device monitors multiple Root Ports, and each RCiEP is +registered as a PMU in /sys/bus/event_source/devices, so users can +select target PMU, and use filter to do further sets. + +Filtering options contains: +event - select the event. +port - select target Root Ports. Information of Root Ports are + shown under sysfs. +bdf - select requester_id of target EP device. +trig_len - set trigger condition for starting event statistics. +trig_mode - set trigger mode. 0 means starting to statistic when bigger + than trigger condition, and 1 means smaller. +thr_len - set threshold for statistics. +thr_mode - set threshold mode. 0 means count when bigger than threshold, + and 1 means smaller. + +Acked-by: Krzysztof Wilczyński +Reviewed-by: John Garry +Signed-off-by: Qi Liu +Reviewed-by: Shaokun Zhang +Link: https://lore.kernel.org/r/20211202080633.2919-3-liuqi115@huawei.com +Signed-off-by: Will Deacon +Signed-off-by: Wangming Shao +Reviewed-by: Junhao He +Reviewed-by: Yang Jihong +Signed-off-by: Zheng Zengkai +Signed-off-by: hongrongxuan + + Conflicts: + MAINTAINERS + drivers/perf/hisilicon/hisi_pcie_pmu.c + +Differed from upstream version, this patch makes additional changes inside hisi_pcie_event_init function. +First, change the judgementation priority of event type to the first. +Second, move the event->cpu assginment to the last. +--- + MAINTAINERS | 5 +- + arch/arm64/configs/openeuler_defconfig | 3 +- + drivers/perf/hisilicon/Kconfig | 9 + + drivers/perf/hisilicon/Makefile | 2 + + drivers/perf/hisilicon/hisi_pcie_pmu.c | 951 +++++++++++++++++++++++++ + include/linux/cpuhotplug.h | 3 + + 6 files changed, 971 insertions(+), 2 deletions(-) + create mode 100644 drivers/perf/hisilicon/hisi_pcie_pmu.c + +diff --git a/MAINTAINERS b/MAINTAINERS +index f8ea3138d341..b4f1e5147b72 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -6660,8 +6660,11 @@ F: Documentation/devicetree/bindings/net/hisilicon*.txt + + HISILICON PMU DRIVER + M: Shaokun Zhang +-W: http://www.hisilicon.com ++M: Qi Liu + S: Supported ++W: http://www.hisilicon.com ++F: Documentation/admin-guide/perf/hisi-pcie-pmu.rst ++F: Documentation/admin-guide/perf/hisi-pmu.rst + F: drivers/perf/hisilicon + F: Documentation/perf/hisi-pmu.rst + +diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig +index b4d263c1f95b..6a7497f2df95 100644 +--- a/arch/arm64/configs/openeuler_defconfig ++++ b/arch/arm64/configs/openeuler_defconfig +@@ -5103,11 +5103,12 @@ CONFIG_ARM_PMU=y + CONFIG_ARM_PMU_ACPI=y + CONFIG_ARM_SMMU_V3_PMU=y + # CONFIG_ARM_DSU_PMU is not set +-CONFIG_HISI_PMU=m + CONFIG_QCOM_L2_PMU=y + CONFIG_QCOM_L3_PMU=y + CONFIG_XGENE_PMU=y + CONFIG_ARM_SPE_PMU=y ++CONFIG_HISI_PMU=m ++CONFIG_HISI_PCIE_PMU=m + CONFIG_RAS=y + + # +diff --git a/drivers/perf/hisilicon/Kconfig b/drivers/perf/hisilicon/Kconfig +index c5d1b7019fff..5546218b5598 100644 +--- a/drivers/perf/hisilicon/Kconfig ++++ b/drivers/perf/hisilicon/Kconfig +@@ -5,3 +5,12 @@ config HISI_PMU + help + Support for HiSilicon SoC L3 Cache performance monitor, Hydra Home + Agent performance monitor and DDR Controller performance monitor. ++ ++config HISI_PCIE_PMU ++ tristate "HiSilicon PCIE PERF PMU" ++ depends on PCI && ARM64 ++ help ++ Provide support for HiSilicon PCIe performance monitoring unit (PMU) ++ RCiEP devices. ++ Adds the PCIe PMU into perf events system for monitoring latency, ++ bandwidth etc. +diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile +index 22e384cdfd53..ad0e8110f373 100644 +--- a/drivers/perf/hisilicon/Makefile ++++ b/drivers/perf/hisilicon/Makefile +@@ -4,3 +4,5 @@ obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o \ + hisi_uncore_pa_pmu.o \ + hisi_uncore_l3t_pmu.o \ + hisi_uncore_lpddrc_pmu.o ++ ++obj-$(CONFIG_HISI_PCIE_PMU) += hisi_pcie_pmu.o +diff --git a/drivers/perf/hisilicon/hisi_pcie_pmu.c b/drivers/perf/hisilicon/hisi_pcie_pmu.c +new file mode 100644 +index 000000000000..1e9e841cfe95 +--- /dev/null ++++ b/drivers/perf/hisilicon/hisi_pcie_pmu.c +@@ -0,0 +1,951 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * This driver adds support for PCIe PMU RCiEP device. Related ++ * perf events are bandwidth, latency etc. ++ * ++ * Copyright (C) 2021 HiSilicon Limited ++ * Author: Qi Liu ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRV_NAME "hisi_pcie_pmu" ++/* Define registers */ ++#define HISI_PCIE_GLOBAL_CTRL 0x00 ++#define HISI_PCIE_EVENT_CTRL 0x010 ++#define HISI_PCIE_CNT 0x090 ++#define HISI_PCIE_EXT_CNT 0x110 ++#define HISI_PCIE_INT_STAT 0x150 ++#define HISI_PCIE_INT_MASK 0x154 ++#define HISI_PCIE_REG_BDF 0xfe0 ++#define HISI_PCIE_REG_VERSION 0xfe4 ++#define HISI_PCIE_REG_INFO 0xfe8 ++ ++/* Define command in HISI_PCIE_GLOBAL_CTRL */ ++#define HISI_PCIE_GLOBAL_EN 0x01 ++#define HISI_PCIE_GLOBAL_NONE 0 ++ ++/* Define command in HISI_PCIE_EVENT_CTRL */ ++#define HISI_PCIE_EVENT_EN BIT_ULL(20) ++#define HISI_PCIE_RESET_CNT BIT_ULL(22) ++#define HISI_PCIE_INIT_SET BIT_ULL(34) ++#define HISI_PCIE_THR_EN BIT_ULL(26) ++#define HISI_PCIE_TARGET_EN BIT_ULL(32) ++#define HISI_PCIE_TRIG_EN BIT_ULL(52) ++ ++/* Define offsets in HISI_PCIE_EVENT_CTRL */ ++#define HISI_PCIE_EVENT_M GENMASK_ULL(15, 0) ++#define HISI_PCIE_THR_MODE_M GENMASK_ULL(27, 27) ++#define HISI_PCIE_THR_M GENMASK_ULL(31, 28) ++#define HISI_PCIE_TARGET_M GENMASK_ULL(52, 36) ++#define HISI_PCIE_TRIG_MODE_M GENMASK_ULL(53, 53) ++#define HISI_PCIE_TRIG_M GENMASK_ULL(59, 56) ++ ++#define HISI_PCIE_MAX_COUNTERS 8 ++#define HISI_PCIE_REG_STEP 8 ++#define HISI_PCIE_THR_MAX_VAL 10 ++#define HISI_PCIE_TRIG_MAX_VAL 10 ++#define HISI_PCIE_MAX_PERIOD (GENMASK_ULL(63, 0)) ++#define HISI_PCIE_INIT_VAL BIT_ULL(63) ++ ++struct hisi_pcie_pmu { ++ struct perf_event *hw_events[HISI_PCIE_MAX_COUNTERS]; ++ struct hlist_node node; ++ struct pci_dev *pdev; ++ struct pmu pmu; ++ void __iomem *base; ++ int irq; ++ u32 identifier; ++ /* Minimum and maximum BDF of root ports monitored by PMU */ ++ u16 bdf_min; ++ u16 bdf_max; ++ int on_cpu; ++}; ++ ++struct hisi_pcie_reg_pair { ++ u16 lo; ++ u16 hi; ++}; ++ ++#define to_pcie_pmu(p) (container_of((p), struct hisi_pcie_pmu, pmu)) ++#define GET_PCI_DEVFN(bdf) ((bdf) & 0xff) ++ ++#define HISI_PCIE_PMU_FILTER_ATTR(_name, _config, _hi, _lo) \ ++ static u64 hisi_pcie_get_##_name(struct perf_event *event) \ ++ { \ ++ return FIELD_GET(GENMASK(_hi, _lo), event->attr._config); \ ++ } \ ++ ++HISI_PCIE_PMU_FILTER_ATTR(event, config, 16, 0); ++HISI_PCIE_PMU_FILTER_ATTR(thr_len, config1, 3, 0); ++HISI_PCIE_PMU_FILTER_ATTR(thr_mode, config1, 4, 4); ++HISI_PCIE_PMU_FILTER_ATTR(trig_len, config1, 8, 5); ++HISI_PCIE_PMU_FILTER_ATTR(trig_mode, config1, 9, 9); ++HISI_PCIE_PMU_FILTER_ATTR(port, config2, 15, 0); ++HISI_PCIE_PMU_FILTER_ATTR(bdf, config2, 31, 16); ++ ++static ssize_t hisi_pcie_format_sysfs_show(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct dev_ext_attribute *eattr; ++ ++ eattr = container_of(attr, struct dev_ext_attribute, attr); ++ ++ return sysfs_emit(buf, "%s\n", (char *)eattr->var); ++} ++ ++static ssize_t hisi_pcie_event_sysfs_show(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct perf_pmu_events_attr *pmu_attr = ++ container_of(attr, struct perf_pmu_events_attr, attr); ++ ++ return sysfs_emit(buf, "config=0x%llx\n", pmu_attr->id); ++} ++ ++#define HISI_PCIE_PMU_FORMAT_ATTR(_name, _format) \ ++ (&((struct dev_ext_attribute[]){ \ ++ { .attr = __ATTR(_name, 0444, hisi_pcie_format_sysfs_show, \ ++ NULL), \ ++ .var = (void *)_format } \ ++ })[0].attr.attr) ++ ++#define HISI_PCIE_PMU_EVENT_ATTR(_name, _id) \ ++ (&((struct perf_pmu_events_attr[]) { \ ++ { .attr = __ATTR(_name, 0444, hisi_pcie_event_sysfs_show, NULL), \ ++ .id = _id, } \ ++ })[0].attr.attr) ++ ++static ssize_t cpumask_show(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(dev_get_drvdata(dev)); ++ ++ return cpumap_print_to_pagebuf(true, buf, cpumask_of(pcie_pmu->on_cpu)); ++} ++static DEVICE_ATTR_RO(cpumask); ++ ++static ssize_t identifier_show(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(dev_get_drvdata(dev)); ++ ++ return sysfs_emit(buf, "%#x\n", pcie_pmu->identifier); ++} ++static DEVICE_ATTR_RO(identifier); ++ ++static ssize_t bus_show(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(dev_get_drvdata(dev)); ++ ++ return sysfs_emit(buf, "%#04x\n", PCI_BUS_NUM(pcie_pmu->bdf_min)); ++} ++static DEVICE_ATTR_RO(bus); ++ ++static struct hisi_pcie_reg_pair ++hisi_pcie_parse_reg_value(struct hisi_pcie_pmu *pcie_pmu, u32 reg_off) ++{ ++ u32 val = readl_relaxed(pcie_pmu->base + reg_off); ++ struct hisi_pcie_reg_pair regs = { ++ .lo = val, ++ .hi = val >> 16, ++ }; ++ ++ return regs; ++} ++ ++/* ++ * Hardware counter and ext_counter work together for bandwidth, latency, bus ++ * utilization and buffer occupancy events. For example, RX memory write latency ++ * events(index = 0x0010), counter counts total delay cycles and ext_counter ++ * counts RX memory write PCIe packets number. ++ * ++ * As we don't want PMU driver to process these two data, "delay cycles" can ++ * be treated as an independent event(index = 0x0010), "RX memory write packets ++ * number" as another(index = 0x10010). BIT 16 is used to distinguish and 0-15 ++ * bits are "real" event index, which can be used to set HISI_PCIE_EVENT_CTRL. ++ */ ++#define EXT_COUNTER_IS_USED(idx) ((idx) & BIT(16)) ++ ++static u32 hisi_pcie_get_real_event(struct perf_event *event) ++{ ++ return hisi_pcie_get_event(event) & GENMASK(15, 0); ++} ++ ++static u32 hisi_pcie_pmu_get_offset(u32 offset, u32 idx) ++{ ++ return offset + HISI_PCIE_REG_STEP * idx; ++} ++ ++static u32 hisi_pcie_pmu_readl(struct hisi_pcie_pmu *pcie_pmu, u32 reg_offset, ++ u32 idx) ++{ ++ u32 offset = hisi_pcie_pmu_get_offset(reg_offset, idx); ++ ++ return readl_relaxed(pcie_pmu->base + offset); ++} ++ ++static void hisi_pcie_pmu_writel(struct hisi_pcie_pmu *pcie_pmu, u32 reg_offset, u32 idx, u32 val) ++{ ++ u32 offset = hisi_pcie_pmu_get_offset(reg_offset, idx); ++ ++ writel_relaxed(val, pcie_pmu->base + offset); ++} ++ ++static u64 hisi_pcie_pmu_readq(struct hisi_pcie_pmu *pcie_pmu, u32 reg_offset, u32 idx) ++{ ++ u32 offset = hisi_pcie_pmu_get_offset(reg_offset, idx); ++ ++ return readq_relaxed(pcie_pmu->base + offset); ++} ++ ++static void hisi_pcie_pmu_writeq(struct hisi_pcie_pmu *pcie_pmu, u32 reg_offset, u32 idx, u64 val) ++{ ++ u32 offset = hisi_pcie_pmu_get_offset(reg_offset, idx); ++ ++ writeq_relaxed(val, pcie_pmu->base + offset); ++} ++ ++static void hisi_pcie_pmu_config_filter(struct perf_event *event) ++{ ++ struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(event->pmu); ++ struct hw_perf_event *hwc = &event->hw; ++ u64 reg = HISI_PCIE_INIT_SET; ++ u64 port, trig_len, thr_len; ++ ++ /* Config HISI_PCIE_EVENT_CTRL according to event. */ ++ reg |= FIELD_PREP(HISI_PCIE_EVENT_M, hisi_pcie_get_real_event(event)); ++ ++ /* Config HISI_PCIE_EVENT_CTRL according to root port or EP device. */ ++ port = hisi_pcie_get_port(event); ++ if (port) ++ reg |= FIELD_PREP(HISI_PCIE_TARGET_M, port); ++ else ++ reg |= HISI_PCIE_TARGET_EN | ++ FIELD_PREP(HISI_PCIE_TARGET_M, hisi_pcie_get_bdf(event)); ++ ++ /* Config HISI_PCIE_EVENT_CTRL according to trigger condition. */ ++ trig_len = hisi_pcie_get_trig_len(event); ++ if (trig_len) { ++ reg |= FIELD_PREP(HISI_PCIE_TRIG_M, trig_len); ++ reg |= FIELD_PREP(HISI_PCIE_TRIG_MODE_M, hisi_pcie_get_trig_mode(event)); ++ reg |= HISI_PCIE_TRIG_EN; ++ } ++ ++ /* Config HISI_PCIE_EVENT_CTRL according to threshold condition. */ ++ thr_len = hisi_pcie_get_thr_len(event); ++ if (thr_len) { ++ reg |= FIELD_PREP(HISI_PCIE_THR_M, thr_len); ++ reg |= FIELD_PREP(HISI_PCIE_THR_MODE_M, hisi_pcie_get_thr_mode(event)); ++ reg |= HISI_PCIE_THR_EN; ++ } ++ ++ hisi_pcie_pmu_writeq(pcie_pmu, HISI_PCIE_EVENT_CTRL, hwc->idx, reg); ++} ++ ++static void hisi_pcie_pmu_clear_filter(struct perf_event *event) ++{ ++ struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(event->pmu); ++ struct hw_perf_event *hwc = &event->hw; ++ ++ hisi_pcie_pmu_writeq(pcie_pmu, HISI_PCIE_EVENT_CTRL, hwc->idx, HISI_PCIE_INIT_SET); ++} ++ ++static bool hisi_pcie_pmu_valid_requester_id(struct hisi_pcie_pmu *pcie_pmu, u32 bdf) ++{ ++ struct pci_dev *root_port, *pdev; ++ u16 rp_bdf; ++ ++ pdev = pci_get_domain_bus_and_slot(pci_domain_nr(pcie_pmu->pdev->bus), PCI_BUS_NUM(bdf), ++ GET_PCI_DEVFN(bdf)); ++ if (!pdev) ++ return false; ++ ++ root_port = pcie_find_root_port(pdev); ++ if (!root_port) { ++ pci_dev_put(pdev); ++ return false; ++ } ++ ++ pci_dev_put(pdev); ++ rp_bdf = pci_dev_id(root_port); ++ return rp_bdf >= pcie_pmu->bdf_min && rp_bdf <= pcie_pmu->bdf_max; ++} ++ ++static bool hisi_pcie_pmu_valid_filter(struct perf_event *event, ++ struct hisi_pcie_pmu *pcie_pmu) ++{ ++ u32 requester_id = hisi_pcie_get_bdf(event); ++ ++ if (hisi_pcie_get_thr_len(event) > HISI_PCIE_THR_MAX_VAL) ++ return false; ++ ++ if (hisi_pcie_get_trig_len(event) > HISI_PCIE_TRIG_MAX_VAL) ++ return false; ++ ++ if (requester_id) { ++ if (!hisi_pcie_pmu_valid_requester_id(pcie_pmu, requester_id)) ++ return false; ++ } ++ ++ return true; ++} ++ ++static bool hisi_pcie_pmu_cmp_event(struct perf_event *target, ++ struct perf_event *event) ++{ ++ return hisi_pcie_get_real_event(target) == hisi_pcie_get_real_event(event); ++} ++ ++static bool hisi_pcie_pmu_validate_event_group(struct perf_event *event) ++{ ++ struct perf_event *sibling, *leader = event->group_leader; ++ struct perf_event *event_group[HISI_PCIE_MAX_COUNTERS]; ++ int counters = 1; ++ int num; ++ ++ event_group[0] = leader; ++ if (!is_software_event(leader)) { ++ if (leader->pmu != event->pmu) ++ return false; ++ ++ if (leader != event && !hisi_pcie_pmu_cmp_event(leader, event)) ++ event_group[counters++] = event; ++ } ++ ++ for_each_sibling_event(sibling, event->group_leader) { ++ if (is_software_event(sibling)) ++ continue; ++ ++ if (sibling->pmu != event->pmu) ++ return false; ++ ++ for (num = 0; num < counters; num++) { ++ if (hisi_pcie_pmu_cmp_event(event_group[num], sibling)) ++ break; ++ } ++ ++ if (num == counters) ++ event_group[counters++] = sibling; ++ } ++ ++ return counters <= HISI_PCIE_MAX_COUNTERS; ++} ++ ++static int hisi_pcie_pmu_event_init(struct perf_event *event) ++{ ++ struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(event->pmu); ++ struct hw_perf_event *hwc = &event->hw; ++ ++ if (event->attr.type != event->pmu->type) ++ return -ENOENT; ++ ++ if (EXT_COUNTER_IS_USED(hisi_pcie_get_event(event))) ++ hwc->event_base = HISI_PCIE_EXT_CNT; ++ else ++ hwc->event_base = HISI_PCIE_CNT; ++ ++ /* Sampling is not supported. */ ++ if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK) ++ return -EOPNOTSUPP; ++ ++ if (!hisi_pcie_pmu_valid_filter(event, pcie_pmu)) ++ return -EINVAL; ++ ++ if (!hisi_pcie_pmu_validate_event_group(event)) ++ return -EINVAL; ++ ++ event->cpu = pcie_pmu->on_cpu; ++ ++ return 0; ++} ++ ++static u64 hisi_pcie_pmu_read_counter(struct perf_event *event) ++{ ++ struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(event->pmu); ++ u32 idx = event->hw.idx; ++ ++ return hisi_pcie_pmu_readq(pcie_pmu, event->hw.event_base, idx); ++} ++ ++static int hisi_pcie_pmu_find_related_event(struct hisi_pcie_pmu *pcie_pmu, ++ struct perf_event *event) ++{ ++ struct perf_event *sibling; ++ int idx; ++ ++ for (idx = 0; idx < HISI_PCIE_MAX_COUNTERS; idx++) { ++ sibling = pcie_pmu->hw_events[idx]; ++ if (!sibling) ++ continue; ++ ++ if (!hisi_pcie_pmu_cmp_event(sibling, event)) ++ continue; ++ ++ /* Related events must be used in group */ ++ if (sibling->group_leader == event->group_leader) ++ return idx; ++ else ++ return -EINVAL; ++ } ++ ++ return idx; ++} ++ ++static int hisi_pcie_pmu_get_event_idx(struct hisi_pcie_pmu *pcie_pmu) ++{ ++ int idx; ++ ++ for (idx = 0; idx < HISI_PCIE_MAX_COUNTERS; idx++) { ++ if (!pcie_pmu->hw_events[idx]) ++ return idx; ++ } ++ ++ return -EINVAL; ++} ++ ++static void hisi_pcie_pmu_event_update(struct perf_event *event) ++{ ++ struct hw_perf_event *hwc = &event->hw; ++ u64 new_cnt, prev_cnt, delta; ++ ++ do { ++ prev_cnt = local64_read(&hwc->prev_count); ++ new_cnt = hisi_pcie_pmu_read_counter(event); ++ } while (local64_cmpxchg(&hwc->prev_count, prev_cnt, ++ new_cnt) != prev_cnt); ++ ++ delta = (new_cnt - prev_cnt) & HISI_PCIE_MAX_PERIOD; ++ local64_add(delta, &event->count); ++} ++ ++static void hisi_pcie_pmu_read(struct perf_event *event) ++{ ++ hisi_pcie_pmu_event_update(event); ++} ++ ++static void hisi_pcie_pmu_set_period(struct perf_event *event) ++{ ++ struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(event->pmu); ++ struct hw_perf_event *hwc = &event->hw; ++ int idx = hwc->idx; ++ ++ local64_set(&hwc->prev_count, HISI_PCIE_INIT_VAL); ++ hisi_pcie_pmu_writeq(pcie_pmu, HISI_PCIE_CNT, idx, HISI_PCIE_INIT_VAL); ++ hisi_pcie_pmu_writeq(pcie_pmu, HISI_PCIE_EXT_CNT, idx, HISI_PCIE_INIT_VAL); ++} ++ ++static void hisi_pcie_pmu_enable_counter(struct hisi_pcie_pmu *pcie_pmu, struct hw_perf_event *hwc) ++{ ++ u32 idx = hwc->idx; ++ u64 val; ++ ++ val = hisi_pcie_pmu_readq(pcie_pmu, HISI_PCIE_EVENT_CTRL, idx); ++ val |= HISI_PCIE_EVENT_EN; ++ hisi_pcie_pmu_writeq(pcie_pmu, HISI_PCIE_EVENT_CTRL, idx, val); ++} ++ ++static void hisi_pcie_pmu_disable_counter(struct hisi_pcie_pmu *pcie_pmu, struct hw_perf_event *hwc) ++{ ++ u32 idx = hwc->idx; ++ u64 val; ++ ++ val = hisi_pcie_pmu_readq(pcie_pmu, HISI_PCIE_EVENT_CTRL, idx); ++ val &= ~HISI_PCIE_EVENT_EN; ++ hisi_pcie_pmu_writeq(pcie_pmu, HISI_PCIE_EVENT_CTRL, idx, val); ++} ++ ++static void hisi_pcie_pmu_enable_int(struct hisi_pcie_pmu *pcie_pmu, struct hw_perf_event *hwc) ++{ ++ u32 idx = hwc->idx; ++ ++ hisi_pcie_pmu_writel(pcie_pmu, HISI_PCIE_INT_MASK, idx, 0); ++} ++ ++static void hisi_pcie_pmu_disable_int(struct hisi_pcie_pmu *pcie_pmu, struct hw_perf_event *hwc) ++{ ++ u32 idx = hwc->idx; ++ ++ hisi_pcie_pmu_writel(pcie_pmu, HISI_PCIE_INT_MASK, idx, 1); ++} ++ ++static void hisi_pcie_pmu_reset_counter(struct hisi_pcie_pmu *pcie_pmu, int idx) ++{ ++ hisi_pcie_pmu_writeq(pcie_pmu, HISI_PCIE_EVENT_CTRL, idx, HISI_PCIE_RESET_CNT); ++ hisi_pcie_pmu_writeq(pcie_pmu, HISI_PCIE_EVENT_CTRL, idx, HISI_PCIE_INIT_SET); ++} ++ ++static void hisi_pcie_pmu_start(struct perf_event *event, int flags) ++{ ++ struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(event->pmu); ++ struct hw_perf_event *hwc = &event->hw; ++ int idx = hwc->idx; ++ u64 prev_cnt; ++ ++ if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED))) ++ return; ++ ++ WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE)); ++ hwc->state = 0; ++ ++ hisi_pcie_pmu_config_filter(event); ++ hisi_pcie_pmu_enable_counter(pcie_pmu, hwc); ++ hisi_pcie_pmu_enable_int(pcie_pmu, hwc); ++ hisi_pcie_pmu_set_period(event); ++ ++ if (flags & PERF_EF_RELOAD) { ++ prev_cnt = local64_read(&hwc->prev_count); ++ hisi_pcie_pmu_writeq(pcie_pmu, hwc->event_base, idx, prev_cnt); ++ } ++ ++ perf_event_update_userpage(event); ++} ++ ++static void hisi_pcie_pmu_stop(struct perf_event *event, int flags) ++{ ++ struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(event->pmu); ++ struct hw_perf_event *hwc = &event->hw; ++ ++ hisi_pcie_pmu_event_update(event); ++ hisi_pcie_pmu_disable_int(pcie_pmu, hwc); ++ hisi_pcie_pmu_disable_counter(pcie_pmu, hwc); ++ hisi_pcie_pmu_clear_filter(event); ++ WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED); ++ hwc->state |= PERF_HES_STOPPED; ++ ++ if (hwc->state & PERF_HES_UPTODATE) ++ return; ++ ++ hwc->state |= PERF_HES_UPTODATE; ++} ++ ++static int hisi_pcie_pmu_add(struct perf_event *event, int flags) ++{ ++ struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(event->pmu); ++ struct hw_perf_event *hwc = &event->hw; ++ int idx; ++ ++ hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE; ++ ++ /* Check all working events to find a related event. */ ++ idx = hisi_pcie_pmu_find_related_event(pcie_pmu, event); ++ if (idx < 0) ++ return idx; ++ ++ /* Current event shares an enabled counter with the related event */ ++ if (idx < HISI_PCIE_MAX_COUNTERS) { ++ hwc->idx = idx; ++ goto start_count; ++ } ++ ++ idx = hisi_pcie_pmu_get_event_idx(pcie_pmu); ++ if (idx < 0) ++ return idx; ++ ++ hwc->idx = idx; ++ pcie_pmu->hw_events[idx] = event; ++ /* Reset Counter to avoid previous statistic interference. */ ++ hisi_pcie_pmu_reset_counter(pcie_pmu, idx); ++ ++start_count: ++ if (flags & PERF_EF_START) ++ hisi_pcie_pmu_start(event, PERF_EF_RELOAD); ++ ++ return 0; ++} ++ ++static void hisi_pcie_pmu_del(struct perf_event *event, int flags) ++{ ++ struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(event->pmu); ++ struct hw_perf_event *hwc = &event->hw; ++ ++ hisi_pcie_pmu_stop(event, PERF_EF_UPDATE); ++ pcie_pmu->hw_events[hwc->idx] = NULL; ++ perf_event_update_userpage(event); ++} ++ ++static void hisi_pcie_pmu_enable(struct pmu *pmu) ++{ ++ struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(pmu); ++ int num; ++ ++ for (num = 0; num < HISI_PCIE_MAX_COUNTERS; num++) { ++ if (pcie_pmu->hw_events[num]) ++ break; ++ } ++ ++ if (num == HISI_PCIE_MAX_COUNTERS) ++ return; ++ ++ writel(HISI_PCIE_GLOBAL_EN, pcie_pmu->base + HISI_PCIE_GLOBAL_CTRL); ++} ++ ++static void hisi_pcie_pmu_disable(struct pmu *pmu) ++{ ++ struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(pmu); ++ ++ writel(HISI_PCIE_GLOBAL_NONE, pcie_pmu->base + HISI_PCIE_GLOBAL_CTRL); ++} ++ ++static irqreturn_t hisi_pcie_pmu_irq(int irq, void *data) ++{ ++ struct hisi_pcie_pmu *pcie_pmu = data; ++ irqreturn_t ret = IRQ_NONE; ++ struct perf_event *event; ++ u32 overflown; ++ int idx; ++ ++ for (idx = 0; idx < HISI_PCIE_MAX_COUNTERS; idx++) { ++ overflown = hisi_pcie_pmu_readl(pcie_pmu, HISI_PCIE_INT_STAT, idx); ++ if (!overflown) ++ continue; ++ ++ /* Clear status of interrupt. */ ++ hisi_pcie_pmu_writel(pcie_pmu, HISI_PCIE_INT_STAT, idx, 1); ++ event = pcie_pmu->hw_events[idx]; ++ if (!event) ++ continue; ++ ++ hisi_pcie_pmu_event_update(event); ++ hisi_pcie_pmu_set_period(event); ++ ret = IRQ_HANDLED; ++ } ++ ++ return ret; ++} ++ ++static int hisi_pcie_pmu_irq_register(struct pci_dev *pdev, struct hisi_pcie_pmu *pcie_pmu) ++{ ++ int irq, ret; ++ ++ ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI); ++ if (ret < 0) { ++ pci_err(pdev, "Failed to enable MSI vectors: %d\n", ret); ++ return ret; ++ } ++ ++ irq = pci_irq_vector(pdev, 0); ++ ret = request_irq(irq, hisi_pcie_pmu_irq, IRQF_NOBALANCING | IRQF_NO_THREAD, DRV_NAME, ++ pcie_pmu); ++ if (ret) { ++ pci_err(pdev, "Failed to register IRQ: %d\n", ret); ++ pci_free_irq_vectors(pdev); ++ return ret; ++ } ++ ++ pcie_pmu->irq = irq; ++ ++ return 0; ++} ++ ++static void hisi_pcie_pmu_irq_unregister(struct pci_dev *pdev, struct hisi_pcie_pmu *pcie_pmu) ++{ ++ free_irq(pcie_pmu->irq, pcie_pmu); ++ pci_free_irq_vectors(pdev); ++} ++ ++static int hisi_pcie_pmu_online_cpu(unsigned int cpu, struct hlist_node *node) ++{ ++ struct hisi_pcie_pmu *pcie_pmu = hlist_entry_safe(node, struct hisi_pcie_pmu, node); ++ ++ if (pcie_pmu->on_cpu == -1) { ++ pcie_pmu->on_cpu = cpu; ++ WARN_ON(irq_set_affinity(pcie_pmu->irq, cpumask_of(cpu))); ++ } ++ ++ return 0; ++} ++ ++static int hisi_pcie_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node) ++{ ++ struct hisi_pcie_pmu *pcie_pmu = hlist_entry_safe(node, struct hisi_pcie_pmu, node); ++ unsigned int target; ++ ++ /* Nothing to do if this CPU doesn't own the PMU */ ++ if (pcie_pmu->on_cpu != cpu) ++ return 0; ++ ++ pcie_pmu->on_cpu = -1; ++ /* Choose a new CPU from all online cpus. */ ++ target = cpumask_first(cpu_online_mask); ++ if (target >= nr_cpu_ids) { ++ pci_err(pcie_pmu->pdev, "There is no CPU to set\n"); ++ return 0; ++ } ++ ++ perf_pmu_migrate_context(&pcie_pmu->pmu, cpu, target); ++ /* Use this CPU for event counting */ ++ pcie_pmu->on_cpu = target; ++ WARN_ON(irq_set_affinity(pcie_pmu->irq, cpumask_of(target))); ++ ++ return 0; ++} ++ ++static struct attribute *hisi_pcie_pmu_events_attr[] = { ++ HISI_PCIE_PMU_EVENT_ATTR(rx_mwr_latency, 0x0010), ++ HISI_PCIE_PMU_EVENT_ATTR(rx_mwr_cnt, 0x10010), ++ HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_latency, 0x0210), ++ HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_cnt, 0x10210), ++ HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_latency, 0x0011), ++ HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_cnt, 0x10011), ++ HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_flux, 0x1005), ++ HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_time, 0x11005), ++ HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_flux, 0x2004), ++ HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_time, 0x12004), ++ NULL ++}; ++ ++static struct attribute_group hisi_pcie_pmu_events_group = { ++ .name = "events", ++ .attrs = hisi_pcie_pmu_events_attr, ++}; ++ ++static struct attribute *hisi_pcie_pmu_format_attr[] = { ++ HISI_PCIE_PMU_FORMAT_ATTR(event, "config:0-16"), ++ HISI_PCIE_PMU_FORMAT_ATTR(thr_len, "config1:0-3"), ++ HISI_PCIE_PMU_FORMAT_ATTR(thr_mode, "config1:4"), ++ HISI_PCIE_PMU_FORMAT_ATTR(trig_len, "config1:5-8"), ++ HISI_PCIE_PMU_FORMAT_ATTR(trig_mode, "config1:9"), ++ HISI_PCIE_PMU_FORMAT_ATTR(port, "config2:0-15"), ++ HISI_PCIE_PMU_FORMAT_ATTR(bdf, "config2:16-31"), ++ NULL ++}; ++ ++static const struct attribute_group hisi_pcie_pmu_format_group = { ++ .name = "format", ++ .attrs = hisi_pcie_pmu_format_attr, ++}; ++ ++static struct attribute *hisi_pcie_pmu_bus_attrs[] = { ++ &dev_attr_bus.attr, ++ NULL ++}; ++ ++static const struct attribute_group hisi_pcie_pmu_bus_attr_group = { ++ .attrs = hisi_pcie_pmu_bus_attrs, ++}; ++ ++static struct attribute *hisi_pcie_pmu_cpumask_attrs[] = { ++ &dev_attr_cpumask.attr, ++ NULL ++}; ++ ++static const struct attribute_group hisi_pcie_pmu_cpumask_attr_group = { ++ .attrs = hisi_pcie_pmu_cpumask_attrs, ++}; ++ ++static struct attribute *hisi_pcie_pmu_identifier_attrs[] = { ++ &dev_attr_identifier.attr, ++ NULL ++}; ++ ++static const struct attribute_group hisi_pcie_pmu_identifier_attr_group = { ++ .attrs = hisi_pcie_pmu_identifier_attrs, ++}; ++ ++static const struct attribute_group *hisi_pcie_pmu_attr_groups[] = { ++ &hisi_pcie_pmu_events_group, ++ &hisi_pcie_pmu_format_group, ++ &hisi_pcie_pmu_bus_attr_group, ++ &hisi_pcie_pmu_cpumask_attr_group, ++ &hisi_pcie_pmu_identifier_attr_group, ++ NULL ++}; ++ ++static int hisi_pcie_alloc_pmu(struct pci_dev *pdev, struct hisi_pcie_pmu *pcie_pmu) ++{ ++ struct hisi_pcie_reg_pair regs; ++ u16 sicl_id, core_id; ++ char *name; ++ ++ regs = hisi_pcie_parse_reg_value(pcie_pmu, HISI_PCIE_REG_BDF); ++ pcie_pmu->bdf_min = regs.lo; ++ pcie_pmu->bdf_max = regs.hi; ++ ++ regs = hisi_pcie_parse_reg_value(pcie_pmu, HISI_PCIE_REG_INFO); ++ sicl_id = regs.hi; ++ core_id = regs.lo; ++ ++ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_pcie%u_core%u", sicl_id, core_id); ++ if (!name) ++ return -ENOMEM; ++ ++ pcie_pmu->pdev = pdev; ++ pcie_pmu->on_cpu = -1; ++ pcie_pmu->identifier = readl(pcie_pmu->base + HISI_PCIE_REG_VERSION); ++ pcie_pmu->pmu = (struct pmu) { ++ .name = name, ++ .module = THIS_MODULE, ++ .event_init = hisi_pcie_pmu_event_init, ++ .pmu_enable = hisi_pcie_pmu_enable, ++ .pmu_disable = hisi_pcie_pmu_disable, ++ .add = hisi_pcie_pmu_add, ++ .del = hisi_pcie_pmu_del, ++ .start = hisi_pcie_pmu_start, ++ .stop = hisi_pcie_pmu_stop, ++ .read = hisi_pcie_pmu_read, ++ .task_ctx_nr = perf_invalid_context, ++ .attr_groups = hisi_pcie_pmu_attr_groups, ++ .capabilities = PERF_PMU_CAP_NO_EXCLUDE, ++ }; ++ ++ return 0; ++} ++ ++static int hisi_pcie_init_pmu(struct pci_dev *pdev, struct hisi_pcie_pmu *pcie_pmu) ++{ ++ int ret; ++ ++ pcie_pmu->base = pci_ioremap_bar(pdev, 2); ++ if (!pcie_pmu->base) { ++ pci_err(pdev, "Ioremap failed for pcie_pmu resource\n"); ++ return -ENOMEM; ++ } ++ ++ ret = hisi_pcie_alloc_pmu(pdev, pcie_pmu); ++ if (ret) ++ goto err_iounmap; ++ ++ ret = hisi_pcie_pmu_irq_register(pdev, pcie_pmu); ++ if (ret) ++ goto err_iounmap; ++ ++ ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE, &pcie_pmu->node); ++ if (ret) { ++ pci_err(pdev, "Failed to register hotplug: %d\n", ret); ++ goto err_irq_unregister; ++ } ++ ++ ret = perf_pmu_register(&pcie_pmu->pmu, pcie_pmu->pmu.name, -1); ++ if (ret) { ++ pci_err(pdev, "Failed to register PCIe PMU: %d\n", ret); ++ goto err_hotplug_unregister; ++ } ++ ++ return ret; ++ ++err_hotplug_unregister: ++ cpuhp_state_remove_instance_nocalls( ++ CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE, &pcie_pmu->node); ++ ++err_irq_unregister: ++ hisi_pcie_pmu_irq_unregister(pdev, pcie_pmu); ++ ++err_iounmap: ++ iounmap(pcie_pmu->base); ++ ++ return ret; ++} ++ ++static void hisi_pcie_uninit_pmu(struct pci_dev *pdev) ++{ ++ struct hisi_pcie_pmu *pcie_pmu = pci_get_drvdata(pdev); ++ ++ perf_pmu_unregister(&pcie_pmu->pmu); ++ cpuhp_state_remove_instance_nocalls( ++ CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE, &pcie_pmu->node); ++ hisi_pcie_pmu_irq_unregister(pdev, pcie_pmu); ++ iounmap(pcie_pmu->base); ++} ++ ++static int hisi_pcie_init_dev(struct pci_dev *pdev) ++{ ++ int ret; ++ ++ ret = pcim_enable_device(pdev); ++ if (ret) { ++ pci_err(pdev, "Failed to enable PCI device: %d\n", ret); ++ return ret; ++ } ++ ++ ret = pcim_iomap_regions(pdev, BIT(2), DRV_NAME); ++ if (ret < 0) { ++ pci_err(pdev, "Failed to request PCI mem regions: %d\n", ret); ++ return ret; ++ } ++ ++ pci_set_master(pdev); ++ ++ return 0; ++} ++ ++static int hisi_pcie_pmu_probe(struct pci_dev *pdev, const struct pci_device_id *id) ++{ ++ struct hisi_pcie_pmu *pcie_pmu; ++ int ret; ++ ++ pcie_pmu = devm_kzalloc(&pdev->dev, sizeof(*pcie_pmu), GFP_KERNEL); ++ if (!pcie_pmu) ++ return -ENOMEM; ++ ++ ret = hisi_pcie_init_dev(pdev); ++ if (ret) ++ return ret; ++ ++ ret = hisi_pcie_init_pmu(pdev, pcie_pmu); ++ if (ret) ++ return ret; ++ ++ pci_set_drvdata(pdev, pcie_pmu); ++ ++ return ret; ++} ++ ++static void hisi_pcie_pmu_remove(struct pci_dev *pdev) ++{ ++ hisi_pcie_uninit_pmu(pdev); ++ pci_set_drvdata(pdev, NULL); ++} ++ ++static const struct pci_device_id hisi_pcie_pmu_ids[] = { ++ { PCI_DEVICE(PCI_VENDOR_ID_HUAWEI, 0xa12d) }, ++ { 0, } ++}; ++MODULE_DEVICE_TABLE(pci, hisi_pcie_pmu_ids); ++ ++static struct pci_driver hisi_pcie_pmu_driver = { ++ .name = DRV_NAME, ++ .id_table = hisi_pcie_pmu_ids, ++ .probe = hisi_pcie_pmu_probe, ++ .remove = hisi_pcie_pmu_remove, ++}; ++ ++static int __init hisi_pcie_module_init(void) ++{ ++ int ret; ++ ++ ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE, ++ "AP_PERF_ARM_HISI_PCIE_PMU_ONLINE", ++ hisi_pcie_pmu_online_cpu, ++ hisi_pcie_pmu_offline_cpu); ++ if (ret) { ++ pr_err("Failed to setup PCIe PMU hotplug: %d\n", ret); ++ return ret; ++ } ++ ++ ret = pci_register_driver(&hisi_pcie_pmu_driver); ++ if (ret) ++ cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE); ++ ++ return ret; ++} ++module_init(hisi_pcie_module_init); ++ ++static void __exit hisi_pcie_module_exit(void) ++{ ++ pci_unregister_driver(&hisi_pcie_pmu_driver); ++ cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE); ++} ++module_exit(hisi_pcie_module_exit); ++ ++MODULE_DESCRIPTION("HiSilicon PCIe PMU driver"); ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Qi Liu "); +diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h +index 225b095a96db..f4078abc061f 100644 +--- a/include/linux/cpuhotplug.h ++++ b/include/linux/cpuhotplug.h +@@ -163,6 +163,9 @@ enum cpuhp_state { + CPUHP_AP_PERF_ARM_HISI_L3_ONLINE, + CPUHP_AP_PERF_ARM_HISI_PA_ONLINE, + CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE, ++ #ifndef __GENKSYMS__ ++ CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE, ++ #endif + CPUHP_AP_PERF_ARM_L2X0_ONLINE, + CPUHP_AP_PERF_ARM_QCOM_L2_ONLINE, + CPUHP_AP_PERF_ARM_QCOM_L3_ONLINE, +-- +2.27.0 + diff --git a/patches/0071-drivers-perf-hisi-Associate-PMUs-in-SICL-with-CPUs-o.patch b/patches/0071-drivers-perf-hisi-Associate-PMUs-in-SICL-with-CPUs-o.patch new file mode 100644 index 0000000..5b9f979 --- /dev/null +++ b/patches/0071-drivers-perf-hisi-Associate-PMUs-in-SICL-with-CPUs-o.patch @@ -0,0 +1,116 @@ +From 0b7b0513121aea4c200c8cd639edf3d1eda1c248 Mon Sep 17 00:00:00 2001 +From: Qi Liu +Date: Tue, 9 Aug 2022 23:06:42 +0800 +Subject: [PATCH 30/55] drivers/perf: hisi: Associate PMUs in SICL with CPUs + online + +mainline inclusion +from mainline-v5.19-rc1 +commit 807907dae9701c4b0593d5195d4839f17d103314 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I5AZ87 +CVE: NA + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=807907dae970 + +-------------------------------------------------------------------------- + +If a PMU is in a SICL (Super IO cluster), it is not appropriate to +associate this PMU with a CPU die. So we associate it with all CPUs +online, rather than CPUs in the nearest SCCL. + +As the firmware of Hip09 platform hasn't been published yet, change +of PMU driver will not influence backwards compatibility between +driver and firmware. + +Signed-off-by: Qi Liu +Reviewed-by: John Garry +Link: https://lore.kernel.org/r/20220415102352.6665-2-liuqi115@huawei.com +Signed-off-by: Will Deacon +Signed-off-by: Wangming Shao +Reviewed-by: Junhao He +Reviewed-by: Yang Jihong +Signed-off-by: Zheng Zengkai +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_pa_pmu.c | 18 +++++++----------- + drivers/perf/hisilicon/hisi_uncore_pmu.c | 4 ++++ + drivers/perf/hisilicon/hisi_uncore_pmu.h | 1 + + 3 files changed, 12 insertions(+), 11 deletions(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c +index 390e59f4ef60..f1e6b5cee075 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c +@@ -258,13 +258,12 @@ static int hisi_pa_pmu_init_data(struct platform_device *pdev, + struct hisi_pmu *pa_pmu) + { + /* +- * Use the SCCL_ID and the index ID to identify the PA PMU, +- * while SCCL_ID is the nearst SCCL_ID from this SICL and +- * CPU core is chosen from this SCCL to manage this PMU. ++ * As PA PMU is in a SICL, use the SICL_ID and the index ID ++ * to identify the PA PMU. + */ + if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id", +- &pa_pmu->sccl_id)) { +- dev_err(&pdev->dev, "Cannot read sccl-id!\n"); ++ &pa_pmu->sicl_id)) { ++ dev_err(&pdev->dev, "Cannot read sicl-id!\n"); + return -EINVAL; + } + +@@ -275,6 +274,7 @@ static int hisi_pa_pmu_init_data(struct platform_device *pdev, + } + + pa_pmu->ccl_id = -1; ++ pa_pmu->sccl_id = -1; + + pa_pmu->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(pa_pmu->base)) { +@@ -399,13 +399,9 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev) + ret = hisi_pa_pmu_dev_probe(pdev, pa_pmu); + if (ret) + return ret; +- /* +- * PA is attached in SICL and the CPU core is chosen to manage this +- * PMU which is the nearest SCCL, while its SCCL_ID is greater than +- * one with the SICL_ID. +- */ ++ + name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sicl%u_pa%u", +- pa_pmu->sccl_id - 1, pa_pmu->index_id); ++ pa_pmu->sicl_id, pa_pmu->index_id); + if (!name) + return -ENOMEM; + +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c +index 4a781c2e1992..9aaaf9cf2b2a 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c +@@ -468,6 +468,10 @@ static bool hisi_pmu_cpu_is_associated_pmu(struct hisi_pmu *hisi_pmu) + { + int sccl_id, ccl_id; + ++ /* If SCCL_ID is -1, the PMU is in a SICL and has no CPU affinity */ ++ if (hisi_pmu->sccl_id == -1) ++ return true; ++ + if (hisi_pmu->ccl_id == -1) { + /* If CCL_ID is -1, the PMU only shares the same SCCL */ + hisi_read_sccl_and_ccl_id(&sccl_id, NULL); +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h +index de6aa17a1355..75dfc12e6497 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h +@@ -84,6 +84,7 @@ struct hisi_pmu { + struct device *dev; + struct hlist_node node; + int sccl_id; ++ int sicl_id; + int ccl_id; + void __iomem *base; + /* the ID of the PMU modules */ +-- +2.27.0 + diff --git a/patches/0072-driver-perf-hisi-fix-kabi-broken-for-struct-hisi_pmu.patch b/patches/0072-driver-perf-hisi-fix-kabi-broken-for-struct-hisi_pmu.patch new file mode 100644 index 0000000..a071efe --- /dev/null +++ b/patches/0072-driver-perf-hisi-fix-kabi-broken-for-struct-hisi_pmu.patch @@ -0,0 +1,75 @@ +From 55424d384fb9dab1f8ac81c7fdfce3260ec255e7 Mon Sep 17 00:00:00 2001 +From: hongrongxuan +Date: Thu, 19 Oct 2023 15:08:35 +0800 +Subject: [PATCH 31/55] driver/perf: hisi: fix kabi broken for struct hisi_pmu + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +------------------------------------------------------------------- + +fix kabi broken in struct hisi_uncore_ops, hisi_pmu_hwevents, +and hisi_pmu, then keep function "hisi_uncore_pmu_counter_valid" interface + +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_pmu.h | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h +index 75dfc12e6497..6a78c13176c2 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h +@@ -59,16 +59,20 @@ struct hisi_uncore_ops { + void (*disable_counter_int)(struct hisi_pmu *, struct hw_perf_event *); + void (*start_counters)(struct hisi_pmu *); + void (*stop_counters)(struct hisi_pmu *); ++#ifndef __GENKSYMS__ + u32 (*get_int_status)(struct hisi_pmu *hisi_pmu); + void (*clear_int_status)(struct hisi_pmu *hisi_pmu, int idx); + void (*enable_filter)(struct perf_event *event); + void (*disable_filter)(struct perf_event *event); ++#endif + }; + + struct hisi_pmu_hwevents { + struct perf_event *hw_events[HISI_MAX_COUNTERS]; + DECLARE_BITMAP(used_mask, HISI_MAX_COUNTERS); ++#ifndef __GENKSYMS__ + const struct attribute_group **attr_groups; ++#endif + }; + + /* Generic pmu struct for different pmu types */ +@@ -84,20 +88,27 @@ struct hisi_pmu { + struct device *dev; + struct hlist_node node; + int sccl_id; ++#ifndef __GENKSYMS__ + int sicl_id; ++#endif + int ccl_id; + void __iomem *base; + /* the ID of the PMU modules */ + u32 index_id; ++#ifndef __GENKSYMS__ + /* For DDRC PMU v2: each DDRC has more than one DMC */ + u32 sub_id; ++#endif + int num_counters; + int counter_bits; + /* check event code range */ + int check_event; ++#ifndef __GENKSYMS__ + u32 identifier; ++#endif + }; + ++int hisi_uncore_pmu_counter_valid(struct hisi_pmu *hisi_pmu, int idx); + int hisi_uncore_pmu_get_event_idx(struct perf_event *event); + void hisi_uncore_pmu_read(struct perf_event *event); + int hisi_uncore_pmu_add(struct perf_event *event, int flags); +-- +2.27.0 + diff --git a/patches/0073-drivers-perf-hisi-Add-Support-for-CPA-PMU.patch b/patches/0073-drivers-perf-hisi-Add-Support-for-CPA-PMU.patch new file mode 100644 index 0000000..668e2be --- /dev/null +++ b/patches/0073-drivers-perf-hisi-Add-Support-for-CPA-PMU.patch @@ -0,0 +1,486 @@ +From a75b20496157f6605843bf6399c7d082ec2a37b2 Mon Sep 17 00:00:00 2001 +From: Qi Liu +Date: Tue, 9 Aug 2022 23:06:43 +0800 +Subject: [PATCH 32/55] drivers/perf: hisi: Add Support for CPA PMU + +mainline inclusion +from mainline-v5.19-rc1 +commit 6b79738b6ed91a2d0fe958819469eeedac3bca81 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I5AZ87 +CVE: NA + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6b79738b6ed9 + +-------------------------------------------------------------------------- + +On HiSilicon Hip09 platform, there is a CPA (Coherency Protocol Agent) on +each SICL (Super IO Cluster) which implements packet format translation, +route parsing and traffic statistics. + +CPA PMU has 8 PMU counters and interrupt is supported to handle counter +overflow. Let's support its driver under the framework of HiSilicon PMU +driver. + +Signed-off-by: Qi Liu +Reviewed-by: John Garry +Reviewed-by: Shaokun Zhang +Link: https://lore.kernel.org/r/20220415102352.6665-3-liuqi115@huawei.com +Signed-off-by: Will Deacon +Signed-off-by: Wangming Shao +Reviewed-by: Junhao He +Reviewed-by: Yang Jihong +Signed-off-by: Zheng Zengkai +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/Makefile | 2 +- + drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c | 409 +++++++++++++++++++ + include/linux/cpuhotplug.h | 3 + + 3 files changed, 413 insertions(+), 1 deletion(-) + create mode 100644 drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c + +diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile +index ad0e8110f373..a3522abb3975 100644 +--- a/drivers/perf/hisilicon/Makefile ++++ b/drivers/perf/hisilicon/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0-only + obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o \ + hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_sllc_pmu.o \ +- hisi_uncore_pa_pmu.o \ ++ hisi_uncore_pa_pmu.o hisi_uncore_cpa_pmu.o \ + hisi_uncore_l3t_pmu.o \ + hisi_uncore_lpddrc_pmu.o + +diff --git a/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c +new file mode 100644 +index 000000000000..a9bb73f76be4 +--- /dev/null ++++ b/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c +@@ -0,0 +1,409 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * HiSilicon SoC CPA(Coherency Protocol Agent) hardware event counters support ++ * ++ * Copyright (C) 2022 HiSilicon Limited ++ * Author: Qi Liu ++ * ++ * This code is based on the uncore PMUs like arm-cci and arm-ccn. ++ */ ++ ++#define pr_fmt(fmt) "cpa pmu: " fmt ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "hisi_uncore_pmu.h" ++ ++/* CPA register definition */ ++#define CPA_PERF_CTRL 0x1c00 ++#define CPA_EVENT_CTRL 0x1c04 ++#define CPA_INT_MASK 0x1c70 ++#define CPA_INT_STATUS 0x1c78 ++#define CPA_INT_CLEAR 0x1c7c ++#define CPA_EVENT_TYPE0 0x1c80 ++#define CPA_VERSION 0x1cf0 ++#define CPA_CNT0_LOWER 0x1d00 ++#define CPA_CFG_REG 0x0534 ++ ++/* CPA operation command */ ++#define CPA_PERF_CTRL_EN BIT_ULL(0) ++#define CPA_EVTYPE_MASK 0xffUL ++#define CPA_PM_CTRL BIT_ULL(9) ++ ++/* CPA has 8-counters */ ++#define CPA_NR_COUNTERS 0x8 ++#define CPA_COUNTER_BITS 64 ++#define CPA_NR_EVENTS 0xff ++#define CPA_REG_OFFSET 0x8 ++ ++static u32 hisi_cpa_pmu_get_counter_offset(int idx) ++{ ++ return (CPA_CNT0_LOWER + idx * CPA_REG_OFFSET); ++} ++ ++static u64 hisi_cpa_pmu_read_counter(struct hisi_pmu *cpa_pmu, ++ struct hw_perf_event *hwc) ++{ ++ return readq(cpa_pmu->base + hisi_cpa_pmu_get_counter_offset(hwc->idx)); ++} ++ ++static void hisi_cpa_pmu_write_counter(struct hisi_pmu *cpa_pmu, ++ struct hw_perf_event *hwc, u64 val) ++{ ++ writeq(val, cpa_pmu->base + hisi_cpa_pmu_get_counter_offset(hwc->idx)); ++} ++ ++static void hisi_cpa_pmu_write_evtype(struct hisi_pmu *cpa_pmu, int idx, ++ u32 type) ++{ ++ u32 reg, reg_idx, shift, val; ++ ++ /* ++ * Select the appropriate event select register(CPA_EVENT_TYPE0/1). ++ * There are 2 event select registers for the 8 hardware counters. ++ * Event code is 8-bits and for the former 4 hardware counters, ++ * CPA_EVENT_TYPE0 is chosen. For the latter 4 hardware counters, ++ * CPA_EVENT_TYPE1 is chosen. ++ */ ++ reg = CPA_EVENT_TYPE0 + (idx / 4) * 4; ++ reg_idx = idx % 4; ++ shift = CPA_REG_OFFSET * reg_idx; ++ ++ /* Write event code to CPA_EVENT_TYPEx Register */ ++ val = readl(cpa_pmu->base + reg); ++ val &= ~(CPA_EVTYPE_MASK << shift); ++ val |= type << shift; ++ writel(val, cpa_pmu->base + reg); ++} ++ ++static void hisi_cpa_pmu_start_counters(struct hisi_pmu *cpa_pmu) ++{ ++ u32 val; ++ ++ val = readl(cpa_pmu->base + CPA_PERF_CTRL); ++ val |= CPA_PERF_CTRL_EN; ++ writel(val, cpa_pmu->base + CPA_PERF_CTRL); ++} ++ ++static void hisi_cpa_pmu_stop_counters(struct hisi_pmu *cpa_pmu) ++{ ++ u32 val; ++ ++ val = readl(cpa_pmu->base + CPA_PERF_CTRL); ++ val &= ~(CPA_PERF_CTRL_EN); ++ writel(val, cpa_pmu->base + CPA_PERF_CTRL); ++} ++ ++static void hisi_cpa_pmu_disable_pm(struct hisi_pmu *cpa_pmu) ++{ ++ u32 val; ++ ++ val = readl(cpa_pmu->base + CPA_CFG_REG); ++ val |= CPA_PM_CTRL; ++ writel(val, cpa_pmu->base + CPA_CFG_REG); ++} ++ ++static void hisi_cpa_pmu_enable_pm(struct hisi_pmu *cpa_pmu) ++{ ++ u32 val; ++ ++ val = readl(cpa_pmu->base + CPA_CFG_REG); ++ val &= ~(CPA_PM_CTRL); ++ writel(val, cpa_pmu->base + CPA_CFG_REG); ++} ++ ++static void hisi_cpa_pmu_enable_counter(struct hisi_pmu *cpa_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ /* Enable counter index in CPA_EVENT_CTRL register */ ++ val = readl(cpa_pmu->base + CPA_EVENT_CTRL); ++ val |= 1 << hwc->idx; ++ writel(val, cpa_pmu->base + CPA_EVENT_CTRL); ++} ++ ++static void hisi_cpa_pmu_disable_counter(struct hisi_pmu *cpa_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ /* Clear counter index in CPA_EVENT_CTRL register */ ++ val = readl(cpa_pmu->base + CPA_EVENT_CTRL); ++ val &= ~(1UL << hwc->idx); ++ writel(val, cpa_pmu->base + CPA_EVENT_CTRL); ++} ++ ++static void hisi_cpa_pmu_enable_counter_int(struct hisi_pmu *cpa_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ /* Write 0 to enable interrupt */ ++ val = readl(cpa_pmu->base + CPA_INT_MASK); ++ val &= ~(1UL << hwc->idx); ++ writel(val, cpa_pmu->base + CPA_INT_MASK); ++} ++ ++static void hisi_cpa_pmu_disable_counter_int(struct hisi_pmu *cpa_pmu, ++ struct hw_perf_event *hwc) ++{ ++ u32 val; ++ ++ /* Write 1 to mask interrupt */ ++ val = readl(cpa_pmu->base + CPA_INT_MASK); ++ val |= 1 << hwc->idx; ++ writel(val, cpa_pmu->base + CPA_INT_MASK); ++} ++ ++static u32 hisi_cpa_pmu_get_int_status(struct hisi_pmu *cpa_pmu) ++{ ++ return readl(cpa_pmu->base + CPA_INT_STATUS); ++} ++ ++static void hisi_cpa_pmu_clear_int_status(struct hisi_pmu *cpa_pmu, int idx) ++{ ++ writel(1 << idx, cpa_pmu->base + CPA_INT_CLEAR); ++} ++ ++static const struct acpi_device_id hisi_cpa_pmu_acpi_match[] = { ++ { "HISI0281", }, ++ {} ++}; ++MODULE_DEVICE_TABLE(acpi, hisi_cpa_pmu_acpi_match); ++ ++static int hisi_cpa_pmu_init_data(struct platform_device *pdev, ++ struct hisi_pmu *cpa_pmu) ++{ ++ if (device_property_read_u32(&pdev->dev, "hisilicon,scl-id", ++ &cpa_pmu->sicl_id)) { ++ dev_err(&pdev->dev, "Can not read sicl-id\n"); ++ return -EINVAL; ++ } ++ ++ if (device_property_read_u32(&pdev->dev, "hisilicon,idx-id", ++ &cpa_pmu->index_id)) { ++ dev_err(&pdev->dev, "Cannot read idx-id\n"); ++ return -EINVAL; ++ } ++ ++ cpa_pmu->ccl_id = -1; ++ cpa_pmu->sccl_id = -1; ++ cpa_pmu->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(cpa_pmu->base)) ++ return PTR_ERR(cpa_pmu->base); ++ ++ cpa_pmu->identifier = readl(cpa_pmu->base + CPA_VERSION); ++ ++ return 0; ++} ++ ++static struct attribute *hisi_cpa_pmu_format_attr[] = { ++ HISI_PMU_FORMAT_ATTR(event, "config:0-15"), ++ NULL ++}; ++ ++static const struct attribute_group hisi_cpa_pmu_format_group = { ++ .name = "format", ++ .attrs = hisi_cpa_pmu_format_attr, ++}; ++ ++static struct attribute *hisi_cpa_pmu_events_attr[] = { ++ HISI_PMU_EVENT_ATTR(cpa_cycles, 0x00), ++ HISI_PMU_EVENT_ATTR(cpa_p1_wr_dat, 0x61), ++ HISI_PMU_EVENT_ATTR(cpa_p1_rd_dat, 0x62), ++ HISI_PMU_EVENT_ATTR(cpa_p0_wr_dat, 0xE1), ++ HISI_PMU_EVENT_ATTR(cpa_p0_rd_dat, 0xE2), ++ NULL ++}; ++ ++static const struct attribute_group hisi_cpa_pmu_events_group = { ++ .name = "events", ++ .attrs = hisi_cpa_pmu_events_attr, ++}; ++ ++static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL); ++ ++static struct attribute *hisi_cpa_pmu_cpumask_attrs[] = { ++ &dev_attr_cpumask.attr, ++ NULL ++}; ++ ++static const struct attribute_group hisi_cpa_pmu_cpumask_attr_group = { ++ .attrs = hisi_cpa_pmu_cpumask_attrs, ++}; ++ ++static struct device_attribute hisi_cpa_pmu_identifier_attr = ++ __ATTR(identifier, 0444, hisi_uncore_pmu_identifier_attr_show, NULL); ++ ++static struct attribute *hisi_cpa_pmu_identifier_attrs[] = { ++ &hisi_cpa_pmu_identifier_attr.attr, ++ NULL ++}; ++ ++static const struct attribute_group hisi_cpa_pmu_identifier_group = { ++ .attrs = hisi_cpa_pmu_identifier_attrs, ++}; ++ ++static const struct attribute_group *hisi_cpa_pmu_attr_groups[] = { ++ &hisi_cpa_pmu_format_group, ++ &hisi_cpa_pmu_events_group, ++ &hisi_cpa_pmu_cpumask_attr_group, ++ &hisi_cpa_pmu_identifier_group, ++ NULL ++}; ++ ++static const struct hisi_uncore_ops hisi_uncore_cpa_pmu_ops = { ++ .write_evtype = hisi_cpa_pmu_write_evtype, ++ .get_event_idx = hisi_uncore_pmu_get_event_idx, ++ .start_counters = hisi_cpa_pmu_start_counters, ++ .stop_counters = hisi_cpa_pmu_stop_counters, ++ .enable_counter = hisi_cpa_pmu_enable_counter, ++ .disable_counter = hisi_cpa_pmu_disable_counter, ++ .enable_counter_int = hisi_cpa_pmu_enable_counter_int, ++ .disable_counter_int = hisi_cpa_pmu_disable_counter_int, ++ .write_counter = hisi_cpa_pmu_write_counter, ++ .read_counter = hisi_cpa_pmu_read_counter, ++ .get_int_status = hisi_cpa_pmu_get_int_status, ++ .clear_int_status = hisi_cpa_pmu_clear_int_status, ++}; ++ ++static int hisi_cpa_pmu_dev_probe(struct platform_device *pdev, ++ struct hisi_pmu *cpa_pmu) ++{ ++ int ret; ++ ++ ret = hisi_cpa_pmu_init_data(pdev, cpa_pmu); ++ if (ret) ++ return ret; ++ ++ ret = hisi_uncore_pmu_init_irq(cpa_pmu, pdev); ++ if (ret) ++ return ret; ++ ++ cpa_pmu->counter_bits = CPA_COUNTER_BITS; ++ cpa_pmu->check_event = CPA_NR_EVENTS; ++ cpa_pmu->pmu_events.attr_groups = hisi_cpa_pmu_attr_groups; ++ cpa_pmu->ops = &hisi_uncore_cpa_pmu_ops; ++ cpa_pmu->num_counters = CPA_NR_COUNTERS; ++ cpa_pmu->dev = &pdev->dev; ++ cpa_pmu->on_cpu = -1; ++ ++ return 0; ++} ++ ++static int hisi_cpa_pmu_probe(struct platform_device *pdev) ++{ ++ struct hisi_pmu *cpa_pmu; ++ char *name; ++ int ret; ++ ++ cpa_pmu = devm_kzalloc(&pdev->dev, sizeof(*cpa_pmu), GFP_KERNEL); ++ if (!cpa_pmu) ++ return -ENOMEM; ++ ++ ret = hisi_cpa_pmu_dev_probe(pdev, cpa_pmu); ++ if (ret) ++ return ret; ++ ++ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sicl%d_cpa%u", ++ cpa_pmu->sicl_id, cpa_pmu->index_id); ++ if (!name) ++ return -ENOMEM; ++ ++ cpa_pmu->pmu = (struct pmu) { ++ .name = name, ++ .module = THIS_MODULE, ++ .task_ctx_nr = perf_invalid_context, ++ .event_init = hisi_uncore_pmu_event_init, ++ .pmu_enable = hisi_uncore_pmu_enable, ++ .pmu_disable = hisi_uncore_pmu_disable, ++ .add = hisi_uncore_pmu_add, ++ .del = hisi_uncore_pmu_del, ++ .start = hisi_uncore_pmu_start, ++ .stop = hisi_uncore_pmu_stop, ++ .read = hisi_uncore_pmu_read, ++ .attr_groups = cpa_pmu->pmu_events.attr_groups, ++ .capabilities = PERF_PMU_CAP_NO_EXCLUDE, ++ }; ++ ++ /* Power Management should be disabled before using CPA PMU. */ ++ hisi_cpa_pmu_disable_pm(cpa_pmu); ++ ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE, ++ &cpa_pmu->node); ++ if (ret) { ++ dev_err(&pdev->dev, "Error %d registering hotplug\n", ret); ++ hisi_cpa_pmu_enable_pm(cpa_pmu); ++ return ret; ++ } ++ ++ ret = perf_pmu_register(&cpa_pmu->pmu, name, -1); ++ if (ret) { ++ dev_err(cpa_pmu->dev, "PMU register failed\n"); ++ cpuhp_state_remove_instance_nocalls( ++ CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE, &cpa_pmu->node); ++ hisi_cpa_pmu_enable_pm(cpa_pmu); ++ return ret; ++ } ++ ++ platform_set_drvdata(pdev, cpa_pmu); ++ return ret; ++} ++ ++static int hisi_cpa_pmu_remove(struct platform_device *pdev) ++{ ++ struct hisi_pmu *cpa_pmu = platform_get_drvdata(pdev); ++ ++ perf_pmu_unregister(&cpa_pmu->pmu); ++ cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE, ++ &cpa_pmu->node); ++ hisi_cpa_pmu_enable_pm(cpa_pmu); ++ return 0; ++} ++ ++static struct platform_driver hisi_cpa_pmu_driver = { ++ .driver = { ++ .name = "hisi_cpa_pmu", ++ .acpi_match_table = ACPI_PTR(hisi_cpa_pmu_acpi_match), ++ .suppress_bind_attrs = true, ++ }, ++ .probe = hisi_cpa_pmu_probe, ++ .remove = hisi_cpa_pmu_remove, ++}; ++ ++static int __init hisi_cpa_pmu_module_init(void) ++{ ++ int ret; ++ ++ ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE, ++ "AP_PERF_ARM_HISI_CPA_ONLINE", ++ hisi_uncore_pmu_online_cpu, ++ hisi_uncore_pmu_offline_cpu); ++ if (ret) { ++ pr_err("setup hotplug failed: %d\n", ret); ++ return ret; ++ } ++ ++ ret = platform_driver_register(&hisi_cpa_pmu_driver); ++ if (ret) ++ cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE); ++ ++ return ret; ++} ++module_init(hisi_cpa_pmu_module_init); ++ ++static void __exit hisi_cpa_pmu_module_exit(void) ++{ ++ platform_driver_unregister(&hisi_cpa_pmu_driver); ++ cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE); ++} ++module_exit(hisi_cpa_pmu_module_exit); ++ ++MODULE_DESCRIPTION("HiSilicon SoC CPA PMU driver"); ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Qi Liu "); +diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h +index f4078abc061f..ee782c3cb7f3 100644 +--- a/include/linux/cpuhotplug.h ++++ b/include/linux/cpuhotplug.h +@@ -158,6 +158,9 @@ enum cpuhp_state { + CPUHP_AP_PERF_S390_SF_ONLINE, + CPUHP_AP_PERF_ARM_CCI_ONLINE, + CPUHP_AP_PERF_ARM_CCN_ONLINE, ++ #ifndef __GENKSYMS__ ++ CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE, ++ #endif + CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE, + CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE, + CPUHP_AP_PERF_ARM_HISI_L3_ONLINE, +-- +2.27.0 + diff --git a/patches/0074-drivers-perf-hisi-Fix-some-event-id-for-hisi-pcie-pm.patch b/patches/0074-drivers-perf-hisi-Fix-some-event-id-for-hisi-pcie-pm.patch new file mode 100644 index 0000000..acf03d4 --- /dev/null +++ b/patches/0074-drivers-perf-hisi-Fix-some-event-id-for-hisi-pcie-pm.patch @@ -0,0 +1,48 @@ +From b860fa9563bef6669732959cf9fc9733b40a9721 Mon Sep 17 00:00:00 2001 +From: Yicong Yang +Date: Thu, 17 Nov 2022 16:41:33 +0800 +Subject: [PATCH 33/55] drivers/perf: hisi: Fix some event id for hisi-pcie-pmu + +mainline inclusion +from mainline-v6.2-rc1 +commit 6b4bb4f38dbfe85247f006f06135ba46450d5bf0 +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6b4bb4f38dbfe85247f006f06135ba46450d5bf0 + +---------------------------------------------------------------------------- + +Some event id of hisi-pcie-pmu is incorrect, fix them. + +Fixes: 8404b0fbc7fb ("drivers/perf: hisi: Add driver for HiSilicon PCIe PMU") +Reviewed-by: Jonathan Cameron +Signed-off-by: Yicong Yang +Link: https://lore.kernel.org/r/20221117084136.53572-2-yangyicong@huawei.com +Signed-off-by: Will Deacon +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_pcie_pmu.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/perf/hisilicon/hisi_pcie_pmu.c b/drivers/perf/hisilicon/hisi_pcie_pmu.c +index 1e9e841cfe95..c115f5c77acb 100644 +--- a/drivers/perf/hisilicon/hisi_pcie_pmu.c ++++ b/drivers/perf/hisilicon/hisi_pcie_pmu.c +@@ -696,10 +696,10 @@ static struct attribute *hisi_pcie_pmu_events_attr[] = { + HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_cnt, 0x10210), + HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_latency, 0x0011), + HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_cnt, 0x10011), +- HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_flux, 0x1005), +- HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_time, 0x11005), +- HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_flux, 0x2004), +- HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_time, 0x12004), ++ HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_flux, 0x0804), ++ HISI_PCIE_PMU_EVENT_ATTR(rx_mrd_time, 0x10804), ++ HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_flux, 0x0405), ++ HISI_PCIE_PMU_EVENT_ATTR(tx_mrd_time, 0x10405), + NULL + }; + +-- +2.27.0 + diff --git a/patches/0075-docs-perf-move-to-the-admin-guide.patch b/patches/0075-docs-perf-move-to-the-admin-guide.patch new file mode 100644 index 0000000..8e71003 --- /dev/null +++ b/patches/0075-docs-perf-move-to-the-admin-guide.patch @@ -0,0 +1,129 @@ +From 73bd937d975076c3f7754919d49d2610401dcf1b Mon Sep 17 00:00:00 2001 +From: Mauro Carvalho Chehab +Date: Tue, 18 Jun 2019 16:06:08 -0300 +Subject: [PATCH 34/55] docs: perf: move to the admin-guide + +mainline inclusion +from mainline-v5.3-rc1 +commit 59809fe88224db24432ad50e62fd8d5f0df738a1 +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=59809fe88224db24432ad50e62fd8d5f0df738a1 + +------------------------------------------------------------- + +The perf infrastructure is used for userspace to track issues. +At least a good part of what's described here is related to +it. + +So, add it to the admin-guide. + +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: hongrongxuan +--- + Documentation/admin-guide/index.rst | 1 + + Documentation/{ => admin-guide}/perf/arm-ccn.rst | 0 + Documentation/{ => admin-guide}/perf/arm_dsu_pmu.rst | 0 + Documentation/{ => admin-guide}/perf/hisi-pmu.rst | 0 + Documentation/{ => admin-guide}/perf/index.rst | 2 -- + Documentation/{ => admin-guide}/perf/qcom_l2_pmu.rst | 0 + Documentation/{ => admin-guide}/perf/qcom_l3_pmu.rst | 0 + Documentation/{ => admin-guide}/perf/xgene-pmu.rst | 0 + MAINTAINERS | 4 ++-- + drivers/perf/qcom_l3_pmu.c | 2 +- + 10 files changed, 4 insertions(+), 5 deletions(-) + rename Documentation/{ => admin-guide}/perf/arm-ccn.rst (100%) + rename Documentation/{ => admin-guide}/perf/arm_dsu_pmu.rst (100%) + rename Documentation/{ => admin-guide}/perf/hisi-pmu.rst (100%) + rename Documentation/{ => admin-guide}/perf/index.rst (95%) + rename Documentation/{ => admin-guide}/perf/qcom_l2_pmu.rst (100%) + rename Documentation/{ => admin-guide}/perf/qcom_l3_pmu.rst (100%) + rename Documentation/{ => admin-guide}/perf/xgene-pmu.rst (100%) + +diff --git a/Documentation/admin-guide/index.rst b/Documentation/admin-guide/index.rst +index 89abc5057349..b75b6ae6f662 100644 +--- a/Documentation/admin-guide/index.rst ++++ b/Documentation/admin-guide/index.rst +@@ -38,6 +38,7 @@ problems and bugs in particular. + ramoops + dynamic-debug-howto + init ++ perf/index + + This is the beginning of a section with information of interest to + application developers. Documents covering various aspects of the kernel +diff --git a/Documentation/perf/arm-ccn.rst b/Documentation/admin-guide/perf/arm-ccn.rst +similarity index 100% +rename from Documentation/perf/arm-ccn.rst +rename to Documentation/admin-guide/perf/arm-ccn.rst +diff --git a/Documentation/perf/arm_dsu_pmu.rst b/Documentation/admin-guide/perf/arm_dsu_pmu.rst +similarity index 100% +rename from Documentation/perf/arm_dsu_pmu.rst +rename to Documentation/admin-guide/perf/arm_dsu_pmu.rst +diff --git a/Documentation/perf/hisi-pmu.rst b/Documentation/admin-guide/perf/hisi-pmu.rst +similarity index 100% +rename from Documentation/perf/hisi-pmu.rst +rename to Documentation/admin-guide/perf/hisi-pmu.rst +diff --git a/Documentation/perf/index.rst b/Documentation/admin-guide/perf/index.rst +similarity index 95% +rename from Documentation/perf/index.rst +rename to Documentation/admin-guide/perf/index.rst +index 4bf848e27f26..9d445451ea18 100644 +--- a/Documentation/perf/index.rst ++++ b/Documentation/admin-guide/perf/index.rst +@@ -1,5 +1,3 @@ +-:orphan: +- + =========================== + Performance monitor support + =========================== +diff --git a/Documentation/perf/qcom_l2_pmu.rst b/Documentation/admin-guide/perf/qcom_l2_pmu.rst +similarity index 100% +rename from Documentation/perf/qcom_l2_pmu.rst +rename to Documentation/admin-guide/perf/qcom_l2_pmu.rst +diff --git a/Documentation/perf/qcom_l3_pmu.rst b/Documentation/admin-guide/perf/qcom_l3_pmu.rst +similarity index 100% +rename from Documentation/perf/qcom_l3_pmu.rst +rename to Documentation/admin-guide/perf/qcom_l3_pmu.rst +diff --git a/Documentation/perf/xgene-pmu.rst b/Documentation/admin-guide/perf/xgene-pmu.rst +similarity index 100% +rename from Documentation/perf/xgene-pmu.rst +rename to Documentation/admin-guide/perf/xgene-pmu.rst +diff --git a/MAINTAINERS b/MAINTAINERS +index 600f432e2e16..e9302e09600b 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -1040,7 +1040,7 @@ APPLIED MICRO (APM) X-GENE SOC PMU + M: Tai Nguyen + S: Supported + F: drivers/perf/xgene_pmu.c +-F: Documentation/perf/xgene-pmu.rst ++F: Documentation/admin-guide/perf/xgene-pmu.rst + F: Documentation/devicetree/bindings/perf/apm-xgene-pmu.txt + + APTINA CAMERA SENSOR PLL +@@ -6666,7 +6666,7 @@ W: http://www.hisilicon.com + F: Documentation/admin-guide/perf/hisi-pcie-pmu.rst + F: Documentation/admin-guide/perf/hisi-pmu.rst + F: drivers/perf/hisilicon +-F: Documentation/perf/hisi-pmu.rst ++F: Documentation/admin-guide/perf/hisi-pmu.rst + + HISILICON PTT DRIVER + M: Yicong Yang +diff --git a/drivers/perf/qcom_l3_pmu.c b/drivers/perf/qcom_l3_pmu.c +index cc88dc92577e..6cefee509e57 100644 +--- a/drivers/perf/qcom_l3_pmu.c ++++ b/drivers/perf/qcom_l3_pmu.c +@@ -7,7 +7,7 @@ + * the slices. User space needs to aggregate to individual counts to provide + * a global picture. + * +- * See Documentation/perf/qcom_l3_pmu.rst for more details. ++ * See Documentation/admin-guide/perf/qcom_l3_pmu.rst for more details. + * + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * +-- +2.27.0 + diff --git a/patches/0076-docs-perf-Add-new-description-on-HiSilicon-uncore-PM.patch b/patches/0076-docs-perf-Add-new-description-on-HiSilicon-uncore-PM.patch new file mode 100644 index 0000000..f025b8d --- /dev/null +++ b/patches/0076-docs-perf-Add-new-description-on-HiSilicon-uncore-PM.patch @@ -0,0 +1,96 @@ +From 4f573c490bf3b2880b8c93a20d2a9ef0d0b90c90 Mon Sep 17 00:00:00 2001 +From: Shaokun Zhang +Date: Mon, 8 Mar 2021 14:50:37 +0800 +Subject: [PATCH 35/55] docs: perf: Add new description on HiSilicon uncore PMU + v2 + +mainline inclusion +from mainline-v5.13-rc1 +commit 9b86b1b41e0f48b5b25918e07aeceb00e13d1ce2 +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9b86b1b41e0f48b5b25918e07aeceb00e13d1ce2 + +-------------------------------------------------------------------- + +Some news functions are added on HiSilicon uncore PMUs. Document them +to provide guidance on how to use them. + +Cc: Mark Rutland +Cc: Will Deacon +Cc: John Garry +Cc: Jonathan Cameron +Reviewed-by: John Garry +Co-developed-by: Qi Liu +Signed-off-by: Qi Liu +Signed-off-by: Shaokun Zhang +Link: https://lore.kernel.org/r/1615186237-22263-10-git-send-email-zhangshaokun@hisilicon.com +Signed-off-by: Will Deacon +Signed-off-by: hongrongxuan +--- + Documentation/admin-guide/perf/hisi-pmu.rst | 49 +++++++++++++++++++++ + 1 file changed, 49 insertions(+) + +diff --git a/Documentation/admin-guide/perf/hisi-pmu.rst b/Documentation/admin-guide/perf/hisi-pmu.rst +index 404a5c3d9d00..3b3120e2dd9e 100644 +--- a/Documentation/admin-guide/perf/hisi-pmu.rst ++++ b/Documentation/admin-guide/perf/hisi-pmu.rst +@@ -53,6 +53,55 @@ Example usage of perf:: + $# perf stat -a -e hisi_sccl3_l3c0/rd_hit_cpipe/ sleep 5 + $# perf stat -a -e hisi_sccl3_l3c0/config=0x02/ sleep 5 + ++For HiSilicon uncore PMU v2 whose identifier is 0x30, the topology is the same ++as PMU v1, but some new functions are added to the hardware. ++ ++(a) L3C PMU supports filtering by core/thread within the cluster which can be ++specified as a bitmap. ++ $# perf stat -a -e hisi_sccl3_l3c0/config=0x02,tt_core=0x3/ sleep 5 ++This will only count the operations from core/thread 0 and 1 in this cluster. ++ ++(b) Tracetag allow the user to chose to count only read, write or atomic ++operations via the tt_req parameeter in perf. The default value counts all ++operations. tt_req is 3bits, 3'b100 represents read operations, 3'b101 ++represents write operations, 3'b110 represents atomic store operations and ++3'b111 represents atomic non-store operations, other values are reserved. ++ $# perf stat -a -e hisi_sccl3_l3c0/config=0x02,tt_req=0x4/ sleep 5 ++This will only count the read operations in this cluster. ++ ++(c) Datasrc allows the user to check where the data comes from. It is 5 bits. ++Some important codes are as follows: ++5'b00001: comes from L3C in this die; ++5'b01000: comes from L3C in the cross-die; ++5'b01001: comes from L3C which is in another socket; ++5'b01110: comes from the local DDR; ++5'b01111: comes from the cross-die DDR; ++5'b10000: comes from cross-socket DDR; ++etc, it is mainly helpful to find that the data source is nearest from the CPU ++cores. If datasrc_cfg is used in the multi-chips, the datasrc_skt shall be ++configured in perf command. ++ $# perf stat -a -e hisi_sccl3_l3c0/config=0xb9,datasrc_cfg=0xE/, ++ hisi_sccl3_l3c0/config=0xb9,datasrc_cfg=0xF/ sleep 5 ++ ++(d)Some HiSilicon SoCs encapsulate multiple CPU and IO dies. Each CPU die ++contains several Compute Clusters (CCLs). The I/O dies are called Super I/O ++clusters (SICL) containing multiple I/O clusters (ICLs). Each CCL/ICL in the ++SoC has a unique ID. Each ID is 11bits, include a 6-bit SCCL-ID and 5-bit ++CCL/ICL-ID. For I/O die, the ICL-ID is followed by: ++5'b00000: I/O_MGMT_ICL; ++5'b00001: Network_ICL; ++5'b00011: HAC_ICL; ++5'b10000: PCIe_ICL; ++ ++Users could configure IDs to count data come from specific CCL/ICL, by setting ++srcid_cmd & srcid_msk, and data desitined for specific CCL/ICL by setting ++tgtid_cmd & tgtid_msk. A set bit in srcid_msk/tgtid_msk means the PMU will not ++check the bit when matching against the srcid_cmd/tgtid_cmd. ++ ++If all of these options are disabled, it can works by the default value that ++doesn't distinguish the filter condition and ID information and will return ++the total counter values in the PMU counters. ++ + The current driver does not support sampling. So "perf record" is unsupported. + Also attach to a task is unsupported as the events are all uncore. + +-- +2.27.0 + diff --git a/patches/0077-docs-perf-Add-description-for-HiSilicon-PCIe-PMU-dri.patch b/patches/0077-docs-perf-Add-description-for-HiSilicon-PCIe-PMU-dri.patch new file mode 100644 index 0000000..d32b3cc --- /dev/null +++ b/patches/0077-docs-perf-Add-description-for-HiSilicon-PCIe-PMU-dri.patch @@ -0,0 +1,145 @@ +From 3f70f78b4853cac77143fe82e99e5375628f8702 Mon Sep 17 00:00:00 2001 +From: Qi Liu +Date: Thu, 2 Dec 2021 16:06:32 +0800 +Subject: [PATCH 36/55] docs: perf: Add description for HiSilicon PCIe PMU + driver + +mainline inclusion +from mainline-v5.17-rc1 +commit c8602008e247f5603317c16f076565a96715e1ba +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c8602008e247f5603317c16f076565a96715e1ba + +------------------------------------------------------------------------ + +PCIe PMU Root Complex Integrated End Point(RCiEP) device is supported on +HiSilicon HIP09 platform. Document it to provide guidance on how to +use it. + +Reviewed-by: John Garry +Signed-off-by: Qi Liu +Reviewed-by: Shaokun Zhang +Link: https://lore.kernel.org/r/20211202080633.2919-2-liuqi115@huawei.com +Signed-off-by: Will Deacon +Signed-off-by: hongrongxuan +--- + .../admin-guide/perf/hisi-pcie-pmu.rst | 106 ++++++++++++++++++ + 1 file changed, 106 insertions(+) + create mode 100644 Documentation/admin-guide/perf/hisi-pcie-pmu.rst + +diff --git a/Documentation/admin-guide/perf/hisi-pcie-pmu.rst b/Documentation/admin-guide/perf/hisi-pcie-pmu.rst +new file mode 100644 +index 000000000000..294ebbdb22af +--- /dev/null ++++ b/Documentation/admin-guide/perf/hisi-pcie-pmu.rst +@@ -0,0 +1,106 @@ ++================================================ ++HiSilicon PCIe Performance Monitoring Unit (PMU) ++================================================ ++ ++On Hip09, HiSilicon PCIe Performance Monitoring Unit (PMU) could monitor ++bandwidth, latency, bus utilization and buffer occupancy data of PCIe. ++ ++Each PCIe Core has a PMU to monitor multi Root Ports of this PCIe Core and ++all Endpoints downstream these Root Ports. ++ ++ ++HiSilicon PCIe PMU driver ++========================= ++ ++The PCIe PMU driver registers a perf PMU with the name of its sicl-id and PCIe ++Core id.:: ++ ++ /sys/bus/event_source/hisi_pcie_ ++ ++PMU driver provides description of available events and filter options in sysfs, ++see /sys/bus/event_source/devices/hisi_pcie_. ++ ++The "format" directory describes all formats of the config (events) and config1 ++(filter options) fields of the perf_event_attr structure. The "events" directory ++describes all documented events shown in perf list. ++ ++The "identifier" sysfs file allows users to identify the version of the ++PMU hardware device. ++ ++The "bus" sysfs file allows users to get the bus number of Root Ports ++monitored by PMU. ++ ++Example usage of perf:: ++ ++ $# perf list ++ hisi_pcie0_0/rx_mwr_latency/ [kernel PMU event] ++ hisi_pcie0_0/rx_mwr_cnt/ [kernel PMU event] ++ ------------------------------------------ ++ ++ $# perf stat -e hisi_pcie0_0/rx_mwr_latency/ ++ $# perf stat -e hisi_pcie0_0/rx_mwr_cnt/ ++ $# perf stat -g -e hisi_pcie0_0/rx_mwr_latency/ -e hisi_pcie0_0/rx_mwr_cnt/ ++ ++The current driver does not support sampling. So "perf record" is unsupported. ++Also attach to a task is unsupported for PCIe PMU. ++ ++Filter options ++-------------- ++ ++1. Target filter ++PMU could only monitor the performance of traffic downstream target Root Ports ++or downstream target Endpoint. PCIe PMU driver support "port" and "bdf" ++interfaces for users, and these two interfaces aren't supported at the same ++time. ++ ++-port ++"port" filter can be used in all PCIe PMU events, target Root Port can be ++selected by configuring the 16-bits-bitmap "port". Multi ports can be selected ++for AP-layer-events, and only one port can be selected for TL/DL-layer-events. ++ ++For example, if target Root Port is 0000:00:00.0 (x8 lanes), bit0 of bitmap ++should be set, port=0x1; if target Root Port is 0000:00:04.0 (x4 lanes), ++bit8 is set, port=0x100; if these two Root Ports are both monitored, port=0x101. ++ ++Example usage of perf:: ++ ++ $# perf stat -e hisi_pcie0_0/rx_mwr_latency,port=0x1/ sleep 5 ++ ++-bdf ++ ++"bdf" filter can only be used in bandwidth events, target Endpoint is selected ++by configuring BDF to "bdf". Counter only counts the bandwidth of message ++requested by target Endpoint. ++ ++For example, "bdf=0x3900" means BDF of target Endpoint is 0000:39:00.0. ++ ++Example usage of perf:: ++ ++ $# perf stat -e hisi_pcie0_0/rx_mrd_flux,bdf=0x3900/ sleep 5 ++ ++2. Trigger filter ++Event statistics start when the first time TLP length is greater/smaller ++than trigger condition. You can set the trigger condition by writing "trig_len", ++and set the trigger mode by writing "trig_mode". This filter can only be used ++in bandwidth events. ++ ++For example, "trig_len=4" means trigger condition is 2^4 DW, "trig_mode=0" ++means statistics start when TLP length > trigger condition, "trig_mode=1" ++means start when TLP length < condition. ++ ++Example usage of perf:: ++ ++ $# perf stat -e hisi_pcie0_0/rx_mrd_flux,trig_len=0x4,trig_mode=1/ sleep 5 ++ ++3. Threshold filter ++Counter counts when TLP length within the specified range. You can set the ++threshold by writing "thr_len", and set the threshold mode by writing ++"thr_mode". This filter can only be used in bandwidth events. ++ ++For example, "thr_len=4" means threshold is 2^4 DW, "thr_mode=0" means ++counter counts when TLP length >= threshold, and "thr_mode=1" means counts ++when TLP length < threshold. ++ ++Example usage of perf:: ++ ++ $# perf stat -e hisi_pcie0_0/rx_mrd_flux,thr_len=0x4,thr_mode=1/ sleep 5 +-- +2.27.0 + diff --git a/patches/0078-docs-perf-Address-some-html-build-warnings.patch b/patches/0078-docs-perf-Address-some-html-build-warnings.patch new file mode 100644 index 0000000..1ab54ec --- /dev/null +++ b/patches/0078-docs-perf-Address-some-html-build-warnings.patch @@ -0,0 +1,71 @@ +From d1ff276b62baa5fd8138f2432bed59773702df7a Mon Sep 17 00:00:00 2001 +From: Qi Liu +Date: Mon, 29 Mar 2021 20:32:01 +0800 +Subject: [PATCH 37/55] docs: perf: Address some html build warnings + +mainline inclusion +from mainline-v5.13-rc1 +commit b88f5e9792cc320a511697dcba8890d032ee3ed3 +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b88f5e9792cc320a511697dcba8890d032ee3ed3 + +---------------------------------------------------------------------------- + +Fix following html build warnings: +Documentation/admin-guide/perf/hisi-pmu.rst:61: WARNING: Unexpected indentation. +Documentation/admin-guide/perf/hisi-pmu.rst:62: WARNING: Block quote ends without a blank line; unexpected unindent. +Documentation/admin-guide/perf/hisi-pmu.rst:69: WARNING: Unexpected indentation. +Documentation/admin-guide/perf/hisi-pmu.rst:70: WARNING: Block quote ends without a blank line; unexpected unindent. +Documentation/admin-guide/perf/hisi-pmu.rst:83: WARNING: Unexpected indentation. + +Fixes: 9b86b1b41e0f ("docs: perf: Add new description on HiSilicon uncore PMU v2") +Reported-by: Stephen Rothwell +Signed-off-by: Qi Liu +Link: https://lore.kernel.org/r/1617021121-31450-1-git-send-email-liuqi115@huawei.com +Signed-off-by: Will Deacon +Signed-off-by: hongrongxuan +--- + Documentation/admin-guide/perf/hisi-pmu.rst | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/Documentation/admin-guide/perf/hisi-pmu.rst b/Documentation/admin-guide/perf/hisi-pmu.rst +index 3b3120e2dd9e..546979360513 100644 +--- a/Documentation/admin-guide/perf/hisi-pmu.rst ++++ b/Documentation/admin-guide/perf/hisi-pmu.rst +@@ -57,16 +57,20 @@ For HiSilicon uncore PMU v2 whose identifier is 0x30, the topology is the same + as PMU v1, but some new functions are added to the hardware. + + (a) L3C PMU supports filtering by core/thread within the cluster which can be +-specified as a bitmap. ++specified as a bitmap:: ++ + $# perf stat -a -e hisi_sccl3_l3c0/config=0x02,tt_core=0x3/ sleep 5 ++ + This will only count the operations from core/thread 0 and 1 in this cluster. + + (b) Tracetag allow the user to chose to count only read, write or atomic + operations via the tt_req parameeter in perf. The default value counts all + operations. tt_req is 3bits, 3'b100 represents read operations, 3'b101 + represents write operations, 3'b110 represents atomic store operations and +-3'b111 represents atomic non-store operations, other values are reserved. ++3'b111 represents atomic non-store operations, other values are reserved:: ++ + $# perf stat -a -e hisi_sccl3_l3c0/config=0x02,tt_req=0x4/ sleep 5 ++ + This will only count the read operations in this cluster. + + (c) Datasrc allows the user to check where the data comes from. It is 5 bits. +@@ -79,7 +83,8 @@ Some important codes are as follows: + 5'b10000: comes from cross-socket DDR; + etc, it is mainly helpful to find that the data source is nearest from the CPU + cores. If datasrc_cfg is used in the multi-chips, the datasrc_skt shall be +-configured in perf command. ++configured in perf command:: ++ + $# perf stat -a -e hisi_sccl3_l3c0/config=0xb9,datasrc_cfg=0xE/, + hisi_sccl3_l3c0/config=0xb9,datasrc_cfg=0xF/ sleep 5 + +-- +2.27.0 + diff --git a/patches/0079-docs-fix-make-htmldocs-warning-in-perf.patch b/patches/0079-docs-fix-make-htmldocs-warning-in-perf.patch new file mode 100644 index 0000000..aa266d7 --- /dev/null +++ b/patches/0079-docs-fix-make-htmldocs-warning-in-perf.patch @@ -0,0 +1,43 @@ +From 73918c84177dc0867dafd8bb3826fead1289425f Mon Sep 17 00:00:00 2001 +From: Wan Jiabing +Date: Mon, 28 Feb 2022 11:16:56 +0800 +Subject: [PATCH 38/55] docs: fix 'make htmldocs' warning in perf + +mainline inclusion +from mainline-v5.18-rc1 +commit 0d6356d6cdd0afeb546f4e8ca653748a8ec3ba26 +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0d6356d6cdd0afeb546f4e8ca653748a8ec3ba26 + +------------------------------------------------------------------- + +Fix following 'make htmldocs' warnings: +./Documentation/admin-guide/perf/hisi-pcie-pmu.rst: WARNING: +document isn't included in any toctree + +Fixes: c8602008e247 ("docs: perf: Add description for HiSilicon PCIe PMU driver") +Signed-off-by: Wan Jiabing +Reviewed-by: John Garry +Link: https://lore.kernel.org/r/20220228031700.1669086-1-wanjiabing@vivo.com +Signed-off-by: Jonathan Corbet +Signed-off-by: hongrongxuan +--- + Documentation/admin-guide/perf/index.rst | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Documentation/admin-guide/perf/index.rst b/Documentation/admin-guide/perf/index.rst +index 9d445451ea18..5a9afa1263f6 100644 +--- a/Documentation/admin-guide/perf/index.rst ++++ b/Documentation/admin-guide/perf/index.rst +@@ -6,6 +6,7 @@ Performance monitor support + :maxdepth: 1 + + hisi-pmu ++ hisi-pcie-pmu + qcom_l2_pmu + qcom_l3_pmu + arm-ccn +-- +2.27.0 + diff --git a/patches/0080-docs-perf-Fix-PMU-instance-name-of-hisi-pcie-pmu.patch b/patches/0080-docs-perf-Fix-PMU-instance-name-of-hisi-pcie-pmu.patch new file mode 100644 index 0000000..7f8d115 --- /dev/null +++ b/patches/0080-docs-perf-Fix-PMU-instance-name-of-hisi-pcie-pmu.patch @@ -0,0 +1,99 @@ +From f6ad3073186b182d495dc42c48baac26cb1c16f2 Mon Sep 17 00:00:00 2001 +From: Yicong Yang +Date: Thu, 17 Nov 2022 16:41:34 +0800 +Subject: [PATCH 39/55] docs: perf: Fix PMU instance name of hisi-pcie-pmu + +mainline inclusion +from mainline-v6.2-rc1 +commit eb79f12b4c41dd2403a0d16772ee72fcd6416015 +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=eb79f12b4c41dd2403a0d16772ee72fcd6416015 + +-------------------------------------------------------------------- + +The PMU instance will be called hisi_pcie_core rather than +hisi_pcie_. Fix this in the documentation. + +Fixes: c8602008e247 ("docs: perf: Add description for HiSilicon PCIe PMU driver") +Reviewed-by: Jonathan Cameron +Signed-off-by: Yicong Yang +Link: https://lore.kernel.org/r/20221117084136.53572-3-yangyicong@huawei.com +Signed-off-by: Will Deacon +Signed-off-by: hongrongxuan +--- + .../admin-guide/perf/hisi-pcie-pmu.rst | 22 +++++++++---------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +diff --git a/Documentation/admin-guide/perf/hisi-pcie-pmu.rst b/Documentation/admin-guide/perf/hisi-pcie-pmu.rst +index 294ebbdb22af..bbe66480ff85 100644 +--- a/Documentation/admin-guide/perf/hisi-pcie-pmu.rst ++++ b/Documentation/admin-guide/perf/hisi-pcie-pmu.rst +@@ -15,10 +15,10 @@ HiSilicon PCIe PMU driver + The PCIe PMU driver registers a perf PMU with the name of its sicl-id and PCIe + Core id.:: + +- /sys/bus/event_source/hisi_pcie_ ++ /sys/bus/event_source/hisi_pcie_core + + PMU driver provides description of available events and filter options in sysfs, +-see /sys/bus/event_source/devices/hisi_pcie_. ++see /sys/bus/event_source/devices/hisi_pcie_core. + + The "format" directory describes all formats of the config (events) and config1 + (filter options) fields of the perf_event_attr structure. The "events" directory +@@ -33,13 +33,13 @@ monitored by PMU. + Example usage of perf:: + + $# perf list +- hisi_pcie0_0/rx_mwr_latency/ [kernel PMU event] +- hisi_pcie0_0/rx_mwr_cnt/ [kernel PMU event] ++ hisi_pcie0_core0/rx_mwr_latency/ [kernel PMU event] ++ hisi_pcie0_core0/rx_mwr_cnt/ [kernel PMU event] + ------------------------------------------ + +- $# perf stat -e hisi_pcie0_0/rx_mwr_latency/ +- $# perf stat -e hisi_pcie0_0/rx_mwr_cnt/ +- $# perf stat -g -e hisi_pcie0_0/rx_mwr_latency/ -e hisi_pcie0_0/rx_mwr_cnt/ ++ $# perf stat -e hisi_pcie0_core0/rx_mwr_latency/ ++ $# perf stat -e hisi_pcie0_core0/rx_mwr_cnt/ ++ $# perf stat -g -e hisi_pcie0_core0/rx_mwr_latency/ -e hisi_pcie0_core0/rx_mwr_cnt/ + + The current driver does not support sampling. So "perf record" is unsupported. + Also attach to a task is unsupported for PCIe PMU. +@@ -64,7 +64,7 @@ bit8 is set, port=0x100; if these two Root Ports are both monitored, port=0x101. + + Example usage of perf:: + +- $# perf stat -e hisi_pcie0_0/rx_mwr_latency,port=0x1/ sleep 5 ++ $# perf stat -e hisi_pcie0_core0/rx_mwr_latency,port=0x1/ sleep 5 + + -bdf + +@@ -76,7 +76,7 @@ For example, "bdf=0x3900" means BDF of target Endpoint is 0000:39:00.0. + + Example usage of perf:: + +- $# perf stat -e hisi_pcie0_0/rx_mrd_flux,bdf=0x3900/ sleep 5 ++ $# perf stat -e hisi_pcie0_core0/rx_mrd_flux,bdf=0x3900/ sleep 5 + + 2. Trigger filter + Event statistics start when the first time TLP length is greater/smaller +@@ -90,7 +90,7 @@ means start when TLP length < condition. + + Example usage of perf:: + +- $# perf stat -e hisi_pcie0_0/rx_mrd_flux,trig_len=0x4,trig_mode=1/ sleep 5 ++ $# perf stat -e hisi_pcie0_core0/rx_mrd_flux,trig_len=0x4,trig_mode=1/ sleep 5 + + 3. Threshold filter + Counter counts when TLP length within the specified range. You can set the +@@ -103,4 +103,4 @@ when TLP length < threshold. + + Example usage of perf:: + +- $# perf stat -e hisi_pcie0_0/rx_mrd_flux,thr_len=0x4,thr_mode=1/ sleep 5 ++ $# perf stat -e hisi_pcie0_core0/rx_mrd_flux,thr_len=0x4,thr_mode=1/ sleep 5 +-- +2.27.0 + diff --git a/patches/0081-drivers-perf-hisi-Add-TLP-filter-support.patch b/patches/0081-drivers-perf-hisi-Add-TLP-filter-support.patch new file mode 100644 index 0000000..b674c28 --- /dev/null +++ b/patches/0081-drivers-perf-hisi-Add-TLP-filter-support.patch @@ -0,0 +1,132 @@ +From 57b8735c25b887a4233ddf7930c821acc78ca3f1 Mon Sep 17 00:00:00 2001 +From: Yicong Yang +Date: Thu, 17 Nov 2022 16:41:36 +0800 +Subject: [PATCH 40/55] drivers/perf: hisi: Add TLP filter support + +mainline inclusion +from mainline-v6.2-rc1 +commit 17d573984d4d5ad73c7cb5edcf2024c585475b0c +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=17d573984d4d5ad73c7cb5edcf2024c585475b0c + +----------------------------------------------------------------------- + +The PMU support to filter the TLP when counting the bandwidth with below +options: + +- only count the TLP headers +- only count the TLP payloads +- count both TLP headers and payloads + +In the current driver it's default to count the TLP payloads only, which +will have an implicity side effects that on the traffic only have header +only TLPs, we'll get no data. + +Make this user configuration through "len_mode" parameter and make it +default to count both TLP headers and payloads when user not specified. +Also update the documentation for it. + +Reviewed-by: Jonathan Cameron +Signed-off-by: Yicong Yang +Link: https://lore.kernel.org/r/20221117084136.53572-5-yangyicong@huawei.com +Signed-off-by: Will Deacon +Signed-off-by: hongrongxuan +--- + .../admin-guide/perf/hisi-pcie-pmu.rst | 22 +++++++++++++++++-- + drivers/perf/hisilicon/hisi_pcie_pmu.c | 14 +++++++++++- + 2 files changed, 33 insertions(+), 3 deletions(-) + +diff --git a/Documentation/admin-guide/perf/hisi-pcie-pmu.rst b/Documentation/admin-guide/perf/hisi-pcie-pmu.rst +index bbe66480ff85..6bace0e24c3f 100644 +--- a/Documentation/admin-guide/perf/hisi-pcie-pmu.rst ++++ b/Documentation/admin-guide/perf/hisi-pcie-pmu.rst +@@ -101,6 +101,24 @@ For example, "thr_len=4" means threshold is 2^4 DW, "thr_mode=0" means + counter counts when TLP length >= threshold, and "thr_mode=1" means counts + when TLP length < threshold. + +-Example usage of perf:: ++ Example usage of perf:: ++ ++ $# perf stat -e hisi_pcie0_core0/rx_mrd_flux,thr_len=0x4,thr_mode=1/ sleep 5 ++ ++4. TLP Length filter ++ ++ When counting bandwidth, the data can be composed of certain parts of TLP ++ packets. You can specify it through "len_mode": ++ ++ - 2'b00: Reserved (Do not use this since the behaviour is undefined) ++ - 2'b01: Bandwidth of TLP payloads ++ - 2'b10: Bandwidth of TLP headers ++ - 2'b11: Bandwidth of both TLP payloads and headers ++ ++ For example, "len_mode=2" means only counting the bandwidth of TLP headers ++ and "len_mode=3" means the final bandwidth data is composed of both TLP ++ headers and payloads. Default value if not specified is 2'b11. ++ ++ Example usage of perf:: + +- $# perf stat -e hisi_pcie0_core0/rx_mrd_flux,thr_len=0x4,thr_mode=1/ sleep 5 ++ $# perf stat -e hisi_pcie0_core0/rx_mrd_flux,len_mode=0x1/ sleep 5 +diff --git a/drivers/perf/hisilicon/hisi_pcie_pmu.c b/drivers/perf/hisilicon/hisi_pcie_pmu.c +index c115f5c77acb..6ded72383bb6 100644 +--- a/drivers/perf/hisilicon/hisi_pcie_pmu.c ++++ b/drivers/perf/hisilicon/hisi_pcie_pmu.c +@@ -47,10 +47,14 @@ + #define HISI_PCIE_EVENT_M GENMASK_ULL(15, 0) + #define HISI_PCIE_THR_MODE_M GENMASK_ULL(27, 27) + #define HISI_PCIE_THR_M GENMASK_ULL(31, 28) ++#define HISI_PCIE_LEN_M GENMASK_ULL(35, 34) + #define HISI_PCIE_TARGET_M GENMASK_ULL(52, 36) + #define HISI_PCIE_TRIG_MODE_M GENMASK_ULL(53, 53) + #define HISI_PCIE_TRIG_M GENMASK_ULL(59, 56) + ++/* Default config of TLP length mode, will count both TLP headers and payloads */ ++#define HISI_PCIE_LEN_M_DEFAULT 3ULL ++ + #define HISI_PCIE_MAX_COUNTERS 8 + #define HISI_PCIE_REG_STEP 8 + #define HISI_PCIE_THR_MAX_VAL 10 +@@ -91,6 +95,7 @@ HISI_PCIE_PMU_FILTER_ATTR(thr_len, config1, 3, 0); + HISI_PCIE_PMU_FILTER_ATTR(thr_mode, config1, 4, 4); + HISI_PCIE_PMU_FILTER_ATTR(trig_len, config1, 8, 5); + HISI_PCIE_PMU_FILTER_ATTR(trig_mode, config1, 9, 9); ++HISI_PCIE_PMU_FILTER_ATTR(len_mode, config1, 11, 10); + HISI_PCIE_PMU_FILTER_ATTR(port, config2, 15, 0); + HISI_PCIE_PMU_FILTER_ATTR(bdf, config2, 31, 16); + +@@ -218,8 +223,8 @@ static void hisi_pcie_pmu_config_filter(struct perf_event *event) + { + struct hisi_pcie_pmu *pcie_pmu = to_pcie_pmu(event->pmu); + struct hw_perf_event *hwc = &event->hw; ++ u64 port, trig_len, thr_len, len_mode; + u64 reg = HISI_PCIE_INIT_SET; +- u64 port, trig_len, thr_len; + + /* Config HISI_PCIE_EVENT_CTRL according to event. */ + reg |= FIELD_PREP(HISI_PCIE_EVENT_M, hisi_pcie_get_real_event(event)); +@@ -248,6 +253,12 @@ static void hisi_pcie_pmu_config_filter(struct perf_event *event) + reg |= HISI_PCIE_THR_EN; + } + ++ len_mode = hisi_pcie_get_len_mode(event); ++ if (len_mode) ++ reg |= FIELD_PREP(HISI_PCIE_LEN_M, len_mode); ++ else ++ reg |= FIELD_PREP(HISI_PCIE_LEN_M, HISI_PCIE_LEN_M_DEFAULT); ++ + hisi_pcie_pmu_writeq(pcie_pmu, HISI_PCIE_EVENT_CTRL, hwc->idx, reg); + } + +@@ -714,6 +725,7 @@ static struct attribute *hisi_pcie_pmu_format_attr[] = { + HISI_PCIE_PMU_FORMAT_ATTR(thr_mode, "config1:4"), + HISI_PCIE_PMU_FORMAT_ATTR(trig_len, "config1:5-8"), + HISI_PCIE_PMU_FORMAT_ATTR(trig_mode, "config1:9"), ++ HISI_PCIE_PMU_FORMAT_ATTR(len_mode, "config1:10-11"), + HISI_PCIE_PMU_FORMAT_ATTR(port, "config2:0-15"), + HISI_PCIE_PMU_FORMAT_ATTR(bdf, "config2:16-31"), + NULL +-- +2.27.0 + diff --git a/patches/0082-drivers-perf-hisi-Don-t-migrate-perf-to-the-CPU-goin.patch b/patches/0082-drivers-perf-hisi-Don-t-migrate-perf-to-the-CPU-goin.patch new file mode 100644 index 0000000..48d1ed4 --- /dev/null +++ b/patches/0082-drivers-perf-hisi-Don-t-migrate-perf-to-the-CPU-goin.patch @@ -0,0 +1,71 @@ +From b6b92242583b60e26a251765356143092000674a Mon Sep 17 00:00:00 2001 +From: Junhao He +Date: Thu, 8 Jun 2023 14:07:55 +0800 +Subject: [PATCH 41/55] drivers/perf: hisi: Don't migrate perf to the CPU going + to teardown + +mainline inclusion +from mainline-v6.5-rc1 +commit 7a6a9f1c5a0a875a421db798d4b2ee022dc1ee1a +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7a6a9f1c5a0a875a421db798d4b2ee022dc1ee1a + +---------------------------------------------------------------------- + +The driver needs to migrate the perf context if the current using CPU going +to teardown. By the time calling the cpuhp::teardown() callback the +cpu_online_mask() hasn't updated yet and still includes the CPU going to +teardown. In current driver's implementation we may migrate the context +to the teardown CPU and leads to the below calltrace: + +... +[ 368.104662][ T932] task:cpuhp/0 state:D stack: 0 pid: 15 ppid: 2 flags:0x00000008 +[ 368.113699][ T932] Call trace: +[ 368.116834][ T932] __switch_to+0x7c/0xbc +[ 368.120924][ T932] __schedule+0x338/0x6f0 +[ 368.125098][ T932] schedule+0x50/0xe0 +[ 368.128926][ T932] schedule_preempt_disabled+0x18/0x24 +[ 368.134229][ T932] __mutex_lock.constprop.0+0x1d4/0x5dc +[ 368.139617][ T932] __mutex_lock_slowpath+0x1c/0x30 +[ 368.144573][ T932] mutex_lock+0x50/0x60 +[ 368.148579][ T932] perf_pmu_migrate_context+0x84/0x2b0 +[ 368.153884][ T932] hisi_pcie_pmu_offline_cpu+0x90/0xe0 [hisi_pcie_pmu] +[ 368.160579][ T932] cpuhp_invoke_callback+0x2a0/0x650 +[ 368.165707][ T932] cpuhp_thread_fun+0xe4/0x190 +[ 368.170316][ T932] smpboot_thread_fn+0x15c/0x1a0 +[ 368.175099][ T932] kthread+0x108/0x13c +[ 368.179012][ T932] ret_from_fork+0x10/0x18 +... + +Use function cpumask_any_but() to find one correct active cpu to fixes +this issue. + +Fixes: 8404b0fbc7fb ("drivers/perf: hisi: Add driver for HiSilicon PCIe PMU") +Signed-off-by: Junhao He +Reviewed-by: Jonathan Cameron +Reviewed-by: Yicong Yang +Acked-by: Mark Rutland +Link: https://lore.kernel.org/r/20230608114326.27649-1-hejunhao3@huawei.com +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_pcie_pmu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/perf/hisilicon/hisi_pcie_pmu.c b/drivers/perf/hisilicon/hisi_pcie_pmu.c +index 6ded72383bb6..b4335bdb3c3e 100644 +--- a/drivers/perf/hisilicon/hisi_pcie_pmu.c ++++ b/drivers/perf/hisilicon/hisi_pcie_pmu.c +@@ -686,7 +686,7 @@ static int hisi_pcie_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node) + + pcie_pmu->on_cpu = -1; + /* Choose a new CPU from all online cpus. */ +- target = cpumask_first(cpu_online_mask); ++ target = cpumask_any_but(cpu_online_mask, cpu); + if (target >= nr_cpu_ids) { + pci_err(pcie_pmu->pdev, "There is no CPU to set\n"); + return 0; +-- +2.27.0 + diff --git a/patches/0083-drivers-perf-fixed-the-issue-that-the-kabi-value-cha.patch b/patches/0083-drivers-perf-fixed-the-issue-that-the-kabi-value-cha.patch new file mode 100644 index 0000000..2153f2f --- /dev/null +++ b/patches/0083-drivers-perf-fixed-the-issue-that-the-kabi-value-cha.patch @@ -0,0 +1,210 @@ +From fa73221de60d9d632d6a233f0a1a99b4350e0190 Mon Sep 17 00:00:00 2001 +From: Junhao He +Date: Mon, 21 Nov 2022 22:03:05 +0800 +Subject: [PATCH 42/55] drivers/perf: fixed the issue that the kabi value + changed + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I5KAX7 + +-------------------------------------------------------------------------- + +Fixed the issue that the kabi value changed when the HiSilicon PMU driver +added the enum variable in "enum cpuhp_state{}". + +The hisi_pcie_pmu and hisi_cpa_pmu drivers to replace the explicit specify +hotplug events with dynamic allocation hotplug events(CPUHP_AP_ONLINE_DYN). +The states between *CPUHP_AP_ONLINE_DYN* and *CPUHP_AP_ONLINE_DYN_END* are +reserved for the dynamic allocation. + +Signed-off-by: Junhao He +Reviewed-by: Yicong Yang +Reviewed-by: Yang Jihong +Reviewed-by: Xiongfeng Wang +Signed-off-by: Zheng Zengkai +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_pcie_pmu.c | 22 ++++++++++--------- + drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c | 23 ++++++++++---------- + include/linux/cpuhotplug.h | 6 ----- + 3 files changed, 24 insertions(+), 27 deletions(-) + +diff --git a/drivers/perf/hisilicon/hisi_pcie_pmu.c b/drivers/perf/hisilicon/hisi_pcie_pmu.c +index b4335bdb3c3e..ccbe995db1e4 100644 +--- a/drivers/perf/hisilicon/hisi_pcie_pmu.c ++++ b/drivers/perf/hisilicon/hisi_pcie_pmu.c +@@ -19,6 +19,9 @@ + #include + #include + ++/* Dynamic CPU hotplug state used by PCIe PMU */ ++static enum cpuhp_state hisi_pcie_pmu_online; ++ + #define DRV_NAME "hisi_pcie_pmu" + /* Define registers */ + #define HISI_PCIE_GLOBAL_CTRL 0x00 +@@ -830,7 +833,7 @@ static int hisi_pcie_init_pmu(struct pci_dev *pdev, struct hisi_pcie_pmu *pcie_p + if (ret) + goto err_iounmap; + +- ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE, &pcie_pmu->node); ++ ret = cpuhp_state_add_instance(hisi_pcie_pmu_online, &pcie_pmu->node); + if (ret) { + pci_err(pdev, "Failed to register hotplug: %d\n", ret); + goto err_irq_unregister; +@@ -845,8 +848,7 @@ static int hisi_pcie_init_pmu(struct pci_dev *pdev, struct hisi_pcie_pmu *pcie_p + return ret; + + err_hotplug_unregister: +- cpuhp_state_remove_instance_nocalls( +- CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE, &pcie_pmu->node); ++ cpuhp_state_remove_instance_nocalls(hisi_pcie_pmu_online, &pcie_pmu->node); + + err_irq_unregister: + hisi_pcie_pmu_irq_unregister(pdev, pcie_pmu); +@@ -862,8 +864,7 @@ static void hisi_pcie_uninit_pmu(struct pci_dev *pdev) + struct hisi_pcie_pmu *pcie_pmu = pci_get_drvdata(pdev); + + perf_pmu_unregister(&pcie_pmu->pmu); +- cpuhp_state_remove_instance_nocalls( +- CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE, &pcie_pmu->node); ++ cpuhp_state_remove_instance_nocalls(hisi_pcie_pmu_online, &pcie_pmu->node); + hisi_pcie_pmu_irq_unregister(pdev, pcie_pmu); + iounmap(pcie_pmu->base); + } +@@ -934,18 +935,19 @@ static int __init hisi_pcie_module_init(void) + { + int ret; + +- ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE, +- "AP_PERF_ARM_HISI_PCIE_PMU_ONLINE", ++ ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, ++ "perf/hisi/pcie:online", + hisi_pcie_pmu_online_cpu, + hisi_pcie_pmu_offline_cpu); +- if (ret) { ++ if (ret < 0) { + pr_err("Failed to setup PCIe PMU hotplug: %d\n", ret); + return ret; + } ++ hisi_pcie_pmu_online = ret; + + ret = pci_register_driver(&hisi_pcie_pmu_driver); + if (ret) +- cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE); ++ cpuhp_remove_multi_state(hisi_pcie_pmu_online); + + return ret; + } +@@ -954,7 +956,7 @@ module_init(hisi_pcie_module_init); + static void __exit hisi_pcie_module_exit(void) + { + pci_unregister_driver(&hisi_pcie_pmu_driver); +- cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE); ++ cpuhp_remove_multi_state(hisi_pcie_pmu_online); + } + module_exit(hisi_pcie_module_exit); + +diff --git a/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c +index a9bb73f76be4..09839dae9b7c 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c +@@ -19,6 +19,9 @@ + + #include "hisi_uncore_pmu.h" + ++/* Dynamic CPU hotplug state used by CPA PMU */ ++static enum cpuhp_state hisi_cpa_pmu_online; ++ + /* CPA register definition */ + #define CPA_PERF_CTRL 0x1c00 + #define CPA_EVENT_CTRL 0x1c04 +@@ -334,8 +337,7 @@ static int hisi_cpa_pmu_probe(struct platform_device *pdev) + + /* Power Management should be disabled before using CPA PMU. */ + hisi_cpa_pmu_disable_pm(cpa_pmu); +- ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE, +- &cpa_pmu->node); ++ ret = cpuhp_state_add_instance(hisi_cpa_pmu_online, &cpa_pmu->node); + if (ret) { + dev_err(&pdev->dev, "Error %d registering hotplug\n", ret); + hisi_cpa_pmu_enable_pm(cpa_pmu); +@@ -345,8 +347,7 @@ static int hisi_cpa_pmu_probe(struct platform_device *pdev) + ret = perf_pmu_register(&cpa_pmu->pmu, name, -1); + if (ret) { + dev_err(cpa_pmu->dev, "PMU register failed\n"); +- cpuhp_state_remove_instance_nocalls( +- CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE, &cpa_pmu->node); ++ cpuhp_state_remove_instance_nocalls(hisi_cpa_pmu_online, &cpa_pmu->node); + hisi_cpa_pmu_enable_pm(cpa_pmu); + return ret; + } +@@ -360,8 +361,7 @@ static int hisi_cpa_pmu_remove(struct platform_device *pdev) + struct hisi_pmu *cpa_pmu = platform_get_drvdata(pdev); + + perf_pmu_unregister(&cpa_pmu->pmu); +- cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE, +- &cpa_pmu->node); ++ cpuhp_state_remove_instance_nocalls(hisi_cpa_pmu_online, &cpa_pmu->node); + hisi_cpa_pmu_enable_pm(cpa_pmu); + return 0; + } +@@ -380,18 +380,19 @@ static int __init hisi_cpa_pmu_module_init(void) + { + int ret; + +- ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE, +- "AP_PERF_ARM_HISI_CPA_ONLINE", ++ ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, ++ "pmu/hisi/cpa:online", + hisi_uncore_pmu_online_cpu, + hisi_uncore_pmu_offline_cpu); +- if (ret) { ++ if (ret < 0) { + pr_err("setup hotplug failed: %d\n", ret); + return ret; + } ++ hisi_cpa_pmu_online = ret; + + ret = platform_driver_register(&hisi_cpa_pmu_driver); + if (ret) +- cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE); ++ cpuhp_remove_multi_state(hisi_cpa_pmu_online); + + return ret; + } +@@ -400,7 +401,7 @@ module_init(hisi_cpa_pmu_module_init); + static void __exit hisi_cpa_pmu_module_exit(void) + { + platform_driver_unregister(&hisi_cpa_pmu_driver); +- cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE); ++ cpuhp_remove_multi_state(hisi_cpa_pmu_online); + } + module_exit(hisi_cpa_pmu_module_exit); + +diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h +index ee782c3cb7f3..225b095a96db 100644 +--- a/include/linux/cpuhotplug.h ++++ b/include/linux/cpuhotplug.h +@@ -158,17 +158,11 @@ enum cpuhp_state { + CPUHP_AP_PERF_S390_SF_ONLINE, + CPUHP_AP_PERF_ARM_CCI_ONLINE, + CPUHP_AP_PERF_ARM_CCN_ONLINE, +- #ifndef __GENKSYMS__ +- CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE, +- #endif + CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE, + CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE, + CPUHP_AP_PERF_ARM_HISI_L3_ONLINE, + CPUHP_AP_PERF_ARM_HISI_PA_ONLINE, + CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE, +- #ifndef __GENKSYMS__ +- CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE, +- #endif + CPUHP_AP_PERF_ARM_L2X0_ONLINE, + CPUHP_AP_PERF_ARM_QCOM_L2_ONLINE, + CPUHP_AP_PERF_ARM_QCOM_L3_ONLINE, +-- +2.27.0 + diff --git a/patches/0084-drivers-perf-fixed-kabi-broken-for-SLLC-and-PA-PMU.patch b/patches/0084-drivers-perf-fixed-kabi-broken-for-SLLC-and-PA-PMU.patch new file mode 100644 index 0000000..fbe6ac1 --- /dev/null +++ b/patches/0084-drivers-perf-fixed-kabi-broken-for-SLLC-and-PA-PMU.patch @@ -0,0 +1,200 @@ +From ed7d3223d519f6749ef72cb295e9ce61d55d722b Mon Sep 17 00:00:00 2001 +From: hongrongxuan +Date: Wed, 25 Oct 2023 17:49:20 +0800 +Subject: [PATCH 43/55] drivers/perf: fixed kabi broken for SLLC and PA PMU + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +------------------------------------------------------------------------ + +Fixed the issue that the kabi value changed when the HiSilicon PMU driver +added the enum variable in "enum cpuhp_state{}". + +The hisi_sllc_pmu and hisi_pa_pmu drivers to replace the explicit specify +hotplug events with dynamic allocation hotplug events(CPUHP_AP_ONLINE_DYN). +The states between *CPUHP_AP_ONLINE_DYN* and *CPUHP_AP_ONLINE_DYN_END* are +reserved for the dynamic allocation. + +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_pa_pmu.c | 25 +++++++++++-------- + drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 25 +++++++++++-------- + include/linux/cpuhotplug.h | 2 -- + 3 files changed, 28 insertions(+), 24 deletions(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c +index f1e6b5cee075..8bab65d50316 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c +@@ -46,6 +46,9 @@ HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_cmd, config1, 32, 22); + HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_msk, config1, 43, 33); + HISI_PMU_EVENT_ATTR_EXTRACTOR(tracetag_en, config1, 44, 44); + ++/* Dynamic CPU hotplug state used by PA PMU */ ++static enum cpuhp_state hisi_pa_pmu_online; ++ + static void hisi_pa_pmu_enable_tracetag(struct perf_event *event) + { + struct hisi_pmu *pa_pmu = to_hisi_pmu(event->pmu); +@@ -405,8 +408,7 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev) + if (!name) + return -ENOMEM; + +- ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE, +- &pa_pmu->node); ++ ret = cpuhp_state_add_instance(hisi_pa_pmu_online, &pa_pmu->node); + if (ret) { + dev_err(&pdev->dev, "Error %d registering hotplug\n", ret); + return ret; +@@ -430,8 +432,7 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev) + ret = perf_pmu_register(&pa_pmu->pmu, name, -1); + if (ret) { + dev_err(pa_pmu->dev, "PMU register failed, ret = %d\n", ret); +- cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE, +- &pa_pmu->node); ++ cpuhp_state_remove_instance(hisi_pa_pmu_online, &pa_pmu->node); + return ret; + } + +@@ -444,8 +445,8 @@ static int hisi_pa_pmu_remove(struct platform_device *pdev) + struct hisi_pmu *pa_pmu = platform_get_drvdata(pdev); + + perf_pmu_unregister(&pa_pmu->pmu); +- cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE, +- &pa_pmu->node); ++ cpuhp_state_remove_instance_nocalls(hisi_pa_pmu_online, &pa_pmu->node); ++ + return 0; + } + +@@ -463,18 +464,20 @@ static int __init hisi_pa_pmu_module_init(void) + { + int ret; + +- ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE, +- "AP_PERF_ARM_HISI_PA_ONLINE", ++ ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, ++ "perf/hisi/pa:online", + hisi_uncore_pmu_online_cpu, + hisi_uncore_pmu_offline_cpu); +- if (ret) { ++ if (ret < 0) { + pr_err("PA PMU: cpuhp state setup failed, ret = %d\n", ret); + return ret; + } + ++ hisi_pa_pmu_online = ret; ++ + ret = platform_driver_register(&hisi_pa_pmu_driver); + if (ret) +- cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE); ++ cpuhp_remove_multi_state(hisi_pa_pmu_online); + + return ret; + } +@@ -483,7 +486,7 @@ module_init(hisi_pa_pmu_module_init); + static void __exit hisi_pa_pmu_module_exit(void) + { + platform_driver_unregister(&hisi_pa_pmu_driver); +- cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE); ++ cpuhp_remove_multi_state(hisi_pa_pmu_online); + } + module_exit(hisi_pa_pmu_module_exit); + +diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c +index 835ec3e2178f..71b199ec447a 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c +@@ -48,6 +48,9 @@ HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_cmd, config1, 32, 22); + HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_msk, config1, 43, 33); + HISI_PMU_EVENT_ATTR_EXTRACTOR(tracetag_en, config1, 44, 44); + ++/* Dynamic CPU hotplug state used by SLLC PMU */ ++static enum cpuhp_state hisi_sllc_pmu_online; ++ + static bool tgtid_is_valid(u32 max, u32 min) + { + return max > 0 && max >= min; +@@ -438,8 +441,7 @@ static int hisi_sllc_pmu_probe(struct platform_device *pdev) + if (!name) + return -ENOMEM; + +- ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE, +- &sllc_pmu->node); ++ ret = cpuhp_state_add_instance(hisi_sllc_pmu_online, &sllc_pmu->node); + if (ret) { + dev_err(&pdev->dev, "Error %d registering hotplug\n", ret); + return ret; +@@ -463,8 +465,7 @@ static int hisi_sllc_pmu_probe(struct platform_device *pdev) + ret = perf_pmu_register(&sllc_pmu->pmu, name, -1); + if (ret) { + dev_err(sllc_pmu->dev, "PMU register failed, ret = %d\n", ret); +- cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE, +- &sllc_pmu->node); ++ cpuhp_state_remove_instance(hisi_sllc_pmu_online, &sllc_pmu->node); + return ret; + } + +@@ -478,8 +479,8 @@ static int hisi_sllc_pmu_remove(struct platform_device *pdev) + struct hisi_pmu *sllc_pmu = platform_get_drvdata(pdev); + + perf_pmu_unregister(&sllc_pmu->pmu); +- cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE, +- &sllc_pmu->node); ++ cpuhp_state_remove_instance_nocalls(hisi_sllc_pmu_online, &sllc_pmu->node); ++ + return 0; + } + +@@ -497,18 +498,20 @@ static int __init hisi_sllc_pmu_module_init(void) + { + int ret; + +- ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE, +- "AP_PERF_ARM_HISI_SLLC_ONLINE", ++ ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, ++ "perf/hisi/sllc:online", + hisi_uncore_pmu_online_cpu, + hisi_uncore_pmu_offline_cpu); +- if (ret) { ++ if (ret < 0) { + pr_err("SLLC PMU: cpuhp state setup failed, ret = %d\n", ret); + return ret; + } + ++ hisi_sllc_pmu_online = ret; ++ + ret = platform_driver_register(&hisi_sllc_pmu_driver); + if (ret) +- cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE); ++ cpuhp_remove_multi_state(hisi_sllc_pmu_online); + + return ret; + } +@@ -517,7 +520,7 @@ module_init(hisi_sllc_pmu_module_init); + static void __exit hisi_sllc_pmu_module_exit(void) + { + platform_driver_unregister(&hisi_sllc_pmu_driver); +- cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE); ++ cpuhp_remove_multi_state(hisi_sllc_pmu_online); + } + module_exit(hisi_sllc_pmu_module_exit); + +diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h +index 225b095a96db..d67c0035165c 100644 +--- a/include/linux/cpuhotplug.h ++++ b/include/linux/cpuhotplug.h +@@ -161,8 +161,6 @@ enum cpuhp_state { + CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE, + CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE, + CPUHP_AP_PERF_ARM_HISI_L3_ONLINE, +- CPUHP_AP_PERF_ARM_HISI_PA_ONLINE, +- CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE, + CPUHP_AP_PERF_ARM_L2X0_ONLINE, + CPUHP_AP_PERF_ARM_QCOM_L2_ONLINE, + CPUHP_AP_PERF_ARM_QCOM_L3_ONLINE, +-- +2.27.0 + diff --git a/patches/0085-perf-hisi-Fix-read-sccl_id-and-ccl_id-error-in-TSV20.patch b/patches/0085-perf-hisi-Fix-read-sccl_id-and-ccl_id-error-in-TSV20.patch new file mode 100644 index 0000000..18603a4 --- /dev/null +++ b/patches/0085-perf-hisi-Fix-read-sccl_id-and-ccl_id-error-in-TSV20.patch @@ -0,0 +1,39 @@ +From 2ee9d506673f6abaee074312d2ae189fd941e58c Mon Sep 17 00:00:00 2001 +From: Junhao He +Date: Wed, 4 Jan 2023 19:55:09 +0800 +Subject: [PATCH 44/55] perf: hisi: Fix read sccl_id and ccl_id error in TSV200 + +driver inclusion +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I68F5A +CVE: NA + +-------------------------------- + +In TSV200 platform, SCCL is Aff3[7:0], CCL is Aff2[7:0] if mt. +Fixes: 1af26389a3 ("perf: hisi: Fix read sccl_id and ccl_id error in some platform") + +Signed-off-by: Junhao He +Reviewed-by: Yang Shen +Reviewed-by: Yang Jihong +Signed-off-by: Zheng Zengkai +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_pmu.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c +index 9aaaf9cf2b2a..91d2da895924 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c +@@ -440,7 +440,6 @@ static void hisi_read_sccl_and_ccl_id(int *scclp, int *cclp) + if (mt) { + switch (read_cpuid_part_number()) { + case HISI_CPU_PART_TSV110: +- case HISI_CPU_PART_TSV200: + case ARM_CPU_PART_CORTEX_A55: + sccl = aff2 >> 3; + ccl = aff2 & 0x7; +-- +2.27.0 + diff --git a/patches/0086-perf-hisi-Add-configs-for-PMU-isolation.patch b/patches/0086-perf-hisi-Add-configs-for-PMU-isolation.patch new file mode 100644 index 0000000..47e148c --- /dev/null +++ b/patches/0086-perf-hisi-Add-configs-for-PMU-isolation.patch @@ -0,0 +1,86 @@ +From 2bbf35baac46c41879f770e2273134192a565f86 Mon Sep 17 00:00:00 2001 +From: Zhang Zekun +Date: Sat, 4 Mar 2023 07:24:36 +0000 +Subject: [PATCH 45/55] perf: hisi: Add configs for PMU isolation + +hulk inclusion +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I6HRGK + +------------------------------------------ + +Add CONFIG_HISI_L3T_PMU and CONFIG_HISI_LPDDRC_PMU to isolate features +of hisi pmu driver. + +This patch isolates commit 0edc58409e30 and 6bf896bea639. + +Signed-off-by: Zhang Zekun +Signed-off-by: hongrongxuan + + Conflicts: + drivers/perf/hisilicon/Kconfig + drivers/perf/hisilicon/Makefile +--- + arch/arm64/configs/openeuler_defconfig | 2 ++ + drivers/perf/hisilicon/Kconfig | 18 ++++++++++++++++++ + drivers/perf/hisilicon/Makefile | 6 +++--- + 3 files changed, 23 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig +index 6a7497f2df95..db461e4c2dae 100644 +--- a/arch/arm64/configs/openeuler_defconfig ++++ b/arch/arm64/configs/openeuler_defconfig +@@ -5108,6 +5108,8 @@ CONFIG_QCOM_L3_PMU=y + CONFIG_XGENE_PMU=y + CONFIG_ARM_SPE_PMU=y + CONFIG_HISI_PMU=m ++CONFIG_HISI_L3T_PMU=m ++CONFIG_HISI_LPDDRC_PMU=m + CONFIG_HISI_PCIE_PMU=m + CONFIG_RAS=y + +diff --git a/drivers/perf/hisilicon/Kconfig b/drivers/perf/hisilicon/Kconfig +index 5546218b5598..91a6e2463180 100644 +--- a/drivers/perf/hisilicon/Kconfig ++++ b/drivers/perf/hisilicon/Kconfig +@@ -14,3 +14,21 @@ config HISI_PCIE_PMU + RCiEP devices. + Adds the PCIe PMU into perf events system for monitoring latency, + bandwidth etc. ++ ++config HISI_L3T_PMU ++ tristate "HiSilicon SoC L3T PMU drivers" ++ depends on HISI_PMU ++ default n ++ help ++ Support for HiSilicon SoC L3 Cache performance monitor, Hydra Home ++ Agent performance monitor and DDR Controller performance monitor. ++ L3T is a specialized PMU driver. ++ ++config HISI_LPDDRC_PMU ++ tristate "HiSilicon SoC LDPPRC PMU drivers" ++ depends on HISI_PMU ++ default n ++ help ++ Support for HiSilicon SoC L3 Cache performance monitor, Hydra Home ++ Agent performance monitor and DDR Controller performance monitor. ++ LPDDRC is a specialize PMU driver. +diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile +index a3522abb3975..26d678eb3250 100644 +--- a/drivers/perf/hisilicon/Makefile ++++ b/drivers/perf/hisilicon/Makefile +@@ -1,8 +1,8 @@ + # SPDX-License-Identifier: GPL-2.0-only + obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o \ + hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_sllc_pmu.o \ +- hisi_uncore_pa_pmu.o hisi_uncore_cpa_pmu.o \ +- hisi_uncore_l3t_pmu.o \ +- hisi_uncore_lpddrc_pmu.o ++ hisi_uncore_pa_pmu.o hisi_uncore_cpa_pmu.o + + obj-$(CONFIG_HISI_PCIE_PMU) += hisi_pcie_pmu.o ++obj-$(CONFIG_HISI_L3T_PMU) += hisi_uncore_l3t_pmu.o ++obj-$(CONFIG_HISI_LPDDRC_PMU) += hisi_uncore_lpddrc_pmu.o +-- +2.27.0 + diff --git a/patches/0087-perf-hisi-Extract-hisi_pmu_init.patch b/patches/0087-perf-hisi-Extract-hisi_pmu_init.patch new file mode 100644 index 0000000..88c44dc --- /dev/null +++ b/patches/0087-perf-hisi-Extract-hisi_pmu_init.patch @@ -0,0 +1,208 @@ +From 021c239865727a9e633d04f3fc490426b51012ad Mon Sep 17 00:00:00 2001 +From: Chen Jun +Date: Tue, 23 May 2023 14:44:24 +0800 +Subject: [PATCH 46/55] perf: hisi: Extract hisi_pmu_init + +mainline inclusion +from mainline-v6.0-rc1 +commit e500405dd15d956790859fa532c64d8186445372 +category: cleanup +bugzilla: https://gitee.com/openeuler/kernel/issues/I77IH6 +CVE: NA + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e500405dd15d956790859fa532c64d8186445372 + +---------------------------------------------------------------------- + +Extract the initialization code of hisi_pmu->pmu into a function + +Signed-off-by: Chen Jun +Link: https://lore.kernel.org/r/20220516131601.48383-1-chenjun102@huawei.com +Signed-off-by: Will Deacon +Signed-off-by: Junhao He +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 16 +--------------- + drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 16 +--------------- + drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 16 +--------------- + drivers/perf/hisilicon/hisi_uncore_pa_pmu.c | 16 +--------------- + drivers/perf/hisilicon/hisi_uncore_pmu.c | 18 ++++++++++++++++++ + drivers/perf/hisilicon/hisi_uncore_pmu.h | 2 ++ + drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 15 +-------------- + 7 files changed, 25 insertions(+), 74 deletions(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +index 457ac6a1ad64..69d2b08847e2 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +@@ -519,21 +519,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev) + "hisi_sccl%u_ddrc%u", ddrc_pmu->sccl_id, + ddrc_pmu->index_id); + +- ddrc_pmu->pmu = (struct pmu) { +- .name = name, +- .module = THIS_MODULE, +- .task_ctx_nr = perf_invalid_context, +- .event_init = hisi_uncore_pmu_event_init, +- .pmu_enable = hisi_uncore_pmu_enable, +- .pmu_disable = hisi_uncore_pmu_disable, +- .add = hisi_uncore_pmu_add, +- .del = hisi_uncore_pmu_del, +- .start = hisi_uncore_pmu_start, +- .stop = hisi_uncore_pmu_stop, +- .read = hisi_uncore_pmu_read, +- .attr_groups = ddrc_pmu->pmu_events.attr_groups, +- .capabilities = PERF_PMU_CAP_NO_EXCLUDE, +- }; ++ hisi_pmu_init(&ddrc_pmu->pmu, name, ddrc_pmu->pmu_events.attr_groups, THIS_MODULE); + + ret = perf_pmu_register(&ddrc_pmu->pmu, name, -1); + if (ret) { +diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +index 3b120fc55e01..c5f752f4ff22 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +@@ -522,21 +522,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev) + + name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_hha%u", + hha_pmu->sccl_id, hha_pmu->index_id); +- hha_pmu->pmu = (struct pmu) { +- .name = name, +- .module = THIS_MODULE, +- .task_ctx_nr = perf_invalid_context, +- .event_init = hisi_uncore_pmu_event_init, +- .pmu_enable = hisi_uncore_pmu_enable, +- .pmu_disable = hisi_uncore_pmu_disable, +- .add = hisi_uncore_pmu_add, +- .del = hisi_uncore_pmu_del, +- .start = hisi_uncore_pmu_start, +- .stop = hisi_uncore_pmu_stop, +- .read = hisi_uncore_pmu_read, +- .attr_groups = hha_pmu->pmu_events.attr_groups, +- .capabilities = PERF_PMU_CAP_NO_EXCLUDE, +- }; ++ hisi_pmu_init(&hha_pmu->pmu, name, hha_pmu->pmu_events.attr_groups, THIS_MODULE); + + ret = perf_pmu_register(&hha_pmu->pmu, name, -1); + if (ret) { +diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +index d70a01587d72..d723e008a0f9 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +@@ -560,21 +560,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev) + */ + name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_l3c%u", + l3c_pmu->sccl_id, l3c_pmu->ccl_id); +- l3c_pmu->pmu = (struct pmu) { +- .name = name, +- .module = THIS_MODULE, +- .task_ctx_nr = perf_invalid_context, +- .event_init = hisi_uncore_pmu_event_init, +- .pmu_enable = hisi_uncore_pmu_enable, +- .pmu_disable = hisi_uncore_pmu_disable, +- .add = hisi_uncore_pmu_add, +- .del = hisi_uncore_pmu_del, +- .start = hisi_uncore_pmu_start, +- .stop = hisi_uncore_pmu_stop, +- .read = hisi_uncore_pmu_read, +- .attr_groups = l3c_pmu->pmu_events.attr_groups, +- .capabilities = PERF_PMU_CAP_NO_EXCLUDE, +- }; ++ hisi_pmu_init(&l3c_pmu->pmu, name, l3c_pmu->pmu_events.attr_groups, THIS_MODULE); + + ret = perf_pmu_register(&l3c_pmu->pmu, name, -1); + if (ret) { +diff --git a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c +index 8bab65d50316..99786ef708a6 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c +@@ -414,21 +414,7 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev) + return ret; + } + +- pa_pmu->pmu = (struct pmu) { +- .module = THIS_MODULE, +- .task_ctx_nr = perf_invalid_context, +- .event_init = hisi_uncore_pmu_event_init, +- .pmu_enable = hisi_uncore_pmu_enable, +- .pmu_disable = hisi_uncore_pmu_disable, +- .add = hisi_uncore_pmu_add, +- .del = hisi_uncore_pmu_del, +- .start = hisi_uncore_pmu_start, +- .stop = hisi_uncore_pmu_stop, +- .read = hisi_uncore_pmu_read, +- .attr_groups = pa_pmu->pmu_events.attr_groups, +- .capabilities = PERF_PMU_CAP_NO_EXCLUDE, +- }; +- ++ hisi_pmu_init(&pa_pmu->pmu, name, pa_pmu->pmu_events.attr_groups, THIS_MODULE); + ret = perf_pmu_register(&pa_pmu->pmu, name, -1); + if (ret) { + dev_err(pa_pmu->dev, "PMU register failed, ret = %d\n", ret); +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c +index 91d2da895924..41640de74072 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c +@@ -540,4 +540,22 @@ int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node) + } + EXPORT_SYMBOL_GPL(hisi_uncore_pmu_offline_cpu); + ++void hisi_pmu_init(struct pmu *pmu, const char *name, ++ const struct attribute_group **attr_groups, struct module *module) ++{ ++ pmu->name = name; ++ pmu->module = module; ++ pmu->task_ctx_nr = perf_invalid_context; ++ pmu->event_init = hisi_uncore_pmu_event_init; ++ pmu->pmu_enable = hisi_uncore_pmu_enable; ++ pmu->pmu_disable = hisi_uncore_pmu_disable; ++ pmu->add = hisi_uncore_pmu_add; ++ pmu->del = hisi_uncore_pmu_del; ++ pmu->start = hisi_uncore_pmu_start; ++ pmu->stop = hisi_uncore_pmu_stop; ++ pmu->read = hisi_uncore_pmu_read; ++ pmu->attr_groups = attr_groups; ++} ++EXPORT_SYMBOL_GPL(hisi_pmu_init); ++ + MODULE_LICENSE("GPL v2"); +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h +index 6a78c13176c2..9818e20d36f8 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h +@@ -135,4 +135,6 @@ ssize_t hisi_uncore_pmu_identifier_attr_show(struct device *dev, + int hisi_uncore_pmu_init_irq(struct hisi_pmu *hisi_pmu, + struct platform_device *pdev); + ++void hisi_pmu_init(struct pmu *pmu, const char *name, ++ const struct attribute_group **attr_groups, struct module *module); + #endif /* __HISI_UNCORE_PMU_H__ */ +diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c +index 71b199ec447a..b71de6597016 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c +@@ -447,20 +447,7 @@ static int hisi_sllc_pmu_probe(struct platform_device *pdev) + return ret; + } + +- sllc_pmu->pmu = (struct pmu) { +- .module = THIS_MODULE, +- .task_ctx_nr = perf_invalid_context, +- .event_init = hisi_uncore_pmu_event_init, +- .pmu_enable = hisi_uncore_pmu_enable, +- .pmu_disable = hisi_uncore_pmu_disable, +- .add = hisi_uncore_pmu_add, +- .del = hisi_uncore_pmu_del, +- .start = hisi_uncore_pmu_start, +- .stop = hisi_uncore_pmu_stop, +- .read = hisi_uncore_pmu_read, +- .attr_groups = sllc_pmu->pmu_events.attr_groups, +- .capabilities = PERF_PMU_CAP_NO_EXCLUDE, +- }; ++ hisi_pmu_init(&sllc_pmu->pmu, name, sllc_pmu->pmu_events.attr_groups, THIS_MODULE); + + ret = perf_pmu_register(&sllc_pmu->pmu, name, -1); + if (ret) { +-- +2.27.0 + diff --git a/patches/0088-drivers-perf-hisi-Advertise-the-PERF_PMU_CAP_NO_EXCL.patch b/patches/0088-drivers-perf-hisi-Advertise-the-PERF_PMU_CAP_NO_EXCL.patch new file mode 100644 index 0000000..9376fad --- /dev/null +++ b/patches/0088-drivers-perf-hisi-Advertise-the-PERF_PMU_CAP_NO_EXCL.patch @@ -0,0 +1,48 @@ +From 31854a763b417d8f751691e9e4fc81b3523c569d Mon Sep 17 00:00:00 2001 +From: Junhao He +Date: Tue, 23 May 2023 14:44:25 +0800 +Subject: [PATCH 47/55] drivers/perf: hisi: Advertise the + PERF_PMU_CAP_NO_EXCLUDE capability + +mainline inclusion +from mainline-v6.3-rc1 +commit 7f95da9d2dc4c20bb374c281ceb8fa40b6208f4b +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I77IH6 +CVE: NA + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7f95da9d2dc4c20bb374c281ceb8fa40b6208f4b + +---------------------------------------------------------------------- + +Missed initialization the variable of pmu::capabilities when extract +the initialization code of hisi_pmu->pmu into a function. + +HISI UNCORE PMU drivers counters that not support context exclusion. +So we have to advertise the PERF_PMU_CAP_NO_EXCLUDE capability. +This ensures that perf will prevent us from handling events where +any exclusion flags are set. + +Signed-off-by: Junhao He +Link: https://lore.kernel.org/r/20230119100307.3660-2-hejunhao3@huawei.com +Signed-off-by: Will Deacon +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_pmu.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c +index 41640de74072..c5860912d765 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c +@@ -555,6 +555,7 @@ void hisi_pmu_init(struct pmu *pmu, const char *name, + pmu->stop = hisi_uncore_pmu_stop; + pmu->read = hisi_uncore_pmu_read; + pmu->attr_groups = attr_groups; ++ pmu->capabilities = PERF_PMU_CAP_NO_EXCLUDE; + } + EXPORT_SYMBOL_GPL(hisi_pmu_init); + +-- +2.27.0 + diff --git a/patches/0089-drivers-perf-hisi-Simplify-the-parameters-of-hisi_pm.patch b/patches/0089-drivers-perf-hisi-Simplify-the-parameters-of-hisi_pm.patch new file mode 100644 index 0000000..29c4f2c --- /dev/null +++ b/patches/0089-drivers-perf-hisi-Simplify-the-parameters-of-hisi_pm.patch @@ -0,0 +1,142 @@ +From 8c346b56153744591b51dadcde8b603b8b872e2d Mon Sep 17 00:00:00 2001 +From: Junhao He +Date: Tue, 23 May 2023 14:44:26 +0800 +Subject: [PATCH 48/55] drivers/perf: hisi: Simplify the parameters of + hisi_pmu_init() + +mainline inclusion +from mainline-v6.3-rc1 +commit 053b5579dacfc5763dda0c073ee14147421d32d7 +category: cleanup +bugzilla: https://gitee.com/openeuler/kernel/issues/I77IH6 +CVE: NA + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=053b5579dacfc5763dda0c073ee14147421d32d7 + +---------------------------------------------------------------------- + +Use "hisi_pmu" to simplify the parameter list for the hisi_pmu_init() +function. + +Signed-off-by: Junhao He +Link: https://lore.kernel.org/r/20230119100307.3660-3-hejunhao3@huawei.com +Signed-off-by: Will Deacon +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 2 +- + drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 2 +- + drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 2 +- + drivers/perf/hisilicon/hisi_uncore_pa_pmu.c | 2 +- + drivers/perf/hisilicon/hisi_uncore_pmu.c | 8 +++++--- + drivers/perf/hisilicon/hisi_uncore_pmu.h | 4 ++-- + drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 2 +- + 7 files changed, 12 insertions(+), 10 deletions(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +index 69d2b08847e2..3a1b3919c736 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +@@ -519,7 +519,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev) + "hisi_sccl%u_ddrc%u", ddrc_pmu->sccl_id, + ddrc_pmu->index_id); + +- hisi_pmu_init(&ddrc_pmu->pmu, name, ddrc_pmu->pmu_events.attr_groups, THIS_MODULE); ++ hisi_pmu_init(ddrc_pmu, name, THIS_MODULE); + + ret = perf_pmu_register(&ddrc_pmu->pmu, name, -1); + if (ret) { +diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +index c5f752f4ff22..9aa951bdf417 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +@@ -522,7 +522,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev) + + name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_hha%u", + hha_pmu->sccl_id, hha_pmu->index_id); +- hisi_pmu_init(&hha_pmu->pmu, name, hha_pmu->pmu_events.attr_groups, THIS_MODULE); ++ hisi_pmu_init(hha_pmu, name, THIS_MODULE); + + ret = perf_pmu_register(&hha_pmu->pmu, name, -1); + if (ret) { +diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +index d723e008a0f9..0406c034e7c4 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +@@ -560,7 +560,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev) + */ + name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_l3c%u", + l3c_pmu->sccl_id, l3c_pmu->ccl_id); +- hisi_pmu_init(&l3c_pmu->pmu, name, l3c_pmu->pmu_events.attr_groups, THIS_MODULE); ++ hisi_pmu_init(l3c_pmu, name, THIS_MODULE); + + ret = perf_pmu_register(&l3c_pmu->pmu, name, -1); + if (ret) { +diff --git a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c +index 99786ef708a6..df8605a0b24d 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c +@@ -414,7 +414,7 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev) + return ret; + } + +- hisi_pmu_init(&pa_pmu->pmu, name, pa_pmu->pmu_events.attr_groups, THIS_MODULE); ++ hisi_pmu_init(pa_pmu, name, THIS_MODULE); + ret = perf_pmu_register(&pa_pmu->pmu, name, -1); + if (ret) { + dev_err(pa_pmu->dev, "PMU register failed, ret = %d\n", ret); +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c +index c5860912d765..13e54e458f9a 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c +@@ -540,9 +540,11 @@ int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node) + } + EXPORT_SYMBOL_GPL(hisi_uncore_pmu_offline_cpu); + +-void hisi_pmu_init(struct pmu *pmu, const char *name, +- const struct attribute_group **attr_groups, struct module *module) ++void hisi_pmu_init(struct hisi_pmu *hisi_pmu, const char *name, ++ struct module *module) + { ++ struct pmu *pmu = &hisi_pmu->pmu; ++ + pmu->name = name; + pmu->module = module; + pmu->task_ctx_nr = perf_invalid_context; +@@ -554,7 +556,7 @@ void hisi_pmu_init(struct pmu *pmu, const char *name, + pmu->start = hisi_uncore_pmu_start; + pmu->stop = hisi_uncore_pmu_stop; + pmu->read = hisi_uncore_pmu_read; +- pmu->attr_groups = attr_groups; ++ pmu->attr_groups = hisi_pmu->pmu_events.attr_groups; + pmu->capabilities = PERF_PMU_CAP_NO_EXCLUDE; + } + EXPORT_SYMBOL_GPL(hisi_pmu_init); +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h +index 9818e20d36f8..27951213c9e8 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h +@@ -135,6 +135,6 @@ ssize_t hisi_uncore_pmu_identifier_attr_show(struct device *dev, + int hisi_uncore_pmu_init_irq(struct hisi_pmu *hisi_pmu, + struct platform_device *pdev); + +-void hisi_pmu_init(struct pmu *pmu, const char *name, +- const struct attribute_group **attr_groups, struct module *module); ++void hisi_pmu_init(struct hisi_pmu *hisi_pmu, const char *name, ++ struct module *module); + #endif /* __HISI_UNCORE_PMU_H__ */ +diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c +index b71de6597016..c1b038fc534e 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c +@@ -447,7 +447,7 @@ static int hisi_sllc_pmu_probe(struct platform_device *pdev) + return ret; + } + +- hisi_pmu_init(&sllc_pmu->pmu, name, sllc_pmu->pmu_events.attr_groups, THIS_MODULE); ++ hisi_pmu_init(sllc_pmu, name, THIS_MODULE); + + ret = perf_pmu_register(&sllc_pmu->pmu, name, -1); + if (ret) { +-- +2.27.0 + diff --git a/patches/0090-drivers-perf-hisi-Extract-initialization-of-cpa_pmu-.patch b/patches/0090-drivers-perf-hisi-Extract-initialization-of-cpa_pmu-.patch new file mode 100644 index 0000000..21b83ce --- /dev/null +++ b/patches/0090-drivers-perf-hisi-Extract-initialization-of-cpa_pmu-.patch @@ -0,0 +1,57 @@ +From 6a6aa532c3e4951259c5c024aa560afe4798e22a Mon Sep 17 00:00:00 2001 +From: Junhao He +Date: Tue, 23 May 2023 14:44:27 +0800 +Subject: [PATCH 49/55] drivers/perf: hisi: Extract initialization of + "cpa_pmu->pmu" + +mainline inclusion +from mainline-v6.3-rc1 +commit e126f6f42f89baee09e088ab6bc48f83ac3a0eae +category: cleanup +bugzilla: https://gitee.com/openeuler/kernel/issues/I77IH6 +CVE: NA + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e126f6f42f89baee09e088ab6bc48f83ac3a0eae + +---------------------------------------------------------------------- + +Use hisi_pmu_init() function to simplify initialization of "cpa_pmu->pmu". + +Signed-off-by: Junhao He +Link: https://lore.kernel.org/r/20230119100307.3660-4-hejunhao3@huawei.com +Signed-off-by: Will Deacon +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c | 16 +--------------- + 1 file changed, 1 insertion(+), 15 deletions(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c +index 09839dae9b7c..1a75351013f1 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c +@@ -319,21 +319,7 @@ static int hisi_cpa_pmu_probe(struct platform_device *pdev) + if (!name) + return -ENOMEM; + +- cpa_pmu->pmu = (struct pmu) { +- .name = name, +- .module = THIS_MODULE, +- .task_ctx_nr = perf_invalid_context, +- .event_init = hisi_uncore_pmu_event_init, +- .pmu_enable = hisi_uncore_pmu_enable, +- .pmu_disable = hisi_uncore_pmu_disable, +- .add = hisi_uncore_pmu_add, +- .del = hisi_uncore_pmu_del, +- .start = hisi_uncore_pmu_start, +- .stop = hisi_uncore_pmu_stop, +- .read = hisi_uncore_pmu_read, +- .attr_groups = cpa_pmu->pmu_events.attr_groups, +- .capabilities = PERF_PMU_CAP_NO_EXCLUDE, +- }; ++ hisi_pmu_init(cpa_pmu, name, THIS_MODULE); + + /* Power Management should be disabled before using CPA PMU. */ + hisi_cpa_pmu_disable_pm(cpa_pmu); +-- +2.27.0 + diff --git a/patches/0091-drivers-perf-hisi-Remove-redundant-initialized-of-pm.patch b/patches/0091-drivers-perf-hisi-Remove-redundant-initialized-of-pm.patch new file mode 100644 index 0000000..64cb597 --- /dev/null +++ b/patches/0091-drivers-perf-hisi-Remove-redundant-initialized-of-pm.patch @@ -0,0 +1,144 @@ +From 2ccc10a1b9770a9205a8ababd910a08dd8512b96 Mon Sep 17 00:00:00 2001 +From: Junhao He +Date: Tue, 23 May 2023 14:44:28 +0800 +Subject: [PATCH 50/55] drivers/perf: hisi: Remove redundant initialized of + pmu->name + +mainline inclusion +from mainline-v6.4-rc1 +commit 25d8c25025a46e7621edde2eb6d5f55c6d29ee86 +category: cleanup +bugzilla: https://gitee.com/openeuler/kernel/issues/I77IH6 +CVE: NA + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=25d8c25025a46e7621edde2eb6d5f55c6d29ee86 + +---------------------------------------------------------------------- + +"pmu->name" is initialized by perf_pmu_register() function, so remove +the redundant initialized in hisi_pmu_init(). + +Signed-off-by: Junhao He +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c | 2 +- + drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 2 +- + drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 2 +- + drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 2 +- + drivers/perf/hisilicon/hisi_uncore_pa_pmu.c | 2 +- + drivers/perf/hisilicon/hisi_uncore_pmu.c | 4 +--- + drivers/perf/hisilicon/hisi_uncore_pmu.h | 3 +-- + drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 2 +- + 8 files changed, 8 insertions(+), 11 deletions(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c +index 1a75351013f1..9322fc3dac07 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c +@@ -319,7 +319,7 @@ static int hisi_cpa_pmu_probe(struct platform_device *pdev) + if (!name) + return -ENOMEM; + +- hisi_pmu_init(cpa_pmu, name, THIS_MODULE); ++ hisi_pmu_init(cpa_pmu, THIS_MODULE); + + /* Power Management should be disabled before using CPA PMU. */ + hisi_cpa_pmu_disable_pm(cpa_pmu); +diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +index 3a1b3919c736..eddeb76ce4c5 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +@@ -519,7 +519,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev) + "hisi_sccl%u_ddrc%u", ddrc_pmu->sccl_id, + ddrc_pmu->index_id); + +- hisi_pmu_init(ddrc_pmu, name, THIS_MODULE); ++ hisi_pmu_init(ddrc_pmu, THIS_MODULE); + + ret = perf_pmu_register(&ddrc_pmu->pmu, name, -1); + if (ret) { +diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +index 9aa951bdf417..1b8f44dada6d 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +@@ -522,7 +522,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev) + + name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_hha%u", + hha_pmu->sccl_id, hha_pmu->index_id); +- hisi_pmu_init(hha_pmu, name, THIS_MODULE); ++ hisi_pmu_init(hha_pmu, THIS_MODULE); + + ret = perf_pmu_register(&hha_pmu->pmu, name, -1); + if (ret) { +diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +index 0406c034e7c4..b2ac90e9f2cd 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +@@ -560,7 +560,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev) + */ + name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_l3c%u", + l3c_pmu->sccl_id, l3c_pmu->ccl_id); +- hisi_pmu_init(l3c_pmu, name, THIS_MODULE); ++ hisi_pmu_init(l3c_pmu, THIS_MODULE); + + ret = perf_pmu_register(&l3c_pmu->pmu, name, -1); + if (ret) { +diff --git a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c +index df8605a0b24d..cf10c84ada41 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c +@@ -414,7 +414,7 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev) + return ret; + } + +- hisi_pmu_init(pa_pmu, name, THIS_MODULE); ++ hisi_pmu_init(pa_pmu, THIS_MODULE); + ret = perf_pmu_register(&pa_pmu->pmu, name, -1); + if (ret) { + dev_err(pa_pmu->dev, "PMU register failed, ret = %d\n", ret); +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c +index 13e54e458f9a..aed38a8c582c 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c +@@ -540,12 +540,10 @@ int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node) + } + EXPORT_SYMBOL_GPL(hisi_uncore_pmu_offline_cpu); + +-void hisi_pmu_init(struct hisi_pmu *hisi_pmu, const char *name, +- struct module *module) ++void hisi_pmu_init(struct hisi_pmu *hisi_pmu, struct module *module) + { + struct pmu *pmu = &hisi_pmu->pmu; + +- pmu->name = name; + pmu->module = module; + pmu->task_ctx_nr = perf_invalid_context; + pmu->event_init = hisi_uncore_pmu_event_init; +diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h +index 27951213c9e8..93b672d9731e 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h ++++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h +@@ -135,6 +135,5 @@ ssize_t hisi_uncore_pmu_identifier_attr_show(struct device *dev, + int hisi_uncore_pmu_init_irq(struct hisi_pmu *hisi_pmu, + struct platform_device *pdev); + +-void hisi_pmu_init(struct hisi_pmu *hisi_pmu, const char *name, +- struct module *module); ++void hisi_pmu_init(struct hisi_pmu *hisi_pmu, struct module *module); + #endif /* __HISI_UNCORE_PMU_H__ */ +diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c +index c1b038fc534e..149a0d8f403f 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c +@@ -447,7 +447,7 @@ static int hisi_sllc_pmu_probe(struct platform_device *pdev) + return ret; + } + +- hisi_pmu_init(sllc_pmu, name, THIS_MODULE); ++ hisi_pmu_init(sllc_pmu, THIS_MODULE); + + ret = perf_pmu_register(&sllc_pmu->pmu, name, -1); + if (ret) { +-- +2.27.0 + diff --git a/patches/0092-drivers-perf-hisi-add-NULL-check-for-name.patch b/patches/0092-drivers-perf-hisi-add-NULL-check-for-name.patch new file mode 100644 index 0000000..18faee2 --- /dev/null +++ b/patches/0092-drivers-perf-hisi-add-NULL-check-for-name.patch @@ -0,0 +1,127 @@ +From 158cb44475a0c6d29c08716ccb3a868262388e55 Mon Sep 17 00:00:00 2001 +From: Junhao He +Date: Tue, 23 May 2023 14:44:29 +0800 +Subject: [PATCH 51/55] drivers/perf: hisi: add NULL check for name + +mainline inclusion +from mainline-v6.4-rc1 +commit 257aedb72e731082ab514058e57b132f0b29d707 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I77IH6 +CVE: NA + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=257aedb72e731082ab514058e57b132f0b29d707 + +---------------------------------------------------------------------- + +When allocations fails that can be NULL now. + +If the name provided is NULL, then the initialization process of the PMU +type and dev will be skipped in function perf_pmu_register(). +Consequently, the PMU will not be able to register into the kernel. +Moreover, in the case of unregister the PMU, the function device_del() +will need to handle NULL pointers, which potentially can cause issues. + +So move this allocation above the cpuhp_state_add_instance() and directly +return if it does fail. + +Signed-off-by: Junhao He +Signed-off-by: hongrongxuan +--- + drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 17 ++++++++++------- + drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 7 +++++-- + drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 11 +++++------ + 3 files changed, 20 insertions(+), 15 deletions(-) + +diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +index eddeb76ce4c5..184f2f986c98 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +@@ -502,13 +502,6 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev) + if (ret) + return ret; + +- ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE, +- &ddrc_pmu->node); +- if (ret) { +- dev_err(&pdev->dev, "Error %d registering hotplug;\n", ret); +- return ret; +- } +- + if (ddrc_pmu->identifier >= HISI_PMU_V2) + name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "hisi_sccl%u_ddrc%u_%u", +@@ -519,6 +512,16 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev) + "hisi_sccl%u_ddrc%u", ddrc_pmu->sccl_id, + ddrc_pmu->index_id); + ++ if (!name) ++ return -ENOMEM; ++ ++ ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE, ++ &ddrc_pmu->node); ++ if (ret) { ++ dev_err(&pdev->dev, "Error %d registering hotplug;\n", ret); ++ return ret; ++ } ++ + hisi_pmu_init(ddrc_pmu, THIS_MODULE); + + ret = perf_pmu_register(&ddrc_pmu->pmu, name, -1); +diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +index 1b8f44dada6d..16038ebf08b6 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +@@ -513,6 +513,11 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev) + if (ret) + return ret; + ++ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_hha%u", ++ hha_pmu->sccl_id, hha_pmu->index_id); ++ if (!name) ++ return -ENOMEM; ++ + ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE, + &hha_pmu->node); + if (ret) { +@@ -520,8 +525,6 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev) + return ret; + } + +- name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_hha%u", +- hha_pmu->sccl_id, hha_pmu->index_id); + hisi_pmu_init(hha_pmu, THIS_MODULE); + + ret = perf_pmu_register(&hha_pmu->pmu, name, -1); +diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +index b2ac90e9f2cd..f9640dbd4095 100644 +--- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c ++++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c +@@ -547,6 +547,11 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev) + if (ret) + return ret; + ++ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_l3c%u", ++ l3c_pmu->sccl_id, l3c_pmu->ccl_id); ++ if (!name) ++ return -ENOMEM; ++ + ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE, + &l3c_pmu->node); + if (ret) { +@@ -554,12 +559,6 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev) + return ret; + } + +- /* +- * CCL_ID is used to identify the L3C in the same SCCL which was +- * used _UID by mistake. +- */ +- name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_l3c%u", +- l3c_pmu->sccl_id, l3c_pmu->ccl_id); + hisi_pmu_init(l3c_pmu, THIS_MODULE); + + ret = perf_pmu_register(&l3c_pmu->pmu, name, -1); +-- +2.27.0 + diff --git a/patches/0093-Revert-perf-smmuv3_pmu-Enable-HiSilicon-Erratum-1620.patch b/patches/0093-Revert-perf-smmuv3_pmu-Enable-HiSilicon-Erratum-1620.patch new file mode 100644 index 0000000..4d63100 --- /dev/null +++ b/patches/0093-Revert-perf-smmuv3_pmu-Enable-HiSilicon-Erratum-1620.patch @@ -0,0 +1,162 @@ +From 418fb2ed339c7856662bb6244ac5477cba81f80f Mon Sep 17 00:00:00 2001 +From: hongrongxuan +Date: Fri, 27 Oct 2023 18:49:23 +0800 +Subject: [PATCH 52/55] Revert "perf/smmuv3_pmu: Enable HiSilicon Erratum + 162001800 quirk" + +driver inclusion +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +----------------------------------------------------------- + +This reverts commit 68088650bec0647cef4d822b31f818a094f5eead. +We inclusion it again from upstream later. + +Signed-off-by: hongrongxuan +--- + drivers/acpi/arm64/iort.c | 16 +----------- + drivers/perf/arm_smmuv3_pmu.c | 48 +++++------------------------------ + include/linux/acpi_iort.h | 1 - + 3 files changed, 8 insertions(+), 57 deletions(-) + +diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c +index 9ad4ee8884de..d507556d508f 100644 +--- a/drivers/acpi/arm64/iort.c ++++ b/drivers/acpi/arm64/iort.c +@@ -1476,23 +1476,9 @@ static void __init arm_smmu_v3_pmcg_init_resources(struct resource *res, + ACPI_EDGE_SENSITIVE, &res[2]); + } + +-static struct acpi_platform_list pmcg_plat_info[] __initdata = { +- /* HiSilicon Hip08 Platform */ +- {"HISI ", "HIP08 ", 0, ACPI_SIG_IORT, greater_than_or_equal, 0, +- IORT_SMMU_V3_PMCG_HISI_HIP08}, +- { } +-}; +- + static int __init arm_smmu_v3_pmcg_add_platdata(struct platform_device *pdev) + { +- u32 model; +- int idx; +- +- idx = acpi_match_platform_list(pmcg_plat_info); +- if (idx >= 0) +- model = pmcg_plat_info[idx].data; +- else +- model = IORT_SMMU_V3_PMCG_GENERIC; ++ u32 model = IORT_SMMU_V3_PMCG_GENERIC; + + return platform_device_add_data(pdev, &model, sizeof(model)); + } +diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c +index bda901e2a5fc..e9cd120f4268 100644 +--- a/drivers/perf/arm_smmuv3_pmu.c ++++ b/drivers/perf/arm_smmuv3_pmu.c +@@ -35,7 +35,6 @@ + */ + + #include +-#include + #include + #include + #include +@@ -94,8 +93,6 @@ + + #define SMMU_PMCG_PA_SHIFT 12 + +-#define SMMU_PMCG_EVCNTR_RDONLY BIT(0) +- + static int cpuhp_state_num; + + struct smmu_pmu { +@@ -110,7 +107,6 @@ struct smmu_pmu { + struct device *dev; + void __iomem *reg_base; + void __iomem *reloc_base; +- u32 options; + u64 counter_mask; + bool global_filter; + }; +@@ -224,27 +220,15 @@ static void smmu_pmu_set_period(struct smmu_pmu *smmu_pmu, + u32 idx = hwc->idx; + u64 new; + +- if (smmu_pmu->options & SMMU_PMCG_EVCNTR_RDONLY) { +- /* +- * On platforms that require this quirk, if the counter starts +- * at < half_counter value and wraps, the current logic of +- * handling the overflow may not work. It is expected that, +- * those platforms will have full 64 counter bits implemented +- * so that such a possibility is remote(eg: HiSilicon HIP08). +- */ +- new = smmu_pmu_counter_get_value(smmu_pmu, idx); +- } else { +- /* +- * We limit the max period to half the max counter value +- * of the counter size, so that even in the case of extreme +- * interrupt latency the counter will (hopefully) not wrap +- * past its initial value. +- */ +- new = smmu_pmu->counter_mask >> 1; +- smmu_pmu_counter_set_value(smmu_pmu, idx, new); +- } ++ /* ++ * We limit the max period to half the max counter value of the counter ++ * size, so that even in the case of extreme interrupt latency the ++ * counter will (hopefully) not wrap past its initial value. ++ */ ++ new = smmu_pmu->counter_mask >> 1; + + local64_set(&hwc->prev_count, new); ++ smmu_pmu_counter_set_value(smmu_pmu, idx, new); + } + + static void smmu_pmu_set_event_filter(struct perf_event *event, +@@ -718,22 +702,6 @@ static void smmu_pmu_reset(struct smmu_pmu *smmu_pmu) + smmu_pmu->reloc_base + SMMU_PMCG_OVSCLR0); + } + +-static void smmu_pmu_get_acpi_options(struct smmu_pmu *smmu_pmu) +-{ +- u32 model; +- +- model = *(u32 *)dev_get_platdata(smmu_pmu->dev); +- +- switch (model) { +- case IORT_SMMU_V3_PMCG_HISI_HIP08: +- /* HiSilicon Erratum 162001800 */ +- smmu_pmu->options |= SMMU_PMCG_EVCNTR_RDONLY; +- break; +- } +- +- dev_notice(smmu_pmu->dev, "option mask 0x%x\n", smmu_pmu->options); +-} +- + static int smmu_pmu_probe(struct platform_device *pdev) + { + struct smmu_pmu *smmu_pmu; +@@ -813,8 +781,6 @@ static int smmu_pmu_probe(struct platform_device *pdev) + return -EINVAL; + } + +- smmu_pmu_get_acpi_options(smmu_pmu); +- + /* Pick one CPU to be the preferred one to use */ + smmu_pmu->on_cpu = raw_smp_processor_id(); + WARN_ON(irq_set_affinity(smmu_pmu->irq, cpumask_of(smmu_pmu->on_cpu))); +diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h +index bdb69125854e..832bd6ae9ad4 100644 +--- a/include/linux/acpi_iort.h ++++ b/include/linux/acpi_iort.h +@@ -31,7 +31,6 @@ + * that, this is not part of the IORT specification. + */ + #define IORT_SMMU_V3_PMCG_GENERIC 0x00000000 /* Generic SMMUv3 PMCG */ +-#define IORT_SMMU_V3_PMCG_HISI_HIP08 0x00000001 /* HiSilicon HIP08 PMCG */ + + int iort_register_domain_token(int trans_id, phys_addr_t base, + struct fwnode_handle *fw_node); +-- +2.27.0 + diff --git a/patches/0094-perf-smmuv3-Enable-HiSilicon-Erratum-162001800-quirk.patch b/patches/0094-perf-smmuv3-Enable-HiSilicon-Erratum-162001800-quirk.patch new file mode 100644 index 0000000..9f4f003 --- /dev/null +++ b/patches/0094-perf-smmuv3-Enable-HiSilicon-Erratum-162001800-quirk.patch @@ -0,0 +1,197 @@ +From b917df0a2ab2eba9cc49d2019f5222e70f42dc60 Mon Sep 17 00:00:00 2001 +From: Shameer Kolothum +Date: Tue, 26 Mar 2019 15:17:53 +0000 +Subject: [PATCH 53/55] perf/smmuv3: Enable HiSilicon Erratum 162001800 quirk + +mainline inclusion +from mainline-v5.2-rc1 +commit 24062fe85860debfdae0eeaa495f27c9971ec163 +category: feature +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=24062fe85860debfdae0eeaa495f27c9971ec163 + +---------------------------------------------------------- + +HiSilicon erratum 162001800 describes the limitation of +SMMUv3 PMCG implementation on HiSilicon Hip08 platforms. + +On these platforms, the PMCG event counter registers +(SMMU_PMCG_EVCNTRn) are read only and as a result it +is not possible to set the initial counter period value +on event monitor start. + +To work around this, the current value of the counter +is read and used for delta calculations. OEM information +from ACPI header is used to identify the affected hardware +platforms. + +Signed-off-by: Shameer Kolothum +Reviewed-by: Hanjun Guo +Reviewed-by: Robin Murphy +Acked-by: Lorenzo Pieralisi +[will: update silicon-errata.txt and add reason string to acpi match] +Signed-off-by: Will Deacon +Signed-off-by: hongrongxuan + + Conflicts: + Documentation/arm64/silicon-errata.txt +--- + Documentation/arm64/silicon-errata.txt | 1 + + drivers/acpi/arm64/iort.c | 16 ++++++++- + drivers/perf/arm_smmuv3_pmu.c | 48 ++++++++++++++++++++++---- + include/linux/acpi_iort.h | 1 + + 4 files changed, 58 insertions(+), 8 deletions(-) + +diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt +index 5016158f5e67..e733d13d7b98 100644 +--- a/Documentation/arm64/silicon-errata.txt ++++ b/Documentation/arm64/silicon-errata.txt +@@ -79,6 +79,7 @@ stable kernels. + | Hisilicon | Hip07 | #161600802 | HISILICON_ERRATUM_161600802 | + | Hisilicon | TSV{110,200} | #1980005 | HISILICON_ERRATUM_1980005 | + | Hisilicon | Hip09 | #162100801 | HISILICON_ERRATUM_161600801 | ++| Hisilicon | Hip08 SMMU PMCG | #162001800 | N/A | + | | | | | + | Qualcomm Tech. | Kryo/Falkor v1 | E1003 | QCOM_FALKOR_ERRATUM_1003 | + | Qualcomm Tech. | Falkor v1 | E1009 | QCOM_FALKOR_ERRATUM_1009 | +diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c +index d507556d508f..abc62558e818 100644 +--- a/drivers/acpi/arm64/iort.c ++++ b/drivers/acpi/arm64/iort.c +@@ -1476,9 +1476,23 @@ static void __init arm_smmu_v3_pmcg_init_resources(struct resource *res, + ACPI_EDGE_SENSITIVE, &res[2]); + } + ++static struct acpi_platform_list pmcg_plat_info[] __initdata = { ++ /* HiSilicon Hip08 Platform */ ++ {"HISI ", "HIP08 ", 0, ACPI_SIG_IORT, greater_than_or_equal, ++ "Erratum #162001800", IORT_SMMU_V3_PMCG_HISI_HIP08}, ++ { } ++}; ++ + static int __init arm_smmu_v3_pmcg_add_platdata(struct platform_device *pdev) + { +- u32 model = IORT_SMMU_V3_PMCG_GENERIC; ++ u32 model; ++ int idx; ++ ++ idx = acpi_match_platform_list(pmcg_plat_info); ++ if (idx >= 0) ++ model = pmcg_plat_info[idx].data; ++ else ++ model = IORT_SMMU_V3_PMCG_GENERIC; + + return platform_device_add_data(pdev, &model, sizeof(model)); + } +diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c +index e9cd120f4268..3df836fd2f70 100644 +--- a/drivers/perf/arm_smmuv3_pmu.c ++++ b/drivers/perf/arm_smmuv3_pmu.c +@@ -35,6 +35,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -93,6 +94,8 @@ + + #define SMMU_PMCG_PA_SHIFT 12 + ++#define SMMU_PMCG_EVCNTR_RDONLY BIT(0) ++ + static int cpuhp_state_num; + + struct smmu_pmu { +@@ -108,6 +111,7 @@ struct smmu_pmu { + void __iomem *reg_base; + void __iomem *reloc_base; + u64 counter_mask; ++ u32 options; + bool global_filter; + }; + +@@ -220,15 +224,27 @@ static void smmu_pmu_set_period(struct smmu_pmu *smmu_pmu, + u32 idx = hwc->idx; + u64 new; + +- /* +- * We limit the max period to half the max counter value of the counter +- * size, so that even in the case of extreme interrupt latency the +- * counter will (hopefully) not wrap past its initial value. +- */ +- new = smmu_pmu->counter_mask >> 1; ++ if (smmu_pmu->options & SMMU_PMCG_EVCNTR_RDONLY) { ++ /* ++ * On platforms that require this quirk, if the counter starts ++ * at < half_counter value and wraps, the current logic of ++ * handling the overflow may not work. It is expected that, ++ * those platforms will have full 64 counter bits implemented ++ * so that such a possibility is remote(eg: HiSilicon HIP08). ++ */ ++ new = smmu_pmu_counter_get_value(smmu_pmu, idx); ++ } else { ++ /* ++ * We limit the max period to half the max counter value ++ * of the counter size, so that even in the case of extreme ++ * interrupt latency the counter will (hopefully) not wrap ++ * past its initial value. ++ */ ++ new = smmu_pmu->counter_mask >> 1; ++ smmu_pmu_counter_set_value(smmu_pmu, idx, new); ++ } + + local64_set(&hwc->prev_count, new); +- smmu_pmu_counter_set_value(smmu_pmu, idx, new); + } + + static void smmu_pmu_set_event_filter(struct perf_event *event, +@@ -702,6 +718,22 @@ static void smmu_pmu_reset(struct smmu_pmu *smmu_pmu) + smmu_pmu->reloc_base + SMMU_PMCG_OVSCLR0); + } + ++static void smmu_pmu_get_acpi_options(struct smmu_pmu *smmu_pmu) ++{ ++ u32 model; ++ ++ model = *(u32 *)dev_get_platdata(smmu_pmu->dev); ++ ++ switch (model) { ++ case IORT_SMMU_V3_PMCG_HISI_HIP08: ++ /* HiSilicon Erratum 162001800 */ ++ smmu_pmu->options |= SMMU_PMCG_EVCNTR_RDONLY; ++ break; ++ } ++ ++ dev_notice(smmu_pmu->dev, "option mask 0x%x\n", smmu_pmu->options); ++} ++ + static int smmu_pmu_probe(struct platform_device *pdev) + { + struct smmu_pmu *smmu_pmu; +@@ -781,6 +813,8 @@ static int smmu_pmu_probe(struct platform_device *pdev) + return -EINVAL; + } + ++ smmu_pmu_get_acpi_options(smmu_pmu); ++ + /* Pick one CPU to be the preferred one to use */ + smmu_pmu->on_cpu = raw_smp_processor_id(); + WARN_ON(irq_set_affinity(smmu_pmu->irq, cpumask_of(smmu_pmu->on_cpu))); +diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h +index 832bd6ae9ad4..bdb69125854e 100644 +--- a/include/linux/acpi_iort.h ++++ b/include/linux/acpi_iort.h +@@ -31,6 +31,7 @@ + * that, this is not part of the IORT specification. + */ + #define IORT_SMMU_V3_PMCG_GENERIC 0x00000000 /* Generic SMMUv3 PMCG */ ++#define IORT_SMMU_V3_PMCG_HISI_HIP08 0x00000001 /* HiSilicon HIP08 PMCG */ + + int iort_register_domain_token(int trans_id, phys_addr_t base, + struct fwnode_handle *fw_node); +-- +2.27.0 + diff --git a/patches/0095-perf-smmuv3-Enable-HiSilicon-Erratum-162001900-quirk.patch b/patches/0095-perf-smmuv3-Enable-HiSilicon-Erratum-162001900-quirk.patch new file mode 100644 index 0000000..30988f3 --- /dev/null +++ b/patches/0095-perf-smmuv3-Enable-HiSilicon-Erratum-162001900-quirk.patch @@ -0,0 +1,170 @@ +From 081bfa93450c8b4aa3f483eb14ec7a1bae34f9d4 Mon Sep 17 00:00:00 2001 +From: Yicong Yang +Date: Mon, 14 Aug 2023 20:40:12 +0800 +Subject: [PATCH 54/55] perf/smmuv3: Enable HiSilicon Erratum 162001900 quirk + for HIP08/09 + +mainline inclusion +from mainline-v6.6-rc1 +commit 0242737dc4eb9f6e9a5ea594b3f93efa0b12f28d +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0242737dc4eb9f6e9a5ea594b3f93efa0b12f28d + +--------------------------------------------------------------------- + +Some HiSilicon SMMU PMCG suffers the erratum 162001900 that the PMU +disable control sometimes fail to disable the counters. This will lead +to error or inaccurate data since before we enable the counters the +counter's still counting for the event used in last perf session. + +This patch tries to fix this by hardening the global disable process. +Before disable the PMU, writing an invalid event type (0xffff) to +focibly stop the counters. Correspondingly restore each events on +pmu::pmu_enable(). + +Signed-off-by: Yicong Yang +Link: https://lore.kernel.org/r/20230814124012.58013-1-yangyicong@huawei.com +Signed-off-by: Will Deacon +Signed-off-by: hongrongxuan + + Conflicts: + Documentation/arch/arm64/silicon-errata.rst +--- + Documentation/arm64/silicon-errata.txt | 3 ++ + drivers/acpi/arm64/iort.c | 5 ++- + drivers/perf/arm_smmuv3_pmu.c | 46 +++++++++++++++++++++++++- + include/linux/acpi_iort.h | 1 + + 4 files changed, 53 insertions(+), 2 deletions(-) + +diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt +index e733d13d7b98..c5aad5509a5a 100644 +--- a/Documentation/arm64/silicon-errata.txt ++++ b/Documentation/arm64/silicon-errata.txt +@@ -80,6 +80,9 @@ stable kernels. + | Hisilicon | TSV{110,200} | #1980005 | HISILICON_ERRATUM_1980005 | + | Hisilicon | Hip09 | #162100801 | HISILICON_ERRATUM_161600801 | + | Hisilicon | Hip08 SMMU PMCG | #162001800 | N/A | ++| Hisilicon | Hip08 SMMU PMCG | #162001900 | N/A ++| ++| | Hip09 SMMU PMCG | | + | | | | | + | Qualcomm Tech. | Kryo/Falkor v1 | E1003 | QCOM_FALKOR_ERRATUM_1003 | + | Qualcomm Tech. | Falkor v1 | E1009 | QCOM_FALKOR_ERRATUM_1009 | +diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c +index abc62558e818..7cfbf52055f8 100644 +--- a/drivers/acpi/arm64/iort.c ++++ b/drivers/acpi/arm64/iort.c +@@ -1479,7 +1479,10 @@ static void __init arm_smmu_v3_pmcg_init_resources(struct resource *res, + static struct acpi_platform_list pmcg_plat_info[] __initdata = { + /* HiSilicon Hip08 Platform */ + {"HISI ", "HIP08 ", 0, ACPI_SIG_IORT, greater_than_or_equal, +- "Erratum #162001800", IORT_SMMU_V3_PMCG_HISI_HIP08}, ++ "Erratum #162001800, Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP08}, ++ /* HiSilicon Hip09 Platform */ ++ {"HISI ", "HIP09 ", 0, ACPI_SIG_IORT, greater_than_or_equal, ++ "Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP09}, + { } + }; + +diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c +index 3df836fd2f70..56e6f6773675 100644 +--- a/drivers/perf/arm_smmuv3_pmu.c ++++ b/drivers/perf/arm_smmuv3_pmu.c +@@ -95,6 +95,7 @@ + #define SMMU_PMCG_PA_SHIFT 12 + + #define SMMU_PMCG_EVCNTR_RDONLY BIT(0) ++#define SMMU_PMCG_HARDEN_DISABLE BIT(1) + + static int cpuhp_state_num; + +@@ -138,6 +139,20 @@ static inline void smmu_pmu_enable(struct pmu *pmu) + writel(SMMU_PMCG_CR_ENABLE, smmu_pmu->reg_base + SMMU_PMCG_CR); + } + ++static int smmu_pmu_apply_event_filter(struct smmu_pmu *smmu_pmu, ++ struct perf_event *event, int idx); ++ ++static inline void smmu_pmu_enable_quirk_hip08_09(struct pmu *pmu) ++{ ++ struct smmu_pmu *smmu_pmu = to_smmu_pmu(pmu); ++ unsigned int idx; ++ ++ for_each_set_bit(idx, smmu_pmu->used_counters, smmu_pmu->num_counters) ++ smmu_pmu_apply_event_filter(smmu_pmu, smmu_pmu->events[idx], idx); ++ ++ smmu_pmu_enable(pmu); ++} ++ + static inline void smmu_pmu_disable(struct pmu *pmu) + { + struct smmu_pmu *smmu_pmu = to_smmu_pmu(pmu); +@@ -146,6 +161,22 @@ static inline void smmu_pmu_disable(struct pmu *pmu) + writel(0, smmu_pmu->reg_base + SMMU_PMCG_IRQ_CTRL); + } + ++static inline void smmu_pmu_disable_quirk_hip08_09(struct pmu *pmu) ++{ ++ struct smmu_pmu *smmu_pmu = to_smmu_pmu(pmu); ++ unsigned int idx; ++ ++ /* ++ * The global disable of PMU sometimes fail to stop the counting. ++ * Harden this by writing an invalid event type to each used counter ++ * to forcibly stop counting. ++ */ ++ for_each_set_bit(idx, smmu_pmu->used_counters, smmu_pmu->num_counters) ++ writel(0xffff, smmu_pmu->reg_base + SMMU_PMCG_EVTYPER(idx)); ++ ++ smmu_pmu_disable(pmu); ++} ++ + static inline void smmu_pmu_counter_set_value(struct smmu_pmu *smmu_pmu, + u32 idx, u64 value) + { +@@ -727,7 +758,10 @@ static void smmu_pmu_get_acpi_options(struct smmu_pmu *smmu_pmu) + switch (model) { + case IORT_SMMU_V3_PMCG_HISI_HIP08: + /* HiSilicon Erratum 162001800 */ +- smmu_pmu->options |= SMMU_PMCG_EVCNTR_RDONLY; ++ smmu_pmu->options |= SMMU_PMCG_EVCNTR_RDONLY | SMMU_PMCG_HARDEN_DISABLE; ++ break; ++ case IORT_SMMU_V3_PMCG_HISI_HIP09: ++ smmu_pmu->options |= SMMU_PMCG_HARDEN_DISABLE; + break; + } + +@@ -815,6 +849,16 @@ static int smmu_pmu_probe(struct platform_device *pdev) + + smmu_pmu_get_acpi_options(smmu_pmu); + ++ /* ++ * For platforms suffer this quirk, the PMU disable sometimes fails to ++ * stop the counters. This will leads to inaccurate or error counting. ++ * Forcibly disable the counters with these quirk handler. ++ */ ++ if (smmu_pmu->options & SMMU_PMCG_HARDEN_DISABLE) { ++ smmu_pmu->pmu.pmu_enable = smmu_pmu_enable_quirk_hip08_09; ++ smmu_pmu->pmu.pmu_disable = smmu_pmu_disable_quirk_hip08_09; ++ } ++ + /* Pick one CPU to be the preferred one to use */ + smmu_pmu->on_cpu = raw_smp_processor_id(); + WARN_ON(irq_set_affinity(smmu_pmu->irq, cpumask_of(smmu_pmu->on_cpu))); +diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h +index bdb69125854e..b1c1c84a422e 100644 +--- a/include/linux/acpi_iort.h ++++ b/include/linux/acpi_iort.h +@@ -32,6 +32,7 @@ + */ + #define IORT_SMMU_V3_PMCG_GENERIC 0x00000000 /* Generic SMMUv3 PMCG */ + #define IORT_SMMU_V3_PMCG_HISI_HIP08 0x00000001 /* HiSilicon HIP08 PMCG */ ++#define IORT_SMMU_V3_PMCG_HISI_HIP09 0x00000002 /* HiSilicon HIP09 PMCG */ + + int iort_register_domain_token(int trans_id, phys_addr_t base, + struct fwnode_handle *fw_node); +-- +2.27.0 + diff --git a/patches/0096-perf-smmuv3-Add-MODULE_ALIAS-for-module-auto-loading.patch b/patches/0096-perf-smmuv3-Add-MODULE_ALIAS-for-module-auto-loading.patch new file mode 100644 index 0000000..759ec89 --- /dev/null +++ b/patches/0096-perf-smmuv3-Add-MODULE_ALIAS-for-module-auto-loading.patch @@ -0,0 +1,57 @@ +From 381dea7a1598760dcffcbce4f819bbe7035a3b13 Mon Sep 17 00:00:00 2001 +From: Yicong Yang +Date: Mon, 14 Aug 2023 21:16:42 +0800 +Subject: [PATCH 55/55] perf/smmuv3: Add MODULE_ALIAS for module auto loading + +mainline inclusion +from mainline-v6.6-rc1 +commit 1b0e3ea9301a422003d385cda8f8dee6c878ad05 +category: bugfix +bugzilla: https://gitee.com/openeuler/kernel/issues/I8AU2M + +Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1b0e3ea9301a422003d385cda8f8dee6c878ad05 + +------------------------------------------------------------------ + +On my ACPI based arm64 server, if the SMMUv3 PMU is configured as +module it won't be loaded automatically after booting even if the +device has already been scanned and added. It's because the module +lacks a platform alias, the uevent mechanism and userspace tools +like udevd make use of this to find the target driver module of the +device. This patch adds the missing platform alias of the module, +then module will be loaded automatically if device exists. + +Before this patch: +[root@localhost tmp]# modinfo arm_smmuv3_pmu | grep alias +alias: of:N*T*Carm,smmu-v3-pmcgC* +alias: of:N*T*Carm,smmu-v3-pmcg + +After this patch: +[root@localhost tmp]# modinfo arm_smmuv3_pmu | grep alias +alias: platform:arm-smmu-v3-pmcg +alias: of:N*T*Carm,smmu-v3-pmcgC* +alias: of:N*T*Carm,smmu-v3-pmcg + +Signed-off-by: Yicong Yang +Link: https://lore.kernel.org/r/20230814131642.65263-1-yangyicong@huawei.com +Signed-off-by: Will Deacon +Signed-off-by: hongrongxuan +--- + drivers/perf/arm_smmuv3_pmu.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c +index 56e6f6773675..1fae44c24ff9 100644 +--- a/drivers/perf/arm_smmuv3_pmu.c ++++ b/drivers/perf/arm_smmuv3_pmu.c +@@ -941,6 +941,7 @@ static void __exit arm_smmu_pmu_exit(void) + + module_exit(arm_smmu_pmu_exit); + ++MODULE_ALIAS("platform:arm-smmu-v3-pmcg"); + MODULE_DESCRIPTION("PMU driver for ARM SMMUv3 Performance Monitors Extension"); + MODULE_AUTHOR("Neil Leeder "); + MODULE_AUTHOR("Shameer Kolothum "); +-- +2.27.0 + diff --git a/series.conf b/series.conf index 1470060..987dcc1 100644 --- a/series.conf +++ b/series.conf @@ -43,3 +43,58 @@ patches/0038-perf-arm-spe-Add-more-sub-classes-for-operation-pack.patch patches/0039-perf-arm_spe-Decode-memory-tagging-properties.patch patches/0040-perf-arm-spe-Add-support-for-ARMv8.3-SPE.patch patches/0041-drivers-perf-Add-support-for-ARMv8.3-SPE.patch +patches/0042-Revert-perf-hisi-Fix-compile-error-if-defined-MODULE.patch +patches/0043-Revert-perf-hisi-Add-support-for-HiSilicon-SoC-L3T-P.patch +patches/0044-Revert-perf-hisi-Add-support-for-HiSilicon-SoC-LPDDR.patch +patches/0045-Revert-perf-hisi-Add-support-for-HiSilicon-SoC-PMU-d.patch +patches/0046-Revert-drivers-perf-Fix-kernel-panic-when-rmmod-PMU-.patch +patches/0047-Revert-perf-hisi-remove-duplicated-code.patch +patches/0048-docs-perf-convert-to-ReST.patch +patches/0049-drivers-perf-Fix-kernel-panic-when-rmmod-PMU-modules.patch +patches/0050-For-drivers-that-do-not-support-context-exclusion-le.patch +patches/0051-drivers-provide-devm_platform_ioremap_resource.patch +patches/0052-perf-hisi-use-devm_platform_ioremap_resource-to-simp.patch +patches/0053-drivers-perf-hisi-Add-identifier-sysfs-file.patch +patches/0054-drivers-perf-hisi-Remove-unnecessary-check-of-counte.patch +patches/0055-drivers-perf-hisi-Refactor-code-for-more-uncore-PMUs.patch +patches/0056-drivers-perf-hisi-Add-PMU-version-for-uncore-PMU-dri.patch +patches/0057-drivers-perf-hisi-Add-new-functions-for-L3C-PMU.patch +patches/0058-drivers-perf-hisi-Add-new-functions-for-HHA-PMU.patch +patches/0059-drivers-perf-hisi-Update-DDRC-PMU-for-programmable-c.patch +patches/0060-drivers-perf-hisi-Add-support-for-HiSilicon-SLLC-PMU.patch +patches/0061-drivers-perf-hisi-Add-support-for-HiSilicon-PA-PMU-d.patch +patches/0062-perf-hisi-Use-irq_set_affinity.patch +patches/0063-drivers-perf-hisi-Fix-data-source-control.patch +patches/0064-perf-hisi-Make-irq-shared.patch +patches/0065-perf-hisi-Fix-read-sccl_id-and-ccl_id-error-in-some-.patch +patches/0066-perf-hisi-Add-support-for-HiSilicon-SoC-L3T-PMU.patch +patches/0067-perf-hisi-Add-support-for-HiSilicon-SoC-LPDDRC-PMU.patch +patches/0068-perf-hisi-Fix-unexpected-modifications-in-hisi_uncor.patch +patches/0069-PCI-Add-pci_dev_id-helper.patch +patches/0070-drivers-perf-hisi-Add-driver-for-HiSilicon-PCIe-PMU.patch +patches/0071-drivers-perf-hisi-Associate-PMUs-in-SICL-with-CPUs-o.patch +patches/0072-driver-perf-hisi-fix-kabi-broken-for-struct-hisi_pmu.patch +patches/0073-drivers-perf-hisi-Add-Support-for-CPA-PMU.patch +patches/0074-drivers-perf-hisi-Fix-some-event-id-for-hisi-pcie-pm.patch +patches/0075-docs-perf-move-to-the-admin-guide.patch +patches/0076-docs-perf-Add-new-description-on-HiSilicon-uncore-PM.patch +patches/0077-docs-perf-Add-description-for-HiSilicon-PCIe-PMU-dri.patch +patches/0078-docs-perf-Address-some-html-build-warnings.patch +patches/0079-docs-fix-make-htmldocs-warning-in-perf.patch +patches/0080-docs-perf-Fix-PMU-instance-name-of-hisi-pcie-pmu.patch +patches/0081-drivers-perf-hisi-Add-TLP-filter-support.patch +patches/0082-drivers-perf-hisi-Don-t-migrate-perf-to-the-CPU-goin.patch +patches/0083-drivers-perf-fixed-the-issue-that-the-kabi-value-cha.patch +patches/0084-drivers-perf-fixed-kabi-broken-for-SLLC-and-PA-PMU.patch +patches/0085-perf-hisi-Fix-read-sccl_id-and-ccl_id-error-in-TSV20.patch +patches/0086-perf-hisi-Add-configs-for-PMU-isolation.patch +patches/0087-perf-hisi-Extract-hisi_pmu_init.patch +patches/0088-drivers-perf-hisi-Advertise-the-PERF_PMU_CAP_NO_EXCL.patch +patches/0089-drivers-perf-hisi-Simplify-the-parameters-of-hisi_pm.patch +patches/0090-drivers-perf-hisi-Extract-initialization-of-cpa_pmu-.patch +patches/0091-drivers-perf-hisi-Remove-redundant-initialized-of-pm.patch +patches/0092-drivers-perf-hisi-add-NULL-check-for-name.patch +patches/0093-Revert-perf-smmuv3_pmu-Enable-HiSilicon-Erratum-1620.patch +patches/0094-perf-smmuv3-Enable-HiSilicon-Erratum-162001800-quirk.patch +patches/0095-perf-smmuv3-Enable-HiSilicon-Erratum-162001900-quirk.patch +patches/0096-perf-smmuv3-Add-MODULE_ALIAS-for-module-auto-loading.patch