LCOV - code coverage report
Current view: top level - drivers/net/nfp/nfpcore - nfp_nffw.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 55 0.0 %
Date: 2024-01-22 15:35:40 Functions: 0 4 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 23 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2018 Netronome Systems, Inc.
       3                 :            :  * All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "nfp_nffw.h"
       7                 :            : 
       8                 :            : #include "../nfp_logs.h"
       9                 :            : #include "nfp_mip.h"
      10                 :            : #include "nfp_resource.h"
      11                 :            : #include "nfp6000/nfp6000.h"
      12                 :            : 
      13                 :            : /*
      14                 :            :  * Init-CSR owner IDs for firmware map to firmware IDs which start at 4.
      15                 :            :  * Lower IDs are reserved for target and loader IDs.
      16                 :            :  */
      17                 :            : #define NFFW_FWID_EXT   3 /* For active MEs that we didn't load. */
      18                 :            : #define NFFW_FWID_BASE  4
      19                 :            : 
      20                 :            : #define NFFW_FWID_ALL   255
      21                 :            : 
      22                 :            : /*
      23                 :            :  * NFFW_INFO_VERSION history:
      24                 :            :  * 0: This was never actually used (before versioning), but it refers to
      25                 :            :  *    the previous struct which had FWINFO_CNT = MEINFO_CNT = 120 that later
      26                 :            :  *    changed to 200.
      27                 :            :  * 1: First versioned struct, with
      28                 :            :  *     FWINFO_CNT = 120
      29                 :            :  *     MEINFO_CNT = 120
      30                 :            :  * 2:  FWINFO_CNT = 200
      31                 :            :  *     MEINFO_CNT = 200
      32                 :            :  */
      33                 :            : #define NFFW_INFO_VERSION_CURRENT 2
      34                 :            : 
      35                 :            : /* Enough for all current chip families */
      36                 :            : #define NFFW_MEINFO_CNT_V1 120
      37                 :            : #define NFFW_FWINFO_CNT_V1 120
      38                 :            : #define NFFW_MEINFO_CNT_V2 200
      39                 :            : #define NFFW_FWINFO_CNT_V2 200
      40                 :            : 
      41                 :            : /* nfp.nffw meinfo */
      42                 :            : struct nffw_meinfo {
      43                 :            :         uint32_t ctxmask_fwid_meid;
      44                 :            : };
      45                 :            : 
      46                 :            : struct nffw_fwinfo {
      47                 :            :         uint32_t loaded_mu_da_mip_off_hi;
      48                 :            :         uint32_t mip_cppid; /**< 0 means no MIP */
      49                 :            :         uint32_t mip_offset_lo;
      50                 :            : };
      51                 :            : 
      52                 :            : struct nfp_nffw_info_v1 {
      53                 :            :         struct nffw_meinfo meinfo[NFFW_MEINFO_CNT_V1];
      54                 :            :         struct nffw_fwinfo fwinfo[NFFW_FWINFO_CNT_V1];
      55                 :            : };
      56                 :            : 
      57                 :            : struct nfp_nffw_info_v2 {
      58                 :            :         struct nffw_meinfo meinfo[NFFW_MEINFO_CNT_V2];
      59                 :            :         struct nffw_fwinfo fwinfo[NFFW_FWINFO_CNT_V2];
      60                 :            : };
      61                 :            : 
      62                 :            : struct nfp_nffw_info_data {
      63                 :            :         uint32_t flags[2];
      64                 :            :         union {
      65                 :            :                 struct nfp_nffw_info_v1 v1;
      66                 :            :                 struct nfp_nffw_info_v2 v2;
      67                 :            :         } info;
      68                 :            : };
      69                 :            : 
      70                 :            : struct nfp_nffw_info {
      71                 :            :         struct nfp_cpp *cpp;
      72                 :            :         struct nfp_resource *res;
      73                 :            : 
      74                 :            :         struct nfp_nffw_info_data fwinf;
      75                 :            : };
      76                 :            : 
      77                 :            : /*
      78                 :            :  * flg_info_version = flags[0]<27:16>
      79                 :            :  * This is a small version counter intended only to detect if the current
      80                 :            :  * implementation can read the current struct. Struct changes should be very
      81                 :            :  * rare and as such a 12-bit counter should cover large spans of time. By the
      82                 :            :  * time it wraps around, we don't expect to have 4096 versions of this struct
      83                 :            :  * to be in use at the same time.
      84                 :            :  */
      85                 :            : static uint32_t
      86                 :            : nffw_res_info_version_get(const struct nfp_nffw_info_data *res)
      87                 :            : {
      88                 :          0 :         return (res->flags[0] >> 16) & 0xfff;
      89                 :            : }
      90                 :            : 
      91                 :            : /* flg_init = flags[0]<0> */
      92                 :            : static uint32_t
      93                 :            : nffw_res_flg_init_get(const struct nfp_nffw_info_data *res)
      94                 :            : {
      95                 :          0 :         return (res->flags[0] >> 0) & 1;
      96                 :            : }
      97                 :            : 
      98                 :            : /* loaded = loaded_mu_da_mip_off_hi<31:31> */
      99                 :            : static uint32_t
     100                 :            : nffw_fwinfo_loaded_get(const struct nffw_fwinfo *fi)
     101                 :            : {
     102                 :          0 :         return (fi->loaded_mu_da_mip_off_hi >> 31) & 1;
     103                 :            : }
     104                 :            : 
     105                 :            : /* mip_cppid = mip_cppid */
     106                 :            : static uint32_t
     107                 :            : nffw_fwinfo_mip_cppid_get(const struct nffw_fwinfo *fi)
     108                 :            : {
     109                 :          0 :         return fi->mip_cppid;
     110                 :            : }
     111                 :            : 
     112                 :            : /* loaded = loaded_mu_da_mip_off_hi<8:8> */
     113                 :            : static uint32_t
     114                 :            : nffw_fwinfo_mip_mu_da_get(const struct nffw_fwinfo *fi)
     115                 :            : {
     116                 :          0 :         return (fi->loaded_mu_da_mip_off_hi >> 8) & 1;
     117                 :            : }
     118                 :            : 
     119                 :            : /* mip_offset = (loaded_mu_da_mip_off_hi<7:0> << 32) | mip_offset_lo */
     120                 :            : static uint64_t
     121                 :            : nffw_fwinfo_mip_offset_get(const struct nffw_fwinfo *fi)
     122                 :            : {
     123                 :          0 :         uint64_t mip_off_hi = fi->loaded_mu_da_mip_off_hi;
     124                 :            : 
     125                 :          0 :         return (mip_off_hi & 0xFF) << 32 | fi->mip_offset_lo;
     126                 :            : }
     127                 :            : 
     128                 :            : static uint32_t
     129                 :            : nffw_res_fwinfos(struct nfp_nffw_info_data *fwinf,
     130                 :            :                 struct nffw_fwinfo **arr)
     131                 :            : {
     132                 :            :         /*
     133                 :            :          * For the this code, version 0 is most likely to be version 1 in this
     134                 :            :          * case. Since the kernel driver does not take responsibility for
     135                 :            :          * initialising the nfp.nffw resource, any previous code (CA firmware or
     136                 :            :          * userspace) that left the version 0 and did set the init flag is going
     137                 :            :          * to be version 1.
     138                 :            :          */
     139                 :          0 :         switch (nffw_res_info_version_get(fwinf)) {
     140                 :          0 :         case 0:
     141                 :            :         case 1:
     142                 :          0 :                 *arr = &fwinf->info.v1.fwinfo[0];
     143                 :            :                 return NFFW_FWINFO_CNT_V1;
     144                 :          0 :         case 2:
     145                 :          0 :                 *arr = &fwinf->info.v2.fwinfo[0];
     146                 :            :                 return NFFW_FWINFO_CNT_V2;
     147                 :            :         default:
     148                 :            :                 *arr = NULL;
     149                 :            :                 return 0;
     150                 :            :         }
     151                 :            : }
     152                 :            : 
     153                 :            : /**
     154                 :            :  * Acquire the lock on the NFFW table
     155                 :            :  *
     156                 :            :  * @param cpp
     157                 :            :  *   NFP CPP handle
     158                 :            :  *
     159                 :            :  * @return
     160                 :            :  *   NFFW info pointer, or NULL on failure
     161                 :            :  */
     162                 :            : struct nfp_nffw_info *
     163                 :          0 : nfp_nffw_info_open(struct nfp_cpp *cpp)
     164                 :            : {
     165                 :            :         int err;
     166                 :            :         uint32_t info_ver;
     167                 :            :         struct nfp_nffw_info *state;
     168                 :            :         struct nfp_nffw_info_data *fwinf;
     169                 :            : 
     170                 :          0 :         state = malloc(sizeof(*state));
     171         [ #  # ]:          0 :         if (state == NULL)
     172                 :            :                 return NULL;
     173                 :            : 
     174                 :            :         memset(state, 0, sizeof(*state));
     175                 :            : 
     176                 :          0 :         state->res = nfp_resource_acquire(cpp, NFP_RESOURCE_NFP_NFFW);
     177         [ #  # ]:          0 :         if (state->res == NULL) {
     178                 :          0 :                 PMD_DRV_LOG(ERR, "NFFW - acquire resource failed");
     179                 :          0 :                 goto err_free;
     180                 :            :         }
     181                 :            : 
     182                 :          0 :         fwinf = &state->fwinf;
     183                 :            : 
     184         [ #  # ]:          0 :         if (sizeof(*fwinf) > nfp_resource_size(state->res))
     185                 :          0 :                 goto err_release;
     186                 :            : 
     187                 :          0 :         err = nfp_cpp_read(cpp, nfp_resource_cpp_id(state->res),
     188                 :          0 :                         nfp_resource_address(state->res),
     189                 :            :                         fwinf, sizeof(*fwinf));
     190         [ #  # ]:          0 :         if (err < (int)sizeof(*fwinf)) {
     191                 :          0 :                 PMD_DRV_LOG(ERR, "NFFW - CPP read error %d", err);
     192                 :          0 :                 goto err_release;
     193                 :            :         }
     194                 :            : 
     195         [ #  # ]:          0 :         if (nffw_res_flg_init_get(fwinf) == 0)
     196                 :          0 :                 goto err_release;
     197                 :            : 
     198                 :            :         info_ver = nffw_res_info_version_get(fwinf);
     199         [ #  # ]:          0 :         if (info_ver > NFFW_INFO_VERSION_CURRENT)
     200                 :          0 :                 goto err_release;
     201                 :            : 
     202                 :          0 :         state->cpp = cpp;
     203                 :          0 :         return state;
     204                 :            : 
     205                 :          0 : err_release:
     206                 :          0 :         nfp_resource_release(state->res);
     207                 :          0 : err_free:
     208                 :          0 :         free(state);
     209                 :          0 :         return NULL;
     210                 :            : }
     211                 :            : 
     212                 :            : /**
     213                 :            :  * Release the lock on the NFFW table
     214                 :            :  *
     215                 :            :  * @param state
     216                 :            :  *   NFFW info pointer
     217                 :            :  */
     218                 :            : void
     219                 :          0 : nfp_nffw_info_close(struct nfp_nffw_info *state)
     220                 :            : {
     221                 :          0 :         nfp_resource_release(state->res);
     222                 :          0 :         free(state);
     223                 :          0 : }
     224                 :            : 
     225                 :            : /**
     226                 :            :  * Return the first firmware ID in the NFFW
     227                 :            :  *
     228                 :            :  * @param state
     229                 :            :  *   NFFW info pointer
     230                 :            :  *
     231                 :            :  * @return:
     232                 :            :  *   First NFFW firmware info, NULL on failure
     233                 :            :  */
     234                 :            : static struct nffw_fwinfo *
     235      [ #  #  # ]:          0 : nfp_nffw_info_fwid_first(struct nfp_nffw_info *state)
     236                 :            : {
     237                 :            :         uint32_t i;
     238                 :            :         uint32_t cnt;
     239                 :            :         struct nffw_fwinfo *fwinfo;
     240                 :            : 
     241                 :            :         cnt = nffw_res_fwinfos(&state->fwinf, &fwinfo);
     242                 :            :         if (cnt == 0)
     243                 :            :                 return NULL;
     244                 :            : 
     245         [ #  # ]:          0 :         for (i = 0; i < cnt; i++)
     246         [ #  # ]:          0 :                 if (nffw_fwinfo_loaded_get(&fwinfo[i]) != 0)
     247                 :          0 :                         return &fwinfo[i];
     248                 :            : 
     249                 :            :         return NULL;
     250                 :            : }
     251                 :            : 
     252                 :            : /**
     253                 :            :  * Retrieve the location of the first FW's MIP
     254                 :            :  *
     255                 :            :  * @param state
     256                 :            :  *   NFFW info pointer
     257                 :            :  * @param cpp_id
     258                 :            :  *   Pointer to the CPP ID of the MIP
     259                 :            :  * @param off
     260                 :            :  *   Pointer to the CPP Address of the MIP
     261                 :            :  *
     262                 :            :  * @return
     263                 :            :  *   0, or -ERRNO
     264                 :            :  */
     265                 :            : int
     266                 :          0 : nfp_nffw_info_mip_first(struct nfp_nffw_info *state,
     267                 :            :                 uint32_t *cpp_id,
     268                 :            :                 uint64_t *offset)
     269                 :            : {
     270                 :            :         struct nffw_fwinfo *fwinfo;
     271                 :            : 
     272                 :          0 :         fwinfo = nfp_nffw_info_fwid_first(state);
     273         [ #  # ]:          0 :         if (fwinfo == NULL)
     274                 :            :                 return -EINVAL;
     275                 :            : 
     276                 :          0 :         *cpp_id = nffw_fwinfo_mip_cppid_get(fwinfo);
     277                 :          0 :         *offset = nffw_fwinfo_mip_offset_get(fwinfo);
     278                 :            : 
     279         [ #  # ]:          0 :         if (nffw_fwinfo_mip_mu_da_get(fwinfo) != 0) {
     280                 :          0 :                 int locality_off = nfp_cpp_mu_locality_lsb(state->cpp);
     281                 :            : 
     282                 :          0 :                 *offset &= ~(NFP_MU_ADDR_ACCESS_TYPE_MASK << locality_off);
     283                 :          0 :                 *offset |= NFP_MU_ADDR_ACCESS_TYPE_DIRECT << locality_off;
     284                 :            :         }
     285                 :            : 
     286                 :            :         return 0;
     287                 :            : }

Generated by: LCOV version 1.14