The original logic don't support load firmware for cards which has no DDR, add the related logic to make it can load firmware successfully.
Signed-off-by: Chaoyong He <chaoyong...@corigine.com> Reviewed-by: Long Wu <long...@corigine.com> Reviewed-by: Peng Zhang <peng.zh...@corigine.com> --- drivers/net/nfp/nfpcore/nfp_nsp.c | 131 +++++++++++++++++++++++++++++- 1 file changed, 128 insertions(+), 3 deletions(-) diff --git a/drivers/net/nfp/nfpcore/nfp_nsp.c b/drivers/net/nfp/nfpcore/nfp_nsp.c index 9837b3354b..dd212a6d7c 100644 --- a/drivers/net/nfp/nfpcore/nfp_nsp.c +++ b/drivers/net/nfp/nfpcore/nfp_nsp.c @@ -37,9 +37,12 @@ #define NSP_DFLT_BUFFER_ADDRESS GENMASK_ULL(39, 0) #define NSP_DFLT_BUFFER_CONFIG 0x20 +#define NSP_DFLT_BUFFER_DMA_CHUNK_ORDER GENMASK_ULL(63, 58) #define NSP_DFLT_BUFFER_SIZE_4KB GENMASK_ULL(15, 8) #define NSP_DFLT_BUFFER_SIZE_MB GENMASK_ULL(7, 0) +#define NFP_CAP_CMD_DMA_SG 0x28 + #define NSP_MAGIC 0xab10 /* @@ -85,6 +88,18 @@ enum nfp_nsp_cmd { SPCODE_DEV_ACTIVATE = 29, /* Activate hardware for multiple pfs case */ }; +struct nfp_nsp_dma_desc { + rte_le32_t size; + rte_le32_t reserved; + rte_le64_t addr; +}; + +struct nfp_nsp_dma_buf { + rte_le32_t chunk_cnt; + rte_le32_t reserved[3]; + struct nfp_nsp_dma_desc descs[]; +}; + static const struct { uint32_t code; const char *msg; @@ -502,6 +517,109 @@ nfp_nsp_command_buf_def(struct nfp_nsp *nsp, return ret; } +static int +nfp_nsp_command_buf_dma_sg(struct nfp_nsp *nsp, + struct nfp_nsp_command_buf_arg *arg, + size_t max_size, + size_t chunk_order) +{ + int ret; + void *chunks; + uint32_t nseg; + size_t total_len; + size_t chunk_size; + rte_iova_t buf_dma; + rte_iova_t chunks_dma; + struct nfp_nsp_dma_buf *buf; + struct nfp_nsp_dma_desc *descs; + + chunk_size = RTE_BIT64(chunk_order); + nseg = DIV_ROUND_UP(max_size, chunk_size); + + /* Malloc memory */ + total_len = sizeof(struct nfp_nsp_dma_buf) + + nseg * sizeof(struct nfp_nsp_dma_desc) + + nseg * chunk_size; + buf = rte_zmalloc(NULL, total_len, 0); + buf_dma = rte_malloc_virt2iova(buf); + + /* Populate struct nfp_nsp_dma_buf */ + buf->chunk_cnt = rte_cpu_to_le_32(nseg); + + /* Init start pointer of sections */ + descs = (void *)((char *)buf + sizeof(struct nfp_nsp_dma_buf)); + chunks = (char *)descs + nseg * sizeof(struct nfp_nsp_dma_desc); + chunks_dma = buf_dma + sizeof(struct nfp_nsp_dma_buf) + + nseg * sizeof(struct nfp_nsp_dma_desc); + + /* Copy in_arg*/ + rte_memcpy(chunks, arg->in_buf, arg->in_size); + + /* Populate struct nfp_nsp_dma_desc */ + for (uint32_t i = 0; i < nseg; i++) { + descs[i].size = rte_cpu_to_le_32(chunk_size); + descs[i].addr = rte_cpu_to_le_64(chunks_dma + i * chunk_size); + } + descs[nseg - 1].size = rte_cpu_to_le_32(max_size - chunk_size * (nseg - 1)); + + /* Send to nsp */ + arg->arg.dma = true; + arg->arg.buf = buf_dma; + ret = nfp_nsp_command_real(nsp, &arg->arg); + if (ret < 0) { + PMD_DRV_LOG(ERR, "NSP: SG DMA failed for command 0x%04x: %d", + arg->arg.code, ret); + goto free_exit; + } + + /* Copy out_arg */ + if (arg->out_buf != NULL && arg->out_size > 0) + rte_memcpy(arg->out_buf, chunks, arg->out_size); + +free_exit: + rte_free(buf); + + return ret; +} + +#define NFP_PAGE_SHIFT 12UL + +static int +nfp_nsp_command_buf_dma(struct nfp_nsp *nsp, + struct nfp_nsp_command_buf_arg *arg, + size_t max_size, + size_t dma_order) +{ + int err; + bool sg_ok; + uint64_t reg; + size_t buf_order; + size_t chunk_order; + struct nfp_cpp *cpp = nsp->cpp; + + err = nfp_cpp_readq(cpp, nfp_resource_cpp_id(nsp->res), + nfp_resource_address(nsp->res) + NFP_CAP_CMD_DMA_SG, + ®); + if (err < 0) + return err; + + sg_ok = reg & RTE_BIT64(arg->arg.code - 1); + if (!sg_ok) { + buf_order = rte_log2_u64(max_size); + if (buf_order > dma_order) { + PMD_DRV_LOG(ERR, "NSP: non-SG DMA for command 0x%04x fail", + arg->arg.code); + return -ENOMEM; + } + + chunk_order = buf_order; + } else { + chunk_order = RTE_MIN(dma_order, NFP_PAGE_SHIFT); + } + + return nfp_nsp_command_buf_dma_sg(nsp, arg, max_size, chunk_order); +} + #define SZ_1M 0x00100000 #define SZ_4K 0x00001000 @@ -513,6 +631,7 @@ nfp_nsp_command_buf(struct nfp_nsp *nsp, size_t size; uint64_t reg; size_t max_size; + size_t dma_order; struct nfp_cpp *cpp = nsp->cpp; if (nsp->ver.minor < 13) { @@ -530,13 +649,19 @@ nfp_nsp_command_buf(struct nfp_nsp *nsp, max_size = RTE_MAX(arg->in_size, arg->out_size); size = FIELD_GET(NSP_DFLT_BUFFER_SIZE_MB, reg) * SZ_1M + FIELD_GET(NSP_DFLT_BUFFER_SIZE_4KB, reg) * SZ_4K; - if (size < max_size) { + dma_order = FIELD_GET(NSP_DFLT_BUFFER_DMA_CHUNK_ORDER, reg); + + if (size >= max_size) { + err = nfp_nsp_command_buf_def(nsp, arg); + } else if (dma_order != 0) { + err = nfp_nsp_command_buf_dma(nsp, arg, max_size, dma_order); + } else { PMD_DRV_LOG(ERR, "NSP: default buffer too small for command %#04x (%zu < %zu).", arg->arg.code, size, max_size); - return -EINVAL; + err = -EINVAL; } - return nfp_nsp_command_buf_def(nsp, arg); + return err; } int -- 2.43.5