net/i40e: new API to add VF MAC address from PF
[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         (void)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         (void)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                         (void)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                         (void)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         (void)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         (void)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                 (void)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         (void)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         /* Find metadata segment */
1612         metadata_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_METADATA,
1613                                                         pkg_hdr);
1614         if (!metadata_seg_hdr) {
1615                 PMD_DRV_LOG(ERR, "Failed to find metadata segment header");
1616                 return -EINVAL;
1617         }
1618         track_id = ((struct i40e_metadata_segment *)metadata_seg_hdr)->track_id;
1619         if (track_id == I40E_DDP_TRACKID_INVALID) {
1620                 PMD_DRV_LOG(ERR, "Invalid track_id");
1621                 return -EINVAL;
1622         }
1623
1624         /* Find profile segment */
1625         profile_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_I40E,
1626                                                        pkg_hdr);
1627         if (!profile_seg_hdr) {
1628                 PMD_DRV_LOG(ERR, "Failed to find profile segment header");
1629                 return -EINVAL;
1630         }
1631
1632         profile_info_sec = rte_zmalloc(
1633                 "i40e_profile_info",
1634                 sizeof(struct i40e_profile_section_header) +
1635                 sizeof(struct i40e_profile_info),
1636                 0);
1637         if (!profile_info_sec) {
1638                 PMD_DRV_LOG(ERR, "Failed to allocate memory");
1639                 return -EINVAL;
1640         }
1641
1642         /* Check if the profile already loaded */
1643         i40e_generate_profile_info_sec(
1644                 ((struct i40e_profile_segment *)profile_seg_hdr)->name,
1645                 &((struct i40e_profile_segment *)profile_seg_hdr)->version,
1646                 track_id, profile_info_sec,
1647                 op == RTE_PMD_I40E_PKG_OP_WR_ADD);
1648         is_exist = i40e_check_profile_info(port, profile_info_sec);
1649         if (is_exist < 0) {
1650                 PMD_DRV_LOG(ERR, "Failed to check profile.");
1651                 rte_free(profile_info_sec);
1652                 return -EINVAL;
1653         }
1654
1655         if (op == RTE_PMD_I40E_PKG_OP_WR_ADD) {
1656                 if (is_exist) {
1657                         PMD_DRV_LOG(ERR, "Profile already exists.");
1658                         rte_free(profile_info_sec);
1659                         return -EEXIST;
1660                 }
1661         } else if (op == RTE_PMD_I40E_PKG_OP_WR_DEL) {
1662                 if (!is_exist) {
1663                         PMD_DRV_LOG(ERR, "Profile does not exist.");
1664                         rte_free(profile_info_sec);
1665                         return -EACCES;
1666                 }
1667         }
1668
1669         if (op == RTE_PMD_I40E_PKG_OP_WR_DEL) {
1670                 status = i40e_rollback_profile(
1671                         hw,
1672                         (struct i40e_profile_segment *)profile_seg_hdr,
1673                         track_id);
1674                 if (status) {
1675                         PMD_DRV_LOG(ERR, "Failed to write profile for delete.");
1676                         rte_free(profile_info_sec);
1677                         return status;
1678                 }
1679         } else {
1680                 status = i40e_write_profile(
1681                         hw,
1682                         (struct i40e_profile_segment *)profile_seg_hdr,
1683                         track_id);
1684                 if (status) {
1685                         if (op == RTE_PMD_I40E_PKG_OP_WR_ADD)
1686                                 PMD_DRV_LOG(ERR, "Failed to write profile for add.");
1687                         else
1688                                 PMD_DRV_LOG(ERR, "Failed to write profile.");
1689                         rte_free(profile_info_sec);
1690                         return status;
1691                 }
1692         }
1693
1694         if (track_id && (op != RTE_PMD_I40E_PKG_OP_WR_ONLY)) {
1695                 /* Modify loaded profiles info list */
1696                 status = i40e_add_rm_profile_info(hw, profile_info_sec);
1697                 if (status) {
1698                         if (op == RTE_PMD_I40E_PKG_OP_WR_ADD)
1699                                 PMD_DRV_LOG(ERR, "Failed to add profile to info list.");
1700                         else
1701                                 PMD_DRV_LOG(ERR, "Failed to delete profile from info list.");
1702                 }
1703         }
1704
1705         rte_free(profile_info_sec);
1706         return status;
1707 }
1708
1709 int rte_pmd_i40e_get_ddp_info(uint8_t *pkg_buff, uint32_t pkg_size,
1710         uint8_t *info_buff, uint32_t info_size,
1711         enum rte_pmd_i40e_package_info type)
1712 {
1713         uint32_t ret_size;
1714         struct i40e_package_header *pkg_hdr;
1715         struct i40e_generic_seg_header *i40e_seg_hdr;
1716         struct i40e_generic_seg_header *note_seg_hdr;
1717         struct i40e_generic_seg_header *metadata_seg_hdr;
1718
1719         if (!info_buff) {
1720                 PMD_DRV_LOG(ERR, "Output info buff is invalid.");
1721                 return -EINVAL;
1722         }
1723
1724         if (!pkg_buff || pkg_size < (sizeof(struct i40e_package_header) +
1725                 sizeof(struct i40e_metadata_segment) +
1726                 sizeof(uint32_t) * 2)) {
1727                 PMD_DRV_LOG(ERR, "Package buff is invalid.");
1728                 return -EINVAL;
1729         }
1730
1731         pkg_hdr = (struct i40e_package_header *)pkg_buff;
1732         if (pkg_hdr->segment_count < 2) {
1733                 PMD_DRV_LOG(ERR, "Segment_count should be 2 at least.");
1734                 return -EINVAL;
1735         }
1736
1737         /* Find metadata segment */
1738         metadata_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_METADATA,
1739                 pkg_hdr);
1740
1741         /* Find global notes segment */
1742         note_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_NOTES,
1743                 pkg_hdr);
1744
1745         /* Find i40e profile segment */
1746         i40e_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_I40E, pkg_hdr);
1747
1748         /* get global header info */
1749         if (type == RTE_PMD_I40E_PKG_INFO_GLOBAL_HEADER) {
1750                 struct rte_pmd_i40e_profile_info *info =
1751                         (struct rte_pmd_i40e_profile_info *)info_buff;
1752
1753                 if (info_size < sizeof(struct rte_pmd_i40e_profile_info)) {
1754                         PMD_DRV_LOG(ERR, "Output info buff size is invalid.");
1755                         return -EINVAL;
1756                 }
1757
1758                 if (!metadata_seg_hdr) {
1759                         PMD_DRV_LOG(ERR, "Failed to find metadata segment header");
1760                         return -EINVAL;
1761                 }
1762
1763                 memset(info, 0, sizeof(struct rte_pmd_i40e_profile_info));
1764                 info->owner = RTE_PMD_I40E_DDP_OWNER_UNKNOWN;
1765                 info->track_id =
1766                         ((struct i40e_metadata_segment *)metadata_seg_hdr)->track_id;
1767
1768                 memcpy(info->name,
1769                         ((struct i40e_metadata_segment *)metadata_seg_hdr)->name,
1770                         I40E_DDP_NAME_SIZE);
1771                 memcpy(&info->version,
1772                         &((struct i40e_metadata_segment *)metadata_seg_hdr)->version,
1773                         sizeof(struct i40e_ddp_version));
1774                 return I40E_SUCCESS;
1775         }
1776
1777         /* get global note size */
1778         if (type == RTE_PMD_I40E_PKG_INFO_GLOBAL_NOTES_SIZE) {
1779                 if (info_size < sizeof(uint32_t)) {
1780                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
1781                         return -EINVAL;
1782                 }
1783                 if (note_seg_hdr == NULL)
1784                         ret_size = 0;
1785                 else
1786                         ret_size = note_seg_hdr->size;
1787                 *(uint32_t *)info_buff = ret_size;
1788                 return I40E_SUCCESS;
1789         }
1790
1791         /* get global note */
1792         if (type == RTE_PMD_I40E_PKG_INFO_GLOBAL_NOTES) {
1793                 if (note_seg_hdr == NULL)
1794                         return -ENOTSUP;
1795                 if (info_size < note_seg_hdr->size) {
1796                         PMD_DRV_LOG(ERR, "Information buffer size is too small");
1797                         return -EINVAL;
1798                 }
1799                 memcpy(info_buff, &note_seg_hdr[1], note_seg_hdr->size);
1800                 return I40E_SUCCESS;
1801         }
1802
1803         /* get i40e segment header info */
1804         if (type == RTE_PMD_I40E_PKG_INFO_HEADER) {
1805                 struct rte_pmd_i40e_profile_info *info =
1806                         (struct rte_pmd_i40e_profile_info *)info_buff;
1807
1808                 if (info_size < sizeof(struct rte_pmd_i40e_profile_info)) {
1809                         PMD_DRV_LOG(ERR, "Output info buff size is invalid.");
1810                         return -EINVAL;
1811                 }
1812
1813                 if (!metadata_seg_hdr) {
1814                         PMD_DRV_LOG(ERR, "Failed to find metadata segment header");
1815                         return -EINVAL;
1816                 }
1817
1818                 if (!i40e_seg_hdr) {
1819                         PMD_DRV_LOG(ERR, "Failed to find i40e segment header");
1820                         return -EINVAL;
1821                 }
1822
1823                 memset(info, 0, sizeof(struct rte_pmd_i40e_profile_info));
1824                 info->owner = RTE_PMD_I40E_DDP_OWNER_UNKNOWN;
1825                 info->track_id =
1826                         ((struct i40e_metadata_segment *)metadata_seg_hdr)->track_id;
1827
1828                 memcpy(info->name,
1829                         ((struct i40e_profile_segment *)i40e_seg_hdr)->name,
1830                         I40E_DDP_NAME_SIZE);
1831                 memcpy(&info->version,
1832                         &((struct i40e_profile_segment *)i40e_seg_hdr)->version,
1833                         sizeof(struct i40e_ddp_version));
1834                 return I40E_SUCCESS;
1835         }
1836
1837         /* get number of devices */
1838         if (type == RTE_PMD_I40E_PKG_INFO_DEVID_NUM) {
1839                 if (info_size < sizeof(uint32_t)) {
1840                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
1841                         return -EINVAL;
1842                 }
1843                 *(uint32_t *)info_buff =
1844                         ((struct i40e_profile_segment *)i40e_seg_hdr)->device_table_count;
1845                 return I40E_SUCCESS;
1846         }
1847
1848         /* get list of devices */
1849         if (type == RTE_PMD_I40E_PKG_INFO_DEVID_LIST) {
1850                 uint32_t dev_num;
1851                 dev_num =
1852                         ((struct i40e_profile_segment *)i40e_seg_hdr)->device_table_count;
1853                 if (info_size < sizeof(struct rte_pmd_i40e_ddp_device_id) * dev_num) {
1854                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
1855                         return -EINVAL;
1856                 }
1857                 memcpy(info_buff,
1858                         ((struct i40e_profile_segment *)i40e_seg_hdr)->device_table,
1859                         sizeof(struct rte_pmd_i40e_ddp_device_id) * dev_num);
1860                 return I40E_SUCCESS;
1861         }
1862
1863         PMD_DRV_LOG(ERR, "Info type %u is invalid.", type);
1864         return -EINVAL;
1865 }
1866
1867 int
1868 rte_pmd_i40e_get_ddp_list(uint8_t port, uint8_t *buff, uint32_t size)
1869 {
1870         struct rte_eth_dev *dev;
1871         struct i40e_hw *hw;
1872         enum i40e_status_code status = I40E_SUCCESS;
1873
1874         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
1875
1876         dev = &rte_eth_devices[port];
1877
1878         if (!is_i40e_supported(dev))
1879                 return -ENOTSUP;
1880
1881         if (size < (I40E_PROFILE_INFO_SIZE * I40E_MAX_PROFILE_NUM + 4))
1882                 return -EINVAL;
1883
1884         hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1885
1886         status = i40e_aq_get_ddp_list(hw, (void *)buff,
1887                                       size, 0, NULL);
1888
1889         return status;
1890 }
1891
1892 static int check_invalid_pkt_type(uint32_t pkt_type)
1893 {
1894         uint32_t l2, l3, l4, tnl, il2, il3, il4;
1895
1896         l2 = pkt_type & RTE_PTYPE_L2_MASK;
1897         l3 = pkt_type & RTE_PTYPE_L3_MASK;
1898         l4 = pkt_type & RTE_PTYPE_L4_MASK;
1899         tnl = pkt_type & RTE_PTYPE_TUNNEL_MASK;
1900         il2 = pkt_type & RTE_PTYPE_INNER_L2_MASK;
1901         il3 = pkt_type & RTE_PTYPE_INNER_L3_MASK;
1902         il4 = pkt_type & RTE_PTYPE_INNER_L4_MASK;
1903
1904         if (l2 &&
1905             l2 != RTE_PTYPE_L2_ETHER &&
1906             l2 != RTE_PTYPE_L2_ETHER_TIMESYNC &&
1907             l2 != RTE_PTYPE_L2_ETHER_ARP &&
1908             l2 != RTE_PTYPE_L2_ETHER_LLDP &&
1909             l2 != RTE_PTYPE_L2_ETHER_NSH &&
1910             l2 != RTE_PTYPE_L2_ETHER_VLAN &&
1911             l2 != RTE_PTYPE_L2_ETHER_QINQ)
1912                 return -1;
1913
1914         if (l3 &&
1915             l3 != RTE_PTYPE_L3_IPV4 &&
1916             l3 != RTE_PTYPE_L3_IPV4_EXT &&
1917             l3 != RTE_PTYPE_L3_IPV6 &&
1918             l3 != RTE_PTYPE_L3_IPV4_EXT_UNKNOWN &&
1919             l3 != RTE_PTYPE_L3_IPV6_EXT &&
1920             l3 != RTE_PTYPE_L3_IPV6_EXT_UNKNOWN)
1921                 return -1;
1922
1923         if (l4 &&
1924             l4 != RTE_PTYPE_L4_TCP &&
1925             l4 != RTE_PTYPE_L4_UDP &&
1926             l4 != RTE_PTYPE_L4_FRAG &&
1927             l4 != RTE_PTYPE_L4_SCTP &&
1928             l4 != RTE_PTYPE_L4_ICMP &&
1929             l4 != RTE_PTYPE_L4_NONFRAG)
1930                 return -1;
1931
1932         if (tnl &&
1933             tnl != RTE_PTYPE_TUNNEL_IP &&
1934             tnl != RTE_PTYPE_TUNNEL_GRENAT &&
1935             tnl != RTE_PTYPE_TUNNEL_VXLAN &&
1936             tnl != RTE_PTYPE_TUNNEL_NVGRE &&
1937             tnl != RTE_PTYPE_TUNNEL_GENEVE &&
1938             tnl != RTE_PTYPE_TUNNEL_GRENAT)
1939                 return -1;
1940
1941         if (il2 &&
1942             il2 != RTE_PTYPE_INNER_L2_ETHER &&
1943             il2 != RTE_PTYPE_INNER_L2_ETHER_VLAN &&
1944             il2 != RTE_PTYPE_INNER_L2_ETHER_QINQ)
1945                 return -1;
1946
1947         if (il3 &&
1948             il3 != RTE_PTYPE_INNER_L3_IPV4 &&
1949             il3 != RTE_PTYPE_INNER_L3_IPV4_EXT &&
1950             il3 != RTE_PTYPE_INNER_L3_IPV6 &&
1951             il3 != RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN &&
1952             il3 != RTE_PTYPE_INNER_L3_IPV6_EXT &&
1953             il3 != RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN)
1954                 return -1;
1955
1956         if (il4 &&
1957             il4 != RTE_PTYPE_INNER_L4_TCP &&
1958             il4 != RTE_PTYPE_INNER_L4_UDP &&
1959             il4 != RTE_PTYPE_INNER_L4_FRAG &&
1960             il4 != RTE_PTYPE_INNER_L4_SCTP &&
1961             il4 != RTE_PTYPE_INNER_L4_ICMP &&
1962             il4 != RTE_PTYPE_INNER_L4_NONFRAG)
1963                 return -1;
1964
1965         return 0;
1966 }
1967
1968 static int check_invalid_ptype_mapping(
1969                 struct rte_pmd_i40e_ptype_mapping *mapping_table,
1970                 uint16_t count)
1971 {
1972         int i;
1973
1974         for (i = 0; i < count; i++) {
1975                 uint16_t ptype = mapping_table[i].hw_ptype;
1976                 uint32_t pkt_type = mapping_table[i].sw_ptype;
1977
1978                 if (ptype >= I40E_MAX_PKT_TYPE)
1979                         return -1;
1980
1981                 if (pkt_type == RTE_PTYPE_UNKNOWN)
1982                         continue;
1983
1984                 if (pkt_type & RTE_PMD_I40E_PTYPE_USER_DEFINE_MASK)
1985                         continue;
1986
1987                 if (check_invalid_pkt_type(pkt_type))
1988                         return -1;
1989         }
1990
1991         return 0;
1992 }
1993
1994 int
1995 rte_pmd_i40e_ptype_mapping_update(
1996                         uint8_t port,
1997                         struct rte_pmd_i40e_ptype_mapping *mapping_items,
1998                         uint16_t count,
1999                         uint8_t exclusive)
2000 {
2001         struct rte_eth_dev *dev;
2002         struct i40e_adapter *ad;
2003         int i;
2004
2005         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2006
2007         dev = &rte_eth_devices[port];
2008
2009         if (!is_i40e_supported(dev))
2010                 return -ENOTSUP;
2011
2012         if (count > I40E_MAX_PKT_TYPE)
2013                 return -EINVAL;
2014
2015         if (check_invalid_ptype_mapping(mapping_items, count))
2016                 return -EINVAL;
2017
2018         ad = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
2019
2020         if (exclusive) {
2021                 for (i = 0; i < I40E_MAX_PKT_TYPE; i++)
2022                         ad->ptype_tbl[i] = RTE_PTYPE_UNKNOWN;
2023         }
2024
2025         for (i = 0; i < count; i++)
2026                 ad->ptype_tbl[mapping_items[i].hw_ptype]
2027                         = mapping_items[i].sw_ptype;
2028
2029         return 0;
2030 }
2031
2032 int rte_pmd_i40e_ptype_mapping_reset(uint8_t port)
2033 {
2034         struct rte_eth_dev *dev;
2035
2036         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2037
2038         dev = &rte_eth_devices[port];
2039
2040         if (!is_i40e_supported(dev))
2041                 return -ENOTSUP;
2042
2043         i40e_set_default_ptype_table(dev);
2044
2045         return 0;
2046 }
2047
2048 int rte_pmd_i40e_ptype_mapping_get(
2049                         uint8_t port,
2050                         struct rte_pmd_i40e_ptype_mapping *mapping_items,
2051                         uint16_t size,
2052                         uint16_t *count,
2053                         uint8_t valid_only)
2054 {
2055         struct rte_eth_dev *dev;
2056         struct i40e_adapter *ad;
2057         int n = 0;
2058         uint16_t i;
2059
2060         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2061
2062         dev = &rte_eth_devices[port];
2063
2064         if (!is_i40e_supported(dev))
2065                 return -ENOTSUP;
2066
2067         ad = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
2068
2069         for (i = 0; i < I40E_MAX_PKT_TYPE; i++) {
2070                 if (n >= size)
2071                         break;
2072                 if (valid_only && ad->ptype_tbl[i] == RTE_PTYPE_UNKNOWN)
2073                         continue;
2074                 mapping_items[n].hw_ptype = i;
2075                 mapping_items[n].sw_ptype = ad->ptype_tbl[i];
2076                 n++;
2077         }
2078
2079         *count = n;
2080         return 0;
2081 }
2082
2083 int rte_pmd_i40e_ptype_mapping_replace(uint8_t port,
2084                                        uint32_t target,
2085                                        uint8_t mask,
2086                                        uint32_t pkt_type)
2087 {
2088         struct rte_eth_dev *dev;
2089         struct i40e_adapter *ad;
2090         uint16_t i;
2091
2092         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2093
2094         dev = &rte_eth_devices[port];
2095
2096         if (!is_i40e_supported(dev))
2097                 return -ENOTSUP;
2098
2099         if (!mask && check_invalid_pkt_type(target))
2100                 return -EINVAL;
2101
2102         if (check_invalid_pkt_type(pkt_type))
2103                 return -EINVAL;
2104
2105         ad = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
2106
2107         for (i = 0; i < I40E_MAX_PKT_TYPE; i++) {
2108                 if (mask) {
2109                         if ((target | ad->ptype_tbl[i]) == target &&
2110                             (target & ad->ptype_tbl[i]))
2111                                 ad->ptype_tbl[i] = pkt_type;
2112                 } else {
2113                         if (ad->ptype_tbl[i] == target)
2114                                 ad->ptype_tbl[i] = pkt_type;
2115                 }
2116         }
2117
2118         return 0;
2119 }
2120
2121 int
2122 rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
2123                              struct ether_addr *mac_addr)
2124 {
2125         struct rte_eth_dev *dev;
2126         struct i40e_pf_vf *vf;
2127         struct i40e_vsi *vsi;
2128         struct i40e_pf *pf;
2129         struct i40e_mac_filter_info mac_filter;
2130         int ret;
2131
2132         if (i40e_validate_mac_addr((u8 *)mac_addr) != I40E_SUCCESS)
2133                 return -EINVAL;
2134
2135         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2136
2137         dev = &rte_eth_devices[port];
2138
2139         if (!is_i40e_supported(dev))
2140                 return -ENOTSUP;
2141
2142         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
2143
2144         if (vf_id >= pf->vf_num || !pf->vfs)
2145                 return -EINVAL;
2146
2147         vf = &pf->vfs[vf_id];
2148         vsi = vf->vsi;
2149         if (!vsi) {
2150                 PMD_DRV_LOG(ERR, "Invalid VSI.");
2151                 return -EINVAL;
2152         }
2153
2154         mac_filter.filter_type = RTE_MACVLAN_PERFECT_MATCH;
2155         ether_addr_copy(mac_addr, &mac_filter.mac_addr);
2156         ret = i40e_vsi_add_mac(vsi, &mac_filter);
2157         if (ret != I40E_SUCCESS) {
2158                 PMD_DRV_LOG(ERR, "Failed to add MAC filter.");
2159                 return -1;
2160         }
2161
2162         return 0;
2163 }