f12b7f4a19cb190bae0d89e897a805b3fa0e6a7c
[deb_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                 i40e_vsi_delete_mac(vsi, &f->mac_info.mac_addr);
595
596         return 0;
597 }
598
599 /* Set vlan strip on/off for specific VF from host */
600 int
601 rte_pmd_i40e_set_vf_vlan_stripq(uint8_t port, uint16_t vf_id, uint8_t on)
602 {
603         struct rte_eth_dev *dev;
604         struct i40e_pf *pf;
605         struct i40e_vsi *vsi;
606         int ret;
607
608         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
609
610         dev = &rte_eth_devices[port];
611
612         if (!is_i40e_supported(dev))
613                 return -ENOTSUP;
614
615         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
616
617         if (vf_id >= pf->vf_num || !pf->vfs) {
618                 PMD_DRV_LOG(ERR, "Invalid argument.");
619                 return -EINVAL;
620         }
621
622         vsi = pf->vfs[vf_id].vsi;
623
624         if (!vsi)
625                 return -EINVAL;
626
627         ret = i40e_vsi_config_vlan_stripping(vsi, !!on);
628         if (ret != I40E_SUCCESS) {
629                 ret = -ENOTSUP;
630                 PMD_DRV_LOG(ERR, "Failed to set VLAN stripping!");
631         }
632
633         return ret;
634 }
635
636 int rte_pmd_i40e_set_vf_vlan_insert(uint8_t port, uint16_t vf_id,
637                                     uint16_t vlan_id)
638 {
639         struct rte_eth_dev *dev;
640         struct i40e_pf *pf;
641         struct i40e_hw *hw;
642         struct i40e_vsi *vsi;
643         struct i40e_vsi_context ctxt;
644         int ret;
645
646         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
647
648         if (vlan_id > ETHER_MAX_VLAN_ID) {
649                 PMD_DRV_LOG(ERR, "Invalid VLAN ID.");
650                 return -EINVAL;
651         }
652
653         dev = &rte_eth_devices[port];
654
655         if (!is_i40e_supported(dev))
656                 return -ENOTSUP;
657
658         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
659         hw = I40E_PF_TO_HW(pf);
660
661         /**
662          * return -ENODEV if SRIOV not enabled, VF number not configured
663          * or no queue assigned.
664          */
665         if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
666             pf->vf_nb_qps == 0)
667                 return -ENODEV;
668
669         if (vf_id >= pf->vf_num || !pf->vfs) {
670                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
671                 return -EINVAL;
672         }
673
674         vsi = pf->vfs[vf_id].vsi;
675         if (!vsi) {
676                 PMD_DRV_LOG(ERR, "Invalid VSI.");
677                 return -EINVAL;
678         }
679
680         vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID);
681         vsi->info.pvid = vlan_id;
682         if (vlan_id > 0)
683                 vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_INSERT_PVID;
684         else
685                 vsi->info.port_vlan_flags &= ~I40E_AQ_VSI_PVLAN_INSERT_PVID;
686
687         memset(&ctxt, 0, sizeof(ctxt));
688         (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
689         ctxt.seid = vsi->seid;
690
691         hw = I40E_VSI_TO_HW(vsi);
692         ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
693         if (ret != I40E_SUCCESS) {
694                 ret = -ENOTSUP;
695                 PMD_DRV_LOG(ERR, "Failed to update VSI params");
696         }
697
698         return ret;
699 }
700
701 int rte_pmd_i40e_set_vf_broadcast(uint8_t port, uint16_t vf_id,
702                                   uint8_t on)
703 {
704         struct rte_eth_dev *dev;
705         struct i40e_pf *pf;
706         struct i40e_vsi *vsi;
707         struct i40e_hw *hw;
708         struct i40e_mac_filter_info filter;
709         struct ether_addr broadcast = {
710                 .addr_bytes = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} };
711         int ret;
712
713         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
714
715         if (on > 1) {
716                 PMD_DRV_LOG(ERR, "on should be 0 or 1.");
717                 return -EINVAL;
718         }
719
720         dev = &rte_eth_devices[port];
721
722         if (!is_i40e_supported(dev))
723                 return -ENOTSUP;
724
725         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
726         hw = I40E_PF_TO_HW(pf);
727
728         if (vf_id >= pf->vf_num || !pf->vfs) {
729                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
730                 return -EINVAL;
731         }
732
733         /**
734          * return -ENODEV if SRIOV not enabled, VF number not configured
735          * or no queue assigned.
736          */
737         if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
738             pf->vf_nb_qps == 0) {
739                 PMD_DRV_LOG(ERR, "SRIOV is not enabled or no queue.");
740                 return -ENODEV;
741         }
742
743         vsi = pf->vfs[vf_id].vsi;
744         if (!vsi) {
745                 PMD_DRV_LOG(ERR, "Invalid VSI.");
746                 return -EINVAL;
747         }
748
749         if (on) {
750                 (void)rte_memcpy(&filter.mac_addr, &broadcast, ETHER_ADDR_LEN);
751                 filter.filter_type = RTE_MACVLAN_PERFECT_MATCH;
752                 ret = i40e_vsi_add_mac(vsi, &filter);
753         } else {
754                 ret = i40e_vsi_delete_mac(vsi, &broadcast);
755         }
756
757         if (ret != I40E_SUCCESS && ret != I40E_ERR_PARAM) {
758                 ret = -ENOTSUP;
759                 PMD_DRV_LOG(ERR, "Failed to set VSI broadcast");
760         } else {
761                 ret = 0;
762         }
763
764         return ret;
765 }
766
767 int rte_pmd_i40e_set_vf_vlan_tag(uint8_t port, uint16_t vf_id, uint8_t on)
768 {
769         struct rte_eth_dev *dev;
770         struct i40e_pf *pf;
771         struct i40e_hw *hw;
772         struct i40e_vsi *vsi;
773         struct i40e_vsi_context ctxt;
774         int ret;
775
776         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
777
778         if (on > 1) {
779                 PMD_DRV_LOG(ERR, "on should be 0 or 1.");
780                 return -EINVAL;
781         }
782
783         dev = &rte_eth_devices[port];
784
785         if (!is_i40e_supported(dev))
786                 return -ENOTSUP;
787
788         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
789         hw = I40E_PF_TO_HW(pf);
790
791         /**
792          * return -ENODEV if SRIOV not enabled, VF number not configured
793          * or no queue assigned.
794          */
795         if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
796             pf->vf_nb_qps == 0) {
797                 PMD_DRV_LOG(ERR, "SRIOV is not enabled or no queue.");
798                 return -ENODEV;
799         }
800
801         if (vf_id >= pf->vf_num || !pf->vfs) {
802                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
803                 return -EINVAL;
804         }
805
806         vsi = pf->vfs[vf_id].vsi;
807         if (!vsi) {
808                 PMD_DRV_LOG(ERR, "Invalid VSI.");
809                 return -EINVAL;
810         }
811
812         vsi->info.valid_sections = cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID);
813         if (on) {
814                 vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_TAGGED;
815                 vsi->info.port_vlan_flags &= ~I40E_AQ_VSI_PVLAN_MODE_UNTAGGED;
816         } else {
817                 vsi->info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_MODE_UNTAGGED;
818                 vsi->info.port_vlan_flags &= ~I40E_AQ_VSI_PVLAN_MODE_TAGGED;
819         }
820
821         memset(&ctxt, 0, sizeof(ctxt));
822         (void)rte_memcpy(&ctxt.info, &vsi->info, sizeof(vsi->info));
823         ctxt.seid = vsi->seid;
824
825         hw = I40E_VSI_TO_HW(vsi);
826         ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
827         if (ret != I40E_SUCCESS) {
828                 ret = -ENOTSUP;
829                 PMD_DRV_LOG(ERR, "Failed to update VSI params");
830         }
831
832         return ret;
833 }
834
835 static int
836 i40e_vlan_filter_count(struct i40e_vsi *vsi)
837 {
838         uint32_t j, k;
839         uint16_t vlan_id;
840         int count = 0;
841
842         for (j = 0; j < I40E_VFTA_SIZE; j++) {
843                 if (!vsi->vfta[j])
844                         continue;
845
846                 for (k = 0; k < I40E_UINT32_BIT_SIZE; k++) {
847                         if (!(vsi->vfta[j] & (1 << k)))
848                                 continue;
849
850                         vlan_id = j * I40E_UINT32_BIT_SIZE + k;
851                         if (!vlan_id)
852                                 continue;
853
854                         count++;
855                 }
856         }
857
858         return count;
859 }
860
861 int rte_pmd_i40e_set_vf_vlan_filter(uint8_t port, uint16_t vlan_id,
862                                     uint64_t vf_mask, uint8_t on)
863 {
864         struct rte_eth_dev *dev;
865         struct i40e_pf *pf;
866         struct i40e_hw *hw;
867         struct i40e_vsi *vsi;
868         uint16_t vf_idx;
869         int ret = I40E_SUCCESS;
870
871         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
872
873         dev = &rte_eth_devices[port];
874
875         if (!is_i40e_supported(dev))
876                 return -ENOTSUP;
877
878         if (vlan_id > ETHER_MAX_VLAN_ID || !vlan_id) {
879                 PMD_DRV_LOG(ERR, "Invalid VLAN ID.");
880                 return -EINVAL;
881         }
882
883         if (vf_mask == 0) {
884                 PMD_DRV_LOG(ERR, "No VF.");
885                 return -EINVAL;
886         }
887
888         if (on > 1) {
889                 PMD_DRV_LOG(ERR, "on is should be 0 or 1.");
890                 return -EINVAL;
891         }
892
893         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
894         hw = I40E_PF_TO_HW(pf);
895
896         /**
897          * return -ENODEV if SRIOV not enabled, VF number not configured
898          * or no queue assigned.
899          */
900         if (!hw->func_caps.sr_iov_1_1 || pf->vf_num == 0 ||
901             pf->vf_nb_qps == 0) {
902                 PMD_DRV_LOG(ERR, "SRIOV is not enabled or no queue.");
903                 return -ENODEV;
904         }
905
906         for (vf_idx = 0; vf_idx < pf->vf_num && ret == I40E_SUCCESS; vf_idx++) {
907                 if (vf_mask & ((uint64_t)(1ULL << vf_idx))) {
908                         vsi = pf->vfs[vf_idx].vsi;
909                         if (on) {
910                                 if (!vsi->vlan_filter_on) {
911                                         vsi->vlan_filter_on = true;
912                                         i40e_aq_set_vsi_vlan_promisc(hw,
913                                                                      vsi->seid,
914                                                                      false,
915                                                                      NULL);
916                                         if (!vsi->vlan_anti_spoof_on)
917                                                 i40e_add_rm_all_vlan_filter(
918                                                         vsi, true);
919                                 }
920                                 ret = i40e_vsi_add_vlan(vsi, vlan_id);
921                         } else {
922                                 ret = i40e_vsi_delete_vlan(vsi, vlan_id);
923
924                                 if (!i40e_vlan_filter_count(vsi)) {
925                                         vsi->vlan_filter_on = false;
926                                         i40e_aq_set_vsi_vlan_promisc(hw,
927                                                                      vsi->seid,
928                                                                      true,
929                                                                      NULL);
930                                 }
931                         }
932                 }
933         }
934
935         if (ret != I40E_SUCCESS) {
936                 ret = -ENOTSUP;
937                 PMD_DRV_LOG(ERR, "Failed to set VF VLAN filter, on = %d", on);
938         }
939
940         return ret;
941 }
942
943 int
944 rte_pmd_i40e_get_vf_stats(uint8_t port,
945                           uint16_t vf_id,
946                           struct rte_eth_stats *stats)
947 {
948         struct rte_eth_dev *dev;
949         struct i40e_pf *pf;
950         struct i40e_vsi *vsi;
951
952         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
953
954         dev = &rte_eth_devices[port];
955
956         if (!is_i40e_supported(dev))
957                 return -ENOTSUP;
958
959         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
960
961         if (vf_id >= pf->vf_num || !pf->vfs) {
962                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
963                 return -EINVAL;
964         }
965
966         vsi = pf->vfs[vf_id].vsi;
967         if (!vsi) {
968                 PMD_DRV_LOG(ERR, "Invalid VSI.");
969                 return -EINVAL;
970         }
971
972         i40e_update_vsi_stats(vsi);
973
974         stats->ipackets = vsi->eth_stats.rx_unicast +
975                         vsi->eth_stats.rx_multicast +
976                         vsi->eth_stats.rx_broadcast;
977         stats->opackets = vsi->eth_stats.tx_unicast +
978                         vsi->eth_stats.tx_multicast +
979                         vsi->eth_stats.tx_broadcast;
980         stats->ibytes   = vsi->eth_stats.rx_bytes;
981         stats->obytes   = vsi->eth_stats.tx_bytes;
982         stats->ierrors  = vsi->eth_stats.rx_discards;
983         stats->oerrors  = vsi->eth_stats.tx_errors + vsi->eth_stats.tx_discards;
984
985         return 0;
986 }
987
988 int
989 rte_pmd_i40e_reset_vf_stats(uint8_t port,
990                             uint16_t vf_id)
991 {
992         struct rte_eth_dev *dev;
993         struct i40e_pf *pf;
994         struct i40e_vsi *vsi;
995
996         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
997
998         dev = &rte_eth_devices[port];
999
1000         if (!is_i40e_supported(dev))
1001                 return -ENOTSUP;
1002
1003         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1004
1005         if (vf_id >= pf->vf_num || !pf->vfs) {
1006                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
1007                 return -EINVAL;
1008         }
1009
1010         vsi = pf->vfs[vf_id].vsi;
1011         if (!vsi) {
1012                 PMD_DRV_LOG(ERR, "Invalid VSI.");
1013                 return -EINVAL;
1014         }
1015
1016         vsi->offset_loaded = false;
1017         i40e_update_vsi_stats(vsi);
1018
1019         return 0;
1020 }
1021
1022 int
1023 rte_pmd_i40e_set_vf_max_bw(uint8_t port, uint16_t vf_id, uint32_t bw)
1024 {
1025         struct rte_eth_dev *dev;
1026         struct i40e_pf *pf;
1027         struct i40e_vsi *vsi;
1028         struct i40e_hw *hw;
1029         int ret = 0;
1030         int i;
1031
1032         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
1033
1034         dev = &rte_eth_devices[port];
1035
1036         if (!is_i40e_supported(dev))
1037                 return -ENOTSUP;
1038
1039         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1040
1041         if (vf_id >= pf->vf_num || !pf->vfs) {
1042                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
1043                 return -EINVAL;
1044         }
1045
1046         vsi = pf->vfs[vf_id].vsi;
1047         if (!vsi) {
1048                 PMD_DRV_LOG(ERR, "Invalid VSI.");
1049                 return -EINVAL;
1050         }
1051
1052         if (bw > I40E_QOS_BW_MAX) {
1053                 PMD_DRV_LOG(ERR, "Bandwidth should not be larger than %dMbps.",
1054                             I40E_QOS_BW_MAX);
1055                 return -EINVAL;
1056         }
1057
1058         if (bw % I40E_QOS_BW_GRANULARITY) {
1059                 PMD_DRV_LOG(ERR, "Bandwidth should be the multiple of %dMbps.",
1060                             I40E_QOS_BW_GRANULARITY);
1061                 return -EINVAL;
1062         }
1063
1064         bw /= I40E_QOS_BW_GRANULARITY;
1065
1066         hw = I40E_VSI_TO_HW(vsi);
1067
1068         /* No change. */
1069         if (bw == vsi->bw_info.bw_limit) {
1070                 PMD_DRV_LOG(INFO,
1071                             "No change for VF max bandwidth. Nothing to do.");
1072                 return 0;
1073         }
1074
1075         /**
1076          * VF bandwidth limitation and TC bandwidth limitation cannot be
1077          * enabled in parallel, quit if TC bandwidth limitation is enabled.
1078          *
1079          * If bw is 0, means disable bandwidth limitation. Then no need to
1080          * check TC bandwidth limitation.
1081          */
1082         if (bw) {
1083                 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1084                         if ((vsi->enabled_tc & BIT_ULL(i)) &&
1085                             vsi->bw_info.bw_ets_credits[i])
1086                                 break;
1087                 }
1088                 if (i != I40E_MAX_TRAFFIC_CLASS) {
1089                         PMD_DRV_LOG(ERR,
1090                                     "TC max bandwidth has been set on this VF,"
1091                                     " please disable it first.");
1092                         return -EINVAL;
1093                 }
1094         }
1095
1096         ret = i40e_aq_config_vsi_bw_limit(hw, vsi->seid, (uint16_t)bw, 0, NULL);
1097         if (ret) {
1098                 PMD_DRV_LOG(ERR,
1099                             "Failed to set VF %d bandwidth, err(%d).",
1100                             vf_id, ret);
1101                 return -EINVAL;
1102         }
1103
1104         /* Store the configuration. */
1105         vsi->bw_info.bw_limit = (uint16_t)bw;
1106         vsi->bw_info.bw_max = 0;
1107
1108         return 0;
1109 }
1110
1111 int
1112 rte_pmd_i40e_set_vf_tc_bw_alloc(uint8_t port, uint16_t vf_id,
1113                                 uint8_t tc_num, uint8_t *bw_weight)
1114 {
1115         struct rte_eth_dev *dev;
1116         struct i40e_pf *pf;
1117         struct i40e_vsi *vsi;
1118         struct i40e_hw *hw;
1119         struct i40e_aqc_configure_vsi_tc_bw_data tc_bw;
1120         int ret = 0;
1121         int i, j;
1122         uint16_t sum;
1123         bool b_change = false;
1124
1125         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
1126
1127         dev = &rte_eth_devices[port];
1128
1129         if (!is_i40e_supported(dev))
1130                 return -ENOTSUP;
1131
1132         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1133
1134         if (vf_id >= pf->vf_num || !pf->vfs) {
1135                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
1136                 return -EINVAL;
1137         }
1138
1139         vsi = pf->vfs[vf_id].vsi;
1140         if (!vsi) {
1141                 PMD_DRV_LOG(ERR, "Invalid VSI.");
1142                 return -EINVAL;
1143         }
1144
1145         if (tc_num > I40E_MAX_TRAFFIC_CLASS) {
1146                 PMD_DRV_LOG(ERR, "TCs should be no more than %d.",
1147                             I40E_MAX_TRAFFIC_CLASS);
1148                 return -EINVAL;
1149         }
1150
1151         sum = 0;
1152         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1153                 if (vsi->enabled_tc & BIT_ULL(i))
1154                         sum++;
1155         }
1156         if (sum != tc_num) {
1157                 PMD_DRV_LOG(ERR,
1158                             "Weight should be set for all %d enabled TCs.",
1159                             sum);
1160                 return -EINVAL;
1161         }
1162
1163         sum = 0;
1164         for (i = 0; i < tc_num; i++) {
1165                 if (!bw_weight[i]) {
1166                         PMD_DRV_LOG(ERR,
1167                                     "The weight should be 1 at least.");
1168                         return -EINVAL;
1169                 }
1170                 sum += bw_weight[i];
1171         }
1172         if (sum != 100) {
1173                 PMD_DRV_LOG(ERR,
1174                             "The summary of the TC weight should be 100.");
1175                 return -EINVAL;
1176         }
1177
1178         /**
1179          * Create the configuration for all the TCs.
1180          */
1181         memset(&tc_bw, 0, sizeof(tc_bw));
1182         tc_bw.tc_valid_bits = vsi->enabled_tc;
1183         j = 0;
1184         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1185                 if (vsi->enabled_tc & BIT_ULL(i)) {
1186                         if (bw_weight[j] !=
1187                                 vsi->bw_info.bw_ets_share_credits[i])
1188                                 b_change = true;
1189
1190                         tc_bw.tc_bw_credits[i] = bw_weight[j];
1191                         j++;
1192                 }
1193         }
1194
1195         /* No change. */
1196         if (!b_change) {
1197                 PMD_DRV_LOG(INFO,
1198                             "No change for TC allocated bandwidth."
1199                             " Nothing to do.");
1200                 return 0;
1201         }
1202
1203         hw = I40E_VSI_TO_HW(vsi);
1204
1205         ret = i40e_aq_config_vsi_tc_bw(hw, vsi->seid, &tc_bw, NULL);
1206         if (ret) {
1207                 PMD_DRV_LOG(ERR,
1208                             "Failed to set VF %d TC bandwidth weight, err(%d).",
1209                             vf_id, ret);
1210                 return -EINVAL;
1211         }
1212
1213         /* Store the configuration. */
1214         j = 0;
1215         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1216                 if (vsi->enabled_tc & BIT_ULL(i)) {
1217                         vsi->bw_info.bw_ets_share_credits[i] = bw_weight[j];
1218                         j++;
1219                 }
1220         }
1221
1222         return 0;
1223 }
1224
1225 int
1226 rte_pmd_i40e_set_vf_tc_max_bw(uint8_t port, uint16_t vf_id,
1227                               uint8_t tc_no, uint32_t bw)
1228 {
1229         struct rte_eth_dev *dev;
1230         struct i40e_pf *pf;
1231         struct i40e_vsi *vsi;
1232         struct i40e_hw *hw;
1233         struct i40e_aqc_configure_vsi_ets_sla_bw_data tc_bw;
1234         int ret = 0;
1235         int i;
1236
1237         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
1238
1239         dev = &rte_eth_devices[port];
1240
1241         if (!is_i40e_supported(dev))
1242                 return -ENOTSUP;
1243
1244         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1245
1246         if (vf_id >= pf->vf_num || !pf->vfs) {
1247                 PMD_DRV_LOG(ERR, "Invalid VF ID.");
1248                 return -EINVAL;
1249         }
1250
1251         vsi = pf->vfs[vf_id].vsi;
1252         if (!vsi) {
1253                 PMD_DRV_LOG(ERR, "Invalid VSI.");
1254                 return -EINVAL;
1255         }
1256
1257         if (bw > I40E_QOS_BW_MAX) {
1258                 PMD_DRV_LOG(ERR, "Bandwidth should not be larger than %dMbps.",
1259                             I40E_QOS_BW_MAX);
1260                 return -EINVAL;
1261         }
1262
1263         if (bw % I40E_QOS_BW_GRANULARITY) {
1264                 PMD_DRV_LOG(ERR, "Bandwidth should be the multiple of %dMbps.",
1265                             I40E_QOS_BW_GRANULARITY);
1266                 return -EINVAL;
1267         }
1268
1269         bw /= I40E_QOS_BW_GRANULARITY;
1270
1271         if (tc_no >= I40E_MAX_TRAFFIC_CLASS) {
1272                 PMD_DRV_LOG(ERR, "TC No. should be less than %d.",
1273                             I40E_MAX_TRAFFIC_CLASS);
1274                 return -EINVAL;
1275         }
1276
1277         hw = I40E_VSI_TO_HW(vsi);
1278
1279         if (!(vsi->enabled_tc & BIT_ULL(tc_no))) {
1280                 PMD_DRV_LOG(ERR, "VF %d TC %d isn't enabled.",
1281                             vf_id, tc_no);
1282                 return -EINVAL;
1283         }
1284
1285         /* No change. */
1286         if (bw == vsi->bw_info.bw_ets_credits[tc_no]) {
1287                 PMD_DRV_LOG(INFO,
1288                             "No change for TC max bandwidth. Nothing to do.");
1289                 return 0;
1290         }
1291
1292         /**
1293          * VF bandwidth limitation and TC bandwidth limitation cannot be
1294          * enabled in parallel, disable VF bandwidth limitation if it's
1295          * enabled.
1296          * If bw is 0, means disable bandwidth limitation. Then no need to
1297          * care about VF bandwidth limitation configuration.
1298          */
1299         if (bw && vsi->bw_info.bw_limit) {
1300                 ret = i40e_aq_config_vsi_bw_limit(hw, vsi->seid, 0, 0, NULL);
1301                 if (ret) {
1302                         PMD_DRV_LOG(ERR,
1303                                     "Failed to disable VF(%d)"
1304                                     " bandwidth limitation, err(%d).",
1305                                     vf_id, ret);
1306                         return -EINVAL;
1307                 }
1308
1309                 PMD_DRV_LOG(INFO,
1310                             "VF max bandwidth is disabled according"
1311                             " to TC max bandwidth setting.");
1312         }
1313
1314         /**
1315          * Get all the TCs' info to create a whole picture.
1316          * Because the incremental change isn't permitted.
1317          */
1318         memset(&tc_bw, 0, sizeof(tc_bw));
1319         tc_bw.tc_valid_bits = vsi->enabled_tc;
1320         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1321                 if (vsi->enabled_tc & BIT_ULL(i)) {
1322                         tc_bw.tc_bw_credits[i] =
1323                                 rte_cpu_to_le_16(
1324                                         vsi->bw_info.bw_ets_credits[i]);
1325                 }
1326         }
1327         tc_bw.tc_bw_credits[tc_no] = rte_cpu_to_le_16((uint16_t)bw);
1328
1329         ret = i40e_aq_config_vsi_ets_sla_bw_limit(hw, vsi->seid, &tc_bw, NULL);
1330         if (ret) {
1331                 PMD_DRV_LOG(ERR,
1332                             "Failed to set VF %d TC %d max bandwidth, err(%d).",
1333                             vf_id, tc_no, ret);
1334                 return -EINVAL;
1335         }
1336
1337         /* Store the configuration. */
1338         vsi->bw_info.bw_ets_credits[tc_no] = (uint16_t)bw;
1339
1340         return 0;
1341 }
1342
1343 int
1344 rte_pmd_i40e_set_tc_strict_prio(uint8_t port, uint8_t tc_map)
1345 {
1346         struct rte_eth_dev *dev;
1347         struct i40e_pf *pf;
1348         struct i40e_vsi *vsi;
1349         struct i40e_veb *veb;
1350         struct i40e_hw *hw;
1351         struct i40e_aqc_configure_switching_comp_ets_data ets_data;
1352         int i;
1353         int ret;
1354
1355         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
1356
1357         dev = &rte_eth_devices[port];
1358
1359         if (!is_i40e_supported(dev))
1360                 return -ENOTSUP;
1361
1362         pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1363
1364         vsi = pf->main_vsi;
1365         if (!vsi) {
1366                 PMD_DRV_LOG(ERR, "Invalid VSI.");
1367                 return -EINVAL;
1368         }
1369
1370         veb = vsi->veb;
1371         if (!veb) {
1372                 PMD_DRV_LOG(ERR, "Invalid VEB.");
1373                 return -EINVAL;
1374         }
1375
1376         if ((tc_map & veb->enabled_tc) != tc_map) {
1377                 PMD_DRV_LOG(ERR,
1378                             "TC bitmap isn't the subset of enabled TCs 0x%x.",
1379                             veb->enabled_tc);
1380                 return -EINVAL;
1381         }
1382
1383         if (tc_map == veb->strict_prio_tc) {
1384                 PMD_DRV_LOG(INFO, "No change for TC bitmap. Nothing to do.");
1385                 return 0;
1386         }
1387
1388         hw = I40E_VSI_TO_HW(vsi);
1389
1390         /* Disable DCBx if it's the first time to set strict priority. */
1391         if (!veb->strict_prio_tc) {
1392                 ret = i40e_aq_stop_lldp(hw, true, NULL);
1393                 if (ret)
1394                         PMD_DRV_LOG(INFO,
1395                                     "Failed to disable DCBx as it's already"
1396                                     " disabled.");
1397                 else
1398                         PMD_DRV_LOG(INFO,
1399                                     "DCBx is disabled according to strict"
1400                                     " priority setting.");
1401         }
1402
1403         memset(&ets_data, 0, sizeof(ets_data));
1404         ets_data.tc_valid_bits = veb->enabled_tc;
1405         ets_data.seepage = I40E_AQ_ETS_SEEPAGE_EN_MASK;
1406         ets_data.tc_strict_priority_flags = tc_map;
1407         /* Get all TCs' bandwidth. */
1408         for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
1409                 if (veb->enabled_tc & BIT_ULL(i)) {
1410                         /* For rubust, if bandwidth is 0, use 1 instead. */
1411                         if (veb->bw_info.bw_ets_share_credits[i])
1412                                 ets_data.tc_bw_share_credits[i] =
1413                                         veb->bw_info.bw_ets_share_credits[i];
1414                         else
1415                                 ets_data.tc_bw_share_credits[i] =
1416                                         I40E_QOS_BW_WEIGHT_MIN;
1417                 }
1418         }
1419
1420         if (!veb->strict_prio_tc)
1421                 ret = i40e_aq_config_switch_comp_ets(
1422                         hw, veb->uplink_seid,
1423                         &ets_data, i40e_aqc_opc_enable_switching_comp_ets,
1424                         NULL);
1425         else if (tc_map)
1426                 ret = i40e_aq_config_switch_comp_ets(
1427                         hw, veb->uplink_seid,
1428                         &ets_data, i40e_aqc_opc_modify_switching_comp_ets,
1429                         NULL);
1430         else
1431                 ret = i40e_aq_config_switch_comp_ets(
1432                         hw, veb->uplink_seid,
1433                         &ets_data, i40e_aqc_opc_disable_switching_comp_ets,
1434                         NULL);
1435
1436         if (ret) {
1437                 PMD_DRV_LOG(ERR,
1438                             "Failed to set TCs' strict priority mode."
1439                             " err (%d)", ret);
1440                 return -EINVAL;
1441         }
1442
1443         veb->strict_prio_tc = tc_map;
1444
1445         /* Enable DCBx again, if all the TCs' strict priority disabled. */
1446         if (!tc_map) {
1447                 ret = i40e_aq_start_lldp(hw, NULL);
1448                 if (ret) {
1449                         PMD_DRV_LOG(ERR,
1450                                     "Failed to enable DCBx, err(%d).", ret);
1451                         return -EINVAL;
1452                 }
1453
1454                 PMD_DRV_LOG(INFO,
1455                             "DCBx is enabled again according to strict"
1456                             " priority setting.");
1457         }
1458
1459         return ret;
1460 }
1461
1462 #define I40E_PROFILE_INFO_SIZE sizeof(struct rte_pmd_i40e_profile_info)
1463 #define I40E_MAX_PROFILE_NUM 16
1464
1465 static void
1466 i40e_generate_profile_info_sec(char *name, struct i40e_ddp_version *version,
1467                                uint32_t track_id, uint8_t *profile_info_sec,
1468                                bool add)
1469 {
1470         struct i40e_profile_section_header *sec = NULL;
1471         struct i40e_profile_info *pinfo;
1472
1473         sec = (struct i40e_profile_section_header *)profile_info_sec;
1474         sec->tbl_size = 1;
1475         sec->data_end = sizeof(struct i40e_profile_section_header) +
1476                 sizeof(struct i40e_profile_info);
1477         sec->section.type = SECTION_TYPE_INFO;
1478         sec->section.offset = sizeof(struct i40e_profile_section_header);
1479         sec->section.size = sizeof(struct i40e_profile_info);
1480         pinfo = (struct i40e_profile_info *)(profile_info_sec +
1481                                              sec->section.offset);
1482         pinfo->track_id = track_id;
1483         memcpy(pinfo->name, name, I40E_DDP_NAME_SIZE);
1484         memcpy(&pinfo->version, version, sizeof(struct i40e_ddp_version));
1485         if (add)
1486                 pinfo->op = I40E_DDP_ADD_TRACKID;
1487         else
1488                 pinfo->op = I40E_DDP_REMOVE_TRACKID;
1489 }
1490
1491 static enum i40e_status_code
1492 i40e_add_rm_profile_info(struct i40e_hw *hw, uint8_t *profile_info_sec)
1493 {
1494         enum i40e_status_code status = I40E_SUCCESS;
1495         struct i40e_profile_section_header *sec;
1496         uint32_t track_id;
1497         uint32_t offset = 0;
1498         uint32_t info = 0;
1499
1500         sec = (struct i40e_profile_section_header *)profile_info_sec;
1501         track_id = ((struct i40e_profile_info *)(profile_info_sec +
1502                                          sec->section.offset))->track_id;
1503
1504         status = i40e_aq_write_ddp(hw, (void *)sec, sec->data_end,
1505                                    track_id, &offset, &info, NULL);
1506         if (status)
1507                 PMD_DRV_LOG(ERR, "Failed to add/remove profile info: "
1508                             "offset %d, info %d",
1509                             offset, info);
1510
1511         return status;
1512 }
1513
1514 /* Check if the profile info exists */
1515 static int
1516 i40e_check_profile_info(uint8_t port, uint8_t *profile_info_sec)
1517 {
1518         struct rte_eth_dev *dev = &rte_eth_devices[port];
1519         struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1520         uint8_t *buff;
1521         struct rte_pmd_i40e_profile_list *p_list;
1522         struct rte_pmd_i40e_profile_info *pinfo, *p;
1523         uint32_t i;
1524         int ret;
1525
1526         buff = rte_zmalloc("pinfo_list",
1527                            (I40E_PROFILE_INFO_SIZE * I40E_MAX_PROFILE_NUM + 4),
1528                            0);
1529         if (!buff) {
1530                 PMD_DRV_LOG(ERR, "failed to allocate memory");
1531                 return -1;
1532         }
1533
1534         ret = i40e_aq_get_ddp_list(
1535                 hw, (void *)buff,
1536                 (I40E_PROFILE_INFO_SIZE * I40E_MAX_PROFILE_NUM + 4),
1537                 0, NULL);
1538         if (ret) {
1539                 PMD_DRV_LOG(ERR, "Failed to get profile info list.");
1540                 rte_free(buff);
1541                 return -1;
1542         }
1543         p_list = (struct rte_pmd_i40e_profile_list *)buff;
1544         pinfo = (struct rte_pmd_i40e_profile_info *)(profile_info_sec +
1545                              sizeof(struct i40e_profile_section_header));
1546         for (i = 0; i < p_list->p_count; i++) {
1547                 p = &p_list->p_info[i];
1548                 if (pinfo->track_id == p->track_id) {
1549                         PMD_DRV_LOG(INFO, "Profile exists.");
1550                         rte_free(buff);
1551                         return 1;
1552                 }
1553         }
1554
1555         rte_free(buff);
1556         return 0;
1557 }
1558
1559 int
1560 rte_pmd_i40e_process_ddp_package(uint8_t port, uint8_t *buff,
1561                                  uint32_t size,
1562                                  enum rte_pmd_i40e_package_op op)
1563 {
1564         struct rte_eth_dev *dev;
1565         struct i40e_hw *hw;
1566         struct i40e_package_header *pkg_hdr;
1567         struct i40e_generic_seg_header *profile_seg_hdr;
1568         struct i40e_generic_seg_header *metadata_seg_hdr;
1569         uint32_t track_id;
1570         uint8_t *profile_info_sec;
1571         int is_exist;
1572         enum i40e_status_code status = I40E_SUCCESS;
1573
1574         if (op != RTE_PMD_I40E_PKG_OP_WR_ADD &&
1575                 op != RTE_PMD_I40E_PKG_OP_WR_ONLY &&
1576                 op != RTE_PMD_I40E_PKG_OP_WR_DEL) {
1577                 PMD_DRV_LOG(ERR, "Operation not supported.");
1578                 return -ENOTSUP;
1579         }
1580
1581         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
1582
1583         dev = &rte_eth_devices[port];
1584
1585         if (!is_i40e_supported(dev))
1586                 return -ENOTSUP;
1587
1588         hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1589
1590         if (size < (sizeof(struct i40e_package_header) +
1591                     sizeof(struct i40e_metadata_segment) +
1592                     sizeof(uint32_t) * 2)) {
1593                 PMD_DRV_LOG(ERR, "Buff is invalid.");
1594                 return -EINVAL;
1595         }
1596
1597         pkg_hdr = (struct i40e_package_header *)buff;
1598
1599         if (!pkg_hdr) {
1600                 PMD_DRV_LOG(ERR, "Failed to fill the package structure");
1601                 return -EINVAL;
1602         }
1603
1604         if (pkg_hdr->segment_count < 2) {
1605                 PMD_DRV_LOG(ERR, "Segment_count should be 2 at least.");
1606                 return -EINVAL;
1607         }
1608
1609         /* Find metadata segment */
1610         metadata_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_METADATA,
1611                                                         pkg_hdr);
1612         if (!metadata_seg_hdr) {
1613                 PMD_DRV_LOG(ERR, "Failed to find metadata segment header");
1614                 return -EINVAL;
1615         }
1616         track_id = ((struct i40e_metadata_segment *)metadata_seg_hdr)->track_id;
1617         if (track_id == I40E_DDP_TRACKID_INVALID) {
1618                 PMD_DRV_LOG(ERR, "Invalid track_id");
1619                 return -EINVAL;
1620         }
1621
1622         /* Find profile segment */
1623         profile_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_I40E,
1624                                                        pkg_hdr);
1625         if (!profile_seg_hdr) {
1626                 PMD_DRV_LOG(ERR, "Failed to find profile segment header");
1627                 return -EINVAL;
1628         }
1629
1630         profile_info_sec = rte_zmalloc(
1631                 "i40e_profile_info",
1632                 sizeof(struct i40e_profile_section_header) +
1633                 sizeof(struct i40e_profile_info),
1634                 0);
1635         if (!profile_info_sec) {
1636                 PMD_DRV_LOG(ERR, "Failed to allocate memory");
1637                 return -EINVAL;
1638         }
1639
1640         /* Check if the profile already loaded */
1641         i40e_generate_profile_info_sec(
1642                 ((struct i40e_profile_segment *)profile_seg_hdr)->name,
1643                 &((struct i40e_profile_segment *)profile_seg_hdr)->version,
1644                 track_id, profile_info_sec,
1645                 op == RTE_PMD_I40E_PKG_OP_WR_ADD);
1646         is_exist = i40e_check_profile_info(port, profile_info_sec);
1647         if (is_exist < 0) {
1648                 PMD_DRV_LOG(ERR, "Failed to check profile.");
1649                 rte_free(profile_info_sec);
1650                 return -EINVAL;
1651         }
1652
1653         if (op == RTE_PMD_I40E_PKG_OP_WR_ADD) {
1654                 if (is_exist) {
1655                         PMD_DRV_LOG(ERR, "Profile already exists.");
1656                         rte_free(profile_info_sec);
1657                         return -EEXIST;
1658                 }
1659         } else if (op == RTE_PMD_I40E_PKG_OP_WR_DEL) {
1660                 if (!is_exist) {
1661                         PMD_DRV_LOG(ERR, "Profile does not exist.");
1662                         rte_free(profile_info_sec);
1663                         return -EACCES;
1664                 }
1665         }
1666
1667         if (op == RTE_PMD_I40E_PKG_OP_WR_DEL) {
1668                 status = i40e_rollback_profile(
1669                         hw,
1670                         (struct i40e_profile_segment *)profile_seg_hdr,
1671                         track_id);
1672                 if (status) {
1673                         PMD_DRV_LOG(ERR, "Failed to write profile for delete.");
1674                         rte_free(profile_info_sec);
1675                         return status;
1676                 }
1677         } else {
1678                 status = i40e_write_profile(
1679                         hw,
1680                         (struct i40e_profile_segment *)profile_seg_hdr,
1681                         track_id);
1682                 if (status) {
1683                         if (op == RTE_PMD_I40E_PKG_OP_WR_ADD)
1684                                 PMD_DRV_LOG(ERR, "Failed to write profile for add.");
1685                         else
1686                                 PMD_DRV_LOG(ERR, "Failed to write profile.");
1687                         rte_free(profile_info_sec);
1688                         return status;
1689                 }
1690         }
1691
1692         if (track_id && (op != RTE_PMD_I40E_PKG_OP_WR_ONLY)) {
1693                 /* Modify loaded profiles info list */
1694                 status = i40e_add_rm_profile_info(hw, profile_info_sec);
1695                 if (status) {
1696                         if (op == RTE_PMD_I40E_PKG_OP_WR_ADD)
1697                                 PMD_DRV_LOG(ERR, "Failed to add profile to info list.");
1698                         else
1699                                 PMD_DRV_LOG(ERR, "Failed to delete profile from info list.");
1700                 }
1701         }
1702
1703         rte_free(profile_info_sec);
1704         return status;
1705 }
1706
1707 int rte_pmd_i40e_get_ddp_info(uint8_t *pkg_buff, uint32_t pkg_size,
1708         uint8_t *info_buff, uint32_t info_size,
1709         enum rte_pmd_i40e_package_info type)
1710 {
1711         uint32_t ret_size;
1712         struct i40e_package_header *pkg_hdr;
1713         struct i40e_generic_seg_header *i40e_seg_hdr;
1714         struct i40e_generic_seg_header *note_seg_hdr;
1715         struct i40e_generic_seg_header *metadata_seg_hdr;
1716
1717         if (!info_buff) {
1718                 PMD_DRV_LOG(ERR, "Output info buff is invalid.");
1719                 return -EINVAL;
1720         }
1721
1722         if (!pkg_buff || pkg_size < (sizeof(struct i40e_package_header) +
1723                 sizeof(struct i40e_metadata_segment) +
1724                 sizeof(uint32_t) * 2)) {
1725                 PMD_DRV_LOG(ERR, "Package buff is invalid.");
1726                 return -EINVAL;
1727         }
1728
1729         pkg_hdr = (struct i40e_package_header *)pkg_buff;
1730         if (pkg_hdr->segment_count < 2) {
1731                 PMD_DRV_LOG(ERR, "Segment_count should be 2 at least.");
1732                 return -EINVAL;
1733         }
1734
1735         /* Find metadata segment */
1736         metadata_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_METADATA,
1737                 pkg_hdr);
1738
1739         /* Find global notes segment */
1740         note_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_NOTES,
1741                 pkg_hdr);
1742
1743         /* Find i40e profile segment */
1744         i40e_seg_hdr = i40e_find_segment_in_package(SEGMENT_TYPE_I40E, pkg_hdr);
1745
1746         /* get global header info */
1747         if (type == RTE_PMD_I40E_PKG_INFO_GLOBAL_HEADER) {
1748                 struct rte_pmd_i40e_profile_info *info =
1749                         (struct rte_pmd_i40e_profile_info *)info_buff;
1750
1751                 if (info_size < sizeof(struct rte_pmd_i40e_profile_info)) {
1752                         PMD_DRV_LOG(ERR, "Output info buff size is invalid.");
1753                         return -EINVAL;
1754                 }
1755
1756                 if (!metadata_seg_hdr) {
1757                         PMD_DRV_LOG(ERR, "Failed to find metadata segment header");
1758                         return -EINVAL;
1759                 }
1760
1761                 memset(info, 0, sizeof(struct rte_pmd_i40e_profile_info));
1762                 info->owner = RTE_PMD_I40E_DDP_OWNER_UNKNOWN;
1763                 info->track_id =
1764                         ((struct i40e_metadata_segment *)metadata_seg_hdr)->track_id;
1765
1766                 memcpy(info->name,
1767                         ((struct i40e_metadata_segment *)metadata_seg_hdr)->name,
1768                         I40E_DDP_NAME_SIZE);
1769                 memcpy(&info->version,
1770                         &((struct i40e_metadata_segment *)metadata_seg_hdr)->version,
1771                         sizeof(struct i40e_ddp_version));
1772                 return I40E_SUCCESS;
1773         }
1774
1775         /* get global note size */
1776         if (type == RTE_PMD_I40E_PKG_INFO_GLOBAL_NOTES_SIZE) {
1777                 if (info_size < sizeof(uint32_t)) {
1778                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
1779                         return -EINVAL;
1780                 }
1781                 if (note_seg_hdr == NULL)
1782                         ret_size = 0;
1783                 else
1784                         ret_size = note_seg_hdr->size;
1785                 *(uint32_t *)info_buff = ret_size;
1786                 return I40E_SUCCESS;
1787         }
1788
1789         /* get global note */
1790         if (type == RTE_PMD_I40E_PKG_INFO_GLOBAL_NOTES) {
1791                 if (note_seg_hdr == NULL)
1792                         return -ENOTSUP;
1793                 if (info_size < note_seg_hdr->size) {
1794                         PMD_DRV_LOG(ERR, "Information buffer size is too small");
1795                         return -EINVAL;
1796                 }
1797                 memcpy(info_buff, &note_seg_hdr[1], note_seg_hdr->size);
1798                 return I40E_SUCCESS;
1799         }
1800
1801         /* get i40e segment header info */
1802         if (type == RTE_PMD_I40E_PKG_INFO_HEADER) {
1803                 struct rte_pmd_i40e_profile_info *info =
1804                         (struct rte_pmd_i40e_profile_info *)info_buff;
1805
1806                 if (info_size < sizeof(struct rte_pmd_i40e_profile_info)) {
1807                         PMD_DRV_LOG(ERR, "Output info buff size is invalid.");
1808                         return -EINVAL;
1809                 }
1810
1811                 if (!metadata_seg_hdr) {
1812                         PMD_DRV_LOG(ERR, "Failed to find metadata segment header");
1813                         return -EINVAL;
1814                 }
1815
1816                 if (!i40e_seg_hdr) {
1817                         PMD_DRV_LOG(ERR, "Failed to find i40e segment header");
1818                         return -EINVAL;
1819                 }
1820
1821                 memset(info, 0, sizeof(struct rte_pmd_i40e_profile_info));
1822                 info->owner = RTE_PMD_I40E_DDP_OWNER_UNKNOWN;
1823                 info->track_id =
1824                         ((struct i40e_metadata_segment *)metadata_seg_hdr)->track_id;
1825
1826                 memcpy(info->name,
1827                         ((struct i40e_profile_segment *)i40e_seg_hdr)->name,
1828                         I40E_DDP_NAME_SIZE);
1829                 memcpy(&info->version,
1830                         &((struct i40e_profile_segment *)i40e_seg_hdr)->version,
1831                         sizeof(struct i40e_ddp_version));
1832                 return I40E_SUCCESS;
1833         }
1834
1835         /* get number of devices */
1836         if (type == RTE_PMD_I40E_PKG_INFO_DEVID_NUM) {
1837                 if (info_size < sizeof(uint32_t)) {
1838                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
1839                         return -EINVAL;
1840                 }
1841                 *(uint32_t *)info_buff =
1842                         ((struct i40e_profile_segment *)i40e_seg_hdr)->device_table_count;
1843                 return I40E_SUCCESS;
1844         }
1845
1846         /* get list of devices */
1847         if (type == RTE_PMD_I40E_PKG_INFO_DEVID_LIST) {
1848                 uint32_t dev_num;
1849                 dev_num =
1850                         ((struct i40e_profile_segment *)i40e_seg_hdr)->device_table_count;
1851                 if (info_size < sizeof(struct rte_pmd_i40e_ddp_device_id) * dev_num) {
1852                         PMD_DRV_LOG(ERR, "Invalid information buffer size");
1853                         return -EINVAL;
1854                 }
1855                 memcpy(info_buff,
1856                         ((struct i40e_profile_segment *)i40e_seg_hdr)->device_table,
1857                         sizeof(struct rte_pmd_i40e_ddp_device_id) * dev_num);
1858                 return I40E_SUCCESS;
1859         }
1860
1861         PMD_DRV_LOG(ERR, "Info type %u is invalid.", type);
1862         return -EINVAL;
1863 }
1864
1865 int
1866 rte_pmd_i40e_get_ddp_list(uint8_t port, uint8_t *buff, uint32_t size)
1867 {
1868         struct rte_eth_dev *dev;
1869         struct i40e_hw *hw;
1870         enum i40e_status_code status = I40E_SUCCESS;
1871
1872         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
1873
1874         dev = &rte_eth_devices[port];
1875
1876         if (!is_i40e_supported(dev))
1877                 return -ENOTSUP;
1878
1879         if (size < (I40E_PROFILE_INFO_SIZE * I40E_MAX_PROFILE_NUM + 4))
1880                 return -EINVAL;
1881
1882         hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1883
1884         status = i40e_aq_get_ddp_list(hw, (void *)buff,
1885                                       size, 0, NULL);
1886
1887         return status;
1888 }
1889
1890 static int check_invalid_pkt_type(uint32_t pkt_type)
1891 {
1892         uint32_t l2, l3, l4, tnl, il2, il3, il4;
1893
1894         l2 = pkt_type & RTE_PTYPE_L2_MASK;
1895         l3 = pkt_type & RTE_PTYPE_L3_MASK;
1896         l4 = pkt_type & RTE_PTYPE_L4_MASK;
1897         tnl = pkt_type & RTE_PTYPE_TUNNEL_MASK;
1898         il2 = pkt_type & RTE_PTYPE_INNER_L2_MASK;
1899         il3 = pkt_type & RTE_PTYPE_INNER_L3_MASK;
1900         il4 = pkt_type & RTE_PTYPE_INNER_L4_MASK;
1901
1902         if (l2 &&
1903             l2 != RTE_PTYPE_L2_ETHER &&
1904             l2 != RTE_PTYPE_L2_ETHER_TIMESYNC &&
1905             l2 != RTE_PTYPE_L2_ETHER_ARP &&
1906             l2 != RTE_PTYPE_L2_ETHER_LLDP &&
1907             l2 != RTE_PTYPE_L2_ETHER_NSH &&
1908             l2 != RTE_PTYPE_L2_ETHER_VLAN &&
1909             l2 != RTE_PTYPE_L2_ETHER_QINQ)
1910                 return -1;
1911
1912         if (l3 &&
1913             l3 != RTE_PTYPE_L3_IPV4 &&
1914             l3 != RTE_PTYPE_L3_IPV4_EXT &&
1915             l3 != RTE_PTYPE_L3_IPV6 &&
1916             l3 != RTE_PTYPE_L3_IPV4_EXT_UNKNOWN &&
1917             l3 != RTE_PTYPE_L3_IPV6_EXT &&
1918             l3 != RTE_PTYPE_L3_IPV6_EXT_UNKNOWN)
1919                 return -1;
1920
1921         if (l4 &&
1922             l4 != RTE_PTYPE_L4_TCP &&
1923             l4 != RTE_PTYPE_L4_UDP &&
1924             l4 != RTE_PTYPE_L4_FRAG &&
1925             l4 != RTE_PTYPE_L4_SCTP &&
1926             l4 != RTE_PTYPE_L4_ICMP &&
1927             l4 != RTE_PTYPE_L4_NONFRAG)
1928                 return -1;
1929
1930         if (tnl &&
1931             tnl != RTE_PTYPE_TUNNEL_IP &&
1932             tnl != RTE_PTYPE_TUNNEL_GRENAT &&
1933             tnl != RTE_PTYPE_TUNNEL_VXLAN &&
1934             tnl != RTE_PTYPE_TUNNEL_NVGRE &&
1935             tnl != RTE_PTYPE_TUNNEL_GENEVE &&
1936             tnl != RTE_PTYPE_TUNNEL_GRENAT)
1937                 return -1;
1938
1939         if (il2 &&
1940             il2 != RTE_PTYPE_INNER_L2_ETHER &&
1941             il2 != RTE_PTYPE_INNER_L2_ETHER_VLAN &&
1942             il2 != RTE_PTYPE_INNER_L2_ETHER_QINQ)
1943                 return -1;
1944
1945         if (il3 &&
1946             il3 != RTE_PTYPE_INNER_L3_IPV4 &&
1947             il3 != RTE_PTYPE_INNER_L3_IPV4_EXT &&
1948             il3 != RTE_PTYPE_INNER_L3_IPV6 &&
1949             il3 != RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN &&
1950             il3 != RTE_PTYPE_INNER_L3_IPV6_EXT &&
1951             il3 != RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN)
1952                 return -1;
1953
1954         if (il4 &&
1955             il4 != RTE_PTYPE_INNER_L4_TCP &&
1956             il4 != RTE_PTYPE_INNER_L4_UDP &&
1957             il4 != RTE_PTYPE_INNER_L4_FRAG &&
1958             il4 != RTE_PTYPE_INNER_L4_SCTP &&
1959             il4 != RTE_PTYPE_INNER_L4_ICMP &&
1960             il4 != RTE_PTYPE_INNER_L4_NONFRAG)
1961                 return -1;
1962
1963         return 0;
1964 }
1965
1966 static int check_invalid_ptype_mapping(
1967                 struct rte_pmd_i40e_ptype_mapping *mapping_table,
1968                 uint16_t count)
1969 {
1970         int i;
1971
1972         for (i = 0; i < count; i++) {
1973                 uint16_t ptype = mapping_table[i].hw_ptype;
1974                 uint32_t pkt_type = mapping_table[i].sw_ptype;
1975
1976                 if (ptype >= I40E_MAX_PKT_TYPE)
1977                         return -1;
1978
1979                 if (pkt_type == RTE_PTYPE_UNKNOWN)
1980                         continue;
1981
1982                 if (pkt_type & RTE_PMD_I40E_PTYPE_USER_DEFINE_MASK)
1983                         continue;
1984
1985                 if (check_invalid_pkt_type(pkt_type))
1986                         return -1;
1987         }
1988
1989         return 0;
1990 }
1991
1992 int
1993 rte_pmd_i40e_ptype_mapping_update(
1994                         uint8_t port,
1995                         struct rte_pmd_i40e_ptype_mapping *mapping_items,
1996                         uint16_t count,
1997                         uint8_t exclusive)
1998 {
1999         struct rte_eth_dev *dev;
2000         struct i40e_adapter *ad;
2001         int i;
2002
2003         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2004
2005         dev = &rte_eth_devices[port];
2006
2007         if (!is_i40e_supported(dev))
2008                 return -ENOTSUP;
2009
2010         if (count > I40E_MAX_PKT_TYPE)
2011                 return -EINVAL;
2012
2013         if (check_invalid_ptype_mapping(mapping_items, count))
2014                 return -EINVAL;
2015
2016         ad = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
2017
2018         if (exclusive) {
2019                 for (i = 0; i < I40E_MAX_PKT_TYPE; i++)
2020                         ad->ptype_tbl[i] = RTE_PTYPE_UNKNOWN;
2021         }
2022
2023         for (i = 0; i < count; i++)
2024                 ad->ptype_tbl[mapping_items[i].hw_ptype]
2025                         = mapping_items[i].sw_ptype;
2026
2027         return 0;
2028 }
2029
2030 int rte_pmd_i40e_ptype_mapping_reset(uint8_t port)
2031 {
2032         struct rte_eth_dev *dev;
2033
2034         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2035
2036         dev = &rte_eth_devices[port];
2037
2038         if (!is_i40e_supported(dev))
2039                 return -ENOTSUP;
2040
2041         i40e_set_default_ptype_table(dev);
2042
2043         return 0;
2044 }
2045
2046 int rte_pmd_i40e_ptype_mapping_get(
2047                         uint8_t port,
2048                         struct rte_pmd_i40e_ptype_mapping *mapping_items,
2049                         uint16_t size,
2050                         uint16_t *count,
2051                         uint8_t valid_only)
2052 {
2053         struct rte_eth_dev *dev;
2054         struct i40e_adapter *ad;
2055         int n = 0;
2056         uint16_t i;
2057
2058         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2059
2060         dev = &rte_eth_devices[port];
2061
2062         if (!is_i40e_supported(dev))
2063                 return -ENOTSUP;
2064
2065         ad = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
2066
2067         for (i = 0; i < I40E_MAX_PKT_TYPE; i++) {
2068                 if (n >= size)
2069                         break;
2070                 if (valid_only && ad->ptype_tbl[i] == RTE_PTYPE_UNKNOWN)
2071                         continue;
2072                 mapping_items[n].hw_ptype = i;
2073                 mapping_items[n].sw_ptype = ad->ptype_tbl[i];
2074                 n++;
2075         }
2076
2077         *count = n;
2078         return 0;
2079 }
2080
2081 int rte_pmd_i40e_ptype_mapping_replace(uint8_t port,
2082                                        uint32_t target,
2083                                        uint8_t mask,
2084                                        uint32_t pkt_type)
2085 {
2086         struct rte_eth_dev *dev;
2087         struct i40e_adapter *ad;
2088         uint16_t i;
2089
2090         RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
2091
2092         dev = &rte_eth_devices[port];
2093
2094         if (!is_i40e_supported(dev))
2095                 return -ENOTSUP;
2096
2097         if (!mask && check_invalid_pkt_type(target))
2098                 return -EINVAL;
2099
2100         if (check_invalid_pkt_type(pkt_type))
2101                 return -EINVAL;
2102
2103         ad = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
2104
2105         for (i = 0; i < I40E_MAX_PKT_TYPE; i++) {
2106                 if (mask) {
2107                         if ((target | ad->ptype_tbl[i]) == target &&
2108                             (target & ad->ptype_tbl[i]))
2109                                 ad->ptype_tbl[i] = pkt_type;
2110                 } else {
2111                         if (ad->ptype_tbl[i] == target)
2112                                 ad->ptype_tbl[i] = pkt_type;
2113                 }
2114         }
2115
2116         return 0;
2117 }