@@ -60,6 +60,7 @@ struct phylink {
60
60
u8 act_link_an_mode ; /* Active MLO_AN_xxx mode */
61
61
u8 link_port ; /* The current non-phy ethtool port */
62
62
__ETHTOOL_DECLARE_LINK_MODE_MASK (supported );
63
+ __ETHTOOL_DECLARE_LINK_MODE_MASK (supported_lpi );
63
64
64
65
/* The link configuration settings */
65
66
struct phylink_link_state link_config ;
@@ -81,12 +82,20 @@ struct phylink {
81
82
unsigned int pcs_state ;
82
83
83
84
bool link_failed ;
85
+ bool mac_supports_eee_ops ;
86
+ bool mac_supports_eee ;
87
+ bool phy_enable_tx_lpi ;
88
+ bool mac_enable_tx_lpi ;
89
+ bool mac_tx_clk_stop ;
90
+ u32 mac_tx_lpi_timer ;
84
91
85
92
struct sfp_bus * sfp_bus ;
86
93
bool sfp_may_have_phy ;
87
94
DECLARE_PHY_INTERFACE_MASK (sfp_interfaces );
88
95
__ETHTOOL_DECLARE_LINK_MODE_MASK (sfp_support );
89
96
u8 sfp_port ;
97
+
98
+ struct eee_config eee_cfg ;
90
99
};
91
100
92
101
#define phylink_printk (level , pl , fmt , ...) \
@@ -1584,6 +1593,39 @@ static const char *phylink_pause_to_str(int pause)
1584
1593
}
1585
1594
}
1586
1595
1596
+ static void phylink_deactivate_lpi (struct phylink * pl )
1597
+ {
1598
+ if (pl -> mac_enable_tx_lpi ) {
1599
+ pl -> mac_enable_tx_lpi = false;
1600
+
1601
+ phylink_dbg (pl , "disabling LPI\n" );
1602
+
1603
+ pl -> mac_ops -> mac_disable_tx_lpi (pl -> config );
1604
+ }
1605
+ }
1606
+
1607
+ static void phylink_activate_lpi (struct phylink * pl )
1608
+ {
1609
+ int err ;
1610
+
1611
+ if (!test_bit (pl -> cur_interface , pl -> config -> lpi_interfaces )) {
1612
+ phylink_dbg (pl , "MAC does not support LPI with %s\n" ,
1613
+ phy_modes (pl -> cur_interface ));
1614
+ return ;
1615
+ }
1616
+
1617
+ phylink_dbg (pl , "LPI timer %uus, tx clock stop %u\n" ,
1618
+ pl -> mac_tx_lpi_timer , pl -> mac_tx_clk_stop );
1619
+
1620
+ err = pl -> mac_ops -> mac_enable_tx_lpi (pl -> config , pl -> mac_tx_lpi_timer ,
1621
+ pl -> mac_tx_clk_stop );
1622
+ if (!err )
1623
+ pl -> mac_enable_tx_lpi = true;
1624
+ else
1625
+ phylink_err (pl , "%ps() failed: %pe\n" ,
1626
+ pl -> mac_ops -> mac_enable_tx_lpi , ERR_PTR (err ));
1627
+ }
1628
+
1587
1629
static void phylink_link_up (struct phylink * pl ,
1588
1630
struct phylink_link_state link_state )
1589
1631
{
@@ -1630,6 +1672,9 @@ static void phylink_link_up(struct phylink *pl,
1630
1672
pl -> cur_interface , speed , duplex ,
1631
1673
!!(link_state .pause & MLO_PAUSE_TX ), rx_pause );
1632
1674
1675
+ if (pl -> mac_supports_eee && pl -> phy_enable_tx_lpi )
1676
+ phylink_activate_lpi (pl );
1677
+
1633
1678
if (ndev )
1634
1679
netif_carrier_on (ndev );
1635
1680
@@ -1646,6 +1691,9 @@ static void phylink_link_down(struct phylink *pl)
1646
1691
1647
1692
if (ndev )
1648
1693
netif_carrier_off (ndev );
1694
+
1695
+ phylink_deactivate_lpi (pl );
1696
+
1649
1697
pl -> mac_ops -> mac_link_down (pl -> config , pl -> act_link_an_mode ,
1650
1698
pl -> cur_interface );
1651
1699
phylink_info (pl , "Link is Down\n" );
@@ -1909,6 +1957,17 @@ struct phylink *phylink_create(struct phylink_config *config,
1909
1957
return ERR_PTR (- EINVAL );
1910
1958
}
1911
1959
1960
+ pl -> mac_supports_eee_ops = mac_ops -> mac_disable_tx_lpi &&
1961
+ mac_ops -> mac_enable_tx_lpi ;
1962
+ pl -> mac_supports_eee = pl -> mac_supports_eee_ops &&
1963
+ pl -> config -> lpi_capabilities &&
1964
+ !phy_interface_empty (pl -> config -> lpi_interfaces );
1965
+
1966
+ /* Set the default EEE configuration */
1967
+ pl -> eee_cfg .eee_enabled = pl -> config -> eee_enabled_default ;
1968
+ pl -> eee_cfg .tx_lpi_enabled = pl -> eee_cfg .eee_enabled ;
1969
+ pl -> eee_cfg .tx_lpi_timer = pl -> config -> lpi_timer_default ;
1970
+
1912
1971
pl -> phy_state .interface = iface ;
1913
1972
pl -> link_interface = iface ;
1914
1973
if (iface == PHY_INTERFACE_MODE_MOCA )
@@ -2013,16 +2072,22 @@ static void phylink_phy_change(struct phy_device *phydev, bool up)
2013
2072
pl -> phy_state .link = up ;
2014
2073
if (!up )
2015
2074
pl -> link_failed = true;
2075
+
2076
+ /* Get the LPI state from phylib */
2077
+ pl -> phy_enable_tx_lpi = phydev -> enable_tx_lpi ;
2078
+ pl -> mac_tx_lpi_timer = phydev -> eee_cfg .tx_lpi_timer ;
2016
2079
mutex_unlock (& pl -> state_mutex );
2017
2080
2018
2081
phylink_run_resolve (pl );
2019
2082
2020
- phylink_dbg (pl , "phy link %s %s/%s/%s/%s/%s\n" , up ? "up" : "down" ,
2083
+ phylink_dbg (pl , "phy link %s %s/%s/%s/%s/%s/%slpi\n" ,
2084
+ up ? "up" : "down" ,
2021
2085
phy_modes (phydev -> interface ),
2022
2086
phy_speed_to_str (phydev -> speed ),
2023
2087
phy_duplex_to_str (phydev -> duplex ),
2024
2088
phy_rate_matching_to_str (phydev -> rate_matching ),
2025
- phylink_pause_to_str (pl -> phy_state .pause ));
2089
+ phylink_pause_to_str (pl -> phy_state .pause ),
2090
+ phydev -> enable_tx_lpi ? "" : "no" );
2026
2091
}
2027
2092
2028
2093
static int phylink_validate_phy (struct phylink * pl , struct phy_device * phy ,
@@ -2152,6 +2217,36 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy,
2152
2217
2153
2218
/* Restrict the phy advertisement according to the MAC support. */
2154
2219
linkmode_copy (phy -> advertising , config .advertising );
2220
+
2221
+ /* If the MAC supports phylink managed EEE, restrict the EEE
2222
+ * advertisement according to the MAC's LPI capabilities.
2223
+ */
2224
+ if (pl -> mac_supports_eee ) {
2225
+ /* If EEE is enabled, then we need to call phy_support_eee()
2226
+ * to ensure that the advertising mask is appropriately set.
2227
+ * This also enables EEE at the PHY.
2228
+ */
2229
+ if (pl -> eee_cfg .eee_enabled )
2230
+ phy_support_eee (phy );
2231
+
2232
+ phy -> eee_cfg .tx_lpi_enabled = pl -> eee_cfg .tx_lpi_enabled ;
2233
+ phy -> eee_cfg .tx_lpi_timer = pl -> eee_cfg .tx_lpi_timer ;
2234
+
2235
+ /* Convert the MAC's LPI capabilities to linkmodes */
2236
+ linkmode_zero (pl -> supported_lpi );
2237
+ phylink_caps_to_linkmodes (pl -> supported_lpi ,
2238
+ pl -> config -> lpi_capabilities );
2239
+
2240
+ /* Restrict the PHYs EEE support/advertisement to the modes
2241
+ * that the MAC supports.
2242
+ */
2243
+ linkmode_and (phy -> advertising_eee , phy -> advertising_eee ,
2244
+ pl -> supported_lpi );
2245
+ } else if (pl -> mac_supports_eee_ops ) {
2246
+ /* MAC supports phylink EEE, but wants EEE always disabled. */
2247
+ phy_disable_eee (phy );
2248
+ }
2249
+
2155
2250
mutex_unlock (& pl -> state_mutex );
2156
2251
mutex_unlock (& phy -> lock );
2157
2252
@@ -2167,7 +2262,13 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy,
2167
2262
if (pl -> config -> mac_managed_pm )
2168
2263
phy -> mac_managed_pm = true;
2169
2264
2170
- return 0 ;
2265
+ /* Allow the MAC to stop its clock if the PHY has the capability */
2266
+ pl -> mac_tx_clk_stop = phy_eee_tx_clock_stop_capable (phy ) > 0 ;
2267
+
2268
+ /* Explicitly configure whether the PHY is allowed to stop it's
2269
+ * receive clock.
2270
+ */
2271
+ return phy_eee_rx_clock_stop (phy , pl -> config -> eee_rx_clk_stop_enable );
2171
2272
}
2172
2273
2173
2274
static int phylink_attach_phy (struct phylink * pl , struct phy_device * phy ,
@@ -2324,6 +2425,8 @@ void phylink_disconnect_phy(struct phylink *pl)
2324
2425
mutex_lock (& phy -> lock );
2325
2426
mutex_lock (& pl -> state_mutex );
2326
2427
pl -> phydev = NULL ;
2428
+ pl -> phy_enable_tx_lpi = false;
2429
+ pl -> mac_tx_clk_stop = false;
2327
2430
mutex_unlock (& pl -> state_mutex );
2328
2431
mutex_unlock (& phy -> lock );
2329
2432
flush_work (& pl -> resolve );
@@ -3078,8 +3181,16 @@ int phylink_ethtool_get_eee(struct phylink *pl, struct ethtool_keee *eee)
3078
3181
3079
3182
ASSERT_RTNL ();
3080
3183
3081
- if (pl -> phydev )
3184
+ if (pl -> mac_supports_eee_ops && !pl -> mac_supports_eee )
3185
+ return ret ;
3186
+
3187
+ if (pl -> phydev ) {
3082
3188
ret = phy_ethtool_get_eee (pl -> phydev , eee );
3189
+ /* Restrict supported linkmode mask */
3190
+ if (ret == 0 && pl -> mac_supports_eee_ops )
3191
+ linkmode_and (eee -> supported , eee -> supported ,
3192
+ pl -> supported_lpi );
3193
+ }
3083
3194
3084
3195
return ret ;
3085
3196
}
@@ -3092,12 +3203,29 @@ EXPORT_SYMBOL_GPL(phylink_ethtool_get_eee);
3092
3203
*/
3093
3204
int phylink_ethtool_set_eee (struct phylink * pl , struct ethtool_keee * eee )
3094
3205
{
3206
+ bool mac_eee = pl -> mac_supports_eee ;
3095
3207
int ret = - EOPNOTSUPP ;
3096
3208
3097
3209
ASSERT_RTNL ();
3098
3210
3099
- if (pl -> phydev )
3211
+ phylink_dbg (pl , "mac %s phylink EEE%s, adv %*pbl, LPI%s timer %uus\n" ,
3212
+ mac_eee ? "supports" : "does not support" ,
3213
+ eee -> eee_enabled ? ", enabled" : "" ,
3214
+ __ETHTOOL_LINK_MODE_MASK_NBITS , eee -> advertised ,
3215
+ eee -> tx_lpi_enabled ? " enabled" : "" , eee -> tx_lpi_timer );
3216
+
3217
+ if (pl -> mac_supports_eee_ops && !mac_eee )
3218
+ return ret ;
3219
+
3220
+ if (pl -> phydev ) {
3221
+ /* Restrict advertisement mask */
3222
+ if (pl -> mac_supports_eee_ops )
3223
+ linkmode_and (eee -> advertised , eee -> advertised ,
3224
+ pl -> supported_lpi );
3100
3225
ret = phy_ethtool_set_eee (pl -> phydev , eee );
3226
+ if (ret == 0 )
3227
+ eee_to_eeecfg (& pl -> eee_cfg , eee );
3228
+ }
3101
3229
3102
3230
return ret ;
3103
3231
}
0 commit comments