mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-03 18:20:25 +02:00 
			
		
		
		
	stmmac: dwmac-intel-plat: fix call balance of tx_clk handling routines
If the clock dwmac->tx_clk was not enabled in intel_eth_plat_probe,
it should not be disabled in any path.
Conversely, if it was enabled in intel_eth_plat_probe, it must be disabled
in all error paths to ensure proper cleanup.
Found by Linux Verification Center (linuxtesting.org) with Klever.
Fixes: 9efc9b2b04 ("net: stmmac: Add dwmac-intel-plat for GBE driver")
Signed-off-by: Vitalii Mordan <mordan@ispras.ru>
Link: https://patch.msgid.link/20241108173334.2973603-1-mordan@ispras.ru
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
			
			
This commit is contained in:
		
							parent
							
								
									eb94b7bb10
								
							
						
					
					
						commit
						5b366eae71
					
				
					 1 changed files with 17 additions and 8 deletions
				
			
		| 
						 | 
					@ -108,7 +108,12 @@ static int intel_eth_plat_probe(struct platform_device *pdev)
 | 
				
			||||||
			if (IS_ERR(dwmac->tx_clk))
 | 
								if (IS_ERR(dwmac->tx_clk))
 | 
				
			||||||
				return PTR_ERR(dwmac->tx_clk);
 | 
									return PTR_ERR(dwmac->tx_clk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			clk_prepare_enable(dwmac->tx_clk);
 | 
								ret = clk_prepare_enable(dwmac->tx_clk);
 | 
				
			||||||
 | 
								if (ret) {
 | 
				
			||||||
 | 
									dev_err(&pdev->dev,
 | 
				
			||||||
 | 
										"Failed to enable tx_clk\n");
 | 
				
			||||||
 | 
									return ret;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/* Check and configure TX clock rate */
 | 
								/* Check and configure TX clock rate */
 | 
				
			||||||
			rate = clk_get_rate(dwmac->tx_clk);
 | 
								rate = clk_get_rate(dwmac->tx_clk);
 | 
				
			||||||
| 
						 | 
					@ -119,7 +124,7 @@ static int intel_eth_plat_probe(struct platform_device *pdev)
 | 
				
			||||||
				if (ret) {
 | 
									if (ret) {
 | 
				
			||||||
					dev_err(&pdev->dev,
 | 
										dev_err(&pdev->dev,
 | 
				
			||||||
						"Failed to set tx_clk\n");
 | 
											"Failed to set tx_clk\n");
 | 
				
			||||||
					return ret;
 | 
										goto err_tx_clk_disable;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -133,7 +138,7 @@ static int intel_eth_plat_probe(struct platform_device *pdev)
 | 
				
			||||||
			if (ret) {
 | 
								if (ret) {
 | 
				
			||||||
				dev_err(&pdev->dev,
 | 
									dev_err(&pdev->dev,
 | 
				
			||||||
					"Failed to set clk_ptp_ref\n");
 | 
										"Failed to set clk_ptp_ref\n");
 | 
				
			||||||
				return ret;
 | 
									goto err_tx_clk_disable;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -149,12 +154,15 @@ static int intel_eth_plat_probe(struct platform_device *pdev)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
 | 
						ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
 | 
				
			||||||
	if (ret) {
 | 
						if (ret)
 | 
				
			||||||
		clk_disable_unprepare(dwmac->tx_clk);
 | 
							goto err_tx_clk_disable;
 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err_tx_clk_disable:
 | 
				
			||||||
 | 
						if (dwmac->data->tx_clk_en)
 | 
				
			||||||
 | 
							clk_disable_unprepare(dwmac->tx_clk);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void intel_eth_plat_remove(struct platform_device *pdev)
 | 
					static void intel_eth_plat_remove(struct platform_device *pdev)
 | 
				
			||||||
| 
						 | 
					@ -162,7 +170,8 @@ static void intel_eth_plat_remove(struct platform_device *pdev)
 | 
				
			||||||
	struct intel_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev);
 | 
						struct intel_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	stmmac_pltfr_remove(pdev);
 | 
						stmmac_pltfr_remove(pdev);
 | 
				
			||||||
	clk_disable_unprepare(dwmac->tx_clk);
 | 
						if (dwmac->data->tx_clk_en)
 | 
				
			||||||
 | 
							clk_disable_unprepare(dwmac->tx_clk);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct platform_driver intel_eth_plat_driver = {
 | 
					static struct platform_driver intel_eth_plat_driver = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue