From patchwork Tue Feb 27 11:15:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chaoyong He X-Patchwork-Id: 137340 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id A88D243C08; Tue, 27 Feb 2024 12:16:21 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id A7CDE406BC; Tue, 27 Feb 2024 12:16:17 +0100 (CET) Received: from NAM10-DM6-obe.outbound.protection.outlook.com (mail-dm6nam10on2109.outbound.protection.outlook.com [40.107.93.109]) by mails.dpdk.org (Postfix) with ESMTP id 8B89D4027D for ; Tue, 27 Feb 2024 12:16:15 +0100 (CET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=GeKqH/F/4kDLKWuuVT5w5iPatX8JGUKkCVc8cd/QL9MVsY/YnomutN5LTZa8pEhWaWgPQay2+2WXLlY3yb3DdjUnQ4N1OTN1MnnHi9ex94iGbvWting2Rdzt/gntmYS1mqwCwM5op+LPgfeIQ1pXLSfpR8jjiGOwdL/rmbvjtTf98pLJytJwhdrVB1ewkHKqMa17EJF2cJ28ZIxUcLlrpy1HFL8TuxElr+RmhH2uK7Z9YqeLAqvE+at+GlQ9l1zzKPEtMV9TqSo2TUWfkDQDXk6vvYk8WvDykUxqbIO5r3OwOPYJUxq5oWs07mh+gU8pglSNtvRJ6tKSrlfaBt7UkQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=N28qLq3CnT5mgKfNjUtE2xEduE0DrZxn3KpAhSJ8E7w=; b=eY4HLlkJKqaTXuBveqbzoKUWvs6/6jr8G1MkAYNe1//EZfzQobBOzp2xY5sDP496mWxaVbPWtLz1kQpLPt57EFn/XamYTpvxozHEwjWBKol8CgMC0cqDHXYS1Rz0nf3farm5/p0g+SvI65o8k8H0S9UixOoi8llXZvViNHyYgBZf/KmT8kP7w/vNeW7V2Ni+QUC1+vqQm/e6+U2r7r7mqAmf1Zy+4NcbJ+mbp8QTl/ExltE7qRZH7n6I6j2ZJwVYlZxrLkclC1stIYT6dGh6LZfJK+tEtZgLArL3O9+VV9toLsEEeYZLlHF067VBPOkH7EI0ei7RMhXeIs+7YxZU5w== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=corigine.com; dmarc=pass action=none header.from=corigine.com; dkim=pass header.d=corigine.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=corigine.onmicrosoft.com; s=selector2-corigine-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=N28qLq3CnT5mgKfNjUtE2xEduE0DrZxn3KpAhSJ8E7w=; b=rY9XsMtyJt/bBdL1i7pUwDwKV8ddnZhbyrFOHev2daPdbSm9jQYLlJkbubZMKkNlneN1xWPwSm9GzozZYz9rbZFRquIst87KQa1QGLDiYBAMR97WQC8CJMAH0TGmcLDkTLipeHENqsYH7W0bY9kBgO7voo8eAyMEb4M3leXfGxM= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=corigine.com; Received: from SJ0PR13MB5545.namprd13.prod.outlook.com (2603:10b6:a03:424::5) by PH7PR13MB5843.namprd13.prod.outlook.com (2603:10b6:510:151::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7316.39; Tue, 27 Feb 2024 11:16:13 +0000 Received: from SJ0PR13MB5545.namprd13.prod.outlook.com ([fe80::8e02:f738:570a:f8aa]) by SJ0PR13MB5545.namprd13.prod.outlook.com ([fe80::8e02:f738:570a:f8aa%7]) with mapi id 15.20.7316.035; Tue, 27 Feb 2024 11:16:13 +0000 From: Chaoyong He To: dev@dpdk.org Cc: oss-drivers@corigine.com, Peng Zhang , Chaoyong He , Long Wu Subject: [PATCH 1/3] net/nfp: add the elf module Date: Tue, 27 Feb 2024 19:15:49 +0800 Message-Id: <20240227111551.3773862-2-chaoyong.he@corigine.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20240227111551.3773862-1-chaoyong.he@corigine.com> References: <20240227111551.3773862-1-chaoyong.he@corigine.com> X-ClientProxiedBy: BY5PR20CA0002.namprd20.prod.outlook.com (2603:10b6:a03:1f4::15) To SJ0PR13MB5545.namprd13.prod.outlook.com (2603:10b6:a03:424::5) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SJ0PR13MB5545:EE_|PH7PR13MB5843:EE_ X-MS-Office365-Filtering-Correlation-Id: c3acae22-fe55-4984-df17-08dc378581f9 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: ccIRc8h3eUeFi6c6YatUyo0QJhjF94k+xZu9gYhMiCDJzKnaD3Uhg/6KlgmMDrtBQfN13tXgw+38hlM8KRD1tFjhVtnJWC/D/4R09k+UChPHR+V+cIoJWrSYItopo3BfgjQgKMirjYYUaqoKIqOdFtH9jgD5k33moELWftWlyj0GvzF8xWub99dSjPYGoFSuQOTU22U575amZGY8PFxA18uVQMH228hexRLYS3AtwCipSH0A3L7ukbuEyQMFmnmXCgK75s8pqa3zBmln0slPYnlvik28j8oA5+O3kI724TSME2dH8jDNBiGOWwSsSiXpnV9IIm2FbqbarJv9H7F32hlOjFfPJAC1memXbxfhQdrOkPOEWW/tTz6D2d7BlB72EpDuyyVbNIefUsHqv7mTo+IqjLSa6dmMC0x57n8XiD7/oOK0y7c+Y+w+AHEnkJQvITJeecJq0k4IZgj4B+rQ+gDsCInqIK8xQ93PIlQ3c5L0C462LOnPKPCLRtas8BOLfGCdgnot5noDADf1YFieI6+/BXZAd3RGem6fXmgBo5ZbO3wqZUgqCqU2z7weBJD1QSChhIolbyn5mXDrmZxK153xJHTl78zcMnedmMaRs0ukKUBhNCW6/6rjhfsXb2I8JNeg+pNhQkBrHdnQODbvkuGVYFdKbcHHDYhu5RETqkDwwJotVQ2x0+s7G9ql9B+lYgaZdEvPkWFM6ri1SPSZjw== X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:SJ0PR13MB5545.namprd13.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230031)(38350700005); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: MDLcP3wH+qn+Rn9IF3ji3xrPuROTMCIR37IUVq1/oBEDX0sPFYENL2IMHx+LaBmGJhj8p9TOUjSKOfd3GCbmodOlM1HWVzVlCPPL034xBP+YRBeXfkHEdJiSsJDBxSM3o6FGeapoMpm6v09t7zhx8sstjVp8QgHeUsVMKS03ZyYIZfukmALxkcKcs4zcPrpvU7Gvc5luojr7pA32VB0eyyUNfz/27YDvvLlQ/Np86a9300YY8SBM+1WZkhd/spMHfT9keeB4rRRC+hVxOZ5GKiEy9pt3Y/8P6N1/XYG/1howY8xcKUyZ3Sz2n0zZyT4YMxsW3YbTQo2+6PLHWR1+77W1mt9O6n5QgbT/3ysxpvqeWL4m8o0Qhia2PFnNrUiNpjc2u9Ead+4DPMZNOh7O8RXwBA2KNFe+E8aabBWp304A7hfQdUqyYRVFNPOagEUSAFa0BRSsLI5bqDDLMpfaeKf2p0hrpwRsyH46idlfKQnlpjJm98QnNzjfhakaDhxxiuAxaehXHtiYoX2pj3DoehglOX0ITSqTVFU4Zn4GXdCfGprEYROy1YJN72iqsLiZ8ASrDor94V3rOrCm99fHv9eTlfaOLd0gUvkfx/P9zhTDTYr2hJVdg3HVJVNJJaE1nL9f3sizlEufolfvber8QzoUBE0Pf40DEK0fktD2CZ59IuRqRs+llvZoABNYnKXxkwFCaG1Ie+YOU5BwGisHHMH6nSs6nrARp5n7HIabTyxieTRs7elFu5HMSz1aAgDYUaQjk+IrAdFlQwjLSyGLLwx+GRZzngY1f1lGXzoE+y/Q/R4ftHXDQrAiS7g+lO23wjp0cy47vL70rrsIo5erFKH+GNvxafPwIpRHBZsAn805buC58f/tpxSZ7f4VQ0EMbAZwCTURlxts+PaqTgxtL7p8KP5BVDPtKbjoZocde+Ch+IaioFJOHduBt3KRFsLBrafeM/i5I1Naqcg+D/huTwU8UTacAP2bqcT5EpFK4z2xJOFiuYGfrj/SXOdx39FLiWd+iPLTo6D1rgxKW8bXmSlyX9Bdmble+fhpeSVR2IZ9d3lATY/uOhPsRO7uN2fYQv9MQb4D+fIZY/Y2g6AVcUfatIdfvV4+/wW326nN/BS3xN4LeDFKiQ9I6NkOOYBddm31TzOJJPnmE0Vt0+OJKa4ptxJnWGjcXUEFWGrJgZWxuQ3UujvG3WWOvazobcM+u0/eIXB+/zB7KNlLaVT6aG9mQPda782FCe3buCO58Pcore31Sxh+OibAGOWJ9rQg1fazOnNPYwi2r/TR0KqPG97CHurcawLgvlmjKGxEa8kbu0pxROrU1ueBLLPigLcWM5/H4xFUtNcJ90Tyqe0NzNAjM6JuSh9nGeMIuxZ97D5Xz0mNTPO9+6l9Yqtic8s3o0vFpvf4Xue2BXqq9162TJY2mIGGWgOXMuFhO28lmudBTx/MtRwwql3j22iT1lLTqQGnI2r/4rQnhU8UDZXtZUYof26bGAG0AJmavF5Qoe+gV/i9qyapMQNQwxYkE5wHX8mTe7yNXqewn1ofUv2TqcRG4MPJ+73R/+V9sX/i5a1IoXtvKwIUlaDfQ6JSwmzo+Ae+ZQWsUYEEnWkMq1b6fg== X-OriginatorOrg: corigine.com X-MS-Exchange-CrossTenant-Network-Message-Id: c3acae22-fe55-4984-df17-08dc378581f9 X-MS-Exchange-CrossTenant-AuthSource: SJ0PR13MB5545.namprd13.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Feb 2024 11:16:13.7499 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: fe128f2c-073b-4c20-818e-7246a585940c X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: J0nruyGpqAosWfAdzSNJcZSmQ5QFcLKGaxNud6HULBHMPb4MgHfJuBr15RVNVLIZW7c+qmW6cIjeQrNeTFbnPIOk0ZW56kZAJA2QDzUBfy0= X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR13MB5843 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Peng Zhang Add the elf module, which can get mip information from the firmware ELF file. Signed-off-by: Peng Zhang Reviewed-by: Chaoyong He Reviewed-by: Long Wu --- drivers/net/nfp/meson.build | 1 + drivers/net/nfp/nfpcore/nfp_elf.c | 1079 +++++++++++++++++++++++++++++ drivers/net/nfp/nfpcore/nfp_elf.h | 13 + drivers/net/nfp/nfpcore/nfp_mip.c | 30 +- drivers/net/nfp/nfpcore/nfp_mip.h | 70 +- 5 files changed, 1168 insertions(+), 25 deletions(-) create mode 100644 drivers/net/nfp/nfpcore/nfp_elf.c create mode 100644 drivers/net/nfp/nfpcore/nfp_elf.h diff --git a/drivers/net/nfp/meson.build b/drivers/net/nfp/meson.build index e376fd328f..959ca01844 100644 --- a/drivers/net/nfp/meson.build +++ b/drivers/net/nfp/meson.build @@ -18,6 +18,7 @@ sources = files( 'nfdk/nfp_nfdk_dp.c', 'nfpcore/nfp_cppcore.c', 'nfpcore/nfp_crc.c', + 'nfpcore/nfp_elf.c', 'nfpcore/nfp_hwinfo.c', 'nfpcore/nfp_mip.c', 'nfpcore/nfp_mutex.c', diff --git a/drivers/net/nfp/nfpcore/nfp_elf.c b/drivers/net/nfp/nfpcore/nfp_elf.c new file mode 100644 index 0000000000..fbd350589b --- /dev/null +++ b/drivers/net/nfp/nfpcore/nfp_elf.c @@ -0,0 +1,1079 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2023 Corigine, Inc. + * All rights reserved. + */ + +#include "nfp_elf.h" + +#include +#include +#include + +#include +#include +#include + +#include "nfp_logs.h" +#include "nfp_mip.h" + +/* + * NFP Chip Families. + * + * These are not enums, because they need to be microcode compatible. + * They are also not maskable. + * + * Note: The NFP-4xxx family is handled as NFP-6xxx in most software + * components. + */ +#define NFP_CHIP_FAMILY_NFP3800 0x3800 +#define NFP_CHIP_FAMILY_NFP6000 0x6000 + +/* Standard ELF */ +#define NFP_ELF_EI_NIDENT 16 +#define NFP_ELF_EI_MAG0 0 +#define NFP_ELF_EI_MAG1 1 +#define NFP_ELF_EI_MAG2 2 +#define NFP_ELF_EI_MAG3 3 +#define NFP_ELF_EI_CLASS 4 +#define NFP_ELF_EI_DATA 5 +#define NFP_ELF_EI_VERSION 6 +#define NFP_ELF_EI_PAD 7 +#define NFP_ELF_ELFMAG0 0x7f +#define NFP_ELF_ELFMAG1 'E' +#define NFP_ELF_ELFMAG2 'L' +#define NFP_ELF_ELFMAG3 'F' +#define NFP_ELF_ELFCLASSNONE 0 +#define NFP_ELF_ELFCLASS32 1 +#define NFP_ELF_ELFCLASS64 2 +#define NFP_ELF_ELFDATANONE 0 +#define NFP_ELF_ELFDATA2LSB 1 +#define NFP_ELF_ELFDATA2MSB 2 + +#define NFP_ELF_ET_NONE 0 +#define NFP_ELF_ET_REL 1 +#define NFP_ELF_ET_EXEC 2 +#define NFP_ELF_ET_DYN 3 +#define NFP_ELF_ET_CORE 4 +#define NFP_ELF_ET_LOPROC 0xFF00 +#define NFP_ELF_ET_HIPROC 0xFFFF +#define NFP_ELF_ET_NFP_PARTIAL_REL (NFP_ELF_ET_LOPROC + NFP_ELF_ET_REL) +#define NFP_ELF_ET_NFP_PARTIAL_EXEC (NFP_ELF_ET_LOPROC + NFP_ELF_ET_EXEC) + +#define NFP_ELF_EM_NFP 250 +#define NFP_ELF_EM_NFP6000 0x6000 + +#define NFP_ELF_SHT_NULL 0 +#define NFP_ELF_SHT_PROGBITS 1 +#define NFP_ELF_SHT_SYMTAB 2 +#define NFP_ELF_SHT_STRTAB 3 +#define NFP_ELF_SHT_RELA 4 +#define NFP_ELF_SHT_HASH 5 +#define NFP_ELF_SHT_DYNAMIC 6 +#define NFP_ELF_SHT_NOTE 7 +#define NFP_ELF_SHT_NOBITS 8 +#define NFP_ELF_SHT_REL 9 +#define NFP_ELF_SHT_SHLIB 10 +#define NFP_ELF_SHT_DYNSYM 11 +#define NFP_ELF_SHT_LOPROC 0x70000000 +#define NFP_ELF_SHT_HIPROC 0x7fffffff +#define NFP_ELF_SHT_LOUSER 0x80000000 +#define NFP_ELF_SHT_HIUSER 0x8fffffff + +#define NFP_ELF_EV_NONE 0 +#define NFP_ELF_EV_CURRENT 1 + +#define NFP_ELF_SHN_UNDEF 0 + +/* EM_NFP ELF flags */ + +/* + * Valid values for FAMILY are: + * 0x6000 - NFP-6xxx/NFP-4xxx + * 0x3800 - NFP-38xx + */ +#define NFP_ELF_EF_NFP_FAMILY_MASK 0xFFFF +#define NFP_ELF_EF_NFP_FAMILY_LSB 8 + +#define NFP_ELF_SHT_NFP_MECONFIG (NFP_ELF_SHT_LOPROC + 1) +#define NFP_ELF_SHT_NFP_INITREG (NFP_ELF_SHT_LOPROC + 2) +#define NFP_ELF_SHT_UOF_DEBUG (NFP_ELF_SHT_LOUSER) + +/* NFP target revision note type */ +#define NFP_ELT_NOTE_NAME_NFP "NFP\0" +#define NFP_ELT_NOTE_NAME_NFP_SZ 4 +#define NFP_ELT_NOTE_NAME_NFP_USER "NFP_USR\0" +#define NFP_ELT_NOTE_NAME_NFP_USER_SZ 8 +#define NFP_ELF_NT_NFP_BUILD_INFO 0x100 +#define NFP_ELF_NT_NFP_REVS 0x101 +#define NFP_ELF_NT_NFP_MIP_LOCATION 0x102 +#define NFP_ELF_NT_NFP_USER 0xf0000000 + + +/* Standard ELF structures */ +struct nfp_elf_elf64_ehdr { + uint8_t e_ident[NFP_ELF_EI_NIDENT]; + rte_le16_t e_type; + rte_le16_t e_machine; + rte_le32_t e_version; + rte_le64_t e_entry; + rte_le64_t e_phoff; + rte_le64_t e_shoff; + rte_le32_t e_flags; + rte_le16_t e_ehsize; + rte_le16_t e_phentsize; + rte_le16_t e_phnum; + rte_le16_t e_shentsize; + rte_le16_t e_shnum; + rte_le16_t e_shstrndx; +}; + +struct nfp_elf_elf64_shdr { + rte_le32_t sh_name; + rte_le32_t sh_type; + rte_le64_t sh_flags; + rte_le64_t sh_addr; + rte_le64_t sh_offset; + rte_le64_t sh_size; + rte_le32_t sh_link; + rte_le32_t sh_info; + rte_le64_t sh_addralign; + rte_le64_t sh_entsize; +}; + +struct nfp_elf_elf64_sym { + rte_le32_t st_name; + uint8_t st_info; + uint8_t st_other; + rte_le16_t st_shndx; + rte_le64_t st_value; + rte_le64_t st_size; +}; + +struct nfp_elf_elf64_rel { + rte_le64_t r_offset; + rte_le64_t r_info; +}; + +struct nfp_elf_elf64_nhdr { + rte_le32_t n_namesz; + rte_le32_t n_descsz; + rte_le32_t n_type; +}; + +/* NFP specific structures */ +struct nfp_elf_elf_meconfig { + rte_le32_t ctx_enables; + rte_le32_t entry; + rte_le32_t misc_control; + rte_le32_t reserved; +}; + +struct nfp_elf_elf_initregentry { + rte_le32_t w0; + rte_le32_t cpp_offset_lo; + rte_le32_t val; + rte_le32_t mask; +}; + +/* NFP NFFW ELF struct and API */ +struct nfp_elf_user_note { + const char *name; + uint32_t data_sz; + void *data; +}; + +/* + * nfp_elf_fw_mip contains firmware related fields from the MIP as well as the + * MIP location in the NFFW file. All fields are only valid if shndx > 0. + * + * This struct will only be available if the firmware contains a .note section + * with a note of type NFP_ELF_NT_NFP_MIP_LOCATION. + */ +struct nfp_elf_fw_mip { + size_t shndx; + uint64_t sh_offset; + rte_le32_t mip_ver; /**< Version of the format of the MIP itself */ + + rte_le32_t fw_version; + rte_le32_t fw_buildnum; + rte_le32_t fw_buildtime; + char fw_name[20]; /**< At most 16 chars, 17 ensures '\0', round up */ + const char *fw_typeid; /**< NULL if none set */ +}; + +/* + * It is preferred to access this struct via the nfp_elf functions + * rather than directly. + */ +struct nfp_elf { + struct nfp_elf_elf64_ehdr *ehdr; + struct nfp_elf_elf64_shdr *shdrs; + size_t shdrs_cnt; + void **shdrs_data; + + /** True if section data has been endian swapped */ + uint8_t *shdrs_host_endian; + + size_t shdr_idx_symtab; + + struct nfp_elf_elf64_sym *syms; + size_t syms_cnt; + + char *shstrtab; + size_t shstrtab_sz; + + char *symstrtab; + size_t symstrtab_sz; + + struct nfp_elf_elf_meconfig *meconfs; + size_t meconfs_cnt; + + /* ==== .note data start ==== */ + + /** + * Following data derived from SHT_NOTE sections for read-only usage. + * These fields are not used in nfp_elf_to_buf() + */ + int rev_min; /**< -1 if file did not specify */ + int rev_max; /**< -1 if file did not specify */ + + /** + * If mip_shndx == 0 and mip_sh_off == 0, the .note stated there is no MIP. + * If mip_shndx == 0 and mip_sh_off == UINT64_MAX, there was no .note and + * a MIP _may_ still be found in the first 256KiB of DRAM/EMEM data. + */ + size_t mip_shndx; /**< Section in which MIP resides, 0 if no MIP */ + uint64_t mip_sh_off; /**< Offset within section (not address) */ + + struct nfp_elf_fw_mip fw_mip; + const char *fw_info_strtab; + size_t fw_info_strtab_sz; + + /* ==== .note.user data start ==== */ + size_t user_note_cnt; + struct nfp_elf_user_note *user_notes; + + void *dbgdata; + + int family; + + /** + * For const entry points in the API, we allocate and keep a buffer + * and for mutable entry points we assume the buffer remains valid + * and we just set pointers to it. + */ + void *_buf; + size_t _bufsz; +}; + +static void +nfp_elf_free(struct nfp_elf *ectx) +{ + if (ectx == NULL) + return; + + free(ectx->shdrs); + free(ectx->shdrs_data); + free(ectx->shdrs_host_endian); + if (ectx->_bufsz != 0) + free(ectx->_buf); + + free(ectx); +} + +static size_t +nfp_elf_get_sec_ent_cnt(struct nfp_elf *ectx, + size_t idx) +{ + uint64_t sh_size = rte_le_to_cpu_64(ectx->shdrs[idx].sh_size); + uint64_t sh_entsize = rte_le_to_cpu_64(ectx->shdrs[idx].sh_entsize); + + if (sh_entsize != 0) + return sh_size / sh_entsize; + + return 0; +} + +static bool +nfp_elf_check_sh_size(uint64_t sh_size) +{ + if (sh_size == 0 || sh_size > UINT32_MAX) + return false; + + return true; +} + +static const char * +nfp_elf_fwinfo_next(struct nfp_elf *ectx, + const char *key_val) +{ + size_t s_len; + const char *strtab = ectx->fw_info_strtab; + ssize_t tab_sz = (ssize_t)ectx->fw_info_strtab_sz; + + if (key_val == NULL) + return strtab; + + s_len = strlen(key_val); + if (key_val < strtab || ((key_val + s_len + 1) >= (strtab + tab_sz - 1))) + return NULL; + + key_val += s_len + 1; + + return key_val; +} + +static const char * +nfp_elf_fwinfo_lookup(struct nfp_elf *ectx, + const char *key) +{ + size_t s_len; + const char *s; + size_t key_len = strlen(key); + const char *strtab = ectx->fw_info_strtab; + ssize_t tab_sz = (ssize_t)ectx->fw_info_strtab_sz; + + if (strtab == NULL) + return NULL; + + for (s = strtab, s_len = strlen(s) + 1; + (s[0] != '\0') && (tab_sz > 0); + s_len = strlen(s) + 1, tab_sz -= s_len, s += s_len) { + if ((strncmp(s, key, key_len) == 0) && (s[key_len] == '=')) + return &s[key_len + 1]; + } + + return NULL; +} + +static bool +nfp_elf_arch_is_thornham(struct nfp_elf *ectx) +{ + if (ectx == NULL) + return false; + + if (ectx->family == NFP_CHIP_FAMILY_NFP6000 || ectx->family == NFP_CHIP_FAMILY_NFP3800) + return true; + + return false; +} + +static int +nfp_elf_parse_sht_rel(struct nfp_elf_elf64_shdr *sec, + struct nfp_elf *ectx, + size_t idx, + uint8_t *buf8) +{ + uint64_t sh_size = rte_le_to_cpu_64(sec->sh_size); + uint64_t sh_offset = rte_le_to_cpu_64(sec->sh_offset); + uint64_t sh_entsize = rte_le_to_cpu_64(sec->sh_entsize); + + if (sh_entsize != sizeof(struct nfp_elf_elf64_rel)) { + PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); + return -EINVAL; + } + + if (!nfp_elf_check_sh_size(sh_size)) { + PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); + return -EINVAL; + } + + ectx->shdrs_data[idx] = buf8 + sh_offset; + ectx->shdrs_host_endian[idx] = 1; + + return 0; +} + +static int +nfp_elf_parse_note_name_nfp(struct nfp_elf *ectx, + size_t idx, + uint32_t ndescsz, + uint32_t ntype, + const char *nname, + rte_le32_t *descword) +{ + if (strncmp(nname, NFP_ELT_NOTE_NAME_NFP, NFP_ELT_NOTE_NAME_NFP_SZ) == 0) { + switch (ntype) { + case NFP_ELF_NT_NFP_REVS: + if (ndescsz != 8) { + PMD_DRV_LOG(ERR, "Invalid ELF NOTE descsz in section %zu.", idx); + return -EINVAL; + } + + ectx->rev_min = (int)rte_le_to_cpu_32(descword[0]); + ectx->rev_max = (int)rte_le_to_cpu_32(descword[1]); + break; + case NFP_ELF_NT_NFP_MIP_LOCATION: + if (ndescsz != 12) { + PMD_DRV_LOG(ERR, "Invalid ELF NOTE descsz in section %zu.", idx); + return -EINVAL; + } + + ectx->mip_shndx = rte_le_to_cpu_32(descword[0]); + if (ectx->mip_shndx == 0) { + ectx->mip_sh_off = 0; + break; + } + + if (ectx->mip_shndx >= ectx->shdrs_cnt) { + PMD_DRV_LOG(ERR, "Invalid ELF NOTE shndx in section %zu.", idx); + return -EINVAL; + } + + ectx->mip_sh_off = rte_le_to_cpu_32(descword[1]) | + (uint64_t)rte_le_to_cpu_32(descword[2]) << 32; + break; + default: + break; + } + } else if (strncmp(nname, NFP_ELT_NOTE_NAME_NFP_USER, + NFP_ELT_NOTE_NAME_NFP_USER_SZ) == 0 && ntype == NFP_ELF_NT_NFP_USER) { + ectx->user_note_cnt++; + } + + return 0; +} + +static int +nfp_elf_parse_sht_note(struct nfp_elf_elf64_shdr *sec, + struct nfp_elf *ectx, + size_t idx, + uint8_t *buf8) +{ + int err; + size_t nsz; + uint8_t *desc; + uint32_t ntype; + uint32_t nnamesz; + uint32_t ndescsz; + const char *nname; + uint8_t *shdrs_data; + rte_le32_t *descword; + struct nfp_elf_elf64_nhdr *nhdr; + struct nfp_elf_user_note *unote; + uint64_t sh_size = rte_le_to_cpu_64(sec->sh_size); + uint64_t sh_offset = rte_le_to_cpu_64(sec->sh_offset); + + if (!nfp_elf_check_sh_size(sh_size)) { + PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); + return -EINVAL; + } + + shdrs_data = buf8 + sh_offset; + ectx->shdrs_data[idx] = shdrs_data; + ectx->shdrs_host_endian[idx] = 0; + + /* Extract notes that we recognise */ + nhdr = (struct nfp_elf_elf64_nhdr *)shdrs_data; + + while ((uint8_t *)nhdr < (shdrs_data + sh_size)) { + nnamesz = rte_le_to_cpu_32(nhdr->n_namesz); + ndescsz = rte_le_to_cpu_32(nhdr->n_descsz); + ntype = rte_le_to_cpu_32(nhdr->n_type); + nname = (const char *)((uint8_t *)nhdr + sizeof(*nhdr)); + descword = (rte_le32_t *)((uint8_t *)nhdr + sizeof(*nhdr) + + ((nnamesz + UINT32_C(3)) & ~UINT32_C(3))); + + err = nfp_elf_parse_note_name_nfp(ectx, idx, ndescsz, ntype, nname, descword); + if (err != 0) + return err; + + nhdr = (struct nfp_elf_elf64_nhdr *)((uint8_t *)descword + + ((ndescsz + UINT32_C(3)) & ~UINT32_C(3))); + } + + if (ectx->user_note_cnt == 0) + return 0; + + ectx->user_notes = calloc(ectx->user_note_cnt, sizeof(*ectx->user_notes)); + if (ectx->user_notes == NULL) { + PMD_DRV_LOG(ERR, "Out of memory."); + return -ENOMEM; + } + + nhdr = (struct nfp_elf_elf64_nhdr *)shdrs_data; + unote = ectx->user_notes; + while ((uint8_t *)nhdr < (shdrs_data + sh_size)) { + nnamesz = rte_le_to_cpu_32(nhdr->n_namesz); + ndescsz = rte_le_to_cpu_32(nhdr->n_descsz); + ntype = rte_le_to_cpu_32(nhdr->n_type); + nname = (const char *)((uint8_t *)nhdr + sizeof(*nhdr)); + desc = (uint8_t *)nhdr + sizeof(*nhdr) + + ((nnamesz + UINT32_C(3)) & ~UINT32_C(3)); + + if (strncmp(nname, NFP_ELT_NOTE_NAME_NFP_USER, + NFP_ELT_NOTE_NAME_NFP_USER_SZ) != 0) + continue; + + if (ntype != NFP_ELF_NT_NFP_USER) + continue; + + unote->name = (const char *)desc; + nsz = strlen(unote->name) + 1; + if (nsz % 4 != 0) + nsz = ((nsz / 4) + 1) * 4; + if (nsz > ndescsz) { + PMD_DRV_LOG(ERR, "Invalid ELF USER NOTE descsz in section %zu.", idx); + return -EINVAL; + } + + unote->data_sz = ndescsz - (uint32_t)nsz; + if (unote->data_sz != 0) + unote->data = desc + nsz; + unote++; + + nhdr = (struct nfp_elf_elf64_nhdr *) + (desc + ((ndescsz + UINT32_C(3)) & ~UINT32_C(3))); + } + + return 0; +} + +static int +nfp_elf_parse_sht_meconfig(struct nfp_elf_elf64_shdr *sec, + struct nfp_elf *ectx, + size_t idx, + uint8_t *buf8) +{ + size_t ent_cnt; + uint8_t *shdrs_data; + uint64_t sh_size = rte_le_to_cpu_64(sec->sh_size); + uint64_t sh_offset = rte_le_to_cpu_64(sec->sh_offset); + + if (!nfp_elf_check_sh_size(sh_size)) { + PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); + return -EINVAL; + } + + shdrs_data = buf8 + sh_offset; + ent_cnt = nfp_elf_get_sec_ent_cnt(ectx, idx); + ectx->shdrs_data[idx] = shdrs_data; + ectx->meconfs = (struct nfp_elf_elf_meconfig *)shdrs_data; + ectx->meconfs_cnt = ent_cnt; + ectx->shdrs_host_endian[idx] = 1; + + return 0; +} + +static int +nfp_elf_parse_sht_initreg(struct nfp_elf_elf64_shdr *sec, + struct nfp_elf *ectx, + size_t idx, + uint8_t *buf8) +{ + uint64_t sh_size = rte_le_to_cpu_64(sec->sh_size); + uint64_t sh_offset = rte_le_to_cpu_64(sec->sh_offset); + uint64_t sh_entsize = rte_le_to_cpu_64(sec->sh_entsize); + + if (!nfp_elf_arch_is_thornham(ectx)) { + PMD_DRV_LOG(ERR, "Section not supported for target arch."); + return -ENOTSUP; + } + + if (sh_entsize != sizeof(struct nfp_elf_elf_initregentry) || + !nfp_elf_check_sh_size(sh_size)) { + PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); + return -EINVAL; + } + + ectx->shdrs_data[idx] = buf8 + sh_offset; + ectx->shdrs_host_endian[idx] = 1; + + return 0; +} + +static int +nfp_elf_parse_sht_symtab(struct nfp_elf_elf64_shdr *sec, + struct nfp_elf *ectx, + size_t idx, + uint8_t *buf8) +{ + uint64_t sh_size = rte_le_to_cpu_64(sec->sh_size); + uint64_t sh_offset = rte_le_to_cpu_64(sec->sh_offset); + uint64_t sh_entsize = rte_le_to_cpu_64(sec->sh_entsize); + + if (sh_entsize != sizeof(struct nfp_elf_elf64_sym) || + !nfp_elf_check_sh_size(sh_size)) { + PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); + return -EINVAL; + } + + ectx->shdrs_data[idx] = buf8 + sh_offset; + ectx->shdrs_host_endian[ectx->shdr_idx_symtab] = 1; + + return 0; +} + +static int +nfp_elf_populate_fw_mip(struct nfp_elf *ectx, + uint8_t *buf8) +{ + uint8_t *pu8; + const char *nx; + uint64_t sh_size; + uint64_t sh_offset; + uint32_t first_entry; + const struct nfp_mip *mip; + struct nfp_elf_elf64_shdr *sec; + const struct nfp_mip_entry *ent; + const struct nfp_mip_fwinfo_entry *fwinfo; + + sec = &ectx->shdrs[ectx->mip_shndx]; + sh_size = rte_le_to_cpu_64(sec->sh_size); + sh_offset = rte_le_to_cpu_64(sec->sh_offset); + pu8 = buf8 + sh_offset + ectx->mip_sh_off; + mip = (const struct nfp_mip *)pu8; + first_entry = rte_le_to_cpu_32(mip->first_entry); + + if (mip->signature != NFP_MIP_SIGNATURE) { + PMD_DRV_LOG(ERR, "Incorrect MIP signature %#08x", + rte_le_to_cpu_32(mip->signature)); + return -EINVAL; + } + + ectx->fw_mip.shndx = ectx->mip_shndx; + ectx->fw_mip.sh_offset = ectx->mip_sh_off; + ectx->fw_mip.mip_ver = mip->mip_version; + + if (ectx->fw_mip.mip_ver != NFP_MIP_VERSION) { + PMD_DRV_LOG(ERR, "MIP note pointer does not point to recognised version."); + return -EINVAL; + } + + ectx->fw_mip.fw_version = mip->version; + ectx->fw_mip.fw_buildnum = mip->buildnum; + ectx->fw_mip.fw_buildtime = mip->buildtime; + strncpy(ectx->fw_mip.fw_name, mip->name, 16); + + /* + * If there is a FWINFO v1 entry, it will be first and + * right after the MIP itself, so in the same section. + */ + if (ectx->mip_sh_off + first_entry + sizeof(*ent) < sh_size) { + pu8 += first_entry; + ent = (const struct nfp_mip_entry *)pu8; + if (ent->type == NFP_MIP_TYPE_FWINFO && ent->version == 1) { + pu8 += sizeof(*ent); + fwinfo = (const struct nfp_mip_fwinfo_entry *)pu8; + if (fwinfo->kv_len != 0) { + ectx->fw_info_strtab_sz = fwinfo->kv_len; + ectx->fw_info_strtab = fwinfo->key_value_strs; + } + } + } + + ectx->fw_mip.fw_typeid = nfp_elf_fwinfo_lookup(ectx, "TypeId"); + + /* + * TypeId will be the last reserved key-value pair, so skip + * to the first entry after it for the user values. + */ + if (ectx->fw_mip.fw_typeid == NULL) + return 0; + + nx = nfp_elf_fwinfo_next(ectx, ectx->fw_mip.fw_typeid); + if (nx == NULL) + ectx->fw_info_strtab_sz = 0; + else + ectx->fw_info_strtab_sz -= (nx - ectx->fw_info_strtab); + ectx->fw_info_strtab = nx; + + return 0; +} + +static int +nfp_elf_read_file_headers(struct nfp_elf *ectx, + void *buf) +{ + uint16_t e_type; + uint32_t e_flags; + uint32_t e_version; + uint16_t e_machine; + + ectx->ehdr = buf; + e_type = rte_le_to_cpu_16(ectx->ehdr->e_type); + e_flags = rte_le_to_cpu_32(ectx->ehdr->e_flags); + e_version = rte_le_to_cpu_32(ectx->ehdr->e_version); + e_machine = rte_le_to_cpu_16(ectx->ehdr->e_machine); + + switch (e_machine) { + case NFP_ELF_EM_NFP: + ectx->family = (e_flags >> NFP_ELF_EF_NFP_FAMILY_LSB) + & NFP_ELF_EF_NFP_FAMILY_MASK; + break; + case NFP_ELF_EM_NFP6000: + ectx->family = NFP_CHIP_FAMILY_NFP6000; + break; + default: + PMD_DRV_LOG(ERR, "Invalid ELF machine type."); + return -EINVAL; + } + + if ((e_type != NFP_ELF_ET_EXEC && e_type != NFP_ELF_ET_REL && + e_type != NFP_ELF_ET_NFP_PARTIAL_EXEC && + e_type != NFP_ELF_ET_NFP_PARTIAL_REL) || + e_version != NFP_ELF_EV_CURRENT || + ectx->ehdr->e_ehsize != sizeof(struct nfp_elf_elf64_ehdr) || + ectx->ehdr->e_shentsize != sizeof(struct nfp_elf_elf64_shdr)) { + PMD_DRV_LOG(ERR, "Invalid ELF file header."); + return -EINVAL; + } + + if (ectx->ehdr->e_shoff < ectx->ehdr->e_ehsize) { + PMD_DRV_LOG(ERR, "Invalid ELF header content."); + return -EINVAL; + } + + if (ectx->ehdr->e_shstrndx >= ectx->ehdr->e_shnum) { + PMD_DRV_LOG(ERR, "Invalid ELF header content."); + return -EINVAL; + } + + return 0; +} + +static int +nfp_elf_read_section_headers(struct nfp_elf *ectx, + uint8_t *buf8, + size_t buf_len) +{ + size_t idx; + int err = 0; + uint8_t *pu8; + uint64_t sh_size; + uint64_t sh_offset; + uint64_t sh_entsize; + struct nfp_elf_elf64_shdr *sec; + uint64_t e_shoff = rte_le_to_cpu_16(ectx->ehdr->e_shoff); + uint16_t e_shnum = rte_le_to_cpu_16(ectx->ehdr->e_shnum); + + if (buf_len < e_shoff + ((size_t)e_shnum * sizeof(*sec))) { + PMD_DRV_LOG(ERR, "ELF data too short."); + return -EINVAL; + } + + pu8 = buf8 + e_shoff; + + if (e_shnum == 0) { + ectx->shdrs = NULL; + ectx->shdrs_data = NULL; + ectx->shdrs_host_endian = NULL; + ectx->shdrs_cnt = 0; + return 0; + } + + ectx->shdrs = calloc(e_shnum, sizeof(*ectx->shdrs)); + if (ectx->shdrs == NULL) { + PMD_DRV_LOG(ERR, "Out of memory."); + return -ENOMEM; + } + + ectx->shdrs_data = calloc(e_shnum, sizeof(void *)); + if (ectx->shdrs_data == NULL) { + PMD_DRV_LOG(ERR, "Out of memory."); + err = -ENOMEM; + goto free_shdrs; + } + + ectx->shdrs_host_endian = calloc(e_shnum, sizeof(ectx->shdrs_host_endian[0])); + if (ectx->shdrs_host_endian == NULL) { + PMD_DRV_LOG(ERR, "Out of memory."); + err = -ENOMEM; + goto free_shdrs_data; + } + + memcpy(ectx->shdrs, pu8, e_shnum * sizeof(*ectx->shdrs)); + ectx->shdrs_cnt = e_shnum; + + for (idx = 0, sec = ectx->shdrs; idx < ectx->shdrs_cnt; idx++, sec++) { + sh_size = rte_le_to_cpu_64(sec->sh_size); + sh_offset = rte_le_to_cpu_64(sec->sh_offset); + sh_entsize = rte_le_to_cpu_64(sec->sh_entsize); + + if (sh_entsize != 0 && (sh_size % sh_entsize != 0)) { + PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); + err = -EINVAL; + goto free_shdrs_host_endian; + } + + switch (rte_le_to_cpu_32(sec->sh_type)) { + case NFP_ELF_SHT_REL: + err = nfp_elf_parse_sht_rel(sec, ectx, idx, buf8); + if (err != 0) { + PMD_DRV_LOG(ERR, "Failed to parse sht rel."); + goto free_shdrs_host_endian; + } + break; + case NFP_ELF_SHT_NOTE: + err = nfp_elf_parse_sht_note(sec, ectx, idx, buf8); + if (err != 0) { + PMD_DRV_LOG(ERR, "Failed to parse sht note."); + goto free_shdrs_host_endian; + } + break; + case NFP_ELF_SHT_NFP_MECONFIG: + err = nfp_elf_parse_sht_meconfig(sec, ectx, idx, buf8); + if (err != 0) { + PMD_DRV_LOG(ERR, "Failed to parse sht meconfig."); + goto free_shdrs_host_endian; + } + break; + case NFP_ELF_SHT_NFP_INITREG: + err = nfp_elf_parse_sht_initreg(sec, ectx, idx, buf8); + if (err != 0) { + PMD_DRV_LOG(ERR, "Failed to parse sht initregp."); + goto free_shdrs_host_endian; + } + break; + case NFP_ELF_SHT_SYMTAB: + err = nfp_elf_parse_sht_symtab(sec, ectx, idx, buf8); + if (err != 0) { + PMD_DRV_LOG(ERR, "Failed to parse sht symtab."); + goto free_shdrs_host_endian; + } + break; + case NFP_ELF_SHT_NOBITS: + case NFP_ELF_SHT_NULL: + break; + default: + if (sh_offset > 0 && sh_size <= 0) + break; + + /* + * Limit sections to 4GiB, because they won't need to be this large + * and this ensures we can handle the file on 32-bit hosts without + * unexpected problems. + */ + if (sh_size > UINT32_MAX) { + PMD_DRV_LOG(ERR, "Invalid ELF section header, index %zu.", idx); + err = -EINVAL; + goto free_shdrs_host_endian; + } + + pu8 = buf8 + sh_offset; + ectx->shdrs_data[idx] = pu8; + ectx->shdrs_host_endian[idx] = 0; + break; + } + } + + return 0; + +free_shdrs_host_endian: + free(ectx->shdrs_host_endian); +free_shdrs_data: + free(ectx->shdrs_data); +free_shdrs: + free(ectx->shdrs); + + return err; +} + +static int +nfp_elf_read_shstrtab(struct nfp_elf *ectx) +{ + struct nfp_elf_elf64_shdr *sec; + uint16_t e_shstrndx = rte_le_to_cpu_16(ectx->ehdr->e_shstrndx); + + if (ectx->ehdr->e_shnum <= ectx->ehdr->e_shstrndx) { + PMD_DRV_LOG(ERR, "Invalid Index."); + return -EINVAL; + } + + sec = &ectx->shdrs[e_shstrndx]; + if (sec == NULL || rte_le_to_cpu_32(sec->sh_type) != NFP_ELF_SHT_STRTAB) { + PMD_DRV_LOG(ERR, "Invalid ELF shstrtab."); + return -EINVAL; + } + + ectx->shstrtab = ectx->shdrs_data[e_shstrndx]; + ectx->shstrtab_sz = rte_le_to_cpu_64(sec->sh_size); + + return 0; +} + +static int +nfp_elf_read_first_symtab(struct nfp_elf *ectx) +{ + size_t idx; + uint32_t sh_type; + uint64_t sh_size; + struct nfp_elf_elf64_shdr *sec; + + for (idx = 0, sec = ectx->shdrs; idx < ectx->shdrs_cnt; idx++, sec++) { + if (sec != NULL) { + sh_type = rte_le_to_cpu_32(sec->sh_type); + if (sh_type == NFP_ELF_SHT_SYMTAB) + break; + } + } + + sh_size = rte_le_to_cpu_64(sec->sh_size); + + if (idx < ectx->shdrs_cnt && sh_type == NFP_ELF_SHT_SYMTAB) { + ectx->shdr_idx_symtab = idx; + ectx->syms = ectx->shdrs_data[idx]; + ectx->syms_cnt = nfp_elf_get_sec_ent_cnt(ectx, idx); + + /* Load symtab's strtab */ + idx = rte_le_to_cpu_32(sec->sh_link); + + if (idx == NFP_ELF_SHN_UNDEF || idx >= ectx->shdrs_cnt) { + PMD_DRV_LOG(ERR, "ELF symtab has no strtab."); + return -EINVAL; + } + + sec = &ectx->shdrs[idx]; + sh_type = rte_le_to_cpu_32(sec->sh_type); + if (sh_type != NFP_ELF_SHT_STRTAB) { + PMD_DRV_LOG(ERR, "ELF symtab has no strtab."); + return -EINVAL; + } + + if (!nfp_elf_check_sh_size(sh_size)) { + PMD_DRV_LOG(ERR, "ELF symtab has invalid strtab."); + return -EINVAL; + } + + ectx->symstrtab = ectx->shdrs_data[idx]; + ectx->symstrtab_sz = sh_size; + } + + return 0; +} + +static int +nfp_elf_is_valid_file(uint8_t *buf8) +{ + if (buf8[NFP_ELF_EI_MAG0] != NFP_ELF_ELFMAG0 || + buf8[NFP_ELF_EI_MAG1] != NFP_ELF_ELFMAG1 || + buf8[NFP_ELF_EI_MAG2] != NFP_ELF_ELFMAG2 || + buf8[NFP_ELF_EI_MAG3] != NFP_ELF_ELFMAG3 || + buf8[NFP_ELF_EI_VERSION] != NFP_ELF_EV_CURRENT || + buf8[NFP_ELF_EI_DATA] != NFP_ELF_ELFDATA2LSB) + return -EINVAL; + + return 0; +} + +static int +nfp_elf_is_valid_class(uint8_t *buf8) +{ + if (buf8[NFP_ELF_EI_CLASS] != NFP_ELF_ELFCLASS64) + return -EINVAL; + + return 0; +} + +static struct nfp_elf * +nfp_elf_mutable_buf(void *buf, + size_t buf_len) +{ + int err = 0; + uint8_t *buf8 = buf; + struct nfp_elf *ectx; + + if (buf == NULL) { + PMD_DRV_LOG(ERR, "Invalid parameters."); + return NULL; + } + + if (buf_len < sizeof(struct nfp_elf_elf64_ehdr)) { + PMD_DRV_LOG(ERR, "ELF data too short."); + return NULL; + } + + ectx = calloc(1, sizeof(struct nfp_elf)); + if (ectx == NULL) { + PMD_DRV_LOG(ERR, "Out of memory."); + return NULL; + } + + ectx->rev_min = -1; + ectx->rev_max = -1; + ectx->mip_sh_off = UINT64_MAX; + + err = nfp_elf_is_valid_file(buf8); + if (err != 0) { + PMD_DRV_LOG(ERR, "Not a valid ELF file."); + goto elf_free; + } + + err = nfp_elf_is_valid_class(buf8); + if (err != 0) { + PMD_DRV_LOG(ERR, "Unknown ELF class."); + goto elf_free; + } + + err = nfp_elf_read_file_headers(ectx, buf); + if (err != 0) { + PMD_DRV_LOG(ERR, "Failed to read file headers."); + goto elf_free; + } + + err = nfp_elf_read_section_headers(ectx, buf8, buf_len); + if (err != 0) { + PMD_DRV_LOG(ERR, "Failed to read section headers."); + goto elf_free; + } + + err = nfp_elf_read_shstrtab(ectx); + if (err != 0) { + PMD_DRV_LOG(ERR, "Failed to read shstrtab."); + goto elf_free; + } + + /* Read first symtab if any, assuming it's the primary or only one */ + err = nfp_elf_read_first_symtab(ectx); + if (err != 0) { + PMD_DRV_LOG(ERR, "Failed to read first symtab."); + goto elf_free; + } + + /* Populate the fw_mip struct if we have a .note for it */ + if (ectx->mip_shndx != 0) { + err = nfp_elf_populate_fw_mip(ectx, buf8); + if (err != 0) { + PMD_DRV_LOG(ERR, "Failed to populate the fw mip."); + goto elf_free; + } + } + + ectx->_buf = buf; + ectx->_bufsz = 0; + + return ectx; + +elf_free: + nfp_elf_free(ectx); + + return NULL; +} + +int +nfp_elf_get_fw_version(uint32_t *fw_version, + char *fw_name) +{ + void *fw_buf; + size_t fsize; + struct nfp_elf *elf; + + if (rte_firmware_read(fw_name, &fw_buf, &fsize) != 0) { + PMD_DRV_LOG(ERR, "firmware %s not found!", fw_name); + return -ENOENT; + } + + elf = nfp_elf_mutable_buf(fw_buf, fsize); + if (elf == NULL) { + PMD_DRV_LOG(ERR, "Parse nffw file failed."); + free(fw_buf); + return -EIO; + } + + *fw_version = rte_le_to_cpu_32(elf->fw_mip.fw_version); + + nfp_elf_free(elf); + free(fw_buf); + return 0; +} + diff --git a/drivers/net/nfp/nfpcore/nfp_elf.h b/drivers/net/nfp/nfpcore/nfp_elf.h new file mode 100644 index 0000000000..4081af6f01 --- /dev/null +++ b/drivers/net/nfp/nfpcore/nfp_elf.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2023 Corigine, Inc. + * All rights reserved. + */ + +#ifndef __NFP_ELF_H__ +#define __NFP_ELF_H__ + +#include + +int nfp_elf_get_fw_version(uint32_t *fw_version, char *fw_name); + +#endif /* __NFP_ELF_H__ */ diff --git a/drivers/net/nfp/nfpcore/nfp_mip.c b/drivers/net/nfp/nfpcore/nfp_mip.c index d5ada3687a..98d1d19047 100644 --- a/drivers/net/nfp/nfpcore/nfp_mip.c +++ b/drivers/net/nfp/nfpcore/nfp_mip.c @@ -10,30 +10,6 @@ #include "nfp_logs.h" #include "nfp_nffw.h" -#define NFP_MIP_SIGNATURE rte_cpu_to_le_32(0x0050494d) /* "MIP\0" */ -#define NFP_MIP_VERSION rte_cpu_to_le_32(1) -#define NFP_MIP_MAX_OFFSET (256 * 1024) - -struct nfp_mip { - uint32_t signature; - uint32_t mip_version; - uint32_t mip_size; - uint32_t first_entry; - - uint32_t version; - uint32_t buildnum; - uint32_t buildtime; - uint32_t loadtime; - - uint32_t symtab_addr; - uint32_t symtab_size; - uint32_t strtab_addr; - uint32_t strtab_size; - - char name[16]; - char toolchain[32]; -}; - /* Read memory and check if it could be a valid MIP */ static int nfp_mip_try_read(struct nfp_cpp *cpp, @@ -134,6 +110,12 @@ nfp_mip_name(const struct nfp_mip *mip) return mip->name; } +uint32_t +nfp_mip_fw_version(const struct nfp_mip *mip) +{ + return rte_le_to_cpu_32(mip->version); +} + /** * Get the address and size of the MIP symbol table. * diff --git a/drivers/net/nfp/nfpcore/nfp_mip.h b/drivers/net/nfp/nfpcore/nfp_mip.h index dbd9af31ed..411fe413d7 100644 --- a/drivers/net/nfp/nfpcore/nfp_mip.h +++ b/drivers/net/nfp/nfpcore/nfp_mip.h @@ -8,12 +8,80 @@ #include "nfp_cpp.h" -struct nfp_mip; +/* "MIP\0" */ +#define NFP_MIP_SIGNATURE rte_cpu_to_le_32(0x0050494d) +#define NFP_MIP_VERSION rte_cpu_to_le_32(1) + +/* nfp_mip_entry_type */ +#define NFP_MIP_TYPE_FWINFO 0x70000002 + +/* Each packed struct field is stored as Little Endian */ +struct nfp_mip { + rte_le32_t signature; + rte_le32_t mip_version; + + rte_le32_t mip_size; + rte_le32_t first_entry; + + rte_le32_t version; + rte_le32_t buildnum; + rte_le32_t buildtime; + rte_le32_t loadtime; + + rte_le32_t symtab_addr; + rte_le32_t symtab_size; + rte_le32_t strtab_addr; + rte_le32_t strtab_size; + + char name[16]; + char toolchain[32]; +}; + +struct nfp_mip_entry { + uint32_t type; + uint32_t version; + uint32_t offset_next; +}; + +/* + * A key-value pair has no imposed limit, but it is recommended that + * consumers only allocate enough memory for keys they plan to process and + * skip over unused keys or ignore values that are longer than expected. + * + * For MIPv1, this will be preceded by struct nfp_mip_entry. + * The entry size will be the size of key_value_strs, round to the next + * 4-byte multiple. If entry size is 0, then there are no key-value strings + * and it will not contain an empty string. + * + * The following keys are reserved and possibly set by the linker. The + * convention is to start linker-set keys with a capital letter. Reserved + * entries will be placed first in key_value_strs, user entries will be + * placed next and be sorted alphabetically. + * TypeId - Present if a user specified fw_typeid when linking. + * + * The following keys are reserved, but not used. Their values are in the + * root MIP struct. + */ +struct nfp_mip_fwinfo_entry { + /** The byte size of @p key_value_strs. */ + uint32_t kv_len; + + /** The number of key-value pairs in the following string. */ + uint32_t num; + + /** + * A series of NUL terminated strings, terminated by an extra + * NUL which is also the last byte of the entry, so an iterator + * can either check on size or when key[0] == '\0'. + */ + char key_value_strs[]; +}; struct nfp_mip *nfp_mip_open(struct nfp_cpp *cpp); void nfp_mip_close(struct nfp_mip *mip); const char *nfp_mip_name(const struct nfp_mip *mip); +uint32_t nfp_mip_fw_version(const struct nfp_mip *mip); void nfp_mip_symtab(const struct nfp_mip *mip, uint32_t *addr, uint32_t *size); void nfp_mip_strtab(const struct nfp_mip *mip, uint32_t *addr, uint32_t *size); From patchwork Tue Feb 27 11:15:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chaoyong He X-Patchwork-Id: 137341 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id A9E2943C08; Tue, 27 Feb 2024 12:16:28 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id E5B9340E2D; Tue, 27 Feb 2024 12:16:20 +0100 (CET) Received: from NAM10-DM6-obe.outbound.protection.outlook.com (mail-dm6nam10on2126.outbound.protection.outlook.com [40.107.93.126]) by mails.dpdk.org (Postfix) with ESMTP id 9B74F406B4 for ; Tue, 27 Feb 2024 12:16:17 +0100 (CET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=loq+FMEvDuf9LCK4B7tgsV6AvuPqioLya0FSrtFOhlYYhwre1QKgLrHpcoDSL/0yx9J330rXHrcIaDt+tAMyvhOssnozm3JlTDbKCERDvDVlWYQruX6Jt2U9qD3ymPVERDy//kSaCi/Wnv8haSy8ZBUiEmcmZYt4IqDjx0XZibH5pEtWuW3SFEjiPT3q6ue90nSTX9s9UvyxiLjEGk6aoqLoWGPPZvVA/t7loXoVIgtquMvu9KwtU3Ks5YIvVQYNEFE0WpwDVUTwM1heWW4JNCoQ5oNnWo3LcVszfxYvQP1JezX0a5ArAX/Nmv3YmOOH7SVuDhtzyK8RWSVX1UHi4w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=i5qgcCWM0A0EoUdV6WJ1lWQ2i1l6RrG5jC8cGVUzeWQ=; b=F6gHdZO+IByphntgHUFhvdXEMGxFSCQVPVJmgNGMw5c8kWUoDUwbRhIDECSHAN7RHijzACrndaS73liTTPvVPfihx5M7zwQaUKiu1emWXXPflVZ3RU/BP/i9nDqnBZjtV6SdoWF1owHqviOGQiFDhn8SpeHD4eYnYVXlWRlT5L2fpZRDbRlQdKUoyckGfOyOLxBg2+gZTHXlP7fDokZdG610hB8+JPNKkm8BjS5GZpB2jTxeXWsgEaHMLgcJYOv3CbF/LbJGazO8iw6ys6ol6EFdZUMxnxFNKSZHPDCCWz4DZ9+8IRs04POpC+miEBfvV+somoBzpJBGvqps7wrWDg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=corigine.com; dmarc=pass action=none header.from=corigine.com; dkim=pass header.d=corigine.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=corigine.onmicrosoft.com; s=selector2-corigine-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=i5qgcCWM0A0EoUdV6WJ1lWQ2i1l6RrG5jC8cGVUzeWQ=; b=BljpOVFWrRvRk7UhO3YZBLh5B+qnxfzIwJaRlx7RMQPOl6R854P977ENEEU6xyuO0jbRKAOBKg0o0xlglDqWqE/sd6tAiGEfIVYJEnQItIE6zEvcewVgVG0PbVVfV+nX5b+XFHVnMnMIbZxPxYD0V8cAPtfEvSMkExVi7vn2r9o= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=corigine.com; Received: from SJ0PR13MB5545.namprd13.prod.outlook.com (2603:10b6:a03:424::5) by PH7PR13MB5843.namprd13.prod.outlook.com (2603:10b6:510:151::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7316.39; Tue, 27 Feb 2024 11:16:16 +0000 Received: from SJ0PR13MB5545.namprd13.prod.outlook.com ([fe80::8e02:f738:570a:f8aa]) by SJ0PR13MB5545.namprd13.prod.outlook.com ([fe80::8e02:f738:570a:f8aa%7]) with mapi id 15.20.7316.035; Tue, 27 Feb 2024 11:16:16 +0000 From: Chaoyong He To: dev@dpdk.org Cc: oss-drivers@corigine.com, Peng Zhang , Chaoyong He , Long Wu Subject: [PATCH 2/3] net/nfp: reload the firmware only when firmware changed Date: Tue, 27 Feb 2024 19:15:50 +0800 Message-Id: <20240227111551.3773862-3-chaoyong.he@corigine.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20240227111551.3773862-1-chaoyong.he@corigine.com> References: <20240227111551.3773862-1-chaoyong.he@corigine.com> X-ClientProxiedBy: BY5PR20CA0002.namprd20.prod.outlook.com (2603:10b6:a03:1f4::15) To SJ0PR13MB5545.namprd13.prod.outlook.com (2603:10b6:a03:424::5) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SJ0PR13MB5545:EE_|PH7PR13MB5843:EE_ X-MS-Office365-Filtering-Correlation-Id: 95b055c3-e371-4beb-bc46-08dc37858364 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: siVUMZc70Qvf8rYJd33VeRe/f4lmiTzYL2pxMI49sDLHg4bcz3Iww8IuuYQrPG3AG/Zlw5G/4Bxm0RptmO7Gg2dBc97D87AG3s/5OUmcWGt++xGyeH2Djeg6qJ5BM0uRhmvonFIRrNjd6bQH2atNvs2tvBNGWfFOFFVHjxpwBzp/nkJlJ4fGFygqugcntmlkNElwUOmYrDgtSghr/3zNlEJZtsQ6YtJGyhZ0eO/PgGWRlb3QXyFo/x4CaQ0GVSHmZy7rZG+me9og/h5RevB5fluiAib19XYVkPoKFvGAF7bBBubzZW1ewKYTn5wbNuicDhXkQ+jdzbml9B5iYCP5nbPyKSBLUWdIUpajrPe12ThvSOfz93K7d5dmCWguIbUNc7JCygkGyYnh9BN6lMeIrvhv/UF/G291Qy+kbohKcdG3qh/oPZLjKuIzCUmsu8VZ10AgyrBS4l7zk+XUo9J1/J0ovs8eQaNgSyXR0z7TtMbvhlybIFuiQH6s3E96lMyQmBhSWOctlHg+DiUM2KhuN8I4Vaj6pewnBqNlmfmOs5xWj+pa3U4U9NB04IHP9RfQeIB9vupRtGdlyO2rfqlUwiHoGm7uOjIWObr2RgXKY/CjzlCnfFwj6TXAcQWd1KJtCNzU+lbbF67UUU8RcXj01T+XdHqdLSxKFqE9dcIptMJmpfechf9yeFv2ZTU+OaIrEaeKtBhcdRJvpJ43tH1L4qJUmgUhTjAxfbHaV6UwU4k= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:SJ0PR13MB5545.namprd13.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230031)(38350700005); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: jUMkCSpMuoUNjrypZI/J5vW8OiZnkIQ4Bq7QN61keF3wEyCQMQVOI4VAKqz3UUqLeXSDDVlq2ex/vlwjdBtCWC8WtSfe7U94HAQ5BPWVfJjS68uaQ/1egGR+xVsaBpkMQYTodvsG/paYXKOI4FCq1sFrJpsqn0nP7d5qx8ILe8vjpJOeN7Q1KPQ0cT5grjWOYyyr5UXqKdxR0c1JOotUfFFQvde+QOZkhQq9dcBphISnAisbR1TaBGcroEzcZ3MRMLGVJoXVQdrhzv/8QEoSQetSUlvRYNW6i6e7HK/JMCBSVDHDeOwpcg2ZU6IDss/Y/0f7fmGrWgyL24JhytG+JlTGrh+1euuV78dmcsA05lt0V6F6O+xCXbjtmmB0BUq7gpPLJuufhw+uL7mxPCWqBblGRHgcxW8f71uxJPqjjaqpyLh8pciagKEAEHVV0H8MTKjxcawzjZ9LyLLqtbS4gO5f8SPjer363Q/Z/NFM4Nb4CibXEkGBgKfKSgKnWjx6N2YJe0Eag+s7U+PWk0Ek/tE2+/Yol8e6BXnMZVbVpiFFlVHn94txtioZAkApUWXbQ3zN+8Vx2LJNuxzRAt53a4dZy2+Hb7Nm1to62w95JRaOhDn4cPXpy1NjTHn9/xJx5/xgJhs3AGh38+LeRz9T8tvAm2+U6kP87SGKRveOsot0lhRqx1vrbqoKbV72zvJQLxaDMpqhkd4z4sbHTjYGl/HZo0B1wSMc/6Xg+mQR2Ke4IsG3eF5qhxv59OJ357jSqz5RvYnbVmvYjCftYre5PvR/OQmK0yb2/mkYw1KxUVWA+NeXtFeZzwAKjsrfprxNejYoiAt2Gktz4Ds0Ze2N6qXCTunzlnVtZJG6Bj/u3h6MXabDRFxkodzFayjD0uFN/y+pMlrW/0kvjME6RtuhA/ygia+1tgMDUc9uNPOeMZYy+bBNJ+ZJE6wqIhTXGrOWArLcTwSFHUmkjvQ2H/J4HU9y0YpP9KcD5MSXuCzkCXxCBOUG1Wdda0GNNOM4Mr/dI8nG7m5nRAPkgc7zXBOj3j0eGNfMhFAG/V0XpBNDaRoCFA7pt5Dedqc6t37qj1i+1CHJGmFqBOUT6VKO/6T/6LIV4bMf3Iv9t2P2olkX9lYXcf6jfhitu4DDeEvgkh7qJmNuM5sqHRBlIwgT++74tHVCOd6dufyXjhOOh5LNeoXU7hw9NdzpgjwNBEYFqT7aAN/xdWH7m9P8bkQQkMf/ME3O/zpbqzIJfc2Y4lvtDLcP+x+RmIUjyZzHBsEO6gAwmUHewIHoQnP2euRdlG5jga751gKrPYS4hglMSttmFC9uBaMhWZT79j+tENaAFEG4bkUwda+hiEfznuc3cjM1u5J2gEN7PdC9zm0YU7dSkxz3b5UxP0/erl7NStd4OTqU+fBLFMR0aDJIyUZ/nIrRGORgR8GiCyrjkmUsYovJvFRT1dhUEF73dJuWASoY+s4qaEyBL3f9mZKfY9tYUaJIBBusnJN//X/RT78K7zxl9QtJopbidLaOLR1S5MsmQ1VBkmvmQZZQMCWOxGzlWR9HoQhSb+oM2OxFDKw8ww+LnhpyndgFQf62CcoxJNCpFpooEoBe7nOlbxlKZMGBXE6nag== X-OriginatorOrg: corigine.com X-MS-Exchange-CrossTenant-Network-Message-Id: 95b055c3-e371-4beb-bc46-08dc37858364 X-MS-Exchange-CrossTenant-AuthSource: SJ0PR13MB5545.namprd13.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Feb 2024 11:16:15.9273 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: fe128f2c-073b-4c20-818e-7246a585940c X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: GgYOgr7cTjAF7uxpHt1wLyceJi/gAsOzVsEj3brxsHZLQPOcmZklr9WPb+OjPXizy1wxfjGyXw4oxhZhzzlJ5ZVNcN0ppEQoGGWDtgPJAzw= X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR13MB5843 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Peng Zhang Add the interfaces of getting firmware version from BSP and ELF file, only reloading the firmware when the version is different, which means the firmware has changed. This will accelerate the average startup time for both multi-PF and single-PF firmware. Signed-off-by: Peng Zhang Reviewed-by: Chaoyong He Reviewed-by: Long Wu --- drivers/net/nfp/nfp_ethdev.c | 85 +++++++++++++++++++++++++++----- drivers/net/nfp/nfp_net_common.c | 17 +++++++ drivers/net/nfp/nfp_net_common.h | 2 + 3 files changed, 93 insertions(+), 11 deletions(-) diff --git a/drivers/net/nfp/nfp_ethdev.c b/drivers/net/nfp/nfp_ethdev.c index 3ece806487..902a62a86b 100644 --- a/drivers/net/nfp/nfp_ethdev.c +++ b/drivers/net/nfp/nfp_ethdev.c @@ -14,6 +14,7 @@ #include "nfd3/nfp_nfd3.h" #include "nfdk/nfp_nfdk.h" #include "nfpcore/nfp_cpp.h" +#include "nfpcore/nfp_elf.h" #include "nfpcore/nfp_hwinfo.h" #include "nfpcore/nfp_rtsym.h" #include "nfpcore/nfp_nsp.h" @@ -1070,6 +1071,35 @@ nfp_fw_unload(struct nfp_cpp *cpp) nfp_nsp_close(nsp); } +static int +nfp_fw_check_change(struct nfp_cpp *cpp, + char *fw_name, + bool *fw_changed) +{ + int ret; + struct nfp_net_hw hw; + uint32_t new_version = 0; + uint32_t old_version = 0; + + ret = nfp_elf_get_fw_version(&new_version, fw_name); + if (ret != 0) + return ret; + + hw.cpp = cpp; + nfp_net_get_fw_version(&hw, &old_version); + + if (new_version != old_version) { + PMD_DRV_LOG(INFO, "FW version is changed, new %u, old %u", + new_version, old_version); + *fw_changed = true; + } else { + PMD_DRV_LOG(INFO, "FW version is not changed and is %u", new_version); + *fw_changed = false; + } + + return 0; +} + static int nfp_fw_reload(struct nfp_nsp *nsp, char *fw_name) @@ -1135,15 +1165,39 @@ nfp_fw_skip_load(const struct nfp_dev_info *dev_info, return false; } +static int +nfp_fw_reload_for_single_pf(struct nfp_nsp *nsp, + char *fw_name, + struct nfp_cpp *cpp) +{ + int ret; + bool fw_changed = true; + + if (nfp_nsp_fw_loaded(nsp)) { + ret = nfp_fw_check_change(cpp, fw_name, &fw_changed); + if (ret != 0) + return ret; + } + + if (!fw_changed) + return 0; + + ret = nfp_fw_reload(nsp, fw_name); + if (ret != 0) + return ret; + + return 0; +} static int -nfp_fw_reload_for_multipf(struct nfp_nsp *nsp, +nfp_fw_reload_for_multi_pf(struct nfp_nsp *nsp, char *fw_name, struct nfp_cpp *cpp, const struct nfp_dev_info *dev_info, struct nfp_multi_pf *multi_pf) { int err; + bool fw_changed = true; bool skip_load_fw = false; err = nfp_net_keepalive_init(cpp, multi_pf); @@ -1154,27 +1208,36 @@ nfp_fw_reload_for_multipf(struct nfp_nsp *nsp, err = nfp_net_keepalive_start(multi_pf); if (err != 0) { - nfp_net_keepalive_uninit(multi_pf); PMD_DRV_LOG(ERR, "NFP write beat failed"); - return err; + goto keepalive_uninit; + } + + if (nfp_nsp_fw_loaded(nsp)) { + err = nfp_fw_check_change(cpp, fw_name, &fw_changed); + if (err != 0) + goto keepalive_stop; } - if (nfp_nsp_fw_loaded(nsp)) + if (!fw_changed) skip_load_fw = nfp_fw_skip_load(dev_info, multi_pf); if (skip_load_fw) return 0; err = nfp_fw_reload(nsp, fw_name); - if (err != 0) { - nfp_net_keepalive_stop(multi_pf); - nfp_net_keepalive_uninit(multi_pf); - return err; - } + if (err != 0) + goto keepalive_stop; nfp_net_keepalive_clear_others(dev_info, multi_pf); return 0; + +keepalive_stop: + nfp_net_keepalive_stop(multi_pf); +keepalive_uninit: + nfp_net_keepalive_uninit(multi_pf); + + return err; } static int @@ -1231,9 +1294,9 @@ nfp_fw_setup(struct rte_pci_device *dev, } if (multi_pf->enabled) - err = nfp_fw_reload_for_multipf(nsp, fw_name, cpp, dev_info, multi_pf); + err = nfp_fw_reload_for_multi_pf(nsp, fw_name, cpp, dev_info, multi_pf); else - err = nfp_fw_reload(nsp, fw_name); + err = nfp_fw_reload_for_single_pf(nsp, fw_name, cpp); nfp_nsp_close(nsp); return err; diff --git a/drivers/net/nfp/nfp_net_common.c b/drivers/net/nfp/nfp_net_common.c index 26ea4ec92f..20e628bfd1 100644 --- a/drivers/net/nfp/nfp_net_common.c +++ b/drivers/net/nfp/nfp_net_common.c @@ -2090,6 +2090,23 @@ nfp_net_get_nsp_info(struct nfp_net_hw *hw, nfp_nsp_close(nsp); } +void +nfp_net_get_fw_version(struct nfp_net_hw *hw, + uint32_t *mip_version) +{ + struct nfp_mip *mip; + + mip = nfp_mip_open(hw->cpp); + if (mip == NULL) { + *mip_version = 0; + return; + } + + *mip_version = nfp_mip_fw_version(mip); + + nfp_mip_close(mip); +} + static void nfp_net_get_mip_name(struct nfp_net_hw *hw, char *mip_name) diff --git a/drivers/net/nfp/nfp_net_common.h b/drivers/net/nfp/nfp_net_common.h index 1c24045b7d..9c46bfd4f6 100644 --- a/drivers/net/nfp/nfp_net_common.h +++ b/drivers/net/nfp/nfp_net_common.h @@ -316,6 +316,8 @@ int nfp_net_fec_get(struct rte_eth_dev *dev, uint32_t *fec_capa); int nfp_net_fec_set(struct rte_eth_dev *dev, uint32_t fec_capa); +void nfp_net_get_fw_version(struct nfp_net_hw *hw, + uint32_t *fw_version); #define NFP_PRIV_TO_APP_FW_NIC(app_fw_priv)\ ((struct nfp_app_fw_nic *)app_fw_priv) From patchwork Tue Feb 27 11:15:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chaoyong He X-Patchwork-Id: 137342 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id A441943C08; Tue, 27 Feb 2024 12:16:36 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 10A4B40ED2; Tue, 27 Feb 2024 12:16:22 +0100 (CET) Received: from NAM10-DM6-obe.outbound.protection.outlook.com (mail-dm6nam10on2111.outbound.protection.outlook.com [40.107.93.111]) by mails.dpdk.org (Postfix) with ESMTP id 0457440DF8 for ; Tue, 27 Feb 2024 12:16:19 +0100 (CET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=nIaGpy36TGhxhjxtMcYaILGV6DPWG6p2fQSbtw+4WRR34JFCXX4K1O9Fr4tFbFXl8wFLBWtw0oeTe0ljjNK2I/SHNDODzsvj8sqa/s6hHCUh3LOCftEKSTiv/yEzM0ZCqgBvbW8sl2m5zCYm6frknkp8BYeJNSyy3XHHWXU9o0Q2PwwHXLxsa+GiV5SC/izOtebYTCQKDrIKovunpUU8K0iLCdLAoIQ0ZnhT1CuN+F6WweGlsqUD1DfA13lfNoUoOmEaU+Qeloi14tDkVVoZdpasesHImGRTJkD0Kyp4bZWessnq7wodl+DOGthnudzSTmIEBKjRPHC2cWmFxNIvJQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=IciFkEM6H34j0fftlM7sD9YSabJ71Xd0jYsnJvcX73g=; b=T6mk6q8PHhyYPt/4OxAdgk6WOmRdqHn60an5hdUft11R5xrUT9MfLD6LsclC/A1eSTOoemUhFMm+a81L5IiMvRA8vIqauqkj6hIc8mI/l7/0pP2TK4GtUw5sS872PK76qpEmFi8I8ES/xA+P11/BKX1GI93AXd+cEL0Zsa8lG0OJ9FI+Q3HGJ1ID2iDEFF8SzHCg/DBpn8fE9lagyNlh/SF9dTLLUOrqUXdbq7s0qdcQT0Wb4L+1QP7Qf+kp6eKSfbB8+7FlzBIPOikRWMgkiwacqcPUb5bQGPCCdJOb7gPsE4pRo8t+pTeTv/JUBR6O0lk54MKgWzu3PBWYwby5WQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=corigine.com; dmarc=pass action=none header.from=corigine.com; dkim=pass header.d=corigine.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=corigine.onmicrosoft.com; s=selector2-corigine-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=IciFkEM6H34j0fftlM7sD9YSabJ71Xd0jYsnJvcX73g=; b=jwI19UEQebp0YCe99AKMJ2HIi9iL9UltryBjG1pcyZfZAc3myyrdOk/z4USR70TB1OvlZxkCyrtXdD8cmN/8J9T8JoePVH5Fqqt8kScsOARXbuas2B5s/+9W1/KuLVGnMiFwEX202Zn4Ga8rL2Zt3LKz9dqPP7FwjsioduIkRsM= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=corigine.com; Received: from SJ0PR13MB5545.namprd13.prod.outlook.com (2603:10b6:a03:424::5) by PH7PR13MB5843.namprd13.prod.outlook.com (2603:10b6:510:151::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7316.39; Tue, 27 Feb 2024 11:16:17 +0000 Received: from SJ0PR13MB5545.namprd13.prod.outlook.com ([fe80::8e02:f738:570a:f8aa]) by SJ0PR13MB5545.namprd13.prod.outlook.com ([fe80::8e02:f738:570a:f8aa%7]) with mapi id 15.20.7316.035; Tue, 27 Feb 2024 11:16:17 +0000 From: Chaoyong He To: dev@dpdk.org Cc: oss-drivers@corigine.com, Peng Zhang , Chaoyong He Subject: [PATCH 3/3] net/nfp: add force reload firmware option Date: Tue, 27 Feb 2024 19:15:51 +0800 Message-Id: <20240227111551.3773862-4-chaoyong.he@corigine.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20240227111551.3773862-1-chaoyong.he@corigine.com> References: <20240227111551.3773862-1-chaoyong.he@corigine.com> X-ClientProxiedBy: BY5PR20CA0002.namprd20.prod.outlook.com (2603:10b6:a03:1f4::15) To SJ0PR13MB5545.namprd13.prod.outlook.com (2603:10b6:a03:424::5) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SJ0PR13MB5545:EE_|PH7PR13MB5843:EE_ X-MS-Office365-Filtering-Correlation-Id: a799c1be-d7a7-41e8-a7c3-08dc37858495 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 3CUvWmdFKTEsrPl/P86LKu2J9iAygfddKKQNikwk0cR/h6W0BiUD82la8fDdfT11jXAcwfHWAbz0GGbgNeMzGsOK/AMg0swU8vXu7XDMJqr76hPq8WzpILjtFV0pIKkupNkBS81MA+lTd5SoVCGV5L/h8dL4CkhZ+ctHORU1/KdbhbryCJB5WN1CuVIO2X9/n2ZYpPhn2MMcUXI182hRzmtsvh84mzgyTTi+elwNgcBoSjYhy6twiy7AYqdmDg0YpWBRrVWBrLoQ1BZkw+MYK42GHYuC6NZg8CttFQC8I18kxm7Cah8Dd37l2tn0v26DnhmFzv+XF8O70ppXtLcH7PwVTbtsLly3CMKKaW+6w/FvYRz24PUNWEzOcNiePB+VpkWH6w0R3NzSdX3I/p7GMBnxLx5pUMGdQVHAofdnzpbEgPx9tywyvuk7bG8N+ndr9C8gb2is2pCPdvJ4CRR+cQcrXhX49G+aXgqr/uZLEHwb57h1M4FiULjMkfybgYWdxa08A906gfGRp0kEuCGX/f0rZ+nSdMllkRW6jwuj8DHR81cMOVF966AsFdzUiwF0TscXk/FiumAf7TQKaGzGv6zwQrRdBfxKEaCgNiZCz0cAulsSG6uXfmJuGdgJaJLJMSF0NyHChjagRPf8Gsue+k/fgLVE0a1uUip2Y9c4//zdwMXITl0+W2H8G27oLYyIxbPy78QvKHMS8RzMGnELLZ1PkuTjGH4sc0Miy6Q7gyw= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:SJ0PR13MB5545.namprd13.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230031)(38350700005); DIR:OUT; SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: K49uq1AdASi2em6rRg+3cQ84DOynySlmzj4OIeHzkGR90eW2t4MVTnjn3fPM2f94BgXhIP5jaRXYVuxN7HOl11mTW8+lT6g9YUVUMKCjL8/DJ91DdHS2EXIqRDHhaxGtNxFRKEdesliGbWUujLmzG6GOb4Q7zKLP/aesS+EpkeDpnay1dUB6/XZNBfHCYLo9hQdqpFtpaptBUljHEe8R8KQ0nESfS4t38f64gRtcEiwwt6BZYONdMejPM1BywnKUsZVAIPAXLKFCpMA2LggQbuMpsMoRz9Me8tr1y++t/djB167bVAhKhc/ZzKfymGHyLjdOlBqu2LxKVosKApOTmacOYZVE2wFLch4d8ocHxFrVTHl+BPtBpYl2QJXpeILTBJ9ZqDxcZwSvx0K41Qh7JofKHGldFmvk2UoVho6FAVE6Bd02xwVoVcorslTZLW1j0eSYQWpHqhmygYuROn5O5tYtYeCmcEmTnifgk7NCTJyg2qpsSiMJ39hTZfGowFbZIfV/bjua1HiAaL5ZidS6uFfkoW6bsEdvv6BNZ0pzOWdgGlmoWPgj+smk+QKD9u0/PbMvTXrwWxGbdLWfMFRK/9z6cLKykB14q89yLy6ZDr/D3oiR9QoHztt95arAlJfUySxzzlk0S2sKz9ugsxYHtPJIsaB/BaeSfOej4nQRKrpFMsZD5Gqwh0mwYs4eMPH8O5oBegHcHBB56eizhFb/KUT424yp1UHDrqltwdbBzePIihDcxuAxs3qIZfKu8VDDWMkhskytK8U7nPQpPZsI4ucwnx62aVOyOQSjF3wtFb3ZxNXd+gI9YloufG7FBRY+z3wAX2hmblOUFKdh326RI7361PNPIMCEKh3wOJqbW0H1vdfj+w4ZK/lU5lKbGaKaJYMJsIKaaOcTktFbiyNRBjLa2XjYst4aLk21wgS9QkJb11je3NlNPa9ZCv7Flx6K2yWz2CwRRpSvzDY2PNT+0qXU9cWc6gYZ0EXq0sqycC4K92nTD7r2RkP8+kAyNHScsII8HoyaRTMbnr7Pr69x3JWcMV5x3Z2aw+vFFe1xmH2cJHfrDZ6O0sXp2eu8ovD4RrkYpgMjeJ/J/XXD77x6xVOtNFhSsdYsb0duO8S5K09iyou4GnvzLtQ9ksBm68VMA6XTJ2h7XTLzJgOzMo7gFM6Fi7R59pjdy4mGNjKHanA1Tjsi5l4hlcXfGHqFE2442IFisTQK+3yvwlm2VFMF46Xf1AjGToWaqq8A2OjjRcG6Xj/HhX1ddM+w4vaJx7cMiopD/Pv0elS3Vz5DpQ3rBSQBi8Ui1UoaXuA0KdYWEFBT3skUVppfeoCZZoz+/kJC2y8kTVBsUPtk47kEldQbohIppMd9oi6u4ot7oSWKKvaEu1MUGUJQtB/8zGX0dhh5j31ts1FYT32ZdFXR6ELSsc9D8SCZ/lPbLbnLbd+jj0XLKhkFCNKu2LbBrApM3/qIGShJgWGZ9KLzyS7n5/3zscwvWXoeJnxBz2eXt/SsVTQWniF4aX4qQSHY8MdHgICLbjUShRaX8mrOYM+oS2DsHQy+5Mp24aqFRYqVurnEdSJvDekNEewvaqM+JvrcwiTdcOTcnF5WGiDQIK/UrJHrGw== X-OriginatorOrg: corigine.com X-MS-Exchange-CrossTenant-Network-Message-Id: a799c1be-d7a7-41e8-a7c3-08dc37858495 X-MS-Exchange-CrossTenant-AuthSource: SJ0PR13MB5545.namprd13.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Feb 2024 11:16:17.7167 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: fe128f2c-073b-4c20-818e-7246a585940c X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 4tMb7GaOyvyGdFryf3z7Qr/h6HXcPJY4RmgyzgropbRssP60Bh/il91RP2jroaS5qTniF9MmERW7P35w5eRJ47kt7Fnsg7XDai1fLGxv5NQ= X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR13MB5843 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Peng Zhang Add an option to force reload the firmware. This option can be ignored in some case, for example: When using a 2 port NFP card and both with this reload firmware option, only the first one will cause the firmware reload and the second one will be ignored. Signed-off-by: Peng Zhang Reviewed-by: Chaoyong He --- drivers/net/nfp/nfp_ethdev.c | 104 +++++++++++++++++++++++++++---- drivers/net/nfp/nfp_net_common.h | 8 +++ 2 files changed, 100 insertions(+), 12 deletions(-) diff --git a/drivers/net/nfp/nfp_ethdev.c b/drivers/net/nfp/nfp_ethdev.c index 902a62a86b..8c38b4e134 100644 --- a/drivers/net/nfp/nfp_ethdev.c +++ b/drivers/net/nfp/nfp_ethdev.c @@ -9,6 +9,7 @@ #include #include +#include #include "flower/nfp_flower.h" #include "nfd3/nfp_nfd3.h" @@ -31,6 +32,71 @@ #define NFP_NET_APP_CAP_SP_INDIFF RTE_BIT64(0) /* Indifferent to port speed */ #define NFP_PF_DRIVER_NAME net_nfp_pf +#define NFP_PF_FORCE_RELOAD_FW "force_reload_fw" + +static int +nfp_devarg_handle_int(const char *key, + const char *value, + void *extra_args) +{ + char *end_ptr; + uint64_t *num = extra_args; + + if (value == NULL) + return -EPERM; + + *num = strtoul(value, &end_ptr, 10); + if (*num == ULONG_MAX) { + PMD_DRV_LOG(ERR, "%s: '%s' is not a valid param", key, value); + return -ERANGE; + } else if (value == end_ptr) { + return -EPERM; + } + + return 0; +} + +static void +nfp_devarg_parse_force_reload_fw(struct rte_kvargs *kvlist, + bool *force_reload_fw) +{ + int ret; + uint64_t value; + + + if (rte_kvargs_count(kvlist, NFP_PF_FORCE_RELOAD_FW) != 1) + return; + + ret = rte_kvargs_process(kvlist, NFP_PF_FORCE_RELOAD_FW, &nfp_devarg_handle_int, &value); + if (ret != 0) + return; + + if (value == 1) + *force_reload_fw = true; + else if (value == 0) + *force_reload_fw = false; + else + PMD_DRV_LOG(ERR, "The param does not work, the format is %s=0/1", + NFP_PF_FORCE_RELOAD_FW); +} + +static void +nfp_devargs_parse(struct nfp_devargs *nfp_devargs_param, + const struct rte_devargs *devargs) +{ + struct rte_kvargs *kvlist; + + if (devargs == NULL) + return; + + kvlist = rte_kvargs_parse(devargs->args, NULL); + if (kvlist == NULL) + return; + + nfp_devarg_parse_force_reload_fw(kvlist, &nfp_devargs_param->force_reload_fw); + + rte_kvargs_free(kvlist); +} static void nfp_net_pf_read_mac(struct nfp_app_fw_nic *app_fw_nic, @@ -1116,7 +1182,8 @@ nfp_fw_reload(struct nfp_nsp *nsp, static bool nfp_fw_skip_load(const struct nfp_dev_info *dev_info, - struct nfp_multi_pf *multi_pf) + struct nfp_multi_pf *multi_pf, + bool *reload_fw) { uint8_t i; uint64_t tmp_beat; @@ -1150,6 +1217,11 @@ nfp_fw_skip_load(const struct nfp_dev_info *dev_info, in_use++; abnormal--; beat[port_num] = 0; + if (*reload_fw) { + *reload_fw = false; + PMD_DRV_LOG(ERR, "The param %s does not work", + NFP_PF_FORCE_RELOAD_FW); + } } } @@ -1168,12 +1240,13 @@ nfp_fw_skip_load(const struct nfp_dev_info *dev_info, static int nfp_fw_reload_for_single_pf(struct nfp_nsp *nsp, char *fw_name, - struct nfp_cpp *cpp) + struct nfp_cpp *cpp, + bool force_reload_fw) { int ret; bool fw_changed = true; - if (nfp_nsp_fw_loaded(nsp)) { + if (nfp_nsp_fw_loaded(nsp) && !force_reload_fw) { ret = nfp_fw_check_change(cpp, fw_name, &fw_changed); if (ret != 0) return ret; @@ -1194,11 +1267,13 @@ nfp_fw_reload_for_multi_pf(struct nfp_nsp *nsp, char *fw_name, struct nfp_cpp *cpp, const struct nfp_dev_info *dev_info, - struct nfp_multi_pf *multi_pf) + struct nfp_multi_pf *multi_pf, + bool force_reload_fw) { int err; bool fw_changed = true; bool skip_load_fw = false; + bool reload_fw = force_reload_fw; err = nfp_net_keepalive_init(cpp, multi_pf); if (err != 0) { @@ -1212,16 +1287,16 @@ nfp_fw_reload_for_multi_pf(struct nfp_nsp *nsp, goto keepalive_uninit; } - if (nfp_nsp_fw_loaded(nsp)) { + if (nfp_nsp_fw_loaded(nsp) && !reload_fw) { err = nfp_fw_check_change(cpp, fw_name, &fw_changed); if (err != 0) goto keepalive_stop; } - if (!fw_changed) - skip_load_fw = nfp_fw_skip_load(dev_info, multi_pf); + if (!fw_changed || reload_fw) + skip_load_fw = nfp_fw_skip_load(dev_info, multi_pf, &reload_fw); - if (skip_load_fw) + if (skip_load_fw && !reload_fw) return 0; err = nfp_fw_reload(nsp, fw_name); @@ -1246,7 +1321,8 @@ nfp_fw_setup(struct rte_pci_device *dev, struct nfp_eth_table *nfp_eth_table, struct nfp_hwinfo *hwinfo, const struct nfp_dev_info *dev_info, - struct nfp_multi_pf *multi_pf) + struct nfp_multi_pf *multi_pf, + bool force_reload_fw) { int err; char fw_name[125]; @@ -1294,9 +1370,10 @@ nfp_fw_setup(struct rte_pci_device *dev, } if (multi_pf->enabled) - err = nfp_fw_reload_for_multi_pf(nsp, fw_name, cpp, dev_info, multi_pf); + err = nfp_fw_reload_for_multi_pf(nsp, fw_name, cpp, dev_info, multi_pf, + force_reload_fw); else - err = nfp_fw_reload_for_single_pf(nsp, fw_name, cpp); + err = nfp_fw_reload_for_single_pf(nsp, fw_name, cpp, force_reload_fw); nfp_nsp_close(nsp); return err; @@ -1769,8 +1846,10 @@ nfp_pf_init(struct rte_pci_device *pci_dev) nfp_eth_set_configured(cpp, index, 0); } + nfp_devargs_parse(&pf_dev->devargs, pci_dev->device.devargs); + if (nfp_fw_setup(pci_dev, cpp, nfp_eth_table, hwinfo, - dev_info, &pf_dev->multi_pf) != 0) { + dev_info, &pf_dev->multi_pf, pf_dev->devargs.force_reload_fw) != 0) { PMD_INIT_LOG(ERR, "Error when uploading firmware"); ret = -EIO; goto eth_table_cleanup; @@ -2151,3 +2230,4 @@ static struct rte_pci_driver rte_nfp_net_pf_pmd = { RTE_PMD_REGISTER_PCI(NFP_PF_DRIVER_NAME, rte_nfp_net_pf_pmd); RTE_PMD_REGISTER_PCI_TABLE(NFP_PF_DRIVER_NAME, pci_id_nfp_pf_net_map); RTE_PMD_REGISTER_KMOD_DEP(NFP_PF_DRIVER_NAME, "* igb_uio | uio_pci_generic | vfio"); +RTE_PMD_REGISTER_PARAM_STRING(NFP_PF_DRIVER_NAME, NFP_PF_FORCE_RELOAD_FW "=<0|1>"); diff --git a/drivers/net/nfp/nfp_net_common.h b/drivers/net/nfp/nfp_net_common.h index 9c46bfd4f6..628c0d3491 100644 --- a/drivers/net/nfp/nfp_net_common.h +++ b/drivers/net/nfp/nfp_net_common.h @@ -94,6 +94,11 @@ struct nfp_process_share { struct nfp_flower_service *fl_service; }; +struct nfp_devargs { + /** Force reload firmware */ + bool force_reload_fw; +}; + struct nfp_pf_dev { /** Backpointer to associated pci device */ struct rte_pci_device *pci_dev; @@ -129,6 +134,9 @@ struct nfp_pf_dev { /** Synchronized info */ struct nfp_sync *sync; struct nfp_process_share process_share; + + /** NFP devarg param */ + struct nfp_devargs devargs; }; #define NFP_NET_FLOW_LIMIT 1024