net/octeontx2: support VLAN filters
[dpdk.git] / drivers / net / octeontx2 / otx2_vlan.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2019 Marvell International Ltd.
3  */
4
5 #include <rte_malloc.h>
6 #include <rte_tailq.h>
7
8 #include "otx2_ethdev.h"
9 #include "otx2_flow.h"
10
11
12 #define VLAN_ID_MATCH   0x1
13 #define VTAG_F_MATCH    0x2
14 #define MAC_ADDR_MATCH  0x4
15 #define QINQ_F_MATCH    0x8
16 #define VLAN_DROP       0x10
17 #define DEF_F_ENTRY     0x20
18
19 enum vtag_cfg_dir {
20         VTAG_TX,
21         VTAG_RX
22 };
23
24 static int
25 nix_vlan_mcam_enb_dis(struct otx2_eth_dev *dev,
26                       uint32_t entry, const int enable)
27 {
28         struct npc_mcam_ena_dis_entry_req *req;
29         struct otx2_mbox *mbox = dev->mbox;
30         int rc = -EINVAL;
31
32         if (enable)
33                 req = otx2_mbox_alloc_msg_npc_mcam_ena_entry(mbox);
34         else
35                 req = otx2_mbox_alloc_msg_npc_mcam_dis_entry(mbox);
36
37         req->entry = entry;
38
39         rc = otx2_mbox_process_msg(mbox, NULL);
40         return rc;
41 }
42
43 static void
44 nix_set_rx_vlan_action(struct rte_eth_dev *eth_dev,
45                     struct mcam_entry *entry, bool qinq, bool drop)
46 {
47         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
48         int pcifunc = otx2_pfvf_func(dev->pf, dev->vf);
49         uint64_t action = 0, vtag_action = 0;
50
51         action = NIX_RX_ACTIONOP_UCAST;
52
53         if (eth_dev->data->dev_conf.rxmode.mq_mode == ETH_MQ_RX_RSS) {
54                 action = NIX_RX_ACTIONOP_RSS;
55                 action |= (uint64_t)(dev->rss_info.alg_idx) << 56;
56         }
57
58         action |= (uint64_t)pcifunc << 4;
59         entry->action = action;
60
61         if (drop) {
62                 entry->action &= ~((uint64_t)0xF);
63                 entry->action |= NIX_RX_ACTIONOP_DROP;
64                 return;
65         }
66
67         if (!qinq) {
68                 /* VTAG0 fields denote CTAG in single vlan case */
69                 vtag_action |= (NIX_RX_VTAGACTION_VTAG_VALID << 15);
70                 vtag_action |= (NPC_LID_LB << 8);
71                 vtag_action |= NIX_RX_VTAGACTION_VTAG0_RELPTR;
72         } else {
73                 /* VTAG0 & VTAG1 fields denote CTAG & STAG respectively */
74                 vtag_action |= (NIX_RX_VTAGACTION_VTAG_VALID << 15);
75                 vtag_action |= (NPC_LID_LB << 8);
76                 vtag_action |= NIX_RX_VTAGACTION_VTAG1_RELPTR;
77                 vtag_action |= (NIX_RX_VTAGACTION_VTAG_VALID << 47);
78                 vtag_action |= ((uint64_t)(NPC_LID_LB) << 40);
79                 vtag_action |= (NIX_RX_VTAGACTION_VTAG0_RELPTR << 32);
80         }
81
82         entry->vtag_action = vtag_action;
83 }
84
85 static int
86 nix_vlan_mcam_free(struct otx2_eth_dev *dev, uint32_t entry)
87 {
88         struct npc_mcam_free_entry_req *req;
89         struct otx2_mbox *mbox = dev->mbox;
90         int rc = -EINVAL;
91
92         req = otx2_mbox_alloc_msg_npc_mcam_free_entry(mbox);
93         req->entry = entry;
94
95         rc = otx2_mbox_process_msg(mbox, NULL);
96         return rc;
97 }
98
99 static int
100 nix_vlan_mcam_write(struct rte_eth_dev *eth_dev, uint16_t ent_idx,
101                     struct mcam_entry *entry, uint8_t intf, uint8_t ena)
102 {
103         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
104         struct npc_mcam_write_entry_req *req;
105         struct otx2_mbox *mbox = dev->mbox;
106         struct msghdr *rsp;
107         int rc = -EINVAL;
108
109         req = otx2_mbox_alloc_msg_npc_mcam_write_entry(mbox);
110
111         req->entry = ent_idx;
112         req->intf = intf;
113         req->enable_entry = ena;
114         memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
115
116         rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
117         return rc;
118 }
119
120 static int
121 nix_vlan_mcam_alloc_and_write(struct rte_eth_dev *eth_dev,
122                               struct mcam_entry *entry,
123                               uint8_t intf, bool drop)
124 {
125         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
126         struct npc_mcam_alloc_and_write_entry_req *req;
127         struct npc_mcam_alloc_and_write_entry_rsp *rsp;
128         struct otx2_mbox *mbox = dev->mbox;
129         int rc = -EINVAL;
130
131         req = otx2_mbox_alloc_msg_npc_mcam_alloc_and_write_entry(mbox);
132
133         if (intf == NPC_MCAM_RX) {
134                 if (!drop && dev->vlan_info.def_rx_mcam_idx) {
135                         req->priority = NPC_MCAM_HIGHER_PRIO;
136                         req->ref_entry = dev->vlan_info.def_rx_mcam_idx;
137                 } else if (drop && dev->vlan_info.qinq_mcam_idx) {
138                         req->priority = NPC_MCAM_LOWER_PRIO;
139                         req->ref_entry = dev->vlan_info.qinq_mcam_idx;
140                 } else {
141                         req->priority = NPC_MCAM_ANY_PRIO;
142                         req->ref_entry = 0;
143                 }
144         } else {
145                 req->priority = NPC_MCAM_ANY_PRIO;
146                 req->ref_entry = 0;
147         }
148
149         req->intf = intf;
150         req->enable_entry = 1;
151         memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
152
153         rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
154         if (rc)
155                 return rc;
156
157         return rsp->entry;
158 }
159
160 static void
161 nix_vlan_update_mac(struct rte_eth_dev *eth_dev, int mcam_index,
162                            int enable)
163 {
164         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
165         struct vlan_mkex_info *mkex = &dev->vlan_info.mkex;
166         volatile uint8_t *key_data, *key_mask;
167         struct npc_mcam_read_entry_req *req;
168         struct npc_mcam_read_entry_rsp *rsp;
169         struct otx2_mbox *mbox = dev->mbox;
170         uint64_t mcam_data, mcam_mask;
171         struct mcam_entry entry;
172         uint8_t intf, mcam_ena;
173         int idx, rc = -EINVAL;
174         uint8_t *mac_addr;
175
176         memset(&entry, 0, sizeof(struct mcam_entry));
177
178         /* Read entry first */
179         req = otx2_mbox_alloc_msg_npc_mcam_read_entry(mbox);
180
181         req->entry = mcam_index;
182
183         rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
184         if (rc) {
185                 otx2_err("Failed to read entry %d", mcam_index);
186                 return;
187         }
188
189         entry = rsp->entry_data;
190         intf = rsp->intf;
191         mcam_ena = rsp->enable;
192
193         /* Update mcam address */
194         key_data = (volatile uint8_t *)entry.kw;
195         key_mask = (volatile uint8_t *)entry.kw_mask;
196
197         if (enable) {
198                 mcam_mask = 0;
199                 otx2_mbox_memcpy(key_mask + mkex->la_xtract.key_off,
200                                  &mcam_mask, mkex->la_xtract.len + 1);
201
202         } else {
203                 mcam_data = 0ULL;
204                 mac_addr = dev->mac_addr;
205                 for (idx = RTE_ETHER_ADDR_LEN - 1; idx >= 0; idx--)
206                         mcam_data |= ((uint64_t)*mac_addr++) << (8 * idx);
207
208                 mcam_mask = BIT_ULL(48) - 1;
209
210                 otx2_mbox_memcpy(key_data + mkex->la_xtract.key_off,
211                                  &mcam_data, mkex->la_xtract.len + 1);
212                 otx2_mbox_memcpy(key_mask + mkex->la_xtract.key_off,
213                                  &mcam_mask, mkex->la_xtract.len + 1);
214         }
215
216         /* Write back the mcam entry */
217         rc = nix_vlan_mcam_write(eth_dev, mcam_index,
218                                  &entry, intf, mcam_ena);
219         if (rc) {
220                 otx2_err("Failed to write entry %d", mcam_index);
221                 return;
222         }
223 }
224
225 void
226 otx2_nix_vlan_update_promisc(struct rte_eth_dev *eth_dev, int enable)
227 {
228         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
229         struct otx2_vlan_info *vlan = &dev->vlan_info;
230         struct vlan_entry *entry;
231
232         /* Already in required mode */
233         if (enable == vlan->promisc_on)
234                 return;
235
236         /* Update default rx entry */
237         if (vlan->def_rx_mcam_idx)
238                 nix_vlan_update_mac(eth_dev, vlan->def_rx_mcam_idx, enable);
239
240         /* Update all other rx filter entries */
241         TAILQ_FOREACH(entry, &vlan->fltr_tbl, next)
242                 nix_vlan_update_mac(eth_dev, entry->mcam_idx, enable);
243
244         vlan->promisc_on = enable;
245 }
246
247 /* Configure mcam entry with required MCAM search rules */
248 static int
249 nix_vlan_mcam_config(struct rte_eth_dev *eth_dev,
250                      uint16_t vlan_id, uint16_t flags)
251 {
252         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
253         struct vlan_mkex_info *mkex = &dev->vlan_info.mkex;
254         volatile uint8_t *key_data, *key_mask;
255         uint64_t mcam_data, mcam_mask;
256         struct mcam_entry entry;
257         uint8_t *mac_addr;
258         int idx, kwi = 0;
259
260         memset(&entry, 0, sizeof(struct mcam_entry));
261         key_data = (volatile uint8_t *)entry.kw;
262         key_mask = (volatile uint8_t *)entry.kw_mask;
263
264         /* Channel base extracted to KW0[11:0] */
265         entry.kw[kwi] = dev->rx_chan_base;
266         entry.kw_mask[kwi] = BIT_ULL(12) - 1;
267
268         /* Adds vlan_id & LB CTAG flag to MCAM KW */
269         if (flags & VLAN_ID_MATCH) {
270                 entry.kw[kwi] |= NPC_LT_LB_CTAG << mkex->lb_lt_offset;
271                 entry.kw_mask[kwi] |= 0xFULL << mkex->lb_lt_offset;
272
273                 mcam_data = (vlan_id << 16);
274                 mcam_mask = (BIT_ULL(16) - 1) << 16;
275                 otx2_mbox_memcpy(key_data + mkex->lb_xtract.key_off,
276                                      &mcam_data, mkex->lb_xtract.len + 1);
277                 otx2_mbox_memcpy(key_mask + mkex->lb_xtract.key_off,
278                                      &mcam_mask, mkex->lb_xtract.len + 1);
279         }
280
281         /* Adds LB STAG flag to MCAM KW */
282         if (flags & QINQ_F_MATCH) {
283                 entry.kw[kwi] |= NPC_LT_LB_STAG << mkex->lb_lt_offset;
284                 entry.kw_mask[kwi] |= 0xFULL << mkex->lb_lt_offset;
285         }
286
287         /* Adds LB CTAG & LB STAG flags to MCAM KW */
288         if (flags & VTAG_F_MATCH) {
289                 entry.kw[kwi] |= (NPC_LT_LB_CTAG | NPC_LT_LB_STAG)
290                                                         << mkex->lb_lt_offset;
291                 entry.kw_mask[kwi] |= (NPC_LT_LB_CTAG & NPC_LT_LB_STAG)
292                                                         << mkex->lb_lt_offset;
293         }
294
295         /* Adds port MAC address to MCAM KW */
296         if (flags & MAC_ADDR_MATCH) {
297                 mcam_data = 0ULL;
298                 mac_addr = dev->mac_addr;
299                 for (idx = RTE_ETHER_ADDR_LEN - 1; idx >= 0; idx--)
300                         mcam_data |= ((uint64_t)*mac_addr++) << (8 * idx);
301
302                 mcam_mask = BIT_ULL(48) - 1;
303                 otx2_mbox_memcpy(key_data + mkex->la_xtract.key_off,
304                                      &mcam_data, mkex->la_xtract.len + 1);
305                 otx2_mbox_memcpy(key_mask + mkex->la_xtract.key_off,
306                                      &mcam_mask, mkex->la_xtract.len + 1);
307         }
308
309         /* VLAN_DROP: for drop action for all vlan packets when filter is on.
310          * For QinQ, enable vtag action for both outer & inner tags
311          */
312         if (flags & VLAN_DROP)
313                 nix_set_rx_vlan_action(eth_dev, &entry, false, true);
314         else if (flags & QINQ_F_MATCH)
315                 nix_set_rx_vlan_action(eth_dev, &entry, true, false);
316         else
317                 nix_set_rx_vlan_action(eth_dev, &entry, false, false);
318
319         if (flags & DEF_F_ENTRY)
320                 dev->vlan_info.def_rx_mcam_ent = entry;
321
322         return nix_vlan_mcam_alloc_and_write(eth_dev, &entry, NIX_INTF_RX,
323                                              flags & VLAN_DROP);
324 }
325
326 /* Installs/Removes/Modifies default rx entry */
327 static int
328 nix_vlan_handle_default_rx_entry(struct rte_eth_dev *eth_dev, bool strip,
329                                  bool filter, bool enable)
330 {
331         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
332         struct otx2_vlan_info *vlan = &dev->vlan_info;
333         uint16_t flags = 0;
334         int mcam_idx, rc;
335
336         /* Use default mcam entry to either drop vlan traffic when
337          * vlan filter is on or strip vtag when strip is enabled.
338          * Allocate default entry which matches port mac address
339          * and vtag(ctag/stag) flags with drop action.
340          */
341         if (!vlan->def_rx_mcam_idx) {
342                 if (!eth_dev->data->promiscuous)
343                         flags = MAC_ADDR_MATCH;
344
345                 if (filter && enable)
346                         flags |= VTAG_F_MATCH | VLAN_DROP;
347                 else if (strip && enable)
348                         flags |= VTAG_F_MATCH;
349                 else
350                         return 0;
351
352                 flags |= DEF_F_ENTRY;
353
354                 mcam_idx = nix_vlan_mcam_config(eth_dev, 0, flags);
355                 if (mcam_idx < 0) {
356                         otx2_err("Failed to config vlan mcam");
357                         return -mcam_idx;
358                 }
359
360                 vlan->def_rx_mcam_idx = mcam_idx;
361                 return 0;
362         }
363
364         /* Filter is already enabled, so packets would be dropped anyways. No
365          * processing needed for enabling strip wrt mcam entry.
366          */
367
368         /* Filter disable request */
369         if (vlan->filter_on && filter && !enable) {
370                 vlan->def_rx_mcam_ent.action &= ~((uint64_t)0xF);
371
372                 /* Free default rx entry only when
373                  * 1. strip is not on and
374                  * 2. qinq entry is allocated before default entry.
375                  */
376                 if (vlan->strip_on ||
377                     (vlan->qinq_on && !vlan->qinq_before_def)) {
378                         if (eth_dev->data->dev_conf.rxmode.mq_mode ==
379                                                                 ETH_MQ_RX_RSS)
380                                 vlan->def_rx_mcam_ent.action |=
381                                                         NIX_RX_ACTIONOP_RSS;
382                         else
383                                 vlan->def_rx_mcam_ent.action |=
384                                                         NIX_RX_ACTIONOP_UCAST;
385                         return nix_vlan_mcam_write(eth_dev,
386                                                    vlan->def_rx_mcam_idx,
387                                                    &vlan->def_rx_mcam_ent,
388                                                    NIX_INTF_RX, 1);
389                 } else {
390                         rc = nix_vlan_mcam_free(dev, vlan->def_rx_mcam_idx);
391                         if (rc)
392                                 return rc;
393                         vlan->def_rx_mcam_idx = 0;
394                 }
395         }
396
397         /* Filter enable request */
398         if (!vlan->filter_on && filter && enable) {
399                 vlan->def_rx_mcam_ent.action &= ~((uint64_t)0xF);
400                 vlan->def_rx_mcam_ent.action |= NIX_RX_ACTIONOP_DROP;
401                 return nix_vlan_mcam_write(eth_dev, vlan->def_rx_mcam_idx,
402                                    &vlan->def_rx_mcam_ent, NIX_INTF_RX, 1);
403         }
404
405         /* Strip disable request */
406         if (vlan->strip_on && strip && !enable) {
407                 if (!vlan->filter_on &&
408                     !(vlan->qinq_on && !vlan->qinq_before_def)) {
409                         rc = nix_vlan_mcam_free(dev, vlan->def_rx_mcam_idx);
410                         if (rc)
411                                 return rc;
412                         vlan->def_rx_mcam_idx = 0;
413                 }
414         }
415
416         return 0;
417 }
418
419 /* Configure vlan stripping on or off */
420 static int
421 nix_vlan_hw_strip(struct rte_eth_dev *eth_dev, const uint8_t enable)
422 {
423         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
424         struct otx2_mbox *mbox = dev->mbox;
425         struct nix_vtag_config *vtag_cfg;
426         int rc = -EINVAL;
427
428         rc = nix_vlan_handle_default_rx_entry(eth_dev, true, false, enable);
429         if (rc) {
430                 otx2_err("Failed to config default rx entry");
431                 return rc;
432         }
433
434         vtag_cfg = otx2_mbox_alloc_msg_nix_vtag_cfg(mbox);
435         /* cfg_type = 1 for rx vlan cfg */
436         vtag_cfg->cfg_type = VTAG_RX;
437
438         if (enable)
439                 vtag_cfg->rx.strip_vtag = 1;
440         else
441                 vtag_cfg->rx.strip_vtag = 0;
442
443         /* Always capture */
444         vtag_cfg->rx.capture_vtag = 1;
445         vtag_cfg->vtag_size = NIX_VTAGSIZE_T4;
446         /* Use rx vtag type index[0] for now */
447         vtag_cfg->rx.vtag_type = 0;
448
449         rc = otx2_mbox_process(mbox);
450         if (rc)
451                 return rc;
452
453         dev->vlan_info.strip_on = enable;
454         return rc;
455 }
456
457 /* Configure vlan filtering on or off for all vlans if vlan_id == 0 */
458 static int
459 nix_vlan_hw_filter(struct rte_eth_dev *eth_dev, const uint8_t enable,
460                    uint16_t vlan_id)
461 {
462         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
463         struct otx2_vlan_info *vlan = &dev->vlan_info;
464         struct vlan_entry *entry;
465         int rc = -EINVAL;
466
467         if (!vlan_id && enable) {
468                 rc = nix_vlan_handle_default_rx_entry(eth_dev, false, true,
469                                                       enable);
470                 if (rc) {
471                         otx2_err("Failed to config vlan mcam");
472                         return rc;
473                 }
474                 dev->vlan_info.filter_on = enable;
475                 return 0;
476         }
477
478         /* Enable/disable existing vlan filter entries */
479         TAILQ_FOREACH(entry, &vlan->fltr_tbl, next) {
480                 if (vlan_id) {
481                         if (entry->vlan_id == vlan_id) {
482                                 rc = nix_vlan_mcam_enb_dis(dev,
483                                                            entry->mcam_idx,
484                                                            enable);
485                                 if (rc)
486                                         return rc;
487                         }
488                 } else {
489                         rc = nix_vlan_mcam_enb_dis(dev, entry->mcam_idx,
490                                                    enable);
491                         if (rc)
492                                 return rc;
493                 }
494         }
495
496         if (!vlan_id && !enable) {
497                 rc = nix_vlan_handle_default_rx_entry(eth_dev, false, true,
498                                                       enable);
499                 if (rc) {
500                         otx2_err("Failed to config vlan mcam");
501                         return rc;
502                 }
503                 dev->vlan_info.filter_on = enable;
504                 return 0;
505         }
506
507         return 0;
508 }
509
510 /* Enable/disable vlan filtering for the given vlan_id */
511 int
512 otx2_nix_vlan_filter_set(struct rte_eth_dev *eth_dev, uint16_t vlan_id,
513                          int on)
514 {
515         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
516         struct otx2_vlan_info *vlan = &dev->vlan_info;
517         struct vlan_entry *entry;
518         int entry_exists = 0;
519         int rc = -EINVAL;
520         int mcam_idx;
521
522         if (!vlan_id) {
523                 otx2_err("Vlan Id can't be zero");
524                 return rc;
525         }
526
527         if (!vlan->def_rx_mcam_idx) {
528                 otx2_err("Vlan Filtering is disabled, enable it first");
529                 return rc;
530         }
531
532         if (on) {
533                 TAILQ_FOREACH(entry, &vlan->fltr_tbl, next) {
534                         if (entry->vlan_id == vlan_id) {
535                                 /* Vlan entry already exists */
536                                 entry_exists = 1;
537                                 /* Mcam entry already allocated */
538                                 if (entry->mcam_idx) {
539                                         rc = nix_vlan_hw_filter(eth_dev, on,
540                                                                 vlan_id);
541                                         return rc;
542                                 }
543                                 break;
544                         }
545                 }
546
547                 if (!entry_exists) {
548                         entry = rte_zmalloc("otx2_nix_vlan_entry",
549                                             sizeof(struct vlan_entry), 0);
550                         if (!entry) {
551                                 otx2_err("Failed to allocate memory");
552                                 return -ENOMEM;
553                         }
554                 }
555
556                 /* Enables vlan_id & mac address based filtering */
557                 if (eth_dev->data->promiscuous)
558                         mcam_idx = nix_vlan_mcam_config(eth_dev, vlan_id,
559                                                         VLAN_ID_MATCH);
560                 else
561                         mcam_idx = nix_vlan_mcam_config(eth_dev, vlan_id,
562                                                         VLAN_ID_MATCH |
563                                                         MAC_ADDR_MATCH);
564                 if (mcam_idx < 0) {
565                         otx2_err("Failed to config vlan mcam");
566                         TAILQ_REMOVE(&vlan->fltr_tbl, entry, next);
567                         rte_free(entry);
568                         return mcam_idx;
569                 }
570
571                 entry->mcam_idx = mcam_idx;
572                 if (!entry_exists) {
573                         entry->vlan_id  = vlan_id;
574                         TAILQ_INSERT_HEAD(&vlan->fltr_tbl, entry, next);
575                 }
576         } else {
577                 TAILQ_FOREACH(entry, &vlan->fltr_tbl, next) {
578                         if (entry->vlan_id == vlan_id) {
579                                 nix_vlan_mcam_free(dev, entry->mcam_idx);
580                                 TAILQ_REMOVE(&vlan->fltr_tbl, entry, next);
581                                 rte_free(entry);
582                                 break;
583                         }
584                 }
585         }
586         return 0;
587 }
588
589 /* Configure double vlan(qinq) on or off */
590 static int
591 otx2_nix_config_double_vlan(struct rte_eth_dev *eth_dev,
592                             const uint8_t enable)
593 {
594         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
595         struct otx2_vlan_info *vlan_info;
596         int mcam_idx;
597         int rc;
598
599         vlan_info = &dev->vlan_info;
600
601         if (!enable) {
602                 if (!vlan_info->qinq_mcam_idx)
603                         return 0;
604
605                 rc = nix_vlan_mcam_free(dev, vlan_info->qinq_mcam_idx);
606                 if (rc)
607                         return rc;
608
609                 vlan_info->qinq_mcam_idx = 0;
610                 dev->vlan_info.qinq_on = 0;
611                 vlan_info->qinq_before_def = 0;
612                 return 0;
613         }
614
615         if (eth_dev->data->promiscuous)
616                 mcam_idx = nix_vlan_mcam_config(eth_dev, 0, QINQ_F_MATCH);
617         else
618                 mcam_idx = nix_vlan_mcam_config(eth_dev, 0,
619                                                 QINQ_F_MATCH | MAC_ADDR_MATCH);
620         if (mcam_idx < 0)
621                 return mcam_idx;
622
623         if (!vlan_info->def_rx_mcam_idx)
624                 vlan_info->qinq_before_def = 1;
625
626         vlan_info->qinq_mcam_idx = mcam_idx;
627         dev->vlan_info.qinq_on = 1;
628         return 0;
629 }
630
631 int
632 otx2_nix_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
633 {
634         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
635         uint64_t offloads = dev->rx_offloads;
636         struct rte_eth_rxmode *rxmode;
637         int rc;
638
639         rxmode = &eth_dev->data->dev_conf.rxmode;
640
641         if (mask & ETH_VLAN_EXTEND_MASK) {
642                 otx2_err("Extend offload not supported");
643                 return -ENOTSUP;
644         }
645
646         if (mask & ETH_VLAN_STRIP_MASK) {
647                 if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_STRIP) {
648                         offloads |= DEV_RX_OFFLOAD_VLAN_STRIP;
649                         rc = nix_vlan_hw_strip(eth_dev, true);
650                 } else {
651                         offloads &= ~DEV_RX_OFFLOAD_VLAN_STRIP;
652                         rc = nix_vlan_hw_strip(eth_dev, false);
653                 }
654                 if (rc)
655                         goto done;
656         }
657
658         if (mask & ETH_VLAN_FILTER_MASK) {
659                 if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_FILTER) {
660                         offloads |= DEV_RX_OFFLOAD_VLAN_FILTER;
661                         rc = nix_vlan_hw_filter(eth_dev, true, 0);
662                 } else {
663                         offloads &= ~DEV_RX_OFFLOAD_VLAN_FILTER;
664                         rc = nix_vlan_hw_filter(eth_dev, false, 0);
665                 }
666                 if (rc)
667                         goto done;
668         }
669
670         if (rxmode->offloads & DEV_RX_OFFLOAD_QINQ_STRIP) {
671                 if (!dev->vlan_info.qinq_on) {
672                         offloads |= DEV_RX_OFFLOAD_QINQ_STRIP;
673                         rc = otx2_nix_config_double_vlan(eth_dev, true);
674                         if (rc)
675                                 goto done;
676                 }
677         } else {
678                 if (dev->vlan_info.qinq_on) {
679                         offloads &= ~DEV_RX_OFFLOAD_QINQ_STRIP;
680                         rc = otx2_nix_config_double_vlan(eth_dev, false);
681                         if (rc)
682                                 goto done;
683                 }
684         }
685
686         if (offloads & (DEV_RX_OFFLOAD_VLAN_STRIP |
687                         DEV_RX_OFFLOAD_QINQ_STRIP)) {
688                 dev->rx_offloads |= offloads;
689                 dev->rx_offload_flags |= NIX_RX_OFFLOAD_VLAN_STRIP_F;
690         }
691
692 done:
693         return rc;
694 }
695
696 void otx2_nix_vlan_strip_queue_set(__rte_unused struct rte_eth_dev *dev,
697                                    __rte_unused uint16_t queue,
698                                    __rte_unused int on)
699 {
700         otx2_err("Not Supported");
701 }
702
703 static int
704 nix_vlan_rx_mkex_offset(uint64_t mask)
705 {
706         int nib_count = 0;
707
708         while (mask) {
709                 nib_count += mask & 1;
710                 mask >>= 1;
711         }
712
713         return nib_count * 4;
714 }
715
716 static int
717 nix_vlan_get_mkex_info(struct otx2_eth_dev *dev)
718 {
719         struct vlan_mkex_info *mkex = &dev->vlan_info.mkex;
720         struct otx2_npc_flow_info *npc = &dev->npc_flow;
721         struct npc_xtract_info *x_info = NULL;
722         uint64_t rx_keyx;
723         otx2_dxcfg_t *p;
724         int rc = -EINVAL;
725
726         if (npc == NULL) {
727                 otx2_err("Missing npc mkex configuration");
728                 return rc;
729         }
730
731 #define NPC_KEX_CHAN_NIBBLE_ENA                 0x7ULL
732 #define NPC_KEX_LB_LTYPE_NIBBLE_ENA             0x1000ULL
733 #define NPC_KEX_LB_LTYPE_NIBBLE_MASK            0xFFFULL
734
735         rx_keyx = npc->keyx_supp_nmask[NPC_MCAM_RX];
736         if ((rx_keyx & NPC_KEX_CHAN_NIBBLE_ENA) != NPC_KEX_CHAN_NIBBLE_ENA)
737                 return rc;
738
739         if ((rx_keyx & NPC_KEX_LB_LTYPE_NIBBLE_ENA) !=
740             NPC_KEX_LB_LTYPE_NIBBLE_ENA)
741                 return rc;
742
743         mkex->lb_lt_offset =
744             nix_vlan_rx_mkex_offset(rx_keyx & NPC_KEX_LB_LTYPE_NIBBLE_MASK);
745
746         p = &npc->prx_dxcfg;
747         x_info = &(*p)[NPC_MCAM_RX][NPC_LID_LA][NPC_LT_LA_ETHER].xtract[0];
748         memcpy(&mkex->la_xtract, x_info, sizeof(struct npc_xtract_info));
749         x_info = &(*p)[NPC_MCAM_RX][NPC_LID_LB][NPC_LT_LB_CTAG].xtract[0];
750         memcpy(&mkex->lb_xtract, x_info, sizeof(struct npc_xtract_info));
751
752         return 0;
753 }
754
755 static void nix_vlan_reinstall_vlan_filters(struct rte_eth_dev *eth_dev)
756 {
757         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
758         struct vlan_entry *entry;
759         int rc;
760
761         /* VLAN filters can't be set without setting filtern on */
762         rc = nix_vlan_handle_default_rx_entry(eth_dev, false, true, true);
763         if (rc) {
764                 otx2_err("Failed to reinstall vlan filters");
765                 return;
766         }
767
768         TAILQ_FOREACH(entry, &dev->vlan_info.fltr_tbl, next) {
769                 rc = otx2_nix_vlan_filter_set(eth_dev, entry->vlan_id, true);
770                 if (rc)
771                         otx2_err("Failed to reinstall filter for vlan:%d",
772                                  entry->vlan_id);
773         }
774 }
775
776 int
777 otx2_nix_vlan_offload_init(struct rte_eth_dev *eth_dev)
778 {
779         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
780         int rc, mask;
781
782         /* Port initialized for first time or restarted */
783         if (!dev->configured) {
784                 rc = nix_vlan_get_mkex_info(dev);
785                 if (rc) {
786                         otx2_err("Failed to get vlan mkex info rc=%d", rc);
787                         return rc;
788                 }
789
790                 TAILQ_INIT(&dev->vlan_info.fltr_tbl);
791         } else {
792                 /* Reinstall all mcam entries now if filter offload is set */
793                 if (eth_dev->data->dev_conf.rxmode.offloads &
794                     DEV_RX_OFFLOAD_VLAN_FILTER)
795                         nix_vlan_reinstall_vlan_filters(eth_dev);
796         }
797
798         mask =
799             ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK;
800         rc = otx2_nix_vlan_offload_set(eth_dev, mask);
801         if (rc) {
802                 otx2_err("Failed to set vlan offload rc=%d", rc);
803                 return rc;
804         }
805
806         return 0;
807 }
808
809 int
810 otx2_nix_vlan_fini(struct rte_eth_dev *eth_dev)
811 {
812         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
813         struct otx2_vlan_info *vlan = &dev->vlan_info;
814         struct vlan_entry *entry;
815         int rc;
816
817         TAILQ_FOREACH(entry, &vlan->fltr_tbl, next) {
818                 if (!dev->configured) {
819                         TAILQ_REMOVE(&vlan->fltr_tbl, entry, next);
820                         rte_free(entry);
821                 } else {
822                         /* MCAM entries freed by flow_fini & lf_free on
823                          * port stop.
824                          */
825                         entry->mcam_idx = 0;
826                 }
827         }
828
829         if (!dev->configured) {
830                 if (vlan->def_rx_mcam_idx) {
831                         rc = nix_vlan_mcam_free(dev, vlan->def_rx_mcam_idx);
832                         if (rc)
833                                 return rc;
834                 }
835         }
836
837         otx2_nix_config_double_vlan(eth_dev, false);
838         vlan->def_rx_mcam_idx = 0;
839         return 0;
840 }