1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2018 Netronome Systems, Inc. 3 * All rights reserved. 4 */ 5 6 #include "nfp_nsp.h" 7 8 #include <nfp_platform.h> 9 #include <rte_common.h> 10 11 #include "nfp_logs.h" 12 #include "nfp_resource.h" 13 14 /* Offsets relative to the CSR base */ 15 #define NSP_STATUS 0x00 16 #define NSP_STATUS_MAGIC GENMASK_ULL(63, 48) 17 #define NSP_STATUS_MAJOR GENMASK_ULL(47, 44) 18 #define NSP_STATUS_MINOR GENMASK_ULL(43, 32) 19 #define NSP_STATUS_CODE GENMASK_ULL(31, 16) 20 #define NSP_STATUS_RESULT GENMASK_ULL(15, 8) 21 #define NSP_STATUS_BUSY RTE_BIT64(0) 22 23 #define NSP_COMMAND 0x08 24 #define NSP_COMMAND_OPTION GENMASK_ULL(63, 32) 25 #define NSP_COMMAND_VER_MAJOR GENMASK_ULL(31, 28) 26 #define NSP_COMMAND_CODE GENMASK_ULL(27, 16) 27 #define NSP_COMMAND_DMA_BUF RTE_BIT64(1) 28 #define NSP_COMMAND_START RTE_BIT64(0) 29 30 /* CPP address to retrieve the data from */ 31 #define NSP_BUFFER 0x10 32 #define NSP_BUFFER_CPP GENMASK_ULL(63, 40) 33 #define NSP_BUFFER_ADDRESS GENMASK_ULL(39, 0) 34 35 #define NSP_DFLT_BUFFER 0x18 36 #define NSP_DFLT_BUFFER_CPP GENMASK_ULL(63, 40) 37 #define NSP_DFLT_BUFFER_ADDRESS GENMASK_ULL(39, 0) 38 39 #define NSP_DFLT_BUFFER_CONFIG 0x20 40 #define NSP_DFLT_BUFFER_SIZE_4KB GENMASK_ULL(15, 8) 41 #define NSP_DFLT_BUFFER_SIZE_MB GENMASK_ULL(7, 0) 42 43 #define NSP_MAGIC 0xab10 44 45 /* 46 * ABI major version is bumped separately without resetting minor 47 * version when the change in NSP is not compatible to old driver. 48 */ 49 #define NSP_MAJOR 1 50 51 /* 52 * ABI minor version is bumped when new feature is introduced 53 * while old driver can still work without this new feature. 54 */ 55 #define NSP_MINOR 8 56 57 #define NSP_CODE_MAJOR GENMASK_ULL(15, 12) 58 #define NSP_CODE_MINOR GENMASK_ULL(11, 0) 59 60 #define NFP_FW_LOAD_RET_MAJOR GENMASK_ULL(15, 8) 61 #define NFP_FW_LOAD_RET_MINOR GENMASK_ULL(23, 16) 62 63 #define NFP_HWINFO_LOOKUP_SIZE GENMASK_ULL(11, 0) 64 65 enum nfp_nsp_cmd { 66 SPCODE_NOOP = 0, /* No operation */ 67 SPCODE_SOFT_RESET = 1, /* Soft reset the NFP */ 68 SPCODE_FW_DEFAULT = 2, /* Load default (UNDI) FW */ 69 SPCODE_PHY_INIT = 3, /* Initialize the PHY */ 70 SPCODE_MAC_INIT = 4, /* Initialize the MAC */ 71 SPCODE_PHY_RXADAPT = 5, /* Re-run PHY RX Adaptation */ 72 SPCODE_FW_LOAD = 6, /* Load fw from buffer, len in option */ 73 SPCODE_ETH_RESCAN = 7, /* Rescan ETHs, write ETH_TABLE to buf */ 74 SPCODE_ETH_CONTROL = 8, /* Update media config from buffer */ 75 SPCODE_NSP_WRITE_FLASH = 11, /* Load and flash image from buffer */ 76 SPCODE_NSP_SENSORS = 12, /* Read NSP sensor(s) */ 77 SPCODE_NSP_IDENTIFY = 13, /* Read NSP version */ 78 SPCODE_FW_STORED = 16, /* If no FW loaded, load flash app FW */ 79 SPCODE_HWINFO_LOOKUP = 17, /* Lookup HWinfo with overwrites etc. */ 80 SPCODE_HWINFO_SET = 18, /* Set HWinfo entry */ 81 SPCODE_FW_LOADED = 19, /* Is application firmware loaded */ 82 SPCODE_VERSIONS = 21, /* Report FW versions */ 83 SPCODE_READ_SFF_EEPROM = 22, /* Read module EEPROM */ 84 SPCODE_READ_MEDIA = 23, /* Get the supported/advertised media for a port */ 85 SPCODE_DEV_ACTIVATE = 29, /* Activate hardware for multiple pfs case */ 86 }; 87 88 static const struct { 89 uint32_t code; 90 const char *msg; 91 } nsp_errors[] = { 92 { 6010, "could not map to phy for port" }, 93 { 6011, "not an allowed rate/lanes for port" }, 94 { 6012, "not an allowed rate/lanes for port" }, 95 { 6013, "high/low error, change other port first" }, 96 { 6014, "config not found in flash" }, 97 }; 98 99 struct nfp_nsp { 100 struct nfp_cpp *cpp; 101 struct nfp_resource *res; 102 struct { 103 uint16_t major; 104 uint16_t minor; 105 } ver; 106 107 /** Eth table config state */ 108 bool modified; 109 uint32_t idx; 110 void *entries; 111 }; 112 113 /* NFP command argument structure */ 114 struct nfp_nsp_command_arg { 115 uint16_t code; /**< NFP SP Command Code */ 116 bool dma; /**< @buf points to a host buffer, not NSP buffer */ 117 bool error_quiet; /**< Don't print command error/warning */ 118 uint32_t timeout_sec; /**< Timeout value to wait for completion in seconds */ 119 uint32_t option; /**< NSP Command Argument */ 120 uint64_t buf; /**< NSP Buffer Address */ 121 /** Callback for interpreting option if error occurred */ 122 void (*error_cb)(struct nfp_nsp *state, uint32_t ret_val); 123 }; 124 125 /* NFP command with buffer argument structure */ 126 struct nfp_nsp_command_buf_arg { 127 struct nfp_nsp_command_arg arg; /**< NFP command argument structure */ 128 const void *in_buf; /**< Buffer with data for input */ 129 void *out_buf; /**< Buffer for output data */ 130 uint32_t in_size; /**< Size of @in_buf */ 131 uint32_t out_size; /**< Size of @out_buf */ 132 }; 133 134 struct nfp_cpp * 135 nfp_nsp_cpp(struct nfp_nsp *state) 136 { 137 return state->cpp; 138 } 139 140 bool 141 nfp_nsp_config_modified(struct nfp_nsp *state) 142 { 143 return state->modified; 144 } 145 146 void 147 nfp_nsp_config_set_modified(struct nfp_nsp *state, 148 bool modified) 149 { 150 state->modified = modified; 151 } 152 153 void * 154 nfp_nsp_config_entries(struct nfp_nsp *state) 155 { 156 return state->entries; 157 } 158 159 uint32_t 160 nfp_nsp_config_idx(struct nfp_nsp *state) 161 { 162 return state->idx; 163 } 164 165 void 166 nfp_nsp_config_set_state(struct nfp_nsp *state, 167 void *entries, 168 uint32_t idx) 169 { 170 state->entries = entries; 171 state->idx = idx; 172 } 173 174 void 175 nfp_nsp_config_clear_state(struct nfp_nsp *state) 176 { 177 state->entries = NULL; 178 state->idx = 0; 179 } 180 181 static void 182 nfp_nsp_print_extended_error(uint32_t ret_val) 183 { 184 uint32_t i; 185 186 if (ret_val == 0) 187 return; 188 189 for (i = 0; i < RTE_DIM(nsp_errors); i++) 190 if (ret_val == nsp_errors[i].code) 191 PMD_DRV_LOG(ERR, "Err msg: %s.", nsp_errors[i].msg); 192 } 193 194 static int 195 nfp_nsp_check(struct nfp_nsp *state) 196 { 197 int err; 198 uint64_t reg; 199 uint32_t nsp_cpp; 200 uint64_t nsp_status; 201 struct nfp_cpp *cpp = state->cpp; 202 203 nsp_cpp = nfp_resource_cpp_id(state->res); 204 nsp_status = nfp_resource_address(state->res) + NSP_STATUS; 205 206 err = nfp_cpp_readq(cpp, nsp_cpp, nsp_status, ®); 207 if (err < 0) { 208 PMD_DRV_LOG(ERR, "NSP - CPP readq failed %d.", err); 209 return err; 210 } 211 212 if (FIELD_GET(NSP_STATUS_MAGIC, reg) != NSP_MAGIC) { 213 PMD_DRV_LOG(ERR, "Can not detect NFP Service Processor."); 214 return -ENODEV; 215 } 216 217 state->ver.major = FIELD_GET(NSP_STATUS_MAJOR, reg); 218 state->ver.minor = FIELD_GET(NSP_STATUS_MINOR, reg); 219 220 if (state->ver.major > NSP_MAJOR || state->ver.minor < NSP_MINOR) { 221 PMD_DRV_LOG(ERR, "Unsupported ABI %hu.%hu.", state->ver.major, 222 state->ver.minor); 223 return -EINVAL; 224 } 225 226 if ((reg & NSP_STATUS_BUSY) != 0) { 227 PMD_DRV_LOG(DEBUG, "Service processor busy!"); 228 return -EBUSY; 229 } 230 231 return 0; 232 } 233 234 /** 235 * Prepare for communication and lock the NSP resource. 236 * 237 * @param cpp 238 * NFP CPP Handle 239 */ 240 struct nfp_nsp * 241 nfp_nsp_open(struct nfp_cpp *cpp) 242 { 243 int err; 244 struct nfp_nsp *state; 245 struct nfp_resource *res; 246 247 res = nfp_resource_acquire(cpp, NFP_RESOURCE_NSP); 248 if (res == NULL) { 249 PMD_DRV_LOG(ERR, "NSP - resource acquire failed."); 250 return NULL; 251 } 252 253 state = malloc(sizeof(*state)); 254 if (state == NULL) { 255 PMD_DRV_LOG(ERR, "NSP - failed to malloc name %s", NFP_RESOURCE_NSP); 256 nfp_resource_release(res); 257 return NULL; 258 } 259 memset(state, 0, sizeof(*state)); 260 state->cpp = cpp; 261 state->res = res; 262 263 err = nfp_nsp_check(state); 264 if (err != 0) { 265 PMD_DRV_LOG(DEBUG, "NSP - check failed."); 266 nfp_nsp_close(state); 267 return NULL; 268 } 269 270 return state; 271 } 272 273 /** 274 * Clean up and unlock the NSP resource. 275 * 276 * @param state 277 * NFP SP state 278 */ 279 void 280 nfp_nsp_close(struct nfp_nsp *state) 281 { 282 nfp_resource_release(state->res); 283 free(state); 284 } 285 286 uint16_t 287 nfp_nsp_get_abi_ver_major(struct nfp_nsp *state) 288 { 289 return state->ver.major; 290 } 291 292 uint16_t 293 nfp_nsp_get_abi_ver_minor(struct nfp_nsp *state) 294 { 295 return state->ver.minor; 296 } 297 298 static int 299 nfp_nsp_wait_reg(struct nfp_cpp *cpp, 300 uint64_t *reg, 301 uint32_t nsp_cpp, 302 uint64_t addr, 303 uint64_t mask, 304 uint64_t val) 305 { 306 int err; 307 uint32_t count = 0; 308 struct timespec wait; 309 310 wait.tv_sec = 0; 311 wait.tv_nsec = 25000000; /* 25ms */ 312 313 for (;;) { 314 err = nfp_cpp_readq(cpp, nsp_cpp, addr, reg); 315 if (err < 0) { 316 PMD_DRV_LOG(ERR, "NSP - CPP readq failed."); 317 return err; 318 } 319 320 if ((*reg & mask) == val) 321 return 0; 322 323 nanosleep(&wait, 0); 324 if (count++ > 1000) /* 25ms * 1000 = 25s */ 325 return -ETIMEDOUT; 326 } 327 } 328 329 /** 330 * Execute a command on the NFP Service Processor 331 * 332 * @param state 333 * NFP SP state 334 * @param arg 335 * NFP command argument structure 336 * 337 * @return 338 * - 0 for success with no result 339 * - Positive value for NSP completion with a result code 340 * - -EAGAIN if the NSP is not yet present 341 * - -ENODEV if the NSP is not a supported model 342 * - -EBUSY if the NSP is stuck 343 * - -EINTR if interrupted while waiting for completion 344 * - -ETIMEDOUT if the NSP took longer than @timeout_sec seconds to complete 345 */ 346 static int 347 nfp_nsp_command_real(struct nfp_nsp *state, 348 const struct nfp_nsp_command_arg *arg) 349 { 350 int err; 351 uint64_t reg; 352 uint32_t nsp_cpp; 353 uint64_t ret_val; 354 uint64_t nsp_base; 355 uint64_t nsp_buffer; 356 uint64_t nsp_status; 357 uint64_t nsp_command; 358 struct nfp_cpp *cpp = state->cpp; 359 360 nsp_cpp = nfp_resource_cpp_id(state->res); 361 nsp_base = nfp_resource_address(state->res); 362 nsp_status = nsp_base + NSP_STATUS; 363 nsp_command = nsp_base + NSP_COMMAND; 364 nsp_buffer = nsp_base + NSP_BUFFER; 365 366 err = nfp_nsp_check(state); 367 if (err != 0) { 368 PMD_DRV_LOG(ERR, "Check NSP command failed."); 369 return err; 370 } 371 372 err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_buffer, arg->buf); 373 if (err < 0) { 374 PMD_DRV_LOG(ERR, "CPP write buffer failed. err %d", err); 375 return err; 376 } 377 378 err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_command, 379 FIELD_PREP(NSP_COMMAND_OPTION, arg->option) | 380 FIELD_PREP(NSP_COMMAND_VER_MAJOR, state->ver.major) | 381 FIELD_PREP(NSP_COMMAND_CODE, arg->code) | 382 FIELD_PREP(NSP_COMMAND_DMA_BUF, arg->dma) | 383 FIELD_PREP(NSP_COMMAND_START, 1)); 384 if (err < 0) { 385 PMD_DRV_LOG(ERR, "CPP write command failed. err %d", err); 386 return err; 387 } 388 389 /* Wait for NSP_COMMAND_START to go to 0 */ 390 err = nfp_nsp_wait_reg(cpp, ®, nsp_cpp, nsp_command, 391 NSP_COMMAND_START, 0); 392 if (err != 0) { 393 PMD_DRV_LOG(ERR, "Error %d waiting for code %#04x to start.", 394 err, arg->code); 395 return err; 396 } 397 398 /* Wait for NSP_STATUS_BUSY to go to 0 */ 399 err = nfp_nsp_wait_reg(cpp, ®, nsp_cpp, nsp_status, 400 NSP_STATUS_BUSY, 0); 401 if (err != 0) { 402 PMD_DRV_LOG(ERR, "Error %d waiting for code %#04x to complete.", 403 err, arg->code); 404 return err; 405 } 406 407 err = nfp_cpp_readq(cpp, nsp_cpp, nsp_command, &ret_val); 408 if (err < 0) { 409 PMD_DRV_LOG(ERR, "CPP read return value failed. err %d", err); 410 return err; 411 } 412 413 ret_val = FIELD_GET(NSP_COMMAND_OPTION, ret_val); 414 415 err = FIELD_GET(NSP_STATUS_RESULT, reg); 416 if (err != 0) { 417 if (!arg->error_quiet) 418 PMD_DRV_LOG(ERR, "Result (error) code set: %d (%d) command: %d.", 419 -err, (int)ret_val, arg->code); 420 421 if (arg->error_cb != 0) 422 arg->error_cb(state, ret_val); 423 else 424 nfp_nsp_print_extended_error(ret_val); 425 426 return -err; 427 } 428 429 return ret_val; 430 } 431 432 static int 433 nfp_nsp_command(struct nfp_nsp *state, 434 uint16_t code) 435 { 436 const struct nfp_nsp_command_arg arg = { 437 .code = code, 438 }; 439 440 return nfp_nsp_command_real(state, &arg); 441 } 442 443 static int 444 nfp_nsp_command_buf_def(struct nfp_nsp *nsp, 445 struct nfp_nsp_command_buf_arg *arg) 446 { 447 int err; 448 int ret; 449 uint64_t reg; 450 uint32_t cpp_id; 451 uint64_t cpp_buf; 452 struct nfp_cpp *cpp = nsp->cpp; 453 454 err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res), 455 nfp_resource_address(nsp->res) + NSP_DFLT_BUFFER, 456 ®); 457 if (err < 0) 458 return err; 459 460 cpp_id = FIELD_GET(NSP_DFLT_BUFFER_CPP, reg) << 8; 461 cpp_buf = FIELD_GET(NSP_DFLT_BUFFER_ADDRESS, reg); 462 463 if (arg->in_buf != NULL && arg->in_size > 0) { 464 err = nfp_cpp_write(cpp, cpp_id, cpp_buf, 465 arg->in_buf, arg->in_size); 466 if (err < 0) 467 return err; 468 } 469 470 /* Zero out remaining part of the buffer */ 471 if (arg->out_buf != NULL && arg->out_size > arg->in_size) { 472 err = nfp_cpp_write(cpp, cpp_id, cpp_buf + arg->in_size, 473 arg->out_buf, arg->out_size - arg->in_size); 474 if (err < 0) 475 return err; 476 } 477 478 if (!FIELD_FIT(NSP_BUFFER_CPP, cpp_id >> 8) || 479 !FIELD_FIT(NSP_BUFFER_ADDRESS, cpp_buf)) { 480 PMD_DRV_LOG(ERR, "Buffer out of reach %#08x %#016lx.", 481 cpp_id, cpp_buf); 482 return -EINVAL; 483 } 484 485 arg->arg.buf = FIELD_PREP(NSP_BUFFER_CPP, cpp_id >> 8) | 486 FIELD_PREP(NSP_BUFFER_ADDRESS, cpp_buf); 487 ret = nfp_nsp_command_real(nsp, &arg->arg); 488 if (ret < 0) { 489 if (!arg->arg.error_quiet) 490 PMD_DRV_LOG(ERR, "NSP command failed."); 491 492 return ret; 493 } 494 495 if (arg->out_buf != NULL && arg->out_size > 0) { 496 err = nfp_cpp_read(cpp, cpp_id, cpp_buf, 497 arg->out_buf, arg->out_size); 498 if (err < 0) 499 return err; 500 } 501 502 return ret; 503 } 504 505 #define SZ_1M 0x00100000 506 #define SZ_4K 0x00001000 507 508 static int 509 nfp_nsp_command_buf(struct nfp_nsp *nsp, 510 struct nfp_nsp_command_buf_arg *arg) 511 { 512 int err; 513 size_t size; 514 uint64_t reg; 515 size_t max_size; 516 struct nfp_cpp *cpp = nsp->cpp; 517 518 if (nsp->ver.minor < 13) { 519 PMD_DRV_LOG(ERR, "NSP: Code %#04x with buffer not supported ABI %hu.%hu).", 520 arg->arg.code, nsp->ver.major, nsp->ver.minor); 521 return -EOPNOTSUPP; 522 } 523 524 err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res), 525 nfp_resource_address(nsp->res) + NSP_DFLT_BUFFER_CONFIG, 526 ®); 527 if (err < 0) 528 return err; 529 530 max_size = RTE_MAX(arg->in_size, arg->out_size); 531 size = FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M + 532 FIELD_GET(NSP_DFLT_BUFFER_SIZE_4KB, reg) * SZ_4K; 533 if (size < max_size) { 534 PMD_DRV_LOG(ERR, "NSP: default buffer too small for command %#04x (%zu < %zu).", 535 arg->arg.code, size, max_size); 536 return -EINVAL; 537 } 538 539 return nfp_nsp_command_buf_def(nsp, arg); 540 } 541 542 int 543 nfp_nsp_wait(struct nfp_nsp *state) 544 { 545 int err; 546 int count = 0; 547 struct timespec wait; 548 549 wait.tv_sec = 0; 550 wait.tv_nsec = 25000000; /* 25ms */ 551 552 for (;;) { 553 err = nfp_nsp_command(state, SPCODE_NOOP); 554 if (err != -EAGAIN) 555 break; 556 557 nanosleep(&wait, 0); 558 559 if (count++ > 1000) { /* 25ms * 1000 = 25s */ 560 err = -ETIMEDOUT; 561 break; 562 } 563 } 564 565 if (err != 0) 566 PMD_DRV_LOG(ERR, "NSP failed to respond %d.", err); 567 568 return err; 569 } 570 571 int 572 nfp_nsp_device_soft_reset(struct nfp_nsp *state) 573 { 574 return nfp_nsp_command(state, SPCODE_SOFT_RESET); 575 } 576 577 int 578 nfp_nsp_mac_reinit(struct nfp_nsp *state) 579 { 580 return nfp_nsp_command(state, SPCODE_MAC_INIT); 581 } 582 583 static void 584 nfp_nsp_load_fw_extended_msg(struct nfp_nsp *state, 585 uint32_t ret_val) 586 { 587 uint32_t minor; 588 uint32_t major; 589 static const char * const major_msg[] = { 590 /* 0 */ "Firmware from driver loaded", 591 /* 1 */ "Firmware from flash loaded", 592 /* 2 */ "Firmware loading failure", 593 }; 594 static const char * const minor_msg[] = { 595 /* 0 */ "", 596 /* 1 */ "no named partition on flash", 597 /* 2 */ "error reading from flash", 598 /* 3 */ "can not deflate", 599 /* 4 */ "not a trusted file", 600 /* 5 */ "can not parse FW file", 601 /* 6 */ "MIP not found in FW file", 602 /* 7 */ "null firmware name in MIP", 603 /* 8 */ "FW version none", 604 /* 9 */ "FW build number none", 605 /* 10 */ "no FW selection policy HWInfo key found", 606 /* 11 */ "static FW selection policy", 607 /* 12 */ "FW version has precedence", 608 /* 13 */ "different FW application load requested", 609 /* 14 */ "development build", 610 }; 611 612 major = FIELD_GET(NFP_FW_LOAD_RET_MAJOR, ret_val); 613 minor = FIELD_GET(NFP_FW_LOAD_RET_MINOR, ret_val); 614 615 if (!nfp_nsp_has_stored_fw_load(state)) 616 return; 617 618 if (major >= RTE_DIM(major_msg)) 619 PMD_DRV_LOG(INFO, "FW loading status: %x.", ret_val); 620 else if (minor >= RTE_DIM(minor_msg)) 621 PMD_DRV_LOG(INFO, "%s, reason code: %d.", major_msg[major], minor); 622 else 623 PMD_DRV_LOG(INFO, "%s%c %s", major_msg[major], 624 minor != 0 ? ',' : '.', minor_msg[minor]); 625 } 626 627 int 628 nfp_nsp_load_fw(struct nfp_nsp *state, 629 void *buf, 630 size_t size) 631 { 632 int ret; 633 struct nfp_nsp_command_buf_arg load_fw = { 634 { 635 .code = SPCODE_FW_LOAD, 636 .option = size, 637 .error_cb = nfp_nsp_load_fw_extended_msg, 638 }, 639 .in_buf = buf, 640 .in_size = size, 641 }; 642 643 ret = nfp_nsp_command_buf(state, &load_fw); 644 if (ret < 0) 645 return ret; 646 647 nfp_nsp_load_fw_extended_msg(state, ret); 648 649 return 0; 650 } 651 652 bool 653 nfp_nsp_fw_loaded(struct nfp_nsp *state) 654 { 655 return nfp_nsp_command(state, SPCODE_FW_LOADED) > 0; 656 } 657 658 int 659 nfp_nsp_read_eth_table(struct nfp_nsp *state, 660 void *buf, 661 size_t size) 662 { 663 struct nfp_nsp_command_buf_arg eth_rescan = { 664 { 665 .code = SPCODE_ETH_RESCAN, 666 .option = size, 667 }, 668 .out_buf = buf, 669 .out_size = size, 670 }; 671 672 return nfp_nsp_command_buf(state, ð_rescan); 673 } 674 675 int 676 nfp_nsp_write_eth_table(struct nfp_nsp *state, 677 const void *buf, 678 size_t size) 679 { 680 struct nfp_nsp_command_buf_arg eth_ctrl = { 681 { 682 .code = SPCODE_ETH_CONTROL, 683 .option = size, 684 }, 685 .in_buf = buf, 686 .in_size = size, 687 }; 688 689 return nfp_nsp_command_buf(state, ð_ctrl); 690 } 691 692 int 693 nfp_nsp_read_identify(struct nfp_nsp *state, 694 void *buf, 695 size_t size) 696 { 697 struct nfp_nsp_command_buf_arg identify = { 698 { 699 .code = SPCODE_NSP_IDENTIFY, 700 .option = size, 701 }, 702 .out_buf = buf, 703 .out_size = size, 704 }; 705 706 return nfp_nsp_command_buf(state, &identify); 707 } 708 709 int 710 nfp_nsp_read_sensors(struct nfp_nsp *state, 711 uint32_t sensor_mask, 712 void *buf, 713 size_t size) 714 { 715 struct nfp_nsp_command_buf_arg sensors = { 716 { 717 .code = SPCODE_NSP_SENSORS, 718 .option = sensor_mask, 719 }, 720 .out_buf = buf, 721 .out_size = size, 722 }; 723 724 return nfp_nsp_command_buf(state, &sensors); 725 } 726 727 int 728 nfp_nsp_hwinfo_set(struct nfp_nsp *state, 729 const void *buf, 730 size_t size) 731 { 732 struct nfp_nsp_command_buf_arg hwinfo_set = { 733 { 734 .code = SPCODE_HWINFO_SET, 735 .option = size, 736 }, 737 .in_buf = buf, 738 .in_size = size, 739 }; 740 741 return nfp_nsp_command_buf(state, &hwinfo_set); 742 } 743 744 int 745 nfp_nsp_device_activate(struct nfp_nsp *state) 746 { 747 if (nfp_nsp_get_abi_ver_minor(state) < 38) 748 return -EOPNOTSUPP; 749 750 return nfp_nsp_command(state, SPCODE_DEV_ACTIVATE); 751 } 752 753 int 754 nfp_nsp_read_media(struct nfp_nsp *state, 755 void *buf, 756 size_t size) 757 { 758 struct nfp_nsp_command_buf_arg media = { 759 { 760 .code = SPCODE_READ_MEDIA, 761 .option = size, 762 }, 763 .out_buf = buf, 764 .out_size = size, 765 }; 766 767 return nfp_nsp_command_buf(state, &media); 768 } 769 770 int 771 nfp_nsp_load_stored_fw(struct nfp_nsp *state) 772 { 773 int ret; 774 struct nfp_nsp_command_buf_arg fw_stored = { 775 { 776 .code = SPCODE_FW_STORED, 777 .error_cb = nfp_nsp_load_fw_extended_msg, 778 }, 779 }; 780 781 ret = nfp_nsp_command_buf(state, &fw_stored); 782 if (ret < 0) 783 return ret; 784 785 nfp_nsp_load_fw_extended_msg(state, ret); 786 787 return 0; 788 } 789 790 static int 791 nfp_nsp_hwinfo_lookup_real(struct nfp_nsp *state, 792 void *buf, 793 size_t size, 794 bool optional) 795 { 796 struct nfp_nsp_command_buf_arg hwinfo_lookup = { 797 { 798 .code = SPCODE_HWINFO_LOOKUP, 799 .option = size, 800 .error_quiet = optional, 801 }, 802 .in_buf = buf, 803 .in_size = size, 804 .out_buf = buf, 805 .out_size = size, 806 }; 807 808 return nfp_nsp_command_buf(state, &hwinfo_lookup); 809 } 810 811 static int 812 nfp_nsp_read_module_eeprom_real(struct nfp_nsp *state, 813 void *buf, 814 uint32_t size) 815 { 816 struct nfp_nsp_command_buf_arg module_eeprom = { 817 { 818 .code = SPCODE_READ_SFF_EEPROM, 819 .option = size, 820 }, 821 .in_buf = buf, 822 .in_size = size, 823 .out_buf = buf, 824 .out_size = size, 825 }; 826 827 return nfp_nsp_command_buf(state, &module_eeprom); 828 } 829 830 int 831 nfp_nsp_read_module_eeprom(struct nfp_nsp *state, 832 int eth_index, 833 uint32_t offset, 834 void *data, 835 uint32_t len, 836 uint32_t *read_len) 837 { 838 int ret; 839 int bufsz; 840 struct __rte_packed_begin eeprom_buf { 841 uint8_t metalen; 842 rte_le16_t length; 843 rte_le16_t offset; 844 rte_le16_t readlen; 845 uint8_t eth_index; 846 uint8_t data[]; 847 } __rte_packed_end * buf; 848 849 /* Buffer must be large enough and rounded to the next block size. */ 850 bufsz = sizeof(*(buf)) + sizeof((buf)->data[0]) * 851 (RTE_ALIGN_CEIL(len, NSP_SFF_EEPROM_BLOCK_LEN)); 852 buf = calloc(1, bufsz); 853 if (buf == NULL) 854 return -ENOMEM; 855 856 buf->metalen = offsetof(struct eeprom_buf, data) / NSP_SFF_EEPROM_BLOCK_LEN; 857 buf->length = rte_cpu_to_le_16(len); 858 buf->offset = rte_cpu_to_le_16(offset); 859 buf->eth_index = eth_index; 860 861 ret = nfp_nsp_read_module_eeprom_real(state, buf, bufsz); 862 if (ret != 0) 863 goto free_exit; 864 865 if (rte_le_to_cpu_16(buf->readlen) < len) { 866 ret = -EIO; 867 goto free_exit; 868 } 869 870 if (len != 0) 871 memcpy(data, buf->data, len); 872 873 *read_len = len; 874 875 free_exit: 876 free(buf); 877 return ret; 878 } 879 880 int 881 nfp_nsp_hwinfo_lookup(struct nfp_nsp *state, 882 void *buf, 883 uint32_t size) 884 { 885 int ret; 886 uint32_t size_tmp; 887 888 if (!nfp_nsp_has_hwinfo_lookup(state)) { 889 PMD_DRV_LOG(ERR, "NSP HWinfo lookup not supported. Please update flash."); 890 return -EOPNOTSUPP; 891 } 892 893 size_tmp = RTE_MIN(size, NFP_HWINFO_LOOKUP_SIZE); 894 895 ret = nfp_nsp_hwinfo_lookup_real(state, buf, size, false); 896 if (ret != 0) 897 return ret; 898 899 if (strnlen(buf, size_tmp) == size_tmp) { 900 PMD_DRV_LOG(ERR, "NSP HWinfo value not NULL terminated."); 901 return -EINVAL; 902 } 903 904 return 0; 905 } 906 907 int 908 nfp_nsp_hwinfo_lookup_optional(struct nfp_nsp *state, 909 void *buf, 910 size_t size, 911 const char *default_val) 912 { 913 int ret; 914 size_t min_size; 915 916 if (strnlen(default_val, size) == size) { 917 PMD_DRV_LOG(ERR, "NSP HWinfo default value not NULL terminated."); 918 return -EINVAL; 919 } 920 921 if (!nfp_nsp_has_hwinfo_lookup(state)) 922 goto default_return; 923 924 min_size = RTE_MIN(size, NFP_HWINFO_LOOKUP_SIZE); 925 ret = nfp_nsp_hwinfo_lookup_real(state, buf, min_size, true); 926 if (ret != 0) { 927 if (ret == -ENOENT) 928 goto default_return; 929 930 PMD_DRV_LOG(ERR, "NSP HWinfo lookup failed: %d.", ret); 931 return ret; 932 } 933 934 if (strnlen(buf, min_size) == min_size) { 935 PMD_DRV_LOG(ERR, "NSP HWinfo value not NULL terminated."); 936 return -EINVAL; 937 } 938 939 return 0; 940 941 default_return: 942 strlcpy(buf, default_val, size); 943 return 0; 944 } 945