Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
0002 /* Copyright (C) 2015-2017 Netronome Systems, Inc. */
0003 
0004 /*
0005  * nfp_mip.c
0006  * Authors: Jakub Kicinski <jakub.kicinski@netronome.com>
0007  *          Jason McMullan <jason.mcmullan@netronome.com>
0008  *          Espen Skoglund <espen.skoglund@netronome.com>
0009  */
0010 #include <linux/kernel.h>
0011 #include <linux/slab.h>
0012 
0013 #include "nfp.h"
0014 #include "nfp_cpp.h"
0015 #include "nfp_nffw.h"
0016 
0017 #define NFP_MIP_SIGNATURE   cpu_to_le32(0x0050494d)  /* "MIP\0" */
0018 #define NFP_MIP_VERSION     cpu_to_le32(1)
0019 #define NFP_MIP_MAX_OFFSET  (256 * 1024)
0020 
0021 struct nfp_mip {
0022     __le32 signature;
0023     __le32 mip_version;
0024     __le32 mip_size;
0025     __le32 first_entry;
0026 
0027     __le32 version;
0028     __le32 buildnum;
0029     __le32 buildtime;
0030     __le32 loadtime;
0031 
0032     __le32 symtab_addr;
0033     __le32 symtab_size;
0034     __le32 strtab_addr;
0035     __le32 strtab_size;
0036 
0037     char name[16];
0038     char toolchain[32];
0039 };
0040 
0041 /* Read memory and check if it could be a valid MIP */
0042 static int
0043 nfp_mip_try_read(struct nfp_cpp *cpp, u32 cpp_id, u64 addr, struct nfp_mip *mip)
0044 {
0045     int ret;
0046 
0047     ret = nfp_cpp_read(cpp, cpp_id, addr, mip, sizeof(*mip));
0048     if (ret != sizeof(*mip)) {
0049         nfp_err(cpp, "Failed to read MIP data (%d, %zu)\n",
0050             ret, sizeof(*mip));
0051         return -EIO;
0052     }
0053     if (mip->signature != NFP_MIP_SIGNATURE) {
0054         nfp_warn(cpp, "Incorrect MIP signature (0x%08x)\n",
0055              le32_to_cpu(mip->signature));
0056         return -EINVAL;
0057     }
0058     if (mip->mip_version != NFP_MIP_VERSION) {
0059         nfp_warn(cpp, "Unsupported MIP version (%d)\n",
0060              le32_to_cpu(mip->mip_version));
0061         return -EINVAL;
0062     }
0063 
0064     return 0;
0065 }
0066 
0067 /* Try to locate MIP using the resource table */
0068 static int nfp_mip_read_resource(struct nfp_cpp *cpp, struct nfp_mip *mip)
0069 {
0070     struct nfp_nffw_info *nffw_info;
0071     u32 cpp_id;
0072     u64 addr;
0073     int err;
0074 
0075     nffw_info = nfp_nffw_info_open(cpp);
0076     if (IS_ERR(nffw_info))
0077         return PTR_ERR(nffw_info);
0078 
0079     err = nfp_nffw_info_mip_first(nffw_info, &cpp_id, &addr);
0080     if (err)
0081         goto exit_close_nffw;
0082 
0083     err = nfp_mip_try_read(cpp, cpp_id, addr, mip);
0084 exit_close_nffw:
0085     nfp_nffw_info_close(nffw_info);
0086     return err;
0087 }
0088 
0089 /**
0090  * nfp_mip_open() - Get device MIP structure
0091  * @cpp:    NFP CPP Handle
0092  *
0093  * Copy MIP structure from NFP device and return it.  The returned
0094  * structure is handled internally by the library and should be
0095  * freed by calling nfp_mip_close().
0096  *
0097  * Return: pointer to mip, NULL on failure.
0098  */
0099 const struct nfp_mip *nfp_mip_open(struct nfp_cpp *cpp)
0100 {
0101     struct nfp_mip *mip;
0102     int err;
0103 
0104     mip = kmalloc(sizeof(*mip), GFP_KERNEL);
0105     if (!mip)
0106         return NULL;
0107 
0108     err = nfp_mip_read_resource(cpp, mip);
0109     if (err) {
0110         kfree(mip);
0111         return NULL;
0112     }
0113 
0114     mip->name[sizeof(mip->name) - 1] = 0;
0115 
0116     return mip;
0117 }
0118 
0119 void nfp_mip_close(const struct nfp_mip *mip)
0120 {
0121     kfree(mip);
0122 }
0123 
0124 const char *nfp_mip_name(const struct nfp_mip *mip)
0125 {
0126     return mip->name;
0127 }
0128 
0129 /**
0130  * nfp_mip_symtab() - Get the address and size of the MIP symbol table
0131  * @mip:    MIP handle
0132  * @addr:   Location for NFP DDR address of MIP symbol table
0133  * @size:   Location for size of MIP symbol table
0134  */
0135 void nfp_mip_symtab(const struct nfp_mip *mip, u32 *addr, u32 *size)
0136 {
0137     *addr = le32_to_cpu(mip->symtab_addr);
0138     *size = le32_to_cpu(mip->symtab_size);
0139 }
0140 
0141 /**
0142  * nfp_mip_strtab() - Get the address and size of the MIP symbol name table
0143  * @mip:    MIP handle
0144  * @addr:   Location for NFP DDR address of MIP symbol name table
0145  * @size:   Location for size of MIP symbol name table
0146  */
0147 void nfp_mip_strtab(const struct nfp_mip *mip, u32 *addr, u32 *size)
0148 {
0149     *addr = le32_to_cpu(mip->strtab_addr);
0150     *size = le32_to_cpu(mip->strtab_size);
0151 }