]> www.infradead.org Git - users/griffoul/linux.git/commitdiff
net: phy: aquantia: save a local shadow of GLOBAL_CFG register values
authorVladimir Oltean <vladimir.oltean@nxp.com>
Thu, 21 Aug 2025 15:20:13 +0000 (18:20 +0300)
committerJakub Kicinski <kuba@kernel.org>
Mon, 25 Aug 2025 17:54:15 +0000 (10:54 -0700)
Currently, aqr_gen2_fill_interface_modes() reads VEND1_GLOBAL_CFG_*
registers to populate phydev->supported_interfaces. But this is not
the only place which needs to read these registers. There is also
aqr107_read_rate().

Based on the premise that these values are statically set by firmware
and the driver only needs to read them, the proposal is to read them
only once, at config_init() time, and use the cached values also in
aqr107_read_rate().

This patch only refactors the aqr_gen2_fill_interface_modes() code to
save the registers to driver memory, and to populate supported_interfaces
based on that.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Link: https://patch.msgid.link/20250821152022.1065237-7-vladimir.oltean@nxp.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/phy/aquantia/aquantia.h
drivers/net/phy/aquantia/aquantia_main.c

index 67ec6f7484af85bbaa6933500d300353ad8b1a12..492052cf1e6e25a1024cca78323e10faf79f5038 100644 (file)
@@ -174,11 +174,38 @@ static const struct aqr107_hw_stat aqr107_hw_stats[] = {
 
 #define AQR107_SGMII_STAT_SZ ARRAY_SIZE(aqr107_hw_stats)
 
+static const struct {
+       int speed;
+       u16 reg;
+} aqr_global_cfg_regs[] = {
+       { SPEED_10,     VEND1_GLOBAL_CFG_10M, },
+       { SPEED_100,    VEND1_GLOBAL_CFG_100M, },
+       { SPEED_1000,   VEND1_GLOBAL_CFG_1G, },
+       { SPEED_2500,   VEND1_GLOBAL_CFG_2_5G, },
+       { SPEED_5000,   VEND1_GLOBAL_CFG_5G, },
+       { SPEED_10000,  VEND1_GLOBAL_CFG_10G, },
+};
+
+#define AQR_NUM_GLOBAL_CFG ARRAY_SIZE(aqr_global_cfg_regs)
+
+enum aqr_rate_adaptation {
+       AQR_RATE_ADAPT_NONE,
+       AQR_RATE_ADAPT_USX,
+       AQR_RATE_ADAPT_PAUSE,
+};
+
+struct aqr_global_syscfg {
+       int speed;
+       phy_interface_t interface;
+       enum aqr_rate_adaptation rate_adapt;
+};
+
 struct aqr107_priv {
        u64 sgmii_stats[AQR107_SGMII_STAT_SZ];
        unsigned long leds_active_low;
        unsigned long leds_active_high;
        bool wait_on_global_cfg;
+       struct aqr_global_syscfg global_cfg[AQR_NUM_GLOBAL_CFG];
 };
 
 #if IS_REACHABLE(CONFIG_HWMON)
index 21fdbda2a0e001ba907789808a0338c1ae0435f7..9d704b7e3dc8c8a643e9d9371b6fc4686eea6fa5 100644 (file)
@@ -860,44 +860,24 @@ static int aqr_gen1_config_init(struct phy_device *phydev)
        return 0;
 }
 
-static const u16 aqr_global_cfg_regs[] = {
-       VEND1_GLOBAL_CFG_10M,
-       VEND1_GLOBAL_CFG_100M,
-       VEND1_GLOBAL_CFG_1G,
-       VEND1_GLOBAL_CFG_2_5G,
-       VEND1_GLOBAL_CFG_5G,
-       VEND1_GLOBAL_CFG_10G,
-};
-
-static int aqr_gen2_fill_interface_modes(struct phy_device *phydev)
+/* Walk the media-speed configuration registers to determine which
+ * host-side serdes modes may be used by the PHY depending on the
+ * negotiated media speed.
+ */
+static int aqr_gen2_read_global_syscfg(struct phy_device *phydev)
 {
-       unsigned long *possible = phydev->possible_interfaces;
        struct aqr107_priv *priv = phydev->priv;
        unsigned int serdes_mode, rate_adapt;
        phy_interface_t interface;
-       int i, val, ret;
+       int i, val;
 
-       /* It's been observed on some models that - when coming out of suspend
-        * - the FW signals that the PHY is ready but the GLOBAL_CFG registers
-        * continue on returning zeroes for some time. Let's poll the 100M
-        * register until it returns a real value as both 113c and 115c support
-        * this mode.
-        */
-       if (priv->wait_on_global_cfg) {
-               ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
-                                               VEND1_GLOBAL_CFG_100M, val,
-                                               val != 0, 1000, 100000, false);
-               if (ret)
-                       return ret;
-       }
+       for (i = 0; i < AQR_NUM_GLOBAL_CFG; i++) {
+               struct aqr_global_syscfg *syscfg = &priv->global_cfg[i];
+
+               syscfg->speed = aqr_global_cfg_regs[i].speed;
 
-       /* Walk the media-speed configuration registers to determine which
-        * host-side serdes modes may be used by the PHY depending on the
-        * negotiated media speed.
-        */
-       for (i = 0; i < ARRAY_SIZE(aqr_global_cfg_regs); i++) {
                val = phy_read_mmd(phydev, MDIO_MMD_VEND1,
-                                  aqr_global_cfg_regs[i]);
+                                  aqr_global_cfg_regs[i].reg);
                if (val < 0)
                        return val;
 
@@ -931,6 +911,55 @@ static int aqr_gen2_fill_interface_modes(struct phy_device *phydev)
                        break;
                }
 
+               syscfg->interface = interface;
+
+               switch (rate_adapt) {
+               case VEND1_GLOBAL_CFG_RATE_ADAPT_NONE:
+                       syscfg->rate_adapt = AQR_RATE_ADAPT_NONE;
+                       break;
+               case VEND1_GLOBAL_CFG_RATE_ADAPT_USX:
+                       syscfg->rate_adapt = AQR_RATE_ADAPT_USX;
+                       break;
+               case VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE:
+                       syscfg->rate_adapt = AQR_RATE_ADAPT_PAUSE;
+                       break;
+               default:
+                       phydev_warn(phydev, "unrecognized rate adapt mode %u\n",
+                                   rate_adapt);
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+static int aqr_gen2_fill_interface_modes(struct phy_device *phydev)
+{
+       unsigned long *possible = phydev->possible_interfaces;
+       struct aqr107_priv *priv = phydev->priv;
+       phy_interface_t interface;
+       int i, val, ret;
+
+       /* It's been observed on some models that - when coming out of suspend
+        * - the FW signals that the PHY is ready but the GLOBAL_CFG registers
+        * continue on returning zeroes for some time. Let's poll the 100M
+        * register until it returns a real value as both 113c and 115c support
+        * this mode.
+        */
+       if (priv->wait_on_global_cfg) {
+               ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
+                                               VEND1_GLOBAL_CFG_100M, val,
+                                               val != 0, 1000, 100000, false);
+               if (ret)
+                       return ret;
+       }
+
+       ret = aqr_gen2_read_global_syscfg(phydev);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < AQR_NUM_GLOBAL_CFG; i++) {
+               interface = priv->global_cfg[i].interface;
                if (interface != PHY_INTERFACE_MODE_NA)
                        __set_bit(interface, possible);
        }