0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/netdevice.h>
0012 #include <linux/ethtool.h>
0013 #include <linux/pci.h>
0014
0015 #include "spider_net.h"
0016
0017
0018 static struct {
0019 const char str[ETH_GSTRING_LEN];
0020 } ethtool_stats_keys[] = {
0021 { "tx_packets" },
0022 { "tx_bytes" },
0023 { "rx_packets" },
0024 { "rx_bytes" },
0025 { "tx_errors" },
0026 { "tx_dropped" },
0027 { "rx_dropped" },
0028 { "rx_descriptor_error" },
0029 { "tx_timeouts" },
0030 { "alloc_rx_skb_error" },
0031 { "rx_iommu_map_error" },
0032 { "tx_iommu_map_error" },
0033 { "rx_desc_unk_state" },
0034 };
0035
0036 static int
0037 spider_net_ethtool_get_link_ksettings(struct net_device *netdev,
0038 struct ethtool_link_ksettings *cmd)
0039 {
0040 struct spider_net_card *card;
0041 card = netdev_priv(netdev);
0042
0043 ethtool_link_ksettings_zero_link_mode(cmd, supported);
0044 ethtool_link_ksettings_add_link_mode(cmd, supported, 1000baseT_Full);
0045 ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
0046
0047 ethtool_link_ksettings_zero_link_mode(cmd, advertising);
0048 ethtool_link_ksettings_add_link_mode(cmd, advertising, 1000baseT_Full);
0049 ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);
0050
0051 cmd->base.port = PORT_FIBRE;
0052 cmd->base.speed = card->phy.speed;
0053 cmd->base.duplex = DUPLEX_FULL;
0054
0055 return 0;
0056 }
0057
0058 static void
0059 spider_net_ethtool_get_drvinfo(struct net_device *netdev,
0060 struct ethtool_drvinfo *drvinfo)
0061 {
0062 struct spider_net_card *card;
0063 card = netdev_priv(netdev);
0064
0065
0066 strlcpy(drvinfo->driver, spider_net_driver_name,
0067 sizeof(drvinfo->driver));
0068 strlcpy(drvinfo->version, VERSION, sizeof(drvinfo->version));
0069 strlcpy(drvinfo->fw_version, "no information",
0070 sizeof(drvinfo->fw_version));
0071 strlcpy(drvinfo->bus_info, pci_name(card->pdev),
0072 sizeof(drvinfo->bus_info));
0073 }
0074
0075 static void
0076 spider_net_ethtool_get_wol(struct net_device *netdev,
0077 struct ethtool_wolinfo *wolinfo)
0078 {
0079
0080 wolinfo->supported = 0;
0081 wolinfo->wolopts = 0;
0082 }
0083
0084 static u32
0085 spider_net_ethtool_get_msglevel(struct net_device *netdev)
0086 {
0087 struct spider_net_card *card;
0088 card = netdev_priv(netdev);
0089 return card->msg_enable;
0090 }
0091
0092 static void
0093 spider_net_ethtool_set_msglevel(struct net_device *netdev,
0094 u32 level)
0095 {
0096 struct spider_net_card *card;
0097 card = netdev_priv(netdev);
0098 card->msg_enable = level;
0099 }
0100
0101 static int
0102 spider_net_ethtool_nway_reset(struct net_device *netdev)
0103 {
0104 if (netif_running(netdev)) {
0105 spider_net_stop(netdev);
0106 spider_net_open(netdev);
0107 }
0108 return 0;
0109 }
0110
0111 static void
0112 spider_net_ethtool_get_ringparam(struct net_device *netdev,
0113 struct ethtool_ringparam *ering,
0114 struct kernel_ethtool_ringparam *kernel_ering,
0115 struct netlink_ext_ack *extack)
0116 {
0117 struct spider_net_card *card = netdev_priv(netdev);
0118
0119 ering->tx_max_pending = SPIDER_NET_TX_DESCRIPTORS_MAX;
0120 ering->tx_pending = card->tx_chain.num_desc;
0121 ering->rx_max_pending = SPIDER_NET_RX_DESCRIPTORS_MAX;
0122 ering->rx_pending = card->rx_chain.num_desc;
0123 }
0124
0125 static int spider_net_get_sset_count(struct net_device *netdev, int sset)
0126 {
0127 switch (sset) {
0128 case ETH_SS_STATS:
0129 return ARRAY_SIZE(ethtool_stats_keys);
0130 default:
0131 return -EOPNOTSUPP;
0132 }
0133 }
0134
0135 static void spider_net_get_ethtool_stats(struct net_device *netdev,
0136 struct ethtool_stats *stats, u64 *data)
0137 {
0138 struct spider_net_card *card = netdev_priv(netdev);
0139
0140 data[0] = netdev->stats.tx_packets;
0141 data[1] = netdev->stats.tx_bytes;
0142 data[2] = netdev->stats.rx_packets;
0143 data[3] = netdev->stats.rx_bytes;
0144 data[4] = netdev->stats.tx_errors;
0145 data[5] = netdev->stats.tx_dropped;
0146 data[6] = netdev->stats.rx_dropped;
0147 data[7] = card->spider_stats.rx_desc_error;
0148 data[8] = card->spider_stats.tx_timeouts;
0149 data[9] = card->spider_stats.alloc_rx_skb_error;
0150 data[10] = card->spider_stats.rx_iommu_map_error;
0151 data[11] = card->spider_stats.tx_iommu_map_error;
0152 data[12] = card->spider_stats.rx_desc_unk_state;
0153 }
0154
0155 static void spider_net_get_strings(struct net_device *netdev, u32 stringset,
0156 u8 *data)
0157 {
0158 memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys));
0159 }
0160
0161 const struct ethtool_ops spider_net_ethtool_ops = {
0162 .get_drvinfo = spider_net_ethtool_get_drvinfo,
0163 .get_wol = spider_net_ethtool_get_wol,
0164 .get_msglevel = spider_net_ethtool_get_msglevel,
0165 .set_msglevel = spider_net_ethtool_set_msglevel,
0166 .get_link = ethtool_op_get_link,
0167 .nway_reset = spider_net_ethtool_nway_reset,
0168 .get_ringparam = spider_net_ethtool_get_ringparam,
0169 .get_strings = spider_net_get_strings,
0170 .get_sset_count = spider_net_get_sset_count,
0171 .get_ethtool_stats = spider_net_get_ethtool_stats,
0172 .get_link_ksettings = spider_net_ethtool_get_link_ksettings,
0173 };
0174