From: Krzysztof Kozlowski <krzk@kernel.org>
To: webgeek1234@gmail.com, Rob Herring <robh@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Thierry Reding <thierry.reding@gmail.com>,
Jonathan Hunter <jonathanh@nvidia.com>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
MyungJoo Ham <myungjoo.ham@samsung.com>,
Kyungmin Park <kyungmin.park@samsung.com>,
Chanwoo Choi <cw00.choi@samsung.com>,
Dmitry Osipenko <digetx@gmail.com>
Cc: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
linux-tegra@vger.kernel.org, linux-pm@vger.kernel.org
Subject: Re: [PATCH v3 5/9] memory: tegra210: Support interconnect framework
Date: Wed, 10 Sep 2025 11:39:41 +0200 [thread overview]
Message-ID: <29ec10fa-1ca4-43eb-a865-7219d39c7140@kernel.org> (raw)
In-Reply-To: <20250906-t210-actmon-v3-5-1403365d571e@gmail.com>
On 06/09/2025 22:16, Aaron Kling via B4 Relay wrote:
> +
> +static int tegra_emc_interconnect_init(struct tegra210_emc *emc)
> +{
> + const struct tegra_mc_soc *soc = emc->mc->soc;
> + struct icc_node *node;
> + int err;
> +
> + emc->icc_provider.dev = emc->dev;
> + emc->icc_provider.set = emc_icc_set;
> + emc->icc_provider.data = &emc->icc_provider;
> + emc->icc_provider.aggregate = soc->icc_ops->aggregate;
> + emc->icc_provider.xlate_extended = emc_of_icc_xlate_extended;
> + emc->icc_provider.get_bw = tegra_emc_icc_get_init_bw;
> +
> + icc_provider_init(&emc->icc_provider);
> +
> + /* create External Memory Controller node */
> + node = icc_node_create(TEGRA_ICC_EMC);
> + if (IS_ERR(node)) {
> + err = PTR_ERR(node);
> + goto err_msg;
return dev_err_probe
> + }
> +
> + node->name = "External Memory Controller";
> + icc_node_add(node, &emc->icc_provider);
> +
> + /* link External Memory Controller to External Memory (DRAM) */
> + err = icc_link_create(node, TEGRA_ICC_EMEM);
> + if (err)
> + goto remove_nodes;
> +
> + /* create External Memory node */
> + node = icc_node_create(TEGRA_ICC_EMEM);
> + if (IS_ERR(node)) {
> + err = PTR_ERR(node);
> + goto remove_nodes;
> + }
> +
> + node->name = "External Memory (DRAM)";
> + icc_node_add(node, &emc->icc_provider);
> +
> + err = icc_provider_register(&emc->icc_provider);
> + if (err)
> + goto remove_nodes;
> +
> + return 0;
> +
> +remove_nodes:
> + icc_nodes_remove(&emc->icc_provider);
> +err_msg:
> + dev_err(emc->dev, "failed to initialize ICC: %d\n", err);
Write descriptive error messages or skip it. It's printing errors also
on ENOMEM.
I will send a patch to fix existing code.
> +
> + return err;
> +}
> +
> +static int tegra_emc_opp_table_init(struct tegra210_emc *emc)
> +{
> + u32 hw_version = BIT(tegra_sku_info.soc_speedo_id);
> + struct dev_pm_opp *opp;
> + unsigned long rate;
> + int opp_token, err, max_opps, i;
> +
> + err = dev_pm_opp_set_supported_hw(emc->dev, &hw_version, 1);
> + if (err < 0) {
> + dev_err(emc->dev, "failed to set OPP supported HW: %d\n", err);
> + return err;
return dev_err_probe
> + }
> + opp_token = err;
> +
> + err = dev_pm_opp_of_add_table(emc->dev);
> + if (err) {
> + if (err == -ENODEV)
> + dev_warn(emc->dev, "OPP table not found, please update your device tree\n");
> + else
> + dev_err(emc->dev, "failed to add OPP table: %d\n", err);
> +
> + goto put_hw_table;
> + }
> +
> + max_opps = dev_pm_opp_get_opp_count(emc->dev);
> + if (max_opps <= 0) {
> + dev_err(emc->dev, "Failed to add OPPs\n");
> + goto remove_table;
> + }
> +
> + if (emc->num_timings != max_opps) {
> + dev_err(emc->dev, "OPP table does not match emc table\n");
> + goto remove_table;
> + }
> +
> + for (i = 0; i < emc->num_timings; i++) {
> + rate = emc->timings[i].rate * 1000;
> + opp = dev_pm_opp_find_freq_exact(emc->dev, rate, true);
> + if (IS_ERR(opp)) {
> + dev_err(emc->dev, "Rate %lu not found in OPP table\n", rate);
> + goto remove_table;
> + }
> +
> + dev_pm_opp_put(opp);
> + }
> +
> + dev_info_once(emc->dev, "OPP HW ver. 0x%x, current clock rate %lu MHz\n",
> + hw_version, clk_get_rate(emc->clk) / 1000000);
> +
> + return 0;
> +
> +remove_table:
> + dev_pm_opp_of_remove_table(emc->dev);
> +put_hw_table:
> + dev_pm_opp_put_supported_hw(opp_token);
> +
> + return err;
> +}
> +
...
> diff --git a/drivers/memory/tegra/tegra210.c b/drivers/memory/tegra/tegra210.c
> index cfa61dd885577a8fbd79c396a1316101197ca1f2..20828a07d2d0cafa739b534c20c12f065b276669 100644
> --- a/drivers/memory/tegra/tegra210.c
> +++ b/drivers/memory/tegra/tegra210.c
> @@ -3,6 +3,9 @@
> * Copyright (C) 2015 NVIDIA CORPORATION. All rights reserved.
> */
>
> +#include <linux/of.h>
> +#include <linux/device.h>
> +
> #include <dt-bindings/memory/tegra210-mc.h>
>
> #include "mc.h"
> @@ -1273,6 +1276,83 @@ static const struct tegra_mc_reset tegra210_mc_resets[] = {
> TEGRA210_MC_RESET(TSECB, 0x970, 0x974, 13),
> };
>
> +static int tegra210_mc_icc_set(struct icc_node *src, struct icc_node *dst)
> +{
> + /* TODO: program PTSA */
> + return 0;
> +}
> +
> +static int tegra210_mc_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
> + u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
> +{
> + /*
> + * ISO clients need to reserve extra bandwidth up-front because
> + * there could be high bandwidth pressure during initial filling
> + * of the client's FIFO buffers. Secondly, we need to take into
> + * account impurities of the memory subsystem.
> + */
> + if (tag & TEGRA_MC_ICC_TAG_ISO)
> + peak_bw = tegra_mc_scale_percents(peak_bw, 400);
> +
> + *agg_avg += avg_bw;
> + *agg_peak = max(*agg_peak, peak_bw);
> +
> + return 0;
> +}
> +
> +static struct icc_node_data *
> +tegra210_mc_of_icc_xlate_extended(const struct of_phandle_args *spec, void *data)
> +{
> + struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
> + const struct tegra_mc_client *client;
> + unsigned int i, idx = spec->args[0];
> + struct icc_node_data *ndata;
> + struct icc_node *node;
> +
> + list_for_each_entry(node, &mc->provider.nodes, node_list) {
> + if (node->id != idx)
> + continue;
> +
> + ndata = kzalloc(sizeof(*ndata), GFP_KERNEL);
> + if (!ndata)
> + return ERR_PTR(-ENOMEM);
> +
> + client = &mc->soc->clients[idx];
> + ndata->node = node;
> +
> + switch (client->swgroup) {
> + case TEGRA_SWGROUP_DC:
> + case TEGRA_SWGROUP_DCB:
> + case TEGRA_SWGROUP_PTC:
> + case TEGRA_SWGROUP_VI:
> + /* these clients are isochronous by default */
> + ndata->tag = TEGRA_MC_ICC_TAG_ISO;
> + break;
> +
> + default:
> + ndata->tag = TEGRA_MC_ICC_TAG_DEFAULT;
> + break;
> + }
> +
> + return ndata;
> + }
> +
> + for (i = 0; i < mc->soc->num_clients; i++) {
> + if (mc->soc->clients[i].id == idx)
> + return ERR_PTR(-EPROBE_DEFER);
This feels like more reasonable use of deferred probe, but I wonder how
is this condition possible.
This xlate is called at earliest after MC ICC is registered. At this
tage all nodes are created, so previous list_for_each_entry() should
succeed and return. If previous list_for_each_entry() did not return,
how can you find a matching client for which the node will be added
later, thus deferred probe?
This is again existing code, of course :)
Best regards,
Krzysztof
next prev parent reply other threads:[~2025-09-10 9:39 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-06 20:16 [PATCH v3 0/9] Support Tegra210 actmon for dynamic EMC scaling Aaron Kling via B4 Relay
2025-09-06 20:16 ` [PATCH v3 1/9] dt-bindings: devfreq: tegra30-actmon: Add Tegra124 fallback for Tegra210 Aaron Kling via B4 Relay
2025-09-06 20:16 ` [PATCH v3 2/9] dt-bindings: memory: tegra210: emc: Document OPP table and interconnect Aaron Kling via B4 Relay
2025-09-10 9:41 ` (subset) " Krzysztof Kozlowski
2025-09-06 20:16 ` [PATCH v3 3/9] dt-bindings: memory: tegra210: Add memory client IDs Aaron Kling via B4 Relay
2025-09-10 9:41 ` (subset) " Krzysztof Kozlowski
2025-09-06 20:16 ` [PATCH v3 4/9] memory: tegra210: Use bindings for client ids Aaron Kling via B4 Relay
2025-09-10 9:41 ` (subset) " Krzysztof Kozlowski
2025-09-06 20:16 ` [PATCH v3 5/9] memory: tegra210: Support interconnect framework Aaron Kling via B4 Relay
2025-09-10 9:39 ` Krzysztof Kozlowski [this message]
2025-09-10 10:06 ` Krzysztof Kozlowski
2025-09-15 6:08 ` Aaron Kling
2025-09-15 7:24 ` Krzysztof Kozlowski
2025-09-06 20:16 ` [PATCH v3 6/9] soc: tegra: fuse: speedo-tegra210: Add soc speedo 2 Aaron Kling via B4 Relay
2025-09-06 20:16 ` [PATCH v3 7/9] arm64: tegra: tegra210: Add actmon Aaron Kling via B4 Relay
2025-09-06 20:16 ` [PATCH v3 8/9] arm64: tegra: Add interconnect properties to Tegra210 device-tree Aaron Kling via B4 Relay
2025-09-06 20:16 ` [PATCH v3 9/9] arm64: tegra: Add OPP tables on Tegra210 Aaron Kling via B4 Relay
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=29ec10fa-1ca4-43eb-a865-7219d39c7140@kernel.org \
--to=krzk@kernel.org \
--cc=conor+dt@kernel.org \
--cc=cw00.choi@samsung.com \
--cc=devicetree@vger.kernel.org \
--cc=digetx@gmail.com \
--cc=jonathanh@nvidia.com \
--cc=krzk+dt@kernel.org \
--cc=kyungmin.park@samsung.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=linux-tegra@vger.kernel.org \
--cc=myungjoo.ham@samsung.com \
--cc=robh@kernel.org \
--cc=thierry.reding@gmail.com \
--cc=webgeek1234@gmail.com \
/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).