Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

soc: aspeed: lpc-snoop: Consolidate channel initialisation

Previously, channel initialisation was a bit perilous with respect to
resource cleanup in error paths. While the implementation had issues,
it at least made an effort to eliminate some of its problems by first
testing whether any channels were enabled, and bailing out if not.

Having improved the robustness of resource handling in probe() we can
now rearrange the initial channel test to be located with the subsequent
test, and rework the unrolled conditional logic to use a loop for an
improvement in readability.

Link: https://patch.msgid.link/20250616-aspeed-lpc-snoop-fixes-v2-9-3cdd59c934d3@codeconstruct.com.au
Acked-by: Jean Delvare <jdelvare@suse.de>
Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>

+24 -27
+24 -27
drivers/soc/aspeed/aspeed-lpc-snoop.c
··· 293 293 kfifo_free(&channel->fifo); 294 294 } 295 295 296 + static void aspeed_lpc_snoop_remove(struct platform_device *pdev) 297 + { 298 + struct aspeed_lpc_snoop *lpc_snoop = dev_get_drvdata(&pdev->dev); 299 + 300 + /* Disable both snoop channels */ 301 + aspeed_lpc_disable_snoop(lpc_snoop, ASPEED_LPC_SNOOP_INDEX_0); 302 + aspeed_lpc_disable_snoop(lpc_snoop, ASPEED_LPC_SNOOP_INDEX_1); 303 + } 304 + 296 305 static int aspeed_lpc_snoop_probe(struct platform_device *pdev) 297 306 { 298 307 struct aspeed_lpc_snoop *lpc_snoop; 299 - struct device *dev; 300 308 struct device_node *np; 301 - u32 port; 309 + struct device *dev; 310 + int idx; 302 311 int rc; 303 312 304 313 dev = &pdev->dev; ··· 330 321 331 322 dev_set_drvdata(&pdev->dev, lpc_snoop); 332 323 333 - rc = of_property_read_u32_index(dev->of_node, "snoop-ports", 0, &port); 334 - if (rc) { 335 - dev_err(dev, "no snoop ports configured\n"); 336 - return -ENODEV; 337 - } 338 - 339 324 lpc_snoop->clk = devm_clk_get_enabled(dev, NULL); 340 325 if (IS_ERR(lpc_snoop->clk)) 341 326 return dev_err_probe(dev, PTR_ERR(lpc_snoop->clk), "couldn't get clock"); ··· 338 335 if (rc) 339 336 return rc; 340 337 341 - rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, ASPEED_LPC_SNOOP_INDEX_0, port); 342 - if (rc) 343 - return rc; 338 + for (idx = ASPEED_LPC_SNOOP_INDEX_0; idx <= ASPEED_LPC_SNOOP_INDEX_MAX; idx++) { 339 + u32 port; 344 340 345 - /* Configuration of 2nd snoop channel port is optional */ 346 - if (of_property_read_u32_index(dev->of_node, "snoop-ports", 347 - 1, &port) == 0) { 348 - rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, ASPEED_LPC_SNOOP_INDEX_1, port); 349 - if (rc) { 350 - aspeed_lpc_disable_snoop(lpc_snoop, ASPEED_LPC_SNOOP_INDEX_0); 351 - return rc; 352 - } 341 + rc = of_property_read_u32_index(dev->of_node, "snoop-ports", idx, &port); 342 + if (rc) 343 + break; 344 + 345 + rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, idx, port); 346 + if (rc) 347 + goto cleanup_channels; 353 348 } 354 349 355 - return 0; 356 - } 350 + return idx == ASPEED_LPC_SNOOP_INDEX_0 ? -ENODEV : 0; 357 351 358 - static void aspeed_lpc_snoop_remove(struct platform_device *pdev) 359 - { 360 - struct aspeed_lpc_snoop *lpc_snoop = dev_get_drvdata(&pdev->dev); 352 + cleanup_channels: 353 + aspeed_lpc_snoop_remove(pdev); 361 354 362 - /* Disable both snoop channels */ 363 - aspeed_lpc_disable_snoop(lpc_snoop, ASPEED_LPC_SNOOP_INDEX_0); 364 - aspeed_lpc_disable_snoop(lpc_snoop, ASPEED_LPC_SNOOP_INDEX_1); 355 + return rc; 365 356 } 366 357 367 358 static const struct aspeed_lpc_snoop_model_data ast2400_model_data = {