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/efx_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_NVRAM
   40 
   41 #if EFSYS_OPT_SIENA
   42 
   43 static const efx_nvram_ops_t    __efx_nvram_siena_ops = {
   44 #if EFSYS_OPT_DIAG
   45         siena_nvram_test,               /* envo_test */
   46 #endif  /* EFSYS_OPT_DIAG */
   47         siena_nvram_type_to_partn,      /* envo_type_to_partn */
   48         siena_nvram_partn_size,         /* envo_partn_size */
   49         siena_nvram_partn_rw_start,     /* envo_partn_rw_start */
   50         siena_nvram_partn_read,         /* envo_partn_read */
   51         siena_nvram_partn_read,         /* envo_partn_read_backup */
   52         siena_nvram_partn_erase,        /* envo_partn_erase */
   53         siena_nvram_partn_write,        /* envo_partn_write */
   54         siena_nvram_partn_rw_finish,    /* envo_partn_rw_finish */
   55         siena_nvram_partn_get_version,  /* envo_partn_get_version */
   56         siena_nvram_partn_set_version,  /* envo_partn_set_version */
   57         NULL,                           /* envo_partn_validate */
   58 };
   59 
   60 #endif  /* EFSYS_OPT_SIENA */
   61 
   62 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
   63 
   64 static const efx_nvram_ops_t    __efx_nvram_ef10_ops = {
   65 #if EFSYS_OPT_DIAG
   66         ef10_nvram_test,                /* envo_test */
   67 #endif  /* EFSYS_OPT_DIAG */
   68         ef10_nvram_type_to_partn,       /* envo_type_to_partn */
   69         ef10_nvram_partn_size,          /* envo_partn_size */
   70         ef10_nvram_partn_rw_start,      /* envo_partn_rw_start */
   71         ef10_nvram_partn_read,          /* envo_partn_read */
   72         ef10_nvram_partn_read_backup,   /* envo_partn_read_backup */
   73         ef10_nvram_partn_erase,         /* envo_partn_erase */
   74         ef10_nvram_partn_write,         /* envo_partn_write */
   75         ef10_nvram_partn_rw_finish,     /* envo_partn_rw_finish */
   76         ef10_nvram_partn_get_version,   /* envo_partn_get_version */
   77         ef10_nvram_partn_set_version,   /* envo_partn_set_version */
   78         ef10_nvram_buffer_validate,     /* envo_buffer_validate */
   79 };
   80 
   81 #endif  /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
   82 
   83         __checkReturn   efx_rc_t
   84 efx_nvram_init(
   85         __in            efx_nic_t *enp)
   86 {
   87         const efx_nvram_ops_t *envop;
   88         efx_rc_t rc;
   89 
   90         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
   91         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
   92         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM));
   93 
   94         switch (enp->en_family) {
   95 #if EFSYS_OPT_SIENA
   96         case EFX_FAMILY_SIENA:
   97                 envop = &__efx_nvram_siena_ops;
   98                 break;
   99 #endif  /* EFSYS_OPT_SIENA */
  100 
  101 #if EFSYS_OPT_HUNTINGTON
  102         case EFX_FAMILY_HUNTINGTON:
  103                 envop = &__efx_nvram_ef10_ops;
  104                 break;
  105 #endif  /* EFSYS_OPT_HUNTINGTON */
  106 
  107 #if EFSYS_OPT_MEDFORD
  108         case EFX_FAMILY_MEDFORD:
  109                 envop = &__efx_nvram_ef10_ops;
  110                 break;
  111 #endif  /* EFSYS_OPT_MEDFORD */
  112 
  113 #if EFSYS_OPT_MEDFORD2
  114         case EFX_FAMILY_MEDFORD2:
  115                 envop = &__efx_nvram_ef10_ops;
  116                 break;
  117 #endif  /* EFSYS_OPT_MEDFORD2 */
  118 
  119         default:
  120                 EFSYS_ASSERT(0);
  121                 rc = ENOTSUP;
  122                 goto fail1;
  123         }
  124 
  125         enp->en_envop = envop;
  126         enp->en_mod_flags |= EFX_MOD_NVRAM;
  127 
  128         enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
  129 
  130         return (0);
  131 
  132 fail1:
  133         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  134 
  135         return (rc);
  136 }
  137 
  138 #if EFSYS_OPT_DIAG
  139 
  140         __checkReturn           efx_rc_t
  141 efx_nvram_test(
  142         __in                    efx_nic_t *enp)
  143 {
  144         const efx_nvram_ops_t *envop = enp->en_envop;
  145         efx_rc_t rc;
  146 
  147         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  148         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
  149 
  150         if ((rc = envop->envo_test(enp)) != 0)
  151                 goto fail1;
  152 
  153         return (0);
  154 
  155 fail1:
  156         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  157 
  158         return (rc);
  159 }
  160 
  161 #endif  /* EFSYS_OPT_DIAG */
  162 
  163         __checkReturn           efx_rc_t
  164 efx_nvram_size(
  165         __in                    efx_nic_t *enp,
  166         __in                    efx_nvram_type_t type,
  167         __out                   size_t *sizep)
  168 {
  169         const efx_nvram_ops_t *envop = enp->en_envop;
  170         uint32_t partn;
  171         efx_rc_t rc;
  172 
  173         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  174         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
  175 
  176         if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
  177                 goto fail1;
  178 
  179         if ((rc = envop->envo_partn_size(enp, partn, sizep)) != 0)
  180                 goto fail2;
  181 
  182         return (0);
  183 
  184 fail2:
  185         EFSYS_PROBE(fail2);
  186 fail1:
  187         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  188         *sizep = 0;
  189 
  190         return (rc);
  191 }
  192 
  193         __checkReturn           efx_rc_t
  194 efx_nvram_get_version(
  195         __in                    efx_nic_t *enp,
  196         __in                    efx_nvram_type_t type,
  197         __out                   uint32_t *subtypep,
  198         __out_ecount(4)         uint16_t version[4])
  199 {
  200         const efx_nvram_ops_t *envop = enp->en_envop;
  201         uint32_t partn;
  202         efx_rc_t rc;
  203 
  204         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  205         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
  206         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
  207 
  208         if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
  209                 goto fail1;
  210 
  211         if ((rc = envop->envo_partn_get_version(enp, partn,
  212                     subtypep, version)) != 0)
  213                 goto fail2;
  214 
  215         return (0);
  216 
  217 fail2:
  218         EFSYS_PROBE(fail2);
  219 fail1:
  220         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  221 
  222         return (rc);
  223 }
  224 
  225         __checkReturn           efx_rc_t
  226 efx_nvram_rw_start(
  227         __in                    efx_nic_t *enp,
  228         __in                    efx_nvram_type_t type,
  229         __out_opt               size_t *chunk_sizep)
  230 {
  231         const efx_nvram_ops_t *envop = enp->en_envop;
  232         uint32_t partn;
  233         efx_rc_t rc;
  234 
  235         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  236         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
  237 
  238         if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
  239                 goto fail1;
  240 
  241         EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
  242 
  243         if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0)
  244                 goto fail2;
  245 
  246         enp->en_nvram_partn_locked = partn;
  247 
  248         return (0);
  249 
  250 fail2:
  251         EFSYS_PROBE(fail2);
  252 fail1:
  253         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  254 
  255         return (rc);
  256 }
  257 
  258         __checkReturn           efx_rc_t
  259 efx_nvram_read_chunk(
  260         __in                    efx_nic_t *enp,
  261         __in                    efx_nvram_type_t type,
  262         __in                    unsigned int offset,
  263         __out_bcount(size)      caddr_t data,
  264         __in                    size_t size)
  265 {
  266         const efx_nvram_ops_t *envop = enp->en_envop;
  267         uint32_t partn;
  268         efx_rc_t rc;
  269 
  270         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  271         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
  272 
  273         if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
  274                 goto fail1;
  275 
  276         EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
  277 
  278         if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0)
  279                 goto fail2;
  280 
  281         return (0);
  282 
  283 fail2:
  284         EFSYS_PROBE(fail2);
  285 fail1:
  286         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  287 
  288         return (rc);
  289 }
  290 
  291 /*
  292  * Read from the backup (writeable) store of an A/B partition.
  293  * For non A/B partitions, there is only a single store, and so this
  294  * function has the same behaviour as efx_nvram_read_chunk().
  295  */
  296         __checkReturn           efx_rc_t
  297 efx_nvram_read_backup(
  298         __in                    efx_nic_t *enp,
  299         __in                    efx_nvram_type_t type,
  300         __in                    unsigned int offset,
  301         __out_bcount(size)      caddr_t data,
  302         __in                    size_t size)
  303 {
  304         const efx_nvram_ops_t *envop = enp->en_envop;
  305         uint32_t partn;
  306         efx_rc_t rc;
  307 
  308         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  309         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
  310 
  311         if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
  312                 goto fail1;
  313 
  314         EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
  315 
  316         if ((rc = envop->envo_partn_read_backup(enp, partn, offset,
  317                     data, size)) != 0)
  318                 goto fail2;
  319 
  320         return (0);
  321 
  322 fail2:
  323         EFSYS_PROBE(fail2);
  324 fail1:
  325         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  326 
  327         return (rc);
  328 }
  329 
  330         __checkReturn           efx_rc_t
  331 efx_nvram_erase(
  332         __in                    efx_nic_t *enp,
  333         __in                    efx_nvram_type_t type)
  334 {
  335         const efx_nvram_ops_t *envop = enp->en_envop;
  336         unsigned int offset = 0;
  337         size_t size = 0;
  338         uint32_t partn;
  339         efx_rc_t rc;
  340 
  341         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  342         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
  343 
  344         if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
  345                 goto fail1;
  346 
  347         EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
  348 
  349         if ((rc = envop->envo_partn_size(enp, partn, &size)) != 0)
  350                 goto fail2;
  351 
  352         if ((rc = envop->envo_partn_erase(enp, partn, offset, size)) != 0)
  353                 goto fail3;
  354 
  355         return (0);
  356 
  357 fail3:
  358         EFSYS_PROBE(fail3);
  359 fail2:
  360         EFSYS_PROBE(fail2);
  361 fail1:
  362         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  363 
  364         return (rc);
  365 }
  366 
  367         __checkReturn           efx_rc_t
  368 efx_nvram_write_chunk(
  369         __in                    efx_nic_t *enp,
  370         __in                    efx_nvram_type_t type,
  371         __in                    unsigned int offset,
  372         __in_bcount(size)       caddr_t data,
  373         __in                    size_t size)
  374 {
  375         const efx_nvram_ops_t *envop = enp->en_envop;
  376         uint32_t partn;
  377         efx_rc_t rc;
  378 
  379         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  380         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
  381 
  382         if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
  383                 goto fail1;
  384 
  385         EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
  386 
  387         if ((rc = envop->envo_partn_write(enp, partn, offset, data, size)) != 0)
  388                 goto fail2;
  389 
  390         return (0);
  391 
  392 fail2:
  393         EFSYS_PROBE(fail2);
  394 fail1:
  395         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  396 
  397         return (rc);
  398 }
  399 
  400         __checkReturn           efx_rc_t
  401 efx_nvram_rw_finish(
  402         __in                    efx_nic_t *enp,
  403         __in                    efx_nvram_type_t type,
  404         __out_opt               uint32_t *verify_resultp)
  405 {
  406         const efx_nvram_ops_t *envop = enp->en_envop;
  407         uint32_t partn;
  408         uint32_t verify_result = 0;
  409         efx_rc_t rc;
  410 
  411         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  412         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
  413 
  414         if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
  415                 goto fail1;
  416 
  417         EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, partn);
  418 
  419         if ((rc = envop->envo_partn_rw_finish(enp, partn, &verify_result)) != 0)
  420                 goto fail2;
  421 
  422         enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
  423 
  424         if (verify_resultp != NULL)
  425                 *verify_resultp = verify_result;
  426 
  427         return (0);
  428 
  429 fail2:
  430         EFSYS_PROBE(fail2);
  431         enp->en_nvram_partn_locked = EFX_NVRAM_PARTN_INVALID;
  432 
  433 fail1:
  434         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  435 
  436         /* Always report verification result */
  437         if (verify_resultp != NULL)
  438                 *verify_resultp = verify_result;
  439 
  440         return (rc);
  441 }
  442 
  443         __checkReturn           efx_rc_t
  444 efx_nvram_set_version(
  445         __in                    efx_nic_t *enp,
  446         __in                    efx_nvram_type_t type,
  447         __in_ecount(4)          uint16_t version[4])
  448 {
  449         const efx_nvram_ops_t *envop = enp->en_envop;
  450         uint32_t partn;
  451         efx_rc_t rc;
  452 
  453         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  454         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
  455         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
  456 
  457         if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
  458                 goto fail1;
  459 
  460         /*
  461          * The Siena implementation of envo_set_version() will attempt to
  462          * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG partition.
  463          * Therefore, you can't have already acquired the NVRAM_UPDATE lock.
  464          */
  465         EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
  466 
  467         if ((rc = envop->envo_partn_set_version(enp, partn, version)) != 0)
  468                 goto fail2;
  469 
  470         return (0);
  471 
  472 fail2:
  473         EFSYS_PROBE(fail2);
  474 fail1:
  475         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  476 
  477         return (rc);
  478 }
  479 
  480 /* Validate buffer contents (before writing to flash) */
  481         __checkReturn           efx_rc_t
  482 efx_nvram_validate(
  483         __in                    efx_nic_t *enp,
  484         __in                    efx_nvram_type_t type,
  485         __in_bcount(partn_size) caddr_t partn_data,
  486         __in                    size_t partn_size)
  487 {
  488         const efx_nvram_ops_t *envop = enp->en_envop;
  489         uint32_t partn;
  490         efx_rc_t rc;
  491 
  492         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  493         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
  494         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
  495 
  496         if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
  497                 goto fail1;
  498 
  499         if (envop->envo_buffer_validate != NULL) {
  500                 if ((rc = envop->envo_buffer_validate(partn,
  501                             partn_data, partn_size)) != 0)
  502                         goto fail2;
  503         }
  504 
  505         return (0);
  506 
  507 fail2:
  508         EFSYS_PROBE(fail2);
  509 fail1:
  510         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  511 
  512         return (rc);
  513 }
  514 
  515 void
  516 efx_nvram_fini(
  517         __in            efx_nic_t *enp)
  518 {
  519         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
  520         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
  521         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
  522 
  523         EFSYS_ASSERT3U(enp->en_nvram_partn_locked, ==, EFX_NVRAM_PARTN_INVALID);
  524 
  525         enp->en_envop = NULL;
  526         enp->en_mod_flags &= ~EFX_MOD_NVRAM;
  527 }
  528 
  529 #endif  /* EFSYS_OPT_NVRAM */
  530 
  531 #if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD
  532 
  533 /*
  534  * Internal MCDI request handling
  535  */
  536 
  537         __checkReturn           efx_rc_t
  538 efx_mcdi_nvram_partitions(
  539         __in                    efx_nic_t *enp,
  540         __out_bcount(size)      caddr_t data,
  541         __in                    size_t size,
  542         __out                   unsigned int *npartnp)
  543 {
  544         efx_mcdi_req_t req;
  545         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_PARTITIONS_IN_LEN,
  546                 MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX);
  547         unsigned int npartn;
  548         efx_rc_t rc;
  549 
  550         req.emr_cmd = MC_CMD_NVRAM_PARTITIONS;
  551         req.emr_in_buf = payload;
  552         req.emr_in_length = MC_CMD_NVRAM_PARTITIONS_IN_LEN;
  553         req.emr_out_buf = payload;
  554         req.emr_out_length = MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX;
  555 
  556         efx_mcdi_execute(enp, &req);
  557 
  558         if (req.emr_rc != 0) {
  559                 rc = req.emr_rc;
  560                 goto fail1;
  561         }
  562 
  563         if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN) {
  564                 rc = EMSGSIZE;
  565                 goto fail2;
  566         }
  567         npartn = MCDI_OUT_DWORD(req, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS);
  568 
  569         if (req.emr_out_length_used < MC_CMD_NVRAM_PARTITIONS_OUT_LEN(npartn)) {
  570                 rc = ENOENT;
  571                 goto fail3;
  572         }
  573 
  574         if (size < npartn * sizeof (uint32_t)) {
  575                 rc = ENOSPC;
  576                 goto fail3;
  577         }
  578 
  579         *npartnp = npartn;
  580 
  581         memcpy(data,
  582             MCDI_OUT2(req, uint32_t, NVRAM_PARTITIONS_OUT_TYPE_ID),
  583             (npartn * sizeof (uint32_t)));
  584 
  585         return (0);
  586 
  587 fail3:
  588         EFSYS_PROBE(fail3);
  589 fail2:
  590         EFSYS_PROBE(fail2);
  591 fail1:
  592         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  593 
  594         return (rc);
  595 }
  596 
  597         __checkReturn           efx_rc_t
  598 efx_mcdi_nvram_metadata(
  599         __in                    efx_nic_t *enp,
  600         __in                    uint32_t partn,
  601         __out                   uint32_t *subtypep,
  602         __out_ecount(4)         uint16_t version[4],
  603         __out_bcount_opt(size)  char *descp,
  604         __in                    size_t size)
  605 {
  606         efx_mcdi_req_t req;
  607         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_METADATA_IN_LEN,
  608                 MC_CMD_NVRAM_METADATA_OUT_LENMAX);
  609         efx_rc_t rc;
  610 
  611         req.emr_cmd = MC_CMD_NVRAM_METADATA;
  612         req.emr_in_buf = payload;
  613         req.emr_in_length = MC_CMD_NVRAM_METADATA_IN_LEN;
  614         req.emr_out_buf = payload;
  615         req.emr_out_length = MC_CMD_NVRAM_METADATA_OUT_LENMAX;
  616 
  617         MCDI_IN_SET_DWORD(req, NVRAM_METADATA_IN_TYPE, partn);
  618 
  619         efx_mcdi_execute_quiet(enp, &req);
  620 
  621         if (req.emr_rc != 0) {
  622                 rc = req.emr_rc;
  623                 goto fail1;
  624         }
  625 
  626         if (req.emr_out_length_used < MC_CMD_NVRAM_METADATA_OUT_LENMIN) {
  627                 rc = EMSGSIZE;
  628                 goto fail2;
  629         }
  630 
  631         if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
  632                 NVRAM_METADATA_OUT_SUBTYPE_VALID)) {
  633                 *subtypep = MCDI_OUT_DWORD(req, NVRAM_METADATA_OUT_SUBTYPE);
  634         } else {
  635                 *subtypep = 0;
  636         }
  637 
  638         if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
  639                 NVRAM_METADATA_OUT_VERSION_VALID)) {
  640                 version[0] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_W);
  641                 version[1] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_X);
  642                 version[2] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Y);
  643                 version[3] = MCDI_OUT_WORD(req, NVRAM_METADATA_OUT_VERSION_Z);
  644         } else {
  645                 version[0] = version[1] = version[2] = version[3] = 0;
  646         }
  647 
  648         if (MCDI_OUT_DWORD_FIELD(req, NVRAM_METADATA_OUT_FLAGS,
  649                 NVRAM_METADATA_OUT_DESCRIPTION_VALID)) {
  650                 /* Return optional descrition string */
  651                 if ((descp != NULL) && (size > 0)) {
  652                         size_t desclen;
  653 
  654                         descp[0] = '\0';
  655                         desclen = (req.emr_out_length_used
  656                             - MC_CMD_NVRAM_METADATA_OUT_LEN(0));
  657 
  658                         EFSYS_ASSERT3U(desclen, <=,
  659                             MC_CMD_NVRAM_METADATA_OUT_DESCRIPTION_MAXNUM);
  660 
  661                         if (size < desclen) {
  662                                 rc = ENOSPC;
  663                                 goto fail3;
  664                         }
  665 
  666                         memcpy(descp, MCDI_OUT2(req, char,
  667                                 NVRAM_METADATA_OUT_DESCRIPTION),
  668                             desclen);
  669 
  670                         /* Ensure string is NUL terminated */
  671                         descp[desclen] = '\0';
  672                 }
  673         }
  674 
  675         return (0);
  676 
  677 fail3:
  678         EFSYS_PROBE(fail3);
  679 fail2:
  680         EFSYS_PROBE(fail2);
  681 fail1:
  682         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  683 
  684         return (rc);
  685 }
  686 
  687         __checkReturn           efx_rc_t
  688 efx_mcdi_nvram_info(
  689         __in                    efx_nic_t *enp,
  690         __in                    uint32_t partn,
  691         __out_opt               size_t *sizep,
  692         __out_opt               uint32_t *addressp,
  693         __out_opt               uint32_t *erase_sizep,
  694         __out_opt               uint32_t *write_sizep)
  695 {
  696         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_INFO_IN_LEN,
  697                 MC_CMD_NVRAM_INFO_V2_OUT_LEN);
  698         efx_mcdi_req_t req;
  699         efx_rc_t rc;
  700 
  701         req.emr_cmd = MC_CMD_NVRAM_INFO;
  702         req.emr_in_buf = payload;
  703         req.emr_in_length = MC_CMD_NVRAM_INFO_IN_LEN;
  704         req.emr_out_buf = payload;
  705         req.emr_out_length = MC_CMD_NVRAM_INFO_V2_OUT_LEN;
  706 
  707         MCDI_IN_SET_DWORD(req, NVRAM_INFO_IN_TYPE, partn);
  708 
  709         efx_mcdi_execute_quiet(enp, &req);
  710 
  711         if (req.emr_rc != 0) {
  712                 rc = req.emr_rc;
  713                 goto fail1;
  714         }
  715 
  716         if (req.emr_out_length_used < MC_CMD_NVRAM_INFO_OUT_LEN) {
  717                 rc = EMSGSIZE;
  718                 goto fail2;
  719         }
  720 
  721         if (sizep)
  722                 *sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_SIZE);
  723 
  724         if (addressp)
  725                 *addressp = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_PHYSADDR);
  726 
  727         if (erase_sizep)
  728                 *erase_sizep = MCDI_OUT_DWORD(req, NVRAM_INFO_OUT_ERASESIZE);
  729 
  730         if (write_sizep) {
  731                 *write_sizep =
  732                         (req.emr_out_length_used <
  733                             MC_CMD_NVRAM_INFO_V2_OUT_LEN) ?
  734                         0 : MCDI_OUT_DWORD(req, NVRAM_INFO_V2_OUT_WRITESIZE);
  735         }
  736 
  737         return (0);
  738 
  739 fail2:
  740         EFSYS_PROBE(fail2);
  741 fail1:
  742         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  743 
  744         return (rc);
  745 }
  746 
  747 /*
  748  * MC_CMD_NVRAM_UPDATE_START_V2 must be used to support firmware-verified
  749  * NVRAM updates. Older firmware will ignore the flags field in the request.
  750  */
  751         __checkReturn           efx_rc_t
  752 efx_mcdi_nvram_update_start(
  753         __in                    efx_nic_t *enp,
  754         __in                    uint32_t partn)
  755 {
  756         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN,
  757                 MC_CMD_NVRAM_UPDATE_START_OUT_LEN);
  758         efx_mcdi_req_t req;
  759         efx_rc_t rc;
  760 
  761         req.emr_cmd = MC_CMD_NVRAM_UPDATE_START;
  762         req.emr_in_buf = payload;
  763         req.emr_in_length = MC_CMD_NVRAM_UPDATE_START_V2_IN_LEN;
  764         req.emr_out_buf = payload;
  765         req.emr_out_length = MC_CMD_NVRAM_UPDATE_START_OUT_LEN;
  766 
  767         MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_START_V2_IN_TYPE, partn);
  768 
  769         MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_START_V2_IN_FLAGS,
  770             NVRAM_UPDATE_START_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
  771 
  772         efx_mcdi_execute(enp, &req);
  773 
  774         if (req.emr_rc != 0) {
  775                 rc = req.emr_rc;
  776                 goto fail1;
  777         }
  778 
  779         return (0);
  780 
  781 fail1:
  782         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  783 
  784         return (rc);
  785 }
  786 
  787         __checkReturn           efx_rc_t
  788 efx_mcdi_nvram_read(
  789         __in                    efx_nic_t *enp,
  790         __in                    uint32_t partn,
  791         __in                    uint32_t offset,
  792         __out_bcount(size)      caddr_t data,
  793         __in                    size_t size,
  794         __in                    uint32_t mode)
  795 {
  796         efx_mcdi_req_t req;
  797         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_READ_IN_V2_LEN,
  798                 MC_CMD_NVRAM_READ_OUT_LENMAX);
  799         efx_rc_t rc;
  800 
  801         if (size > MC_CMD_NVRAM_READ_OUT_LENMAX) {
  802                 rc = EINVAL;
  803                 goto fail1;
  804         }
  805 
  806         req.emr_cmd = MC_CMD_NVRAM_READ;
  807         req.emr_in_buf = payload;
  808         req.emr_in_length = MC_CMD_NVRAM_READ_IN_V2_LEN;
  809         req.emr_out_buf = payload;
  810         req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX;
  811 
  812         MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_TYPE, partn);
  813         MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_OFFSET, offset);
  814         MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_LENGTH, size);
  815         MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_MODE, mode);
  816 
  817         efx_mcdi_execute(enp, &req);
  818 
  819         if (req.emr_rc != 0) {
  820                 rc = req.emr_rc;
  821                 goto fail1;
  822         }
  823 
  824         if (req.emr_out_length_used < MC_CMD_NVRAM_READ_OUT_LEN(size)) {
  825                 rc = EMSGSIZE;
  826                 goto fail2;
  827         }
  828 
  829         memcpy(data,
  830             MCDI_OUT2(req, uint8_t, NVRAM_READ_OUT_READ_BUFFER),
  831             size);
  832 
  833         return (0);
  834 
  835 fail2:
  836         EFSYS_PROBE(fail2);
  837 fail1:
  838         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  839 
  840         return (rc);
  841 }
  842 
  843         __checkReturn           efx_rc_t
  844 efx_mcdi_nvram_erase(
  845         __in                    efx_nic_t *enp,
  846         __in                    uint32_t partn,
  847         __in                    uint32_t offset,
  848         __in                    size_t size)
  849 {
  850         efx_mcdi_req_t req;
  851         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_ERASE_IN_LEN,
  852                 MC_CMD_NVRAM_ERASE_OUT_LEN);
  853         efx_rc_t rc;
  854 
  855         req.emr_cmd = MC_CMD_NVRAM_ERASE;
  856         req.emr_in_buf = payload;
  857         req.emr_in_length = MC_CMD_NVRAM_ERASE_IN_LEN;
  858         req.emr_out_buf = payload;
  859         req.emr_out_length = MC_CMD_NVRAM_ERASE_OUT_LEN;
  860 
  861         MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_TYPE, partn);
  862         MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_OFFSET, offset);
  863         MCDI_IN_SET_DWORD(req, NVRAM_ERASE_IN_LENGTH, size);
  864 
  865         efx_mcdi_execute(enp, &req);
  866 
  867         if (req.emr_rc != 0) {
  868                 rc = req.emr_rc;
  869                 goto fail1;
  870         }
  871 
  872         return (0);
  873 
  874 fail1:
  875         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  876 
  877         return (rc);
  878 }
  879 
  880 /*
  881  * The NVRAM_WRITE MCDI command is a V1 command and so is supported by both
  882  * Sienna and EF10 based boards.  However EF10 based boards support the use
  883  * of this command with payloads up to the maximum MCDI V2 payload length.
  884  */
  885         __checkReturn           efx_rc_t
  886 efx_mcdi_nvram_write(
  887         __in                    efx_nic_t *enp,
  888         __in                    uint32_t partn,
  889         __in                    uint32_t offset,
  890         __in_bcount(size)       caddr_t data,
  891         __in                    size_t size)
  892 {
  893         efx_mcdi_req_t req;
  894         uint8_t *payload;
  895         efx_rc_t rc;
  896         size_t max_data_size;
  897         size_t payload_len = enp->en_nic_cfg.enc_mcdi_max_payload_length;
  898 
  899         max_data_size = payload_len - MC_CMD_NVRAM_WRITE_IN_LEN(0);
  900         EFSYS_ASSERT3U(payload_len, >, 0);
  901         EFSYS_ASSERT3U(max_data_size, <, payload_len);
  902 
  903         if (size > max_data_size) {
  904                 rc = EINVAL;
  905                 goto fail1;
  906         }
  907 
  908         EFSYS_KMEM_ALLOC(enp->en_esip, payload_len, payload);
  909         if (payload == NULL) {
  910                 rc = ENOMEM;
  911                 goto fail2;
  912         }
  913 
  914         (void) memset(payload, 0, payload_len);
  915         req.emr_cmd = MC_CMD_NVRAM_WRITE;
  916         req.emr_in_buf = payload;
  917         req.emr_in_length = MC_CMD_NVRAM_WRITE_IN_LEN(size);
  918         req.emr_out_buf = payload;
  919         req.emr_out_length = MC_CMD_NVRAM_WRITE_OUT_LEN;
  920 
  921         MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_TYPE, partn);
  922         MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_OFFSET, offset);
  923         MCDI_IN_SET_DWORD(req, NVRAM_WRITE_IN_LENGTH, size);
  924 
  925         memcpy(MCDI_IN2(req, uint8_t, NVRAM_WRITE_IN_WRITE_BUFFER),
  926             data, size);
  927 
  928         efx_mcdi_execute(enp, &req);
  929 
  930         if (req.emr_rc != 0) {
  931                 rc = req.emr_rc;
  932                 goto fail3;
  933         }
  934 
  935         EFSYS_KMEM_FREE(enp->en_esip, payload_len, payload);
  936 
  937         return (0);
  938 
  939 fail3:
  940         EFSYS_PROBE(fail3);
  941         EFSYS_KMEM_FREE(enp->en_esip, payload_len, payload);
  942 fail2:
  943         EFSYS_PROBE(fail2);
  944 fail1:
  945         EFSYS_PROBE1(fail1, efx_rc_t, rc);
  946 
  947         return (rc);
  948 }
  949 
  950 /*
  951  * MC_CMD_NVRAM_UPDATE_FINISH_V2 must be used to support firmware-verified
  952  * NVRAM updates. Older firmware will ignore the flags field in the request.
  953  */
  954         __checkReturn           efx_rc_t
  955 efx_mcdi_nvram_update_finish(
  956         __in                    efx_nic_t *enp,
  957         __in                    uint32_t partn,
  958         __in                    boolean_t reboot,
  959         __out_opt               uint32_t *verify_resultp)
  960 {
  961         const efx_nic_cfg_t *encp = &enp->en_nic_cfg;
  962         efx_mcdi_req_t req;
  963         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN,
  964                 MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN);
  965         uint32_t verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
  966         efx_rc_t rc;
  967 
  968         req.emr_cmd = MC_CMD_NVRAM_UPDATE_FINISH;
  969         req.emr_in_buf = payload;
  970         req.emr_in_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_IN_LEN;
  971         req.emr_out_buf = payload;
  972         req.emr_out_length = MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN;
  973 
  974         MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_TYPE, partn);
  975         MCDI_IN_SET_DWORD(req, NVRAM_UPDATE_FINISH_V2_IN_REBOOT, reboot);
  976 
  977         MCDI_IN_POPULATE_DWORD_1(req, NVRAM_UPDATE_FINISH_V2_IN_FLAGS,
  978             NVRAM_UPDATE_FINISH_V2_IN_FLAG_REPORT_VERIFY_RESULT, 1);
  979 
  980         efx_mcdi_execute(enp, &req);
  981 
  982         if (req.emr_rc != 0) {
  983                 rc = req.emr_rc;
  984                 goto fail1;
  985         }
  986 
  987         if (req.emr_out_length_used < MC_CMD_NVRAM_UPDATE_FINISH_V2_OUT_LEN) {
  988                 verify_result = MC_CMD_NVRAM_VERIFY_RC_UNKNOWN;
  989                 if (encp->enc_nvram_update_verify_result_supported) {
  990                         /* Result of update verification is missing */
  991                         rc = EMSGSIZE;
  992                         goto fail2;
  993                 }
  994         } else {
  995                 verify_result =
  996                     MCDI_OUT_DWORD(req, NVRAM_UPDATE_FINISH_V2_OUT_RESULT_CODE);
  997         }
  998 
  999         if ((encp->enc_nvram_update_verify_result_supported) &&
 1000             (verify_result != MC_CMD_NVRAM_VERIFY_RC_SUCCESS)) {
 1001                 /* Update verification failed */
 1002                 rc = EINVAL;
 1003                 goto fail3;
 1004         }
 1005 
 1006         if (verify_resultp != NULL)
 1007                 *verify_resultp = verify_result;
 1008 
 1009         return (0);
 1010 
 1011 fail3:
 1012         EFSYS_PROBE(fail3);
 1013 fail2:
 1014         EFSYS_PROBE(fail2);
 1015 fail1:
 1016         EFSYS_PROBE1(fail1, efx_rc_t, rc);
 1017 
 1018         /* Always report verification result */
 1019         if (verify_resultp != NULL)
 1020                 *verify_resultp = verify_result;
 1021 
 1022         return (rc);
 1023 }
 1024 
 1025 #if EFSYS_OPT_DIAG
 1026 
 1027         __checkReturn           efx_rc_t
 1028 efx_mcdi_nvram_test(
 1029         __in                    efx_nic_t *enp,
 1030         __in                    uint32_t partn)
 1031 {
 1032         efx_mcdi_req_t req;
 1033         EFX_MCDI_DECLARE_BUF(payload, MC_CMD_NVRAM_TEST_IN_LEN,
 1034                 MC_CMD_NVRAM_TEST_OUT_LEN);
 1035         int result;
 1036         efx_rc_t rc;
 1037 
 1038         req.emr_cmd = MC_CMD_NVRAM_TEST;
 1039         req.emr_in_buf = payload;
 1040         req.emr_in_length = MC_CMD_NVRAM_TEST_IN_LEN;
 1041         req.emr_out_buf = payload;
 1042         req.emr_out_length = MC_CMD_NVRAM_TEST_OUT_LEN;
 1043 
 1044         MCDI_IN_SET_DWORD(req, NVRAM_TEST_IN_TYPE, partn);
 1045 
 1046         efx_mcdi_execute(enp, &req);
 1047 
 1048         if (req.emr_rc != 0) {
 1049                 rc = req.emr_rc;
 1050                 goto fail1;
 1051         }
 1052 
 1053         if (req.emr_out_length_used < MC_CMD_NVRAM_TEST_OUT_LEN) {
 1054                 rc = EMSGSIZE;
 1055                 goto fail2;
 1056         }
 1057 
 1058         result = MCDI_OUT_DWORD(req, NVRAM_TEST_OUT_RESULT);
 1059         if (result == MC_CMD_NVRAM_TEST_FAIL) {
 1060                 EFSYS_PROBE1(nvram_test_failure, int, partn);
 1061 
 1062                 rc = (EINVAL);
 1063                 goto fail3;
 1064         }
 1065 
 1066         return (0);
 1067 
 1068 fail3:
 1069         EFSYS_PROBE(fail3);
 1070 fail2:
 1071         EFSYS_PROBE(fail2);
 1072 fail1:
 1073         EFSYS_PROBE1(fail1, efx_rc_t, rc);
 1074 
 1075         return (rc);
 1076 }
 1077 
 1078 #endif  /* EFSYS_OPT_DIAG */
 1079 
 1080 #endif /* EFSYS_OPT_NVRAM || EFSYS_OPT_VPD */

Cache object: f756dcbeb8baa837b92238db1866be1b


[ 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.