Skip to content

Commit 02d5cb5

Browse files
Eugene Crosserdavem330
authored andcommitted
qeth: Accurate ethtool output
For OSA devices that support the QUERY_CARD_INFO command, supply accurate data based on the card type, port mode and link speed via the 'ethtool' interface. Signed-off-by: Eugene Crosser <Eugene.Crosser@ru.ibm.com> Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent d239ae3 commit 02d5cb5

File tree

3 files changed

+185
-49
lines changed

3 files changed

+185
-49
lines changed

drivers/s390/net/qeth_core.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,12 @@ struct qeth_rx {
738738
int qdio_err;
739739
};
740740

741+
struct carrier_info {
742+
__u8 card_type;
743+
__u16 port_mode;
744+
__u32 port_speed;
745+
};
746+
741747
#define QETH_NAPI_WEIGHT NAPI_POLL_WEIGHT
742748

743749
struct qeth_card {
@@ -914,6 +920,8 @@ struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *);
914920
int qeth_mdio_read(struct net_device *, int, int);
915921
int qeth_snmp_command(struct qeth_card *, char __user *);
916922
int qeth_query_oat_command(struct qeth_card *, char __user *);
923+
int qeth_query_card_info(struct qeth_card *card,
924+
struct carrier_info *carrier_info);
917925
int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *,
918926
int (*reply_cb)(struct qeth_card *, struct qeth_reply*, unsigned long),
919927
void *reply_param);

drivers/s390/net/qeth_core_main.c

Lines changed: 150 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4602,6 +4602,42 @@ int qeth_query_oat_command(struct qeth_card *card, char __user *udata)
46024602
}
46034603
EXPORT_SYMBOL_GPL(qeth_query_oat_command);
46044604

4605+
int qeth_query_card_info_cb(struct qeth_card *card,
4606+
struct qeth_reply *reply, unsigned long data)
4607+
{
4608+
struct qeth_ipa_cmd *cmd;
4609+
struct qeth_query_card_info *card_info;
4610+
struct carrier_info *carrier_info;
4611+
4612+
QETH_CARD_TEXT(card, 2, "qcrdincb");
4613+
carrier_info = (struct carrier_info *)reply->param;
4614+
cmd = (struct qeth_ipa_cmd *)data;
4615+
card_info = &cmd->data.setadapterparms.data.card_info;
4616+
if (cmd->data.setadapterparms.hdr.return_code == 0) {
4617+
carrier_info->card_type = card_info->card_type;
4618+
carrier_info->port_mode = card_info->port_mode;
4619+
carrier_info->port_speed = card_info->port_speed;
4620+
}
4621+
4622+
qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
4623+
return 0;
4624+
}
4625+
4626+
int qeth_query_card_info(struct qeth_card *card,
4627+
struct carrier_info *carrier_info)
4628+
{
4629+
struct qeth_cmd_buffer *iob;
4630+
4631+
QETH_CARD_TEXT(card, 2, "qcrdinfo");
4632+
if (!qeth_adp_supported(card, IPA_SETADP_QUERY_CARD_INFO))
4633+
return -EOPNOTSUPP;
4634+
iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_CARD_INFO,
4635+
sizeof(struct qeth_ipacmd_setadpparms_hdr));
4636+
return qeth_send_ipa_cmd(card, iob, qeth_query_card_info_cb,
4637+
(void *)carrier_info);
4638+
}
4639+
EXPORT_SYMBOL_GPL(qeth_query_card_info);
4640+
46054641
static inline int qeth_get_qdio_q_format(struct qeth_card *card)
46064642
{
46074643
switch (card->info.type) {
@@ -5606,92 +5642,158 @@ void qeth_core_get_drvinfo(struct net_device *dev,
56065642
}
56075643
EXPORT_SYMBOL_GPL(qeth_core_get_drvinfo);
56085644

5645+
/* Helper function to fill 'advertizing' and 'supported' which are the same. */
5646+
/* Autoneg and full-duplex are supported and advertized uncondionally. */
5647+
/* Always advertize and support all speeds up to specified, and only one */
5648+
/* specified port type. */
5649+
static void qeth_set_ecmd_adv_sup(struct ethtool_cmd *ecmd,
5650+
int maxspeed, int porttype)
5651+
{
5652+
int port_sup, port_adv, spd_sup, spd_adv;
5653+
5654+
switch (porttype) {
5655+
case PORT_TP:
5656+
port_sup = SUPPORTED_TP;
5657+
port_adv = ADVERTISED_TP;
5658+
break;
5659+
case PORT_FIBRE:
5660+
port_sup = SUPPORTED_FIBRE;
5661+
port_adv = ADVERTISED_FIBRE;
5662+
break;
5663+
default:
5664+
port_sup = SUPPORTED_TP;
5665+
port_adv = ADVERTISED_TP;
5666+
WARN_ON_ONCE(1);
5667+
}
5668+
5669+
/* "Fallthrough" case'es ordered from high to low result in setting */
5670+
/* flags cumulatively, starting from the specified speed and down to */
5671+
/* the lowest possible. */
5672+
spd_sup = 0;
5673+
spd_adv = 0;
5674+
switch (maxspeed) {
5675+
case SPEED_10000:
5676+
spd_sup |= SUPPORTED_10000baseT_Full;
5677+
spd_adv |= ADVERTISED_10000baseT_Full;
5678+
case SPEED_1000:
5679+
spd_sup |= SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full;
5680+
spd_adv |= ADVERTISED_1000baseT_Half |
5681+
ADVERTISED_1000baseT_Full;
5682+
case SPEED_100:
5683+
spd_sup |= SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full;
5684+
spd_adv |= ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full;
5685+
case SPEED_10:
5686+
spd_sup |= SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full;
5687+
spd_adv |= ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full;
5688+
break;
5689+
default:
5690+
spd_sup = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full;
5691+
spd_adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full;
5692+
WARN_ON_ONCE(1);
5693+
}
5694+
ecmd->advertising = ADVERTISED_Autoneg | port_adv | spd_adv;
5695+
ecmd->supported = SUPPORTED_Autoneg | port_sup | spd_sup;
5696+
}
5697+
56095698
int qeth_core_ethtool_get_settings(struct net_device *netdev,
56105699
struct ethtool_cmd *ecmd)
56115700
{
56125701
struct qeth_card *card = netdev->ml_priv;
56135702
enum qeth_link_types link_type;
5703+
struct carrier_info carrier_info;
56145704

56155705
if ((card->info.type == QETH_CARD_TYPE_IQD) || (card->info.guestlan))
56165706
link_type = QETH_LINK_TYPE_10GBIT_ETH;
56175707
else
56185708
link_type = card->info.link_type;
56195709

56205710
ecmd->transceiver = XCVR_INTERNAL;
5621-
ecmd->supported = SUPPORTED_Autoneg;
5622-
ecmd->advertising = ADVERTISED_Autoneg;
56235711
ecmd->duplex = DUPLEX_FULL;
56245712
ecmd->autoneg = AUTONEG_ENABLE;
56255713

56265714
switch (link_type) {
56275715
case QETH_LINK_TYPE_FAST_ETH:
56285716
case QETH_LINK_TYPE_LANE_ETH100:
5629-
ecmd->supported |= SUPPORTED_10baseT_Half |
5630-
SUPPORTED_10baseT_Full |
5631-
SUPPORTED_100baseT_Half |
5632-
SUPPORTED_100baseT_Full |
5633-
SUPPORTED_TP;
5634-
ecmd->advertising |= ADVERTISED_10baseT_Half |
5635-
ADVERTISED_10baseT_Full |
5636-
ADVERTISED_100baseT_Half |
5637-
ADVERTISED_100baseT_Full |
5638-
ADVERTISED_TP;
5717+
qeth_set_ecmd_adv_sup(ecmd, SPEED_100, PORT_TP);
56395718
ecmd->speed = SPEED_100;
56405719
ecmd->port = PORT_TP;
56415720
break;
56425721

56435722
case QETH_LINK_TYPE_GBIT_ETH:
56445723
case QETH_LINK_TYPE_LANE_ETH1000:
5645-
ecmd->supported |= SUPPORTED_10baseT_Half |
5646-
SUPPORTED_10baseT_Full |
5647-
SUPPORTED_100baseT_Half |
5648-
SUPPORTED_100baseT_Full |
5649-
SUPPORTED_1000baseT_Half |
5650-
SUPPORTED_1000baseT_Full |
5651-
SUPPORTED_FIBRE;
5652-
ecmd->advertising |= ADVERTISED_10baseT_Half |
5653-
ADVERTISED_10baseT_Full |
5654-
ADVERTISED_100baseT_Half |
5655-
ADVERTISED_100baseT_Full |
5656-
ADVERTISED_1000baseT_Half |
5657-
ADVERTISED_1000baseT_Full |
5658-
ADVERTISED_FIBRE;
5724+
qeth_set_ecmd_adv_sup(ecmd, SPEED_1000, PORT_FIBRE);
56595725
ecmd->speed = SPEED_1000;
56605726
ecmd->port = PORT_FIBRE;
56615727
break;
56625728

56635729
case QETH_LINK_TYPE_10GBIT_ETH:
5664-
ecmd->supported |= SUPPORTED_10baseT_Half |
5665-
SUPPORTED_10baseT_Full |
5666-
SUPPORTED_100baseT_Half |
5667-
SUPPORTED_100baseT_Full |
5668-
SUPPORTED_1000baseT_Half |
5669-
SUPPORTED_1000baseT_Full |
5670-
SUPPORTED_10000baseT_Full |
5671-
SUPPORTED_FIBRE;
5672-
ecmd->advertising |= ADVERTISED_10baseT_Half |
5673-
ADVERTISED_10baseT_Full |
5674-
ADVERTISED_100baseT_Half |
5675-
ADVERTISED_100baseT_Full |
5676-
ADVERTISED_1000baseT_Half |
5677-
ADVERTISED_1000baseT_Full |
5678-
ADVERTISED_10000baseT_Full |
5679-
ADVERTISED_FIBRE;
5730+
qeth_set_ecmd_adv_sup(ecmd, SPEED_10000, PORT_FIBRE);
56805731
ecmd->speed = SPEED_10000;
56815732
ecmd->port = PORT_FIBRE;
56825733
break;
56835734

56845735
default:
5685-
ecmd->supported |= SUPPORTED_10baseT_Half |
5686-
SUPPORTED_10baseT_Full |
5687-
SUPPORTED_TP;
5688-
ecmd->advertising |= ADVERTISED_10baseT_Half |
5689-
ADVERTISED_10baseT_Full |
5690-
ADVERTISED_TP;
5736+
qeth_set_ecmd_adv_sup(ecmd, SPEED_10, PORT_TP);
56915737
ecmd->speed = SPEED_10;
56925738
ecmd->port = PORT_TP;
56935739
}
56945740

5741+
/* Check if we can obtain more accurate information. */
5742+
/* If QUERY_CARD_INFO command is not supported or fails, */
5743+
/* just return the heuristics that was filled above. */
5744+
if (qeth_query_card_info(card, &carrier_info) != 0)
5745+
return 0;
5746+
5747+
netdev_dbg(netdev,
5748+
"card info: card_type=0x%02x, port_mode=0x%04x, port_speed=0x%08x\n",
5749+
carrier_info.card_type,
5750+
carrier_info.port_mode,
5751+
carrier_info.port_speed);
5752+
5753+
/* Update attributes for which we've obtained more authoritative */
5754+
/* information, leave the rest the way they where filled above. */
5755+
switch (carrier_info.card_type) {
5756+
case CARD_INFO_TYPE_1G_COPPER_A:
5757+
case CARD_INFO_TYPE_1G_COPPER_B:
5758+
qeth_set_ecmd_adv_sup(ecmd, SPEED_1000, PORT_TP);
5759+
ecmd->port = PORT_TP;
5760+
break;
5761+
case CARD_INFO_TYPE_1G_FIBRE_A:
5762+
case CARD_INFO_TYPE_1G_FIBRE_B:
5763+
qeth_set_ecmd_adv_sup(ecmd, SPEED_1000, PORT_FIBRE);
5764+
ecmd->port = PORT_FIBRE;
5765+
break;
5766+
case CARD_INFO_TYPE_10G_FIBRE_A:
5767+
case CARD_INFO_TYPE_10G_FIBRE_B:
5768+
qeth_set_ecmd_adv_sup(ecmd, SPEED_10000, PORT_FIBRE);
5769+
ecmd->port = PORT_FIBRE;
5770+
break;
5771+
}
5772+
5773+
switch (carrier_info.port_mode) {
5774+
case CARD_INFO_PORTM_FULLDUPLEX:
5775+
ecmd->duplex = DUPLEX_FULL;
5776+
break;
5777+
case CARD_INFO_PORTM_HALFDUPLEX:
5778+
ecmd->duplex = DUPLEX_HALF;
5779+
break;
5780+
}
5781+
5782+
switch (carrier_info.port_speed) {
5783+
case CARD_INFO_PORTS_10M:
5784+
ecmd->speed = SPEED_10;
5785+
break;
5786+
case CARD_INFO_PORTS_100M:
5787+
ecmd->speed = SPEED_100;
5788+
break;
5789+
case CARD_INFO_PORTS_1G:
5790+
ecmd->speed = SPEED_1000;
5791+
break;
5792+
case CARD_INFO_PORTS_10G:
5793+
ecmd->speed = SPEED_10000;
5794+
break;
5795+
}
5796+
56955797
return 0;
56965798
}
56975799
EXPORT_SYMBOL_GPL(qeth_core_ethtool_get_settings);

drivers/s390/net/qeth_core_mpc.h

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,24 @@ enum qeth_ipa_set_access_mode_rc {
274274
SET_ACCESS_CTRL_RC_REFLREL_FAILED = 0x0024,
275275
SET_ACCESS_CTRL_RC_REFLREL_DEACT_FAILED = 0x0028,
276276
};
277-
277+
enum qeth_card_info_card_type {
278+
CARD_INFO_TYPE_1G_COPPER_A = 0x61,
279+
CARD_INFO_TYPE_1G_FIBRE_A = 0x71,
280+
CARD_INFO_TYPE_10G_FIBRE_A = 0x91,
281+
CARD_INFO_TYPE_1G_COPPER_B = 0xb1,
282+
CARD_INFO_TYPE_1G_FIBRE_B = 0xa1,
283+
CARD_INFO_TYPE_10G_FIBRE_B = 0xc1,
284+
};
285+
enum qeth_card_info_port_mode {
286+
CARD_INFO_PORTM_HALFDUPLEX = 0x0002,
287+
CARD_INFO_PORTM_FULLDUPLEX = 0x0003,
288+
};
289+
enum qeth_card_info_port_speed {
290+
CARD_INFO_PORTS_10M = 0x00000005,
291+
CARD_INFO_PORTS_100M = 0x00000006,
292+
CARD_INFO_PORTS_1G = 0x00000007,
293+
CARD_INFO_PORTS_10G = 0x00000008,
294+
};
278295

279296
/* (SET)DELIP(M) IPA stuff ***************************************************/
280297
struct qeth_ipacmd_setdelip4 {
@@ -404,6 +421,14 @@ struct qeth_qoat_priv {
404421
char *buffer;
405422
};
406423

424+
struct qeth_query_card_info {
425+
__u8 card_type;
426+
__u8 reserved1;
427+
__u16 port_mode;
428+
__u32 port_speed;
429+
__u32 reserved2;
430+
};
431+
407432
struct qeth_ipacmd_setadpparms_hdr {
408433
__u32 supp_hw_cmds;
409434
__u32 reserved1;
@@ -424,6 +449,7 @@ struct qeth_ipacmd_setadpparms {
424449
struct qeth_snmp_cmd snmp;
425450
struct qeth_set_access_ctrl set_access_ctrl;
426451
struct qeth_query_oat query_oat;
452+
struct qeth_query_card_info card_info;
427453
__u32 mode;
428454
} data;
429455
} __attribute__ ((packed));

0 commit comments

Comments
 (0)