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

net: pse-pd: pd692x0: Preserve PSE configuration across reboots

Detect when PSE hardware is already configured (user byte == 42) and
skip hardware initialization to prevent power interruption to connected
devices during system reboots.

Previously, the driver would always reconfigure the PSE hardware on
probe, causing a port matrix reflash that resulted in temporary power
loss to all connected devices. This change maintains power continuity
by preserving existing configuration when the PSE has been previously
initialized.

Signed-off-by: Kory Maincent <kory.maincent@bootlin.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20251013-feature_pd692x0_reboot_keep_conf-v2-3-68ab082a93dd@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Kory Maincent (Dent Project) and committed by
Jakub Kicinski
8f3d044b 6fa1f8b6

+32 -3
+32 -3
drivers/net/pse-pd/pd692x0.c
··· 30 30 #define PD692X0_FW_MIN_VER 5 31 31 #define PD692X0_FW_PATCH_VER 5 32 32 33 + #define PD692X0_USER_BYTE 42 34 + 33 35 enum pd692x0_fw_state { 34 36 PD692X0_FW_UNKNOWN, 35 37 PD692X0_FW_OK, ··· 82 80 PD692X0_MSG_GET_PORT_PARAM, 83 81 PD692X0_MSG_GET_POWER_BANK, 84 82 PD692X0_MSG_SET_POWER_BANK, 83 + PD692X0_MSG_SET_USER_BYTE, 85 84 86 85 /* add new message above here */ 87 86 PD692X0_MSG_CNT ··· 106 103 bool last_cmd_key; 107 104 unsigned long last_cmd_key_time; 108 105 106 + bool cfg_saved; 109 107 enum ethtool_c33_pse_admin_state admin_state[PD692X0_MAX_PIS]; 110 108 struct regulator_dev *manager_reg[PD692X0_MAX_MANAGERS]; 111 109 int manager_pw_budget[PD692X0_MAX_MANAGERS]; ··· 196 192 [PD692X0_MSG_SET_POWER_BANK] = { 197 193 .key = PD692X0_KEY_CMD, 198 194 .sub = {0x07, 0x0b, 0x57}, 195 + }, 196 + [PD692X0_MSG_SET_USER_BYTE] = { 197 + .key = PD692X0_KEY_PRG, 198 + .sub = {0x41, PD692X0_USER_BYTE}, 199 + .data = {0x4e, 0x4e, 0x4e, 0x4e, 200 + 0x4e, 0x4e, 0x4e, 0x4e}, 199 201 }, 200 202 }; 201 203 ··· 1243 1233 } 1244 1234 } 1245 1235 1236 + static int 1237 + pd692x0_save_user_byte(struct pd692x0_priv *priv) 1238 + { 1239 + struct pd692x0_msg msg, buf; 1240 + 1241 + msg = pd692x0_msg_template_list[PD692X0_MSG_SET_USER_BYTE]; 1242 + return pd692x0_sendrecv_msg(priv, &msg, &buf); 1243 + } 1244 + 1246 1245 static int pd692x0_setup_pi_matrix(struct pse_controller_dev *pcdev) 1247 1246 { 1248 1247 struct pd692x0_priv *priv = to_pd692x0_priv(pcdev); ··· 1287 1268 if (ret) 1288 1269 goto err_managers_req_pw; 1289 1270 1290 - ret = pd692x0_hw_conf_init(priv); 1291 - if (ret) 1292 - goto err_managers_req_pw; 1271 + /* Do not init the conf if it is already saved */ 1272 + if (!priv->cfg_saved) { 1273 + ret = pd692x0_hw_conf_init(priv); 1274 + if (ret) 1275 + goto err_managers_req_pw; 1276 + 1277 + ret = pd692x0_save_user_byte(priv); 1278 + if (ret) 1279 + goto err_managers_req_pw; 1280 + } 1293 1281 1294 1282 pd692x0_of_put_managers(priv, manager); 1295 1283 kfree(manager); ··· 1818 1792 priv->fw_state = PD692X0_FW_OK; 1819 1793 } 1820 1794 } 1795 + 1796 + if (buf.data[2] == PD692X0_USER_BYTE) 1797 + priv->cfg_saved = true; 1821 1798 1822 1799 priv->np = dev->of_node; 1823 1800 priv->pcdev.nr_lines = PD692X0_MAX_PIS;