The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/sfxge/common/siena_nvram.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2009-2016 Solarflare Communications Inc.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions are met:
    9  *
   10  * 1. Redistributions of source code must retain the above copyright notice,
   11  *    this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright notice,
   13  *    this list of conditions and the following disclaimer in the documentation
   14  *    and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
   18  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
   20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   23  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   25  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  *
   28  * The views and conclusions contained in the software and documentation are
   29  * those of the authors and should not be interpreted as representing official
   30  * policies, either expressed or implied, of the FreeBSD Project.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD$");
   35 
   36 #include "efx.h"
   37 #include "efx_impl.h"
   38 
   39 #if EFSYS_OPT_SIENA
   40 
   41 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
   42 
   43         __checkReturn           efx_rc_t
   44 siena_nvram_partn_size(
   45         __in                    efx_nic_t *enp,
   46         __in                    uint32_t partn,
   47         __out                   size_t *sizep)
   48 {
   49         efx_rc_t rc;
   50 
   51         if ((1 << partn) & ~enp->en_u.siena.enu_partn_mask) {
   52                 rc = ENOTSUP;
   53                 goto fail1;
   54         }
   55 
   56         if ((rc = efx_mcdi_nvram_info(enp, partn, sizep,
   57             NULL, NULL, NULL)) != 0) {
   58                 goto fail2;
   59         }
   60 
   61         return (0);
   62 
   63 fail2:
   64         EFSYS_PROBE(fail2);
   65 fail1:
   66         EFSYS_PROBE1(fail1, efx_rc_t, rc);
   67 
   68         return (rc);
   69 }
   70 
   71         __checkReturn           efx_rc_t
   72 siena_nvram_partn_lock(
   73         __in                    efx_nic_t *enp,
   74         __in                    uint32_t partn)
   75 {
   76         efx_rc_t rc;
   77 
   78         if ((rc = efx_mcdi_nvram_update_start(enp, partn)) != 0) {
   79                 goto fail1;
   80         }
   81 
   82         return (0);
   83 
   84 fail1:
   85         EFSYS_PROBE1(fail1, efx_rc_t, rc);
   86 
   87         return (rc);
   88 }
   89 
   90         __checkReturn           efx_rc_t
   91 siena_nvram_partn_read(
   92         __in                    efx_nic_t *enp,
   93         __in                    uint32_t partn,
   94         __in                    unsigned int offset,
   95         __out_bcount(size)      caddr_t data,
   96         __in                    size_t size)
   97 {
   98         size_t chunk;
   99         efx_rc_t rc;
  100 
  101         while (size > 0) {
  102                 chunk = MIN(size, SIENA_NVRAM_CHUNK);
  103 
  104                 if ((rc = efx_mcdi_nvram_read(enp, partn, offset, data, chunk,
  105                             MC_CMD_NVRAM_READ_IN_V2_DEFAULT)) != 0) {
  106                         goto fail1;
  107                 }
  108 
  109                 size -= chunk;
  110                 data += chunk;
  111                 offset += chunk;
  112         }
  113 
  114         return (0);
  115 
  116 fail1:
  117         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  118 
  119         return (rc);
  120 }
  121 
  122         __checkReturn           efx_rc_t
  123 siena_nvram_partn_erase(
  124         __in                    efx_nic_t *enp,
  125         __in                    uint32_t partn,
  126         __in                    unsigned int offset,
  127         __in                    size_t size)
  128 {
  129         efx_rc_t rc;
  130 
  131         if ((rc = efx_mcdi_nvram_erase(enp, partn, offset, size)) != 0) {
  132                 goto fail1;
  133         }
  134 
  135         return (0);
  136 
  137 fail1:
  138         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  139 
  140         return (rc);
  141 }
  142 
  143         __checkReturn           efx_rc_t
  144 siena_nvram_partn_write(
  145         __in                    efx_nic_t *enp,
  146         __in                    uint32_t partn,
  147         __in                    unsigned int offset,
  148         __out_bcount(size)      caddr_t data,
  149         __in                    size_t size)
  150 {
  151         size_t chunk;
  152         efx_rc_t rc;
  153 
  154         while (size > 0) {
  155                 chunk = MIN(size, SIENA_NVRAM_CHUNK);
  156 
  157                 if ((rc = efx_mcdi_nvram_write(enp, partn, offset,
  158                             data, chunk)) != 0) {
  159                         goto fail1;
  160                 }
  161 
  162                 size -= chunk;
  163                 data += chunk;
  164                 offset += chunk;
  165         }
  166 
  167         return (0);
  168 
  169 fail1:
  170         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  171 
  172         return (rc);
  173 }
  174 
  175         __checkReturn           efx_rc_t
  176 siena_nvram_partn_unlock(
  177         __in                    efx_nic_t *enp,
  178         __in                    uint32_t partn,
  179         __out_opt               uint32_t *verify_resultp)
  180 {
  181         boolean_t reboot;
  182         efx_rc_t rc;
  183 
  184         /*
  185          * Reboot into the new image only for PHYs. The driver has to
  186          * explicitly cope with an MC reboot after a firmware update.
  187          */
  188         reboot = (partn == MC_CMD_NVRAM_TYPE_PHY_PORT0 ||
  189                     partn == MC_CMD_NVRAM_TYPE_PHY_PORT1 ||
  190                     partn == MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO);
  191 
  192         rc = efx_mcdi_nvram_update_finish(enp, partn, reboot, verify_resultp);
  193         if (rc != 0)
  194                 goto fail1;
  195 
  196         return (0);
  197 
  198 fail1:
  199         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  200 
  201         return (rc);
  202 }
  203 
  204 #endif  /* EFSYS_OPT_VPD || EFSYS_OPT_NVRAM */
  205 
  206 #if EFSYS_OPT_NVRAM
  207 
  208 typedef struct siena_parttbl_entry_s {
  209         unsigned int            partn;
  210         unsigned int            port;
  211         efx_nvram_type_t        nvtype;
  212 } siena_parttbl_entry_t;
  213 
  214 static siena_parttbl_entry_t siena_parttbl[] = {
  215         {MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO,   1, EFX_NVRAM_NULLPHY},
  216         {MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO,   2, EFX_NVRAM_NULLPHY},
  217         {MC_CMD_NVRAM_TYPE_MC_FW,               1, EFX_NVRAM_MC_FIRMWARE},
  218         {MC_CMD_NVRAM_TYPE_MC_FW,               2, EFX_NVRAM_MC_FIRMWARE},
  219         {MC_CMD_NVRAM_TYPE_MC_FW_BACKUP,        1, EFX_NVRAM_MC_GOLDEN},
  220         {MC_CMD_NVRAM_TYPE_MC_FW_BACKUP,        2, EFX_NVRAM_MC_GOLDEN},
  221         {MC_CMD_NVRAM_TYPE_EXP_ROM,             1, EFX_NVRAM_BOOTROM},
  222         {MC_CMD_NVRAM_TYPE_EXP_ROM,             2, EFX_NVRAM_BOOTROM},
  223         {MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT0,   1, EFX_NVRAM_BOOTROM_CFG},
  224         {MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT1,   2, EFX_NVRAM_BOOTROM_CFG},
  225         {MC_CMD_NVRAM_TYPE_PHY_PORT0,           1, EFX_NVRAM_PHY},
  226         {MC_CMD_NVRAM_TYPE_PHY_PORT1,           2, EFX_NVRAM_PHY},
  227         {MC_CMD_NVRAM_TYPE_FPGA,                1, EFX_NVRAM_FPGA},
  228         {MC_CMD_NVRAM_TYPE_FPGA,                2, EFX_NVRAM_FPGA},
  229         {MC_CMD_NVRAM_TYPE_FPGA_BACKUP,         1, EFX_NVRAM_FPGA_BACKUP},
  230         {MC_CMD_NVRAM_TYPE_FPGA_BACKUP,         2, EFX_NVRAM_FPGA_BACKUP},
  231         {MC_CMD_NVRAM_TYPE_FC_FW,               1, EFX_NVRAM_FCFW},
  232         {MC_CMD_NVRAM_TYPE_FC_FW,               2, EFX_NVRAM_FCFW},
  233         {MC_CMD_NVRAM_TYPE_CPLD,                1, EFX_NVRAM_CPLD},
  234         {MC_CMD_NVRAM_TYPE_CPLD,                2, EFX_NVRAM_CPLD},
  235         {MC_CMD_NVRAM_TYPE_LICENSE,             1, EFX_NVRAM_LICENSE},
  236         {MC_CMD_NVRAM_TYPE_LICENSE,             2, EFX_NVRAM_LICENSE}
  237 };
  238 
  239         __checkReturn           efx_rc_t
  240 siena_nvram_type_to_partn(
  241         __in                    efx_nic_t *enp,
  242         __in                    efx_nvram_type_t type,
  243         __out                   uint32_t *partnp)
  244 {
  245         efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
  246         unsigned int i;
  247 
  248         EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
  249         EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
  250         EFSYS_ASSERT(partnp != NULL);
  251 
  252         for (i = 0; i < EFX_ARRAY_SIZE(siena_parttbl); i++) {
  253                 siena_parttbl_entry_t *entry = &siena_parttbl[i];
  254 
  255                 if (entry->port == emip->emi_port && entry->nvtype == type) {
  256                         *partnp = entry->partn;
  257                         return (0);
  258                 }
  259         }
  260 
  261         return (ENOTSUP);
  262 }
  263 
  264 #if EFSYS_OPT_DIAG
  265 
  266         __checkReturn           efx_rc_t
  267 siena_nvram_test(
  268         __in                    efx_nic_t *enp)
  269 {
  270         efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
  271         siena_parttbl_entry_t *entry;
  272         unsigned int i;
  273         efx_rc_t rc;
  274 
  275         /*
  276          * Iterate over the list of supported partition types
  277          * applicable to *this* port
  278          */
  279         for (i = 0; i < EFX_ARRAY_SIZE(siena_parttbl); i++) {
  280                 entry = &siena_parttbl[i];
  281 
  282                 if (entry->port != emip->emi_port ||
  283                     !(enp->en_u.siena.enu_partn_mask & (1 << entry->partn)))
  284                         continue;
  285 
  286                 if ((rc = efx_mcdi_nvram_test(enp, entry->partn)) != 0) {
  287                         goto fail1;
  288                 }
  289         }
  290 
  291         return (0);
  292 
  293 fail1:
  294         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  295 
  296         return (rc);
  297 }
  298 
  299 #endif  /* EFSYS_OPT_DIAG */
  300 
  301 #define SIENA_DYNAMIC_CFG_SIZE(_nitems)                                 \
  302         (sizeof (siena_mc_dynamic_config_hdr_t) + ((_nitems) *          \
  303         sizeof (((siena_mc_dynamic_config_hdr_t *)NULL)->fw_version[0])))
  304 
  305         __checkReturn           efx_rc_t
  306 siena_nvram_get_dynamic_cfg(
  307         __in                    efx_nic_t *enp,
  308         __in                    uint32_t partn,
  309         __in                    boolean_t vpd,
  310         __out                   siena_mc_dynamic_config_hdr_t **dcfgp,
  311         __out                   size_t *sizep)
  312 {
  313         siena_mc_dynamic_config_hdr_t *dcfg = NULL;
  314         size_t size;
  315         uint8_t cksum;
  316         unsigned int vpd_offset;
  317         unsigned int vpd_length;
  318         unsigned int hdr_length;
  319         unsigned int nversions;
  320         unsigned int pos;
  321         unsigned int region;
  322         efx_rc_t rc;
  323 
  324         EFSYS_ASSERT(partn == MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0 ||
  325                     partn == MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1);
  326 
  327         /*
  328          * Allocate sufficient memory for the entire dynamiccfg area, even
  329          * if we're not actually going to read in the VPD.
  330          */
  331         if ((rc = siena_nvram_partn_size(enp, partn, &size)) != 0)
  332                 goto fail1;
  333 
  334         if (size < SIENA_NVRAM_CHUNK) {
  335                 rc = EINVAL;
  336                 goto fail2;
  337         }
  338 
  339         EFSYS_KMEM_ALLOC(enp->en_esip, size, dcfg);
  340         if (dcfg == NULL) {
  341                 rc = ENOMEM;
  342                 goto fail3;
  343         }
  344 
  345         if ((rc = siena_nvram_partn_read(enp, partn, 0,
  346             (caddr_t)dcfg, SIENA_NVRAM_CHUNK)) != 0)
  347                 goto fail4;
  348 
  349         /* Verify the magic */
  350         if (EFX_DWORD_FIELD(dcfg->magic, EFX_DWORD_0)
  351             != SIENA_MC_DYNAMIC_CONFIG_MAGIC)
  352                 goto invalid1;
  353 
  354         /* All future versions of the structure must be backwards compatible */
  355         EFX_STATIC_ASSERT(SIENA_MC_DYNAMIC_CONFIG_VERSION == 0);
  356 
  357         hdr_length = EFX_WORD_FIELD(dcfg->length, EFX_WORD_0);
  358         nversions = EFX_DWORD_FIELD(dcfg->num_fw_version_items, EFX_DWORD_0);
  359         vpd_offset = EFX_DWORD_FIELD(dcfg->dynamic_vpd_offset, EFX_DWORD_0);
  360         vpd_length = EFX_DWORD_FIELD(dcfg->dynamic_vpd_length, EFX_DWORD_0);
  361 
  362         /* Verify the hdr doesn't overflow the partn size */
  363         if (hdr_length > size || vpd_offset > size || vpd_length > size ||
  364             vpd_length + vpd_offset > size)
  365                 goto invalid2;
  366 
  367         /* Verify the header has room for all it's versions */
  368         if (hdr_length < SIENA_DYNAMIC_CFG_SIZE(0) ||
  369             hdr_length < SIENA_DYNAMIC_CFG_SIZE(nversions))
  370                 goto invalid3;
  371 
  372         /*
  373          * Read the remaining portion of the dcfg, either including
  374          * the whole of VPD (there is no vpd length in this structure,
  375          * so we have to parse each tag), or just the dcfg header itself
  376          */
  377         region = vpd ? vpd_offset + vpd_length : hdr_length;
  378         if (region > SIENA_NVRAM_CHUNK) {
  379                 if ((rc = siena_nvram_partn_read(enp, partn, SIENA_NVRAM_CHUNK,
  380                     (caddr_t)dcfg + SIENA_NVRAM_CHUNK,
  381                     region - SIENA_NVRAM_CHUNK)) != 0)
  382                         goto fail5;
  383         }
  384 
  385         /* Verify checksum */
  386         cksum = 0;
  387         for (pos = 0; pos < hdr_length; pos++)
  388                 cksum += ((uint8_t *)dcfg)[pos];
  389         if (cksum != 0)
  390                 goto invalid4;
  391 
  392         goto done;
  393 
  394 invalid4:
  395         EFSYS_PROBE(invalid4);
  396 invalid3:
  397         EFSYS_PROBE(invalid3);
  398 invalid2:
  399         EFSYS_PROBE(invalid2);
  400 invalid1:
  401         EFSYS_PROBE(invalid1);
  402 
  403         /*
  404          * Construct a new "null" dcfg, with an empty version vector,
  405          * and an empty VPD chunk trailing. This has the neat side effect
  406          * of testing the exception paths in the write path.
  407          */
  408         EFX_POPULATE_DWORD_1(dcfg->magic,
  409                             EFX_DWORD_0, SIENA_MC_DYNAMIC_CONFIG_MAGIC);
  410         EFX_POPULATE_WORD_1(dcfg->length, EFX_WORD_0, sizeof (*dcfg));
  411         EFX_POPULATE_BYTE_1(dcfg->version, EFX_BYTE_0,
  412                             SIENA_MC_DYNAMIC_CONFIG_VERSION);
  413         EFX_POPULATE_DWORD_1(dcfg->dynamic_vpd_offset,
  414                             EFX_DWORD_0, sizeof (*dcfg));
  415         EFX_POPULATE_DWORD_1(dcfg->dynamic_vpd_length, EFX_DWORD_0, 0);
  416         EFX_POPULATE_DWORD_1(dcfg->num_fw_version_items, EFX_DWORD_0, 0);
  417 
  418 done:
  419         *dcfgp = dcfg;
  420         *sizep = size;
  421 
  422         return (0);
  423 
  424 fail5:
  425         EFSYS_PROBE(fail5);
  426 fail4:
  427         EFSYS_PROBE(fail4);
  428 
  429         EFSYS_KMEM_FREE(enp->en_esip, size, dcfg);
  430 
  431 fail3:
  432         EFSYS_PROBE(fail3);
  433 fail2:
  434         EFSYS_PROBE(fail2);
  435 fail1:
  436         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  437 
  438         return (rc);
  439 }
  440 
  441         __checkReturn           efx_rc_t
  442 siena_nvram_get_subtype(
  443         __in                    efx_nic_t *enp,
  444         __in                    uint32_t partn,
  445         __out                   uint32_t *subtypep)
  446 {
  447         efx_mcdi_req_t req;
  448         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_BOARD_CFG_IN_LEN,
  449                 MC_CMD_GET_BOARD_CFG_OUT_LENMAX);
  450         efx_word_t *fw_list;
  451         efx_rc_t rc;
  452 
  453         req.emr_cmd = MC_CMD_GET_BOARD_CFG;
  454         req.emr_in_buf = payload;
  455         req.emr_in_length = MC_CMD_GET_BOARD_CFG_IN_LEN;
  456         req.emr_out_buf = payload;
  457         req.emr_out_length = MC_CMD_GET_BOARD_CFG_OUT_LENMAX;
  458 
  459         efx_mcdi_execute(enp, &req);
  460 
  461         if (req.emr_rc != 0) {
  462                 rc = req.emr_rc;
  463                 goto fail1;
  464         }
  465 
  466         if (req.emr_out_length_used < MC_CMD_GET_BOARD_CFG_OUT_LENMIN) {
  467                 rc = EMSGSIZE;
  468                 goto fail2;
  469         }
  470 
  471         if (req.emr_out_length_used <
  472             MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_OFST +
  473             (partn + 1) * sizeof (efx_word_t)) {
  474                 rc = ENOENT;
  475                 goto fail3;
  476         }
  477 
  478         fw_list = MCDI_OUT2(req, efx_word_t,
  479                             GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST);
  480         *subtypep = EFX_WORD_FIELD(fw_list[partn], EFX_WORD_0);
  481 
  482         return (0);
  483 
  484 fail3:
  485         EFSYS_PROBE(fail3);
  486 fail2:
  487         EFSYS_PROBE(fail2);
  488 fail1:
  489         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  490 
  491         return (rc);
  492 }
  493 
  494         __checkReturn           efx_rc_t
  495 siena_nvram_partn_get_version(
  496         __in                    efx_nic_t *enp,
  497         __in                    uint32_t partn,
  498         __out                   uint32_t *subtypep,
  499         __out_ecount(4)         uint16_t version[4])
  500 {
  501         siena_mc_dynamic_config_hdr_t *dcfg;
  502         siena_parttbl_entry_t *entry;
  503         uint32_t dcfg_partn;
  504         unsigned int i;
  505         efx_rc_t rc;
  506 
  507         if ((1 << partn) & ~enp->en_u.siena.enu_partn_mask) {
  508                 rc = ENOTSUP;
  509                 goto fail1;
  510         }
  511 
  512         if ((rc = siena_nvram_get_subtype(enp, partn, subtypep)) != 0)
  513                 goto fail2;
  514 
  515         /*
  516          * Some partitions are accessible from both ports (for instance BOOTROM)
  517          * Find the highest version reported by all dcfg structures on ports
  518          * that have access to this partition.
  519          */
  520         version[0] = version[1] = version[2] = version[3] = 0;
  521         for (i = 0; i < EFX_ARRAY_SIZE(siena_parttbl); i++) {
  522                 siena_mc_fw_version_t *verp;
  523                 unsigned int nitems;
  524                 uint16_t temp[4];
  525                 size_t length;
  526 
  527                 entry = &siena_parttbl[i];
  528                 if (entry->partn != partn)
  529                         continue;
  530 
  531                 dcfg_partn = (entry->port == 1)
  532                         ? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0
  533                         : MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1;
  534                 /*
  535                  * Ingore missing partitions on port 2, assuming they're due
  536                  * to running on a single port part.
  537                  */
  538                 if ((1 << dcfg_partn) &  ~enp->en_u.siena.enu_partn_mask) {
  539                         if (entry->port == 2)
  540                                 continue;
  541                 }
  542 
  543                 if ((rc = siena_nvram_get_dynamic_cfg(enp, dcfg_partn,
  544                     B_FALSE, &dcfg, &length)) != 0)
  545                         goto fail3;
  546 
  547                 nitems = EFX_DWORD_FIELD(dcfg->num_fw_version_items,
  548                             EFX_DWORD_0);
  549                 if (nitems < entry->partn)
  550                         goto done;
  551 
  552                 verp = &dcfg->fw_version[partn];
  553                 temp[0] = EFX_WORD_FIELD(verp->version_w, EFX_WORD_0);
  554                 temp[1] = EFX_WORD_FIELD(verp->version_x, EFX_WORD_0);
  555                 temp[2] = EFX_WORD_FIELD(verp->version_y, EFX_WORD_0);
  556                 temp[3] = EFX_WORD_FIELD(verp->version_z, EFX_WORD_0);
  557                 if (memcmp(version, temp, sizeof (temp)) < 0)
  558                         memcpy(version, temp, sizeof (temp));
  559 
  560 done:
  561                 EFSYS_KMEM_FREE(enp->en_esip, length, dcfg);
  562         }
  563 
  564         return (0);
  565 
  566 fail3:
  567         EFSYS_PROBE(fail3);
  568 fail2:
  569         EFSYS_PROBE(fail2);
  570 fail1:
  571         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  572 
  573         return (rc);
  574 }
  575 
  576         __checkReturn           efx_rc_t
  577 siena_nvram_partn_rw_start(
  578         __in                    efx_nic_t *enp,
  579         __in                    uint32_t partn,
  580         __out                   size_t *chunk_sizep)
  581 {
  582         efx_rc_t rc;
  583 
  584         if ((rc = siena_nvram_partn_lock(enp, partn)) != 0)
  585                 goto fail1;
  586 
  587         if (chunk_sizep != NULL)
  588                 *chunk_sizep = SIENA_NVRAM_CHUNK;
  589 
  590         return (0);
  591 
  592 fail1:
  593         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  594 
  595         return (rc);
  596 }
  597 
  598         __checkReturn           efx_rc_t
  599 siena_nvram_partn_rw_finish(
  600         __in                    efx_nic_t *enp,
  601         __in                    uint32_t partn,
  602         __out_opt               uint32_t *verify_resultp)
  603 {
  604         efx_rc_t rc;
  605 
  606         if ((rc = siena_nvram_partn_unlock(enp, partn, verify_resultp)) != 0)
  607                 goto fail1;
  608 
  609         return (0);
  610 
  611 fail1:
  612         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  613 
  614         return (rc);
  615 }
  616 
  617         __checkReturn           efx_rc_t
  618 siena_nvram_partn_set_version(
  619         __in                    efx_nic_t *enp,
  620         __in                    uint32_t partn,
  621         __in_ecount(4)          uint16_t version[4])
  622 {
  623         efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
  624         siena_mc_dynamic_config_hdr_t *dcfg = NULL;
  625         siena_mc_fw_version_t *fwverp;
  626         uint32_t dcfg_partn;
  627         size_t dcfg_size;
  628         unsigned int hdr_length;
  629         unsigned int vpd_length;
  630         unsigned int vpd_offset;
  631         unsigned int nitems;
  632         unsigned int required_hdr_length;
  633         unsigned int pos;
  634         uint8_t cksum;
  635         uint32_t subtype;
  636         size_t length;
  637         efx_rc_t rc;
  638 
  639         dcfg_partn = (emip->emi_port == 1)
  640                 ? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0
  641                 : MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1;
  642 
  643         if ((rc = siena_nvram_partn_size(enp, dcfg_partn, &dcfg_size)) != 0)
  644                 goto fail1;
  645 
  646         if ((rc = siena_nvram_partn_lock(enp, dcfg_partn)) != 0)
  647                 goto fail2;
  648 
  649         if ((rc = siena_nvram_get_dynamic_cfg(enp, dcfg_partn,
  650             B_TRUE, &dcfg, &length)) != 0)
  651                 goto fail3;
  652 
  653         hdr_length = EFX_WORD_FIELD(dcfg->length, EFX_WORD_0);
  654         nitems = EFX_DWORD_FIELD(dcfg->num_fw_version_items, EFX_DWORD_0);
  655         vpd_length = EFX_DWORD_FIELD(dcfg->dynamic_vpd_length, EFX_DWORD_0);
  656         vpd_offset = EFX_DWORD_FIELD(dcfg->dynamic_vpd_offset, EFX_DWORD_0);
  657 
  658         /*
  659          * NOTE: This function will blatt any fields trailing the version
  660          * vector, or the VPD chunk.
  661          */
  662         required_hdr_length = SIENA_DYNAMIC_CFG_SIZE(partn + 1);
  663         if (required_hdr_length + vpd_length > length) {
  664                 rc = ENOSPC;
  665                 goto fail4;
  666         }
  667 
  668         if (vpd_offset < required_hdr_length) {
  669                 (void) memmove((caddr_t)dcfg + required_hdr_length,
  670                         (caddr_t)dcfg + vpd_offset, vpd_length);
  671                 vpd_offset = required_hdr_length;
  672                 EFX_POPULATE_DWORD_1(dcfg->dynamic_vpd_offset,
  673                                     EFX_DWORD_0, vpd_offset);
  674         }
  675 
  676         if (hdr_length < required_hdr_length) {
  677                 (void) memset((caddr_t)dcfg + hdr_length, 0,
  678                         required_hdr_length - hdr_length);
  679                 hdr_length = required_hdr_length;
  680                 EFX_POPULATE_WORD_1(dcfg->length,
  681                                     EFX_WORD_0, hdr_length);
  682         }
  683 
  684         /* Get the subtype to insert into the fw_subtype array */
  685         if ((rc = siena_nvram_get_subtype(enp, partn, &subtype)) != 0)
  686                 goto fail5;
  687 
  688         /* Fill out the new version */
  689         fwverp = &dcfg->fw_version[partn];
  690         EFX_POPULATE_DWORD_1(fwverp->fw_subtype, EFX_DWORD_0, subtype);
  691         EFX_POPULATE_WORD_1(fwverp->version_w, EFX_WORD_0, version[0]);
  692         EFX_POPULATE_WORD_1(fwverp->version_x, EFX_WORD_0, version[1]);
  693         EFX_POPULATE_WORD_1(fwverp->version_y, EFX_WORD_0, version[2]);
  694         EFX_POPULATE_WORD_1(fwverp->version_z, EFX_WORD_0, version[3]);
  695 
  696         /* Update the version count */
  697         if (nitems < partn + 1) {
  698                 nitems = partn + 1;
  699                 EFX_POPULATE_DWORD_1(dcfg->num_fw_version_items,
  700                                     EFX_DWORD_0, nitems);
  701         }
  702 
  703         /* Update the checksum */
  704         cksum = 0;
  705         for (pos = 0; pos < hdr_length; pos++)
  706                 cksum += ((uint8_t *)dcfg)[pos];
  707         dcfg->csum.eb_u8[0] -= cksum;
  708 
  709         /* Erase and write the new partition */
  710         if ((rc = siena_nvram_partn_erase(enp, dcfg_partn, 0, dcfg_size)) != 0)
  711                 goto fail6;
  712 
  713         /* Write out the new structure to nvram */
  714         if ((rc = siena_nvram_partn_write(enp, dcfg_partn, 0,
  715             (caddr_t)dcfg, vpd_offset + vpd_length)) != 0)
  716                 goto fail7;
  717 
  718         EFSYS_KMEM_FREE(enp->en_esip, length, dcfg);
  719 
  720         siena_nvram_partn_unlock(enp, dcfg_partn, NULL);
  721 
  722         return (0);
  723 
  724 fail7:
  725         EFSYS_PROBE(fail7);
  726 fail6:
  727         EFSYS_PROBE(fail6);
  728 fail5:
  729         EFSYS_PROBE(fail5);
  730 fail4:
  731         EFSYS_PROBE(fail4);
  732 
  733         EFSYS_KMEM_FREE(enp->en_esip, length, dcfg);
  734 fail3:
  735         EFSYS_PROBE(fail3);
  736 fail2:
  737         EFSYS_PROBE(fail2);
  738 fail1:
  739         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  740 
  741         return (rc);
  742 }
  743 
  744 #endif  /* EFSYS_OPT_NVRAM */
  745 
  746 #endif  /* EFSYS_OPT_SIENA */

Cache object: 300d7fe6bd6e104f8485561181f95642


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.