New upstream version 18.11-rc1
[deb_dpdk.git] / drivers / net / i40e / rte_pmd_i40e.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2017 Intel Corporation
3  */
4
5 #include <rte_malloc.h>
6 #include <rte_tailq.h>
7
8 #include "base/i40e_prototype.h"
9 #include "base/i40e_dcb.h"
10 #include "i40e_ethdev.h"
11 #include "i40e_pf.h"
12 #include "i40e_rxtx.h"
13 #include "rte_pmd_i40e.h"
14
15 int
16 rte_pmd_i40e_ping_vfs(uint16_t port, uint16_t vf)
17 {
18         struct rte_eth_dev *dev;
19         struct i40e_pf *pf;
20
21         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
22
23         dev = &rte_eth_devices[port];
24
25         if (!is_i40e_supported(dev))
26                 return -ENOTSUP;
27
28         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
29
30         if (vf >= pf->vf_num || !pf->vfs) {
31                 PMD_DRV_LOG(ERR, "Invalid argument.");
32                 return -EINVAL;
33         }
34
35         i40e_notify_vf_link_status(dev, &pf->vfs[vf]);
36
37         return 0;
38 }
39
40 int
41 rte_pmd_i40e_set_vf_mac_anti_spoof(uint16_t port, uint16_t vf_id, uint8_t on)
42 {
43         struct rte_eth_dev *dev;
44         struct i40e_pf *pf;
45         struct i40e_vsi *vsi;
46         struct i40e_hw *hw;
47         struct i40e_vsi_context ctxt;
48         int ret;
49
50         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
51
52         dev = &rte_eth_devices[port];
53
54         if (!is_i40e_supported(dev))
55                 return -ENOTSUP;
56
57         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
58
59         if (vf_id >= pf->vf_num || !pf->vfs) {
60                 PMD_DRV_LOG(ERR, "Invalid argument.");
61                 return -EINVAL;
62         }
63
64         vsi = pf->vfs[vf_id].vsi;
65         if (!vsi) {
66                 PMD_DRV_LOG(ERR, "Invalid VSI.");
67                 return -EINVAL;
68         }
69
70         /* Check if it has been already on or off */
71         if (vsi->info.valid_sections &
72                 rte_cpu_to_le_16(I40E_AQ_VSI_PROP_SECURITY_VALID)) {
73                 if (on) {
74                         if ((vsi->info.sec_flags &
75                              I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK) ==
76                             I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK)
77                                 return 0; /* already on */
78                 } else {
79                         if ((vsi->info.sec_flags &
80                              I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK) == 0)
81                                 return 0; /* already off */
82                 }
83         }
84
85         vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SECURITY_VALID);
86         if (on)
87                 vsi->info.sec_flags |= I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK;
88         else
89                 vsi->info.sec_flags &= ~I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK;
90
91         memset(&ctxt, 0, sizeof(ctxt));
92         rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
93         ctxt.seid = vsi->seid;
94
95         hw = I40E_VSI_TO_HW(vsi);
96         ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
97         if (ret != I40E_SUCCESS) {
98                 ret = -ENOTSUP;
99                 PMD_DRV_LOG(ERR, "Failed to update VSI params");
100         }
101
102         return ret;
103 }
104
105 static int
106 i40e_add_rm_all_vlan_filter(struct i40e_vsi *vsi, uint8_t add)
107 {
108         uint32_t j, k;
109         uint16_t vlan_id;
110         struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
111         struct i40e_aqc_add_remove_vlan_element_data vlan_data = {0};
112         int ret;
113
114         for (j = 0; j < I40E_VFTA_SIZE; j++) {
115                 if (!vsi->vfta[j])
116                         continue;
117
118                 for (k = 0; k < I40E_UINT32_BIT_SIZE; k++) {
119                         if (!(vsi->vfta[j] & (1 << k)))
120                                 continue;
121
122                         vlan_id = j * I40E_UINT32_BIT_SIZE + k;
123                         if (!vlan_id)
124                                 continue;
125
126                         vlan_data.vlan_tag = rte_cpu_to_le_16(vlan_id);
127                         if (add)
128                                 ret = i40e_aq_add_vlan(hw, vsi->seid,
129                                                        &vlan_data, 1, NULL);
130                         else
131                                 ret = i40e_aq_remove_vlan(hw, vsi->seid,
132                                                           &vlan_data, 1, NULL);
133                         if (ret != I40E_SUCCESS) {
134                                 PMD_DRV_LOG(ERR,
135                                             "Failed to add/rm vlan filter");
136                                 return ret;
137                         }
138                 }
139         }
140
141         return I40E_SUCCESS;
142 }
143
144 int
145 rte_pmd_i40e_set_vf_vlan_anti_spoof(uint16_t port, uint16_t vf_id, uint8_t on)
146 {
147         struct rte_eth_dev *dev;
148         struct i40e_pf *pf;
149         struct i40e_vsi *vsi;
150         struct i40e_hw *hw;
151         struct i40e_vsi_context ctxt;
152         int ret;
153
154         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
155
156         dev = &rte_eth_devices[port];
157
158         if (!is_i40e_supported(dev))
159                 return -ENOTSUP;
160
161         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
162
163         if (vf_id >= pf->vf_num || !pf->vfs) {
164                 PMD_DRV_LOG(ERR, "Invalid argument.");
165                 return -EINVAL;
166         }
167
168         vsi = pf->vfs[vf_id].vsi;
169         if (!vsi) {
170                 PMD_DRV_LOG(ERR, "Invalid VSI.");
171                 return -EINVAL;
172         }
173
174         /* Check if it has been already on or off */
175         if (vsi->vlan_anti_spoof_on == on)
176                 return 0; /* already on or off */
177
178         vsi->vlan_anti_spoof_on = on;
179         if (!vsi->vlan_filter_on) {
180                 ret = i40e_add_rm_all_vlan_filter(vsi, on);
181                 if (ret) {
182                         PMD_DRV_LOG(ERR, "Failed to add/remove VLAN filters.");
183                         return -ENOTSUP;
184                 }
185         }
186
187         vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SECURITY_VALID);
188         if (on)
189                 vsi->info.sec_flags |= I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK;
190         else
191                 vsi->info.sec_flags &= ~I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK;
192
193         memset(&ctxt, 0, sizeof(ctxt));
194         rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
195         ctxt.seid = vsi->seid;
196
197         hw = I40E_VSI_TO_HW(vsi);
198         ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
199         if (ret != I40E_SUCCESS) {
200                 ret = -ENOTSUP;
201                 PMD_DRV_LOG(ERR, "Failed to update VSI params");
202         }
203
204         return ret;
205 }
206
207 static int
208 i40e_vsi_rm_mac_filter(struct i40e_vsi *vsi)
209 {
210         struct i40e_mac_filter *f;
211         struct i40e_macvlan_filter *mv_f;
212         int i, vlan_num;
213         enum rte_mac_filter_type filter_type;
214         int ret = I40E_SUCCESS;
215         void *temp;
216
217         /* remove all the MACs */
218         TAILQ_FOREACH_SAFE(f, &vsi->mac_list, next, temp) {
219                 vlan_num = vsi->vlan_num;
220                 filter_type = f->mac_info.filter_type;
221                 if (filter_type == RTE_MACVLAN_PERFECT_MATCH ||
222                     filter_type == RTE_MACVLAN_HASH_MATCH) {
223                         if (vlan_num == 0) {
224                                 PMD_DRV_LOG(ERR, "VLAN number shouldn't be 0");
225                                 return I40E_ERR_PARAM;
226                         }
227                 } else if (filter_type == RTE_MAC_PERFECT_MATCH ||
228                            filter_type == RTE_MAC_HASH_MATCH)
229                         vlan_num = 1;
230
231                 mv_f = rte_zmalloc("macvlan_data", vlan_num * sizeof(*mv_f), 0);
232                 if (!mv_f) {
233                         PMD_DRV_LOG(ERR, "failed to allocate memory");
234                         return I40E_ERR_NO_MEMORY;
235                 }
236
237                 for (i = 0; i < vlan_num; i++) {
238                         mv_f[i].filter_type = filter_type;
239                         rte_memcpy(&mv_f[i].macaddr,
240                                          &f->mac_info.mac_addr,
241                                          ETH_ADDR_LEN);
242                 }
243                 if (filter_type == RTE_MACVLAN_PERFECT_MATCH ||
244                     filter_type == RTE_MACVLAN_HASH_MATCH) {
245                         ret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num,
246                                                          &f->mac_info.mac_addr);
247                         if (ret != I40E_SUCCESS) {
248                                 rte_free(mv_f);
249                                 return ret;
250                         }
251                 }
252
253                 ret = i40e_remove_macvlan_filters(vsi, mv_f, vlan_num);
254                 if (ret != I40E_SUCCESS) {
255                         rte_free(mv_f);
256                         return ret;
257                 }
258
259                 rte_free(mv_f);
260                 ret = I40E_SUCCESS;
261         }
262
263         return ret;
264 }
265
266 static int
267 i40e_vsi_restore_mac_filter(struct i40e_vsi *vsi)
268 {
269         struct i40e_mac_filter *f;
270         struct i40e_macvlan_filter *mv_f;
271         int i, vlan_num = 0;
272         int ret = I40E_SUCCESS;
273         void *temp;
274
275         /* restore all the MACs */
276         TAILQ_FOREACH_SAFE(f, &vsi->mac_list, next, temp) {
277                 if ((f->mac_info.filter_type == RTE_MACVLAN_PERFECT_MATCH) ||
278                     (f->mac_info.filter_type == RTE_MACVLAN_HASH_MATCH)) {
279                         /**
280                          * If vlan_num is 0, that's the first time to add mac,
281                          * set mask for vlan_id 0.
282                          */
283                         if (vsi->vlan_num == 0) {
284                                 i40e_set_vlan_filter(vsi, 0, 1);
285                                 vsi->vlan_num = 1;
286                         }
287                         vlan_num = vsi->vlan_num;
288                 } else if ((f->mac_info.filter_type == RTE_MAC_PERFECT_MATCH) ||
289                            (f->mac_info.filter_type == RTE_MAC_HASH_MATCH))
290                         vlan_num = 1;
291
292                 mv_f = rte_zmalloc("macvlan_data", vlan_num * sizeof(*mv_f), 0);
293                 if (!mv_f) {
294                         PMD_DRV_LOG(ERR, "failed to allocate memory");
295                         return I40E_ERR_NO_MEMORY;
296                 }
297
298                 for (i = 0; i < vlan_num; i++) {
299                         mv_f[i].filter_type = f->mac_info.filter_type;
300                         rte_memcpy(&mv_f[i].macaddr,
301                                          &f->mac_info.mac_addr,
302                                          ETH_ADDR_LEN);
303                 }
304
305                 if (f->mac_info.filter_type == RTE_MACVLAN_PERFECT_MATCH ||
306                     f->mac_info.filter_type == RTE_MACVLAN_HASH_MATCH) {
307                         ret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num,
308                                                          &f->mac_info.mac_addr);
309                         if (ret != I40E_SUCCESS) {
310                                 rte_free(mv_f);
311                                 return ret;
312                         }
313                 }
314
315                 ret = i40e_add_macvlan_filters(vsi, mv_f, vlan_num);
316                 if (ret != I40E_SUCCESS) {
317                         rte_free(mv_f);
318                         return ret;
319                 }
320
321                 rte_free(mv_f);
322                 ret = I40E_SUCCESS;
323         }
324
325         return ret;
326 }
327
328 static int
329 i40e_vsi_set_tx_loopback(struct i40e_vsi *vsi, uint8_t on)
330 {
331         struct i40e_vsi_context ctxt;
332         struct i40e_hw *hw;
333         int ret;
334
335         if (!vsi)
336                 return -EINVAL;
337
338         hw = I40E_VSI_TO_HW(vsi);
339
340         /* Use the FW API if FW >= v5.0 */
341         if (hw->aq.fw_maj_ver < 5 && hw->mac.type != I40E_MAC_X722) {
342                 PMD_INIT_LOG(ERR, "FW < v5.0, cannot enable loopback");
343                 return -ENOTSUP;
344         }
345
346         /* Check if it has been already on or off */
347         if (vsi->info.valid_sections &
348                 rte_cpu_to_le_16(I40E_AQ_VSI_PROP_SWITCH_VALID)) {
349                 if (on) {
350                         if ((vsi->info.switch_id &
351                              I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB) ==
352                             I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB)
353                                 return 0; /* already on */
354                 } else {
355                         if ((vsi->info.switch_id &
356                              I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB) == 0)
357                                 return 0; /* already off */
358                 }
359         }
360
361         /* remove all the MAC and VLAN first */
362         ret = i40e_vsi_rm_mac_filter(vsi);
363         if (ret) {
364                 PMD_INIT_LOG(ERR, "Failed to remove MAC filters.");
365                 return ret;
366         }
367         if (vsi->vlan_anti_spoof_on || vsi->vlan_filter_on) {
368                 ret = i40e_add_rm_all_vlan_filter(vsi, 0);
369                 if (ret) {
370                         PMD_INIT_LOG(ERR, "Failed to remove VLAN filters.");
371                         return ret;
372                 }
373         }
374
375         vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SWITCH_VALID);
376         if (on)
377                 vsi->info.switch_id |= I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB;
378         else
379                 vsi->info.switch_id &= ~I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB;
380
381         memset(&ctxt, 0, sizeof(ctxt));
382         rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
383         ctxt.seid = vsi->seid;
384
385         ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
386         if (ret != I40E_SUCCESS) {
387                 PMD_DRV_LOG(ERR, "Failed to update VSI params");
388                 return ret;
389         }
390
391         /* add all the MAC and VLAN back */
392         ret = i40e_vsi_restore_mac_filter(vsi);
393         if (ret)
394                 return ret;
395         if (vsi->vlan_anti_spoof_on || vsi->vlan_filter_on) {
396                 ret = i40e_add_rm_all_vlan_filter(vsi, 1);
397                 if (ret)
398                         return ret;
399         }
400
401         return ret;
402 }
403
404 int
405 rte_pmd_i40e_set_tx_loopback(uint16_t port, uint8_t on)
406 {
407         struct rte_eth_dev *dev;
408         struct i40e_pf *pf;
409         struct i40e_pf_vf *vf;
410         struct i40e_vsi *vsi;
411         uint16_t vf_id;
412         int ret;
413
414         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
415
416         dev = &rte_eth_devices[port];
417
418         if (!is_i40e_supported(dev))
419                 return -ENOTSUP;
420
421         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
422
423         /* setup PF TX loopback */
424         vsi = pf->main_vsi;
425         ret = i40e_vsi_set_tx_loopback(vsi, on);
426         if (ret)
427                 return -ENOTSUP;
428
429         /* setup TX loopback for all the VFs */
430         if (!pf->vfs) {
431                 /* if no VF, do nothing. */
432                 return 0;
433         }
434
435         for (vf_id = 0; vf_id < pf->vf_num; vf_id++) {
436                 vf = &pf->vfs[vf_id];
437                 vsi = vf->vsi;
438
439                 ret = i40e_vsi_set_tx_loopback(vsi, on);
440                 if (ret)
441                         return -ENOTSUP;
442         }
443
444         return ret;
445 }
446
447 int
448 rte_pmd_i40e_set_vf_unicast_promisc(uint16_t port, uint16_t vf_id, uint8_t on)
449 {
450         struct rte_eth_dev *dev;
451         struct i40e_pf *pf;
452         struct i40e_vsi *vsi;
453         struct i40e_hw *hw;
454         int ret;
455
456         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
457
458         dev = &rte_eth_devices[port];
459
460         if (!is_i40e_supported(dev))
461                 return -ENOTSUP;
462
463         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
464
465         if (vf_id >= pf->vf_num || !pf->vfs) {
466                 PMD_DRV_LOG(ERR, "Invalid argument.");
467                 return -EINVAL;
468         }
469
470         vsi = pf->vfs[vf_id].vsi;
471         if (!vsi) {
472                 PMD_DRV_LOG(ERR, "Invalid VSI.");
473                 return -EINVAL;
474         }
475
476         hw = I40E_VSI_TO_HW(vsi);
477
478         ret = i40e_aq_set_vsi_unicast_promiscuous(hw, vsi->seid,
479                                                   on, NULL, true);
480         if (ret != I40E_SUCCESS) {
481                 ret = -ENOTSUP;
482                 PMD_DRV_LOG(ERR, "Failed to set unicast promiscuous mode");
483         }
484
485         return ret;
486 }
487
488 int
489 rte_pmd_i40e_set_vf_multicast_promisc(uint16_t port, uint16_t vf_id, uint8_t on)
490 {
491         struct rte_eth_dev *dev;
492         struct i40e_pf *pf;
493         struct i40e_vsi *vsi;
494         struct i40e_hw *hw;
495         int ret;
496
497         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
498
499         dev = &rte_eth_devices[port];
500
501         if (!is_i40e_supported(dev))
502                 return -ENOTSUP;
503
504         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
505
506         if (vf_id >= pf->vf_num || !pf->vfs) {
507                 PMD_DRV_LOG(ERR, "Invalid argument.");
508                 return -EINVAL;
509         }
510
511         vsi = pf->vfs[vf_id].vsi;
512         if (!vsi) {
513                 PMD_DRV_LOG(ERR, "Invalid VSI.");
514                 return -EINVAL;
515         }
516
517         hw = I40E_VSI_TO_HW(vsi);
518
519         ret = i40e_aq_set_vsi_multicast_promiscuous(hw, vsi->seid,
520                                                     on, NULL);
521         if (ret != I40E_SUCCESS) {
522                 ret = -ENOTSUP;
523                 PMD_DRV_LOG(ERR, "Failed to set multicast promiscuous mode");
524         }
525
526         return ret;
527 }
528
529 int
530 rte_pmd_i40e_set_vf_mac_addr(uint16_t port, uint16_t vf_id,
531                              struct ether_addr *mac_addr)
532 {
533         struct i40e_mac_filter *f;
534         struct rte_eth_dev *dev;
535         struct i40e_pf_vf *vf;
536         struct i40e_vsi *vsi;
537         struct i40e_pf *pf;
538         void *temp;
539
540         if (i40e_validate_mac_addr((u8 *)mac_addr) != I40E_SUCCESS)
541                 return -EINVAL;
542
543         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
544
545         dev = &rte_eth_devices[port];
546
547         if (!is_i40e_supported(dev))
548                 return -ENOTSUP;
549
550         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
551
552         if (vf_id >= pf->vf_num || !pf->vfs)
553                 return -EINVAL;
554
555         vf = &pf->vfs[vf_id];
556         vsi = vf->vsi;
557         if (!vsi) {
558                 PMD_DRV_LOG(ERR, "Invalid VSI.");
559                 return -EINVAL;
560         }
561
562         ether_addr_copy(mac_addr, &vf->mac_addr);
563
564         /* Remove all existing mac */
565         TAILQ_FOREACH_SAFE(f, &vsi->mac_list, next, temp)
566                 if (i40e_vsi_delete_mac(vsi, &f->mac_info.mac_addr)
567                                 != I40E_SUCCESS)
568                         PMD_DRV_LOG(WARNING, "Delete MAC failed");
569
570         return 0;
571 }
572
573 static const struct ether_addr null_mac_addr;
574
575 int
576 rte_pmd_i40e_remove_vf_mac_addr(uint16_t port, uint16_t vf_id,
577         struct ether_addr *mac_addr)
578 {
579         struct rte_eth_dev *dev;
580         struct i40e_pf_vf *vf;
581         struct i40e_vsi *vsi;
582         struct i40e_pf *pf;
583
584         if (i40e_validate_mac_addr((u8 *)mac_addr) != I40E_SUCCESS)
585                 return -EINVAL;
586
587         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
588
589         dev = &rte_eth_devices[port];
590
591         if (!is_i40e_supported(dev))
592                 return -ENOTSUP;
593
594         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
595
596         if (vf_id >= pf->vf_num || !pf->vfs)
597                 return -EINVAL;
598
599         vf = &pf->vfs[vf_id];
600         vsi = vf->vsi;
601         if (!vsi) {
602                 PMD_DRV_LOG(ERR, "Invalid VSI.");
603                 return -EINVAL;
604         }
605
606         if (is_same_ether_addr(mac_addr, &vf->mac_addr))
607                 /* Reset the mac with NULL address */
608                 ether_addr_copy(&null_mac_addr, &vf->mac_addr);
609
610         /* Remove the mac */
611         i40e_vsi_delete_mac(vsi, mac_addr);
612
613         return 0;
614 }
615
616 /* Set vlan strip on/off for specific VF from host */
617 int
618 rte_pmd_i40e_set_vf_vlan_stripq(uint16_t port, uint16_t vf_id, uint8_t on)
619 {
620         struct rte_eth_dev *dev;
621         struct i40e_pf *pf;
622         struct i40e_vsi *vsi;
623         int ret;
624
625         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
626
627         dev = &rte_eth_devices[port];
628
629         if (!is_i40e_supported(dev))
630                 return -ENOTSUP;
631
632         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
633
634         if (vf_id >= pf->vf_num || !pf->vfs) {
635                 PMD_DRV_LOG(ERR, "Invalid argument.");
636                 return -EINVAL;
637         }
638
639         vsi = pf->vfs[vf_id].vsi;
640
641         if (!vsi)
642                 return -EINVAL;
643
644         ret = i40e_vsi_config_vlan_stripping(vsi, !!on);
645         if (ret != I40E_SUCCESS) {
646                 ret = -ENOTSUP;
647                 PMD_DRV_LOG(ERR, "Failed to set VLAN stripping!");
648         }
649
650         return ret;
651 }
652
653 int rte_pmd_i40e_set_vf_vlan_insert(uint16_t port, uint16_t vf_id,
654                                     uint16_t vlan_id)
655 {
656         struct rte_eth_dev *dev;
657         struct i40e_pf *pf;
658         struct i40e_hw *hw;
659         struct i40e_vsi *vsi;
660         struct i40e_vsi_context ctxt;
661         int ret;
662
663         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
664
665         if (vlan_id > ETHER_MAX_VLAN_ID) {
666                 PMD_DRV_LOG(ERR, "Invalid VLAN ID.");
667                 return -EINVAL;
668         }
669
670         dev = &rte_eth_devices[port];
671
672         if (!is_i40e_supported(dev))
673                 return -ENOTSUP;
674
675         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
676         hw = I40E_PF_TO_HW(pf);
677
678         /**
679          * return -ENODEV if SRIOV not enabled, VF number not configured
680          * or no queue assigned.
681          */
682         if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
683             pf->vf_nb_qps == 0)
684                 return -ENODEV;
685
686         if (vf_id >= pf->vf_num || !pf->vfs) {
687                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
688                 return -EINVAL;
689         }
690
691         vsi = pf->vfs[vf_id].vsi;
692         if (!vsi) {
693                 PMD_DRV_LOG(ERR, "Invalid VSI.");
694                 return -EINVAL;
695         }
696
697         vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID);
698         vsi->info.pvid = vlan_id;
699         if (vlan_id > 0)
700                 vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_INSERT_PVID;
701         else
702                 vsi->info.port_vlan_flags &= ~I40E_AQ_VSI_PVLAN_INSERT_PVID;
703
704         memset(&ctxt, 0, sizeof(ctxt));
705         rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
706         ctxt.seid = vsi->seid;
707
708         hw = I40E_VSI_TO_HW(vsi);
709         ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
710         if (ret != I40E_SUCCESS) {
711                 ret = -ENOTSUP;
712                 PMD_DRV_LOG(ERR, "Failed to update VSI params");
713         }
714
715         return ret;
716 }
717
718 int rte_pmd_i40e_set_vf_broadcast(uint16_t port, uint16_t vf_id,
719                                   uint8_t on)
720 {
721         struct rte_eth_dev *dev;
722         struct i40e_pf *pf;
723         struct i40e_vsi *vsi;
724         struct i40e_hw *hw;
725         struct i40e_mac_filter_info filter;
726         struct ether_addr broadcast = {
727                 .addr_bytes = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} };
728         int ret;
729
730         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
731
732         if (on > 1) {
733                 PMD_DRV_LOG(ERR, "on should be 0 or 1.");
734                 return -EINVAL;
735         }
736
737         dev = &rte_eth_devices[port];
738
739         if (!is_i40e_supported(dev))
740                 return -ENOTSUP;
741
742         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
743         hw = I40E_PF_TO_HW(pf);
744
745         if (vf_id >= pf->vf_num || !pf->vfs) {
746                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
747                 return -EINVAL;
748         }
749
750         /**
751          * return -ENODEV if SRIOV not enabled, VF number not configured
752          * or no queue assigned.
753          */
754         if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
755             pf->vf_nb_qps == 0) {
756                 PMD_DRV_LOG(ERR, "SRIOV is not enabled or no queue.");
757                 return -ENODEV;
758         }
759
760         vsi = pf->vfs[vf_id].vsi;
761         if (!vsi) {
762                 PMD_DRV_LOG(ERR, "Invalid VSI.");
763                 return -EINVAL;
764         }
765
766         if (on) {
767                 rte_memcpy(&filter.mac_addr, &broadcast, ETHER_ADDR_LEN);
768                 filter.filter_type = RTE_MACVLAN_PERFECT_MATCH;
769                 ret = i40e_vsi_add_mac(vsi, &filter);
770         } else {
771                 ret = i40e_vsi_delete_mac(vsi, &broadcast);
772         }
773
774         if (ret != I40E_SUCCESS && ret != I40E_ERR_PARAM) {
775                 ret = -ENOTSUP;
776                 PMD_DRV_LOG(ERR, "Failed to set VSI broadcast");
777         } else {
778                 ret = 0;
779         }
780
781         return ret;
782 }
783
784 int rte_pmd_i40e_set_vf_vlan_tag(uint16_t port, uint16_t vf_id, uint8_t on)
785 {
786         struct rte_eth_dev *dev;
787         struct i40e_pf *pf;
788         struct i40e_hw *hw;
789         struct i40e_vsi *vsi;
790         struct i40e_vsi_context ctxt;
791         int ret;
792
793         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
794
795         if (on > 1) {
796                 PMD_DRV_LOG(ERR, "on should be 0 or 1.");
797                 return -EINVAL;
798         }
799
800         dev = &rte_eth_devices[port];
801
802         if (!is_i40e_supported(dev))
803                 return -ENOTSUP;
804
805         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
806         hw = I40E_PF_TO_HW(pf);
807
808         /**
809          * return -ENODEV if SRIOV not enabled, VF number not configured
810          * or no queue assigned.
811          */
812         if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
813             pf->vf_nb_qps == 0) {
814                 PMD_DRV_LOG(ERR, "SRIOV is not enabled or no queue.");
815                 return -ENODEV;
816         }
817
818         if (vf_id >= pf->vf_num || !pf->vfs) {
819                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
820                 return -EINVAL;
821         }
822
823         vsi = pf->vfs[vf_id].vsi;
824         if (!vsi) {
825                 PMD_DRV_LOG(ERR, "Invalid VSI.");
826                 return -EINVAL;
827         }
828
829         vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID);
830         if (on) {
831                 vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_TAGGED;
832                 vsi->info.port_vlan_flags &= ~I40E_AQ_VSI_PVLAN_MODE_UNTAGGED;
833         } else {
834                 vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_UNTAGGED;
835                 vsi->info.port_vlan_flags &= ~I40E_AQ_VSI_PVLAN_MODE_TAGGED;
836         }
837
838         memset(&ctxt, 0, sizeof(ctxt));
839         rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
840         ctxt.seid = vsi->seid;
841
842         hw = I40E_VSI_TO_HW(vsi);
843         ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
844         if (ret != I40E_SUCCESS) {
845                 ret = -ENOTSUP;
846                 PMD_DRV_LOG(ERR, "Failed to update VSI params");
847         }
848
849         return ret;
850 }
851
852 static int
853 i40e_vlan_filter_count(struct i40e_vsi *vsi)
854 {
855         uint32_t j, k;
856         uint16_t vlan_id;
857         int count = 0;
858
859         for (j = 0; j < I40E_VFTA_SIZE; j++) {
860                 if (!vsi->vfta[j])
861                         continue;
862
863                 for (k = 0; k < I40E_UINT32_BIT_SIZE; k++) {
864                         if (!(vsi->vfta[j] & (1 << k)))
865                                 continue;
866
867                         vlan_id = j * I40E_UINT32_BIT_SIZE + k;
868                         if (!vlan_id)
869                                 continue;
870
871                         count++;
872                 }
873         }
874
875         return count;
876 }
877
878 int rte_pmd_i40e_set_vf_vlan_filter(uint16_t port, uint16_t vlan_id,
879                                     uint64_t vf_mask, uint8_t on)
880 {
881         struct rte_eth_dev *dev;
882         struct i40e_pf *pf;
883         struct i40e_hw *hw;
884         struct i40e_vsi *vsi;
885         uint16_t vf_idx;
886         int ret = I40E_SUCCESS;
887
888         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
889
890         dev = &rte_eth_devices[port];
891
892         if (!is_i40e_supported(dev))
893                 return -ENOTSUP;
894
895         if (vlan_id > ETHER_MAX_VLAN_ID || !vlan_id) {
896                 PMD_DRV_LOG(ERR, "Invalid VLAN ID.");
897                 return -EINVAL;
898         }
899
900         if (vf_mask == 0) {
901                 PMD_DRV_LOG(ERR, "No VF.");
902                 return -EINVAL;
903         }
904
905         if (on > 1) {
906                 PMD_DRV_LOG(ERR, "on is should be 0 or 1.");
907                 return -EINVAL;
908         }
909
910         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
911         hw = I40E_PF_TO_HW(pf);
912
913         /**
914          * return -ENODEV if SRIOV not enabled, VF number not configured
915          * or no queue assigned.
916          */
917         if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
918             pf->vf_nb_qps == 0) {
919                 PMD_DRV_LOG(ERR, "SRIOV is not enabled or no queue.");
920                 return -ENODEV;
921         }
922
923         for (vf_idx = 0; vf_idx < pf->vf_num && ret == I40E_SUCCESS; vf_idx++) {
924                 if (vf_mask & ((uint64_t)(1ULL << vf_idx))) {
925                         vsi = pf->vfs[vf_idx].vsi;
926                         if (on) {
927                                 if (!vsi->vlan_filter_on) {
928                                         vsi->vlan_filter_on = true;
929                                         i40e_aq_set_vsi_vlan_promisc(hw,
930                                                                      vsi->seid,
931                                                                      false,
932                                                                      NULL);
933                                         if (!vsi->vlan_anti_spoof_on)
934                                                 i40e_add_rm_all_vlan_filter(
935                                                         vsi, true);
936                                 }
937                                 ret = i40e_vsi_add_vlan(vsi, vlan_id);
938                         } else {
939                                 ret = i40e_vsi_delete_vlan(vsi, vlan_id);
940
941                                 if (!i40e_vlan_filter_count(vsi)) {
942                                         vsi->vlan_filter_on = false;
943                                         i40e_aq_set_vsi_vlan_promisc(hw,
944                                                                      vsi->seid,
945                                                                      true,
946                                                                      NULL);
947                                 }
948                         }
949                 }
950         }
951
952         if (ret != I40E_SUCCESS) {
953                 ret = -ENOTSUP;
954                 PMD_DRV_LOG(ERR, "Failed to set VF VLAN filter, on = %d", on);
955         }
956
957         return ret;
958 }
959
960 int
961 rte_pmd_i40e_get_vf_stats(uint16_t port,
962                           uint16_t vf_id,
963                           struct rte_eth_stats *stats)
964 {
965         struct rte_eth_dev *dev;
966         struct i40e_pf *pf;
967         struct i40e_vsi *vsi;
968
969         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
970
971         dev = &rte_eth_devices[port];
972
973         if (!is_i40e_supported(dev))
974                 return -ENOTSUP;
975
976         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
977
978         if (vf_id >= pf->vf_num || !pf->vfs) {
979                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
980                 return -EINVAL;
981         }
982
983         vsi = pf->vfs[vf_id].vsi;
984         if (!vsi) {
985                 PMD_DRV_LOG(ERR, "Invalid VSI.");
986                 return -EINVAL;
987         }
988
989         i40e_update_vsi_stats(vsi);
990
991         stats->ipackets = vsi->eth_stats.rx_unicast +
992                         vsi->eth_stats.rx_multicast +
993                         vsi->eth_stats.rx_broadcast;
994         stats->opackets = vsi->eth_stats.tx_unicast +
995                         vsi->eth_stats.tx_multicast +
996                         vsi->eth_stats.tx_broadcast;
997         stats->ibytes   = vsi->eth_stats.rx_bytes;
998         stats->obytes   = vsi->eth_stats.tx_bytes;
999         stats->ierrors  = vsi->eth_stats.rx_discards;
1000         stats->oerrors  = vsi->eth_stats.tx_errors + vsi->eth_stats.tx_discards;
1001
1002         return 0;
1003 }
1004
1005 int
1006 rte_pmd_i40e_reset_vf_stats(uint16_t port,
1007                             uint16_t vf_id)
1008 {
1009         struct rte_eth_dev *dev;
1010         struct i40e_pf *pf;
1011         struct i40e_vsi *vsi;
1012
1013         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
1014
1015         dev = &rte_eth_devices[port];
1016
1017         if (!is_i40e_supported(dev))
1018                 return -ENOTSUP;
1019
1020         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1021
1022         if (vf_id >= pf->vf_num || !pf->vfs) {
1023                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
1024                 return -EINVAL;
1025         }
1026
1027         vsi = pf->vfs[vf_id].vsi;
1028         if (!vsi) {
1029                 PMD_DRV_LOG(ERR, "Invalid VSI.");
1030                 return -EINVAL;
1031         }
1032
1033         vsi->offset_loaded = false;
1034         i40e_update_vsi_stats(vsi);
1035
1036         return 0;
1037 }
1038
1039 int
1040 rte_pmd_i40e_set_vf_max_bw(uint16_t port, uint16_t vf_id, uint32_t bw)
1041 {
1042         struct rte_eth_dev *dev;
1043         struct i40e_pf *pf;
1044         struct i40e_vsi *vsi;
1045         struct i40e_hw *hw;
1046         int ret = 0;
1047         int i;
1048
1049         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
1050
1051         dev = &rte_eth_devices[port];
1052
1053         if (!is_i40e_supported(dev))
1054                 return -ENOTSUP;
1055
1056         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1057
1058         if (vf_id >= pf->vf_num || !pf->vfs) {
1059                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
1060                 return -EINVAL;
1061         }
1062
1063         vsi = pf->vfs[vf_id].vsi;
1064         if (!vsi) {
1065                 PMD_DRV_LOG(ERR, "Invalid VSI.");
1066                 return -EINVAL;
1067         }
1068
1069         if (bw > I40E_QOS_BW_MAX) {
1070                 PMD_DRV_LOG(ERR, "Bandwidth should not be larger than %dMbps.",
1071                             I40E_QOS_BW_MAX);
1072                 return -EINVAL;
1073         }
1074
1075         if (bw % I40E_QOS_BW_GRANULARITY) {
1076                 PMD_DRV_LOG(ERR, "Bandwidth should be the multiple of %dMbps.",
1077                             I40E_QOS_BW_GRANULARITY);
1078                 return -EINVAL;
1079         }
1080
1081         bw /= I40E_QOS_BW_GRANULARITY;
1082
1083         hw = I40E_VSI_TO_HW(vsi);
1084
1085         /* No change. */
1086         if (bw == vsi->bw_info.bw_limit) {
1087                 PMD_DRV_LOG(INFO,
1088                             "No change for VF max bandwidth. Nothing to do.");
1089                 return 0;
1090         }
1091
1092         /**
1093          * VF bandwidth limitation and TC bandwidth limitation cannot be
1094          * enabled in parallel, quit if TC bandwidth limitation is enabled.
1095          *
1096          * If bw is 0, means disable bandwidth limitation. Then no need to
1097          * check TC bandwidth limitation.
1098          */
1099         if (bw) {
1100                 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1101                         if ((vsi->enabled_tc & BIT_ULL(i)) &&
1102                             vsi->bw_info.bw_ets_credits[i])
1103                                 break;
1104                 }
1105                 if (i != I40E_MAX_TRAFFIC_CLASS) {
1106                         PMD_DRV_LOG(ERR,
1107                                     "TC max bandwidth has been set on this VF,"
1108                                     " please disable it first.");
1109                         return -EINVAL;
1110                 }
1111         }
1112
1113         ret = i40e_aq_config_vsi_bw_limit(hw, vsi->seid, (uint16_t)bw, 0, NULL);
1114         if (ret) {
1115                 PMD_DRV_LOG(ERR,
1116                             "Failed to set VF %d bandwidth, err(%d).",
1117                             vf_id, ret);
1118                 return -EINVAL;
1119         }
1120
1121         /* Store the configuration. */
1122         vsi->bw_info.bw_limit = (uint16_t)bw;
1123         vsi->bw_info.bw_max = 0;
1124
1125         return 0;
1126 }
1127
1128 int
1129 rte_pmd_i40e_set_vf_tc_bw_alloc(uint16_t port, uint16_t vf_id,
1130                                 uint8_t tc_num, uint8_t *bw_weight)
1131 {
1132         struct rte_eth_dev *dev;
1133         struct i40e_pf *pf;
1134         struct i40e_vsi *vsi;
1135         struct i40e_hw *hw;
1136         struct i40e_aqc_configure_vsi_tc_bw_data tc_bw;
1137         int ret = 0;
1138         int i, j;
1139         uint16_t sum;
1140         bool b_change = false;
1141
1142         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
1143
1144         dev = &rte_eth_devices[port];
1145
1146         if (!is_i40e_supported(dev))
1147                 return -ENOTSUP;
1148
1149         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1150
1151         if (vf_id >= pf->vf_num || !pf->vfs) {
1152                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
1153                 return -EINVAL;
1154         }
1155
1156         vsi = pf->vfs[vf_id].vsi;
1157         if (!vsi) {
1158                 PMD_DRV_LOG(ERR, "Invalid VSI.");
1159                 return -EINVAL;
1160         }
1161
1162         if (tc_num > I40E_MAX_TRAFFIC_CLASS) {
1163                 PMD_DRV_LOG(ERR, "TCs should be no more than %d.",
1164                             I40E_MAX_TRAFFIC_CLASS);
1165                 return -EINVAL;
1166         }
1167
1168         sum = 0;
1169         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1170                 if (vsi->enabled_tc & BIT_ULL(i))
1171                         sum++;
1172         }
1173         if (sum != tc_num) {
1174                 PMD_DRV_LOG(ERR,
1175                             "Weight should be set for all %d enabled TCs.",
1176                             sum);
1177                 return -EINVAL;
1178         }
1179
1180         sum = 0;
1181         for (i = 0; i < tc_num; i++) {
1182                 if (!bw_weight[i]) {
1183                         PMD_DRV_LOG(ERR,
1184                                     "The weight should be 1 at least.");
1185                         return -EINVAL;
1186                 }
1187                 sum += bw_weight[i];
1188         }
1189         if (sum != 100) {
1190                 PMD_DRV_LOG(ERR,
1191                             "The summary of the TC weight should be 100.");
1192                 return -EINVAL;
1193         }
1194
1195         /**
1196          * Create the configuration for all the TCs.
1197          */
1198         memset(&tc_bw, 0, sizeof(tc_bw));
1199         tc_bw.tc_valid_bits = vsi->enabled_tc;
1200         j = 0;
1201         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1202                 if (vsi->enabled_tc & BIT_ULL(i)) {
1203                         if (bw_weight[j] !=
1204                                 vsi->bw_info.bw_ets_share_credits[i])
1205                                 b_change = true;
1206
1207                         tc_bw.tc_bw_credits[i] = bw_weight[j];
1208                         j++;
1209                 }
1210         }
1211
1212         /* No change. */
1213         if (!b_change) {
1214                 PMD_DRV_LOG(INFO,
1215                             "No change for TC allocated bandwidth."
1216                             " Nothing to do.");
1217                 return 0;
1218         }
1219
1220         hw = I40E_VSI_TO_HW(vsi);
1221
1222         ret = i40e_aq_config_vsi_tc_bw(hw, vsi->seid, &tc_bw, NULL);
1223         if (ret) {
1224                 PMD_DRV_LOG(ERR,
1225                             "Failed to set VF %d TC bandwidth weight, err(%d).",
1226                             vf_id, ret);
1227                 return -EINVAL;
1228         }
1229
1230         /* Store the configuration. */
1231         j = 0;
1232         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1233                 if (vsi->enabled_tc & BIT_ULL(i)) {
1234                         vsi->bw_info.bw_ets_share_credits[i] = bw_weight[j];
1235                         j++;
1236                 }
1237         }
1238
1239         return 0;
1240 }
1241
1242 int
1243 rte_pmd_i40e_set_vf_tc_max_bw(uint16_t port, uint16_t vf_id,
1244                               uint8_t tc_no, uint32_t bw)
1245 {
1246         struct rte_eth_dev *dev;
1247         struct i40e_pf *pf;
1248         struct i40e_vsi *vsi;
1249         struct i40e_hw *hw;
1250         struct i40e_aqc_configure_vsi_ets_sla_bw_data tc_bw;
1251         int ret = 0;
1252         int i;
1253
1254         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
1255
1256         dev = &rte_eth_devices[port];
1257
1258         if (!is_i40e_supported(dev))
1259                 return -ENOTSUP;
1260
1261         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1262
1263         if (vf_id >= pf->vf_num || !pf->vfs) {
1264                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
1265                 return -EINVAL;
1266         }
1267
1268         vsi = pf->vfs[vf_id].vsi;
1269         if (!vsi) {
1270                 PMD_DRV_LOG(ERR, "Invalid VSI.");
1271                 return -EINVAL;
1272         }
1273
1274         if (bw > I40E_QOS_BW_MAX) {
1275                 PMD_DRV_LOG(ERR, "Bandwidth should not be larger than %dMbps.",
1276                             I40E_QOS_BW_MAX);
1277                 return -EINVAL;
1278         }
1279
1280         if (bw % I40E_QOS_BW_GRANULARITY) {
1281                 PMD_DRV_LOG(ERR, "Bandwidth should be the multiple of %dMbps.",
1282                             I40E_QOS_BW_GRANULARITY);
1283                 return -EINVAL;
1284         }
1285
1286         bw /= I40E_QOS_BW_GRANULARITY;
1287
1288         if (tc_no >= I40E_MAX_TRAFFIC_CLASS) {
1289                 PMD_DRV_LOG(ERR, "TC No. should be less than %d.",
1290                             I40E_MAX_TRAFFIC_CLASS);
1291                 return -EINVAL;
1292         }
1293
1294         hw = I40E_VSI_TO_HW(vsi);
1295
1296         if (!(vsi->enabled_tc & BIT_ULL(tc_no))) {
1297                 PMD_DRV_LOG(ERR, "VF %d TC %d isn't enabled.",
1298                             vf_id, tc_no);
1299                 return -EINVAL;
1300         }
1301
1302         /* No change. */
1303         if (bw == vsi->bw_info.bw_ets_credits[tc_no]) {
1304                 PMD_DRV_LOG(INFO,
1305                             "No change for TC max bandwidth. Nothing to do.");
1306                 return 0;
1307         }
1308
1309         /**
1310          * VF bandwidth limitation and TC bandwidth limitation cannot be
1311          * enabled in parallel, disable VF bandwidth limitation if it's
1312          * enabled.
1313          * If bw is 0, means disable bandwidth limitation. Then no need to
1314          * care about VF bandwidth limitation configuration.
1315          */
1316         if (bw && vsi->bw_info.bw_limit) {
1317                 ret = i40e_aq_config_vsi_bw_limit(hw, vsi->seid, 0, 0, NULL);
1318                 if (ret) {
1319                         PMD_DRV_LOG(ERR,
1320                                     "Failed to disable VF(%d)"
1321                                     " bandwidth limitation, err(%d).",
1322                                     vf_id, ret);
1323                         return -EINVAL;
1324                 }
1325
1326                 PMD_DRV_LOG(INFO,
1327                             "VF max bandwidth is disabled according"
1328                             " to TC max bandwidth setting.");
1329         }
1330
1331         /**
1332          * Get all the TCs' info to create a whole picture.
1333          * Because the incremental change isn't permitted.
1334          */
1335         memset(&tc_bw, 0, sizeof(tc_bw));
1336         tc_bw.tc_valid_bits = vsi->enabled_tc;
1337         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1338                 if (vsi->enabled_tc & BIT_ULL(i)) {
1339                         tc_bw.tc_bw_credits[i] =
1340                                 rte_cpu_to_le_16(
1341                                         vsi->bw_info.bw_ets_credits[i]);
1342                 }
1343         }
1344         tc_bw.tc_bw_credits[tc_no] = rte_cpu_to_le_16((uint16_t)bw);
1345
1346         ret = i40e_aq_config_vsi_ets_sla_bw_limit(hw, vsi->seid, &tc_bw, NULL);
1347         if (ret) {
1348                 PMD_DRV_LOG(ERR,
1349                             "Failed to set VF %d TC %d max bandwidth, err(%d).",
1350                             vf_id, tc_no, ret);
1351                 return -EINVAL;
1352         }
1353
1354         /* Store the configuration. */
1355         vsi->bw_info.bw_ets_credits[tc_no] = (uint16_t)bw;
1356
1357         return 0;
1358 }
1359
1360 int
1361 rte_pmd_i40e_set_tc_strict_prio(uint16_t port, uint8_t tc_map)
1362 {
1363         struct rte_eth_dev *dev;
1364         struct i40e_pf *pf;
1365         struct i40e_vsi *vsi;
1366         struct i40e_veb *veb;
1367         struct i40e_hw *hw;
1368         struct i40e_aqc_configure_switching_comp_ets_data ets_data;
1369         int i;
1370         int ret;
1371
1372         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
1373
1374         dev = &rte_eth_devices[port];
1375
1376         if (!is_i40e_supported(dev))
1377                 return -ENOTSUP;
1378
1379         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1380
1381         vsi = pf->main_vsi;
1382         if (!vsi) {
1383                 PMD_DRV_LOG(ERR, "Invalid VSI.");
1384                 return -EINVAL;
1385         }
1386
1387         veb = vsi->veb;
1388         if (!veb) {
1389                 PMD_DRV_LOG(ERR, "Invalid VEB.");
1390                 return -EINVAL;
1391         }
1392
1393         if ((tc_map & veb->enabled_tc) != tc_map) {
1394                 PMD_DRV_LOG(ERR,
1395                             "TC bitmap isn't the subset of enabled TCs 0x%x.",
1396                             veb->enabled_tc);
1397                 return -EINVAL;
1398         }
1399
1400         if (tc_map == veb->strict_prio_tc) {
1401                 PMD_DRV_LOG(INFO, "No change for TC bitmap. Nothing to do.");
1402                 return 0;
1403         }
1404
1405         hw = I40E_VSI_TO_HW(vsi);
1406
1407         /* Disable DCBx if it's the first time to set strict priority. */
1408         if (!veb->strict_prio_tc) {
1409                 ret = i40e_aq_stop_lldp(hw, true, NULL);
1410                 if (ret)
1411                         PMD_DRV_LOG(INFO,
1412                                     "Failed to disable DCBx as it's already"
1413                                     " disabled.");
1414                 else
1415                         PMD_DRV_LOG(INFO,
1416                                     "DCBx is disabled according to strict"
1417                                     " priority setting.");
1418         }
1419
1420         memset(&ets_data, 0, sizeof(ets_data));
1421         ets_data.tc_valid_bits = veb->enabled_tc;
1422         ets_data.seepage = I40E_AQ_ETS_SEEPAGE_EN_MASK;
1423         ets_data.tc_strict_priority_flags = tc_map;
1424         /* Get all TCs' bandwidth. */
1425         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1426                 if (veb->enabled_tc & BIT_ULL(i)) {
1427                         /* For rubust, if bandwidth is 0, use 1 instead. */
1428                         if (veb->bw_info.bw_ets_share_credits[i])
1429                                 ets_data.tc_bw_share_credits[i] =
1430                                         veb->bw_info.bw_ets_share_credits[i];
1431                         else
1432                                 ets_data.tc_bw_share_credits[i] =
1433                                         I40E_QOS_BW_WEIGHT_MIN;
1434                 }
1435         }
1436
1437         if (!veb->strict_prio_tc)
1438                 ret = i40e_aq_config_switch_comp_ets(
1439                         hw, veb->uplink_seid,
1440                         &ets_data, i40e_aqc_opc_enable_switching_comp_ets,
1441                         NULL);
1442         else if (tc_map)
1443                 ret = i40e_aq_config_switch_comp_ets(
1444                         hw, veb->uplink_seid,
1445                         &ets_data, i40e_aqc_opc_modify_switching_comp_ets,
1446                         NULL);
1447         else
1448                 ret = i40e_aq_config_switch_comp_ets(
1449                         hw, veb->uplink_seid,
1450                         &ets_data, i40e_aqc_opc_disable_switching_comp_ets,
1451                         NULL);
1452
1453         if (ret) {
1454                 PMD_DRV_LOG(ERR,
1455                             "Failed to set TCs' strict priority mode."
1456                             " err (%d)", ret);
1457                 return -EINVAL;
1458         }
1459
1460         veb->strict_prio_tc = tc_map;
1461
1462         /* Enable DCBx again, if all the TCs' strict priority disabled. */
1463         if (!tc_map) {
1464                 ret = i40e_aq_start_lldp(hw, NULL);
1465                 if (ret) {
1466                         PMD_DRV_LOG(ERR,
1467                                     "Failed to enable DCBx, err(%d).", ret);
1468                         return -EINVAL;
1469                 }
1470
1471                 PMD_DRV_LOG(INFO,
1472                             "DCBx is enabled again according to strict"
1473                             " priority setting.");
1474         }
1475
1476         return ret;
1477 }
1478
1479 #define I40E_PROFILE_INFO_SIZE sizeof(struct rte_pmd_i40e_profile_info)
1480 #define I40E_MAX_PROFILE_NUM 16
1481
1482 static void
1483 i40e_generate_profile_info_sec(char *name, struct i40e_ddp_version *version,
1484                                uint32_t track_id, uint8_t *profile_info_sec,
1485                                bool add)
1486 {
1487         struct i40e_profile_section_header *sec = NULL;
1488         struct i40e_profile_info *pinfo;
1489
1490         sec = (struct i40e_profile_section_header *)profile_info_sec;
1491         sec->tbl_size = 1;
1492         sec->data_end = sizeof(struct i40e_profile_section_header) +
1493                 sizeof(struct i40e_profile_info);
1494         sec->section.type = SECTION_TYPE_INFO;
1495         sec->section.offset = sizeof(struct i40e_profile_section_header);
1496         sec->section.size = sizeof(struct i40e_profile_info);
1497         pinfo = (struct i40e_profile_info *)(profile_info_sec +
1498                                              sec->section.offset);
1499         pinfo->track_id = track_id;
1500         memcpy(pinfo->name, name, I40E_DDP_NAME_SIZE);
1501         memcpy(&pinfo->version, version, sizeof(struct i40e_ddp_version));
1502         if (add)
1503                 pinfo->op = I40E_DDP_ADD_TRACKID;
1504         else
1505                 pinfo->op = I40E_DDP_REMOVE_TRACKID;
1506 }
1507
1508 static enum i40e_status_code
1509 i40e_add_rm_profile_info(struct i40e_hw *hw, uint8_t *profile_info_sec)
1510 {
1511         enum i40e_status_code status = I40E_SUCCESS;
1512         struct i40e_profile_section_header *sec;
1513         uint32_t track_id;
1514         uint32_t offset = 0;
1515         uint32_t info = 0;
1516
1517         sec = (struct i40e_profile_section_header *)profile_info_sec;
1518         track_id = ((struct i40e_profile_info *)(profile_info_sec +
1519                                          sec->section.offset))->track_id;
1520
1521         status = i40e_aq_write_ddp(hw, (void *)sec, sec->data_end,
1522                                    track_id, &offset, &info, NULL);
1523         if (status)
1524                 PMD_DRV_LOG(ERR, "Failed to add/remove profile info: "
1525                             "offset %d, info %d",
1526                             offset, info);
1527
1528         return status;
1529 }
1530
1531 /* Check if the profile info exists */
1532 static int
1533 i40e_check_profile_info(uint16_t port, uint8_t *profile_info_sec)
1534 {
1535         struct rte_eth_dev *dev = &rte_eth_devices[port];
1536         struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1537         uint8_t *buff;
1538         struct rte_pmd_i40e_profile_list *p_list;
1539         struct rte_pmd_i40e_profile_info *pinfo, *p;
1540         uint32_t i;
1541         int ret;
1542         static const uint32_t group_mask = 0x00ff0000;
1543
1544         pinfo = (struct rte_pmd_i40e_profile_info *)(profile_info_sec +
1545                              sizeof(struct i40e_profile_section_header));
1546         if (pinfo->track_id == 0) {
1547                 PMD_DRV_LOG(INFO, "Read-only profile.");
1548                 return 0;
1549         }
1550         buff = rte_zmalloc("pinfo_list",
1551                            (I40E_PROFILE_INFO_SIZE * I40E_MAX_PROFILE_NUM + 4),
1552                            0);
1553         if (!buff) {
1554                 PMD_DRV_LOG(ERR, "failed to allocate memory");
1555                 return -1;
1556         }
1557
1558         ret = i40e_aq_get_ddp_list(
1559                 hw, (void *)buff,
1560                 (I40E_PROFILE_INFO_SIZE * I40E_MAX_PROFILE_NUM + 4),
1561                 0, NULL);
1562         if (ret) {
1563                 PMD_DRV_LOG(ERR, "Failed to get profile info list.");
1564                 rte_free(buff);
1565                 return -1;
1566         }
1567         p_list = (struct rte_pmd_i40e_profile_list *)buff;
1568         for (i = 0; i < p_list->p_count; i++) {
1569                 p = &p_list->p_info[i];
1570                 if (pinfo->track_id == p->track_id) {
1571                         PMD_DRV_LOG(INFO, "Profile exists.");
1572                         rte_free(buff);
1573                         return 1;
1574                 }
1575         }
1576         /* profile with group id 0xff is compatible with any other profile */
1577         if ((pinfo->track_id & group_mask) == group_mask) {
1578                 rte_free(buff);
1579                 return 0;
1580         }
1581         for (i = 0; i < p_list->p_count; i++) {
1582                 p = &p_list->p_info[i];
1583                 if ((p->track_id & group_mask) == 0) {
1584                         PMD_DRV_LOG(INFO, "Profile of the group 0 exists.");
1585                         rte_free(buff);
1586                         return 2;
1587                 }
1588         }
1589         for (i = 0; i < p_list->p_count; i++) {
1590                 p = &p_list->p_info[i];
1591                 if ((p->track_id & group_mask) == group_mask)
1592                         continue;
1593                 if ((pinfo->track_id & group_mask) !=
1594                     (p->track_id & group_mask)) {
1595                         PMD_DRV_LOG(INFO, "Profile of different group exists.");
1596                         rte_free(buff);
1597                         return 3;
1598                 }
1599         }
1600
1601         rte_free(buff);
1602         return 0;
1603 }
1604
1605 int
1606 rte_pmd_i40e_process_ddp_package(uint16_t port, uint8_t *buff,
1607                                  uint32_t size,
1608                                  enum rte_pmd_i40e_package_op op)
1609 {
1610         struct rte_eth_dev *dev;
1611         struct i40e_hw *hw;
1612         struct i40e_package_header *pkg_hdr;
1613         struct i40e_generic_seg_header *profile_seg_hdr;
1614         struct i40e_generic_seg_header *metadata_seg_hdr;
1615         uint32_t track_id;
1616         uint8_t *profile_info_sec;
1617         int is_exist;
1618         enum i40e_status_code status = I40E_SUCCESS;
1619         static const uint32_t type_mask = 0xff000000;
1620
1621         if (op != RTE_PMD_I40E_PKG_OP_WR_ADD &&
1622                 op != RTE_PMD_I40E_PKG_OP_WR_ONLY &&
1623                 op != RTE_PMD_I40E_PKG_OP_WR_DEL) {
1624                 PMD_DRV_LOG(ERR, "Operation not supported.");
1625                 return -ENOTSUP;
1626         }
1627
1628         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
1629
1630         dev = &rte_eth_devices[port];
1631
1632         if (!is_i40e_supported(dev))
1633                 return -ENOTSUP;
1634
1635         hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1636
1637         if (size < (sizeof(struct i40e_package_header) +
1638                     sizeof(struct i40e_metadata_segment) +
1639                     sizeof(uint32_t) * 2)) {
1640                 PMD_DRV_LOG(ERR, "Buff is invalid.");
1641                 return -EINVAL;
1642         }
1643
1644         pkg_hdr = (struct i40e_package_header *)buff;
1645
1646         if (!pkg_hdr) {
1647                 PMD_DRV_LOG(ERR, "Failed to fill the package structure");
1648                 return -EINVAL;
1649         }
1650
1651         if (pkg_hdr->segment_count < 2) {
1652                 PMD_DRV_LOG(ERR, "Segment_count should be 2 at least.");
1653                 return -EINVAL;
1654         }
1655
1656         /* Find metadata segment */
1657         metadata_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_METADATA,
1658                                                         pkg_hdr);
1659         if (!metadata_seg_hdr) {
1660                 PMD_DRV_LOG(ERR, "Failed to find metadata segment header");
1661                 return -EINVAL;
1662         }
1663         track_id = ((struct i40e_metadata_segment *)metadata_seg_hdr)->track_id;
1664         if (track_id == I40E_DDP_TRACKID_INVALID) {
1665                 PMD_DRV_LOG(ERR, "Invalid track_id");
1666                 return -EINVAL;
1667         }
1668
1669         /* force read-only track_id for type 0 */
1670         if ((track_id & type_mask) == 0)
1671                 track_id = 0;
1672
1673         /* Find profile segment */
1674         profile_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_I40E,
1675                                                        pkg_hdr);
1676         if (!profile_seg_hdr) {
1677                 PMD_DRV_LOG(ERR, "Failed to find profile segment header");
1678                 return -EINVAL;
1679         }
1680
1681         profile_info_sec = rte_zmalloc(
1682                 "i40e_profile_info",
1683                 sizeof(struct i40e_profile_section_header) +
1684                 sizeof(struct i40e_profile_info),
1685                 0);
1686         if (!profile_info_sec) {
1687                 PMD_DRV_LOG(ERR, "Failed to allocate memory");
1688                 return -EINVAL;
1689         }
1690
1691         /* Check if the profile already loaded */
1692         i40e_generate_profile_info_sec(
1693                 ((struct i40e_profile_segment *)profile_seg_hdr)->name,
1694                 &((struct i40e_profile_segment *)profile_seg_hdr)->version,
1695                 track_id, profile_info_sec,
1696                 op == RTE_PMD_I40E_PKG_OP_WR_ADD);
1697         is_exist = i40e_check_profile_info(port, profile_info_sec);
1698         if (is_exist < 0) {
1699                 PMD_DRV_LOG(ERR, "Failed to check profile.");
1700                 rte_free(profile_info_sec);
1701                 return -EINVAL;
1702         }
1703
1704         if (op == RTE_PMD_I40E_PKG_OP_WR_ADD) {
1705                 if (is_exist) {
1706                         if (is_exist == 1)
1707                                 PMD_DRV_LOG(ERR, "Profile already exists.");
1708                         else if (is_exist == 2)
1709                                 PMD_DRV_LOG(ERR, "Profile of group 0 already exists.");
1710                         else if (is_exist == 3)
1711                                 PMD_DRV_LOG(ERR, "Profile of different group already exists");
1712                         i40e_update_customized_info(dev, buff, size, op);
1713                         rte_free(profile_info_sec);
1714                         return -EEXIST;
1715                 }
1716         } else if (op == RTE_PMD_I40E_PKG_OP_WR_DEL) {
1717                 if (is_exist != 1) {
1718                         PMD_DRV_LOG(ERR, "Profile does not exist.");
1719                         rte_free(profile_info_sec);
1720                         return -EACCES;
1721                 }
1722         }
1723
1724         if (op == RTE_PMD_I40E_PKG_OP_WR_DEL) {
1725                 status = i40e_rollback_profile(
1726                         hw,
1727                         (struct i40e_profile_segment *)profile_seg_hdr,
1728                         track_id);
1729                 if (status) {
1730                         PMD_DRV_LOG(ERR, "Failed to write profile for delete.");
1731                         rte_free(profile_info_sec);
1732                         return status;
1733                 }
1734         } else {
1735                 status = i40e_write_profile(
1736                         hw,
1737                         (struct i40e_profile_segment *)profile_seg_hdr,
1738                         track_id);
1739                 if (status) {
1740                         if (op == RTE_PMD_I40E_PKG_OP_WR_ADD)
1741                                 PMD_DRV_LOG(ERR, "Failed to write profile for add.");
1742                         else
1743                                 PMD_DRV_LOG(ERR, "Failed to write profile.");
1744                         rte_free(profile_info_sec);
1745                         return status;
1746                 }
1747         }
1748
1749         if (track_id && (op != RTE_PMD_I40E_PKG_OP_WR_ONLY)) {
1750                 /* Modify loaded profiles info list */
1751                 status = i40e_add_rm_profile_info(hw, profile_info_sec);
1752                 if (status) {
1753                         if (op == RTE_PMD_I40E_PKG_OP_WR_ADD)
1754                                 PMD_DRV_LOG(ERR, "Failed to add profile to info list.");
1755                         else
1756                                 PMD_DRV_LOG(ERR, "Failed to delete profile from info list.");
1757                 }
1758         }
1759
1760         if (op == RTE_PMD_I40E_PKG_OP_WR_ADD ||
1761             op == RTE_PMD_I40E_PKG_OP_WR_DEL)
1762                 i40e_update_customized_info(dev, buff, size, op);
1763
1764         rte_free(profile_info_sec);
1765         return status;
1766 }
1767
1768 /* Get number of tvl records in the section */
1769 static unsigned int
1770 i40e_get_tlv_section_size(struct i40e_profile_section_header *sec)
1771 {
1772         unsigned int i, nb_rec, nb_tlv = 0;
1773         struct i40e_profile_tlv_section_record *tlv;
1774
1775         if (!sec)
1776                 return nb_tlv;
1777
1778         /* get number of records in the section */
1779         nb_rec = sec->section.size /
1780                                 sizeof(struct i40e_profile_tlv_section_record);
1781         for (i = 0; i < nb_rec; ) {
1782                 tlv = (struct i40e_profile_tlv_section_record *)&sec[1 + i];
1783                 i += tlv->len;
1784                 nb_tlv++;
1785         }
1786         return nb_tlv;
1787 }
1788
1789 int rte_pmd_i40e_get_ddp_info(uint8_t *pkg_buff, uint32_t pkg_size,
1790         uint8_t *info_buff, uint32_t info_size,
1791         enum rte_pmd_i40e_package_info type)
1792 {
1793         uint32_t ret_size;
1794         struct i40e_package_header *pkg_hdr;
1795         struct i40e_generic_seg_header *i40e_seg_hdr;
1796         struct i40e_generic_seg_header *note_seg_hdr;
1797         struct i40e_generic_seg_header *metadata_seg_hdr;
1798
1799         if (!info_buff) {
1800                 PMD_DRV_LOG(ERR, "Output info buff is invalid.");
1801                 return -EINVAL;
1802         }
1803
1804         if (!pkg_buff || pkg_size < (sizeof(struct i40e_package_header) +
1805                 sizeof(struct i40e_metadata_segment) +
1806                 sizeof(uint32_t) * 2)) {
1807                 PMD_DRV_LOG(ERR, "Package buff is invalid.");
1808                 return -EINVAL;
1809         }
1810
1811         pkg_hdr = (struct i40e_package_header *)pkg_buff;
1812         if (pkg_hdr->segment_count < 2) {
1813                 PMD_DRV_LOG(ERR, "Segment_count should be 2 at least.");
1814                 return -EINVAL;
1815         }
1816
1817         /* Find metadata segment */
1818         metadata_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_METADATA,
1819                 pkg_hdr);
1820
1821         /* Find global notes segment */
1822         note_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_NOTES,
1823                 pkg_hdr);
1824
1825         /* Find i40e profile segment */
1826         i40e_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_I40E, pkg_hdr);
1827
1828         /* get global header info */
1829         if (type == RTE_PMD_I40E_PKG_INFO_GLOBAL_HEADER) {
1830                 struct rte_pmd_i40e_profile_info *info =
1831                         (struct rte_pmd_i40e_profile_info *)info_buff;
1832
1833                 if (info_size < sizeof(struct rte_pmd_i40e_profile_info)) {
1834                         PMD_DRV_LOG(ERR, "Output info buff size is invalid.");
1835                         return -EINVAL;
1836                 }
1837
1838                 if (!metadata_seg_hdr) {
1839                         PMD_DRV_LOG(ERR, "Failed to find metadata segment header");
1840                         return -EINVAL;
1841                 }
1842
1843                 memset(info, 0, sizeof(struct rte_pmd_i40e_profile_info));
1844                 info->owner = RTE_PMD_I40E_DDP_OWNER_UNKNOWN;
1845                 info->track_id =
1846                         ((struct i40e_metadata_segment *)metadata_seg_hdr)->track_id;
1847
1848                 memcpy(info->name,
1849                         ((struct i40e_metadata_segment *)metadata_seg_hdr)->name,
1850                         I40E_DDP_NAME_SIZE);
1851                 memcpy(&info->version,
1852                         &((struct i40e_metadata_segment *)metadata_seg_hdr)->version,
1853                         sizeof(struct i40e_ddp_version));
1854                 return I40E_SUCCESS;
1855         }
1856
1857         /* get global note size */
1858         if (type == RTE_PMD_I40E_PKG_INFO_GLOBAL_NOTES_SIZE) {
1859                 if (info_size < sizeof(uint32_t)) {
1860                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
1861                         return -EINVAL;
1862                 }
1863                 if (note_seg_hdr == NULL)
1864                         ret_size = 0;
1865                 else
1866                         ret_size = note_seg_hdr->size;
1867                 *(uint32_t *)info_buff = ret_size;
1868                 return I40E_SUCCESS;
1869         }
1870
1871         /* get global note */
1872         if (type == RTE_PMD_I40E_PKG_INFO_GLOBAL_NOTES) {
1873                 if (note_seg_hdr == NULL)
1874                         return -ENOTSUP;
1875                 if (info_size < note_seg_hdr->size) {
1876                         PMD_DRV_LOG(ERR, "Information buffer size is too small");
1877                         return -EINVAL;
1878                 }
1879                 memcpy(info_buff, &note_seg_hdr[1], note_seg_hdr->size);
1880                 return I40E_SUCCESS;
1881         }
1882
1883         /* get i40e segment header info */
1884         if (type == RTE_PMD_I40E_PKG_INFO_HEADER) {
1885                 struct rte_pmd_i40e_profile_info *info =
1886                         (struct rte_pmd_i40e_profile_info *)info_buff;
1887
1888                 if (info_size < sizeof(struct rte_pmd_i40e_profile_info)) {
1889                         PMD_DRV_LOG(ERR, "Output info buff size is invalid.");
1890                         return -EINVAL;
1891                 }
1892
1893                 if (!metadata_seg_hdr) {
1894                         PMD_DRV_LOG(ERR, "Failed to find metadata segment header");
1895                         return -EINVAL;
1896                 }
1897
1898                 if (!i40e_seg_hdr) {
1899                         PMD_DRV_LOG(ERR, "Failed to find i40e segment header");
1900                         return -EINVAL;
1901                 }
1902
1903                 memset(info, 0, sizeof(struct rte_pmd_i40e_profile_info));
1904                 info->owner = RTE_PMD_I40E_DDP_OWNER_UNKNOWN;
1905                 info->track_id =
1906                         ((struct i40e_metadata_segment *)metadata_seg_hdr)->track_id;
1907
1908                 memcpy(info->name,
1909                         ((struct i40e_profile_segment *)i40e_seg_hdr)->name,
1910                         I40E_DDP_NAME_SIZE);
1911                 memcpy(&info->version,
1912                         &((struct i40e_profile_segment *)i40e_seg_hdr)->version,
1913                         sizeof(struct i40e_ddp_version));
1914                 return I40E_SUCCESS;
1915         }
1916
1917         /* get number of devices */
1918         if (type == RTE_PMD_I40E_PKG_INFO_DEVID_NUM) {
1919                 if (info_size < sizeof(uint32_t)) {
1920                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
1921                         return -EINVAL;
1922                 }
1923                 *(uint32_t *)info_buff =
1924                         ((struct i40e_profile_segment *)i40e_seg_hdr)->device_table_count;
1925                 return I40E_SUCCESS;
1926         }
1927
1928         /* get list of devices */
1929         if (type == RTE_PMD_I40E_PKG_INFO_DEVID_LIST) {
1930                 uint32_t dev_num;
1931                 dev_num =
1932                         ((struct i40e_profile_segment *)i40e_seg_hdr)->device_table_count;
1933                 if (info_size < sizeof(struct rte_pmd_i40e_ddp_device_id) * dev_num) {
1934                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
1935                         return -EINVAL;
1936                 }
1937                 memcpy(info_buff,
1938                         ((struct i40e_profile_segment *)i40e_seg_hdr)->device_table,
1939                         sizeof(struct rte_pmd_i40e_ddp_device_id) * dev_num);
1940                 return I40E_SUCCESS;
1941         }
1942
1943         /* get number of protocols */
1944         if (type == RTE_PMD_I40E_PKG_INFO_PROTOCOL_NUM) {
1945                 struct i40e_profile_section_header *proto;
1946
1947                 if (info_size < sizeof(uint32_t)) {
1948                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
1949                         return -EINVAL;
1950                 }
1951                 proto = i40e_find_section_in_profile(SECTION_TYPE_PROTO,
1952                                 (struct i40e_profile_segment *)i40e_seg_hdr);
1953                 *(uint32_t *)info_buff = i40e_get_tlv_section_size(proto);
1954                 return I40E_SUCCESS;
1955         }
1956
1957         /* get list of protocols */
1958         if (type == RTE_PMD_I40E_PKG_INFO_PROTOCOL_LIST) {
1959                 uint32_t i, j, nb_tlv, nb_rec, nb_proto_info;
1960                 struct rte_pmd_i40e_proto_info *pinfo;
1961                 struct i40e_profile_section_header *proto;
1962                 struct i40e_profile_tlv_section_record *tlv;
1963
1964                 pinfo = (struct rte_pmd_i40e_proto_info *)info_buff;
1965                 nb_proto_info = info_size /
1966                                         sizeof(struct rte_pmd_i40e_proto_info);
1967                 for (i = 0; i < nb_proto_info; i++) {
1968                         pinfo[i].proto_id = RTE_PMD_I40E_PROTO_UNUSED;
1969                         memset(pinfo[i].name, 0, RTE_PMD_I40E_DDP_NAME_SIZE);
1970                 }
1971                 proto = i40e_find_section_in_profile(SECTION_TYPE_PROTO,
1972                                 (struct i40e_profile_segment *)i40e_seg_hdr);
1973                 nb_tlv = i40e_get_tlv_section_size(proto);
1974                 if (nb_tlv == 0)
1975                         return I40E_SUCCESS;
1976                 if (nb_proto_info < nb_tlv) {
1977                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
1978                         return -EINVAL;
1979                 }
1980                 /* get number of records in the section */
1981                 nb_rec = proto->section.size /
1982                                 sizeof(struct i40e_profile_tlv_section_record);
1983                 tlv = (struct i40e_profile_tlv_section_record *)&proto[1];
1984                 for (i = j = 0; i < nb_rec; j++) {
1985                         pinfo[j].proto_id = tlv->data[0];
1986                         snprintf(pinfo[j].name, I40E_DDP_NAME_SIZE, "%s",
1987                                  (const char *)&tlv->data[1]);
1988                         i += tlv->len;
1989                         tlv = &tlv[tlv->len];
1990                 }
1991                 return I40E_SUCCESS;
1992         }
1993
1994         /* get number of packet classification types */
1995         if (type == RTE_PMD_I40E_PKG_INFO_PCTYPE_NUM) {
1996                 struct i40e_profile_section_header *pctype;
1997
1998                 if (info_size < sizeof(uint32_t)) {
1999                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
2000                         return -EINVAL;
2001                 }
2002                 pctype = i40e_find_section_in_profile(SECTION_TYPE_PCTYPE,
2003                                 (struct i40e_profile_segment *)i40e_seg_hdr);
2004                 *(uint32_t *)info_buff = i40e_get_tlv_section_size(pctype);
2005                 return I40E_SUCCESS;
2006         }
2007
2008         /* get list of packet classification types */
2009         if (type == RTE_PMD_I40E_PKG_INFO_PCTYPE_LIST) {
2010                 uint32_t i, j, nb_tlv, nb_rec, nb_proto_info;
2011                 struct rte_pmd_i40e_ptype_info *pinfo;
2012                 struct i40e_profile_section_header *pctype;
2013                 struct i40e_profile_tlv_section_record *tlv;
2014
2015                 pinfo = (struct rte_pmd_i40e_ptype_info *)info_buff;
2016                 nb_proto_info = info_size /
2017                                         sizeof(struct rte_pmd_i40e_ptype_info);
2018                 for (i = 0; i < nb_proto_info; i++)
2019                         memset(&pinfo[i], RTE_PMD_I40E_PROTO_UNUSED,
2020                                sizeof(struct rte_pmd_i40e_ptype_info));
2021                 pctype = i40e_find_section_in_profile(SECTION_TYPE_PCTYPE,
2022                                 (struct i40e_profile_segment *)i40e_seg_hdr);
2023                 nb_tlv = i40e_get_tlv_section_size(pctype);
2024                 if (nb_tlv == 0)
2025                         return I40E_SUCCESS;
2026                 if (nb_proto_info < nb_tlv) {
2027                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
2028                         return -EINVAL;
2029                 }
2030
2031                 /* get number of records in the section */
2032                 nb_rec = pctype->section.size /
2033                                 sizeof(struct i40e_profile_tlv_section_record);
2034                 tlv = (struct i40e_profile_tlv_section_record *)&pctype[1];
2035                 for (i = j = 0; i < nb_rec; j++) {
2036                         memcpy(&pinfo[j], tlv->data,
2037                                sizeof(struct rte_pmd_i40e_ptype_info));
2038                         i += tlv->len;
2039                         tlv = &tlv[tlv->len];
2040                 }
2041                 return I40E_SUCCESS;
2042         }
2043
2044         /* get number of packet types */
2045         if (type == RTE_PMD_I40E_PKG_INFO_PTYPE_NUM) {
2046                 struct i40e_profile_section_header *ptype;
2047
2048                 if (info_size < sizeof(uint32_t)) {
2049                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
2050                         return -EINVAL;
2051                 }
2052                 ptype = i40e_find_section_in_profile(SECTION_TYPE_PTYPE,
2053                                 (struct i40e_profile_segment *)i40e_seg_hdr);
2054                 *(uint32_t *)info_buff = i40e_get_tlv_section_size(ptype);
2055                 return I40E_SUCCESS;
2056         }
2057
2058         /* get list of packet types */
2059         if (type == RTE_PMD_I40E_PKG_INFO_PTYPE_LIST) {
2060                 uint32_t i, j, nb_tlv, nb_rec, nb_proto_info;
2061                 struct rte_pmd_i40e_ptype_info *pinfo;
2062                 struct i40e_profile_section_header *ptype;
2063                 struct i40e_profile_tlv_section_record *tlv;
2064
2065                 pinfo = (struct rte_pmd_i40e_ptype_info *)info_buff;
2066                 nb_proto_info = info_size /
2067                                         sizeof(struct rte_pmd_i40e_ptype_info);
2068                 for (i = 0; i < nb_proto_info; i++)
2069                         memset(&pinfo[i], RTE_PMD_I40E_PROTO_UNUSED,
2070                                sizeof(struct rte_pmd_i40e_ptype_info));
2071                 ptype = i40e_find_section_in_profile(SECTION_TYPE_PTYPE,
2072                                 (struct i40e_profile_segment *)i40e_seg_hdr);
2073                 nb_tlv = i40e_get_tlv_section_size(ptype);
2074                 if (nb_tlv == 0)
2075                         return I40E_SUCCESS;
2076                 if (nb_proto_info < nb_tlv) {
2077                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
2078                         return -EINVAL;
2079                 }
2080                 /* get number of records in the section */
2081                 nb_rec = ptype->section.size /
2082                                 sizeof(struct i40e_profile_tlv_section_record);
2083                 for (i = j = 0; i < nb_rec; j++) {
2084                         tlv = (struct i40e_profile_tlv_section_record *)
2085                                                                 &ptype[1 + i];
2086                         memcpy(&pinfo[j], tlv->data,
2087                                sizeof(struct rte_pmd_i40e_ptype_info));
2088                         i += tlv->len;
2089                 }
2090                 return I40E_SUCCESS;
2091         }
2092
2093         PMD_DRV_LOG(ERR, "Info type %u is invalid.", type);
2094         return -EINVAL;
2095 }
2096
2097 int
2098 rte_pmd_i40e_get_ddp_list(uint16_t port, uint8_t *buff, uint32_t size)
2099 {
2100         struct rte_eth_dev *dev;
2101         struct i40e_hw *hw;
2102         enum i40e_status_code status = I40E_SUCCESS;
2103
2104         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2105
2106         dev = &rte_eth_devices[port];
2107
2108         if (!is_i40e_supported(dev))
2109                 return -ENOTSUP;
2110
2111         if (size < (I40E_PROFILE_INFO_SIZE * I40E_MAX_PROFILE_NUM + 4))
2112                 return -EINVAL;
2113
2114         hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
2115
2116         status = i40e_aq_get_ddp_list(hw, (void *)buff,
2117                                       size, 0, NULL);
2118
2119         return status;
2120 }
2121
2122 static int check_invalid_pkt_type(uint32_t pkt_type)
2123 {
2124         uint32_t l2, l3, l4, tnl, il2, il3, il4;
2125
2126         l2 = pkt_type & RTE_PTYPE_L2_MASK;
2127         l3 = pkt_type & RTE_PTYPE_L3_MASK;
2128         l4 = pkt_type & RTE_PTYPE_L4_MASK;
2129         tnl = pkt_type & RTE_PTYPE_TUNNEL_MASK;
2130         il2 = pkt_type & RTE_PTYPE_INNER_L2_MASK;
2131         il3 = pkt_type & RTE_PTYPE_INNER_L3_MASK;
2132         il4 = pkt_type & RTE_PTYPE_INNER_L4_MASK;
2133
2134         if (l2 &&
2135             l2 != RTE_PTYPE_L2_ETHER &&
2136             l2 != RTE_PTYPE_L2_ETHER_TIMESYNC &&
2137             l2 != RTE_PTYPE_L2_ETHER_ARP &&
2138             l2 != RTE_PTYPE_L2_ETHER_LLDP &&
2139             l2 != RTE_PTYPE_L2_ETHER_NSH &&
2140             l2 != RTE_PTYPE_L2_ETHER_VLAN &&
2141             l2 != RTE_PTYPE_L2_ETHER_QINQ &&
2142             l2 != RTE_PTYPE_L2_ETHER_PPPOE)
2143                 return -1;
2144
2145         if (l3 &&
2146             l3 != RTE_PTYPE_L3_IPV4 &&
2147             l3 != RTE_PTYPE_L3_IPV4_EXT &&
2148             l3 != RTE_PTYPE_L3_IPV6 &&
2149             l3 != RTE_PTYPE_L3_IPV4_EXT_UNKNOWN &&
2150             l3 != RTE_PTYPE_L3_IPV6_EXT &&
2151             l3 != RTE_PTYPE_L3_IPV6_EXT_UNKNOWN)
2152                 return -1;
2153
2154         if (l4 &&
2155             l4 != RTE_PTYPE_L4_TCP &&
2156             l4 != RTE_PTYPE_L4_UDP &&
2157             l4 != RTE_PTYPE_L4_FRAG &&
2158             l4 != RTE_PTYPE_L4_SCTP &&
2159             l4 != RTE_PTYPE_L4_ICMP &&
2160             l4 != RTE_PTYPE_L4_NONFRAG)
2161                 return -1;
2162
2163         if (tnl &&
2164             tnl != RTE_PTYPE_TUNNEL_IP &&
2165             tnl != RTE_PTYPE_TUNNEL_GRENAT &&
2166             tnl != RTE_PTYPE_TUNNEL_VXLAN &&
2167             tnl != RTE_PTYPE_TUNNEL_NVGRE &&
2168             tnl != RTE_PTYPE_TUNNEL_GENEVE &&
2169             tnl != RTE_PTYPE_TUNNEL_GRENAT &&
2170             tnl != RTE_PTYPE_TUNNEL_GTPC &&
2171             tnl != RTE_PTYPE_TUNNEL_GTPU &&
2172             tnl != RTE_PTYPE_TUNNEL_L2TP)
2173                 return -1;
2174
2175         if (il2 &&
2176             il2 != RTE_PTYPE_INNER_L2_ETHER &&
2177             il2 != RTE_PTYPE_INNER_L2_ETHER_VLAN &&
2178             il2 != RTE_PTYPE_INNER_L2_ETHER_QINQ)
2179                 return -1;
2180
2181         if (il3 &&
2182             il3 != RTE_PTYPE_INNER_L3_IPV4 &&
2183             il3 != RTE_PTYPE_INNER_L3_IPV4_EXT &&
2184             il3 != RTE_PTYPE_INNER_L3_IPV6 &&
2185             il3 != RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN &&
2186             il3 != RTE_PTYPE_INNER_L3_IPV6_EXT &&
2187             il3 != RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN)
2188                 return -1;
2189
2190         if (il4 &&
2191             il4 != RTE_PTYPE_INNER_L4_TCP &&
2192             il4 != RTE_PTYPE_INNER_L4_UDP &&
2193             il4 != RTE_PTYPE_INNER_L4_FRAG &&
2194             il4 != RTE_PTYPE_INNER_L4_SCTP &&
2195             il4 != RTE_PTYPE_INNER_L4_ICMP &&
2196             il4 != RTE_PTYPE_INNER_L4_NONFRAG)
2197                 return -1;
2198
2199         return 0;
2200 }
2201
2202 static int check_invalid_ptype_mapping(
2203                 struct rte_pmd_i40e_ptype_mapping *mapping_table,
2204                 uint16_t count)
2205 {
2206         int i;
2207
2208         for (i = 0; i < count; i++) {
2209                 uint16_t ptype = mapping_table[i].hw_ptype;
2210                 uint32_t pkt_type = mapping_table[i].sw_ptype;
2211
2212                 if (ptype >= I40E_MAX_PKT_TYPE)
2213                         return -1;
2214
2215                 if (pkt_type == RTE_PTYPE_UNKNOWN)
2216                         continue;
2217
2218                 if (pkt_type & RTE_PMD_I40E_PTYPE_USER_DEFINE_MASK)
2219                         continue;
2220
2221                 if (check_invalid_pkt_type(pkt_type))
2222                         return -1;
2223         }
2224
2225         return 0;
2226 }
2227
2228 int
2229 rte_pmd_i40e_ptype_mapping_update(
2230                         uint16_t port,
2231                         struct rte_pmd_i40e_ptype_mapping *mapping_items,
2232                         uint16_t count,
2233                         uint8_t exclusive)
2234 {
2235         struct rte_eth_dev *dev;
2236         struct i40e_adapter *ad;
2237         int i;
2238
2239         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2240
2241         dev = &rte_eth_devices[port];
2242
2243         if (!is_i40e_supported(dev))
2244                 return -ENOTSUP;
2245
2246         if (count > I40E_MAX_PKT_TYPE)
2247                 return -EINVAL;
2248
2249         if (check_invalid_ptype_mapping(mapping_items, count))
2250                 return -EINVAL;
2251
2252         ad = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
2253
2254         if (exclusive) {
2255                 for (i = 0; i < I40E_MAX_PKT_TYPE; i++)
2256                         ad->ptype_tbl[i] = RTE_PTYPE_UNKNOWN;
2257         }
2258
2259         for (i = 0; i < count; i++)
2260                 ad->ptype_tbl[mapping_items[i].hw_ptype]
2261                         = mapping_items[i].sw_ptype;
2262
2263         return 0;
2264 }
2265
2266 int rte_pmd_i40e_ptype_mapping_reset(uint16_t port)
2267 {
2268         struct rte_eth_dev *dev;
2269
2270         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2271
2272         dev = &rte_eth_devices[port];
2273
2274         if (!is_i40e_supported(dev))
2275                 return -ENOTSUP;
2276
2277         i40e_set_default_ptype_table(dev);
2278
2279         return 0;
2280 }
2281
2282 int rte_pmd_i40e_ptype_mapping_get(
2283                         uint16_t port,
2284                         struct rte_pmd_i40e_ptype_mapping *mapping_items,
2285                         uint16_t size,
2286                         uint16_t *count,
2287                         uint8_t valid_only)
2288 {
2289         struct rte_eth_dev *dev;
2290         struct i40e_adapter *ad;
2291         int n = 0;
2292         uint16_t i;
2293
2294         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2295
2296         dev = &rte_eth_devices[port];
2297
2298         if (!is_i40e_supported(dev))
2299                 return -ENOTSUP;
2300
2301         ad = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
2302
2303         for (i = 0; i < I40E_MAX_PKT_TYPE; i++) {
2304                 if (n >= size)
2305                         break;
2306                 if (valid_only && ad->ptype_tbl[i] == RTE_PTYPE_UNKNOWN)
2307                         continue;
2308                 mapping_items[n].hw_ptype = i;
2309                 mapping_items[n].sw_ptype = ad->ptype_tbl[i];
2310                 n++;
2311         }
2312
2313         *count = n;
2314         return 0;
2315 }
2316
2317 int rte_pmd_i40e_ptype_mapping_replace(uint16_t port,
2318                                        uint32_t target,
2319                                        uint8_t mask,
2320                                        uint32_t pkt_type)
2321 {
2322         struct rte_eth_dev *dev;
2323         struct i40e_adapter *ad;
2324         uint16_t i;
2325
2326         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2327
2328         dev = &rte_eth_devices[port];
2329
2330         if (!is_i40e_supported(dev))
2331                 return -ENOTSUP;
2332
2333         if (!mask && check_invalid_pkt_type(target))
2334                 return -EINVAL;
2335
2336         if (check_invalid_pkt_type(pkt_type))
2337                 return -EINVAL;
2338
2339         ad = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
2340
2341         for (i = 0; i < I40E_MAX_PKT_TYPE; i++) {
2342                 if (mask) {
2343                         if ((target | ad->ptype_tbl[i]) == target &&
2344                             (target & ad->ptype_tbl[i]))
2345                                 ad->ptype_tbl[i] = pkt_type;
2346                 } else {
2347                         if (ad->ptype_tbl[i] == target)
2348                                 ad->ptype_tbl[i] = pkt_type;
2349                 }
2350         }
2351
2352         return 0;
2353 }
2354
2355 int
2356 rte_pmd_i40e_add_vf_mac_addr(uint16_t port, uint16_t vf_id,
2357                              struct ether_addr *mac_addr)
2358 {
2359         struct rte_eth_dev *dev;
2360         struct i40e_pf_vf *vf;
2361         struct i40e_vsi *vsi;
2362         struct i40e_pf *pf;
2363         struct i40e_mac_filter_info mac_filter;
2364         int ret;
2365
2366         if (i40e_validate_mac_addr((u8 *)mac_addr) != I40E_SUCCESS)
2367                 return -EINVAL;
2368
2369         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2370
2371         dev = &rte_eth_devices[port];
2372
2373         if (!is_i40e_supported(dev))
2374                 return -ENOTSUP;
2375
2376         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
2377
2378         if (vf_id >= pf->vf_num || !pf->vfs)
2379                 return -EINVAL;
2380
2381         vf = &pf->vfs[vf_id];
2382         vsi = vf->vsi;
2383         if (!vsi) {
2384                 PMD_DRV_LOG(ERR, "Invalid VSI.");
2385                 return -EINVAL;
2386         }
2387
2388         mac_filter.filter_type = RTE_MACVLAN_PERFECT_MATCH;
2389         ether_addr_copy(mac_addr, &mac_filter.mac_addr);
2390         ret = i40e_vsi_add_mac(vsi, &mac_filter);
2391         if (ret != I40E_SUCCESS) {
2392                 PMD_DRV_LOG(ERR, "Failed to add MAC filter.");
2393                 return -1;
2394         }
2395
2396         return 0;
2397 }
2398
2399 int rte_pmd_i40e_flow_type_mapping_reset(uint16_t port)
2400 {
2401         struct rte_eth_dev *dev;
2402
2403         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2404
2405         dev = &rte_eth_devices[port];
2406
2407         if (!is_i40e_supported(dev))
2408                 return -ENOTSUP;
2409
2410         i40e_set_default_pctype_table(dev);
2411
2412         return 0;
2413 }
2414
2415 int rte_pmd_i40e_flow_type_mapping_get(
2416                         uint16_t port,
2417                         struct rte_pmd_i40e_flow_type_mapping *mapping_items)
2418 {
2419         struct rte_eth_dev *dev;
2420         struct i40e_adapter *ad;
2421         uint16_t i;
2422
2423         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2424
2425         dev = &rte_eth_devices[port];
2426
2427         if (!is_i40e_supported(dev))
2428                 return -ENOTSUP;
2429
2430         ad = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
2431
2432         for (i = 0; i < I40E_FLOW_TYPE_MAX; i++) {
2433                 mapping_items[i].flow_type = i;
2434                 mapping_items[i].pctype = ad->pctypes_tbl[i];
2435         }
2436
2437         return 0;
2438 }
2439
2440 int
2441 rte_pmd_i40e_flow_type_mapping_update(
2442                         uint16_t port,
2443                         struct rte_pmd_i40e_flow_type_mapping *mapping_items,
2444                         uint16_t count,
2445                         uint8_t exclusive)
2446 {
2447         struct rte_eth_dev *dev;
2448         struct i40e_adapter *ad;
2449         int i;
2450
2451         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2452
2453         dev = &rte_eth_devices[port];
2454
2455         if (!is_i40e_supported(dev))
2456                 return -ENOTSUP;
2457
2458         if (count > I40E_FLOW_TYPE_MAX)
2459                 return -EINVAL;
2460
2461         for (i = 0; i < count; i++)
2462                 if (mapping_items[i].flow_type >= I40E_FLOW_TYPE_MAX ||
2463                     mapping_items[i].flow_type == RTE_ETH_FLOW_UNKNOWN ||
2464                     (mapping_items[i].pctype &
2465                     (1ULL << I40E_FILTER_PCTYPE_INVALID)))
2466                         return -EINVAL;
2467
2468         ad = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
2469
2470         if (exclusive) {
2471                 for (i = 0; i < I40E_FLOW_TYPE_MAX; i++)
2472                         ad->pctypes_tbl[i] = 0ULL;
2473                 ad->flow_types_mask = 0ULL;
2474         }
2475
2476         for (i = 0; i < count; i++) {
2477                 ad->pctypes_tbl[mapping_items[i].flow_type] =
2478                                                 mapping_items[i].pctype;
2479                 if (mapping_items[i].pctype)
2480                         ad->flow_types_mask |=
2481                                         (1ULL << mapping_items[i].flow_type);
2482                 else
2483                         ad->flow_types_mask &=
2484                                         ~(1ULL << mapping_items[i].flow_type);
2485         }
2486
2487         for (i = 0, ad->pctypes_mask = 0ULL; i < I40E_FLOW_TYPE_MAX; i++)
2488                 ad->pctypes_mask |= ad->pctypes_tbl[i];
2489
2490         return 0;
2491 }
2492
2493 int
2494 rte_pmd_i40e_query_vfid_by_mac(uint16_t port, const struct ether_addr *vf_mac)
2495 {
2496         struct rte_eth_dev *dev;
2497         struct ether_addr *mac;
2498         struct i40e_pf *pf;
2499         int vf_id;
2500         struct i40e_pf_vf *vf;
2501         uint16_t vf_num;
2502
2503         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2504         dev = &rte_eth_devices[port];
2505
2506         if (!is_i40e_supported(dev))
2507                 return -ENOTSUP;
2508
2509         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
2510         vf_num = pf->vf_num;
2511
2512         for (vf_id = 0; vf_id < vf_num; vf_id++) {
2513                 vf = &pf->vfs[vf_id];
2514                 mac = &vf->mac_addr;
2515
2516                 if (is_same_ether_addr(mac, vf_mac))
2517                         return vf_id;
2518         }
2519
2520         return -EINVAL;
2521 }
2522
2523 static int
2524 i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,
2525                               struct i40e_pf *pf)
2526 {
2527         uint16_t i;
2528         struct i40e_vsi *vsi = pf->main_vsi;
2529         uint16_t queue_offset, bsf, tc_index;
2530         struct i40e_vsi_context ctxt;
2531         struct i40e_aqc_vsi_properties_data *vsi_info;
2532         struct i40e_queue_regions *region_info =
2533                                 &pf->queue_region;
2534         int32_t ret = -EINVAL;
2535
2536         if (!region_info->queue_region_number) {
2537                 PMD_INIT_LOG(ERR, "there is no that region id been set before");
2538                 return ret;
2539         }
2540
2541         memset(&ctxt, 0, sizeof(struct i40e_vsi_context));
2542
2543         /* Update Queue Pairs Mapping for currently enabled UPs */
2544         ctxt.seid = vsi->seid;
2545         ctxt.pf_num = hw->pf_id;
2546         ctxt.vf_num = 0;
2547         ctxt.uplink_seid = vsi->uplink_seid;
2548         ctxt.info = vsi->info;
2549         vsi_info = &ctxt.info;
2550
2551         memset(vsi_info->tc_mapping, 0, sizeof(uint16_t) * 8);
2552         memset(vsi_info->queue_mapping, 0, sizeof(uint16_t) * 16);
2553
2554         /* Configure queue region and queue mapping parameters,
2555          * for enabled queue region, allocate queues to this region.
2556          */
2557
2558         for (i = 0; i < region_info->queue_region_number; i++) {
2559                 tc_index = region_info->region[i].region_id;
2560                 bsf = rte_bsf32(region_info->region[i].queue_num);
2561                 queue_offset = region_info->region[i].queue_start_index;
2562                 vsi_info->tc_mapping[tc_index] = rte_cpu_to_le_16(
2563                         (queue_offset << I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |
2564                                 (bsf << I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT));
2565         }
2566
2567         /* Associate queue number with VSI, Keep vsi->nb_qps unchanged */
2568         vsi_info->mapping_flags |=
2569                         rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_CONTIG);
2570         vsi_info->queue_mapping[0] = rte_cpu_to_le_16(vsi->base_queue);
2571         vsi_info->valid_sections |=
2572                 rte_cpu_to_le_16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID);
2573
2574         /* Update the VSI after updating the VSI queue-mapping information */
2575         ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
2576         if (ret) {
2577                 PMD_DRV_LOG(ERR, "Failed to configure queue region mapping = %d ",
2578                                 hw->aq.asq_last_status);
2579                 return ret;
2580         }
2581         /* update the local VSI info with updated queue map */
2582         rte_memcpy(&vsi->info.tc_mapping, &ctxt.info.tc_mapping,
2583                                         sizeof(vsi->info.tc_mapping));
2584         rte_memcpy(&vsi->info.queue_mapping,
2585                         &ctxt.info.queue_mapping,
2586                         sizeof(vsi->info.queue_mapping));
2587         vsi->info.mapping_flags = ctxt.info.mapping_flags;
2588         vsi->info.valid_sections = 0;
2589
2590         return 0;
2591 }
2592
2593
2594 static int
2595 i40e_queue_region_set_region(struct i40e_pf *pf,
2596                                 struct rte_pmd_i40e_queue_region_conf *conf_ptr)
2597 {
2598         uint16_t i;
2599         struct i40e_vsi *main_vsi = pf->main_vsi;
2600         struct i40e_queue_regions *info = &pf->queue_region;
2601         int32_t ret = -EINVAL;
2602
2603         if (!((rte_is_power_of_2(conf_ptr->queue_num)) &&
2604                                 conf_ptr->queue_num <= 64)) {
2605                 PMD_DRV_LOG(ERR, "The region sizes should be any of the following values: 1, 2, 4, 8, 16, 32, 64 as long as the "
2606                         "total number of queues do not exceed the VSI allocation");
2607                 return ret;
2608         }
2609
2610         if (conf_ptr->region_id > I40E_REGION_MAX_INDEX) {
2611                 PMD_DRV_LOG(ERR, "the queue region max index is 7");
2612                 return ret;
2613         }
2614
2615         if ((conf_ptr->queue_start_index + conf_ptr->queue_num)
2616                                         > main_vsi->nb_used_qps) {
2617                 PMD_DRV_LOG(ERR, "the queue index exceeds the VSI range");
2618                 return ret;
2619         }
2620
2621         for (i = 0; i < info->queue_region_number; i++)
2622                 if (conf_ptr->region_id == info->region[i].region_id)
2623                         break;
2624
2625         if (i == info->queue_region_number &&
2626                                 i <= I40E_REGION_MAX_INDEX) {
2627                 info->region[i].region_id = conf_ptr->region_id;
2628                 info->region[i].queue_num = conf_ptr->queue_num;
2629                 info->region[i].queue_start_index =
2630                         conf_ptr->queue_start_index;
2631                 info->queue_region_number++;
2632         } else {
2633                 PMD_DRV_LOG(ERR, "queue region number exceeds maxnum 8 or the queue region id has been set before");
2634                 return ret;
2635         }
2636
2637         return 0;
2638 }
2639
2640 static int
2641 i40e_queue_region_set_flowtype(struct i40e_pf *pf,
2642                         struct rte_pmd_i40e_queue_region_conf *rss_region_conf)
2643 {
2644         int32_t ret = -EINVAL;
2645         struct i40e_queue_regions *info = &pf->queue_region;
2646         uint16_t i, j;
2647         uint16_t region_index, flowtype_index;
2648
2649         /* For the pctype or hardware flowtype of packet,
2650          * the specific index for each type has been defined
2651          * in file i40e_type.h as enum i40e_filter_pctype.
2652          */
2653
2654         if (rss_region_conf->region_id > I40E_PFQF_HREGION_MAX_INDEX) {
2655                 PMD_DRV_LOG(ERR, "the queue region max index is 7");
2656                 return ret;
2657         }
2658
2659         if (rss_region_conf->hw_flowtype >= I40E_FILTER_PCTYPE_MAX) {
2660                 PMD_DRV_LOG(ERR, "the hw_flowtype or PCTYPE max index is 63");
2661                 return ret;
2662         }
2663
2664
2665         for (i = 0; i < info->queue_region_number; i++)
2666                 if (rss_region_conf->region_id == info->region[i].region_id)
2667                         break;
2668
2669         if (i == info->queue_region_number) {
2670                 PMD_DRV_LOG(ERR, "that region id has not been set before");
2671                 ret = -EINVAL;
2672                 return ret;
2673         }
2674         region_index = i;
2675
2676         for (i = 0; i < info->queue_region_number; i++) {
2677                 for (j = 0; j < info->region[i].flowtype_num; j++) {
2678                         if (rss_region_conf->hw_flowtype ==
2679                                 info->region[i].hw_flowtype[j]) {
2680                                 PMD_DRV_LOG(ERR, "that hw_flowtype has been set before");
2681                                 return 0;
2682                         }
2683                 }
2684         }
2685
2686         flowtype_index = info->region[region_index].flowtype_num;
2687         info->region[region_index].hw_flowtype[flowtype_index] =
2688                                         rss_region_conf->hw_flowtype;
2689         info->region[region_index].flowtype_num++;
2690
2691         return 0;
2692 }
2693
2694 static void
2695 i40e_queue_region_pf_flowtype_conf(struct i40e_hw *hw,
2696                                 struct i40e_pf *pf)
2697 {
2698         uint8_t hw_flowtype;
2699         uint32_t pfqf_hregion;
2700         uint16_t i, j, index;
2701         struct i40e_queue_regions *info = &pf->queue_region;
2702
2703         /* For the pctype or hardware flowtype of packet,
2704          * the specific index for each type has been defined
2705          * in file i40e_type.h as enum i40e_filter_pctype.
2706          */
2707
2708         for (i = 0; i < info->queue_region_number; i++) {
2709                 for (j = 0; j < info->region[i].flowtype_num; j++) {
2710                         hw_flowtype = info->region[i].hw_flowtype[j];
2711                         index = hw_flowtype >> 3;
2712                         pfqf_hregion =
2713                                 i40e_read_rx_ctl(hw, I40E_PFQF_HREGION(index));
2714
2715                         if ((hw_flowtype & 0x7) == 0) {
2716                                 pfqf_hregion |= info->region[i].region_id <<
2717                                         I40E_PFQF_HREGION_REGION_0_SHIFT;
2718                                 pfqf_hregion |= 1 <<
2719                                         I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT;
2720                         } else if ((hw_flowtype & 0x7) == 1) {
2721                                 pfqf_hregion |= info->region[i].region_id  <<
2722                                         I40E_PFQF_HREGION_REGION_1_SHIFT;
2723                                 pfqf_hregion |= 1 <<
2724                                         I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT;
2725                         } else if ((hw_flowtype & 0x7) == 2) {
2726                                 pfqf_hregion |= info->region[i].region_id  <<
2727                                         I40E_PFQF_HREGION_REGION_2_SHIFT;
2728                                 pfqf_hregion |= 1 <<
2729                                         I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT;
2730                         } else if ((hw_flowtype & 0x7) == 3) {
2731                                 pfqf_hregion |= info->region[i].region_id  <<
2732                                         I40E_PFQF_HREGION_REGION_3_SHIFT;
2733                                 pfqf_hregion |= 1 <<
2734                                         I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT;
2735                         } else if ((hw_flowtype & 0x7) == 4) {
2736                                 pfqf_hregion |= info->region[i].region_id  <<
2737                                         I40E_PFQF_HREGION_REGION_4_SHIFT;
2738                                 pfqf_hregion |= 1 <<
2739                                         I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT;
2740                         } else if ((hw_flowtype & 0x7) == 5) {
2741                                 pfqf_hregion |= info->region[i].region_id  <<
2742                                         I40E_PFQF_HREGION_REGION_5_SHIFT;
2743                                 pfqf_hregion |= 1 <<
2744                                         I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT;
2745                         } else if ((hw_flowtype & 0x7) == 6) {
2746                                 pfqf_hregion |= info->region[i].region_id  <<
2747                                         I40E_PFQF_HREGION_REGION_6_SHIFT;
2748                                 pfqf_hregion |= 1 <<
2749                                         I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT;
2750                         } else {
2751                                 pfqf_hregion |= info->region[i].region_id  <<
2752                                         I40E_PFQF_HREGION_REGION_7_SHIFT;
2753                                 pfqf_hregion |= 1 <<
2754                                         I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT;
2755                         }
2756
2757                         i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(index),
2758                                                 pfqf_hregion);
2759                 }
2760         }
2761 }
2762
2763 static int
2764 i40e_queue_region_set_user_priority(struct i40e_pf *pf,
2765                 struct rte_pmd_i40e_queue_region_conf *rss_region_conf)
2766 {
2767         struct i40e_queue_regions *info = &pf->queue_region;
2768         int32_t ret = -EINVAL;
2769         uint16_t i, j, region_index;
2770
2771         if (rss_region_conf->user_priority >= I40E_MAX_USER_PRIORITY) {
2772                 PMD_DRV_LOG(ERR, "the queue region max index is 7");
2773                 return ret;
2774         }
2775
2776         if (rss_region_conf->region_id > I40E_REGION_MAX_INDEX) {
2777                 PMD_DRV_LOG(ERR, "the region_id max index is 7");
2778                 return ret;
2779         }
2780
2781         for (i = 0; i < info->queue_region_number; i++)
2782                 if (rss_region_conf->region_id == info->region[i].region_id)
2783                         break;
2784
2785         if (i == info->queue_region_number) {
2786                 PMD_DRV_LOG(ERR, "that region id has not been set before");
2787                 ret = -EINVAL;
2788                 return ret;
2789         }
2790
2791         region_index = i;
2792
2793         for (i = 0; i < info->queue_region_number; i++) {
2794                 for (j = 0; j < info->region[i].user_priority_num; j++) {
2795                         if (info->region[i].user_priority[j] ==
2796                                 rss_region_conf->user_priority) {
2797                                 PMD_DRV_LOG(ERR, "that user priority has been set before");
2798                                 return 0;
2799                         }
2800                 }
2801         }
2802
2803         j = info->region[region_index].user_priority_num;
2804         info->region[region_index].user_priority[j] =
2805                                         rss_region_conf->user_priority;
2806         info->region[region_index].user_priority_num++;
2807
2808         return 0;
2809 }
2810
2811 static int
2812 i40e_queue_region_dcb_configure(struct i40e_hw *hw,
2813                                 struct i40e_pf *pf)
2814 {
2815         struct i40e_dcbx_config dcb_cfg_local;
2816         struct i40e_dcbx_config *dcb_cfg;
2817         struct i40e_queue_regions *info = &pf->queue_region;
2818         struct i40e_dcbx_config *old_cfg = &hw->local_dcbx_config;
2819         int32_t ret = -EINVAL;
2820         uint16_t i, j, prio_index, region_index;
2821         uint8_t tc_map, tc_bw, bw_lf;
2822
2823         if (!info->queue_region_number) {
2824                 PMD_DRV_LOG(ERR, "No queue region been set before");
2825                 return ret;
2826         }
2827
2828         dcb_cfg = &dcb_cfg_local;
2829         memset(dcb_cfg, 0, sizeof(struct i40e_dcbx_config));
2830
2831         /* assume each tc has the same bw */
2832         tc_bw = I40E_MAX_PERCENT / info->queue_region_number;
2833         for (i = 0; i < info->queue_region_number; i++)
2834                 dcb_cfg->etscfg.tcbwtable[i] = tc_bw;
2835         /* to ensure the sum of tcbw is equal to 100 */
2836         bw_lf = I40E_MAX_PERCENT %  info->queue_region_number;
2837         for (i = 0; i < bw_lf; i++)
2838                 dcb_cfg->etscfg.tcbwtable[i]++;
2839
2840         /* assume each tc has the same Transmission Selection Algorithm */
2841         for (i = 0; i < info->queue_region_number; i++)
2842                 dcb_cfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
2843
2844         for (i = 0; i < info->queue_region_number; i++) {
2845                 for (j = 0; j < info->region[i].user_priority_num; j++) {
2846                         prio_index = info->region[i].user_priority[j];
2847                         region_index = info->region[i].region_id;
2848                         dcb_cfg->etscfg.prioritytable[prio_index] =
2849                                                 region_index;
2850                 }
2851         }
2852
2853         /* FW needs one App to configure HW */
2854         dcb_cfg->numapps = I40E_DEFAULT_DCB_APP_NUM;
2855         dcb_cfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
2856         dcb_cfg->app[0].priority = I40E_DEFAULT_DCB_APP_PRIO;
2857         dcb_cfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
2858
2859         tc_map = RTE_LEN2MASK(info->queue_region_number, uint8_t);
2860
2861         dcb_cfg->pfc.willing = 0;
2862         dcb_cfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
2863         dcb_cfg->pfc.pfcenable = tc_map;
2864
2865         /* Copy the new config to the current config */
2866         *old_cfg = *dcb_cfg;
2867         old_cfg->etsrec = old_cfg->etscfg;
2868         ret = i40e_set_dcb_config(hw);
2869
2870         if (ret) {
2871                 PMD_DRV_LOG(ERR, "Set queue region DCB Config failed, err %s aq_err %s",
2872                          i40e_stat_str(hw, ret),
2873                          i40e_aq_str(hw, hw->aq.asq_last_status));
2874                 return ret;
2875         }
2876
2877         return 0;
2878 }
2879
2880 int
2881 i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,
2882         struct i40e_hw *hw, struct i40e_pf *pf, uint16_t on)
2883 {
2884         int32_t ret = -EINVAL;
2885         struct i40e_queue_regions *info = &pf->queue_region;
2886         struct i40e_vsi *main_vsi = pf->main_vsi;
2887
2888         if (on) {
2889                 i40e_queue_region_pf_flowtype_conf(hw, pf);
2890
2891                 ret = i40e_vsi_update_queue_region_mapping(hw, pf);
2892                 if (ret != I40E_SUCCESS) {
2893                         PMD_DRV_LOG(INFO, "Failed to flush queue region mapping.");
2894                         return ret;
2895                 }
2896
2897                 ret = i40e_queue_region_dcb_configure(hw, pf);
2898                 if (ret != I40E_SUCCESS) {
2899                         PMD_DRV_LOG(INFO, "Failed to flush dcb.");
2900                         return ret;
2901                 }
2902
2903                 return 0;
2904         }
2905
2906         if (info->queue_region_number) {
2907                 info->queue_region_number = 1;
2908                 info->region[0].queue_num = main_vsi->nb_used_qps;
2909                 info->region[0].queue_start_index = 0;
2910
2911                 ret = i40e_vsi_update_queue_region_mapping(hw, pf);
2912                 if (ret != I40E_SUCCESS)
2913                         PMD_DRV_LOG(INFO, "Failed to flush queue region mapping.");
2914
2915                 ret = i40e_dcb_init_configure(dev, TRUE);
2916                 if (ret != I40E_SUCCESS) {
2917                         PMD_DRV_LOG(INFO, "Failed to flush dcb.");
2918                         pf->flags &= ~I40E_FLAG_DCB;
2919                 }
2920
2921                 i40e_init_queue_region_conf(dev);
2922         }
2923         return 0;
2924 }
2925
2926 static int
2927 i40e_queue_region_pf_check_rss(struct i40e_pf *pf)
2928 {
2929         struct i40e_hw *hw = I40E_PF_TO_HW(pf);
2930         uint64_t hena;
2931
2932         hena = (uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(0));
2933         hena |= ((uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1))) << 32;
2934
2935         if (!hena)
2936                 return -ENOTSUP;
2937
2938         return 0;
2939 }
2940
2941 static int
2942 i40e_queue_region_get_all_info(struct i40e_pf *pf,
2943                 struct i40e_queue_regions *regions_ptr)
2944 {
2945         struct i40e_queue_regions *info = &pf->queue_region;
2946
2947         rte_memcpy(regions_ptr, info,
2948                         sizeof(struct i40e_queue_regions));
2949
2950         return 0;
2951 }
2952
2953 int rte_pmd_i40e_rss_queue_region_conf(uint16_t port_id,
2954                 enum rte_pmd_i40e_queue_region_op op_type, void *arg)
2955 {
2956         struct rte_eth_dev *dev = &rte_eth_devices[port_id];
2957         struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
2958         struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
2959         int32_t ret;
2960
2961         RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
2962
2963         if (!is_i40e_supported(dev))
2964                 return -ENOTSUP;
2965
2966         if (!(!i40e_queue_region_pf_check_rss(pf)))
2967                 return -ENOTSUP;
2968
2969         /* This queue region feature only support pf by now. It should
2970          * be called after dev_start, and will be clear after dev_stop.
2971          * "RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON"
2972          * is just an enable function which server for other configuration,
2973          * it is for all configuration about queue region from up layer,
2974          * at first will only keep in DPDK softwarestored in driver,
2975          * only after "FLUSH_ON", it commit all configuration to HW.
2976          * Because PMD had to set hardware configuration at a time, so
2977          * it will record all up layer command at first.
2978          * "RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF" is
2979          * just clean all configuration about queue region just now,
2980          * and restore all to DPDK i40e driver default
2981          * config when start up.
2982          */
2983
2984         switch (op_type) {
2985         case RTE_PMD_I40E_RSS_QUEUE_REGION_SET:
2986                 ret = i40e_queue_region_set_region(pf,
2987                                 (struct rte_pmd_i40e_queue_region_conf *)arg);
2988                 break;
2989         case RTE_PMD_I40E_RSS_QUEUE_REGION_FLOWTYPE_SET:
2990                 ret = i40e_queue_region_set_flowtype(pf,
2991                                 (struct rte_pmd_i40e_queue_region_conf *)arg);
2992                 break;
2993         case RTE_PMD_I40E_RSS_QUEUE_REGION_USER_PRIORITY_SET:
2994                 ret = i40e_queue_region_set_user_priority(pf,
2995                                 (struct rte_pmd_i40e_queue_region_conf *)arg);
2996                 break;
2997         case RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON:
2998                 ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 1);
2999                 break;
3000         case RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF:
3001                 ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
3002                 break;
3003         case RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET:
3004                 ret = i40e_queue_region_get_all_info(pf,
3005                                 (struct i40e_queue_regions *)arg);
3006                 break;
3007         default:
3008                 PMD_DRV_LOG(WARNING, "op type (%d) not supported",
3009                             op_type);
3010                 ret = -EINVAL;
3011         }
3012
3013         I40E_WRITE_FLUSH(hw);
3014
3015         return ret;
3016 }
3017
3018 int rte_pmd_i40e_flow_add_del_packet_template(
3019                         uint16_t port,
3020                         const struct rte_pmd_i40e_pkt_template_conf *conf,
3021                         uint8_t add)
3022 {
3023         struct rte_eth_dev *dev = &rte_eth_devices[port];
3024         struct i40e_fdir_filter_conf filter_conf;
3025
3026         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
3027
3028         if (!is_i40e_supported(dev))
3029                 return -ENOTSUP;
3030
3031         memset(&filter_conf, 0, sizeof(filter_conf));
3032         filter_conf.soft_id = conf->soft_id;
3033         filter_conf.input.flow.raw_flow.pctype = conf->input.pctype;
3034         filter_conf.input.flow.raw_flow.packet = conf->input.packet;
3035         filter_conf.input.flow.raw_flow.length = conf->input.length;
3036         filter_conf.input.flow_ext.pkt_template = true;
3037
3038         filter_conf.action.rx_queue = conf->action.rx_queue;
3039         filter_conf.action.behavior =
3040                 (enum i40e_fdir_behavior)conf->action.behavior;
3041         filter_conf.action.report_status =
3042                 (enum i40e_fdir_status)conf->action.report_status;
3043         filter_conf.action.flex_off = conf->action.flex_off;
3044
3045         return i40e_flow_add_del_fdir_filter(dev, &filter_conf, add);
3046 }
3047
3048 int
3049 rte_pmd_i40e_inset_get(uint16_t port, uint8_t pctype,
3050                        struct rte_pmd_i40e_inset *inset,
3051                        enum rte_pmd_i40e_inset_type inset_type)
3052 {
3053         struct rte_eth_dev *dev;
3054         struct i40e_hw *hw;
3055         uint64_t inset_reg;
3056         uint32_t mask_reg[2];
3057         int i;
3058
3059         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
3060
3061         dev = &rte_eth_devices[port];
3062
3063         if (!is_i40e_supported(dev))
3064                 return -ENOTSUP;
3065
3066         if (pctype > 63)
3067                 return -EINVAL;
3068
3069         hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
3070         memset(inset, 0, sizeof(struct rte_pmd_i40e_inset));
3071
3072         switch (inset_type) {
3073         case INSET_HASH:
3074                 /* Get input set */
3075                 inset_reg =
3076                         i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, pctype));
3077                 inset_reg <<= I40E_32_BIT_WIDTH;
3078                 inset_reg |=
3079                         i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(0, pctype));
3080                 /* Get field mask */
3081                 mask_reg[0] =
3082                         i40e_read_rx_ctl(hw, I40E_GLQF_HASH_MSK(0, pctype));
3083                 mask_reg[1] =
3084                         i40e_read_rx_ctl(hw, I40E_GLQF_HASH_MSK(1, pctype));
3085                 break;
3086         case INSET_FDIR:
3087                 inset_reg =
3088                         i40e_read_rx_ctl(hw, I40E_PRTQF_FD_INSET(pctype, 1));
3089                 inset_reg <<= I40E_32_BIT_WIDTH;
3090                 inset_reg |=
3091                         i40e_read_rx_ctl(hw, I40E_PRTQF_FD_INSET(pctype, 0));
3092                 mask_reg[0] =
3093                         i40e_read_rx_ctl(hw, I40E_GLQF_FD_MSK(0, pctype));
3094                 mask_reg[1] =
3095                         i40e_read_rx_ctl(hw, I40E_GLQF_FD_MSK(1, pctype));
3096                 break;
3097         case INSET_FDIR_FLX:
3098                 inset_reg =
3099                         i40e_read_rx_ctl(hw, I40E_PRTQF_FD_FLXINSET(pctype));
3100                 mask_reg[0] =
3101                         i40e_read_rx_ctl(hw, I40E_PRTQF_FD_MSK(pctype, 0));
3102                 mask_reg[1] =
3103                         i40e_read_rx_ctl(hw, I40E_PRTQF_FD_MSK(pctype, 1));
3104                 break;
3105         default:
3106                 PMD_DRV_LOG(ERR, "Unsupported input set type.");
3107                 return -EINVAL;
3108         }
3109
3110         inset->inset = inset_reg;
3111
3112         for (i = 0; i < 2; i++) {
3113                 inset->mask[i].field_idx = ((mask_reg[i] >> 16) & 0x3F);
3114                 inset->mask[i].mask = mask_reg[i] & 0xFFFF;
3115         }
3116
3117         return 0;
3118 }
3119
3120 int
3121 rte_pmd_i40e_inset_set(uint16_t port, uint8_t pctype,
3122                        struct rte_pmd_i40e_inset *inset,
3123                        enum rte_pmd_i40e_inset_type inset_type)
3124 {
3125         struct rte_eth_dev *dev;
3126         struct i40e_hw *hw;
3127         struct i40e_pf *pf;
3128         uint64_t inset_reg;
3129         uint32_t mask_reg[2];
3130         int i;
3131
3132         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
3133
3134         dev = &rte_eth_devices[port];
3135
3136         if (!is_i40e_supported(dev))
3137                 return -ENOTSUP;
3138
3139         if (pctype > 63)
3140                 return -EINVAL;
3141
3142         hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
3143         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
3144
3145         if (pf->support_multi_driver) {
3146                 PMD_DRV_LOG(ERR, "Input set configuration is not supported.");
3147                 return -ENOTSUP;
3148         }
3149
3150         inset_reg = inset->inset;
3151         for (i = 0; i < 2; i++)
3152                 mask_reg[i] = (inset->mask[i].field_idx << 16) |
3153                         inset->mask[i].mask;
3154
3155         switch (inset_type) {
3156         case INSET_HASH:
3157                 i40e_check_write_global_reg(hw, I40E_GLQF_HASH_INSET(0, pctype),
3158                                             (uint32_t)(inset_reg & UINT32_MAX));
3159                 i40e_check_write_global_reg(hw, I40E_GLQF_HASH_INSET(1, pctype),
3160                                             (uint32_t)((inset_reg >>
3161                                              I40E_32_BIT_WIDTH) & UINT32_MAX));
3162                 for (i = 0; i < 2; i++)
3163                         i40e_check_write_global_reg(hw,
3164                                                   I40E_GLQF_HASH_MSK(i, pctype),
3165                                                   mask_reg[i]);
3166                 break;
3167         case INSET_FDIR:
3168                 i40e_check_write_reg(hw, I40E_PRTQF_FD_INSET(pctype, 0),
3169                                      (uint32_t)(inset_reg & UINT32_MAX));
3170                 i40e_check_write_reg(hw, I40E_PRTQF_FD_INSET(pctype, 1),
3171                                      (uint32_t)((inset_reg >>
3172                                               I40E_32_BIT_WIDTH) & UINT32_MAX));
3173                 for (i = 0; i < 2; i++)
3174                         i40e_check_write_global_reg(hw,
3175                                                     I40E_GLQF_FD_MSK(i, pctype),
3176                                                     mask_reg[i]);
3177                 break;
3178         case INSET_FDIR_FLX:
3179                 i40e_check_write_reg(hw, I40E_PRTQF_FD_FLXINSET(pctype),
3180                                      (uint32_t)(inset_reg & UINT32_MAX));
3181                 for (i = 0; i < 2; i++)
3182                         i40e_check_write_reg(hw, I40E_PRTQF_FD_MSK(pctype, i),
3183                                              mask_reg[i]);
3184                 break;
3185         default:
3186                 PMD_DRV_LOG(ERR, "Unsupported input set type.");
3187                 return -EINVAL;
3188         }
3189
3190         I40E_WRITE_FLUSH(hw);
3191         return 0;
3192 }