1
2
3
4
5
6
7
8#include <linux/phy.h>
9
10#include "mlxbf_gige.h"
11#include "mlxbf_gige_regs.h"
12
13
14static int mlxbf_gige_get_regs_len(struct net_device *netdev)
15{
16 return MLXBF_GIGE_MMIO_REG_SZ;
17}
18
19static void mlxbf_gige_get_regs(struct net_device *netdev,
20 struct ethtool_regs *regs, void *p)
21{
22 struct mlxbf_gige *priv = netdev_priv(netdev);
23
24 regs->version = MLXBF_GIGE_REGS_VERSION;
25
26
27
28
29
30
31
32
33 memcpy_fromio(p, priv->base, MLXBF_GIGE_MMIO_REG_SZ);
34}
35
36static void mlxbf_gige_get_ringparam(struct net_device *netdev,
37 struct ethtool_ringparam *ering)
38{
39 struct mlxbf_gige *priv = netdev_priv(netdev);
40
41 ering->rx_max_pending = MLXBF_GIGE_MAX_RXQ_SZ;
42 ering->tx_max_pending = MLXBF_GIGE_MAX_TXQ_SZ;
43 ering->rx_pending = priv->rx_q_entries;
44 ering->tx_pending = priv->tx_q_entries;
45}
46
47static const struct {
48 const char string[ETH_GSTRING_LEN];
49} mlxbf_gige_ethtool_stats_keys[] = {
50 { "hw_access_errors" },
51 { "tx_invalid_checksums" },
52 { "tx_small_frames" },
53 { "tx_index_errors" },
54 { "sw_config_errors" },
55 { "sw_access_errors" },
56 { "rx_truncate_errors" },
57 { "rx_mac_errors" },
58 { "rx_din_dropped_pkts" },
59 { "tx_fifo_full" },
60 { "rx_filter_passed_pkts" },
61 { "rx_filter_discard_pkts" },
62};
63
64static int mlxbf_gige_get_sset_count(struct net_device *netdev, int stringset)
65{
66 if (stringset != ETH_SS_STATS)
67 return -EOPNOTSUPP;
68 return ARRAY_SIZE(mlxbf_gige_ethtool_stats_keys);
69}
70
71static void mlxbf_gige_get_strings(struct net_device *netdev, u32 stringset,
72 u8 *buf)
73{
74 if (stringset != ETH_SS_STATS)
75 return;
76 memcpy(buf, &mlxbf_gige_ethtool_stats_keys,
77 sizeof(mlxbf_gige_ethtool_stats_keys));
78}
79
80static void mlxbf_gige_get_ethtool_stats(struct net_device *netdev,
81 struct ethtool_stats *estats,
82 u64 *data)
83{
84 struct mlxbf_gige *priv = netdev_priv(netdev);
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101 *data++ = priv->stats.hw_access_errors;
102 *data++ = priv->stats.tx_invalid_checksums;
103 *data++ = priv->stats.tx_small_frames;
104 *data++ = priv->stats.tx_index_errors;
105 *data++ = priv->stats.sw_config_errors;
106 *data++ = priv->stats.sw_access_errors;
107 *data++ = priv->stats.rx_truncate_errors;
108 *data++ = priv->stats.rx_mac_errors;
109 *data++ = (priv->stats.rx_din_dropped_pkts +
110 readq(priv->base + MLXBF_GIGE_RX_DIN_DROP_COUNTER));
111 *data++ = priv->stats.tx_fifo_full;
112 *data++ = (priv->stats.rx_filter_passed_pkts +
113 readq(priv->base + MLXBF_GIGE_RX_PASS_COUNTER_ALL));
114 *data++ = (priv->stats.rx_filter_discard_pkts +
115 readq(priv->base + MLXBF_GIGE_RX_DISC_COUNTER_ALL));
116}
117
118static void mlxbf_gige_get_pauseparam(struct net_device *netdev,
119 struct ethtool_pauseparam *pause)
120{
121 pause->autoneg = AUTONEG_DISABLE;
122 pause->rx_pause = 1;
123 pause->tx_pause = 1;
124}
125
126const struct ethtool_ops mlxbf_gige_ethtool_ops = {
127 .get_link = ethtool_op_get_link,
128 .get_ringparam = mlxbf_gige_get_ringparam,
129 .get_regs_len = mlxbf_gige_get_regs_len,
130 .get_regs = mlxbf_gige_get_regs,
131 .get_strings = mlxbf_gige_get_strings,
132 .get_sset_count = mlxbf_gige_get_sset_count,
133 .get_ethtool_stats = mlxbf_gige_get_ethtool_stats,
134 .nway_reset = phy_ethtool_nway_reset,
135 .get_pauseparam = mlxbf_gige_get_pauseparam,
136 .get_link_ksettings = phy_ethtool_get_link_ksettings,
137};
138