1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2021 Marvell.
3 */
4
5 #include <rte_common.h>
6 #include <rte_memzone.h>
7
8 #include "cnxk_ethdev.h"
9
10 #define LOOKUP_ARRAY_SZ (PTYPE_ARRAY_SZ + ERR_ARRAY_SZ + SA_BASE_TBL_SZ + MEMPOOL_TBL_SZ)
11 const uint32_t *
cnxk_nix_supported_ptypes_get(struct rte_eth_dev * eth_dev,size_t * no_of_elements)12 cnxk_nix_supported_ptypes_get(struct rte_eth_dev *eth_dev,
13 size_t *no_of_elements)
14 {
15 RTE_SET_USED(eth_dev);
16
17 static const uint32_t ptypes[] = {
18 RTE_PTYPE_L2_ETHER, /* LA */
19 RTE_PTYPE_L2_ETHER_QINQ, /* LB */
20 RTE_PTYPE_L2_ETHER_VLAN, /* LB */
21 RTE_PTYPE_L2_ETHER_TIMESYNC, /* LB */
22 RTE_PTYPE_L2_ETHER_ARP, /* LC */
23 RTE_PTYPE_L2_ETHER_NSH, /* LC */
24 RTE_PTYPE_L2_ETHER_FCOE, /* LC */
25 RTE_PTYPE_L2_ETHER_MPLS, /* LC */
26 RTE_PTYPE_L3_IPV4, /* LC */
27 RTE_PTYPE_L3_IPV4_EXT, /* LC */
28 RTE_PTYPE_L3_IPV6, /* LC */
29 RTE_PTYPE_L3_IPV6_EXT, /* LC */
30 RTE_PTYPE_L4_TCP, /* LD */
31 RTE_PTYPE_L4_UDP, /* LD */
32 RTE_PTYPE_L4_SCTP, /* LD */
33 RTE_PTYPE_L4_ICMP, /* LD */
34 RTE_PTYPE_L4_IGMP, /* LD */
35 RTE_PTYPE_TUNNEL_GRE, /* LD */
36 RTE_PTYPE_TUNNEL_ESP, /* LD */
37 RTE_PTYPE_TUNNEL_NVGRE, /* LD */
38 RTE_PTYPE_TUNNEL_VXLAN, /* LE */
39 RTE_PTYPE_TUNNEL_GENEVE, /* LE */
40 RTE_PTYPE_TUNNEL_GTPC, /* LE */
41 RTE_PTYPE_TUNNEL_GTPU, /* LE */
42 RTE_PTYPE_TUNNEL_VXLAN_GPE, /* LE */
43 RTE_PTYPE_TUNNEL_MPLS_IN_GRE, /* LE */
44 RTE_PTYPE_TUNNEL_MPLS_IN_UDP, /* LE */
45 RTE_PTYPE_INNER_L2_ETHER, /* LF */
46 RTE_PTYPE_INNER_L3_IPV4, /* LG */
47 RTE_PTYPE_INNER_L3_IPV6, /* LG */
48 RTE_PTYPE_INNER_L4_TCP, /* LH */
49 RTE_PTYPE_INNER_L4_UDP, /* LH */
50 RTE_PTYPE_INNER_L4_SCTP, /* LH */
51 RTE_PTYPE_INNER_L4_ICMP, /* LH */
52 };
53
54 *no_of_elements = RTE_DIM(ptypes);
55 return ptypes;
56 }
57
58 /*
59 * +------------------ +------------------ +
60 * | | IL4 | IL3| IL2 | TU | L4 | L3 | L2 |
61 * +-------------------+-------------------+
62 *
63 * +-------------------+------------------ +
64 * | | LH | LG | LF | LE | LD | LC | LB |
65 * +-------------------+-------------------+
66 *
67 * ptype [LE - LD - LC - LB] = TU - L4 - L3 - T2
68 * ptype_tunnel[LH - LG - LF] = IL4 - IL3 - IL2 - TU
69 *
70 */
71 static void
nix_create_non_tunnel_ptype_array(uint16_t * ptype)72 nix_create_non_tunnel_ptype_array(uint16_t *ptype)
73 {
74 uint8_t lb, lc, ld, le;
75 uint16_t val;
76 uint32_t idx;
77
78 for (idx = 0; idx < PTYPE_NON_TUNNEL_ARRAY_SZ; idx++) {
79 lb = idx & 0xF;
80 lc = (idx & 0xF0) >> 4;
81 ld = (idx & 0xF00) >> 8;
82 le = (idx & 0xF000) >> 12;
83 val = RTE_PTYPE_UNKNOWN;
84
85 switch (lb) {
86 case NPC_LT_LB_STAG_QINQ:
87 val |= RTE_PTYPE_L2_ETHER_QINQ;
88 break;
89 case NPC_LT_LB_CTAG:
90 val |= RTE_PTYPE_L2_ETHER_VLAN;
91 break;
92 default:
93 val |= RTE_PTYPE_L2_ETHER;
94 }
95
96 switch (lc) {
97 case NPC_LT_LC_ARP:
98 val = (val & ~RTE_PTYPE_L2_MASK);
99 val |= RTE_PTYPE_L2_ETHER_ARP;
100 break;
101 case NPC_LT_LC_NSH:
102 val = (val & ~RTE_PTYPE_L2_MASK);
103 val |= RTE_PTYPE_L2_ETHER_NSH;
104 break;
105 case NPC_LT_LC_FCOE:
106 val = (val & ~RTE_PTYPE_L2_MASK);
107 val |= RTE_PTYPE_L2_ETHER_FCOE;
108 break;
109 case NPC_LT_LC_MPLS:
110 val = (val & ~RTE_PTYPE_L2_MASK);
111 val |= RTE_PTYPE_L2_ETHER_MPLS;
112 break;
113 case NPC_LT_LC_IP:
114 val |= RTE_PTYPE_L3_IPV4;
115 break;
116 case NPC_LT_LC_IP_OPT:
117 val |= RTE_PTYPE_L3_IPV4_EXT;
118 break;
119 case NPC_LT_LC_IP6:
120 val |= RTE_PTYPE_L3_IPV6;
121 break;
122 case NPC_LT_LC_IP6_EXT:
123 val |= RTE_PTYPE_L3_IPV6_EXT;
124 break;
125 case NPC_LT_LC_PTP:
126 val = (val & ~RTE_PTYPE_L2_MASK);
127 val |= RTE_PTYPE_L2_ETHER_TIMESYNC;
128 break;
129 }
130
131 switch (ld) {
132 case NPC_LT_LD_TCP:
133 val |= RTE_PTYPE_L4_TCP;
134 break;
135 case NPC_LT_LD_UDP:
136 val |= RTE_PTYPE_L4_UDP;
137 break;
138 case NPC_LT_LD_SCTP:
139 val |= RTE_PTYPE_L4_SCTP;
140 break;
141 case NPC_LT_LD_ICMP:
142 case NPC_LT_LD_ICMP6:
143 val |= RTE_PTYPE_L4_ICMP;
144 break;
145 case NPC_LT_LD_IGMP:
146 val |= RTE_PTYPE_L4_IGMP;
147 break;
148 case NPC_LT_LD_GRE:
149 val |= RTE_PTYPE_TUNNEL_GRE;
150 break;
151 case NPC_LT_LD_NVGRE:
152 val |= RTE_PTYPE_TUNNEL_NVGRE;
153 break;
154 }
155
156 switch (le) {
157 case NPC_LT_LE_VXLAN:
158 val |= RTE_PTYPE_TUNNEL_VXLAN;
159 break;
160 case NPC_LT_LE_ESP:
161 val |= RTE_PTYPE_TUNNEL_ESP;
162 break;
163 case NPC_LT_LE_VXLANGPE:
164 val |= RTE_PTYPE_TUNNEL_VXLAN_GPE;
165 break;
166 case NPC_LT_LE_GENEVE:
167 val |= RTE_PTYPE_TUNNEL_GENEVE;
168 break;
169 case NPC_LT_LE_GTPC:
170 val |= RTE_PTYPE_TUNNEL_GTPC;
171 break;
172 case NPC_LT_LE_GTPU:
173 val |= RTE_PTYPE_TUNNEL_GTPU;
174 break;
175 case NPC_LT_LE_TU_MPLS_IN_GRE:
176 val |= RTE_PTYPE_TUNNEL_MPLS_IN_GRE;
177 break;
178 case NPC_LT_LE_TU_MPLS_IN_UDP:
179 val |= RTE_PTYPE_TUNNEL_MPLS_IN_UDP;
180 break;
181 }
182 ptype[idx] = val;
183 }
184 }
185
186 #define TU_SHIFT(x) ((x) >> PTYPE_NON_TUNNEL_WIDTH)
187 static void
nix_create_tunnel_ptype_array(uint16_t * ptype)188 nix_create_tunnel_ptype_array(uint16_t *ptype)
189 {
190 uint8_t lf, lg, lh;
191 uint16_t val;
192 uint32_t idx;
193
194 /* Skip non tunnel ptype array memory */
195 ptype = ptype + PTYPE_NON_TUNNEL_ARRAY_SZ;
196
197 for (idx = 0; idx < PTYPE_TUNNEL_ARRAY_SZ; idx++) {
198 lf = idx & 0xF;
199 lg = (idx & 0xF0) >> 4;
200 lh = (idx & 0xF00) >> 8;
201 val = RTE_PTYPE_UNKNOWN;
202
203 switch (lf) {
204 case NPC_LT_LF_TU_ETHER:
205 val |= TU_SHIFT(RTE_PTYPE_INNER_L2_ETHER);
206 break;
207 }
208 switch (lg) {
209 case NPC_LT_LG_TU_IP:
210 val |= TU_SHIFT(RTE_PTYPE_INNER_L3_IPV4);
211 break;
212 case NPC_LT_LG_TU_IP6:
213 val |= TU_SHIFT(RTE_PTYPE_INNER_L3_IPV6);
214 break;
215 }
216 switch (lh) {
217 case NPC_LT_LH_TU_TCP:
218 val |= TU_SHIFT(RTE_PTYPE_INNER_L4_TCP);
219 break;
220 case NPC_LT_LH_TU_UDP:
221 val |= TU_SHIFT(RTE_PTYPE_INNER_L4_UDP);
222 break;
223 case NPC_LT_LH_TU_SCTP:
224 val |= TU_SHIFT(RTE_PTYPE_INNER_L4_SCTP);
225 break;
226 case NPC_LT_LH_TU_ICMP:
227 case NPC_LT_LH_TU_ICMP6:
228 val |= TU_SHIFT(RTE_PTYPE_INNER_L4_ICMP);
229 break;
230 }
231
232 ptype[idx] = val;
233 }
234 }
235
236 static void
nix_create_rx_ol_flags_array(void * mem)237 nix_create_rx_ol_flags_array(void *mem)
238 {
239 uint16_t idx, errcode, errlev;
240 uint32_t val, *ol_flags;
241
242 /* Skip ptype array memory */
243 ol_flags = (uint32_t *)((uint8_t *)mem + PTYPE_ARRAY_SZ);
244
245 for (idx = 0; idx < BIT(ERRCODE_ERRLEN_WIDTH); idx++) {
246 errlev = idx & 0xf;
247 errcode = (idx & 0xff0) >> 4;
248
249 val = RTE_MBUF_F_RX_IP_CKSUM_UNKNOWN;
250 val |= RTE_MBUF_F_RX_L4_CKSUM_UNKNOWN;
251 val |= RTE_MBUF_F_RX_OUTER_L4_CKSUM_UNKNOWN;
252
253 switch (errlev) {
254 case NPC_ERRLEV_RE:
255 /* Mark all errors as BAD checksum errors
256 * including Outer L2 length mismatch error
257 */
258 if (errcode) {
259 val |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
260 val |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
261 } else {
262 val |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
263 val |= RTE_MBUF_F_RX_L4_CKSUM_GOOD;
264 }
265 break;
266 case NPC_ERRLEV_LC:
267 if (errcode == NPC_EC_OIP4_CSUM ||
268 errcode == NPC_EC_IP_FRAG_OFFSET_1) {
269 val |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
270 val |= RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD;
271 } else {
272 val |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
273 }
274 break;
275 case NPC_ERRLEV_LG:
276 if (errcode == NPC_EC_IIP4_CSUM)
277 val |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
278 else
279 val |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
280 break;
281 case NPC_ERRLEV_NIX:
282 if (errcode == NIX_RX_PERRCODE_OL4_CHK ||
283 errcode == NIX_RX_PERRCODE_OL4_LEN ||
284 errcode == NIX_RX_PERRCODE_OL4_PORT) {
285 val |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
286 val |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
287 val |= RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD;
288 } else if (errcode == NIX_RX_PERRCODE_IL4_CHK ||
289 errcode == NIX_RX_PERRCODE_IL4_LEN ||
290 errcode == NIX_RX_PERRCODE_IL4_PORT) {
291 val |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
292 val |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
293 } else if (errcode == NIX_RX_PERRCODE_IL3_LEN ||
294 errcode == NIX_RX_PERRCODE_OL3_LEN) {
295 val |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
296 } else {
297 val |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
298 val |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
299 }
300 break;
301 }
302 ol_flags[idx] = val;
303 }
304 }
305
306 void *
cnxk_nix_fastpath_lookup_mem_get(void)307 cnxk_nix_fastpath_lookup_mem_get(void)
308 {
309 const char name[] = CNXK_NIX_FASTPATH_LOOKUP_MEM;
310 const struct rte_memzone *mz;
311 void *mem;
312
313 mz = rte_memzone_lookup(name);
314 if (mz != NULL)
315 return mz->addr;
316
317 /* Request for the first time */
318 mz = rte_memzone_reserve_aligned(name, LOOKUP_ARRAY_SZ, SOCKET_ID_ANY,
319 0, ROC_ALIGN);
320 if (mz != NULL) {
321 mem = mz->addr;
322 /* Form the ptype array lookup memory */
323 nix_create_non_tunnel_ptype_array(mem);
324 nix_create_tunnel_ptype_array(mem);
325 /* Form the rx ol_flags based on errcode */
326 nix_create_rx_ol_flags_array(mem);
327 return mem;
328 }
329 return NULL;
330 }
331
332 int
cnxk_nix_lookup_mem_sa_base_set(struct cnxk_eth_dev * dev)333 cnxk_nix_lookup_mem_sa_base_set(struct cnxk_eth_dev *dev)
334 {
335 void *lookup_mem = cnxk_nix_fastpath_lookup_mem_get();
336 uint16_t port = dev->eth_dev->data->port_id;
337 uintptr_t sa_base_tbl;
338 uintptr_t sa_base;
339 uint8_t sa_w;
340
341 if (!lookup_mem)
342 return -EIO;
343
344 sa_base = roc_nix_inl_inb_sa_base_get(&dev->nix, dev->inb.inl_dev);
345 if (!sa_base)
346 return -ENOTSUP;
347
348 sa_w = plt_log2_u32(dev->nix.ipsec_in_max_spi + 1 -
349 dev->nix.ipsec_in_min_spi);
350
351 /* Set SA Base in lookup mem */
352 sa_base_tbl = (uintptr_t)lookup_mem;
353 sa_base_tbl += PTYPE_ARRAY_SZ + ERR_ARRAY_SZ;
354 *((uintptr_t *)sa_base_tbl + port) = sa_base | sa_w;
355 return 0;
356 }
357
358 int
cnxk_nix_lookup_mem_sa_base_clear(struct cnxk_eth_dev * dev)359 cnxk_nix_lookup_mem_sa_base_clear(struct cnxk_eth_dev *dev)
360 {
361 void *lookup_mem = cnxk_nix_fastpath_lookup_mem_get();
362 uint16_t port = dev->eth_dev->data->port_id;
363 uintptr_t sa_base_tbl;
364
365 if (!lookup_mem)
366 return -EIO;
367
368 /* Set SA Base in lookup mem */
369 sa_base_tbl = (uintptr_t)lookup_mem;
370 sa_base_tbl += PTYPE_ARRAY_SZ + ERR_ARRAY_SZ;
371 *((uintptr_t *)sa_base_tbl + port) = 0;
372 return 0;
373 }
374
375 int
cnxk_nix_lookup_mem_metapool_set(struct cnxk_eth_dev * dev)376 cnxk_nix_lookup_mem_metapool_set(struct cnxk_eth_dev *dev)
377 {
378 void *lookup_mem = cnxk_nix_fastpath_lookup_mem_get();
379 uint16_t port = dev->eth_dev->data->port_id;
380 uintptr_t mp_tbl;
381
382 if (!lookup_mem)
383 return -EIO;
384
385 /* Set Mempool in lookup mem */
386 mp_tbl = (uintptr_t)lookup_mem;
387 mp_tbl += PTYPE_ARRAY_SZ + ERR_ARRAY_SZ + SA_BASE_TBL_SZ;
388 *((uintptr_t *)mp_tbl + port) = dev->nix.meta_mempool;
389 return 0;
390 }
391
392 int
cnxk_nix_lookup_mem_metapool_clear(struct cnxk_eth_dev * dev)393 cnxk_nix_lookup_mem_metapool_clear(struct cnxk_eth_dev *dev)
394 {
395 void *lookup_mem = cnxk_nix_fastpath_lookup_mem_get();
396 uint16_t port = dev->eth_dev->data->port_id;
397 uintptr_t mp_tbl;
398
399 if (!lookup_mem)
400 return -EIO;
401
402 /* Clear Mempool in lookup mem */
403 mp_tbl = (uintptr_t)lookup_mem;
404 mp_tbl += PTYPE_ARRAY_SZ + ERR_ARRAY_SZ + SA_BASE_TBL_SZ;
405 *((uintptr_t *)mp_tbl + port) = dev->nix.meta_mempool;
406 return 0;
407 }
408