]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blob - drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
Merge branch 'for-4.12/asus' into for-linus
[mirror_ubuntu-focal-kernel.git] / drivers / net / ethernet / aquantia / atlantic / aq_ethtool.c
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
15 static 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
25 static 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
33 static u32 aq_ethtool_get_link(struct net_device *ndev)
34 {
35 return ethtool_op_get_link(ndev);
36 }
37
38 static int aq_ethtool_get_link_ksettings(struct net_device *ndev,
39 struct ethtool_link_ksettings *cmd)
40 {
41 struct aq_nic_s *aq_nic = netdev_priv(ndev);
42
43 aq_nic_get_link_ksettings(aq_nic, cmd);
44 cmd->base.speed = netif_carrier_ok(ndev) ?
45 aq_nic_get_link_speed(aq_nic) : 0U;
46
47 return 0;
48 }
49
50 static int
51 aq_ethtool_set_link_ksettings(struct net_device *ndev,
52 const struct ethtool_link_ksettings *cmd)
53 {
54 struct aq_nic_s *aq_nic = netdev_priv(ndev);
55
56 return aq_nic_set_link_ksettings(aq_nic, cmd);
57 }
58
59 /* there "5U" is number of queue[#] stats lines (InPackets+...+InErrors) */
60 static const unsigned int aq_ethtool_stat_queue_lines = 5U;
61 static const unsigned int aq_ethtool_stat_queue_chars =
62 5U * ETH_GSTRING_LEN;
63 static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
64 "InPackets",
65 "InUCast",
66 "InMCast",
67 "InBCast",
68 "InErrors",
69 "OutPackets",
70 "OutUCast",
71 "OutMCast",
72 "OutBCast",
73 "InUCastOctects",
74 "OutUCastOctects",
75 "InMCastOctects",
76 "OutMCastOctects",
77 "InBCastOctects",
78 "OutBCastOctects",
79 "InOctects",
80 "OutOctects",
81 "InPacketsDma",
82 "OutPacketsDma",
83 "InOctetsDma",
84 "OutOctetsDma",
85 "InDroppedDma",
86 "Queue[0] InPackets",
87 "Queue[0] OutPackets",
88 "Queue[0] InJumboPackets",
89 "Queue[0] InLroPackets",
90 "Queue[0] InErrors",
91 "Queue[1] InPackets",
92 "Queue[1] OutPackets",
93 "Queue[1] InJumboPackets",
94 "Queue[1] InLroPackets",
95 "Queue[1] InErrors",
96 "Queue[2] InPackets",
97 "Queue[2] OutPackets",
98 "Queue[2] InJumboPackets",
99 "Queue[2] InLroPackets",
100 "Queue[2] InErrors",
101 "Queue[3] InPackets",
102 "Queue[3] OutPackets",
103 "Queue[3] InJumboPackets",
104 "Queue[3] InLroPackets",
105 "Queue[3] InErrors",
106 "Queue[4] InPackets",
107 "Queue[4] OutPackets",
108 "Queue[4] InJumboPackets",
109 "Queue[4] InLroPackets",
110 "Queue[4] InErrors",
111 "Queue[5] InPackets",
112 "Queue[5] OutPackets",
113 "Queue[5] InJumboPackets",
114 "Queue[5] InLroPackets",
115 "Queue[5] InErrors",
116 "Queue[6] InPackets",
117 "Queue[6] OutPackets",
118 "Queue[6] InJumboPackets",
119 "Queue[6] InLroPackets",
120 "Queue[6] InErrors",
121 "Queue[7] InPackets",
122 "Queue[7] OutPackets",
123 "Queue[7] InJumboPackets",
124 "Queue[7] InLroPackets",
125 "Queue[7] InErrors",
126 };
127
128 static void aq_ethtool_stats(struct net_device *ndev,
129 struct ethtool_stats *stats, u64 *data)
130 {
131 struct aq_nic_s *aq_nic = netdev_priv(ndev);
132
133 /* ASSERT: Need add lines to aq_ethtool_stat_names if AQ_CFG_VECS_MAX > 8 */
134 BUILD_BUG_ON(AQ_CFG_VECS_MAX > 8);
135 memset(data, 0, ARRAY_SIZE(aq_ethtool_stat_names) * sizeof(u64));
136 aq_nic_get_stats(aq_nic, data);
137 }
138
139 static void aq_ethtool_get_drvinfo(struct net_device *ndev,
140 struct ethtool_drvinfo *drvinfo)
141 {
142 struct aq_nic_s *aq_nic = netdev_priv(ndev);
143 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
144 struct pci_dev *pdev = to_pci_dev(ndev->dev.parent);
145 u32 firmware_version = aq_nic_get_fw_version(aq_nic);
146 u32 regs_count = aq_nic_get_regs_count(aq_nic);
147
148 strlcat(drvinfo->driver, AQ_CFG_DRV_NAME, sizeof(drvinfo->driver));
149 strlcat(drvinfo->version, AQ_CFG_DRV_VERSION, sizeof(drvinfo->version));
150
151 snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
152 "%u.%u.%u", firmware_version >> 24,
153 (firmware_version >> 16) & 0xFFU, firmware_version & 0xFFFFU);
154
155 strlcpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "",
156 sizeof(drvinfo->bus_info));
157 drvinfo->n_stats = ARRAY_SIZE(aq_ethtool_stat_names) -
158 (AQ_CFG_VECS_MAX - cfg->vecs) * aq_ethtool_stat_queue_lines;
159 drvinfo->testinfo_len = 0;
160 drvinfo->regdump_len = regs_count;
161 drvinfo->eedump_len = 0;
162 }
163
164 static void aq_ethtool_get_strings(struct net_device *ndev,
165 u32 stringset, u8 *data)
166 {
167 struct aq_nic_s *aq_nic = netdev_priv(ndev);
168 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
169
170 if (stringset == ETH_SS_STATS)
171 memcpy(data, *aq_ethtool_stat_names,
172 sizeof(aq_ethtool_stat_names) -
173 (AQ_CFG_VECS_MAX - cfg->vecs) *
174 aq_ethtool_stat_queue_chars);
175 }
176
177 static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset)
178 {
179 int ret = 0;
180 struct aq_nic_s *aq_nic = netdev_priv(ndev);
181 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
182
183 switch (stringset) {
184 case ETH_SS_STATS:
185 ret = ARRAY_SIZE(aq_ethtool_stat_names) -
186 (AQ_CFG_VECS_MAX - cfg->vecs) *
187 aq_ethtool_stat_queue_lines;
188 break;
189 default:
190 ret = -EOPNOTSUPP;
191 }
192 return ret;
193 }
194
195 static u32 aq_ethtool_get_rss_indir_size(struct net_device *ndev)
196 {
197 return AQ_CFG_RSS_INDIRECTION_TABLE_MAX;
198 }
199
200 static u32 aq_ethtool_get_rss_key_size(struct net_device *ndev)
201 {
202 struct aq_nic_s *aq_nic = netdev_priv(ndev);
203 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
204
205 return sizeof(cfg->aq_rss.hash_secret_key);
206 }
207
208 static int aq_ethtool_get_rss(struct net_device *ndev, u32 *indir, u8 *key,
209 u8 *hfunc)
210 {
211 struct aq_nic_s *aq_nic = netdev_priv(ndev);
212 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
213 unsigned int i = 0U;
214
215 if (hfunc)
216 *hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */
217 if (indir) {
218 for (i = 0; i < AQ_CFG_RSS_INDIRECTION_TABLE_MAX; i++)
219 indir[i] = cfg->aq_rss.indirection_table[i];
220 }
221 if (key)
222 memcpy(key, cfg->aq_rss.hash_secret_key,
223 sizeof(cfg->aq_rss.hash_secret_key));
224 return 0;
225 }
226
227 static int aq_ethtool_get_rxnfc(struct net_device *ndev,
228 struct ethtool_rxnfc *cmd,
229 u32 *rule_locs)
230 {
231 struct aq_nic_s *aq_nic = netdev_priv(ndev);
232 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic);
233 int err = 0;
234
235 switch (cmd->cmd) {
236 case ETHTOOL_GRXRINGS:
237 cmd->data = cfg->vecs;
238 break;
239
240 default:
241 err = -EOPNOTSUPP;
242 break;
243 }
244
245 return err;
246 }
247
248 const struct ethtool_ops aq_ethtool_ops = {
249 .get_link = aq_ethtool_get_link,
250 .get_regs_len = aq_ethtool_get_regs_len,
251 .get_regs = aq_ethtool_get_regs,
252 .get_drvinfo = aq_ethtool_get_drvinfo,
253 .get_strings = aq_ethtool_get_strings,
254 .get_rxfh_indir_size = aq_ethtool_get_rss_indir_size,
255 .get_rxfh_key_size = aq_ethtool_get_rss_key_size,
256 .get_rxfh = aq_ethtool_get_rss,
257 .get_rxnfc = aq_ethtool_get_rxnfc,
258 .get_sset_count = aq_ethtool_get_sset_count,
259 .get_ethtool_stats = aq_ethtool_stats,
260 .get_link_ksettings = aq_ethtool_get_link_ksettings,
261 .set_link_ksettings = aq_ethtool_set_link_ksettings,
262 };