0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <asm/unaligned.h>
0011 #include <linux/bitfield.h>
0012 #include <linux/delay.h>
0013 #include <linux/firmware.h>
0014 #include <linux/kernel.h>
0015 #include <linux/kthread.h>
0016 #include <linux/overflow.h>
0017 #include <linux/sizes.h>
0018 #include <linux/slab.h>
0019
0020 #define NFP_SUBSYS "nfp_nsp"
0021
0022 #include "nfp.h"
0023 #include "nfp_cpp.h"
0024 #include "nfp_nsp.h"
0025
0026 #define NFP_NSP_TIMEOUT_DEFAULT 30
0027 #define NFP_NSP_TIMEOUT_BOOT 30
0028
0029
0030 #define NSP_STATUS 0x00
0031 #define NSP_STATUS_MAGIC GENMASK_ULL(63, 48)
0032 #define NSP_STATUS_MAJOR GENMASK_ULL(47, 44)
0033 #define NSP_STATUS_MINOR GENMASK_ULL(43, 32)
0034 #define NSP_STATUS_CODE GENMASK_ULL(31, 16)
0035 #define NSP_STATUS_RESULT GENMASK_ULL(15, 8)
0036 #define NSP_STATUS_BUSY BIT_ULL(0)
0037
0038 #define NSP_COMMAND 0x08
0039 #define NSP_COMMAND_OPTION GENMASK_ULL(63, 32)
0040 #define NSP_COMMAND_CODE GENMASK_ULL(31, 16)
0041 #define NSP_COMMAND_DMA_BUF BIT_ULL(1)
0042 #define NSP_COMMAND_START BIT_ULL(0)
0043
0044
0045 #define NSP_BUFFER 0x10
0046 #define NSP_BUFFER_CPP GENMASK_ULL(63, 40)
0047 #define NSP_BUFFER_ADDRESS GENMASK_ULL(39, 0)
0048
0049 #define NSP_DFLT_BUFFER 0x18
0050 #define NSP_DFLT_BUFFER_CPP GENMASK_ULL(63, 40)
0051 #define NSP_DFLT_BUFFER_ADDRESS GENMASK_ULL(39, 0)
0052
0053 #define NSP_DFLT_BUFFER_CONFIG 0x20
0054 #define NSP_DFLT_BUFFER_DMA_CHUNK_ORDER GENMASK_ULL(63, 58)
0055 #define NSP_DFLT_BUFFER_SIZE_4KB GENMASK_ULL(15, 8)
0056 #define NSP_DFLT_BUFFER_SIZE_MB GENMASK_ULL(7, 0)
0057
0058 #define NFP_CAP_CMD_DMA_SG 0x28
0059
0060 #define NSP_MAGIC 0xab10
0061 #define NSP_MAJOR 0
0062 #define NSP_MINOR 8
0063
0064 #define NSP_CODE_MAJOR GENMASK(15, 12)
0065 #define NSP_CODE_MINOR GENMASK(11, 0)
0066
0067 #define NFP_FW_LOAD_RET_MAJOR GENMASK(15, 8)
0068 #define NFP_FW_LOAD_RET_MINOR GENMASK(23, 16)
0069
0070 #define NFP_HWINFO_LOOKUP_SIZE GENMASK(11, 0)
0071
0072 #define NFP_VERSIONS_SIZE GENMASK(11, 0)
0073 #define NFP_VERSIONS_CNT_OFF 0
0074 #define NFP_VERSIONS_BSP_OFF 2
0075 #define NFP_VERSIONS_CPLD_OFF 6
0076 #define NFP_VERSIONS_APP_OFF 10
0077 #define NFP_VERSIONS_BUNDLE_OFF 14
0078 #define NFP_VERSIONS_UNDI_OFF 18
0079 #define NFP_VERSIONS_NCSI_OFF 22
0080 #define NFP_VERSIONS_CFGR_OFF 26
0081
0082 #define NSP_SFF_EEPROM_BLOCK_LEN 8
0083
0084 enum nfp_nsp_cmd {
0085 SPCODE_NOOP = 0,
0086 SPCODE_SOFT_RESET = 1,
0087 SPCODE_FW_DEFAULT = 2,
0088 SPCODE_PHY_INIT = 3,
0089 SPCODE_MAC_INIT = 4,
0090 SPCODE_PHY_RXADAPT = 5,
0091 SPCODE_FW_LOAD = 6,
0092 SPCODE_ETH_RESCAN = 7,
0093 SPCODE_ETH_CONTROL = 8,
0094 SPCODE_NSP_WRITE_FLASH = 11,
0095 SPCODE_NSP_SENSORS = 12,
0096 SPCODE_NSP_IDENTIFY = 13,
0097 SPCODE_FW_STORED = 16,
0098 SPCODE_HWINFO_LOOKUP = 17,
0099 SPCODE_HWINFO_SET = 18,
0100 SPCODE_FW_LOADED = 19,
0101 SPCODE_VERSIONS = 21,
0102 SPCODE_READ_SFF_EEPROM = 22,
0103 };
0104
0105 struct nfp_nsp_dma_buf {
0106 __le32 chunk_cnt;
0107 __le32 reserved[3];
0108 struct {
0109 __le32 size;
0110 __le32 reserved;
0111 __le64 addr;
0112 } descs[];
0113 };
0114
0115 static const struct {
0116 int code;
0117 const char *msg;
0118 } nsp_errors[] = {
0119 { 6010, "could not map to phy for port" },
0120 { 6011, "not an allowed rate/lanes for port" },
0121 { 6012, "not an allowed rate/lanes for port" },
0122 { 6013, "high/low error, change other port first" },
0123 { 6014, "config not found in flash" },
0124 };
0125
0126 struct nfp_nsp {
0127 struct nfp_cpp *cpp;
0128 struct nfp_resource *res;
0129 struct {
0130 u16 major;
0131 u16 minor;
0132 } ver;
0133
0134
0135 bool modified;
0136 unsigned int idx;
0137 void *entries;
0138 };
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151 struct nfp_nsp_command_arg {
0152 u16 code;
0153 bool dma;
0154 unsigned int timeout_sec;
0155 u32 option;
0156 u64 buf;
0157 void (*error_cb)(struct nfp_nsp *state, u32 ret_val);
0158 bool error_quiet;
0159 };
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169 struct nfp_nsp_command_buf_arg {
0170 struct nfp_nsp_command_arg arg;
0171 const void *in_buf;
0172 unsigned int in_size;
0173 void *out_buf;
0174 unsigned int out_size;
0175 };
0176
0177 struct nfp_cpp *nfp_nsp_cpp(struct nfp_nsp *state)
0178 {
0179 return state->cpp;
0180 }
0181
0182 bool nfp_nsp_config_modified(struct nfp_nsp *state)
0183 {
0184 return state->modified;
0185 }
0186
0187 void nfp_nsp_config_set_modified(struct nfp_nsp *state, bool modified)
0188 {
0189 state->modified = modified;
0190 }
0191
0192 void *nfp_nsp_config_entries(struct nfp_nsp *state)
0193 {
0194 return state->entries;
0195 }
0196
0197 unsigned int nfp_nsp_config_idx(struct nfp_nsp *state)
0198 {
0199 return state->idx;
0200 }
0201
0202 void
0203 nfp_nsp_config_set_state(struct nfp_nsp *state, void *entries, unsigned int idx)
0204 {
0205 state->entries = entries;
0206 state->idx = idx;
0207 }
0208
0209 void nfp_nsp_config_clear_state(struct nfp_nsp *state)
0210 {
0211 state->entries = NULL;
0212 state->idx = 0;
0213 }
0214
0215 static void nfp_nsp_print_extended_error(struct nfp_nsp *state, u32 ret_val)
0216 {
0217 int i;
0218
0219 if (!ret_val)
0220 return;
0221
0222 for (i = 0; i < ARRAY_SIZE(nsp_errors); i++)
0223 if (ret_val == nsp_errors[i].code)
0224 nfp_err(state->cpp, "err msg: %s\n", nsp_errors[i].msg);
0225 }
0226
0227 static int nfp_nsp_check(struct nfp_nsp *state)
0228 {
0229 struct nfp_cpp *cpp = state->cpp;
0230 u64 nsp_status, reg;
0231 u32 nsp_cpp;
0232 int err;
0233
0234 nsp_cpp = nfp_resource_cpp_id(state->res);
0235 nsp_status = nfp_resource_address(state->res) + NSP_STATUS;
0236
0237 err = nfp_cpp_readq(cpp, nsp_cpp, nsp_status, ®);
0238 if (err < 0)
0239 return err;
0240
0241 if (FIELD_GET(NSP_STATUS_MAGIC, reg) != NSP_MAGIC) {
0242 nfp_err(cpp, "Cannot detect NFP Service Processor\n");
0243 return -ENODEV;
0244 }
0245
0246 state->ver.major = FIELD_GET(NSP_STATUS_MAJOR, reg);
0247 state->ver.minor = FIELD_GET(NSP_STATUS_MINOR, reg);
0248
0249 if (state->ver.major != NSP_MAJOR) {
0250 nfp_err(cpp, "Unsupported ABI %hu.%hu\n",
0251 state->ver.major, state->ver.minor);
0252 return -EINVAL;
0253 }
0254 if (state->ver.minor < NSP_MINOR) {
0255 nfp_err(cpp, "ABI too old to support NIC operation (%u.%hu < %u.%u), please update the management FW on the flash\n",
0256 NSP_MAJOR, state->ver.minor, NSP_MAJOR, NSP_MINOR);
0257 return -EINVAL;
0258 }
0259
0260 if (reg & NSP_STATUS_BUSY) {
0261 nfp_err(cpp, "Service processor busy!\n");
0262 return -EBUSY;
0263 }
0264
0265 return 0;
0266 }
0267
0268
0269
0270
0271
0272 struct nfp_nsp *nfp_nsp_open(struct nfp_cpp *cpp)
0273 {
0274 struct nfp_resource *res;
0275 struct nfp_nsp *state;
0276 int err;
0277
0278 res = nfp_resource_acquire(cpp, NFP_RESOURCE_NSP);
0279 if (IS_ERR(res))
0280 return (void *)res;
0281
0282 state = kzalloc(sizeof(*state), GFP_KERNEL);
0283 if (!state) {
0284 nfp_resource_release(res);
0285 return ERR_PTR(-ENOMEM);
0286 }
0287 state->cpp = cpp;
0288 state->res = res;
0289
0290 err = nfp_nsp_check(state);
0291 if (err) {
0292 nfp_nsp_close(state);
0293 return ERR_PTR(err);
0294 }
0295
0296 return state;
0297 }
0298
0299
0300
0301
0302
0303 void nfp_nsp_close(struct nfp_nsp *state)
0304 {
0305 nfp_resource_release(state->res);
0306 kfree(state);
0307 }
0308
0309 u16 nfp_nsp_get_abi_ver_major(struct nfp_nsp *state)
0310 {
0311 return state->ver.major;
0312 }
0313
0314 u16 nfp_nsp_get_abi_ver_minor(struct nfp_nsp *state)
0315 {
0316 return state->ver.minor;
0317 }
0318
0319 static int
0320 nfp_nsp_wait_reg(struct nfp_cpp *cpp, u64 *reg, u32 nsp_cpp, u64 addr,
0321 u64 mask, u64 val, u32 timeout_sec)
0322 {
0323 const unsigned long wait_until = jiffies + timeout_sec * HZ;
0324 int err;
0325
0326 for (;;) {
0327 const unsigned long start_time = jiffies;
0328
0329 err = nfp_cpp_readq(cpp, nsp_cpp, addr, reg);
0330 if (err < 0)
0331 return err;
0332
0333 if ((*reg & mask) == val)
0334 return 0;
0335
0336 msleep(25);
0337
0338 if (time_after(start_time, wait_until))
0339 return -ETIMEDOUT;
0340 }
0341 }
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358 static int
0359 __nfp_nsp_command(struct nfp_nsp *state, const struct nfp_nsp_command_arg *arg)
0360 {
0361 u64 reg, ret_val, nsp_base, nsp_buffer, nsp_status, nsp_command;
0362 struct nfp_cpp *cpp = state->cpp;
0363 u32 nsp_cpp;
0364 int err;
0365
0366 nsp_cpp = nfp_resource_cpp_id(state->res);
0367 nsp_base = nfp_resource_address(state->res);
0368 nsp_status = nsp_base + NSP_STATUS;
0369 nsp_command = nsp_base + NSP_COMMAND;
0370 nsp_buffer = nsp_base + NSP_BUFFER;
0371
0372 err = nfp_nsp_check(state);
0373 if (err)
0374 return err;
0375
0376 err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_buffer, arg->buf);
0377 if (err < 0)
0378 return err;
0379
0380 err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_command,
0381 FIELD_PREP(NSP_COMMAND_OPTION, arg->option) |
0382 FIELD_PREP(NSP_COMMAND_CODE, arg->code) |
0383 FIELD_PREP(NSP_COMMAND_DMA_BUF, arg->dma) |
0384 FIELD_PREP(NSP_COMMAND_START, 1));
0385 if (err < 0)
0386 return err;
0387
0388
0389 err = nfp_nsp_wait_reg(cpp, ®, nsp_cpp, nsp_command,
0390 NSP_COMMAND_START, 0, NFP_NSP_TIMEOUT_DEFAULT);
0391 if (err) {
0392 nfp_err(cpp, "Error %d waiting for code 0x%04x to start\n",
0393 err, arg->code);
0394 return err;
0395 }
0396
0397
0398 err = nfp_nsp_wait_reg(cpp, ®, nsp_cpp, nsp_status, NSP_STATUS_BUSY,
0399 0, arg->timeout_sec ?: NFP_NSP_TIMEOUT_DEFAULT);
0400 if (err) {
0401 nfp_err(cpp, "Error %d waiting for code 0x%04x to complete\n",
0402 err, arg->code);
0403 return err;
0404 }
0405
0406 err = nfp_cpp_readq(cpp, nsp_cpp, nsp_command, &ret_val);
0407 if (err < 0)
0408 return err;
0409 ret_val = FIELD_GET(NSP_COMMAND_OPTION, ret_val);
0410
0411 err = FIELD_GET(NSP_STATUS_RESULT, reg);
0412 if (err) {
0413 if (!arg->error_quiet)
0414 nfp_warn(cpp, "Result (error) code set: %d (%d) command: %d\n",
0415 -err, (int)ret_val, arg->code);
0416
0417 if (arg->error_cb)
0418 arg->error_cb(state, ret_val);
0419 else
0420 nfp_nsp_print_extended_error(state, ret_val);
0421 return -err;
0422 }
0423
0424 return ret_val;
0425 }
0426
0427 static int nfp_nsp_command(struct nfp_nsp *state, u16 code)
0428 {
0429 const struct nfp_nsp_command_arg arg = {
0430 .code = code,
0431 };
0432
0433 return __nfp_nsp_command(state, &arg);
0434 }
0435
0436 static int
0437 nfp_nsp_command_buf_def(struct nfp_nsp *nsp,
0438 struct nfp_nsp_command_buf_arg *arg)
0439 {
0440 struct nfp_cpp *cpp = nsp->cpp;
0441 u64 reg, cpp_buf;
0442 int err, ret;
0443 u32 cpp_id;
0444
0445 err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res),
0446 nfp_resource_address(nsp->res) +
0447 NSP_DFLT_BUFFER,
0448 ®);
0449 if (err < 0)
0450 return err;
0451
0452 cpp_id = FIELD_GET(NSP_DFLT_BUFFER_CPP, reg) << 8;
0453 cpp_buf = FIELD_GET(NSP_DFLT_BUFFER_ADDRESS, reg);
0454
0455 if (arg->in_buf && arg->in_size) {
0456 err = nfp_cpp_write(cpp, cpp_id, cpp_buf,
0457 arg->in_buf, arg->in_size);
0458 if (err < 0)
0459 return err;
0460 }
0461
0462 if (arg->out_buf && arg->out_size && arg->out_size > arg->in_size) {
0463 err = nfp_cpp_write(cpp, cpp_id, cpp_buf + arg->in_size,
0464 arg->out_buf, arg->out_size - arg->in_size);
0465 if (err < 0)
0466 return err;
0467 }
0468
0469 if (!FIELD_FIT(NSP_BUFFER_CPP, cpp_id >> 8) ||
0470 !FIELD_FIT(NSP_BUFFER_ADDRESS, cpp_buf)) {
0471 nfp_err(cpp, "Buffer out of reach %08x %016llx\n",
0472 cpp_id, cpp_buf);
0473 return -EINVAL;
0474 }
0475
0476 arg->arg.buf = FIELD_PREP(NSP_BUFFER_CPP, cpp_id >> 8) |
0477 FIELD_PREP(NSP_BUFFER_ADDRESS, cpp_buf);
0478 ret = __nfp_nsp_command(nsp, &arg->arg);
0479 if (ret < 0)
0480 return ret;
0481
0482 if (arg->out_buf && arg->out_size) {
0483 err = nfp_cpp_read(cpp, cpp_id, cpp_buf,
0484 arg->out_buf, arg->out_size);
0485 if (err < 0)
0486 return err;
0487 }
0488
0489 return ret;
0490 }
0491
0492 static int
0493 nfp_nsp_command_buf_dma_sg(struct nfp_nsp *nsp,
0494 struct nfp_nsp_command_buf_arg *arg,
0495 unsigned int max_size, unsigned int chunk_order,
0496 unsigned int dma_order)
0497 {
0498 struct nfp_cpp *cpp = nsp->cpp;
0499 struct nfp_nsp_dma_buf *desc;
0500 struct {
0501 dma_addr_t dma_addr;
0502 unsigned long len;
0503 void *chunk;
0504 } *chunks;
0505 size_t chunk_size, dma_size;
0506 dma_addr_t dma_desc;
0507 struct device *dev;
0508 unsigned long off;
0509 int i, ret, nseg;
0510 size_t desc_sz;
0511
0512 chunk_size = BIT_ULL(chunk_order);
0513 dma_size = BIT_ULL(dma_order);
0514 nseg = DIV_ROUND_UP(max_size, chunk_size);
0515
0516 chunks = kcalloc(nseg, sizeof(*chunks), GFP_KERNEL);
0517 if (!chunks)
0518 return -ENOMEM;
0519
0520 off = 0;
0521 ret = -ENOMEM;
0522 for (i = 0; i < nseg; i++) {
0523 unsigned long coff;
0524
0525 chunks[i].chunk = kmalloc(chunk_size,
0526 GFP_KERNEL | __GFP_NOWARN);
0527 if (!chunks[i].chunk)
0528 goto exit_free_prev;
0529
0530 chunks[i].len = min_t(u64, chunk_size, max_size - off);
0531
0532 coff = 0;
0533 if (arg->in_size > off) {
0534 coff = min_t(u64, arg->in_size - off, chunk_size);
0535 memcpy(chunks[i].chunk, arg->in_buf + off, coff);
0536 }
0537 memset(chunks[i].chunk + coff, 0, chunk_size - coff);
0538
0539 off += chunks[i].len;
0540 }
0541
0542 dev = nfp_cpp_device(cpp)->parent;
0543
0544 for (i = 0; i < nseg; i++) {
0545 dma_addr_t addr;
0546
0547 addr = dma_map_single(dev, chunks[i].chunk, chunks[i].len,
0548 DMA_BIDIRECTIONAL);
0549 chunks[i].dma_addr = addr;
0550
0551 ret = dma_mapping_error(dev, addr);
0552 if (ret)
0553 goto exit_unmap_prev;
0554
0555 if (WARN_ONCE(round_down(addr, dma_size) !=
0556 round_down(addr + chunks[i].len - 1, dma_size),
0557 "unaligned DMA address: %pad %lu %zd\n",
0558 &addr, chunks[i].len, dma_size)) {
0559 ret = -EFAULT;
0560 i++;
0561 goto exit_unmap_prev;
0562 }
0563 }
0564
0565 desc_sz = struct_size(desc, descs, nseg);
0566 desc = kmalloc(desc_sz, GFP_KERNEL);
0567 if (!desc) {
0568 ret = -ENOMEM;
0569 goto exit_unmap_all;
0570 }
0571
0572 desc->chunk_cnt = cpu_to_le32(nseg);
0573 for (i = 0; i < nseg; i++) {
0574 desc->descs[i].size = cpu_to_le32(chunks[i].len);
0575 desc->descs[i].addr = cpu_to_le64(chunks[i].dma_addr);
0576 }
0577
0578 dma_desc = dma_map_single(dev, desc, desc_sz, DMA_TO_DEVICE);
0579 ret = dma_mapping_error(dev, dma_desc);
0580 if (ret)
0581 goto exit_free_desc;
0582
0583 arg->arg.dma = true;
0584 arg->arg.buf = dma_desc;
0585 ret = __nfp_nsp_command(nsp, &arg->arg);
0586 if (ret < 0)
0587 goto exit_unmap_desc;
0588
0589 i = 0;
0590 off = 0;
0591 while (off < arg->out_size) {
0592 unsigned int len;
0593
0594 len = min_t(u64, chunks[i].len, arg->out_size - off);
0595 memcpy(arg->out_buf + off, chunks[i].chunk, len);
0596 off += len;
0597 i++;
0598 }
0599
0600 exit_unmap_desc:
0601 dma_unmap_single(dev, dma_desc, desc_sz, DMA_TO_DEVICE);
0602 exit_free_desc:
0603 kfree(desc);
0604 exit_unmap_all:
0605 i = nseg;
0606 exit_unmap_prev:
0607 while (--i >= 0)
0608 dma_unmap_single(dev, chunks[i].dma_addr, chunks[i].len,
0609 DMA_BIDIRECTIONAL);
0610 i = nseg;
0611 exit_free_prev:
0612 while (--i >= 0)
0613 kfree(chunks[i].chunk);
0614 kfree(chunks);
0615 if (ret < 0)
0616 nfp_err(cpp, "NSP: SG DMA failed for command 0x%04x: %d (sz:%d cord:%d)\n",
0617 arg->arg.code, ret, max_size, chunk_order);
0618 return ret;
0619 }
0620
0621 static int
0622 nfp_nsp_command_buf_dma(struct nfp_nsp *nsp,
0623 struct nfp_nsp_command_buf_arg *arg,
0624 unsigned int max_size, unsigned int dma_order)
0625 {
0626 unsigned int chunk_order, buf_order;
0627 struct nfp_cpp *cpp = nsp->cpp;
0628 bool sg_ok;
0629 u64 reg;
0630 int err;
0631
0632 buf_order = order_base_2(roundup_pow_of_two(max_size));
0633
0634 err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res),
0635 nfp_resource_address(nsp->res) + NFP_CAP_CMD_DMA_SG,
0636 ®);
0637 if (err < 0)
0638 return err;
0639 sg_ok = reg & BIT_ULL(arg->arg.code - 1);
0640
0641 if (!sg_ok) {
0642 if (buf_order > dma_order) {
0643 nfp_err(cpp, "NSP: can't service non-SG DMA for command 0x%04x\n",
0644 arg->arg.code);
0645 return -ENOMEM;
0646 }
0647 chunk_order = buf_order;
0648 } else {
0649 chunk_order = min_t(unsigned int, dma_order, PAGE_SHIFT);
0650 }
0651
0652 return nfp_nsp_command_buf_dma_sg(nsp, arg, max_size, chunk_order,
0653 dma_order);
0654 }
0655
0656 static int
0657 nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg)
0658 {
0659 unsigned int dma_order, def_size, max_size;
0660 struct nfp_cpp *cpp = nsp->cpp;
0661 u64 reg;
0662 int err;
0663
0664 if (nsp->ver.minor < 13) {
0665 nfp_err(cpp, "NSP: Code 0x%04x with buffer not supported (ABI %hu.%hu)\n",
0666 arg->arg.code, nsp->ver.major, nsp->ver.minor);
0667 return -EOPNOTSUPP;
0668 }
0669
0670 err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res),
0671 nfp_resource_address(nsp->res) +
0672 NSP_DFLT_BUFFER_CONFIG,
0673 ®);
0674 if (err < 0)
0675 return err;
0676
0677
0678 if (arg->out_buf && arg->out_size && arg->out_size > arg->in_size)
0679 memset(arg->out_buf, 0, arg->out_size - arg->in_size);
0680
0681 max_size = max(arg->in_size, arg->out_size);
0682 def_size = FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M +
0683 FIELD_GET(NSP_DFLT_BUFFER_SIZE_4KB, reg) * SZ_4K;
0684 dma_order = FIELD_GET(NSP_DFLT_BUFFER_DMA_CHUNK_ORDER, reg);
0685 if (def_size >= max_size) {
0686 return nfp_nsp_command_buf_def(nsp, arg);
0687 } else if (!dma_order) {
0688 nfp_err(cpp, "NSP: default buffer too small for command 0x%04x (%u < %u)\n",
0689 arg->arg.code, def_size, max_size);
0690 return -EINVAL;
0691 }
0692
0693 return nfp_nsp_command_buf_dma(nsp, arg, max_size, dma_order);
0694 }
0695
0696 int nfp_nsp_wait(struct nfp_nsp *state)
0697 {
0698 const unsigned long wait_until = jiffies + NFP_NSP_TIMEOUT_BOOT * HZ;
0699 int err;
0700
0701 nfp_dbg(state->cpp, "Waiting for NSP to respond (%u sec max).\n",
0702 NFP_NSP_TIMEOUT_BOOT);
0703
0704 for (;;) {
0705 const unsigned long start_time = jiffies;
0706
0707 err = nfp_nsp_command(state, SPCODE_NOOP);
0708 if (err != -EAGAIN)
0709 break;
0710
0711 if (msleep_interruptible(25)) {
0712 err = -ERESTARTSYS;
0713 break;
0714 }
0715
0716 if (time_after(start_time, wait_until)) {
0717 err = -ETIMEDOUT;
0718 break;
0719 }
0720 }
0721 if (err)
0722 nfp_err(state->cpp, "NSP failed to respond %d\n", err);
0723
0724 return err;
0725 }
0726
0727 int nfp_nsp_device_soft_reset(struct nfp_nsp *state)
0728 {
0729 return nfp_nsp_command(state, SPCODE_SOFT_RESET);
0730 }
0731
0732 int nfp_nsp_mac_reinit(struct nfp_nsp *state)
0733 {
0734 return nfp_nsp_command(state, SPCODE_MAC_INIT);
0735 }
0736
0737 static void nfp_nsp_load_fw_extended_msg(struct nfp_nsp *state, u32 ret_val)
0738 {
0739 static const char * const major_msg[] = {
0740 "Firmware from driver loaded",
0741 "Firmware from flash loaded",
0742 "Firmware loading failure",
0743 };
0744 static const char * const minor_msg[] = {
0745 "",
0746 "no named partition on flash",
0747 "error reading from flash",
0748 "can not deflate",
0749 "not a trusted file",
0750 "can not parse FW file",
0751 "MIP not found in FW file",
0752 "null firmware name in MIP",
0753 "FW version none",
0754 "FW build number none",
0755 "no FW selection policy HWInfo key found",
0756 "static FW selection policy",
0757 "FW version has precedence",
0758 "different FW application load requested",
0759 "development build",
0760 };
0761 unsigned int major, minor;
0762 const char *level;
0763
0764 major = FIELD_GET(NFP_FW_LOAD_RET_MAJOR, ret_val);
0765 minor = FIELD_GET(NFP_FW_LOAD_RET_MINOR, ret_val);
0766
0767 if (!nfp_nsp_has_stored_fw_load(state))
0768 return;
0769
0770
0771 if (major == 0 && (minor == 0 || minor == 10))
0772 level = KERN_DEBUG;
0773 else if (major == 2)
0774 level = KERN_ERR;
0775 else
0776 level = KERN_INFO;
0777
0778 if (major >= ARRAY_SIZE(major_msg))
0779 nfp_printk(level, state->cpp, "FW loading status: %x\n",
0780 ret_val);
0781 else if (minor >= ARRAY_SIZE(minor_msg))
0782 nfp_printk(level, state->cpp, "%s, reason code: %d\n",
0783 major_msg[major], minor);
0784 else
0785 nfp_printk(level, state->cpp, "%s%c %s\n",
0786 major_msg[major], minor ? ',' : '.',
0787 minor_msg[minor]);
0788 }
0789
0790 int nfp_nsp_load_fw(struct nfp_nsp *state, const struct firmware *fw)
0791 {
0792 struct nfp_nsp_command_buf_arg load_fw = {
0793 {
0794 .code = SPCODE_FW_LOAD,
0795 .option = fw->size,
0796 .error_cb = nfp_nsp_load_fw_extended_msg,
0797 },
0798 .in_buf = fw->data,
0799 .in_size = fw->size,
0800 };
0801 int ret;
0802
0803 ret = nfp_nsp_command_buf(state, &load_fw);
0804 if (ret < 0)
0805 return ret;
0806
0807 nfp_nsp_load_fw_extended_msg(state, ret);
0808 return 0;
0809 }
0810
0811 int nfp_nsp_write_flash(struct nfp_nsp *state, const struct firmware *fw)
0812 {
0813 struct nfp_nsp_command_buf_arg write_flash = {
0814 {
0815 .code = SPCODE_NSP_WRITE_FLASH,
0816 .option = fw->size,
0817 .timeout_sec = 900,
0818 },
0819 .in_buf = fw->data,
0820 .in_size = fw->size,
0821 };
0822
0823 return nfp_nsp_command_buf(state, &write_flash);
0824 }
0825
0826 int nfp_nsp_read_eth_table(struct nfp_nsp *state, void *buf, unsigned int size)
0827 {
0828 struct nfp_nsp_command_buf_arg eth_rescan = {
0829 {
0830 .code = SPCODE_ETH_RESCAN,
0831 .option = size,
0832 },
0833 .out_buf = buf,
0834 .out_size = size,
0835 };
0836
0837 return nfp_nsp_command_buf(state, ð_rescan);
0838 }
0839
0840 int nfp_nsp_write_eth_table(struct nfp_nsp *state,
0841 const void *buf, unsigned int size)
0842 {
0843 struct nfp_nsp_command_buf_arg eth_ctrl = {
0844 {
0845 .code = SPCODE_ETH_CONTROL,
0846 .option = size,
0847 },
0848 .in_buf = buf,
0849 .in_size = size,
0850 };
0851
0852 return nfp_nsp_command_buf(state, ð_ctrl);
0853 }
0854
0855 int nfp_nsp_read_identify(struct nfp_nsp *state, void *buf, unsigned int size)
0856 {
0857 struct nfp_nsp_command_buf_arg identify = {
0858 {
0859 .code = SPCODE_NSP_IDENTIFY,
0860 .option = size,
0861 },
0862 .out_buf = buf,
0863 .out_size = size,
0864 };
0865
0866 return nfp_nsp_command_buf(state, &identify);
0867 }
0868
0869 int nfp_nsp_read_sensors(struct nfp_nsp *state, unsigned int sensor_mask,
0870 void *buf, unsigned int size)
0871 {
0872 struct nfp_nsp_command_buf_arg sensors = {
0873 {
0874 .code = SPCODE_NSP_SENSORS,
0875 .option = sensor_mask,
0876 },
0877 .out_buf = buf,
0878 .out_size = size,
0879 };
0880
0881 return nfp_nsp_command_buf(state, &sensors);
0882 }
0883
0884 int nfp_nsp_load_stored_fw(struct nfp_nsp *state)
0885 {
0886 const struct nfp_nsp_command_arg arg = {
0887 .code = SPCODE_FW_STORED,
0888 .error_cb = nfp_nsp_load_fw_extended_msg,
0889 };
0890 int ret;
0891
0892 ret = __nfp_nsp_command(state, &arg);
0893 if (ret < 0)
0894 return ret;
0895
0896 nfp_nsp_load_fw_extended_msg(state, ret);
0897 return 0;
0898 }
0899
0900 static int
0901 __nfp_nsp_hwinfo_lookup(struct nfp_nsp *state, void *buf, unsigned int size,
0902 bool optional)
0903 {
0904 struct nfp_nsp_command_buf_arg hwinfo_lookup = {
0905 {
0906 .code = SPCODE_HWINFO_LOOKUP,
0907 .option = size,
0908 .error_quiet = optional,
0909 },
0910 .in_buf = buf,
0911 .in_size = size,
0912 .out_buf = buf,
0913 .out_size = size,
0914 };
0915
0916 return nfp_nsp_command_buf(state, &hwinfo_lookup);
0917 }
0918
0919 int nfp_nsp_hwinfo_lookup(struct nfp_nsp *state, void *buf, unsigned int size)
0920 {
0921 int err;
0922
0923 size = min_t(u32, size, NFP_HWINFO_LOOKUP_SIZE);
0924
0925 err = __nfp_nsp_hwinfo_lookup(state, buf, size, false);
0926 if (err)
0927 return err;
0928
0929 if (strnlen(buf, size) == size) {
0930 nfp_err(state->cpp, "NSP HWinfo value not NULL-terminated\n");
0931 return -EINVAL;
0932 }
0933
0934 return 0;
0935 }
0936
0937 int nfp_nsp_hwinfo_lookup_optional(struct nfp_nsp *state, void *buf,
0938 unsigned int size, const char *default_val)
0939 {
0940 int err;
0941
0942
0943
0944
0945 if (strnlen(default_val, size) == size)
0946 return -EINVAL;
0947
0948 if (!nfp_nsp_has_hwinfo_lookup(state)) {
0949 strcpy(buf, default_val);
0950 return 0;
0951 }
0952
0953 size = min_t(u32, size, NFP_HWINFO_LOOKUP_SIZE);
0954
0955 err = __nfp_nsp_hwinfo_lookup(state, buf, size, true);
0956 if (err) {
0957 if (err == -ENOENT) {
0958 strcpy(buf, default_val);
0959 return 0;
0960 }
0961
0962 nfp_err(state->cpp, "NSP HWinfo lookup failed: %d\n", err);
0963 return err;
0964 }
0965
0966 if (strnlen(buf, size) == size) {
0967 nfp_err(state->cpp, "NSP HWinfo value not NULL-terminated\n");
0968 return -EINVAL;
0969 }
0970
0971 return 0;
0972 }
0973
0974 int nfp_nsp_hwinfo_set(struct nfp_nsp *state, void *buf, unsigned int size)
0975 {
0976 struct nfp_nsp_command_buf_arg hwinfo_set = {
0977 {
0978 .code = SPCODE_HWINFO_SET,
0979 .option = size,
0980 },
0981 .in_buf = buf,
0982 .in_size = size,
0983 };
0984
0985 return nfp_nsp_command_buf(state, &hwinfo_set);
0986 }
0987
0988 int nfp_nsp_fw_loaded(struct nfp_nsp *state)
0989 {
0990 const struct nfp_nsp_command_arg arg = {
0991 .code = SPCODE_FW_LOADED,
0992 };
0993
0994 return __nfp_nsp_command(state, &arg);
0995 }
0996
0997 int nfp_nsp_versions(struct nfp_nsp *state, void *buf, unsigned int size)
0998 {
0999 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
1011 const 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
1046 static 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
1063 int 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
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 }