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