From: Dan Carpenter <dan.carpenter@linaro.org>
To: Aaron Kling <webgeek1234@gmail.com>
Cc: linux-tegra@vger.kernel.org
Subject: [bug report] memory: tegra210: Support interconnect framework
Date: Fri, 21 Nov 2025 12:32:55 +0300 [thread overview]
Message-ID: <aSAxxzcRZduavJQT@stanley.mountain> (raw)
Hello Aaron Kling,
Commit b33c93babead ("memory: tegra210: Support interconnect
framework") from Oct 27, 2025 (linux-next), leads to the following
Smatch static checker warning:
drivers/memory/tegra/tegra210-emc-core.c:2230 tegra210_emc_probe()
warn: missing unwind goto?
drivers/memory/tegra/tegra210-emc-core.c
2070 static int tegra210_emc_probe(struct platform_device *pdev)
2071 {
2072 struct thermal_cooling_device *cd;
2073 unsigned long current_rate;
2074 struct tegra210_emc *emc;
2075 struct device_node *np;
2076 unsigned int i;
2077 int err;
2078
2079 emc = devm_kzalloc(&pdev->dev, sizeof(*emc), GFP_KERNEL);
2080 if (!emc)
2081 return -ENOMEM;
2082
2083 emc->clk = devm_clk_get(&pdev->dev, "emc");
2084 if (IS_ERR(emc->clk))
2085 return PTR_ERR(emc->clk);
2086
2087 platform_set_drvdata(pdev, emc);
2088 spin_lock_init(&emc->lock);
2089 emc->dev = &pdev->dev;
2090
2091 emc->mc = devm_tegra_memory_controller_get(&pdev->dev);
2092 if (IS_ERR(emc->mc))
2093 return PTR_ERR(emc->mc);
2094
2095 emc->regs = devm_platform_ioremap_resource(pdev, 0);
2096 if (IS_ERR(emc->regs))
2097 return PTR_ERR(emc->regs);
2098
2099 for (i = 0; i < 2; i++) {
2100 emc->channel[i] = devm_platform_ioremap_resource(pdev, 1 + i);
2101 if (IS_ERR(emc->channel[i]))
2102 return PTR_ERR(emc->channel[i]);
2103
2104 }
2105
2106 tegra210_emc_detect(emc);
2107 np = pdev->dev.of_node;
2108
2109 /* attach to the nominal and (optional) derated tables */
2110 err = of_reserved_mem_device_init_by_name(emc->dev, np, "nominal");
2111 if (err < 0) {
2112 dev_err(emc->dev, "failed to get nominal EMC table: %d\n", err);
2113 return err;
2114 }
2115
2116 err = of_reserved_mem_device_init_by_name(emc->dev, np, "derated");
2117 if (err < 0 && err != -ENODEV) {
2118 dev_err(emc->dev, "failed to get derated EMC table: %d\n", err);
2119 goto release;
2120 }
2121
2122 /* validate the tables */
2123 if (emc->nominal) {
2124 err = tegra210_emc_validate_timings(emc, emc->nominal,
2125 emc->num_timings);
2126 if (err < 0)
2127 goto release;
2128 }
2129
2130 if (emc->derated) {
2131 err = tegra210_emc_validate_timings(emc, emc->derated,
2132 emc->num_timings);
2133 if (err < 0)
2134 goto release;
2135 }
2136
2137 /* default to the nominal table */
2138 emc->timings = emc->nominal;
2139
2140 /* pick the current timing based on the current EMC clock rate */
2141 current_rate = clk_get_rate(emc->clk) / 1000;
2142
2143 for (i = 0; i < emc->num_timings; i++) {
2144 if (emc->timings[i].rate == current_rate) {
2145 emc->last = &emc->timings[i];
2146 break;
2147 }
2148 }
2149
2150 if (i == emc->num_timings) {
2151 dev_err(emc->dev, "no EMC table entry found for %lu kHz\n",
2152 current_rate);
2153 err = -ENOENT;
2154 goto release;
2155 }
2156
2157 /* pick a compatible clock change sequence for the EMC table */
2158 for (i = 0; i < ARRAY_SIZE(tegra210_emc_sequences); i++) {
2159 const struct tegra210_emc_sequence *sequence =
2160 tegra210_emc_sequences[i];
2161
2162 if (emc->timings[0].revision == sequence->revision) {
2163 emc->sequence = sequence;
2164 break;
2165 }
2166 }
2167
2168 if (!emc->sequence) {
2169 dev_err(&pdev->dev, "sequence %u not supported\n",
2170 emc->timings[0].revision);
2171 err = -ENOTSUPP;
2172 goto release;
2173 }
2174
2175 emc->offsets = &tegra210_emc_table_register_offsets;
2176 emc->refresh = TEGRA210_EMC_REFRESH_NOMINAL;
2177
2178 emc->provider.owner = THIS_MODULE;
2179 emc->provider.dev = &pdev->dev;
2180 emc->provider.set_rate = tegra210_emc_set_rate;
2181
2182 emc->provider.configs = devm_kcalloc(&pdev->dev, emc->num_timings,
2183 sizeof(*emc->provider.configs),
2184 GFP_KERNEL);
2185 if (!emc->provider.configs) {
2186 err = -ENOMEM;
2187 goto release;
2188 }
2189
2190 emc->provider.num_configs = emc->num_timings;
2191
2192 for (i = 0; i < emc->provider.num_configs; i++) {
2193 struct tegra210_emc_timing *timing = &emc->timings[i];
2194 struct tegra210_clk_emc_config *config =
2195 &emc->provider.configs[i];
2196 u32 value;
2197
2198 config->rate = timing->rate * 1000UL;
2199 config->value = timing->clk_src_emc;
2200
2201 value = timing->burst_mc_regs[MC_EMEM_ARB_MISC0_INDEX];
2202
2203 if ((value & MC_EMEM_ARB_MISC0_EMC_SAME_FREQ) == 0)
2204 config->same_freq = false;
2205 else
2206 config->same_freq = true;
2207 }
2208
2209 err = tegra210_clk_emc_attach(emc->clk, &emc->provider);
2210 if (err < 0) {
2211 dev_err(&pdev->dev, "failed to attach to EMC clock: %d\n", err);
2212 goto release;
2213 }
2214
2215 emc->clkchange_delay = 100;
2216 emc->training_interval = 100;
2217 dev_set_drvdata(emc->dev, emc);
2218
2219 timer_setup(&emc->refresh_timer, tegra210_emc_poll_refresh,
2220 TIMER_DEFERRABLE);
2221 atomic_set(&emc->refresh_poll, 0);
2222 emc->refresh_poll_interval = 1000;
2223
2224 timer_setup(&emc->training, tegra210_emc_train, 0);
2225
2226 tegra210_emc_debugfs_init(emc);
2227
2228 err = tegra210_emc_opp_table_init(emc);
2229 if (!err) {
2230 tegra210_emc_rate_requests_init(emc);
2231 tegra210_emc_interconnect_init(emc);
2232 } else if (err != -ENODEV) {
2233 return err;
This should be goto detach. The other issue is that
tegra210_emc_opp_table_init() needs to be cleaned up as well.
void tegra210_emc_opp_table_cleanup()
{
dev_pm_opp_of_remove_table(emc->dev);
dev_pm_opp_put_supported_hw(opp_token);
}
2234 }
2235
2236 cd = devm_thermal_of_cooling_device_register(emc->dev, np, "emc", emc,
2237 &tegra210_emc_cd_ops);
2238 if (IS_ERR(cd)) {
2239 err = PTR_ERR(cd);
2240 dev_err(emc->dev, "failed to register cooling device: %d\n",
2241 err);
2242 goto detach;
goto cleanup_table;
2243 }
2244
2245 return 0;
2246
cleanup_table:
tegra210_emc_opp_table_cleanup();
2247 detach:
2248 debugfs_remove_recursive(emc->debugfs.root);
2249 tegra210_clk_emc_detach(emc->clk);
2250 release:
2251 of_reserved_mem_device_release(emc->dev);
2252
2253 return err;
2254 }
2255
2256 static void tegra210_emc_remove(struct platform_device *pdev)
2257 {
2258 struct tegra210_emc *emc = platform_get_drvdata(pdev);
2259
Same here:
tegra210_emc_opp_table_cleanup();
2260 debugfs_remove_recursive(emc->debugfs.root);
2261 tegra210_clk_emc_detach(emc->clk);
2262 of_reserved_mem_device_release(emc->dev);
2263 }
regards,
dan carpenter
reply other threads:[~2025-11-21 9:33 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=aSAxxzcRZduavJQT@stanley.mountain \
--to=dan.carpenter@linaro.org \
--cc=linux-tegra@vger.kernel.org \
--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