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

net: fec: Refactor MAC reset to function

The core is reset both in `fec_restart()` (called on link-up) and
`fec_stop()` (going to sleep, driver remove etc.). These two functions
had their separate implementations, which was at first only a register
write and a `udelay()` (and the accompanying block comment). However,
since then we got soft-reset (MAC disable) and Wake-on-LAN support, which
meant that these implementations diverged, often causing bugs.

For instance, as of now, `fec_stop()` does not check for
`FEC_QUIRK_NO_HARD_RESET`, meaning the MII/RMII mode is cleared on eg.
a PM power-down event; and `fec_restart()` missed the refactor renaming
the "magic" constant `1` to `FEC_ECR_RESET`.

To harmonize current implementations, and eliminate this source of
potential future bugs, refactor implementation to a common function.

Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Csókás, Bence <csokas.bence@prolan.hu>
Link: https://patch.msgid.link/20250207121255.161146-2-csokas.bence@prolan.hu
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Csókás, Bence and committed by
Paolo Abeni
67800d29 907dd32b

+25 -27
+25 -27
drivers/net/ethernet/freescale/fec_main.c
··· 1093 1093 } 1094 1094 } 1095 1095 1096 + /* Whack a reset. We should wait for this. 1097 + * For i.MX6SX SOC, enet use AXI bus, we use disable MAC 1098 + * instead of reset MAC itself. 1099 + */ 1100 + static void fec_ctrl_reset(struct fec_enet_private *fep, bool allow_wol) 1101 + { 1102 + u32 val; 1103 + 1104 + if (!allow_wol || !(fep->wol_flag & FEC_WOL_FLAG_SLEEP_ON)) { 1105 + if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES || 1106 + ((fep->quirks & FEC_QUIRK_NO_HARD_RESET) && fep->link)) { 1107 + writel(0, fep->hwp + FEC_ECNTRL); 1108 + } else { 1109 + writel(FEC_ECR_RESET, fep->hwp + FEC_ECNTRL); 1110 + udelay(10); 1111 + } 1112 + } else { 1113 + val = readl(fep->hwp + FEC_ECNTRL); 1114 + val |= (FEC_ECR_MAGICEN | FEC_ECR_SLEEP); 1115 + writel(val, fep->hwp + FEC_ECNTRL); 1116 + } 1117 + } 1118 + 1096 1119 /* 1097 1120 * This function is called to start or restart the FEC during a link 1098 1121 * change, transmit timeout, or to reconfigure the FEC. The network ··· 1132 1109 if (fep->bufdesc_ex) 1133 1110 fec_ptp_save_state(fep); 1134 1111 1135 - /* Whack a reset. We should wait for this. 1136 - * For i.MX6SX SOC, enet use AXI bus, we use disable MAC 1137 - * instead of reset MAC itself. 1138 - */ 1139 - if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES || 1140 - ((fep->quirks & FEC_QUIRK_NO_HARD_RESET) && fep->link)) { 1141 - writel(0, fep->hwp + FEC_ECNTRL); 1142 - } else { 1143 - writel(1, fep->hwp + FEC_ECNTRL); 1144 - udelay(10); 1145 - } 1112 + fec_ctrl_reset(fep, false); 1146 1113 1147 1114 /* 1148 1115 * enet-mac reset will reset mac address registers too, ··· 1386 1373 if (fep->bufdesc_ex) 1387 1374 fec_ptp_save_state(fep); 1388 1375 1389 - /* Whack a reset. We should wait for this. 1390 - * For i.MX6SX SOC, enet use AXI bus, we use disable MAC 1391 - * instead of reset MAC itself. 1392 - */ 1393 - if (!(fep->wol_flag & FEC_WOL_FLAG_SLEEP_ON)) { 1394 - if (fep->quirks & FEC_QUIRK_HAS_MULTI_QUEUES) { 1395 - writel(0, fep->hwp + FEC_ECNTRL); 1396 - } else { 1397 - writel(FEC_ECR_RESET, fep->hwp + FEC_ECNTRL); 1398 - udelay(10); 1399 - } 1400 - } else { 1401 - val = readl(fep->hwp + FEC_ECNTRL); 1402 - val |= (FEC_ECR_MAGICEN | FEC_ECR_SLEEP); 1403 - writel(val, fep->hwp + FEC_ECNTRL); 1404 - } 1376 + fec_ctrl_reset(fep, true); 1405 1377 writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); 1406 1378 writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); 1407 1379