1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Huawei HiNIC PCI Express Linux driver
4 * Copyright(c) 2017 Huawei Technologies Co., Ltd
5 */
6
7#include <linux/types.h>
8#include <linux/netdevice.h>
9#include <linux/etherdevice.h>
10#include <linux/if_vlan.h>
11#include <linux/pci.h>
12#include <linux/device.h>
13#include <linux/errno.h>
14
15#include "hinic_hw_if.h"
16#include "hinic_hw_dev.h"
17#include "hinic_port.h"
18#include "hinic_dev.h"
19
20enum mac_op {
21 MAC_DEL,
22 MAC_SET,
23};
24
25/**
26 * change_mac - change(add or delete) mac address
27 * @nic_dev: nic device
28 * @addr: mac address
29 * @vlan_id: vlan number to set with the mac
30 * @op: add or delete the mac
31 *
32 * Return 0 - Success, negative - Failure
33 **/
34static int change_mac(struct hinic_dev *nic_dev, const u8 *addr,
35 u16 vlan_id, enum mac_op op)
36{
37 struct hinic_hwdev *hwdev = nic_dev->hwdev;
38 struct hinic_port_mac_cmd port_mac_cmd;
39 struct hinic_hwif *hwif = hwdev->hwif;
40 u16 out_size = sizeof(port_mac_cmd);
41 struct pci_dev *pdev = hwif->pdev;
42 enum hinic_port_cmd cmd;
43 int err;
44
45 if (op == MAC_SET)
46 cmd = HINIC_PORT_CMD_SET_MAC;
47 else
48 cmd = HINIC_PORT_CMD_DEL_MAC;
49
50 port_mac_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
51 port_mac_cmd.vlan_id = vlan_id;
52 memcpy(port_mac_cmd.mac, addr, ETH_ALEN);
53
54 err = hinic_port_msg_cmd(hwdev, cmd, buf_in: &port_mac_cmd,
55 in_size: sizeof(port_mac_cmd),
56 buf_out: &port_mac_cmd, out_size: &out_size);
57 if (err || out_size != sizeof(port_mac_cmd) ||
58 (port_mac_cmd.status &&
59 (port_mac_cmd.status != HINIC_PF_SET_VF_ALREADY || !HINIC_IS_VF(hwif)) &&
60 port_mac_cmd.status != HINIC_MGMT_STATUS_EXIST)) {
61 dev_err(&pdev->dev, "Failed to change MAC, err: %d, status: 0x%x, out size: 0x%x\n",
62 err, port_mac_cmd.status, out_size);
63 return -EFAULT;
64 }
65
66 if (port_mac_cmd.status == HINIC_PF_SET_VF_ALREADY) {
67 dev_warn(&pdev->dev, "PF has already set VF mac, ignore %s operation\n",
68 (op == MAC_SET) ? "set" : "del");
69 return HINIC_PF_SET_VF_ALREADY;
70 }
71
72 if (cmd == HINIC_PORT_CMD_SET_MAC && port_mac_cmd.status ==
73 HINIC_MGMT_STATUS_EXIST)
74 dev_warn(&pdev->dev, "MAC is repeated, ignore set operation\n");
75
76 return 0;
77}
78
79/**
80 * hinic_port_add_mac - add mac address
81 * @nic_dev: nic device
82 * @addr: mac address
83 * @vlan_id: vlan number to set with the mac
84 *
85 * Return 0 - Success, negative - Failure
86 **/
87int hinic_port_add_mac(struct hinic_dev *nic_dev,
88 const u8 *addr, u16 vlan_id)
89{
90 return change_mac(nic_dev, addr, vlan_id, op: MAC_SET);
91}
92
93/**
94 * hinic_port_del_mac - remove mac address
95 * @nic_dev: nic device
96 * @addr: mac address
97 * @vlan_id: vlan number that is connected to the mac
98 *
99 * Return 0 - Success, negative - Failure
100 **/
101int hinic_port_del_mac(struct hinic_dev *nic_dev, const u8 *addr,
102 u16 vlan_id)
103{
104 return change_mac(nic_dev, addr, vlan_id, op: MAC_DEL);
105}
106
107/**
108 * hinic_port_get_mac - get the mac address of the nic device
109 * @nic_dev: nic device
110 * @addr: returned mac address
111 *
112 * Return 0 - Success, negative - Failure
113 **/
114int hinic_port_get_mac(struct hinic_dev *nic_dev, u8 *addr)
115{
116 struct hinic_hwdev *hwdev = nic_dev->hwdev;
117 struct hinic_port_mac_cmd port_mac_cmd;
118 struct hinic_hwif *hwif = hwdev->hwif;
119 u16 out_size = sizeof(port_mac_cmd);
120 struct pci_dev *pdev = hwif->pdev;
121 int err;
122
123 port_mac_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
124
125 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_GET_MAC,
126 buf_in: &port_mac_cmd, in_size: sizeof(port_mac_cmd),
127 buf_out: &port_mac_cmd, out_size: &out_size);
128 if (err || out_size != sizeof(port_mac_cmd) || port_mac_cmd.status) {
129 dev_err(&pdev->dev, "Failed to get mac, err: %d, status: 0x%x, out size: 0x%x\n",
130 err, port_mac_cmd.status, out_size);
131 return -EFAULT;
132 }
133
134 memcpy(addr, port_mac_cmd.mac, ETH_ALEN);
135 return 0;
136}
137
138/**
139 * hinic_port_set_mtu - set mtu
140 * @nic_dev: nic device
141 * @new_mtu: new mtu
142 *
143 * Return 0 - Success, negative - Failure
144 **/
145int hinic_port_set_mtu(struct hinic_dev *nic_dev, int new_mtu)
146{
147 struct hinic_hwdev *hwdev = nic_dev->hwdev;
148 struct hinic_port_mtu_cmd port_mtu_cmd;
149 struct hinic_hwif *hwif = hwdev->hwif;
150 u16 out_size = sizeof(port_mtu_cmd);
151 struct pci_dev *pdev = hwif->pdev;
152 int err;
153
154 port_mtu_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
155 port_mtu_cmd.mtu = new_mtu;
156
157 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_CHANGE_MTU,
158 buf_in: &port_mtu_cmd, in_size: sizeof(port_mtu_cmd),
159 buf_out: &port_mtu_cmd, out_size: &out_size);
160 if (err || out_size != sizeof(port_mtu_cmd) || port_mtu_cmd.status) {
161 dev_err(&pdev->dev, "Failed to set mtu, err: %d, status: 0x%x, out size: 0x%x\n",
162 err, port_mtu_cmd.status, out_size);
163 return -EFAULT;
164 }
165
166 return 0;
167}
168
169/**
170 * hinic_port_add_vlan - add vlan to the nic device
171 * @nic_dev: nic device
172 * @vlan_id: the vlan number to add
173 *
174 * Return 0 - Success, negative - Failure
175 **/
176int hinic_port_add_vlan(struct hinic_dev *nic_dev, u16 vlan_id)
177{
178 struct hinic_hwdev *hwdev = nic_dev->hwdev;
179 struct hinic_port_vlan_cmd port_vlan_cmd;
180
181 port_vlan_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
182 port_vlan_cmd.vlan_id = vlan_id;
183
184 return hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_ADD_VLAN,
185 buf_in: &port_vlan_cmd, in_size: sizeof(port_vlan_cmd),
186 NULL, NULL);
187}
188
189/**
190 * hinic_port_del_vlan - delete vlan from the nic device
191 * @nic_dev: nic device
192 * @vlan_id: the vlan number to delete
193 *
194 * Return 0 - Success, negative - Failure
195 **/
196int hinic_port_del_vlan(struct hinic_dev *nic_dev, u16 vlan_id)
197{
198 struct hinic_hwdev *hwdev = nic_dev->hwdev;
199 struct hinic_port_vlan_cmd port_vlan_cmd;
200
201 port_vlan_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
202 port_vlan_cmd.vlan_id = vlan_id;
203
204 return hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_DEL_VLAN,
205 buf_in: &port_vlan_cmd, in_size: sizeof(port_vlan_cmd),
206 NULL, NULL);
207}
208
209/**
210 * hinic_port_set_rx_mode - set rx mode in the nic device
211 * @nic_dev: nic device
212 * @rx_mode: the rx mode to set
213 *
214 * Return 0 - Success, negative - Failure
215 **/
216int hinic_port_set_rx_mode(struct hinic_dev *nic_dev, u32 rx_mode)
217{
218 struct hinic_hwdev *hwdev = nic_dev->hwdev;
219 struct hinic_port_rx_mode_cmd rx_mode_cmd;
220
221 rx_mode_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
222 rx_mode_cmd.rx_mode = rx_mode;
223
224 return hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_SET_RX_MODE,
225 buf_in: &rx_mode_cmd, in_size: sizeof(rx_mode_cmd),
226 NULL, NULL);
227}
228
229/**
230 * hinic_port_link_state - get the link state
231 * @nic_dev: nic device
232 * @link_state: the returned link state
233 *
234 * Return 0 - Success, negative - Failure
235 **/
236int hinic_port_link_state(struct hinic_dev *nic_dev,
237 enum hinic_port_link_state *link_state)
238{
239 struct hinic_hwdev *hwdev = nic_dev->hwdev;
240 struct hinic_hwif *hwif = hwdev->hwif;
241 struct hinic_port_link_cmd link_cmd;
242 struct pci_dev *pdev = hwif->pdev;
243 u16 out_size = sizeof(link_cmd);
244 int err;
245
246 link_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
247
248 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_GET_LINK_STATE,
249 buf_in: &link_cmd, in_size: sizeof(link_cmd),
250 buf_out: &link_cmd, out_size: &out_size);
251 if (err || out_size != sizeof(link_cmd) || link_cmd.status) {
252 dev_err(&pdev->dev, "Failed to get link state, err: %d, status: 0x%x, out size: 0x%x\n",
253 err, link_cmd.status, out_size);
254 return -EINVAL;
255 }
256
257 *link_state = link_cmd.state;
258 return 0;
259}
260
261/**
262 * hinic_port_set_state - set port state
263 * @nic_dev: nic device
264 * @state: the state to set
265 *
266 * Return 0 - Success, negative - Failure
267 **/
268int hinic_port_set_state(struct hinic_dev *nic_dev, enum hinic_port_state state)
269{
270 struct hinic_hwdev *hwdev = nic_dev->hwdev;
271 struct hinic_port_state_cmd port_state;
272 struct hinic_hwif *hwif = hwdev->hwif;
273 struct pci_dev *pdev = hwif->pdev;
274 u16 out_size = sizeof(port_state);
275 int err;
276
277 if (HINIC_IS_VF(hwdev->hwif))
278 return 0;
279
280 port_state.state = state;
281
282 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_SET_PORT_STATE,
283 buf_in: &port_state, in_size: sizeof(port_state),
284 buf_out: &port_state, out_size: &out_size);
285 if (err || out_size != sizeof(port_state) || port_state.status) {
286 dev_err(&pdev->dev, "Failed to set port state, err: %d, status: 0x%x, out size: 0x%x\n",
287 err, port_state.status, out_size);
288 return -EFAULT;
289 }
290
291 return 0;
292}
293
294/**
295 * hinic_port_set_func_state- set func device state
296 * @nic_dev: nic device
297 * @state: the state to set
298 *
299 * Return 0 - Success, negative - Failure
300 **/
301int hinic_port_set_func_state(struct hinic_dev *nic_dev,
302 enum hinic_func_port_state state)
303{
304 struct hinic_port_func_state_cmd func_state;
305 struct hinic_hwdev *hwdev = nic_dev->hwdev;
306 struct hinic_hwif *hwif = hwdev->hwif;
307 struct pci_dev *pdev = hwif->pdev;
308 u16 out_size = sizeof(func_state);
309 int err;
310
311 func_state.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
312 func_state.state = state;
313
314 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_SET_FUNC_STATE,
315 buf_in: &func_state, in_size: sizeof(func_state),
316 buf_out: &func_state, out_size: &out_size);
317 if (err || out_size != sizeof(func_state) || func_state.status) {
318 dev_err(&pdev->dev, "Failed to set port func state, err: %d, status: 0x%x, out size: 0x%x\n",
319 err, func_state.status, out_size);
320 return -EFAULT;
321 }
322
323 return 0;
324}
325
326/**
327 * hinic_port_get_cap - get port capabilities
328 * @nic_dev: nic device
329 * @port_cap: returned port capabilities
330 *
331 * Return 0 - Success, negative - Failure
332 **/
333int hinic_port_get_cap(struct hinic_dev *nic_dev,
334 struct hinic_port_cap *port_cap)
335{
336 struct hinic_hwdev *hwdev = nic_dev->hwdev;
337 struct hinic_hwif *hwif = hwdev->hwif;
338 struct pci_dev *pdev = hwif->pdev;
339 u16 out_size = sizeof(*port_cap);
340 int err;
341
342 port_cap->func_idx = HINIC_HWIF_FUNC_IDX(hwif);
343
344 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_GET_CAP,
345 buf_in: port_cap, in_size: sizeof(*port_cap),
346 buf_out: port_cap, out_size: &out_size);
347 if (err || out_size != sizeof(*port_cap) || port_cap->status) {
348 dev_err(&pdev->dev,
349 "Failed to get port capabilities, err: %d, status: 0x%x, out size: 0x%x\n",
350 err, port_cap->status, out_size);
351 return -EIO;
352 }
353
354 return 0;
355}
356
357/**
358 * hinic_port_set_tso - set port tso configuration
359 * @nic_dev: nic device
360 * @state: the tso state to set
361 *
362 * Return 0 - Success, negative - Failure
363 **/
364int hinic_port_set_tso(struct hinic_dev *nic_dev, enum hinic_tso_state state)
365{
366 struct hinic_hwdev *hwdev = nic_dev->hwdev;
367 struct hinic_hwif *hwif = hwdev->hwif;
368 struct hinic_tso_config tso_cfg = {0};
369 struct pci_dev *pdev = hwif->pdev;
370 u16 out_size = sizeof(tso_cfg);
371 int err;
372
373 tso_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
374 tso_cfg.tso_en = state;
375
376 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_SET_TSO,
377 buf_in: &tso_cfg, in_size: sizeof(tso_cfg),
378 buf_out: &tso_cfg, out_size: &out_size);
379 if (err || out_size != sizeof(tso_cfg) || tso_cfg.status) {
380 dev_err(&pdev->dev,
381 "Failed to set port tso, err: %d, status: 0x%x, out size: 0x%x\n",
382 err, tso_cfg.status, out_size);
383 return -EIO;
384 }
385
386 return 0;
387}
388
389int hinic_set_rx_csum_offload(struct hinic_dev *nic_dev, u32 en)
390{
391 struct hinic_checksum_offload rx_csum_cfg = {0};
392 struct hinic_hwdev *hwdev = nic_dev->hwdev;
393 u16 out_size = sizeof(rx_csum_cfg);
394 struct hinic_hwif *hwif;
395 struct pci_dev *pdev;
396 int err;
397
398 if (!hwdev)
399 return -EINVAL;
400
401 hwif = hwdev->hwif;
402 pdev = hwif->pdev;
403 rx_csum_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
404 rx_csum_cfg.rx_csum_offload = en;
405
406 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_SET_RX_CSUM,
407 buf_in: &rx_csum_cfg, in_size: sizeof(rx_csum_cfg),
408 buf_out: &rx_csum_cfg, out_size: &out_size);
409 if (err || !out_size || rx_csum_cfg.status) {
410 dev_err(&pdev->dev,
411 "Failed to set rx csum offload, err: %d, status: 0x%x, out size: 0x%x\n",
412 err, rx_csum_cfg.status, out_size);
413 return -EIO;
414 }
415
416 return 0;
417}
418
419int hinic_set_rx_vlan_offload(struct hinic_dev *nic_dev, u8 en)
420{
421 struct hinic_hwdev *hwdev = nic_dev->hwdev;
422 struct hinic_vlan_cfg vlan_cfg;
423 struct hinic_hwif *hwif;
424 struct pci_dev *pdev;
425 u16 out_size;
426 int err;
427
428 if (!hwdev)
429 return -EINVAL;
430
431 out_size = sizeof(vlan_cfg);
432 hwif = hwdev->hwif;
433 pdev = hwif->pdev;
434 vlan_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
435 vlan_cfg.vlan_rx_offload = en;
436
437 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_SET_RX_VLAN_OFFLOAD,
438 buf_in: &vlan_cfg, in_size: sizeof(vlan_cfg),
439 buf_out: &vlan_cfg, out_size: &out_size);
440 if (err || !out_size || vlan_cfg.status) {
441 dev_err(&pdev->dev,
442 "Failed to set rx vlan offload, err: %d, status: 0x%x, out size: 0x%x\n",
443 err, vlan_cfg.status, out_size);
444 return -EINVAL;
445 }
446
447 return 0;
448}
449
450int hinic_set_vlan_fliter(struct hinic_dev *nic_dev, u32 en)
451{
452 struct hinic_hwdev *hwdev = nic_dev->hwdev;
453 struct hinic_hwif *hwif = hwdev->hwif;
454 struct pci_dev *pdev = hwif->pdev;
455 struct hinic_vlan_filter vlan_filter;
456 u16 out_size = sizeof(vlan_filter);
457 int err;
458
459 vlan_filter.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
460 vlan_filter.enable = en;
461
462 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_SET_VLAN_FILTER,
463 buf_in: &vlan_filter, in_size: sizeof(vlan_filter),
464 buf_out: &vlan_filter, out_size: &out_size);
465 if (vlan_filter.status == HINIC_MGMT_CMD_UNSUPPORTED) {
466 err = HINIC_MGMT_CMD_UNSUPPORTED;
467 } else if ((err == HINIC_MBOX_VF_CMD_ERROR) &&
468 HINIC_IS_VF(hwif)) {
469 err = HINIC_MGMT_CMD_UNSUPPORTED;
470 } else if (err || !out_size || vlan_filter.status) {
471 dev_err(&pdev->dev,
472 "Failed to set vlan fliter, err: %d, status: 0x%x, out size: 0x%x\n",
473 err, vlan_filter.status, out_size);
474 err = -EINVAL;
475 }
476
477 return err;
478}
479
480int hinic_set_max_qnum(struct hinic_dev *nic_dev, u8 num_rqs)
481{
482 struct hinic_hwdev *hwdev = nic_dev->hwdev;
483 struct hinic_hwif *hwif = hwdev->hwif;
484 struct hinic_rq_num rq_num = { 0 };
485 struct pci_dev *pdev = hwif->pdev;
486 u16 out_size = sizeof(rq_num);
487 int err;
488
489 rq_num.func_id = HINIC_HWIF_FUNC_IDX(hwif);
490 rq_num.num_rqs = num_rqs;
491 rq_num.rq_depth = ilog2(nic_dev->rq_depth);
492
493 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_SET_RQ_IQ_MAP,
494 buf_in: &rq_num, in_size: sizeof(rq_num),
495 buf_out: &rq_num, out_size: &out_size);
496 if (err || !out_size || rq_num.status) {
497 dev_err(&pdev->dev,
498 "Failed to set rxq number, err: %d, status: 0x%x, out size: 0x%x\n",
499 err, rq_num.status, out_size);
500 return -EIO;
501 }
502
503 return 0;
504}
505
506static int hinic_set_rx_lro(struct hinic_dev *nic_dev, u8 ipv4_en, u8 ipv6_en,
507 u8 max_wqe_num)
508{
509 struct hinic_hwdev *hwdev = nic_dev->hwdev;
510 struct hinic_lro_config lro_cfg = { 0 };
511 struct hinic_hwif *hwif = hwdev->hwif;
512 struct pci_dev *pdev = hwif->pdev;
513 u16 out_size = sizeof(lro_cfg);
514 int err;
515
516 lro_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
517 lro_cfg.lro_ipv4_en = ipv4_en;
518 lro_cfg.lro_ipv6_en = ipv6_en;
519 lro_cfg.lro_max_wqe_num = max_wqe_num;
520
521 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_SET_LRO,
522 buf_in: &lro_cfg, in_size: sizeof(lro_cfg),
523 buf_out: &lro_cfg, out_size: &out_size);
524 if (err || !out_size || lro_cfg.status) {
525 dev_err(&pdev->dev,
526 "Failed to set lro offload, err: %d, status: 0x%x, out size: 0x%x\n",
527 err, lro_cfg.status, out_size);
528 return -EIO;
529 }
530
531 return 0;
532}
533
534static int hinic_set_rx_lro_timer(struct hinic_dev *nic_dev, u32 timer_value)
535{
536 struct hinic_hwdev *hwdev = nic_dev->hwdev;
537 struct hinic_lro_timer lro_timer = { 0 };
538 struct hinic_hwif *hwif = hwdev->hwif;
539 struct pci_dev *pdev = hwif->pdev;
540 u16 out_size = sizeof(lro_timer);
541 int err;
542
543 lro_timer.status = 0;
544 lro_timer.type = 0;
545 lro_timer.enable = 1;
546 lro_timer.timer = timer_value;
547
548 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_SET_LRO_TIMER,
549 buf_in: &lro_timer, in_size: sizeof(lro_timer),
550 buf_out: &lro_timer, out_size: &out_size);
551 if (lro_timer.status == 0xFF) {
552 /* For this case, we think status (0xFF) is OK */
553 lro_timer.status = 0;
554 dev_dbg(&pdev->dev,
555 "Set lro timer not supported by the current FW version, it will be 1ms default\n");
556 }
557
558 if (err || !out_size || lro_timer.status) {
559 dev_err(&pdev->dev,
560 "Failed to set lro timer, err: %d, status: 0x%x, out size: 0x%x\n",
561 err, lro_timer.status, out_size);
562
563 return -EIO;
564 }
565
566 return 0;
567}
568
569int hinic_set_rx_lro_state(struct hinic_dev *nic_dev, u8 lro_en,
570 u32 lro_timer, u32 wqe_num)
571{
572 struct hinic_hwdev *hwdev = nic_dev->hwdev;
573 u8 ipv4_en;
574 u8 ipv6_en;
575 int err;
576
577 if (!hwdev)
578 return -EINVAL;
579
580 ipv4_en = lro_en ? 1 : 0;
581 ipv6_en = lro_en ? 1 : 0;
582
583 err = hinic_set_rx_lro(nic_dev, ipv4_en, ipv6_en, max_wqe_num: (u8)wqe_num);
584 if (err)
585 return err;
586
587 if (HINIC_IS_VF(nic_dev->hwdev->hwif))
588 return 0;
589
590 err = hinic_set_rx_lro_timer(nic_dev, timer_value: lro_timer);
591 if (err)
592 return err;
593
594 return 0;
595}
596
597int hinic_rss_set_indir_tbl(struct hinic_dev *nic_dev, u32 tmpl_idx,
598 const u32 *indir_table)
599{
600 struct hinic_rss_indirect_tbl *indir_tbl;
601 struct hinic_func_to_io *func_to_io;
602 struct hinic_cmdq_buf cmd_buf;
603 struct hinic_hwdev *hwdev;
604 struct hinic_hwif *hwif;
605 struct pci_dev *pdev;
606 u32 indir_size;
607 u64 out_param;
608 int err, i;
609 u32 *temp;
610
611 hwdev = nic_dev->hwdev;
612 func_to_io = &hwdev->func_to_io;
613 hwif = hwdev->hwif;
614 pdev = hwif->pdev;
615
616 err = hinic_alloc_cmdq_buf(cmdqs: &func_to_io->cmdqs, cmdq_buf: &cmd_buf);
617 if (err) {
618 dev_err(&pdev->dev, "Failed to allocate cmdq buf\n");
619 return err;
620 }
621
622 cmd_buf.size = sizeof(*indir_tbl);
623
624 indir_tbl = cmd_buf.buf;
625 indir_tbl->group_index = cpu_to_be32(tmpl_idx);
626
627 for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++) {
628 indir_tbl->entry[i] = indir_table[i];
629
630 if (0x3 == (i & 0x3)) {
631 temp = (u32 *)&indir_tbl->entry[i - 3];
632 *temp = cpu_to_be32(*temp);
633 }
634 }
635
636 /* cfg the rss indirect table by command queue */
637 indir_size = HINIC_RSS_INDIR_SIZE / 2;
638 indir_tbl->offset = 0;
639 indir_tbl->size = cpu_to_be32(indir_size);
640
641 err = hinic_cmdq_direct_resp(cmdqs: &func_to_io->cmdqs, mod: HINIC_MOD_L2NIC,
642 cmd: HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
643 buf_in: &cmd_buf, out_param: &out_param);
644 if (err || out_param != 0) {
645 dev_err(&pdev->dev, "Failed to set rss indir table\n");
646 err = -EFAULT;
647 goto free_buf;
648 }
649
650 indir_tbl->offset = cpu_to_be32(indir_size);
651 indir_tbl->size = cpu_to_be32(indir_size);
652 memcpy(&indir_tbl->entry[0], &indir_tbl->entry[indir_size], indir_size);
653
654 err = hinic_cmdq_direct_resp(cmdqs: &func_to_io->cmdqs, mod: HINIC_MOD_L2NIC,
655 cmd: HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
656 buf_in: &cmd_buf, out_param: &out_param);
657 if (err || out_param != 0) {
658 dev_err(&pdev->dev, "Failed to set rss indir table\n");
659 err = -EFAULT;
660 }
661
662free_buf:
663 hinic_free_cmdq_buf(cmdqs: &func_to_io->cmdqs, cmdq_buf: &cmd_buf);
664
665 return err;
666}
667
668int hinic_rss_get_indir_tbl(struct hinic_dev *nic_dev, u32 tmpl_idx,
669 u32 *indir_table)
670{
671 struct hinic_rss_indir_table rss_cfg = { 0 };
672 struct hinic_hwdev *hwdev = nic_dev->hwdev;
673 struct hinic_hwif *hwif = hwdev->hwif;
674 struct pci_dev *pdev = hwif->pdev;
675 u16 out_size = sizeof(rss_cfg);
676 int err = 0, i;
677
678 rss_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
679 rss_cfg.template_id = tmpl_idx;
680
681 err = hinic_port_msg_cmd(hwdev,
682 cmd: HINIC_PORT_CMD_GET_RSS_TEMPLATE_INDIR_TBL,
683 buf_in: &rss_cfg, in_size: sizeof(rss_cfg), buf_out: &rss_cfg,
684 out_size: &out_size);
685 if (err || !out_size || rss_cfg.status) {
686 dev_err(&pdev->dev, "Failed to get indir table, err: %d, status: 0x%x, out size: 0x%x\n",
687 err, rss_cfg.status, out_size);
688 return -EINVAL;
689 }
690
691 hinic_be32_to_cpu(data: rss_cfg.indir, HINIC_RSS_INDIR_SIZE);
692 for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++)
693 indir_table[i] = rss_cfg.indir[i];
694
695 return 0;
696}
697
698int hinic_set_rss_type(struct hinic_dev *nic_dev, u32 tmpl_idx,
699 struct hinic_rss_type rss_type)
700{
701 struct hinic_rss_context_tbl *ctx_tbl;
702 struct hinic_func_to_io *func_to_io;
703 struct hinic_cmdq_buf cmd_buf;
704 struct hinic_hwdev *hwdev;
705 struct hinic_hwif *hwif;
706 struct pci_dev *pdev;
707 u64 out_param;
708 u32 ctx = 0;
709 int err;
710
711 hwdev = nic_dev->hwdev;
712 func_to_io = &hwdev->func_to_io;
713 hwif = hwdev->hwif;
714 pdev = hwif->pdev;
715
716 err = hinic_alloc_cmdq_buf(cmdqs: &func_to_io->cmdqs, cmdq_buf: &cmd_buf);
717 if (err) {
718 dev_err(&pdev->dev, "Failed to allocate cmd buf\n");
719 return -ENOMEM;
720 }
721
722 ctx |= HINIC_RSS_TYPE_SET(1, VALID) |
723 HINIC_RSS_TYPE_SET(rss_type.ipv4, IPV4) |
724 HINIC_RSS_TYPE_SET(rss_type.ipv6, IPV6) |
725 HINIC_RSS_TYPE_SET(rss_type.ipv6_ext, IPV6_EXT) |
726 HINIC_RSS_TYPE_SET(rss_type.tcp_ipv4, TCP_IPV4) |
727 HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6, TCP_IPV6) |
728 HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6_ext, TCP_IPV6_EXT) |
729 HINIC_RSS_TYPE_SET(rss_type.udp_ipv4, UDP_IPV4) |
730 HINIC_RSS_TYPE_SET(rss_type.udp_ipv6, UDP_IPV6);
731
732 cmd_buf.size = sizeof(struct hinic_rss_context_tbl);
733
734 ctx_tbl = (struct hinic_rss_context_tbl *)cmd_buf.buf;
735 ctx_tbl->group_index = cpu_to_be32(tmpl_idx);
736 ctx_tbl->offset = 0;
737 ctx_tbl->size = sizeof(u32);
738 ctx_tbl->size = cpu_to_be32(ctx_tbl->size);
739 ctx_tbl->rsvd = 0;
740 ctx_tbl->ctx = cpu_to_be32(ctx);
741
742 /* cfg the rss context table by command queue */
743 err = hinic_cmdq_direct_resp(cmdqs: &func_to_io->cmdqs, mod: HINIC_MOD_L2NIC,
744 cmd: HINIC_UCODE_CMD_SET_RSS_CONTEXT_TABLE,
745 buf_in: &cmd_buf, out_param: &out_param);
746
747 hinic_free_cmdq_buf(cmdqs: &func_to_io->cmdqs, cmdq_buf: &cmd_buf);
748
749 if (err || out_param != 0) {
750 dev_err(&pdev->dev, "Failed to set rss context table, err: %d\n",
751 err);
752 return -EFAULT;
753 }
754
755 return 0;
756}
757
758int hinic_get_rss_type(struct hinic_dev *nic_dev, u32 tmpl_idx,
759 struct hinic_rss_type *rss_type)
760{
761 struct hinic_rss_context_table ctx_tbl = { 0 };
762 struct hinic_hwdev *hwdev = nic_dev->hwdev;
763 u16 out_size = sizeof(ctx_tbl);
764 struct hinic_hwif *hwif;
765 struct pci_dev *pdev;
766 int err;
767
768 if (!hwdev || !rss_type)
769 return -EINVAL;
770
771 hwif = hwdev->hwif;
772 pdev = hwif->pdev;
773
774 ctx_tbl.func_id = HINIC_HWIF_FUNC_IDX(hwif);
775 ctx_tbl.template_id = tmpl_idx;
776
777 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_GET_RSS_CTX_TBL,
778 buf_in: &ctx_tbl, in_size: sizeof(ctx_tbl),
779 buf_out: &ctx_tbl, out_size: &out_size);
780 if (err || !out_size || ctx_tbl.status) {
781 dev_err(&pdev->dev, "Failed to get hash type, err: %d, status: 0x%x, out size: 0x%x\n",
782 err, ctx_tbl.status, out_size);
783 return -EINVAL;
784 }
785
786 rss_type->ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV4);
787 rss_type->ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6);
788 rss_type->ipv6_ext = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6_EXT);
789 rss_type->tcp_ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV4);
790 rss_type->tcp_ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6);
791 rss_type->tcp_ipv6_ext = HINIC_RSS_TYPE_GET(ctx_tbl.context,
792 TCP_IPV6_EXT);
793 rss_type->udp_ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV4);
794 rss_type->udp_ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV6);
795
796 return 0;
797}
798
799int hinic_rss_set_template_tbl(struct hinic_dev *nic_dev, u32 template_id,
800 const u8 *temp)
801{
802 struct hinic_hwdev *hwdev = nic_dev->hwdev;
803 struct hinic_hwif *hwif = hwdev->hwif;
804 struct hinic_rss_key rss_key = { 0 };
805 struct pci_dev *pdev = hwif->pdev;
806 u16 out_size = sizeof(rss_key);
807 int err;
808
809 rss_key.func_id = HINIC_HWIF_FUNC_IDX(hwif);
810 rss_key.template_id = template_id;
811 memcpy(rss_key.key, temp, HINIC_RSS_KEY_SIZE);
812
813 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_SET_RSS_TEMPLATE_TBL,
814 buf_in: &rss_key, in_size: sizeof(rss_key),
815 buf_out: &rss_key, out_size: &out_size);
816 if (err || !out_size || rss_key.status) {
817 dev_err(&pdev->dev,
818 "Failed to set rss hash key, err: %d, status: 0x%x, out size: 0x%x\n",
819 err, rss_key.status, out_size);
820 return -EINVAL;
821 }
822
823 return 0;
824}
825
826int hinic_rss_get_template_tbl(struct hinic_dev *nic_dev, u32 tmpl_idx,
827 u8 *temp)
828{
829 struct hinic_rss_template_key temp_key = { 0 };
830 struct hinic_hwdev *hwdev = nic_dev->hwdev;
831 u16 out_size = sizeof(temp_key);
832 struct hinic_hwif *hwif;
833 struct pci_dev *pdev;
834 int err;
835
836 if (!hwdev || !temp)
837 return -EINVAL;
838
839 hwif = hwdev->hwif;
840 pdev = hwif->pdev;
841
842 temp_key.func_id = HINIC_HWIF_FUNC_IDX(hwif);
843 temp_key.template_id = tmpl_idx;
844
845 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_GET_RSS_TEMPLATE_TBL,
846 buf_in: &temp_key, in_size: sizeof(temp_key),
847 buf_out: &temp_key, out_size: &out_size);
848 if (err || !out_size || temp_key.status) {
849 dev_err(&pdev->dev, "Failed to set hash key, err: %d, status: 0x%x, out size: 0x%x\n",
850 err, temp_key.status, out_size);
851 return -EINVAL;
852 }
853
854 memcpy(temp, temp_key.key, HINIC_RSS_KEY_SIZE);
855
856 return 0;
857}
858
859int hinic_rss_set_hash_engine(struct hinic_dev *nic_dev, u8 template_id,
860 u8 type)
861{
862 struct hinic_rss_engine_type rss_engine = { 0 };
863 struct hinic_hwdev *hwdev = nic_dev->hwdev;
864 struct hinic_hwif *hwif = hwdev->hwif;
865 struct pci_dev *pdev = hwif->pdev;
866 u16 out_size = sizeof(rss_engine);
867 int err;
868
869 rss_engine.func_id = HINIC_HWIF_FUNC_IDX(hwif);
870 rss_engine.hash_engine = type;
871 rss_engine.template_id = template_id;
872
873 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_SET_RSS_HASH_ENGINE,
874 buf_in: &rss_engine, in_size: sizeof(rss_engine),
875 buf_out: &rss_engine, out_size: &out_size);
876 if (err || !out_size || rss_engine.status) {
877 dev_err(&pdev->dev,
878 "Failed to set hash engine, err: %d, status: 0x%x, out size: 0x%x\n",
879 err, rss_engine.status, out_size);
880 return -EINVAL;
881 }
882
883 return 0;
884}
885
886int hinic_rss_get_hash_engine(struct hinic_dev *nic_dev, u8 tmpl_idx, u8 *type)
887{
888 struct hinic_rss_engine_type hash_type = { 0 };
889 struct hinic_hwdev *hwdev = nic_dev->hwdev;
890 u16 out_size = sizeof(hash_type);
891 struct hinic_hwif *hwif;
892 struct pci_dev *pdev;
893 int err;
894
895 if (!hwdev || !type)
896 return -EINVAL;
897
898 hwif = hwdev->hwif;
899 pdev = hwif->pdev;
900
901 hash_type.func_id = HINIC_HWIF_FUNC_IDX(hwif);
902 hash_type.template_id = tmpl_idx;
903
904 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_GET_RSS_HASH_ENGINE,
905 buf_in: &hash_type, in_size: sizeof(hash_type),
906 buf_out: &hash_type, out_size: &out_size);
907 if (err || !out_size || hash_type.status) {
908 dev_err(&pdev->dev, "Failed to get hash engine, err: %d, status: 0x%x, out size: 0x%x\n",
909 err, hash_type.status, out_size);
910 return -EINVAL;
911 }
912
913 *type = hash_type.hash_engine;
914 return 0;
915}
916
917int hinic_rss_cfg(struct hinic_dev *nic_dev, u8 rss_en, u8 template_id)
918{
919 struct hinic_hwdev *hwdev = nic_dev->hwdev;
920 struct hinic_rss_config rss_cfg = { 0 };
921 struct hinic_hwif *hwif = hwdev->hwif;
922 struct pci_dev *pdev = hwif->pdev;
923 u16 out_size = sizeof(rss_cfg);
924 int err;
925
926 rss_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
927 rss_cfg.rss_en = rss_en;
928 rss_cfg.template_id = template_id;
929 rss_cfg.rq_priority_number = 0;
930
931 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_RSS_CFG,
932 buf_in: &rss_cfg, in_size: sizeof(rss_cfg),
933 buf_out: &rss_cfg, out_size: &out_size);
934 if (err || !out_size || rss_cfg.status) {
935 dev_err(&pdev->dev,
936 "Failed to set rss cfg, err: %d, status: 0x%x, out size: 0x%x\n",
937 err, rss_cfg.status, out_size);
938 return -EINVAL;
939 }
940
941 return 0;
942}
943
944int hinic_rss_template_alloc(struct hinic_dev *nic_dev, u8 *tmpl_idx)
945{
946 struct hinic_rss_template_mgmt template_mgmt = { 0 };
947 struct hinic_hwdev *hwdev = nic_dev->hwdev;
948 struct hinic_hwif *hwif = hwdev->hwif;
949 u16 out_size = sizeof(template_mgmt);
950 struct pci_dev *pdev = hwif->pdev;
951 int err;
952
953 template_mgmt.func_id = HINIC_HWIF_FUNC_IDX(hwif);
954 template_mgmt.cmd = NIC_RSS_CMD_TEMP_ALLOC;
955
956 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_RSS_TEMP_MGR,
957 buf_in: &template_mgmt, in_size: sizeof(template_mgmt),
958 buf_out: &template_mgmt, out_size: &out_size);
959 if (err || !out_size || template_mgmt.status) {
960 dev_err(&pdev->dev, "Failed to alloc rss template, err: %d, status: 0x%x, out size: 0x%x\n",
961 err, template_mgmt.status, out_size);
962 return -EINVAL;
963 }
964
965 *tmpl_idx = template_mgmt.template_id;
966
967 return 0;
968}
969
970int hinic_rss_template_free(struct hinic_dev *nic_dev, u8 tmpl_idx)
971{
972 struct hinic_rss_template_mgmt template_mgmt = { 0 };
973 struct hinic_hwdev *hwdev = nic_dev->hwdev;
974 struct hinic_hwif *hwif = hwdev->hwif;
975 u16 out_size = sizeof(template_mgmt);
976 struct pci_dev *pdev = hwif->pdev;
977 int err;
978
979 template_mgmt.func_id = HINIC_HWIF_FUNC_IDX(hwif);
980 template_mgmt.template_id = tmpl_idx;
981 template_mgmt.cmd = NIC_RSS_CMD_TEMP_FREE;
982
983 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_RSS_TEMP_MGR,
984 buf_in: &template_mgmt, in_size: sizeof(template_mgmt),
985 buf_out: &template_mgmt, out_size: &out_size);
986 if (err || !out_size || template_mgmt.status) {
987 dev_err(&pdev->dev, "Failed to free rss template, err: %d, status: 0x%x, out size: 0x%x\n",
988 err, template_mgmt.status, out_size);
989 return -EINVAL;
990 }
991
992 return 0;
993}
994
995int hinic_get_vport_stats(struct hinic_dev *nic_dev,
996 struct hinic_vport_stats *stats)
997{
998 struct hinic_cmd_vport_stats vport_stats = { 0 };
999 struct hinic_port_stats_info stats_info = { 0 };
1000 struct hinic_hwdev *hwdev = nic_dev->hwdev;
1001 struct hinic_hwif *hwif = hwdev->hwif;
1002 u16 out_size = sizeof(vport_stats);
1003 struct pci_dev *pdev = hwif->pdev;
1004 int err;
1005
1006 stats_info.stats_version = HINIC_PORT_STATS_VERSION;
1007 stats_info.func_id = HINIC_HWIF_FUNC_IDX(hwif);
1008 stats_info.stats_size = sizeof(vport_stats);
1009
1010 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_GET_VPORT_STAT,
1011 buf_in: &stats_info, in_size: sizeof(stats_info),
1012 buf_out: &vport_stats, out_size: &out_size);
1013 if (err || !out_size || vport_stats.status) {
1014 dev_err(&pdev->dev,
1015 "Failed to get function statistics, err: %d, status: 0x%x, out size: 0x%x\n",
1016 err, vport_stats.status, out_size);
1017 return -EFAULT;
1018 }
1019
1020 memcpy(stats, &vport_stats.stats, sizeof(*stats));
1021 return 0;
1022}
1023
1024int hinic_get_phy_port_stats(struct hinic_dev *nic_dev,
1025 struct hinic_phy_port_stats *stats)
1026{
1027 struct hinic_port_stats_info stats_info = { 0 };
1028 struct hinic_hwdev *hwdev = nic_dev->hwdev;
1029 struct hinic_hwif *hwif = hwdev->hwif;
1030 struct hinic_port_stats *port_stats;
1031 u16 out_size = sizeof(*port_stats);
1032 struct pci_dev *pdev = hwif->pdev;
1033 int err;
1034
1035 port_stats = kzalloc(size: sizeof(*port_stats), GFP_KERNEL);
1036 if (!port_stats)
1037 return -ENOMEM;
1038
1039 stats_info.stats_version = HINIC_PORT_STATS_VERSION;
1040 stats_info.stats_size = sizeof(*port_stats);
1041
1042 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_GET_PORT_STATISTICS,
1043 buf_in: &stats_info, in_size: sizeof(stats_info),
1044 buf_out: port_stats, out_size: &out_size);
1045 if (err || !out_size || port_stats->status) {
1046 dev_err(&pdev->dev,
1047 "Failed to get port statistics, err: %d, status: 0x%x, out size: 0x%x\n",
1048 err, port_stats->status, out_size);
1049 err = -EINVAL;
1050 goto out;
1051 }
1052
1053 memcpy(stats, &port_stats->stats, sizeof(*stats));
1054
1055out:
1056 kfree(objp: port_stats);
1057
1058 return err;
1059}
1060
1061int hinic_get_mgmt_version(struct hinic_dev *nic_dev, u8 *mgmt_ver)
1062{
1063 struct hinic_hwdev *hwdev = nic_dev->hwdev;
1064 struct hinic_version_info up_ver = {0};
1065 u16 out_size = sizeof(up_ver);
1066 struct hinic_hwif *hwif;
1067 struct pci_dev *pdev;
1068 int err;
1069
1070 if (!hwdev)
1071 return -EINVAL;
1072
1073 hwif = hwdev->hwif;
1074 pdev = hwif->pdev;
1075
1076 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_GET_MGMT_VERSION,
1077 buf_in: &up_ver, in_size: sizeof(up_ver), buf_out: &up_ver,
1078 out_size: &out_size);
1079 if (err || !out_size || up_ver.status) {
1080 dev_err(&pdev->dev,
1081 "Failed to get mgmt version, err: %d, status: 0x%x, out size: 0x%x\n",
1082 err, up_ver.status, out_size);
1083 return -EINVAL;
1084 }
1085
1086 snprintf(buf: mgmt_ver, HINIC_MGMT_VERSION_MAX_LEN, fmt: "%s", up_ver.ver);
1087
1088 return 0;
1089}
1090
1091int hinic_get_link_mode(struct hinic_hwdev *hwdev,
1092 struct hinic_link_mode_cmd *link_mode)
1093{
1094 u16 out_size;
1095 int err;
1096
1097 if (!hwdev || !link_mode)
1098 return -EINVAL;
1099
1100 link_mode->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
1101 out_size = sizeof(*link_mode);
1102
1103 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_GET_LINK_MODE,
1104 buf_in: link_mode, in_size: sizeof(*link_mode),
1105 buf_out: link_mode, out_size: &out_size);
1106 if (err || !out_size || link_mode->status) {
1107 dev_err(&hwdev->hwif->pdev->dev,
1108 "Failed to get link mode, err: %d, status: 0x%x, out size: 0x%x\n",
1109 err, link_mode->status, out_size);
1110 return -EIO;
1111 }
1112
1113 return 0;
1114}
1115
1116int hinic_set_autoneg(struct hinic_hwdev *hwdev, bool enable)
1117{
1118 struct hinic_set_autoneg_cmd autoneg = {0};
1119 u16 out_size = sizeof(autoneg);
1120 int err;
1121
1122 if (!hwdev)
1123 return -EINVAL;
1124
1125 autoneg.func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
1126 autoneg.enable = enable;
1127
1128 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_SET_AUTONEG,
1129 buf_in: &autoneg, in_size: sizeof(autoneg),
1130 buf_out: &autoneg, out_size: &out_size);
1131 if (err || !out_size || autoneg.status) {
1132 dev_err(&hwdev->hwif->pdev->dev, "Failed to %s autoneg, err: %d, status: 0x%x, out size: 0x%x\n",
1133 enable ? "enable" : "disable", err, autoneg.status,
1134 out_size);
1135 return -EIO;
1136 }
1137
1138 return 0;
1139}
1140
1141int hinic_set_speed(struct hinic_hwdev *hwdev, enum nic_speed_level speed)
1142{
1143 struct hinic_speed_cmd speed_info = {0};
1144 u16 out_size = sizeof(speed_info);
1145 int err;
1146
1147 if (!hwdev)
1148 return -EINVAL;
1149
1150 speed_info.func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
1151 speed_info.speed = speed;
1152
1153 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_SET_SPEED,
1154 buf_in: &speed_info, in_size: sizeof(speed_info),
1155 buf_out: &speed_info, out_size: &out_size);
1156 if (err || !out_size || speed_info.status) {
1157 dev_err(&hwdev->hwif->pdev->dev,
1158 "Failed to set speed, err: %d, status: 0x%x, out size: 0x%x\n",
1159 err, speed_info.status, out_size);
1160 return -EIO;
1161 }
1162
1163 return 0;
1164}
1165
1166int hinic_set_link_settings(struct hinic_hwdev *hwdev,
1167 struct hinic_link_ksettings_info *info)
1168{
1169 u16 out_size = sizeof(*info);
1170 int err;
1171
1172 err = hinic_hilink_msg_cmd(hwdev, cmd: HINIC_HILINK_CMD_SET_LINK_SETTINGS,
1173 buf_in: info, in_size: sizeof(*info), buf_out: info, out_size: &out_size);
1174 if ((info->status != HINIC_MGMT_CMD_UNSUPPORTED &&
1175 info->status) || err || !out_size) {
1176 dev_err(&hwdev->hwif->pdev->dev,
1177 "Failed to set link settings, err: %d, status: 0x%x, out size: 0x%x\n",
1178 err, info->status, out_size);
1179 return -EFAULT;
1180 }
1181
1182 return info->status;
1183}
1184
1185int hinic_get_hw_pause_info(struct hinic_hwdev *hwdev,
1186 struct hinic_pause_config *pause_info)
1187{
1188 u16 out_size = sizeof(*pause_info);
1189 int err;
1190
1191 pause_info->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
1192
1193 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_GET_PAUSE_INFO,
1194 buf_in: pause_info, in_size: sizeof(*pause_info),
1195 buf_out: pause_info, out_size: &out_size);
1196 if (err || !out_size || pause_info->status) {
1197 dev_err(&hwdev->hwif->pdev->dev, "Failed to get pause info, err: %d, status: 0x%x, out size: 0x%x\n",
1198 err, pause_info->status, out_size);
1199 return -EIO;
1200 }
1201
1202 return 0;
1203}
1204
1205int hinic_set_hw_pause_info(struct hinic_hwdev *hwdev,
1206 struct hinic_pause_config *pause_info)
1207{
1208 u16 out_size = sizeof(*pause_info);
1209 int err;
1210
1211 pause_info->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
1212
1213 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_SET_PAUSE_INFO,
1214 buf_in: pause_info, in_size: sizeof(*pause_info),
1215 buf_out: pause_info, out_size: &out_size);
1216 if (err || !out_size || pause_info->status) {
1217 dev_err(&hwdev->hwif->pdev->dev, "Failed to set pause info, err: %d, status: 0x%x, out size: 0x%x\n",
1218 err, pause_info->status, out_size);
1219 return -EIO;
1220 }
1221
1222 return 0;
1223}
1224
1225int hinic_dcb_set_pfc(struct hinic_hwdev *hwdev, u8 pfc_en, u8 pfc_bitmap)
1226{
1227 struct hinic_nic_cfg *nic_cfg = &hwdev->func_to_io.nic_cfg;
1228 struct hinic_set_pfc pfc = {0};
1229 u16 out_size = sizeof(pfc);
1230 int err;
1231
1232 if (HINIC_IS_VF(hwdev->hwif))
1233 return 0;
1234
1235 mutex_lock(&nic_cfg->cfg_mutex);
1236
1237 pfc.func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
1238 pfc.pfc_bitmap = pfc_bitmap;
1239 pfc.pfc_en = pfc_en;
1240
1241 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_SET_PFC,
1242 buf_in: &pfc, in_size: sizeof(pfc), buf_out: &pfc, out_size: &out_size);
1243 if (err || pfc.status || !out_size) {
1244 dev_err(&hwdev->hwif->pdev->dev, "Failed to %s pfc, err: %d, status: 0x%x, out size: 0x%x\n",
1245 pfc_en ? "enable" : "disable", err, pfc.status,
1246 out_size);
1247 mutex_unlock(lock: &nic_cfg->cfg_mutex);
1248 return -EIO;
1249 }
1250
1251 /* pause settings is opposite from pfc */
1252 nic_cfg->rx_pause = pfc_en ? 0 : 1;
1253 nic_cfg->tx_pause = pfc_en ? 0 : 1;
1254
1255 mutex_unlock(lock: &nic_cfg->cfg_mutex);
1256
1257 return 0;
1258}
1259
1260int hinic_set_loopback_mode(struct hinic_hwdev *hwdev, u32 mode, u32 enable)
1261{
1262 struct hinic_port_loopback lb = {0};
1263 u16 out_size = sizeof(lb);
1264 int err;
1265
1266 lb.mode = mode;
1267 lb.en = enable;
1268
1269 if (mode < LOOP_MODE_MIN || mode > LOOP_MODE_MAX) {
1270 dev_err(&hwdev->hwif->pdev->dev,
1271 "Invalid loopback mode %d to set\n", mode);
1272 return -EINVAL;
1273 }
1274
1275 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_SET_LOOPBACK_MODE,
1276 buf_in: &lb, in_size: sizeof(lb), buf_out: &lb, out_size: &out_size);
1277 if (err || !out_size || lb.status) {
1278 dev_err(&hwdev->hwif->pdev->dev,
1279 "Failed to set loopback mode %d en %d, err: %d, status: 0x%x, out size: 0x%x\n",
1280 mode, enable, err, lb.status, out_size);
1281 return -EIO;
1282 }
1283
1284 return 0;
1285}
1286
1287static int _set_led_status(struct hinic_hwdev *hwdev, u8 port,
1288 enum hinic_led_type type,
1289 enum hinic_led_mode mode, u8 reset)
1290{
1291 struct hinic_led_info led_info = {0};
1292 u16 out_size = sizeof(led_info);
1293 struct hinic_pfhwdev *pfhwdev;
1294 int err;
1295
1296 pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
1297
1298 led_info.port = port;
1299 led_info.reset = reset;
1300
1301 led_info.type = type;
1302 led_info.mode = mode;
1303
1304 err = hinic_msg_to_mgmt(pf_to_mgmt: &pfhwdev->pf_to_mgmt, mod: HINIC_MOD_COMM,
1305 cmd: HINIC_COMM_CMD_SET_LED_STATUS,
1306 buf_in: &led_info, in_size: sizeof(led_info),
1307 buf_out: &led_info, out_size: &out_size, sync: HINIC_MGMT_MSG_SYNC);
1308 if (err || led_info.status || !out_size) {
1309 dev_err(&hwdev->hwif->pdev->dev, "Failed to set led status, err: %d, status: 0x%x, out size: 0x%x\n",
1310 err, led_info.status, out_size);
1311 return -EIO;
1312 }
1313
1314 return 0;
1315}
1316
1317int hinic_set_led_status(struct hinic_hwdev *hwdev, u8 port,
1318 enum hinic_led_type type, enum hinic_led_mode mode)
1319{
1320 if (!hwdev)
1321 return -EINVAL;
1322
1323 return _set_led_status(hwdev, port, type, mode, reset: 0);
1324}
1325
1326int hinic_reset_led_status(struct hinic_hwdev *hwdev, u8 port)
1327{
1328 int err;
1329
1330 if (!hwdev)
1331 return -EINVAL;
1332
1333 err = _set_led_status(hwdev, port, type: HINIC_LED_TYPE_INVALID,
1334 mode: HINIC_LED_MODE_INVALID, reset: 1);
1335 if (err)
1336 dev_err(&hwdev->hwif->pdev->dev,
1337 "Failed to reset led status\n");
1338
1339 return err;
1340}
1341
1342static bool hinic_if_sfp_absent(struct hinic_hwdev *hwdev)
1343{
1344 struct hinic_cmd_get_light_module_abs sfp_abs = {0};
1345 u16 out_size = sizeof(sfp_abs);
1346 u8 port_id = hwdev->port_id;
1347 int err;
1348
1349 sfp_abs.port_id = port_id;
1350 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_GET_SFP_ABS,
1351 buf_in: &sfp_abs, in_size: sizeof(sfp_abs), buf_out: &sfp_abs,
1352 out_size: &out_size);
1353 if (sfp_abs.status || err || !out_size) {
1354 dev_err(&hwdev->hwif->pdev->dev,
1355 "Failed to get port%d sfp absent status, err: %d, status: 0x%x, out size: 0x%x\n",
1356 port_id, err, sfp_abs.status, out_size);
1357 return true;
1358 }
1359
1360 return ((sfp_abs.abs_status == 0) ? false : true);
1361}
1362
1363int hinic_get_sfp_eeprom(struct hinic_hwdev *hwdev, u8 *data, u16 *len)
1364{
1365 struct hinic_cmd_get_std_sfp_info sfp_info = {0};
1366 u16 out_size = sizeof(sfp_info);
1367 u8 port_id;
1368 int err;
1369
1370 if (!hwdev || !data || !len)
1371 return -EINVAL;
1372
1373 port_id = hwdev->port_id;
1374
1375 if (hinic_if_sfp_absent(hwdev))
1376 return -ENXIO;
1377
1378 sfp_info.port_id = port_id;
1379 err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_GET_STD_SFP_INFO,
1380 buf_in: &sfp_info, in_size: sizeof(sfp_info), buf_out: &sfp_info,
1381 out_size: &out_size);
1382 if (sfp_info.status || err || !out_size) {
1383 dev_err(&hwdev->hwif->pdev->dev,
1384 "Failed to get port%d sfp eeprom information, err: %d, status: 0x%x, out size: 0x%x\n",
1385 port_id, err, sfp_info.status, out_size);
1386 return -EIO;
1387 }
1388
1389 *len = min_t(u16, sfp_info.eeprom_len, STD_SFP_INFO_MAX_SIZE);
1390 memcpy(data, sfp_info.sfp_info, STD_SFP_INFO_MAX_SIZE);
1391
1392 return 0;
1393}
1394
1395int hinic_get_sfp_type(struct hinic_hwdev *hwdev, u8 *data0, u8 *data1)
1396{
1397 u8 sfp_data[STD_SFP_INFO_MAX_SIZE];
1398 u16 len;
1399 int err;
1400
1401 if (hinic_if_sfp_absent(hwdev))
1402 return -ENXIO;
1403
1404 err = hinic_get_sfp_eeprom(hwdev, data: sfp_data, len: &len);
1405 if (err)
1406 return err;
1407
1408 *data0 = sfp_data[0];
1409 *data1 = sfp_data[1];
1410
1411 return 0;
1412}
1413

source code of linux/drivers/net/ethernet/huawei/hinic/hinic_port.c