1c7e9729dSAlejandro Lucero /* SPDX-License-Identifier: BSD-3-Clause 2c7e9729dSAlejandro Lucero * Copyright(c) 2018 Netronome Systems, Inc. 3c7e9729dSAlejandro Lucero * All rights reserved. 4c7e9729dSAlejandro Lucero */ 5c7e9729dSAlejandro Lucero 6acaa57efSChaoyong He #include "nfp_nsp.h" 7c7e9729dSAlejandro Lucero 8a3460357SChaoyong He #include <nfp_platform.h> 9c7e9729dSAlejandro Lucero #include <rte_common.h> 10c7e9729dSAlejandro Lucero 1152d810dcSJames Hershaw #include "nfp_logs.h" 12c7e9729dSAlejandro Lucero #include "nfp_resource.h" 13c7e9729dSAlejandro Lucero 14acaa57efSChaoyong He /* Offsets relative to the CSR base */ 15acaa57efSChaoyong He #define NSP_STATUS 0x00 16acaa57efSChaoyong He #define NSP_STATUS_MAGIC GENMASK_ULL(63, 48) 17acaa57efSChaoyong He #define NSP_STATUS_MAJOR GENMASK_ULL(47, 44) 18acaa57efSChaoyong He #define NSP_STATUS_MINOR GENMASK_ULL(43, 32) 19acaa57efSChaoyong He #define NSP_STATUS_CODE GENMASK_ULL(31, 16) 20acaa57efSChaoyong He #define NSP_STATUS_RESULT GENMASK_ULL(15, 8) 21acaa57efSChaoyong He #define NSP_STATUS_BUSY RTE_BIT64(0) 22acaa57efSChaoyong He 23acaa57efSChaoyong He #define NSP_COMMAND 0x08 24acaa57efSChaoyong He #define NSP_COMMAND_OPTION GENMASK_ULL(63, 32) 25847aa891SPeng Zhang #define NSP_COMMAND_VER_MAJOR GENMASK_ULL(31, 28) 26847aa891SPeng Zhang #define NSP_COMMAND_CODE GENMASK_ULL(27, 16) 27acaa57efSChaoyong He #define NSP_COMMAND_DMA_BUF RTE_BIT64(1) 28acaa57efSChaoyong He #define NSP_COMMAND_START RTE_BIT64(0) 29acaa57efSChaoyong He 30acaa57efSChaoyong He /* CPP address to retrieve the data from */ 31acaa57efSChaoyong He #define NSP_BUFFER 0x10 32acaa57efSChaoyong He #define NSP_BUFFER_CPP GENMASK_ULL(63, 40) 33acaa57efSChaoyong He #define NSP_BUFFER_ADDRESS GENMASK_ULL(39, 0) 34acaa57efSChaoyong He 35acaa57efSChaoyong He #define NSP_DFLT_BUFFER 0x18 36acaa57efSChaoyong He #define NSP_DFLT_BUFFER_CPP GENMASK_ULL(63, 40) 37acaa57efSChaoyong He #define NSP_DFLT_BUFFER_ADDRESS GENMASK_ULL(39, 0) 38acaa57efSChaoyong He 39acaa57efSChaoyong He #define NSP_DFLT_BUFFER_CONFIG 0x20 40acaa57efSChaoyong He #define NSP_DFLT_BUFFER_SIZE_4KB GENMASK_ULL(15, 8) 41acaa57efSChaoyong He #define NSP_DFLT_BUFFER_SIZE_MB GENMASK_ULL(7, 0) 42acaa57efSChaoyong He 43acaa57efSChaoyong He #define NSP_MAGIC 0xab10 448ad2cc8fSPeng Zhang 458ad2cc8fSPeng Zhang /* 468ad2cc8fSPeng Zhang * ABI major version is bumped separately without resetting minor 478ad2cc8fSPeng Zhang * version when the change in NSP is not compatible to old driver. 488ad2cc8fSPeng Zhang */ 498ad2cc8fSPeng Zhang #define NSP_MAJOR 1 508ad2cc8fSPeng Zhang 518ad2cc8fSPeng Zhang /* 528ad2cc8fSPeng Zhang * ABI minor version is bumped when new feature is introduced 538ad2cc8fSPeng Zhang * while old driver can still work without this new feature. 548ad2cc8fSPeng Zhang */ 55acaa57efSChaoyong He #define NSP_MINOR 8 56acaa57efSChaoyong He 57acaa57efSChaoyong He #define NSP_CODE_MAJOR GENMASK_ULL(15, 12) 58acaa57efSChaoyong He #define NSP_CODE_MINOR GENMASK_ULL(11, 0) 59acaa57efSChaoyong He 60acaa57efSChaoyong He #define NFP_FW_LOAD_RET_MAJOR GENMASK_ULL(15, 8) 61acaa57efSChaoyong He #define NFP_FW_LOAD_RET_MINOR GENMASK_ULL(23, 16) 62acaa57efSChaoyong He 639e76c352SChaoyong He #define NFP_HWINFO_LOOKUP_SIZE GENMASK_ULL(11, 0) 649e76c352SChaoyong He 65acaa57efSChaoyong He enum nfp_nsp_cmd { 66acaa57efSChaoyong He SPCODE_NOOP = 0, /* No operation */ 67acaa57efSChaoyong He SPCODE_SOFT_RESET = 1, /* Soft reset the NFP */ 68acaa57efSChaoyong He SPCODE_FW_DEFAULT = 2, /* Load default (UNDI) FW */ 69acaa57efSChaoyong He SPCODE_PHY_INIT = 3, /* Initialize the PHY */ 70acaa57efSChaoyong He SPCODE_MAC_INIT = 4, /* Initialize the MAC */ 71acaa57efSChaoyong He SPCODE_PHY_RXADAPT = 5, /* Re-run PHY RX Adaptation */ 72acaa57efSChaoyong He SPCODE_FW_LOAD = 6, /* Load fw from buffer, len in option */ 73acaa57efSChaoyong He SPCODE_ETH_RESCAN = 7, /* Rescan ETHs, write ETH_TABLE to buf */ 74acaa57efSChaoyong He SPCODE_ETH_CONTROL = 8, /* Update media config from buffer */ 75acaa57efSChaoyong He SPCODE_NSP_WRITE_FLASH = 11, /* Load and flash image from buffer */ 76acaa57efSChaoyong He SPCODE_NSP_SENSORS = 12, /* Read NSP sensor(s) */ 77acaa57efSChaoyong He SPCODE_NSP_IDENTIFY = 13, /* Read NSP version */ 78acaa57efSChaoyong He SPCODE_FW_STORED = 16, /* If no FW loaded, load flash app FW */ 79acaa57efSChaoyong He SPCODE_HWINFO_LOOKUP = 17, /* Lookup HWinfo with overwrites etc. */ 80acaa57efSChaoyong He SPCODE_HWINFO_SET = 18, /* Set HWinfo entry */ 81acaa57efSChaoyong He SPCODE_FW_LOADED = 19, /* Is application firmware loaded */ 82acaa57efSChaoyong He SPCODE_VERSIONS = 21, /* Report FW versions */ 83acaa57efSChaoyong He SPCODE_READ_SFF_EEPROM = 22, /* Read module EEPROM */ 84acaa57efSChaoyong He SPCODE_READ_MEDIA = 23, /* Get the supported/advertised media for a port */ 8508461d7bSPeng Zhang SPCODE_DEV_ACTIVATE = 29, /* Activate hardware for multiple pfs case */ 86acaa57efSChaoyong He }; 87acaa57efSChaoyong He 88acaa57efSChaoyong He static const struct { 89acaa57efSChaoyong He uint32_t code; 90acaa57efSChaoyong He const char *msg; 91acaa57efSChaoyong He } nsp_errors[] = { 92acaa57efSChaoyong He { 6010, "could not map to phy for port" }, 93acaa57efSChaoyong He { 6011, "not an allowed rate/lanes for port" }, 94acaa57efSChaoyong He { 6012, "not an allowed rate/lanes for port" }, 95acaa57efSChaoyong He { 6013, "high/low error, change other port first" }, 96acaa57efSChaoyong He { 6014, "config not found in flash" }, 97acaa57efSChaoyong He }; 98acaa57efSChaoyong He 99acaa57efSChaoyong He struct nfp_nsp { 100acaa57efSChaoyong He struct nfp_cpp *cpp; 101acaa57efSChaoyong He struct nfp_resource *res; 102acaa57efSChaoyong He struct { 103acaa57efSChaoyong He uint16_t major; 104acaa57efSChaoyong He uint16_t minor; 105acaa57efSChaoyong He } ver; 106acaa57efSChaoyong He 107acaa57efSChaoyong He /** Eth table config state */ 108acaa57efSChaoyong He bool modified; 109acaa57efSChaoyong He uint32_t idx; 110acaa57efSChaoyong He void *entries; 111acaa57efSChaoyong He }; 112acaa57efSChaoyong He 113acaa57efSChaoyong He /* NFP command argument structure */ 114acaa57efSChaoyong He struct nfp_nsp_command_arg { 115acaa57efSChaoyong He uint16_t code; /**< NFP SP Command Code */ 116acaa57efSChaoyong He bool dma; /**< @buf points to a host buffer, not NSP buffer */ 117acaa57efSChaoyong He bool error_quiet; /**< Don't print command error/warning */ 118acaa57efSChaoyong He uint32_t timeout_sec; /**< Timeout value to wait for completion in seconds */ 119acaa57efSChaoyong He uint32_t option; /**< NSP Command Argument */ 120acaa57efSChaoyong He uint64_t buf; /**< NSP Buffer Address */ 121acaa57efSChaoyong He /** Callback for interpreting option if error occurred */ 122acaa57efSChaoyong He void (*error_cb)(struct nfp_nsp *state, uint32_t ret_val); 123acaa57efSChaoyong He }; 124acaa57efSChaoyong He 125acaa57efSChaoyong He /* NFP command with buffer argument structure */ 126acaa57efSChaoyong He struct nfp_nsp_command_buf_arg { 127acaa57efSChaoyong He struct nfp_nsp_command_arg arg; /**< NFP command argument structure */ 128acaa57efSChaoyong He const void *in_buf; /**< Buffer with data for input */ 129acaa57efSChaoyong He void *out_buf; /**< Buffer for output data */ 130acaa57efSChaoyong He uint32_t in_size; /**< Size of @in_buf */ 131acaa57efSChaoyong He uint32_t out_size; /**< Size of @out_buf */ 132acaa57efSChaoyong He }; 133acaa57efSChaoyong He 134acaa57efSChaoyong He struct nfp_cpp * 135acaa57efSChaoyong He nfp_nsp_cpp(struct nfp_nsp *state) 136acaa57efSChaoyong He { 137acaa57efSChaoyong He return state->cpp; 138acaa57efSChaoyong He } 139acaa57efSChaoyong He 140acaa57efSChaoyong He bool 141c7e9729dSAlejandro Lucero nfp_nsp_config_modified(struct nfp_nsp *state) 142c7e9729dSAlejandro Lucero { 143c7e9729dSAlejandro Lucero return state->modified; 144c7e9729dSAlejandro Lucero } 145c7e9729dSAlejandro Lucero 146c7e9729dSAlejandro Lucero void 147d108b9e9SChaoyong He nfp_nsp_config_set_modified(struct nfp_nsp *state, 148acaa57efSChaoyong He bool modified) 149c7e9729dSAlejandro Lucero { 150c7e9729dSAlejandro Lucero state->modified = modified; 151c7e9729dSAlejandro Lucero } 152c7e9729dSAlejandro Lucero 153c7e9729dSAlejandro Lucero void * 154c7e9729dSAlejandro Lucero nfp_nsp_config_entries(struct nfp_nsp *state) 155c7e9729dSAlejandro Lucero { 156c7e9729dSAlejandro Lucero return state->entries; 157c7e9729dSAlejandro Lucero } 158c7e9729dSAlejandro Lucero 159c69debceSChaoyong He uint32_t 160c7e9729dSAlejandro Lucero nfp_nsp_config_idx(struct nfp_nsp *state) 161c7e9729dSAlejandro Lucero { 162c7e9729dSAlejandro Lucero return state->idx; 163c7e9729dSAlejandro Lucero } 164c7e9729dSAlejandro Lucero 165c7e9729dSAlejandro Lucero void 166d108b9e9SChaoyong He nfp_nsp_config_set_state(struct nfp_nsp *state, 167d108b9e9SChaoyong He void *entries, 168c69debceSChaoyong He uint32_t idx) 169c7e9729dSAlejandro Lucero { 170c7e9729dSAlejandro Lucero state->entries = entries; 171c7e9729dSAlejandro Lucero state->idx = idx; 172c7e9729dSAlejandro Lucero } 173c7e9729dSAlejandro Lucero 174c7e9729dSAlejandro Lucero void 175c7e9729dSAlejandro Lucero nfp_nsp_config_clear_state(struct nfp_nsp *state) 176c7e9729dSAlejandro Lucero { 177c7e9729dSAlejandro Lucero state->entries = NULL; 178c7e9729dSAlejandro Lucero state->idx = 0; 179c7e9729dSAlejandro Lucero } 180c7e9729dSAlejandro Lucero 181c7e9729dSAlejandro Lucero static void 182c7e9729dSAlejandro Lucero nfp_nsp_print_extended_error(uint32_t ret_val) 183c7e9729dSAlejandro Lucero { 184c69debceSChaoyong He uint32_t i; 185c7e9729dSAlejandro Lucero 186cbcbfd73SJames Hershaw if (ret_val == 0) 187c7e9729dSAlejandro Lucero return; 188c7e9729dSAlejandro Lucero 189c69debceSChaoyong He for (i = 0; i < RTE_DIM(nsp_errors); i++) 190acaa57efSChaoyong He if (ret_val == nsp_errors[i].code) 191b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Err msg: %s.", nsp_errors[i].msg); 192c7e9729dSAlejandro Lucero } 193c7e9729dSAlejandro Lucero 194c7e9729dSAlejandro Lucero static int 195c7e9729dSAlejandro Lucero nfp_nsp_check(struct nfp_nsp *state) 196c7e9729dSAlejandro Lucero { 197c7e9729dSAlejandro Lucero int err; 198610bf14bSChaoyong He uint64_t reg; 199610bf14bSChaoyong He uint32_t nsp_cpp; 200610bf14bSChaoyong He uint64_t nsp_status; 201610bf14bSChaoyong He struct nfp_cpp *cpp = state->cpp; 202c7e9729dSAlejandro Lucero 203c7e9729dSAlejandro Lucero nsp_cpp = nfp_resource_cpp_id(state->res); 204c7e9729dSAlejandro Lucero nsp_status = nfp_resource_address(state->res) + NSP_STATUS; 205c7e9729dSAlejandro Lucero 206c7e9729dSAlejandro Lucero err = nfp_cpp_readq(cpp, nsp_cpp, nsp_status, ®); 207efa766e1SChaoyong He if (err < 0) { 208b6de4353SZerun Fu PMD_DRV_LOG(ERR, "NSP - CPP readq failed %d.", err); 209c7e9729dSAlejandro Lucero return err; 210efa766e1SChaoyong He } 211c7e9729dSAlejandro Lucero 212c7e9729dSAlejandro Lucero if (FIELD_GET(NSP_STATUS_MAGIC, reg) != NSP_MAGIC) { 213b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Can not detect NFP Service Processor."); 214c7e9729dSAlejandro Lucero return -ENODEV; 215c7e9729dSAlejandro Lucero } 216c7e9729dSAlejandro Lucero 217c7e9729dSAlejandro Lucero state->ver.major = FIELD_GET(NSP_STATUS_MAJOR, reg); 218c7e9729dSAlejandro Lucero state->ver.minor = FIELD_GET(NSP_STATUS_MINOR, reg); 219c7e9729dSAlejandro Lucero 2208ad2cc8fSPeng Zhang if (state->ver.major > NSP_MAJOR || state->ver.minor < NSP_MINOR) { 221b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Unsupported ABI %hu.%hu.", state->ver.major, 222c7e9729dSAlejandro Lucero state->ver.minor); 223c7e9729dSAlejandro Lucero return -EINVAL; 224c7e9729dSAlejandro Lucero } 225c7e9729dSAlejandro Lucero 2264aa75cadSChaoyong He if ((reg & NSP_STATUS_BUSY) != 0) { 2278412feedSZerun Fu PMD_DRV_LOG(DEBUG, "Service processor busy!"); 228c7e9729dSAlejandro Lucero return -EBUSY; 229c7e9729dSAlejandro Lucero } 230c7e9729dSAlejandro Lucero 231c7e9729dSAlejandro Lucero return 0; 232c7e9729dSAlejandro Lucero } 233c7e9729dSAlejandro Lucero 2346d03aa61SChaoyong He /** 2356d03aa61SChaoyong He * Prepare for communication and lock the NSP resource. 2366d03aa61SChaoyong He * 2376d03aa61SChaoyong He * @param cpp 2386d03aa61SChaoyong He * NFP CPP Handle 239c7e9729dSAlejandro Lucero */ 240c7e9729dSAlejandro Lucero struct nfp_nsp * 241c7e9729dSAlejandro Lucero nfp_nsp_open(struct nfp_cpp *cpp) 242c7e9729dSAlejandro Lucero { 243c7e9729dSAlejandro Lucero int err; 244610bf14bSChaoyong He struct nfp_nsp *state; 245610bf14bSChaoyong He struct nfp_resource *res; 246c7e9729dSAlejandro Lucero 247c7e9729dSAlejandro Lucero res = nfp_resource_acquire(cpp, NFP_RESOURCE_NSP); 248efa766e1SChaoyong He if (res == NULL) { 249b6de4353SZerun Fu PMD_DRV_LOG(ERR, "NSP - resource acquire failed."); 250c7e9729dSAlejandro Lucero return NULL; 251efa766e1SChaoyong He } 252c7e9729dSAlejandro Lucero 253c7e9729dSAlejandro Lucero state = malloc(sizeof(*state)); 254cbcbfd73SJames Hershaw if (state == NULL) { 255aa6b4a80SHuaxing Zhu PMD_DRV_LOG(ERR, "NSP - failed to malloc name %s", NFP_RESOURCE_NSP); 256c7e9729dSAlejandro Lucero nfp_resource_release(res); 257c7e9729dSAlejandro Lucero return NULL; 258c7e9729dSAlejandro Lucero } 259c7e9729dSAlejandro Lucero memset(state, 0, sizeof(*state)); 260c7e9729dSAlejandro Lucero state->cpp = cpp; 261c7e9729dSAlejandro Lucero state->res = res; 262c7e9729dSAlejandro Lucero 263c7e9729dSAlejandro Lucero err = nfp_nsp_check(state); 2644aa75cadSChaoyong He if (err != 0) { 265b6de4353SZerun Fu PMD_DRV_LOG(DEBUG, "NSP - check failed."); 266c7e9729dSAlejandro Lucero nfp_nsp_close(state); 267c7e9729dSAlejandro Lucero return NULL; 268c7e9729dSAlejandro Lucero } 269c7e9729dSAlejandro Lucero 270c7e9729dSAlejandro Lucero return state; 271c7e9729dSAlejandro Lucero } 272c7e9729dSAlejandro Lucero 2736d03aa61SChaoyong He /** 2746d03aa61SChaoyong He * Clean up and unlock the NSP resource. 2756d03aa61SChaoyong He * 2766d03aa61SChaoyong He * @param state 2776d03aa61SChaoyong He * NFP SP state 278c7e9729dSAlejandro Lucero */ 279c7e9729dSAlejandro Lucero void 280c7e9729dSAlejandro Lucero nfp_nsp_close(struct nfp_nsp *state) 281c7e9729dSAlejandro Lucero { 282c7e9729dSAlejandro Lucero nfp_resource_release(state->res); 283c7e9729dSAlejandro Lucero free(state); 284c7e9729dSAlejandro Lucero } 285c7e9729dSAlejandro Lucero 286c7e9729dSAlejandro Lucero uint16_t 287c7e9729dSAlejandro Lucero nfp_nsp_get_abi_ver_major(struct nfp_nsp *state) 288c7e9729dSAlejandro Lucero { 289c7e9729dSAlejandro Lucero return state->ver.major; 290c7e9729dSAlejandro Lucero } 291c7e9729dSAlejandro Lucero 292c7e9729dSAlejandro Lucero uint16_t 293c7e9729dSAlejandro Lucero nfp_nsp_get_abi_ver_minor(struct nfp_nsp *state) 294c7e9729dSAlejandro Lucero { 295c7e9729dSAlejandro Lucero return state->ver.minor; 296c7e9729dSAlejandro Lucero } 297c7e9729dSAlejandro Lucero 298c7e9729dSAlejandro Lucero static int 299d108b9e9SChaoyong He nfp_nsp_wait_reg(struct nfp_cpp *cpp, 300d108b9e9SChaoyong He uint64_t *reg, 301d108b9e9SChaoyong He uint32_t nsp_cpp, 302d108b9e9SChaoyong He uint64_t addr, 303d108b9e9SChaoyong He uint64_t mask, 304d108b9e9SChaoyong He uint64_t val) 305c7e9729dSAlejandro Lucero { 306c7e9729dSAlejandro Lucero int err; 307610bf14bSChaoyong He uint32_t count = 0; 308610bf14bSChaoyong He struct timespec wait; 309c7e9729dSAlejandro Lucero 310c7e9729dSAlejandro Lucero wait.tv_sec = 0; 3116d03aa61SChaoyong He wait.tv_nsec = 25000000; /* 25ms */ 312c7e9729dSAlejandro Lucero 313c7e9729dSAlejandro Lucero for (;;) { 314c7e9729dSAlejandro Lucero err = nfp_cpp_readq(cpp, nsp_cpp, addr, reg); 315efa766e1SChaoyong He if (err < 0) { 316b6de4353SZerun Fu PMD_DRV_LOG(ERR, "NSP - CPP readq failed."); 317c7e9729dSAlejandro Lucero return err; 318efa766e1SChaoyong He } 319c7e9729dSAlejandro Lucero 320c7e9729dSAlejandro Lucero if ((*reg & mask) == val) 321c7e9729dSAlejandro Lucero return 0; 322c7e9729dSAlejandro Lucero 323c7e9729dSAlejandro Lucero nanosleep(&wait, 0); 3246d03aa61SChaoyong He if (count++ > 1000) /* 25ms * 1000 = 25s */ 325c7e9729dSAlejandro Lucero return -ETIMEDOUT; 326c7e9729dSAlejandro Lucero } 327c7e9729dSAlejandro Lucero } 328c7e9729dSAlejandro Lucero 3296d03aa61SChaoyong He /** 3306d03aa61SChaoyong He * Execute a command on the NFP Service Processor 331c7e9729dSAlejandro Lucero * 3326d03aa61SChaoyong He * @param state 3336d03aa61SChaoyong He * NFP SP state 3346d03aa61SChaoyong He * @param arg 3356d03aa61SChaoyong He * NFP command argument structure 336c7e9729dSAlejandro Lucero * 3376d03aa61SChaoyong He * @return 3386d03aa61SChaoyong He * - 0 for success with no result 3396d03aa61SChaoyong He * - Positive value for NSP completion with a result code 3406d03aa61SChaoyong He * - -EAGAIN if the NSP is not yet present 3416d03aa61SChaoyong He * - -ENODEV if the NSP is not a supported model 3426d03aa61SChaoyong He * - -EBUSY if the NSP is stuck 3436d03aa61SChaoyong He * - -EINTR if interrupted while waiting for completion 3446d03aa61SChaoyong He * - -ETIMEDOUT if the NSP took longer than @timeout_sec seconds to complete 345c7e9729dSAlejandro Lucero */ 346c7e9729dSAlejandro Lucero static int 347acaa57efSChaoyong He nfp_nsp_command_real(struct nfp_nsp *state, 348acaa57efSChaoyong He const struct nfp_nsp_command_arg *arg) 349c7e9729dSAlejandro Lucero { 350c7e9729dSAlejandro Lucero int err; 351610bf14bSChaoyong He uint64_t reg; 352610bf14bSChaoyong He uint32_t nsp_cpp; 353610bf14bSChaoyong He uint64_t ret_val; 354610bf14bSChaoyong He uint64_t nsp_base; 355610bf14bSChaoyong He uint64_t nsp_buffer; 356610bf14bSChaoyong He uint64_t nsp_status; 357610bf14bSChaoyong He uint64_t nsp_command; 358610bf14bSChaoyong He struct nfp_cpp *cpp = state->cpp; 359c7e9729dSAlejandro Lucero 360c7e9729dSAlejandro Lucero nsp_cpp = nfp_resource_cpp_id(state->res); 361c7e9729dSAlejandro Lucero nsp_base = nfp_resource_address(state->res); 362c7e9729dSAlejandro Lucero nsp_status = nsp_base + NSP_STATUS; 363c7e9729dSAlejandro Lucero nsp_command = nsp_base + NSP_COMMAND; 364c7e9729dSAlejandro Lucero nsp_buffer = nsp_base + NSP_BUFFER; 365c7e9729dSAlejandro Lucero 366c7e9729dSAlejandro Lucero err = nfp_nsp_check(state); 367efa766e1SChaoyong He if (err != 0) { 368b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Check NSP command failed."); 369c7e9729dSAlejandro Lucero return err; 370efa766e1SChaoyong He } 371c7e9729dSAlejandro Lucero 372acaa57efSChaoyong He err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_buffer, arg->buf); 373aa6b4a80SHuaxing Zhu if (err < 0) { 374aa6b4a80SHuaxing Zhu PMD_DRV_LOG(ERR, "CPP write buffer failed. err %d", err); 375c7e9729dSAlejandro Lucero return err; 376aa6b4a80SHuaxing Zhu } 377c7e9729dSAlejandro Lucero 378c7e9729dSAlejandro Lucero err = nfp_cpp_writeq(cpp, nsp_cpp, nsp_command, 379acaa57efSChaoyong He FIELD_PREP(NSP_COMMAND_OPTION, arg->option) | 380847aa891SPeng Zhang FIELD_PREP(NSP_COMMAND_VER_MAJOR, state->ver.major) | 381acaa57efSChaoyong He FIELD_PREP(NSP_COMMAND_CODE, arg->code) | 382acaa57efSChaoyong He FIELD_PREP(NSP_COMMAND_DMA_BUF, arg->dma) | 383c7e9729dSAlejandro Lucero FIELD_PREP(NSP_COMMAND_START, 1)); 384aa6b4a80SHuaxing Zhu if (err < 0) { 385aa6b4a80SHuaxing Zhu PMD_DRV_LOG(ERR, "CPP write command failed. err %d", err); 386c7e9729dSAlejandro Lucero return err; 387aa6b4a80SHuaxing Zhu } 388c7e9729dSAlejandro Lucero 389c7e9729dSAlejandro Lucero /* Wait for NSP_COMMAND_START to go to 0 */ 390c7e9729dSAlejandro Lucero err = nfp_nsp_wait_reg(cpp, ®, nsp_cpp, nsp_command, 391c7e9729dSAlejandro Lucero NSP_COMMAND_START, 0); 3924aa75cadSChaoyong He if (err != 0) { 393b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Error %d waiting for code %#04x to start.", 394acaa57efSChaoyong He err, arg->code); 395c7e9729dSAlejandro Lucero return err; 396c7e9729dSAlejandro Lucero } 397c7e9729dSAlejandro Lucero 398c7e9729dSAlejandro Lucero /* Wait for NSP_STATUS_BUSY to go to 0 */ 399d108b9e9SChaoyong He err = nfp_nsp_wait_reg(cpp, ®, nsp_cpp, nsp_status, 400d108b9e9SChaoyong He NSP_STATUS_BUSY, 0); 4014aa75cadSChaoyong He if (err != 0) { 402b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Error %d waiting for code %#04x to complete.", 403acaa57efSChaoyong He err, arg->code); 404c7e9729dSAlejandro Lucero return err; 405c7e9729dSAlejandro Lucero } 406c7e9729dSAlejandro Lucero 407c7e9729dSAlejandro Lucero err = nfp_cpp_readq(cpp, nsp_cpp, nsp_command, &ret_val); 408aa6b4a80SHuaxing Zhu if (err < 0) { 409aa6b4a80SHuaxing Zhu PMD_DRV_LOG(ERR, "CPP read return value failed. err %d", err); 410c7e9729dSAlejandro Lucero return err; 411aa6b4a80SHuaxing Zhu } 412f842b01aSChaoyong He 413c7e9729dSAlejandro Lucero ret_val = FIELD_GET(NSP_COMMAND_OPTION, ret_val); 414c7e9729dSAlejandro Lucero 415c7e9729dSAlejandro Lucero err = FIELD_GET(NSP_STATUS_RESULT, reg); 4164aa75cadSChaoyong He if (err != 0) { 417acaa57efSChaoyong He if (!arg->error_quiet) 418b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Result (error) code set: %d (%d) command: %d.", 419acaa57efSChaoyong He -err, (int)ret_val, arg->code); 420acaa57efSChaoyong He 421acaa57efSChaoyong He if (arg->error_cb != 0) 422acaa57efSChaoyong He arg->error_cb(state, ret_val); 423acaa57efSChaoyong He else 424c7e9729dSAlejandro Lucero nfp_nsp_print_extended_error(ret_val); 425acaa57efSChaoyong He 426c7e9729dSAlejandro Lucero return -err; 427c7e9729dSAlejandro Lucero } 428c7e9729dSAlejandro Lucero 429c7e9729dSAlejandro Lucero return ret_val; 430c7e9729dSAlejandro Lucero } 431c7e9729dSAlejandro Lucero 432acaa57efSChaoyong He static int 433acaa57efSChaoyong He nfp_nsp_command(struct nfp_nsp *state, 434acaa57efSChaoyong He uint16_t code) 435acaa57efSChaoyong He { 436acaa57efSChaoyong He const struct nfp_nsp_command_arg arg = { 437acaa57efSChaoyong He .code = code, 438acaa57efSChaoyong He }; 439acaa57efSChaoyong He 440acaa57efSChaoyong He return nfp_nsp_command_real(state, &arg); 441acaa57efSChaoyong He } 442c7e9729dSAlejandro Lucero 443c7e9729dSAlejandro Lucero static int 444acaa57efSChaoyong He nfp_nsp_command_buf_def(struct nfp_nsp *nsp, 445acaa57efSChaoyong He struct nfp_nsp_command_buf_arg *arg) 446c7e9729dSAlejandro Lucero { 447610bf14bSChaoyong He int err; 448610bf14bSChaoyong He int ret; 449610bf14bSChaoyong He uint64_t reg; 450c7e9729dSAlejandro Lucero uint32_t cpp_id; 451610bf14bSChaoyong He uint64_t cpp_buf; 452610bf14bSChaoyong He struct nfp_cpp *cpp = nsp->cpp; 453c7e9729dSAlejandro Lucero 454acaa57efSChaoyong He err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res), 455acaa57efSChaoyong He nfp_resource_address(nsp->res) + NSP_DFLT_BUFFER, 456acaa57efSChaoyong He ®); 457acaa57efSChaoyong He if (err < 0) 458acaa57efSChaoyong He return err; 459acaa57efSChaoyong He 460acaa57efSChaoyong He cpp_id = FIELD_GET(NSP_DFLT_BUFFER_CPP, reg) << 8; 461acaa57efSChaoyong He cpp_buf = FIELD_GET(NSP_DFLT_BUFFER_ADDRESS, reg); 462acaa57efSChaoyong He 463acaa57efSChaoyong He if (arg->in_buf != NULL && arg->in_size > 0) { 464acaa57efSChaoyong He err = nfp_cpp_write(cpp, cpp_id, cpp_buf, 465acaa57efSChaoyong He arg->in_buf, arg->in_size); 466acaa57efSChaoyong He if (err < 0) 467acaa57efSChaoyong He return err; 468acaa57efSChaoyong He } 469acaa57efSChaoyong He 470acaa57efSChaoyong He /* Zero out remaining part of the buffer */ 471acaa57efSChaoyong He if (arg->out_buf != NULL && arg->out_size > arg->in_size) { 472acaa57efSChaoyong He err = nfp_cpp_write(cpp, cpp_id, cpp_buf + arg->in_size, 473acaa57efSChaoyong He arg->out_buf, arg->out_size - arg->in_size); 474acaa57efSChaoyong He if (err < 0) 475acaa57efSChaoyong He return err; 476acaa57efSChaoyong He } 477acaa57efSChaoyong He 478acaa57efSChaoyong He if (!FIELD_FIT(NSP_BUFFER_CPP, cpp_id >> 8) || 479acaa57efSChaoyong He !FIELD_FIT(NSP_BUFFER_ADDRESS, cpp_buf)) { 480b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Buffer out of reach %#08x %#016lx.", 481acaa57efSChaoyong He cpp_id, cpp_buf); 482acaa57efSChaoyong He return -EINVAL; 483acaa57efSChaoyong He } 484acaa57efSChaoyong He 485acaa57efSChaoyong He arg->arg.buf = FIELD_PREP(NSP_BUFFER_CPP, cpp_id >> 8) | 486acaa57efSChaoyong He FIELD_PREP(NSP_BUFFER_ADDRESS, cpp_buf); 487acaa57efSChaoyong He ret = nfp_nsp_command_real(nsp, &arg->arg); 488acaa57efSChaoyong He if (ret < 0) { 4899e76c352SChaoyong He if (!arg->arg.error_quiet) 490b6de4353SZerun Fu PMD_DRV_LOG(ERR, "NSP command failed."); 4919e76c352SChaoyong He 492acaa57efSChaoyong He return ret; 493acaa57efSChaoyong He } 494acaa57efSChaoyong He 495acaa57efSChaoyong He if (arg->out_buf != NULL && arg->out_size > 0) { 496acaa57efSChaoyong He err = nfp_cpp_read(cpp, cpp_id, cpp_buf, 497acaa57efSChaoyong He arg->out_buf, arg->out_size); 498acaa57efSChaoyong He if (err < 0) 499acaa57efSChaoyong He return err; 500acaa57efSChaoyong He } 501acaa57efSChaoyong He 502acaa57efSChaoyong He return ret; 503acaa57efSChaoyong He } 504acaa57efSChaoyong He 505acaa57efSChaoyong He #define SZ_1M 0x00100000 506acaa57efSChaoyong He #define SZ_4K 0x00001000 507acaa57efSChaoyong He 508acaa57efSChaoyong He static int 509acaa57efSChaoyong He nfp_nsp_command_buf(struct nfp_nsp *nsp, 510acaa57efSChaoyong He struct nfp_nsp_command_buf_arg *arg) 511acaa57efSChaoyong He { 512acaa57efSChaoyong He int err; 513acaa57efSChaoyong He size_t size; 514acaa57efSChaoyong He uint64_t reg; 515acaa57efSChaoyong He size_t max_size; 516acaa57efSChaoyong He struct nfp_cpp *cpp = nsp->cpp; 517acaa57efSChaoyong He 518c7e9729dSAlejandro Lucero if (nsp->ver.minor < 13) { 519b6de4353SZerun Fu PMD_DRV_LOG(ERR, "NSP: Code %#04x with buffer not supported ABI %hu.%hu).", 520acaa57efSChaoyong He arg->arg.code, nsp->ver.major, nsp->ver.minor); 521c7e9729dSAlejandro Lucero return -EOPNOTSUPP; 522c7e9729dSAlejandro Lucero } 523c7e9729dSAlejandro Lucero 524c7e9729dSAlejandro Lucero err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res), 525d108b9e9SChaoyong He nfp_resource_address(nsp->res) + NSP_DFLT_BUFFER_CONFIG, 526c7e9729dSAlejandro Lucero ®); 527c7e9729dSAlejandro Lucero if (err < 0) 528c7e9729dSAlejandro Lucero return err; 529c7e9729dSAlejandro Lucero 530acaa57efSChaoyong He max_size = RTE_MAX(arg->in_size, arg->out_size); 531acaa57efSChaoyong He size = FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M + 532acaa57efSChaoyong He FIELD_GET(NSP_DFLT_BUFFER_SIZE_4KB, reg) * SZ_4K; 533acaa57efSChaoyong He if (size < max_size) { 534b6de4353SZerun Fu PMD_DRV_LOG(ERR, "NSP: default buffer too small for command %#04x (%zu < %zu).", 535acaa57efSChaoyong He arg->arg.code, size, max_size); 536c7e9729dSAlejandro Lucero return -EINVAL; 537c7e9729dSAlejandro Lucero } 538c7e9729dSAlejandro Lucero 539acaa57efSChaoyong He return nfp_nsp_command_buf_def(nsp, arg); 540c7e9729dSAlejandro Lucero } 541c7e9729dSAlejandro Lucero 542c7e9729dSAlejandro Lucero int 543c7e9729dSAlejandro Lucero nfp_nsp_wait(struct nfp_nsp *state) 544c7e9729dSAlejandro Lucero { 545c7e9729dSAlejandro Lucero int err; 546610bf14bSChaoyong He int count = 0; 547610bf14bSChaoyong He struct timespec wait; 548c7e9729dSAlejandro Lucero 549c7e9729dSAlejandro Lucero wait.tv_sec = 0; 5506d03aa61SChaoyong He wait.tv_nsec = 25000000; /* 25ms */ 551c7e9729dSAlejandro Lucero 552c7e9729dSAlejandro Lucero for (;;) { 553acaa57efSChaoyong He err = nfp_nsp_command(state, SPCODE_NOOP); 554c7e9729dSAlejandro Lucero if (err != -EAGAIN) 555c7e9729dSAlejandro Lucero break; 556c7e9729dSAlejandro Lucero 557c7e9729dSAlejandro Lucero nanosleep(&wait, 0); 558c7e9729dSAlejandro Lucero 5596d03aa61SChaoyong He if (count++ > 1000) { /* 25ms * 1000 = 25s */ 560c7e9729dSAlejandro Lucero err = -ETIMEDOUT; 561c7e9729dSAlejandro Lucero break; 562c7e9729dSAlejandro Lucero } 563c7e9729dSAlejandro Lucero } 564f842b01aSChaoyong He 5654aa75cadSChaoyong He if (err != 0) 566b6de4353SZerun Fu PMD_DRV_LOG(ERR, "NSP failed to respond %d.", err); 567c7e9729dSAlejandro Lucero 568c7e9729dSAlejandro Lucero return err; 569c7e9729dSAlejandro Lucero } 570c7e9729dSAlejandro Lucero 571c7e9729dSAlejandro Lucero int 572c7e9729dSAlejandro Lucero nfp_nsp_device_soft_reset(struct nfp_nsp *state) 573c7e9729dSAlejandro Lucero { 574acaa57efSChaoyong He return nfp_nsp_command(state, SPCODE_SOFT_RESET); 575c7e9729dSAlejandro Lucero } 576c7e9729dSAlejandro Lucero 577c7e9729dSAlejandro Lucero int 578c7e9729dSAlejandro Lucero nfp_nsp_mac_reinit(struct nfp_nsp *state) 579c7e9729dSAlejandro Lucero { 580acaa57efSChaoyong He return nfp_nsp_command(state, SPCODE_MAC_INIT); 581acaa57efSChaoyong He } 582acaa57efSChaoyong He 583acaa57efSChaoyong He static void 584acaa57efSChaoyong He nfp_nsp_load_fw_extended_msg(struct nfp_nsp *state, 585acaa57efSChaoyong He uint32_t ret_val) 586acaa57efSChaoyong He { 587acaa57efSChaoyong He uint32_t minor; 588acaa57efSChaoyong He uint32_t major; 589acaa57efSChaoyong He static const char * const major_msg[] = { 590acaa57efSChaoyong He /* 0 */ "Firmware from driver loaded", 591acaa57efSChaoyong He /* 1 */ "Firmware from flash loaded", 592acaa57efSChaoyong He /* 2 */ "Firmware loading failure", 593acaa57efSChaoyong He }; 594acaa57efSChaoyong He static const char * const minor_msg[] = { 595acaa57efSChaoyong He /* 0 */ "", 596acaa57efSChaoyong He /* 1 */ "no named partition on flash", 597acaa57efSChaoyong He /* 2 */ "error reading from flash", 598acaa57efSChaoyong He /* 3 */ "can not deflate", 599acaa57efSChaoyong He /* 4 */ "not a trusted file", 600acaa57efSChaoyong He /* 5 */ "can not parse FW file", 601acaa57efSChaoyong He /* 6 */ "MIP not found in FW file", 602acaa57efSChaoyong He /* 7 */ "null firmware name in MIP", 603acaa57efSChaoyong He /* 8 */ "FW version none", 604acaa57efSChaoyong He /* 9 */ "FW build number none", 605acaa57efSChaoyong He /* 10 */ "no FW selection policy HWInfo key found", 606acaa57efSChaoyong He /* 11 */ "static FW selection policy", 607acaa57efSChaoyong He /* 12 */ "FW version has precedence", 608acaa57efSChaoyong He /* 13 */ "different FW application load requested", 609acaa57efSChaoyong He /* 14 */ "development build", 610acaa57efSChaoyong He }; 611acaa57efSChaoyong He 612acaa57efSChaoyong He major = FIELD_GET(NFP_FW_LOAD_RET_MAJOR, ret_val); 613acaa57efSChaoyong He minor = FIELD_GET(NFP_FW_LOAD_RET_MINOR, ret_val); 614acaa57efSChaoyong He 615acaa57efSChaoyong He if (!nfp_nsp_has_stored_fw_load(state)) 616acaa57efSChaoyong He return; 617acaa57efSChaoyong He 618acaa57efSChaoyong He if (major >= RTE_DIM(major_msg)) 619b6de4353SZerun Fu PMD_DRV_LOG(INFO, "FW loading status: %x.", ret_val); 620acaa57efSChaoyong He else if (minor >= RTE_DIM(minor_msg)) 621b6de4353SZerun Fu PMD_DRV_LOG(INFO, "%s, reason code: %d.", major_msg[major], minor); 622acaa57efSChaoyong He else 623acaa57efSChaoyong He PMD_DRV_LOG(INFO, "%s%c %s", major_msg[major], 624acaa57efSChaoyong He minor != 0 ? ',' : '.', minor_msg[minor]); 625c7e9729dSAlejandro Lucero } 626c7e9729dSAlejandro Lucero 627c7e9729dSAlejandro Lucero int 628d108b9e9SChaoyong He nfp_nsp_load_fw(struct nfp_nsp *state, 629d108b9e9SChaoyong He void *buf, 630c69debceSChaoyong He size_t size) 631c7e9729dSAlejandro Lucero { 632acaa57efSChaoyong He int ret; 633acaa57efSChaoyong He struct nfp_nsp_command_buf_arg load_fw = { 634acaa57efSChaoyong He { 635acaa57efSChaoyong He .code = SPCODE_FW_LOAD, 636acaa57efSChaoyong He .option = size, 637acaa57efSChaoyong He .error_cb = nfp_nsp_load_fw_extended_msg, 638acaa57efSChaoyong He }, 639acaa57efSChaoyong He .in_buf = buf, 640acaa57efSChaoyong He .in_size = size, 641acaa57efSChaoyong He }; 642acaa57efSChaoyong He 643acaa57efSChaoyong He ret = nfp_nsp_command_buf(state, &load_fw); 644acaa57efSChaoyong He if (ret < 0) 645acaa57efSChaoyong He return ret; 646acaa57efSChaoyong He 647acaa57efSChaoyong He nfp_nsp_load_fw_extended_msg(state, ret); 648acaa57efSChaoyong He 649acaa57efSChaoyong He return 0; 650c7e9729dSAlejandro Lucero } 651c7e9729dSAlejandro Lucero 652f53439aaSPeng Zhang bool 653f53439aaSPeng Zhang nfp_nsp_fw_loaded(struct nfp_nsp *state) 654f53439aaSPeng Zhang { 655f53439aaSPeng Zhang return nfp_nsp_command(state, SPCODE_FW_LOADED) > 0; 656f53439aaSPeng Zhang } 657f53439aaSPeng Zhang 658c7e9729dSAlejandro Lucero int 659d108b9e9SChaoyong He nfp_nsp_read_eth_table(struct nfp_nsp *state, 660d108b9e9SChaoyong He void *buf, 661c69debceSChaoyong He size_t size) 662c7e9729dSAlejandro Lucero { 663acaa57efSChaoyong He struct nfp_nsp_command_buf_arg eth_rescan = { 664acaa57efSChaoyong He { 665acaa57efSChaoyong He .code = SPCODE_ETH_RESCAN, 666acaa57efSChaoyong He .option = size, 667acaa57efSChaoyong He }, 668acaa57efSChaoyong He .out_buf = buf, 669acaa57efSChaoyong He .out_size = size, 670acaa57efSChaoyong He }; 671acaa57efSChaoyong He 672acaa57efSChaoyong He return nfp_nsp_command_buf(state, ð_rescan); 673c7e9729dSAlejandro Lucero } 674c7e9729dSAlejandro Lucero 675c7e9729dSAlejandro Lucero int 676d108b9e9SChaoyong He nfp_nsp_write_eth_table(struct nfp_nsp *state, 677d108b9e9SChaoyong He const void *buf, 678c69debceSChaoyong He size_t size) 679c7e9729dSAlejandro Lucero { 680acaa57efSChaoyong He struct nfp_nsp_command_buf_arg eth_ctrl = { 681acaa57efSChaoyong He { 682acaa57efSChaoyong He .code = SPCODE_ETH_CONTROL, 683acaa57efSChaoyong He .option = size, 684acaa57efSChaoyong He }, 685acaa57efSChaoyong He .in_buf = buf, 686acaa57efSChaoyong He .in_size = size, 687acaa57efSChaoyong He }; 688acaa57efSChaoyong He 689acaa57efSChaoyong He return nfp_nsp_command_buf(state, ð_ctrl); 690c7e9729dSAlejandro Lucero } 691c7e9729dSAlejandro Lucero 692c7e9729dSAlejandro Lucero int 693d108b9e9SChaoyong He nfp_nsp_read_identify(struct nfp_nsp *state, 694d108b9e9SChaoyong He void *buf, 695c69debceSChaoyong He size_t size) 696c7e9729dSAlejandro Lucero { 697acaa57efSChaoyong He struct nfp_nsp_command_buf_arg identify = { 698acaa57efSChaoyong He { 699acaa57efSChaoyong He .code = SPCODE_NSP_IDENTIFY, 700acaa57efSChaoyong He .option = size, 701acaa57efSChaoyong He }, 702acaa57efSChaoyong He .out_buf = buf, 703acaa57efSChaoyong He .out_size = size, 704acaa57efSChaoyong He }; 705acaa57efSChaoyong He 706acaa57efSChaoyong He return nfp_nsp_command_buf(state, &identify); 707c7e9729dSAlejandro Lucero } 708c7e9729dSAlejandro Lucero 709c7e9729dSAlejandro Lucero int 710d108b9e9SChaoyong He nfp_nsp_read_sensors(struct nfp_nsp *state, 711c69debceSChaoyong He uint32_t sensor_mask, 712d108b9e9SChaoyong He void *buf, 713c69debceSChaoyong He size_t size) 714c7e9729dSAlejandro Lucero { 715acaa57efSChaoyong He struct nfp_nsp_command_buf_arg sensors = { 716acaa57efSChaoyong He { 717acaa57efSChaoyong He .code = SPCODE_NSP_SENSORS, 718acaa57efSChaoyong He .option = sensor_mask, 719acaa57efSChaoyong He }, 720acaa57efSChaoyong He .out_buf = buf, 721acaa57efSChaoyong He .out_size = size, 722acaa57efSChaoyong He }; 723acaa57efSChaoyong He 724acaa57efSChaoyong He return nfp_nsp_command_buf(state, &sensors); 725c7e9729dSAlejandro Lucero } 726c7a6970fSZerun Fu 727c7a6970fSZerun Fu int 728c7a6970fSZerun Fu nfp_nsp_hwinfo_set(struct nfp_nsp *state, 729c7a6970fSZerun Fu const void *buf, 730c7a6970fSZerun Fu size_t size) 731c7a6970fSZerun Fu { 732c7a6970fSZerun Fu struct nfp_nsp_command_buf_arg hwinfo_set = { 733c7a6970fSZerun Fu { 734c7a6970fSZerun Fu .code = SPCODE_HWINFO_SET, 735c7a6970fSZerun Fu .option = size, 736c7a6970fSZerun Fu }, 737c7a6970fSZerun Fu .in_buf = buf, 738c7a6970fSZerun Fu .in_size = size, 739c7a6970fSZerun Fu }; 740c7a6970fSZerun Fu 741c7a6970fSZerun Fu return nfp_nsp_command_buf(state, &hwinfo_set); 742c7a6970fSZerun Fu } 7433110ab73SZerun Fu 7443110ab73SZerun Fu int 74508461d7bSPeng Zhang nfp_nsp_device_activate(struct nfp_nsp *state) 74608461d7bSPeng Zhang { 74708461d7bSPeng Zhang if (nfp_nsp_get_abi_ver_minor(state) < 38) 74808461d7bSPeng Zhang return -EOPNOTSUPP; 74908461d7bSPeng Zhang 75008461d7bSPeng Zhang return nfp_nsp_command(state, SPCODE_DEV_ACTIVATE); 75108461d7bSPeng Zhang } 75208461d7bSPeng Zhang 75308461d7bSPeng Zhang int 7543110ab73SZerun Fu nfp_nsp_read_media(struct nfp_nsp *state, 7553110ab73SZerun Fu void *buf, 7563110ab73SZerun Fu size_t size) 7573110ab73SZerun Fu { 7583110ab73SZerun Fu struct nfp_nsp_command_buf_arg media = { 7593110ab73SZerun Fu { 7603110ab73SZerun Fu .code = SPCODE_READ_MEDIA, 7613110ab73SZerun Fu .option = size, 7623110ab73SZerun Fu }, 7633110ab73SZerun Fu .out_buf = buf, 7643110ab73SZerun Fu .out_size = size, 7653110ab73SZerun Fu }; 7663110ab73SZerun Fu 7673110ab73SZerun Fu return nfp_nsp_command_buf(state, &media); 7683110ab73SZerun Fu } 7699e76c352SChaoyong He 7709e76c352SChaoyong He int 7719e76c352SChaoyong He nfp_nsp_load_stored_fw(struct nfp_nsp *state) 7729e76c352SChaoyong He { 7739e76c352SChaoyong He int ret; 7749e76c352SChaoyong He struct nfp_nsp_command_buf_arg fw_stored = { 7759e76c352SChaoyong He { 7769e76c352SChaoyong He .code = SPCODE_FW_STORED, 7779e76c352SChaoyong He .error_cb = nfp_nsp_load_fw_extended_msg, 7789e76c352SChaoyong He }, 7799e76c352SChaoyong He }; 7809e76c352SChaoyong He 7819e76c352SChaoyong He ret = nfp_nsp_command_buf(state, &fw_stored); 7829e76c352SChaoyong He if (ret < 0) 7839e76c352SChaoyong He return ret; 7849e76c352SChaoyong He 7859e76c352SChaoyong He nfp_nsp_load_fw_extended_msg(state, ret); 7869e76c352SChaoyong He 7879e76c352SChaoyong He return 0; 7889e76c352SChaoyong He } 7899e76c352SChaoyong He 7909e76c352SChaoyong He static int 7919e76c352SChaoyong He nfp_nsp_hwinfo_lookup_real(struct nfp_nsp *state, 7929e76c352SChaoyong He void *buf, 7939e76c352SChaoyong He size_t size, 7949e76c352SChaoyong He bool optional) 7959e76c352SChaoyong He { 7969e76c352SChaoyong He struct nfp_nsp_command_buf_arg hwinfo_lookup = { 7979e76c352SChaoyong He { 7989e76c352SChaoyong He .code = SPCODE_HWINFO_LOOKUP, 7999e76c352SChaoyong He .option = size, 8009e76c352SChaoyong He .error_quiet = optional, 8019e76c352SChaoyong He }, 8029e76c352SChaoyong He .in_buf = buf, 8039e76c352SChaoyong He .in_size = size, 8049e76c352SChaoyong He .out_buf = buf, 8059e76c352SChaoyong He .out_size = size, 8069e76c352SChaoyong He }; 8079e76c352SChaoyong He 8089e76c352SChaoyong He return nfp_nsp_command_buf(state, &hwinfo_lookup); 8099e76c352SChaoyong He } 8109e76c352SChaoyong He 8117f693813SChaoyong He static int 8127f693813SChaoyong He nfp_nsp_read_module_eeprom_real(struct nfp_nsp *state, 8137f693813SChaoyong He void *buf, 8147f693813SChaoyong He uint32_t size) 8157f693813SChaoyong He { 8167f693813SChaoyong He struct nfp_nsp_command_buf_arg module_eeprom = { 8177f693813SChaoyong He { 8187f693813SChaoyong He .code = SPCODE_READ_SFF_EEPROM, 8197f693813SChaoyong He .option = size, 8207f693813SChaoyong He }, 8217f693813SChaoyong He .in_buf = buf, 8227f693813SChaoyong He .in_size = size, 8237f693813SChaoyong He .out_buf = buf, 8247f693813SChaoyong He .out_size = size, 8257f693813SChaoyong He }; 8267f693813SChaoyong He 8277f693813SChaoyong He return nfp_nsp_command_buf(state, &module_eeprom); 8287f693813SChaoyong He } 8297f693813SChaoyong He 8307f693813SChaoyong He int 8317f693813SChaoyong He nfp_nsp_read_module_eeprom(struct nfp_nsp *state, 8327f693813SChaoyong He int eth_index, 8337f693813SChaoyong He uint32_t offset, 8347f693813SChaoyong He void *data, 8357f693813SChaoyong He uint32_t len, 8367f693813SChaoyong He uint32_t *read_len) 8377f693813SChaoyong He { 8387f693813SChaoyong He int ret; 8397f693813SChaoyong He int bufsz; 840*e7750639SAndre Muezerie struct __rte_packed_begin eeprom_buf { 8417f693813SChaoyong He uint8_t metalen; 8427f693813SChaoyong He rte_le16_t length; 8437f693813SChaoyong He rte_le16_t offset; 8447f693813SChaoyong He rte_le16_t readlen; 8457f693813SChaoyong He uint8_t eth_index; 8467f693813SChaoyong He uint8_t data[]; 847*e7750639SAndre Muezerie } __rte_packed_end * buf; 8487f693813SChaoyong He 8497f693813SChaoyong He /* Buffer must be large enough and rounded to the next block size. */ 8507f693813SChaoyong He bufsz = sizeof(*(buf)) + sizeof((buf)->data[0]) * 8517f693813SChaoyong He (RTE_ALIGN_CEIL(len, NSP_SFF_EEPROM_BLOCK_LEN)); 8527f693813SChaoyong He buf = calloc(1, bufsz); 8537f693813SChaoyong He if (buf == NULL) 8547f693813SChaoyong He return -ENOMEM; 8557f693813SChaoyong He 8567f693813SChaoyong He buf->metalen = offsetof(struct eeprom_buf, data) / NSP_SFF_EEPROM_BLOCK_LEN; 8577f693813SChaoyong He buf->length = rte_cpu_to_le_16(len); 8587f693813SChaoyong He buf->offset = rte_cpu_to_le_16(offset); 8597f693813SChaoyong He buf->eth_index = eth_index; 8607f693813SChaoyong He 8617f693813SChaoyong He ret = nfp_nsp_read_module_eeprom_real(state, buf, bufsz); 8627f693813SChaoyong He if (ret != 0) 8637f693813SChaoyong He goto free_exit; 8647f693813SChaoyong He 8657f693813SChaoyong He if (rte_le_to_cpu_16(buf->readlen) < len) { 8667f693813SChaoyong He ret = -EIO; 8677f693813SChaoyong He goto free_exit; 8687f693813SChaoyong He } 8697f693813SChaoyong He 8707f693813SChaoyong He if (len != 0) 8717f693813SChaoyong He memcpy(data, buf->data, len); 8727f693813SChaoyong He 8737f693813SChaoyong He *read_len = len; 8747f693813SChaoyong He 8757f693813SChaoyong He free_exit: 8767f693813SChaoyong He free(buf); 8777f693813SChaoyong He return ret; 8787f693813SChaoyong He } 8797f693813SChaoyong He 8807f693813SChaoyong He int 8817f693813SChaoyong He nfp_nsp_hwinfo_lookup(struct nfp_nsp *state, 8827f693813SChaoyong He void *buf, 8837f693813SChaoyong He uint32_t size) 8847f693813SChaoyong He { 8857f693813SChaoyong He int ret; 8867f693813SChaoyong He uint32_t size_tmp; 8877f693813SChaoyong He 8887f693813SChaoyong He if (!nfp_nsp_has_hwinfo_lookup(state)) { 8897f693813SChaoyong He PMD_DRV_LOG(ERR, "NSP HWinfo lookup not supported. Please update flash."); 8907f693813SChaoyong He return -EOPNOTSUPP; 8917f693813SChaoyong He } 8927f693813SChaoyong He 8937f693813SChaoyong He size_tmp = RTE_MIN(size, NFP_HWINFO_LOOKUP_SIZE); 8947f693813SChaoyong He 8957f693813SChaoyong He ret = nfp_nsp_hwinfo_lookup_real(state, buf, size, false); 8967f693813SChaoyong He if (ret != 0) 8977f693813SChaoyong He return ret; 8987f693813SChaoyong He 8997f693813SChaoyong He if (strnlen(buf, size_tmp) == size_tmp) { 9007f693813SChaoyong He PMD_DRV_LOG(ERR, "NSP HWinfo value not NULL terminated."); 9017f693813SChaoyong He return -EINVAL; 9027f693813SChaoyong He } 9037f693813SChaoyong He 9047f693813SChaoyong He return 0; 9057f693813SChaoyong He } 9067f693813SChaoyong He 9079e76c352SChaoyong He int 9089e76c352SChaoyong He nfp_nsp_hwinfo_lookup_optional(struct nfp_nsp *state, 9099e76c352SChaoyong He void *buf, 9109e76c352SChaoyong He size_t size, 9119e76c352SChaoyong He const char *default_val) 9129e76c352SChaoyong He { 9139e76c352SChaoyong He int ret; 9149e76c352SChaoyong He size_t min_size; 9159e76c352SChaoyong He 9169e76c352SChaoyong He if (strnlen(default_val, size) == size) { 917b6de4353SZerun Fu PMD_DRV_LOG(ERR, "NSP HWinfo default value not NULL terminated."); 9189e76c352SChaoyong He return -EINVAL; 9199e76c352SChaoyong He } 9209e76c352SChaoyong He 9219e76c352SChaoyong He if (!nfp_nsp_has_hwinfo_lookup(state)) 9229e76c352SChaoyong He goto default_return; 9239e76c352SChaoyong He 9249e76c352SChaoyong He min_size = RTE_MIN(size, NFP_HWINFO_LOOKUP_SIZE); 9259e76c352SChaoyong He ret = nfp_nsp_hwinfo_lookup_real(state, buf, min_size, true); 9269e76c352SChaoyong He if (ret != 0) { 9279e76c352SChaoyong He if (ret == -ENOENT) 9289e76c352SChaoyong He goto default_return; 9299e76c352SChaoyong He 930b6de4353SZerun Fu PMD_DRV_LOG(ERR, "NSP HWinfo lookup failed: %d.", ret); 9319e76c352SChaoyong He return ret; 9329e76c352SChaoyong He } 9339e76c352SChaoyong He 9349e76c352SChaoyong He if (strnlen(buf, min_size) == min_size) { 935b6de4353SZerun Fu PMD_DRV_LOG(ERR, "NSP HWinfo value not NULL terminated."); 9369e76c352SChaoyong He return -EINVAL; 9379e76c352SChaoyong He } 9389e76c352SChaoyong He 9399e76c352SChaoyong He return 0; 9409e76c352SChaoyong He 9419e76c352SChaoyong He default_return: 9429e76c352SChaoyong He strlcpy(buf, default_val, size); 9439e76c352SChaoyong He return 0; 9449e76c352SChaoyong He } 945