diff options
author | Julian Wiedmann <jwi@linux.ibm.com> | 2020-11-17 17:15:20 +0100 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2020-11-18 17:34:19 -0800 |
commit | 235db5278316cc516de6b44e161a2afa5ccac61c (patch) | |
tree | b84a0bf7f564141c0209d89f8f9ab51f0597d053 /drivers/s390 | |
parent | e92d42e7602b97b9eb73ce810c5bf62cc65cbb7a (diff) | |
download | linux-235db5278316cc516de6b44e161a2afa5ccac61c.tar.bz2 |
s390/qeth: improve selection of ethtool link modes
The link mode is a combination of port speed and port mode. But we
currently only consider the speed, and then typically select the
corresponding TP-based link mode. For 1G and 10G Fibre links this means
we display the wrong link modes.
Move the SPEED_* switch statements inside the PORT_* cases, and only
consider valid combinations where we can select the corresponding
link mode. Add the relevant link modes (1000baseX, 10000baseSR and
1000baseLR) that were introduced back with
commit 5711a9822144 ("net: ethtool: add support for 1000BaseX and missing 10G link modes").
To differentiate between 10000baseSR and 10000baseLR, use the detailed
media_type information that QUERY OAT provides.
Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/net/qeth_core.h | 7 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_main.c | 11 | ||||
-rw-r--r-- | drivers/s390/net/qeth_ethtool.c | 124 |
3 files changed, 93 insertions, 49 deletions
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 843385f9eae0..32ea41b4356b 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -701,10 +701,17 @@ enum qeth_pnso_mode { QETH_PNSO_ADDR_INFO, }; +enum qeth_link_mode { + QETH_LINK_MODE_UNKNOWN, + QETH_LINK_MODE_FIBRE_SHORT, + QETH_LINK_MODE_FIBRE_LONG, +}; + struct qeth_link_info { u32 speed; u8 duplex; u8 port; + enum qeth_link_mode link_mode; }; #define QETH_BROADCAST_WITH_ECHO 0x01 diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 43d8a0a9c121..d9ba0586373b 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -5018,13 +5018,19 @@ static int qeth_init_link_info_oat_cb(struct qeth_card *card, switch (phys_if->media_type) { case QETH_QOAT_PHYS_MEDIA_COPPER: link_info->port = PORT_TP; + link_info->link_mode = QETH_LINK_MODE_UNKNOWN; break; case QETH_QOAT_PHYS_MEDIA_FIBRE_SHORT: + link_info->port = PORT_FIBRE; + link_info->link_mode = QETH_LINK_MODE_FIBRE_SHORT; + break; case QETH_QOAT_PHYS_MEDIA_FIBRE_LONG: link_info->port = PORT_FIBRE; + link_info->link_mode = QETH_LINK_MODE_FIBRE_LONG; break; default: link_info->port = PORT_OTHER; + link_info->link_mode = QETH_LINK_MODE_UNKNOWN; break; } @@ -5038,6 +5044,7 @@ static void qeth_init_link_info(struct qeth_card *card) if (IS_IQD(card) || IS_VM_NIC(card)) { card->info.link_info.speed = SPEED_10000; card->info.link_info.port = PORT_FIBRE; + card->info.link_info.link_mode = QETH_LINK_MODE_FIBRE_SHORT; } else { switch (card->info.link_type) { case QETH_LINK_TYPE_FAST_ETH: @@ -5064,6 +5071,8 @@ static void qeth_init_link_info(struct qeth_card *card) card->info.link_info.speed = SPEED_UNKNOWN; card->info.link_info.port = PORT_OTHER; } + + card->info.link_info.link_mode = QETH_LINK_MODE_UNKNOWN; } /* Get more accurate data via QUERY OAT: */ @@ -5089,6 +5098,8 @@ static void qeth_init_link_info(struct qeth_card *card) card->info.link_info.duplex = link_info.duplex; if (link_info.port != PORT_OTHER) card->info.link_info.port = link_info.port; + if (link_info.link_mode != QETH_LINK_MODE_UNKNOWN) + card->info.link_info.link_mode = link_info.link_mode; } } } diff --git a/drivers/s390/net/qeth_ethtool.c b/drivers/s390/net/qeth_ethtool.c index 50b0c1810850..3a51bbff0ffe 100644 --- a/drivers/s390/net/qeth_ethtool.c +++ b/drivers/s390/net/qeth_ethtool.c @@ -324,7 +324,8 @@ static int qeth_set_per_queue_coalesce(struct net_device *dev, u32 queue, /* Autoneg and full-duplex are supported and advertised unconditionally. */ /* Always advertise and support all speeds up to specified, and only one */ /* specified port type. */ -static void qeth_set_ethtool_link_modes(struct ethtool_link_ksettings *cmd) +static void qeth_set_ethtool_link_modes(struct ethtool_link_ksettings *cmd, + enum qeth_link_mode link_mode) { ethtool_link_ksettings_zero_link_mode(cmd, supported); ethtool_link_ksettings_zero_link_mode(cmd, advertising); @@ -337,58 +338,83 @@ static void qeth_set_ethtool_link_modes(struct ethtool_link_ksettings *cmd) case PORT_TP: ethtool_link_ksettings_add_link_mode(cmd, supported, TP); ethtool_link_ksettings_add_link_mode(cmd, advertising, TP); + + switch (cmd->base.speed) { + case SPEED_10000: + ethtool_link_ksettings_add_link_mode(cmd, supported, + 10000baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 10000baseT_Full); + fallthrough; + case SPEED_1000: + ethtool_link_ksettings_add_link_mode(cmd, supported, + 1000baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 1000baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, supported, + 1000baseT_Half); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 1000baseT_Half); + fallthrough; + case SPEED_100: + ethtool_link_ksettings_add_link_mode(cmd, supported, + 100baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 100baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, supported, + 100baseT_Half); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 100baseT_Half); + fallthrough; + case SPEED_10: + ethtool_link_ksettings_add_link_mode(cmd, supported, + 10baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 10baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, supported, + 10baseT_Half); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 10baseT_Half); + break; + default: + break; + } + break; case PORT_FIBRE: ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE); ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE); - break; - default: - break; - } - /* partially does fall through, to also select lower speeds */ - switch (cmd->base.speed) { - case SPEED_25000: - ethtool_link_ksettings_add_link_mode(cmd, supported, - 25000baseSR_Full); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 25000baseSR_Full); - break; - case SPEED_10000: - ethtool_link_ksettings_add_link_mode(cmd, supported, - 10000baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 10000baseT_Full); - fallthrough; - case SPEED_1000: - ethtool_link_ksettings_add_link_mode(cmd, supported, - 1000baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 1000baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, supported, - 1000baseT_Half); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 1000baseT_Half); - fallthrough; - case SPEED_100: - ethtool_link_ksettings_add_link_mode(cmd, supported, - 100baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 100baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, supported, - 100baseT_Half); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 100baseT_Half); - fallthrough; - case SPEED_10: - ethtool_link_ksettings_add_link_mode(cmd, supported, - 10baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 10baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, supported, - 10baseT_Half); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 10baseT_Half); + switch (cmd->base.speed) { + case SPEED_25000: + ethtool_link_ksettings_add_link_mode(cmd, supported, + 25000baseSR_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 25000baseSR_Full); + break; + case SPEED_10000: + if (link_mode == QETH_LINK_MODE_FIBRE_LONG) { + ethtool_link_ksettings_add_link_mode(cmd, supported, + 10000baseLR_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 10000baseLR_Full); + } else if (link_mode == QETH_LINK_MODE_FIBRE_SHORT) { + ethtool_link_ksettings_add_link_mode(cmd, supported, + 10000baseSR_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 10000baseSR_Full); + } + break; + case SPEED_1000: + ethtool_link_ksettings_add_link_mode(cmd, supported, + 1000baseX_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 1000baseX_Full); + break; + default: + break; + } + break; default: break; @@ -420,7 +446,7 @@ static int qeth_get_link_ksettings(struct net_device *netdev, cmd->base.port = link_info.port; } - qeth_set_ethtool_link_modes(cmd); + qeth_set_ethtool_link_modes(cmd, card->info.link_info.link_mode); return 0; } |