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_VERSIONS = 21,
100 SPCODE_READ_SFF_EEPROM = 22,
101};
102
103struct nfp_nsp_dma_buf {
104 __le32 chunk_cnt;
105 __le32 reserved[3];
106 struct {
107 __le32 size;
108 __le32 reserved;
109 __le64 addr;
110 } descs[];
111};
112
113static const struct {
114 int code;
115 const char *msg;
116} nsp_errors[] = {
117 { 6010, "could not map to phy for port" },
118 { 6011, "not an allowed rate/lanes for port" },
119 { 6012, "not an allowed rate/lanes for port" },
120 { 6013, "high/low error, change other port first" },
121 { 6014, "config not found in flash" },
122};
123
124struct nfp_nsp {
125 struct nfp_cpp *cpp;
126 struct nfp_resource *res;
127 struct {
128 u16 major;
129 u16 minor;
130 } ver;
131
132
133 bool modified;
134 unsigned int idx;
135 void *entries;
136};
137
138
139
140
141
142
143
144
145
146
147struct nfp_nsp_command_arg {
148 u16 code;
149 bool dma;
150 unsigned int timeout_sec;
151 u32 option;
152 u64 buf;
153 void (*error_cb)(struct nfp_nsp *state, u32 ret_val);
154};
155
156
157
158
159
160
161
162
163
164struct nfp_nsp_command_buf_arg {
165 struct nfp_nsp_command_arg arg;
166 const void *in_buf;
167 unsigned int in_size;
168 void *out_buf;
169 unsigned int out_size;
170};
171
172struct nfp_cpp *nfp_nsp_cpp(struct nfp_nsp *state)
173{
174 return state->cpp;
175}
176
177bool nfp_nsp_config_modified(struct nfp_nsp *state)
178{
179 return state->modified;
180}
181
182void nfp_nsp_config_set_modified(struct nfp_nsp *state, bool modified)
183{
184 state->modified = modified;
185}
186
187void *nfp_nsp_config_entries(struct nfp_nsp *state)
188{
189 return state->entries;
190}
191
192unsigned int nfp_nsp_config_idx(struct nfp_nsp *state)
193{
194 return state->idx;
195}
196
197void
198nfp_nsp_config_set_state(struct nfp_nsp *state, void *entries, unsigned int idx)
199{
200 state->entries = entries;
201 state->idx = idx;
202}
203
204void nfp_nsp_config_clear_state(struct nfp_nsp *state)
205{
206 state->entries = NULL;
207 state->idx = 0;
208}
209
210static void nfp_nsp_print_extended_error(struct nfp_nsp *state, u32 ret_val)
211{
212 int i;
213
214 if (!ret_val)
215 return;
216
217 for (i = 0; i < ARRAY_SIZE(nsp_errors); i++)
218 if (ret_val == nsp_errors[i].code)
219 nfp_err(state->cpp, "err msg: %s\n", nsp_errors[i].msg);
220}
221
222static int nfp_nsp_check(struct nfp_nsp *state)
223{
224 struct nfp_cpp *cpp = state->cpp;
225 u64 nsp_status, reg;
226 u32 nsp_cpp;
227 int err;
228
229 nsp_cpp = nfp_resource_cpp_id(state->res);
230 nsp_status = nfp_resource_address(state->res) + NSP_STATUS;
231
232 err = nfp_cpp_readq(cpp, nsp_cpp, nsp_status, ®);
233 if (err < 0)
234 return err;
235
236 if (FIELD_GET(NSP_STATUS_MAGIC, reg) != NSP_MAGIC) {
237 nfp_err(cpp, "Cannot detect NFP Service Processor\n");
238 return -ENODEV;
239 }
240
241 state->ver.major = FIELD_GET(NSP_STATUS_MAJOR, reg);
242 state->ver.minor = FIELD_GET(NSP_STATUS_MINOR, reg);
243
244 if (state->ver.major != NSP_MAJOR) {
245 nfp_err(cpp, "Unsupported ABI %hu.%hu\n",
246 state->ver.major, state->ver.minor);
247 return -EINVAL;
248 }
249 if (state->ver.minor < NSP_MINOR) {
250 nfp_err(cpp, "ABI too old to support NIC operation (%u.%hu < %u.%u), please update the management FW on the flash\n",
251 NSP_MAJOR, state->ver.minor, NSP_MAJOR, NSP_MINOR);
252 return -EINVAL;
253 }
254
255 if (reg & NSP_STATUS_BUSY) {
256 nfp_err(cpp, "Service processor busy!\n");
257 return -EBUSY;
258 }
259
260 return 0;
261}
262
263
264
265
266
267struct nfp_nsp *nfp_nsp_open(struct nfp_cpp *cpp)
268{
269 struct nfp_resource *res;
270 struct nfp_nsp *state;
271 int err;
272
273 res = nfp_resource_acquire(cpp, NFP_RESOURCE_NSP);
274 if (IS_ERR(res))
275 return (void *)res;
276
277 state = kzalloc(sizeof(*state), GFP_KERNEL);
278 if (!state) {
279 nfp_resource_release(res);
280 return ERR_PTR(-ENOMEM);
281 }
282 state->cpp = cpp;
283 state->res = res;
284
285 err = nfp_nsp_check(state);
286 if (err) {
287 nfp_nsp_close(state);
288 return ERR_PTR(err);
289 }
290
291 return state;
292}
293
294
295
296
297
298void nfp_nsp_close(struct nfp_nsp *state)
299{
300 nfp_resource_release(state->res);
301 kfree(state);
302}
303
304u16 nfp_nsp_get_abi_ver_major(struct nfp_nsp *state)
305{
306 return state->ver.major;
307}
308
309u16 nfp_nsp_get_abi_ver_minor(struct nfp_nsp *state)
310{
311 return state->ver.minor;
312}
313
314static int
315nfp_nsp_wait_reg(struct nfp_cpp *cpp, u64 *reg, u32 nsp_cpp, u64 addr,
316 u64 mask, u64 val, u32 timeout_sec)
317{
318 const unsigned long wait_until = jiffies + timeout_sec * HZ;
319 int err;
320
321 for (;;) {
322 const unsigned long start_time = jiffies;
323
324 err = nfp_cpp_readq(cpp, nsp_cpp, addr, reg);
325 if (err < 0)
326 return err;
327
328 if ((*reg & mask) == val)
329 return 0;
330
331 msleep(25);
332
333 if (time_after(start_time, wait_until))
334 return -ETIMEDOUT;
335 }
336}
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353static int
354__nfp_nsp_command(struct nfp_nsp *state, const struct nfp_nsp_command_arg *arg)
355{
356 u64 reg, ret_val, nsp_base, nsp_buffer, nsp_status, nsp_command;
357 struct nfp_cpp *cpp = state->cpp;
358 u32 nsp_cpp;
359 int err;
360
361 nsp_cpp = nfp_resource_cpp_id(state->res);
362 nsp_base = nfp_resource_address(state->res);
363 nsp_status = nsp_base + NSP_STATUS;
364 nsp_command = nsp_base + NSP_COMMAND;
365 nsp_buffer = nsp_base + NSP_BUFFER;
366
367 err = nfp_nsp_check(state);
368 if (err)
369 return err;
370
371 err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_buffer, arg->buf);
372 if (err < 0)
373 return err;
374
375 err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_command,
376 FIELD_PREP(NSP_COMMAND_OPTION, arg->option) |
377 FIELD_PREP(NSP_COMMAND_CODE, arg->code) |
378 FIELD_PREP(NSP_COMMAND_DMA_BUF, arg->dma) |
379 FIELD_PREP(NSP_COMMAND_START, 1));
380 if (err < 0)
381 return err;
382
383
384 err = nfp_nsp_wait_reg(cpp, ®, nsp_cpp, nsp_command,
385 NSP_COMMAND_START, 0, NFP_NSP_TIMEOUT_DEFAULT);
386 if (err) {
387 nfp_err(cpp, "Error %d waiting for code 0x%04x to start\n",
388 err, arg->code);
389 return err;
390 }
391
392
393 err = nfp_nsp_wait_reg(cpp, ®, nsp_cpp, nsp_status, NSP_STATUS_BUSY,
394 0, arg->timeout_sec ?: NFP_NSP_TIMEOUT_DEFAULT);
395 if (err) {
396 nfp_err(cpp, "Error %d waiting for code 0x%04x to complete\n",
397 err, arg->code);
398 return err;
399 }
400
401 err = nfp_cpp_readq(cpp, nsp_cpp, nsp_command, &ret_val);
402 if (err < 0)
403 return err;
404 ret_val = FIELD_GET(NSP_COMMAND_OPTION, ret_val);
405
406 err = FIELD_GET(NSP_STATUS_RESULT, reg);
407 if (err) {
408 nfp_warn(cpp, "Result (error) code set: %d (%d) command: %d\n",
409 -err, (int)ret_val, arg->code);
410 if (arg->error_cb)
411 arg->error_cb(state, ret_val);
412 else
413 nfp_nsp_print_extended_error(state, ret_val);
414 return -err;
415 }
416
417 return ret_val;
418}
419
420static int nfp_nsp_command(struct nfp_nsp *state, u16 code)
421{
422 const struct nfp_nsp_command_arg arg = {
423 .code = code,
424 };
425
426 return __nfp_nsp_command(state, &arg);
427}
428
429static int
430nfp_nsp_command_buf_def(struct nfp_nsp *nsp,
431 struct nfp_nsp_command_buf_arg *arg)
432{
433 struct nfp_cpp *cpp = nsp->cpp;
434 u64 reg, cpp_buf;
435 int err, ret;
436 u32 cpp_id;
437
438 err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res),
439 nfp_resource_address(nsp->res) +
440 NSP_DFLT_BUFFER,
441 ®);
442 if (err < 0)
443 return err;
444
445 cpp_id = FIELD_GET(NSP_DFLT_BUFFER_CPP, reg) << 8;
446 cpp_buf = FIELD_GET(NSP_DFLT_BUFFER_ADDRESS, reg);
447
448 if (arg->in_buf && arg->in_size) {
449 err = nfp_cpp_write(cpp, cpp_id, cpp_buf,
450 arg->in_buf, arg->in_size);
451 if (err < 0)
452 return err;
453 }
454
455 if (arg->out_buf && arg->out_size && arg->out_size > arg->in_size) {
456 err = nfp_cpp_write(cpp, cpp_id, cpp_buf + arg->in_size,
457 arg->out_buf, arg->out_size - arg->in_size);
458 if (err < 0)
459 return err;
460 }
461
462 if (!FIELD_FIT(NSP_BUFFER_CPP, cpp_id >> 8) ||
463 !FIELD_FIT(NSP_BUFFER_ADDRESS, cpp_buf)) {
464 nfp_err(cpp, "Buffer out of reach %08x %016llx\n",
465 cpp_id, cpp_buf);
466 return -EINVAL;
467 }
468
469 arg->arg.buf = FIELD_PREP(NSP_BUFFER_CPP, cpp_id >> 8) |
470 FIELD_PREP(NSP_BUFFER_ADDRESS, cpp_buf);
471 ret = __nfp_nsp_command(nsp, &arg->arg);
472 if (ret < 0)
473 return ret;
474
475 if (arg->out_buf && arg->out_size) {
476 err = nfp_cpp_read(cpp, cpp_id, cpp_buf,
477 arg->out_buf, arg->out_size);
478 if (err < 0)
479 return err;
480 }
481
482 return ret;
483}
484
485static int
486nfp_nsp_command_buf_dma_sg(struct nfp_nsp *nsp,
487 struct nfp_nsp_command_buf_arg *arg,
488 unsigned int max_size, unsigned int chunk_order,
489 unsigned int dma_order)
490{
491 struct nfp_cpp *cpp = nsp->cpp;
492 struct nfp_nsp_dma_buf *desc;
493 struct {
494 dma_addr_t dma_addr;
495 unsigned long len;
496 void *chunk;
497 } *chunks;
498 size_t chunk_size, dma_size;
499 dma_addr_t dma_desc;
500 struct device *dev;
501 unsigned long off;
502 int i, ret, nseg;
503 size_t desc_sz;
504
505 chunk_size = BIT_ULL(chunk_order);
506 dma_size = BIT_ULL(dma_order);
507 nseg = DIV_ROUND_UP(max_size, chunk_size);
508
509 chunks = kzalloc(array_size(sizeof(*chunks), nseg), GFP_KERNEL);
510 if (!chunks)
511 return -ENOMEM;
512
513 off = 0;
514 ret = -ENOMEM;
515 for (i = 0; i < nseg; i++) {
516 unsigned long coff;
517
518 chunks[i].chunk = kmalloc(chunk_size,
519 GFP_KERNEL | __GFP_NOWARN);
520 if (!chunks[i].chunk)
521 goto exit_free_prev;
522
523 chunks[i].len = min_t(u64, chunk_size, max_size - off);
524
525 coff = 0;
526 if (arg->in_size > off) {
527 coff = min_t(u64, arg->in_size - off, chunk_size);
528 memcpy(chunks[i].chunk, arg->in_buf + off, coff);
529 }
530 memset(chunks[i].chunk + coff, 0, chunk_size - coff);
531
532 off += chunks[i].len;
533 }
534
535 dev = nfp_cpp_device(cpp)->parent;
536
537 for (i = 0; i < nseg; i++) {
538 dma_addr_t addr;
539
540 addr = dma_map_single(dev, chunks[i].chunk, chunks[i].len,
541 DMA_BIDIRECTIONAL);
542 chunks[i].dma_addr = addr;
543
544 ret = dma_mapping_error(dev, addr);
545 if (ret)
546 goto exit_unmap_prev;
547
548 if (WARN_ONCE(round_down(addr, dma_size) !=
549 round_down(addr + chunks[i].len - 1, dma_size),
550 "unaligned DMA address: %pad %lu %zd\n",
551 &addr, chunks[i].len, dma_size)) {
552 ret = -EFAULT;
553 i++;
554 goto exit_unmap_prev;
555 }
556 }
557
558 desc_sz = struct_size(desc, descs, nseg);
559 desc = kmalloc(desc_sz, GFP_KERNEL);
560 if (!desc) {
561 ret = -ENOMEM;
562 goto exit_unmap_all;
563 }
564
565 desc->chunk_cnt = cpu_to_le32(nseg);
566 for (i = 0; i < nseg; i++) {
567 desc->descs[i].size = cpu_to_le32(chunks[i].len);
568 desc->descs[i].addr = cpu_to_le64(chunks[i].dma_addr);
569 }
570
571 dma_desc = dma_map_single(dev, desc, desc_sz, DMA_TO_DEVICE);
572 ret = dma_mapping_error(dev, dma_desc);
573 if (ret)
574 goto exit_free_desc;
575
576 arg->arg.dma = true;
577 arg->arg.buf = dma_desc;
578 ret = __nfp_nsp_command(nsp, &arg->arg);
579 if (ret < 0)
580 goto exit_unmap_desc;
581
582 i = 0;
583 off = 0;
584 while (off < arg->out_size) {
585 unsigned int len;
586
587 len = min_t(u64, chunks[i].len, arg->out_size - off);
588 memcpy(arg->out_buf + off, chunks[i].chunk, len);
589 off += len;
590 i++;
591 }
592
593exit_unmap_desc:
594 dma_unmap_single(dev, dma_desc, desc_sz, DMA_TO_DEVICE);
595exit_free_desc:
596 kfree(desc);
597exit_unmap_all:
598 i = nseg;
599exit_unmap_prev:
600 while (--i >= 0)
601 dma_unmap_single(dev, chunks[i].dma_addr, chunks[i].len,
602 DMA_BIDIRECTIONAL);
603 i = nseg;
604exit_free_prev:
605 while (--i >= 0)
606 kfree(chunks[i].chunk);
607 kfree(chunks);
608 if (ret < 0)
609 nfp_err(cpp, "NSP: SG DMA failed for command 0x%04x: %d (sz:%d cord:%d)\n",
610 arg->arg.code, ret, max_size, chunk_order);
611 return ret;
612}
613
614static int
615nfp_nsp_command_buf_dma(struct nfp_nsp *nsp,
616 struct nfp_nsp_command_buf_arg *arg,
617 unsigned int max_size, unsigned int dma_order)
618{
619 unsigned int chunk_order, buf_order;
620 struct nfp_cpp *cpp = nsp->cpp;
621 bool sg_ok;
622 u64 reg;
623 int err;
624
625 buf_order = order_base_2(roundup_pow_of_two(max_size));
626
627 err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res),
628 nfp_resource_address(nsp->res) + NFP_CAP_CMD_DMA_SG,
629 ®);
630 if (err < 0)
631 return err;
632 sg_ok = reg & BIT_ULL(arg->arg.code - 1);
633
634 if (!sg_ok) {
635 if (buf_order > dma_order) {
636 nfp_err(cpp, "NSP: can't service non-SG DMA for command 0x%04x\n",
637 arg->arg.code);
638 return -ENOMEM;
639 }
640 chunk_order = buf_order;
641 } else {
642 chunk_order = min_t(unsigned int, dma_order, PAGE_SHIFT);
643 }
644
645 return nfp_nsp_command_buf_dma_sg(nsp, arg, max_size, chunk_order,
646 dma_order);
647}
648
649static int
650nfp_nsp_command_buf(struct nfp_nsp *nsp, struct nfp_nsp_command_buf_arg *arg)
651{
652 unsigned int dma_order, def_size, max_size;
653 struct nfp_cpp *cpp = nsp->cpp;
654 u64 reg;
655 int err;
656
657 if (nsp->ver.minor < 13) {
658 nfp_err(cpp, "NSP: Code 0x%04x with buffer not supported (ABI %hu.%hu)\n",
659 arg->arg.code, nsp->ver.major, nsp->ver.minor);
660 return -EOPNOTSUPP;
661 }
662
663 err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res),
664 nfp_resource_address(nsp->res) +
665 NSP_DFLT_BUFFER_CONFIG,
666 ®);
667 if (err < 0)
668 return err;
669
670
671 if (arg->out_buf && arg->out_size && arg->out_size > arg->in_size)
672 memset(arg->out_buf, 0, arg->out_size - arg->in_size);
673
674 max_size = max(arg->in_size, arg->out_size);
675 def_size = FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M +
676 FIELD_GET(NSP_DFLT_BUFFER_SIZE_4KB, reg) * SZ_4K;
677 dma_order = FIELD_GET(NSP_DFLT_BUFFER_DMA_CHUNK_ORDER, reg);
678 if (def_size >= max_size) {
679 return nfp_nsp_command_buf_def(nsp, arg);
680 } else if (!dma_order) {
681 nfp_err(cpp, "NSP: default buffer too small for command 0x%04x (%u < %u)\n",
682 arg->arg.code, def_size, max_size);
683 return -EINVAL;
684 }
685
686 return nfp_nsp_command_buf_dma(nsp, arg, max_size, dma_order);
687}
688
689int nfp_nsp_wait(struct nfp_nsp *state)
690{
691 const unsigned long wait_until = jiffies + NFP_NSP_TIMEOUT_BOOT * HZ;
692 int err;
693
694 nfp_dbg(state->cpp, "Waiting for NSP to respond (%u sec max).\n",
695 NFP_NSP_TIMEOUT_BOOT);
696
697 for (;;) {
698 const unsigned long start_time = jiffies;
699
700 err = nfp_nsp_command(state, SPCODE_NOOP);
701 if (err != -EAGAIN)
702 break;
703
704 if (msleep_interruptible(25)) {
705 err = -ERESTARTSYS;
706 break;
707 }
708
709 if (time_after(start_time, wait_until)) {
710 err = -ETIMEDOUT;
711 break;
712 }
713 }
714 if (err)
715 nfp_err(state->cpp, "NSP failed to respond %d\n", err);
716
717 return err;
718}
719
720int nfp_nsp_device_soft_reset(struct nfp_nsp *state)
721{
722 return nfp_nsp_command(state, SPCODE_SOFT_RESET);
723}
724
725int nfp_nsp_mac_reinit(struct nfp_nsp *state)
726{
727 return nfp_nsp_command(state, SPCODE_MAC_INIT);
728}
729
730static void nfp_nsp_load_fw_extended_msg(struct nfp_nsp *state, u32 ret_val)
731{
732 static const char * const major_msg[] = {
733 "Firmware from driver loaded",
734 "Firmware from flash loaded",
735 "Firmware loading failure",
736 };
737 static const char * const minor_msg[] = {
738 "",
739 "no named partition on flash",
740 "error reading from flash",
741 "can not deflate",
742 "not a trusted file",
743 "can not parse FW file",
744 "MIP not found in FW file",
745 "null firmware name in MIP",
746 "FW version none",
747 "FW build number none",
748 "no FW selection policy HWInfo key found",
749 "static FW selection policy",
750 "FW version has precedence",
751 "different FW application load requested",
752 "development build",
753 };
754 unsigned int major, minor;
755 const char *level;
756
757 major = FIELD_GET(NFP_FW_LOAD_RET_MAJOR, ret_val);
758 minor = FIELD_GET(NFP_FW_LOAD_RET_MINOR, ret_val);
759
760 if (!nfp_nsp_has_stored_fw_load(state))
761 return;
762
763
764 if (major == 0 && (minor == 0 || minor == 10))
765 level = KERN_DEBUG;
766 else if (major == 2)
767 level = KERN_ERR;
768 else
769 level = KERN_INFO;
770
771 if (major >= ARRAY_SIZE(major_msg))
772 nfp_printk(level, state->cpp, "FW loading status: %x\n",
773 ret_val);
774 else if (minor >= ARRAY_SIZE(minor_msg))
775 nfp_printk(level, state->cpp, "%s, reason code: %d\n",
776 major_msg[major], minor);
777 else
778 nfp_printk(level, state->cpp, "%s%c %s\n",
779 major_msg[major], minor ? ',' : '.',
780 minor_msg[minor]);
781}
782
783int nfp_nsp_load_fw(struct nfp_nsp *state, const struct firmware *fw)
784{
785 struct nfp_nsp_command_buf_arg load_fw = {
786 {
787 .code = SPCODE_FW_LOAD,
788 .option = fw->size,
789 .error_cb = nfp_nsp_load_fw_extended_msg,
790 },
791 .in_buf = fw->data,
792 .in_size = fw->size,
793 };
794 int ret;
795
796 ret = nfp_nsp_command_buf(state, &load_fw);
797 if (ret < 0)
798 return ret;
799
800 nfp_nsp_load_fw_extended_msg(state, ret);
801 return 0;
802}
803
804int nfp_nsp_write_flash(struct nfp_nsp *state, const struct firmware *fw)
805{
806 struct nfp_nsp_command_buf_arg write_flash = {
807 {
808 .code = SPCODE_NSP_WRITE_FLASH,
809 .option = fw->size,
810 .timeout_sec = 900,
811 },
812 .in_buf = fw->data,
813 .in_size = fw->size,
814 };
815
816 return nfp_nsp_command_buf(state, &write_flash);
817}
818
819int nfp_nsp_read_eth_table(struct nfp_nsp *state, void *buf, unsigned int size)
820{
821 struct nfp_nsp_command_buf_arg eth_rescan = {
822 {
823 .code = SPCODE_ETH_RESCAN,
824 .option = size,
825 },
826 .out_buf = buf,
827 .out_size = size,
828 };
829
830 return nfp_nsp_command_buf(state, ð_rescan);
831}
832
833int nfp_nsp_write_eth_table(struct nfp_nsp *state,
834 const void *buf, unsigned int size)
835{
836 struct nfp_nsp_command_buf_arg eth_ctrl = {
837 {
838 .code = SPCODE_ETH_CONTROL,
839 .option = size,
840 },
841 .in_buf = buf,
842 .in_size = size,
843 };
844
845 return nfp_nsp_command_buf(state, ð_ctrl);
846}
847
848int nfp_nsp_read_identify(struct nfp_nsp *state, void *buf, unsigned int size)
849{
850 struct nfp_nsp_command_buf_arg identify = {
851 {
852 .code = SPCODE_NSP_IDENTIFY,
853 .option = size,
854 },
855 .out_buf = buf,
856 .out_size = size,
857 };
858
859 return nfp_nsp_command_buf(state, &identify);
860}
861
862int nfp_nsp_read_sensors(struct nfp_nsp *state, unsigned int sensor_mask,
863 void *buf, unsigned int size)
864{
865 struct nfp_nsp_command_buf_arg sensors = {
866 {
867 .code = SPCODE_NSP_SENSORS,
868 .option = sensor_mask,
869 },
870 .out_buf = buf,
871 .out_size = size,
872 };
873
874 return nfp_nsp_command_buf(state, &sensors);
875}
876
877int nfp_nsp_load_stored_fw(struct nfp_nsp *state)
878{
879 const struct nfp_nsp_command_arg arg = {
880 .code = SPCODE_FW_STORED,
881 .error_cb = nfp_nsp_load_fw_extended_msg,
882 };
883 int ret;
884
885 ret = __nfp_nsp_command(state, &arg);
886 if (ret < 0)
887 return ret;
888
889 nfp_nsp_load_fw_extended_msg(state, ret);
890 return 0;
891}
892
893static int
894__nfp_nsp_hwinfo_lookup(struct nfp_nsp *state, void *buf, unsigned int size)
895{
896 struct nfp_nsp_command_buf_arg hwinfo_lookup = {
897 {
898 .code = SPCODE_HWINFO_LOOKUP,
899 .option = size,
900 },
901 .in_buf = buf,
902 .in_size = size,
903 .out_buf = buf,
904 .out_size = size,
905 };
906
907 return nfp_nsp_command_buf(state, &hwinfo_lookup);
908}
909
910int nfp_nsp_hwinfo_lookup(struct nfp_nsp *state, void *buf, unsigned int size)
911{
912 int err;
913
914 size = min_t(u32, size, NFP_HWINFO_LOOKUP_SIZE);
915
916 err = __nfp_nsp_hwinfo_lookup(state, buf, size);
917 if (err)
918 return err;
919
920 if (strnlen(buf, size) == size) {
921 nfp_err(state->cpp, "NSP HWinfo value not NULL-terminated\n");
922 return -EINVAL;
923 }
924
925 return 0;
926}
927
928int nfp_nsp_versions(struct nfp_nsp *state, void *buf, unsigned int size)
929{
930 struct nfp_nsp_command_buf_arg versions = {
931 {
932 .code = SPCODE_VERSIONS,
933 .option = min_t(u32, size, NFP_VERSIONS_SIZE),
934 },
935 .out_buf = buf,
936 .out_size = min_t(u32, size, NFP_VERSIONS_SIZE),
937 };
938
939 return nfp_nsp_command_buf(state, &versions);
940}
941
942const char *nfp_nsp_versions_get(enum nfp_nsp_versions id, bool flash,
943 const u8 *buf, unsigned int size)
944{
945 static const u32 id2off[] = {
946 [NFP_VERSIONS_BSP] = NFP_VERSIONS_BSP_OFF,
947 [NFP_VERSIONS_CPLD] = NFP_VERSIONS_CPLD_OFF,
948 [NFP_VERSIONS_APP] = NFP_VERSIONS_APP_OFF,
949 [NFP_VERSIONS_BUNDLE] = NFP_VERSIONS_BUNDLE_OFF,
950 [NFP_VERSIONS_UNDI] = NFP_VERSIONS_UNDI_OFF,
951 [NFP_VERSIONS_NCSI] = NFP_VERSIONS_NCSI_OFF,
952 [NFP_VERSIONS_CFGR] = NFP_VERSIONS_CFGR_OFF,
953 };
954 unsigned int field, buf_field_cnt, buf_off;
955
956 if (id >= ARRAY_SIZE(id2off) || !id2off[id])
957 return ERR_PTR(-EINVAL);
958
959 field = id * 2 + flash;
960
961 buf_field_cnt = get_unaligned_le16(buf);
962 if (buf_field_cnt <= field)
963 return ERR_PTR(-ENOENT);
964
965 buf_off = get_unaligned_le16(buf + id2off[id] + flash * 2);
966 if (!buf_off)
967 return ERR_PTR(-ENOENT);
968
969 if (buf_off >= size)
970 return ERR_PTR(-EINVAL);
971 if (strnlen(&buf[buf_off], size - buf_off) == size - buf_off)
972 return ERR_PTR(-EINVAL);
973
974 return (const char *)&buf[buf_off];
975}
976
977static int
978__nfp_nsp_module_eeprom(struct nfp_nsp *state, void *buf, unsigned int size)
979{
980 struct nfp_nsp_command_buf_arg module_eeprom = {
981 {
982 .code = SPCODE_READ_SFF_EEPROM,
983 .option = size,
984 },
985 .in_buf = buf,
986 .in_size = size,
987 .out_buf = buf,
988 .out_size = size,
989 };
990
991 return nfp_nsp_command_buf(state, &module_eeprom);
992}
993
994int nfp_nsp_read_module_eeprom(struct nfp_nsp *state, int eth_index,
995 unsigned int offset, void *data,
996 unsigned int len, unsigned int *read_len)
997{
998 struct eeprom_buf {
999 u8 metalen;
1000 __le16 length;
1001 __le16 offset;
1002 __le16 readlen;
1003 u8 eth_index;
1004 u8 data[0];
1005 } __packed *buf;
1006 int bufsz, ret;
1007
1008 BUILD_BUG_ON(offsetof(struct eeprom_buf, data) % 8);
1009
1010
1011 bufsz = struct_size(buf, data, round_up(len, NSP_SFF_EEPROM_BLOCK_LEN));
1012 buf = kzalloc(bufsz, GFP_KERNEL);
1013 if (!buf)
1014 return -ENOMEM;
1015
1016 buf->metalen =
1017 offsetof(struct eeprom_buf, data) / NSP_SFF_EEPROM_BLOCK_LEN;
1018 buf->length = cpu_to_le16(len);
1019 buf->offset = cpu_to_le16(offset);
1020 buf->eth_index = eth_index;
1021
1022 ret = __nfp_nsp_module_eeprom(state, buf, bufsz);
1023
1024 *read_len = min_t(unsigned int, len, le16_to_cpu(buf->readlen));
1025 if (*read_len)
1026 memcpy(data, buf->data, *read_len);
1027
1028 if (!ret && *read_len < len)
1029 ret = -EIO;
1030
1031 kfree(buf);
1032
1033 return ret;
1034}
1035