hinic: add rss support
[linux-2.6-block.git] / drivers / net / ethernet / huawei / hinic / hinic_port.c
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_set_rss_type(struct hinic_dev *nic_dev, u32 tmpl_idx,
620                        struct hinic_rss_type rss_type)
621 {
622         struct hinic_rss_context_tbl *ctx_tbl;
623         struct hinic_func_to_io *func_to_io;
624         struct hinic_cmdq_buf cmd_buf;
625         struct hinic_hwdev *hwdev;
626         struct hinic_hwif *hwif;
627         struct pci_dev *pdev;
628         u64 out_param;
629         u32 ctx = 0;
630         int err;
631
632         hwdev = nic_dev->hwdev;
633         func_to_io = &hwdev->func_to_io;
634         hwif = hwdev->hwif;
635         pdev = hwif->pdev;
636
637         err = hinic_alloc_cmdq_buf(&func_to_io->cmdqs, &cmd_buf);
638         if (err) {
639                 dev_err(&pdev->dev, "Failed to allocate cmd buf\n");
640                 return -ENOMEM;
641         }
642
643         ctx |=  HINIC_RSS_TYPE_SET(1, VALID) |
644                 HINIC_RSS_TYPE_SET(rss_type.ipv4, IPV4) |
645                 HINIC_RSS_TYPE_SET(rss_type.ipv6, IPV6) |
646                 HINIC_RSS_TYPE_SET(rss_type.ipv6_ext, IPV6_EXT) |
647                 HINIC_RSS_TYPE_SET(rss_type.tcp_ipv4, TCP_IPV4) |
648                 HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6, TCP_IPV6) |
649                 HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6_ext, TCP_IPV6_EXT) |
650                 HINIC_RSS_TYPE_SET(rss_type.udp_ipv4, UDP_IPV4) |
651                 HINIC_RSS_TYPE_SET(rss_type.udp_ipv6, UDP_IPV6);
652
653         cmd_buf.size = sizeof(struct hinic_rss_context_tbl);
654
655         ctx_tbl = (struct hinic_rss_context_tbl *)cmd_buf.buf;
656         ctx_tbl->group_index = cpu_to_be32(tmpl_idx);
657         ctx_tbl->offset = 0;
658         ctx_tbl->size = sizeof(u32);
659         ctx_tbl->size = cpu_to_be32(ctx_tbl->size);
660         ctx_tbl->rsvd = 0;
661         ctx_tbl->ctx = cpu_to_be32(ctx);
662
663         /* cfg the rss context table by command queue */
664         err = hinic_cmdq_direct_resp(&func_to_io->cmdqs, HINIC_MOD_L2NIC,
665                                      HINIC_UCODE_CMD_SET_RSS_CONTEXT_TABLE,
666                                      &cmd_buf, &out_param);
667
668         hinic_free_cmdq_buf(&func_to_io->cmdqs, &cmd_buf);
669
670         if (err || out_param != 0) {
671                 dev_err(&pdev->dev, "Failed to set rss context table, err: %d\n",
672                         err);
673                 return -EFAULT;
674         }
675
676         return 0;
677 }
678
679 int hinic_rss_set_template_tbl(struct hinic_dev *nic_dev, u32 template_id,
680                                const u8 *temp)
681 {
682         struct hinic_hwdev *hwdev = nic_dev->hwdev;
683         struct hinic_hwif *hwif = hwdev->hwif;
684         struct hinic_rss_key rss_key = { 0 };
685         struct pci_dev *pdev = hwif->pdev;
686         u16 out_size;
687         int err;
688
689         rss_key.func_id = HINIC_HWIF_FUNC_IDX(hwif);
690         rss_key.template_id = template_id;
691         memcpy(rss_key.key, temp, HINIC_RSS_KEY_SIZE);
692
693         err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RSS_TEMPLATE_TBL,
694                                  &rss_key, sizeof(rss_key),
695                                  &rss_key, &out_size);
696         if (err || !out_size || rss_key.status) {
697                 dev_err(&pdev->dev,
698                         "Failed to set rss hash key, err: %d, status: 0x%x, out size: 0x%x\n",
699                         err, rss_key.status, out_size);
700                 return -EINVAL;
701         }
702
703         return 0;
704 }
705
706 int hinic_rss_set_hash_engine(struct hinic_dev *nic_dev, u8 template_id,
707                               u8 type)
708 {
709         struct hinic_rss_engine_type rss_engine = { 0 };
710         struct hinic_hwdev *hwdev = nic_dev->hwdev;
711         struct hinic_hwif *hwif = hwdev->hwif;
712         struct pci_dev *pdev = hwif->pdev;
713         u16 out_size;
714         int err;
715
716         rss_engine.func_id = HINIC_HWIF_FUNC_IDX(hwif);
717         rss_engine.hash_engine = type;
718         rss_engine.template_id = template_id;
719
720         err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RSS_HASH_ENGINE,
721                                  &rss_engine, sizeof(rss_engine),
722                                  &rss_engine, &out_size);
723         if (err || !out_size || rss_engine.status) {
724                 dev_err(&pdev->dev,
725                         "Failed to set hash engine, err: %d, status: 0x%x, out size: 0x%x\n",
726                         err, rss_engine.status, out_size);
727                 return -EINVAL;
728         }
729
730         return 0;
731 }
732
733 int hinic_rss_cfg(struct hinic_dev *nic_dev, u8 rss_en, u8 template_id)
734 {
735         struct hinic_hwdev *hwdev = nic_dev->hwdev;
736         struct hinic_rss_config rss_cfg = { 0 };
737         struct hinic_hwif *hwif = hwdev->hwif;
738         struct pci_dev *pdev = hwif->pdev;
739         u16 out_size;
740         int err;
741
742         rss_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
743         rss_cfg.rss_en = rss_en;
744         rss_cfg.template_id = template_id;
745         rss_cfg.rq_priority_number = 0;
746
747         err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_RSS_CFG,
748                                  &rss_cfg, sizeof(rss_cfg),
749                                  &rss_cfg, &out_size);
750         if (err || !out_size || rss_cfg.status) {
751                 dev_err(&pdev->dev,
752                         "Failed to set rss cfg, err: %d, status: 0x%x, out size: 0x%x\n",
753                         err, rss_cfg.status, out_size);
754                 return -EINVAL;
755         }
756
757         return 0;
758 }
759
760 int hinic_rss_template_alloc(struct hinic_dev *nic_dev, u8 *tmpl_idx)
761 {
762         struct hinic_rss_template_mgmt template_mgmt = { 0 };
763         struct hinic_hwdev *hwdev = nic_dev->hwdev;
764         struct hinic_hwif *hwif = hwdev->hwif;
765         struct pci_dev *pdev = hwif->pdev;
766         u16 out_size;
767         int err;
768
769         template_mgmt.func_id = HINIC_HWIF_FUNC_IDX(hwif);
770         template_mgmt.cmd = NIC_RSS_CMD_TEMP_ALLOC;
771
772         err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
773                                  &template_mgmt, sizeof(template_mgmt),
774                                  &template_mgmt, &out_size);
775         if (err || !out_size || template_mgmt.status) {
776                 dev_err(&pdev->dev, "Failed to alloc rss template, err: %d, status: 0x%x, out size: 0x%x\n",
777                         err, template_mgmt.status, out_size);
778                 return -EINVAL;
779         }
780
781         *tmpl_idx = template_mgmt.template_id;
782
783         return 0;
784 }
785
786 int hinic_rss_template_free(struct hinic_dev *nic_dev, u8 tmpl_idx)
787 {
788         struct hinic_rss_template_mgmt template_mgmt = { 0 };
789         struct hinic_hwdev *hwdev = nic_dev->hwdev;
790         struct hinic_hwif *hwif = hwdev->hwif;
791         struct pci_dev *pdev = hwif->pdev;
792         u16 out_size;
793         int err;
794
795         template_mgmt.func_id = HINIC_HWIF_FUNC_IDX(hwif);
796         template_mgmt.template_id = tmpl_idx;
797         template_mgmt.cmd = NIC_RSS_CMD_TEMP_FREE;
798
799         err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
800                                  &template_mgmt, sizeof(template_mgmt),
801                                  &template_mgmt, &out_size);
802         if (err || !out_size || template_mgmt.status) {
803                 dev_err(&pdev->dev, "Failed to free rss template, err: %d, status: 0x%x, out size: 0x%x\n",
804                         err, template_mgmt.status, out_size);
805                 return -EINVAL;
806         }
807
808         return 0;
809 }