Commit 4139b2b1 authored by Julian Wiedmann's avatar Julian Wiedmann Committed by Jakub Kicinski

s390/qeth: improve QUERY CARD INFO processing

Move all the HW reply data parsing into qeth_query_card_info_cb(), and
use common ethtool enums for transporting the information back to the
caller.

Also only look at the .port_speed field when we couldn't determine the
speed from the .card_type field, and introduce some 'default' cases for
SPEED_UNKNOWN, PORT_OTHER and DUPLEX_UNKNOWN.
Signed-off-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 88ad4d9b
...@@ -701,6 +701,12 @@ enum qeth_pnso_mode { ...@@ -701,6 +701,12 @@ enum qeth_pnso_mode {
QETH_PNSO_ADDR_INFO, QETH_PNSO_ADDR_INFO,
}; };
struct qeth_link_info {
u32 speed;
u8 duplex;
u8 port;
};
#define QETH_BROADCAST_WITH_ECHO 0x01 #define QETH_BROADCAST_WITH_ECHO 0x01
#define QETH_BROADCAST_WITHOUT_ECHO 0x02 #define QETH_BROADCAST_WITHOUT_ECHO 0x02
struct qeth_card_info { struct qeth_card_info {
...@@ -796,12 +802,6 @@ struct qeth_rx { ...@@ -796,12 +802,6 @@ struct qeth_rx {
u8 bufs_refill; u8 bufs_refill;
}; };
struct carrier_info {
__u8 card_type;
__u16 port_mode;
__u32 port_speed;
};
struct qeth_switch_info { struct qeth_switch_info {
__u32 capabilities; __u32 capabilities;
__u32 settings; __u32 settings;
...@@ -1108,7 +1108,7 @@ void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, ...@@ -1108,7 +1108,7 @@ void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
int qeth_query_switch_attributes(struct qeth_card *card, int qeth_query_switch_attributes(struct qeth_card *card,
struct qeth_switch_info *sw_info); struct qeth_switch_info *sw_info);
int qeth_query_card_info(struct qeth_card *card, 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, int qeth_setadpparms_set_access_ctrl(struct qeth_card *card,
enum qeth_ipa_isolation_modes mode); enum qeth_ipa_isolation_modes mode);
......
...@@ -4868,8 +4868,8 @@ static int qeth_query_oat_command(struct qeth_card *card, char __user *udata) ...@@ -4868,8 +4868,8 @@ static int qeth_query_oat_command(struct qeth_card *card, char __user *udata)
static int qeth_query_card_info_cb(struct qeth_card *card, static int qeth_query_card_info_cb(struct qeth_card *card,
struct qeth_reply *reply, unsigned long data) 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_ipa_cmd *cmd = (struct qeth_ipa_cmd *)data;
struct qeth_link_info *link_info = reply->param;
struct qeth_query_card_info *card_info; struct qeth_query_card_info *card_info;
QETH_CARD_TEXT(card, 2, "qcrdincb"); QETH_CARD_TEXT(card, 2, "qcrdincb");
...@@ -4877,14 +4877,67 @@ static int qeth_query_card_info_cb(struct qeth_card *card, ...@@ -4877,14 +4877,67 @@ static int qeth_query_card_info_cb(struct qeth_card *card,
return -EIO; return -EIO;
card_info = &cmd->data.setadapterparms.data.card_info; card_info = &cmd->data.setadapterparms.data.card_info;
carrier_info->card_type = card_info->card_type; netdev_dbg(card->dev,
carrier_info->port_mode = card_info->port_mode; "card info: card_type=0x%02x, port_mode=0x%04x, port_speed=0x%08x\n",
carrier_info->port_speed = card_info->port_speed; 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; return 0;
} }
int qeth_query_card_info(struct qeth_card *card, 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; struct qeth_cmd_buffer *iob;
...@@ -4894,8 +4947,8 @@ int qeth_query_card_info(struct qeth_card *card, ...@@ -4894,8 +4947,8 @@ int qeth_query_card_info(struct qeth_card *card,
iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_CARD_INFO, 0); iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_CARD_INFO, 0);
if (!iob) if (!iob)
return -ENOMEM; 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);
} }
/** /**
......
...@@ -324,8 +324,7 @@ static int qeth_set_per_queue_coalesce(struct net_device *dev, u32 queue, ...@@ -324,8 +324,7 @@ static int qeth_set_per_queue_coalesce(struct net_device *dev, u32 queue,
/* Autoneg and full-duplex are supported and advertised unconditionally. */ /* Autoneg and full-duplex are supported and advertised unconditionally. */
/* Always advertise and support all speeds up to specified, and only one */ /* Always advertise and support all speeds up to specified, and only one */
/* specified port type. */ /* specified port type. */
static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd, static void qeth_set_ethtool_link_modes(struct ethtool_link_ksettings *cmd)
int maxspeed, int porttype)
{ {
ethtool_link_ksettings_zero_link_mode(cmd, supported); ethtool_link_ksettings_zero_link_mode(cmd, supported);
ethtool_link_ksettings_zero_link_mode(cmd, advertising); ethtool_link_ksettings_zero_link_mode(cmd, advertising);
...@@ -334,7 +333,7 @@ static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd, ...@@ -334,7 +333,7 @@ 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, supported, Autoneg);
ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg); ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
switch (porttype) { switch (cmd->base.port) {
case PORT_TP: case PORT_TP:
ethtool_link_ksettings_add_link_mode(cmd, supported, TP); ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
ethtool_link_ksettings_add_link_mode(cmd, advertising, TP); ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
...@@ -350,7 +349,7 @@ static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd, ...@@ -350,7 +349,7 @@ static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd,
} }
/* partially does fall through, to also select lower speeds */ /* partially does fall through, to also select lower speeds */
switch (maxspeed) { switch (cmd->base.speed) {
case SPEED_25000: case SPEED_25000:
ethtool_link_ksettings_add_link_mode(cmd, supported, ethtool_link_ksettings_add_link_mode(cmd, supported,
25000baseSR_Full); 25000baseSR_Full);
...@@ -406,13 +405,12 @@ static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd, ...@@ -406,13 +405,12 @@ static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd,
} }
} }
static int qeth_get_link_ksettings(struct net_device *netdev, static int qeth_get_link_ksettings(struct net_device *netdev,
struct ethtool_link_ksettings *cmd) struct ethtool_link_ksettings *cmd)
{ {
struct qeth_card *card = netdev->ml_priv; struct qeth_card *card = netdev->ml_priv;
struct qeth_link_info link_info;
enum qeth_link_types link_type; enum qeth_link_types link_type;
struct carrier_info carrier_info;
if (IS_IQD(card) || IS_VM_NIC(card)) if (IS_IQD(card) || IS_VM_NIC(card))
link_type = QETH_LINK_TYPE_10GBIT_ETH; link_type = QETH_LINK_TYPE_10GBIT_ETH;
...@@ -449,66 +447,18 @@ static int qeth_get_link_ksettings(struct net_device *netdev, ...@@ -449,66 +447,18 @@ static int qeth_get_link_ksettings(struct net_device *netdev,
cmd->base.speed = SPEED_10; cmd->base.speed = SPEED_10;
cmd->base.port = PORT_TP; 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. */ /* Check if we can obtain more accurate information. */
/* If QUERY_CARD_INFO command is not supported or fails, */ if (!qeth_query_card_info(card, &link_info)) {
/* just return the heuristics that was filled above. */ if (link_info.speed != SPEED_UNKNOWN)
if (qeth_query_card_info(card, &carrier_info)) cmd->base.speed = link_info.speed;
return 0; if (link_info.duplex != DUPLEX_UNKNOWN)
cmd->base.duplex = link_info.duplex;
netdev_dbg(netdev, if (link_info.port != PORT_OTHER)
"card info: card_type=0x%02x, port_mode=0x%04x, port_speed=0x%08x\n", cmd->base.port = link_info.port;
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) { qeth_set_ethtool_link_modes(cmd);
case CARD_INFO_PORTM_FULLDUPLEX:
cmd->base.duplex = DUPLEX_FULL;
break;
case CARD_INFO_PORTM_HALFDUPLEX:
cmd->base.duplex = DUPLEX_HALF;
break;
}
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;
}
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment