linux-doc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Clement LE GOFFIC <clement.legoffic@foss.st.com>
To: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Cc: Will Deacon <will@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Rob Herring <robh@kernel.org>,
	Krzysztof Kozlowski <krzk+dt@kernel.org>,
	Conor Dooley <conor+dt@kernel.org>,
	Maxime Coquelin <mcoquelin.stm32@gmail.com>,
	Alexandre Torgue <alexandre.torgue@foss.st.com>,
	Philipp Zabel <p.zabel@pengutronix.de>,
	Jonathan Corbet <corbet@lwn.net>,
	Gatien Chevallier <gatien.chevallier@foss.st.com>,
	Michael Turquette <mturquette@baylibre.com>,
	Stephen Boyd <sboyd@kernel.org>,
	Gabriel Fernandez <gabriel.fernandez@foss.st.com>,
	Krzysztof Kozlowski <krzk@kernel.org>,
	Le Goffic <legoffic.clement@gmail.com>,
	Julius Werner <jwerner@chromium.org>,
	<linux-arm-kernel@lists.infradead.org>,
	<linux-perf-users@vger.kernel.org>, <devicetree@vger.kernel.org>,
	<linux-stm32@st-md-mailman.stormreply.com>,
	<linux-kernel@vger.kernel.org>, <linux-doc@vger.kernel.org>,
	<linux-clk@vger.kernel.org>
Subject: Re: [PATCH v3 12/19] perf: stm32: introduce DDRPERFM driver
Date: Mon, 28 Jul 2025 15:12:22 +0200	[thread overview]
Message-ID: <2ceafbbe-064e-4227-8b44-edc67d22f6b4@foss.st.com> (raw)
In-Reply-To: <20250725115655.00002304@huawei.com>

Hi Jonathan

On 7/25/25 12:56, Jonathan Cameron wrote:
> On Tue, 22 Jul 2025 16:03:29 +0200
> Clément Le Goffic <clement.legoffic@foss.st.com> wrote:
> 
>> 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>
> Hi Clément,
> 
> Minor comments inline.,
> 
> Thanks,
> 
> Jonathan
> 
>> --- /dev/null
>> +++ b/drivers/perf/stm32_ddr_pmu.c
>> @@ -0,0 +1,896 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (C) 2025, STMicroelectronics - All Rights Reserved
>> + * Author: Clément Le Goffic <clement.legoffic@foss.st.com> for STMicroelectronics.
>> + */
>> +
>> +#include <linux/bus/stm32_firewall_device.h>
>> +#include <linux/clk.h>
>> +#include <linux/hrtimer.h>
>> +#include <linux/io.h>
>> +#include <linux/module.h>
>> +#include <linux/of_platform.h>
> Why?
For of_device_id and platform_device structs
> Looks like of.h is needed so you should include that directly.
> 
> Check all your headers.  mod_devicetable.h should be here
> for instance.

mod_devicetable.h is already included in of_platform.h but imagine it 
should be directly include as I do not use any symbol from of_platform.h

Thank you for pointing this out.
I'll have a look on other includes.

Do you have any method to include directly what you need ?
As of here symbols were available through other include but this is not 
correct.
Is there any tool nor tips to find the right include directly and easily ?

>> +#include <linux/perf_event.h>
>> +#include <linux/reset.h>
> 
>> +
>> +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;
>> +
>> +	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]);
> What is this trying to do?  It seems to be only setting
> 	events = !list_empty(&pmu->counters[pmu->cfg_counters_nb - 1]);
> 
> If so just check that but my guess it you care if there is anything
> in any of them lists.

Indeed the test must be in the for loop, thanks.
The idea here is to loop over the counters and check if one of them is 
still active so we don't stop the HW.

I'll do:
	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;
	}

> 
>> +
>> +	/* If there is activity nothing to do */
>> +	if (events)
>> +		return;
>> +
>> +	hrtimer_cancel(&pmu->hrtimer);
>> +	stm32_ddr_stop_counters(pmu);
>> +
>> +	pmu->selected_set = -1;
>> +
>> +	clk_disable(pmu->clk);
>> +}
> 
> 
>> +static int stm32_ddr_pmu_get_memory_type(struct stm32_ddr_pmu *pmu)
>> +{
>> +	struct platform_device *pdev = to_platform_device(pmu->dev);
>> +	struct device_node *memchan;
>> +
>> +	memchan = of_parse_phandle(pdev->dev.of_node, "memory-channel", 0);
>> +	if (!memchan)
>> +		return dev_err_probe(&pdev->dev, -EINVAL,
>> +				     "Missing device-tree property 'memory-channel'\n");
>> +
>> +	if (of_device_is_compatible(memchan, "jedec,lpddr4-channel"))
> 
> Random thought, feel free to ignore.
> I wonder if it's worth using an of_device_id match table here?
I don't think it would be worth it but if wanted I can switch.
>
>> +		pmu->dram_type = STM32_DDR_PMU_LPDDR4;
>> +	else if (of_device_is_compatible(memchan, "jedec,lpddr3-channel"))
>> +		pmu->dram_type = STM32_DDR_PMU_LPDDR3;
>> +	else if (of_device_is_compatible(memchan, "jedec,ddr4-channel"))
>> +		pmu->dram_type = STM32_DDR_PMU_DDR4;
>> +	else if (of_device_is_compatible(memchan, "jedec,ddr3-channel"))
>> +		pmu->dram_type = STM32_DDR_PMU_DDR3;
>> +	else
>> +		return dev_err_probe(&pdev->dev, -EINVAL, "Unsupported memory channel type\n");
>> +
>> +	if (pmu->dram_type == STM32_DDR_PMU_LPDDR3)
>> +		dev_warn(&pdev->dev,
>> +			 "LPDDR3 supported by DDRPERFM but not supported by DDRCTRL/DDRPHY\n");
>> +
>> +	return 0;
>> +}
> 
>> +static struct attribute *stm32_ddr_pmu_events_attrs_mp[] = {
>> +	STM32_DDR_PMU_EVENT_ATTR(perf_op_is_rd, PERF_OP_IS_RD),
>> +	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,
> 
> No trailing comma for a terminating entry like this.  You got the other cases
> so I guess this one just got missed.

Ack.

>> +};
> 
>> +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 (!pmu)
>> +		return -ENOMEM;
>> +
>> +	platform_set_drvdata(pdev, pmu);
>> +	pmu->dev = &pdev->dev;
>> +
>> +	pmu->cfg = device_get_match_data(pmu->dev);
>> +
>> +	pmu->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
>> +	if (IS_ERR(pmu->membase))
>> +		return PTR_ERR(pmu->membase);
>> +
>> +	if (of_property_present(pmu->dev->of_node, "access-controllers")) {
>> +		ret = stm32_firewall_get_firewall(pmu->dev->of_node, &firewall, 1);
> 
> Jiri is busy driving dev_fwnode() thorugh to get rid of all the directly references
> to of_node.  Probably better to use that here from the start.
> 
> 
>> +		if (ret)
>> +			return dev_err_probe(pmu->dev, ret, "Failed to get firewall\n");
>> +		ret = stm32_firewall_grant_access_by_id(&firewall, firewall.firewall_id);
>> +		if (ret)
>> +			return dev_err_probe(pmu->dev, ret, "Failed to grant access\n");
>> +	}
>> +
>> +	pmu->clk = devm_clk_get_optional_enabled(pmu->dev, NULL);
>> +	if (IS_ERR(pmu->clk))
>> +		return dev_err_probe(pmu->dev, PTR_ERR(pmu->clk), "Failed to get prepare clock\n");
> 
> Comment doesn't match code. This is going to enabled, not just prepared.
Indeed.

>> +
>> +	rst = devm_reset_control_get_optional_exclusive(pmu->dev, NULL);
>> +	if (IS_ERR(rst))
>> +		return dev_err_probe(pmu->dev, PTR_ERR(rst), "Failed to get reset\n");
> 
>> +}

Best regards,
Clément

  parent reply	other threads:[~2025-07-28 13:16 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-22 14:03 [PATCH v3 00/19] Introduce STM32 DDR PMU for STM32MP platforms Clément Le Goffic
2025-07-22 14:03 ` [PATCH v3 01/19] bus: firewall: move stm32_firewall header file in include folder Clément Le Goffic
2025-07-22 14:03 ` [PATCH v3 02/19] dt-bindings: stm32: stm32mp25: add `access-controller-cell` property Clément Le Goffic
2025-07-22 14:03 ` [PATCH v3 03/19] clk: stm32mp25: add firewall grant_access ops Clément Le Goffic
2025-07-22 14:03 ` [PATCH v3 04/19] arm64: dts: st: set rcc as an access-controller Clément Le Goffic
2025-07-22 14:03 ` [PATCH v3 05/19] dt-bindings: memory: factorise LPDDR props into memory props Clément Le Goffic
2025-07-22 21:57   ` Julius Werner
2025-07-23  7:21     ` Clement LE GOFFIC
2025-07-22 14:03 ` [PATCH v3 06/19] dt-bindings: memory: introduce DDR4 Clément Le Goffic
2025-07-22 21:57   ` Julius Werner
2025-07-23  7:30     ` Clement LE GOFFIC
2025-07-22 14:03 ` [PATCH v3 07/19] dt-bindings: memory: factorise LPDDR channel binding into memory channel Clément Le Goffic
2025-07-22 21:58   ` Julius Werner
2025-07-23  7:54     ` Clement LE GOFFIC
2025-07-23  6:57   ` Krzysztof Kozlowski
2025-07-23  7:06     ` Krzysztof Kozlowski
2025-07-23  8:14       ` Clement LE GOFFIC
2025-07-23  8:10     ` Clement LE GOFFIC
2025-07-23  8:18       ` Krzysztof Kozlowski
2025-07-23 21:16       ` Julius Werner
2025-07-22 14:03 ` [PATCH v3 08/19] dt-binding: memory: add DDR4 channel compatible Clément Le Goffic
2025-07-22 14:03 ` [PATCH v3 09/19] arm64: dts: st: add LPDDR channel to stm32mp257f-dk board Clément Le Goffic
2025-07-22 14:03 ` [PATCH v3 10/19] arm64: dts: st: add DDR channel to stm32mp257f-ev1 board Clément Le Goffic
2025-07-22 14:03 ` [PATCH v3 11/19] dt-bindings: perf: stm32: introduce DDRPERFM dt-bindings Clément Le Goffic
2025-07-22 17:01   ` Rob Herring (Arm)
2025-07-22 14:03 ` [PATCH v3 12/19] perf: stm32: introduce DDRPERFM driver Clément Le Goffic
2025-07-25 10:56   ` Jonathan Cameron
2025-07-25 10:59     ` Jonathan Cameron
2025-07-28 13:12       ` Clement LE GOFFIC
2025-07-28 13:12     ` Clement LE GOFFIC [this message]
2025-07-22 14:03 ` [PATCH v3 13/19] Documentation: perf: stm32: add ddrperfm support Clément Le Goffic
2025-07-22 14:03 ` [PATCH v3 14/19] MAINTAINERS: add myself as STM32 DDR PMU maintainer Clément Le Goffic
2025-07-22 14:03 ` [PATCH v3 15/19] ARM: dts: stm32: add ddrperfm on stm32mp131 Clément Le Goffic
2025-07-22 14:03 ` [PATCH v3 16/19] ARM: dts: stm32: add ddrperfm on stm32mp151 Clément Le Goffic
2025-07-22 14:03 ` [PATCH v3 17/19] arm64: dts: st: add ddrperfm on stm32mp251 Clément Le Goffic
2025-07-22 14:03 ` [PATCH v3 18/19] arm64: dts: st: support ddrperfm on stm32mp257f-dk Clément Le Goffic
2025-07-22 14:03 ` [PATCH v3 19/19] 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=2ceafbbe-064e-4227-8b44-edc67d22f6b4@foss.st.com \
    --to=clement.legoffic@foss.st.com \
    --cc=Jonathan.Cameron@huawei.com \
    --cc=alexandre.torgue@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).