[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <279DAED08550A69A+3d025259-f011-4312-946d-6f7564a12898@shingroup.cn>
Date: Wed, 31 Jan 2024 10:57:25 +0800
From: Yang Jialong 杨佳龙 <jialong.yang@...ngroup.cn>
To: Krzysztof Kozlowski <krzysztof.kozlowski@...aro.org>,
Will Deacon <will@...nel.org>, Mark Rutland <mark.rutland@....com>,
Rob Herring <robh+dt@...nel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@...aro.org>,
Conor Dooley <conor+dt@...nel.org>
Cc: shenghui.qu@...ngroup.cn, ke.zhao@...ngroup.cn, zhijie.ren@...ngroup.cn,
Rob Herring <robh@...nel.org>, linux-arm-kernel@...ts.infradead.org,
devicetree@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH v1] perf/hx_arm_ni: Support uncore ARM NI-700 PMU
在 2024/1/30 16:43, Krzysztof Kozlowski 写道:
> On 30/01/2024 09:17, JiaLong.Yang wrote:
>> This code is based on uncore PMUs arm_smmuv3_pmu and arm-cmn.
>> One ni-700 can have many clock domains. Each of them has only one PMU.
>> Here one PMU corresponds to one 'struct ni_pmu' instance.
>> PMU name will be ni_pmu_N_M, which N means different NI-700s and M means
>> different PMU in one NI-700. If only one NI-700 found in NI-700, name will
>> be ni_pmu_N.
>> Node interface event name will be xxni_N_eventname, such as asni_0_rdreq_any.
>> There are many kinds of type of nodes in one clock domain. Also means that
>> there are many kinds of that in one PMU. So we distinguish them by xxni string.
>> Besides, maybe there are many nodes have same type. So we have number N in
>> event name.
>> By ni_pmu_0_0/asni_0_rdreq_any/, we can pinpoint accurate bus traffic.
>> Example1: perf stat -a -e ni_pmu_0_0/asni_0_rdreq_any/,ni_pmu_0_0/cycles/
>> EXample2: perf stat -a -e ni_pmu_0_0/asni,id=0,event=0x0/
>>
>> Signed-off-by: JiaLong.Yang <jialong.yang@...ngroup.cn>
>> ---
>> If I should send Doc*/bindings/perf/*.yaml seperately?
>
> Checkpatch tells you that, doesn't it?
OK. I will send it seperately.
>
> Please run scripts/checkpatch.pl and fix reported warnings. Some
> warnings can be ignored, but the code here looks like it needs a fix.
> Feel free to get in touch if the warning is not clear.
OK.
>
>>
>> .../bindings/perf/hx,c2000-arm-ni.yaml | 58 +
>> .../devicetree/bindings/vendor-prefixes.yaml | 2 +
>> MAINTAINERS | 6 +
>> drivers/perf/Kconfig | 10 +
>> drivers/perf/Makefile | 1 +
>> drivers/perf/hx_arm_ni.c | 1308 +++++++++++++++++
>> 6 files changed, 1385 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/perf/hx,c2000-arm-ni.yaml
>> create mode 100644 drivers/perf/hx_arm_ni.c
>>
>> diff --git a/Documentation/devicetree/bindings/perf/hx,c2000-arm-ni.yaml b/Documentation/devicetree/bindings/perf/hx,c2000-arm-ni.yaml
>> new file mode 100644
>> index 000000000000..1b145ecbfa83
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/perf/hx,c2000-arm-ni.yaml
>> @@ -0,0 +1,58 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/perf/hx,c2000-arm-ni.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: HX-C2000 NI (Network-on_chip Interconnect) Performance Monitors
>> +
>> +maintainers:
>> + - Jialong Yang <jialong.yang@...ngroup.cn>
>> +
>> +properties:
>> + compatible:
>> + enum:
>> + - hx,c2000-arm-ni
>> +
>> + reg:
>> + items:
>> + - description: Physical address of the base (PERIPHBASE) and
>> + size of the whole NI configuration address space.
>> +
>> + interrupts:
>> + minItems: 1
>
> Why?
According to hw, one PMU has one interrupt line. So one NI maybe has
more than one. But actually it depends on hw implementation.
And in C code, I will return error when there is no interrupt.
>
>> + items:
>> + - description: Overflow interrupt for clock domain 0
>> + - description: Overflow interrupt for clock domain 1
>> + - description: Overflow interrupt for clock domain 2
>> + description: Generally, one interrupt line for one PMU. But this also
>> + support one interrupt line for a NI if merged.
>> +
>> +required:
>> + - compatible
>> + - reg
>> + - interrupts
>> +
>> +if:
>> + properties:
>> + compatible:
>> + contains:
>> + const: hx,c2000-arm-ni
>
> Drop entire if. What is the point of it?
This attribute is used to identify different NI in my company's product.
But even if I don't give this attribute, nothing will be wrong in code.
However if I do that, I will couldn't know the relation between sysfs
file and hardware NI.
I will drop it. It will be as a normal way to identify NIs manually.
If there is only one NI and not give pccs-id, no thing wrong will happen.
>
>> +then:
>> + required:
>> + - pccs-id
>> +
>> +additionalProperties: false
>> +
>> +examples:
>> + - |
>> + #include <dt-bindings/interrupt-controller/arm-gic.h>
>> + #include <dt-bindings/interrupt-controller/irq.h>
>> +
>> + ni-pmu@...f0000 {
>
> Node names should be generic. See also an explanation and list of
> examples (not exhaustive) in DT specification:
> https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#generic-names-recommendation
OK.
>
>
>> + compatible = "hx,c2000-arm-ni";
>> + #address-cells = <1>;
>> + #size-cells = <1>;
>
> Broken indentation.....
>
>
> (...)
>
>> + ni_pmu->dev = dev;
>> + ni_pmu->ni = ni;
>> + ni->ni_pmus[cd_idx] = ni_pmu;
>> + }
>> +
>> + devm_kfree(dev, cd_arrays);
>> +
>> + pr_info("End discovering hardware registers.");
>
> That's rather useless print. First entire driver must use dev_*. Second,
> drop it, no need for end-of-function prints.
OK.
>
>> +
>> + return 0;
>> +}
>> +
>> +static int ni_pmu_probe(struct platform_device *pdev)
>> +{
>> + int ret, cd_num, idx, irq_num, irq_idx;
>> + void __iomem *periphbase;
>> + struct global_ni *ni;
>> + struct device *dev = &pdev->dev;
>> + char *name;
>> + static int id;
>> + struct ni_pmu *ni_pmu;
>> +
>> + BUILD_BUG_ON(sizeof(long) == 4);
>
> I am sorry, but what?
I only want to ensure 64 bit environment. Maybe there are many other way.
I will ensure that in Kconfig.
>
>> + BUILD_BUG_ON(sizeof(struct ni_hw_perf_event) >
>> + offsetof(struct hw_perf_event, target));
>> +#define NI_PMU_REG_MAP_SIZE 0xE08
>> + BUILD_BUG_ON(sizeof(struct ni_pmu_reg_map) != NI_PMU_REG_MAP_SIZE);
>> +
>> + pr_info("Begin probing.");
>
> NAK, drop. Drop all silly entrance/exit messages. EVERYWHERE.
OK.
>
>> +
>> + periphbase = devm_platform_ioremap_resource(pdev, 0);
>> +
>
> Drop blank line
OK.
>
>> + if (IS_ERR(periphbase)) {
>> + pr_err("%s: ioremap error.", __func__);
>
> dev_err and you need to print something useful, like error code. Or use
> return dev_err_probe
OK.
>
>> + return PTR_ERR(periphbase);
>> + }
>> +
>> + cd_num = ni_child_number_total(periphbase, periphbase, NI_CD);
>> + pr_info("%d clock domains found in NI-700.", cd_num);
>
> Really, what's with all this printing?
I just want to print how many clock domains.
One clock domain correspond to one PMU.
>
>> +
>> + /* Each clock domain contains one PMU. So cd_num == pmu_num. */
>> + ni = devm_kzalloc(dev,
>> + struct_size(ni, ni_pmus, cd_num),
>> + GFP_KERNEL);
>> + if (!ni)
>> + return -ENOMEM;
>> +
>> + ni->cd_num = cd_num;
>> + ni->base = periphbase;
>> + ni->dev = dev;
>> + ni->on_cpu = raw_smp_processor_id();
>> + platform_set_drvdata(pdev, ni);
>> +
>> + ret = ni_discovery(ni);
>> + if (ret) {
>> + pr_err("%s: discovery error.", __func__);
>> + return ret;
>> + }
>> +
>> + irq_num = platform_irq_count(pdev);
>> + /* Support that one NI with one irq or one clock domain with one irq. */
>> + if (irq_num < 0 || (irq_num != 1 && irq_num != ni->cd_num)) {
>> + pr_err("Error in irq number: %d.", irq_num);
>> + return -EINVAL;
>> + }
>> +
>> + if (irq_num != cd_num) {
>> + pr_warn("Only one IRQ found for all PMU.");
>> + ret = ni_pmu_irq_setup(ni->ni_pmus[0], 0);
>> + if (ret)
>> + return ret;
>> + }
>> +
>> + ni->irq_num = irq_num;
>> +
>> + for (idx = 0, irq_idx = 0; idx < ni->pmu_num; idx++) {
>> + ni_pmu = ni->ni_pmus[idx];
>> + ret = ni_pmu_init_attr_groups(ni_pmu);
>> + if (ret)
>> + return ret;
>> +
>> + if (irq_num == cd_num) {
>> + ret = ni_pmu_irq_setup(ni_pmu, irq_idx++);
>> + if (ret)
>> + return ret;
>> + }
>> +
>> + ni_pmu_reset(ni_pmu);
>> +
>> + ni_pmu->pmu = (struct pmu) {
>> + .module = THIS_MODULE,
>> + .task_ctx_nr = perf_invalid_context,
>> + .pmu_enable = ni_pmu_enable,
>> + .pmu_disable = ni_pmu_disable,
>> + .event_init = ni_pmu_event_init,
>> + .add = ni_pmu_event_add,
>> + .del = ni_pmu_event_del,
>> + .start = ni_pmu_event_start,
>> + .stop = ni_pmu_event_stop,
>> + .read = ni_pmu_event_read,
>> + .attr_groups = ni_pmu->pmu.attr_groups,
>> + .capabilities = PERF_PMU_CAP_NO_EXCLUDE | PERF_PMU_CAP_NO_INTERRUPT,
>> + };
>> +
>> +#ifdef CONFIG_PPC_HX_C2000
>> + if (of_property_read_u32(pdev->dev.of_node, "pccs-id", &id))
>> + pr_warn("No found pccs_id in dts ni pmu node.");
>> +#endif
>> + if (cd_num > 1)
>> + name = devm_kasprintf(dev, GFP_KERNEL, "ni_pmu_%d_%d", id++, idx);
>> + else
>> + name = devm_kasprintf(dev, GFP_KERNEL, "ni_pmu_%d", id++);
>> +
>> + ret = perf_pmu_register(&ni_pmu->pmu, name, -1);
>> + if (ret) {
>> + pr_err("Error %d_%d registering PMU", id - 1, idx);
>> + return ret;
>> + }
>> + }
>> +
>> + ret = cpuhp_state_add_instance_nocalls(ni_hp_state,
>> + &ni->node);
>> + if (ret)
>> + return ret;
>> + pr_info("End probing.");
>
> No, drop.
>
>> +
>> + return 0;
>> +}
>> +
>> +static int ni_pmu_remove(struct platform_device *pdev)
>> +{
>> + struct global_ni *ni = platform_get_drvdata(pdev);
>> + int idx;
>> +
>> + for (idx = 0; idx < ni->pmu_num; idx++)
>> + perf_pmu_unregister(&ni->ni_pmus[idx]->pmu);
>> +
>> + cpuhp_remove_multi_state(ni_hp_state);
>> + return 0;
>> +}
>> +
>> +static const struct of_device_id ni_pmu_of_match[] = {
>> + { .compatible = "hx,c2000-arm-ni" },
>> + {},
>> +};
>> +
>> +static struct platform_driver ni_pmu_driver = {
>> + .driver = {
>> + .name = "ni-pmu",
>> + .of_match_table = of_match_ptr(ni_pmu_of_match),
>
> Drop of_match_ptr. Leads to warnings.
OK.
>
>
> ...
>
>> +
>> +module_init(ni_pmu_init);
>> +module_exit(ni_pmu_exit);
>> +/* PLATFORM END */
>
> Useless comment. Please clean your code from debugging or useless markers.
Done.
>
>
>
> Best regards,
> Krzysztof
>
>
Powered by blists - more mailing lists