net/octeontx2: implement VLAN utility functions
[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
18 enum vtag_cfg_dir {
19         VTAG_TX,
20         VTAG_RX
21 };
22
23 static int
24 __rte_unused nix_vlan_mcam_enb_dis(struct otx2_eth_dev *dev,
25                                    uint32_t entry, const int enable)
26 {
27         struct npc_mcam_ena_dis_entry_req *req;
28         struct otx2_mbox *mbox = dev->mbox;
29         int rc = -EINVAL;
30
31         if (enable)
32                 req = otx2_mbox_alloc_msg_npc_mcam_ena_entry(mbox);
33         else
34                 req = otx2_mbox_alloc_msg_npc_mcam_dis_entry(mbox);
35
36         req->entry = entry;
37
38         rc = otx2_mbox_process_msg(mbox, NULL);
39         return rc;
40 }
41
42 static int
43 __rte_unused nix_vlan_mcam_free(struct otx2_eth_dev *dev, uint32_t entry)
44 {
45         struct npc_mcam_free_entry_req *req;
46         struct otx2_mbox *mbox = dev->mbox;
47         int rc = -EINVAL;
48
49         req = otx2_mbox_alloc_msg_npc_mcam_free_entry(mbox);
50         req->entry = entry;
51
52         rc = otx2_mbox_process_msg(mbox, NULL);
53         return rc;
54 }
55
56 static int
57 __rte_unused nix_vlan_mcam_write(struct rte_eth_dev *eth_dev, uint16_t ent_idx,
58                                  struct mcam_entry *entry, uint8_t intf)
59 {
60         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
61         struct npc_mcam_write_entry_req *req;
62         struct otx2_mbox *mbox = dev->mbox;
63         struct msghdr *rsp;
64         int rc = -EINVAL;
65
66         req = otx2_mbox_alloc_msg_npc_mcam_write_entry(mbox);
67
68         req->entry = ent_idx;
69         req->intf = intf;
70         req->enable_entry = 1;
71         memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
72
73         rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
74         return rc;
75 }
76
77 static int
78 __rte_unused nix_vlan_mcam_alloc_and_write(struct rte_eth_dev *eth_dev,
79                                            struct mcam_entry *entry,
80                                            uint8_t intf, bool drop)
81 {
82         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
83         struct npc_mcam_alloc_and_write_entry_req *req;
84         struct npc_mcam_alloc_and_write_entry_rsp *rsp;
85         struct otx2_mbox *mbox = dev->mbox;
86         int rc = -EINVAL;
87
88         req = otx2_mbox_alloc_msg_npc_mcam_alloc_and_write_entry(mbox);
89
90         if (intf == NPC_MCAM_RX) {
91                 if (!drop && dev->vlan_info.def_rx_mcam_idx) {
92                         req->priority = NPC_MCAM_HIGHER_PRIO;
93                         req->ref_entry = dev->vlan_info.def_rx_mcam_idx;
94                 } else if (drop && dev->vlan_info.qinq_mcam_idx) {
95                         req->priority = NPC_MCAM_LOWER_PRIO;
96                         req->ref_entry = dev->vlan_info.qinq_mcam_idx;
97                 } else {
98                         req->priority = NPC_MCAM_ANY_PRIO;
99                         req->ref_entry = 0;
100                 }
101         } else {
102                 req->priority = NPC_MCAM_ANY_PRIO;
103                 req->ref_entry = 0;
104         }
105
106         req->intf = intf;
107         req->enable_entry = 1;
108         memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
109
110         rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
111         if (rc)
112                 return rc;
113
114         return rsp->entry;
115 }
116
117 static int
118 nix_vlan_rx_mkex_offset(uint64_t mask)
119 {
120         int nib_count = 0;
121
122         while (mask) {
123                 nib_count += mask & 1;
124                 mask >>= 1;
125         }
126
127         return nib_count * 4;
128 }
129
130 static int
131 nix_vlan_get_mkex_info(struct otx2_eth_dev *dev)
132 {
133         struct vlan_mkex_info *mkex = &dev->vlan_info.mkex;
134         struct otx2_npc_flow_info *npc = &dev->npc_flow;
135         struct npc_xtract_info *x_info = NULL;
136         uint64_t rx_keyx;
137         otx2_dxcfg_t *p;
138         int rc = -EINVAL;
139
140         if (npc == NULL) {
141                 otx2_err("Missing npc mkex configuration");
142                 return rc;
143         }
144
145 #define NPC_KEX_CHAN_NIBBLE_ENA                 0x7ULL
146 #define NPC_KEX_LB_LTYPE_NIBBLE_ENA             0x1000ULL
147 #define NPC_KEX_LB_LTYPE_NIBBLE_MASK            0xFFFULL
148
149         rx_keyx = npc->keyx_supp_nmask[NPC_MCAM_RX];
150         if ((rx_keyx & NPC_KEX_CHAN_NIBBLE_ENA) != NPC_KEX_CHAN_NIBBLE_ENA)
151                 return rc;
152
153         if ((rx_keyx & NPC_KEX_LB_LTYPE_NIBBLE_ENA) !=
154             NPC_KEX_LB_LTYPE_NIBBLE_ENA)
155                 return rc;
156
157         mkex->lb_lt_offset =
158             nix_vlan_rx_mkex_offset(rx_keyx & NPC_KEX_LB_LTYPE_NIBBLE_MASK);
159
160         p = &npc->prx_dxcfg;
161         x_info = &(*p)[NPC_MCAM_RX][NPC_LID_LA][NPC_LT_LA_ETHER].xtract[0];
162         memcpy(&mkex->la_xtract, x_info, sizeof(struct npc_xtract_info));
163         x_info = &(*p)[NPC_MCAM_RX][NPC_LID_LB][NPC_LT_LB_CTAG].xtract[0];
164         memcpy(&mkex->lb_xtract, x_info, sizeof(struct npc_xtract_info));
165
166         return 0;
167 }
168
169 int
170 otx2_nix_vlan_offload_init(struct rte_eth_dev *eth_dev)
171 {
172         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
173         int rc;
174
175         /* Port initialized for first time or restarted */
176         if (!dev->configured) {
177                 rc = nix_vlan_get_mkex_info(dev);
178                 if (rc) {
179                         otx2_err("Failed to get vlan mkex info rc=%d", rc);
180                         return rc;
181                 }
182         }
183         return 0;
184 }
185
186 int
187 otx2_nix_vlan_fini(__rte_unused struct rte_eth_dev *eth_dev)
188 {
189         return 0;
190 }