xref: /dpdk/drivers/common/cnxk/roc_nix_ops.c (revision f665790a5dbad7b645ff46f31d65e977324e7bfc)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4 
5 #include "roc_api.h"
6 #include "roc_priv.h"
7 
8 static void
9 nix_lso_tcp(struct nix_lso_format_cfg *req, bool v4)
10 {
11 	__io struct nix_lso_format *field;
12 
13 	/* Format works only with TCP packet marked by OL3/OL4 */
14 	field = (__io struct nix_lso_format *)&req->fields[0];
15 	req->field_mask = NIX_LSO_FIELD_MASK;
16 	/* Outer IPv4/IPv6 */
17 	field->layer = NIX_TXLAYER_OL3;
18 	field->offset = v4 ? 2 : 4;
19 	field->sizem1 = 1; /* 2B */
20 	field->alg = NIX_LSOALG_ADD_PAYLEN;
21 	field++;
22 	if (v4) {
23 		/* IPID field */
24 		field->layer = NIX_TXLAYER_OL3;
25 		field->offset = 4;
26 		field->sizem1 = 1;
27 		/* Incremented linearly per segment */
28 		field->alg = NIX_LSOALG_ADD_SEGNUM;
29 		field++;
30 	}
31 
32 	/* TCP sequence number update */
33 	field->layer = NIX_TXLAYER_OL4;
34 	field->offset = 4;
35 	field->sizem1 = 3; /* 4 bytes */
36 	field->alg = NIX_LSOALG_ADD_OFFSET;
37 	field++;
38 	/* TCP flags field */
39 	field->layer = NIX_TXLAYER_OL4;
40 	field->offset = 12;
41 	field->sizem1 = 1;
42 	field->alg = NIX_LSOALG_TCP_FLAGS;
43 	field++;
44 }
45 
46 static void
47 nix_lso_udp_tun_tcp(struct nix_lso_format_cfg *req, bool outer_v4,
48 		    bool inner_v4)
49 {
50 	__io struct nix_lso_format *field;
51 
52 	field = (__io struct nix_lso_format *)&req->fields[0];
53 	req->field_mask = NIX_LSO_FIELD_MASK;
54 	/* Outer IPv4/IPv6 len */
55 	field->layer = NIX_TXLAYER_OL3;
56 	field->offset = outer_v4 ? 2 : 4;
57 	field->sizem1 = 1; /* 2B */
58 	field->alg = NIX_LSOALG_ADD_PAYLEN;
59 	field++;
60 	if (outer_v4) {
61 		/* IPID */
62 		field->layer = NIX_TXLAYER_OL3;
63 		field->offset = 4;
64 		field->sizem1 = 1;
65 		/* Incremented linearly per segment */
66 		field->alg = NIX_LSOALG_ADD_SEGNUM;
67 		field++;
68 	}
69 
70 	/* Outer UDP length */
71 	field->layer = NIX_TXLAYER_OL4;
72 	field->offset = 4;
73 	field->sizem1 = 1;
74 	field->alg = NIX_LSOALG_ADD_PAYLEN;
75 	field++;
76 
77 	/* Inner IPv4/IPv6 */
78 	field->layer = NIX_TXLAYER_IL3;
79 	field->offset = inner_v4 ? 2 : 4;
80 	field->sizem1 = 1; /* 2B */
81 	field->alg = NIX_LSOALG_ADD_PAYLEN;
82 	field++;
83 	if (inner_v4) {
84 		/* IPID field */
85 		field->layer = NIX_TXLAYER_IL3;
86 		field->offset = 4;
87 		field->sizem1 = 1;
88 		/* Incremented linearly per segment */
89 		field->alg = NIX_LSOALG_ADD_SEGNUM;
90 		field++;
91 	}
92 
93 	/* TCP sequence number update */
94 	field->layer = NIX_TXLAYER_IL4;
95 	field->offset = 4;
96 	field->sizem1 = 3; /* 4 bytes */
97 	field->alg = NIX_LSOALG_ADD_OFFSET;
98 	field++;
99 
100 	/* TCP flags field */
101 	field->layer = NIX_TXLAYER_IL4;
102 	field->offset = 12;
103 	field->sizem1 = 1;
104 	field->alg = NIX_LSOALG_TCP_FLAGS;
105 	field++;
106 }
107 
108 static void
109 nix_lso_tun_tcp(struct nix_lso_format_cfg *req, bool outer_v4, bool inner_v4)
110 {
111 	__io struct nix_lso_format *field;
112 
113 	field = (__io struct nix_lso_format *)&req->fields[0];
114 	req->field_mask = NIX_LSO_FIELD_MASK;
115 	/* Outer IPv4/IPv6 len */
116 	field->layer = NIX_TXLAYER_OL3;
117 	field->offset = outer_v4 ? 2 : 4;
118 	field->sizem1 = 1; /* 2B */
119 	field->alg = NIX_LSOALG_ADD_PAYLEN;
120 	field++;
121 	if (outer_v4) {
122 		/* IPID */
123 		field->layer = NIX_TXLAYER_OL3;
124 		field->offset = 4;
125 		field->sizem1 = 1;
126 		/* Incremented linearly per segment */
127 		field->alg = NIX_LSOALG_ADD_SEGNUM;
128 		field++;
129 	}
130 
131 	/* Inner IPv4/IPv6 */
132 	field->layer = NIX_TXLAYER_IL3;
133 	field->offset = inner_v4 ? 2 : 4;
134 	field->sizem1 = 1; /* 2B */
135 	field->alg = NIX_LSOALG_ADD_PAYLEN;
136 	field++;
137 	if (inner_v4) {
138 		/* IPID field */
139 		field->layer = NIX_TXLAYER_IL3;
140 		field->offset = 4;
141 		field->sizem1 = 1;
142 		/* Incremented linearly per segment */
143 		field->alg = NIX_LSOALG_ADD_SEGNUM;
144 		field++;
145 	}
146 
147 	/* TCP sequence number update */
148 	field->layer = NIX_TXLAYER_IL4;
149 	field->offset = 4;
150 	field->sizem1 = 3; /* 4 bytes */
151 	field->alg = NIX_LSOALG_ADD_OFFSET;
152 	field++;
153 
154 	/* TCP flags field */
155 	field->layer = NIX_TXLAYER_IL4;
156 	field->offset = 12;
157 	field->sizem1 = 1;
158 	field->alg = NIX_LSOALG_TCP_FLAGS;
159 	field++;
160 }
161 
162 int
163 roc_nix_lso_custom_fmt_setup(struct roc_nix *roc_nix,
164 			     struct nix_lso_format *fields, uint16_t nb_fields)
165 {
166 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
167 	struct dev *dev = &nix->dev;
168 	struct mbox *mbox = mbox_get(dev->mbox);
169 	struct nix_lso_format_cfg_rsp *rsp;
170 	struct nix_lso_format_cfg *req;
171 	int rc = -ENOSPC;
172 
173 	if (nb_fields > NIX_LSO_FIELD_MAX) {
174 		rc = -EINVAL;
175 		goto exit;
176 	}
177 
178 	req = mbox_alloc_msg_nix_lso_format_cfg(mbox);
179 	if (req == NULL)
180 		goto exit;
181 
182 	req->field_mask = NIX_LSO_FIELD_MASK;
183 	mbox_memcpy(req->fields, fields,
184 		    sizeof(struct nix_lso_format) * nb_fields);
185 
186 	rc = mbox_process_msg(mbox, (void *)&rsp);
187 	if (rc)
188 		goto exit;
189 
190 	plt_nix_dbg("Setup custom format %u", rsp->lso_format_idx);
191 	rc = rsp->lso_format_idx;
192 exit:
193 	mbox_put(mbox);
194 	return rc;
195 }
196 
197 int
198 roc_nix_lso_fmt_setup(struct roc_nix *roc_nix)
199 {
200 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
201 	struct dev *dev = &nix->dev;
202 	struct mbox *mbox = mbox_get(dev->mbox);
203 	struct nix_lso_format_cfg_rsp *rsp;
204 	struct nix_lso_format_cfg *req;
205 	int rc = -ENOSPC;
206 
207 	/*
208 	 * IPv4/TCP LSO
209 	 */
210 	req = mbox_alloc_msg_nix_lso_format_cfg(mbox);
211 	if (req == NULL)
212 		goto exit;
213 	nix_lso_tcp(req, true);
214 	rc = mbox_process_msg(mbox, (void *)&rsp);
215 	if (rc)
216 		goto exit;
217 
218 	if (rsp->lso_format_idx != NIX_LSO_FORMAT_IDX_TSOV4) {
219 		rc = NIX_ERR_INTERNAL;
220 		goto exit;
221 	}
222 
223 	plt_nix_dbg("tcpv4 lso fmt=%u", rsp->lso_format_idx);
224 
225 	/*
226 	 * IPv6/TCP LSO
227 	 */
228 	req = mbox_alloc_msg_nix_lso_format_cfg(mbox);
229 	if (req == NULL) {
230 		rc =  -ENOSPC;
231 		goto exit;
232 	}
233 	nix_lso_tcp(req, false);
234 	rc = mbox_process_msg(mbox, (void *)&rsp);
235 	if (rc)
236 		goto exit;
237 
238 	if (rsp->lso_format_idx != NIX_LSO_FORMAT_IDX_TSOV6) {
239 		rc = NIX_ERR_INTERNAL;
240 		goto exit;
241 	}
242 
243 	plt_nix_dbg("tcpv6 lso fmt=%u", rsp->lso_format_idx);
244 
245 	/*
246 	 * IPv4/UDP/TUN HDR/IPv4/TCP LSO
247 	 */
248 	req = mbox_alloc_msg_nix_lso_format_cfg(mbox);
249 	if (req == NULL) {
250 		rc =  -ENOSPC;
251 		goto exit;
252 	}
253 	nix_lso_udp_tun_tcp(req, true, true);
254 	rc = mbox_process_msg(mbox, (void *)&rsp);
255 	if (rc)
256 		goto exit;
257 
258 	nix->lso_udp_tun_idx[ROC_NIX_LSO_TUN_V4V4] = rsp->lso_format_idx;
259 	plt_nix_dbg("udp tun v4v4 fmt=%u", rsp->lso_format_idx);
260 
261 	/*
262 	 * IPv4/UDP/TUN HDR/IPv6/TCP LSO
263 	 */
264 	req = mbox_alloc_msg_nix_lso_format_cfg(mbox);
265 	if (req == NULL) {
266 		rc =  -ENOSPC;
267 		goto exit;
268 	}
269 	nix_lso_udp_tun_tcp(req, true, false);
270 	rc = mbox_process_msg(mbox, (void *)&rsp);
271 	if (rc)
272 		goto exit;
273 
274 	nix->lso_udp_tun_idx[ROC_NIX_LSO_TUN_V4V6] = rsp->lso_format_idx;
275 	plt_nix_dbg("udp tun v4v6 fmt=%u", rsp->lso_format_idx);
276 
277 	/*
278 	 * IPv6/UDP/TUN HDR/IPv4/TCP LSO
279 	 */
280 	req = mbox_alloc_msg_nix_lso_format_cfg(mbox);
281 	if (req == NULL) {
282 		rc =  -ENOSPC;
283 		goto exit;
284 	}
285 	nix_lso_udp_tun_tcp(req, false, true);
286 	rc = mbox_process_msg(mbox, (void *)&rsp);
287 	if (rc)
288 		goto exit;
289 
290 	nix->lso_udp_tun_idx[ROC_NIX_LSO_TUN_V6V4] = rsp->lso_format_idx;
291 	plt_nix_dbg("udp tun v6v4 fmt=%u", rsp->lso_format_idx);
292 
293 	/*
294 	 * IPv6/UDP/TUN HDR/IPv6/TCP LSO
295 	 */
296 	req = mbox_alloc_msg_nix_lso_format_cfg(mbox);
297 	if (req == NULL) {
298 		rc =  -ENOSPC;
299 		goto exit;
300 	}
301 	nix_lso_udp_tun_tcp(req, false, false);
302 	rc = mbox_process_msg(mbox, (void *)&rsp);
303 	if (rc)
304 		goto exit;
305 
306 	nix->lso_udp_tun_idx[ROC_NIX_LSO_TUN_V6V6] = rsp->lso_format_idx;
307 	plt_nix_dbg("udp tun v6v6 fmt=%u", rsp->lso_format_idx);
308 
309 	/*
310 	 * IPv4/TUN HDR/IPv4/TCP LSO
311 	 */
312 	req = mbox_alloc_msg_nix_lso_format_cfg(mbox);
313 	if (req == NULL) {
314 		rc =  -ENOSPC;
315 		goto exit;
316 	}
317 	nix_lso_tun_tcp(req, true, true);
318 	rc = mbox_process_msg(mbox, (void *)&rsp);
319 	if (rc)
320 		goto exit;
321 
322 	nix->lso_tun_idx[ROC_NIX_LSO_TUN_V4V4] = rsp->lso_format_idx;
323 	plt_nix_dbg("tun v4v4 fmt=%u", rsp->lso_format_idx);
324 
325 	/*
326 	 * IPv4/TUN HDR/IPv6/TCP LSO
327 	 */
328 	req = mbox_alloc_msg_nix_lso_format_cfg(mbox);
329 	if (req == NULL) {
330 		rc =  -ENOSPC;
331 		goto exit;
332 	}
333 	nix_lso_tun_tcp(req, true, false);
334 	rc = mbox_process_msg(mbox, (void *)&rsp);
335 	if (rc)
336 		goto exit;
337 
338 	nix->lso_tun_idx[ROC_NIX_LSO_TUN_V4V6] = rsp->lso_format_idx;
339 	plt_nix_dbg("tun v4v6 fmt=%u", rsp->lso_format_idx);
340 
341 	/*
342 	 * IPv6/TUN HDR/IPv4/TCP LSO
343 	 */
344 	req = mbox_alloc_msg_nix_lso_format_cfg(mbox);
345 	if (req == NULL) {
346 		rc =  -ENOSPC;
347 		goto exit;
348 	}
349 	nix_lso_tun_tcp(req, false, true);
350 	rc = mbox_process_msg(mbox, (void *)&rsp);
351 	if (rc)
352 		goto exit;
353 
354 	nix->lso_tun_idx[ROC_NIX_LSO_TUN_V6V4] = rsp->lso_format_idx;
355 	plt_nix_dbg("tun v6v4 fmt=%u", rsp->lso_format_idx);
356 
357 	/*
358 	 * IPv6/TUN HDR/IPv6/TCP LSO
359 	 */
360 	req = mbox_alloc_msg_nix_lso_format_cfg(mbox);
361 	if (req == NULL) {
362 		rc =  -ENOSPC;
363 		goto exit;
364 	}
365 
366 	nix_lso_tun_tcp(req, false, false);
367 	rc = mbox_process_msg(mbox, (void *)&rsp);
368 	if (rc)
369 		goto exit;
370 
371 	nix->lso_tun_idx[ROC_NIX_LSO_TUN_V6V6] = rsp->lso_format_idx;
372 	plt_nix_dbg("tun v6v6 fmt=%u", rsp->lso_format_idx);
373 	rc = 0;
374 exit:
375 	mbox_put(mbox);
376 	return rc;
377 }
378 
379 int
380 roc_nix_lso_fmt_get(struct roc_nix *roc_nix,
381 		    uint8_t udp_tun[ROC_NIX_LSO_TUN_MAX],
382 		    uint8_t tun[ROC_NIX_LSO_TUN_MAX])
383 {
384 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
385 
386 	memcpy(udp_tun, nix->lso_udp_tun_idx, ROC_NIX_LSO_TUN_MAX);
387 	memcpy(tun, nix->lso_tun_idx, ROC_NIX_LSO_TUN_MAX);
388 	return 0;
389 }
390 
391 int
392 roc_nix_switch_hdr_set(struct roc_nix *roc_nix, uint64_t switch_header_type,
393 		       uint8_t pre_l2_size_offset,
394 		       uint8_t pre_l2_size_offset_mask,
395 		       uint8_t pre_l2_size_shift_dir)
396 {
397 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
398 	struct dev *dev = &nix->dev;
399 	struct mbox *mbox = mbox_get(dev->mbox);
400 	struct npc_set_pkind *req;
401 	struct msg_resp *rsp;
402 	int rc = -ENOSPC;
403 
404 	if (switch_header_type == 0)
405 		switch_header_type = ROC_PRIV_FLAGS_DEFAULT;
406 
407 	if (switch_header_type != ROC_PRIV_FLAGS_DEFAULT &&
408 	    switch_header_type != ROC_PRIV_FLAGS_EDSA &&
409 	    switch_header_type != ROC_PRIV_FLAGS_HIGIG &&
410 	    switch_header_type != ROC_PRIV_FLAGS_LEN_90B &&
411 	    switch_header_type != ROC_PRIV_FLAGS_EXDSA &&
412 	    switch_header_type != ROC_PRIV_FLAGS_VLAN_EXDSA &&
413 	    switch_header_type != ROC_PRIV_FLAGS_PRE_L2 &&
414 	    switch_header_type != ROC_PRIV_FLAGS_CUSTOM) {
415 		plt_err("switch header type is not supported");
416 		rc = NIX_ERR_PARAM;
417 		goto exit;
418 	}
419 
420 	if (switch_header_type == ROC_PRIV_FLAGS_LEN_90B &&
421 	    !roc_nix_is_sdp(roc_nix)) {
422 		plt_err("chlen90b is not supported on non-SDP device");
423 		rc = NIX_ERR_PARAM;
424 		goto exit;
425 	}
426 
427 	if (switch_header_type == ROC_PRIV_FLAGS_HIGIG &&
428 	    roc_nix_is_vf_or_sdp(roc_nix)) {
429 		plt_err("higig2 is supported on PF devices only");
430 		rc = NIX_ERR_PARAM;
431 		goto exit;
432 	}
433 
434 	req = mbox_alloc_msg_npc_set_pkind(mbox);
435 	if (req == NULL)
436 		goto exit;
437 	req->mode = switch_header_type;
438 
439 	if (switch_header_type == ROC_PRIV_FLAGS_LEN_90B) {
440 		req->mode = ROC_PRIV_FLAGS_CUSTOM;
441 		req->pkind = NPC_RX_CHLEN90B_PKIND;
442 	} else if (switch_header_type == ROC_PRIV_FLAGS_EXDSA) {
443 		req->mode = ROC_PRIV_FLAGS_CUSTOM;
444 		req->pkind = NPC_RX_EXDSA_PKIND;
445 	} else if (switch_header_type == ROC_PRIV_FLAGS_VLAN_EXDSA) {
446 		req->mode = ROC_PRIV_FLAGS_CUSTOM;
447 		req->pkind = NPC_RX_VLAN_EXDSA_PKIND;
448 	} else if (switch_header_type == ROC_PRIV_FLAGS_PRE_L2) {
449 		req->mode = ROC_PRIV_FLAGS_CUSTOM;
450 		req->pkind = NPC_RX_CUSTOM_PRE_L2_PKIND;
451 		req->var_len_off = pre_l2_size_offset;
452 		req->var_len_off_mask = pre_l2_size_offset_mask;
453 		req->shift_dir = pre_l2_size_shift_dir;
454 	}
455 
456 	req->dir = PKIND_RX;
457 	rc = mbox_process_msg(mbox, (void *)&rsp);
458 	if (rc)
459 		goto exit;
460 
461 	req = mbox_alloc_msg_npc_set_pkind(mbox);
462 	if (req == NULL) {
463 		rc = -ENOSPC;
464 		goto exit;
465 	}
466 	req->mode = switch_header_type;
467 	req->dir = PKIND_TX;
468 	rc = mbox_process_msg(mbox, (void *)&rsp);
469 exit:
470 	mbox_put(mbox);
471 	return rc;
472 }
473 
474 int
475 roc_nix_eeprom_info_get(struct roc_nix *roc_nix,
476 			struct roc_nix_eeprom_info *info)
477 {
478 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
479 	struct dev *dev = &nix->dev;
480 	struct mbox *mbox = mbox_get(dev->mbox);
481 	struct cgx_fw_data *rsp = NULL;
482 	int rc;
483 
484 	if (!info) {
485 		plt_err("Input buffer is NULL");
486 		rc = NIX_ERR_PARAM;
487 		goto exit;
488 	}
489 
490 	mbox_alloc_msg_cgx_get_aux_link_info(mbox);
491 	rc = mbox_process_msg(mbox, (void *)&rsp);
492 	if (rc) {
493 		plt_err("Failed to get fw data: %d", rc);
494 		goto exit;
495 	}
496 
497 	info->sff_id = rsp->fwdata.sfp_eeprom.sff_id;
498 	mbox_memcpy(info->buf, rsp->fwdata.sfp_eeprom.buf, SFP_EEPROM_SIZE);
499 	rc = 0;
500 exit:
501 	mbox_put(mbox);
502 	return rc;
503 }
504 
505 int
506 roc_nix_rx_drop_re_set(struct roc_nix *roc_nix, bool ena)
507 {
508 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
509 	struct dev *dev = &nix->dev;
510 	struct mbox *mbox = mbox_get(dev->mbox);
511 	struct nix_rx_cfg *req;
512 	int rc = -EIO;
513 
514 	/* No-op if no change */
515 	if (ena == !!(nix->rx_cfg & ROC_NIX_LF_RX_CFG_DROP_RE)) {
516 		rc = 0;
517 		goto exit;
518 	}
519 
520 	req = mbox_alloc_msg_nix_set_rx_cfg(mbox);
521 	if (req == NULL)
522 		goto exit;
523 
524 	if (ena)
525 		req->len_verify |= NIX_RX_DROP_RE;
526 	/* Keep other flags intact */
527 	if (nix->rx_cfg & ROC_NIX_LF_RX_CFG_LEN_OL3)
528 		req->len_verify |= NIX_RX_OL3_VERIFY;
529 
530 	if (nix->rx_cfg & ROC_NIX_LF_RX_CFG_LEN_OL4)
531 		req->len_verify |= NIX_RX_OL4_VERIFY;
532 
533 	if (nix->rx_cfg & ROC_NIX_LF_RX_CFG_CSUM_OL4)
534 		req->csum_verify |= NIX_RX_CSUM_OL4_VERIFY;
535 
536 	rc = mbox_process(mbox);
537 	if (rc)
538 		goto exit;
539 
540 	if (ena)
541 		nix->rx_cfg |= ROC_NIX_LF_RX_CFG_DROP_RE;
542 	else
543 		nix->rx_cfg &= ~ROC_NIX_LF_RX_CFG_DROP_RE;
544 	rc = 0;
545 exit:
546 	mbox_put(mbox);
547 	return rc;
548 }
549