summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2020-11-19 04:34:21 +0300
committerJakub Kicinski <kuba@kernel.org>2020-11-19 04:34:21 +0300
commitaa8f2cbd5748114e6f283b878f65e743f528d978 (patch)
treeb84a0bf7f564141c0209d89f8f9ab51f0597d053
parentbd4bdeb4f29027199c68104fbdfa07ad45390cc1 (diff)
parent235db5278316cc516de6b44e161a2afa5ccac61c (diff)
downloadlinux-aa8f2cbd5748114e6f283b878f65e743f528d978.tar.xz
Merge branch 's390-qeth-updates-2020-11-17'
Julian Wiedmann says: ==================== s390/qeth: updates 2020-11-17 This brings some cleanups, and a bunch of improvements for our .get_link_ksettings() code. ==================== Link: https://lore.kernel.org/r/20201117161520.1089-1-jwi@linux.ibm.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--drivers/s390/net/qeth_core.h22
-rw-r--r--drivers/s390/net/qeth_core_main.c223
-rw-r--r--drivers/s390/net/qeth_core_mpc.h40
-rw-r--r--drivers/s390/net/qeth_ethtool.c243
-rw-r--r--drivers/s390/net/qeth_l2_main.c33
-rw-r--r--drivers/s390/net/qeth_l3_main.c5
6 files changed, 373 insertions, 193 deletions
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index f73b4756ed5e..32ea41b4356b 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -701,6 +701,19 @@ 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
#define QETH_BROADCAST_WITHOUT_ECHO 0x02
struct qeth_card_info {
@@ -732,6 +745,7 @@ struct qeth_card_info {
struct qeth_card_blkt blkt;
__u32 diagass_support;
__u32 hwtrap;
+ struct qeth_link_info link_info;
};
enum qeth_discipline_id {
@@ -796,12 +810,6 @@ struct qeth_rx {
u8 bufs_refill;
};
-struct carrier_info {
- __u8 card_type;
- __u16 port_mode;
- __u32 port_speed;
-};
-
struct qeth_switch_info {
__u32 capabilities;
__u32 settings;
@@ -1108,7 +1116,7 @@ void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
int qeth_query_switch_attributes(struct qeth_card *card,
struct qeth_switch_info *sw_info);
int qeth_query_card_info(struct qeth_card *card,
- struct carrier_info *carrier_info);
+ struct qeth_link_info *link_info);
int qeth_setadpparms_set_access_ctrl(struct qeth_card *card,
enum qeth_ipa_isolation_modes mode);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 93c9b30ab17a..d9ba0586373b 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -4868,8 +4868,8 @@ out_free:
static int qeth_query_card_info_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data)
{
- struct carrier_info *carrier_info = (struct carrier_info *)reply->param;
struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *)data;
+ struct qeth_link_info *link_info = reply->param;
struct qeth_query_card_info *card_info;
QETH_CARD_TEXT(card, 2, "qcrdincb");
@@ -4877,14 +4877,67 @@ static int qeth_query_card_info_cb(struct qeth_card *card,
return -EIO;
card_info = &cmd->data.setadapterparms.data.card_info;
- carrier_info->card_type = card_info->card_type;
- carrier_info->port_mode = card_info->port_mode;
- carrier_info->port_speed = card_info->port_speed;
+ netdev_dbg(card->dev,
+ "card info: card_type=0x%02x, port_mode=0x%04x, port_speed=0x%08x\n",
+ card_info->card_type, card_info->port_mode,
+ card_info->port_speed);
+
+ switch (card_info->port_mode) {
+ case CARD_INFO_PORTM_FULLDUPLEX:
+ link_info->duplex = DUPLEX_FULL;
+ break;
+ case CARD_INFO_PORTM_HALFDUPLEX:
+ link_info->duplex = DUPLEX_HALF;
+ break;
+ default:
+ link_info->duplex = DUPLEX_UNKNOWN;
+ }
+
+ switch (card_info->card_type) {
+ case CARD_INFO_TYPE_1G_COPPER_A:
+ case CARD_INFO_TYPE_1G_COPPER_B:
+ link_info->speed = SPEED_1000;
+ link_info->port = PORT_TP;
+ break;
+ case CARD_INFO_TYPE_1G_FIBRE_A:
+ case CARD_INFO_TYPE_1G_FIBRE_B:
+ link_info->speed = SPEED_1000;
+ link_info->port = PORT_FIBRE;
+ break;
+ case CARD_INFO_TYPE_10G_FIBRE_A:
+ case CARD_INFO_TYPE_10G_FIBRE_B:
+ link_info->speed = SPEED_10000;
+ link_info->port = PORT_FIBRE;
+ break;
+ default:
+ switch (card_info->port_speed) {
+ case CARD_INFO_PORTS_10M:
+ link_info->speed = SPEED_10;
+ break;
+ case CARD_INFO_PORTS_100M:
+ link_info->speed = SPEED_100;
+ break;
+ case CARD_INFO_PORTS_1G:
+ link_info->speed = SPEED_1000;
+ break;
+ case CARD_INFO_PORTS_10G:
+ link_info->speed = SPEED_10000;
+ break;
+ case CARD_INFO_PORTS_25G:
+ link_info->speed = SPEED_25000;
+ break;
+ default:
+ link_info->speed = SPEED_UNKNOWN;
+ }
+
+ link_info->port = PORT_OTHER;
+ }
+
return 0;
}
int qeth_query_card_info(struct qeth_card *card,
- struct carrier_info *carrier_info)
+ struct qeth_link_info *link_info)
{
struct qeth_cmd_buffer *iob;
@@ -4894,8 +4947,162 @@ int qeth_query_card_info(struct qeth_card *card,
iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_CARD_INFO, 0);
if (!iob)
return -ENOMEM;
- return qeth_send_ipa_cmd(card, iob, qeth_query_card_info_cb,
- (void *)carrier_info);
+
+ return qeth_send_ipa_cmd(card, iob, qeth_query_card_info_cb, link_info);
+}
+
+static int qeth_init_link_info_oat_cb(struct qeth_card *card,
+ struct qeth_reply *reply_priv,
+ unsigned long data)
+{
+ struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *)data;
+ struct qeth_link_info *link_info = reply_priv->param;
+ struct qeth_query_oat_physical_if *phys_if;
+ struct qeth_query_oat_reply *reply;
+
+ if (qeth_setadpparms_inspect_rc(cmd))
+ return -EIO;
+
+ /* Multi-part reply is unexpected, don't bother: */
+ if (cmd->data.setadapterparms.hdr.used_total > 1)
+ return -EINVAL;
+
+ /* Expect the reply to start with phys_if data: */
+ reply = &cmd->data.setadapterparms.data.query_oat.reply[0];
+ if (reply->type != QETH_QOAT_REPLY_TYPE_PHYS_IF ||
+ reply->length < sizeof(*reply))
+ return -EINVAL;
+
+ phys_if = &reply->phys_if;
+
+ switch (phys_if->speed_duplex) {
+ case QETH_QOAT_PHYS_SPEED_10M_HALF:
+ link_info->speed = SPEED_10;
+ link_info->duplex = DUPLEX_HALF;
+ break;
+ case QETH_QOAT_PHYS_SPEED_10M_FULL:
+ link_info->speed = SPEED_10;
+ link_info->duplex = DUPLEX_FULL;
+ break;
+ case QETH_QOAT_PHYS_SPEED_100M_HALF:
+ link_info->speed = SPEED_100;
+ link_info->duplex = DUPLEX_HALF;
+ break;
+ case QETH_QOAT_PHYS_SPEED_100M_FULL:
+ link_info->speed = SPEED_100;
+ link_info->duplex = DUPLEX_FULL;
+ break;
+ case QETH_QOAT_PHYS_SPEED_1000M_HALF:
+ link_info->speed = SPEED_1000;
+ link_info->duplex = DUPLEX_HALF;
+ break;
+ case QETH_QOAT_PHYS_SPEED_1000M_FULL:
+ link_info->speed = SPEED_1000;
+ link_info->duplex = DUPLEX_FULL;
+ break;
+ case QETH_QOAT_PHYS_SPEED_10G_FULL:
+ link_info->speed = SPEED_10000;
+ link_info->duplex = DUPLEX_FULL;
+ break;
+ case QETH_QOAT_PHYS_SPEED_25G_FULL:
+ link_info->speed = SPEED_25000;
+ link_info->duplex = DUPLEX_FULL;
+ break;
+ case QETH_QOAT_PHYS_SPEED_UNKNOWN:
+ default:
+ link_info->speed = SPEED_UNKNOWN;
+ link_info->duplex = DUPLEX_UNKNOWN;
+ break;
+ }
+
+ 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;
+ }
+
+ return 0;
+}
+
+static void qeth_init_link_info(struct qeth_card *card)
+{
+ card->info.link_info.duplex = DUPLEX_FULL;
+
+ 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:
+ case QETH_LINK_TYPE_LANE_ETH100:
+ card->info.link_info.speed = SPEED_100;
+ card->info.link_info.port = PORT_TP;
+ break;
+ case QETH_LINK_TYPE_GBIT_ETH:
+ case QETH_LINK_TYPE_LANE_ETH1000:
+ card->info.link_info.speed = SPEED_1000;
+ card->info.link_info.port = PORT_FIBRE;
+ break;
+ case QETH_LINK_TYPE_10GBIT_ETH:
+ card->info.link_info.speed = SPEED_10000;
+ card->info.link_info.port = PORT_FIBRE;
+ break;
+ case QETH_LINK_TYPE_25GBIT_ETH:
+ card->info.link_info.speed = SPEED_25000;
+ card->info.link_info.port = PORT_FIBRE;
+ break;
+ default:
+ dev_info(&card->gdev->dev, "Unknown link type %x\n",
+ card->info.link_type);
+ 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: */
+ if (qeth_adp_supported(card, IPA_SETADP_QUERY_OAT)) {
+ struct qeth_link_info link_info;
+ struct qeth_cmd_buffer *iob;
+
+ iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_OAT,
+ SETADP_DATA_SIZEOF(query_oat));
+ if (iob) {
+ struct qeth_ipa_cmd *cmd = __ipa_cmd(iob);
+ struct qeth_query_oat *oat_req;
+
+ oat_req = &cmd->data.setadapterparms.data.query_oat;
+ oat_req->subcmd_code = QETH_QOAT_SCOPE_INTERFACE;
+
+ if (!qeth_send_ipa_cmd(card, iob,
+ qeth_init_link_info_oat_cb,
+ &link_info)) {
+ if (link_info.speed != SPEED_UNKNOWN)
+ card->info.link_info.speed = link_info.speed;
+ if (link_info.duplex != DUPLEX_UNKNOWN)
+ 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;
+ }
+ }
+ }
}
/**
@@ -5282,6 +5489,8 @@ retriable:
goto out;
}
+ qeth_init_link_info(card);
+
rc = qeth_init_qdio_queues(card);
if (rc) {
QETH_CARD_TEXT_(card, 2, "9err%d", rc);
diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h
index 6541bab96822..e4bde7daf083 100644
--- a/drivers/s390/net/qeth_core_mpc.h
+++ b/drivers/s390/net/qeth_core_mpc.h
@@ -489,9 +489,45 @@ struct qeth_set_access_ctrl {
__u8 reserved[8];
} __attribute__((packed));
+#define QETH_QOAT_PHYS_SPEED_UNKNOWN 0x00
+#define QETH_QOAT_PHYS_SPEED_10M_HALF 0x01
+#define QETH_QOAT_PHYS_SPEED_10M_FULL 0x02
+#define QETH_QOAT_PHYS_SPEED_100M_HALF 0x03
+#define QETH_QOAT_PHYS_SPEED_100M_FULL 0x04
+#define QETH_QOAT_PHYS_SPEED_1000M_HALF 0x05
+#define QETH_QOAT_PHYS_SPEED_1000M_FULL 0x06
+// n/a 0x07
+#define QETH_QOAT_PHYS_SPEED_10G_FULL 0x08
+// n/a 0x09
+#define QETH_QOAT_PHYS_SPEED_25G_FULL 0x0A
+
+#define QETH_QOAT_PHYS_MEDIA_COPPER 0x01
+#define QETH_QOAT_PHYS_MEDIA_FIBRE_SHORT 0x02
+#define QETH_QOAT_PHYS_MEDIA_FIBRE_LONG 0x04
+
+struct qeth_query_oat_physical_if {
+ u8 res_head[33];
+ u8 speed_duplex;
+ u8 media_type;
+ u8 res_tail[29];
+};
+
+#define QETH_QOAT_REPLY_TYPE_PHYS_IF 0x0004
+
+struct qeth_query_oat_reply {
+ u16 type;
+ u16 length;
+ u16 version;
+ u8 res[10];
+ struct qeth_query_oat_physical_if phys_if;
+};
+
+#define QETH_QOAT_SCOPE_INTERFACE 0x00000001
+
struct qeth_query_oat {
- __u32 subcmd_code;
- __u8 reserved[12];
+ u32 subcmd_code;
+ u8 reserved[12];
+ struct qeth_query_oat_reply reply[];
} __packed;
struct qeth_qoat_priv {
diff --git a/drivers/s390/net/qeth_ethtool.c b/drivers/s390/net/qeth_ethtool.c
index b5caa723326e..3a51bbff0ffe 100644
--- a/drivers/s390/net/qeth_ethtool.c
+++ b/drivers/s390/net/qeth_ethtool.c
@@ -324,8 +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_cmd_adv_sup(struct ethtool_link_ksettings *cmd,
- int maxspeed, int porttype)
+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);
@@ -334,186 +334,119 @@ static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd,
ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
- switch (porttype) {
+ switch (cmd->base.port) {
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:
- ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
- ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
- WARN_ON_ONCE(1);
- }
- /* partially does fall through, to also select lower speeds */
- switch (maxspeed) {
- 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:
- 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);
- WARN_ON_ONCE(1);
+ break;
}
}
-
static int qeth_get_link_ksettings(struct net_device *netdev,
struct ethtool_link_ksettings *cmd)
{
struct qeth_card *card = netdev->ml_priv;
- enum qeth_link_types link_type;
- struct carrier_info carrier_info;
- int rc;
+ struct qeth_link_info link_info;
- if (IS_IQD(card) || IS_VM_NIC(card))
- link_type = QETH_LINK_TYPE_10GBIT_ETH;
- else
- link_type = card->info.link_type;
-
- cmd->base.duplex = DUPLEX_FULL;
+ cmd->base.speed = card->info.link_info.speed;
+ cmd->base.duplex = card->info.link_info.duplex;
+ cmd->base.port = card->info.link_info.port;
cmd->base.autoneg = AUTONEG_ENABLE;
cmd->base.phy_address = 0;
cmd->base.mdio_support = 0;
cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID;
cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID;
- switch (link_type) {
- case QETH_LINK_TYPE_FAST_ETH:
- case QETH_LINK_TYPE_LANE_ETH100:
- cmd->base.speed = SPEED_100;
- cmd->base.port = PORT_TP;
- break;
- case QETH_LINK_TYPE_GBIT_ETH:
- case QETH_LINK_TYPE_LANE_ETH1000:
- cmd->base.speed = SPEED_1000;
- cmd->base.port = PORT_FIBRE;
- break;
- case QETH_LINK_TYPE_10GBIT_ETH:
- cmd->base.speed = SPEED_10000;
- cmd->base.port = PORT_FIBRE;
- break;
- case QETH_LINK_TYPE_25GBIT_ETH:
- cmd->base.speed = SPEED_25000;
- cmd->base.port = PORT_FIBRE;
- break;
- default:
- cmd->base.speed = SPEED_10;
- cmd->base.port = PORT_TP;
- }
- qeth_set_cmd_adv_sup(cmd, cmd->base.speed, cmd->base.port);
-
/* Check if we can obtain more accurate information. */
- /* If QUERY_CARD_INFO command is not supported or fails, */
- /* just return the heuristics that was filled above. */
- rc = qeth_query_card_info(card, &carrier_info);
- if (rc == -EOPNOTSUPP) /* for old hardware, return heuristic */
- return 0;
- if (rc) /* report error from the hardware operation */
- return rc;
- /* on success, fill in the information got from the hardware */
-
- netdev_dbg(netdev,
- "card info: card_type=0x%02x, port_mode=0x%04x, port_speed=0x%08x\n",
- carrier_info.card_type,
- carrier_info.port_mode,
- carrier_info.port_speed);
-
- /* Update attributes for which we've obtained more authoritative */
- /* information, leave the rest the way they where filled above. */
- switch (carrier_info.card_type) {
- case CARD_INFO_TYPE_1G_COPPER_A:
- case CARD_INFO_TYPE_1G_COPPER_B:
- cmd->base.port = PORT_TP;
- qeth_set_cmd_adv_sup(cmd, SPEED_1000, cmd->base.port);
- break;
- case CARD_INFO_TYPE_1G_FIBRE_A:
- case CARD_INFO_TYPE_1G_FIBRE_B:
- cmd->base.port = PORT_FIBRE;
- qeth_set_cmd_adv_sup(cmd, SPEED_1000, cmd->base.port);
- break;
- case CARD_INFO_TYPE_10G_FIBRE_A:
- case CARD_INFO_TYPE_10G_FIBRE_B:
- cmd->base.port = PORT_FIBRE;
- qeth_set_cmd_adv_sup(cmd, SPEED_10000, cmd->base.port);
- break;
- }
-
- switch (carrier_info.port_mode) {
- case CARD_INFO_PORTM_FULLDUPLEX:
- cmd->base.duplex = DUPLEX_FULL;
- break;
- case CARD_INFO_PORTM_HALFDUPLEX:
- cmd->base.duplex = DUPLEX_HALF;
- break;
+ if (!qeth_query_card_info(card, &link_info)) {
+ if (link_info.speed != SPEED_UNKNOWN)
+ cmd->base.speed = link_info.speed;
+ if (link_info.duplex != DUPLEX_UNKNOWN)
+ cmd->base.duplex = link_info.duplex;
+ if (link_info.port != PORT_OTHER)
+ cmd->base.port = link_info.port;
}
- switch (carrier_info.port_speed) {
- case CARD_INFO_PORTS_10M:
- cmd->base.speed = SPEED_10;
- break;
- case CARD_INFO_PORTS_100M:
- cmd->base.speed = SPEED_100;
- break;
- case CARD_INFO_PORTS_1G:
- cmd->base.speed = SPEED_1000;
- break;
- case CARD_INFO_PORTS_10G:
- cmd->base.speed = SPEED_10000;
- break;
- case CARD_INFO_PORTS_25G:
- cmd->base.speed = SPEED_25000;
- break;
- }
+ qeth_set_ethtool_link_modes(cmd, card->info.link_info.link_mode);
return 0;
}
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 28f6dda95736..daeb837abec3 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -737,8 +737,6 @@ static void qeth_l2_dev2br_an_set_cb(void *priv,
*
* On enable, emits a series of address notifications for all
* currently registered hosts.
- *
- * Must be called under rtnl_lock
*/
static int qeth_l2_dev2br_an_set(struct qeth_card *card, bool enable)
{
@@ -1289,16 +1287,19 @@ static void qeth_l2_dev2br_worker(struct work_struct *work)
if (READ_ONCE(card->info.pnso_mode) == QETH_PNSO_NONE)
goto free;
- /* Potential re-config in progress, try again later: */
- if (!rtnl_trylock()) {
- queue_delayed_work(card->event_wq, dwork,
- msecs_to_jiffies(100));
- return;
- }
- if (!netif_device_present(card->dev))
- goto out_unlock;
-
if (data->ac_event.lost_event_mask) {
+ /* Potential re-config in progress, try again later: */
+ if (!rtnl_trylock()) {
+ queue_delayed_work(card->event_wq, dwork,
+ msecs_to_jiffies(100));
+ return;
+ }
+
+ if (!netif_device_present(card->dev)) {
+ rtnl_unlock();
+ goto free;
+ }
+
QETH_DBF_MESSAGE(3,
"Address change notification overflow on device %x\n",
CARD_DEVID(card));
@@ -1328,6 +1329,8 @@ static void qeth_l2_dev2br_worker(struct work_struct *work)
"Address Notification resynced on device %x\n",
CARD_DEVID(card));
}
+
+ rtnl_unlock();
} else {
for (i = 0; i < data->ac_event.num_entries; i++) {
struct qeth_ipacmd_addr_change_entry *entry =
@@ -1339,9 +1342,6 @@ static void qeth_l2_dev2br_worker(struct work_struct *work)
}
}
-out_unlock:
- rtnl_unlock();
-
free:
kfree(data);
}
@@ -2310,11 +2310,8 @@ static void qeth_l2_set_offline(struct qeth_card *card)
card->state = CARD_STATE_DOWN;
qeth_l2_set_pnso_mode(card, QETH_PNSO_NONE);
- if (priv->brport_features & BR_LEARNING_SYNC) {
- rtnl_lock();
+ if (priv->brport_features & BR_LEARNING_SYNC)
qeth_l2_dev2br_fdb_flush(card);
- rtnl_unlock();
- }
}
/* Returns zero if the command is successfully "consumed" */
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index b1c1d2510d55..264b6c782382 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -104,10 +104,7 @@ static bool qeth_l3_is_addr_covered_by_ipato(struct qeth_card *card,
qeth_l3_convert_addr_to_bits(ipatoe->addr, ipatoe_bits,
(ipatoe->proto == QETH_PROT_IPV4) ?
4 : 16);
- if (addr->proto == QETH_PROT_IPV4)
- rc = !memcmp(addr_bits, ipatoe_bits, ipatoe->mask_bits);
- else
- rc = !memcmp(addr_bits, ipatoe_bits, ipatoe->mask_bits);
+ rc = !memcmp(addr_bits, ipatoe_bits, ipatoe->mask_bits);
if (rc)
break;
}