1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright(c) 1999 - 2018 Intel Corporation. */ |
3 | |
4 | /* ethtool support for ixgbevf */ |
5 | |
6 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
7 | |
8 | #include <linux/types.h> |
9 | #include <linux/module.h> |
10 | #include <linux/slab.h> |
11 | #include <linux/pci.h> |
12 | #include <linux/netdevice.h> |
13 | #include <linux/ethtool.h> |
14 | #include <linux/vmalloc.h> |
15 | #include <linux/if_vlan.h> |
16 | #include <linux/uaccess.h> |
17 | |
18 | #include "ixgbevf.h" |
19 | |
20 | enum {NETDEV_STATS, IXGBEVF_STATS}; |
21 | |
22 | struct ixgbe_stats { |
23 | char stat_string[ETH_GSTRING_LEN]; |
24 | int type; |
25 | int sizeof_stat; |
26 | int stat_offset; |
27 | }; |
28 | |
29 | #define IXGBEVF_STAT(_name, _stat) { \ |
30 | .stat_string = _name, \ |
31 | .type = IXGBEVF_STATS, \ |
32 | .sizeof_stat = sizeof_field(struct ixgbevf_adapter, _stat), \ |
33 | .stat_offset = offsetof(struct ixgbevf_adapter, _stat) \ |
34 | } |
35 | |
36 | #define IXGBEVF_NETDEV_STAT(_net_stat) { \ |
37 | .stat_string = #_net_stat, \ |
38 | .type = NETDEV_STATS, \ |
39 | .sizeof_stat = sizeof_field(struct net_device_stats, _net_stat), \ |
40 | .stat_offset = offsetof(struct net_device_stats, _net_stat) \ |
41 | } |
42 | |
43 | static struct ixgbe_stats ixgbevf_gstrings_stats[] = { |
44 | IXGBEVF_NETDEV_STAT(rx_packets), |
45 | IXGBEVF_NETDEV_STAT(tx_packets), |
46 | IXGBEVF_NETDEV_STAT(rx_bytes), |
47 | IXGBEVF_NETDEV_STAT(tx_bytes), |
48 | IXGBEVF_STAT("tx_busy" , tx_busy), |
49 | IXGBEVF_STAT("tx_restart_queue" , restart_queue), |
50 | IXGBEVF_STAT("tx_timeout_count" , tx_timeout_count), |
51 | IXGBEVF_NETDEV_STAT(multicast), |
52 | IXGBEVF_STAT("rx_csum_offload_errors" , hw_csum_rx_error), |
53 | IXGBEVF_STAT("alloc_rx_page" , alloc_rx_page), |
54 | IXGBEVF_STAT("alloc_rx_page_failed" , alloc_rx_page_failed), |
55 | IXGBEVF_STAT("alloc_rx_buff_failed" , alloc_rx_buff_failed), |
56 | IXGBEVF_STAT("tx_ipsec" , tx_ipsec), |
57 | IXGBEVF_STAT("rx_ipsec" , rx_ipsec), |
58 | }; |
59 | |
60 | #define IXGBEVF_QUEUE_STATS_LEN ( \ |
61 | (((struct ixgbevf_adapter *)netdev_priv(netdev))->num_tx_queues + \ |
62 | ((struct ixgbevf_adapter *)netdev_priv(netdev))->num_xdp_queues + \ |
63 | ((struct ixgbevf_adapter *)netdev_priv(netdev))->num_rx_queues) * \ |
64 | (sizeof(struct ixgbevf_stats) / sizeof(u64))) |
65 | #define IXGBEVF_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbevf_gstrings_stats) |
66 | |
67 | #define IXGBEVF_STATS_LEN (IXGBEVF_GLOBAL_STATS_LEN + IXGBEVF_QUEUE_STATS_LEN) |
68 | static const char ixgbe_gstrings_test[][ETH_GSTRING_LEN] = { |
69 | "Register test (offline)" , |
70 | "Link test (on/offline)" |
71 | }; |
72 | |
73 | #define IXGBEVF_TEST_LEN (sizeof(ixgbe_gstrings_test) / ETH_GSTRING_LEN) |
74 | |
75 | static const char ixgbevf_priv_flags_strings[][ETH_GSTRING_LEN] = { |
76 | #define IXGBEVF_PRIV_FLAGS_LEGACY_RX BIT(0) |
77 | "legacy-rx" , |
78 | }; |
79 | |
80 | #define IXGBEVF_PRIV_FLAGS_STR_LEN ARRAY_SIZE(ixgbevf_priv_flags_strings) |
81 | |
82 | static int ixgbevf_get_link_ksettings(struct net_device *netdev, |
83 | struct ethtool_link_ksettings *cmd) |
84 | { |
85 | struct ixgbevf_adapter *adapter = netdev_priv(dev: netdev); |
86 | |
87 | ethtool_link_ksettings_zero_link_mode(cmd, supported); |
88 | ethtool_link_ksettings_add_link_mode(cmd, supported, 10000baseT_Full); |
89 | cmd->base.autoneg = AUTONEG_DISABLE; |
90 | cmd->base.port = -1; |
91 | |
92 | if (adapter->link_up) { |
93 | __u32 speed = SPEED_10000; |
94 | |
95 | switch (adapter->link_speed) { |
96 | case IXGBE_LINK_SPEED_10GB_FULL: |
97 | speed = SPEED_10000; |
98 | break; |
99 | case IXGBE_LINK_SPEED_1GB_FULL: |
100 | speed = SPEED_1000; |
101 | break; |
102 | case IXGBE_LINK_SPEED_100_FULL: |
103 | speed = SPEED_100; |
104 | break; |
105 | } |
106 | |
107 | cmd->base.speed = speed; |
108 | cmd->base.duplex = DUPLEX_FULL; |
109 | } else { |
110 | cmd->base.speed = SPEED_UNKNOWN; |
111 | cmd->base.duplex = DUPLEX_UNKNOWN; |
112 | } |
113 | |
114 | return 0; |
115 | } |
116 | |
117 | static u32 ixgbevf_get_msglevel(struct net_device *netdev) |
118 | { |
119 | struct ixgbevf_adapter *adapter = netdev_priv(dev: netdev); |
120 | |
121 | return adapter->msg_enable; |
122 | } |
123 | |
124 | static void ixgbevf_set_msglevel(struct net_device *netdev, u32 data) |
125 | { |
126 | struct ixgbevf_adapter *adapter = netdev_priv(dev: netdev); |
127 | |
128 | adapter->msg_enable = data; |
129 | } |
130 | |
131 | static int ixgbevf_get_regs_len(struct net_device *netdev) |
132 | { |
133 | #define IXGBE_REGS_LEN 45 |
134 | return IXGBE_REGS_LEN * sizeof(u32); |
135 | } |
136 | |
137 | static void ixgbevf_get_regs(struct net_device *netdev, |
138 | struct ethtool_regs *regs, |
139 | void *p) |
140 | { |
141 | struct ixgbevf_adapter *adapter = netdev_priv(dev: netdev); |
142 | struct ixgbe_hw *hw = &adapter->hw; |
143 | u32 *regs_buff = p; |
144 | u32 regs_len = ixgbevf_get_regs_len(netdev); |
145 | u8 i; |
146 | |
147 | memset(p, 0, regs_len); |
148 | |
149 | /* generate a number suitable for ethtool's register version */ |
150 | regs->version = (1u << 24) | (hw->revision_id << 16) | hw->device_id; |
151 | |
152 | /* General Registers */ |
153 | regs_buff[0] = IXGBE_READ_REG(hw, IXGBE_VFCTRL); |
154 | regs_buff[1] = IXGBE_READ_REG(hw, IXGBE_VFSTATUS); |
155 | regs_buff[2] = IXGBE_READ_REG(hw, IXGBE_VFLINKS); |
156 | regs_buff[3] = IXGBE_READ_REG(hw, IXGBE_VFRXMEMWRAP); |
157 | regs_buff[4] = IXGBE_READ_REG(hw, IXGBE_VFFRTIMER); |
158 | |
159 | /* Interrupt */ |
160 | /* don't read EICR because it can clear interrupt causes, instead |
161 | * read EICS which is a shadow but doesn't clear EICR |
162 | */ |
163 | regs_buff[5] = IXGBE_READ_REG(hw, IXGBE_VTEICS); |
164 | regs_buff[6] = IXGBE_READ_REG(hw, IXGBE_VTEICS); |
165 | regs_buff[7] = IXGBE_READ_REG(hw, IXGBE_VTEIMS); |
166 | regs_buff[8] = IXGBE_READ_REG(hw, IXGBE_VTEIMC); |
167 | regs_buff[9] = IXGBE_READ_REG(hw, IXGBE_VTEIAC); |
168 | regs_buff[10] = IXGBE_READ_REG(hw, IXGBE_VTEIAM); |
169 | regs_buff[11] = IXGBE_READ_REG(hw, IXGBE_VTEITR(0)); |
170 | regs_buff[12] = IXGBE_READ_REG(hw, IXGBE_VTIVAR(0)); |
171 | regs_buff[13] = IXGBE_READ_REG(hw, IXGBE_VTIVAR_MISC); |
172 | |
173 | /* Receive DMA */ |
174 | for (i = 0; i < 2; i++) |
175 | regs_buff[14 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDBAL(i)); |
176 | for (i = 0; i < 2; i++) |
177 | regs_buff[16 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDBAH(i)); |
178 | for (i = 0; i < 2; i++) |
179 | regs_buff[18 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDLEN(i)); |
180 | for (i = 0; i < 2; i++) |
181 | regs_buff[20 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDH(i)); |
182 | for (i = 0; i < 2; i++) |
183 | regs_buff[22 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDT(i)); |
184 | for (i = 0; i < 2; i++) |
185 | regs_buff[24 + i] = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)); |
186 | for (i = 0; i < 2; i++) |
187 | regs_buff[26 + i] = IXGBE_READ_REG(hw, IXGBE_VFSRRCTL(i)); |
188 | |
189 | /* Receive */ |
190 | regs_buff[28] = IXGBE_READ_REG(hw, IXGBE_VFPSRTYPE); |
191 | |
192 | /* Transmit */ |
193 | for (i = 0; i < 2; i++) |
194 | regs_buff[29 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDBAL(i)); |
195 | for (i = 0; i < 2; i++) |
196 | regs_buff[31 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDBAH(i)); |
197 | for (i = 0; i < 2; i++) |
198 | regs_buff[33 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDLEN(i)); |
199 | for (i = 0; i < 2; i++) |
200 | regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDH(i)); |
201 | for (i = 0; i < 2; i++) |
202 | regs_buff[37 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDT(i)); |
203 | for (i = 0; i < 2; i++) |
204 | regs_buff[39 + i] = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(i)); |
205 | for (i = 0; i < 2; i++) |
206 | regs_buff[41 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDWBAL(i)); |
207 | for (i = 0; i < 2; i++) |
208 | regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDWBAH(i)); |
209 | } |
210 | |
211 | static void ixgbevf_get_drvinfo(struct net_device *netdev, |
212 | struct ethtool_drvinfo *drvinfo) |
213 | { |
214 | struct ixgbevf_adapter *adapter = netdev_priv(dev: netdev); |
215 | |
216 | strscpy(p: drvinfo->driver, q: ixgbevf_driver_name, size: sizeof(drvinfo->driver)); |
217 | strscpy(p: drvinfo->bus_info, q: pci_name(pdev: adapter->pdev), |
218 | size: sizeof(drvinfo->bus_info)); |
219 | |
220 | drvinfo->n_priv_flags = IXGBEVF_PRIV_FLAGS_STR_LEN; |
221 | } |
222 | |
223 | static void ixgbevf_get_ringparam(struct net_device *netdev, |
224 | struct ethtool_ringparam *ring, |
225 | struct kernel_ethtool_ringparam *kernel_ring, |
226 | struct netlink_ext_ack *extack) |
227 | { |
228 | struct ixgbevf_adapter *adapter = netdev_priv(dev: netdev); |
229 | |
230 | ring->rx_max_pending = IXGBEVF_MAX_RXD; |
231 | ring->tx_max_pending = IXGBEVF_MAX_TXD; |
232 | ring->rx_pending = adapter->rx_ring_count; |
233 | ring->tx_pending = adapter->tx_ring_count; |
234 | } |
235 | |
236 | static int ixgbevf_set_ringparam(struct net_device *netdev, |
237 | struct ethtool_ringparam *ring, |
238 | struct kernel_ethtool_ringparam *kernel_ring, |
239 | struct netlink_ext_ack *extack) |
240 | { |
241 | struct ixgbevf_adapter *adapter = netdev_priv(dev: netdev); |
242 | struct ixgbevf_ring *tx_ring = NULL, *rx_ring = NULL; |
243 | u32 new_rx_count, new_tx_count; |
244 | int i, j, err = 0; |
245 | |
246 | if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) |
247 | return -EINVAL; |
248 | |
249 | new_tx_count = max_t(u32, ring->tx_pending, IXGBEVF_MIN_TXD); |
250 | new_tx_count = min_t(u32, new_tx_count, IXGBEVF_MAX_TXD); |
251 | new_tx_count = ALIGN(new_tx_count, IXGBE_REQ_TX_DESCRIPTOR_MULTIPLE); |
252 | |
253 | new_rx_count = max_t(u32, ring->rx_pending, IXGBEVF_MIN_RXD); |
254 | new_rx_count = min_t(u32, new_rx_count, IXGBEVF_MAX_RXD); |
255 | new_rx_count = ALIGN(new_rx_count, IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE); |
256 | |
257 | /* if nothing to do return success */ |
258 | if ((new_tx_count == adapter->tx_ring_count) && |
259 | (new_rx_count == adapter->rx_ring_count)) |
260 | return 0; |
261 | |
262 | while (test_and_set_bit(nr: __IXGBEVF_RESETTING, addr: &adapter->state)) |
263 | usleep_range(min: 1000, max: 2000); |
264 | |
265 | if (!netif_running(dev: adapter->netdev)) { |
266 | for (i = 0; i < adapter->num_tx_queues; i++) |
267 | adapter->tx_ring[i]->count = new_tx_count; |
268 | for (i = 0; i < adapter->num_xdp_queues; i++) |
269 | adapter->xdp_ring[i]->count = new_tx_count; |
270 | for (i = 0; i < adapter->num_rx_queues; i++) |
271 | adapter->rx_ring[i]->count = new_rx_count; |
272 | adapter->tx_ring_count = new_tx_count; |
273 | adapter->xdp_ring_count = new_tx_count; |
274 | adapter->rx_ring_count = new_rx_count; |
275 | goto clear_reset; |
276 | } |
277 | |
278 | if (new_tx_count != adapter->tx_ring_count) { |
279 | tx_ring = vmalloc(array_size(sizeof(*tx_ring), |
280 | adapter->num_tx_queues + |
281 | adapter->num_xdp_queues)); |
282 | if (!tx_ring) { |
283 | err = -ENOMEM; |
284 | goto clear_reset; |
285 | } |
286 | |
287 | for (i = 0; i < adapter->num_tx_queues; i++) { |
288 | /* clone ring and setup updated count */ |
289 | tx_ring[i] = *adapter->tx_ring[i]; |
290 | tx_ring[i].count = new_tx_count; |
291 | err = ixgbevf_setup_tx_resources(&tx_ring[i]); |
292 | if (err) { |
293 | while (i) { |
294 | i--; |
295 | ixgbevf_free_tx_resources(&tx_ring[i]); |
296 | } |
297 | |
298 | vfree(addr: tx_ring); |
299 | tx_ring = NULL; |
300 | |
301 | goto clear_reset; |
302 | } |
303 | } |
304 | |
305 | for (j = 0; j < adapter->num_xdp_queues; i++, j++) { |
306 | /* clone ring and setup updated count */ |
307 | tx_ring[i] = *adapter->xdp_ring[j]; |
308 | tx_ring[i].count = new_tx_count; |
309 | err = ixgbevf_setup_tx_resources(&tx_ring[i]); |
310 | if (err) { |
311 | while (i) { |
312 | i--; |
313 | ixgbevf_free_tx_resources(&tx_ring[i]); |
314 | } |
315 | |
316 | vfree(addr: tx_ring); |
317 | tx_ring = NULL; |
318 | |
319 | goto clear_reset; |
320 | } |
321 | } |
322 | } |
323 | |
324 | if (new_rx_count != adapter->rx_ring_count) { |
325 | rx_ring = vmalloc(array_size(sizeof(*rx_ring), |
326 | adapter->num_rx_queues)); |
327 | if (!rx_ring) { |
328 | err = -ENOMEM; |
329 | goto clear_reset; |
330 | } |
331 | |
332 | for (i = 0; i < adapter->num_rx_queues; i++) { |
333 | /* clone ring and setup updated count */ |
334 | rx_ring[i] = *adapter->rx_ring[i]; |
335 | |
336 | /* Clear copied XDP RX-queue info */ |
337 | memset(&rx_ring[i].xdp_rxq, 0, |
338 | sizeof(rx_ring[i].xdp_rxq)); |
339 | |
340 | rx_ring[i].count = new_rx_count; |
341 | err = ixgbevf_setup_rx_resources(adapter, rx_ring: &rx_ring[i]); |
342 | if (err) { |
343 | while (i) { |
344 | i--; |
345 | ixgbevf_free_rx_resources(&rx_ring[i]); |
346 | } |
347 | |
348 | vfree(addr: rx_ring); |
349 | rx_ring = NULL; |
350 | |
351 | goto clear_reset; |
352 | } |
353 | } |
354 | } |
355 | |
356 | /* bring interface down to prepare for update */ |
357 | ixgbevf_down(adapter); |
358 | |
359 | /* Tx */ |
360 | if (tx_ring) { |
361 | for (i = 0; i < adapter->num_tx_queues; i++) { |
362 | ixgbevf_free_tx_resources(adapter->tx_ring[i]); |
363 | *adapter->tx_ring[i] = tx_ring[i]; |
364 | } |
365 | adapter->tx_ring_count = new_tx_count; |
366 | |
367 | for (j = 0; j < adapter->num_xdp_queues; i++, j++) { |
368 | ixgbevf_free_tx_resources(adapter->xdp_ring[j]); |
369 | *adapter->xdp_ring[j] = tx_ring[i]; |
370 | } |
371 | adapter->xdp_ring_count = new_tx_count; |
372 | |
373 | vfree(addr: tx_ring); |
374 | tx_ring = NULL; |
375 | } |
376 | |
377 | /* Rx */ |
378 | if (rx_ring) { |
379 | for (i = 0; i < adapter->num_rx_queues; i++) { |
380 | ixgbevf_free_rx_resources(adapter->rx_ring[i]); |
381 | *adapter->rx_ring[i] = rx_ring[i]; |
382 | } |
383 | adapter->rx_ring_count = new_rx_count; |
384 | |
385 | vfree(addr: rx_ring); |
386 | rx_ring = NULL; |
387 | } |
388 | |
389 | /* restore interface using new values */ |
390 | ixgbevf_up(adapter); |
391 | |
392 | clear_reset: |
393 | /* free Tx resources if Rx error is encountered */ |
394 | if (tx_ring) { |
395 | for (i = 0; |
396 | i < adapter->num_tx_queues + adapter->num_xdp_queues; i++) |
397 | ixgbevf_free_tx_resources(&tx_ring[i]); |
398 | vfree(addr: tx_ring); |
399 | } |
400 | |
401 | clear_bit(nr: __IXGBEVF_RESETTING, addr: &adapter->state); |
402 | return err; |
403 | } |
404 | |
405 | static int ixgbevf_get_sset_count(struct net_device *netdev, int stringset) |
406 | { |
407 | switch (stringset) { |
408 | case ETH_SS_TEST: |
409 | return IXGBEVF_TEST_LEN; |
410 | case ETH_SS_STATS: |
411 | return IXGBEVF_STATS_LEN; |
412 | case ETH_SS_PRIV_FLAGS: |
413 | return IXGBEVF_PRIV_FLAGS_STR_LEN; |
414 | default: |
415 | return -EINVAL; |
416 | } |
417 | } |
418 | |
419 | static void ixgbevf_get_ethtool_stats(struct net_device *netdev, |
420 | struct ethtool_stats *stats, u64 *data) |
421 | { |
422 | struct ixgbevf_adapter *adapter = netdev_priv(dev: netdev); |
423 | struct rtnl_link_stats64 temp; |
424 | const struct rtnl_link_stats64 *net_stats; |
425 | unsigned int start; |
426 | struct ixgbevf_ring *ring; |
427 | int i, j; |
428 | char *p; |
429 | |
430 | ixgbevf_update_stats(adapter); |
431 | net_stats = dev_get_stats(dev: netdev, storage: &temp); |
432 | for (i = 0; i < IXGBEVF_GLOBAL_STATS_LEN; i++) { |
433 | switch (ixgbevf_gstrings_stats[i].type) { |
434 | case NETDEV_STATS: |
435 | p = (char *)net_stats + |
436 | ixgbevf_gstrings_stats[i].stat_offset; |
437 | break; |
438 | case IXGBEVF_STATS: |
439 | p = (char *)adapter + |
440 | ixgbevf_gstrings_stats[i].stat_offset; |
441 | break; |
442 | default: |
443 | data[i] = 0; |
444 | continue; |
445 | } |
446 | |
447 | data[i] = (ixgbevf_gstrings_stats[i].sizeof_stat == |
448 | sizeof(u64)) ? *(u64 *)p : *(u32 *)p; |
449 | } |
450 | |
451 | /* populate Tx queue data */ |
452 | for (j = 0; j < adapter->num_tx_queues; j++) { |
453 | ring = adapter->tx_ring[j]; |
454 | if (!ring) { |
455 | data[i++] = 0; |
456 | data[i++] = 0; |
457 | continue; |
458 | } |
459 | |
460 | do { |
461 | start = u64_stats_fetch_begin(syncp: &ring->syncp); |
462 | data[i] = ring->stats.packets; |
463 | data[i + 1] = ring->stats.bytes; |
464 | } while (u64_stats_fetch_retry(syncp: &ring->syncp, start)); |
465 | i += 2; |
466 | } |
467 | |
468 | /* populate XDP queue data */ |
469 | for (j = 0; j < adapter->num_xdp_queues; j++) { |
470 | ring = adapter->xdp_ring[j]; |
471 | if (!ring) { |
472 | data[i++] = 0; |
473 | data[i++] = 0; |
474 | continue; |
475 | } |
476 | |
477 | do { |
478 | start = u64_stats_fetch_begin(syncp: &ring->syncp); |
479 | data[i] = ring->stats.packets; |
480 | data[i + 1] = ring->stats.bytes; |
481 | } while (u64_stats_fetch_retry(syncp: &ring->syncp, start)); |
482 | i += 2; |
483 | } |
484 | |
485 | /* populate Rx queue data */ |
486 | for (j = 0; j < adapter->num_rx_queues; j++) { |
487 | ring = adapter->rx_ring[j]; |
488 | if (!ring) { |
489 | data[i++] = 0; |
490 | data[i++] = 0; |
491 | continue; |
492 | } |
493 | |
494 | do { |
495 | start = u64_stats_fetch_begin(syncp: &ring->syncp); |
496 | data[i] = ring->stats.packets; |
497 | data[i + 1] = ring->stats.bytes; |
498 | } while (u64_stats_fetch_retry(syncp: &ring->syncp, start)); |
499 | i += 2; |
500 | } |
501 | } |
502 | |
503 | static void ixgbevf_get_strings(struct net_device *netdev, u32 stringset, |
504 | u8 *data) |
505 | { |
506 | struct ixgbevf_adapter *adapter = netdev_priv(dev: netdev); |
507 | char *p = (char *)data; |
508 | int i; |
509 | |
510 | switch (stringset) { |
511 | case ETH_SS_TEST: |
512 | memcpy(data, *ixgbe_gstrings_test, |
513 | IXGBEVF_TEST_LEN * ETH_GSTRING_LEN); |
514 | break; |
515 | case ETH_SS_STATS: |
516 | for (i = 0; i < IXGBEVF_GLOBAL_STATS_LEN; i++) { |
517 | memcpy(p, ixgbevf_gstrings_stats[i].stat_string, |
518 | ETH_GSTRING_LEN); |
519 | p += ETH_GSTRING_LEN; |
520 | } |
521 | |
522 | for (i = 0; i < adapter->num_tx_queues; i++) { |
523 | sprintf(buf: p, fmt: "tx_queue_%u_packets" , i); |
524 | p += ETH_GSTRING_LEN; |
525 | sprintf(buf: p, fmt: "tx_queue_%u_bytes" , i); |
526 | p += ETH_GSTRING_LEN; |
527 | } |
528 | for (i = 0; i < adapter->num_xdp_queues; i++) { |
529 | sprintf(buf: p, fmt: "xdp_queue_%u_packets" , i); |
530 | p += ETH_GSTRING_LEN; |
531 | sprintf(buf: p, fmt: "xdp_queue_%u_bytes" , i); |
532 | p += ETH_GSTRING_LEN; |
533 | } |
534 | for (i = 0; i < adapter->num_rx_queues; i++) { |
535 | sprintf(buf: p, fmt: "rx_queue_%u_packets" , i); |
536 | p += ETH_GSTRING_LEN; |
537 | sprintf(buf: p, fmt: "rx_queue_%u_bytes" , i); |
538 | p += ETH_GSTRING_LEN; |
539 | } |
540 | break; |
541 | case ETH_SS_PRIV_FLAGS: |
542 | memcpy(data, ixgbevf_priv_flags_strings, |
543 | IXGBEVF_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN); |
544 | break; |
545 | } |
546 | } |
547 | |
548 | static int ixgbevf_link_test(struct ixgbevf_adapter *adapter, u64 *data) |
549 | { |
550 | struct ixgbe_hw *hw = &adapter->hw; |
551 | bool link_up; |
552 | u32 link_speed = 0; |
553 | *data = 0; |
554 | |
555 | hw->mac.ops.check_link(hw, &link_speed, &link_up, true); |
556 | if (!link_up) |
557 | *data = 1; |
558 | |
559 | return *data; |
560 | } |
561 | |
562 | /* ethtool register test data */ |
563 | struct ixgbevf_reg_test { |
564 | u16 reg; |
565 | u8 array_len; |
566 | u8 test_type; |
567 | u32 mask; |
568 | u32 write; |
569 | }; |
570 | |
571 | /* In the hardware, registers are laid out either singly, in arrays |
572 | * spaced 0x40 bytes apart, or in contiguous tables. We assume |
573 | * most tests take place on arrays or single registers (handled |
574 | * as a single-element array) and special-case the tables. |
575 | * Table tests are always pattern tests. |
576 | * |
577 | * We also make provision for some required setup steps by specifying |
578 | * registers to be written without any read-back testing. |
579 | */ |
580 | |
581 | #define PATTERN_TEST 1 |
582 | #define SET_READ_TEST 2 |
583 | #define WRITE_NO_TEST 3 |
584 | #define TABLE32_TEST 4 |
585 | #define TABLE64_TEST_LO 5 |
586 | #define TABLE64_TEST_HI 6 |
587 | |
588 | /* default VF register test */ |
589 | static const struct ixgbevf_reg_test reg_test_vf[] = { |
590 | { IXGBE_VFRDBAL(0), 2, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 }, |
591 | { IXGBE_VFRDBAH(0), 2, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, |
592 | { IXGBE_VFRDLEN(0), 2, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, |
593 | { IXGBE_VFRXDCTL(0), 2, WRITE_NO_TEST, 0, IXGBE_RXDCTL_ENABLE }, |
594 | { IXGBE_VFRDT(0), 2, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, |
595 | { IXGBE_VFRXDCTL(0), 2, WRITE_NO_TEST, 0, 0 }, |
596 | { IXGBE_VFTDBAL(0), 2, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, |
597 | { IXGBE_VFTDBAH(0), 2, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, |
598 | { IXGBE_VFTDLEN(0), 2, PATTERN_TEST, 0x000FFF80, 0x000FFF80 }, |
599 | { .reg = 0 } |
600 | }; |
601 | |
602 | static const u32 register_test_patterns[] = { |
603 | 0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF |
604 | }; |
605 | |
606 | static bool reg_pattern_test(struct ixgbevf_adapter *adapter, u64 *data, |
607 | int reg, u32 mask, u32 write) |
608 | { |
609 | u32 pat, val, before; |
610 | |
611 | if (IXGBE_REMOVED(adapter->hw.hw_addr)) { |
612 | *data = 1; |
613 | return true; |
614 | } |
615 | for (pat = 0; pat < ARRAY_SIZE(register_test_patterns); pat++) { |
616 | before = ixgbevf_read_reg(hw: &adapter->hw, reg); |
617 | ixgbe_write_reg(hw: &adapter->hw, reg, |
618 | value: register_test_patterns[pat] & write); |
619 | val = ixgbevf_read_reg(hw: &adapter->hw, reg); |
620 | if (val != (register_test_patterns[pat] & write & mask)) { |
621 | hw_dbg(&adapter->hw, |
622 | "pattern test reg %04X failed: got 0x%08X expected 0x%08X\n" , |
623 | reg, val, |
624 | register_test_patterns[pat] & write & mask); |
625 | *data = reg; |
626 | ixgbe_write_reg(hw: &adapter->hw, reg, value: before); |
627 | return true; |
628 | } |
629 | ixgbe_write_reg(hw: &adapter->hw, reg, value: before); |
630 | } |
631 | return false; |
632 | } |
633 | |
634 | static bool reg_set_and_check(struct ixgbevf_adapter *adapter, u64 *data, |
635 | int reg, u32 mask, u32 write) |
636 | { |
637 | u32 val, before; |
638 | |
639 | if (IXGBE_REMOVED(adapter->hw.hw_addr)) { |
640 | *data = 1; |
641 | return true; |
642 | } |
643 | before = ixgbevf_read_reg(hw: &adapter->hw, reg); |
644 | ixgbe_write_reg(hw: &adapter->hw, reg, value: write & mask); |
645 | val = ixgbevf_read_reg(hw: &adapter->hw, reg); |
646 | if ((write & mask) != (val & mask)) { |
647 | pr_err("set/check reg %04X test failed: got 0x%08X expected 0x%08X\n" , |
648 | reg, (val & mask), write & mask); |
649 | *data = reg; |
650 | ixgbe_write_reg(hw: &adapter->hw, reg, value: before); |
651 | return true; |
652 | } |
653 | ixgbe_write_reg(hw: &adapter->hw, reg, value: before); |
654 | return false; |
655 | } |
656 | |
657 | static int ixgbevf_reg_test(struct ixgbevf_adapter *adapter, u64 *data) |
658 | { |
659 | const struct ixgbevf_reg_test *test; |
660 | u32 i; |
661 | |
662 | if (IXGBE_REMOVED(adapter->hw.hw_addr)) { |
663 | dev_err(&adapter->pdev->dev, |
664 | "Adapter removed - register test blocked\n" ); |
665 | *data = 1; |
666 | return 1; |
667 | } |
668 | test = reg_test_vf; |
669 | |
670 | /* Perform the register test, looping through the test table |
671 | * until we either fail or reach the null entry. |
672 | */ |
673 | while (test->reg) { |
674 | for (i = 0; i < test->array_len; i++) { |
675 | bool b = false; |
676 | |
677 | switch (test->test_type) { |
678 | case PATTERN_TEST: |
679 | b = reg_pattern_test(adapter, data, |
680 | reg: test->reg + (i * 0x40), |
681 | mask: test->mask, |
682 | write: test->write); |
683 | break; |
684 | case SET_READ_TEST: |
685 | b = reg_set_and_check(adapter, data, |
686 | reg: test->reg + (i * 0x40), |
687 | mask: test->mask, |
688 | write: test->write); |
689 | break; |
690 | case WRITE_NO_TEST: |
691 | ixgbe_write_reg(hw: &adapter->hw, |
692 | reg: test->reg + (i * 0x40), |
693 | value: test->write); |
694 | break; |
695 | case TABLE32_TEST: |
696 | b = reg_pattern_test(adapter, data, |
697 | reg: test->reg + (i * 4), |
698 | mask: test->mask, |
699 | write: test->write); |
700 | break; |
701 | case TABLE64_TEST_LO: |
702 | b = reg_pattern_test(adapter, data, |
703 | reg: test->reg + (i * 8), |
704 | mask: test->mask, |
705 | write: test->write); |
706 | break; |
707 | case TABLE64_TEST_HI: |
708 | b = reg_pattern_test(adapter, data, |
709 | reg: test->reg + 4 + (i * 8), |
710 | mask: test->mask, |
711 | write: test->write); |
712 | break; |
713 | } |
714 | if (b) |
715 | return 1; |
716 | } |
717 | test++; |
718 | } |
719 | |
720 | *data = 0; |
721 | return *data; |
722 | } |
723 | |
724 | static void ixgbevf_diag_test(struct net_device *netdev, |
725 | struct ethtool_test *eth_test, u64 *data) |
726 | { |
727 | struct ixgbevf_adapter *adapter = netdev_priv(dev: netdev); |
728 | bool if_running = netif_running(dev: netdev); |
729 | |
730 | if (IXGBE_REMOVED(adapter->hw.hw_addr)) { |
731 | dev_err(&adapter->pdev->dev, |
732 | "Adapter removed - test blocked\n" ); |
733 | data[0] = 1; |
734 | data[1] = 1; |
735 | eth_test->flags |= ETH_TEST_FL_FAILED; |
736 | return; |
737 | } |
738 | set_bit(nr: __IXGBEVF_TESTING, addr: &adapter->state); |
739 | if (eth_test->flags == ETH_TEST_FL_OFFLINE) { |
740 | /* Offline tests */ |
741 | |
742 | hw_dbg(&adapter->hw, "offline testing starting\n" ); |
743 | |
744 | /* Link test performed before hardware reset so autoneg doesn't |
745 | * interfere with test result |
746 | */ |
747 | if (ixgbevf_link_test(adapter, data: &data[1])) |
748 | eth_test->flags |= ETH_TEST_FL_FAILED; |
749 | |
750 | if (if_running) |
751 | /* indicate we're in test mode */ |
752 | ixgbevf_close(netdev); |
753 | else |
754 | ixgbevf_reset(adapter); |
755 | |
756 | hw_dbg(&adapter->hw, "register testing starting\n" ); |
757 | if (ixgbevf_reg_test(adapter, data: &data[0])) |
758 | eth_test->flags |= ETH_TEST_FL_FAILED; |
759 | |
760 | ixgbevf_reset(adapter); |
761 | |
762 | clear_bit(nr: __IXGBEVF_TESTING, addr: &adapter->state); |
763 | if (if_running) |
764 | ixgbevf_open(netdev); |
765 | } else { |
766 | hw_dbg(&adapter->hw, "online testing starting\n" ); |
767 | /* Online tests */ |
768 | if (ixgbevf_link_test(adapter, data: &data[1])) |
769 | eth_test->flags |= ETH_TEST_FL_FAILED; |
770 | |
771 | /* Online tests aren't run; pass by default */ |
772 | data[0] = 0; |
773 | |
774 | clear_bit(nr: __IXGBEVF_TESTING, addr: &adapter->state); |
775 | } |
776 | msleep_interruptible(msecs: 4 * 1000); |
777 | } |
778 | |
779 | static int ixgbevf_nway_reset(struct net_device *netdev) |
780 | { |
781 | struct ixgbevf_adapter *adapter = netdev_priv(dev: netdev); |
782 | |
783 | if (netif_running(dev: netdev)) |
784 | ixgbevf_reinit_locked(adapter); |
785 | |
786 | return 0; |
787 | } |
788 | |
789 | static int ixgbevf_get_coalesce(struct net_device *netdev, |
790 | struct ethtool_coalesce *ec, |
791 | struct kernel_ethtool_coalesce *kernel_coal, |
792 | struct netlink_ext_ack *extack) |
793 | { |
794 | struct ixgbevf_adapter *adapter = netdev_priv(dev: netdev); |
795 | |
796 | /* only valid if in constant ITR mode */ |
797 | if (adapter->rx_itr_setting <= 1) |
798 | ec->rx_coalesce_usecs = adapter->rx_itr_setting; |
799 | else |
800 | ec->rx_coalesce_usecs = adapter->rx_itr_setting >> 2; |
801 | |
802 | /* if in mixed Tx/Rx queues per vector mode, report only Rx settings */ |
803 | if (adapter->q_vector[0]->tx.count && adapter->q_vector[0]->rx.count) |
804 | return 0; |
805 | |
806 | /* only valid if in constant ITR mode */ |
807 | if (adapter->tx_itr_setting <= 1) |
808 | ec->tx_coalesce_usecs = adapter->tx_itr_setting; |
809 | else |
810 | ec->tx_coalesce_usecs = adapter->tx_itr_setting >> 2; |
811 | |
812 | return 0; |
813 | } |
814 | |
815 | static int ixgbevf_set_coalesce(struct net_device *netdev, |
816 | struct ethtool_coalesce *ec, |
817 | struct kernel_ethtool_coalesce *kernel_coal, |
818 | struct netlink_ext_ack *extack) |
819 | { |
820 | struct ixgbevf_adapter *adapter = netdev_priv(dev: netdev); |
821 | struct ixgbevf_q_vector *q_vector; |
822 | int num_vectors, i; |
823 | u16 tx_itr_param, rx_itr_param; |
824 | |
825 | /* don't accept Tx specific changes if we've got mixed RxTx vectors */ |
826 | if (adapter->q_vector[0]->tx.count && |
827 | adapter->q_vector[0]->rx.count && ec->tx_coalesce_usecs) |
828 | return -EINVAL; |
829 | |
830 | if ((ec->rx_coalesce_usecs > (IXGBE_MAX_EITR >> 2)) || |
831 | (ec->tx_coalesce_usecs > (IXGBE_MAX_EITR >> 2))) |
832 | return -EINVAL; |
833 | |
834 | if (ec->rx_coalesce_usecs > 1) |
835 | adapter->rx_itr_setting = ec->rx_coalesce_usecs << 2; |
836 | else |
837 | adapter->rx_itr_setting = ec->rx_coalesce_usecs; |
838 | |
839 | if (adapter->rx_itr_setting == 1) |
840 | rx_itr_param = IXGBE_20K_ITR; |
841 | else |
842 | rx_itr_param = adapter->rx_itr_setting; |
843 | |
844 | if (ec->tx_coalesce_usecs > 1) |
845 | adapter->tx_itr_setting = ec->tx_coalesce_usecs << 2; |
846 | else |
847 | adapter->tx_itr_setting = ec->tx_coalesce_usecs; |
848 | |
849 | if (adapter->tx_itr_setting == 1) |
850 | tx_itr_param = IXGBE_12K_ITR; |
851 | else |
852 | tx_itr_param = adapter->tx_itr_setting; |
853 | |
854 | num_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; |
855 | |
856 | for (i = 0; i < num_vectors; i++) { |
857 | q_vector = adapter->q_vector[i]; |
858 | if (q_vector->tx.count && !q_vector->rx.count) |
859 | /* Tx only */ |
860 | q_vector->itr = tx_itr_param; |
861 | else |
862 | /* Rx only or mixed */ |
863 | q_vector->itr = rx_itr_param; |
864 | ixgbevf_write_eitr(q_vector); |
865 | } |
866 | |
867 | return 0; |
868 | } |
869 | |
870 | static int ixgbevf_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, |
871 | u32 *rules __always_unused) |
872 | { |
873 | struct ixgbevf_adapter *adapter = netdev_priv(dev); |
874 | |
875 | switch (info->cmd) { |
876 | case ETHTOOL_GRXRINGS: |
877 | info->data = adapter->num_rx_queues; |
878 | return 0; |
879 | default: |
880 | hw_dbg(&adapter->hw, "Command parameters not supported\n" ); |
881 | return -EOPNOTSUPP; |
882 | } |
883 | } |
884 | |
885 | static u32 ixgbevf_get_rxfh_indir_size(struct net_device *netdev) |
886 | { |
887 | struct ixgbevf_adapter *adapter = netdev_priv(dev: netdev); |
888 | |
889 | if (adapter->hw.mac.type >= ixgbe_mac_X550_vf) |
890 | return IXGBEVF_X550_VFRETA_SIZE; |
891 | |
892 | return IXGBEVF_82599_RETA_SIZE; |
893 | } |
894 | |
895 | static u32 ixgbevf_get_rxfh_key_size(struct net_device *netdev) |
896 | { |
897 | return IXGBEVF_RSS_HASH_KEY_SIZE; |
898 | } |
899 | |
900 | static int ixgbevf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, |
901 | u8 *hfunc) |
902 | { |
903 | struct ixgbevf_adapter *adapter = netdev_priv(dev: netdev); |
904 | int err = 0; |
905 | |
906 | if (hfunc) |
907 | *hfunc = ETH_RSS_HASH_TOP; |
908 | |
909 | if (adapter->hw.mac.type >= ixgbe_mac_X550_vf) { |
910 | if (key) |
911 | memcpy(key, adapter->rss_key, |
912 | ixgbevf_get_rxfh_key_size(netdev)); |
913 | |
914 | if (indir) { |
915 | int i; |
916 | |
917 | for (i = 0; i < IXGBEVF_X550_VFRETA_SIZE; i++) |
918 | indir[i] = adapter->rss_indir_tbl[i]; |
919 | } |
920 | } else { |
921 | /* If neither indirection table nor hash key was requested |
922 | * - just return a success avoiding taking any locks. |
923 | */ |
924 | if (!indir && !key) |
925 | return 0; |
926 | |
927 | spin_lock_bh(lock: &adapter->mbx_lock); |
928 | if (indir) |
929 | err = ixgbevf_get_reta_locked(hw: &adapter->hw, reta: indir, |
930 | num_rx_queues: adapter->num_rx_queues); |
931 | |
932 | if (!err && key) |
933 | err = ixgbevf_get_rss_key_locked(hw: &adapter->hw, rss_key: key); |
934 | |
935 | spin_unlock_bh(lock: &adapter->mbx_lock); |
936 | } |
937 | |
938 | return err; |
939 | } |
940 | |
941 | static u32 ixgbevf_get_priv_flags(struct net_device *netdev) |
942 | { |
943 | struct ixgbevf_adapter *adapter = netdev_priv(dev: netdev); |
944 | u32 priv_flags = 0; |
945 | |
946 | if (adapter->flags & IXGBEVF_FLAGS_LEGACY_RX) |
947 | priv_flags |= IXGBEVF_PRIV_FLAGS_LEGACY_RX; |
948 | |
949 | return priv_flags; |
950 | } |
951 | |
952 | static int ixgbevf_set_priv_flags(struct net_device *netdev, u32 priv_flags) |
953 | { |
954 | struct ixgbevf_adapter *adapter = netdev_priv(dev: netdev); |
955 | unsigned int flags = adapter->flags; |
956 | |
957 | flags &= ~IXGBEVF_FLAGS_LEGACY_RX; |
958 | if (priv_flags & IXGBEVF_PRIV_FLAGS_LEGACY_RX) |
959 | flags |= IXGBEVF_FLAGS_LEGACY_RX; |
960 | |
961 | if (flags != adapter->flags) { |
962 | adapter->flags = flags; |
963 | |
964 | /* reset interface to repopulate queues */ |
965 | if (netif_running(dev: netdev)) |
966 | ixgbevf_reinit_locked(adapter); |
967 | } |
968 | |
969 | return 0; |
970 | } |
971 | |
972 | static const struct ethtool_ops ixgbevf_ethtool_ops = { |
973 | .supported_coalesce_params = ETHTOOL_COALESCE_USECS, |
974 | .get_drvinfo = ixgbevf_get_drvinfo, |
975 | .get_regs_len = ixgbevf_get_regs_len, |
976 | .get_regs = ixgbevf_get_regs, |
977 | .nway_reset = ixgbevf_nway_reset, |
978 | .get_link = ethtool_op_get_link, |
979 | .get_ringparam = ixgbevf_get_ringparam, |
980 | .set_ringparam = ixgbevf_set_ringparam, |
981 | .get_msglevel = ixgbevf_get_msglevel, |
982 | .set_msglevel = ixgbevf_set_msglevel, |
983 | .self_test = ixgbevf_diag_test, |
984 | .get_sset_count = ixgbevf_get_sset_count, |
985 | .get_strings = ixgbevf_get_strings, |
986 | .get_ethtool_stats = ixgbevf_get_ethtool_stats, |
987 | .get_coalesce = ixgbevf_get_coalesce, |
988 | .set_coalesce = ixgbevf_set_coalesce, |
989 | .get_rxnfc = ixgbevf_get_rxnfc, |
990 | .get_rxfh_indir_size = ixgbevf_get_rxfh_indir_size, |
991 | .get_rxfh_key_size = ixgbevf_get_rxfh_key_size, |
992 | .get_rxfh = ixgbevf_get_rxfh, |
993 | .get_link_ksettings = ixgbevf_get_link_ksettings, |
994 | .get_priv_flags = ixgbevf_get_priv_flags, |
995 | .set_priv_flags = ixgbevf_set_priv_flags, |
996 | }; |
997 | |
998 | void ixgbevf_set_ethtool_ops(struct net_device *netdev) |
999 | { |
1000 | netdev->ethtool_ops = &ixgbevf_ethtool_ops; |
1001 | } |
1002 | |