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