diff options
Diffstat (limited to 'drivers/net/thunderbolt')
| -rw-r--r-- | drivers/net/thunderbolt/main.c | 53 |
1 files changed, 53 insertions, 0 deletions
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 <linux/atomic.h> +#include <linux/ethtool.h> #include <linux/highmem.h> #include <linux/if_vlan.h> #include <linux/jhash.h> @@ -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 |
