Linux Tegra architecture development
 help / color / mirror / Atom feed
* [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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox