This source file includes following definitions.
- set_link_speed
- hinic_get_link_ksettings
- hinic_get_drvinfo
- hinic_get_ringparam
- hinic_get_channels
- hinic_get_rss_hash_opts
- set_l4_rss_hash_ops
- hinic_set_rss_hash_opts
- __set_rss_rxfh
- hinic_get_rxnfc
- hinic_set_rxnfc
- hinic_get_rxfh
- hinic_set_rxfh
- hinic_get_rxfh_key_size
- hinic_get_rxfh_indir_size
- get_drv_queue_stats
- hinic_get_ethtool_stats
- hinic_get_sset_count
- hinic_get_strings
- hinic_set_ethtool_ops
1
2
3
4
5
6
7
8
9
10
11
12
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 static void set_link_speed(struct ethtool_link_ksettings *link_ksettings,
37 enum hinic_speed speed)
38 {
39 switch (speed) {
40 case HINIC_SPEED_10MB_LINK:
41 link_ksettings->base.speed = SPEED_10;
42 break;
43
44 case HINIC_SPEED_100MB_LINK:
45 link_ksettings->base.speed = SPEED_100;
46 break;
47
48 case HINIC_SPEED_1000MB_LINK:
49 link_ksettings->base.speed = SPEED_1000;
50 break;
51
52 case HINIC_SPEED_10GB_LINK:
53 link_ksettings->base.speed = SPEED_10000;
54 break;
55
56 case HINIC_SPEED_25GB_LINK:
57 link_ksettings->base.speed = SPEED_25000;
58 break;
59
60 case HINIC_SPEED_40GB_LINK:
61 link_ksettings->base.speed = SPEED_40000;
62 break;
63
64 case HINIC_SPEED_100GB_LINK:
65 link_ksettings->base.speed = SPEED_100000;
66 break;
67
68 default:
69 link_ksettings->base.speed = SPEED_UNKNOWN;
70 break;
71 }
72 }
73
74 static int hinic_get_link_ksettings(struct net_device *netdev,
75 struct ethtool_link_ksettings
76 *link_ksettings)
77 {
78 struct hinic_dev *nic_dev = netdev_priv(netdev);
79 enum hinic_port_link_state link_state;
80 struct hinic_port_cap port_cap;
81 int err;
82
83 ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);
84 ethtool_link_ksettings_add_link_mode(link_ksettings, supported,
85 Autoneg);
86
87 link_ksettings->base.speed = SPEED_UNKNOWN;
88 link_ksettings->base.autoneg = AUTONEG_DISABLE;
89 link_ksettings->base.duplex = DUPLEX_UNKNOWN;
90
91 err = hinic_port_get_cap(nic_dev, &port_cap);
92 if (err)
93 return err;
94
95 err = hinic_port_link_state(nic_dev, &link_state);
96 if (err)
97 return err;
98
99 if (link_state != HINIC_LINK_STATE_UP)
100 return err;
101
102 set_link_speed(link_ksettings, port_cap.speed);
103
104 if (!!(port_cap.autoneg_cap & HINIC_AUTONEG_SUPPORTED))
105 ethtool_link_ksettings_add_link_mode(link_ksettings,
106 advertising, Autoneg);
107
108 if (port_cap.autoneg_state == HINIC_AUTONEG_ACTIVE)
109 link_ksettings->base.autoneg = AUTONEG_ENABLE;
110
111 link_ksettings->base.duplex = (port_cap.duplex == HINIC_DUPLEX_FULL) ?
112 DUPLEX_FULL : DUPLEX_HALF;
113 return 0;
114 }
115
116 static void hinic_get_drvinfo(struct net_device *netdev,
117 struct ethtool_drvinfo *info)
118 {
119 struct hinic_dev *nic_dev = netdev_priv(netdev);
120 u8 mgmt_ver[HINIC_MGMT_VERSION_MAX_LEN] = {0};
121 struct hinic_hwdev *hwdev = nic_dev->hwdev;
122 struct hinic_hwif *hwif = hwdev->hwif;
123 int err;
124
125 strlcpy(info->driver, HINIC_DRV_NAME, sizeof(info->driver));
126 strlcpy(info->bus_info, pci_name(hwif->pdev), sizeof(info->bus_info));
127
128 err = hinic_get_mgmt_version(nic_dev, mgmt_ver);
129 if (err)
130 return;
131
132 snprintf(info->fw_version, sizeof(info->fw_version), "%s", mgmt_ver);
133 }
134
135 static void hinic_get_ringparam(struct net_device *netdev,
136 struct ethtool_ringparam *ring)
137 {
138 ring->rx_max_pending = HINIC_RQ_DEPTH;
139 ring->tx_max_pending = HINIC_SQ_DEPTH;
140 ring->rx_pending = HINIC_RQ_DEPTH;
141 ring->tx_pending = HINIC_SQ_DEPTH;
142 }
143
144 static void hinic_get_channels(struct net_device *netdev,
145 struct ethtool_channels *channels)
146 {
147 struct hinic_dev *nic_dev = netdev_priv(netdev);
148 struct hinic_hwdev *hwdev = nic_dev->hwdev;
149
150 channels->max_rx = hwdev->nic_cap.max_qps;
151 channels->max_tx = hwdev->nic_cap.max_qps;
152 channels->max_other = 0;
153 channels->max_combined = 0;
154 channels->rx_count = hinic_hwdev_num_qps(hwdev);
155 channels->tx_count = hinic_hwdev_num_qps(hwdev);
156 channels->other_count = 0;
157 channels->combined_count = 0;
158 }
159
160 static int hinic_get_rss_hash_opts(struct hinic_dev *nic_dev,
161 struct ethtool_rxnfc *cmd)
162 {
163 struct hinic_rss_type rss_type = { 0 };
164 int err;
165
166 cmd->data = 0;
167
168 if (!(nic_dev->flags & HINIC_RSS_ENABLE))
169 return 0;
170
171 err = hinic_get_rss_type(nic_dev, nic_dev->rss_tmpl_idx,
172 &rss_type);
173 if (err)
174 return err;
175
176 cmd->data = RXH_IP_SRC | RXH_IP_DST;
177 switch (cmd->flow_type) {
178 case TCP_V4_FLOW:
179 if (rss_type.tcp_ipv4)
180 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
181 break;
182 case TCP_V6_FLOW:
183 if (rss_type.tcp_ipv6)
184 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
185 break;
186 case UDP_V4_FLOW:
187 if (rss_type.udp_ipv4)
188 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
189 break;
190 case UDP_V6_FLOW:
191 if (rss_type.udp_ipv6)
192 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
193 break;
194 case IPV4_FLOW:
195 case IPV6_FLOW:
196 break;
197 default:
198 cmd->data = 0;
199 return -EINVAL;
200 }
201
202 return 0;
203 }
204
205 static int set_l4_rss_hash_ops(struct ethtool_rxnfc *cmd,
206 struct hinic_rss_type *rss_type)
207 {
208 u8 rss_l4_en = 0;
209
210 switch (cmd->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
211 case 0:
212 rss_l4_en = 0;
213 break;
214 case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
215 rss_l4_en = 1;
216 break;
217 default:
218 return -EINVAL;
219 }
220
221 switch (cmd->flow_type) {
222 case TCP_V4_FLOW:
223 rss_type->tcp_ipv4 = rss_l4_en;
224 break;
225 case TCP_V6_FLOW:
226 rss_type->tcp_ipv6 = rss_l4_en;
227 break;
228 case UDP_V4_FLOW:
229 rss_type->udp_ipv4 = rss_l4_en;
230 break;
231 case UDP_V6_FLOW:
232 rss_type->udp_ipv6 = rss_l4_en;
233 break;
234 default:
235 return -EINVAL;
236 }
237
238 return 0;
239 }
240
241 static int hinic_set_rss_hash_opts(struct hinic_dev *nic_dev,
242 struct ethtool_rxnfc *cmd)
243 {
244 struct hinic_rss_type *rss_type = &nic_dev->rss_type;
245 int err;
246
247 if (!(nic_dev->flags & HINIC_RSS_ENABLE)) {
248 cmd->data = 0;
249 return -EOPNOTSUPP;
250 }
251
252
253
254
255 if (cmd->data & ~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 |
256 RXH_L4_B_2_3))
257 return -EINVAL;
258
259
260 if (!(cmd->data & RXH_IP_SRC) || !(cmd->data & RXH_IP_DST))
261 return -EINVAL;
262
263 err = hinic_get_rss_type(nic_dev,
264 nic_dev->rss_tmpl_idx, rss_type);
265 if (err)
266 return -EFAULT;
267
268 switch (cmd->flow_type) {
269 case TCP_V4_FLOW:
270 case TCP_V6_FLOW:
271 case UDP_V4_FLOW:
272 case UDP_V6_FLOW:
273 err = set_l4_rss_hash_ops(cmd, rss_type);
274 if (err)
275 return err;
276 break;
277 case IPV4_FLOW:
278 rss_type->ipv4 = 1;
279 break;
280 case IPV6_FLOW:
281 rss_type->ipv6 = 1;
282 break;
283 default:
284 return -EINVAL;
285 }
286
287 err = hinic_set_rss_type(nic_dev, nic_dev->rss_tmpl_idx,
288 *rss_type);
289 if (err)
290 return -EFAULT;
291
292 return 0;
293 }
294
295 static int __set_rss_rxfh(struct net_device *netdev,
296 const u32 *indir, const u8 *key)
297 {
298 struct hinic_dev *nic_dev = netdev_priv(netdev);
299 int err;
300
301 if (indir) {
302 if (!nic_dev->rss_indir_user) {
303 nic_dev->rss_indir_user =
304 kzalloc(sizeof(u32) * HINIC_RSS_INDIR_SIZE,
305 GFP_KERNEL);
306 if (!nic_dev->rss_indir_user)
307 return -ENOMEM;
308 }
309
310 memcpy(nic_dev->rss_indir_user, indir,
311 sizeof(u32) * HINIC_RSS_INDIR_SIZE);
312
313 err = hinic_rss_set_indir_tbl(nic_dev,
314 nic_dev->rss_tmpl_idx, indir);
315 if (err)
316 return -EFAULT;
317 }
318
319 if (key) {
320 if (!nic_dev->rss_hkey_user) {
321 nic_dev->rss_hkey_user =
322 kzalloc(HINIC_RSS_KEY_SIZE * 2, GFP_KERNEL);
323
324 if (!nic_dev->rss_hkey_user)
325 return -ENOMEM;
326 }
327
328 memcpy(nic_dev->rss_hkey_user, key, HINIC_RSS_KEY_SIZE);
329
330 err = hinic_rss_set_template_tbl(nic_dev,
331 nic_dev->rss_tmpl_idx, key);
332 if (err)
333 return -EFAULT;
334 }
335
336 return 0;
337 }
338
339 static int hinic_get_rxnfc(struct net_device *netdev,
340 struct ethtool_rxnfc *cmd, u32 *rule_locs)
341 {
342 struct hinic_dev *nic_dev = netdev_priv(netdev);
343 int err = 0;
344
345 switch (cmd->cmd) {
346 case ETHTOOL_GRXRINGS:
347 cmd->data = nic_dev->num_qps;
348 break;
349 case ETHTOOL_GRXFH:
350 err = hinic_get_rss_hash_opts(nic_dev, cmd);
351 break;
352 default:
353 err = -EOPNOTSUPP;
354 break;
355 }
356
357 return err;
358 }
359
360 static int hinic_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)
361 {
362 struct hinic_dev *nic_dev = netdev_priv(netdev);
363 int err = 0;
364
365 switch (cmd->cmd) {
366 case ETHTOOL_SRXFH:
367 err = hinic_set_rss_hash_opts(nic_dev, cmd);
368 break;
369 default:
370 err = -EOPNOTSUPP;
371 break;
372 }
373
374 return err;
375 }
376
377 static int hinic_get_rxfh(struct net_device *netdev,
378 u32 *indir, u8 *key, u8 *hfunc)
379 {
380 struct hinic_dev *nic_dev = netdev_priv(netdev);
381 u8 hash_engine_type = 0;
382 int err = 0;
383
384 if (!(nic_dev->flags & HINIC_RSS_ENABLE))
385 return -EOPNOTSUPP;
386
387 if (hfunc) {
388 err = hinic_rss_get_hash_engine(nic_dev,
389 nic_dev->rss_tmpl_idx,
390 &hash_engine_type);
391 if (err)
392 return -EFAULT;
393
394 *hfunc = hash_engine_type ? ETH_RSS_HASH_TOP : ETH_RSS_HASH_XOR;
395 }
396
397 if (indir) {
398 err = hinic_rss_get_indir_tbl(nic_dev,
399 nic_dev->rss_tmpl_idx, indir);
400 if (err)
401 return -EFAULT;
402 }
403
404 if (key)
405 err = hinic_rss_get_template_tbl(nic_dev,
406 nic_dev->rss_tmpl_idx, key);
407
408 return err;
409 }
410
411 static int hinic_set_rxfh(struct net_device *netdev, const u32 *indir,
412 const u8 *key, const u8 hfunc)
413 {
414 struct hinic_dev *nic_dev = netdev_priv(netdev);
415 int err = 0;
416
417 if (!(nic_dev->flags & HINIC_RSS_ENABLE))
418 return -EOPNOTSUPP;
419
420 if (hfunc != ETH_RSS_HASH_NO_CHANGE) {
421 if (hfunc != ETH_RSS_HASH_TOP && hfunc != ETH_RSS_HASH_XOR)
422 return -EOPNOTSUPP;
423
424 nic_dev->rss_hash_engine = (hfunc == ETH_RSS_HASH_XOR) ?
425 HINIC_RSS_HASH_ENGINE_TYPE_XOR :
426 HINIC_RSS_HASH_ENGINE_TYPE_TOEP;
427 err = hinic_rss_set_hash_engine
428 (nic_dev, nic_dev->rss_tmpl_idx,
429 nic_dev->rss_hash_engine);
430 if (err)
431 return -EFAULT;
432 }
433
434 err = __set_rss_rxfh(netdev, indir, key);
435
436 return err;
437 }
438
439 static u32 hinic_get_rxfh_key_size(struct net_device *netdev)
440 {
441 return HINIC_RSS_KEY_SIZE;
442 }
443
444 static u32 hinic_get_rxfh_indir_size(struct net_device *netdev)
445 {
446 return HINIC_RSS_INDIR_SIZE;
447 }
448
449 #define ARRAY_LEN(arr) ((int)((int)sizeof(arr) / (int)sizeof(arr[0])))
450
451 #define HINIC_FUNC_STAT(_stat_item) { \
452 .name = #_stat_item, \
453 .size = FIELD_SIZEOF(struct hinic_vport_stats, _stat_item), \
454 .offset = offsetof(struct hinic_vport_stats, _stat_item) \
455 }
456
457 static struct hinic_stats hinic_function_stats[] = {
458 HINIC_FUNC_STAT(tx_unicast_pkts_vport),
459 HINIC_FUNC_STAT(tx_unicast_bytes_vport),
460 HINIC_FUNC_STAT(tx_multicast_pkts_vport),
461 HINIC_FUNC_STAT(tx_multicast_bytes_vport),
462 HINIC_FUNC_STAT(tx_broadcast_pkts_vport),
463 HINIC_FUNC_STAT(tx_broadcast_bytes_vport),
464
465 HINIC_FUNC_STAT(rx_unicast_pkts_vport),
466 HINIC_FUNC_STAT(rx_unicast_bytes_vport),
467 HINIC_FUNC_STAT(rx_multicast_pkts_vport),
468 HINIC_FUNC_STAT(rx_multicast_bytes_vport),
469 HINIC_FUNC_STAT(rx_broadcast_pkts_vport),
470 HINIC_FUNC_STAT(rx_broadcast_bytes_vport),
471
472 HINIC_FUNC_STAT(tx_discard_vport),
473 HINIC_FUNC_STAT(rx_discard_vport),
474 HINIC_FUNC_STAT(tx_err_vport),
475 HINIC_FUNC_STAT(rx_err_vport),
476 };
477
478 #define HINIC_PORT_STAT(_stat_item) { \
479 .name = #_stat_item, \
480 .size = FIELD_SIZEOF(struct hinic_phy_port_stats, _stat_item), \
481 .offset = offsetof(struct hinic_phy_port_stats, _stat_item) \
482 }
483
484 static struct hinic_stats hinic_port_stats[] = {
485 HINIC_PORT_STAT(mac_rx_total_pkt_num),
486 HINIC_PORT_STAT(mac_rx_total_oct_num),
487 HINIC_PORT_STAT(mac_rx_bad_pkt_num),
488 HINIC_PORT_STAT(mac_rx_bad_oct_num),
489 HINIC_PORT_STAT(mac_rx_good_pkt_num),
490 HINIC_PORT_STAT(mac_rx_good_oct_num),
491 HINIC_PORT_STAT(mac_rx_uni_pkt_num),
492 HINIC_PORT_STAT(mac_rx_multi_pkt_num),
493 HINIC_PORT_STAT(mac_rx_broad_pkt_num),
494 HINIC_PORT_STAT(mac_tx_total_pkt_num),
495 HINIC_PORT_STAT(mac_tx_total_oct_num),
496 HINIC_PORT_STAT(mac_tx_bad_pkt_num),
497 HINIC_PORT_STAT(mac_tx_bad_oct_num),
498 HINIC_PORT_STAT(mac_tx_good_pkt_num),
499 HINIC_PORT_STAT(mac_tx_good_oct_num),
500 HINIC_PORT_STAT(mac_tx_uni_pkt_num),
501 HINIC_PORT_STAT(mac_tx_multi_pkt_num),
502 HINIC_PORT_STAT(mac_tx_broad_pkt_num),
503 HINIC_PORT_STAT(mac_rx_fragment_pkt_num),
504 HINIC_PORT_STAT(mac_rx_undersize_pkt_num),
505 HINIC_PORT_STAT(mac_rx_undermin_pkt_num),
506 HINIC_PORT_STAT(mac_rx_64_oct_pkt_num),
507 HINIC_PORT_STAT(mac_rx_65_127_oct_pkt_num),
508 HINIC_PORT_STAT(mac_rx_128_255_oct_pkt_num),
509 HINIC_PORT_STAT(mac_rx_256_511_oct_pkt_num),
510 HINIC_PORT_STAT(mac_rx_512_1023_oct_pkt_num),
511 HINIC_PORT_STAT(mac_rx_1024_1518_oct_pkt_num),
512 HINIC_PORT_STAT(mac_rx_1519_2047_oct_pkt_num),
513 HINIC_PORT_STAT(mac_rx_2048_4095_oct_pkt_num),
514 HINIC_PORT_STAT(mac_rx_4096_8191_oct_pkt_num),
515 HINIC_PORT_STAT(mac_rx_8192_9216_oct_pkt_num),
516 HINIC_PORT_STAT(mac_rx_9217_12287_oct_pkt_num),
517 HINIC_PORT_STAT(mac_rx_12288_16383_oct_pkt_num),
518 HINIC_PORT_STAT(mac_rx_1519_max_good_pkt_num),
519 HINIC_PORT_STAT(mac_rx_1519_max_bad_pkt_num),
520 HINIC_PORT_STAT(mac_rx_oversize_pkt_num),
521 HINIC_PORT_STAT(mac_rx_jabber_pkt_num),
522 HINIC_PORT_STAT(mac_rx_pause_num),
523 HINIC_PORT_STAT(mac_rx_pfc_pkt_num),
524 HINIC_PORT_STAT(mac_rx_pfc_pri0_pkt_num),
525 HINIC_PORT_STAT(mac_rx_pfc_pri1_pkt_num),
526 HINIC_PORT_STAT(mac_rx_pfc_pri2_pkt_num),
527 HINIC_PORT_STAT(mac_rx_pfc_pri3_pkt_num),
528 HINIC_PORT_STAT(mac_rx_pfc_pri4_pkt_num),
529 HINIC_PORT_STAT(mac_rx_pfc_pri5_pkt_num),
530 HINIC_PORT_STAT(mac_rx_pfc_pri6_pkt_num),
531 HINIC_PORT_STAT(mac_rx_pfc_pri7_pkt_num),
532 HINIC_PORT_STAT(mac_rx_control_pkt_num),
533 HINIC_PORT_STAT(mac_rx_sym_err_pkt_num),
534 HINIC_PORT_STAT(mac_rx_fcs_err_pkt_num),
535 HINIC_PORT_STAT(mac_rx_send_app_good_pkt_num),
536 HINIC_PORT_STAT(mac_rx_send_app_bad_pkt_num),
537 HINIC_PORT_STAT(mac_tx_fragment_pkt_num),
538 HINIC_PORT_STAT(mac_tx_undersize_pkt_num),
539 HINIC_PORT_STAT(mac_tx_undermin_pkt_num),
540 HINIC_PORT_STAT(mac_tx_64_oct_pkt_num),
541 HINIC_PORT_STAT(mac_tx_65_127_oct_pkt_num),
542 HINIC_PORT_STAT(mac_tx_128_255_oct_pkt_num),
543 HINIC_PORT_STAT(mac_tx_256_511_oct_pkt_num),
544 HINIC_PORT_STAT(mac_tx_512_1023_oct_pkt_num),
545 HINIC_PORT_STAT(mac_tx_1024_1518_oct_pkt_num),
546 HINIC_PORT_STAT(mac_tx_1519_2047_oct_pkt_num),
547 HINIC_PORT_STAT(mac_tx_2048_4095_oct_pkt_num),
548 HINIC_PORT_STAT(mac_tx_4096_8191_oct_pkt_num),
549 HINIC_PORT_STAT(mac_tx_8192_9216_oct_pkt_num),
550 HINIC_PORT_STAT(mac_tx_9217_12287_oct_pkt_num),
551 HINIC_PORT_STAT(mac_tx_12288_16383_oct_pkt_num),
552 HINIC_PORT_STAT(mac_tx_1519_max_good_pkt_num),
553 HINIC_PORT_STAT(mac_tx_1519_max_bad_pkt_num),
554 HINIC_PORT_STAT(mac_tx_oversize_pkt_num),
555 HINIC_PORT_STAT(mac_tx_jabber_pkt_num),
556 HINIC_PORT_STAT(mac_tx_pause_num),
557 HINIC_PORT_STAT(mac_tx_pfc_pkt_num),
558 HINIC_PORT_STAT(mac_tx_pfc_pri0_pkt_num),
559 HINIC_PORT_STAT(mac_tx_pfc_pri1_pkt_num),
560 HINIC_PORT_STAT(mac_tx_pfc_pri2_pkt_num),
561 HINIC_PORT_STAT(mac_tx_pfc_pri3_pkt_num),
562 HINIC_PORT_STAT(mac_tx_pfc_pri4_pkt_num),
563 HINIC_PORT_STAT(mac_tx_pfc_pri5_pkt_num),
564 HINIC_PORT_STAT(mac_tx_pfc_pri6_pkt_num),
565 HINIC_PORT_STAT(mac_tx_pfc_pri7_pkt_num),
566 HINIC_PORT_STAT(mac_tx_control_pkt_num),
567 HINIC_PORT_STAT(mac_tx_err_all_pkt_num),
568 HINIC_PORT_STAT(mac_tx_from_app_good_pkt_num),
569 HINIC_PORT_STAT(mac_tx_from_app_bad_pkt_num),
570 };
571
572 #define HINIC_TXQ_STAT(_stat_item) { \
573 .name = "txq%d_"#_stat_item, \
574 .size = FIELD_SIZEOF(struct hinic_txq_stats, _stat_item), \
575 .offset = offsetof(struct hinic_txq_stats, _stat_item) \
576 }
577
578 static struct hinic_stats hinic_tx_queue_stats[] = {
579 HINIC_TXQ_STAT(pkts),
580 HINIC_TXQ_STAT(bytes),
581 HINIC_TXQ_STAT(tx_busy),
582 HINIC_TXQ_STAT(tx_wake),
583 HINIC_TXQ_STAT(tx_dropped),
584 HINIC_TXQ_STAT(big_frags_pkts),
585 };
586
587 #define HINIC_RXQ_STAT(_stat_item) { \
588 .name = "rxq%d_"#_stat_item, \
589 .size = FIELD_SIZEOF(struct hinic_rxq_stats, _stat_item), \
590 .offset = offsetof(struct hinic_rxq_stats, _stat_item) \
591 }
592
593 static struct hinic_stats hinic_rx_queue_stats[] = {
594 HINIC_RXQ_STAT(pkts),
595 HINIC_RXQ_STAT(bytes),
596 HINIC_RXQ_STAT(errors),
597 HINIC_RXQ_STAT(csum_errors),
598 HINIC_RXQ_STAT(other_errors),
599 };
600
601 static void get_drv_queue_stats(struct hinic_dev *nic_dev, u64 *data)
602 {
603 struct hinic_txq_stats txq_stats;
604 struct hinic_rxq_stats rxq_stats;
605 u16 i = 0, j = 0, qid = 0;
606 char *p;
607
608 for (qid = 0; qid < nic_dev->num_qps; qid++) {
609 if (!nic_dev->txqs)
610 break;
611
612 hinic_txq_get_stats(&nic_dev->txqs[qid], &txq_stats);
613 for (j = 0; j < ARRAY_LEN(hinic_tx_queue_stats); j++, i++) {
614 p = (char *)&txq_stats +
615 hinic_tx_queue_stats[j].offset;
616 data[i] = (hinic_tx_queue_stats[j].size ==
617 sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
618 }
619 }
620
621 for (qid = 0; qid < nic_dev->num_qps; qid++) {
622 if (!nic_dev->rxqs)
623 break;
624
625 hinic_rxq_get_stats(&nic_dev->rxqs[qid], &rxq_stats);
626 for (j = 0; j < ARRAY_LEN(hinic_rx_queue_stats); j++, i++) {
627 p = (char *)&rxq_stats +
628 hinic_rx_queue_stats[j].offset;
629 data[i] = (hinic_rx_queue_stats[j].size ==
630 sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
631 }
632 }
633 }
634
635 static void hinic_get_ethtool_stats(struct net_device *netdev,
636 struct ethtool_stats *stats, u64 *data)
637 {
638 struct hinic_dev *nic_dev = netdev_priv(netdev);
639 struct hinic_vport_stats vport_stats = {0};
640 struct hinic_phy_port_stats *port_stats;
641 u16 i = 0, j = 0;
642 char *p;
643 int err;
644
645 err = hinic_get_vport_stats(nic_dev, &vport_stats);
646 if (err)
647 netif_err(nic_dev, drv, netdev,
648 "Failed to get vport stats from firmware\n");
649
650 for (j = 0; j < ARRAY_LEN(hinic_function_stats); j++, i++) {
651 p = (char *)&vport_stats + hinic_function_stats[j].offset;
652 data[i] = (hinic_function_stats[j].size ==
653 sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
654 }
655
656 port_stats = kzalloc(sizeof(*port_stats), GFP_KERNEL);
657 if (!port_stats) {
658 memset(&data[i], 0,
659 ARRAY_LEN(hinic_port_stats) * sizeof(*data));
660 i += ARRAY_LEN(hinic_port_stats);
661 goto get_drv_stats;
662 }
663
664 err = hinic_get_phy_port_stats(nic_dev, port_stats);
665 if (err)
666 netif_err(nic_dev, drv, netdev,
667 "Failed to get port stats from firmware\n");
668
669 for (j = 0; j < ARRAY_LEN(hinic_port_stats); j++, i++) {
670 p = (char *)port_stats + hinic_port_stats[j].offset;
671 data[i] = (hinic_port_stats[j].size ==
672 sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
673 }
674
675 kfree(port_stats);
676
677 get_drv_stats:
678 get_drv_queue_stats(nic_dev, data + i);
679 }
680
681 static int hinic_get_sset_count(struct net_device *netdev, int sset)
682 {
683 struct hinic_dev *nic_dev = netdev_priv(netdev);
684 int count, q_num;
685
686 switch (sset) {
687 case ETH_SS_STATS:
688 q_num = nic_dev->num_qps;
689 count = ARRAY_LEN(hinic_function_stats) +
690 (ARRAY_LEN(hinic_tx_queue_stats) +
691 ARRAY_LEN(hinic_rx_queue_stats)) * q_num;
692
693 count += ARRAY_LEN(hinic_port_stats);
694
695 return count;
696 default:
697 return -EOPNOTSUPP;
698 }
699 }
700
701 static void hinic_get_strings(struct net_device *netdev,
702 u32 stringset, u8 *data)
703 {
704 struct hinic_dev *nic_dev = netdev_priv(netdev);
705 char *p = (char *)data;
706 u16 i, j;
707
708 switch (stringset) {
709 case ETH_SS_STATS:
710 for (i = 0; i < ARRAY_LEN(hinic_function_stats); i++) {
711 memcpy(p, hinic_function_stats[i].name,
712 ETH_GSTRING_LEN);
713 p += ETH_GSTRING_LEN;
714 }
715
716 for (i = 0; i < ARRAY_LEN(hinic_port_stats); i++) {
717 memcpy(p, hinic_port_stats[i].name,
718 ETH_GSTRING_LEN);
719 p += ETH_GSTRING_LEN;
720 }
721
722 for (i = 0; i < nic_dev->num_qps; i++) {
723 for (j = 0; j < ARRAY_LEN(hinic_tx_queue_stats); j++) {
724 sprintf(p, hinic_tx_queue_stats[j].name, i);
725 p += ETH_GSTRING_LEN;
726 }
727 }
728
729 for (i = 0; i < nic_dev->num_qps; i++) {
730 for (j = 0; j < ARRAY_LEN(hinic_rx_queue_stats); j++) {
731 sprintf(p, hinic_rx_queue_stats[j].name, i);
732 p += ETH_GSTRING_LEN;
733 }
734 }
735
736 return;
737 default:
738 return;
739 }
740 }
741
742 static const struct ethtool_ops hinic_ethtool_ops = {
743 .get_link_ksettings = hinic_get_link_ksettings,
744 .get_drvinfo = hinic_get_drvinfo,
745 .get_link = ethtool_op_get_link,
746 .get_ringparam = hinic_get_ringparam,
747 .get_channels = hinic_get_channels,
748 .get_rxnfc = hinic_get_rxnfc,
749 .set_rxnfc = hinic_set_rxnfc,
750 .get_rxfh_key_size = hinic_get_rxfh_key_size,
751 .get_rxfh_indir_size = hinic_get_rxfh_indir_size,
752 .get_rxfh = hinic_get_rxfh,
753 .set_rxfh = hinic_set_rxfh,
754 .get_sset_count = hinic_get_sset_count,
755 .get_ethtool_stats = hinic_get_ethtool_stats,
756 .get_strings = hinic_get_strings,
757 };
758
759 void hinic_set_ethtool_ops(struct net_device *netdev)
760 {
761 netdev->ethtool_ops = &hinic_ethtool_ops;
762 }