ace18d2580490bc29b32c3cbe60a394a6ace8642
[openwrt/staging/blogic.git] / drivers / net / ethernet / huawei / hinic / hinic_ethtool.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Huawei HiNIC PCI Express Linux driver
3 * Copyright(c) 2017 Huawei Technologies Co., Ltd
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 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 */
15
16 #include <linux/kernel.h>
17 #include <linux/pci.h>
18 #include <linux/device.h>
19 #include <linux/module.h>
20 #include <linux/types.h>
21 #include <linux/errno.h>
22 #include <linux/interrupt.h>
23 #include <linux/etherdevice.h>
24 #include <linux/netdevice.h>
25 #include <linux/if_vlan.h>
26 #include <linux/ethtool.h>
27 #include <linux/vmalloc.h>
28
29 #include "hinic_hw_qp.h"
30 #include "hinic_hw_dev.h"
31 #include "hinic_port.h"
32 #include "hinic_tx.h"
33 #include "hinic_rx.h"
34 #include "hinic_dev.h"
35
36 #define SET_LINK_STR_MAX_LEN 128
37
38 #define GET_SUPPORTED_MODE 0
39 #define GET_ADVERTISED_MODE 1
40
41 #define ETHTOOL_ADD_SUPPORTED_SPEED_LINK_MODE(ecmd, mode) \
42 ((ecmd)->supported |= \
43 (1UL << hw_to_ethtool_link_mode_table[mode].link_mode_bit))
44 #define ETHTOOL_ADD_ADVERTISED_SPEED_LINK_MODE(ecmd, mode) \
45 ((ecmd)->advertising |= \
46 (1UL << hw_to_ethtool_link_mode_table[mode].link_mode_bit))
47 #define ETHTOOL_ADD_SUPPORTED_LINK_MODE(ecmd, mode) \
48 ((ecmd)->supported |= SUPPORTED_##mode)
49 #define ETHTOOL_ADD_ADVERTISED_LINK_MODE(ecmd, mode) \
50 ((ecmd)->advertising |= ADVERTISED_##mode)
51
52 struct hw2ethtool_link_mode {
53 enum ethtool_link_mode_bit_indices link_mode_bit;
54 u32 speed;
55 enum hinic_link_mode hw_link_mode;
56 };
57
58 struct cmd_link_settings {
59 u64 supported;
60 u64 advertising;
61
62 u32 speed;
63 u8 duplex;
64 u8 port;
65 u8 autoneg;
66 };
67
68 static u32 hw_to_ethtool_speed[LINK_SPEED_LEVELS] = {
69 SPEED_10, SPEED_100,
70 SPEED_1000, SPEED_10000,
71 SPEED_25000, SPEED_40000,
72 SPEED_100000
73 };
74
75 static struct hw2ethtool_link_mode
76 hw_to_ethtool_link_mode_table[HINIC_LINK_MODE_NUMBERS] = {
77 {
78 .link_mode_bit = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
79 .speed = SPEED_10000,
80 .hw_link_mode = HINIC_10GE_BASE_KR,
81 },
82 {
83 .link_mode_bit = ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
84 .speed = SPEED_40000,
85 .hw_link_mode = HINIC_40GE_BASE_KR4,
86 },
87 {
88 .link_mode_bit = ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
89 .speed = SPEED_40000,
90 .hw_link_mode = HINIC_40GE_BASE_CR4,
91 },
92 {
93 .link_mode_bit = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
94 .speed = SPEED_100000,
95 .hw_link_mode = HINIC_100GE_BASE_KR4,
96 },
97 {
98 .link_mode_bit = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
99 .speed = SPEED_100000,
100 .hw_link_mode = HINIC_100GE_BASE_CR4,
101 },
102 {
103 .link_mode_bit = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
104 .speed = SPEED_25000,
105 .hw_link_mode = HINIC_25GE_BASE_KR_S,
106 },
107 {
108 .link_mode_bit = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
109 .speed = SPEED_25000,
110 .hw_link_mode = HINIC_25GE_BASE_CR_S,
111 },
112 {
113 .link_mode_bit = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
114 .speed = SPEED_25000,
115 .hw_link_mode = HINIC_25GE_BASE_KR,
116 },
117 {
118 .link_mode_bit = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
119 .speed = SPEED_25000,
120 .hw_link_mode = HINIC_25GE_BASE_CR,
121 },
122 {
123 .link_mode_bit = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
124 .speed = SPEED_1000,
125 .hw_link_mode = HINIC_GE_BASE_KX,
126 },
127 };
128
129 static void set_link_speed(struct ethtool_link_ksettings *link_ksettings,
130 enum hinic_speed speed)
131 {
132 switch (speed) {
133 case HINIC_SPEED_10MB_LINK:
134 link_ksettings->base.speed = SPEED_10;
135 break;
136
137 case HINIC_SPEED_100MB_LINK:
138 link_ksettings->base.speed = SPEED_100;
139 break;
140
141 case HINIC_SPEED_1000MB_LINK:
142 link_ksettings->base.speed = SPEED_1000;
143 break;
144
145 case HINIC_SPEED_10GB_LINK:
146 link_ksettings->base.speed = SPEED_10000;
147 break;
148
149 case HINIC_SPEED_25GB_LINK:
150 link_ksettings->base.speed = SPEED_25000;
151 break;
152
153 case HINIC_SPEED_40GB_LINK:
154 link_ksettings->base.speed = SPEED_40000;
155 break;
156
157 case HINIC_SPEED_100GB_LINK:
158 link_ksettings->base.speed = SPEED_100000;
159 break;
160
161 default:
162 link_ksettings->base.speed = SPEED_UNKNOWN;
163 break;
164 }
165 }
166
167 static int hinic_get_link_mode_index(enum hinic_link_mode link_mode)
168 {
169 int i = 0;
170
171 for (i = 0; i < HINIC_LINK_MODE_NUMBERS; i++) {
172 if (link_mode == hw_to_ethtool_link_mode_table[i].hw_link_mode)
173 break;
174 }
175
176 return i;
177 }
178
179 static void hinic_add_ethtool_link_mode(struct cmd_link_settings *link_settings,
180 enum hinic_link_mode hw_link_mode,
181 u32 name)
182 {
183 enum hinic_link_mode link_mode;
184 int idx = 0;
185
186 for (link_mode = 0; link_mode < HINIC_LINK_MODE_NUMBERS; link_mode++) {
187 if (hw_link_mode & ((u32)1 << link_mode)) {
188 idx = hinic_get_link_mode_index(link_mode);
189 if (idx >= HINIC_LINK_MODE_NUMBERS)
190 continue;
191
192 if (name == GET_SUPPORTED_MODE)
193 ETHTOOL_ADD_SUPPORTED_SPEED_LINK_MODE
194 (link_settings, idx);
195 else
196 ETHTOOL_ADD_ADVERTISED_SPEED_LINK_MODE
197 (link_settings, idx);
198 }
199 }
200 }
201
202 static void hinic_link_port_type(struct cmd_link_settings *link_settings,
203 enum hinic_port_type port_type)
204 {
205 switch (port_type) {
206 case HINIC_PORT_ELEC:
207 case HINIC_PORT_TP:
208 ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, TP);
209 ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, TP);
210 link_settings->port = PORT_TP;
211 break;
212
213 case HINIC_PORT_AOC:
214 case HINIC_PORT_FIBRE:
215 ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, FIBRE);
216 ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, FIBRE);
217 link_settings->port = PORT_FIBRE;
218 break;
219
220 case HINIC_PORT_COPPER:
221 ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, FIBRE);
222 ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, FIBRE);
223 link_settings->port = PORT_DA;
224 break;
225
226 case HINIC_PORT_BACKPLANE:
227 ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, Backplane);
228 ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Backplane);
229 link_settings->port = PORT_NONE;
230 break;
231
232 default:
233 link_settings->port = PORT_OTHER;
234 break;
235 }
236 }
237
238 static int hinic_get_link_ksettings(struct net_device *netdev,
239 struct ethtool_link_ksettings
240 *link_ksettings)
241 {
242 struct hinic_dev *nic_dev = netdev_priv(netdev);
243 struct hinic_link_mode_cmd link_mode = { 0 };
244 struct hinic_pause_config pause_info = { 0 };
245 struct cmd_link_settings settings = { 0 };
246 enum hinic_port_link_state link_state;
247 struct hinic_port_cap port_cap;
248 int err;
249
250 ethtool_link_ksettings_zero_link_mode(link_ksettings, supported);
251 ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);
252
253 link_ksettings->base.speed = SPEED_UNKNOWN;
254 link_ksettings->base.autoneg = AUTONEG_DISABLE;
255 link_ksettings->base.duplex = DUPLEX_UNKNOWN;
256
257 err = hinic_port_get_cap(nic_dev, &port_cap);
258 if (err)
259 return err;
260
261 hinic_link_port_type(&settings, port_cap.port_type);
262 link_ksettings->base.port = settings.port;
263
264 err = hinic_port_link_state(nic_dev, &link_state);
265 if (err)
266 return err;
267
268 if (link_state == HINIC_LINK_STATE_UP) {
269 set_link_speed(link_ksettings, port_cap.speed);
270 link_ksettings->base.duplex =
271 (port_cap.duplex == HINIC_DUPLEX_FULL) ?
272 DUPLEX_FULL : DUPLEX_HALF;
273 }
274
275 if (!!(port_cap.autoneg_cap & HINIC_AUTONEG_SUPPORTED))
276 ethtool_link_ksettings_add_link_mode(link_ksettings,
277 advertising, Autoneg);
278
279 if (port_cap.autoneg_state == HINIC_AUTONEG_ACTIVE)
280 link_ksettings->base.autoneg = AUTONEG_ENABLE;
281
282 err = hinic_get_link_mode(nic_dev->hwdev, &link_mode);
283 if (err || link_mode.supported == HINIC_SUPPORTED_UNKNOWN ||
284 link_mode.advertised == HINIC_SUPPORTED_UNKNOWN)
285 return -EIO;
286
287 hinic_add_ethtool_link_mode(&settings, link_mode.supported,
288 GET_SUPPORTED_MODE);
289 hinic_add_ethtool_link_mode(&settings, link_mode.advertised,
290 GET_ADVERTISED_MODE);
291
292 if (!HINIC_IS_VF(nic_dev->hwdev->hwif)) {
293 err = hinic_get_hw_pause_info(nic_dev->hwdev, &pause_info);
294 if (err)
295 return err;
296 ETHTOOL_ADD_SUPPORTED_LINK_MODE(&settings, Pause);
297 if (pause_info.rx_pause && pause_info.tx_pause) {
298 ETHTOOL_ADD_ADVERTISED_LINK_MODE(&settings, Pause);
299 } else if (pause_info.tx_pause) {
300 ETHTOOL_ADD_ADVERTISED_LINK_MODE(&settings, Asym_Pause);
301 } else if (pause_info.rx_pause) {
302 ETHTOOL_ADD_ADVERTISED_LINK_MODE(&settings, Pause);
303 ETHTOOL_ADD_ADVERTISED_LINK_MODE(&settings, Asym_Pause);
304 }
305 }
306
307 bitmap_copy(link_ksettings->link_modes.supported,
308 (unsigned long *)&settings.supported,
309 __ETHTOOL_LINK_MODE_MASK_NBITS);
310 bitmap_copy(link_ksettings->link_modes.advertising,
311 (unsigned long *)&settings.advertising,
312 __ETHTOOL_LINK_MODE_MASK_NBITS);
313
314 return 0;
315 }
316
317 static int hinic_ethtool_to_hw_speed_level(u32 speed)
318 {
319 int i;
320
321 for (i = 0; i < LINK_SPEED_LEVELS; i++) {
322 if (hw_to_ethtool_speed[i] == speed)
323 break;
324 }
325
326 return i;
327 }
328
329 static bool hinic_is_support_speed(enum hinic_link_mode supported_link,
330 u32 speed)
331 {
332 enum hinic_link_mode link_mode;
333 int idx;
334
335 for (link_mode = 0; link_mode < HINIC_LINK_MODE_NUMBERS; link_mode++) {
336 if (!(supported_link & ((u32)1 << link_mode)))
337 continue;
338
339 idx = hinic_get_link_mode_index(link_mode);
340 if (idx >= HINIC_LINK_MODE_NUMBERS)
341 continue;
342
343 if (hw_to_ethtool_link_mode_table[idx].speed == speed)
344 return true;
345 }
346
347 return false;
348 }
349
350 static bool hinic_is_speed_legal(struct hinic_dev *nic_dev, u32 speed)
351 {
352 struct hinic_link_mode_cmd link_mode = { 0 };
353 struct net_device *netdev = nic_dev->netdev;
354 enum nic_speed_level speed_level = 0;
355 int err;
356
357 err = hinic_get_link_mode(nic_dev->hwdev, &link_mode);
358 if (err)
359 return false;
360
361 if (link_mode.supported == HINIC_SUPPORTED_UNKNOWN ||
362 link_mode.advertised == HINIC_SUPPORTED_UNKNOWN)
363 return false;
364
365 speed_level = hinic_ethtool_to_hw_speed_level(speed);
366 if (speed_level >= LINK_SPEED_LEVELS ||
367 !hinic_is_support_speed(link_mode.supported, speed)) {
368 netif_err(nic_dev, drv, netdev,
369 "Unsupported speed: %d\n", speed);
370 return false;
371 }
372
373 return true;
374 }
375
376 static int get_link_settings_type(struct hinic_dev *nic_dev,
377 u8 autoneg, u32 speed, u32 *set_settings)
378 {
379 struct hinic_port_cap port_cap = { 0 };
380 int err;
381
382 err = hinic_port_get_cap(nic_dev, &port_cap);
383 if (err)
384 return err;
385
386 /* always set autonegotiation */
387 if (port_cap.autoneg_cap)
388 *set_settings |= HILINK_LINK_SET_AUTONEG;
389
390 if (autoneg == AUTONEG_ENABLE) {
391 if (!port_cap.autoneg_cap) {
392 netif_err(nic_dev, drv, nic_dev->netdev, "Not support autoneg\n");
393 return -EOPNOTSUPP;
394 }
395 } else if (speed != (u32)SPEED_UNKNOWN) {
396 /* set speed only when autoneg is disabled */
397 if (!hinic_is_speed_legal(nic_dev, speed))
398 return -EINVAL;
399 *set_settings |= HILINK_LINK_SET_SPEED;
400 } else {
401 netif_err(nic_dev, drv, nic_dev->netdev, "Need to set speed when autoneg is off\n");
402 return -EOPNOTSUPP;
403 }
404
405 return 0;
406 }
407
408 static int set_link_settings_separate_cmd(struct hinic_dev *nic_dev,
409 u32 set_settings, u8 autoneg,
410 u32 speed)
411 {
412 enum nic_speed_level speed_level = 0;
413 int err = 0;
414
415 if (set_settings & HILINK_LINK_SET_AUTONEG) {
416 err = hinic_set_autoneg(nic_dev->hwdev,
417 (autoneg == AUTONEG_ENABLE));
418 if (err)
419 netif_err(nic_dev, drv, nic_dev->netdev, "%s autoneg failed\n",
420 (autoneg == AUTONEG_ENABLE) ?
421 "Enable" : "Disable");
422 else
423 netif_info(nic_dev, drv, nic_dev->netdev, "%s autoneg successfully\n",
424 (autoneg == AUTONEG_ENABLE) ?
425 "Enable" : "Disable");
426 }
427
428 if (!err && (set_settings & HILINK_LINK_SET_SPEED)) {
429 speed_level = hinic_ethtool_to_hw_speed_level(speed);
430 err = hinic_set_speed(nic_dev->hwdev, speed_level);
431 if (err)
432 netif_err(nic_dev, drv, nic_dev->netdev, "Set speed %d failed\n",
433 speed);
434 else
435 netif_info(nic_dev, drv, nic_dev->netdev, "Set speed %d successfully\n",
436 speed);
437 }
438
439 return err;
440 }
441
442 static int hinic_set_settings_to_hw(struct hinic_dev *nic_dev,
443 u32 set_settings, u8 autoneg, u32 speed)
444 {
445 struct hinic_link_ksettings_info settings = {0};
446 char set_link_str[SET_LINK_STR_MAX_LEN] = {0};
447 struct net_device *netdev = nic_dev->netdev;
448 enum nic_speed_level speed_level = 0;
449 int err;
450
451 err = snprintf(set_link_str, SET_LINK_STR_MAX_LEN, "%s",
452 (set_settings & HILINK_LINK_SET_AUTONEG) ?
453 (autoneg ? "autong enable " : "autong disable ") : "");
454 if (err < 0 || err >= SET_LINK_STR_MAX_LEN) {
455 netif_err(nic_dev, drv, netdev, "Failed to snprintf link state, function return(%d) and dest_len(%d)\n",
456 err, SET_LINK_STR_MAX_LEN);
457 return -EFAULT;
458 }
459
460 if (set_settings & HILINK_LINK_SET_SPEED) {
461 speed_level = hinic_ethtool_to_hw_speed_level(speed);
462 err = snprintf(set_link_str, SET_LINK_STR_MAX_LEN,
463 "%sspeed %d ", set_link_str, speed);
464 if (err <= 0 || err >= SET_LINK_STR_MAX_LEN) {
465 netif_err(nic_dev, drv, netdev, "Failed to snprintf link speed, function return(%d) and dest_len(%d)\n",
466 err, SET_LINK_STR_MAX_LEN);
467 return -EFAULT;
468 }
469 }
470
471 settings.func_id = HINIC_HWIF_FUNC_IDX(nic_dev->hwdev->hwif);
472 settings.valid_bitmap = set_settings;
473 settings.autoneg = autoneg;
474 settings.speed = speed_level;
475
476 err = hinic_set_link_settings(nic_dev->hwdev, &settings);
477 if (err != HINIC_MGMT_CMD_UNSUPPORTED) {
478 if (err)
479 netif_err(nic_dev, drv, netdev, "Set %s failed\n",
480 set_link_str);
481 else
482 netif_info(nic_dev, drv, netdev, "Set %s successfully\n",
483 set_link_str);
484
485 return err;
486 }
487
488 return set_link_settings_separate_cmd(nic_dev, set_settings, autoneg,
489 speed);
490 }
491
492 static int set_link_settings(struct net_device *netdev, u8 autoneg, u32 speed)
493 {
494 struct hinic_dev *nic_dev = netdev_priv(netdev);
495 u32 set_settings = 0;
496 int err;
497
498 err = get_link_settings_type(nic_dev, autoneg, speed, &set_settings);
499 if (err)
500 return err;
501
502 if (set_settings)
503 err = hinic_set_settings_to_hw(nic_dev, set_settings,
504 autoneg, speed);
505 else
506 netif_info(nic_dev, drv, netdev, "Nothing changed, exit without setting anything\n");
507
508 return err;
509 }
510
511 static int hinic_set_link_ksettings(struct net_device *netdev, const struct
512 ethtool_link_ksettings *link_settings)
513 {
514 /* only support to set autoneg and speed */
515 return set_link_settings(netdev, link_settings->base.autoneg,
516 link_settings->base.speed);
517 }
518
519 static void hinic_get_drvinfo(struct net_device *netdev,
520 struct ethtool_drvinfo *info)
521 {
522 struct hinic_dev *nic_dev = netdev_priv(netdev);
523 u8 mgmt_ver[HINIC_MGMT_VERSION_MAX_LEN] = {0};
524 struct hinic_hwdev *hwdev = nic_dev->hwdev;
525 struct hinic_hwif *hwif = hwdev->hwif;
526 int err;
527
528 strlcpy(info->driver, HINIC_DRV_NAME, sizeof(info->driver));
529 strlcpy(info->bus_info, pci_name(hwif->pdev), sizeof(info->bus_info));
530
531 err = hinic_get_mgmt_version(nic_dev, mgmt_ver);
532 if (err)
533 return;
534
535 snprintf(info->fw_version, sizeof(info->fw_version), "%s", mgmt_ver);
536 }
537
538 static void hinic_get_ringparam(struct net_device *netdev,
539 struct ethtool_ringparam *ring)
540 {
541 struct hinic_dev *nic_dev = netdev_priv(netdev);
542
543 ring->rx_max_pending = HINIC_MAX_QUEUE_DEPTH;
544 ring->tx_max_pending = HINIC_MAX_QUEUE_DEPTH;
545 ring->rx_pending = nic_dev->rq_depth;
546 ring->tx_pending = nic_dev->sq_depth;
547 }
548
549 static int check_ringparam_valid(struct hinic_dev *nic_dev,
550 struct ethtool_ringparam *ring)
551 {
552 if (ring->rx_jumbo_pending || ring->rx_mini_pending) {
553 netif_err(nic_dev, drv, nic_dev->netdev,
554 "Unsupported rx_jumbo_pending/rx_mini_pending\n");
555 return -EINVAL;
556 }
557
558 if (ring->tx_pending > HINIC_MAX_QUEUE_DEPTH ||
559 ring->tx_pending < HINIC_MIN_QUEUE_DEPTH ||
560 ring->rx_pending > HINIC_MAX_QUEUE_DEPTH ||
561 ring->rx_pending < HINIC_MIN_QUEUE_DEPTH) {
562 netif_err(nic_dev, drv, nic_dev->netdev,
563 "Queue depth out of range [%d-%d]\n",
564 HINIC_MIN_QUEUE_DEPTH, HINIC_MAX_QUEUE_DEPTH);
565 return -EINVAL;
566 }
567
568 return 0;
569 }
570
571 static int hinic_set_ringparam(struct net_device *netdev,
572 struct ethtool_ringparam *ring)
573 {
574 struct hinic_dev *nic_dev = netdev_priv(netdev);
575 u16 new_sq_depth, new_rq_depth;
576 int err;
577
578 err = check_ringparam_valid(nic_dev, ring);
579 if (err)
580 return err;
581
582 new_sq_depth = (u16)(1U << (u16)ilog2(ring->tx_pending));
583 new_rq_depth = (u16)(1U << (u16)ilog2(ring->rx_pending));
584
585 if (new_sq_depth == nic_dev->sq_depth &&
586 new_rq_depth == nic_dev->rq_depth)
587 return 0;
588
589 netif_info(nic_dev, drv, netdev,
590 "Change Tx/Rx ring depth from %d/%d to %d/%d\n",
591 nic_dev->sq_depth, nic_dev->rq_depth,
592 new_sq_depth, new_rq_depth);
593
594 nic_dev->sq_depth = new_sq_depth;
595 nic_dev->rq_depth = new_rq_depth;
596
597 if (netif_running(netdev)) {
598 netif_info(nic_dev, drv, netdev, "Restarting netdev\n");
599 err = hinic_close(netdev);
600 if (err) {
601 netif_err(nic_dev, drv, netdev,
602 "Failed to close netdev\n");
603 return -EFAULT;
604 }
605
606 err = hinic_open(netdev);
607 if (err) {
608 netif_err(nic_dev, drv, netdev,
609 "Failed to open netdev\n");
610 return -EFAULT;
611 }
612 }
613
614 return 0;
615 }
616 static void hinic_get_channels(struct net_device *netdev,
617 struct ethtool_channels *channels)
618 {
619 struct hinic_dev *nic_dev = netdev_priv(netdev);
620 struct hinic_hwdev *hwdev = nic_dev->hwdev;
621
622 channels->max_rx = hwdev->nic_cap.max_qps;
623 channels->max_tx = hwdev->nic_cap.max_qps;
624 channels->max_other = 0;
625 channels->max_combined = 0;
626 channels->rx_count = hinic_hwdev_num_qps(hwdev);
627 channels->tx_count = hinic_hwdev_num_qps(hwdev);
628 channels->other_count = 0;
629 channels->combined_count = 0;
630 }
631
632 static int hinic_get_rss_hash_opts(struct hinic_dev *nic_dev,
633 struct ethtool_rxnfc *cmd)
634 {
635 struct hinic_rss_type rss_type = { 0 };
636 int err;
637
638 cmd->data = 0;
639
640 if (!(nic_dev->flags & HINIC_RSS_ENABLE))
641 return 0;
642
643 err = hinic_get_rss_type(nic_dev, nic_dev->rss_tmpl_idx,
644 &rss_type);
645 if (err)
646 return err;
647
648 cmd->data = RXH_IP_SRC | RXH_IP_DST;
649 switch (cmd->flow_type) {
650 case TCP_V4_FLOW:
651 if (rss_type.tcp_ipv4)
652 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
653 break;
654 case TCP_V6_FLOW:
655 if (rss_type.tcp_ipv6)
656 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
657 break;
658 case UDP_V4_FLOW:
659 if (rss_type.udp_ipv4)
660 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
661 break;
662 case UDP_V6_FLOW:
663 if (rss_type.udp_ipv6)
664 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
665 break;
666 case IPV4_FLOW:
667 case IPV6_FLOW:
668 break;
669 default:
670 cmd->data = 0;
671 return -EINVAL;
672 }
673
674 return 0;
675 }
676
677 static int set_l4_rss_hash_ops(struct ethtool_rxnfc *cmd,
678 struct hinic_rss_type *rss_type)
679 {
680 u8 rss_l4_en = 0;
681
682 switch (cmd->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
683 case 0:
684 rss_l4_en = 0;
685 break;
686 case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
687 rss_l4_en = 1;
688 break;
689 default:
690 return -EINVAL;
691 }
692
693 switch (cmd->flow_type) {
694 case TCP_V4_FLOW:
695 rss_type->tcp_ipv4 = rss_l4_en;
696 break;
697 case TCP_V6_FLOW:
698 rss_type->tcp_ipv6 = rss_l4_en;
699 break;
700 case UDP_V4_FLOW:
701 rss_type->udp_ipv4 = rss_l4_en;
702 break;
703 case UDP_V6_FLOW:
704 rss_type->udp_ipv6 = rss_l4_en;
705 break;
706 default:
707 return -EINVAL;
708 }
709
710 return 0;
711 }
712
713 static int hinic_set_rss_hash_opts(struct hinic_dev *nic_dev,
714 struct ethtool_rxnfc *cmd)
715 {
716 struct hinic_rss_type *rss_type = &nic_dev->rss_type;
717 int err;
718
719 if (!(nic_dev->flags & HINIC_RSS_ENABLE)) {
720 cmd->data = 0;
721 return -EOPNOTSUPP;
722 }
723
724 /* RSS does not support anything other than hashing
725 * to queues on src and dst IPs and ports
726 */
727 if (cmd->data & ~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 |
728 RXH_L4_B_2_3))
729 return -EINVAL;
730
731 /* We need at least the IP SRC and DEST fields for hashing */
732 if (!(cmd->data & RXH_IP_SRC) || !(cmd->data & RXH_IP_DST))
733 return -EINVAL;
734
735 err = hinic_get_rss_type(nic_dev,
736 nic_dev->rss_tmpl_idx, rss_type);
737 if (err)
738 return -EFAULT;
739
740 switch (cmd->flow_type) {
741 case TCP_V4_FLOW:
742 case TCP_V6_FLOW:
743 case UDP_V4_FLOW:
744 case UDP_V6_FLOW:
745 err = set_l4_rss_hash_ops(cmd, rss_type);
746 if (err)
747 return err;
748 break;
749 case IPV4_FLOW:
750 rss_type->ipv4 = 1;
751 break;
752 case IPV6_FLOW:
753 rss_type->ipv6 = 1;
754 break;
755 default:
756 return -EINVAL;
757 }
758
759 err = hinic_set_rss_type(nic_dev, nic_dev->rss_tmpl_idx,
760 *rss_type);
761 if (err)
762 return -EFAULT;
763
764 return 0;
765 }
766
767 static int __set_rss_rxfh(struct net_device *netdev,
768 const u32 *indir, const u8 *key)
769 {
770 struct hinic_dev *nic_dev = netdev_priv(netdev);
771 int err;
772
773 if (indir) {
774 if (!nic_dev->rss_indir_user) {
775 nic_dev->rss_indir_user =
776 kzalloc(sizeof(u32) * HINIC_RSS_INDIR_SIZE,
777 GFP_KERNEL);
778 if (!nic_dev->rss_indir_user)
779 return -ENOMEM;
780 }
781
782 memcpy(nic_dev->rss_indir_user, indir,
783 sizeof(u32) * HINIC_RSS_INDIR_SIZE);
784
785 err = hinic_rss_set_indir_tbl(nic_dev,
786 nic_dev->rss_tmpl_idx, indir);
787 if (err)
788 return -EFAULT;
789 }
790
791 if (key) {
792 if (!nic_dev->rss_hkey_user) {
793 nic_dev->rss_hkey_user =
794 kzalloc(HINIC_RSS_KEY_SIZE * 2, GFP_KERNEL);
795
796 if (!nic_dev->rss_hkey_user)
797 return -ENOMEM;
798 }
799
800 memcpy(nic_dev->rss_hkey_user, key, HINIC_RSS_KEY_SIZE);
801
802 err = hinic_rss_set_template_tbl(nic_dev,
803 nic_dev->rss_tmpl_idx, key);
804 if (err)
805 return -EFAULT;
806 }
807
808 return 0;
809 }
810
811 static int hinic_get_rxnfc(struct net_device *netdev,
812 struct ethtool_rxnfc *cmd, u32 *rule_locs)
813 {
814 struct hinic_dev *nic_dev = netdev_priv(netdev);
815 int err = 0;
816
817 switch (cmd->cmd) {
818 case ETHTOOL_GRXRINGS:
819 cmd->data = nic_dev->num_qps;
820 break;
821 case ETHTOOL_GRXFH:
822 err = hinic_get_rss_hash_opts(nic_dev, cmd);
823 break;
824 default:
825 err = -EOPNOTSUPP;
826 break;
827 }
828
829 return err;
830 }
831
832 static int hinic_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)
833 {
834 struct hinic_dev *nic_dev = netdev_priv(netdev);
835 int err = 0;
836
837 switch (cmd->cmd) {
838 case ETHTOOL_SRXFH:
839 err = hinic_set_rss_hash_opts(nic_dev, cmd);
840 break;
841 default:
842 err = -EOPNOTSUPP;
843 break;
844 }
845
846 return err;
847 }
848
849 static int hinic_get_rxfh(struct net_device *netdev,
850 u32 *indir, u8 *key, u8 *hfunc)
851 {
852 struct hinic_dev *nic_dev = netdev_priv(netdev);
853 u8 hash_engine_type = 0;
854 int err = 0;
855
856 if (!(nic_dev->flags & HINIC_RSS_ENABLE))
857 return -EOPNOTSUPP;
858
859 if (hfunc) {
860 err = hinic_rss_get_hash_engine(nic_dev,
861 nic_dev->rss_tmpl_idx,
862 &hash_engine_type);
863 if (err)
864 return -EFAULT;
865
866 *hfunc = hash_engine_type ? ETH_RSS_HASH_TOP : ETH_RSS_HASH_XOR;
867 }
868
869 if (indir) {
870 err = hinic_rss_get_indir_tbl(nic_dev,
871 nic_dev->rss_tmpl_idx, indir);
872 if (err)
873 return -EFAULT;
874 }
875
876 if (key)
877 err = hinic_rss_get_template_tbl(nic_dev,
878 nic_dev->rss_tmpl_idx, key);
879
880 return err;
881 }
882
883 static int hinic_set_rxfh(struct net_device *netdev, const u32 *indir,
884 const u8 *key, const u8 hfunc)
885 {
886 struct hinic_dev *nic_dev = netdev_priv(netdev);
887 int err = 0;
888
889 if (!(nic_dev->flags & HINIC_RSS_ENABLE))
890 return -EOPNOTSUPP;
891
892 if (hfunc != ETH_RSS_HASH_NO_CHANGE) {
893 if (hfunc != ETH_RSS_HASH_TOP && hfunc != ETH_RSS_HASH_XOR)
894 return -EOPNOTSUPP;
895
896 nic_dev->rss_hash_engine = (hfunc == ETH_RSS_HASH_XOR) ?
897 HINIC_RSS_HASH_ENGINE_TYPE_XOR :
898 HINIC_RSS_HASH_ENGINE_TYPE_TOEP;
899 err = hinic_rss_set_hash_engine
900 (nic_dev, nic_dev->rss_tmpl_idx,
901 nic_dev->rss_hash_engine);
902 if (err)
903 return -EFAULT;
904 }
905
906 err = __set_rss_rxfh(netdev, indir, key);
907
908 return err;
909 }
910
911 static u32 hinic_get_rxfh_key_size(struct net_device *netdev)
912 {
913 return HINIC_RSS_KEY_SIZE;
914 }
915
916 static u32 hinic_get_rxfh_indir_size(struct net_device *netdev)
917 {
918 return HINIC_RSS_INDIR_SIZE;
919 }
920
921 #define ARRAY_LEN(arr) ((int)((int)sizeof(arr) / (int)sizeof(arr[0])))
922
923 #define HINIC_FUNC_STAT(_stat_item) { \
924 .name = #_stat_item, \
925 .size = sizeof_field(struct hinic_vport_stats, _stat_item), \
926 .offset = offsetof(struct hinic_vport_stats, _stat_item) \
927 }
928
929 static struct hinic_stats hinic_function_stats[] = {
930 HINIC_FUNC_STAT(tx_unicast_pkts_vport),
931 HINIC_FUNC_STAT(tx_unicast_bytes_vport),
932 HINIC_FUNC_STAT(tx_multicast_pkts_vport),
933 HINIC_FUNC_STAT(tx_multicast_bytes_vport),
934 HINIC_FUNC_STAT(tx_broadcast_pkts_vport),
935 HINIC_FUNC_STAT(tx_broadcast_bytes_vport),
936
937 HINIC_FUNC_STAT(rx_unicast_pkts_vport),
938 HINIC_FUNC_STAT(rx_unicast_bytes_vport),
939 HINIC_FUNC_STAT(rx_multicast_pkts_vport),
940 HINIC_FUNC_STAT(rx_multicast_bytes_vport),
941 HINIC_FUNC_STAT(rx_broadcast_pkts_vport),
942 HINIC_FUNC_STAT(rx_broadcast_bytes_vport),
943
944 HINIC_FUNC_STAT(tx_discard_vport),
945 HINIC_FUNC_STAT(rx_discard_vport),
946 HINIC_FUNC_STAT(tx_err_vport),
947 HINIC_FUNC_STAT(rx_err_vport),
948 };
949
950 #define HINIC_PORT_STAT(_stat_item) { \
951 .name = #_stat_item, \
952 .size = sizeof_field(struct hinic_phy_port_stats, _stat_item), \
953 .offset = offsetof(struct hinic_phy_port_stats, _stat_item) \
954 }
955
956 static struct hinic_stats hinic_port_stats[] = {
957 HINIC_PORT_STAT(mac_rx_total_pkt_num),
958 HINIC_PORT_STAT(mac_rx_total_oct_num),
959 HINIC_PORT_STAT(mac_rx_bad_pkt_num),
960 HINIC_PORT_STAT(mac_rx_bad_oct_num),
961 HINIC_PORT_STAT(mac_rx_good_pkt_num),
962 HINIC_PORT_STAT(mac_rx_good_oct_num),
963 HINIC_PORT_STAT(mac_rx_uni_pkt_num),
964 HINIC_PORT_STAT(mac_rx_multi_pkt_num),
965 HINIC_PORT_STAT(mac_rx_broad_pkt_num),
966 HINIC_PORT_STAT(mac_tx_total_pkt_num),
967 HINIC_PORT_STAT(mac_tx_total_oct_num),
968 HINIC_PORT_STAT(mac_tx_bad_pkt_num),
969 HINIC_PORT_STAT(mac_tx_bad_oct_num),
970 HINIC_PORT_STAT(mac_tx_good_pkt_num),
971 HINIC_PORT_STAT(mac_tx_good_oct_num),
972 HINIC_PORT_STAT(mac_tx_uni_pkt_num),
973 HINIC_PORT_STAT(mac_tx_multi_pkt_num),
974 HINIC_PORT_STAT(mac_tx_broad_pkt_num),
975 HINIC_PORT_STAT(mac_rx_fragment_pkt_num),
976 HINIC_PORT_STAT(mac_rx_undersize_pkt_num),
977 HINIC_PORT_STAT(mac_rx_undermin_pkt_num),
978 HINIC_PORT_STAT(mac_rx_64_oct_pkt_num),
979 HINIC_PORT_STAT(mac_rx_65_127_oct_pkt_num),
980 HINIC_PORT_STAT(mac_rx_128_255_oct_pkt_num),
981 HINIC_PORT_STAT(mac_rx_256_511_oct_pkt_num),
982 HINIC_PORT_STAT(mac_rx_512_1023_oct_pkt_num),
983 HINIC_PORT_STAT(mac_rx_1024_1518_oct_pkt_num),
984 HINIC_PORT_STAT(mac_rx_1519_2047_oct_pkt_num),
985 HINIC_PORT_STAT(mac_rx_2048_4095_oct_pkt_num),
986 HINIC_PORT_STAT(mac_rx_4096_8191_oct_pkt_num),
987 HINIC_PORT_STAT(mac_rx_8192_9216_oct_pkt_num),
988 HINIC_PORT_STAT(mac_rx_9217_12287_oct_pkt_num),
989 HINIC_PORT_STAT(mac_rx_12288_16383_oct_pkt_num),
990 HINIC_PORT_STAT(mac_rx_1519_max_good_pkt_num),
991 HINIC_PORT_STAT(mac_rx_1519_max_bad_pkt_num),
992 HINIC_PORT_STAT(mac_rx_oversize_pkt_num),
993 HINIC_PORT_STAT(mac_rx_jabber_pkt_num),
994 HINIC_PORT_STAT(mac_rx_pause_num),
995 HINIC_PORT_STAT(mac_rx_pfc_pkt_num),
996 HINIC_PORT_STAT(mac_rx_pfc_pri0_pkt_num),
997 HINIC_PORT_STAT(mac_rx_pfc_pri1_pkt_num),
998 HINIC_PORT_STAT(mac_rx_pfc_pri2_pkt_num),
999 HINIC_PORT_STAT(mac_rx_pfc_pri3_pkt_num),
1000 HINIC_PORT_STAT(mac_rx_pfc_pri4_pkt_num),
1001 HINIC_PORT_STAT(mac_rx_pfc_pri5_pkt_num),
1002 HINIC_PORT_STAT(mac_rx_pfc_pri6_pkt_num),
1003 HINIC_PORT_STAT(mac_rx_pfc_pri7_pkt_num),
1004 HINIC_PORT_STAT(mac_rx_control_pkt_num),
1005 HINIC_PORT_STAT(mac_rx_sym_err_pkt_num),
1006 HINIC_PORT_STAT(mac_rx_fcs_err_pkt_num),
1007 HINIC_PORT_STAT(mac_rx_send_app_good_pkt_num),
1008 HINIC_PORT_STAT(mac_rx_send_app_bad_pkt_num),
1009 HINIC_PORT_STAT(mac_tx_fragment_pkt_num),
1010 HINIC_PORT_STAT(mac_tx_undersize_pkt_num),
1011 HINIC_PORT_STAT(mac_tx_undermin_pkt_num),
1012 HINIC_PORT_STAT(mac_tx_64_oct_pkt_num),
1013 HINIC_PORT_STAT(mac_tx_65_127_oct_pkt_num),
1014 HINIC_PORT_STAT(mac_tx_128_255_oct_pkt_num),
1015 HINIC_PORT_STAT(mac_tx_256_511_oct_pkt_num),
1016 HINIC_PORT_STAT(mac_tx_512_1023_oct_pkt_num),
1017 HINIC_PORT_STAT(mac_tx_1024_1518_oct_pkt_num),
1018 HINIC_PORT_STAT(mac_tx_1519_2047_oct_pkt_num),
1019 HINIC_PORT_STAT(mac_tx_2048_4095_oct_pkt_num),
1020 HINIC_PORT_STAT(mac_tx_4096_8191_oct_pkt_num),
1021 HINIC_PORT_STAT(mac_tx_8192_9216_oct_pkt_num),
1022 HINIC_PORT_STAT(mac_tx_9217_12287_oct_pkt_num),
1023 HINIC_PORT_STAT(mac_tx_12288_16383_oct_pkt_num),
1024 HINIC_PORT_STAT(mac_tx_1519_max_good_pkt_num),
1025 HINIC_PORT_STAT(mac_tx_1519_max_bad_pkt_num),
1026 HINIC_PORT_STAT(mac_tx_oversize_pkt_num),
1027 HINIC_PORT_STAT(mac_tx_jabber_pkt_num),
1028 HINIC_PORT_STAT(mac_tx_pause_num),
1029 HINIC_PORT_STAT(mac_tx_pfc_pkt_num),
1030 HINIC_PORT_STAT(mac_tx_pfc_pri0_pkt_num),
1031 HINIC_PORT_STAT(mac_tx_pfc_pri1_pkt_num),
1032 HINIC_PORT_STAT(mac_tx_pfc_pri2_pkt_num),
1033 HINIC_PORT_STAT(mac_tx_pfc_pri3_pkt_num),
1034 HINIC_PORT_STAT(mac_tx_pfc_pri4_pkt_num),
1035 HINIC_PORT_STAT(mac_tx_pfc_pri5_pkt_num),
1036 HINIC_PORT_STAT(mac_tx_pfc_pri6_pkt_num),
1037 HINIC_PORT_STAT(mac_tx_pfc_pri7_pkt_num),
1038 HINIC_PORT_STAT(mac_tx_control_pkt_num),
1039 HINIC_PORT_STAT(mac_tx_err_all_pkt_num),
1040 HINIC_PORT_STAT(mac_tx_from_app_good_pkt_num),
1041 HINIC_PORT_STAT(mac_tx_from_app_bad_pkt_num),
1042 };
1043
1044 #define HINIC_TXQ_STAT(_stat_item) { \
1045 .name = "txq%d_"#_stat_item, \
1046 .size = sizeof_field(struct hinic_txq_stats, _stat_item), \
1047 .offset = offsetof(struct hinic_txq_stats, _stat_item) \
1048 }
1049
1050 static struct hinic_stats hinic_tx_queue_stats[] = {
1051 HINIC_TXQ_STAT(pkts),
1052 HINIC_TXQ_STAT(bytes),
1053 HINIC_TXQ_STAT(tx_busy),
1054 HINIC_TXQ_STAT(tx_wake),
1055 HINIC_TXQ_STAT(tx_dropped),
1056 HINIC_TXQ_STAT(big_frags_pkts),
1057 };
1058
1059 #define HINIC_RXQ_STAT(_stat_item) { \
1060 .name = "rxq%d_"#_stat_item, \
1061 .size = sizeof_field(struct hinic_rxq_stats, _stat_item), \
1062 .offset = offsetof(struct hinic_rxq_stats, _stat_item) \
1063 }
1064
1065 static struct hinic_stats hinic_rx_queue_stats[] = {
1066 HINIC_RXQ_STAT(pkts),
1067 HINIC_RXQ_STAT(bytes),
1068 HINIC_RXQ_STAT(errors),
1069 HINIC_RXQ_STAT(csum_errors),
1070 HINIC_RXQ_STAT(other_errors),
1071 };
1072
1073 static void get_drv_queue_stats(struct hinic_dev *nic_dev, u64 *data)
1074 {
1075 struct hinic_txq_stats txq_stats;
1076 struct hinic_rxq_stats rxq_stats;
1077 u16 i = 0, j = 0, qid = 0;
1078 char *p;
1079
1080 for (qid = 0; qid < nic_dev->num_qps; qid++) {
1081 if (!nic_dev->txqs)
1082 break;
1083
1084 hinic_txq_get_stats(&nic_dev->txqs[qid], &txq_stats);
1085 for (j = 0; j < ARRAY_LEN(hinic_tx_queue_stats); j++, i++) {
1086 p = (char *)&txq_stats +
1087 hinic_tx_queue_stats[j].offset;
1088 data[i] = (hinic_tx_queue_stats[j].size ==
1089 sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
1090 }
1091 }
1092
1093 for (qid = 0; qid < nic_dev->num_qps; qid++) {
1094 if (!nic_dev->rxqs)
1095 break;
1096
1097 hinic_rxq_get_stats(&nic_dev->rxqs[qid], &rxq_stats);
1098 for (j = 0; j < ARRAY_LEN(hinic_rx_queue_stats); j++, i++) {
1099 p = (char *)&rxq_stats +
1100 hinic_rx_queue_stats[j].offset;
1101 data[i] = (hinic_rx_queue_stats[j].size ==
1102 sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
1103 }
1104 }
1105 }
1106
1107 static void hinic_get_ethtool_stats(struct net_device *netdev,
1108 struct ethtool_stats *stats, u64 *data)
1109 {
1110 struct hinic_dev *nic_dev = netdev_priv(netdev);
1111 struct hinic_vport_stats vport_stats = {0};
1112 struct hinic_phy_port_stats *port_stats;
1113 u16 i = 0, j = 0;
1114 char *p;
1115 int err;
1116
1117 err = hinic_get_vport_stats(nic_dev, &vport_stats);
1118 if (err)
1119 netif_err(nic_dev, drv, netdev,
1120 "Failed to get vport stats from firmware\n");
1121
1122 for (j = 0; j < ARRAY_LEN(hinic_function_stats); j++, i++) {
1123 p = (char *)&vport_stats + hinic_function_stats[j].offset;
1124 data[i] = (hinic_function_stats[j].size ==
1125 sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
1126 }
1127
1128 port_stats = kzalloc(sizeof(*port_stats), GFP_KERNEL);
1129 if (!port_stats) {
1130 memset(&data[i], 0,
1131 ARRAY_LEN(hinic_port_stats) * sizeof(*data));
1132 i += ARRAY_LEN(hinic_port_stats);
1133 goto get_drv_stats;
1134 }
1135
1136 err = hinic_get_phy_port_stats(nic_dev, port_stats);
1137 if (err)
1138 netif_err(nic_dev, drv, netdev,
1139 "Failed to get port stats from firmware\n");
1140
1141 for (j = 0; j < ARRAY_LEN(hinic_port_stats); j++, i++) {
1142 p = (char *)port_stats + hinic_port_stats[j].offset;
1143 data[i] = (hinic_port_stats[j].size ==
1144 sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
1145 }
1146
1147 kfree(port_stats);
1148
1149 get_drv_stats:
1150 get_drv_queue_stats(nic_dev, data + i);
1151 }
1152
1153 static int hinic_get_sset_count(struct net_device *netdev, int sset)
1154 {
1155 struct hinic_dev *nic_dev = netdev_priv(netdev);
1156 int count, q_num;
1157
1158 switch (sset) {
1159 case ETH_SS_STATS:
1160 q_num = nic_dev->num_qps;
1161 count = ARRAY_LEN(hinic_function_stats) +
1162 (ARRAY_LEN(hinic_tx_queue_stats) +
1163 ARRAY_LEN(hinic_rx_queue_stats)) * q_num;
1164
1165 count += ARRAY_LEN(hinic_port_stats);
1166
1167 return count;
1168 default:
1169 return -EOPNOTSUPP;
1170 }
1171 }
1172
1173 static void hinic_get_strings(struct net_device *netdev,
1174 u32 stringset, u8 *data)
1175 {
1176 struct hinic_dev *nic_dev = netdev_priv(netdev);
1177 char *p = (char *)data;
1178 u16 i, j;
1179
1180 switch (stringset) {
1181 case ETH_SS_STATS:
1182 for (i = 0; i < ARRAY_LEN(hinic_function_stats); i++) {
1183 memcpy(p, hinic_function_stats[i].name,
1184 ETH_GSTRING_LEN);
1185 p += ETH_GSTRING_LEN;
1186 }
1187
1188 for (i = 0; i < ARRAY_LEN(hinic_port_stats); i++) {
1189 memcpy(p, hinic_port_stats[i].name,
1190 ETH_GSTRING_LEN);
1191 p += ETH_GSTRING_LEN;
1192 }
1193
1194 for (i = 0; i < nic_dev->num_qps; i++) {
1195 for (j = 0; j < ARRAY_LEN(hinic_tx_queue_stats); j++) {
1196 sprintf(p, hinic_tx_queue_stats[j].name, i);
1197 p += ETH_GSTRING_LEN;
1198 }
1199 }
1200
1201 for (i = 0; i < nic_dev->num_qps; i++) {
1202 for (j = 0; j < ARRAY_LEN(hinic_rx_queue_stats); j++) {
1203 sprintf(p, hinic_rx_queue_stats[j].name, i);
1204 p += ETH_GSTRING_LEN;
1205 }
1206 }
1207
1208 return;
1209 default:
1210 return;
1211 }
1212 }
1213
1214 static const struct ethtool_ops hinic_ethtool_ops = {
1215 .get_link_ksettings = hinic_get_link_ksettings,
1216 .set_link_ksettings = hinic_set_link_ksettings,
1217 .get_drvinfo = hinic_get_drvinfo,
1218 .get_link = ethtool_op_get_link,
1219 .get_ringparam = hinic_get_ringparam,
1220 .set_ringparam = hinic_set_ringparam,
1221 .get_channels = hinic_get_channels,
1222 .get_rxnfc = hinic_get_rxnfc,
1223 .set_rxnfc = hinic_set_rxnfc,
1224 .get_rxfh_key_size = hinic_get_rxfh_key_size,
1225 .get_rxfh_indir_size = hinic_get_rxfh_indir_size,
1226 .get_rxfh = hinic_get_rxfh,
1227 .set_rxfh = hinic_set_rxfh,
1228 .get_sset_count = hinic_get_sset_count,
1229 .get_ethtool_stats = hinic_get_ethtool_stats,
1230 .get_strings = hinic_get_strings,
1231 };
1232
1233 void hinic_set_ethtool_ops(struct net_device *netdev)
1234 {
1235 netdev->ethtool_ops = &hinic_ethtool_ops;
1236 }