hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c
....@@ -1,35 +1,5 @@
1
-/*
2
- * Copyright (C) 2015-2017 Netronome Systems, Inc.
3
- *
4
- * This software is dual licensed under the GNU General License Version 2,
5
- * June 1991 as shown in the file COPYING in the top-level directory of this
6
- * source tree or the BSD 2-Clause License provided below. You have the
7
- * option to license this software under the complete terms of either license.
8
- *
9
- * The BSD 2-Clause License:
10
- *
11
- * Redistribution and use in source and binary forms, with or
12
- * without modification, are permitted provided that the following
13
- * conditions are met:
14
- *
15
- * 1. Redistributions of source code must retain the above
16
- * copyright notice, this list of conditions and the following
17
- * disclaimer.
18
- *
19
- * 2. Redistributions in binary form must reproduce the above
20
- * copyright notice, this list of conditions and the following
21
- * disclaimer in the documentation and/or other materials
22
- * provided with the distribution.
23
- *
24
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31
- * SOFTWARE.
32
- */
1
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2
+/* Copyright (C) 2015-2018 Netronome Systems, Inc. */
333
344 /*
355 * nfp_nsp.c
....@@ -37,11 +7,13 @@
377 * Jason McMullan <jason.mcmullan@netronome.com>
388 */
399
10
+#include <asm/unaligned.h>
4011 #include <linux/bitfield.h>
4112 #include <linux/delay.h>
4213 #include <linux/firmware.h>
4314 #include <linux/kernel.h>
4415 #include <linux/kthread.h>
16
+#include <linux/overflow.h>
4517 #include <linux/sizes.h>
4618 #include <linux/slab.h>
4719
....@@ -66,6 +38,7 @@
6638 #define NSP_COMMAND 0x08
6739 #define NSP_COMMAND_OPTION GENMASK_ULL(63, 32)
6840 #define NSP_COMMAND_CODE GENMASK_ULL(31, 16)
41
+#define NSP_COMMAND_DMA_BUF BIT_ULL(1)
6942 #define NSP_COMMAND_START BIT_ULL(0)
7043
7144 /* CPP address to retrieve the data from */
....@@ -78,7 +51,11 @@
7851 #define NSP_DFLT_BUFFER_ADDRESS GENMASK_ULL(39, 0)
7952
8053 #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)
8156 #define NSP_DFLT_BUFFER_SIZE_MB GENMASK_ULL(7, 0)
57
+
58
+#define NFP_CAP_CMD_DMA_SG 0x28
8259
8360 #define NSP_MAGIC 0xab10
8461 #define NSP_MAJOR 0
....@@ -86,6 +63,23 @@
8663
8764 #define NSP_CODE_MAJOR GENMASK(15, 12)
8865 #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
8983
9084 enum nfp_nsp_cmd {
9185 SPCODE_NOOP = 0, /* No operation */
....@@ -100,6 +94,22 @@
10094 SPCODE_NSP_WRITE_FLASH = 11, /* Load and flash image from buffer */
10195 SPCODE_NSP_SENSORS = 12, /* Read NSP sensor(s) */
10296 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
+
105
+struct 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[];
103113 };
104114
105115 static const struct {
....@@ -125,6 +135,43 @@
125135 bool modified;
126136 unsigned int idx;
127137 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
+ */
151
+struct 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
+ */
169
+struct 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;
128175 };
129176
130177 struct nfp_cpp *nfp_nsp_cpp(struct nfp_nsp *state)
....@@ -199,9 +246,14 @@
199246 state->ver.major = FIELD_GET(NSP_STATUS_MAJOR, reg);
200247 state->ver.minor = FIELD_GET(NSP_STATUS_MINOR, reg);
201248
202
- if (state->ver.major != NSP_MAJOR || state->ver.minor < NSP_MINOR) {
249
+ if (state->ver.major != NSP_MAJOR) {
203250 nfp_err(cpp, "Unsupported ABI %hu.%hu\n",
204251 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);
205257 return -EINVAL;
206258 }
207259
....@@ -291,11 +343,7 @@
291343 /**
292344 * __nfp_nsp_command() - Execute a command on the NFP Service Processor
293345 * @state: NFP SP state
294
- * @code: NFP SP Command Code
295
- * @option: NFP SP Command Argument
296
- * @buff_cpp: NFP SP Buffer CPP Address info
297
- * @buff_addr: NFP SP Buffer Host address
298
- * @timeout_sec:Timeout value to wait for completion in seconds
346
+ * @arg: NFP command argument structure
299347 *
300348 * Return: 0 for success with no result
301349 *
....@@ -308,8 +356,7 @@
308356 * -ETIMEDOUT if the NSP took longer than @timeout_sec seconds to complete
309357 */
310358 static int
311
-__nfp_nsp_command(struct nfp_nsp *state, u16 code, u32 option, u32 buff_cpp,
312
- u64 buff_addr, u32 timeout_sec)
359
+__nfp_nsp_command(struct nfp_nsp *state, const struct nfp_nsp_command_arg *arg)
313360 {
314361 u64 reg, ret_val, nsp_base, nsp_buffer, nsp_status, nsp_command;
315362 struct nfp_cpp *cpp = state->cpp;
....@@ -326,22 +373,14 @@
326373 if (err)
327374 return err;
328375
329
- if (!FIELD_FIT(NSP_BUFFER_CPP, buff_cpp >> 8) ||
330
- !FIELD_FIT(NSP_BUFFER_ADDRESS, buff_addr)) {
331
- nfp_err(cpp, "Host buffer out of reach %08x %016llx\n",
332
- buff_cpp, buff_addr);
333
- return -EINVAL;
334
- }
335
-
336
- err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_buffer,
337
- FIELD_PREP(NSP_BUFFER_CPP, buff_cpp >> 8) |
338
- FIELD_PREP(NSP_BUFFER_ADDRESS, buff_addr));
376
+ err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_buffer, arg->buf);
339377 if (err < 0)
340378 return err;
341379
342380 err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_command,
343
- FIELD_PREP(NSP_COMMAND_OPTION, option) |
344
- FIELD_PREP(NSP_COMMAND_CODE, code) |
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) |
345384 FIELD_PREP(NSP_COMMAND_START, 1));
346385 if (err < 0)
347386 return err;
....@@ -351,16 +390,16 @@
351390 NSP_COMMAND_START, 0, NFP_NSP_TIMEOUT_DEFAULT);
352391 if (err) {
353392 nfp_err(cpp, "Error %d waiting for code 0x%04x to start\n",
354
- err, code);
393
+ err, arg->code);
355394 return err;
356395 }
357396
358397 /* Wait for NSP_STATUS_BUSY to go to 0 */
359398 err = nfp_nsp_wait_reg(cpp, &reg, nsp_cpp, nsp_status, NSP_STATUS_BUSY,
360
- 0, timeout_sec);
399
+ 0, arg->timeout_sec ?: NFP_NSP_TIMEOUT_DEFAULT);
361400 if (err) {
362401 nfp_err(cpp, "Error %d waiting for code 0x%04x to complete\n",
363
- err, code);
402
+ err, arg->code);
364403 return err;
365404 }
366405
....@@ -371,54 +410,37 @@
371410
372411 err = FIELD_GET(NSP_STATUS_RESULT, reg);
373412 if (err) {
374
- nfp_warn(cpp, "Result (error) code set: %d (%d) command: %d\n",
375
- -err, (int)ret_val, code);
376
- nfp_nsp_print_extended_error(state, ret_val);
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);
377421 return -err;
378422 }
379423
380424 return ret_val;
381425 }
382426
383
-static int
384
-nfp_nsp_command(struct nfp_nsp *state, u16 code, u32 option, u32 buff_cpp,
385
- u64 buff_addr)
427
+static int nfp_nsp_command(struct nfp_nsp *state, u16 code)
386428 {
387
- return __nfp_nsp_command(state, code, option, buff_cpp, buff_addr,
388
- NFP_NSP_TIMEOUT_DEFAULT);
429
+ const struct nfp_nsp_command_arg arg = {
430
+ .code = code,
431
+ };
432
+
433
+ return __nfp_nsp_command(state, &arg);
389434 }
390435
391436 static int
392
-__nfp_nsp_command_buf(struct nfp_nsp *nsp, u16 code, u32 option,
393
- const void *in_buf, unsigned int in_size, void *out_buf,
394
- unsigned int out_size, u32 timeout_sec)
437
+nfp_nsp_command_buf_def(struct nfp_nsp *nsp,
438
+ struct nfp_nsp_command_buf_arg *arg)
395439 {
396440 struct nfp_cpp *cpp = nsp->cpp;
397
- unsigned int max_size;
398441 u64 reg, cpp_buf;
399
- int ret, err;
442
+ int err, ret;
400443 u32 cpp_id;
401
-
402
- if (nsp->ver.minor < 13) {
403
- nfp_err(cpp, "NSP: Code 0x%04x with buffer not supported (ABI %hu.%hu)\n",
404
- code, nsp->ver.major, nsp->ver.minor);
405
- return -EOPNOTSUPP;
406
- }
407
-
408
- err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res),
409
- nfp_resource_address(nsp->res) +
410
- NSP_DFLT_BUFFER_CONFIG,
411
- &reg);
412
- if (err < 0)
413
- return err;
414
-
415
- max_size = max(in_size, out_size);
416
- if (FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M < max_size) {
417
- nfp_err(cpp, "NSP: default buffer too small for command 0x%04x (%llu < %u)\n",
418
- code, FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M,
419
- max_size);
420
- return -EINVAL;
421
- }
422444
423445 err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res),
424446 nfp_resource_address(nsp->res) +
....@@ -430,27 +452,36 @@
430452 cpp_id = FIELD_GET(NSP_DFLT_BUFFER_CPP, reg) << 8;
431453 cpp_buf = FIELD_GET(NSP_DFLT_BUFFER_ADDRESS, reg);
432454
433
- if (in_buf && in_size) {
434
- err = nfp_cpp_write(cpp, cpp_id, cpp_buf, in_buf, in_size);
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);
435458 if (err < 0)
436459 return err;
437460 }
438461 /* Zero out remaining part of the buffer */
439
- if (out_buf && out_size && out_size > in_size) {
440
- memset(out_buf, 0, out_size - in_size);
441
- err = nfp_cpp_write(cpp, cpp_id, cpp_buf + in_size,
442
- out_buf, out_size - in_size);
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);
443465 if (err < 0)
444466 return err;
445467 }
446468
447
- ret = __nfp_nsp_command(nsp, code, option, cpp_id, cpp_buf,
448
- timeout_sec);
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);
449479 if (ret < 0)
450480 return ret;
451481
452
- if (out_buf && out_size) {
453
- err = nfp_cpp_read(cpp, cpp_id, cpp_buf, out_buf, out_size);
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);
454485 if (err < 0)
455486 return err;
456487 }
....@@ -459,13 +490,207 @@
459490 }
460491
461492 static int
462
-nfp_nsp_command_buf(struct nfp_nsp *nsp, u16 code, u32 option,
463
- const void *in_buf, unsigned int in_size, void *out_buf,
464
- unsigned int out_size)
493
+nfp_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)
465497 {
466
- return __nfp_nsp_command_buf(nsp, code, option, in_buf, in_size,
467
- out_buf, out_size,
468
- NFP_NSP_TIMEOUT_DEFAULT);
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
+
600
+exit_unmap_desc:
601
+ dma_unmap_single(dev, dma_desc, desc_sz, DMA_TO_DEVICE);
602
+exit_free_desc:
603
+ kfree(desc);
604
+exit_unmap_all:
605
+ i = nseg;
606
+exit_unmap_prev:
607
+ while (--i >= 0)
608
+ dma_unmap_single(dev, chunks[i].dma_addr, chunks[i].len,
609
+ DMA_BIDIRECTIONAL);
610
+ i = nseg;
611
+exit_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
+
621
+static int
622
+nfp_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
+ &reg);
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
+
656
+static int
657
+nfp_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
+ &reg);
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);
469694 }
470695
471696 int nfp_nsp_wait(struct nfp_nsp *state)
....@@ -479,7 +704,7 @@
479704 for (;;) {
480705 const unsigned long start_time = jiffies;
481706
482
- err = nfp_nsp_command(state, SPCODE_NOOP, 0, 0, 0);
707
+ err = nfp_nsp_command(state, SPCODE_NOOP);
483708 if (err != -EAGAIN)
484709 break;
485710
....@@ -501,53 +726,378 @@
501726
502727 int nfp_nsp_device_soft_reset(struct nfp_nsp *state)
503728 {
504
- return nfp_nsp_command(state, SPCODE_SOFT_RESET, 0, 0, 0);
729
+ return nfp_nsp_command(state, SPCODE_SOFT_RESET);
505730 }
506731
507732 int nfp_nsp_mac_reinit(struct nfp_nsp *state)
508733 {
509
- return nfp_nsp_command(state, SPCODE_MAC_INIT, 0, 0, 0);
734
+ return nfp_nsp_command(state, SPCODE_MAC_INIT);
735
+}
736
+
737
+static 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]);
510788 }
511789
512790 int nfp_nsp_load_fw(struct nfp_nsp *state, const struct firmware *fw)
513791 {
514
- return nfp_nsp_command_buf(state, SPCODE_FW_LOAD, fw->size, fw->data,
515
- fw->size, NULL, 0);
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;
516809 }
517810
518811 int nfp_nsp_write_flash(struct nfp_nsp *state, const struct firmware *fw)
519812 {
520
- /* The flash time is specified to take a maximum of 70s so we add an
521
- * additional factor to this spec time.
522
- */
523
- u32 timeout_sec = 2.5 * 70;
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
+ };
524822
525
- return __nfp_nsp_command_buf(state, SPCODE_NSP_WRITE_FLASH, fw->size,
526
- fw->data, fw->size, NULL, 0, timeout_sec);
823
+ return nfp_nsp_command_buf(state, &write_flash);
527824 }
528825
529826 int nfp_nsp_read_eth_table(struct nfp_nsp *state, void *buf, unsigned int size)
530827 {
531
- return nfp_nsp_command_buf(state, SPCODE_ETH_RESCAN, size, NULL, 0,
532
- buf, size);
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, &eth_rescan);
533838 }
534839
535840 int nfp_nsp_write_eth_table(struct nfp_nsp *state,
536841 const void *buf, unsigned int size)
537842 {
538
- return nfp_nsp_command_buf(state, SPCODE_ETH_CONTROL, size, buf, size,
539
- NULL, 0);
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, &eth_ctrl);
540853 }
541854
542855 int nfp_nsp_read_identify(struct nfp_nsp *state, void *buf, unsigned int size)
543856 {
544
- return nfp_nsp_command_buf(state, SPCODE_NSP_IDENTIFY, size, NULL, 0,
545
- buf, size);
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);
546867 }
547868
548869 int nfp_nsp_read_sensors(struct nfp_nsp *state, unsigned int sensor_mask,
549870 void *buf, unsigned int size)
550871 {
551
- return nfp_nsp_command_buf(state, SPCODE_NSP_SENSORS, sensor_mask,
552
- NULL, 0, buf, size);
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
+
884
+int 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
+
900
+static 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
+
919
+int 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
+
937
+int 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
+
974
+int 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
+
988
+int 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
+
997
+int 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
+
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[0];
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;
5531103 }