diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 1a8de2bf8655..be10d31abe0c 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -72,6 +72,7 @@ enum ad_link_speed_type { AD_LINK_SPEED_40000MBPS, AD_LINK_SPEED_50000MBPS, AD_LINK_SPEED_56000MBPS, + AD_LINK_SPEED_80000MBPS, AD_LINK_SPEED_100000MBPS, AD_LINK_SPEED_200000MBPS, AD_LINK_SPEED_400000MBPS, @@ -297,6 +298,7 @@ static inline int __check_agg_selection_timer(struct port *port) * %AD_LINK_SPEED_40000MBPS * %AD_LINK_SPEED_50000MBPS * %AD_LINK_SPEED_56000MBPS + * %AD_LINK_SPEED_80000MBPS * %AD_LINK_SPEED_100000MBPS * %AD_LINK_SPEED_200000MBPS * %AD_LINK_SPEED_400000MBPS @@ -365,6 +367,10 @@ static u16 __get_link_speed(struct port *port) speed = AD_LINK_SPEED_56000MBPS; break; + case SPEED_80000: + speed = AD_LINK_SPEED_80000MBPS; + break; + case SPEED_100000: speed = AD_LINK_SPEED_100000MBPS; break; @@ -816,6 +822,9 @@ static u32 __get_agg_bandwidth(struct aggregator *aggregator) case AD_LINK_SPEED_56000MBPS: bandwidth = nports * 56000; break; + case AD_LINK_SPEED_80000MBPS: + bandwidth = nports * 80000; + break; case AD_LINK_SPEED_100000MBPS: bandwidth = nports * 100000; break; diff --git a/drivers/net/phy/phy-caps.h b/drivers/net/phy/phy-caps.h index 5f3f757e0b2f..421088e6f6e8 100644 --- a/drivers/net/phy/phy-caps.h +++ b/drivers/net/phy/phy-caps.h @@ -25,6 +25,7 @@ enum { LINK_CAPA_40000FD, LINK_CAPA_50000FD, LINK_CAPA_56000FD, + LINK_CAPA_80000FD, LINK_CAPA_100000FD, LINK_CAPA_200000FD, LINK_CAPA_400000FD, diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c index 3badf6e84554..d7a4a977fc8a 100644 --- a/drivers/net/phy/phy-core.c +++ b/drivers/net/phy/phy-core.c @@ -48,6 +48,8 @@ const char *phy_speed_to_str(int speed) return "50Gbps"; case SPEED_56000: return "56Gbps"; + case SPEED_80000: + return "80Gbps"; case SPEED_100000: return "100Gbps"; case SPEED_200000: diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c index 17a63c931335..942d43191561 100644 --- a/drivers/net/phy/phy_caps.c +++ b/drivers/net/phy/phy_caps.c @@ -21,6 +21,7 @@ static struct link_capabilities link_caps[__LINK_CAPA_MAX] __ro_after_init = { { SPEED_40000, DUPLEX_FULL, {0} }, /* LINK_CAPA_40000FD */ { SPEED_50000, DUPLEX_FULL, {0} }, /* LINK_CAPA_50000FD */ { SPEED_56000, DUPLEX_FULL, {0} }, /* LINK_CAPA_56000FD */ + { SPEED_80000, DUPLEX_FULL, {0} }, /* LINK_CAPA_80000FD */ { SPEED_100000, DUPLEX_FULL, {0} }, /* LINK_CAPA_100000FD */ { SPEED_200000, DUPLEX_FULL, {0} }, /* LINK_CAPA_200000FD */ { SPEED_400000, DUPLEX_FULL, {0} }, /* LINK_CAPA_400000FD */ @@ -49,6 +50,7 @@ static int speed_duplex_to_capa(int speed, unsigned int duplex) case SPEED_40000: return LINK_CAPA_40000FD; case SPEED_50000: return LINK_CAPA_50000FD; case SPEED_56000: return LINK_CAPA_56000FD; + case SPEED_80000: return LINK_CAPA_80000FD; case SPEED_100000: return LINK_CAPA_100000FD; case SPEED_200000: return LINK_CAPA_200000FD; case SPEED_400000: return LINK_CAPA_400000FD; diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 43d8380aaefb..c8fd6b91cdd4 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -311,6 +311,7 @@ static struct { { MAC_400000FD, SPEED_400000, DUPLEX_FULL, BIT(LINK_CAPA_400000FD) }, { MAC_200000FD, SPEED_200000, DUPLEX_FULL, BIT(LINK_CAPA_200000FD) }, { MAC_100000FD, SPEED_100000, DUPLEX_FULL, BIT(LINK_CAPA_100000FD) }, + { MAC_80000FD, SPEED_80000, DUPLEX_FULL, BIT(LINK_CAPA_80000FD) }, { MAC_56000FD, SPEED_56000, DUPLEX_FULL, BIT(LINK_CAPA_56000FD) }, { MAC_50000FD, SPEED_50000, DUPLEX_FULL, BIT(LINK_CAPA_50000FD) }, { MAC_40000FD, SPEED_40000, DUPLEX_FULL, BIT(LINK_CAPA_40000FD) }, diff --git a/drivers/net/thunderbolt/main.c b/drivers/net/thunderbolt/main.c index dcaa62377808..7aae5d915a1e 100644 --- a/drivers/net/thunderbolt/main.c +++ b/drivers/net/thunderbolt/main.c @@ -10,6 +10,7 @@ */ #include +#include #include #include #include @@ -1261,9 +1262,57 @@ static const struct net_device_ops tbnet_netdev_ops = { .ndo_open = tbnet_open, .ndo_stop = tbnet_stop, .ndo_start_xmit = tbnet_start_xmit, + .ndo_set_mac_address = eth_mac_addr, .ndo_get_stats64 = tbnet_get_stats64, }; +static int tbnet_get_link_ksettings(struct net_device *dev, + struct ethtool_link_ksettings *cmd) +{ + const struct tbnet *net = netdev_priv(dev); + const struct tb_xdomain *xd = net->xd; + int speed; + + ethtool_link_ksettings_zero_link_mode(cmd, supported); + ethtool_link_ksettings_zero_link_mode(cmd, advertising); + + /* Figure out the current link speed and width */ + switch (xd->link_speed) { + case 40: + speed = SPEED_80000; + break; + + case 20: + if (xd->link_width == 2) + speed = SPEED_40000; + else + speed = SPEED_20000; + break; + + case 10: + if (xd->link_width == 2) { + speed = SPEED_20000; + break; + } + fallthrough; + + default: + speed = SPEED_10000; + break; + } + + cmd->base.speed = speed; + cmd->base.duplex = DUPLEX_FULL; + cmd->base.autoneg = AUTONEG_DISABLE; + cmd->base.port = PORT_OTHER; + + return 0; +} + +static const struct ethtool_ops tbnet_ethtool_ops = { + .get_link_ksettings = tbnet_get_link_ksettings, +}; + static void tbnet_generate_mac(struct net_device *dev) { const struct tbnet *net = netdev_priv(dev); @@ -1281,6 +1330,9 @@ static void tbnet_generate_mac(struct net_device *dev) hash = jhash2((u32 *)xd->local_uuid, 4, hash); addr[5] = hash & 0xff; eth_hw_addr_set(dev, addr); + + /* Allow changing it if needed */ + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; } static int tbnet_probe(struct tb_service *svc, const struct tb_service_id *id) @@ -1311,6 +1363,7 @@ static int tbnet_probe(struct tb_service *svc, const struct tb_service_id *id) strcpy(dev->name, "thunderbolt%d"); dev->netdev_ops = &tbnet_netdev_ops; + dev->ethtool_ops = &tbnet_ethtool_ops; /* ThunderboltIP takes advantage of TSO packets but instead of * segmenting them we just split the packet into Thunderbolt diff --git a/include/linux/phylink.h b/include/linux/phylink.h index 38363e566ac3..20996f5778d1 100644 --- a/include/linux/phylink.h +++ b/include/linux/phylink.h @@ -90,9 +90,10 @@ enum { MAC_40000FD = BIT(13), MAC_50000FD = BIT(14), MAC_56000FD = BIT(15), - MAC_100000FD = BIT(16), - MAC_200000FD = BIT(17), - MAC_400000FD = BIT(18), + MAC_80000FD = BIT(16), + MAC_100000FD = BIT(17), + MAC_200000FD = BIT(18), + MAC_400000FD = BIT(19), }; static inline bool phylink_autoneg_inband(unsigned int mode) diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index ce9aeb65a8e1..b74b80508553 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -2203,6 +2203,7 @@ enum ethtool_link_mode_bit_indices { #define SPEED_40000 40000 #define SPEED_50000 50000 #define SPEED_56000 56000 +#define SPEED_80000 80000 #define SPEED_100000 100000 #define SPEED_200000 200000 #define SPEED_400000 400000