hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/drivers/net/ethernet/huawei/hinic/hinic_port.c
....@@ -1,16 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Huawei HiNIC PCI Express Linux driver
34 * 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
- *
145 */
156
167 #include <linux/types.h>
....@@ -46,19 +37,13 @@
4637 static int change_mac(struct hinic_dev *nic_dev, const u8 *addr,
4738 u16 vlan_id, enum mac_op op)
4839 {
49
- struct net_device *netdev = nic_dev->netdev;
5040 struct hinic_hwdev *hwdev = nic_dev->hwdev;
5141 struct hinic_port_mac_cmd port_mac_cmd;
5242 struct hinic_hwif *hwif = hwdev->hwif;
43
+ u16 out_size = sizeof(port_mac_cmd);
5344 struct pci_dev *pdev = hwif->pdev;
5445 enum hinic_port_cmd cmd;
55
- u16 out_size;
5646 int err;
57
-
58
- if (vlan_id >= VLAN_N_VID) {
59
- netif_err(nic_dev, drv, netdev, "Invalid VLAN number\n");
60
- return -EINVAL;
61
- }
6247
6348 if (op == MAC_SET)
6449 cmd = HINIC_PORT_CMD_SET_MAC;
....@@ -72,11 +57,24 @@
7257 err = hinic_port_msg_cmd(hwdev, cmd, &port_mac_cmd,
7358 sizeof(port_mac_cmd),
7459 &port_mac_cmd, &out_size);
75
- if (err || (out_size != sizeof(port_mac_cmd)) || port_mac_cmd.status) {
76
- dev_err(&pdev->dev, "Failed to change MAC, ret = %d\n",
77
- port_mac_cmd.status);
60
+ if (err || out_size != sizeof(port_mac_cmd) ||
61
+ (port_mac_cmd.status &&
62
+ (port_mac_cmd.status != HINIC_PF_SET_VF_ALREADY || !HINIC_IS_VF(hwif)) &&
63
+ port_mac_cmd.status != HINIC_MGMT_STATUS_EXIST)) {
64
+ dev_err(&pdev->dev, "Failed to change MAC, err: %d, status: 0x%x, out size: 0x%x\n",
65
+ err, port_mac_cmd.status, out_size);
7866 return -EFAULT;
7967 }
68
+
69
+ if (port_mac_cmd.status == HINIC_PF_SET_VF_ALREADY) {
70
+ dev_warn(&pdev->dev, "PF has already set VF mac, ignore %s operation\n",
71
+ (op == MAC_SET) ? "set" : "del");
72
+ return HINIC_PF_SET_VF_ALREADY;
73
+ }
74
+
75
+ if (cmd == HINIC_PORT_CMD_SET_MAC && port_mac_cmd.status ==
76
+ HINIC_MGMT_STATUS_EXIST)
77
+ dev_warn(&pdev->dev, "MAC is repeated, ignore set operation\n");
8078
8179 return 0;
8280 }
....@@ -121,8 +119,8 @@
121119 struct hinic_hwdev *hwdev = nic_dev->hwdev;
122120 struct hinic_port_mac_cmd port_mac_cmd;
123121 struct hinic_hwif *hwif = hwdev->hwif;
122
+ u16 out_size = sizeof(port_mac_cmd);
124123 struct pci_dev *pdev = hwif->pdev;
125
- u16 out_size;
126124 int err;
127125
128126 port_mac_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
....@@ -131,8 +129,8 @@
131129 &port_mac_cmd, sizeof(port_mac_cmd),
132130 &port_mac_cmd, &out_size);
133131 if (err || (out_size != sizeof(port_mac_cmd)) || port_mac_cmd.status) {
134
- dev_err(&pdev->dev, "Failed to get mac, ret = %d\n",
135
- port_mac_cmd.status);
132
+ dev_err(&pdev->dev, "Failed to get mac, err: %d, status: 0x%x, out size: 0x%x\n",
133
+ err, port_mac_cmd.status, out_size);
136134 return -EFAULT;
137135 }
138136
....@@ -153,9 +151,9 @@
153151 struct hinic_hwdev *hwdev = nic_dev->hwdev;
154152 struct hinic_port_mtu_cmd port_mtu_cmd;
155153 struct hinic_hwif *hwif = hwdev->hwif;
154
+ u16 out_size = sizeof(port_mtu_cmd);
156155 struct pci_dev *pdev = hwif->pdev;
157156 int err, max_frame;
158
- u16 out_size;
159157
160158 if (new_mtu < HINIC_MIN_MTU_SIZE) {
161159 netif_err(nic_dev, drv, netdev, "mtu < MIN MTU size");
....@@ -174,9 +172,9 @@
174172 err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_CHANGE_MTU,
175173 &port_mtu_cmd, sizeof(port_mtu_cmd),
176174 &port_mtu_cmd, &out_size);
177
- if (err || (out_size != sizeof(port_mtu_cmd)) || port_mtu_cmd.status) {
178
- dev_err(&pdev->dev, "Failed to set mtu, ret = %d\n",
179
- port_mtu_cmd.status);
175
+ if (err || out_size != sizeof(port_mtu_cmd) || port_mtu_cmd.status) {
176
+ dev_err(&pdev->dev, "Failed to set mtu, err: %d, status: 0x%x, out size: 0x%x\n",
177
+ err, port_mtu_cmd.status, out_size);
180178 return -EFAULT;
181179 }
182180
....@@ -257,13 +255,8 @@
257255 struct hinic_hwif *hwif = hwdev->hwif;
258256 struct hinic_port_link_cmd link_cmd;
259257 struct pci_dev *pdev = hwif->pdev;
260
- u16 out_size;
258
+ u16 out_size = sizeof(link_cmd);
261259 int err;
262
-
263
- if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
264
- dev_err(&pdev->dev, "unsupported PCI Function type\n");
265
- return -EINVAL;
266
- }
267260
268261 link_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
269262
....@@ -271,8 +264,8 @@
271264 &link_cmd, sizeof(link_cmd),
272265 &link_cmd, &out_size);
273266 if (err || (out_size != sizeof(link_cmd)) || link_cmd.status) {
274
- dev_err(&pdev->dev, "Failed to get link state, ret = %d\n",
275
- link_cmd.status);
267
+ dev_err(&pdev->dev, "Failed to get link state, err: %d, status: 0x%x, out size: 0x%x\n",
268
+ err, link_cmd.status, out_size);
276269 return -EINVAL;
277270 }
278271
....@@ -293,13 +286,11 @@
293286 struct hinic_port_state_cmd port_state;
294287 struct hinic_hwif *hwif = hwdev->hwif;
295288 struct pci_dev *pdev = hwif->pdev;
296
- u16 out_size;
289
+ u16 out_size = sizeof(port_state);
297290 int err;
298291
299
- if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
300
- dev_err(&pdev->dev, "unsupported PCI Function type\n");
301
- return -EINVAL;
302
- }
292
+ if (HINIC_IS_VF(hwdev->hwif))
293
+ return 0;
303294
304295 port_state.state = state;
305296
....@@ -307,8 +298,8 @@
307298 &port_state, sizeof(port_state),
308299 &port_state, &out_size);
309300 if (err || (out_size != sizeof(port_state)) || port_state.status) {
310
- dev_err(&pdev->dev, "Failed to set port state, ret = %d\n",
311
- port_state.status);
301
+ dev_err(&pdev->dev, "Failed to set port state, err: %d, status: 0x%x, out size: 0x%x\n",
302
+ err, port_state.status, out_size);
312303 return -EFAULT;
313304 }
314305
....@@ -329,7 +320,7 @@
329320 struct hinic_hwdev *hwdev = nic_dev->hwdev;
330321 struct hinic_hwif *hwif = hwdev->hwif;
331322 struct pci_dev *pdev = hwif->pdev;
332
- u16 out_size;
323
+ u16 out_size = sizeof(func_state);
333324 int err;
334325
335326 func_state.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
....@@ -339,8 +330,8 @@
339330 &func_state, sizeof(func_state),
340331 &func_state, &out_size);
341332 if (err || (out_size != sizeof(func_state)) || func_state.status) {
342
- dev_err(&pdev->dev, "Failed to set port func state, ret = %d\n",
343
- func_state.status);
333
+ dev_err(&pdev->dev, "Failed to set port func state, err: %d, status: 0x%x, out size: 0x%x\n",
334
+ err, func_state.status, out_size);
344335 return -EFAULT;
345336 }
346337
....@@ -360,7 +351,7 @@
360351 struct hinic_hwdev *hwdev = nic_dev->hwdev;
361352 struct hinic_hwif *hwif = hwdev->hwif;
362353 struct pci_dev *pdev = hwif->pdev;
363
- u16 out_size;
354
+ u16 out_size = sizeof(*port_cap);
364355 int err;
365356
366357 port_cap->func_idx = HINIC_HWIF_FUNC_IDX(hwif);
....@@ -370,10 +361,1037 @@
370361 port_cap, &out_size);
371362 if (err || (out_size != sizeof(*port_cap)) || port_cap->status) {
372363 dev_err(&pdev->dev,
373
- "Failed to get port capabilities, ret = %d\n",
374
- port_cap->status);
364
+ "Failed to get port capabilities, err: %d, status: 0x%x, out size: 0x%x\n",
365
+ err, port_cap->status, out_size);
366
+ return -EIO;
367
+ }
368
+
369
+ return 0;
370
+}
371
+
372
+/**
373
+ * hinic_port_set_tso - set port tso configuration
374
+ * @nic_dev: nic device
375
+ * @state: the tso state to set
376
+ *
377
+ * Return 0 - Success, negative - Failure
378
+ **/
379
+int hinic_port_set_tso(struct hinic_dev *nic_dev, enum hinic_tso_state state)
380
+{
381
+ struct hinic_hwdev *hwdev = nic_dev->hwdev;
382
+ struct hinic_hwif *hwif = hwdev->hwif;
383
+ struct hinic_tso_config tso_cfg = {0};
384
+ struct pci_dev *pdev = hwif->pdev;
385
+ u16 out_size = sizeof(tso_cfg);
386
+ int err;
387
+
388
+ tso_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
389
+ tso_cfg.tso_en = state;
390
+
391
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_TSO,
392
+ &tso_cfg, sizeof(tso_cfg),
393
+ &tso_cfg, &out_size);
394
+ if (err || out_size != sizeof(tso_cfg) || tso_cfg.status) {
395
+ dev_err(&pdev->dev,
396
+ "Failed to set port tso, err: %d, status: 0x%x, out size: 0x%x\n",
397
+ err, tso_cfg.status, out_size);
398
+ return -EIO;
399
+ }
400
+
401
+ return 0;
402
+}
403
+
404
+int hinic_set_rx_csum_offload(struct hinic_dev *nic_dev, u32 en)
405
+{
406
+ struct hinic_checksum_offload rx_csum_cfg = {0};
407
+ struct hinic_hwdev *hwdev = nic_dev->hwdev;
408
+ u16 out_size = sizeof(rx_csum_cfg);
409
+ struct hinic_hwif *hwif;
410
+ struct pci_dev *pdev;
411
+ int err;
412
+
413
+ if (!hwdev)
414
+ return -EINVAL;
415
+
416
+ hwif = hwdev->hwif;
417
+ pdev = hwif->pdev;
418
+ rx_csum_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
419
+ rx_csum_cfg.rx_csum_offload = en;
420
+
421
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RX_CSUM,
422
+ &rx_csum_cfg, sizeof(rx_csum_cfg),
423
+ &rx_csum_cfg, &out_size);
424
+ if (err || !out_size || rx_csum_cfg.status) {
425
+ dev_err(&pdev->dev,
426
+ "Failed to set rx csum offload, err: %d, status: 0x%x, out size: 0x%x\n",
427
+ err, rx_csum_cfg.status, out_size);
428
+ return -EIO;
429
+ }
430
+
431
+ return 0;
432
+}
433
+
434
+int hinic_set_rx_vlan_offload(struct hinic_dev *nic_dev, u8 en)
435
+{
436
+ struct hinic_hwdev *hwdev = nic_dev->hwdev;
437
+ struct hinic_vlan_cfg vlan_cfg;
438
+ struct hinic_hwif *hwif;
439
+ struct pci_dev *pdev;
440
+ u16 out_size;
441
+ int err;
442
+
443
+ if (!hwdev)
444
+ return -EINVAL;
445
+
446
+ out_size = sizeof(vlan_cfg);
447
+ hwif = hwdev->hwif;
448
+ pdev = hwif->pdev;
449
+ vlan_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
450
+ vlan_cfg.vlan_rx_offload = en;
451
+
452
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RX_VLAN_OFFLOAD,
453
+ &vlan_cfg, sizeof(vlan_cfg),
454
+ &vlan_cfg, &out_size);
455
+ if (err || !out_size || vlan_cfg.status) {
456
+ dev_err(&pdev->dev,
457
+ "Failed to set rx vlan offload, err: %d, status: 0x%x, out size: 0x%x\n",
458
+ err, vlan_cfg.status, out_size);
375459 return -EINVAL;
376460 }
377461
378462 return 0;
379463 }
464
+
465
+int hinic_set_max_qnum(struct hinic_dev *nic_dev, u8 num_rqs)
466
+{
467
+ struct hinic_hwdev *hwdev = nic_dev->hwdev;
468
+ struct hinic_hwif *hwif = hwdev->hwif;
469
+ struct hinic_rq_num rq_num = { 0 };
470
+ struct pci_dev *pdev = hwif->pdev;
471
+ u16 out_size = sizeof(rq_num);
472
+ int err;
473
+
474
+ rq_num.func_id = HINIC_HWIF_FUNC_IDX(hwif);
475
+ rq_num.num_rqs = num_rqs;
476
+ rq_num.rq_depth = ilog2(nic_dev->rq_depth);
477
+
478
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RQ_IQ_MAP,
479
+ &rq_num, sizeof(rq_num),
480
+ &rq_num, &out_size);
481
+ if (err || !out_size || rq_num.status) {
482
+ dev_err(&pdev->dev,
483
+ "Failed to set rxq number, err: %d, status: 0x%x, out size: 0x%x\n",
484
+ err, rq_num.status, out_size);
485
+ return -EIO;
486
+ }
487
+
488
+ return 0;
489
+}
490
+
491
+static int hinic_set_rx_lro(struct hinic_dev *nic_dev, u8 ipv4_en, u8 ipv6_en,
492
+ u8 max_wqe_num)
493
+{
494
+ struct hinic_hwdev *hwdev = nic_dev->hwdev;
495
+ struct hinic_lro_config lro_cfg = { 0 };
496
+ struct hinic_hwif *hwif = hwdev->hwif;
497
+ struct pci_dev *pdev = hwif->pdev;
498
+ u16 out_size = sizeof(lro_cfg);
499
+ int err;
500
+
501
+ lro_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
502
+ lro_cfg.lro_ipv4_en = ipv4_en;
503
+ lro_cfg.lro_ipv6_en = ipv6_en;
504
+ lro_cfg.lro_max_wqe_num = max_wqe_num;
505
+
506
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_LRO,
507
+ &lro_cfg, sizeof(lro_cfg),
508
+ &lro_cfg, &out_size);
509
+ if (err || !out_size || lro_cfg.status) {
510
+ dev_err(&pdev->dev,
511
+ "Failed to set lro offload, err: %d, status: 0x%x, out size: 0x%x\n",
512
+ err, lro_cfg.status, out_size);
513
+ return -EIO;
514
+ }
515
+
516
+ return 0;
517
+}
518
+
519
+static int hinic_set_rx_lro_timer(struct hinic_dev *nic_dev, u32 timer_value)
520
+{
521
+ struct hinic_hwdev *hwdev = nic_dev->hwdev;
522
+ struct hinic_lro_timer lro_timer = { 0 };
523
+ struct hinic_hwif *hwif = hwdev->hwif;
524
+ struct pci_dev *pdev = hwif->pdev;
525
+ u16 out_size = sizeof(lro_timer);
526
+ int err;
527
+
528
+ lro_timer.status = 0;
529
+ lro_timer.type = 0;
530
+ lro_timer.enable = 1;
531
+ lro_timer.timer = timer_value;
532
+
533
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_LRO_TIMER,
534
+ &lro_timer, sizeof(lro_timer),
535
+ &lro_timer, &out_size);
536
+ if (lro_timer.status == 0xFF) {
537
+ /* For this case, we think status (0xFF) is OK */
538
+ lro_timer.status = 0;
539
+ dev_dbg(&pdev->dev,
540
+ "Set lro timer not supported by the current FW version, it will be 1ms default\n");
541
+ }
542
+
543
+ if (err || !out_size || lro_timer.status) {
544
+ dev_err(&pdev->dev,
545
+ "Failed to set lro timer, err: %d, status: 0x%x, out size: 0x%x\n",
546
+ err, lro_timer.status, out_size);
547
+
548
+ return -EIO;
549
+ }
550
+
551
+ return 0;
552
+}
553
+
554
+int hinic_set_rx_lro_state(struct hinic_dev *nic_dev, u8 lro_en,
555
+ u32 lro_timer, u32 wqe_num)
556
+{
557
+ struct hinic_hwdev *hwdev = nic_dev->hwdev;
558
+ u8 ipv4_en;
559
+ u8 ipv6_en;
560
+ int err;
561
+
562
+ if (!hwdev)
563
+ return -EINVAL;
564
+
565
+ ipv4_en = lro_en ? 1 : 0;
566
+ ipv6_en = lro_en ? 1 : 0;
567
+
568
+ err = hinic_set_rx_lro(nic_dev, ipv4_en, ipv6_en, (u8)wqe_num);
569
+ if (err)
570
+ return err;
571
+
572
+ if (HINIC_IS_VF(nic_dev->hwdev->hwif))
573
+ return 0;
574
+
575
+ err = hinic_set_rx_lro_timer(nic_dev, lro_timer);
576
+ if (err)
577
+ return err;
578
+
579
+ return 0;
580
+}
581
+
582
+int hinic_rss_set_indir_tbl(struct hinic_dev *nic_dev, u32 tmpl_idx,
583
+ const u32 *indir_table)
584
+{
585
+ struct hinic_rss_indirect_tbl *indir_tbl;
586
+ struct hinic_func_to_io *func_to_io;
587
+ struct hinic_cmdq_buf cmd_buf;
588
+ struct hinic_hwdev *hwdev;
589
+ struct hinic_hwif *hwif;
590
+ struct pci_dev *pdev;
591
+ u32 indir_size;
592
+ u64 out_param;
593
+ int err, i;
594
+ u32 *temp;
595
+
596
+ hwdev = nic_dev->hwdev;
597
+ func_to_io = &hwdev->func_to_io;
598
+ hwif = hwdev->hwif;
599
+ pdev = hwif->pdev;
600
+
601
+ err = hinic_alloc_cmdq_buf(&func_to_io->cmdqs, &cmd_buf);
602
+ if (err) {
603
+ dev_err(&pdev->dev, "Failed to allocate cmdq buf\n");
604
+ return err;
605
+ }
606
+
607
+ cmd_buf.size = sizeof(*indir_tbl);
608
+
609
+ indir_tbl = cmd_buf.buf;
610
+ indir_tbl->group_index = cpu_to_be32(tmpl_idx);
611
+
612
+ for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++) {
613
+ indir_tbl->entry[i] = indir_table[i];
614
+
615
+ if (0x3 == (i & 0x3)) {
616
+ temp = (u32 *)&indir_tbl->entry[i - 3];
617
+ *temp = cpu_to_be32(*temp);
618
+ }
619
+ }
620
+
621
+ /* cfg the rss indirect table by command queue */
622
+ indir_size = HINIC_RSS_INDIR_SIZE / 2;
623
+ indir_tbl->offset = 0;
624
+ indir_tbl->size = cpu_to_be32(indir_size);
625
+
626
+ err = hinic_cmdq_direct_resp(&func_to_io->cmdqs, HINIC_MOD_L2NIC,
627
+ HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
628
+ &cmd_buf, &out_param);
629
+ if (err || out_param != 0) {
630
+ dev_err(&pdev->dev, "Failed to set rss indir table\n");
631
+ err = -EFAULT;
632
+ goto free_buf;
633
+ }
634
+
635
+ indir_tbl->offset = cpu_to_be32(indir_size);
636
+ indir_tbl->size = cpu_to_be32(indir_size);
637
+ memcpy(&indir_tbl->entry[0], &indir_tbl->entry[indir_size], indir_size);
638
+
639
+ err = hinic_cmdq_direct_resp(&func_to_io->cmdqs, HINIC_MOD_L2NIC,
640
+ HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
641
+ &cmd_buf, &out_param);
642
+ if (err || out_param != 0) {
643
+ dev_err(&pdev->dev, "Failed to set rss indir table\n");
644
+ err = -EFAULT;
645
+ }
646
+
647
+free_buf:
648
+ hinic_free_cmdq_buf(&func_to_io->cmdqs, &cmd_buf);
649
+
650
+ return err;
651
+}
652
+
653
+int hinic_rss_get_indir_tbl(struct hinic_dev *nic_dev, u32 tmpl_idx,
654
+ u32 *indir_table)
655
+{
656
+ struct hinic_rss_indir_table rss_cfg = { 0 };
657
+ struct hinic_hwdev *hwdev = nic_dev->hwdev;
658
+ struct hinic_hwif *hwif = hwdev->hwif;
659
+ struct pci_dev *pdev = hwif->pdev;
660
+ u16 out_size = sizeof(rss_cfg);
661
+ int err = 0, i;
662
+
663
+ rss_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
664
+ rss_cfg.template_id = tmpl_idx;
665
+
666
+ err = hinic_port_msg_cmd(hwdev,
667
+ HINIC_PORT_CMD_GET_RSS_TEMPLATE_INDIR_TBL,
668
+ &rss_cfg, sizeof(rss_cfg), &rss_cfg,
669
+ &out_size);
670
+ if (err || !out_size || rss_cfg.status) {
671
+ dev_err(&pdev->dev, "Failed to get indir table, err: %d, status: 0x%x, out size: 0x%x\n",
672
+ err, rss_cfg.status, out_size);
673
+ return -EINVAL;
674
+ }
675
+
676
+ hinic_be32_to_cpu(rss_cfg.indir, HINIC_RSS_INDIR_SIZE);
677
+ for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++)
678
+ indir_table[i] = rss_cfg.indir[i];
679
+
680
+ return 0;
681
+}
682
+
683
+int hinic_set_rss_type(struct hinic_dev *nic_dev, u32 tmpl_idx,
684
+ struct hinic_rss_type rss_type)
685
+{
686
+ struct hinic_rss_context_tbl *ctx_tbl;
687
+ struct hinic_func_to_io *func_to_io;
688
+ struct hinic_cmdq_buf cmd_buf;
689
+ struct hinic_hwdev *hwdev;
690
+ struct hinic_hwif *hwif;
691
+ struct pci_dev *pdev;
692
+ u64 out_param;
693
+ u32 ctx = 0;
694
+ int err;
695
+
696
+ hwdev = nic_dev->hwdev;
697
+ func_to_io = &hwdev->func_to_io;
698
+ hwif = hwdev->hwif;
699
+ pdev = hwif->pdev;
700
+
701
+ err = hinic_alloc_cmdq_buf(&func_to_io->cmdqs, &cmd_buf);
702
+ if (err) {
703
+ dev_err(&pdev->dev, "Failed to allocate cmd buf\n");
704
+ return -ENOMEM;
705
+ }
706
+
707
+ ctx |= HINIC_RSS_TYPE_SET(1, VALID) |
708
+ HINIC_RSS_TYPE_SET(rss_type.ipv4, IPV4) |
709
+ HINIC_RSS_TYPE_SET(rss_type.ipv6, IPV6) |
710
+ HINIC_RSS_TYPE_SET(rss_type.ipv6_ext, IPV6_EXT) |
711
+ HINIC_RSS_TYPE_SET(rss_type.tcp_ipv4, TCP_IPV4) |
712
+ HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6, TCP_IPV6) |
713
+ HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6_ext, TCP_IPV6_EXT) |
714
+ HINIC_RSS_TYPE_SET(rss_type.udp_ipv4, UDP_IPV4) |
715
+ HINIC_RSS_TYPE_SET(rss_type.udp_ipv6, UDP_IPV6);
716
+
717
+ cmd_buf.size = sizeof(struct hinic_rss_context_tbl);
718
+
719
+ ctx_tbl = (struct hinic_rss_context_tbl *)cmd_buf.buf;
720
+ ctx_tbl->group_index = cpu_to_be32(tmpl_idx);
721
+ ctx_tbl->offset = 0;
722
+ ctx_tbl->size = sizeof(u32);
723
+ ctx_tbl->size = cpu_to_be32(ctx_tbl->size);
724
+ ctx_tbl->rsvd = 0;
725
+ ctx_tbl->ctx = cpu_to_be32(ctx);
726
+
727
+ /* cfg the rss context table by command queue */
728
+ err = hinic_cmdq_direct_resp(&func_to_io->cmdqs, HINIC_MOD_L2NIC,
729
+ HINIC_UCODE_CMD_SET_RSS_CONTEXT_TABLE,
730
+ &cmd_buf, &out_param);
731
+
732
+ hinic_free_cmdq_buf(&func_to_io->cmdqs, &cmd_buf);
733
+
734
+ if (err || out_param != 0) {
735
+ dev_err(&pdev->dev, "Failed to set rss context table, err: %d\n",
736
+ err);
737
+ return -EFAULT;
738
+ }
739
+
740
+ return 0;
741
+}
742
+
743
+int hinic_get_rss_type(struct hinic_dev *nic_dev, u32 tmpl_idx,
744
+ struct hinic_rss_type *rss_type)
745
+{
746
+ struct hinic_rss_context_table ctx_tbl = { 0 };
747
+ struct hinic_hwdev *hwdev = nic_dev->hwdev;
748
+ u16 out_size = sizeof(ctx_tbl);
749
+ struct hinic_hwif *hwif;
750
+ struct pci_dev *pdev;
751
+ int err;
752
+
753
+ if (!hwdev || !rss_type)
754
+ return -EINVAL;
755
+
756
+ hwif = hwdev->hwif;
757
+ pdev = hwif->pdev;
758
+
759
+ ctx_tbl.func_id = HINIC_HWIF_FUNC_IDX(hwif);
760
+ ctx_tbl.template_id = tmpl_idx;
761
+
762
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_RSS_CTX_TBL,
763
+ &ctx_tbl, sizeof(ctx_tbl),
764
+ &ctx_tbl, &out_size);
765
+ if (err || !out_size || ctx_tbl.status) {
766
+ dev_err(&pdev->dev, "Failed to get hash type, err: %d, status: 0x%x, out size: 0x%x\n",
767
+ err, ctx_tbl.status, out_size);
768
+ return -EINVAL;
769
+ }
770
+
771
+ rss_type->ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV4);
772
+ rss_type->ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6);
773
+ rss_type->ipv6_ext = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6_EXT);
774
+ rss_type->tcp_ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV4);
775
+ rss_type->tcp_ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6);
776
+ rss_type->tcp_ipv6_ext = HINIC_RSS_TYPE_GET(ctx_tbl.context,
777
+ TCP_IPV6_EXT);
778
+ rss_type->udp_ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV4);
779
+ rss_type->udp_ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV6);
780
+
781
+ return 0;
782
+}
783
+
784
+int hinic_rss_set_template_tbl(struct hinic_dev *nic_dev, u32 template_id,
785
+ const u8 *temp)
786
+{
787
+ struct hinic_hwdev *hwdev = nic_dev->hwdev;
788
+ struct hinic_hwif *hwif = hwdev->hwif;
789
+ struct hinic_rss_key rss_key = { 0 };
790
+ struct pci_dev *pdev = hwif->pdev;
791
+ u16 out_size = sizeof(rss_key);
792
+ int err;
793
+
794
+ rss_key.func_id = HINIC_HWIF_FUNC_IDX(hwif);
795
+ rss_key.template_id = template_id;
796
+ memcpy(rss_key.key, temp, HINIC_RSS_KEY_SIZE);
797
+
798
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RSS_TEMPLATE_TBL,
799
+ &rss_key, sizeof(rss_key),
800
+ &rss_key, &out_size);
801
+ if (err || !out_size || rss_key.status) {
802
+ dev_err(&pdev->dev,
803
+ "Failed to set rss hash key, err: %d, status: 0x%x, out size: 0x%x\n",
804
+ err, rss_key.status, out_size);
805
+ return -EINVAL;
806
+ }
807
+
808
+ return 0;
809
+}
810
+
811
+int hinic_rss_get_template_tbl(struct hinic_dev *nic_dev, u32 tmpl_idx,
812
+ u8 *temp)
813
+{
814
+ struct hinic_rss_template_key temp_key = { 0 };
815
+ struct hinic_hwdev *hwdev = nic_dev->hwdev;
816
+ u16 out_size = sizeof(temp_key);
817
+ struct hinic_hwif *hwif;
818
+ struct pci_dev *pdev;
819
+ int err;
820
+
821
+ if (!hwdev || !temp)
822
+ return -EINVAL;
823
+
824
+ hwif = hwdev->hwif;
825
+ pdev = hwif->pdev;
826
+
827
+ temp_key.func_id = HINIC_HWIF_FUNC_IDX(hwif);
828
+ temp_key.template_id = tmpl_idx;
829
+
830
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_RSS_TEMPLATE_TBL,
831
+ &temp_key, sizeof(temp_key),
832
+ &temp_key, &out_size);
833
+ if (err || !out_size || temp_key.status) {
834
+ dev_err(&pdev->dev, "Failed to set hash key, err: %d, status: 0x%x, out size: 0x%x\n",
835
+ err, temp_key.status, out_size);
836
+ return -EINVAL;
837
+ }
838
+
839
+ memcpy(temp, temp_key.key, HINIC_RSS_KEY_SIZE);
840
+
841
+ return 0;
842
+}
843
+
844
+int hinic_rss_set_hash_engine(struct hinic_dev *nic_dev, u8 template_id,
845
+ u8 type)
846
+{
847
+ struct hinic_rss_engine_type rss_engine = { 0 };
848
+ struct hinic_hwdev *hwdev = nic_dev->hwdev;
849
+ struct hinic_hwif *hwif = hwdev->hwif;
850
+ struct pci_dev *pdev = hwif->pdev;
851
+ u16 out_size = sizeof(rss_engine);
852
+ int err;
853
+
854
+ rss_engine.func_id = HINIC_HWIF_FUNC_IDX(hwif);
855
+ rss_engine.hash_engine = type;
856
+ rss_engine.template_id = template_id;
857
+
858
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RSS_HASH_ENGINE,
859
+ &rss_engine, sizeof(rss_engine),
860
+ &rss_engine, &out_size);
861
+ if (err || !out_size || rss_engine.status) {
862
+ dev_err(&pdev->dev,
863
+ "Failed to set hash engine, err: %d, status: 0x%x, out size: 0x%x\n",
864
+ err, rss_engine.status, out_size);
865
+ return -EINVAL;
866
+ }
867
+
868
+ return 0;
869
+}
870
+
871
+int hinic_rss_get_hash_engine(struct hinic_dev *nic_dev, u8 tmpl_idx, u8 *type)
872
+{
873
+ struct hinic_rss_engine_type hash_type = { 0 };
874
+ struct hinic_hwdev *hwdev = nic_dev->hwdev;
875
+ u16 out_size = sizeof(hash_type);
876
+ struct hinic_hwif *hwif;
877
+ struct pci_dev *pdev;
878
+ int err;
879
+
880
+ if (!hwdev || !type)
881
+ return -EINVAL;
882
+
883
+ hwif = hwdev->hwif;
884
+ pdev = hwif->pdev;
885
+
886
+ hash_type.func_id = HINIC_HWIF_FUNC_IDX(hwif);
887
+ hash_type.template_id = tmpl_idx;
888
+
889
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_RSS_HASH_ENGINE,
890
+ &hash_type, sizeof(hash_type),
891
+ &hash_type, &out_size);
892
+ if (err || !out_size || hash_type.status) {
893
+ dev_err(&pdev->dev, "Failed to get hash engine, err: %d, status: 0x%x, out size: 0x%x\n",
894
+ err, hash_type.status, out_size);
895
+ return -EINVAL;
896
+ }
897
+
898
+ *type = hash_type.hash_engine;
899
+ return 0;
900
+}
901
+
902
+int hinic_rss_cfg(struct hinic_dev *nic_dev, u8 rss_en, u8 template_id)
903
+{
904
+ struct hinic_hwdev *hwdev = nic_dev->hwdev;
905
+ struct hinic_rss_config rss_cfg = { 0 };
906
+ struct hinic_hwif *hwif = hwdev->hwif;
907
+ struct pci_dev *pdev = hwif->pdev;
908
+ u16 out_size = sizeof(rss_cfg);
909
+ int err;
910
+
911
+ rss_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
912
+ rss_cfg.rss_en = rss_en;
913
+ rss_cfg.template_id = template_id;
914
+ rss_cfg.rq_priority_number = 0;
915
+
916
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_RSS_CFG,
917
+ &rss_cfg, sizeof(rss_cfg),
918
+ &rss_cfg, &out_size);
919
+ if (err || !out_size || rss_cfg.status) {
920
+ dev_err(&pdev->dev,
921
+ "Failed to set rss cfg, err: %d, status: 0x%x, out size: 0x%x\n",
922
+ err, rss_cfg.status, out_size);
923
+ return -EINVAL;
924
+ }
925
+
926
+ return 0;
927
+}
928
+
929
+int hinic_rss_template_alloc(struct hinic_dev *nic_dev, u8 *tmpl_idx)
930
+{
931
+ struct hinic_rss_template_mgmt template_mgmt = { 0 };
932
+ struct hinic_hwdev *hwdev = nic_dev->hwdev;
933
+ struct hinic_hwif *hwif = hwdev->hwif;
934
+ u16 out_size = sizeof(template_mgmt);
935
+ struct pci_dev *pdev = hwif->pdev;
936
+ int err;
937
+
938
+ template_mgmt.func_id = HINIC_HWIF_FUNC_IDX(hwif);
939
+ template_mgmt.cmd = NIC_RSS_CMD_TEMP_ALLOC;
940
+
941
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
942
+ &template_mgmt, sizeof(template_mgmt),
943
+ &template_mgmt, &out_size);
944
+ if (err || !out_size || template_mgmt.status) {
945
+ dev_err(&pdev->dev, "Failed to alloc rss template, err: %d, status: 0x%x, out size: 0x%x\n",
946
+ err, template_mgmt.status, out_size);
947
+ return -EINVAL;
948
+ }
949
+
950
+ *tmpl_idx = template_mgmt.template_id;
951
+
952
+ return 0;
953
+}
954
+
955
+int hinic_rss_template_free(struct hinic_dev *nic_dev, u8 tmpl_idx)
956
+{
957
+ struct hinic_rss_template_mgmt template_mgmt = { 0 };
958
+ struct hinic_hwdev *hwdev = nic_dev->hwdev;
959
+ struct hinic_hwif *hwif = hwdev->hwif;
960
+ u16 out_size = sizeof(template_mgmt);
961
+ struct pci_dev *pdev = hwif->pdev;
962
+ int err;
963
+
964
+ template_mgmt.func_id = HINIC_HWIF_FUNC_IDX(hwif);
965
+ template_mgmt.template_id = tmpl_idx;
966
+ template_mgmt.cmd = NIC_RSS_CMD_TEMP_FREE;
967
+
968
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
969
+ &template_mgmt, sizeof(template_mgmt),
970
+ &template_mgmt, &out_size);
971
+ if (err || !out_size || template_mgmt.status) {
972
+ dev_err(&pdev->dev, "Failed to free rss template, err: %d, status: 0x%x, out size: 0x%x\n",
973
+ err, template_mgmt.status, out_size);
974
+ return -EINVAL;
975
+ }
976
+
977
+ return 0;
978
+}
979
+
980
+int hinic_get_vport_stats(struct hinic_dev *nic_dev,
981
+ struct hinic_vport_stats *stats)
982
+{
983
+ struct hinic_cmd_vport_stats vport_stats = { 0 };
984
+ struct hinic_port_stats_info stats_info = { 0 };
985
+ struct hinic_hwdev *hwdev = nic_dev->hwdev;
986
+ struct hinic_hwif *hwif = hwdev->hwif;
987
+ u16 out_size = sizeof(vport_stats);
988
+ struct pci_dev *pdev = hwif->pdev;
989
+ int err;
990
+
991
+ stats_info.stats_version = HINIC_PORT_STATS_VERSION;
992
+ stats_info.func_id = HINIC_HWIF_FUNC_IDX(hwif);
993
+ stats_info.stats_size = sizeof(vport_stats);
994
+
995
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_VPORT_STAT,
996
+ &stats_info, sizeof(stats_info),
997
+ &vport_stats, &out_size);
998
+ if (err || !out_size || vport_stats.status) {
999
+ dev_err(&pdev->dev,
1000
+ "Failed to get function statistics, err: %d, status: 0x%x, out size: 0x%x\n",
1001
+ err, vport_stats.status, out_size);
1002
+ return -EFAULT;
1003
+ }
1004
+
1005
+ memcpy(stats, &vport_stats.stats, sizeof(*stats));
1006
+ return 0;
1007
+}
1008
+
1009
+int hinic_get_phy_port_stats(struct hinic_dev *nic_dev,
1010
+ struct hinic_phy_port_stats *stats)
1011
+{
1012
+ struct hinic_port_stats_info stats_info = { 0 };
1013
+ struct hinic_hwdev *hwdev = nic_dev->hwdev;
1014
+ struct hinic_hwif *hwif = hwdev->hwif;
1015
+ struct hinic_port_stats *port_stats;
1016
+ u16 out_size = sizeof(*port_stats);
1017
+ struct pci_dev *pdev = hwif->pdev;
1018
+ int err;
1019
+
1020
+ port_stats = kzalloc(sizeof(*port_stats), GFP_KERNEL);
1021
+ if (!port_stats)
1022
+ return -ENOMEM;
1023
+
1024
+ stats_info.stats_version = HINIC_PORT_STATS_VERSION;
1025
+ stats_info.stats_size = sizeof(*port_stats);
1026
+
1027
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_PORT_STATISTICS,
1028
+ &stats_info, sizeof(stats_info),
1029
+ port_stats, &out_size);
1030
+ if (err || !out_size || port_stats->status) {
1031
+ dev_err(&pdev->dev,
1032
+ "Failed to get port statistics, err: %d, status: 0x%x, out size: 0x%x\n",
1033
+ err, port_stats->status, out_size);
1034
+ err = -EINVAL;
1035
+ goto out;
1036
+ }
1037
+
1038
+ memcpy(stats, &port_stats->stats, sizeof(*stats));
1039
+
1040
+out:
1041
+ kfree(port_stats);
1042
+
1043
+ return err;
1044
+}
1045
+
1046
+int hinic_get_mgmt_version(struct hinic_dev *nic_dev, u8 *mgmt_ver)
1047
+{
1048
+ struct hinic_hwdev *hwdev = nic_dev->hwdev;
1049
+ struct hinic_version_info up_ver = {0};
1050
+ u16 out_size = sizeof(up_ver);
1051
+ struct hinic_hwif *hwif;
1052
+ struct pci_dev *pdev;
1053
+ int err;
1054
+
1055
+ if (!hwdev)
1056
+ return -EINVAL;
1057
+
1058
+ hwif = hwdev->hwif;
1059
+ pdev = hwif->pdev;
1060
+
1061
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_MGMT_VERSION,
1062
+ &up_ver, sizeof(up_ver), &up_ver,
1063
+ &out_size);
1064
+ if (err || !out_size || up_ver.status) {
1065
+ dev_err(&pdev->dev,
1066
+ "Failed to get mgmt version, err: %d, status: 0x%x, out size: 0x%x\n",
1067
+ err, up_ver.status, out_size);
1068
+ return -EINVAL;
1069
+ }
1070
+
1071
+ snprintf(mgmt_ver, HINIC_MGMT_VERSION_MAX_LEN, "%s", up_ver.ver);
1072
+
1073
+ return 0;
1074
+}
1075
+
1076
+int hinic_get_link_mode(struct hinic_hwdev *hwdev,
1077
+ struct hinic_link_mode_cmd *link_mode)
1078
+{
1079
+ u16 out_size;
1080
+ int err;
1081
+
1082
+ if (!hwdev || !link_mode)
1083
+ return -EINVAL;
1084
+
1085
+ link_mode->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
1086
+ out_size = sizeof(*link_mode);
1087
+
1088
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_LINK_MODE,
1089
+ link_mode, sizeof(*link_mode),
1090
+ link_mode, &out_size);
1091
+ if (err || !out_size || link_mode->status) {
1092
+ dev_err(&hwdev->hwif->pdev->dev,
1093
+ "Failed to get link mode, err: %d, status: 0x%x, out size: 0x%x\n",
1094
+ err, link_mode->status, out_size);
1095
+ return -EIO;
1096
+ }
1097
+
1098
+ return 0;
1099
+}
1100
+
1101
+int hinic_set_autoneg(struct hinic_hwdev *hwdev, bool enable)
1102
+{
1103
+ struct hinic_set_autoneg_cmd autoneg = {0};
1104
+ u16 out_size = sizeof(autoneg);
1105
+ int err;
1106
+
1107
+ if (!hwdev)
1108
+ return -EINVAL;
1109
+
1110
+ autoneg.func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
1111
+ autoneg.enable = enable;
1112
+
1113
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_AUTONEG,
1114
+ &autoneg, sizeof(autoneg),
1115
+ &autoneg, &out_size);
1116
+ if (err || !out_size || autoneg.status) {
1117
+ dev_err(&hwdev->hwif->pdev->dev, "Failed to %s autoneg, err: %d, status: 0x%x, out size: 0x%x\n",
1118
+ enable ? "enable" : "disable", err, autoneg.status,
1119
+ out_size);
1120
+ return -EIO;
1121
+ }
1122
+
1123
+ return 0;
1124
+}
1125
+
1126
+int hinic_set_speed(struct hinic_hwdev *hwdev, enum nic_speed_level speed)
1127
+{
1128
+ struct hinic_speed_cmd speed_info = {0};
1129
+ u16 out_size = sizeof(speed_info);
1130
+ int err;
1131
+
1132
+ if (!hwdev)
1133
+ return -EINVAL;
1134
+
1135
+ speed_info.func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
1136
+ speed_info.speed = speed;
1137
+
1138
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_SPEED,
1139
+ &speed_info, sizeof(speed_info),
1140
+ &speed_info, &out_size);
1141
+ if (err || !out_size || speed_info.status) {
1142
+ dev_err(&hwdev->hwif->pdev->dev,
1143
+ "Failed to set speed, err: %d, status: 0x%x, out size: 0x%x\n",
1144
+ err, speed_info.status, out_size);
1145
+ return -EIO;
1146
+ }
1147
+
1148
+ return 0;
1149
+}
1150
+
1151
+int hinic_set_link_settings(struct hinic_hwdev *hwdev,
1152
+ struct hinic_link_ksettings_info *info)
1153
+{
1154
+ u16 out_size = sizeof(*info);
1155
+ int err;
1156
+
1157
+ err = hinic_hilink_msg_cmd(hwdev, HINIC_HILINK_CMD_SET_LINK_SETTINGS,
1158
+ info, sizeof(*info), info, &out_size);
1159
+ if ((info->status != HINIC_MGMT_CMD_UNSUPPORTED &&
1160
+ info->status) || err || !out_size) {
1161
+ dev_err(&hwdev->hwif->pdev->dev,
1162
+ "Failed to set link settings, err: %d, status: 0x%x, out size: 0x%x\n",
1163
+ err, info->status, out_size);
1164
+ return -EFAULT;
1165
+ }
1166
+
1167
+ return info->status;
1168
+}
1169
+
1170
+int hinic_get_hw_pause_info(struct hinic_hwdev *hwdev,
1171
+ struct hinic_pause_config *pause_info)
1172
+{
1173
+ u16 out_size = sizeof(*pause_info);
1174
+ int err;
1175
+
1176
+ pause_info->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
1177
+
1178
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_PAUSE_INFO,
1179
+ pause_info, sizeof(*pause_info),
1180
+ pause_info, &out_size);
1181
+ if (err || !out_size || pause_info->status) {
1182
+ dev_err(&hwdev->hwif->pdev->dev, "Failed to get pause info, err: %d, status: 0x%x, out size: 0x%x\n",
1183
+ err, pause_info->status, out_size);
1184
+ return -EIO;
1185
+ }
1186
+
1187
+ return 0;
1188
+}
1189
+
1190
+int hinic_set_hw_pause_info(struct hinic_hwdev *hwdev,
1191
+ struct hinic_pause_config *pause_info)
1192
+{
1193
+ u16 out_size = sizeof(*pause_info);
1194
+ int err;
1195
+
1196
+ pause_info->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
1197
+
1198
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_PAUSE_INFO,
1199
+ pause_info, sizeof(*pause_info),
1200
+ pause_info, &out_size);
1201
+ if (err || !out_size || pause_info->status) {
1202
+ dev_err(&hwdev->hwif->pdev->dev, "Failed to set pause info, err: %d, status: 0x%x, out size: 0x%x\n",
1203
+ err, pause_info->status, out_size);
1204
+ return -EIO;
1205
+ }
1206
+
1207
+ return 0;
1208
+}
1209
+
1210
+int hinic_dcb_set_pfc(struct hinic_hwdev *hwdev, u8 pfc_en, u8 pfc_bitmap)
1211
+{
1212
+ struct hinic_nic_cfg *nic_cfg = &hwdev->func_to_io.nic_cfg;
1213
+ struct hinic_set_pfc pfc = {0};
1214
+ u16 out_size = sizeof(pfc);
1215
+ int err;
1216
+
1217
+ if (HINIC_IS_VF(hwdev->hwif))
1218
+ return 0;
1219
+
1220
+ mutex_lock(&nic_cfg->cfg_mutex);
1221
+
1222
+ pfc.func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
1223
+ pfc.pfc_bitmap = pfc_bitmap;
1224
+ pfc.pfc_en = pfc_en;
1225
+
1226
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_PFC,
1227
+ &pfc, sizeof(pfc), &pfc, &out_size);
1228
+ if (err || pfc.status || !out_size) {
1229
+ dev_err(&hwdev->hwif->pdev->dev, "Failed to %s pfc, err: %d, status: 0x%x, out size: 0x%x\n",
1230
+ pfc_en ? "enable" : "disable", err, pfc.status,
1231
+ out_size);
1232
+ mutex_unlock(&nic_cfg->cfg_mutex);
1233
+ return -EIO;
1234
+ }
1235
+
1236
+ /* pause settings is opposite from pfc */
1237
+ nic_cfg->rx_pause = pfc_en ? 0 : 1;
1238
+ nic_cfg->tx_pause = pfc_en ? 0 : 1;
1239
+
1240
+ mutex_unlock(&nic_cfg->cfg_mutex);
1241
+
1242
+ return 0;
1243
+}
1244
+
1245
+int hinic_set_loopback_mode(struct hinic_hwdev *hwdev, u32 mode, u32 enable)
1246
+{
1247
+ struct hinic_port_loopback lb = {0};
1248
+ u16 out_size = sizeof(lb);
1249
+ int err;
1250
+
1251
+ lb.mode = mode;
1252
+ lb.en = enable;
1253
+
1254
+ if (mode < LOOP_MODE_MIN || mode > LOOP_MODE_MAX) {
1255
+ dev_err(&hwdev->hwif->pdev->dev,
1256
+ "Invalid loopback mode %d to set\n", mode);
1257
+ return -EINVAL;
1258
+ }
1259
+
1260
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_LOOPBACK_MODE,
1261
+ &lb, sizeof(lb), &lb, &out_size);
1262
+ if (err || !out_size || lb.status) {
1263
+ dev_err(&hwdev->hwif->pdev->dev,
1264
+ "Failed to set loopback mode %d en %d, err: %d, status: 0x%x, out size: 0x%x\n",
1265
+ mode, enable, err, lb.status, out_size);
1266
+ return -EIO;
1267
+ }
1268
+
1269
+ return 0;
1270
+}
1271
+
1272
+static int _set_led_status(struct hinic_hwdev *hwdev, u8 port,
1273
+ enum hinic_led_type type,
1274
+ enum hinic_led_mode mode, u8 reset)
1275
+{
1276
+ struct hinic_led_info led_info = {0};
1277
+ u16 out_size = sizeof(led_info);
1278
+ struct hinic_pfhwdev *pfhwdev;
1279
+ int err;
1280
+
1281
+ pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
1282
+
1283
+ led_info.port = port;
1284
+ led_info.reset = reset;
1285
+
1286
+ led_info.type = type;
1287
+ led_info.mode = mode;
1288
+
1289
+ err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
1290
+ HINIC_COMM_CMD_SET_LED_STATUS,
1291
+ &led_info, sizeof(led_info),
1292
+ &led_info, &out_size, HINIC_MGMT_MSG_SYNC);
1293
+ if (err || led_info.status || !out_size) {
1294
+ dev_err(&hwdev->hwif->pdev->dev, "Failed to set led status, err: %d, status: 0x%x, out size: 0x%x\n",
1295
+ err, led_info.status, out_size);
1296
+ return -EIO;
1297
+ }
1298
+
1299
+ return 0;
1300
+}
1301
+
1302
+int hinic_set_led_status(struct hinic_hwdev *hwdev, u8 port,
1303
+ enum hinic_led_type type, enum hinic_led_mode mode)
1304
+{
1305
+ if (!hwdev)
1306
+ return -EINVAL;
1307
+
1308
+ return _set_led_status(hwdev, port, type, mode, 0);
1309
+}
1310
+
1311
+int hinic_reset_led_status(struct hinic_hwdev *hwdev, u8 port)
1312
+{
1313
+ int err;
1314
+
1315
+ if (!hwdev)
1316
+ return -EINVAL;
1317
+
1318
+ err = _set_led_status(hwdev, port, HINIC_LED_TYPE_INVALID,
1319
+ HINIC_LED_MODE_INVALID, 1);
1320
+ if (err)
1321
+ dev_err(&hwdev->hwif->pdev->dev,
1322
+ "Failed to reset led status\n");
1323
+
1324
+ return err;
1325
+}
1326
+
1327
+static bool hinic_if_sfp_absent(struct hinic_hwdev *hwdev)
1328
+{
1329
+ struct hinic_cmd_get_light_module_abs sfp_abs = {0};
1330
+ u16 out_size = sizeof(sfp_abs);
1331
+ u8 port_id = hwdev->port_id;
1332
+ int err;
1333
+
1334
+ sfp_abs.port_id = port_id;
1335
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_SFP_ABS,
1336
+ &sfp_abs, sizeof(sfp_abs), &sfp_abs,
1337
+ &out_size);
1338
+ if (sfp_abs.status || err || !out_size) {
1339
+ dev_err(&hwdev->hwif->pdev->dev,
1340
+ "Failed to get port%d sfp absent status, err: %d, status: 0x%x, out size: 0x%x\n",
1341
+ port_id, err, sfp_abs.status, out_size);
1342
+ return true;
1343
+ }
1344
+
1345
+ return ((sfp_abs.abs_status == 0) ? false : true);
1346
+}
1347
+
1348
+int hinic_get_sfp_eeprom(struct hinic_hwdev *hwdev, u8 *data, u16 *len)
1349
+{
1350
+ struct hinic_cmd_get_std_sfp_info sfp_info = {0};
1351
+ u16 out_size = sizeof(sfp_info);
1352
+ u8 port_id;
1353
+ int err;
1354
+
1355
+ if (!hwdev || !data || !len)
1356
+ return -EINVAL;
1357
+
1358
+ port_id = hwdev->port_id;
1359
+
1360
+ if (hinic_if_sfp_absent(hwdev))
1361
+ return -ENXIO;
1362
+
1363
+ sfp_info.port_id = port_id;
1364
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_STD_SFP_INFO,
1365
+ &sfp_info, sizeof(sfp_info), &sfp_info,
1366
+ &out_size);
1367
+ if (sfp_info.status || err || !out_size) {
1368
+ dev_err(&hwdev->hwif->pdev->dev,
1369
+ "Failed to get port%d sfp eeprom information, err: %d, status: 0x%x, out size: 0x%x\n",
1370
+ port_id, err, sfp_info.status, out_size);
1371
+ return -EIO;
1372
+ }
1373
+
1374
+ *len = min_t(u16, sfp_info.eeprom_len, STD_SFP_INFO_MAX_SIZE);
1375
+ memcpy(data, sfp_info.sfp_info, STD_SFP_INFO_MAX_SIZE);
1376
+
1377
+ return 0;
1378
+}
1379
+
1380
+int hinic_get_sfp_type(struct hinic_hwdev *hwdev, u8 *data0, u8 *data1)
1381
+{
1382
+ u8 sfp_data[STD_SFP_INFO_MAX_SIZE];
1383
+ u16 len;
1384
+ int err;
1385
+
1386
+ if (hinic_if_sfp_absent(hwdev))
1387
+ return -ENXIO;
1388
+
1389
+ err = hinic_get_sfp_eeprom(hwdev, sfp_data, &len);
1390
+ if (err)
1391
+ return err;
1392
+
1393
+ *data0 = sfp_data[0];
1394
+ *data1 = sfp_data[1];
1395
+
1396
+ return 0;
1397
+}