From: Jonathan Cameron <jonathan.cameron@huawei.com>
To: "Clément Le Goffic" <legoffic.clement@gmail.com>
Cc: "Gatien Chevallier" <gatien.chevallier@foss.st.com>,
"Maxime Coquelin" <mcoquelin.stm32@gmail.com>,
"Alexandre Torgue" <alexandre.torgue@foss.st.com>,
"Michael Turquette" <mturquette@baylibre.com>,
"Stephen Boyd" <sboyd@kernel.org>,
"Rob Herring" <robh@kernel.org>,
"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
"Conor Dooley" <conor+dt@kernel.org>,
"Gabriel Fernandez" <gabriel.fernandez@foss.st.com>,
"Krzysztof Kozlowski" <krzk@kernel.org>,
"Julius Werner" <jwerner@chromium.org>,
"Will Deacon" <will@kernel.org>,
"Mark Rutland" <mark.rutland@arm.com>,
"Philipp Zabel" <p.zabel@pengutronix.de>,
"Jonathan Corbet" <corbet@lwn.net>,
linux-stm32@st-md-mailman.stormreply.com,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org,
devicetree@vger.kernel.org, linux-perf-users@vger.kernel.org,
linux-doc@vger.kernel.org,
"Clément Le Goffic" <clement.legoffic@foss.st.com>
Subject: Re: [PATCH v6 13/20] perf: stm32: introduce DDRPERFM driver
Date: Wed, 10 Sep 2025 10:26:27 +0100 [thread overview]
Message-ID: <20250910102627.00007a40@huawei.com> (raw)
In-Reply-To: <20250909-b4-ddrperfm-upstream-v6-13-ce082cc801b5@gmail.com>
On Tue, 09 Sep 2025 12:12:20 +0200
Clément Le Goffic <legoffic.clement@gmail.com> wrote:
> From: Clément Le Goffic <clement.legoffic@foss.st.com>
>
> Introduce the driver for the DDR Performance Monitor available on
> STM32MPU SoC.
>
> On STM32MP2 platforms, the DDRPERFM allows to monitor up to 8 DDR events
> that come from the DDR Controller such as read or write events.
>
> On STM32MP1 platforms, the DDRPERFM cannot monitor any event on any
> counter, there is a notion of set of events.
> Events from different sets cannot be monitored at the same time.
> The first chosen event selects the set.
> The set is coded in the first two bytes of the config value which is on 4
> bytes.
>
> On STM32MP25x series, the DDRPERFM clock is shared with the DDR controller
> and may be secured by bootloaders.
> Access controllers allow to check access to a resource. Use the access
> controller defined in the devicetree to know about the access to the
> DDRPERFM clock.
>
> Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
> Signed-off-by: Clément Le Goffic <legoffic.clement@gmail.com>
Hi Clément
A quick drive by review,
J
> diff --git a/drivers/perf/stm32_ddr_pmu.c b/drivers/perf/stm32_ddr_pmu.c
> new file mode 100644
> index 000000000000..38328663d2c5
> --- /dev/null
> +++ b/drivers/perf/stm32_ddr_pmu.c
> @@ -0,0 +1,897 @@
> +
> +#define MP1_CLR_CNT GENMASK(3, 0)
> +#define MP1_CLR_TIME BIT(31)
> +#define MP2_CLR_CNT GENMASK(7, 0)
> +#define MP2_CLR_TIME BIT(8)
> +
> +/* 4 event counters plus 1 dedicated to time */
> +#define MP1_CNT_NB (4 + 1)
This is never used so I would drop it and rename the MP2_CNT_NB
to indicate it is the max value for any devices supported.
> +/* Index of the time dedicated counter */
> +#define MP1_TIME_CNT_IDX 4
> +
> +/* 8 event counters plus 1 dedicated to time */
> +#define MP2_CNT_NB (8 + 1)
...
> +struct stm32_ddr_pmu {
> + struct pmu pmu;
> + void __iomem *membase;
> + struct device *dev;
> + struct clk *clk;
> + const struct stm32_ddr_pmu_cfg *cfg;
> + struct hrtimer hrtimer;
> + ktime_t poll_period;
> + int selected_set;
> + u32 dram_type;
> + struct list_head counters[];
The absence of a __counted_by() marking made me wonder how
we ensured that this wasn't overrun. I see below that's because
size is always the same. So
struct list_head counters[MP2_CNT_NB];
If you do want to make it dynamic then that is fine but added
a local variable for the size and the __counted_by() marking so
the various analysis tools can check for buffer overruns.
> +};
> +static void stm32_ddr_pmu_event_del(struct perf_event *event, int flags)
> +{
> + struct stm32_ddr_pmu *pmu = to_stm32_ddr_pmu(event->pmu);
> + struct stm32_ddr_cnt *counter = event->pmu_private;
> + bool events = true;
Always set before use, so don't set it here. I'd move this into the
scope of the for loop to make this more obvious.
> +
> + stm32_ddr_pmu_event_stop(event, PERF_EF_UPDATE);
> +
> + stm32_ddr_pmu_free_counter(pmu, counter);
> +
> + for (int i = 0; i < pmu->cfg->counters_nb; i++) {
> + events = !list_empty(&pmu->counters[i]);
> + if (events) /* If there is activity nothing to do */
> + return;
> + }
> +
> + hrtimer_cancel(&pmu->hrtimer);
> + stm32_ddr_stop_counters(pmu);
> +
> + pmu->selected_set = -1;
> +
> + clk_disable(pmu->clk);
> +}
> +
> +#define STM32_DDR_PMU_EVENT_ATTR(_name, _id) \
> + PMU_EVENT_ATTR_ID(_name, stm32_ddr_pmu_sysfs_show, _id)
> +
> +static struct attribute *stm32_ddr_pmu_events_attrs_mp[] = {
> + STM32_DDR_PMU_EVENT_ATTR(perf_op_is_rd, PERF_OP_IS_RD),
Prefixing perf events with perf_ seems unnecessary.
I guess perf_op_is_rd is counting all reads? Is so why not call it simply 'reads'
or something else short like that? If it's cycles when a read is going on then
maybe a more complex is needed, but perf_op_is_rd doesn't convey that to me.
> + STM32_DDR_PMU_EVENT_ATTR(perf_op_is_wr, PERF_OP_IS_WR),
> + STM32_DDR_PMU_EVENT_ATTR(perf_op_is_activate, PERF_OP_IS_ACTIVATE),
> + STM32_DDR_PMU_EVENT_ATTR(ctl_idle, CTL_IDLE),
> + STM32_DDR_PMU_EVENT_ATTR(perf_hpr_req_with_no_credit, PERF_HPR_REQ_WITH_NO_CREDIT),
> + STM32_DDR_PMU_EVENT_ATTR(perf_lpr_req_with_no_credit, PERF_LPR_REQ_WITH_NO_CREDIT),
> + STM32_DDR_PMU_EVENT_ATTR(cactive_ddrc, CACTIVE_DDRC),
> + STM32_DDR_PMU_EVENT_ATTR(perf_op_is_enter_powerdown, PERF_OP_IS_ENTER_POWERDOWN),
> + STM32_DDR_PMU_EVENT_ATTR(perf_op_is_refresh, PERF_OP_IS_REFRESH),
> + STM32_DDR_PMU_EVENT_ATTR(perf_selfresh_mode, PERF_SELFRESH_MODE),
> + STM32_DDR_PMU_EVENT_ATTR(dfi_lp_req, DFI_LP_REQ),
> + STM32_DDR_PMU_EVENT_ATTR(perf_hpr_xact_when_critical, PERF_HPR_XACT_WHEN_CRITICAL),
> + STM32_DDR_PMU_EVENT_ATTR(perf_lpr_xact_when_critical, PERF_LPR_XACT_WHEN_CRITICAL),
> + STM32_DDR_PMU_EVENT_ATTR(perf_wr_xact_when_critical, PERF_WR_XACT_WHEN_CRITICAL),
> + STM32_DDR_PMU_EVENT_ATTR(dfi_lp_req_cpy, DFI_LP_REQ), /* Suffixed '_cpy' to allow the
> + * choice between sets 2 and 3
> + */
> + STM32_DDR_PMU_EVENT_ATTR(time_cnt, TIME_CNT),
> + NULL
> +};
> +static int stm32_ddr_pmu_device_probe(struct platform_device *pdev)
> +{
> + struct stm32_firewall firewall;
> + struct stm32_ddr_pmu *pmu;
> + struct reset_control *rst;
> + struct resource *res;
> + int ret;
> +
> + pmu = devm_kzalloc(&pdev->dev, struct_size(pmu, counters, MP2_CNT_NB), GFP_KERNEL);
If using a fixed number of counters why not put it in the struct
definition and simplify the code? I agree it is probably not
worth making this dynamic given small sizes but I don't mind
if you do want to do this. The only thing that isn't a good idea
is this dynamic, but not really, current situation.
> + if (!pmu)
> + return -ENOMEM;
> +static DEFINE_SIMPLE_DEV_PM_OPS(stm32_ddr_pmu_pm_ops, NULL, stm32_ddr_pmu_device_resume);
> +
> +static const struct of_device_id stm32_ddr_pmu_of_match[] = {
> + {
> + .compatible = "st,stm32mp131-ddr-pmu",
> + .data = &stm32_ddr_pmu_cfg_mp1
Trivial but if you are spinning again, normal convention is trailing commas
in cases like this because maybe other fields will get set later.
> + },
> + {
> + .compatible = "st,stm32mp251-ddr-pmu",
> + .data = &stm32_ddr_pmu_cfg_mp2
> + },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, stm32_ddr_pmu_of_match);
> +
> +static struct platform_driver stm32_ddr_pmu_driver = {
> + .driver = {
> + .name = DRIVER_NAME,
> + .pm = pm_sleep_ptr(&stm32_ddr_pmu_pm_ops),
> + .of_match_table = stm32_ddr_pmu_of_match,
> + },
> + .probe = stm32_ddr_pmu_device_probe,
> + .remove = stm32_ddr_pmu_device_remove,
> +};
> +
> +module_platform_driver(stm32_ddr_pmu_driver);
> +
> +MODULE_AUTHOR("Clément Le Goffic");
> +MODULE_DESCRIPTION("STMicroelectronics STM32 DDR performance monitor driver");
> +MODULE_LICENSE("GPL");
>
next prev parent reply other threads:[~2025-09-10 9:26 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-09 10:12 [PATCH v6 00/20] Introduce STM32 DDR PMU for STM32MP platforms Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 01/20] bus: firewall: move stm32_firewall header file in include folder Clément Le Goffic
2025-09-09 12:25 ` Gatien CHEVALLIER
2025-09-10 7:47 ` Clément Le Goffic
2025-09-10 8:42 ` Gatien CHEVALLIER
2025-09-10 9:43 ` Clément Le Goffic
2025-09-10 9:52 ` Gatien CHEVALLIER
2025-09-09 10:12 ` [PATCH v6 02/20] dt-bindings: stm32: stm32mp25: add `#access-controller-cells` property Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 03/20] clk: stm32mp25: add firewall grant_access ops Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 04/20] arm64: dts: st: set rcc as an access-controller Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 05/20] dt-bindings: memory: factorise LPDDR props into SDRAM props Clément Le Goffic
2025-09-10 7:54 ` Krzysztof Kozlowski
2025-09-10 8:31 ` Clément Le Goffic
2025-09-10 8:41 ` Clément Le Goffic
2025-09-10 8:52 ` Krzysztof Kozlowski
2025-09-09 10:12 ` [PATCH v6 06/20] dt-bindings: memory: introduce DDR4 Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 07/20] dt-bindings: memory: factorise LPDDR channel binding into SDRAM channel Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 08/20] dt-binding: memory: add DDR4 channel compatible Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 09/20] dt-bindings: memory: SDRAM channel: standardise node name Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 10/20] arm64: dts: st: add LPDDR channel to stm32mp257f-dk board Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 11/20] arm64: dts: st: add DDR channel to stm32mp257f-ev1 board Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 12/20] dt-bindings: perf: stm32: introduce DDRPERFM dt-bindings Clément Le Goffic
2025-09-10 7:57 ` Krzysztof Kozlowski
2025-09-10 8:33 ` Clément Le Goffic
2025-09-10 7:57 ` Krzysztof Kozlowski
2025-09-10 8:34 ` Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 13/20] perf: stm32: introduce DDRPERFM driver Clément Le Goffic
2025-09-10 9:26 ` Jonathan Cameron [this message]
2025-09-11 9:56 ` Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 14/20] Documentation: perf: stm32: add ddrperfm support Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 15/20] MAINTAINERS: add myself as STM32 DDR PMU maintainer Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 16/20] ARM: dts: stm32: add ddrperfm on stm32mp131 Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 17/20] ARM: dts: stm32: add ddrperfm on stm32mp151 Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 18/20] arm64: dts: st: add ddrperfm on stm32mp251 Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 19/20] arm64: dts: st: support ddrperfm on stm32mp257f-dk Clément Le Goffic
2025-09-09 10:12 ` [PATCH v6 20/20] arm64: dts: st: support ddrperfm on stm32mp257f-ev1 Clément Le Goffic
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250910102627.00007a40@huawei.com \
--to=jonathan.cameron@huawei.com \
--cc=alexandre.torgue@foss.st.com \
--cc=clement.legoffic@foss.st.com \
--cc=conor+dt@kernel.org \
--cc=corbet@lwn.net \
--cc=devicetree@vger.kernel.org \
--cc=gabriel.fernandez@foss.st.com \
--cc=gatien.chevallier@foss.st.com \
--cc=jwerner@chromium.org \
--cc=krzk+dt@kernel.org \
--cc=krzk@kernel.org \
--cc=legoffic.clement@gmail.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-clk@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=linux-stm32@st-md-mailman.stormreply.com \
--cc=mark.rutland@arm.com \
--cc=mcoquelin.stm32@gmail.com \
--cc=mturquette@baylibre.com \
--cc=p.zabel@pengutronix.de \
--cc=robh@kernel.org \
--cc=sboyd@kernel.org \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).