* [bug report] memory: tegra210: Support interconnect framework
@ 2025-11-21 9:32 Dan Carpenter
0 siblings, 0 replies; only message in thread
From: Dan Carpenter @ 2025-11-21 9:32 UTC (permalink / raw)
To: Aaron Kling; +Cc: linux-tegra
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
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2025-11-21 9:33 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-21 9:32 [bug report] memory: tegra210: Support interconnect framework Dan Carpenter
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.