aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorEugene Crosser <Eugene.Crosser@ru.ibm.com>2013-12-16 03:44:52 -0500
committerDavid S. Miller <davem@davemloft.net>2013-12-17 17:17:13 -0500
commit02d5cb5bb20b9d34db20860aad1891cd9b8e81d5 (patch)
tree635e3fa86c4d23ed682f0e9daf9f8468964e3fc9 /drivers/s390
parentd239ae339e0740d2405f4d8a4d482dbe7b001c69 (diff)
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>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/net/qeth_core.h8
-rw-r--r--drivers/s390/net/qeth_core_main.c198
-rw-r--r--drivers/s390/net/qeth_core_mpc.h28
3 files changed, 185 insertions, 49 deletions
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 41ef94320ee8..d45427c553b0 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -738,6 +738,12 @@ struct qeth_rx {
738 int qdio_err; 738 int qdio_err;
739}; 739};
740 740
741struct carrier_info {
742 __u8 card_type;
743 __u16 port_mode;
744 __u32 port_speed;
745};
746
741#define QETH_NAPI_WEIGHT NAPI_POLL_WEIGHT 747#define QETH_NAPI_WEIGHT NAPI_POLL_WEIGHT
742 748
743struct qeth_card { 749struct qeth_card {
@@ -914,6 +920,8 @@ struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *);
914int qeth_mdio_read(struct net_device *, int, int); 920int qeth_mdio_read(struct net_device *, int, int);
915int qeth_snmp_command(struct qeth_card *, char __user *); 921int qeth_snmp_command(struct qeth_card *, char __user *);
916int qeth_query_oat_command(struct qeth_card *, char __user *); 922int qeth_query_oat_command(struct qeth_card *, char __user *);
923int qeth_query_card_info(struct qeth_card *card,
924 struct carrier_info *carrier_info);
917int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *, 925int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *,
918 int (*reply_cb)(struct qeth_card *, struct qeth_reply*, unsigned long), 926 int (*reply_cb)(struct qeth_card *, struct qeth_reply*, unsigned long),
919 void *reply_param); 927 void *reply_param);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index eb4e1f809feb..f9a85b47e3c3 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -4602,6 +4602,42 @@ out:
4602} 4602}
4603EXPORT_SYMBOL_GPL(qeth_query_oat_command); 4603EXPORT_SYMBOL_GPL(qeth_query_oat_command);
4604 4604
4605int 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
4626int 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}
4639EXPORT_SYMBOL_GPL(qeth_query_card_info);
4640
4605static inline int qeth_get_qdio_q_format(struct qeth_card *card) 4641static inline int qeth_get_qdio_q_format(struct qeth_card *card)
4606{ 4642{
4607 switch (card->info.type) { 4643 switch (card->info.type) {
@@ -5606,11 +5642,65 @@ void qeth_core_get_drvinfo(struct net_device *dev,
5606} 5642}
5607EXPORT_SYMBOL_GPL(qeth_core_get_drvinfo); 5643EXPORT_SYMBOL_GPL(qeth_core_get_drvinfo);
5608 5644
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. */
5649static 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
5609int qeth_core_ethtool_get_settings(struct net_device *netdev, 5698int qeth_core_ethtool_get_settings(struct net_device *netdev,
5610 struct ethtool_cmd *ecmd) 5699 struct ethtool_cmd *ecmd)
5611{ 5700{
5612 struct qeth_card *card = netdev->ml_priv; 5701 struct qeth_card *card = netdev->ml_priv;
5613 enum qeth_link_types link_type; 5702 enum qeth_link_types link_type;
5703 struct carrier_info carrier_info;
5614 5704
5615 if ((card->info.type == QETH_CARD_TYPE_IQD) || (card->info.guestlan)) 5705 if ((card->info.type == QETH_CARD_TYPE_IQD) || (card->info.guestlan))
5616 link_type = QETH_LINK_TYPE_10GBIT_ETH; 5706 link_type = QETH_LINK_TYPE_10GBIT_ETH;
@@ -5618,80 +5708,92 @@ int qeth_core_ethtool_get_settings(struct net_device *netdev,
5618 link_type = card->info.link_type; 5708 link_type = card->info.link_type;
5619 5709
5620 ecmd->transceiver = XCVR_INTERNAL; 5710 ecmd->transceiver = XCVR_INTERNAL;
5621 ecmd->supported = SUPPORTED_Autoneg;
5622 ecmd->advertising = ADVERTISED_Autoneg;
5623 ecmd->duplex = DUPLEX_FULL; 5711 ecmd->duplex = DUPLEX_FULL;
5624 ecmd->autoneg = AUTONEG_ENABLE; 5712 ecmd->autoneg = AUTONEG_ENABLE;
5625 5713
5626 switch (link_type) { 5714 switch (link_type) {
5627 case QETH_LINK_TYPE_FAST_ETH: 5715 case QETH_LINK_TYPE_FAST_ETH:
5628 case QETH_LINK_TYPE_LANE_ETH100: 5716 case QETH_LINK_TYPE_LANE_ETH100:
5629 ecmd->supported |= SUPPORTED_10baseT_Half | 5717 qeth_set_ecmd_adv_sup(ecmd, SPEED_100, PORT_TP);
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;
5639 ecmd->speed = SPEED_100; 5718 ecmd->speed = SPEED_100;
5640 ecmd->port = PORT_TP; 5719 ecmd->port = PORT_TP;
5641 break; 5720 break;
5642 5721
5643 case QETH_LINK_TYPE_GBIT_ETH: 5722 case QETH_LINK_TYPE_GBIT_ETH:
5644 case QETH_LINK_TYPE_LANE_ETH1000: 5723 case QETH_LINK_TYPE_LANE_ETH1000:
5645 ecmd->supported |= SUPPORTED_10baseT_Half | 5724 qeth_set_ecmd_adv_sup(ecmd, SPEED_1000, PORT_FIBRE);
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;
5659 ecmd->speed = SPEED_1000; 5725 ecmd->speed = SPEED_1000;
5660 ecmd->port = PORT_FIBRE; 5726 ecmd->port = PORT_FIBRE;
5661 break; 5727 break;
5662 5728
5663 case QETH_LINK_TYPE_10GBIT_ETH: 5729 case QETH_LINK_TYPE_10GBIT_ETH:
5664 ecmd->supported |= SUPPORTED_10baseT_Half | 5730 qeth_set_ecmd_adv_sup(ecmd, SPEED_10000, PORT_FIBRE);
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;
5680 ecmd->speed = SPEED_10000; 5731 ecmd->speed = SPEED_10000;
5681 ecmd->port = PORT_FIBRE; 5732 ecmd->port = PORT_FIBRE;
5682 break; 5733 break;
5683 5734
5684 default: 5735 default:
5685 ecmd->supported |= SUPPORTED_10baseT_Half | 5736 qeth_set_ecmd_adv_sup(ecmd, SPEED_10, PORT_TP);
5686 SUPPORTED_10baseT_Full |
5687 SUPPORTED_TP;
5688 ecmd->advertising |= ADVERTISED_10baseT_Half |
5689 ADVERTISED_10baseT_Full |
5690 ADVERTISED_TP;
5691 ecmd->speed = SPEED_10; 5737 ecmd->speed = SPEED_10;
5692 ecmd->port = PORT_TP; 5738 ecmd->port = PORT_TP;
5693 } 5739 }
5694 5740
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
5695 return 0; 5797 return 0;
5696} 5798}
5697EXPORT_SYMBOL_GPL(qeth_core_ethtool_get_settings); 5799EXPORT_SYMBOL_GPL(qeth_core_ethtool_get_settings);
diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h
index 07085d55f9a1..0a6e695578cd 100644
--- a/drivers/s390/net/qeth_core_mpc.h
+++ b/drivers/s390/net/qeth_core_mpc.h
@@ -274,7 +274,24 @@ enum qeth_ipa_set_access_mode_rc {
274 SET_ACCESS_CTRL_RC_REFLREL_FAILED = 0x0024, 274 SET_ACCESS_CTRL_RC_REFLREL_FAILED = 0x0024,
275 SET_ACCESS_CTRL_RC_REFLREL_DEACT_FAILED = 0x0028, 275 SET_ACCESS_CTRL_RC_REFLREL_DEACT_FAILED = 0x0028,
276}; 276};
277 277enum 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};
285enum qeth_card_info_port_mode {
286 CARD_INFO_PORTM_HALFDUPLEX = 0x0002,
287 CARD_INFO_PORTM_FULLDUPLEX = 0x0003,
288};
289enum 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};
278 295
279/* (SET)DELIP(M) IPA stuff ***************************************************/ 296/* (SET)DELIP(M) IPA stuff ***************************************************/
280struct qeth_ipacmd_setdelip4 { 297struct qeth_ipacmd_setdelip4 {
@@ -404,6 +421,14 @@ struct qeth_qoat_priv {
404 char *buffer; 421 char *buffer;
405}; 422};
406 423
424struct qeth_query_card_info {
425 __u8 card_type;
426 __u8 reserved1;
427 __u16 port_mode;
428 __u32 port_speed;
429 __u32 reserved2;
430};
431
407struct qeth_ipacmd_setadpparms_hdr { 432struct qeth_ipacmd_setadpparms_hdr {
408 __u32 supp_hw_cmds; 433 __u32 supp_hw_cmds;
409 __u32 reserved1; 434 __u32 reserved1;
@@ -424,6 +449,7 @@ struct qeth_ipacmd_setadpparms {
424 struct qeth_snmp_cmd snmp; 449 struct qeth_snmp_cmd snmp;
425 struct qeth_set_access_ctrl set_access_ctrl; 450 struct qeth_set_access_ctrl set_access_ctrl;
426 struct qeth_query_oat query_oat; 451 struct qeth_query_oat query_oat;
452 struct qeth_query_card_info card_info;
427 __u32 mode; 453 __u32 mode;
428 } data; 454 } data;
429} __attribute__ ((packed)); 455} __attribute__ ((packed));