1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2019 Marvell International Ltd.
3 */
4
5 #include <rte_common.h>
6 #include <rte_memzone.h>
7
8 #include "otx2_common.h"
9 #include "otx2_ethdev.h"
10
11 /* NIX_RX_PARSE_S's ERRCODE + ERRLEV (12 bits) */
12 #define ERRCODE_ERRLEN_WIDTH 12
13 #define ERR_ARRAY_SZ ((BIT(ERRCODE_ERRLEN_WIDTH)) *\
14 sizeof(uint32_t))
15
16 #define SA_TBL_SZ (RTE_MAX_ETHPORTS * sizeof(uint64_t))
17 #define LOOKUP_ARRAY_SZ (PTYPE_ARRAY_SZ + ERR_ARRAY_SZ +\
18 SA_TBL_SZ)
19
20 const uint32_t *
otx2_nix_supported_ptypes_get(struct rte_eth_dev * eth_dev)21 otx2_nix_supported_ptypes_get(struct rte_eth_dev *eth_dev)
22 {
23 RTE_SET_USED(eth_dev);
24
25 static const uint32_t ptypes[] = {
26 RTE_PTYPE_L2_ETHER_QINQ, /* LB */
27 RTE_PTYPE_L2_ETHER_VLAN, /* LB */
28 RTE_PTYPE_L2_ETHER_TIMESYNC, /* LB */
29 RTE_PTYPE_L2_ETHER_ARP, /* LC */
30 RTE_PTYPE_L2_ETHER_NSH, /* LC */
31 RTE_PTYPE_L2_ETHER_FCOE, /* LC */
32 RTE_PTYPE_L2_ETHER_MPLS, /* LC */
33 RTE_PTYPE_L3_IPV4, /* LC */
34 RTE_PTYPE_L3_IPV4_EXT, /* LC */
35 RTE_PTYPE_L3_IPV6, /* LC */
36 RTE_PTYPE_L3_IPV6_EXT, /* LC */
37 RTE_PTYPE_L4_TCP, /* LD */
38 RTE_PTYPE_L4_UDP, /* LD */
39 RTE_PTYPE_L4_SCTP, /* LD */
40 RTE_PTYPE_L4_ICMP, /* LD */
41 RTE_PTYPE_L4_IGMP, /* LD */
42 RTE_PTYPE_TUNNEL_GRE, /* LD */
43 RTE_PTYPE_TUNNEL_ESP, /* LD */
44 RTE_PTYPE_TUNNEL_NVGRE, /* LD */
45 RTE_PTYPE_TUNNEL_VXLAN, /* LE */
46 RTE_PTYPE_TUNNEL_GENEVE, /* LE */
47 RTE_PTYPE_TUNNEL_GTPC, /* LE */
48 RTE_PTYPE_TUNNEL_GTPU, /* LE */
49 RTE_PTYPE_TUNNEL_VXLAN_GPE, /* LE */
50 RTE_PTYPE_TUNNEL_MPLS_IN_GRE, /* LE */
51 RTE_PTYPE_TUNNEL_MPLS_IN_UDP, /* LE */
52 RTE_PTYPE_INNER_L2_ETHER,/* LF */
53 RTE_PTYPE_INNER_L3_IPV4, /* LG */
54 RTE_PTYPE_INNER_L3_IPV6, /* LG */
55 RTE_PTYPE_INNER_L4_TCP, /* LH */
56 RTE_PTYPE_INNER_L4_UDP, /* LH */
57 RTE_PTYPE_INNER_L4_SCTP, /* LH */
58 RTE_PTYPE_INNER_L4_ICMP, /* LH */
59 RTE_PTYPE_UNKNOWN,
60 };
61
62 return ptypes;
63 }
64
65 int
otx2_nix_ptypes_set(struct rte_eth_dev * eth_dev,uint32_t ptype_mask)66 otx2_nix_ptypes_set(struct rte_eth_dev *eth_dev, uint32_t ptype_mask)
67 {
68 struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
69
70 if (ptype_mask) {
71 dev->rx_offload_flags |= NIX_RX_OFFLOAD_PTYPE_F;
72 dev->ptype_disable = 0;
73 } else {
74 dev->rx_offload_flags &= ~NIX_RX_OFFLOAD_PTYPE_F;
75 dev->ptype_disable = 1;
76 }
77
78 otx2_eth_set_rx_function(eth_dev);
79
80 return 0;
81 }
82
83 /*
84 * +------------------ +------------------ +
85 * | | IL4 | IL3| IL2 | TU | L4 | L3 | L2 |
86 * +-------------------+-------------------+
87 *
88 * +-------------------+------------------ +
89 * | | LH | LG | LF | LE | LD | LC | LB |
90 * +-------------------+-------------------+
91 *
92 * ptype [LE - LD - LC - LB] = TU - L4 - L3 - T2
93 * ptype_tunnel[LH - LG - LF] = IL4 - IL3 - IL2 - TU
94 *
95 */
96 static void
nix_create_non_tunnel_ptype_array(uint16_t * ptype)97 nix_create_non_tunnel_ptype_array(uint16_t *ptype)
98 {
99 uint8_t lb, lc, ld, le;
100 uint16_t val;
101 uint32_t idx;
102
103 for (idx = 0; idx < PTYPE_NON_TUNNEL_ARRAY_SZ; idx++) {
104 lb = idx & 0xF;
105 lc = (idx & 0xF0) >> 4;
106 ld = (idx & 0xF00) >> 8;
107 le = (idx & 0xF000) >> 12;
108 val = RTE_PTYPE_UNKNOWN;
109
110 switch (lb) {
111 case NPC_LT_LB_STAG_QINQ:
112 val |= RTE_PTYPE_L2_ETHER_QINQ;
113 break;
114 case NPC_LT_LB_CTAG:
115 val |= RTE_PTYPE_L2_ETHER_VLAN;
116 break;
117 }
118
119 switch (lc) {
120 case NPC_LT_LC_ARP:
121 val |= RTE_PTYPE_L2_ETHER_ARP;
122 break;
123 case NPC_LT_LC_NSH:
124 val |= RTE_PTYPE_L2_ETHER_NSH;
125 break;
126 case NPC_LT_LC_FCOE:
127 val |= RTE_PTYPE_L2_ETHER_FCOE;
128 break;
129 case NPC_LT_LC_MPLS:
130 val |= RTE_PTYPE_L2_ETHER_MPLS;
131 break;
132 case NPC_LT_LC_IP:
133 val |= RTE_PTYPE_L3_IPV4;
134 break;
135 case NPC_LT_LC_IP_OPT:
136 val |= RTE_PTYPE_L3_IPV4_EXT;
137 break;
138 case NPC_LT_LC_IP6:
139 val |= RTE_PTYPE_L3_IPV6;
140 break;
141 case NPC_LT_LC_IP6_EXT:
142 val |= RTE_PTYPE_L3_IPV6_EXT;
143 break;
144 case NPC_LT_LC_PTP:
145 val |= RTE_PTYPE_L2_ETHER_TIMESYNC;
146 break;
147 }
148
149 switch (ld) {
150 case NPC_LT_LD_TCP:
151 val |= RTE_PTYPE_L4_TCP;
152 break;
153 case NPC_LT_LD_UDP:
154 val |= RTE_PTYPE_L4_UDP;
155 break;
156 case NPC_LT_LD_SCTP:
157 val |= RTE_PTYPE_L4_SCTP;
158 break;
159 case NPC_LT_LD_ICMP:
160 case NPC_LT_LD_ICMP6:
161 val |= RTE_PTYPE_L4_ICMP;
162 break;
163 case NPC_LT_LD_IGMP:
164 val |= RTE_PTYPE_L4_IGMP;
165 break;
166 case NPC_LT_LD_GRE:
167 val |= RTE_PTYPE_TUNNEL_GRE;
168 break;
169 case NPC_LT_LD_NVGRE:
170 val |= RTE_PTYPE_TUNNEL_NVGRE;
171 break;
172 }
173
174 switch (le) {
175 case NPC_LT_LE_VXLAN:
176 val |= RTE_PTYPE_TUNNEL_VXLAN;
177 break;
178 case NPC_LT_LE_ESP:
179 val |= RTE_PTYPE_TUNNEL_ESP;
180 break;
181 case NPC_LT_LE_VXLANGPE:
182 val |= RTE_PTYPE_TUNNEL_VXLAN_GPE;
183 break;
184 case NPC_LT_LE_GENEVE:
185 val |= RTE_PTYPE_TUNNEL_GENEVE;
186 break;
187 case NPC_LT_LE_GTPC:
188 val |= RTE_PTYPE_TUNNEL_GTPC;
189 break;
190 case NPC_LT_LE_GTPU:
191 val |= RTE_PTYPE_TUNNEL_GTPU;
192 break;
193 case NPC_LT_LE_TU_MPLS_IN_GRE:
194 val |= RTE_PTYPE_TUNNEL_MPLS_IN_GRE;
195 break;
196 case NPC_LT_LE_TU_MPLS_IN_UDP:
197 val |= RTE_PTYPE_TUNNEL_MPLS_IN_UDP;
198 break;
199 }
200 ptype[idx] = val;
201 }
202 }
203
204 #define TU_SHIFT(x) ((x) >> PTYPE_NON_TUNNEL_WIDTH)
205 static void
nix_create_tunnel_ptype_array(uint16_t * ptype)206 nix_create_tunnel_ptype_array(uint16_t *ptype)
207 {
208 uint8_t lf, lg, lh;
209 uint16_t val;
210 uint32_t idx;
211
212 /* Skip non tunnel ptype array memory */
213 ptype = ptype + PTYPE_NON_TUNNEL_ARRAY_SZ;
214
215 for (idx = 0; idx < PTYPE_TUNNEL_ARRAY_SZ; idx++) {
216 lf = idx & 0xF;
217 lg = (idx & 0xF0) >> 4;
218 lh = (idx & 0xF00) >> 8;
219 val = RTE_PTYPE_UNKNOWN;
220
221 switch (lf) {
222 case NPC_LT_LF_TU_ETHER:
223 val |= TU_SHIFT(RTE_PTYPE_INNER_L2_ETHER);
224 break;
225 }
226 switch (lg) {
227 case NPC_LT_LG_TU_IP:
228 val |= TU_SHIFT(RTE_PTYPE_INNER_L3_IPV4);
229 break;
230 case NPC_LT_LG_TU_IP6:
231 val |= TU_SHIFT(RTE_PTYPE_INNER_L3_IPV6);
232 break;
233 }
234 switch (lh) {
235 case NPC_LT_LH_TU_TCP:
236 val |= TU_SHIFT(RTE_PTYPE_INNER_L4_TCP);
237 break;
238 case NPC_LT_LH_TU_UDP:
239 val |= TU_SHIFT(RTE_PTYPE_INNER_L4_UDP);
240 break;
241 case NPC_LT_LH_TU_SCTP:
242 val |= TU_SHIFT(RTE_PTYPE_INNER_L4_SCTP);
243 break;
244 case NPC_LT_LH_TU_ICMP:
245 case NPC_LT_LH_TU_ICMP6:
246 val |= TU_SHIFT(RTE_PTYPE_INNER_L4_ICMP);
247 break;
248 }
249
250 ptype[idx] = val;
251 }
252 }
253
254 static void
nix_create_rx_ol_flags_array(void * mem)255 nix_create_rx_ol_flags_array(void *mem)
256 {
257 uint16_t idx, errcode, errlev;
258 uint32_t val, *ol_flags;
259
260 /* Skip ptype array memory */
261 ol_flags = (uint32_t *)((uint8_t *)mem + PTYPE_ARRAY_SZ);
262
263 for (idx = 0; idx < BIT(ERRCODE_ERRLEN_WIDTH); idx++) {
264 errlev = idx & 0xf;
265 errcode = (idx & 0xff0) >> 4;
266
267 val = PKT_RX_IP_CKSUM_UNKNOWN;
268 val |= PKT_RX_L4_CKSUM_UNKNOWN;
269 val |= PKT_RX_OUTER_L4_CKSUM_UNKNOWN;
270
271 switch (errlev) {
272 case NPC_ERRLEV_RE:
273 /* Mark all errors as BAD checksum errors
274 * including Outer L2 length mismatch error
275 */
276 if (errcode) {
277 val |= PKT_RX_IP_CKSUM_BAD;
278 val |= PKT_RX_L4_CKSUM_BAD;
279 } else {
280 val |= PKT_RX_IP_CKSUM_GOOD;
281 val |= PKT_RX_L4_CKSUM_GOOD;
282 }
283 break;
284 case NPC_ERRLEV_LC:
285 if (errcode == NPC_EC_OIP4_CSUM ||
286 errcode == NPC_EC_IP_FRAG_OFFSET_1) {
287 val |= PKT_RX_IP_CKSUM_BAD;
288 val |= PKT_RX_EIP_CKSUM_BAD;
289 } else {
290 val |= PKT_RX_IP_CKSUM_GOOD;
291 }
292 break;
293 case NPC_ERRLEV_LG:
294 if (errcode == NPC_EC_IIP4_CSUM)
295 val |= PKT_RX_IP_CKSUM_BAD;
296 else
297 val |= PKT_RX_IP_CKSUM_GOOD;
298 break;
299 case NPC_ERRLEV_NIX:
300 if (errcode == NIX_RX_PERRCODE_OL4_CHK ||
301 errcode == NIX_RX_PERRCODE_OL4_LEN ||
302 errcode == NIX_RX_PERRCODE_OL4_PORT) {
303 val |= PKT_RX_IP_CKSUM_GOOD;
304 val |= PKT_RX_L4_CKSUM_BAD;
305 val |= PKT_RX_OUTER_L4_CKSUM_BAD;
306 } else if (errcode == NIX_RX_PERRCODE_IL4_CHK ||
307 errcode == NIX_RX_PERRCODE_IL4_LEN ||
308 errcode == NIX_RX_PERRCODE_IL4_PORT) {
309 val |= PKT_RX_IP_CKSUM_GOOD;
310 val |= PKT_RX_L4_CKSUM_BAD;
311 } else if (errcode == NIX_RX_PERRCODE_IL3_LEN ||
312 errcode == NIX_RX_PERRCODE_OL3_LEN) {
313 val |= PKT_RX_IP_CKSUM_BAD;
314 } else {
315 val |= PKT_RX_IP_CKSUM_GOOD;
316 val |= PKT_RX_L4_CKSUM_GOOD;
317 }
318 break;
319 }
320 ol_flags[idx] = val;
321 }
322 }
323
324 void *
otx2_nix_fastpath_lookup_mem_get(void)325 otx2_nix_fastpath_lookup_mem_get(void)
326 {
327 const char name[] = OTX2_NIX_FASTPATH_LOOKUP_MEM;
328 const struct rte_memzone *mz;
329 void *mem;
330
331 /* SA_TBL starts after PTYPE_ARRAY & ERR_ARRAY */
332 RTE_BUILD_BUG_ON(OTX2_NIX_SA_TBL_START != (PTYPE_ARRAY_SZ +
333 ERR_ARRAY_SZ));
334
335 mz = rte_memzone_lookup(name);
336 if (mz != NULL)
337 return mz->addr;
338
339 /* Request for the first time */
340 mz = rte_memzone_reserve_aligned(name, LOOKUP_ARRAY_SZ,
341 SOCKET_ID_ANY, 0, OTX2_ALIGN);
342 if (mz != NULL) {
343 mem = mz->addr;
344 /* Form the ptype array lookup memory */
345 nix_create_non_tunnel_ptype_array(mem);
346 nix_create_tunnel_ptype_array(mem);
347 /* Form the rx ol_flags based on errcode */
348 nix_create_rx_ol_flags_array(mem);
349 return mem;
350 }
351 return NULL;
352 }
353