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