platform: allow to force the advertised auto-negotiation link value

This will only work for network devices supporting the BASE-T specification.
This commit is contained in:
Francesco Giudici
2018-06-12 12:57:05 +02:00
parent 45170bad5d
commit 356addb9e6

View File

@@ -384,6 +384,40 @@ nmp_utils_ethtool_get_link_settings (int ifindex,
return TRUE; return TRUE;
} }
#define ADVERTISED_INVALID 0
#define BASET_ALL_MODES ( ADVERTISED_10baseT_Half \
| ADVERTISED_10baseT_Full \
| ADVERTISED_100baseT_Half \
| ADVERTISED_100baseT_Full \
| ADVERTISED_1000baseT_Half \
| ADVERTISED_1000baseT_Full \
| ADVERTISED_10000baseT_Full )
static inline guint32
get_baset_mode (guint32 speed, NMPlatformLinkDuplexType duplex)
{
if (duplex == NM_PLATFORM_LINK_DUPLEX_UNKNOWN)
return ADVERTISED_INVALID;
if (duplex == NM_PLATFORM_LINK_DUPLEX_HALF) {
switch (speed) {
case 10: return ADVERTISED_10baseT_Half;
case 100: return ADVERTISED_100baseT_Half;
case 1000: return ADVERTISED_1000baseT_Half;
default: return ADVERTISED_INVALID;
}
} else {
switch (speed) {
case 10: return ADVERTISED_10baseT_Full;
case 100: return ADVERTISED_100baseT_Full;
case 1000: return ADVERTISED_1000baseT_Full;
case 10000: return ADVERTISED_10000baseT_Full;
default: return ADVERTISED_INVALID;
}
}
}
gboolean gboolean
nmp_utils_ethtool_set_link_settings (int ifindex, nmp_utils_ethtool_set_link_settings (int ifindex,
gboolean autoneg, gboolean autoneg,
@@ -395,6 +429,8 @@ nmp_utils_ethtool_set_link_settings (int ifindex,
}; };
g_return_val_if_fail (ifindex > 0, FALSE); g_return_val_if_fail (ifindex > 0, FALSE);
g_return_val_if_fail ( (speed && duplex != NM_PLATFORM_LINK_DUPLEX_UNKNOWN)
|| (!speed && duplex == NM_PLATFORM_LINK_DUPLEX_UNKNOWN), FALSE);
/* retrieve first current settings */ /* retrieve first current settings */
if (!ethtool_get (ifindex, &edata)) if (!ethtool_get (ifindex, &edata))
@@ -404,7 +440,31 @@ nmp_utils_ethtool_set_link_settings (int ifindex,
edata.cmd = ETHTOOL_SSET; edata.cmd = ETHTOOL_SSET;
if (autoneg) { if (autoneg) {
edata.autoneg = AUTONEG_ENABLE; edata.autoneg = AUTONEG_ENABLE;
edata.advertising = edata.supported; if (!speed)
edata.advertising = edata.supported;
else {
guint32 mode;
mode = get_baset_mode (speed, duplex);
if (!mode) {
nm_log_trace (LOGD_PLATFORM,
"ethtool[%d]: %uBASE-T %s duplex mode cannot be advertised",
ifindex,
speed,
nm_platform_link_duplex_type_to_string (duplex));
return FALSE;
}
if (!(edata.supported & mode)) {
nm_log_trace (LOGD_PLATFORM,
"ethtool[%d]: device does not support %uBASE-T %s duplex mode",
ifindex,
speed,
nm_platform_link_duplex_type_to_string (duplex));
return FALSE;
}
edata.advertising = (edata.supported & ~BASET_ALL_MODES) | mode;
}
} else { } else {
edata.autoneg = AUTONEG_DISABLE; edata.autoneg = AUTONEG_DISABLE;