Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2018 Netronome Systems, Inc.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "nfp_nsp.h"
7 : :
8 : : #include <nfp_platform.h>
9 : : #include <rte_common.h>
10 : :
11 : : #include "nfp_logs.h"
12 : : #include "nfp_resource.h"
13 : :
14 : : /* Offsets relative to the CSR base */
15 : : #define NSP_STATUS 0x00
16 : : #define NSP_STATUS_MAGIC GENMASK_ULL(63, 48)
17 : : #define NSP_STATUS_MAJOR GENMASK_ULL(47, 44)
18 : : #define NSP_STATUS_MINOR GENMASK_ULL(43, 32)
19 : : #define NSP_STATUS_CODE GENMASK_ULL(31, 16)
20 : : #define NSP_STATUS_RESULT GENMASK_ULL(15, 8)
21 : : #define NSP_STATUS_BUSY RTE_BIT64(0)
22 : :
23 : : #define NSP_COMMAND 0x08
24 : : #define NSP_COMMAND_OPTION GENMASK_ULL(63, 32)
25 : : #define NSP_COMMAND_VER_MAJOR GENMASK_ULL(31, 28)
26 : : #define NSP_COMMAND_CODE GENMASK_ULL(27, 16)
27 : : #define NSP_COMMAND_DMA_BUF RTE_BIT64(1)
28 : : #define NSP_COMMAND_START RTE_BIT64(0)
29 : :
30 : : /* CPP address to retrieve the data from */
31 : : #define NSP_BUFFER 0x10
32 : : #define NSP_BUFFER_CPP GENMASK_ULL(63, 40)
33 : : #define NSP_BUFFER_ADDRESS GENMASK_ULL(39, 0)
34 : :
35 : : #define NSP_DFLT_BUFFER 0x18
36 : : #define NSP_DFLT_BUFFER_CPP GENMASK_ULL(63, 40)
37 : : #define NSP_DFLT_BUFFER_ADDRESS GENMASK_ULL(39, 0)
38 : :
39 : : #define NSP_DFLT_BUFFER_CONFIG 0x20
40 : : #define NSP_DFLT_BUFFER_SIZE_4KB GENMASK_ULL(15, 8)
41 : : #define NSP_DFLT_BUFFER_SIZE_MB GENMASK_ULL(7, 0)
42 : :
43 : : #define NSP_MAGIC 0xab10
44 : :
45 : : /*
46 : : * ABI major version is bumped separately without resetting minor
47 : : * version when the change in NSP is not compatible to old driver.
48 : : */
49 : : #define NSP_MAJOR 1
50 : :
51 : : /*
52 : : * ABI minor version is bumped when new feature is introduced
53 : : * while old driver can still work without this new feature.
54 : : */
55 : : #define NSP_MINOR 8
56 : :
57 : : #define NSP_CODE_MAJOR GENMASK_ULL(15, 12)
58 : : #define NSP_CODE_MINOR GENMASK_ULL(11, 0)
59 : :
60 : : #define NFP_FW_LOAD_RET_MAJOR GENMASK_ULL(15, 8)
61 : : #define NFP_FW_LOAD_RET_MINOR GENMASK_ULL(23, 16)
62 : :
63 : : enum nfp_nsp_cmd {
64 : : SPCODE_NOOP = 0, /* No operation */
65 : : SPCODE_SOFT_RESET = 1, /* Soft reset the NFP */
66 : : SPCODE_FW_DEFAULT = 2, /* Load default (UNDI) FW */
67 : : SPCODE_PHY_INIT = 3, /* Initialize the PHY */
68 : : SPCODE_MAC_INIT = 4, /* Initialize the MAC */
69 : : SPCODE_PHY_RXADAPT = 5, /* Re-run PHY RX Adaptation */
70 : : SPCODE_FW_LOAD = 6, /* Load fw from buffer, len in option */
71 : : SPCODE_ETH_RESCAN = 7, /* Rescan ETHs, write ETH_TABLE to buf */
72 : : SPCODE_ETH_CONTROL = 8, /* Update media config from buffer */
73 : : SPCODE_NSP_WRITE_FLASH = 11, /* Load and flash image from buffer */
74 : : SPCODE_NSP_SENSORS = 12, /* Read NSP sensor(s) */
75 : : SPCODE_NSP_IDENTIFY = 13, /* Read NSP version */
76 : : SPCODE_FW_STORED = 16, /* If no FW loaded, load flash app FW */
77 : : SPCODE_HWINFO_LOOKUP = 17, /* Lookup HWinfo with overwrites etc. */
78 : : SPCODE_HWINFO_SET = 18, /* Set HWinfo entry */
79 : : SPCODE_FW_LOADED = 19, /* Is application firmware loaded */
80 : : SPCODE_VERSIONS = 21, /* Report FW versions */
81 : : SPCODE_READ_SFF_EEPROM = 22, /* Read module EEPROM */
82 : : SPCODE_READ_MEDIA = 23, /* Get the supported/advertised media for a port */
83 : : };
84 : :
85 : : static const struct {
86 : : uint32_t code;
87 : : const char *msg;
88 : : } nsp_errors[] = {
89 : : { 6010, "could not map to phy for port" },
90 : : { 6011, "not an allowed rate/lanes for port" },
91 : : { 6012, "not an allowed rate/lanes for port" },
92 : : { 6013, "high/low error, change other port first" },
93 : : { 6014, "config not found in flash" },
94 : : };
95 : :
96 : : struct nfp_nsp {
97 : : struct nfp_cpp *cpp;
98 : : struct nfp_resource *res;
99 : : struct {
100 : : uint16_t major;
101 : : uint16_t minor;
102 : : } ver;
103 : :
104 : : /** Eth table config state */
105 : : bool modified;
106 : : uint32_t idx;
107 : : void *entries;
108 : : };
109 : :
110 : : /* NFP command argument structure */
111 : : struct nfp_nsp_command_arg {
112 : : uint16_t code; /**< NFP SP Command Code */
113 : : bool dma; /**< @buf points to a host buffer, not NSP buffer */
114 : : bool error_quiet; /**< Don't print command error/warning */
115 : : uint32_t timeout_sec; /**< Timeout value to wait for completion in seconds */
116 : : uint32_t option; /**< NSP Command Argument */
117 : : uint64_t buf; /**< NSP Buffer Address */
118 : : /** Callback for interpreting option if error occurred */
119 : : void (*error_cb)(struct nfp_nsp *state, uint32_t ret_val);
120 : : };
121 : :
122 : : /* NFP command with buffer argument structure */
123 : : struct nfp_nsp_command_buf_arg {
124 : : struct nfp_nsp_command_arg arg; /**< NFP command argument structure */
125 : : const void *in_buf; /**< Buffer with data for input */
126 : : void *out_buf; /**< Buffer for output data */
127 : : uint32_t in_size; /**< Size of @in_buf */
128 : : uint32_t out_size; /**< Size of @out_buf */
129 : : };
130 : :
131 : : struct nfp_cpp *
132 : 0 : nfp_nsp_cpp(struct nfp_nsp *state)
133 : : {
134 : 0 : return state->cpp;
135 : : }
136 : :
137 : : bool
138 : 0 : nfp_nsp_config_modified(struct nfp_nsp *state)
139 : : {
140 : 0 : return state->modified;
141 : : }
142 : :
143 : : void
144 : 0 : nfp_nsp_config_set_modified(struct nfp_nsp *state,
145 : : bool modified)
146 : : {
147 : 0 : state->modified = modified;
148 : 0 : }
149 : :
150 : : void *
151 : 0 : nfp_nsp_config_entries(struct nfp_nsp *state)
152 : : {
153 : 0 : return state->entries;
154 : : }
155 : :
156 : : uint32_t
157 : 0 : nfp_nsp_config_idx(struct nfp_nsp *state)
158 : : {
159 : 0 : return state->idx;
160 : : }
161 : :
162 : : void
163 : 0 : nfp_nsp_config_set_state(struct nfp_nsp *state,
164 : : void *entries,
165 : : uint32_t idx)
166 : : {
167 : 0 : state->entries = entries;
168 : 0 : state->idx = idx;
169 : 0 : }
170 : :
171 : : void
172 : 0 : nfp_nsp_config_clear_state(struct nfp_nsp *state)
173 : : {
174 : 0 : state->entries = NULL;
175 : 0 : state->idx = 0;
176 : 0 : }
177 : :
178 : : static void
179 : 0 : nfp_nsp_print_extended_error(uint32_t ret_val)
180 : : {
181 : : uint32_t i;
182 : :
183 [ # # ]: 0 : if (ret_val == 0)
184 : : return;
185 : :
186 [ # # ]: 0 : for (i = 0; i < RTE_DIM(nsp_errors); i++)
187 [ # # ]: 0 : if (ret_val == nsp_errors[i].code)
188 : 0 : PMD_DRV_LOG(ERR, "err msg: %s", nsp_errors[i].msg);
189 : : }
190 : :
191 : : static int
192 : 0 : nfp_nsp_check(struct nfp_nsp *state)
193 : : {
194 : : int err;
195 : : uint64_t reg;
196 : : uint32_t nsp_cpp;
197 : : uint64_t nsp_status;
198 : 0 : struct nfp_cpp *cpp = state->cpp;
199 : :
200 : 0 : nsp_cpp = nfp_resource_cpp_id(state->res);
201 : 0 : nsp_status = nfp_resource_address(state->res) + NSP_STATUS;
202 : :
203 : 0 : err = nfp_cpp_readq(cpp, nsp_cpp, nsp_status, ®);
204 [ # # ]: 0 : if (err < 0) {
205 : 0 : PMD_DRV_LOG(ERR, "NSP - CPP readq failed %d", err);
206 : 0 : return err;
207 : : }
208 : :
209 [ # # ]: 0 : if (FIELD_GET(NSP_STATUS_MAGIC, reg) != NSP_MAGIC) {
210 : 0 : PMD_DRV_LOG(ERR, "Cannot detect NFP Service Processor");
211 : 0 : return -ENODEV;
212 : : }
213 : :
214 : 0 : state->ver.major = FIELD_GET(NSP_STATUS_MAJOR, reg);
215 : 0 : state->ver.minor = FIELD_GET(NSP_STATUS_MINOR, reg);
216 : :
217 [ # # # # ]: 0 : if (state->ver.major > NSP_MAJOR || state->ver.minor < NSP_MINOR) {
218 : 0 : PMD_DRV_LOG(ERR, "Unsupported ABI %hu.%hu", state->ver.major,
219 : : state->ver.minor);
220 : 0 : return -EINVAL;
221 : : }
222 : :
223 [ # # ]: 0 : if ((reg & NSP_STATUS_BUSY) != 0) {
224 : 0 : PMD_DRV_LOG(DEBUG, "Service processor busy!");
225 : 0 : return -EBUSY;
226 : : }
227 : :
228 : : return 0;
229 : : }
230 : :
231 : : /**
232 : : * Prepare for communication and lock the NSP resource.
233 : : *
234 : : * @param cpp
235 : : * NFP CPP Handle
236 : : */
237 : : struct nfp_nsp *
238 : 0 : nfp_nsp_open(struct nfp_cpp *cpp)
239 : : {
240 : : int err;
241 : : struct nfp_nsp *state;
242 : : struct nfp_resource *res;
243 : :
244 : 0 : res = nfp_resource_acquire(cpp, NFP_RESOURCE_NSP);
245 [ # # ]: 0 : if (res == NULL) {
246 : 0 : PMD_DRV_LOG(ERR, "NSP - resource acquire failed");
247 : 0 : return NULL;
248 : : }
249 : :
250 : 0 : state = malloc(sizeof(*state));
251 [ # # ]: 0 : if (state == NULL) {
252 : 0 : nfp_resource_release(res);
253 : 0 : return NULL;
254 : : }
255 : : memset(state, 0, sizeof(*state));
256 : 0 : state->cpp = cpp;
257 : 0 : state->res = res;
258 : :
259 : 0 : err = nfp_nsp_check(state);
260 [ # # ]: 0 : if (err != 0) {
261 : 0 : PMD_DRV_LOG(DEBUG, "NSP - check failed");
262 : 0 : nfp_nsp_close(state);
263 : 0 : return NULL;
264 : : }
265 : :
266 : : return state;
267 : : }
268 : :
269 : : /**
270 : : * Clean up and unlock the NSP resource.
271 : : *
272 : : * @param state
273 : : * NFP SP state
274 : : */
275 : : void
276 : 0 : nfp_nsp_close(struct nfp_nsp *state)
277 : : {
278 : 0 : nfp_resource_release(state->res);
279 : 0 : free(state);
280 : 0 : }
281 : :
282 : : uint16_t
283 : 0 : nfp_nsp_get_abi_ver_major(struct nfp_nsp *state)
284 : : {
285 : 0 : return state->ver.major;
286 : : }
287 : :
288 : : uint16_t
289 : 0 : nfp_nsp_get_abi_ver_minor(struct nfp_nsp *state)
290 : : {
291 : 0 : return state->ver.minor;
292 : : }
293 : :
294 : : static int
295 : 0 : nfp_nsp_wait_reg(struct nfp_cpp *cpp,
296 : : uint64_t *reg,
297 : : uint32_t nsp_cpp,
298 : : uint64_t addr,
299 : : uint64_t mask,
300 : : uint64_t val)
301 : : {
302 : : int err;
303 : : uint32_t count = 0;
304 : : struct timespec wait;
305 : :
306 : 0 : wait.tv_sec = 0;
307 : 0 : wait.tv_nsec = 25000000; /* 25ms */
308 : :
309 : : for (;;) {
310 : 0 : err = nfp_cpp_readq(cpp, nsp_cpp, addr, reg);
311 [ # # ]: 0 : if (err < 0) {
312 : 0 : PMD_DRV_LOG(ERR, "NSP - CPP readq failed");
313 : 0 : return err;
314 : : }
315 : :
316 [ # # ]: 0 : if ((*reg & mask) == val)
317 : : return 0;
318 : :
319 : 0 : nanosleep(&wait, 0);
320 [ # # ]: 0 : if (count++ > 1000) /* 25ms * 1000 = 25s */
321 : : return -ETIMEDOUT;
322 : : }
323 : : }
324 : :
325 : : /**
326 : : * Execute a command on the NFP Service Processor
327 : : *
328 : : * @param state
329 : : * NFP SP state
330 : : * @param arg
331 : : * NFP command argument structure
332 : : *
333 : : * @return
334 : : * - 0 for success with no result
335 : : * - Positive value for NSP completion with a result code
336 : : * - -EAGAIN if the NSP is not yet present
337 : : * - -ENODEV if the NSP is not a supported model
338 : : * - -EBUSY if the NSP is stuck
339 : : * - -EINTR if interrupted while waiting for completion
340 : : * - -ETIMEDOUT if the NSP took longer than @timeout_sec seconds to complete
341 : : */
342 : : static int
343 : 0 : nfp_nsp_command_real(struct nfp_nsp *state,
344 : : const struct nfp_nsp_command_arg *arg)
345 : : {
346 : : int err;
347 : : uint64_t reg;
348 : : uint32_t nsp_cpp;
349 : : uint64_t ret_val;
350 : : uint64_t nsp_base;
351 : : uint64_t nsp_buffer;
352 : : uint64_t nsp_status;
353 : : uint64_t nsp_command;
354 : 0 : struct nfp_cpp *cpp = state->cpp;
355 : :
356 : 0 : nsp_cpp = nfp_resource_cpp_id(state->res);
357 : 0 : nsp_base = nfp_resource_address(state->res);
358 : : nsp_status = nsp_base + NSP_STATUS;
359 : 0 : nsp_command = nsp_base + NSP_COMMAND;
360 : 0 : nsp_buffer = nsp_base + NSP_BUFFER;
361 : :
362 : 0 : err = nfp_nsp_check(state);
363 [ # # ]: 0 : if (err != 0) {
364 : 0 : PMD_DRV_LOG(ERR, "Check NSP command failed");
365 : 0 : return err;
366 : : }
367 : :
368 : 0 : err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_buffer, arg->buf);
369 [ # # ]: 0 : if (err < 0)
370 : : return err;
371 : :
372 : 0 : err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_command,
373 : 0 : FIELD_PREP(NSP_COMMAND_OPTION, arg->option) |
374 : 0 : FIELD_PREP(NSP_COMMAND_VER_MAJOR, state->ver.major) |
375 : 0 : FIELD_PREP(NSP_COMMAND_CODE, arg->code) |
376 : 0 : FIELD_PREP(NSP_COMMAND_DMA_BUF, arg->dma) |
377 : : FIELD_PREP(NSP_COMMAND_START, 1));
378 [ # # ]: 0 : if (err < 0)
379 : : return err;
380 : :
381 : : /* Wait for NSP_COMMAND_START to go to 0 */
382 : 0 : err = nfp_nsp_wait_reg(cpp, ®, nsp_cpp, nsp_command,
383 : : NSP_COMMAND_START, 0);
384 [ # # ]: 0 : if (err != 0) {
385 : 0 : PMD_DRV_LOG(ERR, "Error %d waiting for code %#04x to start",
386 : : err, arg->code);
387 : 0 : return err;
388 : : }
389 : :
390 : : /* Wait for NSP_STATUS_BUSY to go to 0 */
391 : 0 : err = nfp_nsp_wait_reg(cpp, ®, nsp_cpp, nsp_status,
392 : : NSP_STATUS_BUSY, 0);
393 [ # # ]: 0 : if (err != 0) {
394 : 0 : PMD_DRV_LOG(ERR, "Error %d waiting for code %#04x to complete",
395 : : err, arg->code);
396 : 0 : return err;
397 : : }
398 : :
399 : 0 : err = nfp_cpp_readq(cpp, nsp_cpp, nsp_command, &ret_val);
400 [ # # ]: 0 : if (err < 0)
401 : : return err;
402 : :
403 : 0 : ret_val = FIELD_GET(NSP_COMMAND_OPTION, ret_val);
404 : :
405 : 0 : err = FIELD_GET(NSP_STATUS_RESULT, reg);
406 [ # # ]: 0 : if (err != 0) {
407 [ # # ]: 0 : if (!arg->error_quiet)
408 : 0 : PMD_DRV_LOG(WARNING, "Result (error) code set: %d (%d) command: %d",
409 : : -err, (int)ret_val, arg->code);
410 : :
411 [ # # ]: 0 : if (arg->error_cb != 0)
412 : 0 : arg->error_cb(state, ret_val);
413 : : else
414 : 0 : nfp_nsp_print_extended_error(ret_val);
415 : :
416 : 0 : return -err;
417 : : }
418 : :
419 : 0 : return ret_val;
420 : : }
421 : :
422 : : static int
423 : : nfp_nsp_command(struct nfp_nsp *state,
424 : : uint16_t code)
425 : : {
426 : 0 : const struct nfp_nsp_command_arg arg = {
427 : : .code = code,
428 : : };
429 : :
430 : 0 : return nfp_nsp_command_real(state, &arg);
431 : : }
432 : :
433 : : static int
434 : 0 : nfp_nsp_command_buf_def(struct nfp_nsp *nsp,
435 : : struct nfp_nsp_command_buf_arg *arg)
436 : : {
437 : : int err;
438 : : int ret;
439 : : uint64_t reg;
440 : : uint32_t cpp_id;
441 : : uint64_t cpp_buf;
442 : 0 : struct nfp_cpp *cpp = nsp->cpp;
443 : :
444 : 0 : err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res),
445 : 0 : nfp_resource_address(nsp->res) + NSP_DFLT_BUFFER,
446 : : ®);
447 [ # # ]: 0 : if (err < 0)
448 : : return err;
449 : :
450 : 0 : cpp_id = FIELD_GET(NSP_DFLT_BUFFER_CPP, reg) << 8;
451 : 0 : cpp_buf = FIELD_GET(NSP_DFLT_BUFFER_ADDRESS, reg);
452 : :
453 [ # # # # ]: 0 : if (arg->in_buf != NULL && arg->in_size > 0) {
454 : 0 : err = nfp_cpp_write(cpp, cpp_id, cpp_buf,
455 : : arg->in_buf, arg->in_size);
456 [ # # ]: 0 : if (err < 0)
457 : : return err;
458 : : }
459 : :
460 : : /* Zero out remaining part of the buffer */
461 [ # # # # ]: 0 : if (arg->out_buf != NULL && arg->out_size > arg->in_size) {
462 : 0 : err = nfp_cpp_write(cpp, cpp_id, cpp_buf + arg->in_size,
463 : 0 : arg->out_buf, arg->out_size - arg->in_size);
464 [ # # ]: 0 : if (err < 0)
465 : : return err;
466 : : }
467 : :
468 : 0 : if (!FIELD_FIT(NSP_BUFFER_CPP, cpp_id >> 8) ||
469 : : !FIELD_FIT(NSP_BUFFER_ADDRESS, cpp_buf)) {
470 : : PMD_DRV_LOG(ERR, "Buffer out of reach %#08x %#016lx",
471 : : cpp_id, cpp_buf);
472 : : return -EINVAL;
473 : : }
474 : :
475 : 0 : arg->arg.buf = FIELD_PREP(NSP_BUFFER_CPP, cpp_id >> 8) |
476 : : FIELD_PREP(NSP_BUFFER_ADDRESS, cpp_buf);
477 : 0 : ret = nfp_nsp_command_real(nsp, &arg->arg);
478 [ # # ]: 0 : if (ret < 0) {
479 : 0 : PMD_DRV_LOG(ERR, "NSP command failed");
480 : 0 : return ret;
481 : : }
482 : :
483 [ # # # # ]: 0 : if (arg->out_buf != NULL && arg->out_size > 0) {
484 : 0 : err = nfp_cpp_read(cpp, cpp_id, cpp_buf,
485 : : arg->out_buf, arg->out_size);
486 [ # # ]: 0 : if (err < 0)
487 : 0 : return err;
488 : : }
489 : :
490 : : return ret;
491 : : }
492 : :
493 : : #define SZ_1M 0x00100000
494 : : #define SZ_4K 0x00001000
495 : :
496 : : static int
497 : 0 : nfp_nsp_command_buf(struct nfp_nsp *nsp,
498 : : struct nfp_nsp_command_buf_arg *arg)
499 : : {
500 : : int err;
501 : : size_t size;
502 : : uint64_t reg;
503 : : size_t max_size;
504 : 0 : struct nfp_cpp *cpp = nsp->cpp;
505 : :
506 [ # # ]: 0 : if (nsp->ver.minor < 13) {
507 : 0 : PMD_DRV_LOG(ERR, "NSP: Code %#04x with buffer not supported ABI %hu.%hu)",
508 : : arg->arg.code, nsp->ver.major, nsp->ver.minor);
509 : 0 : return -EOPNOTSUPP;
510 : : }
511 : :
512 : 0 : err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res),
513 : 0 : nfp_resource_address(nsp->res) + NSP_DFLT_BUFFER_CONFIG,
514 : : ®);
515 [ # # ]: 0 : if (err < 0)
516 : : return err;
517 : :
518 : 0 : max_size = RTE_MAX(arg->in_size, arg->out_size);
519 : 0 : size = FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M +
520 : 0 : FIELD_GET(NSP_DFLT_BUFFER_SIZE_4KB, reg) * SZ_4K;
521 [ # # ]: 0 : if (size < max_size) {
522 : 0 : PMD_DRV_LOG(ERR, "NSP: default buffer too small for command %#04x (%zu < %zu)",
523 : : arg->arg.code, size, max_size);
524 : 0 : return -EINVAL;
525 : : }
526 : :
527 : 0 : return nfp_nsp_command_buf_def(nsp, arg);
528 : : }
529 : :
530 : : int
531 : 0 : nfp_nsp_wait(struct nfp_nsp *state)
532 : : {
533 : : int err;
534 : : int count = 0;
535 : : struct timespec wait;
536 : :
537 : 0 : wait.tv_sec = 0;
538 : 0 : wait.tv_nsec = 25000000; /* 25ms */
539 : :
540 : : for (;;) {
541 : : err = nfp_nsp_command(state, SPCODE_NOOP);
542 [ # # ]: 0 : if (err != -EAGAIN)
543 : : break;
544 : :
545 : 0 : nanosleep(&wait, 0);
546 : :
547 [ # # ]: 0 : if (count++ > 1000) { /* 25ms * 1000 = 25s */
548 : : err = -ETIMEDOUT;
549 : : break;
550 : : }
551 : : }
552 : :
553 [ # # ]: 0 : if (err != 0)
554 : 0 : PMD_DRV_LOG(ERR, "NSP failed to respond %d", err);
555 : :
556 : 0 : return err;
557 : : }
558 : :
559 : : int
560 : 0 : nfp_nsp_device_soft_reset(struct nfp_nsp *state)
561 : : {
562 : 0 : return nfp_nsp_command(state, SPCODE_SOFT_RESET);
563 : : }
564 : :
565 : : int
566 : 0 : nfp_nsp_mac_reinit(struct nfp_nsp *state)
567 : : {
568 : 0 : return nfp_nsp_command(state, SPCODE_MAC_INIT);
569 : : }
570 : :
571 : : static void
572 : 0 : nfp_nsp_load_fw_extended_msg(struct nfp_nsp *state,
573 : : uint32_t ret_val)
574 : : {
575 : : uint32_t minor;
576 : : uint32_t major;
577 : : static const char * const major_msg[] = {
578 : : /* 0 */ "Firmware from driver loaded",
579 : : /* 1 */ "Firmware from flash loaded",
580 : : /* 2 */ "Firmware loading failure",
581 : : };
582 : : static const char * const minor_msg[] = {
583 : : /* 0 */ "",
584 : : /* 1 */ "no named partition on flash",
585 : : /* 2 */ "error reading from flash",
586 : : /* 3 */ "can not deflate",
587 : : /* 4 */ "not a trusted file",
588 : : /* 5 */ "can not parse FW file",
589 : : /* 6 */ "MIP not found in FW file",
590 : : /* 7 */ "null firmware name in MIP",
591 : : /* 8 */ "FW version none",
592 : : /* 9 */ "FW build number none",
593 : : /* 10 */ "no FW selection policy HWInfo key found",
594 : : /* 11 */ "static FW selection policy",
595 : : /* 12 */ "FW version has precedence",
596 : : /* 13 */ "different FW application load requested",
597 : : /* 14 */ "development build",
598 : : };
599 : :
600 : 0 : major = FIELD_GET(NFP_FW_LOAD_RET_MAJOR, ret_val);
601 : 0 : minor = FIELD_GET(NFP_FW_LOAD_RET_MINOR, ret_val);
602 : :
603 [ # # ]: 0 : if (!nfp_nsp_has_stored_fw_load(state))
604 : : return;
605 : :
606 [ # # ]: 0 : if (major >= RTE_DIM(major_msg))
607 : 0 : PMD_DRV_LOG(INFO, "FW loading status: %x", ret_val);
608 [ # # ]: 0 : else if (minor >= RTE_DIM(minor_msg))
609 : 0 : PMD_DRV_LOG(INFO, "%s, reason code: %d", major_msg[major], minor);
610 : : else
611 [ # # ]: 0 : PMD_DRV_LOG(INFO, "%s%c %s", major_msg[major],
612 : : minor != 0 ? ',' : '.', minor_msg[minor]);
613 : : }
614 : :
615 : : int
616 : 0 : nfp_nsp_load_fw(struct nfp_nsp *state,
617 : : void *buf,
618 : : size_t size)
619 : : {
620 : : int ret;
621 : 0 : struct nfp_nsp_command_buf_arg load_fw = {
622 : : {
623 : : .code = SPCODE_FW_LOAD,
624 : : .option = size,
625 : : .error_cb = nfp_nsp_load_fw_extended_msg,
626 : : },
627 : : .in_buf = buf,
628 : : .in_size = size,
629 : : };
630 : :
631 : 0 : ret = nfp_nsp_command_buf(state, &load_fw);
632 [ # # ]: 0 : if (ret < 0)
633 : : return ret;
634 : :
635 : 0 : nfp_nsp_load_fw_extended_msg(state, ret);
636 : :
637 : 0 : return 0;
638 : : }
639 : :
640 : : bool
641 : 0 : nfp_nsp_fw_loaded(struct nfp_nsp *state)
642 : : {
643 : 0 : return nfp_nsp_command(state, SPCODE_FW_LOADED) > 0;
644 : : }
645 : :
646 : : int
647 : 0 : nfp_nsp_read_eth_table(struct nfp_nsp *state,
648 : : void *buf,
649 : : size_t size)
650 : : {
651 : 0 : struct nfp_nsp_command_buf_arg eth_rescan = {
652 : : {
653 : : .code = SPCODE_ETH_RESCAN,
654 : : .option = size,
655 : : },
656 : : .out_buf = buf,
657 : : .out_size = size,
658 : : };
659 : :
660 : 0 : return nfp_nsp_command_buf(state, ð_rescan);
661 : : }
662 : :
663 : : int
664 : 0 : nfp_nsp_write_eth_table(struct nfp_nsp *state,
665 : : const void *buf,
666 : : size_t size)
667 : : {
668 : 0 : struct nfp_nsp_command_buf_arg eth_ctrl = {
669 : : {
670 : : .code = SPCODE_ETH_CONTROL,
671 : : .option = size,
672 : : },
673 : : .in_buf = buf,
674 : : .in_size = size,
675 : : };
676 : :
677 : 0 : return nfp_nsp_command_buf(state, ð_ctrl);
678 : : }
679 : :
680 : : int
681 : 0 : nfp_nsp_read_identify(struct nfp_nsp *state,
682 : : void *buf,
683 : : size_t size)
684 : : {
685 : 0 : struct nfp_nsp_command_buf_arg identify = {
686 : : {
687 : : .code = SPCODE_NSP_IDENTIFY,
688 : : .option = size,
689 : : },
690 : : .out_buf = buf,
691 : : .out_size = size,
692 : : };
693 : :
694 : 0 : return nfp_nsp_command_buf(state, &identify);
695 : : }
696 : :
697 : : int
698 : 0 : nfp_nsp_read_sensors(struct nfp_nsp *state,
699 : : uint32_t sensor_mask,
700 : : void *buf,
701 : : size_t size)
702 : : {
703 : 0 : struct nfp_nsp_command_buf_arg sensors = {
704 : : {
705 : : .code = SPCODE_NSP_SENSORS,
706 : : .option = sensor_mask,
707 : : },
708 : : .out_buf = buf,
709 : : .out_size = size,
710 : : };
711 : :
712 : 0 : return nfp_nsp_command_buf(state, &sensors);
713 : : }
714 : :
715 : : int
716 : 0 : nfp_nsp_hwinfo_set(struct nfp_nsp *state,
717 : : const void *buf,
718 : : size_t size)
719 : : {
720 : 0 : struct nfp_nsp_command_buf_arg hwinfo_set = {
721 : : {
722 : : .code = SPCODE_HWINFO_SET,
723 : : .option = size,
724 : : },
725 : : .in_buf = buf,
726 : : .in_size = size,
727 : : };
728 : :
729 : 0 : return nfp_nsp_command_buf(state, &hwinfo_set);
730 : : }
731 : :
732 : : int
733 : 0 : nfp_nsp_read_media(struct nfp_nsp *state,
734 : : void *buf,
735 : : size_t size)
736 : : {
737 : 0 : struct nfp_nsp_command_buf_arg media = {
738 : : {
739 : : .code = SPCODE_READ_MEDIA,
740 : : .option = size,
741 : : },
742 : : .out_buf = buf,
743 : : .out_size = size,
744 : : };
745 : :
746 : 0 : return nfp_nsp_command_buf(state, &media);
747 : : }
|