xref: /linux/drivers/net/ethernet/huawei/hinic/hinic_port.c (revision f6d08d9d8543c8ee494b307804b28e2750ffedb9)
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 
20 #define HINIC_MIN_MTU_SIZE              256
21 #define HINIC_MAX_JUMBO_FRAME_SIZE      15872
22 
23 enum mac_op {
24 	MAC_DEL,
25 	MAC_SET,
26 };
27 
28 /**
29  * change_mac - change(add or delete) mac address
30  * @nic_dev: nic device
31  * @addr: mac address
32  * @vlan_id: vlan number to set with the mac
33  * @op: add or delete the mac
34  *
35  * Return 0 - Success, negative - Failure
36  **/
37 static int change_mac(struct hinic_dev *nic_dev, const u8 *addr,
38 		      u16 vlan_id, enum mac_op op)
39 {
40 	struct net_device *netdev = nic_dev->netdev;
41 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
42 	struct hinic_port_mac_cmd port_mac_cmd;
43 	struct hinic_hwif *hwif = hwdev->hwif;
44 	struct pci_dev *pdev = hwif->pdev;
45 	enum hinic_port_cmd cmd;
46 	u16 out_size;
47 	int err;
48 
49 	if (vlan_id >= VLAN_N_VID) {
50 		netif_err(nic_dev, drv, netdev, "Invalid VLAN number\n");
51 		return -EINVAL;
52 	}
53 
54 	if (op == MAC_SET)
55 		cmd = HINIC_PORT_CMD_SET_MAC;
56 	else
57 		cmd = HINIC_PORT_CMD_DEL_MAC;
58 
59 	port_mac_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
60 	port_mac_cmd.vlan_id = vlan_id;
61 	memcpy(port_mac_cmd.mac, addr, ETH_ALEN);
62 
63 	err = hinic_port_msg_cmd(hwdev, cmd, &port_mac_cmd,
64 				 sizeof(port_mac_cmd),
65 				 &port_mac_cmd, &out_size);
66 	if (err || (out_size != sizeof(port_mac_cmd)) || port_mac_cmd.status) {
67 		dev_err(&pdev->dev, "Failed to change MAC, ret = %d\n",
68 			port_mac_cmd.status);
69 		return -EFAULT;
70 	}
71 
72 	return 0;
73 }
74 
75 /**
76  * hinic_port_add_mac - add mac address
77  * @nic_dev: nic device
78  * @addr: mac address
79  * @vlan_id: vlan number to set with the mac
80  *
81  * Return 0 - Success, negative - Failure
82  **/
83 int hinic_port_add_mac(struct hinic_dev *nic_dev,
84 		       const u8 *addr, u16 vlan_id)
85 {
86 	return change_mac(nic_dev, addr, vlan_id, MAC_SET);
87 }
88 
89 /**
90  * hinic_port_del_mac - remove mac address
91  * @nic_dev: nic device
92  * @addr: mac address
93  * @vlan_id: vlan number that is connected to the mac
94  *
95  * Return 0 - Success, negative - Failure
96  **/
97 int hinic_port_del_mac(struct hinic_dev *nic_dev, const u8 *addr,
98 		       u16 vlan_id)
99 {
100 	return change_mac(nic_dev, addr, vlan_id, MAC_DEL);
101 }
102 
103 /**
104  * hinic_port_get_mac - get the mac address of the nic device
105  * @nic_dev: nic device
106  * @addr: returned mac address
107  *
108  * Return 0 - Success, negative - Failure
109  **/
110 int hinic_port_get_mac(struct hinic_dev *nic_dev, u8 *addr)
111 {
112 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
113 	struct hinic_port_mac_cmd port_mac_cmd;
114 	struct hinic_hwif *hwif = hwdev->hwif;
115 	struct pci_dev *pdev = hwif->pdev;
116 	u16 out_size;
117 	int err;
118 
119 	port_mac_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
120 
121 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_MAC,
122 				 &port_mac_cmd, sizeof(port_mac_cmd),
123 				 &port_mac_cmd, &out_size);
124 	if (err || (out_size != sizeof(port_mac_cmd)) || port_mac_cmd.status) {
125 		dev_err(&pdev->dev, "Failed to get mac, ret = %d\n",
126 			port_mac_cmd.status);
127 		return -EFAULT;
128 	}
129 
130 	memcpy(addr, port_mac_cmd.mac, ETH_ALEN);
131 	return 0;
132 }
133 
134 /**
135  * hinic_port_set_mtu - set mtu
136  * @nic_dev: nic device
137  * @new_mtu: new mtu
138  *
139  * Return 0 - Success, negative - Failure
140  **/
141 int hinic_port_set_mtu(struct hinic_dev *nic_dev, int new_mtu)
142 {
143 	struct net_device *netdev = nic_dev->netdev;
144 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
145 	struct hinic_port_mtu_cmd port_mtu_cmd;
146 	struct hinic_hwif *hwif = hwdev->hwif;
147 	struct pci_dev *pdev = hwif->pdev;
148 	int err, max_frame;
149 	u16 out_size;
150 
151 	if (new_mtu < HINIC_MIN_MTU_SIZE) {
152 		netif_err(nic_dev, drv, netdev, "mtu < MIN MTU size");
153 		return -EINVAL;
154 	}
155 
156 	max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
157 	if (max_frame > HINIC_MAX_JUMBO_FRAME_SIZE) {
158 		netif_err(nic_dev, drv, netdev, "mtu > MAX MTU size");
159 		return -EINVAL;
160 	}
161 
162 	port_mtu_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
163 	port_mtu_cmd.mtu = new_mtu;
164 
165 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_CHANGE_MTU,
166 				 &port_mtu_cmd, sizeof(port_mtu_cmd),
167 				 &port_mtu_cmd, &out_size);
168 	if (err || (out_size != sizeof(port_mtu_cmd)) || port_mtu_cmd.status) {
169 		dev_err(&pdev->dev, "Failed to set mtu, ret = %d\n",
170 			port_mtu_cmd.status);
171 		return -EFAULT;
172 	}
173 
174 	return 0;
175 }
176 
177 /**
178  * hinic_port_add_vlan - add vlan to the nic device
179  * @nic_dev: nic device
180  * @vlan_id: the vlan number to add
181  *
182  * Return 0 - Success, negative - Failure
183  **/
184 int hinic_port_add_vlan(struct hinic_dev *nic_dev, u16 vlan_id)
185 {
186 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
187 	struct hinic_port_vlan_cmd port_vlan_cmd;
188 
189 	port_vlan_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
190 	port_vlan_cmd.vlan_id = vlan_id;
191 
192 	return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_ADD_VLAN,
193 				  &port_vlan_cmd, sizeof(port_vlan_cmd),
194 				  NULL, NULL);
195 }
196 
197 /**
198  * hinic_port_del_vlan - delete vlan from the nic device
199  * @nic_dev: nic device
200  * @vlan_id: the vlan number to delete
201  *
202  * Return 0 - Success, negative - Failure
203  **/
204 int hinic_port_del_vlan(struct hinic_dev *nic_dev, u16 vlan_id)
205 {
206 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
207 	struct hinic_port_vlan_cmd port_vlan_cmd;
208 
209 	port_vlan_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
210 	port_vlan_cmd.vlan_id = vlan_id;
211 
212 	return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_DEL_VLAN,
213 				 &port_vlan_cmd, sizeof(port_vlan_cmd),
214 				 NULL, NULL);
215 }
216 
217 /**
218  * hinic_port_set_rx_mode - set rx mode in the nic device
219  * @nic_dev: nic device
220  * @rx_mode: the rx mode to set
221  *
222  * Return 0 - Success, negative - Failure
223  **/
224 int hinic_port_set_rx_mode(struct hinic_dev *nic_dev, u32 rx_mode)
225 {
226 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
227 	struct hinic_port_rx_mode_cmd rx_mode_cmd;
228 
229 	rx_mode_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
230 	rx_mode_cmd.rx_mode = rx_mode;
231 
232 	return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RX_MODE,
233 				  &rx_mode_cmd, sizeof(rx_mode_cmd),
234 				  NULL, NULL);
235 }
236 
237 /**
238  * hinic_port_link_state - get the link state
239  * @nic_dev: nic device
240  * @link_state: the returned link state
241  *
242  * Return 0 - Success, negative - Failure
243  **/
244 int hinic_port_link_state(struct hinic_dev *nic_dev,
245 			  enum hinic_port_link_state *link_state)
246 {
247 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
248 	struct hinic_hwif *hwif = hwdev->hwif;
249 	struct hinic_port_link_cmd link_cmd;
250 	struct pci_dev *pdev = hwif->pdev;
251 	u16 out_size;
252 	int err;
253 
254 	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
255 		dev_err(&pdev->dev, "unsupported PCI Function type\n");
256 		return -EINVAL;
257 	}
258 
259 	link_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
260 
261 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_LINK_STATE,
262 				 &link_cmd, sizeof(link_cmd),
263 				 &link_cmd, &out_size);
264 	if (err || (out_size != sizeof(link_cmd)) || link_cmd.status) {
265 		dev_err(&pdev->dev, "Failed to get link state, ret = %d\n",
266 			link_cmd.status);
267 		return -EINVAL;
268 	}
269 
270 	*link_state = link_cmd.state;
271 	return 0;
272 }
273 
274 /**
275  * hinic_port_set_state - set port state
276  * @nic_dev: nic device
277  * @state: the state to set
278  *
279  * Return 0 - Success, negative - Failure
280  **/
281 int hinic_port_set_state(struct hinic_dev *nic_dev, enum hinic_port_state state)
282 {
283 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
284 	struct hinic_port_state_cmd port_state;
285 	struct hinic_hwif *hwif = hwdev->hwif;
286 	struct pci_dev *pdev = hwif->pdev;
287 	u16 out_size;
288 	int err;
289 
290 	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
291 		dev_err(&pdev->dev, "unsupported PCI Function type\n");
292 		return -EINVAL;
293 	}
294 
295 	port_state.state = state;
296 
297 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_PORT_STATE,
298 				 &port_state, sizeof(port_state),
299 				 &port_state, &out_size);
300 	if (err || (out_size != sizeof(port_state)) || port_state.status) {
301 		dev_err(&pdev->dev, "Failed to set port state, ret = %d\n",
302 			port_state.status);
303 		return -EFAULT;
304 	}
305 
306 	return 0;
307 }
308 
309 /**
310  * hinic_port_set_func_state- set func device state
311  * @nic_dev: nic device
312  * @state: the state to set
313  *
314  * Return 0 - Success, negative - Failure
315  **/
316 int hinic_port_set_func_state(struct hinic_dev *nic_dev,
317 			      enum hinic_func_port_state state)
318 {
319 	struct hinic_port_func_state_cmd func_state;
320 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
321 	struct hinic_hwif *hwif = hwdev->hwif;
322 	struct pci_dev *pdev = hwif->pdev;
323 	u16 out_size;
324 	int err;
325 
326 	func_state.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
327 	func_state.state = state;
328 
329 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_FUNC_STATE,
330 				 &func_state, sizeof(func_state),
331 				 &func_state, &out_size);
332 	if (err || (out_size != sizeof(func_state)) || func_state.status) {
333 		dev_err(&pdev->dev, "Failed to set port func state, ret = %d\n",
334 			func_state.status);
335 		return -EFAULT;
336 	}
337 
338 	return 0;
339 }
340 
341 /**
342  * hinic_port_get_cap - get port capabilities
343  * @nic_dev: nic device
344  * @port_cap: returned port capabilities
345  *
346  * Return 0 - Success, negative - Failure
347  **/
348 int hinic_port_get_cap(struct hinic_dev *nic_dev,
349 		       struct hinic_port_cap *port_cap)
350 {
351 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
352 	struct hinic_hwif *hwif = hwdev->hwif;
353 	struct pci_dev *pdev = hwif->pdev;
354 	u16 out_size;
355 	int err;
356 
357 	port_cap->func_idx = HINIC_HWIF_FUNC_IDX(hwif);
358 
359 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_CAP,
360 				 port_cap, sizeof(*port_cap),
361 				 port_cap, &out_size);
362 	if (err || (out_size != sizeof(*port_cap)) || port_cap->status) {
363 		dev_err(&pdev->dev,
364 			"Failed to get port capabilities, ret = %d\n",
365 			port_cap->status);
366 		return -EINVAL;
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;
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, ret = %d\n",
397 			tso_cfg.status);
398 		return -EINVAL;
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 	struct hinic_hwif *hwif;
409 	struct pci_dev *pdev;
410 	u16 out_size;
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, ret = %d\n",
427 			rx_csum_cfg.status);
428 		return -EINVAL;
429 	}
430 
431 	return 0;
432 }
433 
434 int hinic_set_max_qnum(struct hinic_dev *nic_dev, u8 num_rqs)
435 {
436 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
437 	struct hinic_hwif *hwif = hwdev->hwif;
438 	struct pci_dev *pdev = hwif->pdev;
439 	struct hinic_rq_num rq_num = { 0 };
440 	u16 out_size = sizeof(rq_num);
441 	int err;
442 
443 	rq_num.func_id = HINIC_HWIF_FUNC_IDX(hwif);
444 	rq_num.num_rqs = num_rqs;
445 	rq_num.rq_depth = ilog2(HINIC_SQ_DEPTH);
446 
447 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RQ_IQ_MAP,
448 				 &rq_num, sizeof(rq_num),
449 				 &rq_num, &out_size);
450 	if (err || !out_size || rq_num.status) {
451 		dev_err(&pdev->dev,
452 			"Failed to rxq number, ret = %d\n",
453 			rq_num.status);
454 		return -EINVAL;
455 	}
456 
457 	return 0;
458 }
459 
460 static int hinic_set_rx_lro(struct hinic_dev *nic_dev, u8 ipv4_en, u8 ipv6_en,
461 			    u8 max_wqe_num)
462 {
463 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
464 	struct hinic_hwif *hwif = hwdev->hwif;
465 	struct hinic_lro_config lro_cfg = { 0 };
466 	struct pci_dev *pdev = hwif->pdev;
467 	u16 out_size = sizeof(lro_cfg);
468 	int err;
469 
470 	lro_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
471 	lro_cfg.lro_ipv4_en = ipv4_en;
472 	lro_cfg.lro_ipv6_en = ipv6_en;
473 	lro_cfg.lro_max_wqe_num = max_wqe_num;
474 
475 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_LRO,
476 				 &lro_cfg, sizeof(lro_cfg),
477 				 &lro_cfg, &out_size);
478 	if (err || !out_size || lro_cfg.status) {
479 		dev_err(&pdev->dev,
480 			"Failed to set lro offload, ret = %d\n",
481 			lro_cfg.status);
482 		return -EINVAL;
483 	}
484 
485 	return 0;
486 }
487 
488 static int hinic_set_rx_lro_timer(struct hinic_dev *nic_dev, u32 timer_value)
489 {
490 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
491 	struct hinic_lro_timer lro_timer = { 0 };
492 	struct hinic_hwif *hwif = hwdev->hwif;
493 	struct pci_dev *pdev = hwif->pdev;
494 	u16 out_size = sizeof(lro_timer);
495 	int err;
496 
497 	lro_timer.status = 0;
498 	lro_timer.type = 0;
499 	lro_timer.enable = 1;
500 	lro_timer.timer = timer_value;
501 
502 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_LRO_TIMER,
503 				 &lro_timer, sizeof(lro_timer),
504 				 &lro_timer, &out_size);
505 	if (lro_timer.status == 0xFF) {
506 		/* For this case, we think status (0xFF) is OK */
507 		lro_timer.status = 0;
508 		dev_dbg(&pdev->dev,
509 			"Set lro timer not supported by the current FW version, it will be 1ms default\n");
510 	}
511 
512 	if (err || !out_size || lro_timer.status) {
513 		dev_err(&pdev->dev,
514 			"Failed to set lro timer, ret = %d\n",
515 			lro_timer.status);
516 
517 		return -EINVAL;
518 	}
519 
520 	return 0;
521 }
522 
523 int hinic_set_rx_lro_state(struct hinic_dev *nic_dev, u8 lro_en,
524 			   u32 lro_timer, u32 wqe_num)
525 {
526 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
527 	u8 ipv4_en;
528 	u8 ipv6_en;
529 	int err;
530 
531 	if (!hwdev)
532 		return -EINVAL;
533 
534 	ipv4_en = lro_en ? 1 : 0;
535 	ipv6_en = lro_en ? 1 : 0;
536 
537 	err = hinic_set_rx_lro(nic_dev, ipv4_en, ipv6_en, (u8)wqe_num);
538 	if (err)
539 		return err;
540 
541 	err = hinic_set_rx_lro_timer(nic_dev, lro_timer);
542 	if (err)
543 		return err;
544 
545 	return 0;
546 }
547 
548 int hinic_rss_set_indir_tbl(struct hinic_dev *nic_dev, u32 tmpl_idx,
549 			    const u32 *indir_table)
550 {
551 	struct hinic_rss_indirect_tbl *indir_tbl;
552 	struct hinic_func_to_io *func_to_io;
553 	struct hinic_cmdq_buf cmd_buf;
554 	struct hinic_hwdev *hwdev;
555 	struct hinic_hwif *hwif;
556 	struct pci_dev *pdev;
557 	u32 indir_size;
558 	u64 out_param;
559 	int err, i;
560 	u32 *temp;
561 
562 	hwdev = nic_dev->hwdev;
563 	func_to_io = &hwdev->func_to_io;
564 	hwif = hwdev->hwif;
565 	pdev = hwif->pdev;
566 
567 	err = hinic_alloc_cmdq_buf(&func_to_io->cmdqs, &cmd_buf);
568 	if (err) {
569 		dev_err(&pdev->dev, "Failed to allocate cmdq buf\n");
570 		return err;
571 	}
572 
573 	cmd_buf.size = sizeof(*indir_tbl);
574 
575 	indir_tbl = cmd_buf.buf;
576 	indir_tbl->group_index = cpu_to_be32(tmpl_idx);
577 
578 	for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++) {
579 		indir_tbl->entry[i] = indir_table[i];
580 
581 		if (0x3 == (i & 0x3)) {
582 			temp = (u32 *)&indir_tbl->entry[i - 3];
583 			*temp = cpu_to_be32(*temp);
584 		}
585 	}
586 
587 	/* cfg the rss indirect table by command queue */
588 	indir_size = HINIC_RSS_INDIR_SIZE / 2;
589 	indir_tbl->offset = 0;
590 	indir_tbl->size = cpu_to_be32(indir_size);
591 
592 	err = hinic_cmdq_direct_resp(&func_to_io->cmdqs, HINIC_MOD_L2NIC,
593 				     HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
594 				     &cmd_buf, &out_param);
595 	if (err || out_param != 0) {
596 		dev_err(&pdev->dev, "Failed to set rss indir table\n");
597 		err = -EFAULT;
598 		goto free_buf;
599 	}
600 
601 	indir_tbl->offset = cpu_to_be32(indir_size);
602 	indir_tbl->size = cpu_to_be32(indir_size);
603 	memcpy(&indir_tbl->entry[0], &indir_tbl->entry[indir_size], indir_size);
604 
605 	err = hinic_cmdq_direct_resp(&func_to_io->cmdqs, HINIC_MOD_L2NIC,
606 				     HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
607 				     &cmd_buf, &out_param);
608 	if (err || out_param != 0) {
609 		dev_err(&pdev->dev, "Failed to set rss indir table\n");
610 		err = -EFAULT;
611 	}
612 
613 free_buf:
614 	hinic_free_cmdq_buf(&func_to_io->cmdqs, &cmd_buf);
615 
616 	return err;
617 }
618 
619 int hinic_rss_get_indir_tbl(struct hinic_dev *nic_dev, u32 tmpl_idx,
620 			    u32 *indir_table)
621 {
622 	struct hinic_rss_indir_table rss_cfg = { 0 };
623 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
624 	struct hinic_hwif *hwif = hwdev->hwif;
625 	struct pci_dev *pdev = hwif->pdev;
626 	u16 out_size = sizeof(rss_cfg);
627 	int err = 0, i;
628 
629 	rss_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
630 	rss_cfg.template_id = tmpl_idx;
631 
632 	err = hinic_port_msg_cmd(hwdev,
633 				 HINIC_PORT_CMD_GET_RSS_TEMPLATE_INDIR_TBL,
634 				 &rss_cfg, sizeof(rss_cfg), &rss_cfg,
635 				 &out_size);
636 	if (err || !out_size || rss_cfg.status) {
637 		dev_err(&pdev->dev, "Failed to get indir table, err: %d, status: 0x%x, out size: 0x%x\n",
638 			err, rss_cfg.status, out_size);
639 		return -EINVAL;
640 	}
641 
642 	hinic_be32_to_cpu(rss_cfg.indir, HINIC_RSS_INDIR_SIZE);
643 	for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++)
644 		indir_table[i] = rss_cfg.indir[i];
645 
646 	return 0;
647 }
648 
649 int hinic_set_rss_type(struct hinic_dev *nic_dev, u32 tmpl_idx,
650 		       struct hinic_rss_type rss_type)
651 {
652 	struct hinic_rss_context_tbl *ctx_tbl;
653 	struct hinic_func_to_io *func_to_io;
654 	struct hinic_cmdq_buf cmd_buf;
655 	struct hinic_hwdev *hwdev;
656 	struct hinic_hwif *hwif;
657 	struct pci_dev *pdev;
658 	u64 out_param;
659 	u32 ctx = 0;
660 	int err;
661 
662 	hwdev = nic_dev->hwdev;
663 	func_to_io = &hwdev->func_to_io;
664 	hwif = hwdev->hwif;
665 	pdev = hwif->pdev;
666 
667 	err = hinic_alloc_cmdq_buf(&func_to_io->cmdqs, &cmd_buf);
668 	if (err) {
669 		dev_err(&pdev->dev, "Failed to allocate cmd buf\n");
670 		return -ENOMEM;
671 	}
672 
673 	ctx |=  HINIC_RSS_TYPE_SET(1, VALID) |
674 		HINIC_RSS_TYPE_SET(rss_type.ipv4, IPV4) |
675 		HINIC_RSS_TYPE_SET(rss_type.ipv6, IPV6) |
676 		HINIC_RSS_TYPE_SET(rss_type.ipv6_ext, IPV6_EXT) |
677 		HINIC_RSS_TYPE_SET(rss_type.tcp_ipv4, TCP_IPV4) |
678 		HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6, TCP_IPV6) |
679 		HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6_ext, TCP_IPV6_EXT) |
680 		HINIC_RSS_TYPE_SET(rss_type.udp_ipv4, UDP_IPV4) |
681 		HINIC_RSS_TYPE_SET(rss_type.udp_ipv6, UDP_IPV6);
682 
683 	cmd_buf.size = sizeof(struct hinic_rss_context_tbl);
684 
685 	ctx_tbl = (struct hinic_rss_context_tbl *)cmd_buf.buf;
686 	ctx_tbl->group_index = cpu_to_be32(tmpl_idx);
687 	ctx_tbl->offset = 0;
688 	ctx_tbl->size = sizeof(u32);
689 	ctx_tbl->size = cpu_to_be32(ctx_tbl->size);
690 	ctx_tbl->rsvd = 0;
691 	ctx_tbl->ctx = cpu_to_be32(ctx);
692 
693 	/* cfg the rss context table by command queue */
694 	err = hinic_cmdq_direct_resp(&func_to_io->cmdqs, HINIC_MOD_L2NIC,
695 				     HINIC_UCODE_CMD_SET_RSS_CONTEXT_TABLE,
696 				     &cmd_buf, &out_param);
697 
698 	hinic_free_cmdq_buf(&func_to_io->cmdqs, &cmd_buf);
699 
700 	if (err || out_param != 0) {
701 		dev_err(&pdev->dev, "Failed to set rss context table, err: %d\n",
702 			err);
703 		return -EFAULT;
704 	}
705 
706 	return 0;
707 }
708 
709 int hinic_get_rss_type(struct hinic_dev *nic_dev, u32 tmpl_idx,
710 		       struct hinic_rss_type *rss_type)
711 {
712 	struct hinic_rss_context_table ctx_tbl = { 0 };
713 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
714 	struct hinic_hwif *hwif;
715 	struct pci_dev *pdev;
716 	u16 out_size = sizeof(ctx_tbl);
717 	int err;
718 
719 	if (!hwdev || !rss_type)
720 		return -EINVAL;
721 
722 	hwif = hwdev->hwif;
723 	pdev = hwif->pdev;
724 
725 	ctx_tbl.func_id = HINIC_HWIF_FUNC_IDX(hwif);
726 	ctx_tbl.template_id = tmpl_idx;
727 
728 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_RSS_CTX_TBL,
729 				 &ctx_tbl, sizeof(ctx_tbl),
730 				 &ctx_tbl, &out_size);
731 	if (err || !out_size || ctx_tbl.status) {
732 		dev_err(&pdev->dev, "Failed to get hash type, err: %d, status: 0x%x, out size: 0x%x\n",
733 			err, ctx_tbl.status, out_size);
734 		return -EINVAL;
735 	}
736 
737 	rss_type->ipv4          = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV4);
738 	rss_type->ipv6          = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6);
739 	rss_type->ipv6_ext      = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6_EXT);
740 	rss_type->tcp_ipv4      = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV4);
741 	rss_type->tcp_ipv6      = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6);
742 	rss_type->tcp_ipv6_ext  = HINIC_RSS_TYPE_GET(ctx_tbl.context,
743 						     TCP_IPV6_EXT);
744 	rss_type->udp_ipv4      = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV4);
745 	rss_type->udp_ipv6      = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV6);
746 
747 	return 0;
748 }
749 
750 int hinic_rss_set_template_tbl(struct hinic_dev *nic_dev, u32 template_id,
751 			       const u8 *temp)
752 {
753 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
754 	struct hinic_hwif *hwif = hwdev->hwif;
755 	struct hinic_rss_key rss_key = { 0 };
756 	struct pci_dev *pdev = hwif->pdev;
757 	u16 out_size;
758 	int err;
759 
760 	rss_key.func_id = HINIC_HWIF_FUNC_IDX(hwif);
761 	rss_key.template_id = template_id;
762 	memcpy(rss_key.key, temp, HINIC_RSS_KEY_SIZE);
763 
764 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RSS_TEMPLATE_TBL,
765 				 &rss_key, sizeof(rss_key),
766 				 &rss_key, &out_size);
767 	if (err || !out_size || rss_key.status) {
768 		dev_err(&pdev->dev,
769 			"Failed to set rss hash key, err: %d, status: 0x%x, out size: 0x%x\n",
770 			err, rss_key.status, out_size);
771 		return -EINVAL;
772 	}
773 
774 	return 0;
775 }
776 
777 int hinic_rss_get_template_tbl(struct hinic_dev *nic_dev, u32 tmpl_idx,
778 			       u8 *temp)
779 {
780 	struct hinic_rss_template_key temp_key = { 0 };
781 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
782 	struct hinic_hwif *hwif;
783 	struct pci_dev *pdev;
784 	u16 out_size = sizeof(temp_key);
785 	int err;
786 
787 	if (!hwdev || !temp)
788 		return -EINVAL;
789 
790 	hwif = hwdev->hwif;
791 	pdev = hwif->pdev;
792 
793 	temp_key.func_id = HINIC_HWIF_FUNC_IDX(hwif);
794 	temp_key.template_id = tmpl_idx;
795 
796 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_RSS_TEMPLATE_TBL,
797 				 &temp_key, sizeof(temp_key),
798 				 &temp_key, &out_size);
799 	if (err || !out_size || temp_key.status) {
800 		dev_err(&pdev->dev, "Failed to set hash key, err: %d, status: 0x%x, out size: 0x%x\n",
801 			err, temp_key.status, out_size);
802 		return -EINVAL;
803 	}
804 
805 	memcpy(temp, temp_key.key, HINIC_RSS_KEY_SIZE);
806 
807 	return 0;
808 }
809 
810 int hinic_rss_set_hash_engine(struct hinic_dev *nic_dev, u8 template_id,
811 			      u8 type)
812 {
813 	struct hinic_rss_engine_type rss_engine = { 0 };
814 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
815 	struct hinic_hwif *hwif = hwdev->hwif;
816 	struct pci_dev *pdev = hwif->pdev;
817 	u16 out_size;
818 	int err;
819 
820 	rss_engine.func_id = HINIC_HWIF_FUNC_IDX(hwif);
821 	rss_engine.hash_engine = type;
822 	rss_engine.template_id = template_id;
823 
824 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RSS_HASH_ENGINE,
825 				 &rss_engine, sizeof(rss_engine),
826 				 &rss_engine, &out_size);
827 	if (err || !out_size || rss_engine.status) {
828 		dev_err(&pdev->dev,
829 			"Failed to set hash engine, err: %d, status: 0x%x, out size: 0x%x\n",
830 			err, rss_engine.status, out_size);
831 		return -EINVAL;
832 	}
833 
834 	return 0;
835 }
836 
837 int hinic_rss_get_hash_engine(struct hinic_dev *nic_dev, u8 tmpl_idx, u8 *type)
838 {
839 	struct hinic_rss_engine_type hash_type = { 0 };
840 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
841 	struct hinic_hwif *hwif;
842 	struct pci_dev *pdev;
843 	u16 out_size = sizeof(hash_type);
844 	int err;
845 
846 	if (!hwdev || !type)
847 		return -EINVAL;
848 
849 	hwif = hwdev->hwif;
850 	pdev = hwif->pdev;
851 
852 	hash_type.func_id = HINIC_HWIF_FUNC_IDX(hwif);
853 	hash_type.template_id = tmpl_idx;
854 
855 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_RSS_HASH_ENGINE,
856 				 &hash_type, sizeof(hash_type),
857 				 &hash_type, &out_size);
858 	if (err || !out_size || hash_type.status) {
859 		dev_err(&pdev->dev, "Failed to get hash engine, err: %d, status: 0x%x, out size: 0x%x\n",
860 			err, hash_type.status, out_size);
861 		return -EINVAL;
862 	}
863 
864 	*type = hash_type.hash_engine;
865 	return 0;
866 }
867 
868 int hinic_rss_cfg(struct hinic_dev *nic_dev, u8 rss_en, u8 template_id)
869 {
870 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
871 	struct hinic_rss_config rss_cfg = { 0 };
872 	struct hinic_hwif *hwif = hwdev->hwif;
873 	struct pci_dev *pdev = hwif->pdev;
874 	u16 out_size;
875 	int err;
876 
877 	rss_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
878 	rss_cfg.rss_en = rss_en;
879 	rss_cfg.template_id = template_id;
880 	rss_cfg.rq_priority_number = 0;
881 
882 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_RSS_CFG,
883 				 &rss_cfg, sizeof(rss_cfg),
884 				 &rss_cfg, &out_size);
885 	if (err || !out_size || rss_cfg.status) {
886 		dev_err(&pdev->dev,
887 			"Failed to set rss cfg, err: %d, status: 0x%x, out size: 0x%x\n",
888 			err, rss_cfg.status, out_size);
889 		return -EINVAL;
890 	}
891 
892 	return 0;
893 }
894 
895 int hinic_rss_template_alloc(struct hinic_dev *nic_dev, u8 *tmpl_idx)
896 {
897 	struct hinic_rss_template_mgmt template_mgmt = { 0 };
898 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
899 	struct hinic_hwif *hwif = hwdev->hwif;
900 	struct pci_dev *pdev = hwif->pdev;
901 	u16 out_size;
902 	int err;
903 
904 	template_mgmt.func_id = HINIC_HWIF_FUNC_IDX(hwif);
905 	template_mgmt.cmd = NIC_RSS_CMD_TEMP_ALLOC;
906 
907 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
908 				 &template_mgmt, sizeof(template_mgmt),
909 				 &template_mgmt, &out_size);
910 	if (err || !out_size || template_mgmt.status) {
911 		dev_err(&pdev->dev, "Failed to alloc rss template, err: %d, status: 0x%x, out size: 0x%x\n",
912 			err, template_mgmt.status, out_size);
913 		return -EINVAL;
914 	}
915 
916 	*tmpl_idx = template_mgmt.template_id;
917 
918 	return 0;
919 }
920 
921 int hinic_rss_template_free(struct hinic_dev *nic_dev, u8 tmpl_idx)
922 {
923 	struct hinic_rss_template_mgmt template_mgmt = { 0 };
924 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
925 	struct hinic_hwif *hwif = hwdev->hwif;
926 	struct pci_dev *pdev = hwif->pdev;
927 	u16 out_size;
928 	int err;
929 
930 	template_mgmt.func_id = HINIC_HWIF_FUNC_IDX(hwif);
931 	template_mgmt.template_id = tmpl_idx;
932 	template_mgmt.cmd = NIC_RSS_CMD_TEMP_FREE;
933 
934 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
935 				 &template_mgmt, sizeof(template_mgmt),
936 				 &template_mgmt, &out_size);
937 	if (err || !out_size || template_mgmt.status) {
938 		dev_err(&pdev->dev, "Failed to free rss template, err: %d, status: 0x%x, out size: 0x%x\n",
939 			err, template_mgmt.status, out_size);
940 		return -EINVAL;
941 	}
942 
943 	return 0;
944 }
945