forked from mirrors/linux
		
	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
	
	 Vitalii Mordan
						Vitalii Mordan