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

Configure Feed

Select the types of activity you want to include in your feed.

net: phy: air_en8811h: Introduce resume/suspend and clk_restore_context to ensure correct CKO settings after network interface reinitialization.

If the user reinitializes the network interface, the PHY will reinitialize,
and the CKO settings will revert to their initial configuration(be enabled).
To prevent CKO from being re-enabled,
en8811h_clk_restore_context and en8811h_resume were added
to ensure the CKO settings remain correct.

Signed-off-by: Lucien.Jheng <lucienzx159@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20250630154147.80388-1-lucienzx159@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Lucien.Jheng and committed by
Jakub Kicinski
6b9c9def 10c38949

+41 -4
+41 -4
drivers/net/phy/air_en8811h.c
··· 11 11 * Copyright (C) 2023 Airoha Technology Corp. 12 12 */ 13 13 14 + #include <linux/clk.h> 14 15 #include <linux/clk-provider.h> 15 16 #include <linux/phy.h> 16 17 #include <linux/firmware.h> ··· 158 157 struct led led[EN8811H_LED_COUNT]; 159 158 struct clk_hw hw; 160 159 struct phy_device *phydev; 160 + unsigned int cko_is_enabled; 161 161 }; 162 162 163 163 enum { ··· 867 865 return (pbus_value & EN8811H_CLK_CGM_CKO); 868 866 } 869 867 868 + static int en8811h_clk_save_context(struct clk_hw *hw) 869 + { 870 + struct en8811h_priv *priv = clk_hw_to_en8811h_priv(hw); 871 + 872 + priv->cko_is_enabled = en8811h_clk_is_enabled(hw); 873 + 874 + return 0; 875 + } 876 + 877 + static void en8811h_clk_restore_context(struct clk_hw *hw) 878 + { 879 + struct en8811h_priv *priv = clk_hw_to_en8811h_priv(hw); 880 + 881 + if (!priv->cko_is_enabled) 882 + en8811h_clk_disable(hw); 883 + } 884 + 870 885 static const struct clk_ops en8811h_clk_ops = { 871 - .recalc_rate = en8811h_clk_recalc_rate, 872 - .enable = en8811h_clk_enable, 873 - .disable = en8811h_clk_disable, 874 - .is_enabled = en8811h_clk_is_enabled, 886 + .recalc_rate = en8811h_clk_recalc_rate, 887 + .enable = en8811h_clk_enable, 888 + .disable = en8811h_clk_disable, 889 + .is_enabled = en8811h_clk_is_enabled, 890 + .save_context = en8811h_clk_save_context, 891 + .restore_context = en8811h_clk_restore_context, 875 892 }; 876 893 877 894 static int en8811h_clk_provider_setup(struct device *dev, struct clk_hw *hw) ··· 1170 1149 return IRQ_HANDLED; 1171 1150 } 1172 1151 1152 + static int en8811h_resume(struct phy_device *phydev) 1153 + { 1154 + clk_restore_context(); 1155 + 1156 + return genphy_resume(phydev); 1157 + } 1158 + 1159 + static int en8811h_suspend(struct phy_device *phydev) 1160 + { 1161 + clk_save_context(); 1162 + 1163 + return genphy_suspend(phydev); 1164 + } 1165 + 1173 1166 static struct phy_driver en8811h_driver[] = { 1174 1167 { 1175 1168 PHY_ID_MATCH_MODEL(EN8811H_PHY_ID), ··· 1194 1159 .get_rate_matching = en8811h_get_rate_matching, 1195 1160 .config_aneg = en8811h_config_aneg, 1196 1161 .read_status = en8811h_read_status, 1162 + .resume = en8811h_resume, 1163 + .suspend = en8811h_suspend, 1197 1164 .config_intr = en8811h_clear_intr, 1198 1165 .handle_interrupt = en8811h_handle_interrupt, 1199 1166 .led_hw_is_supported = en8811h_led_hw_is_supported,