net/octeontx2: support VLAN offloads
[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 __rte_unused 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         int rc = -EINVAL;
464
465         if (!vlan_id && enable) {
466                 rc = nix_vlan_handle_default_rx_entry(eth_dev, false, true,
467                                                       enable);
468                 if (rc) {
469                         otx2_err("Failed to config vlan mcam");
470                         return rc;
471                 }
472                 dev->vlan_info.filter_on = enable;
473                 return 0;
474         }
475
476         if (!vlan_id && !enable) {
477                 rc = nix_vlan_handle_default_rx_entry(eth_dev, false, true,
478                                                       enable);
479                 if (rc) {
480                         otx2_err("Failed to config vlan mcam");
481                         return rc;
482                 }
483                 dev->vlan_info.filter_on = enable;
484                 return 0;
485         }
486
487         return 0;
488 }
489
490 /* Configure double vlan(qinq) on or off */
491 static int
492 otx2_nix_config_double_vlan(struct rte_eth_dev *eth_dev,
493                             const uint8_t enable)
494 {
495         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
496         struct otx2_vlan_info *vlan_info;
497         int mcam_idx;
498         int rc;
499
500         vlan_info = &dev->vlan_info;
501
502         if (!enable) {
503                 if (!vlan_info->qinq_mcam_idx)
504                         return 0;
505
506                 rc = nix_vlan_mcam_free(dev, vlan_info->qinq_mcam_idx);
507                 if (rc)
508                         return rc;
509
510                 vlan_info->qinq_mcam_idx = 0;
511                 dev->vlan_info.qinq_on = 0;
512                 vlan_info->qinq_before_def = 0;
513                 return 0;
514         }
515
516         if (eth_dev->data->promiscuous)
517                 mcam_idx = nix_vlan_mcam_config(eth_dev, 0, QINQ_F_MATCH);
518         else
519                 mcam_idx = nix_vlan_mcam_config(eth_dev, 0,
520                                                 QINQ_F_MATCH | MAC_ADDR_MATCH);
521         if (mcam_idx < 0)
522                 return mcam_idx;
523
524         if (!vlan_info->def_rx_mcam_idx)
525                 vlan_info->qinq_before_def = 1;
526
527         vlan_info->qinq_mcam_idx = mcam_idx;
528         dev->vlan_info.qinq_on = 1;
529         return 0;
530 }
531
532 int
533 otx2_nix_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
534 {
535         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
536         uint64_t offloads = dev->rx_offloads;
537         struct rte_eth_rxmode *rxmode;
538         int rc;
539
540         rxmode = &eth_dev->data->dev_conf.rxmode;
541
542         if (mask & ETH_VLAN_EXTEND_MASK) {
543                 otx2_err("Extend offload not supported");
544                 return -ENOTSUP;
545         }
546
547         if (mask & ETH_VLAN_STRIP_MASK) {
548                 if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_STRIP) {
549                         offloads |= DEV_RX_OFFLOAD_VLAN_STRIP;
550                         rc = nix_vlan_hw_strip(eth_dev, true);
551                 } else {
552                         offloads &= ~DEV_RX_OFFLOAD_VLAN_STRIP;
553                         rc = nix_vlan_hw_strip(eth_dev, false);
554                 }
555                 if (rc)
556                         goto done;
557         }
558
559         if (mask & ETH_VLAN_FILTER_MASK) {
560                 if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_FILTER) {
561                         offloads |= DEV_RX_OFFLOAD_VLAN_FILTER;
562                         rc = nix_vlan_hw_filter(eth_dev, true, 0);
563                 } else {
564                         offloads &= ~DEV_RX_OFFLOAD_VLAN_FILTER;
565                         rc = nix_vlan_hw_filter(eth_dev, false, 0);
566                 }
567                 if (rc)
568                         goto done;
569         }
570
571         if (rxmode->offloads & DEV_RX_OFFLOAD_QINQ_STRIP) {
572                 if (!dev->vlan_info.qinq_on) {
573                         offloads |= DEV_RX_OFFLOAD_QINQ_STRIP;
574                         rc = otx2_nix_config_double_vlan(eth_dev, true);
575                         if (rc)
576                                 goto done;
577                 }
578         } else {
579                 if (dev->vlan_info.qinq_on) {
580                         offloads &= ~DEV_RX_OFFLOAD_QINQ_STRIP;
581                         rc = otx2_nix_config_double_vlan(eth_dev, false);
582                         if (rc)
583                                 goto done;
584                 }
585         }
586
587         if (offloads & (DEV_RX_OFFLOAD_VLAN_STRIP |
588                         DEV_RX_OFFLOAD_QINQ_STRIP)) {
589                 dev->rx_offloads |= offloads;
590                 dev->rx_offload_flags |= NIX_RX_OFFLOAD_VLAN_STRIP_F;
591         }
592
593 done:
594         return rc;
595 }
596
597 static int
598 nix_vlan_rx_mkex_offset(uint64_t mask)
599 {
600         int nib_count = 0;
601
602         while (mask) {
603                 nib_count += mask & 1;
604                 mask >>= 1;
605         }
606
607         return nib_count * 4;
608 }
609
610 static int
611 nix_vlan_get_mkex_info(struct otx2_eth_dev *dev)
612 {
613         struct vlan_mkex_info *mkex = &dev->vlan_info.mkex;
614         struct otx2_npc_flow_info *npc = &dev->npc_flow;
615         struct npc_xtract_info *x_info = NULL;
616         uint64_t rx_keyx;
617         otx2_dxcfg_t *p;
618         int rc = -EINVAL;
619
620         if (npc == NULL) {
621                 otx2_err("Missing npc mkex configuration");
622                 return rc;
623         }
624
625 #define NPC_KEX_CHAN_NIBBLE_ENA                 0x7ULL
626 #define NPC_KEX_LB_LTYPE_NIBBLE_ENA             0x1000ULL
627 #define NPC_KEX_LB_LTYPE_NIBBLE_MASK            0xFFFULL
628
629         rx_keyx = npc->keyx_supp_nmask[NPC_MCAM_RX];
630         if ((rx_keyx & NPC_KEX_CHAN_NIBBLE_ENA) != NPC_KEX_CHAN_NIBBLE_ENA)
631                 return rc;
632
633         if ((rx_keyx & NPC_KEX_LB_LTYPE_NIBBLE_ENA) !=
634             NPC_KEX_LB_LTYPE_NIBBLE_ENA)
635                 return rc;
636
637         mkex->lb_lt_offset =
638             nix_vlan_rx_mkex_offset(rx_keyx & NPC_KEX_LB_LTYPE_NIBBLE_MASK);
639
640         p = &npc->prx_dxcfg;
641         x_info = &(*p)[NPC_MCAM_RX][NPC_LID_LA][NPC_LT_LA_ETHER].xtract[0];
642         memcpy(&mkex->la_xtract, x_info, sizeof(struct npc_xtract_info));
643         x_info = &(*p)[NPC_MCAM_RX][NPC_LID_LB][NPC_LT_LB_CTAG].xtract[0];
644         memcpy(&mkex->lb_xtract, x_info, sizeof(struct npc_xtract_info));
645
646         return 0;
647 }
648
649 int
650 otx2_nix_vlan_offload_init(struct rte_eth_dev *eth_dev)
651 {
652         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
653         int rc, mask;
654
655         /* Port initialized for first time or restarted */
656         if (!dev->configured) {
657                 rc = nix_vlan_get_mkex_info(dev);
658                 if (rc) {
659                         otx2_err("Failed to get vlan mkex info rc=%d", rc);
660                         return rc;
661                 }
662
663                 TAILQ_INIT(&dev->vlan_info.fltr_tbl);
664         }
665
666         mask =
667             ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK;
668         rc = otx2_nix_vlan_offload_set(eth_dev, mask);
669         if (rc) {
670                 otx2_err("Failed to set vlan offload rc=%d", rc);
671                 return rc;
672         }
673
674         return 0;
675 }
676
677 int
678 otx2_nix_vlan_fini(struct rte_eth_dev *eth_dev)
679 {
680         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
681         struct otx2_vlan_info *vlan = &dev->vlan_info;
682         int rc;
683
684         if (!dev->configured) {
685                 if (vlan->def_rx_mcam_idx) {
686                         rc = nix_vlan_mcam_free(dev, vlan->def_rx_mcam_idx);
687                         if (rc)
688                                 return rc;
689                 }
690         }
691
692         otx2_nix_config_double_vlan(eth_dev, false);
693         vlan->def_rx_mcam_idx = 0;
694         return 0;
695 }