aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid VomLehn <vomlehn@texas.net>2017-01-24 01:09:18 -0500
committerDavid S. Miller <davem@davemloft.net>2017-01-24 15:03:41 -0500
commitc5760d03d4ebd12f1b2d6723aec4b45327a1d2eb (patch)
treec12eca3c8803f1d333e741dc7f6bd3b2c3fd1b2e
parent753f4783be7b60b2c936c6985ddf42f8ce268ad9 (diff)
net: ethernet: aquantia: Ethtool support
Add the driver interfaces required for support by the ethtool utility. Signed-off-by: Alexander Loktionov <Alexander.Loktionov@aquantia.com> Signed-off-by: Dmitrii Tarakanov <Dmitrii.Tarakanov@aquantia.com> Signed-off-by: Pavel Belous <Pavel.Belous@aquantia.com> Signed-off-by: Dmitry Bezrukov <Dmitry.Bezrukov@aquantia.com> Signed-off-by: David M. VomLehn <vomlehn@texas.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c261
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_ethtool.h19
2 files changed, 280 insertions, 0 deletions
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
new file mode 100644
index 000000000000..c5b025e0dc10
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
@@ -0,0 +1,261 @@
1/*
2 * aQuantia Corporation Network Driver
3 * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 */
9
10/* File aq_ethtool.c: Definition of ethertool related functions. */
11
12#include "aq_ethtool.h"
13#include "aq_nic.h"
14
15static void aq_ethtool_get_regs(struct net_device *ndev,
16 struct ethtool_regs *regs, void *p)
17{
18 struct aq_nic_s *aq_nic = netdev_priv(ndev);
19 u32 regs_count = aq_nic_get_regs_count(aq_nic);
20
21 memset(p, 0, regs_count * sizeof(u32));
22 aq_nic_get_regs(aq_nic, regs, p);
23}
24
25static int aq_ethtool_get_regs_len(struct net_device *ndev)
26{
27 struct aq_nic_s *aq_nic = netdev_priv(ndev);
28 u32 regs_count = aq_nic_get_regs_count(aq_nic);
29
30 return regs_count * sizeof(u32);
31}
32
33static u32 aq_ethtool_get_link(struct net_device *ndev)
34{
35 return ethtool_op_get_link(ndev);
36}
37
38static int aq_ethtool_get_settings(struct net_device *ndev,
39 struct ethtool_cmd *cmd)
40{
41 struct aq_nic_s *aq_nic = netdev_priv(ndev);
42
43 aq_nic_get_link_settings(aq_nic, cmd);
44 ethtool_cmd_speed_set(cmd, netif_carrier_ok(ndev) ?
45 aq_nic_get_link_speed(aq_nic) : 0U);
46
47 return 0;
48}
49
50static int aq_ethtool_set_settings(struct net_device *ndev,
51 struct ethtool_cmd *cmd)
52{
53 struct aq_nic_s *aq_nic = netdev_priv(ndev);
54
55 return aq_nic_set_link_settings(aq_nic, cmd);
56}
57
58/* there "5U" is number of queue[#] stats lines (InPackets+...+InErrors) */
59static const unsigned int aq_ethtool_stat_queue_lines = 5U;
60static const unsigned int aq_ethtool_stat_queue_chars =
61 5U * ETH_GSTRING_LEN;
62static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
63 "InPackets",
64 "InUCast",
65 "InMCast",
66 "InBCast",
67 "InErrors",
68 "OutPackets",
69 "OutUCast",
70 "OutMCast",
71 "OutBCast",
72 "InUCastOctects",
73 "OutUCastOctects",
74 "InMCastOctects",
75 "OutMCastOctects",
76 "InBCastOctects",
77 "OutBCastOctects",
78 "InOctects",
79 "OutOctects",
80 "InPacketsDma",
81 "OutPacketsDma",
82 "InOctetsDma",
83 "OutOctetsDma",
84 "InDroppedDma",
85 "Queue[0] InPackets",
86 "Queue[0] OutPackets",
87 "Queue[0] InJumboPackets",
88 "Queue[0] InLroPackets",
89 "Queue[0] InErrors",
90 "Queue[1] InPackets",
91 "Queue[1] OutPackets",
92 "Queue[1] InJumboPackets",
93 "Queue[1] InLroPackets",
94 "Queue[1] InErrors",
95 "Queue[2] InPackets",
96 "Queue[2] OutPackets",
97 "Queue[2] InJumboPackets",
98 "Queue[2] InLroPackets",
99 "Queue[2] InErrors",
100 "Queue[3] InPackets",
101 "Queue[3] OutPackets",
102 "Queue[3] InJumboPackets",
103 "Queue[3] InLroPackets",
104 "Queue[3] InErrors",
105 "Queue[4] InPackets",
106 "Queue[4] OutPackets",
107 "Queue[4] InJumboPackets",
108 "Queue[4] InLroPackets",
109 "Queue[4] InErrors",
110 "Queue[5] InPackets",
111 "Queue[5] OutPackets",
112 "Queue[5] InJumboPackets",
113 "Queue[5] InLroPackets",
114 "Queue[5] InErrors",
115 "Queue[6] InPackets",
116 "Queue[6] OutPackets",
117 "Queue[6] InJumboPackets",
118 "Queue[6] InLroPackets",
119 "Queue[6] InErrors",
120 "Queue[7] InPackets",
121 "Queue[7] OutPackets",
122 "Queue[7] InJumboPackets",
123 "Queue[7] InLroPackets",
124 "Queue[7] InErrors",
125};
126
127static void aq_ethtool_stats(struct net_device *ndev,
128 struct ethtool_stats *stats, u64 *data)
129{
130 struct aq_nic_s *aq_nic = netdev_priv(ndev);
131
132/* ASSERT: Need add lines to aq_ethtool_stat_names if AQ_CFG_VECS_MAX > 8 */
133 BUILD_BUG_ON(AQ_CFG_VECS_MAX > 8);
134 memset(data, 0, ARRAY_SIZE(aq_ethtool_stat_names) * sizeof(u64));
135 aq_nic_get_stats(aq_nic, data);
136}
137
138static void aq_ethtool_get_drvinfo(struct net_device *ndev,
139 struct ethtool_drvinfo *drvinfo)
140{
141 struct aq_nic_s *aq_nic = netdev_priv(ndev);
142 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
143 struct pci_dev *pdev = to_pci_dev(ndev->dev.parent);
144 u32 firmware_version = aq_nic_get_fw_version(aq_nic);
145 u32 regs_count = aq_nic_get_regs_count(aq_nic);
146
147 strlcat(drvinfo->driver, AQ_CFG_DRV_NAME, sizeof(drvinfo->driver));
148 strlcat(drvinfo->version, AQ_CFG_DRV_VERSION, sizeof(drvinfo->version));
149
150 snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
151 "%u.%u.%u", firmware_version >> 24,
152 (firmware_version >> 16) & 0xFFU, firmware_version & 0xFFFFU);
153
154 strlcpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "",
155 sizeof(drvinfo->bus_info));
156 drvinfo->n_stats = ARRAY_SIZE(aq_ethtool_stat_names) -
157 (AQ_CFG_VECS_MAX - cfg->vecs) * aq_ethtool_stat_queue_lines;
158 drvinfo->testinfo_len = 0;
159 drvinfo->regdump_len = regs_count;
160 drvinfo->eedump_len = 0;
161}
162
163static void aq_ethtool_get_strings(struct net_device *ndev,
164 u32 stringset, u8 *data)
165{
166 struct aq_nic_s *aq_nic = netdev_priv(ndev);
167 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
168
169 if (stringset == ETH_SS_STATS)
170 memcpy(data, *aq_ethtool_stat_names,
171 sizeof(aq_ethtool_stat_names) -
172 (AQ_CFG_VECS_MAX - cfg->vecs) *
173 aq_ethtool_stat_queue_chars);
174}
175
176static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset)
177{
178 int ret = 0;
179 struct aq_nic_s *aq_nic = netdev_priv(ndev);
180 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
181
182 switch (stringset) {
183 case ETH_SS_STATS:
184 ret = ARRAY_SIZE(aq_ethtool_stat_names) -
185 (AQ_CFG_VECS_MAX - cfg->vecs) *
186 aq_ethtool_stat_queue_lines;
187 break;
188 default:
189 ret = -EOPNOTSUPP;
190 }
191 return ret;
192}
193
194static u32 aq_ethtool_get_rss_indir_size(struct net_device *ndev)
195{
196 return AQ_CFG_RSS_INDIRECTION_TABLE_MAX;
197}
198
199static u32 aq_ethtool_get_rss_key_size(struct net_device *ndev)
200{
201 struct aq_nic_s *aq_nic = netdev_priv(ndev);
202 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
203
204 return sizeof(cfg->aq_rss.hash_secret_key);
205}
206
207static int aq_ethtool_get_rss(struct net_device *ndev, u32 *indir, u8 *key,
208 u8 *hfunc)
209{
210 struct aq_nic_s *aq_nic = netdev_priv(ndev);
211 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
212 unsigned int i = 0U;
213
214 if (hfunc)
215 *hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */
216 if (indir) {
217 for (i = 0; i < AQ_CFG_RSS_INDIRECTION_TABLE_MAX; i++)
218 indir[i] = cfg->aq_rss.indirection_table[i];
219 }
220 if (key)
221 memcpy(key, cfg->aq_rss.hash_secret_key,
222 sizeof(cfg->aq_rss.hash_secret_key));
223 return 0;
224}
225
226static int aq_ethtool_get_rxnfc(struct net_device *ndev,
227 struct ethtool_rxnfc *cmd,
228 u32 *rule_locs)
229{
230 struct aq_nic_s *aq_nic = netdev_priv(ndev);
231 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
232 int err = 0;
233
234 switch (cmd->cmd) {
235 case ETHTOOL_GRXRINGS:
236 cmd->data = cfg->vecs;
237 break;
238
239 default:
240 err = -EOPNOTSUPP;
241 break;
242 }
243
244 return err;
245}
246
247const struct ethtool_ops aq_ethtool_ops = {
248 .get_link = aq_ethtool_get_link,
249 .get_regs_len = aq_ethtool_get_regs_len,
250 .get_regs = aq_ethtool_get_regs,
251 .get_settings = aq_ethtool_get_settings,
252 .set_settings = aq_ethtool_set_settings,
253 .get_drvinfo = aq_ethtool_get_drvinfo,
254 .get_strings = aq_ethtool_get_strings,
255 .get_rxfh_indir_size = aq_ethtool_get_rss_indir_size,
256 .get_rxfh_key_size = aq_ethtool_get_rss_key_size,
257 .get_rxfh = aq_ethtool_get_rss,
258 .get_rxnfc = aq_ethtool_get_rxnfc,
259 .get_sset_count = aq_ethtool_get_sset_count,
260 .get_ethtool_stats = aq_ethtool_stats
261};
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.h b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.h
new file mode 100644
index 000000000000..21c126eeb5eb
--- /dev/null
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.h
@@ -0,0 +1,19 @@
1/*
2 * aQuantia Corporation Network Driver
3 * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 */
9
10/* File aq_ethtool.h: Declaration of ethertool related functions. */
11
12#ifndef AQ_ETHTOOL_H
13#define AQ_ETHTOOL_H
14
15#include "aq_common.h"
16
17extern const struct ethtool_ops aq_ethtool_ops;
18
19#endif /* AQ_ETHTOOL_H */