nfp_mip.c (3489B)
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2/* Copyright (C) 2015-2017 Netronome Systems, Inc. */ 3 4/* 5 * nfp_mip.c 6 * Authors: Jakub Kicinski <jakub.kicinski@netronome.com> 7 * Jason McMullan <jason.mcmullan@netronome.com> 8 * Espen Skoglund <espen.skoglund@netronome.com> 9 */ 10#include <linux/kernel.h> 11#include <linux/slab.h> 12 13#include "nfp.h" 14#include "nfp_cpp.h" 15#include "nfp_nffw.h" 16 17#define NFP_MIP_SIGNATURE cpu_to_le32(0x0050494d) /* "MIP\0" */ 18#define NFP_MIP_VERSION cpu_to_le32(1) 19#define NFP_MIP_MAX_OFFSET (256 * 1024) 20 21struct nfp_mip { 22 __le32 signature; 23 __le32 mip_version; 24 __le32 mip_size; 25 __le32 first_entry; 26 27 __le32 version; 28 __le32 buildnum; 29 __le32 buildtime; 30 __le32 loadtime; 31 32 __le32 symtab_addr; 33 __le32 symtab_size; 34 __le32 strtab_addr; 35 __le32 strtab_size; 36 37 char name[16]; 38 char toolchain[32]; 39}; 40 41/* Read memory and check if it could be a valid MIP */ 42static int 43nfp_mip_try_read(struct nfp_cpp *cpp, u32 cpp_id, u64 addr, struct nfp_mip *mip) 44{ 45 int ret; 46 47 ret = nfp_cpp_read(cpp, cpp_id, addr, mip, sizeof(*mip)); 48 if (ret != sizeof(*mip)) { 49 nfp_err(cpp, "Failed to read MIP data (%d, %zu)\n", 50 ret, sizeof(*mip)); 51 return -EIO; 52 } 53 if (mip->signature != NFP_MIP_SIGNATURE) { 54 nfp_warn(cpp, "Incorrect MIP signature (0x%08x)\n", 55 le32_to_cpu(mip->signature)); 56 return -EINVAL; 57 } 58 if (mip->mip_version != NFP_MIP_VERSION) { 59 nfp_warn(cpp, "Unsupported MIP version (%d)\n", 60 le32_to_cpu(mip->mip_version)); 61 return -EINVAL; 62 } 63 64 return 0; 65} 66 67/* Try to locate MIP using the resource table */ 68static int nfp_mip_read_resource(struct nfp_cpp *cpp, struct nfp_mip *mip) 69{ 70 struct nfp_nffw_info *nffw_info; 71 u32 cpp_id; 72 u64 addr; 73 int err; 74 75 nffw_info = nfp_nffw_info_open(cpp); 76 if (IS_ERR(nffw_info)) 77 return PTR_ERR(nffw_info); 78 79 err = nfp_nffw_info_mip_first(nffw_info, &cpp_id, &addr); 80 if (err) 81 goto exit_close_nffw; 82 83 err = nfp_mip_try_read(cpp, cpp_id, addr, mip); 84exit_close_nffw: 85 nfp_nffw_info_close(nffw_info); 86 return err; 87} 88 89/** 90 * nfp_mip_open() - Get device MIP structure 91 * @cpp: NFP CPP Handle 92 * 93 * Copy MIP structure from NFP device and return it. The returned 94 * structure is handled internally by the library and should be 95 * freed by calling nfp_mip_close(). 96 * 97 * Return: pointer to mip, NULL on failure. 98 */ 99const struct nfp_mip *nfp_mip_open(struct nfp_cpp *cpp) 100{ 101 struct nfp_mip *mip; 102 int err; 103 104 mip = kmalloc(sizeof(*mip), GFP_KERNEL); 105 if (!mip) 106 return NULL; 107 108 err = nfp_mip_read_resource(cpp, mip); 109 if (err) { 110 kfree(mip); 111 return NULL; 112 } 113 114 mip->name[sizeof(mip->name) - 1] = 0; 115 116 return mip; 117} 118 119void nfp_mip_close(const struct nfp_mip *mip) 120{ 121 kfree(mip); 122} 123 124const char *nfp_mip_name(const struct nfp_mip *mip) 125{ 126 return mip->name; 127} 128 129/** 130 * nfp_mip_symtab() - Get the address and size of the MIP symbol table 131 * @mip: MIP handle 132 * @addr: Location for NFP DDR address of MIP symbol table 133 * @size: Location for size of MIP symbol table 134 */ 135void nfp_mip_symtab(const struct nfp_mip *mip, u32 *addr, u32 *size) 136{ 137 *addr = le32_to_cpu(mip->symtab_addr); 138 *size = le32_to_cpu(mip->symtab_size); 139} 140 141/** 142 * nfp_mip_strtab() - Get the address and size of the MIP symbol name table 143 * @mip: MIP handle 144 * @addr: Location for NFP DDR address of MIP symbol name table 145 * @size: Location for size of MIP symbol name table 146 */ 147void nfp_mip_strtab(const struct nfp_mip *mip, u32 *addr, u32 *size) 148{ 149 *addr = le32_to_cpu(mip->strtab_addr); 150 *size = le32_to_cpu(mip->strtab_size); 151}