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