0cd2d7abe84475260fa1eacae04678682a356b9f
[dpdk.git] / drivers / net / i40e / rte_pmd_i40e.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <rte_malloc.h>
35 #include <rte_tailq.h>
36
37 #include "base/i40e_prototype.h"
38 #include "i40e_ethdev.h"
39 #include "i40e_pf.h"
40 #include "i40e_rxtx.h"
41 #include "rte_pmd_i40e.h"
42
43 int
44 rte_pmd_i40e_ping_vfs(uint8_t port, uint16_t vf)
45 {
46         struct rte_eth_dev *dev;
47         struct i40e_pf *pf;
48
49         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
50
51         dev = &rte_eth_devices[port];
52
53         if (!is_i40e_supported(dev))
54                 return -ENOTSUP;
55
56         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
57
58         if (vf >= pf->vf_num || !pf->vfs) {
59                 PMD_DRV_LOG(ERR, "Invalid argument.");
60                 return -EINVAL;
61         }
62
63         i40e_notify_vf_link_status(dev, &pf->vfs[vf]);
64
65         return 0;
66 }
67
68 int
69 rte_pmd_i40e_set_vf_mac_anti_spoof(uint8_t port, uint16_t vf_id, uint8_t on)
70 {
71         struct rte_eth_dev *dev;
72         struct i40e_pf *pf;
73         struct i40e_vsi *vsi;
74         struct i40e_hw *hw;
75         struct i40e_vsi_context ctxt;
76         int ret;
77
78         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
79
80         dev = &rte_eth_devices[port];
81
82         if (!is_i40e_supported(dev))
83                 return -ENOTSUP;
84
85         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
86
87         if (vf_id >= pf->vf_num || !pf->vfs) {
88                 PMD_DRV_LOG(ERR, "Invalid argument.");
89                 return -EINVAL;
90         }
91
92         vsi = pf->vfs[vf_id].vsi;
93         if (!vsi) {
94                 PMD_DRV_LOG(ERR, "Invalid VSI.");
95                 return -EINVAL;
96         }
97
98         /* Check if it has been already on or off */
99         if (vsi->info.valid_sections &
100                 rte_cpu_to_le_16(I40E_AQ_VSI_PROP_SECURITY_VALID)) {
101                 if (on) {
102                         if ((vsi->info.sec_flags &
103                              I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK) ==
104                             I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK)
105                                 return 0; /* already on */
106                 } else {
107                         if ((vsi->info.sec_flags &
108                              I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK) == 0)
109                                 return 0; /* already off */
110                 }
111         }
112
113         vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SECURITY_VALID);
114         if (on)
115                 vsi->info.sec_flags |= I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK;
116         else
117                 vsi->info.sec_flags &= ~I40E_AQ_VSI_SEC_FLAG_ENABLE_MAC_CHK;
118
119         memset(&ctxt, 0, sizeof(ctxt));
120         rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
121         ctxt.seid = vsi->seid;
122
123         hw = I40E_VSI_TO_HW(vsi);
124         ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
125         if (ret != I40E_SUCCESS) {
126                 ret = -ENOTSUP;
127                 PMD_DRV_LOG(ERR, "Failed to update VSI params");
128         }
129
130         return ret;
131 }
132
133 static int
134 i40e_add_rm_all_vlan_filter(struct i40e_vsi *vsi, uint8_t add)
135 {
136         uint32_t j, k;
137         uint16_t vlan_id;
138         struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
139         struct i40e_aqc_add_remove_vlan_element_data vlan_data = {0};
140         int ret;
141
142         for (j = 0; j < I40E_VFTA_SIZE; j++) {
143                 if (!vsi->vfta[j])
144                         continue;
145
146                 for (k = 0; k < I40E_UINT32_BIT_SIZE; k++) {
147                         if (!(vsi->vfta[j] & (1 << k)))
148                                 continue;
149
150                         vlan_id = j * I40E_UINT32_BIT_SIZE + k;
151                         if (!vlan_id)
152                                 continue;
153
154                         vlan_data.vlan_tag = rte_cpu_to_le_16(vlan_id);
155                         if (add)
156                                 ret = i40e_aq_add_vlan(hw, vsi->seid,
157                                                        &vlan_data, 1, NULL);
158                         else
159                                 ret = i40e_aq_remove_vlan(hw, vsi->seid,
160                                                           &vlan_data, 1, NULL);
161                         if (ret != I40E_SUCCESS) {
162                                 PMD_DRV_LOG(ERR,
163                                             "Failed to add/rm vlan filter");
164                                 return ret;
165                         }
166                 }
167         }
168
169         return I40E_SUCCESS;
170 }
171
172 int
173 rte_pmd_i40e_set_vf_vlan_anti_spoof(uint8_t port, uint16_t vf_id, uint8_t on)
174 {
175         struct rte_eth_dev *dev;
176         struct i40e_pf *pf;
177         struct i40e_vsi *vsi;
178         struct i40e_hw *hw;
179         struct i40e_vsi_context ctxt;
180         int ret;
181
182         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
183
184         dev = &rte_eth_devices[port];
185
186         if (!is_i40e_supported(dev))
187                 return -ENOTSUP;
188
189         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
190
191         if (vf_id >= pf->vf_num || !pf->vfs) {
192                 PMD_DRV_LOG(ERR, "Invalid argument.");
193                 return -EINVAL;
194         }
195
196         vsi = pf->vfs[vf_id].vsi;
197         if (!vsi) {
198                 PMD_DRV_LOG(ERR, "Invalid VSI.");
199                 return -EINVAL;
200         }
201
202         /* Check if it has been already on or off */
203         if (vsi->vlan_anti_spoof_on == on)
204                 return 0; /* already on or off */
205
206         vsi->vlan_anti_spoof_on = on;
207         if (!vsi->vlan_filter_on) {
208                 ret = i40e_add_rm_all_vlan_filter(vsi, on);
209                 if (ret) {
210                         PMD_DRV_LOG(ERR, "Failed to add/remove VLAN filters.");
211                         return -ENOTSUP;
212                 }
213         }
214
215         vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SECURITY_VALID);
216         if (on)
217                 vsi->info.sec_flags |= I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK;
218         else
219                 vsi->info.sec_flags &= ~I40E_AQ_VSI_SEC_FLAG_ENABLE_VLAN_CHK;
220
221         memset(&ctxt, 0, sizeof(ctxt));
222         rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
223         ctxt.seid = vsi->seid;
224
225         hw = I40E_VSI_TO_HW(vsi);
226         ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
227         if (ret != I40E_SUCCESS) {
228                 ret = -ENOTSUP;
229                 PMD_DRV_LOG(ERR, "Failed to update VSI params");
230         }
231
232         return ret;
233 }
234
235 static int
236 i40e_vsi_rm_mac_filter(struct i40e_vsi *vsi)
237 {
238         struct i40e_mac_filter *f;
239         struct i40e_macvlan_filter *mv_f;
240         int i, vlan_num;
241         enum rte_mac_filter_type filter_type;
242         int ret = I40E_SUCCESS;
243         void *temp;
244
245         /* remove all the MACs */
246         TAILQ_FOREACH_SAFE(f, &vsi->mac_list, next, temp) {
247                 vlan_num = vsi->vlan_num;
248                 filter_type = f->mac_info.filter_type;
249                 if (filter_type == RTE_MACVLAN_PERFECT_MATCH ||
250                     filter_type == RTE_MACVLAN_HASH_MATCH) {
251                         if (vlan_num == 0) {
252                                 PMD_DRV_LOG(ERR, "VLAN number shouldn't be 0");
253                                 return I40E_ERR_PARAM;
254                         }
255                 } else if (filter_type == RTE_MAC_PERFECT_MATCH ||
256                            filter_type == RTE_MAC_HASH_MATCH)
257                         vlan_num = 1;
258
259                 mv_f = rte_zmalloc("macvlan_data", vlan_num * sizeof(*mv_f), 0);
260                 if (!mv_f) {
261                         PMD_DRV_LOG(ERR, "failed to allocate memory");
262                         return I40E_ERR_NO_MEMORY;
263                 }
264
265                 for (i = 0; i < vlan_num; i++) {
266                         mv_f[i].filter_type = filter_type;
267                         rte_memcpy(&mv_f[i].macaddr,
268                                          &f->mac_info.mac_addr,
269                                          ETH_ADDR_LEN);
270                 }
271                 if (filter_type == RTE_MACVLAN_PERFECT_MATCH ||
272                     filter_type == RTE_MACVLAN_HASH_MATCH) {
273                         ret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num,
274                                                          &f->mac_info.mac_addr);
275                         if (ret != I40E_SUCCESS) {
276                                 rte_free(mv_f);
277                                 return ret;
278                         }
279                 }
280
281                 ret = i40e_remove_macvlan_filters(vsi, mv_f, vlan_num);
282                 if (ret != I40E_SUCCESS) {
283                         rte_free(mv_f);
284                         return ret;
285                 }
286
287                 rte_free(mv_f);
288                 ret = I40E_SUCCESS;
289         }
290
291         return ret;
292 }
293
294 static int
295 i40e_vsi_restore_mac_filter(struct i40e_vsi *vsi)
296 {
297         struct i40e_mac_filter *f;
298         struct i40e_macvlan_filter *mv_f;
299         int i, vlan_num = 0;
300         int ret = I40E_SUCCESS;
301         void *temp;
302
303         /* restore all the MACs */
304         TAILQ_FOREACH_SAFE(f, &vsi->mac_list, next, temp) {
305                 if ((f->mac_info.filter_type == RTE_MACVLAN_PERFECT_MATCH) ||
306                     (f->mac_info.filter_type == RTE_MACVLAN_HASH_MATCH)) {
307                         /**
308                          * If vlan_num is 0, that's the first time to add mac,
309                          * set mask for vlan_id 0.
310                          */
311                         if (vsi->vlan_num == 0) {
312                                 i40e_set_vlan_filter(vsi, 0, 1);
313                                 vsi->vlan_num = 1;
314                         }
315                         vlan_num = vsi->vlan_num;
316                 } else if ((f->mac_info.filter_type == RTE_MAC_PERFECT_MATCH) ||
317                            (f->mac_info.filter_type == RTE_MAC_HASH_MATCH))
318                         vlan_num = 1;
319
320                 mv_f = rte_zmalloc("macvlan_data", vlan_num * sizeof(*mv_f), 0);
321                 if (!mv_f) {
322                         PMD_DRV_LOG(ERR, "failed to allocate memory");
323                         return I40E_ERR_NO_MEMORY;
324                 }
325
326                 for (i = 0; i < vlan_num; i++) {
327                         mv_f[i].filter_type = f->mac_info.filter_type;
328                         rte_memcpy(&mv_f[i].macaddr,
329                                          &f->mac_info.mac_addr,
330                                          ETH_ADDR_LEN);
331                 }
332
333                 if (f->mac_info.filter_type == RTE_MACVLAN_PERFECT_MATCH ||
334                     f->mac_info.filter_type == RTE_MACVLAN_HASH_MATCH) {
335                         ret = i40e_find_all_vlan_for_mac(vsi, mv_f, vlan_num,
336                                                          &f->mac_info.mac_addr);
337                         if (ret != I40E_SUCCESS) {
338                                 rte_free(mv_f);
339                                 return ret;
340                         }
341                 }
342
343                 ret = i40e_add_macvlan_filters(vsi, mv_f, vlan_num);
344                 if (ret != I40E_SUCCESS) {
345                         rte_free(mv_f);
346                         return ret;
347                 }
348
349                 rte_free(mv_f);
350                 ret = I40E_SUCCESS;
351         }
352
353         return ret;
354 }
355
356 static int
357 i40e_vsi_set_tx_loopback(struct i40e_vsi *vsi, uint8_t on)
358 {
359         struct i40e_vsi_context ctxt;
360         struct i40e_hw *hw;
361         int ret;
362
363         if (!vsi)
364                 return -EINVAL;
365
366         hw = I40E_VSI_TO_HW(vsi);
367
368         /* Use the FW API if FW >= v5.0 */
369         if (hw->aq.fw_maj_ver < 5) {
370                 PMD_INIT_LOG(ERR, "FW < v5.0, cannot enable loopback");
371                 return -ENOTSUP;
372         }
373
374         /* Check if it has been already on or off */
375         if (vsi->info.valid_sections &
376                 rte_cpu_to_le_16(I40E_AQ_VSI_PROP_SWITCH_VALID)) {
377                 if (on) {
378                         if ((vsi->info.switch_id &
379                              I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB) ==
380                             I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB)
381                                 return 0; /* already on */
382                 } else {
383                         if ((vsi->info.switch_id &
384                              I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB) == 0)
385                                 return 0; /* already off */
386                 }
387         }
388
389         /* remove all the MAC and VLAN first */
390         ret = i40e_vsi_rm_mac_filter(vsi);
391         if (ret) {
392                 PMD_INIT_LOG(ERR, "Failed to remove MAC filters.");
393                 return ret;
394         }
395         if (vsi->vlan_anti_spoof_on || vsi->vlan_filter_on) {
396                 ret = i40e_add_rm_all_vlan_filter(vsi, 0);
397                 if (ret) {
398                         PMD_INIT_LOG(ERR, "Failed to remove VLAN filters.");
399                         return ret;
400                 }
401         }
402
403         vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_SWITCH_VALID);
404         if (on)
405                 vsi->info.switch_id |= I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB;
406         else
407                 vsi->info.switch_id &= ~I40E_AQ_VSI_SW_ID_FLAG_ALLOW_LB;
408
409         memset(&ctxt, 0, sizeof(ctxt));
410         rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
411         ctxt.seid = vsi->seid;
412
413         ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
414         if (ret != I40E_SUCCESS) {
415                 PMD_DRV_LOG(ERR, "Failed to update VSI params");
416                 return ret;
417         }
418
419         /* add all the MAC and VLAN back */
420         ret = i40e_vsi_restore_mac_filter(vsi);
421         if (ret)
422                 return ret;
423         if (vsi->vlan_anti_spoof_on || vsi->vlan_filter_on) {
424                 ret = i40e_add_rm_all_vlan_filter(vsi, 1);
425                 if (ret)
426                         return ret;
427         }
428
429         return ret;
430 }
431
432 int
433 rte_pmd_i40e_set_tx_loopback(uint8_t port, uint8_t on)
434 {
435         struct rte_eth_dev *dev;
436         struct i40e_pf *pf;
437         struct i40e_pf_vf *vf;
438         struct i40e_vsi *vsi;
439         uint16_t vf_id;
440         int ret;
441
442         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
443
444         dev = &rte_eth_devices[port];
445
446         if (!is_i40e_supported(dev))
447                 return -ENOTSUP;
448
449         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
450
451         /* setup PF TX loopback */
452         vsi = pf->main_vsi;
453         ret = i40e_vsi_set_tx_loopback(vsi, on);
454         if (ret)
455                 return -ENOTSUP;
456
457         /* setup TX loopback for all the VFs */
458         if (!pf->vfs) {
459                 /* if no VF, do nothing. */
460                 return 0;
461         }
462
463         for (vf_id = 0; vf_id < pf->vf_num; vf_id++) {
464                 vf = &pf->vfs[vf_id];
465                 vsi = vf->vsi;
466
467                 ret = i40e_vsi_set_tx_loopback(vsi, on);
468                 if (ret)
469                         return -ENOTSUP;
470         }
471
472         return ret;
473 }
474
475 int
476 rte_pmd_i40e_set_vf_unicast_promisc(uint8_t port, uint16_t vf_id, uint8_t on)
477 {
478         struct rte_eth_dev *dev;
479         struct i40e_pf *pf;
480         struct i40e_vsi *vsi;
481         struct i40e_hw *hw;
482         int ret;
483
484         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
485
486         dev = &rte_eth_devices[port];
487
488         if (!is_i40e_supported(dev))
489                 return -ENOTSUP;
490
491         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
492
493         if (vf_id >= pf->vf_num || !pf->vfs) {
494                 PMD_DRV_LOG(ERR, "Invalid argument.");
495                 return -EINVAL;
496         }
497
498         vsi = pf->vfs[vf_id].vsi;
499         if (!vsi) {
500                 PMD_DRV_LOG(ERR, "Invalid VSI.");
501                 return -EINVAL;
502         }
503
504         hw = I40E_VSI_TO_HW(vsi);
505
506         ret = i40e_aq_set_vsi_unicast_promiscuous(hw, vsi->seid,
507                                                   on, NULL, true);
508         if (ret != I40E_SUCCESS) {
509                 ret = -ENOTSUP;
510                 PMD_DRV_LOG(ERR, "Failed to set unicast promiscuous mode");
511         }
512
513         return ret;
514 }
515
516 int
517 rte_pmd_i40e_set_vf_multicast_promisc(uint8_t port, uint16_t vf_id, uint8_t on)
518 {
519         struct rte_eth_dev *dev;
520         struct i40e_pf *pf;
521         struct i40e_vsi *vsi;
522         struct i40e_hw *hw;
523         int ret;
524
525         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
526
527         dev = &rte_eth_devices[port];
528
529         if (!is_i40e_supported(dev))
530                 return -ENOTSUP;
531
532         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
533
534         if (vf_id >= pf->vf_num || !pf->vfs) {
535                 PMD_DRV_LOG(ERR, "Invalid argument.");
536                 return -EINVAL;
537         }
538
539         vsi = pf->vfs[vf_id].vsi;
540         if (!vsi) {
541                 PMD_DRV_LOG(ERR, "Invalid VSI.");
542                 return -EINVAL;
543         }
544
545         hw = I40E_VSI_TO_HW(vsi);
546
547         ret = i40e_aq_set_vsi_multicast_promiscuous(hw, vsi->seid,
548                                                     on, NULL);
549         if (ret != I40E_SUCCESS) {
550                 ret = -ENOTSUP;
551                 PMD_DRV_LOG(ERR, "Failed to set multicast promiscuous mode");
552         }
553
554         return ret;
555 }
556
557 int
558 rte_pmd_i40e_set_vf_mac_addr(uint8_t port, uint16_t vf_id,
559                              struct ether_addr *mac_addr)
560 {
561         struct i40e_mac_filter *f;
562         struct rte_eth_dev *dev;
563         struct i40e_pf_vf *vf;
564         struct i40e_vsi *vsi;
565         struct i40e_pf *pf;
566         void *temp;
567
568         if (i40e_validate_mac_addr((u8 *)mac_addr) != I40E_SUCCESS)
569                 return -EINVAL;
570
571         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
572
573         dev = &rte_eth_devices[port];
574
575         if (!is_i40e_supported(dev))
576                 return -ENOTSUP;
577
578         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
579
580         if (vf_id >= pf->vf_num || !pf->vfs)
581                 return -EINVAL;
582
583         vf = &pf->vfs[vf_id];
584         vsi = vf->vsi;
585         if (!vsi) {
586                 PMD_DRV_LOG(ERR, "Invalid VSI.");
587                 return -EINVAL;
588         }
589
590         ether_addr_copy(mac_addr, &vf->mac_addr);
591
592         /* Remove all existing mac */
593         TAILQ_FOREACH_SAFE(f, &vsi->mac_list, next, temp)
594                 if (i40e_vsi_delete_mac(vsi, &f->mac_info.mac_addr)
595                                 != I40E_SUCCESS)
596                         PMD_DRV_LOG(WARNING, "Delete MAC failed");
597
598         return 0;
599 }
600
601 /* Set vlan strip on/off for specific VF from host */
602 int
603 rte_pmd_i40e_set_vf_vlan_stripq(uint8_t port, uint16_t vf_id, uint8_t on)
604 {
605         struct rte_eth_dev *dev;
606         struct i40e_pf *pf;
607         struct i40e_vsi *vsi;
608         int ret;
609
610         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
611
612         dev = &rte_eth_devices[port];
613
614         if (!is_i40e_supported(dev))
615                 return -ENOTSUP;
616
617         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
618
619         if (vf_id >= pf->vf_num || !pf->vfs) {
620                 PMD_DRV_LOG(ERR, "Invalid argument.");
621                 return -EINVAL;
622         }
623
624         vsi = pf->vfs[vf_id].vsi;
625
626         if (!vsi)
627                 return -EINVAL;
628
629         ret = i40e_vsi_config_vlan_stripping(vsi, !!on);
630         if (ret != I40E_SUCCESS) {
631                 ret = -ENOTSUP;
632                 PMD_DRV_LOG(ERR, "Failed to set VLAN stripping!");
633         }
634
635         return ret;
636 }
637
638 int rte_pmd_i40e_set_vf_vlan_insert(uint8_t port, uint16_t vf_id,
639                                     uint16_t vlan_id)
640 {
641         struct rte_eth_dev *dev;
642         struct i40e_pf *pf;
643         struct i40e_hw *hw;
644         struct i40e_vsi *vsi;
645         struct i40e_vsi_context ctxt;
646         int ret;
647
648         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
649
650         if (vlan_id > ETHER_MAX_VLAN_ID) {
651                 PMD_DRV_LOG(ERR, "Invalid VLAN ID.");
652                 return -EINVAL;
653         }
654
655         dev = &rte_eth_devices[port];
656
657         if (!is_i40e_supported(dev))
658                 return -ENOTSUP;
659
660         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
661         hw = I40E_PF_TO_HW(pf);
662
663         /**
664          * return -ENODEV if SRIOV not enabled, VF number not configured
665          * or no queue assigned.
666          */
667         if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
668             pf->vf_nb_qps == 0)
669                 return -ENODEV;
670
671         if (vf_id >= pf->vf_num || !pf->vfs) {
672                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
673                 return -EINVAL;
674         }
675
676         vsi = pf->vfs[vf_id].vsi;
677         if (!vsi) {
678                 PMD_DRV_LOG(ERR, "Invalid VSI.");
679                 return -EINVAL;
680         }
681
682         vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID);
683         vsi->info.pvid = vlan_id;
684         if (vlan_id > 0)
685                 vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_INSERT_PVID;
686         else
687                 vsi->info.port_vlan_flags &= ~I40E_AQ_VSI_PVLAN_INSERT_PVID;
688
689         memset(&ctxt, 0, sizeof(ctxt));
690         rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
691         ctxt.seid = vsi->seid;
692
693         hw = I40E_VSI_TO_HW(vsi);
694         ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
695         if (ret != I40E_SUCCESS) {
696                 ret = -ENOTSUP;
697                 PMD_DRV_LOG(ERR, "Failed to update VSI params");
698         }
699
700         return ret;
701 }
702
703 int rte_pmd_i40e_set_vf_broadcast(uint8_t port, uint16_t vf_id,
704                                   uint8_t on)
705 {
706         struct rte_eth_dev *dev;
707         struct i40e_pf *pf;
708         struct i40e_vsi *vsi;
709         struct i40e_hw *hw;
710         struct i40e_mac_filter_info filter;
711         struct ether_addr broadcast = {
712                 .addr_bytes = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} };
713         int ret;
714
715         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
716
717         if (on > 1) {
718                 PMD_DRV_LOG(ERR, "on should be 0 or 1.");
719                 return -EINVAL;
720         }
721
722         dev = &rte_eth_devices[port];
723
724         if (!is_i40e_supported(dev))
725                 return -ENOTSUP;
726
727         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
728         hw = I40E_PF_TO_HW(pf);
729
730         if (vf_id >= pf->vf_num || !pf->vfs) {
731                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
732                 return -EINVAL;
733         }
734
735         /**
736          * return -ENODEV if SRIOV not enabled, VF number not configured
737          * or no queue assigned.
738          */
739         if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
740             pf->vf_nb_qps == 0) {
741                 PMD_DRV_LOG(ERR, "SRIOV is not enabled or no queue.");
742                 return -ENODEV;
743         }
744
745         vsi = pf->vfs[vf_id].vsi;
746         if (!vsi) {
747                 PMD_DRV_LOG(ERR, "Invalid VSI.");
748                 return -EINVAL;
749         }
750
751         if (on) {
752                 rte_memcpy(&filter.mac_addr, &broadcast, ETHER_ADDR_LEN);
753                 filter.filter_type = RTE_MACVLAN_PERFECT_MATCH;
754                 ret = i40e_vsi_add_mac(vsi, &filter);
755         } else {
756                 ret = i40e_vsi_delete_mac(vsi, &broadcast);
757         }
758
759         if (ret != I40E_SUCCESS && ret != I40E_ERR_PARAM) {
760                 ret = -ENOTSUP;
761                 PMD_DRV_LOG(ERR, "Failed to set VSI broadcast");
762         } else {
763                 ret = 0;
764         }
765
766         return ret;
767 }
768
769 int rte_pmd_i40e_set_vf_vlan_tag(uint8_t port, uint16_t vf_id, uint8_t on)
770 {
771         struct rte_eth_dev *dev;
772         struct i40e_pf *pf;
773         struct i40e_hw *hw;
774         struct i40e_vsi *vsi;
775         struct i40e_vsi_context ctxt;
776         int ret;
777
778         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
779
780         if (on > 1) {
781                 PMD_DRV_LOG(ERR, "on should be 0 or 1.");
782                 return -EINVAL;
783         }
784
785         dev = &rte_eth_devices[port];
786
787         if (!is_i40e_supported(dev))
788                 return -ENOTSUP;
789
790         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
791         hw = I40E_PF_TO_HW(pf);
792
793         /**
794          * return -ENODEV if SRIOV not enabled, VF number not configured
795          * or no queue assigned.
796          */
797         if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
798             pf->vf_nb_qps == 0) {
799                 PMD_DRV_LOG(ERR, "SRIOV is not enabled or no queue.");
800                 return -ENODEV;
801         }
802
803         if (vf_id >= pf->vf_num || !pf->vfs) {
804                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
805                 return -EINVAL;
806         }
807
808         vsi = pf->vfs[vf_id].vsi;
809         if (!vsi) {
810                 PMD_DRV_LOG(ERR, "Invalid VSI.");
811                 return -EINVAL;
812         }
813
814         vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID);
815         if (on) {
816                 vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_TAGGED;
817                 vsi->info.port_vlan_flags &= ~I40E_AQ_VSI_PVLAN_MODE_UNTAGGED;
818         } else {
819                 vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_UNTAGGED;
820                 vsi->info.port_vlan_flags &= ~I40E_AQ_VSI_PVLAN_MODE_TAGGED;
821         }
822
823         memset(&ctxt, 0, sizeof(ctxt));
824         rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
825         ctxt.seid = vsi->seid;
826
827         hw = I40E_VSI_TO_HW(vsi);
828         ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
829         if (ret != I40E_SUCCESS) {
830                 ret = -ENOTSUP;
831                 PMD_DRV_LOG(ERR, "Failed to update VSI params");
832         }
833
834         return ret;
835 }
836
837 static int
838 i40e_vlan_filter_count(struct i40e_vsi *vsi)
839 {
840         uint32_t j, k;
841         uint16_t vlan_id;
842         int count = 0;
843
844         for (j = 0; j < I40E_VFTA_SIZE; j++) {
845                 if (!vsi->vfta[j])
846                         continue;
847
848                 for (k = 0; k < I40E_UINT32_BIT_SIZE; k++) {
849                         if (!(vsi->vfta[j] & (1 << k)))
850                                 continue;
851
852                         vlan_id = j * I40E_UINT32_BIT_SIZE + k;
853                         if (!vlan_id)
854                                 continue;
855
856                         count++;
857                 }
858         }
859
860         return count;
861 }
862
863 int rte_pmd_i40e_set_vf_vlan_filter(uint8_t port, uint16_t vlan_id,
864                                     uint64_t vf_mask, uint8_t on)
865 {
866         struct rte_eth_dev *dev;
867         struct i40e_pf *pf;
868         struct i40e_hw *hw;
869         struct i40e_vsi *vsi;
870         uint16_t vf_idx;
871         int ret = I40E_SUCCESS;
872
873         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
874
875         dev = &rte_eth_devices[port];
876
877         if (!is_i40e_supported(dev))
878                 return -ENOTSUP;
879
880         if (vlan_id > ETHER_MAX_VLAN_ID || !vlan_id) {
881                 PMD_DRV_LOG(ERR, "Invalid VLAN ID.");
882                 return -EINVAL;
883         }
884
885         if (vf_mask == 0) {
886                 PMD_DRV_LOG(ERR, "No VF.");
887                 return -EINVAL;
888         }
889
890         if (on > 1) {
891                 PMD_DRV_LOG(ERR, "on is should be 0 or 1.");
892                 return -EINVAL;
893         }
894
895         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
896         hw = I40E_PF_TO_HW(pf);
897
898         /**
899          * return -ENODEV if SRIOV not enabled, VF number not configured
900          * or no queue assigned.
901          */
902         if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
903             pf->vf_nb_qps == 0) {
904                 PMD_DRV_LOG(ERR, "SRIOV is not enabled or no queue.");
905                 return -ENODEV;
906         }
907
908         for (vf_idx = 0; vf_idx < pf->vf_num && ret == I40E_SUCCESS; vf_idx++) {
909                 if (vf_mask & ((uint64_t)(1ULL << vf_idx))) {
910                         vsi = pf->vfs[vf_idx].vsi;
911                         if (on) {
912                                 if (!vsi->vlan_filter_on) {
913                                         vsi->vlan_filter_on = true;
914                                         i40e_aq_set_vsi_vlan_promisc(hw,
915                                                                      vsi->seid,
916                                                                      false,
917                                                                      NULL);
918                                         if (!vsi->vlan_anti_spoof_on)
919                                                 i40e_add_rm_all_vlan_filter(
920                                                         vsi, true);
921                                 }
922                                 ret = i40e_vsi_add_vlan(vsi, vlan_id);
923                         } else {
924                                 ret = i40e_vsi_delete_vlan(vsi, vlan_id);
925
926                                 if (!i40e_vlan_filter_count(vsi)) {
927                                         vsi->vlan_filter_on = false;
928                                         i40e_aq_set_vsi_vlan_promisc(hw,
929                                                                      vsi->seid,
930                                                                      true,
931                                                                      NULL);
932                                 }
933                         }
934                 }
935         }
936
937         if (ret != I40E_SUCCESS) {
938                 ret = -ENOTSUP;
939                 PMD_DRV_LOG(ERR, "Failed to set VF VLAN filter, on = %d", on);
940         }
941
942         return ret;
943 }
944
945 int
946 rte_pmd_i40e_get_vf_stats(uint8_t port,
947                           uint16_t vf_id,
948                           struct rte_eth_stats *stats)
949 {
950         struct rte_eth_dev *dev;
951         struct i40e_pf *pf;
952         struct i40e_vsi *vsi;
953
954         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
955
956         dev = &rte_eth_devices[port];
957
958         if (!is_i40e_supported(dev))
959                 return -ENOTSUP;
960
961         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
962
963         if (vf_id >= pf->vf_num || !pf->vfs) {
964                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
965                 return -EINVAL;
966         }
967
968         vsi = pf->vfs[vf_id].vsi;
969         if (!vsi) {
970                 PMD_DRV_LOG(ERR, "Invalid VSI.");
971                 return -EINVAL;
972         }
973
974         i40e_update_vsi_stats(vsi);
975
976         stats->ipackets = vsi->eth_stats.rx_unicast +
977                         vsi->eth_stats.rx_multicast +
978                         vsi->eth_stats.rx_broadcast;
979         stats->opackets = vsi->eth_stats.tx_unicast +
980                         vsi->eth_stats.tx_multicast +
981                         vsi->eth_stats.tx_broadcast;
982         stats->ibytes   = vsi->eth_stats.rx_bytes;
983         stats->obytes   = vsi->eth_stats.tx_bytes;
984         stats->ierrors  = vsi->eth_stats.rx_discards;
985         stats->oerrors  = vsi->eth_stats.tx_errors + vsi->eth_stats.tx_discards;
986
987         return 0;
988 }
989
990 int
991 rte_pmd_i40e_reset_vf_stats(uint8_t port,
992                             uint16_t vf_id)
993 {
994         struct rte_eth_dev *dev;
995         struct i40e_pf *pf;
996         struct i40e_vsi *vsi;
997
998         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
999
1000         dev = &rte_eth_devices[port];
1001
1002         if (!is_i40e_supported(dev))
1003                 return -ENOTSUP;
1004
1005         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1006
1007         if (vf_id >= pf->vf_num || !pf->vfs) {
1008                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
1009                 return -EINVAL;
1010         }
1011
1012         vsi = pf->vfs[vf_id].vsi;
1013         if (!vsi) {
1014                 PMD_DRV_LOG(ERR, "Invalid VSI.");
1015                 return -EINVAL;
1016         }
1017
1018         vsi->offset_loaded = false;
1019         i40e_update_vsi_stats(vsi);
1020
1021         return 0;
1022 }
1023
1024 int
1025 rte_pmd_i40e_set_vf_max_bw(uint8_t port, uint16_t vf_id, uint32_t bw)
1026 {
1027         struct rte_eth_dev *dev;
1028         struct i40e_pf *pf;
1029         struct i40e_vsi *vsi;
1030         struct i40e_hw *hw;
1031         int ret = 0;
1032         int i;
1033
1034         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
1035
1036         dev = &rte_eth_devices[port];
1037
1038         if (!is_i40e_supported(dev))
1039                 return -ENOTSUP;
1040
1041         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1042
1043         if (vf_id >= pf->vf_num || !pf->vfs) {
1044                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
1045                 return -EINVAL;
1046         }
1047
1048         vsi = pf->vfs[vf_id].vsi;
1049         if (!vsi) {
1050                 PMD_DRV_LOG(ERR, "Invalid VSI.");
1051                 return -EINVAL;
1052         }
1053
1054         if (bw > I40E_QOS_BW_MAX) {
1055                 PMD_DRV_LOG(ERR, "Bandwidth should not be larger than %dMbps.",
1056                             I40E_QOS_BW_MAX);
1057                 return -EINVAL;
1058         }
1059
1060         if (bw % I40E_QOS_BW_GRANULARITY) {
1061                 PMD_DRV_LOG(ERR, "Bandwidth should be the multiple of %dMbps.",
1062                             I40E_QOS_BW_GRANULARITY);
1063                 return -EINVAL;
1064         }
1065
1066         bw /= I40E_QOS_BW_GRANULARITY;
1067
1068         hw = I40E_VSI_TO_HW(vsi);
1069
1070         /* No change. */
1071         if (bw == vsi->bw_info.bw_limit) {
1072                 PMD_DRV_LOG(INFO,
1073                             "No change for VF max bandwidth. Nothing to do.");
1074                 return 0;
1075         }
1076
1077         /**
1078          * VF bandwidth limitation and TC bandwidth limitation cannot be
1079          * enabled in parallel, quit if TC bandwidth limitation is enabled.
1080          *
1081          * If bw is 0, means disable bandwidth limitation. Then no need to
1082          * check TC bandwidth limitation.
1083          */
1084         if (bw) {
1085                 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1086                         if ((vsi->enabled_tc & BIT_ULL(i)) &&
1087                             vsi->bw_info.bw_ets_credits[i])
1088                                 break;
1089                 }
1090                 if (i != I40E_MAX_TRAFFIC_CLASS) {
1091                         PMD_DRV_LOG(ERR,
1092                                     "TC max bandwidth has been set on this VF,"
1093                                     " please disable it first.");
1094                         return -EINVAL;
1095                 }
1096         }
1097
1098         ret = i40e_aq_config_vsi_bw_limit(hw, vsi->seid, (uint16_t)bw, 0, NULL);
1099         if (ret) {
1100                 PMD_DRV_LOG(ERR,
1101                             "Failed to set VF %d bandwidth, err(%d).",
1102                             vf_id, ret);
1103                 return -EINVAL;
1104         }
1105
1106         /* Store the configuration. */
1107         vsi->bw_info.bw_limit = (uint16_t)bw;
1108         vsi->bw_info.bw_max = 0;
1109
1110         return 0;
1111 }
1112
1113 int
1114 rte_pmd_i40e_set_vf_tc_bw_alloc(uint8_t port, uint16_t vf_id,
1115                                 uint8_t tc_num, uint8_t *bw_weight)
1116 {
1117         struct rte_eth_dev *dev;
1118         struct i40e_pf *pf;
1119         struct i40e_vsi *vsi;
1120         struct i40e_hw *hw;
1121         struct i40e_aqc_configure_vsi_tc_bw_data tc_bw;
1122         int ret = 0;
1123         int i, j;
1124         uint16_t sum;
1125         bool b_change = false;
1126
1127         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
1128
1129         dev = &rte_eth_devices[port];
1130
1131         if (!is_i40e_supported(dev))
1132                 return -ENOTSUP;
1133
1134         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1135
1136         if (vf_id >= pf->vf_num || !pf->vfs) {
1137                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
1138                 return -EINVAL;
1139         }
1140
1141         vsi = pf->vfs[vf_id].vsi;
1142         if (!vsi) {
1143                 PMD_DRV_LOG(ERR, "Invalid VSI.");
1144                 return -EINVAL;
1145         }
1146
1147         if (tc_num > I40E_MAX_TRAFFIC_CLASS) {
1148                 PMD_DRV_LOG(ERR, "TCs should be no more than %d.",
1149                             I40E_MAX_TRAFFIC_CLASS);
1150                 return -EINVAL;
1151         }
1152
1153         sum = 0;
1154         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1155                 if (vsi->enabled_tc & BIT_ULL(i))
1156                         sum++;
1157         }
1158         if (sum != tc_num) {
1159                 PMD_DRV_LOG(ERR,
1160                             "Weight should be set for all %d enabled TCs.",
1161                             sum);
1162                 return -EINVAL;
1163         }
1164
1165         sum = 0;
1166         for (i = 0; i < tc_num; i++) {
1167                 if (!bw_weight[i]) {
1168                         PMD_DRV_LOG(ERR,
1169                                     "The weight should be 1 at least.");
1170                         return -EINVAL;
1171                 }
1172                 sum += bw_weight[i];
1173         }
1174         if (sum != 100) {
1175                 PMD_DRV_LOG(ERR,
1176                             "The summary of the TC weight should be 100.");
1177                 return -EINVAL;
1178         }
1179
1180         /**
1181          * Create the configuration for all the TCs.
1182          */
1183         memset(&tc_bw, 0, sizeof(tc_bw));
1184         tc_bw.tc_valid_bits = vsi->enabled_tc;
1185         j = 0;
1186         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1187                 if (vsi->enabled_tc & BIT_ULL(i)) {
1188                         if (bw_weight[j] !=
1189                                 vsi->bw_info.bw_ets_share_credits[i])
1190                                 b_change = true;
1191
1192                         tc_bw.tc_bw_credits[i] = bw_weight[j];
1193                         j++;
1194                 }
1195         }
1196
1197         /* No change. */
1198         if (!b_change) {
1199                 PMD_DRV_LOG(INFO,
1200                             "No change for TC allocated bandwidth."
1201                             " Nothing to do.");
1202                 return 0;
1203         }
1204
1205         hw = I40E_VSI_TO_HW(vsi);
1206
1207         ret = i40e_aq_config_vsi_tc_bw(hw, vsi->seid, &tc_bw, NULL);
1208         if (ret) {
1209                 PMD_DRV_LOG(ERR,
1210                             "Failed to set VF %d TC bandwidth weight, err(%d).",
1211                             vf_id, ret);
1212                 return -EINVAL;
1213         }
1214
1215         /* Store the configuration. */
1216         j = 0;
1217         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1218                 if (vsi->enabled_tc & BIT_ULL(i)) {
1219                         vsi->bw_info.bw_ets_share_credits[i] = bw_weight[j];
1220                         j++;
1221                 }
1222         }
1223
1224         return 0;
1225 }
1226
1227 int
1228 rte_pmd_i40e_set_vf_tc_max_bw(uint8_t port, uint16_t vf_id,
1229                               uint8_t tc_no, uint32_t bw)
1230 {
1231         struct rte_eth_dev *dev;
1232         struct i40e_pf *pf;
1233         struct i40e_vsi *vsi;
1234         struct i40e_hw *hw;
1235         struct i40e_aqc_configure_vsi_ets_sla_bw_data tc_bw;
1236         int ret = 0;
1237         int i;
1238
1239         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
1240
1241         dev = &rte_eth_devices[port];
1242
1243         if (!is_i40e_supported(dev))
1244                 return -ENOTSUP;
1245
1246         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1247
1248         if (vf_id >= pf->vf_num || !pf->vfs) {
1249                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
1250                 return -EINVAL;
1251         }
1252
1253         vsi = pf->vfs[vf_id].vsi;
1254         if (!vsi) {
1255                 PMD_DRV_LOG(ERR, "Invalid VSI.");
1256                 return -EINVAL;
1257         }
1258
1259         if (bw > I40E_QOS_BW_MAX) {
1260                 PMD_DRV_LOG(ERR, "Bandwidth should not be larger than %dMbps.",
1261                             I40E_QOS_BW_MAX);
1262                 return -EINVAL;
1263         }
1264
1265         if (bw % I40E_QOS_BW_GRANULARITY) {
1266                 PMD_DRV_LOG(ERR, "Bandwidth should be the multiple of %dMbps.",
1267                             I40E_QOS_BW_GRANULARITY);
1268                 return -EINVAL;
1269         }
1270
1271         bw /= I40E_QOS_BW_GRANULARITY;
1272
1273         if (tc_no >= I40E_MAX_TRAFFIC_CLASS) {
1274                 PMD_DRV_LOG(ERR, "TC No. should be less than %d.",
1275                             I40E_MAX_TRAFFIC_CLASS);
1276                 return -EINVAL;
1277         }
1278
1279         hw = I40E_VSI_TO_HW(vsi);
1280
1281         if (!(vsi->enabled_tc & BIT_ULL(tc_no))) {
1282                 PMD_DRV_LOG(ERR, "VF %d TC %d isn't enabled.",
1283                             vf_id, tc_no);
1284                 return -EINVAL;
1285         }
1286
1287         /* No change. */
1288         if (bw == vsi->bw_info.bw_ets_credits[tc_no]) {
1289                 PMD_DRV_LOG(INFO,
1290                             "No change for TC max bandwidth. Nothing to do.");
1291                 return 0;
1292         }
1293
1294         /**
1295          * VF bandwidth limitation and TC bandwidth limitation cannot be
1296          * enabled in parallel, disable VF bandwidth limitation if it's
1297          * enabled.
1298          * If bw is 0, means disable bandwidth limitation. Then no need to
1299          * care about VF bandwidth limitation configuration.
1300          */
1301         if (bw && vsi->bw_info.bw_limit) {
1302                 ret = i40e_aq_config_vsi_bw_limit(hw, vsi->seid, 0, 0, NULL);
1303                 if (ret) {
1304                         PMD_DRV_LOG(ERR,
1305                                     "Failed to disable VF(%d)"
1306                                     " bandwidth limitation, err(%d).",
1307                                     vf_id, ret);
1308                         return -EINVAL;
1309                 }
1310
1311                 PMD_DRV_LOG(INFO,
1312                             "VF max bandwidth is disabled according"
1313                             " to TC max bandwidth setting.");
1314         }
1315
1316         /**
1317          * Get all the TCs' info to create a whole picture.
1318          * Because the incremental change isn't permitted.
1319          */
1320         memset(&tc_bw, 0, sizeof(tc_bw));
1321         tc_bw.tc_valid_bits = vsi->enabled_tc;
1322         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1323                 if (vsi->enabled_tc & BIT_ULL(i)) {
1324                         tc_bw.tc_bw_credits[i] =
1325                                 rte_cpu_to_le_16(
1326                                         vsi->bw_info.bw_ets_credits[i]);
1327                 }
1328         }
1329         tc_bw.tc_bw_credits[tc_no] = rte_cpu_to_le_16((uint16_t)bw);
1330
1331         ret = i40e_aq_config_vsi_ets_sla_bw_limit(hw, vsi->seid, &tc_bw, NULL);
1332         if (ret) {
1333                 PMD_DRV_LOG(ERR,
1334                             "Failed to set VF %d TC %d max bandwidth, err(%d).",
1335                             vf_id, tc_no, ret);
1336                 return -EINVAL;
1337         }
1338
1339         /* Store the configuration. */
1340         vsi->bw_info.bw_ets_credits[tc_no] = (uint16_t)bw;
1341
1342         return 0;
1343 }
1344
1345 int
1346 rte_pmd_i40e_set_tc_strict_prio(uint8_t port, uint8_t tc_map)
1347 {
1348         struct rte_eth_dev *dev;
1349         struct i40e_pf *pf;
1350         struct i40e_vsi *vsi;
1351         struct i40e_veb *veb;
1352         struct i40e_hw *hw;
1353         struct i40e_aqc_configure_switching_comp_ets_data ets_data;
1354         int i;
1355         int ret;
1356
1357         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
1358
1359         dev = &rte_eth_devices[port];
1360
1361         if (!is_i40e_supported(dev))
1362                 return -ENOTSUP;
1363
1364         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1365
1366         vsi = pf->main_vsi;
1367         if (!vsi) {
1368                 PMD_DRV_LOG(ERR, "Invalid VSI.");
1369                 return -EINVAL;
1370         }
1371
1372         veb = vsi->veb;
1373         if (!veb) {
1374                 PMD_DRV_LOG(ERR, "Invalid VEB.");
1375                 return -EINVAL;
1376         }
1377
1378         if ((tc_map & veb->enabled_tc) != tc_map) {
1379                 PMD_DRV_LOG(ERR,
1380                             "TC bitmap isn't the subset of enabled TCs 0x%x.",
1381                             veb->enabled_tc);
1382                 return -EINVAL;
1383         }
1384
1385         if (tc_map == veb->strict_prio_tc) {
1386                 PMD_DRV_LOG(INFO, "No change for TC bitmap. Nothing to do.");
1387                 return 0;
1388         }
1389
1390         hw = I40E_VSI_TO_HW(vsi);
1391
1392         /* Disable DCBx if it's the first time to set strict priority. */
1393         if (!veb->strict_prio_tc) {
1394                 ret = i40e_aq_stop_lldp(hw, true, NULL);
1395                 if (ret)
1396                         PMD_DRV_LOG(INFO,
1397                                     "Failed to disable DCBx as it's already"
1398                                     " disabled.");
1399                 else
1400                         PMD_DRV_LOG(INFO,
1401                                     "DCBx is disabled according to strict"
1402                                     " priority setting.");
1403         }
1404
1405         memset(&ets_data, 0, sizeof(ets_data));
1406         ets_data.tc_valid_bits = veb->enabled_tc;
1407         ets_data.seepage = I40E_AQ_ETS_SEEPAGE_EN_MASK;
1408         ets_data.tc_strict_priority_flags = tc_map;
1409         /* Get all TCs' bandwidth. */
1410         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1411                 if (veb->enabled_tc & BIT_ULL(i)) {
1412                         /* For rubust, if bandwidth is 0, use 1 instead. */
1413                         if (veb->bw_info.bw_ets_share_credits[i])
1414                                 ets_data.tc_bw_share_credits[i] =
1415                                         veb->bw_info.bw_ets_share_credits[i];
1416                         else
1417                                 ets_data.tc_bw_share_credits[i] =
1418                                         I40E_QOS_BW_WEIGHT_MIN;
1419                 }
1420         }
1421
1422         if (!veb->strict_prio_tc)
1423                 ret = i40e_aq_config_switch_comp_ets(
1424                         hw, veb->uplink_seid,
1425                         &ets_data, i40e_aqc_opc_enable_switching_comp_ets,
1426                         NULL);
1427         else if (tc_map)
1428                 ret = i40e_aq_config_switch_comp_ets(
1429                         hw, veb->uplink_seid,
1430                         &ets_data, i40e_aqc_opc_modify_switching_comp_ets,
1431                         NULL);
1432         else
1433                 ret = i40e_aq_config_switch_comp_ets(
1434                         hw, veb->uplink_seid,
1435                         &ets_data, i40e_aqc_opc_disable_switching_comp_ets,
1436                         NULL);
1437
1438         if (ret) {
1439                 PMD_DRV_LOG(ERR,
1440                             "Failed to set TCs' strict priority mode."
1441                             " err (%d)", ret);
1442                 return -EINVAL;
1443         }
1444
1445         veb->strict_prio_tc = tc_map;
1446
1447         /* Enable DCBx again, if all the TCs' strict priority disabled. */
1448         if (!tc_map) {
1449                 ret = i40e_aq_start_lldp(hw, NULL);
1450                 if (ret) {
1451                         PMD_DRV_LOG(ERR,
1452                                     "Failed to enable DCBx, err(%d).", ret);
1453                         return -EINVAL;
1454                 }
1455
1456                 PMD_DRV_LOG(INFO,
1457                             "DCBx is enabled again according to strict"
1458                             " priority setting.");
1459         }
1460
1461         return ret;
1462 }
1463
1464 #define I40E_PROFILE_INFO_SIZE sizeof(struct rte_pmd_i40e_profile_info)
1465 #define I40E_MAX_PROFILE_NUM 16
1466
1467 static void
1468 i40e_generate_profile_info_sec(char *name, struct i40e_ddp_version *version,
1469                                uint32_t track_id, uint8_t *profile_info_sec,
1470                                bool add)
1471 {
1472         struct i40e_profile_section_header *sec = NULL;
1473         struct i40e_profile_info *pinfo;
1474
1475         sec = (struct i40e_profile_section_header *)profile_info_sec;
1476         sec->tbl_size = 1;
1477         sec->data_end = sizeof(struct i40e_profile_section_header) +
1478                 sizeof(struct i40e_profile_info);
1479         sec->section.type = SECTION_TYPE_INFO;
1480         sec->section.offset = sizeof(struct i40e_profile_section_header);
1481         sec->section.size = sizeof(struct i40e_profile_info);
1482         pinfo = (struct i40e_profile_info *)(profile_info_sec +
1483                                              sec->section.offset);
1484         pinfo->track_id = track_id;
1485         memcpy(pinfo->name, name, I40E_DDP_NAME_SIZE);
1486         memcpy(&pinfo->version, version, sizeof(struct i40e_ddp_version));
1487         if (add)
1488                 pinfo->op = I40E_DDP_ADD_TRACKID;
1489         else
1490                 pinfo->op = I40E_DDP_REMOVE_TRACKID;
1491 }
1492
1493 static enum i40e_status_code
1494 i40e_add_rm_profile_info(struct i40e_hw *hw, uint8_t *profile_info_sec)
1495 {
1496         enum i40e_status_code status = I40E_SUCCESS;
1497         struct i40e_profile_section_header *sec;
1498         uint32_t track_id;
1499         uint32_t offset = 0;
1500         uint32_t info = 0;
1501
1502         sec = (struct i40e_profile_section_header *)profile_info_sec;
1503         track_id = ((struct i40e_profile_info *)(profile_info_sec +
1504                                          sec->section.offset))->track_id;
1505
1506         status = i40e_aq_write_ddp(hw, (void *)sec, sec->data_end,
1507                                    track_id, &offset, &info, NULL);
1508         if (status)
1509                 PMD_DRV_LOG(ERR, "Failed to add/remove profile info: "
1510                             "offset %d, info %d",
1511                             offset, info);
1512
1513         return status;
1514 }
1515
1516 /* Check if the profile info exists */
1517 static int
1518 i40e_check_profile_info(uint8_t port, uint8_t *profile_info_sec)
1519 {
1520         struct rte_eth_dev *dev = &rte_eth_devices[port];
1521         struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1522         uint8_t *buff;
1523         struct rte_pmd_i40e_profile_list *p_list;
1524         struct rte_pmd_i40e_profile_info *pinfo, *p;
1525         uint32_t i;
1526         int ret;
1527
1528         buff = rte_zmalloc("pinfo_list",
1529                            (I40E_PROFILE_INFO_SIZE * I40E_MAX_PROFILE_NUM + 4),
1530                            0);
1531         if (!buff) {
1532                 PMD_DRV_LOG(ERR, "failed to allocate memory");
1533                 return -1;
1534         }
1535
1536         ret = i40e_aq_get_ddp_list(
1537                 hw, (void *)buff,
1538                 (I40E_PROFILE_INFO_SIZE * I40E_MAX_PROFILE_NUM + 4),
1539                 0, NULL);
1540         if (ret) {
1541                 PMD_DRV_LOG(ERR, "Failed to get profile info list.");
1542                 rte_free(buff);
1543                 return -1;
1544         }
1545         p_list = (struct rte_pmd_i40e_profile_list *)buff;
1546         pinfo = (struct rte_pmd_i40e_profile_info *)(profile_info_sec +
1547                              sizeof(struct i40e_profile_section_header));
1548         for (i = 0; i < p_list->p_count; i++) {
1549                 p = &p_list->p_info[i];
1550                 if (pinfo->track_id == p->track_id) {
1551                         PMD_DRV_LOG(INFO, "Profile exists.");
1552                         rte_free(buff);
1553                         return 1;
1554                 }
1555         }
1556
1557         rte_free(buff);
1558         return 0;
1559 }
1560
1561 int
1562 rte_pmd_i40e_process_ddp_package(uint8_t port, uint8_t *buff,
1563                                  uint32_t size,
1564                                  enum rte_pmd_i40e_package_op op)
1565 {
1566         struct rte_eth_dev *dev;
1567         struct i40e_hw *hw;
1568         struct i40e_package_header *pkg_hdr;
1569         struct i40e_generic_seg_header *profile_seg_hdr;
1570         struct i40e_generic_seg_header *metadata_seg_hdr;
1571         uint32_t track_id;
1572         uint8_t *profile_info_sec;
1573         int is_exist;
1574         enum i40e_status_code status = I40E_SUCCESS;
1575
1576         if (op != RTE_PMD_I40E_PKG_OP_WR_ADD &&
1577                 op != RTE_PMD_I40E_PKG_OP_WR_ONLY &&
1578                 op != RTE_PMD_I40E_PKG_OP_WR_DEL) {
1579                 PMD_DRV_LOG(ERR, "Operation not supported.");
1580                 return -ENOTSUP;
1581         }
1582
1583         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
1584
1585         dev = &rte_eth_devices[port];
1586
1587         if (!is_i40e_supported(dev))
1588                 return -ENOTSUP;
1589
1590         hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1591
1592         if (size < (sizeof(struct i40e_package_header) +
1593                     sizeof(struct i40e_metadata_segment) +
1594                     sizeof(uint32_t) * 2)) {
1595                 PMD_DRV_LOG(ERR, "Buff is invalid.");
1596                 return -EINVAL;
1597         }
1598
1599         pkg_hdr = (struct i40e_package_header *)buff;
1600
1601         if (!pkg_hdr) {
1602                 PMD_DRV_LOG(ERR, "Failed to fill the package structure");
1603                 return -EINVAL;
1604         }
1605
1606         if (pkg_hdr->segment_count < 2) {
1607                 PMD_DRV_LOG(ERR, "Segment_count should be 2 at least.");
1608                 return -EINVAL;
1609         }
1610
1611         i40e_update_customized_info(dev, buff, size);
1612
1613         /* Find metadata segment */
1614         metadata_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_METADATA,
1615                                                         pkg_hdr);
1616         if (!metadata_seg_hdr) {
1617                 PMD_DRV_LOG(ERR, "Failed to find metadata segment header");
1618                 return -EINVAL;
1619         }
1620         track_id = ((struct i40e_metadata_segment *)metadata_seg_hdr)->track_id;
1621         if (track_id == I40E_DDP_TRACKID_INVALID) {
1622                 PMD_DRV_LOG(ERR, "Invalid track_id");
1623                 return -EINVAL;
1624         }
1625
1626         /* Find profile segment */
1627         profile_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_I40E,
1628                                                        pkg_hdr);
1629         if (!profile_seg_hdr) {
1630                 PMD_DRV_LOG(ERR, "Failed to find profile segment header");
1631                 return -EINVAL;
1632         }
1633
1634         profile_info_sec = rte_zmalloc(
1635                 "i40e_profile_info",
1636                 sizeof(struct i40e_profile_section_header) +
1637                 sizeof(struct i40e_profile_info),
1638                 0);
1639         if (!profile_info_sec) {
1640                 PMD_DRV_LOG(ERR, "Failed to allocate memory");
1641                 return -EINVAL;
1642         }
1643
1644         /* Check if the profile already loaded */
1645         i40e_generate_profile_info_sec(
1646                 ((struct i40e_profile_segment *)profile_seg_hdr)->name,
1647                 &((struct i40e_profile_segment *)profile_seg_hdr)->version,
1648                 track_id, profile_info_sec,
1649                 op == RTE_PMD_I40E_PKG_OP_WR_ADD);
1650         is_exist = i40e_check_profile_info(port, profile_info_sec);
1651         if (is_exist < 0) {
1652                 PMD_DRV_LOG(ERR, "Failed to check profile.");
1653                 rte_free(profile_info_sec);
1654                 return -EINVAL;
1655         }
1656
1657         if (op == RTE_PMD_I40E_PKG_OP_WR_ADD) {
1658                 if (is_exist) {
1659                         PMD_DRV_LOG(ERR, "Profile already exists.");
1660                         rte_free(profile_info_sec);
1661                         return -EEXIST;
1662                 }
1663         } else if (op == RTE_PMD_I40E_PKG_OP_WR_DEL) {
1664                 if (!is_exist) {
1665                         PMD_DRV_LOG(ERR, "Profile does not exist.");
1666                         rte_free(profile_info_sec);
1667                         return -EACCES;
1668                 }
1669         }
1670
1671         if (op == RTE_PMD_I40E_PKG_OP_WR_DEL) {
1672                 status = i40e_rollback_profile(
1673                         hw,
1674                         (struct i40e_profile_segment *)profile_seg_hdr,
1675                         track_id);
1676                 if (status) {
1677                         PMD_DRV_LOG(ERR, "Failed to write profile for delete.");
1678                         rte_free(profile_info_sec);
1679                         return status;
1680                 }
1681         } else {
1682                 status = i40e_write_profile(
1683                         hw,
1684                         (struct i40e_profile_segment *)profile_seg_hdr,
1685                         track_id);
1686                 if (status) {
1687                         if (op == RTE_PMD_I40E_PKG_OP_WR_ADD)
1688                                 PMD_DRV_LOG(ERR, "Failed to write profile for add.");
1689                         else
1690                                 PMD_DRV_LOG(ERR, "Failed to write profile.");
1691                         rte_free(profile_info_sec);
1692                         return status;
1693                 }
1694         }
1695
1696         if (track_id && (op != RTE_PMD_I40E_PKG_OP_WR_ONLY)) {
1697                 /* Modify loaded profiles info list */
1698                 status = i40e_add_rm_profile_info(hw, profile_info_sec);
1699                 if (status) {
1700                         if (op == RTE_PMD_I40E_PKG_OP_WR_ADD)
1701                                 PMD_DRV_LOG(ERR, "Failed to add profile to info list.");
1702                         else
1703                                 PMD_DRV_LOG(ERR, "Failed to delete profile from info list.");
1704                 }
1705         }
1706
1707         rte_free(profile_info_sec);
1708         return status;
1709 }
1710
1711 /* Get number of tvl records in the section */
1712 static unsigned int
1713 i40e_get_tlv_section_size(struct i40e_profile_section_header *sec)
1714 {
1715         unsigned int i, nb_rec, nb_tlv = 0;
1716         struct i40e_profile_tlv_section_record *tlv;
1717
1718         if (!sec)
1719                 return nb_tlv;
1720
1721         /* get number of records in the section */
1722         nb_rec = sec->section.size /
1723                                 sizeof(struct i40e_profile_tlv_section_record);
1724         for (i = 0; i < nb_rec; ) {
1725                 tlv = (struct i40e_profile_tlv_section_record *)&sec[1 + i];
1726                 i += tlv->len;
1727                 nb_tlv++;
1728         }
1729         return nb_tlv;
1730 }
1731
1732 int rte_pmd_i40e_get_ddp_info(uint8_t *pkg_buff, uint32_t pkg_size,
1733         uint8_t *info_buff, uint32_t info_size,
1734         enum rte_pmd_i40e_package_info type)
1735 {
1736         uint32_t ret_size;
1737         struct i40e_package_header *pkg_hdr;
1738         struct i40e_generic_seg_header *i40e_seg_hdr;
1739         struct i40e_generic_seg_header *note_seg_hdr;
1740         struct i40e_generic_seg_header *metadata_seg_hdr;
1741
1742         if (!info_buff) {
1743                 PMD_DRV_LOG(ERR, "Output info buff is invalid.");
1744                 return -EINVAL;
1745         }
1746
1747         if (!pkg_buff || pkg_size < (sizeof(struct i40e_package_header) +
1748                 sizeof(struct i40e_metadata_segment) +
1749                 sizeof(uint32_t) * 2)) {
1750                 PMD_DRV_LOG(ERR, "Package buff is invalid.");
1751                 return -EINVAL;
1752         }
1753
1754         pkg_hdr = (struct i40e_package_header *)pkg_buff;
1755         if (pkg_hdr->segment_count < 2) {
1756                 PMD_DRV_LOG(ERR, "Segment_count should be 2 at least.");
1757                 return -EINVAL;
1758         }
1759
1760         /* Find metadata segment */
1761         metadata_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_METADATA,
1762                 pkg_hdr);
1763
1764         /* Find global notes segment */
1765         note_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_NOTES,
1766                 pkg_hdr);
1767
1768         /* Find i40e profile segment */
1769         i40e_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_I40E, pkg_hdr);
1770
1771         /* get global header info */
1772         if (type == RTE_PMD_I40E_PKG_INFO_GLOBAL_HEADER) {
1773                 struct rte_pmd_i40e_profile_info *info =
1774                         (struct rte_pmd_i40e_profile_info *)info_buff;
1775
1776                 if (info_size < sizeof(struct rte_pmd_i40e_profile_info)) {
1777                         PMD_DRV_LOG(ERR, "Output info buff size is invalid.");
1778                         return -EINVAL;
1779                 }
1780
1781                 if (!metadata_seg_hdr) {
1782                         PMD_DRV_LOG(ERR, "Failed to find metadata segment header");
1783                         return -EINVAL;
1784                 }
1785
1786                 memset(info, 0, sizeof(struct rte_pmd_i40e_profile_info));
1787                 info->owner = RTE_PMD_I40E_DDP_OWNER_UNKNOWN;
1788                 info->track_id =
1789                         ((struct i40e_metadata_segment *)metadata_seg_hdr)->track_id;
1790
1791                 memcpy(info->name,
1792                         ((struct i40e_metadata_segment *)metadata_seg_hdr)->name,
1793                         I40E_DDP_NAME_SIZE);
1794                 memcpy(&info->version,
1795                         &((struct i40e_metadata_segment *)metadata_seg_hdr)->version,
1796                         sizeof(struct i40e_ddp_version));
1797                 return I40E_SUCCESS;
1798         }
1799
1800         /* get global note size */
1801         if (type == RTE_PMD_I40E_PKG_INFO_GLOBAL_NOTES_SIZE) {
1802                 if (info_size < sizeof(uint32_t)) {
1803                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
1804                         return -EINVAL;
1805                 }
1806                 if (note_seg_hdr == NULL)
1807                         ret_size = 0;
1808                 else
1809                         ret_size = note_seg_hdr->size;
1810                 *(uint32_t *)info_buff = ret_size;
1811                 return I40E_SUCCESS;
1812         }
1813
1814         /* get global note */
1815         if (type == RTE_PMD_I40E_PKG_INFO_GLOBAL_NOTES) {
1816                 if (note_seg_hdr == NULL)
1817                         return -ENOTSUP;
1818                 if (info_size < note_seg_hdr->size) {
1819                         PMD_DRV_LOG(ERR, "Information buffer size is too small");
1820                         return -EINVAL;
1821                 }
1822                 memcpy(info_buff, &note_seg_hdr[1], note_seg_hdr->size);
1823                 return I40E_SUCCESS;
1824         }
1825
1826         /* get i40e segment header info */
1827         if (type == RTE_PMD_I40E_PKG_INFO_HEADER) {
1828                 struct rte_pmd_i40e_profile_info *info =
1829                         (struct rte_pmd_i40e_profile_info *)info_buff;
1830
1831                 if (info_size < sizeof(struct rte_pmd_i40e_profile_info)) {
1832                         PMD_DRV_LOG(ERR, "Output info buff size is invalid.");
1833                         return -EINVAL;
1834                 }
1835
1836                 if (!metadata_seg_hdr) {
1837                         PMD_DRV_LOG(ERR, "Failed to find metadata segment header");
1838                         return -EINVAL;
1839                 }
1840
1841                 if (!i40e_seg_hdr) {
1842                         PMD_DRV_LOG(ERR, "Failed to find i40e segment header");
1843                         return -EINVAL;
1844                 }
1845
1846                 memset(info, 0, sizeof(struct rte_pmd_i40e_profile_info));
1847                 info->owner = RTE_PMD_I40E_DDP_OWNER_UNKNOWN;
1848                 info->track_id =
1849                         ((struct i40e_metadata_segment *)metadata_seg_hdr)->track_id;
1850
1851                 memcpy(info->name,
1852                         ((struct i40e_profile_segment *)i40e_seg_hdr)->name,
1853                         I40E_DDP_NAME_SIZE);
1854                 memcpy(&info->version,
1855                         &((struct i40e_profile_segment *)i40e_seg_hdr)->version,
1856                         sizeof(struct i40e_ddp_version));
1857                 return I40E_SUCCESS;
1858         }
1859
1860         /* get number of devices */
1861         if (type == RTE_PMD_I40E_PKG_INFO_DEVID_NUM) {
1862                 if (info_size < sizeof(uint32_t)) {
1863                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
1864                         return -EINVAL;
1865                 }
1866                 *(uint32_t *)info_buff =
1867                         ((struct i40e_profile_segment *)i40e_seg_hdr)->device_table_count;
1868                 return I40E_SUCCESS;
1869         }
1870
1871         /* get list of devices */
1872         if (type == RTE_PMD_I40E_PKG_INFO_DEVID_LIST) {
1873                 uint32_t dev_num;
1874                 dev_num =
1875                         ((struct i40e_profile_segment *)i40e_seg_hdr)->device_table_count;
1876                 if (info_size < sizeof(struct rte_pmd_i40e_ddp_device_id) * dev_num) {
1877                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
1878                         return -EINVAL;
1879                 }
1880                 memcpy(info_buff,
1881                         ((struct i40e_profile_segment *)i40e_seg_hdr)->device_table,
1882                         sizeof(struct rte_pmd_i40e_ddp_device_id) * dev_num);
1883                 return I40E_SUCCESS;
1884         }
1885
1886         /* get number of protocols */
1887         if (type == RTE_PMD_I40E_PKG_INFO_PROTOCOL_NUM) {
1888                 struct i40e_profile_section_header *proto;
1889
1890                 if (info_size < sizeof(uint32_t)) {
1891                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
1892                         return -EINVAL;
1893                 }
1894                 proto = i40e_find_section_in_profile(SECTION_TYPE_PROTO,
1895                                 (struct i40e_profile_segment *)i40e_seg_hdr);
1896                 *(uint32_t *)info_buff = i40e_get_tlv_section_size(proto);
1897                 return I40E_SUCCESS;
1898         }
1899
1900         /* get list of protocols */
1901         if (type == RTE_PMD_I40E_PKG_INFO_PROTOCOL_LIST) {
1902                 uint32_t i, j, nb_tlv, nb_rec, nb_proto_info;
1903                 struct rte_pmd_i40e_proto_info *pinfo;
1904                 struct i40e_profile_section_header *proto;
1905                 struct i40e_profile_tlv_section_record *tlv;
1906
1907                 pinfo = (struct rte_pmd_i40e_proto_info *)info_buff;
1908                 nb_proto_info = info_size /
1909                                         sizeof(struct rte_pmd_i40e_proto_info);
1910                 for (i = 0; i < nb_proto_info; i++) {
1911                         pinfo[i].proto_id = RTE_PMD_I40E_PROTO_UNUSED;
1912                         memset(pinfo[i].name, 0, RTE_PMD_I40E_DDP_NAME_SIZE);
1913                 }
1914                 proto = i40e_find_section_in_profile(SECTION_TYPE_PROTO,
1915                                 (struct i40e_profile_segment *)i40e_seg_hdr);
1916                 nb_tlv = i40e_get_tlv_section_size(proto);
1917                 if (nb_tlv == 0)
1918                         return I40E_SUCCESS;
1919                 if (nb_proto_info < nb_tlv) {
1920                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
1921                         return -EINVAL;
1922                 }
1923                 /* get number of records in the section */
1924                 nb_rec = proto->section.size /
1925                                 sizeof(struct i40e_profile_tlv_section_record);
1926                 tlv = (struct i40e_profile_tlv_section_record *)&proto[1];
1927                 for (i = j = 0; i < nb_rec; j++) {
1928                         pinfo[j].proto_id = tlv->data[0];
1929                         strncpy(pinfo[j].name, (const char *)&tlv->data[1],
1930                                 I40E_DDP_NAME_SIZE);
1931                         i += tlv->len;
1932                         tlv = &tlv[tlv->len];
1933                 }
1934                 return I40E_SUCCESS;
1935         }
1936
1937         /* get number of packet classification types */
1938         if (type == RTE_PMD_I40E_PKG_INFO_PCTYPE_NUM) {
1939                 struct i40e_profile_section_header *pctype;
1940
1941                 if (info_size < sizeof(uint32_t)) {
1942                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
1943                         return -EINVAL;
1944                 }
1945                 pctype = i40e_find_section_in_profile(SECTION_TYPE_PCTYPE,
1946                                 (struct i40e_profile_segment *)i40e_seg_hdr);
1947                 *(uint32_t *)info_buff = i40e_get_tlv_section_size(pctype);
1948                 return I40E_SUCCESS;
1949         }
1950
1951         /* get list of packet classification types */
1952         if (type == RTE_PMD_I40E_PKG_INFO_PCTYPE_LIST) {
1953                 uint32_t i, j, nb_tlv, nb_rec, nb_proto_info;
1954                 struct rte_pmd_i40e_ptype_info *pinfo;
1955                 struct i40e_profile_section_header *pctype;
1956                 struct i40e_profile_tlv_section_record *tlv;
1957
1958                 pinfo = (struct rte_pmd_i40e_ptype_info *)info_buff;
1959                 nb_proto_info = info_size /
1960                                         sizeof(struct rte_pmd_i40e_ptype_info);
1961                 for (i = 0; i < nb_proto_info; i++)
1962                         memset(&pinfo[i], RTE_PMD_I40E_PROTO_UNUSED,
1963                                sizeof(struct rte_pmd_i40e_ptype_info));
1964                 pctype = i40e_find_section_in_profile(SECTION_TYPE_PCTYPE,
1965                                 (struct i40e_profile_segment *)i40e_seg_hdr);
1966                 nb_tlv = i40e_get_tlv_section_size(pctype);
1967                 if (nb_tlv == 0)
1968                         return I40E_SUCCESS;
1969                 if (nb_proto_info < nb_tlv) {
1970                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
1971                         return -EINVAL;
1972                 }
1973
1974                 /* get number of records in the section */
1975                 nb_rec = pctype->section.size /
1976                                 sizeof(struct i40e_profile_tlv_section_record);
1977                 tlv = (struct i40e_profile_tlv_section_record *)&pctype[1];
1978                 for (i = j = 0; i < nb_rec; j++) {
1979                         memcpy(&pinfo[j], tlv->data,
1980                                sizeof(struct rte_pmd_i40e_ptype_info));
1981                         i += tlv->len;
1982                         tlv = &tlv[tlv->len];
1983                 }
1984                 return I40E_SUCCESS;
1985         }
1986
1987         /* get number of packet types */
1988         if (type == RTE_PMD_I40E_PKG_INFO_PTYPE_NUM) {
1989                 struct i40e_profile_section_header *ptype;
1990
1991                 if (info_size < sizeof(uint32_t)) {
1992                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
1993                         return -EINVAL;
1994                 }
1995                 ptype = i40e_find_section_in_profile(SECTION_TYPE_PTYPE,
1996                                 (struct i40e_profile_segment *)i40e_seg_hdr);
1997                 *(uint32_t *)info_buff = i40e_get_tlv_section_size(ptype);
1998                 return I40E_SUCCESS;
1999         }
2000
2001         /* get list of packet types */
2002         if (type == RTE_PMD_I40E_PKG_INFO_PTYPE_LIST) {
2003                 uint32_t i, j, nb_tlv, nb_rec, nb_proto_info;
2004                 struct rte_pmd_i40e_ptype_info *pinfo;
2005                 struct i40e_profile_section_header *ptype;
2006                 struct i40e_profile_tlv_section_record *tlv;
2007
2008                 pinfo = (struct rte_pmd_i40e_ptype_info *)info_buff;
2009                 nb_proto_info = info_size /
2010                                         sizeof(struct rte_pmd_i40e_ptype_info);
2011                 for (i = 0; i < nb_proto_info; i++)
2012                         memset(&pinfo[i], RTE_PMD_I40E_PROTO_UNUSED,
2013                                sizeof(struct rte_pmd_i40e_ptype_info));
2014                 ptype = i40e_find_section_in_profile(SECTION_TYPE_PTYPE,
2015                                 (struct i40e_profile_segment *)i40e_seg_hdr);
2016                 nb_tlv = i40e_get_tlv_section_size(ptype);
2017                 if (nb_tlv == 0)
2018                         return I40E_SUCCESS;
2019                 if (nb_proto_info < nb_tlv) {
2020                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
2021                         return -EINVAL;
2022                 }
2023                 /* get number of records in the section */
2024                 nb_rec = ptype->section.size /
2025                                 sizeof(struct i40e_profile_tlv_section_record);
2026                 for (i = j = 0; i < nb_rec; j++) {
2027                         tlv = (struct i40e_profile_tlv_section_record *)
2028                                                                 &ptype[1 + i];
2029                         memcpy(&pinfo[j], tlv->data,
2030                                sizeof(struct rte_pmd_i40e_ptype_info));
2031                         i += tlv->len;
2032                 }
2033                 return I40E_SUCCESS;
2034         }
2035
2036         PMD_DRV_LOG(ERR, "Info type %u is invalid.", type);
2037         return -EINVAL;
2038 }
2039
2040 int
2041 rte_pmd_i40e_get_ddp_list(uint8_t port, uint8_t *buff, uint32_t size)
2042 {
2043         struct rte_eth_dev *dev;
2044         struct i40e_hw *hw;
2045         enum i40e_status_code status = I40E_SUCCESS;
2046
2047         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2048
2049         dev = &rte_eth_devices[port];
2050
2051         if (!is_i40e_supported(dev))
2052                 return -ENOTSUP;
2053
2054         if (size < (I40E_PROFILE_INFO_SIZE * I40E_MAX_PROFILE_NUM + 4))
2055                 return -EINVAL;
2056
2057         hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
2058
2059         status = i40e_aq_get_ddp_list(hw, (void *)buff,
2060                                       size, 0, NULL);
2061
2062         return status;
2063 }
2064
2065 static int check_invalid_pkt_type(uint32_t pkt_type)
2066 {
2067         uint32_t l2, l3, l4, tnl, il2, il3, il4;
2068
2069         l2 = pkt_type & RTE_PTYPE_L2_MASK;
2070         l3 = pkt_type & RTE_PTYPE_L3_MASK;
2071         l4 = pkt_type & RTE_PTYPE_L4_MASK;
2072         tnl = pkt_type & RTE_PTYPE_TUNNEL_MASK;
2073         il2 = pkt_type & RTE_PTYPE_INNER_L2_MASK;
2074         il3 = pkt_type & RTE_PTYPE_INNER_L3_MASK;
2075         il4 = pkt_type & RTE_PTYPE_INNER_L4_MASK;
2076
2077         if (l2 &&
2078             l2 != RTE_PTYPE_L2_ETHER &&
2079             l2 != RTE_PTYPE_L2_ETHER_TIMESYNC &&
2080             l2 != RTE_PTYPE_L2_ETHER_ARP &&
2081             l2 != RTE_PTYPE_L2_ETHER_LLDP &&
2082             l2 != RTE_PTYPE_L2_ETHER_NSH &&
2083             l2 != RTE_PTYPE_L2_ETHER_VLAN &&
2084             l2 != RTE_PTYPE_L2_ETHER_QINQ)
2085                 return -1;
2086
2087         if (l3 &&
2088             l3 != RTE_PTYPE_L3_IPV4 &&
2089             l3 != RTE_PTYPE_L3_IPV4_EXT &&
2090             l3 != RTE_PTYPE_L3_IPV6 &&
2091             l3 != RTE_PTYPE_L3_IPV4_EXT_UNKNOWN &&
2092             l3 != RTE_PTYPE_L3_IPV6_EXT &&
2093             l3 != RTE_PTYPE_L3_IPV6_EXT_UNKNOWN)
2094                 return -1;
2095
2096         if (l4 &&
2097             l4 != RTE_PTYPE_L4_TCP &&
2098             l4 != RTE_PTYPE_L4_UDP &&
2099             l4 != RTE_PTYPE_L4_FRAG &&
2100             l4 != RTE_PTYPE_L4_SCTP &&
2101             l4 != RTE_PTYPE_L4_ICMP &&
2102             l4 != RTE_PTYPE_L4_NONFRAG)
2103                 return -1;
2104
2105         if (tnl &&
2106             tnl != RTE_PTYPE_TUNNEL_IP &&
2107             tnl != RTE_PTYPE_TUNNEL_GRENAT &&
2108             tnl != RTE_PTYPE_TUNNEL_VXLAN &&
2109             tnl != RTE_PTYPE_TUNNEL_NVGRE &&
2110             tnl != RTE_PTYPE_TUNNEL_GENEVE &&
2111             tnl != RTE_PTYPE_TUNNEL_GRENAT &&
2112             tnl != RTE_PTYPE_TUNNEL_GTPC &&
2113             tnl != RTE_PTYPE_TUNNEL_GTPU)
2114                 return -1;
2115
2116         if (il2 &&
2117             il2 != RTE_PTYPE_INNER_L2_ETHER &&
2118             il2 != RTE_PTYPE_INNER_L2_ETHER_VLAN &&
2119             il2 != RTE_PTYPE_INNER_L2_ETHER_QINQ)
2120                 return -1;
2121
2122         if (il3 &&
2123             il3 != RTE_PTYPE_INNER_L3_IPV4 &&
2124             il3 != RTE_PTYPE_INNER_L3_IPV4_EXT &&
2125             il3 != RTE_PTYPE_INNER_L3_IPV6 &&
2126             il3 != RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN &&
2127             il3 != RTE_PTYPE_INNER_L3_IPV6_EXT &&
2128             il3 != RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN)
2129                 return -1;
2130
2131         if (il4 &&
2132             il4 != RTE_PTYPE_INNER_L4_TCP &&
2133             il4 != RTE_PTYPE_INNER_L4_UDP &&
2134             il4 != RTE_PTYPE_INNER_L4_FRAG &&
2135             il4 != RTE_PTYPE_INNER_L4_SCTP &&
2136             il4 != RTE_PTYPE_INNER_L4_ICMP &&
2137             il4 != RTE_PTYPE_INNER_L4_NONFRAG)
2138                 return -1;
2139
2140         return 0;
2141 }
2142
2143 static int check_invalid_ptype_mapping(
2144                 struct rte_pmd_i40e_ptype_mapping *mapping_table,
2145                 uint16_t count)
2146 {
2147         int i;
2148
2149         for (i = 0; i < count; i++) {
2150                 uint16_t ptype = mapping_table[i].hw_ptype;
2151                 uint32_t pkt_type = mapping_table[i].sw_ptype;
2152
2153                 if (ptype >= I40E_MAX_PKT_TYPE)
2154                         return -1;
2155
2156                 if (pkt_type == RTE_PTYPE_UNKNOWN)
2157                         continue;
2158
2159                 if (pkt_type & RTE_PMD_I40E_PTYPE_USER_DEFINE_MASK)
2160                         continue;
2161
2162                 if (check_invalid_pkt_type(pkt_type))
2163                         return -1;
2164         }
2165
2166         return 0;
2167 }
2168
2169 int
2170 rte_pmd_i40e_ptype_mapping_update(
2171                         uint8_t port,
2172                         struct rte_pmd_i40e_ptype_mapping *mapping_items,
2173                         uint16_t count,
2174                         uint8_t exclusive)
2175 {
2176         struct rte_eth_dev *dev;
2177         struct i40e_adapter *ad;
2178         int i;
2179
2180         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2181
2182         dev = &rte_eth_devices[port];
2183
2184         if (!is_i40e_supported(dev))
2185                 return -ENOTSUP;
2186
2187         if (count > I40E_MAX_PKT_TYPE)
2188                 return -EINVAL;
2189
2190         if (check_invalid_ptype_mapping(mapping_items, count))
2191                 return -EINVAL;
2192
2193         ad = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
2194
2195         if (exclusive) {
2196                 for (i = 0; i < I40E_MAX_PKT_TYPE; i++)
2197                         ad->ptype_tbl[i] = RTE_PTYPE_UNKNOWN;
2198         }
2199
2200         for (i = 0; i < count; i++)
2201                 ad->ptype_tbl[mapping_items[i].hw_ptype]
2202                         = mapping_items[i].sw_ptype;
2203
2204         return 0;
2205 }
2206
2207 int rte_pmd_i40e_ptype_mapping_reset(uint8_t port)
2208 {
2209         struct rte_eth_dev *dev;
2210
2211         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2212
2213         dev = &rte_eth_devices[port];
2214
2215         if (!is_i40e_supported(dev))
2216                 return -ENOTSUP;
2217
2218         i40e_set_default_ptype_table(dev);
2219
2220         return 0;
2221 }
2222
2223 int rte_pmd_i40e_ptype_mapping_get(
2224                         uint8_t port,
2225                         struct rte_pmd_i40e_ptype_mapping *mapping_items,
2226                         uint16_t size,
2227                         uint16_t *count,
2228                         uint8_t valid_only)
2229 {
2230         struct rte_eth_dev *dev;
2231         struct i40e_adapter *ad;
2232         int n = 0;
2233         uint16_t i;
2234
2235         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2236
2237         dev = &rte_eth_devices[port];
2238
2239         if (!is_i40e_supported(dev))
2240                 return -ENOTSUP;
2241
2242         ad = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
2243
2244         for (i = 0; i < I40E_MAX_PKT_TYPE; i++) {
2245                 if (n >= size)
2246                         break;
2247                 if (valid_only && ad->ptype_tbl[i] == RTE_PTYPE_UNKNOWN)
2248                         continue;
2249                 mapping_items[n].hw_ptype = i;
2250                 mapping_items[n].sw_ptype = ad->ptype_tbl[i];
2251                 n++;
2252         }
2253
2254         *count = n;
2255         return 0;
2256 }
2257
2258 int rte_pmd_i40e_ptype_mapping_replace(uint8_t port,
2259                                        uint32_t target,
2260                                        uint8_t mask,
2261                                        uint32_t pkt_type)
2262 {
2263         struct rte_eth_dev *dev;
2264         struct i40e_adapter *ad;
2265         uint16_t i;
2266
2267         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2268
2269         dev = &rte_eth_devices[port];
2270
2271         if (!is_i40e_supported(dev))
2272                 return -ENOTSUP;
2273
2274         if (!mask && check_invalid_pkt_type(target))
2275                 return -EINVAL;
2276
2277         if (check_invalid_pkt_type(pkt_type))
2278                 return -EINVAL;
2279
2280         ad = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
2281
2282         for (i = 0; i < I40E_MAX_PKT_TYPE; i++) {
2283                 if (mask) {
2284                         if ((target | ad->ptype_tbl[i]) == target &&
2285                             (target & ad->ptype_tbl[i]))
2286                                 ad->ptype_tbl[i] = pkt_type;
2287                 } else {
2288                         if (ad->ptype_tbl[i] == target)
2289                                 ad->ptype_tbl[i] = pkt_type;
2290                 }
2291         }
2292
2293         return 0;
2294 }
2295
2296 int
2297 rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
2298                              struct ether_addr *mac_addr)
2299 {
2300         struct rte_eth_dev *dev;
2301         struct i40e_pf_vf *vf;
2302         struct i40e_vsi *vsi;
2303         struct i40e_pf *pf;
2304         struct i40e_mac_filter_info mac_filter;
2305         int ret;
2306
2307         if (i40e_validate_mac_addr((u8 *)mac_addr) != I40E_SUCCESS)
2308                 return -EINVAL;
2309
2310         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2311
2312         dev = &rte_eth_devices[port];
2313
2314         if (!is_i40e_supported(dev))
2315                 return -ENOTSUP;
2316
2317         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
2318
2319         if (vf_id >= pf->vf_num || !pf->vfs)
2320                 return -EINVAL;
2321
2322         vf = &pf->vfs[vf_id];
2323         vsi = vf->vsi;
2324         if (!vsi) {
2325                 PMD_DRV_LOG(ERR, "Invalid VSI.");
2326                 return -EINVAL;
2327         }
2328
2329         mac_filter.filter_type = RTE_MACVLAN_PERFECT_MATCH;
2330         ether_addr_copy(mac_addr, &mac_filter.mac_addr);
2331         ret = i40e_vsi_add_mac(vsi, &mac_filter);
2332         if (ret != I40E_SUCCESS) {
2333                 PMD_DRV_LOG(ERR, "Failed to add MAC filter.");
2334                 return -1;
2335         }
2336
2337         return 0;
2338 }
2339
2340 int rte_pmd_i40e_flow_type_mapping_reset(uint8_t port)
2341 {
2342         struct rte_eth_dev *dev;
2343
2344         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2345
2346         dev = &rte_eth_devices[port];
2347
2348         if (!is_i40e_supported(dev))
2349                 return -ENOTSUP;
2350
2351         i40e_set_default_pctype_table(dev);
2352
2353         return 0;
2354 }
2355
2356 int rte_pmd_i40e_flow_type_mapping_get(
2357                         uint8_t port,
2358                         struct rte_pmd_i40e_flow_type_mapping *mapping_items)
2359 {
2360         struct rte_eth_dev *dev;
2361         struct i40e_adapter *ad;
2362         uint16_t i;
2363
2364         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2365
2366         dev = &rte_eth_devices[port];
2367
2368         if (!is_i40e_supported(dev))
2369                 return -ENOTSUP;
2370
2371         ad = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
2372
2373         for (i = 0; i < I40E_FLOW_TYPE_MAX; i++) {
2374                 mapping_items[i].flow_type = i;
2375                 mapping_items[i].pctype = ad->pctypes_tbl[i];
2376         }
2377
2378         return 0;
2379 }
2380
2381 int
2382 rte_pmd_i40e_flow_type_mapping_update(
2383                         uint8_t port,
2384                         struct rte_pmd_i40e_flow_type_mapping *mapping_items,
2385                         uint16_t count,
2386                         uint8_t exclusive)
2387 {
2388         struct rte_eth_dev *dev;
2389         struct i40e_adapter *ad;
2390         int i;
2391
2392         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2393
2394         dev = &rte_eth_devices[port];
2395
2396         if (!is_i40e_supported(dev))
2397                 return -ENOTSUP;
2398
2399         if (count > I40E_FLOW_TYPE_MAX)
2400                 return -EINVAL;
2401
2402         for (i = 0; i < count; i++)
2403                 if (mapping_items[i].flow_type >= I40E_FLOW_TYPE_MAX ||
2404                     mapping_items[i].flow_type == RTE_ETH_FLOW_UNKNOWN ||
2405                     (mapping_items[i].pctype &
2406                     (1ULL << I40E_FILTER_PCTYPE_INVALID)))
2407                         return -EINVAL;
2408
2409         ad = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
2410
2411         if (exclusive) {
2412                 for (i = 0; i < I40E_FLOW_TYPE_MAX; i++)
2413                         ad->pctypes_tbl[i] = 0ULL;
2414                 ad->flow_types_mask = 0ULL;
2415         }
2416
2417         for (i = 0; i < count; i++) {
2418                 ad->pctypes_tbl[mapping_items[i].flow_type] =
2419                                                 mapping_items[i].pctype;
2420                 if (mapping_items[i].pctype)
2421                         ad->flow_types_mask |=
2422                                         (1ULL << mapping_items[i].flow_type);
2423                 else
2424                         ad->flow_types_mask &=
2425                                         ~(1ULL << mapping_items[i].flow_type);
2426         }
2427
2428         for (i = 0, ad->pctypes_mask = 0ULL; i < I40E_FLOW_TYPE_MAX; i++)
2429                 ad->pctypes_mask |= ad->pctypes_tbl[i];
2430
2431         return 0;
2432 }