1
2
3
4
5
6
7
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
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
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,
86 SPCODE_SOFT_RESET = 1,
87 SPCODE_FW_DEFAULT = 2,
88 SPCODE_PHY_INIT = 3,
89 SPCODE_MAC_INIT = 4,
90 SPCODE_PHY_RXADAPT = 5,
91 SPCODE_FW_LOAD = 6,
92 SPCODE_ETH_RESCAN = 7,
93 SPCODE_ETH_CONTROL = 8,
94 SPCODE_NSP_WRITE_FLASH = 11,
95 SPCODE_NSP_SENSORS = 12,
96 SPCODE_NSP_IDENTIFY = 13,
97 SPCODE_FW_STORED = 16,
98 SPCODE_HWINFO_LOOKUP = 17,
99 SPCODE_HWINFO_SET = 18,
100 SPCODE_FW_LOADED = 19,
101 SPCODE_VERSIONS = 21,
102 SPCODE_READ_SFF_EEPROM = 22,
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
135 bool modified;
136 unsigned int idx;
137 void *entries;
138};
139
140
141
142
143
144
145
146
147
148
149
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
163
164
165
166
167
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
270
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
301
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
345
346
347
348
349
350
351
352
353
354
355
356
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
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
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
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 = kzalloc(array_size(sizeof(*chunks), nseg), 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
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 "Firmware from driver loaded",
741 "Firmware from flash loaded",
742 "Firmware loading failure",
743 };
744 static const char * const minor_msg[] = {
745 "",
746 "no named partition on flash",
747 "error reading from flash",
748 "can not deflate",
749 "not a trusted file",
750 "can not parse FW file",
751 "MIP not found in FW file",
752 "null firmware name in MIP",
753 "FW version none",
754 "FW build number none",
755 "no FW selection policy HWInfo key found",
756 "static FW selection policy",
757 "FW version has precedence",
758 "different FW application load requested",
759 "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
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
943
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
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}
1104