nfp_nsp.c (26756B)
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2/* Copyright (C) 2015-2018 Netronome Systems, Inc. */ 3 4/* 5 * nfp_nsp.c 6 * Author: Jakub Kicinski <jakub.kicinski@netronome.com> 7 * Jason McMullan <jason.mcmullan@netronome.com> 8 */ 9 10#include <asm/unaligned.h> 11#include <linux/bitfield.h> 12#include <linux/delay.h> 13#include <linux/firmware.h> 14#include <linux/kernel.h> 15#include <linux/kthread.h> 16#include <linux/overflow.h> 17#include <linux/sizes.h> 18#include <linux/slab.h> 19 20#define NFP_SUBSYS "nfp_nsp" 21 22#include "nfp.h" 23#include "nfp_cpp.h" 24#include "nfp_nsp.h" 25 26#define NFP_NSP_TIMEOUT_DEFAULT 30 27#define NFP_NSP_TIMEOUT_BOOT 30 28 29/* Offsets relative to the CSR base */ 30#define NSP_STATUS 0x00 31#define NSP_STATUS_MAGIC GENMASK_ULL(63, 48) 32#define NSP_STATUS_MAJOR GENMASK_ULL(47, 44) 33#define NSP_STATUS_MINOR GENMASK_ULL(43, 32) 34#define NSP_STATUS_CODE GENMASK_ULL(31, 16) 35#define NSP_STATUS_RESULT GENMASK_ULL(15, 8) 36#define NSP_STATUS_BUSY BIT_ULL(0) 37 38#define NSP_COMMAND 0x08 39#define NSP_COMMAND_OPTION GENMASK_ULL(63, 32) 40#define NSP_COMMAND_CODE GENMASK_ULL(31, 16) 41#define NSP_COMMAND_DMA_BUF BIT_ULL(1) 42#define NSP_COMMAND_START BIT_ULL(0) 43 44/* CPP address to retrieve the data from */ 45#define NSP_BUFFER 0x10 46#define NSP_BUFFER_CPP GENMASK_ULL(63, 40) 47#define NSP_BUFFER_ADDRESS GENMASK_ULL(39, 0) 48 49#define NSP_DFLT_BUFFER 0x18 50#define NSP_DFLT_BUFFER_CPP GENMASK_ULL(63, 40) 51#define NSP_DFLT_BUFFER_ADDRESS GENMASK_ULL(39, 0) 52 53#define NSP_DFLT_BUFFER_CONFIG 0x20 54#define NSP_DFLT_BUFFER_DMA_CHUNK_ORDER GENMASK_ULL(63, 58) 55#define NSP_DFLT_BUFFER_SIZE_4KB GENMASK_ULL(15, 8) 56#define NSP_DFLT_BUFFER_SIZE_MB GENMASK_ULL(7, 0) 57 58#define NFP_CAP_CMD_DMA_SG 0x28 59 60#define NSP_MAGIC 0xab10 61#define NSP_MAJOR 0 62#define NSP_MINOR 8 63 64#define NSP_CODE_MAJOR GENMASK(15, 12) 65#define NSP_CODE_MINOR GENMASK(11, 0) 66 67#define NFP_FW_LOAD_RET_MAJOR GENMASK(15, 8) 68#define NFP_FW_LOAD_RET_MINOR GENMASK(23, 16) 69 70#define NFP_HWINFO_LOOKUP_SIZE GENMASK(11, 0) 71 72#define NFP_VERSIONS_SIZE GENMASK(11, 0) 73#define NFP_VERSIONS_CNT_OFF 0 74#define NFP_VERSIONS_BSP_OFF 2 75#define NFP_VERSIONS_CPLD_OFF 6 76#define NFP_VERSIONS_APP_OFF 10 77#define NFP_VERSIONS_BUNDLE_OFF 14 78#define NFP_VERSIONS_UNDI_OFF 18 79#define NFP_VERSIONS_NCSI_OFF 22 80#define NFP_VERSIONS_CFGR_OFF 26 81 82#define NSP_SFF_EEPROM_BLOCK_LEN 8 83 84enum nfp_nsp_cmd { 85 SPCODE_NOOP = 0, /* No operation */ 86 SPCODE_SOFT_RESET = 1, /* Soft reset the NFP */ 87 SPCODE_FW_DEFAULT = 2, /* Load default (UNDI) FW */ 88 SPCODE_PHY_INIT = 3, /* Initialize the PHY */ 89 SPCODE_MAC_INIT = 4, /* Initialize the MAC */ 90 SPCODE_PHY_RXADAPT = 5, /* Re-run PHY RX Adaptation */ 91 SPCODE_FW_LOAD = 6, /* Load fw from buffer, len in option */ 92 SPCODE_ETH_RESCAN = 7, /* Rescan ETHs, write ETH_TABLE to buf */ 93 SPCODE_ETH_CONTROL = 8, /* Update media config from buffer */ 94 SPCODE_NSP_WRITE_FLASH = 11, /* Load and flash image from buffer */ 95 SPCODE_NSP_SENSORS = 12, /* Read NSP sensor(s) */ 96 SPCODE_NSP_IDENTIFY = 13, /* Read NSP version */ 97 SPCODE_FW_STORED = 16, /* If no FW loaded, load flash app FW */ 98 SPCODE_HWINFO_LOOKUP = 17, /* Lookup HWinfo with overwrites etc. */ 99 SPCODE_HWINFO_SET = 18, /* Set HWinfo entry */ 100 SPCODE_FW_LOADED = 19, /* Is application firmware loaded */ 101 SPCODE_VERSIONS = 21, /* Report FW versions */ 102 SPCODE_READ_SFF_EEPROM = 22, /* Read module EEPROM */ 103}; 104 105struct nfp_nsp_dma_buf { 106 __le32 chunk_cnt; 107 __le32 reserved[3]; 108 struct { 109 __le32 size; 110 __le32 reserved; 111 __le64 addr; 112 } descs[]; 113}; 114 115static const struct { 116 int code; 117 const char *msg; 118} nsp_errors[] = { 119 { 6010, "could not map to phy for port" }, 120 { 6011, "not an allowed rate/lanes for port" }, 121 { 6012, "not an allowed rate/lanes for port" }, 122 { 6013, "high/low error, change other port first" }, 123 { 6014, "config not found in flash" }, 124}; 125 126struct nfp_nsp { 127 struct nfp_cpp *cpp; 128 struct nfp_resource *res; 129 struct { 130 u16 major; 131 u16 minor; 132 } ver; 133 134 /* Eth table config state */ 135 bool modified; 136 unsigned int idx; 137 void *entries; 138}; 139 140/** 141 * struct nfp_nsp_command_arg - NFP command argument structure 142 * @code: NFP SP Command Code 143 * @dma: @buf points to a host buffer, not NSP buffer 144 * @timeout_sec:Timeout value to wait for completion in seconds 145 * @option: NFP SP Command Argument 146 * @buf: NFP SP Buffer Address 147 * @error_cb: Callback for interpreting option if error occurred 148 * @error_quiet:Don't print command error/warning. Protocol errors are still 149 * logged. 150 */ 151struct nfp_nsp_command_arg { 152 u16 code; 153 bool dma; 154 unsigned int timeout_sec; 155 u32 option; 156 u64 buf; 157 void (*error_cb)(struct nfp_nsp *state, u32 ret_val); 158 bool error_quiet; 159}; 160 161/** 162 * struct nfp_nsp_command_buf_arg - NFP command with buffer argument structure 163 * @arg: NFP command argument structure 164 * @in_buf: Buffer with data for input 165 * @in_size: Size of @in_buf 166 * @out_buf: Buffer for output data 167 * @out_size: Size of @out_buf 168 */ 169struct nfp_nsp_command_buf_arg { 170 struct nfp_nsp_command_arg arg; 171 const void *in_buf; 172 unsigned int in_size; 173 void *out_buf; 174 unsigned int out_size; 175}; 176 177struct nfp_cpp *nfp_nsp_cpp(struct nfp_nsp *state) 178{ 179 return state->cpp; 180} 181 182bool nfp_nsp_config_modified(struct nfp_nsp *state) 183{ 184 return state->modified; 185} 186 187void nfp_nsp_config_set_modified(struct nfp_nsp *state, bool modified) 188{ 189 state->modified = modified; 190} 191 192void *nfp_nsp_config_entries(struct nfp_nsp *state) 193{ 194 return state->entries; 195} 196 197unsigned int nfp_nsp_config_idx(struct nfp_nsp *state) 198{ 199 return state->idx; 200} 201 202void 203nfp_nsp_config_set_state(struct nfp_nsp *state, void *entries, unsigned int idx) 204{ 205 state->entries = entries; 206 state->idx = idx; 207} 208 209void nfp_nsp_config_clear_state(struct nfp_nsp *state) 210{ 211 state->entries = NULL; 212 state->idx = 0; 213} 214 215static void nfp_nsp_print_extended_error(struct nfp_nsp *state, u32 ret_val) 216{ 217 int i; 218 219 if (!ret_val) 220 return; 221 222 for (i = 0; i < ARRAY_SIZE(nsp_errors); i++) 223 if (ret_val == nsp_errors[i].code) 224 nfp_err(state->cpp, "err msg: %s\n", nsp_errors[i].msg); 225} 226 227static int nfp_nsp_check(struct nfp_nsp *state) 228{ 229 struct nfp_cpp *cpp = state->cpp; 230 u64 nsp_status, reg; 231 u32 nsp_cpp; 232 int err; 233 234 nsp_cpp = nfp_resource_cpp_id(state->res); 235 nsp_status = nfp_resource_address(state->res) + NSP_STATUS; 236 237 err = nfp_cpp_readq(cpp, nsp_cpp, nsp_status, ®); 238 if (err < 0) 239 return err; 240 241 if (FIELD_GET(NSP_STATUS_MAGIC, reg) != NSP_MAGIC) { 242 nfp_err(cpp, "Cannot detect NFP Service Processor\n"); 243 return -ENODEV; 244 } 245 246 state->ver.major = FIELD_GET(NSP_STATUS_MAJOR, reg); 247 state->ver.minor = FIELD_GET(NSP_STATUS_MINOR, reg); 248 249 if (state->ver.major != NSP_MAJOR) { 250 nfp_err(cpp, "Unsupported ABI %hu.%hu\n", 251 state->ver.major, state->ver.minor); 252 return -EINVAL; 253 } 254 if (state->ver.minor < NSP_MINOR) { 255 nfp_err(cpp, "ABI too old to support NIC operation (%u.%hu < %u.%u), please update the management FW on the flash\n", 256 NSP_MAJOR, state->ver.minor, NSP_MAJOR, NSP_MINOR); 257 return -EINVAL; 258 } 259 260 if (reg & NSP_STATUS_BUSY) { 261 nfp_err(cpp, "Service processor busy!\n"); 262 return -EBUSY; 263 } 264 265 return 0; 266} 267 268/** 269 * nfp_nsp_open() - Prepare for communication and lock the NSP resource. 270 * @cpp: NFP CPP Handle 271 */ 272struct nfp_nsp *nfp_nsp_open(struct nfp_cpp *cpp) 273{ 274 struct nfp_resource *res; 275 struct nfp_nsp *state; 276 int err; 277 278 res = nfp_resource_acquire(cpp, NFP_RESOURCE_NSP); 279 if (IS_ERR(res)) 280 return (void *)res; 281 282 state = kzalloc(sizeof(*state), GFP_KERNEL); 283 if (!state) { 284 nfp_resource_release(res); 285 return ERR_PTR(-ENOMEM); 286 } 287 state->cpp = cpp; 288 state->res = res; 289 290 err = nfp_nsp_check(state); 291 if (err) { 292 nfp_nsp_close(state); 293 return ERR_PTR(err); 294 } 295 296 return state; 297} 298 299/** 300 * nfp_nsp_close() - Clean up and unlock the NSP resource. 301 * @state: NFP SP state 302 */ 303void nfp_nsp_close(struct nfp_nsp *state) 304{ 305 nfp_resource_release(state->res); 306 kfree(state); 307} 308 309u16 nfp_nsp_get_abi_ver_major(struct nfp_nsp *state) 310{ 311 return state->ver.major; 312} 313 314u16 nfp_nsp_get_abi_ver_minor(struct nfp_nsp *state) 315{ 316 return state->ver.minor; 317} 318 319static int 320nfp_nsp_wait_reg(struct nfp_cpp *cpp, u64 *reg, u32 nsp_cpp, u64 addr, 321 u64 mask, u64 val, u32 timeout_sec) 322{ 323 const unsigned long wait_until = jiffies + timeout_sec * HZ; 324 int err; 325 326 for (;;) { 327 const unsigned long start_time = jiffies; 328 329 err = nfp_cpp_readq(cpp, nsp_cpp, addr, reg); 330 if (err < 0) 331 return err; 332 333 if ((*reg & mask) == val) 334 return 0; 335 336 msleep(25); 337 338 if (time_after(start_time, wait_until)) 339 return -ETIMEDOUT; 340 } 341} 342 343/** 344 * __nfp_nsp_command() - Execute a command on the NFP Service Processor 345 * @state: NFP SP state 346 * @arg: NFP command argument structure 347 * 348 * Return: 0 for success with no result 349 * 350 * positive value for NSP completion with a result code 351 * 352 * -EAGAIN if the NSP is not yet present 353 * -ENODEV if the NSP is not a supported model 354 * -EBUSY if the NSP is stuck 355 * -EINTR if interrupted while waiting for completion 356 * -ETIMEDOUT if the NSP took longer than @timeout_sec seconds to complete 357 */ 358static int 359__nfp_nsp_command(struct nfp_nsp *state, const struct nfp_nsp_command_arg *arg) 360{ 361 u64 reg, ret_val, nsp_base, nsp_buffer, nsp_status, nsp_command; 362 struct nfp_cpp *cpp = state->cpp; 363 u32 nsp_cpp; 364 int err; 365 366 nsp_cpp = nfp_resource_cpp_id(state->res); 367 nsp_base = nfp_resource_address(state->res); 368 nsp_status = nsp_base + NSP_STATUS; 369 nsp_command = nsp_base + NSP_COMMAND; 370 nsp_buffer = nsp_base + NSP_BUFFER; 371 372 err = nfp_nsp_check(state); 373 if (err) 374 return err; 375 376 err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_buffer, arg->buf); 377 if (err < 0) 378 return err; 379 380 err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_command, 381 FIELD_PREP(NSP_COMMAND_OPTION, arg->option) | 382 FIELD_PREP(NSP_COMMAND_CODE, arg->code) | 383 FIELD_PREP(NSP_COMMAND_DMA_BUF, arg->dma) | 384 FIELD_PREP(NSP_COMMAND_START, 1)); 385 if (err < 0) 386 return err; 387 388 /* Wait for NSP_COMMAND_START to go to 0 */ 389 err = nfp_nsp_wait_reg(cpp, ®, nsp_cpp, nsp_command, 390 NSP_COMMAND_START, 0, NFP_NSP_TIMEOUT_DEFAULT); 391 if (err) { 392 nfp_err(cpp, "Error %d waiting for code 0x%04x to start\n", 393 err, arg->code); 394 return err; 395 } 396 397 /* Wait for NSP_STATUS_BUSY to go to 0 */ 398 err = nfp_nsp_wait_reg(cpp, ®, nsp_cpp, nsp_status, NSP_STATUS_BUSY, 399 0, arg->timeout_sec ?: NFP_NSP_TIMEOUT_DEFAULT); 400 if (err) { 401 nfp_err(cpp, "Error %d waiting for code 0x%04x to complete\n", 402 err, arg->code); 403 return err; 404 } 405 406 err = nfp_cpp_readq(cpp, nsp_cpp, nsp_command, &ret_val); 407 if (err < 0) 408 return err; 409 ret_val = FIELD_GET(NSP_COMMAND_OPTION, ret_val); 410 411 err = FIELD_GET(NSP_STATUS_RESULT, reg); 412 if (err) { 413 if (!arg->error_quiet) 414 nfp_warn(cpp, "Result (error) code set: %d (%d) command: %d\n", 415 -err, (int)ret_val, arg->code); 416 417 if (arg->error_cb) 418 arg->error_cb(state, ret_val); 419 else 420 nfp_nsp_print_extended_error(state, ret_val); 421 return -err; 422 } 423 424 return ret_val; 425} 426 427static int nfp_nsp_command(struct nfp_nsp *state, u16 code) 428{ 429 const struct nfp_nsp_command_arg arg = { 430 .code = code, 431 }; 432 433 return __nfp_nsp_command(state, &arg); 434} 435 436static int 437nfp_nsp_command_buf_def(struct nfp_nsp *nsp, 438 struct nfp_nsp_command_buf_arg *arg) 439{ 440 struct nfp_cpp *cpp = nsp->cpp; 441 u64 reg, cpp_buf; 442 int err, ret; 443 u32 cpp_id; 444 445 err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res), 446 nfp_resource_address(nsp->res) + 447 NSP_DFLT_BUFFER, 448 ®); 449 if (err < 0) 450 return err; 451 452 cpp_id = FIELD_GET(NSP_DFLT_BUFFER_CPP, reg) << 8; 453 cpp_buf = FIELD_GET(NSP_DFLT_BUFFER_ADDRESS, reg); 454 455 if (arg->in_buf && arg->in_size) { 456 err = nfp_cpp_write(cpp, cpp_id, cpp_buf, 457 arg->in_buf, arg->in_size); 458 if (err < 0) 459 return err; 460 } 461 /* Zero out remaining part of the buffer */ 462 if (arg->out_buf && arg->out_size && arg->out_size > arg->in_size) { 463 err = nfp_cpp_write(cpp, cpp_id, cpp_buf + arg->in_size, 464 arg->out_buf, arg->out_size - arg->in_size); 465 if (err < 0) 466 return err; 467 } 468 469 if (!FIELD_FIT(NSP_BUFFER_CPP, cpp_id >> 8) || 470 !FIELD_FIT(NSP_BUFFER_ADDRESS, cpp_buf)) { 471 nfp_err(cpp, "Buffer out of reach %08x %016llx\n", 472 cpp_id, cpp_buf); 473 return -EINVAL; 474 } 475 476 arg->arg.buf = FIELD_PREP(NSP_BUFFER_CPP, cpp_id >> 8) | 477 FIELD_PREP(NSP_BUFFER_ADDRESS, cpp_buf); 478 ret = __nfp_nsp_command(nsp, &arg->arg); 479 if (ret < 0) 480 return ret; 481 482 if (arg->out_buf && arg->out_size) { 483 err = nfp_cpp_read(cpp, cpp_id, cpp_buf, 484 arg->out_buf, arg->out_size); 485 if (err < 0) 486 return err; 487 } 488 489 return ret; 490} 491 492static int 493nfp_nsp_command_buf_dma_sg(struct nfp_nsp *nsp, 494 struct nfp_nsp_command_buf_arg *arg, 495 unsigned int max_size, unsigned int chunk_order, 496 unsigned int dma_order) 497{ 498 struct nfp_cpp *cpp = nsp->cpp; 499 struct nfp_nsp_dma_buf *desc; 500 struct { 501 dma_addr_t dma_addr; 502 unsigned long len; 503 void *chunk; 504 } *chunks; 505 size_t chunk_size, dma_size; 506 dma_addr_t dma_desc; 507 struct device *dev; 508 unsigned long off; 509 int i, ret, nseg; 510 size_t desc_sz; 511 512 chunk_size = BIT_ULL(chunk_order); 513 dma_size = BIT_ULL(dma_order); 514 nseg = DIV_ROUND_UP(max_size, chunk_size); 515 516 chunks = kcalloc(nseg, sizeof(*chunks), GFP_KERNEL); 517 if (!chunks) 518 return -ENOMEM; 519 520 off = 0; 521 ret = -ENOMEM; 522 for (i = 0; i < nseg; i++) { 523 unsigned long coff; 524 525 chunks[i].chunk = kmalloc(chunk_size, 526 GFP_KERNEL | __GFP_NOWARN); 527 if (!chunks[i].chunk) 528 goto exit_free_prev; 529 530 chunks[i].len = min_t(u64, chunk_size, max_size - off); 531 532 coff = 0; 533 if (arg->in_size > off) { 534 coff = min_t(u64, arg->in_size - off, chunk_size); 535 memcpy(chunks[i].chunk, arg->in_buf + off, coff); 536 } 537 memset(chunks[i].chunk + coff, 0, chunk_size - coff); 538 539 off += chunks[i].len; 540 } 541 542 dev = nfp_cpp_device(cpp)->parent; 543 544 for (i = 0; i < nseg; i++) { 545 dma_addr_t addr; 546 547 addr = dma_map_single(dev, chunks[i].chunk, chunks[i].len, 548 DMA_BIDIRECTIONAL); 549 chunks[i].dma_addr = addr; 550 551 ret = dma_mapping_error(dev, addr); 552 if (ret) 553 goto exit_unmap_prev; 554 555 if (WARN_ONCE(round_down(addr, dma_size) != 556 round_down(addr + chunks[i].len - 1, dma_size), 557 "unaligned DMA address: %pad %lu %zd\n", 558 &addr, chunks[i].len, dma_size)) { 559 ret = -EFAULT; 560 i++; 561 goto exit_unmap_prev; 562 } 563 } 564 565 desc_sz = struct_size(desc, descs, nseg); 566 desc = kmalloc(desc_sz, GFP_KERNEL); 567 if (!desc) { 568 ret = -ENOMEM; 569 goto exit_unmap_all; 570 } 571 572 desc->chunk_cnt = cpu_to_le32(nseg); 573 for (i = 0; i < nseg; i++) { 574 desc->descs[i].size = cpu_to_le32(chunks[i].len); 575 desc->descs[i].addr = cpu_to_le64(chunks[i].dma_addr); 576 } 577 578 dma_desc = dma_map_single(dev, desc, desc_sz, DMA_TO_DEVICE); 579 ret = dma_mapping_error(dev, dma_desc); 580 if (ret) 581 goto exit_free_desc; 582 583 arg->arg.dma = true; 584 arg->arg.buf = dma_desc; 585 ret = __nfp_nsp_command(nsp, &arg->arg); 586 if (ret < 0) 587 goto exit_unmap_desc; 588 589 i = 0; 590 off = 0; 591 while (off < arg->out_size) { 592 unsigned int len; 593 594 len = min_t(u64, chunks[i].len, arg->out_size - off); 595 memcpy(arg->out_buf + off, chunks[i].chunk, len); 596 off += len; 597 i++; 598 } 599 600exit_unmap_desc: 601 dma_unmap_single(dev, dma_desc, desc_sz, DMA_TO_DEVICE); 602exit_free_desc: 603 kfree(desc); 604exit_unmap_all: 605 i = nseg; 606exit_unmap_prev: 607 while (--i >= 0) 608 dma_unmap_single(dev, chunks[i].dma_addr, chunks[i].len, 609 DMA_BIDIRECTIONAL); 610 i = nseg; 611exit_free_prev: 612 while (--i >= 0) 613 kfree(chunks[i].chunk); 614 kfree(chunks); 615 if (ret < 0) 616 nfp_err(cpp, "NSP: SG DMA failed for command 0x%04x: %d (sz:%d cord:%d)\n", 617 arg->arg.code, ret, max_size, chunk_order); 618 return ret; 619} 620 621static int 622nfp_nsp_command_buf_dma(struct nfp_nsp *nsp, 623 struct nfp_nsp_command_buf_arg *arg, 624 unsigned int max_size, unsigned int dma_order) 625{ 626 unsigned int chunk_order, buf_order; 627 struct nfp_cpp *cpp = nsp->cpp; 628 bool sg_ok; 629 u64 reg; 630 int err; 631 632 buf_order = order_base_2(roundup_pow_of_two(max_size)); 633 634 err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res), 635 nfp_resource_address(nsp->res) + NFP_CAP_CMD_DMA_SG, 636 ®); 637 if (err < 0) 638 return err; 639 sg_ok = reg & BIT_ULL(arg->arg.code - 1); 640 641 if (!sg_ok) { 642 if (buf_order > dma_order) { 643 nfp_err(cpp, "NSP: can't service non-SG DMA for command 0x%04x\n", 644 arg->arg.code); 645 return -ENOMEM; 646 } 647 chunk_order = buf_order; 648 } else { 649 chunk_order = min_t(unsigned int, dma_order, PAGE_SHIFT); 650 } 651 652 return nfp_nsp_command_buf_dma_sg(nsp, arg, max_size, chunk_order, 653 dma_order); 654} 655 656static int 657nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg) 658{ 659 unsigned int dma_order, def_size, max_size; 660 struct nfp_cpp *cpp = nsp->cpp; 661 u64 reg; 662 int err; 663 664 if (nsp->ver.minor < 13) { 665 nfp_err(cpp, "NSP: Code 0x%04x with buffer not supported (ABI %hu.%hu)\n", 666 arg->arg.code, nsp->ver.major, nsp->ver.minor); 667 return -EOPNOTSUPP; 668 } 669 670 err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res), 671 nfp_resource_address(nsp->res) + 672 NSP_DFLT_BUFFER_CONFIG, 673 ®); 674 if (err < 0) 675 return err; 676 677 /* Zero out undefined part of the out buffer */ 678 if (arg->out_buf && arg->out_size && arg->out_size > arg->in_size) 679 memset(arg->out_buf, 0, arg->out_size - arg->in_size); 680 681 max_size = max(arg->in_size, arg->out_size); 682 def_size = FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M + 683 FIELD_GET(NSP_DFLT_BUFFER_SIZE_4KB, reg) * SZ_4K; 684 dma_order = FIELD_GET(NSP_DFLT_BUFFER_DMA_CHUNK_ORDER, reg); 685 if (def_size >= max_size) { 686 return nfp_nsp_command_buf_def(nsp, arg); 687 } else if (!dma_order) { 688 nfp_err(cpp, "NSP: default buffer too small for command 0x%04x (%u < %u)\n", 689 arg->arg.code, def_size, max_size); 690 return -EINVAL; 691 } 692 693 return nfp_nsp_command_buf_dma(nsp, arg, max_size, dma_order); 694} 695 696int nfp_nsp_wait(struct nfp_nsp *state) 697{ 698 const unsigned long wait_until = jiffies + NFP_NSP_TIMEOUT_BOOT * HZ; 699 int err; 700 701 nfp_dbg(state->cpp, "Waiting for NSP to respond (%u sec max).\n", 702 NFP_NSP_TIMEOUT_BOOT); 703 704 for (;;) { 705 const unsigned long start_time = jiffies; 706 707 err = nfp_nsp_command(state, SPCODE_NOOP); 708 if (err != -EAGAIN) 709 break; 710 711 if (msleep_interruptible(25)) { 712 err = -ERESTARTSYS; 713 break; 714 } 715 716 if (time_after(start_time, wait_until)) { 717 err = -ETIMEDOUT; 718 break; 719 } 720 } 721 if (err) 722 nfp_err(state->cpp, "NSP failed to respond %d\n", err); 723 724 return err; 725} 726 727int nfp_nsp_device_soft_reset(struct nfp_nsp *state) 728{ 729 return nfp_nsp_command(state, SPCODE_SOFT_RESET); 730} 731 732int nfp_nsp_mac_reinit(struct nfp_nsp *state) 733{ 734 return nfp_nsp_command(state, SPCODE_MAC_INIT); 735} 736 737static void nfp_nsp_load_fw_extended_msg(struct nfp_nsp *state, u32 ret_val) 738{ 739 static const char * const major_msg[] = { 740 /* 0 */ "Firmware from driver loaded", 741 /* 1 */ "Firmware from flash loaded", 742 /* 2 */ "Firmware loading failure", 743 }; 744 static const char * const minor_msg[] = { 745 /* 0 */ "", 746 /* 1 */ "no named partition on flash", 747 /* 2 */ "error reading from flash", 748 /* 3 */ "can not deflate", 749 /* 4 */ "not a trusted file", 750 /* 5 */ "can not parse FW file", 751 /* 6 */ "MIP not found in FW file", 752 /* 7 */ "null firmware name in MIP", 753 /* 8 */ "FW version none", 754 /* 9 */ "FW build number none", 755 /* 10 */ "no FW selection policy HWInfo key found", 756 /* 11 */ "static FW selection policy", 757 /* 12 */ "FW version has precedence", 758 /* 13 */ "different FW application load requested", 759 /* 14 */ "development build", 760 }; 761 unsigned int major, minor; 762 const char *level; 763 764 major = FIELD_GET(NFP_FW_LOAD_RET_MAJOR, ret_val); 765 minor = FIELD_GET(NFP_FW_LOAD_RET_MINOR, ret_val); 766 767 if (!nfp_nsp_has_stored_fw_load(state)) 768 return; 769 770 /* Lower the message level in legacy case */ 771 if (major == 0 && (minor == 0 || minor == 10)) 772 level = KERN_DEBUG; 773 else if (major == 2) 774 level = KERN_ERR; 775 else 776 level = KERN_INFO; 777 778 if (major >= ARRAY_SIZE(major_msg)) 779 nfp_printk(level, state->cpp, "FW loading status: %x\n", 780 ret_val); 781 else if (minor >= ARRAY_SIZE(minor_msg)) 782 nfp_printk(level, state->cpp, "%s, reason code: %d\n", 783 major_msg[major], minor); 784 else 785 nfp_printk(level, state->cpp, "%s%c %s\n", 786 major_msg[major], minor ? ',' : '.', 787 minor_msg[minor]); 788} 789 790int nfp_nsp_load_fw(struct nfp_nsp *state, const struct firmware *fw) 791{ 792 struct nfp_nsp_command_buf_arg load_fw = { 793 { 794 .code = SPCODE_FW_LOAD, 795 .option = fw->size, 796 .error_cb = nfp_nsp_load_fw_extended_msg, 797 }, 798 .in_buf = fw->data, 799 .in_size = fw->size, 800 }; 801 int ret; 802 803 ret = nfp_nsp_command_buf(state, &load_fw); 804 if (ret < 0) 805 return ret; 806 807 nfp_nsp_load_fw_extended_msg(state, ret); 808 return 0; 809} 810 811int nfp_nsp_write_flash(struct nfp_nsp *state, const struct firmware *fw) 812{ 813 struct nfp_nsp_command_buf_arg write_flash = { 814 { 815 .code = SPCODE_NSP_WRITE_FLASH, 816 .option = fw->size, 817 .timeout_sec = 900, 818 }, 819 .in_buf = fw->data, 820 .in_size = fw->size, 821 }; 822 823 return nfp_nsp_command_buf(state, &write_flash); 824} 825 826int nfp_nsp_read_eth_table(struct nfp_nsp *state, void *buf, unsigned int size) 827{ 828 struct nfp_nsp_command_buf_arg eth_rescan = { 829 { 830 .code = SPCODE_ETH_RESCAN, 831 .option = size, 832 }, 833 .out_buf = buf, 834 .out_size = size, 835 }; 836 837 return nfp_nsp_command_buf(state, ð_rescan); 838} 839 840int nfp_nsp_write_eth_table(struct nfp_nsp *state, 841 const void *buf, unsigned int size) 842{ 843 struct nfp_nsp_command_buf_arg eth_ctrl = { 844 { 845 .code = SPCODE_ETH_CONTROL, 846 .option = size, 847 }, 848 .in_buf = buf, 849 .in_size = size, 850 }; 851 852 return nfp_nsp_command_buf(state, ð_ctrl); 853} 854 855int nfp_nsp_read_identify(struct nfp_nsp *state, void *buf, unsigned int size) 856{ 857 struct nfp_nsp_command_buf_arg identify = { 858 { 859 .code = SPCODE_NSP_IDENTIFY, 860 .option = size, 861 }, 862 .out_buf = buf, 863 .out_size = size, 864 }; 865 866 return nfp_nsp_command_buf(state, &identify); 867} 868 869int nfp_nsp_read_sensors(struct nfp_nsp *state, unsigned int sensor_mask, 870 void *buf, unsigned int size) 871{ 872 struct nfp_nsp_command_buf_arg sensors = { 873 { 874 .code = SPCODE_NSP_SENSORS, 875 .option = sensor_mask, 876 }, 877 .out_buf = buf, 878 .out_size = size, 879 }; 880 881 return nfp_nsp_command_buf(state, &sensors); 882} 883 884int nfp_nsp_load_stored_fw(struct nfp_nsp *state) 885{ 886 const struct nfp_nsp_command_arg arg = { 887 .code = SPCODE_FW_STORED, 888 .error_cb = nfp_nsp_load_fw_extended_msg, 889 }; 890 int ret; 891 892 ret = __nfp_nsp_command(state, &arg); 893 if (ret < 0) 894 return ret; 895 896 nfp_nsp_load_fw_extended_msg(state, ret); 897 return 0; 898} 899 900static int 901__nfp_nsp_hwinfo_lookup(struct nfp_nsp *state, void *buf, unsigned int size, 902 bool optional) 903{ 904 struct nfp_nsp_command_buf_arg hwinfo_lookup = { 905 { 906 .code = SPCODE_HWINFO_LOOKUP, 907 .option = size, 908 .error_quiet = optional, 909 }, 910 .in_buf = buf, 911 .in_size = size, 912 .out_buf = buf, 913 .out_size = size, 914 }; 915 916 return nfp_nsp_command_buf(state, &hwinfo_lookup); 917} 918 919int nfp_nsp_hwinfo_lookup(struct nfp_nsp *state, void *buf, unsigned int size) 920{ 921 int err; 922 923 size = min_t(u32, size, NFP_HWINFO_LOOKUP_SIZE); 924 925 err = __nfp_nsp_hwinfo_lookup(state, buf, size, false); 926 if (err) 927 return err; 928 929 if (strnlen(buf, size) == size) { 930 nfp_err(state->cpp, "NSP HWinfo value not NULL-terminated\n"); 931 return -EINVAL; 932 } 933 934 return 0; 935} 936 937int nfp_nsp_hwinfo_lookup_optional(struct nfp_nsp *state, void *buf, 938 unsigned int size, const char *default_val) 939{ 940 int err; 941 942 /* Ensure that the default value is usable irrespective of whether 943 * it is actually going to be used. 944 */ 945 if (strnlen(default_val, size) == size) 946 return -EINVAL; 947 948 if (!nfp_nsp_has_hwinfo_lookup(state)) { 949 strcpy(buf, default_val); 950 return 0; 951 } 952 953 size = min_t(u32, size, NFP_HWINFO_LOOKUP_SIZE); 954 955 err = __nfp_nsp_hwinfo_lookup(state, buf, size, true); 956 if (err) { 957 if (err == -ENOENT) { 958 strcpy(buf, default_val); 959 return 0; 960 } 961 962 nfp_err(state->cpp, "NSP HWinfo lookup failed: %d\n", err); 963 return err; 964 } 965 966 if (strnlen(buf, size) == size) { 967 nfp_err(state->cpp, "NSP HWinfo value not NULL-terminated\n"); 968 return -EINVAL; 969 } 970 971 return 0; 972} 973 974int nfp_nsp_hwinfo_set(struct nfp_nsp *state, void *buf, unsigned int size) 975{ 976 struct nfp_nsp_command_buf_arg hwinfo_set = { 977 { 978 .code = SPCODE_HWINFO_SET, 979 .option = size, 980 }, 981 .in_buf = buf, 982 .in_size = size, 983 }; 984 985 return nfp_nsp_command_buf(state, &hwinfo_set); 986} 987 988int nfp_nsp_fw_loaded(struct nfp_nsp *state) 989{ 990 const struct nfp_nsp_command_arg arg = { 991 .code = SPCODE_FW_LOADED, 992 }; 993 994 return __nfp_nsp_command(state, &arg); 995} 996 997int nfp_nsp_versions(struct nfp_nsp *state, void *buf, unsigned int size) 998{ 999 struct nfp_nsp_command_buf_arg versions = { 1000 { 1001 .code = SPCODE_VERSIONS, 1002 .option = min_t(u32, size, NFP_VERSIONS_SIZE), 1003 }, 1004 .out_buf = buf, 1005 .out_size = min_t(u32, size, NFP_VERSIONS_SIZE), 1006 }; 1007 1008 return nfp_nsp_command_buf(state, &versions); 1009} 1010 1011const char *nfp_nsp_versions_get(enum nfp_nsp_versions id, bool flash, 1012 const u8 *buf, unsigned int size) 1013{ 1014 static const u32 id2off[] = { 1015 [NFP_VERSIONS_BSP] = NFP_VERSIONS_BSP_OFF, 1016 [NFP_VERSIONS_CPLD] = NFP_VERSIONS_CPLD_OFF, 1017 [NFP_VERSIONS_APP] = NFP_VERSIONS_APP_OFF, 1018 [NFP_VERSIONS_BUNDLE] = NFP_VERSIONS_BUNDLE_OFF, 1019 [NFP_VERSIONS_UNDI] = NFP_VERSIONS_UNDI_OFF, 1020 [NFP_VERSIONS_NCSI] = NFP_VERSIONS_NCSI_OFF, 1021 [NFP_VERSIONS_CFGR] = NFP_VERSIONS_CFGR_OFF, 1022 }; 1023 unsigned int field, buf_field_cnt, buf_off; 1024 1025 if (id >= ARRAY_SIZE(id2off) || !id2off[id]) 1026 return ERR_PTR(-EINVAL); 1027 1028 field = id * 2 + flash; 1029 1030 buf_field_cnt = get_unaligned_le16(buf); 1031 if (buf_field_cnt <= field) 1032 return ERR_PTR(-ENOENT); 1033 1034 buf_off = get_unaligned_le16(buf + id2off[id] + flash * 2); 1035 if (!buf_off) 1036 return ERR_PTR(-ENOENT); 1037 1038 if (buf_off >= size) 1039 return ERR_PTR(-EINVAL); 1040 if (strnlen(&buf[buf_off], size - buf_off) == size - buf_off) 1041 return ERR_PTR(-EINVAL); 1042 1043 return (const char *)&buf[buf_off]; 1044} 1045 1046static int 1047__nfp_nsp_module_eeprom(struct nfp_nsp *state, void *buf, unsigned int size) 1048{ 1049 struct nfp_nsp_command_buf_arg module_eeprom = { 1050 { 1051 .code = SPCODE_READ_SFF_EEPROM, 1052 .option = size, 1053 }, 1054 .in_buf = buf, 1055 .in_size = size, 1056 .out_buf = buf, 1057 .out_size = size, 1058 }; 1059 1060 return nfp_nsp_command_buf(state, &module_eeprom); 1061} 1062 1063int nfp_nsp_read_module_eeprom(struct nfp_nsp *state, int eth_index, 1064 unsigned int offset, void *data, 1065 unsigned int len, unsigned int *read_len) 1066{ 1067 struct eeprom_buf { 1068 u8 metalen; 1069 __le16 length; 1070 __le16 offset; 1071 __le16 readlen; 1072 u8 eth_index; 1073 u8 data[]; 1074 } __packed *buf; 1075 int bufsz, ret; 1076 1077 BUILD_BUG_ON(offsetof(struct eeprom_buf, data) % 8); 1078 1079 /* Buffer must be large enough and rounded to the next block size. */ 1080 bufsz = struct_size(buf, data, round_up(len, NSP_SFF_EEPROM_BLOCK_LEN)); 1081 buf = kzalloc(bufsz, GFP_KERNEL); 1082 if (!buf) 1083 return -ENOMEM; 1084 1085 buf->metalen = 1086 offsetof(struct eeprom_buf, data) / NSP_SFF_EEPROM_BLOCK_LEN; 1087 buf->length = cpu_to_le16(len); 1088 buf->offset = cpu_to_le16(offset); 1089 buf->eth_index = eth_index; 1090 1091 ret = __nfp_nsp_module_eeprom(state, buf, bufsz); 1092 1093 *read_len = min_t(unsigned int, len, le16_to_cpu(buf->readlen)); 1094 if (*read_len) 1095 memcpy(data, buf->data, *read_len); 1096 1097 if (!ret && *read_len < len) 1098 ret = -EIO; 1099 1100 kfree(buf); 1101 1102 return ret; 1103}