diff options
author | Eugene Crosser <Eugene.Crosser@ru.ibm.com> | 2013-12-16 03:44:52 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-12-17 17:17:13 -0500 |
commit | 02d5cb5bb20b9d34db20860aad1891cd9b8e81d5 (patch) | |
tree | 635e3fa86c4d23ed682f0e9daf9f8468964e3fc9 | |
parent | d239ae339e0740d2405f4d8a4d482dbe7b001c69 (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>
-rw-r--r-- | drivers/s390/net/qeth_core.h | 8 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_main.c | 198 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_mpc.h | 28 |
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 | ||
741 | struct 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 | ||
743 | struct qeth_card { | 749 | struct qeth_card { |
@@ -914,6 +920,8 @@ struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *); | |||
914 | int qeth_mdio_read(struct net_device *, int, int); | 920 | int qeth_mdio_read(struct net_device *, int, int); |
915 | int qeth_snmp_command(struct qeth_card *, char __user *); | 921 | int qeth_snmp_command(struct qeth_card *, char __user *); |
916 | int qeth_query_oat_command(struct qeth_card *, char __user *); | 922 | 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); | ||
917 | int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *, | 925 | int 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 | } |
4603 | EXPORT_SYMBOL_GPL(qeth_query_oat_command); | 4603 | EXPORT_SYMBOL_GPL(qeth_query_oat_command); |
4604 | 4604 | ||
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 | |||
4605 | static inline int qeth_get_qdio_q_format(struct qeth_card *card) | 4641 | static 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 | } |
5607 | EXPORT_SYMBOL_GPL(qeth_core_get_drvinfo); | 5643 | EXPORT_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. */ | ||
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 | |||
5609 | int qeth_core_ethtool_get_settings(struct net_device *netdev, | 5698 | int 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 | } |
5697 | EXPORT_SYMBOL_GPL(qeth_core_ethtool_get_settings); | 5799 | EXPORT_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 | 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 | }; | ||
278 | 295 | ||
279 | /* (SET)DELIP(M) IPA stuff ***************************************************/ | 296 | /* (SET)DELIP(M) IPA stuff ***************************************************/ |
280 | struct qeth_ipacmd_setdelip4 { | 297 | struct qeth_ipacmd_setdelip4 { |
@@ -404,6 +421,14 @@ struct qeth_qoat_priv { | |||
404 | char *buffer; | 421 | char *buffer; |
405 | }; | 422 | }; |
406 | 423 | ||
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 | |||
407 | struct qeth_ipacmd_setadpparms_hdr { | 432 | struct 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)); |